Initial commit
This commit is contained in:
commit
c2fb6ccf5f
4 changed files with 136 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
/target
|
||||||
|
config.toml
|
||||||
|
Cargo.lock
|
17
Cargo.toml
Normal file
17
Cargo.toml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
[package]
|
||||||
|
name = "frogbot"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
matrix-sdk = {version = "0.6.2", features = ["anyhow", "e2e-encryption", "socks"]}
|
||||||
|
anyhow = "1.0.71"
|
||||||
|
clap = "4.2.7"
|
||||||
|
toml = "0.7.4"
|
||||||
|
log = "0.4.17"
|
||||||
|
env_logger = "0.10.0"
|
||||||
|
tokio = {version = "1.28.1", features = ["parking_lot", "rt-multi-thread", "macros"]}
|
||||||
|
serde = {version = "1.0.163", features = ["derive"]}
|
||||||
|
tracing-subscriber = "0.3.17"
|
5
config.toml.example
Normal file
5
config.toml.example
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
homeserver = "https://myserver.example.com/"
|
||||||
|
display_name = "MyBot"
|
||||||
|
username = "mybot"
|
||||||
|
# Change this, seriously, do it
|
||||||
|
password = "supersecretpassword"
|
111
src/main.rs
Normal file
111
src/main.rs
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
use anyhow;
|
||||||
|
use toml;
|
||||||
|
use tokio;
|
||||||
|
use log::*;
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
use matrix_sdk::{
|
||||||
|
Client,
|
||||||
|
config::SyncSettings,
|
||||||
|
room::Room,
|
||||||
|
|
||||||
|
ruma::OwnedDeviceId,
|
||||||
|
ruma::api::client::uiaa,
|
||||||
|
ruma::events::room::member::StrippedRoomMemberEvent,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
struct TomlConfig {
|
||||||
|
homeserver: String,
|
||||||
|
username: String,
|
||||||
|
display_name: String,
|
||||||
|
password: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> anyhow::Result<()> {
|
||||||
|
// init logging
|
||||||
|
tracing_subscriber::fmt::init();
|
||||||
|
let config = load_config();
|
||||||
|
let client = Client::builder()
|
||||||
|
.homeserver_url(&config.homeserver)
|
||||||
|
.handle_refresh_tokens()
|
||||||
|
.build()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
// try login
|
||||||
|
client
|
||||||
|
.login_username(&config.username, &config.password)
|
||||||
|
.initial_device_display_name(&config.display_name)
|
||||||
|
.send()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
info!("Logged in successfully!");
|
||||||
|
info!("server: '{}', username: '{}', display name: '{}'", &config.homeserver, &config.username, &config.display_name);
|
||||||
|
|
||||||
|
// sync client once so we get latest events to work on before we continue
|
||||||
|
client.sync_once(SyncSettings::default()).await?;
|
||||||
|
|
||||||
|
info!("Deleting old encryption devices");
|
||||||
|
let current_device_id = client.device_id().expect("Failed to get device ID");
|
||||||
|
let old_devices: Vec<OwnedDeviceId> = client.devices().await?.devices.iter().filter(|d| d.device_id != current_device_id).map(|d| d.device_id.to_owned()).collect();
|
||||||
|
|
||||||
|
// Deleting these devices needs "user interaction" or something, so we just send password again
|
||||||
|
// and it works :D
|
||||||
|
if let Err(e) = client.delete_devices(&old_devices, None).await {
|
||||||
|
if let Some(info) = e.uiaa_response() {
|
||||||
|
let mut password = uiaa::Password::new(
|
||||||
|
uiaa::UserIdentifier::UserIdOrLocalpart(&config.username),
|
||||||
|
&config.password,
|
||||||
|
);
|
||||||
|
password.session = info.session.as_deref();
|
||||||
|
client
|
||||||
|
.delete_devices(&old_devices, Some(uiaa::AuthData::Password(password)))
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
info!("Finished deleting old encryption devices");
|
||||||
|
info!("Rejecting stale invites");
|
||||||
|
for room in client.invited_rooms() {
|
||||||
|
room.reject_invitation().await.unwrap_or_default();
|
||||||
|
}
|
||||||
|
info!("Finished rejecting stale invites");
|
||||||
|
|
||||||
|
// Add handler to deal with new room invites
|
||||||
|
// TODO: Add code to filter rooms and only accept invites for rooms in config file
|
||||||
|
client.add_event_handler(|ev: StrippedRoomMemberEvent, room: Room, client: Client| async move {
|
||||||
|
info!("Processing room member event, room type: {:?}", room.room_type());
|
||||||
|
if let Room::Invited(invited_room) = room {
|
||||||
|
let room_name = ev.content.displayname.unwrap_or(String::from(""));
|
||||||
|
let is_dm = ev.content.is_direct.unwrap_or(true);
|
||||||
|
let is_bad_room = is_dm || invited_room.is_space() || room_name.is_empty();
|
||||||
|
info!("Got invite to room: '{}' sent by '{}'", room_name, ev.sender);
|
||||||
|
if is_bad_room {
|
||||||
|
info!("This room is probably a DM, ignoring!");
|
||||||
|
if let Err(e) = invited_room.reject_invitation().await {
|
||||||
|
warn!("Failed to reject invite with error: {}", e);
|
||||||
|
}
|
||||||
|
return ();
|
||||||
|
} else {
|
||||||
|
if let Err(e) = invited_room.accept_invitation().await {
|
||||||
|
warn!("Failed to accept room invite with error: {}", e);
|
||||||
|
}
|
||||||
|
info!("Joining room!");
|
||||||
|
if let Err(e) = client.join_room_by_id(invited_room.room_id()).await {
|
||||||
|
warn!("Failed to join room with id: {} and error: {}", invited_room.room_id(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Now keep on syncing forever. `sync()` will use the latest sync token automatically.
|
||||||
|
info!("Starting sync loop");
|
||||||
|
client.sync(SyncSettings::default()).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_config() -> TomlConfig {
|
||||||
|
// fuck error handling, it's too early in the program execution for that shit
|
||||||
|
let config: TomlConfig = toml::from_str(&std::fs::read_to_string("./config.toml").unwrap()).unwrap();
|
||||||
|
return config; // see, so clean!
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue