0000: 75 73 65 20 61 6e 79 68 6f 77 3a 3a 7b 61 6e 79 use anyhow::{any
0010: 68 6f 77 2c 20 62 61 69 6c 2c 20 43 6f 6e 74 65 how, bail, Conte
0020: 78 74 2c 20 52 65 73 75 6c 74 7d 3b 0a 75 73 65 xt, Result};.use
0030: 20 61 73 79 6e 63 5f 73 74 64 3a 3a 74 61 73 6b async_std::task
0040: 3b 0a 75 73 65 20 63 68 72 6f 6e 6f 3a 3a 44 61 ;.use chrono::Da
0050: 74 65 54 69 6d 65 3b 0a 75 73 65 20 6c 61 7a 79 teTime;.use lazy
0060: 5f 73 74 61 74 69 63 3a 3a 6c 61 7a 79 5f 73 74 _static::lazy_st
0070: 61 74 69 63 3b 0a 75 73 65 20 72 65 67 65 78 3a atic;.use regex:
0080: 3a 52 65 67 65 78 3b 0a 75 73 65 20 73 71 6c 78 :Regex;.use sqlx
0090: 3a 3a 70 6f 73 74 67 72 65 73 3a 3a 50 67 50 6f ::postgres::PgPo
00a0: 6f 6c 4f 70 74 69 6f 6e 73 3b 0a 75 73 65 20 73 olOptions;.use s
00b0: 74 64 3a 3a 7b 0a 09 62 6f 72 72 6f 77 3a 3a 43 td::{..borrow::C
00c0: 6f 77 2c 0a 09 63 6f 6c 6c 65 63 74 69 6f 6e 73 ow,..collections
00d0: 3a 3a 7b 0a 09 09 42 54 72 65 65 4d 61 70 2c 0a ::{...BTreeMap,.
00e0: 09 09 48 61 73 68 53 65 74 2c 0a 09 7d 2c 0a 09 ..HashSet,..},..
00f0: 73 79 6e 63 3a 3a 7b 41 72 63 2c 20 4d 75 74 65 sync::{Arc, Mute
0100: 78 7d 2c 0a 7d 3b 0a 0a 6c 61 7a 79 5f 73 74 61 x},.};..lazy_sta
0110: 74 69 63 21 20 7b 0a 09 73 74 61 74 69 63 20 72 tic! {..static r
0120: 65 66 20 52 45 5f 44 45 4c 41 59 3a 20 52 65 67 ef RE_DELAY: Reg
0130: 65 78 20 3d 20 52 65 67 65 78 3a 3a 6e 65 77 28 ex = Regex::new(
0140: 72 22 5e 54 6f 6f 20 4d 61 6e 79 20 52 65 71 75 r"^Too Many Requ
0150: 65 73 74 73 3a 20 72 65 74 72 79 20 61 66 74 65 ests: retry afte
0160: 72 20 28 5b 30 2d 39 5d 2b 29 28 2c 2e 2a 29 3f r ([0-9]+)(,.*)?
0170: 24 22 29 2e 75 6e 77 72 61 70 28 29 3b 0a 7d 0a $").unwrap();.}.
0180: 0a 23 5b 64 65 72 69 76 65 28 43 6c 6f 6e 65 29 .#[derive(Clone)
0190: 5d 0a 70 75 62 20 73 74 72 75 63 74 20 43 6f 72 ].pub struct Cor
01a0: 65 20 7b 0a 09 6f 77 6e 65 72 5f 63 68 61 74 3a e {..owner_chat:
01b0: 20 74 65 6c 65 67 72 61 6d 5f 62 6f 74 3a 3a 55 telegram_bot::U
01c0: 73 65 72 49 64 2c 0a 09 70 75 62 20 74 67 3a 20 serId,..pub tg:
01d0: 74 65 6c 65 67 72 61 6d 5f 62 6f 74 3a 3a 41 70 telegram_bot::Ap
01e0: 69 2c 0a 09 70 75 62 20 6d 79 3a 20 74 65 6c 65 i,..pub my: tele
01f0: 67 72 61 6d 5f 62 6f 74 3a 3a 55 73 65 72 2c 0a gram_bot::User,.
0200: 09 70 6f 6f 6c 3a 20 73 71 6c 78 3a 3a 50 6f 6f .pool: sqlx::Poo
0210: 6c 3c 73 71 6c 78 3a 3a 50 6f 73 74 67 72 65 73 l<sqlx::Postgres
0220: 3e 2c 0a 09 73 6f 75 72 63 65 73 3a 20 41 72 63 >,..sources: Arc
0230: 3c 4d 75 74 65 78 3c 48 61 73 68 53 65 74 3c 41 <Mutex<HashSet<A
0240: 72 63 3c 69 33 32 3e 3e 3e 3e 2c 0a 09 68 74 74 rc<i32>>>>,..htt
0250: 70 5f 63 6c 69 65 6e 74 3a 20 72 65 71 77 65 73 p_client: reqwes
0260: 74 3a 3a 43 6c 69 65 6e 74 2c 0a 7d 0a 0a 69 6d t::Client,.}..im
0270: 70 6c 20 43 6f 72 65 20 7b 0a 09 70 75 62 20 66 pl Core {..pub f
0280: 6e 20 6e 65 77 28 73 65 74 74 69 6e 67 73 3a 20 n new(settings:
0290: 63 6f 6e 66 69 67 3a 3a 43 6f 6e 66 69 67 29 20 config::Config)
02a0: 2d 3e 20 52 65 73 75 6c 74 3c 41 72 63 3c 43 6f -> Result<Arc<Co
02b0: 72 65 3e 3e 20 7b 0a 09 09 6c 65 74 20 6f 77 6e re>> {...let own
02c0: 65 72 20 3d 20 73 65 74 74 69 6e 67 73 2e 67 65 er = settings.ge
02d0: 74 5f 69 6e 74 28 22 6f 77 6e 65 72 22 29 3f 3b t_int("owner")?;
02e0: 0a 09 09 6c 65 74 20 61 70 69 5f 6b 65 79 20 3d ...let api_key =
02f0: 20 73 65 74 74 69 6e 67 73 2e 67 65 74 5f 73 74 settings.get_st
0300: 72 69 6e 67 28 22 61 70 69 5f 6b 65 79 22 29 3f ring("api_key")?
0310: 3b 0a 09 09 6c 65 74 20 74 67 20 3d 20 74 65 6c ;...let tg = tel
0320: 65 67 72 61 6d 5f 62 6f 74 3a 3a 41 70 69 3a 3a egram_bot::Api::
0330: 6e 65 77 28 61 70 69 5f 6b 65 79 29 3b 0a 09 09 new(api_key);...
0340: 6c 65 74 20 74 67 5f 63 6c 6f 6e 65 64 20 3d 20 let tg_cloned =
0350: 74 67 2e 63 6c 6f 6e 65 28 29 3b 0a 0a 09 09 6c tg.clone();....l
0360: 65 74 20 6d 75 74 20 63 6c 69 65 6e 74 20 3d 20 et mut client =
0370: 72 65 71 77 65 73 74 3a 3a 43 6c 69 65 6e 74 3a reqwest::Client:
0380: 3a 62 75 69 6c 64 65 72 28 29 3b 0a 09 09 69 66 :builder();...if
0390: 20 6c 65 74 20 4f 6b 28 70 72 6f 78 79 29 20 3d let Ok(proxy) =
03a0: 20 73 65 74 74 69 6e 67 73 2e 67 65 74 5f 73 74 settings.get_st
03b0: 72 69 6e 67 28 22 70 72 6f 78 79 22 29 20 7b 0a ring("proxy") {.
03c0: 09 09 09 6c 65 74 20 70 72 6f 78 79 20 3d 20 72 ...let proxy = r
03d0: 65 71 77 65 73 74 3a 3a 50 72 6f 78 79 3a 3a 61 eqwest::Proxy::a
03e0: 6c 6c 28 70 72 6f 78 79 29 3f 3b 0a 09 09 09 63 ll(proxy)?;....c
03f0: 6c 69 65 6e 74 20 3d 20 63 6c 69 65 6e 74 2e 70 lient = client.p
0400: 72 6f 78 79 28 70 72 6f 78 79 29 3b 0a 09 09 7d roxy(proxy);...}
0410: 0a 09 09 6c 65 74 20 68 74 74 70 5f 63 6c 69 65 ...let http_clie
0420: 6e 74 20 3d 20 63 6c 69 65 6e 74 2e 62 75 69 6c nt = client.buil
0430: 64 28 29 3f 3b 0a 09 09 6c 65 74 20 63 6f 72 65 d()?;...let core
0440: 20 3d 20 41 72 63 3a 3a 6e 65 77 28 43 6f 72 65 = Arc::new(Core
0450: 20 7b 0a 09 09 09 74 67 2c 0a 09 09 09 6d 79 3a {....tg,....my:
0460: 20 74 61 73 6b 3a 3a 62 6c 6f 63 6b 5f 6f 6e 28 task::block_on(
0470: 61 73 79 6e 63 20 7b 0a 09 09 09 09 74 67 5f 63 async {.....tg_c
0480: 6c 6f 6e 65 64 2e 73 65 6e 64 28 74 65 6c 65 67 loned.send(teleg
0490: 72 61 6d 5f 62 6f 74 3a 3a 47 65 74 4d 65 29 2e ram_bot::GetMe).
04a0: 61 77 61 69 74 0a 09 09 09 7d 29 3f 2c 0a 09 09 await....})?,...
04b0: 09 6f 77 6e 65 72 5f 63 68 61 74 3a 20 74 65 6c .owner_chat: tel
04c0: 65 67 72 61 6d 5f 62 6f 74 3a 3a 55 73 65 72 49 egram_bot::UserI
04d0: 64 3a 3a 6e 65 77 28 6f 77 6e 65 72 29 2c 0a 09 d::new(owner),..
04e0: 09 09 70 6f 6f 6c 3a 20 50 67 50 6f 6f 6c 4f 70 ..pool: PgPoolOp
04f0: 74 69 6f 6e 73 3a 3a 6e 65 77 28 29 0a 09 09 09 tions::new()....
0500: 09 2e 6d 61 78 5f 63 6f 6e 6e 65 63 74 69 6f 6e ..max_connection
0510: 73 28 35 29 0a 09 09 09 09 2e 61 63 71 75 69 72 s(5)......acquir
0520: 65 5f 74 69 6d 65 6f 75 74 28 73 74 64 3a 3a 74 e_timeout(std::t
0530: 69 6d 65 3a 3a 44 75 72 61 74 69 6f 6e 3a 3a 6e ime::Duration::n
0540: 65 77 28 33 30 30 2c 20 30 29 29 0a 09 09 09 09 ew(300, 0)).....
0550: 2e 69 64 6c 65 5f 74 69 6d 65 6f 75 74 28 73 74 .idle_timeout(st
0560: 64 3a 3a 74 69 6d 65 3a 3a 44 75 72 61 74 69 6f d::time::Duratio
0570: 6e 3a 3a 6e 65 77 28 36 30 2c 20 30 29 29 0a 09 n::new(60, 0))..
0580: 09 09 09 2e 63 6f 6e 6e 65 63 74 5f 6c 61 7a 79 ....connect_lazy
0590: 28 26 73 65 74 74 69 6e 67 73 2e 67 65 74 5f 73 (&settings.get_s
05a0: 74 72 69 6e 67 28 22 70 67 22 29 3f 29 3f 2c 0a tring("pg")?)?,.
05b0: 09 09 09 73 6f 75 72 63 65 73 3a 20 41 72 63 3a ...sources: Arc:
05c0: 3a 6e 65 77 28 4d 75 74 65 78 3a 3a 6e 65 77 28 :new(Mutex::new(
05d0: 48 61 73 68 53 65 74 3a 3a 6e 65 77 28 29 29 29 HashSet::new()))
05e0: 2c 0a 09 09 09 68 74 74 70 5f 63 6c 69 65 6e 74 ,....http_client
05f0: 2c 0a 09 09 7d 29 3b 0a 09 09 6c 65 74 20 63 6c ,...});...let cl
0600: 6f 6e 65 20 3d 20 63 6f 72 65 2e 63 6c 6f 6e 65 one = core.clone
0610: 28 29 3b 0a 09 09 74 61 73 6b 3a 3a 73 70 61 77 ();...task::spaw
0620: 6e 28 61 73 79 6e 63 20 6d 6f 76 65 20 7b 0a 09 n(async move {..
0630: 09 09 6c 6f 6f 70 20 7b 0a 09 09 09 09 6c 65 74 ..loop {.....let
0640: 20 64 65 6c 61 79 20 3d 20 6d 61 74 63 68 20 26 delay = match &
0650: 63 6c 6f 6e 65 2e 61 75 74 6f 66 65 74 63 68 28 clone.autofetch(
0660: 29 2e 61 77 61 69 74 20 7b 0a 09 09 09 09 09 45 ).await {......E
0670: 72 72 28 65 72 72 29 20 3d 3e 20 7b 0a 09 09 09 rr(err) => {....
0680: 09 09 09 69 66 20 6c 65 74 20 45 72 72 28 65 72 ...if let Err(er
0690: 72 29 20 3d 20 63 6c 6f 6e 65 2e 73 65 6e 64 28 r) = clone.send(
06a0: 66 6f 72 6d 61 74 21 28 22 f0 9f 9b 91 20 7b 3a format!("š {:
06b0: 3f 7d 22 2c 20 65 72 72 29 2c 20 4e 6f 6e 65 2c ?}", err), None,
06c0: 20 4e 6f 6e 65 29 2e 61 77 61 69 74 20 7b 0a 09 None).await {..
06d0: 09 09 09 09 09 09 65 70 72 69 6e 74 6c 6e 21 28 ......eprintln!(
06e0: 22 41 75 74 6f 66 65 74 63 68 20 65 72 72 6f 72 "Autofetch error
06f0: 3a 20 7b 7d 22 2c 20 65 72 72 29 3b 0a 09 09 09 : {}", err);....
0700: 09 09 09 7d 3b 0a 09 09 09 09 09 09 73 74 64 3a ...};.......std:
0710: 3a 74 69 6d 65 3a 3a 44 75 72 61 74 69 6f 6e 3a :time::Duration:
0720: 3a 66 72 6f 6d 5f 73 65 63 73 28 36 30 29 0a 09 :from_secs(60)..
0730: 09 09 09 09 7d 2c 0a 09 09 09 09 09 4f 6b 28 74 ....},......Ok(t
0740: 69 6d 65 29 20 3d 3e 20 2a 74 69 6d 65 2c 0a 09 ime) => *time,..
0750: 09 09 09 7d 3b 0a 09 09 09 09 74 61 73 6b 3a 3a ...};.....task::
0760: 73 6c 65 65 70 28 64 65 6c 61 79 29 2e 61 77 61 sleep(delay).awa
0770: 69 74 3b 0a 09 09 09 7d 0a 09 09 7d 29 3b 0a 09 it;....}...});..
0780: 09 4f 6b 28 63 6f 72 65 29 0a 09 7d 0a 0a 09 70 .Ok(core)..}...p
0790: 75 62 20 66 6e 20 73 74 72 65 61 6d 28 26 73 65 ub fn stream(&se
07a0: 6c 66 29 20 2d 3e 20 74 65 6c 65 67 72 61 6d 5f lf) -> telegram_
07b0: 62 6f 74 3a 3a 55 70 64 61 74 65 73 53 74 72 65 bot::UpdatesStre
07c0: 61 6d 20 7b 0a 09 09 73 65 6c 66 2e 74 67 2e 73 am {...self.tg.s
07d0: 74 72 65 61 6d 28 29 0a 09 7d 0a 0a 09 70 75 62 tream()..}...pub
07e0: 20 61 73 79 6e 63 20 66 6e 20 73 65 6e 64 3c 27 async fn send<'
07f0: 61 2c 20 53 3e 28 26 73 65 6c 66 2c 20 6d 73 67 a, S>(&self, msg
0800: 3a 20 53 2c 20 74 61 72 67 65 74 3a 20 4f 70 74 : S, target: Opt
0810: 69 6f 6e 3c 74 65 6c 65 67 72 61 6d 5f 62 6f 74 ion<telegram_bot
0820: 3a 3a 55 73 65 72 49 64 3e 2c 20 6d 6f 64 65 3a ::UserId>, mode:
0830: 20 4f 70 74 69 6f 6e 3c 74 65 6c 65 67 72 61 6d Option<telegram
0840: 5f 62 6f 74 3a 3a 74 79 70 65 73 3a 3a 50 61 72 _bot::types::Par
0850: 73 65 4d 6f 64 65 3e 29 20 2d 3e 20 52 65 73 75 seMode>) -> Resu
0860: 6c 74 3c 28 29 3e 0a 09 77 68 65 72 65 20 53 3a lt<()>..where S:
0870: 20 49 6e 74 6f 3c 43 6f 77 3c 27 61 2c 20 73 74 Into<Cow<'a, st
0880: 72 3e 3e 20 7b 0a 09 09 6c 65 74 20 6d 6f 64 65 r>> {...let mode
0890: 20 3d 20 6d 6f 64 65 2e 75 6e 77 72 61 70 5f 6f = mode.unwrap_o
08a0: 72 28 74 65 6c 65 67 72 61 6d 5f 62 6f 74 3a 3a r(telegram_bot::
08b0: 74 79 70 65 73 3a 3a 50 61 72 73 65 4d 6f 64 65 types::ParseMode
08c0: 3a 3a 48 74 6d 6c 29 3b 0a 09 09 6c 65 74 20 74 ::Html);...let t
08d0: 61 72 67 65 74 20 3d 20 74 61 72 67 65 74 2e 75 arget = target.u
08e0: 6e 77 72 61 70 5f 6f 72 28 73 65 6c 66 2e 6f 77 nwrap_or(self.ow
08f0: 6e 65 72 5f 63 68 61 74 29 3b 0a 09 09 73 65 6c ner_chat);...sel
0900: 66 2e 72 65 71 75 65 73 74 28 74 65 6c 65 67 72 f.request(telegr
0910: 61 6d 5f 62 6f 74 3a 3a 53 65 6e 64 4d 65 73 73 am_bot::SendMess
0920: 61 67 65 3a 3a 6e 65 77 28 74 61 72 67 65 74 2c age::new(target,
0930: 20 6d 73 67 29 2e 70 61 72 73 65 5f 6d 6f 64 65 msg).parse_mode
0940: 28 6d 6f 64 65 29 29 2e 61 77 61 69 74 3f 3b 0a (mode)).await?;.
0950: 09 09 4f 6b 28 28 29 29 0a 09 7d 0a 0a 09 70 75 ..Ok(())..}...pu
0960: 62 20 61 73 79 6e 63 20 66 6e 20 72 65 71 75 65 b async fn reque
0970: 73 74 3c 52 65 71 3a 20 74 65 6c 65 67 72 61 6d st<Req: telegram
0980: 5f 62 6f 74 3a 3a 52 65 71 75 65 73 74 3e 20 28 _bot::Request> (
0990: 26 73 65 6c 66 2c 20 72 65 71 3a 20 52 65 71 29 &self, req: Req)
09a0: 20 2d 3e 20 52 65 73 75 6c 74 3c 3c 52 65 71 3a -> Result<<Req:
09b0: 3a 52 65 73 70 6f 6e 73 65 20 61 73 20 74 65 6c :Response as tel
09c0: 65 67 72 61 6d 5f 62 6f 74 3a 3a 52 65 73 70 6f egram_bot::Respo
09d0: 6e 73 65 54 79 70 65 3e 3a 3a 54 79 70 65 3e 20 nseType>::Type>
09e0: 7b 0a 09 09 6c 6f 6f 70 20 7b 0a 09 09 09 6c 65 {...loop {....le
09f0: 74 20 72 65 73 20 3d 20 73 65 6c 66 2e 74 67 2e t res = self.tg.
0a00: 73 65 6e 64 28 26 72 65 71 29 2e 61 77 61 69 74 send(&req).await
0a10: 3b 0a 09 09 09 6d 61 74 63 68 20 72 65 73 20 7b ;....match res {
0a20: 0a 09 09 09 09 4f 6b 28 5f 29 20 3d 3e 20 72 65 .....Ok(_) => re
0a30: 74 75 72 6e 20 4f 6b 28 72 65 73 3f 29 2c 0a 09 turn Ok(res?),..
0a40: 09 09 09 45 72 72 28 65 72 72 29 20 3d 3e 20 7b ...Err(err) => {
0a50: 0a 09 09 09 09 09 64 62 67 21 28 26 65 72 72 29 ......dbg!(&err)
0a60: 3b 0a 09 09 09 09 09 69 66 20 6c 65 74 20 53 6f ;......if let So
0a70: 6d 65 28 63 61 70 73 29 20 3d 20 52 45 5f 44 45 me(caps) = RE_DE
0a80: 4c 41 59 2e 63 61 70 74 75 72 65 73 28 65 72 72 LAY.captures(err
0a90: 2e 74 6f 5f 73 74 72 69 6e 67 28 29 2e 61 73 5f .to_string().as_
0aa0: 72 65 66 28 29 29 20 7b 0a 09 09 09 09 09 09 69 ref()) {.......i
0ab0: 66 20 6c 65 74 20 53 6f 6d 65 28 64 65 6c 61 79 f let Some(delay
0ac0: 29 20 3d 20 63 61 70 73 2e 67 65 74 28 31 29 20 ) = caps.get(1)
0ad0: 7b 0a 09 09 09 09 09 09 09 6c 65 74 20 64 65 6c {........let del
0ae0: 61 79 20 3d 20 64 65 6c 61 79 2e 61 73 5f 73 74 ay = delay.as_st
0af0: 72 28 29 2e 70 61 72 73 65 3a 3a 3c 75 36 34 3e r().parse::<u64>
0b00: 28 29 3f 3b 0a 09 09 09 09 09 09 09 70 72 69 6e ()?;........prin
0b10: 74 6c 6e 21 28 22 54 68 72 6f 74 74 6c 65 64 2c tln!("Throttled,
0b20: 20 77 61 69 74 69 6e 67 20 7b 7d 20 73 65 6e 63 waiting {} senc
0b30: 6f 6e 64 73 2e 22 2c 20 64 65 6c 61 79 29 3b 0a onds.", delay);.
0b40: 09 09 09 09 09 09 09 74 61 73 6b 3a 3a 73 6c 65 .......task::sle
0b50: 65 70 28 73 74 64 3a 3a 74 69 6d 65 3a 3a 44 75 ep(std::time::Du
0b60: 72 61 74 69 6f 6e 3a 3a 66 72 6f 6d 5f 73 65 63 ration::from_sec
0b70: 73 28 64 65 6c 61 79 29 29 2e 61 77 61 69 74 3b s(delay)).await;
0b80: 0a 09 09 09 09 09 09 7d 20 65 6c 73 65 20 7b 0a .......} else {.
0b90: 09 09 09 09 09 09 09 62 61 69 6c 21 28 22 43 61 .......bail!("Ca
0ba0: 6e 27 74 20 72 65 61 64 20 74 68 72 6f 74 74 6c n't read throttl
0bb0: 69 6e 67 20 6d 65 73 73 61 67 65 2e 22 29 3b 0a ing message.");.
0bc0: 09 09 09 09 09 09 7d 0a 09 09 09 09 09 7d 20 65 ......}......} e
0bd0: 6c 73 65 20 7b 0a 09 09 09 09 09 09 72 65 74 75 lse {.......retu
0be0: 72 6e 20 45 72 72 28 65 72 72 2e 69 6e 74 6f 28 rn Err(err.into(
0bf0: 29 29 3b 0a 09 09 09 09 09 7d 0a 09 09 09 09 7d ));......}.....}
0c00: 2c 0a 09 09 09 7d 3b 0a 09 09 7d 0a 09 7d 0a 0a ,....};...}..}..
0c10: 09 70 75 62 20 61 73 79 6e 63 20 66 6e 20 63 68 .pub async fn ch
0c20: 65 63 6b 3c 53 3e 28 26 73 65 6c 66 2c 20 69 64 eck<S>(&self, id
0c30: 3a 20 26 69 33 32 2c 20 6f 77 6e 65 72 3a 20 53 : &i32, owner: S
0c40: 2c 20 72 65 61 6c 3a 20 62 6f 6f 6c 29 20 2d 3e , real: bool) ->
0c50: 20 52 65 73 75 6c 74 3c 43 6f 77 3c 27 5f 2c 20 Result<Cow<'_,
0c60: 73 74 72 3e 3e 0a 09 77 68 65 72 65 20 53 3a 20 str>>..where S:
0c70: 49 6e 74 6f 3c 69 36 34 3e 20 7b 0a 09 09 6c 65 Into<i64> {...le
0c80: 74 20 6f 77 6e 65 72 20 3d 20 6f 77 6e 65 72 2e t owner = owner.
0c90: 69 6e 74 6f 28 29 3b 0a 0a 09 09 6c 65 74 20 6d into();....let m
0ca0: 75 74 20 70 6f 73 74 65 64 3a 20 69 33 32 20 3d ut posted: i32 =
0cb0: 20 30 3b 0a 09 09 6c 65 74 20 69 64 20 3d 20 7b 0;...let id = {
0cc0: 0a 09 09 09 6c 65 74 20 6d 75 74 20 73 65 74 20 ....let mut set
0cd0: 3d 20 73 65 6c 66 2e 73 6f 75 72 63 65 73 2e 6c = self.sources.l
0ce0: 6f 63 6b 28 29 2e 75 6e 77 72 61 70 28 29 3b 0a ock().unwrap();.
0cf0: 09 09 09 6d 61 74 63 68 20 73 65 74 2e 67 65 74 ...match set.get
0d00: 28 69 64 29 20 7b 0a 09 09 09 09 53 6f 6d 65 28 (id) {.....Some(
0d10: 69 64 29 20 3d 3e 20 69 64 2e 63 6c 6f 6e 65 28 id) => id.clone(
0d20: 29 2c 0a 09 09 09 09 4e 6f 6e 65 20 3d 3e 20 7b ),.....None => {
0d30: 0a 09 09 09 09 09 6c 65 74 20 69 64 20 3d 20 41 ......let id = A
0d40: 72 63 3a 3a 6e 65 77 28 2a 69 64 29 3b 0a 09 09 rc::new(*id);...
0d50: 09 09 09 73 65 74 2e 69 6e 73 65 72 74 28 69 64 ...set.insert(id
0d60: 2e 63 6c 6f 6e 65 28 29 29 3b 0a 09 09 09 09 09 .clone());......
0d70: 69 64 2e 63 6c 6f 6e 65 28 29 0a 09 09 09 09 7d id.clone().....}
0d80: 2c 0a 09 09 09 7d 0a 09 09 7d 3b 0a 09 09 6c 65 ,....}...};...le
0d90: 74 20 63 6f 75 6e 74 20 3d 20 41 72 63 3a 3a 73 t count = Arc::s
0da0: 74 72 6f 6e 67 5f 63 6f 75 6e 74 28 26 69 64 29 trong_count(&id)
0db0: 3b 0a 09 09 69 66 20 63 6f 75 6e 74 20 3d 3d 20 ;...if count ==
0dc0: 32 20 7b 0a 09 09 09 6c 65 74 20 73 6f 75 72 63 2 {....let sourc
0dd0: 65 20 3d 20 73 71 6c 78 3a 3a 71 75 65 72 79 21 e = sqlx::query!
0de0: 28 22 73 65 6c 65 63 74 20 73 6f 75 72 63 65 5f ("select source_
0df0: 69 64 2c 20 63 68 61 6e 6e 65 6c 5f 69 64 2c 20 id, channel_id,
0e00: 75 72 6c 2c 20 69 76 5f 68 61 73 68 2c 20 6f 77 url, iv_hash, ow
0e10: 6e 65 72 2c 20 75 72 6c 5f 72 65 20 66 72 6f 6d ner, url_re from
0e20: 20 72 73 73 74 67 5f 73 6f 75 72 63 65 20 77 68 rsstg_source wh
0e30: 65 72 65 20 73 6f 75 72 63 65 5f 69 64 20 3d 20 ere source_id =
0e40: 24 31 20 61 6e 64 20 6f 77 6e 65 72 20 3d 20 24 $1 and owner = $
0e50: 32 22 2c 0a 09 09 09 09 2a 69 64 2c 20 6f 77 6e 2",.....*id, own
0e60: 65 72 29 2e 66 65 74 63 68 5f 6f 6e 65 28 26 6d er).fetch_one(&m
0e70: 75 74 20 73 65 6c 66 2e 70 6f 6f 6c 2e 61 63 71 ut self.pool.acq
0e80: 75 69 72 65 28 29 2e 61 77 61 69 74 3f 29 2e 61 uire().await?).a
0e90: 77 61 69 74 3f 3b 0a 09 09 09 6c 65 74 20 64 65 wait?;....let de
0ea0: 73 74 69 6e 61 74 69 6f 6e 20 3d 20 6d 61 74 63 stination = matc
0eb0: 68 20 72 65 61 6c 20 7b 0a 09 09 09 09 74 72 75 h real {.....tru
0ec0: 65 20 3d 3e 20 74 65 6c 65 67 72 61 6d 5f 62 6f e => telegram_bo
0ed0: 74 3a 3a 55 73 65 72 49 64 3a 3a 6e 65 77 28 73 t::UserId::new(s
0ee0: 6f 75 72 63 65 2e 63 68 61 6e 6e 65 6c 5f 69 64 ource.channel_id
0ef0: 29 2c 0a 09 09 09 09 66 61 6c 73 65 20 3d 3e 20 ),.....false =>
0f00: 74 65 6c 65 67 72 61 6d 5f 62 6f 74 3a 3a 55 73 telegram_bot::Us
0f10: 65 72 49 64 3a 3a 6e 65 77 28 73 6f 75 72 63 65 erId::new(source
0f20: 2e 6f 77 6e 65 72 29 2c 0a 09 09 09 7d 3b 0a 09 .owner),....};..
0f30: 09 09 6c 65 74 20 6d 75 74 20 74 68 69 73 5f 66 ..let mut this_f
0f40: 65 74 63 68 3a 20 4f 70 74 69 6f 6e 3c 44 61 74 etch: Option<Dat
0f50: 65 54 69 6d 65 3c 63 68 72 6f 6e 6f 3a 3a 46 69 eTime<chrono::Fi
0f60: 78 65 64 4f 66 66 73 65 74 3e 3e 20 3d 20 4e 6f xedOffset>> = No
0f70: 6e 65 3b 0a 09 09 09 6c 65 74 20 6d 75 74 20 70 ne;....let mut p
0f80: 6f 73 74 73 3a 20 42 54 72 65 65 4d 61 70 3c 44 osts: BTreeMap<D
0f90: 61 74 65 54 69 6d 65 3c 63 68 72 6f 6e 6f 3a 3a ateTime<chrono::
0fa0: 46 69 78 65 64 4f 66 66 73 65 74 3e 2c 20 53 74 FixedOffset>, St
0fb0: 72 69 6e 67 3e 20 3d 20 42 54 72 65 65 4d 61 70 ring> = BTreeMap
0fc0: 3a 3a 6e 65 77 28 29 3b 0a 0a 09 09 09 6c 65 74 ::new();.....let
0fd0: 20 72 65 73 70 6f 6e 73 65 20 3d 20 73 65 6c 66 response = self
0fe0: 2e 68 74 74 70 5f 63 6c 69 65 6e 74 2e 67 65 74 .http_client.get
0ff0: 28 26 73 6f 75 72 63 65 2e 75 72 6c 29 2e 73 65 (&source.url).se
1000: 6e 64 28 29 2e 61 77 61 69 74 3f 3b 0a 09 09 09 nd().await?;....
1010: 6c 65 74 20 73 74 61 74 75 73 20 3d 20 72 65 73 let status = res
1020: 70 6f 6e 73 65 2e 73 74 61 74 75 73 28 29 3b 0a ponse.status();.
1030: 09 09 09 6c 65 74 20 63 6f 6e 74 65 6e 74 20 3d ...let content =
1040: 20 72 65 73 70 6f 6e 73 65 2e 62 79 74 65 73 28 response.bytes(
1050: 29 2e 61 77 61 69 74 3f 3b 0a 09 09 09 6d 61 74 ).await?;....mat
1060: 63 68 20 72 73 73 3a 3a 43 68 61 6e 6e 65 6c 3a ch rss::Channel:
1070: 3a 72 65 61 64 5f 66 72 6f 6d 28 26 63 6f 6e 74 :read_from(&cont
1080: 65 6e 74 5b 2e 2e 5d 29 20 7b 0a 09 09 09 09 4f ent[..]) {.....O
1090: 6b 28 66 65 65 64 29 20 3d 3e 20 7b 0a 09 09 09 k(feed) => {....
10a0: 09 09 66 6f 72 20 69 74 65 6d 20 69 6e 20 66 65 ..for item in fe
10b0: 65 64 2e 69 74 65 6d 73 28 29 20 7b 0a 09 09 09 ed.items() {....
10c0: 09 09 09 69 66 20 6c 65 74 20 53 6f 6d 65 28 6c ...if let Some(l
10d0: 69 6e 6b 29 20 3d 20 69 74 65 6d 2e 6c 69 6e 6b ink) = item.link
10e0: 28 29 20 7b 0a 09 09 09 09 09 09 09 6c 65 74 20 () {........let
10f0: 64 61 74 65 20 3d 20 6d 61 74 63 68 20 69 74 65 date = match ite
1100: 6d 2e 70 75 62 5f 64 61 74 65 28 29 20 7b 0a 09 m.pub_date() {..
1110: 09 09 09 09 09 09 09 53 6f 6d 65 28 66 65 65 64 .......Some(feed
1120: 5f 64 61 74 65 29 20 3d 3e 20 44 61 74 65 54 69 _date) => DateTi
1130: 6d 65 3a 3a 70 61 72 73 65 5f 66 72 6f 6d 5f 72 me::parse_from_r
1140: 66 63 32 38 32 32 28 66 65 65 64 5f 64 61 74 65 fc2822(feed_date
1150: 29 2c 0a 09 09 09 09 09 09 09 09 4e 6f 6e 65 20 ),.........None
1160: 3d 3e 20 44 61 74 65 54 69 6d 65 3a 3a 70 61 72 => DateTime::par
1170: 73 65 5f 66 72 6f 6d 5f 72 66 63 33 33 33 39 28 se_from_rfc3339(
1180: 26 69 74 65 6d 2e 64 75 62 6c 69 6e 5f 63 6f 72 &item.dublin_cor
1190: 65 5f 65 78 74 28 29 2e 75 6e 77 72 61 70 28 29 e_ext().unwrap()
11a0: 2e 64 61 74 65 73 28 29 5b 30 5d 29 2c 0a 09 09 .dates()[0]),...
11b0: 09 09 09 09 09 7d 3f 3b 0a 09 09 09 09 09 09 09 .....}?;........
11c0: 6c 65 74 20 75 72 6c 20 3d 20 6c 69 6e 6b 3b 0a let url = link;.
11d0: 09 09 09 09 09 09 09 70 6f 73 74 73 2e 69 6e 73 .......posts.ins
11e0: 65 72 74 28 64 61 74 65 2c 20 75 72 6c 2e 74 6f ert(date, url.to
11f0: 5f 73 74 72 69 6e 67 28 29 29 3b 0a 09 09 09 09 _string());.....
1200: 09 09 7d 0a 09 09 09 09 09 7d 3b 0a 09 09 09 09 ..}......};.....
1210: 7d 2c 0a 09 09 09 09 45 72 72 28 65 72 72 29 20 },.....Err(err)
1220: 3d 3e 20 6d 61 74 63 68 20 65 72 72 20 7b 0a 09 => match err {..
1230: 09 09 09 09 72 73 73 3a 3a 45 72 72 6f 72 3a 3a ....rss::Error::
1240: 49 6e 76 61 6c 69 64 53 74 61 72 74 54 61 67 20 InvalidStartTag
1250: 3d 3e 20 7b 0a 09 09 09 09 09 09 6c 65 74 20 66 => {.......let f
1260: 65 65 64 20 3d 20 61 74 6f 6d 5f 73 79 6e 64 69 eed = atom_syndi
1270: 63 61 74 69 6f 6e 3a 3a 46 65 65 64 3a 3a 72 65 cation::Feed::re
1280: 61 64 5f 66 72 6f 6d 28 26 63 6f 6e 74 65 6e 74 ad_from(&content
1290: 5b 2e 2e 5d 29 0a 09 09 09 09 09 09 09 2e 77 69 [..]).........wi
12a0: 74 68 5f 63 6f 6e 74 65 78 74 28 7c 7c 20 66 6f th_context(|| fo
12b0: 72 6d 61 74 21 28 22 50 72 6f 62 6c 65 6d 20 6f rmat!("Problem o
12c0: 70 65 6e 69 6e 67 20 66 65 65 64 20 75 72 6c 3a pening feed url:
12d0: 5c 6e 7b 7d 5c 6e 7b 7d 22 2c 20 26 73 6f 75 72 \n{}\n{}", &sour
12e0: 63 65 2e 75 72 6c 2c 20 73 74 61 74 75 73 29 29 ce.url, status))
12f0: 3f 3b 0a 09 09 09 09 09 09 66 6f 72 20 69 74 65 ?;.......for ite
1300: 6d 20 69 6e 20 66 65 65 64 2e 65 6e 74 72 69 65 m in feed.entrie
1310: 73 28 29 20 7b 0a 09 09 09 09 09 09 09 6c 65 74 s() {........let
1320: 20 64 61 74 65 20 3d 20 69 74 65 6d 2e 70 75 62 date = item.pub
1330: 6c 69 73 68 65 64 28 29 2e 75 6e 77 72 61 70 28 lished().unwrap(
1340: 29 3b 0a 09 09 09 09 09 09 09 6c 65 74 20 75 72 );........let ur
1350: 6c 20 3d 20 69 74 65 6d 2e 6c 69 6e 6b 73 28 29 l = item.links()
1360: 5b 30 5d 2e 68 72 65 66 28 29 3b 0a 09 09 09 09 [0].href();.....
1370: 09 09 09 70 6f 73 74 73 2e 69 6e 73 65 72 74 28 ...posts.insert(
1380: 2a 64 61 74 65 2c 20 75 72 6c 2e 74 6f 5f 73 74 *date, url.to_st
1390: 72 69 6e 67 28 29 29 3b 0a 09 09 09 09 09 09 7d ring());.......}
13a0: 3b 0a 09 09 09 09 09 7d 2c 0a 09 09 09 09 09 72 ;......},......r
13b0: 73 73 3a 3a 45 72 72 6f 72 3a 3a 45 6f 66 20 3d ss::Error::Eof =
13c0: 3e 20 28 29 2c 0a 09 09 09 09 09 5f 20 3d 3e 20 > (),......_ =>
13d0: 62 61 69 6c 21 28 22 55 6e 73 75 70 70 6f 72 74 bail!("Unsupport
13e0: 65 64 20 6f 72 20 6d 61 6e 67 6c 65 64 20 63 6f ed or mangled co
13f0: 6e 74 65 6e 74 3a 5c 6e 7b 3a 3f 7d 5c 6e 7b 3a ntent:\n{:?}\n{:
1400: 23 3f 7d 5c 6e 7b 3a 23 3f 7d 5c 6e 22 2c 20 26 #?}\n{:#?}\n", &
1410: 73 6f 75 72 63 65 2e 75 72 6c 2c 20 65 72 72 2c source.url, err,
1420: 20 73 74 61 74 75 73 29 0a 09 09 09 09 7d 0a 09 status).....}..
1430: 09 09 7d 3b 0a 09 09 09 66 6f 72 20 28 64 61 74 ..};....for (dat
1440: 65 2c 20 75 72 6c 29 20 69 6e 20 70 6f 73 74 73 e, url) in posts
1450: 2e 69 74 65 72 28 29 20 7b 0a 09 09 09 09 6c 65 .iter() {.....le
1460: 74 20 70 6f 73 74 5f 75 72 6c 3a 20 43 6f 77 3c t post_url: Cow<
1470: 73 74 72 3e 20 3d 20 6d 61 74 63 68 20 73 6f 75 str> = match sou
1480: 72 63 65 2e 75 72 6c 5f 72 65 20 7b 0a 09 09 09 rce.url_re {....
1490: 09 09 53 6f 6d 65 28 72 65 66 20 78 29 20 3d 3e ..Some(ref x) =>
14a0: 20 73 65 64 72 65 67 65 78 3a 3a 52 65 70 6c 61 sedregex::Repla
14b0: 63 65 43 6f 6d 6d 61 6e 64 3a 3a 6e 65 77 28 78 ceCommand::new(x
14c0: 29 3f 2e 65 78 65 63 75 74 65 28 75 72 6c 29 2c )?.execute(url),
14d0: 0a 09 09 09 09 09 4e 6f 6e 65 20 3d 3e 20 75 72 ......None => ur
14e0: 6c 2e 69 6e 74 6f 28 29 2c 0a 09 09 09 09 7d 3b l.into(),.....};
14f0: 0a 09 09 09 09 69 66 20 6c 65 74 20 53 6f 6d 65 .....if let Some
1500: 28 65 78 69 73 74 73 29 20 3d 20 73 71 6c 78 3a (exists) = sqlx:
1510: 3a 71 75 65 72 79 21 28 22 73 65 6c 65 63 74 20 :query!("select
1520: 65 78 69 73 74 73 28 73 65 6c 65 63 74 20 74 72 exists(select tr
1530: 75 65 20 66 72 6f 6d 20 72 73 73 74 67 5f 70 6f ue from rsstg_po
1540: 73 74 20 77 68 65 72 65 20 75 72 6c 20 3d 20 24 st where url = $
1550: 31 20 61 6e 64 20 73 6f 75 72 63 65 5f 69 64 20 1 and source_id
1560: 3d 20 24 32 29 20 61 73 20 65 78 69 73 74 73 3b = $2) as exists;
1570: 22 2c 0a 09 09 09 09 09 26 70 6f 73 74 5f 75 72 ",......&post_ur
1580: 6c 2c 20 2a 69 64 29 2e 66 65 74 63 68 5f 6f 6e l, *id).fetch_on
1590: 65 28 26 6d 75 74 20 73 65 6c 66 2e 70 6f 6f 6c e(&mut self.pool
15a0: 2e 61 63 71 75 69 72 65 28 29 2e 61 77 61 69 74 .acquire().await
15b0: 3f 29 2e 61 77 61 69 74 3f 2e 65 78 69 73 74 73 ?).await?.exists
15c0: 20 7b 0a 09 09 09 09 09 69 66 20 21 20 65 78 69 {......if ! exi
15d0: 73 74 73 20 7b 0a 09 09 09 09 09 09 69 66 20 74 sts {.......if t
15e0: 68 69 73 5f 66 65 74 63 68 2e 69 73 5f 6e 6f 6e his_fetch.is_non
15f0: 65 28 29 20 7c 7c 20 2a 64 61 74 65 20 3e 20 74 e() || *date > t
1600: 68 69 73 5f 66 65 74 63 68 2e 75 6e 77 72 61 70 his_fetch.unwrap
1610: 28 29 20 7b 0a 09 09 09 09 09 09 09 74 68 69 73 () {........this
1620: 5f 66 65 74 63 68 20 3d 20 53 6f 6d 65 28 2a 64 _fetch = Some(*d
1630: 61 74 65 29 3b 0a 09 09 09 09 09 09 7d 3b 0a 09 ate);.......};..
1640: 09 09 09 09 09 73 65 6c 66 2e 72 65 71 75 65 73 .....self.reques
1650: 74 28 20 6d 61 74 63 68 20 26 73 6f 75 72 63 65 t( match &source
1660: 2e 69 76 5f 68 61 73 68 20 7b 0a 09 09 09 09 09 .iv_hash {......
1670: 09 09 09 53 6f 6d 65 28 68 61 73 68 29 20 3d 3e ...Some(hash) =>
1680: 20 74 65 6c 65 67 72 61 6d 5f 62 6f 74 3a 3a 53 telegram_bot::S
1690: 65 6e 64 4d 65 73 73 61 67 65 3a 3a 6e 65 77 28 endMessage::new(
16a0: 64 65 73 74 69 6e 61 74 69 6f 6e 2c 20 66 6f 72 destination, for
16b0: 6d 61 74 21 28 22 3c 61 20 68 72 65 66 3d 5c 22 mat!("<a href=\"
16c0: 68 74 74 70 73 3a 2f 2f 74 2e 6d 65 2f 69 76 3f https://t.me/iv?
16d0: 75 72 6c 3d 7b 7d 26 72 68 61 73 68 3d 7b 7d 5c url={}&rhash={}\
16e0: 22 3e 20 3c 2f 61 3e 7b 30 7d 22 2c 20 26 70 6f "> </a>{0}", &po
16f0: 73 74 5f 75 72 6c 2c 20 68 61 73 68 29 29 2c 0a st_url, hash)),.
1700: 09 09 09 09 09 09 09 09 4e 6f 6e 65 20 3d 3e 20 ........None =>
1710: 74 65 6c 65 67 72 61 6d 5f 62 6f 74 3a 3a 53 65 telegram_bot::Se
1720: 6e 64 4d 65 73 73 61 67 65 3a 3a 6e 65 77 28 64 ndMessage::new(d
1730: 65 73 74 69 6e 61 74 69 6f 6e 2c 20 66 6f 72 6d estination, form
1740: 61 74 21 28 22 7b 7d 22 2c 20 70 6f 73 74 5f 75 at!("{}", post_u
1750: 72 6c 29 29 2c 0a 09 09 09 09 09 09 09 7d 2e 70 rl)),........}.p
1760: 61 72 73 65 5f 6d 6f 64 65 28 74 65 6c 65 67 72 arse_mode(telegr
1770: 61 6d 5f 62 6f 74 3a 3a 74 79 70 65 73 3a 3a 50 am_bot::types::P
1780: 61 72 73 65 4d 6f 64 65 3a 3a 48 74 6d 6c 29 29 arseMode::Html))
1790: 2e 61 77 61 69 74 0a 09 09 09 09 09 09 09 2e 63 .await.........c
17a0: 6f 6e 74 65 78 74 28 22 43 61 6e 27 74 20 70 6f ontext("Can't po
17b0: 73 74 20 6d 65 73 73 61 67 65 3a 22 29 3f 3b 0a st message:")?;.
17c0: 09 09 09 09 09 09 73 71 6c 78 3a 3a 71 75 65 72 ......sqlx::quer
17d0: 79 21 28 22 69 6e 73 65 72 74 20 69 6e 74 6f 20 y!("insert into
17e0: 72 73 73 74 67 5f 70 6f 73 74 20 28 73 6f 75 72 rsstg_post (sour
17f0: 63 65 5f 69 64 2c 20 70 6f 73 74 65 64 2c 20 75 ce_id, posted, u
1800: 72 6c 29 20 76 61 6c 75 65 73 20 28 24 31 2c 20 rl) values ($1,
1810: 24 32 2c 20 24 33 29 3b 22 2c 0a 09 09 09 09 09 $2, $3);",......
1820: 09 09 2a 69 64 2c 20 64 61 74 65 2c 20 26 70 6f ..*id, date, &po
1830: 73 74 5f 75 72 6c 29 2e 65 78 65 63 75 74 65 28 st_url).execute(
1840: 26 6d 75 74 20 73 65 6c 66 2e 70 6f 6f 6c 2e 61 &mut self.pool.a
1850: 63 71 75 69 72 65 28 29 2e 61 77 61 69 74 3f 29 cquire().await?)
1860: 2e 61 77 61 69 74 3f 3b 0a 09 09 09 09 09 7d 3b .await?;......};
1870: 0a 09 09 09 09 7d 3b 0a 09 09 09 09 70 6f 73 74 .....};.....post
1880: 65 64 20 2b 3d 20 31 3b 0a 09 09 09 7d 3b 0a 09 ed += 1;....};..
1890: 09 09 70 6f 73 74 73 2e 63 6c 65 61 72 28 29 3b ..posts.clear();
18a0: 0a 09 09 7d 3b 0a 09 09 73 71 6c 78 3a 3a 71 75 ...};...sqlx::qu
18b0: 65 72 79 21 28 22 75 70 64 61 74 65 20 72 73 73 ery!("update rss
18c0: 74 67 5f 73 6f 75 72 63 65 20 73 65 74 20 6c 61 tg_source set la
18d0: 73 74 5f 73 63 72 61 70 65 20 3d 20 6e 6f 77 28 st_scrape = now(
18e0: 29 20 77 68 65 72 65 20 73 6f 75 72 63 65 5f 69 ) where source_i
18f0: 64 20 3d 20 24 31 3b 22 2c 0a 09 09 09 2a 69 64 d = $1;",....*id
1900: 29 2e 65 78 65 63 75 74 65 28 26 6d 75 74 20 73 ).execute(&mut s
1910: 65 6c 66 2e 70 6f 6f 6c 2e 61 63 71 75 69 72 65 elf.pool.acquire
1920: 28 29 2e 61 77 61 69 74 3f 29 2e 61 77 61 69 74 ().await?).await
1930: 3f 3b 0a 09 09 4f 6b 28 66 6f 72 6d 61 74 21 28 ?;...Ok(format!(
1940: 22 50 6f 73 74 65 64 3a 20 7b 7d 22 2c 20 26 70 "Posted: {}", &p
1950: 6f 73 74 65 64 29 2e 69 6e 74 6f 28 29 29 0a 09 osted).into())..
1960: 7d 0a 0a 09 70 75 62 20 61 73 79 6e 63 20 66 6e }...pub async fn
1970: 20 64 65 6c 65 74 65 3c 53 3e 28 26 73 65 6c 66 delete<S>(&self
1980: 2c 20 73 6f 75 72 63 65 5f 69 64 3a 20 26 69 33 , source_id: &i3
1990: 32 2c 20 6f 77 6e 65 72 3a 20 53 29 20 2d 3e 20 2, owner: S) ->
19a0: 52 65 73 75 6c 74 3c 43 6f 77 3c 27 5f 2c 20 73 Result<Cow<'_, s
19b0: 74 72 3e 3e 0a 09 77 68 65 72 65 20 53 3a 20 49 tr>>..where S: I
19c0: 6e 74 6f 3c 69 36 34 3e 20 7b 0a 09 09 6c 65 74 nto<i64> {...let
19d0: 20 6f 77 6e 65 72 20 3d 20 6f 77 6e 65 72 2e 69 owner = owner.i
19e0: 6e 74 6f 28 29 3b 0a 0a 09 09 6d 61 74 63 68 20 nto();....match
19f0: 73 71 6c 78 3a 3a 71 75 65 72 79 21 28 22 64 65 sqlx::query!("de
1a00: 6c 65 74 65 20 66 72 6f 6d 20 72 73 73 74 67 5f lete from rsstg_
1a10: 73 6f 75 72 63 65 20 77 68 65 72 65 20 73 6f 75 source where sou
1a20: 72 63 65 5f 69 64 20 3d 20 24 31 20 61 6e 64 20 rce_id = $1 and
1a30: 6f 77 6e 65 72 20 3d 20 24 32 3b 22 2c 0a 09 09 owner = $2;",...
1a40: 09 73 6f 75 72 63 65 5f 69 64 2c 20 6f 77 6e 65 .source_id, owne
1a50: 72 29 2e 65 78 65 63 75 74 65 28 26 6d 75 74 20 r).execute(&mut
1a60: 73 65 6c 66 2e 70 6f 6f 6c 2e 61 63 71 75 69 72 self.pool.acquir
1a70: 65 28 29 2e 61 77 61 69 74 3f 29 2e 61 77 61 69 e().await?).awai
1a80: 74 3f 2e 72 6f 77 73 5f 61 66 66 65 63 74 65 64 t?.rows_affected
1a90: 28 29 20 7b 0a 09 09 09 30 20 3d 3e 20 7b 20 4f () {....0 => { O
1aa0: 6b 28 22 4e 6f 20 64 61 74 61 20 66 6f 75 6e 64 k("No data found
1ab0: 20 66 6f 75 6e 64 2e 22 2e 69 6e 74 6f 28 29 29 found.".into())
1ac0: 20 7d 2c 0a 09 09 09 78 20 3d 3e 20 7b 20 4f 6b },....x => { Ok
1ad0: 28 66 6f 72 6d 61 74 21 28 22 7b 7d 20 73 6f 75 (format!("{} sou
1ae0: 72 63 65 73 20 72 65 6d 6f 76 65 64 2e 22 2c 20 rces removed.",
1af0: 78 29 2e 69 6e 74 6f 28 29 29 20 7d 2c 0a 09 09 x).into()) },...
1b00: 7d 0a 09 7d 0a 0a 09 70 75 62 20 61 73 79 6e 63 }..}...pub async
1b10: 20 66 6e 20 63 6c 65 61 6e 3c 53 3e 28 26 73 65 fn clean<S>(&se
1b20: 6c 66 2c 20 73 6f 75 72 63 65 5f 69 64 3a 20 26 lf, source_id: &
1b30: 69 33 32 2c 20 6f 77 6e 65 72 3a 20 53 29 20 2d i32, owner: S) -
1b40: 3e 20 52 65 73 75 6c 74 3c 43 6f 77 3c 27 5f 2c > Result<Cow<'_,
1b50: 20 73 74 72 3e 3e 0a 09 77 68 65 72 65 20 53 3a str>>..where S:
1b60: 20 49 6e 74 6f 3c 69 36 34 3e 20 7b 0a 09 09 6c Into<i64> {...l
1b70: 65 74 20 6f 77 6e 65 72 20 3d 20 6f 77 6e 65 72 et owner = owner
1b80: 2e 69 6e 74 6f 28 29 3b 0a 0a 09 09 6d 61 74 63 .into();....matc
1b90: 68 20 73 71 6c 78 3a 3a 71 75 65 72 79 21 28 22 h sqlx::query!("
1ba0: 64 65 6c 65 74 65 20 66 72 6f 6d 20 72 73 73 74 delete from rsst
1bb0: 67 5f 70 6f 73 74 20 70 20 75 73 69 6e 67 20 72 g_post p using r
1bc0: 73 73 74 67 5f 73 6f 75 72 63 65 20 73 20 77 68 sstg_source s wh
1bd0: 65 72 65 20 70 2e 73 6f 75 72 63 65 5f 69 64 20 ere p.source_id
1be0: 3d 20 24 31 20 61 6e 64 20 6f 77 6e 65 72 20 3d = $1 and owner =
1bf0: 20 24 32 20 61 6e 64 20 70 2e 73 6f 75 72 63 65 $2 and p.source
1c00: 5f 69 64 20 3d 20 73 2e 73 6f 75 72 63 65 5f 69 _id = s.source_i
1c10: 64 3b 22 2c 0a 09 09 09 73 6f 75 72 63 65 5f 69 d;",....source_i
1c20: 64 2c 20 6f 77 6e 65 72 29 2e 65 78 65 63 75 74 d, owner).execut
1c30: 65 28 26 6d 75 74 20 73 65 6c 66 2e 70 6f 6f 6c e(&mut self.pool
1c40: 2e 61 63 71 75 69 72 65 28 29 2e 61 77 61 69 74 .acquire().await
1c50: 3f 29 2e 61 77 61 69 74 3f 2e 72 6f 77 73 5f 61 ?).await?.rows_a
1c60: 66 66 65 63 74 65 64 28 29 20 7b 0a 09 09 09 30 ffected() {....0
1c70: 20 3d 3e 20 7b 20 4f 6b 28 22 4e 6f 20 64 61 74 => { Ok("No dat
1c80: 61 20 66 6f 75 6e 64 20 66 6f 75 6e 64 2e 22 2e a found found.".
1c90: 69 6e 74 6f 28 29 29 20 7d 2c 0a 09 09 09 78 20 into()) },....x
1ca0: 3d 3e 20 7b 20 4f 6b 28 66 6f 72 6d 61 74 21 28 => { Ok(format!(
1cb0: 22 7b 7d 20 70 6f 73 74 73 20 70 75 72 67 65 64 "{} posts purged
1cc0: 2e 22 2c 20 78 29 2e 69 6e 74 6f 28 29 29 20 7d .", x).into()) }
1cd0: 2c 0a 09 09 7d 0a 09 7d 0a 0a 09 70 75 62 20 61 ,...}..}...pub a
1ce0: 73 79 6e 63 20 66 6e 20 65 6e 61 62 6c 65 3c 53 sync fn enable<S
1cf0: 3e 28 26 73 65 6c 66 2c 20 73 6f 75 72 63 65 5f >(&self, source_
1d00: 69 64 3a 20 26 69 33 32 2c 20 6f 77 6e 65 72 3a id: &i32, owner:
1d10: 20 53 29 20 2d 3e 20 52 65 73 75 6c 74 3c 26 73 S) -> Result<&s
1d20: 74 72 3e 0a 09 77 68 65 72 65 20 53 3a 20 49 6e tr>..where S: In
1d30: 74 6f 3c 69 36 34 3e 20 7b 0a 09 09 6c 65 74 20 to<i64> {...let
1d40: 6f 77 6e 65 72 20 3d 20 6f 77 6e 65 72 2e 69 6e owner = owner.in
1d50: 74 6f 28 29 3b 0a 0a 09 09 6d 61 74 63 68 20 73 to();....match s
1d60: 71 6c 78 3a 3a 71 75 65 72 79 21 28 22 75 70 64 qlx::query!("upd
1d70: 61 74 65 20 72 73 73 74 67 5f 73 6f 75 72 63 65 ate rsstg_source
1d80: 20 73 65 74 20 65 6e 61 62 6c 65 64 20 3d 20 74 set enabled = t
1d90: 72 75 65 20 77 68 65 72 65 20 73 6f 75 72 63 65 rue where source
1da0: 5f 69 64 20 3d 20 24 31 20 61 6e 64 20 6f 77 6e _id = $1 and own
1db0: 65 72 20 3d 20 24 32 22 2c 0a 09 09 09 73 6f 75 er = $2",....sou
1dc0: 72 63 65 5f 69 64 2c 20 6f 77 6e 65 72 29 2e 65 rce_id, owner).e
1dd0: 78 65 63 75 74 65 28 26 6d 75 74 20 73 65 6c 66 xecute(&mut self
1de0: 2e 70 6f 6f 6c 2e 61 63 71 75 69 72 65 28 29 2e .pool.acquire().
1df0: 61 77 61 69 74 3f 29 2e 61 77 61 69 74 3f 2e 72 await?).await?.r
1e00: 6f 77 73 5f 61 66 66 65 63 74 65 64 28 29 20 7b ows_affected() {
1e10: 0a 09 09 09 31 20 3d 3e 20 7b 20 4f 6b 28 22 53 ....1 => { Ok("S
1e20: 6f 75 72 63 65 20 65 6e 61 62 6c 65 64 2e 22 29 ource enabled.")
1e30: 20 7d 2c 0a 09 09 09 30 20 3d 3e 20 7b 20 4f 6b },....0 => { Ok
1e40: 28 22 53 6f 75 72 63 65 20 6e 6f 74 20 66 6f 75 ("Source not fou
1e50: 6e 64 2e 22 29 20 7d 2c 0a 09 09 09 5f 20 3d 3e nd.") },...._ =>
1e60: 20 7b 20 45 72 72 28 61 6e 79 68 6f 77 21 28 22 { Err(anyhow!("
1e70: 44 61 74 61 62 61 73 65 20 65 72 72 6f 72 2e 22 Database error."
1e80: 29 29 20 7d 2c 0a 09 09 7d 0a 09 7d 0a 0a 09 70 )) },...}..}...p
1e90: 75 62 20 61 73 79 6e 63 20 66 6e 20 64 69 73 61 ub async fn disa
1ea0: 62 6c 65 3c 53 3e 28 26 73 65 6c 66 2c 20 73 6f ble<S>(&self, so
1eb0: 75 72 63 65 5f 69 64 3a 20 26 69 33 32 2c 20 6f urce_id: &i32, o
1ec0: 77 6e 65 72 3a 20 53 29 20 2d 3e 20 52 65 73 75 wner: S) -> Resu
1ed0: 6c 74 3c 26 73 74 72 3e 0a 09 77 68 65 72 65 20 lt<&str>..where
1ee0: 53 3a 20 49 6e 74 6f 3c 69 36 34 3e 20 7b 0a 09 S: Into<i64> {..
1ef0: 09 6c 65 74 20 6f 77 6e 65 72 20 3d 20 6f 77 6e .let owner = own
1f00: 65 72 2e 69 6e 74 6f 28 29 3b 0a 0a 09 09 6d 61 er.into();....ma
1f10: 74 63 68 20 73 71 6c 78 3a 3a 71 75 65 72 79 21 tch sqlx::query!
1f20: 28 22 75 70 64 61 74 65 20 72 73 73 74 67 5f 73 ("update rsstg_s
1f30: 6f 75 72 63 65 20 73 65 74 20 65 6e 61 62 6c 65 ource set enable
1f40: 64 20 3d 20 66 61 6c 73 65 20 77 68 65 72 65 20 d = false where
1f50: 73 6f 75 72 63 65 5f 69 64 20 3d 20 24 31 20 61 source_id = $1 a
1f60: 6e 64 20 6f 77 6e 65 72 20 3d 20 24 32 22 2c 0a nd owner = $2",.
1f70: 09 09 09 73 6f 75 72 63 65 5f 69 64 2c 20 6f 77 ...source_id, ow
1f80: 6e 65 72 29 2e 65 78 65 63 75 74 65 28 26 6d 75 ner).execute(&mu
1f90: 74 20 73 65 6c 66 2e 70 6f 6f 6c 2e 61 63 71 75 t self.pool.acqu
1fa0: 69 72 65 28 29 2e 61 77 61 69 74 3f 29 2e 61 77 ire().await?).aw
1fb0: 61 69 74 3f 2e 72 6f 77 73 5f 61 66 66 65 63 74 ait?.rows_affect
1fc0: 65 64 28 29 20 7b 0a 09 09 09 31 20 3d 3e 20 7b ed() {....1 => {
1fd0: 20 4f 6b 28 22 53 6f 75 72 63 65 20 64 69 73 61 Ok("Source disa
1fe0: 62 6c 65 64 2e 22 29 20 7d 2c 0a 09 09 09 30 20 bled.") },....0
1ff0: 3d 3e 20 7b 20 4f 6b 28 22 53 6f 75 72 63 65 20 => { Ok("Source
2000: 6e 6f 74 20 66 6f 75 6e 64 2e 22 29 20 7d 2c 0a not found.") },.
2010: 09 09 09 5f 20 3d 3e 20 7b 20 45 72 72 28 61 6e ..._ => { Err(an
2020: 79 68 6f 77 21 28 22 44 61 74 61 62 61 73 65 20 yhow!("Database
2030: 65 72 72 6f 72 2e 22 29 29 20 7d 2c 0a 09 09 7d error.")) },...}
2040: 0a 09 7d 0a 0a 09 70 75 62 20 61 73 79 6e 63 20 ..}...pub async
2050: 66 6e 20 75 70 64 61 74 65 3c 53 3e 28 26 73 65 fn update<S>(&se
2060: 6c 66 2c 20 75 70 64 61 74 65 3a 20 4f 70 74 69 lf, update: Opti
2070: 6f 6e 3c 69 33 32 3e 2c 20 63 68 61 6e 6e 65 6c on<i32>, channel
2080: 3a 20 26 73 74 72 2c 20 63 68 61 6e 6e 65 6c 5f : &str, channel_
2090: 69 64 3a 20 69 36 34 2c 20 75 72 6c 3a 20 26 73 id: i64, url: &s
20a0: 74 72 2c 20 69 76 5f 68 61 73 68 3a 20 4f 70 74 tr, iv_hash: Opt
20b0: 69 6f 6e 3c 26 73 74 72 3e 2c 20 75 72 6c 5f 72 ion<&str>, url_r
20c0: 65 3a 20 4f 70 74 69 6f 6e 3c 26 73 74 72 3e 2c e: Option<&str>,
20d0: 20 6f 77 6e 65 72 3a 20 53 29 20 2d 3e 20 52 65 owner: S) -> Re
20e0: 73 75 6c 74 3c 26 73 74 72 3e 0a 09 77 68 65 72 sult<&str>..wher
20f0: 65 20 53 3a 20 49 6e 74 6f 3c 69 36 34 3e 20 7b e S: Into<i64> {
2100: 0a 09 09 6c 65 74 20 6f 77 6e 65 72 20 3d 20 6f ...let owner = o
2110: 77 6e 65 72 2e 69 6e 74 6f 28 29 3b 0a 0a 09 09 wner.into();....
2120: 6d 61 74 63 68 20 6d 61 74 63 68 20 75 70 64 61 match match upda
2130: 74 65 20 7b 0a 09 09 09 09 53 6f 6d 65 28 69 64 te {.....Some(id
2140: 29 20 3d 3e 20 7b 0a 09 09 09 09 09 73 71 6c 78 ) => {......sqlx
2150: 3a 3a 71 75 65 72 79 21 28 22 75 70 64 61 74 65 ::query!("update
2160: 20 72 73 73 74 67 5f 73 6f 75 72 63 65 20 73 65 rsstg_source se
2170: 74 20 63 68 61 6e 6e 65 6c 5f 69 64 20 3d 20 24 t channel_id = $
2180: 32 2c 20 75 72 6c 20 3d 20 24 33 2c 20 69 76 5f 2, url = $3, iv_
2190: 68 61 73 68 20 3d 20 24 34 2c 20 6f 77 6e 65 72 hash = $4, owner
21a0: 20 3d 20 24 35 2c 20 63 68 61 6e 6e 65 6c 20 3d = $5, channel =
21b0: 20 24 36 2c 20 75 72 6c 5f 72 65 20 3d 20 24 37 $6, url_re = $7
21c0: 20 77 68 65 72 65 20 73 6f 75 72 63 65 5f 69 64 where source_id
21d0: 20 3d 20 24 31 22 2c 0a 09 09 09 09 09 09 69 64 = $1",.......id
21e0: 2c 20 63 68 61 6e 6e 65 6c 5f 69 64 2c 20 75 72 , channel_id, ur
21f0: 6c 2c 20 69 76 5f 68 61 73 68 2c 20 6f 77 6e 65 l, iv_hash, owne
2200: 72 2c 20 63 68 61 6e 6e 65 6c 2c 20 75 72 6c 5f r, channel, url_
2210: 72 65 29 2e 65 78 65 63 75 74 65 28 26 6d 75 74 re).execute(&mut
2220: 20 73 65 6c 66 2e 70 6f 6f 6c 2e 61 63 71 75 69 self.pool.acqui
2230: 72 65 28 29 2e 61 77 61 69 74 3f 29 2e 61 77 61 re().await?).awa
2240: 69 74 0a 09 09 09 09 7d 2c 0a 09 09 09 09 4e 6f it.....},.....No
2250: 6e 65 20 3d 3e 20 7b 0a 09 09 09 09 09 73 71 6c ne => {......sql
2260: 78 3a 3a 71 75 65 72 79 21 28 22 69 6e 73 65 72 x::query!("inser
2270: 74 20 69 6e 74 6f 20 72 73 73 74 67 5f 73 6f 75 t into rsstg_sou
2280: 72 63 65 20 28 63 68 61 6e 6e 65 6c 5f 69 64 2c rce (channel_id,
2290: 20 75 72 6c 2c 20 69 76 5f 68 61 73 68 2c 20 6f url, iv_hash, o
22a0: 77 6e 65 72 2c 20 63 68 61 6e 6e 65 6c 2c 20 75 wner, channel, u
22b0: 72 6c 5f 72 65 29 20 76 61 6c 75 65 73 20 28 24 rl_re) values ($
22c0: 31 2c 20 24 32 2c 20 24 33 2c 20 24 34 2c 20 24 1, $2, $3, $4, $
22d0: 35 2c 20 24 36 29 22 2c 0a 09 09 09 09 09 09 63 5, $6)",.......c
22e0: 68 61 6e 6e 65 6c 5f 69 64 2c 20 75 72 6c 2c 20 hannel_id, url,
22f0: 69 76 5f 68 61 73 68 2c 20 6f 77 6e 65 72 2c 20 iv_hash, owner,
2300: 63 68 61 6e 6e 65 6c 2c 20 75 72 6c 5f 72 65 29 channel, url_re)
2310: 2e 65 78 65 63 75 74 65 28 26 6d 75 74 20 73 65 .execute(&mut se
2320: 6c 66 2e 70 6f 6f 6c 2e 61 63 71 75 69 72 65 28 lf.pool.acquire(
2330: 29 2e 61 77 61 69 74 3f 29 2e 61 77 61 69 74 0a ).await?).await.
2340: 09 09 09 09 7d 2c 0a 09 09 09 7d 20 7b 0a 09 09 ....},....} {...
2350: 09 4f 6b 28 5f 29 20 3d 3e 20 4f 6b 28 6d 61 74 .Ok(_) => Ok(mat
2360: 63 68 20 75 70 64 61 74 65 20 7b 0a 09 09 09 09 ch update {.....
2370: 53 6f 6d 65 28 5f 29 20 3d 3e 20 22 43 68 61 6e Some(_) => "Chan
2380: 6e 65 6c 20 75 70 64 61 74 65 64 2e 22 2c 0a 09 nel updated.",..
2390: 09 09 09 4e 6f 6e 65 20 3d 3e 20 22 43 68 61 6e ...None => "Chan
23a0: 6e 65 6c 20 61 64 64 65 64 2e 22 2c 0a 09 09 09 nel added.",....
23b0: 7d 29 2c 0a 09 09 09 45 72 72 28 73 71 6c 78 3a }),....Err(sqlx:
23c0: 3a 45 72 72 6f 72 3a 3a 44 61 74 61 62 61 73 65 :Error::Database
23d0: 28 65 72 72 29 29 20 3d 3e 20 7b 0a 09 09 09 09 (err)) => {.....
23e0: 6d 61 74 63 68 20 65 72 72 2e 64 6f 77 6e 63 61 match err.downca
23f0: 73 74 3a 3a 3c 73 71 6c 78 3a 3a 70 6f 73 74 67 st::<sqlx::postg
2400: 72 65 73 3a 3a 50 67 44 61 74 61 62 61 73 65 45 res::PgDatabaseE
2410: 72 72 6f 72 3e 28 29 2e 72 6f 75 74 69 6e 65 28 rror>().routine(
2420: 29 20 7b 0a 09 09 09 09 09 53 6f 6d 65 28 22 5f ) {......Some("_
2430: 62 74 5f 63 68 65 63 6b 5f 75 6e 69 71 75 65 22 bt_check_unique"
2440: 2c 20 29 20 3d 3e 20 7b 0a 09 09 09 09 09 09 4f , ) => {.......O
2450: 6b 28 22 44 75 70 6c 69 63 61 74 65 20 6b 65 79 k("Duplicate key
2460: 2e 22 29 0a 09 09 09 09 09 7d 2c 0a 09 09 09 09 .")......},.....
2470: 09 53 6f 6d 65 28 5f 29 20 3d 3e 20 7b 0a 09 09 .Some(_) => {...
2480: 09 09 09 09 4f 6b 28 22 44 61 74 61 62 61 73 65 ....Ok("Database
2490: 20 65 72 72 6f 72 2e 22 29 0a 09 09 09 09 09 7d error.")......}
24a0: 2c 0a 09 09 09 09 09 4e 6f 6e 65 20 3d 3e 20 7b ,......None => {
24b0: 0a 09 09 09 09 09 09 4f 6b 28 22 4e 6f 20 64 61 .......Ok("No da
24c0: 74 61 62 61 73 65 20 65 72 72 6f 72 20 65 78 74 tabase error ext
24d0: 72 61 63 74 65 64 2e 22 29 0a 09 09 09 09 09 7d racted.")......}
24e0: 2c 0a 09 09 09 09 7d 0a 09 09 09 7d 2c 0a 09 09 ,.....}....},...
24f0: 09 45 72 72 28 65 72 72 29 20 3d 3e 20 7b 0a 09 .Err(err) => {..
2500: 09 09 09 62 61 69 6c 21 28 22 53 6f 72 72 79 2c ...bail!("Sorry,
2510: 20 75 6e 6b 6e 6f 77 6e 20 65 72 72 6f 72 3a 5c unknown error:\
2520: 6e 7b 3a 23 3f 7d 5c 6e 22 2c 20 65 72 72 29 3b n{:#?}\n", err);
2530: 0a 09 09 09 7d 2c 0a 09 09 7d 0a 09 7d 0a 0a 09 ....},...}..}...
2540: 61 73 79 6e 63 20 66 6e 20 61 75 74 6f 66 65 74 async fn autofet
2550: 63 68 28 26 73 65 6c 66 29 20 2d 3e 20 52 65 73 ch(&self) -> Res
2560: 75 6c 74 3c 73 74 64 3a 3a 74 69 6d 65 3a 3a 44 ult<std::time::D
2570: 75 72 61 74 69 6f 6e 3e 20 7b 0a 09 09 6c 65 74 uration> {...let
2580: 20 6d 75 74 20 64 65 6c 61 79 20 3d 20 63 68 72 mut delay = chr
2590: 6f 6e 6f 3a 3a 44 75 72 61 74 69 6f 6e 3a 3a 6d ono::Duration::m
25a0: 69 6e 75 74 65 73 28 31 29 3b 0a 09 09 6c 65 74 inutes(1);...let
25b0: 20 6e 6f 77 20 3d 20 63 68 72 6f 6e 6f 3a 3a 4c now = chrono::L
25c0: 6f 63 61 6c 3a 3a 6e 6f 77 28 29 3b 0a 09 09 6c ocal::now();...l
25d0: 65 74 20 6d 75 74 20 71 75 65 75 65 20 3d 20 73 et mut queue = s
25e0: 71 6c 78 3a 3a 71 75 65 72 79 21 28 72 23 22 73 qlx::query!(r#"s
25f0: 65 6c 65 63 74 20 73 6f 75 72 63 65 5f 69 64 2c elect source_id,
2600: 20 6e 65 78 74 5f 66 65 74 63 68 20 61 73 20 22 next_fetch as "
2610: 6e 65 78 74 5f 66 65 74 63 68 3a 20 44 61 74 65 next_fetch: Date
2620: 54 69 6d 65 3c 63 68 72 6f 6e 6f 3a 3a 4c 6f 63 Time<chrono::Loc
2630: 61 6c 3e 22 2c 20 6f 77 6e 65 72 20 66 72 6f 6d al>", owner from
2640: 20 72 73 73 74 67 5f 6f 72 64 65 72 20 6e 61 74 rsstg_order nat
2650: 75 72 61 6c 20 6c 65 66 74 20 6a 6f 69 6e 20 72 ural left join r
2660: 73 73 74 67 5f 73 6f 75 72 63 65 20 77 68 65 72 sstg_source wher
2670: 65 20 6e 65 78 74 5f 66 65 74 63 68 20 3c 20 6e e next_fetch < n
2680: 6f 77 28 29 20 2b 20 69 6e 74 65 72 76 61 6c 20 ow() + interval
2690: 27 31 20 6d 69 6e 75 74 65 27 3b 22 23 29 0a 09 '1 minute';"#)..
26a0: 09 09 2e 66 65 74 63 68 5f 61 6c 6c 28 26 6d 75 ...fetch_all(&mu
26b0: 74 20 73 65 6c 66 2e 70 6f 6f 6c 2e 61 63 71 75 t self.pool.acqu
26c0: 69 72 65 28 29 2e 61 77 61 69 74 3f 29 2e 61 77 ire().await?).aw
26d0: 61 69 74 3f 3b 0a 09 09 66 6f 72 20 72 6f 77 20 ait?;...for row
26e0: 69 6e 20 71 75 65 75 65 2e 69 74 65 72 28 29 20 in queue.iter()
26f0: 7b 0a 09 09 09 69 66 20 6c 65 74 20 53 6f 6d 65 {....if let Some
2700: 28 6e 65 78 74 5f 66 65 74 63 68 29 20 3d 20 72 (next_fetch) = r
2710: 6f 77 2e 6e 65 78 74 5f 66 65 74 63 68 20 7b 0a ow.next_fetch {.
2720: 09 09 09 09 69 66 20 6e 65 78 74 5f 66 65 74 63 ....if next_fetc
2730: 68 20 3c 20 6e 6f 77 20 7b 0a 09 09 09 09 09 69 h < now {......i
2740: 66 20 6c 65 74 20 28 53 6f 6d 65 28 6f 77 6e 65 f let (Some(owne
2750: 72 29 2c 20 53 6f 6d 65 28 73 6f 75 72 63 65 5f r), Some(source_
2760: 69 64 29 29 20 3d 20 28 72 6f 77 2e 6f 77 6e 65 id)) = (row.owne
2770: 72 2c 20 72 6f 77 2e 73 6f 75 72 63 65 5f 69 64 r, row.source_id
2780: 29 20 7b 0a 09 09 09 09 09 09 6c 65 74 20 63 6c ) {.......let cl
2790: 6f 6e 65 20 3d 20 43 6f 72 65 20 7b 0a 09 09 09 one = Core {....
27a0: 09 09 09 09 6f 77 6e 65 72 5f 63 68 61 74 3a 20 ....owner_chat:
27b0: 74 65 6c 65 67 72 61 6d 5f 62 6f 74 3a 3a 55 73 telegram_bot::Us
27c0: 65 72 49 64 3a 3a 6e 65 77 28 6f 77 6e 65 72 29 erId::new(owner)
27d0: 2c 0a 09 09 09 09 09 09 09 2e 2e 73 65 6c 66 2e ,..........self.
27e0: 63 6c 6f 6e 65 28 29 0a 09 09 09 09 09 09 7d 3b clone().......};
27f0: 0a 09 09 09 09 09 09 74 61 73 6b 3a 3a 73 70 61 .......task::spa
2800: 77 6e 28 61 73 79 6e 63 20 6d 6f 76 65 20 7b 0a wn(async move {.
2810: 09 09 09 09 09 09 09 69 66 20 6c 65 74 20 45 72 .......if let Er
2820: 72 28 65 72 72 29 20 3d 20 63 6c 6f 6e 65 2e 63 r(err) = clone.c
2830: 68 65 63 6b 28 26 73 6f 75 72 63 65 5f 69 64 2c heck(&source_id,
2840: 20 6f 77 6e 65 72 2c 20 74 72 75 65 29 2e 61 77 owner, true).aw
2850: 61 69 74 20 7b 0a 09 09 09 09 09 09 09 09 69 66 ait {.........if
2860: 20 6c 65 74 20 45 72 72 28 65 72 72 29 20 3d 20 let Err(err) =
2870: 63 6c 6f 6e 65 2e 73 65 6e 64 28 26 66 6f 72 6d clone.send(&form
2880: 61 74 21 28 22 f0 9f 9b 91 20 7b 3a 3f 7d 22 2c at!("š {:?}",
2890: 20 65 72 72 29 2c 20 4e 6f 6e 65 2c 20 4e 6f 6e err), None, Non
28a0: 65 29 2e 61 77 61 69 74 20 7b 0a 09 09 09 09 09 e).await {......
28b0: 09 09 09 09 64 62 67 21 28 22 43 68 65 63 6b 20 ....dbg!("Check
28c0: 65 72 72 6f 72 3a 20 7b 7d 22 2c 20 65 72 72 29 error: {}", err)
28d0: 3b 0a 09 09 09 09 09 09 09 09 09 2f 2f 20 63 6c ;..........// cl
28e0: 6f 6e 65 2e 64 69 73 61 62 6c 65 28 26 73 6f 75 one.disable(&sou
28f0: 72 63 65 5f 69 64 2c 20 6f 77 6e 65 72 29 2e 61 rce_id, owner).a
2900: 77 61 69 74 2e 75 6e 77 72 61 70 28 29 3b 0a 09 wait.unwrap();..
2910: 09 09 09 09 09 09 09 7d 3b 0a 09 09 09 09 09 09 .......};.......
2920: 09 7d 3b 0a 09 09 09 09 09 09 7d 29 3b 0a 09 09 .};.......});...
2930: 09 09 09 7d 0a 09 09 09 09 7d 20 65 6c 73 65 20 ...}.....} else
2940: 69 66 20 6e 65 78 74 5f 66 65 74 63 68 20 2d 20 if next_fetch -
2950: 6e 6f 77 20 3c 20 64 65 6c 61 79 20 7b 0a 09 09 now < delay {...
2960: 09 09 09 64 65 6c 61 79 20 3d 20 6e 65 78 74 5f ...delay = next_
2970: 66 65 74 63 68 20 2d 20 6e 6f 77 3b 0a 09 09 09 fetch - now;....
2980: 09 7d 0a 09 09 09 7d 0a 09 09 7d 3b 0a 09 09 71 .}....}...};...q
2990: 75 65 75 65 2e 63 6c 65 61 72 28 29 3b 0a 09 09 ueue.clear();...
29a0: 4f 6b 28 64 65 6c 61 79 2e 74 6f 5f 73 74 64 28 Ok(delay.to_std(
29b0: 29 3f 29 0a 09 7d 0a 0a 09 70 75 62 20 61 73 79 )?)..}...pub asy
29c0: 6e 63 20 66 6e 20 6c 69 73 74 3c 53 3e 28 26 73 nc fn list<S>(&s
29d0: 65 6c 66 2c 20 6f 77 6e 65 72 3a 20 53 29 20 2d elf, owner: S) -
29e0: 3e 20 52 65 73 75 6c 74 3c 53 74 72 69 6e 67 3e > Result<String>
29f0: 0a 09 77 68 65 72 65 20 53 3a 20 49 6e 74 6f 3c ..where S: Into<
2a00: 69 36 34 3e 20 7b 0a 09 09 6c 65 74 20 6f 77 6e i64> {...let own
2a10: 65 72 20 3d 20 6f 77 6e 65 72 2e 69 6e 74 6f 28 er = owner.into(
2a20: 29 3b 0a 0a 09 09 6c 65 74 20 6d 75 74 20 72 65 );....let mut re
2a30: 70 6c 79 3a 20 56 65 63 3c 43 6f 77 3c 73 74 72 ply: Vec<Cow<str
2a40: 3e 3e 20 3d 20 76 65 63 21 5b 5d 3b 0a 09 09 72 >> = vec![];...r
2a50: 65 70 6c 79 2e 70 75 73 68 28 22 43 68 61 6e 6e eply.push("Chann
2a60: 65 6c 73 3a 22 2e 69 6e 74 6f 28 29 29 3b 0a 09 els:".into());..
2a70: 09 6c 65 74 20 72 6f 77 73 20 3d 20 73 71 6c 78 .let rows = sqlx
2a80: 3a 3a 71 75 65 72 79 21 28 22 73 65 6c 65 63 74 ::query!("select
2a90: 20 73 6f 75 72 63 65 5f 69 64 2c 20 63 68 61 6e source_id, chan
2aa0: 6e 65 6c 2c 20 65 6e 61 62 6c 65 64 2c 20 75 72 nel, enabled, ur
2ab0: 6c 2c 20 69 76 5f 68 61 73 68 2c 20 75 72 6c 5f l, iv_hash, url_
2ac0: 72 65 20 66 72 6f 6d 20 72 73 73 74 67 5f 73 6f re from rsstg_so
2ad0: 75 72 63 65 20 77 68 65 72 65 20 6f 77 6e 65 72 urce where owner
2ae0: 20 3d 20 24 31 20 6f 72 64 65 72 20 62 79 20 73 = $1 order by s
2af0: 6f 75 72 63 65 5f 69 64 22 2c 0a 09 09 09 6f 77 ource_id",....ow
2b00: 6e 65 72 29 2e 66 65 74 63 68 5f 61 6c 6c 28 26 ner).fetch_all(&
2b10: 6d 75 74 20 2a 73 65 6c 66 2e 70 6f 6f 6c 2e 61 mut *self.pool.a
2b20: 63 71 75 69 72 65 28 29 2e 61 77 61 69 74 3f 29 cquire().await?)
2b30: 2e 61 77 61 69 74 3f 3b 0a 09 09 66 6f 72 20 72 .await?;...for r
2b40: 6f 77 20 69 6e 20 72 6f 77 73 2e 69 74 65 72 28 ow in rows.iter(
2b50: 29 20 7b 0a 09 09 09 72 65 70 6c 79 2e 70 75 73 ) {....reply.pus
2b60: 68 28 66 6f 72 6d 61 74 21 28 22 5c 6e 5c 5c 23 h(format!("\n\\#
2b70: ef b8 8f e2 83 a3 20 7b 7d 20 5c 5c 2a ef b8 8f ļøā£ {} \\*ļø
2b80: e2 83 a3 20 60 7b 7d 60 20 7b 7d 5c 6e f0 9f 94 ⣠`{}` {}\nš
2b90: 97 20 60 7b 7d 60 22 2c 20 72 6f 77 2e 73 6f 75 `{}`", row.sou
2ba0: 72 63 65 5f 69 64 2c 20 72 6f 77 2e 63 68 61 6e rce_id, row.chan
2bb0: 6e 65 6c 2c 0a 09 09 09 09 6d 61 74 63 68 20 72 nel,.....match r
2bc0: 6f 77 2e 65 6e 61 62 6c 65 64 20 7b 0a 09 09 09 ow.enabled {....
2bd0: 09 09 74 72 75 65 20 20 3d 3e 20 22 f0 9f 94 84 ..true => "š
2be0: 20 65 6e 61 62 6c 65 64 22 2c 0a 09 09 09 09 09 enabled",......
2bf0: 66 61 6c 73 65 20 3d 3e 20 22 e2 9b 94 20 64 69 false => "ā di
2c00: 73 61 62 6c 65 64 22 2c 0a 09 09 09 09 7d 2c 20 sabled",.....},
2c10: 72 6f 77 2e 75 72 6c 29 2e 69 6e 74 6f 28 29 29 row.url).into())
2c20: 3b 0a 09 09 09 69 66 20 6c 65 74 20 53 6f 6d 65 ;....if let Some
2c30: 28 68 61 73 68 29 20 3d 20 26 72 6f 77 2e 69 76 (hash) = &row.iv
2c40: 5f 68 61 73 68 20 7b 0a 09 09 09 09 72 65 70 6c _hash {.....repl
2c50: 79 2e 70 75 73 68 28 66 6f 72 6d 61 74 21 28 22 y.push(format!("
2c60: 49 56 3a 20 60 7b 7d 60 22 2c 20 68 61 73 68 29 IV: `{}`", hash)
2c70: 2e 69 6e 74 6f 28 29 29 3b 0a 09 09 09 7d 0a 09 .into());....}..
2c80: 09 09 69 66 20 6c 65 74 20 53 6f 6d 65 28 72 65 ..if let Some(re
2c90: 29 20 3d 20 26 72 6f 77 2e 75 72 6c 5f 72 65 20 ) = &row.url_re
2ca0: 7b 0a 09 09 09 09 72 65 70 6c 79 2e 70 75 73 68 {.....reply.push
2cb0: 28 66 6f 72 6d 61 74 21 28 22 52 45 3a 20 60 7b (format!("RE: `{
2cc0: 7d 60 22 2c 20 72 65 29 2e 69 6e 74 6f 28 29 29 }`", re).into())
2cd0: 3b 0a 09 09 09 7d 0a 09 09 7d 3b 0a 09 09 4f 6b ;....}...};...Ok
2ce0: 28 72 65 70 6c 79 2e 6a 6f 69 6e 28 22 5c 6e 22 (reply.join("\n"
2cf0: 29 29 0a 09 7d 0a 7d 0a ))..}.}.