mod bot; mod configs; mod context; use crate::bot::create_commands; use crate::configs::GeoffreyBotConfig; use crate::context::GeoffreyContext; use bot::commands::add_item::AddItemCommand; use bot::commands::add_location::AddLocationCommand; use bot::commands::find::FindCommand; use bot::commands::selling::SellingCommand; use bot::commands::BotCommand; use geoffrey_models::models::player::UserID; use serenity::utils::{content_safe, ContentSafeOptions}; use serenity::{ async_trait, model::{ gateway::Ready, interactions::{Interaction, InteractionResponseType}, }, prelude::*, }; use std::path::PathBuf; use structopt::StructOpt; #[derive(Debug, StructOpt, Clone)] #[structopt(name = "GeoffreyBot", about = "Geoffrey Discord Bot")] struct Args { #[structopt(env = "GEOFFREY_BOT_CONFIG", parse(from_os_str))] config: PathBuf, } struct HttpClient; impl TypeMapKey for HttpClient { type Value = serenity::client::Client; } struct Handler; #[async_trait] impl EventHandler for Handler { async fn ready(&self, ctx: Context, ready: Ready) { println!("{} is connected!", ready.user.name); let commands = create_commands(&ctx).await.unwrap(); println!("The following bot have been registered:"); for command in commands { println!( "{}: {} - {:?}", command.name, command.description, command.options ); } } async fn interaction_create(&self, ctx: Context, interaction: Interaction) { let data = ctx.data.read().await; let geoffrey_ctx = data.get::().unwrap(); if let Interaction::ApplicationCommand(command) = interaction { let user_id = UserID::DiscordUUID { discord_uuid: command.user.id.0, }; let msg = match command.data.name.as_str() { "find" => FindCommand::command(geoffrey_ctx, user_id, command.clone()).await, "selling" => SellingCommand::command(geoffrey_ctx, user_id, command.clone()).await, "add_location" => { AddLocationCommand::command(geoffrey_ctx, user_id, command.clone()).await } "add_item" => AddItemCommand::command(geoffrey_ctx, user_id, command.clone()).await, _ => "not implemented :(".to_string(), }; let msg = content_safe(&ctx.cache, &msg, &ContentSafeOptions::default()).await; command .create_interaction_response(&ctx.http, |resp| { resp.kind(InteractionResponseType::ChannelMessageWithSource) .interaction_response_data(|message| message.content(msg)) }) .await .unwrap(); } else if let Interaction::Autocomplete(auto_complete) = interaction { auto_complete .create_autocomplete_response(&ctx.http, |resp| resp) .await .unwrap() } else if let Interaction::MessageComponent(msg) = interaction { msg.create_interaction_response(&ctx.http, |resp| resp) .await .unwrap() } else if let Interaction::Ping(_) = interaction { println!("Ping recv'ed"); } } } #[tokio::main] async fn main() { let args: Args = Args::from_args(); let cfg = match GeoffreyBotConfig::new(args.config.as_path()) { Ok(cfg) => cfg, Err(e) => { println!("Error opening config: {}", e); return; } }; let mut client = Client::builder(cfg.discord.token.clone()) .event_handler(Handler) .application_id(cfg.discord.app_id) .await .expect("Error creating Geoffrey client"); { let mut data = client.data.write().await; data.insert::(GeoffreyContext { http_client: reqwest::Client::new(), cfg, }) } if let Err(why) = client.start().await { println!("Client error: {:?}", why); } }