use serenity::{ all::{ChunkGuildFilter, GuildId, GuildMembersChunkEvent}, async_trait, client::{Context, EventHandler}, model::gateway::GatewayIntents, Client, }; 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; /// 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(2000), false, ChunkGuildFilter::None, None); } println!("Cache built successfully!"); } 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 = 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); } } } } }