2024-10-28 21:53:04 +00:00
|
|
|
use crate::common::database::Wolves;
|
2024-10-28 02:06:24 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use sqlx::{Pool, Sqlite};
|
|
|
|
|
2024-10-28 00:51:39 +00:00
|
|
|
/**
|
2024-10-28 21:53:04 +00:00
|
|
|
This file relates to anything that directly interacts with teh wolves API
|
|
|
|
*/
|
2024-10-28 00:51:39 +00:00
|
|
|
|
2024-10-28 02:06:24 +00:00
|
|
|
#[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<String>,
|
|
|
|
// note: Option<String>,
|
|
|
|
// expiry: String,
|
|
|
|
// requested: String,
|
|
|
|
// approved: String,
|
|
|
|
// sitename: String,
|
|
|
|
// domain: String,
|
|
|
|
}
|
|
|
|
async fn add_users_wolves(db: &Pool<Sqlite>, 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
|
|
|
|
",
|
|
|
|
)
|
2024-10-28 21:53:04 +00:00
|
|
|
.bind(&user.member_id)
|
|
|
|
.bind(&user.contact_email)
|
|
|
|
.fetch_optional(db)
|
|
|
|
.await
|
2024-10-28 02:06:24 +00:00
|
|
|
{
|
|
|
|
Ok(_) => {}
|
|
|
|
Err(e) => {
|
|
|
|
println!("Failure to insert into Wolves {:?}", user);
|
|
|
|
println!("{:?}", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-28 01:29:01 +00:00
|
|
|
/**
|
|
|
|
This is getting data for Clubs and Socs
|
|
|
|
*/
|
|
|
|
pub mod cns {
|
2024-10-28 21:53:04 +00:00
|
|
|
use crate::common::database::{get_server_config_bulk, DataBase, ServerMembers, ServerMembersWolves, Servers};
|
2024-10-28 21:34:21 +00:00
|
|
|
use crate::common::set_roles::normal::update_server;
|
2024-10-28 21:53:04 +00:00
|
|
|
use crate::common::wolves::{add_users_wolves, WolvesResultUserMin};
|
|
|
|
use crate::Config;
|
2024-10-28 00:51:39 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use serenity::client::Context;
|
|
|
|
use serenity::model::id::GuildId;
|
|
|
|
use sqlx::{Pool, Sqlite};
|
2024-10-28 21:53:04 +00:00
|
|
|
use std::collections::BTreeMap;
|
2024-10-28 00:51:39 +00:00
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Debug)]
|
|
|
|
struct WolvesResultUser {
|
2024-10-28 21:51:14 +00:00
|
|
|
// TODO: Might be worth trying to get this replaced with the club/soc ID?
|
2024-10-28 00:51:39 +00:00
|
|
|
committee: String,
|
|
|
|
member_id: String,
|
|
|
|
first_name: String,
|
|
|
|
last_name: String,
|
|
|
|
contact_email: String,
|
|
|
|
opt_in_email: String,
|
|
|
|
student_id: Option<String>,
|
|
|
|
note: Option<String>,
|
|
|
|
expiry: String,
|
|
|
|
requested: String,
|
|
|
|
approved: String,
|
|
|
|
sitename: String,
|
|
|
|
domain: String,
|
|
|
|
}
|
|
|
|
|
2024-10-28 02:06:24 +00:00
|
|
|
impl From<&WolvesResultUser> for WolvesResultUserMin {
|
|
|
|
fn from(value: &WolvesResultUser) -> Self {
|
|
|
|
Self {
|
|
|
|
member_id: value.member_id.to_owned(),
|
|
|
|
contact_email: value.contact_email.to_owned(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-28 00:51:39 +00:00
|
|
|
#[derive(Deserialize, Serialize, Debug)]
|
|
|
|
struct WolvesResult {
|
|
|
|
success: i8,
|
|
|
|
result: Vec<WolvesResultUser>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Debug)]
|
|
|
|
struct WolvesResultLocal {
|
|
|
|
pub id_wolves: String,
|
|
|
|
pub email: String,
|
|
|
|
pub expiry: String,
|
|
|
|
}
|
2024-10-28 01:29:01 +00:00
|
|
|
pub async fn get_wolves(ctx: &Context) {
|
2024-10-28 00:51:39 +00:00
|
|
|
let db_lock = {
|
|
|
|
let data_read = ctx.data.read().await;
|
|
|
|
data_read.get::<DataBase>().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::<Config>().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::<BTreeMap<_, _>>();
|
|
|
|
|
|
|
|
// list of users that need to be updated for this server
|
|
|
|
let mut user_to_update = vec![];
|
2024-10-28 01:29:01 +00:00
|
|
|
for user in get_wolves_sub(&config, wolves_api).await {
|
2024-10-28 00:51:39 +00:00
|
|
|
let id = user.member_id.parse::<u64>().unwrap_or_default();
|
|
|
|
match existing.get(&(id as i64)) {
|
|
|
|
None => {
|
|
|
|
// user does not exist already, add everything
|
2024-10-28 02:06:24 +00:00
|
|
|
add_users_wolves(&db, &WolvesResultUserMin::from(&user)).await;
|
2024-10-28 00:51:39 +00:00
|
|
|
add_users_server_members(&db, server, &user).await;
|
|
|
|
}
|
|
|
|
Some(old) => {
|
|
|
|
// always update wolves table, in case data has changed
|
2024-10-28 02:06:24 +00:00
|
|
|
add_users_wolves(&db, &WolvesResultUserMin::from(&user)).await;
|
2024-10-28 00:51:39 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-28 01:29:01 +00:00
|
|
|
async fn get_server_member(db: &Pool<Sqlite>, server: &GuildId) -> Vec<ServerMembersWolves> {
|
2024-10-28 00:51:39 +00:00
|
|
|
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()
|
|
|
|
}
|
|
|
|
|
2024-10-28 01:29:01 +00:00
|
|
|
async fn get_wolves_sub(config: &Config, wolves_api: &str) -> Vec<WolvesResultUser> {
|
2024-10-28 00:51:39 +00:00
|
|
|
if config.wolves_url.is_empty() {
|
|
|
|
return vec![];
|
|
|
|
}
|
|
|
|
|
2024-10-28 02:06:24 +00:00
|
|
|
let url = format!("{}/get_members", &config.wolves_url);
|
|
|
|
|
2024-10-28 00:51:39 +00:00
|
|
|
// get wolves data
|
2024-10-28 02:06:24 +00:00
|
|
|
if let Ok(mut res) = surf::post(&url).header("X-AM-Identity", wolves_api).await {
|
2024-10-28 00:51:39 +00:00
|
|
|
if let Ok(WolvesResult {
|
|
|
|
success,
|
|
|
|
result,
|
|
|
|
}) = res.body_json().await
|
|
|
|
{
|
|
|
|
if success != 1 {
|
|
|
|
return vec![];
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vec![]
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn add_users_server_members(db: &Pool<Sqlite>, 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-10-28 01:34:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Get and store the data on C&S committees
|
|
|
|
*/
|
2024-10-28 12:49:35 +00:00
|
|
|
pub mod committees {
|
2024-10-28 21:53:04 +00:00
|
|
|
use crate::common::database::DataBase;
|
|
|
|
use crate::Config;
|
2024-10-28 12:49:35 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use serenity::client::Context;
|
2024-10-28 21:53:04 +00:00
|
|
|
use sqlx::{Pool, Sqlite};
|
2024-10-28 12:49:35 +00:00
|
|
|
|
|
|
|
// This is what Wolves returns to us
|
|
|
|
#[derive(Deserialize, Serialize, Debug)]
|
|
|
|
struct WolvesResult {
|
|
|
|
success: i8,
|
|
|
|
result: Vec<WolvesResultCNS>,
|
|
|
|
}
|
|
|
|
|
|
|
|
// this is teh actual data we care about
|
|
|
|
#[derive(Deserialize, Serialize, Debug)]
|
|
|
|
struct WolvesResultCNS {
|
|
|
|
id: String,
|
|
|
|
name: String,
|
|
|
|
// Link to their page such as https://ulwolves.ie/society/computer
|
|
|
|
link: String,
|
|
|
|
// array of Committee members member_id's
|
2024-10-28 21:53:04 +00:00
|
|
|
committee: Vec<String>,
|
2024-10-28 12:49:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Database entry for it
|
|
|
|
#[derive(Debug, Clone, sqlx::FromRow)]
|
|
|
|
pub struct Committees {
|
2024-10-28 21:53:04 +00:00
|
|
|
pub id: i64,
|
|
|
|
pub name: String,
|
|
|
|
pub link: String,
|
|
|
|
#[sqlx(json)]
|
|
|
|
pub committee: Vec<i64>,
|
2024-10-28 12:49:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl From<WolvesResultCNS> for Committees {
|
|
|
|
fn from(value: WolvesResultCNS) -> Self {
|
2024-10-28 21:53:04 +00:00
|
|
|
Self {
|
2024-10-28 12:49:35 +00:00
|
|
|
id: value.id.parse().unwrap_or(0),
|
|
|
|
name: value.name,
|
|
|
|
link: value.link,
|
|
|
|
committee: value.committee.iter().map(|x| x.parse::<i64>().unwrap_or(0)).collect(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-28 21:53:04 +00:00
|
|
|
pub async fn get_cns(ctx: &Context) {
|
2024-10-28 12:49:35 +00:00
|
|
|
let db_lock = {
|
|
|
|
let data_read = ctx.data.read().await;
|
|
|
|
data_read.get::<DataBase>().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::<Config>().expect("Expected Config in TypeMap.").clone()
|
|
|
|
};
|
|
|
|
let config = config_lock.read().await;
|
|
|
|
|
|
|
|
// request data from wolves
|
2024-11-09 12:51:41 +00:00
|
|
|
for committee_wolves in get_committees(&config).await {
|
|
|
|
let committee = Committees::from(committee_wolves);
|
|
|
|
add_committee(&db, &committee).await;
|
2024-10-28 12:49:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-09 12:51:41 +00:00
|
|
|
async fn get_committees(config: &Config) -> Vec<WolvesResultCNS> {
|
2024-10-28 12:49:35 +00:00
|
|
|
if config.wolves_url.is_empty() {
|
|
|
|
return vec![];
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Change teh stored env value to teh base domain
|
2024-11-09 12:51:41 +00:00
|
|
|
// TODO: this address may change
|
2024-10-28 12:49:35 +00:00
|
|
|
let url = format!("{}/get_cns", &config.wolves_url);
|
|
|
|
|
|
|
|
// get wolves data
|
2024-11-09 12:51:41 +00:00
|
|
|
if let Ok(mut res) = surf::post(&url).header("X-AM-Identity", &config.wolves_api).await {
|
2024-10-28 21:53:04 +00:00
|
|
|
if let Ok(WolvesResult {
|
|
|
|
success,
|
|
|
|
result,
|
|
|
|
}) = res.body_json().await
|
|
|
|
{
|
2024-10-28 12:49:35 +00:00
|
|
|
if success != 1 {
|
|
|
|
return vec![];
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vec![]
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn add_committee(db: &Pool<Sqlite>, committee: &Committees) {
|
|
|
|
match sqlx::query_as::<_, Committees>(
|
|
|
|
"
|
|
|
|
INSERT INTO committees (id, name, link, committee)
|
|
|
|
VALUES ($1, $2, $3, $4)
|
|
|
|
ON CONFLICT(id) DO UPDATE SET committee = $4
|
|
|
|
",
|
|
|
|
)
|
2024-10-28 21:53:04 +00:00
|
|
|
.bind(committee.id)
|
|
|
|
.bind(&committee.name)
|
|
|
|
.bind(&committee.link)
|
|
|
|
.bind(serde_json::to_string(&committee.committee).unwrap_or_default())
|
|
|
|
.fetch_optional(db)
|
|
|
|
.await
|
2024-10-28 12:49:35 +00:00
|
|
|
{
|
|
|
|
Ok(_) => {}
|
|
|
|
Err(e) => {
|
|
|
|
println!("Failure to insert into Committees {:?}", committee);
|
|
|
|
println!("{:?}", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-10-28 01:34:23 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
get the data for an individual user
|
|
|
|
*/
|
2024-10-28 02:06:24 +00:00
|
|
|
pub mod individual {
|
|
|
|
use crate::common::database::DataBase;
|
|
|
|
use crate::common::wolves::{add_users_wolves, WolvesResultUserMin};
|
|
|
|
use crate::Config;
|
2024-10-28 21:53:04 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use serenity::client::Context;
|
2024-10-28 02:06:24 +00:00
|
|
|
|
|
|
|
#[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<String>,
|
|
|
|
// note: Option<String>,
|
|
|
|
// expiry: String,
|
|
|
|
// requested: String,
|
|
|
|
// approved: String,
|
|
|
|
// sitename: String,
|
|
|
|
// domain: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<&WolvesResultUser> for WolvesResultUserMin {
|
|
|
|
fn from(value: &WolvesResultUser) -> Self {
|
|
|
|
Self {
|
|
|
|
member_id: value.member_id.to_owned(),
|
|
|
|
contact_email: value.contact_email.to_owned(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Debug)]
|
|
|
|
struct WolvesResult {
|
|
|
|
success: i8,
|
|
|
|
result: WolvesResultUser,
|
|
|
|
}
|
|
|
|
|
2024-10-28 21:53:04 +00:00
|
|
|
pub async fn get_user(ctx: &Context, email: &str) -> bool {
|
2024-10-28 02:06:24 +00:00
|
|
|
let db_lock = {
|
|
|
|
let data_read = ctx.data.read().await;
|
|
|
|
data_read.get::<DataBase>().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::<Config>().expect("Expected Config in TypeMap.").clone()
|
|
|
|
};
|
|
|
|
let config = config_lock.read().await;
|
|
|
|
|
|
|
|
// TODO: proper api key management
|
|
|
|
let api_key = "";
|
|
|
|
// request data from wolves
|
|
|
|
match get_user_sub(&config, api_key, email).await {
|
2024-10-28 21:53:04 +00:00
|
|
|
None => false,
|
2024-10-28 02:06:24 +00:00
|
|
|
// if exists save it and return true
|
|
|
|
Some(user) => {
|
|
|
|
// add to db
|
|
|
|
add_users_wolves(&db, &WolvesResultUserMin::from(&user)).await;
|
|
|
|
|
|
|
|
true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-10-28 21:53:04 +00:00
|
|
|
async fn get_user_sub(config: &Config, wolves_api: &str, _email: &str) -> Option<WolvesResultUser> {
|
2024-10-28 02:06:24 +00:00
|
|
|
if config.wolves_url.is_empty() {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Change teh stored env value to teh base domain
|
|
|
|
let url = format!("{}/get_member", &config.wolves_url);
|
|
|
|
|
|
|
|
// get wolves data
|
|
|
|
if let Ok(mut res) = surf::post(&url).header("X-AM-Identity", wolves_api).await {
|
2024-10-28 21:53:04 +00:00
|
|
|
if let Ok(WolvesResult {
|
|
|
|
success,
|
|
|
|
result,
|
|
|
|
}) = res.body_json().await
|
|
|
|
{
|
2024-10-28 02:06:24 +00:00
|
|
|
if success != 1 {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Some(result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
None
|
|
|
|
}
|
2024-10-28 21:53:04 +00:00
|
|
|
}
|