Add working bot

This commit is contained in:
2023-05-11 14:13:50 +01:00
parent fb6cfa8e08
commit 83c753add8
7 changed files with 2095 additions and 0 deletions
+148
View File
@@ -0,0 +1,148 @@
use std::env;
use std::error::Error;
use serenity::async_trait;
use serenity::builder::CreateApplicationCommands;
use serenity::model::application::command::Command;
use serenity::model::application::interaction::{Interaction, InteractionResponseType};
use serenity::model::gateway::Ready;
use serenity::model::id::GuildId;
use serenity::model::prelude::command::CommandOptionType;
use serenity::model::prelude::interaction::application_command::{
ApplicationCommandInteraction, CommandDataOptionValue,
};
use serenity::model::prelude::Role;
use serenity::prelude::*;
use tracing::{event, Level};
type StdErr<T> = Result<T, Box<dyn Error + Send + Sync>>;
struct Handler;
async fn user_to_role(ctx: &Context, cmd: &ApplicationCommandInteraction) -> StdErr<String> {
if let Some(role_option) = cmd.data.options.iter().find(|opt| opt.name == "role") {
if let Some(CommandDataOptionValue::Role(role)) = &role_option.resolved {
let guild_id = cmd.guild_id.ok_or("No guild id in command")?.into();
let user_id = cmd.user.id.into();
if cmd.data.name == "giverole" {
ctx.http
.add_member_role(
guild_id,
user_id,
role.id.into(),
Some("User added themselves to role via bot."),
)
.await?;
} else {
ctx.http
.remove_member_role(
guild_id,
user_id,
role.id.into(),
Some("User removed themselves from role via bot."),
)
.await?;
}
Ok("Role updated".into())
} else {
Err("Invalid role value".into())
}
} else {
Err("No role option given".into())
}
}
async fn handle(r: StdErr<String>) -> String {
r.unwrap_or_else(|error| {
event!(Level::ERROR, ?error, "Error handling command");
"Sorry, there was an error while handling that command.".into()
})
}
fn register_commands(cmds: &mut CreateApplicationCommands) -> &mut CreateApplicationCommands {
cmds.create_application_command(|cmd| cmd.name("ping").description("Go pong!"))
.create_application_command(|cmd| cmd.name("roles").description("List available roles"))
.create_application_command(|cmd| {
cmd.name("giverole")
.description("Add yourself to a role")
.create_option(|c| {
c.name("role")
.kind(CommandOptionType::Role)
.description("The role you want to be added to")
.required(true)
})
})
.create_application_command(|cmd| {
cmd.name("takerole")
.description("Remove yourself from a role")
.create_option(|c| {
c.name("role")
.kind(CommandOptionType::Role)
.description("The role you want to be removed from")
.required(true)
})
})
}
#[async_trait]
impl EventHandler for Handler {
async fn interaction_create(&self, ctx: Context, interaction: Interaction) {
if let Interaction::ApplicationCommand(command) = interaction {
println!("Received command interaction: {:#?}", command);
let content = match command.data.name.as_str() {
"ping" => "pong!".to_string(),
"giverole" => handle(user_to_role(&ctx, &command).await).await,
"takerole" => handle(user_to_role(&ctx, &command).await).await,
_ => "not implemented :(".to_string(),
};
if let Err(why) = command
.create_interaction_response(&ctx.http, |response| {
response
.kind(InteractionResponseType::ChannelMessageWithSource)
.interaction_response_data(|message| {
message.content(content).ephemeral(true)
})
})
.await
{
println!("Cannot respond to slash command: {}", why);
}
}
}
async fn ready(&self, ctx: Context, ready: Ready) {
println!("{} is connected!", ready.user.name);
// If a guild id is given, run in dev mode and register commands to that guild.
if let Ok(gid) = env::var("GUILD_ID") {
event!(Level::INFO, ?gid, "Running in debug mode for guild");
let guild_id = GuildId(gid.parse().expect("GUILD_ID must be int"));
let commands = GuildId::set_application_commands(&guild_id, &ctx.http, |commands| {
register_commands(commands)
})
.await;
} else {
let guild_command = Command::set_global_application_commands(&ctx.http, |commands| {
register_commands(commands)
})
.await;
}
}
}
#[tokio::main]
async fn main() -> StdErr<()> {
tracing_subscriber::fmt::init();
// Configure the client with your Discord bot token in the environment.
let token = env::var("DISCORD_TOKEN").expect("Expected a token in the environment");
// Build our client.
let mut client = Client::builder(token, GatewayIntents::empty())
.event_handler(Handler)
.await
.expect("Error creating client");
Ok(client.start().await?)
}