feat/40-reroll-on-disinterest #54
@ -1,10 +1,10 @@
|
||||
import { format, isToday } from "date-fns";
|
||||
import { utcToZonedTime } from "date-fns-tz"
|
||||
import { GuildScheduledEvent } from "discord.js";
|
||||
import { logger } from "../logger";
|
||||
import de from "date-fns/locale/de";
|
||||
import { Maybe } from "../interfaces";
|
||||
|
||||
export function createDateStringFromEvent(eventStartDate:Date, requestId: string, guildId?: string): string {
|
||||
export function createDateStringFromEvent(eventStartDate: Maybe<Date>, requestId: string, guildId?: string): string {
|
||||
if (!eventStartDate) {
|
||||
logger.error("Event has no start. Cannot create dateString.", { guildId, requestId })
|
||||
return `"habe keinen Startzeitpunkt ermitteln können"`
|
||||
|
@ -21,8 +21,7 @@ export type Vote = {
|
||||
}
|
||||
export type VoteMessageInfo = {
|
||||
votes: Vote[],
|
||||
eventId: string,
|
||||
eventDate: Date
|
||||
event: GuildScheduledEvent,
|
||||
}
|
||||
export default class VoteController {
|
||||
private client: ExtendedClient
|
||||
@ -74,11 +73,8 @@ export default class VoteController {
|
||||
logger.debug(`${vote.movie} : ${vote.count} -> above: ${overOneVote}`)
|
||||
return overOneVote
|
||||
}
|
||||
public async handleReroll(voteMessage: VoteMessage, guildId: string, requestId: string) {
|
||||
// get the movies currently being voted on, their votes, the eventId and its date
|
||||
const voteInfo: VoteMessageInfo = await this.parseVoteInfoFromVoteMessage(voteMessage, requestId)
|
||||
|
||||
magnetotail marked this conversation as resolved
Outdated
|
||||
let movies: string[] = Array()
|
||||
public async generateRerollMovieList(voteInfo: VoteMessageInfo, guildId: string, requestId: string) {
|
||||
if (config.bot.reroll_retains_top_picks) {
|
||||
const votedOnMovies = voteInfo.votes.filter(this.hasAtLeastOneVote).filter(x => x.emote !== NONE_OF_THAT)
|
||||
logger.info(`Found ${votedOnMovies.length} with votes`, { requestId, guildId })
|
||||
@ -86,40 +82,53 @@ export default class VoteController {
|
||||
logger.info(`Fetching ${newMovieCount} from jellyfin`)
|
||||
const newMovies: string[] = await this.yavinJellyfinHandler.getRandomMovieNames(newMovieCount, guildId, requestId)
|
||||
// merge
|
||||
movies = newMovies.concat(votedOnMovies.map(x => x.movie))
|
||||
return newMovies.concat(votedOnMovies.map(x => x.movie))
|
||||
} else {
|
||||
// get movies from jellyfin to fill the remaining slots
|
||||
const newMovieCount: number = config.bot.random_movie_count
|
||||
logger.info(`Fetching ${newMovieCount} from jellyfin`)
|
||||
movies = await this.yavinJellyfinHandler.getRandomMovieNames(newMovieCount, guildId, requestId)
|
||||
return await this.yavinJellyfinHandler.getRandomMovieNames(newMovieCount, guildId, requestId)
|
||||
}
|
||||
// create new message
|
||||
}
|
||||
|
||||
magnetotail marked this conversation as resolved
Outdated
magnetotail
commented
is not a message, only messagetext is not a message, only messagetext
kenobi
commented
a455fd8ff7e6b8ffb032fb4aed9389da68ee513b
kenobi
commented
done done
|
||||
public async handleReroll(voteMessage: VoteMessage, guildId: string, requestId: string) {
|
||||
// get the movies currently being voted on, their votes, the eventId and its date
|
||||
const voteInfo: VoteMessageInfo = await this.parseVoteInfoFromVoteMessage(voteMessage, requestId)
|
||||
if (!voteInfo.event.scheduledStartAt) {
|
||||
logger.info("Event does not have a start date, cancelling", { guildId: voteInfo.event.guildId, requestId })
|
||||
return
|
||||
}
|
||||
|
||||
let movies: string[] = await this.generateRerollMovieList(voteInfo, guildId, requestId)
|
||||
|
||||
logger.info(`Creating new poll message with new movies: ${movies}`, { requestId, guildId })
|
||||
const messageText = this.createVoteMessageText(voteInfo.eventId, voteInfo.eventDate, movies, guildId, requestId)
|
||||
const announcementChannel = this.client.getAnnouncementChannelForGuild(guildId)
|
||||
if (!announcementChannel) {
|
||||
logger.error(`No announcementChannel found for ${guildId}, can't post poll`)
|
||||
return
|
||||
}
|
||||
magnetotail marked this conversation as resolved
Outdated
magnetotail
commented
why not pin message in method above? why not pin message in method above?
kenobi
commented
7d794a8001a66d068f949c893d689a068c3caeed
should have been moved to prepareAndSendVoteMessage()
|
||||
|
||||
try {
|
||||
logger.info(`Trying to remove old vote Message`, { requestId, guildId })
|
||||
this.removeMessage(voteMessage)
|
||||
} catch (err) {
|
||||
// TODO: integrate failure DM to media Admin to inform about inability to delete old message
|
||||
logger.error(`Error during removeMessage: ${err}`)
|
||||
}
|
||||
|
||||
const sentMessage = await this.sendVoteMessage(messageText, movies.length, announcementChannel)
|
||||
sentMessage.pin()
|
||||
logger.info(`Sent and pinned new poll message`, { requestId, guildId })
|
||||
const sentMessage = this.prepareAndSendVoteMessage({
|
||||
event: voteInfo.event,
|
||||
movies,
|
||||
announcementChannel,
|
||||
startDate: voteInfo.event.scheduledStartAt,
|
||||
pinAfterSending: true
|
||||
},
|
||||
guildId,
|
||||
requestId)
|
||||
logger.debug(`Sent reroll message: ${JSON.stringify(sentMessage)}`, { requestId, guildId })
|
||||
}
|
||||
|
||||
private async fetchEventStartDateByEventId(guild: Guild, eventId: string, requestId: string): Promise<Maybe<Date>> {
|
||||
private async fetchEventByEventId(guild: Guild, eventId: string, requestId: string): Promise<Maybe<GuildScheduledEvent>> {
|
||||
const guildEvent: GuildScheduledEvent = await guild.scheduledEvents.fetch(eventId)
|
||||
if (!guildEvent) logger.error(`GuildScheduledEvent with id${eventId} could not be found`, { requestId, guildId: guild.id })
|
||||
if (guildEvent.scheduledStartAt)
|
||||
return guildEvent.scheduledStartAt
|
||||
return guildEvent
|
||||
}
|
||||
|
||||
public async parseVoteInfoFromVoteMessage(message: VoteMessage, requestId: string): Promise<VoteMessageInfo> {
|
||||
@ -129,8 +138,7 @@ export default class VoteController {
|
||||
if (!message.guild)
|
||||
throw new Error(`Message ${message.id} not a guild message`)
|
||||
|
||||
let eventStartDate: Maybe<Date> = await this.fetchEventStartDateByEventId(message.guild, parsedIds.eventId, requestId)
|
||||
if (!eventStartDate) eventStartDate = this.parseEventDateFromMessage(message.cleanContent, message.guild.id, requestId)
|
||||
const event: Maybe<GuildScheduledEvent> = await this.fetchEventByEventId(message.guild, parsedIds.eventId, requestId)
|
||||
|
||||
let votes: Vote[] = []
|
||||
for (const line of lines) {
|
||||
@ -149,7 +157,7 @@ export default class VoteController {
|
||||
}
|
||||
}
|
||||
}
|
||||
return <VoteMessageInfo>{ eventId: parsedIds.eventId, eventDate: eventStartDate, votes }
|
||||
return <VoteMessageInfo>{ event, votes }
|
||||
}
|
||||
public parseEventDateFromMessage(message: string, guildId: string, requestId: string): Date {
|
||||
logger.warn(`Falling back to RegEx parsing to get Event Date`, { guildId, requestId })
|
||||
@ -168,15 +176,15 @@ export default class VoteController {
|
||||
}
|
||||
|
||||
public async prepareAndSendVoteMessage(inputInfo: prepareVoteMessageInput, guildId: string, requestId: string) {
|
||||
const messageText = this.createVoteMessageText(inputInfo.event.id, inputInfo.startDate, inputInfo.movies, guildId, requestId)
|
||||
const messageText = this.createVoteMessageText(inputInfo.event, inputInfo.movies, guildId, requestId)
|
||||
const sentMessage = await this.sendVoteMessage(messageText, inputInfo.movies.length, inputInfo.announcementChannel)
|
||||
if (inputInfo.pinAfterSending)
|
||||
sentMessage.pin()
|
||||
return sentMessage
|
||||
}
|
||||
|
||||
public createVoteMessageText(eventId: string, eventStartDate: Date, movies: string[], guildId: string, requestId: string): string {
|
||||
let message = `[Abstimmung] für https://discord.com/events/${guildId}/${eventId} \n<@&${config.bot.announcement_role}> Es gibt eine neue Abstimmung für die nächste Watchparty ${createDateStringFromEvent(eventStartDate, guildId, requestId)}! Stimme hierunter für den nächsten Film ab!\n`
|
||||
public createVoteMessageText(event: GuildScheduledEvent, movies: string[], guildId: string, requestId: string): string {
|
||||
let message = `[Abstimmung] für https://discord.com/events/${guildId}/${event.id} \n<@&${config.bot.announcement_role}> Es gibt eine neue Abstimmung für die nächste Watchparty ${createDateStringFromEvent(event.scheduledStartAt, 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")
|
||||
@ -186,6 +194,7 @@ export default class VoteController {
|
||||
return message
|
||||
}
|
||||
|
||||
// TODO: Refactor into separate message controller
|
||||
public async sendVoteMessage(messageText: string, movieCount: number, announcementChannel: TextChannel) {
|
||||
|
||||
const options: MessageCreateOptions = {
|
||||
|
@ -29,11 +29,16 @@ describe('vote controller - none_of_that functions', () => {
|
||||
id: 'mockId'
|
||||
}
|
||||
}
|
||||
const mockEvent: GuildScheduledEvent = <GuildScheduledEvent><unknown>{
|
||||
scheduledStartAt: testEventDate,
|
||||
id: testEventId,
|
||||
guild: testGuildId
|
||||
}
|
||||
const mockJellyfinHandler: JellyfinHandler = <JellyfinHandler><unknown>{
|
||||
getRandomMovieNames: jest.fn().mockReturnValue(["movie1"])
|
||||
}
|
||||
const votes = new VoteController(mockClient, mockJellyfinHandler)
|
||||
const mockMessageContent = votes.createVoteMessageText(testEventId, testEventDate, testMovies, testGuildId, "requestId")
|
||||
const mockMessageContent = votes.createVoteMessageText(mockEvent, testMovies, testGuildId, "requestId")
|
||||
|
||||
test('sendVoteClosedMessage', async () => {
|
||||
mockClient.getAnnouncementChannelForGuild = jest.fn().mockReturnValue({
|
||||
@ -57,29 +62,6 @@ describe('vote controller - none_of_that functions', () => {
|
||||
content: `[Abstimmung beendet] für https://discord.com/events/${testGuildId}/${testEventId}\n<@&WATCHPARTY_ANNOUNCEMENT_ROLE> Wir gucken MovieNew am 01.01. um 01:00`
|
||||
})
|
||||
})
|
||||
// test('checkForPollsToClose', async () => {
|
||||
//
|
||||
// const testGuild: Guild = <Guild><unknown>{
|
||||
// scheduledEvents: {
|
||||
// fetch: jest.fn().mockImplementation(() => {
|
||||
// return new Promise(resolve => {
|
||||
// resolve([
|
||||
// { name: "Event Name" },
|
||||
// { name: "Event: VOTING OFFEN", scheduledStartTimestamp: "" },
|
||||
// { name: "another voting" },
|
||||
// ]
|
||||
// )
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// const result = await votes.checkForPollsToClose(testGuild)
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// })
|
||||
|
||||
test('getVotesByEmote', async () => {
|
||||
const mockMessage: Message = <Message><unknown>{
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Emoji, NONE_OF_THAT } from "../../server/constants"
|
||||
import VoteController, { Vote, VoteMessageInfo } from "../../server/helper/vote.controller"
|
||||
import VoteController, { VoteMessageInfo } from "../../server/helper/vote.controller"
|
||||
import { JellyfinHandler } from "../../server/jellyfin/handler"
|
||||
import { ExtendedClient } from "../../server/structures/client"
|
||||
import { VoteMessage } from "../../server/helper/messageIdentifiers"
|
||||
import { Message, MessageReaction } from "discord.js"
|
||||
import { GuildScheduledEvent, MessageReaction } from "discord.js"
|
||||
test('parse votes from vote message', async () => {
|
||||
const testMovies = [
|
||||
'Movie1',
|
||||
@ -16,12 +16,16 @@ test('parse votes from vote message', async () => {
|
||||
const testEventDate = new Date('2023-01-01')
|
||||
const testGuildId = "888999888"
|
||||
const voteController: VoteController = new VoteController(<ExtendedClient>{}, <JellyfinHandler>{})
|
||||
const testMessage = voteController.createVoteMessageText(testEventId, testEventDate, testMovies, testGuildId, "requestId")
|
||||
const mockEvent: GuildScheduledEvent = <GuildScheduledEvent><unknown>{
|
||||
scheduledStartAt: testEventDate,
|
||||
id: testEventId,
|
||||
guild: testGuildId
|
||||
}
|
||||
const testMessage = voteController.createVoteMessageText(mockEvent, testMovies, testGuildId, "requestId")
|
||||
|
||||
|
||||
const expectedResult: VoteMessageInfo = {
|
||||
eventId: testEventId,
|
||||
eventDate: testEventDate,
|
||||
event: mockEvent,
|
||||
votes: [
|
||||
{ emote: Emoji.one, count: 1, movie: testMovies[0] },
|
||||
{ emote: Emoji.two, count: 2, movie: testMovies[1] },
|
||||
@ -40,6 +44,8 @@ test('parse votes from vote message', async () => {
|
||||
fetch: jest.fn().mockImplementation((input: any) => {
|
||||
if (input === testEventId)
|
||||
return {
|
||||
id: testEventId,
|
||||
guild: testGuildId,
|
||||
scheduledStartAt: testEventDate
|
||||
}
|
||||
})
|
||||
@ -61,8 +67,8 @@ test('parse votes from vote message', async () => {
|
||||
const result = await voteController.parseVoteInfoFromVoteMessage(message, 'requestId')
|
||||
console.log(JSON.stringify(result))
|
||||
expect(Array.isArray(result)).toBe(false)
|
||||
expect(result.eventId).toEqual(testEventId)
|
||||
expect(result.eventDate).toEqual(testEventDate)
|
||||
expect(result.event.id).toEqual(testEventId)
|
||||
expect(result.event.scheduledStartAt).toEqual(testEventDate)
|
||||
expect(result.votes.length).toEqual(expectedResult.votes.length)
|
||||
expect(result).toEqual(expectedResult)
|
||||
})
|
||||
@ -79,7 +85,12 @@ test('parse votes from vote message', () => {
|
||||
const testEventDate = new Date('2023-01-01')
|
||||
const testGuildId = "888999888"
|
||||
const voteController: VoteController = new VoteController(<ExtendedClient>{}, <JellyfinHandler>{})
|
||||
const testMessage = voteController.createVoteMessageText(testEventId, testEventDate, testMovies, testGuildId, "requestId")
|
||||
const mockEvent: GuildScheduledEvent = <GuildScheduledEvent><unknown>{
|
||||
scheduledStartAt: testEventDate,
|
||||
id: testEventId,
|
||||
guild: testGuildId
|
||||
}
|
||||
const testMessage = voteController.createVoteMessageText(mockEvent, testMovies, testGuildId, "requestId")
|
||||
|
||||
const result = voteController.parseGuildIdAndEventIdFromWholeMessage(testMessage)
|
||||
expect(result).toEqual({ guildId: testGuildId, eventId: testEventId })
|
||||
@ -108,7 +119,12 @@ test.skip('handles complete none_of_that vote', () => {
|
||||
}
|
||||
}
|
||||
const voteController = new VoteController(mockClient, mockJellyfinHandler)
|
||||
const mockMessageContent = voteController.createVoteMessageText(testEventId, testEventDate, testMovies, testGuildId, "requestId")
|
||||
const mockEvent: GuildScheduledEvent = <GuildScheduledEvent><unknown>{
|
||||
scheduledStartAt: testEventDate,
|
||||
id: testEventId,
|
||||
guild: testGuildId
|
||||
}
|
||||
const mockMessageContent = voteController.createVoteMessageText(mockEvent, testMovies, testGuildId, "requestId")
|
||||
const reactedUponMessage: VoteMessage = <VoteMessage><unknown>{
|
||||
cleanContent: mockMessageContent,
|
||||
guild: {
|
||||
|
Loading…
Reference in New Issue
Block a user
maybe extract this if-else to a method to keep code more compact
7d794a8001
done