Compare commits

..

16 Commits

Author SHA1 Message Date
a60fc2db7e remove unnecessary maybe type union
All checks were successful
Compile the repository / compile (pull_request) Successful in 17s
Run unit tests / test (pull_request) Successful in 15s
2023-11-25 20:35:15 +01:00
a50ac1716f make return value for role non optional, instead throws on error
All checks were successful
Compile the repository / compile (pull_request) Successful in 22s
Run unit tests / test (pull_request) Successful in 19s
2023-11-25 20:05:37 +01:00
ef39c6315d fix interface name and import
All checks were successful
Compile the repository / compile (pull_request) Successful in 19s
Run unit tests / test (pull_request) Successful in 18s
2023-11-25 19:51:02 +01:00
1f372b0aac fix naming for reaction 2023-11-25 19:50:54 +01:00
d1aacbb3d3 fix incorrect parameter passing
All checks were successful
Compile the repository / compile (pull_request) Successful in 16s
Run unit tests / test (pull_request) Successful in 15s
2023-11-22 19:56:20 +01:00
1ae8278fb8 remove unused client
Some checks failed
Compile the repository / compile (pull_request) Failing after 18s
Run unit tests / test (pull_request) Successful in 16s
2023-11-22 19:51:35 +01:00
417b24d408 add function to fetch announcement role id
All checks were successful
Compile the repository / compile (pull_request) Successful in 16s
Run unit tests / test (pull_request) Successful in 14s
intended flow: use id fetch function to get role for current guild, use role id to fetch role from discord role cache,
use role in intended use case
currently the role id is hardcoded, needs to be read from some sort of cache which persists the ids in config file
needs to be differentiated by guild id and role type
could be the target of a user configurable frontend in the future
2023-11-21 23:33:25 +01:00
88061c361c rename announcement role assign function
All checks were successful
Compile the repository / compile (pull_request) Successful in 16s
Run unit tests / test (pull_request) Successful in 15s
2023-11-21 22:42:50 +01:00
f83f54749d move manage announce roles to role controller
All checks were successful
Run unit tests / test (pull_request) Successful in 16s
Compile the repository / compile (pull_request) Successful in 17s
2023-11-21 22:42:00 +01:00
90b0b07080 extend Maybe type to also include void 2023-11-21 22:40:53 +01:00
6d0eaed426 fix incorrect method call
All checks were successful
Compile the repository / compile (pull_request) Successful in 17s
Run unit tests / test (pull_request) Successful in 13s
2023-11-20 00:31:16 +01:00
8f320cee5c implement very basic functionality of role add/rm
Some checks failed
Compile the repository / compile (pull_request) Failing after 16s
Run unit tests / test (pull_request) Successful in 14s
2023-11-20 00:27:23 +01:00
016bb243cc add messageReactionRemove
All checks were successful
Compile the repository / compile (pull_request) Successful in 21s
Run unit tests / test (pull_request) Successful in 1m33s
2023-11-20 00:17:28 +01:00
2c8cd96ac7 call vote controller in messageReactionAdd 2023-11-20 00:17:19 +01:00
ba4aefed8e add a minimal vote controller 2023-11-20 00:17:02 +01:00
8efae12907 add hook 2023-11-20 00:03:45 +01:00
7 changed files with 125 additions and 44 deletions

View File

@ -82,41 +82,5 @@ Für eine Erklärung wie das alles funktioniert mach einfach /mitgucken für ein
}
export async function manageAnnouncementRoles(guild: Guild, reaction: MessageReaction, requestId: string) {
const guildId = guild.id
logger.info("Managing roles", { guildId, requestId })
const announcementRole: Role | undefined = (await guild.roles.fetch()).find(role => role.id === config.bot.announcement_role)
if (!announcementRole) {
logger.error(`Could not find announcement role! Aborting! Was looking for role with id: ${config.bot.announcement_role}`, { guildId, requestId })
return
}
const usersWhoWantRole: User[] = (await reaction.users.fetch()).filter(user => !user.bot).map(user => user)
const allUsers = (await guild.members.fetch())
const usersWhoHaveRole: GuildMember[] = allUsers
.filter(member => member.roles.cache
.find(role => role.id === config.bot.announcement_role) !== undefined)
.map(member => member)
const usersWhoNeedRoleRevoked: GuildMember[] = usersWhoHaveRole
.filter(userWhoHas => !usersWhoWantRole.map(wanter => wanter.id).includes(userWhoHas.id))
const usersWhoDontHaveRole: GuildMember[] = allUsers
.filter(member => member.roles.cache
.find(role => role.id === config.bot.announcement_role) === undefined)
.map(member => member)
const usersWhoNeedRole: GuildMember[] = usersWhoDontHaveRole
.filter(userWhoNeeds => usersWhoWantRole.map(wanter => wanter.id).includes(userWhoNeeds.id))
logger.debug(`Theses users will get the role removed: ${JSON.stringify(usersWhoNeedRoleRevoked)}`, { guildId, requestId })
logger.debug(`Theses users will get the role added: ${JSON.stringify(usersWhoNeedRole)}`, { guildId, requestId })
usersWhoNeedRoleRevoked.forEach(user => user.roles.remove(announcementRole))
usersWhoNeedRole.forEach(user => user.roles.add(announcementRole))
}

View File

@ -22,7 +22,6 @@ export async function execute(messageReaction: MessageReaction, user: User) {
}
logger.info(`Got reaction on message`, { requestId, guildId })
//logger.debug(`reactedUponMessage payload: ${JSON.stringify(reactedUponMessage)}`)
logger.info(`emoji: ${messageReaction.emoji.toString()}`)
@ -39,7 +38,8 @@ export async function execute(messageReaction: MessageReaction, user: User) {
}
else if (isInitialAnnouncement(reactedUponMessage)) {
if (messageReaction.emoji.toString() === Emoji.ticket) {
logger.error(`Got a role emoji. Not implemented yet. ${reactedUponMessage.id}`)
logger.error(`Got a role emoji. ${reactedUponMessage.id}`)
return client.roleController.addMediaRoleToUser(user, messageReaction.message.guild, requestId)
}
return
}

View File

@ -0,0 +1,33 @@
import { Message, MessageReaction, User } from "discord.js";
import { logger, newRequestId, noGuildId } from "../logger";
import { Emoji } from "../constants";
import { client } from "../..";
import { isInitialAnnouncement } from "../helper/messageIdentifiers";
export const name = 'messageReactionRemove'
export async function execute(messageReaction: MessageReaction, user: User) {
if (user.id == client.user?.id) {
logger.info('Skipping bot reaction')
return
}
const requestId = newRequestId()
const guildId = messageReaction.message.inGuild() ? messageReaction.message.guildId : noGuildId
const reactedUponMessage: Message = messageReaction.message.partial ? await messageReaction.message.fetch() : messageReaction.message
if (!messageReaction.message.guild) {
logger.warn(`Received messageReactionRemove on non-guild message.`, { requestId })
return
}
logger.info(`Got reaction on message`, { requestId, guildId })
logger.info(`emoji: ${messageReaction.emoji.toString()}`)
if (isInitialAnnouncement(reactedUponMessage)) {
if (messageReaction.emoji.toString() === Emoji.ticket) {
logger.info(`User: ${user.id}, ${user.username} has removed a ticket reaction. Starting role management`, { requestId, guildId })
return client.roleController.removeMediaRoleFromUser(user, messageReaction.message.guild, requestId)
}
}
}

View File

@ -0,0 +1,83 @@
import { Guild, MessageReaction, Role, User } from "discord.js";
import { GuildMember } from "discord.js";
import { logger } from "../logger";
import { config } from "../configuration";
import { Maybe } from "../interfaces";
export default class RoleController {
constructor() { }
private getAnnounceRoleIdForGuild(guildId: string): string {
const role = config.bot.announcement_role
if (!role) throw new Error(`No announcementRole defined for guild ${guildId}`)
return role
}
public async addRoleToUser(member: GuildMember, role: Role, guildId: string, requestId: string) {
logger.info(`Adding Role ${role.id} to user ${member.id}|${member.user.username}`, { requestId, guildId })
return await member.roles.add(role)
}
private async removeRoleFromUser(member: GuildMember, role: Role, guildId: string, requestId: string) {
logger.info(`Removing Role ${role.id} from user ${member.id}|${member.user.username}`, { requestId, guildId })
return await member.roles.remove(role)
}
public async addMediaRoleToUser(user: User, guild: Guild, requestId: string) {
const roleToAdd = await this.getAnnouncementRoleForGuild(guild, requestId)
if (!roleToAdd) throw new Error(`No announcementRole found to add to user`)
const guildMember = await guild.members.fetch(user)
return this.addRoleToUser(guildMember, roleToAdd, guild.id, requestId)
}
public async removeMediaRoleFromUser(user: User, guild: Guild, requestId: string) {
const roleToRemove = await this.getAnnouncementRoleForGuild(guild, requestId)
if (!roleToRemove) throw new Error(`No announcementRole found to remove from user`)
const guildMember = await guild.members.fetch(user)
return this.removeRoleFromUser(guildMember, roleToRemove, guild.id, requestId)
}
public async getAnnouncementRoleForGuild(guild: Guild, requestId: string): Promise<Role> {
const mediaRole = this.getAnnounceRoleIdForGuild(guild.id)
const announcement_role = await guild.roles.fetch()
.then(fetchedRoles => fetchedRoles.find(role => role.id === mediaRole))
.catch(error => {
logger.error(`Could not find announcement_role with id ${config.bot.announcement_role}. Error: ${error}`, { requestId, guildId: guild.id })
throw error
})
if (!announcement_role) throw new Error(`Could not find announcement_role with id ${config.bot.announcement_role}.`)
return announcement_role
}
public async assignAnnouncementRolesFromReaction(guild: Guild, reaction: MessageReaction, requestId: string) {
const guildId = guild.id
logger.info("Managing roles", { guildId, requestId })
const announcementRole = await this.getAnnouncementRoleForGuild(guild, requestId)
const usersWhoWantRole: User[] = (await reaction.users.fetch()).filter(user => !user.bot).map(user => user)
const allUsers = await guild.members.fetch()
const usersWhoHaveRole: GuildMember[] = allUsers
.filter(member => member.roles.cache
.find(role => role.id === announcementRole.id) !== undefined)
.map(member => member)
const usersWhoNeedRoleRevoked: GuildMember[] = usersWhoHaveRole
.filter(userWhoHas => !usersWhoWantRole.map(wanter => wanter.id).includes(userWhoHas.id))
const usersWhoDontHaveRole: GuildMember[] = allUsers
.filter(member => member.roles.cache
.find(role => role.id === announcementRole.id) === undefined)
.map(member => member)
const usersWhoNeedRole: GuildMember[] = usersWhoDontHaveRole
.filter(userWhoNeeds => usersWhoWantRole.map(wanter => wanter.id).includes(userWhoNeeds.id))
logger.debug(`Theses users will get the role removed: ${JSON.stringify(usersWhoNeedRoleRevoked)}`, { guildId, requestId })
logger.debug(`Theses users will get the role added: ${JSON.stringify(usersWhoNeedRole)}`, { guildId, requestId })
usersWhoNeedRoleRevoked.forEach(user => this.removeRoleFromUser(user, announcementRole, guild.id, requestId))
usersWhoNeedRole.forEach(user => this.addRoleToUser(user, announcementRole, guild.id, requestId))
}
}

View File

@ -5,7 +5,7 @@ import { getMembersWithRoleFromGuild } from "./roleFilter"
import { config } from "../configuration"
import { VoteMessage, isVoteEndedMessage, isVoteMessage } from "./messageIdentifiers"
import { createDateStringFromEvent } from "./dateHelper"
import { Maybe, voteMessageInputInformation as prepareVoteMessageInput } from "../interfaces"
import { Maybe, prepareVoteMessageInput } from "../interfaces"
import format from "date-fns/format"
import toDate from "date-fns/toDate"
import differenceInDays from "date-fns/differenceInDays"

View File

@ -39,7 +39,7 @@ export interface JellyfinConfig {
collectionUser: string
}
export type PermissionLevel = "VIEWER" | "ADMIN" | "TEMPORARY"
export interface voteMessageInputInformation {
export interface prepareVoteMessageInput {
movies: string[],
startDate: Date,
event: GuildScheduledEvent,

View File

@ -2,7 +2,6 @@ import { ApplicationCommandDataResolvable, Client, ClientOptions, Collection, Gu
import fs from 'fs';
import { ScheduledTask, schedule } from "node-cron";
import { v4 as uuid } from 'uuid';
import { manageAnnouncementRoles } from "../commands/announce";
import { config } from "../configuration";
import { Maybe } from "../interfaces";
import { JellyfinHandler } from "../jellyfin/handler";
@ -11,6 +10,7 @@ import { CommandType } from "../types/commandTypes";
import { isInitialAnnouncement } from "../helper/messageIdentifiers";
import VoteController from "../helper/vote.controller";
import { yavinJellyfinHandler } from "../..";
import RoleController from "../helper/role.controller";
@ -19,6 +19,7 @@ export class ExtendedClient extends Client {
private commandFilePath = `${__dirname}/../commands`
private jellyfin: JellyfinHandler
public voteController: VoteController = new VoteController(this, yavinJellyfinHandler)
public roleController: RoleController = new RoleController()
public commands: Collection<string, CommandType> = new Collection()
private announcementChannels: Collection<string, TextChannel> = new Collection() //guildId to TextChannel
private announcementRoleHandlerTask: Collection<string, ScheduledTask> = new Collection() //one task per guild
@ -172,10 +173,10 @@ export class ExtendedClient extends Client {
}
//logger.debug(`Message: ${JSON.stringify(message, null, 2)}`, { guildId: guild.id, requestId })
const reactions = message.reactions.resolve("🎫")
const ticketReaction = message.reactions.resolve("🎫")
//logger.debug(`reactions: ${JSON.stringify(reactions, null, 2)}`, { guildId: guild.id, requestId })
if (reactions) {
manageAnnouncementRoles(message.guild, reactions, requestId)
if (ticketReaction) {
this.roleController.assignAnnouncementRolesFromReaction(message.guild, ticketReaction, requestId)
} else {
logger.error("Did not get reactions! Aborting!", { guildId: guild.id, requestId })
}