diff --git a/src/handler.rs b/src/handler.rs index dc5390b..b19004b 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -2,6 +2,7 @@ use color_eyre::eyre::{eyre, ContextCompat}; use serenity::{ async_trait, builder::CreateApplicationCommands, + http::Http, model::{ interactions::application_command::ApplicationCommandOptionType, prelude::{application_command::*, *}, @@ -12,7 +13,7 @@ use tracing::{debug, error, info}; use crate::{ lawsuit::{Lawsuit, LawsuitState}, - WrapErr, + Mongo, WrapErr, }; fn slash_commands(commands: &mut CreateApplicationCommands) -> &mut CreateApplicationCommands { @@ -103,7 +104,7 @@ impl EventHandler for Handler { let result = match command.data.name.as_str() { "lawsuit" => { - let result = lawsuit_command_handler(&command).await; + let result = lawsuit_command_handler(&command, &ctx.http, &self.mongo).await; if let Err(err) = result { error!(?err, "Error processing response"); command @@ -140,6 +141,8 @@ impl EventHandler for Handler { async fn lawsuit_command_handler( command: &ApplicationCommandInteraction, + http: impl AsRef, + mongo_client: &Mongo, ) -> color_eyre::Result<()> { let options = &command.data.options; let subcomamnd = options.get(0).wrap_err("needs subcommand")?; @@ -153,18 +156,35 @@ async fn lawsuit_command_handler( let plaintiff_layer = get_user_optional(options.get(3)).wrap_err("plaintiff_layer")?; let accused_layer = get_user_optional(options.get(4)).wrap_err("accused_layer")?; - let lawsuit = Lawsuit { + let mut lawsuit = Lawsuit { plaintiff: plaintiff.0.id, accused: accused.0.id, plaintiff_layer: plaintiff_layer.map(|l| l.0.id), accused_layer: accused_layer.map(|l| l.0.id), reason: reason.to_owned(), state: LawsuitState::Initial, - court_room: Default::default(), + court_room: None, }; + lawsuit + .initialize( + command.guild_id.wrap_err("guild_id not found")?.to_string(), + mongo_client, + ) + .await + .wrap_err("initialize lawsuit")?; + info!(?lawsuit, "Created lawsuit"); + command + .create_interaction_response(http, |res| { + res.kind(InteractionResponseType::ChannelMessageWithSource) + .interaction_response_data(|message| { + message.content("hani erstellt, keis problem") + }) + }) + .await + .wrap_err("success reponse")?; Ok(()) } _ => Err(eyre!("Unknown subcommand")), diff --git a/src/lawsuit.rs b/src/lawsuit.rs index 551bc38..9a3df51 100644 --- a/src/lawsuit.rs +++ b/src/lawsuit.rs @@ -1,5 +1,9 @@ +use color_eyre::Result; use serde::{Deserialize, Serialize}; use serenity::model::id::{ChannelId, UserId}; +use tracing::info; + +use crate::Mongo; #[derive(Debug, Clone, Copy, Serialize, Deserialize)] pub enum LawsuitState { @@ -16,5 +20,21 @@ pub struct Lawsuit { pub accused_layer: Option, pub reason: String, pub state: LawsuitState, - pub court_room: ChannelId, + pub court_room: Option, +} + +impl Lawsuit { + pub async fn initialize(&mut self, guild_id: String, mongo_client: &Mongo) -> Result<()> { + let state = mongo_client.find_state(&guild_id).await?; + + let state = match state { + Some(state) => state, + None => { + info!(%guild_id, "No state found for guild, creating new state"); + mongo_client.new_state(guild_id).await? + } + }; + + Ok(()) + } } diff --git a/src/main.rs b/src/main.rs index 99b97cd..2aa4663 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,7 +26,12 @@ async fn main() -> Result<()> { let mongo_uri = env::var("MONGO_URI").wrap_err("MONGO_URI not found in the environment")?; let db_name = env::var("DB_NAME").unwrap_or_else(|_| "court-bot".to_string()); - let mongo = Mongo::connect(&mongo_uri, &db_name).await?; + let username = env::var("MONGO_INITDB_ROOT_USERNAME") + .wrap_err("MONGO_INITDB_ROOT_USERNAME not found in the environment")?; + let password = env::var("MONGO_INITDB_ROOT_PASSWORD") + .wrap_err("MONGO_INITDB_ROOT_PASSWORD not found in the environment")?; + + let mongo = Mongo::connect(&mongo_uri, &db_name, username, password).await?; info!("Connected to mongodb"); diff --git a/src/model.rs b/src/model.rs index 5429358..3c57c07 100644 --- a/src/model.rs +++ b/src/model.rs @@ -1,43 +1,78 @@ use color_eyre::Result; -use mongodb::{options::ClientOptions, Client, Database}; +use mongodb::{ + bson::doc, + options::{ClientOptions, Credential}, + Client, Database, +}; use serde::{Deserialize, Serialize}; -use serenity::model::id::{ChannelId, GuildId}; use crate::{lawsuit::Lawsuit, WrapErr}; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct State { - pub guild_id: GuildId, + pub guild_id: String, pub lawsuits: Vec, - pub justice_category: ChannelId, + pub justice_category: Option, pub court_rooms: Vec, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct CourtRoom { - pub channel_id: ChannelId, + pub channel_id: String, pub ongoing_lawsuit: bool, } pub struct Mongo { - client: Client, db: Database, } impl Mongo { - pub async fn connect(uri: &str, db_name: &str) -> Result { + pub async fn connect( + uri: &str, + db_name: &str, + username: String, + password: String, + ) -> Result { let mut client_options = ClientOptions::parse(uri) .await .wrap_err("failed to create client options")?; client_options.app_name = Some("Discord Court Bot".to_owned()); + let mut credentials = Credential::default(); + credentials.username = Some(username); + credentials.password = Some(password); + client_options.credential = Some(credentials); let client = Client::with_options(client_options).wrap_err("failed to create client")?; let db = client.database(db_name); - Ok(Self { client, db }) + Ok(Self { db }) } - pub fn insert_lawsuit(lawsuit: &Lawsuit) {} + pub async fn find_state(&self, guild_id: &str) -> Result> { + let collection = self.db.collection("state"); + let state = collection + .find_one(doc! {"guild_id": guild_id }, None) + .await + .wrap_err("find state")?; + + Ok(state) + } + + pub async fn new_state(&self, guild_id: String) -> Result { + let state = State { + guild_id, + lawsuits: vec![], + justice_category: None, + court_rooms: vec![], + }; + + let collection = self.db.collection::("state"); + collection + .insert_one(&state, None) + .await + .wrap_err("insert state")?; + Ok(state) + } }