Compare commits
2 Commits
a2c55ad676
...
e774474a55
Author | SHA1 | Date | |
---|---|---|---|
e774474a55 | |||
24754decf4 |
@ -1,11 +1,14 @@
|
|||||||
import { Guild, GuildMember, GuildScheduledEvent, GuildScheduledEventEditOptions, GuildScheduledEventSetStatusArg, GuildScheduledEventStatus, Message, MessageCreateOptions, MessageEditOptions, TextChannel, messageLink } from 'discord.js'
|
import { Guild, GuildMember, Message, MessageCreateOptions, MessageReaction, Role, TextChannel, User } from 'discord.js'
|
||||||
import { v4 as uuid } from 'uuid'
|
import { v4 as uuid } from 'uuid'
|
||||||
|
import { client } from '../..'
|
||||||
import { config } from '../configuration'
|
import { config } from '../configuration'
|
||||||
import { Emotes } from '../events/guildScheduledEventCreate'
|
|
||||||
import { logger } from '../logger'
|
import { logger } from '../logger'
|
||||||
import { Command } from '../structures/command'
|
import { Command } from '../structures/command'
|
||||||
import { RunOptions } from '../types/commandTypes'
|
import { RunOptions } from '../types/commandTypes'
|
||||||
import { client } from '../..'
|
import { off } from 'process'
|
||||||
|
import { ScheduledTask, schedule } from 'node-cron'
|
||||||
|
|
||||||
|
let task: ScheduledTask
|
||||||
|
|
||||||
export default new Command({
|
export default new Command({
|
||||||
name: 'announce',
|
name: 'announce',
|
||||||
@ -29,14 +32,18 @@ export default new Command({
|
|||||||
})
|
})
|
||||||
|
|
||||||
function isAdmin(member: GuildMember): boolean {
|
function isAdmin(member: GuildMember): boolean {
|
||||||
return member.roles.cache.find((role, _) => role.id === config.bot.jf_admin_role) != undefined
|
return member.roles.cache.find((role, _) => role.id === config.bot.jf_admin_role) !== undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
async function sendAnnouncement(guildId: string, requestId: string): Promise<void> {
|
async function sendAnnouncement(guildId: string, requestId: string): Promise<void> {
|
||||||
logger.info("Sending announcement")
|
logger.info("Sending announcement")
|
||||||
const announcementChannel: TextChannel = client.getAnnouncementChannelForGuild(guildId)
|
const announcementChannel: TextChannel = client.getAnnouncementChannelForGuild(guildId)
|
||||||
|
|
||||||
const body = `Hey! @everyone! Hier ist der Watchparty Bot vom Hartzarett.
|
const currentPinnedAnnouncementMessages = (await announcementChannel.messages.fetchPinned()).filter(message => message.cleanContent.includes("[announcement]"))
|
||||||
|
currentPinnedAnnouncementMessages.forEach(async (message) => await message.unpin())
|
||||||
|
currentPinnedAnnouncementMessages.forEach(message => message.delete())
|
||||||
|
|
||||||
|
const body = `[announcement] Hey! @everyone! Hier ist der Watchparty Bot vom Hartzarett.
|
||||||
|
|
||||||
Wir machen in Zukunft regelmäßig Watchparties! Falls du mitmachen möchtest, reagiere einfach auf diesen Post mit 🎫, dann bekommst du automatisch eine Rolle zugewiesen und wirst benachrichtigt sobald es in der Zukunft weitere Watchparties und Filme zum abstimmen gibt.
|
Wir machen in Zukunft regelmäßig Watchparties! Falls du mitmachen möchtest, reagiere einfach auf diesen Post mit 🎫, dann bekommst du automatisch eine Rolle zugewiesen und wirst benachrichtigt sobald es in der Zukunft weitere Watchparties und Filme zum abstimmen gibt.
|
||||||
|
|
||||||
@ -47,5 +54,46 @@ Für eine Erklärung wie das alles funktioniert mach einfach /mitgucken für ein
|
|||||||
content: body
|
content: body
|
||||||
}
|
}
|
||||||
const message: Message<true> = await announcementChannel.send(options)
|
const message: Message<true> = await announcementChannel.send(options)
|
||||||
message.react("🎫")
|
await message.react("🎫")
|
||||||
}
|
await message.pin()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ export interface Config {
|
|||||||
workaround_token: string
|
workaround_token: string
|
||||||
watcher_role: string
|
watcher_role: string
|
||||||
jf_admin_role: string
|
jf_admin_role: string
|
||||||
|
announcement_role: string
|
||||||
announcement_channel_id: string
|
announcement_channel_id: string
|
||||||
jf_collection_id: string
|
jf_collection_id: string
|
||||||
}
|
}
|
||||||
@ -57,6 +58,7 @@ export const config: Config = {
|
|||||||
workaround_token: process.env.TOKEN ?? "",
|
workaround_token: process.env.TOKEN ?? "",
|
||||||
watcher_role: process.env.WATCHER_ROLE ?? "",
|
watcher_role: process.env.WATCHER_ROLE ?? "",
|
||||||
jf_admin_role: process.env.ADMIN_ROLE ?? "",
|
jf_admin_role: process.env.ADMIN_ROLE ?? "",
|
||||||
|
announcement_role: process.env.WATCHPARTY_ANNOUNCEMENT_ROLE ?? "",
|
||||||
announcement_channel_id: process.env.CHANNEL_ID ?? "",
|
announcement_channel_id: process.env.CHANNEL_ID ?? "",
|
||||||
jf_collection_id: process.env.JELLYFIN_COLLECTION_ID ?? ""
|
jf_collection_id: process.env.JELLYFIN_COLLECTION_ID ?? ""
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,10 @@ import fs from 'fs'
|
|||||||
import { config } from "../configuration";
|
import { config } from "../configuration";
|
||||||
import { logger } from "../logger";
|
import { logger } from "../logger";
|
||||||
import { JellyfinHandler } from "../jellyfin/handler";
|
import { JellyfinHandler } from "../jellyfin/handler";
|
||||||
|
import { ScheduledTask, schedule } from "node-cron";
|
||||||
|
import { manageAnnouncementRoles } from "../commands/announce";
|
||||||
|
import { v4 as uuid } from 'uuid'
|
||||||
|
import { task } from "../events/guildScheduledEventCreate";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -13,6 +17,7 @@ export class ExtendedClient extends Client {
|
|||||||
private jellyfin: JellyfinHandler
|
private jellyfin: JellyfinHandler
|
||||||
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
|
||||||
public constructor(jf: JellyfinHandler) {
|
public constructor(jf: JellyfinHandler) {
|
||||||
const intents: IntentsBitField = new IntentsBitField()
|
const intents: IntentsBitField = new IntentsBitField()
|
||||||
intents.add(IntentsBitField.Flags.GuildMembers, IntentsBitField.Flags.MessageContent, IntentsBitField.Flags.Guilds, IntentsBitField.Flags.DirectMessages, IntentsBitField.Flags.GuildScheduledEvents, IntentsBitField.Flags.GuildVoiceStates)
|
intents.add(IntentsBitField.Flags.GuildMembers, IntentsBitField.Flags.MessageContent, IntentsBitField.Flags.Guilds, IntentsBitField.Flags.DirectMessages, IntentsBitField.Flags.GuildScheduledEvents, IntentsBitField.Flags.GuildVoiceStates)
|
||||||
@ -60,14 +65,15 @@ export class ExtendedClient extends Client {
|
|||||||
this.commands.set(command.name, command)
|
this.commands.set(command.name, command)
|
||||||
slashCommands.push(command)
|
slashCommands.push(command)
|
||||||
}
|
}
|
||||||
this.on("ready", (client: Client) => {
|
this.on("ready", async (client: Client) => {
|
||||||
//logger.info(`Ready processing ${JSON.stringify(client)}`)
|
//logger.info(`Ready processing ${JSON.stringify(client)}`)
|
||||||
logger.info(`SlashCommands: ${JSON.stringify(slashCommands)}`)
|
logger.info(`SlashCommands: ${JSON.stringify(slashCommands)}`)
|
||||||
const guilds = client.guilds.cache
|
const guilds = client.guilds.cache
|
||||||
|
|
||||||
this.registerCommands(slashCommands, guilds)
|
this.registerCommands(slashCommands, guilds)
|
||||||
this.cacheUsers(guilds)
|
this.cacheUsers(guilds)
|
||||||
this.cacheAnnouncementServer(guilds)
|
await this.cacheAnnouncementServer(guilds)
|
||||||
|
this.startAnnouncementRoleBackgroundTask(guilds)
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.info(`Error refreshing slash commands: ${error}`)
|
logger.info(`Error refreshing slash commands: ${error}`)
|
||||||
@ -117,4 +123,39 @@ export class ExtendedClient extends Client {
|
|||||||
logger.error(error)
|
logger.error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async startAnnouncementRoleBackgroundTask(guilds: Collection<string, Guild>) {
|
||||||
|
for (const guild of guilds.values()) {
|
||||||
|
logger.info("Starting background task for announcement role", { guildId: guild.id })
|
||||||
|
const textChannel: TextChannel = this.getAnnouncementChannelForGuild(guild.id)
|
||||||
|
this.announcementRoleHandlerTask.set(guild.id, schedule("*/10 * * * * *", async () => {
|
||||||
|
const requestId = uuid()
|
||||||
|
const messages = (await textChannel.messages.fetchPinned()).filter(message => message.cleanContent.includes("[announcement]"))
|
||||||
|
|
||||||
|
if (messages.size > 1) {
|
||||||
|
logger.error("More than one pinned announcement Messages found. Unable to know which one people react to. Please fix!", { guildId: guild.id, requestId })
|
||||||
|
} else if (messages.size == 0) {
|
||||||
|
logger.error("Could not find any pinned announcement messages. Unable to manage roles!", { guildId: guild.id, requestId })
|
||||||
|
}
|
||||||
|
|
||||||
|
const message = messages.at(0)!
|
||||||
|
|
||||||
|
const reactions = await message.reactions.resolve("🎫")
|
||||||
|
if (reactions) {
|
||||||
|
manageAnnouncementRoles(message.guild, reactions, requestId)
|
||||||
|
} else {
|
||||||
|
logger.error("Did not get reactions! Aborting!", { guildId: guild.id, requestId })
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public stopAnnouncementRoleBackgroundTask(guild: string | Guild, requestId: string) {
|
||||||
|
const guildId: string = guild instanceof Guild ? guild.id : guild
|
||||||
|
const task: ScheduledTask | undefined = guild instanceof Guild ? this.announcementRoleHandlerTask.get(guild.id) : this.announcementRoleHandlerTask.get(guild)
|
||||||
|
if (!task) {
|
||||||
|
logger.error(`No task found for guildID ${guildId}.`, { guildId, requestId })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
task.stop()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user