forked from Skynet/discord-bot
feat: updating teh data from wolves should now also update roles for whoever changed.
This should lead to faster activations of folks who have previously linked, join a server, then get membership. Closes #6
This commit is contained in:
parent
7303b5782c
commit
3779222a38
4 changed files with 127 additions and 23 deletions
|
@ -1,4 +1,12 @@
|
|||
use skynet_discord_bot::{db_init, get_config, get_data::get_wolves};
|
||||
use serenity::{
|
||||
async_trait,
|
||||
client::{Context, EventHandler},
|
||||
model::gateway::{GatewayIntents, Ready},
|
||||
Client,
|
||||
};
|
||||
use skynet_discord_bot::{db_init, get_config, get_data::get_wolves, Config, DataBase};
|
||||
use std::{process, sync::Arc};
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
|
@ -8,6 +16,36 @@ async fn main() {
|
|||
Err(_) => return,
|
||||
};
|
||||
|
||||
// handle wolves api here
|
||||
get_wolves(&db, &config).await;
|
||||
// Intents are a bitflag, bitwise operations can be used to dictate which intents to use
|
||||
let intents = GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::GUILD_MEMBERS;
|
||||
// Build our client.
|
||||
let mut client = Client::builder(&config.discord_token, intents)
|
||||
.event_handler(Handler {})
|
||||
.await
|
||||
.expect("Error creating client");
|
||||
|
||||
{
|
||||
let mut data = client.data.write().await;
|
||||
|
||||
data.insert::<Config>(Arc::new(RwLock::new(config)));
|
||||
data.insert::<DataBase>(Arc::new(RwLock::new(db)));
|
||||
}
|
||||
|
||||
if let Err(why) = client.start().await {
|
||||
println!("Client error: {:?}", why);
|
||||
}
|
||||
}
|
||||
|
||||
struct Handler;
|
||||
#[async_trait]
|
||||
impl EventHandler for Handler {
|
||||
async fn ready(&self, ctx: Context, ready: Ready) {
|
||||
let ctx = Arc::new(ctx);
|
||||
println!("{} is connected!", ready.user.name);
|
||||
|
||||
get_wolves(&ctx).await;
|
||||
|
||||
// finish up
|
||||
process::exit(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,6 +59,6 @@ async fn bulk_check(ctx: Arc<Context>) {
|
|||
let db = db_lock.read().await;
|
||||
|
||||
for server_config in get_server_config_bulk(&db).await {
|
||||
update_server(&db, &ctx, &server_config, &[]).await;
|
||||
update_server(&ctx, &server_config, &[], &vec![]).await;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use serenity::{
|
|||
},
|
||||
};
|
||||
use skynet_discord_bot::get_data::get_wolves;
|
||||
use skynet_discord_bot::{get_server_config, set_roles::update_server, Config, DataBase, Servers};
|
||||
use skynet_discord_bot::{get_server_config, set_roles::update_server, DataBase, Servers};
|
||||
use sqlx::{Error, Pool, Sqlite};
|
||||
|
||||
pub async fn run(command: &ApplicationCommandInteraction, ctx: &Context) -> String {
|
||||
|
@ -173,14 +173,8 @@ async fn add_server(db: &Pool<Sqlite>, ctx: &Context, server: &Servers) -> Resul
|
|||
|
||||
// update all users
|
||||
if update {
|
||||
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;
|
||||
|
||||
// handle wolves api here
|
||||
get_wolves(db, &config).await;
|
||||
get_wolves(ctx).await;
|
||||
|
||||
let mut roles_remove = vec![];
|
||||
if current_remove {
|
||||
|
@ -189,7 +183,7 @@ async fn add_server(db: &Pool<Sqlite>, ctx: &Context, server: &Servers) -> Resul
|
|||
if past_remove {
|
||||
roles_remove.push(past_role)
|
||||
}
|
||||
update_server(db, ctx, server, &roles_remove).await;
|
||||
update_server(ctx, server, &roles_remove, &vec![]).await;
|
||||
}
|
||||
|
||||
insert
|
||||
|
|
92
src/lib.rs
92
src/lib.rs
|
@ -381,7 +381,14 @@ pub fn random_string(len: usize) -> String {
|
|||
|
||||
pub mod set_roles {
|
||||
use super::*;
|
||||
pub async fn update_server(db: &Pool<Sqlite>, ctx: &Context, server: &Servers, remove_roles: &[Option<RoleId>]) {
|
||||
pub async fn update_server(ctx: &Context, server: &Servers, remove_roles: &[Option<RoleId>], members_changed: &Vec<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,
|
||||
|
@ -392,7 +399,7 @@ pub mod set_roles {
|
|||
let mut roles_set = [0, 0, 0];
|
||||
let mut members = vec![];
|
||||
|
||||
for member in get_server_member_bulk(db, server).await {
|
||||
for member in get_server_member_bulk(&db, server).await {
|
||||
if let Some(x) = member.discord {
|
||||
members.push(x);
|
||||
}
|
||||
|
@ -401,6 +408,11 @@ pub mod set_roles {
|
|||
|
||||
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![];
|
||||
|
||||
|
@ -448,7 +460,7 @@ pub mod set_roles {
|
|||
}
|
||||
}
|
||||
|
||||
set_server_numbers(db, server, members_all as i64, members.len() as i64).await;
|
||||
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]);
|
||||
|
@ -499,6 +511,8 @@ 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 {
|
||||
|
@ -528,20 +542,77 @@ pub mod get_data {
|
|||
pub email: String,
|
||||
pub expiry: String,
|
||||
}
|
||||
pub async fn get_wolves(db: &Pool<Sqlite>, config: &Config) {
|
||||
for server_config in get_server_config_bulk(db).await {
|
||||
pub async fn get_wolves(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;
|
||||
|
||||
for server_config in get_server_config_bulk(&db).await {
|
||||
let Servers {
|
||||
server,
|
||||
wolves_api,
|
||||
..
|
||||
} = server_config;
|
||||
} = &server_config;
|
||||
|
||||
for user in get_wolves_sub(config, &wolves_api).await {
|
||||
add_users_wolves(db, &server, &user).await;
|
||||
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![];
|
||||
for user in get_wolves_sub(&config, wolves_api).await {
|
||||
let id = user.wolves_id.parse::<u64>().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<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
|
||||
)
|
||||
"#,
|
||||
)
|
||||
.bind(*server.as_u64() as i64)
|
||||
.fetch_all(db)
|
||||
.await
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
async fn get_wolves_sub(config: &Config, wolves_api: &str) -> Vec<WolvesResultUser> {
|
||||
if config.wolves_url.is_empty() {
|
||||
return vec![];
|
||||
|
@ -565,7 +636,7 @@ pub mod get_data {
|
|||
vec![]
|
||||
}
|
||||
|
||||
async fn add_users_wolves(db: &Pool<Sqlite>, server: &GuildId, user: &WolvesResultUser) {
|
||||
async fn add_users_wolves(db: &Pool<Sqlite>, user: &WolvesResultUser) {
|
||||
// expiry
|
||||
match sqlx::query_as::<_, Wolves>(
|
||||
"
|
||||
|
@ -585,7 +656,8 @@ pub mod get_data {
|
|||
println!("{:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
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)
|
||||
|
|
Loading…
Reference in a new issue