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; #[derive(Deserialize)] pub struct StoryParams { id: Option, chapter: Option, } pub async fn render(Query(params): Query) -> Markup { if let Some(id) = params.id { //let story = state.wattpad.get_story(id.as_str()).await; let story = get_story(id.as_str()).await; if let Ok(story) = story { if let Some(part_idx) = params.chapter { let part = story.get_part(part_idx).await; if let Ok(part) = part { let style_matching_regex = Regex::new("style=\"(.+?)\"").unwrap(); html! { (DOCTYPE) html { head { meta name="viewport" content="width=device-width, initial-scale=1.0"; style {(PreEscaped( grass::include!("./css/index.scss") ))} script {(PreEscaped( include_str!("../../scripts/StoryContent.js") ))} } body { (Header({ let mut story_parts: Vec = story._parts.iter().enumerate().map(|(idx, part)| HeaderLink { path: format!("/story?id={}&chapter={}", story.id, idx), name: part.title.clone(), prefix: None, postfix: None }).collect(); story_parts.insert(0, HeaderLink { path: format!("/story?id={}", story.id), name: "Details".to_string(), prefix: None, postfix: Some("|".to_string()) }); story_parts.insert(0, HeaderLink { path: "/".to_string(), name: "Homepage".to_string(), prefix: None, postfix: None }); story_parts }, format!("/story?id={}&chapter={}", story.id, part_idx))) div .story-content { @for paragraph in part.get_paragraphs().expect("Failed to get paragraphs of part") { p style=({ let attributes = paragraph.attributes.unwrap_or_default(); let captures = style_matching_regex.captures(attributes.as_str()); match captures { Some(e) => e.get(1).unwrap().as_str().to_string(), None => String::default() } }) { (PreEscaped(paragraph.html)) } } } div .story-nav { @if part_idx > 0 { a href=(format!("/story?id={}&chapter={}", story.id, part_idx-1)) { "<" } } " | " @if part_idx < story._parts.len() - 1 { a href=(format!("/story?id={}&chapter={}", story.id, part_idx+1)) { ">" } } } } } } } else { html! { h1 { "Err: Chapter not found" } } } } else { html! { (DOCTYPE) html { head { meta name="viewport" content="width=device-width, initial-scale=1.0"; style {(PreEscaped( grass::include!("./css/index.scss") ))} script {(PreEscaped( include_str!("../../scripts/StoryDetails.js") ))} } body { (Header({ let mut story_parts: Vec = story._parts.iter().enumerate().map(|(idx, part)| HeaderLink { path: format!("/story?id={}&chapter={}", story.id, idx), name: part.title.clone(), prefix: None, postfix: None }).collect(); story_parts.insert(0, HeaderLink { path: format!("/story?id={}", story.id), name: "Details".to_string(), prefix: None, postfix: Some("|".to_string()) }); story_parts.insert(0, HeaderLink { path: "/".to_string(), name: "Homepage".to_string(), prefix: None, postfix: None }); story_parts }, format!("/story?id={}", story.id))) div .story-page-container { div .story-page { img .story-cover #storycover src=(story.cover); div .story-details { h3 #storyname { (story.title) } p { (PreEscaped(story.description.replace("\n", "
"))) } p { "Original URL: " a href=(story.url) { (story.url) } br; "Author: " a href=(format!("/user?name={}", story._user.fullname)) {(story._user.name)} br; "© " (story.copyright) } div .tag-container { @for tag in story.tags { div .tag { a href=(format!("/search?query={}&type=tag", tag)) { "#"(tag) } } } } } } div .story-buttons #detail-buttons { button #favorite { "Save Story" } } } } } } } } else { html! { h1 { "Err: Story not found" } } } } else { html! { h1 { "Err: Story not specified" } } } }