Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reject exact duplicate requests #225

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ projects:
request:
invalidTicketEmoji: ⏸
noLinkEmoji: ⛔
warningLifetime: 5000
duplicateRequestEmoji: 🔁
warningLifetime: 7500
waitingEmoji: ⌛

invalidRequestJql: created > -24h
Expand Down
2 changes: 2 additions & 0 deletions src/BotConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export class RequestConfig {

public invalidTicketEmoji: string;
public noLinkEmoji: string;
public duplicateRequestEmoji: string;
public warningLifetime: number;
public invalidRequestJql: string;
public waitingEmoji: string;
Expand All @@ -48,6 +49,7 @@ export class RequestConfig {

this.invalidTicketEmoji = config.get( 'request.invalidTicketEmoji' );
this.noLinkEmoji = config.get( 'request.noLinkEmoji' );
this.duplicateRequestEmoji = config.get( 'request.duplicateRequestEmoji' );
this.warningLifetime = config.get( 'request.warningLifetime' );
this.invalidRequestJql = config.get( 'request.invalidRequestJql' );
this.waitingEmoji = config.get( 'request.waitingEmoji' );
Expand Down
24 changes: 23 additions & 1 deletion src/events/request/RequestEventHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export default class RequestEventHandler implements EventHandler<'message'> {
return;
}

if ( BotConfig.request.invalidRequestJql ) {
if ( BotConfig.request.invalidTicketEmoji && BotConfig.request.invalidRequestJql ) {
if ( !await RequestsUtil.checkTicketValidity( tickets ) ) {
try {
await origin.react( BotConfig.request.invalidTicketEmoji );
Expand All @@ -84,6 +84,28 @@ export default class RequestEventHandler implements EventHandler<'message'> {
const internalChannelId = this.internalChannels.get( origin.channel.id );
const internalChannel = await DiscordUtil.getChannel( internalChannelId );

if ( BotConfig.request.duplicateRequestEmoji && internalChannel instanceof TextChannel ) {
const match = RequestsUtil.findExactMatchInPendingRequests( origin, internalChannel );

if ( match != origin ) {
const parent = await RequestsUtil.getOriginMessage( match );

try {
await origin.react( BotConfig.request.duplicateRequestEmoji );
} catch ( error ) {
this.logger.error( error );
}

try {
const warning = await origin.channel.send( `${ origin.author }, your request (<${ origin.url }>) has already been requested at <${ parent.url }>.` );
await DiscordUtil.deleteWithDelay( warning, BotConfig.request.warningLifetime );
} catch ( error ) {
this.logger.error( error );
}
return;
}
}

if ( requestLimit && requestLimit >= 0 && internalChannel instanceof TextChannel ) {
const internalChannelUserMessages = internalChannel.messages.cache
.filter( message => message.embeds.length > 0 && message.embeds[0].author.name == origin.author.tag )
Expand Down
12 changes: 11 additions & 1 deletion src/util/RequestsUtil.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EmbedField, Message, PartialMessage, Snowflake, TextChannel, User } from 'discord.js';
import { EmbedField, Message, PartialMessage, Snowflake, TextChannel, User, TextBasedChannels } from 'discord.js';
import * as log4js from 'log4js';
import BotConfig from '../BotConfig';
import DiscordUtil from './DiscordUtil';
Expand Down Expand Up @@ -145,4 +145,14 @@ export class RequestsUtil {
return content.replace( /([[\]\\])/gm, '\\$1' )
.replace( regex, '[$<ticketid>$<anchor>](https://bugs.mojang.com/browse/$<ticketid>$<query>$<anchor>)' );
}

public static findExactMatchInPendingRequests( origin: Message, internalChannel: TextBasedChannels ): Message {
const matcher = this.replaceTicketReferencesWithRichLinks( origin.content );
if ( internalChannel instanceof TextChannel ) {
const matches = internalChannel.messages.cache.filter( message => message.embeds.length > 0 && message.embeds[0].description == matcher );
return matches.size > 0 ? matches.first() : origin;
} else {
return origin;
}
}
}