Hex Artifact Content
Logged in as anonymous

Artifact 11d0fdcfbe7ff82f0bf4f7e8cde82b172a2b26b0c77795d52d02c115ec4b25b8:


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