0000: 75 73 65 20 73 74 64 3a 3a 63 6f 6c 6c 65 63 74 use std::collect
0010: 69 6f 6e 73 3a 3a 42 54 72 65 65 4d 61 70 3b 0a ions::BTreeMap;.
0020: 0a 75 73 65 20 63 6f 6e 66 69 67 3b 0a 0a 75 73 .use config;..us
0030: 65 20 74 6f 6b 69 6f 3b 0a 75 73 65 20 72 73 73 e tokio;.use rss
0040: 3b 0a 75 73 65 20 63 68 72 6f 6e 6f 3a 3a 44 61 ;.use chrono::Da
0050: 74 65 54 69 6d 65 3b 0a 0a 75 73 65 20 72 65 67 teTime;..use reg
0060: 65 78 3a 3a 52 65 67 65 78 3b 0a 0a 75 73 65 20 ex::Regex;..use
0070: 74 6f 6b 69 6f 3a 3a 73 74 72 65 61 6d 3a 3a 53 tokio::stream::S
0080: 74 72 65 61 6d 45 78 74 3b 0a 75 73 65 20 74 65 treamExt;.use te
0090: 6c 65 67 72 61 6d 5f 62 6f 74 3a 3a 2a 3b 0a 0a legram_bot::*;..
00a0: 75 73 65 20 73 71 6c 78 3a 3a 70 6f 73 74 67 72 use sqlx::postgr
00b0: 65 73 3a 3a 50 67 50 6f 6f 6c 4f 70 74 69 6f 6e es::PgPoolOption
00c0: 73 3b 0a 75 73 65 20 73 71 6c 78 3a 3a 52 6f 77 s;.use sqlx::Row
00d0: 3b 0a 0a 74 79 70 65 20 52 65 73 75 6c 74 3c 54 ;..type Result<T
00e0: 3e 20 3d 20 73 74 64 3a 3a 72 65 73 75 6c 74 3a > = std::result:
00f0: 3a 52 65 73 75 6c 74 3c 54 2c 20 42 6f 78 3c 64 :Result<T, Box<d
0100: 79 6e 20 73 74 64 3a 3a 65 72 72 6f 72 3a 3a 45 yn std::error::E
0110: 72 72 6f 72 3e 3e 3b 0a 0a 23 5b 64 65 72 69 76 rror>>;..#[deriv
0120: 65 28 43 6c 6f 6e 65 29 5d 0a 73 74 72 75 63 74 e(Clone)].struct
0130: 20 43 6f 72 65 20 7b 0a 09 6f 77 6e 65 72 3a 20 Core {..owner:
0140: 69 36 34 2c 0a 09 61 70 69 5f 6b 65 79 3a 20 53 i64,..api_key: S
0150: 74 72 69 6e 67 2c 0a 09 6f 77 6e 65 72 5f 63 68 tring,..owner_ch
0160: 61 74 3a 20 55 73 65 72 49 64 2c 0a 09 74 67 3a at: UserId,..tg:
0170: 20 74 65 6c 65 67 72 61 6d 5f 62 6f 74 3a 3a 41 telegram_bot::A
0180: 70 69 2c 0a 09 6d 79 3a 20 55 73 65 72 2c 0a 09 pi,..my: User,..
0190: 70 6f 6f 6c 3a 20 73 71 6c 78 3a 3a 50 6f 6f 6c pool: sqlx::Pool
01a0: 3c 73 71 6c 78 3a 3a 50 6f 73 74 67 72 65 73 3e <sqlx::Postgres>
01b0: 2c 0a 7d 0a 0a 69 6d 70 6c 20 43 6f 72 65 20 7b ,.}..impl Core {
01c0: 0a 09 61 73 79 6e 63 20 66 6e 20 6e 65 77 28 73 ..async fn new(s
01d0: 65 74 74 69 6e 67 73 3a 20 63 6f 6e 66 69 67 3a ettings: config:
01e0: 3a 43 6f 6e 66 69 67 29 20 2d 3e 20 52 65 73 75 :Config) -> Resu
01f0: 6c 74 3c 43 6f 72 65 3e 20 7b 0a 09 09 6c 65 74 lt<Core> {...let
0200: 20 6f 77 6e 65 72 20 3d 20 73 65 74 74 69 6e 67 owner = setting
0210: 73 2e 67 65 74 5f 69 6e 74 28 22 6f 77 6e 65 72 s.get_int("owner
0220: 22 29 3f 3b 0a 09 09 6c 65 74 20 61 70 69 5f 6b ")?;...let api_k
0230: 65 79 20 3d 20 73 65 74 74 69 6e 67 73 2e 67 65 ey = settings.ge
0240: 74 5f 73 74 72 28 22 61 70 69 5f 6b 65 79 22 29 t_str("api_key")
0250: 3f 3b 0a 09 09 6c 65 74 20 74 67 20 3d 20 41 70 ?;...let tg = Ap
0260: 69 3a 3a 6e 65 77 28 26 61 70 69 5f 6b 65 79 29 i::new(&api_key)
0270: 3b 0a 09 09 6c 65 74 20 63 6f 72 65 20 3d 20 43 ;...let core = C
0280: 6f 72 65 20 7b 0a 09 09 09 6f 77 6e 65 72 3a 20 ore {....owner:
0290: 6f 77 6e 65 72 2c 0a 09 09 09 61 70 69 5f 6b 65 owner,....api_ke
02a0: 79 3a 20 61 70 69 5f 6b 65 79 2e 63 6c 6f 6e 65 y: api_key.clone
02b0: 28 29 2c 0a 09 09 09 6d 79 3a 20 74 67 2e 73 65 (),....my: tg.se
02c0: 6e 64 28 74 65 6c 65 67 72 61 6d 5f 62 6f 74 3a nd(telegram_bot:
02d0: 3a 47 65 74 4d 65 29 2e 61 77 61 69 74 3f 2c 0a :GetMe).await?,.
02e0: 09 09 09 74 67 3a 20 74 67 2c 0a 09 09 09 6f 77 ...tg: tg,....ow
02f0: 6e 65 72 5f 63 68 61 74 3a 20 55 73 65 72 49 64 ner_chat: UserId
0300: 3a 3a 6e 65 77 28 6f 77 6e 65 72 29 2c 0a 09 09 ::new(owner),...
0310: 09 70 6f 6f 6c 3a 20 50 67 50 6f 6f 6c 4f 70 74 .pool: PgPoolOpt
0320: 69 6f 6e 73 3a 3a 6e 65 77 28 29 2e 6d 61 78 5f ions::new().max_
0330: 63 6f 6e 6e 65 63 74 69 6f 6e 73 28 35 29 2e 63 connections(5).c
0340: 6f 6e 6e 65 63 74 28 26 73 65 74 74 69 6e 67 73 onnect(&settings
0350: 2e 67 65 74 5f 73 74 72 28 22 70 67 22 29 3f 29 .get_str("pg")?)
0360: 2e 61 77 61 69 74 3f 2c 0a 09 09 7d 3b 0a 09 09 .await?,...};...
0370: 6c 65 74 20 63 6c 6f 6e 65 20 3d 20 63 6f 72 65 let clone = core
0380: 2e 63 6c 6f 6e 65 28 29 3b 0a 09 09 74 6f 6b 69 .clone();...toki
0390: 6f 3a 3a 73 70 61 77 6e 28 61 73 79 6e 63 20 6d o::spawn(async m
03a0: 6f 76 65 20 7b 0a 09 09 09 69 66 20 6c 65 74 20 ove {....if let
03b0: 45 72 72 28 65 72 72 29 20 3d 20 63 6c 6f 6e 65 Err(err) = clone
03c0: 2e 61 75 74 6f 66 65 74 63 68 28 29 2e 61 77 61 .autofetch().awa
03d0: 69 74 20 7b 0a 09 09 09 09 65 70 72 69 6e 74 6c it {.....eprintl
03e0: 6e 21 28 22 63 6f 6e 6e 65 63 74 69 6f 6e 20 65 n!("connection e
03f0: 72 72 6f 72 3a 20 7b 7d 22 2c 20 65 72 72 29 3b rror: {}", err);
0400: 0a 09 09 09 7d 0a 09 09 7d 29 3b 0a 09 09 4f 6b ....}...});...Ok
0410: 28 63 6f 72 65 29 0a 09 7d 0a 0a 09 66 6e 20 73 (core)..}...fn s
0420: 74 72 65 61 6d 28 26 73 65 6c 66 29 20 2d 3e 20 tream(&self) ->
0430: 74 65 6c 65 67 72 61 6d 5f 62 6f 74 3a 3a 55 70 telegram_bot::Up
0440: 64 61 74 65 73 53 74 72 65 61 6d 20 7b 0a 09 09 datesStream {...
0450: 73 65 6c 66 2e 74 67 2e 73 74 72 65 61 6d 28 29 self.tg.stream()
0460: 0a 09 7d 0a 0a 09 66 6e 20 64 65 62 75 67 28 26 ..}...fn debug(&
0470: 73 65 6c 66 2c 20 6d 73 67 3a 20 26 73 74 72 29 self, msg: &str)
0480: 20 2d 3e 20 52 65 73 75 6c 74 3c 28 29 3e 20 7b -> Result<()> {
0490: 0a 09 09 73 65 6c 66 2e 74 67 2e 73 70 61 77 6e ...self.tg.spawn
04a0: 28 53 65 6e 64 4d 65 73 73 61 67 65 3a 3a 6e 65 (SendMessage::ne
04b0: 77 28 73 65 6c 66 2e 6f 77 6e 65 72 5f 63 68 61 w(self.owner_cha
04c0: 74 2c 20 6d 73 67 29 29 3b 0a 09 09 4f 6b 28 28 t, msg));...Ok((
04d0: 29 29 0a 09 7d 0a 0a 09 61 73 79 6e 63 20 66 6e ))..}...async fn
04e0: 20 63 68 65 63 6b 28 26 73 65 6c 66 2c 20 69 64 check(&self, id
04f0: 3a 20 26 69 33 32 2c 20 72 65 61 6c 3a 20 4f 70 : &i32, real: Op
0500: 74 69 6f 6e 3c 62 6f 6f 6c 3e 29 20 2d 3e 20 52 tion<bool>) -> R
0510: 65 73 75 6c 74 3c 28 29 3e 20 7b 0a 09 09 6d 61 esult<()> {...ma
0520: 74 63 68 20 73 71 6c 78 3a 3a 71 75 65 72 79 28 tch sqlx::query(
0530: 22 73 65 6c 65 63 74 20 73 6f 75 72 63 65 5f 69 "select source_i
0540: 64 2c 20 63 68 61 6e 6e 65 6c 5f 69 64 2c 20 75 d, channel_id, u
0550: 72 6c 2c 20 69 76 5f 68 61 73 68 2c 20 6f 77 6e rl, iv_hash, own
0560: 65 72 20 66 72 6f 6d 20 72 73 73 74 67 5f 73 6f er from rsstg_so
0570: 75 72 63 65 20 77 68 65 72 65 20 73 6f 75 72 63 urce where sourc
0580: 65 5f 69 64 20 3d 20 24 31 22 29 0a 09 09 09 2e e_id = $1").....
0590: 62 69 6e 64 28 69 64 29 0a 09 09 09 2e 66 65 74 bind(id).....fet
05a0: 63 68 5f 6f 6e 65 28 26 73 65 6c 66 2e 70 6f 6f ch_one(&self.poo
05b0: 6c 29 2e 61 77 61 69 74 20 7b 0a 09 09 09 4f 6b l).await {....Ok
05c0: 28 72 6f 77 29 20 3d 3e 20 7b 0a 09 09 09 09 6c (row) => {.....l
05d0: 65 74 20 63 68 61 6e 6e 65 6c 5f 69 64 3a 20 69 et channel_id: i
05e0: 36 34 20 3d 20 72 6f 77 2e 74 72 79 5f 67 65 74 64 = row.try_get
05f0: 28 22 63 68 61 6e 6e 65 6c 5f 69 64 22 29 3f 3b ("channel_id")?;
0600: 0a 09 09 09 09 6c 65 74 20 64 65 73 74 69 6e 61 .....let destina
0610: 74 69 6f 6e 20 3d 20 6d 61 74 63 68 20 72 65 61 tion = match rea
0620: 6c 20 7b 0a 09 09 09 09 09 53 6f 6d 65 28 74 72 l {......Some(tr
0630: 75 65 29 20 3d 3e 20 55 73 65 72 49 64 3a 3a 6e ue) => UserId::n
0640: 65 77 28 63 68 61 6e 6e 65 6c 5f 69 64 29 2c 0a ew(channel_id),.
0650: 09 09 09 09 09 53 6f 6d 65 28 66 61 6c 73 65 29 .....Some(false)
0660: 20 7c 20 4e 6f 6e 65 20 3d 3e 20 55 73 65 72 49 | None => UserI
0670: 64 3a 3a 6e 65 77 28 72 6f 77 2e 74 72 79 5f 67 d::new(row.try_g
0680: 65 74 28 22 6f 77 6e 65 72 22 29 3f 29 2c 0a 09 et("owner")?),..
0690: 09 09 09 7d 3b 0a 09 09 09 09 6c 65 74 20 75 72 ...};.....let ur
06a0: 6c 3a 20 26 73 74 72 20 3d 20 72 6f 77 2e 74 72 l: &str = row.tr
06b0: 79 5f 67 65 74 28 22 75 72 6c 22 29 3f 3b 0a 09 y_get("url")?;..
06c0: 09 09 09 6c 65 74 20 6d 75 74 20 74 68 69 73 5f ...let mut this_
06d0: 66 65 74 63 68 3a 20 4f 70 74 69 6f 6e 3c 44 61 fetch: Option<Da
06e0: 74 65 54 69 6d 65 3c 63 68 72 6f 6e 6f 3a 3a 46 teTime<chrono::F
06f0: 69 78 65 64 4f 66 66 73 65 74 3e 3e 20 3d 20 4e ixedOffset>> = N
0700: 6f 6e 65 3b 0a 09 09 09 09 6c 65 74 20 69 76 5f one;.....let iv_
0710: 68 61 73 68 3a 20 4f 70 74 69 6f 6e 3c 26 73 74 hash: Option<&st
0720: 72 3e 20 3d 20 72 6f 77 2e 74 72 79 5f 67 65 74 r> = row.try_get
0730: 28 22 69 76 5f 68 61 73 68 22 29 3f 3b 0a 09 09 ("iv_hash")?;...
0740: 09 09 6c 65 74 20 6d 75 74 20 70 6f 73 74 73 3a ..let mut posts:
0750: 20 42 54 72 65 65 4d 61 70 3c 44 61 74 65 54 69 BTreeMap<DateTi
0760: 6d 65 3c 63 68 72 6f 6e 6f 3a 3a 46 69 78 65 64 me<chrono::Fixed
0770: 4f 66 66 73 65 74 3e 2c 20 53 74 72 69 6e 67 3e Offset>, String>
0780: 20 3d 20 42 54 72 65 65 4d 61 70 3a 3a 6e 65 77 = BTreeMap::new
0790: 28 29 3b 0a 09 09 09 09 6d 61 74 63 68 20 72 73 ();.....match rs
07a0: 73 3a 3a 43 68 61 6e 6e 65 6c 3a 3a 66 72 6f 6d s::Channel::from
07b0: 5f 75 72 6c 28 75 72 6c 29 20 7b 0a 09 09 09 09 _url(url) {.....
07c0: 09 4f 6b 28 66 65 65 64 29 20 3d 3e 20 7b 0a 09 .Ok(feed) => {..
07d0: 09 09 09 09 09 73 65 6c 66 2e 64 65 62 75 67 28 .....self.debug(
07e0: 26 66 6f 72 6d 61 74 21 28 22 23 20 74 69 74 6c &format!("# titl
07f0: 65 3a 7b 3a 3f 7d 20 74 74 6c 3a 7b 3a 3f 7d 20 e:{:?} ttl:{:?}
0800: 68 6f 75 72 73 3a 7b 3a 3f 7d 20 64 61 79 73 3a hours:{:?} days:
0810: 7b 3a 3f 7d 22 2c 20 66 65 65 64 2e 74 69 74 6c {:?}", feed.titl
0820: 65 28 29 2c 20 66 65 65 64 2e 74 74 6c 28 29 2c e(), feed.ttl(),
0830: 20 66 65 65 64 2e 73 6b 69 70 5f 68 6f 75 72 73 feed.skip_hours
0840: 28 29 2c 20 66 65 65 64 2e 73 6b 69 70 5f 64 61 (), feed.skip_da
0850: 79 73 28 29 29 29 3f 3b 0a 09 09 09 09 09 09 66 ys()))?;.......f
0860: 6f 72 20 69 74 65 6d 20 69 6e 20 66 65 65 64 2e or item in feed.
0870: 69 74 65 6d 73 28 29 20 7b 0a 09 09 09 09 09 09 items() {.......
0880: 09 6c 65 74 20 64 61 74 65 20 3d 20 6d 61 74 63 .let date = matc
0890: 68 20 69 74 65 6d 2e 70 75 62 5f 64 61 74 65 28 h item.pub_date(
08a0: 29 20 7b 0a 09 09 09 09 09 09 09 09 53 6f 6d 65 ) {.........Some
08b0: 28 66 65 65 64 5f 64 61 74 65 29 20 3d 3e 20 44 (feed_date) => D
08c0: 61 74 65 54 69 6d 65 3a 3a 70 61 72 73 65 5f 66 ateTime::parse_f
08d0: 72 6f 6d 5f 72 66 63 32 38 32 32 28 66 65 65 64 rom_rfc2822(feed
08e0: 5f 64 61 74 65 29 2c 0a 09 09 09 09 09 09 09 09 _date),.........
08f0: 4e 6f 6e 65 20 3d 3e 20 44 61 74 65 54 69 6d 65 None => DateTime
0900: 3a 3a 70 61 72 73 65 5f 66 72 6f 6d 5f 72 66 63 ::parse_from_rfc
0910: 33 33 33 39 28 26 69 74 65 6d 2e 64 75 62 6c 69 3339(&item.dubli
0920: 6e 5f 63 6f 72 65 5f 65 78 74 28 29 2e 75 6e 77 n_core_ext().unw
0930: 72 61 70 28 29 2e 64 61 74 65 73 28 29 5b 30 5d rap().dates()[0]
0940: 29 2c 0a 09 09 09 09 09 09 09 7d 3f 3b 0a 09 09 ),........}?;...
0950: 09 09 09 09 09 6c 65 74 20 75 72 6c 20 3d 20 69 .....let url = i
0960: 74 65 6d 2e 6c 69 6e 6b 28 29 2e 75 6e 77 72 61 tem.link().unwra
0970: 70 28 29 2e 74 6f 5f 73 74 72 69 6e 67 28 29 3b p().to_string();
0980: 0a 09 09 09 09 09 09 09 70 6f 73 74 73 2e 69 6e ........posts.in
0990: 73 65 72 74 28 64 61 74 65 2e 63 6c 6f 6e 65 28 sert(date.clone(
09a0: 29 2c 20 75 72 6c 2e 63 6c 6f 6e 65 28 29 29 3b ), url.clone());
09b0: 0a 09 09 09 09 09 09 7d 3b 0a 09 09 09 09 09 09 .......};.......
09c0: 66 6f 72 20 28 64 61 74 65 2c 20 75 72 6c 29 20 for (date, url)
09d0: 69 6e 20 70 6f 73 74 73 2e 69 74 65 72 28 29 20 in posts.iter()
09e0: 7b 0a 09 09 09 09 09 09 09 6d 61 74 63 68 20 73 {........match s
09f0: 71 6c 78 3a 3a 71 75 65 72 79 28 22 73 65 6c 65 qlx::query("sele
0a00: 63 74 20 65 78 69 73 74 73 28 73 65 6c 65 63 74 ct exists(select
0a10: 20 74 72 75 65 20 66 72 6f 6d 20 72 73 73 74 67 true from rsstg
0a20: 5f 70 6f 73 74 20 77 68 65 72 65 20 75 72 6c 20 _post where url
0a30: 3d 20 24 31 20 61 6e 64 20 73 6f 75 72 63 65 5f = $1 and source_
0a40: 69 64 20 3d 20 24 32 29 20 61 73 20 65 78 69 73 id = $2) as exis
0a50: 74 73 3b 22 29 0a 09 09 09 09 09 09 09 09 2e 62 ts;")..........b
0a60: 69 6e 64 28 26 75 72 6c 29 0a 09 09 09 09 09 09 ind(&url).......
0a70: 09 09 2e 62 69 6e 64 28 69 64 29 0a 09 09 09 09 ...bind(id).....
0a80: 09 09 09 09 2e 66 65 74 63 68 5f 6f 6e 65 28 26 .....fetch_one(&
0a90: 73 65 6c 66 2e 70 6f 6f 6c 29 2e 61 77 61 69 74 self.pool).await
0aa0: 20 7b 0a 09 09 09 09 09 09 09 09 4f 6b 28 72 6f {.........Ok(ro
0ab0: 77 29 20 3d 3e 20 7b 0a 09 09 09 09 09 09 09 09 w) => {.........
0ac0: 09 6c 65 74 20 65 78 69 73 74 73 3a 20 62 6f 6f .let exists: boo
0ad0: 6c 20 3d 20 72 6f 77 2e 74 72 79 5f 67 65 74 28 l = row.try_get(
0ae0: 22 65 78 69 73 74 73 22 29 3f 3b 0a 09 09 09 09 "exists")?;.....
0af0: 09 09 09 09 09 69 66 20 21 20 65 78 69 73 74 73 .....if ! exists
0b00: 20 7b 0a 09 09 09 09 09 09 09 09 09 09 69 66 20 {...........if
0b10: 74 68 69 73 5f 66 65 74 63 68 20 3d 3d 20 4e 6f this_fetch == No
0b20: 6e 65 20 7c 7c 20 2a 64 61 74 65 20 3e 20 74 68 ne || *date > th
0b30: 69 73 5f 66 65 74 63 68 2e 75 6e 77 72 61 70 28 is_fetch.unwrap(
0b40: 29 20 7b 0a 09 09 09 09 09 09 09 09 09 09 09 74 ) {............t
0b50: 68 69 73 5f 66 65 74 63 68 20 3d 20 53 6f 6d 65 his_fetch = Some
0b60: 28 2a 64 61 74 65 29 3b 0a 09 09 09 09 09 09 09 (*date);........
0b70: 09 09 09 7d 0a 09 09 09 09 09 09 09 09 09 09 6d ...}...........m
0b80: 61 74 63 68 20 73 65 6c 66 2e 74 67 2e 73 65 6e atch self.tg.sen
0b90: 64 28 20 6d 61 74 63 68 20 69 76 5f 68 61 73 68 d( match iv_hash
0ba0: 20 7b 0a 09 09 09 09 09 09 09 09 09 09 09 09 53 {.............S
0bb0: 6f 6d 65 28 78 29 20 3d 3e 20 53 65 6e 64 4d 65 ome(x) => SendMe
0bc0: 73 73 61 67 65 3a 3a 6e 65 77 28 64 65 73 74 69 ssage::new(desti
0bd0: 6e 61 74 69 6f 6e 2c 20 66 6f 72 6d 61 74 21 28 nation, format!(
0be0: 22 3c 61 20 68 72 65 66 3d 5c 22 68 74 74 70 73 "<a href=\"https
0bf0: 3a 2f 2f 74 2e 6d 65 2f 69 76 3f 75 72 6c 3d 7b ://t.me/iv?url={
0c00: 7d 26 72 68 61 73 68 3d 7b 7d 5c 22 3e 20 3c 2f }&rhash={}\"> </
0c10: 61 3e 7b 30 7d 22 2c 20 75 72 6c 2c 20 78 29 29 a>{0}", url, x))
0c20: 2c 0a 09 09 09 09 09 09 09 09 09 09 09 09 4e 6f ,.............No
0c30: 6e 65 20 3d 3e 20 53 65 6e 64 4d 65 73 73 61 67 ne => SendMessag
0c40: 65 3a 3a 6e 65 77 28 64 65 73 74 69 6e 61 74 69 e::new(destinati
0c50: 6f 6e 2c 20 66 6f 72 6d 61 74 21 28 22 7b 7d 22 on, format!("{}"
0c60: 2c 20 75 72 6c 29 29 2c 0a 09 09 09 09 09 09 09 , url)),........
0c70: 09 09 09 09 7d 2e 70 61 72 73 65 5f 6d 6f 64 65 ....}.parse_mode
0c80: 28 74 79 70 65 73 3a 3a 50 61 72 73 65 4d 6f 64 (types::ParseMod
0c90: 65 3a 3a 48 74 6d 6c 29 29 2e 61 77 61 69 74 20 e::Html)).await
0ca0: 7b 0a 09 09 09 09 09 09 09 09 09 09 09 4f 6b 28 {............Ok(
0cb0: 5f 29 20 3d 3e 20 7b 0a 09 09 09 09 09 09 09 09 _) => {.........
0cc0: 09 09 09 09 6d 61 74 63 68 20 73 71 6c 78 3a 3a ....match sqlx::
0cd0: 71 75 65 72 79 28 22 69 6e 73 65 72 74 20 69 6e query("insert in
0ce0: 74 6f 20 72 73 73 74 67 5f 70 6f 73 74 20 28 73 to rsstg_post (s
0cf0: 6f 75 72 63 65 5f 69 64 2c 20 70 6f 73 74 65 64 ource_id, posted
0d00: 2c 20 75 72 6c 29 20 76 61 6c 75 65 73 20 28 24 , url) values ($
0d10: 31 2c 20 24 32 2c 20 24 33 29 3b 22 29 0a 09 09 1, $2, $3);")...
0d20: 09 09 09 09 09 09 09 09 09 09 09 2e 62 69 6e 64 ............bind
0d30: 28 69 64 29 0a 09 09 09 09 09 09 09 09 09 09 09 (id)............
0d40: 09 09 2e 62 69 6e 64 28 64 61 74 65 29 0a 09 09 ...bind(date)...
0d50: 09 09 09 09 09 09 09 09 09 09 09 2e 62 69 6e 64 ............bind
0d60: 28 75 72 6c 29 0a 09 09 09 09 09 09 09 09 09 09 (url)...........
0d70: 09 09 09 2e 65 78 65 63 75 74 65 28 26 73 65 6c ....execute(&sel
0d80: 66 2e 70 6f 6f 6c 29 2e 61 77 61 69 74 20 7b 0a f.pool).await {.
0d90: 09 09 09 09 09 09 09 09 09 09 09 09 09 09 4f 6b ..............Ok
0da0: 28 5f 29 20 3d 3e 20 7b 7d 2c 0a 09 09 09 09 09 (_) => {},......
0db0: 09 09 09 09 09 09 09 09 09 45 72 72 28 65 72 72 .........Err(err
0dc0: 29 20 3d 3e 20 7b 0a 09 09 09 09 09 09 09 09 09 ) => {..........
0dd0: 09 09 09 09 09 09 73 65 6c 66 2e 64 65 62 75 67 ......self.debug
0de0: 28 26 65 72 72 2e 74 6f 5f 73 74 72 69 6e 67 28 (&err.to_string(
0df0: 29 29 3f 3b 0a 09 09 09 09 09 09 09 09 09 09 09 ))?;............
0e00: 09 09 09 7d 2c 0a 09 09 09 09 09 09 09 09 09 09 ...},...........
0e10: 09 09 7d 3b 0a 09 09 09 09 09 09 09 09 09 09 09 ..};............
0e20: 7d 2c 0a 09 09 09 09 09 09 09 09 09 09 09 45 72 },............Er
0e30: 72 28 65 72 72 29 20 3d 3e 20 7b 0a 09 09 09 09 r(err) => {.....
0e40: 09 09 09 09 09 09 09 09 73 65 6c 66 2e 64 65 62 ........self.deb
0e50: 75 67 28 26 65 72 72 2e 74 6f 5f 73 74 72 69 6e ug(&err.to_strin
0e60: 67 28 29 29 3f 3b 0a 09 09 09 09 09 09 09 09 09 g())?;..........
0e70: 09 09 7d 2c 0a 09 09 09 09 09 09 09 09 09 09 7d ..},...........}
0e80: 3b 0a 09 09 09 09 09 09 09 09 09 09 74 6f 6b 69 ;...........toki
0e90: 6f 3a 3a 74 69 6d 65 3a 3a 64 65 6c 61 79 5f 66 o::time::delay_f
0ea0: 6f 72 28 73 74 64 3a 3a 74 69 6d 65 3a 3a 44 75 or(std::time::Du
0eb0: 72 61 74 69 6f 6e 3a 3a 6e 65 77 28 34 2c 20 30 ration::new(4, 0
0ec0: 29 29 2e 61 77 61 69 74 3b 0a 09 09 09 09 09 09 )).await;.......
0ed0: 09 09 09 7d 0a 09 09 09 09 09 09 09 09 7d 2c 0a ...}.........},.
0ee0: 09 09 09 09 09 09 09 09 45 72 72 28 65 72 72 29 ........Err(err)
0ef0: 20 3d 3e 20 7b 0a 09 09 09 09 09 09 09 09 09 73 => {..........s
0f00: 65 6c 66 2e 64 65 62 75 67 28 26 65 72 72 2e 74 elf.debug(&err.t
0f10: 6f 5f 73 74 72 69 6e 67 28 29 29 3f 3b 0a 09 09 o_string())?;...
0f20: 09 09 09 09 09 09 7d 2c 0a 09 09 09 09 09 09 09 ......},........
0f30: 7d 3b 0a 09 09 09 09 09 09 7d 3b 0a 09 09 09 09 };.......};.....
0f40: 09 09 70 6f 73 74 73 2e 63 6c 65 61 72 28 29 3b ..posts.clear();
0f50: 0a 09 09 09 09 09 7d 2c 0a 09 09 09 09 09 45 72 ......},......Er
0f60: 72 28 65 72 72 29 20 3d 3e 20 7b 0a 09 09 09 09 r(err) => {.....
0f70: 09 09 73 65 6c 66 2e 64 65 62 75 67 28 26 65 72 ..self.debug(&er
0f80: 72 2e 74 6f 5f 73 74 72 69 6e 67 28 29 29 3f 3b r.to_string())?;
0f90: 0a 09 09 09 09 09 7d 2c 0a 09 09 09 09 7d 3b 0a ......},.....};.
0fa0: 09 09 09 09 6d 61 74 63 68 20 73 71 6c 78 3a 3a ....match sqlx::
0fb0: 71 75 65 72 79 28 22 75 70 64 61 74 65 20 72 73 query("update rs
0fc0: 73 74 67 5f 73 6f 75 72 63 65 20 73 65 74 20 6c stg_source set l
0fd0: 61 73 74 5f 73 63 72 61 70 65 20 3d 20 6e 6f 77 ast_scrape = now
0fe0: 28 29 20 77 68 65 72 65 20 73 6f 75 72 63 65 5f () where source_
0ff0: 69 64 20 3d 20 24 31 3b 22 29 0a 09 09 09 09 09 id = $1;")......
1000: 2e 62 69 6e 64 28 69 64 29 0a 09 09 09 09 09 2e .bind(id).......
1010: 65 78 65 63 75 74 65 28 26 73 65 6c 66 2e 70 6f execute(&self.po
1020: 6f 6c 29 2e 61 77 61 69 74 20 7b 0a 09 09 09 09 ol).await {.....
1030: 09 4f 6b 28 5f 29 20 3d 3e 20 7b 7d 2c 0a 09 09 .Ok(_) => {},...
1040: 09 09 09 45 72 72 28 65 72 72 29 20 3d 3e 20 7b ...Err(err) => {
1050: 0a 09 09 09 09 09 09 73 65 6c 66 2e 64 65 62 75 .......self.debu
1060: 67 28 26 65 72 72 2e 74 6f 5f 73 74 72 69 6e 67 g(&err.to_string
1070: 28 29 29 3f 3b 0a 09 09 09 09 09 7d 2c 0a 09 09 ())?;......},...
1080: 09 09 7d 3b 0a 09 09 09 7d 2c 0a 09 09 09 45 72 ..};....},....Er
1090: 72 28 65 72 72 29 20 3d 3e 20 7b 0a 09 09 09 09 r(err) => {.....
10a0: 73 65 6c 66 2e 64 65 62 75 67 28 26 65 72 72 2e self.debug(&err.
10b0: 74 6f 5f 73 74 72 69 6e 67 28 29 29 3f 3b 0a 09 to_string())?;..
10c0: 09 09 7d 2c 0a 09 09 7d 3b 0a 09 09 4f 6b 28 28 ..},...};...Ok((
10d0: 29 29 0a 09 7d 0a 0a 09 61 73 79 6e 63 20 66 6e ))..}...async fn
10e0: 20 63 6c 65 61 6e 28 26 73 65 6c 66 2c 20 73 6f clean(&self, so
10f0: 75 72 63 65 5f 69 64 3a 20 69 33 32 29 20 2d 3e urce_id: i32) ->
1100: 20 52 65 73 75 6c 74 3c 28 29 3e 20 7b 0a 09 09 Result<()> {...
1110: 6d 61 74 63 68 20 73 71 6c 78 3a 3a 71 75 65 72 match sqlx::quer
1120: 79 28 22 64 65 6c 65 74 65 20 66 72 6f 6d 20 72 y("delete from r
1130: 73 73 74 67 5f 70 6f 73 74 20 77 68 65 72 65 20 sstg_post where
1140: 73 6f 75 72 63 65 5f 69 64 20 3d 20 24 31 3b 22 source_id = $1;"
1150: 29 0a 09 09 09 2e 62 69 6e 64 28 73 6f 75 72 63 ).....bind(sourc
1160: 65 5f 69 64 29 0a 09 09 09 2e 65 78 65 63 75 74 e_id).....execut
1170: 65 28 26 73 65 6c 66 2e 70 6f 6f 6c 29 2e 61 77 e(&self.pool).aw
1180: 61 69 74 20 7b 0a 09 09 09 4f 6b 28 5f 29 20 3d ait {....Ok(_) =
1190: 3e 20 7b 7d 2c 0a 09 09 09 45 72 72 28 65 72 72 > {},....Err(err
11a0: 29 20 3d 3e 20 7b 0a 09 09 09 09 73 65 6c 66 2e ) => {.....self.
11b0: 64 65 62 75 67 28 26 65 72 72 2e 74 6f 5f 73 74 debug(&err.to_st
11c0: 72 69 6e 67 28 29 29 3f 3b 0a 09 09 09 7d 2c 0a ring())?;....},.
11d0: 09 09 7d 3b 0a 09 09 4f 6b 28 28 29 29 0a 09 7d ..};...Ok(())..}
11e0: 0a 0a 09 61 73 79 6e 63 20 66 6e 20 65 6e 61 62 ...async fn enab
11f0: 6c 65 28 26 73 65 6c 66 2c 20 73 6f 75 72 63 65 le(&self, source
1200: 5f 69 64 3a 20 26 69 33 32 29 20 2d 3e 20 52 65 _id: &i32) -> Re
1210: 73 75 6c 74 3c 28 29 3e 20 7b 0a 09 09 6d 61 74 sult<()> {...mat
1220: 63 68 20 73 71 6c 78 3a 3a 71 75 65 72 79 28 22 ch sqlx::query("
1230: 75 70 64 61 74 65 20 72 73 73 74 67 5f 73 6f 75 update rsstg_sou
1240: 72 63 65 20 73 65 74 20 65 6e 61 62 6c 65 64 20 rce set enabled
1250: 3d 20 74 72 75 65 20 77 68 65 72 65 20 73 6f 75 = true where sou
1260: 72 63 65 5f 69 64 20 3d 20 24 31 22 29 0a 09 09 rce_id = $1")...
1270: 09 2e 62 69 6e 64 28 73 6f 75 72 63 65 5f 69 64 ..bind(source_id
1280: 29 0a 09 09 09 2e 65 78 65 63 75 74 65 28 26 73 ).....execute(&s
1290: 65 6c 66 2e 70 6f 6f 6c 29 2e 61 77 61 69 74 20 elf.pool).await
12a0: 7b 0a 09 09 09 4f 6b 28 5f 29 20 3d 3e 20 7b 7d {....Ok(_) => {}
12b0: 2c 0a 09 09 09 45 72 72 28 65 72 72 29 20 3d 3e ,....Err(err) =>
12c0: 20 7b 0a 09 09 09 09 73 65 6c 66 2e 64 65 62 75 {.....self.debu
12d0: 67 28 26 65 72 72 2e 74 6f 5f 73 74 72 69 6e 67 g(&err.to_string
12e0: 28 29 29 3f 3b 0a 09 09 09 7d 2c 0a 09 09 7d 0a ())?;....},...}.
12f0: 09 09 4f 6b 28 28 29 29 0a 09 7d 0a 0a 09 61 73 ..Ok(())..}...as
1300: 79 6e 63 20 66 6e 20 64 69 73 61 62 6c 65 28 26 ync fn disable(&
1310: 73 65 6c 66 2c 20 73 6f 75 72 63 65 5f 69 64 3a self, source_id:
1320: 20 26 69 33 32 29 20 2d 3e 20 52 65 73 75 6c 74 &i32) -> Result
1330: 3c 28 29 3e 20 7b 0a 09 09 6d 61 74 63 68 20 73 <()> {...match s
1340: 71 6c 78 3a 3a 71 75 65 72 79 28 22 75 70 64 61 qlx::query("upda
1350: 74 65 20 72 73 73 74 67 5f 73 6f 75 72 63 65 20 te rsstg_source
1360: 73 65 74 20 65 6e 61 62 6c 65 64 20 3d 20 66 61 set enabled = fa
1370: 6c 73 65 20 77 68 65 72 65 20 73 6f 75 72 63 65 lse where source
1380: 5f 69 64 20 3d 20 24 31 22 29 0a 09 09 09 2e 62 _id = $1").....b
1390: 69 6e 64 28 73 6f 75 72 63 65 5f 69 64 29 0a 09 ind(source_id)..
13a0: 09 09 2e 65 78 65 63 75 74 65 28 26 73 65 6c 66 ...execute(&self
13b0: 2e 70 6f 6f 6c 29 2e 61 77 61 69 74 20 7b 0a 09 .pool).await {..
13c0: 09 09 4f 6b 28 5f 29 20 3d 3e 20 7b 7d 2c 0a 09 ..Ok(_) => {},..
13d0: 09 09 45 72 72 28 65 72 72 29 20 3d 3e 20 7b 0a ..Err(err) => {.
13e0: 09 09 09 09 73 65 6c 66 2e 64 65 62 75 67 28 26 ....self.debug(&
13f0: 65 72 72 2e 74 6f 5f 73 74 72 69 6e 67 28 29 29 err.to_string())
1400: 3f 3b 0a 09 09 09 7d 2c 0a 09 09 7d 0a 09 09 4f ?;....},...}...O
1410: 6b 28 28 29 29 0a 09 7d 0a 0a 09 61 73 79 6e 63 k(())..}...async
1420: 20 66 6e 20 61 75 74 6f 66 65 74 63 68 28 26 73 fn autofetch(&s
1430: 65 6c 66 29 20 2d 3e 20 52 65 73 75 6c 74 3c 28 elf) -> Result<(
1440: 29 3e 20 7b 0a 09 09 6c 65 74 20 6d 75 74 20 64 )> {...let mut d
1450: 65 6c 61 79 20 3d 20 63 68 72 6f 6e 6f 3a 3a 44 elay = chrono::D
1460: 75 72 61 74 69 6f 6e 3a 3a 6d 69 6e 75 74 65 73 uration::minutes
1470: 28 35 29 3b 0a 09 09 6c 65 74 20 6d 75 74 20 6e (5);...let mut n
1480: 65 78 74 5f 66 65 74 63 68 3a 20 44 61 74 65 54 ext_fetch: DateT
1490: 69 6d 65 3c 63 68 72 6f 6e 6f 3a 3a 4c 6f 63 61 ime<chrono::Loca
14a0: 6c 3e 3b 0a 09 09 6c 65 74 20 6d 75 74 20 6e 6f l>;...let mut no
14b0: 77 3b 0a 09 09 6c 6f 6f 70 20 7b 0a 09 09 09 73 w;...loop {....s
14c0: 65 6c 66 2e 64 65 62 75 67 28 22 63 79 63 6c 65 elf.debug("cycle
14d0: 22 29 3f 3b 0a 09 09 09 6e 6f 77 20 3d 20 63 68 ")?;....now = ch
14e0: 72 6f 6e 6f 3a 3a 4c 6f 63 61 6c 3a 3a 6e 6f 77 rono::Local::now
14f0: 28 29 3b 0a 09 09 09 6c 65 74 20 6d 75 74 20 72 ();....let mut r
1500: 6f 77 73 20 3d 20 73 71 6c 78 3a 3a 71 75 65 72 ows = sqlx::quer
1510: 79 28 22 73 65 6c 65 63 74 20 73 6f 75 72 63 65 y("select source
1520: 5f 69 64 2c 20 6e 65 78 74 5f 66 65 74 63 68 20 _id, next_fetch
1530: 66 72 6f 6d 20 72 73 73 74 67 5f 6f 72 64 65 72 from rsstg_order
1540: 20 6e 61 74 75 72 61 6c 20 6c 65 66 74 20 6a 6f natural left jo
1550: 69 6e 20 72 73 73 74 67 5f 73 6f 75 72 63 65 20 in rsstg_source
1560: 6e 61 74 75 72 61 6c 20 6c 65 66 74 20 6a 6f 69 natural left joi
1570: 6e 20 72 73 73 74 67 5f 63 68 61 6e 6e 65 6c 20 n rsstg_channel
1580: 77 68 65 72 65 20 6e 65 78 74 5f 66 65 74 63 68 where next_fetch
1590: 20 3c 20 6e 6f 77 28 29 3b 22 29 0a 09 09 09 09 < now();").....
15a0: 2e 66 65 74 63 68 28 26 73 65 6c 66 2e 70 6f 6f .fetch(&self.poo
15b0: 6c 29 3b 0a 09 09 09 77 68 69 6c 65 20 6c 65 74 l);....while let
15c0: 20 53 6f 6d 65 28 72 6f 77 29 20 3d 20 72 6f 77 Some(row) = row
15d0: 73 2e 74 72 79 5f 6e 65 78 74 28 29 2e 61 77 61 s.try_next().awa
15e0: 69 74 2e 75 6e 77 72 61 70 28 29 20 7b 0a 09 09 it.unwrap() {...
15f0: 09 09 6c 65 74 20 73 6f 75 72 63 65 5f 69 64 3a ..let source_id:
1600: 20 69 33 32 20 3d 20 72 6f 77 2e 74 72 79 5f 67 i32 = row.try_g
1610: 65 74 28 22 73 6f 75 72 63 65 5f 69 64 22 29 3f et("source_id")?
1620: 3b 0a 09 09 09 09 6e 65 78 74 5f 66 65 74 63 68 ;.....next_fetch
1630: 20 3d 20 72 6f 77 2e 74 72 79 5f 67 65 74 28 22 = row.try_get("
1640: 6e 65 78 74 5f 66 65 74 63 68 22 29 3f 3b 0a 09 next_fetch")?;..
1650: 09 09 09 69 66 20 6e 65 78 74 5f 66 65 74 63 68 ...if next_fetch
1660: 20 3c 20 6e 6f 77 20 7b 0a 09 09 09 09 09 6d 61 < now {......ma
1670: 74 63 68 20 73 71 6c 78 3a 3a 71 75 65 72 79 28 tch sqlx::query(
1680: 22 75 70 64 61 74 65 20 72 73 73 74 67 5f 73 6f "update rsstg_so
1690: 75 72 63 65 20 73 65 74 20 6c 61 73 74 5f 73 63 urce set last_sc
16a0: 72 61 70 65 20 3d 20 6e 6f 77 28 29 20 2b 20 69 rape = now() + i
16b0: 6e 74 65 72 76 61 6c 20 27 31 20 68 6f 75 72 27 nterval '1 hour'
16c0: 20 77 68 65 72 65 20 73 6f 75 72 63 65 5f 69 64 where source_id
16d0: 20 3d 20 24 31 3b 22 29 0a 09 09 09 09 09 09 2e = $1;")........
16e0: 62 69 6e 64 28 73 6f 75 72 63 65 5f 69 64 29 0a bind(source_id).
16f0: 09 09 09 09 09 09 2e 65 78 65 63 75 74 65 28 26 .......execute(&
1700: 73 65 6c 66 2e 70 6f 6f 6c 29 2e 61 77 61 69 74 self.pool).await
1710: 20 7b 0a 09 09 09 09 09 09 4f 6b 28 5f 29 20 3d {.......Ok(_) =
1720: 3e 20 7b 7d 2c 0a 09 09 09 09 09 09 45 72 72 28 > {},.......Err(
1730: 65 72 72 29 20 3d 3e 20 7b 0a 09 09 09 09 09 09 err) => {.......
1740: 09 73 65 6c 66 2e 64 65 62 75 67 28 26 65 72 72 .self.debug(&err
1750: 2e 74 6f 5f 73 74 72 69 6e 67 28 29 29 3f 3b 0a .to_string())?;.
1760: 09 09 09 09 09 09 7d 2c 0a 09 09 09 09 09 7d 3b ......},......};
1770: 0a 09 09 09 09 09 6c 65 74 20 63 6c 6f 6e 65 20 ......let clone
1780: 3d 20 73 65 6c 66 2e 63 6c 6f 6e 65 28 29 3b 0a = self.clone();.
1790: 09 09 09 09 09 74 6f 6b 69 6f 3a 3a 73 70 61 77 .....tokio::spaw
17a0: 6e 28 61 73 79 6e 63 20 6d 6f 76 65 20 7b 0a 09 n(async move {..
17b0: 09 09 09 09 09 69 66 20 6c 65 74 20 45 72 72 28 .....if let Err(
17c0: 65 72 72 29 20 3d 20 63 6c 6f 6e 65 2e 63 68 65 err) = clone.che
17d0: 63 6b 28 26 73 6f 75 72 63 65 5f 69 64 2e 63 6c ck(&source_id.cl
17e0: 6f 6e 65 28 29 2c 20 53 6f 6d 65 28 74 72 75 65 one(), Some(true
17f0: 29 29 2e 61 77 61 69 74 20 7b 0a 09 09 09 09 09 )).await {......
1800: 09 09 65 70 72 69 6e 74 6c 6e 21 28 22 63 6f 6e ..eprintln!("con
1810: 6e 65 63 74 69 6f 6e 20 65 72 72 6f 72 3a 20 7b nection error: {
1820: 7d 22 2c 20 65 72 72 29 3b 0a 09 09 09 09 09 09 }", err);.......
1830: 7d 0a 09 09 09 09 09 7d 29 3b 0a 09 09 09 09 7d }......});.....}
1840: 20 65 6c 73 65 20 7b 0a 09 09 09 09 09 69 66 20 else {......if
1850: 6e 65 78 74 5f 66 65 74 63 68 20 2d 20 6e 6f 77 next_fetch - now
1860: 20 3c 20 64 65 6c 61 79 20 7b 0a 09 09 09 09 09 < delay {......
1870: 09 64 65 6c 61 79 20 3d 20 6e 65 78 74 5f 66 65 .delay = next_fe
1880: 74 63 68 20 2d 20 6e 6f 77 3b 0a 09 09 09 09 09 tch - now;......
1890: 7d 0a 09 09 09 09 7d 0a 09 09 09 7d 3b 0a 09 09 }.....}....};...
18a0: 09 74 6f 6b 69 6f 3a 3a 74 69 6d 65 3a 3a 64 65 .tokio::time::de
18b0: 6c 61 79 5f 66 6f 72 28 64 65 6c 61 79 2e 74 6f lay_for(delay.to
18c0: 5f 73 74 64 28 29 3f 29 2e 61 77 61 69 74 3b 0a _std()?).await;.
18d0: 09 09 09 64 65 6c 61 79 20 3d 20 63 68 72 6f 6e ...delay = chron
18e0: 6f 3a 3a 44 75 72 61 74 69 6f 6e 3a 3a 6d 69 6e o::Duration::min
18f0: 75 74 65 73 28 35 29 3b 0a 09 09 7d 0a 09 09 2f utes(5);...}.../
1900: 2f 4f 6b 28 28 29 29 0a 09 7d 0a 0a 7d 0a 0a 23 /Ok(())..}..}..#
1910: 5b 74 6f 6b 69 6f 3a 3a 6d 61 69 6e 28 62 61 73 [tokio::main(bas
1920: 69 63 5f 73 63 68 65 64 75 6c 65 72 29 5d 0a 61 ic_scheduler)].a
1930: 73 79 6e 63 20 66 6e 20 6d 61 69 6e 28 29 20 2d sync fn main() -
1940: 3e 20 52 65 73 75 6c 74 3c 28 29 3e 20 7b 0a 09 > Result<()> {..
1950: 6c 65 74 20 6d 75 74 20 73 65 74 74 69 6e 67 73 let mut settings
1960: 20 3d 20 63 6f 6e 66 69 67 3a 3a 43 6f 6e 66 69 = config::Confi
1970: 67 3a 3a 64 65 66 61 75 6c 74 28 29 3b 0a 09 73 g::default();..s
1980: 65 74 74 69 6e 67 73 2e 6d 65 72 67 65 28 63 6f ettings.merge(co
1990: 6e 66 69 67 3a 3a 46 69 6c 65 3a 3a 77 69 74 68 nfig::File::with
19a0: 5f 6e 61 6d 65 28 22 72 73 73 74 67 22 29 29 3f _name("rsstg"))?
19b0: 3b 0a 0a 09 6c 65 74 20 72 65 5f 75 73 65 72 6e ;...let re_usern
19c0: 61 6d 65 20 3d 20 52 65 67 65 78 3a 3a 6e 65 77 ame = Regex::new
19d0: 28 72 22 5e 40 5b 61 2d 7a 41 2d 5a 5d 5b 61 2d (r"^@[a-zA-Z][a-
19e0: 7a 41 2d 5a 30 2d 39 5f 5d 2b 24 22 29 3f 3b 0a zA-Z0-9_]+$")?;.
19f0: 09 6c 65 74 20 72 65 5f 6c 69 6e 6b 20 3d 20 52 .let re_link = R
1a00: 65 67 65 78 3a 3a 6e 65 77 28 72 22 5e 68 74 74 egex::new(r"^htt
1a10: 70 73 3f 3a 2f 2f 5b 61 2d 7a 41 2d 5a 2e 30 2d ps?://[a-zA-Z.0-
1a20: 39 2d 5d 2b 2f 5b 2d 5f 61 2d 7a 41 2d 5a 2e 30 9-]+/[-_a-zA-Z.0
1a30: 2d 39 2f 3f 3d 5d 2b 24 22 29 3f 3b 0a 09 6c 65 -9/?=]+$")?;..le
1a40: 74 20 72 65 5f 69 76 5f 68 61 73 68 20 3d 20 52 t re_iv_hash = R
1a50: 65 67 65 78 3a 3a 6e 65 77 28 72 22 5e 5b 61 2d egex::new(r"^[a-
1a60: 66 30 2d 39 5d 7b 31 34 7d 24 22 29 3f 3b 0a 0a f0-9]{14}$")?;..
1a70: 09 6c 65 74 20 63 6f 72 65 20 3d 20 43 6f 72 65 .let core = Core
1a80: 3a 3a 6e 65 77 28 73 65 74 74 69 6e 67 73 29 2e ::new(settings).
1a90: 61 77 61 69 74 3f 3b 0a 0a 09 6c 65 74 20 6d 75 await?;...let mu
1aa0: 74 20 73 74 72 65 61 6d 20 3d 20 63 6f 72 65 2e t stream = core.
1ab0: 73 74 72 65 61 6d 28 29 3b 0a 0a 09 77 68 69 6c stream();...whil
1ac0: 65 20 6c 65 74 20 53 6f 6d 65 28 75 70 64 61 74 e let Some(updat
1ad0: 65 29 20 3d 20 73 74 72 65 61 6d 2e 6e 65 78 74 e) = stream.next
1ae0: 28 29 2e 61 77 61 69 74 20 7b 0a 09 09 6c 65 74 ().await {...let
1af0: 20 75 70 64 61 74 65 20 3d 20 75 70 64 61 74 65 update = update
1b00: 3f 3b 0a 09 09 6d 61 74 63 68 20 75 70 64 61 74 ?;...match updat
1b10: 65 2e 6b 69 6e 64 20 7b 0a 09 09 09 55 70 64 61 e.kind {....Upda
1b20: 74 65 4b 69 6e 64 3a 3a 4d 65 73 73 61 67 65 28 teKind::Message(
1b30: 6d 65 73 73 61 67 65 29 20 3d 3e 20 7b 0a 09 09 message) => {...
1b40: 09 09 6c 65 74 20 6d 75 74 20 72 65 70 6c 79 3a ..let mut reply:
1b50: 20 56 65 63 3c 53 74 72 69 6e 67 3e 20 3d 20 76 Vec<String> = v
1b60: 65 63 21 5b 5d 3b 0a 09 09 09 09 6d 61 74 63 68 ec![];.....match
1b70: 20 6d 65 73 73 61 67 65 2e 6b 69 6e 64 20 7b 0a message.kind {.
1b80: 09 09 09 09 09 4d 65 73 73 61 67 65 4b 69 6e 64 .....MessageKind
1b90: 3a 3a 54 65 78 74 20 7b 20 72 65 66 20 64 61 74 ::Text { ref dat
1ba0: 61 2c 20 2e 2e 20 7d 20 3d 3e 20 7b 0a 09 09 09 a, .. } => {....
1bb0: 09 09 09 6c 65 74 20 6d 75 74 20 77 6f 72 64 73 ...let mut words
1bc0: 20 3d 20 64 61 74 61 2e 73 70 6c 69 74 5f 77 68 = data.split_wh
1bd0: 69 74 65 73 70 61 63 65 28 29 3b 0a 09 09 09 09 itespace();.....
1be0: 09 09 6c 65 74 20 63 6d 64 20 3d 20 77 6f 72 64 ..let cmd = word
1bf0: 73 2e 6e 65 78 74 28 29 2e 75 6e 77 72 61 70 28 s.next().unwrap(
1c00: 29 3b 0a 09 09 09 09 09 09 6d 61 74 63 68 20 63 );.......match c
1c10: 6d 64 20 7b 0a 0a 2f 2f 20 73 74 61 72 74 0a 0a md {..// start..
1c20: 09 09 09 09 09 09 09 22 2f 73 74 61 72 74 22 20 ......."/start"
1c30: 3d 3e 20 7b 0a 09 09 09 09 09 09 09 09 72 65 70 => {.........rep
1c40: 6c 79 2e 70 75 73 68 28 22 4e 6f 74 20 69 6e 20 ly.push("Not in
1c50: 73 65 72 76 69 63 65 20 79 65 74 5c 5c 2e 20 54 service yet\\. T
1c60: 72 79 20 6c 61 74 65 72 5c 5c 2e 22 2e 74 6f 5f ry later\\.".to_
1c70: 73 74 72 69 6e 67 28 29 29 3b 0a 09 09 09 09 09 string());......
1c80: 09 09 7d 2c 0a 0a 2f 2f 20 6c 69 73 74 0a 0a 09 ..},..// list...
1c90: 09 09 09 09 09 09 22 2f 6c 69 73 74 22 20 3d 3e ......"/list" =>
1ca0: 20 7b 0a 09 09 09 09 09 09 09 09 72 65 70 6c 79 {.........reply
1cb0: 2e 70 75 73 68 28 22 43 68 61 6e 6e 65 6c 73 3a .push("Channels:
1cc0: 22 2e 74 6f 5f 73 74 72 69 6e 67 28 29 29 3b 0a ".to_string());.
1cd0: 09 09 09 09 09 09 09 09 6c 65 74 20 6d 75 74 20 ........let mut
1ce0: 72 6f 77 73 20 3d 20 73 71 6c 78 3a 3a 71 75 65 rows = sqlx::que
1cf0: 72 79 28 22 73 65 6c 65 63 74 20 73 6f 75 72 63 ry("select sourc
1d00: 65 5f 69 64 2c 20 75 73 65 72 6e 61 6d 65 2c 20 e_id, username,
1d10: 65 6e 61 62 6c 65 64 2c 20 75 72 6c 2c 20 69 76 enabled, url, iv
1d20: 5f 68 61 73 68 20 66 72 6f 6d 20 72 73 73 74 67 _hash from rsstg
1d30: 5f 73 6f 75 72 63 65 20 6c 65 66 74 20 6a 6f 69 _source left joi
1d40: 6e 20 72 73 73 74 67 5f 63 68 61 6e 6e 65 6c 20 n rsstg_channel
1d50: 75 73 69 6e 67 20 28 63 68 61 6e 6e 65 6c 5f 69 using (channel_i
1d60: 64 29 20 77 68 65 72 65 20 6f 77 6e 65 72 20 3d d) where owner =
1d70: 20 24 31 20 6f 72 64 65 72 20 62 79 20 73 6f 75 $1 order by sou
1d80: 72 63 65 5f 69 64 22 29 0a 09 09 09 09 09 09 09 rce_id")........
1d90: 09 09 2e 62 69 6e 64 28 69 36 34 3a 3a 66 72 6f ...bind(i64::fro
1da0: 6d 28 6d 65 73 73 61 67 65 2e 66 72 6f 6d 2e 69 m(message.from.i
1db0: 64 29 29 0a 09 09 09 09 09 09 09 09 09 2e 66 65 d))...........fe
1dc0: 74 63 68 28 26 63 6f 72 65 2e 70 6f 6f 6c 29 3b tch(&core.pool);
1dd0: 0a 09 09 09 09 09 09 09 09 77 68 69 6c 65 20 6c .........while l
1de0: 65 74 20 53 6f 6d 65 28 72 6f 77 29 20 3d 20 72 et Some(row) = r
1df0: 6f 77 73 2e 74 72 79 5f 6e 65 78 74 28 29 2e 61 ows.try_next().a
1e00: 77 61 69 74 3f 20 7b 0a 09 09 09 09 09 09 09 09 wait? {.........
1e10: 09 6c 65 74 20 73 6f 75 72 63 65 5f 69 64 3a 20 .let source_id:
1e20: 69 33 32 20 3d 20 72 6f 77 2e 74 72 79 5f 67 65 i32 = row.try_ge
1e30: 74 28 22 73 6f 75 72 63 65 5f 69 64 22 29 3f 3b t("source_id")?;
1e40: 0a 09 09 09 09 09 09 09 09 09 6c 65 74 20 75 73 ..........let us
1e50: 65 72 6e 61 6d 65 3a 20 26 73 74 72 20 3d 20 72 ername: &str = r
1e60: 6f 77 2e 74 72 79 5f 67 65 74 28 22 75 73 65 72 ow.try_get("user
1e70: 6e 61 6d 65 22 29 3f 3b 0a 09 09 09 09 09 09 09 name")?;........
1e80: 09 09 6c 65 74 20 65 6e 61 62 6c 65 64 3a 20 62 ..let enabled: b
1e90: 6f 6f 6c 20 3d 20 72 6f 77 2e 74 72 79 5f 67 65 ool = row.try_ge
1ea0: 74 28 22 65 6e 61 62 6c 65 64 22 29 3f 3b 0a 09 t("enabled")?;..
1eb0: 09 09 09 09 09 09 09 09 6c 65 74 20 75 72 6c 3a ........let url:
1ec0: 20 26 73 74 72 20 3d 20 72 6f 77 2e 74 72 79 5f &str = row.try_
1ed0: 67 65 74 28 22 75 72 6c 22 29 3f 3b 0a 09 09 09 get("url")?;....
1ee0: 09 09 09 09 09 09 6c 65 74 20 69 76 5f 68 61 73 ......let iv_has
1ef0: 68 3a 20 4f 70 74 69 6f 6e 3c 26 73 74 72 3e 20 h: Option<&str>
1f00: 3d 20 72 6f 77 2e 74 72 79 5f 67 65 74 28 22 69 = row.try_get("i
1f10: 76 5f 68 61 73 68 22 29 3f 3b 0a 09 09 09 09 09 v_hash")?;......
1f20: 09 09 09 09 72 65 70 6c 79 2e 70 75 73 68 28 66 ....reply.push(f
1f30: 6f 72 6d 61 74 21 28 22 5c 6e 5c 5c 23 ef b8 8f ormat!("\n\\#️
1f40: e2 83 a3 20 7b 7d 20 5c 5c 2a ef b8 8f e2 83 a3 ⃣ {} \\*️⃣
1f50: 20 60 7b 7d 60 20 7b 7d 5c 6e f0 9f 94 97 20 60 `{}` {}\n🔗 `
1f60: 7b 7d 60 22 2c 20 73 6f 75 72 63 65 5f 69 64 2c {}`", source_id,
1f70: 20 75 73 65 72 6e 61 6d 65 2c 20 20 0a 09 09 09 username, ....
1f80: 09 09 09 09 09 09 09 6d 61 74 63 68 20 65 6e 61 .......match ena
1f90: 62 6c 65 64 20 7b 0a 09 09 09 09 09 09 09 09 09 bled {..........
1fa0: 09 09 74 72 75 65 20 20 3d 3e 20 22 f0 9f 94 84 ..true => "🔄
1fb0: 20 65 6e 61 62 6c 65 64 22 2c 0a 09 09 09 09 09 enabled",......
1fc0: 09 09 09 09 09 09 66 61 6c 73 65 20 3d 3e 20 22 ......false => "
1fd0: e2 9b 94 20 64 69 73 61 62 6c 65 64 22 2c 0a 09 ⛔ disabled",..
1fe0: 09 09 09 09 09 09 09 09 09 7d 2c 20 75 72 6c 29 .........}, url)
1ff0: 29 3b 0a 09 09 09 09 09 09 09 09 09 69 66 20 6c );..........if l
2000: 65 74 20 53 6f 6d 65 28 68 61 73 68 29 20 3d 20 et Some(hash) =
2010: 69 76 5f 68 61 73 68 20 7b 0a 09 09 09 09 09 09 iv_hash {.......
2020: 09 09 09 09 72 65 70 6c 79 2e 70 75 73 68 28 66 ....reply.push(f
2030: 6f 72 6d 61 74 21 28 22 49 56 20 60 7b 7d 60 22 ormat!("IV `{}`"
2040: 2c 20 68 61 73 68 29 29 3b 0a 09 09 09 09 09 09 , hash));.......
2050: 09 09 09 7d 0a 09 09 09 09 09 09 09 09 7d 0a 09 ...}.........}..
2060: 09 09 09 09 09 09 7d 2c 0a 0a 2f 2f 20 61 64 64 ......},..// add
2070: 0a 0a 09 09 09 09 09 09 09 22 2f 61 64 64 22 20 ........."/add"
2080: 7c 20 22 2f 75 70 64 61 74 65 22 20 3d 3e 20 7b | "/update" => {
2090: 0a 09 09 09 09 09 09 09 09 6c 65 74 20 6d 75 74 .........let mut
20a0: 20 73 6f 75 72 63 65 5f 69 64 3a 20 69 33 32 20 source_id: i32
20b0: 3d 20 30 3b 0a 09 09 09 09 09 09 09 09 69 66 20 = 0;.........if
20c0: 63 6d 64 20 3d 3d 20 22 2f 75 70 64 61 74 65 22 cmd == "/update"
20d0: 20 7b 0a 09 09 09 09 09 09 09 09 09 73 6f 75 72 {..........sour
20e0: 63 65 5f 69 64 20 3d 20 77 6f 72 64 73 2e 6e 65 ce_id = words.ne
20f0: 78 74 28 29 2e 75 6e 77 72 61 70 28 29 2e 70 61 xt().unwrap().pa
2100: 72 73 65 3a 3a 3c 69 33 32 3e 28 29 3f 3b 0a 09 rse::<i32>()?;..
2110: 09 09 09 09 09 09 09 7d 0a 09 09 09 09 09 09 09 .......}........
2120: 09 6c 65 74 20 28 63 68 61 6e 6e 65 6c 2c 20 75 .let (channel, u
2130: 72 6c 2c 20 69 76 5f 68 61 73 68 29 20 3d 20 28 rl, iv_hash) = (
2140: 77 6f 72 64 73 2e 6e 65 78 74 28 29 2e 75 6e 77 words.next().unw
2150: 72 61 70 28 29 2c 20 77 6f 72 64 73 2e 6e 65 78 rap(), words.nex
2160: 74 28 29 2e 75 6e 77 72 61 70 28 29 2c 20 77 6f t().unwrap(), wo
2170: 72 64 73 2e 6e 65 78 74 28 29 29 3b 0a 09 09 09 rds.next());....
2180: 09 09 09 09 09 6c 65 74 20 6f 6b 5f 6c 69 6e 6b .....let ok_link
2190: 20 3d 20 72 65 5f 6c 69 6e 6b 2e 69 73 5f 6d 61 = re_link.is_ma
21a0: 74 63 68 28 26 75 72 6c 29 3b 0a 09 09 09 09 09 tch(&url);......
21b0: 09 09 09 6c 65 74 20 6f 6b 5f 68 61 73 68 20 3d ...let ok_hash =
21c0: 20 6d 61 74 63 68 20 69 76 5f 68 61 73 68 20 7b match iv_hash {
21d0: 0a 09 09 09 09 09 09 09 09 09 53 6f 6d 65 28 68 ..........Some(h
21e0: 61 73 68 29 20 3d 3e 20 72 65 5f 69 76 5f 68 61 ash) => re_iv_ha
21f0: 73 68 2e 69 73 5f 6d 61 74 63 68 28 26 68 61 73 sh.is_match(&has
2200: 68 29 2c 0a 09 09 09 09 09 09 09 09 09 4e 6f 6e h),..........Non
2210: 65 20 3d 3e 20 74 72 75 65 2c 0a 09 09 09 09 09 e => true,......
2220: 09 09 09 7d 3b 0a 09 09 09 09 09 09 09 09 69 66 ...};.........if
2230: 20 21 20 6f 6b 5f 6c 69 6e 6b 20 7b 0a 09 09 09 ! ok_link {....
2240: 09 09 09 09 09 09 72 65 70 6c 79 2e 70 75 73 68 ......reply.push
2250: 28 22 4c 69 6e 6b 20 73 68 6f 75 6c 64 20 62 65 ("Link should be
2260: 20 6c 69 6e 6b 20 74 6f 20 61 74 6f 6d 2f 72 73 link to atom/rs
2270: 73 20 66 65 65 64 2c 20 73 6f 6d 65 74 68 69 6e s feed, somethin
2280: 67 20 6c 69 6b 65 20 5c 22 68 74 74 70 73 3a 2f g like \"https:/
2290: 2f 64 6f 6d 61 69 6e 2f 70 61 74 68 5c 22 5c 5c /domain/path\"\\
22a0: 2e 22 2e 74 6f 5f 73 74 72 69 6e 67 28 29 29 3b .".to_string());
22b0: 0a 09 09 09 09 09 09 09 09 09 63 6f 72 65 2e 64 ..........core.d
22c0: 65 62 75 67 28 26 66 6f 72 6d 61 74 21 28 22 55 ebug(&format!("U
22d0: 72 6c 3a 20 7b 3a 3f 7d 22 2c 20 26 75 72 6c 29 rl: {:?}", &url)
22e0: 29 3f 3b 0a 09 09 09 09 09 09 09 09 7d 0a 09 09 )?;.........}...
22f0: 09 09 09 09 09 09 69 66 20 21 20 6f 6b 5f 68 61 ......if ! ok_ha
2300: 73 68 20 7b 0a 09 09 09 09 09 09 09 09 09 72 65 sh {..........re
2310: 70 6c 79 2e 70 75 73 68 28 22 49 56 20 68 61 73 ply.push("IV has
2320: 68 20 73 68 6f 75 6c 64 20 62 65 20 31 34 20 68 h should be 14 h
2330: 65 78 20 64 69 67 69 74 73 2e 22 2e 74 6f 5f 73 ex digits.".to_s
2340: 74 72 69 6e 67 28 29 29 3b 0a 09 09 09 09 09 09 tring());.......
2350: 09 09 09 63 6f 72 65 2e 64 65 62 75 67 28 26 66 ...core.debug(&f
2360: 6f 72 6d 61 74 21 28 22 49 56 3a 20 7b 3a 3f 7d ormat!("IV: {:?}
2370: 22 2c 20 26 69 76 5f 68 61 73 68 29 29 3f 3b 0a ", &iv_hash))?;.
2380: 09 09 09 09 09 09 09 09 7d 0a 09 09 09 09 09 09 ........}.......
2390: 09 09 69 66 20 6f 6b 5f 6c 69 6e 6b 20 26 26 20 ..if ok_link &&
23a0: 6f 6b 5f 68 61 73 68 20 7b 0a 09 09 09 09 09 09 ok_hash {.......
23b0: 09 09 09 6c 65 74 20 63 68 61 6e 3a 20 4f 70 74 ...let chan: Opt
23c0: 69 6f 6e 3c 69 36 34 3e 20 3d 20 6d 61 74 63 68 ion<i64> = match
23d0: 20 73 71 6c 78 3a 3a 71 75 65 72 79 28 22 73 65 sqlx::query("se
23e0: 6c 65 63 74 20 63 68 61 6e 6e 65 6c 5f 69 64 20 lect channel_id
23f0: 66 72 6f 6d 20 72 73 73 74 67 5f 63 68 61 6e 6e from rsstg_chann
2400: 65 6c 20 77 68 65 72 65 20 75 73 65 72 6e 61 6d el where usernam
2410: 65 20 3d 20 24 31 22 29 0a 09 09 09 09 09 09 09 e = $1")........
2420: 09 09 09 2e 62 69 6e 64 28 63 68 61 6e 6e 65 6c ....bind(channel
2430: 29 0a 09 09 09 09 09 09 09 09 09 09 2e 66 65 74 )............fet
2440: 63 68 5f 6f 6e 65 28 26 63 6f 72 65 2e 70 6f 6f ch_one(&core.poo
2450: 6c 29 2e 61 77 61 69 74 20 7b 0a 09 09 09 09 09 l).await {......
2460: 09 09 09 09 09 09 4f 6b 28 63 68 61 6e 29 20 3d ......Ok(chan) =
2470: 3e 20 53 6f 6d 65 28 63 68 61 6e 2e 74 72 79 5f > Some(chan.try_
2480: 67 65 74 28 22 63 68 61 6e 6e 65 6c 5f 69 64 22 get("channel_id"
2490: 29 3f 29 2c 0a 09 09 09 09 09 09 09 09 09 09 09 )?),............
24a0: 45 72 72 28 73 71 6c 78 3a 3a 45 72 72 6f 72 3a Err(sqlx::Error:
24b0: 3a 52 6f 77 4e 6f 74 46 6f 75 6e 64 29 20 3d 3e :RowNotFound) =>
24c0: 20 7b 0a 09 09 09 09 09 09 09 09 09 09 09 09 72 {.............r
24d0: 65 70 6c 79 2e 70 75 73 68 28 22 53 6f 72 72 79 eply.push("Sorry
24e0: 2c 20 49 20 64 6f 6e 27 74 20 6b 6e 6f 77 20 61 , I don't know a
24f0: 62 6f 75 74 20 74 68 61 74 20 63 68 61 6e 6e 65 bout that channe
2500: 6c 2e 20 50 6c 65 61 73 65 2c 20 61 64 64 20 61 l. Please, add a
2510: 20 63 68 61 6e 6e 65 6c 20 77 69 74 68 20 2f 61 channel with /a
2520: 64 64 63 68 61 6e 2e 22 2e 74 6f 5f 73 74 72 69 ddchan.".to_stri
2530: 6e 67 28 29 29 3b 0a 09 09 09 09 09 09 09 09 09 ng());..........
2540: 09 09 09 4e 6f 6e 65 0a 09 09 09 09 09 09 09 09 ...None.........
2550: 09 09 09 7d 2c 0a 09 09 09 09 09 09 09 09 09 09 ...},...........
2560: 09 45 72 72 28 65 72 72 29 20 3d 3e 20 7b 0a 09 .Err(err) => {..
2570: 09 09 09 09 09 09 09 09 09 09 09 72 65 70 6c 79 ...........reply
2580: 2e 70 75 73 68 28 22 53 6f 72 72 79 2c 20 75 6e .push("Sorry, un
2590: 6b 6e 6f 77 6e 20 65 72 72 6f 72 5c 5c 2e 22 2e known error\\.".
25a0: 74 6f 5f 73 74 72 69 6e 67 28 29 29 3b 0a 09 09 to_string());...
25b0: 09 09 09 09 09 09 09 09 09 09 63 6f 72 65 2e 64 ..........core.d
25c0: 65 62 75 67 28 26 66 6f 72 6d 61 74 21 28 22 53 ebug(&format!("S
25d0: 6f 72 72 79 2c 20 75 6e 6b 6e 6f 77 6e 20 65 72 orry, unknown er
25e0: 72 6f 72 3a 20 7b 3a 23 3f 7d 5c 6e 22 2c 20 65 ror: {:#?}\n", e
25f0: 72 72 29 29 3f 3b 0a 09 09 09 09 09 09 09 09 09 rr))?;..........
2600: 09 09 09 4e 6f 6e 65 0a 09 09 09 09 09 09 09 09 ...None.........
2610: 09 09 09 7d 2c 0a 09 09 09 09 09 09 09 09 09 7d ...},..........}
2620: 3b 0a 09 09 09 09 09 09 09 09 09 69 66 20 6c 65 ;..........if le
2630: 74 20 53 6f 6d 65 28 63 68 61 6e 29 20 3d 20 63 t Some(chan) = c
2640: 68 61 6e 20 7b 0a 09 09 09 09 09 09 09 09 09 09 han {...........
2650: 6d 61 74 63 68 20 69 66 20 63 6d 64 20 3d 3d 20 match if cmd ==
2660: 22 2f 75 70 64 61 74 65 22 20 7b 0a 09 09 09 09 "/update" {.....
2670: 09 09 09 09 09 09 09 09 73 71 6c 78 3a 3a 71 75 ........sqlx::qu
2680: 65 72 79 28 22 75 70 64 61 74 65 20 72 73 73 74 ery("update rsst
2690: 67 5f 73 6f 75 72 63 65 20 73 65 74 20 63 68 61 g_source set cha
26a0: 6e 6e 65 6c 5f 69 64 20 3d 20 24 32 2c 20 75 72 nnel_id = $2, ur
26b0: 6c 20 3d 20 24 33 2c 20 69 76 5f 68 61 73 68 20 l = $3, iv_hash
26c0: 3d 20 24 34 2c 20 6f 77 6e 65 72 20 3d 20 24 34 = $4, owner = $4
26d0: 20 77 68 65 72 65 20 73 6f 75 72 63 65 5f 69 64 where source_id
26e0: 20 3d 20 24 31 22 29 2e 62 69 6e 64 28 73 6f 75 = $1").bind(sou
26f0: 72 63 65 5f 69 64 29 0a 09 09 09 09 09 09 09 09 rce_id).........
2700: 09 09 09 7d 20 65 6c 73 65 20 7b 0a 09 09 09 09 ...} else {.....
2710: 09 09 09 09 09 09 09 09 73 71 6c 78 3a 3a 71 75 ........sqlx::qu
2720: 65 72 79 28 22 69 6e 73 65 72 74 20 69 6e 74 6f ery("insert into
2730: 20 72 73 73 74 67 5f 73 6f 75 72 63 65 20 28 63 rsstg_source (c
2740: 68 61 6e 6e 65 6c 5f 69 64 2c 20 75 72 6c 2c 20 hannel_id, url,
2750: 69 76 5f 68 61 73 68 2c 20 6f 77 6e 65 72 29 20 iv_hash, owner)
2760: 76 61 6c 75 65 73 20 28 24 31 2c 20 24 32 2c 20 values ($1, $2,
2770: 24 33 2c 20 24 34 29 22 29 0a 09 09 09 09 09 09 $3, $4)").......
2780: 09 09 09 09 09 7d 0a 09 09 09 09 09 09 09 09 09 .....}..........
2790: 09 09 2e 62 69 6e 64 28 63 68 61 6e 29 0a 09 09 ...bind(chan)...
27a0: 09 09 09 09 09 09 09 09 09 2e 62 69 6e 64 28 75 ..........bind(u
27b0: 72 6c 29 0a 09 09 09 09 09 09 09 09 09 09 09 2e rl).............
27c0: 62 69 6e 64 28 69 76 5f 68 61 73 68 29 0a 09 09 bind(iv_hash)...
27d0: 09 09 09 09 09 09 09 09 09 2e 62 69 6e 64 28 69 ..........bind(i
27e0: 36 34 3a 3a 66 72 6f 6d 28 6d 65 73 73 61 67 65 64::from(message
27f0: 2e 66 72 6f 6d 2e 69 64 29 29 0a 09 09 09 09 09 .from.id))......
2800: 09 09 09 09 09 09 2e 65 78 65 63 75 74 65 28 26 .......execute(&
2810: 63 6f 72 65 2e 70 6f 6f 6c 29 2e 61 77 61 69 74 core.pool).await
2820: 20 7b 0a 09 09 09 09 09 09 09 09 09 09 09 4f 6b {............Ok
2830: 28 5f 29 20 3d 3e 20 72 65 70 6c 79 2e 70 75 73 (_) => reply.pus
2840: 68 28 22 43 68 61 6e 6e 65 6c 20 61 64 64 65 64 h("Channel added
2850: 5c 5c 2e 22 2e 74 6f 5f 73 74 72 69 6e 67 28 29 \\.".to_string()
2860: 29 2c 0a 09 09 09 09 09 09 09 09 09 09 09 45 72 ),............Er
2870: 72 28 73 71 6c 78 3a 3a 45 72 72 6f 72 3a 3a 44 r(sqlx::Error::D
2880: 61 74 61 62 61 73 65 28 65 72 72 29 29 20 3d 3e atabase(err)) =>
2890: 20 7b 0a 09 09 09 09 09 09 09 09 09 09 09 09 6d {.............m
28a0: 61 74 63 68 20 65 72 72 2e 64 6f 77 6e 63 61 73 atch err.downcas
28b0: 74 3a 3a 3c 73 71 6c 78 3a 3a 70 6f 73 74 67 72 t::<sqlx::postgr
28c0: 65 73 3a 3a 50 67 44 61 74 61 62 61 73 65 45 72 es::PgDatabaseEr
28d0: 72 6f 72 3e 28 29 2e 72 6f 75 74 69 6e 65 28 29 ror>().routine()
28e0: 20 7b 0a 09 09 09 09 09 09 09 09 09 09 09 09 09 {..............
28f0: 53 6f 6d 65 28 22 5f 62 74 5f 63 68 65 63 6b 5f Some("_bt_check_
2900: 75 6e 69 71 75 65 22 2c 20 29 20 3d 3e 20 7b 0a unique", ) => {.
2910: 09 09 09 09 09 09 09 09 09 09 09 09 09 09 72 65 ..............re
2920: 70 6c 79 2e 70 75 73 68 28 22 44 75 70 6c 69 63 ply.push("Duplic
2930: 61 74 65 20 6b 65 79 5c 5c 2e 22 2e 74 6f 5f 73 ate key\\.".to_s
2940: 74 72 69 6e 67 28 29 29 3b 0a 09 09 09 09 09 09 tring());.......
2950: 09 09 09 09 09 09 09 7d 2c 0a 09 09 09 09 09 09 .......},.......
2960: 09 09 09 09 09 09 09 53 6f 6d 65 28 5f 29 20 3d .......Some(_) =
2970: 3e 20 7b 0a 09 09 09 09 09 09 09 09 09 09 09 09 > {.............
2980: 09 09 72 65 70 6c 79 2e 70 75 73 68 28 22 44 61 ..reply.push("Da
2990: 74 61 62 61 73 65 20 65 72 72 6f 72 5c 5c 2e 22 tabase error\\."
29a0: 2e 74 6f 5f 73 74 72 69 6e 67 28 29 29 3b 0a 09 .to_string());..
29b0: 09 09 09 09 09 09 09 09 09 09 09 09 7d 2c 0a 09 ............},..
29c0: 09 09 09 09 09 09 09 09 09 09 09 09 4e 6f 6e 65 ............None
29d0: 20 3d 3e 20 7b 0a 09 09 09 09 09 09 09 09 09 09 => {...........
29e0: 09 09 09 09 72 65 70 6c 79 2e 70 75 73 68 28 22 ....reply.push("
29f0: 4e 6f 20 64 61 74 61 62 61 73 65 20 65 72 72 6f No database erro
2a00: 72 20 65 78 74 72 61 63 74 65 64 5c 5c 2e 22 2e r extracted\\.".
2a10: 74 6f 5f 73 74 72 69 6e 67 28 29 29 3b 0a 09 09 to_string());...
2a20: 09 09 09 09 09 09 09 09 09 09 09 7d 2c 0a 09 09 ...........},...
2a30: 09 09 09 09 09 09 09 09 09 09 7d 3b 0a 09 09 09 ..........};....
2a40: 09 09 09 09 09 09 09 09 7d 2c 0a 09 09 09 09 09 ........},......
2a50: 09 09 09 09 09 09 45 72 72 28 65 72 72 29 20 3d ......Err(err) =
2a60: 3e 20 7b 0a 09 09 09 09 09 09 09 09 09 09 09 09 > {.............
2a70: 72 65 70 6c 79 2e 70 75 73 68 28 22 53 6f 72 72 reply.push("Sorr
2a80: 79 2c 20 75 6e 6b 6e 6f 77 6e 20 65 72 72 6f 72 y, unknown error
2a90: 5c 5c 2e 22 2e 74 6f 5f 73 74 72 69 6e 67 28 29 \\.".to_string()
2aa0: 29 3b 0a 09 09 09 09 09 09 09 09 09 09 09 09 63 );.............c
2ab0: 6f 72 65 2e 64 65 62 75 67 28 26 66 6f 72 6d 61 ore.debug(&forma
2ac0: 74 21 28 22 53 6f 72 72 79 2c 20 75 6e 6b 6e 6f t!("Sorry, unkno
2ad0: 77 6e 20 65 72 72 6f 72 3a 20 7b 3a 23 3f 7d 5c wn error: {:#?}\
2ae0: 6e 22 2c 20 65 72 72 29 29 3f 3b 0a 09 09 09 09 n", err))?;.....
2af0: 09 09 09 09 09 09 09 7d 2c 0a 09 09 09 09 09 09 .......},.......
2b00: 09 09 09 09 7d 3b 0a 09 09 09 09 09 09 09 09 09 ....};..........
2b10: 7d 3b 0a 09 09 09 09 09 09 09 09 7d 3b 0a 09 09 };.........};...
2b20: 09 09 09 09 09 7d 2c 0a 0a 2f 2f 20 61 64 64 63 .....},..// addc
2b30: 68 61 6e 0a 0a 09 09 09 09 09 09 09 22 2f 61 64 han........."/ad
2b40: 64 63 68 61 6e 22 20 3d 3e 20 7b 0a 09 09 09 09 dchan" => {.....
2b50: 09 09 09 09 6c 65 74 20 63 68 61 6e 6e 65 6c 20 ....let channel
2b60: 3d 20 77 6f 72 64 73 2e 6e 65 78 74 28 29 2e 75 = words.next().u
2b70: 6e 77 72 61 70 28 29 3b 0a 09 09 09 09 09 09 09 nwrap();........
2b80: 09 69 66 20 21 20 72 65 5f 75 73 65 72 6e 61 6d .if ! re_usernam
2b90: 65 2e 69 73 5f 6d 61 74 63 68 28 26 63 68 61 6e e.is_match(&chan
2ba0: 6e 65 6c 29 20 7b 0a 09 09 09 09 09 09 09 09 09 nel) {..........
2bb0: 72 65 70 6c 79 2e 70 75 73 68 28 22 55 73 65 72 reply.push("User
2bc0: 6e 61 6d 65 73 20 73 68 6f 75 6c 64 20 62 65 20 names should be
2bd0: 73 6f 6d 65 74 68 69 6e 67 20 6c 69 6b 65 20 5c something like \
2be0: 22 40 5c 5c 5b 61 5c 5c 2d 7a 41 5c 5c 2d 5a 5d "@\\[a\\-zA\\-Z]
2bf0: 5c 5c 5b 61 5c 5c 2d 7a 41 5c 5c 2d 5a 30 5c 5c \\[a\\-zA\\-Z0\\
2c00: 2d 39 5c 5c 5f 5d 2b 5c 22 2c 20 61 72 65 6e 27 -9\\_]+\", aren'
2c10: 74 20 74 68 65 79 3f 22 2e 74 6f 5f 73 74 72 69 t they?".to_stri
2c20: 6e 67 28 29 29 3b 0a 09 09 09 09 09 09 09 09 7d ng());.........}
2c30: 20 65 6c 73 65 20 7b 0a 09 09 09 09 09 09 09 09 else {.........
2c40: 09 6c 65 74 20 63 68 61 6e 3a 20 4f 70 74 69 6f .let chan: Optio
2c50: 6e 3c 69 36 34 3e 20 3d 20 6d 61 74 63 68 20 73 n<i64> = match s
2c60: 71 6c 78 3a 3a 71 75 65 72 79 28 22 73 65 6c 65 qlx::query("sele
2c70: 63 74 20 63 68 61 6e 6e 65 6c 5f 69 64 20 66 72 ct channel_id fr
2c80: 6f 6d 20 72 73 73 74 67 5f 63 68 61 6e 6e 65 6c om rsstg_channel
2c90: 20 77 68 65 72 65 20 75 73 65 72 6e 61 6d 65 20 where username
2ca0: 3d 20 24 31 22 29 0a 09 09 09 09 09 09 09 09 09 = $1")..........
2cb0: 09 2e 62 69 6e 64 28 63 68 61 6e 6e 65 6c 29 0a ..bind(channel).
2cc0: 09 09 09 09 09 09 09 09 09 09 2e 66 65 74 63 68 ...........fetch
2cd0: 5f 6f 6e 65 28 26 63 6f 72 65 2e 70 6f 6f 6c 29 _one(&core.pool)
2ce0: 2e 61 77 61 69 74 20 7b 0a 09 09 09 09 09 09 09 .await {........
2cf0: 09 09 09 09 4f 6b 28 63 68 61 6e 29 20 3d 3e 20 ....Ok(chan) =>
2d00: 53 6f 6d 65 28 63 68 61 6e 2e 74 72 79 5f 67 65 Some(chan.try_ge
2d10: 74 28 22 63 68 61 6e 6e 65 6c 5f 69 64 22 29 3f t("channel_id")?
2d20: 29 2c 0a 09 09 09 09 09 09 09 09 09 09 09 45 72 ),............Er
2d30: 72 28 73 71 6c 78 3a 3a 45 72 72 6f 72 3a 3a 52 r(sqlx::Error::R
2d40: 6f 77 4e 6f 74 46 6f 75 6e 64 29 20 3d 3e 20 4e owNotFound) => N
2d50: 6f 6e 65 2c 0a 09 09 09 09 09 09 09 09 09 09 09 one,............
2d60: 45 72 72 28 65 72 72 29 20 3d 3e 20 7b 0a 09 09 Err(err) => {...
2d70: 09 09 09 09 09 09 09 09 09 09 72 65 70 6c 79 2e ..........reply.
2d80: 70 75 73 68 28 22 53 6f 72 72 79 2c 20 75 6e 6b push("Sorry, unk
2d90: 6e 6f 77 6e 20 65 72 72 6f 72 5c 5c 2e 22 2e 74 nown error\\.".t
2da0: 6f 5f 73 74 72 69 6e 67 28 29 29 3b 0a 09 09 09 o_string());....
2db0: 09 09 09 09 09 09 09 09 09 63 6f 72 65 2e 64 65 .........core.de
2dc0: 62 75 67 28 26 66 6f 72 6d 61 74 21 28 22 53 6f bug(&format!("So
2dd0: 72 72 79 2c 20 75 6e 6b 6e 6f 77 6e 20 65 72 72 rry, unknown err
2de0: 6f 72 3a 20 7b 3a 23 3f 7d 5c 6e 22 2c 20 65 72 or: {:#?}\n", er
2df0: 72 29 29 3f 3b 0a 09 09 09 09 09 09 09 09 09 09 r))?;...........
2e00: 09 09 4e 6f 6e 65 0a 09 09 09 09 09 09 09 09 09 ..None..........
2e10: 09 09 7d 2c 0a 09 09 09 09 09 09 09 09 09 7d 3b ..},..........};
2e20: 0a 09 09 09 09 09 09 09 09 09 6d 61 74 63 68 20 ..........match
2e30: 63 68 61 6e 20 7b 0a 09 09 09 09 09 09 09 09 09 chan {..........
2e40: 09 53 6f 6d 65 28 63 68 61 6e 29 20 3d 3e 20 7b .Some(chan) => {
2e50: 0a 09 09 09 09 09 09 09 09 09 09 09 6c 65 74 20 ............let
2e60: 6e 65 77 5f 63 68 61 6e 20 3d 20 63 6f 72 65 2e new_chan = core.
2e70: 74 67 2e 73 65 6e 64 28 74 65 6c 65 67 72 61 6d tg.send(telegram
2e80: 5f 62 6f 74 3a 3a 47 65 74 43 68 61 74 3a 3a 6e _bot::GetChat::n
2e90: 65 77 28 74 65 6c 65 67 72 61 6d 5f 62 6f 74 3a ew(telegram_bot:
2ea0: 3a 74 79 70 65 73 3a 3a 43 68 61 74 49 64 3a 3a :types::ChatId::
2eb0: 6e 65 77 28 63 68 61 6e 29 29 29 2e 61 77 61 69 new(chan))).awai
2ec0: 74 3f 3b 0a 09 09 09 09 09 09 09 09 09 09 09 69 t?;............i
2ed0: 66 20 69 36 34 3a 3a 66 72 6f 6d 28 6e 65 77 5f f i64::from(new_
2ee0: 63 68 61 6e 2e 69 64 28 29 29 20 3d 3d 20 63 68 chan.id()) == ch
2ef0: 61 6e 20 7b 0a 09 09 09 09 09 09 09 09 09 09 09 an {............
2f00: 09 72 65 70 6c 79 2e 70 75 73 68 28 22 49 20 61 .reply.push("I a
2f10: 6c 72 65 61 64 79 20 6b 6e 6f 77 20 74 68 61 74 lready know that
2f20: 20 63 68 61 6e 6e 65 6c 5c 5c 2e 22 2e 74 6f 5f channel\\.".to_
2f30: 73 74 72 69 6e 67 28 29 29 3b 0a 09 09 09 09 09 string());......
2f40: 09 09 09 09 09 09 7d 20 65 6c 73 65 20 7b 0a 09 ......} else {..
2f50: 09 09 09 09 09 09 09 09 09 09 09 72 65 70 6c 79 ...........reply
2f60: 2e 70 75 73 68 28 22 48 6d 6d 2c 20 63 68 61 6e .push("Hmm, chan
2f70: 6e 65 6c 20 68 61 73 20 63 68 61 6e 67 65 64 e2 nel has changed
2f80: 80 a6 20 49 27 6c 6c 20 66 69 78 20 69 74 20 6c I'll fix it l
2f90: 61 74 65 72 5c 5c 2e 22 2e 74 6f 5f 73 74 72 69 ater\\.".to_stri
2fa0: 6e 67 28 29 29 3b 0a 09 09 09 09 09 09 09 09 09 ng());..........
2fb0: 09 09 7d 3b 0a 09 09 09 09 09 09 09 09 09 09 7d ..};...........}
2fc0: 2c 0a 09 09 09 09 09 09 09 09 09 09 4e 6f 6e 65 ,...........None
2fd0: 20 3d 3e 20 7b 0a 09 09 09 09 09 09 09 09 09 09 => {...........
2fe0: 09 6d 61 74 63 68 20 63 6f 72 65 2e 74 67 2e 73 .match core.tg.s
2ff0: 65 6e 64 28 74 65 6c 65 67 72 61 6d 5f 62 6f 74 end(telegram_bot
3000: 3a 3a 47 65 74 43 68 61 74 41 64 6d 69 6e 69 73 ::GetChatAdminis
3010: 74 72 61 74 6f 72 73 3a 3a 6e 65 77 28 74 65 6c trators::new(tel
3020: 65 67 72 61 6d 5f 62 6f 74 3a 3a 74 79 70 65 73 egram_bot::types
3030: 3a 3a 43 68 61 74 52 65 66 3a 3a 43 68 61 6e 6e ::ChatRef::Chann
3040: 65 6c 55 73 65 72 6e 61 6d 65 28 63 68 61 6e 6e elUsername(chann
3050: 65 6c 2e 74 6f 5f 73 74 72 69 6e 67 28 29 29 29 el.to_string()))
3060: 29 2e 61 77 61 69 74 20 7b 0a 09 09 09 09 09 09 ).await {.......
3070: 09 09 09 09 09 09 4f 6b 28 63 68 61 6e 5f 61 64 ......Ok(chan_ad
3080: 6d 29 20 3d 3e 20 7b 0a 09 09 09 09 09 09 09 09 m) => {.........
3090: 09 09 09 09 09 6c 65 74 20 28 6d 75 74 20 6d 65 .....let (mut me
30a0: 2c 20 6d 75 74 20 75 73 65 72 29 20 3d 20 28 66 , mut user) = (f
30b0: 61 6c 73 65 2c 20 66 61 6c 73 65 29 3b 0a 09 09 alse, false);...
30c0: 09 09 09 09 09 09 09 09 09 09 09 66 6f 72 20 61 ...........for a
30d0: 64 6d 69 6e 20 69 6e 20 26 63 68 61 6e 5f 61 64 dmin in &chan_ad
30e0: 6d 20 7b 0a 09 09 09 09 09 09 09 09 09 09 09 09 m {.............
30f0: 09 09 69 66 20 61 64 6d 69 6e 2e 75 73 65 72 2e ..if admin.user.
3100: 69 64 20 3d 3d 20 63 6f 72 65 2e 6d 79 2e 69 64 id == core.my.id
3110: 20 7b 0a 09 09 09 09 09 09 09 09 09 09 09 09 09 {..............
3120: 09 09 6d 65 20 3d 20 74 72 75 65 3b 0a 09 09 09 ..me = true;....
3130: 09 09 09 09 09 09 09 09 09 09 09 7d 3b 0a 09 09 ...........};...
3140: 09 09 09 09 09 09 09 09 09 09 09 09 69 66 20 61 ............if a
3150: 64 6d 69 6e 2e 75 73 65 72 2e 69 64 20 3d 3d 20 dmin.user.id ==
3160: 6d 65 73 73 61 67 65 2e 66 72 6f 6d 2e 69 64 20 message.from.id
3170: 7b 0a 09 09 09 09 09 09 09 09 09 09 09 09 09 09 {...............
3180: 09 75 73 65 72 20 3d 20 74 72 75 65 3b 0a 09 09 .user = true;...
3190: 09 09 09 09 09 09 09 09 09 09 09 09 7d 3b 0a 09 ............};..
31a0: 09 09 09 09 09 09 09 09 09 09 09 09 7d 3b 0a 09 ............};..
31b0: 09 09 09 09 09 09 09 09 09 09 09 09 69 66 20 21 ............if !
31c0: 20 6d 65 20 20 20 7b 20 72 65 70 6c 79 2e 70 75 me { reply.pu
31d0: 73 68 28 22 49 20 6e 65 65 64 20 74 6f 20 62 65 sh("I need to be
31e0: 20 61 64 6d 69 6e 20 6f 6e 20 74 68 61 74 20 63 admin on that c
31f0: 68 61 6e 6e 65 6c 5c 5c 2e 22 2e 74 6f 5f 73 74 hannel\\.".to_st
3200: 72 69 6e 67 28 29 29 3b 20 7d 3b 0a 09 09 09 09 ring()); };.....
3210: 09 09 09 09 09 09 09 09 09 69 66 20 21 20 75 73 .........if ! us
3220: 65 72 20 7b 20 72 65 70 6c 79 2e 70 75 73 68 28 er { reply.push(
3230: 22 59 6f 75 20 73 68 6f 75 6c 64 20 62 65 20 61 "You should be a
3240: 64 6d 69 6e 20 6f 6e 20 74 68 61 74 20 63 68 61 dmin on that cha
3250: 6e 6e 65 6c 5c 5c 2e 22 2e 74 6f 5f 73 74 72 69 nnel\\.".to_stri
3260: 6e 67 28 29 29 3b 20 7d 3b 0a 09 09 09 09 09 09 ng()); };.......
3270: 09 09 09 09 09 09 09 69 66 20 6d 65 20 26 26 20 .......if me &&
3280: 75 73 65 72 20 7b 0a 09 09 09 09 09 09 09 09 09 user {..........
3290: 09 09 09 09 09 6c 65 74 20 63 68 61 6e 5f 69 64 .....let chan_id
32a0: 20 3d 20 63 6f 72 65 2e 74 67 2e 73 65 6e 64 28 = core.tg.send(
32b0: 74 65 6c 65 67 72 61 6d 5f 62 6f 74 3a 3a 47 65 telegram_bot::Ge
32c0: 74 43 68 61 74 3a 3a 6e 65 77 28 74 65 6c 65 67 tChat::new(teleg
32d0: 72 61 6d 5f 62 6f 74 3a 3a 74 79 70 65 73 3a 3a ram_bot::types::
32e0: 43 68 61 74 52 65 66 3a 3a 43 68 61 6e 6e 65 6c ChatRef::Channel
32f0: 55 73 65 72 6e 61 6d 65 28 63 68 61 6e 6e 65 6c Username(channel
3300: 2e 74 6f 5f 73 74 72 69 6e 67 28 29 29 29 29 2e .to_string()))).
3310: 61 77 61 69 74 3f 3b 0a 09 09 09 09 09 09 09 09 await?;.........
3320: 09 09 09 09 09 09 73 71 6c 78 3a 3a 71 75 65 72 ......sqlx::quer
3330: 79 28 22 69 6e 73 65 72 74 20 69 6e 74 6f 20 72 y("insert into r
3340: 73 73 74 67 5f 63 68 61 6e 6e 65 6c 20 28 63 68 sstg_channel (ch
3350: 61 6e 6e 65 6c 5f 69 64 2c 20 75 73 65 72 6e 61 annel_id, userna
3360: 6d 65 29 20 76 61 6c 75 65 73 20 28 24 31 2c 20 me) values ($1,
3370: 24 32 29 3b 22 29 0a 09 09 09 09 09 09 09 09 09 $2);")..........
3380: 09 09 09 09 09 09 2e 62 69 6e 64 28 69 36 34 3a .......bind(i64:
3390: 3a 66 72 6f 6d 28 63 68 61 6e 5f 69 64 2e 69 64 :from(chan_id.id
33a0: 28 29 29 29 0a 09 09 09 09 09 09 09 09 09 09 09 ()))............
33b0: 09 09 09 09 2e 62 69 6e 64 28 63 68 61 6e 6e 65 .....bind(channe
33c0: 6c 29 0a 09 09 09 09 09 09 09 09 09 09 09 09 09 l)..............
33d0: 09 09 2e 65 78 65 63 75 74 65 28 26 63 6f 72 65 ...execute(&core
33e0: 2e 70 6f 6f 6c 29 2e 61 77 61 69 74 3f 3b 0a 09 .pool).await?;..
33f0: 09 09 09 09 09 09 09 09 09 09 09 09 09 72 65 70 .............rep
3400: 6c 79 2e 70 75 73 68 28 22 47 6f 6f 64 2c 20 49 ly.push("Good, I
3410: 20 6b 6e 6f 77 20 74 68 61 74 20 63 68 61 6e 6e know that chann
3420: 65 6c 20 6e 6f 77 5c 5c 2e 5c 6e 22 2e 74 6f 5f el now\\.\n".to_
3430: 73 74 72 69 6e 67 28 29 29 3b 0a 09 09 09 09 09 string());......
3440: 09 09 09 09 09 09 09 09 7d 3b 0a 09 09 09 09 09 ........};......
3450: 09 09 09 09 09 09 09 7d 2c 0a 09 09 09 09 09 09 .......},.......
3460: 09 09 09 09 09 09 45 72 72 28 5f 29 20 3d 3e 20 ......Err(_) =>
3470: 7b 0a 09 09 09 09 09 09 09 09 09 09 09 09 09 72 {..............r
3480: 65 70 6c 79 2e 70 75 73 68 28 22 53 6f 72 72 79 eply.push("Sorry
3490: 2c 20 49 20 68 61 76 65 20 6e 6f 20 61 63 63 65 , I have no acce
34a0: 73 73 20 74 6f 20 74 68 61 74 20 63 68 61 74 5c ss to that chat\
34b0: 5c 2e 22 2e 74 6f 5f 73 74 72 69 6e 67 28 29 29 \.".to_string())
34c0: 3b 0a 09 09 09 09 09 09 09 09 09 09 09 09 7d 2c ;.............},
34d0: 0a 09 09 09 09 09 09 09 09 09 09 09 7d 3b 0a 09 ............};..
34e0: 09 09 09 09 09 09 09 09 09 7d 2c 0a 09 09 09 09 .........},.....
34f0: 09 09 09 09 09 7d 3b 0a 09 09 09 09 09 09 09 09 .....};.........
3500: 7d 3b 0a 09 09 09 09 09 09 09 7d 2c 0a 0a 2f 2f };........},..//
3510: 20 63 68 65 63 6b 0a 0a 09 09 09 09 09 09 09 22 check........."
3520: 2f 63 68 65 63 6b 22 20 3d 3e 20 7b 0a 09 09 09 /check" => {....
3530: 09 09 09 09 09 26 63 6f 72 65 2e 63 68 65 63 6b .....&core.check
3540: 28 26 77 6f 72 64 73 2e 6e 65 78 74 28 29 2e 75 (&words.next().u
3550: 6e 77 72 61 70 28 29 2e 70 61 72 73 65 3a 3a 3c nwrap().parse::<
3560: 69 33 32 3e 28 29 3f 2c 20 4e 6f 6e 65 29 2e 61 i32>()?, None).a
3570: 77 61 69 74 3f 3b 0a 09 09 09 09 09 09 09 7d 2c wait?;........},
3580: 0a 0a 2f 2f 20 63 6c 65 61 72 0a 0a 09 09 09 09 ..// clear......
3590: 09 09 09 22 2f 63 6c 65 61 6e 22 20 3d 3e 20 7b ..."/clean" => {
35a0: 0a 09 09 09 09 09 09 09 09 69 66 20 63 6f 72 65 .........if core
35b0: 2e 6f 77 6e 65 72 20 21 3d 20 69 36 34 3a 3a 66 .owner != i64::f
35c0: 72 6f 6d 28 6d 65 73 73 61 67 65 2e 66 72 6f 6d rom(message.from
35d0: 2e 69 64 29 20 7b 0a 09 09 09 09 09 09 09 09 09 .id) {..........
35e0: 72 65 70 6c 79 2e 70 75 73 68 28 22 52 65 73 65 reply.push("Rese
35f0: 72 76 65 64 20 66 6f 72 20 74 65 73 74 69 6e 67 rved for testing
3600: 5c 5c 2e 22 2e 74 6f 5f 73 74 72 69 6e 67 28 29 \\.".to_string()
3610: 29 3b 0a 09 09 09 09 09 09 09 09 7d 20 65 6c 73 );.........} els
3620: 65 20 7b 0a 09 09 09 09 09 09 09 09 09 6c 65 74 e {..........let
3630: 20 73 6f 75 72 63 65 5f 69 64 20 3d 20 77 6f 72 source_id = wor
3640: 64 73 2e 6e 65 78 74 28 29 2e 75 6e 77 72 61 70 ds.next().unwrap
3650: 28 29 2e 70 61 72 73 65 3a 3a 3c 69 33 32 3e 28 ().parse::<i32>(
3660: 29 2e 75 6e 77 72 61 70 5f 6f 72 28 30 29 3b 0a ).unwrap_or(0);.
3670: 09 09 09 09 09 09 09 09 09 26 63 6f 72 65 2e 63 .........&core.c
3680: 6c 65 61 6e 28 73 6f 75 72 63 65 5f 69 64 29 2e lean(source_id).
3690: 61 77 61 69 74 3f 3b 0a 09 09 09 09 09 09 09 09 await?;.........
36a0: 7d 0a 09 09 09 09 09 09 09 7d 2c 0a 0a 2f 2f 20 }........},..//
36b0: 65 6e 61 62 6c 65 0a 0a 09 09 09 09 09 09 09 22 enable........."
36c0: 2f 65 6e 61 62 6c 65 22 20 3d 3e 20 7b 0a 09 09 /enable" => {...
36d0: 09 09 09 09 09 09 6d 61 74 63 68 20 63 6f 72 65 ......match core
36e0: 2e 65 6e 61 62 6c 65 28 26 77 6f 72 64 73 2e 6e .enable(&words.n
36f0: 65 78 74 28 29 2e 75 6e 77 72 61 70 28 29 2e 70 ext().unwrap().p
3700: 61 72 73 65 3a 3a 3c 69 33 32 3e 28 29 3f 29 2e arse::<i32>()?).
3710: 61 77 61 69 74 20 7b 0a 09 09 09 09 09 09 09 09 await {.........
3720: 09 4f 6b 28 5f 29 20 3d 3e 20 7b 0a 09 09 09 09 .Ok(_) => {.....
3730: 09 09 09 09 09 09 72 65 70 6c 79 2e 70 75 73 68 ......reply.push
3740: 28 22 43 68 61 6e 6e 65 6c 20 65 6e 61 62 6c 65 ("Channel enable
3750: 64 5c 5c 2e 22 2e 74 6f 5f 73 74 72 69 6e 67 28 d\\.".to_string(
3760: 29 29 3b 0a 09 09 09 09 09 09 09 09 09 7d 0a 09 ));..........}..
3770: 09 09 09 09 09 09 09 09 45 72 72 28 65 72 72 29 ........Err(err)
3780: 20 3d 3e 20 7b 0a 09 09 09 09 09 09 09 09 09 09 => {...........
3790: 63 6f 72 65 2e 64 65 62 75 67 28 26 65 72 72 2e core.debug(&err.
37a0: 74 6f 5f 73 74 72 69 6e 67 28 29 29 3f 3b 0a 09 to_string())?;..
37b0: 09 09 09 09 09 09 09 09 7d 2c 0a 09 09 09 09 09 ........},......
37c0: 09 09 09 7d 3b 0a 09 09 09 09 09 09 09 7d 2c 0a ...};........},.
37d0: 0a 2f 2f 20 64 69 73 61 62 6c 65 0a 0a 09 09 09 .// disable.....
37e0: 09 09 09 09 22 2f 64 69 73 61 62 6c 65 22 20 3d ...."/disable" =
37f0: 3e 20 7b 0a 09 09 09 09 09 09 09 09 6d 61 74 63 > {.........matc
3800: 68 20 63 6f 72 65 2e 64 69 73 61 62 6c 65 28 26 h core.disable(&
3810: 77 6f 72 64 73 2e 6e 65 78 74 28 29 2e 75 6e 77 words.next().unw
3820: 72 61 70 28 29 2e 70 61 72 73 65 3a 3a 3c 69 33 rap().parse::<i3
3830: 32 3e 28 29 3f 29 2e 61 77 61 69 74 20 7b 0a 09 2>()?).await {..
3840: 09 09 09 09 09 09 09 09 4f 6b 28 5f 29 20 3d 3e ........Ok(_) =>
3850: 20 7b 0a 09 09 09 09 09 09 09 09 09 09 72 65 70 {...........rep
3860: 6c 79 2e 70 75 73 68 28 22 43 68 61 6e 6e 65 6c ly.push("Channel
3870: 20 64 69 73 61 62 6c 65 64 5c 5c 2e 22 2e 74 6f disabled\\.".to
3880: 5f 73 74 72 69 6e 67 28 29 29 3b 0a 09 09 09 09 _string());.....
3890: 09 09 09 09 09 7d 0a 09 09 09 09 09 09 09 09 09 .....}..........
38a0: 45 72 72 28 65 72 72 29 20 3d 3e 20 7b 0a 09 09 Err(err) => {...
38b0: 09 09 09 09 09 09 09 09 63 6f 72 65 2e 64 65 62 ........core.deb
38c0: 75 67 28 26 65 72 72 2e 74 6f 5f 73 74 72 69 6e ug(&err.to_strin
38d0: 67 28 29 29 3f 3b 0a 09 09 09 09 09 09 09 09 09 g())?;..........
38e0: 7d 2c 0a 09 09 09 09 09 09 09 09 7d 3b 0a 09 09 },.........};...
38f0: 09 09 09 09 09 7d 2c 0a 0a 09 09 09 09 09 09 09 .....},.........
3900: 5f 20 3d 3e 20 7b 0a 09 09 09 09 09 09 09 7d 2c _ => {........},
3910: 0a 09 09 09 09 09 09 7d 3b 0a 09 09 09 09 09 7d .......};......}
3920: 2c 0a 09 09 09 09 09 5f 20 3d 3e 20 7b 0a 09 09 ,......_ => {...
3930: 09 09 09 7d 2c 0a 09 09 09 09 7d 3b 0a 09 09 09 ...},.....};....
3940: 09 69 66 20 72 65 70 6c 79 2e 6c 65 6e 28 29 20 .if reply.len()
3950: 3e 20 30 20 7b 0a 09 09 09 09 09 6d 61 74 63 68 > 0 {......match
3960: 20 63 6f 72 65 2e 74 67 2e 73 65 6e 64 28 6d 65 core.tg.send(me
3970: 73 73 61 67 65 2e 74 65 78 74 5f 72 65 70 6c 79 ssage.text_reply
3980: 28 72 65 70 6c 79 2e 6a 6f 69 6e 28 22 5c 6e 22 (reply.join("\n"
3990: 29 29 2e 70 61 72 73 65 5f 6d 6f 64 65 28 74 79 )).parse_mode(ty
39a0: 70 65 73 3a 3a 50 61 72 73 65 4d 6f 64 65 3a 3a pes::ParseMode::
39b0: 4d 61 72 6b 64 6f 77 6e 56 32 29 29 2e 61 77 61 MarkdownV2)).awa
39c0: 69 74 20 7b 0a 09 09 09 09 09 09 4f 6b 28 5f 29 it {.......Ok(_)
39d0: 20 3d 3e 20 7b 7d 2c 0a 09 09 09 09 09 09 45 72 => {},.......Er
39e0: 72 28 65 72 72 29 20 3d 3e 20 7b 0a 09 09 09 09 r(err) => {.....
39f0: 09 09 09 64 62 67 21 28 72 65 70 6c 79 2e 6a 6f ...dbg!(reply.jo
3a00: 69 6e 28 22 5c 6e 22 29 29 3b 0a 09 09 09 09 09 in("\n"));......
3a10: 09 09 70 72 69 6e 74 6c 6e 21 28 22 7b 7d 22 2c ..println!("{}",
3a20: 20 65 72 72 29 3b 0a 09 09 09 09 09 09 7d 2c 0a err);.......},.
3a30: 09 09 09 09 09 7d 0a 09 09 09 09 7d 0a 09 09 09 .....}.....}....
3a40: 7d 2c 0a 09 09 09 5f 20 3d 3e 20 7b 7d 2c 0a 09 },...._ => {},..
3a50: 09 7d 3b 0a 09 7d 0a 0a 09 4f 6b 28 28 29 29 0a .};..}...Ok(()).
3a60: 7d 0a }.