feat: timezone implementation

This commit is contained in:
Patrick 2024-09-12 19:35:51 +02:00
parent 41f9b6f3f5
commit b2c44e9003
Signed by: patrick
GPG key ID: 451F95EFB8BECD0F

View file

@ -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<String> {
attachments.push(id.to_string());
}
}
let time = get_msg_time(&v).ok_or_eyre("Message without time???")?;
let secs = config.timezone.parse::<i32>()?;
println!("{:?}", secs);
let tz = FixedOffset::east_opt(config.timezone.parse::<i32>()? * 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<String> {
#[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::<i32>()
.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<String> {
fn get_msg_time(val: &Value) -> Option<DateTime<Utc>> {
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> {