From 327ff99b693c838476e98cbf599c6ed2ee50f2d9 Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Tue, 17 Jun 2025 16:21:15 +0100 Subject: [PATCH 01/37] fix: the pipeline got caught on a lint This isnt in the 1.87 rustfmt but its stilla good catch --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index abf8a2d..734fa2c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -109,7 +109,7 @@ pub fn get_config() -> Config { } } if let Ok(x) = env::var("COMMITTEE_CATEGORY") { - for part in x.split(",") { + for part in x.split(',') { if let Ok(x) = part.trim().parse::() { config.committee_category.push(ChannelId::new(x)); } From 3a56d7bba5fa2ca562ab5288f8799339cdc947e3 Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Tue, 17 Jun 2025 16:21:57 +0100 Subject: [PATCH 02/37] feat: lock the ``nix build`` to using the repo rust version --- flake.lock | 17 +++++++++++++++++ flake.nix | 23 +++++++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/flake.lock b/flake.lock index 9f7289a..2c4a9bc 100644 --- a/flake.lock +++ b/flake.lock @@ -32,6 +32,22 @@ "type": "indirect" } }, + "nixpkgs-mozilla": { + "flake": false, + "locked": { + "lastModified": 1744624473, + "narHash": "sha256-S6zT/w5SyAkJ//dYdjbrXgm+6Vkd/k7qqUl4WgZ6jjk=", + "owner": "mozilla", + "repo": "nixpkgs-mozilla", + "rev": "2292d4b35aa854e312ad2e95c4bb5c293656f21a", + "type": "github" + }, + "original": { + "owner": "mozilla", + "repo": "nixpkgs-mozilla", + "type": "github" + } + }, "nixpkgs_2": { "locked": { "lastModified": 1722995383, @@ -51,6 +67,7 @@ "inputs": { "naersk": "naersk", "nixpkgs": "nixpkgs_2", + "nixpkgs-mozilla": "nixpkgs-mozilla", "utils": "utils" } }, diff --git a/flake.nix b/flake.nix index b707b60..f7fee94 100644 --- a/flake.nix +++ b/flake.nix @@ -4,6 +4,10 @@ inputs = { nixpkgs.url = "nixpkgs/nixos-unstable"; naersk.url = "github:nix-community/naersk"; + nixpkgs-mozilla = { + url = "github:mozilla/nixpkgs-mozilla"; + flake = false; + }; utils.url = "github:numtide/flake-utils"; }; @@ -17,12 +21,27 @@ nixpkgs, utils, naersk, + nixpkgs-mozilla, }: utils.lib.eachDefaultSystem ( system: let overrides = (builtins.fromTOML (builtins.readFile ./rust-toolchain.toml)); - pkgs = (import nixpkgs) {inherit system;}; - naersk' = pkgs.callPackage naersk {}; + pkgs = (import nixpkgs) { + inherit system; + + overlays = [ + (import nixpkgs-mozilla) + ]; + }; + toolchain = (pkgs.rustChannelOf { + rustToolchain = ./rust-toolchain.toml; + sha256 = "sha256-KUm16pHj+cRedf8vxs/Hd2YWxpOrWZ7UOrwhILdSJBU="; + }).rust; + + naersk' = pkgs.callPackage naersk { + cargo = toolchain; + rustc = toolchain; + }; package_name = "skynet_discord_bot"; desc = "Skynet Discord Bot"; buildInputs = with pkgs; [ From 1dc5c105df7ba80643b596d3de025a28871aba2c Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Wed, 18 Jun 2025 03:57:04 +0100 Subject: [PATCH 03/37] fix: needed to add git and git lfs to teh path of the service --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index f7fee94..1b39fbb 100644 --- a/flake.nix +++ b/flake.nix @@ -122,7 +122,7 @@ wantedBy = []; after = ["network-online.target"]; environment = environment_config; - + path = with pkgs; [ git git-lfs ]; serviceConfig = { Type = "oneshot"; User = "${cfg.user}"; From 7403f531eb38a8c1ff0621d0c7f2fb30ecc919fd Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Tue, 24 Jun 2025 00:00:56 +0100 Subject: [PATCH 04/37] feat: the backend is pretty simple, just pull the rep link from teh config_toml and add on the path to the docs. Then its just linking it all up. Closes #37 --- src/commands/wolves.rs | 17 +++++++++++++++++ src/main.rs | 1 + 2 files changed, 18 insertions(+) diff --git a/src/commands/wolves.rs b/src/commands/wolves.rs index d790f9f..d78454b 100644 --- a/src/commands/wolves.rs +++ b/src/commands/wolves.rs @@ -279,6 +279,22 @@ pub mod link { } } +pub mod link_docs { + use super::*; + pub mod users { + use super::*; + use serenity::all::CommandInteraction; + + pub async fn run(_command: &CommandInteraction, _ctx: &Context) -> String { + "https://forgejo.skynet.ie/Skynet/discord-bot/src/branch/main/doc/User.md".to_string() + } + } + + // pub mod committee { + // + // } +} + pub mod verify { use super::*; use crate::commands::wolves::link::{db_pending_clear_expired, get_server_member_discord, get_verify_from_db}; @@ -522,4 +538,5 @@ pub fn register() -> CreateCommand { .add_sub_option(CreateCommandOption::new(CommandOptionType::String, "minecraft_username", "Your Minecraft username").required(true)) .add_sub_option(CreateCommandOption::new(CommandOptionType::Boolean, "bedrock_account", "Is this a Bedrock account?").required(false)), ) + .add_option(CreateCommandOption::new(CommandOptionType::SubCommand, "docs", "Link to where the documentation can be found.")) } diff --git a/src/main.rs b/src/main.rs index 9de027e..238777d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -177,6 +177,7 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use "verify" => commands::wolves::verify::run(&command, &ctx).await, "unlink" => commands::wolves::unlink::run(&command, &ctx).await, "link_minecraft" => commands::minecraft::user::add::run(&command, &ctx).await, + "docs" => commands::wolves::link_docs::users::run(&command, &ctx).await, // "link" => commands::count::servers::run(&command, &ctx).await, &_ => format!("not implemented :( wolves {}", x.name.as_str()), }, From c4da3e91096741dc827f3a5ac3c184160b8f1e8c Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Sat, 5 Jul 2025 15:31:53 +0100 Subject: [PATCH 05/37] fix: only allow image files to be chosen --- src/common/server_icon.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/common/server_icon.rs b/src/common/server_icon.rs index 8fcbcee..abd0972 100644 --- a/src/common/server_icon.rs +++ b/src/common/server_icon.rs @@ -286,9 +286,19 @@ pub mod update_icon { fn logos_filter(festival_data: &FestivalData, existing: Vec) -> Vec { let mut filtered: Vec = vec![]; + let allowed_files = vec![".png", ".jpeg", ".gif", ".svg"]; 'outer: for logo in existing { let name_lowercase0 = logo.name.to_ascii_lowercase(); let name_lowercase = name_lowercase0.to_str().unwrap_or_default(); + let mut allowed = false; + for allowed_type in &allowed_files { + if name_lowercase.ends_with(allowed_type) { + allowed = true; + } + } + if !allowed { + continue; + } if !festival_data.current.is_empty() { // if its a current festival filter based on it From 76f8aa2712dcfeb701b3dce16c7d93323afbeb66 Mon Sep 17 00:00:00 2001 From: esy Date: Sun, 6 Jul 2025 18:12:04 +0000 Subject: [PATCH 06/37] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 01543e6..1f49dc1 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Skynet Discord Bot The Skynet bot is designed to manage users on Discord. It allows users to link their UL Wolves account with Wolves in a GDPR compliant manner. -Skynet (bot) is hosted is hosted by the Computer Society on Skynet (computer cluster). +Skynet (bot) is hosted by the Computer Society on Skynet (computer cluster). ## Documentation We have split up the documentation into different segments depending on who the user is. From 764e8cd620d61ed6ca6d168cd06489e94d40b615 Mon Sep 17 00:00:00 2001 From: Daragh Date: Sun, 6 Jul 2025 23:28:51 +0000 Subject: [PATCH 07/37] Fix LFS on discord bot (#39) Reviewed-on: https://forgejo.skynet.ie/Skynet/discord-bot/pulls/39 Thanks @esy Co-authored-by: Daragh Co-committed-by: Daragh --- flake.nix | 1 + src/common/server_icon.rs | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/flake.nix b/flake.nix index 1b39fbb..4494ace 100644 --- a/flake.nix +++ b/flake.nix @@ -221,6 +221,7 @@ after = ["network-online.target"]; wants = []; environment = environment_config; + path = with pkgs; [ git git-lfs ]; serviceConfig = { User = "${cfg.user}"; diff --git a/src/common/server_icon.rs b/src/common/server_icon.rs index abd0972..d99f265 100644 --- a/src/common/server_icon.rs +++ b/src/common/server_icon.rs @@ -191,6 +191,28 @@ pub mod update_icon { { dbg!(e); } + + if let Err(e) = Command::new("git") + // Install LFS for the repo + .arg("lfs") + .arg("install") + .current_dir(&folder) + .output() + { + dbg!(e); + } + + if let Err(e) = Command::new("git") + // clone the repo, gracefully "fails" + .arg("lfs") + .arg("pull") + .arg("origin") + .arg("main") + .current_dir(&folder) + .output() + { + dbg!(e); + } } fn get_logos(config: &Config, config_toml: &ConfigToml) -> Vec { From b8ffd421844414b44cc66d7ef671c206072027da Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Mon, 7 Jul 2025 21:29:37 +0100 Subject: [PATCH 08/37] feat: the bot wasnt using any caching, this should make many operations far faster now --- src/main.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 238777d..2770db7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,16 @@ pub mod commands; use crate::commands::role_adder::tools::on_role_change; -use serenity::all::{ActivityData, Command, CommandDataOptionValue, CreateMessage, EditInteractionResponse, GuildMemberUpdateEvent, Interaction}; -use serenity::model::guild::Member; +use serenity::all::{ + ActivityData, Command, CommandDataOptionValue, CreateMessage, EditInteractionResponse, GuildId, GuildMemberUpdateEvent, Interaction, +}; use serenity::{ async_trait, client::{Context, EventHandler}, + gateway::ChunkGuildFilter, model::{ gateway::{GatewayIntents, Ready}, + guild::Member, user::OnlineStatus, }, Client, @@ -24,6 +27,14 @@ struct Handler; #[async_trait] impl EventHandler for Handler { + // this caches members of all servers teh bot is in + async fn cache_ready(&self, ctx: Context, guilds: Vec) { + for guild in guilds { + ctx.shard.chunk_guild(guild, Some(500), false, ChunkGuildFilter::None, None); + } + println!("Cache built successfully!"); + } + // handles previously linked accounts joining the server async fn guild_member_addition(&self, ctx: Context, new_member: Member) { let db_lock = { @@ -281,6 +292,7 @@ async fn main() { // Build our client. let mut client = Client::builder(&config.discord_token, intents) .event_handler(Handler {}) + .cache_settings(serenity::cache::Settings::default()) .await .expect("Error creating client"); From 3abbb8d4854a41754bda907271ef1504fbbfe53b Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Mon, 7 Jul 2025 22:18:04 +0100 Subject: [PATCH 09/37] feat: added script to clean up the committee server if it got flooded with extra channels --- Cargo.toml | 3 + src/bin/cleanup_committee.rs | 129 +++++++++++++++++++++++++++++++++++ src/common/set_roles.rs | 6 +- 3 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 src/bin/cleanup_committee.rs diff --git a/Cargo.toml b/Cargo.toml index b179901..bca450c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,9 @@ name = "update_minecraft" [[bin]] name = "update_server-icon" +[[bin]] +name = "cleanup_committee" + [dependencies] # discord library serenity = { version = "0.12", default-features = false, features = ["client", "gateway", "rustls_backend", "model", "cache"] } diff --git a/src/bin/cleanup_committee.rs b/src/bin/cleanup_committee.rs new file mode 100644 index 0000000..7d2ea5a --- /dev/null +++ b/src/bin/cleanup_committee.rs @@ -0,0 +1,129 @@ +use serenity::all::{ChunkGuildFilter, GuildId}; +use serenity::{ + async_trait, + client::{Context, EventHandler}, + model::gateway::{GatewayIntents, Ready}, + Client, +}; +use skynet_discord_bot::common::database::{db_init, DataBase}; + +use skynet_discord_bot::common::set_roles::committee::{db_roles_get}; +use skynet_discord_bot::{get_config, Config}; +use sqlx::{Pool, Sqlite}; +use std::{process, sync::Arc}; +use tokio::sync::RwLock; + +/// Cleanup teh Committee server +/// +/// This removes any invalid roles/channels which ay have been set up accidentally +/// DO NOT run this locally unless you have a fresh copy of teh live database handy. +#[tokio::main] +async fn main() { + let config = get_config(); + let db = match db_init(&config).await { + Ok(x) => x, + Err(_) => return, + }; + + // Intents are a bitflag, bitwise operations can be used to dictate which intents to use + let intents = GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::GUILD_MEMBERS; + // Build our client. + let mut client = Client::builder(&config.discord_token, intents) + .event_handler(Handler {}) + .cache_settings(serenity::cache::Settings::default()) + .await + .expect("Error creating client"); + + { + let mut data = client.data.write().await; + + data.insert::(Arc::new(RwLock::new(config))); + data.insert::(Arc::new(RwLock::new(db))); + } + + if let Err(why) = client.start().await { + println!("Client error: {:?}", why); + } +} + +struct Handler; +#[async_trait] +impl EventHandler for Handler { + async fn cache_ready(&self, ctx: Context, guilds: Vec) { + for guild in guilds { + ctx.shard.chunk_guild(guild, Some(500), false, ChunkGuildFilter::None, None); + } + println!("Cache built successfully!"); + } + + async fn ready(&self, ctx: Context, ready: Ready) { + let ctx = Arc::new(ctx); + println!("{} is connected!", ready.user.name); + + let db_lock = { + let data_read = ctx.data.read().await; + data_read.get::().expect("Expected Config in TypeMap.").clone() + }; + + let db = db_lock.read().await; + + let config_lock = { + let data_read = ctx.data.read().await; + data_read.get::().expect("Expected Config in TypeMap.").clone() + }; + let config = config_lock.read().await; + + cleanup(&db, &ctx, &config).await; + // finish up + process::exit(0); + } +} + +async fn cleanup(db: &Pool, ctx: &Context, config: &Config) { + let server = config.committee_server; + let committees = db_roles_get(db).await; + + if let Ok(channels) = server.channels(ctx).await { + for (id, channel) in &channels { + let name = &channel.name; + let committee_tmp = committees.iter().filter(|x| &x.name_channel == name).collect::>(); + let committee = match committee_tmp.first() { + // if there are no committees which match then this is not a channelw e care about + None => { + continue; + } + Some(x) => x, + }; + + // if the id of the channel does not match then remove it + if id != &committee.id_channel { + println!("Deleting Channel - ID: {} Name: {}", id, &channel.name); + if let Err(e) = channel.delete(ctx).await { + dbg!(e); + } + } + } + } + + if let Ok(mut roles) = server.roles(ctx).await { + for (id, role) in &mut roles { + let name = &role.name; + let committee_tmp = committees.iter().filter(|x| &x.name_role == name).collect::>(); + let committee = match committee_tmp.first() { + // if there are no committees which match then this is not a channelw e care about + None => { + continue; + } + Some(x) => x, + }; + + // if the id of the role does not match then remove it + if id != &committee.id_role { + println!("Deleting Role - ID: {} Name: {}", id, &role.name); + if let Err(e) = role.delete(ctx).await { + dbg!(e); + } + } + } + } +} \ No newline at end of file diff --git a/src/common/set_roles.rs b/src/common/set_roles.rs index 4e24b1a..0012539 100644 --- a/src/common/set_roles.rs +++ b/src/common/set_roles.rs @@ -400,10 +400,10 @@ pub mod committee { #[derive(Debug, Clone, Deserialize, Serialize)] pub struct CommitteeRoles { id_wolves: i64, - id_role: RoleId, - id_channel: ChannelId, + pub id_role: RoleId, + pub id_channel: ChannelId, pub name_role: String, - name_channel: String, + pub name_channel: String, pub count: i64, } From e901f3ed74120cb533b6eff7a873a8cd07776efd Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Mon, 7 Jul 2025 22:22:25 +0100 Subject: [PATCH 10/37] feat: add caching to everything, should make all member interacts faster --- src/bin/cleanup_committee.rs | 6 +++--- src/bin/update_committee.rs | 9 +++++++++ src/bin/update_data.rs | 9 +++++++++ src/bin/update_server-icon.rs | 9 +++++++++ src/bin/update_users.rs | 9 +++++++++ src/main.rs | 2 +- 6 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/bin/cleanup_committee.rs b/src/bin/cleanup_committee.rs index 7d2ea5a..a2c3772 100644 --- a/src/bin/cleanup_committee.rs +++ b/src/bin/cleanup_committee.rs @@ -7,7 +7,7 @@ use serenity::{ }; use skynet_discord_bot::common::database::{db_init, DataBase}; -use skynet_discord_bot::common::set_roles::committee::{db_roles_get}; +use skynet_discord_bot::common::set_roles::committee::db_roles_get; use skynet_discord_bot::{get_config, Config}; use sqlx::{Pool, Sqlite}; use std::{process, sync::Arc}; @@ -51,7 +51,7 @@ struct Handler; impl EventHandler for Handler { async fn cache_ready(&self, ctx: Context, guilds: Vec) { for guild in guilds { - ctx.shard.chunk_guild(guild, Some(500), false, ChunkGuildFilter::None, None); + ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None); } println!("Cache built successfully!"); } @@ -126,4 +126,4 @@ async fn cleanup(db: &Pool, ctx: &Context, config: &Config) { } } } -} \ No newline at end of file +} diff --git a/src/bin/update_committee.rs b/src/bin/update_committee.rs index d2026c0..2eef977 100644 --- a/src/bin/update_committee.rs +++ b/src/bin/update_committee.rs @@ -1,3 +1,4 @@ +use serenity::all::{ChunkGuildFilter, GuildId}; use serenity::{ async_trait, client::{Context, EventHandler}, @@ -23,6 +24,7 @@ async fn main() { // Build our client. let mut client = Client::builder(&config.discord_token, intents) .event_handler(Handler {}) + .cache_settings(serenity::cache::Settings::default()) .await .expect("Error creating client"); @@ -41,6 +43,13 @@ async fn main() { struct Handler; #[async_trait] impl EventHandler for Handler { + async fn cache_ready(&self, ctx: Context, guilds: Vec) { + for guild in guilds { + ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None); + } + println!("Cache built successfully!"); + } + async fn ready(&self, ctx: Context, ready: Ready) { let ctx = Arc::new(ctx); println!("{} is connected!", ready.user.name); diff --git a/src/bin/update_data.rs b/src/bin/update_data.rs index 2d36892..d184ccd 100644 --- a/src/bin/update_data.rs +++ b/src/bin/update_data.rs @@ -1,3 +1,4 @@ +use serenity::all::{ChunkGuildFilter, GuildId}; use serenity::{ async_trait, client::{Context, EventHandler}, @@ -27,6 +28,7 @@ async fn main() { // Build our client. let mut client = Client::builder(&config.discord_token, intents) .event_handler(Handler {}) + .cache_settings(serenity::cache::Settings::default()) .await .expect("Error creating client"); @@ -45,6 +47,13 @@ async fn main() { struct Handler; #[async_trait] impl EventHandler for Handler { + async fn cache_ready(&self, ctx: Context, guilds: Vec) { + for guild in guilds { + ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None); + } + println!("Cache built successfully!"); + } + async fn ready(&self, ctx: Context, ready: Ready) { let ctx = Arc::new(ctx); println!("{} is connected!", ready.user.name); diff --git a/src/bin/update_server-icon.rs b/src/bin/update_server-icon.rs index ff4cef9..2c093f9 100644 --- a/src/bin/update_server-icon.rs +++ b/src/bin/update_server-icon.rs @@ -1,3 +1,4 @@ +use serenity::all::{ChunkGuildFilter, GuildId}; use serenity::{ async_trait, client::{Context, EventHandler}, @@ -25,6 +26,7 @@ async fn main() { // Build our client. let mut client = Client::builder(&config.discord_token, intents) .event_handler(Handler {}) + .cache_settings(serenity::cache::Settings::default()) .await .expect("Error creating client"); @@ -43,6 +45,13 @@ async fn main() { struct Handler; #[async_trait] impl EventHandler for Handler { + async fn cache_ready(&self, ctx: Context, guilds: Vec) { + for guild in guilds { + ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None); + } + println!("Cache built successfully!"); + } + async fn ready(&self, ctx: Context, ready: Ready) { let ctx = Arc::new(ctx); println!("{} is connected!", ready.user.name); diff --git a/src/bin/update_users.rs b/src/bin/update_users.rs index 3617d14..27dc1d6 100644 --- a/src/bin/update_users.rs +++ b/src/bin/update_users.rs @@ -1,3 +1,4 @@ +use serenity::all::{ChunkGuildFilter, GuildId}; use serenity::{ async_trait, client::{Context, EventHandler}, @@ -23,6 +24,7 @@ async fn main() { // Build our client. let mut client = Client::builder(&config.discord_token, intents) .event_handler(Handler {}) + .cache_settings(serenity::cache::Settings::default()) .await .expect("Error creating client"); @@ -41,6 +43,13 @@ async fn main() { struct Handler; #[async_trait] impl EventHandler for Handler { + async fn cache_ready(&self, ctx: Context, guilds: Vec) { + for guild in guilds { + ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None); + } + println!("Cache built successfully!"); + } + async fn ready(&self, ctx: Context, ready: Ready) { let ctx = Arc::new(ctx); println!("{} is connected!", ready.user.name); diff --git a/src/main.rs b/src/main.rs index 2770db7..b09fb7a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -30,7 +30,7 @@ impl EventHandler for Handler { // this caches members of all servers teh bot is in async fn cache_ready(&self, ctx: Context, guilds: Vec) { for guild in guilds { - ctx.shard.chunk_guild(guild, Some(500), false, ChunkGuildFilter::None, None); + ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None); } println!("Cache built successfully!"); } From 2b2dfc253147a0ed5f4456db5c20b421deae71c9 Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Sun, 20 Jul 2025 20:32:43 +0100 Subject: [PATCH 11/37] feat: cleaned up array that was used to count members/changes to a struct --- src/common/set_roles.rs | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/common/set_roles.rs b/src/common/set_roles.rs index 0012539..5c7e29c 100644 --- a/src/common/set_roles.rs +++ b/src/common/set_roles.rs @@ -5,6 +5,13 @@ pub mod normal { use serenity::model::id::{GuildId, RoleId, UserId}; use sqlx::{Pool, Sqlite}; + struct RolesChange { + total: i32, + new: i32, + current_add: i32, + current_rem: i32, + } + pub async fn update_server(ctx: &Context, server: &Servers, remove_roles: &[Option], members_changed: &[UserId]) { let db_lock = { let data_read = ctx.data.read().await; @@ -20,7 +27,12 @@ pub mod normal { .. } = server; - let mut roles_set = [0, 0, 0]; + let mut roles_set = RolesChange { + total: 0, + new: 0, + current_add: 0, + current_rem: 0, + }; let mut members = vec![]; for member in get_server_member_bulk(&db, server).await { @@ -38,17 +50,19 @@ pub mod normal { } if members.contains(&member.user.id) { + roles_set.total += 1; + let mut roles = vec![]; if let Some(role) = &role_past { if !member.roles.contains(role) { - roles_set[0] += 1; + roles_set.new += 1; roles.push(role.to_owned()); } } if !member.roles.contains(role_current) { - roles_set[1] += 1; + roles_set.current_add += 1; roles.push(role_current.to_owned()); } @@ -65,7 +79,7 @@ pub mod normal { } if member.roles.contains(role_current) { - roles_set[2] += 1; + roles_set.current_rem += 1; // if theya re not a current member and have the role then remove it if let Err(e) = member.remove_role(ctx, role_current).await { println!("{:?}", e); @@ -83,7 +97,14 @@ pub mod normal { set_server_numbers(&db, server, members_all as i64, members.len() as i64).await; // small bit of logging to note changes over time - println!("{:?} Changes: New: +{}, Current: +{}/-{}", server.get(), roles_set[0], roles_set[1], roles_set[2]); + println!( + "{:?} Total: {} Changes: New: +{}, Current: +{}/-{}", + server.get(), + roles_set.total, + roles_set.new, + roles_set.current_add, + roles_set.current_rem + ); } pub async fn get_server_member_bulk(db: &Pool, server: &GuildId) -> Vec { From 04aa0e63d4fb0422c2762799eab3d5e3c145abc4 Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Sun, 20 Jul 2025 20:37:28 +0100 Subject: [PATCH 12/37] feat: setup update users to be every 5 min while using the cache --- src/main.rs | 51 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index b09fb7a..5dab67f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,8 @@ pub mod commands; use crate::commands::role_adder::tools::on_role_change; use serenity::all::{ - ActivityData, Command, CommandDataOptionValue, CreateMessage, EditInteractionResponse, GuildId, GuildMemberUpdateEvent, Interaction, + ActivityData, Command, CommandDataOptionValue, CreateMessage, EditInteractionResponse, GuildId, GuildMemberUpdateEvent, GuildMembersChunkEvent, + Interaction, }; use serenity::{ async_trait, @@ -15,15 +16,20 @@ use serenity::{ }, Client, }; -use skynet_discord_bot::common::database::{db_init, get_server_config, get_server_member, DataBase}; +use skynet_discord_bot::common::database::{db_init, get_server_config, get_server_config_bulk, get_server_member, DataBase}; use skynet_discord_bot::common::set_roles::committee::update_committees; +use skynet_discord_bot::common::set_roles::normal; use skynet_discord_bot::common::wolves::committees::Committees; use skynet_discord_bot::{get_config, Config}; use sqlx::{Pool, Sqlite}; +use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; +use std::time::Duration; use tokio::sync::RwLock; -struct Handler; +struct Handler { + is_loop_running: AtomicBool, +} #[async_trait] impl EventHandler for Handler { @@ -35,6 +41,41 @@ impl EventHandler for Handler { println!("Cache built successfully!"); } + async fn guild_members_chunk(&self, ctx: Context, chunk: GuildMembersChunkEvent) { + if (chunk.chunk_index + 1) == chunk.chunk_count { + // from https://github.com/serenity-rs/serenity/blob/18349f7bba43acad4261103eb38fe01d93f382df/examples/e13_parallel_loops/src/main.rs#L48 + let ctx = Arc::new(ctx); + + if !self.is_loop_running.load(Ordering::Relaxed) { + // We have to clone the Arc, as it gets moved into the new thread. + + { + // this is to update member roles every 5 min + let ctx1 = Arc::clone(&ctx); + tokio::spawn(async move { + let db_lock = { + let data_read = ctx1.data.read().await; + data_read.get::().expect("Expected Database in TypeMap.").clone() + }; + let db = db_lock.read().await; + + loop { + println!("User update - Start"); + for server_config in get_server_config_bulk(&db).await { + normal::update_server(&ctx, &server_config, &[], &[]).await; + } + println!("User update - End"); + tokio::time::sleep(Duration::from_secs(60 * 5)).await; + } + }); + } + + // Now that the loop is running, we set the bool to true + self.is_loop_running.swap(true, Ordering::Relaxed); + } + } + } + // handles previously linked accounts joining the server async fn guild_member_addition(&self, ctx: Context, new_member: Member) { let db_lock = { @@ -291,7 +332,9 @@ async fn main() { let intents = GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::GUILD_MEMBERS; // Build our client. let mut client = Client::builder(&config.discord_token, intents) - .event_handler(Handler {}) + .event_handler(Handler { + is_loop_running: AtomicBool::new(false), + }) .cache_settings(serenity::cache::Settings::default()) .await .expect("Error creating client"); From 3dd81a5c5412dda8090f3d3651a236628ee5a964 Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Sun, 20 Jul 2025 20:40:15 +0100 Subject: [PATCH 13/37] feat: remove the update_users service --- Cargo.toml | 5 +-- flake.nix | 2 -- src/bin/update_users.rs | 76 ----------------------------------------- 3 files changed, 1 insertion(+), 82 deletions(-) delete mode 100644 src/bin/update_users.rs diff --git a/Cargo.toml b/Cargo.toml index bca450c..f2bc696 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,9 +8,6 @@ edition = "2021" [[bin]] name = "update_data" -[[bin]] -name = "update_users" - [[bin]] name = "update_committee" @@ -38,7 +35,7 @@ surf = "2.3" dotenvy = "0.15" # For sqlite -sqlx = { version = "0.8", features = [ "runtime-tokio", "sqlite", "migrate" ] } +sqlx = { version = "0.8", features = ["runtime-tokio", "sqlite", "migrate"] } serde_json = { version = "1.0", features = ["raw_value"] } # create random strings diff --git a/flake.nix b/flake.nix index 4494ace..04e062b 100644 --- a/flake.nix +++ b/flake.nix @@ -154,8 +154,6 @@ scripts = { # every 20 min "update_data" = "*:0,10,20,30,40,50"; - # groups are updated every hour, offset from teh ldap - "update_users" = "*:05:00"; # Committee server has its own timer "update_committee" = "*:15:00"; # minecraft stuff is updated at 5am diff --git a/src/bin/update_users.rs b/src/bin/update_users.rs deleted file mode 100644 index 27dc1d6..0000000 --- a/src/bin/update_users.rs +++ /dev/null @@ -1,76 +0,0 @@ -use serenity::all::{ChunkGuildFilter, GuildId}; -use serenity::{ - async_trait, - client::{Context, EventHandler}, - model::gateway::{GatewayIntents, Ready}, - Client, -}; -use skynet_discord_bot::common::database::{db_init, get_server_config_bulk, DataBase}; -use skynet_discord_bot::common::set_roles::normal; -use skynet_discord_bot::{get_config, Config}; -use std::{process, sync::Arc}; -use tokio::sync::RwLock; - -#[tokio::main] -async fn main() { - let config = get_config(); - let db = match db_init(&config).await { - Ok(x) => x, - Err(_) => return, - }; - - // Intents are a bitflag, bitwise operations can be used to dictate which intents to use - let intents = GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::GUILD_MEMBERS; - // Build our client. - let mut client = Client::builder(&config.discord_token, intents) - .event_handler(Handler {}) - .cache_settings(serenity::cache::Settings::default()) - .await - .expect("Error creating client"); - - { - let mut data = client.data.write().await; - - data.insert::(Arc::new(RwLock::new(config))); - data.insert::(Arc::new(RwLock::new(db))); - } - - if let Err(why) = client.start().await { - println!("Client error: {:?}", why); - } -} - -struct Handler; -#[async_trait] -impl EventHandler for Handler { - async fn cache_ready(&self, ctx: Context, guilds: Vec) { - for guild in guilds { - ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None); - } - println!("Cache built successfully!"); - } - - async fn ready(&self, ctx: Context, ready: Ready) { - let ctx = Arc::new(ctx); - println!("{} is connected!", ready.user.name); - - // this goes into each server and sets roles for each wolves member - check_bulk(Arc::clone(&ctx)).await; - - // finish up - process::exit(0); - } -} - -async fn check_bulk(ctx: Arc) { - let db_lock = { - let data_read = ctx.data.read().await; - data_read.get::().expect("Expected Config in TypeMap.").clone() - }; - - let db = db_lock.read().await; - - for server_config in get_server_config_bulk(&db).await { - normal::update_server(&ctx, &server_config, &[], &[]).await; - } -} From a8bed0bacc72295eb193f1351bb6cb33a730ccf6 Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Sun, 20 Jul 2025 20:42:32 +0100 Subject: [PATCH 14/37] fix: was calling the wrong ctx --- src/main.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index 5dab67f..08699e4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -51,10 +51,10 @@ impl EventHandler for Handler { { // this is to update member roles every 5 min - let ctx1 = Arc::clone(&ctx); + let ctx_task = Arc::clone(&ctx); tokio::spawn(async move { let db_lock = { - let data_read = ctx1.data.read().await; + let data_read = ctx_task.data.read().await; data_read.get::().expect("Expected Database in TypeMap.").clone() }; let db = db_lock.read().await; @@ -62,7 +62,7 @@ impl EventHandler for Handler { loop { println!("User update - Start"); for server_config in get_server_config_bulk(&db).await { - normal::update_server(&ctx, &server_config, &[], &[]).await; + normal::update_server(&ctx_task, &server_config, &[], &[]).await; } println!("User update - End"); tokio::time::sleep(Duration::from_secs(60 * 5)).await; From 43ef787d59f1315a8537e318b6ae2c88ca3d3f29 Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Sun, 20 Jul 2025 22:25:31 +0100 Subject: [PATCH 15/37] fix: no need to pass in teh full object, a reference will do --- src/common/set_roles.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/set_roles.rs b/src/common/set_roles.rs index 5c7e29c..c51c52e 100644 --- a/src/common/set_roles.rs +++ b/src/common/set_roles.rs @@ -168,7 +168,7 @@ pub mod committee { use std::collections::HashMap; use std::sync::Arc; - pub async fn check_committee(ctx: Arc) { + pub async fn check_committee(ctx: &Context) { let db_lock = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Config in TypeMap.").clone() From 1729ec0a54d1656139f403b7a9c50131dedd5d6e Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Sun, 20 Jul 2025 22:26:51 +0100 Subject: [PATCH 16/37] feat: drastically speed up the committee server script, it no longer tries to remove the committee role from those who dont have it. --- src/common/set_roles.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/common/set_roles.rs b/src/common/set_roles.rs index c51c52e..fbbc828 100644 --- a/src/common/set_roles.rs +++ b/src/common/set_roles.rs @@ -329,15 +329,11 @@ pub mod committee { None => { vec![] } - Some(x) => { - let mut tmp = x.to_owned(); - if !tmp.is_empty() { - tmp.push(committee_member); - } - tmp - } + Some(x) => x.to_owned(), }; + let on_committee = !roles_required.is_empty(); + let mut roles_rem = vec![]; let mut roles_add = vec![]; // get a list of all the roles to remove from someone @@ -346,14 +342,25 @@ pub mod committee { for role in &roles_current { roles_current_id.push(role.id.to_owned()); if !roles_required.contains(&role.id) { - roles_rem.push(role.id.to_owned()); + if role.id == committee_member { + if !on_committee { + roles_rem.push(role.id.to_owned()); + } + } } } - if !roles_required.is_empty() { + let has_committee_role = roles_current_id.contains(&committee_member); + + if on_committee && !has_committee_role { // if there are committee roles then give the general purporse role roles_add.push(committee_member); + } + if !on_committee && has_committee_role { + roles_rem.push(committee_member); + } + if !roles_required.is_empty() { if let Some(x) = roles_db.get_mut(&0) { x.count += 1; } @@ -372,8 +379,6 @@ pub mod committee { if !roles_add.is_empty() { // these roles are flavor roles, only there to make folks mentionable member.add_roles(&ctx, &roles_add).await.unwrap_or_default(); - } else { - member.remove_roles(&ctx, &[committee_member]).await.unwrap_or_default(); } } From 5815cde38b1216f4b286e19617ae324fe15ebadd Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Sun, 20 Jul 2025 22:28:59 +0100 Subject: [PATCH 17/37] fmt: better wording for logs --- src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 08699e4..76ef059 100644 --- a/src/main.rs +++ b/src/main.rs @@ -60,11 +60,11 @@ impl EventHandler for Handler { let db = db_lock.read().await; loop { - println!("User update - Start"); + println!("Update - Users - Start"); for server_config in get_server_config_bulk(&db).await { normal::update_server(&ctx_task, &server_config, &[], &[]).await; } - println!("User update - End"); + println!("Update - Users - End"); tokio::time::sleep(Duration::from_secs(60 * 5)).await; } }); From 96eb81293b498b71f55824d47e8f7f72314cb03b Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Sun, 20 Jul 2025 22:32:55 +0100 Subject: [PATCH 18/37] feat: got the committee update running smoothly (using cache and far far faster due to fixing some logic issues) --- src/main.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 76ef059..ffbd10d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,7 +18,7 @@ use serenity::{ }; use skynet_discord_bot::common::database::{db_init, get_server_config, get_server_config_bulk, get_server_member, DataBase}; use skynet_discord_bot::common::set_roles::committee::update_committees; -use skynet_discord_bot::common::set_roles::normal; +use skynet_discord_bot::common::set_roles::{committee, normal}; use skynet_discord_bot::common::wolves::committees::Committees; use skynet_discord_bot::{get_config, Config}; use sqlx::{Pool, Sqlite}; @@ -70,6 +70,19 @@ impl EventHandler for Handler { }); } + { + // this is to update committee roles every 5 min + let ctx_task = Arc::clone(&ctx); + tokio::spawn(async move { + loop { + println!("Update - Committee - Start"); + committee::check_committee(&ctx_task).await; + println!("Update - Committee - End"); + tokio::time::sleep(Duration::from_secs(60 * 5)).await; + } + }); + } + // Now that the loop is running, we set the bool to true self.is_loop_running.swap(true, Ordering::Relaxed); } From eb8821674080a465f275f9e8fcf03fa18a40f776 Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Sun, 20 Jul 2025 22:33:56 +0100 Subject: [PATCH 19/37] feat: removed the cronjob for updating the committee server --- Cargo.toml | 3 -- flake.nix | 2 -- src/bin/update_committee.rs | 63 ------------------------------------- 3 files changed, 68 deletions(-) delete mode 100644 src/bin/update_committee.rs diff --git a/Cargo.toml b/Cargo.toml index f2bc696..deb6676 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,9 +8,6 @@ edition = "2021" [[bin]] name = "update_data" -[[bin]] -name = "update_committee" - [[bin]] name = "update_minecraft" diff --git a/flake.nix b/flake.nix index 04e062b..ea52e09 100644 --- a/flake.nix +++ b/flake.nix @@ -154,8 +154,6 @@ scripts = { # every 20 min "update_data" = "*:0,10,20,30,40,50"; - # Committee server has its own timer - "update_committee" = "*:15:00"; # minecraft stuff is updated at 5am "update_minecraft" = "5:10:00"; # server icon gets updated daily at midnight diff --git a/src/bin/update_committee.rs b/src/bin/update_committee.rs deleted file mode 100644 index 2eef977..0000000 --- a/src/bin/update_committee.rs +++ /dev/null @@ -1,63 +0,0 @@ -use serenity::all::{ChunkGuildFilter, GuildId}; -use serenity::{ - async_trait, - client::{Context, EventHandler}, - model::gateway::{GatewayIntents, Ready}, - Client, -}; -use skynet_discord_bot::common::database::{db_init, DataBase}; -use skynet_discord_bot::common::set_roles::committee; -use skynet_discord_bot::{get_config, Config}; -use std::{process, sync::Arc}; -use tokio::sync::RwLock; - -#[tokio::main] -async fn main() { - let config = get_config(); - let db = match db_init(&config).await { - Ok(x) => x, - Err(_) => return, - }; - - // Intents are a bitflag, bitwise operations can be used to dictate which intents to use - let intents = GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::GUILD_MEMBERS; - // Build our client. - let mut client = Client::builder(&config.discord_token, intents) - .event_handler(Handler {}) - .cache_settings(serenity::cache::Settings::default()) - .await - .expect("Error creating client"); - - { - let mut data = client.data.write().await; - - data.insert::(Arc::new(RwLock::new(config))); - data.insert::(Arc::new(RwLock::new(db))); - } - - if let Err(why) = client.start().await { - println!("Client error: {:?}", why); - } -} - -struct Handler; -#[async_trait] -impl EventHandler for Handler { - async fn cache_ready(&self, ctx: Context, guilds: Vec) { - for guild in guilds { - ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None); - } - println!("Cache built successfully!"); - } - - async fn ready(&self, ctx: Context, ready: Ready) { - let ctx = Arc::new(ctx); - println!("{} is connected!", ready.user.name); - - // u[date committee server - committee::check_committee(Arc::clone(&ctx)).await; - - // finish up - process::exit(0); - } -} From 13eb2307543c7d117661a8affedae04f175084f4 Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Sun, 20 Jul 2025 22:48:04 +0100 Subject: [PATCH 20/37] fix: updating the wolves (user data) should not trigger a server update (directly). That should always be triggered separately. This was a holdover from a time when updating teh users was expensive (timewise) --- src/common/wolves.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/common/wolves.rs b/src/common/wolves.rs index 6f73842..e199ad2 100644 --- a/src/common/wolves.rs +++ b/src/common/wolves.rs @@ -49,7 +49,6 @@ async fn add_users_wolves(db: &Pool, user: &WolvesResultUserMin) { */ pub mod cns { use crate::common::database::{get_server_config_bulk, DataBase, ServerMembers, ServerMembersWolves, Servers}; - use crate::common::set_roles::normal::update_server; use crate::common::wolves::{add_users_wolves, WolvesResultUserMin}; use crate::Config; use serenity::client::Context; @@ -96,7 +95,6 @@ pub mod cns { let existing = existing_tmp.iter().map(|data| (data.id_wolves, data)).collect::>(); // list of users that need to be updated for this server - let mut user_to_update = vec![]; let mut server_name_tmp = None; for user in wolves.get_members(wolves_api).await { // dbg!(&user.committee); @@ -115,10 +113,6 @@ pub mod cns { add_users_wolves(&db, &WolvesResultUserMin::from(&user)).await; if old.expiry != user.expiry { add_users_server_members(&db, server, &user).await; - - if let Some(discord_id) = old.discord { - user_to_update.push(discord_id); - } } } } @@ -129,9 +123,6 @@ pub mod cns { set_server_member(&db, server, cs_id).await; } } - if !user_to_update.is_empty() { - update_server(ctx, &server_config, &[], &user_to_update).await; - } } } From 227db8a74130d104aff9e767fb155f72913e06a8 Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Sun, 20 Jul 2025 22:54:34 +0100 Subject: [PATCH 21/37] feat: moved the update data to the main thread --- Cargo.toml | 4 --- flake.nix | 2 -- src/bin/update_data.rs | 70 ------------------------------------------ src/main.rs | 22 ++++++++++++- 4 files changed, 21 insertions(+), 77 deletions(-) delete mode 100644 src/bin/update_data.rs diff --git a/Cargo.toml b/Cargo.toml index deb6676..ef48675 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,10 +4,6 @@ version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[[bin]] -name = "update_data" - [[bin]] name = "update_minecraft" diff --git a/flake.nix b/flake.nix index ea52e09..31d6434 100644 --- a/flake.nix +++ b/flake.nix @@ -152,8 +152,6 @@ # modify these scripts = { - # every 20 min - "update_data" = "*:0,10,20,30,40,50"; # minecraft stuff is updated at 5am "update_minecraft" = "5:10:00"; # server icon gets updated daily at midnight diff --git a/src/bin/update_data.rs b/src/bin/update_data.rs deleted file mode 100644 index d184ccd..0000000 --- a/src/bin/update_data.rs +++ /dev/null @@ -1,70 +0,0 @@ -use serenity::all::{ChunkGuildFilter, GuildId}; -use serenity::{ - async_trait, - client::{Context, EventHandler}, - model::gateway::{GatewayIntents, Ready}, - Client, -}; -use skynet_discord_bot::common::database::{db_init, DataBase}; -use skynet_discord_bot::common::wolves::cns::get_wolves; -use skynet_discord_bot::common::wolves::committees::get_cns; -use skynet_discord_bot::{get_config, Config}; -use std::{process, sync::Arc}; -use tokio::sync::RwLock; - -#[tokio::main] -async fn main() { - let config = get_config(); - let db = match db_init(&config).await { - Ok(x) => x, - Err(e) => { - dbg!(e); - return; - } - }; - - // Intents are a bitflag, bitwise operations can be used to dictate which intents to use - let intents = GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::GUILD_MEMBERS; - // Build our client. - let mut client = Client::builder(&config.discord_token, intents) - .event_handler(Handler {}) - .cache_settings(serenity::cache::Settings::default()) - .await - .expect("Error creating client"); - - { - let mut data = client.data.write().await; - - data.insert::(Arc::new(RwLock::new(config))); - data.insert::(Arc::new(RwLock::new(db))); - } - - if let Err(why) = client.start().await { - println!("Client error: {:?}", why); - } -} - -struct Handler; -#[async_trait] -impl EventHandler for Handler { - async fn cache_ready(&self, ctx: Context, guilds: Vec) { - for guild in guilds { - ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None); - } - println!("Cache built successfully!"); - } - - async fn ready(&self, ctx: Context, ready: Ready) { - let ctx = Arc::new(ctx); - println!("{} is connected!", ready.user.name); - - // get the data for each individual club/soc - get_wolves(&ctx).await; - - // get teh data for the clubs/socs committees - get_cns(&ctx).await; - - // finish up - process::exit(0); - } -} diff --git a/src/main.rs b/src/main.rs index ffbd10d..df08f6b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,7 +19,8 @@ use serenity::{ use skynet_discord_bot::common::database::{db_init, get_server_config, get_server_config_bulk, get_server_member, DataBase}; use skynet_discord_bot::common::set_roles::committee::update_committees; use skynet_discord_bot::common::set_roles::{committee, normal}; -use skynet_discord_bot::common::wolves::committees::Committees; +use skynet_discord_bot::common::wolves::cns::get_wolves; +use skynet_discord_bot::common::wolves::committees::{get_cns, Committees}; use skynet_discord_bot::{get_config, Config}; use sqlx::{Pool, Sqlite}; use std::sync::atomic::{AtomicBool, Ordering}; @@ -49,6 +50,25 @@ impl EventHandler for Handler { if !self.is_loop_running.load(Ordering::Relaxed) { // We have to clone the Arc, as it gets moved into the new thread. + { + // This updates all the data, wolves user data and the committees + let ctx_task = Arc::clone(&ctx); + tokio::spawn(async move { + loop { + println!("Update - Data - Start"); + + // get the data for each individual club/soc + get_wolves(&ctx_task).await; + + // get teh data for the clubs/socs committees + get_cns(&ctx_task).await; + + println!("Update - Data - End"); + tokio::time::sleep(Duration::from_secs(60 * 5)).await; + } + }); + } + { // this is to update member roles every 5 min let ctx_task = Arc::clone(&ctx); From feff293043b4f2f587e9aef6475decdc5d3e87cb Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Sun, 20 Jul 2025 23:12:02 +0100 Subject: [PATCH 22/37] feat: moved the update server icon to the main thread --- Cargo.toml | 3 -- flake.nix | 3 +- src/bin/update_server-icon.rs | 78 ----------------------------------- src/commands/server_icon.rs | 2 +- src/main.rs | 40 +++++++++++++++++- 5 files changed, 40 insertions(+), 86 deletions(-) delete mode 100644 src/bin/update_server-icon.rs diff --git a/Cargo.toml b/Cargo.toml index ef48675..79ad1d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,9 +7,6 @@ edition = "2021" [[bin]] name = "update_minecraft" -[[bin]] -name = "update_server-icon" - [[bin]] name = "cleanup_committee" diff --git a/flake.nix b/flake.nix index 31d6434..2dee869 100644 --- a/flake.nix +++ b/flake.nix @@ -153,9 +153,8 @@ # modify these scripts = { # minecraft stuff is updated at 5am + # this service does not depend on teh discord cache "update_minecraft" = "5:10:00"; - # server icon gets updated daily at midnight - "update_server-icon" = "0:01:00"; }; in { options.services."${package_name}" = { diff --git a/src/bin/update_server-icon.rs b/src/bin/update_server-icon.rs deleted file mode 100644 index 2c093f9..0000000 --- a/src/bin/update_server-icon.rs +++ /dev/null @@ -1,78 +0,0 @@ -use serenity::all::{ChunkGuildFilter, GuildId}; -use serenity::{ - async_trait, - client::{Context, EventHandler}, - model::gateway::{GatewayIntents, Ready}, - Client, -}; -use skynet_discord_bot::common::server_icon::{get_config_icons, update_icon}; -use skynet_discord_bot::{ - common::database::{db_init, DataBase}, - get_config, Config, -}; -use std::{process, sync::Arc}; -use tokio::sync::RwLock; - -#[tokio::main] -async fn main() { - let config = get_config(); - let db = match db_init(&config).await { - Ok(x) => x, - Err(_) => return, - }; - - // Intents are a bitflag, bitwise operations can be used to dictate which intents to use - let intents = GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::GUILD_MEMBERS; - // Build our client. - let mut client = Client::builder(&config.discord_token, intents) - .event_handler(Handler {}) - .cache_settings(serenity::cache::Settings::default()) - .await - .expect("Error creating client"); - - { - let mut data = client.data.write().await; - - data.insert::(Arc::new(RwLock::new(config))); - data.insert::(Arc::new(RwLock::new(db))); - } - - if let Err(why) = client.start().await { - println!("Client error: {:?}", why); - } -} - -struct Handler; -#[async_trait] -impl EventHandler for Handler { - async fn cache_ready(&self, ctx: Context, guilds: Vec) { - for guild in guilds { - ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None); - } - println!("Cache built successfully!"); - } - - async fn ready(&self, ctx: Context, ready: Ready) { - let ctx = Arc::new(ctx); - println!("{} is connected!", ready.user.name); - - let db_lock = { - let data_read = ctx.data.read().await; - data_read.get::().expect("Expected Config in TypeMap.").clone() - }; - let db = db_lock.read().await; - - let config_lock = { - let data_read = ctx.data.read().await; - data_read.get::().expect("Expected Config in TypeMap.").clone() - }; - - let config_global = config_lock.read().await; - let config_toml = get_config_icons::minimal(); - - update_icon::update_icon_main(&ctx, &db, &config_global, &config_toml).await; - - // finish up - process::exit(0); - } -} diff --git a/src/commands/server_icon.rs b/src/commands/server_icon.rs index 9c970fc..59d755f 100644 --- a/src/commands/server_icon.rs +++ b/src/commands/server_icon.rs @@ -93,7 +93,7 @@ pub(crate) mod user { } } - async fn get_current_icon(db: &Pool) -> Option { + pub async fn get_current_icon(db: &Pool) -> Option { match sqlx::query_as::<_, ServerIcons>( " SELECT * from server_icons ORDER BY id DESC LIMIT 1 diff --git a/src/main.rs b/src/main.rs index df08f6b..6e6ad8a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,11 @@ pub mod commands; use crate::commands::role_adder::tools::on_role_change; +use crate::commands::server_icon::user::current::icon::get_current_icon; +use chrono::{Days, SecondsFormat, TimeDelta, Utc}; use serenity::all::{ - ActivityData, Command, CommandDataOptionValue, CreateMessage, EditInteractionResponse, GuildId, GuildMemberUpdateEvent, GuildMembersChunkEvent, - Interaction, + ActivityData, Command, CommandDataOptionValue, CreateAttachment, CreateMessage, EditInteractionResponse, GuildId, GuildMemberUpdateEvent, + GuildMembersChunkEvent, Interaction, }; use serenity::{ async_trait, @@ -17,6 +19,7 @@ use serenity::{ Client, }; use skynet_discord_bot::common::database::{db_init, get_server_config, get_server_config_bulk, get_server_member, DataBase}; +use skynet_discord_bot::common::server_icon::{get_config_icons, update_icon}; use skynet_discord_bot::common::set_roles::committee::update_committees; use skynet_discord_bot::common::set_roles::{committee, normal}; use skynet_discord_bot::common::wolves::cns::get_wolves; @@ -103,6 +106,39 @@ impl EventHandler for Handler { }); } + { + // this updates teh server icon once a day + let ctx_task = Arc::clone(&ctx); + tokio::spawn(async move { + let db_lock = { + let data_read = ctx_task.data.read().await; + data_read.get::().expect("Expected Database in TypeMap.").clone() + }; + let db = db_lock.read().await; + let config_lock = { + let data_read = ctx.data.read().await; + data_read.get::().expect("Expected Config in TypeMap.").clone() + }; + + let config_global = config_lock.read().await; + let config_toml = get_config_icons::minimal(); + + loop { + println!("Update - Logo - Start"); + // even though this task will run every 5 min it will only actually change the icon when its a day old + if let Some(logo) = get_current_icon(&db).await { + let now = Utc::now(); + let yesterday = now.checked_sub_days(Days::new(1)).unwrap_or_default(); + if logo.date < yesterday.to_rfc3339_opts(SecondsFormat::Millis, true) { + update_icon::update_icon_main(&ctx, &db, &config_global, &config_toml).await; + } + } + println!("Update - Logo - End"); + tokio::time::sleep(Duration::from_secs(60 * 5)).await; + } + }); + } + // Now that the loop is running, we set the bool to true self.is_loop_running.swap(true, Ordering::Relaxed); } From 1af7f28a453bda331c203e862a71258690860490 Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Sun, 20 Jul 2025 23:40:34 +0100 Subject: [PATCH 23/37] feat: restore teh original services, giving up the logging and control was too much --- Cargo.toml | 9 ++++ flake.nix | 8 ++++ src/bin/update_committee.rs | 63 ++++++++++++++++++++++++++++ src/bin/update_data.rs | 70 +++++++++++++++++++++++++++++++ src/bin/update_server-icon.rs | 78 +++++++++++++++++++++++++++++++++++ src/bin/update_users.rs | 76 ++++++++++++++++++++++++++++++++++ 6 files changed, 304 insertions(+) create mode 100644 src/bin/update_committee.rs create mode 100644 src/bin/update_data.rs create mode 100644 src/bin/update_server-icon.rs create mode 100644 src/bin/update_users.rs diff --git a/Cargo.toml b/Cargo.toml index 79ad1d0..832eb09 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,9 +4,18 @@ version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[[bin]] +name = "update_data" + +[[bin]] +name = "update_committee" + [[bin]] name = "update_minecraft" +[[bin]] +name = "update_server-icon" + [[bin]] name = "cleanup_committee" diff --git a/flake.nix b/flake.nix index 2dee869..81f4490 100644 --- a/flake.nix +++ b/flake.nix @@ -152,9 +152,17 @@ # modify these scripts = { + # every 10 min + "update_data" = "*:0,10,20,30,40,50"; + # groups are updated every hour, offset from teh ldap + "update_users" = "*:5,15,25,35,45,55"; + # Committee server has its own timer + "update_committee" = "*:5,15,25,35,45,55"; # minecraft stuff is updated at 5am # this service does not depend on teh discord cache "update_minecraft" = "5:10:00"; + # server icon gets updated daily at midnight + "update_server-icon" = "0:01:00"; }; in { options.services."${package_name}" = { diff --git a/src/bin/update_committee.rs b/src/bin/update_committee.rs new file mode 100644 index 0000000..b348d18 --- /dev/null +++ b/src/bin/update_committee.rs @@ -0,0 +1,63 @@ +use serenity::all::{ChunkGuildFilter, GuildId}; +use serenity::{ + async_trait, + client::{Context, EventHandler}, + model::gateway::{GatewayIntents, Ready}, + Client, +}; +use skynet_discord_bot::common::database::{db_init, DataBase}; +use skynet_discord_bot::common::set_roles::committee; +use skynet_discord_bot::{get_config, Config}; +use std::{process, sync::Arc}; +use tokio::sync::RwLock; + +#[tokio::main] +async fn main() { + let config = get_config(); + let db = match db_init(&config).await { + Ok(x) => x, + Err(_) => return, + }; + + // Intents are a bitflag, bitwise operations can be used to dictate which intents to use + let intents = GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::GUILD_MEMBERS; + // Build our client. + let mut client = Client::builder(&config.discord_token, intents) + .event_handler(Handler {}) + .cache_settings(serenity::cache::Settings::default()) + .await + .expect("Error creating client"); + + { + let mut data = client.data.write().await; + + data.insert::(Arc::new(RwLock::new(config))); + data.insert::(Arc::new(RwLock::new(db))); + } + + if let Err(why) = client.start().await { + println!("Client error: {:?}", why); + } +} + +struct Handler; +#[async_trait] +impl EventHandler for Handler { + async fn cache_ready(&self, ctx: Context, guilds: Vec) { + for guild in guilds { + ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None); + } + println!("Cache built successfully!"); + } + + async fn ready(&self, ctx: Context, ready: Ready) { + let ctx = Arc::new(ctx); + println!("{} is connected!", ready.user.name); + + // u[date committee server + committee::check_committee(&ctx).await; + + // finish up + process::exit(0); + } +} diff --git a/src/bin/update_data.rs b/src/bin/update_data.rs new file mode 100644 index 0000000..d184ccd --- /dev/null +++ b/src/bin/update_data.rs @@ -0,0 +1,70 @@ +use serenity::all::{ChunkGuildFilter, GuildId}; +use serenity::{ + async_trait, + client::{Context, EventHandler}, + model::gateway::{GatewayIntents, Ready}, + Client, +}; +use skynet_discord_bot::common::database::{db_init, DataBase}; +use skynet_discord_bot::common::wolves::cns::get_wolves; +use skynet_discord_bot::common::wolves::committees::get_cns; +use skynet_discord_bot::{get_config, Config}; +use std::{process, sync::Arc}; +use tokio::sync::RwLock; + +#[tokio::main] +async fn main() { + let config = get_config(); + let db = match db_init(&config).await { + Ok(x) => x, + Err(e) => { + dbg!(e); + return; + } + }; + + // Intents are a bitflag, bitwise operations can be used to dictate which intents to use + let intents = GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::GUILD_MEMBERS; + // Build our client. + let mut client = Client::builder(&config.discord_token, intents) + .event_handler(Handler {}) + .cache_settings(serenity::cache::Settings::default()) + .await + .expect("Error creating client"); + + { + let mut data = client.data.write().await; + + data.insert::(Arc::new(RwLock::new(config))); + data.insert::(Arc::new(RwLock::new(db))); + } + + if let Err(why) = client.start().await { + println!("Client error: {:?}", why); + } +} + +struct Handler; +#[async_trait] +impl EventHandler for Handler { + async fn cache_ready(&self, ctx: Context, guilds: Vec) { + for guild in guilds { + ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None); + } + println!("Cache built successfully!"); + } + + async fn ready(&self, ctx: Context, ready: Ready) { + let ctx = Arc::new(ctx); + println!("{} is connected!", ready.user.name); + + // get the data for each individual club/soc + get_wolves(&ctx).await; + + // get teh data for the clubs/socs committees + get_cns(&ctx).await; + + // finish up + process::exit(0); + } +} diff --git a/src/bin/update_server-icon.rs b/src/bin/update_server-icon.rs new file mode 100644 index 0000000..2c093f9 --- /dev/null +++ b/src/bin/update_server-icon.rs @@ -0,0 +1,78 @@ +use serenity::all::{ChunkGuildFilter, GuildId}; +use serenity::{ + async_trait, + client::{Context, EventHandler}, + model::gateway::{GatewayIntents, Ready}, + Client, +}; +use skynet_discord_bot::common::server_icon::{get_config_icons, update_icon}; +use skynet_discord_bot::{ + common::database::{db_init, DataBase}, + get_config, Config, +}; +use std::{process, sync::Arc}; +use tokio::sync::RwLock; + +#[tokio::main] +async fn main() { + let config = get_config(); + let db = match db_init(&config).await { + Ok(x) => x, + Err(_) => return, + }; + + // Intents are a bitflag, bitwise operations can be used to dictate which intents to use + let intents = GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::GUILD_MEMBERS; + // Build our client. + let mut client = Client::builder(&config.discord_token, intents) + .event_handler(Handler {}) + .cache_settings(serenity::cache::Settings::default()) + .await + .expect("Error creating client"); + + { + let mut data = client.data.write().await; + + data.insert::(Arc::new(RwLock::new(config))); + data.insert::(Arc::new(RwLock::new(db))); + } + + if let Err(why) = client.start().await { + println!("Client error: {:?}", why); + } +} + +struct Handler; +#[async_trait] +impl EventHandler for Handler { + async fn cache_ready(&self, ctx: Context, guilds: Vec) { + for guild in guilds { + ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None); + } + println!("Cache built successfully!"); + } + + async fn ready(&self, ctx: Context, ready: Ready) { + let ctx = Arc::new(ctx); + println!("{} is connected!", ready.user.name); + + let db_lock = { + let data_read = ctx.data.read().await; + data_read.get::().expect("Expected Config in TypeMap.").clone() + }; + let db = db_lock.read().await; + + let config_lock = { + let data_read = ctx.data.read().await; + data_read.get::().expect("Expected Config in TypeMap.").clone() + }; + + let config_global = config_lock.read().await; + let config_toml = get_config_icons::minimal(); + + update_icon::update_icon_main(&ctx, &db, &config_global, &config_toml).await; + + // finish up + process::exit(0); + } +} diff --git a/src/bin/update_users.rs b/src/bin/update_users.rs new file mode 100644 index 0000000..27dc1d6 --- /dev/null +++ b/src/bin/update_users.rs @@ -0,0 +1,76 @@ +use serenity::all::{ChunkGuildFilter, GuildId}; +use serenity::{ + async_trait, + client::{Context, EventHandler}, + model::gateway::{GatewayIntents, Ready}, + Client, +}; +use skynet_discord_bot::common::database::{db_init, get_server_config_bulk, DataBase}; +use skynet_discord_bot::common::set_roles::normal; +use skynet_discord_bot::{get_config, Config}; +use std::{process, sync::Arc}; +use tokio::sync::RwLock; + +#[tokio::main] +async fn main() { + let config = get_config(); + let db = match db_init(&config).await { + Ok(x) => x, + Err(_) => return, + }; + + // Intents are a bitflag, bitwise operations can be used to dictate which intents to use + let intents = GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::GUILD_MEMBERS; + // Build our client. + let mut client = Client::builder(&config.discord_token, intents) + .event_handler(Handler {}) + .cache_settings(serenity::cache::Settings::default()) + .await + .expect("Error creating client"); + + { + let mut data = client.data.write().await; + + data.insert::(Arc::new(RwLock::new(config))); + data.insert::(Arc::new(RwLock::new(db))); + } + + if let Err(why) = client.start().await { + println!("Client error: {:?}", why); + } +} + +struct Handler; +#[async_trait] +impl EventHandler for Handler { + async fn cache_ready(&self, ctx: Context, guilds: Vec) { + for guild in guilds { + ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None); + } + println!("Cache built successfully!"); + } + + async fn ready(&self, ctx: Context, ready: Ready) { + let ctx = Arc::new(ctx); + println!("{} is connected!", ready.user.name); + + // this goes into each server and sets roles for each wolves member + check_bulk(Arc::clone(&ctx)).await; + + // finish up + process::exit(0); + } +} + +async fn check_bulk(ctx: Arc) { + let db_lock = { + let data_read = ctx.data.read().await; + data_read.get::().expect("Expected Config in TypeMap.").clone() + }; + + let db = db_lock.read().await; + + for server_config in get_server_config_bulk(&db).await { + normal::update_server(&ctx, &server_config, &[], &[]).await; + } +} From bd9d0cd43f12ce062ceab1811848ede632d4e4c3 Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Sun, 20 Jul 2025 23:44:13 +0100 Subject: [PATCH 24/37] fix: these do not need to use teh cache --- src/bin/update_data.rs | 7 ------- src/bin/update_server-icon.rs | 7 ------- 2 files changed, 14 deletions(-) diff --git a/src/bin/update_data.rs b/src/bin/update_data.rs index d184ccd..e67720e 100644 --- a/src/bin/update_data.rs +++ b/src/bin/update_data.rs @@ -47,13 +47,6 @@ async fn main() { struct Handler; #[async_trait] impl EventHandler for Handler { - async fn cache_ready(&self, ctx: Context, guilds: Vec) { - for guild in guilds { - ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None); - } - println!("Cache built successfully!"); - } - async fn ready(&self, ctx: Context, ready: Ready) { let ctx = Arc::new(ctx); println!("{} is connected!", ready.user.name); diff --git a/src/bin/update_server-icon.rs b/src/bin/update_server-icon.rs index 2c093f9..c59634e 100644 --- a/src/bin/update_server-icon.rs +++ b/src/bin/update_server-icon.rs @@ -45,13 +45,6 @@ async fn main() { struct Handler; #[async_trait] impl EventHandler for Handler { - async fn cache_ready(&self, ctx: Context, guilds: Vec) { - for guild in guilds { - ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None); - } - println!("Cache built successfully!"); - } - async fn ready(&self, ctx: Context, ready: Ready) { let ctx = Arc::new(ctx); println!("{} is connected!", ready.user.name); From 6d08312f48dca12d4b06d104499ef3633fa21924 Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Sun, 20 Jul 2025 23:46:30 +0100 Subject: [PATCH 25/37] fix: these were not using teh cache to access teh member/role data *was executing before teh cache was built (``cache_ready`` is only when teh cache has been init, not when it is populated) --- src/bin/cleanup_committee.rs | 35 +++++++++++++++++------------------ src/bin/update_committee.rs | 17 ++++++++--------- src/bin/update_users.rs | 19 +++++++++---------- 3 files changed, 34 insertions(+), 37 deletions(-) diff --git a/src/bin/cleanup_committee.rs b/src/bin/cleanup_committee.rs index a2c3772..cc68536 100644 --- a/src/bin/cleanup_committee.rs +++ b/src/bin/cleanup_committee.rs @@ -1,4 +1,4 @@ -use serenity::all::{ChunkGuildFilter, GuildId}; +use serenity::all::{ChunkGuildFilter, GuildId, GuildMembersChunkEvent}; use serenity::{ async_trait, client::{Context, EventHandler}, @@ -56,26 +56,25 @@ impl EventHandler for Handler { println!("Cache built successfully!"); } - async fn ready(&self, ctx: Context, ready: Ready) { - let ctx = Arc::new(ctx); - println!("{} is connected!", ready.user.name); + async fn guild_members_chunk(&self, ctx: Context, chunk: GuildMembersChunkEvent) { + if (chunk.chunk_index + 1) == chunk.chunk_count { + let db_lock = { + let data_read = ctx.data.read().await; + data_read.get::().expect("Expected Config in TypeMap.").clone() + }; - let db_lock = { - let data_read = ctx.data.read().await; - data_read.get::().expect("Expected Config in TypeMap.").clone() - }; + let db = db_lock.read().await; - let db = db_lock.read().await; + let config_lock = { + let data_read = ctx.data.read().await; + data_read.get::().expect("Expected Config in TypeMap.").clone() + }; + let config = config_lock.read().await; - let config_lock = { - let data_read = ctx.data.read().await; - data_read.get::().expect("Expected Config in TypeMap.").clone() - }; - let config = config_lock.read().await; - - cleanup(&db, &ctx, &config).await; - // finish up - process::exit(0); + cleanup(&db, &ctx, &config).await; + // finish up + process::exit(0); + } } } diff --git a/src/bin/update_committee.rs b/src/bin/update_committee.rs index b348d18..e3e7277 100644 --- a/src/bin/update_committee.rs +++ b/src/bin/update_committee.rs @@ -1,4 +1,4 @@ -use serenity::all::{ChunkGuildFilter, GuildId}; +use serenity::all::{ChunkGuildFilter, GuildId, GuildMembersChunkEvent}; use serenity::{ async_trait, client::{Context, EventHandler}, @@ -50,14 +50,13 @@ impl EventHandler for Handler { println!("Cache built successfully!"); } - async fn ready(&self, ctx: Context, ready: Ready) { - let ctx = Arc::new(ctx); - println!("{} is connected!", ready.user.name); + async fn guild_members_chunk(&self, ctx: Context, chunk: GuildMembersChunkEvent) { + if (chunk.chunk_index + 1) == chunk.chunk_count { + // u[date committee server + committee::check_committee(&ctx).await; - // u[date committee server - committee::check_committee(&ctx).await; - - // finish up - process::exit(0); + // finish up + process::exit(0); + } } } diff --git a/src/bin/update_users.rs b/src/bin/update_users.rs index 27dc1d6..6ba99b0 100644 --- a/src/bin/update_users.rs +++ b/src/bin/update_users.rs @@ -1,4 +1,4 @@ -use serenity::all::{ChunkGuildFilter, GuildId}; +use serenity::all::{ChunkGuildFilter, GuildId, GuildMembersChunkEvent}; use serenity::{ async_trait, client::{Context, EventHandler}, @@ -50,19 +50,18 @@ impl EventHandler for Handler { println!("Cache built successfully!"); } - async fn ready(&self, ctx: Context, ready: Ready) { - let ctx = Arc::new(ctx); - println!("{} is connected!", ready.user.name); + async fn guild_members_chunk(&self, ctx: Context, chunk: GuildMembersChunkEvent) { + if (chunk.chunk_index + 1) == chunk.chunk_count { + // this goes into each server and sets roles for each wolves member + check_bulk(&ctx).await; - // this goes into each server and sets roles for each wolves member - check_bulk(Arc::clone(&ctx)).await; - - // finish up - process::exit(0); + // finish up + process::exit(0); + } } } -async fn check_bulk(ctx: Arc) { +async fn check_bulk(ctx: &Context) { let db_lock = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Config in TypeMap.").clone() From 57d4947edfdcb005faaa98d45d7973dbe1870557 Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Sun, 20 Jul 2025 23:48:05 +0100 Subject: [PATCH 26/37] fix: no longer needint to wait until the cache in teh main program is filled --- src/main.rs | 100 ---------------------------------------------------- 1 file changed, 100 deletions(-) diff --git a/src/main.rs b/src/main.rs index 6e6ad8a..e76bd34 100644 --- a/src/main.rs +++ b/src/main.rs @@ -45,106 +45,6 @@ impl EventHandler for Handler { println!("Cache built successfully!"); } - async fn guild_members_chunk(&self, ctx: Context, chunk: GuildMembersChunkEvent) { - if (chunk.chunk_index + 1) == chunk.chunk_count { - // from https://github.com/serenity-rs/serenity/blob/18349f7bba43acad4261103eb38fe01d93f382df/examples/e13_parallel_loops/src/main.rs#L48 - let ctx = Arc::new(ctx); - - if !self.is_loop_running.load(Ordering::Relaxed) { - // We have to clone the Arc, as it gets moved into the new thread. - - { - // This updates all the data, wolves user data and the committees - let ctx_task = Arc::clone(&ctx); - tokio::spawn(async move { - loop { - println!("Update - Data - Start"); - - // get the data for each individual club/soc - get_wolves(&ctx_task).await; - - // get teh data for the clubs/socs committees - get_cns(&ctx_task).await; - - println!("Update - Data - End"); - tokio::time::sleep(Duration::from_secs(60 * 5)).await; - } - }); - } - - { - // this is to update member roles every 5 min - let ctx_task = Arc::clone(&ctx); - tokio::spawn(async move { - let db_lock = { - let data_read = ctx_task.data.read().await; - data_read.get::().expect("Expected Database in TypeMap.").clone() - }; - let db = db_lock.read().await; - - loop { - println!("Update - Users - Start"); - for server_config in get_server_config_bulk(&db).await { - normal::update_server(&ctx_task, &server_config, &[], &[]).await; - } - println!("Update - Users - End"); - tokio::time::sleep(Duration::from_secs(60 * 5)).await; - } - }); - } - - { - // this is to update committee roles every 5 min - let ctx_task = Arc::clone(&ctx); - tokio::spawn(async move { - loop { - println!("Update - Committee - Start"); - committee::check_committee(&ctx_task).await; - println!("Update - Committee - End"); - tokio::time::sleep(Duration::from_secs(60 * 5)).await; - } - }); - } - - { - // this updates teh server icon once a day - let ctx_task = Arc::clone(&ctx); - tokio::spawn(async move { - let db_lock = { - let data_read = ctx_task.data.read().await; - data_read.get::().expect("Expected Database in TypeMap.").clone() - }; - let db = db_lock.read().await; - let config_lock = { - let data_read = ctx.data.read().await; - data_read.get::().expect("Expected Config in TypeMap.").clone() - }; - - let config_global = config_lock.read().await; - let config_toml = get_config_icons::minimal(); - - loop { - println!("Update - Logo - Start"); - // even though this task will run every 5 min it will only actually change the icon when its a day old - if let Some(logo) = get_current_icon(&db).await { - let now = Utc::now(); - let yesterday = now.checked_sub_days(Days::new(1)).unwrap_or_default(); - if logo.date < yesterday.to_rfc3339_opts(SecondsFormat::Millis, true) { - update_icon::update_icon_main(&ctx, &db, &config_global, &config_toml).await; - } - } - println!("Update - Logo - End"); - tokio::time::sleep(Duration::from_secs(60 * 5)).await; - } - }); - } - - // Now that the loop is running, we set the bool to true - self.is_loop_running.swap(true, Ordering::Relaxed); - } - } - } - // handles previously linked accounts joining the server async fn guild_member_addition(&self, ctx: Context, new_member: Member) { let db_lock = { From 9d409e3692c8be39d7d98cccc18cd60f8bf8fa51 Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Mon, 21 Jul 2025 00:38:59 +0100 Subject: [PATCH 27/37] fmt: clippy and nightly fmt --- .rustfmt.toml | 2 +- src/bin/cleanup_committee.rs | 15 ++++++---- src/bin/update_committee.rs | 14 +++++---- src/bin/update_data.rs | 12 ++++---- src/bin/update_minecraft.rs | 10 +++++-- src/bin/update_server-icon.rs | 7 +++-- src/bin/update_users.rs | 16 ++++++---- src/commands/add_server.rs | 14 +++++---- src/commands/count.rs | 13 ++++---- src/commands/minecraft.rs | 56 +++++++++++++++++++++-------------- src/commands/role_adder.rs | 3 +- src/commands/server_icon.rs | 6 ++-- src/commands/wolves.rs | 28 +++++++++++------- src/common/database.rs | 19 +++++++----- src/common/minecraft.rs | 9 ++---- src/common/renderer.rs | 6 ++-- src/common/set_roles.rs | 49 ++++++++++++++++-------------- src/common/wolves.rs | 16 +++++----- src/lib.rs | 6 ++-- src/main.rs | 36 +++++++++------------- 20 files changed, 194 insertions(+), 143 deletions(-) diff --git a/.rustfmt.toml b/.rustfmt.toml index 6aeb30c..2b0831a 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -7,4 +7,4 @@ fn_params_layout = "Compressed" struct_lit_width = 0 tab_spaces = 2 use_small_heuristics = "Max" -#imports_granularity="Crate" \ No newline at end of file +imports_granularity = "Crate" \ No newline at end of file diff --git a/src/bin/cleanup_committee.rs b/src/bin/cleanup_committee.rs index cc68536..76f0526 100644 --- a/src/bin/cleanup_committee.rs +++ b/src/bin/cleanup_committee.rs @@ -1,14 +1,17 @@ -use serenity::all::{ChunkGuildFilter, GuildId, GuildMembersChunkEvent}; use serenity::{ + all::{ChunkGuildFilter, GuildId, GuildMembersChunkEvent}, async_trait, client::{Context, EventHandler}, - model::gateway::{GatewayIntents, Ready}, + model::gateway::GatewayIntents, Client, }; -use skynet_discord_bot::common::database::{db_init, DataBase}; - -use skynet_discord_bot::common::set_roles::committee::db_roles_get; -use skynet_discord_bot::{get_config, Config}; +use skynet_discord_bot::{ + common::{ + database::{db_init, DataBase}, + set_roles::committee::db_roles_get, + }, + get_config, Config, +}; use sqlx::{Pool, Sqlite}; use std::{process, sync::Arc}; use tokio::sync::RwLock; diff --git a/src/bin/update_committee.rs b/src/bin/update_committee.rs index e3e7277..ff263f6 100644 --- a/src/bin/update_committee.rs +++ b/src/bin/update_committee.rs @@ -1,13 +1,17 @@ -use serenity::all::{ChunkGuildFilter, GuildId, GuildMembersChunkEvent}; use serenity::{ + all::{ChunkGuildFilter, GuildId, GuildMembersChunkEvent}, async_trait, client::{Context, EventHandler}, - model::gateway::{GatewayIntents, Ready}, + model::gateway::GatewayIntents, Client, }; -use skynet_discord_bot::common::database::{db_init, DataBase}; -use skynet_discord_bot::common::set_roles::committee; -use skynet_discord_bot::{get_config, Config}; +use skynet_discord_bot::{ + common::{ + database::{db_init, DataBase}, + set_roles::committee, + }, + get_config, Config, +}; use std::{process, sync::Arc}; use tokio::sync::RwLock; diff --git a/src/bin/update_data.rs b/src/bin/update_data.rs index e67720e..902920e 100644 --- a/src/bin/update_data.rs +++ b/src/bin/update_data.rs @@ -1,14 +1,16 @@ -use serenity::all::{ChunkGuildFilter, GuildId}; use serenity::{ async_trait, client::{Context, EventHandler}, model::gateway::{GatewayIntents, Ready}, Client, }; -use skynet_discord_bot::common::database::{db_init, DataBase}; -use skynet_discord_bot::common::wolves::cns::get_wolves; -use skynet_discord_bot::common::wolves::committees::get_cns; -use skynet_discord_bot::{get_config, Config}; +use skynet_discord_bot::{ + common::{ + database::{db_init, DataBase}, + wolves::{cns::get_wolves, committees::get_cns}, + }, + get_config, Config, +}; use std::{process, sync::Arc}; use tokio::sync::RwLock; diff --git a/src/bin/update_minecraft.rs b/src/bin/update_minecraft.rs index f5d3634..f7c24e0 100644 --- a/src/bin/update_minecraft.rs +++ b/src/bin/update_minecraft.rs @@ -1,6 +1,10 @@ -use skynet_discord_bot::common::database::db_init; -use skynet_discord_bot::common::minecraft::{get_minecraft_config, update_server, whitelist_wipe}; -use skynet_discord_bot::get_config; +use skynet_discord_bot::{ + common::{ + database::db_init, + minecraft::{get_minecraft_config, update_server, whitelist_wipe}, + }, + get_config, +}; use std::collections::HashSet; #[tokio::main] diff --git a/src/bin/update_server-icon.rs b/src/bin/update_server-icon.rs index c59634e..ba9de80 100644 --- a/src/bin/update_server-icon.rs +++ b/src/bin/update_server-icon.rs @@ -1,13 +1,14 @@ -use serenity::all::{ChunkGuildFilter, GuildId}; use serenity::{ async_trait, client::{Context, EventHandler}, model::gateway::{GatewayIntents, Ready}, Client, }; -use skynet_discord_bot::common::server_icon::{get_config_icons, update_icon}; use skynet_discord_bot::{ - common::database::{db_init, DataBase}, + common::{ + database::{db_init, DataBase}, + server_icon::{get_config_icons, update_icon}, + }, get_config, Config, }; use std::{process, sync::Arc}; diff --git a/src/bin/update_users.rs b/src/bin/update_users.rs index 6ba99b0..c146a25 100644 --- a/src/bin/update_users.rs +++ b/src/bin/update_users.rs @@ -1,13 +1,17 @@ -use serenity::all::{ChunkGuildFilter, GuildId, GuildMembersChunkEvent}; use serenity::{ + all::{ChunkGuildFilter, GuildId, GuildMembersChunkEvent}, async_trait, client::{Context, EventHandler}, - model::gateway::{GatewayIntents, Ready}, + model::gateway::GatewayIntents, Client, }; -use skynet_discord_bot::common::database::{db_init, get_server_config_bulk, DataBase}; -use skynet_discord_bot::common::set_roles::normal; -use skynet_discord_bot::{get_config, Config}; +use skynet_discord_bot::{ + common::{ + database::{db_init, get_server_config_bulk, DataBase}, + set_roles::normal, + }, + get_config, Config, +}; use std::{process, sync::Arc}; use tokio::sync::RwLock; @@ -70,6 +74,6 @@ async fn check_bulk(ctx: &Context) { let db = db_lock.read().await; for server_config in get_server_config_bulk(&db).await { - normal::update_server(&ctx, &server_config, &[], &[]).await; + normal::update_server(ctx, &server_config, &[], &[]).await; } } diff --git a/src/commands/add_server.rs b/src/commands/add_server.rs index 387bd9e..63f3d49 100644 --- a/src/commands/add_server.rs +++ b/src/commands/add_server.rs @@ -1,8 +1,12 @@ -use serenity::all::{CommandDataOption, CommandDataOptionValue, CommandInteraction}; -use serenity::client::Context; -use skynet_discord_bot::common::database::{get_server_config, DataBase, Servers}; -use skynet_discord_bot::common::set_roles::normal::update_server; -use skynet_discord_bot::common::wolves::cns::get_wolves; +use serenity::{ + all::{CommandDataOption, CommandDataOptionValue, CommandInteraction}, + client::Context, +}; +use skynet_discord_bot::common::{ + database::{get_server_config, DataBase, Servers}, + set_roles::normal::update_server, + wolves::cns::get_wolves, +}; use sqlx::{Error, Pool, Sqlite}; pub async fn run(command: &CommandInteraction, ctx: &Context) -> String { diff --git a/src/commands/count.rs b/src/commands/count.rs index 678c9e0..2bed533 100644 --- a/src/commands/count.rs +++ b/src/commands/count.rs @@ -5,8 +5,7 @@ pub mod committee { use serenity::all::{ CommandDataOption, CommandDataOptionValue, CommandInteraction, CommandOptionType, Context, CreateCommand, CreateCommandOption, }; - use skynet_discord_bot::common::database::DataBase; - use skynet_discord_bot::common::set_roles::committee::db_roles_get; + use skynet_discord_bot::common::{database::DataBase, set_roles::committee::db_roles_get}; pub async fn run(command: &CommandInteraction, ctx: &Context) -> String { let sub_options = if let Some(CommandDataOption { @@ -85,9 +84,13 @@ pub mod servers { // get the list of all the current clubs/socs use serde::{Deserialize, Serialize}; use serenity::all::{CommandInteraction, CommandOptionType, Context, CreateCommand, CreateCommandOption}; - use skynet_discord_bot::common::database::{get_server_config_bulk, DataBase}; - use skynet_discord_bot::common::set_roles::committee::get_committees; - use skynet_discord_bot::get_now_iso; + use skynet_discord_bot::{ + common::{ + database::{get_server_config_bulk, DataBase}, + set_roles::committee::get_committees, + }, + get_now_iso, + }; use sqlx::{Pool, Sqlite}; use std::collections::HashMap; diff --git a/src/commands/minecraft.rs b/src/commands/minecraft.rs index ca395c6..f3a050d 100644 --- a/src/commands/minecraft.rs +++ b/src/commands/minecraft.rs @@ -9,11 +9,17 @@ pub(crate) mod user { use super::*; use crate::commands::wolves::link::get_server_member_discord; use serde::{Deserialize, Serialize}; - use serenity::all::{CommandDataOption, CommandDataOptionValue, CommandInteraction}; - use serenity::model::id::UserId; - use skynet_discord_bot::common::database::Wolves; - use skynet_discord_bot::common::minecraft::{whitelist_update, Minecraft}; - use skynet_discord_bot::Config; + use serenity::{ + all::{CommandDataOption, CommandDataOptionValue, CommandInteraction}, + model::id::UserId, + }; + use skynet_discord_bot::{ + common::{ + database::Wolves, + minecraft::{whitelist_update, Minecraft}, + }, + Config, + }; use sqlx::Error; pub async fn run(command: &CommandInteraction, ctx: &Context) -> String { @@ -185,14 +191,17 @@ pub(crate) mod server { use super::*; pub(crate) mod add { - use serenity::all::{CommandDataOption, CommandDataOptionValue, CommandInteraction, CommandOptionType, CreateCommand, CreateCommandOption}; - use serenity::model::id::GuildId; + use serenity::{ + all::{CommandDataOption, CommandDataOptionValue, CommandInteraction, CommandOptionType, CreateCommand, CreateCommandOption}, + model::id::GuildId, + }; use sqlx::Error; // this is to managfe the server side of commands related to minecraft use super::*; - use skynet_discord_bot::common::minecraft::update_server; - use skynet_discord_bot::common::minecraft::Minecraft; - use skynet_discord_bot::Config; + use skynet_discord_bot::{ + common::minecraft::{update_server, Minecraft}, + Config, + }; pub fn register() -> CreateCommand { CreateCommand::new("minecraft_add") @@ -260,12 +269,14 @@ pub(crate) mod server { } pub(crate) mod list { - use serenity::all::CommandInteraction; - use serenity::builder::CreateCommand; - use serenity::client::Context; - use skynet_discord_bot::common::database::DataBase; - use skynet_discord_bot::common::minecraft::{get_minecraft_config_server, server_information}; - use skynet_discord_bot::Config; + use serenity::{all::CommandInteraction, builder::CreateCommand, client::Context}; + use skynet_discord_bot::{ + common::{ + database::DataBase, + minecraft::{get_minecraft_config_server, server_information}, + }, + Config, + }; pub fn register() -> CreateCommand { CreateCommand::new("minecraft_list") @@ -320,12 +331,13 @@ pub(crate) mod server { } pub(crate) mod delete { - use serenity::all::{CommandDataOption, CommandDataOptionValue, CommandInteraction, CommandOptionType, CreateCommandOption}; - use serenity::builder::CreateCommand; - use serenity::client::Context; - use serenity::model::id::GuildId; - use skynet_discord_bot::common::database::DataBase; - use skynet_discord_bot::common::minecraft::Minecraft; + use serenity::{ + all::{CommandDataOption, CommandDataOptionValue, CommandInteraction, CommandOptionType, CreateCommandOption}, + builder::CreateCommand, + client::Context, + model::id::GuildId, + }; + use skynet_discord_bot::common::{database::DataBase, minecraft::Minecraft}; use sqlx::{Error, Pool, Sqlite}; pub fn register() -> CreateCommand { diff --git a/src/commands/role_adder.rs b/src/commands/role_adder.rs index f58803b..20928ba 100644 --- a/src/commands/role_adder.rs +++ b/src/commands/role_adder.rs @@ -142,8 +142,7 @@ pub mod edit { pub mod list {} pub mod tools { - use serenity::client::Context; - use serenity::model::guild::Member; + use serenity::{client::Context, model::guild::Member}; use skynet_discord_bot::common::database::RoleAdder; use sqlx::{Pool, Sqlite}; diff --git a/src/commands/server_icon.rs b/src/commands/server_icon.rs index 59d755f..2989c42 100644 --- a/src/commands/server_icon.rs +++ b/src/commands/server_icon.rs @@ -113,8 +113,10 @@ pub(crate) mod user { pub(crate) mod festival { use serenity::all::{CommandInteraction, Context}; - use skynet_discord_bot::common::server_icon::{get_config_icons, update_icon::get_festival}; - use skynet_discord_bot::Config; + use skynet_discord_bot::{ + common::server_icon::{get_config_icons, update_icon::get_festival}, + Config, + }; // use this to return what current festivals are active? pub async fn run(_command: &CommandInteraction, ctx: &Context) -> String { diff --git a/src/commands/wolves.rs b/src/commands/wolves.rs index d78454b..f137622 100644 --- a/src/commands/wolves.rs +++ b/src/commands/wolves.rs @@ -4,11 +4,16 @@ use lettre::{ Message, SmtpTransport, Transport, }; use maud::html; -use serenity::all::CommandOptionType; -use serenity::builder::CreateCommandOption; -use serenity::{builder::CreateCommand, client::Context, model::id::UserId}; -use skynet_discord_bot::common::database::{DataBase, Wolves, WolvesVerify}; -use skynet_discord_bot::{get_now_iso, random_string, Config}; +use serenity::{ + all::CommandOptionType, + builder::{CreateCommand, CreateCommandOption}, + client::Context, + model::id::UserId, +}; +use skynet_discord_bot::{ + common::database::{DataBase, Wolves, WolvesVerify}, + get_now_iso, random_string, Config, +}; use sqlx::{Pool, Sqlite}; pub mod link { @@ -298,11 +303,14 @@ pub mod link_docs { pub mod verify { use super::*; use crate::commands::wolves::link::{db_pending_clear_expired, get_server_member_discord, get_verify_from_db}; - use serenity::all::{CommandDataOption, CommandDataOptionValue, CommandInteraction}; - use serenity::model::user::User; - use skynet_discord_bot::common::database::get_server_config; - use skynet_discord_bot::common::database::{ServerMembersWolves, Servers}; - use skynet_discord_bot::common::wolves::committees::Committees; + use serenity::{ + all::{CommandDataOption, CommandDataOptionValue, CommandInteraction}, + model::user::User, + }; + use skynet_discord_bot::common::{ + database::{get_server_config, ServerMembersWolves, Servers}, + wolves::committees::Committees, + }; use sqlx::Error; pub async fn run(command: &CommandInteraction, ctx: &Context) -> String { diff --git a/src/common/database.rs b/src/common/database.rs index 0663799..190baf2 100644 --- a/src/common/database.rs +++ b/src/common/database.rs @@ -1,12 +1,17 @@ use crate::Config; use serde::{Deserialize, Serialize}; -use serenity::model::guild; -use serenity::model::id::{ChannelId, GuildId, RoleId, UserId}; -use serenity::prelude::TypeMapKey; -use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions, SqliteRow}; -use sqlx::{Error, FromRow, Pool, Row, Sqlite}; -use std::str::FromStr; -use std::sync::Arc; +use serenity::{ + model::{ + guild, + id::{ChannelId, GuildId, RoleId, UserId}, + }, + prelude::TypeMapKey, +}; +use sqlx::{ + sqlite::{SqliteConnectOptions, SqlitePoolOptions, SqliteRow}, + Error, FromRow, Pool, Row, Sqlite, +}; +use std::{str::FromStr, sync::Arc}; use tokio::sync::RwLock; pub struct DataBase; diff --git a/src/common/minecraft.rs b/src/common/minecraft.rs index 4faa8ed..b7362e6 100644 --- a/src/common/minecraft.rs +++ b/src/common/minecraft.rs @@ -1,10 +1,7 @@ -use crate::common::set_roles::normal::get_server_member_bulk; -use crate::Config; -use serde::de::DeserializeOwned; -use serde::{Deserialize, Serialize}; +use crate::{common::set_roles::normal::get_server_member_bulk, Config}; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serenity::model::id::GuildId; -use sqlx::sqlite::SqliteRow; -use sqlx::{Error, FromRow, Pool, Row, Sqlite}; +use sqlx::{sqlite::SqliteRow, Error, FromRow, Pool, Row, Sqlite}; #[derive(Debug, Clone, Deserialize, Serialize)] pub struct Minecraft { diff --git a/src/common/renderer.rs b/src/common/renderer.rs index f99d891..e105c16 100644 --- a/src/common/renderer.rs +++ b/src/common/renderer.rs @@ -1,8 +1,10 @@ // this code is taken from https://github.com/MCorange99/svg2colored-png/tree/main // I was unable to figure out how to use usvg myself so younked it from here. -use std::ffi::OsStr; -use std::path::{Path, PathBuf}; +use std::{ + ffi::OsStr, + path::{Path, PathBuf}, +}; // use clap::builder::OsStr; use color_eyre::{eyre::bail, Result}; diff --git a/src/common/set_roles.rs b/src/common/set_roles.rs index fbbc828..3a894ee 100644 --- a/src/common/set_roles.rs +++ b/src/common/set_roles.rs @@ -1,8 +1,12 @@ pub mod normal { - use crate::common::database::{DataBase, ServerMembersWolves, Servers, Wolves}; - use crate::get_now_iso; - use serenity::client::Context; - use serenity::model::id::{GuildId, RoleId, UserId}; + use crate::{ + common::database::{DataBase, ServerMembersWolves, Servers, Wolves}, + get_now_iso, + }; + use serenity::{ + client::Context, + model::id::{GuildId, RoleId, UserId}, + }; use sqlx::{Pool, Sqlite}; struct RolesChange { @@ -152,21 +156,22 @@ pub mod normal { // for updating committee members pub mod committee { - use crate::common::database::{get_channel_from_row, get_role_from_row, DataBase, Wolves}; - use crate::common::wolves::committees::Committees; - use crate::Config; + use crate::{ + common::{ + database::{get_channel_from_row, get_role_from_row, DataBase, Wolves}, + wolves::committees::Committees, + }, + Config, + }; use serde::{Deserialize, Serialize}; - use serenity::all::EditRole; - use serenity::builder::CreateChannel; - use serenity::client::Context; - use serenity::model::channel::ChannelType; - use serenity::model::guild::Member; - use serenity::model::id::ChannelId; - use serenity::model::prelude::RoleId; - use sqlx::sqlite::SqliteRow; - use sqlx::{Error, FromRow, Pool, Row, Sqlite}; + use serenity::{ + all::EditRole, + builder::CreateChannel, + client::Context, + model::{channel::ChannelType, guild::Member, id::ChannelId, prelude::RoleId}, + }; + use sqlx::{sqlite::SqliteRow, Error, FromRow, Pool, Row, Sqlite}; use std::collections::HashMap; - use std::sync::Arc; pub async fn check_committee(ctx: &Context) { let db_lock = { @@ -187,7 +192,7 @@ pub mod committee { // because to use it to update a single user we need to pre-get the members of teh server let mut members = server.members(&ctx, None, None).await.unwrap_or_default(); - update_committees(&db, &ctx, &config_global, &mut members).await; + update_committees(&db, ctx, &config_global, &mut members).await; } /** @@ -342,11 +347,11 @@ pub mod committee { for role in &roles_current { roles_current_id.push(role.id.to_owned()); if !roles_required.contains(&role.id) { - if role.id == committee_member { - if !on_committee { - roles_rem.push(role.id.to_owned()); - } + if role.id == committee_member && on_committee { + continue; } + + roles_rem.push(role.id.to_owned()); } } diff --git a/src/common/wolves.rs b/src/common/wolves.rs index e199ad2..7ee71df 100644 --- a/src/common/wolves.rs +++ b/src/common/wolves.rs @@ -48,11 +48,14 @@ async fn add_users_wolves(db: &Pool, user: &WolvesResultUserMin) { This is getting data for Clubs and Socs */ pub mod cns { - use crate::common::database::{get_server_config_bulk, DataBase, ServerMembers, ServerMembersWolves, Servers}; - use crate::common::wolves::{add_users_wolves, WolvesResultUserMin}; - use crate::Config; - use serenity::client::Context; - use serenity::model::id::GuildId; + use crate::{ + common::{ + database::{get_server_config_bulk, DataBase, ServerMembers, ServerMembersWolves, Servers}, + wolves::{add_users_wolves, WolvesResultUserMin}, + }, + Config, + }; + use serenity::{client::Context, model::id::GuildId}; use sqlx::{Pool, Sqlite}; use std::collections::BTreeMap; @@ -191,8 +194,7 @@ pub mod cns { Get and store the data on C&S committees */ pub mod committees { - use crate::common::database::DataBase; - use crate::Config; + use crate::{common::database::DataBase, Config}; use serenity::client::Context; use sqlx::{Pool, Sqlite}; diff --git a/src/lib.rs b/src/lib.rs index 734fa2c..75c9d78 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,8 +3,10 @@ pub mod common; use chrono::{Datelike, SecondsFormat, Utc}; use dotenvy::dotenv; use rand::{distr::Alphanumeric, rng, Rng}; -use serenity::model::id::{ChannelId, GuildId, RoleId}; -use serenity::prelude::TypeMapKey; +use serenity::{ + model::id::{ChannelId, GuildId, RoleId}, + prelude::TypeMapKey, +}; use std::{env, sync::Arc}; use tokio::sync::RwLock; diff --git a/src/main.rs b/src/main.rs index e76bd34..c0bddb3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,39 +1,33 @@ pub mod commands; use crate::commands::role_adder::tools::on_role_change; -use crate::commands::server_icon::user::current::icon::get_current_icon; -use chrono::{Days, SecondsFormat, TimeDelta, Utc}; -use serenity::all::{ - ActivityData, Command, CommandDataOptionValue, CreateAttachment, CreateMessage, EditInteractionResponse, GuildId, GuildMemberUpdateEvent, - GuildMembersChunkEvent, Interaction, -}; use serenity::{ + all::{Command, CommandDataOptionValue, CreateMessage, EditInteractionResponse, Interaction}, async_trait, client::{Context, EventHandler}, - gateway::ChunkGuildFilter, + gateway::{ActivityData, ChunkGuildFilter}, model::{ + event::GuildMemberUpdateEvent, gateway::{GatewayIntents, Ready}, guild::Member, + id::GuildId, user::OnlineStatus, }, Client, }; -use skynet_discord_bot::common::database::{db_init, get_server_config, get_server_config_bulk, get_server_member, DataBase}; -use skynet_discord_bot::common::server_icon::{get_config_icons, update_icon}; -use skynet_discord_bot::common::set_roles::committee::update_committees; -use skynet_discord_bot::common::set_roles::{committee, normal}; -use skynet_discord_bot::common::wolves::cns::get_wolves; -use skynet_discord_bot::common::wolves::committees::{get_cns, Committees}; -use skynet_discord_bot::{get_config, Config}; +use skynet_discord_bot::{ + common::{ + database::{db_init, get_server_config, get_server_member, DataBase}, + set_roles::committee::update_committees, + wolves::committees::Committees, + }, + get_config, Config, +}; use sqlx::{Pool, Sqlite}; -use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; -use std::time::Duration; use tokio::sync::RwLock; -struct Handler { - is_loop_running: AtomicBool, -} +struct Handler; #[async_trait] impl EventHandler for Handler { @@ -301,9 +295,7 @@ async fn main() { let intents = GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::GUILD_MEMBERS; // Build our client. let mut client = Client::builder(&config.discord_token, intents) - .event_handler(Handler { - is_loop_running: AtomicBool::new(false), - }) + .event_handler(Handler) .cache_settings(serenity::cache::Settings::default()) .await .expect("Error creating client"); From d0726169ee106d2da49f3960a82c86ebb481290b Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Mon, 21 Jul 2025 00:50:20 +0100 Subject: [PATCH 28/37] clippy: changes from nightly clippy all of this is embeding teh var into teh format macro --- src/bin/cleanup_committee.rs | 2 +- src/bin/update_committee.rs | 2 +- src/bin/update_data.rs | 2 +- src/bin/update_server-icon.rs | 2 +- src/bin/update_users.rs | 2 +- src/commands/add_server.rs | 4 ++-- src/commands/count.rs | 4 ++-- src/commands/minecraft.rs | 8 ++++---- src/commands/role_adder.rs | 12 ++++++------ src/commands/server_icon.rs | 2 +- src/commands/wolves.rs | 10 +++++----- src/common/database.rs | 2 +- src/common/minecraft.rs | 2 +- src/common/renderer.rs | 2 +- src/common/set_roles.rs | 14 +++++++------- src/common/wolves.rs | 12 ++++++------ src/main.rs | 12 ++++++------ 17 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/bin/cleanup_committee.rs b/src/bin/cleanup_committee.rs index 76f0526..c6485a7 100644 --- a/src/bin/cleanup_committee.rs +++ b/src/bin/cleanup_committee.rs @@ -45,7 +45,7 @@ async fn main() { } if let Err(why) = client.start().await { - println!("Client error: {:?}", why); + println!("Client error: {why:?}"); } } diff --git a/src/bin/update_committee.rs b/src/bin/update_committee.rs index ff263f6..b2792e0 100644 --- a/src/bin/update_committee.rs +++ b/src/bin/update_committee.rs @@ -40,7 +40,7 @@ async fn main() { } if let Err(why) = client.start().await { - println!("Client error: {:?}", why); + println!("Client error: {why:?}"); } } diff --git a/src/bin/update_data.rs b/src/bin/update_data.rs index 902920e..8f73ce9 100644 --- a/src/bin/update_data.rs +++ b/src/bin/update_data.rs @@ -42,7 +42,7 @@ async fn main() { } if let Err(why) = client.start().await { - println!("Client error: {:?}", why); + println!("Client error: {why:?}"); } } diff --git a/src/bin/update_server-icon.rs b/src/bin/update_server-icon.rs index ba9de80..56957da 100644 --- a/src/bin/update_server-icon.rs +++ b/src/bin/update_server-icon.rs @@ -39,7 +39,7 @@ async fn main() { } if let Err(why) = client.start().await { - println!("Client error: {:?}", why); + println!("Client error: {why:?}"); } } diff --git a/src/bin/update_users.rs b/src/bin/update_users.rs index c146a25..6ac9e00 100644 --- a/src/bin/update_users.rs +++ b/src/bin/update_users.rs @@ -40,7 +40,7 @@ async fn main() { } if let Err(why) = client.start().await { - println!("Client error: {:?}", why); + println!("Client error: {why:?}"); } } diff --git a/src/commands/add_server.rs b/src/commands/add_server.rs index 63f3d49..0c7dd2f 100644 --- a/src/commands/add_server.rs +++ b/src/commands/add_server.rs @@ -76,8 +76,8 @@ pub async fn run(command: &CommandInteraction, ctx: &Context) -> String { match add_server(&db, ctx, &server_data).await { Ok(_) => {} Err(e) => { - println!("{:?}", e); - return format!("Failure to insert into Servers {:?}", server_data); + println!("{e:?}"); + return format!("Failure to insert into Servers {server_data:?}"); } } diff --git a/src/commands/count.rs b/src/commands/count.rs index 2bed533..8a64ee7 100644 --- a/src/commands/count.rs +++ b/src/commands/count.rs @@ -52,7 +52,7 @@ pub mod committee { for (count, name) in cs { let leading = if count < 10 { " " } else { "" }; - let line = format!("{}{} {}", leading, count, name); + let line = format!("{leading}{count} {name}"); let length = line.len() + 1; @@ -146,7 +146,7 @@ pub mod servers { "" }; - let line = format!("{}{} {}{} {}", current_leading, current, past_leading, past, name); + let line = format!("{current_leading}{current} {past_leading}{past} {name}"); let length = line.len() + 1; diff --git a/src/commands/minecraft.rs b/src/commands/minecraft.rs index f3a050d..a4d1b1b 100644 --- a/src/commands/minecraft.rs +++ b/src/commands/minecraft.rs @@ -75,14 +75,14 @@ pub(crate) mod user { Ok(_) => {} Err(e) => { dbg!("{:?}", e); - return format!("Failure to minecraft username {:?}", username); + return format!("Failure to minecraft username {username:?}"); } } username_mc = username.to_string(); } else { match get_minecraft_bedrock(username, &config.minecraft_mcprofile).await { None => { - return format!("No UID found for {:?}", username); + return format!("No UID found for {username:?}"); } Some(x) => { match add_minecraft_bedrock(&db, &command.user.id, &x.floodgateuid).await { @@ -238,7 +238,7 @@ pub(crate) mod server { match add_server(&db, &g_id, &server_minecraft).await { Ok(_) => {} Err(e) => { - println!("{:?}", e); + println!("{e:?}"); return format!("Failure to insert into Minecraft {} {}", &g_id, &server_minecraft); } } @@ -375,7 +375,7 @@ pub(crate) mod server { match server_remove(&db, &g_id, &server_minecraft).await { Ok(_) => {} Err(e) => { - println!("{:?}", e); + println!("{e:?}"); return format!("Failure to insert into Minecraft {} {}", &g_id, &server_minecraft); } } diff --git a/src/commands/role_adder.rs b/src/commands/role_adder.rs index 20928ba..e60ac83 100644 --- a/src/commands/role_adder.rs +++ b/src/commands/role_adder.rs @@ -79,8 +79,8 @@ pub mod edit { match add_server(&db, &server_data, delete).await { Ok(_) => {} Err(e) => { - println!("{:?}", e); - return format!("Failure to insert into Servers {:?}", server_data); + println!("{e:?}"); + return format!("Failure to insert into Servers {server_data:?}"); } } @@ -101,9 +101,9 @@ pub mod edit { } if delete { - format!("Removed {} + {} = {}", role_a_name, role_b_name, role_c_name) + format!("Removed {role_a_name} + {role_b_name} = {role_c_name}") } else { - format!("Added {} + {} = {}", role_a_name, role_b_name, role_c_name) + format!("Added {role_a_name} + {role_b_name} = {role_c_name}") } } @@ -179,13 +179,13 @@ pub mod tools { if !roles_add.is_empty() { if let Err(e) = new_data.add_roles(&ctx, &roles_add).await { - println!("{:?}", e); + println!("{e:?}"); } } if !roles_remove.is_empty() { if let Err(e) = new_data.remove_roles(&ctx, &roles_remove).await { - println!("{:?}", e); + println!("{e:?}"); } } } diff --git a/src/commands/server_icon.rs b/src/commands/server_icon.rs index 2989c42..0cba1b1 100644 --- a/src/commands/server_icon.rs +++ b/src/commands/server_icon.rs @@ -207,7 +207,7 @@ pub(crate) mod user { // the `` is so that the numbers will be rendered in monospaced font // the <> is to suppress the URL embed - let line = format!("``{}{}`` [{}](<{}>)", current_leading, times, name, url); + let line = format!("``{current_leading}{times}`` [{name}](<{url}>)"); let length = line.len() + 1; diff --git a/src/commands/wolves.rs b/src/commands/wolves.rs index f137622..dc40ad0 100644 --- a/src/commands/wolves.rs +++ b/src/commands/wolves.rs @@ -115,7 +115,7 @@ pub mod link { } } - format!("Verification email sent to {}, it may take up to 15 min for it to arrive. If it takes longer check the Junk folder.", email) + format!("Verification email sent to {email}, it may take up to 15 min for it to arrive. If it takes longer check the Junk folder.") } pub async fn get_server_member_discord(db: &Pool, user: &UserId) -> Option { @@ -365,12 +365,12 @@ pub mod verify { "Discord username linked to Wolves".to_string() } Err(e) => { - println!("{:?}", e); + println!("{e:?}"); "Failed to save, please try /link_wolves again".to_string() } }; } - Err(e) => println!("{:?}", e), + Err(e) => println!("{e:?}"), } "Failed to verify".to_string() @@ -427,7 +427,7 @@ pub mod verify { } if let Err(e) = member.add_roles(&ctx, &roles).await { - println!("{:?}", e); + println!("{e:?}"); } } } @@ -443,7 +443,7 @@ pub mod verify { WHERE committee LIKE ?1 "#, ) - .bind(format!("%{}%", wolves_id)) + .bind(format!("%{wolves_id}%")) .fetch_all(db) .await .unwrap_or_else(|e| { diff --git a/src/common/database.rs b/src/common/database.rs index 190baf2..0c18668 100644 --- a/src/common/database.rs +++ b/src/common/database.rs @@ -225,7 +225,7 @@ pub async fn db_init(config: &Config) -> Result, Error> { let pool = SqlitePoolOptions::new() .max_connections(5) .connect_with( - SqliteConnectOptions::from_str(&format!("sqlite://{}", database))? + SqliteConnectOptions::from_str(&format!("sqlite://{database}"))? .foreign_keys(true) .create_if_missing(true), ) diff --git a/src/common/minecraft.rs b/src/common/minecraft.rs index b7362e6..60f7820 100644 --- a/src/common/minecraft.rs +++ b/src/common/minecraft.rs @@ -152,7 +152,7 @@ pub async fn get_minecraft_config_server(db: &Pool, g_id: GuildId) -> Ve } pub async fn whitelist_update(add: &Vec<(String, bool)>, server: &str, token: &str) { - println!("Update whitelist for {}", server); + println!("Update whitelist for {server}"); let url_base = format!("https://panel.games.skynet.ie/api/client/servers/{server}"); let bearer = format!("Bearer {token}"); diff --git a/src/common/renderer.rs b/src/common/renderer.rs index e105c16..97e73a0 100644 --- a/src/common/renderer.rs +++ b/src/common/renderer.rs @@ -179,7 +179,7 @@ impl Renderer { } fn set_color(&self, svg: &str, color: &String) -> String { - svg.replace("fill=\"currentColor\"", &format!("fill=\"#{}\"", color)) + svg.replace("fill=\"currentColor\"", &format!("fill=\"#{color}\"")) } fn get_svg_data(&self, fi: &Path) -> Result { diff --git a/src/common/set_roles.rs b/src/common/set_roles.rs index 3a894ee..6352c24 100644 --- a/src/common/set_roles.rs +++ b/src/common/set_roles.rs @@ -71,7 +71,7 @@ pub mod normal { } if let Err(e) = member.add_roles(ctx, &roles).await { - println!("{:?}", e); + println!("{e:?}"); } } else { // old and never @@ -86,13 +86,13 @@ pub mod normal { roles_set.current_rem += 1; // if theya re not a current member and have the role then remove it if let Err(e) = member.remove_role(ctx, role_current).await { - println!("{:?}", e); + println!("{e:?}"); } } } for role in remove_roles.iter().flatten() { if let Err(e) = member.remove_role(ctx, role).await { - println!("{:?}", e); + println!("{e:?}"); } } } @@ -148,7 +148,7 @@ pub mod normal { Ok(_) => {} Err(e) => { println!("Failure to insert into {}", server.get()); - println!("{:?}", e); + println!("{e:?}"); } } } @@ -471,8 +471,8 @@ pub mod committee { { Ok(_) => {} Err(e) => { - println!("Failure to insert into Wolves {:?}", role); - println!("{:?}", e); + println!("Failure to insert into Wolves {role:?}"); + println!("{e:?}"); } } } @@ -489,7 +489,7 @@ pub mod committee { .await .unwrap_or_else(|e| { println!("Failure to get Roles from committee_roles"); - println!("{:?}", e); + println!("{e:?}"); vec![] }) } diff --git a/src/common/wolves.rs b/src/common/wolves.rs index 7ee71df..17305f6 100644 --- a/src/common/wolves.rs +++ b/src/common/wolves.rs @@ -38,8 +38,8 @@ async fn add_users_wolves(db: &Pool, user: &WolvesResultUserMin) { { Ok(_) => {} Err(e) => { - println!("Failure to insert into Wolves {:?}", user); - println!("{:?}", e); + println!("Failure to insert into Wolves {user:?}"); + println!("{e:?}"); } } } @@ -145,7 +145,7 @@ pub mod cns { Ok(_) => {} Err(e) => { println!("Failure to set server name {}", server.get()); - println!("{:?}", e); + println!("{e:?}"); } } } @@ -184,7 +184,7 @@ pub mod cns { Ok(_) => {} Err(e) => { println!("Failure to insert into ServerMembers {} {:?}", server.get(), user); - println!("{:?}", e); + println!("{e:?}"); } } } @@ -263,8 +263,8 @@ pub mod committees { { Ok(_) => {} Err(e) => { - println!("Failure to insert into Committees {:?}", committee); - println!("{:?}", e); + println!("Failure to insert into Committees {committee:?}"); + println!("{e:?}"); } } } diff --git a/src/main.rs b/src/main.rs index c0bddb3..6a87f84 100644 --- a/src/main.rs +++ b/src/main.rs @@ -81,7 +81,7 @@ impl EventHandler for Handler { } if let Err(e) = new_member.add_roles(&ctx, &roles).await { - println!("{:?}", e); + println!("{e:?}"); } } else { let tmp = get_committee(&db, config_server.wolves_id).await; @@ -146,7 +146,7 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use { Ok(_) => {} Err(e) => { - println!("{:?}", e) + println!("{e:?}") } } @@ -154,7 +154,7 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use match config.committee_server.set_commands(&ctx.http, vec![commands::count::committee::register()]).await { Ok(_) => {} Err(e) => { - println!("{:?}", e) + println!("{e:?}") } } @@ -173,7 +173,7 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use { Ok(_) => {} Err(e) => { - println!("{:?}", e) + println!("{e:?}") } } } @@ -260,7 +260,7 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use }; if let Err(why) = command.edit_response(&ctx.http, EditInteractionResponse::new().content(content)).await { - println!("Cannot respond to slash command: {}", why); + println!("Cannot respond to slash command: {why}"); } } } @@ -312,6 +312,6 @@ async fn main() { // Shards will automatically attempt to reconnect, and will perform // exponential backoff until it reconnects. if let Err(why) = client.start().await { - println!("Client error: {:?}", why); + println!("Client error: {why:?}"); } } From 854e946a8fd692e1ed1eaca15b1805d0a90e5d35 Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Mon, 21 Jul 2025 00:59:48 +0100 Subject: [PATCH 29/37] ci: improve the pipeline to test for the full suite ci: dont pull in the lfs for teh PR pipeline build ci: checkout without LFS ci: see if using the ref directly will help ci: test a slight modification ci: see if new get ldfs script works ci: test using teh new v8 --- .forgejo/workflows/check_lfs.yaml | 2 -- .forgejo/workflows/on_pr.yaml | 51 +++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 .forgejo/workflows/on_pr.yaml diff --git a/.forgejo/workflows/check_lfs.yaml b/.forgejo/workflows/check_lfs.yaml index dca575c..aaa2117 100644 --- a/.forgejo/workflows/check_lfs.yaml +++ b/.forgejo/workflows/check_lfs.yaml @@ -1,9 +1,7 @@ on: - - pull_request - push - workflow_dispatch - jobs: check_lfs: # nix/docker diff --git a/.forgejo/workflows/on_pr.yaml b/.forgejo/workflows/on_pr.yaml new file mode 100644 index 0000000..d17dc47 --- /dev/null +++ b/.forgejo/workflows/on_pr.yaml @@ -0,0 +1,51 @@ +on: + - pull_request + +jobs: + check_lfs: + # nix/docker + runs-on: nix + steps: + - uses: https://github.com/MPLew-is/lfs-check-action@1 + + # rust code must be formatted for standardisation + lint_fmt: + # build it using teh base nixos system, helps with caching + runs-on: nix + steps: + # get the repo first + - uses: https://code.forgejo.org/actions/checkout@v4 + - uses: https://forgejo.skynet.ie/Skynet/actions/get_lfs/nix@v8 + with: + server_url: ${{ gitea.server_url }} + repository: ${{ gitea.repository }} + - run: nix build .#fmt --verbose + + # clippy is incredibly useful for making yer code better + lint_clippy: + # build it using teh base nixos system, helps with caching + runs-on: nix + permissions: + checks: write + steps: + # get the repo first + - uses: https://code.forgejo.org/actions/checkout@v4 + - uses: https://forgejo.skynet.ie/Skynet/actions/get_lfs/nix@v8 + with: + server_url: ${{ gitea.server_url }} + repository: ${{ gitea.repository }} + - run: nix build .#clippy --verbose + + build: + # build it using teh base nixos system, helps with caching + runs-on: nix + needs: [ lint_fmt, lint_clippy ] + steps: + # get the repo first + - uses: https://code.forgejo.org/actions/checkout@v4 + - uses: https://forgejo.skynet.ie/Skynet/actions/get_lfs/nix@v8 + with: + server_url: ${{ gitea.server_url }} + repository: ${{ gitea.repository }} + - name: "Build it locally" + run: nix build --verbose From 095ff6f2cea5b3d35880d4a55b60930b60e3efcb Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Mon, 21 Jul 2025 02:51:33 +0100 Subject: [PATCH 30/37] fix: better handling of returning teh committees --- src/commands/count.rs | 6 ++++-- src/common/set_roles.rs | 26 +++++++++++++++++++------- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/commands/count.rs b/src/commands/count.rs index 8a64ee7..2368bca 100644 --- a/src/commands/count.rs +++ b/src/commands/count.rs @@ -102,8 +102,10 @@ pub mod servers { let db = db_lock.read().await; let mut committees = HashMap::new(); - for committee in get_committees(&db).await { - committees.insert(committee.id, committee.to_owned()); + if let Some(x) = get_committees(&db).await { + for committee in x { + committees.insert(committee.id, committee.to_owned()); + } } let mut cs = vec![]; diff --git a/src/common/set_roles.rs b/src/common/set_roles.rs index 6352c24..6e71992 100644 --- a/src/common/set_roles.rs +++ b/src/common/set_roles.rs @@ -201,7 +201,12 @@ pub mod committee { pub async fn update_committees(db: &Pool, ctx: &Context, config: &Config, members: &mut Vec) { let server = config.committee_server; let committee_member = config.committee_role; - let committees = get_committees(db).await; + let committees = match get_committees(db).await { + None => { + return; + } + Some(x) => x, + }; let categories = config.committee_category.clone(); // information about the server @@ -328,6 +333,10 @@ pub mod committee { // now we have a map of all users that should get roles time to go through all the folks on teh server for member in members { + // if member.user.id != 136522490632601600 { + // continue; + // } + // let roles_current = member.roles(ctx).unwrap_or_default(); let roles_required = match users_roles.get(&member.user.id) { @@ -494,8 +503,8 @@ pub mod committee { }) } - pub async fn get_committees(db: &Pool) -> Vec { - sqlx::query_as::<_, Committees>( + pub async fn get_committees(db: &Pool) -> Option> { + match sqlx::query_as::<_, Committees>( r#" SELECT * FROM committees @@ -503,10 +512,13 @@ pub mod committee { ) .fetch_all(db) .await - .unwrap_or_else(|e| { - dbg!(e); - vec![] - }) + { + Ok(x) => Some(x), + Err(e) => { + dbg!(e); + None + } + } } async fn get_server_member_discord(db: &Pool, user: &i64) -> Option { From a225c14b4fdaafe390dc8840065946d8c2a2e4b8 Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Mon, 21 Jul 2025 04:29:03 +0100 Subject: [PATCH 31/37] fix: was ddossing the poor database guild_members_chunk is triggered for each chunk for each server it is on, and the bot is currently in 10 servers so it was runnign teh same thigns 10 times, clogging up conenctions --- src/bin/cleanup_committee.rs | 18 +++++++++++++----- src/bin/update_committee.rs | 18 +++++++++++++----- src/bin/update_users.rs | 27 ++++++++++++++++++++------- 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/src/bin/cleanup_committee.rs b/src/bin/cleanup_committee.rs index c6485a7..188cc5b 100644 --- a/src/bin/cleanup_committee.rs +++ b/src/bin/cleanup_committee.rs @@ -52,15 +52,23 @@ async fn main() { struct Handler; #[async_trait] impl EventHandler for Handler { - async fn cache_ready(&self, ctx: Context, guilds: Vec) { - for guild in guilds { - ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None); - } - println!("Cache built successfully!"); + async fn cache_ready(&self, ctx: Context, _guilds: Vec) { + let config_lock = { + let data_read = ctx.data.read().await; + data_read.get::().expect("Expected Config in TypeMap.").clone() + }; + let config_global = config_lock.read().await; + + let server = config_global.committee_server; + + ctx.shard.chunk_guild(server, Some(2000), false, ChunkGuildFilter::None, None); + + println!("Cache loaded"); } async fn guild_members_chunk(&self, ctx: Context, chunk: GuildMembersChunkEvent) { if (chunk.chunk_index + 1) == chunk.chunk_count { + println!("Cache built successfully!"); let db_lock = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Config in TypeMap.").clone() diff --git a/src/bin/update_committee.rs b/src/bin/update_committee.rs index b2792e0..b8cc6c2 100644 --- a/src/bin/update_committee.rs +++ b/src/bin/update_committee.rs @@ -47,15 +47,23 @@ async fn main() { struct Handler; #[async_trait] impl EventHandler for Handler { - async fn cache_ready(&self, ctx: Context, guilds: Vec) { - for guild in guilds { - ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None); - } - println!("Cache built successfully!"); + async fn cache_ready(&self, ctx: Context, _guilds: Vec) { + let config_lock = { + let data_read = ctx.data.read().await; + data_read.get::().expect("Expected Config in TypeMap.").clone() + }; + let config_global = config_lock.read().await; + + let server = config_global.committee_server; + + ctx.shard.chunk_guild(server, Some(2000), false, ChunkGuildFilter::None, None); + + println!("Cache loaded"); } async fn guild_members_chunk(&self, ctx: Context, chunk: GuildMembersChunkEvent) { if (chunk.chunk_index + 1) == chunk.chunk_count { + println!("Cache built successfully!"); // u[date committee server committee::check_committee(&ctx).await; diff --git a/src/bin/update_users.rs b/src/bin/update_users.rs index 6ac9e00..0cb11ac 100644 --- a/src/bin/update_users.rs +++ b/src/bin/update_users.rs @@ -12,6 +12,7 @@ use skynet_discord_bot::{ }, get_config, Config, }; +use std::sync::atomic::{AtomicUsize, Ordering}; use std::{process, sync::Arc}; use tokio::sync::RwLock; @@ -27,7 +28,10 @@ async fn main() { let intents = GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::GUILD_MEMBERS; // Build our client. let mut client = Client::builder(&config.discord_token, intents) - .event_handler(Handler {}) + .event_handler(Handler { + server_count: Default::default(), + server_cached: Default::default(), + }) .cache_settings(serenity::cache::Settings::default()) .await .expect("Error creating client"); @@ -44,23 +48,32 @@ async fn main() { } } -struct Handler; +struct Handler { + server_count: AtomicUsize, + server_cached: AtomicUsize, +} #[async_trait] impl EventHandler for Handler { async fn cache_ready(&self, ctx: Context, guilds: Vec) { + self.server_count.swap(guilds.len(), Ordering::SeqCst); for guild in guilds { ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None); } - println!("Cache built successfully!"); + println!("Cache loaded {}", &self.server_count.load(Ordering::SeqCst)); } async fn guild_members_chunk(&self, ctx: Context, chunk: GuildMembersChunkEvent) { if (chunk.chunk_index + 1) == chunk.chunk_count { - // this goes into each server and sets roles for each wolves member - check_bulk(&ctx).await; + self.server_cached.fetch_add(1, Ordering::SeqCst); + if (self.server_cached.load(Ordering::SeqCst) + 1) == self.server_count.load(Ordering::SeqCst) { + println!("Cache built successfully!"); - // finish up - process::exit(0); + // this goes into each server and sets roles for each wolves member + check_bulk(&ctx).await; + + // finish up + process::exit(0); + } } } } From 061b73378a9484478226559f4a70cdb6721e7e13 Mon Sep 17 00:00:00 2001 From: silver Date: Sun, 31 Aug 2025 11:51:57 +0000 Subject: [PATCH 32/37] Bump the bot --- src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.rs b/src/main.rs index 6a87f84..aecabec 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,6 +27,7 @@ use sqlx::{Pool, Sqlite}; use std::sync::Arc; use tokio::sync::RwLock; +// Need To Define The Stuct (Committed To Bump The Bot) struct Handler; #[async_trait] From 3149a5f99fc927397fec18840ceb9cbe54d65ce0 Mon Sep 17 00:00:00 2001 From: silver Date: Sun, 31 Aug 2025 11:55:35 +0000 Subject: [PATCH 33/37] Bump 2 --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index aecabec..bbf389f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,7 +27,7 @@ use sqlx::{Pool, Sqlite}; use std::sync::Arc; use tokio::sync::RwLock; -// Need To Define The Stuct (Committed To Bump The Bot) +// Need To Define The Stuct (Committed To Bump The Bot) struct Handler; #[async_trait] From 7526a82bb7c384c16a09992458868b2f669ed279 Mon Sep 17 00:00:00 2001 From: Brendan Golden Date: Thu, 4 Sep 2025 23:11:24 +0100 Subject: [PATCH 34/37] feat: kill the service if it persists longer than 9 min --- flake.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/flake.nix b/flake.nix index 81f4490..3a6032f 100644 --- a/flake.nix +++ b/flake.nix @@ -128,6 +128,8 @@ User = "${cfg.user}"; Group = "${cfg.user}"; ExecStart = "${self.defaultPackage."${system}"}/bin/${script}"; + # kill each service if its ran for 9 min + TimeoutStartSec=540; EnvironmentFile = [ "${cfg.env.discord}" "${cfg.env.mail}" From 7e90f451965b0edbd331765ad295a02f31d2bf24 Mon Sep 17 00:00:00 2001 From: Roman Moisieiev Date: Thu, 11 Sep 2025 12:35:50 +0100 Subject: [PATCH 35/37] Fix typos --- .taplo.toml | 2 ++ src/bin/cleanup_committee.rs | 8 ++++---- src/commands/add_server.rs | 2 +- src/commands/count.rs | 2 +- src/commands/minecraft.rs | 2 +- src/commands/role_adder.rs | 4 ++-- src/commands/server_icon.rs | 2 +- src/commands/wolves.rs | 8 ++++---- src/common/minecraft.rs | 4 ++-- src/common/renderer.rs | 5 ++--- src/common/server_icon.rs | 2 +- src/common/set_roles.rs | 12 ++++++------ src/lib.rs | 2 +- src/main.rs | 9 ++++----- 14 files changed, 32 insertions(+), 32 deletions(-) create mode 100644 .taplo.toml diff --git a/.taplo.toml b/.taplo.toml new file mode 100644 index 0000000..3b409e9 --- /dev/null +++ b/.taplo.toml @@ -0,0 +1,2 @@ +[formatting] +column_width = 120 diff --git a/src/bin/cleanup_committee.rs b/src/bin/cleanup_committee.rs index 188cc5b..9a01f4c 100644 --- a/src/bin/cleanup_committee.rs +++ b/src/bin/cleanup_committee.rs @@ -18,8 +18,8 @@ use tokio::sync::RwLock; /// Cleanup teh Committee server /// -/// This removes any invalid roles/channels which ay have been set up accidentally -/// DO NOT run this locally unless you have a fresh copy of teh live database handy. +/// This removes any invalid roles/channels which have been set up accidentally +/// DO NOT run this locally unless you have a fresh copy of the live database handy. #[tokio::main] async fn main() { let config = get_config(); @@ -98,7 +98,7 @@ async fn cleanup(db: &Pool, ctx: &Context, config: &Config) { let name = &channel.name; let committee_tmp = committees.iter().filter(|x| &x.name_channel == name).collect::>(); let committee = match committee_tmp.first() { - // if there are no committees which match then this is not a channelw e care about + // if there are no committees which match then this is not a channel we care about None => { continue; } @@ -120,7 +120,7 @@ async fn cleanup(db: &Pool, ctx: &Context, config: &Config) { let name = &role.name; let committee_tmp = committees.iter().filter(|x| &x.name_role == name).collect::>(); let committee = match committee_tmp.first() { - // if there are no committees which match then this is not a channelw e care about + // if there are no committees which match then this is not a channel we care about None => { continue; } diff --git a/src/commands/add_server.rs b/src/commands/add_server.rs index 0c7dd2f..4511c1b 100644 --- a/src/commands/add_server.rs +++ b/src/commands/add_server.rs @@ -102,7 +102,7 @@ async fn add_server(db: &Pool, ctx: &Context, server: &Servers) -> Resul .fetch_optional(db) .await; - // if the entry does not exist already tehn do a user update + // if the entry does not exist already then do a user update let (update, current_remove, current_role, past_remove, past_role) = match &existing { None => (true, false, None, false, None), Some(x) => { diff --git a/src/commands/count.rs b/src/commands/count.rs index 2368bca..d354db0 100644 --- a/src/commands/count.rs +++ b/src/commands/count.rs @@ -152,7 +152,7 @@ pub mod servers { let length = line.len() + 1; - // +3 is to account for the closing fense + // +3 is to account for the closing fence if length < (limit + 3) { response.push(line); limit -= length; diff --git a/src/commands/minecraft.rs b/src/commands/minecraft.rs index a4d1b1b..61f4280 100644 --- a/src/commands/minecraft.rs +++ b/src/commands/minecraft.rs @@ -196,7 +196,7 @@ pub(crate) mod server { model::id::GuildId, }; use sqlx::Error; - // this is to managfe the server side of commands related to minecraft + // this is to manage the server side of commands related to minecraft use super::*; use skynet_discord_bot::{ common::minecraft::{update_server, Minecraft}, diff --git a/src/commands/role_adder.rs b/src/commands/role_adder.rs index e60ac83..7f59c08 100644 --- a/src/commands/role_adder.rs +++ b/src/commands/role_adder.rs @@ -147,7 +147,7 @@ pub mod tools { use sqlx::{Pool, Sqlite}; pub async fn on_role_change(db: &Pool, ctx: &Context, new_data: Member) { - // check if the role changed is part of the oens for this server + // check if the role changed is part of the ones for this server if let Ok(role_adders) = sqlx::query_as::<_, RoleAdder>( r#" SELECT * @@ -163,7 +163,7 @@ pub mod tools { let mut roles_remove = vec![]; for role_adder in role_adders { - // if the user has both A dnd B give them C + // if the user has both A and B give them C if new_data.roles.contains(&role_adder.role_a) && new_data.roles.contains(&role_adder.role_b) && !new_data.roles.contains(&role_adder.role_c) { roles_add.push(role_adder.role_c); diff --git a/src/commands/server_icon.rs b/src/commands/server_icon.rs index 0cba1b1..2ab087e 100644 --- a/src/commands/server_icon.rs +++ b/src/commands/server_icon.rs @@ -211,7 +211,7 @@ pub(crate) mod user { let length = line.len() + 1; - // +3 is to account for the closing fense + // +3 is to account for the closing fence if length < (limit + 3) { response.push(line); limit -= length; diff --git a/src/commands/wolves.rs b/src/commands/wolves.rs index dc40ad0..0c8ddfc 100644 --- a/src/commands/wolves.rs +++ b/src/commands/wolves.rs @@ -101,7 +101,7 @@ pub mod link { return "Email already verified".to_string(); } - // generate a auth key + // generate an auth key let auth = random_string(20); match send_mail(&config, &details.email, &auth, &command.user.name) { Ok(_) => match save_to_db(&db, &details, &auth, &command.user.id).await { @@ -210,7 +210,7 @@ pub mod link { .subject("Skynet: Link Discord to Wolves.") .multipart( // This is composed of two parts. - // also helps not trip spam settings (uneven number of url's + // also helps not trip spam settings (uneven number of urls) MultiPart::alternative() .singlepart(SinglePart::builder().header(header::ContentType::TEXT_PLAIN).body(body_text)) .singlepart(SinglePart::builder().header(header::ContentType::TEXT_HTML).body(html.into_string())), @@ -460,7 +460,7 @@ pub mod verify { let config = config_lock.read().await; if let Some(x) = get_server_member_discord(db, &discord.id).await { - // if they are a member of one or more committees, and in teh committee server then give the teh general committee role + // if they are a member of one or more committees, and in teh committee server then give them the general committee role // they will get teh more specific vanity role later if !get_committees_id(db, x.id_wolves).await.is_empty() { let server = config.committee_server; @@ -500,7 +500,7 @@ pub mod unlink { }; let db = db_lock.read().await; - // dosent matter if there is one or not, it will be removed regardless + // doesn't matter if there is one or not, it will be removed regardless delete_link(&db, &command.user.id).await; "Discord link removed".to_string() diff --git a/src/common/minecraft.rs b/src/common/minecraft.rs index 60f7820..77cd754 100644 --- a/src/common/minecraft.rs +++ b/src/common/minecraft.rs @@ -24,7 +24,7 @@ impl<'r> FromRow<'r, SqliteRow> for Minecraft { /** loop through all members of server get a list of folks with mc accounts that are members -and a list that arent members +and a list that aren't members */ pub async fn update_server(server_id: &str, db: &Pool, g_id: &GuildId, config: &Config) { let mut usernames = vec![]; @@ -109,7 +109,7 @@ pub async fn whitelist_wipe(server: &str, token: &str) { }; post(&format!("{url_base}/files/delete"), &bearer, &deletion).await; - // recreate teh file, passing in the type here so the compiler knows what type of vec it is + // recreate the file, passing in the type here so the compiler knows what type of Vec it is post::>(&format!("{url_base}/files/write?file=%2Fwhitelist.json"), &bearer, &vec![]).await; // reload the whitelist diff --git a/src/common/renderer.rs b/src/common/renderer.rs index 97e73a0..f2c50cc 100644 --- a/src/common/renderer.rs +++ b/src/common/renderer.rs @@ -1,12 +1,11 @@ // this code is taken from https://github.com/MCorange99/svg2colored-png/tree/main -// I was unable to figure out how to use usvg myself so younked it from here. +// I was unable to figure out how to use usvg myself so yoinked it from here. use std::{ ffi::OsStr, path::{Path, PathBuf}, }; -// use clap::builder::OsStr; use color_eyre::{eyre::bail, Result}; use usvg_text_layout::TreeTextToPath; @@ -17,7 +16,7 @@ pub struct Args { /// Output folder where the PNG's will be placed pub output: PathBuf, - /// Comma seperated colors that will be used in HEX Eg. 000000,ffffff + /// Comma separated colors that will be used in HEX Eg. 000000,ffffff /// Can be like an object: black:000000,white:ffffff pub colors: String, diff --git a/src/common/server_icon.rs b/src/common/server_icon.rs index d99f265..1a7c2ef 100644 --- a/src/common/server_icon.rs +++ b/src/common/server_icon.rs @@ -281,7 +281,7 @@ pub mod update_icon { // check if exists if !path_new.exists() { - // convert if it hasnt been converted already + // convert if it hasn't been converted already match r.render(&path_local, &args) { Ok(_) => {} Err(_e) => { diff --git a/src/common/set_roles.rs b/src/common/set_roles.rs index 6e71992..9115986 100644 --- a/src/common/set_roles.rs +++ b/src/common/set_roles.rs @@ -48,7 +48,7 @@ pub mod normal { if let Ok(x) = server.members(ctx, None, None).await { for member in x { - // members_changed acts as an override to only deal with teh users in it + // members_changed acts as an override to only deal with the users in it if !members_changed.is_empty() && !members_changed.contains(&member.user.id) { continue; } @@ -84,7 +84,7 @@ pub mod normal { if member.roles.contains(role_current) { roles_set.current_rem += 1; - // if theya re not a current member and have the role then remove it + // if they're not a current member and have the role then remove it if let Err(e) = member.remove_role(ctx, role_current).await { println!("{e:?}"); } @@ -196,7 +196,7 @@ pub mod committee { } /** - This function can take a vec of members (or just one) and gives tehm the appropiate roles on teh committee server + This function can take a Vec of members (or just one) and gives them the appropriate roles on teh committee server */ pub async fn update_committees(db: &Pool, ctx: &Context, config: &Config, members: &mut Vec) { let server = config.committee_server; @@ -228,11 +228,11 @@ pub mod committee { let mut channels = server.channels(&ctx).await.unwrap_or_default(); - // a map of users and the roles they are goign to be getting + // a map of users and the roles they are going to be getting let mut users_roles = HashMap::new(); let mut re_order = false; - // we need to create roles and channels if tehy dont already exist + // we need to create roles and channels if they don't already exist let mut category_index = 0; let mut i = 0; loop { @@ -367,7 +367,7 @@ pub mod committee { let has_committee_role = roles_current_id.contains(&committee_member); if on_committee && !has_committee_role { - // if there are committee roles then give the general purporse role + // if there are committee roles then give the general purpose role roles_add.push(committee_member); } if !on_committee && has_committee_role { diff --git a/src/lib.rs b/src/lib.rs index 75c9d78..1a6afb1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,7 +36,7 @@ pub struct Config { pub committee_role: RoleId, pub committee_category: Vec, - // items pertaining to compsoc only + // items pertaining to CompSoc only pub compsoc_server: GuildId, } impl TypeMapKey for Config { diff --git a/src/main.rs b/src/main.rs index bbf389f..aeebac7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,7 +27,6 @@ use sqlx::{Pool, Sqlite}; use std::sync::Arc; use tokio::sync::RwLock; -// Need To Define The Stuct (Committed To Bump The Bot) struct Handler; #[async_trait] @@ -117,7 +116,7 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use let db = db_lock.read().await; - // check if the role changed is part of the oens for this server + // check if the role changed is part of the ones for this server if let Some(x) = new_data { on_role_change(&db, &ctx, x).await; } @@ -159,13 +158,13 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use } } - // compsoc Server + // CompSoc Server match config .compsoc_server .set_commands( &ctx.http, vec![ - // commands just for the compsoc server + // commands just for the CompSoc server commands::count::servers::register(), commands::server_icon::user::register(), ], @@ -182,7 +181,7 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use async fn interaction_create(&self, ctx: Context, interaction: Interaction) { if let Interaction::Command(command) = interaction { let _ = command.defer_ephemeral(&ctx.http).await; - //println!("Received command interaction: {:#?}", command); + // println!("Received command interaction: {:#?}", command); let content = match command.data.name.as_str() { // user commands From d70a037057c6209b2340b22a749359a16f7d164a Mon Sep 17 00:00:00 2001 From: Roman Moisieiev Date: Thu, 11 Sep 2025 12:36:48 +0100 Subject: [PATCH 36/37] Blame: ignore Fix Typos commit --- .git-blame-ignore-revs | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000..a338a00 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +# Fix typos +7e90f451965b0edbd331765ad295a02f31d2bf24 From 062f826d28b4d385423656b10cca84b3644c8e60 Mon Sep 17 00:00:00 2001 From: Roman Moisieiev Date: Thu, 11 Sep 2025 12:54:54 +0100 Subject: [PATCH 37/37] Remove RwLock for database --- src/bin/cleanup_committee.rs | 6 ++---- src/bin/update_committee.rs | 2 +- src/bin/update_data.rs | 2 +- src/bin/update_server-icon.rs | 5 ++--- src/bin/update_users.rs | 15 +++++++++------ src/commands/add_server.rs | 3 +-- src/commands/count.rs | 6 ++---- src/commands/minecraft.rs | 16 ++++++---------- src/commands/role_adder.rs | 3 +-- src/commands/server_icon.rs | 9 +++------ src/commands/wolves.rs | 9 +++------ src/common/database.rs | 3 +-- src/common/set_roles.rs | 8 ++------ src/common/wolves.rs | 6 ++---- src/main.rs | 10 +++------- 15 files changed, 39 insertions(+), 64 deletions(-) diff --git a/src/bin/cleanup_committee.rs b/src/bin/cleanup_committee.rs index 9a01f4c..141af89 100644 --- a/src/bin/cleanup_committee.rs +++ b/src/bin/cleanup_committee.rs @@ -41,7 +41,7 @@ async fn main() { let mut data = client.data.write().await; data.insert::(Arc::new(RwLock::new(config))); - data.insert::(Arc::new(RwLock::new(db))); + data.insert::(Arc::new(db)); } if let Err(why) = client.start().await { @@ -69,13 +69,11 @@ impl EventHandler for Handler { async fn guild_members_chunk(&self, ctx: Context, chunk: GuildMembersChunkEvent) { if (chunk.chunk_index + 1) == chunk.chunk_count { println!("Cache built successfully!"); - let db_lock = { + let db = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Config in TypeMap.").clone() }; - let db = db_lock.read().await; - let config_lock = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Config in TypeMap.").clone() diff --git a/src/bin/update_committee.rs b/src/bin/update_committee.rs index b8cc6c2..d90cbac 100644 --- a/src/bin/update_committee.rs +++ b/src/bin/update_committee.rs @@ -36,7 +36,7 @@ async fn main() { let mut data = client.data.write().await; data.insert::(Arc::new(RwLock::new(config))); - data.insert::(Arc::new(RwLock::new(db))); + data.insert::(Arc::new(db)); } if let Err(why) = client.start().await { diff --git a/src/bin/update_data.rs b/src/bin/update_data.rs index 8f73ce9..fe4138f 100644 --- a/src/bin/update_data.rs +++ b/src/bin/update_data.rs @@ -38,7 +38,7 @@ async fn main() { let mut data = client.data.write().await; data.insert::(Arc::new(RwLock::new(config))); - data.insert::(Arc::new(RwLock::new(db))); + data.insert::(Arc::new(db)); } if let Err(why) = client.start().await { diff --git a/src/bin/update_server-icon.rs b/src/bin/update_server-icon.rs index 56957da..c4f9eca 100644 --- a/src/bin/update_server-icon.rs +++ b/src/bin/update_server-icon.rs @@ -35,7 +35,7 @@ async fn main() { let mut data = client.data.write().await; data.insert::(Arc::new(RwLock::new(config))); - data.insert::(Arc::new(RwLock::new(db))); + data.insert::(Arc::new(db)); } if let Err(why) = client.start().await { @@ -50,11 +50,10 @@ impl EventHandler for Handler { let ctx = Arc::new(ctx); println!("{} is connected!", ready.user.name); - let db_lock = { + let db = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Config in TypeMap.").clone() }; - let db = db_lock.read().await; let config_lock = { let data_read = ctx.data.read().await; diff --git a/src/bin/update_users.rs b/src/bin/update_users.rs index 0cb11ac..3150bcf 100644 --- a/src/bin/update_users.rs +++ b/src/bin/update_users.rs @@ -12,8 +12,13 @@ use skynet_discord_bot::{ }, get_config, Config, }; -use std::sync::atomic::{AtomicUsize, Ordering}; -use std::{process, sync::Arc}; +use std::{ + process, + sync::{ + atomic::{AtomicUsize, Ordering}, + Arc, + }, +}; use tokio::sync::RwLock; #[tokio::main] @@ -40,7 +45,7 @@ async fn main() { let mut data = client.data.write().await; data.insert::(Arc::new(RwLock::new(config))); - data.insert::(Arc::new(RwLock::new(db))); + data.insert::(Arc::new(db)); } if let Err(why) = client.start().await { @@ -79,13 +84,11 @@ impl EventHandler for Handler { } async fn check_bulk(ctx: &Context) { - let db_lock = { + let db = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Config in TypeMap.").clone() }; - let db = db_lock.read().await; - for server_config in get_server_config_bulk(&db).await { normal::update_server(ctx, &server_config, &[], &[]).await; } diff --git a/src/commands/add_server.rs b/src/commands/add_server.rs index 4511c1b..eaf0971 100644 --- a/src/commands/add_server.rs +++ b/src/commands/add_server.rs @@ -56,11 +56,10 @@ pub async fn run(command: &CommandInteraction, ctx: &Context) -> String { return "Please provide a valid channel for ``Bot Channel``".to_string(); }; - let db_lock = { + let db = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Databse in TypeMap.").clone() }; - let db = db_lock.read().await; let server_data = Servers { server: command.guild_id.unwrap_or_default(), diff --git a/src/commands/count.rs b/src/commands/count.rs index d354db0..41b9d81 100644 --- a/src/commands/count.rs +++ b/src/commands/count.rs @@ -27,11 +27,10 @@ pub mod committee { false }; - let db_lock = { + let db = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Databse in TypeMap.").clone() }; - let db = db_lock.read().await; let mut cs = vec![]; // pull it from a DB @@ -95,11 +94,10 @@ pub mod servers { use std::collections::HashMap; pub async fn run(_command: &CommandInteraction, ctx: &Context) -> String { - let db_lock = { + let db = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Databse in TypeMap.").clone() }; - let db = db_lock.read().await; let mut committees = HashMap::new(); if let Some(x) = get_committees(&db).await { diff --git a/src/commands/minecraft.rs b/src/commands/minecraft.rs index 61f4280..5098f11 100644 --- a/src/commands/minecraft.rs +++ b/src/commands/minecraft.rs @@ -23,11 +23,10 @@ pub(crate) mod user { use sqlx::Error; pub async fn run(command: &CommandInteraction, ctx: &Context) -> String { - let db_lock = { + let db = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Databse in TypeMap.").clone() }; - let db = db_lock.read().await; let config_lock = { let data_read = ctx.data.read().await; @@ -229,11 +228,10 @@ pub(crate) mod server { return String::from("Expected Server ID"); }; - let db_lock = { + let db = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Databse in TypeMap.").clone() }; - let db = db_lock.read().await; match add_server(&db, &g_id, &server_minecraft).await { Ok(_) => {} @@ -290,11 +288,10 @@ pub(crate) mod server { Some(x) => x, }; - let db_lock = { + let db = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Databse in TypeMap.").clone() }; - let db = db_lock.read().await; let servers = get_minecraft_config_server(&db, g_id).await; @@ -366,11 +363,10 @@ pub(crate) mod server { return String::from("Expected Server ID"); }; - let db_lock = { - let data_read = ctx.data.read().await; - data_read.get::().expect("Expected Databse in TypeMap.").clone() + let db = { + let data = ctx.data.read().await; + data.get::().expect("Expected Databse in TypeMap.").clone() }; - let db = db_lock.read().await; match server_remove(&db, &g_id, &server_minecraft).await { Ok(_) => {} diff --git a/src/commands/role_adder.rs b/src/commands/role_adder.rs index 7f59c08..0573b37 100644 --- a/src/commands/role_adder.rs +++ b/src/commands/role_adder.rs @@ -62,11 +62,10 @@ pub mod edit { false }; - let db_lock = { + let db = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Databse in TypeMap.").clone() }; - let db = db_lock.read().await; let server = command.guild_id.unwrap_or_default(); let server_data = RoleAdder { diff --git a/src/commands/server_icon.rs b/src/commands/server_icon.rs index 2ab087e..d4a78d5 100644 --- a/src/commands/server_icon.rs +++ b/src/commands/server_icon.rs @@ -18,11 +18,10 @@ pub(crate) mod admin { use super::*; pub async fn run(_command: &CommandInteraction, ctx: &Context) -> String { - let db_lock = { + let db = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Databse in TypeMap.").clone() }; - let db = db_lock.read().await; let config_lock = { let data_read = ctx.data.read().await; @@ -69,11 +68,10 @@ pub(crate) mod user { use sqlx::{Pool, Sqlite}; pub async fn run(command: &CommandInteraction, ctx: &Context) -> String { - let db_lock = { + let db = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Databse in TypeMap.").clone() }; - let db = db_lock.read().await; let config_toml = get_config_icons::minimal(); @@ -145,11 +143,10 @@ pub(crate) mod user { use sqlx::{Pool, Sqlite}; pub async fn run(_command: &CommandInteraction, ctx: &Context) -> String { - let db_lock = { + let db = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Databse in TypeMap.").clone() }; - let db = db_lock.read().await; let config_toml = get_config_icons::minimal(); diff --git a/src/commands/wolves.rs b/src/commands/wolves.rs index 0c8ddfc..843ca70 100644 --- a/src/commands/wolves.rs +++ b/src/commands/wolves.rs @@ -21,11 +21,10 @@ pub mod link { use serenity::all::{CommandDataOption, CommandDataOptionValue, CommandInteraction}; pub async fn run(command: &CommandInteraction, ctx: &Context) -> String { - let db_lock = { + let db = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Databse in TypeMap.").clone() }; - let db = db_lock.read().await; let config_lock = { let data_read = ctx.data.read().await; @@ -314,11 +313,10 @@ pub mod verify { use sqlx::Error; pub async fn run(command: &CommandInteraction, ctx: &Context) -> String { - let db_lock = { + let db = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Database in TypeMap.").clone() }; - let db = db_lock.read().await; // check if user has used /link_wolves let details = if let Some(x) = get_verify_from_db(&db, &command.user.id).await { @@ -494,11 +492,10 @@ pub mod unlink { use sqlx::{Pool, Sqlite}; pub async fn run(command: &CommandInteraction, ctx: &Context) -> String { - let db_lock = { + let db = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Databse in TypeMap.").clone() }; - let db = db_lock.read().await; // doesn't matter if there is one or not, it will be removed regardless delete_link(&db, &command.user.id).await; diff --git a/src/common/database.rs b/src/common/database.rs index 0c18668..2eaf5df 100644 --- a/src/common/database.rs +++ b/src/common/database.rs @@ -12,11 +12,10 @@ use sqlx::{ Error, FromRow, Pool, Row, Sqlite, }; use std::{str::FromStr, sync::Arc}; -use tokio::sync::RwLock; pub struct DataBase; impl TypeMapKey for DataBase { - type Value = Arc>>; + type Value = Arc>; } #[derive(Debug, Clone, Deserialize, Serialize)] diff --git a/src/common/set_roles.rs b/src/common/set_roles.rs index 9115986..e11c637 100644 --- a/src/common/set_roles.rs +++ b/src/common/set_roles.rs @@ -17,13 +17,11 @@ pub mod normal { } pub async fn update_server(ctx: &Context, server: &Servers, remove_roles: &[Option], members_changed: &[UserId]) { - let db_lock = { + let db = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Database in TypeMap.").clone() }; - let db = db_lock.read().await; - let Servers { server, role_past, @@ -174,13 +172,11 @@ pub mod committee { use std::collections::HashMap; pub async fn check_committee(ctx: &Context) { - let db_lock = { + let db = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Config in TypeMap.").clone() }; - let db = db_lock.read().await; - let config_lock = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Config in TypeMap.").clone() diff --git a/src/common/wolves.rs b/src/common/wolves.rs index 17305f6..3744558 100644 --- a/src/common/wolves.rs +++ b/src/common/wolves.rs @@ -69,11 +69,10 @@ pub mod cns { } pub async fn get_wolves(ctx: &Context) { - let db_lock = { + let db = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Database in TypeMap.").clone() }; - let db = db_lock.read().await; let config_lock = { let data_read = ctx.data.read().await; @@ -224,11 +223,10 @@ pub mod committees { } pub async fn get_cns(ctx: &Context) { - let db_lock = { + let db = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Database in TypeMap.").clone() }; - let db = db_lock.read().await; let config_lock = { let data_read = ctx.data.read().await; diff --git a/src/main.rs b/src/main.rs index aeebac7..8dff675 100644 --- a/src/main.rs +++ b/src/main.rs @@ -41,13 +41,11 @@ impl EventHandler for Handler { // handles previously linked accounts joining the server async fn guild_member_addition(&self, ctx: Context, new_member: Member) { - let db_lock = { + let db = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Config in TypeMap.").clone() }; - let db = db_lock.read().await; - let config_lock = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Config in TypeMap.").clone() @@ -109,13 +107,11 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use // handles role updates async fn guild_member_update(&self, ctx: Context, _old_data: Option, new_data: Option, _: GuildMemberUpdateEvent) { // get config/db - let db_lock = { + let db = { let data_read = ctx.data.read().await; data_read.get::().expect("Expected Config in TypeMap.").clone() }; - let db = db_lock.read().await; - // check if the role changed is part of the ones for this server if let Some(x) = new_data { on_role_change(&db, &ctx, x).await; @@ -304,7 +300,7 @@ async fn main() { let mut data = client.data.write().await; data.insert::(Arc::new(RwLock::new(config))); - data.insert::(Arc::new(RwLock::new(db))); + data.insert::(Arc::new(db)); } // Finally, start a single shard, and start listening to events.