feat: add bridge-ctl CLI for runtime control
Made-with: Cursor
This commit is contained in:
@@ -1,3 +1,93 @@
|
||||
fn main() {
|
||||
println!("bridge-ctl");
|
||||
use std::io::{BufRead, BufReader, Write};
|
||||
use std::os::unix::net::UnixStream;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(name = "bridge-ctl")]
|
||||
#[command(about = "Control a running owncast-irc-bridge instance")]
|
||||
struct Cli {
|
||||
/// Path to the bridge control socket
|
||||
#[arg(short, long, default_value = "/tmp/owncast-irc-bridge.sock")]
|
||||
socket: PathBuf,
|
||||
|
||||
#[command(subcommand)]
|
||||
command: Commands,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum Commands {
|
||||
/// Show bridge status
|
||||
Status,
|
||||
/// Control IRC connection
|
||||
Irc {
|
||||
#[command(subcommand)]
|
||||
action: ConnectionAction,
|
||||
},
|
||||
/// Control Owncast connection
|
||||
Owncast {
|
||||
#[command(subcommand)]
|
||||
action: ConnectionAction,
|
||||
},
|
||||
/// Shut down the bridge
|
||||
Quit,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum ConnectionAction {
|
||||
Connect,
|
||||
Disconnect,
|
||||
Reconnect,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let cli = Cli::parse();
|
||||
|
||||
let command_str = match &cli.command {
|
||||
Commands::Status => "status".to_string(),
|
||||
Commands::Quit => "quit".to_string(),
|
||||
Commands::Irc { action } => format!("irc {}", action_str(action)),
|
||||
Commands::Owncast { action } => format!("owncast {}", action_str(action)),
|
||||
};
|
||||
|
||||
match send_command(&cli.socket, &command_str) {
|
||||
Ok(response) => print!("{response}"),
|
||||
Err(e) => {
|
||||
eprintln!("Error: {e}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn action_str(action: &ConnectionAction) -> &'static str {
|
||||
match action {
|
||||
ConnectionAction::Connect => "connect",
|
||||
ConnectionAction::Disconnect => "disconnect",
|
||||
ConnectionAction::Reconnect => "reconnect",
|
||||
}
|
||||
}
|
||||
|
||||
fn send_command(socket_path: &PathBuf, command: &str) -> Result<String, Box<dyn std::error::Error>> {
|
||||
let mut stream = UnixStream::connect(socket_path)?;
|
||||
stream.set_read_timeout(Some(Duration::from_secs(5)))?;
|
||||
|
||||
writeln!(stream, "{command}")?;
|
||||
stream.flush()?;
|
||||
|
||||
let reader = BufReader::new(stream);
|
||||
let mut response = String::new();
|
||||
for line in reader.lines() {
|
||||
match line {
|
||||
Ok(l) => {
|
||||
response.push_str(&l);
|
||||
response.push('\n');
|
||||
}
|
||||
Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => break,
|
||||
Err(ref e) if e.kind() == std::io::ErrorKind::TimedOut => break,
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
}
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user