diff --git a/src/commands/info_cmds.rs b/src/commands/info_cmds.rs index b2590ea..a26af4f 100644 --- a/src/commands/info_cmds.rs +++ b/src/commands/info_cmds.rs @@ -24,10 +24,16 @@ use crate::{ #[command] #[can_blacklist(false)] async fn help(ctx: &Context, msg: &Message, _args: String) -> CommandResult { + let pool = ctx.data.read().await + .get::().cloned().expect("Could not get SQLPool from data"); + + let user_data = UserData::from_id(&msg.author, &ctx, &pool).await.unwrap(); + let desc = user_data.response(&pool, "help").await; + msg.channel_id.send_message(ctx, |m| m - .embed(|e| e + .embed(move |e| e .title("Help") - .description("Help Description") + .description(desc) .color(THEME_COLOR) ) ).await?; @@ -37,10 +43,16 @@ async fn help(ctx: &Context, msg: &Message, _args: String) -> CommandResult { #[command] async fn info(ctx: &Context, msg: &Message, _args: String) -> CommandResult { + let pool = ctx.data.read().await + .get::().cloned().expect("Could not get SQLPool from data"); + + let user_data = UserData::from_id(&msg.author, &ctx, &pool).await.unwrap(); + let desc = user_data.response(&pool, "info").await; + msg.channel_id.send_message(ctx, |m| m - .embed(|e| e + .embed(move |e| e .title("Info") - .description("Info Description") + .description(desc) .color(THEME_COLOR) ) ).await?; @@ -50,10 +62,29 @@ async fn info(ctx: &Context, msg: &Message, _args: String) -> CommandResult { #[command] async fn donate(ctx: &Context, msg: &Message, _args: String) -> CommandResult { + let pool = ctx.data.read().await + .get::().cloned().expect("Could not get SQLPool from data"); + + let user_data = UserData::from_id(&msg.author, &ctx, &pool).await.unwrap(); + let desc = user_data.response(&pool, "donate").await; + msg.channel_id.send_message(ctx, |m| m - .embed(|e| e + .embed(move |e| e .title("Donate") - .description("Donate Description") + .description(desc) + .color(THEME_COLOR) + ) + ).await?; + + Ok(()) +} + +#[command] +async fn dashboard(ctx: &Context, msg: &Message, _args: String) -> CommandResult { + msg.channel_id.send_message(ctx, |m| m + .embed(move |e| e + .title("Dashboard") + .description("https://reminder-bot.com/dashboard") .color(THEME_COLOR) ) ).await?; @@ -66,17 +97,17 @@ async fn clock(ctx: &Context, msg: &Message, args: String) -> CommandResult { let pool = ctx.data.read().await .get::().cloned().expect("Could not get SQLPool from data"); - let user_data = UserData::from_id(&msg.author, &ctx, pool).await.unwrap(); + let user_data = UserData::from_id(&msg.author, &ctx, &pool).await.unwrap(); let tz: Tz = user_data.timezone.parse().unwrap(); let now = Utc::now().with_timezone(&tz); if args == "12".to_string() { - let _ = msg.channel_id.say(&ctx, format!("Current time: **{}**", now.format("%I:%M:%S %p"))).await; + let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "clock/time").await.replacen("{}", &now.format("%I:%M:%S %p").to_string(), 1)).await; } else { - let _ = msg.channel_id.say(&ctx, format!("Current time: **{}**", now.format("%H:%M:%S"))).await; + let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "clock/time").await.replacen("{}", &now.format("%H:%M:%S").to_string(), 1)).await; } Ok(()) diff --git a/src/commands/moderation_cmds.rs b/src/commands/moderation_cmds.rs index c1790e5..1d9dadf 100644 --- a/src/commands/moderation_cmds.rs +++ b/src/commands/moderation_cmds.rs @@ -21,8 +21,6 @@ use crate::{ GuildData, }, SQLPool, - framework::SendFromDb, - time_parser::TimeParser, }; lazy_static! { @@ -41,14 +39,14 @@ async fn blacklist(ctx: &Context, msg: &Message, args: String) -> CommandResult let mut channel = match capture_opt { Some(capture) => - ChannelData::from_id(capture.as_str().parse::().unwrap(), pool.clone()).await.unwrap(), + ChannelData::from_id(capture.as_str().parse::().unwrap(), &pool).await.unwrap(), None => - ChannelData::from_channel(msg.channel(&ctx).await.unwrap(), pool.clone()).await.unwrap(), + ChannelData::from_channel(msg.channel(&ctx).await.unwrap(), &pool).await.unwrap(), }; channel.blacklisted = !channel.blacklisted; - channel.commit_changes(pool).await; + channel.commit_changes(&pool).await; if channel.blacklisted { let _ = msg.channel_id.say(&ctx, "Blacklisted").await; @@ -65,25 +63,25 @@ async fn timezone(ctx: &Context, msg: &Message, args: String) -> CommandResult { let pool = ctx.data.read().await .get::().cloned().expect("Could not get SQLPool from data"); - let mut user_data = UserData::from_id(&msg.author, &ctx, pool.clone()).await.unwrap(); + let mut user_data = UserData::from_id(&msg.author, &ctx, &pool).await.unwrap(); if args.len() > 0 { match args.parse::() { Ok(_) => { user_data.timezone = args; - user_data.commit_changes(pool).await; + user_data.commit_changes(&pool).await; - let _ = msg.channel_id.say_named(&ctx, user_data.language, "timezone/set_p").await; + let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "timezone/set_p").await).await; } Err(_) => { - let _ = msg.channel_id.say_named(&ctx, user_data.language, "timezone/no_timezone").await; + let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "timezone/no_timezone").await).await; } } } else { - let _ = msg.channel_id.say_named(&ctx, user_data.language, "timezone/no_argument").await; + let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "timezone/no_argument").await).await; } Ok(()) @@ -94,7 +92,7 @@ async fn language(ctx: &Context, msg: &Message, args: String) -> CommandResult { let pool = ctx.data.read().await .get::().cloned().expect("Could not get SQLPool from data"); - let mut user_data = UserData::from_id(&msg.author, &ctx, pool.clone()).await.unwrap(); + let mut user_data = UserData::from_id(&msg.author, &ctx, &pool).await.unwrap(); match sqlx::query!( " @@ -106,13 +104,13 @@ SELECT code FROM languages WHERE code = ? OR name = ? Ok(row) => { user_data.language = row.code; - user_data.commit_changes(pool).await; + user_data.commit_changes(&pool).await; - let _ = msg.channel_id.say_named(&ctx, user_data.language, "lang/set_p").await; + let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "lang/set_p").await).await; }, Err(_) => { - let _ = msg.channel_id.say_named(&ctx, user_data.language, "lang/invalid").await; + let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "lang/invalid").await).await; }, } @@ -124,22 +122,20 @@ async fn prefix(ctx: &Context, msg: &Message, args: String) -> CommandResult { let pool = ctx.data.read().await .get::().cloned().expect("Could not get SQLPool from data"); - let mut guild_data = GuildData::from_guild(msg.guild(&ctx).await.unwrap(), pool.clone()).await.unwrap(); - let user_data = UserData::from_id(&msg.author, &ctx, pool.clone()).await.unwrap(); + let mut guild_data = GuildData::from_guild(msg.guild(&ctx).await.unwrap(), &pool).await.unwrap(); + let user_data = UserData::from_id(&msg.author, &ctx, &pool).await.unwrap(); if args.len() > 5 { - let _ = msg.channel_id.say_named(&ctx, user_data.language, "prefix/too_long").await; - + let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "prefix/too_long").await).await; } else if args.len() == 0 { - let _ = msg.channel_id.say_named(&ctx, user_data.language, "prefix/no_argument").await; + let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "prefix/no_argument").await).await; } else { guild_data.prefix = args; + guild_data.commit_changes(&pool).await; - guild_data.commit_changes(pool).await; - - let _ = msg.channel_id.say_named(&ctx, user_data.language, "prefix/success").await; + let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "prefix/success").await).await; } Ok(()) diff --git a/src/commands/reminder_cmds.rs b/src/commands/reminder_cmds.rs index 0b31cdc..a69de99 100644 --- a/src/commands/reminder_cmds.rs +++ b/src/commands/reminder_cmds.rs @@ -10,18 +10,12 @@ use serenity::{ framework::standard::CommandResult, }; -use chrono_tz::{ - Tz, - Etc::UTC, -}; - use crate::{ models::{ ChannelData, UserData, }, SQLPool, - framework::SendFromDb, time_parser::TimeParser, }; @@ -33,20 +27,20 @@ async fn pause(ctx: &Context, msg: &Message, args: String) -> CommandResult { let pool = ctx.data.read().await .get::().cloned().expect("Could not get SQLPool from data"); - let user_data = UserData::from_id(&msg.author, &ctx, pool.clone()).await.unwrap(); - let mut channel = ChannelData::from_channel(msg.channel(&ctx).await.unwrap(), pool.clone()).await.unwrap(); + let user_data = UserData::from_id(&msg.author, &ctx, &pool).await.unwrap(); + let mut channel = ChannelData::from_channel(msg.channel(&ctx).await.unwrap(), &pool).await.unwrap(); if args.len() == 0 { channel.paused = !channel.paused; channel.paused_until = None; - channel.commit_changes(pool).await; + channel.commit_changes(&pool).await; if channel.paused { - let _ = msg.channel_id.say_named(&ctx, user_data.language, "paused/paused_indefinite").await; + let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "paused/paused_indefinite").await).await; } else { - let _ = msg.channel_id.say_named(&ctx, user_data.language, "paused/unpaused").await; + let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "paused/unpaused").await).await; } } else { @@ -58,13 +52,13 @@ async fn pause(ctx: &Context, msg: &Message, args: String) -> CommandResult { channel.paused = true; channel.paused_until = Some(NaiveDateTime::from_timestamp(timestamp, 0)); - channel.commit_changes(pool).await; + channel.commit_changes(&pool).await; - let _ = msg.channel_id.say_named(&ctx, user_data.language, "paused/paused_until").await; + let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "paused/paused_until").await).await; }, Err(_) => { - let _ = msg.channel_id.say_named(&ctx, user_data.language, "paused/invalid_time").await; + let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "paused/invalid_time").await).await; }, } } diff --git a/src/framework.rs b/src/framework.rs index eb068ec..9dd9b21 100644 --- a/src/framework.rs +++ b/src/framework.rs @@ -1,14 +1,12 @@ use async_trait::async_trait; use serenity::{ - Result as SerenityResult, client::Context, framework::{ Framework, standard::CommandResult, }, model::{ - id::ChannelId, guild::{ Guild, Member, @@ -43,33 +41,6 @@ use crate::{ type CommandFn = for<'fut> fn(&'fut Context, &'fut Message, String) -> BoxFuture<'fut, CommandResult>; -#[async_trait] -pub trait SendFromDb { - async fn say_named(&self, ctx: &&Context, language: String, name: &str) -> SerenityResult; -} - -struct Value { - value: String, -} - -#[async_trait] -impl SendFromDb for ChannelId { - async fn say_named(&self, ctx: &&Context, language: String, name: &str) -> SerenityResult { - let pool = ctx.data.read().await - .get::().cloned().expect("Could not get SQLPool from data"); - - let row = sqlx::query_as!(Value, - " -SELECT value FROM strings WHERE (language = ? OR language = 'EN') AND name = ? ORDER BY language = 'EN' - ", language, name) - .fetch_one(&pool) - .await - .expect("No string with that name"); - - self.say(ctx, row.value).await - } -} - #[derive(Debug)] pub enum PermissionLevel { Unrestricted, @@ -293,7 +264,7 @@ impl Framework for RegexFramework { let pool = ctx.data.read().await .get::().cloned().expect("Could not get SQLPool from data"); - match sqlx::query!("SELECT prefix FROM guilds WHERE id = ?", guild.id.as_u64()) + match sqlx::query!("SELECT prefix FROM guilds WHERE guild = ?", guild.id.as_u64()) .fetch_one(&pool) .await { Ok(row) => { @@ -347,7 +318,7 @@ impl Framework for RegexFramework { .get::().cloned().expect("Could not get SQLPool from data"); let command = self.commands.get(full_match.name("cmd").unwrap().as_str()).unwrap(); - let channel_data = ChannelData::from_channel(msg.channel(&ctx).await.unwrap(), pool).await; + let channel_data = ChannelData::from_channel(msg.channel(&ctx).await.unwrap(), &pool).await; if !command.can_blacklist || !channel_data.map(|c| c.blacklisted).unwrap_or(false) { let args = full_match.name("args") diff --git a/src/main.rs b/src/main.rs index 1e8add1..0d0f288 100644 --- a/src/main.rs +++ b/src/main.rs @@ -61,10 +61,12 @@ async fn main() -> Result<(), Box> { .add_command("help", &info_cmds::HELP_COMMAND) .add_command("info", &info_cmds::INFO_COMMAND) .add_command("donate", &info_cmds::DONATE_COMMAND) + .add_command("dashboard", &info_cmds::DASHBOARD_COMMAND) .add_command("clock", &info_cmds::CLOCK_COMMAND) .add_command("todo", &todo_cmds::TODO_PARSE_COMMAND) .add_command("blacklist", &moderation_cmds::BLACKLIST_COMMAND) .add_command("timezone", &moderation_cmds::TIMEZONE_COMMAND) + .add_command("prefix", &moderation_cmds::PREFIX_COMMAND) .add_command("lang", &moderation_cmds::LANGUAGE_COMMAND) .add_command("pause", &reminder_cmds::PAUSE_COMMAND) .build(); diff --git a/src/models.rs b/src/models.rs index 6e8a14e..18e5eca 100644 --- a/src/models.rs +++ b/src/models.rs @@ -1,7 +1,6 @@ use serenity::{ prelude::Context, model::{ - id::ChannelId, guild::Guild, channel::Channel, user::User, @@ -19,14 +18,14 @@ pub struct GuildData { } impl GuildData { - pub async fn from_guild(guild: Guild, pool: MySqlPool) -> Result> { + pub async fn from_guild(guild: Guild, pool: &MySqlPool) -> Result> { let guild_id = guild.id.as_u64().clone(); if let Ok(g) = sqlx::query_as!(Self, " SELECT id, guild, name, prefix FROM guilds WHERE guild = ? ", guild_id) - .fetch_one(&pool) + .fetch_one(pool) .await { Ok(g) @@ -36,24 +35,24 @@ SELECT id, guild, name, prefix FROM guilds WHERE guild = ? " INSERT INTO guilds (guild, name) VALUES (?, ?) ", guild_id, guild.name) - .execute(&pool) + .execute(&pool.clone()) .await?; Ok(sqlx::query_as!(Self, " SELECT id, guild, name, prefix FROM guilds WHERE guild = ? ", guild_id) - .fetch_one(&pool) + .fetch_one(pool) .await?) } } - pub async fn commit_changes(&self, pool: MySqlPool) { + pub async fn commit_changes(&self, pool: &MySqlPool) { sqlx::query!( " UPDATE guilds SET name = ?, prefix = ? WHERE id = ? ", self.name, self.prefix, self.id) - .execute(&pool) + .execute(pool) .await.unwrap(); } } @@ -72,23 +71,23 @@ pub struct ChannelData { } impl ChannelData { - pub async fn from_id(channel_id: u64, pool: MySqlPool) -> Option { + pub async fn from_id(channel_id: u64, pool: &MySqlPool) -> Option { sqlx::query_as_unchecked!(Self, " SELECT * FROM channels WHERE channel = ? ", channel_id) - .fetch_one(&pool) + .fetch_one(pool) .await.ok() } - pub async fn from_channel(channel: Channel, pool: MySqlPool) -> Result> { + pub async fn from_channel(channel: Channel, pool: &MySqlPool) -> Result> { let channel_id = channel.id().as_u64().clone(); if let Ok(c) = sqlx::query_as_unchecked!(Self, " SELECT * FROM channels WHERE channel = ? ", channel_id) - .fetch_one(&pool) + .fetch_one(pool) .await { Ok(c) @@ -106,24 +105,24 @@ SELECT * FROM channels WHERE channel = ? " INSERT INTO channels (channel, name, guild_id) VALUES (?, ?, (SELECT id FROM guilds WHERE guild = ?)) ", channel_id, channel_name, guild_id) - .execute(&pool) + .execute(&pool.clone()) .await?; Ok(sqlx::query_as_unchecked!(Self, " SELECT * FROM channels WHERE channel = ? ", channel_id) - .fetch_one(&pool) + .fetch_one(pool) .await?) } } - pub async fn commit_changes(&self, pool: MySqlPool) { + pub async fn commit_changes(&self, pool: &MySqlPool) { sqlx::query!( " UPDATE channels SET name = ?, nudge = ?, blacklisted = ?, webhook_id = ?, webhook_token = ?, paused = ?, paused_until = ? WHERE id = ? ", self.name, self.nudge, self.blacklisted, self.webhook_id, self.webhook_token, self.paused, self.paused_until, self.id) - .execute(&pool) + .execute(pool) .await.unwrap(); } } @@ -138,14 +137,14 @@ pub struct UserData { } impl UserData { - pub async fn from_id(user: &User, ctx: &&Context, pool: MySqlPool) -> Result> { + pub async fn from_id(user: &User, ctx: &&Context, pool: &MySqlPool) -> Result> { let user_id = user.id.as_u64().clone(); if let Ok(c) = sqlx::query_as_unchecked!(Self, " SELECT id, user, name, dm_channel, language, timezone FROM users WHERE user = ? ", user_id) - .fetch_one(&pool) + .fetch_one(pool) .await { Ok(c) @@ -154,35 +153,49 @@ SELECT id, user, name, dm_channel, language, timezone FROM users WHERE user = ? let dm_channel = user.create_dm_channel(ctx).await?; let dm_id = dm_channel.id.as_u64().clone(); + let pool_c = pool.clone(); + sqlx::query!( " INSERT INTO channels (channel) VALUES (?) ", dm_id) - .execute(&pool) + .execute(&pool_c) .await?; sqlx::query!( " INSERT INTO users (user, name, dm_channel) VALUES (?, ?, (SELECT id FROM channels WHERE channel = ?)) ", user_id, user.name, dm_id) - .execute(&pool) + .execute(&pool_c) .await?; Ok(sqlx::query_as_unchecked!(Self, " SELECT id, user, name, dm_channel, language, timezone FROM users WHERE user = ? ", user_id) - .fetch_one(&pool) + .fetch_one(pool) .await?) } } - pub async fn commit_changes(&self, pool: MySqlPool) { + pub async fn commit_changes(&self, pool: &MySqlPool) { sqlx::query!( " UPDATE users SET name = ?, language = ?, timezone = ? WHERE id = ? ", self.name, self.language, self.timezone, self.id) - .execute(&pool) + .execute(pool) .await.unwrap(); } + + pub async fn response(&self, pool: &MySqlPool, name: &str) -> String { + let row = sqlx::query!( + " +SELECT value FROM strings WHERE (language = ? OR language = 'EN') AND name = ? ORDER BY language = 'EN' + ", self.language, name) + .fetch_one(pool) + .await + .expect("No string with that name"); + + row.value.expect("No string with that name") + } } diff --git a/src/time_parser.rs b/src/time_parser.rs index 2f506ec..8d7df4d 100644 --- a/src/time_parser.rs +++ b/src/time_parser.rs @@ -10,8 +10,7 @@ use std::fmt::{ }; use chrono_tz::Tz; -use chrono::offset::Utc; -use chrono::{Timelike, Datelike, TimeZone}; +use chrono::TimeZone; #[derive(Debug)] pub enum InvalidTime {