feat: downloadable attachments

This commit is contained in:
Patrick 2024-09-04 21:18:33 +02:00
parent 21301e2bf1
commit 4cb71ccf5e
Signed by: patrick
GPG key ID: 451F95EFB8BECD0F
3 changed files with 142 additions and 3 deletions

75
Cargo.lock generated
View file

@ -49,6 +49,12 @@ dependencies = [
"rustc-demangle", "rustc-demangle",
] ]
[[package]]
name = "base64"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.6.0" version = "2.6.0"
@ -125,12 +131,65 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 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]] [[package]]
name = "futures-core" name = "futures-core"
version = "0.3.30" version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" 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]] [[package]]
name = "futures-sink" name = "futures-sink"
version = "0.3.30" version = "0.3.30"
@ -155,11 +214,16 @@ version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [ dependencies = [
"futures-channel",
"futures-core", "futures-core",
"futures-io",
"futures-macro",
"futures-sink", "futures-sink",
"futures-task", "futures-task",
"memchr",
"pin-project-lite", "pin-project-lite",
"pin-utils", "pin-utils",
"slab",
] ]
[[package]] [[package]]
@ -521,7 +585,9 @@ dependencies = [
name = "signal-to-blog" name = "signal-to-blog"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"base64",
"color-eyre", "color-eyre",
"futures",
"jsonrpsee", "jsonrpsee",
"serde", "serde",
"serde_json", "serde_json",
@ -531,6 +597,15 @@ dependencies = [
"tokio-util", "tokio-util",
] ]
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.13.2" version = "1.13.2"

View file

@ -4,7 +4,9 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
base64 = "0.22.1"
color-eyre = "0.6.3" color-eyre = "0.6.3"
futures = "0.3.30"
jsonrpsee = { version = "0.24.3", features = ["macros", "async-client"] } jsonrpsee = { version = "0.24.3", features = ["macros", "async-client"] }
serde = { version = "1.0.209", features = ["derive"] } serde = { version = "1.0.209", features = ["derive"] }
serde_json = "1.0.127" serde_json = "1.0.127"

View file

@ -1,7 +1,13 @@
use std::fs::{create_dir, write};
use std::path::Path;
use std::process::Stdio; use std::process::Stdio;
use base64::prelude::BASE64_STANDARD;
use base64::Engine;
use color_eyre::eyre::Result; 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::process::Command;
use tokio_util::codec::{FramedRead, LinesCodec}; use tokio_util::codec::{FramedRead, LinesCodec};
@ -26,13 +32,69 @@ async fn main() -> Result<()> {
inner: FramedRead::new(cmd.stdout.take().unwrap(), LinesCodec::new()), 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?; let mut stream = client.subscribe_receive(None).await?;
{ loop {
let v = stream.next().await.unwrap()?; let v = stream.next().await.unwrap()?;
println!("{v}"); 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?; stream.unsubscribe().await?;
Ok(()) 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<Vec<(&'a str, String)>> {
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())
}