crabmail

Static HTML email archive viewer in Rust
git clone git://git.alexwennerberg.com/crabmail
Log | Files | Refs | README | LICENSE

commit bd34058ac1ab759d4e31254ff4f405f854bde4a5
parent 9ba844c6e06ee12fa7180423437a3351cfddc8eb
Author: alex wennerberg <alex@alexwennerberg.com>
Date:   Sun, 20 Mar 2022 14:13:01 -0700

Cleanup compiler warnings

Diffstat:
MTODO | 2+-
Msrc/arg.rs | 3++-
Msrc/maildir.rs | 20++------------------
Msrc/main.rs | 46++++------------------------------------------
Msrc/models.rs | 16----------------
Msrc/templates/gmi.rs | 8--------
Msrc/templates/html.rs | 15+++++++--------
Msrc/templates/mod.rs | 2+-
Msrc/templates/xml.rs | 10+++++-----
Msrc/threading.rs | 2+-
Msrc/time.rs | 38++------------------------------------
11 files changed, 25 insertions(+), 137 deletions(-)

diff --git a/TODO b/TODO @@ -2,11 +2,11 @@ TODO ==== atom feeds working -> pull last x into threads paginate list home -fix docs fix "to" in email export reference mblaze command, add examples to readme fix all the build warnings remove unused +fix docs check for html escape bugz Duplicate ID verification: warn on duplicate ID, use first received-date. This diff --git a/src/arg.rs b/src/arg.rs @@ -13,7 +13,7 @@ use std::env; use std::ffi::OsString; -use std::os::unix::ffi::OsStrExt; + use std::path::PathBuf; use std::process::exit; use std::str::FromStr; @@ -87,6 +87,7 @@ impl Args { } } +#[allow(dead_code)] fn parse_arg<T: FromStr>(a: Option<OsString>) -> T { a.and_then(|a| a.into_string().ok()) .and_then(|a| a.parse().ok()) diff --git a/src/maildir.rs b/src/maildir.rs @@ -15,7 +15,6 @@ use std::error; use std::fmt; use std::fs; -use std::io::prelude::*; use std::ops::Deref; use std::path::PathBuf; @@ -55,30 +54,15 @@ impl From<&'static str> for MailEntryError { } } -enum MailData { - None, - #[cfg(not(feature = "mmap"))] - Bytes(Vec<u8>), - #[cfg(feature = "mmap")] - File(memmap::Mmap), -} - -impl MailData { - fn is_none(&self) -> bool { - match self { - MailData::None => true, - _ => false, - } - } -} - /// This struct represents a single email message inside /// the maildir. Creation of the struct does not automatically /// load the content of the email file into memory - however, /// that may happen upon calling functions that require parsing /// the email. pub struct MailEntry { + #[allow(dead_code)] id: String, + #[allow(dead_code)] flags: String, path: PathBuf, } diff --git a/src/main.rs b/src/main.rs @@ -9,7 +9,6 @@ use std::fs; use std::path::PathBuf; use models::*; -use std::io::prelude::*; use config::{Config, INSTANCE}; mod arg; @@ -33,7 +32,7 @@ pub fn append_ext(ext: impl AsRef<OsStr>, path: &PathBuf) -> PathBuf { impl Lists { fn write_lists(&mut self) { - std::fs::create_dir_all(&self.out_dir); + std::fs::create_dir_all(&self.out_dir).ok(); let css = include_bytes!("style.css"); write_if_unchanged(&self.out_dir.join("style.css"), css); let base_path = self.out_dir.join("index"); @@ -62,15 +61,6 @@ fn write_if_unchanged(path: &PathBuf, data: &[u8]) -> bool { return true; } -// / is disallowed in paths. ; is disallowed in message IDs -// assumes unix-like filesystem. TODO windows compatability if someone asks - -enum Format { - XML, - HTML, - GMI, -} - impl List { fn persist(&mut self) { self.write_threads(); @@ -107,8 +97,8 @@ impl List { let mut files_written: HashSet<PathBuf> = HashSet::new(); let thread_dir = self.out_dir.join("threads"); let message_dir = self.out_dir.join("messages"); - std::fs::create_dir_all(&thread_dir).unwrap(); - std::fs::create_dir_all(&message_dir).unwrap(); + std::fs::create_dir_all(&thread_dir).ok(); + std::fs::create_dir_all(&message_dir).ok(); // Used for atom for thread_ids in &self.thread_idx.threads { // Load thread @@ -149,7 +139,7 @@ impl List { match entry { Ok(e) => { if !files_written.contains(&e.path()) { - fs::remove_file(&e.path()); + fs::remove_file(&e.path()).ok(); } } Err(_) => continue, @@ -206,31 +196,3 @@ fn main() -> Result<()> { lists.write_lists(); Ok(()) } - -// TODO del this stuff -// -// -// fn write_index(lists: Vec<String>) -> Result<()> { -// let description = &Config::global().description; -// let tmp = html! { -// h1(class="page-title") { -// : format!("Mail Archives"); -// } -// : Raw(&description); - -// @if description.len() > 1 { -// br; -// } -// hr; -// @for list in &lists { -// a(href=list, class="bigger bold") { -// :list; -// } -// br; -// } -// }; -// let file = File::create(&Config::global().out_dir.join("index.html"))?; -// let mut br = BufWriter::new(file); -// layout("Mail Archives".to_string(), tmp).write_to_io(&mut br)?; -// Ok(()) -// } diff --git a/src/models.rs b/src/models.rs @@ -50,22 +50,6 @@ pub struct ThreadSummary { pub last_reply: i64, // unix } -impl List { - pub fn new(name: &str) -> Self { - let con = Config::global(); - let sub: Subsection = match con.get_subsection(name) { - Some(c) => c, - None => con.default_subsection(name), - }; - Self { - thread_idx: ThreadIdx::default(), - config: sub, - thread_topics: vec![], - out_dir: Config::global().out_dir.join(name), - } - } -} - pub struct Thread { pub messages: Vec<StrMessage>, } diff --git a/src/templates/gmi.rs b/src/templates/gmi.rs @@ -124,14 +124,6 @@ To: {to}{optional_headers} } } -// Convert body to gemini -// gonna be complex -fn escape_body(s: &str) -> String { - let mut out = " ".to_string(); - out.push_str(&s.replace("\n", "\n ")); - out -} - // escape header fn h(s: &str) -> String { s.replace("\n", " ") diff --git a/src/templates/html.rs b/src/templates/html.rs @@ -5,9 +5,8 @@ use crate::time::Date; use crate::util::*; use linkify::{LinkFinder, LinkKind}; use nanotemplate::template; -use std::borrow::Cow; -const header: &str = r#"<!DOCTYPE html> +const HEADER: &str = r#"<!DOCTYPE html> <html> <head> <title>{title}</title> @@ -20,7 +19,7 @@ const header: &str = r#"<!DOCTYPE html> <body> "#; -const footer: &str = r#" +const FOOTER: &str = r#" Archive generated with <a href='https://crabmail.flounder.online/'>crabmail</a> </body> </html> @@ -40,7 +39,7 @@ impl Lists { {lists} <hr>"#; template( - &format!("{}{}{}", header, body, footer), + &format!("{}{}{}", HEADER, body, FOOTER), &[ ("title", "Mail Archives"), ("css_path", "style.css"), @@ -105,14 +104,14 @@ impl List { {footer} "#, &[ - ("header", header), + ("header", HEADER), ("description", &self.config.description), ("title", self.config.title.as_str()), ("css_path", "../style.css"), ("threads", &threads), ("list_email", &self.config.email), ("rss_svg", RSS_SVG), - ("footer", footer), + ("footer", FOOTER), ], ) .unwrap(); @@ -148,7 +147,7 @@ impl Thread { <div> "#; let mut out = template( - &format!("{}{}", header, body), + &format!("{}{}", HEADER, body), // TODO html escape &[ ("title", x(&root.subject).as_ref()), @@ -266,7 +265,7 @@ data:image/svg+xml,<?xml version="1.0" encoding="UTF-8"?> pub fn email_body(body: &str, flowed: bool) -> String { let mut bytes = Vec::new(); let mut body = body; - let mut tmp = String::new(); + let tmp; if flowed { tmp = unformat_flowed(body); body = &tmp; diff --git a/src/templates/mod.rs b/src/templates/mod.rs @@ -3,4 +3,4 @@ pub mod html; pub mod util; pub mod xml; -const PAGE_SIZE: i32 = 100; +// const PAGE_SIZE: i32 = 100; diff --git a/src/templates/xml.rs b/src/templates/xml.rs @@ -1,10 +1,10 @@ -use super::util::xml_escape; +// use super::util::xml_escape; use crate::models::*; -use crate::templates::util::xml_safe; -use anyhow::{Context, Result}; -use nanotemplate::template; +// use crate::templates::util::xml_safe; +// use anyhow::{Context, Result}; +// use nanotemplate::template; -const ATOM_ENTRY_LIMIT: i32 = 100; +// const ATOM_ENTRY_LIMIT: i32 = 100; // impl List { // fn to_xml(&self) { diff --git a/src/threading.rs b/src/threading.rs @@ -4,7 +4,7 @@ // stores use mail_parser::parsers::fields::thread::thread_name; -use mail_parser::{DateTime, Message}; +use mail_parser::{Message}; use std::collections::HashMap; use std::path::PathBuf; diff --git a/src/time.rs b/src/time.rs @@ -25,8 +25,10 @@ const DAYS_PER_4Y: i64 = 365 * 4 + 1; pub struct Date { year: u32, month: u8, + #[allow(dead_code)] day_of_year: u32, day_of_month: u8, + #[allow(dead_code)] day_of_week: u8, hour: u8, minute: u8, @@ -134,42 +136,6 @@ fn secs_to_date(unixtime: i64) -> Date { second: (remsecs % 60) as u8, } } - -const SOLAR_YEAR_SECS: u64 = 31556926; - -pub fn timeago(unixtime: u64) -> String { - let current_time = SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() - .as_secs(); - if unixtime > current_time { - return "in the future".to_owned(); - } - let diff = current_time - unixtime; - let amount: u64; - let metric: &str; - // if diff < 60 { - // amount = diff; - // metric = "second"; - // } else if diff < 60 * 60 { - // amount = diff / 60; - // metric = "minute"; - if diff < 60 * 60 * 24 { - amount = diff / (60 * 60); - metric = "hour"; - } else if diff < SOLAR_YEAR_SECS * 2 { - amount = diff / (60 * 60 * 24); - metric = "day"; - } else { - amount = diff / SOLAR_YEAR_SECS * 2; - metric = "year"; - } - match amount { - 1 => format!("{} {} ago", amount, metric), - _ => format!("{} {}s ago", amount, metric), - } -} - #[cfg(test)] mod tests { use super::*;