0000: 75 73 65 20 63 72 61 74 65 3a 3a 7b 0a 09 63 6f use crate::{..co
0010: 6d 6d 61 6e 64 2c 0a 09 73 71 6c 3a 3a 44 62 2c mmand,..sql::Db,
0020: 0a 7d 3b 0a 0a 75 73 65 20 73 74 64 3a 3a 7b 0a .};..use std::{.
0030: 09 62 6f 72 72 6f 77 3a 3a 43 6f 77 2c 0a 09 63 .borrow::Cow,..c
0040: 6f 6c 6c 65 63 74 69 6f 6e 73 3a 3a 7b 0a 09 09 ollections::{...
0050: 42 54 72 65 65 4d 61 70 2c 0a 09 09 48 61 73 68 BTreeMap,...Hash
0060: 53 65 74 2c 0a 09 7d 2c 0a 09 73 79 6e 63 3a 3a Set,..},..sync::
0070: 7b 0a 09 09 41 72 63 2c 0a 09 09 4d 75 74 65 78 {...Arc,...Mutex
0080: 0a 09 7d 2c 0a 7d 3b 0a 0a 75 73 65 20 61 6e 79 ..},.};..use any
0090: 68 6f 77 3a 3a 7b 0a 09 61 6e 79 68 6f 77 2c 0a how::{..anyhow,.
00a0: 09 62 61 69 6c 2c 0a 09 52 65 73 75 6c 74 2c 0a .bail,..Result,.
00b0: 7d 3b 0a 75 73 65 20 61 73 79 6e 63 5f 73 74 64 };.use async_std
00c0: 3a 3a 74 61 73 6b 3b 0a 75 73 65 20 63 68 72 6f ::task;.use chro
00d0: 6e 6f 3a 3a 44 61 74 65 54 69 6d 65 3b 0a 75 73 no::DateTime;.us
00e0: 65 20 6c 61 7a 79 5f 73 74 61 74 69 63 3a 3a 6c e lazy_static::l
00f0: 61 7a 79 5f 73 74 61 74 69 63 3b 0a 75 73 65 20 azy_static;.use
0100: 72 65 67 65 78 3a 3a 52 65 67 65 78 3b 0a 75 73 regex::Regex;.us
0110: 65 20 74 67 62 6f 74 3a 3a 7b 0a 09 61 70 69 3a e tgbot::{..api:
0120: 3a 43 6c 69 65 6e 74 2c 0a 09 68 61 6e 64 6c 65 :Client,..handle
0130: 72 3a 3a 55 70 64 61 74 65 48 61 6e 64 6c 65 72 r::UpdateHandler
0140: 2c 0a 09 74 79 70 65 73 3a 3a 7b 0a 09 09 42 6f ,..types::{...Bo
0150: 74 2c 0a 09 09 43 68 61 74 50 65 65 72 49 64 2c t,...ChatPeerId,
0160: 0a 09 09 43 6f 6d 6d 61 6e 64 2c 0a 09 09 47 65 ...Command,...Ge
0170: 74 42 6f 74 2c 0a 09 09 4d 65 73 73 61 67 65 2c tBot,...Message,
0180: 0a 09 09 50 61 72 73 65 4d 6f 64 65 2c 0a 09 09 ...ParseMode,...
0190: 53 65 6e 64 4d 65 73 73 61 67 65 2c 0a 09 09 55 SendMessage,...U
01a0: 70 64 61 74 65 2c 0a 09 09 55 70 64 61 74 65 54 pdate,...UpdateT
01b0: 79 70 65 2c 0a 09 09 55 73 65 72 50 65 65 72 49 ype,...UserPeerI
01c0: 64 2c 0a 09 7d 2c 0a 7d 3b 0a 0a 6c 61 7a 79 5f d,..},.};..lazy_
01d0: 73 74 61 74 69 63 21 7b 0a 09 70 75 62 20 73 74 static!{..pub st
01e0: 61 74 69 63 20 72 65 66 20 52 45 5f 53 50 45 43 atic ref RE_SPEC
01f0: 49 41 4c 3a 20 52 65 67 65 78 20 3d 20 52 65 67 IAL: Regex = Reg
0200: 65 78 3a 3a 6e 65 77 28 72 22 28 5b 5c 2d 5f 2a ex::new(r"([\-_*
0210: 5c 5b 5c 5d 28 29 7e 60 3e 23 2b 7c 7b 7d 5c 2e \[\]()~`>#+|{}\.
0220: 21 5d 29 22 29 2e 75 6e 77 72 61 70 28 29 3b 0a !])").unwrap();.
0230: 7d 0a 0a 2f 2f 2f 20 45 6e 63 6f 64 65 73 20 73 }../// Encodes s
0240: 70 65 63 69 61 6c 20 48 54 4d 4c 20 65 6e 74 69 pecial HTML enti
0250: 74 69 65 73 20 74 6f 20 70 72 65 76 65 6e 74 20 ties to prevent
0260: 74 68 65 6d 20 69 6e 74 65 72 66 65 72 69 6e 67 them interfering
0270: 20 77 69 74 68 20 54 65 6c 65 67 72 61 6d 20 48 with Telegram H
0280: 54 4d 4c 0a 70 75 62 20 66 6e 20 65 6e 63 6f 64 TML.pub fn encod
0290: 65 20 28 74 65 78 74 3a 20 26 73 74 72 29 20 2d e (text: &str) -
02a0: 3e 20 43 6f 77 3c 27 5f 2c 20 73 74 72 3e 20 7b > Cow<'_, str> {
02b0: 0a 09 52 45 5f 53 50 45 43 49 41 4c 2e 72 65 70 ..RE_SPECIAL.rep
02c0: 6c 61 63 65 5f 61 6c 6c 28 74 65 78 74 2c 20 22 lace_all(text, "
02d0: 5c 5c 24 31 22 29 0a 7d 0a 0a 23 5b 64 65 72 69 \\$1").}..#[deri
02e0: 76 65 28 43 6c 6f 6e 65 29 5d 0a 70 75 62 20 73 ve(Clone)].pub s
02f0: 74 72 75 63 74 20 43 6f 72 65 20 7b 0a 09 6f 77 truct Core {..ow
0300: 6e 65 72 5f 63 68 61 74 3a 20 43 68 61 74 50 65 ner_chat: ChatPe
0310: 65 72 49 64 2c 0a 09 2f 2f 20 6d 61 78 5f 64 65 erId,..// max_de
0320: 6c 61 79 3a 20 75 31 36 2c 0a 09 70 75 62 20 74 lay: u16,..pub t
0330: 67 3a 20 43 6c 69 65 6e 74 2c 0a 09 70 75 62 20 g: Client,..pub
0340: 6d 65 3a 20 42 6f 74 2c 0a 09 70 75 62 20 64 62 me: Bot,..pub db
0350: 3a 20 44 62 2c 0a 09 73 6f 75 72 63 65 73 3a 20 : Db,..sources:
0360: 41 72 63 3c 4d 75 74 65 78 3c 48 61 73 68 53 65 Arc<Mutex<HashSe
0370: 74 3c 41 72 63 3c 69 33 32 3e 3e 3e 3e 2c 0a 09 t<Arc<i32>>>>,..
0380: 68 74 74 70 5f 63 6c 69 65 6e 74 3a 20 72 65 71 http_client: req
0390: 77 65 73 74 3a 3a 43 6c 69 65 6e 74 2c 0a 7d 0a west::Client,.}.
03a0: 0a 69 6d 70 6c 20 43 6f 72 65 20 7b 0a 09 70 75 .impl Core {..pu
03b0: 62 20 61 73 79 6e 63 20 66 6e 20 6e 65 77 28 73 b async fn new(s
03c0: 65 74 74 69 6e 67 73 3a 20 63 6f 6e 66 69 67 3a ettings: config:
03d0: 3a 43 6f 6e 66 69 67 29 20 2d 3e 20 52 65 73 75 :Config) -> Resu
03e0: 6c 74 3c 43 6f 72 65 3e 20 7b 0a 09 09 6c 65 74 lt<Core> {...let
03f0: 20 6f 77 6e 65 72 5f 63 68 61 74 20 3d 20 43 68 owner_chat = Ch
0400: 61 74 50 65 65 72 49 64 3a 3a 66 72 6f 6d 28 73 atPeerId::from(s
0410: 65 74 74 69 6e 67 73 2e 67 65 74 5f 69 6e 74 28 ettings.get_int(
0420: 22 6f 77 6e 65 72 22 29 3f 29 3b 0a 09 09 6c 65 "owner")?);...le
0430: 74 20 61 70 69 5f 6b 65 79 20 3d 20 73 65 74 74 t api_key = sett
0440: 69 6e 67 73 2e 67 65 74 5f 73 74 72 69 6e 67 28 ings.get_string(
0450: 22 61 70 69 5f 6b 65 79 22 29 3f 3b 0a 09 09 6c "api_key")?;...l
0460: 65 74 20 74 67 20 3d 20 43 6c 69 65 6e 74 3a 3a et tg = Client::
0470: 6e 65 77 28 26 61 70 69 5f 6b 65 79 29 3f 3b 0a new(&api_key)?;.
0480: 0a 09 09 6c 65 74 20 6d 75 74 20 63 6c 69 65 6e ...let mut clien
0490: 74 20 3d 20 72 65 71 77 65 73 74 3a 3a 43 6c 69 t = reqwest::Cli
04a0: 65 6e 74 3a 3a 62 75 69 6c 64 65 72 28 29 3b 0a ent::builder();.
04b0: 09 09 69 66 20 6c 65 74 20 4f 6b 28 70 72 6f 78 ..if let Ok(prox
04c0: 79 29 20 3d 20 73 65 74 74 69 6e 67 73 2e 67 65 y) = settings.ge
04d0: 74 5f 73 74 72 69 6e 67 28 22 70 72 6f 78 79 22 t_string("proxy"
04e0: 29 20 7b 0a 09 09 09 6c 65 74 20 70 72 6f 78 79 ) {....let proxy
04f0: 20 3d 20 72 65 71 77 65 73 74 3a 3a 50 72 6f 78 = reqwest::Prox
0500: 79 3a 3a 61 6c 6c 28 70 72 6f 78 79 29 3f 3b 0a y::all(proxy)?;.
0510: 09 09 09 63 6c 69 65 6e 74 20 3d 20 63 6c 69 65 ...client = clie
0520: 6e 74 2e 70 72 6f 78 79 28 70 72 6f 78 79 29 3b nt.proxy(proxy);
0530: 0a 09 09 7d 0a 09 09 6c 65 74 20 68 74 74 70 5f ...}...let http_
0540: 63 6c 69 65 6e 74 20 3d 20 63 6c 69 65 6e 74 2e client = client.
0550: 62 75 69 6c 64 28 29 3f 3b 0a 09 09 6c 65 74 20 build()?;...let
0560: 6d 65 20 3d 20 74 67 2e 65 78 65 63 75 74 65 28 me = tg.execute(
0570: 47 65 74 42 6f 74 29 2e 61 77 61 69 74 3f 3b 0a GetBot).await?;.
0580: 09 09 6c 65 74 20 63 6f 72 65 20 3d 20 43 6f 72 ..let core = Cor
0590: 65 20 7b 0a 09 09 09 74 67 2c 0a 09 09 09 6d 65 e {....tg,....me
05a0: 2c 0a 09 09 09 6f 77 6e 65 72 5f 63 68 61 74 2c ,....owner_chat,
05b0: 0a 09 09 09 64 62 3a 20 44 62 3a 3a 6e 65 77 28 ....db: Db::new(
05c0: 26 73 65 74 74 69 6e 67 73 2e 67 65 74 5f 73 74 &settings.get_st
05d0: 72 69 6e 67 28 22 70 67 22 29 3f 29 3f 2c 0a 09 ring("pg")?)?,..
05e0: 09 09 73 6f 75 72 63 65 73 3a 20 41 72 63 3a 3a ..sources: Arc::
05f0: 6e 65 77 28 4d 75 74 65 78 3a 3a 6e 65 77 28 48 new(Mutex::new(H
0600: 61 73 68 53 65 74 3a 3a 6e 65 77 28 29 29 29 2c ashSet::new())),
0610: 0a 09 09 09 68 74 74 70 5f 63 6c 69 65 6e 74 2c ....http_client,
0620: 0a 09 09 09 2f 2f 20 6d 61 78 5f 64 65 6c 61 79 ....// max_delay
0630: 3a 20 36 30 2c 0a 09 09 7d 3b 0a 09 09 6c 65 74 : 60,...};...let
0640: 20 63 6c 6f 6e 65 20 3d 20 63 6f 72 65 2e 63 6c clone = core.cl
0650: 6f 6e 65 28 29 3b 0a 09 09 74 61 73 6b 3a 3a 73 one();...task::s
0660: 70 61 77 6e 28 61 73 79 6e 63 20 6d 6f 76 65 20 pawn(async move
0670: 7b 0a 09 09 09 6c 6f 6f 70 20 7b 0a 09 09 09 09 {....loop {.....
0680: 6c 65 74 20 64 65 6c 61 79 20 3d 20 6d 61 74 63 let delay = matc
0690: 68 20 26 63 6c 6f 6e 65 2e 61 75 74 6f 66 65 74 h &clone.autofet
06a0: 63 68 28 29 2e 61 77 61 69 74 20 7b 0a 09 09 09 ch().await {....
06b0: 09 09 45 72 72 28 65 72 72 29 20 3d 3e 20 7b 0a ..Err(err) => {.
06c0: 09 09 09 09 09 09 69 66 20 6c 65 74 20 45 72 72 ......if let Err
06d0: 28 65 72 72 29 20 3d 20 63 6c 6f 6e 65 2e 73 65 (err) = clone.se
06e0: 6e 64 28 66 6f 72 6d 61 74 21 28 22 f0 9f 9b 91 nd(format!("š
06f0: 20 7b 65 72 72 3a 3f 7d 22 29 2c 20 4e 6f 6e 65 {err:?}"), None
0700: 2c 20 4e 6f 6e 65 29 2e 61 77 61 69 74 20 7b 0a , None).await {.
0710: 09 09 09 09 09 09 09 65 70 72 69 6e 74 6c 6e 21 .......eprintln!
0720: 28 22 41 75 74 6f 66 65 74 63 68 20 65 72 72 6f ("Autofetch erro
0730: 72 3a 20 7b 65 72 72 3a 3f 7d 22 29 3b 0a 09 09 r: {err:?}");...
0740: 09 09 09 09 7d 3b 0a 09 09 09 09 09 09 73 74 64 ....};.......std
0750: 3a 3a 74 69 6d 65 3a 3a 44 75 72 61 74 69 6f 6e ::time::Duration
0760: 3a 3a 66 72 6f 6d 5f 73 65 63 73 28 36 30 29 0a ::from_secs(60).
0770: 09 09 09 09 09 7d 2c 0a 09 09 09 09 09 4f 6b 28 .....},......Ok(
0780: 74 69 6d 65 29 20 3d 3e 20 2a 74 69 6d 65 2c 0a time) => *time,.
0790: 09 09 09 09 7d 3b 0a 09 09 09 09 74 61 73 6b 3a ....};.....task:
07a0: 3a 73 6c 65 65 70 28 64 65 6c 61 79 29 2e 61 77 :sleep(delay).aw
07b0: 61 69 74 3b 0a 09 09 09 7d 0a 09 09 7d 29 3b 0a ait;....}...});.
07c0: 09 09 4f 6b 28 63 6f 72 65 29 0a 09 7d 0a 0a 09 ..Ok(core)..}...
07d0: 70 75 62 20 61 73 79 6e 63 20 66 6e 20 73 65 6e pub async fn sen
07e0: 64 20 3c 53 3e 28 26 73 65 6c 66 2c 20 6d 73 67 d <S>(&self, msg
07f0: 3a 20 53 2c 20 74 61 72 67 65 74 3a 20 4f 70 74 : S, target: Opt
0800: 69 6f 6e 3c 43 68 61 74 50 65 65 72 49 64 3e 2c ion<ChatPeerId>,
0810: 20 6d 6f 64 65 3a 20 4f 70 74 69 6f 6e 3c 50 61 mode: Option<Pa
0820: 72 73 65 4d 6f 64 65 3e 29 20 2d 3e 20 52 65 73 rseMode>) -> Res
0830: 75 6c 74 3c 4d 65 73 73 61 67 65 3e 0a 09 77 68 ult<Message>..wh
0840: 65 72 65 20 53 3a 20 49 6e 74 6f 3c 53 74 72 69 ere S: Into<Stri
0850: 6e 67 3e 20 7b 0a 09 09 6c 65 74 20 6d 73 67 20 ng> {...let msg
0860: 3d 20 6d 73 67 2e 69 6e 74 6f 28 29 3b 0a 0a 09 = msg.into();...
0870: 09 6c 65 74 20 6d 6f 64 65 20 3d 20 6d 6f 64 65 .let mode = mode
0880: 2e 75 6e 77 72 61 70 5f 6f 72 28 50 61 72 73 65 .unwrap_or(Parse
0890: 4d 6f 64 65 3a 3a 48 74 6d 6c 29 3b 0a 09 09 6c Mode::Html);...l
08a0: 65 74 20 74 61 72 67 65 74 20 3d 20 74 61 72 67 et target = targ
08b0: 65 74 2e 75 6e 77 72 61 70 5f 6f 72 28 73 65 6c et.unwrap_or(sel
08c0: 66 2e 6f 77 6e 65 72 5f 63 68 61 74 29 3b 0a 09 f.owner_chat);..
08d0: 09 4f 6b 28 73 65 6c 66 2e 74 67 2e 65 78 65 63 .Ok(self.tg.exec
08e0: 75 74 65 28 0a 09 09 09 53 65 6e 64 4d 65 73 73 ute(....SendMess
08f0: 61 67 65 3a 3a 6e 65 77 28 74 61 72 67 65 74 2c age::new(target,
0900: 20 6d 73 67 29 0a 09 09 09 09 2e 77 69 74 68 5f msg)......with_
0910: 70 61 72 73 65 5f 6d 6f 64 65 28 6d 6f 64 65 29 parse_mode(mode)
0920: 0a 09 09 29 2e 61 77 61 69 74 3f 29 0a 09 7d 0a ...).await?)..}.
0930: 0a 09 70 75 62 20 61 73 79 6e 63 20 66 6e 20 63 ..pub async fn c
0940: 68 65 63 6b 20 28 26 73 65 6c 66 2c 20 69 64 3a heck (&self, id:
0950: 20 69 33 32 2c 20 72 65 61 6c 3a 20 62 6f 6f 6c i32, real: bool
0960: 29 20 2d 3e 20 52 65 73 75 6c 74 3c 53 74 72 69 ) -> Result<Stri
0970: 6e 67 3e 20 7b 0a 09 09 6c 65 74 20 6d 75 74 20 ng> {...let mut
0980: 70 6f 73 74 65 64 3a 20 69 33 32 20 3d 20 30 3b posted: i32 = 0;
0990: 0a 09 09 6c 65 74 20 6d 75 74 20 63 6f 6e 6e 20 ...let mut conn
09a0: 3d 20 73 65 6c 66 2e 64 62 2e 62 65 67 69 6e 28 = self.db.begin(
09b0: 29 2e 61 77 61 69 74 3f 3b 0a 0a 09 09 6c 65 74 ).await?;....let
09c0: 20 69 64 20 3d 20 7b 0a 09 09 09 6c 65 74 20 6d id = {....let m
09d0: 75 74 20 73 65 74 20 3d 20 73 65 6c 66 2e 73 6f ut set = self.so
09e0: 75 72 63 65 73 2e 6c 6f 63 6b 28 29 2e 75 6e 77 urces.lock().unw
09f0: 72 61 70 28 29 3b 0a 09 09 09 6d 61 74 63 68 20 rap();....match
0a00: 73 65 74 2e 67 65 74 28 26 69 64 29 20 7b 0a 09 set.get(&id) {..
0a10: 09 09 09 53 6f 6d 65 28 69 64 29 20 3d 3e 20 69 ...Some(id) => i
0a20: 64 2e 63 6c 6f 6e 65 28 29 2c 0a 09 09 09 09 4e d.clone(),.....N
0a30: 6f 6e 65 20 3d 3e 20 7b 0a 09 09 09 09 09 6c 65 one => {......le
0a40: 74 20 69 64 20 3d 20 41 72 63 3a 3a 6e 65 77 28 t id = Arc::new(
0a50: 69 64 29 3b 0a 09 09 09 09 09 73 65 74 2e 69 6e id);......set.in
0a60: 73 65 72 74 28 69 64 2e 63 6c 6f 6e 65 28 29 29 sert(id.clone())
0a70: 3b 0a 09 09 09 09 09 69 64 2e 63 6c 6f 6e 65 28 ;......id.clone(
0a80: 29 0a 09 09 09 09 7d 2c 0a 09 09 09 7d 0a 09 09 ).....},....}...
0a90: 7d 3b 0a 09 09 6c 65 74 20 63 6f 75 6e 74 20 3d };...let count =
0aa0: 20 41 72 63 3a 3a 73 74 72 6f 6e 67 5f 63 6f 75 Arc::strong_cou
0ab0: 6e 74 28 26 69 64 29 3b 0a 09 09 69 66 20 63 6f nt(&id);...if co
0ac0: 75 6e 74 20 3d 3d 20 32 20 7b 0a 09 09 09 6c 65 unt == 2 {....le
0ad0: 74 20 73 6f 75 72 63 65 20 3d 20 63 6f 6e 6e 2e t source = conn.
0ae0: 67 65 74 5f 73 6f 75 72 63 65 28 2a 69 64 2c 20 get_source(*id,
0af0: 73 65 6c 66 2e 6f 77 6e 65 72 5f 63 68 61 74 29 self.owner_chat)
0b00: 2e 61 77 61 69 74 3f 3b 0a 09 09 09 63 6f 6e 6e .await?;....conn
0b10: 2e 73 65 74 5f 73 63 72 61 70 65 28 2a 69 64 29 .set_scrape(*id)
0b20: 2e 61 77 61 69 74 3f 3b 0a 09 09 09 6c 65 74 20 .await?;....let
0b30: 64 65 73 74 69 6e 61 74 69 6f 6e 20 3d 20 43 68 destination = Ch
0b40: 61 74 50 65 65 72 49 64 3a 3a 66 72 6f 6d 28 6d atPeerId::from(m
0b50: 61 74 63 68 20 72 65 61 6c 20 7b 0a 09 09 09 09 atch real {.....
0b60: 74 72 75 65 20 3d 3e 20 73 6f 75 72 63 65 2e 63 true => source.c
0b70: 68 61 6e 6e 65 6c 5f 69 64 2c 0a 09 09 09 09 66 hannel_id,.....f
0b80: 61 6c 73 65 20 3d 3e 20 73 6f 75 72 63 65 2e 6f alse => source.o
0b90: 77 6e 65 72 2c 0a 09 09 09 7d 29 3b 0a 09 09 09 wner,....});....
0ba0: 6c 65 74 20 6d 75 74 20 74 68 69 73 5f 66 65 74 let mut this_fet
0bb0: 63 68 3a 20 4f 70 74 69 6f 6e 3c 44 61 74 65 54 ch: Option<DateT
0bc0: 69 6d 65 3c 63 68 72 6f 6e 6f 3a 3a 46 69 78 65 ime<chrono::Fixe
0bd0: 64 4f 66 66 73 65 74 3e 3e 20 3d 20 4e 6f 6e 65 dOffset>> = None
0be0: 3b 0a 09 09 09 6c 65 74 20 6d 75 74 20 70 6f 73 ;....let mut pos
0bf0: 74 73 3a 20 42 54 72 65 65 4d 61 70 3c 44 61 74 ts: BTreeMap<Dat
0c00: 65 54 69 6d 65 3c 63 68 72 6f 6e 6f 3a 3a 46 69 eTime<chrono::Fi
0c10: 78 65 64 4f 66 66 73 65 74 3e 2c 20 53 74 72 69 xedOffset>, Stri
0c20: 6e 67 3e 20 3d 20 42 54 72 65 65 4d 61 70 3a 3a ng> = BTreeMap::
0c30: 6e 65 77 28 29 3b 0a 0a 09 09 09 6c 65 74 20 72 new();.....let r
0c40: 65 73 70 6f 6e 73 65 20 3d 20 73 65 6c 66 2e 68 esponse = self.h
0c50: 74 74 70 5f 63 6c 69 65 6e 74 2e 67 65 74 28 26 ttp_client.get(&
0c60: 73 6f 75 72 63 65 2e 75 72 6c 29 2e 73 65 6e 64 source.url).send
0c70: 28 29 2e 61 77 61 69 74 3f 3b 0a 09 09 09 6c 65 ().await?;....le
0c80: 74 20 73 74 61 74 75 73 20 3d 20 72 65 73 70 6f t status = respo
0c90: 6e 73 65 2e 73 74 61 74 75 73 28 29 3b 0a 09 09 nse.status();...
0ca0: 09 6c 65 74 20 63 6f 6e 74 65 6e 74 20 3d 20 72 .let content = r
0cb0: 65 73 70 6f 6e 73 65 2e 62 79 74 65 73 28 29 2e esponse.bytes().
0cc0: 61 77 61 69 74 3f 3b 0a 09 09 09 6d 61 74 63 68 await?;....match
0cd0: 20 72 73 73 3a 3a 43 68 61 6e 6e 65 6c 3a 3a 72 rss::Channel::r
0ce0: 65 61 64 5f 66 72 6f 6d 28 26 63 6f 6e 74 65 6e ead_from(&conten
0cf0: 74 5b 2e 2e 5d 29 20 7b 0a 09 09 09 09 4f 6b 28 t[..]) {.....Ok(
0d00: 66 65 65 64 29 20 3d 3e 20 7b 0a 09 09 09 09 09 feed) => {......
0d10: 66 6f 72 20 69 74 65 6d 20 69 6e 20 66 65 65 64 for item in feed
0d20: 2e 69 74 65 6d 73 28 29 20 7b 0a 09 09 09 09 09 .items() {......
0d30: 09 69 66 20 6c 65 74 20 53 6f 6d 65 28 6c 69 6e .if let Some(lin
0d40: 6b 29 20 3d 20 69 74 65 6d 2e 6c 69 6e 6b 28 29 k) = item.link()
0d50: 20 7b 0a 09 09 09 09 09 09 09 6c 65 74 20 64 61 {........let da
0d60: 74 65 20 3d 20 6d 61 74 63 68 20 69 74 65 6d 2e te = match item.
0d70: 70 75 62 5f 64 61 74 65 28 29 20 7b 0a 09 09 09 pub_date() {....
0d80: 09 09 09 09 09 53 6f 6d 65 28 66 65 65 64 5f 64 .....Some(feed_d
0d90: 61 74 65 29 20 3d 3e 20 44 61 74 65 54 69 6d 65 ate) => DateTime
0da0: 3a 3a 70 61 72 73 65 5f 66 72 6f 6d 5f 72 66 63 ::parse_from_rfc
0db0: 32 38 32 32 28 66 65 65 64 5f 64 61 74 65 29 2c 2822(feed_date),
0dc0: 0a 09 09 09 09 09 09 09 09 4e 6f 6e 65 20 3d 3e .........None =>
0dd0: 20 44 61 74 65 54 69 6d 65 3a 3a 70 61 72 73 65 DateTime::parse
0de0: 5f 66 72 6f 6d 5f 72 66 63 33 33 33 39 28 26 69 _from_rfc3339(&i
0df0: 74 65 6d 2e 64 75 62 6c 69 6e 5f 63 6f 72 65 5f tem.dublin_core_
0e00: 65 78 74 28 29 2e 75 6e 77 72 61 70 28 29 2e 64 ext().unwrap().d
0e10: 61 74 65 73 28 29 5b 30 5d 29 2c 0a 09 09 09 09 ates()[0]),.....
0e20: 09 09 09 7d 3f 3b 0a 09 09 09 09 09 09 09 6c 65 ...}?;........le
0e30: 74 20 75 72 6c 20 3d 20 6c 69 6e 6b 3b 0a 09 09 t url = link;...
0e40: 09 09 09 09 09 70 6f 73 74 73 2e 69 6e 73 65 72 .....posts.inser
0e50: 74 28 64 61 74 65 2c 20 75 72 6c 2e 74 6f 5f 73 t(date, url.to_s
0e60: 74 72 69 6e 67 28 29 29 3b 0a 09 09 09 09 09 09 tring());.......
0e70: 7d 0a 09 09 09 09 09 7d 3b 0a 09 09 09 09 7d 2c }......};.....},
0e80: 0a 09 09 09 09 45 72 72 28 65 72 72 29 20 3d 3e .....Err(err) =>
0e90: 20 6d 61 74 63 68 20 65 72 72 20 7b 0a 09 09 09 match err {....
0ea0: 09 09 72 73 73 3a 3a 45 72 72 6f 72 3a 3a 49 6e ..rss::Error::In
0eb0: 76 61 6c 69 64 53 74 61 72 74 54 61 67 20 3d 3e validStartTag =>
0ec0: 20 7b 0a 09 09 09 09 09 09 6d 61 74 63 68 20 61 {.......match a
0ed0: 74 6f 6d 5f 73 79 6e 64 69 63 61 74 69 6f 6e 3a tom_syndication:
0ee0: 3a 46 65 65 64 3a 3a 72 65 61 64 5f 66 72 6f 6d :Feed::read_from
0ef0: 28 26 63 6f 6e 74 65 6e 74 5b 2e 2e 5d 29 20 7b (&content[..]) {
0f00: 0a 09 09 09 09 09 09 09 4f 6b 28 66 65 65 64 29 ........Ok(feed)
0f10: 20 3d 3e 20 7b 0a 09 09 09 09 09 09 09 09 66 6f => {.........fo
0f20: 72 20 69 74 65 6d 20 69 6e 20 66 65 65 64 2e 65 r item in feed.e
0f30: 6e 74 72 69 65 73 28 29 20 7b 0a 09 09 09 09 09 ntries() {......
0f40: 09 09 09 09 6c 65 74 20 64 61 74 65 20 3d 20 69 ....let date = i
0f50: 74 65 6d 2e 70 75 62 6c 69 73 68 65 64 28 29 2e tem.published().
0f60: 75 6e 77 72 61 70 28 29 3b 0a 09 09 09 09 09 09 unwrap();.......
0f70: 09 09 09 6c 65 74 20 75 72 6c 20 3d 20 69 74 65 ...let url = ite
0f80: 6d 2e 6c 69 6e 6b 73 28 29 5b 30 5d 2e 68 72 65 m.links()[0].hre
0f90: 66 28 29 3b 0a 09 09 09 09 09 09 09 09 09 70 6f f();..........po
0fa0: 73 74 73 2e 69 6e 73 65 72 74 28 2a 64 61 74 65 sts.insert(*date
0fb0: 2c 20 75 72 6c 2e 74 6f 5f 73 74 72 69 6e 67 28 , url.to_string(
0fc0: 29 29 3b 0a 09 09 09 09 09 09 09 09 7d 3b 0a 09 ));.........};..
0fd0: 09 09 09 09 09 09 7d 2c 0a 09 09 09 09 09 09 09 ......},........
0fe0: 45 72 72 28 65 72 72 29 20 3d 3e 20 7b 0a 09 09 Err(err) => {...
0ff0: 09 09 09 09 09 09 62 61 69 6c 21 28 22 55 6e 73 ......bail!("Uns
1000: 75 70 70 6f 72 74 65 64 20 6f 72 20 6d 61 6e 67 upported or mang
1010: 6c 65 64 20 63 6f 6e 74 65 6e 74 3a 5c 6e 7b 3a led content:\n{:
1020: 3f 7d 5c 6e 7b 65 72 72 3a 23 3f 7d 5c 6e 7b 73 ?}\n{err:#?}\n{s
1030: 74 61 74 75 73 3a 23 3f 7d 5c 6e 22 2c 20 26 73 tatus:#?}\n", &s
1040: 6f 75 72 63 65 2e 75 72 6c 29 0a 09 09 09 09 09 ource.url)......
1050: 09 09 7d 2c 0a 09 09 09 09 09 09 7d 0a 09 09 09 ..},.......}....
1060: 09 09 7d 2c 0a 09 09 09 09 09 72 73 73 3a 3a 45 ..},......rss::E
1070: 72 72 6f 72 3a 3a 45 6f 66 20 3d 3e 20 28 29 2c rror::Eof => (),
1080: 0a 09 09 09 09 09 5f 20 3d 3e 20 62 61 69 6c 21 ......_ => bail!
1090: 28 22 55 6e 73 75 70 70 6f 72 74 65 64 20 6f 72 ("Unsupported or
10a0: 20 6d 61 6e 67 6c 65 64 20 63 6f 6e 74 65 6e 74 mangled content
10b0: 3a 5c 6e 7b 3a 3f 7d 5c 6e 7b 65 72 72 3a 23 3f :\n{:?}\n{err:#?
10c0: 7d 5c 6e 7b 73 74 61 74 75 73 3a 23 3f 7d 5c 6e }\n{status:#?}\n
10d0: 22 2c 20 26 73 6f 75 72 63 65 2e 75 72 6c 29 0a ", &source.url).
10e0: 09 09 09 09 7d 0a 09 09 09 7d 3b 0a 09 09 09 66 ....}....};....f
10f0: 6f 72 20 28 64 61 74 65 2c 20 75 72 6c 29 20 69 or (date, url) i
1100: 6e 20 70 6f 73 74 73 2e 69 74 65 72 28 29 20 7b n posts.iter() {
1110: 0a 09 09 09 09 6c 65 74 20 70 6f 73 74 5f 75 72 .....let post_ur
1120: 6c 3a 20 43 6f 77 3c 73 74 72 3e 20 3d 20 6d 61 l: Cow<str> = ma
1130: 74 63 68 20 73 6f 75 72 63 65 2e 75 72 6c 5f 72 tch source.url_r
1140: 65 20 7b 0a 09 09 09 09 09 53 6f 6d 65 28 72 65 e {......Some(re
1150: 66 20 78 29 20 3d 3e 20 73 65 64 72 65 67 65 78 f x) => sedregex
1160: 3a 3a 52 65 70 6c 61 63 65 43 6f 6d 6d 61 6e 64 ::ReplaceCommand
1170: 3a 3a 6e 65 77 28 78 29 3f 2e 65 78 65 63 75 74 ::new(x)?.execut
1180: 65 28 75 72 6c 29 2c 0a 09 09 09 09 09 4e 6f 6e e(url),......Non
1190: 65 20 3d 3e 20 75 72 6c 2e 69 6e 74 6f 28 29 2c e => url.into(),
11a0: 0a 09 09 09 09 7d 3b 0a 09 09 09 09 69 66 20 6c .....};.....if l
11b0: 65 74 20 53 6f 6d 65 28 65 78 69 73 74 73 29 20 et Some(exists)
11c0: 3d 20 63 6f 6e 6e 2e 65 78 69 73 74 73 28 26 70 = conn.exists(&p
11d0: 6f 73 74 5f 75 72 6c 2c 20 2a 69 64 29 2e 61 77 ost_url, *id).aw
11e0: 61 69 74 3f 20 7b 0a 09 09 09 09 09 69 66 20 21 ait? {......if !
11f0: 20 65 78 69 73 74 73 20 7b 0a 09 09 09 09 09 09 exists {.......
1200: 69 66 20 74 68 69 73 5f 66 65 74 63 68 2e 69 73 if this_fetch.is
1210: 5f 6e 6f 6e 65 28 29 20 7c 7c 20 2a 64 61 74 65 _none() || *date
1220: 20 3e 20 74 68 69 73 5f 66 65 74 63 68 2e 75 6e > this_fetch.un
1230: 77 72 61 70 28 29 20 7b 0a 09 09 09 09 09 09 09 wrap() {........
1240: 74 68 69 73 5f 66 65 74 63 68 20 3d 20 53 6f 6d this_fetch = Som
1250: 65 28 2a 64 61 74 65 29 3b 0a 09 09 09 09 09 09 e(*date);.......
1260: 7d 3b 0a 09 09 09 09 09 09 73 65 6c 66 2e 73 65 };.......self.se
1270: 6e 64 28 20 6d 61 74 63 68 20 26 73 6f 75 72 63 nd( match &sourc
1280: 65 2e 69 76 5f 68 61 73 68 20 7b 0a 09 09 09 09 e.iv_hash {.....
1290: 09 09 09 53 6f 6d 65 28 68 61 73 68 29 20 3d 3e ...Some(hash) =>
12a0: 20 66 6f 72 6d 61 74 21 28 22 3c 61 20 68 72 65 format!("<a hre
12b0: 66 3d 5c 22 68 74 74 70 73 3a 2f 2f 74 2e 6d 65 f=\"https://t.me
12c0: 2f 69 76 3f 75 72 6c 3d 7b 70 6f 73 74 5f 75 72 /iv?url={post_ur
12d0: 6c 7d 26 72 68 61 73 68 3d 7b 68 61 73 68 7d 5c l}&rhash={hash}\
12e0: 22 3e 20 3c 2f 61 3e 7b 70 6f 73 74 5f 75 72 6c "> </a>{post_url
12f0: 7d 22 29 2c 0a 09 09 09 09 09 09 09 4e 6f 6e 65 }"),........None
1300: 20 3d 3e 20 66 6f 72 6d 61 74 21 28 22 7b 70 6f => format!("{po
1310: 73 74 5f 75 72 6c 7d 22 29 2c 0a 09 09 09 09 09 st_url}"),......
1320: 09 7d 2c 20 53 6f 6d 65 28 64 65 73 74 69 6e 61 .}, Some(destina
1330: 74 69 6f 6e 29 2c 20 53 6f 6d 65 28 50 61 72 73 tion), Some(Pars
1340: 65 4d 6f 64 65 3a 3a 48 74 6d 6c 29 29 2e 61 77 eMode::Html)).aw
1350: 61 69 74 3f 3b 0a 09 09 09 09 09 09 63 6f 6e 6e ait?;.......conn
1360: 2e 61 64 64 5f 70 6f 73 74 28 2a 69 64 2c 20 64 .add_post(*id, d
1370: 61 74 65 2c 20 26 70 6f 73 74 5f 75 72 6c 29 2e ate, &post_url).
1380: 61 77 61 69 74 3f 3b 0a 09 09 09 09 09 7d 3b 0a await?;......};.
1390: 09 09 09 09 7d 3b 0a 09 09 09 09 70 6f 73 74 65 ....};.....poste
13a0: 64 20 2b 3d 20 31 3b 0a 09 09 09 7d 3b 0a 09 09 d += 1;....};...
13b0: 09 70 6f 73 74 73 2e 63 6c 65 61 72 28 29 3b 0a .posts.clear();.
13c0: 09 09 7d 3b 0a 09 09 4f 6b 28 66 6f 72 6d 61 74 ..};...Ok(format
13d0: 21 28 22 50 6f 73 74 65 64 3a 20 7b 70 6f 73 74 !("Posted: {post
13e0: 65 64 7d 22 29 29 0a 09 7d 0a 0a 09 61 73 79 6e ed}"))..}...asyn
13f0: 63 20 66 6e 20 61 75 74 6f 66 65 74 63 68 28 26 c fn autofetch(&
1400: 73 65 6c 66 29 20 2d 3e 20 52 65 73 75 6c 74 3c self) -> Result<
1410: 73 74 64 3a 3a 74 69 6d 65 3a 3a 44 75 72 61 74 std::time::Durat
1420: 69 6f 6e 3e 20 7b 0a 09 09 6c 65 74 20 6d 75 74 ion> {...let mut
1430: 20 64 65 6c 61 79 20 3d 20 63 68 72 6f 6e 6f 3a delay = chrono:
1440: 3a 44 75 72 61 74 69 6f 6e 3a 3a 6d 69 6e 75 74 :Duration::minut
1450: 65 73 28 31 29 3b 0a 09 09 6c 65 74 20 6e 6f 77 es(1);...let now
1460: 20 3d 20 63 68 72 6f 6e 6f 3a 3a 4c 6f 63 61 6c = chrono::Local
1470: 3a 3a 6e 6f 77 28 29 3b 0a 09 09 6c 65 74 20 71 ::now();...let q
1480: 75 65 75 65 20 3d 20 7b 0a 09 09 09 6c 65 74 20 ueue = {....let
1490: 6d 75 74 20 63 6f 6e 6e 20 3d 20 73 65 6c 66 2e mut conn = self.
14a0: 64 62 2e 62 65 67 69 6e 28 29 2e 61 77 61 69 74 db.begin().await
14b0: 3f 3b 0a 09 09 09 63 6f 6e 6e 2e 67 65 74 5f 71 ?;....conn.get_q
14c0: 75 65 75 65 28 29 2e 61 77 61 69 74 3f 0a 09 09 ueue().await?...
14d0: 7d 3b 0a 09 09 66 6f 72 20 72 6f 77 20 69 6e 20 };...for row in
14e0: 71 75 65 75 65 20 7b 0a 09 09 09 69 66 20 6c 65 queue {....if le
14f0: 74 20 53 6f 6d 65 28 6e 65 78 74 5f 66 65 74 63 t Some(next_fetc
1500: 68 29 20 3d 20 72 6f 77 2e 6e 65 78 74 5f 66 65 h) = row.next_fe
1510: 74 63 68 20 7b 0a 09 09 09 09 69 66 20 6e 65 78 tch {.....if nex
1520: 74 5f 66 65 74 63 68 20 3c 20 6e 6f 77 20 7b 0a t_fetch < now {.
1530: 09 09 09 09 09 69 66 20 6c 65 74 20 28 53 6f 6d .....if let (Som
1540: 65 28 6f 77 6e 65 72 29 2c 20 53 6f 6d 65 28 73 e(owner), Some(s
1550: 6f 75 72 63 65 5f 69 64 29 29 20 3d 20 28 72 6f ource_id)) = (ro
1560: 77 2e 6f 77 6e 65 72 2c 20 72 6f 77 2e 73 6f 75 w.owner, row.sou
1570: 72 63 65 5f 69 64 29 20 7b 0a 09 09 09 09 09 09 rce_id) {.......
1580: 6c 65 74 20 63 6c 6f 6e 65 20 3d 20 43 6f 72 65 let clone = Core
1590: 20 7b 0a 09 09 09 09 09 09 09 6f 77 6e 65 72 5f {........owner_
15a0: 63 68 61 74 3a 20 43 68 61 74 50 65 65 72 49 64 chat: ChatPeerId
15b0: 3a 3a 66 72 6f 6d 28 6f 77 6e 65 72 29 2c 0a 09 ::from(owner),..
15c0: 09 09 09 09 09 09 2e 2e 73 65 6c 66 2e 63 6c 6f ........self.clo
15d0: 6e 65 28 29 0a 09 09 09 09 09 09 7d 3b 0a 09 09 ne().......};...
15e0: 09 09 09 09 6c 65 74 20 73 6f 75 72 63 65 20 3d ....let source =
15f0: 20 7b 0a 09 09 09 09 09 09 09 6c 65 74 20 6d 75 {........let mu
1600: 74 20 63 6f 6e 6e 20 3d 20 73 65 6c 66 2e 64 62 t conn = self.db
1610: 2e 62 65 67 69 6e 28 29 2e 61 77 61 69 74 3f 3b .begin().await?;
1620: 0a 09 09 09 09 09 09 09 6d 61 74 63 68 20 63 6f ........match co
1630: 6e 6e 2e 67 65 74 5f 6f 6e 65 28 6f 77 6e 65 72 nn.get_one(owner
1640: 2c 20 73 6f 75 72 63 65 5f 69 64 29 2e 61 77 61 , source_id).awa
1650: 69 74 20 7b 0a 09 09 09 09 09 09 09 09 4f 6b 28 it {.........Ok(
1660: 53 6f 6d 65 28 73 6f 75 72 63 65 29 29 20 3d 3e Some(source)) =>
1670: 20 73 6f 75 72 63 65 2e 74 6f 5f 73 74 72 69 6e source.to_strin
1680: 67 28 29 2c 0a 09 09 09 09 09 09 09 09 4f 6b 28 g(),.........Ok(
1690: 4e 6f 6e 65 29 20 3d 3e 20 22 53 6f 75 72 63 65 None) => "Source
16a0: 20 6e 6f 74 20 66 6f 75 6e 64 20 69 6e 20 64 61 not found in da
16b0: 74 61 62 61 73 65 3f 22 2e 74 6f 5f 73 74 72 69 tabase?".to_stri
16c0: 6e 67 28 29 2c 0a 09 09 09 09 09 09 09 09 45 72 ng(),.........Er
16d0: 72 28 65 72 72 29 20 3d 3e 20 66 6f 72 6d 61 74 r(err) => format
16e0: 21 28 22 46 61 69 6c 65 64 20 74 6f 20 66 65 74 !("Failed to fet
16f0: 63 68 20 73 6f 75 72 63 65 20 64 61 74 61 3a 5c ch source data:\
1700: 6e 7b 65 72 72 7d 22 29 2c 0a 09 09 09 09 09 09 n{err}"),.......
1710: 09 7d 0a 09 09 09 09 09 09 7d 3b 0a 09 09 09 09 .}.......};.....
1720: 09 09 74 61 73 6b 3a 3a 73 70 61 77 6e 28 61 73 ..task::spawn(as
1730: 79 6e 63 20 6d 6f 76 65 20 7b 0a 09 09 09 09 09 ync move {......
1740: 09 09 69 66 20 6c 65 74 20 45 72 72 28 65 72 72 ..if let Err(err
1750: 29 20 3d 20 63 6c 6f 6e 65 2e 63 68 65 63 6b 28 ) = clone.check(
1760: 73 6f 75 72 63 65 5f 69 64 2c 20 74 72 75 65 29 source_id, true)
1770: 2e 61 77 61 69 74 20 7b 0a 09 09 09 09 09 09 09 .await {........
1780: 09 69 66 20 6c 65 74 20 45 72 72 28 65 72 72 29 .if let Err(err)
1790: 20 3d 20 63 6c 6f 6e 65 2e 73 65 6e 64 28 26 66 = clone.send(&f
17a0: 6f 72 6d 61 74 21 28 22 7b 73 6f 75 72 63 65 7d ormat!("{source}
17b0: 5c 6e f0 9f 9b 91 20 7b 7d 22 2c 20 65 6e 63 6f \nš {}", enco
17c0: 64 65 28 26 65 72 72 2e 74 6f 5f 73 74 72 69 6e de(&err.to_strin
17d0: 67 28 29 29 29 2c 20 4e 6f 6e 65 2c 20 53 6f 6d g())), None, Som
17e0: 65 28 50 61 72 73 65 4d 6f 64 65 3a 3a 4d 61 72 e(ParseMode::Mar
17f0: 6b 64 6f 77 6e 56 32 29 29 2e 61 77 61 69 74 20 kdownV2)).await
1800: 7b 0a 09 09 09 09 09 09 09 09 09 65 70 72 69 6e {..........eprin
1810: 74 6c 6e 21 28 22 43 68 65 63 6b 20 65 72 72 6f tln!("Check erro
1820: 72 3a 20 7b 65 72 72 3a 3f 7d 22 29 3b 0a 09 09 r: {err:?}");...
1830: 09 09 09 09 09 09 09 2f 2f 20 63 6c 6f 6e 65 2e .......// clone.
1840: 64 69 73 61 62 6c 65 28 26 73 6f 75 72 63 65 5f disable(&source_
1850: 69 64 2c 20 6f 77 6e 65 72 29 2e 61 77 61 69 74 id, owner).await
1860: 2e 75 6e 77 72 61 70 28 29 3b 0a 09 09 09 09 09 .unwrap();......
1870: 09 09 09 7d 3b 0a 09 09 09 09 09 09 09 7d 3b 0a ...};........};.
1880: 09 09 09 09 09 09 7d 29 3b 0a 09 09 09 09 09 7d ......});......}
1890: 0a 09 09 09 09 7d 20 65 6c 73 65 20 69 66 20 6e .....} else if n
18a0: 65 78 74 5f 66 65 74 63 68 20 2d 20 6e 6f 77 20 ext_fetch - now
18b0: 3c 20 64 65 6c 61 79 20 7b 0a 09 09 09 09 09 64 < delay {......d
18c0: 65 6c 61 79 20 3d 20 6e 65 78 74 5f 66 65 74 63 elay = next_fetc
18d0: 68 20 2d 20 6e 6f 77 3b 0a 09 09 09 09 7d 0a 09 h - now;.....}..
18e0: 09 09 7d 0a 09 09 7d 3b 0a 09 09 4f 6b 28 64 65 ..}...};...Ok(de
18f0: 6c 61 79 2e 74 6f 5f 73 74 64 28 29 3f 29 0a 09 lay.to_std()?)..
1900: 7d 0a 0a 09 70 75 62 20 61 73 79 6e 63 20 66 6e }...pub async fn
1910: 20 6c 69 73 74 20 28 26 73 65 6c 66 2c 20 6f 77 list (&self, ow
1920: 6e 65 72 3a 20 55 73 65 72 50 65 65 72 49 64 29 ner: UserPeerId)
1930: 20 2d 3e 20 52 65 73 75 6c 74 3c 53 74 72 69 6e -> Result<Strin
1940: 67 3e 20 7b 0a 09 09 6c 65 74 20 6d 75 74 20 72 g> {...let mut r
1950: 65 70 6c 79 3a 20 56 65 63 3c 53 74 72 69 6e 67 eply: Vec<String
1960: 3e 20 3d 20 76 65 63 21 5b 5d 3b 0a 09 09 72 65 > = vec![];...re
1970: 70 6c 79 2e 70 75 73 68 28 22 43 68 61 6e 6e 65 ply.push("Channe
1980: 6c 73 3a 22 2e 69 6e 74 6f 28 29 29 3b 0a 09 09 ls:".into());...
1990: 6c 65 74 20 6d 75 74 20 63 6f 6e 6e 20 3d 20 73 let mut conn = s
19a0: 65 6c 66 2e 64 62 2e 62 65 67 69 6e 28 29 2e 61 elf.db.begin().a
19b0: 77 61 69 74 3f 3b 0a 09 09 66 6f 72 20 72 6f 77 wait?;...for row
19c0: 20 69 6e 20 63 6f 6e 6e 2e 67 65 74 5f 6c 69 73 in conn.get_lis
19d0: 74 28 6f 77 6e 65 72 29 2e 61 77 61 69 74 3f 20 t(owner).await?
19e0: 7b 0a 09 09 09 72 65 70 6c 79 2e 70 75 73 68 28 {....reply.push(
19f0: 72 6f 77 2e 74 6f 5f 73 74 72 69 6e 67 28 29 29 row.to_string())
1a00: 3b 0a 09 09 7d 3b 0a 09 09 4f 6b 28 72 65 70 6c ;...};...Ok(repl
1a10: 79 2e 6a 6f 69 6e 28 22 5c 6e 5c 6e 22 29 29 0a y.join("\n\n")).
1a20: 09 7d 0a 7d 0a 0a 69 6d 70 6c 20 55 70 64 61 74 .}.}..impl Updat
1a30: 65 48 61 6e 64 6c 65 72 20 66 6f 72 20 43 6f 72 eHandler for Cor
1a40: 65 20 7b 0a 09 61 73 79 6e 63 20 66 6e 20 68 61 e {..async fn ha
1a50: 6e 64 6c 65 20 28 26 73 65 6c 66 2c 20 75 70 64 ndle (&self, upd
1a60: 61 74 65 3a 20 55 70 64 61 74 65 29 20 7b 0a 09 ate: Update) {..
1a70: 09 69 66 20 6c 65 74 20 55 70 64 61 74 65 54 79 .if let UpdateTy
1a80: 70 65 3a 3a 4d 65 73 73 61 67 65 28 6d 73 67 29 pe::Message(msg)
1a90: 20 3d 20 75 70 64 61 74 65 2e 75 70 64 61 74 65 = update.update
1aa0: 5f 74 79 70 65 20 7b 0a 09 09 09 69 66 20 6c 65 _type {....if le
1ab0: 74 20 4f 6b 28 63 6d 64 29 20 3d 20 43 6f 6d 6d t Ok(cmd) = Comm
1ac0: 61 6e 64 3a 3a 74 72 79 5f 66 72 6f 6d 28 6d 73 and::try_from(ms
1ad0: 67 29 20 7b 0a 09 09 09 09 6c 65 74 20 6d 73 67 g) {.....let msg
1ae0: 20 3d 20 63 6d 64 2e 67 65 74 5f 6d 65 73 73 61 = cmd.get_messa
1af0: 67 65 28 29 3b 0a 09 09 09 09 6c 65 74 20 77 6f ge();.....let wo
1b00: 72 64 73 20 3d 20 63 6d 64 2e 67 65 74 5f 61 72 rds = cmd.get_ar
1b10: 67 73 28 29 3b 0a 09 09 09 09 6c 65 74 20 63 6f gs();.....let co
1b20: 6d 6d 61 6e 64 20 3d 20 63 6d 64 2e 67 65 74 5f mmand = cmd.get_
1b30: 6e 61 6d 65 28 29 3b 0a 09 09 09 09 6c 65 74 20 name();.....let
1b40: 72 65 73 20 3d 20 6d 61 74 63 68 20 63 6f 6d 6d res = match comm
1b50: 61 6e 64 20 7b 0a 09 09 09 09 09 22 2f 63 68 65 and {......"/che
1b60: 63 6b 22 20 7c 20 22 2f 63 6c 65 61 6e 22 20 7c ck" | "/clean" |
1b70: 20 22 2f 65 6e 61 62 6c 65 22 20 7c 20 22 2f 64 "/enable" | "/d
1b80: 65 6c 65 74 65 22 20 7c 20 22 2f 64 69 73 61 62 elete" | "/disab
1b90: 6c 65 22 20 3d 3e 20 63 6f 6d 6d 61 6e 64 3a 3a le" => command::
1ba0: 63 6f 6d 6d 61 6e 64 28 73 65 6c 66 2c 20 63 6f command(self, co
1bb0: 6d 6d 61 6e 64 2c 20 6d 73 67 2c 20 77 6f 72 64 mmand, msg, word
1bc0: 73 29 2e 61 77 61 69 74 2c 0a 09 09 09 09 09 22 s).await,......"
1bd0: 2f 73 74 61 72 74 22 20 3d 3e 20 63 6f 6d 6d 61 /start" => comma
1be0: 6e 64 3a 3a 73 74 61 72 74 28 73 65 6c 66 2c 20 nd::start(self,
1bf0: 6d 73 67 29 2e 61 77 61 69 74 2c 0a 09 09 09 09 msg).await,.....
1c00: 09 22 2f 6c 69 73 74 22 20 3d 3e 20 63 6f 6d 6d ."/list" => comm
1c10: 61 6e 64 3a 3a 6c 69 73 74 28 73 65 6c 66 2c 20 and::list(self,
1c20: 6d 73 67 29 2e 61 77 61 69 74 2c 0a 09 09 09 09 msg).await,.....
1c30: 09 22 2f 61 64 64 22 20 7c 20 22 2f 75 70 64 61 ."/add" | "/upda
1c40: 74 65 22 20 3d 3e 20 63 6f 6d 6d 61 6e 64 3a 3a te" => command::
1c50: 75 70 64 61 74 65 28 73 65 6c 66 2c 20 63 6f 6d update(self, com
1c60: 6d 61 6e 64 2c 20 6d 73 67 2c 20 77 6f 72 64 73 mand, msg, words
1c70: 29 2e 61 77 61 69 74 2c 0a 09 09 09 09 09 61 6e ).await,......an
1c80: 79 20 3d 3e 20 45 72 72 28 61 6e 79 68 6f 77 21 y => Err(anyhow!
1c90: 28 22 55 6e 6b 6e 6f 77 6e 20 63 6f 6d 6d 61 6e ("Unknown comman
1ca0: 64 3a 20 7b 61 6e 79 7d 22 29 29 2c 0a 09 09 09 d: {any}")),....
1cb0: 09 7d 3b 0a 09 09 09 09 69 66 20 6c 65 74 20 45 .};.....if let E
1cc0: 72 72 28 65 72 72 29 20 3d 20 72 65 73 20 7b 0a rr(err) = res {.
1cd0: 09 09 09 09 09 69 66 20 6c 65 74 20 45 72 72 28 .....if let Err(
1ce0: 65 72 72 32 29 20 3d 20 73 65 6c 66 2e 73 65 6e err2) = self.sen
1cf0: 64 28 66 6f 72 6d 61 74 21 28 22 5c 5c 23 65 72 d(format!("\\#er
1d00: 72 6f 72 5c 6e 60 60 60 5c 6e 7b 65 72 72 3a 3f ror\n```\n{err:?
1d10: 7d 5c 6e 60 60 60 22 29 2c 0a 09 09 09 09 09 09 }\n```"),.......
1d20: 53 6f 6d 65 28 6d 73 67 2e 63 68 61 74 2e 67 65 Some(msg.chat.ge
1d30: 74 5f 69 64 28 29 29 2c 0a 09 09 09 09 09 09 53 t_id()),.......S
1d40: 6f 6d 65 28 50 61 72 73 65 4d 6f 64 65 3a 3a 4d ome(ParseMode::M
1d50: 61 72 6b 64 6f 77 6e 56 32 29 0a 09 09 09 09 09 arkdownV2)......
1d60: 29 2e 61 77 61 69 74 7b 0a 09 09 09 09 09 09 64 ).await{.......d
1d70: 62 67 21 28 65 72 72 32 29 3b 0a 09 09 09 09 09 bg!(err2);......
1d80: 7d 3b 0a 09 09 09 09 7d 0a 09 09 09 7d 3b 0a 09 };.....}....};..
1d90: 09 7d 3b 0a 09 7d 0a 7d 0a .};..}.}.