refacto into Bot struct
This commit is contained in:
parent
b4caf4a98b
commit
8beae909b8
170
src/main.rs
170
src/main.rs
|
@ -8,13 +8,7 @@ use std::{
|
|||
use clap::Clap;
|
||||
use matrix_sdk::{
|
||||
self, async_trait,
|
||||
events::{
|
||||
room::{
|
||||
member::MemberEventContent,
|
||||
message::{MessageEventContent, TextMessageEventContent},
|
||||
},
|
||||
StrippedStateEvent, SyncMessageEvent,
|
||||
},
|
||||
events::{room::member::MemberEventContent, StrippedStateEvent},
|
||||
Client, ClientConfig, EventEmitter, RoomState, Session, SyncSettings,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
|
@ -22,39 +16,83 @@ use thiserror::Error;
|
|||
use tokio::time::sleep;
|
||||
use url::Url;
|
||||
|
||||
struct AutoJoinBot {
|
||||
struct BadNewsBot {
|
||||
client: Client,
|
||||
config: Config,
|
||||
}
|
||||
|
||||
impl BadNewsBot {
|
||||
pub fn new(config: Config) -> anyhow::Result<Self> {
|
||||
let client_config = ClientConfig::new().store_path(config.state_dir.join("store"));
|
||||
let client = Client::new_with_config(config.homeserver.clone(), client_config)?;
|
||||
|
||||
Ok(Self { client, config })
|
||||
}
|
||||
|
||||
pub async fn init(&self) -> anyhow::Result<()> {
|
||||
load_or_init_session(&self).await?;
|
||||
|
||||
self.client
|
||||
.add_event_emitter(Box::new(AutoJoinHandler::new(self.client.clone())))
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn run(&self) {
|
||||
self.client.sync(SyncSettings::default()).await
|
||||
}
|
||||
}
|
||||
|
||||
async fn load_or_init_session(bot: &BadNewsBot) -> anyhow::Result<()> {
|
||||
let session_file = bot.config.state_dir.join("session.yaml");
|
||||
|
||||
if session_file.is_file() {
|
||||
let reader = BufReader::new(File::open(session_file)?);
|
||||
|
||||
let session: Session = serde_yaml::from_reader(reader)?;
|
||||
|
||||
bot.client.restore_login(session.clone()).await?;
|
||||
|
||||
println!("Reused session: {}, {}", session.user_id, session.device_id);
|
||||
} else {
|
||||
let response = bot
|
||||
.client
|
||||
.login(
|
||||
&bot.config.username,
|
||||
&bot.config.password,
|
||||
None,
|
||||
Some("autojoin bot"),
|
||||
)
|
||||
.await?;
|
||||
|
||||
println!("logged in as {}", bot.config.username);
|
||||
|
||||
let session = Session {
|
||||
access_token: response.access_token,
|
||||
user_id: response.user_id,
|
||||
device_id: response.device_id,
|
||||
};
|
||||
|
||||
let writer = BufWriter::new(File::create(session_file)?);
|
||||
serde_yaml::to_writer(writer, &session)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct AutoJoinHandler {
|
||||
client: Client,
|
||||
}
|
||||
|
||||
impl AutoJoinBot {
|
||||
pub fn new(client: Client) -> Self {
|
||||
impl AutoJoinHandler {
|
||||
fn new(client: Client) -> Self {
|
||||
Self { client }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl EventEmitter for AutoJoinBot {
|
||||
async fn on_room_message(
|
||||
&self,
|
||||
room: RoomState,
|
||||
event: &SyncMessageEvent<MessageEventContent>,
|
||||
) {
|
||||
if let RoomState::Joined(room) = room {
|
||||
if let SyncMessageEvent {
|
||||
content: MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }),
|
||||
sender,
|
||||
..
|
||||
} = event
|
||||
{
|
||||
let member = room.get_member(&sender).await.unwrap().unwrap();
|
||||
let name = member
|
||||
.display_name()
|
||||
.unwrap_or_else(|| member.user_id().as_str());
|
||||
println!("{}: {}", name, msg_body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter for AutoJoinHandler {
|
||||
async fn on_stripped_state_member(
|
||||
&self,
|
||||
room: RoomState,
|
||||
|
@ -95,62 +133,6 @@ impl EventEmitter for AutoJoinBot {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: use nice error handling
|
||||
async fn load_or_init_session(
|
||||
client: &Client,
|
||||
session_file: PathBuf,
|
||||
username: &str,
|
||||
password: &str,
|
||||
) -> anyhow::Result<()> {
|
||||
if session_file.is_file() {
|
||||
let reader = BufReader::new(File::open(session_file)?);
|
||||
|
||||
let session: Session = serde_yaml::from_reader(reader)?;
|
||||
|
||||
client.restore_login(session.clone()).await?;
|
||||
|
||||
println!("Reused session: {}, {}", session.user_id, session.device_id);
|
||||
} else {
|
||||
let response = client
|
||||
.login(username, password, None, Some("autojoin bot"))
|
||||
.await?;
|
||||
|
||||
println!("logged in as {}", username);
|
||||
|
||||
let session = Session {
|
||||
access_token: response.access_token,
|
||||
user_id: response.user_id,
|
||||
device_id: response.device_id,
|
||||
};
|
||||
|
||||
let writer = BufWriter::new(File::create(session_file)?);
|
||||
serde_yaml::to_writer(writer, &session)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn login_and_sync(
|
||||
homeserver_url: Url,
|
||||
username: &str,
|
||||
password: &str,
|
||||
state_dir: PathBuf,
|
||||
) -> anyhow::Result<()> {
|
||||
let client_config = ClientConfig::new().store_path(state_dir.join("store"));
|
||||
|
||||
let client = Client::new_with_config(homeserver_url, client_config)?;
|
||||
|
||||
load_or_init_session(&client, state_dir.join("session.yaml"), username, password).await?;
|
||||
|
||||
client
|
||||
.add_event_emitter(Box::new(AutoJoinBot::new(client.clone())))
|
||||
.await;
|
||||
|
||||
client.sync(SyncSettings::default()).await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
enum BadNewsError {
|
||||
#[error("problem accessing configuration file")]
|
||||
|
@ -189,11 +171,9 @@ async fn main() -> anyhow::Result<()> {
|
|||
|
||||
let config: Config = serde_yaml::from_reader(BufReader::new(File::open(config_file)?))?;
|
||||
|
||||
login_and_sync(
|
||||
config.homeserver,
|
||||
&config.username,
|
||||
&config.password,
|
||||
config.state_dir,
|
||||
)
|
||||
.await
|
||||
let bot = BadNewsBot::new(config)?;
|
||||
bot.init().await?;
|
||||
bot.run().await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue