format more files
All checks were successful
Compile the repository / compile (pull_request) Successful in 1m12s
All checks were successful
Compile the repository / compile (pull_request) Successful in 1m12s
This commit is contained in:
@ -13,169 +13,169 @@ import { checkForPollsToClose } from "../commands/closepoll";
|
||||
|
||||
|
||||
export class ExtendedClient extends Client {
|
||||
private eventFilePath = `${__dirname}/../events`
|
||||
private commandFilePath = `${__dirname}/../commands`
|
||||
private jellyfin: JellyfinHandler
|
||||
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
|
||||
private pollCloseBackgroundTasks: Collection<string, ScheduledTask> = new Collection()
|
||||
public constructor(jf: JellyfinHandler) {
|
||||
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)
|
||||
const options: ClientOptions = { intents }
|
||||
super(options)
|
||||
this.jellyfin = jf
|
||||
}
|
||||
public async start() {
|
||||
if (process.env.NODE_ENV === 'test') return
|
||||
const promises: Promise<any>[] = []
|
||||
promises.push(this.registerSlashCommands())
|
||||
promises.push(this.registerEventCallback())
|
||||
Promise.all(promises).then(() => {
|
||||
this.login(config.bot.token)
|
||||
})
|
||||
}
|
||||
private async importFile(filepath: string): Promise<any> {
|
||||
logger.debug(`Importing ${filepath}`)
|
||||
const imported = await import(filepath)
|
||||
logger.debug(`Imported ${JSON.stringify(imported)}`)
|
||||
return imported.default ?? imported
|
||||
}
|
||||
public async registerCommands(cmds: ApplicationCommandDataResolvable[], guildIds: Collection<Snowflake, Guild>) {
|
||||
if (guildIds) {
|
||||
guildIds.forEach(guild => {
|
||||
this.guilds.cache.get(guild.id)?.commands.set(cmds)
|
||||
logger.info(`Registering commands to ${guild.name}|${guild.id}`)
|
||||
})
|
||||
} else {
|
||||
this.application?.commands.set(cmds)
|
||||
logger.info(`Registering global commands`)
|
||||
}
|
||||
return
|
||||
}
|
||||
public async registerSlashCommands(): Promise<void> {
|
||||
try {
|
||||
const slashCommands: ApplicationCommandDataResolvable[] = []
|
||||
const commandFiles = fs.readdirSync(this.commandFilePath).filter(file => file.endsWith('.ts') || file.endsWith('.js'))
|
||||
for (const commandFile of commandFiles) {
|
||||
const filePath = `${this.commandFilePath}/${commandFile}`
|
||||
const command = await this.importFile(filePath)
|
||||
logger.debug(JSON.stringify(command))
|
||||
if (!command.name) return
|
||||
this.commands.set(command.name, command)
|
||||
slashCommands.push(command)
|
||||
}
|
||||
this.on("ready", async (client: Client) => {
|
||||
//logger.info(`Ready processing ${JSON.stringify(client)}`)
|
||||
logger.info(`SlashCommands: ${JSON.stringify(slashCommands)}`)
|
||||
const guilds = client.guilds.cache
|
||||
private eventFilePath = `${__dirname}/../events`
|
||||
private commandFilePath = `${__dirname}/../commands`
|
||||
private jellyfin: JellyfinHandler
|
||||
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
|
||||
private pollCloseBackgroundTasks: Collection<string, ScheduledTask> = new Collection()
|
||||
public constructor(jf: JellyfinHandler) {
|
||||
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)
|
||||
const options: ClientOptions = { intents }
|
||||
super(options)
|
||||
this.jellyfin = jf
|
||||
}
|
||||
public async start() {
|
||||
if (process.env.NODE_ENV === 'test') return
|
||||
const promises: Promise<any>[] = []
|
||||
promises.push(this.registerSlashCommands())
|
||||
promises.push(this.registerEventCallback())
|
||||
Promise.all(promises).then(() => {
|
||||
this.login(config.bot.token)
|
||||
})
|
||||
}
|
||||
private async importFile(filepath: string): Promise<any> {
|
||||
logger.debug(`Importing ${filepath}`)
|
||||
const imported = await import(filepath)
|
||||
logger.debug(`Imported ${JSON.stringify(imported)}`)
|
||||
return imported.default ?? imported
|
||||
}
|
||||
public async registerCommands(cmds: ApplicationCommandDataResolvable[], guildIds: Collection<Snowflake, Guild>) {
|
||||
if (guildIds) {
|
||||
guildIds.forEach(guild => {
|
||||
this.guilds.cache.get(guild.id)?.commands.set(cmds)
|
||||
logger.info(`Registering commands to ${guild.name}|${guild.id}`)
|
||||
})
|
||||
} else {
|
||||
this.application?.commands.set(cmds)
|
||||
logger.info(`Registering global commands`)
|
||||
}
|
||||
return
|
||||
}
|
||||
public async registerSlashCommands(): Promise<void> {
|
||||
try {
|
||||
const slashCommands: ApplicationCommandDataResolvable[] = []
|
||||
const commandFiles = fs.readdirSync(this.commandFilePath).filter(file => file.endsWith('.ts') || file.endsWith('.js'))
|
||||
for (const commandFile of commandFiles) {
|
||||
const filePath = `${this.commandFilePath}/${commandFile}`
|
||||
const command = await this.importFile(filePath)
|
||||
logger.debug(JSON.stringify(command))
|
||||
if (!command.name) return
|
||||
this.commands.set(command.name, command)
|
||||
slashCommands.push(command)
|
||||
}
|
||||
this.on("ready", async (client: Client) => {
|
||||
//logger.info(`Ready processing ${JSON.stringify(client)}`)
|
||||
logger.info(`SlashCommands: ${JSON.stringify(slashCommands)}`)
|
||||
const guilds = client.guilds.cache
|
||||
|
||||
this.registerCommands(slashCommands, guilds)
|
||||
this.cacheUsers(guilds)
|
||||
await this.cacheAnnouncementServer(guilds)
|
||||
this.startAnnouncementRoleBackgroundTask(guilds)
|
||||
this.startPollCloseBackgroundTasks()
|
||||
})
|
||||
} catch (error) {
|
||||
logger.info(`Error refreshing slash commands: ${error}`)
|
||||
}
|
||||
}
|
||||
private async cacheAnnouncementServer(guilds: Collection<Snowflake, Guild>) {
|
||||
for (const guild of guilds.values()) {
|
||||
const channels: TextChannel[] = <TextChannel[]>(await guild.channels.fetch())
|
||||
?.filter(channel => channel?.id === config.bot.announcement_channel_id)
|
||||
.map((value) => value)
|
||||
this.registerCommands(slashCommands, guilds)
|
||||
this.cacheUsers(guilds)
|
||||
await this.cacheAnnouncementServer(guilds)
|
||||
this.startAnnouncementRoleBackgroundTask(guilds)
|
||||
this.startPollCloseBackgroundTasks()
|
||||
})
|
||||
} catch (error) {
|
||||
logger.info(`Error refreshing slash commands: ${error}`)
|
||||
}
|
||||
}
|
||||
private async cacheAnnouncementServer(guilds: Collection<Snowflake, Guild>) {
|
||||
for (const guild of guilds.values()) {
|
||||
const channels: TextChannel[] = <TextChannel[]>(await guild.channels.fetch())
|
||||
?.filter(channel => channel?.id === config.bot.announcement_channel_id)
|
||||
.map((value) => value)
|
||||
|
||||
if (!channels || channels.length != 1) {
|
||||
logger.error(`Could not find announcement channel for guild ${guild.name} with guildId ${guild.id}. Found ${channels}`)
|
||||
continue
|
||||
}
|
||||
logger.info(`Fetched announcement channel: ${JSON.stringify(channels[0])}`)
|
||||
this.announcementChannels.set(guild.id, channels[0])
|
||||
}
|
||||
}
|
||||
public getAnnouncementChannelForGuild(guildId: string): Maybe<TextChannel> {
|
||||
return this.announcementChannels.get(guildId)
|
||||
}
|
||||
public async cacheUsers(guilds: Collection<Snowflake, Guild>) {
|
||||
guilds.forEach((guild: Guild, id: Snowflake) => {
|
||||
logger.info(`Fetching members for ${guild.name}|${id}`)
|
||||
guild.members.fetch()
|
||||
logger.info(`Fetched: ${guild.memberCount} members`)
|
||||
})
|
||||
}
|
||||
public async registerEventCallback() {
|
||||
try {
|
||||
const eventFiles = fs.readdirSync(this.eventFilePath).filter(file => file.endsWith('.ts') || file.endsWith('.js'));
|
||||
for (const file of eventFiles) {
|
||||
const filePath = `${this.eventFilePath}/${file}`
|
||||
const event = await this.importFile(filePath)
|
||||
if (event.once) {
|
||||
logger.info(`Registering once ${file}`)
|
||||
this.once(event.name, (...args: any[]) => event.execute(...args))
|
||||
}
|
||||
else {
|
||||
logger.info(`Registering on ${file}`)
|
||||
this.on(event.name, (...args: any[]) => event.execute(...args))
|
||||
}
|
||||
}
|
||||
logger.info(`Registered event names ${this.eventNames()}`)
|
||||
} catch (error) {
|
||||
logger.error(error)
|
||||
}
|
||||
}
|
||||
if (!channels || channels.length != 1) {
|
||||
logger.error(`Could not find announcement channel for guild ${guild.name} with guildId ${guild.id}. Found ${channels}`)
|
||||
continue
|
||||
}
|
||||
logger.info(`Fetched announcement channel: ${JSON.stringify(channels[0])}`)
|
||||
this.announcementChannels.set(guild.id, channels[0])
|
||||
}
|
||||
}
|
||||
public getAnnouncementChannelForGuild(guildId: string): Maybe<TextChannel> {
|
||||
return this.announcementChannels.get(guildId)
|
||||
}
|
||||
public async cacheUsers(guilds: Collection<Snowflake, Guild>) {
|
||||
guilds.forEach((guild: Guild, id: Snowflake) => {
|
||||
logger.info(`Fetching members for ${guild.name}|${id}`)
|
||||
guild.members.fetch()
|
||||
logger.info(`Fetched: ${guild.memberCount} members`)
|
||||
})
|
||||
}
|
||||
public async registerEventCallback() {
|
||||
try {
|
||||
const eventFiles = fs.readdirSync(this.eventFilePath).filter(file => file.endsWith('.ts') || file.endsWith('.js'));
|
||||
for (const file of eventFiles) {
|
||||
const filePath = `${this.eventFilePath}/${file}`
|
||||
const event = await this.importFile(filePath)
|
||||
if (event.once) {
|
||||
logger.info(`Registering once ${file}`)
|
||||
this.once(event.name, (...args: any[]) => event.execute(...args))
|
||||
}
|
||||
else {
|
||||
logger.info(`Registering on ${file}`)
|
||||
this.on(event.name, (...args: any[]) => event.execute(...args))
|
||||
}
|
||||
}
|
||||
logger.info(`Registered event names ${this.eventNames()}`)
|
||||
} catch (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: Maybe<TextChannel> = this.getAnnouncementChannelForGuild(guild.id)
|
||||
if (!textChannel) {
|
||||
logger.error("Could not find announcement channel. Aborting", { guildId: guild.id })
|
||||
return
|
||||
}
|
||||
this.announcementRoleHandlerTask.set(guild.id, schedule("*/10 * * * * *", async () => {
|
||||
const requestId = uuid()
|
||||
const messages = (await textChannel.messages.fetchPinned()).filter(message => message.cleanContent.includes("[initial]"))
|
||||
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: Maybe<TextChannel> = this.getAnnouncementChannelForGuild(guild.id)
|
||||
if (!textChannel) {
|
||||
logger.error("Could not find announcement channel. Aborting", { guildId: guild.id })
|
||||
return
|
||||
}
|
||||
this.announcementRoleHandlerTask.set(guild.id, schedule("*/10 * * * * *", async () => {
|
||||
const requestId = uuid()
|
||||
const messages = (await textChannel.messages.fetchPinned()).filter(message => message.cleanContent.includes("[initial]"))
|
||||
|
||||
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 })
|
||||
return
|
||||
} else if (messages.size == 0) {
|
||||
logger.error("Could not find any pinned announcement messages. Unable to manage roles!", { guildId: guild.id, requestId })
|
||||
return
|
||||
}
|
||||
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 })
|
||||
return
|
||||
} else if (messages.size == 0) {
|
||||
logger.error("Could not find any pinned announcement messages. Unable to manage roles!", { guildId: guild.id, requestId })
|
||||
return
|
||||
}
|
||||
|
||||
const message = await messages.at(0)?.fetch()
|
||||
if (!message) {
|
||||
logger.error(`No pinned message found`, { guildId: guild.id, requestId })
|
||||
return
|
||||
}
|
||||
//logger.debug(`Message: ${JSON.stringify(message, null, 2)}`, { guildId: guild.id, requestId })
|
||||
const message = await messages.at(0)?.fetch()
|
||||
if (!message) {
|
||||
logger.error(`No pinned message found`, { guildId: guild.id, requestId })
|
||||
return
|
||||
}
|
||||
//logger.debug(`Message: ${JSON.stringify(message, null, 2)}`, { guildId: guild.id, requestId })
|
||||
|
||||
const reactions = message.reactions.resolve("🎫")
|
||||
//logger.debug(`reactions: ${JSON.stringify(reactions, null, 2)}`, { guildId: guild.id, requestId })
|
||||
if (reactions) {
|
||||
manageAnnouncementRoles(message.guild, reactions, requestId)
|
||||
} else {
|
||||
logger.error("Did not get reactions! Aborting!", { guildId: guild.id, requestId })
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
const reactions = message.reactions.resolve("🎫")
|
||||
//logger.debug(`reactions: ${JSON.stringify(reactions, null, 2)}`, { guildId: guild.id, requestId })
|
||||
if (reactions) {
|
||||
manageAnnouncementRoles(message.guild, reactions, requestId)
|
||||
} else {
|
||||
logger.error("Did not get reactions! Aborting!", { guildId: guild.id, requestId })
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
public stopAnnouncementRoleBackgroundTask(guildId: string, requestId: string) {
|
||||
const task: Maybe<ScheduledTask> = this.announcementRoleHandlerTask.get(guildId)
|
||||
if (!task) {
|
||||
logger.error(`No task found for guildID ${guildId}.`, { guildId, requestId })
|
||||
return
|
||||
}
|
||||
task.stop()
|
||||
}
|
||||
public stopAnnouncementRoleBackgroundTask(guildId: string, requestId: string) {
|
||||
const task: Maybe<ScheduledTask> = this.announcementRoleHandlerTask.get(guildId)
|
||||
if (!task) {
|
||||
logger.error(`No task found for guildID ${guildId}.`, { guildId, requestId })
|
||||
return
|
||||
}
|
||||
task.stop()
|
||||
}
|
||||
|
||||
private async startPollCloseBackgroundTasks() {
|
||||
for (const guild of this.guilds.cache) {
|
||||
this.pollCloseBackgroundTasks.set(guild[1].id, schedule("0 * * * * *", () => checkForPollsToClose(guild[1])))
|
||||
}
|
||||
}
|
||||
private async startPollCloseBackgroundTasks() {
|
||||
for (const guild of this.guilds.cache) {
|
||||
this.pollCloseBackgroundTasks.set(guild[1].id, schedule("0 * * * * *", () => checkForPollsToClose(guild[1])))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { CommandType } from "../types/commandTypes";
|
||||
|
||||
export class Command {
|
||||
constructor(commandOptions: CommandType) {
|
||||
Object.assign(this, commandOptions)
|
||||
}
|
||||
constructor(commandOptions: CommandType) {
|
||||
Object.assign(this, commandOptions)
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { ClientEvents } from "discord.js";
|
||||
|
||||
export class Event<Key extends keyof ClientEvents>{
|
||||
constructor(
|
||||
public event: Key,
|
||||
public run: (...args: ClientEvents[Key]) => unknown
|
||||
) { }
|
||||
constructor(
|
||||
public event: Key,
|
||||
public run: (...args: ClientEvents[Key]) => unknown
|
||||
) { }
|
||||
}
|
||||
|
Reference in New Issue
Block a user