Merge branch 'main' into feat/hide-summary-and-sidebar

This commit is contained in:
Matthew Esposito 2024-05-29 18:46:10 -04:00 committed by GitHub
commit 093d240530
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 356 additions and 325 deletions

445
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@ name = "redlib"
description = " Alternative private front-end to Reddit"
license = "AGPL-3.0"
repository = "https://github.com/redlib-org/redlib"
version = "0.31.2"
version = "0.33.0"
authors = [
"Matthew Esposito <matt+cargo@matthew.science>",
"spikecodes <19519553+spikecodes@users.noreply.github.com>",

View File

@ -380,12 +380,13 @@ REDLIB_DEFAULT_USE_HLS = "on"
Assign a default value for each instance-specific setting by passing environment variables to Redlib in the format `REDLIB_{X}`. Replace `{X}` with the setting name (see list below) in capital letters.
| Name | Possible values | Default value | Description |
| ------------------------- | --------------- | ---------------- | --------------------------------------------------------------------------------------------------------- |
| `SFW_ONLY` | `["on", "off"]` | `off` | Enables SFW-only mode for the instance, i.e. all NSFW content is filtered. |
| `BANNER` | String | (empty) | Allows the server to set a banner to be displayed. Currently this is displayed on the instance info page. |
| `ROBOTS_DISABLE_INDEXING` | `["on", "off"]` | `off` | Disables indexing of the instance by search engines. |
| Name | Possible values | Default value | Description |
| ------------------------- | --------------- | ---------------- | --------------------------------------------------------------------------------------------------------- |
| `SFW_ONLY` | `["on", "off"]` | `off` | Enables SFW-only mode for the instance, i.e. all NSFW content is filtered. |
| `BANNER` | String | (empty) | Allows the server to set a banner to be displayed. Currently this is displayed on the instance info page. |
| `ROBOTS_DISABLE_INDEXING` | `["on", "off"]` | `off` | Disables indexing of the instance by search engines. |
| `PUSHSHIFT_FRONTEND` | String | `undelete.pullpush.io` | Allows the server to set the Pushshift frontend to be used with "removed" links. |
| `PORT` | Integer 0-65535 | `8080` | The **internal** port Redlib listens on. |
## Default user settings

View File

@ -170,7 +170,7 @@ fn request(method: &'static Method, path: String, redirect: bool, quarantine: bo
// Construct the hyper client from the HTTPS connector.
let client: Client<_, Body> = CLIENT.clone();
let (token, vendor_id, device_id, user_agent, loid) = {
let (token, vendor_id, device_id, mut user_agent, loid) = {
let client = block_on(OAUTH_CLIENT.read());
(
client.token.clone(),
@ -180,6 +180,12 @@ fn request(method: &'static Method, path: String, redirect: bool, quarantine: bo
client.headers_map.get("x-reddit-loid").cloned().unwrap_or_default(),
)
};
// Check if multi sub requested. If so, replace "Android" with a tricky word.
if path.contains('+') {
user_agent = user_agent.replace("Android", "Andr\u{200B}oid");
}
// Build request to Reddit. When making a GET, request gzip compression.
// (Reddit doesn't do brotli yet.)
let builder = Request::builder()

View File

@ -151,7 +151,7 @@ pub async fn item(req: Request<Body>) -> Result<Response<Body>, String> {
}
if have_after {
before = "t3_".to_owned();
"t3_".clone_into(&mut before);
before.push_str(&duplicates[0].id);
}
@ -161,7 +161,7 @@ pub async fn item(req: Request<Body>) -> Result<Response<Body>, String> {
if have_before {
// The next batch will need to start from one after the
// last post in the current batch.
after = "t3_".to_owned();
"t3_".clone_into(&mut after);
after.push_str(&duplicates[l - 1].id);
// Here is where things get terrible. Notice that we
@ -182,7 +182,7 @@ pub async fn item(req: Request<Body>) -> Result<Response<Body>, String> {
match json(new_path, true).await {
Ok(response) => {
if !response[1]["data"]["children"].as_array().unwrap_or(&Vec::new()).is_empty() {
before = "t3_".to_owned();
"t3_".clone_into(&mut before);
before.push_str(&duplicates[0].id);
}
}

View File

@ -4,6 +4,44 @@
// Filled in with real app versions
pub static _IOS_APP_VERSION_LIST: &[&str; 1] = &[""];
pub static ANDROID_APP_VERSION_LIST: &[&str; 150] = &[
"Version 2023.48.0/Build 1319123",
"Version 2023.49.0/Build 1321715",
"Version 2023.49.1/Build 1322281",
"Version 2023.50.0/Build 1332338",
"Version 2023.50.1/Build 1345844",
"Version 2024.02.0/Build 1368985",
"Version 2024.03.0/Build 1379408",
"Version 2024.04.0/Build 1391236",
"Version 2024.05.0/Build 1403584",
"Version 2024.06.0/Build 1418489",
"Version 2024.07.0/Build 1429651",
"Version 2024.08.0/Build 1439531",
"Version 2024.10.0/Build 1470045",
"Version 2024.10.1/Build 1478645",
"Version 2024.11.0/Build 1480707",
"Version 2024.12.0/Build 1494694",
"Version 2024.13.0/Build 1505187",
"Version 2024.14.0/Build 1520556",
"Version 2024.15.0/Build 1536823",
"Version 2024.16.0/Build 1551366",
"Version 2024.17.0/Build 1568106",
"Version 2024.18.0/Build 1577901",
"Version 2024.18.1/Build 1585304",
"Version 2024.19.0/Build 1593346",
"Version 2024.20.0/Build 1612800",
"Version 2024.20.1/Build 1615586",
"Version 2024.20.2/Build 1624969",
"Version 2024.21.0/Build 1631686",
"Version 2024.22.0/Build 1645257",
"Version 2024.22.1/Build 1652272",
"Version 2023.21.0/Build 956283",
"Version 2023.22.0/Build 968223",
"Version 2023.23.0/Build 983896",
"Version 2023.24.0/Build 998541",
"Version 2023.25.0/Build 1014750",
"Version 2023.25.1/Build 1018737",
"Version 2023.26.0/Build 1019073",
"Version 2023.27.0/Build 1031923",
"Version 2023.28.0/Build 1046887",
"Version 2023.29.0/Build 1059855",
"Version 2023.30.0/Build 1078734",
@ -26,14 +64,14 @@ pub static ANDROID_APP_VERSION_LIST: &[&str; 150] = &[
"Version 2023.44.0/Build 1268622",
"Version 2023.45.0/Build 1281371",
"Version 2023.47.0/Build 1303604",
"Version 2023.48.0/Build 1319123",
"Version 2023.49.0/Build 1321715",
"Version 2023.49.1/Build 1322281",
"Version 2023.50.0/Build 1332338",
"Version 2023.50.1/Build 1345844",
"Version 2024.02.0/Build 1368985",
"Version 2024.03.0/Build 1379408",
"Version 2024.04.0/Build 1391236",
"Version 2022.42.0/Build 638508",
"Version 2022.43.0/Build 648277",
"Version 2022.44.0/Build 664348",
"Version 2022.45.0/Build 677985",
"Version 2023.01.0/Build 709875",
"Version 2023.02.0/Build 717912",
"Version 2023.03.0/Build 729220",
"Version 2023.04.0/Build 744681",
"Version 2023.05.0/Build 755453",
"Version 2023.06.0/Build 775017",
"Version 2023.07.0/Build 788827",
@ -56,14 +94,14 @@ pub static ANDROID_APP_VERSION_LIST: &[&str; 150] = &[
"Version 2023.19.0/Build 927681",
"Version 2023.20.0/Build 943980",
"Version 2023.20.1/Build 946732",
"Version 2023.21.0/Build 956283",
"Version 2023.22.0/Build 968223",
"Version 2023.23.0/Build 983896",
"Version 2023.24.0/Build 998541",
"Version 2023.25.0/Build 1014750",
"Version 2023.25.1/Build 1018737",
"Version 2023.26.0/Build 1019073",
"Version 2023.27.0/Build 1031923",
"Version 2022.20.0/Build 487703",
"Version 2022.21.0/Build 492436",
"Version 2022.22.0/Build 498700",
"Version 2022.23.0/Build 502374",
"Version 2022.23.1/Build 506606",
"Version 2022.24.0/Build 510950",
"Version 2022.24.1/Build 513462",
"Version 2022.25.0/Build 515072",
"Version 2022.25.1/Build 516394",
"Version 2022.25.2/Build 519915",
"Version 2022.26.0/Build 521193",
@ -86,14 +124,14 @@ pub static ANDROID_APP_VERSION_LIST: &[&str; 150] = &[
"Version 2022.40.0/Build 624782",
"Version 2022.41.0/Build 630468",
"Version 2022.41.1/Build 634168",
"Version 2022.42.0/Build 638508",
"Version 2022.43.0/Build 648277",
"Version 2022.44.0/Build 664348",
"Version 2022.45.0/Build 677985",
"Version 2023.01.0/Build 709875",
"Version 2023.02.0/Build 717912",
"Version 2023.03.0/Build 729220",
"Version 2023.04.0/Build 744681",
"Version 2021.39.1/Build 372418",
"Version 2021.41.0/Build 376052",
"Version 2021.42.0/Build 378193",
"Version 2021.43.0/Build 382019",
"Version 2021.44.0/Build 385129",
"Version 2021.45.0/Build 387663",
"Version 2021.46.0/Build 392043",
"Version 2021.47.0/Build 394342",
"Version 2022.10.0/Build 429896",
"Version 2022.1.0/Build 402829",
"Version 2022.11.0/Build 433004",
@ -106,15 +144,7 @@ pub static ANDROID_APP_VERSION_LIST: &[&str; 150] = &[
"Version 2022.17.0/Build 468480",
"Version 2022.18.0/Build 473740",
"Version 2022.19.1/Build 482464",
"Version 2022.20.0/Build 487703",
"Version 2022.2.0/Build 405543",
"Version 2022.21.0/Build 492436",
"Version 2022.22.0/Build 498700",
"Version 2022.23.0/Build 502374",
"Version 2022.23.1/Build 506606",
"Version 2022.24.0/Build 510950",
"Version 2022.24.1/Build 513462",
"Version 2022.25.0/Build 515072",
"Version 2022.3.0/Build 408637",
"Version 2022.4.0/Build 411368",
"Version 2022.5.0/Build 414731",
@ -124,35 +154,5 @@ pub static ANDROID_APP_VERSION_LIST: &[&str; 150] = &[
"Version 2022.7.0/Build 420849",
"Version 2022.8.0/Build 423906",
"Version 2022.9.0/Build 426592",
"Version 2021.20.0/Build 326964",
"Version 2021.21.0/Build 327703",
"Version 2021.21.1/Build 328461",
"Version 2021.22.0/Build 329696",
"Version 2021.23.0/Build 331631",
"Version 2021.24.0/Build 333951",
"Version 2021.25.0/Build 335451",
"Version 2021.26.0/Build 336739",
"Version 2021.27.0/Build 338857",
"Version 2021.28.0/Build 340747",
"Version 2021.29.0/Build 342342",
"Version 2021.30.0/Build 343820",
"Version 2021.31.0/Build 346485",
"Version 2021.32.0/Build 349507",
"Version 2021.33.0/Build 351843",
"Version 2021.34.0/Build 353911",
"Version 2021.35.0/Build 355878",
"Version 2021.36.0/Build 359254",
"Version 2021.36.1/Build 360572",
"Version 2021.37.0/Build 361905",
"Version 2021.38.0/Build 365032",
"Version 2021.39.0/Build 369068",
"Version 2021.39.1/Build 372418",
"Version 2021.41.0/Build 376052",
"Version 2021.42.0/Build 378193",
"Version 2021.43.0/Build 382019",
"Version 2021.44.0/Build 385129",
"Version 2021.45.0/Build 387663",
"Version 2021.46.0/Build 392043",
"Version 2021.47.0/Build 394342",
];
pub static _IOS_OS_VERSION_LIST: &[&str; 1] = &[""];

View File

@ -1,3 +1,5 @@
#![allow(dead_code)]
use brotli::enc::{BrotliCompress, BrotliEncoderParams};
use cached::proc_macro::cached;
use cookie::Cookie;

View File

@ -877,9 +877,9 @@ pub fn format_url(url: &str) -> String {
// These are links we want to replace in-body
static REDDIT_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r#"href="(https|http|)://(www\.|old\.|np\.|amp\.|new\.|)(reddit\.com|redd\.it)/"#).unwrap());
static REDDIT_PREVIEW_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"https?://(external-preview|preview)\.redd\.it(.*)[^?]").unwrap());
static REDDIT_PREVIEW_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"https?://(external-preview|preview|i)\.redd\.it(.*)[^?]").unwrap());
static REDDIT_EMOJI_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"https?://(www|).redditstatic\.com/(.*)").unwrap());
static REDLIB_PREVIEW_LINK_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r#"/preview/(pre|external-pre)/(.*?)>"#).unwrap());
static REDLIB_PREVIEW_LINK_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r#"/(img|preview/)(pre|external-pre)?/(.*?)>"#).unwrap());
static REDLIB_PREVIEW_TEXT_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r">(.*?)</a>").unwrap());
// Rewrite Reddit links to Redlib in body of text
@ -903,14 +903,47 @@ pub fn rewrite_urls(input_text: &str) -> String {
let formatted_url = format_url(REDDIT_PREVIEW_REGEX.find(&text1).map(|x| x.as_str()).unwrap_or_default());
let image_url = REDLIB_PREVIEW_LINK_REGEX.find(&formatted_url).map_or("", |m| m.as_str()).to_string();
let image_text = REDLIB_PREVIEW_TEXT_REGEX.find(&formatted_url).map_or("", |m| m.as_str()).to_string();
let mut image_caption = REDLIB_PREVIEW_TEXT_REGEX.find(&formatted_url).map_or("", |m| m.as_str()).to_string();
let image_to_replace = format!("<a href=\"{image_url}{image_text}").replace(">>", ">");
let image_replacement = format!("<a href=\"{image_url}<img src=\"{image_url}</a>");
/* As long as image_caption isn't empty remove first and last four characters of image_text to leave us with just the text in the caption without any HTML.
This makes it possible to enclose it in a <figcaption> later on without having stray HTML breaking it */
if !image_caption.is_empty() {
image_caption = image_caption[1..image_caption.len() - 4].to_string();
}
// image_url contains > at the end of it, and right above this we remove image_text's front >, leaving us with just a single > between them
let image_to_replace = format!("<a href=\"{image_url}{image_caption}</a>");
// _image_replacement needs to be in scope for the replacement at the bottom of the loop
let mut _image_replacement = String::new();
/* We don't want to show a caption that's just the image's link, so we check if we find a Reddit preview link within the image's caption.
If we don't find one we must have actual text, so we include a <figcaption> block that contains it.
Otherwise we don't include the <figcaption> block as we don't need it. */
if REDDIT_PREVIEW_REGEX.find(&image_caption).is_none() {
// Without this " would show as \" instead. "\&quot;" is how the quotes are formatted within image_text beforehand
image_caption = image_caption.replace("\\&quot;", "\"");
_image_replacement = format!("<figure><a href=\"{image_url}<img loading=\"lazy\" src=\"{image_url}</a><figcaption>{image_caption}</figcaption></figure>");
} else {
_image_replacement = format!("<figure><a href=\"{image_url}<img loading=\"lazy\" src=\"{image_url}</a></figure>");
}
/* In order to know if we're dealing with a normal or external preview we need to take a look at the first capture group of REDDIT_PREVIEW_REGEX
if it's preview we're dealing with something that needs /preview/pre, external-preview is /preview/external-pre, and i is /img */
let reddit_preview_regex_capture = REDDIT_PREVIEW_REGEX.captures(&text1).unwrap().get(1).map_or("", |m| m.as_str()).to_string();
let mut _preview_type = String::new();
if reddit_preview_regex_capture == "preview" {
_preview_type = "/preview/pre".to_string();
} else if reddit_preview_regex_capture == "external-preview" {
_preview_type = "/preview/external-pre".to_string();
} else {
_preview_type = "/img".to_string();
}
text1 = REDDIT_PREVIEW_REGEX
.replace(&text1, formatted_url)
.replace(&image_to_replace, &image_replacement)
.replace(&text1, format!("{_preview_type}$2"))
.replace(&image_to_replace, &_image_replacement)
.to_string()
}
}
@ -1166,11 +1199,8 @@ async fn test_fetching_ws() {
#[test]
fn test_rewriting_image_links() {
let input = r#"<p><a href="https://preview.redd.it/zq21ggkj2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=539d8050628ec1190cac26468fe99cc66b6071ab">https://preview.redd.it/zq21ggkj2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=539d8050628ec1190cac26468fe99cc66b6071ab</a></p>
<p><a href="https://preview.redd.it/vty9ocij2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=fc7c7ef993a5e9ef656d5f5d9cf8290a0a1df877">https://preview.redd.it/vty9ocij2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=fc7c7ef993a5e9ef656d5f5d9cf8290a0a1df877</a></p>
<p><a href="https://preview.redd.it/bdfdxkjj2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=d0fa420ece27605e882e89cb4711d75d774322ac">https://preview.redd.it/bdfdxkjj2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=d0fa420ece27605e882e89cb4711d75d774322ac</a></p>
<p><a href="https://preview.redd.it/6awags382xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=9c563aed4f07a91bdd249b5a3cea43a79710dcfc">caption 1</a></p>
<p><a href="https://preview.redd.it/rbu2ca2b2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=afb538cf784d2e339de9a91aba5dc9c92e47988f">caption 2</a></p>"#;
let output = r#"<p><a href="/preview/pre/zq21ggkj2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=539d8050628ec1190cac26468fe99cc66b6071ab"><img src="/preview/pre/zq21ggkj2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=539d8050628ec1190cac26468fe99cc66b6071ab"></a></p> <p><a href="/preview/pre/vty9ocij2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=fc7c7ef993a5e9ef656d5f5d9cf8290a0a1df877"><img src="/preview/pre/vty9ocij2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=fc7c7ef993a5e9ef656d5f5d9cf8290a0a1df877"></a></p> <p><a href="/preview/pre/bdfdxkjj2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=d0fa420ece27605e882e89cb4711d75d774322ac"><img src="/preview/pre/bdfdxkjj2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=d0fa420ece27605e882e89cb4711d75d774322ac"></a></p> <p><a href="/preview/pre/6awags382xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=9c563aed4f07a91bdd249b5a3cea43a79710dcfc"><img src="/preview/pre/6awags382xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=9c563aed4f07a91bdd249b5a3cea43a79710dcfc"></a></p> <p><a href="/preview/pre/rbu2ca2b2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=afb538cf784d2e339de9a91aba5dc9c92e47988f"><img src="/preview/pre/rbu2ca2b2xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=afb538cf784d2e339de9a91aba5dc9c92e47988f"></a></p>"#;
let input =
r#"<p><a href="https://preview.redd.it/6awags382xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=9c563aed4f07a91bdd249b5a3cea43a79710dcfc">caption 1</a></p>"#;
let output = r#"<p><figure><a href="/preview/pre/6awags382xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=9c563aed4f07a91bdd249b5a3cea43a79710dcfc"><img loading="lazy" src="/preview/pre/6awags382xo31.png?width=2560&amp;format=png&amp;auto=webp&amp;s=9c563aed4f07a91bdd249b5a3cea43a79710dcfc"></a><figcaption>caption 1</figcaption></figure></p"#;
assert_eq!(rewrite_urls(input), output);
}

View File

@ -187,6 +187,11 @@ nav #redlib {
vertical-align: -2px;
}
figcaption {
margin-top: 5px;
text-align: center;
}
#settings_link {
opacity: 0.8;
margin-left: 10px;
@ -979,10 +984,6 @@ a.search_subreddit:hover {
vertical-align: bottom;
}
.gallery figcaption {
margin-top: 5px;
}
.gallery .outbound_url {
color: var(--accent);
text-overflow: ellipsis;
@ -1010,6 +1011,9 @@ a.search_subreddit:hover {
.post_body img {
max-width: 100%;
display: block;
margin-left: auto;
margin-right: auto;
}
.post_poll {
@ -1187,6 +1191,10 @@ a.search_subreddit:hover {
}
}
.comment figure {
margin: 0;
}
.comment_left, .comment_right {
display: flex;
flex-direction: column;
@ -1484,10 +1492,19 @@ input[type="submit"] {
width: 100%;
}
.md > *:not(:first-child) {
.md > p:not(:first-child):not(:last-child) {
margin-top: 20px;
}
.md > figure:first-of-type {
margin-top: 5px;
margin-bottom: 0px;
}
.md > figure:not(:first-of-type) {
margin-top: 10px;
}
.md h1 { font-size: 22px; }
.md h2 { font-size: 20px; }
.md h3 { font-size: 18px; }