implement /wol
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
use std::{collections::HashSet, sync::Arc};
|
||||
|
||||
use anyhow::Result as AnyhowResult;
|
||||
use anyhow::{Context as _, Result as AnyhowResult};
|
||||
use deltachat::{
|
||||
chat::{self, ChatId},
|
||||
contact::ContactId,
|
||||
context::Context,
|
||||
message::Message,
|
||||
};
|
||||
use eui48::MacAddress;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::config::BotConfig;
|
||||
@@ -90,7 +91,83 @@ pub async fn wol_command(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// TODO
|
||||
let mac = match args.first() {
|
||||
None => {
|
||||
match ctx_lock.config.machines.values().find(|m| m.is_default) {
|
||||
Some(machine) => machine.mac,
|
||||
None => {
|
||||
let usage = wol_usage(&ctx_lock.config);
|
||||
chat::send_text_msg(&dchat_ctx_lock, chat_id, usage).await?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(arg) => {
|
||||
if let Some(machine) = ctx_lock.config.machines.get(*arg) {
|
||||
machine.mac
|
||||
} else if let Ok(mac) = MacAddress::parse_str(arg) {
|
||||
mac
|
||||
} else {
|
||||
let usage = wol_usage(&ctx_lock.config);
|
||||
chat::send_text_msg(&dchat_ctx_lock, chat_id, usage).await?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let reply = match send_magic_packet(mac).await {
|
||||
Ok(()) => format!("Magic packet sent to {}.", mac_to_string(mac)),
|
||||
Err(e) => format!("Failed to send magic packet: {e:#}"),
|
||||
};
|
||||
chat::send_text_msg(&dchat_ctx_lock, chat_id, reply).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn wol_usage(config: &BotConfig) -> String {
|
||||
let mut forms: Vec<String> = Vec::new();
|
||||
|
||||
if config.machines.values().any(|m| m.is_default) {
|
||||
forms.push("/wol".to_owned());
|
||||
}
|
||||
|
||||
let mut names: Vec<&str> = config.machines.keys().map(String::as_str).collect();
|
||||
names.sort();
|
||||
if !names.is_empty() {
|
||||
forms.push(format!("/wol <{}>", names.join("|")));
|
||||
}
|
||||
|
||||
forms.push("/wol <XX:XX:XX:XX:XX:XX>".to_owned());
|
||||
|
||||
format!("Usage: {}", forms.join(" OR "))
|
||||
}
|
||||
|
||||
fn mac_to_string(mac: MacAddress) -> String {
|
||||
let b = mac.as_bytes();
|
||||
format!(
|
||||
"{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
|
||||
b[0], b[1], b[2], b[3], b[4], b[5]
|
||||
)
|
||||
}
|
||||
|
||||
async fn send_magic_packet(mac: MacAddress) -> AnyhowResult<()> {
|
||||
let mut packet = [0u8; 102];
|
||||
packet[..6].fill(0xFF);
|
||||
let mac_bytes = mac.as_bytes();
|
||||
for i in 0..16 {
|
||||
packet[6 + i * 6..6 + (i + 1) * 6].copy_from_slice(mac_bytes);
|
||||
}
|
||||
|
||||
let socket = tokio::net::UdpSocket::bind("0.0.0.0:0")
|
||||
.await
|
||||
.context("Failed to bind UDP socket for WoL")?;
|
||||
socket
|
||||
.set_broadcast(true)
|
||||
.context("Failed to enable broadcast on UDP socket")?;
|
||||
socket
|
||||
.send_to(&packet, "255.255.255.255:9")
|
||||
.await
|
||||
.context("Failed to send magic packet")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -111,7 +188,7 @@ pub async fn ssh_unlock_disk_command(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// TODO
|
||||
chat::send_text_msg(&dchat_ctx_lock, chat_id, format!("*ssh unlock disk* {:?}", args)).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user