0000: 75 73 65 20 63 72 61 74 65 3a 3a 63 6f 6d 6d 61 use crate::comma
0010: 6e 64 3b 0a 0a 75 73 65 20 73 74 64 3a 3a 7b 0a nd;..use std::{.
0020: 09 62 6f 72 72 6f 77 3a 3a 43 6f 77 2c 0a 09 63 .borrow::Cow,..c
0030: 6f 6c 6c 65 63 74 69 6f 6e 73 3a 3a 7b 0a 09 09 ollections::{...
0040: 42 54 72 65 65 4d 61 70 2c 0a 09 09 48 61 73 68 BTreeMap,...Hash
0050: 53 65 74 2c 0a 09 7d 2c 0a 09 6e 75 6d 3a 3a 54 Set,..},..num::T
0060: 72 79 46 72 6f 6d 49 6e 74 45 72 72 6f 72 2c 0a ryFromIntError,.
0070: 09 73 79 6e 63 3a 3a 7b 0a 09 09 41 72 63 2c 0a .sync::{...Arc,.
0080: 09 09 4d 75 74 65 78 0a 09 7d 2c 0a 7d 3b 0a 0a ..Mutex..},.};..
0090: 75 73 65 20 61 6e 79 68 6f 77 3a 3a 7b 0a 09 61 use anyhow::{..a
00a0: 6e 79 68 6f 77 2c 0a 09 62 61 69 6c 2c 0a 09 52 nyhow,..bail,..R
00b0: 65 73 75 6c 74 2c 0a 7d 3b 0a 75 73 65 20 61 73 esult,.};.use as
00c0: 79 6e 63 5f 73 74 64 3a 3a 74 61 73 6b 3b 0a 75 ync_std::task;.u
00d0: 73 65 20 63 68 72 6f 6e 6f 3a 3a 44 61 74 65 54 se chrono::DateT
00e0: 69 6d 65 3b 0a 75 73 65 20 66 72 61 6e 6b 65 6e ime;.use franken
00f0: 73 74 65 69 6e 3a 3a 7b 0a 09 63 6c 69 65 6e 74 stein::{..client
0100: 5f 72 65 71 77 65 73 74 3a 3a 42 6f 74 2c 0a 09 _reqwest::Bot,..
0110: 6d 65 74 68 6f 64 73 3a 3a 7b 0a 09 09 47 65 74 methods::{...Get
0120: 55 70 64 61 74 65 73 50 61 72 61 6d 73 2c 0a 09 UpdatesParams,..
0130: 09 53 65 6e 64 4d 65 73 73 61 67 65 50 61 72 61 .SendMessagePara
0140: 6d 73 0a 09 7d 2c 0a 09 74 79 70 65 73 3a 3a 7b ms..},..types::{
0150: 0a 09 09 41 6c 6c 6f 77 65 64 55 70 64 61 74 65 ...AllowedUpdate
0160: 2c 0a 09 09 4d 65 73 73 61 67 65 45 6e 74 69 74 ,...MessageEntit
0170: 79 54 79 70 65 2c 0a 09 09 55 73 65 72 2c 0a 09 yType,...User,..
0180: 7d 2c 0a 09 75 70 64 61 74 65 73 3a 3a 55 70 64 },..updates::Upd
0190: 61 74 65 43 6f 6e 74 65 6e 74 2c 0a 09 41 73 79 ateContent,..Asy
01a0: 6e 63 54 65 6c 65 67 72 61 6d 41 70 69 2c 0a 09 ncTelegramApi,..
01b0: 50 61 72 73 65 4d 6f 64 65 2c 0a 7d 3b 0a 75 73 ParseMode,.};.us
01c0: 65 20 73 71 6c 78 3a 3a 70 6f 73 74 67 72 65 73 e sqlx::postgres
01d0: 3a 3a 50 67 50 6f 6f 6c 4f 70 74 69 6f 6e 73 3b ::PgPoolOptions;
01e0: 0a 75 73 65 20 74 68 69 73 65 72 72 6f 72 3a 3a .use thiserror::
01f0: 45 72 72 6f 72 3b 0a 0a 23 5b 64 65 72 69 76 65 Error;..#[derive
0200: 28 45 72 72 6f 72 2c 20 44 65 62 75 67 29 5d 0a (Error, Debug)].
0210: 70 75 62 20 65 6e 75 6d 20 52 73 73 45 72 72 6f pub enum RssErro
0220: 72 20 7b 0a 09 2f 2f 20 23 5b 65 72 72 6f 72 28 r {..// #[error(
0230: 74 72 61 6e 73 70 61 72 65 6e 74 29 5d 0a 09 2f transparent)]../
0240: 2f 20 54 67 28 23 5b 66 72 6f 6d 5d 20 54 67 45 / Tg(#[from] TgE
0250: 72 72 6f 72 29 2c 0a 09 23 5b 65 72 72 6f 72 28 rror),..#[error(
0260: 74 72 61 6e 73 70 61 72 65 6e 74 29 5d 0a 09 49 transparent)]..I
0270: 6e 74 28 23 5b 66 72 6f 6d 5d 20 54 72 79 46 72 nt(#[from] TryFr
0280: 6f 6d 49 6e 74 45 72 72 6f 72 29 2c 0a 7d 0a 0a omIntError),.}..
0290: 23 5b 64 65 72 69 76 65 28 43 6c 6f 6e 65 29 5d #[derive(Clone)]
02a0: 0a 70 75 62 20 73 74 72 75 63 74 20 43 6f 72 65 .pub struct Core
02b0: 20 7b 0a 09 6f 77 6e 65 72 5f 63 68 61 74 3a 20 {..owner_chat:
02c0: 69 36 34 2c 0a 09 70 75 62 20 74 67 3a 20 42 6f i64,..pub tg: Bo
02d0: 74 2c 0a 09 70 75 62 20 6d 65 3a 20 55 73 65 72 t,..pub me: User
02e0: 2c 0a 09 70 6f 6f 6c 3a 20 73 71 6c 78 3a 3a 50 ,..pool: sqlx::P
02f0: 6f 6f 6c 3c 73 71 6c 78 3a 3a 50 6f 73 74 67 72 ool<sqlx::Postgr
0300: 65 73 3e 2c 0a 09 73 6f 75 72 63 65 73 3a 20 41 es>,..sources: A
0310: 72 63 3c 4d 75 74 65 78 3c 48 61 73 68 53 65 74 rc<Mutex<HashSet
0320: 3c 41 72 63 3c 69 33 32 3e 3e 3e 3e 2c 0a 09 68 <Arc<i32>>>>,..h
0330: 74 74 70 5f 63 6c 69 65 6e 74 3a 20 72 65 71 77 ttp_client: reqw
0340: 65 73 74 3a 3a 43 6c 69 65 6e 74 2c 0a 7d 0a 0a est::Client,.}..
0350: 69 6d 70 6c 20 43 6f 72 65 20 7b 0a 09 70 75 62 impl Core {..pub
0360: 20 61 73 79 6e 63 20 66 6e 20 6e 65 77 28 73 65 async fn new(se
0370: 74 74 69 6e 67 73 3a 20 63 6f 6e 66 69 67 3a 3a ttings: config::
0380: 43 6f 6e 66 69 67 29 20 2d 3e 20 52 65 73 75 6c Config) -> Resul
0390: 74 3c 41 72 63 3c 43 6f 72 65 3e 3e 20 7b 0a 09 t<Arc<Core>> {..
03a0: 09 6c 65 74 20 6f 77 6e 65 72 5f 63 68 61 74 20 .let owner_chat
03b0: 3d 20 73 65 74 74 69 6e 67 73 2e 67 65 74 5f 69 = settings.get_i
03c0: 6e 74 28 22 6f 77 6e 65 72 22 29 3f 3b 0a 09 09 nt("owner")?;...
03d0: 6c 65 74 20 61 70 69 5f 6b 65 79 20 3d 20 73 65 let api_key = se
03e0: 74 74 69 6e 67 73 2e 67 65 74 5f 73 74 72 69 6e ttings.get_strin
03f0: 67 28 22 61 70 69 5f 6b 65 79 22 29 3f 3b 0a 09 g("api_key")?;..
0400: 09 6c 65 74 20 74 67 20 3d 20 42 6f 74 3a 3a 6e .let tg = Bot::n
0410: 65 77 28 26 61 70 69 5f 6b 65 79 29 3b 0a 0a 09 ew(&api_key);...
0420: 09 6c 65 74 20 6d 75 74 20 63 6c 69 65 6e 74 20 .let mut client
0430: 3d 20 72 65 71 77 65 73 74 3a 3a 43 6c 69 65 6e = reqwest::Clien
0440: 74 3a 3a 62 75 69 6c 64 65 72 28 29 3b 0a 09 09 t::builder();...
0450: 69 66 20 6c 65 74 20 4f 6b 28 70 72 6f 78 79 29 if let Ok(proxy)
0460: 20 3d 20 73 65 74 74 69 6e 67 73 2e 67 65 74 5f = settings.get_
0470: 73 74 72 69 6e 67 28 22 70 72 6f 78 79 22 29 20 string("proxy")
0480: 7b 0a 09 09 09 6c 65 74 20 70 72 6f 78 79 20 3d {....let proxy =
0490: 20 72 65 71 77 65 73 74 3a 3a 50 72 6f 78 79 3a reqwest::Proxy:
04a0: 3a 61 6c 6c 28 70 72 6f 78 79 29 3f 3b 0a 09 09 :all(proxy)?;...
04b0: 09 63 6c 69 65 6e 74 20 3d 20 63 6c 69 65 6e 74 .client = client
04c0: 2e 70 72 6f 78 79 28 70 72 6f 78 79 29 3b 0a 09 .proxy(proxy);..
04d0: 09 7d 0a 09 09 6c 65 74 20 68 74 74 70 5f 63 6c .}...let http_cl
04e0: 69 65 6e 74 20 3d 20 63 6c 69 65 6e 74 2e 62 75 ient = client.bu
04f0: 69 6c 64 28 29 3f 3b 0a 09 09 6c 65 74 20 6d 65 ild()?;...let me
0500: 20 3d 20 74 67 2e 67 65 74 5f 6d 65 28 29 2e 61 = tg.get_me().a
0510: 77 61 69 74 3f 3b 0a 09 09 6c 65 74 20 6d 65 20 wait?;...let me
0520: 3d 20 6d 65 2e 72 65 73 75 6c 74 3b 0a 09 09 6c = me.result;...l
0530: 65 74 20 63 6f 72 65 20 3d 20 41 72 63 3a 3a 6e et core = Arc::n
0540: 65 77 28 43 6f 72 65 20 7b 0a 09 09 09 74 67 2c ew(Core {....tg,
0550: 0a 09 09 09 6d 65 2c 0a 09 09 09 6f 77 6e 65 72 ....me,....owner
0560: 5f 63 68 61 74 2c 0a 09 09 09 70 6f 6f 6c 3a 20 _chat,....pool:
0570: 50 67 50 6f 6f 6c 4f 70 74 69 6f 6e 73 3a 3a 6e PgPoolOptions::n
0580: 65 77 28 29 0a 09 09 09 09 2e 6d 61 78 5f 63 6f ew()......max_co
0590: 6e 6e 65 63 74 69 6f 6e 73 28 35 29 0a 09 09 09 nnections(5)....
05a0: 09 2e 61 63 71 75 69 72 65 5f 74 69 6d 65 6f 75 ..acquire_timeou
05b0: 74 28 73 74 64 3a 3a 74 69 6d 65 3a 3a 44 75 72 t(std::time::Dur
05c0: 61 74 69 6f 6e 3a 3a 6e 65 77 28 33 30 30 2c 20 ation::new(300,
05d0: 30 29 29 0a 09 09 09 09 2e 69 64 6c 65 5f 74 69 0))......idle_ti
05e0: 6d 65 6f 75 74 28 73 74 64 3a 3a 74 69 6d 65 3a meout(std::time:
05f0: 3a 44 75 72 61 74 69 6f 6e 3a 3a 6e 65 77 28 36 :Duration::new(6
0600: 30 2c 20 30 29 29 0a 09 09 09 09 2e 63 6f 6e 6e 0, 0))......conn
0610: 65 63 74 5f 6c 61 7a 79 28 26 73 65 74 74 69 6e ect_lazy(&settin
0620: 67 73 2e 67 65 74 5f 73 74 72 69 6e 67 28 22 70 gs.get_string("p
0630: 67 22 29 3f 29 3f 2c 0a 09 09 09 73 6f 75 72 63 g")?)?,....sourc
0640: 65 73 3a 20 41 72 63 3a 3a 6e 65 77 28 4d 75 74 es: Arc::new(Mut
0650: 65 78 3a 3a 6e 65 77 28 48 61 73 68 53 65 74 3a ex::new(HashSet:
0660: 3a 6e 65 77 28 29 29 29 2c 0a 09 09 09 68 74 74 :new())),....htt
0670: 70 5f 63 6c 69 65 6e 74 2c 0a 09 09 7d 29 3b 0a p_client,...});.
0680: 09 09 6c 65 74 20 63 6c 6f 6e 65 20 3d 20 63 6f ..let clone = co
0690: 72 65 2e 63 6c 6f 6e 65 28 29 3b 0a 09 09 74 61 re.clone();...ta
06a0: 73 6b 3a 3a 73 70 61 77 6e 28 61 73 79 6e 63 20 sk::spawn(async
06b0: 6d 6f 76 65 20 7b 0a 09 09 09 6c 6f 6f 70 20 7b move {....loop {
06c0: 0a 09 09 09 09 6c 65 74 20 64 65 6c 61 79 20 3d .....let delay =
06d0: 20 6d 61 74 63 68 20 26 63 6c 6f 6e 65 2e 61 75 match &clone.au
06e0: 74 6f 66 65 74 63 68 28 29 2e 61 77 61 69 74 20 tofetch().await
06f0: 7b 0a 09 09 09 09 09 45 72 72 28 65 72 72 29 20 {......Err(err)
0700: 3d 3e 20 7b 0a 09 09 09 09 09 09 69 66 20 6c 65 => {.......if le
0710: 74 20 45 72 72 28 65 72 72 29 20 3d 20 63 6c 6f t Err(err) = clo
0720: 6e 65 2e 73 65 6e 64 28 66 6f 72 6d 61 74 21 28 ne.send(format!(
0730: 22 f0 9f 9b 91 20 7b 65 72 72 3a 3f 7d 22 29 2c "š {err:?}"),
0740: 20 4e 6f 6e 65 2c 20 4e 6f 6e 65 29 2e 61 77 61 None, None).awa
0750: 69 74 20 7b 0a 09 09 09 09 09 09 09 65 70 72 69 it {........epri
0760: 6e 74 6c 6e 21 28 22 41 75 74 6f 66 65 74 63 68 ntln!("Autofetch
0770: 20 65 72 72 6f 72 3a 20 7b 65 72 72 3a 3f 7d 22 error: {err:?}"
0780: 29 3b 0a 09 09 09 09 09 09 7d 3b 0a 09 09 09 09 );.......};.....
0790: 09 09 73 74 64 3a 3a 74 69 6d 65 3a 3a 44 75 72 ..std::time::Dur
07a0: 61 74 69 6f 6e 3a 3a 66 72 6f 6d 5f 73 65 63 73 ation::from_secs
07b0: 28 36 30 29 0a 09 09 09 09 09 7d 2c 0a 09 09 09 (60)......},....
07c0: 09 09 4f 6b 28 74 69 6d 65 29 20 3d 3e 20 2a 74 ..Ok(time) => *t
07d0: 69 6d 65 2c 0a 09 09 09 09 7d 3b 0a 09 09 09 09 ime,.....};.....
07e0: 74 61 73 6b 3a 3a 73 6c 65 65 70 28 64 65 6c 61 task::sleep(dela
07f0: 79 29 2e 61 77 61 69 74 3b 0a 09 09 09 7d 0a 09 y).await;....}..
0800: 09 7d 29 3b 0a 09 09 4f 6b 28 63 6f 72 65 29 0a .});...Ok(core).
0810: 09 7d 0a 0a 09 70 75 62 20 61 73 79 6e 63 20 66 .}...pub async f
0820: 6e 20 73 74 72 65 61 6d 28 26 73 65 6c 66 29 20 n stream(&self)
0830: 2d 3e 20 52 65 73 75 6c 74 3c 28 29 3e 20 7b 0a -> Result<()> {.
0840: 09 09 6c 65 74 20 6d 75 74 20 6f 66 66 73 65 74 ..let mut offset
0850: 3a 20 69 36 34 20 3d 20 30 3b 0a 09 09 6c 65 74 : i64 = 0;...let
0860: 20 6d 75 74 20 70 61 72 61 6d 73 20 3d 20 47 65 mut params = Ge
0870: 74 55 70 64 61 74 65 73 50 61 72 61 6d 73 20 7b tUpdatesParams {
0880: 0a 09 09 09 6f 66 66 73 65 74 3a 20 4e 6f 6e 65 ....offset: None
0890: 2c 0a 09 09 09 6c 69 6d 69 74 3a 20 53 6f 6d 65 ,....limit: Some
08a0: 28 31 30 30 29 2c 0a 09 09 09 74 69 6d 65 6f 75 (100),....timeou
08b0: 74 3a 20 53 6f 6d 65 28 33 30 30 29 2c 0a 09 09 t: Some(300),...
08c0: 09 61 6c 6c 6f 77 65 64 5f 75 70 64 61 74 65 73 .allowed_updates
08d0: 3a 20 53 6f 6d 65 28 76 65 63 21 5b 41 6c 6c 6f : Some(vec![Allo
08e0: 77 65 64 55 70 64 61 74 65 3a 3a 4d 65 73 73 61 wedUpdate::Messa
08f0: 67 65 5d 29 2c 0a 09 09 7d 3b 0a 09 09 6c 6f 6f ge]),...};...loo
0900: 70 20 7b 0a 09 09 09 6c 65 74 20 75 70 64 61 74 p {....let updat
0910: 65 73 20 3d 20 73 65 6c 66 2e 74 67 2e 67 65 74 es = self.tg.get
0920: 5f 75 70 64 61 74 65 73 28 26 70 61 72 61 6d 73 _updates(¶ms
0930: 29 2e 61 77 61 69 74 3f 2e 72 65 73 75 6c 74 3b ).await?.result;
0940: 0a 09 09 09 69 66 20 75 70 64 61 74 65 73 2e 69 ....if updates.i
0950: 73 5f 65 6d 70 74 79 28 29 20 7b 0a 09 09 09 09 s_empty() {.....
0960: 6f 66 66 73 65 74 20 3d 20 30 3b 0a 09 09 09 09 offset = 0;.....
0970: 70 61 72 61 6d 73 2e 6f 66 66 73 65 74 20 3d 20 params.offset =
0980: 4e 6f 6e 65 3b 0a 09 09 09 09 63 6f 6e 74 69 6e None;.....contin
0990: 75 65 3b 0a 09 09 09 7d 0a 09 09 09 66 6f 72 20 ue;....}....for
09a0: 75 70 64 61 74 65 20 69 6e 20 75 70 64 61 74 65 update in update
09b0: 73 20 7b 0a 09 09 09 09 69 66 20 69 36 34 3a 3a s {.....if i64::
09c0: 66 72 6f 6d 28 75 70 64 61 74 65 2e 75 70 64 61 from(update.upda
09d0: 74 65 5f 69 64 29 20 3e 3d 20 6f 66 66 73 65 74 te_id) >= offset
09e0: 20 7b 0a 09 09 09 09 09 6f 66 66 73 65 74 20 3d {......offset =
09f0: 20 69 36 34 3a 3a 66 72 6f 6d 28 75 70 64 61 74 i64::from(updat
0a00: 65 2e 75 70 64 61 74 65 5f 69 64 29 20 2b 20 31 e.update_id) + 1
0a10: 3b 0a 09 09 09 09 09 70 61 72 61 6d 73 2e 6f 66 ;......params.of
0a20: 66 73 65 74 20 3d 20 53 6f 6d 65 28 6f 66 66 73 fset = Some(offs
0a30: 65 74 29 3b 0a 09 09 09 09 7d 0a 09 09 09 09 69 et);.....}.....i
0a40: 66 20 6c 65 74 20 55 70 64 61 74 65 43 6f 6e 74 f let UpdateCont
0a50: 65 6e 74 3a 3a 4d 65 73 73 61 67 65 28 6d 73 67 ent::Message(msg
0a60: 29 20 3d 20 75 70 64 61 74 65 2e 63 6f 6e 74 65 ) = update.conte
0a70: 6e 74 20 7b 0a 09 09 09 09 09 69 66 20 6c 65 74 nt {......if let
0a80: 20 53 6f 6d 65 28 74 65 78 74 29 20 3d 20 6d 73 Some(text) = ms
0a90: 67 2e 74 65 78 74 20 7b 0a 09 09 09 09 09 09 69 g.text {.......i
0aa0: 66 20 6c 65 74 20 53 6f 6d 65 28 65 6e 74 69 74 f let Some(entit
0ab0: 69 65 73 29 20 3d 20 6d 73 67 2e 65 6e 74 69 74 ies) = msg.entit
0ac0: 69 65 73 20 7b 0a 09 09 09 09 09 09 09 6c 65 74 ies {........let
0ad0: 20 63 68 61 72 73 3a 20 56 65 63 3c 75 31 36 3e chars: Vec<u16>
0ae0: 20 3d 20 74 65 78 74 2e 65 6e 63 6f 64 65 5f 75 = text.encode_u
0af0: 74 66 31 36 28 29 2e 63 6f 6c 6c 65 63 74 28 29 tf16().collect()
0b00: 3b 0a 09 09 09 09 09 09 09 66 6f 72 20 65 6e 74 ;........for ent
0b10: 69 74 79 20 69 6e 20 65 6e 74 69 74 69 65 73 20 ity in entities
0b20: 7b 0a 09 09 09 09 09 09 09 09 69 66 20 65 6e 74 {.........if ent
0b30: 69 74 79 2e 74 79 70 65 5f 66 69 65 6c 64 20 3d ity.type_field =
0b40: 3d 20 4d 65 73 73 61 67 65 45 6e 74 69 74 79 54 = MessageEntityT
0b50: 79 70 65 3a 3a 42 6f 74 43 6f 6d 6d 61 6e 64 20 ype::BotCommand
0b60: 26 26 20 65 6e 74 69 74 79 2e 6f 66 66 73 65 74 && entity.offset
0b70: 20 21 3d 20 30 20 7b 0a 09 09 09 09 09 09 09 09 != 0 {.........
0b80: 09 62 61 69 6c 21 28 22 63 6f 6d 6d 61 6e 64 73 .bail!("commands
0b90: 20 73 68 6f 75 6c 64 20 62 65 20 61 74 20 6d 65 should be at me
0ba0: 73 73 61 67 65 20 73 74 61 72 74 22 29 3b 0a 09 ssage start");..
0bb0: 09 09 09 09 09 09 09 7d 3b 0a 09 09 09 09 09 09 .......};.......
0bc0: 09 09 6c 65 74 20 63 6d 64 20 3d 20 53 74 72 69 ..let cmd = Stri
0bd0: 6e 67 3a 3a 66 72 6f 6d 5f 75 74 66 31 36 5f 6c ng::from_utf16_l
0be0: 6f 73 73 79 28 26 63 68 61 72 73 5b 65 6e 74 69 ossy(&chars[enti
0bf0: 74 79 2e 6f 66 66 73 65 74 20 61 73 20 75 73 69 ty.offset as usi
0c00: 7a 65 2e 2e 65 6e 74 69 74 79 2e 6c 65 6e 67 74 ze..entity.lengt
0c10: 68 20 61 73 20 75 73 69 7a 65 5d 29 3b 0a 09 09 h as usize]);...
0c20: 09 09 09 09 09 09 6c 65 74 20 77 6f 72 64 73 3a ......let words:
0c30: 20 56 65 63 3c 26 73 74 72 3e 20 3d 20 74 65 78 Vec<&str> = tex
0c40: 74 2e 73 70 6c 69 74 5f 77 68 69 74 65 73 70 61 t.split_whitespa
0c50: 63 65 28 29 2e 63 6f 6c 6c 65 63 74 28 29 3b 0a ce().collect();.
0c60: 09 09 09 09 09 09 09 09 6d 61 74 63 68 20 63 6d ........match cm
0c70: 64 2e 61 73 5f 72 65 66 28 29 20 7b 0a 09 09 09 d.as_ref() {....
0c80: 09 09 09 09 09 09 22 2f 63 68 65 63 6b 22 20 7c ......"/check" |
0c90: 20 22 2f 63 6c 65 61 6e 22 20 7c 20 22 2f 65 6e "/clean" | "/en
0ca0: 61 62 6c 65 22 20 7c 20 22 2f 64 65 6c 65 74 65 able" | "/delete
0cb0: 22 20 7c 20 22 2f 64 69 73 61 62 6c 65 22 20 3d " | "/disable" =
0cc0: 3e 20 7b 20 63 6f 6d 6d 61 6e 64 3a 3a 63 6f 6d > { command::com
0cd0: 6d 61 6e 64 28 73 65 6c 66 2c 20 6d 73 67 2e 63 mand(self, msg.c
0ce0: 68 61 74 2e 69 64 2c 20 77 6f 72 64 73 29 2e 61 hat.id, words).a
0cf0: 77 61 69 74 3f 20 7d 2c 0a 09 09 09 09 09 09 09 wait? },........
0d00: 09 09 22 2f 73 74 61 72 74 22 20 3d 3e 20 7b 20 .."/start" => {
0d10: 63 6f 6d 6d 61 6e 64 3a 3a 73 74 61 72 74 28 73 command::start(s
0d20: 65 6c 66 2c 20 6d 73 67 2e 63 68 61 74 2e 69 64 elf, msg.chat.id
0d30: 29 2e 61 77 61 69 74 3f 3b 20 7d 2c 0a 09 09 09 ).await?; },....
0d40: 09 09 09 09 09 09 22 2f 6c 69 73 74 22 20 3d 3e ......"/list" =>
0d50: 20 7b 20 63 6f 6d 6d 61 6e 64 3a 3a 6c 69 73 74 { command::list
0d60: 28 73 65 6c 66 2c 20 6d 73 67 2e 63 68 61 74 2e (self, msg.chat.
0d70: 69 64 29 2e 61 77 61 69 74 3f 3b 20 7d 2c 0a 09 id).await?; },..
0d80: 09 09 09 09 09 09 09 09 22 2f 61 64 64 22 20 7c ........"/add" |
0d90: 20 22 2f 75 70 64 61 74 65 22 20 3d 3e 20 7b 20 "/update" => {
0da0: 63 6f 6d 6d 61 6e 64 3a 3a 75 70 64 61 74 65 28 command::update(
0db0: 73 65 6c 66 2c 20 6d 73 67 2e 63 68 61 74 2e 69 self, msg.chat.i
0dc0: 64 2c 20 77 6f 72 64 73 29 2e 61 77 61 69 74 3f d, words).await?
0dd0: 3b 20 7d 2c 0a 09 09 09 09 09 09 09 09 09 61 6e ; },..........an
0de0: 79 20 3d 3e 20 7b 0a 09 09 09 09 09 09 09 09 09 y => {..........
0df0: 09 73 65 6c 66 2e 73 65 6e 64 28 66 6f 72 6d 61 .self.send(forma
0e00: 74 21 28 22 5c 5c 23 65 72 72 6f 72 5c 6e 60 60 t!("\\#error\n``
0e10: 60 5c 6e 55 6e 6b 6e 6f 77 6e 20 63 6f 6d 6d 61 `\nUnknown comma
0e20: 6e 64 3a 20 7b 61 6e 79 7d 5c 6e 60 60 60 22 29 nd: {any}\n```")
0e30: 2c 0a 09 09 09 09 09 09 09 09 09 09 09 53 6f 6d ,............Som
0e40: 65 28 6d 73 67 2e 63 68 61 74 2e 69 64 29 2c 0a e(msg.chat.id),.
0e50: 09 09 09 09 09 09 09 09 09 09 09 53 6f 6d 65 28 ...........Some(
0e60: 50 61 72 73 65 4d 6f 64 65 3a 3a 4d 61 72 6b 64 ParseMode::Markd
0e70: 6f 77 6e 56 32 29 0a 09 09 09 09 09 09 09 09 09 ownV2)..........
0e80: 09 29 2e 61 77 61 69 74 3f 3b 0a 09 09 09 09 09 .).await?;......
0e90: 09 09 09 09 7d 2c 0a 09 09 09 09 09 09 09 09 7d ....},.........}
0ea0: 3b 0a 09 09 09 09 09 09 09 7d 3b 0a 09 09 09 09 ;........};.....
0eb0: 09 09 7d 3b 0a 09 09 09 09 09 7d 3b 0a 09 09 09 ..};......};....
0ec0: 09 7d 3b 0a 09 09 09 7d 0a 09 09 7d 0a 09 7d 0a .};....}...}..}.
0ed0: 0a 09 70 75 62 20 61 73 79 6e 63 20 66 6e 20 73 ..pub async fn s
0ee0: 65 6e 64 20 3c 53 3e 28 26 73 65 6c 66 2c 20 6d end <S>(&self, m
0ef0: 73 67 3a 20 53 2c 20 74 61 72 67 65 74 3a 20 4f sg: S, target: O
0f00: 70 74 69 6f 6e 3c 69 36 34 3e 2c 20 6d 6f 64 65 ption<i64>, mode
0f10: 3a 20 4f 70 74 69 6f 6e 3c 50 61 72 73 65 4d 6f : Option<ParseMo
0f20: 64 65 3e 29 20 2d 3e 20 52 65 73 75 6c 74 3c 28 de>) -> Result<(
0f30: 29 3e 0a 09 77 68 65 72 65 20 53 3a 20 49 6e 74 )>..where S: Int
0f40: 6f 3c 53 74 72 69 6e 67 3e 20 7b 0a 09 09 6c 65 o<String> {...le
0f50: 74 20 6d 73 67 20 3d 20 6d 73 67 2e 69 6e 74 6f t msg = msg.into
0f60: 28 29 3b 0a 0a 09 09 6c 65 74 20 6d 6f 64 65 20 ();....let mode
0f70: 3d 20 6d 6f 64 65 2e 75 6e 77 72 61 70 5f 6f 72 = mode.unwrap_or
0f80: 28 50 61 72 73 65 4d 6f 64 65 3a 3a 48 74 6d 6c (ParseMode::Html
0f90: 29 3b 0a 09 09 6c 65 74 20 74 61 72 67 65 74 20 );...let target
0fa0: 3d 20 74 61 72 67 65 74 2e 75 6e 77 72 61 70 5f = target.unwrap_
0fb0: 6f 72 28 73 65 6c 66 2e 6f 77 6e 65 72 5f 63 68 or(self.owner_ch
0fc0: 61 74 29 3b 0a 09 09 6c 65 74 20 73 65 6e 64 20 at);...let send
0fd0: 3d 20 53 65 6e 64 4d 65 73 73 61 67 65 50 61 72 = SendMessagePar
0fe0: 61 6d 73 3a 3a 62 75 69 6c 64 65 72 28 29 0a 09 ams::builder()..
0ff0: 09 09 2e 63 68 61 74 5f 69 64 28 74 61 72 67 65 ...chat_id(targe
1000: 74 29 0a 09 09 09 2e 74 65 78 74 28 6d 73 67 29 t).....text(msg)
1010: 0a 09 09 09 2e 70 61 72 73 65 5f 6d 6f 64 65 28 .....parse_mode(
1020: 6d 6f 64 65 29 0a 09 09 09 2e 62 75 69 6c 64 28 mode).....build(
1030: 29 3b 0a 09 09 73 65 6c 66 2e 74 67 2e 73 65 6e );...self.tg.sen
1040: 64 5f 6d 65 73 73 61 67 65 28 26 73 65 6e 64 29 d_message(&send)
1050: 2e 61 77 61 69 74 3f 3b 0a 09 09 4f 6b 28 28 29 .await?;...Ok(()
1060: 29 0a 09 7d 0a 0a 09 70 75 62 20 61 73 79 6e 63 )..}...pub async
1070: 20 66 6e 20 63 68 65 63 6b 20 28 26 73 65 6c 66 fn check (&self
1080: 2c 20 69 64 3a 20 26 69 33 32 2c 20 6f 77 6e 65 , id: &i32, owne
1090: 72 3a 20 69 36 34 2c 20 72 65 61 6c 3a 20 62 6f r: i64, real: bo
10a0: 6f 6c 29 20 2d 3e 20 52 65 73 75 6c 74 3c 43 6f ol) -> Result<Co
10b0: 77 3c 27 5f 2c 20 73 74 72 3e 3e 20 7b 0a 09 09 w<'_, str>> {...
10c0: 6c 65 74 20 6d 75 74 20 70 6f 73 74 65 64 3a 20 let mut posted:
10d0: 69 33 32 20 3d 20 30 3b 0a 09 09 6c 65 74 20 6d i32 = 0;...let m
10e0: 75 74 20 63 6f 6e 6e 20 3d 20 73 65 6c 66 2e 70 ut conn = self.p
10f0: 6f 6f 6c 2e 61 63 71 75 69 72 65 28 29 2e 61 77 ool.acquire().aw
1100: 61 69 74 3f 3b 0a 0a 09 09 6c 65 74 20 69 64 20 ait?;....let id
1110: 3d 20 7b 0a 09 09 09 6c 65 74 20 6d 75 74 20 73 = {....let mut s
1120: 65 74 20 3d 20 73 65 6c 66 2e 73 6f 75 72 63 65 et = self.source
1130: 73 2e 6c 6f 63 6b 28 29 2e 75 6e 77 72 61 70 28 s.lock().unwrap(
1140: 29 3b 0a 09 09 09 6d 61 74 63 68 20 73 65 74 2e );....match set.
1150: 67 65 74 28 69 64 29 20 7b 0a 09 09 09 09 53 6f get(id) {.....So
1160: 6d 65 28 69 64 29 20 3d 3e 20 69 64 2e 63 6c 6f me(id) => id.clo
1170: 6e 65 28 29 2c 0a 09 09 09 09 4e 6f 6e 65 20 3d ne(),.....None =
1180: 3e 20 7b 0a 09 09 09 09 09 6c 65 74 20 69 64 20 > {......let id
1190: 3d 20 41 72 63 3a 3a 6e 65 77 28 2a 69 64 29 3b = Arc::new(*id);
11a0: 0a 09 09 09 09 09 73 65 74 2e 69 6e 73 65 72 74 ......set.insert
11b0: 28 69 64 2e 63 6c 6f 6e 65 28 29 29 3b 0a 09 09 (id.clone());...
11c0: 09 09 09 69 64 2e 63 6c 6f 6e 65 28 29 0a 09 09 ...id.clone()...
11d0: 09 09 7d 2c 0a 09 09 09 7d 0a 09 09 7d 3b 0a 09 ..},....}...};..
11e0: 09 6c 65 74 20 63 6f 75 6e 74 20 3d 20 41 72 63 .let count = Arc
11f0: 3a 3a 73 74 72 6f 6e 67 5f 63 6f 75 6e 74 28 26 ::strong_count(&
1200: 69 64 29 3b 0a 09 09 69 66 20 63 6f 75 6e 74 20 id);...if count
1210: 3d 3d 20 32 20 7b 0a 09 09 09 6c 65 74 20 73 6f == 2 {....let so
1220: 75 72 63 65 20 3d 20 73 71 6c 78 3a 3a 71 75 65 urce = sqlx::que
1230: 72 79 21 28 22 73 65 6c 65 63 74 20 73 6f 75 72 ry!("select sour
1240: 63 65 5f 69 64 2c 20 63 68 61 6e 6e 65 6c 5f 69 ce_id, channel_i
1250: 64 2c 20 75 72 6c 2c 20 69 76 5f 68 61 73 68 2c d, url, iv_hash,
1260: 20 6f 77 6e 65 72 2c 20 75 72 6c 5f 72 65 20 66 owner, url_re f
1270: 72 6f 6d 20 72 73 73 74 67 5f 73 6f 75 72 63 65 rom rsstg_source
1280: 20 77 68 65 72 65 20 73 6f 75 72 63 65 5f 69 64 where source_id
1290: 20 3d 20 24 31 20 61 6e 64 20 6f 77 6e 65 72 20 = $1 and owner
12a0: 3d 20 24 32 22 2c 0a 09 09 09 09 2a 69 64 2c 20 = $2",.....*id,
12b0: 6f 77 6e 65 72 29 2e 66 65 74 63 68 5f 6f 6e 65 owner).fetch_one
12c0: 28 26 6d 75 74 20 2a 63 6f 6e 6e 29 2e 61 77 61 (&mut *conn).awa
12d0: 69 74 3f 3b 0a 09 09 09 6c 65 74 20 64 65 73 74 it?;....let dest
12e0: 69 6e 61 74 69 6f 6e 20 3d 20 6d 61 74 63 68 20 ination = match
12f0: 72 65 61 6c 20 7b 0a 09 09 09 09 74 72 75 65 20 real {.....true
1300: 3d 3e 20 73 6f 75 72 63 65 2e 63 68 61 6e 6e 65 => source.channe
1310: 6c 5f 69 64 2c 0a 09 09 09 09 66 61 6c 73 65 20 l_id,.....false
1320: 3d 3e 20 73 6f 75 72 63 65 2e 6f 77 6e 65 72 2c => source.owner,
1330: 0a 09 09 09 7d 3b 0a 09 09 09 6c 65 74 20 6d 75 ....};....let mu
1340: 74 20 74 68 69 73 5f 66 65 74 63 68 3a 20 4f 70 t this_fetch: Op
1350: 74 69 6f 6e 3c 44 61 74 65 54 69 6d 65 3c 63 68 tion<DateTime<ch
1360: 72 6f 6e 6f 3a 3a 46 69 78 65 64 4f 66 66 73 65 rono::FixedOffse
1370: 74 3e 3e 20 3d 20 4e 6f 6e 65 3b 0a 09 09 09 6c t>> = None;....l
1380: 65 74 20 6d 75 74 20 70 6f 73 74 73 3a 20 42 54 et mut posts: BT
1390: 72 65 65 4d 61 70 3c 44 61 74 65 54 69 6d 65 3c reeMap<DateTime<
13a0: 63 68 72 6f 6e 6f 3a 3a 46 69 78 65 64 4f 66 66 chrono::FixedOff
13b0: 73 65 74 3e 2c 20 53 74 72 69 6e 67 3e 20 3d 20 set>, String> =
13c0: 42 54 72 65 65 4d 61 70 3a 3a 6e 65 77 28 29 3b BTreeMap::new();
13d0: 0a 0a 09 09 09 6c 65 74 20 72 65 73 70 6f 6e 73 .....let respons
13e0: 65 20 3d 20 73 65 6c 66 2e 68 74 74 70 5f 63 6c e = self.http_cl
13f0: 69 65 6e 74 2e 67 65 74 28 26 73 6f 75 72 63 65 ient.get(&source
1400: 2e 75 72 6c 29 2e 73 65 6e 64 28 29 2e 61 77 61 .url).send().awa
1410: 69 74 3f 3b 0a 09 09 09 6c 65 74 20 73 74 61 74 it?;....let stat
1420: 75 73 20 3d 20 72 65 73 70 6f 6e 73 65 2e 73 74 us = response.st
1430: 61 74 75 73 28 29 3b 0a 09 09 09 6c 65 74 20 63 atus();....let c
1440: 6f 6e 74 65 6e 74 20 3d 20 72 65 73 70 6f 6e 73 ontent = respons
1450: 65 2e 62 79 74 65 73 28 29 2e 61 77 61 69 74 3f e.bytes().await?
1460: 3b 0a 09 09 09 6d 61 74 63 68 20 72 73 73 3a 3a ;....match rss::
1470: 43 68 61 6e 6e 65 6c 3a 3a 72 65 61 64 5f 66 72 Channel::read_fr
1480: 6f 6d 28 26 63 6f 6e 74 65 6e 74 5b 2e 2e 5d 29 om(&content[..])
1490: 20 7b 0a 09 09 09 09 4f 6b 28 66 65 65 64 29 20 {.....Ok(feed)
14a0: 3d 3e 20 7b 0a 09 09 09 09 09 66 6f 72 20 69 74 => {......for it
14b0: 65 6d 20 69 6e 20 66 65 65 64 2e 69 74 65 6d 73 em in feed.items
14c0: 28 29 20 7b 0a 09 09 09 09 09 09 69 66 20 6c 65 () {.......if le
14d0: 74 20 53 6f 6d 65 28 6c 69 6e 6b 29 20 3d 20 69 t Some(link) = i
14e0: 74 65 6d 2e 6c 69 6e 6b 28 29 20 7b 0a 09 09 09 tem.link() {....
14f0: 09 09 09 09 6c 65 74 20 64 61 74 65 20 3d 20 6d ....let date = m
1500: 61 74 63 68 20 69 74 65 6d 2e 70 75 62 5f 64 61 atch item.pub_da
1510: 74 65 28 29 20 7b 0a 09 09 09 09 09 09 09 09 53 te() {.........S
1520: 6f 6d 65 28 66 65 65 64 5f 64 61 74 65 29 20 3d ome(feed_date) =
1530: 3e 20 44 61 74 65 54 69 6d 65 3a 3a 70 61 72 73 > DateTime::pars
1540: 65 5f 66 72 6f 6d 5f 72 66 63 32 38 32 32 28 66 e_from_rfc2822(f
1550: 65 65 64 5f 64 61 74 65 29 2c 0a 09 09 09 09 09 eed_date),......
1560: 09 09 09 4e 6f 6e 65 20 3d 3e 20 44 61 74 65 54 ...None => DateT
1570: 69 6d 65 3a 3a 70 61 72 73 65 5f 66 72 6f 6d 5f ime::parse_from_
1580: 72 66 63 33 33 33 39 28 26 69 74 65 6d 2e 64 75 rfc3339(&item.du
1590: 62 6c 69 6e 5f 63 6f 72 65 5f 65 78 74 28 29 2e blin_core_ext().
15a0: 75 6e 77 72 61 70 28 29 2e 64 61 74 65 73 28 29 unwrap().dates()
15b0: 5b 30 5d 29 2c 0a 09 09 09 09 09 09 09 7d 3f 3b [0]),........}?;
15c0: 0a 09 09 09 09 09 09 09 6c 65 74 20 75 72 6c 20 ........let url
15d0: 3d 20 6c 69 6e 6b 3b 0a 09 09 09 09 09 09 09 70 = link;........p
15e0: 6f 73 74 73 2e 69 6e 73 65 72 74 28 64 61 74 65 osts.insert(date
15f0: 2c 20 75 72 6c 2e 74 6f 5f 73 74 72 69 6e 67 28 , url.to_string(
1600: 29 29 3b 0a 09 09 09 09 09 09 7d 0a 09 09 09 09 ));.......}.....
1610: 09 7d 3b 0a 09 09 09 09 7d 2c 0a 09 09 09 09 45 .};.....},.....E
1620: 72 72 28 65 72 72 29 20 3d 3e 20 6d 61 74 63 68 rr(err) => match
1630: 20 65 72 72 20 7b 0a 09 09 09 09 09 72 73 73 3a err {......rss:
1640: 3a 45 72 72 6f 72 3a 3a 49 6e 76 61 6c 69 64 53 :Error::InvalidS
1650: 74 61 72 74 54 61 67 20 3d 3e 20 7b 0a 09 09 09 tartTag => {....
1660: 09 09 09 6d 61 74 63 68 20 61 74 6f 6d 5f 73 79 ...match atom_sy
1670: 6e 64 69 63 61 74 69 6f 6e 3a 3a 46 65 65 64 3a ndication::Feed:
1680: 3a 72 65 61 64 5f 66 72 6f 6d 28 26 63 6f 6e 74 :read_from(&cont
1690: 65 6e 74 5b 2e 2e 5d 29 20 7b 0a 09 09 09 09 09 ent[..]) {......
16a0: 09 09 4f 6b 28 66 65 65 64 29 20 3d 3e 20 7b 0a ..Ok(feed) => {.
16b0: 09 09 09 09 09 09 09 09 66 6f 72 20 69 74 65 6d ........for item
16c0: 20 69 6e 20 66 65 65 64 2e 65 6e 74 72 69 65 73 in feed.entries
16d0: 28 29 20 7b 0a 09 09 09 09 09 09 09 09 09 6c 65 () {..........le
16e0: 74 20 64 61 74 65 20 3d 20 69 74 65 6d 2e 70 75 t date = item.pu
16f0: 62 6c 69 73 68 65 64 28 29 2e 75 6e 77 72 61 70 blished().unwrap
1700: 28 29 3b 0a 09 09 09 09 09 09 09 09 09 6c 65 74 ();..........let
1710: 20 75 72 6c 20 3d 20 69 74 65 6d 2e 6c 69 6e 6b url = item.link
1720: 73 28 29 5b 30 5d 2e 68 72 65 66 28 29 3b 0a 09 s()[0].href();..
1730: 09 09 09 09 09 09 09 09 70 6f 73 74 73 2e 69 6e ........posts.in
1740: 73 65 72 74 28 2a 64 61 74 65 2c 20 75 72 6c 2e sert(*date, url.
1750: 74 6f 5f 73 74 72 69 6e 67 28 29 29 3b 0a 09 09 to_string());...
1760: 09 09 09 09 09 09 7d 3b 0a 09 09 09 09 09 09 09 ......};........
1770: 7d 2c 0a 09 09 09 09 09 09 09 45 72 72 28 65 72 },........Err(er
1780: 72 29 20 3d 3e 20 7b 0a 09 09 09 09 09 09 09 09 r) => {.........
1790: 62 61 69 6c 21 28 22 55 6e 73 75 70 70 6f 72 74 bail!("Unsupport
17a0: 65 64 20 6f 72 20 6d 61 6e 67 6c 65 64 20 63 6f ed or mangled co
17b0: 6e 74 65 6e 74 3a 5c 6e 7b 3a 3f 7d 5c 6e 7b 65 ntent:\n{:?}\n{e
17c0: 72 72 3a 23 3f 7d 5c 6e 7b 73 74 61 74 75 73 3a rr:#?}\n{status:
17d0: 23 3f 7d 5c 6e 22 2c 20 26 73 6f 75 72 63 65 2e #?}\n", &source.
17e0: 75 72 6c 29 0a 09 09 09 09 09 09 09 7d 2c 0a 09 url)........},..
17f0: 09 09 09 09 09 7d 0a 09 09 09 09 09 7d 2c 0a 09 .....}......},..
1800: 09 09 09 09 72 73 73 3a 3a 45 72 72 6f 72 3a 3a ....rss::Error::
1810: 45 6f 66 20 3d 3e 20 28 29 2c 0a 09 09 09 09 09 Eof => (),......
1820: 5f 20 3d 3e 20 62 61 69 6c 21 28 22 55 6e 73 75 _ => bail!("Unsu
1830: 70 70 6f 72 74 65 64 20 6f 72 20 6d 61 6e 67 6c pported or mangl
1840: 65 64 20 63 6f 6e 74 65 6e 74 3a 5c 6e 7b 3a 3f ed content:\n{:?
1850: 7d 5c 6e 7b 65 72 72 3a 23 3f 7d 5c 6e 7b 73 74 }\n{err:#?}\n{st
1860: 61 74 75 73 3a 23 3f 7d 5c 6e 22 2c 20 26 73 6f atus:#?}\n", &so
1870: 75 72 63 65 2e 75 72 6c 29 0a 09 09 09 09 7d 0a urce.url).....}.
1880: 09 09 09 7d 3b 0a 09 09 09 66 6f 72 20 28 64 61 ...};....for (da
1890: 74 65 2c 20 75 72 6c 29 20 69 6e 20 70 6f 73 74 te, url) in post
18a0: 73 2e 69 74 65 72 28 29 20 7b 0a 09 09 09 09 6c s.iter() {.....l
18b0: 65 74 20 70 6f 73 74 5f 75 72 6c 3a 20 43 6f 77 et post_url: Cow
18c0: 3c 73 74 72 3e 20 3d 20 6d 61 74 63 68 20 73 6f <str> = match so
18d0: 75 72 63 65 2e 75 72 6c 5f 72 65 20 7b 0a 09 09 urce.url_re {...
18e0: 09 09 09 53 6f 6d 65 28 72 65 66 20 78 29 20 3d ...Some(ref x) =
18f0: 3e 20 73 65 64 72 65 67 65 78 3a 3a 52 65 70 6c > sedregex::Repl
1900: 61 63 65 43 6f 6d 6d 61 6e 64 3a 3a 6e 65 77 28 aceCommand::new(
1910: 78 29 3f 2e 65 78 65 63 75 74 65 28 75 72 6c 29 x)?.execute(url)
1920: 2c 0a 09 09 09 09 09 4e 6f 6e 65 20 3d 3e 20 75 ,......None => u
1930: 72 6c 2e 69 6e 74 6f 28 29 2c 0a 09 09 09 09 7d rl.into(),.....}
1940: 3b 0a 09 09 09 09 69 66 20 6c 65 74 20 53 6f 6d ;.....if let Som
1950: 65 28 65 78 69 73 74 73 29 20 3d 20 73 71 6c 78 e(exists) = sqlx
1960: 3a 3a 71 75 65 72 79 21 28 22 73 65 6c 65 63 74 ::query!("select
1970: 20 65 78 69 73 74 73 28 73 65 6c 65 63 74 20 74 exists(select t
1980: 72 75 65 20 66 72 6f 6d 20 72 73 73 74 67 5f 70 rue from rsstg_p
1990: 6f 73 74 20 77 68 65 72 65 20 75 72 6c 20 3d 20 ost where url =
19a0: 24 31 20 61 6e 64 20 73 6f 75 72 63 65 5f 69 64 $1 and source_id
19b0: 20 3d 20 24 32 29 20 61 73 20 65 78 69 73 74 73 = $2) as exists
19c0: 3b 22 2c 0a 09 09 09 09 09 26 70 6f 73 74 5f 75 ;",......&post_u
19d0: 72 6c 2c 20 2a 69 64 29 2e 66 65 74 63 68 5f 6f rl, *id).fetch_o
19e0: 6e 65 28 26 6d 75 74 20 2a 63 6f 6e 6e 29 2e 61 ne(&mut *conn).a
19f0: 77 61 69 74 3f 2e 65 78 69 73 74 73 20 7b 0a 09 wait?.exists {..
1a00: 09 09 09 09 69 66 20 21 20 65 78 69 73 74 73 20 ....if ! exists
1a10: 7b 0a 09 09 09 09 09 09 69 66 20 74 68 69 73 5f {.......if this_
1a20: 66 65 74 63 68 2e 69 73 5f 6e 6f 6e 65 28 29 20 fetch.is_none()
1a30: 7c 7c 20 2a 64 61 74 65 20 3e 20 74 68 69 73 5f || *date > this_
1a40: 66 65 74 63 68 2e 75 6e 77 72 61 70 28 29 20 7b fetch.unwrap() {
1a50: 0a 09 09 09 09 09 09 09 74 68 69 73 5f 66 65 74 ........this_fet
1a60: 63 68 20 3d 20 53 6f 6d 65 28 2a 64 61 74 65 29 ch = Some(*date)
1a70: 3b 0a 09 09 09 09 09 09 7d 3b 0a 09 09 09 09 09 ;.......};......
1a80: 09 73 65 6c 66 2e 73 65 6e 64 28 20 6d 61 74 63 .self.send( matc
1a90: 68 20 26 73 6f 75 72 63 65 2e 69 76 5f 68 61 73 h &source.iv_has
1aa0: 68 20 7b 0a 09 09 09 09 09 09 09 53 6f 6d 65 28 h {........Some(
1ab0: 68 61 73 68 29 20 3d 3e 20 66 6f 72 6d 61 74 21 hash) => format!
1ac0: 28 22 3c 61 20 68 72 65 66 3d 5c 22 68 74 74 70 ("<a href=\"http
1ad0: 73 3a 2f 2f 74 2e 6d 65 2f 69 76 3f 75 72 6c 3d s://t.me/iv?url=
1ae0: 7b 70 6f 73 74 5f 75 72 6c 7d 26 72 68 61 73 68 {post_url}&rhash
1af0: 3d 7b 68 61 73 68 7d 5c 22 3e 20 3c 2f 61 3e 7b ={hash}\"> </a>{
1b00: 70 6f 73 74 5f 75 72 6c 7d 22 29 2c 0a 09 09 09 post_url}"),....
1b10: 09 09 09 09 4e 6f 6e 65 20 3d 3e 20 66 6f 72 6d ....None => form
1b20: 61 74 21 28 22 7b 70 6f 73 74 5f 75 72 6c 7d 22 at!("{post_url}"
1b30: 29 2c 0a 09 09 09 09 09 09 7d 2c 20 53 6f 6d 65 ),.......}, Some
1b40: 28 64 65 73 74 69 6e 61 74 69 6f 6e 29 2c 20 53 (destination), S
1b50: 6f 6d 65 28 50 61 72 73 65 4d 6f 64 65 3a 3a 48 ome(ParseMode::H
1b60: 74 6d 6c 29 29 2e 61 77 61 69 74 3f 3b 0a 09 09 tml)).await?;...
1b70: 09 09 09 09 73 71 6c 78 3a 3a 71 75 65 72 79 21 ....sqlx::query!
1b80: 28 22 69 6e 73 65 72 74 20 69 6e 74 6f 20 72 73 ("insert into rs
1b90: 73 74 67 5f 70 6f 73 74 20 28 73 6f 75 72 63 65 stg_post (source
1ba0: 5f 69 64 2c 20 70 6f 73 74 65 64 2c 20 75 72 6c _id, posted, url
1bb0: 29 20 76 61 6c 75 65 73 20 28 24 31 2c 20 24 32 ) values ($1, $2
1bc0: 2c 20 24 33 29 3b 22 2c 0a 09 09 09 09 09 09 09 , $3);",........
1bd0: 2a 69 64 2c 20 64 61 74 65 2c 20 26 70 6f 73 74 *id, date, &post
1be0: 5f 75 72 6c 29 2e 65 78 65 63 75 74 65 28 26 6d _url).execute(&m
1bf0: 75 74 20 2a 63 6f 6e 6e 29 2e 61 77 61 69 74 3f ut *conn).await?
1c00: 3b 0a 09 09 09 09 09 7d 3b 0a 09 09 09 09 7d 3b ;......};.....};
1c10: 0a 09 09 09 09 70 6f 73 74 65 64 20 2b 3d 20 31 .....posted += 1
1c20: 3b 0a 09 09 09 7d 3b 0a 09 09 09 70 6f 73 74 73 ;....};....posts
1c30: 2e 63 6c 65 61 72 28 29 3b 0a 09 09 7d 3b 0a 09 .clear();...};..
1c40: 09 73 71 6c 78 3a 3a 71 75 65 72 79 21 28 22 75 .sqlx::query!("u
1c50: 70 64 61 74 65 20 72 73 73 74 67 5f 73 6f 75 72 pdate rsstg_sour
1c60: 63 65 20 73 65 74 20 6c 61 73 74 5f 73 63 72 61 ce set last_scra
1c70: 70 65 20 3d 20 6e 6f 77 28 29 20 77 68 65 72 65 pe = now() where
1c80: 20 73 6f 75 72 63 65 5f 69 64 20 3d 20 24 31 3b source_id = $1;
1c90: 22 2c 0a 09 09 09 2a 69 64 29 2e 65 78 65 63 75 ",....*id).execu
1ca0: 74 65 28 26 6d 75 74 20 2a 63 6f 6e 6e 29 2e 61 te(&mut *conn).a
1cb0: 77 61 69 74 3f 3b 0a 09 09 4f 6b 28 66 6f 72 6d wait?;...Ok(form
1cc0: 61 74 21 28 22 50 6f 73 74 65 64 3a 20 7b 70 6f at!("Posted: {po
1cd0: 73 74 65 64 7d 22 29 2e 69 6e 74 6f 28 29 29 0a sted}").into()).
1ce0: 09 7d 0a 0a 09 70 75 62 20 61 73 79 6e 63 20 66 .}...pub async f
1cf0: 6e 20 64 65 6c 65 74 65 20 28 26 73 65 6c 66 2c n delete (&self,
1d00: 20 73 6f 75 72 63 65 5f 69 64 3a 20 26 69 33 32 source_id: &i32
1d10: 2c 20 6f 77 6e 65 72 3a 20 69 36 34 29 20 2d 3e , owner: i64) ->
1d20: 20 52 65 73 75 6c 74 3c 43 6f 77 3c 27 5f 2c 20 Result<Cow<'_,
1d30: 73 74 72 3e 3e 20 7b 0a 09 09 6d 61 74 63 68 20 str>> {...match
1d40: 73 71 6c 78 3a 3a 71 75 65 72 79 21 28 22 64 65 sqlx::query!("de
1d50: 6c 65 74 65 20 66 72 6f 6d 20 72 73 73 74 67 5f lete from rsstg_
1d60: 73 6f 75 72 63 65 20 77 68 65 72 65 20 73 6f 75 source where sou
1d70: 72 63 65 5f 69 64 20 3d 20 24 31 20 61 6e 64 20 rce_id = $1 and
1d80: 6f 77 6e 65 72 20 3d 20 24 32 3b 22 2c 0a 09 09 owner = $2;",...
1d90: 09 73 6f 75 72 63 65 5f 69 64 2c 20 6f 77 6e 65 .source_id, owne
1da0: 72 29 2e 65 78 65 63 75 74 65 28 26 6d 75 74 20 r).execute(&mut
1db0: 2a 73 65 6c 66 2e 70 6f 6f 6c 2e 61 63 71 75 69 *self.pool.acqui
1dc0: 72 65 28 29 2e 61 77 61 69 74 3f 29 2e 61 77 61 re().await?).awa
1dd0: 69 74 3f 2e 72 6f 77 73 5f 61 66 66 65 63 74 65 it?.rows_affecte
1de0: 64 28 29 20 7b 0a 09 09 09 30 20 3d 3e 20 7b 20 d() {....0 => {
1df0: 4f 6b 28 22 4e 6f 20 64 61 74 61 20 66 6f 75 6e Ok("No data foun
1e00: 64 20 66 6f 75 6e 64 2e 22 2e 69 6e 74 6f 28 29 d found.".into()
1e10: 29 20 7d 2c 0a 09 09 09 78 20 3d 3e 20 7b 20 4f ) },....x => { O
1e20: 6b 28 66 6f 72 6d 61 74 21 28 22 7b 7d 20 73 6f k(format!("{} so
1e30: 75 72 63 65 73 20 72 65 6d 6f 76 65 64 2e 22 2c urces removed.",
1e40: 20 78 29 2e 69 6e 74 6f 28 29 29 20 7d 2c 0a 09 x).into()) },..
1e50: 09 7d 0a 09 7d 0a 0a 09 70 75 62 20 61 73 79 6e .}..}...pub asyn
1e60: 63 20 66 6e 20 63 6c 65 61 6e 20 28 26 73 65 6c c fn clean (&sel
1e70: 66 2c 20 73 6f 75 72 63 65 5f 69 64 3a 20 26 69 f, source_id: &i
1e80: 33 32 2c 20 6f 77 6e 65 72 3a 20 69 36 34 29 20 32, owner: i64)
1e90: 2d 3e 20 52 65 73 75 6c 74 3c 43 6f 77 3c 27 5f -> Result<Cow<'_
1ea0: 2c 20 73 74 72 3e 3e 20 7b 0a 09 09 6d 61 74 63 , str>> {...matc
1eb0: 68 20 73 71 6c 78 3a 3a 71 75 65 72 79 21 28 22 h sqlx::query!("
1ec0: 64 65 6c 65 74 65 20 66 72 6f 6d 20 72 73 73 74 delete from rsst
1ed0: 67 5f 70 6f 73 74 20 70 20 75 73 69 6e 67 20 72 g_post p using r
1ee0: 73 73 74 67 5f 73 6f 75 72 63 65 20 73 20 77 68 sstg_source s wh
1ef0: 65 72 65 20 70 2e 73 6f 75 72 63 65 5f 69 64 20 ere p.source_id
1f00: 3d 20 24 31 20 61 6e 64 20 6f 77 6e 65 72 20 3d = $1 and owner =
1f10: 20 24 32 20 61 6e 64 20 70 2e 73 6f 75 72 63 65 $2 and p.source
1f20: 5f 69 64 20 3d 20 73 2e 73 6f 75 72 63 65 5f 69 _id = s.source_i
1f30: 64 3b 22 2c 0a 09 09 09 73 6f 75 72 63 65 5f 69 d;",....source_i
1f40: 64 2c 20 6f 77 6e 65 72 29 2e 65 78 65 63 75 74 d, owner).execut
1f50: 65 28 26 6d 75 74 20 2a 73 65 6c 66 2e 70 6f 6f e(&mut *self.poo
1f60: 6c 2e 61 63 71 75 69 72 65 28 29 2e 61 77 61 69 l.acquire().awai
1f70: 74 3f 29 2e 61 77 61 69 74 3f 2e 72 6f 77 73 5f t?).await?.rows_
1f80: 61 66 66 65 63 74 65 64 28 29 20 7b 0a 09 09 09 affected() {....
1f90: 30 20 3d 3e 20 7b 20 4f 6b 28 22 4e 6f 20 64 61 0 => { Ok("No da
1fa0: 74 61 20 66 6f 75 6e 64 20 66 6f 75 6e 64 2e 22 ta found found."
1fb0: 2e 69 6e 74 6f 28 29 29 20 7d 2c 0a 09 09 09 78 .into()) },....x
1fc0: 20 3d 3e 20 7b 20 4f 6b 28 66 6f 72 6d 61 74 21 => { Ok(format!
1fd0: 28 22 7b 78 7d 20 70 6f 73 74 73 20 70 75 72 67 ("{x} posts purg
1fe0: 65 64 2e 22 29 2e 69 6e 74 6f 28 29 29 20 7d 2c ed.").into()) },
1ff0: 0a 09 09 7d 0a 09 7d 0a 0a 09 70 75 62 20 61 73 ...}..}...pub as
2000: 79 6e 63 20 66 6e 20 65 6e 61 62 6c 65 20 28 26 ync fn enable (&
2010: 73 65 6c 66 2c 20 73 6f 75 72 63 65 5f 69 64 3a self, source_id:
2020: 20 26 69 33 32 2c 20 6f 77 6e 65 72 3a 20 69 36 &i32, owner: i6
2030: 34 29 20 2d 3e 20 52 65 73 75 6c 74 3c 26 73 74 4) -> Result<&st
2040: 72 3e 20 7b 0a 09 09 6d 61 74 63 68 20 73 71 6c r> {...match sql
2050: 78 3a 3a 71 75 65 72 79 21 28 22 75 70 64 61 74 x::query!("updat
2060: 65 20 72 73 73 74 67 5f 73 6f 75 72 63 65 20 73 e rsstg_source s
2070: 65 74 20 65 6e 61 62 6c 65 64 20 3d 20 74 72 75 et enabled = tru
2080: 65 20 77 68 65 72 65 20 73 6f 75 72 63 65 5f 69 e where source_i
2090: 64 20 3d 20 24 31 20 61 6e 64 20 6f 77 6e 65 72 d = $1 and owner
20a0: 20 3d 20 24 32 22 2c 0a 09 09 09 73 6f 75 72 63 = $2",....sourc
20b0: 65 5f 69 64 2c 20 6f 77 6e 65 72 29 2e 65 78 65 e_id, owner).exe
20c0: 63 75 74 65 28 26 6d 75 74 20 2a 73 65 6c 66 2e cute(&mut *self.
20d0: 70 6f 6f 6c 2e 61 63 71 75 69 72 65 28 29 2e 61 pool.acquire().a
20e0: 77 61 69 74 3f 29 2e 61 77 61 69 74 3f 2e 72 6f wait?).await?.ro
20f0: 77 73 5f 61 66 66 65 63 74 65 64 28 29 20 7b 0a ws_affected() {.
2100: 09 09 09 31 20 3d 3e 20 7b 20 4f 6b 28 22 53 6f ...1 => { Ok("So
2110: 75 72 63 65 20 65 6e 61 62 6c 65 64 2e 22 29 20 urce enabled.")
2120: 7d 2c 0a 09 09 09 30 20 3d 3e 20 7b 20 4f 6b 28 },....0 => { Ok(
2130: 22 53 6f 75 72 63 65 20 6e 6f 74 20 66 6f 75 6e "Source not foun
2140: 64 2e 22 29 20 7d 2c 0a 09 09 09 5f 20 3d 3e 20 d.") },...._ =>
2150: 7b 20 45 72 72 28 61 6e 79 68 6f 77 21 28 22 44 { Err(anyhow!("D
2160: 61 74 61 62 61 73 65 20 65 72 72 6f 72 2e 22 29 atabase error.")
2170: 29 20 7d 2c 0a 09 09 7d 0a 09 7d 0a 0a 09 70 75 ) },...}..}...pu
2180: 62 20 61 73 79 6e 63 20 66 6e 20 64 69 73 61 62 b async fn disab
2190: 6c 65 20 28 26 73 65 6c 66 2c 20 73 6f 75 72 63 le (&self, sourc
21a0: 65 5f 69 64 3a 20 26 69 33 32 2c 20 6f 77 6e 65 e_id: &i32, owne
21b0: 72 3a 20 69 36 34 29 20 2d 3e 20 52 65 73 75 6c r: i64) -> Resul
21c0: 74 3c 26 73 74 72 3e 20 7b 0a 09 09 6d 61 74 63 t<&str> {...matc
21d0: 68 20 73 71 6c 78 3a 3a 71 75 65 72 79 21 28 22 h sqlx::query!("
21e0: 75 70 64 61 74 65 20 72 73 73 74 67 5f 73 6f 75 update rsstg_sou
21f0: 72 63 65 20 73 65 74 20 65 6e 61 62 6c 65 64 20 rce set enabled
2200: 3d 20 66 61 6c 73 65 20 77 68 65 72 65 20 73 6f = false where so
2210: 75 72 63 65 5f 69 64 20 3d 20 24 31 20 61 6e 64 urce_id = $1 and
2220: 20 6f 77 6e 65 72 20 3d 20 24 32 22 2c 0a 09 09 owner = $2",...
2230: 09 73 6f 75 72 63 65 5f 69 64 2c 20 6f 77 6e 65 .source_id, owne
2240: 72 29 2e 65 78 65 63 75 74 65 28 26 6d 75 74 20 r).execute(&mut
2250: 2a 73 65 6c 66 2e 70 6f 6f 6c 2e 61 63 71 75 69 *self.pool.acqui
2260: 72 65 28 29 2e 61 77 61 69 74 3f 29 2e 61 77 61 re().await?).awa
2270: 69 74 3f 2e 72 6f 77 73 5f 61 66 66 65 63 74 65 it?.rows_affecte
2280: 64 28 29 20 7b 0a 09 09 09 31 20 3d 3e 20 7b 20 d() {....1 => {
2290: 4f 6b 28 22 53 6f 75 72 63 65 20 64 69 73 61 62 Ok("Source disab
22a0: 6c 65 64 2e 22 29 20 7d 2c 0a 09 09 09 30 20 3d led.") },....0 =
22b0: 3e 20 7b 20 4f 6b 28 22 53 6f 75 72 63 65 20 6e > { Ok("Source n
22c0: 6f 74 20 66 6f 75 6e 64 2e 22 29 20 7d 2c 0a 09 ot found.") },..
22d0: 09 09 5f 20 3d 3e 20 7b 20 45 72 72 28 61 6e 79 .._ => { Err(any
22e0: 68 6f 77 21 28 22 44 61 74 61 62 61 73 65 20 65 how!("Database e
22f0: 72 72 6f 72 2e 22 29 29 20 7d 2c 0a 09 09 7d 0a rror.")) },...}.
2300: 09 7d 0a 0a 09 70 75 62 20 61 73 79 6e 63 20 66 .}...pub async f
2310: 6e 20 75 70 64 61 74 65 20 28 26 73 65 6c 66 2c n update (&self,
2320: 20 75 70 64 61 74 65 3a 20 4f 70 74 69 6f 6e 3c update: Option<
2330: 69 33 32 3e 2c 20 63 68 61 6e 6e 65 6c 3a 20 26 i32>, channel: &
2340: 73 74 72 2c 20 63 68 61 6e 6e 65 6c 5f 69 64 3a str, channel_id:
2350: 20 69 36 34 2c 20 75 72 6c 3a 20 26 73 74 72 2c i64, url: &str,
2360: 20 69 76 5f 68 61 73 68 3a 20 4f 70 74 69 6f 6e iv_hash: Option
2370: 3c 26 73 74 72 3e 2c 20 75 72 6c 5f 72 65 3a 20 <&str>, url_re:
2380: 4f 70 74 69 6f 6e 3c 26 73 74 72 3e 2c 20 6f 77 Option<&str>, ow
2390: 6e 65 72 3a 20 69 36 34 29 20 2d 3e 20 52 65 73 ner: i64) -> Res
23a0: 75 6c 74 3c 26 73 74 72 3e 20 7b 0a 09 09 6c 65 ult<&str> {...le
23b0: 74 20 6d 75 74 20 63 6f 6e 6e 20 3d 20 73 65 6c t mut conn = sel
23c0: 66 2e 70 6f 6f 6c 2e 61 63 71 75 69 72 65 28 29 f.pool.acquire()
23d0: 2e 61 77 61 69 74 3f 3b 0a 0a 09 09 6d 61 74 63 .await?;....matc
23e0: 68 20 6d 61 74 63 68 20 75 70 64 61 74 65 20 7b h match update {
23f0: 0a 09 09 09 09 53 6f 6d 65 28 69 64 29 20 3d 3e .....Some(id) =>
2400: 20 7b 0a 09 09 09 09 09 73 71 6c 78 3a 3a 71 75 {......sqlx::qu
2410: 65 72 79 21 28 22 75 70 64 61 74 65 20 72 73 73 ery!("update rss
2420: 74 67 5f 73 6f 75 72 63 65 20 73 65 74 20 63 68 tg_source set ch
2430: 61 6e 6e 65 6c 5f 69 64 20 3d 20 24 32 2c 20 75 annel_id = $2, u
2440: 72 6c 20 3d 20 24 33 2c 20 69 76 5f 68 61 73 68 rl = $3, iv_hash
2450: 20 3d 20 24 34 2c 20 6f 77 6e 65 72 20 3d 20 24 = $4, owner = $
2460: 35 2c 20 63 68 61 6e 6e 65 6c 20 3d 20 24 36 2c 5, channel = $6,
2470: 20 75 72 6c 5f 72 65 20 3d 20 24 37 20 77 68 65 url_re = $7 whe
2480: 72 65 20 73 6f 75 72 63 65 5f 69 64 20 3d 20 24 re source_id = $
2490: 31 22 2c 0a 09 09 09 09 09 09 69 64 2c 20 63 68 1",.......id, ch
24a0: 61 6e 6e 65 6c 5f 69 64 2c 20 75 72 6c 2c 20 69 annel_id, url, i
24b0: 76 5f 68 61 73 68 2c 20 6f 77 6e 65 72 2c 20 63 v_hash, owner, c
24c0: 68 61 6e 6e 65 6c 2c 20 75 72 6c 5f 72 65 29 2e hannel, url_re).
24d0: 65 78 65 63 75 74 65 28 26 6d 75 74 20 2a 63 6f execute(&mut *co
24e0: 6e 6e 29 2e 61 77 61 69 74 0a 09 09 09 09 7d 2c nn).await.....},
24f0: 0a 09 09 09 09 4e 6f 6e 65 20 3d 3e 20 7b 0a 09 .....None => {..
2500: 09 09 09 09 73 71 6c 78 3a 3a 71 75 65 72 79 21 ....sqlx::query!
2510: 28 22 69 6e 73 65 72 74 20 69 6e 74 6f 20 72 73 ("insert into rs
2520: 73 74 67 5f 73 6f 75 72 63 65 20 28 63 68 61 6e stg_source (chan
2530: 6e 65 6c 5f 69 64 2c 20 75 72 6c 2c 20 69 76 5f nel_id, url, iv_
2540: 68 61 73 68 2c 20 6f 77 6e 65 72 2c 20 63 68 61 hash, owner, cha
2550: 6e 6e 65 6c 2c 20 75 72 6c 5f 72 65 29 20 76 61 nnel, url_re) va
2560: 6c 75 65 73 20 28 24 31 2c 20 24 32 2c 20 24 33 lues ($1, $2, $3
2570: 2c 20 24 34 2c 20 24 35 2c 20 24 36 29 22 2c 0a , $4, $5, $6)",.
2580: 09 09 09 09 09 09 63 68 61 6e 6e 65 6c 5f 69 64 ......channel_id
2590: 2c 20 75 72 6c 2c 20 69 76 5f 68 61 73 68 2c 20 , url, iv_hash,
25a0: 6f 77 6e 65 72 2c 20 63 68 61 6e 6e 65 6c 2c 20 owner, channel,
25b0: 75 72 6c 5f 72 65 29 2e 65 78 65 63 75 74 65 28 url_re).execute(
25c0: 26 6d 75 74 20 2a 63 6f 6e 6e 29 2e 61 77 61 69 &mut *conn).awai
25d0: 74 0a 09 09 09 09 7d 2c 0a 09 09 09 7d 20 7b 0a t.....},....} {.
25e0: 09 09 09 4f 6b 28 5f 29 20 3d 3e 20 4f 6b 28 6d ...Ok(_) => Ok(m
25f0: 61 74 63 68 20 75 70 64 61 74 65 20 7b 0a 09 09 atch update {...
2600: 09 09 53 6f 6d 65 28 5f 29 20 3d 3e 20 22 43 68 ..Some(_) => "Ch
2610: 61 6e 6e 65 6c 20 75 70 64 61 74 65 64 2e 22 2c annel updated.",
2620: 0a 09 09 09 09 4e 6f 6e 65 20 3d 3e 20 22 43 68 .....None => "Ch
2630: 61 6e 6e 65 6c 20 61 64 64 65 64 2e 22 2c 0a 09 annel added.",..
2640: 09 09 7d 29 2c 0a 09 09 09 45 72 72 28 73 71 6c ..}),....Err(sql
2650: 78 3a 3a 45 72 72 6f 72 3a 3a 44 61 74 61 62 61 x::Error::Databa
2660: 73 65 28 65 72 72 29 29 20 3d 3e 20 7b 0a 09 09 se(err)) => {...
2670: 09 09 6d 61 74 63 68 20 65 72 72 2e 64 6f 77 6e ..match err.down
2680: 63 61 73 74 3a 3a 3c 73 71 6c 78 3a 3a 70 6f 73 cast::<sqlx::pos
2690: 74 67 72 65 73 3a 3a 50 67 44 61 74 61 62 61 73 tgres::PgDatabas
26a0: 65 45 72 72 6f 72 3e 28 29 2e 72 6f 75 74 69 6e eError>().routin
26b0: 65 28 29 20 7b 0a 09 09 09 09 09 53 6f 6d 65 28 e() {......Some(
26c0: 22 5f 62 74 5f 63 68 65 63 6b 5f 75 6e 69 71 75 "_bt_check_uniqu
26d0: 65 22 2c 20 29 20 3d 3e 20 7b 0a 09 09 09 09 09 e", ) => {......
26e0: 09 4f 6b 28 22 44 75 70 6c 69 63 61 74 65 20 6b .Ok("Duplicate k
26f0: 65 79 2e 22 29 0a 09 09 09 09 09 7d 2c 0a 09 09 ey.")......},...
2700: 09 09 09 53 6f 6d 65 28 5f 29 20 3d 3e 20 7b 0a ...Some(_) => {.
2710: 09 09 09 09 09 09 4f 6b 28 22 44 61 74 61 62 61 ......Ok("Databa
2720: 73 65 20 65 72 72 6f 72 2e 22 29 0a 09 09 09 09 se error.").....
2730: 09 7d 2c 0a 09 09 09 09 09 4e 6f 6e 65 20 3d 3e .},......None =>
2740: 20 7b 0a 09 09 09 09 09 09 4f 6b 28 22 4e 6f 20 {.......Ok("No
2750: 64 61 74 61 62 61 73 65 20 65 72 72 6f 72 20 65 database error e
2760: 78 74 72 61 63 74 65 64 2e 22 29 0a 09 09 09 09 xtracted.").....
2770: 09 7d 2c 0a 09 09 09 09 7d 0a 09 09 09 7d 2c 0a .},.....}....},.
2780: 09 09 09 45 72 72 28 65 72 72 29 20 3d 3e 20 7b ...Err(err) => {
2790: 0a 09 09 09 09 62 61 69 6c 21 28 22 53 6f 72 72 .....bail!("Sorr
27a0: 79 2c 20 75 6e 6b 6e 6f 77 6e 20 65 72 72 6f 72 y, unknown error
27b0: 3a 5c 6e 7b 65 72 72 3a 23 3f 7d 5c 6e 22 29 3b :\n{err:#?}\n");
27c0: 0a 09 09 09 7d 2c 0a 09 09 7d 0a 09 7d 0a 0a 09 ....},...}..}...
27d0: 61 73 79 6e 63 20 66 6e 20 61 75 74 6f 66 65 74 async fn autofet
27e0: 63 68 28 26 73 65 6c 66 29 20 2d 3e 20 52 65 73 ch(&self) -> Res
27f0: 75 6c 74 3c 73 74 64 3a 3a 74 69 6d 65 3a 3a 44 ult<std::time::D
2800: 75 72 61 74 69 6f 6e 3e 20 7b 0a 09 09 6c 65 74 uration> {...let
2810: 20 6d 75 74 20 64 65 6c 61 79 20 3d 20 63 68 72 mut delay = chr
2820: 6f 6e 6f 3a 3a 44 75 72 61 74 69 6f 6e 3a 3a 6d ono::Duration::m
2830: 69 6e 75 74 65 73 28 31 29 3b 0a 09 09 6c 65 74 inutes(1);...let
2840: 20 6e 6f 77 20 3d 20 63 68 72 6f 6e 6f 3a 3a 4c now = chrono::L
2850: 6f 63 61 6c 3a 3a 6e 6f 77 28 29 3b 0a 09 09 6c ocal::now();...l
2860: 65 74 20 6d 75 74 20 71 75 65 75 65 20 3d 20 73 et mut queue = s
2870: 71 6c 78 3a 3a 71 75 65 72 79 21 28 72 23 22 73 qlx::query!(r#"s
2880: 65 6c 65 63 74 20 73 6f 75 72 63 65 5f 69 64 2c elect source_id,
2890: 20 6e 65 78 74 5f 66 65 74 63 68 20 61 73 20 22 next_fetch as "
28a0: 6e 65 78 74 5f 66 65 74 63 68 3a 20 44 61 74 65 next_fetch: Date
28b0: 54 69 6d 65 3c 63 68 72 6f 6e 6f 3a 3a 4c 6f 63 Time<chrono::Loc
28c0: 61 6c 3e 22 2c 20 6f 77 6e 65 72 20 66 72 6f 6d al>", owner from
28d0: 20 72 73 73 74 67 5f 6f 72 64 65 72 20 6e 61 74 rsstg_order nat
28e0: 75 72 61 6c 20 6c 65 66 74 20 6a 6f 69 6e 20 72 ural left join r
28f0: 73 73 74 67 5f 73 6f 75 72 63 65 20 77 68 65 72 sstg_source wher
2900: 65 20 6e 65 78 74 5f 66 65 74 63 68 20 3c 20 6e e next_fetch < n
2910: 6f 77 28 29 20 2b 20 69 6e 74 65 72 76 61 6c 20 ow() + interval
2920: 27 31 20 6d 69 6e 75 74 65 27 3b 22 23 29 0a 09 '1 minute';"#)..
2930: 09 09 2e 66 65 74 63 68 5f 61 6c 6c 28 26 6d 75 ...fetch_all(&mu
2940: 74 20 2a 73 65 6c 66 2e 70 6f 6f 6c 2e 61 63 71 t *self.pool.acq
2950: 75 69 72 65 28 29 2e 61 77 61 69 74 3f 29 2e 61 uire().await?).a
2960: 77 61 69 74 3f 3b 0a 09 09 66 6f 72 20 72 6f 77 wait?;...for row
2970: 20 69 6e 20 71 75 65 75 65 2e 69 74 65 72 28 29 in queue.iter()
2980: 20 7b 0a 09 09 09 69 66 20 6c 65 74 20 53 6f 6d {....if let Som
2990: 65 28 6e 65 78 74 5f 66 65 74 63 68 29 20 3d 20 e(next_fetch) =
29a0: 72 6f 77 2e 6e 65 78 74 5f 66 65 74 63 68 20 7b row.next_fetch {
29b0: 0a 09 09 09 09 69 66 20 6e 65 78 74 5f 66 65 74 .....if next_fet
29c0: 63 68 20 3c 20 6e 6f 77 20 7b 0a 09 09 09 09 09 ch < now {......
29d0: 69 66 20 6c 65 74 20 28 53 6f 6d 65 28 6f 77 6e if let (Some(own
29e0: 65 72 29 2c 20 53 6f 6d 65 28 73 6f 75 72 63 65 er), Some(source
29f0: 5f 69 64 29 29 20 3d 20 28 72 6f 77 2e 6f 77 6e _id)) = (row.own
2a00: 65 72 2c 20 72 6f 77 2e 73 6f 75 72 63 65 5f 69 er, row.source_i
2a10: 64 29 20 7b 0a 09 09 09 09 09 09 6c 65 74 20 63 d) {.......let c
2a20: 6c 6f 6e 65 20 3d 20 43 6f 72 65 20 7b 0a 09 09 lone = Core {...
2a30: 09 09 09 09 09 6f 77 6e 65 72 5f 63 68 61 74 3a .....owner_chat:
2a40: 20 6f 77 6e 65 72 2c 0a 09 09 09 09 09 09 09 2e owner,.........
2a50: 2e 73 65 6c 66 2e 63 6c 6f 6e 65 28 29 0a 09 09 .self.clone()...
2a60: 09 09 09 09 7d 3b 0a 09 09 09 09 09 09 74 61 73 ....};.......tas
2a70: 6b 3a 3a 73 70 61 77 6e 28 61 73 79 6e 63 20 6d k::spawn(async m
2a80: 6f 76 65 20 7b 0a 09 09 09 09 09 09 09 69 66 20 ove {........if
2a90: 6c 65 74 20 45 72 72 28 65 72 72 29 20 3d 20 63 let Err(err) = c
2aa0: 6c 6f 6e 65 2e 63 68 65 63 6b 28 26 73 6f 75 72 lone.check(&sour
2ab0: 63 65 5f 69 64 2c 20 6f 77 6e 65 72 2c 20 74 72 ce_id, owner, tr
2ac0: 75 65 29 2e 61 77 61 69 74 20 7b 0a 09 09 09 09 ue).await {.....
2ad0: 09 09 09 09 69 66 20 6c 65 74 20 45 72 72 28 65 ....if let Err(e
2ae0: 72 72 29 20 3d 20 63 6c 6f 6e 65 2e 73 65 6e 64 rr) = clone.send
2af0: 28 26 66 6f 72 6d 61 74 21 28 22 f0 9f 9b 91 20 (&format!("š
2b00: 7b 65 72 72 3a 3f 7d 22 29 2c 20 4e 6f 6e 65 2c {err:?}"), None,
2b10: 20 4e 6f 6e 65 29 2e 61 77 61 69 74 20 7b 0a 09 None).await {..
2b20: 09 09 09 09 09 09 09 09 65 70 72 69 6e 74 6c 6e ........eprintln
2b30: 21 28 22 43 68 65 63 6b 20 65 72 72 6f 72 3a 20 !("Check error:
2b40: 7b 65 72 72 3a 3f 7d 22 29 3b 0a 09 09 09 09 09 {err:?}");......
2b50: 09 09 09 09 2f 2f 20 63 6c 6f 6e 65 2e 64 69 73 ....// clone.dis
2b60: 61 62 6c 65 28 26 73 6f 75 72 63 65 5f 69 64 2c able(&source_id,
2b70: 20 6f 77 6e 65 72 29 2e 61 77 61 69 74 2e 75 6e owner).await.un
2b80: 77 72 61 70 28 29 3b 0a 09 09 09 09 09 09 09 09 wrap();.........
2b90: 7d 3b 0a 09 09 09 09 09 09 09 7d 3b 0a 09 09 09 };........};....
2ba0: 09 09 09 7d 29 3b 0a 09 09 09 09 09 7d 0a 09 09 ...});......}...
2bb0: 09 09 7d 20 65 6c 73 65 20 69 66 20 6e 65 78 74 ..} else if next
2bc0: 5f 66 65 74 63 68 20 2d 20 6e 6f 77 20 3c 20 64 _fetch - now < d
2bd0: 65 6c 61 79 20 7b 0a 09 09 09 09 09 64 65 6c 61 elay {......dela
2be0: 79 20 3d 20 6e 65 78 74 5f 66 65 74 63 68 20 2d y = next_fetch -
2bf0: 20 6e 6f 77 3b 0a 09 09 09 09 7d 0a 09 09 09 7d now;.....}....}
2c00: 0a 09 09 7d 3b 0a 09 09 71 75 65 75 65 2e 63 6c ...};...queue.cl
2c10: 65 61 72 28 29 3b 0a 09 09 4f 6b 28 64 65 6c 61 ear();...Ok(dela
2c20: 79 2e 74 6f 5f 73 74 64 28 29 3f 29 0a 09 7d 0a y.to_std()?)..}.
2c30: 0a 09 70 75 62 20 61 73 79 6e 63 20 66 6e 20 6c ..pub async fn l
2c40: 69 73 74 20 28 26 73 65 6c 66 2c 20 6f 77 6e 65 ist (&self, owne
2c50: 72 3a 20 69 36 34 29 20 2d 3e 20 52 65 73 75 6c r: i64) -> Resul
2c60: 74 3c 53 74 72 69 6e 67 3e 20 7b 0a 09 09 6c 65 t<String> {...le
2c70: 74 20 6d 75 74 20 72 65 70 6c 79 3a 20 56 65 63 t mut reply: Vec
2c80: 3c 43 6f 77 3c 73 74 72 3e 3e 20 3d 20 76 65 63 <Cow<str>> = vec
2c90: 21 5b 5d 3b 0a 09 09 72 65 70 6c 79 2e 70 75 73 ![];...reply.pus
2ca0: 68 28 22 43 68 61 6e 6e 65 6c 73 3a 22 2e 69 6e h("Channels:".in
2cb0: 74 6f 28 29 29 3b 0a 09 09 6c 65 74 20 72 6f 77 to());...let row
2cc0: 73 20 3d 20 73 71 6c 78 3a 3a 71 75 65 72 79 21 s = sqlx::query!
2cd0: 28 22 73 65 6c 65 63 74 20 73 6f 75 72 63 65 5f ("select source_
2ce0: 69 64 2c 20 63 68 61 6e 6e 65 6c 2c 20 65 6e 61 id, channel, ena
2cf0: 62 6c 65 64 2c 20 75 72 6c 2c 20 69 76 5f 68 61 bled, url, iv_ha
2d00: 73 68 2c 20 75 72 6c 5f 72 65 20 66 72 6f 6d 20 sh, url_re from
2d10: 72 73 73 74 67 5f 73 6f 75 72 63 65 20 77 68 65 rsstg_source whe
2d20: 72 65 20 6f 77 6e 65 72 20 3d 20 24 31 20 6f 72 re owner = $1 or
2d30: 64 65 72 20 62 79 20 73 6f 75 72 63 65 5f 69 64 der by source_id
2d40: 22 2c 0a 09 09 09 6f 77 6e 65 72 29 2e 66 65 74 ",....owner).fet
2d50: 63 68 5f 61 6c 6c 28 26 6d 75 74 20 2a 73 65 6c ch_all(&mut *sel
2d60: 66 2e 70 6f 6f 6c 2e 61 63 71 75 69 72 65 28 29 f.pool.acquire()
2d70: 2e 61 77 61 69 74 3f 29 2e 61 77 61 69 74 3f 3b .await?).await?;
2d80: 0a 09 09 66 6f 72 20 72 6f 77 20 69 6e 20 72 6f ...for row in ro
2d90: 77 73 2e 69 74 65 72 28 29 20 7b 0a 09 09 09 72 ws.iter() {....r
2da0: 65 70 6c 79 2e 70 75 73 68 28 66 6f 72 6d 61 74 eply.push(format
2db0: 21 28 22 5c 6e 5c 5c 23 ef b8 8f e2 83 a3 20 7b !("\n\\#ļøā£ {
2dc0: 7d 20 5c 5c 2a ef b8 8f e2 83 a3 20 60 7b 7d 60 } \\*ļøā£ `{}`
2dd0: 20 7b 7d 5c 6e f0 9f 94 97 20 60 7b 7d 60 22 2c {}\nš `{}`",
2de0: 20 72 6f 77 2e 73 6f 75 72 63 65 5f 69 64 2c 20 row.source_id,
2df0: 72 6f 77 2e 63 68 61 6e 6e 65 6c 2c 0a 09 09 09 row.channel,....
2e00: 09 6d 61 74 63 68 20 72 6f 77 2e 65 6e 61 62 6c .match row.enabl
2e10: 65 64 20 7b 0a 09 09 09 09 09 74 72 75 65 20 20 ed {......true
2e20: 3d 3e 20 22 f0 9f 94 84 20 65 6e 61 62 6c 65 64 => "š enabled
2e30: 22 2c 0a 09 09 09 09 09 66 61 6c 73 65 20 3d 3e ",......false =>
2e40: 20 22 e2 9b 94 20 64 69 73 61 62 6c 65 64 22 2c "ā disabled",
2e50: 0a 09 09 09 09 7d 2c 20 72 6f 77 2e 75 72 6c 29 .....}, row.url)
2e60: 2e 69 6e 74 6f 28 29 29 3b 0a 09 09 09 69 66 20 .into());....if
2e70: 6c 65 74 20 53 6f 6d 65 28 68 61 73 68 29 20 3d let Some(hash) =
2e80: 20 26 72 6f 77 2e 69 76 5f 68 61 73 68 20 7b 0a &row.iv_hash {.
2e90: 09 09 09 09 72 65 70 6c 79 2e 70 75 73 68 28 66 ....reply.push(f
2ea0: 6f 72 6d 61 74 21 28 22 49 56 3a 20 60 7b 68 61 ormat!("IV: `{ha
2eb0: 73 68 7d 60 22 29 2e 69 6e 74 6f 28 29 29 3b 0a sh}`").into());.
2ec0: 09 09 09 7d 0a 09 09 09 69 66 20 6c 65 74 20 53 ...}....if let S
2ed0: 6f 6d 65 28 72 65 29 20 3d 20 26 72 6f 77 2e 75 ome(re) = &row.u
2ee0: 72 6c 5f 72 65 20 7b 0a 09 09 09 09 72 65 70 6c rl_re {.....repl
2ef0: 79 2e 70 75 73 68 28 66 6f 72 6d 61 74 21 28 22 y.push(format!("
2f00: 52 45 3a 20 60 7b 72 65 7d 60 22 29 2e 69 6e 74 RE: `{re}`").int
2f10: 6f 28 29 29 3b 0a 09 09 09 7d 0a 09 09 7d 3b 0a o());....}...};.
2f20: 09 09 4f 6b 28 72 65 70 6c 79 2e 6a 6f 69 6e 28 ..Ok(reply.join(
2f30: 22 5c 6e 22 29 29 0a 09 7d 0a 7d 0a "\n"))..}.}.