104 lines
4.9 KiB
TypeScript
104 lines
4.9 KiB
TypeScript
import { addDays, format, isAfter } from "date-fns";
|
||
import toDate from "date-fns/fp/toDate";
|
||
import { GuildScheduledEvent, Message, MessageCreateOptions, TextChannel } from "discord.js";
|
||
import { ScheduledTask, schedule } from "node-cron";
|
||
import { v4 as uuid } from "uuid";
|
||
import { client, jellyfinHandler } from "../..";
|
||
import { closePoll } from "../commands/closepoll";
|
||
import { config } from "../configuration";
|
||
import { logger } from "../logger";
|
||
import { Maybe } from "../interfaces";
|
||
|
||
|
||
export const name = 'guildScheduledEventCreate'
|
||
|
||
export enum Emotes { "1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣", "8️⃣", "9️⃣", "🔟" }
|
||
|
||
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 })
|
||
event.edit({ name: "Watchparty - Voting offen" })
|
||
const movies = await jellyfinHandler.getRandomMovies(5, event.guildId, requestId)
|
||
|
||
logger.info(`Got ${movies.length} random movies. Creating voting`, { guildId: event.guildId, requestId })
|
||
logger.debug(`Movies: ${JSON.stringify(movies.map(movie => movie.name))}`, { guildId: event.guildId, requestId })
|
||
|
||
const announcementChannel: Maybe<TextChannel> = client.getAnnouncementChannelForGuild(event.guildId)
|
||
if(!announcementChannel) {
|
||
logger.error("Could not find announcement channel. Aborting", { guildId: event.guildId, requestId })
|
||
return
|
||
}
|
||
logger.debug(`Found channel ${JSON.stringify(announcementChannel, null, 2)}`, { guildId: event.guildId, requestId })
|
||
|
||
if(!event.scheduledStartAt) {
|
||
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]\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`
|
||
|
||
for (let i = 0; i < movies.length; i++) {
|
||
message = message.concat(Emotes[i]).concat(": ").concat(movies[i].name ?? "Film hatte keinen Namen :(").concat("\n")
|
||
}
|
||
|
||
const options: MessageCreateOptions = {
|
||
allowedMentions: { parse: ["roles"]},
|
||
content: message
|
||
}
|
||
|
||
const sentMessage: Message<true> = await (await announcementChannel.fetch()).send(options)
|
||
|
||
for (let i = 0; i < movies.length; i++) {
|
||
sentMessage.react(Emotes[i])
|
||
}
|
||
|
||
if (!task) {
|
||
task = schedule("0 * * * * *", () => checkForPollsToClose(event))
|
||
}
|
||
|
||
// sentMessage.pin() //todo: uncomment when bot has permission to pin messages. Also update closepoll.ts to only fetch pinned messages
|
||
}
|
||
}
|
||
|
||
async function checkForPollsToClose(event: GuildScheduledEvent): Promise<void> {
|
||
const requestId = uuid()
|
||
logger.info(`Automatic check for poll closing.`, { guildId: event.guildId, requestId })
|
||
if (!event.guild) {
|
||
logger.error("No guild in event. Cancelling.", { guildId: event.guildId, requestId })
|
||
return
|
||
}
|
||
//refetch event in case the time changed or the poll is already closed
|
||
const events = (await event.guild.scheduledEvents.fetch())
|
||
.filter(event => event.name.toLowerCase().includes("voting offen"))
|
||
.map((value) => value)
|
||
|
||
if (!events || events.length <= 0) {
|
||
logger.info("Did not find any events. Cancelling", { guildId: event.guildId, requestId })
|
||
return
|
||
} else if (events.length > 1) {
|
||
logger.error(`More than one event found. Don't know which one is the right one :( Events: ${JSON.stringify(events, null, 2)}`, { guildId: event.guildId, requestId })
|
||
return
|
||
}
|
||
const updatedEvent = events[0] //add two hours because of different timezones in discord api and Date.now()
|
||
if (!updatedEvent.scheduledStartTimestamp) {
|
||
logger.error("Event does not have a scheduled start time. Cancelling", { guildId: event.guildId, requestId })
|
||
return
|
||
}
|
||
|
||
const eventDate: Date = toDate(updatedEvent.scheduledStartTimestamp)
|
||
const closePollDate: Date = addDays(eventDate, -2)
|
||
|
||
if (isAfter(Date.now(), closePollDate)) {
|
||
logger.info("Less than two days until event. Closing poll", { guildId: event.guildId, requestId })
|
||
closePoll(event.guild, requestId)
|
||
} else {
|
||
logger.info(`ScheduledStart: ${closePollDate}. Now: ${toDate(Date.now())}`, { guildId: event.guildId, requestId })
|
||
}
|
||
} |