improvements to todo interface, now using todos and todoc as with old versionn

This commit is contained in:
jude 2020-10-17 15:21:00 +01:00
parent 87a7c69b76
commit fd84a57e82
2 changed files with 153 additions and 165 deletions

View File

@ -19,6 +19,8 @@ use crate::{
use sqlx::MySqlPool;
use std::convert::TryFrom;
use async_trait::async_trait;
#[derive(Debug)]
struct TodoNotFound;
@ -232,6 +234,97 @@ DELETE FROM todos WHERE user_id = (SELECT id FROM users WHERE user = ?) AND guil
Ok(())
}
async fn execute(&self, ctx: &Context, msg: &Message, subcommand: SubCommand, extra: String) {
let pool = ctx
.data
.read()
.await
.get::<SQLPool>()
.cloned()
.expect("Could not get SQLPool from data");
let user_data = UserData::from_user(&msg.author, &ctx, &pool).await.unwrap();
let prefix = GuildData::prefix_from_id(msg.guild_id, &pool).await;
match subcommand {
SubCommand::View => {
let todo_items = self.view(pool).await.unwrap();
let mut todo_groups = vec!["".to_string()];
let mut char_count = 0;
todo_items.iter().enumerate().for_each(|(count, todo)| {
let display = format!("{}: {}\n", count + 1, todo.value);
if char_count + display.len() > MESSAGE_CODE_LIMIT as usize {
char_count = display.len();
todo_groups.push(display);
} else {
char_count += display.len();
let last_group = todo_groups.pop().unwrap();
todo_groups.push(format!("{}{}", last_group, display));
}
});
for group in todo_groups {
let _ = msg
.channel_id
.send_message(&ctx, |m| {
m.embed(|e| e.title(format!("{} Todo", self.name())).description(group))
})
.await;
}
}
SubCommand::Add => {
let content = user_data
.response(&pool, "todo/added")
.await
.replacen("{name}", &extra, 1);
self.add(extra, pool).await.unwrap();
let _ = msg.channel_id.say(&ctx, content).await;
}
SubCommand::Remove => {
let _ = if let Ok(num) = extra.parse::<usize>() {
if let Ok(todo) = self.remove(num - 1, &pool).await {
let content = user_data.response(&pool, "todo/removed").await.replacen(
"{}",
&todo.value,
1,
);
msg.channel_id.say(&ctx, content)
} else {
msg.channel_id
.say(&ctx, user_data.response(&pool, "todo/error_index").await)
}
} else {
let content = user_data
.response(&pool, "todo/error_value")
.await
.replacen("{prefix}", &prefix, 1)
.replacen("{command}", &self.command(Some(subcommand)), 1);
msg.channel_id.say(&ctx, content)
}
.await;
}
SubCommand::Clear => {
self.clear(&pool).await.unwrap();
let content = user_data.response(&pool, "todo/cleared").await;
let _ = msg.channel_id.say(&ctx, content).await;
}
}
}
}
enum SubCommand {
@ -252,7 +345,7 @@ impl TryFrom<Option<&str>> for SubCommand {
Some("clear") => Ok(SubCommand::Clear),
None => Ok(SubCommand::View),
None | Some("") => Ok(SubCommand::View),
Some(_unrecognised) => Err(()),
}
@ -271,6 +364,22 @@ impl ToString for SubCommand {
}
}
#[async_trait]
trait Execute {
async fn execute(self, ctx: &Context, msg: &Message, extra: String, target: TodoTarget);
}
#[async_trait]
impl Execute for Result<SubCommand, ()> {
async fn execute(self, ctx: &Context, msg: &Message, extra: String, target: TodoTarget) {
if let Ok(subcommand) = self {
target.execute(ctx, msg, subcommand, extra).await;
} else {
show_help(&ctx, msg, Some(target)).await;
}
}
}
#[command]
#[permission_level(Managed)]
async fn todo_user(ctx: &Context, msg: &Message, args: String) -> CommandResult {
@ -284,83 +393,51 @@ async fn todo_user(ctx: &Context, msg: &Message, args: String) -> CommandResult
let subcommand_opt = SubCommand::try_from(split.next());
if let Ok(subcommand) = subcommand_opt {
todo(
ctx,
msg,
target,
subcommand,
split.collect::<Vec<&str>>().join(" "),
)
subcommand_opt
.execute(ctx, msg, split.collect::<Vec<&str>>().join(" "), target)
.await;
} else {
show_help(&ctx, msg, Some(target)).await;
}
Ok(())
}
#[command]
#[supports_dm(false)]
#[permission_level(Managed)]
async fn todo_parse(ctx: &Context, msg: &Message, args: String) -> CommandResult {
async fn todo_channel(ctx: &Context, msg: &Message, args: String) -> CommandResult {
let mut split = args.split(' ');
if let Some(target) = split.next() {
let target_opt = match target {
"user" => Some(TodoTarget {
let target = TodoTarget {
user: msg.author.id,
guild: None,
channel: None,
}),
"channel" => {
if let Some(gid) = msg.guild_id {
Some(TodoTarget {
user: msg.author.id,
guild: Some(gid),
guild: msg.guild_id,
channel: Some(msg.channel_id),
})
} else {
None
}
}
"server" | "guild" => {
if let Some(gid) = msg.guild_id {
Some(TodoTarget {
user: msg.author.id,
guild: Some(gid),
channel: None,
})
} else {
None
}
}
_ => None,
};
if let Some(target) = target_opt {
let subcommand_opt = SubCommand::try_from(split.next());
if let Ok(subcommand) = subcommand_opt {
todo(
ctx,
msg,
target,
subcommand,
split.collect::<Vec<&str>>().join(" "),
)
subcommand_opt
.execute(ctx, msg, split.collect::<Vec<&str>>().join(" "), target)
.await;
Ok(())
}
#[command]
#[supports_dm(false)]
#[permission_level(Managed)]
async fn todo_guild(ctx: &Context, msg: &Message, args: String) -> CommandResult {
let mut split = args.split(' ');
let target = TodoTarget {
user: msg.author.id,
guild: msg.guild_id,
channel: None,
};
let subcommand_opt = SubCommand::try_from(split.next());
subcommand_opt
.execute(ctx, msg, split.collect::<Vec<&str>>().join(" "), target)
.await;
} else {
show_help(&ctx, msg, Some(target)).await;
}
} else {
show_help(&ctx, msg, None).await;
}
} else {
show_help(&ctx, msg, None).await;
}
Ok(())
}
@ -390,103 +467,3 @@ async fn show_help(ctx: &Context, msg: &Message, target: Option<TodoTarget>) {
let _ = msg.channel_id.say(&ctx, content).await;
}
async fn todo(
ctx: &Context,
msg: &Message,
target: TodoTarget,
subcommand: SubCommand,
extra: String,
) {
let pool = ctx
.data
.read()
.await
.get::<SQLPool>()
.cloned()
.expect("Could not get SQLPool from data");
let user_data = UserData::from_user(&msg.author, &ctx, &pool).await.unwrap();
let prefix = GuildData::prefix_from_id(msg.guild_id, &pool).await;
match subcommand {
SubCommand::View => {
let todo_items = target.view(pool).await.unwrap();
let mut todo_groups = vec!["".to_string()];
let mut char_count = 0;
todo_items.iter().enumerate().for_each(|(count, todo)| {
let display = format!("{}: {}\n", count + 1, todo.value);
if char_count + display.len() > MESSAGE_CODE_LIMIT as usize {
char_count = display.len();
todo_groups.push(display);
} else {
char_count += display.len();
let last_group = todo_groups.pop().unwrap();
todo_groups.push(format!("{}{}", last_group, display));
}
});
for group in todo_groups {
let _ = msg
.channel_id
.send_message(&ctx, |m| {
m.embed(|e| {
e.title(format!("{} Todo", target.name()))
.description(group)
})
})
.await;
}
}
SubCommand::Add => {
let content = user_data
.response(&pool, "todo/added")
.await
.replacen("{name}", &extra, 1);
target.add(extra, pool).await.unwrap();
let _ = msg.channel_id.say(&ctx, content).await;
}
SubCommand::Remove => {
let _ = if let Ok(num) = extra.parse::<usize>() {
if let Ok(todo) = target.remove(num - 1, &pool).await {
let content = user_data.response(&pool, "todo/removed").await.replacen(
"{}",
&todo.value,
1,
);
msg.channel_id.say(&ctx, content)
} else {
msg.channel_id
.say(&ctx, user_data.response(&pool, "todo/error_index").await)
}
} else {
let content = user_data
.response(&pool, "todo/error_value")
.await
.replacen("{prefix}", &prefix, 1)
.replacen("{command}", &target.command(Some(subcommand)), 1);
msg.channel_id.say(&ctx, content)
}
.await;
}
SubCommand::Clear => {
target.clear(&pool).await.unwrap();
let content = user_data.response(&pool, "todo/cleared").await;
let _ = msg.channel_id.say(&ctx, content).await;
}
}
}

View File

@ -70,6 +70,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let framework = RegexFramework::new(logged_in_id)
.default_prefix(DEFAULT_PREFIX.clone())
.ignore_bots(env::var("IGNORE_BOTS").map_or(true, |var| var == "1"))
// info commands
.add_command("ping", &info_cmds::PING_COMMAND)
.add_command("help", &info_cmds::HELP_COMMAND)
.add_command("info", &info_cmds::INFO_COMMAND)
@ -77,6 +78,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
.add_command("donate", &info_cmds::DONATE_COMMAND)
.add_command("dashboard", &info_cmds::DASHBOARD_COMMAND)
.add_command("clock", &info_cmds::CLOCK_COMMAND)
// reminder commands
.add_command("timer", &reminder_cmds::TIMER_COMMAND)
.add_command("remind", &reminder_cmds::REMIND_COMMAND)
.add_command("r", &reminder_cmds::REMIND_COMMAND)
@ -85,9 +87,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
.add_command("natural", &reminder_cmds::NATURAL_COMMAND)
.add_command("n", &reminder_cmds::NATURAL_COMMAND)
.add_command("", &reminder_cmds::NATURAL_COMMAND)
// management commands
.add_command("look", &reminder_cmds::LOOK_COMMAND)
.add_command("del", &reminder_cmds::DELETE_COMMAND)
.add_command("todo", &todo_cmds::TODO_PARSE_COMMAND)
// to-do commands
.add_command("todo", &todo_cmds::TODO_USER_COMMAND)
.add_command("todo user", &todo_cmds::TODO_USER_COMMAND)
.add_command("todoc", &todo_cmds::TODO_CHANNEL_COMMAND)
.add_command("todo channel", &todo_cmds::TODO_CHANNEL_COMMAND)
.add_command("todos", &todo_cmds::TODO_GUILD_COMMAND)
.add_command("todo server", &todo_cmds::TODO_GUILD_COMMAND)
.add_command("todo guild", &todo_cmds::TODO_GUILD_COMMAND)
// moderation commands
.add_command("blacklist", &moderation_cmds::BLACKLIST_COMMAND)
.add_command("restrict", &moderation_cmds::RESTRICT_COMMAND)
.add_command("timezone", &moderation_cmds::TIMEZONE_COMMAND)