send mime type and size with memes
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
LordMZTE 2021-06-22 16:36:38 +02:00
parent cd1875240d
commit 6322919e6d
4 changed files with 91 additions and 35 deletions

View file

@ -1,2 +1,4 @@
# 0.2.2
- DATABASE FORMAT CHANGE
- meme cache is now updated after reponse has been sent to reduce latency
- MIME type and file size is now sent with memes

View file

@ -40,6 +40,7 @@ use serde_json::json;
mod config;
mod meme;
mod responder;
mod util;
#[derive(Debug, StructOpt)]
struct Opt {

View file

@ -1,55 +1,66 @@
use crate::Bot;
use crate::{util, Bot};
use anyhow::Context;
use log::{error, info, warn};
use matrix_sdk::{
api::r0::media::create_content,
events::{
room::message::{
ImageMessageEventContent,
MessageEventContent,
MessageType,
VideoMessageEventContent,
room::{
message::{
ImageMessageEventContent,
MessageEventContent,
MessageType,
VideoInfo,
VideoMessageEventContent,
},
ImageInfo,
},
AnyMessageEventContent,
},
identifiers::MxcUri,
room::{Joined, Room},
UInt,
};
use mime::Mime;
use serde::{Deserialize, Serialize};
use std::{io::Cursor, sync::atomic::Ordering};
/// A meme stored in the cache database
#[derive(Debug, Deserialize, Serialize)]
struct CachedMeme {
/// mxc url of the meme
mxc: MxcUri,
ty: CachedMemeType,
/// MIME type of the meme
#[serde(with = "util::mime_serialize")]
mime: Mime,
/// file size of the meme
size: UInt,
}
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)),
}
}
}
fn into_message_type(self, name: String) -> Option<MessageType> {
let Self { mxc, mime, size } = self;
#[derive(Debug, Deserialize, Serialize)]
enum CachedMemeType {
Image,
Video,
}
impl CachedMemeType {
fn from_mime_name(name: &mime::Name) -> Option<Self> {
match *name {
mime::VIDEO => Some(Self::Video),
mime::IMAGE => Some(Self::Image),
match mime.type_() {
mime::IMAGE => Some(MessageType::Image(ImageMessageEventContent::plain(
name,
mxc,
Some(Box::new({
let mut info = ImageInfo::new();
info.mimetype = Some(mime.to_string());
info.size = Some(size);
info
})),
))),
mime::VIDEO => Some(MessageType::Video(VideoMessageEventContent::plain(
name,
mxc,
Some(Box::new({
let mut info = VideoInfo::new();
info.mimetype = Some(mime.to_string());
info.size = Some(size);
info
})),
))),
_ => None,
}
}
@ -100,8 +111,7 @@ 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 size = resp.len();
let create_content::Response { content_uri, .. } = bot
.client
.read()
@ -111,7 +121,9 @@ pub async fn on_msg(msg: &str, room: Room, bot: &Bot) -> anyhow::Result<()> {
let cached = CachedMeme {
mxc: content_uri,
ty,
mime,
size: UInt::new(size as u64)
.context("Meme has file size over allowed limit!")?,
};
bot.memecache
@ -146,7 +158,9 @@ pub async fn on_msg(msg: &str, room: Room, bot: &Bot) -> anyhow::Result<()> {
}
async fn send_meme(room: &Joined, cached: CachedMeme, meme_name: String) -> anyhow::Result<()> {
let msg_ty = cached.into_message_type(meme_name);
let msg_ty = cached
.into_message_type(meme_name)
.context("Found meme that is neither image nor video!")?;
room.send(
AnyMessageEventContent::RoomMessage(MessageEventContent::new(msg_ty)),

39
src/util.rs Normal file
View file

@ -0,0 +1,39 @@
pub mod mime_serialize {
use mime::Mime;
use serde::{
de::{self, Unexpected, Visitor},
Deserializer,
Serializer,
};
pub fn serialize<S>(data: &Mime, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&data.to_string())
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<Mime, D::Error>
where
D: Deserializer<'de>,
{
struct Vis;
impl<'de> Visitor<'de> for Vis {
type Value = Mime;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a MIME type")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
v.parse()
.map_err(|_| de::Error::invalid_value(Unexpected::Str(v), &Vis))
}
}
deserializer.deserialize_str(Vis)
}
}