From ce026fc2226bd5d84030cd4f5eafa88390495877 Mon Sep 17 00:00:00 2001 From: Marek 'seqre' Grzelak Date: Sat, 28 Oct 2023 19:17:49 -0500 Subject: [PATCH 1/4] [misc] add script to simplify Diesel migrations --- dsl.sh | 3 +++ 1 file changed, 3 insertions(+) create mode 100755 dsl.sh diff --git a/dsl.sh b/dsl.sh new file mode 100755 index 0000000..04a919e --- /dev/null +++ b/dsl.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +diesel --database-url "db.sqlite" migration --migration-dir migrations/sqlite "$@" \ No newline at end of file From 5156be94fef31cc13cc2e9679295dae28e80511e Mon Sep 17 00:00:00 2001 From: Marek 'seqre' Grzelak Date: Sun, 7 Jan 2024 17:20:22 -0600 Subject: [PATCH 2/4] [feat] initial HoF implementation --- .../down.sql | 4 + .../2023-11-07-004602_add_hall_of_fame/up.sql | 24 ++ src/commands/hall_of_fame.rs | 205 ++++++++++++++++++ src/commands/mod.rs | 1 + src/ctx_data.rs | 5 +- src/main.rs | 3 +- src/models/hall_of_fame.rs | 41 ++++ src/models/mod.rs | 1 + src/schema.rs | 6 +- 9 files changed, 287 insertions(+), 3 deletions(-) create mode 100644 migrations/sqlite/2023-11-07-004602_add_hall_of_fame/down.sql create mode 100644 migrations/sqlite/2023-11-07-004602_add_hall_of_fame/up.sql create mode 100644 src/commands/hall_of_fame.rs create mode 100644 src/models/hall_of_fame.rs diff --git a/migrations/sqlite/2023-11-07-004602_add_hall_of_fame/down.sql b/migrations/sqlite/2023-11-07-004602_add_hall_of_fame/down.sql new file mode 100644 index 0000000..8e7191a --- /dev/null +++ b/migrations/sqlite/2023-11-07-004602_add_hall_of_fame/down.sql @@ -0,0 +1,4 @@ +-- This file should undo anything in `up.sql` + +DROP TABLE IF EXISTS "hall_of_fame_entries"; +DROP TABLE IF EXISTS "hall_of_fame_tables"; \ No newline at end of file diff --git a/migrations/sqlite/2023-11-07-004602_add_hall_of_fame/up.sql b/migrations/sqlite/2023-11-07-004602_add_hall_of_fame/up.sql new file mode 100644 index 0000000..5fe472f --- /dev/null +++ b/migrations/sqlite/2023-11-07-004602_add_hall_of_fame/up.sql @@ -0,0 +1,24 @@ +-- Your SQL goes here + +CREATE TABLE IF NOT EXISTS "hall_of_fame_tables" +( + "id" INTEGER PRIMARY KEY NOT NULL, + "guild_id" BIGINT NOT NULL, + "title" TEXT NOT NULL, + "description" TEXT, + "creation_date" TEXT NOT NULL, + + UNIQUE ("guild_id", "title") +); + +CREATE TABLE IF NOT EXISTS "hall_of_fame_entries" +( + "id" INTEGER PRIMARY KEY NOT NULL, + "hof_id" INTEGER NOT NULL, + "user_id" BIGINT NOT NULL, + "description" TEXT, + "creation_date" TEXT NOT NULL, + + FOREIGN KEY ("hof_id") REFERENCES "hall_of_fame_tables" ("id") ON DELETE CASCADE +); + diff --git a/src/commands/hall_of_fame.rs b/src/commands/hall_of_fame.rs new file mode 100644 index 0000000..69f8c02 --- /dev/null +++ b/src/commands/hall_of_fame.rs @@ -0,0 +1,205 @@ +use std::{ + collections::{HashMap, HashSet}, + sync::Arc, +}; + +use diesel::{prelude::*, ExpressionMethods}; +use itertools::Itertools; +use poise::serenity_prelude::{GuildId, User}; +use time::OffsetDateTime; +use tokio::sync::RwLock; +use tracing::{debug, info}; + +use crate::{ + ctx_data::CtxData, + models::hall_of_fame::{NewEntry, NewTable, Table}, + Conn, Context, Error, Result, +}; + +#[derive(Debug)] +pub struct HofData { + hofs: RwLock>>, +} + +impl HofData { + pub async fn add_table(&self, guild_id: GuildId, table: String) { + self.hofs + .write() + .await + .entry(guild_id) + .and_modify(|hofs| { + hofs.insert(table); + }) + .or_default(); + } + + pub async fn get_hof_tables(&self, guild_id: &GuildId) -> HashSet { + // TODO: allow dirty read + self.hofs + .read() + .await + .get(&guild_id) + .map(|h| h.clone()) + .unwrap_or_default() + } +} + +impl HofData { + pub fn new(db: &Conn) -> Self { + use crate::schema::hall_of_fame_tables::dsl::*; + + let hofs = hall_of_fame_tables + .load::(&mut db.get().unwrap()) + .unwrap(); + + let hofs = hofs + .into_iter() + .group_by(|h| h.guild_id) + .into_iter() + .map(|(grp, hfs)| (GuildId(grp as u64), hfs.map(|h| h.title).collect())) + .collect(); + + Self { + hofs: RwLock::new(hofs), + } + } +} + +#[allow(clippy::unused_async)] +#[poise::command(slash_command, subcommands("show", "create", "add"))] +pub async fn hof(_ctx: Context<'_>) -> Result<()> { + Ok(()) +} + +async fn autocomplete<'a>(ctx: Context<'_>, partial: &'a str) -> HashSet { + let guild = ctx.guild_id().unwrap(); + + ctx.data() + .hof_data + .get_hof_tables(&guild) + .await + .into_iter() + .filter(|h| h.starts_with(partial)) + .collect() +} + +/// List Hall of Fame tables +#[poise::command(slash_command)] +pub async fn show(ctx: Context<'_>, #[autocomplete = "autocomplete"] hof: String) -> Result<()> { + use crate::{ + models::hall_of_fame::Entry, + schema::{hall_of_fame_entries::dsl::*, hall_of_fame_tables::dsl::*}, + }; + + let guild = ctx.guild_id().unwrap(); + + let hof = hall_of_fame_tables + .filter(guild_id.eq::(guild.into())) + .filter(title.eq(&hof)) + .first::
(&mut ctx.data().db.get().unwrap())?; + + debug!("{:#?}", hof); + + ctx.reply(format!("{:?}", hof)).await?; + // TODO: embed + + let entries = hall_of_fame_entries + .filter(hof_id.eq(hof.id)) + .load::(&mut ctx.data().db.get().unwrap())?; + + ctx.reply(format!("entries: {:?}", entries)).await?; + + Ok(()) +} + +#[derive(Debug, poise::Modal)] +#[name = "Create Hall of Fame table"] +struct HofCreationModal { + #[min_length = 5] + #[max_length = 100] + title: String, + #[paragraph] + #[max_length = 500] + description: Option, +} + +#[poise::command(slash_command)] +pub async fn create(ctx: poise::ApplicationContext<'_, Arc, Error>) -> Result<()> { + use poise::Modal as _; + + use crate::schema::hall_of_fame_tables::dsl::*; + + let data = HofCreationModal::execute(ctx).await?; + + if let Some(data) = data { + let guild = ctx.guild_id().unwrap(); + // let time = OffsetDateTime::now_utc() + // .format(&TIME_FORMAT.get().unwrap()) + // .unwrap(); + + let new_hof = NewTable { + guild_id: &(guild.0 as i64), + title: &data.title, + description: data.description, + creation_date: &"", // TODO: fix + }; + + let result = diesel::insert_into(hall_of_fame_tables) + .values(&new_hof) + .execute(&mut ctx.data().db.get().unwrap()); + + let response = match result { + Ok(_) => { + ctx.data.hof_data.add_table(guild, data.title).await; + "Success" + } + _ => "Failure", + }; + + ctx.reply(response).await?; + } + + return Ok(()); +} + +#[poise::command(slash_command)] +pub async fn add( + ctx: Context<'_>, + #[autocomplete = "autocomplete"] hof: String, + user: User, + reason: String, +) -> Result<()> { + use crate::schema::{hall_of_fame_entries::dsl::*, hall_of_fame_tables::dsl::*}; + let guild = ctx.guild_id().unwrap(); + + debug!("u:{user} r:{reason}"); + + if reason.len() > 256 { + ctx.reply( + "Reason is too long, it can be 256 characters long at +most.", + ) + .await?; + return Ok(()); + } + + let hof = hall_of_fame_tables + .filter(guild_id.eq::(guild.into())) + .filter(title.eq(&hof)) + .first::
(&mut ctx.data().db.get().unwrap())?; + + let new_entry = NewEntry { + hof_id: &hof.id, + user_id: &(user.id.0 as i64), + description: Some(&reason), + creation_date: &"", + }; + + let result = diesel::insert_into(hall_of_fame_entries) + .values(&new_entry) + .execute(&mut ctx.data().db.get().unwrap()); + + debug!("{:?}", result); + + Ok(()) +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 424a36b..b83f1ff 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -5,6 +5,7 @@ use regex::Regex; use crate::{Context, Result}; pub mod changelog; +pub mod hall_of_fame; pub mod ping; #[allow(clippy::cast_precision_loss)] diff --git a/src/ctx_data.rs b/src/ctx_data.rs index 27a9780..4a437cb 100644 --- a/src/ctx_data.rs +++ b/src/ctx_data.rs @@ -1,5 +1,5 @@ use crate::{ - commands::{ping::PingData, todo::TodoData}, + commands::{hall_of_fame::HofData, ping::PingData, todo::TodoData}, settings::Settings, Conn, }; @@ -9,16 +9,19 @@ pub struct CtxData { pub db: Conn, pub ping_data: PingData, pub todo_data: TodoData, + pub hof_data: HofData, pub settings: Settings, } impl CtxData { pub fn new(db: Conn, settings: Settings) -> Self { let todo_data = TodoData::new(&db); + let hof_data = HofData::new(&db); Self { db, ping_data: PingData::new(), todo_data, + hof_data, settings, } } diff --git a/src/main.rs b/src/main.rs index 44656a9..3418031 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,7 @@ use poise::serenity_prelude as serenity; use tracing::{debug, error, info}; use crate::{ - commands::{changelog, ping, todo}, + commands::{changelog, hall_of_fame, ping, todo}, ctx_data::CtxData, settings::Settings, }; @@ -98,6 +98,7 @@ async fn main() { changelog::version(), ping::ping(), todo::todo(), + hall_of_fame::hof(), ], event_handler: |ctx, event, framework, data| { Box::pin(framework::event_handler(ctx, event, framework, data)) diff --git a/src/models/hall_of_fame.rs b/src/models/hall_of_fame.rs new file mode 100644 index 0000000..fb64573 --- /dev/null +++ b/src/models/hall_of_fame.rs @@ -0,0 +1,41 @@ +use diesel::{Insertable, Queryable}; + +use crate::schema::{hall_of_fame_entries, hall_of_fame_tables}; + +#[derive(Queryable, Debug)] +#[diesel(check_for_backend(diesel::sqlite::Sqlite))] +pub struct Table { + pub id: i32, + pub guild_id: i64, + pub title: String, + pub description: Option, + pub creation_date: String, +} + +#[derive(Queryable, Debug)] +#[diesel(check_for_backend(diesel::sqlite::Sqlite))] +pub struct Entry { + pub id: i32, + pub hof_id: i32, + pub user_id: i64, + pub description: Option, + pub creation_date: String, +} + +#[derive(Insertable)] +#[diesel(table_name = hall_of_fame_tables)] +pub struct NewTable<'a> { + pub guild_id: &'a i64, + pub title: &'a str, + pub description: Option, + pub creation_date: &'a str, +} + +#[derive(Insertable)] +#[diesel(table_name = hall_of_fame_entries)] +pub struct NewEntry<'a> { + pub hof_id: &'a i32, + pub user_id: &'a i64, + pub description: Option<&'a str>, + pub creation_date: &'a str, +} diff --git a/src/models/mod.rs b/src/models/mod.rs index ff6eb8e..31a49e5 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -1 +1,2 @@ +pub mod hall_of_fame; pub mod todo; diff --git a/src/schema.rs b/src/schema.rs index 2940481..6323d5b 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -34,4 +34,8 @@ diesel::table! { diesel::joinable!(hall_of_fame_entries -> hall_of_fame_tables (hof_id)); -diesel::allow_tables_to_appear_in_same_query!(hall_of_fame_entries, hall_of_fame_tables, todos,); +diesel::allow_tables_to_appear_in_same_query!( + hall_of_fame_entries, + hall_of_fame_tables, + todos, +); From aff7a4e62104cb8f93f8e5511f46018f75b31cc7 Mon Sep 17 00:00:00 2001 From: Marek 'seqre' Grzelak Date: Mon, 15 Jan 2024 22:17:46 -0600 Subject: [PATCH 3/4] [feat] improvement in HoF implementation --- src/commands/hall_of_fame.rs | 168 ++++++++++++++++++++++++++--------- src/commands/mod.rs | 6 +- src/commands/todo.rs | 16 +--- src/schema.rs | 6 +- 4 files changed, 134 insertions(+), 62 deletions(-) diff --git a/src/commands/hall_of_fame.rs b/src/commands/hall_of_fame.rs index 69f8c02..9134959 100644 --- a/src/commands/hall_of_fame.rs +++ b/src/commands/hall_of_fame.rs @@ -5,14 +5,14 @@ use std::{ use diesel::{prelude::*, ExpressionMethods}; use itertools::Itertools; -use poise::serenity_prelude::{GuildId, User}; +use poise::serenity_prelude::{GuildId, MessageBuilder, User, UserId}; use time::OffsetDateTime; use tokio::sync::RwLock; -use tracing::{debug, info}; use crate::{ + commands::{DISCORD_EMBED_FIELDS_LIMIT, TIME_FORMAT}, ctx_data::CtxData, - models::hall_of_fame::{NewEntry, NewTable, Table}, + models::hall_of_fame::{Entry, NewEntry, NewTable, Table}, Conn, Context, Error, Result, }; @@ -23,14 +23,8 @@ pub struct HofData { impl HofData { pub async fn add_table(&self, guild_id: GuildId, table: String) { - self.hofs - .write() - .await - .entry(guild_id) - .and_modify(|hofs| { - hofs.insert(table); - }) - .or_default(); + let mut hofs = self.hofs.write().await; + hofs.entry(guild_id).or_default().insert(table); } pub async fn get_hof_tables(&self, guild_id: &GuildId) -> HashSet { @@ -80,46 +74,125 @@ async fn autocomplete<'a>(ctx: Context<'_>, partial: &'a str) -> HashSet .await .into_iter() .filter(|h| h.starts_with(partial)) + .sorted() .collect() } /// List Hall of Fame tables #[poise::command(slash_command)] -pub async fn show(ctx: Context<'_>, #[autocomplete = "autocomplete"] hof: String) -> Result<()> { - use crate::{ - models::hall_of_fame::Entry, - schema::{hall_of_fame_entries::dsl::*, hall_of_fame_tables::dsl::*}, +pub async fn show( + ctx: Context<'_>, + #[autocomplete = "autocomplete"] hof: String, + user: Option, +) -> Result<()> { + let guild = ctx.guild_id().unwrap(); + + match user { + None => show_hof(ctx, guild, hof).await?, + Some(user_id) => show_user(ctx, guild, hof, user_id).await?, }; - let guild = ctx.guild_id().unwrap(); + Ok(()) +} + +async fn show_hof(ctx: Context<'_>, guild: GuildId, hof: String) -> Result<()> { + use crate::schema::{hall_of_fame_entries::dsl::*, hall_of_fame_tables::dsl::*}; let hof = hall_of_fame_tables .filter(guild_id.eq::(guild.into())) .filter(title.eq(&hof)) .first::
(&mut ctx.data().db.get().unwrap())?; - debug!("{:#?}", hof); + let entries = hall_of_fame_entries + .filter(hof_id.eq(hof.id)) + .load::(&mut ctx.data().db.get().unwrap())?; - ctx.reply(format!("{:?}", hof)).await?; - // TODO: embed + let entries: Vec<_> = entries + .into_iter() + .counts_by(|e| e.user_id) + .into_iter() + .sorted_by_cached_key(|(_, v)| -(*v as i32)) + .take(DISCORD_EMBED_FIELDS_LIMIT as usize) + .collect(); + + let mut entries2 = vec![]; + for (k, v) in entries.into_iter() { + entries2.push((get_nickname(ctx, &guild, k).await?, v, true)); + } + + let response = ctx + .send(|reply| { + reply.embed(|embed| { + let desc = hof.description.unwrap_or_default(); + let desc = if entries2.is_empty() { + let mix = if desc.is_empty() { "" } else { "\n\n" }; + format!("{}{}{}", desc, mix, "There are no entries.") + } else { + desc + }; + embed.description(desc); + + embed.title(&hof.title).fields(entries2); + + embed + }) + }) + .await?; + Ok(()) +} +async fn show_user(ctx: Context<'_>, guild: GuildId, hof: String, user: User) -> Result<()> { + use crate::schema::{hall_of_fame_entries::dsl::*, hall_of_fame_tables::dsl::*}; + + let hof = hall_of_fame_tables + .filter(guild_id.eq::(guild.into())) + .filter(title.eq(&hof)) + .first::
(&mut ctx.data().db.get().unwrap())?; let entries = hall_of_fame_entries .filter(hof_id.eq(hof.id)) + .filter(user_id.eq(user.id.0 as i64)) .load::(&mut ctx.data().db.get().unwrap())?; - ctx.reply(format!("entries: {:?}", entries)).await?; + let entries: Vec<_> = entries + .into_iter() + .map(|e| { + format!( + "*{}*: {}", + e.creation_date, + e.description.unwrap_or(String::from("Missing reason")) + ) + }) + .collect(); + + let mut msg = MessageBuilder::new(); + msg.push(format!("### {} entries for ", hof.title)) + .mention(&user) + .push_line(""); + + for entry in entries.iter().rev() { + msg.push_line(format!("- {}", entry)); + } + + ctx.reply(msg.build()).await?; Ok(()) } +async fn get_nickname(ctx: Context<'_>, guild_id: &GuildId, id: i64) -> Result { + let userid = UserId(id as u64); + let user = userid.to_user(ctx).await?; + let guild_nick = user.nick_in(ctx, guild_id).await; + Ok(guild_nick.unwrap_or(user.name)) +} + #[derive(Debug, poise::Modal)] #[name = "Create Hall of Fame table"] struct HofCreationModal { - #[min_length = 5] - #[max_length = 100] + #[min_length = 4] + #[max_length = 64] title: String, #[paragraph] - #[max_length = 500] + #[max_length = 128] description: Option, } @@ -133,15 +206,25 @@ pub async fn create(ctx: poise::ApplicationContext<'_, Arc, Error>) -> if let Some(data) = data { let guild = ctx.guild_id().unwrap(); - // let time = OffsetDateTime::now_utc() - // .format(&TIME_FORMAT.get().unwrap()) - // .unwrap(); + let time = OffsetDateTime::now_utc().format(&TIME_FORMAT).unwrap(); + + let desc = match data.description { + Some(s) => { + let desc = s.trim(); + if desc.is_empty() { + None + } else { + Some(desc.to_string()) + } + } + None => None, + }; let new_hof = NewTable { guild_id: &(guild.0 as i64), title: &data.title, - description: data.description, - creation_date: &"", // TODO: fix + description: desc, + creation_date: &time, }; let result = diesel::insert_into(hall_of_fame_tables) @@ -156,7 +239,8 @@ pub async fn create(ctx: poise::ApplicationContext<'_, Arc, Error>) -> _ => "Failure", }; - ctx.reply(response).await?; + ctx.send(|reply| reply.content(response).reply(true).ephemeral(true)) + .await?; } return Ok(()); @@ -167,21 +251,11 @@ pub async fn add( ctx: Context<'_>, #[autocomplete = "autocomplete"] hof: String, user: User, - reason: String, + #[max_length = 128] reason: String, ) -> Result<()> { use crate::schema::{hall_of_fame_entries::dsl::*, hall_of_fame_tables::dsl::*}; let guild = ctx.guild_id().unwrap(); - - debug!("u:{user} r:{reason}"); - - if reason.len() > 256 { - ctx.reply( - "Reason is too long, it can be 256 characters long at -most.", - ) - .await?; - return Ok(()); - } + let time = OffsetDateTime::now_utc().format(&TIME_FORMAT).unwrap(); let hof = hall_of_fame_tables .filter(guild_id.eq::(guild.into())) @@ -192,14 +266,22 @@ most.", hof_id: &hof.id, user_id: &(user.id.0 as i64), description: Some(&reason), - creation_date: &"", + creation_date: &time, }; let result = diesel::insert_into(hall_of_fame_entries) .values(&new_entry) .execute(&mut ctx.data().db.get().unwrap()); - debug!("{:?}", result); + let msg = MessageBuilder::new() + .mention(&user) + .push(" was added to ") + .push_bold(&hof.title) + .push(": ") + .push_italic_safe(&reason) + .build(); + + ctx.reply(msg).await?; Ok(()) } diff --git a/src/commands/mod.rs b/src/commands/mod.rs index b83f1ff..0e824d1 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,6 +1,7 @@ -use std::sync::LazyLock; +use std::sync::{LazyLock, OnceLock}; use regex::Regex; +use time::{format_description, format_description::FormatItem}; use crate::{Context, Result}; @@ -15,6 +16,9 @@ pub mod todo; pub const DISCORD_EMBED_FIELDS_LIMIT: u32 = 24; static USER_PING_REGEX: LazyLock = LazyLock::new(|| Regex::new(r"<@(\d+)>").unwrap()); +static TIME_FORMAT: LazyLock>> = LazyLock::new(|| { + format_description::parse("[year]-[month]-[day] [hour]:[minute]:[second]").unwrap() +}); #[poise::command(track_edits, slash_command)] pub async fn help( diff --git a/src/commands/todo.rs b/src/commands/todo.rs index b0ca103..cda2a9b 100644 --- a/src/commands/todo.rs +++ b/src/commands/todo.rs @@ -29,13 +29,11 @@ use tokio_stream::{self as stream, StreamExt}; use tracing::debug; use crate::{ - commands::DISCORD_EMBED_FIELDS_LIMIT, + commands::{DISCORD_EMBED_FIELDS_LIMIT, TIME_FORMAT}, models::todo::{NewTodo, Todo}, Conn, Context, Result, }; -static TIME_FORMAT: OnceLock>> = OnceLock::new(); - #[derive(Debug, Clone, Copy, Default)] pub enum Priority { #[default] @@ -161,10 +159,6 @@ impl TodoData { }) .collect::>(); - let _ = TIME_FORMAT.set( - format_description::parse("[year]-[month]-[day] [hour]:[minute]:[second]").unwrap(), - ); - Self { iterators: Mutex::new(iterators), } @@ -303,9 +297,7 @@ pub async fn add( let data = if content.len() > 1024 { "Content can't have more than 1024 characters.".to_string() } else { - let time = OffsetDateTime::now_utc() - .format(&TIME_FORMAT.get().unwrap()) - .unwrap(); + let time = OffsetDateTime::now_utc().format(&TIME_FORMAT).unwrap(); let new_id = ctx.data().todo_data.get_id(ctx.channel_id()); let nickname = match &assignee { Some(m) => get_member_nickname(m), @@ -375,9 +367,7 @@ pub async fn delete(ctx: Context<'_>, #[description = "TODO id"] todo_id: i64) - pub async fn complete(ctx: Context<'_>, #[description = "TODO id"] todo_id: i64) -> Result<()> { use crate::schema::todos::dsl::{channel_id, completion_date, id, todo, todos}; - let time = OffsetDateTime::now_utc() - .format(&TIME_FORMAT.get().unwrap()) - .unwrap(); + let time = OffsetDateTime::now_utc().format(&TIME_FORMAT).unwrap(); let completed: QueryResult = diesel::update(todos) .filter(channel_id.eq(i64::from(ctx.channel_id()))) diff --git a/src/schema.rs b/src/schema.rs index 6323d5b..2940481 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -34,8 +34,4 @@ diesel::table! { diesel::joinable!(hall_of_fame_entries -> hall_of_fame_tables (hof_id)); -diesel::allow_tables_to_appear_in_same_query!( - hall_of_fame_entries, - hall_of_fame_tables, - todos, -); +diesel::allow_tables_to_appear_in_same_query!(hall_of_fame_entries, hall_of_fame_tables, todos,); From 7c36d9c255b42d19617e719fe673cc85b5388a76 Mon Sep 17 00:00:00 2001 From: Marek 'seqre' Grzelak Date: Mon, 15 Jan 2024 22:35:43 -0600 Subject: [PATCH 4/4] [chore] clippy --- src/commands/hall_of_fame.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/commands/hall_of_fame.rs b/src/commands/hall_of_fame.rs index 9134959..2c41476 100644 --- a/src/commands/hall_of_fame.rs +++ b/src/commands/hall_of_fame.rs @@ -32,8 +32,8 @@ impl HofData { self.hofs .read() .await - .get(&guild_id) - .map(|h| h.clone()) + .get(guild_id) + .cloned() .unwrap_or_default() } } @@ -243,7 +243,7 @@ pub async fn create(ctx: poise::ApplicationContext<'_, Arc, Error>) -> .await?; } - return Ok(()); + Ok(()) } #[poise::command(slash_command)]