1use crate::action::{CastAction, ReactionAction, ReactionInfo};
4use crate::proto::reactions_by_target_request::Target;
5use crate::proto::{CastsByParentRequest, ReactionType, ReactionsByTargetRequest};
6use crate::proto::embed::Embed as ProtoEmbed;
7use crate::utils::{cast_action_from_message, reaction_from_message};
8use crate::HubService;
9use async_trait::async_trait;
10use eyre::Result;
11use serde::{Deserialize, Serialize};
12
13#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Default)]
15pub struct Cast {
16 pub cast_id: CastId,
17 pub parent: Option<Parent>,
18 pub mentions: Vec<Mention>,
19 pub embeds: Vec<Embed>,
20 pub text: String,
21 pub cast_time: u32
23}
24
25impl Cast {
26
27 fn new(text: Option<String>) -> Self {
28 Cast {
29 text: text.unwrap_or_default(),
30 ..Default::default()
31 }
32 }
33
34
35
36
37}
38
39#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
40pub struct Mention {
41 pub fid: u64,
42 pub start_pos: u32
43}
44
45#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
46pub enum Embed {
47 Url(String),
48 CastId(CastId)
49}
50
51impl Into<crate::proto::Embed> for Embed {
52 fn into(self) -> crate::proto::Embed {
53 let proto_embed = match self {
54 Embed::Url(string) => ProtoEmbed::Url(string),
55 Embed::CastId(cast) => ProtoEmbed::CastId(cast.into())
56 };
57 crate::proto::Embed {
58 embed: Some(proto_embed)
59 }
60 }
61}
62
63#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
64pub enum Parent {
65 Url(String),
66 CastId(CastId)
67}
68
69impl Into<Target> for Parent {
70 fn into(self) -> Target {
71 match self {
72 Parent::Url(url) => {
73 Target::TargetUrl(url)
74 }
75 Parent::CastId(cast_id) => {
76 Target::TargetCastId(cast_id.into())
77 }
78 }
79 }
80}
81
82impl Into<crate::proto::casts_by_parent_request::Parent> for Parent {
83 fn into(self) -> crate::proto::casts_by_parent_request::Parent {
84 match self {
85 Parent::Url(url) => {
86 crate::proto::casts_by_parent_request::Parent::ParentUrl(url)
87 }
88 Parent::CastId(id) => {
89 crate::proto::casts_by_parent_request::Parent::ParentCastId(
90 crate::proto::CastId {
91 fid: id.fid,
92 hash: id.hash
93 }
94 )
95 }
96 }
97 }
98}
99
100#[derive(Debug, Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Default)]
101pub struct CastId {
102 pub fid: u64,
103 pub hash: Vec<u8>
104}
105
106impl Into<crate::proto::CastId> for CastId {
107 fn into(self) -> crate::proto::CastId {
108 crate::proto::CastId {
109 fid: self.fid,
110 hash: self.hash,
111 }
112 }
113}
114
115#[async_trait]
117pub trait PostService {
118 async fn get_post(&mut self, cast_id: CastId) -> Option<Cast>;
119 async fn get_posts_by_parent(&mut self, parent: Parent, page_token: Option<Vec<u8>>, page_size: Option<u32>, reverse: Option<bool>) -> Result<(Vec<Cast>, Option<Vec<u8>>)>;
123 async fn get_reacts_by_parent(&mut self, reaction_type: ReactionType, parent: Parent, page_token: Option<Vec<u8>>, page_size: Option<u32>, reverse: Option<bool>) -> Result<(Vec<ReactionInfo>, Option<Vec<u8>>)>;
124}
125
126#[async_trait]
127impl PostService for HubService {
128 async fn get_post(&mut self, cast_id: CastId) -> Option<Cast> {
129 let proto = crate::proto::CastId {
130 fid: cast_id.fid,
131 hash: cast_id.hash
132 };
133 let res = self.get_cast(proto).await.ok()?.into_inner();
134 match cast_action_from_message(res)? {
135 CastAction::CastAdd(cast) => Some(cast),
136 CastAction::CastRemove(_) => None
137 }
138 }
139
140 async fn get_posts_by_parent(&mut self, parent: Parent, page_token: Option<Vec<u8>>, page_size: Option<u32>, reverse: Option<bool>) -> Result<(Vec<Cast>, Option<Vec<u8>>)> {
141 let request = CastsByParentRequest {
142 page_size,
143 page_token,
144 reverse,
145 parent: Some(parent.into()),
146 };
147 let res = self.get_casts_by_parent(request).await?.into_inner();
148 let mut messages = Vec::new();
149 for message in res.messages {
150 if let Some(CastAction::CastAdd(add)) = cast_action_from_message(message) {
151 messages.push(add);
152 }
153 }
154 Ok((messages, res.next_page_token))
155 }
156
157 async fn get_reacts_by_parent(&mut self, reaction_type: ReactionType, parent: Parent, page_token: Option<Vec<u8>>, page_size: Option<u32>, reverse: Option<bool>) -> Result<(Vec<ReactionInfo>, Option<Vec<u8>>)> {
158 let request = ReactionsByTargetRequest {
159 reaction_type: Some(reaction_type.into()),
160 page_size,
161 page_token,
162 reverse,
163 target: Some(parent.into()),
164 };
165
166 let res = self.get_reactions_by_target(request).await?.into_inner();
167 let mut reactions = Vec::new();
168 for message in res.messages {
169 if let Some(react) = reaction_from_message(message) {
170 if let ReactionAction::Add(info) = react {
171 reactions.push(info);
172 }
173 }
174 }
175 Ok((reactions, res.next_page_token))
176 }
177}