mod api; mod binance; mod bot; mod config; mod storage; use std::path::Path; use std::sync::Arc; use log::info; use tokio::net::TcpListener; use tokio::sync::{broadcast, Mutex}; use bot::manager::BotManager; use bot::runner::TradeEvent; use config::AppConfig; use storage::db::Database; #[derive(Clone)] pub struct AppState { pub db: Arc>, pub manager: Arc>, pub event_tx: broadcast::Sender, pub auth_token: String, } #[tokio::main] async fn main() { dotenvy::dotenv().ok(); env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init(); let cfg = AppConfig::from_env(); let db = Database::new(Path::new(&cfg.db_path)) .expect("Veritabanı başlatılamadı"); let db = Arc::new(Mutex::new(db)); let (event_tx, _) = broadcast::channel::(64); let manager = BotManager::new( Arc::clone(&db), event_tx.clone(), cfg.api_key.clone(), cfg.api_secret.clone(), ); let manager = Arc::new(Mutex::new(manager)); // Aktif botları otomatik başlat { let db_guard = db.lock().await; let bots = db_guard.get_bots().unwrap_or_default(); drop(db_guard); let mut mgr = manager.lock().await; for bot in bots.into_iter().filter(|b| b.active) { info!("Otomatik başlatılıyor: {} ({})", bot.symbol, bot.id); mgr.start(bot); } } let state = AppState { db, manager, event_tx, auth_token: cfg.auth_token, }; let router = api::routes::build(state); let listener = TcpListener::bind(&cfg.listen_addr).await .expect("Port dinlenemiyor"); info!("MSE çalışıyor: http://{}", cfg.listen_addr); axum::serve(listener, router).await.expect("Sunucu hatası"); }