From b2c44e90030b1333e20012641904080def43b6dd Mon Sep 17 00:00:00 2001 From: Patrick Date: Thu, 12 Sep 2024 19:35:51 +0200 Subject: [PATCH] feat: timezone implementation --- src/main.rs | 224 ++++++++++++++++++++++++---------------------------- 1 file changed, 104 insertions(+), 120 deletions(-) diff --git a/src/main.rs b/src/main.rs index e0c70a6..fc71132 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,14 @@ use copy_dir::copy_dir; -use std::fs::{create_dir_all, remove_file, write, File, OpenOptions}; -use std::io::{BufRead, BufReader, Write}; +use std::fs::{create_dir_all, read_to_string, remove_file, write, File, OpenOptions}; +use std::io::{BufRead, BufReader, Read, Write}; use std::path::{Path, PathBuf}; use std::process::Stdio; use askama::Template; use base64::prelude::BASE64_STANDARD; use base64::Engine; -use chrono::{DateTime, Days, Local}; +use chrono::offset::FixedOffset; +use chrono::{DateTime, Days, Local, Utc}; use clap::{command, Parser}; use color_eyre::eyre::{eyre, OptionExt, Result}; use futures::future::join_all; @@ -42,6 +43,10 @@ struct Config { ///The used as the journal #[arg(short, long)] url: String, + + ///The timezone used if none is given in the data folder + #[arg(short, long)] + timezone: String, } #[derive(Debug, Default, Template)] @@ -89,11 +94,18 @@ async fn generate_post(config: &Config, client: &mut Client) -> Result { attachments.push(id.to_string()); } } + let time = get_msg_time(&v).ok_or_eyre("Message without time???")?; + let secs = config.timezone.parse::()?; + println!("{:?}", secs); + let tz = FixedOffset::east_opt(config.timezone.parse::()? * 3600) + .ok_or_eyre("timezone von nem anderen planete?")?; + let time = time.with_timezone(&tz); + println!("{:?}", time); msgs.push(Message { content: get_msg_text(&v).unwrap_or("").to_string(), attachments, - time: get_msg_time(&v).ok_or_eyre("Message without time???")?, + time: time.format("%H:%M").to_string(), }); } if msgs.is_empty() { @@ -117,10 +129,15 @@ async fn generate_post(config: &Config, client: &mut Client) -> Result { #[tokio::main] async fn main() -> Result<()> { - let config = Config::parse(); + let mut config = Config::parse(); if !Path::new(&config.data_folder).exists() { create_dir_all(&config.data_folder)? } + let tz_data_path = format!("{}/tz.data", config.data_folder); + if Path::new(&tz_data_path).exists() { + config.timezone = read_to_string(&tz_data_path)?; + } + println!("{:?}", config.timezone); let mut cmd = Command::new(COMMAND_PATH) .arg("jsonRpc") @@ -146,131 +163,69 @@ async fn main() -> Result<()> { continue; } else if sender != &config.allowed_sender { println!("{:?}", sender); - client - .send( - None, - vec![sender.to_string()], - Vec::new(), - false, - false, - "This is the signal-to-blog bot, you are not in the list of allowed writers." - .to_string(), - Vec::new(), - Vec::new(), - Vec::new(), - None, - None, - None, - Vec::new(), - Vec::new(), - Vec::new(), - None, - None, - None, - None, - None, - None, - None, - None, - ) - .await?; + send( + &client, + sender, + "This is the signal-to-blog bot, you are not in the list of allowed writers." + .to_string(), + ) + .await?; continue; }; println!("{v}"); println!("{:?}", text); if let Some(text) = text { // ©ontrol character - if let Some(text) = text.strip_prefix("©").and_then(|x| Some(x.trim())) { - match text { + let cmds: Vec<&str> = text.split_whitespace().collect(); + if cmds.len() >= 2 && cmds[0] == "©" { + match cmds[1] { + "help" => { + let text = " +Available commands: + - post: Generate post for yesterday + - tz: change timezone +" + .to_string(); + send(&client, sender, text).await?; + } "post" => { let res = generate_post(&config, &mut client).await; if let Ok(res) = res { - client - .send( - None, - vec![sender.to_string()], - Vec::new(), - false, - false, - format!("Generated blog post at: {}/{}", config.url, res) - .to_string(), - Vec::new(), - Vec::new(), - Vec::new(), - None, - None, - None, - Vec::new(), - Vec::new(), - Vec::new(), - None, - None, - None, - None, - None, - None, - None, - None, - ) - .await?; + send( + &client, + sender, + format!("Generated blog post at: {}/{}", config.url, res), + ) + .await?; } else { - client - .send( - None, - vec![sender.to_string()], - Vec::new(), - false, - false, - format!("Error generating blog post:\n{:?}", res).to_string(), - Vec::new(), - Vec::new(), - Vec::new(), - None, - None, - None, - Vec::new(), - Vec::new(), - Vec::new(), - None, - None, - None, - None, - None, - None, - None, - None, - ) - .await?; + send( + &client, + sender, + format!("Error generating blog post:\n{:?}", res), + ) + .await?; + } + } + "tz" => { + if cmds.get(2).is_some_and(|x| { + x.parse::() + .is_ok_and(|x| FixedOffset::east_opt(x * 3600).is_some()) + }) { + println!("{}", tz_data_path); + let mut file = OpenOptions::new() + .create(true) + .write(true) + .open(&tz_data_path)?; + file.write_all(cmds[2].as_bytes())?; + config.timezone = cmds[2].to_string(); + + send(&client, sender, format!("Updated tz data")).await?; + } else { + send(&client, sender, format!("Error parsing")).await?; } } _ => { - client - .send( - None, - vec![sender.to_string()], - Vec::new(), - false, - false, - format!("Unknown command: {}", text).to_string(), - Vec::new(), - Vec::new(), - Vec::new(), - None, - None, - None, - Vec::new(), - Vec::new(), - Vec::new(), - None, - None, - None, - None, - None, - None, - None, - None, - ) - .await?; + send(&client, sender, format!("Unknown command: {}", text)).await?; } } continue; @@ -283,6 +238,36 @@ async fn main() -> Result<()> { writeln!(file, "{}", v.to_string())?; } } +async fn send(client: &Client, sender: &str, msg: String) -> Result<()> { + client + .send( + None, + vec![sender.to_string()], + Vec::new(), + false, + false, + msg, + Vec::new(), + Vec::new(), + Vec::new(), + None, + None, + None, + Vec::new(), + Vec::new(), + Vec::new(), + None, + None, + None, + None, + None, + None, + None, + None, + ) + .await?; + Ok(()) +} /// make sure the directory exists before trying to save into it fn save_picture(file: &PathBuf, content: &str) -> Result<()> { @@ -325,12 +310,11 @@ fn get_msg_sender(val: &Value) -> Option<&str> { val.pointer("/envelope/source").and_then(|x| x.as_str()) } -fn get_msg_time(val: &Value) -> Option { +fn get_msg_time(val: &Value) -> Option> { let time = val .pointer("/envelope/timestamp") .and_then(|x| x.as_i64())?; - let time = DateTime::from_timestamp(time, 0)?; - Some(time.format("%H:%M").to_string()) + DateTime::from_timestamp_millis(time) } fn get_msg_text(val: &Value) -> Option<&str> {