use crate::common::database::Wolves; use serde::{Deserialize, Serialize}; use sqlx::{Pool, Sqlite}; /** This file relates to anything that directly interacts with teh wolves API */ #[derive(Deserialize, Serialize, Debug)] struct WolvesResultUserMin { // 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, } async fn add_users_wolves(db: &Pool, user: &WolvesResultUserMin) { // 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); } } } /** This is getting data for Clubs and Socs */ pub mod cns { use crate::common::database::{get_server_config_bulk, DataBase, ServerMembers, ServerMembersWolves, Servers}; use crate::common::wolves::{add_users_wolves, WolvesResultUserMin}; use crate::Config; use serenity::client::Context; use serenity::model::id::GuildId; use sqlx::{Pool, Sqlite}; use std::collections::BTreeMap; impl From<&wolves_oxidised::WolvesUser> for WolvesResultUserMin { fn from(value: &wolves_oxidised::WolvesUser) -> Self { Self { member_id: value.member_id.to_owned(), contact_email: value.contact_email.to_owned(), } } } pub async fn get_wolves(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; // set up teh client let wolves = wolves_oxidised::Client::new(&config.wolves_url, Some(&config.wolves_api)); for server_config in get_server_config_bulk(&db).await { let Servers { server, // this is the unique api key for each club/soc wolves_api, wolves_id, .. } = &server_config; // dbg!(&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 server_name_tmp = None; for user in wolves.get_members(wolves_api).await { // dbg!(&user.committee); if server_name_tmp.is_none() { server_name_tmp = Some(user.committee_id); } 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, &WolvesResultUserMin::from(&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, &WolvesResultUserMin::from(&user)).await; if old.expiry != user.expiry { add_users_server_members(&db, server, &user).await; } } } } if let Some(cs_id) = server_name_tmp { if &cs_id != wolves_id { set_server_member(&db, server, cs_id).await; } } } } async fn set_server_member(db: &Pool, server: &GuildId, wolves_id: i64) { match sqlx::query_as::<_, Servers>( " UPDATE servers SET wolves_id = ? WHERE server = ? ", ) .bind(wolves_id) .bind(server.get() as i64) .fetch_optional(db) .await { Ok(_) => {} Err(e) => { println!("Failure to set server name {}", server.get()); println!("{:?}", e); } } } 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.get() as i64) .fetch_all(db) .await .unwrap_or_default() } async fn add_users_server_members(db: &Pool, server: &GuildId, user: &wolves_oxidised::WolvesUser) { match sqlx::query_as::<_, ServerMembers>( " INSERT OR REPLACE INTO server_members (server, id_wolves, expiry) VALUES (?1, ?2, ?3) ", ) .bind(server.get() as i64) .bind(&user.member_id) .bind(&user.expiry) .fetch_optional(db) .await { Ok(_) => {} Err(e) => { println!("Failure to insert into ServerMembers {} {:?}", server.get(), user); println!("{:?}", e); } } } } /** Get and store the data on C&S committees */ pub mod committees { use crate::common::database::DataBase; use crate::Config; use serenity::client::Context; use sqlx::{Pool, Sqlite}; // Database entry for it #[derive(Debug, Clone, sqlx::FromRow)] pub struct Committees { pub id: i64, pub name_full: String, pub name_profile: String, pub name_plain: String, pub link: String, #[sqlx(json)] pub committee: Vec, } impl From for Committees { fn from(value: wolves_oxidised::WolvesCNS) -> Self { Self { id: value.id, name_full: value.name_full, name_profile: value.name_profile, name_plain: value.name_plain, link: value.link, committee: value.committee, } } } pub async fn get_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; let wolves = wolves_oxidised::Client::new(&config.wolves_url, Some(&config.wolves_api)); // request data from wolves for committee_wolves in wolves.get_committees().await { let committee = Committees::from(committee_wolves); add_committee(&db, &committee).await; } } async fn add_committee(db: &Pool, committee: &Committees) { match sqlx::query_as::<_, Committees>( " INSERT INTO committees (id, name_profile, name_full, name_plain, link, committee) VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT(id) DO UPDATE SET committee = $6 ", ) .bind(committee.id) .bind(&committee.name_profile) .bind(&committee.name_full) .bind(&committee.name_plain) .bind(&committee.link) .bind(serde_json::to_string(&committee.committee).unwrap_or_default()) .fetch_optional(db) .await { Ok(_) => {} Err(e) => { println!("Failure to insert into Committees {:?}", committee); println!("{:?}", e); } } } }