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 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/Cargo.toml b/Cargo.toml index bca450c..832eb09 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,13 +4,9 @@ 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_users" - [[bin]] name = "update_committee" @@ -38,7 +34,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..81f4490 100644 --- a/flake.nix +++ b/flake.nix @@ -152,13 +152,14 @@ # modify these scripts = { - # every 20 min + # every 10 min "update_data" = "*:0,10,20,30,40,50"; # groups are updated every hour, offset from teh ldap - "update_users" = "*:05:00"; + "update_users" = "*:5,15,25,35,45,55"; # Committee server has its own timer - "update_committee" = "*:15:00"; + "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"; diff --git a/src/bin/cleanup_committee.rs b/src/bin/cleanup_committee.rs index a2c3772..c6485a7 100644 --- a/src/bin/cleanup_committee.rs +++ b/src/bin/cleanup_committee.rs @@ -1,14 +1,17 @@ -use serenity::all::{ChunkGuildFilter, GuildId}; 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; @@ -42,7 +45,7 @@ async fn main() { } if let Err(why) = client.start().await { - println!("Client error: {:?}", why); + println!("Client error: {why:?}"); } } @@ -56,26 +59,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 2eef977..b2792e0 100644 --- a/src/bin/update_committee.rs +++ b/src/bin/update_committee.rs @@ -1,13 +1,17 @@ -use serenity::all::{ChunkGuildFilter, GuildId}; 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; @@ -36,7 +40,7 @@ async fn main() { } if let Err(why) = client.start().await { - println!("Client error: {:?}", why); + println!("Client error: {why:?}"); } } @@ -50,14 +54,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(Arc::clone(&ctx)).await; - - // finish up - process::exit(0); + // finish up + process::exit(0); + } } } diff --git a/src/bin/update_data.rs b/src/bin/update_data.rs index d184ccd..8f73ce9 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; @@ -40,20 +42,13 @@ async fn main() { } if let Err(why) = client.start().await { - println!("Client error: {:?}", why); + 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); 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 2c093f9..56957da 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}; @@ -38,20 +39,13 @@ async fn main() { } if let Err(why) = client.start().await { - println!("Client error: {:?}", why); + 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); diff --git a/src/bin/update_users.rs b/src/bin/update_users.rs index 27dc1d6..6ac9e00 100644 --- a/src/bin/update_users.rs +++ b/src/bin/update_users.rs @@ -1,13 +1,17 @@ -use serenity::all::{ChunkGuildFilter, GuildId}; 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; @@ -36,7 +40,7 @@ async fn main() { } if let Err(why) = client.start().await { - println!("Client error: {:?}", why); + println!("Client error: {why:?}"); } } @@ -50,19 +54,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() @@ -71,6 +74,6 @@ async fn check_bulk(ctx: Arc) { 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..0c7dd2f 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 { @@ -72,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 678c9e0..8a64ee7 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 { @@ -53,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; @@ -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; @@ -143,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 ca395c6..a4d1b1b 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 { @@ -69,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 { @@ -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") @@ -229,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); } } @@ -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 { @@ -363,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 f58803b..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}") } } @@ -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}; @@ -180,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 9c970fc..0cba1b1 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 @@ -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 { @@ -205,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 d78454b..dc40ad0 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 { @@ -110,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 { @@ -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 { @@ -357,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() @@ -419,7 +427,7 @@ pub mod verify { } if let Err(e) = member.add_roles(&ctx, &roles).await { - println!("{:?}", e); + println!("{e:?}"); } } } @@ -435,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 0663799..0c18668 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; @@ -220,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 4faa8ed..60f7820 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 { @@ -155,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 f99d891..97e73a0 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}; @@ -177,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 0012539..6352c24 100644 --- a/src/common/set_roles.rs +++ b/src/common/set_roles.rs @@ -1,10 +1,21 @@ 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 { + 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 +31,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,22 +54,24 @@ 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()); } if let Err(e) = member.add_roles(ctx, &roles).await { - println!("{:?}", e); + println!("{e:?}"); } } else { // old and never @@ -65,16 +83,16 @@ 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); + println!("{e:?}"); } } } for role in remove_roles.iter().flatten() { if let Err(e) = member.remove_role(ctx, role).await { - println!("{:?}", e); + println!("{e:?}"); } } } @@ -83,7 +101,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 { @@ -123,7 +148,7 @@ pub mod normal { Ok(_) => {} Err(e) => { println!("Failure to insert into {}", server.get()); - println!("{:?}", e); + println!("{e:?}"); } } } @@ -131,23 +156,24 @@ 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: 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() @@ -166,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; } /** @@ -308,15 +334,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 @@ -325,14 +347,25 @@ 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 && on_committee { + continue; + } + 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; } @@ -351,8 +384,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(); } } @@ -440,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:?}"); } } } @@ -458,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 6f73842..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:?}"); } } } @@ -48,12 +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::set_roles::normal::update_server; - 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; @@ -96,7 +98,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 +116,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 +126,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; - } } } @@ -151,7 +145,7 @@ pub mod cns { Ok(_) => {} Err(e) => { println!("Failure to set server name {}", server.get()); - println!("{:?}", e); + println!("{e:?}"); } } } @@ -190,7 +184,7 @@ pub mod cns { Ok(_) => {} Err(e) => { println!("Failure to insert into ServerMembers {} {:?}", server.get(), user); - println!("{:?}", e); + println!("{e:?}"); } } } @@ -200,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}; @@ -270,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/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 b09fb7a..6a87f84 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,24 +1,28 @@ pub mod commands; use crate::commands::role_adder::tools::on_role_change; -use serenity::all::{ - ActivityData, Command, CommandDataOptionValue, CreateMessage, EditInteractionResponse, GuildId, GuildMemberUpdateEvent, 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_member, DataBase}; -use skynet_discord_bot::common::set_roles::committee::update_committees; -use skynet_discord_bot::common::wolves::committees::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::Arc; use tokio::sync::RwLock; @@ -77,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; @@ -142,7 +146,7 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use { Ok(_) => {} Err(e) => { - println!("{:?}", e) + println!("{e:?}") } } @@ -150,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:?}") } } @@ -169,7 +173,7 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use { Ok(_) => {} Err(e) => { - println!("{:?}", e) + println!("{e:?}") } } } @@ -256,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}"); } } } @@ -291,7 +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 {}) + .event_handler(Handler) .cache_settings(serenity::cache::Settings::default()) .await .expect("Error creating client"); @@ -308,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:?}"); } }