send mime type and size with memes
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
cd1875240d
commit
6322919e6d
|
@ -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
|
||||
|
|
|
@ -40,6 +40,7 @@ use serde_json::json;
|
|||
mod config;
|
||||
mod meme;
|
||||
mod responder;
|
||||
mod util;
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
struct Opt {
|
||||
|
|
|
@ -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
39
src/util.rs
Normal 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)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue