Compare commits

..

No commits in common. "4b4e5cb2894346684034cba93a5ac1ec6f884f9f" and "7526a82bb7c384c16a09992458868b2f669ed279" have entirely different histories.

23 changed files with 1047 additions and 1166 deletions

View file

@ -7,5 +7,4 @@ fn_params_layout = "Compressed"
struct_lit_width = 0 struct_lit_width = 0
tab_spaces = 2 tab_spaces = 2
use_small_heuristics = "Max" use_small_heuristics = "Max"
# imports_granularity = "Crate" imports_granularity = "Crate"

1891
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -21,19 +21,11 @@ name = "cleanup_committee"
[dependencies] [dependencies]
# discord library # discord library
serenity = { version = "0.12", default-features = false, features = [ serenity = { version = "0.12", default-features = false, features = ["client", "gateway", "rustls_backend", "model", "cache"] }
"client",
"gateway",
"rustls_backend",
"model",
"cache",
] }
tokio = { version = "1", features = ["macros", "rt-multi-thread", "full"] } tokio = { version = "1", features = ["macros", "rt-multi-thread", "full"] }
# wolves api # wolves api
wolves_oxidised = { git = "https://forgejo.skynet.ie/Skynet/wolves-oxidised.git", features = [ wolves_oxidised = { git = "https://forgejo.skynet.ie/Skynet/wolves-oxidised.git", features = ["unstable"] }
"unstable",
] }
# wolves_oxidised = { path = "../wolves-oxidised", features = ["unstable"] } # wolves_oxidised = { path = "../wolves-oxidised", features = ["unstable"] }
# to make the http requests # to make the http requests
@ -55,12 +47,13 @@ chrono = "0.4"
lettre = "0.11" lettre = "0.11"
maud = "0.27" maud = "0.27"
toml = "0.9.5" toml = "0.8.23"
serde = "1.0" serde = "1.0"
# for image conversion # for image conversion
eyre = "0.6.12" eyre = "0.6.8"
color-eyre = "0.6.5" color-eyre = "0.6.2"
usvg = "0.45.1" usvg-text-layout = "0.29.0"
resvg = "0.45.1" usvg = "0.29.0"
tiny-skia = "0.11.4" resvg = "0.29.0"
tiny-skia = "0.8.3"

View file

@ -16,10 +16,10 @@ use sqlx::{Pool, Sqlite};
use std::{process, sync::Arc}; use std::{process, sync::Arc};
use tokio::sync::RwLock; use tokio::sync::RwLock;
/// Cleanup the Committee server /// Cleanup teh Committee server
/// ///
/// This removes any invalid roles/channels which have been set up accidentally /// 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 the live database handy. /// DO NOT run this locally unless you have a fresh copy of teh live database handy.
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
let config = get_config(); let config = get_config();
@ -41,7 +41,7 @@ async fn main() {
let mut data = client.data.write().await; let mut data = client.data.write().await;
data.insert::<Config>(Arc::new(RwLock::new(config))); data.insert::<Config>(Arc::new(RwLock::new(config)));
data.insert::<DataBase>(Arc::new(db)); data.insert::<DataBase>(Arc::new(RwLock::new(db)));
} }
if let Err(why) = client.start().await { if let Err(why) = client.start().await {
@ -69,11 +69,13 @@ impl EventHandler for Handler {
async fn guild_members_chunk(&self, ctx: Context, chunk: GuildMembersChunkEvent) { async fn guild_members_chunk(&self, ctx: Context, chunk: GuildMembersChunkEvent) {
if (chunk.chunk_index + 1) == chunk.chunk_count { if (chunk.chunk_index + 1) == chunk.chunk_count {
println!("Cache built successfully!"); println!("Cache built successfully!");
let db = { let db_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone() data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone()
}; };
let db = db_lock.read().await;
let config_lock = { let config_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<Config>().expect("Expected Config in TypeMap.").clone() data_read.get::<Config>().expect("Expected Config in TypeMap.").clone()
@ -96,7 +98,7 @@ async fn cleanup(db: &Pool<Sqlite>, ctx: &Context, config: &Config) {
let name = &channel.name; let name = &channel.name;
let committee_tmp = committees.iter().filter(|x| &x.name_channel == name).collect::<Vec<_>>(); let committee_tmp = committees.iter().filter(|x| &x.name_channel == name).collect::<Vec<_>>();
let committee = match committee_tmp.first() { let committee = match committee_tmp.first() {
// if there are no committees which match then this is not a channel we care about // if there are no committees which match then this is not a channelw e care about
None => { None => {
continue; continue;
} }
@ -118,7 +120,7 @@ async fn cleanup(db: &Pool<Sqlite>, ctx: &Context, config: &Config) {
let name = &role.name; let name = &role.name;
let committee_tmp = committees.iter().filter(|x| &x.name_role == name).collect::<Vec<_>>(); let committee_tmp = committees.iter().filter(|x| &x.name_role == name).collect::<Vec<_>>();
let committee = match committee_tmp.first() { let committee = match committee_tmp.first() {
// if there are no committees which match then this is not a channel we care about // if there are no committees which match then this is not a channelw e care about
None => { None => {
continue; continue;
} }

View file

@ -36,7 +36,7 @@ async fn main() {
let mut data = client.data.write().await; let mut data = client.data.write().await;
data.insert::<Config>(Arc::new(RwLock::new(config))); data.insert::<Config>(Arc::new(RwLock::new(config)));
data.insert::<DataBase>(Arc::new(db)); data.insert::<DataBase>(Arc::new(RwLock::new(db)));
} }
if let Err(why) = client.start().await { if let Err(why) = client.start().await {

View file

@ -38,7 +38,7 @@ async fn main() {
let mut data = client.data.write().await; let mut data = client.data.write().await;
data.insert::<Config>(Arc::new(RwLock::new(config))); data.insert::<Config>(Arc::new(RwLock::new(config)));
data.insert::<DataBase>(Arc::new(db)); data.insert::<DataBase>(Arc::new(RwLock::new(db)));
} }
if let Err(why) = client.start().await { if let Err(why) = client.start().await {
@ -56,7 +56,7 @@ impl EventHandler for Handler {
// get the data for each individual club/soc // get the data for each individual club/soc
get_wolves(&ctx).await; get_wolves(&ctx).await;
// get the data for the clubs/socs committees // get teh data for the clubs/socs committees
get_cns(&ctx).await; get_cns(&ctx).await;
// finish up // finish up

View file

@ -22,7 +22,7 @@ async fn main() {
// wipe whitelist first // wipe whitelist first
if !wiped.contains(&server.minecraft) { if !wiped.contains(&server.minecraft) {
whitelist_wipe(&server.minecraft, &config.discord_token_minecraft).await; whitelist_wipe(&server.minecraft, &config.discord_token_minecraft).await;
// add it to the done list so its not done again // add it to teh done list so its not done again
wiped.insert(&server.minecraft); wiped.insert(&server.minecraft);
} }

View file

@ -35,7 +35,7 @@ async fn main() {
let mut data = client.data.write().await; let mut data = client.data.write().await;
data.insert::<Config>(Arc::new(RwLock::new(config))); data.insert::<Config>(Arc::new(RwLock::new(config)));
data.insert::<DataBase>(Arc::new(db)); data.insert::<DataBase>(Arc::new(RwLock::new(db)));
} }
if let Err(why) = client.start().await { if let Err(why) = client.start().await {
@ -50,10 +50,11 @@ impl EventHandler for Handler {
let ctx = Arc::new(ctx); let ctx = Arc::new(ctx);
println!("{} is connected!", ready.user.name); println!("{} is connected!", ready.user.name);
let db = { let db_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone() data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone()
}; };
let db = db_lock.read().await;
let config_lock = { let config_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;

View file

@ -40,7 +40,7 @@ async fn main() {
let mut data = client.data.write().await; let mut data = client.data.write().await;
data.insert::<Config>(Arc::new(RwLock::new(config))); data.insert::<Config>(Arc::new(RwLock::new(config)));
data.insert::<DataBase>(Arc::new(db)); data.insert::<DataBase>(Arc::new(RwLock::new(db)));
} }
if let Err(why) = client.start().await { if let Err(why) = client.start().await {
@ -79,11 +79,13 @@ impl EventHandler for Handler {
} }
async fn check_bulk(ctx: &Context) { async fn check_bulk(ctx: &Context) {
let db = { let db_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone() data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone()
}; };
let db = db_lock.read().await;
for server_config in get_server_config_bulk(&db).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;
} }

View file

@ -56,10 +56,11 @@ pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
return "Please provide a valid channel for ``Bot Channel``".to_string(); return "Please provide a valid channel for ``Bot Channel``".to_string();
}; };
let db = { let db_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone() data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
}; };
let db = db_lock.read().await;
let server_data = Servers { let server_data = Servers {
server: command.guild_id.unwrap_or_default(), server: command.guild_id.unwrap_or_default(),
@ -101,7 +102,7 @@ async fn add_server(db: &Pool<Sqlite>, ctx: &Context, server: &Servers) -> Resul
.fetch_optional(db) .fetch_optional(db)
.await; .await;
// if the entry does not exist already then do a user update // if the entry does not exist already tehn do a user update
let (update, current_remove, current_role, past_remove, past_role) = match &existing { let (update, current_remove, current_role, past_remove, past_role) = match &existing {
None => (true, false, None, false, None), None => (true, false, None, false, None),
Some(x) => { Some(x) => {

View file

@ -27,10 +27,11 @@ pub mod committee {
false false
}; };
let db = { let db_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone() data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
}; };
let db = db_lock.read().await;
let mut cs = vec![]; let mut cs = vec![];
// pull it from a DB // pull it from a DB
@ -94,10 +95,11 @@ pub mod servers {
use std::collections::HashMap; use std::collections::HashMap;
pub async fn run(_command: &CommandInteraction, ctx: &Context) -> String { pub async fn run(_command: &CommandInteraction, ctx: &Context) -> String {
let db = { let db_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone() data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
}; };
let db = db_lock.read().await;
let mut committees = HashMap::new(); let mut committees = HashMap::new();
if let Some(x) = get_committees(&db).await { if let Some(x) = get_committees(&db).await {
@ -119,7 +121,7 @@ pub mod servers {
cs.push((total, total, String::from("Skynet Network"))); cs.push((total, total, String::from("Skynet Network")));
cs.push((wolves_current, wolves_past, String::from("Clubs/Socs Servers"))); cs.push((wolves_current, wolves_past, String::from("Clubs/Socs Servers")));
// treat the committee server as its own thing // treat teh committee server as its own thing
let committee_current = get_wolves_committee(&db).await; let committee_current = get_wolves_committee(&db).await;
cs.push((committee_current, committee_current, String::from("Committee Server"))); cs.push((committee_current, committee_current, String::from("Committee Server")));
@ -150,7 +152,7 @@ pub mod servers {
let length = line.len() + 1; let length = line.len() + 1;
// +3 is to account for the closing fence // +3 is to account for the closing fense
if length < (limit + 3) { if length < (limit + 3) {
response.push(line); response.push(line);
limit -= length; limit -= length;

View file

@ -23,10 +23,11 @@ pub(crate) mod user {
use sqlx::Error; use sqlx::Error;
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String { pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
let db = { let db_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone() data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
}; };
let db = db_lock.read().await;
let config_lock = { let config_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
@ -195,7 +196,7 @@ pub(crate) mod server {
model::id::GuildId, model::id::GuildId,
}; };
use sqlx::Error; use sqlx::Error;
// this is to manage the server side of commands related to minecraft // this is to managfe the server side of commands related to minecraft
use super::*; use super::*;
use skynet_discord_bot::{ use skynet_discord_bot::{
common::minecraft::{update_server, Minecraft}, common::minecraft::{update_server, Minecraft},
@ -228,10 +229,11 @@ pub(crate) mod server {
return String::from("Expected Server ID"); return String::from("Expected Server ID");
}; };
let db = { let db_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone() data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
}; };
let db = db_lock.read().await;
match add_server(&db, &g_id, &server_minecraft).await { match add_server(&db, &g_id, &server_minecraft).await {
Ok(_) => {} Ok(_) => {}
@ -288,10 +290,11 @@ pub(crate) mod server {
Some(x) => x, Some(x) => x,
}; };
let db = { let db_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone() data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
}; };
let db = db_lock.read().await;
let servers = get_minecraft_config_server(&db, g_id).await; let servers = get_minecraft_config_server(&db, g_id).await;
@ -363,10 +366,11 @@ pub(crate) mod server {
return String::from("Expected Server ID"); return String::from("Expected Server ID");
}; };
let db = { let db_lock = {
let data = ctx.data.read().await; let data_read = ctx.data.read().await;
data.get::<DataBase>().expect("Expected Databse in TypeMap.").clone() data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
}; };
let db = db_lock.read().await;
match server_remove(&db, &g_id, &server_minecraft).await { match server_remove(&db, &g_id, &server_minecraft).await {
Ok(_) => {} Ok(_) => {}
@ -376,7 +380,7 @@ pub(crate) mod server {
} }
} }
// no need to clear the whitelist as it will be reset within 24hr anyways // no need to clear teh whitelist as it will be reset within 24hr anyways
"Removed minecraft_server info".to_string() "Removed minecraft_server info".to_string()
} }

View file

@ -62,10 +62,11 @@ pub mod edit {
false false
}; };
let db = { let db_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone() data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
}; };
let db = db_lock.read().await;
let server = command.guild_id.unwrap_or_default(); let server = command.guild_id.unwrap_or_default();
let server_data = RoleAdder { let server_data = RoleAdder {
@ -146,7 +147,7 @@ pub mod tools {
use sqlx::{Pool, Sqlite}; use sqlx::{Pool, Sqlite};
pub async fn on_role_change(db: &Pool<Sqlite>, ctx: &Context, new_data: Member) { pub async fn on_role_change(db: &Pool<Sqlite>, ctx: &Context, new_data: Member) {
// check if the role changed is part of the ones for this server // check if the role changed is part of the oens for this server
if let Ok(role_adders) = sqlx::query_as::<_, RoleAdder>( if let Ok(role_adders) = sqlx::query_as::<_, RoleAdder>(
r#" r#"
SELECT * SELECT *
@ -162,7 +163,7 @@ pub mod tools {
let mut roles_remove = vec![]; let mut roles_remove = vec![];
for role_adder in role_adders { for role_adder in role_adders {
// if the user has both A and B give them C // if the user has both A dnd 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) 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); roles_add.push(role_adder.role_c);

View file

@ -18,10 +18,11 @@ pub(crate) mod admin {
use super::*; use super::*;
pub async fn run(_command: &CommandInteraction, ctx: &Context) -> String { pub async fn run(_command: &CommandInteraction, ctx: &Context) -> String {
let db = { let db_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone() data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
}; };
let db = db_lock.read().await;
let config_lock = { let config_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
@ -57,7 +58,7 @@ pub(crate) mod user {
format!("{}/src/branch/main/{}/{}", &config_toml.source.repo, &config_toml.source.directory, logo_name) format!("{}/src/branch/main/{}/{}", &config_toml.source.repo, &config_toml.source.directory, logo_name)
} }
/// Regular users can get the link to the current icon /// Regular users can get teh link to teh current icon
pub(crate) mod current { pub(crate) mod current {
use super::*; use super::*;
@ -68,10 +69,11 @@ pub(crate) mod user {
use sqlx::{Pool, Sqlite}; use sqlx::{Pool, Sqlite};
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String { pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
let db = { let db_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone() data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
}; };
let db = db_lock.read().await;
let config_toml = get_config_icons::minimal(); let config_toml = get_config_icons::minimal();
@ -143,10 +145,11 @@ pub(crate) mod user {
use sqlx::{Pool, Sqlite}; use sqlx::{Pool, Sqlite};
pub async fn run(_command: &CommandInteraction, ctx: &Context) -> String { pub async fn run(_command: &CommandInteraction, ctx: &Context) -> String {
let db = { let db_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone() data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
}; };
let db = db_lock.read().await;
let config_toml = get_config_icons::minimal(); let config_toml = get_config_icons::minimal();
@ -208,7 +211,7 @@ pub(crate) mod user {
let length = line.len() + 1; let length = line.len() + 1;
// +3 is to account for the closing fence // +3 is to account for the closing fense
if length < (limit + 3) { if length < (limit + 3) {
response.push(line); response.push(line);
limit -= length; limit -= length;

View file

@ -21,10 +21,11 @@ pub mod link {
use serenity::all::{CommandDataOption, CommandDataOptionValue, CommandInteraction}; use serenity::all::{CommandDataOption, CommandDataOptionValue, CommandInteraction};
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String { pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
let db = { let db_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone() data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone()
}; };
let db = db_lock.read().await;
let config_lock = { let config_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
@ -76,7 +77,7 @@ pub mod link {
Some(x) => x, Some(x) => x,
}; };
// save the user id and email to the db // save teh user id and email to teh db
match save_to_db_user(&db, id, email).await { match save_to_db_user(&db, id, email).await {
Ok(x) => x, Ok(x) => x,
Err(x) => { Err(x) => {
@ -100,7 +101,7 @@ pub mod link {
return "Email already verified".to_string(); return "Email already verified".to_string();
} }
// generate an auth key // generate a auth key
let auth = random_string(20); let auth = random_string(20);
match send_mail(&config, &details.email, &auth, &command.user.name) { match send_mail(&config, &details.email, &auth, &command.user.name) {
Ok(_) => match save_to_db(&db, &details, &auth, &command.user.id).await { Ok(_) => match save_to_db(&db, &details, &auth, &command.user.id).await {
@ -209,7 +210,7 @@ pub mod link {
.subject("Skynet: Link Discord to Wolves.") .subject("Skynet: Link Discord to Wolves.")
.multipart( .multipart(
// This is composed of two parts. // This is composed of two parts.
// also helps not trip spam settings (uneven number of urls) // also helps not trip spam settings (uneven number of url's
MultiPart::alternative() MultiPart::alternative()
.singlepart(SinglePart::builder().header(header::ContentType::TEXT_PLAIN).body(body_text)) .singlepart(SinglePart::builder().header(header::ContentType::TEXT_PLAIN).body(body_text))
.singlepart(SinglePart::builder().header(header::ContentType::TEXT_HTML).body(html.into_string())), .singlepart(SinglePart::builder().header(header::ContentType::TEXT_HTML).body(html.into_string())),
@ -313,10 +314,11 @@ pub mod verify {
use sqlx::Error; use sqlx::Error;
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String { pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
let db = { let db_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<DataBase>().expect("Expected Database in TypeMap.").clone() data_read.get::<DataBase>().expect("Expected Database in TypeMap.").clone()
}; };
let db = db_lock.read().await;
// check if user has used /link_wolves // check if user has used /link_wolves
let details = if let Some(x) = get_verify_from_db(&db, &command.user.id).await { let details = if let Some(x) = get_verify_from_db(&db, &command.user.id).await {
@ -354,7 +356,7 @@ pub mod verify {
Ok(_) => { Ok(_) => {
return match set_discord(&db, &command.user.id, &details.email).await { return match set_discord(&db, &command.user.id, &details.email).await {
Ok(_) => { Ok(_) => {
// get the right roles for the user // get teh right roles for the user
set_server_roles(&db, &command.user, ctx).await; set_server_roles(&db, &command.user, ctx).await;
// check if they are a committee member, and on that server // check if they are a committee member, and on that server
@ -458,8 +460,8 @@ pub mod verify {
let config = config_lock.read().await; let config = config_lock.read().await;
if let Some(x) = get_server_member_discord(db, &discord.id).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 the committee server then give the general committee role // if they are a member of one or more committees, and in teh committee server then give the teh general committee role
// they will get the more specific vanity role later // they will get teh more specific vanity role later
if !get_committees_id(db, x.id_wolves).await.is_empty() { if !get_committees_id(db, x.id_wolves).await.is_empty() {
let server = config.committee_server; let server = config.committee_server;
let committee_member = config.committee_role; let committee_member = config.committee_role;
@ -492,12 +494,13 @@ pub mod unlink {
use sqlx::{Pool, Sqlite}; use sqlx::{Pool, Sqlite};
pub async fn run(command: &CommandInteraction, ctx: &Context) -> String { pub async fn run(command: &CommandInteraction, ctx: &Context) -> String {
let db = { let db_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<DataBase>().expect("Expected Databse in TypeMap.").clone() data_read.get::<DataBase>().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 // dosent matter if there is one or not, it will be removed regardless
delete_link(&db, &command.user.id).await; delete_link(&db, &command.user.id).await;
"Discord link removed".to_string() "Discord link removed".to_string()

View file

@ -12,10 +12,11 @@ use sqlx::{
Error, FromRow, Pool, Row, Sqlite, Error, FromRow, Pool, Row, Sqlite,
}; };
use std::{str::FromStr, sync::Arc}; use std::{str::FromStr, sync::Arc};
use tokio::sync::RwLock;
pub struct DataBase; pub struct DataBase;
impl TypeMapKey for DataBase { impl TypeMapKey for DataBase {
type Value = Arc<Pool<Sqlite>>; type Value = Arc<RwLock<Pool<Sqlite>>>;
} }
#[derive(Debug, Clone, Deserialize, Serialize)] #[derive(Debug, Clone, Deserialize, Serialize)]

View file

@ -24,7 +24,7 @@ impl<'r> FromRow<'r, SqliteRow> for Minecraft {
/** /**
loop through all members of server loop through all members of server
get a list of folks with mc accounts that are members get a list of folks with mc accounts that are members
and a list that aren't members and a list that arent members
*/ */
pub async fn update_server(server_id: &str, db: &Pool<Sqlite>, g_id: &GuildId, config: &Config) { pub async fn update_server(server_id: &str, db: &Pool<Sqlite>, g_id: &GuildId, config: &Config) {
let mut usernames = vec![]; 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; post(&format!("{url_base}/files/delete"), &bearer, &deletion).await;
// recreate the file, passing in the type here so the compiler knows what type of Vec it is // recreate teh file, passing in the type here so the compiler knows what type of vec it is
post::<Vec<&str>>(&format!("{url_base}/files/write?file=%2Fwhitelist.json"), &bearer, &vec![]).await; post::<Vec<&str>>(&format!("{url_base}/files/write?file=%2Fwhitelist.json"), &bearer, &vec![]).await;
// reload the whitelist // reload the whitelist

View file

@ -1,13 +1,14 @@
// this code is taken from https://github.com/MCorange99/svg2colored-png/tree/main // 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 yoinked it from here. // I was unable to figure out how to use usvg myself so younked it from here.
use std::{ use std::{
ffi::OsStr, ffi::OsStr,
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::Arc,
}; };
// use clap::builder::OsStr;
use color_eyre::{eyre::bail, Result}; use color_eyre::{eyre::bail, Result};
use usvg_text_layout::TreeTextToPath;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Args { pub struct Args {
@ -16,7 +17,7 @@ pub struct Args {
/// Output folder where the PNG's will be placed /// Output folder where the PNG's will be placed
pub output: PathBuf, pub output: PathBuf,
/// Comma separated colors that will be used in HEX Eg. 000000,ffffff /// Comma seperated colors that will be used in HEX Eg. 000000,ffffff
/// Can be like an object: black:000000,white:ffffff /// Can be like an object: black:000000,white:ffffff
pub colors: String, pub colors: String,
@ -36,7 +37,7 @@ enum ColorType {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Renderer { pub struct Renderer {
fontdb: Arc<usvg::fontdb::Database>, fontdb: usvg_text_layout::fontdb::Database,
colors: ColorType, colors: ColorType,
size: (u32, u32), size: (u32, u32),
pub count: u64, pub count: u64,
@ -44,48 +45,60 @@ pub struct Renderer {
impl Renderer { impl Renderer {
pub fn new(args: &Args) -> Result<Self> { pub fn new(args: &Args) -> Result<Self> {
let mut db = usvg::fontdb::Database::default(); let mut db = usvg_text_layout::fontdb::Database::new();
db.load_system_fonts(); db.load_system_fonts();
let mut this = Self { let mut this = Self {
fontdb: Arc::new(db), fontdb: db,
colors: ColorType::None, colors: ColorType::None,
size: (args.width, args.height), size: (args.width, args.height),
count: 0, count: 0,
}; };
this.colors = if args.colors.contains(':') { let colors = if args.colors.contains(':') {
let obj = args.colors.split(',').map(|s| { //? object
let mut iter = s.split(':'); let obj = args
let [Some(a), Some(b), None] = std::array::from_fn(|_| iter.next()) else { .colors
dbg!("Invalid color object, try checking help"); .split(',')
return None; .map(|s| {
}; let s = s.split(':').collect::<Vec<&str>>();
Some((a.to_string(), b.to_string())) if s.len() < 2 {
}); dbg!("Invalid color object, try checking help");
return None;
}
let colors = obj Some((s[0].to_string(), s[1].to_string()))
.flatten()
.map(|c| {
std::fs::create_dir_all(args.output.join(&c.0))?;
Ok(c)
}) })
.collect::<std::io::Result<_>>()?; .collect::<Vec<Option<(String, String)>>>();
let mut colors = Vec::new();
for c in obj.into_iter().flatten() {
std::fs::create_dir_all(args.output.join(&c.0))?;
colors.push(c);
}
ColorType::Object(colors) ColorType::Object(colors)
} else { } else {
let colors = args //? list
.colors // let colors = args.colors.split(",").map(|s| {
.split(',') // s.to_string()
.map(|color| -> std::io::Result<String> { // })
std::fs::create_dir_all(args.output.join(color))?; // .collect::<Vec<String>>();
Ok(color.to_string())
}) let mut colors = Vec::new();
.collect::<std::io::Result<_>>()?;
for color in args.colors.split(',') {
std::fs::create_dir_all(args.output.join(color))?;
colors.push(color.to_string())
}
ColorType::Array(colors) ColorType::Array(colors)
}; };
this.colors = colors;
Ok(this) Ok(this)
} }
@ -131,11 +144,10 @@ impl Renderer {
let opt = usvg::Options { let opt = usvg::Options {
// Get file's absolute directory. // Get file's absolute directory.
resources_dir: std::fs::canonicalize(fi).ok().and_then(|p| p.parent().map(|p| p.to_path_buf())), resources_dir: std::fs::canonicalize(fi).ok().and_then(|p| p.parent().map(|p| p.to_path_buf())),
fontdb: self.fontdb.clone(),
..Default::default() ..Default::default()
}; };
let tree = match usvg::Tree::from_data(svg.as_bytes(), &opt) { let mut tree = match usvg::Tree::from_data(svg.as_bytes(), &opt) {
Ok(v) => v, Ok(v) => v,
Err(_) => { Err(_) => {
dbg!("Failed to parse {fi:?}"); dbg!("Failed to parse {fi:?}");
@ -143,14 +155,14 @@ impl Renderer {
} }
}; };
let mut pixmap = tiny_skia::Pixmap::new(self.size.0, self.size.1).unwrap(); tree.convert_text(&self.fontdb);
let scale = {
let x = tree.size().width() / self.size.0 as f32;
let y = tree.size().height() / self.size.0 as f32;
x.min(y)
};
resvg::render(&tree, usvg::Transform::default().post_scale(scale, scale), &mut pixmap.as_mut()); let mut pixmap = tiny_skia::Pixmap::new(self.size.0, self.size.1).unwrap();
// log::info!("Rendering {fo:?}");
//? maybe handle this and possibly throw error if its none
let _ = resvg::render(&tree, usvg::FitTo::Size(self.size.0, self.size.1), tiny_skia::Transform::default(), pixmap.as_mut());
pixmap.save_png(fo)?; pixmap.save_png(fo)?;
self.count += 1; self.count += 1;

View file

@ -281,7 +281,7 @@ pub mod update_icon {
// check if exists // check if exists
if !path_new.exists() { if !path_new.exists() {
// convert if it hasn't been converted already // convert if it hasnt been converted already
match r.render(&path_local, &args) { match r.render(&path_local, &args) {
Ok(_) => {} Ok(_) => {}
Err(_e) => { Err(_e) => {
@ -349,7 +349,7 @@ pub mod update_icon {
} }
async fn logo_set(ctx: &Context, db: &Pool<Sqlite>, server: &GuildId, logo_selected: &LogoData) { async fn logo_set(ctx: &Context, db: &Pool<Sqlite>, server: &GuildId, logo_selected: &LogoData) {
// add to the database // add to teh database
if !logo_set_db(db, logo_selected).await { if !logo_set_db(db, logo_selected).await {
// something went wrong // something went wrong
return; return;

View file

@ -17,11 +17,13 @@ pub mod normal {
} }
pub async fn update_server(ctx: &Context, server: &Servers, remove_roles: &[Option<RoleId>], members_changed: &[UserId]) { pub async fn update_server(ctx: &Context, server: &Servers, remove_roles: &[Option<RoleId>], members_changed: &[UserId]) {
let db = { let db_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<DataBase>().expect("Expected Database in TypeMap.").clone() data_read.get::<DataBase>().expect("Expected Database in TypeMap.").clone()
}; };
let db = db_lock.read().await;
let Servers { let Servers {
server, server,
role_past, role_past,
@ -46,7 +48,7 @@ pub mod normal {
if let Ok(x) = server.members(ctx, None, None).await { if let Ok(x) = server.members(ctx, None, None).await {
for member in x { for member in x {
// members_changed acts as an override to only deal with the users in it // members_changed acts as an override to only deal with teh users in it
if !members_changed.is_empty() && !members_changed.contains(&member.user.id) { if !members_changed.is_empty() && !members_changed.contains(&member.user.id) {
continue; continue;
} }
@ -82,7 +84,7 @@ pub mod normal {
if member.roles.contains(role_current) { if member.roles.contains(role_current) {
roles_set.current_rem += 1; roles_set.current_rem += 1;
// if they're not a current member and have the role then remove it // 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 { if let Err(e) = member.remove_role(ctx, role_current).await {
println!("{e:?}"); println!("{e:?}");
} }
@ -172,11 +174,13 @@ pub mod committee {
use std::collections::HashMap; use std::collections::HashMap;
pub async fn check_committee(ctx: &Context) { pub async fn check_committee(ctx: &Context) {
let db = { let db_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone() data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone()
}; };
let db = db_lock.read().await;
let config_lock = { let config_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<Config>().expect("Expected Config in TypeMap.").clone() data_read.get::<Config>().expect("Expected Config in TypeMap.").clone()
@ -185,14 +189,14 @@ pub mod committee {
let server = config_global.committee_server; let server = config_global.committee_server;
// because to use it to update a single user we need to pre-get the members of the server // 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(); 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;
} }
/** /**
This function can take a Vec of members (or just one) and gives them the appropriate roles on the committee server This function can take a vec of members (or just one) and gives tehm the appropiate roles on teh committee server
*/ */
pub async fn update_committees(db: &Pool<Sqlite>, ctx: &Context, config: &Config, members: &mut Vec<Member>) { pub async fn update_committees(db: &Pool<Sqlite>, ctx: &Context, config: &Config, members: &mut Vec<Member>) {
let server = config.committee_server; let server = config.committee_server;
@ -224,11 +228,11 @@ pub mod committee {
let mut channels = server.channels(&ctx).await.unwrap_or_default(); let mut channels = server.channels(&ctx).await.unwrap_or_default();
// a map of users and the roles they are going to be getting // a map of users and the roles they are goign to be getting
let mut users_roles = HashMap::new(); let mut users_roles = HashMap::new();
let mut re_order = false; let mut re_order = false;
// we need to create roles and channels if they don't already exist // we need to create roles and channels if tehy dont already exist
let mut category_index = 0; let mut category_index = 0;
let mut i = 0; let mut i = 0;
loop { loop {
@ -294,7 +298,7 @@ pub mod committee {
// save it to the db in case of crash or error // save it to the db in case of crash or error
db_role_set(db, &tmp).await; db_role_set(db, &tmp).await;
// insert it into the local cache // insert it into teh local cache
e.insert(tmp); e.insert(tmp);
re_order = true; re_order = true;
@ -327,7 +331,7 @@ pub mod committee {
} }
} }
// now we have a map of all users that should get roles time to go through all the folks on the server // 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 { for member in members {
// if member.user.id != 136522490632601600 { // if member.user.id != 136522490632601600 {
// continue; // continue;
@ -363,7 +367,7 @@ pub mod committee {
let has_committee_role = roles_current_id.contains(&committee_member); let has_committee_role = roles_current_id.contains(&committee_member);
if on_committee && !has_committee_role { if on_committee && !has_committee_role {
// if there are committee roles then give the general purpose role // if there are committee roles then give the general purporse role
roles_add.push(committee_member); roles_add.push(committee_member);
} }
if !on_committee && has_committee_role { if !on_committee && has_committee_role {
@ -401,10 +405,10 @@ pub mod committee {
if re_order { if re_order {
let channel_id = role.id_channel.to_owned(); let channel_id = role.id_channel.to_owned();
if let Some(channel) = channels.get_mut(&channel_id) { if let Some(channel) = channels.get_mut(&channel_id) {
// record the position of each of the C&S channels // record the position of each of teh C&S channels
positions.push(channel.position); positions.push(channel.position);
// pull out the channel names // pull out teh channel names
channel_names.push((role.name_channel.to_owned(), channel_id)); channel_names.push((role.name_channel.to_owned(), channel_id));
} }
} }

View file

@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
use sqlx::{Pool, Sqlite}; use sqlx::{Pool, Sqlite};
/** /**
This file relates to anything that directly interacts with the wolves API This file relates to anything that directly interacts with teh wolves API
*/ */
#[derive(Deserialize, Serialize, Debug)] #[derive(Deserialize, Serialize, Debug)]
@ -69,10 +69,11 @@ pub mod cns {
} }
pub async fn get_wolves(ctx: &Context) { pub async fn get_wolves(ctx: &Context) {
let db = { let db_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<DataBase>().expect("Expected Database in TypeMap.").clone() data_read.get::<DataBase>().expect("Expected Database in TypeMap.").clone()
}; };
let db = db_lock.read().await;
let config_lock = { let config_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
@ -80,7 +81,7 @@ pub mod cns {
}; };
let config = config_lock.read().await; let config = config_lock.read().await;
// set up the client // set up teh client
let wolves = wolves_oxidised::Client::new(&config.wolves_url, Some(&config.wolves_api)); let wolves = wolves_oxidised::Client::new(&config.wolves_url, Some(&config.wolves_api));
for server_config in get_server_config_bulk(&db).await { for server_config in get_server_config_bulk(&db).await {
@ -223,10 +224,11 @@ pub mod committees {
} }
pub async fn get_cns(ctx: &Context) { pub async fn get_cns(ctx: &Context) {
let db = { let db_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<DataBase>().expect("Expected Database in TypeMap.").clone() data_read.get::<DataBase>().expect("Expected Database in TypeMap.").clone()
}; };
let db = db_lock.read().await;
let config_lock = { let config_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;

View file

@ -12,7 +12,7 @@ use tokio::sync::RwLock;
#[derive(Debug)] #[derive(Debug)]
pub struct Config { pub struct Config {
// manages where the database is stored // manages where teh database is stored
pub home: String, pub home: String,
pub database: String, pub database: String,
@ -36,7 +36,7 @@ pub struct Config {
pub committee_role: RoleId, pub committee_role: RoleId,
pub committee_category: Vec<ChannelId>, pub committee_category: Vec<ChannelId>,
// items pertaining to CompSoc only // items pertaining to compsoc only
pub compsoc_server: GuildId, pub compsoc_server: GuildId,
} }
impl TypeMapKey for Config { impl TypeMapKey for Config {
@ -106,19 +106,22 @@ pub fn get_config() -> Config {
} }
} }
if let Ok(x) = env::var("COMMITTEE_ROLE") { if let Ok(x) = env::var("COMMITTEE_ROLE") {
let x = x.trim().parse().unwrap(); if let Ok(x) = x.trim().parse::<u64>() {
config.committee_role = RoleId::new(x); config.committee_role = RoleId::new(x);
}
} }
if let Ok(x) = env::var("COMMITTEE_CATEGORY") { if let Ok(x) = env::var("COMMITTEE_CATEGORY") {
for part in x.split(',') { for part in x.split(',') {
let x = part.trim().parse().unwrap(); if let Ok(x) = part.trim().parse::<u64>() {
config.committee_category.push(ChannelId::new(x)); config.committee_category.push(ChannelId::new(x));
}
} }
} }
if let Ok(x) = env::var("COMPSOC_DISCORD") { if let Ok(x) = env::var("COMPSOC_DISCORD") {
let x = x.trim().parse().unwrap(); if let Ok(x) = x.trim().parse::<u64>() {
config.compsoc_server = GuildId::new(x); config.compsoc_server = GuildId::new(x);
}
} }
config config

View file

@ -27,11 +27,12 @@ use sqlx::{Pool, Sqlite};
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::RwLock; use tokio::sync::RwLock;
// Need To Define The Stuct (Committed To Bump The Bot)
struct Handler; struct Handler;
#[async_trait] #[async_trait]
impl EventHandler for Handler { impl EventHandler for Handler {
// this caches members of all servers the bot is in // this caches members of all servers teh bot is in
async fn cache_ready(&self, ctx: Context, guilds: Vec<GuildId>) { async fn cache_ready(&self, ctx: Context, guilds: Vec<GuildId>) {
for guild in guilds { for guild in guilds {
ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None); ctx.shard.chunk_guild(guild, Some(2000), false, ChunkGuildFilter::None, None);
@ -41,11 +42,13 @@ impl EventHandler for Handler {
// handles previously linked accounts joining the server // handles previously linked accounts joining the server
async fn guild_member_addition(&self, ctx: Context, new_member: Member) { async fn guild_member_addition(&self, ctx: Context, new_member: Member) {
let db = { let db_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone() data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone()
}; };
let db = db_lock.read().await;
let config_lock = { let config_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<Config>().expect("Expected Config in TypeMap.").clone() data_read.get::<Config>().expect("Expected Config in TypeMap.").clone()
@ -107,12 +110,14 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use
// handles role updates // handles role updates
async fn guild_member_update(&self, ctx: Context, _old_data: Option<Member>, new_data: Option<Member>, _: GuildMemberUpdateEvent) { async fn guild_member_update(&self, ctx: Context, _old_data: Option<Member>, new_data: Option<Member>, _: GuildMemberUpdateEvent) {
// get config/db // get config/db
let db = { let db_lock = {
let data_read = ctx.data.read().await; let data_read = ctx.data.read().await;
data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone() data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone()
}; };
// check if the role changed is part of the ones for this server let db = db_lock.read().await;
// check if the role changed is part of the oens for this server
if let Some(x) = new_data { if let Some(x) = new_data {
on_role_change(&db, &ctx, x).await; on_role_change(&db, &ctx, x).await;
} }
@ -154,13 +159,13 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use
} }
} }
// CompSoc Server // compsoc Server
match config match config
.compsoc_server .compsoc_server
.set_commands( .set_commands(
&ctx.http, &ctx.http,
vec![ vec![
// commands just for the CompSoc server // commands just for the compsoc server
commands::count::servers::register(), commands::count::servers::register(),
commands::server_icon::user::register(), commands::server_icon::user::register(),
], ],
@ -177,7 +182,7 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use
async fn interaction_create(&self, ctx: Context, interaction: Interaction) { async fn interaction_create(&self, ctx: Context, interaction: Interaction) {
if let Interaction::Command(command) = interaction { if let Interaction::Command(command) = interaction {
let _ = command.defer_ephemeral(&ctx.http).await; 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() { let content = match command.data.name.as_str() {
// user commands // user commands
@ -212,7 +217,7 @@ Sign up on [UL Wolves]({}) and go to https://discord.com/channels/{}/{} and use
format!("not implemented :( committee {}", x.name.as_str()) format!("not implemented :( committee {}", x.name.as_str())
} }
}, },
// TODO: move the minecraft commands in here as a subgroup // TODO: move teh minecraft commands in here as a subgroup
// "link" => commands::count::servers::run(&command, &ctx).await, // "link" => commands::count::servers::run(&command, &ctx).await,
&_ => format!("not implemented :( committee {}", x.name.as_str()), &_ => format!("not implemented :( committee {}", x.name.as_str()),
}, },
@ -300,7 +305,7 @@ async fn main() {
let mut data = client.data.write().await; let mut data = client.data.write().await;
data.insert::<Config>(Arc::new(RwLock::new(config))); data.insert::<Config>(Arc::new(RwLock::new(config)));
data.insert::<DataBase>(Arc::new(db)); data.insert::<DataBase>(Arc::new(RwLock::new(db)));
} }
// Finally, start a single shard, and start listening to events. // Finally, start a single shard, and start listening to events.