Skip to content

Commit 69897e9

Browse files
committed
Minimal working TODO example
1 parent 7ff4b74 commit 69897e9

File tree

11 files changed

+824
-504
lines changed

11 files changed

+824
-504
lines changed

Cargo.lock

+375-312
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,10 @@ version = "0.1.0"
44
edition = "2021"
55

66
[dependencies]
7-
serenity = { version = "0.10", default-features = false, features = ["builder", "cache", "client", "gateway", "model", "http", "utils", "rustls_backend", "unstable_discord_api"] }
7+
async-trait = { version = "0.1.52" }
8+
serenity = { version = "0.11.1", default-features = false, features = ["client", "gateway", "model", "rustls_backend", "unstable_discord_api"] }
89
tokio = { version = "1.15.0", features = ["full"] }
10+
dotenv = { version = "0.15.0" }
11+
diesel = { version = "1.4.8", features = ["sqlite", "chrono"] }
12+
chrono = { version = "0.4", features = ["serde"] }
13+
serde = { version = "1.0.136" }

diesel.toml

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# For documentation on how to configure this file,
2+
# see diesel.rs/guides/configuring-diesel-cli
3+
4+
[print_schema]
5+
file = "src/schema.rs"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-- This file should undo anything in `up.sql`
2+
3+
DROP TABLE "todos"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-- Create TODO table
2+
3+
CREATE TABLE IF NOT EXISTS "todos" (
4+
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
5+
"channel_id" BIGINT NOT NULL,
6+
"todo" TEXT NOT NULL,
7+
"creation_date" TEXT NOT NULL,
8+
"completion_date" TEXT
9+
);

src/commands/mod.rs

+90-12
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,98 @@
1-
use serenity::model::interactions::application_command::ApplicationCommandInteraction;
1+
use async_trait::async_trait;
2+
use serenity::{
3+
builder::{CreateApplicationCommand, CreateApplicationCommands},
4+
client::Context,
5+
model::interactions::{
6+
application_command::ApplicationCommandInteraction,
7+
Interaction,
8+
InteractionResponseType,
9+
},
10+
};
11+
use std::error::Error;
212

3-
use crate::Handler;
13+
use crate::{
14+
commands::todo::TodoCommand,
15+
Secubot,
16+
};
417

5-
pub trait Command {
6-
fn execute(handler: &Handler, interaction: &ApplicationCommandInteraction) -> String;
18+
mod todo;
19+
20+
pub type CommandResult = Result<(), Box<dyn Error>>;
21+
22+
#[async_trait]
23+
pub trait Command: Send + Sync {
24+
fn get_name(&self) -> &'static str;
25+
fn add_application_command(&self, command: &mut CreateApplicationCommand);
26+
async fn handle(
27+
&self,
28+
ctx: &Context,
29+
command: &ApplicationCommandInteraction,
30+
secubot: &Secubot,
31+
) -> CommandResult;
732
}
833

9-
//use std::collections::HashMap;
34+
pub struct Commands {
35+
commands: Vec<Box<dyn Command>>,
36+
}
1037

11-
//static COMMANDS: HashMap<String, Box<dyn Command>> = HashMap::from([
12-
// ("ping".to_string(), Box::new(ping::Ping))
13-
//]);
38+
impl Commands {
39+
pub fn new() -> Self {
40+
Self {
41+
commands: Self::get_commands(),
42+
}
43+
}
1444

45+
fn get_commands() -> Vec<Box<dyn Command>> {
46+
vec![
47+
Box::new(TodoCommand::new()),
48+
]
49+
}
1550

16-
mod ping;
17-
pub use ping::Ping;
51+
pub fn register_commands(&self, commands: &mut CreateApplicationCommands) {
52+
for command in &self.commands {
53+
commands.create_application_command(|com| {
54+
command.add_application_command(com);
55+
com.name(command.get_name())
56+
});
57+
}
58+
}
1859

19-
mod todo;
20-
pub use todo::{Todo, TodoActions};
60+
pub async fn handle(&self, ctx: Context, interaction: Interaction, secubot: &Secubot) {
61+
if let Interaction::ApplicationCommand(command) = interaction {
62+
let requested_command_name = command.data.name.as_str();
63+
let bot_command_option = self
64+
.commands
65+
.iter()
66+
.find(|command| command.get_name() == requested_command_name);
67+
68+
if let Some(bot_command) = bot_command_option {
69+
//let channel_id = command.channel_id;
70+
//let http = ctx.http.clone();
71+
72+
let error_message =
73+
if let Err(e) = bot_command.handle(&ctx, &command, secubot).await {
74+
println!("Could not respond: {:?}", e);
75+
format!("Could not generate response:\n```\n{}\n```", e)
76+
} else {
77+
"".to_owned()
78+
};
79+
if !error_message.is_empty() {
80+
// Try to create message (if not exists) and then edit it (if existed already)
81+
command
82+
.create_interaction_response(&ctx.http, |response| {
83+
response.kind(InteractionResponseType::ChannelMessageWithSource)
84+
})
85+
.await;
86+
87+
command
88+
.edit_original_interaction_response(&ctx.http, |response| {
89+
response.content(error_message)
90+
})
91+
.await;
92+
}
93+
} else {
94+
println!("Invalid command received");
95+
}
96+
}
97+
}
98+
}

0 commit comments

Comments
 (0)