save category

This commit is contained in:
nora 2022-06-14 22:01:10 +02:00
parent ac13fa1676
commit 9c6f958f68
3 changed files with 133 additions and 76 deletions

View file

@ -2,7 +2,6 @@ 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::*, *},
@ -84,6 +83,10 @@ pub struct Handler {
pub mongo: Mongo, pub mongo: Mongo,
} }
enum Response {
Simple(String),
}
#[async_trait] #[async_trait]
impl EventHandler for Handler { impl EventHandler for Handler {
async fn ready(&self, ctx: Context, ready: Ready) { async fn ready(&self, ctx: Context, ready: Ready) {
@ -113,56 +116,70 @@ impl EventHandler for Handler {
async fn interaction_create(&self, ctx: Context, interaction: Interaction) { async fn interaction_create(&self, ctx: Context, interaction: Interaction) {
if let Interaction::ApplicationCommand(command) = interaction { if let Interaction::ApplicationCommand(command) = interaction {
if let Err(err) = self.handle_interaction(ctx, command).await {
error!(?err, "An error occurred");
}
}
}
}
impl Handler {
async fn handle_interaction(
&self,
ctx: Context,
command: ApplicationCommandInteraction,
) -> color_eyre::Result<()> {
debug!(name = %command.data.name, "Received command interaction"); debug!(name = %command.data.name, "Received command interaction");
let result = match command.data.name.as_str() { let response = match command.data.name.as_str() {
"lawsuit" => { "lawsuit" => lawsuit_command_handler(&command, &ctx, &self.mongo).await,
let result = lawsuit_command_handler(&command, &ctx.http, &self.mongo).await; _ => Ok(Response::Simple("not implemented :(".to_owned())),
if let Err(err) = result {
error!(?err, "Error processing response");
command
.create_interaction_response(&ctx.http, |response| {
response
.kind(InteractionResponseType::ChannelMessageWithSource)
.interaction_response_data(|message| {
message.content("An error occurred")
})
})
.await
.wrap_err("error response")
} else {
Ok(())
}
}
_ => command
.create_interaction_response(&ctx.http, |response| {
response
.kind(InteractionResponseType::ChannelMessageWithSource)
.interaction_response_data(|message| {
message.content("not implemented :(")
})
})
.await
.wrap_err("not implemented response"),
}; };
if let Err(err) = result {
error!(?err, "Error sending response"); match response {
Ok(response) => self.send_response(ctx, command, response).await,
Err(err) => {
error!(?err, "Error during command execution");
self.send_response(
ctx,
command,
Response::Simple("An internal error occurred".to_owned()),
)
.await
} }
} }
} }
async fn send_response(
&self,
ctx: Context,
command: ApplicationCommandInteraction,
response: Response,
) -> color_eyre::Result<()> {
command
.create_interaction_response(&ctx.http, |res| match response {
Response::Simple(content) => res
.kind(InteractionResponseType::ChannelMessageWithSource)
.interaction_response_data(|message| message.content(content)),
})
.await
.wrap_err("sending response")?;
Ok(())
}
} }
async fn lawsuit_command_handler( async fn lawsuit_command_handler(
command: &ApplicationCommandInteraction, command: &ApplicationCommandInteraction,
http: impl AsRef<Http>, ctx: &Context,
mongo_client: &Mongo, mongo_client: &Mongo,
) -> color_eyre::Result<()> { ) -> color_eyre::Result<Response> {
let options = &command.data.options; let options = &command.data.options;
let subcomamnd = options.get(0).wrap_err("needs subcommand")?; let subcommand = options.get(0).wrap_err("needs subcommand")?;
match subcomamnd.name.as_str() { let options = &subcommand.options;
let guild_id = command.guild_id.wrap_err("guild_id not found")?.to_string();
match subcommand.name.as_str() {
"create" => { "create" => {
let options = &subcomamnd.options;
let plaintiff = UserOption::get(options.get(0)).wrap_err("plaintiff")?; let plaintiff = UserOption::get(options.get(0)).wrap_err("plaintiff")?;
let accused = UserOption::get(options.get(1)).wrap_err("accused")?; let accused = UserOption::get(options.get(1)).wrap_err("accused")?;
let reason = StringOption::get(options.get(2)).wrap_err("reason")?; let reason = StringOption::get(options.get(2)).wrap_err("reason")?;
@ -182,27 +199,34 @@ async fn lawsuit_command_handler(
}; };
lawsuit lawsuit
.initialize( .initialize(&guild_id, mongo_client)
command.guild_id.wrap_err("guild_id not found")?.to_string(),
mongo_client,
)
.await .await
.wrap_err("initialize lawsuit")?; .wrap_err("initialize lawsuit")?;
info!(?lawsuit, "Created lawsuit"); info!(?lawsuit, "Created lawsuit");
command Ok(Response::Simple("hani erstellt, keis problem".to_owned()))
.create_interaction_response(http, |res| { }
res.kind(InteractionResponseType::ChannelMessageWithSource) "set_category" => {
.interaction_response_data(|message| { let channel = ChannelOption::get(options.get(0))?;
message.content("hani erstellt, keis problem")
}) let channel = channel
}) .id
.await .to_channel(&ctx.http)
.wrap_err("success reponse")?; .await
Ok(()) .wrap_err("fetch category for set_category")?;
match channel.category() {
Some(category) => {
let id = category.id;
mongo_client
.set_court_category(&guild_id, &id.to_string())
.await?;
}
None => return Ok(Response::Simple("Das ist keine Kategorie!".to_owned())),
}
Ok(Response::Simple("isch gsetzt".to_owned()))
} }
"set_category" => Ok(()),
_ => Err(eyre!("Unknown subcommand")), _ => Err(eyre!("Unknown subcommand")),
} }
} }
@ -273,3 +297,20 @@ impl GetOption for StringOption {
} }
} }
} }
struct ChannelOption;
#[nougat::gat]
impl GetOption for ChannelOption {
type Get<'a> = &'a PartialChannel;
fn extract(
command: &ApplicationCommandInteractionDataOptionValue,
) -> crate::Result<Self::Get<'_>> {
if let ApplicationCommandInteractionDataOptionValue::Channel(channel) = command {
Ok(channel)
} else {
Err(eyre!("Expected string!"))
}
}
}

View file

@ -1,7 +1,6 @@
use color_eyre::Result; 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; use crate::Mongo;
@ -24,16 +23,8 @@ pub struct Lawsuit {
} }
impl Lawsuit { impl Lawsuit {
pub async fn initialize(&mut self, guild_id: String, mongo_client: &Mongo) -> Result<()> { pub async fn initialize(&mut self, guild_id: &str, mongo_client: &Mongo) -> Result<()> {
let state = mongo_client.find_state(&guild_id).await?; let _state = mongo_client.find_or_insert_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(()) Ok(())
} }

View file

@ -2,9 +2,10 @@ use color_eyre::Result;
use mongodb::{ use mongodb::{
bson::doc, bson::doc,
options::{ClientOptions, Credential}, options::{ClientOptions, Credential},
Client, Database, Client, Collection, Database,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tracing::info;
use crate::{lawsuit::Lawsuit, WrapErr}; use crate::{lawsuit::Lawsuit, WrapErr};
@ -12,7 +13,7 @@ use crate::{lawsuit::Lawsuit, WrapErr};
pub struct State { pub struct State {
pub guild_id: String, pub guild_id: String,
pub lawsuits: Vec<Lawsuit>, pub lawsuits: Vec<Lawsuit>,
pub justice_category: Option<String>, pub court_category: Option<String>,
pub court_rooms: Vec<CourtRoom>, pub court_rooms: Vec<CourtRoom>,
} }
@ -50,13 +51,21 @@ impl Mongo {
Ok(Self { db }) Ok(Self { db })
} }
pub async fn find_state(&self, guild_id: &str) -> Result<Option<State>> { pub async fn find_or_insert_state(&self, guild_id: &str) -> Result<State> {
let collection = self.db.collection("state"); let coll = self.state_coll();
let state = collection let state = coll
.find_one(doc! {"guild_id": guild_id }, None) .find_one(doc! {"guild_id": &guild_id }, None)
.await .await
.wrap_err("find state")?; .wrap_err("find state")?;
let state = match state {
Some(state) => state,
None => {
info!(%guild_id, "No state found for guild, creating new state");
self.new_state(guild_id.to_owned()).await?
}
};
Ok(state) Ok(state)
} }
@ -64,15 +73,31 @@ impl Mongo {
let state = State { let state = State {
guild_id, guild_id,
lawsuits: vec![], lawsuits: vec![],
justice_category: None, court_category: None,
court_rooms: vec![], court_rooms: vec![],
}; };
let collection = self.db.collection::<State>("state"); let coll = self.db.collection::<State>("state");
collection coll.insert_one(&state, None)
.insert_one(&state, None)
.await .await
.wrap_err("insert state")?; .wrap_err("insert state")?;
Ok(state) Ok(state)
} }
pub async fn set_court_category(&self, guild_id: &str, category: &str) -> Result<()> {
let _ = self.find_or_insert_state(guild_id).await?;
let coll = self.state_coll();
coll.update_one(
doc! {"guild_id": &guild_id },
doc! {"$set": { "court_category": category }},
None,
)
.await
.wrap_err("update court category")?;
Ok(())
}
fn state_coll(&self) -> Collection<State> {
self.db.collection("state")
}
} }