Compare commits
48 Commits
284e03ccf9
...
e187ccd14a
Author | SHA1 | Date | |
---|---|---|---|
e187ccd14a | |||
|
8a3ceaf94a | ||
|
bd47c206a1 | ||
|
7a099f259f | ||
|
4ea911e6b2 | ||
|
31d68afdc9 | ||
|
96a7e155c5 | ||
|
045a8852ec | ||
|
4cc8bf8318 | ||
|
1715b36ae9 | ||
|
6102b08894 | ||
|
892b0e89c8 | ||
|
a64e2143f3 | ||
|
e13d9b7239 | ||
|
e597ed8f06 | ||
|
8c67d33721 | ||
|
26aa374bbd | ||
|
5b8b1e36ca | ||
|
093d240530 | ||
|
9048565d48 | ||
|
6b2aab23c8 | ||
|
6b11d936b3 | ||
|
34692359cf | ||
|
33411a7588 | ||
|
5a0f0f96f5 | ||
|
273d889f1b | ||
|
93594fc642 | ||
|
af6f3d3b3f | ||
|
62b791bb24 | ||
|
e9af28b6eb | ||
|
2f2cded671 | ||
|
b22fb7cd7b | ||
|
75b0149313 | ||
|
50fad938dd | ||
|
b6f5831d10 | ||
|
565b50646f | ||
|
6484ebf897 | ||
|
3f863c8991 | ||
|
e581f432dd | ||
|
2c8f5a7ac1 | ||
|
6d83b07aaa | ||
|
27f25e0fb1 | ||
|
89140c8cf7 | ||
|
99048c4683 | ||
|
ccfe7d0eeb | ||
|
f7c182dcd8 | ||
|
9bd540d659 | ||
|
4f6a14739b |
@ -38,6 +38,8 @@ REDLIB_DEFAULT_AUTOPLAY_VIDEOS=off
|
|||||||
REDLIB_DEFAULT_SUBSCRIPTIONS=
|
REDLIB_DEFAULT_SUBSCRIPTIONS=
|
||||||
# Hide awards by default
|
# Hide awards by default
|
||||||
REDLIB_DEFAULT_HIDE_AWARDS=off
|
REDLIB_DEFAULT_HIDE_AWARDS=off
|
||||||
|
# Hide sidebar and summary
|
||||||
|
REDLIB_DEFAULT_HIDE_SIDEBAR_AND_SUMMARY=off
|
||||||
# Disable the confirmation before visiting Reddit
|
# Disable the confirmation before visiting Reddit
|
||||||
REDLIB_DEFAULT_DISABLE_VISIT_REDDIT_CONFIRMATION=off
|
REDLIB_DEFAULT_DISABLE_VISIT_REDDIT_CONFIRMATION=off
|
||||||
# Hide score by default
|
# Hide score by default
|
||||||
|
16
.github/workflows/main-rust.yml
vendored
16
.github/workflows/main-rust.yml
vendored
@ -30,9 +30,15 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
|
|
||||||
|
- name: Install musl-gcc
|
||||||
|
run: sudo apt-get install musl-tools
|
||||||
|
|
||||||
|
- name: Install cargo musl target
|
||||||
|
run: rustup target add x86_64-unknown-linux-musl
|
||||||
|
|
||||||
# Building actions
|
# Building actions
|
||||||
- name: Build
|
- name: Build
|
||||||
run: RUSTFLAGS='-C target-feature=+crt-static' cargo build --release --target x86_64-unknown-linux-gnu
|
run: RUSTFLAGS='-C target-feature=+crt-static' cargo build --release --target x86_64-unknown-linux-musl
|
||||||
|
|
||||||
- name: Versions
|
- name: Versions
|
||||||
id: version
|
id: version
|
||||||
@ -45,17 +51,17 @@ jobs:
|
|||||||
run: cargo publish --no-verify --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
run: cargo publish --no-verify --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
||||||
|
|
||||||
- name: Calculate SHA512 checksum
|
- name: Calculate SHA512 checksum
|
||||||
run: sha512sum target/x86_64-unknown-linux-gnu/release/redlib > redlib.sha512
|
run: sha512sum target/x86_64-unknown-linux-musl/release/redlib > redlib.sha512
|
||||||
|
|
||||||
- name: Calculate SHA256 checksum
|
- name: Calculate SHA256 checksum
|
||||||
run: sha256sum target/x86_64-unknown-linux-gnu/release/redlib > redlib.sha256
|
run: sha256sum target/x86_64-unknown-linux-musl/release/redlib > redlib.sha256
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v3
|
||||||
name: Upload a Build Artifact
|
name: Upload a Build Artifact
|
||||||
with:
|
with:
|
||||||
name: redlib
|
name: redlib
|
||||||
path: |
|
path: |
|
||||||
target/x86_64-unknown-linux-gnu/release/redlib
|
target/x86_64-unknown-linux-musl/release/redlib
|
||||||
redlib.sha512
|
redlib.sha512
|
||||||
redlib.sha256
|
redlib.sha256
|
||||||
|
|
||||||
@ -68,7 +74,7 @@ jobs:
|
|||||||
name: ${{ steps.version.outputs.VERSION }} - ${{ github.event.head_commit.message }}
|
name: ${{ steps.version.outputs.VERSION }} - ${{ github.event.head_commit.message }}
|
||||||
draft: true
|
draft: true
|
||||||
files: |
|
files: |
|
||||||
target/x86_64-unknown-linux-gnu/release/redlib
|
target/x86_64-unknown-linux-musl/release/redlib
|
||||||
redlib.sha512
|
redlib.sha512
|
||||||
redlib.sha256
|
redlib.sha256
|
||||||
body: |
|
body: |
|
||||||
|
2
.replit
2
.replit
@ -1,2 +1,2 @@
|
|||||||
run = "while :; do set -ex; nix-env -iA nixpkgs.unzip; curl -o./redlib.zip -fsSL -- https://nightly.link/redlib-org/redlib/workflows/main-rust/main/redlib.zip; unzip -n redlib.zip; mv target/x86_64-unknown-linux-gnu/release/redlib .; chmod +x redlib; set +e; ./redlib -H 63115200; sleep 1; done"
|
run = "while :; do set -ex; nix-env -iA nixpkgs.unzip; curl -o./redlib.zip -fsSL -- https://nightly.link/redlib-org/redlib/workflows/main-rust/main/redlib.zip; unzip -n redlib.zip; mv target/x86_64-unknown-linux-musl/release/redlib .; chmod +x redlib; set +e; ./redlib -H 63115200; sleep 1; done"
|
||||||
language = "bash"
|
language = "bash"
|
||||||
|
479
Cargo.lock
generated
479
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,7 @@ name = "redlib"
|
|||||||
description = " Alternative private front-end to Reddit"
|
description = " Alternative private front-end to Reddit"
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
repository = "https://git.stardust.wtf/Ayaka/redlib"
|
repository = "https://git.stardust.wtf/Ayaka/redlib"
|
||||||
version = "0.31.2"
|
version = "0.34.0"
|
||||||
authors = [
|
authors = [
|
||||||
"Matthew Esposito <matt+cargo@matthew.science>",
|
"Matthew Esposito <matt+cargo@matthew.science>",
|
||||||
"spikecodes <19519553+spikecodes@users.noreply.github.com>",
|
"spikecodes <19519553+spikecodes@users.noreply.github.com>",
|
||||||
@ -12,7 +12,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
askama = { version = "0.12.1", default-features = false }
|
askama = { version = "0.12.1", default-features = false }
|
||||||
cached = { version = "0.48.1", features = ["async"] }
|
cached = { version = "0.51.3", features = ["async"] }
|
||||||
clap = { version = "4.4.11", default-features = false, features = [
|
clap = { version = "4.4.11", default-features = false, features = [
|
||||||
"std",
|
"std",
|
||||||
"env",
|
"env",
|
||||||
@ -31,13 +31,13 @@ time = { version = "0.3.31", features = ["local-offset"] }
|
|||||||
url = "2.5.0"
|
url = "2.5.0"
|
||||||
rust-embed = { version = "8.1.0", features = ["include-exclude"] }
|
rust-embed = { version = "8.1.0", features = ["include-exclude"] }
|
||||||
libflate = "2.0.0"
|
libflate = "2.0.0"
|
||||||
brotli = { version = "3.4.0", features = ["std"] }
|
brotli = { version = "6.0.0", features = ["std"] }
|
||||||
toml = "0.8.8"
|
toml = "0.8.8"
|
||||||
once_cell = "1.19.0"
|
once_cell = "1.19.0"
|
||||||
serde_yaml = "0.9.29"
|
serde_yaml = "0.9.29"
|
||||||
build_html = "2.4.0"
|
build_html = "2.4.0"
|
||||||
uuid = { version = "1.6.1", features = ["v4"] }
|
uuid = { version = "1.6.1", features = ["v4"] }
|
||||||
base64 = "0.21.5"
|
base64 = "0.22.1"
|
||||||
fastrand = "2.0.1"
|
fastrand = "2.0.1"
|
||||||
log = "0.4.20"
|
log = "0.4.20"
|
||||||
pretty_env_logger = "0.5.0"
|
pretty_env_logger = "0.5.0"
|
||||||
|
13
README.md
13
README.md
@ -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.
|
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 |
|
| 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. |
|
| `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. |
|
| `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. |
|
| `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. |
|
| `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
|
## Default user settings
|
||||||
|
|
||||||
@ -393,7 +394,7 @@ Assign a default value for each user-modifiable setting by passing environment v
|
|||||||
|
|
||||||
| Name | Possible values | Default value |
|
| Name | Possible values | Default value |
|
||||||
| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------- |
|
| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------- |
|
||||||
| `THEME` | `["system", "light", "dark", "black", "dracula", "nord", "laserwave", "violet", "gold", "rosebox", "gruvboxdark", "gruvboxlight"]` | `system` |
|
| `THEME` | `["system", "light", "dark", "black", "dracula", "nord", "laserwave", "violet", "gold", "rosebox", "gruvboxdark", "gruvboxlight", "tokyoNight", "icebergDark"]` | `system` |
|
||||||
| `FRONT_PAGE` | `["default", "popular", "all"]` | `default` |
|
| `FRONT_PAGE` | `["default", "popular", "all"]` | `default` |
|
||||||
| `LAYOUT` | `["card", "clean", "compact"]` | `card` |
|
| `LAYOUT` | `["card", "clean", "compact"]` | `card` |
|
||||||
| `WIDE` | `["on", "off"]` | `off` |
|
| `WIDE` | `["on", "off"]` | `off` |
|
||||||
|
@ -170,7 +170,7 @@ fn request(method: &'static Method, path: String, redirect: bool, quarantine: bo
|
|||||||
// Construct the hyper client from the HTTPS connector.
|
// Construct the hyper client from the HTTPS connector.
|
||||||
let client: Client<_, Body> = CLIENT.clone();
|
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());
|
let client = block_on(OAUTH_CLIENT.read());
|
||||||
(
|
(
|
||||||
client.token.clone(),
|
client.token.clone(),
|
||||||
@ -180,6 +180,14 @@ fn request(method: &'static Method, path: String, redirect: bool, quarantine: bo
|
|||||||
client.headers_map.get("x-reddit-loid").cloned().unwrap_or_default(),
|
client.headers_map.get("x-reddit-loid").cloned().unwrap_or_default(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Replace "Android" with a tricky word.
|
||||||
|
// Issues: #78/#115, #116
|
||||||
|
// If you include the word "Android", you will get a number of different errors
|
||||||
|
// I guess they don't expect mobile traffic on the endpoints we use
|
||||||
|
// Scrawled on wall for next poor soul: Run the test suite.
|
||||||
|
user_agent = user_agent.replace("Android", "Andr\u{200B}oid");
|
||||||
|
|
||||||
// Build request to Reddit. When making a GET, request gzip compression.
|
// Build request to Reddit. When making a GET, request gzip compression.
|
||||||
// (Reddit doesn't do brotli yet.)
|
// (Reddit doesn't do brotli yet.)
|
||||||
let builder = Request::builder()
|
let builder = Request::builder()
|
||||||
|
@ -68,6 +68,10 @@ pub struct Config {
|
|||||||
#[serde(alias = "LIBREDDIT_DEFAULT_HIDE_AWARDS")]
|
#[serde(alias = "LIBREDDIT_DEFAULT_HIDE_AWARDS")]
|
||||||
pub(crate) default_hide_awards: Option<String>,
|
pub(crate) default_hide_awards: Option<String>,
|
||||||
|
|
||||||
|
#[serde(rename = "REDLIB_DEFAULT_HIDE_SIDEBAR_AND_SUMMARY")]
|
||||||
|
#[serde(alias = "LIBREDDIT_DEFAULT_HIDE_SIDEBAR_AND_SUMMARY")]
|
||||||
|
pub(crate) default_hide_sidebar_and_summary: Option<String>,
|
||||||
|
|
||||||
#[serde(rename = "REDLIB_DEFAULT_HIDE_SCORE")]
|
#[serde(rename = "REDLIB_DEFAULT_HIDE_SCORE")]
|
||||||
#[serde(alias = "LIBREDDIT_DEFAULT_HIDE_SCORE")]
|
#[serde(alias = "LIBREDDIT_DEFAULT_HIDE_SCORE")]
|
||||||
pub(crate) default_hide_score: Option<String>,
|
pub(crate) default_hide_score: Option<String>,
|
||||||
@ -125,8 +129,9 @@ impl Config {
|
|||||||
default_show_nsfw: parse("REDLIB_DEFAULT_SHOW_NSFW"),
|
default_show_nsfw: parse("REDLIB_DEFAULT_SHOW_NSFW"),
|
||||||
default_blur_nsfw: parse("REDLIB_DEFAULT_BLUR_NSFW"),
|
default_blur_nsfw: parse("REDLIB_DEFAULT_BLUR_NSFW"),
|
||||||
default_use_hls: parse("REDLIB_DEFAULT_USE_HLS"),
|
default_use_hls: parse("REDLIB_DEFAULT_USE_HLS"),
|
||||||
default_hide_hls_notification: parse("REDLIB_DEFAULT_HIDE_HLS"),
|
default_hide_hls_notification: parse("REDLIB_DEFAULT_HIDE_HLS_NOTIFICATION"),
|
||||||
default_hide_awards: parse("REDLIB_DEFAULT_HIDE_AWARDS"),
|
default_hide_awards: parse("REDLIB_DEFAULT_HIDE_AWARDS"),
|
||||||
|
default_hide_sidebar_and_summary: parse("REDLIB_DEFAULT_HIDE_SIDEBAR_AND_SUMMARY"),
|
||||||
default_hide_score: parse("REDLIB_DEFAULT_HIDE_SCORE"),
|
default_hide_score: parse("REDLIB_DEFAULT_HIDE_SCORE"),
|
||||||
default_subscriptions: parse("REDLIB_DEFAULT_SUBSCRIPTIONS"),
|
default_subscriptions: parse("REDLIB_DEFAULT_SUBSCRIPTIONS"),
|
||||||
default_disable_visit_reddit_confirmation: parse("REDLIB_DEFAULT_DISABLE_VISIT_REDDIT_CONFIRMATION"),
|
default_disable_visit_reddit_confirmation: parse("REDLIB_DEFAULT_DISABLE_VISIT_REDDIT_CONFIRMATION"),
|
||||||
@ -151,6 +156,7 @@ fn get_setting_from_config(name: &str, config: &Config) -> Option<String> {
|
|||||||
"REDLIB_DEFAULT_HIDE_HLS_NOTIFICATION" => config.default_hide_hls_notification.clone(),
|
"REDLIB_DEFAULT_HIDE_HLS_NOTIFICATION" => config.default_hide_hls_notification.clone(),
|
||||||
"REDLIB_DEFAULT_WIDE" => config.default_wide.clone(),
|
"REDLIB_DEFAULT_WIDE" => config.default_wide.clone(),
|
||||||
"REDLIB_DEFAULT_HIDE_AWARDS" => config.default_hide_awards.clone(),
|
"REDLIB_DEFAULT_HIDE_AWARDS" => config.default_hide_awards.clone(),
|
||||||
|
"REDLIB_DEFAULT_HIDE_SIDEBAR_AND_SUMMARY" => config.default_hide_awards.clone(),
|
||||||
"REDLIB_DEFAULT_HIDE_SCORE" => config.default_hide_score.clone(),
|
"REDLIB_DEFAULT_HIDE_SCORE" => config.default_hide_score.clone(),
|
||||||
"REDLIB_DEFAULT_SUBSCRIPTIONS" => config.default_subscriptions.clone(),
|
"REDLIB_DEFAULT_SUBSCRIPTIONS" => config.default_subscriptions.clone(),
|
||||||
"REDLIB_DEFAULT_DISABLE_VISIT_REDDIT_CONFIRMATION" => config.default_disable_visit_reddit_confirmation.clone(),
|
"REDLIB_DEFAULT_DISABLE_VISIT_REDDIT_CONFIRMATION" => config.default_disable_visit_reddit_confirmation.clone(),
|
||||||
|
@ -151,7 +151,7 @@ pub async fn item(req: Request<Body>) -> Result<Response<Body>, String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if have_after {
|
if have_after {
|
||||||
before = "t3_".to_owned();
|
"t3_".clone_into(&mut before);
|
||||||
before.push_str(&duplicates[0].id);
|
before.push_str(&duplicates[0].id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +161,7 @@ pub async fn item(req: Request<Body>) -> Result<Response<Body>, String> {
|
|||||||
if have_before {
|
if have_before {
|
||||||
// The next batch will need to start from one after the
|
// The next batch will need to start from one after the
|
||||||
// last post in the current batch.
|
// last post in the current batch.
|
||||||
after = "t3_".to_owned();
|
"t3_".clone_into(&mut after);
|
||||||
after.push_str(&duplicates[l - 1].id);
|
after.push_str(&duplicates[l - 1].id);
|
||||||
|
|
||||||
// Here is where things get terrible. Notice that we
|
// 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 {
|
match json(new_path, true).await {
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
if !response[1]["data"]["children"].as_array().unwrap_or(&Vec::new()).is_empty() {
|
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);
|
before.push_str(&duplicates[0].id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,44 @@
|
|||||||
// Filled in with real app versions
|
// Filled in with real app versions
|
||||||
pub static _IOS_APP_VERSION_LIST: &[&str; 1] = &[""];
|
pub static _IOS_APP_VERSION_LIST: &[&str; 1] = &[""];
|
||||||
pub static ANDROID_APP_VERSION_LIST: &[&str; 150] = &[
|
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.28.0/Build 1046887",
|
||||||
"Version 2023.29.0/Build 1059855",
|
"Version 2023.29.0/Build 1059855",
|
||||||
"Version 2023.30.0/Build 1078734",
|
"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.44.0/Build 1268622",
|
||||||
"Version 2023.45.0/Build 1281371",
|
"Version 2023.45.0/Build 1281371",
|
||||||
"Version 2023.47.0/Build 1303604",
|
"Version 2023.47.0/Build 1303604",
|
||||||
"Version 2023.48.0/Build 1319123",
|
"Version 2022.42.0/Build 638508",
|
||||||
"Version 2023.49.0/Build 1321715",
|
"Version 2022.43.0/Build 648277",
|
||||||
"Version 2023.49.1/Build 1322281",
|
"Version 2022.44.0/Build 664348",
|
||||||
"Version 2023.50.0/Build 1332338",
|
"Version 2022.45.0/Build 677985",
|
||||||
"Version 2023.50.1/Build 1345844",
|
"Version 2023.01.0/Build 709875",
|
||||||
"Version 2024.02.0/Build 1368985",
|
"Version 2023.02.0/Build 717912",
|
||||||
"Version 2024.03.0/Build 1379408",
|
"Version 2023.03.0/Build 729220",
|
||||||
"Version 2024.04.0/Build 1391236",
|
"Version 2023.04.0/Build 744681",
|
||||||
"Version 2023.05.0/Build 755453",
|
"Version 2023.05.0/Build 755453",
|
||||||
"Version 2023.06.0/Build 775017",
|
"Version 2023.06.0/Build 775017",
|
||||||
"Version 2023.07.0/Build 788827",
|
"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.19.0/Build 927681",
|
||||||
"Version 2023.20.0/Build 943980",
|
"Version 2023.20.0/Build 943980",
|
||||||
"Version 2023.20.1/Build 946732",
|
"Version 2023.20.1/Build 946732",
|
||||||
"Version 2023.21.0/Build 956283",
|
"Version 2022.20.0/Build 487703",
|
||||||
"Version 2023.22.0/Build 968223",
|
"Version 2022.21.0/Build 492436",
|
||||||
"Version 2023.23.0/Build 983896",
|
"Version 2022.22.0/Build 498700",
|
||||||
"Version 2023.24.0/Build 998541",
|
"Version 2022.23.0/Build 502374",
|
||||||
"Version 2023.25.0/Build 1014750",
|
"Version 2022.23.1/Build 506606",
|
||||||
"Version 2023.25.1/Build 1018737",
|
"Version 2022.24.0/Build 510950",
|
||||||
"Version 2023.26.0/Build 1019073",
|
"Version 2022.24.1/Build 513462",
|
||||||
"Version 2023.27.0/Build 1031923",
|
"Version 2022.25.0/Build 515072",
|
||||||
"Version 2022.25.1/Build 516394",
|
"Version 2022.25.1/Build 516394",
|
||||||
"Version 2022.25.2/Build 519915",
|
"Version 2022.25.2/Build 519915",
|
||||||
"Version 2022.26.0/Build 521193",
|
"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.40.0/Build 624782",
|
||||||
"Version 2022.41.0/Build 630468",
|
"Version 2022.41.0/Build 630468",
|
||||||
"Version 2022.41.1/Build 634168",
|
"Version 2022.41.1/Build 634168",
|
||||||
"Version 2022.42.0/Build 638508",
|
"Version 2021.39.1/Build 372418",
|
||||||
"Version 2022.43.0/Build 648277",
|
"Version 2021.41.0/Build 376052",
|
||||||
"Version 2022.44.0/Build 664348",
|
"Version 2021.42.0/Build 378193",
|
||||||
"Version 2022.45.0/Build 677985",
|
"Version 2021.43.0/Build 382019",
|
||||||
"Version 2023.01.0/Build 709875",
|
"Version 2021.44.0/Build 385129",
|
||||||
"Version 2023.02.0/Build 717912",
|
"Version 2021.45.0/Build 387663",
|
||||||
"Version 2023.03.0/Build 729220",
|
"Version 2021.46.0/Build 392043",
|
||||||
"Version 2023.04.0/Build 744681",
|
"Version 2021.47.0/Build 394342",
|
||||||
"Version 2022.10.0/Build 429896",
|
"Version 2022.10.0/Build 429896",
|
||||||
"Version 2022.1.0/Build 402829",
|
"Version 2022.1.0/Build 402829",
|
||||||
"Version 2022.11.0/Build 433004",
|
"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.17.0/Build 468480",
|
||||||
"Version 2022.18.0/Build 473740",
|
"Version 2022.18.0/Build 473740",
|
||||||
"Version 2022.19.1/Build 482464",
|
"Version 2022.19.1/Build 482464",
|
||||||
"Version 2022.20.0/Build 487703",
|
|
||||||
"Version 2022.2.0/Build 405543",
|
"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.3.0/Build 408637",
|
||||||
"Version 2022.4.0/Build 411368",
|
"Version 2022.4.0/Build 411368",
|
||||||
"Version 2022.5.0/Build 414731",
|
"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.7.0/Build 420849",
|
||||||
"Version 2022.8.0/Build 423906",
|
"Version 2022.8.0/Build 423906",
|
||||||
"Version 2022.9.0/Build 426592",
|
"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] = &[""];
|
pub static _IOS_OS_VERSION_LIST: &[&str; 1] = &[""];
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use brotli::enc::{BrotliCompress, BrotliEncoderParams};
|
use brotli::enc::{BrotliCompress, BrotliEncoderParams};
|
||||||
use cached::proc_macro::cached;
|
use cached::proc_macro::cached;
|
||||||
use cookie::Cookie;
|
use cookie::Cookie;
|
||||||
@ -15,6 +17,7 @@ use libflate::gzip;
|
|||||||
use route_recognizer::{Params, Router};
|
use route_recognizer::{Params, Router};
|
||||||
use std::{
|
use std::{
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
|
fmt::Display,
|
||||||
io,
|
io,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
result::Result,
|
result::Result,
|
||||||
@ -65,12 +68,12 @@ impl CompressionType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToString for CompressionType {
|
impl Display for CompressionType {
|
||||||
fn to_string(&self) -> String {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Gzip => "gzip".to_string(),
|
Self::Gzip => write!(f, "gzip"),
|
||||||
Self::Brotli => "br".to_string(),
|
Self::Brotli => write!(f, "br"),
|
||||||
Self::Passthrough => String::new(),
|
Self::Passthrough => Ok(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ struct SettingsTemplate {
|
|||||||
|
|
||||||
// CONSTANTS
|
// CONSTANTS
|
||||||
|
|
||||||
const PREFS: [&str; 15] = [
|
const PREFS: [&str; 16] = [
|
||||||
"theme",
|
"theme",
|
||||||
"front_page",
|
"front_page",
|
||||||
"layout",
|
"layout",
|
||||||
@ -31,6 +31,7 @@ const PREFS: [&str; 15] = [
|
|||||||
"use_hls",
|
"use_hls",
|
||||||
"hide_hls_notification",
|
"hide_hls_notification",
|
||||||
"autoplay_videos",
|
"autoplay_videos",
|
||||||
|
"hide_sidebar_and_summary",
|
||||||
"fixed_navbar",
|
"fixed_navbar",
|
||||||
"hide_awards",
|
"hide_awards",
|
||||||
"hide_score",
|
"hide_score",
|
||||||
|
@ -7,6 +7,8 @@ use askama::Template;
|
|||||||
use cookie::Cookie;
|
use cookie::Cookie;
|
||||||
use hyper::{Body, Request, Response};
|
use hyper::{Body, Request, Response};
|
||||||
|
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use regex::Regex;
|
||||||
use time::{Duration, OffsetDateTime};
|
use time::{Duration, OffsetDateTime};
|
||||||
|
|
||||||
// STRUCTS
|
// STRUCTS
|
||||||
@ -50,10 +52,13 @@ struct WallTemplate {
|
|||||||
url: String,
|
url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GEO_FILTER_MATCH: Lazy<Regex> = Lazy::new(|| Regex::new(r"geo_filter=(?<region>\w+)").unwrap());
|
||||||
|
|
||||||
// SERVICES
|
// SERVICES
|
||||||
pub async fn community(req: Request<Body>) -> Result<Response<Body>, String> {
|
pub async fn community(req: Request<Body>) -> Result<Response<Body>, String> {
|
||||||
// Build Reddit API path
|
// Build Reddit API path
|
||||||
let root = req.uri().path() == "/";
|
let root = req.uri().path() == "/";
|
||||||
|
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 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());
|
||||||
@ -107,7 +112,11 @@ pub async fn community(req: Request<Body>) -> Result<Response<Body>, String> {
|
|||||||
|
|
||||||
let mut params = String::from("&raw_json=1");
|
let mut params = String::from("&raw_json=1");
|
||||||
if sub_name == "popular" {
|
if sub_name == "popular" {
|
||||||
params.push_str("&geo_filter=GLOBAL");
|
let geo_filter = match GEO_FILTER_MATCH.captures(&query) {
|
||||||
|
Some(geo_filter) => geo_filter["region"].to_string(),
|
||||||
|
None => "GLOBAL".to_owned(),
|
||||||
|
};
|
||||||
|
params.push_str(&format!("&geo_filter={geo_filter}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = format!("/r/{sub_name}/{sort}.json?{}{params}", req.uri().query().unwrap_or_default());
|
let path = format!("/r/{sub_name}/{sort}.json?{}{params}", req.uri().query().unwrap_or_default());
|
||||||
|
58
src/utils.rs
58
src/utils.rs
@ -577,6 +577,7 @@ pub struct Preferences {
|
|||||||
pub show_nsfw: String,
|
pub show_nsfw: String,
|
||||||
pub blur_nsfw: String,
|
pub blur_nsfw: String,
|
||||||
pub hide_hls_notification: String,
|
pub hide_hls_notification: String,
|
||||||
|
pub hide_sidebar_and_summary: String,
|
||||||
pub use_hls: String,
|
pub use_hls: String,
|
||||||
pub autoplay_videos: String,
|
pub autoplay_videos: String,
|
||||||
pub fixed_navbar: String,
|
pub fixed_navbar: String,
|
||||||
@ -611,6 +612,7 @@ impl Preferences {
|
|||||||
layout: setting(req, "layout"),
|
layout: setting(req, "layout"),
|
||||||
wide: setting(req, "wide"),
|
wide: setting(req, "wide"),
|
||||||
show_nsfw: setting(req, "show_nsfw"),
|
show_nsfw: setting(req, "show_nsfw"),
|
||||||
|
hide_sidebar_and_summary: setting(req, "hide_sidebar_and_summary"),
|
||||||
blur_nsfw: setting(req, "blur_nsfw"),
|
blur_nsfw: setting(req, "blur_nsfw"),
|
||||||
use_hls: setting(req, "use_hls"),
|
use_hls: setting(req, "use_hls"),
|
||||||
hide_hls_notification: setting(req, "hide_hls_notification"),
|
hide_hls_notification: setting(req, "hide_hls_notification"),
|
||||||
@ -875,9 +877,9 @@ pub fn format_url(url: &str) -> String {
|
|||||||
|
|
||||||
// These are links we want to replace in-body
|
// 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_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 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());
|
static REDLIB_PREVIEW_TEXT_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r">(.*?)</a>").unwrap());
|
||||||
|
|
||||||
// Rewrite Reddit links to Redlib in body of text
|
// Rewrite Reddit links to Redlib in body of text
|
||||||
@ -901,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 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_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(">>", ">");
|
/* 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.
|
||||||
let image_replacement = format!("<a href=\"{image_url}<img src=\"{image_url}</a>");
|
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. "\"" is how the quotes are formatted within image_text beforehand
|
||||||
|
image_caption = image_caption.replace("\\"", "\"");
|
||||||
|
|
||||||
|
_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
|
text1 = REDDIT_PREVIEW_REGEX
|
||||||
.replace(&text1, formatted_url)
|
.replace(&text1, format!("{_preview_type}$2"))
|
||||||
.replace(&image_to_replace, &image_replacement)
|
.replace(&image_to_replace, &_image_replacement)
|
||||||
.to_string()
|
.to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1164,11 +1199,8 @@ async fn test_fetching_ws() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rewriting_image_links() {
|
fn test_rewriting_image_links() {
|
||||||
let input = r#"<p><a href="https://preview.redd.it/zq21ggkj2xo31.png?width=2560&format=png&auto=webp&s=539d8050628ec1190cac26468fe99cc66b6071ab">https://preview.redd.it/zq21ggkj2xo31.png?width=2560&format=png&auto=webp&s=539d8050628ec1190cac26468fe99cc66b6071ab</a></p>
|
let input =
|
||||||
<p><a href="https://preview.redd.it/vty9ocij2xo31.png?width=2560&format=png&auto=webp&s=fc7c7ef993a5e9ef656d5f5d9cf8290a0a1df877">https://preview.redd.it/vty9ocij2xo31.png?width=2560&format=png&auto=webp&s=fc7c7ef993a5e9ef656d5f5d9cf8290a0a1df877</a></p>
|
r#"<p><a href="https://preview.redd.it/6awags382xo31.png?width=2560&format=png&auto=webp&s=9c563aed4f07a91bdd249b5a3cea43a79710dcfc">caption 1</a></p>"#;
|
||||||
<p><a href="https://preview.redd.it/bdfdxkjj2xo31.png?width=2560&format=png&auto=webp&s=d0fa420ece27605e882e89cb4711d75d774322ac">https://preview.redd.it/bdfdxkjj2xo31.png?width=2560&format=png&auto=webp&s=d0fa420ece27605e882e89cb4711d75d774322ac</a></p>
|
let output = r#"<p><figure><a href="/preview/pre/6awags382xo31.png?width=2560&format=png&auto=webp&s=9c563aed4f07a91bdd249b5a3cea43a79710dcfc"><img loading="lazy" src="/preview/pre/6awags382xo31.png?width=2560&format=png&auto=webp&s=9c563aed4f07a91bdd249b5a3cea43a79710dcfc"></a><figcaption>caption 1</figcaption></figure></p"#;
|
||||||
<p><a href="https://preview.redd.it/6awags382xo31.png?width=2560&format=png&auto=webp&s=9c563aed4f07a91bdd249b5a3cea43a79710dcfc">caption 1</a></p>
|
|
||||||
<p><a href="https://preview.redd.it/rbu2ca2b2xo31.png?width=2560&format=png&auto=webp&s=afb538cf784d2e339de9a91aba5dc9c92e47988f">caption 2</a></p>"#;
|
|
||||||
let output = r#"<p><a href="/preview/pre/zq21ggkj2xo31.png?width=2560&format=png&auto=webp&s=539d8050628ec1190cac26468fe99cc66b6071ab"><img src="/preview/pre/zq21ggkj2xo31.png?width=2560&format=png&auto=webp&s=539d8050628ec1190cac26468fe99cc66b6071ab"></a></p> <p><a href="/preview/pre/vty9ocij2xo31.png?width=2560&format=png&auto=webp&s=fc7c7ef993a5e9ef656d5f5d9cf8290a0a1df877"><img src="/preview/pre/vty9ocij2xo31.png?width=2560&format=png&auto=webp&s=fc7c7ef993a5e9ef656d5f5d9cf8290a0a1df877"></a></p> <p><a href="/preview/pre/bdfdxkjj2xo31.png?width=2560&format=png&auto=webp&s=d0fa420ece27605e882e89cb4711d75d774322ac"><img src="/preview/pre/bdfdxkjj2xo31.png?width=2560&format=png&auto=webp&s=d0fa420ece27605e882e89cb4711d75d774322ac"></a></p> <p><a href="/preview/pre/6awags382xo31.png?width=2560&format=png&auto=webp&s=9c563aed4f07a91bdd249b5a3cea43a79710dcfc"><img src="/preview/pre/6awags382xo31.png?width=2560&format=png&auto=webp&s=9c563aed4f07a91bdd249b5a3cea43a79710dcfc"></a></p> <p><a href="/preview/pre/rbu2ca2b2xo31.png?width=2560&format=png&auto=webp&s=afb538cf784d2e339de9a91aba5dc9c92e47988f"><img src="/preview/pre/rbu2ca2b2xo31.png?width=2560&format=png&auto=webp&s=afb538cf784d2e339de9a91aba5dc9c92e47988f"></a></p>"#;
|
|
||||||
assert_eq!(rewrite_urls(input), output);
|
assert_eq!(rewrite_urls(input), output);
|
||||||
}
|
}
|
||||||
|
@ -187,6 +187,11 @@ nav #redlib {
|
|||||||
vertical-align: -2px;
|
vertical-align: -2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
figcaption {
|
||||||
|
margin-top: 5px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
#settings_link {
|
#settings_link {
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
@ -979,10 +984,6 @@ a.search_subreddit:hover {
|
|||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gallery figcaption {
|
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gallery .outbound_url {
|
.gallery .outbound_url {
|
||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
@ -1010,6 +1011,9 @@ a.search_subreddit:hover {
|
|||||||
|
|
||||||
.post_body img {
|
.post_body img {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.post_poll {
|
.post_poll {
|
||||||
@ -1098,7 +1102,7 @@ a.search_subreddit:hover {
|
|||||||
display: auto;
|
display: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (min-width: 480px) {
|
@media screen and (min-width: 481px) {
|
||||||
#post_links > li.mobile_item {
|
#post_links > li.mobile_item {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@ -1187,6 +1191,10 @@ a.search_subreddit:hover {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.comment figure {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.comment_left, .comment_right {
|
.comment_left, .comment_right {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -1484,10 +1492,19 @@ input[type="submit"] {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.md > *:not(:first-child) {
|
.md > p:not(:first-child):not(:last-child) {
|
||||||
margin-top: 20px;
|
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 h1 { font-size: 22px; }
|
||||||
.md h2 { font-size: 20px; }
|
.md h2 { font-size: 20px; }
|
||||||
.md h3 { font-size: 18px; }
|
.md h3 { font-size: 18px; }
|
||||||
|
14
static/themes/icebergDark.css
Normal file
14
static/themes/icebergDark.css
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/* icebergDark theme setting */
|
||||||
|
.icebergDark {
|
||||||
|
--accent: #85a0c7;
|
||||||
|
--green: #b5bf82;
|
||||||
|
--text: #c6c8d1;
|
||||||
|
--foreground: #454d73;
|
||||||
|
--background: #161821;
|
||||||
|
--outside: #1f2233;
|
||||||
|
--post: #1f2233;
|
||||||
|
--panel-border: 1px solid #454d73;
|
||||||
|
--highlighted: #0f1117;
|
||||||
|
--visited: #0f1117;
|
||||||
|
--shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
@ -71,11 +71,16 @@
|
|||||||
<input type="hidden" value="off" name="autoplay_videos">
|
<input type="hidden" value="off" name="autoplay_videos">
|
||||||
<input type="checkbox" name="autoplay_videos" id="autoplay_videos" {% if prefs.autoplay_videos == "on" %}checked{% endif %}>
|
<input type="checkbox" name="autoplay_videos" id="autoplay_videos" {% if prefs.autoplay_videos == "on" %}checked{% endif %}>
|
||||||
</div>
|
</div>
|
||||||
<div class="prefs-group">
|
<div class="prefs-group">
|
||||||
<label for="fixed_navbar">Keep navbar fixed</label>
|
<label for="fixed_navbar">Keep navbar fixed</label>
|
||||||
<input type="hidden" value="off" name="fixed_navbar">
|
<input type="hidden" value="off" name="fixed_navbar">
|
||||||
<input type="checkbox" name="fixed_navbar" {% if prefs.fixed_navbar == "on" %}checked{% endif %}>
|
<input type="checkbox" name="fixed_navbar" {% if prefs.fixed_navbar == "on" %}checked{% endif %}>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="prefs-group">
|
||||||
|
<label for="hide_sidebar_and_summary">Hide the summary and sidebar</label>
|
||||||
|
<input type="hidden" value="off" name="hide_sidebar_and_summary">
|
||||||
|
<input type="checkbox" name="hide_sidebar_and_summary" {% if prefs.hide_sidebar_and_summary == "on" %}checked{% endif %}>
|
||||||
|
</div>
|
||||||
<div class="prefs-group">
|
<div class="prefs-group">
|
||||||
<label for="use_hls">Use HLS for videos</label>
|
<label for="use_hls">Use HLS for videos</label>
|
||||||
<details id="feeds">
|
<details id="feeds">
|
||||||
|
@ -82,7 +82,7 @@
|
|||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if is_filtered || (!sub.name.is_empty() && sub.name != "all" && sub.name != "popular" && !sub.name.contains("+")) %}
|
{% if is_filtered || (!sub.name.is_empty() && sub.name != "all" && sub.name != "popular" && !sub.name.contains("+")) && prefs.hide_sidebar_and_summary != "on" %}
|
||||||
<aside>
|
<aside>
|
||||||
{% if is_filtered %}
|
{% if is_filtered %}
|
||||||
<center>(Content from r/{{ sub.name }} has been filtered)</center>
|
<center>(Content from r/{{ sub.name }} has been filtered)</center>
|
||||||
|
Loading…
Reference in New Issue
Block a user