use crate::album_manager::AlbumManager; use crate::error::Error; use crate::migrations::{CURRENT_DB_VERSION, do_migration}; use crate::rass::RaaSHandler; use config::{Config, File}; use j_db::database::Database; use reqwest::Url; use serde::{Deserialize, Serialize}; use serenity::model::id::ChannelId; use serenity::model::prelude::{GuildId, UserId}; use serenity::prelude::TypeMapKey; use std::net::SocketAddr; use std::path::{Path, PathBuf}; use std::sync::Arc; use j_db::metadata::DBMetadata; use structopt::StructOpt; use tokio::sync::mpsc::{channel, Receiver, Sender}; use tokio::sync::Mutex; #[derive(Debug, StructOpt)] #[structopt(name = "fren", about = "Friend Bot")] pub struct Args { pub cfg_path: PathBuf, } #[derive(Debug, Clone, Deserialize, Serialize)] pub struct PicOxConfig { api_base_url: Url, token: String, } #[derive(Debug, Deserialize, Serialize, Clone)] pub struct BotConfig { pub bot_token: String, pub img_path: PathBuf, pub base_url: Url, pub story_path: PathBuf, pub voice_path: PathBuf, pub nft_path: PathBuf, pub db_path: PathBuf, pub admins: Vec, pub guild_id: GuildId, pub api_addr: SocketAddr, pub announcement_channel: ChannelId, pub toys: Vec, pub effect_role_duration: i64, pub picox: PicOxConfig, } impl BotConfig { pub fn new(config_path: &Path) -> Result { let cfg = Config::builder() .add_source(File::from(config_path)) .build()?; cfg.try_deserialize() } } #[derive(Debug)] pub struct BotState { pub accepted_nsfw: Option, pub bad_apple_running: bool, pub speak_lock: Mutex<()>, pub raas_handler: Option, } impl BotState { pub async fn new() -> Result { Ok(Self { accepted_nsfw: None, bad_apple_running: false, speak_lock: Mutex::new(()), raas_handler: None, }) } } pub struct GlobalData { pub args: Args, pub cfg: BotConfig, pub bot_state: BotState, pub db: Database, pub picox: AlbumManager, } impl GlobalData { pub async fn new(args: Args, cfg: BotConfig) -> Result { let db = Database::new(&cfg.db_path)?; let version = db.version()?; if version == 0 { db.insert::( DBMetadata { id: None, version: CURRENT_DB_VERSION, }).unwrap(); } do_migration(&db); Ok(Self { args, bot_state: BotState::new().await?, db, cfg: cfg.clone(), picox: AlbumManager::new(cfg.picox.api_base_url, &cfg.picox.token), }) } pub async fn reload(&mut self) -> Result<(), Error> { let cfg = BotConfig::new(&self.args.cfg_path)?; self.cfg = cfg; self.bot_state = BotState::new().await?; Ok(()) } } impl TypeMapKey for GlobalData { type Value = GlobalData; } #[derive(Debug, Clone)] pub struct Channel { pub recv: Arc>>, pub send: Arc>>, } impl Channel { pub fn new() -> Self { let (send, recv) = channel::(10); Self { recv: Arc::new(Mutex::new(recv)), send: Arc::new(Mutex::new(send)), } } } impl TypeMapKey for Channel { type Value = Channel; }