feat: better command handling

This commit is contained in:
Patrick 2024-09-11 21:40:37 +02:00
parent 2fb8f1dbbf
commit 4760406224
Signed by: patrick
GPG key ID: 451F95EFB8BECD0F
3 changed files with 221 additions and 62 deletions

68
Cargo.lock generated
View file

@ -68,7 +68,7 @@ version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
dependencies = [
"windows-sys",
"windows-sys 0.52.0",
]
[[package]]
@ -78,7 +78,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
dependencies = [
"anstyle",
"windows-sys",
"windows-sys 0.52.0",
]
[[package]]
@ -304,6 +304,16 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "eyre"
version = "0.6.12"
@ -314,6 +324,12 @@ dependencies = [
"once_cell",
]
[[package]]
name = "fastrand"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6"
[[package]]
name = "fnv"
version = "1.0.7"
@ -594,6 +610,12 @@ version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
[[package]]
name = "linux-raw-sys"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]]
name = "lock_api"
version = "0.4.12"
@ -656,7 +678,7 @@ dependencies = [
"hermit-abi",
"libc",
"wasi",
"windows-sys",
"windows-sys 0.52.0",
]
[[package]]
@ -808,6 +830,19 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152"
[[package]]
name = "rustix"
version = "0.38.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.52.0",
]
[[package]]
name = "ryu"
version = "1.0.18"
@ -889,6 +924,7 @@ dependencies = [
"jsonrpsee",
"serde",
"serde_json",
"tempfile",
"thiserror",
"tokio",
"tokio-stream",
@ -917,7 +953,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
dependencies = [
"libc",
"windows-sys",
"windows-sys 0.52.0",
]
[[package]]
@ -937,6 +973,19 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "tempfile"
version = "3.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64"
dependencies = [
"cfg-if",
"fastrand",
"once_cell",
"rustix",
"windows-sys 0.59.0",
]
[[package]]
name = "thiserror"
version = "1.0.63"
@ -982,7 +1031,7 @@ dependencies = [
"signal-hook-registry",
"socket2",
"tokio-macros",
"windows-sys",
"windows-sys 0.52.0",
]
[[package]]
@ -1202,6 +1251,15 @@ dependencies = [
"windows-targets",
]
[[package]]
name = "windows-sys"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"

View file

@ -13,6 +13,7 @@ futures = "0.3.30"
jsonrpsee = { version = "0.24.3", features = ["macros", "async-client"] }
serde = { version = "1.0.209", features = ["derive"] }
serde_json = "1.0.127"
tempfile = "3.12.0"
thiserror = "1.0.63"
tokio = { version = "1.40.0", features = ["full"] }
tokio-stream = "0.1.15"

View file

@ -1,18 +1,21 @@
use std::fs::{create_dir_all, write, File, OpenOptions};
use std::fs::{create_dir_all, remove_file, rename, write, File, OpenOptions};
use std::io::{BufRead, BufReader, Write};
use std::path::{Path, PathBuf};
use std::process::Stdio;
use std::time::Duration;
use askama::Template;
use base64::prelude::BASE64_STANDARD;
use base64::Engine;
use chrono::{DateTime, Local, Timelike};
use chrono::{DateTime, Local};
use clap::{command, Parser};
use color_eyre::eyre::Result;
use color_eyre::eyre::{eyre, Result};
use futures::future::join_all;
use jsonrpsee::async_client::{Client, ClientBuilder};
use serde_json::Value;
use tempfile::tempdir;
use tokio::process::Command;
use tokio::task::yield_now;
use tokio_util::codec::{FramedRead, LinesCodec};
use crate::jsonrpc::RpcClient;
@ -37,9 +40,9 @@ struct Config {
#[arg(short, long)]
output_folder: String,
///The time of day when generate the post
///The used as the journal
#[arg(short, long)]
time: String,
url: String,
}
#[derive(Debug, Default, Template)]
@ -57,14 +60,12 @@ struct Message {
time: String,
}
async fn generate_post(config: &Config, client: &mut Client) -> Result<()> {
async fn generate_post(config: &Config, client: &mut Client) -> Result<String> {
let day: DateTime<Local> = Local::now();
let _hour = day.hour();
let folder: PathBuf = [config.output_folder.clone(), day.to_rfc3339()]
.iter()
.collect();
if !folder.exists() {
create_dir_all(&folder)?;
let file = PathBuf::from(format!("{}/texts.json", config.data_folder));
let tempdir = tempdir()?;
if !file.exists() {
return Err(eyre!("No content to post"));
}
let mut template = PostTemplate {
date: day.to_rfc3339(),
@ -72,29 +73,44 @@ async fn generate_post(config: &Config, client: &mut Client) -> Result<()> {
..Default::default()
};
let mut msgs = Vec::new();
let file = File::open(format!("{}/texts.json", config.data_folder))?;
let reader = BufReader::new(file);
for line in reader.lines() {
let v = serde_json::from_str(&line?)?;
let mut attachments = Vec::new();
if let Some(i) = get_msg_attachments(client, &v).await {
for (id, content) in i {
let path = folder.join(id);
save_picture(&path, &content)?;
attachments.push(id.to_string());
{
let file = File::open(file.clone())?;
let reader = BufReader::new(file.try_clone()?);
for line in reader.lines() {
let v = serde_json::from_str(&line?)?;
let mut attachments = Vec::new();
if let Some(i) = get_msg_attachments(client, &v).await {
for (id, content) in i {
let path = tempdir.path().join(id);
save_picture(&path, &content)?;
attachments.push(id.to_string());
}
}
msgs.push(Message {
content: get_msg_text(&v).unwrap_or("").to_string(),
attachments,
time: get_msg_time(&v).unwrap(),
});
}
if msgs.is_empty() {
return Err(eyre!("No content to post"));
};
template.messages = msgs;
msgs.push(Message {
content: get_msg_text(&v).unwrap_or("").to_string(),
attachments,
time: get_msg_time(&v).unwrap(),
});
println!("{}", template.render()?);
write(tempdir.path().join("index.md"), template.render()?)?;
}
template.messages = msgs;
println!("{}", template.render()?);
Ok(())
let folder: PathBuf = [config.output_folder.clone(), day.to_rfc3339()]
.iter()
.collect();
if folder.exists() {
return Err(eyre!("Blog folder already exists"));
}
rename(tempdir, folder)?;
// Delete messages after we're finished with writing
remove_file(file)?;
Ok(day.to_rfc3339())
}
#[tokio::main]
@ -120,17 +136,18 @@ async fn main() -> Result<()> {
let mut stream = client.subscribe_receive(None).await?;
loop {
let v = stream.next().await.unwrap()?;
let sender = get_msg_sender(&v);
// which message doesn't have a sender?
let sender = get_msg_sender(&v).expect("which message doesn't have a sender?");
let text = get_msg_text(&v);
let at = get_msg_attachments(&mut client, &v).await;
if text.is_none() && at.is_none() {
continue;
} else if sender != Some(&config.allowed_sender) {
} else if sender != &config.allowed_sender {
println!("{:?}", sender);
if let Some(x) = sender {
client.send(
client
.send(
None,
vec![x.to_string()],
vec![sender.to_string()],
Vec::new(),
false,
false,
@ -153,33 +170,116 @@ async fn main() -> Result<()> {
None,
None,
None,
).await?;
}
)
.await?;
continue;
};
println!("{v}");
println!("{:?}", text);
if text == Some("post") {
generate_post(&config, &mut client).await?;
} else {
let mut file = OpenOptions::new()
.append(true)
.create(true)
.open(format!("{}/texts.json", config.data_folder))?;
writeln!(file, "{}", v.to_string())?;
if let Some(text) = text {
// ©ontrol character
if let Some(text) = text.strip_prefix("©").and_then(|x| Some(x.trim())) {
match text {
"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?;
} 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?;
}
}
_ => {
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?;
}
}
continue;
}
}
//let at = get_msg_attachments(&mut client, &v).await;
//if let Some(i) = at {
// for (id, content) in i {
// let path = format!("{}/{}", &config.data_folder, id);
// save_picture(&path, &content)?;
// }
//}
let mut file = OpenOptions::new()
.append(true)
.create(true)
.open(format!("{}/texts.json", config.data_folder))?;
writeln!(file, "{}", v.to_string())?;
}
//stream.unsubscribe().await?;
//Ok(())
}
/// make sure the directory exists before trying to save into it