Compare commits
	
		
			58 Commits
		
	
	
		
			3298c7a244
			...
			feat/cicd
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 36d1306180 | |||
| 69bde313b5 | |||
| 7af3d87048 | |||
| 73741230b1 | |||
| 4f6d4f646a | |||
| 6169649261 | |||
| 0560c4620c | |||
| be3ee5e493 | |||
| 251e6ae3d6 | |||
| 2edd0312dc | |||
| e52e845851 | |||
| 61544feaba | |||
| 1966640239 | |||
| fa9998e92c | |||
| c1a449bafe | |||
| d5d82043f0 | |||
| 51ebf2e939 | |||
| f314b2f355 | |||
| a4d7c57d10 | |||
| 2802afa7d5 | |||
| 3a5ea5d4ff | |||
| 45d87275bf | |||
| 31e440434e | |||
| 3d70b56eb7 | |||
| 5b98c9bf2f | |||
| 9da8f47784 | |||
| e8c58d5ff8 | |||
| f2b5ee502f | |||
| 749e1c89ab | |||
| 0d5799796a | |||
| b7986d276b | |||
| 8540381834 | |||
| 7e67d1fed9 | |||
| 0cb19ba8f1 | |||
| 5dcf766593 | |||
| 808bdd033e | |||
| 33f031d333 | |||
| 40d9523e21 | |||
| 26e74a62c1 | |||
| c0f91aad79 | |||
| 79ffde5f34 | |||
| 911b9e4884 | |||
| 31a9e0eb28 | |||
| bcf788293e | |||
| 934b6dfead | |||
| cd0c8c0017 | |||
| 83f803d0e7 | |||
| 2cb652aee6 | |||
| 034d14eb15 | |||
| c8bfc47ddf | |||
| b67982ed38 | |||
| e3144fc402 | |||
| 1970f4b0cb | |||
| 8ac4f568a0 | |||
| 09f4efc96c | |||
| 6e0c3b8ef6 | |||
| 8ee36f7510 | |||
| 1593e126eb | 
| @ -22,6 +22,6 @@ jobs: | |||||||
|       - name: Log in to the Container registry |       - name: Log in to the Container registry | ||||||
|         run: docker login -u ${{ env.USER }} -p ${{ secrets.TOKEN }} ${{ env.REGISTRY }} |         run: docker login -u ${{ env.USER }} -p ${{ secrets.TOKEN }} ${{ env.REGISTRY }} | ||||||
|       - name: Build Container |       - name: Build Container | ||||||
|         run: docker build -t "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" -t "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ node -p "require('./package.json').version" }}". |         run: docker build -t "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" . | ||||||
|       - name: Push Container |       - name: Push Container | ||||||
|         run: docker push --all-tags "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}" |         run: docker push --all-tags "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}" | ||||||
|  | |||||||
							
								
								
									
										19
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										19
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -1,12 +1,12 @@ | |||||||
| { | { | ||||||
|   "name": "node-jellyfin-discord-bot", |   "name": "node-jellyfin-discord-bot", | ||||||
|   "version": "1.0.4", |   "version": "1.1.3", | ||||||
|   "lockfileVersion": 2, |   "lockfileVersion": 2, | ||||||
|   "requires": true, |   "requires": true, | ||||||
|   "packages": { |   "packages": { | ||||||
|     "": { |     "": { | ||||||
|       "name": "node-jellyfin-discord-bot", |       "name": "node-jellyfin-discord-bot", | ||||||
|       "version": "1.0.4", |       "version": "1.1.3", | ||||||
|       "license": "MIT", |       "license": "MIT", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@discordjs/rest": "^1.7.0", |         "@discordjs/rest": "^1.7.0", | ||||||
| @ -17,6 +17,7 @@ | |||||||
|         "@types/uuid": "^9.0.1", |         "@types/uuid": "^9.0.1", | ||||||
|         "axios": "^1.3.5", |         "axios": "^1.3.5", | ||||||
|         "date-fns": "^2.29.3", |         "date-fns": "^2.29.3", | ||||||
|  |         "date-fns-tz": "^2.0.0", | ||||||
|         "discord-api-types": "^0.37.38", |         "discord-api-types": "^0.37.38", | ||||||
|         "discord.js": "^14.9.0", |         "discord.js": "^14.9.0", | ||||||
|         "dotenv": "^16.0.3", |         "dotenv": "^16.0.3", | ||||||
| @ -2626,6 +2627,14 @@ | |||||||
|         "url": "https://opencollective.com/date-fns" |         "url": "https://opencollective.com/date-fns" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |     "node_modules/date-fns-tz": { | ||||||
|  |       "version": "2.0.0", | ||||||
|  |       "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-2.0.0.tgz", | ||||||
|  |       "integrity": "sha512-OAtcLdB9vxSXTWHdT8b398ARImVwQMyjfYGkKD2zaGpHseG2UPHbHjXELReErZFxWdSLph3c2zOaaTyHfOhERQ==", | ||||||
|  |       "peerDependencies": { | ||||||
|  |         "date-fns": ">=2.0.0" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     "node_modules/debug": { |     "node_modules/debug": { | ||||||
|       "version": "4.3.4", |       "version": "4.3.4", | ||||||
|       "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", |       "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", | ||||||
| @ -8905,6 +8914,12 @@ | |||||||
|       "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", |       "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", | ||||||
|       "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==" |       "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==" | ||||||
|     }, |     }, | ||||||
|  |     "date-fns-tz": { | ||||||
|  |       "version": "2.0.0", | ||||||
|  |       "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-2.0.0.tgz", | ||||||
|  |       "integrity": "sha512-OAtcLdB9vxSXTWHdT8b398ARImVwQMyjfYGkKD2zaGpHseG2UPHbHjXELReErZFxWdSLph3c2zOaaTyHfOhERQ==", | ||||||
|  |       "requires": {} | ||||||
|  |     }, | ||||||
|     "debug": { |     "debug": { | ||||||
|       "version": "4.3.4", |       "version": "4.3.4", | ||||||
|       "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", |       "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "node-jellyfin-discord-bot", |   "name": "node-jellyfin-discord-bot", | ||||||
|   "version": "1.0.4", |   "version": "1.1.3", | ||||||
|   "description": "A discord bot to sync jellyfin accounts with discord roles", |   "description": "A discord bot to sync jellyfin accounts with discord roles", | ||||||
|   "main": "index.js", |   "main": "index.js", | ||||||
|   "license": "MIT", |   "license": "MIT", | ||||||
| @ -13,6 +13,7 @@ | |||||||
|     "@types/uuid": "^9.0.1", |     "@types/uuid": "^9.0.1", | ||||||
|     "axios": "^1.3.5", |     "axios": "^1.3.5", | ||||||
|     "date-fns": "^2.29.3", |     "date-fns": "^2.29.3", | ||||||
|  |     "date-fns-tz": "^2.0.0", | ||||||
|     "discord-api-types": "^0.37.38", |     "discord-api-types": "^0.37.38", | ||||||
|     "discord.js": "^14.9.0", |     "discord.js": "^14.9.0", | ||||||
|     "dotenv": "^16.0.3", |     "dotenv": "^16.0.3", | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ import { Guild, GuildScheduledEvent, GuildScheduledEventEditOptions, GuildSchedu | |||||||
| import { v4 as uuid } from 'uuid' | import { v4 as uuid } from 'uuid' | ||||||
| import { client } from '../..' | import { client } from '../..' | ||||||
| import { config } from '../configuration' | import { config } from '../configuration' | ||||||
| import { Emotes } from '../events/guildScheduledEventCreate' | import { Emotes } from '../events/autoCreateVoteByWPEvent' | ||||||
| import { Maybe } from '../interfaces' | import { Maybe } from '../interfaces' | ||||||
| import { logger } from '../logger' | import { logger } from '../logger' | ||||||
| import { Command } from '../structures/command' | 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) { | 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 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 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 = { |     const options: MessageCreateOptions = { | ||||||
|         content: body, |         content: body, | ||||||
|         allowedMentions: { parse: ["roles"] } |         allowedMentions: { parse: ["roles"] } | ||||||
|  | |||||||
							
								
								
									
										48
									
								
								server/events/announceManualWatchparty.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								server/events/announceManualWatchparty.ts
									
									
									
									
									
										Normal 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 }) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -1,12 +1,11 @@ | |||||||
| import { format } from "date-fns"; |  | ||||||
| import { GuildScheduledEvent, Message, MessageCreateOptions, TextChannel } from "discord.js"; | import { GuildScheduledEvent, Message, MessageCreateOptions, TextChannel } from "discord.js"; | ||||||
| import { ScheduledTask } from "node-cron"; | import { ScheduledTask } from "node-cron"; | ||||||
| import { v4 as uuid } from "uuid"; | import { v4 as uuid } from "uuid"; | ||||||
| import { client, yavinJellyfinHandler } from "../.."; | import { client, yavinJellyfinHandler } from "../.."; | ||||||
| import { config } from "../configuration"; | import { config } from "../configuration"; | ||||||
|  | import { createDateStringFromEvent } from "../helper/dateHelper"; | ||||||
| import { Maybe } from "../interfaces"; | import { Maybe } from "../interfaces"; | ||||||
| import { logger } from "../logger"; | import { logger } from "../logger"; | ||||||
| import { SemanticClassificationFormat } from "typescript"; |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| export const name = 'guildScheduledEventCreate' | export const name = 'guildScheduledEventCreate' | ||||||
| @ -18,8 +17,7 @@ export let task: ScheduledTask | undefined | |||||||
| 
 | 
 | ||||||
| export async function execute(event: GuildScheduledEvent) { | export async function execute(event: GuildScheduledEvent) { | ||||||
|     const requestId = uuid() |     const requestId = uuid() | ||||||
|     logger.debug(`New event created: ${JSON.stringify(event, null, 2)}`, { guildId: event.guildId, requestId }) |      | ||||||
| 
 |  | ||||||
|     if (event.name.toLowerCase().includes("!nextwp")) { |     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.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 }) |         logger.debug("Renaming event", { guildId: event.guildId, requestId }) | ||||||
| @ -40,9 +38,7 @@ export async function execute(event: GuildScheduledEvent) { | |||||||
|             logger.info("EVENT DOES NOT HAVE STARTDATE; CANCELLING", {guildId: event.guildId, requestId}) |             logger.info("EVENT DOES NOT HAVE STARTDATE; CANCELLING", {guildId: event.guildId, requestId}) | ||||||
|             return |             return | ||||||
|         } |         } | ||||||
|         const date = format(event.scheduledStartAt, "dd.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 ${createDateStringFromEvent(event, event.guildId, requestId)}! Stimme hierunter für den nächsten Film ab!\n` | ||||||
|         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++) { |         for (let i = 0; i < movies.length; i++) { | ||||||
|             message = message.concat(Emotes[i]).concat(": ").concat(movies[i]).concat("\n") |             message = message.concat(Emotes[i]).concat(": ").concat(movies[i]).concat("\n") | ||||||
| @ -51,7 +47,7 @@ export async function execute(event: GuildScheduledEvent) { | |||||||
| 
 | 
 | ||||||
|         const options: MessageCreateOptions = { |         const options: MessageCreateOptions = { | ||||||
|             allowedMentions: { parse: ["roles"]}, |             allowedMentions: { parse: ["roles"]}, | ||||||
|             content: message |             content: message, | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         const sentMessage: Message<true> = await (await announcementChannel.fetch()).send(options) |         const sentMessage: Message<true> = await (await announcementChannel.fetch()).send(options) | ||||||
							
								
								
									
										52
									
								
								server/events/deleteAnnouncementsWhenWPEnds.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								server/events/deleteAnnouncementsWhenWPEnds.ts
									
									
									
									
									
										Normal 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 | ||||||
|  | } | ||||||
| @ -1,6 +1,6 @@ | |||||||
| import { GuildMember, GuildScheduledEvent, GuildScheduledEventStatus } from "discord.js"; | import { GuildMember, GuildScheduledEvent, GuildScheduledEventStatus } from "discord.js"; | ||||||
| import { v4 as uuid } from "uuid"; | import { v4 as uuid } from "uuid"; | ||||||
| import { client, jellyfinHandler } from "../.."; | import { jellyfinHandler } from "../.."; | ||||||
| import { getGuildSpecificTriggerRoleId } from "../helper/roleFilter"; | import { getGuildSpecificTriggerRoleId } from "../helper/roleFilter"; | ||||||
| import { logger } from "../logger"; | import { logger } from "../logger"; | ||||||
| 
 | 
 | ||||||
| @ -10,7 +10,7 @@ export const name = 'guildScheduledEventUpdate' | |||||||
| export async function execute(oldEvent: GuildScheduledEvent, newEvent: GuildScheduledEvent) { | export async function execute(oldEvent: GuildScheduledEvent, newEvent: GuildScheduledEvent) { | ||||||
|     try { |     try { | ||||||
|         const requestId = uuid() |         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) { |         if (!newEvent.guild) { | ||||||
|             logger.error("Event has no guild, aborting.", { guildId: newEvent.guildId, requestId }) |             logger.error("Event has no guild, aborting.", { guildId: newEvent.guildId, requestId }) | ||||||
|             return |             return | ||||||
| @ -32,13 +32,7 @@ export async function execute(oldEvent: GuildScheduledEvent, newEvent: GuildSche | |||||||
|             if (newEvent.status === GuildScheduledEventStatus.Active) |             if (newEvent.status === GuildScheduledEventStatus.Active) | ||||||
|                 createJFUsers(members, newEvent.name, requestId) |                 createJFUsers(members, newEvent.name, requestId) | ||||||
|             else { |             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 => { |                 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.`)) |                     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.`)) | ||||||
|                 }) |                 }) | ||||||
							
								
								
									
										23
									
								
								server/helper/dateHelper.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								server/helper/dateHelper.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | |||||||
|  | import { format, isToday, toDate } 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"; | ||||||
|  |  | ||||||
|  | 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 timeZone = 'Europe/Berlin' | ||||||
|  |     const zonedDateTime = utcToZonedTime(event.scheduledStartAt, timeZone) | ||||||
|  |     const time = format(zonedDateTime, "HH:mm", {locale: de}) | ||||||
|  |      | ||||||
|  |     if(isToday(zonedDateTime)) { | ||||||
|  |         return `heute um ${time}` | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const date = format(zonedDateTime, "eeee dd.MM", {locale: de}) | ||||||
|  |     return `am ${date} um ${time}` | ||||||
|  | } | ||||||
| @ -2,7 +2,7 @@ import { GuildMember } from "discord.js"; | |||||||
| import { JellyfinConfig, Maybe, PermissionLevel } from "../interfaces"; | import { JellyfinConfig, Maybe, PermissionLevel } from "../interfaces"; | ||||||
| import { logger } from "../logger"; | import { logger } from "../logger"; | ||||||
| import { CreateUserByNameOperationRequest, DeleteUserRequest, GetItemsRequest, ItemsApi, SystemApi, UpdateUserPasswordOperationRequest, UpdateUserPolicyOperationRequest, UserApi } from "./apis"; | import { CreateUserByNameOperationRequest, DeleteUserRequest, GetItemsRequest, ItemsApi, SystemApi, UpdateUserPasswordOperationRequest, UpdateUserPolicyOperationRequest, UserApi } from "./apis"; | ||||||
| import { BaseItemDto, UpdateUserPasswordRequest } from "./models"; | import { BaseItemDto, UpdateUserPasswordRequest, UpdateUserPolicyRequest } from "./models"; | ||||||
| import { UserDto } from "./models/UserDto"; | import { UserDto } from "./models/UserDto"; | ||||||
| import { Configuration, ConfigurationParameters } from "./runtime"; | import { Configuration, ConfigurationParameters } from "./runtime"; | ||||||
|  |  | ||||||
| @ -52,24 +52,46 @@ export class JellyfinHandler { | |||||||
|     return (Math.random() * 10000 + 10000).toFixed(0) |     return (Math.random() * 10000 + 10000).toFixed(0) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public async createUserAccountForDiscordUser(discordUser: GuildMember, level: PermissionLevel, guildId?: string, requestId?: string): Promise<UserDto> { |   public async createUserAccountForDiscordUser(discordUser: GuildMember, level: PermissionLevel, requestId: string, guildId?: string): Promise<UserDto> { | ||||||
|     const newUserName = this.generateJFUserName(discordUser, level) |     const newUserName = this.generateJFUserName(discordUser, level) | ||||||
|     logger.info(`New Username for ${discordUser.displayName}: ${newUserName}`, { guildId, requestId }) |     logger.info(`New Username for ${discordUser.displayName}: ${newUserName}`, { guildId, requestId }) | ||||||
|     const req: CreateUserByNameOperationRequest = { |     const req: CreateUserByNameOperationRequest = { | ||||||
|       createUserByNameRequest: { |       createUserByNameRequest: { | ||||||
|         name: newUserName, |         name: newUserName, | ||||||
|         password: this.generatePasswordForUser(), |         password: this.generatePasswordForUser() | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     logger.debug(JSON.stringify(req), { requestId, guildId }) |     logger.debug(JSON.stringify(req), { requestId, guildId }) | ||||||
|     const createResult = await this.userApi.createUserByName(req) |     const createResult = await this.userApi.createUserByName(req) | ||||||
|     if (createResult) { |     if (createResult) { | ||||||
|  |       if(createResult.policy) { | ||||||
|  |         this.setUserPermissions(createResult, requestId, guildId) | ||||||
|  |       } | ||||||
|       (await discordUser.createDM()).send(`Ich hab dir mal nen Account angelegt :)\nDein Username ist ${createResult.name}, dein Password ist "${req.createUserByNameRequest.password}"!`) |       (await discordUser.createDM()).send(`Ich hab dir mal nen Account angelegt :)\nDein Username ist ${createResult.name}, dein Password ist "${req.createUserByNameRequest.password}"!`) | ||||||
|       return createResult |       return createResult | ||||||
|     } |     } | ||||||
|     else throw new Error('Could not create User in Jellyfin') |     else throw new Error('Could not create User in Jellyfin') | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   public async setUserPermissions(user: UserDto, requestId: string, guildId?: string) { | ||||||
|  |     if(!user.policy || !user.id) { | ||||||
|  |       logger.error(`Cannot update user policy. User ${user.name} has no policy to modify`, {guildId, requestId})  | ||||||
|  |       return | ||||||
|  |     } | ||||||
|  |     user.policy.enableVideoPlaybackTranscoding = false | ||||||
|  |  | ||||||
|  |     const operation: UpdateUserPolicyRequest = { | ||||||
|  |       ...user.policy, | ||||||
|  |       enableVideoPlaybackTranscoding: false | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const request: UpdateUserPolicyOperationRequest = { | ||||||
|  |       userId: user.id, | ||||||
|  |       updateUserPolicyRequest: operation | ||||||
|  |     } | ||||||
|  |     this.userApi.updateUserPolicy(request) | ||||||
|  |   } | ||||||
|  |  | ||||||
|   public async isUserAlreadyPresent(discordUser: GuildMember, requestId?: string): Promise<boolean> { |   public async isUserAlreadyPresent(discordUser: GuildMember, requestId?: string): Promise<boolean> { | ||||||
|     const jfuser = await this.getUser(discordUser, requestId) |     const jfuser = await this.getUser(discordUser, requestId) | ||||||
|     logger.debug(`Presence for DiscordUser ${discordUser.id}:${jfuser !== undefined}`, { guildId: discordUser.guild.id, requestId }) |     logger.debug(`Presence for DiscordUser ${discordUser.id}:${jfuser !== undefined}`, { guildId: discordUser.guild.id, requestId }) | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user