feat: will update users when there are changes made to teh server config

This commit is contained in:
silver 2023-11-23 16:12:28 +00:00
parent 432dd0e4a0
commit 66446e8df8
3 changed files with 161 additions and 118 deletions

View file

@ -1,14 +1,10 @@
use serenity::{
async_trait,
client::{Context, EventHandler},
model::{
gateway::{GatewayIntents, Ready},
id::GuildId,
},
model::gateway::{GatewayIntents, Ready},
Client,
};
use skynet_discord_bot::{db_init, get_config, get_now_iso, get_server_config_bulk, Config, DataBase, ServerMembersWolves, Servers, Wolves};
use sqlx::{Pool, Sqlite};
use skynet_discord_bot::{db_init, get_config, get_server_config_bulk, update_server, Config, DataBase};
use std::{process, sync::Arc};
use tokio::sync::RwLock;
@ -63,112 +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 {
let Servers {
server,
role_past,
role_current,
..
} = server_config;
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 {
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 let Some(role) = &role_current {
if !member.roles.contains(role) {
roles_set[1] += 1;
roles.push(role.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 let Some(role) = &role_current {
if member.roles.contains(role) {
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).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]);
}
}
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);
}
update_server(&db, &ctx, &server_config, &[]).await;
}
}

View file

@ -6,7 +6,7 @@ use serenity::{
prelude::{command::CommandOptionType, interaction::application_command::CommandDataOptionValue},
},
};
use skynet_discord_bot::{DataBase, Servers};
use skynet_discord_bot::{get_server_config, update_server, DataBase, Servers};
use sqlx::{Error, Pool, Sqlite};
pub async fn run(command: &ApplicationCommandInteraction, ctx: &Context) -> String {
@ -92,7 +92,7 @@ pub async fn run(command: &ApplicationCommandInteraction, ctx: &Context) -> Stri
member_current: 0,
};
match add_server(&db, &server_data).await {
match add_server(&db, ctx, &server_data).await {
Ok(_) => {}
Err(e) => {
println!("{:?}", e);
@ -130,11 +130,12 @@ pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicatio
})
}
async fn add_server(db: &Pool<Sqlite>, server: &Servers) -> Result<Option<Servers>, Error> {
async fn add_server(db: &Pool<Sqlite>, ctx: &Context, server: &Servers) -> Result<Option<Servers>, Error> {
let existing = get_server_config(db, &server.server).await;
let role_past = server.role_past.map(|x| *x.as_u64() as i64);
let role_current = server.role_current.map(|x| *x.as_u64() as i64);
sqlx::query_as::<_, Servers>(
let insert = sqlx::query_as::<_, Servers>(
"
INSERT OR REPLACE INTO servers (server, wolves_api, role_past, role_current)
VALUES (?1, ?2, ?3, ?4)
@ -145,5 +146,41 @@ async fn add_server(db: &Pool<Sqlite>, server: &Servers) -> Result<Option<Server
.bind(role_past)
.bind(role_current)
.fetch_optional(db)
.await
.await;
// if the entry does not exist already tehn do a user update
let (update, current_remove, current_role, past_remove, past_role) = match &existing {
None => (true, false, None, false, None),
Some(x) => {
let mut result = (false, false, None, false, None);
if x.wolves_api != server.wolves_api {
result.0 = true;
}
if x.role_current != server.role_current {
result.0 = true;
result.1 = true;
result.2 = x.role_current;
}
if x.role_past != server.role_past {
result.0 = true;
result.3 = true;
result.4 = x.role_past;
}
result
}
};
// update all users
if update {
let mut roles_remove = vec![];
if current_remove {
roles_remove.push(current_role)
}
if past_remove {
roles_remove.push(past_role)
}
update_server(db, ctx, server, &roles_remove).await;
}
insert
}

View file

@ -10,6 +10,7 @@ use serenity::{
use chrono::{Datelike, SecondsFormat, Utc};
use rand::{distributions::Alphanumeric, thread_rng, Rng};
use serenity::client::Context;
use serenity::model::id::UserId;
use sqlx::{
sqlite::{SqliteConnectOptions, SqlitePoolOptions, SqliteRow},
@ -377,3 +378,118 @@ pub fn get_now_iso(short: bool) -> String {
pub fn random_string(len: usize) -> String {
thread_rng().sample_iter(&Alphanumeric).take(len).map(char::from).collect()
}
pub async fn update_server(db: &Pool<Sqlite>, ctx: &Context, server: &Servers, remove_roles: &[Option<RoleId>]) {
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 {
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 let Some(role) = &role_current {
if !member.roles.contains(role) {
roles_set[1] += 1;
roles.push(role.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 let Some(role) = &role_current {
if member.roles.contains(role) {
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).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]);
}
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);
}
}
}