Templatize redirects
This commit is contained in:
parent
0cb7031c36
commit
aa7c8c85df
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -851,9 +851,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "funty"
|
name = "funty"
|
||||||
version = "1.2.0"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1847abb9cb65d566acd5942e94aea9c8f547ad02c98e1649326fc0e8910b8b1e"
|
checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
@ -1200,13 +1200,13 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lexical-core"
|
name = "lexical-core"
|
||||||
version = "0.7.5"
|
version = "0.7.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "21f866863575d0e1d654fbeeabdc927292fdf862873dc3c96c6f753357e13374"
|
checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 0.1.10",
|
||||||
"ryu",
|
"ryu",
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
tab_spaces = 2
|
tab_spaces = 2
|
||||||
hard_tabs = true
|
hard_tabs = true
|
||||||
max_width = 150
|
max_width = 175
|
31
src/main.rs
31
src/main.rs
@ -1,7 +1,3 @@
|
|||||||
// Import Crates
|
|
||||||
// use askama::filters::format;
|
|
||||||
use tide::{Middleware, Next, Request, Response, utils::{After, async_trait}};
|
|
||||||
|
|
||||||
// Reference local files
|
// Reference local files
|
||||||
mod post;
|
mod post;
|
||||||
mod proxy;
|
mod proxy;
|
||||||
@ -11,6 +7,13 @@ mod subreddit;
|
|||||||
mod user;
|
mod user;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
|
// Import Crates
|
||||||
|
use tide::{
|
||||||
|
utils::{async_trait, After},
|
||||||
|
Middleware, Next, Request, Response,
|
||||||
|
};
|
||||||
|
use utils::{error, redirect};
|
||||||
|
|
||||||
// Build middleware
|
// Build middleware
|
||||||
struct HttpsRedirect<HttpsOnly>(HttpsOnly);
|
struct HttpsRedirect<HttpsOnly>(HttpsOnly);
|
||||||
struct NormalizePath;
|
struct NormalizePath;
|
||||||
@ -28,7 +31,7 @@ where
|
|||||||
let mut secured = request.url().to_owned();
|
let mut secured = request.url().to_owned();
|
||||||
secured.set_scheme("https").unwrap_or_default();
|
secured.set_scheme("https").unwrap_or_default();
|
||||||
|
|
||||||
Ok(Response::builder(302).header("Location", secured.to_string()).build())
|
Ok(redirect(secured.to_string()))
|
||||||
} else {
|
} else {
|
||||||
Ok(next.run(request).await)
|
Ok(next.run(request).await)
|
||||||
}
|
}
|
||||||
@ -48,12 +51,7 @@ impl<State: Clone + Send + Sync + 'static> Middleware<State> for NormalizePath {
|
|||||||
|
|
||||||
// Create Services
|
// Create Services
|
||||||
async fn style(_req: Request<()>) -> tide::Result {
|
async fn style(_req: Request<()>) -> tide::Result {
|
||||||
Ok(
|
Ok(Response::builder(200).content_type("text/css").body(include_str!("../static/style.css")).build())
|
||||||
Response::builder(200)
|
|
||||||
.content_type("text/css")
|
|
||||||
.body(include_str!("../static/style.css"))
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Required for creating a PWA
|
// Required for creating a PWA
|
||||||
@ -68,12 +66,7 @@ async fn manifest(_req: Request<()>) -> tide::Result {
|
|||||||
|
|
||||||
// Required for the manifest to be valid
|
// Required for the manifest to be valid
|
||||||
async fn pwa_logo(_req: Request<()>) -> tide::Result {
|
async fn pwa_logo(_req: Request<()>) -> tide::Result {
|
||||||
Ok(
|
Ok(Response::builder(200).content_type("image/png").body(include_bytes!("../static/logo.png").as_ref()).build())
|
||||||
Response::builder(200)
|
|
||||||
.content_type("image/png")
|
|
||||||
.body(include_bytes!("../static/logo.png").as_ref())
|
|
||||||
.build(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Required for iOS App Icons
|
// Required for iOS App Icons
|
||||||
@ -206,12 +199,12 @@ async fn main() -> tide::Result<()> {
|
|||||||
Ok("best") | Ok("hot") | Ok("new") | Ok("top") | Ok("rising") | Ok("controversial") => subreddit::page(req).await,
|
Ok("best") | Ok("hot") | Ok("new") | Ok("top") | Ok("rising") | Ok("controversial") => subreddit::page(req).await,
|
||||||
// Short link for post
|
// Short link for post
|
||||||
Ok(id) if id.len() > 4 && id.len() < 7 => post::item(req).await,
|
Ok(id) if id.len() > 4 && id.len() < 7 => post::item(req).await,
|
||||||
_ => utils::error("Nothing here".to_string()).await
|
_ => error("Nothing here".to_string()).await,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Default service in case no routes match
|
// Default service in case no routes match
|
||||||
app.at("*").get(|_| utils::error("Nothing here".to_string()));
|
app.at("*").get(|_| error("Nothing here".to_string()));
|
||||||
|
|
||||||
app.listen(address).await?;
|
app.listen(address).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
15
src/post.rs
15
src/post.rs
@ -30,18 +30,13 @@ pub async fn item(req: Request<()>) -> tide::Result {
|
|||||||
// If there's no sort query but there's a default sort, set sort to default_sort
|
// If there's no sort query but there's a default sort, set sort to default_sort
|
||||||
if sort.is_empty() && !default_sort.is_empty() {
|
if sort.is_empty() && !default_sort.is_empty() {
|
||||||
sort = default_sort;
|
sort = default_sort;
|
||||||
path = format!(
|
path = format!("{}.json?{}&sort={}&raw_json=1", req.url().path(), req.url().query().unwrap_or_default(), sort);
|
||||||
"{}.json?{}&sort={}&raw_json=1",
|
|
||||||
req.url().path(),
|
|
||||||
req.url().query().unwrap_or_default(),
|
|
||||||
sort
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log the post ID being fetched in debug mode
|
// Log the post ID being fetched in debug mode
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
dbg!(req.param("id").unwrap_or(""));
|
dbg!(req.param("id").unwrap_or(""));
|
||||||
|
|
||||||
let single_thread = &req.param("comment_id").is_ok();
|
let single_thread = &req.param("comment_id").is_ok();
|
||||||
let highlighted_comment = &req.param("comment_id").unwrap_or_default();
|
let highlighted_comment = &req.param("comment_id").unwrap_or_default();
|
||||||
|
|
||||||
@ -160,13 +155,13 @@ async fn parse_comments(json: &serde_json::Value, post_link: &str, post_author:
|
|||||||
} else {
|
} else {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
let parent_kind_and_id = val(&comment, "parent_id");
|
let parent_kind_and_id = val(&comment, "parent_id");
|
||||||
let parent_info = parent_kind_and_id.split("_").collect::<Vec<&str>>();
|
let parent_info = parent_kind_and_id.split("_").collect::<Vec<&str>>();
|
||||||
|
|
||||||
let id = val(&comment, "id");
|
let id = val(&comment, "id");
|
||||||
let highlighted = id == highlighted_comment;
|
let highlighted = id == highlighted_comment;
|
||||||
|
|
||||||
comments.push(Comment {
|
comments.push(Comment {
|
||||||
id,
|
id,
|
||||||
kind: comment["kind"].as_str().unwrap_or_default().to_string(),
|
kind: comment["kind"].as_str().unwrap_or_default().to_string(),
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// CRATES
|
// CRATES
|
||||||
use crate::utils::{prefs, template, Preferences};
|
use crate::utils::{prefs, redirect, template, Preferences};
|
||||||
use askama::Template;
|
use askama::Template;
|
||||||
use tide::{http::Cookie, Request, Response};
|
use tide::{http::Cookie, Request};
|
||||||
use time::{Duration, OffsetDateTime};
|
use time::{Duration, OffsetDateTime};
|
||||||
|
|
||||||
// STRUCTS
|
// STRUCTS
|
||||||
@ -35,11 +35,7 @@ pub async fn get(req: Request<()>) -> tide::Result {
|
|||||||
pub async fn set(mut req: Request<()>) -> tide::Result {
|
pub async fn set(mut req: Request<()>) -> tide::Result {
|
||||||
let form: SettingsForm = req.body_form().await.unwrap_or_default();
|
let form: SettingsForm = req.body_form().await.unwrap_or_default();
|
||||||
|
|
||||||
let mut res = Response::builder(302)
|
let mut res = redirect("/settings".to_string());
|
||||||
.content_type("text/html")
|
|
||||||
.header("Location", "/settings")
|
|
||||||
.body(r#"Redirecting to <a href="/settings">settings</a>..."#)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let names = vec!["theme", "front_page", "layout", "wide", "comment_sort", "show_nsfw"];
|
let names = vec!["theme", "front_page", "layout", "wide", "comment_sort", "show_nsfw"];
|
||||||
let values = vec![form.theme, form.front_page, form.layout, form.wide, form.comment_sort, form.show_nsfw];
|
let values = vec![form.theme, form.front_page, form.layout, form.wide, form.comment_sort, form.show_nsfw];
|
||||||
@ -60,22 +56,16 @@ pub async fn set(mut req: Request<()>) -> tide::Result {
|
|||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Set cookies using response "Set-Cookie" header
|
// Set cookies using response "Set-Cookie" header
|
||||||
pub async fn restore(req: Request<()>) -> tide::Result {
|
pub async fn restore(req: Request<()>) -> tide::Result {
|
||||||
let form: SettingsForm = req.query()?;
|
let form: SettingsForm = req.query()?;
|
||||||
|
|
||||||
|
|
||||||
let path = match form.redirect {
|
let path = match form.redirect {
|
||||||
Some(value) => format!("/{}/", value),
|
Some(value) => format!("/{}/", value),
|
||||||
None => "/".to_string()
|
None => "/".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut res = Response::builder(302)
|
let mut res = redirect(path);
|
||||||
.content_type("text/html")
|
|
||||||
.header("Location", path.to_owned())
|
|
||||||
.body(format!("Redirecting to <a href=\"{0}\">{0}</a>...", path))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
let names = vec!["theme", "front_page", "layout", "wide", "comment_sort", "show_nsfw", "subscriptions"];
|
let names = vec!["theme", "front_page", "layout", "wide", "comment_sort", "show_nsfw", "subscriptions"];
|
||||||
let values = vec![form.theme, form.front_page, form.layout, form.wide, form.comment_sort, form.show_nsfw, form.subscriptions];
|
let values = vec![form.theme, form.front_page, form.layout, form.wide, form.comment_sort, form.show_nsfw, form.subscriptions];
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// CRATES
|
// CRATES
|
||||||
use crate::utils::*;
|
use crate::utils::*;
|
||||||
use askama::Template;
|
use askama::Template;
|
||||||
use tide::{http::Cookie, Request, Response};
|
use tide::{http::Cookie, Request};
|
||||||
use time::{Duration, OffsetDateTime};
|
use time::{Duration, OffsetDateTime};
|
||||||
|
|
||||||
// STRUCTS
|
// STRUCTS
|
||||||
@ -31,18 +31,15 @@ pub async fn page(req: Request<()>) -> tide::Result {
|
|||||||
let front_page = cookie(&req, "front_page");
|
let front_page = cookie(&req, "front_page");
|
||||||
let sort = req.param("sort").unwrap_or_else(|_| req.param("id").unwrap_or("hot")).to_string();
|
let sort = req.param("sort").unwrap_or_else(|_| req.param("id").unwrap_or("hot")).to_string();
|
||||||
|
|
||||||
let sub = req
|
let sub = req.param("sub").map(String::from).unwrap_or(if front_page == "default" || front_page.is_empty() {
|
||||||
.param("sub")
|
if subscribed.is_empty() {
|
||||||
.map(String::from)
|
"popular".to_string()
|
||||||
.unwrap_or(if front_page == "default" || front_page.is_empty() {
|
|
||||||
if subscribed.is_empty() {
|
|
||||||
"popular".to_string()
|
|
||||||
} else {
|
|
||||||
subscribed.to_owned()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
front_page.to_owned()
|
subscribed.to_owned()
|
||||||
});
|
}
|
||||||
|
} else {
|
||||||
|
front_page.to_owned()
|
||||||
|
});
|
||||||
|
|
||||||
let path = format!("/r/{}/{}.json?{}&raw_json=1", sub, sort, req.url().query().unwrap_or_default());
|
let path = format!("/r/{}/{}.json?{}&raw_json=1", sub, sort, req.url().query().unwrap_or_default());
|
||||||
|
|
||||||
@ -112,11 +109,7 @@ pub async fn subscriptions(req: Request<()>) -> tide::Result {
|
|||||||
format!("/r/{}", sub)
|
format!("/r/{}", sub)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut res = Response::builder(302)
|
let mut res = redirect(path);
|
||||||
.content_type("text/html")
|
|
||||||
.header("Location", path.to_owned())
|
|
||||||
.body(format!("Redirecting to <a href=\"{0}\">{0}</a>...", path))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
// Delete cookie if empty, else set
|
// Delete cookie if empty, else set
|
||||||
if sub_list.is_empty() {
|
if sub_list.is_empty() {
|
||||||
@ -165,14 +158,8 @@ async fn subreddit(sub: &str) -> Result<Subreddit, String> {
|
|||||||
let active: i64 = res["data"]["accounts_active"].as_u64().unwrap_or_default() as i64;
|
let active: i64 = res["data"]["accounts_active"].as_u64().unwrap_or_default() as i64;
|
||||||
|
|
||||||
// Fetch subreddit icon either from the community_icon or icon_img value
|
// Fetch subreddit icon either from the community_icon or icon_img value
|
||||||
let community_icon: &str = res["data"]["community_icon"]
|
let community_icon: &str = res["data"]["community_icon"].as_str().map_or("", |s| s.split('?').collect::<Vec<&str>>()[0]);
|
||||||
.as_str()
|
let icon = if community_icon.is_empty() { val(&res, "icon_img") } else { community_icon.to_string() };
|
||||||
.map_or("", |s| s.split('?').collect::<Vec<&str>>()[0]);
|
|
||||||
let icon = if community_icon.is_empty() {
|
|
||||||
val(&res, "icon_img")
|
|
||||||
} else {
|
|
||||||
community_icon.to_string()
|
|
||||||
};
|
|
||||||
|
|
||||||
let sub = Subreddit {
|
let sub = Subreddit {
|
||||||
name: val(&res, "display_name"),
|
name: val(&res, "display_name"),
|
||||||
|
33
src/utils.rs
33
src/utils.rs
@ -162,24 +162,14 @@ pub fn prefs(req: Request<()>) -> Preferences {
|
|||||||
wide: cookie(&req, "wide"),
|
wide: cookie(&req, "wide"),
|
||||||
show_nsfw: cookie(&req, "show_nsfw"),
|
show_nsfw: cookie(&req, "show_nsfw"),
|
||||||
comment_sort: cookie(&req, "comment_sort"),
|
comment_sort: cookie(&req, "comment_sort"),
|
||||||
subscriptions: cookie(&req, "subscriptions")
|
subscriptions: cookie(&req, "subscriptions").split('+').map(String::from).filter(|s| !s.is_empty()).collect(),
|
||||||
.split('+')
|
|
||||||
.map(String::from)
|
|
||||||
.filter(|s| !s.is_empty())
|
|
||||||
.collect(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grab a query param from a url
|
// Grab a query param from a url
|
||||||
pub fn param(path: &str, value: &str) -> String {
|
pub fn param(path: &str, value: &str) -> String {
|
||||||
match Url::parse(format!("https://libredd.it/{}", path).as_str()) {
|
match Url::parse(format!("https://libredd.it/{}", path).as_str()) {
|
||||||
Ok(url) => url
|
Ok(url) => url.query_pairs().into_owned().collect::<HashMap<_, _>>().get(value).unwrap_or(&String::new()).to_owned(),
|
||||||
.query_pairs()
|
|
||||||
.into_owned()
|
|
||||||
.collect::<HashMap<_, _>>()
|
|
||||||
.get(value)
|
|
||||||
.unwrap_or(&String::new())
|
|
||||||
.to_owned(),
|
|
||||||
_ => String::new(),
|
_ => String::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -226,8 +216,8 @@ pub async fn media(data: &Value) -> (String, Media, Vec<GalleryMedia>) {
|
|||||||
} else if data["secure_media"]["reddit_video"]["fallback_url"].is_string() {
|
} else if data["secure_media"]["reddit_video"]["fallback_url"].is_string() {
|
||||||
post_type = "video";
|
post_type = "video";
|
||||||
format_url(data["secure_media"]["reddit_video"]["fallback_url"].as_str().unwrap_or_default())
|
format_url(data["secure_media"]["reddit_video"]["fallback_url"].as_str().unwrap_or_default())
|
||||||
// Handle images, whether GIFs or pics
|
|
||||||
} else if data["post_hint"].as_str().unwrap_or("") == "image" {
|
} else if data["post_hint"].as_str().unwrap_or("") == "image" {
|
||||||
|
// Handle images, whether GIFs or pics
|
||||||
let preview = data["preview"]["images"][0].clone();
|
let preview = data["preview"]["images"][0].clone();
|
||||||
let mp4 = &preview["variants"]["mp4"];
|
let mp4 = &preview["variants"]["mp4"];
|
||||||
if mp4.is_object() {
|
if mp4.is_object() {
|
||||||
@ -438,13 +428,16 @@ pub async fn fetch_posts(path: &str, fallback_title: String) -> Result<(Vec<Post
|
|||||||
// NETWORKING
|
// NETWORKING
|
||||||
//
|
//
|
||||||
|
|
||||||
pub fn template(f: impl Template) -> tide::Result {
|
pub fn template(t: impl Template) -> tide::Result {
|
||||||
Ok(
|
Ok(Response::builder(200).content_type("text/html").body(t.render().unwrap_or_default()).build())
|
||||||
Response::builder(200)
|
}
|
||||||
.content_type("text/html")
|
|
||||||
.body(f.render().unwrap_or_default())
|
pub fn redirect(path: String) -> Response {
|
||||||
.build(),
|
Response::builder(302)
|
||||||
)
|
.content_type("text/html")
|
||||||
|
.header("Location", &path)
|
||||||
|
.body(format!("Redirecting to <a href=\"{0}\">{0}</a>...", path))
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn error(msg: String) -> tide::Result {
|
pub async fn error(msg: String) -> tide::Result {
|
||||||
|
Loading…
Reference in New Issue
Block a user