Verified Commit 8970ce17 authored by Mathias B.'s avatar Mathias B.
Browse files

Prise en compte des rôles dans la synchronisation des mises à jour des membres

parent e8ee8898
......@@ -139,12 +139,9 @@ impl EventHandler for Handler {
old_if_available: Option<Member>,
new: Member,
) {
process_handler_result(
MemberRepository::update(new.user.id, new.guild_id, new.nick.as_ref()).await,
);
process_handler_result(
crate::modules::logging::guild_member_update(old_if_available.as_ref(), &new).await,
);
process_handler_result(MemberRepository::update(new.user.id, new.guild_id, new.nick.as_ref()).await);
process_handler_result(crate::modules::synchrotron::event_handler::guild_member_roles_update(old_if_available.as_ref(), &new).await);
process_handler_result(crate::modules::logging::guild_member_update(old_if_available.as_ref(), &new).await);
}
async fn guild_members_chunk(&self, ctx: Context, chunk: GuildMembersChunkEvent) {
......
INSERT INTO discord.guild_member_roles
SELECT gm.guild_member_id, r.id
FROM discord.guild_members gm
INNER JOIN discord.roles r ON r.guilds_id = gm.guilds_id
WHERE gm.guilds_id = $2
AND gm.users_id = $1
AND r.id = ANY ($3::bigint[])
ON CONFLICT DO NOTHING
\ No newline at end of file
SELECT r.id
FROM discord.guild_member_roles gmr
INNER JOIN discord.guild_members gm ON gmr.guild_members_guild_member_id = gm.guild_member_id
INNER JOIN discord.roles r ON gmr.id_roles = r.id
WHERE gm.users_id = $1
AND gm.guilds_id = $2;
\ No newline at end of file
DELETE
FROM discord.guild_member_roles gmr
USING discord.guild_members gm, discord.roles r
-- Conditions de jointures
WHERE gmr.guild_members_guild_member_id = gm.guild_member_id
AND gmr.id_roles = r.id
-- Fin conditions de jointures
AND gm.users_id = $1
AND gm.guilds_id = $2
AND r.id = ANY($3::bigint[])
\ No newline at end of file
use crate::repositories::ConfigRepository;
use crate::repositories::{ConfigRepository, RoleRepository};
use crate::repositories::GuildRepository;
use crate::utils::functions;
use datastructs::discord::GuildData;
......@@ -7,6 +7,8 @@ use futures::StreamExt;
use serenity::client::bridge::gateway::ChunkGuildFilter;
use serenity::model::prelude::*;
use serenity::prelude::*;
use std::collections::HashSet;
use itertools::Itertools;
pub async fn cache_ready(ctx: &Context, guilds: &[GuildId]) -> eyre::Result<()> {
for guild_id in guilds {
......@@ -44,3 +46,39 @@ pub async fn guild_create(ctx: &Context, guild: Guild, is_new: bool) -> eyre::Re
Ok(())
}
pub async fn guild_member_roles_update(old_if_available: Option<&Member>, new_member: &Member) -> eyre::Result<()> {
match old_if_available {
Some(old_member) => {
tracing::info!("Calcul des différences de rôles");
let old_roles = old_member.roles.iter().copied().collect::<HashSet<RoleId>>();
let new_roles = new_member.roles.iter().copied().collect::<HashSet<RoleId>>();
// Rôles dans les anciens, mais pas dans les nouveaux rôles, donc à enlever de la base de données
let assignments_to_remove = old_roles.difference(&new_roles).copied().collect_vec();
// Rôles dans les nouveaux, mais pas dans les anciens rôles, donc à insérer dans la base de données
let assignments_to_add = new_roles.difference(&old_roles).copied().collect_vec();
tracing::info!("Rôles retirés: {:?}", assignments_to_remove);
tracing::info!("Rôles ajoutés: {:?}", assignments_to_add);
if !assignments_to_remove.is_empty() {
RoleRepository::unassign_roles(new_member.guild_id, new_member.user.id, &assignments_to_remove).await?;
}
if !assignments_to_add.is_empty() {
RoleRepository::assign_roles(new_member.guild_id, new_member.user.id, &assignments_to_add).await?;
}
}
None => {
tracing::warn!("Pas d'anciennes données sur le membre disponible. Tous les rôles seront retirés puis réassignés");
let assignments = RoleRepository::retrieve_roles_for_user(new_member.guild_id, new_member.user.id).await?;
RoleRepository::unassign_roles(new_member.guild_id, new_member.user.id, &assignments).await?;
RoleRepository::assign_roles(new_member.guild_id, new_member.user.id, &new_member.roles).await?;
}
};
Ok(())
}
\ No newline at end of file
......@@ -2,13 +2,55 @@ use crate::repositories::PostgreSQLResult;
use crate::utils::database::DatabaseClient;
use datastructs::discord::RoleData;
use serenity::model::guild::Member;
use serenity::model::id::GuildId;
use serenity::model::id::{GuildId, UserId, RoleId};
use std::collections::{HashMap, HashSet};
use tracing::{instrument, warn};
use itertools::Itertools;
pub struct RoleRepository;
impl RoleRepository {
pub async fn unassign_roles(guild_id: GuildId, user_id: UserId, roles: &[RoleId]) -> super::PostgreSQLResult<u64> {
let db = DatabaseClient::get();
let role_ids = roles.iter().copied().map(i64::from).collect_vec();
db.execute(
include_str!("../files/sql/synchrotron/members/unassign_user_roles.sql"),
&[
&i64::from(user_id),
&i64::from(guild_id),
&role_ids
]
).await
}
pub async fn assign_roles(guild_id: GuildId, user_id: UserId, roles: &[RoleId]) -> super::PostgreSQLResult<u64> {
let db = DatabaseClient::get();
let role_ids = roles.iter().copied().map(i64::from).collect_vec();
db.execute(
include_str!("../files/sql/synchrotron/members/assign_user_roles.sql"),
&[
&i64::from(user_id),
&i64::from(guild_id),
&role_ids
]
).await
}
pub async fn retrieve_roles_for_user(guild_id: GuildId, user_id: UserId) -> super::PostgreSQLResult<Vec<RoleId>> {
let db = DatabaseClient::get();
let rows = db.query(
include_str!("../files/sql/synchrotron/members/query_roles.sql"),
&[
&i64::from(user_id),
&i64::from(guild_id)
]
).await?;
Ok(rows.iter().map(|row| RoleId(row.get::<_, i64>("id") as u64)).collect_vec())
}
pub async fn copy_temporary_roles(
temp_table_id: u32,
roles: &[RoleData],
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment