feat: reply to commands
Reply to commands in addition to executing them.
This commit is contained in:
parent
3eb8ae7ddb
commit
52257759cb
4 changed files with 112 additions and 32 deletions
45
Cargo.lock
generated
45
Cargo.lock
generated
|
@ -1,5 +1,14 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b476ce7103678b0c6d3d395dbbae31d48ff910bd28be979ba5d48c6351131d0d"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.11.0"
|
||||
|
@ -565,14 +574,15 @@ dependencies = [
|
|||
"chrono",
|
||||
"clap",
|
||||
"fern",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"matrix-sdk",
|
||||
"regex",
|
||||
"serde",
|
||||
"tokio",
|
||||
"toml",
|
||||
"tracing",
|
||||
"url",
|
||||
"wole",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -834,6 +844,24 @@ version = "0.1.57"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8963b85b8ce3074fecffde43b4b0dded83ce2f367dc8d363afc56679f3ee820b"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
"thread_local",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cab7a364d15cde1e505267766a2d3c4e22a843e1a601f0fa7564c0f82ced11c"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
version = "0.5.3"
|
||||
|
@ -1171,6 +1199,15 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.44"
|
||||
|
@ -1532,12 +1569,6 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wole"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "130532c58c60bb816f30c3975734d9c4cb78981213b6dbcf19ba86539ed36e80"
|
||||
|
||||
[[package]]
|
||||
name = "ws2_32-sys"
|
||||
version = "0.2.1"
|
||||
|
|
|
@ -9,7 +9,6 @@ license = "AGPL-3.0-only"
|
|||
|
||||
[dependencies]
|
||||
matrix-sdk = { version = "0.1.0", default_features = false, features = ["messages"] }
|
||||
wole = "0.1.3"
|
||||
fern = "0.6.0"
|
||||
chrono = "0.4.19"
|
||||
tracing = { version = "0.1.21", features = ["log"] }
|
||||
|
@ -21,4 +20,5 @@ toml = "0.5.7"
|
|||
serde = { version = "1.0.116", features = ["derive"] }
|
||||
anyhow = "1.0.33"
|
||||
clap = "2.33.3"
|
||||
matrix-wol = { path = "." }
|
||||
regex = "1.4.1"
|
||||
lazy_static = "1.4.0"
|
||||
|
|
91
src/bot.rs
91
src/bot.rs
|
@ -1,29 +1,33 @@
|
|||
use crate::{config::Host, wol};
|
||||
|
||||
use std::time::Duration;
|
||||
use std::{collections::HashMap, str::FromStr, time::Duration};
|
||||
|
||||
use tracing::{error, info};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use matrix_sdk::{
|
||||
self,
|
||||
identifiers::RoomId,
|
||||
events::{
|
||||
room::{
|
||||
member::MemberEventContent,
|
||||
message::{MessageEvent, MessageEventContent, TextMessageEventContent},
|
||||
message::{MessageEvent, MessageEventContent, TextMessageEventContent, NoticeMessageEventContent},
|
||||
},
|
||||
stripped::StrippedStateEvent,
|
||||
},
|
||||
Client, EventEmitter, SyncRoom,
|
||||
};
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
|
||||
pub(crate) struct WakeOnLanBot {
|
||||
pub(crate) client: Client,
|
||||
pub(crate) hosts: Vec<Host>,
|
||||
pub(crate) hosts: HashMap<String, Host>,
|
||||
}
|
||||
|
||||
impl WakeOnLanBot {
|
||||
pub fn new(client: Client, hosts: Vec<Host>) -> Self {
|
||||
pub fn new(client: Client, hosts: HashMap<String, Host>) -> Self {
|
||||
Self { client, hosts }
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +70,7 @@ impl EventEmitter for WakeOnLanBot {
|
|||
}
|
||||
async fn on_room_message(&self, room: SyncRoom, event: &MessageEvent) {
|
||||
match room {
|
||||
SyncRoom::Joined(_room) => {
|
||||
SyncRoom::Joined(room) => {
|
||||
let msg_body = if let MessageEvent {
|
||||
content:
|
||||
MessageEventContent::Text(TextMessageEventContent { body: msg_body, .. }),
|
||||
|
@ -78,25 +82,70 @@ impl EventEmitter for WakeOnLanBot {
|
|||
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
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Ok(command) = Command::from_str(&msg_body) {
|
||||
handle_command(command, &self.client, &self.hosts, event, &room.read().await.room_id.clone()).await;
|
||||
} else {
|
||||
//TODO: give help text
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_command(command: Command, client: &Client, hosts: &HashMap<String, Host>, event: &MessageEvent, room: &RoomId) {
|
||||
match command {
|
||||
Command::Wake { host } => {
|
||||
if let Some(host_conf) = hosts.get(&host) {
|
||||
if host_conf.users.contains(&event.sender.to_string()) {
|
||||
info!("Waking host {}", host);
|
||||
match wol::wake(host_conf.mac_addr) {
|
||||
Ok(()) => {
|
||||
info!("Magic packet sent to {} successfully", host);
|
||||
send_message(client, &format!("Successfully send magic packet to {}", host), room).await;
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Couldn't send magic packet to {}, error: {}", host, e);
|
||||
send_message(client, &format!("Failed to send magic packet to {}", host), room).await;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
send_message(client, &format!("No permission to wake up {}!", host), room).await;
|
||||
}
|
||||
} else {
|
||||
send_message(client, &format!("Host {} not found!", host), room).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn send_message(client: &Client, message: &str, room: &RoomId) {
|
||||
client.room_send(room, MessageEventContent::Notice(NoticeMessageEventContent {
|
||||
body: message.to_owned(),
|
||||
format: None,
|
||||
formatted_body: None,
|
||||
relates_to: None,
|
||||
}), None).await.unwrap(); //TODO error handling here
|
||||
}
|
||||
|
||||
enum Command {
|
||||
Wake { host: String },
|
||||
}
|
||||
|
||||
impl FromStr for Command {
|
||||
type Err = &'static str;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
lazy_static! {
|
||||
static ref RE_WAKE: Regex = Regex::new("!wake (?P<host>.*)").unwrap();
|
||||
}
|
||||
|
||||
if let Some(captures) = RE_WAKE.captures(s) {
|
||||
return Ok(Self::Wake {
|
||||
host: captures["host"].to_string(),
|
||||
});
|
||||
} else {
|
||||
return Err("Invalid command");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use anyhow::{Context, Result};
|
||||
use clap::{clap_app, crate_authors, crate_description, crate_name, crate_version};
|
||||
use serde::Deserialize;
|
||||
use std::collections::HashMap;
|
||||
use tracing::info;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
@ -8,12 +9,11 @@ pub(crate) struct Config {
|
|||
pub(crate) hs_url: String,
|
||||
pub(crate) username: String,
|
||||
pub(crate) password: String,
|
||||
pub(crate) hosts: Vec<Host>,
|
||||
pub(crate) hosts: HashMap<String, Host>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub(crate) struct Host {
|
||||
pub(crate) name: String,
|
||||
pub(crate) mac_addr: [u8; 6],
|
||||
pub(crate) users: Vec<String>,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue