Wip commit
This commit is contained in:
@ -26,7 +26,7 @@ FROM macro
|
||||
WHERE
|
||||
guild_id = (SELECT id FROM guilds WHERE guild = ?)
|
||||
AND name LIKE CONCAT(?, '%')",
|
||||
ctx.guild_id().unwrap().0,
|
||||
ctx.guild_id().unwrap().get(),
|
||||
partial,
|
||||
)
|
||||
.fetch_all(&ctx.data().database)
|
||||
|
@ -18,7 +18,7 @@ pub async fn delete_macro(
|
||||
match sqlx::query!(
|
||||
"
|
||||
SELECT id FROM macro WHERE guild_id = (SELECT id FROM guilds WHERE guild = ?) AND name = ?",
|
||||
ctx.guild_id().unwrap().0,
|
||||
ctx.guild_id().unwrap().get(),
|
||||
name
|
||||
)
|
||||
.fetch_one(&ctx.data().database)
|
||||
|
@ -1,4 +1,7 @@
|
||||
use poise::CreateReply;
|
||||
use poise::{
|
||||
serenity_prelude::{CreateEmbed, CreateEmbedFooter},
|
||||
CreateReply,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
component_models::pager::{MacroPager, Pager},
|
||||
@ -20,11 +23,7 @@ pub async fn list_macro(ctx: Context<'_>) -> Result<(), Error> {
|
||||
|
||||
let resp = show_macro_page(¯os, 0);
|
||||
|
||||
ctx.send(|m| {
|
||||
*m = resp;
|
||||
m
|
||||
})
|
||||
.await?;
|
||||
ctx.send(resp).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -37,15 +36,12 @@ pub fn show_macro_page<U, E>(macros: &[CommandMacro<U, E>], page: usize) -> Crea
|
||||
let pager = MacroPager::new(page);
|
||||
|
||||
if macros.is_empty() {
|
||||
let mut reply = CreateReply::default();
|
||||
|
||||
reply.embed(|e| {
|
||||
e.title("Macros")
|
||||
return CreateReply::default().embed(
|
||||
CreateEmbed::new()
|
||||
.title("Macros")
|
||||
.description("No Macros Set Up. Use `/macro record` to get started.")
|
||||
.color(*THEME_COLOR)
|
||||
});
|
||||
|
||||
return reply;
|
||||
.color(*THEME_COLOR),
|
||||
);
|
||||
}
|
||||
|
||||
let pages = max_macro_page(macros);
|
||||
@ -70,20 +66,13 @@ pub fn show_macro_page<U, E>(macros: &[CommandMacro<U, E>], page: usize) -> Crea
|
||||
}
|
||||
});
|
||||
|
||||
let mut reply = CreateReply::default();
|
||||
|
||||
reply
|
||||
.embed(|e| {
|
||||
e.title("Macros")
|
||||
CreateReply::default()
|
||||
.embed(
|
||||
CreateEmbed::new()
|
||||
.title("Macros")
|
||||
.fields(fields)
|
||||
.footer(|f| f.text(format!("Page {} of {}", page + 1, pages)))
|
||||
.color(*THEME_COLOR)
|
||||
})
|
||||
.components(|comp| {
|
||||
pager.create_button_row(pages, comp);
|
||||
|
||||
comp
|
||||
});
|
||||
|
||||
reply
|
||||
.footer(CreateEmbedFooter::new(format!("Page {} of {}", page + 1, pages))),
|
||||
)
|
||||
.components(vec![pager.create_button_row(pages)])
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use lazy_regex::regex;
|
||||
use poise::serenity_prelude::CommandOptionType;
|
||||
use poise::{serenity_prelude::CommandOptionType, CreateReply};
|
||||
use regex::Captures;
|
||||
use serde_json::{json, Value};
|
||||
|
||||
@ -25,7 +25,7 @@ pub async fn migrate_macro(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let aliases = sqlx::query_as!(
|
||||
Alias,
|
||||
"SELECT name, command FROM command_aliases WHERE guild_id = (SELECT id FROM guilds WHERE guild = ?)",
|
||||
guild_id.0
|
||||
guild_id.get()
|
||||
)
|
||||
.fetch_all(&mut *transaction)
|
||||
.await?;
|
||||
@ -37,7 +37,7 @@ pub async fn migrate_macro(ctx: Context<'_>) -> Result<(), Error> {
|
||||
Some(cmd_macro) => {
|
||||
sqlx::query!(
|
||||
"INSERT INTO macro (guild_id, name, description, commands) VALUES ((SELECT id FROM guilds WHERE guild = ?), ?, ?, ?)",
|
||||
cmd_macro.guild_id.0,
|
||||
cmd_macro.guild_id.get(),
|
||||
cmd_macro.name,
|
||||
cmd_macro.description,
|
||||
cmd_macro.commands
|
||||
@ -54,7 +54,7 @@ pub async fn migrate_macro(ctx: Context<'_>) -> Result<(), Error> {
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
ctx.send(|b| b.content(format!("Added {} macros.", added_aliases))).await?;
|
||||
ctx.send(CreateReply::default().content(format!("Added {} macros.", added_aliases))).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
use std::collections::hash_map::Entry;
|
||||
|
||||
use poise::{serenity_prelude::CreateEmbed, CreateReply};
|
||||
|
||||
use crate::{consts::THEME_COLOR, models::command_macro::CommandMacro, Context, Error};
|
||||
|
||||
/// Start recording up to 5 commands to replay
|
||||
@ -32,23 +34,24 @@ pub async fn record_macro(
|
||||
let row = sqlx::query!(
|
||||
"
|
||||
SELECT 1 as _e FROM macro WHERE guild_id = (SELECT id FROM guilds WHERE guild = ?) AND name = ?",
|
||||
guild_id.0,
|
||||
guild_id.get(),
|
||||
name
|
||||
)
|
||||
.fetch_one(&ctx.data().database)
|
||||
.await;
|
||||
|
||||
if row.is_ok() {
|
||||
ctx.send(|m| {
|
||||
m.ephemeral(true).embed(|e| {
|
||||
e.title("Unique Name Required")
|
||||
ctx.send(
|
||||
CreateReply::default().ephemeral(true).embed(
|
||||
CreateEmbed::new()
|
||||
.title("Unique Name Required")
|
||||
.description(
|
||||
"A macro already exists under this name.
|
||||
Please select a unique name for your macro.",
|
||||
)
|
||||
.color(*THEME_COLOR)
|
||||
})
|
||||
})
|
||||
.color(*THEME_COLOR),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
let okay = {
|
||||
@ -63,28 +66,30 @@ Please select a unique name for your macro.",
|
||||
};
|
||||
|
||||
if okay {
|
||||
ctx.send(|m| {
|
||||
m.ephemeral(true).embed(|e| {
|
||||
e.title("Macro Recording Started")
|
||||
ctx.send(
|
||||
CreateReply::default().ephemeral(true).embed(
|
||||
CreateEmbed::new()
|
||||
.title("Macro Recording Started")
|
||||
.description(
|
||||
"Run up to 5 commands, or type `/macro finish` to stop at any point.
|
||||
Any commands ran as part of recording will be inconsequential",
|
||||
)
|
||||
.color(*THEME_COLOR)
|
||||
})
|
||||
})
|
||||
.color(*THEME_COLOR),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
ctx.send(|m| {
|
||||
m.ephemeral(true).embed(|e| {
|
||||
e.title("Macro Already Recording")
|
||||
ctx.send(
|
||||
CreateReply::default().ephemeral(true).embed(
|
||||
CreateEmbed::new()
|
||||
.title("Macro Already Recording")
|
||||
.description(
|
||||
"You are already recording a macro in this server.
|
||||
Please use `/macro finish` to end this recording before starting another.",
|
||||
)
|
||||
.color(*THEME_COLOR)
|
||||
})
|
||||
})
|
||||
.color(*THEME_COLOR),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
@ -108,13 +113,14 @@ pub async fn finish_macro(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let contained = lock.get(&key);
|
||||
|
||||
if contained.map_or(true, |cmacro| cmacro.commands.is_empty()) {
|
||||
ctx.send(|m| {
|
||||
m.embed(|e| {
|
||||
e.title("No Macro Recorded")
|
||||
ctx.send(
|
||||
CreateReply::default().embed(
|
||||
CreateEmbed::new()
|
||||
.title("No Macro Recorded")
|
||||
.description("Use `/macro record` to start recording a macro")
|
||||
.color(*THEME_COLOR)
|
||||
})
|
||||
})
|
||||
.color(*THEME_COLOR),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
let command_macro = contained.unwrap();
|
||||
@ -122,7 +128,7 @@ pub async fn finish_macro(ctx: Context<'_>) -> Result<(), Error> {
|
||||
|
||||
sqlx::query!(
|
||||
"INSERT INTO macro (guild_id, name, description, commands) VALUES ((SELECT id FROM guilds WHERE guild = ?), ?, ?, ?)",
|
||||
command_macro.guild_id.0,
|
||||
command_macro.guild_id.get(),
|
||||
command_macro.name,
|
||||
command_macro.description,
|
||||
json
|
||||
@ -131,13 +137,14 @@ pub async fn finish_macro(ctx: Context<'_>) -> Result<(), Error> {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
ctx.send(|m| {
|
||||
m.embed(|e| {
|
||||
e.title("Macro Recorded")
|
||||
ctx.send(
|
||||
CreateReply::default().embed(
|
||||
CreateEmbed::new()
|
||||
.title("Macro Recorded")
|
||||
.description("Use `/macro run` to execute the macro")
|
||||
.color(*THEME_COLOR)
|
||||
})
|
||||
})
|
||||
.color(*THEME_COLOR),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,8 @@
|
||||
use poise::{
|
||||
serenity_prelude::{CommandOption, CreateEmbed},
|
||||
CreateReply,
|
||||
};
|
||||
|
||||
use super::super::autocomplete::macro_name_autocomplete;
|
||||
use crate::{models::command_macro::guild_command_macro, Context, Data, Error, THEME_COLOR};
|
||||
|
||||
@ -18,15 +23,15 @@ pub async fn run_macro(
|
||||
match guild_command_macro(&Context::Application(ctx), &name).await {
|
||||
Some(command_macro) => {
|
||||
Context::Application(ctx)
|
||||
.send(|b| {
|
||||
b.embed(|e| {
|
||||
e.title("Running Macro").color(*THEME_COLOR).description(format!(
|
||||
.send(CreateReply::default().embed(
|
||||
CreateEmbed::new().title("Running Macro").color(*THEME_COLOR).description(
|
||||
format!(
|
||||
"Running macro {} ({} commands)",
|
||||
command_macro.name,
|
||||
command_macro.commands.len()
|
||||
))
|
||||
})
|
||||
})
|
||||
),
|
||||
),
|
||||
))
|
||||
.await?;
|
||||
|
||||
for command in command_macro.commands {
|
||||
|
@ -1,22 +1,22 @@
|
||||
use chrono::offset::Utc;
|
||||
use poise::{serenity_prelude as serenity, serenity_prelude::Mentionable};
|
||||
use poise::{
|
||||
serenity_prelude as serenity,
|
||||
serenity_prelude::{CreateEmbed, CreateEmbedFooter, Mentionable},
|
||||
CreateReply,
|
||||
};
|
||||
|
||||
use crate::{models::CtxData, Context, Error, THEME_COLOR};
|
||||
|
||||
fn footer(
|
||||
ctx: Context<'_>,
|
||||
) -> impl FnOnce(&mut serenity::CreateEmbedFooter) -> &mut serenity::CreateEmbedFooter {
|
||||
fn footer(ctx: Context<'_>) -> CreateEmbedFooter {
|
||||
let shard_count = ctx.serenity_context().cache.shard_count();
|
||||
let shard = ctx.serenity_context().shard_id;
|
||||
|
||||
move |f| {
|
||||
f.text(format!(
|
||||
"{}\nshard {} of {}",
|
||||
concat!(env!("CARGO_PKG_NAME"), " ver ", env!("CARGO_PKG_VERSION")),
|
||||
shard,
|
||||
shard_count,
|
||||
))
|
||||
}
|
||||
CreateEmbedFooter::new(format!(
|
||||
"{}\nshard {} of {}",
|
||||
concat!(env!("CARGO_PKG_NAME"), " ver ", env!("CARGO_PKG_VERSION")),
|
||||
shard,
|
||||
shard_count,
|
||||
))
|
||||
}
|
||||
|
||||
/// Get an overview of bot commands
|
||||
@ -24,9 +24,10 @@ fn footer(
|
||||
pub async fn help(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let footer = footer(ctx);
|
||||
|
||||
ctx.send(|m| {
|
||||
m.ephemeral(true).embed(|e| {
|
||||
e.title("Help")
|
||||
ctx.send(
|
||||
CreateReply::default().ephemeral(true).embed(
|
||||
CreateEmbed::new()
|
||||
.title("Help")
|
||||
.color(*THEME_COLOR)
|
||||
.description(
|
||||
"__Info Commands__
|
||||
@ -55,9 +56,9 @@ __Advanced Commands__
|
||||
`/macro` - Record and replay command sequences
|
||||
",
|
||||
)
|
||||
.footer(footer)
|
||||
})
|
||||
})
|
||||
.footer(footer),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
@ -69,9 +70,10 @@ pub async fn info(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let footer = footer(ctx);
|
||||
|
||||
let _ = ctx
|
||||
.send(|m| {
|
||||
m.ephemeral(true).embed(|e| {
|
||||
e.title("Info")
|
||||
.send(
|
||||
CreateReply::default().ephemeral(true).embed(
|
||||
CreateEmbed::new()
|
||||
.title("Info")
|
||||
.description(
|
||||
"Help: `/help`
|
||||
|
||||
@ -84,9 +86,9 @@ Invite the bot: https://invite.reminder-bot.com/
|
||||
Use our dashboard: https://reminder-bot.com/",
|
||||
)
|
||||
.footer(footer)
|
||||
.color(*THEME_COLOR)
|
||||
})
|
||||
})
|
||||
.color(*THEME_COLOR),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
@ -97,8 +99,7 @@ Use our dashboard: https://reminder-bot.com/",
|
||||
pub async fn donate(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let footer = footer(ctx);
|
||||
|
||||
ctx.send(|m| m.embed(|e| {
|
||||
e.title("Donate")
|
||||
ctx.send(CreateReply::default().embed(CreateEmbed::new().title("Donate")
|
||||
.description("Thinking of adding a monthly contribution?
|
||||
Click below for my Patreon and official bot server :)
|
||||
|
||||
@ -117,7 +118,7 @@ Just $2 USD/month!
|
||||
*Please note, you must be in the JellyWX Discord server to receive Patreon features*")
|
||||
.footer(footer)
|
||||
.color(*THEME_COLOR)
|
||||
}),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
|
||||
@ -129,14 +130,15 @@ Just $2 USD/month!
|
||||
pub async fn dashboard(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let footer = footer(ctx);
|
||||
|
||||
ctx.send(|m| {
|
||||
m.ephemeral(true).embed(|e| {
|
||||
e.title("Dashboard")
|
||||
ctx.send(
|
||||
CreateReply::default().ephemeral(true).embed(
|
||||
CreateEmbed::new()
|
||||
.title("Dashboard")
|
||||
.description("**https://reminder-bot.com/dashboard**")
|
||||
.footer(footer)
|
||||
.color(*THEME_COLOR)
|
||||
})
|
||||
})
|
||||
.color(*THEME_COLOR),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
@ -150,9 +152,11 @@ pub async fn clock(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let tz = ctx.timezone().await;
|
||||
let now = Utc::now().with_timezone(&tz);
|
||||
|
||||
ctx.send(|m| {
|
||||
m.ephemeral(true).content(format!("Time in **{}**: `{}`", tz, now.format("%H:%M")))
|
||||
})
|
||||
ctx.send(CreateReply::default().ephemeral(true).content(format!(
|
||||
"Time in **{}**: `{}`",
|
||||
tz,
|
||||
now.format("%H:%M")
|
||||
)))
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
@ -168,13 +172,11 @@ pub async fn clock_context_menu(ctx: Context<'_>, user: serenity::User) -> Resul
|
||||
|
||||
let now = Utc::now().with_timezone(&tz);
|
||||
|
||||
ctx.send(|m| {
|
||||
m.ephemeral(true).content(format!(
|
||||
"Time in {}'s timezone: `{}`",
|
||||
user.mention(),
|
||||
now.format("%H:%M")
|
||||
))
|
||||
})
|
||||
ctx.send(CreateReply::default().ephemeral(true).content(format!(
|
||||
"Time in {}'s timezone: `{}`",
|
||||
user.mention(),
|
||||
now.format("%H:%M")
|
||||
)))
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
|
@ -2,6 +2,10 @@ use chrono::offset::Utc;
|
||||
use chrono_tz::{Tz, TZ_VARIANTS};
|
||||
use levenshtein::levenshtein;
|
||||
use log::warn;
|
||||
use poise::{
|
||||
serenity_prelude::{CreateEmbed, CreateEmbedFooter},
|
||||
CreateReply,
|
||||
};
|
||||
|
||||
use super::autocomplete::timezone_autocomplete;
|
||||
use crate::{consts::THEME_COLOR, models::CtxData, Context, Error};
|
||||
@ -26,17 +30,18 @@ pub async fn timezone(
|
||||
|
||||
let now = Utc::now().with_timezone(&tz);
|
||||
|
||||
ctx.send(|m| {
|
||||
m.embed(|e| {
|
||||
e.title("Timezone Set")
|
||||
ctx.send(
|
||||
CreateReply::default().embed(
|
||||
CreateEmbed::new()
|
||||
.title("Timezone Set")
|
||||
.description(format!(
|
||||
"Timezone has been set to **{}**. Your current time should be `{}`",
|
||||
timezone,
|
||||
now.format("%H:%M")
|
||||
))
|
||||
.color(*THEME_COLOR)
|
||||
})
|
||||
})
|
||||
.color(*THEME_COLOR),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
@ -60,16 +65,15 @@ pub async fn timezone(
|
||||
)
|
||||
});
|
||||
|
||||
ctx.send(|m| {
|
||||
m.embed(|e| {
|
||||
e.title("Timezone Not Recognized")
|
||||
ctx.send(CreateReply::default().embed(CreateEmbed::new()
|
||||
.title("Timezone Not Recognized")
|
||||
.description("Possibly you meant one of the following timezones, otherwise click [here](https://gist.github.com/JellyWX/913dfc8b63d45192ad6cb54c829324ee):")
|
||||
.color(*THEME_COLOR)
|
||||
.fields(fields)
|
||||
.footer(|f| f.text(footer_text))
|
||||
.footer(CreateEmbedFooter::new(footer_text))
|
||||
.url("https://gist.github.com/JellyWX/913dfc8b63d45192ad6cb54c829324ee")
|
||||
})
|
||||
})
|
||||
)
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
@ -78,9 +82,10 @@ pub async fn timezone(
|
||||
(t.to_string(), format!("🕗 `{}`", Utc::now().with_timezone(t).format("%H:%M")), true)
|
||||
});
|
||||
|
||||
ctx.send(|m| {
|
||||
m.embed(|e| {
|
||||
e.title("Timezone Usage")
|
||||
ctx.send(
|
||||
CreateReply::default().embed(
|
||||
CreateEmbed::new()
|
||||
.title("Timezone Usage")
|
||||
.description(
|
||||
"**Usage:**
|
||||
`/timezone Name`
|
||||
@ -92,10 +97,10 @@ You may want to use one of the popular timezones below, otherwise click [here](h
|
||||
)
|
||||
.color(*THEME_COLOR)
|
||||
.fields(popular_timezones_iter)
|
||||
.footer(|f| f.text(footer_text))
|
||||
.url("https://gist.github.com/JellyWX/913dfc8b63d45192ad6cb54c829324ee")
|
||||
})
|
||||
})
|
||||
.footer(CreateEmbedFooter::new(footer_text))
|
||||
.url("https://gist.github.com/JellyWX/913dfc8b63d45192ad6cb54c829324ee"),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
@ -136,13 +141,11 @@ pub async fn set_ephemeral_confirmations(ctx: Context<'_>) -> Result<(), Error>
|
||||
guild_data.ephemeral_confirmations = true;
|
||||
guild_data.commit_changes(&ctx.data().database).await;
|
||||
|
||||
ctx.send(|r| {
|
||||
r.ephemeral(true).embed(|e| {
|
||||
e.title("Confirmations ephemeral")
|
||||
ctx.send(CreateReply::default().ephemeral(true).embed(CreateEmbed::new().title("Confirmations ephemeral")
|
||||
.description("Reminder confirmations will be sent privately, and removed when your client restarts.")
|
||||
.color(*THEME_COLOR)
|
||||
})
|
||||
})
|
||||
)
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
@ -160,15 +163,13 @@ pub async fn unset_ephemeral_confirmations(ctx: Context<'_>) -> Result<(), Error
|
||||
guild_data.ephemeral_confirmations = false;
|
||||
guild_data.commit_changes(&ctx.data().database).await;
|
||||
|
||||
ctx.send(|r| {
|
||||
r.ephemeral(true).embed(|e| {
|
||||
e.title("Confirmations public")
|
||||
ctx.send(CreateReply::default().ephemeral(true).embed(CreateEmbed::new().title("Confirmations public")
|
||||
.description(
|
||||
"Reminder confirmations will be sent as regular messages, and won't be removed automatically.",
|
||||
)
|
||||
.color(*THEME_COLOR)
|
||||
})
|
||||
})
|
||||
)
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
@ -187,13 +188,14 @@ pub async fn set_allowed_dm(ctx: Context<'_>) -> Result<(), Error> {
|
||||
user_data.allowed_dm = true;
|
||||
user_data.commit_changes(&ctx.data().database).await;
|
||||
|
||||
ctx.send(|r| {
|
||||
r.ephemeral(true).embed(|e| {
|
||||
e.title("DMs permitted")
|
||||
ctx.send(
|
||||
CreateReply::default().ephemeral(true).embed(
|
||||
CreateEmbed::new()
|
||||
.title("DMs permitted")
|
||||
.description("You will receive a message if a user sets a DM reminder for you.")
|
||||
.color(*THEME_COLOR)
|
||||
})
|
||||
})
|
||||
.color(*THEME_COLOR),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
@ -206,15 +208,16 @@ pub async fn unset_allowed_dm(ctx: Context<'_>) -> Result<(), Error> {
|
||||
user_data.allowed_dm = false;
|
||||
user_data.commit_changes(&ctx.data().database).await;
|
||||
|
||||
ctx.send(|r| {
|
||||
r.ephemeral(true).embed(|e| {
|
||||
e.title("DMs blocked")
|
||||
ctx.send(
|
||||
CreateReply::default().ephemeral(true).embed(
|
||||
CreateEmbed::new()
|
||||
.title("DMs blocked")
|
||||
.description(
|
||||
"You can still set DM reminders for yourself or for users with DMs enabled.",
|
||||
)
|
||||
.color(*THEME_COLOR)
|
||||
})
|
||||
})
|
||||
.color(*THEME_COLOR),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
@ -230,15 +233,13 @@ pub async fn webhook(ctx: Context<'_>) -> Result<(), Error> {
|
||||
match ctx.channel_data().await {
|
||||
Ok(data) => {
|
||||
if let (Some(id), Some(token)) = (data.webhook_id, data.webhook_token) {
|
||||
ctx.send(|b| {
|
||||
b.ephemeral(true).content(format!(
|
||||
"**Warning!**
|
||||
ctx.send(CreateReply::default().ephemeral(true).content(format!(
|
||||
"**Warning!**
|
||||
This link can be used by users to anonymously send messages, with or without permissions.
|
||||
Do not share it!
|
||||
|| https://discord.com/api/webhooks/{}/{} ||",
|
||||
id, token,
|
||||
))
|
||||
})
|
||||
id, token,
|
||||
)))
|
||||
.await?;
|
||||
} else {
|
||||
ctx.say("No webhook configured on this channel.").await?;
|
||||
|
@ -5,7 +5,11 @@ use chrono_tz::Tz;
|
||||
use log::warn;
|
||||
use num_integer::Integer;
|
||||
use poise::{
|
||||
serenity_prelude::{builder::CreateEmbed, model::channel::Channel, ButtonStyle, ReactionType},
|
||||
serenity_prelude::{
|
||||
builder::CreateEmbed, model::channel::Channel, ButtonStyle, CreateActionRow, CreateButton,
|
||||
CreateEmbedFooter, CreateSelectMenu, CreateSelectMenuKind, CreateSelectMenuOption,
|
||||
ReactionType,
|
||||
},
|
||||
CreateReply, Modal,
|
||||
};
|
||||
|
||||
@ -125,21 +129,19 @@ pub async fn offset(
|
||||
let channels = guild
|
||||
.channels
|
||||
.iter()
|
||||
.filter(|(_, channel)| match channel {
|
||||
Channel::Guild(guild_channel) => guild_channel.is_text_based(),
|
||||
_ => false,
|
||||
})
|
||||
.map(|(id, _)| id.0.to_string())
|
||||
.filter(|(_, channel)| channel.is_text_based())
|
||||
.map(|(id, _)| id.get().to_string())
|
||||
.collect::<Vec<String>>()
|
||||
.join(",");
|
||||
|
||||
sqlx::query!(
|
||||
"
|
||||
UPDATE reminders
|
||||
INNER JOIN
|
||||
`channels` ON `channels`.id = reminders.channel_id
|
||||
SET reminders.`utc_time` = DATE_ADD(reminders.`utc_time`, INTERVAL ? SECOND)
|
||||
WHERE FIND_IN_SET(channels.`channel`, ?)",
|
||||
UPDATE reminders
|
||||
INNER JOIN `channels`
|
||||
ON `channels`.id = reminders.channel_id
|
||||
SET reminders.`utc_time` = DATE_ADD(reminders.`utc_time`, INTERVAL ? SECOND)
|
||||
WHERE FIND_IN_SET(channels.`channel`, ?)
|
||||
",
|
||||
combined_time as i64,
|
||||
channels
|
||||
)
|
||||
@ -148,9 +150,15 @@ WHERE FIND_IN_SET(channels.`channel`, ?)",
|
||||
.unwrap();
|
||||
} else {
|
||||
sqlx::query!(
|
||||
"UPDATE reminders INNER JOIN `channels` ON `channels`.id = reminders.channel_id SET reminders.`utc_time` = reminders.`utc_time` + ? WHERE channels.`channel` = ?",
|
||||
"
|
||||
UPDATE reminders
|
||||
INNER JOIN `channels`
|
||||
ON `channels`.id = reminders.channel_id
|
||||
SET reminders.`utc_time` = reminders.`utc_time` + ?
|
||||
WHERE channels.`channel` = ?
|
||||
",
|
||||
combined_time as i64,
|
||||
ctx.channel_id().0
|
||||
ctx.channel_id().get()
|
||||
)
|
||||
.execute(&ctx.data().database)
|
||||
.await
|
||||
@ -216,9 +224,9 @@ pub async fn look(
|
||||
}),
|
||||
};
|
||||
|
||||
let channel_opt = ctx.channel_id().to_channel_cached(&ctx);
|
||||
let channel_opt = ctx.channel_id().to_channel_cached(&ctx.cache());
|
||||
|
||||
let channel_id = if let Some(Channel::Guild(channel)) = channel_opt {
|
||||
let channel_id = if let Some(channel) = channel_opt {
|
||||
if Some(channel.guild_id) == ctx.guild_id() {
|
||||
flags.channel_id.unwrap_or_else(|| ctx.channel_id())
|
||||
} else {
|
||||
@ -228,11 +236,8 @@ pub async fn look(
|
||||
ctx.channel_id()
|
||||
};
|
||||
|
||||
let channel_name = if let Some(Channel::Guild(channel)) = channel_id.to_channel_cached(&ctx) {
|
||||
Some(channel.name)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let channel_name =
|
||||
channel_id.to_channel_cached(&ctx.cache()).map(|channel| channel.name.clone());
|
||||
|
||||
let reminders = Reminder::from_channel(&ctx.data().database, channel_id, &flags).await;
|
||||
|
||||
@ -260,23 +265,21 @@ pub async fn look(
|
||||
|
||||
let pager = LookPager::new(flags, timezone);
|
||||
|
||||
ctx.send(|r| {
|
||||
r.ephemeral(true)
|
||||
.embed(|e| {
|
||||
e.title(format!(
|
||||
"Reminders{}",
|
||||
channel_name.map_or(String::new(), |n| format!(" on #{}", n))
|
||||
))
|
||||
.description(display)
|
||||
.footer(|f| f.text(format!("Page {} of {}", 1, pages)))
|
||||
.color(*THEME_COLOR)
|
||||
})
|
||||
.components(|comp| {
|
||||
pager.create_button_row(pages, comp);
|
||||
|
||||
comp
|
||||
})
|
||||
})
|
||||
ctx.send(
|
||||
CreateReply::default()
|
||||
.ephemeral(true)
|
||||
.embed(
|
||||
CreateEmbed::new()
|
||||
.title(format!(
|
||||
"Reminders{}",
|
||||
channel_name.map_or(String::new(), |n| format!(" on #{}", n))
|
||||
))
|
||||
.description(display)
|
||||
.footer(CreateEmbedFooter::new(format!("Page {} of {}", 1, pages)))
|
||||
.color(*THEME_COLOR),
|
||||
)
|
||||
.components(vec![pager.create_button_row(pages)]),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
@ -298,11 +301,7 @@ pub async fn delete(ctx: Context<'_>) -> Result<(), Error> {
|
||||
|
||||
let resp = show_delete_page(&reminders, 0, timezone);
|
||||
|
||||
ctx.send(|r| {
|
||||
*r = resp;
|
||||
r
|
||||
})
|
||||
.await?;
|
||||
ctx.send(resp).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -333,16 +332,12 @@ pub fn show_delete_page(reminders: &[Reminder], page: usize, timezone: Tz) -> Cr
|
||||
let pager = DelPager::new(page, timezone);
|
||||
|
||||
if reminders.is_empty() {
|
||||
let mut reply = CreateReply::default();
|
||||
let embed = CreateEmbed::new()
|
||||
.title("Delete Reminders")
|
||||
.description("No Reminders")
|
||||
.color(*THEME_COLOR);
|
||||
|
||||
reply
|
||||
.embed(|e| e.title("Delete Reminders").description("No Reminders").color(*THEME_COLOR))
|
||||
.components(|comp| {
|
||||
pager.create_button_row(0, comp);
|
||||
comp
|
||||
});
|
||||
|
||||
return reply;
|
||||
return CreateReply::default().embed(embed).components(vec![pager.create_button_row(0)]);
|
||||
}
|
||||
|
||||
let pages = max_delete_page(reminders, &timezone);
|
||||
@ -391,49 +386,42 @@ pub fn show_delete_page(reminders: &[Reminder], page: usize, timezone: Tz) -> Cr
|
||||
|
||||
let del_selector = ComponentDataModel::DelSelector(DelSelector { page, timezone });
|
||||
|
||||
let mut reply = CreateReply::default();
|
||||
let embed = CreateEmbed::new()
|
||||
.title("Delete Reminders")
|
||||
.description(display)
|
||||
.footer(CreateEmbedFooter::new(format!("Page {} of {}", page + 1, pages)))
|
||||
.color(*THEME_COLOR);
|
||||
|
||||
reply
|
||||
.embed(|e| {
|
||||
e.title("Delete Reminders")
|
||||
.description(display)
|
||||
.footer(|f| f.text(format!("Page {} of {}", page + 1, pages)))
|
||||
.color(*THEME_COLOR)
|
||||
})
|
||||
.components(|comp| {
|
||||
pager.create_button_row(pages, comp);
|
||||
let select_menu = CreateSelectMenu::new(
|
||||
del_selector.to_custom_id(),
|
||||
CreateSelectMenuKind::String {
|
||||
options: shown_reminders
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(count, reminder)| {
|
||||
let c = reminder.display_content();
|
||||
let description = if c.len() > 100 {
|
||||
format!(
|
||||
"{}...",
|
||||
reminder.display_content().chars().take(97).collect::<String>()
|
||||
)
|
||||
} else {
|
||||
c.to_string()
|
||||
};
|
||||
|
||||
comp.create_action_row(|row| {
|
||||
row.create_select_menu(|menu| {
|
||||
menu.custom_id(del_selector.to_custom_id()).options(|opt| {
|
||||
for (count, reminder) in shown_reminders.iter().enumerate() {
|
||||
opt.create_option(|o| {
|
||||
o.label(count + first_num).value(reminder.id).description({
|
||||
let c = reminder.display_content();
|
||||
|
||||
if c.len() > 100 {
|
||||
format!(
|
||||
"{}...",
|
||||
reminder
|
||||
.display_content()
|
||||
.chars()
|
||||
.take(97)
|
||||
.collect::<String>()
|
||||
)
|
||||
} else {
|
||||
c.to_string()
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
opt
|
||||
})
|
||||
CreateSelectMenuOption::new(
|
||||
(count + first_num).to_string(),
|
||||
reminder.id.to_string(),
|
||||
)
|
||||
.description(description)
|
||||
})
|
||||
})
|
||||
});
|
||||
.collect(),
|
||||
},
|
||||
);
|
||||
|
||||
reply
|
||||
CreateReply::default()
|
||||
.embed(embed)
|
||||
.components(vec![pager.create_button_row(pages), CreateActionRow::SelectMenu(select_menu)])
|
||||
}
|
||||
|
||||
fn time_difference(start_time: DateTime<Utc>) -> String {
|
||||
@ -465,19 +453,20 @@ pub async fn timer_base(_ctx: Context<'_>) -> Result<(), Error> {
|
||||
default_member_permissions = "MANAGE_GUILD"
|
||||
)]
|
||||
pub async fn list_timer(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let owner = ctx.guild_id().map(|g| g.0).unwrap_or_else(|| ctx.author().id.0);
|
||||
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(|m| {
|
||||
m.embed(|e| {
|
||||
e.fields(timers.iter().map(|timer| {
|
||||
(&timer.name, format!("⌚ `{}`", time_difference(timer.start_time)), false)
|
||||
}))
|
||||
.color(*THEME_COLOR)
|
||||
})
|
||||
})
|
||||
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?;
|
||||
@ -497,7 +486,7 @@ 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.0).unwrap_or_else(|| ctx.author().id.0);
|
||||
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;
|
||||
|
||||
@ -530,7 +519,7 @@ 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.0).unwrap_or_else(|| ctx.author().id.0);
|
||||
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)
|
||||
@ -604,7 +593,7 @@ pub async fn multiline(
|
||||
None => {
|
||||
warn!("Unexpected None encountered in /multiline");
|
||||
Ok(Context::Application(ctx)
|
||||
.send(|m| m.content("Unexpected error.").ephemeral(true))
|
||||
.send(CreateReply::default().content("Unexpected error.").ephemeral(true))
|
||||
.await
|
||||
.map(|_| ())?)
|
||||
}
|
||||
@ -682,9 +671,9 @@ async fn create_reminder(
|
||||
|
||||
if list.is_empty() {
|
||||
if ctx.guild_id().is_some() {
|
||||
vec![ReminderScope::Channel(ctx.channel_id().0)]
|
||||
vec![ReminderScope::Channel(ctx.channel_id().get())]
|
||||
} else {
|
||||
vec![ReminderScope::User(ctx.author().id.0)]
|
||||
vec![ReminderScope::User(ctx.author().id.get())]
|
||||
}
|
||||
} else {
|
||||
list
|
||||
@ -709,10 +698,9 @@ async fn create_reminder(
|
||||
},
|
||||
)
|
||||
} else {
|
||||
ctx.send(|b| {
|
||||
b.content(
|
||||
"`repeat` is only available to Patreon subscribers or self-hosted users")
|
||||
})
|
||||
ctx.send(CreateReply::default().content(
|
||||
"`repeat` is only available to Patreon subscribers or self-hosted users",
|
||||
))
|
||||
.await?;
|
||||
|
||||
return Ok(());
|
||||
@ -722,17 +710,16 @@ async fn create_reminder(
|
||||
};
|
||||
|
||||
if processed_interval.is_none() && interval.is_some() {
|
||||
ctx.send(|b| {
|
||||
b.content(
|
||||
"Repeat interval could not be processed. Try similar to `1 hour` or `4 days`")
|
||||
})
|
||||
ctx.send(CreateReply::default().content(
|
||||
"Repeat interval could not be processed. Try similar to `1 hour` or `4 days`",
|
||||
))
|
||||
.await?;
|
||||
} else if processed_expires.is_none() && expires.is_some() {
|
||||
ctx.send(|b| {
|
||||
b.ephemeral(true).content(
|
||||
ctx.send(
|
||||
CreateReply::default().ephemeral(true).content(
|
||||
"Expiry time failed to process. Please make it as clear as possible",
|
||||
)
|
||||
})
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
let mut builder = MultiReminderBuilder::new(&ctx, ctx.guild_id())
|
||||
@ -756,37 +743,20 @@ async fn create_reminder(
|
||||
reminder_id: reminder,
|
||||
});
|
||||
|
||||
ctx.send(|m| {
|
||||
m.embed(|c| {
|
||||
*c = embed;
|
||||
c
|
||||
})
|
||||
.components(|c| {
|
||||
c.create_action_row(|r| {
|
||||
r.create_button(|b| {
|
||||
b.emoji(ReactionType::Unicode("🔕".to_string()))
|
||||
.label("Cancel")
|
||||
.style(ButtonStyle::Danger)
|
||||
.custom_id(undo_button.to_custom_id())
|
||||
})
|
||||
.create_button(|b| {
|
||||
b.emoji(ReactionType::Unicode("📝".to_string()))
|
||||
.label("Edit")
|
||||
.style(ButtonStyle::Link)
|
||||
.url("https://beta.reminder-bot.com/dashboard")
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
ctx.send(CreateReply::default().embed(embed).components(vec![
|
||||
CreateActionRow::Buttons(vec![
|
||||
CreateButton::new(undo_button.to_custom_id())
|
||||
.emoji(ReactionType::Unicode("🔕".to_string()))
|
||||
.label("Cancel")
|
||||
.style(ButtonStyle::Danger),
|
||||
CreateButton::new_link("https://beta.reminder-bot.com/dashboard")
|
||||
.emoji(ReactionType::Unicode("📝".to_string()))
|
||||
.label("Edit"),
|
||||
]),
|
||||
]))
|
||||
.await?;
|
||||
} else {
|
||||
ctx.send(|m| {
|
||||
m.embed(|c| {
|
||||
*c = embed;
|
||||
c
|
||||
})
|
||||
})
|
||||
.await?;
|
||||
ctx.send(CreateReply::default().embed(embed)).await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,10 @@
|
||||
use poise::CreateReply;
|
||||
use poise::{
|
||||
serenity_prelude::{
|
||||
CreateActionRow, CreateEmbed, CreateEmbedFooter, CreateSelectMenu, CreateSelectMenuKind,
|
||||
CreateSelectMenuOption,
|
||||
},
|
||||
CreateReply,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
component_models::{
|
||||
@ -48,7 +54,7 @@ pub async fn todo_guild_add(
|
||||
sqlx::query!(
|
||||
"INSERT INTO todos (guild_id, value)
|
||||
VALUES ((SELECT id FROM guilds WHERE guild = ?), ?)",
|
||||
ctx.guild_id().unwrap().0,
|
||||
ctx.guild_id().unwrap().get(),
|
||||
task
|
||||
)
|
||||
.execute(&ctx.data().database)
|
||||
@ -73,7 +79,7 @@ pub async fn todo_guild_view(ctx: Context<'_>) -> Result<(), Error> {
|
||||
"SELECT todos.id, value FROM todos
|
||||
INNER JOIN guilds ON todos.guild_id = guilds.id
|
||||
WHERE guilds.guild = ?",
|
||||
ctx.guild_id().unwrap().0,
|
||||
ctx.guild_id().unwrap().get(),
|
||||
)
|
||||
.fetch_all(&ctx.data().database)
|
||||
.await
|
||||
@ -82,13 +88,9 @@ WHERE guilds.guild = ?",
|
||||
.map(|row| (row.id as usize, row.value.clone()))
|
||||
.collect::<Vec<(usize, String)>>();
|
||||
|
||||
let resp = show_todo_page(&values, 0, None, None, ctx.guild_id().map(|g| g.0));
|
||||
let resp = show_todo_page(&values, 0, None, None, ctx.guild_id().map(|g| g.get()));
|
||||
|
||||
ctx.send(|r| {
|
||||
*r = resp;
|
||||
r
|
||||
})
|
||||
.await?;
|
||||
ctx.send(resp).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -123,8 +125,8 @@ pub async fn todo_channel_add(
|
||||
sqlx::query!(
|
||||
"INSERT INTO todos (guild_id, channel_id, value)
|
||||
VALUES ((SELECT id FROM guilds WHERE guild = ?), (SELECT id FROM channels WHERE channel = ?), ?)",
|
||||
ctx.guild_id().unwrap().0,
|
||||
ctx.channel_id().0,
|
||||
ctx.guild_id().unwrap().get(),
|
||||
ctx.channel_id().get(),
|
||||
task
|
||||
)
|
||||
.execute(&ctx.data().database)
|
||||
@ -149,7 +151,7 @@ pub async fn todo_channel_view(ctx: Context<'_>) -> Result<(), Error> {
|
||||
"SELECT todos.id, value FROM todos
|
||||
INNER JOIN channels ON todos.channel_id = channels.id
|
||||
WHERE channels.channel = ?",
|
||||
ctx.channel_id().0,
|
||||
ctx.channel_id().get(),
|
||||
)
|
||||
.fetch_all(&ctx.data().database)
|
||||
.await
|
||||
@ -158,14 +160,15 @@ WHERE channels.channel = ?",
|
||||
.map(|row| (row.id as usize, row.value.clone()))
|
||||
.collect::<Vec<(usize, String)>>();
|
||||
|
||||
let resp =
|
||||
show_todo_page(&values, 0, None, Some(ctx.channel_id().0), ctx.guild_id().map(|g| g.0));
|
||||
let resp = show_todo_page(
|
||||
&values,
|
||||
0,
|
||||
None,
|
||||
Some(ctx.channel_id().get()),
|
||||
ctx.guild_id().map(|g| g.get()),
|
||||
);
|
||||
|
||||
ctx.send(|r| {
|
||||
*r = resp;
|
||||
r
|
||||
})
|
||||
.await?;
|
||||
ctx.send(resp).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -185,7 +188,7 @@ pub async fn todo_user_add(
|
||||
sqlx::query!(
|
||||
"INSERT INTO todos (user_id, value)
|
||||
VALUES ((SELECT id FROM users WHERE user = ?), ?)",
|
||||
ctx.author().id.0,
|
||||
ctx.author().id.get(),
|
||||
task
|
||||
)
|
||||
.execute(&ctx.data().database)
|
||||
@ -204,7 +207,7 @@ pub async fn todo_user_view(ctx: Context<'_>) -> Result<(), Error> {
|
||||
"SELECT todos.id, value FROM todos
|
||||
INNER JOIN users ON todos.user_id = users.id
|
||||
WHERE users.user = ?",
|
||||
ctx.author().id.0,
|
||||
ctx.author().id.get(),
|
||||
)
|
||||
.fetch_all(&ctx.data().database)
|
||||
.await
|
||||
@ -213,13 +216,9 @@ WHERE users.user = ?",
|
||||
.map(|row| (row.id as usize, row.value.clone()))
|
||||
.collect::<Vec<(usize, String)>>();
|
||||
|
||||
let resp = show_todo_page(&values, 0, Some(ctx.author().id.0), None, None);
|
||||
let resp = show_todo_page(&values, 0, Some(ctx.author().id.get()), None, None);
|
||||
|
||||
ctx.send(|r| {
|
||||
*r = resp;
|
||||
r
|
||||
})
|
||||
.await?;
|
||||
ctx.send(resp).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -306,61 +305,51 @@ pub fn show_todo_page(
|
||||
};
|
||||
|
||||
if todo_ids.is_empty() {
|
||||
let mut reply = CreateReply::default();
|
||||
|
||||
reply.embed(|e| {
|
||||
e.title(format!("{} Todo List", title))
|
||||
CreateReply::default().embed(
|
||||
CreateEmbed::new()
|
||||
.title(format!("{} Todo List", title))
|
||||
.description("Todo List Empty!")
|
||||
.footer(|f| f.text(format!("Page {} of {}", page + 1, pages)))
|
||||
.color(*THEME_COLOR)
|
||||
});
|
||||
|
||||
reply
|
||||
.footer(CreateEmbedFooter::new(format!("Page {} of {}", page + 1, pages))),
|
||||
)
|
||||
} else {
|
||||
let todo_selector =
|
||||
ComponentDataModel::TodoSelector(TodoSelector { page, user_id, channel_id, guild_id });
|
||||
|
||||
let mut reply = CreateReply::default();
|
||||
|
||||
reply
|
||||
.embed(|e| {
|
||||
e.title(format!("{} Todo List", title))
|
||||
CreateReply::default()
|
||||
.embed(
|
||||
CreateEmbed::new()
|
||||
.title(format!("{} Todo List", title))
|
||||
.description(display)
|
||||
.footer(|f| f.text(format!("Page {} of {}", page + 1, pages)))
|
||||
.color(*THEME_COLOR)
|
||||
})
|
||||
.components(|comp| {
|
||||
pager.create_button_row(pages, comp);
|
||||
.footer(CreateEmbedFooter::new(format!("Page {} of {}", page + 1, pages))),
|
||||
)
|
||||
.components(vec![
|
||||
pager.create_button_row(pages),
|
||||
CreateActionRow::SelectMenu(CreateSelectMenu::new(
|
||||
todo_selector.to_custom_id(),
|
||||
CreateSelectMenuKind::String {
|
||||
options: todo_ids
|
||||
.iter()
|
||||
.zip(&display_vec)
|
||||
.enumerate()
|
||||
.map(|(count, (id, disp))| {
|
||||
let c = disp.split_once(' ').unwrap_or(("", "")).1;
|
||||
let description = if c.len() > 100 {
|
||||
format!("{}...", c.chars().take(97).collect::<String>())
|
||||
} else {
|
||||
c.to_string()
|
||||
};
|
||||
|
||||
comp.create_action_row(|row| {
|
||||
row.create_select_menu(|menu| {
|
||||
menu.custom_id(todo_selector.to_custom_id()).options(|opt| {
|
||||
for (count, (id, disp)) in todo_ids.iter().zip(&display_vec).enumerate()
|
||||
{
|
||||
opt.create_option(|o| {
|
||||
o.label(format!("Mark {} complete", count + first_num))
|
||||
.value(id)
|
||||
.description({
|
||||
let c = disp.split_once(' ').unwrap_or(("", "")).1;
|
||||
|
||||
if c.len() > 100 {
|
||||
format!(
|
||||
"{}...",
|
||||
c.chars().take(97).collect::<String>()
|
||||
)
|
||||
} else {
|
||||
c.to_string()
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
opt
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
reply
|
||||
CreateSelectMenuOption::new(
|
||||
format!("Mark {} complete", count + first_num),
|
||||
id.to_string(),
|
||||
)
|
||||
.description(description)
|
||||
})
|
||||
.collect(),
|
||||
},
|
||||
)),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user