From 6626d35b9818ede81f697d73df65f1693791fe09 Mon Sep 17 00:00:00 2001 From: Nutomic Date: Wed, 13 Dec 2023 15:14:59 +0100 Subject: [PATCH 01/23] Second attempt to make command line options more consistent (#4249) Co-authored-by: Dessalines --- src/lib.rs | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 3807405f63..7b7436e65d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,7 +24,7 @@ use actix_web::{ Result, }; use actix_web_prom::PrometheusMetricsBuilder; -use clap::{ArgAction, Parser}; +use clap::Parser; use lemmy_api_common::{ context::LemmyContext, lemmy_db_views::structs::SiteView, @@ -72,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 { - /// Disables running scheduled tasks. + /// 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, action=ArgAction::Set)] + /// 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)] 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: @@ -114,7 +113,7 @@ pub async fn start_lemmy_server(args: CmdArgs) -> Result<(), LemmyError> { // 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()?); } @@ -194,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; } @@ -212,7 +211,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, From 0b2df3980fe3381f38fec9c9c057d06cae2ef17b Mon Sep 17 00:00:00 2001 From: Dessalines Date: Wed, 13 Dec 2023 09:24:24 -0500 Subject: [PATCH 02/23] Version 0.19.0-rc.15 --- Cargo.lock | 24 ++++++++++++------------ Cargo.toml | 24 ++++++++++++------------ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 042b55e565..d2baff5b1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2523,7 +2523,7 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lemmy_api" -version = "0.19.0-rc.14" +version = "0.19.0-rc.15" dependencies = [ "activitypub_federation", "actix-web", @@ -2551,7 +2551,7 @@ dependencies = [ [[package]] name = "lemmy_api_common" -version = "0.19.0-rc.14" +version = "0.19.0-rc.15" dependencies = [ "activitypub_federation", "actix-web", @@ -2585,7 +2585,7 @@ dependencies = [ [[package]] name = "lemmy_api_crud" -version = "0.19.0-rc.14" +version = "0.19.0-rc.15" dependencies = [ "activitypub_federation", "actix-web", @@ -2607,7 +2607,7 @@ dependencies = [ [[package]] name = "lemmy_apub" -version = "0.19.0-rc.14" +version = "0.19.0-rc.15" dependencies = [ "activitypub_federation", "actix-web", @@ -2646,7 +2646,7 @@ dependencies = [ [[package]] name = "lemmy_db_schema" -version = "0.19.0-rc.14" +version = "0.19.0-rc.15" dependencies = [ "activitypub_federation", "async-trait", @@ -2682,7 +2682,7 @@ dependencies = [ [[package]] name = "lemmy_db_views" -version = "0.19.0-rc.14" +version = "0.19.0-rc.15" dependencies = [ "actix-web", "diesel", @@ -2700,7 +2700,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_actor" -version = "0.19.0-rc.14" +version = "0.19.0-rc.15" dependencies = [ "chrono", "diesel", @@ -2717,7 +2717,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_moderator" -version = "0.19.0-rc.14" +version = "0.19.0-rc.15" dependencies = [ "diesel", "diesel-async", @@ -2729,7 +2729,7 @@ dependencies = [ [[package]] name = "lemmy_federate" -version = "0.19.0-rc.14" +version = "0.19.0-rc.15" dependencies = [ "activitypub_federation", "anyhow", @@ -2752,7 +2752,7 @@ dependencies = [ [[package]] name = "lemmy_routes" -version = "0.19.0-rc.14" +version = "0.19.0-rc.15" dependencies = [ "activitypub_federation", "actix-web", @@ -2776,7 +2776,7 @@ dependencies = [ [[package]] name = "lemmy_server" -version = "0.19.0-rc.14" +version = "0.19.0-rc.15" dependencies = [ "activitypub_federation", "actix-cors", @@ -2818,7 +2818,7 @@ dependencies = [ [[package]] name = "lemmy_utils" -version = "0.19.0-rc.14" +version = "0.19.0-rc.15" dependencies = [ "actix-web", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 7589a5996a..8f41318a5f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace.package] -version = "0.19.0-rc.14" +version = "0.19.0-rc.15" edition = "2021" description = "A link aggregator for the fediverse" license = "AGPL-3.0" @@ -84,16 +84,16 @@ unused_self = "deny" unwrap_used = "deny" [workspace.dependencies] -lemmy_api = { version = "=0.19.0-rc.14", path = "./crates/api" } -lemmy_api_crud = { version = "=0.19.0-rc.14", path = "./crates/api_crud" } -lemmy_apub = { version = "=0.19.0-rc.14", path = "./crates/apub" } -lemmy_utils = { version = "=0.19.0-rc.14", path = "./crates/utils" } -lemmy_db_schema = { version = "=0.19.0-rc.14", path = "./crates/db_schema" } -lemmy_api_common = { version = "=0.19.0-rc.14", path = "./crates/api_common" } -lemmy_routes = { version = "=0.19.0-rc.14", path = "./crates/routes" } -lemmy_db_views = { version = "=0.19.0-rc.14", path = "./crates/db_views" } -lemmy_db_views_actor = { version = "=0.19.0-rc.14", path = "./crates/db_views_actor" } -lemmy_db_views_moderator = { version = "=0.19.0-rc.14", path = "./crates/db_views_moderator" } +lemmy_api = { version = "=0.19.0-rc.15", path = "./crates/api" } +lemmy_api_crud = { version = "=0.19.0-rc.15", path = "./crates/api_crud" } +lemmy_apub = { version = "=0.19.0-rc.15", path = "./crates/apub" } +lemmy_utils = { version = "=0.19.0-rc.15", path = "./crates/utils" } +lemmy_db_schema = { version = "=0.19.0-rc.15", path = "./crates/db_schema" } +lemmy_api_common = { version = "=0.19.0-rc.15", path = "./crates/api_common" } +lemmy_routes = { version = "=0.19.0-rc.15", path = "./crates/routes" } +lemmy_db_views = { version = "=0.19.0-rc.15", path = "./crates/db_views" } +lemmy_db_views_actor = { version = "=0.19.0-rc.15", path = "./crates/db_views_actor" } +lemmy_db_views_moderator = { version = "=0.19.0-rc.15", path = "./crates/db_views_moderator" } activitypub_federation = { version = "0.5.0-beta.6", default-features = false, features = [ "actix-web", ] } @@ -164,7 +164,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.14", path = "crates/federate" } +lemmy_federate = { version = "0.19.0-rc.15", path = "crates/federate" } activitypub_federation = { workspace = true } diesel = { workspace = true } diesel-async = { workspace = true } From 01aa17f38e5cb88a3956cc5e4c4a810e1e522eb8 Mon Sep 17 00:00:00 2001 From: Nutomic Date: Wed, 13 Dec 2023 15:29:10 +0100 Subject: [PATCH 03/23] Reenable API tests that were accidentally skipped (#4259) * Reenable API tests that were accidentally skipped * log get comment parent id failure --- .gitignore | 1 - api_tests/src/community.spec.ts | 2 +- api_tests/src/shared.ts | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 6883b4eca1..07a8382018 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/api_tests/src/community.spec.ts b/api_tests/src/community.spec.ts index fc5f347b61..b4a58bb7be 100644 --- a/api_tests/src/community.spec.ts +++ b/api_tests/src/community.spec.ts @@ -249,7 +249,7 @@ test("Admin actions in remote community are not federated to origin", async () = expect(gammaPost2.post_view.creator_banned_from_community).toBe(false); }); -test.only("moderator view", async () => { +test("moderator view", async () => { // register a new user with their own community on alpha and post to it let otherUser = await registerUser(alpha, alphaUrl); diff --git a/api_tests/src/shared.ts b/api_tests/src/shared.ts index d2193d90d3..0545eee57e 100644 --- a/api_tests/src/shared.ts +++ b/api_tests/src/shared.ts @@ -863,6 +863,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; } } From 32afc32bc085862dc09d19370b1ccde7b17c9a2f Mon Sep 17 00:00:00 2001 From: dullbananas Date: Thu, 14 Dec 2023 05:10:01 -0700 Subject: [PATCH 04/23] Correctly combine sorts in post view cursor-based pagination (#4247) * Update post_view.rs * Update post_view.rs * Update Cargo.toml * Update post_view.rs * fix * Update post_view.rs --------- Co-authored-by: SleeplessOne1917 Co-authored-by: Dessalines --- Cargo.lock | 1 + crates/db_views/Cargo.toml | 1 + crates/db_views/src/post_view.rs | 336 ++++++++++++++++++------------- 3 files changed, 202 insertions(+), 136 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d2baff5b1b..f4d0846d65 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2685,6 +2685,7 @@ name = "lemmy_db_views" version = "0.19.0-rc.15" dependencies = [ "actix-web", + "chrono", "diesel", "diesel-async", "diesel_ltree", diff --git a/crates/db_views/Cargo.toml b/crates/db_views/Cargo.toml index 847b743921..5c8fd21ebc 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/post_view.rs b/crates/db_views/src/post_view.rs index 3eeeb8993d..1d15c7c41d 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -1,15 +1,13 @@ 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,12 +33,12 @@ 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::{fuzzy_search, get_conn, limit_and_offset, now, DbConn, DbPool, ListFn, Queries, ReadFn}, ListingType, SortType, }; @@ -48,53 +46,32 @@ 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< @@ -334,16 +311,6 @@ fn queries<'a>() -> Queries< .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)); } @@ -481,85 +448,101 @@ 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, + 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 tie_breaker = match options.sort.unwrap_or(SortType::Hot) { + // A second time-based sort would not be very useful + SortType::New | SortType::Old | SortType::NewComments => None, + _ => Some((Ord::Desc, field!(published))), + }; + + let sorts = [ + Some((Ord::Desc, featured_field)), + Some(main_sort), + tie_breaker, + ]; + 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), }; - 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); + + 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() { @@ -737,15 +720,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, @@ -762,6 +747,7 @@ mod tests { SubscribedType, }; use serial_test::serial; + use std::time::Duration; struct Data { inserted_instance: Instance, @@ -1431,6 +1417,84 @@ 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; + } + 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) From 7353be5b68893e57ca88b1db1412dc4d4fb38ce4 Mon Sep 17 00:00:00 2001 From: phiresky Date: Thu, 14 Dec 2023 13:25:04 +0100 Subject: [PATCH 05/23] federate-less-noisy (#4263) --- crates/federate/src/lib.rs | 8 ++++---- crates/federate/src/worker.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/federate/src/lib.rs b/crates/federate/src/lib.rs index b6c820aaad..382aa59b88 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 ad2b5b7d2b..a383d61b24 100644 --- a/crates/federate/src/worker.rs +++ b/crates/federate/src/worker.rs @@ -221,7 +221,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()); From 4a55d4f87185a38e00a8cc32c69040c7f869b531 Mon Sep 17 00:00:00 2001 From: Nutomic Date: Thu, 14 Dec 2023 13:25:47 +0100 Subject: [PATCH 06/23] Quick fix for Peertube federation (fixes #4261) (#4264) * Quick fix for Peertube federation (fixes #4261) * prettier * apub assets should be included in slow check paths --- .woodpecker.yml | 3 +- .../apub/assets/peertube/objects/group.json | 159 ++---- .../apub/assets/peertube/objects/person.json | 148 ++---- .../apub/assets/peertube/objects/video.json | 478 +++++++++--------- crates/apub/src/protocol/objects/group.rs | 1 + crates/apub/src/protocol/objects/person.rs | 1 + 6 files changed, 322 insertions(+), 468 deletions(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index 0b8b6f8c88..6e30293dee 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 diff --git a/crates/apub/assets/peertube/objects/group.json b/crates/apub/assets/peertube/objects/group.json index cf4e216c46..1817fb2022 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" - }, - "support": { - "@type": "sc:Text", - "@id": "pt:support" - }, - "likes": { - "@id": "as:likes", - "@type": "@id" - }, - "dislikes": { - "@id": "as:dislikes", - "@type": "@id" - }, + "sc": "http://schema.org/", "playlists": { "@id": "pt:playlists", "@type": "@id" }, - "shares": { - "@id": "as:shares", - "@type": "@id" + "support": { + "@type": "sc:Text", + "@id": "pt:support" }, - "comments": { - "@id": "as:comments", - "@type": "@id" - } + "icons": "as:icon" + } + ], + "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" } ], - "summary": "Un logiciel libre pour reprendre le contrôle de vos vidéos", - "support": null, + "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 871e88e133..2b1acdaad6 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" - }, - "support": { - "@type": "sc:Text", - "@id": "pt:support" - }, - "likes": { - "@id": "as:likes", - "@type": "@id" - }, - "dislikes": { - "@id": "as:dislikes", - "@type": "@id" - }, + "sc": "http://schema.org/", "playlists": { "@id": "pt:playlists", "@type": "@id" }, - "shares": { - "@id": "as:shares", - "@type": "@id" + "support": { + "@type": "sc:Text", + "@id": "pt:support" }, - "comments": { - "@id": "as:comments", - "@type": "@id" - } + "icons": "as:icon" + } + ], + "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": null + "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 78e732fe58..daca3d554c 100644 --- a/crates/apub/assets/peertube/objects/video.json +++ b/crates/apub/assets/peertube/objects/video.json @@ -1,339 +1,406 @@ { - "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" - }, + "@context": [ + "https://www.w3.org/ns/activitystreams", + "https://w3id.org/security/v1", { - "type": "Hashtag", - "name": "Mastodon" + "RsaSignature2017": "https://w3id.org/security#RsaSignature2017" }, { - "type": "Hashtag", - "name": "PeerTube " + "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", + "identifier": "sc:identifier", + "isLiveBroadcast": "sc:isLiveBroadcast", + "liveSaveReplay": { + "@type": "sc:Boolean", + "@id": "pt:liveSaveReplay" + }, + "permanentLive": { + "@type": "sc:Boolean", + "@id": "pt:permanentLive" + }, + "latencyMode": { + "@type": "sc:Number", + "@id": "pt:latencyMode" + }, + "Infohash": "pt:Infohash", + "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" + }, + "state": { + "@type": "sc:Number", + "@id": "pt:state" + }, + "size": { + "@type": "sc:Number", + "@id": "pt:size" + }, + "fps": { + "@type": "sc:Number", + "@id": "pt:fps" + }, + "commentsEnabled": { + "@type": "sc:Boolean", + "@id": "pt:commentsEnabled" + }, + "downloadEnabled": { + "@type": "sc:Boolean", + "@id": "pt:downloadEnabled" + }, + "waitTranscoding": { + "@type": "sc:Boolean", + "@id": "pt:waitTranscoding" + }, + "support": { + "@type": "sc:Text", + "@id": "pt:support" + }, + "likes": { + "@id": "as:likes", + "@type": "@id" + }, + "dislikes": { + "@id": "as:dislikes", + "@type": "@id" + }, + "shares": { + "@id": "as:shares", + "@type": "@id" + }, + "comments": { + "@id": "as:comments", + "@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": "15", - "name": "Science & Technology" - }, - "licence": { - "identifier": "2", - "name": "Attribution - Share Alike" + "identifier": "11", + "name": "News & Politics" }, - "language": { - "identifier": "en", - "name": "English" - }, - "views": 4805, + "views": 83, "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" - }, + "published": "2023-12-12T17:02:02.188Z", + "originallyPublishedAt": "2023-12-11T23:00:00.000Z", + "updated": "2023-12-14T06:40:34.279Z", + "tag": [ { - "identifier": "tr", - "name": "Turkish", - "url": "https://framatube.org/lazy-static/video-captions/1b2ea189-760c-4a3e-98d3-16f596c151f0-tr.vtt" + "type": "Hashtag", + "name": "France3" }, { - "identifier": "vi", - "name": "Vietnamese", - "url": "https://framatube.org/lazy-static/video-captions/552b4086-54ab-4eb3-a8b3-7611a2175e77-vi.vtt" + "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://framatube.org/static/thumbnails/1f9eb76e-c089-4bdd-af14-602935a6db72.jpg", + "url": "https://peertube.stream/lazy-static/thumbnails/208d2248-6fa3-4a58-a2e6-c6f176559457.jpg", "mediaType": "image/jpeg", "width": 280, "height": 157 }, { "type": "Image", - "url": "https://framatube.org/lazy-static/previews/8f89d4d8-696f-4512-9a1a-72f1d12caede.jpg", + "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://framatube.org/videos/watch/4294a720-f263-4ea4-9392-cf9cea4d5277" + "href": "https://peertube.stream/videos/watch/46cc7342-fdd5-4583-ae16-2eeb340d3b60" }, { "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", + "href": "https://peertube.stream/static/streaming-playlists/hls/46cc7342-fdd5-4583-ae16-2eeb340d3b60/7847c00b-17f0-4cd9-b788-94283bd96d5b-master.m3u8", "tag": [ { "type": "Infohash", - "name": "caf7178ddd2013e28c9fbcbb7be28df25d03a023" + "name": "f50d9a3e851756a1fc1da7fe8b6e40f849c1f3a1" + }, + { + "type": "Infohash", + "name": "fdddadfcf01c52808a5716ac9c0f09e379a1ca69" }, { "type": "Infohash", - "name": "cc18bb140f51f64090ba41c951fba85705cafa38" + "name": "c309597f071c6ab59e1a6935be3dc1ceb58c9250" }, { "type": "Infohash", - "name": "595513d823a1aecc18abacac94a1ebb0c31ec009" + "name": "5c28ed3e05102a678dc047a126650fe53d45ded4" }, { "type": "Infohash", - "name": "6ae0ce749a57d0f8ff70286878ea7661f85eebf7" + "name": "085f2c72c69af02913177534ec601349ca2b4f01" }, { "type": "Infohash", - "name": "4eb799f42d461929ed8dd4befae274c9a4404b99" + "name": "37b9dbeab6f433e94f80a614f888e9a1e9ee3534" }, { "type": "Infohash", - "name": "b48d1ea795657668783544fd1c9baf637198a323" + "name": "cc15513891e63a92743730ba65ab256f8825f071" }, { "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" + "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://framatube.org/static/streaming-playlists/hls/4294a720-f263-4ea4-9392-cf9cea4d5277/64147344-1957-480d-9106-59dd7bbf5661-1080-fragmented.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": 14653991, - "fps": 24 + "size": 90186372, + "fps": 25 }, { "type": "Link", "rel": ["metadata", "video/mp4"], "mediaType": "application/json", - "href": "https://framatube.org/api/v1/videos/4294a720-f263-4ea4-9392-cf9cea4d5277/metadata/1421492", + "href": "https://peertube.stream/api/v1/videos/46cc7342-fdd5-4583-ae16-2eeb340d3b60/metadata/1570438", "height": 1080, - "fps": 24 + "fps": 25 }, { "type": "Link", "mediaType": "application/x-bittorrent", - "href": "https://framatube.org/lazy-static/torrents/83fa27e3-aba7-4e01-9e66-931086374176-1080-hls.torrent", + "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%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", + "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://framatube.org/static/streaming-playlists/hls/4294a720-f263-4ea4-9392-cf9cea4d5277/0efaeae5-7468-4c45-ade5-d3b6c732621f-720-fragmented.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": 9939723, - "fps": 24 + "size": 50950797, + "fps": 25 }, { "type": "Link", "rel": ["metadata", "video/mp4"], "mediaType": "application/json", - "href": "https://framatube.org/api/v1/videos/4294a720-f263-4ea4-9392-cf9cea4d5277/metadata/1421496", + "href": "https://peertube.stream/api/v1/videos/46cc7342-fdd5-4583-ae16-2eeb340d3b60/metadata/1570447", "height": 720, - "fps": 24 + "fps": 25 }, { "type": "Link", "mediaType": "application/x-bittorrent", - "href": "https://framatube.org/lazy-static/torrents/b325c824-c052-46e2-9b46-887595055521-720-hls.torrent", + "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%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", + "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://framatube.org/static/streaming-playlists/hls/4294a720-f263-4ea4-9392-cf9cea4d5277/201f9772-4971-4bc3-8356-9b85b405ae5d-480-fragmented.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": 7398758, - "fps": 24 + "size": 31542462, + "fps": 25 }, { "type": "Link", "rel": ["metadata", "video/mp4"], "mediaType": "application/json", - "href": "https://framatube.org/api/v1/videos/4294a720-f263-4ea4-9392-cf9cea4d5277/metadata/1421494", + "href": "https://peertube.stream/api/v1/videos/46cc7342-fdd5-4583-ae16-2eeb340d3b60/metadata/1570441", "height": 480, - "fps": 24 + "fps": 25 }, { "type": "Link", "mediaType": "application/x-bittorrent", - "href": "https://framatube.org/lazy-static/torrents/bd99f84e-e9bc-4d36-bea6-6f06000f87c5-480-hls.torrent", + "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%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", + "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://framatube.org/static/streaming-playlists/hls/4294a720-f263-4ea4-9392-cf9cea4d5277/b2313ae6-da36-4fe3-bec5-aa352824a38a-360-fragmented.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": 6133890, - "fps": 24 + "size": 23389554, + "fps": 25 }, { "type": "Link", "rel": ["metadata", "video/mp4"], "mediaType": "application/json", - "href": "https://framatube.org/api/v1/videos/4294a720-f263-4ea4-9392-cf9cea4d5277/metadata/1421495", + "href": "https://peertube.stream/api/v1/videos/46cc7342-fdd5-4583-ae16-2eeb340d3b60/metadata/1570442", "height": 360, - "fps": 24 + "fps": 25 }, { "type": "Link", "mediaType": "application/x-bittorrent", - "href": "https://framatube.org/lazy-static/torrents/b939430a-fdfd-4da7-a030-759ecafa6ac7-360-hls.torrent", + "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%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", + "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://framatube.org/static/streaming-playlists/hls/4294a720-f263-4ea4-9392-cf9cea4d5277/06a866f2-0527-4d68-93b7-c656d7374e86-240-fragmented.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": 4861464, - "fps": 24 + "size": 16040535, + "fps": 25 }, { "type": "Link", "rel": ["metadata", "video/mp4"], "mediaType": "application/json", - "href": "https://framatube.org/api/v1/videos/4294a720-f263-4ea4-9392-cf9cea4d5277/metadata/1421497", + "href": "https://peertube.stream/api/v1/videos/46cc7342-fdd5-4583-ae16-2eeb340d3b60/metadata/1570448", "height": 240, - "fps": 24 + "fps": 25 }, { "type": "Link", "mediaType": "application/x-bittorrent", - "href": "https://framatube.org/lazy-static/torrents/072001ee-18ad-4859-af10-9d7bf12d640c-240-hls.torrent", + "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%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", + "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://framatube.org/static/streaming-playlists/hls/4294a720-f263-4ea4-9392-cf9cea4d5277/f8a1caed-057f-4700-a28e-004efc158b15-0-fragmented.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": 3141179, + "size": 6074306, "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", + "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://framatube.org/lazy-static/torrents/77cb6940-7e90-48d1-a391-bfa463b9600c-0-hls.torrent", + "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%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", + "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 } ] @@ -342,124 +409,33 @@ "type": "Link", "name": "tracker-http", "rel": ["tracker", "http"], - "href": "https://framatube.org/tracker/announce" + "href": "https://peertube.stream/tracker/announce" }, { "type": "Link", "name": "tracker-websocket", "rel": ["tracker", "websocket"], - "href": "wss://framatube.org:443/tracker/socket" + "href": "wss://peertube.stream: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", + "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://framatube.org/accounts/framasoft" + "id": "https://peertube.stream/accounts/createurs" }, { "type": "Group", - "id": "https://framatube.org/video-channels/joinpeertube" + "id": "https://peertube.stream/video-channels/vu" } ], - "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", - { - "RsaSignature2017": "https://w3id.org/security#RsaSignature2017" - }, - { - "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" - }, - "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" - } - } - ] + "isLiveBroadcast": false, + "liveSaveReplay": null, + "permanentLive": null, + "latencyMode": null, + "peertubeLiveChat": false } diff --git a/crates/apub/src/protocol/objects/group.rs b/crates/apub/src/protocol/objects/group.rs index 8346e85b7c..7dce298a6d 100644 --- a/crates/apub/src/protocol/objects/group.rs +++ b/crates/apub/src/protocol/objects/group.rs @@ -57,6 +57,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 cc9607c7fc..c8cae5541d 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, From 442ec0b9f8cfb1787265b55ccf403a9a937bd9ad Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 14 Dec 2023 07:26:01 -0500 Subject: [PATCH 07/23] Upgrading lemmy-js-client to 0.19.0 (#4260) --- api_tests/package.json | 16 ++-- api_tests/yarn.lock | 168 +++++++++++++++++++------------------- docker/docker-compose.yml | 2 +- 3 files changed, 93 insertions(+), 93 deletions(-) diff --git a/api_tests/package.json b/api_tests/package.json index 8ab01b628f..4d3e57d21e 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.10", - "@types/node": "^20.9.4", - "@typescript-eslint/eslint-plugin": "^6.12.0", - "@typescript-eslint/parser": "^6.12.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.54.0", + "eslint": "^8.55.0", "eslint-plugin-prettier": "^5.0.1", "jest": "^29.5.0", - "lemmy-js-client": "0.19.0-rc.19", - "prettier": "^3.1.0", + "lemmy-js-client": "0.19.0", + "prettier": "^3.1.1", "ts-jest": "^29.1.0", - "typescript": "^5.3.2" + "typescript": "^5.3.3" } } diff --git a/api_tests/yarn.lock b/api_tests/yarn.lock index ebf36bc581..d2cf2ab26e 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.54.0": - version "8.54.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.54.0.tgz#4fab9a2ff7860082c304f750e94acd644cf984cf" - integrity sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ== +"@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.10": - version "29.5.10" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.10.tgz#a10fc5bab9e426081c12b2ef73d24d4f0c9b7f50" - integrity sha512-tE4yxKEphEyxj9s4inideLHktW/x6DwesIwWZ9NN1FKf9zbJYsnhBoA9vrHA/IuIOKwPa5PcFBNV4lpMIOEzyQ== +"@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.4": - version "20.9.4" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.9.4.tgz#cc8f970e869c26834bdb7ed480b30ede622d74c7" - integrity sha512-wmyg8HUhcn6ACjsn8oKYjkN/zUzQeNtMy44weTJSM6p4MMzEOuKbA3OjJ267uPCOW7Xex9dyrNTful8XTQYoDA== +"@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.12.0": - version "6.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.12.0.tgz#2a647d278bb48bf397fef07ba0507612ff9dd812" - integrity sha512-XOpZ3IyJUIV1b15M7HVOpgQxPPF7lGXgsfcEIu3yDxFPaf/xZKt7s9QO/pbk7vpWQyVulpJbu4E5LwpZiQo4kA== +"@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.12.0" - "@typescript-eslint/type-utils" "6.12.0" - "@typescript-eslint/utils" "6.12.0" - "@typescript-eslint/visitor-keys" "6.12.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.12.0": - version "6.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.12.0.tgz#9fb21ed7d88065a4a2ee21eb80b8578debb8217c" - integrity sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg== +"@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.12.0" - "@typescript-eslint/types" "6.12.0" - "@typescript-eslint/typescript-estree" "6.12.0" - "@typescript-eslint/visitor-keys" "6.12.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.12.0": - version "6.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz#5833a16dbe19cfbad639d4d33bcca5e755c7044b" - integrity sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw== +"@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.12.0" - "@typescript-eslint/visitor-keys" "6.12.0" + "@typescript-eslint/types" "6.14.0" + "@typescript-eslint/visitor-keys" "6.14.0" -"@typescript-eslint/type-utils@6.12.0": - version "6.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.12.0.tgz#968f7c95162808d69950ab5dff710ad730e58287" - integrity sha512-WWmRXxhm1X8Wlquj+MhsAG4dU/Blvf1xDgGaYCzfvStP2NwPQh6KBvCDbiOEvaE0filhranjIlK/2fSTVwtBng== +"@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.12.0" - "@typescript-eslint/utils" "6.12.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.12.0": - version "6.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.12.0.tgz#ffc5297bcfe77003c8b7b545b51c2505748314ac" - integrity sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q== +"@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.12.0": - version "6.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz#764ccc32598549e5b48ec99e3b85f89b1385310c" - integrity sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw== +"@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.12.0" - "@typescript-eslint/visitor-keys" "6.12.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.12.0": - version "6.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.12.0.tgz#c6ce8c06fe9b0212620e5674a2036f6f8f611754" - integrity sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ== +"@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.12.0" - "@typescript-eslint/types" "6.12.0" - "@typescript-eslint/typescript-estree" "6.12.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.12.0": - version "6.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz#5877950de42a0f3344261b7a1eee15417306d7e9" - integrity sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw== +"@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.12.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.54.0: - version "8.54.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.54.0.tgz#588e0dd4388af91a2e8fa37ea64924074c783537" - integrity sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA== +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.54.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-rc.19: - version "0.19.0-rc.19" - resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.19.0-rc.19.tgz#13932ab2b40cf16aa5218715509ebdc48f874f84" - integrity sha512-kae8V33QixbyYIA+pn7+sCeOOWL3eRgnFaNkZU8Y8vxhwZExIhkZus9jzVt/BoyPddVlafyBHxgAUsWXLA4tRA== +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.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.0.tgz#c6d16474a5f764ea1a4a373c593b779697744d5e" - integrity sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw== +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.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.2.tgz#00d1c7c1c46928c5845c1ee8d0cc2791031d4c43" - integrity sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ== +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/docker/docker-compose.yml b/docker/docker-compose.yml index fdf6c32c2c..712c3d8cf7 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -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.8 + image: dessalines/lemmy-ui:0.19.0-rc.14 # 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 From 59eef85bb76019508fcd889c28f54d4a43128646 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 14 Dec 2023 07:59:27 -0500 Subject: [PATCH 08/23] Version 0.19.0-rc.16 --- Cargo.lock | 24 ++++++++++++------------ Cargo.toml | 24 ++++++++++++------------ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f4d0846d65..0c3144d517 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2523,7 +2523,7 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lemmy_api" -version = "0.19.0-rc.15" +version = "0.19.0-rc.16" dependencies = [ "activitypub_federation", "actix-web", @@ -2551,7 +2551,7 @@ dependencies = [ [[package]] name = "lemmy_api_common" -version = "0.19.0-rc.15" +version = "0.19.0-rc.16" dependencies = [ "activitypub_federation", "actix-web", @@ -2585,7 +2585,7 @@ dependencies = [ [[package]] name = "lemmy_api_crud" -version = "0.19.0-rc.15" +version = "0.19.0-rc.16" dependencies = [ "activitypub_federation", "actix-web", @@ -2607,7 +2607,7 @@ dependencies = [ [[package]] name = "lemmy_apub" -version = "0.19.0-rc.15" +version = "0.19.0-rc.16" dependencies = [ "activitypub_federation", "actix-web", @@ -2646,7 +2646,7 @@ dependencies = [ [[package]] name = "lemmy_db_schema" -version = "0.19.0-rc.15" +version = "0.19.0-rc.16" dependencies = [ "activitypub_federation", "async-trait", @@ -2682,7 +2682,7 @@ dependencies = [ [[package]] name = "lemmy_db_views" -version = "0.19.0-rc.15" +version = "0.19.0-rc.16" dependencies = [ "actix-web", "chrono", @@ -2701,7 +2701,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_actor" -version = "0.19.0-rc.15" +version = "0.19.0-rc.16" dependencies = [ "chrono", "diesel", @@ -2718,7 +2718,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_moderator" -version = "0.19.0-rc.15" +version = "0.19.0-rc.16" dependencies = [ "diesel", "diesel-async", @@ -2730,7 +2730,7 @@ dependencies = [ [[package]] name = "lemmy_federate" -version = "0.19.0-rc.15" +version = "0.19.0-rc.16" dependencies = [ "activitypub_federation", "anyhow", @@ -2753,7 +2753,7 @@ dependencies = [ [[package]] name = "lemmy_routes" -version = "0.19.0-rc.15" +version = "0.19.0-rc.16" dependencies = [ "activitypub_federation", "actix-web", @@ -2777,7 +2777,7 @@ dependencies = [ [[package]] name = "lemmy_server" -version = "0.19.0-rc.15" +version = "0.19.0-rc.16" dependencies = [ "activitypub_federation", "actix-cors", @@ -2819,7 +2819,7 @@ dependencies = [ [[package]] name = "lemmy_utils" -version = "0.19.0-rc.15" +version = "0.19.0-rc.16" dependencies = [ "actix-web", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 8f41318a5f..a64a82bf76 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace.package] -version = "0.19.0-rc.15" +version = "0.19.0-rc.16" edition = "2021" description = "A link aggregator for the fediverse" license = "AGPL-3.0" @@ -84,16 +84,16 @@ unused_self = "deny" unwrap_used = "deny" [workspace.dependencies] -lemmy_api = { version = "=0.19.0-rc.15", path = "./crates/api" } -lemmy_api_crud = { version = "=0.19.0-rc.15", path = "./crates/api_crud" } -lemmy_apub = { version = "=0.19.0-rc.15", path = "./crates/apub" } -lemmy_utils = { version = "=0.19.0-rc.15", path = "./crates/utils" } -lemmy_db_schema = { version = "=0.19.0-rc.15", path = "./crates/db_schema" } -lemmy_api_common = { version = "=0.19.0-rc.15", path = "./crates/api_common" } -lemmy_routes = { version = "=0.19.0-rc.15", path = "./crates/routes" } -lemmy_db_views = { version = "=0.19.0-rc.15", path = "./crates/db_views" } -lemmy_db_views_actor = { version = "=0.19.0-rc.15", path = "./crates/db_views_actor" } -lemmy_db_views_moderator = { version = "=0.19.0-rc.15", path = "./crates/db_views_moderator" } +lemmy_api = { version = "=0.19.0-rc.16", path = "./crates/api" } +lemmy_api_crud = { version = "=0.19.0-rc.16", path = "./crates/api_crud" } +lemmy_apub = { version = "=0.19.0-rc.16", path = "./crates/apub" } +lemmy_utils = { version = "=0.19.0-rc.16", path = "./crates/utils" } +lemmy_db_schema = { version = "=0.19.0-rc.16", path = "./crates/db_schema" } +lemmy_api_common = { version = "=0.19.0-rc.16", path = "./crates/api_common" } +lemmy_routes = { version = "=0.19.0-rc.16", path = "./crates/routes" } +lemmy_db_views = { version = "=0.19.0-rc.16", path = "./crates/db_views" } +lemmy_db_views_actor = { version = "=0.19.0-rc.16", path = "./crates/db_views_actor" } +lemmy_db_views_moderator = { version = "=0.19.0-rc.16", path = "./crates/db_views_moderator" } activitypub_federation = { version = "0.5.0-beta.6", default-features = false, features = [ "actix-web", ] } @@ -164,7 +164,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.15", path = "crates/federate" } +lemmy_federate = { version = "0.19.0-rc.16", path = "crates/federate" } activitypub_federation = { workspace = true } diesel = { workspace = true } diesel-async = { workspace = true } From ac209d58b48ecb60c80f6423e811f8d98aa548e6 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 14 Dec 2023 10:26:42 -0500 Subject: [PATCH 09/23] Adding a retry on a few fetches. (#4267) --- api_tests/src/comment.spec.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/api_tests/src/comment.spec.ts b/api_tests/src/comment.spec.ts index 1ce40a5cc5..4655a81ffc 100644 --- a/api_tests/src/comment.spec.ts +++ b/api_tests/src/comment.spec.ts @@ -344,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) { @@ -405,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, ); From af4d008ce4e2ed17eea487352a920047f5b09103 Mon Sep 17 00:00:00 2001 From: Nutomic Date: Thu, 14 Dec 2023 17:18:15 +0100 Subject: [PATCH 10/23] Minor CI improvements (#4266) * Speed up SQL formatting in CI with parallel processing * mess up formatting * check permissions * make repo world writable * need git * use debian image * apt update * perl image for faster install * fix format * run restore cache in parallel to format * add drone-cache exit code * revert sql format changes --- .woodpecker.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.woodpecker.yml b/.woodpecker.yml index 6e30293dee..6b9126bffe 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -85,6 +85,7 @@ steps: - if [[ "$IGNORED" ]]; then echo "Ignored files present:\n$IGNORED\n"; exit 1; fi restore-cache: + group: format image: meltwater/drone-cache:v1 pull: true settings: @@ -104,6 +105,7 @@ steps: - ".cargo_home" - "target" - "api_tests/node_modules" + exit_code: true secrets: [MINIO_ENDPOINT, MINIO_WRITE_USER, MINIO_WRITE_PASSWORD, MINIO_BUCKET] when: *slow_check_paths @@ -230,6 +232,7 @@ steps: - ".cargo_home" - "target" - "api_tests/node_modules" + exit_code: true secrets: [MINIO_ENDPOINT, MINIO_WRITE_USER, MINIO_WRITE_PASSWORD, MINIO_BUCKET] when: From 70530a8ad2dc064baa9668f623e3196caacfdc64 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 14 Dec 2023 11:35:52 -0500 Subject: [PATCH 11/23] Optimizing sql format check. (#4268) * Optimizing sql format check. * Fixing format testing. * Fixing format testing 2. --- scripts/sql_format_check.sh | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/scripts/sql_format_check.sh b/scripts/sql_format_check.sh index 0178204dee..a75425da8f 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 From e4b97ad8a9a1a3581481cccdd2ce010354a8b970 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 14 Dec 2023 18:36:33 -0500 Subject: [PATCH 12/23] Revert "Minor CI improvements (#4266)" (#4271) This reverts commit af4d008ce4e2ed17eea487352a920047f5b09103. --- .woodpecker.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index 6b9126bffe..6e30293dee 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -85,7 +85,6 @@ steps: - if [[ "$IGNORED" ]]; then echo "Ignored files present:\n$IGNORED\n"; exit 1; fi restore-cache: - group: format image: meltwater/drone-cache:v1 pull: true settings: @@ -105,7 +104,6 @@ steps: - ".cargo_home" - "target" - "api_tests/node_modules" - exit_code: true secrets: [MINIO_ENDPOINT, MINIO_WRITE_USER, MINIO_WRITE_PASSWORD, MINIO_BUCKET] when: *slow_check_paths @@ -232,7 +230,6 @@ steps: - ".cargo_home" - "target" - "api_tests/node_modules" - exit_code: true secrets: [MINIO_ENDPOINT, MINIO_WRITE_USER, MINIO_WRITE_PASSWORD, MINIO_BUCKET] when: From 246e38a45b7ad110a303a79449d3b3466d3ce170 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Fri, 15 Dec 2023 05:34:17 -0500 Subject: [PATCH 13/23] Making login case-insensitive. Fixes #4272 (#4273) * Making login case-insensitive. Fixes #4272 * Removing redundant lowercase. --- crates/db_schema/src/impls/instance.rs | 11 +++++++---- crates/db_schema/src/impls/post.rs | 2 +- crates/db_views/src/local_user_view.rs | 17 +++++++++++++---- crates/db_views/src/post_view.rs | 16 ++++++++++++---- 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/crates/db_schema/src/impls/instance.rs b/crates/db_schema/src/impls/instance.rs index 7da4ce354b..7d63c9ffa3 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 d65fd23983..4f2f88cb21 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::{ @@ -30,6 +29,7 @@ use crate::{ }, traits::{Crud, Likeable, Saveable}, utils::{ + functions::coalesce, get_conn, naive_now, DbPool, diff --git a/crates/db_views/src/local_user_view.rs b/crates/db_views/src/local_user_view.rs index dd0e3631b4..cb9ab86c48 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_view.rs b/crates/db_views/src/post_view.rs index 1d15c7c41d..745e32c181 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -4,7 +4,6 @@ use diesel::{ dsl::{exists, not, IntervalDsl}, pg::Pg, result::Error, - sql_function, sql_types, BoolExpressionMethods, BoxableExpression, @@ -38,14 +37,23 @@ use lemmy_db_schema::{ post_read, post_saved, }, - utils::{fuzzy_search, get_conn, limit_and_offset, now, 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); - #[derive(Clone, Copy, Debug, PartialEq, Eq)] enum Ord { Desc, From 719b76a6e71d895459c79cf9f199f8886ff8673e Mon Sep 17 00:00:00 2001 From: Dessalines Date: Fri, 15 Dec 2023 05:36:58 -0500 Subject: [PATCH 14/23] Create comment in transaction. Fixes #3741 (#4265) * Create comment in transaction. Fixes #3741 * Removing if let on comment create. --- crates/db_schema/src/impls/comment.rs | 113 +++++++++++++------------- 1 file changed, 58 insertions(+), 55 deletions(-) diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index 35bc8314ad..aef399c595 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; - - if let Ok(comment_insert) = inserted_comment { - let comment_id = comment_insert.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; - - // 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); - - if let Some(parent_id) = parent_id { - let top_parent = format!("0.{}", parent_id); - let update_child_count_stmt = format!( - " + 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?; + + 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) + }); + + 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 + + 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!( + " 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?; + } + } + updated_comment + }) as _ + }) + .await } pub async fn read_from_apub_id( pool: &mut DbPool<'_>, From 7a182c982ba3a9ee862862d4beb2dc0df5b37c34 Mon Sep 17 00:00:00 2001 From: Nutomic Date: Fri, 15 Dec 2023 12:28:08 +0100 Subject: [PATCH 15/23] Debug random test failure (#4275) --- crates/db_views_actor/src/person_view.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/db_views_actor/src/person_view.rs b/crates/db_views_actor/src/person_view.rs index 16e9b3bc66..f42fa15cfe 100644 --- a/crates/db_views_actor/src/person_view.rs +++ b/crates/db_views_actor/src/person_view.rs @@ -230,6 +230,7 @@ mod tests { #[tokio::test] #[serial] + #[allow(clippy::dbg_macro)] async fn exclude_deleted() { let pool = &build_db_pool_for_tests().await; let pool = &mut pool.into(); @@ -256,6 +257,7 @@ mod tests { .list(pool) .await .unwrap(); + dbg!(&list); assert_eq!(list.len(), 1); assert_eq!(list[0].person.id, data.bob.id); From a7ba5c9dd33475fd8ae9bb41c39cf8875775a488 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 15 Dec 2023 04:42:28 -0700 Subject: [PATCH 16/23] Sort by post id in post view (#4270) * Sort by post id in post view * Remove tie_breaker --------- Co-authored-by: Dessalines Co-authored-by: Nutomic --- crates/db_views/src/post_view.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index 745e32c181..a40e384808 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -490,16 +490,10 @@ fn queries<'a>() -> Queries< query = query.filter(post_aggregates::published.gt(now() - interval)); } - let tie_breaker = match options.sort.unwrap_or(SortType::Hot) { - // A second time-based sort would not be very useful - SortType::New | SortType::Old | SortType::NewComments => None, - _ => Some((Ord::Desc, field!(published))), - }; - let sorts = [ Some((Ord::Desc, featured_field)), Some(main_sort), - tie_breaker, + Some((Ord::Desc, field!(post_id))), ]; let sorts_iter = sorts.iter().flatten(); From aab3ca4eb0888b6089fb5b68805b06ad4b4f43af Mon Sep 17 00:00:00 2001 From: Dessalines Date: Fri, 15 Dec 2023 06:53:26 -0500 Subject: [PATCH 17/23] Version 0.19.0 --- Cargo.lock | 24 ++++++++++++------------ Cargo.toml | 24 ++++++++++++------------ docker/docker-compose.yml | 4 ++-- docker/federation/docker-compose.yml | 2 +- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0c3144d517..5589c610c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2523,7 +2523,7 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lemmy_api" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "activitypub_federation", "actix-web", @@ -2551,7 +2551,7 @@ dependencies = [ [[package]] name = "lemmy_api_common" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "activitypub_federation", "actix-web", @@ -2585,7 +2585,7 @@ dependencies = [ [[package]] name = "lemmy_api_crud" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "activitypub_federation", "actix-web", @@ -2607,7 +2607,7 @@ dependencies = [ [[package]] name = "lemmy_apub" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "activitypub_federation", "actix-web", @@ -2646,7 +2646,7 @@ dependencies = [ [[package]] name = "lemmy_db_schema" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "activitypub_federation", "async-trait", @@ -2682,7 +2682,7 @@ dependencies = [ [[package]] name = "lemmy_db_views" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "actix-web", "chrono", @@ -2701,7 +2701,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_actor" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "chrono", "diesel", @@ -2718,7 +2718,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_moderator" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "diesel", "diesel-async", @@ -2730,7 +2730,7 @@ dependencies = [ [[package]] name = "lemmy_federate" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "activitypub_federation", "anyhow", @@ -2753,7 +2753,7 @@ dependencies = [ [[package]] name = "lemmy_routes" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "activitypub_federation", "actix-web", @@ -2777,7 +2777,7 @@ dependencies = [ [[package]] name = "lemmy_server" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "activitypub_federation", "actix-cors", @@ -2819,7 +2819,7 @@ dependencies = [ [[package]] name = "lemmy_utils" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "actix-web", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index a64a82bf76..75d2852c63 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace.package] -version = "0.19.0-rc.16" +version = "0.19.0" edition = "2021" description = "A link aggregator for the fediverse" license = "AGPL-3.0" @@ -84,16 +84,16 @@ unused_self = "deny" unwrap_used = "deny" [workspace.dependencies] -lemmy_api = { version = "=0.19.0-rc.16", path = "./crates/api" } -lemmy_api_crud = { version = "=0.19.0-rc.16", path = "./crates/api_crud" } -lemmy_apub = { version = "=0.19.0-rc.16", path = "./crates/apub" } -lemmy_utils = { version = "=0.19.0-rc.16", path = "./crates/utils" } -lemmy_db_schema = { version = "=0.19.0-rc.16", path = "./crates/db_schema" } -lemmy_api_common = { version = "=0.19.0-rc.16", path = "./crates/api_common" } -lemmy_routes = { version = "=0.19.0-rc.16", path = "./crates/routes" } -lemmy_db_views = { version = "=0.19.0-rc.16", path = "./crates/db_views" } -lemmy_db_views_actor = { version = "=0.19.0-rc.16", path = "./crates/db_views_actor" } -lemmy_db_views_moderator = { version = "=0.19.0-rc.16", path = "./crates/db_views_moderator" } +lemmy_api = { version = "=0.19.0", path = "./crates/api" } +lemmy_api_crud = { version = "=0.19.0", path = "./crates/api_crud" } +lemmy_apub = { version = "=0.19.0", path = "./crates/apub" } +lemmy_utils = { version = "=0.19.0", path = "./crates/utils" } +lemmy_db_schema = { version = "=0.19.0", path = "./crates/db_schema" } +lemmy_api_common = { version = "=0.19.0", path = "./crates/api_common" } +lemmy_routes = { version = "=0.19.0", path = "./crates/routes" } +lemmy_db_views = { version = "=0.19.0", path = "./crates/db_views" } +lemmy_db_views_actor = { version = "=0.19.0", path = "./crates/db_views_actor" } +lemmy_db_views_moderator = { version = "=0.19.0", path = "./crates/db_views_moderator" } activitypub_federation = { version = "0.5.0-beta.6", default-features = false, features = [ "actix-web", ] } @@ -164,7 +164,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.16", path = "crates/federate" } +lemmy_federate = { version = "0.19.0", path = "crates/federate" } activitypub_federation = { workspace = true } diesel = { workspace = true } diesel-async = { workspace = true } diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 712c3d8cf7..4c1a674118 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 @@ -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.14 + 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 diff --git a/docker/federation/docker-compose.yml b/docker/federation/docker-compose.yml index 142267596b..6e0e7f2d26 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 From bc32b408b523b9b64aa57b8e47748f96cce0dae5 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Mon, 18 Dec 2023 04:25:05 -0500 Subject: [PATCH 18/23] Fixing private message reports. (#4279) --- api_tests/prepare-drone-federation-test.sh | 2 +- api_tests/src/private_message.spec.ts | 40 +++++++++++++++++++ api_tests/src/shared.ts | 14 +++++++ .../api/src/private_message_report/create.rs | 5 +++ 4 files changed, 60 insertions(+), 1 deletion(-) diff --git a/api_tests/prepare-drone-federation-test.sh b/api_tests/prepare-drone-federation-test.sh index 0f7591b312..4710168d99 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/private_message.spec.ts b/api_tests/src/private_message.spec.ts index 08c519df7f..75dcaee336 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 0545eee57e..fe51fb0469 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"; @@ -781,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 { diff --git a/crates/api/src/private_message_report/create.rs b/crates/api/src/private_message_report/create.rs index 75620bf8b6..7aca9661bd 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, From dcb89f52d6c7a0dac6d0cd769ea00c31da7d8dcd Mon Sep 17 00:00:00 2001 From: dullbananas Date: Mon, 18 Dec 2023 02:31:39 -0700 Subject: [PATCH 19/23] Don't update comment_aggregates if updating path fails (#4281) --- crates/db_schema/src/impls/comment.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index aef399c595..7173b79d23 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -87,7 +87,7 @@ impl Comment { let updated_comment = diesel::update(comment.find(comment_id)) .set(path.eq(ltree)) .get_result::(conn) - .await; + .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, @@ -121,7 +121,7 @@ where ca.comment_id = c.id" sql_query(update_child_count_stmt).execute(conn).await?; } } - updated_comment + Ok(updated_comment) }) as _ }) .await From 6790b54d4d6a0a0161f38320f6f85e26c58185d9 Mon Sep 17 00:00:00 2001 From: phiresky Date: Mon, 18 Dec 2023 19:17:10 +0100 Subject: [PATCH 20/23] make activity channel infallible (#4295) --- crates/api_common/src/send_activity.rs | 4 ++-- crates/apub/src/activities/mod.rs | 7 ++++--- crates/federate/src/worker.rs | 1 + 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/crates/api_common/src/send_activity.rs b/crates/api_common/src/send_activity.rs index 6d9c722a17..ceaed48268 100644 --- a/crates/api_common/src/send_activity.rs +++ b/crates/api_common/src/send_activity.rs @@ -98,9 +98,9 @@ impl ActivityChannel { Ok(()) } - pub async fn close(outgoing_activities_task: JoinHandle>) -> 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/apub/src/activities/mod.rs b/crates/apub/src/activities/mod.rs index ee3eb16fff..83d029d4e5 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/federate/src/worker.rs b/crates/federate/src/worker.rs index a383d61b24..963814ad98 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; }; From 8583a856079b9273c97d1b7826dcf5c8ab311ce5 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Mon, 18 Dec 2023 14:20:42 -0500 Subject: [PATCH 21/23] Version 0.19.1-rc.1 --- Cargo.lock | 24 ++++++++++++------------ Cargo.toml | 24 ++++++++++++------------ crates/utils/translations | 2 +- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5589c610c5..9952b7aae0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2523,7 +2523,7 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lemmy_api" -version = "0.19.0" +version = "0.19.1-rc.1" dependencies = [ "activitypub_federation", "actix-web", @@ -2551,7 +2551,7 @@ dependencies = [ [[package]] name = "lemmy_api_common" -version = "0.19.0" +version = "0.19.1-rc.1" dependencies = [ "activitypub_federation", "actix-web", @@ -2585,7 +2585,7 @@ dependencies = [ [[package]] name = "lemmy_api_crud" -version = "0.19.0" +version = "0.19.1-rc.1" dependencies = [ "activitypub_federation", "actix-web", @@ -2607,7 +2607,7 @@ dependencies = [ [[package]] name = "lemmy_apub" -version = "0.19.0" +version = "0.19.1-rc.1" dependencies = [ "activitypub_federation", "actix-web", @@ -2646,7 +2646,7 @@ dependencies = [ [[package]] name = "lemmy_db_schema" -version = "0.19.0" +version = "0.19.1-rc.1" dependencies = [ "activitypub_federation", "async-trait", @@ -2682,7 +2682,7 @@ dependencies = [ [[package]] name = "lemmy_db_views" -version = "0.19.0" +version = "0.19.1-rc.1" dependencies = [ "actix-web", "chrono", @@ -2701,7 +2701,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_actor" -version = "0.19.0" +version = "0.19.1-rc.1" dependencies = [ "chrono", "diesel", @@ -2718,7 +2718,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_moderator" -version = "0.19.0" +version = "0.19.1-rc.1" dependencies = [ "diesel", "diesel-async", @@ -2730,7 +2730,7 @@ dependencies = [ [[package]] name = "lemmy_federate" -version = "0.19.0" +version = "0.19.1-rc.1" dependencies = [ "activitypub_federation", "anyhow", @@ -2753,7 +2753,7 @@ dependencies = [ [[package]] name = "lemmy_routes" -version = "0.19.0" +version = "0.19.1-rc.1" dependencies = [ "activitypub_federation", "actix-web", @@ -2777,7 +2777,7 @@ dependencies = [ [[package]] name = "lemmy_server" -version = "0.19.0" +version = "0.19.1-rc.1" dependencies = [ "activitypub_federation", "actix-cors", @@ -2819,7 +2819,7 @@ dependencies = [ [[package]] name = "lemmy_utils" -version = "0.19.0" +version = "0.19.1-rc.1" dependencies = [ "actix-web", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 75d2852c63..655f2c3a94 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace.package] -version = "0.19.0" +version = "0.19.1-rc.1" edition = "2021" description = "A link aggregator for the fediverse" license = "AGPL-3.0" @@ -84,16 +84,16 @@ unused_self = "deny" unwrap_used = "deny" [workspace.dependencies] -lemmy_api = { version = "=0.19.0", path = "./crates/api" } -lemmy_api_crud = { version = "=0.19.0", path = "./crates/api_crud" } -lemmy_apub = { version = "=0.19.0", path = "./crates/apub" } -lemmy_utils = { version = "=0.19.0", path = "./crates/utils" } -lemmy_db_schema = { version = "=0.19.0", path = "./crates/db_schema" } -lemmy_api_common = { version = "=0.19.0", path = "./crates/api_common" } -lemmy_routes = { version = "=0.19.0", path = "./crates/routes" } -lemmy_db_views = { version = "=0.19.0", path = "./crates/db_views" } -lemmy_db_views_actor = { version = "=0.19.0", path = "./crates/db_views_actor" } -lemmy_db_views_moderator = { version = "=0.19.0", path = "./crates/db_views_moderator" } +lemmy_api = { version = "=0.19.1-rc.1", path = "./crates/api" } +lemmy_api_crud = { version = "=0.19.1-rc.1", path = "./crates/api_crud" } +lemmy_apub = { version = "=0.19.1-rc.1", path = "./crates/apub" } +lemmy_utils = { version = "=0.19.1-rc.1", path = "./crates/utils" } +lemmy_db_schema = { version = "=0.19.1-rc.1", path = "./crates/db_schema" } +lemmy_api_common = { version = "=0.19.1-rc.1", path = "./crates/api_common" } +lemmy_routes = { version = "=0.19.1-rc.1", path = "./crates/routes" } +lemmy_db_views = { version = "=0.19.1-rc.1", path = "./crates/db_views" } +lemmy_db_views_actor = { version = "=0.19.1-rc.1", path = "./crates/db_views_actor" } +lemmy_db_views_moderator = { version = "=0.19.1-rc.1", path = "./crates/db_views_moderator" } activitypub_federation = { version = "0.5.0-beta.6", default-features = false, features = [ "actix-web", ] } @@ -164,7 +164,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", path = "crates/federate" } +lemmy_federate = { version = "0.19.1-rc.1", path = "crates/federate" } activitypub_federation = { workspace = true } diesel = { workspace = true } diesel-async = { workspace = true } diff --git a/crates/utils/translations b/crates/utils/translations index 7a38baa734..9474a7c0fb 160000 --- a/crates/utils/translations +++ b/crates/utils/translations @@ -1 +1 @@ -Subproject commit 7a38baa7341cfa9299df5a80ebe42fe298380e40 +Subproject commit 9474a7c0fbc968b8da29251bf5183b7de383cebf From 2899ba013106a3462d6a4d95eb19bf37ae451117 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Tue, 19 Dec 2023 04:46:41 -0500 Subject: [PATCH 22/23] Fixing broken post_read logic. Fixes #4290 (#4297) --- crates/db_views/src/post_view.rs | 48 ++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index a40e384808..857e7f644e 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -412,7 +412,8 @@ fn queries<'a>() -> Queries< .unwrap_or(true) { // Do not hide read posts when it is a user profile view - if let (Some(_creator_id), Some(person_id)) = (options.creator_id, my_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))); } } @@ -741,7 +742,7 @@ 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, RANK_DEFAULT}, @@ -749,7 +750,7 @@ mod tests { SubscribedType, }; use serial_test::serial; - use std::time::Duration; + use std::{collections::HashSet, time::Duration}; struct Data { inserted_instance: Instance, @@ -1497,6 +1498,47 @@ mod tests { 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) From a507a39336d0240fb8c12363e84ffe062624b7cc Mon Sep 17 00:00:00 2001 From: Nutomic Date: Tue, 19 Dec 2023 11:26:00 +0100 Subject: [PATCH 23/23] Add missing test cleanup (#4289) * Add missing test cleanup * cleanup --- crates/db_views/src/private_message_view.rs | 17 ++++++++++------- crates/db_views_actor/src/person_view.rs | 2 -- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/crates/db_views/src/private_message_view.rs b/crates/db_views/src/private_message_view.rs index 54bae94827..26d97038ce 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_actor/src/person_view.rs b/crates/db_views_actor/src/person_view.rs index f42fa15cfe..16e9b3bc66 100644 --- a/crates/db_views_actor/src/person_view.rs +++ b/crates/db_views_actor/src/person_view.rs @@ -230,7 +230,6 @@ mod tests { #[tokio::test] #[serial] - #[allow(clippy::dbg_macro)] async fn exclude_deleted() { let pool = &build_db_pool_for_tests().await; let pool = &mut pool.into(); @@ -257,7 +256,6 @@ mod tests { .list(pool) .await .unwrap(); - dbg!(&list); assert_eq!(list.len(), 1); assert_eq!(list[0].person.id, data.bob.id);