98 lines
2.6 KiB
Rust
98 lines
2.6 KiB
Rust
use axum::{Json, Router, routing::post};
|
|
use serde::Serialize;
|
|
use std::process::Command;
|
|
use tower_http::services::ServeDir;
|
|
|
|
#[derive(Serialize)]
|
|
struct ApiResponse {
|
|
status: String,
|
|
message: String,
|
|
}
|
|
|
|
fn env_or_exit(key: &str) -> String {
|
|
std::env::var(key).unwrap_or_else(|_| {
|
|
eprintln!("Error : env {} missing", key);
|
|
std::process::exit(1);
|
|
})
|
|
}
|
|
|
|
async fn wake() -> Json<ApiResponse> {
|
|
let mac = env_or_exit("MAC_ADDRESS");
|
|
|
|
let output = Command::new("wakeonlan").arg(&mac).output();
|
|
|
|
match output {
|
|
Ok(o) if o.status.success() => Json(ApiResponse {
|
|
status: "ok".into(),
|
|
message: "Magic packet send !".into(),
|
|
}),
|
|
Ok(o) => Json(ApiResponse {
|
|
status: "error".into(),
|
|
message: String::from_utf8_lossy(&o.stderr).to_string(),
|
|
}),
|
|
Err(e) => Json(ApiResponse {
|
|
status: "error".into(),
|
|
message: e.to_string(),
|
|
}),
|
|
}
|
|
}
|
|
|
|
async fn shutdown() -> Json<ApiResponse> {
|
|
let pc_ip = env_or_exit("PC_IP");
|
|
let ssh_user = env_or_exit("SSH_USER");
|
|
let ssh_key = env_or_exit("SSH_KEY_PATH");
|
|
|
|
let output = Command::new("ssh")
|
|
.args([
|
|
"-i",
|
|
&ssh_key,
|
|
"-o",
|
|
"StrictHostKeyChecking=accept-new",
|
|
"-o",
|
|
"ConnectTimeout=5",
|
|
&format!("{}@{}", ssh_user, pc_ip),
|
|
"sudo /sbin/shutdown -h now",
|
|
])
|
|
.output();
|
|
|
|
match output {
|
|
Ok(o) if o.status.success() => Json(ApiResponse {
|
|
status: "ok".into(),
|
|
message: "Shotdown...".into(),
|
|
}),
|
|
Ok(o) => Json(ApiResponse {
|
|
status: "error".into(),
|
|
message: String::from_utf8_lossy(&o.stderr).to_string(),
|
|
}),
|
|
Err(e) => Json(ApiResponse {
|
|
status: "error".into(),
|
|
message: e.to_string(),
|
|
}),
|
|
}
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() {
|
|
dotenvy::dotenv().ok();
|
|
|
|
env_or_exit("MAC_ADDRESS");
|
|
env_or_exit("PC_IP");
|
|
env_or_exit("SSH_USER");
|
|
env_or_exit("SSH_KEY_PATH");
|
|
|
|
let port: u16 = std::env::var("PORT")
|
|
.unwrap_or_else(|_| "5050".into())
|
|
.parse()
|
|
.expect("invalid port");
|
|
|
|
let app = Router::new()
|
|
.route("/wake", post(wake))
|
|
.route("/shutdown", post(shutdown))
|
|
.nest_service("/", ServeDir::new("public"));
|
|
|
|
let addr = format!("127.0.0.1:{}", port);
|
|
println!("Started on http://{}", addr);
|
|
|
|
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
|
|
axum::serve(listener, app).await.unwrap();
|
|
}
|