diff --git a/.cargo/config b/.cargo/config deleted file mode 100644 index bff29e6e1..000000000 --- a/.cargo/config +++ /dev/null @@ -1,2 +0,0 @@ -[build] -rustflags = ["--cfg", "tokio_unstable"] diff --git a/.dockerignore b/.dockerignore index 5982307c0..43381f7b7 100644 --- a/.dockerignore +++ b/.dockerignore @@ -5,4 +5,4 @@ api_tests ansible tests *.sh -pictrs \ No newline at end of file +pictrs diff --git a/.gitignore b/.gitignore index 6883b4eca..07a838201 100644 --- a/.gitignore +++ b/.gitignore @@ -20,7 +20,6 @@ query_testing/**/reports/*.json api_tests/node_modules api_tests/.yalc api_tests/yalc.lock -api_tests/test.png api_tests/pict-rs # pictrs data diff --git a/.woodpecker.yml b/.woodpecker.yml index 29e5939b5..1ae2df457 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -6,7 +6,8 @@ variables: - &slow_check_paths - path: # rust source code - - "**/*.rs" + - "crates/**" + - "src/**" - "**/Cargo.toml" - "Cargo.lock" # database migrations @@ -60,7 +61,7 @@ steps: image: rustlang/rust:nightly environment: # store cargo data in repo folder so that it gets cached between steps - CARGO_HOME: .cargo + CARGO_HOME: .cargo_home commands: # need make existing toolchain available - cargo +nightly fmt -- --check @@ -75,6 +76,14 @@ steps: - cargo binstall -y cargo-machete - cargo machete + ignored_files: + group: format + image: alpine:3 + commands: + - apk add git + - IGNORED=$(git ls-files --cached -i --exclude-standard) + - if [[ "$IGNORED" ]]; then echo "Ignored files present:\n$IGNORED\n"; exit 1; fi + restore-cache: image: meltwater/drone-cache:v1 pull: true @@ -92,7 +101,7 @@ steps: cache_key: "rust-cache" path-style: true mount: - - ".cargo" + - ".cargo_home" - "target" - "api_tests/node_modules" secrets: @@ -103,7 +112,7 @@ steps: check_api_common_default_features: image: *rust_image environment: - CARGO_HOME: .cargo + CARGO_HOME: .cargo_home commands: - cargo check --package lemmy_api_common when: *slow_check_paths @@ -111,7 +120,7 @@ steps: lemmy_api_common_doesnt_depend_on_diesel: image: *rust_image environment: - CARGO_HOME: .cargo + CARGO_HOME: .cargo_home commands: - "! cargo tree -p lemmy_api_common --no-default-features -i diesel" when: *slow_check_paths @@ -119,7 +128,7 @@ steps: lemmy_api_common_works_with_wasm: image: *rust_image environment: - CARGO_HOME: .cargo + CARGO_HOME: .cargo_home commands: - "rustup target add wasm32-unknown-unknown" - "cargo check --target wasm32-unknown-unknown -p lemmy_api_common" @@ -128,7 +137,7 @@ steps: check_defaults_hjson_updated: image: *rust_image environment: - CARGO_HOME: .cargo + CARGO_HOME: .cargo_home commands: - export LEMMY_CONFIG_LOCATION=./config/config.hjson - ./scripts/update_config_defaults.sh config/defaults_current.hjson @@ -138,7 +147,7 @@ steps: check_diesel_schema: image: willsquire/diesel-cli environment: - CARGO_HOME: .cargo + CARGO_HOME: .cargo_home DATABASE_URL: postgres://lemmy:password@database:5432/lemmy commands: - diesel migration run @@ -149,7 +158,7 @@ steps: check_diesel_migration_revertable: image: willsquire/diesel-cli environment: - CARGO_HOME: .cargo + CARGO_HOME: .cargo_home DATABASE_URL: postgres://lemmy:password@database:5432/lemmy commands: - diesel migration run @@ -159,7 +168,7 @@ steps: cargo_clippy: image: *rust_image environment: - CARGO_HOME: .cargo + CARGO_HOME: .cargo_home commands: # when adding new clippy lints, make sure to also add them in scripts/lint.sh - rustup component add clippy @@ -169,7 +178,7 @@ steps: cargo_build: image: *rust_image environment: - CARGO_HOME: .cargo + CARGO_HOME: .cargo_home commands: - cargo build - mv target/debug/lemmy_server target/lemmy_server @@ -181,7 +190,7 @@ steps: environment: LEMMY_DATABASE_URL: postgres://lemmy:password@database:5432/lemmy RUST_BACKTRACE: "1" - CARGO_HOME: .cargo + CARGO_HOME: .cargo_home commands: - export LEMMY_CONFIG_LOCATION=../../config/config.hjson - cargo test --workspace --no-fail-fast @@ -218,7 +227,7 @@ steps: region: us-east-1 path-style: true mount: - - ".cargo" + - ".cargo_home" - "target" - "api_tests/node_modules" secrets: @@ -233,9 +242,7 @@ steps: settings: repo: dessalines/lemmy dockerfile: docker/Dockerfile - # TODO fix arm build: see: https://woodpecker.join-lemmy.org/repos/129/pipeline/2888/20 - # platforms: linux/amd64,linux/arm64 - platforms: linux/amd64 + platforms: linux/amd64, linux/arm64 build_args: - RUST_RELEASE_MODE=release tag: ${CI_COMMIT_TAG} @@ -255,6 +262,19 @@ steps: when: event: cron + # using https://github.com/pksunkara/cargo-workspaces + publish_to_crates_io: + image: *rust_image + commands: + - 'echo "pub const VERSION: &str = \"$(git describe --tag)\";" > "crates/utils/src/version.rs"' + - cargo install cargo-workspaces + - cp -r migrations crates/db_schema/ + - cargo login "$CARGO_API_TOKEN" + - cargo workspaces publish --from-git --allow-dirty --no-verify --allow-branch "${CI_COMMIT_TAG}" --yes custom "${CI_COMMIT_TAG}" + secrets: [cargo_api_token] + when: + event: tag + notify_on_failure: image: alpine:3 commands: diff --git a/Cargo.lock b/Cargo.lock index 5dc623073..4a32818e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,9 +10,9 @@ checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" [[package]] name = "activitypub_federation" -version = "0.5.0-beta.5" +version = "0.5.0-beta.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3d9484e58e121ce93b84407e077f5888526a8edccb8a8447d14e3ff611aaa3" +checksum = "0e0aafb8ad437a019bac2e11d47fad6131974dace1855640a09d0e71d26571c1" dependencies = [ "activitystreams-kinds", "actix-web", @@ -29,7 +29,7 @@ dependencies = [ "http-signature-normalization", "http-signature-normalization-reqwest", "httpdate", - "itertools 0.10.5", + "itertools 0.12.0", "moka", "once_cell", "openssl", @@ -75,9 +75,9 @@ dependencies = [ [[package]] name = "actix-cors" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b340e9cfa5b08690aae90fb61beb44e9b06f44fe3d0f93781aaa58cfba86245e" +checksum = "0346d8c1f762b41b458ed3145eea914966bb9ad20b9be0d6d463b20d45586370" dependencies = [ "actix-utils", "actix-web", @@ -90,15 +90,15 @@ dependencies = [ [[package]] name = "actix-form-data" -version = "0.7.0-beta.4" +version = "0.7.0-beta.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2163627f82eef55c4551f3e58ba0da92d733fa3afe8d0c13986a9ba00d1f9f7" +checksum = "02564e87c7a34fe7877d6b60259413ea04412b91abbabd3c2c71610e24800d0d" dependencies = [ "actix-multipart", - "actix-rt", "actix-web", "futures-core", "mime", + "streem", "thiserror", "tokio", "tracing", @@ -115,7 +115,7 @@ dependencies = [ "actix-service", "actix-tls", "actix-utils", - "ahash 0.8.5", + "ahash", "base64 0.21.5", "bitflags 2.4.1", "brotli", @@ -151,7 +151,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -196,7 +196,6 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28f32d40287d3f402ae0028a9d54bef51af15c8769492826a69d28f81893151d" dependencies = [ - "actix-macros", "futures-core", "tokio", ] @@ -241,7 +240,7 @@ dependencies = [ "futures-core", "impl-more", "pin-project-lite", - "rustls 0.21.8", + "rustls 0.21.10", "rustls-webpki", "tokio", "tokio-rustls 0.23.4", @@ -276,7 +275,7 @@ dependencies = [ "actix-tls", "actix-utils", "actix-web-codegen", - "ahash 0.8.5", + "ahash", "bytes", "bytestring", "cfg-if", @@ -310,7 +309,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -328,6 +327,19 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "actix-web-prom" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f23f332a652836b8f3a6876103c70c9ed436d0e69fa779ab5d7f57b1d5c8d488" +dependencies = [ + "actix-web", + "futures-core", + "pin-project-lite", + "prometheus", + "regex", +] + [[package]] name = "addr2line" version = "0.21.0" @@ -345,20 +357,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.7.7" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - -[[package]] -name = "ahash" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7d5a2cecb58716e47d67d5703a249964b14c7be1ec3cad3affc295b2d1c35d" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" dependencies = [ "cfg-if", "getrandom", @@ -391,6 +392,12 @@ dependencies = [ "alloc-no-stdlib", ] +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + [[package]] name = "android-tzdata" version = "0.1.1" @@ -408,9 +415,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" dependencies = [ "anstyle", "anstyle-parse", @@ -428,30 +435,30 @@ checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -481,9 +488,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f658e2baef915ba0f26f1f7c42bfb8e12f532a01f449a090ded75ae7a07e9ba2" +checksum = "bc2d0cfb2a7388d34f590e76686704c494ed7aaceed62ee1ba35cbf363abc2a5" dependencies = [ "flate2", "futures-core", @@ -492,26 +499,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "async-io" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" -dependencies = [ - "async-lock", - "autocfg", - "cfg-if", - "concurrent-queue", - "futures-lite", - "log", - "parking", - "polling", - "rustix 0.37.26", - "slab", - "socket2 0.4.10", - "waker-fn", -] - [[package]] name = "async-lock" version = "2.8.0" @@ -540,7 +527,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -551,7 +538,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -567,6 +554,12 @@ dependencies = [ "quick-xml 0.30.0", ] +[[package]] +name = "atomic" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" + [[package]] name = "autocfg" version = "1.1.0" @@ -633,6 +626,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "barrel" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad9e605929a6964efbec5ac0884bd0fe93f12a3b1eb271f52c251316640c68d9" + [[package]] name = "base32" version = "0.4.0" @@ -732,9 +731,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "2.5.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da74e2b81409b1b743f8f0c62cc6254afefb8b8e50bbfe3735550f7aeefa3448" +checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -772,9 +771,9 @@ checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "bytestring" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "238e4886760d98c4f899360c834fa93e62cf7f721ac3c2da375cbdf4b8679aae" +checksum = "74d80203ea6b29df88012294f62733de21cfeab47f17b41af3a38bc30a03ee72" dependencies = [ "bytes", ] @@ -804,9 +803,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12024c4645c97566567129c204f65d5815a8c9aecf30fcbe682b2fe034996d36" +checksum = "e34637b3140142bdf929fb439e8aa4ebad7651ebf7b1080b3930aa16ac1459ff" dependencies = [ "serde", ] @@ -861,6 +860,16 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "chumsky" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eebd66744a15ded14960ab4ccdbfb51ad3b81f51f3f04a80adac98c985396c9" +dependencies = [ + "hashbrown 0.14.3", + "stacker", +] + [[package]] name = "cipher" version = "0.4.4" @@ -873,9 +882,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.7" +version = "4.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" +checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" dependencies = [ "clap_builder", "clap_derive", @@ -883,9 +892,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.7" +version = "4.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" +checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" dependencies = [ "anstream", "anstyle", @@ -902,7 +911,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -937,9 +946,9 @@ dependencies = [ [[package]] name = "color-spantrace" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce" +checksum = "cd6be1b2a7e382e2b98b43b2adcca6bb0e465af0bdd38123873ae61eb17a72c2" dependencies = [ "once_cell", "owo-colors", @@ -969,28 +978,17 @@ dependencies = [ "memchr", ] -[[package]] -name = "concurrent-queue" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "config" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d379af7f68bfc21714c6c7dea883544201741d2ce8274bb12fa54f89507f52a7" +checksum = "23738e11972c7643e4ec947840fc463b6a571afcd3e735bdfce7d03c7a784aca" dependencies = [ "async-trait", - "json5", "lazy_static", "nom", "pathdiff", "ron", - "rust-ini", "serde", "serde_json", "toml 0.5.11", @@ -1016,8 +1014,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd326812b3fd01da5bb1af7d340d0d555fd3d4b641e7f1dfcf5962a902952787" dependencies = [ "futures-core", - "prost 0.12.1", - "prost-types 0.12.1", + "prost 0.12.3", + "prost-types 0.12.3", "tonic 0.10.2", "tracing-core", ] @@ -1058,7 +1056,7 @@ dependencies = [ "futures-task", "hdrhistogram", "humantime", - "prost-types 0.12.1", + "prost-types 0.12.3", "serde", "serde_json", "thread_local", @@ -1115,9 +1113,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -1125,15 +1123,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fbc60abd742b35f2492f808e1abbb83d45f72db402e14c55057edc9c7b1e9e4" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" dependencies = [ "libc", ] @@ -1258,7 +1256,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -1291,7 +1289,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core 0.20.3", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -1301,7 +1299,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown 0.14.2", + "hashbrown 0.14.3", "lock_api", "once_cell", "parking_lot_core 0.9.9", @@ -1320,6 +1318,18 @@ dependencies = [ "tokio", ] +[[package]] +name = "deadpool" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb84100978c1c7b37f09ed3ce3e5f843af02c2a2c431bae5b19230dad2c1b490" +dependencies = [ + "async-trait", + "deadpool-runtime", + "num_cpus", + "tokio", +] + [[package]] name = "deadpool-runtime" version = "0.1.3" @@ -1331,9 +1341,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc" dependencies = [ "powerfmt", "serde", @@ -1396,18 +1406,18 @@ dependencies = [ [[package]] name = "deser-hjson" -version = "1.2.0" +version = "2.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e1ab99fef4d11b2de312a0650bbf312fb48aa11a00084f35b27bf8c57d4cad" +checksum = "7d94aac4095c08ded7e4b9ba7fc2b2929f11b94bb96897ca188b0f64e01688e1" dependencies = [ "serde", ] [[package]] name = "diesel" -version = "2.1.3" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2268a214a6f118fce1838edba3d1561cf0e78d8de785475957a580a7f8c69d33" +checksum = "62c6fcf842f17f8c78ecf7c81d75c5ce84436b41ee07e03f490fbb5f5a8731d8" dependencies = [ "bitflags 2.4.1", "byteorder", @@ -1416,17 +1426,18 @@ dependencies = [ "itoa", "pq-sys", "serde_json", + "time", "uuid", ] [[package]] name = "diesel-async" -version = "0.3.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e7974099f0d9bde0e010dd3a673555276a474f3362a7a52ab535a57b7c5056" +checksum = "acada1517534c92d3f382217b485db8a8638f111b0e3f2a2a8e26165050f77be" dependencies = [ "async-trait", - "deadpool", + "deadpool 0.9.5", "diesel", "futures-util", "scoped-futures", @@ -1443,7 +1454,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -1454,7 +1465,7 @@ checksum = "c7267437d5b12df60ae29bd97f8d120f1c3a6272d6f213551afa56bbb2ecfbb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -1466,7 +1477,7 @@ dependencies = [ "diesel_table_macro_syntax", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -1496,7 +1507,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc5557efc453706fed5e4fa85006fe9817c224c3f480a34c7e5959fd700921c5" dependencies = [ - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -1519,12 +1530,6 @@ dependencies = [ "chrono", ] -[[package]] -name = "dlv-list" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" - [[package]] name = "doku" version = "0.21.1" @@ -1557,9 +1562,9 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" [[package]] name = "dyn-clone" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd" +checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" [[package]] name = "either" @@ -1673,22 +1678,22 @@ checksum = "b5320ae4c3782150d900b79807611a59a99fc9a1d61d686faafc24b93fc8d7ca" [[package]] name = "enum-map" -version = "2.7.0" +version = "2.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53337c2dbf26a3c31eccc73a37b10c1614e8d4ae99b6a50d553e8936423c1f16" +checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9" dependencies = [ "enum-map-derive", ] [[package]] name = "enum-map-derive" -version = "0.14.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04d0b288e3bb1d861c4403c1774a6f7a798781dfc519b3647df2a3dd4ae95f25" +checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -1723,12 +1728,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1748,9 +1753,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "eyre" -version = "0.6.8" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" +checksum = "8bbb8258be8305fb0237d7b295f47bb24ff1b136a535f473baf40e70468515aa" dependencies = [ "indenter", "once_cell", @@ -1781,15 +1786,6 @@ dependencies = [ "regex", ] -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - [[package]] name = "fastrand" version = "2.0.1" @@ -1798,9 +1794,9 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "fdeflate" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10" +checksum = "64d6dafc854908ff5da46ff3f8f473c6984119a2876a383a860246dd7841a868" dependencies = [ "simd-adler32", ] @@ -1821,6 +1817,18 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "spin 0.9.8", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1844,9 +1852,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -1873,9 +1881,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" dependencies = [ "futures-channel", "futures-core", @@ -1888,9 +1896,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" dependencies = [ "futures-core", "futures-sink", @@ -1898,15 +1906,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" dependencies = [ "futures-core", "futures-task", @@ -1915,53 +1923,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" - -[[package]] -name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" dependencies = [ "futures-channel", "futures-core", @@ -2009,9 +2002,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "glob" @@ -2021,9 +2014,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "h2" -version = "0.3.21" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" dependencies = [ "bytes", "fnv", @@ -2031,7 +2024,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 1.9.3", + "indexmap 2.1.0", "slab", "tokio", "tokio-util", @@ -2043,9 +2036,6 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.7", -] [[package]] name = "hashbrown" @@ -2053,22 +2043,26 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ff8ae62cd3a9102e5637afc8452c55acf3844001bd5374e0b0bd7b6616c038" dependencies = [ - "ahash 0.8.5", + "ahash", ] [[package]] name = "hashbrown" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash", + "allocator-api2", +] [[package]] name = "hdrhistogram" -version = "7.5.2" +version = "7.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f19b9f54f7c7f55e31401bb647626ce0cf0f67b0004982ce815b3ee72a02aa8" +checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d" dependencies = [ - "base64 0.13.1", + "base64 0.21.5", "byteorder", "flate2", "nom", @@ -2171,9 +2165,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", @@ -2182,9 +2176,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -2202,10 +2196,11 @@ dependencies = [ [[package]] name = "http-signature-normalization-reqwest" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c382c69a07b21accae86298d520579403af6479b1cd1c389e3ee11f01d48627" +checksum = "10cfb84663420ec12c4422820bfdf5e8e5e57467892587f43ac432e73ebce880" dependencies = [ + "async-trait", "base64 0.13.1", "http-signature-normalization", "httpdate", @@ -2260,14 +2255,14 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http", "hyper", - "rustls 0.21.8", + "rustls 0.21.10", "tokio", "tokio-rustls 0.24.1", ] @@ -2338,9 +2333,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -2385,12 +2380,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", - "hashbrown 0.14.2", + "hashbrown 0.14.3", "serde", ] @@ -2448,10 +2443,19 @@ dependencies = [ ] [[package]] -name = "itoa" -version = "1.0.9" +name = "itertools" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "jni" @@ -2484,24 +2488,13 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" dependencies = [ "wasm-bindgen", ] -[[package]] -name = "json5" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" -dependencies = [ - "pest", - "pest_derive", - "serde", -] - [[package]] name = "jsonwebtoken" version = "8.3.0" @@ -2530,7 +2523,7 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lemmy_api" -version = "0.19.0-rc.6" +version = "0.19.1-rc.2" dependencies = [ "activitypub_federation", "actix-web", @@ -2558,7 +2551,7 @@ dependencies = [ [[package]] name = "lemmy_api_common" -version = "0.19.0-rc.6" +version = "0.19.1-rc.2" dependencies = [ "activitypub_federation", "actix-web", @@ -2597,16 +2590,20 @@ dependencies = [ [[package]] name = "lemmy_api_crud" -version = "0.19.0-rc.6" +version = "0.19.1-rc.2" dependencies = [ "activitypub_federation", "actix-web", + "anyhow", "bcrypt", + "futures", "lemmy_api_common", "lemmy_db_schema", "lemmy_db_views", "lemmy_db_views_actor", "lemmy_utils", + "moka", + "once_cell", "tracing", "url", "uuid", @@ -2615,7 +2612,7 @@ dependencies = [ [[package]] name = "lemmy_apub" -version = "0.19.0-rc.6" +version = "0.19.1-rc.2" dependencies = [ "activitypub_federation", "actix-web", @@ -2629,7 +2626,7 @@ dependencies = [ "html2md", "html2text", "http", - "itertools 0.11.0", + "itertools 0.12.0", "lemmy_api_common", "lemmy_db_schema", "lemmy_db_views", @@ -2652,13 +2649,13 @@ dependencies = [ [[package]] name = "lemmy_db_schema" -version = "0.19.0-rc.6" +version = "0.19.1-rc.2" dependencies = [ "activitypub_federation", "async-trait", "bcrypt", "chrono", - "deadpool", + "deadpool 0.10.0", "diesel", "diesel-async", "diesel-derive-enum", @@ -2669,7 +2666,7 @@ dependencies = [ "lemmy_utils", "once_cell", "regex", - "rustls 0.21.8", + "rustls 0.21.10", "serde", "serde_json", "serde_with", @@ -2688,9 +2685,10 @@ dependencies = [ [[package]] name = "lemmy_db_views" -version = "0.19.0-rc.6" +version = "0.19.1-rc.2" dependencies = [ "actix-web", + "chrono", "diesel", "diesel-async", "diesel_ltree", @@ -2706,7 +2704,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_actor" -version = "0.19.0-rc.6" +version = "0.19.1-rc.2" dependencies = [ "chrono", "diesel", @@ -2723,7 +2721,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_moderator" -version = "0.19.0-rc.6" +version = "0.19.1-rc.2" dependencies = [ "diesel", "diesel-async", @@ -2735,7 +2733,7 @@ dependencies = [ [[package]] name = "lemmy_federate" -version = "0.19.0-rc.6" +version = "0.19.1-rc.2" dependencies = [ "activitypub_federation", "anyhow", @@ -2758,7 +2756,7 @@ dependencies = [ [[package]] name = "lemmy_routes" -version = "0.19.0-rc.6" +version = "0.19.1-rc.2" dependencies = [ "activitypub_federation", "actix-web", @@ -2783,11 +2781,12 @@ dependencies = [ [[package]] name = "lemmy_server" -version = "0.19.0-rc.6" +version = "0.19.1-rc.2" dependencies = [ "activitypub_federation", "actix-cors", "actix-web", + "actix-web-prom", "chrono", "clap", "clokwerk", @@ -2816,7 +2815,7 @@ dependencies = [ "tracing", "tracing-actix-web", "tracing-error", - "tracing-log", + "tracing-log 0.2.0", "tracing-opentelemetry 0.19.0", "tracing-subscriber", "url", @@ -2824,7 +2823,7 @@ dependencies = [ [[package]] name = "lemmy_utils" -version = "0.19.0-rc.6" +version = "0.19.1-rc.2" dependencies = [ "actix-web", "anyhow", @@ -2835,7 +2834,7 @@ dependencies = [ "futures", "html2text", "http", - "itertools 0.11.0", + "itertools 0.12.0", "lettre", "markdown-it", "once_cell", @@ -2861,35 +2860,37 @@ dependencies = [ [[package]] name = "lettre" -version = "0.10.4" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bd09637ae3ec7bd605b8e135e757980b3968430ff2b1a4a94fb7769e50166d" +checksum = "a48c2e9831b370bc2d7233c2620298c45f3a158ed6b4b8d7416b2ada5a268fd8" dependencies = [ "async-trait", "base64 0.21.5", + "chumsky", "email-encoding", "email_address", - "fastrand 1.9.0", + "fastrand", "futures-io", "futures-util", "hostname", "httpdate", - "idna 0.3.0", + "idna 0.5.0", "mime", "native-tls", "nom", "once_cell", "quoted_printable", - "socket2 0.4.10", + "socket2 0.5.5", "tokio", "tokio-native-tls", + "url", ] [[package]] name = "libc" -version = "0.2.149" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "line-wrap" @@ -2923,21 +2924,15 @@ checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" [[package]] name = "linux-raw-sys" -version = "0.3.8" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - -[[package]] -name = "linux-raw-sys" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "local-channel" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a493488de5f18c8ffcba89eebb8532ffc562dc400490eb65b84893fae0b178" +checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" dependencies = [ "futures-core", "futures-sink", @@ -2946,9 +2941,9 @@ dependencies = [ [[package]] name = "local-waker" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e34f76eb3611940e0e7d53a9aaa4e6a3151f69541a282fd0dad5571420c53ff1" +checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" [[package]] name = "lock_api" @@ -2962,9 +2957,9 @@ dependencies = [ [[package]] name = "lodepng" -version = "3.9.1" +version = "3.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3cdccd0cf57a5d456f0656ebcff72c2e19503287e1afbf3b84382812adc0606" +checksum = "b00f56ff9bcd5721ab172b73eac8a7d4e9439f47a98581e666178dbe7df97e13" dependencies = [ "crc32fast", "fallible_collections", @@ -2996,9 +2991,9 @@ dependencies = [ [[package]] name = "markdown-it" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c44ffb00018b76ef3c6eff5e17d34b44f0bbded0b70291940564c527cba07ad8" +checksum = "181d1b4704b0a2fc6027d3f758a7eedb975dcbaab86e6794901b8cfc52af94d5" dependencies = [ "argparse", "const_format", @@ -3100,6 +3095,60 @@ dependencies = [ "autocfg", ] +[[package]] +name = "metrics" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fde3af1a009ed76a778cb84fdef9e7dbbdf5775ae3e4cc1f434a6a307f6f76c5" +dependencies = [ + "ahash", + "metrics-macros", + "portable-atomic", +] + +[[package]] +name = "metrics-exporter-prometheus" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a4964177ddfdab1e3a2b37aec7cf320e14169abb0ed73999f558136409178d5" +dependencies = [ + "base64 0.21.5", + "hyper", + "indexmap 1.9.3", + "ipnet", + "metrics", + "metrics-util", + "quanta", + "thiserror", + "tokio", +] + +[[package]] +name = "metrics-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddece26afd34c31585c74a4db0630c376df271c285d682d1e55012197830b6df" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.40", +] + +[[package]] +name = "metrics-util" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4de2ed6e491ed114b40b732e4d1659a9d53992ebd87490c44a6ffe23739d973e" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", + "hashbrown 0.13.1", + "metrics", + "num_cpus", + "quanta", + "sketches-ddsketch", +] + [[package]] name = "migrations_internals" version = "2.1.0" @@ -3155,9 +3204,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", "log", @@ -3167,12 +3216,12 @@ dependencies = [ [[package]] name = "moka" -version = "0.11.3" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa6e72583bf6830c956235bff0d5afec8cf2952f579ebad18ae7821a917d950f" +checksum = "d8017ec3548ffe7d4cef7ac0e12b044c01164a74c0f3119420faeaf13490ad8b" dependencies = [ - "async-io", "async-lock", + "async-trait", "crossbeam-channel", "crossbeam-epoch", "crossbeam-utils", @@ -3181,7 +3230,6 @@ dependencies = [ "parking_lot 0.12.1", "quanta", "rustc_version", - "scheduled-thread-pool", "skeptic", "smallvec", "tagptr", @@ -3196,6 +3244,15 @@ version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d02c0b00610773bb7fc61d85e13d86c7858cbdf00e1a120bfc41bc055dbaa0e" +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom", +] + [[package]] name = "native-tls" version = "0.2.11" @@ -3308,15 +3365,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl" -version = "0.10.59" +version = "0.10.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a257ad03cd8fb16ad4172fedf8094451e1af1c4b70097636ef2eac9a5f0cc33" +checksum = "6b8419dc8cc6d866deb801274bba2e6f8f6108c1bb7fcc10ee5ab864931dbb45" dependencies = [ "bitflags 2.4.1", "cfg-if", @@ -3335,7 +3392,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -3346,9 +3403,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.95" +version = "0.9.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40a4130519a360279579c2053038317e40eff64d13fd3f004f9e1b72b8a6aaf9" +checksum = "c3eaad34cdd97d81de97964fc7f29e2d104f483840d906ef56daa1912338460b" dependencies = [ "cc", "libc", @@ -3379,18 +3436,24 @@ version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f4b8347cc26099d3aeee044065ecc3ae11469796b4d65d065a23a584ed92a6f" dependencies = [ - "opentelemetry_api 0.19.0", + "opentelemetry_api", "opentelemetry_sdk 0.19.0", ] [[package]] name = "opentelemetry" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9591d937bc0e6d2feb6f71a559540ab300ea49955229c347a517a28d27784c54" +checksum = "1e32339a5dc40459130b3bd269e9892439f55b33e772d2a9d402a789baaf4e8a" dependencies = [ - "opentelemetry_api 0.20.0", - "opentelemetry_sdk 0.20.0", + "futures-core", + "futures-sink", + "indexmap 2.1.0", + "js-sys", + "once_cell", + "pin-project-lite", + "thiserror", + "urlencoding", ] [[package]] @@ -3413,17 +3476,17 @@ dependencies = [ [[package]] name = "opentelemetry-otlp" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e5e5a5c4135864099f3faafbe939eb4d7f9b80ebf68a8448da961b32a7c1275" +checksum = "f24cda83b20ed2433c68241f918d0f6fdec8b1d43b7a9590ab4420c5095ca930" dependencies = [ "async-trait", "futures-core", "http", - "opentelemetry-proto 0.3.0", + "opentelemetry 0.21.0", + "opentelemetry-proto 0.4.0", "opentelemetry-semantic-conventions", - "opentelemetry_api 0.20.0", - "opentelemetry_sdk 0.20.0", + "opentelemetry_sdk 0.21.1", "prost 0.11.9", "thiserror", "tokio", @@ -3445,23 +3508,23 @@ dependencies = [ [[package]] name = "opentelemetry-proto" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e3f814aa9f8c905d0ee4bde026afd3b2577a97c10e1699912e3e44f0c4cbeb" +checksum = "a2e155ce5cc812ea3d1dffbd1539aed653de4bf4882d60e6e04dcf0901d674e1" dependencies = [ - "opentelemetry_api 0.20.0", - "opentelemetry_sdk 0.20.0", + "opentelemetry 0.21.0", + "opentelemetry_sdk 0.21.1", "prost 0.11.9", "tonic 0.9.2", ] [[package]] name = "opentelemetry-semantic-conventions" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73c9f9340ad135068800e7f1b24e9e09ed9e7143f5bf8518ded3d3ec69789269" +checksum = "f5774f1ef1f982ef2a447f6ee04ec383981a3ab99c8e77a1a7b30182e65bbc84" dependencies = [ - "opentelemetry 0.20.0", + "opentelemetry 0.21.0", ] [[package]] @@ -3480,22 +3543,6 @@ dependencies = [ "urlencoding", ] -[[package]] -name = "opentelemetry_api" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a81f725323db1b1206ca3da8bb19874bbd3f57c3bcd59471bfb04525b265b9b" -dependencies = [ - "futures-channel", - "futures-util", - "indexmap 1.9.3", - "js-sys", - "once_cell", - "pin-project-lite", - "thiserror", - "urlencoding", -] - [[package]] name = "opentelemetry_sdk" version = "0.19.0" @@ -3510,7 +3557,7 @@ dependencies = [ "futures-executor", "futures-util", "once_cell", - "opentelemetry_api 0.19.0", + "opentelemetry_api", "percent-encoding", "rand", "thiserror", @@ -3520,22 +3567,21 @@ dependencies = [ [[package]] name = "opentelemetry_sdk" -version = "0.20.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa8e705a0612d48139799fcbaba0d4a90f06277153e43dd2bdc16c6f0edd8026" +checksum = "968ba3f2ca03e90e5187f5e4f46c791ef7f2c163ae87789c8ce5f5ca3b7b7de5" dependencies = [ "async-trait", "crossbeam-channel", "futures-channel", "futures-executor", "futures-util", + "glob", "once_cell", - "opentelemetry_api 0.20.0", + "opentelemetry 0.21.0", "ordered-float", "percent-encoding", "rand", - "regex", - "serde_json", "thiserror", "tokio", "tokio-stream", @@ -3543,23 +3589,13 @@ dependencies = [ [[package]] name = "ordered-float" -version = "3.9.2" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1e1c390732d15f1d48471625cd92d154e66db2c56645e29a9cd26f4699f72dc" +checksum = "a76df7075c7d4d01fdcb46c912dd17fba5b60c78ea480b475f2b6ab6f666584e" dependencies = [ "num-traits", ] -[[package]] -name = "ordered-multimap" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a" -dependencies = [ - "dlv-list", - "hashbrown 0.12.3", -] - [[package]] name = "overload" version = "0.1.1" @@ -3572,12 +3608,6 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" -[[package]] -name = "parking" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" - [[package]] name = "parking_lot" version = "0.11.2" @@ -3649,54 +3679,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" - -[[package]] -name = "pest" -version = "2.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" -dependencies = [ - "memchr", - "thiserror", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn 2.0.38", -] - -[[package]] -name = "pest_meta" -version = "2.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6" -dependencies = [ - "once_cell", - "pest", - "sha2", -] +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "phf" @@ -3742,7 +3727,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" dependencies = [ - "siphasher", + "siphasher 0.3.11", ] [[package]] @@ -3751,59 +3736,66 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" dependencies = [ - "siphasher", + "siphasher 0.3.11", ] [[package]] name = "pict-rs" -version = "0.4.5" +version = "0.5.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4abe9ff018542d54d486f8fe3ea05f7bb09dc172fdbaa08e945abf0e64b2495" +checksum = "f24eed67dd30cd04e67959b7c9a2b14c8e7c9d9a67b095eb56c70477a6eef212" dependencies = [ "actix-form-data", - "actix-rt", - "actix-server", "actix-web", "anyhow", "async-trait", + "barrel", "base64 0.21.5", "clap", "color-eyre", "config", "console-subscriber 0.2.0", "dashmap", - "futures-util", + "deadpool 0.9.5", + "diesel", + "diesel-async", + "diesel-derive-enum", + "flume", + "futures-core", "hex", "md-5", + "metrics", + "metrics-exporter-prometheus", "mime", - "num_cpus", - "once_cell", - "opentelemetry 0.20.0", - "opentelemetry-otlp 0.13.0", + "opentelemetry 0.21.0", + "opentelemetry-otlp 0.14.0", + "opentelemetry_sdk 0.21.1", "pin-project-lite", - "quick-xml 0.30.0", + "refinery", "reqwest", "reqwest-middleware", "reqwest-tracing", "rusty-s3", "serde", + "serde-tuple-vec-map", "serde_json", "serde_urlencoded", "sha2", "sled", "storage-path-generator", + "streem", "subtle", "thiserror", "time", "tokio", + "tokio-postgres", "tokio-util", - "toml 0.8.4", + "toml 0.8.8", "tracing", "tracing-actix-web", "tracing-error", - "tracing-futures", - "tracing-log", - "tracing-opentelemetry 0.21.0", + "tracing-log 0.2.0", + "tracing-opentelemetry 0.22.0", "tracing-subscriber", "url", "uuid", @@ -3826,7 +3818,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -3849,14 +3841,14 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "plist" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a4a0cfc5fb21a09dc6af4bf834cf10d4a32fccd9e2ea468c4b1751a097487aa" +checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef" dependencies = [ "base64 0.21.5", - "indexmap 1.9.3", + "indexmap 2.1.0", "line-wrap", - "quick-xml 0.30.0", + "quick-xml 0.31.0", "serde", "time", ] @@ -3875,19 +3867,23 @@ dependencies = [ ] [[package]] -name = "polling" -version = "2.8.0" +name = "portable-atomic" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" + +[[package]] +name = "postgres" +version = "0.19.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7915b33ed60abc46040cbcaa25ffa1c7ec240668e0477c4f3070786f5916d451" dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "concurrent-queue", - "libc", + "bytes", + "fallible-iterator", + "futures-util", "log", - "pin-project-lite", - "windows-sys 0.48.0", + "tokio", + "tokio-postgres", ] [[package]] @@ -3917,6 +3913,10 @@ dependencies = [ "bytes", "fallible-iterator", "postgres-protocol", + "serde", + "serde_json", + "time", + "uuid", ] [[package]] @@ -3948,9 +3948,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" dependencies = [ "unicode-ident", ] @@ -3965,7 +3965,7 @@ dependencies = [ "byteorder", "hex", "lazy_static", - "rustix 0.36.16", + "rustix 0.36.17", ] [[package]] @@ -3997,12 +3997,12 @@ dependencies = [ [[package]] name = "prost" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fdd22f3b9c31b53c060df4a0613a1c7f062d4115a2b984dd15b1858f7e340d" +checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" dependencies = [ "bytes", - "prost-derive 0.12.1", + "prost-derive 0.12.3", ] [[package]] @@ -4020,15 +4020,15 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "265baba7fabd416cf5078179f7d2cbeca4ce7a9041111900675ea7c4cb8a4c32" +checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", "itertools 0.11.0", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -4042,11 +4042,11 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e081b29f63d83a4bc75cfc9f3fe424f9156cf92d8a4f0c9407cce9a1b67327cf" +checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" dependencies = [ - "prost 0.12.1", + "prost 0.12.3", ] [[package]] @@ -4091,16 +4091,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "quick-xml" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc053f057dd768a56f62cd7e434c42c831d296968997e9ac1f76ea7c2d14c41" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "quick-xml" version = "0.30.0" @@ -4112,6 +4102,15 @@ dependencies = [ "serde", ] +[[package]] +name = "quick-xml" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +dependencies = [ + "memchr", +] + [[package]] name = "quote" version = "1.0.33" @@ -4123,9 +4122,9 @@ dependencies = [ [[package]] name = "quoted_printable" -version = "0.4.8" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3866219251662ec3b26fc217e3e05bf9c4f84325234dfb96bf0bf840889e49" +checksum = "79ec282e887b434b68c18fe5c121d38e72a5cf35119b59e54ec5b992ea9c8eb0" [[package]] name = "rand" @@ -4174,7 +4173,7 @@ checksum = "b8f439da1766942fe069954da6058b2e6c1760eb878bae76f5be9fc29f56f574" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -4186,15 +4185,6 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -4204,6 +4194,52 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "refinery" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "529664dbccc0a296947615c997a857912d72d1c44be1fafb7bae54ecfa7a8c24" +dependencies = [ + "refinery-core", + "refinery-macros", +] + +[[package]] +name = "refinery-core" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e895cb870cf06e92318cbbeb701f274d022d5ca87a16fa8244e291cd035ef954" +dependencies = [ + "async-trait", + "cfg-if", + "lazy_static", + "log", + "postgres", + "regex", + "serde", + "siphasher 1.0.0", + "thiserror", + "time", + "tokio", + "tokio-postgres", + "toml 0.7.8", + "url", + "walkdir", +] + +[[package]] +name = "refinery-macros" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123e8b80f8010c3ae38330c81e76938fc7adf6cdbfbaad20295bb8c22718b4f1" +dependencies = [ + "proc-macro2", + "quote", + "refinery-core", + "regex", + "syn 2.0.40", +] + [[package]] name = "regex" version = "1.10.2" @@ -4281,7 +4317,7 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.21.8", + "rustls 0.21.10", "rustls-pemfile", "serde", "serde_json", @@ -4297,7 +4333,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 0.25.2", + "webpki-roots 0.25.3", "winreg", ] @@ -4342,9 +4378,9 @@ checksum = "4389f1d5789befaf6029ebd9f7dac4af7f7e3d61b69d4f30e2ac02b57e7712b0" [[package]] name = "rgb" -version = "0.8.36" +version = "0.8.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59" +checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" dependencies = [ "bytemuck", ] @@ -4372,9 +4408,9 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.5" +version = "0.17.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" +checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" dependencies = [ "cc", "getrandom", @@ -4427,16 +4463,6 @@ dependencies = [ "quick-xml 0.30.0", ] -[[package]] -name = "rust-ini" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df" -dependencies = [ - "cfg-if", - "ordered-multimap", -] - [[package]] name = "rustc-demangle" version = "0.1.23" @@ -4454,9 +4480,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.36.16" +version = "0.36.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6da3636faa25820d8648e0e31c5d519bbb01f72fdf57131f0f5f7da5fed36eab" +checksum = "305efbd14fde4139eb501df5f136994bb520b033fa9fbdce287507dc23b8c7ed" dependencies = [ "bitflags 1.3.2", "errno", @@ -4468,29 +4494,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.26" +version = "0.38.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84f3f8f960ed3b5a59055428714943298bf3fa2d4a1d53135084e0544829d995" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustix" -version = "0.38.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" dependencies = [ "bitflags 2.4.1", "errno", "libc", - "linux-raw-sys 0.4.10", - "windows-sys 0.48.0", + "linux-raw-sys 0.4.12", + "windows-sys 0.52.0", ] [[package]] @@ -4507,21 +4519,21 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.8" +version = "0.21.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "446e14c5cda4f3f30fe71863c34ec70f5ac79d6087097ad0bb433e1be5edf04c" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", - "ring 0.17.5", + "ring 0.17.7", "rustls-webpki", "sct", ] [[package]] name = "rustls-pemfile" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ "base64 0.21.5", ] @@ -4532,7 +4544,7 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.5", + "ring 0.17.7", "untrusted 0.9.0", ] @@ -4544,15 +4556,15 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "rusty-s3" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c92776b0db0fea6d7cc3abb9d0d745814c71124471a3bfd84b1265a28c06130" +checksum = "31aa883f1b986a5249641e574ca0e11ac4fb9970b009c6fbb96fedaf4fa78db8" dependencies = [ "base64 0.21.5", "hmac", "md-5", "percent-encoding", - "quick-xml 0.27.1", + "quick-xml 0.30.0", "serde", "serde_json", "sha2", @@ -4563,9 +4575,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "safemem" @@ -4591,15 +4603,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "scheduled-thread-pool" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" -dependencies = [ - "parking_lot 0.12.1", -] - [[package]] name = "scoped-futures" version = "0.1.3" @@ -4622,7 +4625,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.5", + "ring 0.17.7", "untrusted 0.9.0", ] @@ -4671,31 +4674,40 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.189" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] [[package]] -name = "serde_derive" -version = "1.0.189" +name = "serde-tuple-vec-map" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" +checksum = "a04d0ebe0de77d7d445bb729a895dcb0a288854b267ca85f030ce51cdc578c82" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.1.0", "itoa", "ryu", "serde", @@ -4741,7 +4753,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.0.2", + "indexmap 2.1.0", "serde", "serde_json", "serde_with_macros", @@ -4757,7 +4769,7 @@ dependencies = [ "darling 0.20.3", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -4782,7 +4794,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -4849,6 +4861,12 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +[[package]] +name = "siphasher" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54ac45299ccbd390721be55b412d41931911f654fa99e2cb8bfb57184b2061fe" + [[package]] name = "sitemap-rs" version = "0.2.0" @@ -4874,6 +4892,12 @@ dependencies = [ "walkdir", ] +[[package]] +name = "sketches-ddsketch" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68a406c1882ed7f29cd5e248c9848a80e7cb6ae0fea82346d2746f2f941c07e1" + [[package]] name = "slab" version = "0.4.9" @@ -4901,9 +4925,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "smart-default" @@ -4913,7 +4937,7 @@ checksum = "0eb01866308440fc64d6c44d9e86c5cc17adfe33c4d6eed55da9145044d0ffc1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -4947,6 +4971,9 @@ name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] [[package]] name = "stacker" @@ -4967,6 +4994,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f11d35dae9818c4313649da4a97c8329e29357a7fe584526c1d78f5b63ef836" +[[package]] +name = "streem" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8b0c8184b0fe05b37dd75d66205195cd57563c6c87cb92134a025a34a6ab34" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "string_cache" version = "0.8.7" @@ -5032,7 +5069,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -5054,9 +5091,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.38" +version = "2.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "13fa70a4ee923979ffb522cacce59d34421ebdea5625e1073c4326ef9d2dd42e" dependencies = [ "proc-macro2", "quote", @@ -5128,14 +5165,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", - "fastrand 2.0.1", - "redox_syscall 0.3.5", - "rustix 0.38.20", + "fastrand", + "redox_syscall 0.4.1", + "rustix 0.38.28", "windows-sys 0.48.0", ] @@ -5152,9 +5189,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" dependencies = [ "winapi-util", ] @@ -5176,7 +5213,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -5241,9 +5278,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.33.0" +version = "1.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +checksum = "841d45b238a16291a4e1584e61820b8ae57d696cc5015c459c229ccc6990cc1c" dependencies = [ "backtrace", "bytes", @@ -5271,13 +5308,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -5324,7 +5361,7 @@ checksum = "dd5831152cb0d3f79ef5523b357319ba154795d64c7078b2daa95a803b54057f" dependencies = [ "futures", "ring 0.16.20", - "rustls 0.21.8", + "rustls 0.21.10", "tokio", "tokio-postgres", "tokio-rustls 0.24.1", @@ -5347,7 +5384,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.8", + "rustls 0.21.10", "tokio", ] @@ -5399,14 +5436,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.4" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ef75d881185fd2df4a040793927c153d863651108a93c7e17a9e591baa95cc6" +checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.20.4", + "toml_edit 0.21.0", ] [[package]] @@ -5424,7 +5461,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.1.0", "serde", "serde_spanned", "toml_datetime", @@ -5433,11 +5470,11 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.20.4" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380f9e8120405471f7c9ad1860a713ef5ece6a670c7eae39225e477340f32fc4" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" dependencies = [ - "indexmap 2.0.2", + "indexmap 2.1.0", "serde", "serde_spanned", "toml_datetime", @@ -5522,7 +5559,7 @@ dependencies = [ "hyper-timeout", "percent-encoding", "pin-project", - "prost 0.12.1", + "prost 0.12.3", "tokio", "tokio-stream", "tower", @@ -5599,10 +5636,10 @@ checksum = "1fe0d5feac3f4ca21ba33496bcb1ccab58cca6412b1405ae80f0581541e0ca78" dependencies = [ "actix-web", "mutually_exclusive_features", - "opentelemetry 0.20.0", + "opentelemetry 0.21.0", "pin-project", "tracing", - "tracing-opentelemetry 0.21.0", + "tracing-opentelemetry 0.22.0", "uuid", ] @@ -5614,7 +5651,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -5658,6 +5695,17 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + [[package]] name = "tracing-opentelemetry" version = "0.16.0" @@ -5667,7 +5715,7 @@ dependencies = [ "opentelemetry 0.16.0", "tracing", "tracing-core", - "tracing-log", + "tracing-log 0.1.4", "tracing-subscriber", ] @@ -5681,24 +5729,26 @@ dependencies = [ "opentelemetry 0.19.0", "tracing", "tracing-core", - "tracing-log", + "tracing-log 0.1.4", "tracing-subscriber", ] [[package]] name = "tracing-opentelemetry" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75327c6b667828ddc28f5e3f169036cb793c3f588d83bf0f262a7f062ffed3c8" +checksum = "c67ac25c5407e7b961fafc6f7e9aa5958fd297aada2d20fa2ae1737357e55596" dependencies = [ + "js-sys", "once_cell", - "opentelemetry 0.20.0", - "opentelemetry_sdk 0.20.0", + "opentelemetry 0.21.0", + "opentelemetry_sdk 0.21.1", "smallvec", "tracing", "tracing-core", - "tracing-log", + "tracing-log 0.2.0", "tracing-subscriber", + "web-time", ] [[package]] @@ -5713,9 +5763,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers", "nu-ansi-term", @@ -5728,21 +5778,21 @@ dependencies = [ "thread_local", "tracing", "tracing-core", - "tracing-log", + "tracing-log 0.2.0", "tracing-serde", ] [[package]] name = "triomphe" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee8098afad3fb0c54a9007aab6804558410503ad676d4633f9c2559a00ac0f" +checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3" [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "ts-rs" @@ -5764,7 +5814,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", "termcolor", ] @@ -5785,7 +5835,7 @@ checksum = "29a3151c41d0b13e3d011f98adc24434560ef06673a155a6c7f66b9879eecce2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] @@ -5794,12 +5844,6 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" -[[package]] -name = "ucd-trie" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" - [[package]] name = "unicase" version = "2.7.0" @@ -5811,9 +5855,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" [[package]] name = "unicode-general-category" @@ -5862,12 +5906,12 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", - "idna 0.4.0", + "idna 0.5.0", "percent-encoding", "serde", ] @@ -5886,9 +5930,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "utf8-width" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1" +checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" [[package]] name = "utf8parse" @@ -5898,10 +5942,11 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.5.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc" +checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" dependencies = [ + "atomic", "getrandom", "serde", ] @@ -5924,12 +5969,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "waker-fn" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" - [[package]] name = "walkdir" version = "2.4.0" @@ -5957,9 +5996,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -5967,24 +6006,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" dependencies = [ "cfg-if", "js-sys", @@ -5994,9 +6033,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -6004,22 +6043,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" [[package]] name = "wasm-streams" @@ -6045,9 +6084,19 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57099a701fb3a8043f993e8228dc24229c7b942e2b009a1b962e54489ba1d3bf" dependencies = [ "js-sys", "wasm-bindgen", @@ -6086,7 +6135,7 @@ version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" dependencies = [ - "ring 0.17.5", + "ring 0.17.7", "untrusted 0.9.0", ] @@ -6101,9 +6150,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.2" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" +checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" [[package]] name = "whoami" @@ -6173,6 +6222,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -6203,6 +6261,21 @@ dependencies = [ "windows_x86_64_msvc 0.48.5", ] +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -6215,6 +6288,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -6227,6 +6306,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -6239,6 +6324,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -6251,6 +6342,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -6263,6 +6360,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -6275,6 +6378,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -6288,10 +6397,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] -name = "winnow" -version = "0.5.17" +name = "windows_x86_64_msvc" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "winnow" +version = "0.5.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c830786f7720c2fd27a1a0e27a709dbd3c4d009b56d098fc742d4f4eab91fe2" dependencies = [ "memchr", ] @@ -6334,29 +6449,29 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.13" +version = "0.7.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ffc046c9f849405a42c87e82e2f2f861d1f0a06b855910c76c2bd1e87be900c" +checksum = "306dca4455518f1f31635ec308b6b3e4eb1b11758cefafc782827d0aa7acb5c7" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.13" +version = "0.7.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "246c000cfc5f942bac7ff99fde24a9ebb589d92e024bc758c6c733c15a02a73e" +checksum = "be912bf68235a88fbefd1b73415cb218405958d1655b2ece9035a19920bdf6ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.38", + "syn 2.0.40", ] [[package]] name = "zeroize" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" [[package]] name = "zstd" diff --git a/Cargo.toml b/Cargo.toml index fa8b865e0..c47625d9b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [workspace.package] -version = "0.19.0-rc.6" +version = "0.19.1-rc.2" +publish = false edition = "2021" description = "A link aggregator for the fediverse" license = "AGPL-3.0" @@ -84,23 +85,23 @@ unused_self = "deny" unwrap_used = "deny" [workspace.dependencies] -lemmy_api = { version = "=0.19.0-rc.6", path = "./crates/api" } -lemmy_api_crud = { version = "=0.19.0-rc.6", path = "./crates/api_crud" } -lemmy_apub = { version = "=0.19.0-rc.6", path = "./crates/apub" } -lemmy_utils = { version = "=0.19.0-rc.6", path = "./crates/utils" } -lemmy_db_schema = { version = "=0.19.0-rc.6", path = "./crates/db_schema" } -lemmy_api_common = { version = "=0.19.0-rc.6", path = "./crates/api_common" } -lemmy_routes = { version = "=0.19.0-rc.6", path = "./crates/routes" } -lemmy_db_views = { version = "=0.19.0-rc.6", path = "./crates/db_views" } -lemmy_db_views_actor = { version = "=0.19.0-rc.6", path = "./crates/db_views_actor" } -lemmy_db_views_moderator = { version = "=0.19.0-rc.6", path = "./crates/db_views_moderator" } -activitypub_federation = { version = "0.5.0-beta.5", default-features = false, features = [ +lemmy_api = { version = "=0.19.1-rc.2", path = "./crates/api" } +lemmy_api_crud = { version = "=0.19.1-rc.2", path = "./crates/api_crud" } +lemmy_apub = { version = "=0.19.1-rc.2", path = "./crates/apub" } +lemmy_utils = { version = "=0.19.1-rc.2", path = "./crates/utils" } +lemmy_db_schema = { version = "=0.19.1-rc.2", path = "./crates/db_schema" } +lemmy_api_common = { version = "=0.19.1-rc.2", path = "./crates/api_common" } +lemmy_routes = { version = "=0.19.1-rc.2", path = "./crates/routes" } +lemmy_db_views = { version = "=0.19.1-rc.2", path = "./crates/db_views" } +lemmy_db_views_actor = { version = "=0.19.1-rc.2", path = "./crates/db_views_actor" } +lemmy_db_views_moderator = { version = "=0.19.1-rc.2", path = "./crates/db_views_moderator" } +activitypub_federation = { version = "0.5.0-beta.6", default-features = false, features = [ "actix-web", ] } -diesel = "2.1.3" +diesel = "2.1.4" diesel_migrations = "2.1.0" -diesel-async = "0.3.2" -serde = { version = "1.0.189", features = ["derive"] } +diesel-async = "0.4.1" +serde = { version = "1.0.193", features = ["derive"] } serde_with = "3.4.0" actix-web = { version = "4.4.0", default-features = false, features = [ "macros", @@ -111,11 +112,11 @@ actix-web = { version = "4.4.0", default-features = false, features = [ "cookies", ] } tracing = "0.1.40" -tracing-actix-web = { version = "0.7.8", default-features = false } +tracing-actix-web = { version = "0.7.9", default-features = false } tracing-error = "0.2.0" -tracing-log = "0.1.4" -tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } -url = { version = "2.4.1", features = ["serde"] } +tracing-log = "0.2.0" +tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +url = { version = "2.5.0", features = ["serde"] } reqwest = { version = "0.11.22", features = ["json", "blocking", "gzip"] } reqwest-middleware = "0.2.4" reqwest-tracing = "0.4.6" @@ -123,9 +124,9 @@ clokwerk = "0.4.0" doku = { version = "0.21.1", features = ["url-2"] } bcrypt = "0.15.0" chrono = { version = "0.4.31", features = ["serde"], default-features = false } -serde_json = { version = "1.0.107", features = ["preserve_order"] } +serde_json = { version = "1.0.108", features = ["preserve_order"] } base64 = "0.21.5" -uuid = { version = "1.5.0", features = ["serde", "v4"] } +uuid = { version = "1.6.1", features = ["serde", "v4"] } async-trait = "0.1.74" captcha = "0.0.9" anyhow = { version = "1.0.75", features = [ @@ -133,26 +134,28 @@ anyhow = { version = "1.0.75", features = [ ] } # backtrace is on by default on nightly, but not stable rust diesel_ltree = "0.3.0" serial_test = "2.0.0" -tokio = { version = "1.33.0", features = ["full"] } +tokio = { version = "1.35.0", features = ["full"] } regex = "1.10.2" -once_cell = "1.18.0" +once_cell = "1.19.0" diesel-derive-newtype = "2.1.0" diesel-derive-enum = { version = "2.1.0", features = ["postgres"] } strum = "0.25.0" strum_macros = "0.25.3" -itertools = "0.11.0" -futures = "0.3.28" -http = "0.2.9" +itertools = "0.12.0" +futures = "0.3.29" +http = "0.2.11" +percent-encoding = "2.3.1" rosetta-i18n = "0.1.3" opentelemetry = { version = "0.19.0", features = ["rt-tokio"] } tracing-opentelemetry = { version = "0.19.0" } ts-rs = { version = "7.0.0", features = ["serde-compat", "chrono-impl"] } -rustls = { version = "0.21.8", features = ["dangerous_configuration"] } -futures-util = "0.3.28" +rustls = { version = "0.21.10", features = ["dangerous_configuration"] } +futures-util = "0.3.29" tokio-postgres = "0.7.10" tokio-postgres-rustls = "0.10.0" urlencoding = "2.1.3" enum-map = "2.7" +moka = { version = "0.12.1", features = ["future"] } [dependencies] lemmy_api = { workspace = true } @@ -162,7 +165,7 @@ lemmy_utils = { workspace = true } lemmy_db_schema = { workspace = true } lemmy_api_common = { workspace = true } lemmy_routes = { workspace = true } -lemmy_federate = { version = "0.19.0-rc.6", path = "crates/federate" } +lemmy_federate = { version = "0.19.1-rc.2", path = "crates/federate" } activitypub_federation = { workspace = true } diesel = { workspace = true } diesel-async = { workspace = true } @@ -182,11 +185,12 @@ tracing-opentelemetry = { workspace = true, optional = true } opentelemetry = { workspace = true, optional = true } console-subscriber = { version = "0.1.10", optional = true } opentelemetry-otlp = { version = "0.12.0", optional = true } -pict-rs = { version = "0.4.5", optional = true } +pict-rs = { version = "0.5.0-rc.2", optional = true } tokio.workspace = true -actix-cors = "0.6.4" +actix-cors = "0.6.5" futures-util = { workspace = true } chrono = { workspace = true } prometheus = { version = "0.13.3", features = ["process"] } serial_test = { workspace = true } -clap = { version = "4.4.7", features = ["derive"] } +clap = { version = "4.4.11", features = ["derive"] } +actix-web-prom = "0.7.0" diff --git a/README.md b/README.md index a3f6ceb2a..3227f74d8 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![Translation status](http://weblate.join-lemmy.org/widgets/lemmy/-/lemmy/svg-badge.svg)](http://weblate.join-lemmy.org/engage/lemmy/) [![License](https://img.shields.io/github/license/LemmyNet/lemmy.svg)](LICENSE) ![GitHub stars](https://img.shields.io/github/stars/LemmyNet/lemmy?style=social) -[![Delightful Humane Tech](https://codeberg.org/teaserbot-labs/delightful-humane-design/raw/branch/main/humane-tech-badge.svg)](https://codeberg.org/teaserbot-labs/delightful-humane-design) + diff --git a/api_tests/.eslintrc.json b/api_tests/.eslintrc.json index c48d71f94..75b1706aa 100644 --- a/api_tests/.eslintrc.json +++ b/api_tests/.eslintrc.json @@ -14,6 +14,7 @@ "@typescript-eslint/ban-ts-comment": 0, "@typescript-eslint/no-explicit-any": 0, "@typescript-eslint/explicit-module-boundary-types": 0, + "@typescript-eslint/no-var-requires": 0, "arrow-body-style": 0, "curly": 0, "eol-last": 0, diff --git a/api_tests/package.json b/api_tests/package.json index bd6681535..4d3e57d21 100644 --- a/api_tests/package.json +++ b/api_tests/package.json @@ -19,17 +19,17 @@ "api-test-image": "jest -i image.spec.ts" }, "devDependencies": { - "@types/jest": "^29.5.8", - "@types/node": "^20.9.0", - "@typescript-eslint/eslint-plugin": "^6.10.0", - "@typescript-eslint/parser": "^6.10.0", + "@types/jest": "^29.5.11", + "@types/node": "^20.10.4", + "@typescript-eslint/eslint-plugin": "^6.14.0", + "@typescript-eslint/parser": "^6.14.0", "download-file-sync": "^1.0.4", - "eslint": "^8.53.0", + "eslint": "^8.55.0", "eslint-plugin-prettier": "^5.0.1", "jest": "^29.5.0", - "lemmy-js-client": "0.19.0-alpha.18", - "prettier": "^3.0.0", + "lemmy-js-client": "0.19.0", + "prettier": "^3.1.1", "ts-jest": "^29.1.0", - "typescript": "^5.0.4" + "typescript": "^5.3.3" } } diff --git a/api_tests/pict-rs b/api_tests/pict-rs deleted file mode 100755 index 521d0fdc3..000000000 Binary files a/api_tests/pict-rs and /dev/null differ diff --git a/api_tests/prepare-drone-federation-test.sh b/api_tests/prepare-drone-federation-test.sh index 0f7591b31..4710168d9 100755 --- a/api_tests/prepare-drone-federation-test.sh +++ b/api_tests/prepare-drone-federation-test.sh @@ -9,7 +9,7 @@ export RUST_LOG="warn,lemmy_server=debug,lemmy_federate=debug,lemmy_api=debug,le export LEMMY_TEST_FAST_FEDERATION=1 # by default, the persistent federation queue has delays in the scale of 30s-5min # pictrs setup -if ! [ -f "pict-rs" ]; then +if [ ! -f "pict-rs" ]; then curl "https://git.asonix.dog/asonix/pict-rs/releases/download/v0.5.0-beta.2/pict-rs-linux-amd64" -o api_tests/pict-rs chmod +x api_tests/pict-rs fi diff --git a/api_tests/src/comment.spec.ts b/api_tests/src/comment.spec.ts index 915c87a57..4655a81ff 100644 --- a/api_tests/src/comment.spec.ts +++ b/api_tests/src/comment.spec.ts @@ -39,7 +39,6 @@ import { delay, } from "./shared"; import { CommentView, CommunityView } from "lemmy-js-client"; -import { LemmyHttp } from "lemmy-js-client"; let betaCommunity: CommunityView | undefined; let postOnAlphaRes: PostResponse; @@ -345,17 +344,26 @@ test("Federated comment like", async () => { test("Reply to a comment from another instance, get notification", async () => { await alpha.markAllAsRead(); - let betaCommunity = (await resolveBetaCommunity(alpha)).community; + let betaCommunity = ( + await waitUntil( + () => resolveBetaCommunity(alpha), + c => !!c.community?.community.instance_id, + ) + ).community; if (!betaCommunity) { throw "Missing beta community"; } + const postOnAlphaRes = await createPost(alpha, betaCommunity.community.id); // Create a root-level trunk-branch comment on alpha let commentRes = await createComment(alpha, postOnAlphaRes.post_view.post.id); // find that comment id on beta let betaComment = ( - await resolveComment(beta, commentRes.comment_view.comment) + await waitUntil( + () => resolveComment(beta, commentRes.comment_view.comment), + c => c.comment?.counts.score === 1, + ) ).comment; if (!betaComment) { @@ -406,7 +414,10 @@ test("Reply to a comment from another instance, get notification", async () => { expect(alphaUnreadCountRes.replies).toBeGreaterThanOrEqual(1); // check inbox of replies on alpha, fetching read/unread both - let alphaRepliesRes = await getReplies(alpha); + let alphaRepliesRes = await waitUntil( + () => getReplies(alpha), + r => r.replies.length > 0, + ); const alphaReply = alphaRepliesRes.replies.find( r => r.comment.id === alphaComment.comment.id, ); diff --git a/api_tests/src/community.spec.ts b/api_tests/src/community.spec.ts index 3b6697a68..b4a58bb7b 100644 --- a/api_tests/src/community.spec.ts +++ b/api_tests/src/community.spec.ts @@ -32,7 +32,7 @@ import { resolveBetaCommunity, longDelay, } from "./shared"; -import { EditSite, LemmyHttp } from "lemmy-js-client"; +import { EditSite } from "lemmy-js-client"; beforeAll(setupLogins); diff --git a/api_tests/src/image.spec.ts b/api_tests/src/image.spec.ts index e6407ec1a..569507d07 100644 --- a/api_tests/src/image.spec.ts +++ b/api_tests/src/image.spec.ts @@ -7,7 +7,7 @@ import { PurgePost, } from "lemmy-js-client"; import { - alpha, + alphaImage, alphaUrl, beta, betaUrl, @@ -18,22 +18,22 @@ import { setupLogins, unfollowRemotes, } from "./shared"; -import fs = require("fs"); const downloadFileSync = require("download-file-sync"); beforeAll(setupLogins); afterAll(() => { - unfollowRemotes(alpha); + unfollowRemotes(alphaImage); }); test("Upload image and delete it", async () => { - // upload test image - const upload_image = fs.readFileSync("test.png"); + // Upload test image. We use a simple string buffer as pictrs doesnt require an actual image + // in testing mode. + const upload_image = Buffer.from("test"); const upload_form: UploadImage = { image: upload_image, }; - const upload = await alpha.uploadImage(upload_form); + const upload = await alphaImage.uploadImage(upload_form); expect(upload.files![0].file).toBeDefined(); expect(upload.files![0].delete_token).toBeDefined(); expect(upload.url).toBeDefined(); @@ -48,7 +48,7 @@ test("Upload image and delete it", async () => { token: upload.files![0].delete_token, filename: upload.files![0].file, }; - const delete_ = await alpha.deleteImage(delete_form); + const delete_ = await alphaImage.deleteImage(delete_form); expect(delete_).toBe(true); // ensure that image is deleted @@ -57,10 +57,10 @@ test("Upload image and delete it", async () => { }); test("Purge user, uploaded image removed", async () => { - let user = await registerUser(alpha, alphaUrl); + let user = await registerUser(alphaImage, alphaUrl); // upload test image - const upload_image = fs.readFileSync("test.png"); + const upload_image = Buffer.from("test"); const upload_form: UploadImage = { image: upload_image, }; @@ -79,7 +79,7 @@ test("Purge user, uploaded image removed", async () => { const purge_form: PurgePerson = { person_id: site.my_user!.local_user_view.person.id, }; - const delete_ = await alpha.purgePerson(purge_form); + const delete_ = await alphaImage.purgePerson(purge_form); expect(delete_.success).toBe(true); // ensure that image is deleted @@ -91,7 +91,7 @@ test("Purge post, linked image removed", async () => { let user = await registerUser(beta, betaUrl); // upload test image - const upload_image = fs.readFileSync("test.png"); + const upload_image = Buffer.from("test"); const upload_form: UploadImage = { image: upload_image, }; diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index f92fedf6c..72029157d 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -39,7 +39,7 @@ import { loginUser, } from "./shared"; import { PostView } from "lemmy-js-client/dist/types/PostView"; -import { LemmyHttp, ResolveObject } from "lemmy-js-client"; +import { ResolveObject } from "lemmy-js-client"; let betaCommunity: CommunityView | undefined; diff --git a/api_tests/src/private_message.spec.ts b/api_tests/src/private_message.spec.ts index 08c519df7..75dcaee33 100644 --- a/api_tests/src/private_message.spec.ts +++ b/api_tests/src/private_message.spec.ts @@ -10,6 +10,7 @@ import { deletePrivateMessage, unfollowRemotes, waitUntil, + reportPrivateMessage, } from "./shared"; let recipient_id: number; @@ -109,3 +110,42 @@ test("Delete a private message", async () => { betaPms1.private_messages.length, ); }); + +test("Create a private message report", async () => { + let pmRes = await createPrivateMessage(alpha, recipient_id); + let betaPms1 = await waitUntil( + () => listPrivateMessages(beta), + m => + !!m.private_messages.find( + e => + e.private_message.ap_id === + pmRes.private_message_view.private_message.ap_id, + ), + ); + let betaPm = betaPms1.private_messages[0]; + expect(betaPm).toBeDefined(); + + // Make sure that only the recipient can report it, so this should fail + await expect( + reportPrivateMessage( + alpha, + pmRes.private_message_view.private_message.id, + "a reason", + ), + ).rejects.toStrictEqual(Error("couldnt_create_report")); + + // This one should pass + let reason = "another reason"; + let report = await reportPrivateMessage( + beta, + betaPm.private_message.id, + reason, + ); + + expect(report.private_message_report_view.private_message.id).toBe( + betaPm.private_message.id, + ); + expect(report.private_message_report_view.private_message_report.reason).toBe( + reason, + ); +}); diff --git a/api_tests/src/shared.ts b/api_tests/src/shared.ts index ace3a6fac..fe51fb046 100644 --- a/api_tests/src/shared.ts +++ b/api_tests/src/shared.ts @@ -4,12 +4,14 @@ import { BlockInstance, BlockInstanceResponse, CommunityId, + CreatePrivateMessageReport, GetReplies, GetRepliesResponse, GetUnreadCountResponse, InstanceId, LemmyHttp, PostView, + PrivateMessageReportResponse, SuccessResponse, } from "lemmy-js-client"; import { CreatePost } from "lemmy-js-client/dist/types/CreatePost"; @@ -75,17 +77,20 @@ import { GetPersonDetailsResponse } from "lemmy-js-client/dist/types/GetPersonDe import { GetPersonDetails } from "lemmy-js-client/dist/types/GetPersonDetails"; import { ListingType } from "lemmy-js-client/dist/types/ListingType"; +export const fetchFunction = fetch; + export let alphaUrl = "http://127.0.0.1:8541"; export let betaUrl = "http://127.0.0.1:8551"; export let gammaUrl = "http://127.0.0.1:8561"; export let deltaUrl = "http://127.0.0.1:8571"; export let epsilonUrl = "http://127.0.0.1:8581"; -export let alpha = new LemmyHttp(alphaUrl); -export let beta = new LemmyHttp(betaUrl); -export let gamma = new LemmyHttp(gammaUrl); -export let delta = new LemmyHttp(deltaUrl); -export let epsilon = new LemmyHttp(epsilonUrl); +export let alpha = new LemmyHttp(alphaUrl, { fetchFunction }); +export let alphaImage = new LemmyHttp(alphaUrl); +export let beta = new LemmyHttp(betaUrl, { fetchFunction }); +export let gamma = new LemmyHttp(gammaUrl, { fetchFunction }); +export let delta = new LemmyHttp(deltaUrl, { fetchFunction }); +export let epsilon = new LemmyHttp(epsilonUrl, { fetchFunction }); export let betaAllowedInstances = [ "lemmy-alpha", @@ -135,6 +140,7 @@ export async function setupLogins() { resEpsilon, ]); alpha.setHeaders({ Authorization: `Bearer ${res[0].jwt ?? ""}` }); + alphaImage.setHeaders({ Authorization: `Bearer ${res[0].jwt ?? ""}` }); beta.setHeaders({ Authorization: `Bearer ${res[1].jwt ?? ""}` }); gamma.setHeaders({ Authorization: `Bearer ${res[2].jwt ?? ""}` }); delta.setHeaders({ Authorization: `Bearer ${res[3].jwt ?? ""}` }); @@ -325,6 +331,7 @@ export async function getComments( post_id: post_id, type_: listingType, sort: "New", + limit: 50, }; return api.getComments(form); } @@ -776,6 +783,18 @@ export async function reportComment( return api.createCommentReport(form); } +export async function reportPrivateMessage( + api: LemmyHttp, + private_message_id: number, + reason: string, +): Promise { + let form: CreatePrivateMessageReport = { + private_message_id, + reason, + }; + return api.createPrivateMessageReport(form); +} + export async function listCommentReports( api: LemmyHttp, ): Promise { @@ -789,6 +808,7 @@ export function getPosts( ): Promise { let form: GetPosts = { type_: listingType, + limit: 50, }; return api.getPosts(form); } @@ -857,6 +877,7 @@ export function getCommentParentId(comment: Comment): number | undefined { if (split.length > 1) { return Number(split[split.length - 2]); } else { + console.log(`Failed to extract comment parent id from ${comment.path}`); return undefined; } } diff --git a/api_tests/src/user.spec.ts b/api_tests/src/user.spec.ts index c3c7d0bec..ccfc5e1fe 100644 --- a/api_tests/src/user.spec.ts +++ b/api_tests/src/user.spec.ts @@ -18,6 +18,7 @@ import { saveUserSettings, getPost, getComments, + fetchFunction, } from "./shared"; import { LemmyHttp, SaveUserSettings } from "lemmy-js-client"; import { GetPosts } from "lemmy-js-client/dist/types/GetPosts"; @@ -114,6 +115,7 @@ test("Delete user", async () => { test("Requests with invalid auth should be treated as unauthenticated", async () => { let invalid_auth = new LemmyHttp(alphaUrl, { headers: { Authorization: "Bearer foobar" }, + fetchFunction, }); let site = await getSite(invalid_auth); expect(site.my_user).toBeUndefined(); diff --git a/api_tests/test.png b/api_tests/test.png deleted file mode 100644 index b01d868e9..000000000 Binary files a/api_tests/test.png and /dev/null differ diff --git a/api_tests/yarn.lock b/api_tests/yarn.lock index 9a272efee..d2cf2ab26 100644 --- a/api_tests/yarn.lock +++ b/api_tests/yarn.lock @@ -314,10 +314,10 @@ resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.9.1.tgz#449dfa81a57a1d755b09aa58d826c1262e4283b4" integrity sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA== -"@eslint/eslintrc@^2.1.3": - version "2.1.3" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.3.tgz#797470a75fe0fbd5a53350ee715e85e87baff22d" - integrity sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA== +"@eslint/eslintrc@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" + integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== dependencies: ajv "^6.12.4" debug "^4.3.2" @@ -329,10 +329,10 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.53.0": - version "8.53.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.53.0.tgz#bea56f2ed2b5baea164348ff4d5a879f6f81f20d" - integrity sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w== +"@eslint/js@8.55.0": + version "8.55.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.55.0.tgz#b721d52060f369aa259cf97392403cb9ce892ec6" + integrity sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA== "@humanwhocodes/config-array@^0.11.13": version "0.11.13" @@ -704,10 +704,10 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/jest@^29.5.8": - version "29.5.8" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.8.tgz#ed5c256fe2bc7c38b1915ee5ef1ff24a3427e120" - integrity sha512-fXEFTxMV2Co8ZF5aYFJv+YeA08RTYJfhtN5c9JSv/mFEMe+xxjufCb+PHL+bJcMs/ebPUsBu+UNTEz+ydXrR6g== +"@types/jest@^29.5.11": + version "29.5.11" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.11.tgz#0c13aa0da7d0929f078ab080ae5d4ced80fa2f2c" + integrity sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ== dependencies: expect "^29.0.0" pretty-format "^29.0.0" @@ -722,10 +722,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.8.0.tgz#10ddf0119cf20028781c06d7115562934e53f745" integrity sha512-LzcWltT83s1bthcvjBmiBvGJiiUe84NWRHkw+ZV6Fr41z2FbIzvc815dk2nQ3RAKMuN2fkenM/z3Xv2QzEpYxQ== -"@types/node@^20.9.0": - version "20.9.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.9.0.tgz#bfcdc230583aeb891cf51e73cfdaacdd8deae298" - integrity sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw== +"@types/node@^20.10.4": + version "20.10.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.4.tgz#b246fd84d55d5b1b71bf51f964bd514409347198" + integrity sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg== dependencies: undici-types "~5.26.4" @@ -751,16 +751,16 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^6.10.0": - version "6.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.10.0.tgz#cfe2bd34e26d2289212946b96ab19dcad64b661a" - integrity sha512-uoLj4g2OTL8rfUQVx2AFO1hp/zja1wABJq77P6IclQs6I/m9GLrm7jCdgzZkvWdDCQf1uEvoa8s8CupsgWQgVg== +"@typescript-eslint/eslint-plugin@^6.14.0": + version "6.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.14.0.tgz#fc1ab5f23618ba590c87e8226ff07a760be3dd7b" + integrity sha512-1ZJBykBCXaSHG94vMMKmiHoL0MhNHKSVlcHVYZNw+BKxufhqQVTOawNpwwI1P5nIFZ/4jLVop0mcY6mJJDFNaw== dependencies: "@eslint-community/regexpp" "^4.5.1" - "@typescript-eslint/scope-manager" "6.10.0" - "@typescript-eslint/type-utils" "6.10.0" - "@typescript-eslint/utils" "6.10.0" - "@typescript-eslint/visitor-keys" "6.10.0" + "@typescript-eslint/scope-manager" "6.14.0" + "@typescript-eslint/type-utils" "6.14.0" + "@typescript-eslint/utils" "6.14.0" + "@typescript-eslint/visitor-keys" "6.14.0" debug "^4.3.4" graphemer "^1.4.0" ignore "^5.2.4" @@ -768,72 +768,72 @@ semver "^7.5.4" ts-api-utils "^1.0.1" -"@typescript-eslint/parser@^6.10.0": - version "6.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.10.0.tgz#578af79ae7273193b0b6b61a742a2bc8e02f875a" - integrity sha512-+sZwIj+s+io9ozSxIWbNB5873OSdfeBEH/FR0re14WLI6BaKuSOnnwCJ2foUiu8uXf4dRp1UqHP0vrZ1zXGrog== +"@typescript-eslint/parser@^6.14.0": + version "6.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.14.0.tgz#a2d6a732e0d2b95c73f6a26ae7362877cc1b4212" + integrity sha512-QjToC14CKacd4Pa7JK4GeB/vHmWFJckec49FR4hmIRf97+KXole0T97xxu9IFiPxVQ1DBWrQ5wreLwAGwWAVQA== dependencies: - "@typescript-eslint/scope-manager" "6.10.0" - "@typescript-eslint/types" "6.10.0" - "@typescript-eslint/typescript-estree" "6.10.0" - "@typescript-eslint/visitor-keys" "6.10.0" + "@typescript-eslint/scope-manager" "6.14.0" + "@typescript-eslint/types" "6.14.0" + "@typescript-eslint/typescript-estree" "6.14.0" + "@typescript-eslint/visitor-keys" "6.14.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@6.10.0": - version "6.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.10.0.tgz#b0276118b13d16f72809e3cecc86a72c93708540" - integrity sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg== +"@typescript-eslint/scope-manager@6.14.0": + version "6.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.14.0.tgz#53d24363fdb5ee0d1d8cda4ed5e5321272ab3d48" + integrity sha512-VT7CFWHbZipPncAZtuALr9y3EuzY1b1t1AEkIq2bTXUPKw+pHoXflGNG5L+Gv6nKul1cz1VH8fz16IThIU0tdg== dependencies: - "@typescript-eslint/types" "6.10.0" - "@typescript-eslint/visitor-keys" "6.10.0" + "@typescript-eslint/types" "6.14.0" + "@typescript-eslint/visitor-keys" "6.14.0" -"@typescript-eslint/type-utils@6.10.0": - version "6.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.10.0.tgz#1007faede067c78bdbcef2e8abb31437e163e2e1" - integrity sha512-wYpPs3hgTFblMYwbYWPT3eZtaDOjbLyIYuqpwuLBBqhLiuvJ+9sEp2gNRJEtR5N/c9G1uTtQQL5AhV0fEPJYcg== +"@typescript-eslint/type-utils@6.14.0": + version "6.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.14.0.tgz#ac9cb5ba0615c837f1a6b172feeb273d36e4f8af" + integrity sha512-x6OC9Q7HfYKqjnuNu5a7kffIYs3No30isapRBJl1iCHLitD8O0lFbRcVGiOcuyN837fqXzPZ1NS10maQzZMKqw== dependencies: - "@typescript-eslint/typescript-estree" "6.10.0" - "@typescript-eslint/utils" "6.10.0" + "@typescript-eslint/typescript-estree" "6.14.0" + "@typescript-eslint/utils" "6.14.0" debug "^4.3.4" ts-api-utils "^1.0.1" -"@typescript-eslint/types@6.10.0": - version "6.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.10.0.tgz#f4f0a84aeb2ac546f21a66c6e0da92420e921367" - integrity sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg== +"@typescript-eslint/types@6.14.0": + version "6.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.14.0.tgz#935307f7a931016b7a5eb25d494ea3e1f613e929" + integrity sha512-uty9H2K4Xs8E47z3SnXEPRNDfsis8JO27amp2GNCnzGETEW3yTqEIVg5+AI7U276oGF/tw6ZA+UesxeQ104ceA== -"@typescript-eslint/typescript-estree@6.10.0": - version "6.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.10.0.tgz#667381eed6f723a1a8ad7590a31f312e31e07697" - integrity sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg== +"@typescript-eslint/typescript-estree@6.14.0": + version "6.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.14.0.tgz#90c7ddd45cd22139adf3d4577580d04c9189ac13" + integrity sha512-yPkaLwK0yH2mZKFE/bXkPAkkFgOv15GJAUzgUVonAbv0Hr4PK/N2yaA/4XQbTZQdygiDkpt5DkxPELqHguNvyw== dependencies: - "@typescript-eslint/types" "6.10.0" - "@typescript-eslint/visitor-keys" "6.10.0" + "@typescript-eslint/types" "6.14.0" + "@typescript-eslint/visitor-keys" "6.14.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" semver "^7.5.4" ts-api-utils "^1.0.1" -"@typescript-eslint/utils@6.10.0": - version "6.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.10.0.tgz#4d76062d94413c30e402c9b0df8c14aef8d77336" - integrity sha512-v+pJ1/RcVyRc0o4wAGux9x42RHmAjIGzPRo538Z8M1tVx6HOnoQBCX/NoadHQlZeC+QO2yr4nNSFWOoraZCAyg== +"@typescript-eslint/utils@6.14.0": + version "6.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.14.0.tgz#856a9e274367d99ffbd39c48128b93a86c4261e3" + integrity sha512-XwRTnbvRr7Ey9a1NT6jqdKX8y/atWG+8fAIu3z73HSP8h06i3r/ClMhmaF/RGWGW1tHJEwij1uEg2GbEmPYvYg== dependencies: "@eslint-community/eslint-utils" "^4.4.0" "@types/json-schema" "^7.0.12" "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "6.10.0" - "@typescript-eslint/types" "6.10.0" - "@typescript-eslint/typescript-estree" "6.10.0" + "@typescript-eslint/scope-manager" "6.14.0" + "@typescript-eslint/types" "6.14.0" + "@typescript-eslint/typescript-estree" "6.14.0" semver "^7.5.4" -"@typescript-eslint/visitor-keys@6.10.0": - version "6.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.10.0.tgz#b9eaf855a1ac7e95633ae1073af43d451e8f84e3" - integrity sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg== +"@typescript-eslint/visitor-keys@6.14.0": + version "6.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.14.0.tgz#1d1d486581819287de824a56c22f32543561138e" + integrity sha512-fB5cw6GRhJUz03MrROVuj5Zm/Q+XWlVdIsFj+Zb1Hvqouc8t+XP2H5y53QYU/MGtd2dPg6/vJJlhoX3xc2ehfw== dependencies: - "@typescript-eslint/types" "6.10.0" + "@typescript-eslint/types" "6.14.0" eslint-visitor-keys "^3.4.1" "@ungap/structured-clone@^1.2.0": @@ -1338,15 +1338,15 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4 resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint@^8.53.0: - version "8.53.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.53.0.tgz#14f2c8244298fcae1f46945459577413ba2697ce" - integrity sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag== +eslint@^8.55.0: + version "8.55.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.55.0.tgz#078cb7b847d66f2c254ea1794fa395bf8e7e03f8" + integrity sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.3" - "@eslint/js" "8.53.0" + "@eslint/eslintrc" "^2.1.4" + "@eslint/js" "8.55.0" "@humanwhocodes/config-array" "^0.11.13" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" @@ -2286,10 +2286,10 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -lemmy-js-client@0.19.0-alpha.18: - version "0.19.0-alpha.18" - resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.19.0-alpha.18.tgz#f94841681cabdf9d5c4ce7048eacb57557f68724" - integrity sha512-cKJfKKnjK+ijk0Yd6ydtne3Y4FILp2RbQg05pCru9n6PCyPAa85eQL4QxPB1PPed20ckSZRcHLcnr/bYFDgpaw== +lemmy-js-client@0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.19.0.tgz#50098183264fa176784857f45665b06994b31e18" + integrity sha512-h+E8wC9RKjlToWw9+kuGFAzk4Fiaf61KqAwzvoCDAfj2L1r+YNt5EDMOggGCoRx5PlqLuIVr7BNEU46KxJfmHA== dependencies: cross-fetch "^3.1.5" form-data "^4.0.0" @@ -2619,10 +2619,10 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.0.3.tgz#432a51f7ba422d1469096c0fdc28e235db8f9643" - integrity sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg== +prettier@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.1.tgz#6ba9f23165d690b6cbdaa88cb0807278f7019848" + integrity sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw== pretty-format@^29.0.0, pretty-format@^29.7.0: version "29.7.0" @@ -2952,10 +2952,10 @@ type-fest@^0.21.3: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== -typescript@^5.0.4: - version "5.2.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" - integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== +typescript@^5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" + integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== undici-types@~5.26.4: version "5.26.5" diff --git a/crates/api/Cargo.toml b/crates/api/Cargo.toml index 6327e45fd..f22c9192a 100644 --- a/crates/api/Cargo.toml +++ b/crates/api/Cargo.toml @@ -1,5 +1,6 @@ [package] name = "lemmy_api" +publish = false version.workspace = true edition.workspace = true description.workspace = true diff --git a/crates/api/src/comment/distinguish.rs b/crates/api/src/comment/distinguish.rs index f29e01f76..a346bf4ca 100644 --- a/crates/api/src/comment/distinguish.rs +++ b/crates/api/src/comment/distinguish.rs @@ -26,6 +26,11 @@ pub async fn distinguish_comment( ) .await?; + // Verify that only the creator can distinguish + if local_user_view.person.id != orig_comment.creator.id { + Err(LemmyErrorType::NoCommentEditAllowed)? + } + // Verify that only a mod or admin can distinguish a comment check_community_mod_action( &local_user_view.person, diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index e3acae193..faa74824e 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -82,16 +82,7 @@ pub fn read_auth_token(req: &HttpRequest) -> Result, LemmyError> } // If that fails, try to read from cookie else if let Some(cookie) = &req.cookie(AUTH_COOKIE_NAME) { - // ensure that its marked as httponly and secure - let secure = cookie.secure().unwrap_or_default(); - let http_only = cookie.http_only().unwrap_or_default(); - let is_debug_mode = cfg!(debug_assertions); - - if !is_debug_mode && (!secure || !http_only) { - Err(LemmyError::from(LemmyErrorType::AuthCookieInsecure)) - } else { - Ok(Some(cookie.value().to_string())) - } + Ok(Some(cookie.value().to_string())) } // Otherwise, there's no auth else { diff --git a/crates/api/src/post/get_link_metadata.rs b/crates/api/src/post/get_link_metadata.rs index babceedb4..a6a0c973b 100644 --- a/crates/api/src/post/get_link_metadata.rs +++ b/crates/api/src/post/get_link_metadata.rs @@ -1,4 +1,4 @@ -use actix_web::web::{Data, Json}; +use actix_web::web::{Data, Json, Query}; use lemmy_api_common::{ context::LemmyContext, post::{GetSiteMetadata, GetSiteMetadataResponse}, @@ -8,7 +8,7 @@ use lemmy_utils::error::LemmyError; #[tracing::instrument(skip(context))] pub async fn get_link_metadata( - data: Json, + data: Query, context: Data, ) -> Result, LemmyError> { let metadata = fetch_link_metadata(&data.url, false, &context).await?; diff --git a/crates/api/src/private_message_report/create.rs b/crates/api/src/private_message_report/create.rs index 75620bf8b..7aca9661b 100644 --- a/crates/api/src/private_message_report/create.rs +++ b/crates/api/src/private_message_report/create.rs @@ -31,6 +31,11 @@ pub async fn create_pm_report( let private_message_id = data.private_message_id; let private_message = PrivateMessage::read(&mut context.pool(), private_message_id).await?; + // Make sure that only the recipient of the private message can create a report + if person_id != private_message.recipient_id { + Err(LemmyErrorType::CouldntCreateReport)? + } + let report_form = PrivateMessageReportForm { creator_id: person_id, private_message_id, diff --git a/crates/api/src/site/block.rs b/crates/api/src/site/block.rs index be48e8ce8..7d28e43d5 100644 --- a/crates/api/src/site/block.rs +++ b/crates/api/src/site/block.rs @@ -19,6 +19,10 @@ pub async fn block_instance( ) -> Result, LemmyError> { let instance_id = data.instance_id; let person_id = local_user_view.person.id; + if local_user_view.person.instance_id == instance_id { + return Err(LemmyErrorType::CantBlockLocalInstance)?; + } + let instance_block_form = InstanceBlockForm { person_id, instance_id, diff --git a/crates/api/src/sitemap.rs b/crates/api/src/sitemap.rs index 438a8b8e8..b1b961350 100644 --- a/crates/api/src/sitemap.rs +++ b/crates/api/src/sitemap.rs @@ -26,7 +26,7 @@ async fn generate_urlset( } pub async fn get_sitemap(context: Data) -> LemmyResult { - info!("Generating sitemap with posts from last {} hours...", 24); + info!("Generating sitemap...",); let posts = Post::list_for_sitemap(&mut context.pool()).await?; info!("Loaded latest {} posts", posts.len()); @@ -36,7 +36,7 @@ pub async fn get_sitemap(context: Data) -> LemmyResult>) -> LemmyResult<()> { + pub async fn close(outgoing_activities_task: JoinHandle<()>) -> LemmyResult<()> { ACTIVITY_CHANNEL.keepalive_sender.lock().await.take(); - outgoing_activities_task.await??; + outgoing_activities_task.await?; Ok(()) } } diff --git a/crates/api_common/src/utils.rs b/crates/api_common/src/utils.rs index 024a75102..e37070268 100644 --- a/crates/api_common/src/utils.rs +++ b/crates/api_common/src/utils.rs @@ -48,7 +48,7 @@ use tracing::warn; use url::{ParseError, Url}; use urlencoding::encode; -pub static AUTH_COOKIE_NAME: &str = "auth"; +pub static AUTH_COOKIE_NAME: &str = "jwt"; #[tracing::instrument(skip_all)] pub async fn is_mod_or_admin( diff --git a/crates/api_crud/Cargo.toml b/crates/api_crud/Cargo.toml index 867c3f215..f4f89c2e5 100644 --- a/crates/api_crud/Cargo.toml +++ b/crates/api_crud/Cargo.toml @@ -1,5 +1,6 @@ [package] name = "lemmy_api_crud" +publish = false version.workspace = true edition.workspace = true description.workspace = true @@ -22,5 +23,12 @@ bcrypt = { workspace = true } actix-web = { workspace = true } tracing = { workspace = true } url = { workspace = true } -webmention = "0.5.0" +futures.workspace = true uuid = { workspace = true } +moka.workspace = true +once_cell.workspace = true +anyhow.workspace = true +webmention = "0.5.0" + +[package.metadata.cargo-machete] +ignored = ["futures"] diff --git a/crates/api_crud/src/site/read.rs b/crates/api_crud/src/site/read.rs index aceee29d4..c340ce44b 100644 --- a/crates/api_crud/src/site/read.rs +++ b/crates/api_crud/src/site/read.rs @@ -21,46 +21,68 @@ use lemmy_utils::{ error::{LemmyError, LemmyErrorExt, LemmyErrorType}, version, }; +use moka::future::Cache; +use once_cell::sync::Lazy; +use std::time::Duration; #[tracing::instrument(skip(context))] pub async fn get_site( local_user_view: Option, context: Data, ) -> Result, LemmyError> { - let site_view = SiteView::read_local(&mut context.pool()).await?; + static CACHE: Lazy> = Lazy::new(|| { + Cache::builder() + .max_capacity(1) + .time_to_live(Duration::from_secs(1)) + .build() + }); - let admins = PersonView::admins(&mut context.pool()).await?; + // This data is independent from the user account so we can cache it across requests + let mut site_response = CACHE + .try_get_with::<_, LemmyError>((), async { + let site_view = SiteView::read_local(&mut context.pool()).await?; + let admins = PersonView::admins(&mut context.pool()).await?; + let all_languages = Language::read_all(&mut context.pool()).await?; + let discussion_languages = SiteLanguage::read_local_raw(&mut context.pool()).await?; + let taglines = Tagline::get_all(&mut context.pool(), site_view.local_site.id).await?; + let custom_emojis = + CustomEmojiView::get_all(&mut context.pool(), site_view.local_site.id).await?; + Ok(GetSiteResponse { + site_view, + admins, + version: version::VERSION.to_string(), + my_user: None, + all_languages, + discussion_languages, + taglines, + custom_emojis, + }) + }) + .await + .map_err(|e| anyhow::anyhow!("Failed to construct site response: {e}"))?; - // Build the local user - let my_user = if let Some(local_user_view) = local_user_view { + // Build the local user with parallel queries and add it to site response + site_response.my_user = if let Some(local_user_view) = local_user_view { let person_id = local_user_view.person.id; let local_user_id = local_user_view.local_user.id; + let pool = &mut context.pool(); - let follows = CommunityFollowerView::for_person(&mut context.pool(), person_id) - .await - .with_lemmy_type(LemmyErrorType::SystemErrLogin)?; - - let person_id = local_user_view.person.id; - let community_blocks = CommunityBlockView::for_person(&mut context.pool(), person_id) - .await - .with_lemmy_type(LemmyErrorType::SystemErrLogin)?; - - let instance_blocks = InstanceBlockView::for_person(&mut context.pool(), person_id) - .await - .with_lemmy_type(LemmyErrorType::SystemErrLogin)?; - - let person_id = local_user_view.person.id; - let person_blocks = PersonBlockView::for_person(&mut context.pool(), person_id) - .await - .with_lemmy_type(LemmyErrorType::SystemErrLogin)?; - - let moderates = CommunityModeratorView::for_person(&mut context.pool(), person_id) - .await - .with_lemmy_type(LemmyErrorType::SystemErrLogin)?; - - let discussion_languages = LocalUserLanguage::read(&mut context.pool(), local_user_id) - .await - .with_lemmy_type(LemmyErrorType::SystemErrLogin)?; + let ( + follows, + community_blocks, + instance_blocks, + person_blocks, + moderates, + discussion_languages, + ) = lemmy_db_schema::try_join_with_pool!(pool => ( + |pool| CommunityFollowerView::for_person(pool, person_id), + |pool| CommunityBlockView::for_person(pool, person_id), + |pool| InstanceBlockView::for_person(pool, person_id), + |pool| PersonBlockView::for_person(pool, person_id), + |pool| CommunityModeratorView::for_person(pool, person_id), + |pool| LocalUserLanguage::read(pool, local_user_id) + )) + .with_lemmy_type(LemmyErrorType::SystemErrLogin)?; Some(MyUserInfo { local_user_view, @@ -75,20 +97,5 @@ pub async fn get_site( None }; - let all_languages = Language::read_all(&mut context.pool()).await?; - let discussion_languages = SiteLanguage::read_local_raw(&mut context.pool()).await?; - let taglines = Tagline::get_all(&mut context.pool(), site_view.local_site.id).await?; - let custom_emojis = - CustomEmojiView::get_all(&mut context.pool(), site_view.local_site.id).await?; - - Ok(Json(GetSiteResponse { - site_view, - admins, - version: version::VERSION.to_string(), - my_user, - all_languages, - discussion_languages, - taglines, - custom_emojis, - })) + Ok(Json(site_response)) } diff --git a/crates/apub/Cargo.toml b/crates/apub/Cargo.toml index bb8c921ca..2f865ed4e 100644 --- a/crates/apub/Cargo.toml +++ b/crates/apub/Cargo.toml @@ -1,5 +1,6 @@ [package] name = "lemmy_apub" +publish = false version.workspace = true edition.workspace = true description.workspace = true @@ -40,12 +41,12 @@ async-trait = { workspace = true } anyhow = { workspace = true } reqwest = { workspace = true } once_cell = { workspace = true } -serde_with = { workspace = true } +moka.workspace = true +serde_with.workspace = true html2md = "0.2.14" html2text = "0.6.0" stringreader = "0.1.1" enum_delegate = "0.2.0" -moka = { version = "0.11", features = ["future"] } [dev-dependencies] serial_test = { workspace = true } diff --git a/crates/apub/assets/peertube/objects/group.json b/crates/apub/assets/peertube/objects/group.json index cf4e216c4..1817fb202 100644 --- a/crates/apub/assets/peertube/objects/group.json +++ b/crates/apub/assets/peertube/objects/group.json @@ -1,30 +1,4 @@ { - "type": "Group", - "id": "https://framatube.org/video-channels/joinpeertube", - "following": "https://framatube.org/video-channels/joinpeertube/following", - "followers": "https://framatube.org/video-channels/joinpeertube/followers", - "playlists": "https://framatube.org/video-channels/joinpeertube/playlists", - "inbox": "https://framatube.org/video-channels/joinpeertube/inbox", - "outbox": "https://framatube.org/video-channels/joinpeertube/outbox", - "preferredUsername": "joinpeertube", - "url": "https://framatube.org/video-channels/joinpeertube", - "name": "A propos de PeerTube", - "endpoints": { - "sharedInbox": "https://framatube.org/inbox" - }, - "publicKey": { - "id": "https://framatube.org/video-channels/joinpeertube#main-key", - "owner": "https://framatube.org/video-channels/joinpeertube", - "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsJCIZJga+4Kumb9Wrmpy\ntyV7kWdINImoXBiFkGG+6OHreHN2C3UPwTu9IkX/e20NaX6Ly6c0busieW7yh//q\nomHl2U8zz2Z5xQHUN/2ljQjUNO+89OV6cFIGyEvcwc6QhuqGvrcxonjrEkux7xSv\nxQM4kZ3YW1Sii4piFpGGIm1pcUkOxFab8PWVB5Hzpg/df2/XOmH8UECT5vaMRPE6\ns6hNiQNE34z9QmPiG6nUlaWb/WDcMYbma3sUVWW3DI008ukLlwLaLIm30ax8CEYt\nHEv2jOQb1E1sXtBPe1FI+dXRgTIk40KF50KLqcgwJH1y5ck7c8IEeooj+tYGVqPr\npQIDAQAB\n-----END PUBLIC KEY-----" - }, - "published": "2021-08-09T14:26:09.514Z", - "icon": { - "type": "Image", - "mediaType": "image/png", - "height": 120, - "width": 120, - "url": "https://framatube.org/lazy-static/avatars/a2c2ff10-9da6-4c6c-9b25-2e557fa74b66.png" - }, "@context": [ "https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1", @@ -33,99 +7,66 @@ }, { "pt": "https://joinpeertube.org/ns#", - "sc": "http://schema.org#", - "Hashtag": "as:Hashtag", - "uuid": "sc:identifier", - "category": "sc:category", - "licence": "sc:license", - "subtitleLanguage": "sc:subtitleLanguage", - "sensitive": "as:sensitive", - "language": "sc:inLanguage", - "isLiveBroadcast": "sc:isLiveBroadcast", - "liveSaveReplay": { - "@type": "sc:Boolean", - "@id": "pt:liveSaveReplay" - }, - "permanentLive": { - "@type": "sc:Boolean", - "@id": "pt:permanentLive" - }, - "Infohash": "pt:Infohash", - "Playlist": "pt:Playlist", - "PlaylistElement": "pt:PlaylistElement", - "originallyPublishedAt": "sc:datePublished", - "views": { - "@type": "sc:Number", - "@id": "pt:views" - }, - "state": { - "@type": "sc:Number", - "@id": "pt:state" - }, - "size": { - "@type": "sc:Number", - "@id": "pt:size" - }, - "fps": { - "@type": "sc:Number", - "@id": "pt:fps" - }, - "startTimestamp": { - "@type": "sc:Number", - "@id": "pt:startTimestamp" - }, - "stopTimestamp": { - "@type": "sc:Number", - "@id": "pt:stopTimestamp" - }, - "position": { - "@type": "sc:Number", - "@id": "pt:position" - }, - "commentsEnabled": { - "@type": "sc:Boolean", - "@id": "pt:commentsEnabled" - }, - "downloadEnabled": { - "@type": "sc:Boolean", - "@id": "pt:downloadEnabled" - }, - "waitTranscoding": { - "@type": "sc:Boolean", - "@id": "pt:waitTranscoding" + "sc": "http://schema.org/", + "playlists": { + "@id": "pt:playlists", + "@type": "@id" }, "support": { "@type": "sc:Text", "@id": "pt:support" }, - "likes": { - "@id": "as:likes", - "@type": "@id" - }, - "dislikes": { - "@id": "as:dislikes", - "@type": "@id" - }, - "playlists": { - "@id": "pt:playlists", - "@type": "@id" - }, - "shares": { - "@id": "as:shares", - "@type": "@id" - }, - "comments": { - "@id": "as:comments", - "@type": "@id" - } + "icons": "as:icon" } ], - "summary": "Un logiciel libre pour reprendre le contrôle de vos vidéos", - "support": null, + "type": "Group", + "id": "https://peertube.stream/video-channels/vu", + "following": "https://peertube.stream/video-channels/vu/following", + "followers": "https://peertube.stream/video-channels/vu/followers", + "playlists": "https://peertube.stream/video-channels/vu/playlists", + "inbox": "https://peertube.stream/video-channels/vu/inbox", + "outbox": "https://peertube.stream/video-channels/vu/outbox", + "preferredUsername": "vu", + "url": "https://peertube.stream/video-channels/vu", + "name": "VU", + "endpoints": { + "sharedInbox": "https://peertube.stream/inbox" + }, + "publicKey": { + "id": "https://peertube.stream/video-channels/vu#main-key", + "owner": "https://peertube.stream/video-channels/vu", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtcWpN7efQx5C7ecWkw3r\nX4ViPy/bl3d3iyVLyP6z/3+WAUKJxqR+QKlNzxM7NglzB0B48NYu2cg4iuwKkSK9\ntrfMC/Ze0H10Wo/5kUH5YQKzLo4syHOuuM+1rbZFBbzVFwk4k0qqLFTXQ+Y6WNSS\nG9OlFYZNpRaUkgF8Q/KCsngn68qsZ0gLly9FJb+6+j3IppLJNXrBpFB5qulWibL+\neN+3XMnaTm6ge6X+rFti5r6dh10grL0KU/eZKmGyadgdwYdvR/LLtBWwFIwSJShk\nuIPhcz2zbkwrV3AixLe76TLGXX5M9qczfsVYLupyU7TwPlFM2ENDtDdfp41sWaZa\nxQIDAQAB\n-----END PUBLIC KEY-----" + }, + "published": "2020-12-10T16:07:08.406Z", + "icon": [ + { + "type": "Image", + "mediaType": "image/jpeg", + "height": 48, + "width": 48, + "url": "https://peertube.stream/lazy-static/avatars/45ec87d5-c8ec-4fcf-948f-d5a928b56496.jpg" + }, + { + "type": "Image", + "mediaType": "image/jpeg", + "height": 120, + "width": 120, + "url": "https://peertube.stream/lazy-static/avatars/3296c098-abbb-4fda-a67a-ab88e447ca19.jpg" + } + ], + "image": { + "type": "Image", + "mediaType": "image/jpeg", + "height": 317, + "width": 1920, + "url": "https://peertube.stream/lazy-static/banners/550c0541-3021-4d4b-8654-54d0c4cda96d.jpg" + }, + "summary": "VU c'est du lundi au samedi sur France 5 à 20h00 \nRetrouvez les meilleurs moments de la télévision, en 6 minutes.\n\nChaîne PeerTube non-officielle.", + "support": "Suivre VU :\n- Twitter : https://twitter.com/vufrancetv\n- Facebook :https://www.facebook.com/vufrancetv/\n- Site : https://www.france.tv/france-5/vu/", "attributedTo": [ { "type": "Person", - "id": "https://framatube.org/accounts/framasoft" + "id": "https://peertube.stream/accounts/createurs" } ] } diff --git a/crates/apub/assets/peertube/objects/person.json b/crates/apub/assets/peertube/objects/person.json index 871e88e13..2b1acdaad 100644 --- a/crates/apub/assets/peertube/objects/person.json +++ b/crates/apub/assets/peertube/objects/person.json @@ -1,30 +1,4 @@ { - "type": "Person", - "id": "https://framatube.org/accounts/framasoft", - "following": "https://framatube.org/accounts/framasoft/following", - "followers": "https://framatube.org/accounts/framasoft/followers", - "playlists": "https://framatube.org/accounts/framasoft/playlists", - "inbox": "https://framatube.org/accounts/framasoft/inbox", - "outbox": "https://framatube.org/accounts/framasoft/outbox", - "preferredUsername": "framasoft", - "url": "https://framatube.org/accounts/framasoft", - "name": "Framasoft", - "endpoints": { - "sharedInbox": "https://framatube.org/inbox" - }, - "publicKey": { - "id": "https://framatube.org/accounts/framasoft#main-key", - "owner": "https://framatube.org/accounts/framasoft", - "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuRh3frgIg866D0y0FThp\nSUkJImMcHGkUvpYQYv2iUgarZZtEbwT8PfQf0bJazy+cP8KqQmMDf5PBhT7dfdny\nf/GKGMw9Olc+QISeKDj3sqZ3Csrm4KV4avMGCfth6eSU7LozojeSGCXdUFz/8UgE\nfhV4mJjEX/FbwRYoKlagv5rY9mkX5XomzZU+z9j6ZVXyofwOwJvmI1hq0SYDv2bc\neB/RgIh/H0nyMtF8o+0CT42FNEET9j9m1BKOBtPzwZHmitKRkEmui5cK256s1laB\nT61KHpcD9gQKkQ+I3sFEzCBUJYfVo6fUe+GehBZuAfq4qDhd15SfE4K9veDscDFI\nTwIDAQAB\n-----END PUBLIC KEY-----" - }, - "published": "2018-03-01T15:16:17.118Z", - "icon": { - "type": "Image", - "mediaType": "image/png", - "height": null, - "width": null, - "url": "https://framatube.org/lazy-static/avatars/f73876f5-1d45-4f8a-942a-d3d5d5ac5dc1.png" - }, "@context": [ "https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1", @@ -33,92 +7,52 @@ }, { "pt": "https://joinpeertube.org/ns#", - "sc": "http://schema.org#", - "Hashtag": "as:Hashtag", - "uuid": "sc:identifier", - "category": "sc:category", - "licence": "sc:license", - "subtitleLanguage": "sc:subtitleLanguage", - "sensitive": "as:sensitive", - "language": "sc:inLanguage", - "isLiveBroadcast": "sc:isLiveBroadcast", - "liveSaveReplay": { - "@type": "sc:Boolean", - "@id": "pt:liveSaveReplay" - }, - "permanentLive": { - "@type": "sc:Boolean", - "@id": "pt:permanentLive" - }, - "Infohash": "pt:Infohash", - "Playlist": "pt:Playlist", - "PlaylistElement": "pt:PlaylistElement", - "originallyPublishedAt": "sc:datePublished", - "views": { - "@type": "sc:Number", - "@id": "pt:views" - }, - "state": { - "@type": "sc:Number", - "@id": "pt:state" - }, - "size": { - "@type": "sc:Number", - "@id": "pt:size" - }, - "fps": { - "@type": "sc:Number", - "@id": "pt:fps" - }, - "startTimestamp": { - "@type": "sc:Number", - "@id": "pt:startTimestamp" - }, - "stopTimestamp": { - "@type": "sc:Number", - "@id": "pt:stopTimestamp" - }, - "position": { - "@type": "sc:Number", - "@id": "pt:position" - }, - "commentsEnabled": { - "@type": "sc:Boolean", - "@id": "pt:commentsEnabled" - }, - "downloadEnabled": { - "@type": "sc:Boolean", - "@id": "pt:downloadEnabled" - }, - "waitTranscoding": { - "@type": "sc:Boolean", - "@id": "pt:waitTranscoding" + "sc": "http://schema.org/", + "playlists": { + "@id": "pt:playlists", + "@type": "@id" }, "support": { "@type": "sc:Text", "@id": "pt:support" }, - "likes": { - "@id": "as:likes", - "@type": "@id" - }, - "dislikes": { - "@id": "as:dislikes", - "@type": "@id" - }, - "playlists": { - "@id": "pt:playlists", - "@type": "@id" - }, - "shares": { - "@id": "as:shares", - "@type": "@id" - }, - "comments": { - "@id": "as:comments", - "@type": "@id" - } + "icons": "as:icon" } ], - "summary": null + "type": "Person", + "id": "https://peertube.stream/accounts/createurs", + "following": "https://peertube.stream/accounts/createurs/following", + "followers": "https://peertube.stream/accounts/createurs/followers", + "playlists": "https://peertube.stream/accounts/createurs/playlists", + "inbox": "https://peertube.stream/accounts/createurs/inbox", + "outbox": "https://peertube.stream/accounts/createurs/outbox", + "preferredUsername": "createurs", + "url": "https://peertube.stream/accounts/createurs", + "name": "Créateurs", + "endpoints": { + "sharedInbox": "https://peertube.stream/inbox" + }, + "publicKey": { + "id": "https://peertube.stream/accounts/createurs#main-key", + "owner": "https://peertube.stream/accounts/createurs", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxqkQhbRYbA81+WTYjorR\n2lEMad3kYCnzDjGTLr4I92eanzFHxyELGnjzP6TpEvjOiB9NrCRrqU/iFPLdgrq2\nwIFcXPWdCq6Gcg7QLlaeMM0JoJmr0KTEhzg0XKCo96UsyTzaF4DISxqi8RyoyWeU\nEkgiOzlkdYTlouq3MlQH+p1PBAsNUQfIEUsU+l6k1vzbm8JRwlT+D1bNde4I/Lqs\n4uB5ru3zzInwZ2hz9+heiriNoGEBv74rZHYn966tZVX8iMGx2+m6okozEdEQbqCl\n0ekqDcd8P6CoFqqeeu8coh82OUtuFI/XsbetdWA55YQmSHyMiTsIwVbeoogIETbI\n4QIDAQAB\n-----END PUBLIC KEY-----" + }, + "published": "2020-11-11T17:12:37.243Z", + "icon": [ + { + "type": "Image", + "mediaType": "image/png", + "height": 48, + "width": 48, + "url": "https://peertube.stream/lazy-static/avatars/1760df9a-3c96-45fc-9342-c313a3bf2210.png" + }, + { + "type": "Image", + "mediaType": "image/png", + "height": 120, + "width": 120, + "url": "https://peertube.stream/lazy-static/avatars/c27b672d-ad8f-498a-adbe-553af8da56f9.png" + } + ], + "summary": "Centralisation de miroirs de chaînes. La grande majorité a été contactée ou diffuse sous licence avec paternité.\n\nCompte maintenu par [Raph](https://tooter.social/@raph)." } diff --git a/crates/apub/assets/peertube/objects/video.json b/crates/apub/assets/peertube/objects/video.json index 78e732fe5..daca3d554 100644 --- a/crates/apub/assets/peertube/objects/video.json +++ b/crates/apub/assets/peertube/objects/video.json @@ -1,372 +1,4 @@ { - "type": "Video", - "id": "https://framatube.org/videos/watch/4294a720-f263-4ea4-9392-cf9cea4d5277", - "name": "What is the Fediverse?", - "duration": "PT98S", - "uuid": "4294a720-f263-4ea4-9392-cf9cea4d5277", - "tag": [ - { - "type": "Hashtag", - "name": "fediverse" - }, - { - "type": "Hashtag", - "name": "framasoft" - }, - { - "type": "Hashtag", - "name": "Mastodon" - }, - { - "type": "Hashtag", - "name": "PeerTube " - } - ], - "category": { - "identifier": "15", - "name": "Science & Technology" - }, - "licence": { - "identifier": "2", - "name": "Attribution - Share Alike" - }, - "language": { - "identifier": "en", - "name": "English" - }, - "views": 4805, - "sensitive": false, - "waitTranscoding": true, - "isLiveBroadcast": false, - "liveSaveReplay": null, - "permanentLive": null, - "state": 1, - "commentsEnabled": true, - "downloadEnabled": true, - "published": "2022-04-28T11:51:16.293Z", - "originallyPublishedAt": null, - "updated": "2022-05-03T11:39:02.489Z", - "mediaType": "text/markdown", - "content": "Help us translate the subtitles [on our translation tool](https://weblate.framasoft.org/projects/what-is-the-fediverse-video/subtitles/).\r\n\r\n**Animation Produced by** [LILA](https://libreart.info/) - [ZeMarmot Team](https://film.zemarmot.net/)\r\n**Direction & Animation** by Aryeom\r\n**Script & Technology** by Jehan\r\n**Voice by** Paul Peterson\r\n**Licence**: [CC-By-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)\r\n\r\n**Sponsored by** [Framasoft](https://framasoft.org/)\r\n\r\n**Sound by** ORL - [AMMD](https://ammd.net/)\r\n\r\n**Music**: \"Dolling\" by CyberSDF - [CC-BY 4.0](https://creativecommons.org/licenses/by/4.0/)", - "support": null, - "subtitleLanguage": [ - { - "identifier": "ca", - "name": "Catalan", - "url": "https://framatube.org/lazy-static/video-captions/6f8aedd2-c61b-47f6-a2c9-75b15af24d14-ca.vtt" - }, - { - "identifier": "en", - "name": "English", - "url": "https://framatube.org/lazy-static/video-captions/2f199e59-5cf8-4529-a033-9d6dd4a858ca-en.vtt" - }, - { - "identifier": "es", - "name": "Spanish", - "url": "https://framatube.org/lazy-static/video-captions/3f74c16b-925f-45e1-8388-e358428c2436-es.vtt" - }, - { - "identifier": "eu", - "name": "Basque", - "url": "https://framatube.org/lazy-static/video-captions/c4c88e7e-b9d4-4192-bcf2-caf025ddc9fd-eu.vtt" - }, - { - "identifier": "fr", - "name": "French", - "url": "https://framatube.org/lazy-static/video-captions/c18906e3-6257-43e7-90e4-fa2c8ded258b-fr.vtt" - }, - { - "identifier": "hu", - "name": "Hungarian", - "url": "https://framatube.org/lazy-static/video-captions/0a8a295d-a288-404b-b7b3-a2272bc2a6fb-hu.vtt" - }, - { - "identifier": "it", - "name": "Italian", - "url": "https://framatube.org/lazy-static/video-captions/cf857bd9-8b04-4018-af9a-23fa1ff7662d-it.vtt" - }, - { - "identifier": "nb", - "name": "Norwegian Bokmål", - "url": "https://framatube.org/lazy-static/video-captions/12e3a0e9-a29e-4b06-8538-91bed2a11242-nb.vtt" - }, - { - "identifier": "oc", - "name": "Occitan", - "url": "https://framatube.org/lazy-static/video-captions/d841af30-97bf-4a0c-b1f9-e163ba77f23f-oc.vtt" - }, - { - "identifier": "sh", - "name": "Serbo-Croatian", - "url": "https://framatube.org/lazy-static/video-captions/7afe4dae-745f-4769-9f17-9c3a079235cf-sh.vtt" - }, - { - "identifier": "tr", - "name": "Turkish", - "url": "https://framatube.org/lazy-static/video-captions/1b2ea189-760c-4a3e-98d3-16f596c151f0-tr.vtt" - }, - { - "identifier": "vi", - "name": "Vietnamese", - "url": "https://framatube.org/lazy-static/video-captions/552b4086-54ab-4eb3-a8b3-7611a2175e77-vi.vtt" - } - ], - "icon": [ - { - "type": "Image", - "url": "https://framatube.org/static/thumbnails/1f9eb76e-c089-4bdd-af14-602935a6db72.jpg", - "mediaType": "image/jpeg", - "width": 280, - "height": 157 - }, - { - "type": "Image", - "url": "https://framatube.org/lazy-static/previews/8f89d4d8-696f-4512-9a1a-72f1d12caede.jpg", - "mediaType": "image/jpeg", - "width": 850, - "height": 480 - } - ], - "url": [ - { - "type": "Link", - "mediaType": "text/html", - "href": "https://framatube.org/videos/watch/4294a720-f263-4ea4-9392-cf9cea4d5277" - }, - { - "type": "Link", - "mediaType": "application/x-mpegURL", - "href": "https://framatube.org/static/streaming-playlists/hls/4294a720-f263-4ea4-9392-cf9cea4d5277/adc259cb-06f7-496c-8a50-599e58358b29-master.m3u8", - "tag": [ - { - "type": "Infohash", - "name": "caf7178ddd2013e28c9fbcbb7be28df25d03a023" - }, - { - "type": "Infohash", - "name": "cc18bb140f51f64090ba41c951fba85705cafa38" - }, - { - "type": "Infohash", - "name": "595513d823a1aecc18abacac94a1ebb0c31ec009" - }, - { - "type": "Infohash", - "name": "6ae0ce749a57d0f8ff70286878ea7661f85eebf7" - }, - { - "type": "Infohash", - "name": "4eb799f42d461929ed8dd4befae274c9a4404b99" - }, - { - "type": "Infohash", - "name": "b48d1ea795657668783544fd1c9baf637198a323" - }, - { - "type": "Link", - "name": "sha256", - "mediaType": "application/json", - "href": "https://framatube.org/static/streaming-playlists/hls/4294a720-f263-4ea4-9392-cf9cea4d5277/b414eda3-c8af-4271-8dde-253db28aacd1-segments-sha256.json" - }, - { - "type": "Link", - "mediaType": "video/mp4", - "href": "https://framatube.org/static/streaming-playlists/hls/4294a720-f263-4ea4-9392-cf9cea4d5277/64147344-1957-480d-9106-59dd7bbf5661-1080-fragmented.mp4", - "height": 1080, - "size": 14653991, - "fps": 24 - }, - { - "type": "Link", - "rel": ["metadata", "video/mp4"], - "mediaType": "application/json", - "href": "https://framatube.org/api/v1/videos/4294a720-f263-4ea4-9392-cf9cea4d5277/metadata/1421492", - "height": 1080, - "fps": 24 - }, - { - "type": "Link", - "mediaType": "application/x-bittorrent", - "href": "https://framatube.org/lazy-static/torrents/83fa27e3-aba7-4e01-9e66-931086374176-1080-hls.torrent", - "height": 1080 - }, - { - "type": "Link", - "mediaType": "application/x-bittorrent;x-scheme-handler/magnet", - "href": "magnet:?xs=https%3A%2F%2Fframatube.org%2Flazy-static%2Ftorrents%2F83fa27e3-aba7-4e01-9e66-931086374176-1080-hls.torrent&xt=urn:btih:5651916e4301c812412f51381c5af0c1f627bfcb&dn=What+is+the+Fediverse%3F&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F4294a720-f263-4ea4-9392-cf9cea4d5277%2F64147344-1957-480d-9106-59dd7bbf5661-1080-fragmented.mp4", - "height": 1080 - }, - { - "type": "Link", - "mediaType": "video/mp4", - "href": "https://framatube.org/static/streaming-playlists/hls/4294a720-f263-4ea4-9392-cf9cea4d5277/0efaeae5-7468-4c45-ade5-d3b6c732621f-720-fragmented.mp4", - "height": 720, - "size": 9939723, - "fps": 24 - }, - { - "type": "Link", - "rel": ["metadata", "video/mp4"], - "mediaType": "application/json", - "href": "https://framatube.org/api/v1/videos/4294a720-f263-4ea4-9392-cf9cea4d5277/metadata/1421496", - "height": 720, - "fps": 24 - }, - { - "type": "Link", - "mediaType": "application/x-bittorrent", - "href": "https://framatube.org/lazy-static/torrents/b325c824-c052-46e2-9b46-887595055521-720-hls.torrent", - "height": 720 - }, - { - "type": "Link", - "mediaType": "application/x-bittorrent;x-scheme-handler/magnet", - "href": "magnet:?xs=https%3A%2F%2Fframatube.org%2Flazy-static%2Ftorrents%2Fb325c824-c052-46e2-9b46-887595055521-720-hls.torrent&xt=urn:btih:b5a1db245fe156edab7f1981693178dcd47075d2&dn=What+is+the+Fediverse%3F&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F4294a720-f263-4ea4-9392-cf9cea4d5277%2F0efaeae5-7468-4c45-ade5-d3b6c732621f-720-fragmented.mp4", - "height": 720 - }, - { - "type": "Link", - "mediaType": "video/mp4", - "href": "https://framatube.org/static/streaming-playlists/hls/4294a720-f263-4ea4-9392-cf9cea4d5277/201f9772-4971-4bc3-8356-9b85b405ae5d-480-fragmented.mp4", - "height": 480, - "size": 7398758, - "fps": 24 - }, - { - "type": "Link", - "rel": ["metadata", "video/mp4"], - "mediaType": "application/json", - "href": "https://framatube.org/api/v1/videos/4294a720-f263-4ea4-9392-cf9cea4d5277/metadata/1421494", - "height": 480, - "fps": 24 - }, - { - "type": "Link", - "mediaType": "application/x-bittorrent", - "href": "https://framatube.org/lazy-static/torrents/bd99f84e-e9bc-4d36-bea6-6f06000f87c5-480-hls.torrent", - "height": 480 - }, - { - "type": "Link", - "mediaType": "application/x-bittorrent;x-scheme-handler/magnet", - "href": "magnet:?xs=https%3A%2F%2Fframatube.org%2Flazy-static%2Ftorrents%2Fbd99f84e-e9bc-4d36-bea6-6f06000f87c5-480-hls.torrent&xt=urn:btih:6cbe09b50cf7788923a2ec4852a3b2bfd1cd1907&dn=What+is+the+Fediverse%3F&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F4294a720-f263-4ea4-9392-cf9cea4d5277%2F201f9772-4971-4bc3-8356-9b85b405ae5d-480-fragmented.mp4", - "height": 480 - }, - { - "type": "Link", - "mediaType": "video/mp4", - "href": "https://framatube.org/static/streaming-playlists/hls/4294a720-f263-4ea4-9392-cf9cea4d5277/b2313ae6-da36-4fe3-bec5-aa352824a38a-360-fragmented.mp4", - "height": 360, - "size": 6133890, - "fps": 24 - }, - { - "type": "Link", - "rel": ["metadata", "video/mp4"], - "mediaType": "application/json", - "href": "https://framatube.org/api/v1/videos/4294a720-f263-4ea4-9392-cf9cea4d5277/metadata/1421495", - "height": 360, - "fps": 24 - }, - { - "type": "Link", - "mediaType": "application/x-bittorrent", - "href": "https://framatube.org/lazy-static/torrents/b939430a-fdfd-4da7-a030-759ecafa6ac7-360-hls.torrent", - "height": 360 - }, - { - "type": "Link", - "mediaType": "application/x-bittorrent;x-scheme-handler/magnet", - "href": "magnet:?xs=https%3A%2F%2Fframatube.org%2Flazy-static%2Ftorrents%2Fb939430a-fdfd-4da7-a030-759ecafa6ac7-360-hls.torrent&xt=urn:btih:16693f14ad9e53fc41d335e3fa409c2f943d7b68&dn=What+is+the+Fediverse%3F&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F4294a720-f263-4ea4-9392-cf9cea4d5277%2Fb2313ae6-da36-4fe3-bec5-aa352824a38a-360-fragmented.mp4", - "height": 360 - }, - { - "type": "Link", - "mediaType": "video/mp4", - "href": "https://framatube.org/static/streaming-playlists/hls/4294a720-f263-4ea4-9392-cf9cea4d5277/06a866f2-0527-4d68-93b7-c656d7374e86-240-fragmented.mp4", - "height": 240, - "size": 4861464, - "fps": 24 - }, - { - "type": "Link", - "rel": ["metadata", "video/mp4"], - "mediaType": "application/json", - "href": "https://framatube.org/api/v1/videos/4294a720-f263-4ea4-9392-cf9cea4d5277/metadata/1421497", - "height": 240, - "fps": 24 - }, - { - "type": "Link", - "mediaType": "application/x-bittorrent", - "href": "https://framatube.org/lazy-static/torrents/072001ee-18ad-4859-af10-9d7bf12d640c-240-hls.torrent", - "height": 240 - }, - { - "type": "Link", - "mediaType": "application/x-bittorrent;x-scheme-handler/magnet", - "href": "magnet:?xs=https%3A%2F%2Fframatube.org%2Flazy-static%2Ftorrents%2F072001ee-18ad-4859-af10-9d7bf12d640c-240-hls.torrent&xt=urn:btih:b823f54d8cd73f9d7a55266ce683f43bf772d26a&dn=What+is+the+Fediverse%3F&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F4294a720-f263-4ea4-9392-cf9cea4d5277%2F06a866f2-0527-4d68-93b7-c656d7374e86-240-fragmented.mp4", - "height": 240 - }, - { - "type": "Link", - "mediaType": "video/mp4", - "href": "https://framatube.org/static/streaming-playlists/hls/4294a720-f263-4ea4-9392-cf9cea4d5277/f8a1caed-057f-4700-a28e-004efc158b15-0-fragmented.mp4", - "height": 0, - "size": 3141179, - "fps": 0 - }, - { - "type": "Link", - "rel": ["metadata", "video/mp4"], - "mediaType": "application/json", - "href": "https://framatube.org/api/v1/videos/4294a720-f263-4ea4-9392-cf9cea4d5277/metadata/1421493", - "height": 0, - "fps": 0 - }, - { - "type": "Link", - "mediaType": "application/x-bittorrent", - "href": "https://framatube.org/lazy-static/torrents/77cb6940-7e90-48d1-a391-bfa463b9600c-0-hls.torrent", - "height": 0 - }, - { - "type": "Link", - "mediaType": "application/x-bittorrent;x-scheme-handler/magnet", - "href": "magnet:?xs=https%3A%2F%2Fframatube.org%2Flazy-static%2Ftorrents%2F77cb6940-7e90-48d1-a391-bfa463b9600c-0-hls.torrent&xt=urn:btih:9bc7717ed01869507041e31a7e65baffa78ba651&dn=What+is+the+Fediverse%3F&tr=https%3A%2F%2Fframatube.org%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fframatube.org%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fframatube.org%2Fstatic%2Fstreaming-playlists%2Fhls%2F4294a720-f263-4ea4-9392-cf9cea4d5277%2Ff8a1caed-057f-4700-a28e-004efc158b15-0-fragmented.mp4", - "height": 0 - } - ] - }, - { - "type": "Link", - "name": "tracker-http", - "rel": ["tracker", "http"], - "href": "https://framatube.org/tracker/announce" - }, - { - "type": "Link", - "name": "tracker-websocket", - "rel": ["tracker", "websocket"], - "href": "wss://framatube.org:443/tracker/socket" - } - ], - "likes": "https://framatube.org/videos/watch/4294a720-f263-4ea4-9392-cf9cea4d5277/likes", - "dislikes": "https://framatube.org/videos/watch/4294a720-f263-4ea4-9392-cf9cea4d5277/dislikes", - "shares": "https://framatube.org/videos/watch/4294a720-f263-4ea4-9392-cf9cea4d5277/announces", - "comments": "https://framatube.org/videos/watch/4294a720-f263-4ea4-9392-cf9cea4d5277/comments", - "attributedTo": [ - { - "type": "Person", - "id": "https://framatube.org/accounts/framasoft" - }, - { - "type": "Group", - "id": "https://framatube.org/video-channels/joinpeertube" - } - ], - "to": ["https://www.w3.org/ns/activitystreams#Public"], - "cc": ["https://framatube.org/accounts/framasoft/followers"], "@context": [ "https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1", @@ -375,7 +7,7 @@ }, { "pt": "https://joinpeertube.org/ns#", - "sc": "http://schema.org#", + "sc": "http://schema.org/", "Hashtag": "as:Hashtag", "uuid": "sc:identifier", "category": "sc:category", @@ -383,6 +15,7 @@ "subtitleLanguage": "sc:subtitleLanguage", "sensitive": "as:sensitive", "language": "sc:inLanguage", + "identifier": "sc:identifier", "isLiveBroadcast": "sc:isLiveBroadcast", "liveSaveReplay": { "@type": "sc:Boolean", @@ -392,10 +25,26 @@ "@type": "sc:Boolean", "@id": "pt:permanentLive" }, + "latencyMode": { + "@type": "sc:Number", + "@id": "pt:latencyMode" + }, "Infohash": "pt:Infohash", - "Playlist": "pt:Playlist", - "PlaylistElement": "pt:PlaylistElement", + "tileWidth": { + "@type": "sc:Number", + "@id": "pt:tileWidth" + }, + "tileHeight": { + "@type": "sc:Number", + "@id": "pt:tileHeight" + }, + "tileDuration": { + "@type": "sc:Number", + "@id": "pt:tileDuration" + }, "originallyPublishedAt": "sc:datePublished", + "uploadDate": "sc:uploadDate", + "hasParts": "sc:hasParts", "views": { "@type": "sc:Number", "@id": "pt:views" @@ -412,18 +61,6 @@ "@type": "sc:Number", "@id": "pt:fps" }, - "startTimestamp": { - "@type": "sc:Number", - "@id": "pt:startTimestamp" - }, - "stopTimestamp": { - "@type": "sc:Number", - "@id": "pt:stopTimestamp" - }, - "position": { - "@type": "sc:Number", - "@id": "pt:position" - }, "commentsEnabled": { "@type": "sc:Boolean", "@id": "pt:commentsEnabled" @@ -448,10 +85,6 @@ "@id": "as:dislikes", "@type": "@id" }, - "playlists": { - "@id": "pt:playlists", - "@type": "@id" - }, "shares": { "@id": "as:shares", "@type": "@id" @@ -461,5 +94,348 @@ "@type": "@id" } } - ] + ], + "to": ["https://www.w3.org/ns/activitystreams#Public"], + "cc": ["https://peertube.stream/accounts/createurs/followers"], + "type": "Video", + "id": "https://peertube.stream/videos/watch/46cc7342-fdd5-4583-ae16-2eeb340d3b60", + "name": "VU du 12/12/23 : Démission \"refrusée\"", + "duration": "PT383S", + "uuid": "46cc7342-fdd5-4583-ae16-2eeb340d3b60", + "category": { + "identifier": "11", + "name": "News & Politics" + }, + "views": 83, + "sensitive": false, + "waitTranscoding": true, + "state": 1, + "commentsEnabled": true, + "downloadEnabled": true, + "published": "2023-12-12T17:02:02.188Z", + "originallyPublishedAt": "2023-12-11T23:00:00.000Z", + "updated": "2023-12-14T06:40:34.279Z", + "tag": [ + { + "type": "Hashtag", + "name": "France3" + }, + { + "type": "Hashtag", + "name": "lezapping" + } + ], + "mediaType": "text/markdown", + "content": "Un regard impertinent et libre, orchestré par Patrick Menais et son équipe, sur le monde de l’image.\n\nEn avant-première du lundi au samedi à17h00 sur Facebook, Twitter et YouTube.\n\nDu lundi au samedi à 20h00 sur France 5.\n\nhttps://www.facebook.com/vufrancetv\nhttps://twitter.com/VuFrancetv", + "support": null, + "subtitleLanguage": [], + "icon": [ + { + "type": "Image", + "url": "https://peertube.stream/lazy-static/thumbnails/208d2248-6fa3-4a58-a2e6-c6f176559457.jpg", + "mediaType": "image/jpeg", + "width": 280, + "height": 157 + }, + { + "type": "Image", + "url": "https://peertube.stream/lazy-static/previews/73d34e91-0233-443b-a1c3-d98a7ec6a87c.jpg", + "mediaType": "image/jpeg", + "width": 850, + "height": 480 + } + ], + "preview": [ + { + "type": "Image", + "rel": ["storyboard"], + "url": [ + { + "mediaType": "image/jpeg", + "href": "https://peertube.stream/lazy-static/storyboards/fb103d5f-8f76-4c8b-bc81-f952961cacfd.jpg", + "width": 1920, + "height": 1080, + "tileWidth": 192, + "tileHeight": 108, + "tileDuration": "PT4S" + } + ] + } + ], + "url": [ + { + "type": "Link", + "mediaType": "text/html", + "href": "https://peertube.stream/videos/watch/46cc7342-fdd5-4583-ae16-2eeb340d3b60" + }, + { + "type": "Link", + "mediaType": "application/x-mpegURL", + "href": "https://peertube.stream/static/streaming-playlists/hls/46cc7342-fdd5-4583-ae16-2eeb340d3b60/7847c00b-17f0-4cd9-b788-94283bd96d5b-master.m3u8", + "tag": [ + { + "type": "Infohash", + "name": "f50d9a3e851756a1fc1da7fe8b6e40f849c1f3a1" + }, + { + "type": "Infohash", + "name": "fdddadfcf01c52808a5716ac9c0f09e379a1ca69" + }, + { + "type": "Infohash", + "name": "c309597f071c6ab59e1a6935be3dc1ceb58c9250" + }, + { + "type": "Infohash", + "name": "5c28ed3e05102a678dc047a126650fe53d45ded4" + }, + { + "type": "Infohash", + "name": "085f2c72c69af02913177534ec601349ca2b4f01" + }, + { + "type": "Infohash", + "name": "37b9dbeab6f433e94f80a614f888e9a1e9ee3534" + }, + { + "type": "Infohash", + "name": "cc15513891e63a92743730ba65ab256f8825f071" + }, + { + "type": "Link", + "name": "sha256", + "mediaType": "application/json", + "href": "https://peertube.stream/static/streaming-playlists/hls/46cc7342-fdd5-4583-ae16-2eeb340d3b60/a3f5af94-ba6b-4349-a4b0-151cebdf9af6-segments-sha256.json" + }, + { + "type": "Link", + "mediaType": "video/mp4", + "href": "https://peertube.stream/static/streaming-playlists/hls/46cc7342-fdd5-4583-ae16-2eeb340d3b60/5a3db28f-a4b2-49ae-963e-7fd9414efe7c-1080-fragmented.mp4", + "height": 1080, + "size": 90186372, + "fps": 25 + }, + { + "type": "Link", + "rel": ["metadata", "video/mp4"], + "mediaType": "application/json", + "href": "https://peertube.stream/api/v1/videos/46cc7342-fdd5-4583-ae16-2eeb340d3b60/metadata/1570438", + "height": 1080, + "fps": 25 + }, + { + "type": "Link", + "mediaType": "application/x-bittorrent", + "href": "https://peertube.stream/lazy-static/torrents/c3dd78f2-ff9b-41f1-899d-55440f512e09-1080-hls.torrent", + "height": 1080 + }, + { + "type": "Link", + "mediaType": "application/x-bittorrent;x-scheme-handler/magnet", + "href": "magnet:?xs=https%3A%2F%2Fpeertube.stream%2Flazy-static%2Ftorrents%2Fc3dd78f2-ff9b-41f1-899d-55440f512e09-1080-hls.torrent&xt=urn:btih:944323d8a38e077cdea5c1b1aa82300d1f49076a&dn=VU+du+12%2F12%2F23+%3A+D%C3%A9mission+%22refrus%C3%A9e%22&tr=https%3A%2F%2Fpeertube.stream%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fpeertube.stream%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fpeertube.stream%2Fstatic%2Fstreaming-playlists%2Fhls%2F46cc7342-fdd5-4583-ae16-2eeb340d3b60%2F5a3db28f-a4b2-49ae-963e-7fd9414efe7c-1080-fragmented.mp4", + "height": 1080 + }, + { + "type": "Link", + "mediaType": "video/mp4", + "href": "https://peertube.stream/static/streaming-playlists/hls/46cc7342-fdd5-4583-ae16-2eeb340d3b60/557f45f0-60b7-418c-bddd-e55701b387bb-720-fragmented.mp4", + "height": 720, + "size": 50950797, + "fps": 25 + }, + { + "type": "Link", + "rel": ["metadata", "video/mp4"], + "mediaType": "application/json", + "href": "https://peertube.stream/api/v1/videos/46cc7342-fdd5-4583-ae16-2eeb340d3b60/metadata/1570447", + "height": 720, + "fps": 25 + }, + { + "type": "Link", + "mediaType": "application/x-bittorrent", + "href": "https://peertube.stream/lazy-static/torrents/0529c736-0c49-4efd-a9ff-c4989b4c2071-720-hls.torrent", + "height": 720 + }, + { + "type": "Link", + "mediaType": "application/x-bittorrent;x-scheme-handler/magnet", + "href": "magnet:?xs=https%3A%2F%2Fpeertube.stream%2Flazy-static%2Ftorrents%2F0529c736-0c49-4efd-a9ff-c4989b4c2071-720-hls.torrent&xt=urn:btih:a2662d0714edf3882193f782814441eb904460be&dn=VU+du+12%2F12%2F23+%3A+D%C3%A9mission+%22refrus%C3%A9e%22&tr=https%3A%2F%2Fpeertube.stream%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fpeertube.stream%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fpeertube.stream%2Fstatic%2Fstreaming-playlists%2Fhls%2F46cc7342-fdd5-4583-ae16-2eeb340d3b60%2F557f45f0-60b7-418c-bddd-e55701b387bb-720-fragmented.mp4", + "height": 720 + }, + { + "type": "Link", + "mediaType": "video/mp4", + "href": "https://peertube.stream/static/streaming-playlists/hls/46cc7342-fdd5-4583-ae16-2eeb340d3b60/097e6338-4c6e-4c21-8fed-7df0a245c9b3-480-fragmented.mp4", + "height": 480, + "size": 31542462, + "fps": 25 + }, + { + "type": "Link", + "rel": ["metadata", "video/mp4"], + "mediaType": "application/json", + "href": "https://peertube.stream/api/v1/videos/46cc7342-fdd5-4583-ae16-2eeb340d3b60/metadata/1570441", + "height": 480, + "fps": 25 + }, + { + "type": "Link", + "mediaType": "application/x-bittorrent", + "href": "https://peertube.stream/lazy-static/torrents/56b47f85-b2de-44b1-9089-db13c8534e1c-480-hls.torrent", + "height": 480 + }, + { + "type": "Link", + "mediaType": "application/x-bittorrent;x-scheme-handler/magnet", + "href": "magnet:?xs=https%3A%2F%2Fpeertube.stream%2Flazy-static%2Ftorrents%2F56b47f85-b2de-44b1-9089-db13c8534e1c-480-hls.torrent&xt=urn:btih:9d1cc84a448ba531d2f5422a8910fd79580768ff&dn=VU+du+12%2F12%2F23+%3A+D%C3%A9mission+%22refrus%C3%A9e%22&tr=https%3A%2F%2Fpeertube.stream%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fpeertube.stream%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fpeertube.stream%2Fstatic%2Fstreaming-playlists%2Fhls%2F46cc7342-fdd5-4583-ae16-2eeb340d3b60%2F097e6338-4c6e-4c21-8fed-7df0a245c9b3-480-fragmented.mp4", + "height": 480 + }, + { + "type": "Link", + "mediaType": "video/mp4", + "href": "https://peertube.stream/static/streaming-playlists/hls/46cc7342-fdd5-4583-ae16-2eeb340d3b60/b6db1f0c-0b6f-4f26-b811-d38631f4c42b-360-fragmented.mp4", + "height": 360, + "size": 23389554, + "fps": 25 + }, + { + "type": "Link", + "rel": ["metadata", "video/mp4"], + "mediaType": "application/json", + "href": "https://peertube.stream/api/v1/videos/46cc7342-fdd5-4583-ae16-2eeb340d3b60/metadata/1570442", + "height": 360, + "fps": 25 + }, + { + "type": "Link", + "mediaType": "application/x-bittorrent", + "href": "https://peertube.stream/lazy-static/torrents/89df203a-586e-4d09-b645-21c321ae81c2-360-hls.torrent", + "height": 360 + }, + { + "type": "Link", + "mediaType": "application/x-bittorrent;x-scheme-handler/magnet", + "href": "magnet:?xs=https%3A%2F%2Fpeertube.stream%2Flazy-static%2Ftorrents%2F89df203a-586e-4d09-b645-21c321ae81c2-360-hls.torrent&xt=urn:btih:40dbe1b6fb96d87d0750b32b26fd52913f22c84e&dn=VU+du+12%2F12%2F23+%3A+D%C3%A9mission+%22refrus%C3%A9e%22&tr=https%3A%2F%2Fpeertube.stream%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fpeertube.stream%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fpeertube.stream%2Fstatic%2Fstreaming-playlists%2Fhls%2F46cc7342-fdd5-4583-ae16-2eeb340d3b60%2Fb6db1f0c-0b6f-4f26-b811-d38631f4c42b-360-fragmented.mp4", + "height": 360 + }, + { + "type": "Link", + "mediaType": "video/mp4", + "href": "https://peertube.stream/static/streaming-playlists/hls/46cc7342-fdd5-4583-ae16-2eeb340d3b60/d0d23e04-a7b2-47f9-8072-94a06dc0c402-240-fragmented.mp4", + "height": 240, + "size": 16040535, + "fps": 25 + }, + { + "type": "Link", + "rel": ["metadata", "video/mp4"], + "mediaType": "application/json", + "href": "https://peertube.stream/api/v1/videos/46cc7342-fdd5-4583-ae16-2eeb340d3b60/metadata/1570448", + "height": 240, + "fps": 25 + }, + { + "type": "Link", + "mediaType": "application/x-bittorrent", + "href": "https://peertube.stream/lazy-static/torrents/29c43d5c-b26f-404c-a286-7aff2e2bb139-240-hls.torrent", + "height": 240 + }, + { + "type": "Link", + "mediaType": "application/x-bittorrent;x-scheme-handler/magnet", + "href": "magnet:?xs=https%3A%2F%2Fpeertube.stream%2Flazy-static%2Ftorrents%2F29c43d5c-b26f-404c-a286-7aff2e2bb139-240-hls.torrent&xt=urn:btih:f3f102c22d48b8a0aec19be463d8f04fb3a3f499&dn=VU+du+12%2F12%2F23+%3A+D%C3%A9mission+%22refrus%C3%A9e%22&tr=https%3A%2F%2Fpeertube.stream%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fpeertube.stream%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fpeertube.stream%2Fstatic%2Fstreaming-playlists%2Fhls%2F46cc7342-fdd5-4583-ae16-2eeb340d3b60%2Fd0d23e04-a7b2-47f9-8072-94a06dc0c402-240-fragmented.mp4", + "height": 240 + }, + { + "type": "Link", + "mediaType": "video/mp4", + "href": "https://peertube.stream/static/streaming-playlists/hls/46cc7342-fdd5-4583-ae16-2eeb340d3b60/6f3b1939-67c4-45f0-bd93-2508721dda69-144-fragmented.mp4", + "height": 144, + "size": 10969421, + "fps": 25 + }, + { + "type": "Link", + "rel": ["metadata", "video/mp4"], + "mediaType": "application/json", + "href": "https://peertube.stream/api/v1/videos/46cc7342-fdd5-4583-ae16-2eeb340d3b60/metadata/1570449", + "height": 144, + "fps": 25 + }, + { + "type": "Link", + "mediaType": "application/x-bittorrent", + "href": "https://peertube.stream/lazy-static/torrents/e39095d9-8fa2-4543-a66f-b4b9d6165a4e-144-hls.torrent", + "height": 144 + }, + { + "type": "Link", + "mediaType": "application/x-bittorrent;x-scheme-handler/magnet", + "href": "magnet:?xs=https%3A%2F%2Fpeertube.stream%2Flazy-static%2Ftorrents%2Fe39095d9-8fa2-4543-a66f-b4b9d6165a4e-144-hls.torrent&xt=urn:btih:8b263d7e814d611597a36dcd9655d959c86605a4&dn=VU+du+12%2F12%2F23+%3A+D%C3%A9mission+%22refrus%C3%A9e%22&tr=https%3A%2F%2Fpeertube.stream%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fpeertube.stream%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fpeertube.stream%2Fstatic%2Fstreaming-playlists%2Fhls%2F46cc7342-fdd5-4583-ae16-2eeb340d3b60%2F6f3b1939-67c4-45f0-bd93-2508721dda69-144-fragmented.mp4", + "height": 144 + }, + { + "type": "Link", + "mediaType": "video/mp4", + "href": "https://peertube.stream/static/streaming-playlists/hls/46cc7342-fdd5-4583-ae16-2eeb340d3b60/86ab6cca-46e5-4c6e-9c2c-8aef803b85f2-0-fragmented.mp4", + "height": 0, + "size": 6074306, + "fps": 0 + }, + { + "type": "Link", + "rel": ["metadata", "video/mp4"], + "mediaType": "application/json", + "href": "https://peertube.stream/api/v1/videos/46cc7342-fdd5-4583-ae16-2eeb340d3b60/metadata/1570439", + "height": 0, + "fps": 0 + }, + { + "type": "Link", + "mediaType": "application/x-bittorrent", + "href": "https://peertube.stream/lazy-static/torrents/25ae194d-c3ec-412a-886f-3b0d02599ca7-0-hls.torrent", + "height": 0 + }, + { + "type": "Link", + "mediaType": "application/x-bittorrent;x-scheme-handler/magnet", + "href": "magnet:?xs=https%3A%2F%2Fpeertube.stream%2Flazy-static%2Ftorrents%2F25ae194d-c3ec-412a-886f-3b0d02599ca7-0-hls.torrent&xt=urn:btih:e4458f2445732a228e9a83e2ae53a103f5e1097e&dn=VU+du+12%2F12%2F23+%3A+D%C3%A9mission+%22refrus%C3%A9e%22&tr=https%3A%2F%2Fpeertube.stream%2Ftracker%2Fannounce&tr=wss%3A%2F%2Fpeertube.stream%3A443%2Ftracker%2Fsocket&ws=https%3A%2F%2Fpeertube.stream%2Fstatic%2Fstreaming-playlists%2Fhls%2F46cc7342-fdd5-4583-ae16-2eeb340d3b60%2F86ab6cca-46e5-4c6e-9c2c-8aef803b85f2-0-fragmented.mp4", + "height": 0 + } + ] + }, + { + "type": "Link", + "name": "tracker-http", + "rel": ["tracker", "http"], + "href": "https://peertube.stream/tracker/announce" + }, + { + "type": "Link", + "name": "tracker-websocket", + "rel": ["tracker", "websocket"], + "href": "wss://peertube.stream:443/tracker/socket" + } + ], + "likes": "https://peertube.stream/videos/watch/46cc7342-fdd5-4583-ae16-2eeb340d3b60/likes", + "dislikes": "https://peertube.stream/videos/watch/46cc7342-fdd5-4583-ae16-2eeb340d3b60/dislikes", + "shares": "https://peertube.stream/videos/watch/46cc7342-fdd5-4583-ae16-2eeb340d3b60/announces", + "comments": "https://peertube.stream/videos/watch/46cc7342-fdd5-4583-ae16-2eeb340d3b60/comments", + "hasParts": "https://peertube.stream/videos/watch/46cc7342-fdd5-4583-ae16-2eeb340d3b60/chapters", + "attributedTo": [ + { + "type": "Person", + "id": "https://peertube.stream/accounts/createurs" + }, + { + "type": "Group", + "id": "https://peertube.stream/video-channels/vu" + } + ], + "isLiveBroadcast": false, + "liveSaveReplay": null, + "permanentLive": null, + "latencyMode": null, + "peertubeLiveChat": false } diff --git a/crates/apub/src/activities/mod.rs b/crates/apub/src/activities/mod.rs index ee3eb16ff..83d029d4e 100644 --- a/crates/apub/src/activities/mod.rs +++ b/crates/apub/src/activities/mod.rs @@ -225,11 +225,12 @@ where Ok(()) } -pub async fn handle_outgoing_activities(context: Data) -> LemmyResult<()> { +pub async fn handle_outgoing_activities(context: Data) { while let Some(data) = ActivityChannel::retrieve_activity().await { - match_outgoing_activities(data, &context.reset_request_count()).await? + if let Err(e) = match_outgoing_activities(data, &context.reset_request_count()).await { + tracing::warn!("error while saving outgoing activity to db: {e}"); + } } - Ok(()) } pub async fn match_outgoing_activities( diff --git a/crates/apub/src/api/read_person.rs b/crates/apub/src/api/read_person.rs index 26ad287f1..b32fc5b5f 100644 --- a/crates/apub/src/api/read_person.rs +++ b/crates/apub/src/api/read_person.rs @@ -65,7 +65,6 @@ pub async fn read_person( saved_only, local_user: local_user_view.as_ref(), community_id, - is_profile_view: true, page, limit, creator_id, @@ -79,7 +78,6 @@ pub async fn read_person( sort: sort.map(post_to_comment_sort_type), saved_only, community_id, - is_profile_view: true, page, limit, creator_id, diff --git a/crates/apub/src/http/mod.rs b/crates/apub/src/http/mod.rs index 7c1d8529a..d3e925de4 100644 --- a/crates/apub/src/http/mod.rs +++ b/crates/apub/src/http/mod.rs @@ -96,6 +96,13 @@ pub(crate) async fn get_activity( if sensitive { Ok(HttpResponse::Forbidden().finish()) } else { - create_apub_response(&activity.data) + // Don't use create_apub_response() to avoid duplicate context (the activity stored in db + // already includes context). + let json = serde_json::to_string_pretty(&activity.data)?; + Ok( + HttpResponse::Ok() + .content_type(FEDERATION_CONTENT_TYPE) + .body(json), + ) } } diff --git a/crates/apub/src/protocol/objects/group.rs b/crates/apub/src/protocol/objects/group.rs index 2b70d1fa5..1a85cb59f 100644 --- a/crates/apub/src/protocol/objects/group.rs +++ b/crates/apub/src/protocol/objects/group.rs @@ -52,6 +52,7 @@ pub struct Group { pub(crate) summary: Option, #[serde(deserialize_with = "deserialize_skip_error", default)] pub(crate) source: Option, + #[serde(deserialize_with = "deserialize_skip_error", default)] pub(crate) icon: Option, /// banner pub(crate) image: Option, diff --git a/crates/apub/src/protocol/objects/person.rs b/crates/apub/src/protocol/objects/person.rs index cc9607c7f..c8cae5541 100644 --- a/crates/apub/src/protocol/objects/person.rs +++ b/crates/apub/src/protocol/objects/person.rs @@ -38,6 +38,7 @@ pub struct Person { #[serde(deserialize_with = "deserialize_skip_error", default)] pub(crate) source: Option, /// user avatar + #[serde(deserialize_with = "deserialize_skip_error", default)] pub(crate) icon: Option, /// user banner pub(crate) image: Option, diff --git a/crates/db_schema/Cargo.toml b/crates/db_schema/Cargo.toml index 67fea0c04..fc2957e8f 100644 --- a/crates/db_schema/Cargo.toml +++ b/crates/db_schema/Cargo.toml @@ -67,7 +67,7 @@ once_cell = { workspace = true, optional = true } diesel_ltree = { workspace = true, optional = true } async-trait = { workspace = true } tracing = { workspace = true } -deadpool = { version = "0.9.5", features = ["rt_tokio_1"], optional = true } +deadpool = { version = "0.10.0", features = ["rt_tokio_1"], optional = true } ts-rs = { workspace = true, optional = true } futures-util = { workspace = true } tokio = { workspace = true, optional = true } diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index 35bc8314a..7173b79d2 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -59,52 +59,55 @@ impl Comment { ) -> Result { let conn = &mut get_conn(pool).await?; - // Insert, to get the id - let inserted_comment = insert_into(comment) - .values(comment_form) - .on_conflict(ap_id) - .do_update() - .set(comment_form) - .get_result::(conn) - .await; + conn + .build_transaction() + .run(|conn| { + Box::pin(async move { + // Insert, to get the id + let inserted_comment = insert_into(comment) + .values(comment_form) + .on_conflict(ap_id) + .do_update() + .set(comment_form) + .get_result::(conn) + .await?; - if let Ok(comment_insert) = inserted_comment { - let comment_id = comment_insert.id; + let comment_id = inserted_comment.id; - // You need to update the ltree column - let ltree = Ltree(if let Some(parent_path) = parent_path { - // The previous parent will already have 0 in it - // Append this comment id - format!("{}.{}", parent_path.0, comment_id) - } else { - // '0' is always the first path, append to that - format!("{}.{}", 0, comment_id) - }); + // You need to update the ltree column + let ltree = Ltree(if let Some(parent_path) = parent_path { + // The previous parent will already have 0 in it + // Append this comment id + format!("{}.{}", parent_path.0, comment_id) + } else { + // '0' is always the first path, append to that + format!("{}.{}", 0, comment_id) + }); - let updated_comment = diesel::update(comment.find(comment_id)) - .set(path.eq(ltree)) - .get_result::(conn) - .await; + let updated_comment = diesel::update(comment.find(comment_id)) + .set(path.eq(ltree)) + .get_result::(conn) + .await?; - // Update the child count for the parent comment_aggregates - // You could do this with a trigger, but since you have to do this manually anyway, - // you can just have it here - if let Some(parent_path) = parent_path { - // You have to update counts for all parents, not just the immediate one - // TODO if the performance of this is terrible, it might be better to do this as part of a - // scheduled query... although the counts would often be wrong. - // - // The child_count query for reference: - // select c.id, c.path, count(c2.id) as child_count from comment c - // left join comment c2 on c2.path <@ c.path and c2.path != c.path - // group by c.id + // Update the child count for the parent comment_aggregates + // You could do this with a trigger, but since you have to do this manually anyway, + // you can just have it here + if let Some(parent_path) = parent_path { + // You have to update counts for all parents, not just the immediate one + // TODO if the performance of this is terrible, it might be better to do this as part of a + // scheduled query... although the counts would often be wrong. + // + // The child_count query for reference: + // select c.id, c.path, count(c2.id) as child_count from comment c + // left join comment c2 on c2.path <@ c.path and c2.path != c.path + // group by c.id - let parent_id = parent_path.0.split('.').nth(1); + let parent_id = parent_path.0.split('.').nth(1); - if let Some(parent_id) = parent_id { - let top_parent = format!("0.{}", parent_id); - let update_child_count_stmt = format!( - " + if let Some(parent_id) = parent_id { + let top_parent = format!("0.{}", parent_id); + let update_child_count_stmt = format!( + " update comment_aggregates ca set child_count = c.child_count from ( select c.id, c.path, count(c2.id) as child_count from comment c @@ -113,15 +116,15 @@ from ( group by c.id ) as c where ca.comment_id = c.id" - ); + ); - sql_query(update_child_count_stmt).execute(conn).await?; - } - } - updated_comment - } else { - inserted_comment - } + sql_query(update_child_count_stmt).execute(conn).await?; + } + } + Ok(updated_comment) + }) as _ + }) + .await } pub async fn read_from_apub_id( pool: &mut DbPool<'_>, diff --git a/crates/db_schema/src/impls/instance.rs b/crates/db_schema/src/impls/instance.rs index 7da4ce354..7d63c9ffa 100644 --- a/crates/db_schema/src/impls/instance.rs +++ b/crates/db_schema/src/impls/instance.rs @@ -13,12 +13,17 @@ use crate::{ federation_queue_state::FederationQueueState, instance::{Instance, InstanceForm}, }, - utils::{functions::lower, get_conn, naive_now, now, DbPool}, + utils::{ + functions::{coalesce, lower}, + get_conn, + naive_now, + now, + DbPool, + }, }; use diesel::{ dsl::{count_star, insert_into}, result::Error, - sql_types::{Nullable, Timestamptz}, ExpressionMethods, NullableExpressionMethods, QueryDsl, @@ -157,5 +162,3 @@ impl Instance { .await } } - -sql_function! { fn coalesce(x: Nullable, y: Timestamptz) -> Timestamptz; } diff --git a/crates/db_schema/src/impls/post.rs b/crates/db_schema/src/impls/post.rs index d1880e6e2..caa54c167 100644 --- a/crates/db_schema/src/impls/post.rs +++ b/crates/db_schema/src/impls/post.rs @@ -1,4 +1,3 @@ -use super::instance::coalesce; use crate::{ newtypes::{CommunityId, DbUrl, PersonId, PostId}, schema::post::dsl::{ @@ -29,7 +28,16 @@ use crate::{ PostUpdateForm, }, traits::{Crud, Likeable, Saveable}, - utils::{get_conn, naive_now, DbPool, DELETED_REPLACEMENT_TEXT, FETCH_LIMIT_MAX}, + utils::{ + functions::coalesce, + get_conn, + naive_now, + DbPool, + DELETED_REPLACEMENT_TEXT, + FETCH_LIMIT_MAX, + SITEMAP_DAYS, + SITEMAP_LIMIT, + }, }; use ::url::Url; use chrono::{Duration, Utc}; @@ -109,8 +117,9 @@ impl Post { .filter(local.eq(true)) .filter(deleted.eq(false)) .filter(removed.eq(false)) - .filter(published.ge(Utc::now().naive_utc() - Duration::days(1))) + .filter(published.ge(Utc::now().naive_utc() - Duration::days(SITEMAP_DAYS))) .order(published.desc()) + .limit(SITEMAP_LIMIT) .load::<(DbUrl, chrono::DateTime)>(conn) .await } diff --git a/crates/db_schema/src/lib.rs b/crates/db_schema/src/lib.rs index 8d5ad8d79..a53a1733c 100644 --- a/crates/db_schema/src/lib.rs +++ b/crates/db_schema/src/lib.rs @@ -31,7 +31,11 @@ pub mod schema; #[cfg(feature = "full")] pub mod aliases { use crate::schema::{community_moderator, person}; - diesel::alias!(person as person1: Person1, person as person2: Person2, community_moderator as community_moderator1: CommunityModerator1); + diesel::alias!( + person as person1: Person1, + person as person2: Person2, + community_moderator as community_moderator1: CommunityModerator1 + ); } pub mod source; #[cfg(feature = "full")] diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index 1e67bd04d..7c5e05dd7 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -24,6 +24,7 @@ use diesel_async::{ pooled_connection::{ deadpool::{Object as PooledConnection, Pool}, AsyncDieselConnectionManager, + ManagerConfig, }, }; use diesel_migrations::EmbeddedMigrations; @@ -45,7 +46,10 @@ use url::Url; const FETCH_LIMIT_DEFAULT: i64 = 10; pub const FETCH_LIMIT_MAX: i64 = 50; +pub const SITEMAP_LIMIT: i64 = 50000; +pub const SITEMAP_DAYS: i64 = 31; const POOL_TIMEOUT: Option = Some(Duration::from_secs(5)); +pub const RANK_DEFAULT: f64 = 0.0001; pub type ActualDbPool = Pool; @@ -261,7 +265,9 @@ pub async fn build_db_pool() -> Result { let manager = if tls_enabled { // diesel-async does not support any TLS connections out of the box, so we need to manually // provide a setup function which handles creating the connection - AsyncDieselConnectionManager::::new_with_setup(&db_url, establish_connection) + let mut config = ManagerConfig::default(); + config.custom_setup = Box::new(establish_connection); + AsyncDieselConnectionManager::::new_with_config(&db_url, config) } else { AsyncDieselConnectionManager::::new(&db_url) }; diff --git a/crates/db_views/Cargo.toml b/crates/db_views/Cargo.toml index 847b74392..5c8fd21eb 100644 --- a/crates/db_views/Cargo.toml +++ b/crates/db_views/Cargo.toml @@ -41,3 +41,4 @@ actix-web = { workspace = true, optional = true } [dev-dependencies] serial_test = { workspace = true } tokio = { workspace = true } +chrono = { workspace = true } diff --git a/crates/db_views/src/comment_report_view.rs b/crates/db_views/src/comment_report_view.rs index b883fb8fe..a26b984b2 100644 --- a/crates/db_views/src/comment_report_view.rs +++ b/crates/db_views/src/comment_report_view.rs @@ -105,16 +105,18 @@ fn queries<'a>() -> Queries< query = query.filter(post::community_id.eq(community_id)); } + // If viewing all reports, order by newest, but if viewing unresolved only, show the oldest first (FIFO) if options.unresolved_only { - query = query.filter(comment_report::resolved.eq(false)); + query = query + .filter(comment_report::resolved.eq(false)) + .order_by(comment_report::published.asc()); + } else { + query = query.order_by(comment_report::published.desc()); } let (limit, offset) = limit_and_offset(options.page, options.limit)?; - query = query - .order_by(comment_report::published.asc()) - .limit(limit) - .offset(offset); + query = query.limit(limit).offset(offset); // If its not an admin, get only the ones you mod if !user.local_user.admin { @@ -230,7 +232,7 @@ mod tests { post::{Post, PostInsertForm}, }, traits::{Crud, Joinable, Reportable}, - utils::build_db_pool_for_tests, + utils::{build_db_pool_for_tests, RANK_DEFAULT}, }; use serial_test::serial; @@ -431,7 +433,7 @@ mod tests { downvotes: 0, published: agg.published, child_count: 0, - hot_rank: 0.1728, + hot_rank: RANK_DEFAULT, controversy_rank: 0.0, }, my_vote: None, @@ -475,8 +477,8 @@ mod tests { assert_eq!( reports, [ - expected_sara_report_view.clone(), expected_jessica_report_view.clone(), + expected_sara_report_view.clone(), ] ); diff --git a/crates/db_views/src/comment_view.rs b/crates/db_views/src/comment_view.rs index 99e8c9661..4b6db17a5 100644 --- a/crates/db_views/src/comment_view.rs +++ b/crates/db_views/src/comment_view.rs @@ -177,14 +177,18 @@ fn queries<'a>() -> Queries< }; let list = move |mut conn: DbConn<'a>, options: CommentQuery<'a>| async move { - let person_id = options.local_user.map(|l| l.person.id); - let local_user_id = options.local_user.map(|l| l.local_user.id); + let my_person_id = options.local_user.map(|l| l.person.id); + let my_local_user_id = options.local_user.map(|l| l.local_user.id); // The left join below will return None in this case - let person_id_join = person_id.unwrap_or(PersonId(-1)); - let local_user_id_join = local_user_id.unwrap_or(LocalUserId(-1)); + let person_id_join = my_person_id.unwrap_or(PersonId(-1)); + let local_user_id_join = my_local_user_id.unwrap_or(LocalUserId(-1)); - let mut query = all_joins(comment::table.into_boxed(), person_id, options.saved_only); + let mut query = all_joins( + comment::table.into_boxed(), + my_person_id, + options.saved_only, + ); if let Some(creator_id) = options.creator_id { query = query.filter(comment::creator_id.eq(creator_id)); @@ -373,7 +377,6 @@ pub struct CommentQuery<'a> { pub saved_only: bool, pub liked_only: bool, pub disliked_only: bool, - pub is_profile_view: bool, pub page: Option, pub limit: Option, pub max_depth: Option, @@ -410,7 +413,7 @@ mod tests { post::{Post, PostInsertForm}, }, traits::{Blockable, Crud, Joinable, Likeable}, - utils::build_db_pool_for_tests, + utils::{build_db_pool_for_tests, RANK_DEFAULT}, SubscribedType, }; use serial_test::serial; @@ -1045,7 +1048,7 @@ mod tests { downvotes: 0, published: agg.published, child_count: 5, - hot_rank: 0.1728, + hot_rank: RANK_DEFAULT, controversy_rank: 0.0, }, } diff --git a/crates/db_views/src/local_user_view.rs b/crates/db_views/src/local_user_view.rs index dd0e3631b..cb9ab86c4 100644 --- a/crates/db_views/src/local_user_view.rs +++ b/crates/db_views/src/local_user_view.rs @@ -5,7 +5,14 @@ use diesel_async::RunQueryDsl; use lemmy_db_schema::{ newtypes::{LocalUserId, PersonId}, schema::{local_user, person, person_aggregates}, - utils::{functions::lower, DbConn, DbPool, ListFn, Queries, ReadFn}, + utils::{ + functions::{coalesce, lower}, + DbConn, + DbPool, + ListFn, + Queries, + ReadFn, + }, }; use lemmy_utils::error::{LemmyError, LemmyErrorType}; use std::future::{ready, Ready}; @@ -34,7 +41,9 @@ fn queries<'a>( let mut query = local_user::table.into_boxed(); query = match search { ReadBy::Id(local_user_id) => query.filter(local_user::id.eq(local_user_id)), - ReadBy::Email(from_email) => query.filter(local_user::email.eq(from_email)), + ReadBy::Email(from_email) => { + query.filter(lower(coalesce(local_user::email, "")).eq(from_email.to_lowercase())) + } _ => query, }; let mut query = query.inner_join(person::table); @@ -43,8 +52,8 @@ fn queries<'a>( ReadBy::Name(name) => query.filter(lower(person::name).eq(name.to_lowercase())), ReadBy::NameOrEmail(name_or_email) => query.filter( lower(person::name) - .eq(lower(name_or_email)) - .or(local_user::email.eq(name_or_email)), + .eq(lower(name_or_email.to_lowercase())) + .or(lower(coalesce(local_user::email, "")).eq(name_or_email.to_lowercase())), ), _ => query, }; diff --git a/crates/db_views/src/post_report_view.rs b/crates/db_views/src/post_report_view.rs index 32d8f8392..843b1ee54 100644 --- a/crates/db_views/src/post_report_view.rs +++ b/crates/db_views/src/post_report_view.rs @@ -83,16 +83,18 @@ fn queries<'a>() -> Queries< query = query.filter(post::community_id.eq(community_id)); } + // If viewing all reports, order by newest, but if viewing unresolved only, show the oldest first (FIFO) if options.unresolved_only { - query = query.filter(post_report::resolved.eq(false)); + query = query + .filter(post_report::resolved.eq(false)) + .order_by(post_report::published.asc()); + } else { + query = query.order_by(post_report::published.desc()); } let (limit, offset) = limit_and_offset(options.page, options.limit)?; - query = query - .order_by(post_report::published.asc()) - .limit(limit) - .offset(offset); + query = query.limit(limit).offset(offset); // If its not an admin, get only the ones you mod if !user.local_user.admin { @@ -337,8 +339,8 @@ mod tests { .await .unwrap(); - assert_eq!(reports[0].creator.id, inserted_sara.id); - assert_eq!(reports[1].creator.id, inserted_jessica.id); + assert_eq!(reports[1].creator.id, inserted_sara.id); + assert_eq!(reports[0].creator.id, inserted_jessica.id); // Make sure the counts are correct let report_count = PostReportView::get_report_count(pool, inserted_timmy.id, false, None) diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index 1292d577e..5868dbbb0 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -1,15 +1,12 @@ use crate::structs::{LocalUserView, PaginationCursor, PostView}; use diesel::{ debug_query, - dsl::{self, exists, not, IntervalDsl}, - expression::AsExpression, + dsl::{exists, not, IntervalDsl}, pg::Pg, result::Error, - sql_function, - sql_types::{self, SingleValue, SqlType, Timestamptz}, + sql_types, BoolExpressionMethods, BoxableExpression, - Expression, ExpressionMethods, IntoSql, JoinOnDsl, @@ -35,66 +32,54 @@ use lemmy_db_schema::{ person_block, person_post_aggregates, post, - post_aggregates::{self, newest_comment_time}, + post_aggregates, post_like, post_read, post_saved, }, - utils::{fuzzy_search, get_conn, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, + utils::{ + functions::coalesce, + fuzzy_search, + get_conn, + limit_and_offset, + now, + DbConn, + DbPool, + ListFn, + Queries, + ReadFn, + }, ListingType, SortType, }; use tracing::debug; -sql_function!(fn coalesce(x: sql_types::Nullable, y: sql_types::BigInt) -> sql_types::BigInt); - -fn order_and_page_filter_desc( - query: Q, - column: C, - options: &PostQuery, - getter: impl Fn(&PostAggregates) -> T, -) -> Q -where - Q: diesel::query_dsl::methods::ThenOrderDsl, Output = Q> - + diesel::query_dsl::methods::ThenOrderDsl, Output = Q> - + diesel::query_dsl::methods::FilterDsl, Output = Q> - + diesel::query_dsl::methods::FilterDsl, Output = Q>, - C: Expression + Copy, - C::SqlType: SingleValue + SqlType, - T: AsExpression, -{ - let mut query = query.then_order_by(column.desc()); - if let Some(before) = &options.page_before_or_equal { - query = query.filter(column.ge(getter(&before.0))); - } - if let Some(after) = &options.page_after { - query = query.filter(column.le(getter(&after.0))); - } - query +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum Ord { + Desc, + Asc, } -fn order_and_page_filter_asc( - query: Q, - column: C, - options: &PostQuery, - getter: impl Fn(&PostAggregates) -> T, -) -> Q -where - Q: diesel::query_dsl::methods::ThenOrderDsl, Output = Q> - + diesel::query_dsl::methods::FilterDsl, Output = Q> - + diesel::query_dsl::methods::FilterDsl, Output = Q>, - C: Expression + Copy, - C::SqlType: SingleValue + SqlType, - T: AsExpression, -{ - let mut query = query.then_order_by(column.asc()); - if let Some(before) = &options.page_before_or_equal { - query = query.filter(column.le(getter(&before.0))); - } - if let Some(after) = &options.page_after { - query = query.filter(column.ge(getter(&after.0))); - } - query +struct PaginationCursorField { + then_order_by_desc: fn(Q) -> Q, + then_order_by_asc: fn(Q) -> Q, + le: fn(&PostAggregates) -> Box>, + ge: fn(&PostAggregates) -> Box>, + ne: fn(&PostAggregates) -> Box>, +} + +/// Returns `PaginationCursorField<_, _>` for the given name +macro_rules! field { + ($name:ident) => { + // Type inference doesn't work if normal method call syntax is used + PaginationCursorField { + then_order_by_desc: |query| QueryDsl::then_order_by(query, post_aggregates::$name.desc()), + then_order_by_asc: |query| QueryDsl::then_order_by(query, post_aggregates::$name.asc()), + le: |e| Box::new(post_aggregates::$name.le(e.$name)), + ge: |e| Box::new(post_aggregates::$name.ge(e.$name)), + ne: |e| Box::new(post_aggregates::$name.ne(e.$name)), + } + }; } fn queries<'a>() -> Queries< @@ -274,8 +259,16 @@ fn queries<'a>() -> Queries< // Hide deleted and removed for non-admins or mods if !is_mod_or_admin { query = query - .filter(community::removed.eq(false)) - .filter(post::removed.eq(false)) + .filter( + community::removed + .eq(false) + .or(post::creator_id.eq(person_id_join)), + ) + .filter( + post::removed + .eq(false) + .or(post::creator_id.eq(person_id_join)), + ) // users can see their own deleted posts .filter( community::deleted @@ -293,16 +286,16 @@ fn queries<'a>() -> Queries< }; let list = move |mut conn: DbConn<'a>, options: PostQuery<'a>| async move { - let person_id = options.local_user.map(|l| l.person.id); - let local_user_id = options.local_user.map(|l| l.local_user.id); + let my_person_id = options.local_user.map(|l| l.person.id); + let my_local_user_id = options.local_user.map(|l| l.local_user.id); // The left join below will return None in this case - let person_id_join = person_id.unwrap_or(PersonId(-1)); - let local_user_id_join = local_user_id.unwrap_or(LocalUserId(-1)); + let person_id_join = my_person_id.unwrap_or(PersonId(-1)); + let local_user_id_join = my_local_user_id.unwrap_or(LocalUserId(-1)); let mut query = all_joins( post_aggregates::table.into_boxed(), - person_id, + my_person_id, options.saved_only, ); @@ -310,7 +303,7 @@ fn queries<'a>() -> Queries< query = query.filter(community::deleted.eq(false)); // only show deleted posts to creator - if let Some(person_id) = person_id { + if let Some(person_id) = my_person_id { query = query.filter(post::deleted.eq(false).or(post::creator_id.eq(person_id))); } else { query = query.filter(post::deleted.eq(false)); @@ -321,21 +314,11 @@ fn queries<'a>() -> Queries< .map(|l| l.local_user.admin) .unwrap_or(false); // only show removed posts to admin when viewing user profile - if !(options.is_profile_view && is_admin) { + if !(options.creator_id.is_some() && is_admin) { query = query .filter(community::removed.eq(false)) .filter(post::removed.eq(false)); } - if options.community_id.is_none() || options.community_id_just_for_prefetch { - query = order_and_page_filter_desc(query, post_aggregates::featured_local, &options, |e| { - e.featured_local - }); - } else { - query = - order_and_page_filter_desc(query, post_aggregates::featured_community, &options, |e| { - e.featured_community - }); - } if let Some(community_id) = options.community_id { query = query.filter(post_aggregates::community_id.eq(community_id)); } @@ -344,41 +327,47 @@ fn queries<'a>() -> Queries< query = query.filter(post_aggregates::creator_id.eq(creator_id)); } - if let Some(person_id) = person_id { - let is_subscribed = exists( - community_follower::table.filter( - post_aggregates::community_id - .eq(community_follower::community_id) - .and(community_follower::person_id.eq(person_id)), - ), - ); - match options.listing_type.unwrap_or_default() { - ListingType::Subscribed => query = query.filter(is_subscribed), - ListingType::Local => { - query = query - .filter(community::local.eq(true)) - .filter(community::hidden.eq(false).or(is_subscribed)); + if let Some(listing_type) = options.listing_type { + if let Some(person_id) = my_person_id { + let is_subscribed = exists( + community_follower::table.filter( + post_aggregates::community_id + .eq(community_follower::community_id) + .and(community_follower::person_id.eq(person_id)), + ), + ); + match listing_type { + ListingType::Subscribed => query = query.filter(is_subscribed), + ListingType::Local => { + query = query + .filter(community::local.eq(true)) + .filter(community::hidden.eq(false).or(is_subscribed)); + } + ListingType::All => query = query.filter(community::hidden.eq(false).or(is_subscribed)), + ListingType::ModeratorView => { + query = query.filter(exists( + community_moderator::table.filter( + post::community_id + .eq(community_moderator::community_id) + .and(community_moderator::person_id.eq(person_id)), + ), + )); + } } - ListingType::All => query = query.filter(community::hidden.eq(false).or(is_subscribed)), - ListingType::ModeratorView => { - query = query.filter(exists( - community_moderator::table.filter( - post::community_id - .eq(community_moderator::community_id) - .and(community_moderator::person_id.eq(person_id)), - ), - )); + } + // If your person_id is missing, only show local + else { + match listing_type { + ListingType::Local => { + query = query + .filter(community::local.eq(true)) + .filter(community::hidden.eq(false)); + } + _ => query = query.filter(community::hidden.eq(false)), } } } else { - match options.listing_type.unwrap_or_default() { - ListingType::Local => { - query = query - .filter(community::local.eq(true)) - .filter(community::hidden.eq(false)); - } - _ => query = query.filter(community::hidden.eq(false)), - } + query = query.filter(community::hidden.eq(false)); } if let Some(url_search) = &options.url_search { @@ -412,7 +401,7 @@ fn queries<'a>() -> Queries< query = query.filter(person::bot_account.eq(false)); }; - if let (true, Some(person_id)) = (options.saved_only, person_id) { + if let (true, Some(person_id)) = (options.saved_only, my_person_id) { query = query.filter(is_saved(person_id)); } // Only hide the read posts, if the saved_only is false. Otherwise ppl with the hide_read @@ -423,12 +412,13 @@ fn queries<'a>() -> Queries< .unwrap_or(true) { // Do not hide read posts when it is a user profile view - if let (false, Some(person_id)) = (options.is_profile_view, person_id) { + // Or, only hide read posts on non-profile views + if let (None, Some(person_id)) = (options.creator_id, my_person_id) { query = query.filter(not(is_read(person_id))); } } - if let Some(person_id) = person_id { + if let Some(person_id) = my_person_id { if options.liked_only { query = query.filter(score(person_id).eq(1)); } else if options.disliked_only { @@ -438,7 +428,7 @@ fn queries<'a>() -> Queries< // Dont filter blocks or missing languages for moderator view type if let (Some(person_id), false) = ( - person_id, + my_person_id, options.listing_type.unwrap_or_default() == ListingType::ModeratorView, ) { // Filter out the rows with missing languages @@ -467,86 +457,96 @@ fn queries<'a>() -> Queries< ))); query = query.filter(not(is_creator_blocked(person_id))); } - let now = diesel::dsl::now.into_sql::(); + let featured_field = if options.community_id.is_none() || options.community_id_just_for_prefetch { - use post_aggregates::{ - comments, - controversy_rank, - hot_rank, - hot_rank_active, - published, - scaled_rank, - score, - }; - match options.sort.as_ref().unwrap_or(&SortType::Hot) { - SortType::Active => { - query = - order_and_page_filter_desc(query, hot_rank_active, &options, |e| e.hot_rank_active); - query = order_and_page_filter_desc(query, published, &options, |e| e.published); - } - SortType::Hot => { - query = order_and_page_filter_desc(query, hot_rank, &options, |e| e.hot_rank); - query = order_and_page_filter_desc(query, published, &options, |e| e.published); - } - SortType::Scaled => { - query = order_and_page_filter_desc(query, scaled_rank, &options, |e| e.scaled_rank); - query = order_and_page_filter_desc(query, published, &options, |e| e.published); - } - SortType::Controversial => { - query = - order_and_page_filter_desc(query, controversy_rank, &options, |e| e.controversy_rank); - query = order_and_page_filter_desc(query, published, &options, |e| e.published); - } - SortType::New => { - query = order_and_page_filter_desc(query, published, &options, |e| e.published) - } - SortType::Old => { - query = order_and_page_filter_asc(query, published, &options, |e| e.published) - } - SortType::NewComments => { - query = order_and_page_filter_desc(query, newest_comment_time, &options, |e| { - e.newest_comment_time - }) - } - SortType::MostComments => { - query = order_and_page_filter_desc(query, comments, &options, |e| e.comments); - query = order_and_page_filter_desc(query, published, &options, |e| e.published); - } - SortType::TopAll => { - query = order_and_page_filter_desc(query, score, &options, |e| e.score); - query = order_and_page_filter_desc(query, published, &options, |e| e.published); - } - o @ (SortType::TopYear - | SortType::TopMonth - | SortType::TopWeek - | SortType::TopDay - | SortType::TopHour - | SortType::TopSixHour - | SortType::TopTwelveHour - | SortType::TopThreeMonths - | SortType::TopSixMonths - | SortType::TopNineMonths) => { - let interval = match o { - SortType::TopYear => 1.years(), - SortType::TopMonth => 1.months(), - SortType::TopWeek => 1.weeks(), - SortType::TopDay => 1.days(), - SortType::TopHour => 1.hours(), - SortType::TopSixHour => 6.hours(), - SortType::TopTwelveHour => 12.hours(), - SortType::TopThreeMonths => 3.months(), - SortType::TopSixMonths => 6.months(), - SortType::TopNineMonths => 9.months(), - _ => return Err(Error::NotFound), - }; - query = query.filter(post_aggregates::published.gt(now - interval)); - query = order_and_page_filter_desc(query, score, &options, |e| e.score); - query = order_and_page_filter_desc(query, published, &options, |e| e.published); - } - } + field!(featured_local) + } else { + field!(featured_community) }; + let (main_sort, top_sort_interval) = match options.sort.unwrap_or(SortType::Hot) { + SortType::Active => ((Ord::Desc, field!(hot_rank_active)), None), + SortType::Hot => ((Ord::Desc, field!(hot_rank)), None), + SortType::Scaled => ((Ord::Desc, field!(scaled_rank)), None), + SortType::Controversial => ((Ord::Desc, field!(controversy_rank)), None), + SortType::New => ((Ord::Desc, field!(published)), None), + SortType::Old => ((Ord::Asc, field!(published)), None), + SortType::NewComments => ((Ord::Desc, field!(newest_comment_time)), None), + SortType::MostComments => ((Ord::Desc, field!(comments)), None), + SortType::TopAll => ((Ord::Desc, field!(score)), None), + SortType::TopYear => ((Ord::Desc, field!(score)), Some(1.years())), + SortType::TopMonth => ((Ord::Desc, field!(score)), Some(1.months())), + SortType::TopWeek => ((Ord::Desc, field!(score)), Some(1.weeks())), + SortType::TopDay => ((Ord::Desc, field!(score)), Some(1.days())), + SortType::TopHour => ((Ord::Desc, field!(score)), Some(1.hours())), + SortType::TopSixHour => ((Ord::Desc, field!(score)), Some(6.hours())), + SortType::TopTwelveHour => ((Ord::Desc, field!(score)), Some(12.hours())), + SortType::TopThreeMonths => ((Ord::Desc, field!(score)), Some(3.months())), + SortType::TopSixMonths => ((Ord::Desc, field!(score)), Some(6.months())), + SortType::TopNineMonths => ((Ord::Desc, field!(score)), Some(9.months())), + }; + + if let Some(interval) = top_sort_interval { + query = query.filter(post_aggregates::published.gt(now() - interval)); + } + + let sorts = [ + Some((Ord::Desc, featured_field)), + Some(main_sort), + Some((Ord::Desc, field!(post_id))), + ]; + let sorts_iter = sorts.iter().flatten(); + + // This loop does almost the same thing as sorting by and comparing tuples. If the rows were + // only sorted by 1 field called `foo` in descending order, then it would be like this: + // + // ``` + // query = query.then_order_by(foo.desc()); + // if let Some(first) = &options.page_after { + // query = query.filter(foo.le(first.foo)); + // } + // if let Some(last) = &page_before_or_equal { + // query = query.filter(foo.ge(last.foo)); + // } + // ``` + // + // If multiple rows have the same value for a sorted field, then they are + // grouped together, and the rows in that group are sorted by the next fields. + // When checking if a row is within the range determined by the cursors, a field + // that's sorted after other fields is only compared if the row and the cursor + // are in the same group created by the previous sort, which is checked by using + // `or` to skip the comparison if any previously sorted field is not equal. + for (i, (order, field)) in sorts_iter.clone().enumerate() { + // Both cursors are treated as inclusive here. `page_after` is made exclusive + // by adding `1` to the offset. + let (then_order_by_field, compare_first, compare_last) = match order { + Ord::Desc => (field.then_order_by_desc, field.le, field.ge), + Ord::Asc => (field.then_order_by_asc, field.ge, field.le), + }; + + query = then_order_by_field(query); + + for (cursor_data, compare) in [ + (&options.page_after, compare_first), + (&options.page_before_or_equal, compare_last), + ] { + let Some(cursor_data) = cursor_data else { + continue; + }; + let mut condition: Box> = + Box::new(compare(&cursor_data.0)); + + // For each field that was sorted before the current one, skip the filter by changing + // `condition` to `true` if the row's value doesn't equal the cursor's value. + for (_, other_field) in sorts_iter.clone().take(i) { + condition = Box::new(condition.or((other_field.ne)(&cursor_data.0))); + } + + query = query.filter(condition); + } + } + let (limit, mut offset) = limit_and_offset(options.page, options.limit)?; if options.page_after.is_some() { // always skip exactly one post because that's the last post of the previous page @@ -621,8 +621,6 @@ pub struct PostQuery<'a> { pub saved_only: bool, pub liked_only: bool, pub disliked_only: bool, - pub moderator_view: bool, - pub is_profile_view: bool, pub page: Option, pub limit: Option, pub page_after: Option, @@ -725,15 +723,17 @@ mod tests { #![allow(clippy::indexing_slicing)] use crate::{ - post_view::{PostQuery, PostView}, + post_view::{PaginationCursorData, PostQuery, PostView}, structs::LocalUserView, }; + use chrono::Utc; use lemmy_db_schema::{ aggregates::structs::PostAggregates, impls::actor_language::UNDETERMINED_ID, newtypes::LanguageId, source::{ actor_language::LocalUserLanguage, + comment::{Comment, CommentInsertForm}, community::{Community, CommunityInsertForm, CommunityModerator, CommunityModeratorForm}, community_block::{CommunityBlock, CommunityBlockForm}, instance::Instance, @@ -742,22 +742,24 @@ mod tests { local_user::{LocalUser, LocalUserInsertForm, LocalUserUpdateForm}, person::{Person, PersonInsertForm}, person_block::{PersonBlock, PersonBlockForm}, - post::{Post, PostInsertForm, PostLike, PostLikeForm, PostUpdateForm}, + post::{Post, PostInsertForm, PostLike, PostLikeForm, PostRead, PostUpdateForm}, }, traits::{Blockable, Crud, Joinable, Likeable}, - utils::{build_db_pool_for_tests, DbPool}, + utils::{build_db_pool_for_tests, DbPool, RANK_DEFAULT}, SortType, SubscribedType, }; use serial_test::serial; + use std::{collections::HashSet, time::Duration}; struct Data { inserted_instance: Instance, local_user_view: LocalUserView, - inserted_blocked_person: Person, + blocked_local_user_view: LocalUserView, inserted_bot: Person, inserted_community: Community, inserted_post: Post, + inserted_bot_post: Post, } async fn init_data(pool: &mut DbPool<'_>) -> Data { @@ -809,6 +811,14 @@ mod tests { let inserted_blocked_person = Person::create(pool, &blocked_person).await.unwrap(); + let blocked_local_user_form = LocalUserInsertForm::builder() + .person_id(inserted_blocked_person.id) + .password_encrypted(String::new()) + .build(); + let inserted_blocked_local_user = LocalUser::create(pool, &blocked_local_user_form) + .await + .unwrap(); + let post_from_blocked_person = PostInsertForm::builder() .name("blocked_person_post".to_string()) .creator_id(inserted_blocked_person.id) @@ -842,20 +852,26 @@ mod tests { .community_id(inserted_community.id) .build(); - let _inserted_bot_post = Post::create(pool, &new_bot_post).await.unwrap(); + let inserted_bot_post = Post::create(pool, &new_bot_post).await.unwrap(); let local_user_view = LocalUserView { local_user: inserted_local_user, person: inserted_person, counts: Default::default(), }; + let blocked_local_user_view = LocalUserView { + local_user: inserted_blocked_local_user, + person: inserted_blocked_person, + counts: Default::default(), + }; Data { inserted_instance, local_user_view, - inserted_blocked_person, + blocked_local_user_view, inserted_bot, inserted_community, inserted_post, + inserted_bot_post, } } @@ -1245,7 +1261,7 @@ mod tests { // Remove the post Post::update( pool, - data.inserted_post.id, + data.inserted_bot_post.id, &PostUpdateForm { removed: Some(true), ..Default::default() @@ -1265,18 +1281,21 @@ mod tests { .unwrap(); assert_eq!(1, post_listings_no_admin.len()); - // Removed post is shown to admins on profile page + // Removed bot post is shown to admins on its profile page data.local_user_view.local_user.admin = true; let post_listings_is_admin = PostQuery { sort: Some(SortType::New), + creator_id: Some(data.inserted_bot.id), local_user: Some(&data.local_user_view), - is_profile_view: true, ..Default::default() } .list(pool) .await .unwrap(); - assert_eq!(2, post_listings_is_admin.len()); + assert_eq!( + data.inserted_bot.id, + post_listings_is_admin[0].post.creator_id + ); cleanup(data, pool).await; } @@ -1300,34 +1319,25 @@ mod tests { .await .unwrap(); - // Make sure you don't see the deleted post in the results - let post_listings_no_creator = PostQuery { - sort: Some(SortType::New), - ..Default::default() - } - .list(pool) - .await - .unwrap(); - let not_contains_deleted = post_listings_no_creator + // Deleted post is only shown to creator + for (local_user, expect_contains_deleted) in [ + (None, false), + (Some(&data.blocked_local_user_view), false), + (Some(&data.local_user_view), true), + ] { + let contains_deleted = PostQuery { + sort: Some(SortType::New), + local_user, + ..Default::default() + } + .list(pool) + .await + .unwrap() .iter() - .map(|p| p.post.id) - .all(|p| p != data.inserted_post.id); - assert!(not_contains_deleted); + .any(|p| p.post.id == data.inserted_post.id); - // Deleted post is shown to creator - let post_listings_is_creator = PostQuery { - sort: Some(SortType::New), - local_user: Some(&data.local_user_view), - ..Default::default() + assert_eq!(expect_contains_deleted, contains_deleted); } - .list(pool) - .await - .unwrap(); - let contains_deleted = post_listings_is_creator - .iter() - .map(|p| p.post.id) - .any(|p| p == data.inserted_post.id); - assert!(contains_deleted); cleanup(data, pool).await; } @@ -1410,6 +1420,125 @@ mod tests { cleanup(data, pool).await; } + #[tokio::test] + #[serial] + async fn pagination_includes_each_post_once() { + let pool = &build_db_pool_for_tests().await; + let pool = &mut pool.into(); + let data = init_data(pool).await; + + let community_form = CommunityInsertForm::builder() + .name("yes".to_string()) + .title("yes".to_owned()) + .public_key("pubkey".to_string()) + .instance_id(data.inserted_instance.id) + .build(); + let inserted_community = Community::create(pool, &community_form).await.unwrap(); + + let mut inserted_post_ids = vec![]; + let mut inserted_comment_ids = vec![]; + + // Create 150 posts with varying non-correlating values for publish date, number of comments, and featured + for comments in 0..10 { + for _ in 0..15 { + let post_form = PostInsertForm::builder() + .name("keep Christ in Christmas".to_owned()) + .creator_id(data.local_user_view.person.id) + .community_id(inserted_community.id) + .featured_local(Some((comments % 2) == 0)) + .featured_community(Some((comments % 2) == 0)) + .published(Some(Utc::now() - Duration::from_secs(comments % 3))) + .build(); + let inserted_post = Post::create(pool, &post_form).await.unwrap(); + inserted_post_ids.push(inserted_post.id); + + for _ in 0..comments { + let comment_form = CommentInsertForm::builder() + .creator_id(data.local_user_view.person.id) + .post_id(inserted_post.id) + .content("yes".to_owned()) + .build(); + let inserted_comment = Comment::create(pool, &comment_form, None).await.unwrap(); + inserted_comment_ids.push(inserted_comment.id); + } + } + } + + let mut listed_post_ids = vec![]; + let mut page_after = None; + loop { + let post_listings = PostQuery { + community_id: Some(inserted_community.id), + sort: Some(SortType::MostComments), + limit: Some(10), + page_after, + ..Default::default() + } + .list(pool) + .await + .unwrap(); + + listed_post_ids.extend(post_listings.iter().map(|p| p.post.id)); + + if let Some(p) = post_listings.into_iter().last() { + page_after = Some(PaginationCursorData(p.counts)); + } else { + break; + } + } + + inserted_post_ids.sort_unstable_by_key(|id| id.0); + listed_post_ids.sort_unstable_by_key(|id| id.0); + + assert_eq!(inserted_post_ids, listed_post_ids); + + Community::delete(pool, inserted_community.id) + .await + .unwrap(); + cleanup(data, pool).await; + } + + #[tokio::test] + #[serial] + async fn post_listings_hide_read() { + let pool = &build_db_pool_for_tests().await; + let pool = &mut pool.into(); + let mut data = init_data(pool).await; + + // Make sure local user hides read posts + let local_user_form = LocalUserUpdateForm { + show_read_posts: Some(false), + ..Default::default() + }; + let inserted_local_user = + LocalUser::update(pool, data.local_user_view.local_user.id, &local_user_form) + .await + .unwrap(); + data.local_user_view.local_user = inserted_local_user; + + // Mark a post as read + PostRead::mark_as_read( + pool, + HashSet::from([data.inserted_bot_post.id]), + data.local_user_view.person.id, + ) + .await + .unwrap(); + + // Make sure you don't see the read post in the results + let post_listings_hide_read = PostQuery { + sort: Some(SortType::New), + local_user: Some(&data.local_user_view), + ..Default::default() + } + .list(pool) + .await + .unwrap(); + assert_eq!(1, post_listings_hide_read.len()); + + cleanup(data, pool).await; + } + async fn cleanup(data: Data, pool: &mut DbPool<'_>) { let num_deleted = Post::delete(pool, data.inserted_post.id).await.unwrap(); Community::delete(pool, data.inserted_community.id) @@ -1419,7 +1548,7 @@ mod tests { .await .unwrap(); Person::delete(pool, data.inserted_bot.id).await.unwrap(); - Person::delete(pool, data.inserted_blocked_person.id) + Person::delete(pool, data.blocked_local_user_view.person.id) .await .unwrap(); Instance::delete(pool, data.inserted_instance.id) @@ -1526,10 +1655,10 @@ mod tests { newest_comment_time: inserted_post.published, featured_community: false, featured_local: false, - hot_rank: 0.1728, - hot_rank_active: 0.1728, + hot_rank: RANK_DEFAULT, + hot_rank_active: RANK_DEFAULT, controversy_rank: 0.0, - scaled_rank: 0.3621, + scaled_rank: RANK_DEFAULT, community_id: inserted_post.community_id, creator_id: inserted_post.creator_id, instance_id: data.inserted_instance.id, diff --git a/crates/db_views/src/private_message_view.rs b/crates/db_views/src/private_message_view.rs index 54bae9482..26d97038c 100644 --- a/crates/db_views/src/private_message_view.rs +++ b/crates/db_views/src/private_message_view.rs @@ -210,7 +210,7 @@ mod tests { .recipient_id(timmy.id) .content(message_content.clone()) .build(); - let _inserted_sara_timmy_message_form = PrivateMessage::create(pool, &sara_timmy_message_form) + PrivateMessage::create(pool, &sara_timmy_message_form) .await .unwrap(); @@ -219,7 +219,7 @@ mod tests { .recipient_id(jess.id) .content(message_content.clone()) .build(); - let _inserted_sara_jess_message_form = PrivateMessage::create(pool, &sara_jess_message_form) + PrivateMessage::create(pool, &sara_jess_message_form) .await .unwrap(); @@ -228,7 +228,7 @@ mod tests { .recipient_id(sara.id) .content(message_content.clone()) .build(); - let _inserted_timmy_sara_message_form = PrivateMessage::create(pool, &timmy_sara_message_form) + PrivateMessage::create(pool, &timmy_sara_message_form) .await .unwrap(); @@ -237,13 +237,13 @@ mod tests { .recipient_id(timmy.id) .content(message_content.clone()) .build(); - let _inserted_jess_timmy_message_form = PrivateMessage::create(pool, &jess_timmy_message_form) + PrivateMessage::create(pool, &jess_timmy_message_form) .await .unwrap(); let timmy_messages = PrivateMessageQuery { unread_only: false, - creator_id: Option::None, + creator_id: None, ..Default::default() } .list(pool, timmy.id) @@ -260,7 +260,7 @@ mod tests { let timmy_unread_messages = PrivateMessageQuery { unread_only: true, - creator_id: Option::None, + creator_id: None, ..Default::default() } .list(pool, timmy.id) @@ -320,7 +320,7 @@ mod tests { let timmy_messages = PrivateMessageQuery { unread_only: true, - creator_id: Option::None, + creator_id: None, ..Default::default() } .list(pool, timmy.id) @@ -333,5 +333,8 @@ mod tests { .await .unwrap(); assert_eq!(timmy_unread_messages, 1); + + // This also deletes all persons and private messages thanks to sql `on delete cascade` + Instance::delete(pool, instance.id).await.unwrap(); } } diff --git a/crates/db_views/src/registration_application_view.rs b/crates/db_views/src/registration_application_view.rs index 1b0b1a370..9a298eb77 100644 --- a/crates/db_views/src/registration_application_view.rs +++ b/crates/db_views/src/registration_application_view.rs @@ -49,8 +49,13 @@ fn queries<'a>() -> Queries< let list = move |mut conn: DbConn<'a>, options: RegistrationApplicationQuery| async move { let mut query = all_joins(registration_application::table.into_boxed()); + // If viewing all applications, order by newest, but if viewing unresolved only, show the oldest first (FIFO) if options.unread_only { - query = query.filter(registration_application::admin_id.is_null()) + query = query + .filter(registration_application::admin_id.is_null()) + .order_by(registration_application::published.asc()); + } else { + query = query.order_by(registration_application::published.desc()); } if options.verified_email_only { @@ -59,10 +64,7 @@ fn queries<'a>() -> Queries< let (limit, offset) = limit_and_offset(options.page, options.limit)?; - query = query - .limit(limit) - .offset(offset) - .order_by(registration_application::published.asc()); + query = query.limit(limit).offset(offset); query.load::(&mut conn).await }; diff --git a/crates/db_views_actor/src/person_view.rs b/crates/db_views_actor/src/person_view.rs index b259ec7a6..16e9b3bc6 100644 --- a/crates/db_views_actor/src/person_view.rs +++ b/crates/db_views_actor/src/person_view.rs @@ -1,6 +1,5 @@ use crate::structs::PersonView; use diesel::{ - dsl::exists, pg::Pg, result::Error, BoolExpressionMethods, @@ -13,7 +12,17 @@ use diesel_async::RunQueryDsl; use lemmy_db_schema::{ newtypes::PersonId, schema::{local_user, person, person_aggregates}, - utils::{fuzzy_search, limit_and_offset, now, DbConn, DbPool, ListFn, Queries, ReadFn}, + utils::{ + functions::coalesce, + fuzzy_search, + limit_and_offset, + now, + DbConn, + DbPool, + ListFn, + Queries, + ReadFn, + }, SortType, }; use serde::{Deserialize, Serialize}; @@ -48,21 +57,15 @@ fn post_to_person_sort_type(sort: SortType) -> PersonSortType { fn queries<'a>( ) -> Queries, impl ListFn<'a, PersonView, ListMode>> { - let creator_is_admin = exists( - local_user::table.filter( - person::id - .eq(local_user::person_id) - .and(local_user::admin.eq(true)), - ), - ); let all_joins = move |query: person::BoxedQuery<'a, Pg>| { query .inner_join(person_aggregates::table) + .left_join(local_user::table) .filter(person::deleted.eq(false)) .select(( person::all_columns, person_aggregates::all_columns, - creator_is_admin, + coalesce(local_user::admin.nullable(), false), )) }; @@ -77,7 +80,7 @@ fn queries<'a>( match mode { ListMode::Admins => { query = query - .filter(creator_is_admin.eq(true)) + .filter(local_user::admin.eq(true)) .filter(person::deleted.eq(false)) .order_by(person::published); } diff --git a/crates/federate/Cargo.toml b/crates/federate/Cargo.toml index 85c781a40..9ccd8adc3 100644 --- a/crates/federate/Cargo.toml +++ b/crates/federate/Cargo.toml @@ -1,5 +1,6 @@ [package] name = "lemmy_federate" +publish = false version.workspace = true edition.workspace = true description.workspace = true @@ -30,5 +31,5 @@ reqwest.workspace = true serde_json.workspace = true tokio = { workspace = true, features = ["full"] } tracing.workspace = true -moka = { version = "0.11.3", features = ["future"] } -tokio-util = "0.7.9" +moka.workspace = true +tokio-util = "0.7.10" diff --git a/crates/federate/src/lib.rs b/crates/federate/src/lib.rs index b6c820aaa..382aa59b8 100644 --- a/crates/federate/src/lib.rs +++ b/crates/federate/src/lib.rs @@ -154,7 +154,6 @@ async fn receive_print_stats( tokio::select! { ele = receiver.recv() => { let Some((domain, ele)) = ele else { - tracing::info!("done. quitting"); print_stats(pool, &stats).await; return; }; @@ -181,9 +180,9 @@ async fn print_stats(pool: &mut DbPool<'_>, stats: &HashMap 0 { @@ -195,10 +194,11 @@ async fn print_stats(pool: &mut DbPool<'_>, stats: &HashMap 0 { - tracing::info!("{}: Ok. {} behind", domain, behind); + tracing::debug!("{}: Ok. {} activities behind", domain, behind); + behind_count += 1; } else { ok_count += 1; } } - tracing::info!("{ok_count} others up to date"); + tracing::info!("{ok_count} others up to date. {behind_count} instances behind."); } diff --git a/crates/federate/src/worker.rs b/crates/federate/src/worker.rs index ad2b5b7d2..963814ad9 100644 --- a/crates/federate/src/worker.rs +++ b/crates/federate/src/worker.rs @@ -171,6 +171,7 @@ impl InstanceWorker { .await .context("failed reading activity from db")? else { + tracing::debug!("{}: {:?} does not exist", self.instance.domain, id); self.state.last_successful_id = Some(id); continue; }; @@ -221,7 +222,7 @@ impl InstanceWorker { SendActivityTask::prepare(object, actor.as_ref(), inbox_urls, &self.context).await?; for task in requests { // usually only one due to shared inbox - tracing::info!("sending out {}", task); + tracing::debug!("sending out {}", task); while let Err(e) = task.sign_and_send(&self.context).await { self.state.fail_count += 1; self.state.last_retry = Some(Utc::now()); diff --git a/crates/routes/Cargo.toml b/crates/routes/Cargo.toml index 00044e294..fd326183d 100644 --- a/crates/routes/Cargo.toml +++ b/crates/routes/Cargo.toml @@ -1,5 +1,6 @@ [package] name = "lemmy_routes" +publish = false version.workspace = true edition.workspace = true description.workspace = true diff --git a/crates/routes/src/feeds.rs b/crates/routes/src/feeds.rs index 46997055f..56c75a625 100644 --- a/crates/routes/src/feeds.rs +++ b/crates/routes/src/feeds.rs @@ -25,13 +25,7 @@ use lemmy_utils::{ utils::markdown::{markdown_to_html, sanitize_html}, }; use once_cell::sync::Lazy; -use rss::{ - extension::dublincore::DublinCoreExtensionBuilder, - ChannelBuilder, - GuidBuilder, - Item, - ItemBuilder, -}; +use rss::{extension::dublincore::DublinCoreExtension, Channel, Guid, Item}; use serde::Deserialize; use std::{collections::BTreeMap, str::FromStr}; @@ -146,18 +140,19 @@ async fn get_feed_data( let items = create_post_items(posts, &context.settings().get_protocol_and_hostname())?; - let mut channel_builder = ChannelBuilder::default(); - channel_builder - .namespaces(RSS_NAMESPACE.clone()) - .title(&format!("{} - {}", site_view.site.name, listing_type)) - .link(context.settings().get_protocol_and_hostname()) - .items(items); + let mut channel = Channel { + namespaces: RSS_NAMESPACE.clone(), + title: format!("{} - {}", site_view.site.name, listing_type), + link: context.settings().get_protocol_and_hostname(), + items, + ..Default::default() + }; if let Some(site_desc) = site_view.site.description { - channel_builder.description(&site_desc); + channel.set_description(&site_desc); } - let rss = channel_builder.build().to_string(); + let rss = channel.to_string(); Ok( HttpResponse::Ok() .content_type("application/rss+xml") @@ -217,7 +212,7 @@ async fn get_feed( } .map_err(ErrorBadRequest)?; - let rss = builder.build().to_string(); + let rss = builder.to_string(); Ok( HttpResponse::Ok() @@ -233,7 +228,7 @@ async fn get_feed_user( limit: &i64, page: &i64, user_name: &str, -) -> Result { +) -> Result { let site_view = SiteView::read_local(&mut context.pool()).await?; let person = Person::read_from_name(&mut context.pool(), user_name, false).await?; @@ -252,14 +247,15 @@ async fn get_feed_user( let items = create_post_items(posts, &context.settings().get_protocol_and_hostname())?; - let mut channel_builder = ChannelBuilder::default(); - channel_builder - .namespaces(RSS_NAMESPACE.clone()) - .title(&format!("{} - {}", site_view.site.name, person.name)) - .link(person.actor_id.to_string()) - .items(items); + let channel = Channel { + namespaces: RSS_NAMESPACE.clone(), + title: format!("{} - {}", site_view.site.name, person.name), + link: person.actor_id.to_string(), + items, + ..Default::default() + }; - Ok(channel_builder) + Ok(channel) } #[tracing::instrument(skip_all)] @@ -269,7 +265,7 @@ async fn get_feed_community( limit: &i64, page: &i64, community_name: &str, -) -> Result { +) -> Result { let site_view = SiteView::read_local(&mut context.pool()).await?; let community = Community::read_from_name(&mut context.pool(), community_name, false).await?; @@ -287,18 +283,19 @@ async fn get_feed_community( let items = create_post_items(posts, &context.settings().get_protocol_and_hostname())?; - let mut channel_builder = ChannelBuilder::default(); - channel_builder - .namespaces(RSS_NAMESPACE.clone()) - .title(&format!("{} - {}", site_view.site.name, community.name)) - .link(community.actor_id.to_string()) - .items(items); + let mut channel = Channel { + namespaces: RSS_NAMESPACE.clone(), + title: format!("{} - {}", site_view.site.name, community.name), + link: community.actor_id.to_string(), + items, + ..Default::default() + }; if let Some(community_desc) = community.description { - channel_builder.description(markdown_to_html(&community_desc)); + channel.set_description(markdown_to_html(&community_desc)); } - Ok(channel_builder) + Ok(channel) } #[tracing::instrument(skip_all)] @@ -308,7 +305,7 @@ async fn get_feed_front( limit: &i64, page: &i64, jwt: &str, -) -> Result { +) -> Result { let site_view = SiteView::read_local(&mut context.pool()).await?; let local_user = local_user_view_from_jwt(jwt, context).await?; @@ -328,22 +325,23 @@ async fn get_feed_front( let protocol_and_hostname = context.settings().get_protocol_and_hostname(); let items = create_post_items(posts, &protocol_and_hostname)?; - let mut channel_builder = ChannelBuilder::default(); - channel_builder - .namespaces(RSS_NAMESPACE.clone()) - .title(&format!("{} - Subscribed", site_view.site.name)) - .link(protocol_and_hostname) - .items(items); + let mut channel = Channel { + namespaces: RSS_NAMESPACE.clone(), + title: format!("{} - Subscribed", site_view.site.name), + link: protocol_and_hostname, + items, + ..Default::default() + }; if let Some(site_desc) = site_view.site.description { - channel_builder.description(markdown_to_html(&site_desc)); + channel.set_description(markdown_to_html(&site_desc)); } - Ok(channel_builder) + Ok(channel) } #[tracing::instrument(skip_all)] -async fn get_feed_inbox(context: &LemmyContext, jwt: &str) -> Result { +async fn get_feed_inbox(context: &LemmyContext, jwt: &str) -> Result { let site_view = SiteView::read_local(&mut context.pool()).await?; let local_user = local_user_view_from_jwt(jwt, context).await?; let person_id = local_user.local_user.person_id; @@ -378,18 +376,19 @@ async fn get_feed_inbox(context: &LemmyContext, jwt: &str) -> Result Result { - let mut i = ItemBuilder::default(); - i.title(format!("Reply from {creator_name}")); - let author_url = format!("{protocol_and_hostname}/u/{creator_name}"); - i.author(format!( - "/u/{creator_name} (link)" - )); - let dt = published; - i.pub_date(dt.to_rfc2822()); - i.comments(url.to_owned()); - let guid = GuidBuilder::default().permalink(true).value(url).build(); - i.guid(guid); - i.link(url.to_owned()); // TODO add images - let html = markdown_to_html(content); - i.description(html); - Ok(i.build()) + let author_url = format!("{protocol_and_hostname}/u/{creator_name}"); + let guid = Some(Guid { + permalink: true, + value: url.to_owned(), + }); + let description = Some(markdown_to_html(content)); + + Ok(Item { + title: Some(format!("Reply from {creator_name}")), + author: Some(format!( + "/u/{creator_name} (link)" + )), + pub_date: Some(published.to_rfc2822()), + comments: Some(url.to_owned()), + link: Some(url.to_owned()), + guid, + description, + ..Default::default() + }) } #[tracing::instrument(skip_all)] @@ -464,31 +467,21 @@ fn create_post_items( let mut items: Vec = Vec::new(); for p in posts { - let mut i = ItemBuilder::default(); - let mut dc_extension = DublinCoreExtensionBuilder::default(); - - i.title(sanitize_html(&p.post.name)); - - dc_extension.creators(vec![p.creator.actor_id.to_string()]); - - let dt = p.post.published; - i.pub_date(dt.to_rfc2822()); - + // TODO add images let post_url = format!("{}/post/{}", protocol_and_hostname, p.post.id); - i.comments(post_url.clone()); - let guid = GuidBuilder::default() - .permalink(true) - .value(&post_url) - .build(); - i.guid(guid); - let community_url = format!( "{}/c/{}", protocol_and_hostname, sanitize_html(&p.community.name) ); - - // TODO add images + let dublin_core_ext = Some(DublinCoreExtension { + creators: vec![p.creator.actor_id.to_string()], + ..DublinCoreExtension::default() + }); + let guid = Some(Guid { + permalink: true, + value: post_url.clone(), + }); let mut description = format!("submitted by {} to {}
{} points | {} comments", p.creator.actor_id, sanitize_html(&p.creator.name), @@ -499,23 +492,31 @@ fn create_post_items( p.counts.comments); // If its a url post, add it to the description - if let Some(url) = p.post.url { + let link = Some(if let Some(url) = p.post.url { let link_html = format!("
{url}"); description.push_str(&link_html); - i.link(url.to_string()); + url.to_string() } else { - i.link(post_url.clone()); - } + post_url.clone() + }); if let Some(body) = p.post.body { let html = markdown_to_html(&body); description.push_str(&html); } - i.description(description); + let i = Item { + title: Some(sanitize_html(&p.post.name)), + pub_date: Some(p.post.published.to_rfc2822()), + comments: Some(post_url.clone()), + guid, + description: Some(description), + dublin_core_ext, + link, + ..Default::default() + }; - i.dublin_core_ext(dc_extension.build()); - items.push(i.build()); + items.push(i); } Ok(items) diff --git a/crates/routes/src/webfinger.rs b/crates/routes/src/webfinger.rs index afb2d33ae..fdb22c4cf 100644 --- a/crates/routes/src/webfinger.rs +++ b/crates/routes/src/webfinger.rs @@ -37,12 +37,11 @@ async fn get_webfinger_response( ) -> Result { let name = extract_webfinger_name(&info.resource, &context)?; - let name_ = name.clone(); - let user_id: Option = Person::read_from_name(&mut context.pool(), &name_, false) + let user_id: Option = Person::read_from_name(&mut context.pool(), name, false) .await .ok() .map(|c| c.actor_id.into()); - let community_id: Option = Community::read_from_name(&mut context.pool(), &name, false) + let community_id: Option = Community::read_from_name(&mut context.pool(), name, false) .await .ok() .map(|c| c.actor_id.into()); diff --git a/crates/utils/Cargo.toml b/crates/utils/Cargo.toml index c2e0cac54..57fd10655 100644 --- a/crates/utils/Cargo.toml +++ b/crates/utils/Cargo.toml @@ -41,12 +41,12 @@ uuid = { workspace = true, features = ["serde", "v4"] } rosetta-i18n = { workspace = true } tokio = { workspace = true } urlencoding = { workspace = true } -openssl = "0.10.57" +openssl = "0.10.61" html2text = "0.6.0" -deser-hjson = "1.2.0" +deser-hjson = "2.2.4" smart-default = "0.7.1" -lettre = { version = "0.10.4", features = ["tokio1", "tokio1-native-tls"] } -markdown-it = "0.5.1" +lettre = { version = "0.11.2", features = ["tokio1", "tokio1-native-tls"] } +markdown-it = "0.6.0" ts-rs = { workspace = true, optional = true } enum-map = { workspace = true } diff --git a/crates/utils/src/error.rs b/crates/utils/src/error.rs index c5cbaa07e..7d84dcbf6 100644 --- a/crates/utils/src/error.rs +++ b/crates/utils/src/error.rs @@ -221,14 +221,13 @@ pub enum LemmyErrorType { CouldntSendWebmention, ContradictingFilters, InstanceBlockAlreadyExists, - /// `jwt` cookie must be marked secure and httponly - AuthCookieInsecure, /// Thrown when an API call is submitted with more than 1000 array elements, see [[MAX_API_PARAM_ELEMENTS]] TooManyItems, CommunityHasNoFollowers, BanExpirationInPast, InvalidUnixTime, InvalidBotAction, + CantBlockLocalInstance, Unknown(String), } diff --git a/crates/utils/src/rate_limit/mod.rs b/crates/utils/src/rate_limit/mod.rs index 63090749b..b2efbe2c9 100644 --- a/crates/utils/src/rate_limit/mod.rs +++ b/crates/utils/src/rate_limit/mod.rs @@ -36,11 +36,11 @@ impl RateLimitCell { let state_weak_ref = Arc::downgrade(&state); tokio::spawn(async move { - let hour = Duration::from_secs(3600); + let interval = Duration::from_secs(120); // This loop stops when all other references to `state` are dropped while let Some(state) = state_weak_ref.upgrade() { - tokio::time::sleep(hour).await; + tokio::time::sleep(interval).await; state .lock() .expect("Failed to lock rate limit mutex for reading") diff --git a/crates/utils/src/utils/validation.rs b/crates/utils/src/utils/validation.rs index 36aa2c5f1..654232a46 100644 --- a/crates/utils/src/utils/validation.rs +++ b/crates/utils/src/utils/validation.rs @@ -4,9 +4,6 @@ use once_cell::sync::Lazy; use regex::{Regex, RegexBuilder}; use url::Url; -static VALID_POST_TITLE_REGEX: Lazy = - Lazy::new(|| Regex::new(r".*\S{3,200}.*").expect("compile regex")); - // From here: https://github.com/vector-im/element-android/blob/develop/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixPatterns.kt#L35 static VALID_MATRIX_ID_REGEX: Lazy = Lazy::new(|| { Regex::new(r"^@[A-Za-z0-9\\x21-\\x39\\x3B-\\x7F]+:[A-Za-z0-9.-]+(:[0-9]{2,5})?$") @@ -150,7 +147,8 @@ pub fn is_valid_matrix_id(matrix_id: &str) -> LemmyResult<()> { } pub fn is_valid_post_title(title: &str) -> LemmyResult<()> { - let check = VALID_POST_TITLE_REGEX.is_match(title) && !has_newline(title); + let length = title.trim().len(); + let check = (3..=200).contains(&length) && !has_newline(title); if !check { Err(LemmyErrorType::InvalidPostTitle.into()) } else { @@ -330,9 +328,13 @@ mod tests { fn regex_checks() { assert!(is_valid_post_title("hi").is_err()); assert!(is_valid_post_title("him").is_ok()); + assert!(is_valid_post_title(" him ").is_ok()); assert!(is_valid_post_title("n\n\n\n\nanother").is_err()); assert!(is_valid_post_title("hello there!\n this is a test.").is_err()); assert!(is_valid_post_title("hello there! this is a test.").is_ok()); + assert!(is_valid_post_title(("12345".repeat(40) + "x").as_str()).is_err()); + assert!(is_valid_post_title("12345".repeat(40).as_str()).is_ok()); + assert!(is_valid_post_title((("12345".repeat(40)) + " ").as_str()).is_ok()); } #[test] diff --git a/crates/utils/translations b/crates/utils/translations index a36865ee8..15815aea7 160000 --- a/crates/utils/translations +++ b/crates/utils/translations @@ -1 +1 @@ -Subproject commit a36865ee8ca3658fea31ba948b67b75a812e84fc +Subproject commit 15815aea74fe97360afc03496b3ad62588649af0 diff --git a/docker/Dockerfile b/docker/Dockerfile index eab612598..6ba506961 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,10 +1,17 @@ +# syntax=docker/dockerfile:1.6 ARG RUST_VERSION=1.72.1 ARG CARGO_BUILD_FEATURES=default ARG RUST_RELEASE_MODE=debug + ARG AMD_BUILDER_IMAGE=rust:${RUST_VERSION} -ARG ARM_BUILDER_IMAGE=blackdex/rust-musl:aarch64-musl-stable-${RUST_VERSION}-openssl3 +ARG ARM_BUILDER_IMAGE="ghcr.io/raskyld/aarch64-lemmy-linux-gnu:v0.1.0" + ARG AMD_RUNNER_IMAGE=debian:bookworm-slim -ARG ARM_RUNNER_IMAGE=alpine:3.18 +ARG ARM_RUNNER_IMAGE=debian:bookworm-slim + +ARG UNAME=lemmy +ARG UID=1000 +ARG GID=1000 # AMD64 builder FROM --platform=${BUILDPLATFORM} ${AMD_BUILDER_IMAGE} AS build-amd64 @@ -21,91 +28,83 @@ RUN --mount=type=cache,target=/lemmy/target set -ex; \ if [ "${RUST_RELEASE_MODE}" = "debug" ]; then \ echo "pub const VERSION: &str = \"$(git describe --tag)\";" > crates/utils/src/version.rs; \ cargo build --features "${CARGO_BUILD_FEATURES}"; \ - mv target/debug/lemmy_server ./lemmy; \ + mv target/"${RUST_RELEASE_MODE}"/lemmy_server ./lemmy_server; \ fi # Release build -RUN set -ex; \ +RUN --mount=type=cache,target=/lemmy/target set -ex; \ if [ "${RUST_RELEASE_MODE}" = "release" ]; then \ echo "pub const VERSION: &str = \"$(git describe --tag)\";" > crates/utils/src/version.rs; \ + [ -z "$USE_RELEASE_CACHE" ] && cargo clean --release; \ cargo build --features "${CARGO_BUILD_FEATURES}" --release; \ - mv target/release/lemmy_server ./lemmy; \ + mv target/"${RUST_RELEASE_MODE}"/lemmy_server ./lemmy_server; \ fi # ARM64 builder -# TODO currently broken -# FROM --platform=${BUILDPLATFORM} ${ARM_BUILDER_IMAGE} as build-arm64 +# NB(raskyld): this is a hack to be able to COPY --from= this image, because the variable doesn't +# seem to be expended in --form arg of COPY :( +FROM --platform=linux/amd64 ${ARM_BUILDER_IMAGE} AS build-arm64 -# ENV DEBIAN_FRONTEND=noninteractive -# ENV CARGO_HOME=/root/.cargo -# ENV PQ_LIB_DIR=/usr/local/musl/pq15/lib +ARG RUST_RELEASE_MODE +ARG CARGO_BUILD_FEATURES -# RUN apt update && apt install -y \ -# --no-install-recommends \ -# git +WORKDIR /home/lemmy/src +USER 10001:10001 -# RUN mkdir -pv "${CARGO_HOME}" && \ -# rustup set profile minimal && \ -# rustup target add aarch64-unknown-linux-musl +COPY --chown=lemmy:lemmy . ./ -# ARG CARGO_BUILD_FEATURES -# ARG RUST_RELEASE_MODE +ENV PATH="/home/lemmy/.cargo/bin:${PATH}" +ENV RUST_RELEASE_MODE=${RUST_RELEASE_MODE} \ + CARGO_BUILD_FEATURES=${CARGO_BUILD_FEATURES} -# WORKDIR /lemmy +# Debug build +RUN --mount=type=cache,target=./target,uid=10001,gid=10001 set -ex; \ + if [ "${RUST_RELEASE_MODE}" = "debug" ]; then \ + echo "pub const VERSION: &str = \"$(git describe --tag)\";" > crates/utils/src/version.rs; \ + cargo build --features "${CARGO_BUILD_FEATURES}"; \ + mv "./target/$CARGO_BUILD_TARGET/$RUST_RELEASE_MODE/lemmy_server" /home/lemmy/lemmy_server; \ + fi -# COPY . ./ +# Release build +RUN --mount=type=cache,target=./target,uid=10001,gid=10001 set -ex; \ + if [ "${RUST_RELEASE_MODE}" = "release" ]; then \ + echo "pub const VERSION: &str = \"$(git describe --tag)\";" > crates/utils/src/version.rs; \ + [ -z "$USE_RELEASE_CACHE" ] && cargo clean --release; \ + cargo build --features "${CARGO_BUILD_FEATURES}" --release; \ + mv "./target/$CARGO_BUILD_TARGET/$RUST_RELEASE_MODE/lemmy_server" /home/lemmy/lemmy_server; \ + fi -# # Debug build -# RUN --mount=type=cache,target=/lemmy/target set -ex; \ -# if [ "${RUST_RELEASE_MODE}" = "debug" ]; then \ -# echo "pub const VERSION: &str = \"$(git describe --tag)\";" > crates/utils/src/version.rs; \ -# cargo build --target=aarch64-unknown-linux-musl --features "${CARGO_BUILD_FEATURES}"; \ -# mv target/aarch64-unknown-linux-musl/debug/lemmy_server ./lemmy; \ -# fi - -# # Release build -# RUN set -ex; \ -# if [ "${RUST_RELEASE_MODE}" = "release" ]; then \ -# echo "pub const VERSION: &str = \"$(git describe --tag)\";" > crates/utils/src/version.rs; \ -# cargo build --target=aarch64-unknown-linux-musl --features "${CARGO_BUILD_FEATURES}" --release; \ -# mv target/aarch64-unknown-linux-musl/release/lemmy_server ./lemmy; \ -# fi - -## Final image -FROM ${AMD_RUNNER_IMAGE} +# amd64 base runner +FROM ${AMD_RUNNER_IMAGE} AS runner-linux-amd64 # Federation needs CA certificates RUN apt update && apt install -y libssl-dev libpq-dev ca-certificates -# Debian / Ubuntu non-root user creds -ARG UNAME=lemmy -ARG UID=1000 -ARG GID=1000 -RUN groupadd -g $GID -o $UNAME -RUN useradd -m -u $UID -g $GID -o -s /bin/bash $UNAME +COPY --from=build-amd64 --chmod=0755 /lemmy/lemmy_server /usr/local/bin + +# arm base runner +FROM ${ARM_RUNNER_IMAGE} AS runner-linux-arm64 + +RUN apt update && apt install -y ca-certificates libssl-dev libpq-dev + +COPY --from=build-arm64 --chmod=0755 /home/lemmy/lemmy_server /usr/local/bin + +# Final image that use a base runner based on the target OS and ARCH +FROM runner-${TARGETOS}-${TARGETARCH} + +LABEL org.opencontainers.image.authors="The Lemmy Authors" +LABEL org.opencontainers.image.source="https://github.com/LemmyNet/lemmy" +LABEL org.opencontainers.image.licenses="AGPL-3.0-or-later" +LABEL org.opencontainers.image.description="A link aggregator and forum for the fediverse" + +ARG UNAME +ARG GID +ARG UID + +RUN groupadd -g ${GID} -o ${UNAME} && \ + useradd -m -u ${UID} -g ${GID} -o -s /bin/bash ${UNAME} USER $UNAME -COPY --from=build-amd64 /lemmy/lemmy ./ -CMD ["./lemmy"] +ENTRYPOINT ["lemmy_server"] EXPOSE 8536 STOPSIGNAL SIGTERM - -## Arm Runner -# FROM --platform=${BUILDPLATFORM} ${ARM_RUNNER_IMAGE} - -# ARG UNAME=lemmy -# ARG UID=1000 -# ARG GID=1000 - -# RUN apk add --no-cache ca-certificates - -# COPY --from=build-arm64 --chmod=0755 /lemmy/lemmy /usr/local/bin - -# RUN addgroup -S -g ${GID} ${UNAME} && \ -# adduser -S -H -D -G ${UNAME} -u ${UID} -g "" -s /sbin/nologin ${UNAME} -# USER $UNAME - -# CMD ["lemmy"] -# EXPOSE 8536 -# STOPSIGNAL SIGTERM - diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 000000000..8972055a0 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,21 @@ +# Building Lemmy Images + +Lemmy's images are meant to be **built** on `linux/amd64`, +but they can be **executed** on both `linux/amd64` and `linux/arm64`. + +To do so we need to use a _cross toolchain_ whose goal is to build +**from** amd64 **to** arm64. + +Namely, we need to link the _lemmy_server_ with `pq` and `openssl` +shared libraries and a few others, and they need to be in `arm64`, +indeed. + +The toolchain we use to cross-compile is specifically tailored for +Lemmy's needs, see [the image repository][image-repo]. + +#### References + +- [The Linux Documentation Project on Shared Libraries][tldp-lib] + +[tldp-lib]: https://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html +[image-repo]: https://github.com/raskyld/lemmy-cross-toolchains diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index f2933cc4e..eb81766cc 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -25,7 +25,7 @@ services: lemmy: # use "image" to pull down an already compiled lemmy. make sure to comment out "build". - # image: dessalines/lemmy:0.18.4 + # image: dessalines/lemmy:0.19.0 # platform: linux/x86_64 # no arm64 support. uncomment platform if using m1. # use "build" to build your local lemmy server image for development. make sure to comment out "image". # run: docker compose up --build @@ -43,8 +43,8 @@ services: - RUST_LOG="warn,lemmy_server=debug,lemmy_api=debug,lemmy_api_common=debug,lemmy_api_crud=debug,lemmy_apub=debug,lemmy_db_schema=debug,lemmy_db_views=debug,lemmy_db_views_actor=debug,lemmy_db_views_moderator=debug,lemmy_routes=debug,lemmy_utils=debug,lemmy_websocket=debug" - RUST_BACKTRACE=full ports: - # prometheus metrics available at the path /metrics on port 10002 by default - # enable prometheus metrics by setting the CARGO_BUILD_FEATURES build arg above to "prometheus-metrics" + # prometheus metrics can be enabled with the `prometheus` config option. they are available on + # port 10002, path /metrics by default - "10002:10002" volumes: - ./lemmy.hjson:/config/config.hjson:Z @@ -55,7 +55,7 @@ services: lemmy-ui: # use "image" to pull down an already compiled lemmy-ui. make sure to comment out "build". - image: dessalines/lemmy-ui:0.19.0-rc.3 + image: dessalines/lemmy-ui:0.19.0 # platform: linux/x86_64 # no arm64 support. uncomment platform if using m1. # use "build" to build your local lemmy ui image for development. make sure to comment out "image". # run: docker compose up --build @@ -77,7 +77,7 @@ services: init: true pictrs: - image: asonix/pictrs:0.5.0-alpha.20 + image: asonix/pictrs:0.5.0-rc.2 # this needs to match the pictrs url in lemmy.hjson hostname: pictrs # we can set options to pictrs like this, here we set max. image size and forced format for conversion diff --git a/docker/federation/docker-compose.yml b/docker/federation/docker-compose.yml index 142267596..a8c6160df 100644 --- a/docker/federation/docker-compose.yml +++ b/docker/federation/docker-compose.yml @@ -2,7 +2,7 @@ version: "3.7" x-ui-default: &ui-default init: true - image: dessalines/lemmy-ui:0.19.0-rc.3 + image: dessalines/lemmy-ui:0.19.0 # assuming lemmy-ui is cloned besides lemmy directory # build: # context: ../../../lemmy-ui @@ -49,7 +49,7 @@ services: pictrs: restart: always - image: asonix/pictrs:0.4.0-beta.19 + image: asonix/pictrs:0.5.0-rc.2 user: 991:991 volumes: - ./volumes/pictrs_alpha:/mnt:Z diff --git a/migrations/2023-11-22-194806_low_rank_defaults/down.sql b/migrations/2023-11-22-194806_low_rank_defaults/down.sql new file mode 100644 index 000000000..2b1be4cfe --- /dev/null +++ b/migrations/2023-11-22-194806_low_rank_defaults/down.sql @@ -0,0 +1,11 @@ +ALTER TABLE community_aggregates + ALTER COLUMN hot_rank SET DEFAULT 0.1728; + +ALTER TABLE comment_aggregates + ALTER COLUMN hot_rank SET DEFAULT 0.1728; + +ALTER TABLE post_aggregates + ALTER COLUMN hot_rank SET DEFAULT 0.1728, + ALTER COLUMN hot_rank_active SET DEFAULT 0.1728, + ALTER COLUMN scaled_rank SET DEFAULT 0.3621; + diff --git a/migrations/2023-11-22-194806_low_rank_defaults/up.sql b/migrations/2023-11-22-194806_low_rank_defaults/up.sql new file mode 100644 index 000000000..a1ef1ff51 --- /dev/null +++ b/migrations/2023-11-22-194806_low_rank_defaults/up.sql @@ -0,0 +1,16 @@ +-- Change the hot_ranks to a miniscule number, so that new / fetched content +-- won't crowd out existing content. +-- +-- They must be non-zero, in order for them to be picked up by the hot_ranks updater. +-- See https://github.com/LemmyNet/lemmy/issues/4178 +ALTER TABLE community_aggregates + ALTER COLUMN hot_rank SET DEFAULT 0.0001; + +ALTER TABLE comment_aggregates + ALTER COLUMN hot_rank SET DEFAULT 0.0001; + +ALTER TABLE post_aggregates + ALTER COLUMN hot_rank SET DEFAULT 0.0001, + ALTER COLUMN hot_rank_active SET DEFAULT 0.0001, + ALTER COLUMN scaled_rank SET DEFAULT 0.0001; + diff --git a/migrations/2023-12-06-180359_edit_active_users/down.sql b/migrations/2023-12-06-180359_edit_active_users/down.sql new file mode 100644 index 000000000..dfdce712c --- /dev/null +++ b/migrations/2023-12-06-180359_edit_active_users/down.sql @@ -0,0 +1,72 @@ +CREATE OR REPLACE FUNCTION community_aggregates_activity (i text) + RETURNS TABLE ( + count_ bigint, + community_id_ integer) + LANGUAGE plpgsql + AS $$ +BEGIN + RETURN query + SELECT + count(*), + community_id + FROM ( + SELECT + c.creator_id, + p.community_id + FROM + comment c + INNER JOIN post p ON c.post_id = p.id + INNER JOIN person pe ON c.creator_id = pe.id + WHERE + c.published > ('now'::timestamp - i::interval) + AND pe.bot_account = FALSE + UNION + SELECT + p.creator_id, + p.community_id + FROM + post p + INNER JOIN person pe ON p.creator_id = pe.id + WHERE + p.published > ('now'::timestamp - i::interval) + AND pe.bot_account = FALSE) a +GROUP BY + community_id; +END; +$$; + +CREATE OR REPLACE FUNCTION site_aggregates_activity (i text) + RETURNS integer + LANGUAGE plpgsql + AS $$ +DECLARE + count_ integer; +BEGIN + SELECT + count(*) INTO count_ + FROM ( + SELECT + c.creator_id + FROM + comment c + INNER JOIN person u ON c.creator_id = u.id + INNER JOIN person pe ON c.creator_id = pe.id + WHERE + c.published > ('now'::timestamp - i::interval) + AND u.local = TRUE + AND pe.bot_account = FALSE + UNION + SELECT + p.creator_id + FROM + post p + INNER JOIN person u ON p.creator_id = u.id + INNER JOIN person pe ON p.creator_id = pe.id + WHERE + p.published > ('now'::timestamp - i::interval) + AND u.local = TRUE + AND pe.bot_account = FALSE) a; + RETURN count_; +END; +$$; + diff --git a/migrations/2023-12-06-180359_edit_active_users/up.sql b/migrations/2023-12-06-180359_edit_active_users/up.sql new file mode 100644 index 000000000..4fe7689fc --- /dev/null +++ b/migrations/2023-12-06-180359_edit_active_users/up.sql @@ -0,0 +1,114 @@ +-- Edit community aggregates to include voters as active users +CREATE OR REPLACE FUNCTION community_aggregates_activity (i text) + RETURNS TABLE ( + count_ bigint, + community_id_ integer) + LANGUAGE plpgsql + AS $$ +BEGIN + RETURN query + SELECT + count(*), + community_id + FROM ( + SELECT + c.creator_id, + p.community_id + FROM + comment c + INNER JOIN post p ON c.post_id = p.id + INNER JOIN person pe ON c.creator_id = pe.id + WHERE + c.published > ('now'::timestamp - i::interval) + AND pe.bot_account = FALSE + UNION + SELECT + p.creator_id, + p.community_id + FROM + post p + INNER JOIN person pe ON p.creator_id = pe.id + WHERE + p.published > ('now'::timestamp - i::interval) + AND pe.bot_account = FALSE + UNION + SELECT + pl.person_id, + p.community_id + FROM + post_like pl + INNER JOIN post p ON pl.post_id = p.id + INNER JOIN person pe ON pl.person_id = pe.id + WHERE + pl.published > ('now'::timestamp - i::interval) + AND pe.bot_account = FALSE + UNION + SELECT + cl.person_id, + p.community_id + FROM + comment_like cl + INNER JOIN post p ON cl.post_id = p.id + INNER JOIN person pe ON cl.person_id = pe.id + WHERE + cl.published > ('now'::timestamp - i::interval) + AND pe.bot_account = FALSE) a +GROUP BY + community_id; +END; +$$; + +-- Edit site aggregates to include voters and people who have read posts as active users +CREATE OR REPLACE FUNCTION site_aggregates_activity (i text) + RETURNS integer + LANGUAGE plpgsql + AS $$ +DECLARE + count_ integer; +BEGIN + SELECT + count(*) INTO count_ + FROM ( + SELECT + c.creator_id + FROM + comment c + INNER JOIN person pe ON c.creator_id = pe.id + WHERE + c.published > ('now'::timestamp - i::interval) + AND pe.local = TRUE + AND pe.bot_account = FALSE + UNION + SELECT + p.creator_id + FROM + post p + INNER JOIN person pe ON p.creator_id = pe.id + WHERE + p.published > ('now'::timestamp - i::interval) + AND pe.local = TRUE + AND pe.bot_account = FALSE + UNION + SELECT + pl.person_id + FROM + post_like pl + INNER JOIN person pe ON pl.person_id = pe.id + WHERE + pl.published > ('now'::timestamp - i::interval) + AND pe.local = TRUE + AND pe.bot_account = FALSE + UNION + SELECT + cl.person_id + FROM + comment_like cl + INNER JOIN person pe ON cl.person_id = pe.id + WHERE + cl.published > ('now'::timestamp - i::interval) + AND pe.local = TRUE + AND pe.bot_account = FALSE) a; + RETURN count_; +END; +$$; + diff --git a/scripts/sql_format_check.sh b/scripts/sql_format_check.sh index 0178204de..a75425da8 100755 --- a/scripts/sql_format_check.sh +++ b/scripts/sql_format_check.sh @@ -7,9 +7,12 @@ CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" cd $CWD/../ -find migrations -type f -name "*.sql" -print0 | while read -d $'\0' FILE -do - TMP_FILE="/tmp/tmp_pg_format.sql" - pg_format $FILE > $TMP_FILE - diff -u $FILE $TMP_FILE -done +# Copy the files to a temp dir +TMP_DIR=$(mktemp -d) +cp -a migrations/. $TMP_DIR + +# Format the new files +find $TMP_DIR -type f -name '*.sql' -exec pg_format -i {} + + +# Diff the directories +diff -r migrations $TMP_DIR diff --git a/src/lib.rs b/src/lib.rs index 72c46fd38..1b2507f4e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,14 +16,15 @@ use activitypub_federation::config::{FederationConfig, FederationMiddleware}; use actix_cors::Cors; use actix_web::{ dev::{ServerHandle, ServiceResponse}, - middleware::{self, ErrorHandlerResponse, ErrorHandlers}, + middleware::{self, Condition, ErrorHandlerResponse, ErrorHandlers}, web::Data, App, HttpResponse, HttpServer, Result, }; -use clap::{ArgAction, Parser}; +use actix_web_prom::PrometheusMetricsBuilder; +use clap::Parser; use lemmy_api_common::{ context::LemmyContext, lemmy_db_views::structs::SiteView, @@ -48,7 +49,9 @@ use lemmy_utils::{ rate_limit::RateLimitCell, response::jsonify_plain_text_errors, settings::{structs::Settings, SETTINGS}, + version, }; +use prometheus::default_registry; use prometheus_metrics::serve_prometheus; use reqwest_middleware::ClientBuilder; use reqwest_tracing::TracingMiddleware; @@ -69,24 +72,23 @@ use url::Url; long_about = "A link aggregator for the fediverse.\n\nThis is the Lemmy backend API server. This will connect to a PostgreSQL database, run any pending migrations and start accepting API requests." )] pub struct CmdArgs { + /// Don't run scheduled tasks. + /// + /// If you are running multiple Lemmy server processes, you probably want to disable scheduled tasks on + /// all but one of the processes, to avoid running the tasks more often than intended. #[arg(long, default_value_t = false)] - /// Disables running scheduled tasks. - /// - /// If you are running multiple Lemmy server processes, - /// you probably want to disable scheduled tasks on all but one of the processes, - /// to avoid running the tasks more often than intended. disable_scheduled_tasks: bool, - /// Whether or not to run the HTTP server. + /// Disables the HTTP server. /// - /// This can be used to run a Lemmy server process that only runs scheduled tasks. - #[arg(long, default_value_t = true, action=ArgAction::Set)] - http_server: bool, - /// Whether or not to emit outgoing ActivityPub messages. + /// This can be used to run a Lemmy server process that only performs scheduled tasks or activity sending. + #[arg(long, default_value_t = false)] + disable_http_server: bool, + /// Disable sending outgoing ActivityPub messages. /// - /// Set to true for a simple setup. Only set to false for horizontally scaled setups. - /// See https://join-lemmy.org/docs/administration/horizontal_scaling.html for detail. - #[arg(long, default_value_t = true, action=ArgAction::Set)] - federate_activities: bool, + /// Only pass this for horizontally scaled setups. + /// See https://join-lemmy.org/docs/administration/horizontal_scaling.html for details. + #[arg(long, default_value_t = false)] + disable_activity_sending: bool, /// The index of this outgoing federation process. /// /// Defaults to 1/1. If you want to split the federation workload onto n servers, run each server 1≤i≤n with these args: @@ -106,9 +108,12 @@ pub struct CmdArgs { /// Placing the main function in lib.rs allows other crates to import it and embed Lemmy pub async fn start_lemmy_server(args: CmdArgs) -> Result<(), LemmyError> { + // Print version number to log + println!("Lemmy v{}", version::VERSION); + // return error 503 while running db migrations and startup tasks let mut startup_server_handle = None; - if args.http_server { + if !args.disable_http_server { startup_server_handle = Some(create_startup_server()?); } @@ -131,7 +136,7 @@ pub async fn start_lemmy_server(args: CmdArgs) -> Result<(), LemmyError> { let federation_enabled = local_site.federation_enabled; if federation_enabled { - println!("federation enabled, host is {}", &SETTINGS.hostname); + println!("Federation enabled, host is {}", &SETTINGS.hostname); } check_private_instance_and_federation_enabled(&local_site)?; @@ -142,7 +147,7 @@ pub async fn start_lemmy_server(args: CmdArgs) -> Result<(), LemmyError> { let rate_limit_cell = RateLimitCell::new(rate_limit_config); println!( - "Starting http server at {}:{}", + "Starting HTTP server at {}:{}", SETTINGS.bind, SETTINGS.port ); @@ -188,7 +193,7 @@ pub async fn start_lemmy_server(args: CmdArgs) -> Result<(), LemmyError> { let request_data = federation_config.to_request_data(); let outgoing_activities_task = tokio::task::spawn(handle_outgoing_activities(request_data)); - let server = if args.http_server { + let server = if !args.disable_http_server { if let Some(startup_server_handle) = startup_server_handle { startup_server_handle.stop(true).await; } @@ -201,7 +206,7 @@ pub async fn start_lemmy_server(args: CmdArgs) -> Result<(), LemmyError> { } else { None }; - let federate = args.federate_activities.then(|| { + let federate = (!args.disable_activity_sending).then(|| { start_stop_federation_workers_cancellable( Opts { process_index: args.federate_process_index, @@ -265,7 +270,6 @@ fn create_http_server( ) -> Result { // this must come before the HttpServer creation // creates a middleware that populates http metrics for each path, method, and status code - #[cfg(feature = "prometheus-metrics")] let prom_api_metrics = PrometheusMetricsBuilder::new("lemmy_api") .registry(default_registry().clone()) .build() @@ -295,7 +299,11 @@ fn create_http_server( .app_data(Data::new(context.clone())) .app_data(Data::new(rate_limit_cell.clone())) .wrap(FederationMiddleware::new(federation_config.clone())) - .wrap(SessionMiddleware::new(context.clone())); + .wrap(SessionMiddleware::new(context.clone())) + .wrap(Condition::new( + SETTINGS.prometheus.is_some(), + prom_api_metrics.clone(), + )); // The routes app @@ -325,7 +333,7 @@ fn cors_config(settings: &Settings) -> Cors { (Some(origin), false) => { // Need to call send_wildcard() explicitly, passing this into allowed_origin() results in error if cors_origin_setting.as_deref() == Some("*") { - Cors::default().send_wildcard() + Cors::default().allow_any_origin().send_wildcard() } else { Cors::default() .allowed_origin(&origin) diff --git a/src/main.rs b/src/main.rs index a876f7f11..1544bcecf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,13 +18,10 @@ pub async fn main() -> Result<(), LemmyError> { .port() .unwrap_or(8080); let pictrs_address = ["127.0.0.1", &pictrs_port.to_string()].join(":"); - pict_rs::ConfigSource::memory(serde_json::json!({ + let pictrs_config = pict_rs::ConfigSource::memory(serde_json::json!({ "server": { "address": pictrs_address }, - "old_db": { - "path": "./pictrs/old" - }, "repo": { "type": "sled", "path": "./pictrs/sled-repo" @@ -36,7 +33,7 @@ pub async fn main() -> Result<(), LemmyError> { })) .init::<&str>(None) .expect("initialize pictrs config"); - let (lemmy, pictrs) = tokio::join!(start_lemmy_server(args), pict_rs::run()); + let (lemmy, pictrs) = tokio::join!(start_lemmy_server(args), pictrs_config.run_on_localset()); lemmy?; pictrs.expect("run pictrs"); }