mirror of https://github.com/spikecodes/libreddit
parent
e60b913452
commit
a19f46ad18
|
@ -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, parse_post, template, Post, Preferences};
|
||||
use crate::utils::{error, filter_posts, get_filters, nsfw_landing, parse_post, setting, template, Post, Preferences};
|
||||
|
||||
use askama::Template;
|
||||
use hyper::{Body, Request, Response};
|
||||
|
@ -65,8 +65,15 @@ pub async fn item(req: Request<Body>) -> Result<Response<Body>, String> {
|
|||
match json(path, quarantined).await {
|
||||
// Process response JSON.
|
||||
Ok(response) => {
|
||||
let filters = get_filters(&req);
|
||||
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 {
|
||||
return Ok(nsfw_landing(req).await.unwrap_or_default());
|
||||
}
|
||||
|
||||
let filters = get_filters(&req);
|
||||
let (duplicates, num_posts_filtered, all_posts_filtered) = parse_duplicates(&response[1], &filters).await;
|
||||
|
||||
// These are the values for the "before=", "after=", and "sort="
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::client::json;
|
|||
use crate::server::RequestExt;
|
||||
use crate::subreddit::{can_access_quarantine, quarantine};
|
||||
use crate::utils::{
|
||||
error, format_num, get_filters, param, parse_post, rewrite_urls, setting, template, time, val, Author, Awards, Comment, Flair, FlairPart, Post, Preferences,
|
||||
error, format_num, get_filters, nsfw_landing, param, parse_post, rewrite_urls, setting, template, time, val, Author, Awards, Comment, Flair, FlairPart, Post, Preferences,
|
||||
};
|
||||
use hyper::{Body, Request, Response};
|
||||
|
||||
|
@ -55,6 +55,13 @@ pub async fn item(req: Request<Body>) -> Result<Response<Body>, String> {
|
|||
Ok(response) => {
|
||||
// Parse the JSON into Post and Comment structs
|
||||
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 {
|
||||
return Ok(nsfw_landing(req).await.unwrap_or_default());
|
||||
}
|
||||
|
||||
let comments = parse_comments(&response[1], &post.permalink, &post.author.name, highlighted_comment, &get_filters(&req));
|
||||
let url = req.uri().to_string();
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// CRATES
|
||||
use crate::utils::{
|
||||
catch_random, error, filter_posts, format_num, format_url, get_filters, param, redirect, rewrite_urls, setting, template, val, Post, Preferences, Subreddit,
|
||||
catch_random, error, filter_posts, format_num, format_url, get_filters, nsfw_landing, param, redirect, rewrite_urls, setting, template, val, Post, Preferences, Subreddit,
|
||||
};
|
||||
use crate::{client::json, server::ResponseExt, RequestExt};
|
||||
use askama::Template;
|
||||
|
@ -96,6 +96,12 @@ 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
|
||||
// has disabled the display of NSFW content.
|
||||
if setting(&req, "show_nsfw") != "on" && sub.nsfw {
|
||||
return Ok(nsfw_landing(req).await.unwrap_or_default());
|
||||
}
|
||||
|
||||
let path = format!("/r/{}/{}.json?{}&raw_json=1", sub_name.clone(), sort, req.uri().query().unwrap_or_default());
|
||||
let url = String::from(req.uri().path_and_query().map_or("", |val| val.as_str()));
|
||||
let redirect_url = url[1..].replace('?', "%3F").replace('&', "%26").replace('+', "%2B");
|
||||
|
@ -416,5 +422,6 @@ async fn subreddit(sub: &str, quarantined: bool) -> Result<Subreddit, String> {
|
|||
members: format_num(members),
|
||||
active: format_num(active),
|
||||
wiki: res["data"]["wiki_enabled"].as_bool().unwrap_or_default(),
|
||||
nsfw: res["data"]["over18"].as_bool().unwrap_or_default(),
|
||||
})
|
||||
}
|
||||
|
|
11
src/user.rs
11
src/user.rs
|
@ -1,7 +1,7 @@
|
|||
// CRATES
|
||||
use crate::client::json;
|
||||
use crate::server::RequestExt;
|
||||
use crate::utils::{error, filter_posts, format_url, get_filters, param, setting, template, Post, Preferences, User};
|
||||
use crate::utils::{error, filter_posts, format_url, get_filters, nsfw_landing, param, setting, template, Post, Preferences, User};
|
||||
use askama::Template;
|
||||
use hyper::{Body, Request, Response};
|
||||
use time::{macros::format_description, OffsetDateTime};
|
||||
|
@ -45,8 +45,16 @@ pub async fn profile(req: Request<Body>) -> Result<Response<Body>, String> {
|
|||
// Retrieve other variables from libbacon request
|
||||
let sort = param(&path, "sort").unwrap_or_default();
|
||||
let username = req.param("name").unwrap_or_default();
|
||||
|
||||
// Retrieve info from user about page.
|
||||
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 {
|
||||
return Ok(nsfw_landing(req).await.unwrap_or_default());
|
||||
}
|
||||
|
||||
let filters = get_filters(&req);
|
||||
if filters.contains(&["u_", &username].concat()) {
|
||||
template(UserTemplate {
|
||||
|
@ -111,6 +119,7 @@ async fn user(name: &str) -> Result<User, String> {
|
|||
created: created.format(format_description!("[month repr:short] [day] '[year repr:last_two]")).unwrap_or_default(),
|
||||
banner: about("banner_img"),
|
||||
description: about("public_description"),
|
||||
nsfw: res["data"]["subreddit"]["over_18"].as_bool().unwrap_or_default(),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
67
src/utils.rs
67
src/utils.rs
|
@ -13,6 +13,16 @@ use std::str::FromStr;
|
|||
use time::{macros::format_description, Duration, OffsetDateTime};
|
||||
use url::Url;
|
||||
|
||||
/// Identifies whether or not the page is a subreddit, a user page, or a post.
|
||||
/// This is used by the NSFW landing template to determine the mesage to convey
|
||||
/// to the user.
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub enum ResourceType {
|
||||
Subreddit,
|
||||
User,
|
||||
Post,
|
||||
}
|
||||
|
||||
// Post flair with content, background color and foreground color
|
||||
pub struct Flair {
|
||||
pub flair_parts: Vec<FlairPart>,
|
||||
|
@ -214,6 +224,7 @@ pub struct Post {
|
|||
pub comments: (String, String),
|
||||
pub gallery: Vec<GalleryMedia>,
|
||||
pub awards: Awards,
|
||||
pub nsfw: bool,
|
||||
}
|
||||
|
||||
impl Post {
|
||||
|
@ -314,6 +325,7 @@ impl Post {
|
|||
comments: format_num(data["num_comments"].as_i64().unwrap_or_default()),
|
||||
gallery,
|
||||
awards,
|
||||
nsfw: post["data"]["over_18"].as_bool().unwrap_or_default(),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -405,6 +417,27 @@ pub struct ErrorTemplate {
|
|||
pub url: String,
|
||||
}
|
||||
|
||||
/// Template for NSFW landing page. The landing page is displayed when a page's
|
||||
/// content is wholly NSFW, but a user has not enabled the option to view NSFW
|
||||
/// posts.
|
||||
#[derive(Template)]
|
||||
#[template(path = "nsfwlanding.html")]
|
||||
pub struct NSFWLandingTemplate {
|
||||
/// Identifier for the resource. This is either a subreddit name or a
|
||||
/// username. (In the case of the latter, set is_user to true.)
|
||||
pub res: String,
|
||||
|
||||
/// Identifies whether or not the resource is a subreddit, a user page,
|
||||
/// or a post.
|
||||
pub res_type: ResourceType,
|
||||
|
||||
/// User preferences.
|
||||
pub prefs: Preferences,
|
||||
|
||||
/// Request URL.
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
// User struct containing metadata about user
|
||||
pub struct User {
|
||||
|
@ -415,6 +448,7 @@ pub struct User {
|
|||
pub created: String,
|
||||
pub banner: String,
|
||||
pub description: String,
|
||||
pub nsfw: bool,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -429,6 +463,7 @@ pub struct Subreddit {
|
|||
pub members: (String, String),
|
||||
pub active: (String, String),
|
||||
pub wiki: bool,
|
||||
pub nsfw: bool,
|
||||
}
|
||||
|
||||
// Parser for query params, used in sorting (eg. /r/rust/?sort=hot)
|
||||
|
@ -602,6 +637,7 @@ pub async fn parse_post(post: &serde_json::Value) -> Post {
|
|||
comments: format_num(post["data"]["num_comments"].as_i64().unwrap_or_default()),
|
||||
gallery,
|
||||
awards,
|
||||
nsfw: post["data"]["over_18"].as_bool().unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -813,6 +849,37 @@ 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())
|
||||
}
|
||||
|
||||
/// 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<Body>) -> Result<Response<Body>, 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.
|
||||
let res: String = if !req.param("name").unwrap_or_default().is_empty() {
|
||||
res_type = ResourceType::User;
|
||||
req.param("name").unwrap_or_default()
|
||||
} else if !req.param("id").unwrap_or_default().is_empty() {
|
||||
res_type = ResourceType::Post;
|
||||
req.param("id").unwrap_or_default()
|
||||
} else {
|
||||
res_type = ResourceType::Subreddit;
|
||||
req.param("sub").unwrap_or_default()
|
||||
};
|
||||
|
||||
let body = NSFWLandingTemplate {
|
||||
res,
|
||||
res_type,
|
||||
prefs: Preferences::new(req),
|
||||
url,
|
||||
}
|
||||
.render()
|
||||
.unwrap_or_default();
|
||||
|
||||
Ok(Response::builder().status(403).header("content-type", "text/html").body(body.into()).unwrap_or_default())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::format_num;
|
||||
|
|
|
@ -1286,6 +1286,31 @@ td, th {
|
|||
color: var(--accent);
|
||||
};
|
||||
|
||||
/* NSFW Landing Page */
|
||||
|
||||
#nsfw_landing {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#nsfw_landing h1 {
|
||||
display: inline-block;
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#nsfw_landing p {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#nsfw_landing a {
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
/* Mobile */
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
{% extends "base.html" %}
|
||||
{% block title %}NSFW content gated{% endblock %}
|
||||
{% block sortstyle %}{% endblock %}
|
||||
{% block content %}
|
||||
<div id="nsfw_landing">
|
||||
{% if res_type == crate::utils::ResourceType::Subreddit %}
|
||||
<h1>😱 r/{{ res }} is a NSFW community!</h1>
|
||||
{% else if res_type == crate::utils::ResourceType::User %}
|
||||
<h1>😱 u/{{ res }}'s content is NSFW!</h1>
|
||||
{% else if res_type == crate::utils::ResourceType::Post %}
|
||||
<h1>😱 This post is NSFW!</h1>
|
||||
{% endif %}
|
||||
<br />
|
||||
<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>
|
||||
</div>
|
||||
{% endblock %}
|
Loading…
Reference in New Issue