Move all commands to their own files
This commit is contained in:
38
src/commands/todo/channel/add.rs
Normal file
38
src/commands/todo/channel/add.rs
Normal file
@ -0,0 +1,38 @@
|
||||
use crate::{models::CtxData, Context, Error};
|
||||
|
||||
/// Add an item to the channel todo list
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
rename = "add",
|
||||
guild_only = true,
|
||||
identifying_name = "todo_channel_add",
|
||||
default_member_permissions = "MANAGE_GUILD"
|
||||
)]
|
||||
pub async fn add(
|
||||
ctx: Context<'_>,
|
||||
#[description = "The task to add to the todo list"] task: String,
|
||||
) -> Result<(), Error> {
|
||||
// ensure channel is cached
|
||||
let _ = ctx.channel_data().await;
|
||||
|
||||
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().get(),
|
||||
ctx.channel_id().get(),
|
||||
task
|
||||
)
|
||||
.execute(&ctx.data().database)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
ctx.say("Item added to todo list").await?;
|
||||
|
||||
Ok(())
|
||||
}
|
16
src/commands/todo/channel/mod.rs
Normal file
16
src/commands/todo/channel/mod.rs
Normal file
@ -0,0 +1,16 @@
|
||||
pub mod add;
|
||||
pub mod view;
|
||||
|
||||
use crate::{Context, Error};
|
||||
|
||||
/// Manage the channel todo list
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
rename = "channel",
|
||||
guild_only = true,
|
||||
identifying_name = "todo_channel_base",
|
||||
default_member_permissions = "MANAGE_GUILD"
|
||||
)]
|
||||
pub async fn channel(_ctx: Context<'_>) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
38
src/commands/todo/channel/view.rs
Normal file
38
src/commands/todo/channel/view.rs
Normal file
@ -0,0 +1,38 @@
|
||||
use crate::{commands::todo::show_todo_page, Context, Error};
|
||||
|
||||
/// View and remove from the channel todo list
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
rename = "view",
|
||||
guild_only = true,
|
||||
identifying_name = "todo_channel_view",
|
||||
default_member_permissions = "MANAGE_GUILD"
|
||||
)]
|
||||
pub async fn view(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let values = sqlx::query!(
|
||||
"
|
||||
SELECT todos.id, value FROM todos
|
||||
INNER JOIN channels ON todos.channel_id = channels.id
|
||||
WHERE channels.channel = ?
|
||||
",
|
||||
ctx.channel_id().get(),
|
||||
)
|
||||
.fetch_all(&ctx.data().database)
|
||||
.await
|
||||
.unwrap()
|
||||
.iter()
|
||||
.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().get()),
|
||||
ctx.guild_id().map(|g| g.get()),
|
||||
);
|
||||
|
||||
ctx.send(resp).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
31
src/commands/todo/guild/add.rs
Normal file
31
src/commands/todo/guild/add.rs
Normal file
@ -0,0 +1,31 @@
|
||||
use crate::{Context, Error};
|
||||
|
||||
/// Add an item to the server todo list
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
rename = "add",
|
||||
guild_only = true,
|
||||
identifying_name = "todo_guild_add",
|
||||
default_member_permissions = "MANAGE_GUILD"
|
||||
)]
|
||||
pub async fn add(
|
||||
ctx: Context<'_>,
|
||||
#[description = "The task to add to the todo list"] task: String,
|
||||
) -> Result<(), Error> {
|
||||
sqlx::query!(
|
||||
"
|
||||
INSERT INTO todos (guild_id, value)
|
||||
VALUES (
|
||||
(SELECT id FROM guilds WHERE guild = ?), ?
|
||||
)",
|
||||
ctx.guild_id().unwrap().get(),
|
||||
task
|
||||
)
|
||||
.execute(&ctx.data().database)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
ctx.say("Item added to todo list").await?;
|
||||
|
||||
Ok(())
|
||||
}
|
15
src/commands/todo/guild/mod.rs
Normal file
15
src/commands/todo/guild/mod.rs
Normal file
@ -0,0 +1,15 @@
|
||||
pub mod add;
|
||||
pub mod view;
|
||||
|
||||
use crate::{Context, Error};
|
||||
|
||||
/// Manage the server todo list
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
rename = "server",
|
||||
guild_only = true,
|
||||
default_member_permissions = "MANAGE_GUILD"
|
||||
)]
|
||||
pub async fn guild(_ctx: Context<'_>) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
32
src/commands/todo/guild/view.rs
Normal file
32
src/commands/todo/guild/view.rs
Normal file
@ -0,0 +1,32 @@
|
||||
use crate::{commands::todo::show_todo_page, Context, Error};
|
||||
|
||||
/// View and remove from the server todo list
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
rename = "view",
|
||||
guild_only = true,
|
||||
identifying_name = "todo_guild_view",
|
||||
default_member_permissions = "MANAGE_GUILD"
|
||||
)]
|
||||
pub async fn view(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let values = sqlx::query!(
|
||||
"
|
||||
SELECT todos.id, value FROM todos
|
||||
INNER JOIN guilds ON todos.guild_id = guilds.id
|
||||
WHERE guilds.guild = ?
|
||||
",
|
||||
ctx.guild_id().unwrap().get(),
|
||||
)
|
||||
.fetch_all(&ctx.data().database)
|
||||
.await
|
||||
.unwrap()
|
||||
.iter()
|
||||
.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.get()));
|
||||
|
||||
ctx.send(resp).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
157
src/commands/todo/mod.rs
Normal file
157
src/commands/todo/mod.rs
Normal file
@ -0,0 +1,157 @@
|
||||
use poise::{
|
||||
serenity_prelude::{
|
||||
CreateActionRow, CreateEmbed, CreateEmbedFooter, CreateSelectMenu, CreateSelectMenuKind,
|
||||
CreateSelectMenuOption,
|
||||
},
|
||||
CreateReply,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
component_models::{
|
||||
pager::{Pager, TodoPager},
|
||||
ComponentDataModel, TodoSelector,
|
||||
},
|
||||
consts::{EMBED_DESCRIPTION_MAX_LENGTH, SELECT_MAX_ENTRIES, THEME_COLOR},
|
||||
Context, Error,
|
||||
};
|
||||
|
||||
pub mod channel;
|
||||
pub mod guild;
|
||||
pub mod user;
|
||||
|
||||
/// Manage todo lists
|
||||
#[poise::command(slash_command, default_member_permissions = "MANAGE_GUILD")]
|
||||
pub async fn todo(_ctx: Context<'_>) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn max_todo_page(todo_values: &[(usize, String)]) -> usize {
|
||||
let mut rows = 0;
|
||||
let mut char_count = 0;
|
||||
|
||||
todo_values.iter().enumerate().map(|(c, (_, v))| format!("{}: {}", c, v)).fold(
|
||||
1,
|
||||
|mut pages, text| {
|
||||
rows += 1;
|
||||
char_count += text.len();
|
||||
|
||||
if char_count > EMBED_DESCRIPTION_MAX_LENGTH || rows > SELECT_MAX_ENTRIES {
|
||||
rows = 1;
|
||||
char_count = text.len();
|
||||
pages += 1;
|
||||
}
|
||||
|
||||
pages
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn show_todo_page(
|
||||
todo_values: &[(usize, String)],
|
||||
page: usize,
|
||||
user_id: Option<u64>,
|
||||
channel_id: Option<u64>,
|
||||
guild_id: Option<u64>,
|
||||
) -> CreateReply {
|
||||
let pager = TodoPager::new(page, user_id, channel_id, guild_id);
|
||||
|
||||
let pages = max_todo_page(todo_values);
|
||||
let mut page = page;
|
||||
if page >= pages {
|
||||
page = pages - 1;
|
||||
}
|
||||
|
||||
let mut char_count = 0;
|
||||
let mut rows = 0;
|
||||
let mut skipped_rows = 0;
|
||||
let mut skipped_char_count = 0;
|
||||
let mut first_num = 0;
|
||||
|
||||
let mut skipped_pages = 0;
|
||||
|
||||
let (todo_ids, display_vec): (Vec<usize>, Vec<String>) = todo_values
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(c, (i, v))| (i, format!("`{}`: {}", c + 1, v)))
|
||||
.skip_while(|(_, p)| {
|
||||
first_num += 1;
|
||||
skipped_rows += 1;
|
||||
skipped_char_count += p.len();
|
||||
|
||||
if skipped_char_count > EMBED_DESCRIPTION_MAX_LENGTH
|
||||
|| skipped_rows > SELECT_MAX_ENTRIES
|
||||
{
|
||||
skipped_rows = 1;
|
||||
skipped_char_count = p.len();
|
||||
skipped_pages += 1;
|
||||
}
|
||||
|
||||
skipped_pages < page
|
||||
})
|
||||
.take_while(|(_, p)| {
|
||||
rows += 1;
|
||||
char_count += p.len();
|
||||
|
||||
char_count < EMBED_DESCRIPTION_MAX_LENGTH && rows <= SELECT_MAX_ENTRIES
|
||||
})
|
||||
.unzip();
|
||||
|
||||
let display = display_vec.join("\n");
|
||||
|
||||
let title = if user_id.is_some() {
|
||||
"Your"
|
||||
} else if channel_id.is_some() {
|
||||
"Channel"
|
||||
} else {
|
||||
"Server"
|
||||
};
|
||||
|
||||
if todo_ids.is_empty() {
|
||||
CreateReply::default().embed(
|
||||
CreateEmbed::new()
|
||||
.title(format!("{} Todo List", title))
|
||||
.description("Todo List Empty!")
|
||||
.color(*THEME_COLOR)
|
||||
.footer(CreateEmbedFooter::new(format!("Page {} of {}", page + 1, pages))),
|
||||
)
|
||||
} else {
|
||||
let todo_selector =
|
||||
ComponentDataModel::TodoSelector(TodoSelector { page, user_id, channel_id, guild_id });
|
||||
|
||||
CreateReply::default()
|
||||
.embed(
|
||||
CreateEmbed::new()
|
||||
.title(format!("{} Todo List", title))
|
||||
.description(display)
|
||||
.color(*THEME_COLOR)
|
||||
.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()
|
||||
};
|
||||
|
||||
CreateSelectMenuOption::new(
|
||||
format!("Mark {} complete", count + first_num),
|
||||
id.to_string(),
|
||||
)
|
||||
.description(description)
|
||||
})
|
||||
.collect(),
|
||||
},
|
||||
)),
|
||||
])
|
||||
}
|
||||
}
|
27
src/commands/todo/user/add.rs
Normal file
27
src/commands/todo/user/add.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use crate::{Context, Error};
|
||||
|
||||
/// Add an item to your personal todo list
|
||||
#[poise::command(slash_command, rename = "add", identifying_name = "todo_user_add")]
|
||||
pub async fn add(
|
||||
ctx: Context<'_>,
|
||||
#[description = "The task to add to the todo list"] task: String,
|
||||
) -> Result<(), Error> {
|
||||
sqlx::query!(
|
||||
"
|
||||
INSERT INTO todos (user_id, value)
|
||||
VALUES (
|
||||
(SELECT id FROM users WHERE user = ?),
|
||||
?
|
||||
)
|
||||
",
|
||||
ctx.author().id.get(),
|
||||
task
|
||||
)
|
||||
.execute(&ctx.data().database)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
ctx.say("Item added to todo list").await?;
|
||||
|
||||
Ok(())
|
||||
}
|
10
src/commands/todo/user/mod.rs
Normal file
10
src/commands/todo/user/mod.rs
Normal file
@ -0,0 +1,10 @@
|
||||
pub mod add;
|
||||
pub mod view;
|
||||
|
||||
use crate::{Context, Error};
|
||||
|
||||
/// Manage your personal todo list
|
||||
#[poise::command(slash_command, rename = "user", identifying_name = "todo_user_base")]
|
||||
pub async fn user(_ctx: Context<'_>) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
26
src/commands/todo/user/view.rs
Normal file
26
src/commands/todo/user/view.rs
Normal file
@ -0,0 +1,26 @@
|
||||
use crate::{commands::todo::show_todo_page, Context, Error};
|
||||
|
||||
/// View and remove from your personal todo list
|
||||
#[poise::command(slash_command, rename = "view", identifying_name = "todo_user_view")]
|
||||
pub async fn view(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let values = sqlx::query!(
|
||||
"
|
||||
SELECT todos.id, value FROM todos
|
||||
INNER JOIN users ON todos.user_id = users.id
|
||||
WHERE users.user = ?
|
||||
",
|
||||
ctx.author().id.get(),
|
||||
)
|
||||
.fetch_all(&ctx.data().database)
|
||||
.await
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|row| (row.id as usize, row.value.clone()))
|
||||
.collect::<Vec<(usize, String)>>();
|
||||
|
||||
let resp = show_todo_page(&values, 0, Some(ctx.author().id.get()), None, None);
|
||||
|
||||
ctx.send(resp).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
Reference in New Issue
Block a user