2025-12-21 23:40:44 -03:00
|
|
|
|
2025-12-03 18:42:22 -03:00
|
|
|
use log::info;
|
2025-12-20 19:58:04 -03:00
|
|
|
use std::net::SocketAddr;
|
2025-12-03 18:42:22 -03:00
|
|
|
|
2025-12-04 09:03:03 -03:00
|
|
|
mod shared;
|
2025-12-03 18:42:22 -03:00
|
|
|
mod ui_server;
|
|
|
|
|
|
2025-12-20 19:58:04 -03:00
|
|
|
fn init_logging() {
|
Redesign home page with beautiful layout, add People/Contacts, rename Tools to Compliance
- Complete home page redesign with large icons, full descriptions, recent documents
- Add People (Contacts) menu item and page with contacts management
- Move Paper right after Chat in menu order
- Rename Tools to Compliance with shield icon
- Settings moved to end of menu
- Logo click now shows home page
- Add Project, Canvas, Goals, Player, Workspace, Video, Learn to menu
- New CSS for home page with modern card layout
2026-01-09 20:56:59 -03:00
|
|
|
botlib::logging::init_compact_logger("info");
|
2025-12-20 19:58:04 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn get_port() -> u16 {
|
|
|
|
|
std::env::var("BOTUI_PORT")
|
|
|
|
|
.ok()
|
|
|
|
|
.and_then(|p| p.parse().ok())
|
|
|
|
|
.unwrap_or(3000)
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-03 18:42:22 -03:00
|
|
|
#[tokio::main]
|
2025-12-20 19:58:04 -03:00
|
|
|
async fn main() -> anyhow::Result<()> {
|
|
|
|
|
init_logging();
|
|
|
|
|
|
2025-12-21 23:40:44 -03:00
|
|
|
let version = env!("CARGO_PKG_VERSION");
|
|
|
|
|
info!("BotUI {version} starting...");
|
2025-12-03 18:42:22 -03:00
|
|
|
|
|
|
|
|
let app = ui_server::configure_router();
|
2025-12-20 19:58:04 -03:00
|
|
|
let port = get_port();
|
|
|
|
|
let addr = SocketAddr::from(([0, 0, 0, 0], port));
|
2025-12-03 18:42:22 -03:00
|
|
|
|
|
|
|
|
let listener = tokio::net::TcpListener::bind(addr).await?;
|
2025-12-21 23:40:44 -03:00
|
|
|
info!("UI server listening on http://{addr}");
|
2025-12-20 19:58:04 -03:00
|
|
|
|
|
|
|
|
axum::serve(listener, app)
|
|
|
|
|
.with_graceful_shutdown(shutdown_signal())
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
|
info!("BotUI shutdown complete");
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async fn shutdown_signal() {
|
|
|
|
|
let ctrl_c = async {
|
2025-12-21 23:40:44 -03:00
|
|
|
if let Err(e) = tokio::signal::ctrl_c().await {
|
|
|
|
|
log::error!("Failed to install Ctrl+C handler: {e}");
|
|
|
|
|
}
|
2025-12-20 19:58:04 -03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#[cfg(unix)]
|
|
|
|
|
let terminate = async {
|
2025-12-21 23:40:44 -03:00
|
|
|
match tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate()) {
|
|
|
|
|
Ok(mut signal) => {
|
|
|
|
|
signal.recv().await;
|
|
|
|
|
}
|
|
|
|
|
Err(e) => {
|
|
|
|
|
log::error!("Failed to install SIGTERM handler: {e}");
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-12-20 19:58:04 -03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#[cfg(not(unix))]
|
|
|
|
|
let terminate = std::future::pending::<()>();
|
2025-12-03 18:42:22 -03:00
|
|
|
|
2025-12-20 19:58:04 -03:00
|
|
|
tokio::select! {
|
2025-12-21 23:40:44 -03:00
|
|
|
() = ctrl_c => info!("Received Ctrl+C, shutting down..."),
|
|
|
|
|
() = terminate => info!("Received SIGTERM, shutting down..."),
|
2025-12-20 19:58:04 -03:00
|
|
|
}
|
2025-12-03 18:42:22 -03:00
|
|
|
}
|