tgbot/types/definitions/reaction.rs
1use serde::{Deserialize, Serialize};
2
3use crate::{
4 api::{Method, Payload},
5 types::{Chat, ChatId, Integer, User},
6};
7
8/// Represents a reaction added to a message along with the number of times it was added.
9#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
10pub struct ReactionCount {
11 /// Type of the reaction.
12 #[serde(rename = "type")]
13 pub reaction_type: ReactionType,
14 /// Number of times the reaction was added.
15 pub total_count: Integer,
16}
17
18impl ReactionCount {
19 /// Creates a new `ReactionCount`.
20 ///
21 /// # Arguments
22 ///
23 /// * `reaction_type` - Type of the reaction.
24 /// * `total_count` - Number of times the reaction was added.
25 pub fn new(reaction_type: ReactionType, total_count: Integer) -> Self {
26 Self {
27 reaction_type,
28 total_count,
29 }
30 }
31}
32
33/// Represents reaction changes on a message with anonymous reactions.
34#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
35pub struct MessageReactionCountUpdated {
36 /// The chat containing the message.
37 pub chat: Chat,
38 /// Date of the change in Unix time.
39 pub date: Integer,
40 /// Unique message identifier inside the chat.
41 pub message_id: Integer,
42 /// List of reactions that are present on the message.
43 pub reactions: Vec<ReactionCount>,
44}
45
46impl MessageReactionCountUpdated {
47 /// Creates a new `MessageReactionCountUpdated`.
48 ///
49 /// # Arguments
50 ///
51 /// * `chat` - The chat containing the message.
52 /// * `date` - Date of the change in Unix time.
53 /// * `message_id` - Unique message identifier inside the chat.
54 /// * `reactions` - List of reactions that are present on the message.
55 pub fn new<A, B>(chat: A, date: Integer, message_id: Integer, reactions: B) -> Self
56 where
57 A: Into<Chat>,
58 B: IntoIterator<Item = ReactionCount>,
59 {
60 Self {
61 chat: chat.into(),
62 date,
63 message_id,
64 reactions: reactions.into_iter().collect(),
65 }
66 }
67}
68
69/// Represents a reaction type.
70#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
71#[serde(from = "RawReactionType", into = "RawReactionType")]
72pub enum ReactionType {
73 /// A reaction based on a custom emoji.
74 CustomEmoji(String),
75 /// A reaction based on a predefined emoji.
76 Emoji(String),
77 /// The reaction is paid.
78 Paid,
79}
80
81impl ReactionType {
82 /// Creates a new `ReactionType` based on a custom emoji.
83 ///
84 /// # Arguments
85 ///
86 /// `value` - A custom emoji.
87 pub fn custom_emoji<T>(value: T) -> Self
88 where
89 T: Into<String>,
90 {
91 Self::CustomEmoji(value.into())
92 }
93
94 /// Creates a new `ReactionType` based on a predefined emoji.
95 ///
96 /// # Arguments
97 ///
98 /// `value` - A predefined emoji.
99 pub fn emoji<T>(value: T) -> Self
100 where
101 T: Into<String>,
102 {
103 Self::Emoji(value.into())
104 }
105}
106
107#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
108#[serde(rename_all = "snake_case", tag = "type")]
109enum RawReactionType {
110 CustomEmoji { custom_emoji_id: String },
111 Emoji { emoji: String },
112 Paid,
113}
114
115impl From<ReactionType> for RawReactionType {
116 fn from(value: ReactionType) -> Self {
117 match value {
118 ReactionType::CustomEmoji(custom_emoji_id) => Self::CustomEmoji { custom_emoji_id },
119 ReactionType::Emoji(emoji) => Self::Emoji { emoji },
120 ReactionType::Paid => Self::Paid,
121 }
122 }
123}
124
125impl From<RawReactionType> for ReactionType {
126 fn from(value: RawReactionType) -> Self {
127 match value {
128 RawReactionType::CustomEmoji { custom_emoji_id } => Self::CustomEmoji(custom_emoji_id),
129 RawReactionType::Emoji { emoji } => Self::Emoji(emoji),
130 RawReactionType::Paid => Self::Paid,
131 }
132 }
133}
134
135/// Represents a change of a reaction on a message performed by a user.
136#[serde_with::skip_serializing_none]
137#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
138pub struct MessageReactionUpdated {
139 /// The chat containing the message the user reacted to.
140 pub chat: Chat,
141 /// Date of the change in Unix time.
142 pub date: Integer,
143 /// Unique identifier of the message inside the chat.
144 pub message_id: Integer,
145 /// New list of reaction types that have been set by the user.
146 pub new_reaction: Vec<ReactionType>,
147 /// Previous list of reaction types that were set by the user.
148 pub old_reaction: Vec<ReactionType>,
149 /// The chat on behalf of which the reaction was changed, if the user is anonymous.
150 pub actor_chat: Option<Chat>,
151 /// The user that changed the reaction, if the user isn't anonymous.
152 pub user: Option<User>,
153}
154
155impl MessageReactionUpdated {
156 /// Creates a new `MessageReactionUpdated`.
157 ///
158 /// # Arguments
159 ///
160 /// * `chat` - The chat containing the message the user reacted to.
161 /// * `date` - Date of the change in Unix time.
162 /// * `message_id` - Unique identifier of the message inside the chat.
163 /// * `new_reaction` - New list of reaction types that have been set by the user.
164 /// * `old_reaction` - Previous list of reaction types that were set by the user.
165 pub fn new<A, B, C>(chat: A, date: Integer, message_id: Integer, new_reaction: B, old_reaction: C) -> Self
166 where
167 A: Into<Chat>,
168 B: IntoIterator<Item = ReactionType>,
169 C: IntoIterator<Item = ReactionType>,
170 {
171 Self {
172 chat: chat.into(),
173 date,
174 message_id,
175 new_reaction: new_reaction.into_iter().collect(),
176 old_reaction: old_reaction.into_iter().collect(),
177 actor_chat: None,
178 user: None,
179 }
180 }
181
182 /// Sets a new actor chat.
183 ///
184 /// # Arguments
185 ///
186 /// * `value` - The chat on behalf of which the reaction was changed, if the user is anonymous.
187 pub fn with_actor_chat<T>(mut self, value: T) -> Self
188 where
189 T: Into<Chat>,
190 {
191 self.actor_chat = Some(value.into());
192 self
193 }
194
195 /// Sets a new user.
196 ///
197 /// # Arguments
198 ///
199 /// * `value` - The user that changed the reaction, if the user isn't anonymous.
200 pub fn with_user(mut self, value: User) -> Self {
201 self.user = Some(value);
202 self
203 }
204}
205
206/// Remove up to 10000 recent reactions in a group
207/// or a supergroup chat added by a given user or chat.
208///
209/// The bot must have the 'can_delete_messages' administrator right in the chat.
210#[serde_with::skip_serializing_none]
211#[derive(Clone, Debug, Serialize)]
212pub struct DeleteAllMessageReactions {
213 chat_id: ChatId,
214 actor_chat_id: Option<Integer>,
215 user_id: Option<Integer>,
216}
217
218impl DeleteAllMessageReactions {
219 /// Creates a new `DeleteAllMessageReactions`.
220 ///
221 /// # Arguments
222 ///
223 /// * `chat_id` - Unique identifier for the target chat.
224 pub fn new<T>(chat_id: T) -> Self
225 where
226 T: Into<ChatId>,
227 {
228 Self {
229 chat_id: chat_id.into(),
230 actor_chat_id: None,
231 user_id: None,
232 }
233 }
234
235 /// Sets a new actor chat ID.
236 ///
237 /// # Arguments
238 ///
239 /// * `value` - Identifier of the chat whose reactions will be removed,
240 /// if the reactions were added by a chat
241 pub fn with_actor_chat_id(mut self, value: Integer) -> Self {
242 self.actor_chat_id = Some(value);
243 self
244 }
245
246 /// Sets a new user ID.
247 ///
248 /// # Arguments
249 ///
250 /// * `value` - Identifier of the user whose reactions will be removed,
251 /// if the reactions were added by a user
252 pub fn with_user_id(mut self, value: Integer) -> Self {
253 self.user_id = Some(value);
254 self
255 }
256}
257
258impl Method for DeleteAllMessageReactions {
259 type Response = bool;
260
261 fn into_payload(self) -> Payload {
262 Payload::json("deleteAllMessageReactions", self)
263 }
264}
265
266/// Removes a reaction from a message in a group or a supergroup chat.
267///
268/// The bot must have the `can_delete_messages` administrator right in the chat.
269#[serde_with::skip_serializing_none]
270#[derive(Clone, Debug, Serialize)]
271pub struct DeleteMessageReaction {
272 chat_id: ChatId,
273 message_id: Integer,
274 actor_chat_id: Option<Integer>,
275 user_id: Option<Integer>,
276}
277
278impl DeleteMessageReaction {
279 /// Creates a new `DeleteMessageReaction`.
280 ///
281 /// # Arguments
282 ///
283 /// * `chat_id` - Unique identifier of the target chat.
284 /// * `message_id` - Identifier of the target message.
285 pub fn new<T>(chat_id: T, message_id: Integer) -> Self
286 where
287 T: Into<ChatId>,
288 {
289 Self {
290 chat_id: chat_id.into(),
291 message_id,
292 actor_chat_id: None,
293 user_id: None,
294 }
295 }
296
297 /// Sets a new actor chat ID.
298 ///
299 /// # Arguments
300 ///
301 /// * `value` - Identifier of the chat whose reaction will be removed,
302 /// if the reaction was added by a chat.
303 pub fn with_actor_chat_id(mut self, value: Integer) -> Self {
304 self.actor_chat_id = Some(value);
305 self
306 }
307
308 /// Sets a new user ID.
309 ///
310 /// # Arguments
311 ///
312 /// * `value` - Identifier of the user whose reaction will be removed,
313 /// if the reaction was added by a chat.
314 pub fn with_user_id(mut self, value: Integer) -> Self {
315 self.user_id = Some(value);
316 self
317 }
318}
319
320impl Method for DeleteMessageReaction {
321 type Response = bool;
322
323 fn into_payload(self) -> Payload {
324 Payload::json("deleteMessageReaction", self)
325 }
326}
327
328/// Changes the chosen reactions on a message.
329///
330/// Service messages of some types can't be reacted to.
331/// Automatically forwarded messages from a channel to its discussion group have
332/// the same available reactions as messages in the channel.
333/// Bots can't use paid reactions.
334#[serde_with::skip_serializing_none]
335#[derive(Clone, Debug, Serialize)]
336pub struct SetMessageReaction {
337 chat_id: ChatId,
338 is_big: bool,
339 message_id: Integer,
340 reaction: Option<Vec<ReactionType>>,
341}
342
343impl SetMessageReaction {
344 /// Creates a new `SetMessageReaction`.
345 ///
346 /// # Arguments
347 ///
348 /// * `chat_id` - Unique identifier of the target chat.
349 /// * `message_id` - Identifier of the target message.
350 pub fn new<T>(chat_id: T, message_id: Integer) -> Self
351 where
352 T: Into<ChatId>,
353 {
354 Self {
355 chat_id: chat_id.into(),
356 message_id,
357 reaction: None,
358 is_big: false,
359 }
360 }
361
362 /// Sets a new value for the `is_big` flag.
363 ///
364 /// # Arguments
365 ///
366 /// * `value` - Whether to set the reaction with a big animation.
367 pub fn with_is_big(mut self, value: bool) -> Self {
368 self.is_big = value;
369 self
370 }
371
372 /// Sets a new list of reaction types.
373 ///
374 /// # Arguments
375 ///
376 /// * `value` - New list of reaction types to set on the message.
377 ///
378 /// Currently, as non-premium users, bots can set up to one reaction per message.
379 /// A custom emoji reaction can be used if it is either already present on
380 /// the message or explicitly allowed by chat administrators.
381 pub fn with_reaction<T>(mut self, value: T) -> Self
382 where
383 T: IntoIterator<Item = ReactionType>,
384 {
385 self.reaction = Some(value.into_iter().collect());
386 self
387 }
388}
389
390impl Method for SetMessageReaction {
391 type Response = bool;
392
393 fn into_payload(self) -> Payload {
394 Payload::json("setMessageReaction", self)
395 }
396}