From 1510fc1641573e98d8ddd345998cd5568cd15c19 Mon Sep 17 00:00:00 2001 From: GitHub Date: Sat, 12 Oct 2024 17:18:06 +0800 Subject: [PATCH] atom.xml --- Cargo.lock | 100 +--------------------------------- Cargo.toml | 5 +- src/controller/inn.rs | 121 +++++++++++++++++------------------------- src/main.rs | 4 +- templates/atom.xml | 25 +++++++++ 5 files changed, 80 insertions(+), 175 deletions(-) create mode 100644 templates/atom.xml diff --git a/Cargo.lock b/Cargo.lock index 2ecafca..cff013c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,21 +75,6 @@ dependencies = [ "url", ] -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - [[package]] name = "arc-swap" version = "1.7.1" @@ -134,9 +119,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a3a5ed3201df5658d1aa45060c5a57dc9dba8a8ada20d696d67cb0c479ee043" dependencies = [ "chrono", - "derive_builder", "diligent-date-parser", - "never", "quick-xml", ] @@ -478,10 +461,7 @@ version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ - "android-tzdata", - "iana-time-zone", "num-traits", - "windows-targets", ] [[package]] @@ -503,12 +483,6 @@ dependencies = [ "static_assertions", ] -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - [[package]] name = "cpufeatures" version = "0.2.14" @@ -628,37 +602,6 @@ dependencies = [ "serde", ] -[[package]] -name = "derive_builder" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" -dependencies = [ - "derive_builder_macro", -] - -[[package]] -name = "derive_builder_core" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "derive_builder_macro" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" -dependencies = [ - "derive_builder_core", - "syn", -] - [[package]] name = "digest" version = "0.10.7" @@ -807,7 +750,6 @@ dependencies = [ "bincode 2.0.0-rc.3", "cached", "captcha", - "chrono", "data-encoding", "fast2s", "garde", @@ -1203,29 +1145,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "iana-time-zone" -version = "0.1.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -1336,11 +1255,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jieba-rs" version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e2b0210dc78b49337af9e49d7ae41a39dceac6e5985613f1cf7763e2f76a25" +source = "git+https://github.com/messense/jieba-rs.git?rev=b39957e#b39957e9a6d738c4b00f3fa645da971ad426ec21" dependencies = [ "cedarwood", - "derive_builder", "fxhash", "lazy_static", "phf", @@ -1636,12 +1553,6 @@ dependencies = [ "jobserver", ] -[[package]] -name = "never" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c96aba5aa877601bb3f6dd6a63a969e1f82e60646e81e71b14496995e9853c91" - [[package]] name = "new_debug_unreachable" version = "1.0.6" @@ -3326,15 +3237,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets", -] - [[package]] name = "windows-registry" version = "0.2.0" diff --git a/Cargo.toml b/Cargo.toml index 841ce0f..320f208 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT License" [dependencies] ammonia = "4.0.0" -atom_syndication = "0.12" +atom_syndication = { version = "0.12", default-features = false } axum = { version = "0.7.5", features = ["http1", "http2", "form", "query", "multipart", "tokio"], default-features = false } axum-extra = { version = "0.9", features = ["typed-header"] } axum_garde = { version = "0.20.0", default-features = false, features = ["form"] } @@ -14,7 +14,6 @@ basic-toml = "*" bincode = "2.0.0-rc.3" cached = { version = "0.53", default-features = false, features = ["proc_macro", "ahash"] } captcha = { version = "0.0", default-features = false } -chrono = { version = "0.4", default-features = false, features = ["clock"] } data-encoding = "*" fast2s = "0.3" garde = { version = "0.20.0", features = ["derive"] } @@ -23,7 +22,7 @@ identicon = { git = "https://github.com/freedit-dev/identicon.git", default-feat image = { version = "0.25.2", default-features = false, features = ["jpeg", "png", "gif"] } img-parts = "0.3.0" indexmap = "2" -jieba-rs = "0.7.0" +jieba-rs = { git = "https://github.com/messense/jieba-rs.git", rev = "b39957e" } jiff = { version = "0.1.13", default-features = false, features = ["std"] } latex2mathml = "0.2.3" mozjpeg = "0.10.10" diff --git a/src/controller/inn.rs b/src/controller/inn.rs index 3530781..f07d4fa 100644 --- a/src/controller/inn.rs +++ b/src/controller/inn.rs @@ -26,10 +26,7 @@ use super::{ Claim, Comment, Feed, FormPost, Inn, InnType, Post, PostContent, PostStatus, SiteConfig, User, }; use crate::{error::AppError, DB}; -use atom_syndication::{ - CategoryBuilder, ContentBuilder, EntryBuilder, FeedBuilder, LinkBuilder, PersonBuilder, Text, - WriteConfig, -}; + use axum::{ extract::{Path, Query}, response::{IntoResponse, Redirect}, @@ -39,7 +36,6 @@ use axum_extra::{headers::Cookie, TypedHeader}; use axum_garde::WithValidation; use bincode::config::standard; use cached::proc_macro::cached; -use chrono::{DateTime, Utc}; use garde::Validate; use jiff::Timestamp; use rinja::filters::{escape, Html}; @@ -47,11 +43,7 @@ use rinja_axum::{into_response, Template}; use serde::Deserialize; use sled::{transaction::ConflictableTransactionError, Transactional}; use sled::{Batch, Db}; -use std::{ - collections::{BTreeSet, HashMap, HashSet}, - path::PathBuf, - sync::LazyLock, -}; +use std::collections::{BTreeSet, HashMap, HashSet}; /// Page data: `inn_create.html` #[derive(Template)] @@ -1155,10 +1147,27 @@ fn recommend_users() -> Result, AppError> { Ok(users) } -static FEED_CONFIG: LazyLock = LazyLock::new(|| WriteConfig { - write_document_declaration: false, - indent_size: Some(2), -}); +/// Page data: `atom.xml` +#[derive(Template)] +#[template(path = "atom.xml")] +struct PageAtom { + domain: String, + title: String, + iid: u32, + categories: Vec, + updated: String, + subtitle: String, + entries: Vec, +} + +struct Entry { + title: String, + iid: u32, + pid: u32, + updated: String, + author: (String, u32), + content: String, +} /// `GET /inn/:iid/atom.xml` inn page pub(crate) async fn inn_feed(Path(i): Path) -> Result { @@ -1177,18 +1186,12 @@ pub(crate) async fn inn_feed(Path(i): Path) -> Result) -> Result) -> Result = DateTime::::from_timestamp(post.created_at, 0).unwrap(); - let entry = EntryBuilder::default() - .authors(vec![PersonBuilder::default() - .name(user.username) - .uri(Some(format!("{}/user/{}", &site_config.domain, user.uid))) - .build()]) - .id(&post_link) - .updated(dt) - .links(vec![LinkBuilder::default() - .rel("alternate".to_owned()) - .mime_type(Some("text/html".to_owned())) - .href(post_link) - .build()]) - .title(Text::plain(post.title)) - .content(Some(ContentBuilder::default().value(Some(content)).build())) - .build(); + let updated = Timestamp::from_second(post.created_at) + .unwrap() + .strftime("%Y-%m-%dT%H:%M:%SZ") + .to_string(); + let entry = Entry { + title: post.title, + iid: post.iid, + pid: post.pid, + updated, + author: (user.username, user.uid), + content, + }; + entries.push(entry); } - let mut feed = FeedBuilder::default() - .title(title) - .subtitle(Some(Text::plain(description))) - .id(&self_link) - .link( - LinkBuilder::default() - .rel("self".to_owned()) - .mime_type(Some("application/atom+xml".to_owned())) - .href(self_link) - .build(), - ) - .link( - LinkBuilder::default() - .rel("alternate".to_owned()) - .mime_type(Some("text/html".to_owned())) - .href(alternate_link) - .build(), - ) - .build(); + let updated = entries[0].updated.clone(); + let page_atom = PageAtom { + domain: site_config.domain, + title, + iid, + categories, + updated, + subtitle: description, + entries, + }; - feed.set_categories(categories); - feed.set_entries(entries); - - let mut output = Vec::new(); - feed.write_with_config(&mut output, *FEED_CONFIG).unwrap(); - - let headers = [( - http::header::CONTENT_TYPE, - http::HeaderValue::from_static("application/xml"), - )]; - - Ok((headers, output)) + Ok(into_response(&page_atom)) } /// get [OutPostList] from pids diff --git a/src/main.rs b/src/main.rs index c859457..20a6d90 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,10 +3,10 @@ #![warn(clippy::pedantic)] // #![warn(clippy::unwrap_used)] -use chrono::Utc; use freedit::{ router, AppError, CONFIG, DB, VERSION, {clear_invalid, cron_feed, Tan}, }; +use jiff::Timestamp; use std::{fs, net::SocketAddr, path::PathBuf}; use tokio::net::TcpListener; use tracing::{error, info, warn}; @@ -89,7 +89,7 @@ fn create_snapshot(db: &sled::Db) { let checksum = db.checksum().unwrap(); info!(%checksum); - let ts = Utc::now().format("%Y-%m-%d-%H-%M-%S"); + let ts = Timestamp::now().strftime("%Y-%m-%d-%H-%M-%S"); let mut snapshot_path = PathBuf::from("snapshots"); if !snapshot_path.exists() { fs::create_dir_all(&snapshot_path).unwrap(); diff --git a/templates/atom.xml b/templates/atom.xml new file mode 100644 index 0000000..be02b7c --- /dev/null +++ b/templates/atom.xml @@ -0,0 +1,25 @@ + + {{ title }} + {{ domain }}/inn/{{ iid }} + {{ updated }} + + + {{ subtitle }} + {% for category in categories %} + + {% endfor %} + + {% for entry in entries %} + + {{ entry.title }} + {{ domain }}/inn/{{ entry.iid }}/{{ entry.pid }} + {{ entry.updated }} + + {{ entry.author.0 }} + {{ domain }}/user/{{ entry.author.1 }} + + + {{ entry.content|trim }} + + {% endfor %} + \ No newline at end of file