matrix-wol/src/bot.rs

103 lines
3.3 KiB
Rust

use crate::{config::Host, wol};
use std::time::Duration;
use tracing::{error, info};
use async_trait::async_trait;
use matrix_sdk::{
self,
events::{
room::{
member::MemberEventContent,
message::{MessageEvent, MessageEventContent, TextMessageEventContent},
},
stripped::StrippedStateEvent,
},
Client, EventEmitter, SyncRoom,
};
pub(crate) struct WakeOnLanBot {
pub(crate) client: Client,
pub(crate) hosts: Vec<Host>,
}
impl WakeOnLanBot {
pub fn new(client: Client, hosts: Vec<Host>) -> Self {
Self { client, hosts }
}
}
#[async_trait]
impl EventEmitter for WakeOnLanBot {
async fn on_stripped_state_member(
&self,
room: SyncRoom,
_room_member: &StrippedStateEvent<MemberEventContent>,
_: Option<MemberEventContent>,
) {
match room {
SyncRoom::Invited(room) => {
let room = room.read().await;
info!("Autojoining room {}", room.room_id);
let mut delay = 2;
while let Err(err) = self.client.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
info!(
"Failed to join room {} ({:?}), retrying in {}s",
room.room_id, err, delay
);
tokio::time::delay_for(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: SyncRoom, event: &MessageEvent) {
match room {
SyncRoom::Joined(_room) => {
let msg_body = if let MessageEvent {
content:
MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }),
..
} = event
{
msg_body.clone()
} else {
String::new()
};
for host in &self.hosts {
//TODO: pull the host name out of the message and check it. If the hostname is
//invalid, complain
if msg_body == format!("!wake {}", host.name) {
if host.users.contains(&event.sender.to_string()) {
info!("Waking host {}", host.name);
//TODO: reply here
match wol::wake(host.mac_addr) {
Ok(()) => info!("Magic packet sent to {} successfully", host.name),
Err(e) => error!(
"Couldn't send magic packet to {}, error: {}",
host.name, e
),
}
}
}
}
}
_ => {}
}
}
}