1use rustigram_types::story::{InputStoryContent, Story, StoryArea};
2
3use crate::client::BotClient;
4use crate::error::Result;
5use rustigram_types::message::{MessageEntity, ParseMode};
6use serde::Serialize;
7use std::future::{Future, IntoFuture};
8use std::pin::Pin;
9
10macro_rules! impl_into_future {
14 ($builder:ident, $return_ty:ty, $method:literal) => {
15 impl IntoFuture for $builder {
16 type Output = Result<$return_ty>;
17 type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
18
19 fn into_future(self) -> Self::IntoFuture {
20 Box::pin(async move { self.client.post_json($method, &self.params).await })
21 }
22 }
23 };
24}
25
26#[derive(Serialize)]
29struct PostStoryParams {
30 business_connection_id: String,
31 content: InputStoryContent,
36 active_period: u32,
40 #[serde(skip_serializing_if = "Option::is_none")]
41 caption: Option<String>,
42 #[serde(skip_serializing_if = "Option::is_none")]
43 parse_mode: Option<ParseMode>,
44 #[serde(skip_serializing_if = "Option::is_none")]
45 caption_entities: Option<Vec<MessageEntity>>,
46 #[serde(skip_serializing_if = "Option::is_none")]
49 areas: Option<Vec<StoryArea>>,
50 #[serde(skip_serializing_if = "Option::is_none")]
51 post_to_chat_page: Option<bool>,
52 #[serde(skip_serializing_if = "Option::is_none")]
53 protect_content: Option<bool>,
54}
55
56pub struct PostStory {
63 client: BotClient,
64 params: PostStoryParams,
65}
66
67impl PostStory {
68 pub(crate) fn new(
69 client: BotClient,
70 business_connection_id: impl Into<String>,
71 content: InputStoryContent,
72 active_period: u32,
73 ) -> Self {
74 Self {
75 client,
76 params: PostStoryParams {
77 business_connection_id: business_connection_id.into(),
78 content,
79 active_period,
80 caption: None,
81 parse_mode: None,
82 caption_entities: None,
83 areas: None,
84 post_to_chat_page: None,
85 protect_content: None,
86 },
87 }
88 }
89 pub fn caption(mut self, c: impl Into<String>) -> Self {
91 self.params.caption = Some(c.into());
92 self
93 }
94 pub fn parse_mode(mut self, m: ParseMode) -> Self {
96 self.params.parse_mode = Some(m);
97 self
98 }
99 pub fn caption_entities(mut self, e: Vec<MessageEntity>) -> Self {
101 self.params.caption_entities = Some(e);
102 self
103 }
104 pub fn areas(mut self, a: Vec<StoryArea>) -> Self {
107 self.params.areas = Some(a);
108 self
109 }
110 pub fn post_to_chat_page(mut self, v: bool) -> Self {
112 self.params.post_to_chat_page = Some(v);
113 self
114 }
115 pub fn protect_content(mut self, v: bool) -> Self {
117 self.params.protect_content = Some(v);
118 self
119 }
120}
121
122impl_into_future!(PostStory, Story, "postStory");
123
124#[derive(Serialize)]
127struct RepostStoryParams {
128 business_connection_id: String,
129 from_chat_id: i64,
130 from_story_id: i64,
131 active_period: u32,
135 #[serde(skip_serializing_if = "Option::is_none")]
136 post_to_chat_page: Option<bool>,
137 #[serde(skip_serializing_if = "Option::is_none")]
138 protect_content: Option<bool>,
139}
140
141pub struct RepostStory {
149 client: BotClient,
150 params: RepostStoryParams,
151}
152
153impl RepostStory {
154 pub(crate) fn new(
155 client: BotClient,
156 business_connection_id: impl Into<String>,
157 from_chat_id: i64,
158 from_story_id: i64,
159 active_period: u32,
160 ) -> Self {
161 Self {
162 client,
163 params: RepostStoryParams {
164 business_connection_id: business_connection_id.into(),
165 from_chat_id,
166 from_story_id,
167 active_period,
168 post_to_chat_page: None,
169 protect_content: None,
170 },
171 }
172 }
173 pub fn post_to_chat_page(mut self, v: bool) -> Self {
175 self.params.post_to_chat_page = Some(v);
176 self
177 }
178 pub fn protect_content(mut self, v: bool) -> Self {
180 self.params.protect_content = Some(v);
181 self
182 }
183}
184
185impl_into_future!(RepostStory, Story, "repostStory");
186
187#[derive(Serialize)]
190struct EditStoryParams {
191 business_connection_id: String,
192 story_id: i64,
193 content: InputStoryContent,
196 #[serde(skip_serializing_if = "Option::is_none")]
197 caption: Option<String>,
198 #[serde(skip_serializing_if = "Option::is_none")]
199 parse_mode: Option<ParseMode>,
200 #[serde(skip_serializing_if = "Option::is_none")]
201 caption_entities: Option<Vec<MessageEntity>>,
202 #[serde(skip_serializing_if = "Option::is_none")]
205 areas: Option<Vec<StoryArea>>,
206}
207
208pub struct EditStory {
214 client: BotClient,
215 params: EditStoryParams,
216}
217
218impl EditStory {
219 pub(crate) fn new(
220 client: BotClient,
221 business_connection_id: impl Into<String>,
222 story_id: i64,
223 content: InputStoryContent,
224 ) -> Self {
225 Self {
226 client,
227 params: EditStoryParams {
228 business_connection_id: business_connection_id.into(),
229 story_id,
230 content,
231 caption: None,
232 parse_mode: None,
233 caption_entities: None,
234 areas: None,
235 },
236 }
237 }
238 pub fn caption(mut self, c: impl Into<String>) -> Self {
240 self.params.caption = Some(c.into());
241 self
242 }
243 pub fn parse_mode(mut self, m: ParseMode) -> Self {
245 self.params.parse_mode = Some(m);
246 self
247 }
248 pub fn caption_entities(mut self, e: Vec<MessageEntity>) -> Self {
250 self.params.caption_entities = Some(e);
251 self
252 }
253 pub fn areas(mut self, a: Vec<StoryArea>) -> Self {
256 self.params.areas = Some(a);
257 self
258 }
259}
260
261impl_into_future!(EditStory, Story, "editStory");
262
263#[derive(Serialize)]
266struct DeleteStoryParams {
267 business_connection_id: String,
268 story_id: i64,
269}
270
271pub struct DeleteStory {
276 client: BotClient,
277 params: DeleteStoryParams,
278}
279
280impl DeleteStory {
281 pub(crate) fn new(
282 client: BotClient,
283 business_connection_id: impl Into<String>,
284 story_id: i64,
285 ) -> Self {
286 Self {
287 client,
288 params: DeleteStoryParams {
289 business_connection_id: business_connection_id.into(),
290 story_id,
291 },
292 }
293 }
294}
295
296impl_into_future!(DeleteStory, bool, "deleteStory");