0000: 2f 2f 21 20 54 65 6c 65 67 72 61 6d 20 41 50 49 //! Telegram API
0010: 20 69 6e 74 65 67 72 61 74 69 6f 6e 20 66 6f 72 integration for
0020: 20 73 65 6e 64 69 6e 67 20 6d 65 73 73 61 67 65 sending message
0030: 73 20 61 6e 64 20 61 74 74 61 63 68 6d 65 6e 74 s and attachment
0040: 73 2e 0a 0a 75 73 65 20 63 72 61 74 65 3a 3a 75 s...use crate::u
0050: 74 69 6c 73 3a 3a 7b 0a 09 41 74 74 61 63 68 6d tils::{..Attachm
0060: 65 6e 74 2c 0a 09 76 61 6c 69 64 61 74 65 2c 0a ent,..validate,.
0070: 7d 3b 0a 0a 75 73 65 20 73 74 64 3a 3a 7b 0a 09 };..use std::{..
0080: 63 6f 6c 6c 65 63 74 69 6f 6e 73 3a 3a 48 61 73 collections::Has
0090: 68 4d 61 70 2c 0a 09 66 6d 74 3a 3a 44 65 62 75 hMap,..fmt::Debu
00a0: 67 2c 0a 7d 3b 0a 0a 75 73 65 20 73 74 61 63 6b g,.};..use stack
00b0: 65 64 5f 65 72 72 6f 72 73 3a 3a 7b 0a 09 62 61 ed_errors::{..ba
00c0: 69 6c 2c 0a 09 52 65 73 75 6c 74 2c 0a 09 53 74 il,..Result,..St
00d0: 61 63 6b 61 62 6c 65 45 72 72 2c 0a 7d 3b 0a 75 ackableErr,.};.u
00e0: 73 65 20 74 67 62 6f 74 3a 3a 7b 0a 09 61 70 69 se tgbot::{..api
00f0: 3a 3a 43 6c 69 65 6e 74 2c 0a 09 74 79 70 65 73 ::Client,..types
0100: 3a 3a 7b 0a 09 09 43 68 61 74 50 65 65 72 49 64 ::{...ChatPeerId
0110: 2c 0a 09 09 49 6e 70 75 74 46 69 6c 65 2c 0a 09 ,...InputFile,..
0120: 09 49 6e 70 75 74 46 69 6c 65 52 65 61 64 65 72 .InputFileReader
0130: 2c 0a 09 09 49 6e 70 75 74 4d 65 64 69 61 44 6f ,...InputMediaDo
0140: 63 75 6d 65 6e 74 2c 0a 09 09 49 6e 70 75 74 54 cument,...InputT
0150: 65 78 74 2c 0a 09 09 4d 65 64 69 61 47 72 6f 75 ext,...MediaGrou
0160: 70 2c 0a 09 09 4d 65 64 69 61 47 72 6f 75 70 49 p,...MediaGroupI
0170: 74 65 6d 2c 0a 09 09 4d 65 73 73 61 67 65 2c 0a tem,...Message,.
0180: 09 09 50 61 72 73 65 4d 6f 64 65 3a 3a 48 74 6d ..ParseMode::Htm
0190: 6c 2c 0a 09 09 53 65 6e 64 44 6f 63 75 6d 65 6e l,...SendDocumen
01a0: 74 2c 0a 09 09 53 65 6e 64 4d 65 64 69 61 47 72 t,...SendMediaGr
01b0: 6f 75 70 2c 0a 09 09 53 65 6e 64 4d 65 73 73 61 oup,...SendMessa
01c0: 67 65 2c 0a 09 7d 2c 0a 7d 3b 0a 0a 23 5b 64 65 ge,..},.};..#[de
01d0: 72 69 76 65 28 44 65 62 75 67 29 5d 0a 70 75 62 rive(Debug)].pub
01e0: 20 73 74 72 75 63 74 20 54 65 6c 65 67 72 61 6d struct Telegram
01f0: 54 72 61 6e 73 70 6f 72 74 20 7b 0a 09 74 67 3a Transport {..tg:
0200: 20 43 6c 69 65 6e 74 2c 0a 09 72 65 63 69 70 69 Client,..recipi
0210: 65 6e 74 73 3a 20 48 61 73 68 4d 61 70 3c 53 74 ents: HashMap<St
0220: 72 69 6e 67 2c 20 43 68 61 74 50 65 65 72 49 64 ring, ChatPeerId
0230: 3e 2c 0a 09 70 75 62 20 64 65 66 61 75 6c 74 3a >,..pub default:
0240: 20 43 68 61 74 50 65 65 72 49 64 2c 0a 7d 0a 0a ChatPeerId,.}..
0250: 69 6d 70 6c 20 54 65 6c 65 67 72 61 6d 54 72 61 impl TelegramTra
0260: 6e 73 70 6f 72 74 20 7b 0a 09 2f 2f 2f 20 43 72 nsport {../// Cr
0270: 65 61 74 65 73 20 61 20 6e 65 77 20 60 54 65 6c eates a new `Tel
0280: 65 67 72 61 6d 54 72 61 6e 73 70 6f 72 74 60 20 egramTransport`
0290: 69 6e 73 74 61 6e 63 65 2e 0a 09 2f 2f 2f 0a 09 instance...///..
02a0: 2f 2f 2f 20 23 20 41 72 67 75 6d 65 6e 74 73 0a /// # Arguments.
02b0: 09 2f 2f 2f 20 2a 20 60 61 70 69 5f 6b 65 79 60 ./// * `api_key`
02c0: 20 2d 20 54 65 6c 65 67 72 61 6d 20 42 6f 74 20 - Telegram Bot
02d0: 41 50 49 20 74 6f 6b 65 6e 2e 0a 09 2f 2f 2f 20 API token...///
02e0: 2a 20 60 72 65 63 69 70 69 65 6e 74 73 60 20 2d * `recipients` -
02f0: 20 4d 61 70 70 69 6e 67 20 6f 66 20 65 6d 61 69 Mapping of emai
0300: 6c 20 61 64 64 72 65 73 73 65 73 20 74 6f 20 54 l addresses to T
0310: 65 6c 65 67 72 61 6d 20 63 68 61 74 20 49 44 73 elegram chat IDs
0320: 2e 0a 09 2f 2f 2f 20 2a 20 60 73 65 74 74 69 6e .../// * `settin
0330: 67 73 60 20 2d 20 41 64 64 69 74 69 6f 6e 61 6c gs` - Additional
0340: 20 63 6f 6e 66 69 67 75 72 61 74 69 6f 6e 20 28 configuration (
0350: 41 50 49 20 67 61 74 65 77 61 79 2c 20 64 65 66 API gateway, def
0360: 61 75 6c 74 20 63 68 61 74 29 2e 0a 09 2f 2f 2f ault chat)...///
0370: 0a 09 2f 2f 2f 20 23 20 45 72 72 6f 72 73 0a 09 ../// # Errors..
0380: 2f 2f 2f 20 52 65 74 75 72 6e 73 20 61 6e 20 65 /// Returns an e
0390: 72 72 6f 72 20 69 66 20 63 6f 6e 66 69 67 75 72 rror if configur
03a0: 61 74 69 6f 6e 20 76 61 6c 75 65 73 20 63 61 6e ation values can
03b0: 6e 6f 74 20 62 65 20 72 65 61 64 20 6f 72 20 69 not be read or i
03c0: 66 20 54 65 6c 65 67 72 61 6d 0a 09 2f 2f 2f 20 f Telegram..///
03d0: 41 50 49 20 63 6c 69 65 6e 74 20 63 72 65 61 74 API client creat
03e0: 69 6f 6e 20 66 61 69 6c 73 2e 0a 09 70 75 62 20 ion fails...pub
03f0: 66 6e 20 6e 65 77 20 28 61 70 69 5f 6b 65 79 3a fn new (api_key:
0400: 20 53 74 72 69 6e 67 2c 20 72 65 63 69 70 69 65 String, recipie
0410: 6e 74 73 3a 20 48 61 73 68 4d 61 70 3c 53 74 72 nts: HashMap<Str
0420: 69 6e 67 2c 20 69 36 34 3e 2c 20 73 65 74 74 69 ing, i64>, setti
0430: 6e 67 73 3a 20 26 63 6f 6e 66 69 67 3a 3a 43 6f ngs: &config::Co
0440: 6e 66 69 67 29 20 2d 3e 20 52 65 73 75 6c 74 3c nfig) -> Result<
0450: 54 65 6c 65 67 72 61 6d 54 72 61 6e 73 70 6f 72 TelegramTranspor
0460: 74 3e 20 7b 0a 09 09 6c 65 74 20 64 65 66 61 75 t> {...let defau
0470: 6c 74 20 3d 20 73 65 74 74 69 6e 67 73 2e 67 65 lt = settings.ge
0480: 74 5f 69 6e 74 28 22 64 65 66 61 75 6c 74 22 29 t_int("default")
0490: 0a 09 09 09 2e 63 6f 6e 74 65 78 74 28 22 5b 73 .....context("[s
04a0: 6d 74 70 32 74 67 2e 74 6f 6d 6c 5d 20 6d 69 73 mtp2tg.toml] mis
04b0: 73 69 6e 67 20 5c 22 64 65 66 61 75 6c 74 5c 22 sing \"default\"
04c0: 20 72 65 63 69 70 69 65 6e 74 2e 5c 6e 22 29 3f recipient.\n")?
04d0: 3b 0a 09 09 6c 65 74 20 61 70 69 5f 67 61 74 65 ;...let api_gate
04e0: 77 61 79 20 3d 20 73 65 74 74 69 6e 67 73 2e 67 way = settings.g
04f0: 65 74 5f 73 74 72 69 6e 67 28 22 61 70 69 5f 67 et_string("api_g
0500: 61 74 65 77 61 79 22 29 0a 09 09 09 2e 63 6f 6e ateway").....con
0510: 74 65 78 74 28 22 5b 73 6d 74 70 32 74 67 2e 74 text("[smtp2tg.t
0520: 6f 6d 6c 5d 20 6d 69 73 73 69 6e 67 20 5c 22 61 oml] missing \"a
0530: 70 69 5f 67 61 74 65 77 61 79 5c 22 20 64 65 73 pi_gateway\" des
0540: 74 69 6e 61 74 69 6f 6e 2e 5c 6e 22 29 3f 3b 0a tination.\n")?;.
0550: 0a 09 09 6c 65 74 20 74 67 20 3d 20 43 6c 69 65 ...let tg = Clie
0560: 6e 74 3a 3a 6e 65 77 28 61 70 69 5f 6b 65 79 29 nt::new(api_key)
0570: 0a 09 09 09 2e 63 6f 6e 74 65 78 74 28 22 46 61 .....context("Fa
0580: 69 6c 65 64 20 74 6f 20 63 72 65 61 74 65 20 41 iled to create A
0590: 50 49 2e 5c 6e 22 29 3f 0a 09 09 09 2e 77 69 74 PI.\n")?.....wit
05a0: 68 5f 68 6f 73 74 28 61 70 69 5f 67 61 74 65 77 h_host(api_gatew
05b0: 61 79 29 3b 0a 09 09 6c 65 74 20 72 65 63 69 70 ay);...let recip
05c0: 69 65 6e 74 73 20 3d 20 72 65 63 69 70 69 65 6e ients = recipien
05d0: 74 73 2e 69 6e 74 6f 5f 69 74 65 72 28 29 0a 09 ts.into_iter()..
05e0: 09 09 2e 6d 61 70 28 7c 28 61 2c 20 62 29 7c 20 ...map(|(a, b)|
05f0: 28 61 2c 20 43 68 61 74 50 65 65 72 49 64 3a 3a (a, ChatPeerId::
0600: 66 72 6f 6d 28 62 29 29 29 2e 63 6f 6c 6c 65 63 from(b))).collec
0610: 74 28 29 3b 0a 09 09 6c 65 74 20 64 65 66 61 75 t();...let defau
0620: 6c 74 20 3d 20 43 68 61 74 50 65 65 72 49 64 3a lt = ChatPeerId:
0630: 3a 66 72 6f 6d 28 64 65 66 61 75 6c 74 29 3b 0a :from(default);.
0640: 0a 09 09 4f 6b 28 54 65 6c 65 67 72 61 6d 54 72 ...Ok(TelegramTr
0650: 61 6e 73 70 6f 72 74 20 7b 0a 09 09 09 74 67 2c ansport {....tg,
0660: 0a 09 09 09 72 65 63 69 70 69 65 6e 74 73 2c 0a ....recipients,.
0670: 09 09 09 64 65 66 61 75 6c 74 2c 0a 09 09 7d 29 ...default,...})
0680: 0a 09 7d 0a 0a 09 2f 2f 2f 20 53 65 6e 64 73 20 ..}.../// Sends
0690: 61 20 64 65 62 75 67 20 6d 65 73 73 61 67 65 20 a debug message
06a0: 74 6f 20 74 68 65 20 64 65 66 61 75 6c 74 20 63 to the default c
06b0: 68 61 74 2e 0a 09 2f 2f 2f 0a 09 2f 2f 2f 20 23 hat...///../// #
06c0: 20 41 72 67 75 6d 65 6e 74 73 0a 09 2f 2f 2f 20 Arguments..///
06d0: 2a 20 60 6d 73 67 60 20 2d 20 4d 65 73 73 61 67 * `msg` - Messag
06e0: 65 20 74 65 78 74 20 74 6f 20 73 65 6e 64 2e 0a e text to send..
06f0: 09 2f 2f 2f 0a 09 2f 2f 2f 20 23 20 52 65 74 75 .///../// # Retu
0700: 72 6e 73 0a 09 2f 2f 2f 20 2a 20 60 52 65 73 75 rns../// * `Resu
0710: 6c 74 3c 4d 65 73 73 61 67 65 3e 60 20 2d 20 54 lt<Message>` - T
0720: 65 6c 65 67 72 61 6d 20 41 50 49 20 72 65 73 70 elegram API resp
0730: 6f 6e 73 65 2e 0a 09 2f 2f 2f 0a 09 2f 2f 2f 20 onse...///..///
0740: 23 20 45 72 72 6f 72 73 0a 09 2f 2f 2f 20 52 65 # Errors../// Re
0750: 74 75 72 6e 73 20 61 6e 20 65 72 72 6f 72 20 69 turns an error i
0760: 66 20 60 6d 73 67 60 20 63 6f 6e 74 61 69 6e 73 f `msg` contains
0770: 20 61 20 63 6c 6f 73 69 6e 67 20 54 65 6c 65 67 a closing Teleg
0780: 72 61 6d 20 74 61 67 20 6f 72 20 73 65 6e 64 69 ram tag or sendi
0790: 6e 67 20 66 61 69 6c 73 2e 0a 09 70 75 62 20 61 ng fails...pub a
07a0: 73 79 6e 63 20 66 6e 20 64 65 62 75 67 20 28 26 sync fn debug (&
07b0: 73 65 6c 66 2c 20 6d 73 67 3a 20 26 73 74 72 29 self, msg: &str)
07c0: 20 2d 3e 20 52 65 73 75 6c 74 3c 4d 65 73 73 61 -> Result<Messa
07d0: 67 65 3e 20 7b 0a 09 09 73 65 6c 66 2e 73 65 6e ge> {...self.sen
07e0: 64 28 26 73 65 6c 66 2e 64 65 66 61 75 6c 74 2c d(&self.default,
07f0: 20 26 66 6f 72 6d 61 74 21 28 22 3c 70 72 65 3e &format!("<pre>
0800: 7b 7d 3c 2f 70 72 65 3e 22 2c 20 76 61 6c 69 64 {}</pre>", valid
0810: 61 74 65 28 6d 73 67 29 2e 73 74 61 63 6b 28 29 ate(msg).stack()
0820: 3f 29 29 2e 61 77 61 69 74 0a 09 7d 0a 0a 09 2f ?)).await..}.../
0830: 2f 2f 20 52 65 74 72 69 65 76 65 73 20 61 20 63 // Retrieves a c
0840: 68 61 74 20 49 44 20 62 79 20 6e 61 6d 65 2e 0a hat ID by name..
0850: 09 2f 2f 2f 0a 09 2f 2f 2f 20 23 20 41 72 67 75 .///../// # Argu
0860: 6d 65 6e 74 73 0a 09 2f 2f 2f 20 2a 20 60 6e 61 ments../// * `na
0870: 6d 65 60 20 2d 20 4e 61 6d 65 20 6f 72 20 65 6d me` - Name or em
0880: 61 69 6c 20 74 6f 20 6c 6f 6f 6b 20 75 70 2e 0a ail to look up..
0890: 09 2f 2f 2f 0a 09 2f 2f 2f 20 23 20 52 65 74 75 .///../// # Retu
08a0: 72 6e 73 0a 09 2f 2f 2f 20 2a 20 60 52 65 73 75 rns../// * `Resu
08b0: 6c 74 3c 26 43 68 61 74 50 65 65 72 49 64 3e 60 lt<&ChatPeerId>`
08c0: 20 2d 20 43 68 61 74 20 49 44 20 69 66 20 66 6f - Chat ID if fo
08d0: 75 6e 64 2e 0a 09 2f 2f 2f 0a 09 2f 2f 2f 20 23 und...///../// #
08e0: 20 45 72 72 6f 72 73 0a 09 2f 2f 2f 20 52 65 74 Errors../// Ret
08f0: 75 72 6e 73 20 61 6e 20 65 72 72 6f 72 20 69 66 urns an error if
0900: 20 60 6e 61 6d 65 60 20 69 73 20 6e 6f 74 20 63 `name` is not c
0910: 6f 6e 66 69 67 75 72 65 64 2e 0a 09 70 75 62 20 onfigured...pub
0920: 66 6e 20 67 65 74 20 28 26 73 65 6c 66 2c 20 6e fn get (&self, n
0930: 61 6d 65 3a 20 26 73 74 72 29 20 2d 3e 20 52 65 ame: &str) -> Re
0940: 73 75 6c 74 3c 26 43 68 61 74 50 65 65 72 49 64 sult<&ChatPeerId
0950: 3e 20 7b 0a 09 09 73 65 6c 66 2e 72 65 63 69 70 > {...self.recip
0960: 69 65 6e 74 73 2e 67 65 74 28 26 6e 61 6d 65 2e ients.get(&name.
0970: 74 6f 5f 6c 6f 77 65 72 63 61 73 65 28 29 29 0a to_lowercase()).
0980: 09 09 09 2e 77 69 74 68 5f 63 6f 6e 74 65 78 74 ....with_context
0990: 28 7c 7c 20 66 6f 72 6d 61 74 21 28 22 52 65 63 (|| format!("Rec
09a0: 69 70 69 65 6e 74 20 7b 6e 61 6d 65 3a 3f 7d 20 ipient {name:?}
09b0: 6e 6f 74 20 66 6f 75 6e 64 20 69 6e 20 63 6f 6e not found in con
09c0: 66 69 67 75 72 61 74 69 6f 6e 22 29 29 0a 09 7d figuration"))..}
09d0: 0a 0a 09 2f 2f 2f 20 53 65 6e 64 73 20 61 20 74 .../// Sends a t
09e0: 65 78 74 20 6d 65 73 73 61 67 65 20 74 6f 20 61 ext message to a
09f0: 20 73 70 65 63 69 66 69 65 64 20 63 68 61 74 2e specified chat.
0a00: 0a 09 2f 2f 2f 0a 09 2f 2f 2f 20 23 20 41 72 67 ..///../// # Arg
0a10: 75 6d 65 6e 74 73 0a 09 2f 2f 2f 20 2a 20 60 74 uments../// * `t
0a20: 6f 60 20 2d 20 54 61 72 67 65 74 20 63 68 61 74 o` - Target chat
0a30: 20 49 44 2e 0a 09 2f 2f 2f 20 2a 20 60 6d 73 67 ID.../// * `msg
0a40: 60 20 2d 20 4d 65 73 73 61 67 65 20 74 65 78 74 ` - Message text
0a50: 20 28 73 75 70 70 6f 72 74 73 20 48 54 4d 4c 20 (supports HTML
0a60: 66 6f 72 6d 61 74 74 69 6e 67 29 2e 0a 09 2f 2f formatting)...//
0a70: 2f 0a 09 2f 2f 2f 20 23 20 52 65 74 75 72 6e 73 /../// # Returns
0a80: 0a 09 2f 2f 2f 20 2a 20 60 52 65 73 75 6c 74 3c ../// * `Result<
0a90: 4d 65 73 73 61 67 65 3e 60 20 2d 20 54 65 6c 65 Message>` - Tele
0aa0: 67 72 61 6d 20 41 50 49 20 72 65 73 70 6f 6e 73 gram API respons
0ab0: 65 2e 0a 09 70 75 62 20 61 73 79 6e 63 20 66 6e e...pub async fn
0ac0: 20 73 65 6e 64 20 28 26 73 65 6c 66 2c 20 74 6f send (&self, to
0ad0: 3a 20 26 43 68 61 74 50 65 65 72 49 64 2c 20 6d : &ChatPeerId, m
0ae0: 73 67 3a 20 26 73 74 72 29 20 2d 3e 20 52 65 73 sg: &str) -> Res
0af0: 75 6c 74 3c 4d 65 73 73 61 67 65 3e 20 7b 0a 09 ult<Message> {..
0b00: 09 73 65 6c 66 2e 74 67 2e 65 78 65 63 75 74 65 .self.tg.execute
0b10: 28 0a 09 09 09 53 65 6e 64 4d 65 73 73 61 67 65 (....SendMessage
0b20: 3a 3a 6e 65 77 28 2a 74 6f 2c 20 49 6e 70 75 74 ::new(*to, Input
0b30: 54 65 78 74 3a 3a 66 72 6f 6d 28 6d 73 67 29 2e Text::from(msg).
0b40: 77 69 74 68 5f 66 6f 72 6d 61 74 28 48 74 6d 6c with_format(Html
0b50: 29 29 0a 09 09 29 2e 61 77 61 69 74 2e 73 74 61 ))...).await.sta
0b60: 63 6b 28 29 0a 09 7d 0a 0a 09 2f 2f 2f 20 53 65 ck()..}.../// Se
0b70: 6e 64 73 20 61 20 6d 65 73 73 61 67 65 20 77 69 nds a message wi
0b80: 74 68 20 61 74 74 61 63 68 6d 65 6e 74 73 20 74 th attachments t
0b90: 6f 20 61 20 73 70 65 63 69 66 69 65 64 20 63 68 o a specified ch
0ba0: 61 74 2e 0a 09 2f 2f 2f 0a 09 2f 2f 2f 20 23 20 at...///../// #
0bb0: 41 72 67 75 6d 65 6e 74 73 0a 09 2f 2f 2f 20 2a Arguments../// *
0bc0: 20 60 74 6f 60 20 2d 20 54 61 72 67 65 74 20 63 `to` - Target c
0bd0: 68 61 74 20 49 44 2e 0a 09 2f 2f 2f 20 2a 20 60 hat ID.../// * `
0be0: 6d 65 64 69 61 60 20 2d 20 4c 69 73 74 20 6f 66 media` - List of
0bf0: 20 61 74 74 61 63 68 6d 65 6e 74 73 2c 20 6e 6f attachments, no
0c00: 6e 2d 65 6d 70 74 79 2e 0a 09 2f 2f 2f 20 2a 20 n-empty.../// *
0c10: 60 6d 73 67 60 20 2d 20 4d 65 73 73 61 67 65 20 `msg` - Message
0c20: 74 65 78 74 20 28 73 75 70 70 6f 72 74 73 20 48 text (supports H
0c30: 54 4d 4c 20 66 6f 72 6d 61 74 74 69 6e 67 29 2e TML formatting).
0c40: 0a 09 2f 2f 2f 0a 09 2f 2f 2f 20 23 20 52 65 74 ..///../// # Ret
0c50: 75 72 6e 73 0a 09 2f 2f 2f 20 2a 20 60 52 65 73 urns../// * `Res
0c60: 75 6c 74 3c 28 29 3e 60 20 2d 20 66 61 69 6c 73 ult<()>` - fails
0c70: 20 69 66 20 60 6d 65 64 69 61 60 20 69 73 20 65 if `media` is e
0c80: 6d 70 74 79 2c 20 70 72 6f 62 6c 65 6d 73 20 66 mpty, problems f
0c90: 6f 72 6d 69 6e 67 20 6d 65 64 69 61 0a 09 2f 2f orming media..//
0ca0: 2f 20 20 20 67 72 6f 75 70 2c 20 72 65 71 75 65 / group, reque
0cb0: 73 74 20 66 61 69 6c 73 2e 0a 09 70 75 62 20 61 st fails...pub a
0cc0: 73 79 6e 63 20 66 6e 20 73 65 6e 64 67 72 6f 75 sync fn sendgrou
0cd0: 70 20 28 26 73 65 6c 66 2c 20 74 6f 3a 20 26 43 p (&self, to: &C
0ce0: 68 61 74 50 65 65 72 49 64 2c 20 6d 65 64 69 61 hatPeerId, media
0cf0: 3a 20 56 65 63 3c 41 74 74 61 63 68 6d 65 6e 74 : Vec<Attachment
0d00: 3e 2c 20 6d 73 67 3a 20 26 73 74 72 29 20 2d 3e >, msg: &str) ->
0d10: 20 52 65 73 75 6c 74 3c 28 29 3e 20 7b 0a 09 09 Result<()> {...
0d20: 69 66 20 6d 65 64 69 61 2e 6c 65 6e 28 29 20 3e if media.len() >
0d30: 20 31 20 7b 0a 09 09 09 6c 65 74 20 6d 75 74 20 1 {....let mut
0d40: 61 74 74 61 63 68 20 3d 20 76 65 63 21 5b 5d 3b attach = vec![];
0d50: 0a 09 09 09 6c 65 74 20 6d 75 74 20 70 6f 73 20 ....let mut pos
0d60: 3d 20 6d 65 64 69 61 2e 6c 65 6e 28 29 3b 0a 09 = media.len();..
0d70: 09 09 66 6f 72 20 66 69 6c 65 20 69 6e 20 6d 65 ..for file in me
0d80: 64 69 61 20 7b 0a 09 09 09 09 6c 65 74 20 6d 75 dia {.....let mu
0d90: 74 20 64 6f 63 20 3d 20 49 6e 70 75 74 4d 65 64 t doc = InputMed
0da0: 69 61 44 6f 63 75 6d 65 6e 74 3a 3a 66 72 6f 6d iaDocument::from
0db0: 28 0a 09 09 09 09 09 49 6e 70 75 74 46 69 6c 65 (......InputFile
0dc0: 3a 3a 66 72 6f 6d 28 0a 09 09 09 09 09 09 49 6e ::from(.......In
0dd0: 70 75 74 46 69 6c 65 52 65 61 64 65 72 3a 3a 66 putFileReader::f
0de0: 72 6f 6d 28 66 69 6c 65 2e 64 61 74 61 29 0a 09 rom(file.data)..
0df0: 09 09 09 09 09 09 2e 77 69 74 68 5f 66 69 6c 65 .......with_file
0e00: 5f 6e 61 6d 65 28 66 69 6c 65 2e 6e 61 6d 65 29 _name(file.name)
0e10: 0a 09 09 09 09 09 29 0a 09 09 09 09 29 3b 0a 09 ......).....);..
0e20: 09 09 09 69 66 20 70 6f 73 20 3d 3d 20 31 20 7b ...if pos == 1 {
0e30: 0a 09 09 09 09 09 64 6f 63 20 3d 20 64 6f 63 2e ......doc = doc.
0e40: 77 69 74 68 5f 63 61 70 74 69 6f 6e 28 49 6e 70 with_caption(Inp
0e50: 75 74 54 65 78 74 3a 3a 66 72 6f 6d 28 6d 73 67 utText::from(msg
0e60: 29 0a 09 09 09 09 09 09 2e 77 69 74 68 5f 66 6f )........with_fo
0e70: 72 6d 61 74 28 48 74 6d 6c 29 29 3b 0a 09 09 09 rmat(Html));....
0e80: 09 7d 0a 09 09 09 09 70 6f 73 20 2d 3d 20 31 3b .}.....pos -= 1;
0e90: 0a 09 09 09 09 61 74 74 61 63 68 2e 70 75 73 68 .....attach.push
0ea0: 28 4d 65 64 69 61 47 72 6f 75 70 49 74 65 6d 3a (MediaGroupItem:
0eb0: 3a 66 72 6f 6d 28 64 6f 63 29 29 3b 0a 09 09 09 :from(doc));....
0ec0: 7d 0a 09 09 09 73 65 6c 66 2e 74 67 2e 65 78 65 }....self.tg.exe
0ed0: 63 75 74 65 28 53 65 6e 64 4d 65 64 69 61 47 72 cute(SendMediaGr
0ee0: 6f 75 70 3a 3a 6e 65 77 28 2a 74 6f 2c 20 4d 65 oup::new(*to, Me
0ef0: 64 69 61 47 72 6f 75 70 3a 3a 6e 65 77 28 61 74 diaGroup::new(at
0f00: 74 61 63 68 29 2e 73 74 61 63 6b 28 29 3f 29 29 tach).stack()?))
0f10: 2e 61 77 61 69 74 2e 73 74 61 63 6b 28 29 3f 3b .await.stack()?;
0f20: 0a 09 09 7d 20 65 6c 73 65 20 7b 0a 09 09 09 69 ...} else {....i
0f30: 66 20 6d 65 64 69 61 2e 69 73 5f 65 6d 70 74 79 f media.is_empty
0f40: 28 29 20 7b 0a 09 09 09 09 62 61 69 6c 21 28 22 () {.....bail!("
0f50: 41 74 20 6c 65 61 73 74 20 6f 6e 65 20 61 74 74 At least one att
0f60: 61 63 68 6d 65 6e 74 20 69 73 20 72 65 71 75 69 achment is requi
0f70: 72 65 64 2e 22 29 3b 0a 09 09 09 7d 0a 09 09 09 red.");....}....
0f80: 73 65 6c 66 2e 74 67 2e 65 78 65 63 75 74 65 28 self.tg.execute(
0f90: 0a 09 09 09 09 53 65 6e 64 44 6f 63 75 6d 65 6e .....SendDocumen
0fa0: 74 3a 3a 6e 65 77 28 0a 09 09 09 09 09 2a 74 6f t::new(......*to
0fb0: 2c 0a 09 09 09 09 09 49 6e 70 75 74 46 69 6c 65 ,......InputFile
0fc0: 52 65 61 64 65 72 3a 3a 66 72 6f 6d 28 6d 65 64 Reader::from(med
0fd0: 69 61 5b 30 5d 2e 64 61 74 61 2e 63 6c 6f 6e 65 ia[0].data.clone
0fe0: 28 29 29 0a 09 09 09 09 09 09 2e 77 69 74 68 5f ())........with_
0ff0: 66 69 6c 65 5f 6e 61 6d 65 28 6d 65 64 69 61 5b file_name(media[
1000: 30 5d 2e 6e 61 6d 65 2e 63 6c 6f 6e 65 28 29 29 0].name.clone())
1010: 0a 09 09 09 09 29 2e 77 69 74 68 5f 63 61 70 74 .....).with_capt
1020: 69 6f 6e 28 49 6e 70 75 74 54 65 78 74 3a 3a 66 ion(InputText::f
1030: 72 6f 6d 28 6d 73 67 29 0a 09 09 09 09 09 2e 77 rom(msg).......w
1040: 69 74 68 5f 66 6f 72 6d 61 74 28 48 74 6d 6c 29 ith_format(Html)
1050: 29 0a 09 09 09 29 2e 61 77 61 69 74 2e 73 74 61 )....).await.sta
1060: 63 6b 28 29 3f 3b 0a 09 09 7d 0a 09 09 4f 6b 28 ck()?;...}...Ok(
1070: 28 29 29 0a 09 7d 0a 7d 0a ())..}.}.