17 Commits

Author SHA1 Message Date
51ebf2e939 1.1.1
All checks were successful
Build a docker image for node-jellyfin-role-bot / build-docker-image (push) Successful in 12s
2023-06-23 19:44:58 +02:00
f314b2f355 maybe fix a docker build typo 2023-06-23 19:44:44 +02:00
a4d7c57d10 1.1.0
All checks were successful
Build a docker image for node-jellyfin-role-bot / build-docker-image (push) Successful in 14s
2023-06-23 19:33:31 +02:00
2802afa7d5 Merge pull request 'feat/#42_announce_manual_watchparty' (#50) from feat/#42_announce_manual_watchparty into master
Reviewed-on: #50
2023-06-23 19:31:57 +02:00
3a5ea5d4ff improve message clarity when no start date in event found
All checks were successful
Compile the repository / compile (pull_request) Successful in 4m8s
2023-06-23 19:30:17 +02:00
45d87275bf prevent announcement when description contains !private
All checks were successful
Compile the repository / compile (pull_request) Successful in 1m43s
2023-06-23 15:56:36 +02:00
31e440434e properly clean up wp announcements without event only 2023-06-23 15:51:48 +02:00
3d70b56eb7 Merge pull request 'feat/#43_append_event_invite' (#49) from feat/#43_append_event_invite into master
Reviewed-on: #49
2023-06-23 15:49:59 +02:00
3298c7a244 Merge pull request 'Create option "none of that" in voting' (#48) from feat/#39_none_of_that into master
Reviewed-on: #48
2023-06-23 15:49:43 +02:00
5b98c9bf2f 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
2023-06-23 14:37:41 +02:00
ee363e065c 1.0.4
All checks were successful
Build a docker image for node-jellyfin-role-bot / build-docker-image (push) Successful in 47s
2023-06-22 23:23:56 +02:00
9af847f234 Fix docker-build for good 2023-06-22 23:23:38 +02:00
a18406e7e4 1.0.3
Some checks failed
Build a docker image for node-jellyfin-role-bot / build-docker-image (push) Failing after 8s
2023-06-22 23:18:41 +02:00
b9f65125dc Hopefully fix ci/cd 2023-06-22 23:18:06 +02:00
9da8f47784 add event box to vote closed message
All checks were successful
Compile the repository / compile (pull_request) Successful in 1m18s
2023-06-22 19:38:59 +02:00
e8c58d5ff8 add event box to create message 2023-06-22 19:35:47 +02:00
8569a3e1e6 Create option "none of that" in voting
All checks were successful
Compile the repository / compile (pull_request) Successful in 1m19s
2023-06-22 18:53:29 +02:00
11 changed files with 133 additions and 25 deletions

View File

@ -19,11 +19,9 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Get Package Version
run: VERSION = node -p "require('./package.json').version"
- name: Log in to the Container registry
run: docker login -u ${{ env.USER }} -p ${{ secrets.TOKEN }} ${{ env.REGISTRY }}
- name: Build Container
run: docker build -t "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" -t "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}".
run: docker build -t "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" -t "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ node -p "require('./package.json').version" }}" .
- name: Push Container
run: docker push --all-tags "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest"
run: docker push --all-tags "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}"

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "node-jellyfin-discord-bot",
"version": "1.0.2",
"version": "1.1.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "node-jellyfin-discord-bot",
"version": "1.0.2",
"version": "1.1.1",
"license": "MIT",
"dependencies": {
"@discordjs/rest": "^1.7.0",

View File

@ -1,6 +1,6 @@
{
"name": "node-jellyfin-discord-bot",
"version": "1.0.2",
"version": "1.1.1",
"description": "A discord bot to sync jellyfin accounts with discord roles",
"main": "index.js",
"license": "MIT",

View File

@ -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'
@ -75,7 +75,7 @@ export async function closePoll(guild: Guild, requestId: string) {
async function sendVoteClosedMessage(event: GuildScheduledEvent, movie: string, guildId: string, requestId: string) {
const date = event.scheduledStartAt ? format(event.scheduledStartAt, "dd.MM") : "Fehler, event hatte kein Datum"
const time = event.scheduledStartAt ? format(event.scheduledStartAt, "HH:mm") : "Fehler, event hatte kein Datum"
const body = `[Abstimmung beendet] <@&${config.bot.announcement_role}> Wir gucken ${movie} am ${date} um ${time}`
const body = `[Abstimmung beendet] für https://discord.com/events/${event.guildId}/${event.id}\n<@&${config.bot.announcement_role}> Wir gucken ${movie} am ${date} um ${time}`
const options: MessageCreateOptions = {
content: body,
allowedMentions: { parse: ["roles"] }

View File

@ -0,0 +1,48 @@
import { GuildScheduledEvent, TextChannel } from "discord.js";
import { v4 as uuid } from "uuid";
import { client } from "../..";
import { config } from "../configuration";
import { createDateStringFromEvent } from "../helper/dateHelper";
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()
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!", { guildId, requestId })
if(event.description.includes("!private")) {
logger.info("Event description contains \"!private\". Won't announce.", { guildId, requestId })
return
}
const channel: Maybe<TextChannel> = 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.", { guildId, requestId })
}
} catch (error) {
// sendFailureDM(error)
logger.error(<string>error, { guildId, requestId })
}
}

View File

@ -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";
@ -11,12 +11,12 @@ import { logger } from "../logger";
export const name = 'guildScheduledEventCreate'
export enum Emotes { "1⃣", "2⃣", "3⃣", "4⃣", "5⃣", "6⃣", "7⃣", "8⃣", "9⃣", "🔟" }
export const NONE_OF_THAT = "❌"
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 })
@ -38,17 +38,16 @@ 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]\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")
}
message = message.concat(NONE_OF_THAT).concat(": Wenn dir nichts davon gefällt.")
const options: MessageCreateOptions = {
allowedMentions: { parse: ["roles"]},
content: message
content: message,
}
const sentMessage: Message<true> = await (await announcementChannel.fetch()).send(options)
@ -56,6 +55,7 @@ export async function execute(event: GuildScheduledEvent) {
for (let i = 0; i < movies.length; i++) {
sentMessage.react(Emotes[i])
}
sentMessage.react(NONE_OF_THAT)
// sentMessage.pin() //todo: uncomment when bot has permission to pin messages. Also update closepoll.ts to only fetch pinned messages
}

View File

@ -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(<string>error, { guildId: newEvent.guildId, requestId })
}
}
function filterAnnouncementsByPendingWPs(messages: Collection<string, Message<true>>, events: Collection<string, GuildScheduledEvent<GuildScheduledEventStatus>>): Message<true>[] {
const filteredMessages: Message<true>[] = []
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
}

View File

@ -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.`))
})

View File

@ -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}`
}