1use std::{error::Error, fmt};
2
3use serde::{Deserialize, Serialize};
4
5use crate::{
6 api::{Method, Payload},
7 types::{Audio, Integer, Message, ParseMode, PhotoSize},
8};
9
10#[serde_with::skip_serializing_none]
12#[derive(Clone, Copy, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
13pub struct Birthdate {
14 pub day: Integer,
16 pub month: Integer,
18 pub year: Option<Integer>,
20}
21
22impl Birthdate {
23 pub fn new(day: Integer, month: Integer) -> Self {
30 Self { day, month, year: None }
31 }
32
33 pub fn with_year(mut self, value: Integer) -> Self {
39 self.year = Some(value);
40 self
41 }
42}
43
44#[serde_with::skip_serializing_none]
47#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
48pub struct SharedUser {
49 pub user_id: Integer,
54 pub first_name: Option<String>,
56 pub last_name: Option<String>,
58 pub photo: Option<Vec<PhotoSize>>,
60 pub username: Option<String>,
62}
63
64impl SharedUser {
65 pub fn new(user_id: Integer) -> Self {
71 Self {
72 user_id,
73 first_name: None,
74 last_name: None,
75 photo: None,
76 username: None,
77 }
78 }
79
80 pub fn with_first_name<T>(mut self, value: T) -> Self
86 where
87 T: Into<String>,
88 {
89 self.first_name = Some(value.into());
90 self
91 }
92
93 pub fn with_last_name<T>(mut self, value: T) -> Self
99 where
100 T: Into<String>,
101 {
102 self.last_name = Some(value.into());
103 self
104 }
105
106 pub fn with_photo<T>(mut self, value: T) -> Self
112 where
113 T: IntoIterator<Item = PhotoSize>,
114 {
115 self.photo = Some(value.into_iter().collect());
116 self
117 }
118
119 pub fn with_username<T>(mut self, value: T) -> Self
125 where
126 T: Into<String>,
127 {
128 self.username = Some(value.into());
129 self
130 }
131}
132
133#[serde_with::skip_serializing_none]
135#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
136pub struct User {
137 pub first_name: String,
139 pub id: UserPeerId,
141 pub is_bot: bool,
143 pub added_to_attachment_menu: Option<bool>,
145 pub is_premium: Option<bool>,
147 pub language_code: Option<String>,
151 pub last_name: Option<String>,
153 pub username: Option<UserUsername>,
155}
156
157impl User {
158 pub fn new<A, B>(id: A, first_name: B, is_bot: bool) -> Self
166 where
167 A: Into<UserPeerId>,
168 B: Into<String>,
169 {
170 Self {
171 first_name: first_name.into(),
172 id: id.into(),
173 is_bot,
174 added_to_attachment_menu: None,
175 is_premium: None,
176 language_code: None,
177 last_name: None,
178 username: None,
179 }
180 }
181
182 pub fn get_full_name(&self) -> String {
184 let mut full_name = self.first_name.clone();
185 if let Some(ref last_name) = self.last_name {
186 full_name.push(' ');
187 full_name += last_name;
188 }
189 full_name
190 }
191
192 pub fn get_link(&self) -> String {
198 format!("tg://user?id={}", self.id.0)
199 }
200
201 pub fn get_link_mention(&self, parse_mode: ParseMode) -> Result<String, MentionError> {
211 let full_name = parse_mode.escape(self.get_full_name());
212 let user_link = self.get_link();
213 Ok(match parse_mode {
214 ParseMode::Markdown => return Err(MentionError::UnsupportedParseMode(parse_mode)),
215 ParseMode::MarkdownV2 => format!(r#"[{full_name}]({user_link})"#),
216 ParseMode::Html => format!(r#"<a href="{user_link}">{full_name}</a>"#),
217 })
218 }
219
220 pub fn with_added_to_attachment_menu(mut self, value: bool) -> Self {
226 self.added_to_attachment_menu = Some(value);
227 self
228 }
229
230 pub fn with_is_premium(mut self, value: bool) -> Self {
236 self.is_premium = Some(value);
237 self
238 }
239
240 pub fn with_language_code<T>(mut self, value: T) -> Self
246 where
247 T: Into<String>,
248 {
249 self.language_code = Some(value.into());
250 self
251 }
252
253 pub fn with_last_name<T>(mut self, value: T) -> Self
259 where
260 T: Into<String>,
261 {
262 self.last_name = Some(value.into());
263 self
264 }
265
266 pub fn with_username<T>(mut self, value: T) -> Self
272 where
273 T: Into<UserUsername>,
274 {
275 self.username = Some(value.into());
276 self
277 }
278}
279
280#[derive(Debug)]
282pub enum MentionError {
283 UnsupportedParseMode(ParseMode),
285}
286
287impl Error for MentionError {}
288
289impl fmt::Display for MentionError {
290 fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
291 match self {
292 MentionError::UnsupportedParseMode(parse_mode) => {
293 write!(out, "can not mention with {parse_mode} parse mode")
294 }
295 }
296 }
297}
298
299#[derive(Clone, Debug, Deserialize, Serialize)]
301pub struct UserProfileAudios {
302 pub audios: Vec<Audio>,
304 pub total_count: Integer,
306}
307
308impl UserProfileAudios {
309 pub fn new<T>(audios: T, total_count: Integer) -> Self
316 where
317 T: IntoIterator<Item = Audio>,
318 {
319 Self {
320 audios: audios.into_iter().collect(),
321 total_count,
322 }
323 }
324}
325
326#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
328pub struct UserProfilePhotos {
329 pub photos: Vec<Vec<PhotoSize>>,
331 pub total_count: Integer,
333}
334
335impl UserProfilePhotos {
336 pub fn new<A, B>(photos: A, total_count: Integer) -> Self
343 where
344 A: IntoIterator<Item = B>,
345 B: IntoIterator<Item = PhotoSize>,
346 {
347 Self {
348 photos: photos.into_iter().map(|x| x.into_iter().collect()).collect(),
349 total_count,
350 }
351 }
352}
353
354#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
356#[serde(from = "Integer", into = "Integer")]
357pub struct UserPeerId(Integer);
358
359impl From<Integer> for UserPeerId {
360 fn from(value: Integer) -> Self {
361 Self(value)
362 }
363}
364
365impl From<UserPeerId> for Integer {
366 fn from(value: UserPeerId) -> Self {
367 value.0
368 }
369}
370
371impl fmt::Display for UserPeerId {
372 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
373 self.0.fmt(f)
374 }
375}
376
377impl PartialEq<Integer> for UserPeerId {
378 fn eq(&self, other: &Integer) -> bool {
379 self.0.eq(other)
380 }
381}
382
383#[derive(Copy, Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
385pub struct UserRating {
386 pub current_level_rating: Integer,
388 pub level: Integer,
392 pub rating: Integer,
394 pub next_level_rating: Option<Integer>,
396}
397
398#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
400#[serde(from = "String", into = "String")]
401pub struct UserUsername(String);
402
403impl From<&str> for UserUsername {
404 fn from(value: &str) -> Self {
405 Self(String::from(value))
406 }
407}
408
409impl From<String> for UserUsername {
410 fn from(value: String) -> Self {
411 Self(value)
412 }
413}
414
415impl From<UserUsername> for String {
416 fn from(value: UserUsername) -> Self {
417 value.0
418 }
419}
420
421impl fmt::Display for UserUsername {
422 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
423 self.0.fmt(f)
424 }
425}
426
427impl PartialEq<String> for UserUsername {
428 fn eq(&self, other: &String) -> bool {
429 self.0.eq(other)
430 }
431}
432
433impl PartialEq<str> for UserUsername {
434 fn eq(&self, other: &str) -> bool {
435 self.0.eq(other)
436 }
437}
438
439#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, PartialOrd, Serialize)]
441#[serde(untagged)]
442pub enum UserId {
443 Id(UserPeerId),
445 Username(UserUsername),
447}
448
449impl From<&str> for UserId {
450 fn from(username: &str) -> UserId {
451 UserId::Username(String::from(username).into())
452 }
453}
454
455impl From<String> for UserId {
456 fn from(username: String) -> UserId {
457 UserId::Username(username.into())
458 }
459}
460
461impl From<Integer> for UserId {
462 fn from(id: Integer) -> UserId {
463 UserId::Id(id.into())
464 }
465}
466
467impl fmt::Display for UserId {
468 fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
469 match self {
470 UserId::Id(chat_id) => write!(out, "{}", chat_id.0),
471 UserId::Username(username) => write!(out, "{}", username.0),
472 }
473 }
474}
475
476impl From<UserPeerId> for UserId {
477 fn from(value: UserPeerId) -> Self {
478 UserId::Id(value)
479 }
480}
481
482impl From<UserUsername> for UserId {
483 fn from(value: UserUsername) -> Self {
484 UserId::Username(value)
485 }
486}
487
488#[derive(Clone, Copy, Debug, Serialize)]
490pub struct GetUserPersonalChatMessages {
491 user_id: Integer,
492 limit: Integer,
493}
494
495impl GetUserPersonalChatMessages {
496 pub fn new(user_id: Integer, limit: Integer) -> Self {
503 Self { user_id, limit }
504 }
505}
506
507impl Method for GetUserPersonalChatMessages {
508 type Response = Vec<Message>;
509
510 fn into_payload(self) -> Payload {
511 Payload::json("getUserPersonalChatMessages", self)
512 }
513}
514
515#[serde_with::skip_serializing_none]
517#[derive(Clone, Copy, Debug, Serialize)]
518pub struct GetUserProfileAudios {
519 user_id: Integer,
520 limit: Option<Integer>,
521 offset: Option<Integer>,
522}
523
524impl GetUserProfileAudios {
525 pub fn new(user_id: Integer) -> Self {
531 Self {
532 user_id,
533 limit: None,
534 offset: None,
535 }
536 }
537
538 pub fn with_limit(mut self, value: Integer) -> Self {
546 self.limit = Some(value);
547 self
548 }
549
550 pub fn with_offset(mut self, value: Integer) -> Self {
558 self.offset = Some(value);
559 self
560 }
561}
562
563impl Method for GetUserProfileAudios {
564 type Response = UserProfileAudios;
565
566 fn into_payload(self) -> Payload {
567 Payload::json("getUserProfileAudios", self)
568 }
569}
570
571#[serde_with::skip_serializing_none]
573#[derive(Clone, Copy, Debug, Serialize)]
574pub struct GetUserProfilePhotos {
575 user_id: Integer,
576 limit: Option<Integer>,
577 offset: Option<Integer>,
578}
579
580impl GetUserProfilePhotos {
581 pub fn new(user_id: Integer) -> Self {
587 GetUserProfilePhotos {
588 user_id,
589 offset: None,
590 limit: None,
591 }
592 }
593
594 pub fn with_limit(mut self, limit: Integer) -> Self {
600 self.limit = Some(limit);
601 self
602 }
603
604 pub fn with_offset(mut self, offset: Integer) -> Self {
612 self.offset = Some(offset);
613 self
614 }
615}
616
617impl Method for GetUserProfilePhotos {
618 type Response = UserProfilePhotos;
619
620 fn into_payload(self) -> Payload {
621 Payload::json("getUserProfilePhotos", self)
622 }
623}
624
625#[serde_with::skip_serializing_none]
629#[derive(Clone, Debug, Serialize)]
630pub struct SetUserEmojiStatus {
631 user_id: Integer,
632 emoji_status_custom_emoji_id: Option<String>,
633 emoji_status_expiration_date: Option<Integer>,
634}
635
636impl SetUserEmojiStatus {
637 pub fn new(user_id: Integer) -> Self {
643 Self {
644 user_id,
645 emoji_status_custom_emoji_id: None,
646 emoji_status_expiration_date: None,
647 }
648 }
649
650 pub fn with_emoji_id<T>(mut self, value: T) -> Self
657 where
658 T: Into<String>,
659 {
660 self.emoji_status_custom_emoji_id = Some(value.into());
661 self
662 }
663
664 pub fn with_expiration_date(mut self, value: Integer) -> Self {
670 self.emoji_status_expiration_date = Some(value);
671 self
672 }
673}
674
675impl Method for SetUserEmojiStatus {
676 type Response = bool;
677
678 fn into_payload(self) -> Payload {
679 Payload::json("setUserEmojiStatus", self)
680 }
681}