use crate::config::BotConfig; use crate::inventory::ItemType; use crate::models::api_key::Apikey; use crate::models::lil_fren::{ draw_dancing, draw_frankenstein, draw_gone, draw_magic, draw_mining, draw_resonance_cascade, draw_sick, draw_sleep, draw_standing, draw_tax_fraud, AliveState, LilFren, }; use crate::models::task::Task; use crate::user::User; use crate::{command, group, GlobalData}; use json::JsonValue; use serenity::all::{CreateAttachment, CreateMessage, FormattedTimestamp, FormattedTimestampStyle}; use serenity::client::Context; use serenity::framework::standard::{Args, CommandResult}; use serenity::model::channel::Message; use serenity::model::misc::EmojiIdentifier; use serenity::model::prelude::UserId; use serenity::model::Timestamp; use serenity::utils::MessageBuilder; use std::borrow::Cow; #[group] #[commands( reload, dump_db, load_db, add_key, debug_buddy, draw_buddy_states, op_give, list_tasks )] pub struct ADMIN; pub fn is_admin(user_id: &UserId, cfg: &BotConfig) -> bool { cfg.admins.contains(user_id) } #[command] async fn reload(ctx: &Context, msg: &Message, _args: Args) -> CommandResult { let mut data = ctx.data.write().await; let global_data = data.get_mut::().unwrap(); if !is_admin(&msg.author.id, &global_data.cfg) { return Ok(()); } global_data.reload().await?; msg.reply(&ctx.http, "Reload done ;)").await?; Ok(()) } #[command] async fn dump_db(ctx: &Context, msg: &Message, _args: Args) -> CommandResult { let mut data = ctx.data.write().await; let global_data = data.get_mut::().unwrap(); if !is_admin(&msg.author.id, &global_data.cfg) { return Ok(()); } let db_dump = global_data.db.dump_db()?; let output = db_dump.pretty(4); msg.author .id .create_dm_channel(&ctx.http) .await? .send_message( &ctx.http, CreateMessage::new() .content("The current DB state") .add_file(CreateAttachment::bytes( Cow::from(output.as_bytes()), "db.json".to_string(), )), ) .await?; Ok(()) } #[command] async fn load_db(ctx: &Context, msg: &Message, _args: Args) -> CommandResult { let mut data = ctx.data.write().await; let global_data = data.get_mut::().unwrap(); if !is_admin(&msg.author.id, &global_data.cfg) { return Ok(()); } if let Some(attachment) = msg.attachments.first() { let db_bytes = attachment.download().await?; let db_string = String::from_utf8(db_bytes)?; let json_value: JsonValue = match json::parse(&db_string) { Ok(v) => v, Err(e) => { msg.reply(&ctx.http, format!("Error parsing json: {}", e)) .await?; return Ok(()); } }; match global_data.db.import_db(json_value) { Ok(_) => { msg.reply(&ctx.http, "Database imported successfully") .await? } Err(err) => { msg.reply(&ctx.http, format!("Error importing db: {}", err)) .await?; return Ok(()); } }; } Ok(()) } #[command] async fn add_key(ctx: &Context, msg: &Message, args: Args) -> CommandResult { let mut data = ctx.data.write().await; let global_data = data.get_mut::().unwrap(); if !is_admin(&msg.author.id, &global_data.cfg) { return Ok(()); } let (api_key, key) = if args.len() == 1 { let user_id = args.parse::()?; let user = user_id.to_user(&ctx.http).await?; Apikey::new(&format!("{}'s Key", user.name), Some(user_id)) } else { Apikey::new(&format!("{}'s Key", msg.author.name), Some(msg.author.id)) }; global_data.db.insert::(api_key.clone())?; let dm = msg.author.create_dm_channel(&ctx.http).await?; dm.say( &ctx.http, format!("Key '{}' added. Api Key: {}", api_key.name, key), ) .await?; Ok(()) } #[command] #[description("Check little buddy stats")] async fn debug_buddy(ctx: &Context, msg: &Message, _args: Args) -> CommandResult { let mut data = ctx.data.write().await; let global_data = data.get_mut::().unwrap(); if !is_admin(&msg.author.id, &global_data.cfg) { return Ok(()); } let lil_fren = LilFren::get_lil_fren(&global_data.db)?; if let Some(lil_fren) = lil_fren { if lil_fren.is_alive() == AliveState::Alive { msg.reply( &ctx.http, format!( "Hunger: {} Thirst: {} Entertainment: {} Smarts: {} Metabolism: {} State: {:?}", lil_fren.hunger, lil_fren.thirst, lil_fren.entertainment, lil_fren.smarts, lil_fren.metabolism, lil_fren.state ), ) .await?; } else { msg.reply(&ctx.http, "Lil buddy is dead!").await?; } } else { msg.reply(&ctx.http, "Sorry no little buddy found!").await?; } Ok(()) } #[command] #[description("Check little buddy stats")] async fn draw_buddy_states(ctx: &Context, msg: &Message, args: Args) -> CommandResult { let emoji = args.parse::()?; let emoji = msg.guild_id.unwrap().emoji(&ctx.http, emoji.id).await?; msg.reply(&ctx.http, draw_standing(&emoji)).await?; msg.reply(&ctx.http, draw_dancing(&emoji)).await?; msg.reply(&ctx.http, draw_frankenstein(&emoji)).await?; msg.reply(&ctx.http, draw_sick(&emoji)).await?; msg.reply(&ctx.http, draw_magic(&emoji)).await?; msg.reply(&ctx.http, draw_resonance_cascade(&emoji)).await?; msg.reply(&ctx.http, draw_tax_fraud(&emoji)).await?; msg.reply(&ctx.http, draw_sleep(&emoji)).await?; msg.reply(&ctx.http, draw_mining(&emoji)).await?; msg.reply(&ctx.http, draw_gone()).await?; Ok(()) } #[command] #[description("Hey can I get op? I'm from planet minecraft")] async fn op_give(ctx: &Context, msg: &Message, args: Args) -> CommandResult { let mut data = ctx.data.write().await; let global_data = data.get_mut::().unwrap(); if args.is_empty() { msg.reply(&ctx.http, "You need to select an item to give") .await?; return Ok(()); } if !is_admin(&msg.author.id, &global_data.cfg) { return Ok(()); } let msg_content = args.rest().to_lowercase(); let item = match msg_content.parse::() { Ok(i) => i, Err(_) => { msg.reply(&ctx.http, "I don't know what the heck that is tbh.") .await?; return Ok(()); } }; User::give_item(&global_data.db, msg.author.id, item, 1, None)?; msg.reply( &ctx, format!("[Console] Op has given {} 1 {}", msg.author.name, item), ) .await?; Ok(()) } #[command] #[description("List scheduled tasks")] async fn list_tasks(ctx: &Context, msg: &Message) -> CommandResult { let data = ctx.data.read().await; let global_data = data.get::().unwrap(); let tasks: Vec = global_data.db.filter(|_, _task: &Task| true)?.collect(); let mut resp = MessageBuilder::new(); for task in &tasks { let timestamp = Timestamp::from(task.time); let time_tag = FormattedTimestamp::new(timestamp, Some(FormattedTimestampStyle::ShortDateTime)); resp.push_line(format!( "* **Task**: {:?} **Next Execution**: {}", task.task_type, time_tag )); } msg.reply(&ctx.http, resp.build()).await?; Ok(()) }