update libs

This commit is contained in:
LordMZTE 2022-01-23 15:16:51 +01:00
parent 653592649d
commit c270953ab2
4 changed files with 133 additions and 167 deletions

View file

@ -7,26 +7,26 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
anyhow = "1.0" anyhow = "1.0.53"
bincode = "1.3.3" bincode = "1.3.3"
clap = "2.33.3" clap = "3.0.10"
env_logger = "0.8.4" env_logger = "0.9.0"
log = "0.4.13" log = "0.4.14"
mime = "0.3.16" mime = "0.3.16"
mime_guess = "2.0.3" mime_guess = "2.0.3"
rand = "0.8.4" rand = "0.8.4"
serde_json = "1.0.61" serde_json = "1.0.78"
sled = "0.34.6" sled = "0.34.7"
structopt = "0.3.21" structopt = "0.3.26"
toml = "0.5.8" toml = "0.5.8"
[dependencies.libjens] [dependencies.libjens]
git = "https://tilera.xyz/git/lordmzte/libjens.git" git = "https://tilera.xyz/git/lordmzte/libjens.git"
rev = "d4a8b3" rev = "1.1.0"
[dependencies.matrix-sdk] [dependencies.matrix-sdk]
git = "https://github.com/matrix-org/matrix-rust-sdk.git" git = "https://github.com/matrix-org/matrix-rust-sdk.git"
tag = "0.3.0" rev = "c79e62d"
features = ["encryption"] features = ["encryption"]
[dependencies.url] [dependencies.url]
@ -34,9 +34,9 @@ version = "2.2.2"
features = ["serde"] features = ["serde"]
[dependencies.serde] [dependencies.serde]
version = "1.0" version = "1.0.135"
features = ["derive"] features = ["derive"]
[dependencies.tokio] [dependencies.tokio]
version = "1.7.0" version = "1.15.0"
features = ["macros"] features = ["macros"]

View file

@ -2,27 +2,37 @@ use anyhow::{anyhow, bail, Context};
use libjens::JMClient; use libjens::JMClient;
use log::{error, info, warn}; use log::{error, info, warn};
use matrix_sdk::{ use matrix_sdk::{
api::r0::session::login, config::SyncSettings,
async_trait,
deserialized_responses::SyncResponse, deserialized_responses::SyncResponse,
events::{ encryption::verification::Verification,
room::{
member::MemberEventContent,
message::{MessageEventContent, MessageType, TextMessageEventContent},
},
AnyToDeviceEvent,
StrippedStateEvent,
SyncMessageEvent,
},
room::Room, room::Room,
verification::Verification, ruma::{
EventHandler, api::client::r0::{
session::login,
uiaa::{AuthData, Password, UserIdentifier},
},
assign,
events::{
room::{
member::StrippedRoomMemberEvent,
message::{
MessageType,
RoomMessageEventContent,
SyncRoomMessageEvent,
TextMessageEventContent,
},
},
AnyToDeviceEvent,
SyncMessageEvent,
},
UserId,
},
Client,
LoopCtrl, LoopCtrl,
}; };
use rand::{rngs::StdRng, SeedableRng}; use rand::{rngs::StdRng, SeedableRng};
use sled::Db; use sled::Db;
use std::{ use std::{
collections::BTreeMap,
path::PathBuf, path::PathBuf,
sync::{ sync::{
atomic::{AtomicBool, AtomicU32}, atomic::{AtomicBool, AtomicU32},
@ -35,8 +45,6 @@ use tokio::sync::{Mutex, RwLock};
use config::Config; use config::Config;
use matrix_sdk::{self, api::r0::uiaa::AuthData, identifiers::UserId, Client, SyncSettings};
use serde_json::json;
mod config; mod config;
mod meme; mod meme;
mod responder; mod responder;
@ -63,37 +71,41 @@ async fn main() -> anyhow::Result<()> {
toml::from_slice::<Config>(&config).map_err(|e| anyhow!("Error parsing config: {}", e))?; toml::from_slice::<Config>(&config).map_err(|e| anyhow!("Error parsing config: {}", e))?;
let config = Arc::new(config); let config = Arc::new(config);
let client = Arc::new(RwLock::new(Client::new(config.homeserver_url.clone())?)); let client = Client::new(config.homeserver_url.clone())?;
let device_name = config.device_name.as_ref().map(String::as_ref); let device_name = config.device_name.as_ref().map(String::as_ref);
let login::Response { user_id, .. } = client
.read() let bot = Arc::new(Bot {
.await client: client.clone(),
.login(&config.user_id, &config.password, device_name, device_name) jm_client: RwLock::new(JMClient::new()),
.await?; memecache: sled::open(config.store_path.join("memecache"))
.map_err(|e| anyhow!("error opening memecache: {}", e))?,
config: Arc::clone(&config),
meme_count: AtomicU32::new(0),
rng: Mutex::new(StdRng::from_rng(rand::thread_rng())?),
});
client client
.write() .register_event_handler(on_stripped_state_member)
.await
.set_event_handler(Box::new(Bot {
client: Arc::clone(&client),
jm_client: RwLock::new(JMClient::new()),
memecache: sled::open(config.store_path.join("memecache"))
.map_err(|e| anyhow!("error opening memecache: {}", e))?,
config: Arc::clone(&config),
meme_count: AtomicU32::new(0),
rng: Mutex::new(StdRng::from_rng(rand::thread_rng())?),
}))
.await; .await;
let bot_ = Arc::clone(&bot);
client
.register_event_handler(move |ev, client, room| {
on_room_message(ev, client, room, Arc::clone(&bot_))
})
.await;
let login::Response { user_id, .. } = client
.login(&config.user_id, &config.password, device_name, Some("ruff"))
.await?;
let initial = AtomicBool::from(true); let initial = AtomicBool::from(true);
let initial_ref = &initial; let initial_ref = &initial;
let client_ref = &client.read().await; let client_ref = &client;
let config_ref = &config; let config_ref = &config;
let user_id_ref = &user_id; let user_id_ref = &user_id;
client client
.read()
.await
.sync_with_callback(SyncSettings::new(), |response| async move { .sync_with_callback(SyncSettings::new(), |response| async move {
if let Err(e) = on_response(&response, client_ref).await { if let Err(e) = on_response(&response, client_ref).await {
error!("Error processing response: {}", e); error!("Error processing response: {}", e);
@ -103,7 +115,7 @@ async fn main() -> anyhow::Result<()> {
if initial.load(std::sync::atomic::Ordering::SeqCst) { if initial.load(std::sync::atomic::Ordering::SeqCst) {
if let Err(e) = if let Err(e) =
on_initial_response(client_ref, &user_id_ref, &config_ref.password).await on_initial_response(client_ref, user_id_ref, &config_ref.password).await
{ {
error!("Error processing initial response: {}", e); error!("Error processing initial response: {}", e);
} }
@ -119,7 +131,7 @@ async fn main() -> anyhow::Result<()> {
} }
pub struct Bot { pub struct Bot {
client: Arc<RwLock<Client>>, client: Client,
jm_client: RwLock<JMClient>, jm_client: RwLock<JMClient>,
memecache: Db, memecache: Db,
config: Arc<Config>, config: Arc<Config>,
@ -130,77 +142,60 @@ pub struct Bot {
rng: Mutex<StdRng>, rng: Mutex<StdRng>,
} }
#[async_trait] async fn on_stripped_state_member(event: StrippedRoomMemberEvent, client: Client, room: Room) {
impl EventHandler for Bot { if event.state_key == client.user_id().await.unwrap() {
async fn on_stripped_state_member( return;
&self,
room: Room,
room_member: &StrippedStateEvent<MemberEventContent>,
_: Option<MemberEventContent>,
) {
if room_member.state_key == self.client.read().await.user_id().await.unwrap() {
return;
}
if let Room::Invited(room) = room {
info!("Autojoining room {}", room.room_id());
let mut delay = 2;
while let Err(err) = self
.client
.read()
.await
.join_room_by_id(&room.room_id())
.await
{
// retry autojoin due to synapse sending invites, before the
// invited user can join for more information see
// https://github.com/matrix-org/synapse/issues/4345
warn!(
"Failed to join room {} ({:?}), retrying in {}s",
room.room_id(),
err,
delay
);
tokio::time::sleep(Duration::from_secs(delay)).await;
delay *= 2;
if delay > 3600 {
error!("Can't join room {} ({:?})", room.room_id(), err);
break;
}
}
info!("Successfully joined room {}", room.room_id());
}
} }
async fn on_room_message(&self, room: Room, msg: &SyncMessageEvent<MessageEventContent>) { if let Room::Invited(room) = room {
if self info!("Autojoining room {}", room.room_id());
.client let mut delay = 2;
.read()
.await while let Err(err) = client.join_room_by_id(room.room_id()).await {
.user_id() // retry autojoin due to synapse sending invites, before the
.await // invited user can join for more information see
.map(|u| u == msg.sender) // https://github.com/matrix-org/synapse/issues/4345
.unwrap_or(true) warn!(
{ "Failed to join room {} ({:?}), retrying in {}s",
return; room.room_id(),
err,
delay
);
tokio::time::sleep(Duration::from_secs(delay)).await;
delay *= 2;
if delay > 3600 {
error!("Can't join room {} ({:?})", room.room_id(), err);
break;
}
} }
if let SyncMessageEvent { info!("Successfully joined room {}", room.room_id());
content: }
MessageEventContent { }
msgtype: MessageType::Text(TextMessageEventContent { body: msg_body, .. }),
.. async fn on_room_message(msg: SyncRoomMessageEvent, client: Client, room: Room, bot: Arc<Bot>) {
}, if client
.. .user_id()
} = msg .await
{ .map(|u| u == msg.sender)
if let Err(e) = responder::on_msg(msg_body, room, self).await { .unwrap_or(true)
error!("Responder error: {}", e); {
} return;
}
if let SyncMessageEvent {
content:
RoomMessageEventContent {
msgtype: MessageType::Text(TextMessageEventContent { body: msg_body, .. }),
..
},
..
} = msg
{
if let Err(e) = responder::on_msg(&msg_body, room, &bot).await {
error!("Responder error: {}", e);
} }
} }
} }
@ -253,23 +248,6 @@ async fn on_response(response: &SyncResponse, client: &Client) -> anyhow::Result
Ok(()) Ok(())
} }
fn auth_data<'a>(user: &UserId, password: &str, session: Option<&'a str>) -> AuthData<'a> {
let mut auth_parameters = BTreeMap::new();
let identifier = json!({
"type": "m.id.user",
"user": user,
});
auth_parameters.insert("identifier".to_owned(), identifier);
auth_parameters.insert("password".to_owned(), password.to_owned().into());
AuthData::DirectRequest {
kind: "m.login.password",
auth_parameters,
session,
}
}
async fn bootstrap_cross_signing( async fn bootstrap_cross_signing(
client: &Client, client: &Client,
user_id: &UserId, user_id: &UserId,
@ -278,7 +256,11 @@ async fn bootstrap_cross_signing(
info!("bootstrapping e2e"); info!("bootstrapping e2e");
if let Err(e) = client.bootstrap_cross_signing(None).await { if let Err(e) = client.bootstrap_cross_signing(None).await {
if let Some(response) = e.uiaa_response() { if let Some(response) = e.uiaa_response() {
let auth_data = auth_data(&user_id, &password, response.session.as_deref()); let auth_data = AuthData::Password(assign!(
Password::new(UserIdentifier::MatrixId(user_id.as_str()), password),
{ session: response.session.as_deref() }
));
client client
.bootstrap_cross_signing(Some(auth_data)) .bootstrap_cross_signing(Some(auth_data))
.await .await

View file

@ -2,25 +2,24 @@ use crate::{util, Bot};
use anyhow::Context; use anyhow::Context;
use log::{error, info, warn}; use log::{error, info, warn};
use matrix_sdk::{ use matrix_sdk::{
api::r0::media::create_content, room::{Joined, Room},
events::{ ruma::{
room::{ api::client::r0::media::create_content,
events::room::{
message::{ message::{
FileInfo, FileInfo,
FileMessageEventContent, FileMessageEventContent,
ImageMessageEventContent, ImageMessageEventContent,
MessageEventContent,
MessageType, MessageType,
RoomMessageEventContent,
VideoInfo, VideoInfo,
VideoMessageEventContent, VideoMessageEventContent,
}, },
ImageInfo, ImageInfo,
}, },
AnyMessageEventContent, MxcUri,
UInt,
}, },
identifiers::MxcUri,
room::{Joined, Room},
UInt,
}; };
use mime::Mime; use mime::Mime;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -30,7 +29,7 @@ use std::{io::Cursor, sync::atomic::Ordering};
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
struct CachedMeme { struct CachedMeme {
/// mxc url of the meme /// mxc url of the meme
mxc: MxcUri, mxc: Box<MxcUri>,
/// MIME type of the meme /// MIME type of the meme
#[serde(with = "util::mime_serialize")] #[serde(with = "util::mime_serialize")]
mime: Mime, mime: Mime,
@ -104,13 +103,8 @@ pub async fn on_msg(msg: &str, room: Room, bot: &Bot) -> anyhow::Result<()> {
let id = if let Ok(id) = id.parse::<u32>() { let id = if let Ok(id) = id.parse::<u32>() {
id id
} else { } else {
room.send( room.send(RoomMessageEventContent::text_plain("Invalid ID!"), None)
AnyMessageEventContent::RoomMessage(MessageEventContent::text_plain( .await?;
"Invalid ID!",
)),
None,
)
.await?;
return Ok(()); return Ok(());
}; };
@ -161,12 +155,8 @@ async fn cache_send_meme(meme_id: u32, bot: &Bot, room: Joined) -> anyhow::Resul
if let Some(mime) = mime_guess::from_path(&meme.link).first() { if let Some(mime) = mime_guess::from_path(&meme.link).first() {
let size = resp.len(); let size = resp.len();
let create_content::Response { content_uri, .. } = bot let create_content::Response { content_uri, .. } =
.client bot.client.upload(&mime, &mut Cursor::new(resp)).await?;
.read()
.await
.upload(&mime, &mut Cursor::new(resp))
.await?;
let cached = CachedMeme { let cached = CachedMeme {
mxc: content_uri, mxc: content_uri,
@ -202,10 +192,7 @@ async fn cache_send_meme(meme_id: u32, bot: &Bot, room: Joined) -> anyhow::Resul
} }
} else { } else {
room.send( room.send(
AnyMessageEventContent::RoomMessage(MessageEventContent::text_plain(&format!( RoomMessageEventContent::text_plain(format!("No meme with id '{}'", meme_id)),
"No meme with id '{}'",
meme_id
))),
None, None,
) )
.await?; .await?;
@ -216,12 +203,9 @@ async fn cache_send_meme(meme_id: u32, bot: &Bot, room: Joined) -> anyhow::Resul
async fn send_meme(room: &Joined, cached: CachedMeme) -> anyhow::Result<()> { async fn send_meme(room: &Joined, cached: CachedMeme) -> anyhow::Result<()> {
let msg_ty = cached.into_message_type(); let msg_ty = cached.into_message_type();
room.send( room.send(RoomMessageEventContent::new(msg_ty), None)
AnyMessageEventContent::RoomMessage(MessageEventContent::new(msg_ty)), .await
None, .context("Failed to send meme")?;
)
.await
.context("Failed to send meme")?;
Ok(()) Ok(())
} }

View file

@ -10,7 +10,7 @@ pub mod mime_serialize {
where where
S: Serializer, S: Serializer,
{ {
serializer.serialize_str(&data.to_string()) serializer.serialize_str(data.as_ref())
} }
pub fn deserialize<'de, D>(deserializer: D) -> Result<Mime, D::Error> pub fn deserialize<'de, D>(deserializer: D) -> Result<Mime, D::Error>