mirror of
https://github.com/ZeppelinBot/Zeppelin.git
synced 2025-03-15 05:41:51 +00:00
feat(persist): reapply persisted data after delay
This enables better interoperability with other bots that apply roles on join. This is because bots that apply roles on join often run into a race condition where they're both setting the member's roles at the same time without knowing about the other, which results in one bot's roles overriding the other one's. Reapplying Zeppelin's roles after a delay should ensure that persisted roles get applied properly even in these cases.
This commit is contained in:
parent
1e5378a274
commit
514e93aa23
1 changed files with 44 additions and 22 deletions
|
@ -1,14 +1,51 @@
|
||||||
import { PermissionFlagsBits } from "discord.js";
|
import { GuildMember, PermissionFlagsBits } from "discord.js";
|
||||||
|
import { GuildPluginData } from "knub";
|
||||||
import intersection from "lodash.intersection";
|
import intersection from "lodash.intersection";
|
||||||
|
import { PersistedData } from "../../../data/entities/PersistedData";
|
||||||
|
import { SECONDS } from "../../../utils";
|
||||||
import { canAssignRole } from "../../../utils/canAssignRole";
|
import { canAssignRole } from "../../../utils/canAssignRole";
|
||||||
import { getMissingPermissions } from "../../../utils/getMissingPermissions";
|
import { getMissingPermissions } from "../../../utils/getMissingPermissions";
|
||||||
import { missingPermissionError } from "../../../utils/missingPermissionError";
|
import { missingPermissionError } from "../../../utils/missingPermissionError";
|
||||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||||
import { RoleManagerPlugin } from "../../RoleManager/RoleManagerPlugin";
|
import { RoleManagerPlugin } from "../../RoleManager/RoleManagerPlugin";
|
||||||
import { persistEvt } from "../types";
|
import { PersistPluginType, persistEvt } from "../types";
|
||||||
|
|
||||||
const p = PermissionFlagsBits;
|
const p = PermissionFlagsBits;
|
||||||
|
|
||||||
|
async function applyPersistedData(
|
||||||
|
pluginData: GuildPluginData<PersistPluginType>,
|
||||||
|
persistedData: PersistedData,
|
||||||
|
member: GuildMember,
|
||||||
|
): Promise<string[]> {
|
||||||
|
const config = await pluginData.config.getForMember(member);
|
||||||
|
const guildRoles = Array.from(pluginData.guild.roles.cache.keys());
|
||||||
|
const restoredData: string[] = [];
|
||||||
|
|
||||||
|
const persistedRoles = config.persisted_roles;
|
||||||
|
if (persistedRoles.length) {
|
||||||
|
const roleManager = pluginData.getPlugin(RoleManagerPlugin);
|
||||||
|
const rolesToRestore = intersection(persistedRoles, persistedData.roles, guildRoles).filter(
|
||||||
|
(roleId) => !member.roles.cache.has(roleId),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (rolesToRestore.length) {
|
||||||
|
restoredData.push("roles");
|
||||||
|
for (const roleId of rolesToRestore) {
|
||||||
|
roleManager.addRole(member.id, roleId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.persist_nicknames && persistedData.nickname && member.nickname !== persistedData.nickname) {
|
||||||
|
restoredData.push("nickname");
|
||||||
|
await member.edit({
|
||||||
|
nick: persistedData.nickname,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return restoredData;
|
||||||
|
}
|
||||||
|
|
||||||
export const LoadDataEvt = persistEvt({
|
export const LoadDataEvt = persistEvt({
|
||||||
event: "guildMemberAdd",
|
event: "guildMemberAdd",
|
||||||
|
|
||||||
|
@ -23,7 +60,6 @@ export const LoadDataEvt = persistEvt({
|
||||||
await pluginData.state.persistedData.clear(member.id);
|
await pluginData.state.persistedData.clear(member.id);
|
||||||
|
|
||||||
const config = await pluginData.config.getForMember(member);
|
const config = await pluginData.config.getForMember(member);
|
||||||
const restoredData: string[] = [];
|
|
||||||
|
|
||||||
// Check permissions
|
// Check permissions
|
||||||
const me = pluginData.guild.members.cache.get(pluginData.client.user!.id)!;
|
const me = pluginData.guild.members.cache.get(pluginData.client.user!.id)!;
|
||||||
|
@ -52,25 +88,11 @@ export const LoadDataEvt = persistEvt({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const persistedRoles = config.persisted_roles;
|
const restoredData = await applyPersistedData(pluginData, persistedData, member);
|
||||||
if (persistedRoles.length) {
|
setTimeout(() => {
|
||||||
const roleManager = pluginData.getPlugin(RoleManagerPlugin);
|
// Reapply persisted data after a while for better interop with other bots that restore roles
|
||||||
const rolesToRestore = intersection(persistedRoles, persistedData.roles, guildRoles);
|
void applyPersistedData(pluginData, persistedData, member);
|
||||||
|
}, 5 * SECONDS);
|
||||||
if (rolesToRestore.length) {
|
|
||||||
restoredData.push("roles");
|
|
||||||
for (const roleId of rolesToRestore) {
|
|
||||||
roleManager.addRole(member.id, roleId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.persist_nicknames && persistedData.nickname) {
|
|
||||||
restoredData.push("nickname");
|
|
||||||
await member.edit({
|
|
||||||
nick: persistedData.nickname,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (restoredData.length) {
|
if (restoredData.length) {
|
||||||
pluginData.getPlugin(LogsPlugin).logMemberRestore({
|
pluginData.getPlugin(LogsPlugin).logMemberRestore({
|
||||||
|
|
Loading…
Add table
Reference in a new issue