WIP
This commit is contained in:
parent
3a437db2b6
commit
b34da70c8b
|
@ -6,16 +6,18 @@ use crate::discord::event_handler::Handler;
|
|||
|
||||
pub struct Client {
|
||||
serenity_client: SerenityClient,
|
||||
database_client: DatabaseClient,
|
||||
}
|
||||
|
||||
impl<'a> Client {
|
||||
async fn new() -> Self {
|
||||
impl Client {
|
||||
pub async fn new() -> Self {
|
||||
let mut database_client = DatabaseClient::new();
|
||||
database_client.connect().await;
|
||||
|
||||
let discord_token = get_env_variable("DISCORD_TOKEN");
|
||||
let intents = GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT;
|
||||
let database_client = DatabaseClient::new();
|
||||
|
||||
let event_handler = Handler {
|
||||
database: &database_client,
|
||||
database: database_client,
|
||||
};
|
||||
|
||||
let serenity_client = match SerenityClient::builder(discord_token, intents)
|
||||
|
@ -26,15 +28,10 @@ impl<'a> Client {
|
|||
Err(e) => panic!("Failed to instantiate Discord Client: {e}"),
|
||||
};
|
||||
|
||||
Client {
|
||||
serenity_client,
|
||||
database_client,
|
||||
}
|
||||
Client { serenity_client }
|
||||
}
|
||||
|
||||
pub async fn start(&mut self) {
|
||||
self.database_client.connect().await;
|
||||
|
||||
if let Err(e) = self.serenity_client.start().await {
|
||||
panic!("Could not connect the bot: {e}");
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Module for database interaction and wrapping
|
||||
|
||||
pub mod client;
|
||||
mod models;
|
||||
pub mod models;
|
||||
|
||||
pub use client::Client;
|
||||
|
|
|
@ -116,7 +116,7 @@ impl Client {
|
|||
pub async fn get_all<T: YorokobotModel + for<'de> Deserialize<'de>>(
|
||||
&self,
|
||||
filter: Option<Document>,
|
||||
) {
|
||||
) -> Vec<T> {
|
||||
let mut result: Vec<T> = vec![];
|
||||
|
||||
let mut cursor = match filter {
|
||||
|
@ -129,6 +129,8 @@ impl Client {
|
|||
result
|
||||
.push(from_bson(Bson::Document(document)).expect("Could not deserialize document"));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
|
|
@ -5,46 +5,25 @@
|
|||
use mongodb::bson::oid::ObjectId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub const COLLECTIONS_NAMES: [&str; 2] = ["guilds", "tags"];
|
||||
pub const COLLECTIONS_NAMES: [&str; 1] = ["tags"];
|
||||
|
||||
pub trait YorokobotModel {
|
||||
fn get_collection_name() -> String;
|
||||
}
|
||||
|
||||
/// Settings for a server
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GuildSettings {
|
||||
admin_only_can_tag: bool,
|
||||
server_ban_list: Vec<String>,
|
||||
}
|
||||
|
||||
/// Server infos
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Guild {
|
||||
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
|
||||
id: Option<ObjectId>,
|
||||
discord_guild_id: String,
|
||||
bot_settings: GuildSettings,
|
||||
}
|
||||
|
||||
/// Tags
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Tag {
|
||||
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
|
||||
id: Option<ObjectId>,
|
||||
name: String,
|
||||
guild: String,
|
||||
is_nsfw: bool,
|
||||
subscribers: Vec<String>,
|
||||
pub id: Option<ObjectId>,
|
||||
pub name: String,
|
||||
pub guild_id: String,
|
||||
pub is_nsfw: bool,
|
||||
pub subscribers: Vec<String>,
|
||||
}
|
||||
|
||||
impl YorokobotModel for Guild {
|
||||
fn get_collection_name() -> String {
|
||||
"guilds".to_string()
|
||||
}
|
||||
}
|
||||
impl YorokobotModel for Tag {
|
||||
fn get_collection_name() -> String {
|
||||
"traits".to_string()
|
||||
"tags".to_string()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
pub mod event_handler;
|
||||
|
||||
mod commands;
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
pub mod bulk_create_tag;
|
||||
pub mod create_tag;
|
||||
pub mod delete_tag;
|
||||
pub mod list_tags;
|
||||
pub mod source_code;
|
22
src/discord/commands/bulk_create_tag.rs
Normal file
22
src/discord/commands/bulk_create_tag.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
use serenity::{builder::CreateApplicationCommand, model::prelude::command::CommandOptionType};
|
||||
|
||||
pub fn register(
|
||||
command: &mut CreateApplicationCommand,
|
||||
max_args_number: u32,
|
||||
) -> &mut CreateApplicationCommand {
|
||||
command
|
||||
.name("bulk_create_tag")
|
||||
.description("Add multiples tags");
|
||||
|
||||
for i in 0..max_args_number {
|
||||
command.create_option(|option| {
|
||||
option
|
||||
.name(format!("tag{}", i + 1))
|
||||
.description("A new tag to add")
|
||||
.kind(CommandOptionType::String)
|
||||
.required(i == 0)
|
||||
});
|
||||
}
|
||||
|
||||
command
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
use mongodb::bson::doc;
|
||||
|
||||
use serenity::{
|
||||
builder::{CreateApplicationCommand, CreateInteractionResponseData},
|
||||
model::{
|
||||
application::interaction::application_command::ApplicationCommandInteraction,
|
||||
prelude::{
|
||||
command::CommandOptionType, interaction::application_command::CommandDataOptionValue,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
use crate::database::{models::Tag, Client as DatabaseClient};
|
||||
|
||||
pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand {
|
||||
command
|
||||
.name("create_tag")
|
||||
.description("Add a new tag")
|
||||
.create_option(|option| {
|
||||
option
|
||||
.name("tag")
|
||||
.description("The tag to create")
|
||||
.kind(CommandOptionType::String)
|
||||
.required(true)
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn run<'a, 'b>(
|
||||
response: &'a mut CreateInteractionResponseData<'b>,
|
||||
command: &ApplicationCommandInteraction,
|
||||
database: &DatabaseClient,
|
||||
) -> &'a mut CreateInteractionResponseData<'b> {
|
||||
let arg = command
|
||||
.data
|
||||
.options
|
||||
.get(0)
|
||||
.expect("Missing option")
|
||||
.resolved
|
||||
.as_ref()
|
||||
.expect("Could not deserialize option");
|
||||
|
||||
let guild_id = command
|
||||
.guild_id
|
||||
.expect("Could not fetch guild id")
|
||||
.to_string();
|
||||
|
||||
if let CommandDataOptionValue::String(tag_name) = arg {
|
||||
let matching_tags = database
|
||||
.get_all::<Tag>(Some(doc! {"name": tag_name, "guild_id": guild_id.as_str()}))
|
||||
.await;
|
||||
|
||||
if !matching_tags.is_empty() {
|
||||
response.content("This tag already exist for this server");
|
||||
} else {
|
||||
match database
|
||||
.insert_one(Tag {
|
||||
id: None,
|
||||
name: tag_name.to_string(),
|
||||
guild_id: guild_id.clone(),
|
||||
is_nsfw: false,
|
||||
subscribers: vec![],
|
||||
})
|
||||
.await
|
||||
{
|
||||
Ok(_) => response.content("Tag successfully created."),
|
||||
Err(_) => response.content("Error creating the tag"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
response
|
||||
}
|
14
src/discord/commands/delete_tag.rs
Normal file
14
src/discord/commands/delete_tag.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
use serenity::{builder::CreateApplicationCommand, model::prelude::command::CommandOptionType};
|
||||
|
||||
pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand {
|
||||
command
|
||||
.name("delete_tag")
|
||||
.description("Delete a tag")
|
||||
.create_option(|option| {
|
||||
option
|
||||
.name("tag")
|
||||
.description("The tag to delete")
|
||||
.kind(CommandOptionType::String)
|
||||
.required(true)
|
||||
})
|
||||
}
|
5
src/discord/commands/list_tags.rs
Normal file
5
src/discord/commands/list_tags.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
use serenity::builder::CreateApplicationCommand;
|
||||
|
||||
pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand {
|
||||
command.name("list_tags").description("List your own tags")
|
||||
}
|
17
src/discord/commands/source_code.rs
Normal file
17
src/discord/commands/source_code.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
use serenity::builder::{CreateApplicationCommand, CreateInteractionResponseData};
|
||||
|
||||
pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand {
|
||||
command
|
||||
.name("source_code")
|
||||
.description("Access to the bot source code")
|
||||
}
|
||||
|
||||
pub fn run<'a, 'b>(
|
||||
response: &'a mut CreateInteractionResponseData<'b>,
|
||||
) -> &'a mut CreateInteractionResponseData<'b> {
|
||||
response.embed(|embed| {
|
||||
embed
|
||||
.title("Yorokobot repository")
|
||||
.description("https://sr.ht/~victormignot/yorokobot/")
|
||||
})
|
||||
}
|
|
@ -1,87 +1,69 @@
|
|||
use crate::database::Client as DatabaseClient;
|
||||
use serenity::{
|
||||
async_trait,
|
||||
model::gateway::Ready,
|
||||
model::{
|
||||
application::command::{Command, CommandOptionType},
|
||||
prelude::ResumedEvent,
|
||||
application::command::Command,
|
||||
prelude::{
|
||||
interaction::{Interaction, InteractionResponseType},
|
||||
ResumedEvent,
|
||||
},
|
||||
},
|
||||
prelude::{Context, EventHandler},
|
||||
};
|
||||
|
||||
use crate::database::Client as DatabaseClient;
|
||||
use super::commands::*;
|
||||
|
||||
const MAX_ARGS_NUMBER: u32 = 25;
|
||||
|
||||
pub struct Handler<'a> {
|
||||
pub database: &'a DatabaseClient,
|
||||
pub struct Handler {
|
||||
pub database: DatabaseClient,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl EventHandler for Handler<'_> {
|
||||
impl EventHandler for Handler {
|
||||
async fn ready(&self, ctx: Context, ready: Ready) {
|
||||
println!("Successfully connected as {}", ready.user.name);
|
||||
|
||||
match Command::create_global_application_command(&ctx.http, |command| {
|
||||
command
|
||||
.name("create_tag")
|
||||
.description("Add a new tag")
|
||||
.create_option(|option| {
|
||||
option
|
||||
.name("tag")
|
||||
.description("The tag to create")
|
||||
.kind(CommandOptionType::String)
|
||||
.required(true)
|
||||
match Command::set_global_application_commands(&ctx.http, |commands| {
|
||||
commands
|
||||
.create_application_command(|command| source_code::register(command))
|
||||
.create_application_command(|command| create_tag::register(command))
|
||||
.create_application_command(|command| {
|
||||
bulk_create_tag::register(command, MAX_ARGS_NUMBER)
|
||||
})
|
||||
.create_application_command(|command| delete_tag::register(command))
|
||||
.create_application_command(|command| list_tags::register(command))
|
||||
})
|
||||
.await
|
||||
{
|
||||
Ok(_) => println!("Successfully registered create_tag command"),
|
||||
Err(e) => println!("Failed to register create_tag command : {e}"),
|
||||
};
|
||||
|
||||
match Command::create_global_application_command(&ctx.http, |command| {
|
||||
let command = command
|
||||
.name("bulk_create_tag")
|
||||
.description("Add multiples tags");
|
||||
|
||||
for i in 0..MAX_ARGS_NUMBER {
|
||||
command.create_option(|option| {
|
||||
option
|
||||
.name(format!("tag{}", i + 1))
|
||||
.description("A new tag to add")
|
||||
.kind(CommandOptionType::String)
|
||||
.required(i == 0)
|
||||
});
|
||||
}
|
||||
|
||||
command
|
||||
})
|
||||
.await
|
||||
{
|
||||
Ok(_) => println!("Successfully registered bulk_create_tag command"),
|
||||
Err(e) => println!("Failed to register bulk_create_tag command: {e}"),
|
||||
};
|
||||
|
||||
match Command::create_global_application_command(&ctx.http, |command| {
|
||||
command
|
||||
.name("delete_tag")
|
||||
.description("Delete a tag")
|
||||
.create_option(|option| {
|
||||
option
|
||||
.name("tag")
|
||||
.description("The tag to delete")
|
||||
.kind(CommandOptionType::String)
|
||||
.required(true)
|
||||
})
|
||||
})
|
||||
.await
|
||||
{
|
||||
Ok(_) => println!("Successfully registered delete_tag command"),
|
||||
Err(e) => println!("Failed to register delete_tag command: {e}"),
|
||||
Ok(_) => println!("Successfully registered application commands"),
|
||||
Err(e) => println!("Failed to register application commands: {e}"),
|
||||
};
|
||||
}
|
||||
|
||||
async fn resume(&self, _: Context, _: ResumedEvent) {
|
||||
println!("Successfully reconnected.")
|
||||
}
|
||||
|
||||
async fn interaction_create(&self, ctx: Context, interaction: Interaction) {
|
||||
if let Interaction::ApplicationCommand(command) = interaction {
|
||||
println!("Received command {}", command.data.name);
|
||||
|
||||
if let Err(e) = command
|
||||
.create_interaction_response(&ctx.http, |response| {
|
||||
response
|
||||
.kind(InteractionResponseType::ChannelMessageWithSource)
|
||||
.interaction_response_data(|message| match command.data.name.as_str() {
|
||||
"source_code" => source_code::run(message),
|
||||
"create_tag" => create_tag::run(message, &command, &self.database),
|
||||
_ => message.content("Not yet implemented"),
|
||||
})
|
||||
})
|
||||
.await
|
||||
{
|
||||
println!("Failed to answer to command: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue