Rearranged some commands
Working on a macro to automatically add option wrappers
This commit is contained in:
parent
d0833b7bca
commit
eb92eacb90
61
Cargo.lock
generated
61
Cargo.lock
generated
@ -123,7 +123,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -134,7 +134,7 @@ checksum = "fdf6721fb0140e4f897002dd086c06f6c27775df19cfe1fccb21181a48fd2c98"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -571,7 +571,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -582,7 +582,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -673,7 +673,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"proc-macro2-diagnostics",
|
||||
"quote",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -937,7 +937,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1440,7 +1440,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1840,7 +1840,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1925,7 +1925,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"proc-macro2-diagnostics",
|
||||
"quote",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1974,7 +1974,7 @@ dependencies = [
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2091,7 +2091,7 @@ dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2136,9 +2136,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.71"
|
||||
version = "1.0.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8"
|
||||
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@ -2151,7 +2151,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
"version_check",
|
||||
"yansi",
|
||||
]
|
||||
@ -2190,9 +2190,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
version = "1.0.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@ -2253,7 +2253,7 @@ checksum = "2566c4bf6845f2c2e83b27043c3f5dfcd5ba8f2937d6c00dc009bfb51a079dc4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2316,6 +2316,8 @@ dependencies = [
|
||||
"num-integer",
|
||||
"poise",
|
||||
"postman",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rand",
|
||||
"regex",
|
||||
"reminder_web",
|
||||
@ -2326,6 +2328,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"serde_repr",
|
||||
"sqlx",
|
||||
"syn 2.0.49",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
@ -2481,7 +2484,7 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rocket_http",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
"unicode-xid",
|
||||
"version_check",
|
||||
]
|
||||
@ -2749,7 +2752,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2781,7 +2784,7 @@ checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3241,9 +3244,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.42"
|
||||
version = "2.0.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b7d0a2c048d661a1a59fcd7355baa232f7ed34e0ee4df2eef3c1c1c0d3852d8"
|
||||
checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -3338,7 +3341,7 @@ checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3422,7 +3425,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3556,7 +3559,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3668,7 +3671,7 @@ checksum = "0b122284365ba8497be951b9a21491f70c9688eb6fddc582931a0703f6a00ece"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3898,7 +3901,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
@ -3932,7 +3935,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
@ -4204,7 +4207,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.42",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -7,6 +7,9 @@ license = "AGPL-3.0 only"
|
||||
description = "Reminder Bot for Discord, now in Rust"
|
||||
|
||||
[dependencies]
|
||||
quote = "1.0.35"
|
||||
proc-macro2 = "1.0.78"
|
||||
syn = { version = "2.0.49", features = ["full"] }
|
||||
poise = "0.6.1"
|
||||
dotenv = "0.15"
|
||||
tokio = { version = "1", features = ["process", "full"] }
|
||||
|
63
src/commands/command_macro/finish_macro.rs
Normal file
63
src/commands/command_macro/finish_macro.rs
Normal file
@ -0,0 +1,63 @@
|
||||
use poise::{serenity_prelude::CreateEmbed, CreateReply};
|
||||
|
||||
use crate::{consts::THEME_COLOR, Context, Error};
|
||||
|
||||
/// Finish current macro recording
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
rename = "finish",
|
||||
guild_only = true,
|
||||
default_member_permissions = "MANAGE_GUILD",
|
||||
identifying_name = "finish_macro"
|
||||
)]
|
||||
pub async fn finish_macro(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let key = (ctx.guild_id().unwrap(), ctx.author().id);
|
||||
|
||||
{
|
||||
let lock = ctx.data().recording_macros.read().await;
|
||||
let contained = lock.get(&key);
|
||||
|
||||
if contained.map_or(true, |r#macro| r#macro.commands.is_empty()) {
|
||||
ctx.send(
|
||||
CreateReply::default().embed(
|
||||
CreateEmbed::new()
|
||||
.title("No Macro Recorded")
|
||||
.description("Use `/macro record` to start recording a macro")
|
||||
.color(*THEME_COLOR),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
let command_macro = contained.unwrap();
|
||||
let json = serde_json::to_string(&command_macro.commands).unwrap();
|
||||
|
||||
sqlx::query!(
|
||||
"INSERT INTO command_macro (guild_id, name, description, commands) VALUES ((SELECT id FROM guilds WHERE guild = ?), ?, ?, ?)",
|
||||
command_macro.guild_id.get(),
|
||||
command_macro.name,
|
||||
command_macro.description,
|
||||
json
|
||||
)
|
||||
.execute(&ctx.data().database)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
ctx.send(
|
||||
CreateReply::default().embed(
|
||||
CreateEmbed::new()
|
||||
.title("Macro Recorded")
|
||||
.description("Use `/macro run` to execute the macro")
|
||||
.color(*THEME_COLOR),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut lock = ctx.data().recording_macros.write().await;
|
||||
lock.remove(&key);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
13
src/commands/command_macro/macro_base.rs
Normal file
13
src/commands/command_macro/macro_base.rs
Normal file
@ -0,0 +1,13 @@
|
||||
use crate::{Context, Error};
|
||||
|
||||
/// Record and replay command sequences
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
rename = "macro",
|
||||
guild_only = true,
|
||||
default_member_permissions = "MANAGE_GUILD",
|
||||
identifying_name = "macro_base"
|
||||
)]
|
||||
pub async fn macro_base(_ctx: Context<'_>) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
@ -1,18 +1,6 @@
|
||||
use crate::{Context, Error};
|
||||
|
||||
pub mod delete;
|
||||
pub mod list;
|
||||
pub mod record;
|
||||
pub mod run;
|
||||
|
||||
/// Record and replay command sequences
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
rename = "macro",
|
||||
guild_only = true,
|
||||
default_member_permissions = "MANAGE_GUILD",
|
||||
identifying_name = "macro_base"
|
||||
)]
|
||||
pub async fn macro_base(_ctx: Context<'_>) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
pub mod delete_macro;
|
||||
pub mod finish_macro;
|
||||
pub mod list_macro;
|
||||
pub mod macro_base;
|
||||
pub mod record_macro;
|
||||
pub mod run_macro;
|
||||
|
@ -100,63 +100,3 @@ Please use `/macro finish` to end this recording before starting another.",
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Finish current macro recording
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
rename = "finish",
|
||||
guild_only = true,
|
||||
default_member_permissions = "MANAGE_GUILD",
|
||||
identifying_name = "finish_macro"
|
||||
)]
|
||||
pub async fn finish_macro(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let key = (ctx.guild_id().unwrap(), ctx.author().id);
|
||||
|
||||
{
|
||||
let lock = ctx.data().recording_macros.read().await;
|
||||
let contained = lock.get(&key);
|
||||
|
||||
if contained.map_or(true, |r#macro| r#macro.commands.is_empty()) {
|
||||
ctx.send(
|
||||
CreateReply::default().embed(
|
||||
CreateEmbed::new()
|
||||
.title("No Macro Recorded")
|
||||
.description("Use `/macro record` to start recording a macro")
|
||||
.color(*THEME_COLOR),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
let command_macro = contained.unwrap();
|
||||
let json = serde_json::to_string(&command_macro.commands).unwrap();
|
||||
|
||||
sqlx::query!(
|
||||
"INSERT INTO command_macro (guild_id, name, description, commands) VALUES ((SELECT id FROM guilds WHERE guild = ?), ?, ?, ?)",
|
||||
command_macro.guild_id.get(),
|
||||
command_macro.name,
|
||||
command_macro.description,
|
||||
json
|
||||
)
|
||||
.execute(&ctx.data().database)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
ctx.send(
|
||||
CreateReply::default().embed(
|
||||
CreateEmbed::new()
|
||||
.title("Macro Recorded")
|
||||
.description("Use `/macro run` to execute the macro")
|
||||
.color(*THEME_COLOR),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut lock = ctx.data().recording_macros.write().await;
|
||||
lock.remove(&key);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
80
src/commands/command_proc/mod.rs
Normal file
80
src/commands/command_proc/mod.rs
Normal file
@ -0,0 +1,80 @@
|
||||
use proc_macro2::{Ident, Span, TokenStream};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use syn::{punctuated::Punctuated, token::Comma, FnArg, Pat};
|
||||
|
||||
struct RecordableCommand<T: Serialize + DeserializeOwned, R> {
|
||||
args: T,
|
||||
func: dyn Fn(T) -> R,
|
||||
}
|
||||
|
||||
/// Takes a function and produces a serializable struct of its args.
|
||||
pub fn arg_struct(mut function: syn::ItemFn) -> TokenStream {
|
||||
let struct_name = Ident::new(&format!("{}_args", function.sig.ident), Span::call_site());
|
||||
let wrapped_fn_name = Ident::new(&format!("{}_fn", function.sig.ident), Span::call_site());
|
||||
|
||||
let fn_name = &function.sig.ident;
|
||||
let fn_generics = &function.sig.generics;
|
||||
let fn_inputs = &function.sig.inputs;
|
||||
let fn_args = &function
|
||||
.sig
|
||||
.inputs
|
||||
.iter()
|
||||
.map(|arg| match arg {
|
||||
FnArg::Receiver(_) => {
|
||||
panic!("Can't accept Receiver arg")
|
||||
}
|
||||
FnArg::Typed(p) => p.pat.clone(),
|
||||
})
|
||||
.collect::<Punctuated<Box<Pat>, Comma>>();
|
||||
let fn_retval = &function.sig.output;
|
||||
let fn_body = &function.block;
|
||||
|
||||
quote::quote! {
|
||||
pub async fn #fn_name #fn_generics(#fn_inputs) -> #fn_retval {
|
||||
#wrapped_fn_name(#fn_args).await
|
||||
}
|
||||
|
||||
pub async fn #wrapped_fn_name #fn_generics(#fn_inputs) -> #fn_retval {
|
||||
#fn_body
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
#[poise]
|
||||
#[wrapper]
|
||||
pub async fn command(...args) {
|
||||
...block
|
||||
}
|
||||
|
||||
... becomes ...
|
||||
|
||||
#[poise]
|
||||
fn command(...args) {
|
||||
command_fn(
|
||||
...args
|
||||
)
|
||||
}
|
||||
|
||||
struct RecordableCommand<T> {
|
||||
args: T
|
||||
func: Func<T>
|
||||
}
|
||||
|
||||
impl Execute<T> for RecordableCommand<T> {
|
||||
fn execute() {
|
||||
// Unpack self.args into self.func
|
||||
}
|
||||
}
|
||||
|
||||
struct command_args {
|
||||
...args
|
||||
}
|
||||
|
||||
fn command_fn(...args) {
|
||||
...block
|
||||
}
|
||||
|
||||
*/
|
@ -1,6 +1,8 @@
|
||||
mod autocomplete;
|
||||
pub mod command_macro;
|
||||
mod command_proc;
|
||||
pub mod info_cmds;
|
||||
pub mod moderation_cmds;
|
||||
pub mod reminder_cmds;
|
||||
pub mod timer;
|
||||
pub mod todo_cmds;
|
||||
|
@ -1,9 +1,8 @@
|
||||
use std::{collections::HashSet, string::ToString};
|
||||
|
||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||
use chrono::NaiveDateTime;
|
||||
use chrono_tz::Tz;
|
||||
use log::warn;
|
||||
use num_integer::Integer;
|
||||
use poise::{
|
||||
serenity_prelude::{
|
||||
builder::CreateEmbed, model::channel::Channel, ButtonStyle, CreateActionRow, CreateButton,
|
||||
@ -32,7 +31,6 @@ use crate::{
|
||||
look_flags::{LookFlags, TimeDisplayType},
|
||||
Reminder,
|
||||
},
|
||||
timer::Timer,
|
||||
CtxData,
|
||||
},
|
||||
time_parser::natural_parser,
|
||||
@ -422,122 +420,6 @@ pub fn show_delete_page(reminders: &[Reminder], page: usize, timezone: Tz) -> Cr
|
||||
.components(vec![pager.create_button_row(pages), CreateActionRow::SelectMenu(select_menu)])
|
||||
}
|
||||
|
||||
fn time_difference(start_time: DateTime<Utc>) -> String {
|
||||
let delta = (Utc::now() - start_time).num_seconds();
|
||||
|
||||
let (minutes, seconds) = delta.div_rem(&60);
|
||||
let (hours, minutes) = minutes.div_rem(&60);
|
||||
let (days, hours) = hours.div_rem(&24);
|
||||
|
||||
format!("{} days, {:02}:{:02}:{:02}", days, hours, minutes, seconds)
|
||||
}
|
||||
|
||||
/// Manage timers
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
rename = "timer",
|
||||
identifying_name = "timer_base",
|
||||
default_member_permissions = "MANAGE_GUILD"
|
||||
)]
|
||||
pub async fn timer_base(_ctx: Context<'_>) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// List the timers in this server or DM channel
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
rename = "list",
|
||||
identifying_name = "list_timer",
|
||||
default_member_permissions = "MANAGE_GUILD"
|
||||
)]
|
||||
pub async fn list_timer(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let owner = ctx.guild_id().map(|g| g.get()).unwrap_or_else(|| ctx.author().id.get());
|
||||
|
||||
let timers = Timer::from_owner(owner, &ctx.data().database).await;
|
||||
|
||||
if !timers.is_empty() {
|
||||
ctx.send(
|
||||
CreateReply::default().embed(
|
||||
CreateEmbed::new()
|
||||
.fields(timers.iter().map(|timer| {
|
||||
(&timer.name, format!("⌚ `{}`", time_difference(timer.start_time)), false)
|
||||
}))
|
||||
.color(*THEME_COLOR),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
ctx.say("No timers currently. Use `/timer start` to create a new timer").await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Start a new timer from now
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
rename = "start",
|
||||
identifying_name = "start_timer",
|
||||
default_member_permissions = "MANAGE_GUILD"
|
||||
)]
|
||||
pub async fn start_timer(
|
||||
ctx: Context<'_>,
|
||||
#[description = "Name for the new timer"] name: String,
|
||||
) -> Result<(), Error> {
|
||||
let owner = ctx.guild_id().map(|g| g.get()).unwrap_or_else(|| ctx.author().id.get());
|
||||
|
||||
let count = Timer::count_from_owner(owner, &ctx.data().database).await;
|
||||
|
||||
if count >= 25 {
|
||||
ctx.say("You already have 25 timers. Please delete some timers before creating a new one")
|
||||
.await?;
|
||||
} else if name.len() <= 32 {
|
||||
Timer::create(&name, owner, &ctx.data().database).await;
|
||||
|
||||
ctx.say("Created a new timer").await?;
|
||||
} else {
|
||||
ctx.say(format!(
|
||||
"Please name your timer something shorted (max. 32 characters, you used {})",
|
||||
name.len()
|
||||
))
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Delete a timer
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
rename = "delete",
|
||||
identifying_name = "delete_timer",
|
||||
default_member_permissions = "MANAGE_GUILD"
|
||||
)]
|
||||
pub async fn delete_timer(
|
||||
ctx: Context<'_>,
|
||||
#[description = "Name of timer to delete"] name: String,
|
||||
) -> Result<(), Error> {
|
||||
let owner = ctx.guild_id().map(|g| g.get()).unwrap_or_else(|| ctx.author().id.get());
|
||||
|
||||
let exists =
|
||||
sqlx::query!("SELECT 1 as _r FROM timers WHERE owner = ? AND name = ?", owner, name)
|
||||
.fetch_one(&ctx.data().database)
|
||||
.await;
|
||||
|
||||
if exists.is_ok() {
|
||||
sqlx::query!("DELETE FROM timers WHERE owner = ? AND name = ?", owner, name)
|
||||
.execute(&ctx.data().database)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
ctx.say("Deleted a timer").await?;
|
||||
} else {
|
||||
ctx.say("Could not find a timer by that name").await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(poise::Modal)]
|
||||
#[name = "Reminder"]
|
||||
struct ContentModal {
|
||||
|
33
src/commands/timer/delete_timer.rs
Normal file
33
src/commands/timer/delete_timer.rs
Normal file
@ -0,0 +1,33 @@
|
||||
use crate::{Context, Error};
|
||||
|
||||
/// Delete a timer
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
rename = "delete",
|
||||
identifying_name = "delete_timer",
|
||||
default_member_permissions = "MANAGE_GUILD"
|
||||
)]
|
||||
pub async fn delete_timer(
|
||||
ctx: Context<'_>,
|
||||
#[description = "Name of timer to delete"] name: String,
|
||||
) -> Result<(), Error> {
|
||||
let owner = ctx.guild_id().map(|g| g.get()).unwrap_or_else(|| ctx.author().id.get());
|
||||
|
||||
let exists =
|
||||
sqlx::query!("SELECT 1 as _r FROM timers WHERE owner = ? AND name = ?", owner, name)
|
||||
.fetch_one(&ctx.data().database)
|
||||
.await;
|
||||
|
||||
if exists.is_ok() {
|
||||
sqlx::query!("DELETE FROM timers WHERE owner = ? AND name = ?", owner, name)
|
||||
.execute(&ctx.data().database)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
ctx.say("Deleted a timer").await?;
|
||||
} else {
|
||||
ctx.say("Could not find a timer by that name").await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
45
src/commands/timer/list_timer.rs
Normal file
45
src/commands/timer/list_timer.rs
Normal file
@ -0,0 +1,45 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use num_integer::Integer;
|
||||
use poise::{serenity_prelude::CreateEmbed, CreateReply};
|
||||
|
||||
use crate::{consts::THEME_COLOR, models::timer::Timer, Context, Error};
|
||||
|
||||
fn time_difference(start_time: DateTime<Utc>) -> String {
|
||||
let delta = (Utc::now() - start_time).num_seconds();
|
||||
|
||||
let (minutes, seconds) = delta.div_rem(&60);
|
||||
let (hours, minutes) = minutes.div_rem(&60);
|
||||
let (days, hours) = hours.div_rem(&24);
|
||||
|
||||
format!("{} days, {:02}:{:02}:{:02}", days, hours, minutes, seconds)
|
||||
}
|
||||
|
||||
/// List the timers in this server or DM channel
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
rename = "list",
|
||||
identifying_name = "list_timer",
|
||||
default_member_permissions = "MANAGE_GUILD"
|
||||
)]
|
||||
pub async fn list_timer(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let owner = ctx.guild_id().map(|g| g.get()).unwrap_or_else(|| ctx.author().id.get());
|
||||
|
||||
let timers = Timer::from_owner(owner, &ctx.data().database).await;
|
||||
|
||||
if !timers.is_empty() {
|
||||
ctx.send(
|
||||
CreateReply::default().embed(
|
||||
CreateEmbed::new()
|
||||
.fields(timers.iter().map(|timer| {
|
||||
(&timer.name, format!("⌚ `{}`", time_difference(timer.start_time)), false)
|
||||
}))
|
||||
.color(*THEME_COLOR),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
ctx.say("No timers currently. Use `/timer start` to create a new timer").await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
4
src/commands/timer/mod.rs
Normal file
4
src/commands/timer/mod.rs
Normal file
@ -0,0 +1,4 @@
|
||||
pub mod delete_timer;
|
||||
pub mod list_timer;
|
||||
pub mod start_timer;
|
||||
pub mod timer_base;
|
34
src/commands/timer/start_timer.rs
Normal file
34
src/commands/timer/start_timer.rs
Normal file
@ -0,0 +1,34 @@
|
||||
use crate::{models::timer::Timer, Context, Error};
|
||||
|
||||
/// Start a new timer from now
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
rename = "start",
|
||||
identifying_name = "start_timer",
|
||||
default_member_permissions = "MANAGE_GUILD"
|
||||
)]
|
||||
pub async fn start_timer(
|
||||
ctx: Context<'_>,
|
||||
#[description = "Name for the new timer"] name: String,
|
||||
) -> Result<(), Error> {
|
||||
let owner = ctx.guild_id().map(|g| g.get()).unwrap_or_else(|| ctx.author().id.get());
|
||||
|
||||
let count = Timer::count_from_owner(owner, &ctx.data().database).await;
|
||||
|
||||
if count >= 25 {
|
||||
ctx.say("You already have 25 timers. Please delete some timers before creating a new one")
|
||||
.await?;
|
||||
} else if name.len() <= 32 {
|
||||
Timer::create(&name, owner, &ctx.data().database).await;
|
||||
|
||||
ctx.say("Created a new timer").await?;
|
||||
} else {
|
||||
ctx.say(format!(
|
||||
"Please name your timer something shorted (max. 32 characters, you used {})",
|
||||
name.len()
|
||||
))
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
12
src/commands/timer/timer_base.rs
Normal file
12
src/commands/timer/timer_base.rs
Normal file
@ -0,0 +1,12 @@
|
||||
use crate::{Context, Error};
|
||||
|
||||
/// Manage timers
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
rename = "timer",
|
||||
identifying_name = "timer_base",
|
||||
default_member_permissions = "MANAGE_GUILD"
|
||||
)]
|
||||
pub async fn timer_base(_ctx: Context<'_>) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
@ -17,7 +17,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
commands::{
|
||||
command_macro::list::{max_macro_page, show_macro_page},
|
||||
command_macro::list_macro::{max_macro_page, show_macro_page},
|
||||
reminder_cmds::{max_delete_page, show_delete_page},
|
||||
todo_cmds::{max_todo_page, show_todo_page},
|
||||
},
|
||||
|
22
src/main.rs
22
src/main.rs
@ -34,7 +34,7 @@ use sqlx::{MySql, Pool};
|
||||
use tokio::sync::{broadcast, broadcast::Sender, RwLock};
|
||||
|
||||
use crate::{
|
||||
commands::{command_macro, info_cmds, moderation_cmds, reminder_cmds, todo_cmds},
|
||||
commands::{command_macro, info_cmds, moderation_cmds, reminder_cmds, timer, todo_cmds},
|
||||
consts::THEME_COLOR,
|
||||
event_handlers::listener,
|
||||
hooks::all_checks,
|
||||
@ -126,13 +126,13 @@ async fn _main(tx: Sender<()>) -> Result<(), Box<dyn StdError + Send + Sync>> {
|
||||
moderation_cmds::webhook(),
|
||||
poise::Command {
|
||||
subcommands: vec![
|
||||
command_macro::delete::delete_macro(),
|
||||
command_macro::record::finish_macro(),
|
||||
command_macro::list::list_macro(),
|
||||
command_macro::record::record_macro(),
|
||||
command_macro::run::run_macro(),
|
||||
command_macro::delete_macro::delete_macro(),
|
||||
command_macro::finish_macro::finish_macro(),
|
||||
command_macro::list_macro::list_macro(),
|
||||
command_macro::record_macro::record_macro(),
|
||||
command_macro::run_macro::run_macro(),
|
||||
],
|
||||
..command_macro::macro_base()
|
||||
..command_macro::macro_base::macro_base()
|
||||
},
|
||||
reminder_cmds::pause(),
|
||||
reminder_cmds::offset(),
|
||||
@ -141,11 +141,11 @@ async fn _main(tx: Sender<()>) -> Result<(), Box<dyn StdError + Send + Sync>> {
|
||||
reminder_cmds::delete(),
|
||||
poise::Command {
|
||||
subcommands: vec![
|
||||
reminder_cmds::list_timer(),
|
||||
reminder_cmds::start_timer(),
|
||||
reminder_cmds::delete_timer(),
|
||||
timer::list_timer::list_timer(),
|
||||
timer::start_timer::start_timer(),
|
||||
timer::delete_timer::delete_timer(),
|
||||
],
|
||||
..reminder_cmds::timer_base()
|
||||
..timer::timer_base::timer_base()
|
||||
},
|
||||
reminder_cmds::multiline(),
|
||||
reminder_cmds::remind(),
|
||||
|
Loading…
Reference in New Issue
Block a user