diff --git a/index.html b/index.html index 6c81801..7431ca6 100644 --- a/index.html +++ b/index.html @@ -46,12 +46,19 @@ span { + + + + + + +

things running on the server

- + + + + + + + +

pinned stuff

+
+ + + + + + + + + +

everything else

- diff --git a/int.html b/int.html index 5a15c43..a2e4155 100644 --- a/int.html +++ b/int.html @@ -1,5 +1,4 @@ - @@ -7,8 +6,17 @@ + + + + + + + diff --git a/src/data.rs b/src/data.rs index b9fc07f..f13c41f 100644 --- a/src/data.rs +++ b/src/data.rs @@ -32,7 +32,7 @@ impl Data { status_updated: Mutex::new((Instant::now(), false)), } } - pub fn status_sync(&self, dbg: bool) -> MutexGuard { + pub fn status_sync(&'_ self, dbg: bool) -> MutexGuard<'_, Status> { let mut updated = self.status_updated.blocking_lock(); let now = Instant::now(); if (now - updated.0).as_secs_f32() > 3.0 || (dbg && !updated.1) { @@ -47,7 +47,7 @@ impl Data { self.status.blocking_lock() } } - pub async fn status_async(&self, dbg: bool) -> MutexGuard { + pub async fn status_async(&'_ self, dbg: bool) -> MutexGuard<'_, Status> { let mut updated = self.status_updated.lock().await; let now = Instant::now(); if (now - updated.0).as_secs_f32() > 3.0 || (dbg && !updated.1) { diff --git a/src/main.rs b/src/main.rs index b058f53..92a692f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,7 +26,7 @@ async fn index_dbg(data: &State) -> RawHtml { async fn index_gen(data: &State, dbg: bool) -> RawHtml { let status = data.status_async(dbg).await; - return RawHtml(data.index.gen(&status, dbg, data.globals.clone())); + RawHtml(data.index.gen(&status, dbg, data.globals.clone())) } #[get("/int")] diff --git a/src/status.rs b/src/status.rs index 29d4a5f..2d321a6 100644 --- a/src/status.rs +++ b/src/status.rs @@ -2,8 +2,8 @@ use std::{collections::BTreeMap, os::unix::fs::PermissionsExt, path::Path, time: use tokio::time::Instant; -const SLASHINFO: &'static str = "/srv/tomatenmhark-slashinfo/"; -const REDIRECT: &'static str = "/srv/tomatenmhark-redirect/"; +const SLASHINFO: &str = "/srv/tomatenmhark-slashinfo/"; +const REDIRECT: &str = "/srv/tomatenmhark-redirect/"; pub struct Status( pub BTreeMap, Option)>, @@ -40,36 +40,31 @@ impl Status { ); let mut rest = BTreeMap::new(); if let Ok(rd) = std::fs::read_dir(SLASHINFO) { - for f in rd { - if let Ok(f) = f { - if let Some(id) = f.file_name().to_str() { - if !map.contains_key(id) { - let mut p = f.path(); - p.push("desc"); - if let Ok(desc) = std::fs::read_to_string(&p) { - let info = Path::new(SLASHINFO).join(id).join("index.html"); - let info = info.starts_with(SLASHINFO) - && info.try_exists().ok() == Some(true); - let redirect = Path::new(REDIRECT).join(id); - let redirect = redirect.starts_with(REDIRECT) - && redirect.try_exists().ok() == Some(true); - let desc = desc.trim(); - if let Some(i) = desc.find('\n') { - rest.insert( - id.to_owned(), - ( - info, - redirect, - desc[0..i].trim().to_owned(), - Some(desc[i + 1..].trim().to_owned()), - ), - ); - } else { - rest.insert( - id.to_owned(), - (info, redirect, desc.to_owned(), None), - ); - } + for f in rd.filter_map(Result::ok) { + if let Some(id) = f.file_name().to_str() { + if !map.contains_key(id) { + let mut p = f.path(); + p.push("desc"); + if let Ok(desc) = std::fs::read_to_string(&p) { + let info = Path::new(SLASHINFO).join(id).join("index.html"); + let info = + info.starts_with(SLASHINFO) && info.try_exists().ok() == Some(true); + let redirect = Path::new(REDIRECT).join(id); + let redirect = redirect.starts_with(REDIRECT) + && redirect.try_exists().ok() == Some(true); + let desc = desc.trim(); + if let Some(i) = desc.find('\n') { + rest.insert( + id.to_owned(), + ( + info, + redirect, + desc[0..i].trim().to_owned(), + Some(desc[i + 1..].trim().to_owned()), + ), + ); + } else { + rest.insert(id.to_owned(), (info, redirect, desc.to_owned(), None)); } } } @@ -143,26 +138,25 @@ impl Status { fn query_status_sync(mut func: impl FnMut(&str, bool, bool, &str, Option), dbg: bool) { if let Ok(rd) = std::fs::read_dir("/tmp/") { - for f in rd { - if let Ok(f) = f { - if let Some(name) = f.file_name().to_str() { - if name.starts_with("tomatenmhark-status-") { - let id = name["tomatenmhark-status-".len()..].trim(); - if !id.is_empty() { - if let Ok(status) = std::fs::read_to_string(f.path()) - .as_ref() - .map(|v| v.trim_end()) - { - if !status.is_empty() { - let info = Path::new(SLASHINFO).join(id).join("index.html"); - let info = info.starts_with(SLASHINFO) - && info.try_exists().ok() == Some(true); - let redirect = Path::new(REDIRECT).join(id); - let redirect = redirect.starts_with(REDIRECT) - && redirect.try_exists().ok() == Some(true); - func(id, info, redirect, status, None); - } - } + for f in rd.filter_map(Result::ok) { + if let Some(name) = f.file_name().to_str() { + if let Some(id) = name + .strip_prefix("tomatenmhark-status-") + .map(|v| v.trim()) + .filter(|v| !v.is_empty()) + { + if let Ok(status) = std::fs::read_to_string(f.path()) + .as_ref() + .map(|v| v.trim_end()) + { + if !status.is_empty() { + let info = Path::new(SLASHINFO).join(id).join("index.html"); + let info = + info.starts_with(SLASHINFO) && info.try_exists().ok() == Some(true); + let redirect = Path::new(REDIRECT).join(id); + let redirect = redirect.starts_with(REDIRECT) + && redirect.try_exists().ok() == Some(true); + func(id, info, redirect, status, None); } } } @@ -170,28 +164,26 @@ fn query_status_sync(mut func: impl FnMut(&str, bool, bool, &str, Option), + IfEq(usize, usize, Templates, Option), + IfLine(usize, usize, Templates, Option), For(Vec, Templates), } @@ -94,8 +96,8 @@ pub struct TemplateInfo { last_end_was_else: Option, } -const COMMENT_START: &'static str = ""; +const COMMENT_START: &str = ""; impl Template { pub fn parse( mut src: &str, @@ -137,13 +139,14 @@ impl Templates { if let Some(comment_end) = src.find(COMMENT_END) { // extract comment content - let comment_og = src[..comment_end].trim(); - *src = &src[comment_end + COMMENT_END.len()..].trim_start_matches('\r'); + let comment_og = src[..comment_end].trim_start(); + *src = src[comment_end + COMMENT_END.len()..].trim_start_matches('\r'); *src = src.strip_prefix('\n').unwrap_or(src); // do template things let comment = comment_og.to_lowercase(); let mut comment = comment.split(char::is_whitespace); - match comment.next().unwrap_or("") { + let comment_match = comment.next().unwrap_or(""); + match comment_match { "//" | "#" => {} "end" => { break 'parsing; @@ -170,7 +173,8 @@ impl Templates { let var_name = comment .next() .ok_or(TemplateParseError::MissingVariable("set"))?; - let value = comment_og[3..].trim_start()[var_name.len()..].trim_start(); + let value = &comment_og[3..].trim_start()[var_name.len()..]; + let value = value.strip_prefix(char::is_whitespace).unwrap_or(value); out.push(TemplateType::Set(info.var(var_name), value.to_owned())); } "concat" => { @@ -187,22 +191,55 @@ impl Templates { ), )); } - "if" => { + "if" | "ifeq" | "ifline" => { let prev_lewe = info.last_end_was_else; info.last_end_was_else = Some(false); - out.push(TemplateType::If( - info.var( - comment - .next() - .ok_or(TemplateParseError::MissingVariable("if"))?, - ), + let (t_if, t_else) = ( Templates::parse(src, info)?, if info.last_end_was_else.is_some_and(|v| v) { Some(Templates::parse(src, info)?) } else { None }, - )); + ); + out.push(match comment_match { + "if" => TemplateType::If( + info.var( + comment + .next() + .ok_or(TemplateParseError::MissingVariable("if"))?, + ), + t_if, + t_else, + ), + "ifeq" => TemplateType::IfEq( + info.var( + comment + .next() + .ok_or(TemplateParseError::MissingVariable("ifeq"))?, + ), + info.var( + comment + .next() + .ok_or(TemplateParseError::MissingVariable("ifeq"))?, + ), + t_if, + t_else, + ), + "ifline" => { + TemplateType::IfLine( + info.var(comment.next().ok_or( + TemplateParseError::MissingVariable("ifline"), + )?), + info.var(comment.next().ok_or( + TemplateParseError::MissingVariable("ifline"), + )?), + t_if, + t_else, + ) + } + _ => unreachable!(), + }); info.last_end_was_else = prev_lewe; } "for" => { @@ -256,7 +293,7 @@ pub enum TemplateParseError { impl Display for TemplateParseError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Self::UnclosedComment => write!(f, "There is an unclosed comment. Make sure all ``"), + Self::UnclosedComment => write!(f, "There is an unclosed comment. Make sure all ``"), Self::InvalidTemplateKeyword(kw) => write!(f, "Invalid keyword `{kw}` after `