From 1e1ab93667ed5eecd411741d8d85548eadb0ef23 Mon Sep 17 00:00:00 2001 From: Sammy Date: Fri, 9 Jun 2023 23:56:45 +0200 Subject: [PATCH] Fix edgecases for automatic user creation - make eventdescription !wp case insensitive - Create accounts for users in channel without subscription when event starts - Make sent messages caused by VoiceState event dependant on creation result (created, enabled) - Create tmp user if normal user exists but is disabled --- server/events/guildScheduledEventUpdate.ts | 27 ++++++++++++++-------- server/events/voiceStateUpdate.ts | 26 ++++++++++++++------- server/jellyfin/handler.ts | 22 ++++++++++-------- 3 files changed, 49 insertions(+), 26 deletions(-) diff --git a/server/events/guildScheduledEventUpdate.ts b/server/events/guildScheduledEventUpdate.ts index b5e89ee..c08353f 100644 --- a/server/events/guildScheduledEventUpdate.ts +++ b/server/events/guildScheduledEventUpdate.ts @@ -1,8 +1,8 @@ -import { GuildScheduledEvent, GuildScheduledEventStatus, Collection, Snowflake, GuildScheduledEventUser } from "discord.js"; -import { logger } from "../logger"; -import { jellyfinHandler } from "../.." +import { GuildMember, GuildScheduledEvent, GuildScheduledEventStatus } from "discord.js"; import { v4 as uuid } from "uuid"; +import { jellyfinHandler } from "../.."; import { getGuildSpecificTriggerRoleId } from "../helper/roleFilter"; +import { logger } from "../logger"; export const name = 'guildScheduledEventUpdate' @@ -12,14 +12,23 @@ export async function execute(oldEvent: GuildScheduledEvent, newEvent: GuildSche logger.info(JSON.stringify(newEvent, null, 2)) const requestId = uuid() - if (newEvent.description?.includes("!WP") && [GuildScheduledEventStatus.Active, GuildScheduledEventStatus.Completed].includes(newEvent.status)) { + if (newEvent.description?.toLowerCase().includes("!wp") && [GuildScheduledEventStatus.Active, GuildScheduledEventStatus.Completed].includes(newEvent.status)) { const roles = getGuildSpecificTriggerRoleId(newEvent.guildId).map((key, value)=> value) - const members = (await newEvent.fetchSubscribers({ withMember: true })).filter(member => !member.member.roles.cache.hasAny(...roles)) + const eventMembers = (await newEvent.fetchSubscribers({ withMember: true })).filter(member => !member.member.roles.cache.hasAny(...roles)).map((value, _) => value.member) + const channelMembers = newEvent.channel?.members.filter(member => !member.roles.cache.hasAny(...roles)).map((value, _) => value ) + const allMembers = eventMembers.concat(channelMembers ?? []) + + const members: GuildMember[] = [] + for(const member of allMembers){ + if(!members.find(x => x.id == member.id)) + members.push(member) + } + if (newEvent.status === GuildScheduledEventStatus.Active) createJFUsers(members, newEvent.name, requestId) else { members.forEach(member => { - member.member.createDM().then(channel => channel.send(`Die Watchparty ist vorbei, dein Account wurde wieder gelöscht. Wenn du einen permanenten Account haben möchtest, melde dich bei Samantha oder Marukus.`)) + member.createDM().then(channel => channel.send(`Die Watchparty ist vorbei, dein Account wurde wieder gelöscht. Wenn du einen permanenten Account haben möchtest, melde dich bei Samantha oder Marukus.`)) }) deleteJFUsers(newEvent.guildId, requestId) } @@ -28,11 +37,11 @@ export async function execute(oldEvent: GuildScheduledEvent, newEvent: GuildSche logger.error(error) } } -async function createJFUsers(members: Collection>, movieName: string, requestId?: string) { +async function createJFUsers(members: GuildMember[], movieName: string, requestId?: string) { logger.info(`Creating users for: \n ${JSON.stringify(members, null, 2)}`) members.forEach(member => { - member.member.createDM().then(channel => channel.send(`Hey! Du hast dich für die Watchparty von ${movieName} angemeldet! Es geht gleich los!`)) - jellyfinHandler.upsertUser(member.member, "TEMPORARY", requestId) + member.createDM().then(channel => channel.send(`Hey! Du hast dich für die Watchparty von ${movieName} angemeldet! Es geht gleich los!`)) + jellyfinHandler.upsertUser(member, "TEMPORARY", requestId) }) } diff --git a/server/events/voiceStateUpdate.ts b/server/events/voiceStateUpdate.ts index 31ff560..d4ef660 100644 --- a/server/events/voiceStateUpdate.ts +++ b/server/events/voiceStateUpdate.ts @@ -1,7 +1,8 @@ -import { GuildScheduledEvent, GuildScheduledEventStatus, Collection, Snowflake, GuildScheduledEventUser, User, VoiceState } from "discord.js"; -import { logger } from "../logger"; -import { jellyfinHandler } from "../.." +import { VoiceState } from "discord.js"; import { v4 as uuid } from "uuid"; +import { jellyfinHandler } from "../.."; +import { UserUpsertResult } from "../jellyfin/handler"; +import { logger } from "../logger"; export const name = 'voiceStateUpdate' @@ -9,13 +10,15 @@ export const name = 'voiceStateUpdate' export async function execute(oldState: VoiceState, newState: VoiceState) { try { + logger.info(JSON.stringify(newState, null, 2)) //ignore events like mute/unmute if(newState.channel?.id === oldState.channel?.id) { + logger.info("Not handling VoiceState event because channelid of old and new was the same (i.e. mute/unmute event)") return } const scheduledEvents = (await newState.guild.scheduledEvents.fetch()) - .filter((key, value) => key.description?.includes("!WP") && key.isActive()) + .filter((key, value) => key.description?.toLowerCase().includes("!wp") && key.isActive()) .map((key, value) => key) const scheduledEventUsers = (await Promise.all(scheduledEvents.map(event => event.fetchSubscribers({withMember: true})))) @@ -29,19 +32,26 @@ export async function execute(oldState: VoiceState, newState: VoiceState) { userFound = true; }) }) - if(userFound) + if(userFound) { + logger.info(`Not handling VoiceState event because user was already subscribed and got an account from there. User: ${JSON.stringify(newState.member, null, 2)}`) return + } if (scheduledEvents.find(event => event.channelId === newState.channelId)) { if(newState.member){ logger.info("YO! Da ist jemand dem Channel mit dem Event beigetreten, ich kümmer mich mal um nen Account!") - - newState.member.createDM().then(channel => channel.send(`Hey! Du bist unserer Watchparty beigetreten, ich leg dir mal nen Account an, damit du mitschauen kannst!`)) - jellyfinHandler.upsertUser(newState.member, "TEMPORARY", uuid()) + const result = await jellyfinHandler.upsertUser(newState.member, "TEMPORARY", uuid()) + if (result === UserUpsertResult.created) { + newState.member.createDM().then(channel => channel.send(`Hey! Du bist unserer Watchparty beigetreten, ich hab dir gerade die Zugangsdaten für den Mediaserver geschickt!`)) + } else { + newState.member.createDM().then(channel => channel.send(`Hey! Du bist unserer Watchparty beigetreten aber du hast bereits einen Account. Falls du ein neues Passwort brauchst nutze /reset_passwort!`)) + } } else { logger.error("WTF? Expected Member?? When doing things") } + } else { + logger.info("VoiceState channelId was not the id of any channel with events") } }catch(error){ logger.error(error) diff --git a/server/jellyfin/handler.ts b/server/jellyfin/handler.ts index 1617a44..18bb0e4 100644 --- a/server/jellyfin/handler.ts +++ b/server/jellyfin/handler.ts @@ -1,12 +1,11 @@ import { GuildMember } from "discord.js"; +import { Config } from "../configuration"; +import { Maybe, PermissionLevel } from "../interfaces"; +import { logger } from "../logger"; import { CreateUserByNameOperationRequest, DeleteUserRequest, SystemApi, UpdateUserPasswordOperationRequest, UpdateUserPolicyOperationRequest, UserApi } from "./apis"; +import { UpdateUserPasswordRequest } from "./models"; import { UserDto } from "./models/UserDto"; import { Configuration, ConfigurationParameters } from "./runtime"; -import { CreateUserByNameRequest, UpdateUserEasyPasswordRequest, UpdateUserPasswordRequest, UpdateUserPolicyRequest } from "./models"; -import { Config } from "../configuration"; -import { logger } from "../logger"; -import { Maybe, PermissionLevel } from "../interfaces"; -import { v4 as uuid } from "uuid"; export class JellyfinHandler { @@ -210,15 +209,20 @@ export class JellyfinHandler { } } - public async upsertUser(newMember: GuildMember, level: PermissionLevel, requestId?: string) { - logger.error(`Trying to upsert user ${newMember.displayName}, with permissionLevel ${level}`, { guildId: newMember.guild.id, requestId }) + public async upsertUser(newMember: GuildMember, level: PermissionLevel, requestId?: string): Promise { + logger.info(`Trying to upsert user ${newMember.displayName}, with permissionLevel ${level}`, { guildId: newMember.guild.id, requestId }) const jfuser = await this.getUser(newMember, requestId) - if (jfuser) { + if (jfuser && !jfuser.policy?.isDisabled) { logger.info(`User with name ${newMember.displayName} is already present`, { guildId: newMember.guild.id, requestId }) await this.enableUser(jfuser, newMember.guild.id, requestId) + return UserUpsertResult.enabled } else { this.createUserAccountForDiscordUser(newMember, level, newMember.guild.id, requestId) + return UserUpsertResult.created } } -} + + +} +export enum UserUpsertResult {enabled, created} -- 2.40.1