Compare commits
8 commits
3654232dd6
...
ecbb4f3bb6
| Author | SHA1 | Date | |
|---|---|---|---|
| ecbb4f3bb6 | |||
| 4467690ff1 | |||
| 55c3e967bc | |||
| 09b26c1b39 | |||
| ce95a54227 | |||
| eb21bf0d51 | |||
| 6702f976cb | |||
| a42853ac5a |
12 changed files with 202 additions and 499 deletions
218
koucha/Cargo.lock
generated
218
koucha/Cargo.lock
generated
|
|
@ -53,9 +53,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aws-lc-rs"
|
name = "aws-lc-rs"
|
||||||
version = "1.15.3"
|
version = "1.15.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e84ce723ab67259cfeb9877c6a639ee9eb7a27b28123abd71db7f0d5d0cc9d86"
|
checksum = "7b7b6141e96a8c160799cc2d5adecd5cbbe5054cb8c7c4af53da0f83bb7ad256"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aws-lc-sys",
|
"aws-lc-sys",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
|
|
@ -63,9 +63,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aws-lc-sys"
|
name = "aws-lc-sys"
|
||||||
version = "0.36.0"
|
version = "0.37.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "43a442ece363113bd4bd4c8b18977a7798dd4d3c3383f34fb61936960e8f4ad8"
|
checksum = "5c34dda4df7017c8db52132f0f8a2e0f8161649d15723ed63fc00c82d0f2081a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"cmake",
|
"cmake",
|
||||||
|
|
@ -73,58 +73,6 @@ dependencies = [
|
||||||
"fs_extra",
|
"fs_extra",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "axum"
|
|
||||||
version = "0.8.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8"
|
|
||||||
dependencies = [
|
|
||||||
"axum-core",
|
|
||||||
"bytes",
|
|
||||||
"form_urlencoded",
|
|
||||||
"futures-util",
|
|
||||||
"http",
|
|
||||||
"http-body",
|
|
||||||
"http-body-util",
|
|
||||||
"hyper",
|
|
||||||
"hyper-util",
|
|
||||||
"itoa",
|
|
||||||
"matchit",
|
|
||||||
"memchr",
|
|
||||||
"mime",
|
|
||||||
"percent-encoding",
|
|
||||||
"pin-project-lite",
|
|
||||||
"serde_core",
|
|
||||||
"serde_json",
|
|
||||||
"serde_path_to_error",
|
|
||||||
"serde_urlencoded",
|
|
||||||
"sync_wrapper",
|
|
||||||
"tokio",
|
|
||||||
"tower",
|
|
||||||
"tower-layer",
|
|
||||||
"tower-service",
|
|
||||||
"tracing",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "axum-core"
|
|
||||||
version = "0.5.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"futures-core",
|
|
||||||
"http",
|
|
||||||
"http-body",
|
|
||||||
"http-body-util",
|
|
||||||
"mime",
|
|
||||||
"pin-project-lite",
|
|
||||||
"sync_wrapper",
|
|
||||||
"tower-layer",
|
|
||||||
"tower-service",
|
|
||||||
"tracing",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.22.1"
|
version = "0.22.1"
|
||||||
|
|
@ -169,15 +117,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.11.0"
|
version = "1.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3"
|
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.52"
|
version = "1.2.55"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cd4932aefd12402b36c60956a4fe0035421f544799057659ff86f923657aada3"
|
checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"find-msvc-tools",
|
"find-msvc-tools",
|
||||||
"jobserver",
|
"jobserver",
|
||||||
|
|
@ -504,9 +452,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "find-msvc-tools"
|
name = "find-msvc-tools"
|
||||||
version = "0.1.7"
|
version = "0.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f449e6c6c08c865631d4890cfacf252b3d396c9bcc83adb6623cdb02a8336c41"
|
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flume"
|
name = "flume"
|
||||||
|
|
@ -778,12 +726,6 @@ version = "1.10.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
|
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "httpdate"
|
|
||||||
version = "1.0.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "1.8.1"
|
version = "1.8.1"
|
||||||
|
|
@ -798,7 +740,6 @@ dependencies = [
|
||||||
"http",
|
"http",
|
||||||
"http-body",
|
"http-body",
|
||||||
"httparse",
|
"httparse",
|
||||||
"httpdate",
|
|
||||||
"itoa",
|
"itoa",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"pin-utils",
|
"pin-utils",
|
||||||
|
|
@ -825,14 +766,13 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper-util"
|
name = "hyper-util"
|
||||||
version = "0.1.19"
|
version = "0.1.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f"
|
checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http",
|
"http",
|
||||||
"http-body",
|
"http-body",
|
||||||
|
|
@ -851,9 +791,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iana-time-zone"
|
name = "iana-time-zone"
|
||||||
version = "0.1.64"
|
version = "0.1.65"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb"
|
checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"android_system_properties",
|
"android_system_properties",
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
|
|
@ -1047,9 +987,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.83"
|
version = "0.3.85"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8"
|
checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
|
|
@ -1059,7 +999,6 @@ dependencies = [
|
||||||
name = "koucha"
|
name = "koucha"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
|
||||||
"chrono",
|
"chrono",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"rss",
|
"rss",
|
||||||
|
|
@ -1084,9 +1023,9 @@ checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libm"
|
name = "libm"
|
||||||
version = "0.2.15"
|
version = "0.2.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
|
checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libredox"
|
name = "libredox"
|
||||||
|
|
@ -1137,12 +1076,6 @@ version = "0.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
|
checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "matchit"
|
|
||||||
version = "0.8.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "md-5"
|
name = "md-5"
|
||||||
version = "0.10.6"
|
version = "0.10.6"
|
||||||
|
|
@ -1236,9 +1169,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-probe"
|
name = "openssl-probe"
|
||||||
version = "0.2.0"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391"
|
checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking"
|
name = "parking"
|
||||||
|
|
@ -1343,9 +1276,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.105"
|
version = "1.0.106"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7"
|
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
@ -1374,7 +1307,7 @@ dependencies = [
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"rustls",
|
"rustls",
|
||||||
"socket2",
|
"socket2",
|
||||||
"thiserror 2.0.17",
|
"thiserror 2.0.18",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
"web-time",
|
"web-time",
|
||||||
|
|
@ -1396,7 +1329,7 @@ dependencies = [
|
||||||
"rustls",
|
"rustls",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
"slab",
|
"slab",
|
||||||
"thiserror 2.0.17",
|
"thiserror 2.0.18",
|
||||||
"tinyvec",
|
"tinyvec",
|
||||||
"tracing",
|
"tracing",
|
||||||
"web-time",
|
"web-time",
|
||||||
|
|
@ -1418,9 +1351,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.43"
|
version = "1.0.44"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a"
|
checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
@ -1626,9 +1559,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls-pki-types"
|
name = "rustls-pki-types"
|
||||||
version = "1.13.2"
|
version = "1.14.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282"
|
checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"web-time",
|
"web-time",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
|
|
@ -1663,9 +1596,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls-webpki"
|
name = "rustls-webpki"
|
||||||
version = "0.103.8"
|
version = "0.103.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52"
|
checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aws-lc-rs",
|
"aws-lc-rs",
|
||||||
"ring",
|
"ring",
|
||||||
|
|
@ -1775,17 +1708,6 @@ dependencies = [
|
||||||
"zmij",
|
"zmij",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_path_to_error"
|
|
||||||
version = "0.1.20"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457"
|
|
||||||
dependencies = [
|
|
||||||
"itoa",
|
|
||||||
"serde",
|
|
||||||
"serde_core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_urlencoded"
|
name = "serde_urlencoded"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
|
|
@ -1848,9 +1770,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.11"
|
version = "0.4.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
|
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
|
|
@ -1863,9 +1785,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.6.1"
|
version = "0.6.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881"
|
checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.60.2",
|
"windows-sys 0.60.2",
|
||||||
|
|
@ -1930,7 +1852,7 @@ dependencies = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha2",
|
"sha2",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"thiserror 2.0.17",
|
"thiserror 2.0.18",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
|
@ -2012,7 +1934,7 @@ dependencies = [
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
"stringprep",
|
"stringprep",
|
||||||
"thiserror 2.0.17",
|
"thiserror 2.0.18",
|
||||||
"tracing",
|
"tracing",
|
||||||
"whoami",
|
"whoami",
|
||||||
]
|
]
|
||||||
|
|
@ -2049,7 +1971,7 @@ dependencies = [
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
"stringprep",
|
"stringprep",
|
||||||
"thiserror 2.0.17",
|
"thiserror 2.0.18",
|
||||||
"tracing",
|
"tracing",
|
||||||
"whoami",
|
"whoami",
|
||||||
]
|
]
|
||||||
|
|
@ -2073,7 +1995,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
"sqlx-core",
|
"sqlx-core",
|
||||||
"thiserror 2.0.17",
|
"thiserror 2.0.18",
|
||||||
"tracing",
|
"tracing",
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
@ -2140,9 +2062,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "system-configuration"
|
name = "system-configuration"
|
||||||
version = "0.6.1"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
|
checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"core-foundation 0.9.4",
|
"core-foundation 0.9.4",
|
||||||
|
|
@ -2170,11 +2092,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "2.0.17"
|
version = "2.0.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
|
checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl 2.0.17",
|
"thiserror-impl 2.0.18",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2190,9 +2112,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "2.0.17"
|
version = "2.0.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
|
checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
@ -2299,7 +2221,6 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower-layer",
|
"tower-layer",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"tracing",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2466,9 +2387,9 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasip2"
|
name = "wasip2"
|
||||||
version = "1.0.1+wasi-0.2.4"
|
version = "1.0.2+wasi-0.2.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
|
checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wit-bindgen",
|
"wit-bindgen",
|
||||||
]
|
]
|
||||||
|
|
@ -2481,9 +2402,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.106"
|
version = "0.2.108"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd"
|
checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
|
@ -2494,11 +2415,12 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-futures"
|
name = "wasm-bindgen-futures"
|
||||||
version = "0.4.56"
|
version = "0.4.58"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c"
|
checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
"futures-util",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
|
|
@ -2507,9 +2429,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro"
|
name = "wasm-bindgen-macro"
|
||||||
version = "0.2.106"
|
version = "0.2.108"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3"
|
checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"wasm-bindgen-macro-support",
|
"wasm-bindgen-macro-support",
|
||||||
|
|
@ -2517,9 +2439,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro-support"
|
name = "wasm-bindgen-macro-support"
|
||||||
version = "0.2.106"
|
version = "0.2.108"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40"
|
checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
|
@ -2530,18 +2452,18 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-shared"
|
name = "wasm-bindgen-shared"
|
||||||
version = "0.2.106"
|
version = "0.2.108"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4"
|
checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "web-sys"
|
name = "web-sys"
|
||||||
version = "0.3.83"
|
version = "0.3.85"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac"
|
checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
|
|
@ -2559,9 +2481,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webpki-root-certs"
|
name = "webpki-root-certs"
|
||||||
version = "1.0.5"
|
version = "1.0.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "36a29fc0408b113f68cf32637857ab740edfafdf460c326cd2afaa2d84cc05dc"
|
checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
]
|
]
|
||||||
|
|
@ -2945,9 +2867,9 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wit-bindgen"
|
name = "wit-bindgen"
|
||||||
version = "0.46.0"
|
version = "0.51.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "writeable"
|
name = "writeable"
|
||||||
|
|
@ -2980,18 +2902,18 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.8.33"
|
version = "0.8.38"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd"
|
checksum = "57cf3aa6855b23711ee9852dfc97dfaa51c45feaba5b645d0c777414d494a961"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zerocopy-derive",
|
"zerocopy-derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy-derive"
|
name = "zerocopy-derive"
|
||||||
version = "0.8.33"
|
version = "0.8.38"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1"
|
checksum = "8a616990af1a287837c4fe6596ad77ef57948f787e46ce28e166facc0cc1cb75"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
@ -3060,6 +2982,6 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zmij"
|
name = "zmij"
|
||||||
version = "1.0.14"
|
version = "1.0.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bd8f3f50b848df28f887acb68e41201b5aea6bc8a8dacc00fb40635ff9a72fea"
|
checksum = "3ff05f8caa9038894637571ae6b9e29466c1f4f829d26c9b28f869a29cbe3445"
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
axum = "0.8.8"
|
|
||||||
reqwest = "0.13.1"
|
reqwest = "0.13.1"
|
||||||
rss = "2.0.12"
|
rss = "2.0.12"
|
||||||
tokio = { version = "1.49.0", features = ["full"] }
|
tokio = { version = "1.49.0", features = ["full"] }
|
||||||
|
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
use std::error::Error;
|
|
||||||
|
|
||||||
#[tokio::main]
|
|
||||||
async fn main() -> Result<(), Box<dyn Error>> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -4,8 +4,6 @@ mod feed;
|
||||||
pub use feed::Feed;
|
pub use feed::Feed;
|
||||||
mod feed_channel;
|
mod feed_channel;
|
||||||
pub use feed_channel::FeedChannel;
|
pub use feed_channel::FeedChannel;
|
||||||
mod feed_item;
|
|
||||||
pub use feed_item::FeedItem;
|
|
||||||
mod channel;
|
mod channel;
|
||||||
pub use channel::Channel;
|
pub use channel::Channel;
|
||||||
mod item;
|
mod item;
|
||||||
|
|
@ -17,17 +15,16 @@ macro_rules! define_key {
|
||||||
pub struct $name(i64);
|
pub struct $name(i64);
|
||||||
};
|
};
|
||||||
|
|
||||||
($name:ident, $($field:ident),* $(,)?) => {
|
($name:ident, $($field:ident : $type:ty),* $(,)?) => {
|
||||||
#[derive(PartialEq, Debug, Copy, Clone)]
|
#[derive(PartialEq, Debug, Copy, Clone)]
|
||||||
pub struct $name {
|
pub struct $name {
|
||||||
$($field: i64),*
|
$($field: $type),*
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
define_key!(UserKey);
|
define_key!(UserKey);
|
||||||
define_key!(FeedKey);
|
define_key!(FeedKey);
|
||||||
define_key!(FeedChannelKey, feed_id, channel_id);
|
define_key!(FeedChannelKey, feed_key: FeedKey, channel_key: ChannelKey);
|
||||||
define_key!(FeedItemKey, feed_id, item_id);
|
|
||||||
define_key!(ChannelKey);
|
define_key!(ChannelKey);
|
||||||
define_key!(ItemKey);
|
define_key!(ItemKey);
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ use crate::{
|
||||||
feed_channel::UnparsedFeedChannel,
|
feed_channel::UnparsedFeedChannel,
|
||||||
item::UnparsedItem,
|
item::UnparsedItem,
|
||||||
},
|
},
|
||||||
fetch::FetchedRSSChannel,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct UnparsedChannel {
|
pub struct UnparsedChannel {
|
||||||
|
|
@ -23,7 +22,7 @@ pub struct UnparsedChannel {
|
||||||
impl UnparsedChannel {
|
impl UnparsedChannel {
|
||||||
pub fn parse(self) -> Result<Channel> {
|
pub fn parse(self) -> Result<Channel> {
|
||||||
Ok(Channel {
|
Ok(Channel {
|
||||||
id: ChannelKey(self.id),
|
key: ChannelKey(self.id),
|
||||||
title: self.title,
|
title: self.title,
|
||||||
link: Url::parse(&self.link)?,
|
link: Url::parse(&self.link)?,
|
||||||
description: self.description,
|
description: self.description,
|
||||||
|
|
@ -36,7 +35,7 @@ impl UnparsedChannel {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Channel {
|
pub struct Channel {
|
||||||
id: ChannelKey,
|
key: ChannelKey,
|
||||||
title: String,
|
title: String,
|
||||||
link: Url,
|
link: Url,
|
||||||
description: Option<String>,
|
description: Option<String>,
|
||||||
|
|
@ -44,31 +43,27 @@ pub struct Channel {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Channel {
|
impl Channel {
|
||||||
pub fn id(&self) -> ChannelKey { self.id }
|
pub fn key(&self) -> ChannelKey { self.key }
|
||||||
pub fn title(&self) -> &str { &self.title }
|
pub fn title(&self) -> &str { &self.title }
|
||||||
pub fn link(&self) -> &Url { &self.link }
|
pub fn link(&self) -> &Url { &self.link }
|
||||||
pub fn description(&self) -> Option<&str> { self.description.as_deref() }
|
pub fn description(&self) -> Option<&str> { self.description.as_deref() }
|
||||||
pub fn last_fetched(&self) -> Option<DateTime<Utc>> { self.last_fetched }
|
pub fn last_fetched(&self) -> Option<DateTime<Utc>> { self.last_fetched }
|
||||||
|
|
||||||
pub async fn get_all(pool: &AdapterPool) -> Result<Vec<Self>> {
|
pub async fn get_all(pool: &AdapterPool) -> Result<Vec<Self>> {
|
||||||
let channels: Result<Vec<Channel>> = sqlx::query_as!(
|
sqlx::query_as!(
|
||||||
UnparsedChannel,
|
UnparsedChannel,
|
||||||
"SELECT id, title, link, description, last_fetched FROM channels"
|
"SELECT id, title, link, description, last_fetched FROM channels"
|
||||||
).fetch_all(&pool.0).await?.into_iter().map(UnparsedChannel::parse).collect();
|
).fetch_all(&pool.0).await?.into_iter().map(UnparsedChannel::parse).collect()
|
||||||
|
|
||||||
channels
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get(pool: &AdapterPool, id: ChannelKey) -> Result<Self> {
|
pub async fn get(pool: &AdapterPool, key: ChannelKey) -> Result<Self> {
|
||||||
let channel: Result<Self> = sqlx::query_as!(
|
sqlx::query_as!(
|
||||||
UnparsedChannel,
|
UnparsedChannel,
|
||||||
"SELECT id, title, link, description, last_fetched
|
"SELECT id, title, link, description, last_fetched
|
||||||
FROM channels
|
FROM channels
|
||||||
WHERE id = ?",
|
WHERE id = ?",
|
||||||
id.0
|
key.0
|
||||||
).fetch_one(&pool.0).await?.parse();
|
).fetch_one(&pool.0).await?.parse()
|
||||||
|
|
||||||
channel
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_or_create(
|
pub async fn get_or_create(
|
||||||
|
|
@ -76,84 +71,38 @@ impl Channel {
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let link_str = link.as_str();
|
let link_str = link.as_str();
|
||||||
|
|
||||||
let channel = sqlx::query_as!(
|
sqlx::query_as!(
|
||||||
UnparsedChannel,
|
UnparsedChannel,
|
||||||
"INSERT INTO channels (title, link)
|
"INSERT INTO channels (title, link)
|
||||||
VALUES(?, ?)
|
VALUES(?, ?)
|
||||||
ON CONFLICT(link) DO UPDATE SET link = link
|
ON CONFLICT(link) DO UPDATE SET link = link
|
||||||
RETURNING id, title, link, description, last_fetched",
|
RETURNING id, title, link, description, last_fetched",
|
||||||
link_str, link_str // We use the url as a placeholder title
|
link_str, link_str // We use the url as a placeholder title
|
||||||
).fetch_one(&pool.0).await?.parse();
|
).fetch_one(&pool.0).await?.parse()
|
||||||
|
|
||||||
channel
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO implement fetch skipping
|
|
||||||
pub fn should_skip_fetch(&self) -> bool { false }
|
|
||||||
|
|
||||||
pub async fn update_metadata(
|
|
||||||
&self, pool: &AdapterPool, fetched: FetchedRSSChannel
|
|
||||||
) -> Result<()> {
|
|
||||||
let title = fetched.title();
|
|
||||||
let description = fetched.description();
|
|
||||||
let link = fetched.link().as_str();
|
|
||||||
let fetched_at = fetched.fetched_at().to_rfc2822();
|
|
||||||
sqlx::query!(
|
|
||||||
"UPDATE channels
|
|
||||||
SET title = ?, link = ?, description = ?,
|
|
||||||
last_fetched = ?
|
|
||||||
WHERE id = ?",
|
|
||||||
title, link, description, fetched_at,
|
|
||||||
self.id.0
|
|
||||||
).execute(&pool.0).await?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_feed_channels(
|
async fn get_feed_channels(
|
||||||
&self, pool: &AdapterPool
|
&self, pool: &AdapterPool
|
||||||
) -> Result<Vec<FeedChannel>> {
|
) -> Result<Vec<FeedChannel>> {
|
||||||
let feeds: Result<Vec<FeedChannel>> = sqlx::query_as!(
|
sqlx::query_as!(
|
||||||
UnparsedFeedChannel,
|
UnparsedFeedChannel,
|
||||||
"SELECT channel_id, feed_id, initial_score, gravity, boost
|
"SELECT channel_id, feed_id, initial_score, gravity, boost
|
||||||
FROM feed_channels
|
FROM feed_channels
|
||||||
WHERE channel_id = ?",
|
WHERE channel_id = ?",
|
||||||
self.id.0
|
self.key.0
|
||||||
).fetch_all(&pool.0).await?.into_iter()
|
).fetch_all(&pool.0).await?.into_iter()
|
||||||
.map(UnparsedFeedChannel::parse).collect();
|
.map(UnparsedFeedChannel::parse).collect()
|
||||||
|
|
||||||
feeds
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn update_items(
|
|
||||||
&self, pool: &AdapterPool, fetched: FetchedRSSChannel
|
|
||||||
) -> Result<()> {
|
|
||||||
let fetched_at = fetched.fetched_at();
|
|
||||||
|
|
||||||
let feed_channels = self.get_feed_channels(pool).await?;
|
|
||||||
|
|
||||||
for rss_item in fetched.items() {
|
|
||||||
let new_item = Item::get_or_create(pool, self.id, rss_item.guid()).await?;
|
|
||||||
new_item.update_content(pool, rss_item, &fetched_at).await?;
|
|
||||||
for feed_channel in &feed_channels {
|
|
||||||
feed_channel.add_item(pool, &new_item).await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_items(&self, pool: &AdapterPool) -> Result<Vec<Item>> {
|
pub async fn get_items(&self, pool: &AdapterPool) -> Result<Vec<Item>> {
|
||||||
let items: Result<Vec<Item>> = sqlx::query_as!(
|
sqlx::query_as!(
|
||||||
UnparsedItem,
|
UnparsedItem,
|
||||||
"SELECT id as `id!`, channel_id, fetched_at, title, description,
|
"SELECT id as `id!`, channel_id, fetched_at, title, description,
|
||||||
content
|
content
|
||||||
FROM items
|
FROM items
|
||||||
WHERE channel_id = ?",
|
WHERE channel_id = ?",
|
||||||
self.id.0
|
self.key.0
|
||||||
).fetch_all(&pool.0).await?.into_iter().map(UnparsedItem::parse).collect();
|
).fetch_all(&pool.0).await?.into_iter().map(UnparsedItem::parse).collect()
|
||||||
|
|
||||||
items
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -161,10 +110,7 @@ impl Channel {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
db::{
|
db::{Feed, User},
|
||||||
Feed,
|
|
||||||
User,
|
|
||||||
},
|
|
||||||
test_utils::{
|
test_utils::{
|
||||||
FEED1, FEED2, CHANNEL_TITLE, CHANNEL_DESC, USERNAME, FEED_TITLE,
|
FEED1, FEED2, CHANNEL_TITLE, CHANNEL_DESC, USERNAME, FEED_TITLE,
|
||||||
FEED_TITLE2, ITEM_GUID, ITEM_GUID2,
|
FEED_TITLE2, ITEM_GUID, ITEM_GUID2,
|
||||||
|
|
@ -173,7 +119,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use chrono::TimeZone;
|
use chrono::TimeZone;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_unparsed_item() {
|
fn parse_unparsed_item() {
|
||||||
const CHANNEL_ID: i64 = 1;
|
const CHANNEL_ID: i64 = 1;
|
||||||
|
|
@ -188,7 +134,7 @@ mod tests {
|
||||||
};
|
};
|
||||||
let channel = raw_channel.parse().unwrap();
|
let channel = raw_channel.parse().unwrap();
|
||||||
|
|
||||||
assert_eq!(channel.id.0, CHANNEL_ID);
|
assert_eq!(channel.key.0, CHANNEL_ID);
|
||||||
assert_eq!(channel.title, CHANNEL_TITLE);
|
assert_eq!(channel.title, CHANNEL_TITLE);
|
||||||
assert_eq!(channel.link.as_str(), FEED1);
|
assert_eq!(channel.link.as_str(), FEED1);
|
||||||
assert_eq!(channel.description, Some(CHANNEL_DESC.to_string()));
|
assert_eq!(channel.description, Some(CHANNEL_DESC.to_string()));
|
||||||
|
|
@ -213,10 +159,10 @@ mod tests {
|
||||||
let adapter = setup_adapter().await;
|
let adapter = setup_adapter().await;
|
||||||
let pool = adapter.get_pool();
|
let pool = adapter.get_pool();
|
||||||
let channel_a = setup_channel(pool).await;
|
let channel_a = setup_channel(pool).await;
|
||||||
|
|
||||||
let channel_b = Channel::get(pool, channel_a.id()).await.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(channel_a.id, channel_b.id);
|
let channel_b = Channel::get(pool, channel_a.key()).await.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(channel_a.key, channel_b.key);
|
||||||
assert_eq!(channel_a.title, channel_b.title);
|
assert_eq!(channel_a.title, channel_b.title);
|
||||||
assert_eq!(channel_a.link, channel_b.link);
|
assert_eq!(channel_a.link, channel_b.link);
|
||||||
assert_eq!(channel_a.last_fetched, channel_b.last_fetched);
|
assert_eq!(channel_a.last_fetched, channel_b.last_fetched);
|
||||||
|
|
@ -226,12 +172,12 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn create() {
|
async fn create() {
|
||||||
let adapter = setup_adapter().await;
|
let adapter = setup_adapter().await;
|
||||||
let pool = adapter.get_pool();
|
let pool = adapter.get_pool();
|
||||||
let url_feed = Url::parse(FEED1).unwrap();
|
let url_feed = Url::parse(FEED1).unwrap();
|
||||||
|
|
||||||
let channel = Channel::get_or_create(pool, url_feed).await.unwrap();
|
let channel = Channel::get_or_create(pool, url_feed).await.unwrap();
|
||||||
|
|
||||||
assert!(channel.id().0 > 0);
|
assert!(channel.key().0 > 0);
|
||||||
assert_eq!(channel.link().as_str(), FEED1);
|
assert_eq!(channel.link().as_str(), FEED1);
|
||||||
assert!(channel.title().len() > 0);
|
assert!(channel.title().len() > 0);
|
||||||
}
|
}
|
||||||
|
|
@ -239,19 +185,19 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn create_duplicate_returns_existing() {
|
async fn create_duplicate_returns_existing() {
|
||||||
let adapter = setup_adapter().await;
|
let adapter = setup_adapter().await;
|
||||||
let pool = adapter.get_pool();
|
let pool = adapter.get_pool();
|
||||||
let url_feed = Url::parse(FEED1).unwrap();
|
let url_feed = Url::parse(FEED1).unwrap();
|
||||||
|
|
||||||
let channel1 = Channel::get_or_create(pool, url_feed.clone()).await.unwrap();
|
let channel1 = Channel::get_or_create(pool, url_feed.clone()).await.unwrap();
|
||||||
let channel2 = Channel::get_or_create(pool, url_feed).await.unwrap();
|
let channel2 = Channel::get_or_create(pool, url_feed).await.unwrap();
|
||||||
|
|
||||||
assert_eq!(channel1.id(), channel2.id());
|
assert_eq!(channel1.key(), channel2.key());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn get_all_channels() {
|
async fn get_all_channels() {
|
||||||
let adapter = setup_adapter().await;
|
let adapter = setup_adapter().await;
|
||||||
let pool = adapter.get_pool();
|
let pool = adapter.get_pool();
|
||||||
let url_feed1 = Url::parse(FEED1).unwrap();
|
let url_feed1 = Url::parse(FEED1).unwrap();
|
||||||
let url_feed2 = Url::parse(FEED2).unwrap();
|
let url_feed2 = Url::parse(FEED2).unwrap();
|
||||||
|
|
||||||
|
|
@ -270,29 +216,11 @@ mod tests {
|
||||||
let channel = setup_channel(pool).await;
|
let channel = setup_channel(pool).await;
|
||||||
|
|
||||||
let user = User::create(pool, USERNAME).await.unwrap();
|
let user = User::create(pool, USERNAME).await.unwrap();
|
||||||
let feed1 = Feed::create(pool, user.id(), FEED_TITLE).await.unwrap();
|
let feed1 = Feed::create(pool, user.key(), FEED_TITLE).await.unwrap();
|
||||||
let feed2 = Feed::create(pool, user.id(), FEED_TITLE2).await.unwrap();
|
let feed2 = Feed::create(pool, user.key(), FEED_TITLE2).await.unwrap();
|
||||||
|
|
||||||
feed1.add_channel(pool, channel.id).await.unwrap();
|
feed1.add_channel(pool, channel.key).await.unwrap();
|
||||||
feed2.add_channel(pool, channel.id).await.unwrap();
|
feed2.add_channel(pool, channel.key).await.unwrap();
|
||||||
|
|
||||||
let fc_list = channel.get_feed_channels(pool).await.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(fc_list.len(), 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn get_channels() {
|
|
||||||
let adapter = setup_adapter().await;
|
|
||||||
let pool = adapter.get_pool();
|
|
||||||
let channel = setup_channel(pool).await;
|
|
||||||
|
|
||||||
let user = User::create(pool, USERNAME).await.unwrap();
|
|
||||||
let feed1 = Feed::create(pool, user.id(), FEED_TITLE).await.unwrap();
|
|
||||||
let feed2 = Feed::create(pool, user.id(), FEED_TITLE2).await.unwrap();
|
|
||||||
|
|
||||||
feed1.add_channel(pool, channel.id).await.unwrap();
|
|
||||||
feed2.add_channel(pool, channel.id).await.unwrap();
|
|
||||||
|
|
||||||
let fc_list = channel.get_feed_channels(pool).await.unwrap();
|
let fc_list = channel.get_feed_channels(pool).await.unwrap();
|
||||||
|
|
||||||
|
|
@ -305,8 +233,8 @@ mod tests {
|
||||||
let pool = adapter.get_pool();
|
let pool = adapter.get_pool();
|
||||||
let channel = setup_channel(pool).await;
|
let channel = setup_channel(pool).await;
|
||||||
|
|
||||||
Item::get_or_create(pool, channel.id(), ITEM_GUID).await.unwrap();
|
Item::get_or_create(pool, channel.key(), ITEM_GUID).await.unwrap();
|
||||||
Item::get_or_create(pool, channel.id(), ITEM_GUID2).await.unwrap();
|
Item::get_or_create(pool, channel.key(), ITEM_GUID2).await.unwrap();
|
||||||
|
|
||||||
let items = channel.get_items(pool).await.unwrap();
|
let items = channel.get_items(pool).await.unwrap();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,65 +19,61 @@ pub struct UnparsedFeed {
|
||||||
impl UnparsedFeed {
|
impl UnparsedFeed {
|
||||||
pub fn parse(self) -> Result<Feed> {
|
pub fn parse(self) -> Result<Feed> {
|
||||||
Ok(Feed {
|
Ok(Feed {
|
||||||
id: FeedKey(self.id),
|
key: FeedKey(self.id),
|
||||||
title: self.title,
|
title: self.title,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Feed {
|
pub struct Feed {
|
||||||
id: FeedKey,
|
key: FeedKey,
|
||||||
title: String,
|
title: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Feed {
|
impl Feed {
|
||||||
pub fn id(&self) -> FeedKey { self.id }
|
pub fn key(&self) -> FeedKey { self.key }
|
||||||
pub fn title(&self) -> &str { &self.title }
|
pub fn title(&self) -> &str { &self.title }
|
||||||
|
|
||||||
pub async fn get(
|
pub async fn get(
|
||||||
pool: &AdapterPool, id: FeedKey
|
pool: &AdapterPool, key: FeedKey
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let feed = sqlx::query_as!(
|
sqlx::query_as!(
|
||||||
UnparsedFeed,
|
UnparsedFeed,
|
||||||
"SELECT id, title FROM feeds WHERE id = ?",
|
"SELECT id, title FROM feeds WHERE id = ?",
|
||||||
id.0
|
key.0
|
||||||
).fetch_one(&pool.0).await?.parse();
|
).fetch_one(&pool.0).await?.parse()
|
||||||
|
|
||||||
feed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create(
|
pub async fn create(
|
||||||
pool: &AdapterPool, user_id: UserKey, title: &str
|
pool: &AdapterPool, user_key: UserKey, title: &str
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let new_feed = sqlx::query_as!(
|
sqlx::query_as!(
|
||||||
UnparsedFeed,
|
UnparsedFeed,
|
||||||
"INSERT INTO feeds (user_id, title)
|
"INSERT INTO feeds (user_id, title)
|
||||||
VALUES (?, ?)
|
VALUES (?, ?)
|
||||||
RETURNING id as `id!`, title",
|
RETURNING id as `id!`, title",
|
||||||
user_id.0, title
|
user_key.0, title
|
||||||
).fetch_one(&pool.0).await?.parse();
|
).fetch_one(&pool.0).await?.parse()
|
||||||
|
|
||||||
new_feed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update_title(
|
pub async fn update_title(
|
||||||
pool: &AdapterPool, id: FeedKey, new_title: &str
|
pool: &AdapterPool, key: FeedKey, new_title: &str
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"UPDATE feeds SET title = ? WHERE id = ?",
|
"UPDATE feeds SET title = ? WHERE id = ?",
|
||||||
new_title, id.0
|
new_title, key.0
|
||||||
).execute(&pool.0).await?;
|
).execute(&pool.0).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn add_channel(
|
pub async fn add_channel(
|
||||||
&self, pool: &AdapterPool, channel_id: ChannelKey
|
&self, pool: &AdapterPool, channel_key: ChannelKey
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"INSERT INTO feed_channels (feed_id, channel_id)
|
"INSERT INTO feed_channels (feed_id, channel_id)
|
||||||
VALUES (?, ?)",
|
VALUES (?, ?)",
|
||||||
self.id.0, channel_id.0
|
self.key.0, channel_key.0
|
||||||
).execute(&pool.0).await?;
|
).execute(&pool.0).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -86,7 +82,7 @@ impl Feed {
|
||||||
pub async fn get_items(
|
pub async fn get_items(
|
||||||
&self, pool: &AdapterPool, limit: u8, offset: u32
|
&self, pool: &AdapterPool, limit: u8, offset: u32
|
||||||
) -> Result<Vec<Item>> {
|
) -> Result<Vec<Item>> {
|
||||||
let items: Result<Vec<Item>> = sqlx::query_as!(
|
sqlx::query_as!(
|
||||||
UnparsedItem,
|
UnparsedItem,
|
||||||
"SELECT i.id as `id!`, i.channel_id, i.fetched_at, i.title, i.description,
|
"SELECT i.id as `id!`, i.channel_id, i.fetched_at, i.title, i.description,
|
||||||
i.content
|
i.content
|
||||||
|
|
@ -95,26 +91,22 @@ impl Feed {
|
||||||
WHERE feed_id = ? AND archived = FALSE
|
WHERE feed_id = ? AND archived = FALSE
|
||||||
ORDER BY score DESC
|
ORDER BY score DESC
|
||||||
LIMIT ? OFFSET ?",
|
LIMIT ? OFFSET ?",
|
||||||
self.id.0, limit, offset
|
self.key.0, limit, offset
|
||||||
).fetch_all(&pool.0).await?.into_iter().map(UnparsedItem::parse).collect();
|
).fetch_all(&pool.0).await?.into_iter().map(UnparsedItem::parse).collect()
|
||||||
|
|
||||||
items
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_channels(
|
pub async fn get_channels(
|
||||||
&self, pool: &AdapterPool
|
&self, pool: &AdapterPool
|
||||||
) -> Result<Vec<Channel>> {
|
) -> Result<Vec<Channel>> {
|
||||||
let channels: Result<Vec<Channel>> = sqlx::query_as!(
|
sqlx::query_as!(
|
||||||
UnparsedChannel,
|
UnparsedChannel,
|
||||||
"SELECT c.id as `id!`, c.title, c.link, c.description, c.last_fetched
|
"SELECT c.id as `id!`, c.title, c.link, c.description, c.last_fetched
|
||||||
FROM channels c
|
FROM channels c
|
||||||
JOIN feed_channels fc on c.id = fc.channel_id
|
JOIN feed_channels fc on c.id = fc.channel_id
|
||||||
WHERE fc.feed_id = ?",
|
WHERE fc.feed_id = ?",
|
||||||
self.id.0
|
self.key.0
|
||||||
).fetch_all(&pool.0).await?.into_iter()
|
).fetch_all(&pool.0).await?.into_iter()
|
||||||
.map(UnparsedChannel::parse).collect();
|
.map(UnparsedChannel::parse).collect()
|
||||||
|
|
||||||
channels
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -142,7 +134,7 @@ mod tests {
|
||||||
|
|
||||||
let f = uf.parse().unwrap();
|
let f = uf.parse().unwrap();
|
||||||
|
|
||||||
assert_eq!(f.id.0, FID);
|
assert_eq!(f.key.0, FID);
|
||||||
assert_eq!(f.title, FEED_TITLE);
|
assert_eq!(f.title, FEED_TITLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -152,9 +144,9 @@ mod tests {
|
||||||
let pool = adapter.get_pool();
|
let pool = adapter.get_pool();
|
||||||
let feed = setup_feed(pool).await;
|
let feed = setup_feed(pool).await;
|
||||||
|
|
||||||
let gotten_feed = Feed::get(pool, feed.id).await.unwrap();
|
let gotten_feed = Feed::get(pool, feed.key).await.unwrap();
|
||||||
|
|
||||||
assert_eq!(feed.id, gotten_feed.id);
|
assert_eq!(feed.key, gotten_feed.key);
|
||||||
assert_eq!(feed.title, gotten_feed.title);
|
assert_eq!(feed.title, gotten_feed.title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -163,9 +155,9 @@ mod tests {
|
||||||
let adapter = setup_adapter().await;
|
let adapter = setup_adapter().await;
|
||||||
let pool = adapter.get_pool();
|
let pool = adapter.get_pool();
|
||||||
let user = User::create(pool, USERNAME).await.unwrap();
|
let user = User::create(pool, USERNAME).await.unwrap();
|
||||||
let feed = Feed::create(pool, user.id(), FEED_TITLE).await.unwrap();
|
let feed = Feed::create(pool, user.key(), FEED_TITLE).await.unwrap();
|
||||||
|
|
||||||
assert!(feed.id().0 > 0);
|
assert!(feed.key().0 > 0);
|
||||||
assert_eq!(feed.title(), FEED_TITLE);
|
assert_eq!(feed.title(), FEED_TITLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,9 +168,9 @@ mod tests {
|
||||||
let pool = adapter.get_pool();
|
let pool = adapter.get_pool();
|
||||||
let feed = setup_feed(pool).await;
|
let feed = setup_feed(pool).await;
|
||||||
|
|
||||||
Feed::update_title(pool, feed.id(), NEW_FEED_TITLE).await.unwrap();
|
Feed::update_title(pool, feed.key(), NEW_FEED_TITLE).await.unwrap();
|
||||||
|
|
||||||
let updated = Feed::get(pool, feed.id()).await.unwrap();
|
let updated = Feed::get(pool, feed.key()).await.unwrap();
|
||||||
assert_eq!(updated.title(), NEW_FEED_TITLE);
|
assert_eq!(updated.title(), NEW_FEED_TITLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -189,12 +181,12 @@ mod tests {
|
||||||
let feed = setup_feed(pool).await;
|
let feed = setup_feed(pool).await;
|
||||||
let channel = setup_channel(pool).await;
|
let channel = setup_channel(pool).await;
|
||||||
|
|
||||||
feed.add_channel(pool, channel.id()).await.unwrap();
|
feed.add_channel(pool, channel.key()).await.unwrap();
|
||||||
|
|
||||||
let channels = feed.get_channels(pool).await.unwrap();
|
let channels = feed.get_channels(pool).await.unwrap();
|
||||||
let gotten_channel = &channels[0];
|
let gotten_channel = &channels[0];
|
||||||
|
|
||||||
assert_eq!(gotten_channel.id().0, channel.id().0);
|
assert_eq!(gotten_channel.key().0, channel.key().0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
@ -207,8 +199,8 @@ mod tests {
|
||||||
let url2 = Url::parse(FEED2).unwrap();
|
let url2 = Url::parse(FEED2).unwrap();
|
||||||
let channel2 = Channel::get_or_create(pool, url2).await.unwrap();
|
let channel2 = Channel::get_or_create(pool, url2).await.unwrap();
|
||||||
|
|
||||||
feed.add_channel(pool, channel1.id()).await.unwrap();
|
feed.add_channel(pool, channel1.key()).await.unwrap();
|
||||||
feed.add_channel(pool, channel2.id()).await.unwrap();
|
feed.add_channel(pool, channel2.key()).await.unwrap();
|
||||||
|
|
||||||
let channels = feed.get_channels(pool).await.unwrap();
|
let channels = feed.get_channels(pool).await.unwrap();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use crate::{
|
||||||
ChannelKey,
|
ChannelKey,
|
||||||
Feed,
|
Feed,
|
||||||
FeedKey,
|
FeedKey,
|
||||||
|
FeedChannelKey,
|
||||||
Item,
|
Item,
|
||||||
},
|
},
|
||||||
score::{
|
score::{
|
||||||
|
|
@ -26,8 +27,10 @@ pub struct UnparsedFeedChannel {
|
||||||
impl UnparsedFeedChannel {
|
impl UnparsedFeedChannel {
|
||||||
pub fn parse(self) -> Result<FeedChannel> {
|
pub fn parse(self) -> Result<FeedChannel> {
|
||||||
Ok(FeedChannel {
|
Ok(FeedChannel {
|
||||||
channel_id: ChannelKey(self.channel_id),
|
key: FeedChannelKey {
|
||||||
feed_id: FeedKey(self.feed_id),
|
feed_key: FeedKey(self.feed_id),
|
||||||
|
channel_key: ChannelKey(self.channel_id),
|
||||||
|
},
|
||||||
initial_score: Score::new(self.initial_score),
|
initial_score: Score::new(self.initial_score),
|
||||||
gravity: Gravity::new(self.gravity),
|
gravity: Gravity::new(self.gravity),
|
||||||
boost: Boost::new(self.boost),
|
boost: Boost::new(self.boost),
|
||||||
|
|
@ -36,8 +39,7 @@ impl UnparsedFeedChannel {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FeedChannel {
|
pub struct FeedChannel {
|
||||||
channel_id: ChannelKey,
|
key: FeedChannelKey,
|
||||||
feed_id: FeedKey,
|
|
||||||
initial_score: Score,
|
initial_score: Score,
|
||||||
gravity: Gravity,
|
gravity: Gravity,
|
||||||
boost: Boost,
|
boost: Boost,
|
||||||
|
|
@ -45,10 +47,10 @@ pub struct FeedChannel {
|
||||||
|
|
||||||
impl FeedChannel {
|
impl FeedChannel {
|
||||||
pub async fn get_channel(&self, pool: &AdapterPool) -> Result<Channel> {
|
pub async fn get_channel(&self, pool: &AdapterPool) -> Result<Channel> {
|
||||||
Channel::get(pool, self.channel_id).await
|
Channel::get(pool, self.key.channel_key).await
|
||||||
}
|
}
|
||||||
pub async fn get_feed(&self, pool: &AdapterPool) -> Result<Feed> {
|
pub async fn get_feed(&self, pool: &AdapterPool) -> Result<Feed> {
|
||||||
Feed::get(pool, self.feed_id).await
|
Feed::get(pool, self.key.feed_key).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn add_item(
|
pub async fn add_item(
|
||||||
|
|
@ -60,14 +62,14 @@ impl FeedChannel {
|
||||||
async fn add_item_at(
|
async fn add_item_at(
|
||||||
&self, pool: &AdapterPool, item: &Item, add_at: DateTime<Utc>
|
&self, pool: &AdapterPool, item: &Item, add_at: DateTime<Utc>
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let int_item_id = item.id().0;
|
let int_item_id = item.key().0;
|
||||||
let int_initial_score = i64::from(self.initial_score);
|
let int_initial_score = i64::from(self.initial_score);
|
||||||
let string_last_updated = add_at.to_rfc2822();
|
let string_last_updated = add_at.to_rfc2822();
|
||||||
|
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"INSERT OR IGNORE INTO feed_items (feed_id, item_id, score, last_updated)
|
"INSERT OR IGNORE INTO feed_items (feed_id, item_id, score, last_updated)
|
||||||
VALUES (?, ?, ?, ?)",
|
VALUES (?, ?, ?, ?)",
|
||||||
self.feed_id.0, int_item_id, int_initial_score, string_last_updated
|
self.key.feed_key.0, int_item_id, int_initial_score, string_last_updated
|
||||||
).execute(&pool.0).await?;
|
).execute(&pool.0).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -105,8 +107,8 @@ mod tests {
|
||||||
|
|
||||||
let fc = ufc.parse().unwrap();
|
let fc = ufc.parse().unwrap();
|
||||||
|
|
||||||
assert_eq!(fc.channel_id.0, CID);
|
assert_eq!(fc.key.channel_key.0, CID);
|
||||||
assert_eq!(fc.feed_id.0, FID);
|
assert_eq!(fc.key.feed_key.0, FID);
|
||||||
assert_eq!(i64::from(fc.initial_score), IS);
|
assert_eq!(i64::from(fc.initial_score), IS);
|
||||||
assert_eq!(i64::from(fc.gravity), G);
|
assert_eq!(i64::from(fc.gravity), G);
|
||||||
assert_eq!(i64::from(fc.boost), B);
|
assert_eq!(i64::from(fc.boost), B);
|
||||||
|
|
@ -122,15 +124,17 @@ mod tests {
|
||||||
let channel = Channel::get_or_create(pool, url).await.unwrap();
|
let channel = Channel::get_or_create(pool, url).await.unwrap();
|
||||||
|
|
||||||
let fc = FeedChannel {
|
let fc = FeedChannel {
|
||||||
channel_id: channel.id(),
|
key: FeedChannelKey {
|
||||||
feed_id: FeedKey(1), // Fake Feed
|
feed_key: FeedKey(1), // Fake Feed
|
||||||
|
channel_key: channel.key(),
|
||||||
|
},
|
||||||
initial_score: Score::new(None),
|
initial_score: Score::new(None),
|
||||||
gravity: Gravity::new(None),
|
gravity: Gravity::new(None),
|
||||||
boost: Boost::new(None),
|
boost: Boost::new(None),
|
||||||
};
|
};
|
||||||
|
|
||||||
let channel_from_fc = fc.get_channel(pool).await.unwrap();
|
let channel_from_fc = fc.get_channel(pool).await.unwrap();
|
||||||
assert_eq!(channel_from_fc.id(), channel.id());
|
assert_eq!(channel_from_fc.key(), channel.key());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
@ -139,18 +143,20 @@ mod tests {
|
||||||
let pool = adapter.get_pool();
|
let pool = adapter.get_pool();
|
||||||
|
|
||||||
let user = User::create(pool, "Alice").await.unwrap();
|
let user = User::create(pool, "Alice").await.unwrap();
|
||||||
let feed = Feed::create(pool, user.id(), "My Feed").await.unwrap();
|
let feed = Feed::create(pool, user.key(), "My Feed").await.unwrap();
|
||||||
|
|
||||||
let fc = FeedChannel {
|
let fc = FeedChannel {
|
||||||
channel_id: ChannelKey(1), // Fake Channel
|
key: FeedChannelKey {
|
||||||
feed_id: feed.id(),
|
feed_key: feed.key(),
|
||||||
|
channel_key: ChannelKey(1), // Fake Channel
|
||||||
|
},
|
||||||
initial_score: Score::new(None),
|
initial_score: Score::new(None),
|
||||||
gravity: Gravity::new(None),
|
gravity: Gravity::new(None),
|
||||||
boost: Boost::new(None),
|
boost: Boost::new(None),
|
||||||
};
|
};
|
||||||
|
|
||||||
let feed_from_fc = fc.get_feed(pool).await.unwrap();
|
let feed_from_fc = fc.get_feed(pool).await.unwrap();
|
||||||
assert_eq!(feed_from_fc.id(), feed.id());
|
assert_eq!(feed_from_fc.key(), feed.key());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
@ -160,21 +166,23 @@ mod tests {
|
||||||
let pool = adapter.get_pool();
|
let pool = adapter.get_pool();
|
||||||
|
|
||||||
let user = User::create(pool, "Alice").await.unwrap();
|
let user = User::create(pool, "Alice").await.unwrap();
|
||||||
let feed = Feed::create(pool, user.id(), "My Feed").await.unwrap();
|
let feed = Feed::create(pool, user.key(), "My Feed").await.unwrap();
|
||||||
let url = Url::parse(FEED1).unwrap();
|
let url = Url::parse(FEED1).unwrap();
|
||||||
let channel = Channel::get_or_create(pool, url).await.unwrap();
|
let channel = Channel::get_or_create(pool, url).await.unwrap();
|
||||||
let fc = FeedChannel {
|
let fc = FeedChannel {
|
||||||
channel_id: channel.id(),
|
key: FeedChannelKey {
|
||||||
feed_id: feed.id(),
|
feed_key: feed.key(),
|
||||||
|
channel_key: channel.key(),
|
||||||
|
},
|
||||||
initial_score: Score::new(None),
|
initial_score: Score::new(None),
|
||||||
gravity: Gravity::new(None),
|
gravity: Gravity::new(None),
|
||||||
boost: Boost::new(None),
|
boost: Boost::new(None),
|
||||||
};
|
};
|
||||||
|
|
||||||
let item = Item::get_or_create(pool, channel.id(), "item-guid").await.unwrap();
|
let item = Item::get_or_create(pool, channel.key(), "item-guid").await.unwrap();
|
||||||
fc.add_item_at(pool, &item, dt).await.unwrap();
|
fc.add_item_at(pool, &item, dt).await.unwrap();
|
||||||
|
|
||||||
let items = feed.get_items(pool, 1, 0).await.unwrap();
|
let items = feed.get_items(pool, 1, 0).await.unwrap();
|
||||||
assert_eq!(items[0].id(), item.id());
|
assert_eq!(items[0].key(), item.key());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,101 +0,0 @@
|
||||||
use chrono::{DateTime, Utc};
|
|
||||||
use crate::{
|
|
||||||
Result,
|
|
||||||
AdapterPool,
|
|
||||||
db::{
|
|
||||||
FeedItemKey,
|
|
||||||
},
|
|
||||||
score::{
|
|
||||||
TimedScore,
|
|
||||||
UnparsedTimedScore
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct UnparsedFeedItem {
|
|
||||||
pub item_id: i64,
|
|
||||||
pub feed_id: i64,
|
|
||||||
pub score: i64,
|
|
||||||
pub last_updated: String,
|
|
||||||
pub boosted_at: Option<String>,
|
|
||||||
}
|
|
||||||
impl UnparsedFeedItem {
|
|
||||||
pub fn parse(self) -> Result<FeedItem> {
|
|
||||||
Ok(FeedItem {
|
|
||||||
key: FeedItemKey {
|
|
||||||
feed_id: self.feed_id,
|
|
||||||
item_id: self.item_id,
|
|
||||||
},
|
|
||||||
score: (UnparsedTimedScore {
|
|
||||||
value: self.score,
|
|
||||||
last_updated: DateTime::parse_from_rfc2822(&self.last_updated)?
|
|
||||||
.with_timezone(&Utc),
|
|
||||||
last_boosted: self.boosted_at.as_deref()
|
|
||||||
.map(DateTime::parse_from_rfc2822)
|
|
||||||
.transpose()?
|
|
||||||
.map(|dt| dt.with_timezone(&Utc)),
|
|
||||||
}).parse(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct FeedItem {
|
|
||||||
key: FeedItemKey,
|
|
||||||
score: TimedScore,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FeedItem {
|
|
||||||
pub fn key(&self) -> FeedItemKey { self.key }
|
|
||||||
pub fn score(&self) -> TimedScore { self.score.clone() }
|
|
||||||
|
|
||||||
pub async fn archive(
|
|
||||||
&self, pool: &AdapterPool
|
|
||||||
) -> Result<()> {
|
|
||||||
sqlx::query!(
|
|
||||||
"UPDATE feed_items
|
|
||||||
SET archived = ?
|
|
||||||
WHERE feed_id = ? AND item_id = ?",
|
|
||||||
true, self.key.feed_id, self.key.item_id
|
|
||||||
).execute(&pool.0).await?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn update_score(
|
|
||||||
pool: &AdapterPool, key: FeedItemKey, new_score: TimedScore
|
|
||||||
) -> Result<()> {
|
|
||||||
let unparsed_score = UnparsedTimedScore::unparse(new_score);
|
|
||||||
let last_updated = unparsed_score.last_updated.to_rfc2822();
|
|
||||||
let boosted_at = unparsed_score.last_boosted.map(|lb| lb.to_rfc2822());
|
|
||||||
|
|
||||||
sqlx::query!(
|
|
||||||
"UPDATE feed_items
|
|
||||||
SET score = ?, last_updated = ?, boosted_at = ?
|
|
||||||
WHERE feed_id = ? AND item_id = ?",
|
|
||||||
unparsed_score.value, last_updated, boosted_at, key.feed_id, key.item_id
|
|
||||||
).execute(&pool.0).await?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use crate::test_utils::get_datetime;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn parse_feed_item() {
|
|
||||||
let dt = get_datetime();
|
|
||||||
let upi = UnparsedFeedItem {
|
|
||||||
item_id: 1,
|
|
||||||
feed_id: 2,
|
|
||||||
score: 5,
|
|
||||||
last_updated: dt.to_string(),
|
|
||||||
boosted_at: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let fi = upi.parse().unwrap();
|
|
||||||
assert_eq!(fi.key.item_id, 1);
|
|
||||||
assert_eq!(fi.key.feed_id, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -5,7 +5,6 @@ use crate::{
|
||||||
ChannelKey,
|
ChannelKey,
|
||||||
ItemKey,
|
ItemKey,
|
||||||
},
|
},
|
||||||
fetch::FetchedRSSItem,
|
|
||||||
};
|
};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
|
|
||||||
|
|
@ -22,7 +21,7 @@ pub struct UnparsedItem {
|
||||||
impl UnparsedItem {
|
impl UnparsedItem {
|
||||||
pub fn parse(self) -> Result<Item> {
|
pub fn parse(self) -> Result<Item> {
|
||||||
Ok(Item {
|
Ok(Item {
|
||||||
id: ItemKey(self.id),
|
key: ItemKey(self.id),
|
||||||
channel_id: ChannelKey(self.channel_id),
|
channel_id: ChannelKey(self.channel_id),
|
||||||
fetched_at: match self.fetched_at {
|
fetched_at: match self.fetched_at {
|
||||||
Some(dt_str) => Some(DateTime::parse_from_rfc2822(&dt_str)?
|
Some(dt_str) => Some(DateTime::parse_from_rfc2822(&dt_str)?
|
||||||
|
|
@ -38,10 +37,9 @@ impl UnparsedItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Item {
|
pub struct Item {
|
||||||
id: ItemKey,
|
key: ItemKey,
|
||||||
channel_id: ChannelKey,
|
channel_id: ChannelKey,
|
||||||
|
|
||||||
#[allow(dead_code)] // TODO: Use for score decay calculations later
|
|
||||||
fetched_at: Option<DateTime<Utc>>,
|
fetched_at: Option<DateTime<Utc>>,
|
||||||
title: Option<String>,
|
title: Option<String>,
|
||||||
description: Option<String>,
|
description: Option<String>,
|
||||||
|
|
@ -49,7 +47,7 @@ pub struct Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Item {
|
impl Item {
|
||||||
pub fn id(&self) -> ItemKey { self.id }
|
pub fn key(&self) -> ItemKey { self.key }
|
||||||
pub fn channel(&self) -> ChannelKey { self.channel_id }
|
pub fn channel(&self) -> ChannelKey { self.channel_id }
|
||||||
pub fn title(&self) -> Option<&str> { self.title.as_deref() }
|
pub fn title(&self) -> Option<&str> { self.title.as_deref() }
|
||||||
pub fn description(&self) -> Option<&str> { self.description.as_deref() }
|
pub fn description(&self) -> Option<&str> { self.description.as_deref() }
|
||||||
|
|
@ -71,26 +69,6 @@ impl Item {
|
||||||
|
|
||||||
item
|
item
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update_content(
|
|
||||||
&self, pool: &AdapterPool, fetched: &FetchedRSSItem, fetched_at: &DateTime<Utc>
|
|
||||||
) -> Result<()> {
|
|
||||||
let title = fetched.title();
|
|
||||||
let description = fetched.description();
|
|
||||||
let content = fetched.content();
|
|
||||||
let string_fetched_at = fetched_at.to_rfc2822();
|
|
||||||
|
|
||||||
sqlx::query!(
|
|
||||||
"UPDATE items
|
|
||||||
SET title = ?, description = ?, content = ?,
|
|
||||||
fetched_at = ?
|
|
||||||
WHERE id = ?",
|
|
||||||
title, description, content, string_fetched_at,
|
|
||||||
self.id.0
|
|
||||||
).execute(&pool.0).await?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
@ -120,7 +98,7 @@ mod tests {
|
||||||
};
|
};
|
||||||
let item = raw_item.parse().unwrap();
|
let item = raw_item.parse().unwrap();
|
||||||
|
|
||||||
assert_eq!(item.id.0, ITEM_ID);
|
assert_eq!(item.key.0, ITEM_ID);
|
||||||
assert_eq!(item.channel_id.0, CHANNEL_ID);
|
assert_eq!(item.channel_id.0, CHANNEL_ID);
|
||||||
assert_eq!(item.fetched_at, Some(date));
|
assert_eq!(item.fetched_at, Some(date));
|
||||||
assert_eq!(item.title, Some(ITEM_TITLE.to_string()));
|
assert_eq!(item.title, Some(ITEM_TITLE.to_string()));
|
||||||
|
|
@ -136,9 +114,9 @@ mod tests {
|
||||||
let pool = adapter.get_pool();
|
let pool = adapter.get_pool();
|
||||||
let channel = setup_channel(pool).await;
|
let channel = setup_channel(pool).await;
|
||||||
|
|
||||||
let item1 = Item::get_or_create(pool, channel.id(), ITEM_GUID).await.unwrap();
|
let item1 = Item::get_or_create(pool, channel.key(), ITEM_GUID).await.unwrap();
|
||||||
let item2 = Item::get_or_create(pool, channel.id(), ITEM_GUID).await.unwrap();
|
let item2 = Item::get_or_create(pool, channel.key(), ITEM_GUID).await.unwrap();
|
||||||
|
|
||||||
assert_eq!(item1.id(), item2.id());
|
assert_eq!(item1.key(), item2.key());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,60 +15,52 @@ pub struct UnparsedUser {
|
||||||
impl UnparsedUser {
|
impl UnparsedUser {
|
||||||
pub fn parse(self) -> Result<User> {
|
pub fn parse(self) -> Result<User> {
|
||||||
Ok(User {
|
Ok(User {
|
||||||
id: UserKey(self.id),
|
key: UserKey(self.id),
|
||||||
name: self.name
|
name: self.name
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct User {
|
pub struct User {
|
||||||
id: UserKey,
|
key: UserKey,
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl User {
|
impl User {
|
||||||
pub fn id(&self) -> UserKey { self.id }
|
pub fn key(&self) -> UserKey { self.key }
|
||||||
pub fn name(&self) -> &str { &self.name }
|
pub fn name(&self) -> &str { &self.name }
|
||||||
|
|
||||||
pub async fn get(pool: &AdapterPool, id: UserKey) -> Result<Self> {
|
pub async fn get(pool: &AdapterPool, key: UserKey) -> Result<Self> {
|
||||||
let user = sqlx::query_as!(
|
sqlx::query_as!(
|
||||||
UnparsedUser,
|
UnparsedUser,
|
||||||
"SELECT id, name FROM users WHERE id = ?",
|
"SELECT id, name FROM users WHERE id = ?",
|
||||||
id.0
|
key.0
|
||||||
).fetch_one(&pool.0).await?.parse();
|
).fetch_one(&pool.0).await?.parse()
|
||||||
|
|
||||||
user
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_all(pool: &AdapterPool) -> Result<Vec<Self>> {
|
pub async fn get_all(pool: &AdapterPool) -> Result<Vec<Self>> {
|
||||||
let users: Result<Vec<Self>> = sqlx::query_as!(
|
sqlx::query_as!(
|
||||||
UnparsedUser,
|
UnparsedUser,
|
||||||
"SELECT id, name FROM users"
|
"SELECT id, name FROM users"
|
||||||
).fetch_all(&pool.0).await?.into_iter().map(UnparsedUser::parse).collect();
|
).fetch_all(&pool.0).await?.into_iter().map(UnparsedUser::parse).collect()
|
||||||
|
|
||||||
users
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create(pool: &AdapterPool, name: &str) -> Result<Self> {
|
pub async fn create(pool: &AdapterPool, name: &str) -> Result<Self> {
|
||||||
let result = sqlx::query!(
|
sqlx::query_as!(
|
||||||
|
UnparsedUser,
|
||||||
"INSERT INTO users (name)
|
"INSERT INTO users (name)
|
||||||
VALUES (?)
|
VALUES (?)
|
||||||
RETURNING id, name",
|
RETURNING id, name",
|
||||||
name
|
name
|
||||||
).fetch_one(&pool.0).await?;
|
).fetch_one(&pool.0).await?.parse()
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
id: UserKey(result.id),
|
|
||||||
name: result.name,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update_name(
|
pub async fn update_name(
|
||||||
pool: &AdapterPool, id: UserKey, new_name: &str
|
pool: &AdapterPool, key: UserKey, new_name: &str
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"UPDATE users SET name = ? WHERE id = ?",
|
"UPDATE users SET name = ? WHERE id = ?",
|
||||||
new_name, id.0
|
new_name, key.0
|
||||||
).execute(&pool.0).await?;
|
).execute(&pool.0).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -78,7 +70,7 @@ impl User {
|
||||||
let feeds: Result<Vec<Feed>> = sqlx::query_as!(
|
let feeds: Result<Vec<Feed>> = sqlx::query_as!(
|
||||||
UnparsedFeed,
|
UnparsedFeed,
|
||||||
"SELECT id, title FROM feeds WHERE user_id = ?",
|
"SELECT id, title FROM feeds WHERE user_id = ?",
|
||||||
self.id.0
|
self.key.0
|
||||||
).fetch_all(&pool.0).await?.into_iter()
|
).fetch_all(&pool.0).await?.into_iter()
|
||||||
.map(UnparsedFeed::parse).collect();
|
.map(UnparsedFeed::parse).collect();
|
||||||
|
|
||||||
|
|
@ -106,7 +98,7 @@ mod tests {
|
||||||
};
|
};
|
||||||
|
|
||||||
let user = unparsed_user.parse().unwrap();
|
let user = unparsed_user.parse().unwrap();
|
||||||
assert_eq!(user.id.0, UID);
|
assert_eq!(user.key.0, UID);
|
||||||
assert_eq!(user.name, USERNAME);
|
assert_eq!(user.name, USERNAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,9 +108,9 @@ mod tests {
|
||||||
let pool = adapter.get_pool();
|
let pool = adapter.get_pool();
|
||||||
let new_user = User::create(pool, USERNAME).await.unwrap();
|
let new_user = User::create(pool, USERNAME).await.unwrap();
|
||||||
|
|
||||||
let fetched_user = User::get(pool, new_user.id).await.unwrap();
|
let fetched_user = User::get(pool, new_user.key).await.unwrap();
|
||||||
assert_eq!(fetched_user.name, USERNAME);
|
assert_eq!(fetched_user.name, USERNAME);
|
||||||
assert_eq!(fetched_user.id.0, 1);
|
assert_eq!(fetched_user.key.0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
@ -142,7 +134,7 @@ mod tests {
|
||||||
let user = User::create(pool, USERNAME).await.unwrap();
|
let user = User::create(pool, USERNAME).await.unwrap();
|
||||||
|
|
||||||
assert_eq!(user.name, USERNAME);
|
assert_eq!(user.name, USERNAME);
|
||||||
assert_eq!(user.id.0, 1);
|
assert_eq!(user.key.0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
|
@ -164,9 +156,9 @@ mod tests {
|
||||||
let pool = adapter.get_pool();
|
let pool = adapter.get_pool();
|
||||||
|
|
||||||
let user = User::create(pool, USERNAME).await.unwrap();
|
let user = User::create(pool, USERNAME).await.unwrap();
|
||||||
User::update_name(pool, user.id, NEW_USERNAME).await.unwrap();
|
User::update_name(pool, user.key, NEW_USERNAME).await.unwrap();
|
||||||
|
|
||||||
let updated = User::get(pool, user.id).await.unwrap();
|
let updated = User::get(pool, user.key).await.unwrap();
|
||||||
assert_eq!(updated.name, NEW_USERNAME);
|
assert_eq!(updated.name, NEW_USERNAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -177,7 +169,7 @@ mod tests {
|
||||||
|
|
||||||
let user1 = User::create(pool, USERNAME).await.unwrap();
|
let user1 = User::create(pool, USERNAME).await.unwrap();
|
||||||
User::create(pool, USERNAME2).await.unwrap();
|
User::create(pool, USERNAME2).await.unwrap();
|
||||||
let status = User::update_name(pool, user1.id, USERNAME2).await;
|
let status = User::update_name(pool, user1.key, USERNAME2).await;
|
||||||
|
|
||||||
assert!(status.is_err());
|
assert!(status.is_err());
|
||||||
}
|
}
|
||||||
|
|
@ -187,8 +179,8 @@ mod tests {
|
||||||
let adapter = setup_adapter().await;
|
let adapter = setup_adapter().await;
|
||||||
let pool = adapter.get_pool();
|
let pool = adapter.get_pool();
|
||||||
let user = User::create(pool, USERNAME).await.unwrap();
|
let user = User::create(pool, USERNAME).await.unwrap();
|
||||||
Feed::create(pool, user.id, FEED_TITLE).await.unwrap();
|
Feed::create(pool, user.key, FEED_TITLE).await.unwrap();
|
||||||
Feed::create(pool, user.id, FEED_TITLE2).await.unwrap();
|
Feed::create(pool, user.key, FEED_TITLE2).await.unwrap();
|
||||||
|
|
||||||
let feeds = user.get_feeds(pool).await.unwrap();
|
let feeds = user.get_feeds(pool).await.unwrap();
|
||||||
assert_eq!(feeds.len(), 2);
|
assert_eq!(feeds.len(), 2);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
Result,
|
Result,
|
||||||
db::{Channel, ChannelId},
|
db::Channel,
|
||||||
AdapterClient,
|
AdapterClient,
|
||||||
};
|
};
|
||||||
use reqwest::Url;
|
use reqwest::Url;
|
||||||
|
|
@ -60,10 +60,6 @@ impl FetchedRSSChannel {
|
||||||
pub async fn fetch_channel(
|
pub async fn fetch_channel(
|
||||||
client: &AdapterClient, channel: Channel
|
client: &AdapterClient, channel: Channel
|
||||||
) -> Result<Option<Self>> {
|
) -> Result<Option<Self>> {
|
||||||
if channel.should_skip_fetch() {
|
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
|
|
||||||
let bytestream = client.0.get(channel.link().clone())
|
let bytestream = client.0.get(channel.link().clone())
|
||||||
.send().await?
|
.send().await?
|
||||||
.bytes().await?;
|
.bytes().await?;
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@ pub const ITEM_TITLE: &str = "My Item!";
|
||||||
pub const ITEM_DESC: &str = "My Item's description";
|
pub const ITEM_DESC: &str = "My Item's description";
|
||||||
pub const ITEM_CONT: &str = "The content of my Item";
|
pub const ITEM_CONT: &str = "The content of my Item";
|
||||||
|
|
||||||
|
|
||||||
pub fn get_datetime() -> DateTime<Utc> {
|
pub fn get_datetime() -> DateTime<Utc> {
|
||||||
Utc.with_ymd_and_hms(2020,1,1,0,0,0).unwrap()
|
Utc.with_ymd_and_hms(2020,1,1,0,0,0).unwrap()
|
||||||
}
|
}
|
||||||
|
|
@ -49,5 +48,5 @@ pub async fn setup_channel(pool: &AdapterPool) -> Channel {
|
||||||
|
|
||||||
pub async fn setup_feed(pool: &AdapterPool) -> Feed {
|
pub async fn setup_feed(pool: &AdapterPool) -> Feed {
|
||||||
let user = User::create(pool, USERNAME).await.unwrap();
|
let user = User::create(pool, USERNAME).await.unwrap();
|
||||||
Feed::create(pool, user.id(), FEED_TITLE).await.unwrap()
|
Feed::create(pool, user.key(), FEED_TITLE).await.unwrap()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue