103 lines
3.3 KiB
Rust
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
|
|
),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|