12 Commits

Author SHA1 Message Date
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
6 changed files with 119 additions and 41 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.info(`Got reaction on message`, { requestId, guildId })
//logger.debug(`reactedUponMessage payload: ${JSON.stringify(reactedUponMessage)}`)
logger.info(`emoji: ${messageReaction.emoji.toString()}`) logger.info(`emoji: ${messageReaction.emoji.toString()}`)
@ -39,7 +38,8 @@ export async function execute(messageReaction: MessageReaction, user: User) {
} }
else if (isInitialAnnouncement(reactedUponMessage)) { else if (isInitialAnnouncement(reactedUponMessage)) {
if (messageReaction.emoji.toString() === Emoji.ticket) { 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 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,80 @@
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<Maybe<Role>> {
const mediaRole = this.getAnnounceRoleIdForGuild(guild.id)
return 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 }) })
}
public async assignAnnouncementRolesFromReactions(guild: Guild, reaction: MessageReaction, requestId: string) {
const guildId = guild.id
logger.info("Managing roles", { guildId, requestId })
const announcementRole = await this.getAnnouncementRoleForGuild(guild, requestId)
if (!announcementRole)
throw new Error(`No announcementRole found in guild ${guildId}`)
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

@ -1,7 +1,7 @@
import { Collection } from "@discordjs/collection" import { Collection } from "@discordjs/collection"
import { GuildScheduledEvent, Role, TextChannel } from "discord.js" import { GuildScheduledEvent, Role, TextChannel } from "discord.js"
export type Maybe<T> = T | undefined | null export type Maybe<T> = T | undefined | null | void
export interface Player { export interface Player {
name: string name: string
} }

View File

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