Check-in [f322efafd9]
Logged in as anonymous
Overview
Comment:0.1.11: optimize out one table, fix /add and /update, add /delete
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: f322efafd9b53ad8541a6d24aae75ccfb79cb457716f8e79ade46f8441b3cebb
User & Date: arcade on 2020-11-30 19:49:57.922
Other Links: manifest | tags
Context
2020-12-07
19:17
0.1.12: add guards around checker, fix fetching next source, on check report errors to owner check-in: 5148f929f3 user: arcade tags: trunk
2020-11-30
19:49
0.1.11: optimize out one table, fix /add and /update, add /delete check-in: f322efafd9 user: arcade tags: trunk
2020-11-29
19:48
added lock, detailed errors check-in: 39ee25f5c3 user: arcade tags: trunk
Changes
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

[[package]]
name = "async-global-executor"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "async-executor 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "async-io 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "futures-lite 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "once_cell 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "async-io"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "concurrent-queue 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "fastrand 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "futures-lite 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "libc 0.2.80 (registry+https://github.com/rust-lang/crates.io-index)",
 "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",







|







|







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

[[package]]
name = "async-global-executor"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "async-executor 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "async-io 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
 "futures-lite 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "once_cell 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "async-io"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "concurrent-queue 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "fastrand 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "futures-lite 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "libc 0.2.80 (registry+https://github.com/rust-lang/crates.io-index)",
 "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146

[[package]]
name = "async-std"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "async-global-executor 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
 "async-io 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "async-mutex 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "blocking 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "crossbeam-utils 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
 "futures-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 "futures-core 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 "futures-io 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 "futures-lite 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "gloo-timers 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 "kv-log-macro 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
 "memchr 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "once_cell 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "pin-project-lite 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
 "pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "wasm-bindgen-futures 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "async-task"
version = "4.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"








|
















|







115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146

[[package]]
name = "async-std"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "async-global-executor 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
 "async-io 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
 "async-mutex 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "blocking 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "crossbeam-utils 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
 "futures-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 "futures-core 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 "futures-io 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 "futures-lite 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "gloo-timers 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 "kv-log-macro 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
 "memchr 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 "num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "once_cell 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "pin-project-lite 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
 "pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "wasm-bindgen-futures 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "async-task"
version = "4.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"

479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "strsim 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "darling_macro"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "darling_core 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "derive_builder"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "darling 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "derive_builder_core 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "derive_builder_core"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "darling 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "digest"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [







|









|











|










|







479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "strsim 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "darling_macro"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "darling_core 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "derive_builder"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "darling 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "derive_builder_core 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "derive_builder_core"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "darling 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "digest"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
[[package]]
name = "failure_derive"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
 "synstructure 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "fastrand"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"







|







575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
[[package]]
name = "failure_derive"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
 "synstructure 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "fastrand"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
name = "futures-macro"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro-hack 0.5.19 (registry+https://github.com/rust-lang/crates.io-index)",
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "futures-sink"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"








|







728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
name = "futures-macro"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro-hack 0.5.19 (registry+https://github.com/rust-lang/crates.io-index)",
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "futures-sink"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"

804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
[[package]]
name = "gloo-timers"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "futures-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 "futures-core 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 "js-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
 "wasm-bindgen 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
 "web-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "h2"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [







|
|
|







804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
[[package]]
name = "gloo-timers"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "futures-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 "futures-core 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 "js-sys 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
 "wasm-bindgen 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
 "web-sys 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "h2"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
[[package]]
name = "itoa"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "js-sys"
version = "0.3.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "wasm-bindgen 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [







|


|







1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
[[package]]
name = "itoa"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "js-sys"
version = "0.3.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "wasm-bindgen 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
[[package]]
name = "pin-project-internal"
version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "pin-project-internal"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "pin-project-lite"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"








|









|







1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
[[package]]
name = "pin-project-internal"
version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "pin-project-internal"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "pin-project-lite"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"

1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
 "derive_builder 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "quick-xml 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "rsstg"
version = "0.1.9"
dependencies = [
 "anyhow 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
 "chrono 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
 "config 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
 "futures 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 "futures-util 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",







|







1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
 "derive_builder 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "quick-xml 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "rsstg"
version = "0.1.11"
dependencies = [
 "anyhow 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
 "chrono 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
 "config 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
 "futures 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 "futures-util 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
[[package]]
name = "serde_derive"
version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "serde_json"
version = "1.0.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [







|







1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
[[package]]
name = "serde_derive"
version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "serde_json"
version = "1.0.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
 "futures 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "sha2 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "sqlx-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "sqlx-rt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
 "url 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "sqlx-rt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"







|







2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
 "futures 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "sha2 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
 "sqlx-core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "sqlx-rt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
 "url 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "sqlx-rt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
[[package]]
name = "subtle"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "syn"
version = "1.0.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "synstructure"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
 "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "tap"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"







|














|







2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
[[package]]
name = "subtle"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "syn"
version = "1.0.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "synstructure"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
 "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "tap"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
[[package]]
name = "thiserror-impl"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "thread_local"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [







|







2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
[[package]]
name = "thiserror-impl"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "thread_local"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
[[package]]
name = "tokio-macros"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "tokio-reactor"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [







|







2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
[[package]]
name = "tokio-macros"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "tokio-reactor"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
[[package]]
name = "tracing-attributes"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "tracing-core"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [







|







2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
[[package]]
name = "tracing-attributes"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "tracing-core"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "wasm-bindgen"
version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
 "wasm-bindgen-macro 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "wasm-bindgen-backend"
version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "bumpalo 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
 "wasm-bindgen-shared 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "wasm-bindgen-futures"
version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
 "js-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
 "wasm-bindgen 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
 "web-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "wasm-bindgen-macro"
version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "wasm-bindgen-macro-support 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)",
 "wasm-bindgen-backend 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
 "wasm-bindgen-shared 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "wasm-bindgen-shared"
version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "web-sys"
version = "0.3.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "js-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
 "wasm-bindgen 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "wepoll-sys"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [







|


|
|




|







|
|




|


|
|
|
|




|



|




|




|
|
|




|




|


|
|







2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "wasm-bindgen"
version = "0.2.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "wasm-bindgen-macro 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "wasm-bindgen-backend"
version = "0.2.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "bumpalo 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
 "wasm-bindgen-shared 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "wasm-bindgen-futures"
version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 "js-sys 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
 "wasm-bindgen 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
 "web-sys 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "wasm-bindgen-macro"
version = "0.2.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "wasm-bindgen-macro-support 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "proc-macro2 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 "syn 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
 "wasm-bindgen-backend 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
 "wasm-bindgen-shared 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "wasm-bindgen-shared"
version = "0.2.69"
source = "registry+https://github.com/rust-lang/crates.io-index"

[[package]]
name = "web-sys"
version = "0.3.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
 "js-sys 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
 "wasm-bindgen 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
name = "wepoll-sys"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
"checksum ahash 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4243ec6feddc812c0f442d9765374d250aba94e10ecf8b632e1b1c118547e8"
"checksum aho-corasick 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
"checksum anyhow 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)" = "bf8dcb5b4bbaa28653b647d8c77bd4ed40183b48882e130c1f1ffb73de069fd7"
"checksum arrayvec 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
"checksum async-channel 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "59740d83946db6a5af71ae25ddf9562c2b176b2ca42cf99a455f09f4a220d6b9"
"checksum async-executor 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eb877970c7b440ead138f6321a3b5395d6061183af779340b65e20c0fede9146"
"checksum async-global-executor 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "73079b49cd26b8fd5a15f68fc7707fc78698dc2a3d61430f2a7a9430230dfa04"
"checksum async-io 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "458c8f66c246624e7cf87c01451f3392ab77d66a0f105a49d9353b30ea97ced8"
"checksum async-mutex 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e"
"checksum async-native-tls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9e9e7a929bd34c68a82d58a4de7f86fffdaf97fb2af850162a7bb19dd7269b33"
"checksum async-std 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a7e82538bc65a25dbdff70e4c5439d52f068048ab97cdea0acd73f131594caa1"
"checksum async-task 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0"
"checksum atoi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5c897df197d57c25b37df9d8fa2f93ddbfeee9ebd2264350ac79c8ec4b795885"
"checksum atomic-waker 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a"
"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"







|







2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
"checksum ahash 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4243ec6feddc812c0f442d9765374d250aba94e10ecf8b632e1b1c118547e8"
"checksum aho-corasick 0.7.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
"checksum anyhow 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)" = "bf8dcb5b4bbaa28653b647d8c77bd4ed40183b48882e130c1f1ffb73de069fd7"
"checksum arrayvec 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
"checksum async-channel 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "59740d83946db6a5af71ae25ddf9562c2b176b2ca42cf99a455f09f4a220d6b9"
"checksum async-executor 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eb877970c7b440ead138f6321a3b5395d6061183af779340b65e20c0fede9146"
"checksum async-global-executor 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "73079b49cd26b8fd5a15f68fc7707fc78698dc2a3d61430f2a7a9430230dfa04"
"checksum async-io 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9315f8f07556761c3e48fec2e6b276004acf426e6dc068b2c2251854d65ee0fd"
"checksum async-mutex 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e"
"checksum async-native-tls 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9e9e7a929bd34c68a82d58a4de7f86fffdaf97fb2af850162a7bb19dd7269b33"
"checksum async-std 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a7e82538bc65a25dbdff70e4c5439d52f068048ab97cdea0acd73f131594caa1"
"checksum async-task 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0"
"checksum atoi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5c897df197d57c25b37df9d8fa2f93ddbfeee9ebd2264350ac79c8ec4b795885"
"checksum atomic-waker 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a"
"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
"checksum ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
"checksum indexmap 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2"
"checksum instant 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
"checksum itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
"checksum js-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)" = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum kv-log-macro 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum lexical-core 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616"
"checksum libc 0.2.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
"checksum linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d262045c5b87c0861b3f004610afd0e2c851e2908d08b6c870cbb9d5f494ecd"
"checksum linked-hash-map 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"







|







2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
"checksum ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
"checksum indexmap 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2"
"checksum instant 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
"checksum itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
"checksum js-sys 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d7383929f7c9c7c2d0fa596f325832df98c3704f2c60553080f7127a58175"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum kv-log-macro 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum lexical-core 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616"
"checksum libc 0.2.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
"checksum linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d262045c5b87c0861b3f004610afd0e2c851e2908d08b6c870cbb9d5f494ecd"
"checksum linked-hash-map 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
"checksum sqlx-macros 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7acd32cba35531345f8a94a038874baf00efd0b701c913f5b00d2870b474b64"
"checksum sqlx-rt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63fc5454c9dd7aaea3a0eeeb65ca40d06d0d8e7413a8184f7c3a3ffa5056190b"
"checksum static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
"checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d"
"checksum stringprep 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1"
"checksum strsim 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
"checksum subtle 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "343f3f510c2915908f155e94f17220b19ccfacf2a64a2a5d8004f2c3e311e7fd"
"checksum syn 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)" = "6c1e438504729046a5cfae47f97c30d6d083c7d91d94603efdae3477fc070d4c"
"checksum synstructure 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
"checksum tap 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "36474e732d1affd3a6ed582781b3683df3d0563714c59c39591e8ff707cf078e"
"checksum telegram-bot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc9552e972bcb551705fcad45bd0b86eca12a22379db36cdfa6d053e1a19b2de"
"checksum telegram-bot-raw 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e4fc120e2b85d639fc932a4aa7c1b6a5f1189fb86948d7a02037d1d8f1ef559"
"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
"checksum thiserror 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9ae34b84616eedaaf1e9dd6026dbe00dcafa92aa0c8077cb69df1fcfe5e53e"
"checksum thiserror-impl 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56"







|







3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
"checksum sqlx-macros 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7acd32cba35531345f8a94a038874baf00efd0b701c913f5b00d2870b474b64"
"checksum sqlx-rt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63fc5454c9dd7aaea3a0eeeb65ca40d06d0d8e7413a8184f7c3a3ffa5056190b"
"checksum static_assertions 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
"checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d"
"checksum stringprep 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1"
"checksum strsim 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
"checksum subtle 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "343f3f510c2915908f155e94f17220b19ccfacf2a64a2a5d8004f2c3e311e7fd"
"checksum syn 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)" = "8833e20724c24de12bbaba5ad230ea61c3eafb05b881c7c9d3cfe8638b187e68"
"checksum synstructure 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
"checksum tap 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "36474e732d1affd3a6ed582781b3683df3d0563714c59c39591e8ff707cf078e"
"checksum telegram-bot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc9552e972bcb551705fcad45bd0b86eca12a22379db36cdfa6d053e1a19b2de"
"checksum telegram-bot-raw 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0e4fc120e2b85d639fc932a4aa7c1b6a5f1189fb86948d7a02037d1d8f1ef559"
"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
"checksum thiserror 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9ae34b84616eedaaf1e9dd6026dbe00dcafa92aa0c8077cb69df1fcfe5e53e"
"checksum thiserror-impl 1.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56"
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
"checksum version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
"checksum waker-fn 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
"checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230"
"checksum want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
"checksum wasi 0.10.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
"checksum wasm-bindgen 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42"
"checksum wasm-bindgen-backend 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68"
"checksum wasm-bindgen-futures 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)" = "b7866cab0aa01de1edf8b5d7936938a7e397ee50ce24119aef3e1eaa3b6171da"
"checksum wasm-bindgen-macro 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038"
"checksum wasm-bindgen-macro-support 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe"
"checksum wasm-bindgen-shared 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307"
"checksum web-sys 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf6ef87ad7ae8008e15a355ce696bed26012b7caa21605188cfd8214ab51e2d"
"checksum wepoll-sys 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0fcb14dea929042224824779fbc82d9fab8d2e6d3cbc0ac404de8edf489e77ff"
"checksum whoami 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7884773ab69074615cb8f8425d0e53f11710786158704fca70f53e71b0e05504"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9"
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
"checksum wyz 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
"checksum yaml-rust 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d"







|
|
|
|
|
|
|











3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
"checksum version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
"checksum waker-fn 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
"checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230"
"checksum want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
"checksum wasi 0.10.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
"checksum wasm-bindgen 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)" = "3cd364751395ca0f68cafb17666eee36b63077fb5ecd972bbcd74c90c4bf736e"
"checksum wasm-bindgen-backend 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)" = "1114f89ab1f4106e5b55e688b828c0ab0ea593a1ea7c094b141b14cbaaec2d62"
"checksum wasm-bindgen-futures 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "1fe9756085a84584ee9457a002b7cdfe0bfff169f45d2591d8be1345a6780e35"
"checksum wasm-bindgen-macro 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6ac8995ead1f084a8dea1e65f194d0973800c7f571f6edd70adf06ecf77084"
"checksum wasm-bindgen-macro-support 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)" = "b5a48c72f299d80557c7c62e37e7225369ecc0c963964059509fbafe917c7549"
"checksum wasm-bindgen-shared 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)" = "7e7811dd7f9398f14cc76efd356f98f03aa30419dea46aa810d71e819fc97158"
"checksum web-sys 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)" = "222b1ef9334f92a21d3fb53dc3fd80f30836959a90f9274a626d7e06315ba3c3"
"checksum wepoll-sys 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0fcb14dea929042224824779fbc82d9fab8d2e6d3cbc0ac404de8edf489e77ff"
"checksum whoami 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7884773ab69074615cb8f8425d0e53f11710786158704fca70f53e71b0e05504"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9"
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
"checksum wyz 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
"checksum yaml-rust 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d"
1
2
3
4
5
6
7
8
9
10
[package]
name = "rsstg"
version = "0.1.10"
authors = ["arcade"]
edition = "2018"

[dependencies]
chrono = "*"
config = "*"
futures = "*"


|







1
2
3
4
5
6
7
8
9
10
[package]
name = "rsstg"
version = "0.1.11"
authors = ["arcade"]
edition = "2018"

[dependencies]
chrono = "*"
config = "*"
futures = "*"
Modified rsstg.sql from [7684f91d94] to [eaca20cec6].
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
create table rsstg_updates (owner integer, update jsonb);

create unique index rsstg_updates__id on rsstg_updates(update->>'update_id');

-- create table rsstg_users (id integer);
create table rsstg_channel (
	channel_id bigint primary key,
	username text not null);
create unique index rsstg_channel__username on rsstg_channel(username);

create table rsstg_source (
	source_id serial,

	channel_id integer not null,
	url text not null,
	last_scrape not null timestamptz default now(),
	enabled boolean not null default false,
	iv_hash text,
	owner bigint not null);
create unique index rsstg_source__source_id on rsstg_source(source_id);
create unique index rsstg_source__channel_id__owner on rsstg_source(channel_id, owner);
create index rsstg_source__owner on rsstg_source(owner);

create table rsstg_post (
	source_id integer not null,
	date int not null,
	url text not null,
	hour smallint not null generated always as (extract('hour' from  posted)) stored,
	FOREIGN KEY (source_id) REFERENCES rsstg_source(source_id)
);
create unique index rsstg_post__url on rsstg_post(url);
create index rsstg_post__hour on rsstg_post(hour);
create index rsstg_post__posted_hour on rsstg_post(posted,hour);

create or replace view rsstg_order as
	select source_id, coalesce(last_scrape + make_interval(0,0,0,0,0,(60 / (coalesce(activity, 1)/7 + 1) )::integer), now() - interval '1 minute') as next_fetch, owner




<
<
<
<
<
<


>















|







1
2
3
4






5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
create table rsstg_updates (owner integer, update jsonb);

create unique index rsstg_updates__id on rsstg_updates(update->>'update_id');







create table rsstg_source (
	source_id serial,
	channel text not null,
	channel_id integer not null,
	url text not null,
	last_scrape not null timestamptz default now(),
	enabled boolean not null default false,
	iv_hash text,
	owner bigint not null);
create unique index rsstg_source__source_id on rsstg_source(source_id);
create unique index rsstg_source__channel_id__owner on rsstg_source(channel_id, owner);
create index rsstg_source__owner on rsstg_source(owner);

create table rsstg_post (
	source_id integer not null,
	date int not null,
	url text not null,
	hour smallint not null generated always as (extract('hour' from  posted)) stored,
	FOREIGN KEY (source_id) REFERENCES rsstg_source(source_id) on delete cascade,
);
create unique index rsstg_post__url on rsstg_post(url);
create index rsstg_post__hour on rsstg_post(hour);
create index rsstg_post__posted_hour on rsstg_post(posted,hour);

create or replace view rsstg_order as
	select source_id, coalesce(last_scrape + make_interval(0,0,0,0,0,(60 / (coalesce(activity, 1)/7 + 1) )::integer), now() - interval '1 minute') as next_fetch, owner
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
use sqlx::postgres::PgPoolOptions;
use sqlx::Row;
use sqlx::Done; // .rows_affected()

#[macro_use]
extern crate lazy_static;

use anyhow::{anyhow, Context, Result};

#[derive(Clone)]
struct Core {
	owner: i64,
	api_key: String,
	owner_chat: UserId,
	tg: telegram_bot::Api,







|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
use sqlx::postgres::PgPoolOptions;
use sqlx::Row;
use sqlx::Done; // .rows_affected()

#[macro_use]
extern crate lazy_static;

use anyhow::{anyhow, bail, Context, Result};

#[derive(Clone)]
struct Core {
	owner: i64,
	api_key: String,
	owner_chat: UserId,
	tg: telegram_bot::Api,
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
















140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

















166
167
168
169
170
171
172
173
174
175
176
177
178









179
180


181
182
183



184


185
186
187









188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228

229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
				.connect_timeout(std::time::Duration::new(300, 0))
				.idle_timeout(std::time::Duration::new(60, 0))
				.connect_lazy(&settings.get_str("pg")?)?,
		};
		let clone = core.clone();
		tokio::spawn(async move {
			if let Err(err) = &clone.autofetch().await {
				if let Err(err) = clone.debug(&format!("{:?}", err)) {
					eprintln!("Autofetch error: {}", err);
				};
			}
		});
		Ok(core)
	}

	fn stream(&self) -> telegram_bot::UpdatesStream {
		self.tg.stream()
	}

	fn debug(&self, msg: &str) -> Result<()> {
		self.tg.spawn(SendMessage::new(self.owner_chat, msg));
		Ok(())
	}

	async fn check<S>(&self, id: &i32, owner: S, real: bool) -> Result<()>
	where S: Into<i64> {
		let owner: i64 = owner.into();
		let mut conn = self.pool.acquire().await
			.with_context(|| format!("🛑 Query queue fetch conn:\n{:?}", &self.pool))?;
		let row = sqlx::query("select source_id, channel_id, url, iv_hash, owner from rsstg_source where source_id = $1 and owner = $2")
			.bind(id)
			.bind(owner)
			.fetch_one(&mut conn).await
			.with_context(|| format!("🛑 Query source:\n{:?}", &self.pool))?;
		drop(conn);
		let channel_id: i64 = row.try_get("channel_id")?;
		let destination = match real {
			true => UserId::new(channel_id),
			false => UserId::new(row.try_get("owner")?),
		};
		let url: &str = row.try_get("url")?;
		let mut this_fetch: Option<DateTime<chrono::FixedOffset>> = None;
		let iv_hash: Option<&str> = row.try_get("iv_hash")?;
		let mut posts: BTreeMap<DateTime<chrono::FixedOffset>, String> = BTreeMap::new();
		let feed = rss::Channel::from_url(url)
			.with_context(|| format!("🛑 Problem opening feed url:\n{}", &url))?;
		for item in feed.items() {
			let date = match item.pub_date() {
				Some(feed_date) => DateTime::parse_from_rfc2822(feed_date),
				None => DateTime::parse_from_rfc3339(&item.dublin_core_ext().unwrap().dates()[0]),
			}?;
			let url = item.link().unwrap().to_string();
			posts.insert(date.clone(), url.clone());
		};
		for (date, url) in posts.iter() {
			let mut conn = self.pool.acquire().await
				.with_context(|| format!("🛑 Check post fetch conn:\n{:?}", &self.pool))?;
			let row = sqlx::query("select exists(select true from rsstg_post where url = $1 and source_id = $2) as exists;")
				.bind(&url)
				.bind(id)
				.fetch_one(&mut conn).await
				.with_context(|| format!("🛑 Check post:\n{:?}", &conn))?;
			let exists: bool = row.try_get("exists")?;
			if ! exists {
				if this_fetch == None || *date > this_fetch.unwrap() {
					this_fetch = Some(*date);
				};
				self.tg.send( match iv_hash {
						Some(x) => SendMessage::new(destination, format!("<a href=\"https://t.me/iv?url={}&rhash={}\"> </a>{0}", url, x)),
						None => SendMessage::new(destination, format!("{}", url)),
					}.parse_mode(types::ParseMode::Html)).await
					.context("🛑 Can't post message:")?;
				sqlx::query("insert into rsstg_post (source_id, posted, url) values ($1, $2, $3);")
					.bind(id)
					.bind(date)
					.bind(url)
					.execute(&mut conn).await
					.with_context(|| format!("🛑Record post:\n{:?}", &conn))?;
				drop(conn);
				tokio::time::delay_for(std::time::Duration::new(4, 0)).await;
			};
		};
		posts.clear();
		let mut conn = self.pool.acquire().await
			.with_context(|| format!("🛑 Update scrape fetch conn:\n{:?}", &self.pool))?;
		sqlx::query("update rsstg_source set last_scrape = now() where source_id = $1;")
			.bind(id)
			.execute(&mut conn).await
			.with_context(|| format!("🛑 Update scrape:\n{:?}", &conn))?;
		Ok(())
	}

















	async fn clean<S>(&self, source_id: &i32, id: S) -> Result<String>
	where S: Into<i64> {
		let id: i64 = id.into();
		let mut conn = self.pool.acquire().await
			.with_context(|| format!("🛑 Clean fetch conn:\n{:?}", &self.pool))?;
		match sqlx::query("delete from rsstg_post p using rsstg_source s where p.source_id = $1 and owner = $2 and p.source_id = s.source_id;")
			.bind(source_id)
			.bind(id)
			.execute(&mut conn).await
			.with_context(|| format!("🛑 Clean seen posts:\n{:?}", &self.pool))?
			.rows_affected() {
			0 => { Ok("No data found found\\.".to_string()) },
			x => { Ok(format!("{} posts purged\\.", x)) },
		}
	}

	async fn enable<S>(&self, source_id: &i32, id: S) -> Result<&str>
	where S: Into<i64> {
		let id: i64 = id.into();
		let mut conn = self.pool.acquire().await
			.with_context(|| format!("🛑 Enable fetch conn:\n{:?}", &self.pool))?;
		match sqlx::query("update rsstg_source set enabled = true where source_id = $1 and owner = $2")
			.bind(source_id)
			.bind(id)
			.execute(&mut conn).await
			.with_context(|| format!("🛑 Enable source:\n{:?}", &self.pool))?

















			.rows_affected() {
			1 => { Ok("Source disabled\\.") },
			0 => { Ok("Source not found\\.") },
			_ => { Err(anyhow!("Database error.")) },
		}
	}

	async fn disable<S>(&self, source_id: &i32, id: S) -> Result<&str>
	where S: Into<i64> {
		let id: i64 = id.into();
		let mut conn = self.pool.acquire().await
			.with_context(|| format!("🛑 Disable fetch conn:\n{:?}", &self.pool))?;
		match sqlx::query("update rsstg_source set enabled = false where source_id = $1 and owner = $2")









			.bind(source_id)
			.bind(id)


			.execute(&mut conn).await
			.with_context(|| format!("🛑 Disable source:\n{:?}", &self.pool))?
			.rows_affected() {



			1 => { Ok("Source disabled\\.") },


			0 => { Ok("Source not found\\.") },
			_ => { Err(anyhow!("Database error.")) },
		}









	}

	async fn autofetch(&self) -> Result<()> {
		let mut delay = chrono::Duration::minutes(5);
		let mut now;
		loop {
			let mut conn = self.pool.acquire().await
				.with_context(|| format!("🛑 Autofetch fetch conn:\n{:?}", &self.pool))?;
			now = chrono::Local::now();
			let mut queue = sqlx::query("select source_id, next_fetch, owner from rsstg_order natural left join rsstg_source natural left join rsstg_channel where next_fetch < now();")
				.fetch_all(&mut conn).await?;
			for row in queue.iter() {
				let source_id: i32 = row.try_get("source_id")?;
				let owner: i64 = row.try_get("owner")?;
				let next_fetch: DateTime<chrono::Local> = row.try_get("next_fetch")?;
				if next_fetch < now {
					sqlx::query("update rsstg_source set last_scrape = now() + interval '1 hour' where source_id = $1;")
						.bind(source_id)
						.execute(&mut conn).await
						.with_context(|| format!("🛑 Lock source:\n\n{:?}", &self.pool))?;
					let clone = self.clone();
					tokio::spawn(async move {
						if let Err(err) = clone.check(&source_id, owner, true).await {
							if let Err(err) = clone.debug(&format!("{:?}", err)) {
								eprintln!("Check error: {}", err);
							};
						};
					});
				} else {
					if next_fetch - now < delay {
						delay = next_fetch - now;
					}
				}
			};
			queue.clear();
			tokio::time::delay_for(delay.to_std()?).await;
			delay = chrono::Duration::minutes(5);
		}
	}

	async fn list(&self, id: telegram_bot::UserId) -> Result<Vec<String>> {

		let id = i64::from(id);
		let mut reply = vec![];
		let mut conn = self.pool.acquire().await
			.with_context(|| format!("🛑 List fetch conn:\n{:?}", &self.pool))?;
		reply.push("Channels:".to_string());
		let rows = sqlx::query("select source_id, username, enabled, url, iv_hash from rsstg_source left join rsstg_channel using (channel_id) where owner = $1 order by source_id")
			.bind(id)
			.fetch_all(&mut conn).await?;
		for row in rows.iter() {
			let source_id: i32 = row.try_get("source_id")?;
			let username: &str = row.try_get("username")?;
			let enabled: bool = row.try_get("enabled")?;
			let url: &str = row.try_get("url")?;
			let iv_hash: Option<&str> = row.try_get("iv_hash")?;
			reply.push(format!("\n\\#️⃣ {} \\*️⃣ `{}` {}\n🔗 `{}`", source_id, username,  
				match enabled {
					true  => "🔄 enabled",
					false => "⛔ disabled",







|




















|




|











|










|




|









|





|






|



|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

|

|


|

|






|

|

|


|

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







|

|

|
|
>
>
>
>
>
>
>
>
>
|
|
>
>
|
<
<
>
>
>
|
>
>
|
|
|
>
>
>
>
>
>
>
>
>







|

|









|



|
















|
>
|


|

|
|



|







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225


226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
				.connect_timeout(std::time::Duration::new(300, 0))
				.idle_timeout(std::time::Duration::new(60, 0))
				.connect_lazy(&settings.get_str("pg")?)?,
		};
		let clone = core.clone();
		tokio::spawn(async move {
			if let Err(err) = &clone.autofetch().await {
				if let Err(err) = clone.debug(&format!("🛑 {:?}", err)) {
					eprintln!("Autofetch error: {}", err);
				};
			}
		});
		Ok(core)
	}

	fn stream(&self) -> telegram_bot::UpdatesStream {
		self.tg.stream()
	}

	fn debug(&self, msg: &str) -> Result<()> {
		self.tg.spawn(SendMessage::new(self.owner_chat, msg));
		Ok(())
	}

	async fn check<S>(&self, id: &i32, owner: S, real: bool) -> Result<()>
	where S: Into<i64> {
		let owner: i64 = owner.into();
		let mut conn = self.pool.acquire().await
			.with_context(|| format!("Query queue fetch conn:\n{:?}", &self.pool))?;
		let row = sqlx::query("select source_id, channel_id, url, iv_hash, owner from rsstg_source where source_id = $1 and owner = $2")
			.bind(id)
			.bind(owner)
			.fetch_one(&mut conn).await
			.with_context(|| format!("Query source:\n{:?}", &self.pool))?;
		drop(conn);
		let channel_id: i64 = row.try_get("channel_id")?;
		let destination = match real {
			true => UserId::new(channel_id),
			false => UserId::new(row.try_get("owner")?),
		};
		let url: &str = row.try_get("url")?;
		let mut this_fetch: Option<DateTime<chrono::FixedOffset>> = None;
		let iv_hash: Option<&str> = row.try_get("iv_hash")?;
		let mut posts: BTreeMap<DateTime<chrono::FixedOffset>, String> = BTreeMap::new();
		let feed = rss::Channel::from_url(url)
			.with_context(|| format!("Problem opening feed url:\n{}", &url))?;
		for item in feed.items() {
			let date = match item.pub_date() {
				Some(feed_date) => DateTime::parse_from_rfc2822(feed_date),
				None => DateTime::parse_from_rfc3339(&item.dublin_core_ext().unwrap().dates()[0]),
			}?;
			let url = item.link().unwrap().to_string();
			posts.insert(date.clone(), url.clone());
		};
		for (date, url) in posts.iter() {
			let mut conn = self.pool.acquire().await
				.with_context(|| format!("Check post fetch conn:\n{:?}", &self.pool))?;
			let row = sqlx::query("select exists(select true from rsstg_post where url = $1 and source_id = $2) as exists;")
				.bind(&url)
				.bind(id)
				.fetch_one(&mut conn).await
				.with_context(|| format!("Check post:\n{:?}", &conn))?;
			let exists: bool = row.try_get("exists")?;
			if ! exists {
				if this_fetch == None || *date > this_fetch.unwrap() {
					this_fetch = Some(*date);
				};
				self.tg.send( match iv_hash {
						Some(x) => SendMessage::new(destination, format!("<a href=\"https://t.me/iv?url={}&rhash={}\"> </a>{0}", url, x)),
						None => SendMessage::new(destination, format!("{}", url)),
					}.parse_mode(types::ParseMode::Html)).await
					.context("Can't post message:")?;
				sqlx::query("insert into rsstg_post (source_id, posted, url) values ($1, $2, $3);")
					.bind(id)
					.bind(date)
					.bind(url)
					.execute(&mut conn).await
					.with_context(|| format!("Record post:\n{:?}", &conn))?;
				drop(conn);
				tokio::time::delay_for(std::time::Duration::new(4, 0)).await;
			};
		};
		posts.clear();
		let mut conn = self.pool.acquire().await
			.with_context(|| format!("Update scrape fetch conn:\n{:?}", &self.pool))?;
		sqlx::query("update rsstg_source set last_scrape = now() where source_id = $1;")
			.bind(id)
			.execute(&mut conn).await
			.with_context(|| format!("Update scrape:\n{:?}", &conn))?;
		Ok(())
	}

	async fn delete<S>(&self, source_id: &i32, owner: S) -> Result<String>
	where S: Into<i64> {
		let owner: i64 = owner.into();
		let mut conn = self.pool.acquire().await
			.with_context(|| format!("Delete fetch conn:\n{:?}", &self.pool))?;
		match sqlx::query("delete from rsstg_source where source_id = $1 and owner = $2;")
			.bind(source_id)
			.bind(owner)
			.execute(&mut conn).await
			.with_context(|| format!("Delete source rule:\n{:?}", &self.pool))?
			.rows_affected() {
			0 => { Ok("No data found found\\.".to_string()) },
			x => { Ok(format!("{} sources removed\\.", x)) },
		}
	}

	async fn clean<S>(&self, source_id: &i32, owner: S) -> Result<String>
	where S: Into<i64> {
		let owner: i64 = owner.into();
		let mut conn = self.pool.acquire().await
			.with_context(|| format!("Clean fetch conn:\n{:?}", &self.pool))?;
		match sqlx::query("delete from rsstg_post p using rsstg_source s where p.source_id = $1 and owner = $2 and p.source_id = s.source_id;")
			.bind(source_id)
			.bind(owner)
			.execute(&mut conn).await
			.with_context(|| format!("Clean seen posts:\n{:?}", &self.pool))?
			.rows_affected() {
			0 => { Ok("No data found found\\.".to_string()) },
			x => { Ok(format!("{} posts purged\\.", x)) },
		}
	}

	async fn enable<S>(&self, source_id: &i32, owner: S) -> Result<&str>
	where S: Into<i64> {
		let owner: i64 = owner.into();
		let mut conn = self.pool.acquire().await
			.with_context(|| format!("Enable fetch conn:\n{:?}", &self.pool))?;
		match sqlx::query("update rsstg_source set enabled = true where source_id = $1 and owner = $2")
			.bind(source_id)
			.bind(owner)
			.execute(&mut conn).await
			.with_context(|| format!("Enable source:\n{:?}", &self.pool))?
			.rows_affected() {
			1 => { Ok("Source disabled\\.") },
			0 => { Ok("Source not found\\.") },
			_ => { Err(anyhow!("Database error.")) },
		}
	}

	async fn disable<S>(&self, source_id: &i32, owner: S) -> Result<&str>
	where S: Into<i64> {
		let owner: i64 = owner.into();
		let mut conn = self.pool.acquire().await
			.with_context(|| format!("Disable fetch conn:\n{:?}", &self.pool))?;
		match sqlx::query("update rsstg_source set enabled = false where source_id = $1 and owner = $2")
			.bind(source_id)
			.bind(owner)
			.execute(&mut conn).await
			.with_context(|| format!("Disable source:\n{:?}", &self.pool))?
			.rows_affected() {
			1 => { Ok("Source disabled\\.") },
			0 => { Ok("Source not found\\.") },
			_ => { Err(anyhow!("Database error.")) },
		}
	}

	async fn update<S>(&self, update: Option<i32>, channel: &str, channel_id: i64, url: &str, iv_hash: Option<&str>, owner: S) -> Result<String>
	where S: Into<i64> {
		let owner: i64 = owner.into();
		let mut conn = self.pool.acquire().await
			.with_context(|| format!("Update fetch conn:\n{:?}", &self.pool))?;

		match match update {
				Some(id) => {
					sqlx::query("update rsstg_source set channel_id = $2, url = $3, iv_hash = $4, owner = $5, channel = $6 where source_id = $1").bind(id)
				},
				None => {
					sqlx::query("insert into rsstg_source (channel_id, url, iv_hash, owner, channel) values ($1, $2, $3, $4, $5)")
				},
			}
			.bind(channel_id)
			.bind(url)
			.bind(iv_hash)
			.bind(owner)
			.bind(channel)
			.execute(&mut conn).await {


			Ok(_) => return Ok(String::from("Channel added\\.")),
			Err(sqlx::Error::Database(err)) => {
				match err.downcast::<sqlx::postgres::PgDatabaseError>().routine() {
					Some("_bt_check_unique", ) => {
						return Ok("Duplicate key\\.".to_string())
					},
					Some(_) => {
						return Ok("Database error\\.".to_string())
					},
					None => {
						return Ok("No database error extracted\\.".to_string())
					},
				};
			},
			Err(err) => {
				bail!("Sorry, unknown error:\n{:#?}\n", err);
			},
		};
	}

	async fn autofetch(&self) -> Result<()> {
		let mut delay = chrono::Duration::minutes(5);
		let mut now;
		loop {
			let mut conn = self.pool.acquire().await
				.with_context(|| format!("Autofetch fetch conn:\n{:?}", &self.pool))?;
			now = chrono::Local::now();
			let mut queue = sqlx::query("select source_id, next_fetch, owner from rsstg_order natural left join rsstg_source where next_fetch < now();")
				.fetch_all(&mut conn).await?;
			for row in queue.iter() {
				let source_id: i32 = row.try_get("source_id")?;
				let owner: i64 = row.try_get("owner")?;
				let next_fetch: DateTime<chrono::Local> = row.try_get("next_fetch")?;
				if next_fetch < now {
					sqlx::query("update rsstg_source set last_scrape = now() + interval '1 hour' where source_id = $1;")
						.bind(source_id)
						.execute(&mut conn).await
						.with_context(|| format!(" Lock source:\n\n{:?}", &self.pool))?;
					let clone = self.clone();
					tokio::spawn(async move {
						if let Err(err) = clone.check(&source_id, owner, true).await {
							if let Err(err) = clone.debug(&format!("🛑 {:?}", err)) {
								eprintln!("Check error: {}", err);
							};
						};
					});
				} else {
					if next_fetch - now < delay {
						delay = next_fetch - now;
					}
				}
			};
			queue.clear();
			tokio::time::delay_for(delay.to_std()?).await;
			delay = chrono::Duration::minutes(5);
		}
	}

	async fn list<S>(&self, owner: S) -> Result<Vec<String>>
	where S: Into<i64> {
		let owner = owner.into();
		let mut reply = vec![];
		let mut conn = self.pool.acquire().await
			.with_context(|| format!("List fetch conn:\n{:?}", &self.pool))?;
		reply.push("Channels:".to_string());
		let rows = sqlx::query("select source_id, channel, enabled, url, iv_hash from rsstg_source where owner = $1 order by source_id")
			.bind(owner)
			.fetch_all(&mut conn).await?;
		for row in rows.iter() {
			let source_id: i32 = row.try_get("source_id")?;
			let username: &str = row.try_get("channel")?;
			let enabled: bool = row.try_get("enabled")?;
			let url: &str = row.try_get("url")?;
			let iv_hash: Option<&str> = row.try_get("iv_hash")?;
			reply.push(format!("\n\\#️⃣ {} \\*️⃣ `{}` {}\n🔗 `{}`", source_id, username,  
				match enabled {
					true  => "🔄 enabled",
					false => "⛔ disabled",
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274

	let core = Core::new(settings).await?;

	let mut stream = core.stream();

	while let Some(update) = stream.next().await {
		if let Err(err) = handle(update?, &core).await {
			core.debug(&format!("{:?}", err))?;
		};
	}

	Ok(())
}

async fn handle(update: telegram_bot::Update, core: &Core) -> Result<()> {







|







317
318
319
320
321
322
323
324
325
326
327
328
329
330
331

	let core = Core::new(settings).await?;

	let mut stream = core.stream();

	while let Some(update) = stream.next().await {
		if let Err(err) = handle(update?, &core).await {
			core.debug(&format!("🛑 {:?}", err))?;
		};
	}

	Ok(())
}

async fn handle(update: telegram_bot::Update, core: &Core) -> Result<()> {
298
299
300
301
302
303
304
305

306
307



308
309







310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359

360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405

406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
						"/list" => {
							reply.append(&mut core.list(message.from.id).await?);
						},

// add

						"/add" | "/update" => {
							let mut source_id: i32 = 0;

							if cmd == "/update" {
								source_id = words.next().unwrap().parse::<i32>()?;



							}
							let (channel, url, iv_hash) = (words.next().unwrap(), words.next().unwrap(), words.next());







							let ok_link = RE_LINK.is_match(&url);
							let ok_hash = match iv_hash {
								Some(hash) => RE_IV_HASH.is_match(&hash),
								None => true,
							};
							if ! ok_link {
								reply.push("Link should be link to atom/rss feed, something like \"https://domain/path\"\\.".to_string());
								core.debug(&format!("Url: {:?}", &url))?;
							}
							if ! ok_hash {
								reply.push("IV hash should be 14 hex digits.".to_string());
								core.debug(&format!("IV: {:?}", &iv_hash))?;
							}
							if ok_link && ok_hash {
								let chan: Option<i64> = match sqlx::query("select channel_id from rsstg_channel where username = $1")
									.bind(channel)
									.fetch_one(&core.pool).await {
										Ok(chan) => Some(chan.try_get("channel_id")?),
										Err(sqlx::Error::RowNotFound) => {
											let chan_id = i64::from(core.tg.send(telegram_bot::GetChat::new(telegram_bot::types::ChatRef::ChannelUsername(channel.to_string()))).await?.id());
											sqlx::query("insert into rsstg_channel (channel_id, username) values ($1, $2);")
												.bind(chan_id)
												.bind(channel)
												.execute(&core.pool).await?;
											Some(chan_id)
										},
										Err(err) => {
											reply.push("Sorry, unknown error\\.".to_string());
											core.debug(&format!("Sorry, unknown error:\n{:#?}\n", err))?;
											None
										},
								};
								if let Some(chan) = chan {
									match if cmd == "/update" {
											sqlx::query("update rsstg_source set channel_id = $2, url = $3, iv_hash = $4, owner = $4 where source_id = $1").bind(source_id)
										} else {
											sqlx::query("insert into rsstg_source (channel_id, url, iv_hash, owner) values ($1, $2, $3, $4)")
										}
										.bind(chan)
										.bind(url)
										.bind(iv_hash)
										.bind(i64::from(message.from.id))
										.execute(&core.pool).await {
										Ok(_) => reply.push("Channel added\\.".to_string()),
										Err(sqlx::Error::Database(err)) => {
											match err.downcast::<sqlx::postgres::PgDatabaseError>().routine() {
												Some("_bt_check_unique", ) => {
													reply.push("Duplicate key\\.".to_string());
												},
												Some(_) => {

													reply.push("Database error\\.".to_string());
												},
												None => {
													reply.push("No database error extracted\\.".to_string());
												},
											};
										},
										Err(err) => {
											reply.push("Sorry, unknown error\\.".to_string());
											core.debug(&format!("Sorry, unknown error:\n{:#?}\n", err))?;
										},
									};
								};
							};
						},

// addchan

						"/addchan" => {
							let channel = words.next().unwrap();
							if ! RE_USERNAME.is_match(&channel) {
								reply.push("Usernames should be something like \"@\\[a\\-zA\\-Z]\\[a\\-zA\\-Z0\\-9\\_]+\", aren't they?".to_string());
							} else {
								let chan: Option<i64> = match sqlx::query("select channel_id from rsstg_channel where username = $1")
									.bind(channel)
									.fetch_one(&core.pool).await {
										Ok(chan) => Some(chan.try_get("channel_id")?),
										Err(sqlx::Error::RowNotFound) => None,
										Err(err) => {
											reply.push("Sorry, unknown error\\.".to_string());
											core.debug(&format!("Sorry, unknown error:\n{:#?}", err))?;
											None
										},
								};
								match chan {
									Some(chan) => {
										let new_chan = core.tg.send(telegram_bot::GetChat::new(telegram_bot::types::ChatId::new(chan))).await?;
										if i64::from(new_chan.id()) == chan {
											reply.push("I already know that channel\\.".to_string());
										} else {
											reply.push("Hmm, channel has changed… I'll fix it later\\.".to_string());
										};
									},
									None => {
										match core.tg.send(telegram_bot::GetChatAdministrators::new(telegram_bot::types::ChatRef::ChannelUsername(channel.to_string()))).await {
											Ok(chan_adm) => {

												let (mut me, mut user) = (false, false);
												for admin in &chan_adm {
													if admin.user.id == core.my.id {
														me = true;
													};
													if admin.user.id == message.from.id {
														user = true;
													};
												};
												if ! me   { reply.push("I need to be admin on that channel\\.".to_string()); };
												if ! user { reply.push("You should be admin on that channel\\.".to_string()); };
												if me && user {
													let chan_id = core.tg.send(telegram_bot::GetChat::new(telegram_bot::types::ChatRef::ChannelUsername(channel.to_string()))).await?;
													sqlx::query("insert into rsstg_channel (channel_id, username) values ($1, $2);")
														.bind(i64::from(chan_id.id()))
														.bind(channel)
														.execute(&core.pool).await?;
													reply.push("Good, I know that channel now\\.\n".to_string());
												};
											},
											Err(_) => {
												reply.push("Sorry, I have no access to that chat\\.".to_string());
											},
										};
									},
								};
							};
						},

// check

						"/check" => {
							match &words.next().unwrap().parse::<i32>() {
								Err(err) => {
									reply.push(format!("I need a number\\.\n{}", &err));
								},
								Ok(number) => {
									core.check(&number, message.from.id, false).await
										.context("🛑 Channel check failed.")?;
								},
							};
						},

// clean

						"/clean" => {







|
>

|
>
>
>

|
>
>
>
>
>
>
>
|
<
<
<
<
<

|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
>
|
<
|
<
<
|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
<
>
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<











|







355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378





379
380
381








































382
383
384

385


386





387
























388







389

390
391
392
393
394
395
396
397
398
399
400
401






402









403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
						"/list" => {
							reply.append(&mut core.list(message.from.id).await?);
						},

// add

						"/add" | "/update" => {
							let mut source_id: Option<i32> = None;
							let at_least = "Requires at least 3 parameters.";
							if cmd == "/update" {
								let first_word = words.next()
									.context(at_least)?;
								source_id = Some(first_word.parse::<i32>()
									.with_context(|| format!("I need a number, but got {}.", first_word))?);
							}
							let (channel, url, iv_hash) = (
								words.next().context(at_least)?,
								words.next().context(at_least)?,
								words.next());
							if ! RE_USERNAME.is_match(&channel) {
								reply.push("Usernames should be something like \"@\\[a\\-zA\\-Z]\\[a\\-zA\\-Z0\\-9\\_]+\", aren't they?".to_string());
								bail!("Wrong username {:?}.", &channel);
							}
							if ! RE_LINK.is_match(&url) {





								reply.push("Link should be link to atom/rss feed, something like \"https://domain/path\"\\.".to_string());
								bail!("Url: {:?}", &url);
							}








































							if let Some(hash) = iv_hash {
								if ! RE_IV_HASH.is_match(&hash) {
									reply.push("IV hash should be 14 hex digits.".to_string());

									bail!("IV: {:?}", &iv_hash);


								};





							};
























							let channel_id = i64::from(core.tg.send(telegram_bot::GetChat::new(telegram_bot::types::ChatRef::ChannelUsername(channel.to_string()))).await?.id());







							let chan_adm = core.tg.send(telegram_bot::GetChatAdministrators::new(telegram_bot::types::ChatRef::ChannelUsername(channel.to_string()))).await

								.context("Sorry, I have no access to that chat\\.")?;
							let (mut me, mut user) = (false, false);
							for admin in chan_adm {
								if admin.user.id == core.my.id {
									me = true;
								};
								if admin.user.id == message.from.id {
									user = true;
								};
							};
							if ! me   { bail!("I need to be admin on that channel\\."); };
							if ! user { bail!("You should be admin on that channel\\."); };






							reply.push(core.update(source_id, channel, channel_id, url, iv_hash, message.from.id).await?);









						},

// check

						"/check" => {
							match &words.next().unwrap().parse::<i32>() {
								Err(err) => {
									reply.push(format!("I need a number\\.\n{}", &err));
								},
								Ok(number) => {
									core.check(&number, message.from.id, false).await
										.context("Channel check failed.")?;
								},
							};
						},

// clean

						"/clean" => {
469
470
471
472
473
474
475














476
477
478
479
480
481
482
								},
								Ok(number) => {
									let result = core.enable(&number, message.from.id).await?;
									reply.push(result.to_string());
								},
							};
						},















// disable

						"/disable" => {
							match &words.next().unwrap().parse::<i32>() {
								Err(err) => {
									reply.push(format!("I need a number\\.\n{}", &err));







>
>
>
>
>
>
>
>
>
>
>
>
>
>







439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
								},
								Ok(number) => {
									let result = core.enable(&number, message.from.id).await?;
									reply.push(result.to_string());
								},
							};
						},

// delete

						"/delete" => {
							match &words.next().unwrap().parse::<i32>() {
								Err(err) => {
									reply.push(format!("I need a number\\.\n{}", &err));
								},
								Ok(number) => {
									let result = core.delete(&number, message.from.id).await?;
									reply.push(result.to_string());
								},
							};
						},

// disable

						"/disable" => {
							match &words.next().unwrap().parse::<i32>() {
								Err(err) => {
									reply.push(format!("I need a number\\.\n{}", &err));