From ffda32302e4d8d5ae540c726c14b0d700bc19b38 Mon Sep 17 00:00:00 2001 From: Lea Nasarek Date: Wed, 5 Aug 2026 15:24:55 +0200 Subject: [PATCH 1/2] feat: add geo_filter preference removes the geo_filter regex from the request URL and instead adds a preference --- src/settings.rs | 15 ++++++++- src/subreddit.rs | 67 ++++++++++++++--------------------------- src/utils.rs | 12 +++++--- templates/settings.html | 6 ++++ 4 files changed, 51 insertions(+), 49 deletions(-) diff --git a/src/settings.rs b/src/settings.rs index 84cd41a5..4acfa0f7 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -24,7 +24,7 @@ struct SettingsTemplate { // CONSTANTS -const PREFS: [&str; 19] = [ +const PREFS: [&str; 20] = [ "theme", "front_page", "layout", @@ -44,6 +44,19 @@ const PREFS: [&str; 19] = [ "disable_visit_reddit_confirmation", "video_quality", "remove_default_feeds", + "geo_filter", +]; + +pub static GEO_FILTERS: [&'static str; 250] = [ + "GLOBAL", "AD", "AE", "AF", "AG", "AI", "AL", "AM", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", + "BN", "BO", "BQ", "BR", "BS", "BT", "BV", "BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CU", "CV", "CW", "CX", "CY", + "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", "GA", "GB", "GD", "GE", "GF", "GG", "GH", "GI", + "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT", "JE", + "JM", "JO", "JP", "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", + "ME", "MF", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG", "NI", "NL", "NO", + "NP", "NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY", "QA", "RE", "RO", "RS", "RU", "RW", "SA", "SB", "SC", + "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "SS", "ST", "SV", "SX", "SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", + "TO", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", "WS", "YE", "YT", "ZA", "ZM", "ZW", ]; // FUNCTIONS diff --git a/src/subreddit.rs b/src/subreddit.rs index 34877250..30ef3160 100644 --- a/src/subreddit.rs +++ b/src/subreddit.rs @@ -1,7 +1,8 @@ #![allow(clippy::cmp_owned)] use crate::utils::{ - Post, Preferences, Subreddit, catch_random, error, filter_posts, format_num, format_url, get_filters, info, nsfw_landing, param, redirect, rewrite_urls, setting, template, to_absolute_url, val + catch_random, error, filter_posts, format_num, format_url, get_filters, info, nsfw_landing, param, redirect, rewrite_urls, setting, template, to_absolute_url, val, Post, + Preferences, Subreddit, }; use crate::{client::json, server::RequestExt, server::ResponseExt}; use crate::{config, utils}; @@ -11,9 +12,7 @@ use htmlescape::decode_html; use hyper::{Body, Request, Response}; use chrono::DateTime; -use regex::Regex; -use rss::{ChannelBuilder, Item, Enclosure}; -use std::sync::LazyLock; +use rss::{ChannelBuilder, Enclosure, Item}; use time::{Duration, OffsetDateTime}; // STRUCTS @@ -57,13 +56,11 @@ struct WallTemplate { url: String, } -static GEO_FILTER_MATCH: LazyLock = LazyLock::new(|| Regex::new(r"geo_filter=(?\w+)").unwrap()); - // SERVICES pub async fn community(req: Request) -> Result, String> { + let prefs = Preferences::new(&req); // Build Reddit API path let root = req.uri().path() == "/"; - let query = req.uri().query().unwrap_or_default().to_string(); let subscribed = setting(&req, "subscriptions"); let front_page = setting(&req, "front_page"); let remove_default_feeds = setting(&req, "remove_default_feeds") == "on"; @@ -133,11 +130,7 @@ pub async fn community(req: Request) -> Result, String> { let mut params = String::from("&raw_json=1"); if sub_name == "popular" { - let geo_filter = match GEO_FILTER_MATCH.captures(&query) { - Some(geo_filter) => geo_filter["region"].to_string(), - None => "GLOBAL".to_owned(), - }; - params.push_str(&format!("&geo_filter={geo_filter}")); + params.push_str(&format!("&geo_filter={}", prefs.geo_filter)); } let path = format!("/r/{}/{sort}.json?{}{params}", sub_name.replace('+', "%2B"), req.uri().query().unwrap_or_default()); @@ -152,7 +145,7 @@ pub async fn community(req: Request) -> Result, String> { posts: Vec::new(), sort: (sort, param(&path, "t").unwrap_or_default()), ends: (param(&path, "after").unwrap_or_default(), String::new()), - prefs: Preferences::new(&req), + prefs, url, redirect_url, is_filtered: true, @@ -655,23 +648,13 @@ fn apply_enclosure(item: &mut Item, post: &Post) { // Embed the number of gallery images in description and content since // only the first image in the gallery is used for the enclosure if post.post_type == "gallery" && post.gallery.len() > 1 { - item.set_description( - format!("Gallery with {} images", - to_absolute_url(&post.permalink), - post.gallery.len() - ) - ); + item.set_description(format!("Gallery with {} images", to_absolute_url(&post.permalink), post.gallery.len())); if let Some(content) = item.content() { - let new_content = format!( - "{}
{}", - item.description().unwrap_or(""), - content, - ); + let new_content = format!("{}
{}", item.description().unwrap_or(""), content,); item.set_content(new_content); } } - } fn get_rss_image(post: &Post) -> Option { @@ -694,25 +677,21 @@ fn get_rss_image(post: &Post) -> Option { /// Determines the MIME type based on file extension in a URL. /// Handles both absolute and relative URLs with query parameters. fn get_mime_type(url: &str) -> &'static str { - // Extract the path component, removing query parameters - let path = url.split('?').next().unwrap_or(url); - - // Get the file extension (everything after the last dot) - let extension = path - .rsplit('.') - .next() - .unwrap_or("") - .to_lowercase(); - - // Match common image extensions - match extension.as_str() { - "jpg" | "jpeg" => "image/jpeg", - "png" => "image/png", - "gif" => "image/gif", - "webp" => "image/webp", - "svg" => "image/svg+xml", - _ => "application/octet-stream", - } + // Extract the path component, removing query parameters + let path = url.split('?').next().unwrap_or(url); + + // Get the file extension (everything after the last dot) + let extension = path.rsplit('.').next().unwrap_or("").to_lowercase(); + + // Match common image extensions + match extension.as_str() { + "jpg" | "jpeg" => "image/jpeg", + "png" => "image/png", + "gif" => "image/gif", + "webp" => "image/webp", + "svg" => "image/svg+xml", + _ => "application/octet-stream", + } } #[cfg(test)] diff --git a/src/utils.rs b/src/utils.rs index 36b798f4..077d07ab 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -667,6 +667,8 @@ pub struct Preferences { pub hide_score: String, #[revision(start = 1)] pub remove_default_feeds: String, + #[revision(start = 1)] + pub geo_filter: String, } fn serialize_vec_with_plus(vec: &[String], serializer: S) -> Result @@ -725,6 +727,7 @@ impl Preferences { hide_awards: setting(req, "hide_awards"), hide_score: setting(req, "hide_score"), remove_default_feeds: setting(req, "remove_default_feeds"), + geo_filter: setting(req, "geo_filter"), } } @@ -1543,10 +1546,11 @@ mod tests { hide_awards: "off".to_owned(), hide_score: "off".to_owned(), remove_default_feeds: "off".to_owned(), + geo_filter: "GLOBAL".to_owned(), }; let urlencoded = serde_urlencoded::to_string(prefs).expect("Failed to serialize Prefs"); - assert_eq!(urlencoded, "theme=laserwave&front_page=default&layout=compact&wide=on&blur_spoiler=on&show_nsfw=off&blur_nsfw=on&hide_hls_notification=off&video_quality=best&hide_sidebar_and_summary=off&use_hls=on&autoplay_videos=on&fixed_navbar=on&disable_visit_reddit_confirmation=on&comment_sort=confidence&post_sort=top&subscriptions=memes%2Bmildlyinteresting&filters=&hide_awards=off&hide_score=off&remove_default_feeds=off"); + assert_eq!(urlencoded, "theme=laserwave&front_page=default&layout=compact&wide=on&blur_spoiler=on&show_nsfw=off&blur_nsfw=on&hide_hls_notification=off&video_quality=best&hide_sidebar_and_summary=off&use_hls=on&autoplay_videos=on&fixed_navbar=on&disable_visit_reddit_confirmation=on&comment_sort=confidence&post_sort=top&subscriptions=memes%2Bmildlyinteresting&filters=&hide_awards=off&hide_score=off&remove_default_feeds=off&geo_filter=GLOBAL"); } #[test] @@ -1655,9 +1659,9 @@ How`s your monitor by the way? Any IPS bleed whatsoever? I either got lucky or t } static KNOWN_GOOD_CONFIGS: &[&str] = &[ - "ఴӅβØØҞÉဏႢձĬ༧ȒʯऌԔӵ୮༏", - "ਧՊΥÀÃǎƱГ۸ඣമĖฤ႙ʟาúໜϾௐɥঀĜໃહཞઠѫҲɂఙ࿔DzઉƲӟӻĻฅΜδ໖ԜǗဖငƦơ৶Ą௩ԹʛใЛʃශаΏ", - "ਧԩΥÀÃΊ౭൩ඔႠϼҭöҪƸռઇԾॐნɔາǒՍҰच௨ಖມŃЉŐདƦ๙ϩএఠȝഽйʮჯඒϰळՋ௮ສ৵ऎΦѧਹಧଟƙŃ३î༦ŌပղयƟแҜ།", + "ఴǐΪØÃҤÉఅഐႮვÆվƟ๑ഈ௲º", + "ਧճΥÀÃǙŨ౭ѰЉਠ༃ඍୟϊÓႼઞƶDzѾҠŶဿৠǡȈЧတĄঘशƕİԪӥОϥΪѼĔજɍႰůƅıęႵຈഛशખӺफƊўચபūগລનаΦǮʀԅཪ٦ಟซωॶԓԙµ", + "ਧՎΥºÃǖবб྾цҗҢจഘĦਝ೨ծമ۞তʦཤཎຟՐȸ൯ങஏ९ȹ૯нե࿑Ʋථఐ۳ԊຍखʟషၡŁलſԇચਆॹǕϻΪজԯǐĦЅթȣơϱǃඛϾຝϤ໐Քµ", ]; #[test] diff --git a/templates/settings.html b/templates/settings.html index c3d8086b..fd28dc1c 100644 --- a/templates/settings.html +++ b/templates/settings.html @@ -49,6 +49,12 @@ +
+ + +
Content From 8633f476b07b7762d50e1b09950461df730fe461 Mon Sep 17 00:00:00 2001 From: Lea Nasarek Date: Wed, 2 Sep 2026 15:00:05 +0200 Subject: [PATCH 2/2] feat(geo_filter): add env variable --- .env.example | 2 ++ app.json | 3 +++ src/config.rs | 5 +++++ src/instance_info.rs | 5 ++++- src/utils.rs | 2 +- templates/settings.html | 2 +- 6 files changed, 16 insertions(+), 3 deletions(-) diff --git a/.env.example b/.env.example index 5e60b082..e8167146 100644 --- a/.env.example +++ b/.env.example @@ -50,3 +50,5 @@ REDLIB_DEFAULT_DISABLE_VISIT_REDDIT_CONFIRMATION=off REDLIB_DEFAULT_HIDE_SCORE=off # Enable fixed navbar by default REDLIB_DEFAULT_FIXED_NAVBAR=on +# Set the default geo filter +REDLIB_DEFAULT_GEO_FILTER=GLOBAL diff --git a/app.json b/app.json index 4af7cfec..e5fe2918 100644 --- a/app.json +++ b/app.json @@ -79,6 +79,9 @@ }, "REDLIB_DEFAULT_REMOVE_DEFAULT_FEEDS": { "required": false + }, + "REDLIB_DEFAULT_GEO_FILTER": { + "required": false } } } diff --git a/src/config.rs b/src/config.rs index 8f92c9b7..24d5b014 100644 --- a/src/config.rs +++ b/src/config.rs @@ -108,6 +108,9 @@ pub struct Config { #[serde(rename = "REDLIB_DEFAULT_REMOVE_DEFAULT_FEEDS")] pub(crate) default_remove_default_feeds: Option, + + #[serde(rename = "REDLIB_DEFAULT_GEO_FILTER")] + pub(crate) default_geo_filter: Option, } impl Config { @@ -156,6 +159,7 @@ impl Config { enable_rss: parse("REDLIB_ENABLE_RSS"), full_url: parse("REDLIB_FULL_URL"), default_remove_default_feeds: parse("REDLIB_DEFAULT_REMOVE_DEFAULT_FEEDS"), + default_geo_filter: parse("REDLIB_DEFAULT_GEO_FILTER"), } } } @@ -186,6 +190,7 @@ fn get_setting_from_config(name: &str, config: &Config) -> Option { "REDLIB_ENABLE_RSS" => config.enable_rss.clone(), "REDLIB_FULL_URL" => config.full_url.clone(), "REDLIB_DEFAULT_REMOVE_DEFAULT_FEEDS" => config.default_remove_default_feeds.clone(), + "REDLIB_DEFAULT_GEO_FILTER" => config.default_geo_filter.clone(), _ => None, } } diff --git a/src/instance_info.rs b/src/instance_info.rs index 8fc46a6a..09a66868 100644 --- a/src/instance_info.rs +++ b/src/instance_info.rs @@ -151,6 +151,7 @@ impl InstanceInfo { ["Hide HLS notification", &convert(&self.config.default_hide_hls_notification)], ["Subscriptions", &convert(&self.config.default_subscriptions)], ["Filters", &convert(&self.config.default_filters)], + ["Geo filter", &convert(&self.config.default_geo_filter)], ]) .with_header_row(["Default preferences"]), ); @@ -187,7 +188,8 @@ impl InstanceInfo { Default use HLS: {:?}\n Default hide HLS notification: {:?}\n Default subscriptions: {:?}\n - Default filters: {:?}\n", + Default filters: {:?}\n, + Default geo filter: {:?}\n", self.package_name, self.crate_version, self.git_commit, @@ -215,6 +217,7 @@ impl InstanceInfo { self.config.default_hide_hls_notification, self.config.default_subscriptions, self.config.default_filters, + self.config.default_geo_filter, ) } StringType::Html => self.to_table(), diff --git a/src/utils.rs b/src/utils.rs index 077d07ab..f2b649d2 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -727,7 +727,7 @@ impl Preferences { hide_awards: setting(req, "hide_awards"), hide_score: setting(req, "hide_score"), remove_default_feeds: setting(req, "remove_default_feeds"), - geo_filter: setting(req, "geo_filter"), + geo_filter: setting_or_default(req, "geo_filter", "GLOBAL".to_string()), } } diff --git a/templates/settings.html b/templates/settings.html index fd28dc1c..181b04a5 100644 --- a/templates/settings.html +++ b/templates/settings.html @@ -52,7 +52,7 @@