From 5b98c9bf2fe955d09ef8d7be50d24988ec5b09a1 Mon Sep 17 00:00:00 2001 From: Sammy Date: Fri, 23 Jun 2023 14:37:29 +0200 Subject: [PATCH 1/4] Rename event files to specific case We can add multiple eventhandlers per eventname. To avoid confusion and large files and to improve concise file names the event files were renamed --- server/commands/closepoll.ts | 2 +- server/events/announceManualWatchparty.ts | 26 +++++++++++++++++++ ...ntCreate.ts => autoCreateVoteByWPEvent.ts} | 3 +-- ...Update.ts => handlePermJFAccountByRole.ts} | 0 ...ate.ts => handleTempJFUserByVoiceEvent.ts} | 0 ...date.ts => handleTempJFUsersByWPEvents.ts} | 0 6 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 server/events/announceManualWatchparty.ts rename server/events/{guildScheduledEventCreate.ts => autoCreateVoteByWPEvent.ts} (96%) rename server/events/{guildMemberUpdate.ts => handlePermJFAccountByRole.ts} (100%) rename server/events/{voiceStateUpdate.ts => handleTempJFUserByVoiceEvent.ts} (100%) rename server/events/{guildScheduledEventUpdate.ts => handleTempJFUsersByWPEvents.ts} (100%) diff --git a/server/commands/closepoll.ts b/server/commands/closepoll.ts index ff3dfd8..8d0a3ba 100644 --- a/server/commands/closepoll.ts +++ b/server/commands/closepoll.ts @@ -3,7 +3,7 @@ import { Guild, GuildScheduledEvent, GuildScheduledEventEditOptions, GuildSchedu import { v4 as uuid } from 'uuid' import { client } from '../..' import { config } from '../configuration' -import { Emotes } from '../events/guildScheduledEventCreate' +import { Emotes } from '../events/autoCreateVoteByWPEvent' import { Maybe } from '../interfaces' import { logger } from '../logger' import { Command } from '../structures/command' diff --git a/server/events/announceManualWatchparty.ts b/server/events/announceManualWatchparty.ts new file mode 100644 index 0000000..e5b0e8f --- /dev/null +++ b/server/events/announceManualWatchparty.ts @@ -0,0 +1,26 @@ +import { format } from "date-fns"; +import { GuildScheduledEvent, Message, MessageCreateOptions, TextChannel } from "discord.js"; +import { ScheduledTask } from "node-cron"; +import { v4 as uuid } from "uuid"; +import { client, yavinJellyfinHandler } from "../.."; +import { config } from "../configuration"; +import { Maybe } from "../interfaces"; +import { logger } from "../logger"; + + +export const name = 'guildScheduledEventCreate' + +export async function execute(event: GuildScheduledEvent) { + const guildId = event.guildId + const requestId = uuid() + + if(event.description?.includes("!wp")) { + logger.info("Got manual create event of watchparty event!") + + + + + + } + +} \ No newline at end of file diff --git a/server/events/guildScheduledEventCreate.ts b/server/events/autoCreateVoteByWPEvent.ts similarity index 96% rename from server/events/guildScheduledEventCreate.ts rename to server/events/autoCreateVoteByWPEvent.ts index 74071b2..5ea0e5f 100644 --- a/server/events/guildScheduledEventCreate.ts +++ b/server/events/autoCreateVoteByWPEvent.ts @@ -17,8 +17,7 @@ export let task: ScheduledTask | undefined export async function execute(event: GuildScheduledEvent) { const requestId = uuid() - logger.debug(`New event created: ${JSON.stringify(event, null, 2)}`, { guildId: event.guildId, requestId }) - + if (event.name.toLowerCase().includes("!nextwp")) { logger.info("Event was a placeholder event to start a new watchparty and voting. Creating vote!", { guildId: event.guildId, requestId }) logger.debug("Renaming event", { guildId: event.guildId, requestId }) diff --git a/server/events/guildMemberUpdate.ts b/server/events/handlePermJFAccountByRole.ts similarity index 100% rename from server/events/guildMemberUpdate.ts rename to server/events/handlePermJFAccountByRole.ts diff --git a/server/events/voiceStateUpdate.ts b/server/events/handleTempJFUserByVoiceEvent.ts similarity index 100% rename from server/events/voiceStateUpdate.ts rename to server/events/handleTempJFUserByVoiceEvent.ts diff --git a/server/events/guildScheduledEventUpdate.ts b/server/events/handleTempJFUsersByWPEvents.ts similarity index 100% rename from server/events/guildScheduledEventUpdate.ts rename to server/events/handleTempJFUsersByWPEvents.ts From 31e440434e7d26651edfec1ab7a8175d7376c05a Mon Sep 17 00:00:00 2001 From: Sammy Date: Fri, 23 Jun 2023 15:51:07 +0200 Subject: [PATCH 2/4] properly clean up wp announcements without event only --- server/events/announceManualWatchparty.ts | 30 ++++++++--- server/events/autoCreateVoteByWPEvent.ts | 6 +-- .../events/deleteAnnouncementsWhenWPEnds.ts | 52 +++++++++++++++++++ server/events/handleTempJFUsersByWPEvents.ts | 12 ++--- server/helper/dateHelper.ts | 16 ++++++ 5 files changed, 97 insertions(+), 19 deletions(-) create mode 100644 server/events/deleteAnnouncementsWhenWPEnds.ts create mode 100644 server/helper/dateHelper.ts diff --git a/server/events/announceManualWatchparty.ts b/server/events/announceManualWatchparty.ts index e5b0e8f..a37f5d3 100644 --- a/server/events/announceManualWatchparty.ts +++ b/server/events/announceManualWatchparty.ts @@ -1,9 +1,8 @@ -import { format } from "date-fns"; -import { GuildScheduledEvent, Message, MessageCreateOptions, TextChannel } from "discord.js"; -import { ScheduledTask } from "node-cron"; +import { GuildScheduledEvent, TextChannel } from "discord.js"; import { v4 as uuid } from "uuid"; -import { client, yavinJellyfinHandler } from "../.."; +import { client } from "../.."; import { config } from "../configuration"; +import { createDateStringFromEvent } from "../helper/dateHelper"; import { Maybe } from "../interfaces"; import { logger } from "../logger"; @@ -13,14 +12,33 @@ export const name = 'guildScheduledEventCreate' export async function execute(event: GuildScheduledEvent) { const guildId = event.guildId const requestId = uuid() + try { + if (!event.description) { + logger.debug("Got GuildScheduledEventCreate event. But has no description. Aborting.") + return + } - if(event.description?.includes("!wp")) { - logger.info("Got manual create event of watchparty event!") + if (event.description.includes("!wp")) { + logger.info("Got manual create event of watchparty event!", { guildId, requestId }) + const channel: Maybe = client.getAnnouncementChannelForGuild(guildId) + if (!channel) { + logger.error("Could not obtain announcement channel. Aborting announcement.", { guildId, requestId }) + return + } + const message = `[Watchparty] https://discord.com/events/${event.guildId}/${event.id} \nHey <@&${config.bot.announcement_role}>, wir gucken ${event.name} ${createDateStringFromEvent(event, guildId, requestId)}` + channel.send(message) + } else { + logger.debug("Got GuildScheduledEventCreate event but no !wp in description. Not creating manual wp announcement.") + } + } catch (error) { + // sendFailureDM(error) + logger.error(error, { guildId, requestId }) } + } \ No newline at end of file diff --git a/server/events/autoCreateVoteByWPEvent.ts b/server/events/autoCreateVoteByWPEvent.ts index 5ea0e5f..6377928 100644 --- a/server/events/autoCreateVoteByWPEvent.ts +++ b/server/events/autoCreateVoteByWPEvent.ts @@ -1,9 +1,9 @@ -import { format } from "date-fns"; import { GuildScheduledEvent, Message, MessageCreateOptions, TextChannel } from "discord.js"; import { ScheduledTask } from "node-cron"; import { v4 as uuid } from "uuid"; import { client, yavinJellyfinHandler } from "../.."; import { config } from "../configuration"; +import { createDateStringFromEvent } from "../helper/dateHelper"; import { Maybe } from "../interfaces"; import { logger } from "../logger"; @@ -38,9 +38,7 @@ export async function execute(event: GuildScheduledEvent) { logger.info("EVENT DOES NOT HAVE STARTDATE; CANCELLING", {guildId: event.guildId, requestId}) return } - const date = format(event.scheduledStartAt, "dd.MM") - const time = format(event.scheduledStartAt, "HH:mm") - let message = `[Abstimmung] für https://discord.com/events/${event.guildId}/${event.id}\n<@&${config.bot.announcement_role}> Es gibt eine neue Abstimmung für die nächste Watchparty am ${date} um ${time}! Stimme hierunter für den nächsten Film ab!\n` + let message = `[Abstimmung] für https://discord.com/events/${event.guildId}/${event.id}\n<@&${config.bot.announcement_role}> Es gibt eine neue Abstimmung für die nächste Watchparty ${createDateStringFromEvent(event, event.guildId, requestId)}! Stimme hierunter für den nächsten Film ab!\n` for (let i = 0; i < movies.length; i++) { message = message.concat(Emotes[i]).concat(": ").concat(movies[i]).concat("\n") diff --git a/server/events/deleteAnnouncementsWhenWPEnds.ts b/server/events/deleteAnnouncementsWhenWPEnds.ts new file mode 100644 index 0000000..df35f4b --- /dev/null +++ b/server/events/deleteAnnouncementsWhenWPEnds.ts @@ -0,0 +1,52 @@ +import { Collection, GuildScheduledEvent, GuildScheduledEventStatus, Message } from "discord.js"; +import { v4 as uuid } from "uuid"; +import { client } from "../.."; +import { logger } from "../logger"; + + +export const name = 'guildScheduledEventUpdate' + +export async function execute(oldEvent: GuildScheduledEvent, newEvent: GuildScheduledEvent) { + const requestId = uuid() + try { + if (!newEvent.guild) { + logger.error("Event has no guild, aborting.", { guildId: newEvent.guildId, requestId }) + return + } + const guildId = newEvent.guildId + + if (newEvent.description?.toLowerCase().includes("!wp") && newEvent.status === GuildScheduledEventStatus.Completed) { + logger.info("A watchparty ended. Cleaning up announcements!", { guildId, requestId }) + const announcementChannel = client.getAnnouncementChannelForGuild(newEvent.guild.id) + if (!announcementChannel) { + logger.error("Could not find announcement channel. Aborting", { guildId: newEvent.guild.id, requestId }) + return + } + + const events = await newEvent.guild.scheduledEvents.fetch() + + const wpAnnouncements = (await announcementChannel.messages.fetch()).filter(message => !message.cleanContent.includes("[initial]")) + const announcementsWithoutEvent = filterAnnouncementsByPendingWPs(wpAnnouncements, events) + logger.info(`Deleting ${announcementsWithoutEvent.length} announcements.`, {guildId, requestId}) + announcementsWithoutEvent.forEach(message => message.delete()) + } + } catch (error) { + logger.error(error, { guildId: newEvent.guildId, requestId }) + } +} + +function filterAnnouncementsByPendingWPs(messages: Collection>, events: Collection>): Message[] { + const filteredMessages: Message[] = [] + for (const message of messages.values()) { + let foundEventForMessage = false + for (const event of events.values()) { + if (message.cleanContent.includes(event.id)) { //announcement always has eventid because of eventbox + foundEventForMessage = true + } + } + if(!foundEventForMessage){ + filteredMessages.push(message) + } + } + return filteredMessages +} \ No newline at end of file diff --git a/server/events/handleTempJFUsersByWPEvents.ts b/server/events/handleTempJFUsersByWPEvents.ts index eed87e7..42a719c 100644 --- a/server/events/handleTempJFUsersByWPEvents.ts +++ b/server/events/handleTempJFUsersByWPEvents.ts @@ -1,6 +1,6 @@ import { GuildMember, GuildScheduledEvent, GuildScheduledEventStatus } from "discord.js"; import { v4 as uuid } from "uuid"; -import { client, jellyfinHandler } from "../.."; +import { jellyfinHandler } from "../.."; import { getGuildSpecificTriggerRoleId } from "../helper/roleFilter"; import { logger } from "../logger"; @@ -10,7 +10,7 @@ export const name = 'guildScheduledEventUpdate' export async function execute(oldEvent: GuildScheduledEvent, newEvent: GuildScheduledEvent) { try { const requestId = uuid() - logger.debug(`Got scheduledEvent update. New Event: ${JSON.stringify(newEvent, null, 2)}`, { guildId: newEvent.guildId, requestId }) + // logger.debug(`Got scheduledEvent update. New Event: ${JSON.stringify(newEvent, null, 2)}`, { guildId: newEvent.guildId, requestId }) if (!newEvent.guild) { logger.error("Event has no guild, aborting.", { guildId: newEvent.guildId, requestId }) return @@ -32,13 +32,7 @@ export async function execute(oldEvent: GuildScheduledEvent, newEvent: GuildSche if (newEvent.status === GuildScheduledEventStatus.Active) createJFUsers(members, newEvent.name, requestId) else { - const announcementChannel = await client.getAnnouncementChannelForGuild(newEvent.guild.id) - if(!announcementChannel) { - logger.error("Could not find announcement channel. Aborting", { guildId: newEvent.guild.id, requestId }) - return - } - const announcements = (await announcementChannel.messages.fetch()).filter(message => !message.pinned) - announcements.forEach(message => message.delete()) + members.forEach(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.`)) }) diff --git a/server/helper/dateHelper.ts b/server/helper/dateHelper.ts new file mode 100644 index 0000000..f51752a --- /dev/null +++ b/server/helper/dateHelper.ts @@ -0,0 +1,16 @@ +import { format } from "date-fns"; +import { GuildScheduledEvent } from "discord.js"; +import { logger } from "../logger"; + +export function createDateStringFromEvent(event: GuildScheduledEvent, requestId: string, guildId?: string): string { + if(!event.scheduledStartAt) { + logger.error("Event has no start. Cannot create dateString.", {guildId, requestId}) + return "habe keinen Startzeitpunkt ermitteln können" + } + + const date = format(event.scheduledStartAt, "dd.MM") + const time = format(event.scheduledStartAt, "HH:mm") + + + return `am ${date} um ${time}` +} \ No newline at end of file From 45d87275bfd91981f98af4661ec03e34509624c8 Mon Sep 17 00:00:00 2001 From: Sammy Date: Fri, 23 Jun 2023 15:56:36 +0200 Subject: [PATCH 3/4] prevent announcement when description contains !private --- server/events/announceManualWatchparty.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/server/events/announceManualWatchparty.ts b/server/events/announceManualWatchparty.ts index a37f5d3..da29f13 100644 --- a/server/events/announceManualWatchparty.ts +++ b/server/events/announceManualWatchparty.ts @@ -20,6 +20,10 @@ export async function execute(event: GuildScheduledEvent) { if (event.description.includes("!wp")) { logger.info("Got manual create event of watchparty event!", { guildId, requestId }) + if(event.description.includes("!private")) { + logger.info("Event description contains \"!private\". Won't announce.", { guildId, requestId }) + return + } const channel: Maybe = client.getAnnouncementChannelForGuild(guildId) @@ -32,7 +36,7 @@ export async function execute(event: GuildScheduledEvent) { channel.send(message) } else { - logger.debug("Got GuildScheduledEventCreate event but no !wp in description. Not creating manual wp announcement.") + logger.debug("Got GuildScheduledEventCreate event but no !wp in description. Not creating manual wp announcement.", { guildId, requestId }) } } catch (error) { From 3a5ea5d4ff2abf4dd3416f698361e6073e1e51fa Mon Sep 17 00:00:00 2001 From: Sammy Date: Fri, 23 Jun 2023 19:30:17 +0200 Subject: [PATCH 4/4] improve message clarity when no start date in event found --- server/helper/dateHelper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/helper/dateHelper.ts b/server/helper/dateHelper.ts index f51752a..914f533 100644 --- a/server/helper/dateHelper.ts +++ b/server/helper/dateHelper.ts @@ -5,7 +5,7 @@ import { logger } from "../logger"; export function createDateStringFromEvent(event: GuildScheduledEvent, requestId: string, guildId?: string): string { if(!event.scheduledStartAt) { logger.error("Event has no start. Cannot create dateString.", {guildId, requestId}) - return "habe keinen Startzeitpunkt ermitteln können" + return `"habe keinen Startzeitpunkt ermitteln können"` } const date = format(event.scheduledStartAt, "dd.MM")