This commit is contained in:
nora 2022-06-14 21:19:47 +02:00
parent 724d7467c3
commit e44c292f1f
4 changed files with 95 additions and 15 deletions

View file

@ -2,6 +2,7 @@ use color_eyre::eyre::{eyre, ContextCompat};
use serenity::{ use serenity::{
async_trait, async_trait,
builder::CreateApplicationCommands, builder::CreateApplicationCommands,
http::Http,
model::{ model::{
interactions::application_command::ApplicationCommandOptionType, interactions::application_command::ApplicationCommandOptionType,
prelude::{application_command::*, *}, prelude::{application_command::*, *},
@ -12,7 +13,7 @@ use tracing::{debug, error, info};
use crate::{ use crate::{
lawsuit::{Lawsuit, LawsuitState}, lawsuit::{Lawsuit, LawsuitState},
WrapErr, Mongo, WrapErr,
}; };
fn slash_commands(commands: &mut CreateApplicationCommands) -> &mut CreateApplicationCommands { fn slash_commands(commands: &mut CreateApplicationCommands) -> &mut CreateApplicationCommands {
@ -103,7 +104,7 @@ impl EventHandler for Handler {
let result = match command.data.name.as_str() { let result = match command.data.name.as_str() {
"lawsuit" => { "lawsuit" => {
let result = lawsuit_command_handler(&command).await; let result = lawsuit_command_handler(&command, &ctx.http, &self.mongo).await;
if let Err(err) = result { if let Err(err) = result {
error!(?err, "Error processing response"); error!(?err, "Error processing response");
command command
@ -140,6 +141,8 @@ impl EventHandler for Handler {
async fn lawsuit_command_handler( async fn lawsuit_command_handler(
command: &ApplicationCommandInteraction, command: &ApplicationCommandInteraction,
http: impl AsRef<Http>,
mongo_client: &Mongo,
) -> color_eyre::Result<()> { ) -> color_eyre::Result<()> {
let options = &command.data.options; let options = &command.data.options;
let subcomamnd = options.get(0).wrap_err("needs subcommand")?; 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 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 accused_layer = get_user_optional(options.get(4)).wrap_err("accused_layer")?;
let lawsuit = Lawsuit { let mut lawsuit = Lawsuit {
plaintiff: plaintiff.0.id, plaintiff: plaintiff.0.id,
accused: accused.0.id, accused: accused.0.id,
plaintiff_layer: plaintiff_layer.map(|l| l.0.id), plaintiff_layer: plaintiff_layer.map(|l| l.0.id),
accused_layer: accused_layer.map(|l| l.0.id), accused_layer: accused_layer.map(|l| l.0.id),
reason: reason.to_owned(), reason: reason.to_owned(),
state: LawsuitState::Initial, 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"); 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(()) Ok(())
} }
_ => Err(eyre!("Unknown subcommand")), _ => Err(eyre!("Unknown subcommand")),

View file

@ -1,5 +1,9 @@
use color_eyre::Result;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serenity::model::id::{ChannelId, UserId}; use serenity::model::id::{ChannelId, UserId};
use tracing::info;
use crate::Mongo;
#[derive(Debug, Clone, Copy, Serialize, Deserialize)] #[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum LawsuitState { pub enum LawsuitState {
@ -16,5 +20,21 @@ pub struct Lawsuit {
pub accused_layer: Option<UserId>, pub accused_layer: Option<UserId>,
pub reason: String, pub reason: String,
pub state: LawsuitState, pub state: LawsuitState,
pub court_room: ChannelId, pub court_room: Option<ChannelId>,
}
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(())
}
} }

View file

@ -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 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 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"); info!("Connected to mongodb");

View file

@ -1,43 +1,78 @@
use color_eyre::Result; use color_eyre::Result;
use mongodb::{options::ClientOptions, Client, Database}; use mongodb::{
bson::doc,
options::{ClientOptions, Credential},
Client, Database,
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serenity::model::id::{ChannelId, GuildId};
use crate::{lawsuit::Lawsuit, WrapErr}; use crate::{lawsuit::Lawsuit, WrapErr};
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct State { pub struct State {
pub guild_id: GuildId, pub guild_id: String,
pub lawsuits: Vec<Lawsuit>, pub lawsuits: Vec<Lawsuit>,
pub justice_category: ChannelId, pub justice_category: Option<String>,
pub court_rooms: Vec<CourtRoom>, pub court_rooms: Vec<CourtRoom>,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CourtRoom { pub struct CourtRoom {
pub channel_id: ChannelId, pub channel_id: String,
pub ongoing_lawsuit: bool, pub ongoing_lawsuit: bool,
} }
pub struct Mongo { pub struct Mongo {
client: Client,
db: Database, db: Database,
} }
impl Mongo { impl Mongo {
pub async fn connect(uri: &str, db_name: &str) -> Result<Self> { pub async fn connect(
uri: &str,
db_name: &str,
username: String,
password: String,
) -> Result<Self> {
let mut client_options = ClientOptions::parse(uri) let mut client_options = ClientOptions::parse(uri)
.await .await
.wrap_err("failed to create client options")?; .wrap_err("failed to create client options")?;
client_options.app_name = Some("Discord Court Bot".to_owned()); 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 client = Client::with_options(client_options).wrap_err("failed to create client")?;
let db = client.database(db_name); 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<Option<State>> {
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<State> {
let state = State {
guild_id,
lawsuits: vec![],
justice_category: None,
court_rooms: vec![],
};
let collection = self.db.collection::<State>("state");
collection
.insert_one(&state, None)
.await
.wrap_err("insert state")?;
Ok(state)
}
} }