This commit is contained in:
nora 2022-06-19 19:47:08 +02:00
parent ccdc51f826
commit 36b4a9d5b0
6 changed files with 81 additions and 98 deletions

1
Cargo.lock generated
View file

@ -206,7 +206,6 @@ dependencies = [
"poise", "poise",
"serde", "serde",
"serde_json", "serde_json",
"serenity",
"tokio", "tokio",
"tracing", "tracing",
"tracing-subscriber", "tracing-subscriber",

View file

@ -15,8 +15,3 @@ tracing-subscriber = { version = "0.3.11", features = ["env-filter"] }
serde = { version = "1.0.137", features = ["derive"] } serde = { version = "1.0.137", features = ["derive"] }
serde_json = "1.0.81" serde_json = "1.0.81"
poise = "0.2.2" poise = "0.2.2"
[dependencies.serenity]
version = "0.11.2"
default-features = false
features = ["builder", "cache", "client", "gateway", "collector", "http", "rustls_backend", "tokio", "typemap_rev", "utils"]

View file

@ -1,16 +1,8 @@
use std::fmt::{Debug, Display, Formatter}; use std::fmt::{Debug, Display, Formatter};
use color_eyre::eyre::{eyre, ContextCompat}; use color_eyre::{eyre::ContextCompat, Result};
use mongodb::bson::Uuid; use mongodb::bson::Uuid;
use serenity::{ use poise::{serenity::model::prelude::*, serenity_prelude as serenity, Event};
async_trait,
builder::CreateApplicationCommands,
model::{
interactions::application_command::ApplicationCommandOptionType,
prelude::{application_command::*, *},
},
prelude::*,
};
use tracing::{debug, error, info}; use tracing::{debug, error, info};
use crate::{ use crate::{
@ -19,20 +11,6 @@ use crate::{
Mongo, Report, WrapErr, Mongo, Report, WrapErr,
}; };
fn slash_commands(commands: &mut CreateApplicationCommands) -> &mut CreateApplicationCommands {
commands.create_application_command(|command| {
command
.name("lawsuit")
.description("Einen Gerichtsprozess starten")
.create_option(|option| {
option
.name("clear")
.description("Alle Rechtsprozessdaten löschen")
.kind(ApplicationCommandOptionType::SubCommand)
})
})
}
pub struct Handler { pub struct Handler {
pub dev_guild_id: Option<GuildId>, pub dev_guild_id: Option<GuildId>,
pub set_global_commands: bool, pub set_global_commands: bool,
@ -60,15 +38,9 @@ impl Display for Response {
} }
} }
} }
/*
#[async_trait] #[async_trait]
impl EventHandler for Handler { impl EventHandler for Handler {
async fn guild_member_addition(&self, ctx: Context, new_member: Member) {
if let Err(err) = self.handle_guild_member_join(ctx, new_member).await {
error!(?err, "An error occurred in guild_member_addition handler");
}
}
async fn ready(&self, ctx: Context, ready: Ready) { async fn ready(&self, ctx: Context, ready: Ready) {
info!(name = %ready.user.name, "Bot is connected!"); info!(name = %ready.user.name, "Bot is connected!");
@ -93,13 +65,13 @@ impl EventHandler for Handler {
} }
} }
} }
*/
impl Handler { impl Handler {
async fn handle_guild_member_join( async fn handle_guild_member_join(
&self, &self,
ctx: Context, ctx: &serenity::Context,
mut member: Member, member: &Member,
) -> color_eyre::Result<()> { ) -> Result<()> {
let guild_id = member.guild_id; let guild_id = member.guild_id;
let user_id = member.user.id; let user_id = member.user.id;
let state = self.mongo.find_or_insert_state(guild_id.into()).await?; let state = self.mongo.find_or_insert_state(guild_id.into()).await?;
@ -116,6 +88,7 @@ impl Handler {
info!("New member was in prison, giving them the prison role"); info!("New member was in prison, giving them the prison role");
member member
.clone()
.add_role(&ctx.http, role_id) .add_role(&ctx.http, role_id)
.await .await
.wrap_err("add role to member in prison")?; .wrap_err("add role to member in prison")?;
@ -128,9 +101,14 @@ impl Handler {
#[poise::command( #[poise::command(
slash_command, slash_command,
subcommands("prison_set_role", "prison_arrest", "prison_release") subcommands(
"lawsuit_create",
"lawsuit_set_category",
"lawsuit_close",
"lawsuit_clear"
)
)] )]
async fn lawsuit(_: crate::Context<'_>) -> color_eyre::Result<()> { pub async fn lawsuit(_: crate::Context<'_>) -> Result<()> {
unreachable!() unreachable!()
} }
@ -144,7 +122,7 @@ async fn lawsuit_create(
#[description = "Der Grund für die Klage"] reason: String, #[description = "Der Grund für die Klage"] reason: String,
#[description = "Der Anwalt des Klägers"] plaintiff_lawyer: Option<User>, #[description = "Der Anwalt des Klägers"] plaintiff_lawyer: Option<User>,
#[description = "Der Anwalt des Angeklagten"] accused_lawyer: Option<User>, #[description = "Der Anwalt des Angeklagten"] accused_lawyer: Option<User>,
) -> color_eyre::Result<()> { ) -> Result<()> {
lawsuit_create_impl( lawsuit_create_impl(
ctx, ctx,
plaintiff, plaintiff,
@ -159,42 +137,30 @@ async fn lawsuit_create(
} }
/// Die Rolle für Gefangene setzen /// Die Rolle für Gefangene setzen
#[poise::command( #[poise::command(slash_command, required_permissions = "MANAGE_GUILD")]
slash_command,
required_permissions = "MANAGE_GUILD",
on_error = "error_handler"
)]
async fn lawsuit_set_category( async fn lawsuit_set_category(
ctx: crate::Context<'_>, ctx: crate::Context<'_>,
#[description = "Die Kategorie"] category: Channel, #[description = "Die Kategorie"] category: Channel,
) -> color_eyre::Result<()> { ) -> Result<()> {
lawsuit_set_category_impl(ctx, category) lawsuit_set_category_impl(ctx, category)
.await .await
.wrap_err("lawsuit_set_category") .wrap_err("lawsuit_set_category")
} }
/// Den Gerichtsprozess abschliessen und ein Urteil fällen /// Den Gerichtsprozess abschliessen und ein Urteil fällen
#[poise::command( #[poise::command(slash_command, required_permissions = "MANAGE_GUILD")]
slash_command,
required_permissions = "MANAGE_GUILD",
on_error = "error_handler"
)]
async fn lawsuit_close( async fn lawsuit_close(
ctx: crate::Context<'_>, ctx: crate::Context<'_>,
#[description = "Das Urteil"] verdict: String, #[description = "Das Urteil"] verdict: String,
) -> color_eyre::Result<()> { ) -> Result<()> {
lawsuit_close_impl(ctx, verdict) lawsuit_close_impl(ctx, verdict)
.await .await
.wrap_err("lawsuit_close") .wrap_err("lawsuit_close")
} }
/// Alle Rechtsprozessdaten löschen /// Alle Rechtsprozessdaten löschen
#[poise::command( #[poise::command(slash_command, required_permissions = "MANAGE_GUILD")]
slash_command, async fn lawsuit_clear(ctx: crate::Context<'_>) -> Result<()> {
required_permissions = "MANAGE_GUILD",
on_error = "error_handler"
)]
async fn lawsuit_clear(ctx: crate::Context<'_>) -> color_eyre::Result<()> {
lawsuit_clear_impl(ctx).await.wrap_err("lawsuit_clear") lawsuit_clear_impl(ctx).await.wrap_err("lawsuit_clear")
} }
@ -202,20 +168,16 @@ async fn lawsuit_clear(ctx: crate::Context<'_>) -> color_eyre::Result<()> {
slash_command, slash_command,
subcommands("prison_set_role", "prison_arrest", "prison_release") subcommands("prison_set_role", "prison_arrest", "prison_release")
)] )]
async fn prison(_: crate::Context<'_>) -> color_eyre::Result<()> { pub async fn prison(_: crate::Context<'_>) -> Result<()> {
unreachable!() unreachable!()
} }
/// Die Rolle für Gefangene setzen /// Die Rolle für Gefangene setzen
#[poise::command( #[poise::command(slash_command, required_permissions = "MANAGE_GUILD")]
slash_command,
required_permissions = "MANAGE_GUILD",
on_error = "error_handler"
)]
async fn prison_set_role( async fn prison_set_role(
ctx: crate::Context<'_>, ctx: crate::Context<'_>,
#[description = "Die Rolle"] role: Role, #[description = "Die Rolle"] role: Role,
) -> color_eyre::Result<()> { ) -> Result<()> {
prison_set_role_impl(ctx, role) prison_set_role_impl(ctx, role)
.await .await
.wrap_err("prison_set_role") .wrap_err("prison_set_role")
@ -226,7 +188,7 @@ async fn prison_set_role(
async fn prison_arrest( async fn prison_arrest(
ctx: crate::Context<'_>, ctx: crate::Context<'_>,
#[description = "Die Person zum einsperren"] user: User, #[description = "Die Person zum einsperren"] user: User,
) -> color_eyre::Result<()> { ) -> Result<()> {
prison_arrest_impl(ctx, user) prison_arrest_impl(ctx, user)
.await .await
.wrap_err("prison_arrest") .wrap_err("prison_arrest")
@ -237,7 +199,7 @@ async fn prison_arrest(
async fn prison_release( async fn prison_release(
ctx: crate::Context<'_>, ctx: crate::Context<'_>,
#[description = "Die Person zum freilassen"] user: User, #[description = "Die Person zum freilassen"] user: User,
) -> color_eyre::Result<()> { ) -> Result<()> {
prison_release_impl(ctx, user) prison_release_impl(ctx, user)
.await .await
.wrap_err("prison_release") .wrap_err("prison_release")
@ -251,7 +213,7 @@ async fn lawsuit_create_impl(
reason: String, reason: String,
plaintiff_lawyer: Option<User>, plaintiff_lawyer: Option<User>,
accused_lawyer: Option<User>, accused_lawyer: Option<User>,
) -> color_eyre::Result<()> { ) -> Result<()> {
let guild_id = ctx.guild_id().wrap_err("guild_id not found")?; let guild_id = ctx.guild_id().wrap_err("guild_id not found")?;
let lawsuit = Lawsuit { let lawsuit = Lawsuit {
@ -283,10 +245,7 @@ async fn lawsuit_create_impl(
Ok(()) Ok(())
} }
async fn lawsuit_set_category_impl( async fn lawsuit_set_category_impl(ctx: crate::Context<'_>, category: Channel) -> Result<()> {
ctx: crate::Context<'_>,
category: Channel,
) -> color_eyre::Result<()> {
let guild_id = ctx.guild_id().wrap_err("guild_id not found")?; let guild_id = ctx.guild_id().wrap_err("guild_id not found")?;
//let channel = channel //let channel = channel
@ -311,7 +270,7 @@ async fn lawsuit_set_category_impl(
Ok(()) Ok(())
} }
async fn lawsuit_close_impl(ctx: crate::Context<'_>, verdict: String) -> color_eyre::Result<()> { async fn lawsuit_close_impl(ctx: crate::Context<'_>, verdict: String) -> Result<()> {
let guild_id = ctx.guild_id().wrap_err("guild_id not found")?; let guild_id = ctx.guild_id().wrap_err("guild_id not found")?;
let member = ctx.author_member().await.wrap_err("member not found")?; let member = ctx.author_member().await.wrap_err("member not found")?;
@ -379,7 +338,7 @@ async fn lawsuit_close_impl(ctx: crate::Context<'_>, verdict: String) -> color_e
Ok(()) Ok(())
} }
async fn lawsuit_clear_impl(ctx: crate::Context<'_>) -> color_eyre::Result<()> { async fn lawsuit_clear_impl(ctx: crate::Context<'_>) -> Result<()> {
let guild_id = ctx.guild_id().wrap_err("guild_id not found")?; let guild_id = ctx.guild_id().wrap_err("guild_id not found")?;
ctx.data().mongo.delete_guild(guild_id.into()).await?; ctx.data().mongo.delete_guild(guild_id.into()).await?;
@ -387,7 +346,7 @@ async fn lawsuit_clear_impl(ctx: crate::Context<'_>) -> color_eyre::Result<()> {
Ok(()) Ok(())
} }
async fn prison_set_role_impl(ctx: crate::Context<'_>, role: Role) -> color_eyre::Result<()> { async fn prison_set_role_impl(ctx: crate::Context<'_>, role: Role) -> Result<()> {
ctx.data() ctx.data()
.mongo .mongo
.set_prison_role( .set_prison_role(
@ -401,7 +360,7 @@ async fn prison_set_role_impl(ctx: crate::Context<'_>, role: Role) -> color_eyre
Ok(()) Ok(())
} }
async fn prison_arrest_impl(ctx: crate::Context<'_>, user: User) -> color_eyre::Result<()> { async fn prison_arrest_impl(ctx: crate::Context<'_>, user: User) -> Result<()> {
let mongo_client = &ctx.data().mongo; let mongo_client = &ctx.data().mongo;
let guild_id = ctx.guild_id().wrap_err("guild_id not found")?; let guild_id = ctx.guild_id().wrap_err("guild_id not found")?;
let http = &ctx.discord().http; let http = &ctx.discord().http;
@ -432,7 +391,7 @@ async fn prison_arrest_impl(ctx: crate::Context<'_>, user: User) -> color_eyre::
Ok(()) Ok(())
} }
async fn prison_release_impl(ctx: crate::Context<'_>, user: User) -> color_eyre::Result<()> { async fn prison_release_impl(ctx: crate::Context<'_>, user: User) -> Result<()> {
let mongo_client = &ctx.data().mongo; let mongo_client = &ctx.data().mongo;
let guild_id = ctx.guild_id().wrap_err("guild_id not found")?; let guild_id = ctx.guild_id().wrap_err("guild_id not found")?;
let http = &ctx.discord().http; let http = &ctx.discord().http;
@ -466,6 +425,26 @@ async fn prison_release_impl(ctx: crate::Context<'_>, user: User) -> color_eyre:
Ok(()) Ok(())
} }
async fn error_handler(error: poise::FrameworkError<'_, Handler, Report>) { pub async fn listener(
ctx: &serenity::Context,
event: &Event<'_>,
_: poise::FrameworkContext<'_, Handler, Report>,
data: &Handler,
) -> Result<()> {
match event {
Event::GuildMemberAddition { new_member } => {
if let Err(err) = data.handle_guild_member_join(ctx, &new_member).await {
error!(?err, "An error occurred in guild_member_addition handler");
}
}
Event::Ready { data_about_bot } => {
info!(name = %data_about_bot.user.name, "Bot is connected!");
}
_ => {}
}
Ok(())
}
pub async fn error_handler(error: poise::FrameworkError<'_, Handler, Report>) {
error!(?error, "Error during command execution"); error!(?error, "Error during command execution");
} }

View file

@ -2,12 +2,9 @@ use std::sync::Arc;
use color_eyre::Result; use color_eyre::Result;
use mongodb::bson::{doc, Uuid}; use mongodb::bson::{doc, Uuid};
use poise::{serenity::model::prelude::*, serenity_prelude::Http};
use poise::serenity_prelude::CreateMessage;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serenity::{
builder::CreateMessage,
http::Http,
model::{channel::PermissionOverwriteType, prelude::*, Permissions},
};
use tracing::{error, info}; use tracing::{error, info};
use crate::{ use crate::{

View file

@ -7,7 +7,7 @@ mod model;
use std::env; use std::env;
use color_eyre::{eyre::WrapErr, Report, Result}; use color_eyre::{eyre::WrapErr, Report, Result};
use serenity::{model::prelude::*, prelude::*}; use poise::serenity_prelude as serenity;
use tracing::info; use tracing::info;
use tracing_subscriber::EnvFilter; use tracing_subscriber::EnvFilter;
@ -41,7 +41,7 @@ async fn main() -> Result<()> {
let token = env::var("DISCORD_TOKEN").wrap_err("DISCORD_TOKEN not found in environment")?; let token = env::var("DISCORD_TOKEN").wrap_err("DISCORD_TOKEN not found in environment")?;
let dev_guild_id = if env::var("DEV").is_ok() { let dev_guild_id = if env::var("DEV").is_ok() {
Some(GuildId( Some(serenity::GuildId(
env::var("GUILD_ID") env::var("GUILD_ID")
.wrap_err("GUILD_ID not found in environment, must be set when DEV is set")? .wrap_err("GUILD_ID not found in environment, must be set when DEV is set")?
.parse() .parse()
@ -53,15 +53,28 @@ async fn main() -> Result<()> {
let set_global_commands = env::var("SET_GLOBAL").is_ok(); let set_global_commands = env::var("SET_GLOBAL").is_ok();
let mut client = Client::builder(token, GatewayIntents::empty()) poise::Framework::build()
.event_handler(Handler { .token(token)
.user_data_setup(move |_, _, _| {
Box::pin(async move {
Ok(Handler {
dev_guild_id, dev_guild_id,
set_global_commands, set_global_commands,
mongo, mongo,
}) })
.intents(GatewayIntents::GUILD_MEMBERS) })
})
.options(poise::FrameworkOptions {
commands: vec![handler::lawsuit(), handler::prison()],
on_error: |err| Box::pin(async { handler::error_handler(err).await }),
listener: |ctx, event, ctx2, data| {
Box::pin(async move { handler::listener(ctx, event, ctx2, data).await })
},
..Default::default()
})
.intents(serenity::GatewayIntents::GUILD_MEMBERS)
.run()
.await .await
.wrap_err("failed to create discord client")?; .wrap_err("failed to create discord client")?;
Ok(())
client.start().await.wrap_err("running client")
} }

View file

@ -11,8 +11,8 @@ use mongodb::{
options::{ClientOptions, Credential, UpdateOptions}, options::{ClientOptions, Credential, UpdateOptions},
Client, Collection, Database, Client, Collection, Database,
}; };
use poise::serenity::model::id::{ChannelId, GuildId, RoleId, UserId};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serenity::model::id::{ChannelId, GuildId, RoleId, UserId};
use tracing::info; use tracing::info;
use crate::{lawsuit::Lawsuit, WrapErr}; use crate::{lawsuit::Lawsuit, WrapErr};