diff --git a/Cargo.lock b/Cargo.lock index 638fc3c..1c0b5c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -49,6 +49,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "bitflags" version = "2.6.0" @@ -125,12 +131,65 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + [[package]] name = "futures-core" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "futures-sink" version = "0.3.30" @@ -155,11 +214,16 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ + "futures-channel", "futures-core", + "futures-io", + "futures-macro", "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", + "slab", ] [[package]] @@ -521,7 +585,9 @@ dependencies = [ name = "signal-to-blog" version = "0.1.0" dependencies = [ + "base64", "color-eyre", + "futures", "jsonrpsee", "serde", "serde_json", @@ -531,6 +597,15 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + [[package]] name = "smallvec" version = "1.13.2" diff --git a/Cargo.toml b/Cargo.toml index eecd201..b929192 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,9 @@ version = "0.1.0" edition = "2021" [dependencies] +base64 = "0.22.1" color-eyre = "0.6.3" +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" diff --git a/src/main.rs b/src/main.rs index faf39ea..0f857e2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,13 @@ +use std::fs::{create_dir, write}; +use std::path::Path; use std::process::Stdio; +use base64::prelude::BASE64_STANDARD; +use base64::Engine; use color_eyre::eyre::Result; -use jsonrpsee::async_client::ClientBuilder; +use futures::future::join_all; +use jsonrpsee::async_client::{Client, ClientBuilder}; +use serde_json::Value; use tokio::process::Command; use tokio_util::codec::{FramedRead, LinesCodec}; @@ -26,13 +32,69 @@ async fn main() -> Result<()> { inner: FramedRead::new(cmd.stdout.take().unwrap(), LinesCodec::new()), }; - let client = ClientBuilder::default().build_with_tokio(sender, receiver); + let mut client = ClientBuilder::default().build_with_tokio(sender, receiver); let mut stream = client.subscribe_receive(None).await?; - { + loop { let v = stream.next().await.unwrap()?; println!("{v}"); + println!("{:?}", get_msg_text(&v)); + println!("{:?}", get_msg_sender(&v)); + let at = get_msg_attachments(&mut client, &v).await; + if let Some(i) = at { + for (id, content) in i { + save_picture(id, &content)?; + } + } } stream.unsubscribe().await?; Ok(()) } + +fn save_picture(name: &str, content: &str) -> Result<()> { + if !Path::new("./data/").exists() { + create_dir("./data/")? + } + write(format!("./data/{}", name), BASE64_STANDARD.decode(content)?)?; + Ok(()) +} + +async fn get_msg_attachments<'a>( + client: &mut Client, + val: &'a Value, +) -> Option> { + let account = val.get("account")?.as_str()?; + let attachments = val + .pointer("/envelope/dataMessage/attachments")? + .as_array()?; + let recipient = val.pointer("/envelope/source")?.as_str()?; + join_all(attachments.into_iter().map(|i| async { + let id = i.get("id")?.as_str()?; + let val = client + .get_attachment( + Some(account.to_string()), + id.to_string(), + Some(recipient.to_string()), + None, + ) + .await + .ok(); + val.and_then(|x| { + x.get("data") + .and_then(|x| x.as_str().map(|x| x.to_string())) + }) + .and_then(|x| Some((id, x))) + })) + .await + .into_iter() + .collect() +} + +fn get_msg_sender(val: &Value) -> Option<&str> { + val.pointer("/envelope/source").and_then(|x| x.as_str()) +} + +fn get_msg_text(val: &Value) -> Option<&str> { + val.pointer("/envelope/dataMessage/message") + .and_then(|x| x.as_str()) +}