diff --git a/src/bin/update_data.rs b/src/bin/update_data.rs index ec3713a..b5d89a5 100644 --- a/src/bin/update_data.rs +++ b/src/bin/update_data.rs @@ -4,9 +4,10 @@ use serenity::{ model::gateway::{GatewayIntents, Ready}, Client, }; -use skynet_discord_bot::{db_init, get_config, get_data::get_wolves_cns, Config, DataBase}; +use skynet_discord_bot::{db_init, get_config, Config, DataBase}; use std::{process, sync::Arc}; use tokio::sync::RwLock; +use skynet_discord_bot::common::wolves::get_data::get_wolves_cns; #[tokio::main] async fn main() { diff --git a/src/commands/add_server.rs b/src/commands/add_server.rs index 1889257..8c7e9e5 100644 --- a/src/commands/add_server.rs +++ b/src/commands/add_server.rs @@ -6,7 +6,7 @@ use serenity::{ prelude::{command::CommandOptionType, interaction::application_command::CommandDataOptionValue}, }, }; -use skynet_discord_bot::get_data::get_wolves_cns; +use skynet_discord_bot::common::wolves::get_data::get_wolves_cns; use skynet_discord_bot::{get_server_config, is_admin, set_roles::update_server, DataBase, Servers}; use sqlx::{Error, Pool, Sqlite}; diff --git a/src/common/database.rs b/src/common/database.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/common/mod.rs b/src/common/mod.rs new file mode 100644 index 0000000..5d73638 --- /dev/null +++ b/src/common/mod.rs @@ -0,0 +1 @@ +pub mod wolves; \ No newline at end of file diff --git a/src/common/wolves.rs b/src/common/wolves.rs new file mode 100644 index 0000000..d92c34d --- /dev/null +++ b/src/common/wolves.rs @@ -0,0 +1,187 @@ +/** + This file relates to anything that directly interacts with teh wolves API + */ + + +// #[derive(Debug, Clone, sqlx::FromRow)] +// pub struct Committees { +// pub id: i64, +// pub name: String, +// pub link: String, +// pub members: Vec, +// } + +pub mod get_data { + use crate::set_roles::update_server; + use std::collections::BTreeMap; + use serde::{Deserialize, Serialize}; + use serenity::client::Context; + use serenity::model::id::GuildId; + use sqlx::{Pool, Sqlite}; + use crate::{get_server_config_bulk, Config, DataBase, ServerMembers, ServerMembersWolves, Servers, Wolves}; + + #[derive(Deserialize, Serialize, Debug)] + struct WolvesResultUser { + committee: String, + member_id: String, + first_name: String, + last_name: String, + contact_email: String, + opt_in_email: String, + student_id: Option, + note: Option, + expiry: String, + requested: String, + approved: String, + sitename: String, + domain: String, + } + + #[derive(Deserialize, Serialize, Debug)] + struct WolvesResult { + success: i8, + result: Vec, + } + + #[derive(Deserialize, Serialize, Debug)] + struct WolvesResultLocal { + pub id_wolves: String, + pub email: String, + pub expiry: String, + } + pub async fn get_wolves_cns(ctx: &Context) { + let db_lock = { + 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; + data_read.get::().expect("Expected Config in TypeMap.").clone() + }; + let config = config_lock.read().await; + + for server_config in get_server_config_bulk(&db).await { + let Servers { + server, + wolves_api, + .. + } = &server_config; + + let existing_tmp = get_server_member(&db, server).await; + 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![]; + for user in get_wolves_cns_sub(&config, wolves_api).await { + let id = user.member_id.parse::().unwrap_or_default(); + match existing.get(&(id as i64)) { + None => { + // user does not exist already, add everything + add_users_wolves(&db, &user).await; + add_users_server_members(&db, server, &user).await; + } + Some(old) => { + // always update wolves table, in case data has changed + add_users_wolves(&db, &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); + } + } + } + } + } + + if !user_to_update.is_empty() { + update_server(ctx, &server_config, &[], &user_to_update).await; + } + } + } + + pub async fn get_server_member(db: &Pool, server: &GuildId) -> Vec { + sqlx::query_as::<_, ServerMembersWolves>( + r#" + SELECT * + FROM server_members + JOIN wolves USING (id_wolves) + WHERE ( + server = ? + AND discord IS NOT NULL + ) + "#, + ) + .bind(*server.as_u64() as i64) + .fetch_all(db) + .await + .unwrap_or_default() + } + + async fn get_wolves_cns_sub(config: &Config, wolves_api: &str) -> Vec { + if config.wolves_url.is_empty() { + return vec![]; + } + + // get wolves data + if let Ok(mut res) = surf::post(&config.wolves_url).header("X-AM-Identity", wolves_api).await { + if let Ok(WolvesResult { + success, + result, + }) = res.body_json().await + { + if success != 1 { + return vec![]; + } + + return result; + } + } + + vec![] + } + + async fn add_users_wolves(db: &Pool, user: &WolvesResultUser) { + // expiry + match sqlx::query_as::<_, Wolves>( + " + INSERT INTO wolves (id_wolves, email) + VALUES ($1, $2) + ON CONFLICT(id_wolves) DO UPDATE SET email = $2 + ", + ) + .bind(&user.member_id) + .bind(&user.contact_email) + .fetch_optional(db) + .await + { + Ok(_) => {} + Err(e) => { + println!("Failure to insert into Wolves {:?}", user); + println!("{:?}", e); + } + } + } + async fn add_users_server_members(db: &Pool, server: &GuildId, user: &WolvesResultUser) { + match sqlx::query_as::<_, ServerMembers>( + " + INSERT OR REPLACE INTO server_members (server, id_wolves, expiry) + VALUES (?1, ?2, ?3) + ", + ) + .bind(*server.as_u64() as i64) + .bind(&user.member_id) + .bind(&user.expiry) + .fetch_optional(db) + .await + { + Ok(_) => {} + Err(e) => { + println!("Failure to insert into ServerMembers {} {:?}", server.as_u64(), user); + println!("{:?}", e); + } + } + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 6c6ded9..9e1c599 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +pub mod common; + use dotenvy::dotenv; use serde::{Deserialize, Serialize}; use serenity::{ @@ -202,13 +204,6 @@ impl<'r> FromRow<'r, SqliteRow> for WolvesVerify { } } -#[derive(Debug, Clone, sqlx::FromRow)] -pub struct Committee { - pub id: i64, - pub name: UserId, - pub members: Vec, -} - #[derive(Debug, Clone, Deserialize, Serialize)] pub struct Servers { pub server: GuildId, @@ -218,7 +213,7 @@ pub struct Servers { pub member_past: i64, pub member_current: i64, pub bot_channel_id: ChannelId, - // these can be removed in teh future with an API update + // TODO: these can be removed in teh future with an API update pub server_name: String, pub wolves_link: String, } @@ -508,177 +503,6 @@ pub mod set_roles { } } -pub mod get_data { - use super::*; - use crate::set_roles::update_server; - use std::collections::BTreeMap; - - #[derive(Deserialize, Serialize, Debug)] - struct WolvesResultUser { - committee: String, - member_id: String, - first_name: String, - last_name: String, - contact_email: String, - opt_in_email: String, - student_id: Option, - note: Option, - expiry: String, - requested: String, - approved: String, - sitename: String, - domain: String, - } - - #[derive(Deserialize, Serialize, Debug)] - struct WolvesResult { - success: i8, - result: Vec, - } - - #[derive(Deserialize, Serialize, Debug)] - struct WolvesResultLocal { - pub id_wolves: String, - pub email: String, - pub expiry: String, - } - pub async fn get_wolves_cns(ctx: &Context) { - let db_lock = { - 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; - data_read.get::().expect("Expected Config in TypeMap.").clone() - }; - let config = config_lock.read().await; - - for server_config in get_server_config_bulk(&db).await { - let Servers { - server, - wolves_api, - .. - } = &server_config; - - let existing_tmp = get_server_member(&db, server).await; - 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![]; - for user in get_wolves_cns_sub(&config, wolves_api).await { - let id = user.member_id.parse::().unwrap_or_default(); - match existing.get(&(id as i64)) { - None => { - // user does not exist already, add everything - add_users_wolves(&db, &user).await; - add_users_server_members(&db, server, &user).await; - } - Some(old) => { - // always update wolves table, in case data has changed - add_users_wolves(&db, &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); - } - } - } - } - } - - if !user_to_update.is_empty() { - update_server(ctx, &server_config, &[], &user_to_update).await; - } - } - } - - pub async fn get_server_member(db: &Pool, server: &GuildId) -> Vec { - sqlx::query_as::<_, ServerMembersWolves>( - r#" - SELECT * - FROM server_members - JOIN wolves USING (id_wolves) - WHERE ( - server = ? - AND discord IS NOT NULL - ) - "#, - ) - .bind(*server.as_u64() as i64) - .fetch_all(db) - .await - .unwrap_or_default() - } - - async fn get_wolves_cns_sub(config: &Config, wolves_api: &str) -> Vec { - if config.wolves_url.is_empty() { - return vec![]; - } - - // get wolves data - if let Ok(mut res) = surf::post(&config.wolves_url).header("X-AM-Identity", wolves_api).await { - if let Ok(WolvesResult { - success, - result, - }) = res.body_json().await - { - if success != 1 { - return vec![]; - } - - return result; - } - } - - vec![] - } - - async fn add_users_wolves(db: &Pool, user: &WolvesResultUser) { - // expiry - match sqlx::query_as::<_, Wolves>( - " - INSERT INTO wolves (id_wolves, email) - VALUES ($1, $2) - ON CONFLICT(id_wolves) DO UPDATE SET email = $2 - ", - ) - .bind(&user.member_id) - .bind(&user.contact_email) - .fetch_optional(db) - .await - { - Ok(_) => {} - Err(e) => { - println!("Failure to insert into Wolves {:?}", user); - println!("{:?}", e); - } - } - } - async fn add_users_server_members(db: &Pool, server: &GuildId, user: &WolvesResultUser) { - match sqlx::query_as::<_, ServerMembers>( - " - INSERT OR REPLACE INTO server_members (server, id_wolves, expiry) - VALUES (?1, ?2, ?3) - ", - ) - .bind(*server.as_u64() as i64) - .bind(&user.member_id) - .bind(&user.expiry) - .fetch_optional(db) - .await - { - Ok(_) => {} - Err(e) => { - println!("Failure to insert into ServerMembers {} {:?}", server.as_u64(), user); - println!("{:?}", e); - } - } - } -} - /** For any time ye need to check if a user who calls a command has admin privlages */