From e1323687a7f7540381c39b4c863d7d3177d2e119 Mon Sep 17 00:00:00 2001 From: Dark <7890309+DarkView@users.noreply.github.com> Date: Tue, 21 Jul 2020 01:02:42 +0200 Subject: [PATCH] Migrated Persist to new Plugin structure --- backend/src/plugins/Persist/PersistPlugin.ts | 33 ++++++++++++ .../src/plugins/Persist/events/LoadDataEvt.ts | 52 +++++++++++++++++++ .../plugins/Persist/events/StoreDataEvt.ts | 35 +++++++++++++ backend/src/plugins/Persist/types.ts | 22 ++++++++ backend/src/plugins/availablePlugins.ts | 2 + 5 files changed, 144 insertions(+) create mode 100644 backend/src/plugins/Persist/PersistPlugin.ts create mode 100644 backend/src/plugins/Persist/events/LoadDataEvt.ts create mode 100644 backend/src/plugins/Persist/events/StoreDataEvt.ts create mode 100644 backend/src/plugins/Persist/types.ts diff --git a/backend/src/plugins/Persist/PersistPlugin.ts b/backend/src/plugins/Persist/PersistPlugin.ts new file mode 100644 index 00000000..6233d696 --- /dev/null +++ b/backend/src/plugins/Persist/PersistPlugin.ts @@ -0,0 +1,33 @@ +import { PluginOptions } from "knub"; +import { zeppelinPlugin } from "../ZeppelinPluginBlueprint"; +import { PersistPluginType, ConfigSchema } from "./types"; +import { GuildPersistedData } from "src/data/GuildPersistedData"; +import { GuildLogs } from "src/data/GuildLogs"; +import { StoreDataEvt } from "./events/StoreDataEvt"; +import { LoadDataEvt } from "./events/LoadDataEvt"; + +const defaultOptions: PluginOptions = { + config: { + persisted_roles: [], + persist_nicknames: false, + persist_voice_mutes: false, + }, +}; + +export const PersistPlugin = zeppelinPlugin()("persist", { + configSchema: ConfigSchema, + defaultOptions, + + // prettier-ignore + events: [ + StoreDataEvt, + LoadDataEvt, + ], + + onLoad(pluginData) { + const { state, guild } = pluginData; + + state.persistedData = GuildPersistedData.getGuildInstance(guild.id); + state.logs = new GuildLogs(guild.id); + }, +}); diff --git a/backend/src/plugins/Persist/events/LoadDataEvt.ts b/backend/src/plugins/Persist/events/LoadDataEvt.ts new file mode 100644 index 00000000..63404921 --- /dev/null +++ b/backend/src/plugins/Persist/events/LoadDataEvt.ts @@ -0,0 +1,52 @@ +import { persistEvent } from "../types"; +import { MemberOptions } from "eris"; +import intersection from "lodash.intersection"; +import { LogType } from "src/data/LogType"; +import { stripObjectToScalars } from "src/utils"; + +export const LoadDataEvt = persistEvent({ + event: "guildMemberAdd", + + async listener(meta) { + const member = meta.args.member; + const pluginData = meta.pluginData; + + const memberRolesLock = await pluginData.locks.acquire(`member-roles-${member.id}`); + + const persistedData = await pluginData.state.persistedData.find(member.id); + if (!persistedData) { + memberRolesLock.unlock(); + return; + } + + const toRestore: MemberOptions = {}; + const config = pluginData.config.getForMember(member); + const restoredData = []; + + const persistedRoles = config.persisted_roles; + if (persistedRoles.length) { + const rolesToRestore = intersection(persistedRoles, persistedData.roles); + if (rolesToRestore.length) { + restoredData.push("roles"); + toRestore.roles = Array.from(new Set([...rolesToRestore, ...member.roles])); + } + } + + if (config.persist_nicknames && persistedData.nickname) { + restoredData.push("nickname"); + toRestore.nick = persistedData.nickname; + } + + if (restoredData.length) { + await member.edit(toRestore, "Restored upon rejoin"); + await pluginData.state.persistedData.clear(member.id); + + pluginData.state.logs.log(LogType.MEMBER_RESTORE, { + member: stripObjectToScalars(member, ["user", "roles"]), + restoredData: restoredData.join(", "), + }); + } + + memberRolesLock.unlock(); + }, +}); diff --git a/backend/src/plugins/Persist/events/StoreDataEvt.ts b/backend/src/plugins/Persist/events/StoreDataEvt.ts new file mode 100644 index 00000000..5de3bc8a --- /dev/null +++ b/backend/src/plugins/Persist/events/StoreDataEvt.ts @@ -0,0 +1,35 @@ +import { persistEvent } from "../types"; +import { IPartialPersistData } from "src/data/GuildPersistedData"; +import { Member } from "eris"; +import intersection from "lodash.intersection"; + +export const StoreDataEvt = persistEvent({ + event: "guildMemberRemove", + + async listener(meta) { + const member = meta.args.member as Member; + const pluginData = meta.pluginData; + + let persist = false; + const persistData: IPartialPersistData = {}; + const config = pluginData.config.getForUser(member.user); + + const persistedRoles = config.persisted_roles; + if (persistedRoles.length && member.roles) { + const rolesToPersist = intersection(persistedRoles, member.roles); + if (rolesToPersist.length) { + persist = true; + persistData.roles = rolesToPersist; + } + } + + if (config.persist_nicknames && member.nick) { + persist = true; + persistData.nickname = member.nick; + } + + if (persist) { + pluginData.state.persistedData.set(member.id, persistData); + } + }, +}); diff --git a/backend/src/plugins/Persist/types.ts b/backend/src/plugins/Persist/types.ts new file mode 100644 index 00000000..d7900cbd --- /dev/null +++ b/backend/src/plugins/Persist/types.ts @@ -0,0 +1,22 @@ +import * as t from "io-ts"; +import { BasePluginType, eventListener } from "knub"; +import { GuildPersistedData } from "src/data/GuildPersistedData"; +import { GuildLogs } from "src/data/GuildLogs"; + +export const ConfigSchema = t.type({ + persisted_roles: t.array(t.string), + persist_nicknames: t.boolean, + persist_voice_mutes: t.boolean, // Deprecated, here to not break old configs +}); +export type TConfigSchema = t.TypeOf; + +export interface PersistPluginType extends BasePluginType { + config: TConfigSchema; + + state: { + persistedData: GuildPersistedData; + logs: GuildLogs; + }; +} + +export const persistEvent = eventListener(); diff --git a/backend/src/plugins/availablePlugins.ts b/backend/src/plugins/availablePlugins.ts index 0dce5a2c..06705dba 100644 --- a/backend/src/plugins/availablePlugins.ts +++ b/backend/src/plugins/availablePlugins.ts @@ -1,10 +1,12 @@ import { UtilityPlugin } from "./Utility/UtilityPlugin"; import { LocateUserPlugin } from "./LocateUser/LocateUserPlugin"; import { ZeppelinPluginBlueprint } from "./ZeppelinPluginBlueprint"; +import { PersistPlugin } from "./Persist/PersistPlugin"; // prettier-ignore export const guildPlugins: Array> = [ LocateUserPlugin, + PersistPlugin, UtilityPlugin, ];