From e046144bf3ddcad50e498d7ca530f81736baf64a Mon Sep 17 00:00:00 2001 From: gmnsii Date: Wed, 22 Mar 2023 23:18:35 -0700 Subject: [PATCH 1/3] Allow bypassing nsfw gate for posts On instances that are not sfw-only, the nsfw gate for posts can now be bypassed. --- src/duplicates.rs | 13 +++++++------ src/post.rs | 9 +++++---- src/subreddit.rs | 6 ++++-- src/user.rs | 5 +++-- src/utils.rs | 16 +++++++++++++--- templates/nsfwlanding.html | 4 +++- 6 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/duplicates.rs b/src/duplicates.rs index d747d46..6810367 100644 --- a/src/duplicates.rs +++ b/src/duplicates.rs @@ -3,7 +3,7 @@ use crate::client::json; use crate::server::RequestExt; use crate::subreddit::{can_access_quarantine, quarantine}; -use crate::utils::{error, filter_posts, get_filters, nsfw_landing, parse_post, setting, template, Post, Preferences}; +use crate::utils::{error, filter_posts, get_filters, nsfw_landing, parse_post, template, Post, Preferences}; use askama::Template; use hyper::{Body, Request, Response}; @@ -67,11 +67,12 @@ pub async fn item(req: Request) -> Result, String> { Ok(response) => { let post = parse_post(&response[0]["data"]["children"][0]).await; + let req_url = req.uri().to_string(); // Return landing page if this post if this Reddit deems this post // 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()); + // or if the instance is SFW-only + if post.nsfw && crate::utils::should_be_nsfw_gated(&req, &req_url) { + return Ok(nsfw_landing(req, req_url).await.unwrap_or_default()); } let filters = get_filters(&req); @@ -195,14 +196,13 @@ pub async fn item(req: Request) -> Result, String> { after = response[1]["data"]["after"].as_str().unwrap_or_default().to_string(); } } - let url = req.uri().to_string(); template(DuplicatesTemplate { params: DuplicatesParams { before, after, sort }, post, duplicates, prefs: Preferences::new(&req), - url, + url: req_url, num_posts_filtered, all_posts_filtered, }) @@ -234,3 +234,4 @@ async fn parse_duplicates(json: &serde_json::Value, filters: &HashSet) - let (num_posts_filtered, all_posts_filtered) = filter_posts(&mut duplicates, filters); (duplicates, num_posts_filtered, all_posts_filtered) } + diff --git a/src/post.rs b/src/post.rs index f2f5eaf..3cdf171 100644 --- a/src/post.rs +++ b/src/post.rs @@ -56,15 +56,15 @@ pub async fn item(req: Request) -> Result, String> { // Parse the JSON into Post and Comment structs let post = parse_post(&response[0]["data"]["children"][0]).await; + let req_url = req.uri().to_string(); // Return landing page if this post if this Reddit deems this post // 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()); + if post.nsfw && crate::utils::should_be_nsfw_gated(&req, &req_url) { + return Ok(nsfw_landing(req, req_url).await.unwrap_or_default()); } let comments = parse_comments(&response[1], &post.permalink, &post.author.name, highlighted_comment, &get_filters(&req), &req); - let url = req.uri().to_string(); // Use the Post and Comment structs to generate a website to show users template(PostTemplate { @@ -73,7 +73,7 @@ pub async fn item(req: Request) -> Result, String> { sort, prefs: Preferences::new(&req), single_thread, - url, + url: req_url, }) } // If the Reddit API returns an error, exit and send error page to user @@ -190,3 +190,4 @@ fn parse_comments(json: &serde_json::Value, post_link: &str, post_author: &str, }) .collect() } + diff --git a/src/subreddit.rs b/src/subreddit.rs index e253885..59382c6 100644 --- a/src/subreddit.rs +++ b/src/subreddit.rs @@ -97,10 +97,11 @@ pub async fn community(req: Request) -> Result, String> { } }; + let req_url = req.uri().to_string(); // Return landing page if this post if this is NSFW community but the user // 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()); + if sub.nsfw && crate::utils::should_be_nsfw_gated(&req, &req_url) { + return Ok(nsfw_landing(req, req_url).await.unwrap_or_default()); } let path = format!("/r/{}/{}.json?{}&raw_json=1", sub_name.clone(), sort, req.uri().query().unwrap_or_default()); @@ -433,3 +434,4 @@ async fn subreddit(sub: &str, quarantined: bool) -> Result { nsfw: res["data"]["over18"].as_bool().unwrap_or_default(), }) } + diff --git a/src/user.rs b/src/user.rs index 53f4090..9c1b166 100644 --- a/src/user.rs +++ b/src/user.rs @@ -50,11 +50,12 @@ pub async fn profile(req: Request) -> Result, String> { // Retrieve info from user about page. let user = user(&username).await.unwrap_or_default(); + let req_url = req.uri().to_string(); // Return landing page if this post if this Reddit deems this 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()); + if user.nsfw && crate::utils::should_be_nsfw_gated(&req, &req_url) { + return Ok(nsfw_landing(req, req_url).await.unwrap_or_default()); } let filters = get_filters(&req); diff --git a/src/utils.rs b/src/utils.rs index e6cb2f7..9d68dc7 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -893,11 +893,21 @@ pub fn sfw_only() -> bool { } } +// Determines if a request shoud redirect to a nsfw landing gate. +pub fn should_be_nsfw_gated(req: &Request, req_url: &String) -> bool { + let sfw_instance = sfw_only(); + let gate_nsfw = (setting(&req, "show_nsfw") != "on") || sfw_instance; + + // Nsfw landing gate should not be bypassed on a sfw only instance, + let bypass_gate = !sfw_instance && req_url.ends_with("&bypass_nsfw_landing"); + + gate_nsfw && !bypass_gate +} + /// Renders 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> { +pub async fn nsfw_landing(req: Request, req_url: String) -> Result, String> { let res_type: ResourceType; - let url = req.uri().to_string(); // Determine from the request URL if the resource is a subreddit, a user // page, or a post. @@ -916,7 +926,7 @@ pub async fn nsfw_landing(req: Request) -> Result, String> res, res_type, prefs: Preferences::new(&req), - url, + url: req_url, } .render() .unwrap_or_default(); diff --git a/templates/nsfwlanding.html b/templates/nsfwlanding.html index f6287a3..b499389 100644 --- a/templates/nsfwlanding.html +++ b/templates/nsfwlanding.html @@ -19,10 +19,12 @@ {% if crate::utils::sfw_only() %} This instance of Libreddit is SFW-only.

{% else %} - Enable "Show NSFW posts" in settings 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 %}. + Enable "Show NSFW posts" in settings 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 %}.
+ {% if res_type == crate::utils::ResourceType::Post %} You can also bypass this gate by clicking on this link.{% endif %} {% endif %}

{% endblock %} {% block footer %} {% endblock %} + From a0726c5903266be4ec3bba54db982d32bf2db27a Mon Sep 17 00:00:00 2001 From: gmnsii Date: Thu, 23 Mar 2023 11:09:33 -0700 Subject: [PATCH 2/3] Change the bypass message and format code The bypass message now indicates that the bypass is only temporary. --- build.rs | 4 +--- src/duplicates.rs | 5 ++--- src/post.rs | 3 +-- src/subreddit.rs | 3 +-- src/user.rs | 2 +- src/utils.rs | 10 +++++----- templates/nsfwlanding.html | 2 +- 7 files changed, 12 insertions(+), 17 deletions(-) diff --git a/build.rs b/build.rs index 3ee44a4..26b1ed9 100644 --- a/build.rs +++ b/build.rs @@ -1,6 +1,4 @@ -use std::{ - process::{Command, ExitStatus, Output}, -}; +use std::process::{Command, ExitStatus, Output}; #[cfg(not(target_os = "windows"))] use std::os::unix::process::ExitStatusExt; diff --git a/src/duplicates.rs b/src/duplicates.rs index 6810367..b099acf 100644 --- a/src/duplicates.rs +++ b/src/duplicates.rs @@ -67,12 +67,12 @@ pub async fn item(req: Request) -> Result, String> { Ok(response) => { let post = parse_post(&response[0]["data"]["children"][0]).await; - let req_url = req.uri().to_string(); + let req_url = req.uri().to_string(); // Return landing page if this post if this Reddit deems this post // NSFW, but we have also disabled the display of NSFW content // or if the instance is SFW-only if post.nsfw && crate::utils::should_be_nsfw_gated(&req, &req_url) { - return Ok(nsfw_landing(req, req_url).await.unwrap_or_default()); + return Ok(nsfw_landing(req, req_url).await.unwrap_or_default()); } let filters = get_filters(&req); @@ -234,4 +234,3 @@ async fn parse_duplicates(json: &serde_json::Value, filters: &HashSet) - let (num_posts_filtered, all_posts_filtered) = filter_posts(&mut duplicates, filters); (duplicates, num_posts_filtered, all_posts_filtered) } - diff --git a/src/post.rs b/src/post.rs index 3cdf171..8644284 100644 --- a/src/post.rs +++ b/src/post.rs @@ -56,7 +56,7 @@ pub async fn item(req: Request) -> Result, String> { // Parse the JSON into Post and Comment structs let post = parse_post(&response[0]["data"]["children"][0]).await; - let req_url = req.uri().to_string(); + let req_url = req.uri().to_string(); // Return landing page if this post if this Reddit deems this post // NSFW, but we have also disabled the display of NSFW content // or if the instance is SFW-only. @@ -190,4 +190,3 @@ fn parse_comments(json: &serde_json::Value, post_link: &str, post_author: &str, }) .collect() } - diff --git a/src/subreddit.rs b/src/subreddit.rs index 59382c6..ee57ea5 100644 --- a/src/subreddit.rs +++ b/src/subreddit.rs @@ -97,7 +97,7 @@ pub async fn community(req: Request) -> Result, String> { } }; - let req_url = req.uri().to_string(); + let req_url = req.uri().to_string(); // Return landing page if this post if this is NSFW community but the user // has disabled the display of NSFW content or if the instance is SFW-only. if sub.nsfw && crate::utils::should_be_nsfw_gated(&req, &req_url) { @@ -434,4 +434,3 @@ async fn subreddit(sub: &str, quarantined: bool) -> Result { nsfw: res["data"]["over18"].as_bool().unwrap_or_default(), }) } - diff --git a/src/user.rs b/src/user.rs index 9c1b166..efa70a9 100644 --- a/src/user.rs +++ b/src/user.rs @@ -50,7 +50,7 @@ pub async fn profile(req: Request) -> Result, String> { // Retrieve info from user about page. let user = user(&username).await.unwrap_or_default(); - let req_url = req.uri().to_string(); + let req_url = req.uri().to_string(); // Return landing page if this post if this Reddit deems this user NSFW, // but we have also disabled the display of NSFW content or if the instance // is SFW-only. diff --git a/src/utils.rs b/src/utils.rs index 9d68dc7..3290eab 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -895,13 +895,13 @@ pub fn sfw_only() -> bool { // Determines if a request shoud redirect to a nsfw landing gate. pub fn should_be_nsfw_gated(req: &Request, req_url: &String) -> bool { - let sfw_instance = sfw_only(); - let gate_nsfw = (setting(&req, "show_nsfw") != "on") || sfw_instance; + let sfw_instance = sfw_only(); + let gate_nsfw = (setting(&req, "show_nsfw") != "on") || sfw_instance; - // Nsfw landing gate should not be bypassed on a sfw only instance, - let bypass_gate = !sfw_instance && req_url.ends_with("&bypass_nsfw_landing"); + // Nsfw landing gate should not be bypassed on a sfw only instance, + let bypass_gate = !sfw_instance && req_url.ends_with("&bypass_nsfw_landing"); - gate_nsfw && !bypass_gate + gate_nsfw && !bypass_gate } /// Renders the landing page for NSFW content when the user has not enabled diff --git a/templates/nsfwlanding.html b/templates/nsfwlanding.html index b499389..4dc8c86 100644 --- a/templates/nsfwlanding.html +++ b/templates/nsfwlanding.html @@ -20,7 +20,7 @@ This instance of Libreddit is SFW-only.

{% else %} Enable "Show NSFW posts" in settings 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 %}.
- {% if res_type == crate::utils::ResourceType::Post %} You can also bypass this gate by clicking on this link.{% endif %} + {% if res_type == crate::utils::ResourceType::Post %} You can also temporarily bypass this gate and view the post by clicking on this link.{% endif %} {% endif %}

From 8be69f6fe5a99acdec053eef9871a3d1a2f035ce Mon Sep 17 00:00:00 2001 From: gmnsii Date: Thu, 23 Mar 2023 12:36:04 -0700 Subject: [PATCH 3/3] Checks if the link contains the parameter instead of ends with it To know if the gate should be bypassed, we check if the link contains the pasameter instead of checking if the link ends with it. This is impostant, for example if we were to implement searching for comments within a post. If we wanted to search for comments within a post that we have bypassed the gate to view: the link will look like https://libreddit-instance/r/somesub/comments/post-id/post-title&bypass_nsfw_landing/?q=some-query&type=comment --- src/utils.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.rs b/src/utils.rs index 3290eab..172bf4d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -899,7 +899,7 @@ pub fn should_be_nsfw_gated(req: &Request, req_url: &String) -> bool { let gate_nsfw = (setting(&req, "show_nsfw") != "on") || sfw_instance; // Nsfw landing gate should not be bypassed on a sfw only instance, - let bypass_gate = !sfw_instance && req_url.ends_with("&bypass_nsfw_landing"); + let bypass_gate = !sfw_instance && req_url.contains("&bypass_nsfw_landing"); gate_nsfw && !bypass_gate }