Compare commits
10 commits
3927734083
...
344d6d3585
Author | SHA1 | Date | |
---|---|---|---|
344d6d3585 | |||
b7161e2614 | |||
32249364ff | |||
f1138a3c81 | |||
61e76db8dd | |||
3e6dc9d560 | |||
aff6299ac7 | |||
bd80bda22f | |||
fe5aa5b252 | |||
273c58d035 |
17 changed files with 643 additions and 255 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2419,6 +2419,7 @@ dependencies = [
|
||||||
"maud",
|
"maud",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"serenity",
|
"serenity",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"surf",
|
"surf",
|
||||||
|
|
|
@ -26,6 +26,7 @@ dotenvy = "0.15.7"
|
||||||
|
|
||||||
# For sqlite
|
# For sqlite
|
||||||
sqlx = { version = "0.7.1", features = [ "runtime-tokio", "sqlite", "migrate" ] }
|
sqlx = { version = "0.7.1", features = [ "runtime-tokio", "sqlite", "migrate" ] }
|
||||||
|
serde_json = { version = "1.0", features = ["raw_value"] }
|
||||||
|
|
||||||
# create random strings
|
# create random strings
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
|
|
@ -3,8 +3,8 @@ DROP TABLE committee;
|
||||||
|
|
||||||
-- new table pulling from teh api
|
-- new table pulling from teh api
|
||||||
CREATE TABLE IF NOT EXISTS committees (
|
CREATE TABLE IF NOT EXISTS committees (
|
||||||
id integer PRIMARY KEY,
|
id integer PRIMARY KEY,
|
||||||
name text not null,
|
name text not null,
|
||||||
link text not null,
|
link text not null,
|
||||||
members text not null
|
committee text not null
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
use serenity::{
|
use serenity::{
|
||||||
async_trait,
|
async_trait,
|
||||||
client::{Context, EventHandler},
|
client::{Context, EventHandler},
|
||||||
model::gateway::{GatewayIntents, Ready},
|
model::gateway::{GatewayIntents, Ready},
|
||||||
Client,
|
Client,
|
||||||
};
|
};
|
||||||
|
use skynet_discord_bot::common::database::{db_init, DataBase};
|
||||||
|
use skynet_discord_bot::common::wolves::cns::get_wolves;
|
||||||
|
use skynet_discord_bot::common::wolves::committees::get_cns;
|
||||||
use skynet_discord_bot::{get_config, Config};
|
use skynet_discord_bot::{get_config, Config};
|
||||||
use std::{process, sync::Arc};
|
use std::{process, sync::Arc};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
use skynet_discord_bot::common::database::{db_init, DataBase};
|
|
||||||
use skynet_discord_bot::common::wolves::get_data::get_wolves_cns;
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
@ -46,7 +47,10 @@ impl EventHandler for Handler {
|
||||||
println!("{} is connected!", ready.user.name);
|
println!("{} is connected!", ready.user.name);
|
||||||
|
|
||||||
// get the data for each individual club/soc
|
// get the data for each individual club/soc
|
||||||
get_wolves_cns(&ctx).await;
|
get_wolves(&ctx).await;
|
||||||
|
|
||||||
|
// get teh data for the clubs/socs committees
|
||||||
|
get_cns(&ctx).await;
|
||||||
|
|
||||||
// finish up
|
// finish up
|
||||||
process::exit(0);
|
process::exit(0);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use skynet_discord_bot::get_config;
|
|
||||||
use std::collections::HashSet;
|
|
||||||
use skynet_discord_bot::common::database::db_init;
|
use skynet_discord_bot::common::database::db_init;
|
||||||
use skynet_discord_bot::common::minecraft::{get_minecraft_config, update_server, whitelist_wipe};
|
use skynet_discord_bot::common::minecraft::{get_minecraft_config, update_server, whitelist_wipe};
|
||||||
|
use skynet_discord_bot::get_config;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
use serenity::{
|
use serenity::{
|
||||||
async_trait,
|
async_trait,
|
||||||
client::{Context, EventHandler},
|
client::{Context, EventHandler},
|
||||||
model::gateway::{GatewayIntents, Ready},
|
model::gateway::{GatewayIntents, Ready},
|
||||||
Client,
|
Client,
|
||||||
};
|
};
|
||||||
use skynet_discord_bot::{get_config, set_roles, Config};
|
use skynet_discord_bot::common::database::{db_init, get_server_config_bulk, DataBase};
|
||||||
|
use skynet_discord_bot::common::set_roles::{committee, normal};
|
||||||
|
use skynet_discord_bot::{get_config, Config};
|
||||||
use std::{process, sync::Arc};
|
use std::{process, sync::Arc};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
use skynet_discord_bot::common::database::{db_init, get_server_config_bulk, DataBase};
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
@ -44,14 +45,18 @@ 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);
|
||||||
|
|
||||||
bulk_check(Arc::clone(&ctx)).await;
|
// this goes into each server and sets roles for each wolves member
|
||||||
|
check_bulk(Arc::clone(&ctx)).await;
|
||||||
|
|
||||||
|
// u[date committee server
|
||||||
|
committee::check_committee(Arc::clone(&ctx)).await;
|
||||||
|
|
||||||
// finish up
|
// finish up
|
||||||
process::exit(0);
|
process::exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn bulk_check(ctx: Arc<Context>) {
|
async fn check_bulk(ctx: Arc<Context>) {
|
||||||
let db_lock = {
|
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()
|
||||||
|
@ -60,6 +65,6 @@ async fn bulk_check(ctx: Arc<Context>) {
|
||||||
let db = db_lock.read().await;
|
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 {
|
||||||
set_roles::update_server(&ctx, &server_config, &[], &[]).await;
|
normal::update_server(&ctx, &server_config, &[], &[]).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
use serenity::{
|
use serenity::{
|
||||||
builder::CreateApplicationCommand,
|
builder::CreateApplicationCommand,
|
||||||
client::Context,
|
client::Context,
|
||||||
model::{
|
model::{
|
||||||
application::interaction::application_command::ApplicationCommandInteraction,
|
application::interaction::application_command::ApplicationCommandInteraction,
|
||||||
prelude::{command::CommandOptionType, interaction::application_command::CommandDataOptionValue},
|
prelude::{command::CommandOptionType, interaction::application_command::CommandDataOptionValue},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use skynet_discord_bot::common::wolves::get_data::get_wolves_cns;
|
|
||||||
use skynet_discord_bot::{is_admin, set_roles::update_server};
|
|
||||||
use sqlx::{Error, Pool, Sqlite};
|
|
||||||
use skynet_discord_bot::common::database::{get_server_config, DataBase, Servers};
|
use skynet_discord_bot::common::database::{get_server_config, DataBase, Servers};
|
||||||
|
use skynet_discord_bot::common::set_roles::normal::update_server;
|
||||||
|
use skynet_discord_bot::common::wolves::cns::get_wolves;
|
||||||
|
use skynet_discord_bot::is_admin;
|
||||||
|
use sqlx::{Error, Pool, Sqlite};
|
||||||
|
|
||||||
pub async fn run(command: &ApplicationCommandInteraction, ctx: &Context) -> String {
|
pub async fn run(command: &ApplicationCommandInteraction, ctx: &Context) -> String {
|
||||||
// check if user has high enough permisssions
|
// check if user has high enough permisssions
|
||||||
|
@ -216,7 +217,7 @@ async fn add_server(db: &Pool<Sqlite>, ctx: &Context, server: &Servers) -> Resul
|
||||||
// update all users
|
// update all users
|
||||||
if update {
|
if update {
|
||||||
// handle wolves api here
|
// handle wolves api here
|
||||||
get_wolves_cns(ctx).await;
|
get_wolves(ctx).await;
|
||||||
|
|
||||||
let mut roles_remove = vec![];
|
let mut roles_remove = vec![];
|
||||||
if current_remove {
|
if current_remove {
|
||||||
|
|
|
@ -13,9 +13,9 @@ use serenity::{
|
||||||
prelude::{command::CommandOptionType, interaction::application_command::CommandDataOptionValue},
|
prelude::{command::CommandOptionType, interaction::application_command::CommandDataOptionValue},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use skynet_discord_bot::common::database::{DataBase, Wolves, WolvesVerify};
|
||||||
use skynet_discord_bot::{get_now_iso, random_string, Config};
|
use skynet_discord_bot::{get_now_iso, random_string, Config};
|
||||||
use sqlx::{Pool, Sqlite};
|
use sqlx::{Pool, Sqlite};
|
||||||
use skynet_discord_bot::common::database::{DataBase, Wolves, WolvesVerify};
|
|
||||||
|
|
||||||
pub mod link {
|
pub mod link {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -241,8 +241,8 @@ pub mod verify {
|
||||||
use crate::commands::link_email::link::{db_pending_clear_expired, get_verify_from_db};
|
use crate::commands::link_email::link::{db_pending_clear_expired, get_verify_from_db};
|
||||||
use serenity::model::user::User;
|
use serenity::model::user::User;
|
||||||
use skynet_discord_bot::common::database::get_server_config;
|
use skynet_discord_bot::common::database::get_server_config;
|
||||||
use sqlx::Error;
|
|
||||||
use skynet_discord_bot::common::database::{ServerMembersWolves, Servers};
|
use skynet_discord_bot::common::database::{ServerMembersWolves, Servers};
|
||||||
|
use sqlx::Error;
|
||||||
|
|
||||||
pub async fn run(command: &ApplicationCommandInteraction, ctx: &Context) -> String {
|
pub async fn run(command: &ApplicationCommandInteraction, ctx: &Context) -> String {
|
||||||
let db_lock = {
|
let db_lock = {
|
||||||
|
|
|
@ -16,10 +16,10 @@ pub(crate) mod user {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::commands::link_email::link::get_server_member_discord;
|
use crate::commands::link_email::link::get_server_member_discord;
|
||||||
use serenity::model::id::UserId;
|
use serenity::model::id::UserId;
|
||||||
use skynet_discord_bot::Config;
|
|
||||||
use sqlx::Error;
|
|
||||||
use skynet_discord_bot::common::database::Wolves;
|
use skynet_discord_bot::common::database::Wolves;
|
||||||
use skynet_discord_bot::common::minecraft::{whitelist_update, Minecraft};
|
use skynet_discord_bot::common::minecraft::{whitelist_update, Minecraft};
|
||||||
|
use skynet_discord_bot::Config;
|
||||||
|
use sqlx::Error;
|
||||||
|
|
||||||
pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand {
|
pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand {
|
||||||
command.name("link_minecraft").description("Link your minecraft account").create_option(|option| {
|
command.name("link_minecraft").description("Link your minecraft account").create_option(|option| {
|
||||||
|
@ -124,9 +124,9 @@ pub(crate) mod server {
|
||||||
use sqlx::Error;
|
use sqlx::Error;
|
||||||
// this is to managfe 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::{is_admin, Config};
|
|
||||||
use skynet_discord_bot::common::minecraft::Minecraft;
|
|
||||||
use skynet_discord_bot::common::minecraft::update_server;
|
use skynet_discord_bot::common::minecraft::update_server;
|
||||||
|
use skynet_discord_bot::common::minecraft::Minecraft;
|
||||||
|
use skynet_discord_bot::{is_admin, Config};
|
||||||
|
|
||||||
pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand {
|
pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand {
|
||||||
command.name("minecraft_add").description("Add a minecraft server").create_option(|option| {
|
command.name("minecraft_add").description("Add a minecraft server").create_option(|option| {
|
||||||
|
@ -205,9 +205,9 @@ pub(crate) mod server {
|
||||||
use serenity::builder::CreateApplicationCommand;
|
use serenity::builder::CreateApplicationCommand;
|
||||||
use serenity::client::Context;
|
use serenity::client::Context;
|
||||||
use serenity::model::prelude::application_command::ApplicationCommandInteraction;
|
use serenity::model::prelude::application_command::ApplicationCommandInteraction;
|
||||||
use skynet_discord_bot::{is_admin, Config};
|
|
||||||
use skynet_discord_bot::common::database::DataBase;
|
use skynet_discord_bot::common::database::DataBase;
|
||||||
use skynet_discord_bot::common::minecraft::{get_minecraft_config_server, server_information};
|
use skynet_discord_bot::common::minecraft::{get_minecraft_config_server, server_information};
|
||||||
|
use skynet_discord_bot::{is_admin, Config};
|
||||||
|
|
||||||
pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand {
|
pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand {
|
||||||
command.name("minecraft_list").description("List your minecraft servers")
|
command.name("minecraft_list").description("List your minecraft servers")
|
||||||
|
@ -268,10 +268,10 @@ pub(crate) mod server {
|
||||||
use serenity::model::application::command::CommandOptionType;
|
use serenity::model::application::command::CommandOptionType;
|
||||||
use serenity::model::id::GuildId;
|
use serenity::model::id::GuildId;
|
||||||
use serenity::model::prelude::application_command::{ApplicationCommandInteraction, CommandDataOptionValue};
|
use serenity::model::prelude::application_command::{ApplicationCommandInteraction, CommandDataOptionValue};
|
||||||
use skynet_discord_bot::is_admin;
|
|
||||||
use sqlx::{Error, Pool, Sqlite};
|
|
||||||
use skynet_discord_bot::common::database::DataBase;
|
use skynet_discord_bot::common::database::DataBase;
|
||||||
use skynet_discord_bot::common::minecraft::Minecraft;
|
use skynet_discord_bot::common::minecraft::Minecraft;
|
||||||
|
use skynet_discord_bot::is_admin;
|
||||||
|
use sqlx::{Error, Pool, Sqlite};
|
||||||
|
|
||||||
pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand {
|
pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand {
|
||||||
command.name("minecraft_delete").description("Delete a minecraft server").create_option(|option| {
|
command.name("minecraft_delete").description("Delete a minecraft server").create_option(|option| {
|
||||||
|
|
|
@ -7,9 +7,9 @@ use serenity::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use skynet_discord_bot::common::database::{DataBase, RoleAdder};
|
||||||
use skynet_discord_bot::is_admin;
|
use skynet_discord_bot::is_admin;
|
||||||
use sqlx::{Error, Pool, Sqlite};
|
use sqlx::{Error, Pool, Sqlite};
|
||||||
use skynet_discord_bot::common::database::{DataBase, RoleAdder};
|
|
||||||
|
|
||||||
pub mod edit {
|
pub mod edit {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use serenity::prelude::TypeMapKey;
|
use crate::Config;
|
||||||
use std::sync::Arc;
|
|
||||||
use tokio::sync::RwLock;
|
|
||||||
use sqlx::{Error, FromRow, Pool, Row, Sqlite};
|
|
||||||
use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions, SqliteRow};
|
|
||||||
use serenity::model::id::{ChannelId, GuildId, RoleId, UserId};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serenity::model::guild;
|
use serenity::model::guild;
|
||||||
|
use serenity::model::id::{ChannelId, GuildId, RoleId, UserId};
|
||||||
|
use serenity::prelude::TypeMapKey;
|
||||||
|
use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions, SqliteRow};
|
||||||
|
use sqlx::{Error, FromRow, Pool, Row, Sqlite};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use crate::Config;
|
use std::sync::Arc;
|
||||||
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
pub struct DataBase;
|
pub struct DataBase;
|
||||||
impl TypeMapKey for DataBase {
|
impl TypeMapKey for DataBase {
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use crate::common::set_roles::normal::get_server_member_bulk;
|
||||||
|
use crate::Config;
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use sqlx::{Error, FromRow, Pool, Row, Sqlite};
|
use serde::{Deserialize, Serialize};
|
||||||
use serenity::model::id::GuildId;
|
use serenity::model::id::GuildId;
|
||||||
use sqlx::sqlite::SqliteRow;
|
use sqlx::sqlite::SqliteRow;
|
||||||
use crate::Config;
|
use sqlx::{Error, FromRow, Pool, Row, Sqlite};
|
||||||
use crate::set_roles::get_server_member_bulk;
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||||
pub struct Minecraft {
|
pub struct Minecraft {
|
||||||
|
@ -25,7 +24,6 @@ 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
|
||||||
|
@ -164,4 +162,3 @@ pub async fn get_minecraft_config_server(db: &Pool<Sqlite>, g_id: GuildId) -> Ve
|
||||||
.await
|
.await
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
pub mod wolves;
|
|
||||||
pub mod database;
|
pub mod database;
|
||||||
pub mod minecraft;
|
pub mod minecraft;
|
||||||
|
pub mod set_roles;
|
||||||
|
pub mod wolves;
|
||||||
|
|
263
src/common/set_roles.rs
Normal file
263
src/common/set_roles.rs
Normal file
|
@ -0,0 +1,263 @@
|
||||||
|
pub mod normal {
|
||||||
|
use crate::common::database::{DataBase, ServerMembersWolves, Servers, Wolves};
|
||||||
|
use crate::get_now_iso;
|
||||||
|
use serenity::client::Context;
|
||||||
|
use serenity::model::id::{GuildId, RoleId, UserId};
|
||||||
|
use sqlx::{Pool, Sqlite};
|
||||||
|
|
||||||
|
pub async fn update_server(ctx: &Context, server: &Servers, remove_roles: &[Option<RoleId>], members_changed: &[UserId]) {
|
||||||
|
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 Servers {
|
||||||
|
server,
|
||||||
|
role_past,
|
||||||
|
role_current,
|
||||||
|
..
|
||||||
|
} = server;
|
||||||
|
|
||||||
|
let mut roles_set = [0, 0, 0];
|
||||||
|
let mut members = vec![];
|
||||||
|
|
||||||
|
for member in get_server_member_bulk(&db, server).await {
|
||||||
|
if let Some(x) = member.discord {
|
||||||
|
members.push(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut members_all = members.len();
|
||||||
|
|
||||||
|
if let Ok(x) = server.members(ctx, None, None).await {
|
||||||
|
for mut member in x {
|
||||||
|
// 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) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if members.contains(&member.user.id) {
|
||||||
|
let mut roles = vec![];
|
||||||
|
|
||||||
|
if let Some(role) = &role_past {
|
||||||
|
if !member.roles.contains(role) {
|
||||||
|
roles_set[0] += 1;
|
||||||
|
roles.push(role.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !member.roles.contains(role_current) {
|
||||||
|
roles_set[1] += 1;
|
||||||
|
roles.push(role_current.to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(e) = member.add_roles(ctx, &roles).await {
|
||||||
|
println!("{:?}", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// old and never
|
||||||
|
|
||||||
|
if let Some(role) = &role_past {
|
||||||
|
if member.roles.contains(role) {
|
||||||
|
members_all += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if member.roles.contains(role_current) {
|
||||||
|
roles_set[2] += 1;
|
||||||
|
// 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 {
|
||||||
|
println!("{:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for role in remove_roles.iter().flatten() {
|
||||||
|
if let Err(e) = member.remove_role(ctx, role).await {
|
||||||
|
println!("{:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set_server_numbers(&db, server, members_all as i64, members.len() as i64).await;
|
||||||
|
|
||||||
|
// small bit of logging to note changes over time
|
||||||
|
println!("{:?} Changes: New: +{}, Current: +{}/-{}", server.as_u64(), roles_set[0], roles_set[1], roles_set[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_server_member_bulk(db: &Pool<Sqlite>, server: &GuildId) -> Vec<ServerMembersWolves> {
|
||||||
|
sqlx::query_as::<_, ServerMembersWolves>(
|
||||||
|
r#"
|
||||||
|
SELECT *
|
||||||
|
FROM server_members
|
||||||
|
JOIN wolves USING (id_wolves)
|
||||||
|
WHERE (
|
||||||
|
server = ?
|
||||||
|
AND discord IS NOT NULL
|
||||||
|
AND expiry > ?
|
||||||
|
)
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.bind(*server.as_u64() as i64)
|
||||||
|
.bind(get_now_iso(true))
|
||||||
|
.fetch_all(db)
|
||||||
|
.await
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn set_server_numbers(db: &Pool<Sqlite>, server: &GuildId, past: i64, current: i64) {
|
||||||
|
match sqlx::query_as::<_, Wolves>(
|
||||||
|
"
|
||||||
|
UPDATE servers
|
||||||
|
SET member_past = ?, member_current = ?
|
||||||
|
WHERE server = ?
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.bind(past)
|
||||||
|
.bind(current)
|
||||||
|
.bind(*server.as_u64() as i64)
|
||||||
|
.fetch_optional(db)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => {
|
||||||
|
println!("Failure to insert into {}", server.as_u64());
|
||||||
|
println!("{:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// for updating committee members
|
||||||
|
pub mod committee {
|
||||||
|
use crate::common::database::{DataBase, Wolves};
|
||||||
|
use crate::common::wolves::committees::Committees;
|
||||||
|
use serenity::client::Context;
|
||||||
|
use serenity::model::guild::Member;
|
||||||
|
use serenity::model::id::{GuildId, RoleId};
|
||||||
|
use sqlx::{Pool, Sqlite};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
pub async fn check_committee(ctx: Arc<Context>) {
|
||||||
|
let db_lock = {
|
||||||
|
let data_read = ctx.data.read().await;
|
||||||
|
data_read.get::<DataBase>().expect("Expected Config in TypeMap.").clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
let db = db_lock.read().await;
|
||||||
|
|
||||||
|
let server = GuildId(1220150752656363520);
|
||||||
|
let mut members = server.members(&ctx, None, None).await.unwrap_or_default();
|
||||||
|
|
||||||
|
update_committees(&db, &ctx, &mut members).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn update_committees(db: &Pool<Sqlite>, ctx: &Context, members: &mut Vec<Member>) {
|
||||||
|
let server = GuildId(1220150752656363520);
|
||||||
|
let committee_member = RoleId(1226602779968274573);
|
||||||
|
let committees = get_committees(db).await;
|
||||||
|
|
||||||
|
// information about the server
|
||||||
|
let roles = server.roles(&ctx).await.unwrap_or_default();
|
||||||
|
|
||||||
|
// make a hashmap of the nameof roles to quickly get them out again
|
||||||
|
let mut roles_name = HashMap::new();
|
||||||
|
for role in roles.values() {
|
||||||
|
roles_name.insert(role.name.to_owned(), role.to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
// a map of users and the roles they are goign to be getting
|
||||||
|
let mut users_roles = HashMap::new();
|
||||||
|
|
||||||
|
// a list of all the roles that can be removed from folks who should have them
|
||||||
|
let mut committee_roles = vec![committee_member];
|
||||||
|
|
||||||
|
for committee in &committees {
|
||||||
|
// get the role for this committee/club/soc
|
||||||
|
let role = match roles_name.get(&committee.name) {
|
||||||
|
Some(x) => Some(x.to_owned()),
|
||||||
|
None => {
|
||||||
|
// create teh role if it does not exist
|
||||||
|
match server.create_role(&ctx, |r| r.hoist(false).mentionable(true).name(&committee.name)).await {
|
||||||
|
Ok(x) => Some(x),
|
||||||
|
Err(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// so if the role exists
|
||||||
|
if let Some(r) = role {
|
||||||
|
committee_roles.push(r.id);
|
||||||
|
|
||||||
|
for id_wolves in &committee.committee {
|
||||||
|
// ID in this is the wolves ID, so we need to get a matching discord ID (if one exists)
|
||||||
|
if let Some(x) = get_server_member_discord(db, id_wolves).await {
|
||||||
|
if let Some(member_tmp) = x.discord {
|
||||||
|
let values = users_roles.entry(member_tmp).or_insert(vec![]);
|
||||||
|
values.push(r.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
let roles_required = match users_roles.get(&member.user.id) {
|
||||||
|
None => {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
Some(x) => {
|
||||||
|
let mut combined = x.to_owned();
|
||||||
|
// this is the main role, since it provides access to everything.
|
||||||
|
combined.push(committee_member);
|
||||||
|
combined
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// get a list of all the roles to remove from someone
|
||||||
|
let mut roles_rem = vec![];
|
||||||
|
for role in &committee_roles {
|
||||||
|
if !roles_required.contains(role) {
|
||||||
|
roles_rem.push(role.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !roles_rem.is_empty() {
|
||||||
|
member.remove_roles(&ctx, &roles_rem).await.unwrap_or_default();
|
||||||
|
}
|
||||||
|
|
||||||
|
if !roles_required.is_empty() {
|
||||||
|
// these roles are flavor roles, only there to make folks mentionable
|
||||||
|
member.add_roles(&ctx, &roles_required).await.unwrap_or_default();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_committees(db: &Pool<Sqlite>) -> Vec<Committees> {
|
||||||
|
sqlx::query_as::<_, Committees>(
|
||||||
|
r#"
|
||||||
|
SELECT *
|
||||||
|
FROM committees
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.fetch_all(db)
|
||||||
|
.await
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_server_member_discord(db: &Pool<Sqlite>, user: &i64) -> Option<Wolves> {
|
||||||
|
sqlx::query_as::<_, Wolves>(
|
||||||
|
r#"
|
||||||
|
SELECT *
|
||||||
|
FROM wolves
|
||||||
|
WHERE id_wolves = ?
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.bind(user)
|
||||||
|
.fetch_one(db)
|
||||||
|
.await
|
||||||
|
.ok()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,28 +1,66 @@
|
||||||
|
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
|
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<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
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.bind(&user.member_id)
|
||||||
|
.bind(&user.contact_email)
|
||||||
|
.fetch_optional(db)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => {
|
||||||
|
println!("Failure to insert into Wolves {:?}", user);
|
||||||
|
println!("{:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// #[derive(Debug, Clone, sqlx::FromRow)]
|
/**
|
||||||
// pub struct Committees {
|
This is getting data for Clubs and Socs
|
||||||
// pub id: i64,
|
*/
|
||||||
// pub name: String,
|
pub mod cns {
|
||||||
// pub link: String,
|
use crate::common::database::{get_server_config_bulk, DataBase, ServerMembers, ServerMembersWolves, Servers};
|
||||||
// pub members: Vec<i64>,
|
use crate::common::set_roles::normal::update_server;
|
||||||
// }
|
use crate::common::wolves::{add_users_wolves, WolvesResultUserMin};
|
||||||
|
use crate::Config;
|
||||||
pub mod get_data {
|
|
||||||
use crate::set_roles::update_server;
|
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serenity::client::Context;
|
use serenity::client::Context;
|
||||||
use serenity::model::id::GuildId;
|
use serenity::model::id::GuildId;
|
||||||
use sqlx::{Pool, Sqlite};
|
use sqlx::{Pool, Sqlite};
|
||||||
use crate::Config;
|
use std::collections::BTreeMap;
|
||||||
use crate::common::database::{get_server_config_bulk, DataBase, ServerMembers, ServerMembersWolves, Servers, Wolves};
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
struct WolvesResultUser {
|
struct WolvesResultUser {
|
||||||
|
// TODO: Might be worth trying to get this replaced with the club/soc ID?
|
||||||
committee: String,
|
committee: String,
|
||||||
member_id: String,
|
member_id: String,
|
||||||
first_name: String,
|
first_name: String,
|
||||||
|
@ -38,6 +76,15 @@ pub mod get_data {
|
||||||
domain: 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)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
struct WolvesResult {
|
struct WolvesResult {
|
||||||
success: i8,
|
success: i8,
|
||||||
|
@ -50,7 +97,7 @@ pub mod get_data {
|
||||||
pub email: String,
|
pub email: String,
|
||||||
pub expiry: String,
|
pub expiry: String,
|
||||||
}
|
}
|
||||||
pub async fn get_wolves_cns(ctx: &Context) {
|
pub async fn get_wolves(ctx: &Context) {
|
||||||
let db_lock = {
|
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()
|
||||||
|
@ -75,17 +122,17 @@ pub mod get_data {
|
||||||
|
|
||||||
// list of users that need to be updated for this server
|
// list of users that need to be updated for this server
|
||||||
let mut user_to_update = vec![];
|
let mut user_to_update = vec![];
|
||||||
for user in get_wolves_cns_sub(&config, wolves_api).await {
|
for user in get_wolves_sub(&config, wolves_api).await {
|
||||||
let id = user.member_id.parse::<u64>().unwrap_or_default();
|
let id = user.member_id.parse::<u64>().unwrap_or_default();
|
||||||
match existing.get(&(id as i64)) {
|
match existing.get(&(id as i64)) {
|
||||||
None => {
|
None => {
|
||||||
// user does not exist already, add everything
|
// user does not exist already, add everything
|
||||||
add_users_wolves(&db, &user).await;
|
add_users_wolves(&db, &WolvesResultUserMin::from(&user)).await;
|
||||||
add_users_server_members(&db, server, &user).await;
|
add_users_server_members(&db, server, &user).await;
|
||||||
}
|
}
|
||||||
Some(old) => {
|
Some(old) => {
|
||||||
// always update wolves table, in case data has changed
|
// always update wolves table, in case data has changed
|
||||||
add_users_wolves(&db, &user).await;
|
add_users_wolves(&db, &WolvesResultUserMin::from(&user)).await;
|
||||||
if old.expiry != user.expiry {
|
if old.expiry != user.expiry {
|
||||||
add_users_server_members(&db, server, &user).await;
|
add_users_server_members(&db, server, &user).await;
|
||||||
|
|
||||||
|
@ -103,7 +150,7 @@ pub mod get_data {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_server_member(db: &Pool<Sqlite>, server: &GuildId) -> Vec<ServerMembersWolves> {
|
async fn get_server_member(db: &Pool<Sqlite>, server: &GuildId) -> Vec<ServerMembersWolves> {
|
||||||
sqlx::query_as::<_, ServerMembersWolves>(
|
sqlx::query_as::<_, ServerMembersWolves>(
|
||||||
r#"
|
r#"
|
||||||
SELECT *
|
SELECT *
|
||||||
|
@ -121,13 +168,15 @@ pub mod get_data {
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_wolves_cns_sub(config: &Config, wolves_api: &str) -> Vec<WolvesResultUser> {
|
async fn get_wolves_sub(config: &Config, wolves_api: &str) -> Vec<WolvesResultUser> {
|
||||||
if config.wolves_url.is_empty() {
|
if config.wolves_url.is_empty() {
|
||||||
return vec![];
|
return vec![];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let url = format!("{}/get_members", &config.wolves_url);
|
||||||
|
|
||||||
// get wolves data
|
// get wolves data
|
||||||
if let Ok(mut res) = surf::post(&config.wolves_url).header("X-AM-Identity", wolves_api).await {
|
if let Ok(mut res) = surf::post(&url).header("X-AM-Identity", wolves_api).await {
|
||||||
if let Ok(WolvesResult {
|
if let Ok(WolvesResult {
|
||||||
success,
|
success,
|
||||||
result,
|
result,
|
||||||
|
@ -144,27 +193,6 @@ pub mod get_data {
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn add_users_wolves(db: &Pool<Sqlite>, 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<Sqlite>, server: &GuildId, user: &WolvesResultUser) {
|
async fn add_users_server_members(db: &Pool<Sqlite>, server: &GuildId, user: &WolvesResultUser) {
|
||||||
match sqlx::query_as::<_, ServerMembers>(
|
match sqlx::query_as::<_, ServerMembers>(
|
||||||
"
|
"
|
||||||
|
@ -186,3 +214,221 @@ pub mod get_data {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get and store the data on C&S committees
|
||||||
|
*/
|
||||||
|
pub mod committees {
|
||||||
|
use crate::common::database::DataBase;
|
||||||
|
use crate::Config;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serenity::client::Context;
|
||||||
|
use sqlx::{Pool, Sqlite};
|
||||||
|
|
||||||
|
// 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
|
||||||
|
committee: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Database entry for it
|
||||||
|
#[derive(Debug, Clone, sqlx::FromRow)]
|
||||||
|
pub struct Committees {
|
||||||
|
pub id: i64,
|
||||||
|
pub name: String,
|
||||||
|
pub link: String,
|
||||||
|
#[sqlx(json)]
|
||||||
|
pub committee: Vec<i64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<WolvesResultCNS> for Committees {
|
||||||
|
fn from(value: WolvesResultCNS) -> Self {
|
||||||
|
Self {
|
||||||
|
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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_cns(ctx: &Context) {
|
||||||
|
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
|
||||||
|
for committee in get_committees(&config, api_key).await {
|
||||||
|
let tmp = Committees::from(committee);
|
||||||
|
add_committee(&db, &tmp).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_committees(config: &Config, wolves_api: &str) -> Vec<WolvesResultCNS> {
|
||||||
|
if config.wolves_url.is_empty() {
|
||||||
|
return vec![];
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Change teh stored env value to teh base domain
|
||||||
|
let url = format!("{}/get_cns", &config.wolves_url);
|
||||||
|
|
||||||
|
// get wolves data
|
||||||
|
if let Ok(mut res) = surf::post(&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_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
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.bind(committee.id)
|
||||||
|
.bind(&committee.name)
|
||||||
|
.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
get the data for an individual user
|
||||||
|
*/
|
||||||
|
pub mod individual {
|
||||||
|
use crate::common::database::DataBase;
|
||||||
|
use crate::common::wolves::{add_users_wolves, WolvesResultUserMin};
|
||||||
|
use crate::Config;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serenity::client::Context;
|
||||||
|
|
||||||
|
#[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,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_user(ctx: &Context, email: &str) -> bool {
|
||||||
|
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 {
|
||||||
|
None => false,
|
||||||
|
// if exists save it and return true
|
||||||
|
Some(user) => {
|
||||||
|
// add to db
|
||||||
|
add_users_wolves(&db, &WolvesResultUserMin::from(&user)).await;
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_user_sub(config: &Config, wolves_api: &str, _email: &str) -> Option<WolvesResultUser> {
|
||||||
|
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 {
|
||||||
|
if let Ok(WolvesResult {
|
||||||
|
success,
|
||||||
|
result,
|
||||||
|
}) = res.body_json().await
|
||||||
|
{
|
||||||
|
if success != 1 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Some(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
144
src/lib.rs
144
src/lib.rs
|
@ -1,26 +1,13 @@
|
||||||
pub mod common;
|
pub mod common;
|
||||||
|
|
||||||
use dotenvy::dotenv;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use serenity::{
|
|
||||||
model::id::{GuildId, RoleId},
|
|
||||||
prelude::TypeMapKey,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::set_roles::get_server_member_bulk;
|
|
||||||
use chrono::{Datelike, SecondsFormat, Utc};
|
use chrono::{Datelike, SecondsFormat, Utc};
|
||||||
|
use dotenvy::dotenv;
|
||||||
use rand::{distributions::Alphanumeric, thread_rng, Rng};
|
use rand::{distributions::Alphanumeric, thread_rng, Rng};
|
||||||
use serde::de::DeserializeOwned;
|
|
||||||
use serenity::client::Context;
|
use serenity::client::Context;
|
||||||
use serenity::model::id::UserId;
|
|
||||||
use serenity::model::prelude::application_command::ApplicationCommandInteraction;
|
use serenity::model::prelude::application_command::ApplicationCommandInteraction;
|
||||||
use sqlx::{
|
use serenity::prelude::TypeMapKey;
|
||||||
Pool, Sqlite,
|
|
||||||
};
|
|
||||||
use std::{env, sync::Arc};
|
use std::{env, sync::Arc};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
use common::database::{ServerMembersWolves, Servers};
|
|
||||||
|
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
// manages where teh database is stored
|
// manages where teh database is stored
|
||||||
pub home: String,
|
pub home: String,
|
||||||
|
@ -103,133 +90,6 @@ pub fn random_string(len: usize) -> String {
|
||||||
thread_rng().sample_iter(&Alphanumeric).take(len).map(char::from).collect()
|
thread_rng().sample_iter(&Alphanumeric).take(len).map(char::from).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod set_roles {
|
|
||||||
use crate::common::database::{DataBase, Wolves};
|
|
||||||
use super::*;
|
|
||||||
pub async fn update_server(ctx: &Context, server: &Servers, remove_roles: &[Option<RoleId>], members_changed: &[UserId]) {
|
|
||||||
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 Servers {
|
|
||||||
server,
|
|
||||||
role_past,
|
|
||||||
role_current,
|
|
||||||
..
|
|
||||||
} = server;
|
|
||||||
|
|
||||||
let mut roles_set = [0, 0, 0];
|
|
||||||
let mut members = vec![];
|
|
||||||
|
|
||||||
for member in get_server_member_bulk(&db, server).await {
|
|
||||||
if let Some(x) = member.discord {
|
|
||||||
members.push(x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let mut members_all = members.len();
|
|
||||||
|
|
||||||
if let Ok(x) = server.members(ctx, None, None).await {
|
|
||||||
for mut member in x {
|
|
||||||
// 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) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if members.contains(&member.user.id) {
|
|
||||||
let mut roles = vec![];
|
|
||||||
|
|
||||||
if let Some(role) = &role_past {
|
|
||||||
if !member.roles.contains(role) {
|
|
||||||
roles_set[0] += 1;
|
|
||||||
roles.push(role.to_owned());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !member.roles.contains(role_current) {
|
|
||||||
roles_set[1] += 1;
|
|
||||||
roles.push(role_current.to_owned());
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Err(e) = member.add_roles(ctx, &roles).await {
|
|
||||||
println!("{:?}", e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// old and never
|
|
||||||
|
|
||||||
if let Some(role) = &role_past {
|
|
||||||
if member.roles.contains(role) {
|
|
||||||
members_all += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if member.roles.contains(role_current) {
|
|
||||||
roles_set[2] += 1;
|
|
||||||
// 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 {
|
|
||||||
println!("{:?}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for role in remove_roles.iter().flatten() {
|
|
||||||
if let Err(e) = member.remove_role(ctx, role).await {
|
|
||||||
println!("{:?}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
set_server_numbers(&db, server, members_all as i64, members.len() as i64).await;
|
|
||||||
|
|
||||||
// small bit of logging to note changes over time
|
|
||||||
println!("{:?} Changes: New: +{}, Current: +{}/-{}", server.as_u64(), roles_set[0], roles_set[1], roles_set[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_server_member_bulk(db: &Pool<Sqlite>, server: &GuildId) -> Vec<ServerMembersWolves> {
|
|
||||||
sqlx::query_as::<_, ServerMembersWolves>(
|
|
||||||
r#"
|
|
||||||
SELECT *
|
|
||||||
FROM server_members
|
|
||||||
JOIN wolves USING (id_wolves)
|
|
||||||
WHERE (
|
|
||||||
server = ?
|
|
||||||
AND discord IS NOT NULL
|
|
||||||
AND expiry > ?
|
|
||||||
)
|
|
||||||
"#,
|
|
||||||
)
|
|
||||||
.bind(*server.as_u64() as i64)
|
|
||||||
.bind(get_now_iso(true))
|
|
||||||
.fetch_all(db)
|
|
||||||
.await
|
|
||||||
.unwrap_or_default()
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn set_server_numbers(db: &Pool<Sqlite>, server: &GuildId, past: i64, current: i64) {
|
|
||||||
match sqlx::query_as::<_, Wolves>(
|
|
||||||
"
|
|
||||||
UPDATE servers
|
|
||||||
SET member_past = ?, member_current = ?
|
|
||||||
WHERE server = ?
|
|
||||||
",
|
|
||||||
)
|
|
||||||
.bind(past)
|
|
||||||
.bind(current)
|
|
||||||
.bind(*server.as_u64() as i64)
|
|
||||||
.fetch_optional(db)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(e) => {
|
|
||||||
println!("Failure to insert into {}", server.as_u64());
|
|
||||||
println!("{:?}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
For any time ye need to check if a user who calls a command has admin privlages
|
For any time ye need to check if a user who calls a command has admin privlages
|
||||||
*/
|
*/
|
||||||
|
|
29
src/main.rs
29
src/main.rs
|
@ -2,21 +2,23 @@ pub mod commands;
|
||||||
|
|
||||||
use crate::commands::role_adder::tools::on_role_change;
|
use crate::commands::role_adder::tools::on_role_change;
|
||||||
use serenity::model::guild::Member;
|
use serenity::model::guild::Member;
|
||||||
|
use serenity::model::id::GuildId;
|
||||||
use serenity::{
|
use serenity::{
|
||||||
async_trait,
|
async_trait,
|
||||||
client::{Context, EventHandler},
|
client::{Context, EventHandler},
|
||||||
model::{
|
model::{
|
||||||
application::{command::Command, interaction::Interaction},
|
application::{command::Command, interaction::Interaction},
|
||||||
gateway::{GatewayIntents, Ready},
|
gateway::{GatewayIntents, Ready},
|
||||||
prelude::Activity,
|
prelude::Activity,
|
||||||
user::OnlineStatus,
|
user::OnlineStatus,
|
||||||
},
|
},
|
||||||
Client,
|
Client,
|
||||||
};
|
};
|
||||||
|
use skynet_discord_bot::common::database::{db_init, get_server_config, get_server_member, DataBase};
|
||||||
|
use skynet_discord_bot::common::set_roles::committee::update_committees;
|
||||||
use skynet_discord_bot::{get_config, Config};
|
use skynet_discord_bot::{get_config, Config};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
use skynet_discord_bot::common::database::{db_init, get_server_config, get_server_member, DataBase};
|
|
||||||
|
|
||||||
struct Handler;
|
struct Handler;
|
||||||
|
|
||||||
|
@ -35,6 +37,13 @@ impl EventHandler for Handler {
|
||||||
Some(x) => x,
|
Some(x) => x,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// committee server takes priority
|
||||||
|
if new_member.guild_id.eq(&GuildId(1220150752656363520)) {
|
||||||
|
let mut member = vec![new_member.clone()];
|
||||||
|
update_committees(&db, &ctx, &mut member).await;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if get_server_member(&db, &new_member.guild_id, &new_member).await.is_ok() {
|
if get_server_member(&db, &new_member.guild_id, &new_member).await.is_ok() {
|
||||||
let mut roles = vec![];
|
let mut roles = vec![];
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue