(#23) Implement FERRIT_SFW_ONLY (#24)

This commit is contained in:
Matt 2022-10-21 20:21:20 -04:00 committed by GitHub
parent 4afd963c64
commit 8906b66cb3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 38 additions and 14 deletions

View File

@ -68,8 +68,9 @@ pub async fn item(req: Request<Body>) -> Result<Response<Body>, String> {
let post = parse_post(&response[0]["data"]["children"][0]).await; let post = parse_post(&response[0]["data"]["children"][0]).await;
// Return landing page if this post if this Reddit deems this post // Return landing page if this post if this Reddit deems this post
// NSFW, but we have also disabled the display of NSFW content. // NSFW, but we have also disabled the display of NSFW content
if setting(&req, "show_nsfw") != "on" && post.nsfw { // 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()); return Ok(nsfw_landing(req).await.unwrap_or_default());
} }
@ -125,9 +126,7 @@ pub async fn item(req: Request<Body>) -> Result<Response<Body>, String> {
let query_str = req.uri().query().unwrap_or_default().to_string(); let query_str = req.uri().query().unwrap_or_default().to_string();
if !query_str.is_empty() { if !query_str.is_empty() {
let query: Vec<&str> = query_str.split('&').collect::<Vec<&str>>(); for param in query_str.split('&') {
for param in query.into_iter() {
let kv: Vec<&str> = param.split('=').collect(); let kv: Vec<&str> = param.split('=').collect();
if kv.len() < 2 { if kv.len() < 2 {
// Reject invalid query parameter. // Reject invalid query parameter.

View File

@ -57,8 +57,9 @@ pub async fn item(req: Request<Body>) -> Result<Response<Body>, String> {
let post = parse_post(&response[0]["data"]["children"][0]).await; let post = parse_post(&response[0]["data"]["children"][0]).await;
// Return landing page if this post if this Reddit deems this post // Return landing page if this post if this Reddit deems this post
// NSFW, but we have also disabled the display of NSFW content. // NSFW, but we have also disabled the display of NSFW content
if setting(&req, "show_nsfw") != "on" && post.nsfw { // 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()); return Ok(nsfw_landing(req).await.unwrap_or_default());
} }

View File

@ -1,5 +1,5 @@
// CRATES // 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::{ use crate::{
client::json, client::json,
subreddit::{can_access_quarantine, quarantine}, subreddit::{can_access_quarantine, quarantine},
@ -48,7 +48,12 @@ struct SearchTemplate {
// SERVICES // SERVICES
pub async fn find(req: Request<Body>) -> Result<Response<Body>, String> { pub async fn find(req: Request<Body>) -> Result<Response<Body>, 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 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(); let query = param(&path, "q").unwrap_or_default();

View File

@ -97,8 +97,8 @@ pub async fn community(req: Request<Body>) -> Result<Response<Body>, String> {
}; };
// Return landing page if this post if this is NSFW community but the user // Return landing page if this post if this is NSFW community but the user
// has disabled the display of NSFW content. // has disabled the display of NSFW content or if the instance is SFW-only.
if setting(&req, "show_nsfw") != "on" && sub.nsfw { if sub.nsfw && (setting(&req, "show_nsfw") != "on" || crate::utils::sfw_only()) {
return Ok(nsfw_landing(req).await.unwrap_or_default()); return Ok(nsfw_landing(req).await.unwrap_or_default());
} }

View File

@ -50,8 +50,9 @@ pub async fn profile(req: Request<Body>) -> Result<Response<Body>, String> {
let user = user(&username).await.unwrap_or_default(); let user = user(&username).await.unwrap_or_default();
// Return landing page if this post if this Reddit deems this user NSFW, // Return landing page if this post if this Reddit deems this user NSFW,
// but we have also disabled the display of NSFW content. // but we have also disabled the display of NSFW content or if the instance
if setting(&req, "show_nsfw") != "on" && user.nsfw { // is SFW-only.
if user.nsfw && (setting(&req, "show_nsfw") != "on" || crate::utils::sfw_only()) {
return Ok(nsfw_landing(req).await.unwrap_or_default()); return Ok(nsfw_landing(req).await.unwrap_or_default());
} }

View File

@ -9,6 +9,7 @@ use regex::Regex;
use rust_embed::RustEmbed; use rust_embed::RustEmbed;
use serde_json::Value; use serde_json::Value;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::env;
use std::str::FromStr; use std::str::FromStr;
use time::{macros::format_description, Duration, OffsetDateTime}; use time::{macros::format_description, Duration, OffsetDateTime};
use url::Url; use url::Url;
@ -849,6 +850,13 @@ pub async fn error(req: Request<Body>, msg: String) -> Result<Response<Body>, St
Ok(Response::builder().status(404).header("content-type", "text/html").body(body.into()).unwrap_or_default()) 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 /// Render the landing page for NSFW content when the user has not enabled
/// "show NSFW posts" in settings. /// "show NSFW posts" in settings.
pub async fn nsfw_landing(req: Request<Body>) -> Result<Response<Body>, String> { pub async fn nsfw_landing(req: Request<Body>) -> Result<Response<Body>, String> {

View File

@ -30,7 +30,7 @@
<nav> <nav>
<div id="logo"> <div id="logo">
<a id="ferrit_logo" href="/"><span id="ferrit_logo_p1">ferr</span><span id="ferrit_logo_p2">it.</span></a> <a id="ferrit_logo" href="/"><span id="ferrit_logo_p1">ferr</span><span id="ferrit_logo_p2">it.</span></a>
<span id="version">v{{ env!("CARGO_PKG_VERSION") }}</span> <span id="version">v{{ env!("CARGO_PKG_VERSION") }}{% if crate::utils::sfw_only() %} <span title="This instance is SFW-only.">💼</span>{% endif %}</span>
{% block subscriptions %}{% endblock %} {% block subscriptions %}{% endblock %}
</div> </div>
{% block search %}{% endblock %} {% block search %}{% endblock %}

View File

@ -11,6 +11,10 @@
<h1>😱 This post is NSFW!</h1> <h1>😱 This post is NSFW!</h1>
{% endif %} {% endif %}
<br /> <br />
{% if crate::utils::sfw_only() %}
<p>This instance of Ferrit is SFW-only.</p>
{% else %}
<p>Enable "Show NSFW posts" in <a href="/settings">settings</a> to view this {% if res_type == crate::utils::ResourceType::Subreddit %}subreddit{% else if res_type == crate::utils::ResourceType::User %}user's posts or comments{% else if res_type == crate::utils::ResourceType::Post %}post{% endif %}.</p> <p>Enable "Show NSFW posts" in <a href="/settings">settings</a> to view this {% if res_type == crate::utils::ResourceType::Subreddit %}subreddit{% else if res_type == crate::utils::ResourceType::User %}user's posts or comments{% else if res_type == crate::utils::ResourceType::Post %}post{% endif %}.</p>
{% endif %}
</div> </div>
{% endblock %} {% endblock %}

View File

@ -49,6 +49,7 @@
{% call utils::options(prefs.comment_sort, ["confidence", "top", "new", "controversial", "old"], "confidence") %} {% call utils::options(prefs.comment_sort, ["confidence", "top", "new", "controversial", "old"], "confidence") %}
</select> </select>
</div> </div>
{% if !crate::utils::sfw_only() %}
<div id="show_nsfw"> <div id="show_nsfw">
<label for="show_nsfw">Show NSFW posts:</label> <label for="show_nsfw">Show NSFW posts:</label>
<input type="hidden" value="off" name="show_nsfw"> <input type="hidden" value="off" name="show_nsfw">
@ -59,6 +60,7 @@
<input type="hidden" value="off" name="blur_nsfw"> <input type="hidden" value="off" name="blur_nsfw">
<input type="checkbox" name="blur_nsfw" {% if prefs.blur_nsfw == "on" %}checked{% endif %}> <input type="checkbox" name="blur_nsfw" {% if prefs.blur_nsfw == "on" %}checked{% endif %}>
</div> </div>
{% endif %}
<div id="autoplay_videos"> <div id="autoplay_videos">
<label for="autoplay_videos">Autoplay videos</label> <label for="autoplay_videos">Autoplay videos</label>
<input type="hidden" value="off" name="autoplay_videos"> <input type="hidden" value="off" name="autoplay_videos">
@ -116,6 +118,10 @@
<div id="settings_note"> <div id="settings_note">
<p><b>Note:</b> settings and subscriptions are saved in browser cookies. Clearing your cookies will reset them.</p><br> <p><b>Note:</b> settings and subscriptions are saved in browser cookies. Clearing your cookies will reset them.</p><br>
<p>You can restore your current settings and subscriptions after clearing your cookies using <a href="/settings/restore/?theme={{ prefs.theme }}&front_page={{ prefs.front_page }}&layout={{ prefs.layout }}&wide={{ prefs.wide }}&post_sort={{ prefs.post_sort }}&comment_sort={{ prefs.comment_sort }}&show_nsfw={{ prefs.show_nsfw }}&blur_nsfw={{ prefs.blur_nsfw }}&use_hls={{ prefs.use_hls }}&hide_hls_notification={{ prefs.hide_hls_notification }}&subscriptions={{ prefs.subscriptions.join("%2B") }}&filters={{ prefs.filters.join("%2B") }}">this link</a>.</p> <p>You can restore your current settings and subscriptions after clearing your cookies using <a href="/settings/restore/?theme={{ prefs.theme }}&front_page={{ prefs.front_page }}&layout={{ prefs.layout }}&wide={{ prefs.wide }}&post_sort={{ prefs.post_sort }}&comment_sort={{ prefs.comment_sort }}&show_nsfw={{ prefs.show_nsfw }}&blur_nsfw={{ prefs.blur_nsfw }}&use_hls={{ prefs.use_hls }}&hide_hls_notification={{ prefs.hide_hls_notification }}&subscriptions={{ prefs.subscriptions.join("%2B") }}&filters={{ prefs.filters.join("%2B") }}">this link</a>.</p>
<br />
{% if crate::utils::sfw_only() %}
<p>This instance is SFW-only. It will block all NSFW content.</p>
{% endif %}
</div> </div>
</div> </div>