2023-06-15 21:56:15 +02:00
import { addDays , format , isAfter } from "date-fns" ;
import toDate from "date-fns/fp/toDate" ;
2023-06-13 23:15:03 +02:00
import { GuildScheduledEvent , Message , MessageCreateOptions , TextChannel } from "discord.js" ;
2023-06-10 22:53:11 +02:00
import { ScheduledTask , schedule } from "node-cron" ;
2023-06-10 14:23:10 +02:00
import { v4 as uuid } from "uuid" ;
2023-06-15 22:33:22 +02:00
import { client , yavinJellyfinHandler } from "../.." ;
2023-06-10 22:53:11 +02:00
import { closePoll } from "../commands/closepoll" ;
2023-06-10 14:23:10 +02:00
import { config } from "../configuration" ;
2023-06-15 21:56:15 +02:00
import { Maybe } from "../interfaces" ;
2023-06-15 22:33:22 +02:00
import { logger } from "../logger" ;
2023-06-10 14:23:10 +02:00
export const name = 'guildScheduledEventCreate'
2023-06-10 22:53:11 +02:00
export enum Emotes { "1️ ⃣" , "2️ ⃣" , "3️ ⃣" , "4️ ⃣" , "5️ ⃣" , "6️ ⃣" , "7️ ⃣" , "8️ ⃣" , "9️ ⃣" , "🔟" }
export let task : ScheduledTask | undefined
2023-06-10 14:23:10 +02:00
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" } )
2023-06-15 22:33:22 +02:00
const movies = await yavinJellyfinHandler . getRandomMovies ( 5 , event . guildId , requestId )
2023-06-10 14:23:10 +02:00
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 } )
2023-06-15 21:56:15 +02:00
const announcementChannel : Maybe < TextChannel > = client . getAnnouncementChannelForGuild ( event . guildId )
if ( ! announcementChannel ) {
logger . error ( "Could not find announcement channel. Aborting" , { guildId : event.guildId , requestId } )
return
}
2023-06-12 20:27:54 +02:00
logger . debug ( ` Found channel ${ JSON . stringify ( announcementChannel , null , 2 ) } ` , { guildId : event.guildId , requestId } )
2023-06-10 14:23:10 +02:00
2023-06-14 22:24:39 +02:00
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 `
2023-06-10 14:23:10 +02:00
for ( let i = 0 ; i < movies . length ; i ++ ) {
2023-06-15 21:56:15 +02:00
message = message . concat ( Emotes [ i ] ) . concat ( ": " ) . concat ( movies [ i ] . name ? ? "Film hatte keinen Namen :(" ) . concat ( "\n" )
2023-06-10 14:23:10 +02:00
}
2023-06-13 23:15:03 +02:00
const options : MessageCreateOptions = {
allowedMentions : { parse : [ "roles" ] } ,
content : message
}
const sentMessage : Message < true > = await ( await announcementChannel . fetch ( ) ) . send ( options )
2023-06-10 14:23:10 +02:00
for ( let i = 0 ; i < movies . length ; i ++ ) {
2023-06-10 17:27:32 +02:00
sentMessage . react ( Emotes [ i ] )
2023-06-10 14:23:10 +02:00
}
2023-06-11 09:01:25 +02:00
if ( ! task ) {
2023-06-10 22:53:11 +02:00
task = schedule ( "0 * * * * *" , ( ) = > checkForPollsToClose ( event ) )
}
2023-06-10 17:27:32 +02:00
// sentMessage.pin() //todo: uncomment when bot has permission to pin messages. Also update closepoll.ts to only fetch pinned messages
2023-06-10 14:23:10 +02:00
}
2023-06-10 22:53:11 +02:00
}
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" ) )
2023-06-15 21:56:15 +02:00
. map ( ( value ) = > value )
2023-06-10 22:53:11 +02:00
2023-06-11 09:01:25 +02:00
if ( ! events || events . length <= 0 ) {
2023-06-10 22:53:11 +02:00
logger . info ( "Did not find any events. Cancelling" , { guildId : event.guildId , requestId } )
return
2023-06-11 09:01:25 +02:00
} else if ( events . length > 1 ) {
2023-06-10 22:53:11 +02:00
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()
2023-06-11 09:01:25 +02:00
if ( ! updatedEvent . scheduledStartTimestamp ) {
2023-06-10 22:53:11 +02:00
logger . error ( "Event does not have a scheduled start time. Cancelling" , { guildId : event.guildId , requestId } )
return
}
2023-06-12 19:43:33 +02:00
const eventDate : Date = toDate ( updatedEvent . scheduledStartTimestamp )
const closePollDate : Date = addDays ( eventDate , - 2 )
if ( isAfter ( Date . now ( ) , closePollDate ) ) {
2023-06-10 22:53:11 +02:00
logger . info ( "Less than two days until event. Closing poll" , { guildId : event.guildId , requestId } )
closePoll ( event . guild , requestId )
} else {
2023-06-12 19:43:33 +02:00
logger . info ( ` ScheduledStart: ${ closePollDate } . Now: ${ toDate ( Date . now ( ) ) } ` , { guildId : event.guildId , requestId } )
2023-06-10 22:53:11 +02:00
}
2023-06-10 14:23:10 +02:00
}