181 lines
5.8 KiB
Rust
181 lines
5.8 KiB
Rust
use hero_websocket_server::{ServerBuilder, ServerConfig};
|
|
use clap::Parser;
|
|
|
|
#[derive(Parser, Debug)]
|
|
#[clap(author, version, about, long_about = None)]
|
|
struct Args {
|
|
#[clap(short = 'H', long, value_parser, default_value = "127.0.0.1")]
|
|
host: String,
|
|
|
|
#[clap(short, long, value_parser, default_value_t = 8443)]
|
|
port: u16,
|
|
|
|
#[clap(long, value_parser, default_value = "redis://127.0.0.1/")]
|
|
redis_url: String,
|
|
|
|
#[clap(long, help = "Enable authentication")]
|
|
auth: bool,
|
|
|
|
#[clap(long, help = "Enable TLS/WSS")]
|
|
tls: bool,
|
|
|
|
#[clap(long, value_parser, help = "Path to TLS certificate file")]
|
|
cert: Option<String>,
|
|
|
|
#[clap(long, value_parser, help = "Path to TLS private key file")]
|
|
key: Option<String>,
|
|
|
|
#[clap(long, value_parser, help = "Separate port for TLS connections")]
|
|
tls_port: Option<u16>,
|
|
|
|
#[clap(short, long, action = clap::ArgAction::Count, help = "Increase verbosity (-v for debug, -vv for trace)")]
|
|
verbose: u8,
|
|
|
|
#[clap(long, help = "Remove timestamps from log output")]
|
|
no_timestamp: bool,
|
|
|
|
#[clap(long, help = "Enable webhook handling")]
|
|
webhooks: bool,
|
|
|
|
#[clap(short, long, value_parser, help = "Path to configuration file")]
|
|
config: Option<String>,
|
|
|
|
#[clap(long, help = "Generate a sample configuration file")]
|
|
generate_config: bool,
|
|
}
|
|
|
|
#[actix_web::main]
|
|
async fn main() -> std::io::Result<()> {
|
|
let args = Args::parse();
|
|
|
|
// Handle config file generation
|
|
if args.generate_config {
|
|
let sample_config = ServerConfig::create_sample();
|
|
let config_path = "config.json";
|
|
match sample_config.to_file(config_path) {
|
|
Ok(_) => {
|
|
println!("✅ Sample configuration file generated: {}", config_path);
|
|
println!("📝 Edit the file to customize your server configuration.");
|
|
return Ok(());
|
|
}
|
|
Err(e) => {
|
|
eprintln!("❌ Failed to generate config file: {}", e);
|
|
std::process::exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Load configuration from file if provided, otherwise use CLI args
|
|
let config = if let Some(config_path) = &args.config {
|
|
match ServerConfig::from_file(config_path) {
|
|
Ok(config) => {
|
|
println!("📄 Loaded configuration from: {}", config_path);
|
|
config
|
|
}
|
|
Err(e) => {
|
|
eprintln!("❌ Failed to load config file {}: {}", config_path, e);
|
|
std::process::exit(1);
|
|
}
|
|
}
|
|
} else {
|
|
// Create config from CLI arguments
|
|
ServerConfig {
|
|
host: args.host.clone(),
|
|
port: args.port,
|
|
redis_url: args.redis_url.clone(),
|
|
auth: args.auth,
|
|
tls: args.tls,
|
|
cert: args.cert.clone(),
|
|
key: args.key.clone(),
|
|
tls_port: args.tls_port,
|
|
webhooks: args.webhooks,
|
|
circles: std::collections::HashMap::new(), // Empty circles when using CLI
|
|
}
|
|
};
|
|
|
|
// Configure logging based on verbosity level
|
|
let log_config = match args.verbose {
|
|
0 => {
|
|
// Default: suppress actix server logs, show only hero_websocket_server info and above
|
|
"warn,hero_websocket_server=info"
|
|
}
|
|
1 => {
|
|
// -v: show debug for hero_websocket_server, info for actix
|
|
"info,hero_websocket_server=debug,actix_server=info"
|
|
}
|
|
2 => {
|
|
// -vv: show debug for everything
|
|
"debug"
|
|
}
|
|
_ => {
|
|
// -vvv and above: show trace for everything
|
|
"trace"
|
|
}
|
|
};
|
|
|
|
std::env::set_var("RUST_LOG", log_config);
|
|
|
|
// Configure env_logger with or without timestamps
|
|
if args.no_timestamp {
|
|
env_logger::Builder::from_default_env()
|
|
.format_timestamp(None)
|
|
.init();
|
|
} else {
|
|
env_logger::init();
|
|
}
|
|
|
|
// Validate configuration
|
|
if let Err(e) = config.validate() {
|
|
eprintln!("❌ Configuration validation failed: {}", e);
|
|
std::process::exit(1);
|
|
}
|
|
|
|
// Build server from configuration
|
|
let builder = ServerBuilder::new().from_config(config.clone());
|
|
|
|
let server = match builder.build() {
|
|
Ok(server) => server,
|
|
Err(e) => {
|
|
eprintln!("Error building server: {}", e);
|
|
std::process::exit(1);
|
|
}
|
|
};
|
|
|
|
println!("🚀 Starting Circles WebSocket Server");
|
|
println!("📋 Configuration:");
|
|
println!(" Host: {}", config.host);
|
|
println!(" Port: {}", config.port);
|
|
println!(" Redis URL: {}", config.redis_url);
|
|
if let Some(tls_port) = config.tls_port {
|
|
println!(" TLS Port: {}", tls_port);
|
|
}
|
|
println!(" Authentication: {}", if config.auth { "ENABLED" } else { "DISABLED" });
|
|
println!(" TLS/WSS: {}", if config.tls { "ENABLED" } else { "DISABLED" });
|
|
println!(" Webhooks: {}", if config.webhooks { "ENABLED" } else { "DISABLED" });
|
|
println!(" Circles configured: {}", config.circles.len());
|
|
|
|
if config.tls {
|
|
if let (Some(cert), Some(key)) = (&config.cert, &config.key) {
|
|
println!(" Certificate: {}", cert);
|
|
println!(" Private Key: {}", key);
|
|
}
|
|
}
|
|
|
|
if config.webhooks {
|
|
println!(" Webhook secrets loaded from environment variables:");
|
|
println!(" - STRIPE_WEBHOOK_SECRET");
|
|
println!(" - IDENFY_WEBHOOK_SECRET");
|
|
}
|
|
|
|
if config.auth && !config.circles.is_empty() {
|
|
println!(" Configured circles:");
|
|
for (circle_name, members) in &config.circles {
|
|
println!(" - {}: {} members", circle_name, members.len());
|
|
}
|
|
}
|
|
println!();
|
|
|
|
let (server_task, _server_handle) = server.spawn_circle_server()?;
|
|
server_task.await?
|
|
}
|