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 63 68 72 6f 6e 6f 3a 3a 44 61 74 65 54 69 6d chrono::DateTim
0040: 65 3b 0a 75 73 65 20 73 71 6c 78 3a 3a 7b 0a 09 e;.use sqlx::{..
0050: 70 6f 73 74 67 72 65 73 3a 3a 50 67 50 6f 6f 6c postgres::PgPool
0060: 4f 70 74 69 6f 6e 73 2c 0a 09 52 6f 77 2c 0a 7d Options,..Row,.}
0070: 3b 0a 75 73 65 20 73 74 64 3a 3a 7b 0a 09 62 6f ;.use std::{..bo
0080: 72 72 6f 77 3a 3a 43 6f 77 2c 0a 09 63 6f 6c 6c rrow::Cow,..coll
0090: 65 63 74 69 6f 6e 73 3a 3a 7b 0a 09 09 42 54 72 ections::{...BTr
00a0: 65 65 4d 61 70 2c 0a 09 09 48 61 73 68 53 65 74 eeMap,...HashSet
00b0: 2c 0a 09 7d 2c 0a 09 73 79 6e 63 3a 3a 7b 41 72 ,..},..sync::{Ar
00c0: 63 2c 20 4d 75 74 65 78 7d 2c 0a 7d 3b 0a 0a 23 c, Mutex},.};..#
00d0: 5b 64 65 72 69 76 65 28 43 6c 6f 6e 65 29 5d 0a [derive(Clone)].
00e0: 70 75 62 20 73 74 72 75 63 74 20 43 6f 72 65 20 pub struct Core
00f0: 7b 0a 09 2f 2f 6f 77 6e 65 72 3a 20 69 36 34 2c {..//owner: i64,
0100: 0a 09 2f 2f 61 70 69 5f 6b 65 79 3a 20 53 74 72 ..//api_key: Str
0110: 69 6e 67 2c 0a 09 6f 77 6e 65 72 5f 63 68 61 74 ing,..owner_chat
0120: 3a 20 74 65 6c 65 67 72 61 6d 5f 62 6f 74 3a 3a : telegram_bot::
0130: 55 73 65 72 49 64 2c 0a 09 70 75 62 20 74 67 3a UserId,..pub tg:
0140: 20 74 65 6c 65 67 72 61 6d 5f 62 6f 74 3a 3a 41 telegram_bot::A
0150: 70 69 2c 0a 09 70 75 62 20 6d 79 3a 20 74 65 6c pi,..pub my: tel
0160: 65 67 72 61 6d 5f 62 6f 74 3a 3a 55 73 65 72 2c egram_bot::User,
0170: 0a 09 70 6f 6f 6c 3a 20 73 71 6c 78 3a 3a 50 6f ..pool: sqlx::Po
0180: 6f 6c 3c 73 71 6c 78 3a 3a 50 6f 73 74 67 72 65 ol<sqlx::Postgre
0190: 73 3e 2c 0a 09 73 6f 75 72 63 65 73 3a 20 41 72 s>,..sources: Ar
01a0: 63 3c 4d 75 74 65 78 3c 48 61 73 68 53 65 74 3c c<Mutex<HashSet<
01b0: 41 72 63 3c 69 33 32 3e 3e 3e 3e 2c 0a 7d 0a 0a Arc<i32>>>>,.}..
01c0: 69 6d 70 6c 20 43 6f 72 65 20 7b 0a 09 70 75 62 impl Core {..pub
01d0: 20 61 73 79 6e 63 20 66 6e 20 6e 65 77 28 73 65 async fn new(se
01e0: 74 74 69 6e 67 73 3a 20 63 6f 6e 66 69 67 3a 3a ttings: config::
01f0: 43 6f 6e 66 69 67 29 20 2d 3e 20 52 65 73 75 6c Config) -> Resul
0200: 74 3c 41 72 63 3c 43 6f 72 65 3e 3e 20 7b 0a 09 t<Arc<Core>> {..
0210: 09 6c 65 74 20 6f 77 6e 65 72 20 3d 20 73 65 74 .let owner = set
0220: 74 69 6e 67 73 2e 67 65 74 5f 69 6e 74 28 22 6f tings.get_int("o
0230: 77 6e 65 72 22 29 3f 3b 0a 09 09 6c 65 74 20 61 wner")?;...let a
0240: 70 69 5f 6b 65 79 20 3d 20 73 65 74 74 69 6e 67 pi_key = setting
0250: 73 2e 67 65 74 5f 73 74 72 69 6e 67 28 22 61 70 s.get_string("ap
0260: 69 5f 6b 65 79 22 29 3f 3b 0a 09 09 6c 65 74 20 i_key")?;...let
0270: 74 67 20 3d 20 74 65 6c 65 67 72 61 6d 5f 62 6f tg = telegram_bo
0280: 74 3a 3a 41 70 69 3a 3a 6e 65 77 28 26 61 70 69 t::Api::new(&api
0290: 5f 6b 65 79 29 3b 0a 09 09 6c 65 74 20 63 6f 72 _key);...let cor
02a0: 65 20 3d 20 41 72 63 3a 3a 6e 65 77 28 43 6f 72 e = Arc::new(Cor
02b0: 65 20 7b 0a 09 09 09 2f 2f 6f 77 6e 65 72 2c 0a e {....//owner,.
02c0: 09 09 09 2f 2f 61 70 69 5f 6b 65 79 3a 20 61 70 ...//api_key: ap
02d0: 69 5f 6b 65 79 2e 63 6c 6f 6e 65 28 29 2c 0a 09 i_key.clone(),..
02e0: 09 09 6d 79 3a 20 74 67 2e 73 65 6e 64 28 74 65 ..my: tg.send(te
02f0: 6c 65 67 72 61 6d 5f 62 6f 74 3a 3a 47 65 74 4d legram_bot::GetM
0300: 65 29 2e 61 77 61 69 74 3f 2c 0a 09 09 09 74 67 e).await?,....tg
0310: 2c 0a 09 09 09 6f 77 6e 65 72 5f 63 68 61 74 3a ,....owner_chat:
0320: 20 74 65 6c 65 67 72 61 6d 5f 62 6f 74 3a 3a 55 telegram_bot::U
0330: 73 65 72 49 64 3a 3a 6e 65 77 28 6f 77 6e 65 72 serId::new(owner
0340: 29 2c 0a 09 09 09 70 6f 6f 6c 3a 20 50 67 50 6f ),....pool: PgPo
0350: 6f 6c 4f 70 74 69 6f 6e 73 3a 3a 6e 65 77 28 29 olOptions::new()
0360: 0a 09 09 09 09 2e 6d 61 78 5f 63 6f 6e 6e 65 63 ......max_connec
0370: 74 69 6f 6e 73 28 35 29 0a 09 09 09 09 2e 63 6f tions(5)......co
0380: 6e 6e 65 63 74 5f 74 69 6d 65 6f 75 74 28 73 74 nnect_timeout(st
0390: 64 3a 3a 74 69 6d 65 3a 3a 44 75 72 61 74 69 6f d::time::Duratio
03a0: 6e 3a 3a 6e 65 77 28 33 30 30 2c 20 30 29 29 0a n::new(300, 0)).
03b0: 09 09 09 09 2e 69 64 6c 65 5f 74 69 6d 65 6f 75 .....idle_timeou
03c0: 74 28 73 74 64 3a 3a 74 69 6d 65 3a 3a 44 75 72 t(std::time::Dur
03d0: 61 74 69 6f 6e 3a 3a 6e 65 77 28 36 30 2c 20 30 ation::new(60, 0
03e0: 29 29 0a 09 09 09 09 2e 63 6f 6e 6e 65 63 74 5f ))......connect_
03f0: 6c 61 7a 79 28 26 73 65 74 74 69 6e 67 73 2e 67 lazy(&settings.g
0400: 65 74 5f 73 74 72 69 6e 67 28 22 70 67 22 29 3f et_string("pg")?
0410: 29 3f 2c 0a 09 09 09 73 6f 75 72 63 65 73 3a 20 )?,....sources:
0420: 41 72 63 3a 3a 6e 65 77 28 4d 75 74 65 78 3a 3a Arc::new(Mutex::
0430: 6e 65 77 28 48 61 73 68 53 65 74 3a 3a 6e 65 77 new(HashSet::new
0440: 28 29 29 29 2c 0a 09 09 7d 29 3b 0a 09 09 6c 65 ())),...});...le
0450: 74 20 63 6c 6f 6e 65 20 3d 20 63 6f 72 65 2e 63 t clone = core.c
0460: 6c 6f 6e 65 28 29 3b 0a 09 09 74 6f 6b 69 6f 3a lone();...tokio:
0470: 3a 73 70 61 77 6e 28 61 73 79 6e 63 20 6d 6f 76 :spawn(async mov
0480: 65 20 7b 0a 09 09 09 6c 6f 6f 70 20 7b 0a 09 09 e {....loop {...
0490: 09 09 6c 65 74 20 64 65 6c 61 79 20 3d 20 6d 61 ..let delay = ma
04a0: 74 63 68 20 26 63 6c 6f 6e 65 2e 61 75 74 6f 66 tch &clone.autof
04b0: 65 74 63 68 28 29 2e 61 77 61 69 74 20 7b 0a 09 etch().await {..
04c0: 09 09 09 09 45 72 72 28 65 72 72 29 20 3d 3e 20 ....Err(err) =>
04d0: 7b 0a 09 09 09 09 09 09 69 66 20 6c 65 74 20 45 {.......if let E
04e0: 72 72 28 65 72 72 29 20 3d 20 63 6c 6f 6e 65 2e rr(err) = clone.
04f0: 73 65 6e 64 28 66 6f 72 6d 61 74 21 28 22 f0 9f send(format!("š
0500: 9b 91 20 7b 3a 3f 7d 22 2c 20 65 72 72 29 2c 20 {:?}", err),
0510: 4e 6f 6e 65 2c 20 4e 6f 6e 65 29 2e 61 77 61 69 None, None).awai
0520: 74 20 7b 0a 09 09 09 09 09 09 09 65 70 72 69 6e t {........eprin
0530: 74 6c 6e 21 28 22 41 75 74 6f 66 65 74 63 68 20 tln!("Autofetch
0540: 65 72 72 6f 72 3a 20 7b 7d 22 2c 20 65 72 72 29 error: {}", err)
0550: 3b 0a 09 09 09 09 09 09 7d 3b 0a 09 09 09 09 09 ;.......};......
0560: 09 74 6f 6b 69 6f 3a 3a 74 69 6d 65 3a 3a 44 75 .tokio::time::Du
0570: 72 61 74 69 6f 6e 3a 3a 66 72 6f 6d 5f 73 65 63 ration::from_sec
0580: 73 28 36 30 29 0a 09 09 09 09 09 7d 2c 0a 09 09 s(60)......},...
0590: 09 09 09 4f 6b 28 74 69 6d 65 29 20 3d 3e 20 2a ...Ok(time) => *
05a0: 74 69 6d 65 2c 0a 09 09 09 09 7d 3b 0a 09 09 09 time,.....};....
05b0: 09 74 6f 6b 69 6f 3a 3a 74 69 6d 65 3a 3a 73 6c .tokio::time::sl
05c0: 65 65 70 28 64 65 6c 61 79 29 2e 61 77 61 69 74 eep(delay).await
05d0: 3b 0a 09 09 09 7d 0a 09 09 7d 29 3b 0a 09 09 4f ;....}...});...O
05e0: 6b 28 63 6f 72 65 29 0a 09 7d 0a 0a 09 70 75 62 k(core)..}...pub
05f0: 20 66 6e 20 73 74 72 65 61 6d 28 26 73 65 6c 66 fn stream(&self
0600: 29 20 2d 3e 20 74 65 6c 65 67 72 61 6d 5f 62 6f ) -> telegram_bo
0610: 74 3a 3a 55 70 64 61 74 65 73 53 74 72 65 61 6d t::UpdatesStream
0620: 20 7b 0a 09 09 73 65 6c 66 2e 74 67 2e 73 74 72 {...self.tg.str
0630: 65 61 6d 28 29 0a 09 7d 0a 0a 09 70 75 62 20 61 eam()..}...pub a
0640: 73 79 6e 63 20 66 6e 20 73 65 6e 64 3c 27 61 2c sync fn send<'a,
0650: 20 53 3e 28 26 73 65 6c 66 2c 20 6d 73 67 3a 20 S>(&self, msg:
0660: 53 2c 20 74 61 72 67 65 74 3a 20 4f 70 74 69 6f S, target: Optio
0670: 6e 3c 74 65 6c 65 67 72 61 6d 5f 62 6f 74 3a 3a n<telegram_bot::
0680: 55 73 65 72 49 64 3e 2c 20 6d 6f 64 65 3a 20 4f UserId>, mode: O
0690: 70 74 69 6f 6e 3c 74 65 6c 65 67 72 61 6d 5f 62 ption<telegram_b
06a0: 6f 74 3a 3a 74 79 70 65 73 3a 3a 50 61 72 73 65 ot::types::Parse
06b0: 4d 6f 64 65 3e 29 20 2d 3e 20 52 65 73 75 6c 74 Mode>) -> Result
06c0: 3c 28 29 3e 0a 09 77 68 65 72 65 20 53 3a 20 49 <()>..where S: I
06d0: 6e 74 6f 3c 43 6f 77 3c 27 61 2c 20 73 74 72 3e nto<Cow<'a, str>
06e0: 3e 20 7b 0a 09 09 6c 65 74 20 6d 6f 64 65 20 3d > {...let mode =
06f0: 20 6d 6f 64 65 2e 75 6e 77 72 61 70 5f 6f 72 28 mode.unwrap_or(
0700: 74 65 6c 65 67 72 61 6d 5f 62 6f 74 3a 3a 74 79 telegram_bot::ty
0710: 70 65 73 3a 3a 50 61 72 73 65 4d 6f 64 65 3a 3a pes::ParseMode::
0720: 48 74 6d 6c 29 3b 0a 09 09 6c 65 74 20 74 61 72 Html);...let tar
0730: 67 65 74 20 3d 20 74 61 72 67 65 74 2e 75 6e 77 get = target.unw
0740: 72 61 70 5f 6f 72 28 73 65 6c 66 2e 6f 77 6e 65 rap_or(self.owne
0750: 72 5f 63 68 61 74 29 3b 0a 09 09 73 65 6c 66 2e r_chat);...self.
0760: 74 67 2e 73 65 6e 64 28 74 65 6c 65 67 72 61 6d tg.send(telegram
0770: 5f 62 6f 74 3a 3a 53 65 6e 64 4d 65 73 73 61 67 _bot::SendMessag
0780: 65 3a 3a 6e 65 77 28 74 61 72 67 65 74 2c 20 6d e::new(target, m
0790: 73 67 29 2e 70 61 72 73 65 5f 6d 6f 64 65 28 6d sg).parse_mode(m
07a0: 6f 64 65 29 29 2e 61 77 61 69 74 3f 3b 0a 09 09 ode)).await?;...
07b0: 4f 6b 28 28 29 29 0a 09 7d 0a 0a 09 70 75 62 20 Ok(())..}...pub
07c0: 61 73 79 6e 63 20 66 6e 20 63 68 65 63 6b 3c 53 async fn check<S
07d0: 3e 28 26 73 65 6c 66 2c 20 69 64 3a 20 26 69 33 >(&self, id: &i3
07e0: 32 2c 20 6f 77 6e 65 72 3a 20 53 2c 20 72 65 61 2, owner: S, rea
07f0: 6c 3a 20 62 6f 6f 6c 29 20 2d 3e 20 52 65 73 75 l: bool) -> Resu
0800: 6c 74 3c 43 6f 77 3c 27 5f 2c 20 73 74 72 3e 3e lt<Cow<'_, str>>
0810: 0a 09 77 68 65 72 65 20 53 3a 20 49 6e 74 6f 3c ..where S: Into<
0820: 69 36 34 3e 20 7b 0a 09 09 6c 65 74 20 6f 77 6e i64> {...let own
0830: 65 72 20 3d 20 6f 77 6e 65 72 2e 69 6e 74 6f 28 er = owner.into(
0840: 29 3b 0a 0a 09 09 6c 65 74 20 6d 75 74 20 70 6f );....let mut po
0850: 73 74 65 64 3a 20 69 33 32 20 3d 20 30 3b 0a 09 sted: i32 = 0;..
0860: 09 6c 65 74 20 69 64 20 3d 20 7b 0a 09 09 09 6c .let id = {....l
0870: 65 74 20 6d 75 74 20 73 65 74 20 3d 20 73 65 6c et mut set = sel
0880: 66 2e 73 6f 75 72 63 65 73 2e 6c 6f 63 6b 28 29 f.sources.lock()
0890: 2e 75 6e 77 72 61 70 28 29 3b 0a 09 09 09 6d 61 .unwrap();....ma
08a0: 74 63 68 20 73 65 74 2e 67 65 74 28 69 64 29 20 tch set.get(id)
08b0: 7b 0a 09 09 09 09 53 6f 6d 65 28 69 64 29 20 3d {.....Some(id) =
08c0: 3e 20 69 64 2e 63 6c 6f 6e 65 28 29 2c 0a 09 09 > id.clone(),...
08d0: 09 09 4e 6f 6e 65 20 3d 3e 20 7b 0a 09 09 09 09 ..None => {.....
08e0: 09 6c 65 74 20 69 64 20 3d 20 41 72 63 3a 3a 6e .let id = Arc::n
08f0: 65 77 28 2a 69 64 29 3b 0a 09 09 09 09 09 73 65 ew(*id);......se
0900: 74 2e 69 6e 73 65 72 74 28 69 64 2e 63 6c 6f 6e t.insert(id.clon
0910: 65 28 29 29 3b 0a 09 09 09 09 09 69 64 2e 63 6c e());......id.cl
0920: 6f 6e 65 28 29 0a 09 09 09 09 7d 2c 0a 09 09 09 one().....},....
0930: 7d 0a 09 09 7d 3b 0a 09 09 6c 65 74 20 63 6f 75 }...};...let cou
0940: 6e 74 20 3d 20 41 72 63 3a 3a 73 74 72 6f 6e 67 nt = Arc::strong
0950: 5f 63 6f 75 6e 74 28 26 69 64 29 3b 0a 09 09 69 _count(&id);...i
0960: 66 20 63 6f 75 6e 74 20 3d 3d 20 32 20 7b 0a 09 f count == 2 {..
0970: 09 09 6c 65 74 20 6d 75 74 20 63 6f 6e 6e 20 3d ..let mut conn =
0980: 20 73 65 6c 66 2e 70 6f 6f 6c 2e 61 63 71 75 69 self.pool.acqui
0990: 72 65 28 29 2e 61 77 61 69 74 0a 09 09 09 09 2e re().await......
09a0: 77 69 74 68 5f 63 6f 6e 74 65 78 74 28 7c 7c 20 with_context(||
09b0: 66 6f 72 6d 61 74 21 28 22 51 75 65 72 79 20 71 format!("Query q
09c0: 75 65 75 65 20 66 65 74 63 68 20 63 6f 6e 6e 3a ueue fetch conn:
09d0: 5c 6e 7b 3a 3f 7d 22 2c 20 26 73 65 6c 66 2e 70 \n{:?}", &self.p
09e0: 6f 6f 6c 29 29 3f 3b 0a 09 09 09 6c 65 74 20 72 ool))?;....let r
09f0: 6f 77 20 3d 20 73 71 6c 78 3a 3a 71 75 65 72 79 ow = sqlx::query
0a00: 28 22 73 65 6c 65 63 74 20 73 6f 75 72 63 65 5f ("select source_
0a10: 69 64 2c 20 63 68 61 6e 6e 65 6c 5f 69 64 2c 20 id, channel_id,
0a20: 75 72 6c 2c 20 69 76 5f 68 61 73 68 2c 20 6f 77 url, iv_hash, ow
0a30: 6e 65 72 2c 20 75 72 6c 5f 72 65 20 66 72 6f 6d ner, url_re from
0a40: 20 72 73 73 74 67 5f 73 6f 75 72 63 65 20 77 68 rsstg_source wh
0a50: 65 72 65 20 73 6f 75 72 63 65 5f 69 64 20 3d 20 ere source_id =
0a60: 24 31 20 61 6e 64 20 6f 77 6e 65 72 20 3d 20 24 $1 and owner = $
0a70: 32 22 29 0a 09 09 09 09 2e 62 69 6e 64 28 2a 69 2")......bind(*i
0a80: 64 29 0a 09 09 09 09 2e 62 69 6e 64 28 6f 77 6e d)......bind(own
0a90: 65 72 29 0a 09 09 09 09 2e 66 65 74 63 68 5f 6f er)......fetch_o
0aa0: 6e 65 28 26 6d 75 74 20 63 6f 6e 6e 29 2e 61 77 ne(&mut conn).aw
0ab0: 61 69 74 0a 09 09 09 09 2e 77 69 74 68 5f 63 6f ait......with_co
0ac0: 6e 74 65 78 74 28 7c 7c 20 66 6f 72 6d 61 74 21 ntext(|| format!
0ad0: 28 22 51 75 65 72 79 20 73 6f 75 72 63 65 3a 5c ("Query source:\
0ae0: 6e 7b 3a 3f 7d 22 2c 20 26 73 65 6c 66 2e 70 6f n{:?}", &self.po
0af0: 6f 6c 29 29 3f 3b 0a 09 09 09 64 72 6f 70 28 63 ol))?;....drop(c
0b00: 6f 6e 6e 29 3b 0a 09 09 09 6c 65 74 20 63 68 61 onn);....let cha
0b10: 6e 6e 65 6c 5f 69 64 3a 20 69 36 34 20 3d 20 72 nnel_id: i64 = r
0b20: 6f 77 2e 74 72 79 5f 67 65 74 28 22 63 68 61 6e ow.try_get("chan
0b30: 6e 65 6c 5f 69 64 22 29 3f 3b 0a 09 09 09 6c 65 nel_id")?;....le
0b40: 74 20 75 72 6c 3a 20 26 73 74 72 20 3d 20 72 6f t url: &str = ro
0b50: 77 2e 74 72 79 5f 67 65 74 28 22 75 72 6c 22 29 w.try_get("url")
0b60: 3f 3b 0a 09 09 09 6c 65 74 20 69 76 5f 68 61 73 ?;....let iv_has
0b70: 68 3a 20 4f 70 74 69 6f 6e 3c 26 73 74 72 3e 20 h: Option<&str>
0b80: 3d 20 72 6f 77 2e 74 72 79 5f 67 65 74 28 22 69 = row.try_get("i
0b90: 76 5f 68 61 73 68 22 29 3f 3b 0a 09 09 09 6c 65 v_hash")?;....le
0ba0: 74 20 75 72 6c 5f 72 65 20 3d 20 6d 61 74 63 68 t url_re = match
0bb0: 20 72 6f 77 2e 74 72 79 5f 67 65 74 28 22 75 72 row.try_get("ur
0bc0: 6c 5f 72 65 22 29 3f 20 7b 0a 09 09 09 09 53 6f l_re")? {.....So
0bd0: 6d 65 28 78 29 20 3d 3e 20 53 6f 6d 65 28 73 65 me(x) => Some(se
0be0: 64 72 65 67 65 78 3a 3a 52 65 70 6c 61 63 65 43 dregex::ReplaceC
0bf0: 6f 6d 6d 61 6e 64 3a 3a 6e 65 77 28 78 29 3f 29 ommand::new(x)?)
0c00: 2c 0a 09 09 09 09 4e 6f 6e 65 20 3d 3e 20 4e 6f ,.....None => No
0c10: 6e 65 2c 0a 09 09 09 7d 3b 0a 09 09 09 6c 65 74 ne,....};....let
0c20: 20 64 65 73 74 69 6e 61 74 69 6f 6e 20 3d 20 6d destination = m
0c30: 61 74 63 68 20 72 65 61 6c 20 7b 0a 09 09 09 09 atch real {.....
0c40: 74 72 75 65 20 3d 3e 20 74 65 6c 65 67 72 61 6d true => telegram
0c50: 5f 62 6f 74 3a 3a 55 73 65 72 49 64 3a 3a 6e 65 _bot::UserId::ne
0c60: 77 28 63 68 61 6e 6e 65 6c 5f 69 64 29 2c 0a 09 w(channel_id),..
0c70: 09 09 09 66 61 6c 73 65 20 3d 3e 20 74 65 6c 65 ...false => tele
0c80: 67 72 61 6d 5f 62 6f 74 3a 3a 55 73 65 72 49 64 gram_bot::UserId
0c90: 3a 3a 6e 65 77 28 72 6f 77 2e 74 72 79 5f 67 65 ::new(row.try_ge
0ca0: 74 28 22 6f 77 6e 65 72 22 29 3f 29 2c 0a 09 09 t("owner")?),...
0cb0: 09 7d 3b 0a 09 09 09 6c 65 74 20 6d 75 74 20 74 .};....let mut t
0cc0: 68 69 73 5f 66 65 74 63 68 3a 20 4f 70 74 69 6f his_fetch: Optio
0cd0: 6e 3c 44 61 74 65 54 69 6d 65 3c 63 68 72 6f 6e n<DateTime<chron
0ce0: 6f 3a 3a 46 69 78 65 64 4f 66 66 73 65 74 3e 3e o::FixedOffset>>
0cf0: 20 3d 20 4e 6f 6e 65 3b 0a 09 09 09 6c 65 74 20 = None;....let
0d00: 6d 75 74 20 70 6f 73 74 73 3a 20 42 54 72 65 65 mut posts: BTree
0d10: 4d 61 70 3c 44 61 74 65 54 69 6d 65 3c 63 68 72 Map<DateTime<chr
0d20: 6f 6e 6f 3a 3a 46 69 78 65 64 4f 66 66 73 65 74 ono::FixedOffset
0d30: 3e 2c 20 53 74 72 69 6e 67 3e 20 3d 20 42 54 72 >, String> = BTr
0d40: 65 65 4d 61 70 3a 3a 6e 65 77 28 29 3b 0a 09 09 eeMap::new();...
0d50: 09 6c 65 74 20 72 65 73 70 6f 6e 73 65 20 3d 20 .let response =
0d60: 72 65 71 77 65 73 74 3a 3a 67 65 74 28 75 72 6c reqwest::get(url
0d70: 29 2e 61 77 61 69 74 3f 3b 0a 09 09 09 6c 65 74 ).await?;....let
0d80: 20 73 74 61 74 75 73 20 3d 20 72 65 73 70 6f 6e status = respon
0d90: 73 65 2e 73 74 61 74 75 73 28 29 3b 0a 09 09 09 se.status();....
0da0: 6c 65 74 20 63 6f 6e 74 65 6e 74 20 3d 20 72 65 let content = re
0db0: 73 70 6f 6e 73 65 2e 62 79 74 65 73 28 29 2e 61 sponse.bytes().a
0dc0: 77 61 69 74 3f 3b 0a 09 09 09 6d 61 74 63 68 20 wait?;....match
0dd0: 72 73 73 3a 3a 43 68 61 6e 6e 65 6c 3a 3a 72 65 rss::Channel::re
0de0: 61 64 5f 66 72 6f 6d 28 26 63 6f 6e 74 65 6e 74 ad_from(&content
0df0: 5b 2e 2e 5d 29 20 7b 0a 09 09 09 09 4f 6b 28 66 [..]) {.....Ok(f
0e00: 65 65 64 29 20 3d 3e 20 7b 0a 09 09 09 09 09 66 eed) => {......f
0e10: 6f 72 20 69 74 65 6d 20 69 6e 20 66 65 65 64 2e or item in feed.
0e20: 69 74 65 6d 73 28 29 20 7b 0a 09 09 09 09 09 09 items() {.......
0e30: 69 66 20 6c 65 74 20 53 6f 6d 65 28 6c 69 6e 6b if let Some(link
0e40: 29 20 3d 20 69 74 65 6d 2e 6c 69 6e 6b 28 29 20 ) = item.link()
0e50: 7b 0a 09 09 09 09 09 09 09 6c 65 74 20 64 61 74 {........let dat
0e60: 65 20 3d 20 6d 61 74 63 68 20 69 74 65 6d 2e 70 e = match item.p
0e70: 75 62 5f 64 61 74 65 28 29 20 7b 0a 09 09 09 09 ub_date() {.....
0e80: 09 09 09 09 53 6f 6d 65 28 66 65 65 64 5f 64 61 ....Some(feed_da
0e90: 74 65 29 20 3d 3e 20 44 61 74 65 54 69 6d 65 3a te) => DateTime:
0ea0: 3a 70 61 72 73 65 5f 66 72 6f 6d 5f 72 66 63 32 :parse_from_rfc2
0eb0: 38 32 32 28 66 65 65 64 5f 64 61 74 65 29 2c 0a 822(feed_date),.
0ec0: 09 09 09 09 09 09 09 09 4e 6f 6e 65 20 3d 3e 20 ........None =>
0ed0: 44 61 74 65 54 69 6d 65 3a 3a 70 61 72 73 65 5f DateTime::parse_
0ee0: 66 72 6f 6d 5f 72 66 63 33 33 33 39 28 26 69 74 from_rfc3339(&it
0ef0: 65 6d 2e 64 75 62 6c 69 6e 5f 63 6f 72 65 5f 65 em.dublin_core_e
0f00: 78 74 28 29 2e 75 6e 77 72 61 70 28 29 2e 64 61 xt().unwrap().da
0f10: 74 65 73 28 29 5b 30 5d 29 2c 0a 09 09 09 09 09 tes()[0]),......
0f20: 09 09 7d 3f 3b 0a 09 09 09 09 09 09 09 6c 65 74 ..}?;........let
0f30: 20 75 72 6c 20 3d 20 6c 69 6e 6b 3b 0a 09 09 09 url = link;....
0f40: 09 09 09 09 70 6f 73 74 73 2e 69 6e 73 65 72 74 ....posts.insert
0f50: 28 64 61 74 65 2c 20 75 72 6c 2e 74 6f 5f 73 74 (date, url.to_st
0f60: 72 69 6e 67 28 29 29 3b 0a 09 09 09 09 09 09 7d ring());.......}
0f70: 0a 09 09 09 09 09 7d 3b 0a 09 09 09 09 7d 2c 0a ......};.....},.
0f80: 09 09 09 09 45 72 72 28 65 72 72 29 20 3d 3e 20 ....Err(err) =>
0f90: 6d 61 74 63 68 20 65 72 72 20 7b 0a 09 09 09 09 match err {.....
0fa0: 09 72 73 73 3a 3a 45 72 72 6f 72 3a 3a 49 6e 76 .rss::Error::Inv
0fb0: 61 6c 69 64 53 74 61 72 74 54 61 67 20 3d 3e 20 alidStartTag =>
0fc0: 7b 0a 09 09 09 09 09 09 6c 65 74 20 66 65 65 64 {.......let feed
0fd0: 20 3d 20 61 74 6f 6d 5f 73 79 6e 64 69 63 61 74 = atom_syndicat
0fe0: 69 6f 6e 3a 3a 46 65 65 64 3a 3a 72 65 61 64 5f ion::Feed::read_
0ff0: 66 72 6f 6d 28 26 63 6f 6e 74 65 6e 74 5b 2e 2e from(&content[..
1000: 5d 29 0a 09 09 09 09 09 09 09 2e 77 69 74 68 5f ]).........with_
1010: 63 6f 6e 74 65 78 74 28 7c 7c 20 66 6f 72 6d 61 context(|| forma
1020: 74 21 28 22 50 72 6f 62 6c 65 6d 20 6f 70 65 6e t!("Problem open
1030: 69 6e 67 20 66 65 65 64 20 75 72 6c 3a 5c 6e 7b ing feed url:\n{
1040: 7d 5c 6e 7b 7d 22 2c 20 26 75 72 6c 2c 20 73 74 }\n{}", &url, st
1050: 61 74 75 73 29 29 3f 3b 0a 09 09 09 09 09 09 66 atus))?;.......f
1060: 6f 72 20 69 74 65 6d 20 69 6e 20 66 65 65 64 2e or item in feed.
1070: 65 6e 74 72 69 65 73 28 29 20 7b 0a 09 09 09 09 entries() {.....
1080: 09 09 09 6c 65 74 20 64 61 74 65 20 3d 20 69 74 ...let date = it
1090: 65 6d 2e 70 75 62 6c 69 73 68 65 64 28 29 2e 75 em.published().u
10a0: 6e 77 72 61 70 28 29 3b 0a 09 09 09 09 09 09 09 nwrap();........
10b0: 6c 65 74 20 75 72 6c 20 3d 20 69 74 65 6d 2e 6c let url = item.l
10c0: 69 6e 6b 73 28 29 5b 30 5d 2e 68 72 65 66 28 29 inks()[0].href()
10d0: 3b 0a 09 09 09 09 09 09 09 70 6f 73 74 73 2e 69 ;........posts.i
10e0: 6e 73 65 72 74 28 2a 64 61 74 65 2c 20 75 72 6c nsert(*date, url
10f0: 2e 74 6f 5f 73 74 72 69 6e 67 28 29 29 3b 0a 09 .to_string());..
1100: 09 09 09 09 09 7d 3b 0a 09 09 09 09 09 7d 2c 0a .....};......},.
1110: 09 09 09 09 09 72 73 73 3a 3a 45 72 72 6f 72 3a .....rss::Error:
1120: 3a 45 6f 66 20 3d 3e 20 28 29 2c 0a 09 09 09 09 :Eof => (),.....
1130: 09 5f 20 3d 3e 20 62 61 69 6c 21 28 22 55 6e 73 ._ => bail!("Uns
1140: 75 70 70 6f 72 74 65 64 20 6f 72 20 6d 61 6e 67 upported or mang
1150: 6c 65 64 20 63 6f 6e 74 65 6e 74 3a 5c 6e 7b 3a led content:\n{:
1160: 3f 7d 5c 6e 7b 3a 23 3f 7d 5c 6e 7b 3a 23 3f 7d ?}\n{:#?}\n{:#?}
1170: 5c 6e 22 2c 20 26 75 72 6c 2c 20 65 72 72 2c 20 \n", &url, err,
1180: 73 74 61 74 75 73 29 0a 09 09 09 09 7d 0a 09 09 status).....}...
1190: 09 7d 3b 0a 09 09 09 66 6f 72 20 28 64 61 74 65 .};....for (date
11a0: 2c 20 75 72 6c 29 20 69 6e 20 70 6f 73 74 73 2e , url) in posts.
11b0: 69 74 65 72 28 29 20 7b 0a 09 09 09 09 6c 65 74 iter() {.....let
11c0: 20 6d 75 74 20 63 6f 6e 6e 20 3d 20 73 65 6c 66 mut conn = self
11d0: 2e 70 6f 6f 6c 2e 61 63 71 75 69 72 65 28 29 2e .pool.acquire().
11e0: 61 77 61 69 74 0a 09 09 09 09 09 2e 77 69 74 68 await.......with
11f0: 5f 63 6f 6e 74 65 78 74 28 7c 7c 20 66 6f 72 6d _context(|| form
1200: 61 74 21 28 22 43 68 65 63 6b 20 70 6f 73 74 20 at!("Check post
1210: 66 65 74 63 68 20 63 6f 6e 6e 3a 5c 6e 7b 3a 3f fetch conn:\n{:?
1220: 7d 22 2c 20 26 73 65 6c 66 2e 70 6f 6f 6c 29 29 }", &self.pool))
1230: 3f 3b 0a 09 09 09 09 6c 65 74 20 70 6f 73 74 5f ?;.....let post_
1240: 75 72 6c 3a 20 43 6f 77 3c 73 74 72 3e 20 3d 20 url: Cow<str> =
1250: 6d 61 74 63 68 20 75 72 6c 5f 72 65 20 7b 0a 09 match url_re {..
1260: 09 09 09 09 53 6f 6d 65 28 72 65 66 20 78 29 20 ....Some(ref x)
1270: 3d 3e 20 78 2e 65 78 65 63 75 74 65 28 75 72 6c => x.execute(url
1280: 29 2c 0a 09 09 09 09 09 4e 6f 6e 65 20 3d 3e 20 ),......None =>
1290: 75 72 6c 2e 69 6e 74 6f 28 29 2c 0a 09 09 09 09 url.into(),.....
12a0: 7d 3b 0a 09 09 09 09 6c 65 74 20 72 6f 77 20 3d };.....let row =
12b0: 20 73 71 6c 78 3a 3a 71 75 65 72 79 28 22 73 65 sqlx::query("se
12c0: 6c 65 63 74 20 65 78 69 73 74 73 28 73 65 6c 65 lect exists(sele
12d0: 63 74 20 74 72 75 65 20 66 72 6f 6d 20 72 73 73 ct true from rss
12e0: 74 67 5f 70 6f 73 74 20 77 68 65 72 65 20 75 72 tg_post where ur
12f0: 6c 20 3d 20 24 31 20 61 6e 64 20 73 6f 75 72 63 l = $1 and sourc
1300: 65 5f 69 64 20 3d 20 24 32 29 20 61 73 20 65 78 e_id = $2) as ex
1310: 69 73 74 73 3b 22 29 0a 09 09 09 09 09 2e 62 69 ists;").......bi
1320: 6e 64 28 26 2a 70 6f 73 74 5f 75 72 6c 29 0a 09 nd(&*post_url)..
1330: 09 09 09 09 2e 62 69 6e 64 28 2a 69 64 29 0a 09 .....bind(*id)..
1340: 09 09 09 09 2e 66 65 74 63 68 5f 6f 6e 65 28 26 .....fetch_one(&
1350: 6d 75 74 20 63 6f 6e 6e 29 2e 61 77 61 69 74 0a mut conn).await.
1360: 09 09 09 09 09 2e 77 69 74 68 5f 63 6f 6e 74 65 ......with_conte
1370: 78 74 28 7c 7c 20 66 6f 72 6d 61 74 21 28 22 43 xt(|| format!("C
1380: 68 65 63 6b 20 70 6f 73 74 3a 5c 6e 7b 3a 3f 7d heck post:\n{:?}
1390: 22 2c 20 26 63 6f 6e 6e 29 29 3f 3b 0a 09 09 09 ", &conn))?;....
13a0: 09 6c 65 74 20 65 78 69 73 74 73 3a 20 62 6f 6f .let exists: boo
13b0: 6c 20 3d 20 72 6f 77 2e 74 72 79 5f 67 65 74 28 l = row.try_get(
13c0: 22 65 78 69 73 74 73 22 29 3f 3b 0a 09 09 09 09 "exists")?;.....
13d0: 69 66 20 21 20 65 78 69 73 74 73 20 7b 0a 09 09 if ! exists {...
13e0: 09 09 09 69 66 20 74 68 69 73 5f 66 65 74 63 68 ...if this_fetch
13f0: 20 3d 3d 20 4e 6f 6e 65 20 7c 7c 20 2a 64 61 74 == None || *dat
1400: 65 20 3e 20 74 68 69 73 5f 66 65 74 63 68 2e 75 e > this_fetch.u
1410: 6e 77 72 61 70 28 29 20 7b 0a 09 09 09 09 09 09 nwrap() {.......
1420: 74 68 69 73 5f 66 65 74 63 68 20 3d 20 53 6f 6d this_fetch = Som
1430: 65 28 2a 64 61 74 65 29 3b 0a 09 09 09 09 09 7d e(*date);......}
1440: 3b 0a 09 09 09 09 09 73 65 6c 66 2e 74 67 2e 73 ;......self.tg.s
1450: 65 6e 64 28 20 6d 61 74 63 68 20 69 76 5f 68 61 end( match iv_ha
1460: 73 68 20 7b 0a 09 09 09 09 09 09 09 53 6f 6d 65 sh {........Some
1470: 28 68 61 73 68 29 20 3d 3e 20 74 65 6c 65 67 72 (hash) => telegr
1480: 61 6d 5f 62 6f 74 3a 3a 53 65 6e 64 4d 65 73 73 am_bot::SendMess
1490: 61 67 65 3a 3a 6e 65 77 28 64 65 73 74 69 6e 61 age::new(destina
14a0: 74 69 6f 6e 2c 20 66 6f 72 6d 61 74 21 28 22 3c tion, format!("<
14b0: 61 20 68 72 65 66 3d 5c 22 68 74 74 70 73 3a 2f a href=\"https:/
14c0: 2f 74 2e 6d 65 2f 69 76 3f 75 72 6c 3d 7b 7d 26 /t.me/iv?url={}&
14d0: 72 68 61 73 68 3d 7b 7d 5c 22 3e 20 3c 2f 61 3e rhash={}\"> </a>
14e0: 7b 30 7d 22 2c 20 26 70 6f 73 74 5f 75 72 6c 2c {0}", &post_url,
14f0: 20 68 61 73 68 29 29 2c 0a 09 09 09 09 09 09 09 hash)),........
1500: 4e 6f 6e 65 20 3d 3e 20 74 65 6c 65 67 72 61 6d None => telegram
1510: 5f 62 6f 74 3a 3a 53 65 6e 64 4d 65 73 73 61 67 _bot::SendMessag
1520: 65 3a 3a 6e 65 77 28 64 65 73 74 69 6e 61 74 69 e::new(destinati
1530: 6f 6e 2c 20 66 6f 72 6d 61 74 21 28 22 7b 7d 22 on, format!("{}"
1540: 2c 20 70 6f 73 74 5f 75 72 6c 29 29 2c 0a 09 09 , post_url)),...
1550: 09 09 09 09 7d 2e 70 61 72 73 65 5f 6d 6f 64 65 ....}.parse_mode
1560: 28 74 65 6c 65 67 72 61 6d 5f 62 6f 74 3a 3a 74 (telegram_bot::t
1570: 79 70 65 73 3a 3a 50 61 72 73 65 4d 6f 64 65 3a ypes::ParseMode:
1580: 3a 48 74 6d 6c 29 29 2e 61 77 61 69 74 0a 09 09 :Html)).await...
1590: 09 09 09 09 2e 63 6f 6e 74 65 78 74 28 22 43 61 .....context("Ca
15a0: 6e 27 74 20 70 6f 73 74 20 6d 65 73 73 61 67 65 n't post message
15b0: 3a 22 29 3f 3b 0a 09 09 09 09 09 73 71 6c 78 3a :")?;......sqlx:
15c0: 3a 71 75 65 72 79 28 22 69 6e 73 65 72 74 20 69 :query("insert i
15d0: 6e 74 6f 20 72 73 73 74 67 5f 70 6f 73 74 20 28 nto rsstg_post (
15e0: 73 6f 75 72 63 65 5f 69 64 2c 20 70 6f 73 74 65 source_id, poste
15f0: 64 2c 20 75 72 6c 29 20 76 61 6c 75 65 73 20 28 d, url) values (
1600: 24 31 2c 20 24 32 2c 20 24 33 29 3b 22 29 0a 09 $1, $2, $3);")..
1610: 09 09 09 09 09 2e 62 69 6e 64 28 2a 69 64 29 0a ......bind(*id).
1620: 09 09 09 09 09 09 2e 62 69 6e 64 28 64 61 74 65 .......bind(date
1630: 29 0a 09 09 09 09 09 09 2e 62 69 6e 64 28 26 2a )........bind(&*
1640: 70 6f 73 74 5f 75 72 6c 29 0a 09 09 09 09 09 09 post_url).......
1650: 2e 65 78 65 63 75 74 65 28 26 6d 75 74 20 63 6f .execute(&mut co
1660: 6e 6e 29 2e 61 77 61 69 74 0a 09 09 09 09 09 09 nn).await.......
1670: 2e 77 69 74 68 5f 63 6f 6e 74 65 78 74 28 7c 7c .with_context(||
1680: 20 66 6f 72 6d 61 74 21 28 22 52 65 63 6f 72 64 format!("Record
1690: 20 70 6f 73 74 3a 5c 6e 7b 3a 3f 7d 22 2c 20 26 post:\n{:?}", &
16a0: 63 6f 6e 6e 29 29 3f 3b 0a 09 09 09 09 09 64 72 conn))?;......dr
16b0: 6f 70 28 63 6f 6e 6e 29 3b 0a 09 09 09 09 09 74 op(conn);......t
16c0: 6f 6b 69 6f 3a 3a 74 69 6d 65 3a 3a 73 6c 65 65 okio::time::slee
16d0: 70 28 73 74 64 3a 3a 74 69 6d 65 3a 3a 44 75 72 p(std::time::Dur
16e0: 61 74 69 6f 6e 3a 3a 6e 65 77 28 34 2c 20 30 29 ation::new(4, 0)
16f0: 29 2e 61 77 61 69 74 3b 0a 09 09 09 09 7d 3b 0a ).await;.....};.
1700: 09 09 09 09 70 6f 73 74 65 64 20 2b 3d 20 31 3b ....posted += 1;
1710: 0a 09 09 09 7d 3b 0a 09 09 09 70 6f 73 74 73 2e ....};....posts.
1720: 63 6c 65 61 72 28 29 3b 0a 09 09 7d 3b 0a 09 09 clear();...};...
1730: 6c 65 74 20 6d 75 74 20 63 6f 6e 6e 20 3d 20 73 let mut conn = s
1740: 65 6c 66 2e 70 6f 6f 6c 2e 61 63 71 75 69 72 65 elf.pool.acquire
1750: 28 29 2e 61 77 61 69 74 0a 09 09 09 2e 77 69 74 ().await.....wit
1760: 68 5f 63 6f 6e 74 65 78 74 28 7c 7c 20 66 6f 72 h_context(|| for
1770: 6d 61 74 21 28 22 55 70 64 61 74 65 20 73 63 72 mat!("Update scr
1780: 61 70 65 20 66 65 74 63 68 20 63 6f 6e 6e 3a 5c ape fetch conn:\
1790: 6e 7b 3a 3f 7d 22 2c 20 26 73 65 6c 66 2e 70 6f n{:?}", &self.po
17a0: 6f 6c 29 29 3f 3b 0a 09 09 73 71 6c 78 3a 3a 71 ol))?;...sqlx::q
17b0: 75 65 72 79 28 22 75 70 64 61 74 65 20 72 73 73 uery("update rss
17c0: 74 67 5f 73 6f 75 72 63 65 20 73 65 74 20 6c 61 tg_source set la
17d0: 73 74 5f 73 63 72 61 70 65 20 3d 20 6e 6f 77 28 st_scrape = now(
17e0: 29 20 77 68 65 72 65 20 73 6f 75 72 63 65 5f 69 ) where source_i
17f0: 64 20 3d 20 24 31 3b 22 29 0a 09 09 09 2e 62 69 d = $1;").....bi
1800: 6e 64 28 2a 69 64 29 0a 09 09 09 2e 65 78 65 63 nd(*id).....exec
1810: 75 74 65 28 26 6d 75 74 20 63 6f 6e 6e 29 2e 61 ute(&mut conn).a
1820: 77 61 69 74 0a 09 09 09 2e 77 69 74 68 5f 63 6f wait.....with_co
1830: 6e 74 65 78 74 28 7c 7c 20 66 6f 72 6d 61 74 21 ntext(|| format!
1840: 28 22 55 70 64 61 74 65 20 73 63 72 61 70 65 3a ("Update scrape:
1850: 5c 6e 7b 3a 3f 7d 22 2c 20 26 63 6f 6e 6e 29 29 \n{:?}", &conn))
1860: 3f 3b 0a 09 09 4f 6b 28 66 6f 72 6d 61 74 21 28 ?;...Ok(format!(
1870: 22 50 6f 73 74 65 64 3a 20 7b 7d 22 2c 20 26 70 "Posted: {}", &p
1880: 6f 73 74 65 64 29 2e 69 6e 74 6f 28 29 29 0a 09 osted).into())..
1890: 7d 0a 0a 09 70 75 62 20 61 73 79 6e 63 20 66 6e }...pub async fn
18a0: 20 64 65 6c 65 74 65 3c 53 3e 28 26 73 65 6c 66 delete<S>(&self
18b0: 2c 20 73 6f 75 72 63 65 5f 69 64 3a 20 26 69 33 , source_id: &i3
18c0: 32 2c 20 6f 77 6e 65 72 3a 20 53 29 20 2d 3e 20 2, owner: S) ->
18d0: 52 65 73 75 6c 74 3c 43 6f 77 3c 27 5f 2c 20 73 Result<Cow<'_, s
18e0: 74 72 3e 3e 0a 09 77 68 65 72 65 20 53 3a 20 49 tr>>..where S: I
18f0: 6e 74 6f 3c 69 36 34 3e 20 7b 0a 09 09 6c 65 74 nto<i64> {...let
1900: 20 6f 77 6e 65 72 20 3d 20 6f 77 6e 65 72 2e 69 owner = owner.i
1910: 6e 74 6f 28 29 3b 0a 0a 09 09 6c 65 74 20 6d 75 nto();....let mu
1920: 74 20 63 6f 6e 6e 20 3d 20 73 65 6c 66 2e 70 6f t conn = self.po
1930: 6f 6c 2e 61 63 71 75 69 72 65 28 29 2e 61 77 61 ol.acquire().awa
1940: 69 74 0a 09 09 09 2e 77 69 74 68 5f 63 6f 6e 74 it.....with_cont
1950: 65 78 74 28 7c 7c 20 66 6f 72 6d 61 74 21 28 22 ext(|| format!("
1960: 44 65 6c 65 74 65 20 66 65 74 63 68 20 63 6f 6e Delete fetch con
1970: 6e 3a 5c 6e 7b 3a 3f 7d 22 2c 20 26 73 65 6c 66 n:\n{:?}", &self
1980: 2e 70 6f 6f 6c 29 29 3f 3b 0a 09 09 6d 61 74 63 .pool))?;...matc
1990: 68 20 73 71 6c 78 3a 3a 71 75 65 72 79 28 22 64 h sqlx::query("d
19a0: 65 6c 65 74 65 20 66 72 6f 6d 20 72 73 73 74 67 elete from rsstg
19b0: 5f 73 6f 75 72 63 65 20 77 68 65 72 65 20 73 6f _source where so
19c0: 75 72 63 65 5f 69 64 20 3d 20 24 31 20 61 6e 64 urce_id = $1 and
19d0: 20 6f 77 6e 65 72 20 3d 20 24 32 3b 22 29 0a 09 owner = $2;")..
19e0: 09 09 2e 62 69 6e 64 28 73 6f 75 72 63 65 5f 69 ...bind(source_i
19f0: 64 29 0a 09 09 09 2e 62 69 6e 64 28 6f 77 6e 65 d).....bind(owne
1a00: 72 29 0a 09 09 09 2e 65 78 65 63 75 74 65 28 26 r).....execute(&
1a10: 6d 75 74 20 63 6f 6e 6e 29 2e 61 77 61 69 74 0a mut conn).await.
1a20: 09 09 09 2e 77 69 74 68 5f 63 6f 6e 74 65 78 74 ....with_context
1a30: 28 7c 7c 20 66 6f 72 6d 61 74 21 28 22 44 65 6c (|| format!("Del
1a40: 65 74 65 20 73 6f 75 72 63 65 20 72 75 6c 65 3a ete source rule:
1a50: 5c 6e 7b 3a 3f 7d 22 2c 20 26 73 65 6c 66 2e 70 \n{:?}", &self.p
1a60: 6f 6f 6c 29 29 3f 0a 09 09 09 2e 72 6f 77 73 5f ool))?.....rows_
1a70: 61 66 66 65 63 74 65 64 28 29 20 7b 0a 09 09 09 affected() {....
1a80: 30 20 3d 3e 20 7b 20 4f 6b 28 22 4e 6f 20 64 61 0 => { Ok("No da
1a90: 74 61 20 66 6f 75 6e 64 20 66 6f 75 6e 64 2e 22 ta found found."
1aa0: 2e 69 6e 74 6f 28 29 29 20 7d 2c 0a 09 09 09 78 .into()) },....x
1ab0: 20 3d 3e 20 7b 20 4f 6b 28 66 6f 72 6d 61 74 21 => { Ok(format!
1ac0: 28 22 7b 7d 20 73 6f 75 72 63 65 73 20 72 65 6d ("{} sources rem
1ad0: 6f 76 65 64 2e 22 2c 20 78 29 2e 69 6e 74 6f 28 oved.", x).into(
1ae0: 29 29 20 7d 2c 0a 09 09 7d 0a 09 7d 0a 0a 09 70 )) },...}..}...p
1af0: 75 62 20 61 73 79 6e 63 20 66 6e 20 63 6c 65 61 ub async fn clea
1b00: 6e 3c 53 3e 28 26 73 65 6c 66 2c 20 73 6f 75 72 n<S>(&self, sour
1b10: 63 65 5f 69 64 3a 20 26 69 33 32 2c 20 6f 77 6e ce_id: &i32, own
1b20: 65 72 3a 20 53 29 20 2d 3e 20 52 65 73 75 6c 74 er: S) -> Result
1b30: 3c 43 6f 77 3c 27 5f 2c 20 73 74 72 3e 3e 0a 09 <Cow<'_, str>>..
1b40: 77 68 65 72 65 20 53 3a 20 49 6e 74 6f 3c 69 36 where S: Into<i6
1b50: 34 3e 20 7b 0a 09 09 6c 65 74 20 6f 77 6e 65 72 4> {...let owner
1b60: 20 3d 20 6f 77 6e 65 72 2e 69 6e 74 6f 28 29 3b = owner.into();
1b70: 0a 0a 09 09 6c 65 74 20 6d 75 74 20 63 6f 6e 6e ....let mut conn
1b80: 20 3d 20 73 65 6c 66 2e 70 6f 6f 6c 2e 61 63 71 = self.pool.acq
1b90: 75 69 72 65 28 29 2e 61 77 61 69 74 0a 09 09 09 uire().await....
1ba0: 2e 77 69 74 68 5f 63 6f 6e 74 65 78 74 28 7c 7c .with_context(||
1bb0: 20 66 6f 72 6d 61 74 21 28 22 43 6c 65 61 6e 20 format!("Clean
1bc0: 66 65 74 63 68 20 63 6f 6e 6e 3a 5c 6e 7b 3a 3f fetch conn:\n{:?
1bd0: 7d 22 2c 20 26 73 65 6c 66 2e 70 6f 6f 6c 29 29 }", &self.pool))
1be0: 3f 3b 0a 09 09 6d 61 74 63 68 20 73 71 6c 78 3a ?;...match sqlx:
1bf0: 3a 71 75 65 72 79 28 22 64 65 6c 65 74 65 20 66 :query("delete f
1c00: 72 6f 6d 20 72 73 73 74 67 5f 70 6f 73 74 20 70 rom rsstg_post p
1c10: 20 75 73 69 6e 67 20 72 73 73 74 67 5f 73 6f 75 using rsstg_sou
1c20: 72 63 65 20 73 20 77 68 65 72 65 20 70 2e 73 6f rce s where p.so
1c30: 75 72 63 65 5f 69 64 20 3d 20 24 31 20 61 6e 64 urce_id = $1 and
1c40: 20 6f 77 6e 65 72 20 3d 20 24 32 20 61 6e 64 20 owner = $2 and
1c50: 70 2e 73 6f 75 72 63 65 5f 69 64 20 3d 20 73 2e p.source_id = s.
1c60: 73 6f 75 72 63 65 5f 69 64 3b 22 29 0a 09 09 09 source_id;")....
1c70: 2e 62 69 6e 64 28 73 6f 75 72 63 65 5f 69 64 29 .bind(source_id)
1c80: 0a 09 09 09 2e 62 69 6e 64 28 6f 77 6e 65 72 29 .....bind(owner)
1c90: 0a 09 09 09 2e 65 78 65 63 75 74 65 28 26 6d 75 .....execute(&mu
1ca0: 74 20 63 6f 6e 6e 29 2e 61 77 61 69 74 0a 09 09 t conn).await...
1cb0: 09 2e 77 69 74 68 5f 63 6f 6e 74 65 78 74 28 7c ..with_context(|
1cc0: 7c 20 66 6f 72 6d 61 74 21 28 22 43 6c 65 61 6e | format!("Clean
1cd0: 20 73 65 65 6e 20 70 6f 73 74 73 3a 5c 6e 7b 3a seen posts:\n{:
1ce0: 3f 7d 22 2c 20 26 73 65 6c 66 2e 70 6f 6f 6c 29 ?}", &self.pool)
1cf0: 29 3f 0a 09 09 09 2e 72 6f 77 73 5f 61 66 66 65 )?.....rows_affe
1d00: 63 74 65 64 28 29 20 7b 0a 09 09 09 30 20 3d 3e cted() {....0 =>
1d10: 20 7b 20 4f 6b 28 22 4e 6f 20 64 61 74 61 20 66 { Ok("No data f
1d20: 6f 75 6e 64 20 66 6f 75 6e 64 2e 22 2e 69 6e 74 ound found.".int
1d30: 6f 28 29 29 20 7d 2c 0a 09 09 09 78 20 3d 3e 20 o()) },....x =>
1d40: 7b 20 4f 6b 28 66 6f 72 6d 61 74 21 28 22 7b 7d { Ok(format!("{}
1d50: 20 70 6f 73 74 73 20 70 75 72 67 65 64 2e 22 2c posts purged.",
1d60: 20 78 29 2e 69 6e 74 6f 28 29 29 20 7d 2c 0a 09 x).into()) },..
1d70: 09 7d 0a 09 7d 0a 0a 09 70 75 62 20 61 73 79 6e .}..}...pub asyn
1d80: 63 20 66 6e 20 65 6e 61 62 6c 65 3c 53 3e 28 26 c fn enable<S>(&
1d90: 73 65 6c 66 2c 20 73 6f 75 72 63 65 5f 69 64 3a self, source_id:
1da0: 20 26 69 33 32 2c 20 6f 77 6e 65 72 3a 20 53 29 &i32, owner: S)
1db0: 20 2d 3e 20 52 65 73 75 6c 74 3c 26 73 74 72 3e -> Result<&str>
1dc0: 0a 09 77 68 65 72 65 20 53 3a 20 49 6e 74 6f 3c ..where S: Into<
1dd0: 69 36 34 3e 20 7b 0a 09 09 6c 65 74 20 6f 77 6e i64> {...let own
1de0: 65 72 20 3d 20 6f 77 6e 65 72 2e 69 6e 74 6f 28 er = owner.into(
1df0: 29 3b 0a 0a 09 09 6c 65 74 20 6d 75 74 20 63 6f );....let mut co
1e00: 6e 6e 20 3d 20 73 65 6c 66 2e 70 6f 6f 6c 2e 61 nn = self.pool.a
1e10: 63 71 75 69 72 65 28 29 2e 61 77 61 69 74 0a 09 cquire().await..
1e20: 09 09 2e 77 69 74 68 5f 63 6f 6e 74 65 78 74 28 ...with_context(
1e30: 7c 7c 20 66 6f 72 6d 61 74 21 28 22 45 6e 61 62 || format!("Enab
1e40: 6c 65 20 66 65 74 63 68 20 63 6f 6e 6e 3a 5c 6e le fetch conn:\n
1e50: 7b 3a 3f 7d 22 2c 20 26 73 65 6c 66 2e 70 6f 6f {:?}", &self.poo
1e60: 6c 29 29 3f 3b 0a 09 09 6d 61 74 63 68 20 73 71 l))?;...match sq
1e70: 6c 78 3a 3a 71 75 65 72 79 28 22 75 70 64 61 74 lx::query("updat
1e80: 65 20 72 73 73 74 67 5f 73 6f 75 72 63 65 20 73 e rsstg_source s
1e90: 65 74 20 65 6e 61 62 6c 65 64 20 3d 20 74 72 75 et enabled = tru
1ea0: 65 20 77 68 65 72 65 20 73 6f 75 72 63 65 5f 69 e where source_i
1eb0: 64 20 3d 20 24 31 20 61 6e 64 20 6f 77 6e 65 72 d = $1 and owner
1ec0: 20 3d 20 24 32 22 29 0a 09 09 09 2e 62 69 6e 64 = $2").....bind
1ed0: 28 73 6f 75 72 63 65 5f 69 64 29 0a 09 09 09 2e (source_id).....
1ee0: 62 69 6e 64 28 6f 77 6e 65 72 29 0a 09 09 09 2e bind(owner).....
1ef0: 65 78 65 63 75 74 65 28 26 6d 75 74 20 63 6f 6e execute(&mut con
1f00: 6e 29 2e 61 77 61 69 74 0a 09 09 09 2e 77 69 74 n).await.....wit
1f10: 68 5f 63 6f 6e 74 65 78 74 28 7c 7c 20 66 6f 72 h_context(|| for
1f20: 6d 61 74 21 28 22 45 6e 61 62 6c 65 20 73 6f 75 mat!("Enable sou
1f30: 72 63 65 3a 5c 6e 7b 3a 3f 7d 22 2c 20 26 73 65 rce:\n{:?}", &se
1f40: 6c 66 2e 70 6f 6f 6c 29 29 3f 0a 09 09 09 2e 72 lf.pool))?.....r
1f50: 6f 77 73 5f 61 66 66 65 63 74 65 64 28 29 20 7b ows_affected() {
1f60: 0a 09 09 09 31 20 3d 3e 20 7b 20 4f 6b 28 22 53 ....1 => { Ok("S
1f70: 6f 75 72 63 65 20 65 6e 61 62 6c 65 64 2e 22 29 ource enabled.")
1f80: 20 7d 2c 0a 09 09 09 30 20 3d 3e 20 7b 20 4f 6b },....0 => { Ok
1f90: 28 22 53 6f 75 72 63 65 20 6e 6f 74 20 66 6f 75 ("Source not fou
1fa0: 6e 64 2e 22 29 20 7d 2c 0a 09 09 09 5f 20 3d 3e nd.") },...._ =>
1fb0: 20 7b 20 45 72 72 28 61 6e 79 68 6f 77 21 28 22 { Err(anyhow!("
1fc0: 44 61 74 61 62 61 73 65 20 65 72 72 6f 72 2e 22 Database error."
1fd0: 29 29 20 7d 2c 0a 09 09 7d 0a 09 7d 0a 0a 09 70 )) },...}..}...p
1fe0: 75 62 20 61 73 79 6e 63 20 66 6e 20 64 69 73 61 ub async fn disa
1ff0: 62 6c 65 3c 53 3e 28 26 73 65 6c 66 2c 20 73 6f ble<S>(&self, so
2000: 75 72 63 65 5f 69 64 3a 20 26 69 33 32 2c 20 6f urce_id: &i32, o
2010: 77 6e 65 72 3a 20 53 29 20 2d 3e 20 52 65 73 75 wner: S) -> Resu
2020: 6c 74 3c 26 73 74 72 3e 0a 09 77 68 65 72 65 20 lt<&str>..where
2030: 53 3a 20 49 6e 74 6f 3c 69 36 34 3e 20 7b 0a 09 S: Into<i64> {..
2040: 09 6c 65 74 20 6f 77 6e 65 72 20 3d 20 6f 77 6e .let owner = own
2050: 65 72 2e 69 6e 74 6f 28 29 3b 0a 0a 09 09 6c 65 er.into();....le
2060: 74 20 6d 75 74 20 63 6f 6e 6e 20 3d 20 73 65 6c t mut conn = sel
2070: 66 2e 70 6f 6f 6c 2e 61 63 71 75 69 72 65 28 29 f.pool.acquire()
2080: 2e 61 77 61 69 74 0a 09 09 09 2e 77 69 74 68 5f .await.....with_
2090: 63 6f 6e 74 65 78 74 28 7c 7c 20 66 6f 72 6d 61 context(|| forma
20a0: 74 21 28 22 44 69 73 61 62 6c 65 20 66 65 74 63 t!("Disable fetc
20b0: 68 20 63 6f 6e 6e 3a 5c 6e 7b 3a 3f 7d 22 2c 20 h conn:\n{:?}",
20c0: 26 73 65 6c 66 2e 70 6f 6f 6c 29 29 3f 3b 0a 09 &self.pool))?;..
20d0: 09 6d 61 74 63 68 20 73 71 6c 78 3a 3a 71 75 65 .match sqlx::que
20e0: 72 79 28 22 75 70 64 61 74 65 20 72 73 73 74 67 ry("update rsstg
20f0: 5f 73 6f 75 72 63 65 20 73 65 74 20 65 6e 61 62 _source set enab
2100: 6c 65 64 20 3d 20 66 61 6c 73 65 20 77 68 65 72 led = false wher
2110: 65 20 73 6f 75 72 63 65 5f 69 64 20 3d 20 24 31 e source_id = $1
2120: 20 61 6e 64 20 6f 77 6e 65 72 20 3d 20 24 32 22 and owner = $2"
2130: 29 0a 09 09 09 2e 62 69 6e 64 28 73 6f 75 72 63 ).....bind(sourc
2140: 65 5f 69 64 29 0a 09 09 09 2e 62 69 6e 64 28 6f e_id).....bind(o
2150: 77 6e 65 72 29 0a 09 09 09 2e 65 78 65 63 75 74 wner).....execut
2160: 65 28 26 6d 75 74 20 63 6f 6e 6e 29 2e 61 77 61 e(&mut conn).awa
2170: 69 74 0a 09 09 09 2e 77 69 74 68 5f 63 6f 6e 74 it.....with_cont
2180: 65 78 74 28 7c 7c 20 66 6f 72 6d 61 74 21 28 22 ext(|| format!("
2190: 44 69 73 61 62 6c 65 20 73 6f 75 72 63 65 3a 5c Disable source:\
21a0: 6e 7b 3a 3f 7d 22 2c 20 26 73 65 6c 66 2e 70 6f n{:?}", &self.po
21b0: 6f 6c 29 29 3f 0a 09 09 09 2e 72 6f 77 73 5f 61 ol))?.....rows_a
21c0: 66 66 65 63 74 65 64 28 29 20 7b 0a 09 09 09 31 ffected() {....1
21d0: 20 3d 3e 20 7b 20 4f 6b 28 22 53 6f 75 72 63 65 => { Ok("Source
21e0: 20 64 69 73 61 62 6c 65 64 2e 22 29 20 7d 2c 0a disabled.") },.
21f0: 09 09 09 30 20 3d 3e 20 7b 20 4f 6b 28 22 53 6f ...0 => { Ok("So
2200: 75 72 63 65 20 6e 6f 74 20 66 6f 75 6e 64 2e 22 urce not found."
2210: 29 20 7d 2c 0a 09 09 09 5f 20 3d 3e 20 7b 20 45 ) },...._ => { E
2220: 72 72 28 61 6e 79 68 6f 77 21 28 22 44 61 74 61 rr(anyhow!("Data
2230: 62 61 73 65 20 65 72 72 6f 72 2e 22 29 29 20 7d base error.")) }
2240: 2c 0a 09 09 7d 0a 09 7d 0a 0a 09 70 75 62 20 61 ,...}..}...pub a
2250: 73 79 6e 63 20 66 6e 20 75 70 64 61 74 65 3c 53 sync fn update<S
2260: 3e 28 26 73 65 6c 66 2c 20 75 70 64 61 74 65 3a >(&self, update:
2270: 20 4f 70 74 69 6f 6e 3c 69 33 32 3e 2c 20 63 68 Option<i32>, ch
2280: 61 6e 6e 65 6c 3a 20 26 73 74 72 2c 20 63 68 61 annel: &str, cha
2290: 6e 6e 65 6c 5f 69 64 3a 20 69 36 34 2c 20 75 72 nnel_id: i64, ur
22a0: 6c 3a 20 26 73 74 72 2c 20 69 76 5f 68 61 73 68 l: &str, iv_hash
22b0: 3a 20 4f 70 74 69 6f 6e 3c 26 73 74 72 3e 2c 20 : Option<&str>,
22c0: 75 72 6c 5f 72 65 3a 20 4f 70 74 69 6f 6e 3c 26 url_re: Option<&
22d0: 73 74 72 3e 2c 20 6f 77 6e 65 72 3a 20 53 29 20 str>, owner: S)
22e0: 2d 3e 20 52 65 73 75 6c 74 3c 26 73 74 72 3e 0a -> Result<&str>.
22f0: 09 77 68 65 72 65 20 53 3a 20 49 6e 74 6f 3c 69 .where S: Into<i
2300: 36 34 3e 20 7b 0a 09 09 6c 65 74 20 6f 77 6e 65 64> {...let owne
2310: 72 20 3d 20 6f 77 6e 65 72 2e 69 6e 74 6f 28 29 r = owner.into()
2320: 3b 0a 0a 09 09 6c 65 74 20 6d 75 74 20 63 6f 6e ;....let mut con
2330: 6e 20 3d 20 73 65 6c 66 2e 70 6f 6f 6c 2e 61 63 n = self.pool.ac
2340: 71 75 69 72 65 28 29 2e 61 77 61 69 74 0a 09 09 quire().await...
2350: 09 2e 77 69 74 68 5f 63 6f 6e 74 65 78 74 28 7c ..with_context(|
2360: 7c 20 66 6f 72 6d 61 74 21 28 22 55 70 64 61 74 | format!("Updat
2370: 65 20 66 65 74 63 68 20 63 6f 6e 6e 3a 5c 6e 7b e fetch conn:\n{
2380: 3a 3f 7d 22 2c 20 26 73 65 6c 66 2e 70 6f 6f 6c :?}", &self.pool
2390: 29 29 3f 3b 0a 0a 09 09 6d 61 74 63 68 20 6d 61 ))?;....match ma
23a0: 74 63 68 20 75 70 64 61 74 65 20 7b 0a 09 09 09 tch update {....
23b0: 09 53 6f 6d 65 28 69 64 29 20 3d 3e 20 7b 0a 09 .Some(id) => {..
23c0: 09 09 09 09 73 71 6c 78 3a 3a 71 75 65 72 79 28 ....sqlx::query(
23d0: 22 75 70 64 61 74 65 20 72 73 73 74 67 5f 73 6f "update rsstg_so
23e0: 75 72 63 65 20 73 65 74 20 63 68 61 6e 6e 65 6c urce set channel
23f0: 5f 69 64 20 3d 20 24 32 2c 20 75 72 6c 20 3d 20 _id = $2, url =
2400: 24 33 2c 20 69 76 5f 68 61 73 68 20 3d 20 24 34 $3, iv_hash = $4
2410: 2c 20 6f 77 6e 65 72 20 3d 20 24 35 2c 20 63 68 , owner = $5, ch
2420: 61 6e 6e 65 6c 20 3d 20 24 36 2c 20 75 72 6c 5f annel = $6, url_
2430: 72 65 20 3d 20 24 37 20 77 68 65 72 65 20 73 6f re = $7 where so
2440: 75 72 63 65 5f 69 64 20 3d 20 24 31 22 29 2e 62 urce_id = $1").b
2450: 69 6e 64 28 69 64 29 0a 09 09 09 09 7d 2c 0a 09 ind(id).....},..
2460: 09 09 09 4e 6f 6e 65 20 3d 3e 20 7b 0a 09 09 09 ...None => {....
2470: 09 09 73 71 6c 78 3a 3a 71 75 65 72 79 28 22 69 ..sqlx::query("i
2480: 6e 73 65 72 74 20 69 6e 74 6f 20 72 73 73 74 67 nsert into rsstg
2490: 5f 73 6f 75 72 63 65 20 28 63 68 61 6e 6e 65 6c _source (channel
24a0: 5f 69 64 2c 20 75 72 6c 2c 20 69 76 5f 68 61 73 _id, url, iv_has
24b0: 68 2c 20 6f 77 6e 65 72 2c 20 63 68 61 6e 6e 65 h, owner, channe
24c0: 6c 2c 20 75 72 6c 5f 72 65 29 20 76 61 6c 75 65 l, url_re) value
24d0: 73 20 28 24 31 2c 20 24 32 2c 20 24 33 2c 20 24 s ($1, $2, $3, $
24e0: 34 2c 20 24 35 2c 20 24 36 29 22 29 0a 09 09 09 4, $5, $6)")....
24f0: 09 7d 2c 0a 09 09 09 7d 0a 09 09 09 2e 62 69 6e .},....}.....bin
2500: 64 28 63 68 61 6e 6e 65 6c 5f 69 64 29 0a 09 09 d(channel_id)...
2510: 09 2e 62 69 6e 64 28 75 72 6c 29 0a 09 09 09 2e ..bind(url).....
2520: 62 69 6e 64 28 69 76 5f 68 61 73 68 29 0a 09 09 bind(iv_hash)...
2530: 09 2e 62 69 6e 64 28 6f 77 6e 65 72 29 0a 09 09 ..bind(owner)...
2540: 09 2e 62 69 6e 64 28 63 68 61 6e 6e 65 6c 29 0a ..bind(channel).
2550: 09 09 09 2e 62 69 6e 64 28 75 72 6c 5f 72 65 29 ....bind(url_re)
2560: 0a 09 09 09 2e 65 78 65 63 75 74 65 28 26 6d 75 .....execute(&mu
2570: 74 20 63 6f 6e 6e 29 2e 61 77 61 69 74 20 7b 0a t conn).await {.
2580: 09 09 09 4f 6b 28 5f 29 20 3d 3e 20 4f 6b 28 6d ...Ok(_) => Ok(m
2590: 61 74 63 68 20 75 70 64 61 74 65 20 7b 0a 09 09 atch update {...
25a0: 09 09 53 6f 6d 65 28 5f 29 20 3d 3e 20 22 43 68 ..Some(_) => "Ch
25b0: 61 6e 6e 65 6c 20 75 70 64 61 74 65 64 2e 22 2c annel updated.",
25c0: 0a 09 09 09 09 4e 6f 6e 65 20 3d 3e 20 22 43 68 .....None => "Ch
25d0: 61 6e 6e 65 6c 20 61 64 64 65 64 2e 22 2c 0a 09 annel added.",..
25e0: 09 09 7d 29 2c 0a 09 09 09 45 72 72 28 73 71 6c ..}),....Err(sql
25f0: 78 3a 3a 45 72 72 6f 72 3a 3a 44 61 74 61 62 61 x::Error::Databa
2600: 73 65 28 65 72 72 29 29 20 3d 3e 20 7b 0a 09 09 se(err)) => {...
2610: 09 09 6d 61 74 63 68 20 65 72 72 2e 64 6f 77 6e ..match err.down
2620: 63 61 73 74 3a 3a 3c 73 71 6c 78 3a 3a 70 6f 73 cast::<sqlx::pos
2630: 74 67 72 65 73 3a 3a 50 67 44 61 74 61 62 61 73 tgres::PgDatabas
2640: 65 45 72 72 6f 72 3e 28 29 2e 72 6f 75 74 69 6e eError>().routin
2650: 65 28 29 20 7b 0a 09 09 09 09 09 53 6f 6d 65 28 e() {......Some(
2660: 22 5f 62 74 5f 63 68 65 63 6b 5f 75 6e 69 71 75 "_bt_check_uniqu
2670: 65 22 2c 20 29 20 3d 3e 20 7b 0a 09 09 09 09 09 e", ) => {......
2680: 09 4f 6b 28 22 44 75 70 6c 69 63 61 74 65 20 6b .Ok("Duplicate k
2690: 65 79 2e 22 29 0a 09 09 09 09 09 7d 2c 0a 09 09 ey.")......},...
26a0: 09 09 09 53 6f 6d 65 28 5f 29 20 3d 3e 20 7b 0a ...Some(_) => {.
26b0: 09 09 09 09 09 09 4f 6b 28 22 44 61 74 61 62 61 ......Ok("Databa
26c0: 73 65 20 65 72 72 6f 72 2e 22 29 0a 09 09 09 09 se error.").....
26d0: 09 7d 2c 0a 09 09 09 09 09 4e 6f 6e 65 20 3d 3e .},......None =>
26e0: 20 7b 0a 09 09 09 09 09 09 4f 6b 28 22 4e 6f 20 {.......Ok("No
26f0: 64 61 74 61 62 61 73 65 20 65 72 72 6f 72 20 65 database error e
2700: 78 74 72 61 63 74 65 64 2e 22 29 0a 09 09 09 09 xtracted.").....
2710: 09 7d 2c 0a 09 09 09 09 7d 0a 09 09 09 7d 2c 0a .},.....}....},.
2720: 09 09 09 45 72 72 28 65 72 72 29 20 3d 3e 20 7b ...Err(err) => {
2730: 0a 09 09 09 09 62 61 69 6c 21 28 22 53 6f 72 72 .....bail!("Sorr
2740: 79 2c 20 75 6e 6b 6e 6f 77 6e 20 65 72 72 6f 72 y, unknown error
2750: 3a 5c 6e 7b 3a 23 3f 7d 5c 6e 22 2c 20 65 72 72 :\n{:#?}\n", err
2760: 29 3b 0a 09 09 09 7d 2c 0a 09 09 7d 0a 09 7d 0a );....},...}..}.
2770: 0a 09 61 73 79 6e 63 20 66 6e 20 61 75 74 6f 66 ..async fn autof
2780: 65 74 63 68 28 26 73 65 6c 66 29 20 2d 3e 20 52 etch(&self) -> R
2790: 65 73 75 6c 74 3c 73 74 64 3a 3a 74 69 6d 65 3a esult<std::time:
27a0: 3a 44 75 72 61 74 69 6f 6e 3e 20 7b 0a 09 09 6c :Duration> {...l
27b0: 65 74 20 6d 75 74 20 64 65 6c 61 79 20 3d 20 63 et mut delay = c
27c0: 68 72 6f 6e 6f 3a 3a 44 75 72 61 74 69 6f 6e 3a hrono::Duration:
27d0: 3a 6d 69 6e 75 74 65 73 28 31 29 3b 0a 09 09 6c :minutes(1);...l
27e0: 65 74 20 6d 75 74 20 63 6f 6e 6e 20 3d 20 73 65 et mut conn = se
27f0: 6c 66 2e 70 6f 6f 6c 2e 61 63 71 75 69 72 65 28 lf.pool.acquire(
2800: 29 2e 61 77 61 69 74 0a 09 09 09 2e 77 69 74 68 ).await.....with
2810: 5f 63 6f 6e 74 65 78 74 28 7c 7c 20 66 6f 72 6d _context(|| form
2820: 61 74 21 28 22 41 75 74 6f 66 65 74 63 68 20 66 at!("Autofetch f
2830: 65 74 63 68 20 63 6f 6e 6e 3a 5c 6e 7b 3a 3f 7d etch conn:\n{:?}
2840: 22 2c 20 26 73 65 6c 66 2e 70 6f 6f 6c 29 29 3f ", &self.pool))?
2850: 3b 0a 09 09 6c 65 74 20 6e 6f 77 20 3d 20 63 68 ;...let now = ch
2860: 72 6f 6e 6f 3a 3a 4c 6f 63 61 6c 3a 3a 6e 6f 77 rono::Local::now
2870: 28 29 3b 0a 09 09 6c 65 74 20 6d 75 74 20 71 75 ();...let mut qu
2880: 65 75 65 20 3d 20 73 71 6c 78 3a 3a 71 75 65 72 eue = sqlx::quer
2890: 79 28 22 73 65 6c 65 63 74 20 73 6f 75 72 63 65 y("select source
28a0: 5f 69 64 2c 20 6e 65 78 74 5f 66 65 74 63 68 2c _id, next_fetch,
28b0: 20 6f 77 6e 65 72 20 66 72 6f 6d 20 72 73 73 74 owner from rsst
28c0: 67 5f 6f 72 64 65 72 20 6e 61 74 75 72 61 6c 20 g_order natural
28d0: 6c 65 66 74 20 6a 6f 69 6e 20 72 73 73 74 67 5f left join rsstg_
28e0: 73 6f 75 72 63 65 20 77 68 65 72 65 20 6e 65 78 source where nex
28f0: 74 5f 66 65 74 63 68 20 3c 20 6e 6f 77 28 29 20 t_fetch < now()
2900: 2b 20 69 6e 74 65 72 76 61 6c 20 27 31 20 6d 69 + interval '1 mi
2910: 6e 75 74 65 27 3b 22 29 0a 09 09 09 2e 66 65 74 nute';").....fet
2920: 63 68 5f 61 6c 6c 28 26 6d 75 74 20 63 6f 6e 6e ch_all(&mut conn
2930: 29 2e 61 77 61 69 74 3f 3b 0a 09 09 66 6f 72 20 ).await?;...for
2940: 72 6f 77 20 69 6e 20 71 75 65 75 65 2e 69 74 65 row in queue.ite
2950: 72 28 29 20 7b 0a 09 09 09 6c 65 74 20 73 6f 75 r() {....let sou
2960: 72 63 65 5f 69 64 3a 20 69 33 32 20 3d 20 72 6f rce_id: i32 = ro
2970: 77 2e 74 72 79 5f 67 65 74 28 22 73 6f 75 72 63 w.try_get("sourc
2980: 65 5f 69 64 22 29 3f 3b 0a 09 09 09 6c 65 74 20 e_id")?;....let
2990: 6f 77 6e 65 72 3a 20 69 36 34 20 3d 20 72 6f 77 owner: i64 = row
29a0: 2e 74 72 79 5f 67 65 74 28 22 6f 77 6e 65 72 22 .try_get("owner"
29b0: 29 3f 3b 0a 09 09 09 6c 65 74 20 6e 65 78 74 5f )?;....let next_
29c0: 66 65 74 63 68 3a 20 44 61 74 65 54 69 6d 65 3c fetch: DateTime<
29d0: 63 68 72 6f 6e 6f 3a 3a 4c 6f 63 61 6c 3e 20 3d chrono::Local> =
29e0: 20 72 6f 77 2e 74 72 79 5f 67 65 74 28 22 6e 65 row.try_get("ne
29f0: 78 74 5f 66 65 74 63 68 22 29 3f 3b 0a 09 09 09 xt_fetch")?;....
2a00: 69 66 20 6e 65 78 74 5f 66 65 74 63 68 20 3c 20 if next_fetch <
2a10: 6e 6f 77 20 7b 0a 09 09 09 09 6c 65 74 20 63 6c now {.....let cl
2a20: 6f 6e 65 20 3d 20 43 6f 72 65 20 7b 0a 09 09 09 one = Core {....
2a30: 09 09 6f 77 6e 65 72 5f 63 68 61 74 3a 20 74 65 ..owner_chat: te
2a40: 6c 65 67 72 61 6d 5f 62 6f 74 3a 3a 55 73 65 72 legram_bot::User
2a50: 49 64 3a 3a 6e 65 77 28 6f 77 6e 65 72 29 2c 0a Id::new(owner),.
2a60: 09 09 09 09 09 2e 2e 73 65 6c 66 2e 63 6c 6f 6e .......self.clon
2a70: 65 28 29 0a 09 09 09 09 7d 3b 0a 09 09 09 09 74 e().....};.....t
2a80: 6f 6b 69 6f 3a 3a 73 70 61 77 6e 28 61 73 79 6e okio::spawn(asyn
2a90: 63 20 6d 6f 76 65 20 7b 0a 09 09 09 09 09 69 66 c move {......if
2aa0: 20 6c 65 74 20 45 72 72 28 65 72 72 29 20 3d 20 let Err(err) =
2ab0: 63 6c 6f 6e 65 2e 63 68 65 63 6b 28 26 73 6f 75 clone.check(&sou
2ac0: 72 63 65 5f 69 64 2c 20 6f 77 6e 65 72 2c 20 74 rce_id, owner, t
2ad0: 72 75 65 29 2e 61 77 61 69 74 20 7b 0a 09 09 09 rue).await {....
2ae0: 09 09 09 69 66 20 6c 65 74 20 45 72 72 28 65 72 ...if let Err(er
2af0: 72 29 20 3d 20 63 6c 6f 6e 65 2e 73 65 6e 64 28 r) = clone.send(
2b00: 26 66 6f 72 6d 61 74 21 28 22 f0 9f 9b 91 20 7b &format!("š {
2b10: 3a 3f 7d 22 2c 20 65 72 72 29 2c 20 4e 6f 6e 65 :?}", err), None
2b20: 2c 20 4e 6f 6e 65 29 2e 61 77 61 69 74 20 7b 0a , None).await {.
2b30: 09 09 09 09 09 09 09 65 70 72 69 6e 74 6c 6e 21 .......eprintln!
2b40: 28 22 43 68 65 63 6b 20 65 72 72 6f 72 3a 20 7b ("Check error: {
2b50: 7d 22 2c 20 65 72 72 29 3b 0a 09 09 09 09 09 09 }", err);.......
2b60: 7d 3b 0a 09 09 09 09 09 7d 3b 0a 09 09 09 09 7d };......};.....}
2b70: 29 3b 0a 09 09 09 7d 20 65 6c 73 65 20 69 66 20 );....} else if
2b80: 6e 65 78 74 5f 66 65 74 63 68 20 2d 20 6e 6f 77 next_fetch - now
2b90: 20 3c 20 64 65 6c 61 79 20 7b 0a 09 09 09 09 64 < delay {.....d
2ba0: 65 6c 61 79 20 3d 20 6e 65 78 74 5f 66 65 74 63 elay = next_fetc
2bb0: 68 20 2d 20 6e 6f 77 3b 0a 09 09 09 7d 0a 09 09 h - now;....}...
2bc0: 7d 3b 0a 09 09 71 75 65 75 65 2e 63 6c 65 61 72 };...queue.clear
2bd0: 28 29 3b 0a 09 09 4f 6b 28 64 65 6c 61 79 2e 74 ();...Ok(delay.t
2be0: 6f 5f 73 74 64 28 29 3f 29 0a 09 7d 0a 0a 09 70 o_std()?)..}...p
2bf0: 75 62 20 61 73 79 6e 63 20 66 6e 20 6c 69 73 74 ub async fn list
2c00: 3c 53 3e 28 26 73 65 6c 66 2c 20 6f 77 6e 65 72 <S>(&self, owner
2c10: 3a 20 53 29 20 2d 3e 20 52 65 73 75 6c 74 3c 53 : S) -> Result<S
2c20: 74 72 69 6e 67 3e 0a 09 77 68 65 72 65 20 53 3a tring>..where S:
2c30: 20 49 6e 74 6f 3c 69 36 34 3e 20 7b 0a 09 09 6c Into<i64> {...l
2c40: 65 74 20 6f 77 6e 65 72 20 3d 20 6f 77 6e 65 72 et owner = owner
2c50: 2e 69 6e 74 6f 28 29 3b 0a 0a 09 09 6c 65 74 20 .into();....let
2c60: 6d 75 74 20 72 65 70 6c 79 3a 20 56 65 63 3c 43 mut reply: Vec<C
2c70: 6f 77 3c 73 74 72 3e 3e 20 3d 20 76 65 63 21 5b ow<str>> = vec![
2c80: 5d 3b 0a 09 09 6c 65 74 20 6d 75 74 20 63 6f 6e ];...let mut con
2c90: 6e 20 3d 20 73 65 6c 66 2e 70 6f 6f 6c 2e 61 63 n = self.pool.ac
2ca0: 71 75 69 72 65 28 29 2e 61 77 61 69 74 0a 09 09 quire().await...
2cb0: 09 2e 77 69 74 68 5f 63 6f 6e 74 65 78 74 28 7c ..with_context(|
2cc0: 7c 20 66 6f 72 6d 61 74 21 28 22 4c 69 73 74 20 | format!("List
2cd0: 66 65 74 63 68 20 63 6f 6e 6e 3a 5c 6e 7b 3a 3f fetch conn:\n{:?
2ce0: 7d 22 2c 20 26 73 65 6c 66 2e 70 6f 6f 6c 29 29 }", &self.pool))
2cf0: 3f 3b 0a 09 09 72 65 70 6c 79 2e 70 75 73 68 28 ?;...reply.push(
2d00: 22 43 68 61 6e 6e 65 6c 73 3a 22 2e 69 6e 74 6f "Channels:".into
2d10: 28 29 29 3b 0a 09 09 6c 65 74 20 72 6f 77 73 20 ());...let rows
2d20: 3d 20 73 71 6c 78 3a 3a 71 75 65 72 79 28 22 73 = sqlx::query("s
2d30: 65 6c 65 63 74 20 73 6f 75 72 63 65 5f 69 64 2c elect source_id,
2d40: 20 63 68 61 6e 6e 65 6c 2c 20 65 6e 61 62 6c 65 channel, enable
2d50: 64 2c 20 75 72 6c 2c 20 69 76 5f 68 61 73 68 2c d, url, iv_hash,
2d60: 20 75 72 6c 5f 72 65 20 66 72 6f 6d 20 72 73 73 url_re from rss
2d70: 74 67 5f 73 6f 75 72 63 65 20 77 68 65 72 65 20 tg_source where
2d80: 6f 77 6e 65 72 20 3d 20 24 31 20 6f 72 64 65 72 owner = $1 order
2d90: 20 62 79 20 73 6f 75 72 63 65 5f 69 64 22 29 0a by source_id").
2da0: 09 09 09 2e 62 69 6e 64 28 6f 77 6e 65 72 29 0a ....bind(owner).
2db0: 09 09 09 2e 66 65 74 63 68 5f 61 6c 6c 28 26 6d ....fetch_all(&m
2dc0: 75 74 20 63 6f 6e 6e 29 2e 61 77 61 69 74 3f 3b ut conn).await?;
2dd0: 0a 09 09 66 6f 72 20 72 6f 77 20 69 6e 20 72 6f ...for row in ro
2de0: 77 73 2e 69 74 65 72 28 29 20 7b 0a 09 09 09 6c ws.iter() {....l
2df0: 65 74 20 73 6f 75 72 63 65 5f 69 64 3a 20 69 33 et source_id: i3
2e00: 32 20 3d 20 72 6f 77 2e 74 72 79 5f 67 65 74 28 2 = row.try_get(
2e10: 22 73 6f 75 72 63 65 5f 69 64 22 29 3f 3b 0a 09 "source_id")?;..
2e20: 09 09 6c 65 74 20 75 73 65 72 6e 61 6d 65 3a 20 ..let username:
2e30: 26 73 74 72 20 3d 20 72 6f 77 2e 74 72 79 5f 67 &str = row.try_g
2e40: 65 74 28 22 63 68 61 6e 6e 65 6c 22 29 3f 3b 0a et("channel")?;.
2e50: 09 09 09 6c 65 74 20 65 6e 61 62 6c 65 64 3a 20 ...let enabled:
2e60: 62 6f 6f 6c 20 3d 20 72 6f 77 2e 74 72 79 5f 67 bool = row.try_g
2e70: 65 74 28 22 65 6e 61 62 6c 65 64 22 29 3f 3b 0a et("enabled")?;.
2e80: 09 09 09 6c 65 74 20 75 72 6c 3a 20 26 73 74 72 ...let url: &str
2e90: 20 3d 20 72 6f 77 2e 74 72 79 5f 67 65 74 28 22 = row.try_get("
2ea0: 75 72 6c 22 29 3f 3b 0a 09 09 09 6c 65 74 20 69 url")?;....let i
2eb0: 76 5f 68 61 73 68 3a 20 4f 70 74 69 6f 6e 3c 26 v_hash: Option<&
2ec0: 73 74 72 3e 20 3d 20 72 6f 77 2e 74 72 79 5f 67 str> = row.try_g
2ed0: 65 74 28 22 69 76 5f 68 61 73 68 22 29 3f 3b 0a et("iv_hash")?;.
2ee0: 09 09 09 6c 65 74 20 75 72 6c 5f 72 65 3a 20 4f ...let url_re: O
2ef0: 70 74 69 6f 6e 3c 26 73 74 72 3e 20 3d 20 72 6f ption<&str> = ro
2f00: 77 2e 74 72 79 5f 67 65 74 28 22 75 72 6c 5f 72 w.try_get("url_r
2f10: 65 22 29 3f 3b 0a 09 09 09 72 65 70 6c 79 2e 70 e")?;....reply.p
2f20: 75 73 68 28 66 6f 72 6d 61 74 21 28 22 5c 6e 5c ush(format!("\n\
2f30: 5c 23 ef b8 8f e2 83 a3 20 7b 7d 20 5c 5c 2a ef \#ļøā£ {} \\*ļ
2f40: b8 8f e2 83 a3 20 60 7b 7d 60 20 7b 7d 5c 6e f0 øā£ `{}` {}\nš
2f50: 9f 94 97 20 60 7b 7d 60 22 2c 20 73 6f 75 72 63 `{}`", sourc
2f60: 65 5f 69 64 2c 20 75 73 65 72 6e 61 6d 65 2c 20 e_id, username,
2f70: 20 0a 09 09 09 09 6d 61 74 63 68 20 65 6e 61 62 .....match enab
2f80: 6c 65 64 20 7b 0a 09 09 09 09 09 74 72 75 65 20 led {......true
2f90: 20 3d 3e 20 22 f0 9f 94 84 20 65 6e 61 62 6c 65 => "š enable
2fa0: 64 22 2c 0a 09 09 09 09 09 66 61 6c 73 65 20 3d d",......false =
2fb0: 3e 20 22 e2 9b 94 20 64 69 73 61 62 6c 65 64 22 > "ā disabled"
2fc0: 2c 0a 09 09 09 09 7d 2c 20 75 72 6c 29 2e 69 6e ,.....}, url).in
2fd0: 74 6f 28 29 29 3b 0a 09 09 09 69 66 20 6c 65 74 to());....if let
2fe0: 20 53 6f 6d 65 28 68 61 73 68 29 20 3d 20 69 76 Some(hash) = iv
2ff0: 5f 68 61 73 68 20 7b 0a 09 09 09 09 72 65 70 6c _hash {.....repl
3000: 79 2e 70 75 73 68 28 66 6f 72 6d 61 74 21 28 22 y.push(format!("
3010: 49 56 3a 20 60 7b 7d 60 22 2c 20 68 61 73 68 29 IV: `{}`", hash)
3020: 2e 69 6e 74 6f 28 29 29 3b 0a 09 09 09 7d 0a 09 .into());....}..
3030: 09 09 69 66 20 6c 65 74 20 53 6f 6d 65 28 72 65 ..if let Some(re
3040: 29 20 3d 20 75 72 6c 5f 72 65 20 7b 0a 09 09 09 ) = url_re {....
3050: 09 72 65 70 6c 79 2e 70 75 73 68 28 66 6f 72 6d .reply.push(form
3060: 61 74 21 28 22 52 45 3a 20 60 7b 7d 60 22 2c 20 at!("RE: `{}`",
3070: 72 65 29 2e 69 6e 74 6f 28 29 29 3b 0a 09 09 09 re).into());....
3080: 7d 0a 09 09 7d 3b 0a 09 09 4f 6b 28 72 65 70 6c }...};...Ok(repl
3090: 79 2e 6a 6f 69 6e 28 22 5c 6e 22 29 29 0a 09 7d y.join("\n"))..}
30a0: 0a 7d 0a .}.