diff --git a/server/events/guildMemberUpdate.ts b/server/events/guildMemberUpdate.ts index 5949ec9..4b0d773 100644 --- a/server/events/guildMemberUpdate.ts +++ b/server/events/guildMemberUpdate.ts @@ -1,5 +1,5 @@ import { Collection, GuildMember } from "discord.js" -import { filterRolesFromMemberUpdate } from "../helper/roleFilter" +import { filterRolesFromMemberUpdate, getGuildSpecificTriggerRoleId } from "../helper/roleFilter" import { ChangedRoles, PermissionLevel } from "../interfaces" import { jellyfinHandler } from "../.." import { v4 as uuid } from "uuid" @@ -18,7 +18,7 @@ export async function execute(oldMember: GuildMember, newMember: GuildMember) { } const removedRoleMatches = changedRoles.removedRoles.find(rRole => rRole.id === key) if (removedRoleMatches) { - jellyfinHandler.removeUser(newMember, requestId) + jellyfinHandler.removeUser(newMember, level, requestId) } }) } catch (error) { @@ -26,10 +26,5 @@ export async function execute(oldMember: GuildMember, newMember: GuildMember) { } } -function getGuildSpecificTriggerRoleId(id: string): Collection { - const outVal = new Collection() - outVal.set('1096819983889215659', "VIEWER") - outVal.set('1097990848613986526', "ADMIN") - return outVal -} + diff --git a/server/events/guildScheduledEventUpdate.ts b/server/events/guildScheduledEventUpdate.ts index 84c51e2..b5e89ee 100644 --- a/server/events/guildScheduledEventUpdate.ts +++ b/server/events/guildScheduledEventUpdate.ts @@ -1,7 +1,8 @@ -import { GuildScheduledEvent, GuildScheduledEventStatus, Collection, Snowflake, GuildScheduledEventUser} from "discord.js"; +import { GuildScheduledEvent, GuildScheduledEventStatus, Collection, Snowflake, GuildScheduledEventUser } from "discord.js"; import { logger } from "../logger"; import { jellyfinHandler } from "../.." import { v4 as uuid } from "uuid"; +import { getGuildSpecificTriggerRoleId } from "../helper/roleFilter"; export const name = 'guildScheduledEventUpdate' @@ -9,32 +10,33 @@ export const name = 'guildScheduledEventUpdate' export async function execute(oldEvent: GuildScheduledEvent, newEvent: GuildScheduledEvent) { try { logger.info(JSON.stringify(newEvent, null, 2)) + const requestId = uuid() if (newEvent.description?.includes("!WP") && [GuildScheduledEventStatus.Active, GuildScheduledEventStatus.Completed].includes(newEvent.status)) { - const members = await newEvent.fetchSubscribers({withMember: true}) - newEvent.guild?.members.fetch - if(newEvent.status === GuildScheduledEventStatus.Active) - createJFUsers(members, newEvent.name) - else - deleteJFUsers(members) + const roles = getGuildSpecificTriggerRoleId(newEvent.guildId).map((key, value)=> value) + const members = (await newEvent.fetchSubscribers({ withMember: true })).filter(member => !member.member.roles.cache.hasAny(...roles)) + 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.`)) + }) + deleteJFUsers(newEvent.guildId, requestId) + } } - } catch(error) { + } catch (error) { logger.error(error) } } - -async function createJFUsers(members: Collection>, movieName: string) { +async function createJFUsers(members: Collection>, 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, "wird eh nicht genutzt", uuid()) + jellyfinHandler.upsertUser(member.member, "TEMPORARY", requestId) }) } -async function deleteJFUsers(members: Collection>) { - logger.info(`Deleting users for: \n ${JSON.stringify(members, null, 2)}`) - members.forEach(member => { - member.member.createDM().then(channel => channel.send(`Hey! Da die Watchparty vorbei ist, hab ich deinen Account wieder entfernt. Falls du einen permanenten Account haben möchtest frag bitte Samantha oder Marukus :)`)) - jellyfinHandler.removeUser(member.member, uuid()) - }) +async function deleteJFUsers(guildId: string, requestId?: string) { + logger.info(`Watchparty ended, deleting tmp users`) + jellyfinHandler.purge(guildId, requestId) } \ No newline at end of file diff --git a/server/events/voiceStateUpdate.ts b/server/events/voiceStateUpdate.ts index 5a043cd..31ff560 100644 --- a/server/events/voiceStateUpdate.ts +++ b/server/events/voiceStateUpdate.ts @@ -38,7 +38,7 @@ export async function execute(oldState: VoiceState, newState: VoiceState) { 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, "wird eh nicht genutzt", uuid()) + jellyfinHandler.upsertUser(newState.member, "TEMPORARY", uuid()) } else { logger.error("WTF? Expected Member?? When doing things") } diff --git a/server/helper/roleFilter.ts b/server/helper/roleFilter.ts index 3c64323..7d64efe 100644 --- a/server/helper/roleFilter.ts +++ b/server/helper/roleFilter.ts @@ -1,5 +1,5 @@ -import { GuildMember } from "discord.js" -import { ChangedRoles } from "../interfaces" +import { Collection, GuildMember } from "discord.js" +import { ChangedRoles, PermissionLevel } from "../interfaces" import { logger } from "../logger" export function filterRolesFromMemberUpdate(oldMember: GuildMember, newMember: GuildMember): ChangedRoles { @@ -14,3 +14,10 @@ export function filterRolesFromMemberUpdate(oldMember: GuildMember, newMember: G return { addedRoles, removedRoles } } + +export function getGuildSpecificTriggerRoleId(guildId: string): Collection { + const outVal = new Collection() + outVal.set('1096819983889215659', "VIEWER") + outVal.set('1097990848613986526', "ADMIN") + return outVal +} \ No newline at end of file diff --git a/server/interfaces.ts b/server/interfaces.ts index 1d8ccd1..e9807d3 100644 --- a/server/interfaces.ts +++ b/server/interfaces.ts @@ -32,4 +32,4 @@ export interface ChangedRoles { addedRoles: Collection removedRoles: Collection } -export type PermissionLevel = "VIEWER" | "ADMIN" +export type PermissionLevel = "VIEWER" | "ADMIN" | "TEMPORARY" diff --git a/server/jellyfin/handler.ts b/server/jellyfin/handler.ts index b6dc2ea..2c6bdbc 100644 --- a/server/jellyfin/handler.ts +++ b/server/jellyfin/handler.ts @@ -1,11 +1,11 @@ import { GuildMember } from "discord.js"; -import { CreateUserByNameOperationRequest, SystemApi, UpdateUserPasswordOperationRequest, UpdateUserPolicyOperationRequest, UserApi } from "./apis"; +import { CreateUserByNameOperationRequest, DeleteUserRequest, SystemApi, UpdateUserPasswordOperationRequest, UpdateUserPolicyOperationRequest, UserApi } from "./apis"; 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 } from "../interfaces"; +import { Maybe, PermissionLevel } from "../interfaces"; import { v4 as uuid } from "uuid"; @@ -46,8 +46,8 @@ export class JellyfinHandler { logger.info(`Initialized Jellyfin handler`, { requestId: 'Init' }) } - private generateJFUserName(discordUser: GuildMember): string { - return discordUser.displayName + private generateJFUserName(discordUser: GuildMember, level: PermissionLevel): string { + return `${discordUser.displayName}${level == "TEMPORARY" ? "_tmp" : ""}` } public async addPermissionsToUserAccount(jfUserAccount: UserDto, guildId: string, requestId: string): Promise { @@ -58,8 +58,8 @@ export class JellyfinHandler { return (Math.random() * 10000 + 10000).toFixed(0) } - public async createUserAccountForDiscordUser(discordUser: GuildMember, guildId?: string, requestId?: string): Promise { - const newUserName = this.generateJFUserName(discordUser) + public async createUserAccountForDiscordUser(discordUser: GuildMember, level: PermissionLevel, guildId?: string, requestId?: string): Promise { + const newUserName = this.generateJFUserName(discordUser, level) logger.info(`New Username for ${discordUser.displayName}: ${newUserName}`, { guildId, requestId }) const req: CreateUserByNameOperationRequest = { createUserByNameRequest: { @@ -94,30 +94,50 @@ export class JellyfinHandler { } public async getUser(discordUser: GuildMember, requestId?: string): Promise> { - logger.info(`Getting user for discord member ${discordUser.displayName}`, {requestId}) - const jfUsernameFromDiscordUsername = this.generateJFUserName(discordUser) + logger.info(`Getting user for discord member ${discordUser.displayName}`, { requestId }) const jfUsers = await this.getCurrentUsers(discordUser.guild.id, requestId) - const foundUser = jfUsers.find(x => x.name === jfUsernameFromDiscordUsername) + const foundUser = jfUsers.find(x => x.name?.includes(discordUser.displayName)) return foundUser } - public async removeUser(newMember: GuildMember, requestId?: string) { - logger.error(`Trying to remove user ${newMember.displayName}, but method is not implemented`, {requestId}) + public async removeUser(newMember: GuildMember, level: PermissionLevel, requestId?: string) { + logger.info(`${level == "TEMPORARY" ? "Deleting" : "Disabling" } user ${newMember.displayName}, but method is not implemented`, { requestId }) const jfuser = await this.getUser(newMember, requestId) - if (jfuser) { - await this.disableUser(jfuser, newMember.guild.id, requestId) + if (jfuser && jfuser.id) { + if (level === "TEMPORARY") { + const r: DeleteUserRequest = { + userId: jfuser.id + } + this.userApi.deleteUser(r) + } + else + await this.disableUser(jfuser, newMember.guild.id, requestId) } } + public async purge(guildId: string, requestId?: string) { + logger.info("Deleting tmp users") + const users = (await this.userApi.getUsers()).filter(user => user.name?.endsWith("_tmp")) + + users.forEach(user => { + if(user.id) { + const r: DeleteUserRequest = { + userId: user.id + } + this.userApi.deleteUser(r) + } + }) + } + public async resetUserPasswort(member: GuildMember, requestId?: string) { - logger.info(`Resetting password for user ${member.displayName}`, {requestId}) + logger.info(`Resetting password for user ${member.displayName}`, { requestId }) const jfUser = await this.getUser(member, requestId) if (jfUser && jfUser.id) { // const reset: UpdateUserPasswordRequest = { // resetPassword: true // } - + // const shit: UpdateUserPasswordOperationRequest = { // updateUserPasswordRequest: reset, // userId: jfUser.id @@ -127,7 +147,7 @@ export class JellyfinHandler { // logger.info("Resetting password", {requestId}) // await this.userApi.updateUserPassword(shit); - + const password = this.generatePasswordForUser() const passwordRequest: UpdateUserPasswordRequest = { // resetPassword: true, @@ -140,7 +160,7 @@ export class JellyfinHandler { userId: jfUser.id } - logger.info("Setting new password", {requestId}) + logger.info("Setting new password", { requestId }) await this.userApi.updateUserPassword(passwordOperationRequest); @@ -190,14 +210,14 @@ export class JellyfinHandler { } } - public async upsertUser(newMember: GuildMember, level: string, requestId?: string) { + public async upsertUser(newMember: GuildMember, level: PermissionLevel, requestId?: string) { logger.error(`Trying to upsert user ${newMember.displayName}, with permissionLevel ${level}`) const jfuser = await this.getUser(newMember, requestId) if (jfuser) { logger.info(`User with name ${newMember.displayName} is already present`) await this.enableUser(jfuser, newMember.guild.id, requestId) } else { - this.createUserAccountForDiscordUser(newMember, newMember.guild.id, requestId) + this.createUserAccountForDiscordUser(newMember, level, newMember.guild.id, requestId) } } }