Compare commits
	
		
			3 Commits
		
	
	
		
			4b42966284
			...
			jellywx/gu
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b0a04bb289 | |||
| eef1f6f3e8 | |||
| 3d08027325 | 
							
								
								
									
										92
									
								
								migration/05-restructure-guild-table.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								migration/05-restructure-guild-table.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | |||||||
|  | SET foreign_key_checks = 0; | ||||||
|  |  | ||||||
|  | START TRANSACTION; | ||||||
|  |  | ||||||
|  | -- drop existing constraints | ||||||
|  | ALTER TABLE channels DROP FOREIGN KEY `channels_ibfk_1`; | ||||||
|  | ALTER TABLE command_aliases DROP FOREIGN KEY `command_aliases_ibfk_1`; | ||||||
|  | ALTER TABLE events DROP FOREIGN KEY `events_ibfk_1`; | ||||||
|  | ALTER TABLE guild_users DROP FOREIGN KEY `guild_users_ibfk_1`; | ||||||
|  | ALTER TABLE macro DROP FOREIGN KEY `macro_ibfk_1`; | ||||||
|  | ALTER TABLE roles DROP FOREIGN KEY `roles_ibfk_1`; | ||||||
|  | ALTER TABLE todos DROP FOREIGN KEY `todos_ibfk_2`; | ||||||
|  | ALTER TABLE reminder_template DROP FOREIGN KEY `reminder_template_ibfk_1`; | ||||||
|  |  | ||||||
|  | -- update foreign key types | ||||||
|  | ALTER TABLE channels MODIFY `guild_id` BIGINT UNSIGNED; | ||||||
|  | ALTER TABLE command_aliases MODIFY `guild_id` BIGINT UNSIGNED; | ||||||
|  | ALTER TABLE events MODIFY `guild_id` BIGINT UNSIGNED; | ||||||
|  | ALTER TABLE guild_users MODIFY `guild` BIGINT UNSIGNED; | ||||||
|  | ALTER TABLE macro MODIFY `guild_id` BIGINT UNSIGNED; | ||||||
|  | ALTER TABLE roles MODIFY `guild_id` BIGINT UNSIGNED; | ||||||
|  | ALTER TABLE todos MODIFY `guild_id` BIGINT UNSIGNED; | ||||||
|  | ALTER TABLE reminder_template MODIFY `guild_id` BIGINT UNSIGNED; | ||||||
|  |  | ||||||
|  | -- update foreign key values | ||||||
|  | UPDATE channels SET `guild_id` = (SELECT `guild` FROM guilds WHERE guilds.`id` = `guild_id`); | ||||||
|  | UPDATE command_aliases SET `guild_id` = (SELECT `guild` FROM guilds WHERE guilds.`id` = `guild_id`); | ||||||
|  | UPDATE events SET `guild_id` = (SELECT `guild` FROM guilds WHERE guilds.`id` = `guild_id`); | ||||||
|  | UPDATE guild_users SET `guild` = (SELECT `guild` FROM guilds WHERE guilds.`id` = guild_users.`guild`); | ||||||
|  | UPDATE macro SET `guild_id` = (SELECT `guild` FROM guilds WHERE guilds.`id` = `guild_id`); | ||||||
|  | UPDATE roles SET `guild_id` = (SELECT `guild` FROM guilds WHERE guilds.`id` = `guild_id`); | ||||||
|  | UPDATE todos SET `guild_id` = (SELECT `guild` FROM guilds WHERE guilds.`id` = `guild_id`); | ||||||
|  | UPDATE reminder_template SET `guild_id` = (SELECT `guild` FROM guilds WHERE guilds.`id` = `guild_id`); | ||||||
|  |  | ||||||
|  | -- update guilds table | ||||||
|  | ALTER TABLE guilds MODIFY `id` BIGINT UNSIGNED NOT NULL; | ||||||
|  | UPDATE guilds SET `id` = `guild`; | ||||||
|  | ALTER TABLE guilds DROP COLUMN `guild`; | ||||||
|  | ALTER TABLE guilds ADD COLUMN `default_channel` BIGINT UNSIGNED; | ||||||
|  | ALTER TABLE guilds ADD CONSTRAINT `default_channel_fk` | ||||||
|  |     FOREIGN KEY (`default_channel`) | ||||||
|  |         REFERENCES channels(`channel`) | ||||||
|  |         ON DELETE SET NULL | ||||||
|  |         ON UPDATE CASCADE; | ||||||
|  |  | ||||||
|  | -- re-add constraints | ||||||
|  | ALTER TABLE channels ADD CONSTRAINT | ||||||
|  |     FOREIGN KEY (`guild_id`) | ||||||
|  |         REFERENCES guilds(`id`) | ||||||
|  |         ON DELETE CASCADE | ||||||
|  |         ON UPDATE CASCADE; | ||||||
|  |  | ||||||
|  | ALTER TABLE command_aliases ADD CONSTRAINT | ||||||
|  |     FOREIGN KEY (`guild_id`) | ||||||
|  |         REFERENCES guilds(`id`) | ||||||
|  |         ON DELETE CASCADE | ||||||
|  |         ON UPDATE CASCADE; | ||||||
|  |  | ||||||
|  | ALTER TABLE events ADD CONSTRAINT | ||||||
|  |     FOREIGN KEY (`guild_id`) | ||||||
|  |         REFERENCES guilds(`id`) | ||||||
|  |         ON DELETE CASCADE | ||||||
|  |         ON UPDATE CASCADE; | ||||||
|  |  | ||||||
|  | ALTER TABLE guild_users ADD CONSTRAINT | ||||||
|  |     FOREIGN KEY (`guild`) | ||||||
|  |         REFERENCES guilds(`id`) | ||||||
|  |         ON DELETE CASCADE | ||||||
|  |         ON UPDATE CASCADE; | ||||||
|  |  | ||||||
|  | ALTER TABLE macro ADD CONSTRAINT | ||||||
|  |     FOREIGN KEY (`guild_id`) | ||||||
|  |         REFERENCES guilds(`id`) | ||||||
|  |         ON DELETE CASCADE | ||||||
|  |         ON UPDATE CASCADE; | ||||||
|  |  | ||||||
|  | ALTER TABLE roles ADD CONSTRAINT | ||||||
|  |     FOREIGN KEY (`guild_id`) | ||||||
|  |         REFERENCES guilds(`id`) | ||||||
|  |         ON DELETE CASCADE | ||||||
|  |         ON UPDATE CASCADE; | ||||||
|  |  | ||||||
|  | ALTER TABLE todos ADD CONSTRAINT | ||||||
|  |     FOREIGN KEY (`guild_id`) | ||||||
|  |         REFERENCES guilds(`id`) | ||||||
|  |         ON DELETE CASCADE | ||||||
|  |         ON UPDATE CASCADE; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | COMMIT; | ||||||
|  |  | ||||||
|  | SET foreign_key_checks = 1; | ||||||
| @@ -24,7 +24,7 @@ pub async fn macro_name_autocomplete(ctx: Context<'_>, partial: &str) -> Vec<Str | |||||||
| SELECT name | SELECT name | ||||||
| FROM macro | FROM macro | ||||||
| WHERE | WHERE | ||||||
|     guild_id = (SELECT id FROM guilds WHERE guild = ?) |     guild_id = ? | ||||||
|     AND name LIKE CONCAT(?, '%')", |     AND name LIKE CONCAT(?, '%')", | ||||||
|         ctx.guild_id().unwrap().0, |         ctx.guild_id().unwrap().0, | ||||||
|         partial, |         partial, | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ pub async fn delete_macro( | |||||||
| ) -> Result<(), Error> { | ) -> Result<(), Error> { | ||||||
|     match sqlx::query!( |     match sqlx::query!( | ||||||
|         " |         " | ||||||
| SELECT id FROM macro WHERE guild_id = (SELECT id FROM guilds WHERE guild = ?) AND name = ?", | SELECT id FROM macro WHERE guild_id = ? AND name = ?", | ||||||
|         ctx.guild_id().unwrap().0, |         ctx.guild_id().unwrap().0, | ||||||
|         name |         name | ||||||
|     ) |     ) | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ pub async fn migrate_macro(ctx: Context<'_>) -> Result<(), Error> { | |||||||
|  |  | ||||||
|     let aliases = sqlx::query_as!( |     let aliases = sqlx::query_as!( | ||||||
|         Alias, |         Alias, | ||||||
|         "SELECT name, command FROM command_aliases WHERE guild_id = (SELECT id FROM guilds WHERE guild = ?)", |         "SELECT name, command FROM command_aliases WHERE guild_id = ?", | ||||||
|         guild_id.0 |         guild_id.0 | ||||||
|     ) |     ) | ||||||
|     .fetch_all(&mut transaction) |     .fetch_all(&mut transaction) | ||||||
| @@ -36,7 +36,7 @@ pub async fn migrate_macro(ctx: Context<'_>) -> Result<(), Error> { | |||||||
|         match parse_text_command(guild_id, alias.name, &alias.command) { |         match parse_text_command(guild_id, alias.name, &alias.command) { | ||||||
|             Some(cmd_macro) => { |             Some(cmd_macro) => { | ||||||
|                 sqlx::query!( |                 sqlx::query!( | ||||||
|                     "INSERT INTO macro (guild_id, name, description, commands) VALUES ((SELECT id FROM guilds WHERE guild = ?), ?, ?, ?)", |                     "INSERT INTO macro (guild_id, name, description, commands) VALUES (?, ?, ?, ?)", | ||||||
|                     cmd_macro.guild_id.0, |                     cmd_macro.guild_id.0, | ||||||
|                     cmd_macro.name, |                     cmd_macro.name, | ||||||
|                     cmd_macro.description, |                     cmd_macro.description, | ||||||
|   | |||||||
| @@ -31,7 +31,7 @@ pub async fn record_macro( | |||||||
|  |  | ||||||
|     let row = sqlx::query!( |     let row = sqlx::query!( | ||||||
|         " |         " | ||||||
| SELECT 1 as _e FROM macro WHERE guild_id = (SELECT id FROM guilds WHERE guild = ?) AND name = ?", | SELECT 1 as _e FROM macro WHERE guild_id = ? AND name = ?", | ||||||
|         guild_id.0, |         guild_id.0, | ||||||
|         name |         name | ||||||
|     ) |     ) | ||||||
| @@ -121,7 +121,7 @@ pub async fn finish_macro(ctx: Context<'_>) -> Result<(), Error> { | |||||||
|             let json = serde_json::to_string(&command_macro.commands).unwrap(); |             let json = serde_json::to_string(&command_macro.commands).unwrap(); | ||||||
|  |  | ||||||
|             sqlx::query!( |             sqlx::query!( | ||||||
|                 "INSERT INTO macro (guild_id, name, description, commands) VALUES ((SELECT id FROM guilds WHERE guild = ?), ?, ?, ?)", |                 "INSERT INTO macro (guild_id, name, description, commands) VALUES (?, ?, ?, ?)", | ||||||
|                 command_macro.guild_id.0, |                 command_macro.guild_id.0, | ||||||
|                 command_macro.name, |                 command_macro.name, | ||||||
|                 command_macro.description, |                 command_macro.description, | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ use chrono::offset::Utc; | |||||||
| use chrono_tz::{Tz, TZ_VARIANTS}; | use chrono_tz::{Tz, TZ_VARIANTS}; | ||||||
| use levenshtein::levenshtein; | use levenshtein::levenshtein; | ||||||
| use log::warn; | use log::warn; | ||||||
|  | use poise::serenity_prelude::{ChannelId, Mentionable}; | ||||||
|  |  | ||||||
| use super::autocomplete::timezone_autocomplete; | use super::autocomplete::timezone_autocomplete; | ||||||
| use crate::{consts::THEME_COLOR, models::CtxData, Context, Error}; | use crate::{consts::THEME_COLOR, models::CtxData, Context, Error}; | ||||||
| @@ -148,11 +149,51 @@ pub async fn unset_allowed_dm(ctx: Context<'_>) -> Result<(), Error> { | |||||||
|     Ok(()) |     Ok(()) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /// Set defaults for commands | ||||||
|  | #[poise::command( | ||||||
|  |     slash_command, | ||||||
|  |     identifying_name = "default", | ||||||
|  |     default_member_permissions = "MANAGE_GUILD" | ||||||
|  | )] | ||||||
|  | pub async fn default(_ctx: Context<'_>) -> Result<(), Error> { | ||||||
|  |     Ok(()) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /// Set a default channel for reminders to be sent to | ||||||
|  | #[poise::command( | ||||||
|  |     slash_command, | ||||||
|  |     guild_only = true, | ||||||
|  |     identifying_name = "default_channel", | ||||||
|  |     default_member_permissions = "MANAGE_GUILD" | ||||||
|  | )] | ||||||
|  | pub async fn default_channel( | ||||||
|  |     ctx: Context<'_>, | ||||||
|  |     #[description = "Channel to send reminders to by default"] channel: Option<ChannelId>, | ||||||
|  | ) -> Result<(), Error> { | ||||||
|  |     if let Some(mut guild_data) = ctx.guild_data().await { | ||||||
|  |         guild_data.default_channel = channel.map(|c| c.0); | ||||||
|  |  | ||||||
|  |         guild_data.commit_changes(&ctx.data().database).await?; | ||||||
|  |  | ||||||
|  |         if let Some(channel) = channel { | ||||||
|  |             ctx.send(|r| { | ||||||
|  |                 r.ephemeral(true).content(format!("Default channel set to {}", channel.mention())) | ||||||
|  |             }) | ||||||
|  |             .await?; | ||||||
|  |         } else { | ||||||
|  |             ctx.send(|r| r.ephemeral(true).content("Default channel unset.")).await?; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     Ok(()) | ||||||
|  | } | ||||||
|  |  | ||||||
| /// View the webhook being used to send reminders to this channel | /// View the webhook being used to send reminders to this channel | ||||||
| #[poise::command( | #[poise::command( | ||||||
|     slash_command, |     slash_command, | ||||||
|     identifying_name = "webhook_url", |     identifying_name = "webhook_url", | ||||||
|     required_permissions = "ADMINISTRATOR" |     required_permissions = "ADMINISTRATOR", | ||||||
|  |     default_member_permissions = "ADMINISTRATOR" | ||||||
| )] | )] | ||||||
| pub async fn webhook(ctx: Context<'_>) -> Result<(), Error> { | pub async fn webhook(ctx: Context<'_>) -> Result<(), Error> { | ||||||
|     match ctx.channel_data().await { |     match ctx.channel_data().await { | ||||||
|   | |||||||
| @@ -653,7 +653,9 @@ async fn create_reminder( | |||||||
|                 let list = channels.map(|arg| parse_mention_list(&arg)).unwrap_or_default(); |                 let list = channels.map(|arg| parse_mention_list(&arg)).unwrap_or_default(); | ||||||
|  |  | ||||||
|                 if list.is_empty() { |                 if list.is_empty() { | ||||||
|                     if ctx.guild_id().is_some() { |                     if let Some(channel_id) = ctx.default_channel().await { | ||||||
|  |                         vec![ReminderScope::Channel(channel_id.0)] | ||||||
|  |                     } else if ctx.guild_id().is_some() { | ||||||
|                         vec![ReminderScope::Channel(ctx.channel_id().0)] |                         vec![ReminderScope::Channel(ctx.channel_id().0)] | ||||||
|                     } else { |                     } else { | ||||||
|                         vec![ReminderScope::User(ctx.author().id.0)] |                         vec![ReminderScope::User(ctx.author().id.0)] | ||||||
|   | |||||||
| @@ -47,7 +47,7 @@ pub async fn todo_guild_add( | |||||||
| ) -> Result<(), Error> { | ) -> Result<(), Error> { | ||||||
|     sqlx::query!( |     sqlx::query!( | ||||||
|         "INSERT INTO todos (guild_id, value) |         "INSERT INTO todos (guild_id, value) | ||||||
| VALUES ((SELECT id FROM guilds WHERE guild = ?), ?)", | VALUES (?, ?)", | ||||||
|         ctx.guild_id().unwrap().0, |         ctx.guild_id().unwrap().0, | ||||||
|         task |         task | ||||||
|     ) |     ) | ||||||
| @@ -70,9 +70,7 @@ VALUES ((SELECT id FROM guilds WHERE guild = ?), ?)", | |||||||
| )] | )] | ||||||
| pub async fn todo_guild_view(ctx: Context<'_>) -> Result<(), Error> { | pub async fn todo_guild_view(ctx: Context<'_>) -> Result<(), Error> { | ||||||
|     let values = sqlx::query!( |     let values = sqlx::query!( | ||||||
|         "SELECT todos.id, value FROM todos |         "SELECT todos.id, value FROM todos WHERE guild_id = ?", | ||||||
| INNER JOIN guilds ON todos.guild_id = guilds.id |  | ||||||
| WHERE guilds.guild = ?", |  | ||||||
|         ctx.guild_id().unwrap().0, |         ctx.guild_id().unwrap().0, | ||||||
|     ) |     ) | ||||||
|     .fetch_all(&ctx.data().database) |     .fetch_all(&ctx.data().database) | ||||||
| @@ -122,7 +120,7 @@ pub async fn todo_channel_add( | |||||||
|  |  | ||||||
|     sqlx::query!( |     sqlx::query!( | ||||||
|         "INSERT INTO todos (guild_id, channel_id, value) |         "INSERT INTO todos (guild_id, channel_id, value) | ||||||
| VALUES ((SELECT id FROM guilds WHERE guild = ?), (SELECT id FROM channels WHERE channel = ?), ?)", | VALUES (?, (SELECT id FROM channels WHERE channel = ?), ?)", | ||||||
|         ctx.guild_id().unwrap().0, |         ctx.guild_id().unwrap().0, | ||||||
|         ctx.channel_id().0, |         ctx.channel_id().0, | ||||||
|         task |         task | ||||||
|   | |||||||
| @@ -222,9 +222,7 @@ WHERE channels.channel = ?", | |||||||
|                         .collect::<Vec<(usize, String)>>() |                         .collect::<Vec<(usize, String)>>() | ||||||
|                     } else { |                     } else { | ||||||
|                         sqlx::query!( |                         sqlx::query!( | ||||||
|                             "SELECT todos.id, value FROM todos |                             "SELECT todos.id, value FROM todos WHERE guild_id = ?", | ||||||
| INNER JOIN guilds ON todos.guild_id = guilds.id |  | ||||||
| WHERE guilds.guild = ?", |  | ||||||
|                             pager.guild_id, |                             pager.guild_id, | ||||||
|                         ) |                         ) | ||||||
|                         .fetch_all(&data.database) |                         .fetch_all(&data.database) | ||||||
|   | |||||||
| @@ -6,7 +6,9 @@ use poise::{ | |||||||
|     serenity_prelude::{model::application::interaction::Interaction, utils::shard_id}, |     serenity_prelude::{model::application::interaction::Interaction, utils::shard_id}, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| use crate::{component_models::ComponentDataModel, Data, Error, THEME_COLOR}; | use crate::{ | ||||||
|  |     component_models::ComponentDataModel, models::guild_data::GuildData, Data, Error, THEME_COLOR, | ||||||
|  | }; | ||||||
|  |  | ||||||
| pub async fn listener( | pub async fn listener( | ||||||
|     ctx: &serenity::Context, |     ctx: &serenity::Context, | ||||||
| @@ -27,7 +29,7 @@ pub async fn listener( | |||||||
|             if *is_new { |             if *is_new { | ||||||
|                 let guild_id = guild.id.as_u64().to_owned(); |                 let guild_id = guild.id.as_u64().to_owned(); | ||||||
|  |  | ||||||
|                 sqlx::query!("INSERT IGNORE INTO guilds (guild) VALUES (?)", guild_id) |                 sqlx::query!("INSERT IGNORE INTO guilds (id) VALUES (?)", guild_id) | ||||||
|                     .execute(&data.database) |                     .execute(&data.database) | ||||||
|                     .await?; |                     .await?; | ||||||
|  |  | ||||||
| @@ -61,16 +63,28 @@ To stay up to date on the latest features and fixes, join our [Discord](https:// | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         poise::Event::GuildDelete { incomplete, .. } => { |         poise::Event::GuildDelete { incomplete, .. } => { | ||||||
|             let _ = sqlx::query!("DELETE FROM guilds WHERE guild = ?", incomplete.id.0) |             let _ = sqlx::query!("DELETE FROM guilds WHERE id = ?", incomplete.id.0) | ||||||
|                 .execute(&data.database) |                 .execute(&data.database) | ||||||
|                 .await; |                 .await; | ||||||
|         } |         } | ||||||
|         poise::Event::InteractionCreate { interaction } => { |         poise::Event::InteractionCreate { interaction } => { | ||||||
|             if let Interaction::MessageComponent(component) = interaction { |             match interaction { | ||||||
|                 let component_model = ComponentDataModel::from_custom_id(&component.data.custom_id); |                 Interaction::ApplicationCommand(app_command) => { | ||||||
|  |                     if let Some(guild_id) = app_command.guild_id { | ||||||
|  |                         // check database guild exists | ||||||
|  |                         GuildData::from_guild(guild_id, &data.database).await?; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 Interaction::MessageComponent(component) => { | ||||||
|  |                     let component_model = | ||||||
|  |                         ComponentDataModel::from_custom_id(&component.data.custom_id); | ||||||
|  |  | ||||||
|                     component_model.act(ctx, data, component).await; |                     component_model.act(ctx, data, component).await; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  |                 _ => {} | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         _ => {} |         _ => {} | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -120,6 +120,10 @@ async fn _main(tx: Sender<()>) -> Result<(), Box<dyn StdError + Send + Sync>> { | |||||||
|                 ], |                 ], | ||||||
|                 ..command_macro::macro_base() |                 ..command_macro::macro_base() | ||||||
|             }, |             }, | ||||||
|  |             poise::Command { | ||||||
|  |                 subcommands: vec![moderation_cmds::default_channel()], | ||||||
|  |                 ..moderation_cmds::default() | ||||||
|  |             }, | ||||||
|             reminder_cmds::pause(), |             reminder_cmds::pause(), | ||||||
|             reminder_cmds::offset(), |             reminder_cmds::offset(), | ||||||
|             reminder_cmds::nudge(), |             reminder_cmds::nudge(), | ||||||
|   | |||||||
| @@ -38,7 +38,7 @@ SELECT id, name, nudge, blacklisted, webhook_id, webhook_token, paused, paused_u | |||||||
|  |  | ||||||
|             sqlx::query!( |             sqlx::query!( | ||||||
|                 " |                 " | ||||||
| INSERT IGNORE INTO channels (channel, name, guild_id) VALUES (?, ?, (SELECT id FROM guilds WHERE guild = ?)) | INSERT IGNORE INTO channels (channel, name, guild_id) VALUES (?, ?, ?) | ||||||
|                 ", |                 ", | ||||||
|                 channel_id, |                 channel_id, | ||||||
|                 channel_name, |                 channel_name, | ||||||
|   | |||||||
| @@ -43,7 +43,7 @@ pub async fn guild_command_macro( | |||||||
| ) -> Option<CommandMacro<Data, Error>> { | ) -> Option<CommandMacro<Data, Error>> { | ||||||
|     let row = sqlx::query!( |     let row = sqlx::query!( | ||||||
|         " |         " | ||||||
| SELECT * FROM macro WHERE guild_id = (SELECT id FROM guilds WHERE guild = ?) AND name = ? | SELECT * FROM macro WHERE guild_id = ? AND name = ? | ||||||
|         ", |         ", | ||||||
|         ctx.guild_id().unwrap().0, |         ctx.guild_id().unwrap().0, | ||||||
|         name |         name | ||||||
|   | |||||||
							
								
								
									
										52
									
								
								src/models/guild_data.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/models/guild_data.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | |||||||
|  | use sqlx::MySqlPool; | ||||||
|  |  | ||||||
|  | use crate::GuildId; | ||||||
|  |  | ||||||
|  | pub struct GuildData { | ||||||
|  |     pub id: u64, | ||||||
|  |     pub default_channel: Option<u64>, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl GuildData { | ||||||
|  |     pub async fn from_guild(guild: GuildId, pool: &MySqlPool) -> Result<Self, sqlx::Error> { | ||||||
|  |         let guild_id = guild.0; | ||||||
|  |  | ||||||
|  |         if let Ok(row) = sqlx::query_as_unchecked!( | ||||||
|  |             Self, | ||||||
|  |             " | ||||||
|  | SELECT id, default_channel FROM guilds WHERE id = ? | ||||||
|  |             ", | ||||||
|  |             guild_id | ||||||
|  |         ) | ||||||
|  |         .fetch_one(pool) | ||||||
|  |         .await | ||||||
|  |         { | ||||||
|  |             Ok(row) | ||||||
|  |         } else { | ||||||
|  |             sqlx::query!( | ||||||
|  |                 " | ||||||
|  | INSERT IGNORE INTO guilds (id) VALUES (?) | ||||||
|  |                 ", | ||||||
|  |                 guild_id | ||||||
|  |             ) | ||||||
|  |             .execute(&pool.clone()) | ||||||
|  |             .await?; | ||||||
|  |  | ||||||
|  |             Ok(Self { id: guild_id, default_channel: None }) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     pub async fn commit_changes(&self, pool: &MySqlPool) -> Result<(), sqlx::Error> { | ||||||
|  |         sqlx::query!( | ||||||
|  |             " | ||||||
|  | UPDATE guilds SET default_channel = ? WHERE id = ? | ||||||
|  |             ", | ||||||
|  |             self.default_channel, | ||||||
|  |             self.id | ||||||
|  |         ) | ||||||
|  |         .execute(pool) | ||||||
|  |         .await?; | ||||||
|  |  | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,28 +1,28 @@ | |||||||
| pub mod channel_data; | pub mod channel_data; | ||||||
| pub mod command_macro; | pub mod command_macro; | ||||||
|  | pub mod guild_data; | ||||||
| pub mod reminder; | pub mod reminder; | ||||||
| pub mod timer; | pub mod timer; | ||||||
| pub mod user_data; | pub mod user_data; | ||||||
|  |  | ||||||
| use chrono_tz::Tz; | use chrono_tz::Tz; | ||||||
| use poise::serenity_prelude::{async_trait, model::id::UserId}; | use log::warn; | ||||||
|  | use poise::serenity_prelude::{async_trait, model::id::UserId, ChannelId}; | ||||||
|  |  | ||||||
| use crate::{ | use crate::{ | ||||||
|     models::{channel_data::ChannelData, user_data::UserData}, |     models::{channel_data::ChannelData, guild_data::GuildData, user_data::UserData}, | ||||||
|     CommandMacro, Context, Data, Error, GuildId, |     CommandMacro, Context, Data, Error, GuildId, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #[async_trait] | #[async_trait] | ||||||
| pub trait CtxData { | pub trait CtxData { | ||||||
|     async fn user_data<U: Into<UserId> + Send>(&self, user_id: U) -> Result<UserData, Error>; |     async fn user_data<U: Into<UserId> + Send>(&self, user_id: U) -> Result<UserData, Error>; | ||||||
|  |  | ||||||
|     async fn author_data(&self) -> Result<UserData, Error>; |     async fn author_data(&self) -> Result<UserData, Error>; | ||||||
|  |  | ||||||
|     async fn timezone(&self) -> Tz; |     async fn timezone(&self) -> Tz; | ||||||
|  |  | ||||||
|     async fn channel_data(&self) -> Result<ChannelData, Error>; |     async fn channel_data(&self) -> Result<ChannelData, Error>; | ||||||
|  |     async fn guild_data(&self) -> Option<GuildData>; | ||||||
|     async fn command_macros(&self) -> Result<Vec<CommandMacro<Data, Error>>, Error>; |     async fn command_macros(&self) -> Result<Vec<CommandMacro<Data, Error>>, Error>; | ||||||
|  |     async fn default_channel(&self) -> Option<ChannelId>; | ||||||
| } | } | ||||||
|  |  | ||||||
| #[async_trait] | #[async_trait] | ||||||
| @@ -51,24 +51,55 @@ impl CtxData for Context<'_> { | |||||||
|     async fn command_macros(&self) -> Result<Vec<CommandMacro<Data, Error>>, Error> { |     async fn command_macros(&self) -> Result<Vec<CommandMacro<Data, Error>>, Error> { | ||||||
|         self.data().command_macros(self.guild_id().unwrap()).await |         self.data().command_macros(self.guild_id().unwrap()).await | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     async fn default_channel(&self) -> Option<ChannelId> { | ||||||
|  |         match self.guild_id() { | ||||||
|  |             Some(guild_id) => { | ||||||
|  |                 let guild_data = GuildData::from_guild(guild_id, &self.data().database).await; | ||||||
|  |  | ||||||
|  |                 match guild_data { | ||||||
|  |                     Ok(data) => data.default_channel.map(|c| ChannelId(c)), | ||||||
|  |  | ||||||
|  |                     Err(e) => { | ||||||
|  |                         warn!("SQL error: {:?}", e); | ||||||
|  |  | ||||||
|  |                         None | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             None => None, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     async fn guild_data(&self) -> Option<GuildData> { | ||||||
|  |         match self.guild_id() { | ||||||
|  |             Some(guild_id) => GuildData::from_guild(guild_id, &self.data().database).await.ok(), | ||||||
|  |  | ||||||
|  |             None => None, | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl Data { | impl Data { | ||||||
|     pub(crate) async fn command_macros( |     pub async fn command_macros( | ||||||
|         &self, |         &self, | ||||||
|         guild_id: GuildId, |         guild_id: GuildId, | ||||||
|     ) -> Result<Vec<CommandMacro<Data, Error>>, Error> { |     ) -> Result<Vec<CommandMacro<Data, Error>>, Error> { | ||||||
|         let rows = sqlx::query!( |         let rows = sqlx::query!( | ||||||
|             "SELECT name, description, commands FROM macro WHERE guild_id = (SELECT id FROM guilds WHERE guild = ?)", |             "SELECT name, description, commands FROM macro WHERE guild_id = ?", | ||||||
|             guild_id.0 |             guild_id.0 | ||||||
|         ) |         ) | ||||||
|         .fetch_all(&self.database) |         .fetch_all(&self.database) | ||||||
|         .await?.iter().map(|row| CommandMacro { |         .await? | ||||||
|  |         .iter() | ||||||
|  |         .map(|row| CommandMacro { | ||||||
|             guild_id, |             guild_id, | ||||||
|             name: row.name.clone(), |             name: row.name.clone(), | ||||||
|             description: row.description.clone(), |             description: row.description.clone(), | ||||||
|             commands: serde_json::from_str(&row.commands).unwrap(), |             commands: serde_json::from_str(&row.commands).unwrap(), | ||||||
|         }).collect(); |         }) | ||||||
|  |         .collect(); | ||||||
|  |  | ||||||
|         Ok(rows) |         Ok(rows) | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -245,7 +245,7 @@ LEFT JOIN | |||||||
| ON | ON | ||||||
|     reminders.set_by = users.id |     reminders.set_by = users.id | ||||||
| WHERE | WHERE | ||||||
|     channels.guild_id = (SELECT id FROM guilds WHERE guild = ?) |     channels.guild_id = ? | ||||||
|                 ", |                 ", | ||||||
|                     guild_id.as_u64() |                     guild_id.as_u64() | ||||||
|                 ) |                 ) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user