quick bodge (fix later)

This commit is contained in:
ayaka 2025-05-24 01:02:46 +12:00
parent 9001a92273
commit 6b0ee8eafb
4 changed files with 176 additions and 48 deletions

20
Cargo.lock generated
View File

@ -1355,7 +1355,16 @@ dependencies = [
] ]
[[package]] [[package]]
name = "redlib" name = "redox_syscall"
version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1"
dependencies = [
"bitflags",
]
[[package]]
name = "redsunlib"
version = "0.36.0" version = "0.36.0"
dependencies = [ dependencies = [
"arc-swap", "arc-swap",
@ -1402,15 +1411,6 @@ dependencies = [
"uuid", "uuid",
] ]
[[package]]
name = "redox_syscall"
version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1"
dependencies = [
"bitflags",
]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.11.1" version = "1.11.1"

View File

@ -342,7 +342,7 @@ async fn main() {
// Configure settings // Configure settings
app.at("/settings").get(|r| settings::get(r).boxed()).post(|r| settings::set(r).boxed()); app.at("/settings").get(|r| settings::get(r).boxed()).post(|r| settings::set(r).boxed());
app.at("/settings/restore").get(|r| settings::restore(r).boxed()); app.at("/settings/restore").get(|r| settings::restore(r).boxed());
app.at("/settings/encoded-restore").post(|r| settings::encoded_restore(r).boxed()); // app.at("/settings/encoded-restore").post(|r| settings::encoded_restore(r).boxed()); NOTE: TODO (Well, TOFIX)
app.at("/settings/update").get(|r| settings::update(r).boxed()); app.at("/settings/update").get(|r| settings::update(r).boxed());
// Mascots // Mascots

View File

@ -3,13 +3,16 @@
use crate::{config, utils}; use crate::{config, utils};
// CRATES // CRATES
use crate::utils::{ use crate::utils::{
catch_random, error, filter_posts, format_num, format_url, get_filters, nsfw_landing, param, redirect, rewrite_urls, setting, template, val, Post, Preferences, Subreddit, catch_random, error, filter_posts, format_num, format_url, get_filters, info, nsfw_landing, param, redirect, rewrite_urls, setting, template, val, Post, Preferences,
Subreddit,
}; };
use crate::{client::json, server::RequestExt, server::ResponseExt}; use crate::{client::json, server::RequestExt, server::ResponseExt};
use cookie::Cookie; use cookie::Cookie;
use htmlescape::decode_html;
use hyper::{Body, Request, Response}; use hyper::{Body, Request, Response};
use rinja::Template; use rinja::Template;
use chrono::DateTime;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use regex::Regex; use regex::Regex;
use time::{macros::format_description, Duration, OffsetDateTime}; use time::{macros::format_description, Duration, OffsetDateTime};
@ -66,6 +69,7 @@ pub async fn community(req: Request<Body>) -> Result<Response<Body>, String> {
let query = req.uri().query().unwrap_or_default().to_string(); let query = req.uri().query().unwrap_or_default().to_string();
let subscribed = setting(&req, "subscriptions"); let subscribed = setting(&req, "subscriptions");
let front_page = setting(&req, "front_page"); let front_page = setting(&req, "front_page");
let remove_default_feeds = setting(&req, "remove_default_feeds") == "on";
let post_sort = req.cookie("post_sort").map_or_else(|| "hot".to_string(), |c| c.value().to_string()); let post_sort = req.cookie("post_sort").map_or_else(|| "hot".to_string(), |c| c.value().to_string());
let sort = req.param("sort").unwrap_or_else(|| req.param("id").unwrap_or(post_sort)); let sort = req.param("sort").unwrap_or_else(|| req.param("id").unwrap_or(post_sort));
@ -78,6 +82,21 @@ pub async fn community(req: Request<Body>) -> Result<Response<Body>, String> {
} else { } else {
front_page.clone() front_page.clone()
}); });
if (sub_name == "popular" || sub_name == "all") && remove_default_feeds {
if subscribed.is_empty() {
return info(req, "Subscribe to some subreddits! (Default feeds disabled in settings)").await;
} else {
// If there are subscribed subs, but we get here, then the problem is that front_page pref is set to something besides default.
// Tell user to go to settings and change front page to default.
return info(
req,
"You have subscribed to some subreddits, but your front page is not set to default. Visit settings and change front page to default.",
)
.await;
}
}
let quarantined = can_access_quarantine(&req, &sub_name) || root; let quarantined = can_access_quarantine(&req, &sub_name) || root;
// Handle random subreddits // Handle random subreddits
@ -213,6 +232,41 @@ pub fn can_access_quarantine(req: &Request<Body>, sub: &str) -> bool {
setting(req, &format!("allow_quaran_{}", sub.to_lowercase())).parse().unwrap_or_default() setting(req, &format!("allow_quaran_{}", sub.to_lowercase())).parse().unwrap_or_default()
} }
// Join items in chunks of 4000 bytes in length for cookies
pub fn join_until_size_limit<T: std::fmt::Display>(vec: &[T]) -> Vec<std::string::String> {
let mut result = Vec::new();
let mut list = String::new();
let mut current_size = 0;
for item in vec {
// Size in bytes
let item_size = item.to_string().len();
// Use 4000 bytes to leave us some headroom because the name and options of the cookie count towards the 4096 byte cap
if current_size + item_size > 4000 {
// If last item add a seperator on the end of the list so it's interpreted properly in tanden with the next cookie
list.push('+');
// Push current list to result vector
result.push(list);
// Reset the list variable so we can continue with only new items
list = String::new();
}
// Add separator if not the first item
if !list.is_empty() {
list.push('+');
}
// Add current item to list
list.push_str(&item.to_string());
current_size = list.len() + item_size;
}
// Make sure to push whatever the remaining subreddits are there into the result vector
result.push(list);
// Return resulting vector
result
}
// Sub, filter, unfilter, quicklist, unquicklist or unsub by setting subscription cookie using response "Set-Cookie" header // Sub, filter, unfilter, quicklist, unquicklist or unsub by setting subscription cookie using response "Set-Cookie" header
pub async fn subscriptions_filters_quicklists(req: Request<Body>) -> Result<Response<Body>, String> { pub async fn subscriptions_filters_quicklists(req: Request<Body>) -> Result<Response<Body>, String> {
let sub = req.param("sub").unwrap_or_default(); let sub = req.param("sub").unwrap_or_default();
@ -314,28 +368,100 @@ pub async fn subscriptions_filters_quicklists(req: Request<Body>) -> Result<Resp
let mut response = redirect(&path); let mut response = redirect(&path);
// Delete cookie if empty, else set // If sub_list is empty remove all subscriptions cookies, otherwise update them and remove old ones
if sub_list.is_empty() { if sub_list.is_empty() {
// Remove subscriptions cookie
response.remove_cookie("subscriptions".to_string()); response.remove_cookie("subscriptions".to_string());
} else {
response.insert_cookie( // Start with first numbered subscriptions cookie
Cookie::build(("subscriptions", sub_list.join("+"))) let mut subscriptions_number = 1;
.path("/")
.http_only(true) // While whatever subscriptionsNUMBER cookie we're looking at has a value
.expires(OffsetDateTime::now_utc() + Duration::weeks(52)) while req.cookie(&format!("subscriptions{}", subscriptions_number)).is_some() {
.into(), // Remove that subscriptions cookie
); response.remove_cookie(format!("subscriptions{}", subscriptions_number));
// Increment subscriptions cookie number
subscriptions_number += 1;
} }
if filters.is_empty() {
response.remove_cookie("filters".to_string());
} else { } else {
// Start at 0 to keep track of what number we need to start deleting old subscription cookies from
let mut subscriptions_number_to_delete_from = 0;
// Starting at 0 so we handle the subscription cookie without a number first
for (subscriptions_number, list) in join_until_size_limit(&sub_list).into_iter().enumerate() {
let subscriptions_cookie = if subscriptions_number == 0 {
"subscriptions".to_string()
} else {
format!("subscriptions{}", subscriptions_number)
};
response.insert_cookie( response.insert_cookie(
Cookie::build(("filters", filters.join("+"))) Cookie::build((subscriptions_cookie, list))
.path("/") .path("/")
.http_only(true) .http_only(true)
.expires(OffsetDateTime::now_utc() + Duration::weeks(52)) .expires(OffsetDateTime::now_utc() + Duration::weeks(52))
.into(), .into(),
); );
subscriptions_number_to_delete_from += 1;
}
// While whatever subscriptionsNUMBER cookie we're looking at has a value
while req.cookie(&format!("subscriptions{}", subscriptions_number_to_delete_from)).is_some() {
// Remove that subscriptions cookie
response.remove_cookie(format!("subscriptions{}", subscriptions_number_to_delete_from));
// Increment subscriptions cookie number
subscriptions_number_to_delete_from += 1;
}
}
// If filters is empty remove all filters cookies, otherwise update them and remove old ones
if filters.is_empty() {
// Remove filters cookie
response.remove_cookie("filters".to_string());
// Start with first numbered filters cookie
let mut filters_number = 1;
// While whatever filtersNUMBER cookie we're looking at has a value
while req.cookie(&format!("filters{}", filters_number)).is_some() {
// Remove that filters cookie
response.remove_cookie(format!("filters{}", filters_number));
// Increment filters cookie number
filters_number += 1;
}
} else {
// Start at 0 to keep track of what number we need to start deleting old filters cookies from
let mut filters_number_to_delete_from = 0;
for (filters_number, list) in join_until_size_limit(&filters).into_iter().enumerate() {
let filters_cookie = if filters_number == 0 {
"filters".to_string()
} else {
format!("filters{}", filters_number)
};
response.insert_cookie(
Cookie::build((filters_cookie, list))
.path("/")
.http_only(true)
.expires(OffsetDateTime::now_utc() + Duration::weeks(52))
.into(),
);
filters_number_to_delete_from += 1;
}
// While whatever filtersNUMBER cookie we're looking at has a value
while req.cookie(&format!("filters{}", filters_number_to_delete_from)).is_some() {
// Remove that filters cookie
response.remove_cookie(format!("filters{}", filters_number_to_delete_from));
// Increment filters cookie number
filters_number_to_delete_from += 1;
} }
if quicklist.is_empty() { if quicklist.is_empty() {
response.remove_cookie("quicklist".to_string()); response.remove_cookie("quicklist".to_string());
@ -348,6 +474,7 @@ pub async fn subscriptions_filters_quicklists(req: Request<Body>) -> Result<Resp
.into(), .into(),
); );
} }
}
Ok(response) Ok(response)
} }
@ -527,9 +654,10 @@ pub async fn rss(req: Request<Body>) -> Result<Response<Body>, String> {
.into_iter() .into_iter()
.map(|post| Item { .map(|post| Item {
title: Some(post.title.to_string()), title: Some(post.title.to_string()),
link: Some(utils::get_post_url(&post)), link: Some(format_url(&utils::get_post_url(&post))),
author: Some(post.author.name), author: Some(post.author.name),
content: Some(rewrite_urls(&post.body)), content: Some(rewrite_urls(&decode_html(&post.body).unwrap())),
pub_date: Some(DateTime::from_timestamp(post.created_ts as i64, 0).unwrap_or_default().to_rfc2822()),
description: Some(format!( description: Some(format!(
"<a href='{}{}'>Comments</a>", "<a href='{}{}'>Comments</a>",
config::get_setting("REDLIB_FULL_URL").unwrap_or_default(), config::get_setting("REDLIB_FULL_URL").unwrap_or_default(),

View File

@ -37,12 +37,6 @@
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>Interface</legend> <legend>Interface</legend>
<div class="prefs-group">
<label for="remove_default_feeds">Remove default feeds</label>
<input type="hidden" value="off" name="remove_default_feeds">
<input type="checkbox" name="remove_default_feeds" id="remove_default_feeds" {% if
prefs.remove_default_feeds=="on" %}checked{% endif %}>
</div>
<div class="prefs-group"> <div class="prefs-group">
<label for="front_page">Front page:</label> <label for="front_page">Front page:</label>
<select name="front_page" id="front_page"> <select name="front_page" id="front_page">
@ -55,6 +49,12 @@
{% call utils::options(prefs.layout, ["card", "clean", "compact", "old", "waterfall"], "card") %} {% call utils::options(prefs.layout, ["card", "clean", "compact", "old", "waterfall"], "card") %}
</select> </select>
</div> </div>
<div class="prefs-group">
<label for="remove_default_feeds">Remove default feeds</label>
<input type="hidden" value="off" name="remove_default_feeds">
<input type="checkbox" name="remove_default_feeds" id="remove_default_feeds" {% if
prefs.remove_default_feeds=="on" %}checked{% endif %}>
</div>
<div class="prefs-group"> <div class="prefs-group">
<label for="wide">Wide UI:</label> <label for="wide">Wide UI:</label>
<input type="hidden" value="off" name="wide"> <input type="hidden" value="off" name="wide">
@ -219,7 +219,7 @@
</div> </div>
{% endif %} {% endif %}
<div id="settings_note"> <!-- <div id="settings_note"> NOTE: TODO
<p><b>Note:</b> settings and subscriptions are saved in browser cookies. Clearing your cookies will reset them. <p><b>Note:</b> settings and subscriptions are saved in browser cookies. Clearing your cookies will reset them.
</p> </p>
<br> <br>
@ -248,7 +248,7 @@
<button class="import" type="submit">Import</button> <button class="import" type="submit">Import</button>
</form> </form>
</div> </div>
</div> </div> -->
</div> </div>
{% endblock %} {% endblock %}