diff --git a/.drone.yml b/.drone.yml index eef8de5..4f6f7f0 100644 --- a/.drone.yml +++ b/.drone.yml @@ -17,6 +17,7 @@ steps: - apt update - apt install -y cmake - cargo build --release -v + - strip target/release/ruff - name: publish image: plugins/gitea-release diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..bf3210d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,5 @@ +# 0.2.1 +- added video support +- added `jens` command +- added `party` command +- meme cache now stores data encoded with bincode. **DELETE BEFORE UPDATE** diff --git a/Cargo.toml b/Cargo.toml index 52e545b..c20c221 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ruff" -version = "0.2.0" +version = "0.2.1" authors = ["LordMZTE "] edition = "2018" @@ -8,6 +8,7 @@ edition = "2018" [dependencies] anyhow = "1.0" +bincode = "1.3.3" clap = "2.33.3" env_logger = "0.8.4" log = "0.4.13" diff --git a/exampleconfig.toml b/exampleconfig.toml index 98b5375..de55c40 100644 --- a/exampleconfig.toml +++ b/exampleconfig.toml @@ -15,9 +15,11 @@ memes = [ { keyword = "hendrik", randomcat = "hendrik" }, { keyword = "hey", id = 243 }, { keyword = "itbyhf", id = 314 }, + { keyword = "jens", id = 343 }, { keyword = "jonasled", id = 164 }, { keyword = "kappa", id = 182 }, { keyword = "lordmzte", id = 315 }, + { keyword = "party", id = 619 }, { keyword = "realtox", id = 168 }, { keyword = "sklave", id = 304 }, { keyword = "tilera", id = 316 }, diff --git a/src/main.rs b/src/main.rs index 396d385..0413a40 100644 --- a/src/main.rs +++ b/src/main.rs @@ -140,7 +140,7 @@ impl EventHandler for Bot { } if let Room::Invited(room) = room { - println!("Autojoining room {}", room.room_id()); + info!("Autojoining room {}", room.room_id()); let mut delay = 2; while let Err(err) = self @@ -274,18 +274,18 @@ async fn bootstrap_cross_signing( ) -> anyhow::Result<()> { info!("bootstrapping e2e"); if let Err(e) = client.bootstrap_cross_signing(None).await { - warn!("couldnt bootstrap e2e without auth data"); if let Some(response) = e.uiaa_response() { let auth_data = auth_data(&user_id, &password, response.session.as_deref()); client .bootstrap_cross_signing(Some(auth_data)) .await .context("Couldn't bootstrap cross signing")?; - info!("bootstrapped e2e with auth data"); } else { bail!("Error during cross-signing bootstrap {:#?}", e); } } + info!("bootstrapped e2e"); + Ok(()) } diff --git a/src/responder.rs b/src/responder.rs index 3f2badc..afafc0f 100644 --- a/src/responder.rs +++ b/src/responder.rs @@ -4,15 +4,55 @@ use log::{error, info, warn}; use matrix_sdk::{ api::r0::media::create_content, events::{ - room::message::{ImageMessageEventContent, MessageEventContent, MessageType}, + room::message::{ + ImageMessageEventContent, MessageEventContent, MessageType, VideoMessageEventContent, + }, AnyMessageEventContent, }, identifiers::MxcUri, room::{Joined, Room}, }; +use serde::{Deserialize, Serialize}; use std::io::Cursor; use std::sync::atomic::Ordering; +#[derive(Debug, Deserialize, Serialize)] +struct CachedMeme { + mxc: MxcUri, + ty: CachedMemeType, +} + +impl CachedMeme { + fn into_message_type(self, name: String) -> MessageType { + match self { + Self { + mxc, + ty: CachedMemeType::Image, + } => MessageType::Image(ImageMessageEventContent::plain(name, mxc, None)), + Self { + mxc, + ty: CachedMemeType::Video, + } => MessageType::Video(VideoMessageEventContent::plain(name, mxc, None)), + } + } +} + +#[derive(Debug, Deserialize, Serialize)] +enum CachedMemeType { + Image, + Video, +} + +impl CachedMemeType { + fn from_mime_name(name: &mime::Name) -> Option { + match *name { + mime::VIDEO => Some(Self::Video), + mime::IMAGE => Some(Self::Image), + _ => None, + } + } +} + pub async fn on_msg(msg: &str, room: Room, bot: &Bot) -> anyhow::Result<()> { let room = match room { Room::Joined(room) => room, @@ -42,12 +82,8 @@ pub async fn on_msg(msg: &str, room: Room, bot: &Bot) -> anyhow::Result<()> { } Ok(id) => { if let Some(ivec) = bot.memecache.get(id.to_le_bytes())? { - info!("Meme {} found in cache!", id); - let mxc = String::from_utf8(ivec.as_ref().to_vec()).context( - "Found invalid utf8 mxc url in memecache! Is the cache borked?", - )?; - - send_meme(&room, mxc.into(), meme_name.clone()).await?; + let cached = bincode::deserialize::(&ivec)?; + send_meme(&room, cached, meme_name.clone()).await?; } else { info!("Meme {} not found in cache, uploading...", id); let resp = bot @@ -62,6 +98,8 @@ pub async fn on_msg(msg: &str, room: Room, bot: &Bot) -> anyhow::Result<()> { let resp = resp.bytes().await?; if let Some(mime) = mime_guess::from_path(&meme.link).first() { + let ty = CachedMemeType::from_mime_name(&mime.type_()) + .context("Found meme that is neither video nor image!")?; let create_content::Response { content_uri, .. } = bot .client .read() @@ -69,12 +107,15 @@ pub async fn on_msg(msg: &str, room: Room, bot: &Bot) -> anyhow::Result<()> { .upload(&mime, &mut Cursor::new(resp)) .await?; - bot.memecache.insert( - id.to_le_bytes(), - content_uri.to_string().into_bytes(), - )?; + let cached = CachedMeme { + mxc: content_uri, + ty, + }; - send_meme(&room, content_uri, meme_name.clone()).await?; + bot.memecache + .insert(id.to_le_bytes(), bincode::serialize(&cached)?)?; + + send_meme(&room, cached, meme_name.clone()).await?; } else { error!( "Couldn't guess MIME type of meme '{}', skipping.", @@ -93,11 +134,11 @@ pub async fn on_msg(msg: &str, room: Room, bot: &Bot) -> anyhow::Result<()> { Ok(()) } -async fn send_meme(room: &Joined, mxc: MxcUri, meme_name: String) -> anyhow::Result<()> { +async fn send_meme(room: &Joined, cached: CachedMeme, meme_name: String) -> anyhow::Result<()> { + let msg_ty = cached.into_message_type(meme_name); + room.send( - AnyMessageEventContent::RoomMessage(MessageEventContent::new(MessageType::Image( - ImageMessageEventContent::plain(meme_name, mxc, None), - ))), + AnyMessageEventContent::RoomMessage(MessageEventContent::new(msg_ty)), None, ) .await