From 3f764b4a5ffc1b998a6609c1af9c9ae3a03181fa Mon Sep 17 00:00:00 2001 From: chandler05 Date: Fri, 4 Dec 2020 15:25:29 -0600 Subject: [PATCH 01/28] add bulk emoji --- config/default.yml | 1 + config/template.yml | 3 +++ src/BotConfig.ts | 2 ++ 3 files changed, 6 insertions(+) diff --git a/config/default.yml b/config/default.yml index 6e0662b6..90c62e60 100644 --- a/config/default.yml +++ b/config/default.yml @@ -35,6 +35,7 @@ request: ignorePrependResponseMessageEmoji: ✅ ignoreResolutionEmoji: 💬 + bulkEmoji: 📁 resolveDelay: 10000 prependResponseMessage: whenResolved diff --git a/config/template.yml b/config/template.yml index c4740d75..cff7994f 100644 --- a/config/template.yml +++ b/config/template.yml @@ -84,6 +84,9 @@ request: # An emoji or emoji ID which, when used, doesn't trigger the response template message. ignorePrependResponseMessageEmoji: + # An emoji or emoji ID which indicates a request message to be added to a bulk action. + bulkEmoji: + # The amount of time in milliseconds between a volunteer reacts to the message and the bot deletes its message. resolveDelay: diff --git a/src/BotConfig.ts b/src/BotConfig.ts index 00cb6970..b4c337e0 100644 --- a/src/BotConfig.ts +++ b/src/BotConfig.ts @@ -25,6 +25,7 @@ export class RequestConfig { public suggestedEmoji: string[]; public ignorePrependResponseMessageEmoji: string; public ignoreResolutionEmoji: string; + public bulkEmoji: string; public resolveDelay: number; public prependResponseMessage: PrependResponseMessageType; public prependResponseMessageInLog: boolean; @@ -45,6 +46,7 @@ export class RequestConfig { this.suggestedEmoji = getOrDefault( 'request.suggestedEmoji', [] ); this.ignorePrependResponseMessageEmoji = config.get( 'request.ignorePrependResponseMessageEmoji' ); this.ignoreResolutionEmoji = config.get( 'request.ignoreResolutionEmoji' ); + this.bulkEmoji = config.get( 'request.bulkEmoji' ); this.resolveDelay = config.get( 'request.resolveDelay' ); this.prependResponseMessage = getOrDefault( 'request.prependResponseMessage', PrependResponseMessageType.Never ); From a0ae9b7dde8ee3dfec9520c8f94b30b1f546103b Mon Sep 17 00:00:00 2001 From: chandler05 <66492208+chandler05@users.noreply.github.com> Date: Fri, 4 Dec 2020 16:34:28 -0600 Subject: [PATCH 02/28] Add bulk command --- config/default.yml | 1 + src/commands/BulkCommand.ts | 82 +++++++++++++++++++++++++++++++++ src/commands/CommandRegistry.ts | 2 + 3 files changed, 85 insertions(+) create mode 100644 src/commands/BulkCommand.ts diff --git a/config/default.yml b/config/default.yml index 90c62e60..9c5a7956 100644 --- a/config/default.yml +++ b/config/default.yml @@ -32,6 +32,7 @@ request: - ☑️ - ❌ - 💬 + - 📁 ignorePrependResponseMessageEmoji: ✅ ignoreResolutionEmoji: 💬 diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts new file mode 100644 index 00000000..e54d0e97 --- /dev/null +++ b/src/commands/BulkCommand.ts @@ -0,0 +1,82 @@ +import { Message, TextChannel } from 'discord.js'; +import PrefixCommand from './PrefixCommand'; +import MentionCommand from './MentionCommand'; +import Command from './Command'; +import DiscordUtil from '../util/DiscordUtil'; +import BotConfig from '../BotConfig'; + +export default class BulkCommand extends PrefixCommand { + public readonly aliases = ['bulk', 'filter']; + + public async run( message: Message, args: string ): Promise { + if ( args.length ) { + return false; + } + + //get messages with bulk reaction from user + let bulkMessages: Set; + + for ( let i = 0; i < BotConfig.request.internalChannels.length; i++ ) { + const internalChannelId = BotConfig.request.internalChannels[i]; + try { + const internalChannel = await DiscordUtil.getChannel( internalChannelId ); + if ( internalChannel instanceof TextChannel ) { + const messages = internalChannel.messages; + for (const message of messages) { + const reaction = message.reactions.cache.get( BotConfig.request.bulkEmoji ); + if ( reaction.users.cache.get( message.author ) ) { + bulkMessages.add( message ); + } + } + } + } catch ( err ) { + Command.logger.error( err ); + return false; + } + } + + const bulkMessageArray = Array.from( bulkMessages ); + + //get tickets and create filter + let firstMentioned: string; + let ticketKeys: string[]; + + try { + for ( let j = 0; j < bulkMessageArray.length; j++ ) { + const message = bulkMessageArray[j]; + const ticket = Array.from( this.getTickets( message.toString() ) ); + if ( firstMentioned == null ) { + firstMentioned = ticket[1]; + } + ticket.forEach( key => ticketKeys.push( key ) ); + const reaction = message.reactions.cache.get( BotConfig.request.bulkEmoji ); + await reaction.users.remove( message.author ); + } + } catch ( err ) { + Command.logger.error( err ); + return false; + } + const filter = `https://bugs.mojang.com/browse/${ firstMentioned }?jql=key%20in(${ ticketKeys.join( '%2C' ) })` + try { + await message.channel.send( `${ message.author.toString() } ${ filter }` ); + } catch { + return false; + } + + return true; + } + + private getTickets( content: string ): Set { + let ticketMatch: RegExpExecArray; + const regex = MentionCommand.getTicketIdRegex(); + const ticketMatches: Set = new Set(); + while ( ( ticketMatch = regex.exec( content ) ) !== null ) { + ticketMatches.add( ticketMatch[1] ); + } + return ticketMatches; + } + + public asString(): string { + return '!jira bulk'; + } +} diff --git a/src/commands/CommandRegistry.ts b/src/commands/CommandRegistry.ts index 1384a371..add19be1 100644 --- a/src/commands/CommandRegistry.ts +++ b/src/commands/CommandRegistry.ts @@ -1,4 +1,5 @@ import BugCommand from './BugCommand'; +import BulkCommand from './BulkCommand'; import HelpCommand from './HelpCommand'; import PingCommand from './PingCommand'; import MooCommand from './MooCommand'; @@ -9,6 +10,7 @@ import ShutdownCommand from './ShutdownCommand'; export default class CommandRegistry { public static BUG_COMMAND = new BugCommand(); + public static BULK_COMMAND = new BulkCommand(); public static HELP_COMMAND = new HelpCommand(); public static MENTION_COMMAND = new MentionCommand(); public static MOO_COMMAND = new MooCommand(); From 544d4a8d14e074f54f3cc0a3e537ea2fb2567954 Mon Sep 17 00:00:00 2001 From: chandler05 <66492208+chandler05@users.noreply.github.com> Date: Fri, 4 Dec 2020 16:39:26 -0600 Subject: [PATCH 03/28] Formatting and messages --- src/commands/BulkCommand.ts | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts index e54d0e97..b8e6e7a2 100644 --- a/src/commands/BulkCommand.ts +++ b/src/commands/BulkCommand.ts @@ -13,7 +13,6 @@ export default class BulkCommand extends PrefixCommand { return false; } - //get messages with bulk reaction from user let bulkMessages: Set; for ( let i = 0; i < BotConfig.request.internalChannels.length; i++ ) { @@ -21,11 +20,11 @@ export default class BulkCommand extends PrefixCommand { try { const internalChannel = await DiscordUtil.getChannel( internalChannelId ); if ( internalChannel instanceof TextChannel ) { - const messages = internalChannel.messages; - for (const message of messages) { - const reaction = message.reactions.cache.get( BotConfig.request.bulkEmoji ); + const channelMessages = internalChannel.messages; + for ( const channelMessage of channelMessages ) { + const reaction = channelMessage.reactions.cache.get( BotConfig.request.bulkEmoji ); if ( reaction.users.cache.get( message.author ) ) { - bulkMessages.add( message ); + bulkMessages.add( channelMessage ); } } } @@ -37,19 +36,18 @@ export default class BulkCommand extends PrefixCommand { const bulkMessageArray = Array.from( bulkMessages ); - //get tickets and create filter let firstMentioned: string; let ticketKeys: string[]; try { for ( let j = 0; j < bulkMessageArray.length; j++ ) { - const message = bulkMessageArray[j]; - const ticket = Array.from( this.getTickets( message.toString() ) ); + const bulkMessage = bulkMessageArray[j]; + const ticket = Array.from( this.getTickets( bulkMessage.toString() ) ); if ( firstMentioned == null ) { firstMentioned = ticket[1]; } ticket.forEach( key => ticketKeys.push( key ) ); - const reaction = message.reactions.cache.get( BotConfig.request.bulkEmoji ); + const reaction = bulkMessage.reactions.cache.get( BotConfig.request.bulkEmoji ); await reaction.users.remove( message.author ); } } catch ( err ) { From 6c0d3a0a1d05035736411d151d9f8baba0ecf865 Mon Sep 17 00:00:00 2001 From: chandler05 <66492208+chandler05@users.noreply.github.com> Date: Fri, 4 Dec 2020 16:40:12 -0600 Subject: [PATCH 04/28] Semicolon --- src/commands/BulkCommand.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts index b8e6e7a2..403f04a4 100644 --- a/src/commands/BulkCommand.ts +++ b/src/commands/BulkCommand.ts @@ -54,7 +54,7 @@ export default class BulkCommand extends PrefixCommand { Command.logger.error( err ); return false; } - const filter = `https://bugs.mojang.com/browse/${ firstMentioned }?jql=key%20in(${ ticketKeys.join( '%2C' ) })` + const filter = `https://bugs.mojang.com/browse/${ firstMentioned }?jql=key%20in(${ ticketKeys.join( '%2C' ) })`; try { await message.channel.send( `${ message.author.toString() } ${ filter }` ); } catch { From 635731fec6e2d9f981bf9d10d78bf824bfa4b5b2 Mon Sep 17 00:00:00 2001 From: chandler05 Date: Fri, 4 Dec 2020 16:44:05 -0600 Subject: [PATCH 05/28] Await --- src/commands/BulkCommand.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts index 403f04a4..61382ae7 100644 --- a/src/commands/BulkCommand.ts +++ b/src/commands/BulkCommand.ts @@ -21,7 +21,7 @@ export default class BulkCommand extends PrefixCommand { const internalChannel = await DiscordUtil.getChannel( internalChannelId ); if ( internalChannel instanceof TextChannel ) { const channelMessages = internalChannel.messages; - for ( const channelMessage of channelMessages ) { + for await ( const channelMessage of channelMessages ) { const reaction = channelMessage.reactions.cache.get( BotConfig.request.bulkEmoji ); if ( reaction.users.cache.get( message.author ) ) { bulkMessages.add( channelMessage ); From 2dfc80d2094c9087fffa79065897352d369a3064 Mon Sep 17 00:00:00 2001 From: chandler05 Date: Fri, 4 Dec 2020 16:59:15 -0600 Subject: [PATCH 06/28] Error --- src/commands/BulkCommand.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts index 61382ae7..62885275 100644 --- a/src/commands/BulkCommand.ts +++ b/src/commands/BulkCommand.ts @@ -20,7 +20,7 @@ export default class BulkCommand extends PrefixCommand { try { const internalChannel = await DiscordUtil.getChannel( internalChannelId ); if ( internalChannel instanceof TextChannel ) { - const channelMessages = internalChannel.messages; + const channelMessages = internalChannel.messages.cache; for await ( const channelMessage of channelMessages ) { const reaction = channelMessage.reactions.cache.get( BotConfig.request.bulkEmoji ); if ( reaction.users.cache.get( message.author ) ) { From 9b364136e52cd059d220d17416dfdddd87fbbc99 Mon Sep 17 00:00:00 2001 From: chandler05 Date: Sat, 5 Dec 2020 09:26:31 -0600 Subject: [PATCH 07/28] values --- src/commands/BulkCommand.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts index 62885275..f9b10f47 100644 --- a/src/commands/BulkCommand.ts +++ b/src/commands/BulkCommand.ts @@ -20,7 +20,7 @@ export default class BulkCommand extends PrefixCommand { try { const internalChannel = await DiscordUtil.getChannel( internalChannelId ); if ( internalChannel instanceof TextChannel ) { - const channelMessages = internalChannel.messages.cache; + const channelMessages = internalChannel.messages.cache.values(); for await ( const channelMessage of channelMessages ) { const reaction = channelMessage.reactions.cache.get( BotConfig.request.bulkEmoji ); if ( reaction.users.cache.get( message.author ) ) { From 6e6eeffe9ae1efb9fed93f8be0a6ef7a3fe4ac15 Mon Sep 17 00:00:00 2001 From: chandler05 <66492208+chandler05@users.noreply.github.com> Date: Sat, 5 Dec 2020 09:32:17 -0600 Subject: [PATCH 08/28] Update BulkCommand.ts --- src/commands/BulkCommand.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts index f9b10f47..0f26c648 100644 --- a/src/commands/BulkCommand.ts +++ b/src/commands/BulkCommand.ts @@ -23,7 +23,7 @@ export default class BulkCommand extends PrefixCommand { const channelMessages = internalChannel.messages.cache.values(); for await ( const channelMessage of channelMessages ) { const reaction = channelMessage.reactions.cache.get( BotConfig.request.bulkEmoji ); - if ( reaction.users.cache.get( message.author ) ) { + if ( reaction.users.cache.get( message.author.id ) ) { bulkMessages.add( channelMessage ); } } @@ -48,7 +48,7 @@ export default class BulkCommand extends PrefixCommand { } ticket.forEach( key => ticketKeys.push( key ) ); const reaction = bulkMessage.reactions.cache.get( BotConfig.request.bulkEmoji ); - await reaction.users.remove( message.author ); + await reaction.users.remove( message.author.id ); } } catch ( err ) { Command.logger.error( err ); From 37870ffd6f19f1e49853da022dd1892fdddf5b10 Mon Sep 17 00:00:00 2001 From: chandler05 <66492208+chandler05@users.noreply.github.com> Date: Sat, 5 Dec 2020 09:39:30 -0600 Subject: [PATCH 09/28] Change to arrays --- src/commands/BulkCommand.ts | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts index 0f26c648..a7834a9f 100644 --- a/src/commands/BulkCommand.ts +++ b/src/commands/BulkCommand.ts @@ -13,7 +13,7 @@ export default class BulkCommand extends PrefixCommand { return false; } - let bulkMessages: Set; + let bulkMessages: Messages[]; for ( let i = 0; i < BotConfig.request.internalChannels.length; i++ ) { const internalChannelId = BotConfig.request.internalChannels[i]; @@ -24,7 +24,7 @@ export default class BulkCommand extends PrefixCommand { for await ( const channelMessage of channelMessages ) { const reaction = channelMessage.reactions.cache.get( BotConfig.request.bulkEmoji ); if ( reaction.users.cache.get( message.author.id ) ) { - bulkMessages.add( channelMessage ); + bulkMessages.push( channelMessage ); } } } @@ -32,17 +32,15 @@ export default class BulkCommand extends PrefixCommand { Command.logger.error( err ); return false; } - } - - const bulkMessageArray = Array.from( bulkMessages ); + } let firstMentioned: string; let ticketKeys: string[]; try { - for ( let j = 0; j < bulkMessageArray.length; j++ ) { - const bulkMessage = bulkMessageArray[j]; - const ticket = Array.from( this.getTickets( bulkMessage.toString() ) ); + for ( let j = 0; j < bulkMessages.length; j++ ) { + const bulkMessage = bulkMessages[j]; + const ticket = this.getTickets( bulkMessage.toString() ); if ( firstMentioned == null ) { firstMentioned = ticket[1]; } @@ -64,12 +62,12 @@ export default class BulkCommand extends PrefixCommand { return true; } - private getTickets( content: string ): Set { + private getTickets( content: string ): string[] { let ticketMatch: RegExpExecArray; const regex = MentionCommand.getTicketIdRegex(); - const ticketMatches: Set = new Set(); + const ticketMatches: string[] = []; while ( ( ticketMatch = regex.exec( content ) ) !== null ) { - ticketMatches.add( ticketMatch[1] ); + ticketMatches.push( ticketMatch[1] ); } return ticketMatches; } From 74580c33042a9481cc78b2d56af9e920180cfad2 Mon Sep 17 00:00:00 2001 From: chandler05 Date: Sat, 5 Dec 2020 09:42:18 -0600 Subject: [PATCH 10/28] spaces --- src/commands/BulkCommand.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts index a7834a9f..9223ff6e 100644 --- a/src/commands/BulkCommand.ts +++ b/src/commands/BulkCommand.ts @@ -32,7 +32,7 @@ export default class BulkCommand extends PrefixCommand { Command.logger.error( err ); return false; } - } + } let firstMentioned: string; let ticketKeys: string[]; From 4e6bd2172bf4cc8f5b0317174cb5da01136552d2 Mon Sep 17 00:00:00 2001 From: chandler05 <66492208+chandler05@users.noreply.github.com> Date: Sat, 5 Dec 2020 09:59:59 -0600 Subject: [PATCH 11/28] Update BulkCommand.ts --- src/commands/BulkCommand.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts index 9223ff6e..ae70261f 100644 --- a/src/commands/BulkCommand.ts +++ b/src/commands/BulkCommand.ts @@ -13,7 +13,7 @@ export default class BulkCommand extends PrefixCommand { return false; } - let bulkMessages: Messages[]; + let bulkMessages: Message[]; for ( let i = 0; i < BotConfig.request.internalChannels.length; i++ ) { const internalChannelId = BotConfig.request.internalChannels[i]; From 63e01685714398e2dbf15921350536c2dd446b9f Mon Sep 17 00:00:00 2001 From: chandler05 Date: Sat, 5 Dec 2020 22:59:23 -0600 Subject: [PATCH 12/28] Rework system to work better --- src/commands/BulkCommand.ts | 52 ++++++------------- .../reaction/ReactionAddEventHandler.ts | 5 ++ .../reaction/ReactionRemoveEventHandler.ts | 5 ++ .../request/RequestBulkAddEventHandler.ts | 21 ++++++++ .../request/RequestBulkRemoveEventHandler.ts | 27 ++++++++++ 5 files changed, 74 insertions(+), 36 deletions(-) create mode 100644 src/events/request/RequestBulkAddEventHandler.ts create mode 100644 src/events/request/RequestBulkRemoveEventHandler.ts diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts index ae70261f..e1886b1c 100644 --- a/src/commands/BulkCommand.ts +++ b/src/commands/BulkCommand.ts @@ -1,58 +1,38 @@ -import { Message, TextChannel } from 'discord.js'; +import { Message, User } from 'discord.js'; import PrefixCommand from './PrefixCommand'; import MentionCommand from './MentionCommand'; -import Command from './Command'; -import DiscordUtil from '../util/DiscordUtil'; +import { RequestsUtil } from '../util/RequestsUtil'; import BotConfig from '../BotConfig'; export default class BulkCommand extends PrefixCommand { public readonly aliases = ['bulk', 'filter']; + public static currentBulkReactions: Map; + public async run( message: Message, args: string ): Promise { if ( args.length ) { return false; } - let bulkMessages: Message[]; - - for ( let i = 0; i < BotConfig.request.internalChannels.length; i++ ) { - const internalChannelId = BotConfig.request.internalChannels[i]; - try { - const internalChannel = await DiscordUtil.getChannel( internalChannelId ); - if ( internalChannel instanceof TextChannel ) { - const channelMessages = internalChannel.messages.cache.values(); - for await ( const channelMessage of channelMessages ) { - const reaction = channelMessage.reactions.cache.get( BotConfig.request.bulkEmoji ); - if ( reaction.users.cache.get( message.author.id ) ) { - bulkMessages.push( channelMessage ); - } - } - } - } catch ( err ) { - Command.logger.error( err ); - return false; - } - } - - let firstMentioned: string; let ticketKeys: string[]; + let firstMentioned: string; try { - for ( let j = 0; j < bulkMessages.length; j++ ) { - const bulkMessage = bulkMessages[j]; - const ticket = this.getTickets( bulkMessage.toString() ); - if ( firstMentioned == null ) { - firstMentioned = ticket[1]; - } - ticket.forEach( key => ticketKeys.push( key ) ); - const reaction = bulkMessage.reactions.cache.get( BotConfig.request.bulkEmoji ); - await reaction.users.remove( message.author.id ); + const bulkMessages = BulkCommand.currentBulkReactions.get( message.author ); + let originMessages: Message[]; + for ( const bulk of bulkMessages ) { + originMessages.push( await RequestsUtil.getOriginMessage( bulk ) ); + bulk.reactions.cache.get( BotConfig.request.bulkEmoji ).users.remove( message.author ); } - } catch ( err ) { - Command.logger.error( err ); + originMessages.forEach( origin => this.getTickets( origin.content ).forEach( ticket => ticketKeys.push( ticket ) ) ); + firstMentioned = ticketKeys[0]; + BulkCommand.currentBulkReactions.delete( message.author ); + } catch { return false; } + const filter = `https://bugs.mojang.com/browse/${ firstMentioned }?jql=key%20in(${ ticketKeys.join( '%2C' ) })`; + try { await message.channel.send( `${ message.author.toString() } ${ filter }` ); } catch { diff --git a/src/events/reaction/ReactionAddEventHandler.ts b/src/events/reaction/ReactionAddEventHandler.ts index 2aab23af..979831f4 100644 --- a/src/events/reaction/ReactionAddEventHandler.ts +++ b/src/events/reaction/ReactionAddEventHandler.ts @@ -1,6 +1,7 @@ import { MessageReaction, User } from 'discord.js'; import BotConfig from '../../BotConfig'; import DiscordEventHandler from '../EventHandler'; +import RequestBulkAddEventHandler from '../request/RequestBulkAddEventHandler'; import RequestEventHandler from '../request/RequestEventHandler'; import RequestReopenEventHandler from '../request/RequestReopenEventHandler'; import RequestResolveEventHandler from '../request/RequestResolveEventHandler'; @@ -14,6 +15,7 @@ export default class ReactionAddEventHandler implements DiscordEventHandler<'mes private readonly botUserId: string; private readonly roleSelectHandler = new RoleSelectEventHandler(); + private readonly requestBulkAddEventHandler = new RequestBulkAddEventHandler(); private readonly requestResolveEventHandler = new RequestResolveEventHandler(); private readonly requestReactionRemovalEventHandler = new RequestReactionRemovalEventHandler(); private readonly requestReopenEventHandler: RequestReopenEventHandler; @@ -39,6 +41,9 @@ export default class ReactionAddEventHandler implements DiscordEventHandler<'mes if ( BotConfig.roleGroups.find( g => g.message === messageReaction.message.id ) ) { // Handle role selection return this.roleSelectHandler.onEvent( messageReaction, user ); + } else if ( BotConfig.request.internalChannels.includes( messageReaction.message.channel.id ) && messageReaction.emoji.name === BotConfig.request.bulkEmoji ) { + // Handle adding a request to a bulk action + return this.requestBulkAddEventHandler.onEvent( messageReaction, user ); } else if ( BotConfig.request.internalChannels.includes( messageReaction.message.channel.id ) ) { // Handle resolving user request return this.requestResolveEventHandler.onEvent( messageReaction, user ); diff --git a/src/events/reaction/ReactionRemoveEventHandler.ts b/src/events/reaction/ReactionRemoveEventHandler.ts index 46376ea3..6345cdcd 100644 --- a/src/events/reaction/ReactionRemoveEventHandler.ts +++ b/src/events/reaction/ReactionRemoveEventHandler.ts @@ -1,6 +1,7 @@ import { MessageReaction, User } from 'discord.js'; import BotConfig from '../../BotConfig'; import EventHandler from '../EventHandler'; +import RequestBulkRemoveEventHandler from '../request/RequestBulkRemoveEventHandler'; import RequestUnresolveEventHandler from '../request/RequestUnresolveEventHandler'; import RoleRemoveEventHandler from '../roles/RoleRemoveEventHandler'; import MojiraBot from '../../MojiraBot'; @@ -12,6 +13,7 @@ export default class ReactionRemoveEventHandler implements EventHandler<'message private readonly roleRemoveHandler = new RoleRemoveEventHandler(); private readonly requestUnresolveEventHandler = new RequestUnresolveEventHandler(); + private readonly requestBulkRemoveEventHandler = new RequestBulkRemoveEventHandler(); constructor( botUserId: string ) { this.botUserId = botUserId; @@ -30,6 +32,9 @@ export default class ReactionRemoveEventHandler implements EventHandler<'message if ( BotConfig.roleGroups.find( g => g.message === messageReaction.message.id ) ) { // Handle role removal return this.roleRemoveHandler.onEvent( messageReaction, user ); + } else if ( BotConfig.request.internalChannels.includes( messageReaction.message.channel.id ) && messageReaction.emoji.name === BotConfig.request.bulkEmoji ) { + // Handle removing a request from a bulk action + return this.requestBulkRemoveEventHandler.onEvent( messageReaction, user ); } else if ( BotConfig.request.internalChannels.includes( messageReaction.message.channel.id ) ) { // Handle unresolving user request return this.requestUnresolveEventHandler.onEvent( messageReaction, user ); diff --git a/src/events/request/RequestBulkAddEventHandler.ts b/src/events/request/RequestBulkAddEventHandler.ts new file mode 100644 index 00000000..08b66e4e --- /dev/null +++ b/src/events/request/RequestBulkAddEventHandler.ts @@ -0,0 +1,21 @@ +import { MessageReaction, User } from 'discord.js'; +import * as log4js from 'log4js'; +import EventHandler from '../EventHandler'; +import BulkCommand from '../../commands/BulkCommand'; + +export default class RequestBulkAddEventHandler implements EventHandler<'messageReactionAdd'> { + public readonly eventName = 'messageReactionAdd'; + + private logger = log4js.getLogger( 'RequestBulkAddEventHandler' ); + + // This syntax is used to ensure that `this` refers to the `RequestResolveEventHandler` object + public onEvent = async ( reaction: MessageReaction, user: User ): Promise => { + this.logger.info( `User ${ user.tag } added '${ reaction.emoji.name }' reaction to request message '${ reaction.message.id }'` ); + + if ( BulkCommand.currentBulkReactions.has( user ) ) { + BulkCommand.currentBulkReactions.get( user ).push( reaction.message ); + } else { + BulkCommand.currentBulkReactions.set( user, [reaction.message] ); + } + }; +} diff --git a/src/events/request/RequestBulkRemoveEventHandler.ts b/src/events/request/RequestBulkRemoveEventHandler.ts new file mode 100644 index 00000000..df60b7e3 --- /dev/null +++ b/src/events/request/RequestBulkRemoveEventHandler.ts @@ -0,0 +1,27 @@ +import { MessageReaction, User } from 'discord.js'; +import * as log4js from 'log4js'; +import BulkCommand from '../../commands/BulkCommand'; +import EventHandler from '../EventHandler'; + +export default class RequestBulkRemoveEventHandler implements EventHandler<'messageReactionRemove'> { + public readonly eventName = 'messageReactionRemove'; + + private logger = log4js.getLogger( 'RequestBulkRemoveEventHandler' ); + + // This syntax is used to ensure that `this` refers to the `RequestResolveEventHandler` object + public onEvent = async ( reaction: MessageReaction, user: User ): Promise => { + this.logger.info( `User ${ user.tag } removed '${ reaction.emoji.name }' reaction from request message '${ reaction.message.id }'` ); + + if ( BulkCommand.currentBulkReactions.has( user ) ) { + const currentMessages = BulkCommand.currentBulkReactions.get( user ); + for ( let i = 0; i <= currentMessages.length; i++ ) { + const currentMessage = currentMessages[i]; + if ( currentMessage === reaction.message ) { + BulkCommand.currentBulkReactions.delete( user ); + BulkCommand.currentBulkReactions.set( user, currentMessages.splice( i, 1 ) ); + break; + } + } + } + }; +} From da2fb91faf3866420600af143dbd963ae80c30dd Mon Sep 17 00:00:00 2001 From: chandler05 Date: Sat, 5 Dec 2020 23:03:26 -0600 Subject: [PATCH 13/28] Catch promise --- src/commands/BulkCommand.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts index e1886b1c..20a9348a 100644 --- a/src/commands/BulkCommand.ts +++ b/src/commands/BulkCommand.ts @@ -1,6 +1,7 @@ import { Message, User } from 'discord.js'; import PrefixCommand from './PrefixCommand'; import MentionCommand from './MentionCommand'; +import Command from './Command'; import { RequestsUtil } from '../util/RequestsUtil'; import BotConfig from '../BotConfig'; @@ -22,7 +23,12 @@ export default class BulkCommand extends PrefixCommand { let originMessages: Message[]; for ( const bulk of bulkMessages ) { originMessages.push( await RequestsUtil.getOriginMessage( bulk ) ); - bulk.reactions.cache.get( BotConfig.request.bulkEmoji ).users.remove( message.author ); + try { + bulk.reactions.cache.get( BotConfig.request.bulkEmoji ).users.remove( message.author ); + } catch (error) { + Command.logger.error( err ); + return false; + } } originMessages.forEach( origin => this.getTickets( origin.content ).forEach( ticket => ticketKeys.push( ticket ) ) ); firstMentioned = ticketKeys[0]; From 367a9845b0117546a425ab6aa1004b981f3e763d Mon Sep 17 00:00:00 2001 From: chandler05 Date: Sat, 5 Dec 2020 23:05:19 -0600 Subject: [PATCH 14/28] A-WAIT --- src/commands/BulkCommand.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts index 20a9348a..61c0ce80 100644 --- a/src/commands/BulkCommand.ts +++ b/src/commands/BulkCommand.ts @@ -1,7 +1,6 @@ import { Message, User } from 'discord.js'; import PrefixCommand from './PrefixCommand'; import MentionCommand from './MentionCommand'; -import Command from './Command'; import { RequestsUtil } from '../util/RequestsUtil'; import BotConfig from '../BotConfig'; @@ -23,12 +22,7 @@ export default class BulkCommand extends PrefixCommand { let originMessages: Message[]; for ( const bulk of bulkMessages ) { originMessages.push( await RequestsUtil.getOriginMessage( bulk ) ); - try { - bulk.reactions.cache.get( BotConfig.request.bulkEmoji ).users.remove( message.author ); - } catch (error) { - Command.logger.error( err ); - return false; - } + await bulk.reactions.cache.get( BotConfig.request.bulkEmoji ).users.remove( message.author ); } originMessages.forEach( origin => this.getTickets( origin.content ).forEach( ticket => ticketKeys.push( ticket ) ) ); firstMentioned = ticketKeys[0]; From 208f71ecca7d2606cf822d706936f1414622a6bd Mon Sep 17 00:00:00 2001 From: chandler05 Date: Sun, 6 Dec 2020 00:01:39 -0600 Subject: [PATCH 15/28] Allow resolving through !jira bulk --- src/commands/BulkCommand.ts | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts index 61c0ce80..617d937f 100644 --- a/src/commands/BulkCommand.ts +++ b/src/commands/BulkCommand.ts @@ -1,6 +1,9 @@ import { Message, User } from 'discord.js'; import PrefixCommand from './PrefixCommand'; import MentionCommand from './MentionCommand'; +import ResolveRequestMessageTask from '../tasks/ResolveRequestMessageTask'; +import TaskScheduler from '../tasks/TaskScheduler'; +import emojiRegex = require( 'emoji-regex/text.js' ); import { RequestsUtil } from '../util/RequestsUtil'; import BotConfig from '../BotConfig'; @@ -10,8 +13,22 @@ export default class BulkCommand extends PrefixCommand { public static currentBulkReactions: Map; public async run( message: Message, args: string ): Promise { + let rawEmoji: string; + if ( args.length ) { - return false; + const customEmoji = /^/; + const unicodeEmoji = emojiRegex(); + + if ( customEmoji.test( args ) || unicodeEmoji.test( args ) ) { + rawEmoji = args; + const emojiMatch = customEmoji.exec( args ); + if ( emojiMatch ) { + rawEmoji = emojiMatch[2]; + } + } else { + await message.channel.send( `**Error:** ${ args } is not a valid emoji.` ); + return false; + } } let ticketKeys: string[]; @@ -26,6 +43,13 @@ export default class BulkCommand extends PrefixCommand { } originMessages.forEach( origin => this.getTickets( origin.content ).forEach( ticket => ticketKeys.push( ticket ) ) ); firstMentioned = ticketKeys[0]; + if ( rawEmoji ) { + bulkMessages.forEach( resolvable => TaskScheduler.addOneTimeMessageTask( + resolvable, + new ResolveRequestMessageTask( rawEmoji, message.author ), + BotConfig.request.resolveDelay || 0 + ) ); + } BulkCommand.currentBulkReactions.delete( message.author ); } catch { return false; @@ -52,7 +76,7 @@ export default class BulkCommand extends PrefixCommand { return ticketMatches; } - public asString(): string { - return '!jira bulk'; + public asString( args: string ): string { + return `!jira bulk ${ args }`; } } From 69a9820261a4f4af8cecf24e5b8523fcd34a5b2e Mon Sep 17 00:00:00 2001 From: chandler05 <66492208+chandler05@users.noreply.github.com> Date: Sun, 6 Dec 2020 18:08:18 -0600 Subject: [PATCH 16/28] Update src/events/request/RequestBulkRemoveEventHandler.ts Co-authored-by: SPGoding <15277496+SPGoding@users.noreply.github.com> --- src/events/request/RequestBulkRemoveEventHandler.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/events/request/RequestBulkRemoveEventHandler.ts b/src/events/request/RequestBulkRemoveEventHandler.ts index df60b7e3..9102e709 100644 --- a/src/events/request/RequestBulkRemoveEventHandler.ts +++ b/src/events/request/RequestBulkRemoveEventHandler.ts @@ -17,8 +17,7 @@ export default class RequestBulkRemoveEventHandler implements EventHandler<'mess for ( let i = 0; i <= currentMessages.length; i++ ) { const currentMessage = currentMessages[i]; if ( currentMessage === reaction.message ) { - BulkCommand.currentBulkReactions.delete( user ); - BulkCommand.currentBulkReactions.set( user, currentMessages.splice( i, 1 ) ); + currentMessages.splice( i, 1 ); break; } } From 9c7d8c3d14d50c9d66810a206dca2522e7d12a06 Mon Sep 17 00:00:00 2001 From: chandler05 <66492208+chandler05@users.noreply.github.com> Date: Sun, 6 Dec 2020 18:08:31 -0600 Subject: [PATCH 17/28] Update src/commands/BulkCommand.ts Co-authored-by: SPGoding <15277496+SPGoding@users.noreply.github.com> --- src/commands/BulkCommand.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts index 617d937f..27802f39 100644 --- a/src/commands/BulkCommand.ts +++ b/src/commands/BulkCommand.ts @@ -41,7 +41,7 @@ export default class BulkCommand extends PrefixCommand { originMessages.push( await RequestsUtil.getOriginMessage( bulk ) ); await bulk.reactions.cache.get( BotConfig.request.bulkEmoji ).users.remove( message.author ); } - originMessages.forEach( origin => this.getTickets( origin.content ).forEach( ticket => ticketKeys.push( ticket ) ) ); + originMessages.forEach( origin => ticketKeys.push( ...this.getTickets( origin.content ) ) ); firstMentioned = ticketKeys[0]; if ( rawEmoji ) { bulkMessages.forEach( resolvable => TaskScheduler.addOneTimeMessageTask( From 27af05f0f5a2e3f037894640638429e4fe5cd124 Mon Sep 17 00:00:00 2001 From: chandler05 Date: Sun, 6 Dec 2020 18:10:53 -0600 Subject: [PATCH 18/28] Fixes batch --- src/commands/BulkCommand.ts | 10 +++++----- src/events/request/RequestBulkAddEventHandler.ts | 6 +++--- src/events/request/RequestBulkRemoveEventHandler.ts | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts index 617d937f..fa98a042 100644 --- a/src/commands/BulkCommand.ts +++ b/src/commands/BulkCommand.ts @@ -1,4 +1,4 @@ -import { Message, User } from 'discord.js'; +import { Message } from 'discord.js'; import PrefixCommand from './PrefixCommand'; import MentionCommand from './MentionCommand'; import ResolveRequestMessageTask from '../tasks/ResolveRequestMessageTask'; @@ -10,13 +10,13 @@ import BotConfig from '../BotConfig'; export default class BulkCommand extends PrefixCommand { public readonly aliases = ['bulk', 'filter']; - public static currentBulkReactions: Map; + public static currentBulkReactions = new Map(); public async run( message: Message, args: string ): Promise { let rawEmoji: string; if ( args.length ) { - const customEmoji = /^/; + const customEmoji = /^/; const unicodeEmoji = emojiRegex(); if ( customEmoji.test( args ) || unicodeEmoji.test( args ) ) { @@ -35,7 +35,7 @@ export default class BulkCommand extends PrefixCommand { let firstMentioned: string; try { - const bulkMessages = BulkCommand.currentBulkReactions.get( message.author ); + const bulkMessages = BulkCommand.currentBulkReactions.get( message.author.tag ); let originMessages: Message[]; for ( const bulk of bulkMessages ) { originMessages.push( await RequestsUtil.getOriginMessage( bulk ) ); @@ -50,7 +50,7 @@ export default class BulkCommand extends PrefixCommand { BotConfig.request.resolveDelay || 0 ) ); } - BulkCommand.currentBulkReactions.delete( message.author ); + BulkCommand.currentBulkReactions.delete( message.author.tag ); } catch { return false; } diff --git a/src/events/request/RequestBulkAddEventHandler.ts b/src/events/request/RequestBulkAddEventHandler.ts index 08b66e4e..71d502be 100644 --- a/src/events/request/RequestBulkAddEventHandler.ts +++ b/src/events/request/RequestBulkAddEventHandler.ts @@ -12,10 +12,10 @@ export default class RequestBulkAddEventHandler implements EventHandler<'message public onEvent = async ( reaction: MessageReaction, user: User ): Promise => { this.logger.info( `User ${ user.tag } added '${ reaction.emoji.name }' reaction to request message '${ reaction.message.id }'` ); - if ( BulkCommand.currentBulkReactions.has( user ) ) { - BulkCommand.currentBulkReactions.get( user ).push( reaction.message ); + if ( BulkCommand.currentBulkReactions.has( user.tag ) ) { + BulkCommand.currentBulkReactions.get( user.tag ).push( reaction.message ); } else { - BulkCommand.currentBulkReactions.set( user, [reaction.message] ); + BulkCommand.currentBulkReactions.set( user.tag, [reaction.message] ); } }; } diff --git a/src/events/request/RequestBulkRemoveEventHandler.ts b/src/events/request/RequestBulkRemoveEventHandler.ts index df60b7e3..c6bd70a3 100644 --- a/src/events/request/RequestBulkRemoveEventHandler.ts +++ b/src/events/request/RequestBulkRemoveEventHandler.ts @@ -12,13 +12,13 @@ export default class RequestBulkRemoveEventHandler implements EventHandler<'mess public onEvent = async ( reaction: MessageReaction, user: User ): Promise => { this.logger.info( `User ${ user.tag } removed '${ reaction.emoji.name }' reaction from request message '${ reaction.message.id }'` ); - if ( BulkCommand.currentBulkReactions.has( user ) ) { - const currentMessages = BulkCommand.currentBulkReactions.get( user ); + if ( BulkCommand.currentBulkReactions.has( user.tag ) ) { + const currentMessages = BulkCommand.currentBulkReactions.get( user.tag ); for ( let i = 0; i <= currentMessages.length; i++ ) { const currentMessage = currentMessages[i]; - if ( currentMessage === reaction.message ) { - BulkCommand.currentBulkReactions.delete( user ); - BulkCommand.currentBulkReactions.set( user, currentMessages.splice( i, 1 ) ); + if ( currentMessage.id === reaction.message.id ) { + BulkCommand.currentBulkReactions.delete( user.tag ); + BulkCommand.currentBulkReactions.set( user.tag, currentMessages.splice( i, 1 ) ); break; } } From 93ef5d11bd5a0674dc574ca997aefdd2f0665476 Mon Sep 17 00:00:00 2001 From: chandler05 Date: Sun, 6 Dec 2020 19:00:25 -0600 Subject: [PATCH 19/28] Add EmojiUtil --- src/commands/BulkCommand.ts | 43 +++++++++++++++++++------------------ src/commands/PollCommand.ts | 19 +++++----------- src/util/EmojiUtil.ts | 17 +++++++++++++++ 3 files changed, 44 insertions(+), 35 deletions(-) create mode 100644 src/util/EmojiUtil.ts diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts index 5d4e6918..fc50c788 100644 --- a/src/commands/BulkCommand.ts +++ b/src/commands/BulkCommand.ts @@ -1,10 +1,11 @@ import { Message } from 'discord.js'; import PrefixCommand from './PrefixCommand'; import MentionCommand from './MentionCommand'; +import Command from './Command'; import ResolveRequestMessageTask from '../tasks/ResolveRequestMessageTask'; import TaskScheduler from '../tasks/TaskScheduler'; -import emojiRegex = require( 'emoji-regex/text.js' ); import { RequestsUtil } from '../util/RequestsUtil'; +import { EmojiUtil } from '../util/EmojiUtil'; import BotConfig from '../BotConfig'; export default class BulkCommand extends PrefixCommand { @@ -12,28 +13,20 @@ export default class BulkCommand extends PrefixCommand { public static currentBulkReactions = new Map(); - public async run( message: Message, args: string ): Promise { - let rawEmoji: string; + private emoji: string; - if ( args.length ) { - const customEmoji = /^/; - const unicodeEmoji = emojiRegex(); + private ticketKeys: string[]; + private firstMentioned: string; - if ( customEmoji.test( args ) || unicodeEmoji.test( args ) ) { - rawEmoji = args; - const emojiMatch = customEmoji.exec( args ); - if ( emojiMatch ) { - rawEmoji = emojiMatch[2]; - } - } else { + public async run( message: Message, args: string ): Promise { + if ( args.length ) { + this.emoji = EmojiUtil.getEmoji( args ); + if ( !this.emoji ) { await message.channel.send( `**Error:** ${ args } is not a valid emoji.` ); return false; } } - let ticketKeys: string[]; - let firstMentioned: string; - try { const bulkMessages = BulkCommand.currentBulkReactions.get( message.author.tag ); let originMessages: Message[]; @@ -41,12 +34,12 @@ export default class BulkCommand extends PrefixCommand { originMessages.push( await RequestsUtil.getOriginMessage( bulk ) ); await bulk.reactions.cache.get( BotConfig.request.bulkEmoji ).users.remove( message.author ); } - originMessages.forEach( origin => ticketKeys.push( ...this.getTickets( origin.content ) ) ); - firstMentioned = ticketKeys[0]; - if ( rawEmoji ) { + originMessages.forEach( origin => this.ticketKeys.push( ...this.getTickets( origin.content ) ) ); + this.firstMentioned = this.ticketKeys[0]; + if ( this.emoji ) { bulkMessages.forEach( resolvable => TaskScheduler.addOneTimeMessageTask( resolvable, - new ResolveRequestMessageTask( rawEmoji, message.author ), + new ResolveRequestMessageTask( this.emoji, message.author ), BotConfig.request.resolveDelay || 0 ) ); } @@ -55,7 +48,7 @@ export default class BulkCommand extends PrefixCommand { return false; } - const filter = `https://bugs.mojang.com/browse/${ firstMentioned }?jql=key%20in(${ ticketKeys.join( '%2C' ) })`; + const filter = `https://bugs.mojang.com/browse/${ this.firstMentioned }?jql=key%20in(${ this.ticketKeys.join( '%2C' ) })`; try { await message.channel.send( `${ message.author.toString() } ${ filter }` ); @@ -63,6 +56,14 @@ export default class BulkCommand extends PrefixCommand { return false; } + if ( message.deletable ) { + try { + await message.delete(); + } catch ( err ) { + Command.logger.error( err ); + } + } + return true; } diff --git a/src/commands/PollCommand.ts b/src/commands/PollCommand.ts index a9a7b07e..f0ef5008 100644 --- a/src/commands/PollCommand.ts +++ b/src/commands/PollCommand.ts @@ -1,7 +1,7 @@ import PrefixCommand from './PrefixCommand'; import { Message, TextChannel, DMChannel, MessageEmbed, NewsChannel } from 'discord.js'; import Command from './Command'; -import emojiRegex = require( 'emoji-regex/text.js' ); +import { EmojiUtil } from '../util/EmojiUtil'; import PermissionRegistry from '../permissions/PermissionRegistry'; import { ReactionsUtil } from '../util/ReactionsUtil'; @@ -103,27 +103,18 @@ export default class PollCommand extends PrefixCommand { const optionArgs = /^\s*(\S+)\s+(.+)\s*$/.exec( option ); - const customEmoji = /^/; - const unicodeEmoji = emojiRegex(); - if ( !optionArgs ) { await this.sendSyntaxMessage( message.channel, 'Invalid options' ); return false; } const emoji = optionArgs[1]; - if ( customEmoji.test( emoji ) || unicodeEmoji.test( emoji ) ) { - let emojiName = emoji; - let rawEmoji = emoji; - const emojiMatch = customEmoji.exec( emoji ); - if ( emojiMatch ) { - emojiName = emojiMatch[1]; - rawEmoji = emojiMatch[2]; - } + const emojiTest = EmojiUtil.getEmoji( emoji ); + if ( emojiTest ) { options.push( { emoji: emoji, - emojiName: emojiName, - rawEmoji: rawEmoji, + emojiName: emojiTest, + rawEmoji: emojiTest, text: optionArgs[2], } ); } else { diff --git a/src/util/EmojiUtil.ts b/src/util/EmojiUtil.ts new file mode 100644 index 00000000..f6eda49f --- /dev/null +++ b/src/util/EmojiUtil.ts @@ -0,0 +1,17 @@ +import emojiRegex = require( 'emoji-regex/text.js' ); + +export class EmojiUtil { + public static getEmoji( args: string ): string { + const customEmoji = /^/; + const unicodeEmoji = emojiRegex(); + let rawEmoji: string; + if ( unicodeEmoji.test( args ) ) { + rawEmoji = args; + } else if ( customEmoji.test( args ) ) { + rawEmoji = customEmoji.exec( args )[2]; + } else { + return; + } + return rawEmoji; + } +} \ No newline at end of file From bb6612f822a7b23865603bd1c8bc6f11a301ad71 Mon Sep 17 00:00:00 2001 From: chandler05 Date: Sun, 6 Dec 2020 20:27:24 -0600 Subject: [PATCH 20/28] Initialize properly, add deletion of messages, add to requests util --- config/default.yml | 2 + config/template.yml | 3 ++ src/BotConfig.ts | 4 ++ src/commands/BulkCommand.ts | 66 +++++++++++------------ src/events/request/RequestEventHandler.ts | 12 +---- src/util/RequestsUtil.ts | 11 ++++ 6 files changed, 53 insertions(+), 45 deletions(-) diff --git a/config/default.yml b/config/default.yml index c9378e37..557183e3 100644 --- a/config/default.yml +++ b/config/default.yml @@ -10,6 +10,8 @@ forbiddenTicketPrefix: '!' requiredTicketPrefix: '' +filterRemovalTimeout: 300000 + projects: - BDS - MC diff --git a/config/template.yml b/config/template.yml index be1d7ff3..4c400587 100644 --- a/config/template.yml +++ b/config/template.yml @@ -34,6 +34,9 @@ forbiddenTicketPrefix: # When omitted or empty, no prefix is required for posting embeds. requiredTicketPrefix: +# The time (in milliseconds) the bot will wait before removing a '!jira bulk' filter +filterRemovalTimeout: + # The projects the bot should be able to find tickets for. projects: - diff --git a/src/BotConfig.ts b/src/BotConfig.ts index 4aea5467..7e2b1ff3 100644 --- a/src/BotConfig.ts +++ b/src/BotConfig.ts @@ -107,6 +107,8 @@ export default class BotConfig { public static requiredTicketPrefix: string; public static forbiddenTicketPrefix: string; + public static filterRemovalTimeout: number; + public static projects: string[]; public static request: RequestConfig; @@ -129,6 +131,8 @@ export default class BotConfig { this.forbiddenTicketPrefix = getOrDefault( 'forbiddenTicketPrefix', '' ); this.requiredTicketPrefix = getOrDefault( 'requiredTicketPrefix', '' ); + this.filterRemovalTimeout = config.get( 'filterRemovalTimeout' ); + this.projects = config.get( 'projects' ); this.request = new RequestConfig(); diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts index fc50c788..8a4a9b1b 100644 --- a/src/commands/BulkCommand.ts +++ b/src/commands/BulkCommand.ts @@ -1,6 +1,5 @@ import { Message } from 'discord.js'; import PrefixCommand from './PrefixCommand'; -import MentionCommand from './MentionCommand'; import Command from './Command'; import ResolveRequestMessageTask from '../tasks/ResolveRequestMessageTask'; import TaskScheduler from '../tasks/TaskScheduler'; @@ -13,45 +12,54 @@ export default class BulkCommand extends PrefixCommand { public static currentBulkReactions = new Map(); - private emoji: string; - - private ticketKeys: string[]; - private firstMentioned: string; - public async run( message: Message, args: string ): Promise { + let emoji: string; + if ( args.length ) { - this.emoji = EmojiUtil.getEmoji( args ); - if ( !this.emoji ) { + emoji = EmojiUtil.getEmoji( args ); + if ( !emoji ) { await message.channel.send( `**Error:** ${ args } is not a valid emoji.` ); return false; } } + let ticketKeys: string[] = []; + let firstMentioned: string; + try { const bulkMessages = BulkCommand.currentBulkReactions.get( message.author.tag ); - let originMessages: Message[]; - for ( const bulk of bulkMessages ) { - originMessages.push( await RequestsUtil.getOriginMessage( bulk ) ); - await bulk.reactions.cache.get( BotConfig.request.bulkEmoji ).users.remove( message.author ); - } - originMessages.forEach( origin => this.ticketKeys.push( ...this.getTickets( origin.content ) ) ); - this.firstMentioned = this.ticketKeys[0]; - if ( this.emoji ) { - bulkMessages.forEach( resolvable => TaskScheduler.addOneTimeMessageTask( - resolvable, - new ResolveRequestMessageTask( this.emoji, message.author ), - BotConfig.request.resolveDelay || 0 - ) ); + let originMessages: Message[] = []; + if ( bulkMessages ) { + for ( const bulk of bulkMessages ) { + originMessages.push( await RequestsUtil.getOriginMessage( bulk ) ); + await bulk.reactions.cache.get( BotConfig.request.bulkEmoji ).users.remove( message.author ); + } + originMessages.forEach( origin => ticketKeys.push( ...RequestsUtil.getTickets( origin.content ) ) ); + firstMentioned = ticketKeys[0]; + if ( emoji ) { + bulkMessages.forEach( resolvable => TaskScheduler.addOneTimeMessageTask( + resolvable, + new ResolveRequestMessageTask( emoji, message.author ), + BotConfig.request.resolveDelay || 0 + ) ); + } + BulkCommand.currentBulkReactions.delete( message.author.tag ); + } else { + return false; } - BulkCommand.currentBulkReactions.delete( message.author.tag ); } catch { return false; } - const filter = `https://bugs.mojang.com/browse/${ this.firstMentioned }?jql=key%20in(${ this.ticketKeys.join( '%2C' ) })`; + const filter = `https://bugs.mojang.com/browse/${ firstMentioned }?jql=key%20in(${ ticketKeys.join( '%2C' ) })`; try { - await message.channel.send( `${ message.author.toString() } ${ filter }` ); + const filterMessage = await message.channel.send( `${ message.author.toString() } ${ filter }` ); + + const timeout = BotConfig.filterRemovalTimeout; + if ( timeout ) { + await filterMessage.delete( { timeout } ); + } } catch { return false; } @@ -67,16 +75,6 @@ export default class BulkCommand extends PrefixCommand { return true; } - private getTickets( content: string ): string[] { - let ticketMatch: RegExpExecArray; - const regex = MentionCommand.getTicketIdRegex(); - const ticketMatches: string[] = []; - while ( ( ticketMatch = regex.exec( content ) ) !== null ) { - ticketMatches.push( ticketMatch[1] ); - } - return ticketMatches; - } - public asString( args: string ): string { return `!jira bulk ${ args }`; } diff --git a/src/events/request/RequestEventHandler.ts b/src/events/request/RequestEventHandler.ts index 72a7d2fc..9f8c0912 100644 --- a/src/events/request/RequestEventHandler.ts +++ b/src/events/request/RequestEventHandler.ts @@ -66,7 +66,7 @@ export default class RequestEventHandler implements EventHandler<'message'> { } if ( BotConfig.request.invalidRequestJql ) { - const tickets = this.getTickets( origin.content ); + const tickets = RequestsUtil.getTickets( origin.content ); const searchResults = await this.jira.search.search( { jql: `(${ BotConfig.request.invalidRequestJql }) AND key in (${ tickets.join( ',' ) })`, fields: ['key'], @@ -124,16 +124,6 @@ export default class RequestEventHandler implements EventHandler<'message'> { } }; - private getTickets( content: string ): string[] { - let ticketMatch: RegExpExecArray; - const regex = MentionCommand.getTicketIdRegex(); - const ticketMatches: string[] = []; - while ( ( ticketMatch = regex.exec( content ) ) !== null ) { - ticketMatches.push( ticketMatch[1] ); - } - return ticketMatches; - } - private replaceTicketReferencesWithRichLinks( content: string, regex: RegExp ): string { // Only one of the two capture groups ($1 and $2) can catch an ID at the same time. // `$1$2` is used to get the ID from either of the two groups. diff --git a/src/util/RequestsUtil.ts b/src/util/RequestsUtil.ts index ae933062..0c195b88 100644 --- a/src/util/RequestsUtil.ts +++ b/src/util/RequestsUtil.ts @@ -1,5 +1,6 @@ import { Message, TextChannel } from 'discord.js'; import BotConfig from '../BotConfig'; +import MentionCommand from '../commands/MentionCommand'; import DiscordUtil from './DiscordUtil'; export class RequestsUtil { @@ -48,4 +49,14 @@ export class RequestsUtil { .replace( '{{url}}', message.url ) .replace( '{{message}}', message.content.replace( /(^|\n)/g, '$1> ' ) ); } + + public static getTickets( content: string ): string[] { + let ticketMatch: RegExpExecArray; + const regex = MentionCommand.getTicketIdRegex(); + const ticketMatches: string[] = []; + while ( ( ticketMatch = regex.exec( content ) ) !== null ) { + ticketMatches.push( ticketMatch[1] ); + } + return ticketMatches; + } } \ No newline at end of file From a2cf6421553535958e8a7952a1283875aa9a2316 Mon Sep 17 00:00:00 2001 From: chandler05 Date: Sun, 6 Dec 2020 20:29:25 -0600 Subject: [PATCH 21/28] Let to const --- src/commands/BulkCommand.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts index 8a4a9b1b..32530d1a 100644 --- a/src/commands/BulkCommand.ts +++ b/src/commands/BulkCommand.ts @@ -23,12 +23,12 @@ export default class BulkCommand extends PrefixCommand { } } - let ticketKeys: string[] = []; + const ticketKeys: string[] = []; let firstMentioned: string; try { const bulkMessages = BulkCommand.currentBulkReactions.get( message.author.tag ); - let originMessages: Message[] = []; + const originMessages: Message[] = []; if ( bulkMessages ) { for ( const bulk of bulkMessages ) { originMessages.push( await RequestsUtil.getOriginMessage( bulk ) ); From acf0a4c72c52fda43f494742d4d5eb21b49a89c0 Mon Sep 17 00:00:00 2001 From: chandler05 Date: Sun, 6 Dec 2020 20:38:45 -0600 Subject: [PATCH 22/28] Remove bulk event handlers --- .../reaction/ReactionAddEventHandler.ts | 5 --- .../reaction/ReactionRemoveEventHandler.ts | 5 --- .../request/RequestBulkAddEventHandler.ts | 21 ----------- .../request/RequestBulkRemoveEventHandler.ts | 26 ------------- .../request/RequestResolveEventHandler.ts | 37 +++++++++++-------- .../request/RequestUnresolveEventHandler.ts | 30 ++++++++++----- 6 files changed, 43 insertions(+), 81 deletions(-) delete mode 100644 src/events/request/RequestBulkAddEventHandler.ts delete mode 100644 src/events/request/RequestBulkRemoveEventHandler.ts diff --git a/src/events/reaction/ReactionAddEventHandler.ts b/src/events/reaction/ReactionAddEventHandler.ts index 979831f4..2aab23af 100644 --- a/src/events/reaction/ReactionAddEventHandler.ts +++ b/src/events/reaction/ReactionAddEventHandler.ts @@ -1,7 +1,6 @@ import { MessageReaction, User } from 'discord.js'; import BotConfig from '../../BotConfig'; import DiscordEventHandler from '../EventHandler'; -import RequestBulkAddEventHandler from '../request/RequestBulkAddEventHandler'; import RequestEventHandler from '../request/RequestEventHandler'; import RequestReopenEventHandler from '../request/RequestReopenEventHandler'; import RequestResolveEventHandler from '../request/RequestResolveEventHandler'; @@ -15,7 +14,6 @@ export default class ReactionAddEventHandler implements DiscordEventHandler<'mes private readonly botUserId: string; private readonly roleSelectHandler = new RoleSelectEventHandler(); - private readonly requestBulkAddEventHandler = new RequestBulkAddEventHandler(); private readonly requestResolveEventHandler = new RequestResolveEventHandler(); private readonly requestReactionRemovalEventHandler = new RequestReactionRemovalEventHandler(); private readonly requestReopenEventHandler: RequestReopenEventHandler; @@ -41,9 +39,6 @@ export default class ReactionAddEventHandler implements DiscordEventHandler<'mes if ( BotConfig.roleGroups.find( g => g.message === messageReaction.message.id ) ) { // Handle role selection return this.roleSelectHandler.onEvent( messageReaction, user ); - } else if ( BotConfig.request.internalChannels.includes( messageReaction.message.channel.id ) && messageReaction.emoji.name === BotConfig.request.bulkEmoji ) { - // Handle adding a request to a bulk action - return this.requestBulkAddEventHandler.onEvent( messageReaction, user ); } else if ( BotConfig.request.internalChannels.includes( messageReaction.message.channel.id ) ) { // Handle resolving user request return this.requestResolveEventHandler.onEvent( messageReaction, user ); diff --git a/src/events/reaction/ReactionRemoveEventHandler.ts b/src/events/reaction/ReactionRemoveEventHandler.ts index 6345cdcd..46376ea3 100644 --- a/src/events/reaction/ReactionRemoveEventHandler.ts +++ b/src/events/reaction/ReactionRemoveEventHandler.ts @@ -1,7 +1,6 @@ import { MessageReaction, User } from 'discord.js'; import BotConfig from '../../BotConfig'; import EventHandler from '../EventHandler'; -import RequestBulkRemoveEventHandler from '../request/RequestBulkRemoveEventHandler'; import RequestUnresolveEventHandler from '../request/RequestUnresolveEventHandler'; import RoleRemoveEventHandler from '../roles/RoleRemoveEventHandler'; import MojiraBot from '../../MojiraBot'; @@ -13,7 +12,6 @@ export default class ReactionRemoveEventHandler implements EventHandler<'message private readonly roleRemoveHandler = new RoleRemoveEventHandler(); private readonly requestUnresolveEventHandler = new RequestUnresolveEventHandler(); - private readonly requestBulkRemoveEventHandler = new RequestBulkRemoveEventHandler(); constructor( botUserId: string ) { this.botUserId = botUserId; @@ -32,9 +30,6 @@ export default class ReactionRemoveEventHandler implements EventHandler<'message if ( BotConfig.roleGroups.find( g => g.message === messageReaction.message.id ) ) { // Handle role removal return this.roleRemoveHandler.onEvent( messageReaction, user ); - } else if ( BotConfig.request.internalChannels.includes( messageReaction.message.channel.id ) && messageReaction.emoji.name === BotConfig.request.bulkEmoji ) { - // Handle removing a request from a bulk action - return this.requestBulkRemoveEventHandler.onEvent( messageReaction, user ); } else if ( BotConfig.request.internalChannels.includes( messageReaction.message.channel.id ) ) { // Handle unresolving user request return this.requestUnresolveEventHandler.onEvent( messageReaction, user ); diff --git a/src/events/request/RequestBulkAddEventHandler.ts b/src/events/request/RequestBulkAddEventHandler.ts deleted file mode 100644 index 71d502be..00000000 --- a/src/events/request/RequestBulkAddEventHandler.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { MessageReaction, User } from 'discord.js'; -import * as log4js from 'log4js'; -import EventHandler from '../EventHandler'; -import BulkCommand from '../../commands/BulkCommand'; - -export default class RequestBulkAddEventHandler implements EventHandler<'messageReactionAdd'> { - public readonly eventName = 'messageReactionAdd'; - - private logger = log4js.getLogger( 'RequestBulkAddEventHandler' ); - - // This syntax is used to ensure that `this` refers to the `RequestResolveEventHandler` object - public onEvent = async ( reaction: MessageReaction, user: User ): Promise => { - this.logger.info( `User ${ user.tag } added '${ reaction.emoji.name }' reaction to request message '${ reaction.message.id }'` ); - - if ( BulkCommand.currentBulkReactions.has( user.tag ) ) { - BulkCommand.currentBulkReactions.get( user.tag ).push( reaction.message ); - } else { - BulkCommand.currentBulkReactions.set( user.tag, [reaction.message] ); - } - }; -} diff --git a/src/events/request/RequestBulkRemoveEventHandler.ts b/src/events/request/RequestBulkRemoveEventHandler.ts deleted file mode 100644 index 9c5a8ed6..00000000 --- a/src/events/request/RequestBulkRemoveEventHandler.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { MessageReaction, User } from 'discord.js'; -import * as log4js from 'log4js'; -import BulkCommand from '../../commands/BulkCommand'; -import EventHandler from '../EventHandler'; - -export default class RequestBulkRemoveEventHandler implements EventHandler<'messageReactionRemove'> { - public readonly eventName = 'messageReactionRemove'; - - private logger = log4js.getLogger( 'RequestBulkRemoveEventHandler' ); - - // This syntax is used to ensure that `this` refers to the `RequestResolveEventHandler` object - public onEvent = async ( reaction: MessageReaction, user: User ): Promise => { - this.logger.info( `User ${ user.tag } removed '${ reaction.emoji.name }' reaction from request message '${ reaction.message.id }'` ); - - if ( BulkCommand.currentBulkReactions.has( user.tag ) ) { - const currentMessages = BulkCommand.currentBulkReactions.get( user.tag ); - for ( let i = 0; i <= currentMessages.length; i++ ) { - const currentMessage = currentMessages[i]; - if ( currentMessage.id === reaction.message.id ) { - currentMessages.splice( i, 1 ); - break; - } - } - } - }; -} diff --git a/src/events/request/RequestResolveEventHandler.ts b/src/events/request/RequestResolveEventHandler.ts index 5e086506..7acea687 100644 --- a/src/events/request/RequestResolveEventHandler.ts +++ b/src/events/request/RequestResolveEventHandler.ts @@ -1,6 +1,7 @@ import { MessageReaction, User } from 'discord.js'; import * as log4js from 'log4js'; import BotConfig, { PrependResponseMessageType } from '../../BotConfig'; +import BulkCommand from '../../commands/BulkCommand'; import ResolveRequestMessageTask from '../../tasks/ResolveRequestMessageTask'; import TaskScheduler from '../../tasks/TaskScheduler'; import { RequestsUtil } from '../../util/RequestsUtil'; @@ -17,24 +18,30 @@ export default class RequestResolveEventHandler implements EventHandler<'message TaskScheduler.clearMessageTasks( reaction.message ); - if ( BotConfig.request.prependResponseMessage == PrependResponseMessageType.WhenResolved - && BotConfig.request.ignorePrependResponseMessageEmoji !== reaction.emoji.name ) { - const origin = await RequestsUtil.getOriginMessage( reaction.message ); - if ( origin ) { - try { - await reaction.message.edit( RequestsUtil.getResponseMessage( origin ) ); - } catch ( error ) { - this.logger.error( error ); + if ( BotConfig.request.bulkEmoji !== reaction.emoji.name ) { + if ( BotConfig.request.prependResponseMessage == PrependResponseMessageType.WhenResolved + && BotConfig.request.ignorePrependResponseMessageEmoji !== reaction.emoji.name ) { + const origin = await RequestsUtil.getOriginMessage( reaction.message ); + if ( origin ) { + try { + await reaction.message.edit( RequestsUtil.getResponseMessage( origin ) ); + } catch ( error ) { + this.logger.error( error ); + } } } - } - if ( BotConfig.request.ignoreResolutionEmoji !== reaction.emoji.name ) { - TaskScheduler.addOneTimeMessageTask( - reaction.message, - new ResolveRequestMessageTask( reaction.emoji, user ), - BotConfig.request.resolveDelay || 0 - ); + if ( BotConfig.request.ignoreResolutionEmoji !== reaction.emoji.name ) { + TaskScheduler.addOneTimeMessageTask( + reaction.message, + new ResolveRequestMessageTask( reaction.emoji, user ), + BotConfig.request.resolveDelay || 0 + ); + } + } else if ( BulkCommand.currentBulkReactions.has( user.tag ) ) { + BulkCommand.currentBulkReactions.get( user.tag ).push( reaction.message ); + } else { + BulkCommand.currentBulkReactions.set( user.tag, [reaction.message] ); } }; } diff --git a/src/events/request/RequestUnresolveEventHandler.ts b/src/events/request/RequestUnresolveEventHandler.ts index 6ec4043e..03872e42 100644 --- a/src/events/request/RequestUnresolveEventHandler.ts +++ b/src/events/request/RequestUnresolveEventHandler.ts @@ -1,6 +1,7 @@ import { MessageReaction, User } from 'discord.js'; import * as log4js from 'log4js'; import BotConfig, { PrependResponseMessageType } from '../../BotConfig'; +import BulkCommand from '../../commands/BulkCommand'; import TaskScheduler from '../../tasks/TaskScheduler'; import EventHandler from '../EventHandler'; @@ -13,17 +14,28 @@ export default class RequestUnresolveEventHandler implements EventHandler<'messa public onEvent = async ( { emoji, message }: MessageReaction, user: User ): Promise => { this.logger.info( `User ${ user.tag } removed '${ emoji.name }' reaction from request message '${ message.id }'` ); - if ( BotConfig.request.prependResponseMessage == PrependResponseMessageType.WhenResolved ) { - try { - await message.edit( '' ); - } catch ( error ) { - this.logger.error( error ); + if ( BotConfig.request.bulkEmoji !== emoji.name ) { + if ( BotConfig.request.prependResponseMessage == PrependResponseMessageType.WhenResolved ) { + try { + await message.edit( '' ); + } catch ( error ) { + this.logger.error( error ); + } } - } - if ( message.reactions.cache.size <= BotConfig.request.suggestedEmoji.length ) { - this.logger.info( `Cleared message task for request message '${ message.id }'` ); - TaskScheduler.clearMessageTasks( message ); + if ( message.reactions.cache.size <= BotConfig.request.suggestedEmoji.length ) { + this.logger.info( `Cleared message task for request message '${ message.id }'` ); + TaskScheduler.clearMessageTasks( message ); + } + } else if ( BulkCommand.currentBulkReactions.has( user.tag ) ) { + const currentMessages = BulkCommand.currentBulkReactions.get( user.tag ); + for ( let i = 0; i <= currentMessages.length; i++ ) { + const currentMessage = currentMessages[i]; + if ( currentMessage.id === message.id ) { + currentMessages.splice( i, 1 ); + break; + } + } } }; } \ No newline at end of file From 021c83c9aa6b112a19d1791d863d43cfaccd4b72 Mon Sep 17 00:00:00 2001 From: SPGoding <15277496+SPGoding@users.noreply.github.com> Date: Sun, 6 Dec 2020 21:18:48 -0600 Subject: [PATCH 23/28] Fix poll command not working --- src/commands/PollCommand.ts | 8 +++----- src/util/EmojiUtil.ts | 8 ++++---- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/commands/PollCommand.ts b/src/commands/PollCommand.ts index f0ef5008..934ff5e1 100644 --- a/src/commands/PollCommand.ts +++ b/src/commands/PollCommand.ts @@ -7,7 +7,6 @@ import { ReactionsUtil } from '../util/ReactionsUtil'; interface PollOption { emoji: string; - emojiName?: string; rawEmoji: string; text: string; } @@ -109,12 +108,11 @@ export default class PollCommand extends PrefixCommand { } const emoji = optionArgs[1]; - const emojiTest = EmojiUtil.getEmoji( emoji ); - if ( emojiTest ) { + const rawEmoji = EmojiUtil.getEmoji( emoji ); + if ( rawEmoji ) { options.push( { emoji: emoji, - emojiName: emojiTest, - rawEmoji: emojiTest, + rawEmoji: rawEmoji, text: optionArgs[2], } ); } else { diff --git a/src/util/EmojiUtil.ts b/src/util/EmojiUtil.ts index f6eda49f..a3bad84c 100644 --- a/src/util/EmojiUtil.ts +++ b/src/util/EmojiUtil.ts @@ -5,12 +5,12 @@ export class EmojiUtil { const customEmoji = /^/; const unicodeEmoji = emojiRegex(); let rawEmoji: string; - if ( unicodeEmoji.test( args ) ) { - rawEmoji = args; - } else if ( customEmoji.test( args ) ) { + if ( customEmoji.test( args ) ) { rawEmoji = customEmoji.exec( args )[2]; + } else if ( unicodeEmoji.test( args ) ) { + rawEmoji = args; } else { - return; + return undefined; } return rawEmoji; } From ad442bdba63e8c0f76a69737005acf90887d1713 Mon Sep 17 00:00:00 2001 From: chandler05 Date: Mon, 7 Dec 2020 19:07:00 -0600 Subject: [PATCH 24/28] Changes --- src/commands/BulkCommand.ts | 14 +++++--------- src/events/request/RequestResolveEventHandler.ts | 12 +++++++++--- src/events/request/RequestUnresolveEventHandler.ts | 4 ++-- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts index 32530d1a..e286ef5a 100644 --- a/src/commands/BulkCommand.ts +++ b/src/commands/BulkCommand.ts @@ -1,11 +1,10 @@ import { Message } from 'discord.js'; import PrefixCommand from './PrefixCommand'; import Command from './Command'; -import ResolveRequestMessageTask from '../tasks/ResolveRequestMessageTask'; -import TaskScheduler from '../tasks/TaskScheduler'; import { RequestsUtil } from '../util/RequestsUtil'; import { EmojiUtil } from '../util/EmojiUtil'; import BotConfig from '../BotConfig'; +import RequestResolveEventHandler from '../events/request/RequestResolveEventHandler'; export default class BulkCommand extends PrefixCommand { public readonly aliases = ['bulk', 'filter']; @@ -33,16 +32,13 @@ export default class BulkCommand extends PrefixCommand { for ( const bulk of bulkMessages ) { originMessages.push( await RequestsUtil.getOriginMessage( bulk ) ); await bulk.reactions.cache.get( BotConfig.request.bulkEmoji ).users.remove( message.author ); + if ( emoji ) { + const reaction = await bulk.react( emoji ); + await new RequestResolveEventHandler().onEvent( reaction, message.author ); + } } originMessages.forEach( origin => ticketKeys.push( ...RequestsUtil.getTickets( origin.content ) ) ); firstMentioned = ticketKeys[0]; - if ( emoji ) { - bulkMessages.forEach( resolvable => TaskScheduler.addOneTimeMessageTask( - resolvable, - new ResolveRequestMessageTask( emoji, message.author ), - BotConfig.request.resolveDelay || 0 - ) ); - } BulkCommand.currentBulkReactions.delete( message.author.tag ); } else { return false; diff --git a/src/events/request/RequestResolveEventHandler.ts b/src/events/request/RequestResolveEventHandler.ts index 77bc2c24..619942f8 100644 --- a/src/events/request/RequestResolveEventHandler.ts +++ b/src/events/request/RequestResolveEventHandler.ts @@ -39,10 +39,16 @@ export default class RequestResolveEventHandler implements EventHandler<'message BotConfig.request.resolveDelay || 0 ); } - } else if ( BulkCommand.currentBulkReactions.has( user.tag ) ) { - BulkCommand.currentBulkReactions.get( user.tag ).push( reaction.message ); } else { - BulkCommand.currentBulkReactions.set( user.tag, [reaction.message] ); + try { + if ( !BulkCommand.currentBulkReactions.has( user.tag ) ) { + BulkCommand.currentBulkReactions.set( user.tag, [ reaction.message ] ); + } else { + BulkCommand.currentBulkReactions.get( user.tag ).push( reaction.message ); + } + } catch ( error ) { + this.logger.error( error ); + } } }; } diff --git a/src/events/request/RequestUnresolveEventHandler.ts b/src/events/request/RequestUnresolveEventHandler.ts index 639531b8..f5a944d5 100644 --- a/src/events/request/RequestUnresolveEventHandler.ts +++ b/src/events/request/RequestUnresolveEventHandler.ts @@ -3,7 +3,7 @@ import * as log4js from 'log4js'; import BotConfig, { PrependResponseMessageType } from '../../BotConfig'; import BulkCommand from '../../commands/BulkCommand'; import TaskScheduler from '../../tasks/TaskScheduler'; -import { RequestsUtil } from '../../util/RequestsUtil' +import { RequestsUtil } from '../../util/RequestsUtil'; import EventHandler from '../EventHandler'; export default class RequestUnresolveEventHandler implements EventHandler<'messageReactionRemove'> { @@ -16,7 +16,7 @@ export default class RequestUnresolveEventHandler implements EventHandler<'messa this.logger.info( `User ${ user.tag } removed '${ emoji.name }' reaction from request message '${ message.id }'` ); if ( BotConfig.request.bulkEmoji !== emoji.name ) { - await message.edit( message.embeds[0].setColor( RequestsUtil.getEmbedColor() ) ); + await message.edit( message.embeds[0].setColor( RequestsUtil.getEmbedColor() ) ); if ( BotConfig.request.prependResponseMessage == PrependResponseMessageType.WhenResolved ) { try { await message.edit( '' ); From 3bdcbf49d06c21b36b5421b12d23d76d31bf2a03 Mon Sep 17 00:00:00 2001 From: chandler05 <66492208+chandler05@users.noreply.github.com> Date: Tue, 4 May 2021 19:10:45 -0500 Subject: [PATCH 25/28] Fix merge errors --- src/commands/BulkCommand.ts | 3 ++- src/util/RequestsUtil.ts | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts index e286ef5a..9b85fdd8 100644 --- a/src/commands/BulkCommand.ts +++ b/src/commands/BulkCommand.ts @@ -5,6 +5,7 @@ import { RequestsUtil } from '../util/RequestsUtil'; import { EmojiUtil } from '../util/EmojiUtil'; import BotConfig from '../BotConfig'; import RequestResolveEventHandler from '../events/request/RequestResolveEventHandler'; +import MojiraBot from '../MojiraBot'; export default class BulkCommand extends PrefixCommand { public readonly aliases = ['bulk', 'filter']; @@ -34,7 +35,7 @@ export default class BulkCommand extends PrefixCommand { await bulk.reactions.cache.get( BotConfig.request.bulkEmoji ).users.remove( message.author ); if ( emoji ) { const reaction = await bulk.react( emoji ); - await new RequestResolveEventHandler().onEvent( reaction, message.author ); + await new RequestResolveEventHandler( MojiraBot.client.user.id ).onEvent( reaction, message.author ); } } originMessages.forEach( origin => ticketKeys.push( ...RequestsUtil.getTickets( origin.content ) ) ); diff --git a/src/util/RequestsUtil.ts b/src/util/RequestsUtil.ts index f358ac97..77292d08 100644 --- a/src/util/RequestsUtil.ts +++ b/src/util/RequestsUtil.ts @@ -3,7 +3,6 @@ import * as log4js from 'log4js'; import BotConfig from '../BotConfig'; import MentionCommand from '../commands/MentionCommand'; import DiscordUtil from './DiscordUtil'; -import MentionCommand from '../commands/MentionCommand'; import MojiraBot from '../MojiraBot'; interface OriginIds { From af6a76c1f13004353ee89495ad389cb5508ca316 Mon Sep 17 00:00:00 2001 From: chandler05 <66492208+chandler05@users.noreply.github.com> Date: Fri, 14 May 2021 07:51:41 -0500 Subject: [PATCH 26/28] Refactor command to produce different results in different cases, store by user --- src/commands/BulkCommand.ts | 50 +++++++++++-------- .../request/RequestResolveEventHandler.ts | 12 ++--- .../request/RequestUnresolveEventHandler.ts | 11 +--- 3 files changed, 35 insertions(+), 38 deletions(-) diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts index 9b85fdd8..e1b6bd11 100644 --- a/src/commands/BulkCommand.ts +++ b/src/commands/BulkCommand.ts @@ -1,4 +1,4 @@ -import { Message } from 'discord.js'; +import { Message, MessageReaction, User } from 'discord.js'; import PrefixCommand from './PrefixCommand'; import Command from './Command'; import { RequestsUtil } from '../util/RequestsUtil'; @@ -10,7 +10,7 @@ import MojiraBot from '../MojiraBot'; export default class BulkCommand extends PrefixCommand { public readonly aliases = ['bulk', 'filter']; - public static currentBulkReactions = new Map(); + public static currentBulkReactions = new Map(); public async run( message: Message, args: string ): Promise { let emoji: string; @@ -27,46 +27,54 @@ export default class BulkCommand extends PrefixCommand { let firstMentioned: string; try { - const bulkMessages = BulkCommand.currentBulkReactions.get( message.author.tag ); + const bulkMessages = BulkCommand.currentBulkReactions.get( message.author ); const originMessages: Message[] = []; if ( bulkMessages ) { for ( const bulk of bulkMessages ) { originMessages.push( await RequestsUtil.getOriginMessage( bulk ) ); - await bulk.reactions.cache.get( BotConfig.request.bulkEmoji ).users.remove( message.author ); + if ( emoji ) { - const reaction = await bulk.react( emoji ); - await new RequestResolveEventHandler( MojiraBot.client.user.id ).onEvent( reaction, message.author ); + let reaction: MessageReaction; + if ( bulk.reactions.cache.has( emoji ) ) { + reaction = bulk.reactions.cache.get( emoji ); + } else { + reaction = await bulk.react( emoji ); + } + if ( emoji != BotConfig.request.bulkEmoji ) { + await new RequestResolveEventHandler( MojiraBot.client.user.id ).onEvent( reaction, message.author ); + return true; + } else { + await bulk.reactions.cache.get( BotConfig.request.bulkEmoji ).users.remove( message.author ); + } } } originMessages.forEach( origin => ticketKeys.push( ...RequestsUtil.getTickets( origin.content ) ) ); firstMentioned = ticketKeys[0]; - BulkCommand.currentBulkReactions.delete( message.author.tag ); + if ( emoji == BotConfig.request.bulkEmoji ) { + BulkCommand.currentBulkReactions.delete( message.author ); + return true; + } } else { return false; } - } catch { + } catch ( err ) { + Command.logger.error( err ); return false; } const filter = `https://bugs.mojang.com/browse/${ firstMentioned }?jql=key%20in(${ ticketKeys.join( '%2C' ) })`; try { - const filterMessage = await message.channel.send( `${ message.author.toString() } ${ filter }` ); - - const timeout = BotConfig.filterRemovalTimeout; - if ( timeout ) { - await filterMessage.delete( { timeout } ); - } - } catch { + await message.channel.send( `${ message.author.toString() } ${ filter }` ); + } catch ( err ) { + Command.logger.error( err ); return false; } - if ( message.deletable ) { - try { - await message.delete(); - } catch ( err ) { - Command.logger.error( err ); - } + try { + await message.react( '✅' ); + } catch ( err ) { + Command.logger.error( err ); } return true; diff --git a/src/events/request/RequestResolveEventHandler.ts b/src/events/request/RequestResolveEventHandler.ts index 51384176..16a0966d 100644 --- a/src/events/request/RequestResolveEventHandler.ts +++ b/src/events/request/RequestResolveEventHandler.ts @@ -51,14 +51,10 @@ export default class RequestResolveEventHandler implements EventHandler<'message ); } } else { - try { - if ( !BulkCommand.currentBulkReactions.has( user.tag ) ) { - BulkCommand.currentBulkReactions.set( user.tag, [ reaction.message ] ); - } else { - BulkCommand.currentBulkReactions.get( user.tag ).push( reaction.message ); - } - } catch ( error ) { - this.logger.error( error ); + if ( !BulkCommand.currentBulkReactions.has( user ) ) { + BulkCommand.currentBulkReactions.set( user, [ reaction.message ] ); + } else { + BulkCommand.currentBulkReactions.get( user ).push( reaction.message ); } } }; diff --git a/src/events/request/RequestUnresolveEventHandler.ts b/src/events/request/RequestUnresolveEventHandler.ts index 57135516..68857709 100644 --- a/src/events/request/RequestUnresolveEventHandler.ts +++ b/src/events/request/RequestUnresolveEventHandler.ts @@ -43,15 +43,8 @@ export default class RequestUnresolveEventHandler implements EventHandler<'messa this.logger.info( `Cleared message task for request message '${ message.id }'` ); TaskScheduler.clearMessageTasks( message ); } - } else if ( BulkCommand.currentBulkReactions.has( user.tag ) ) { - const currentMessages = BulkCommand.currentBulkReactions.get( user.tag ); - for ( let i = 0; i <= currentMessages.length; i++ ) { - const currentMessage = currentMessages[i]; - if ( currentMessage.id === message.id ) { - currentMessages.splice( i, 1 ); - break; - } - } + } else if ( BulkCommand.currentBulkReactions.has( user ) ) { + BulkCommand.currentBulkReactions.set( user, BulkCommand.currentBulkReactions.get( user ).filter( stored => stored != message ) ); } }; } \ No newline at end of file From fa0fbb0e9ae9ddb51ee8422f7177c38e654bc7fd Mon Sep 17 00:00:00 2001 From: chandler05 <66492208+chandler05@users.noreply.github.com> Date: Fri, 14 May 2021 07:54:13 -0500 Subject: [PATCH 27/28] Fix some formatting --- src/commands/BulkCommand.ts | 2 +- src/util/RequestsUtil.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/BulkCommand.ts b/src/commands/BulkCommand.ts index e1b6bd11..cdcf9499 100644 --- a/src/commands/BulkCommand.ts +++ b/src/commands/BulkCommand.ts @@ -50,7 +50,7 @@ export default class BulkCommand extends PrefixCommand { } originMessages.forEach( origin => ticketKeys.push( ...RequestsUtil.getTickets( origin.content ) ) ); firstMentioned = ticketKeys[0]; - if ( emoji == BotConfig.request.bulkEmoji ) { + if ( emoji == BotConfig.request.bulkEmoji ) { BulkCommand.currentBulkReactions.delete( message.author ); return true; } diff --git a/src/util/RequestsUtil.ts b/src/util/RequestsUtil.ts index d8a4decb..d3497302 100644 --- a/src/util/RequestsUtil.ts +++ b/src/util/RequestsUtil.ts @@ -82,7 +82,7 @@ export class RequestsUtil { ticketMatches.push( ticketMatch[1] ); } return ticketMatches; - } + } // https://stackoverflow.com/a/3426956 private static hashCode( str: string ): number { From a2f84c709b7e9766ecd47c9318baf573da31a9e3 Mon Sep 17 00:00:00 2001 From: chandler05 <66492208+chandler05@users.noreply.github.com> Date: Wed, 19 May 2021 07:55:44 -0500 Subject: [PATCH 28/28] Changes --- src/events/request/RequestResolveEventHandler.ts | 4 ++-- src/tasks/ResolveRequestMessageTask.ts | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/events/request/RequestResolveEventHandler.ts b/src/events/request/RequestResolveEventHandler.ts index 16a0966d..4ca1e61a 100644 --- a/src/events/request/RequestResolveEventHandler.ts +++ b/src/events/request/RequestResolveEventHandler.ts @@ -28,7 +28,6 @@ export default class RequestResolveEventHandler implements EventHandler<'message this.logger.info( `User ${ user.tag } added '${ reaction.emoji.name }' reaction to request message '${ reaction.message.id }'` ); TaskScheduler.clearMessageTasks( reaction.message ); - await reaction.message.edit( reaction.message.embeds[0].setColor( RequestsUtil.getEmbedColor( user ) ) ); if ( BotConfig.request.bulkEmoji !== reaction.emoji.name ) { if ( BotConfig.request.prependResponseMessage == PrependResponseMessageType.WhenResolved @@ -44,9 +43,10 @@ export default class RequestResolveEventHandler implements EventHandler<'message } if ( BotConfig.request.ignoreResolutionEmoji !== reaction.emoji.name ) { + await reaction.message.edit( reaction.message.embeds[0].setColor( RequestsUtil.getEmbedColor( user ) ) ); TaskScheduler.addOneTimeMessageTask( reaction.message, - new ResolveRequestMessageTask( reaction.emoji, user ), + new ResolveRequestMessageTask( reaction.emoji, user, this.botUserId ), BotConfig.request.resolveDelay || 0 ); } diff --git a/src/tasks/ResolveRequestMessageTask.ts b/src/tasks/ResolveRequestMessageTask.ts index e7b2553c..2ec6ffbe 100644 --- a/src/tasks/ResolveRequestMessageTask.ts +++ b/src/tasks/ResolveRequestMessageTask.ts @@ -4,17 +4,20 @@ import DiscordUtil from '../util/DiscordUtil'; import { RequestsUtil } from '../util/RequestsUtil'; import MessageTask from './MessageTask'; import * as log4js from 'log4js'; +import BulkCommand from '../commands/BulkCommand'; export default class ResolveRequestMessageTask extends MessageTask { private static logger = log4js.getLogger( 'ResolveRequestMessageTask' ); private readonly emoji: EmojiResolvable; private readonly user: User; + private readonly botUserId: string; - constructor( emoji: EmojiResolvable, user: User ) { + constructor( emoji: EmojiResolvable, user: User, botUserId: string ) { super(); this.emoji = emoji; this.user = user; + this.botUserId = botUserId; } public async run( copy: Message ): Promise { @@ -33,6 +36,16 @@ export default class ResolveRequestMessageTask extends MessageTask { if ( origin ) { try { + await origin.reactions.cache.forEach( async reaction => { + if ( reaction.emoji.name == BotConfig.request.bulkEmoji ) { + const users = await reaction.users.fetch(); + users.forEach( user => { + if ( user.id != this.botUserId ) { + BulkCommand.currentBulkReactions.set( user, BulkCommand.currentBulkReactions.get( user ).filter( message => origin != message ) ); + } + } ); + } + } ); await origin.reactions.removeAll(); } catch ( error ) { ResolveRequestMessageTask.logger.error( error );