From 8906b66cb316d4f42a96a16871087eabeed1fffb Mon Sep 17 00:00:00 2001 From: Matt Date: Fri, 21 Oct 2022 20:21:20 -0400 Subject: [PATCH] (#23) Implement FERRIT_SFW_ONLY (#24) --- src/duplicates.rs | 9 ++++----- src/post.rs | 5 +++-- src/search.rs | 9 +++++++-- src/subreddit.rs | 4 ++-- src/user.rs | 5 +++-- src/utils.rs | 8 ++++++++ templates/base.html | 2 +- templates/nsfwlanding.html | 4 ++++ templates/settings.html | 6 ++++++ 9 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/duplicates.rs b/src/duplicates.rs index 12bce84..d68d1b3 100644 --- a/src/duplicates.rs +++ b/src/duplicates.rs @@ -68,8 +68,9 @@ pub async fn item(req: Request) -> Result, String> { let post = parse_post(&response[0]["data"]["children"][0]).await; // Return landing page if this post if this Reddit deems this post - // NSFW, but we have also disabled the display of NSFW content. - if setting(&req, "show_nsfw") != "on" && post.nsfw { + // NSFW, but we have also disabled the display of NSFW content + // or if the instance is SFW-only. + if post.nsfw && (setting(&req, "show_nsfw") != "on" || crate::utils::sfw_only()) { return Ok(nsfw_landing(req).await.unwrap_or_default()); } @@ -125,9 +126,7 @@ pub async fn item(req: Request) -> Result, String> { let query_str = req.uri().query().unwrap_or_default().to_string(); if !query_str.is_empty() { - let query: Vec<&str> = query_str.split('&').collect::>(); - - for param in query.into_iter() { + for param in query_str.split('&') { let kv: Vec<&str> = param.split('=').collect(); if kv.len() < 2 { // Reject invalid query parameter. diff --git a/src/post.rs b/src/post.rs index 4a38f4b..2f00dd1 100644 --- a/src/post.rs +++ b/src/post.rs @@ -57,8 +57,9 @@ pub async fn item(req: Request) -> Result, String> { let post = parse_post(&response[0]["data"]["children"][0]).await; // Return landing page if this post if this Reddit deems this post - // NSFW, but we have also disabled the display of NSFW content. - if setting(&req, "show_nsfw") != "on" && post.nsfw { + // NSFW, but we have also disabled the display of NSFW content + // or if the instance is SFW-only. + if post.nsfw && (setting(&req, "show_nsfw") != "on" || crate::utils::sfw_only()) { return Ok(nsfw_landing(req).await.unwrap_or_default()); } diff --git a/src/search.rs b/src/search.rs index 0a62b06..03e0d3d 100644 --- a/src/search.rs +++ b/src/search.rs @@ -1,5 +1,5 @@ // CRATES -use crate::utils::{catch_random, error, filter_posts, format_num, format_url, get_filters, param, redirect, setting, template, val, Post, Preferences}; +use crate::utils::{self, catch_random, error, filter_posts, format_num, format_url, get_filters, param, redirect, setting, template, val, Post, Preferences}; use crate::{ client::json, subreddit::{can_access_quarantine, quarantine}, @@ -48,7 +48,12 @@ struct SearchTemplate { // SERVICES pub async fn find(req: Request) -> Result, String> { - let nsfw_results = if setting(&req, "show_nsfw") == "on" { "&include_over_18=on" } else { "" }; + // This ensures that during a search, no NSFW posts are fetched at all + let nsfw_results = if setting(&req, "show_nsfw") == "on" && !utils::sfw_only() { + "&include_over_18=on" + } else { + "" + }; let path = format!("{}.json?{}{}&raw_json=1", req.uri().path(), req.uri().query().unwrap_or_default(), nsfw_results); let query = param(&path, "q").unwrap_or_default(); diff --git a/src/subreddit.rs b/src/subreddit.rs index 242a508..750bb1e 100644 --- a/src/subreddit.rs +++ b/src/subreddit.rs @@ -97,8 +97,8 @@ pub async fn community(req: Request) -> Result, String> { }; // Return landing page if this post if this is NSFW community but the user - // has disabled the display of NSFW content. - if setting(&req, "show_nsfw") != "on" && sub.nsfw { + // has disabled the display of NSFW content or if the instance is SFW-only. + if sub.nsfw && (setting(&req, "show_nsfw") != "on" || crate::utils::sfw_only()) { return Ok(nsfw_landing(req).await.unwrap_or_default()); } diff --git a/src/user.rs b/src/user.rs index 2872984..2d7eef6 100644 --- a/src/user.rs +++ b/src/user.rs @@ -50,8 +50,9 @@ pub async fn profile(req: Request) -> Result, String> { let user = user(&username).await.unwrap_or_default(); // Return landing page if this post if this Reddit deems this user NSFW, - // but we have also disabled the display of NSFW content. - if setting(&req, "show_nsfw") != "on" && user.nsfw { + // but we have also disabled the display of NSFW content or if the instance + // is SFW-only. + if user.nsfw && (setting(&req, "show_nsfw") != "on" || crate::utils::sfw_only()) { return Ok(nsfw_landing(req).await.unwrap_or_default()); } diff --git a/src/utils.rs b/src/utils.rs index 60af11b..ab3ed0d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -9,6 +9,7 @@ use regex::Regex; use rust_embed::RustEmbed; use serde_json::Value; use std::collections::{HashMap, HashSet}; +use std::env; use std::str::FromStr; use time::{macros::format_description, Duration, OffsetDateTime}; use url::Url; @@ -849,6 +850,13 @@ pub async fn error(req: Request, msg: String) -> Result, St Ok(Response::builder().status(404).header("content-type", "text/html").body(body.into()).unwrap_or_default()) } +/// Set the FERRIT_SFW_ONLY environment variable to anything, to enable SFW-only mode. +/// If environment variable is set, this bool will be true. Otherwise it will be false. +/// This variable is set by the instance operator, and as such, side-steps the user config +pub fn sfw_only() -> bool { + env::var("FERRIT_SFW_ONLY").is_ok() +} + /// Render the landing page for NSFW content when the user has not enabled /// "show NSFW posts" in settings. pub async fn nsfw_landing(req: Request) -> Result, String> { diff --git a/templates/base.html b/templates/base.html index b5bb01b..bd8273d 100644 --- a/templates/base.html +++ b/templates/base.html @@ -30,7 +30,7 @@