From b3cf350d3feab21c78fbec30bd58f252c9991860 Mon Sep 17 00:00:00 2001 From: Ruthenic Date: Fri, 17 Mar 2023 12:41:52 -0400 Subject: [PATCH] stuff --- .cargo/config.toml | 3 +++ Cargo.lock | 5 ++-- Cargo.toml | 5 ++-- css/index.scss | 1 + scripts/History.js | 53 ++++++++++++++++++++++++++++++++++++ src/cached_wattpad.rs | 2 +- src/main.rs | 6 ++++- src/routes/history.rs | 60 +++++++++++++++++++++++++++++++++++++++++ src/routes/index.rs | 4 ++- src/routes/mod.rs | 1 + src/routes/not_found.rs | 1 + src/routes/story.rs | 2 ++ src/web_api.rs | 17 ++++++++++++ 13 files changed, 153 insertions(+), 7 deletions(-) create mode 100644 .cargo/config.toml create mode 100644 scripts/History.js create mode 100644 src/routes/history.rs create mode 100644 src/web_api.rs diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..0c38d57 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,3 @@ +[target.x86_64-unknown-linux-gnu] +linker = "clang" +rustflags = ["-C", "link-arg=-fuse-ld=/usr/bin/mold"] diff --git a/Cargo.lock b/Cargo.lock index 8aa65a0..ab124ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1923,6 +1923,7 @@ dependencies = [ "maud", "regex", "serde", + "serde_json", "tokio", "tracing", "tracing-subscriber", @@ -2019,9 +2020,9 @@ checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "wattpad" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9826298a0db9284b994af09fef8a564840af0e9e2621440aef46a5bd066481ed" +checksum = "3d03f3af6f6244f85e6dd6a3981677de18daf8b8e1d8fd1d35642d47fc2a4e3f" dependencies = [ "anyhow", "regex", diff --git a/Cargo.toml b/Cargo.toml index 43ccd9f..0e0207a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] anyhow = "1.0.69" -axum = { version = "0.6.10", features = ["macros"] } +axum = { version = "0.6.10", features = ["macros", "json"] } cached = "0.42.0" chrono = "0.4.24" grass = { version = "0.12.3", features = ["macro"] } @@ -15,7 +15,8 @@ lazy_static = "1.4.0" maud = { git = "https://github.com/lambda-fairy/maud", features = ["axum"] } regex = "1.7.1" serde = { version = "1.0.152", features = ["derive"] } +serde_json = "1.0.94" tokio = { version = "1.26.0", features = ["full"] } tracing = "0.1.37" tracing-subscriber = "0.3.16" -wattpad = "0.2.4" +wattpad = "0.2.5" diff --git a/css/index.scss b/css/index.scss index 52182ad..4503e28 100644 --- a/css/index.scss +++ b/css/index.scss @@ -83,6 +83,7 @@ a:hover { .story-details { display: flex; flex-direction: column; + align-self: flex-start; } } diff --git a/scripts/History.js b/scripts/History.js new file mode 100644 index 0000000..95e4c55 --- /dev/null +++ b/scripts/History.js @@ -0,0 +1,53 @@ +const oldOnloadHandler = window.onload ?? (() => {}); + +async function historyLoad() { + const historyDiv = document.getElementById("story-list"); + historyDiv.textContent = ""; + + const readingHistory = JSON.parse( + localStorage.getItem("readingHistory") ?? "[]" + ); + + for (let i = 0; i < readingHistory.length; i++) { + const story = await ( + await fetch(`/api/getStory?id=${readingHistory[i]}`) + ).json(); + + const searchEle = document.createElement("a"); + searchEle.className = "story"; + searchEle.href = + "/story?id=" + + story.id + + (localStorage.getItem(`${story.id}_progress`) + ? `&chapter=${localStorage.getItem(`${story.id}_progress`)}` + : ""); + const coverEle = document.createElement("img"); + coverEle.src = story.cover; + const div = document.createElement("div"); + const titleEle = document.createElement("h3"); + titleEle.textContent = story.title; + div.appendChild(titleEle); + const descEle = document.createElement("p"); + descEle.innerHTML = story.description.replace("\n", "
"); + div.appendChild(descEle); + searchEle.appendChild(coverEle); + searchEle.appendChild(div); + historyDiv?.appendChild(searchEle); + } +} + +window.onload = async () => { + oldOnloadHandler(); + + // render history + await historyLoad(); + + /* // clear history button + const button = document.getElementById("clear-button"); + + button.onclick = async () => { + localStorage.removeItem("readingHistory"); + // rerender history + await historyLoad(); + }; */ +}; diff --git a/src/cached_wattpad.rs b/src/cached_wattpad.rs index 9e650cb..86bf288 100644 --- a/src/cached_wattpad.rs +++ b/src/cached_wattpad.rs @@ -18,7 +18,7 @@ pub async fn get_story(id: &str) -> Result { .get(id) { let time_diff = current_time.signed_duration_since(cache_item.1); - if time_diff.num_minutes() <= 5 { + if time_diff.num_minutes() <= 15 { tracing::debug!("Cache hit for story {}", id); return Ok(cache_item.0.clone()); } diff --git a/src/main.rs b/src/main.rs index 3e674e9..ff0d928 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,9 @@ mod cached_wattpad; mod components; mod routes; +mod web_api; -use routes::{index, not_found, story}; +use routes::{history, index, not_found, story}; use axum::{extract::Extension, routing::get, Router}; use lazy_static::lazy_static; @@ -10,6 +11,7 @@ use maud::{html, Markup}; use std::{net::SocketAddr, sync::Arc}; use tokio::runtime::Runtime; use wattpad::Wattpad; +use web_api::get_story; lazy_static! { pub static ref TOKIO: Runtime = Runtime::new().unwrap(); @@ -25,6 +27,8 @@ fn main() { let app = Router::new() .route("/", get(index::render)) .route("/story", get(story::render)) + .route("/history", get(history::render)) + .route("/api/getStory", get(get_story)) .fallback(not_found::render); tracing::info!("Listening on {}", addr); diff --git a/src/routes/history.rs b/src/routes/history.rs new file mode 100644 index 0000000..77e3000 --- /dev/null +++ b/src/routes/history.rs @@ -0,0 +1,60 @@ +use std::sync::Arc; + +use crate::cached_wattpad::*; +use crate::components::header::{Header, HeaderLink}; +use crate::WATTPAD; +use axum::extract::{Extension, Query, State as AxumState}; +use maud::{html, Markup, PreEscaped, DOCTYPE}; +use regex::Regex; +use serde::Deserialize; + +pub async fn render() -> Markup { + html! { + (DOCTYPE) + title {"Home | Voltpad"}; + meta name="viewport" content="width=device-width, initial-scale=1.0"; + style {(PreEscaped( + grass::include!("./css/index.scss") + ))} + script {(PreEscaped( + include_str!("../../scripts/History.js") + ))} + ( + Header(vec![ + HeaderLink { + name: "Home".to_string(), + path: "/".to_string(), + prefix: None, + postfix: None + }, + HeaderLink { + name: "Search".to_string(), + path: "/search".to_string(), + prefix: None, + postfix: None + }, + HeaderLink { + name: "History".to_string(), + path: "/history".to_string(), + prefix: None, + postfix: None + }, + HeaderLink { + name: "About".to_string(), + path: "/about".to_string(), + prefix: None, + postfix: None + }, + ], "/history".to_string()) + ) + div .index-content { + h1 { "History" } + noscript { + h3 { + "This won't work without JS. Run off now, GNU LibreJS looking motherfuckers." + } + } + div .story-list #story-list; + } + } +} diff --git a/src/routes/index.rs b/src/routes/index.rs index 578ffb3..f007245 100644 --- a/src/routes/index.rs +++ b/src/routes/index.rs @@ -1,10 +1,12 @@ use crate::components::header::{Header, HeaderLink}; use cached::proc_macro::cached; -use maud::{html, Markup, PreEscaped}; +use maud::{html, Markup, PreEscaped, DOCTYPE}; #[cached] pub async fn render() -> Markup { html! { + (DOCTYPE) + title {"Home | Voltpad"}; meta name="viewport" content="width=device-width, initial-scale=1.0"; style {(PreEscaped( grass::include!("./css/index.scss") diff --git a/src/routes/mod.rs b/src/routes/mod.rs index 3ef05d6..f202a11 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -1,3 +1,4 @@ +pub mod history; pub mod index; pub mod not_found; pub mod story; diff --git a/src/routes/not_found.rs b/src/routes/not_found.rs index aeb528b..d475913 100644 --- a/src/routes/not_found.rs +++ b/src/routes/not_found.rs @@ -8,6 +8,7 @@ pub async fn render() -> (StatusCode, Markup) { ( StatusCode::NOT_FOUND, html! { + title {"404 | Voltpad"}; meta name="viewport" content="width=device-width, initial-scale=1.0"; style {(PreEscaped( grass::include!("./css/index.scss") diff --git a/src/routes/story.rs b/src/routes/story.rs index c359103..6b89869 100644 --- a/src/routes/story.rs +++ b/src/routes/story.rs @@ -27,6 +27,7 @@ pub async fn render(Query(params): Query) -> Markup { (DOCTYPE) html { head { + title {(format!("{} | Voltpad", part.title))}; meta name="viewport" content="width=device-width, initial-scale=1.0"; style {(PreEscaped( grass::include!("./css/index.scss") @@ -76,6 +77,7 @@ pub async fn render(Query(params): Query) -> Markup { (DOCTYPE) html { head { + title {(format!("{} | Voltpad", story.title))}; meta name="viewport" content="width=device-width, initial-scale=1.0"; style {(PreEscaped( grass::include!("./css/index.scss") diff --git a/src/web_api.rs b/src/web_api.rs new file mode 100644 index 0000000..4d56449 --- /dev/null +++ b/src/web_api.rs @@ -0,0 +1,17 @@ +use crate::cached_wattpad::get_story as get_story_from_wattpad; +use axum::extract::{Json, Query}; +use serde::Deserialize; +use wattpad::Story; + +#[derive(Deserialize)] +pub struct GetStoryParams { + pub id: String, +} + +pub async fn get_story(Query(params): Query) -> Json { + let story = get_story_from_wattpad(¶ms.id) + .await + .expect("idk jump off a bridge"); + + Json(story) +}