diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7827d8221..41032a8c3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ # Contributing -See [here](https://dev.lemmy.ml/docs/contributing.html) for contributing Instructions. +See [here](https://lemmy.ml/docs/contributing.html) for contributing Instructions. diff --git a/Cargo.lock b/Cargo.lock index 7823e9fc2..cf741d689 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1761,6 +1761,7 @@ dependencies = [ "async-trait", "awc", "background-jobs", + "backtrace", "base64 0.13.0", "bcrypt", "chrono", diff --git a/README.md b/README.md index 3d5fe3d24..211759e1f 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@
Join Lemmy · - Documentation + Documentation · Report Bug · @@ -65,7 +65,7 @@ Each Lemmy server can set its own moderation policy; appointing site-wide admins - Open source, [AGPL License](/LICENSE). - Self hostable, easy to deploy. - - Comes with [Docker](https://dev.lemmy.ml/docs/administration_install_docker.html) and [Ansible](https://dev.lemmy.ml/docs/administration_install_ansible.html). + - Comes with [Docker](https://lemmy.ml/docs/administration_install_docker.html) and [Ansible](https://lemmy.ml/docs/administration_install_ansible.html). - Clean, mobile-friendly interface. - Only a minimum of a username and password is required to sign up! - User avatar support. @@ -100,8 +100,8 @@ Each Lemmy server can set its own moderation policy; appointing site-wide admins ## Installation -- [Docker](https://dev.lemmy.ml/docs/administration_install_docker.html) -- [Ansible](https://dev.lemmy.ml/docs/administration_install_ansible.html) +- [Docker](https://lemmy.ml/docs/administration_install_docker.html) +- [Ansible](https://lemmy.ml/docs/administration_install_ansible.html) ## Lemmy Projects @@ -134,9 +134,9 @@ Lemmy is free, open-source software, meaning no advertising, monetizing, or vent ## Contributing -- [Contributing instructions](https://dev.lemmy.ml/docs/contributing.html) -- [Docker Development](https://dev.lemmy.ml/docs/contributing_docker_development.html) -- [Local Development](https://dev.lemmy.ml/docs/contributing_local_development.html) +- [Contributing instructions](https://lemmy.ml/docs/contributing.html) +- [Docker Development](https://lemmy.ml/docs/contributing_docker_development.html) +- [Local Development](https://lemmy.ml/docs/contributing_local_development.html) ### Translations diff --git a/RELEASES.md b/RELEASES.md index 34ddd62ad..b362d7f17 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -20,7 +20,7 @@ Here are some of the bigger changes: - The first **federation public beta release**, woohoo :fireworks: - All Lemmy functionality now works over ActivityPub (except turning remote users into mods/admins) - Instance allowlist and blocklist -- Documentation for [admins](https://dev.lemmy.ml/docs/administration_federation.html) and [devs](https://dev.lemmy.ml/docs/contributing_federation_overview.html) on how federation works +- Documentation for [admins](https://lemmy.ml/docs/administration_federation.html) and [devs](https://lemmy.ml/docs/contributing_federation_overview.html) on how federation works - Upgraded to newest versions of @asonix activitypub libraries - Full local federation setup for manual testing - Automated testing for nearly every federation action @@ -54,18 +54,18 @@ Here are some of the bigger changes: ## Contributors -We'd also like to thank both the [NLnet foundation](https://nlnet.nl/) for their support in allowing us to work full-time on Lemmy ( as well as their support for [other important open-source projects](https://nlnet.nl/project/current.html) ), [those who sponsor us](https://dev.lemmy.ml/sponsors), and those who [help translate Lemmy](https://weblate.yerbamate.ml/projects/lemmy/). Every little bit does help. We remain committed to never allowing advertisements, monetizing, or venture-capital in Lemmy; software should be communal, and should benefit humanity, not a small group of company owners. +We'd also like to thank both the [NLnet foundation](https://nlnet.nl/) for their support in allowing us to work full-time on Lemmy ( as well as their support for [other important open-source projects](https://nlnet.nl/project/current.html) ), [those who sponsor us](https://lemmy.ml/sponsors), and those who [help translate Lemmy](https://weblate.yerbamate.ml/projects/lemmy/). Every little bit does help. We remain committed to never allowing advertisements, monetizing, or venture-capital in Lemmy; software should be communal, and should benefit humanity, not a small group of company owners. ## Upgrading -- [with manual Docker installation](https://dev.lemmy.ml/docs/administration_install_docker.html#updating) -- [with Ansible installation](https://dev.lemmy.ml/docs/administration_install_ansible.html) +- [with manual Docker installation](https://lemmy.ml/docs/administration_install_docker.html#updating) +- [with Ansible installation](https://lemmy.ml/docs/administration_install_ansible.html) ## Testing Federation Federation is finally ready in Lemmy, pending possible bugs or other issues. So for now we suggest to enable federation only on test servers, or try it on our own test servers ( [enterprise](https://enterprise.lemmy.ml/), [ds9](https://ds9.lemmy.ml/), [voyager](https://voyager.lemmy.ml/) ). -If everything goes well, after a few weeks we will enable federation on dev.lemmy.ml, at first with a limited number of trusted instances. We will also likely change the domain to https://lemmy.ml . Keep in mind that changing domains after turning on federation will break things. +If everything goes well, after a few weeks we will enable federation on lemmy.ml, at first with a limited number of trusted instances. We will also likely change the domain to https://lemmy.ml . Keep in mind that changing domains after turning on federation will break things. To enable on your instance, edit your [lemmy.hjson](https://github.com/LemmyNet/lemmy/blob/main/config/defaults.hjson#L60) federation section to `enabled: true`, and restart. @@ -147,7 +147,7 @@ Overall, since our last major release in January (v0.6.0), we have closed over Before starting the upgrade, make sure that you have a working backup of your database and image files. See our -[documentation](https://dev.lemmy.ml/docs/administration_backup_and_restore.html) +[documentation](https://lemmy.ml/docs/administration_backup_and_restore.html) for backup instructions. **With Ansible:** @@ -203,4 +203,4 @@ This is the biggest release by far: Another major announcement is that Lemmy now has another lead developer besides me, [@felix@radical.town](https://radical.town/@felix). Theyve created a better documentation system, implemented RSS feeds, simplified docker and project configs, upgraded actix, working on federation, a whole lot else. -https://dev.lemmy.ml +https://lemmy.ml diff --git a/ansible/templates/config.hjson b/ansible/templates/config.hjson index 2e60ffc24..134b01656 100644 --- a/ansible/templates/config.hjson +++ b/ansible/templates/config.hjson @@ -1,6 +1,6 @@ { # for more info about the config, check out the documentation - # https://dev.lemmy.ml/docs/administration_configuration.html + # https://lemmy.ml/docs/administration_configuration.html # settings related to the postgresql database database: { @@ -9,7 +9,7 @@ # host where postgres is running host: "postgres" } - # the domain name of your instance (eg "dev.lemmy.ml") + # the domain name of your instance (eg "lemmy.ml") hostname: "{{ domain }}" # json web token for authorization between server and client jwt_secret: "{{ jwt_password }}" @@ -26,7 +26,7 @@ # whether to enable activitypub federation. enabled: false # Allows and blocks are described here: - # https://dev.lemmy.ml/docs/administration_federation.html#instance-allowlist-and-blocklist + # https://lemmy.ml/docs/administration_federation.html#instance-allowlist-and-blocklist # # comma separated list of instances with which federation is allowed # allowed_instances: "" diff --git a/config/defaults.hjson b/config/defaults.hjson index f23b1fb13..86502ec93 100644 --- a/config/defaults.hjson +++ b/config/defaults.hjson @@ -25,7 +25,7 @@ # maximum number of active sql connections pool_size: 5 } - # the domain name of your instance (eg "dev.lemmy.ml") + # the domain name of your instance (eg "lemmy.ml") hostname: null # address where lemmy should listen for incoming requests bind: "0.0.0.0" @@ -65,7 +65,7 @@ # whether to enable activitypub federation. enabled: false # Allows and blocks are described here: - # https://dev.lemmy.ml/docs/administration_federation.html#instance-allowlist-and-blocklist + # https://lemmy.ml/docs/administration_federation.html#instance-allowlist-and-blocklist # # comma separated list of instances with which federation is allowed allowed_instances: "" diff --git a/docker/lemmy.hjson b/docker/lemmy.hjson index a5d131223..2d9bfa358 100644 --- a/docker/lemmy.hjson +++ b/docker/lemmy.hjson @@ -1,6 +1,6 @@ { # for more info about the config, check out the documentation - # https://dev.lemmy.ml/docs/administration_configuration.html + # https://lemmy.ml/docs/administration_configuration.html setup: { # username for the admin user @@ -11,7 +11,7 @@ site_name: "lemmy-test" } - # the domain name of your instance (eg "dev.lemmy.ml") + # the domain name of your instance (eg "lemmy.ml") hostname: "my_domain" # address where lemmy should listen for incoming requests bind: "0.0.0.0" diff --git a/docs/src/about_ranking.md b/docs/src/about_ranking.md index 0f91b7e39..854b4da88 100644 --- a/docs/src/about_ranking.md +++ b/docs/src/about_ranking.md @@ -1,16 +1,17 @@ # Trending / Hot / Best Sorting algorithm -## Goals + +An expected feature in link aggregators is a kind of "Trending" sort which shows users a mixture of new posts / comments and popular ones, making for a display order which highlights the most currently active parts of the site / thread. This keeps the experience fresh and makes sure the site stays moving. Various flaws can be found in the ways that popular link aggregators like Reddit have implemented "Hot" or "Trending" sorts, so Lemmy has its own algorithm. + +## Goals and Considerations - During the day, new posts and comments should be near the top, so they can be voted on. - After a day or so, the time factor should go away. - Use a log scale, since votes tend to snowball, and so the first 10 votes are just as important as the next hundred. -## Reddit Sorting -[Reddit's comment sorting algorithm](https://medium.com/hacking-and-gonzo/how-reddit-ranking-algorithms-work-ef111e33d0d9), the wilson confidence sort, is inadequate, because it completely ignores time. What ends up happening, especially in smaller subreddits, is that the early comments end up getting upvoted, and newer comments stay at the bottom, never to be seen. Research showed that nearly all top comments are just the [first ones posted.](https://minimaxir.com/2016/11/first-comment/) +| Reddit | Hacker News | Lemmy | +|-|-|-| +| Does not take the lifetime of the thread into account, [giving early comments an overwhelming advantage over later ones,](https://minimaxir.com/2016/11/first-comment/) with the effect being even worse in small communities. New comments pool at the bottom of the thread, effectively killing off discussion and making each thread a race to comment early. This lowers the quality of conversation and rewards comments that are repetitive and spammy. | While far superior to Reddit's implementation for its decay of scores over time, [Hacker News' ranking algorithm](https://medium.com/hacking-and-gonzo/how-hacker-news-ranking-algorithm-works-1d9b0cf2c08d) does not use a logarithmic scale for scores. | Counterbalances the snowballing effect of votes over time with a logarithmic scale. Negates the inherent advantage of early comments while still ensuring that votes still matter in the long-term, not nuking older popular comments. | -## Hacker News Sorting -The [Hacker New's ranking algorithm](https://medium.com/hacking-and-gonzo/how-hacker-news-ranking-algorithm-works-1d9b0cf2c08d) is great, but it doesn't use a log scale for the scores. - -## My Algorithm +## Additional Details ``` Rank = ScaleFactor * log(Max(1, 3 + Score)) / (Time + 2)^Gravity diff --git a/docs/src/administration_federation.md b/docs/src/administration_federation.md index 5dc0b1a2e..c7044ac24 100644 --- a/docs/src/administration_federation.md +++ b/docs/src/administration_federation.md @@ -6,17 +6,17 @@ To enable federation, change the setting `federation.enabled` to `true` in `lemm Federation does not start automatically, but needs to be triggered manually through the search. To do this you have to enter a reference to a remote object, such as: -- `!main@dev.lemmy.ml` (Community) -- `@nutomic@dev.lemmy.ml` (User) -- `https://dev.lemmy.ml/c/programming` (Community) -- `https://dev.lemmy.ml/u/nutomic` (User) -- `https://dev.lemmy.ml/post/123` (Post) +- `!main@lemmy.ml` (Community) +- `@nutomic@lemmy.ml` (User) +- `https://lemmy.ml/c/programming` (Community) +- `https://lemmy.ml/u/nutomic` (User) +- `https://lemmy.ml/post/123` (Post) For an overview of how federation in Lemmy works on a technical level, check out our [Federation Overview](contributing_federation_overview.md). ## Instance allowlist and blocklist -The federation section of Lemmy's config has two variables `allowed_instances` and `blocked_instances`. These control which other instances Lemmy will federate with. Both settings take a comma separated list of domains, eg `dev.lemmy.ml, example.com`. You can either change those settings via `/admin`, or directly on the server filesystem. +The federation section of Lemmy's config has two variables `allowed_instances` and `blocked_instances`. These control which other instances Lemmy will federate with. Both settings take a comma separated list of domains, eg `lemmy.ml,example.com`. You can either change those settings via `/admin`, or directly on the server filesystem. It is important to note that these settings only affect sending and receiving of data between instances. If allow federation with a certain instance, and then remove it from the allowlist, this will not affect previously federated data. These communities, users, posts and comments will still be shown. They will just not be updated anymore. And even if an instance is blocked, it can still fetch and display public data from your instance. diff --git a/docs/src/contributing_apub_api_outline.md b/docs/src/contributing_apub_api_outline.md index 4fac3cf8d..92cdf9c0e 100644 --- a/docs/src/contributing_apub_api_outline.md +++ b/docs/src/contributing_apub_api_outline.md @@ -96,7 +96,7 @@ Receives activities from user: `Follow`, `Undo/Follow`, `Create`, `Update`, `Lik |---|---|---| | `preferredUsername` | yes | Name of the actor | | `name` | yes | Title of the community | -| `category` | yes | Hardcoded list of categories, see https://dev.lemmy.ml/api/v1/categories | +| `category` | yes | Hardcoded list of categories, see https://lemmy.ml/api/v1/categories | | `sensitive` | yes | True indicates that all posts in the community are nsfw | | `attributedTo` | yes | First the community creator, then all the remaining moderators | | `content` | no | Text for the community sidebar, usually containing a description and rules | @@ -689,4 +689,4 @@ Sent to: User "to": "https://enterprise.lemmy.ml/u/riker/inbox", "object": ... } -``` \ No newline at end of file +``` diff --git a/docs/src/lemmy_council.md b/docs/src/lemmy_council.md index 5de3a6c01..d5dc5a6e4 100644 --- a/docs/src/lemmy_council.md +++ b/docs/src/lemmy_council.md @@ -11,11 +11,11 @@ This section describes all the aspects of Lemmy where the council has decision m - Priorities / Emphasis - Controversial features (For example, an unpopular feature should be removed) - Moderation and conflict resolution on: - - [dev.lemmy.ml](https://dev.lemmy.ml/) + - [lemmy.ml](https://lemmy.ml/) - [github.com/LemmyNet/lemmy](https://github.com/LemmyNet/lemmy) - [yerbamate.ml/LemmyNet/lemmy](https://yerbamate.ml/LemmyNet/lemmy) - [weblate.yerbamate.ml/projects/lemmy/](https://weblate.yerbamate.ml/projects/lemmy/) -- Technical administration of dev.lemmy.ml +- Technical administration of lemmy.ml - Official Lemmy accounts - [Mastodon](https://mastodon.social/@LemmyDev) - [Liberapay](https://liberapay.com/Lemmy/) @@ -67,13 +67,13 @@ stay open for at least two days. ## 7. Communication - A private Matrix chat for all council members. -- (Once private communities are done) A private community on dev.lemmy.ml for issues. +- (Once private communities are done) A private community on lemmy.ml for issues. ## 8. Member List / Contact Info General Contact [@LemmyDev Mastodon](https://mastodon.social/@LemmyDev) -- [Dessalines](https://dev.lemmy.ml/u/dessalines) -- [Nutomic](https://dev.lemmy.ml/u/nutomic) -- [AgreeableLandscape](https://dev.lemmy.ml/u/AgreeableLandscape) -- [fruechtchen](https://dev.lemmy.ml/u/fruechtchen) -- [kixiQu](https://dev.lemmy.ml/u/kixiQu) +- [Dessalines](https://lemmy.ml/u/dessalines) +- [Nutomic](https://lemmy.ml/u/nutomic) +- [AgreeableLandscape](https://lemmy.ml/u/AgreeableLandscape) +- [fruechtchen](https://lemmy.ml/u/fruechtchen) +- [kixiQu](https://lemmy.ml/u/kixiQu) diff --git a/lemmy_api/src/post.rs b/lemmy_api/src/post.rs index d5515b5cd..298076f75 100644 --- a/lemmy_api/src/post.rs +++ b/lemmy_api/src/post.rs @@ -247,7 +247,7 @@ impl Perform for GetPosts { let community_name = data.community_name.to_owned(); let posts = match blocking(context.pool(), move |conn| { PostQueryBuilder::create(conn) - .listing_type(type_) + .listing_type(&type_) .sort(&sort) .show_nsfw(show_nsfw) .for_community_id(community_id) diff --git a/lemmy_api/src/site.rs b/lemmy_api/src/site.rs index 6d504f267..e4b1dd213 100644 --- a/lemmy_api/src/site.rs +++ b/lemmy_api/src/site.rs @@ -333,8 +333,6 @@ impl Perform for Search { ) -> Result { let data: &Search = &self; - dbg!(&data); - match search_by_apub_id(&data.q, context).await { Ok(r) => return Ok(r), Err(e) => debug!("Failed to resolve search query as activitypub ID: {}", e), diff --git a/lemmy_apub/Cargo.toml b/lemmy_apub/Cargo.toml index 5610ed699..7e8f792a5 100644 --- a/lemmy_apub/Cargo.toml +++ b/lemmy_apub/Cargo.toml @@ -46,3 +46,4 @@ anyhow = "1.0" thiserror = "1.0" background-jobs = " 0.8" reqwest = { version = "0.10", features = ["json"] } +backtrace = "0.3" diff --git a/lemmy_apub/src/objects/mod.rs b/lemmy_apub/src/objects/mod.rs index f365b528c..a162c165b 100644 --- a/lemmy_apub/src/objects/mod.rs +++ b/lemmy_apub/src/objects/mod.rs @@ -48,16 +48,14 @@ pub(in crate::objects) fn check_object_domain( where T: Base + AsBase, { - let actor_id = if let Some(url) = expected_domain { - check_is_apub_id_valid(&url)?; + let object_id = if let Some(url) = expected_domain { let domain = url.domain().context(location_info!())?; apub.id(domain)?.context(location_info!())? } else { - let actor_id = apub.id_unchecked().context(location_info!())?; - check_is_apub_id_valid(&actor_id)?; - actor_id + apub.id_unchecked().context(location_info!())? }; - Ok(actor_id.to_string()) + check_is_apub_id_valid(&object_id)?; + Ok(object_id.to_string()) } pub(in crate::objects) fn set_content_and_source( diff --git a/lemmy_apub/src/objects/post.rs b/lemmy_apub/src/objects/post.rs index ce16f8d13..a058d8b7c 100644 --- a/lemmy_apub/src/objects/post.rs +++ b/lemmy_apub/src/objects/post.rs @@ -17,6 +17,7 @@ use activitystreams::{ }; use activitystreams_ext::Ext1; use anyhow::Context; +use backtrace::Backtrace; use lemmy_db::{ community::Community, post::{Post, PostForm}, @@ -32,6 +33,7 @@ use lemmy_utils::{ LemmyError, }; use lemmy_websocket::LemmyContext; +use log::error; use url::Url; #[async_trait::async_trait(?Send)] @@ -130,6 +132,15 @@ impl FromApub for PostForm { let community = get_or_fetch_and_upsert_community(community_actor_id, context, request_counter).await?; + if community.local && creator.local { + let page_id = page.id_unchecked().context(location_info!())?; + let bt = Backtrace::new(); + error!( + "Lemmy is parsing a local post as remote, page id: {}, stack trace: {:?}", + page_id, bt + ); + } + let thumbnail_url = match &page.inner.image() { Some(any_image) => Image::from_any_base( any_image diff --git a/lemmy_db/src/lib.rs b/lemmy_db/src/lib.rs index 608632061..bad646d14 100644 --- a/lemmy_db/src/lib.rs +++ b/lemmy_db/src/lib.rs @@ -156,7 +156,7 @@ pub enum SortType { TopAll, } -#[derive(EnumString, ToString, Debug, Serialize, Deserialize)] +#[derive(EnumString, ToString, Debug, Serialize, Deserialize, Clone)] pub enum ListingType { All, Local, diff --git a/lemmy_db/src/post_view.rs b/lemmy_db/src/post_view.rs index 0ec4a9797..3fb6d2b06 100644 --- a/lemmy_db/src/post_view.rs +++ b/lemmy_db/src/post_view.rs @@ -160,7 +160,7 @@ pub struct PostView { pub struct PostQueryBuilder<'a> { conn: &'a PgConnection, query: BoxedQuery<'a, Pg>, - listing_type: ListingType, + listing_type: &'a ListingType, sort: &'a SortType, my_user_id: Option, for_creator_id: Option, @@ -184,7 +184,7 @@ impl<'a> PostQueryBuilder<'a> { PostQueryBuilder { conn, query, - listing_type: ListingType::All, + listing_type: &ListingType::All, sort: &SortType::Hot, my_user_id: None, for_creator_id: None, @@ -200,7 +200,7 @@ impl<'a> PostQueryBuilder<'a> { } } - pub fn listing_type(mut self, listing_type: ListingType) -> Self { + pub fn listing_type(mut self, listing_type: &'a ListingType) -> Self { self.listing_type = listing_type; self } @@ -497,7 +497,7 @@ mod tests { }; let read_post_listings_with_user = PostQueryBuilder::create(&conn) - .listing_type(ListingType::Community) + .listing_type(&ListingType::Community) .sort(&SortType::New) .for_community_id(inserted_community.id) .my_user_id(inserted_user.id) @@ -505,7 +505,7 @@ mod tests { .unwrap(); let read_post_listings_no_user = PostQueryBuilder::create(&conn) - .listing_type(ListingType::Community) + .listing_type(&ListingType::Community) .sort(&SortType::New) .for_community_id(inserted_community.id) .list() diff --git a/lemmy_utils/src/settings.rs b/lemmy_utils/src/settings.rs index 960c48b85..4edcbd13b 100644 --- a/lemmy_utils/src/settings.rs +++ b/lemmy_utils/src/settings.rs @@ -172,7 +172,7 @@ impl Settings { } } - /// Returns something like `http://localhost` or `https://dev.lemmy.ml`, + /// Returns something like `http://localhost` or `https://lemmy.ml`, /// with the correct protocol and hostname. pub fn get_protocol_and_hostname(&self) -> String { format!("{}://{}", self.get_protocol_string(), self.hostname) diff --git a/query_testing/apache_bench_report.sh b/query_testing/apache_bench_report.sh index 06ceb4843..d062a5111 100755 --- a/query_testing/apache_bench_report.sh +++ b/query_testing/apache_bench_report.sh @@ -4,9 +4,9 @@ set -e declare -a arr=( "https://mastodon.social/" "https://peertube.social/" -"https://dev.lemmy.ml/" -"https://dev.lemmy.ml/feeds/all.xml" -"https://dev.lemmy.ml/.well-known/nodeinfo" +"https://lemmy.ml/" +"https://lemmy.ml/feeds/all.xml" +"https://lemmy.ml/.well-known/nodeinfo" "https://fediverse.blog/.well-known/nodeinfo" "https://torrents-csv.ml/service/search?q=wheel&page=1&type_=torrent" ) diff --git a/src/routes/feeds.rs b/src/routes/feeds.rs index a9454be4d..fc4a31372 100644 --- a/src/routes/feeds.rs +++ b/src/routes/feeds.rs @@ -42,7 +42,8 @@ enum RequestType { pub fn config(cfg: &mut web::ServiceConfig) { cfg .route("/feeds/{type}/{name}.xml", web::get().to(get_feed)) - .route("/feeds/all.xml", web::get().to(get_all_feed)); + .route("/feeds/all.xml", web::get().to(get_all_feed)) + .route("/feeds/local.xml", web::get().to(get_local_feed)); } lazy_static! { @@ -61,34 +62,43 @@ async fn get_all_feed( context: web::Data, ) -> Result { let sort_type = get_sort_type(info).map_err(ErrorBadRequest)?; - - let rss = blocking(context.pool(), move |conn| { - get_feed_all_data(conn, &sort_type) - }) - .await? - .map_err(ErrorBadRequest)?; - - Ok( - HttpResponse::Ok() - .content_type("application/rss+xml") - .body(rss), - ) + Ok(get_feed_data(&context, ListingType::All, sort_type).await?) } -fn get_feed_all_data(conn: &PgConnection, sort_type: &SortType) -> Result { - let site_view = SiteView::read(&conn)?; +async fn get_local_feed( + info: web::Query, + context: web::Data, +) -> Result { + let sort_type = get_sort_type(info).map_err(ErrorBadRequest)?; + Ok(get_feed_data(&context, ListingType::Local, sort_type).await?) +} - let posts = PostQueryBuilder::create(&conn) - .listing_type(ListingType::All) - .sort(sort_type) - .list()?; +async fn get_feed_data( + context: &LemmyContext, + listing_type: ListingType, + sort_type: SortType, +) -> Result { + let site_view = blocking(context.pool(), move |conn| SiteView::read(&conn)).await??; + + let listing_type_ = listing_type.clone(); + let posts = blocking(context.pool(), move |conn| { + PostQueryBuilder::create(&conn) + .listing_type(&listing_type_) + .sort(&sort_type) + .list() + }) + .await??; let items = create_post_items(posts)?; let mut channel_builder = ChannelBuilder::default(); channel_builder .namespaces(RSS_NAMESPACE.to_owned()) - .title(&format!("{} - All", site_view.name)) + .title(&format!( + "{} - {}", + site_view.name, + listing_type.to_string() + )) .link(Settings::get().get_protocol_and_hostname()) .items(items); @@ -96,7 +106,12 @@ fn get_feed_all_data(conn: &PgConnection, sort_type: &SortType) -> Result