Skip to content

Commit

Permalink
feat(anti-ghostping): remove feature
Browse files Browse the repository at this point in the history
  • Loading branch information
noftaly committed Feb 29, 2024
1 parent 45abe2d commit 9b64ff6
Show file tree
Hide file tree
Showing 3 changed files with 2 additions and 133 deletions.
4 changes: 0 additions & 4 deletions config/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ export const messages = {
},
wrongUserInteractionReply: 'Tu ne peux pas cliquer sur ces boutons, ils sont réservés à {user}.',
},
ghostPing: {
alertSingular: ':warning: **{mentions}**, tu as été mentionné par {user.username} mais le message a été supprimé. :innocent:',
alertPlural: ':warning: **{mentions}**, vous avez été mentionnés par {user.username} mais le message a été supprimé. :innocent:',
},
logs: {
readableEvents: {
[DiscordLogType.MemberNicknameUpdate]: ':label: Changement de surnom',
Expand Down
59 changes: 2 additions & 57 deletions src/listeners/client/messageDelete.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import { Listener } from '@sapphire/framework';
import type { Message } from 'discord.js';
import { AuditLogEvent, User } from 'discord.js';
import pupa from 'pupa';
import { messages } from '@/config/messages';
import { settings } from '@/config/settings';
import { AuditLogEvent } from 'discord.js';
import { ReactionRole } from '@/models/reactionRole';
import * as DiscordLogManager from '@/structures/logs/DiscordLogManager';
import type { GuildMessage } from '@/types';
import { DiscordLogType } from '@/types/database';
import { noop, nullop } from '@/utils';
import { nullop } from '@/utils';

export class MessageDeleteListener extends Listener {
public async run(message: Message): Promise<void> {
Expand Down Expand Up @@ -44,56 +40,5 @@ export class MessageDeleteListener extends Listener {
this.container.caches.reactionRolesIds.delete(message.id);
this.container.logger.debug(`[Reaction Roles] Removed reaction-role message ${message.id} because it was deleted. (url: ${message.url})`);
}

await this._checkAntiGhostPing(message);
}

private async _checkAntiGhostPing(message: GuildMessage): Promise<void> {
// List of all the users that were mentionned in the deleted message.
const userMentions = message.mentions.users.values()
.filter(usr => !usr.bot && usr.id !== message.author.id);
// List of all the roles that were mentionned in the deleted message.
const roleMentions = message.mentions.roles
.values()
.filter(role => !role.managed)
.toArray();
// List of users/roles that were mentionned.
const mentions = [...userMentions, ...roleMentions];

// If no-one was mentionned, then ignore.
if (mentions.length === 0)
return;

// Choose the message (plural if multiple people (or a role) were ghost-ping)
const severalPeopleAffected = mentions.length > 1 || roleMentions.length > 0;
const baseMessage = severalPeopleAffected
? messages.ghostPing.alertPlural
: messages.ghostPing.alertSingular;

const botNotificationMessage = await message.channel.send(
pupa(baseMessage, {
mentions: mentions
.map(mention => (mention instanceof User ? mention.username : mention.name))
.join(', '),
user: message.author,
}),
).catch(noop);
if (!botNotificationMessage)
return;

// If a group of people were ghost-ping, we don't want one people to just remove the alert.
if (severalPeopleAffected)
return;

await botNotificationMessage.react(settings.emojis.remove).catch(noop);
const collector = botNotificationMessage
.createReactionCollector({
filter: (r, user) => (r.emoji.id ?? r.emoji.name) === settings.emojis.remove
&& (user.id === message.mentions.users.first()!.id)
&& !user.bot,
}).on('collect', async () => {
collector.stop();
await botNotificationMessage.delete().catch(noop);
});
}
}
72 changes: 0 additions & 72 deletions src/listeners/client/messageUpdate.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import { Listener } from '@sapphire/framework';
import type { Message } from 'discord.js';
import { User } from 'discord.js';
import pupa from 'pupa';
import { messages } from '@/config/messages';
import { settings } from '@/config/settings';
import * as DiscordLogManager from '@/structures/logs/DiscordLogManager';
import type { GuildMessage } from '@/types';
import { DiscordLogType } from '@/types/database';
import { noop } from '@/utils';

export class MessageUpdateListener extends Listener {
public async run(oldMessage: Message, newMessage: Message): Promise<void> {
Expand All @@ -30,71 +24,5 @@ export class MessageUpdateListener extends Listener {
guildId: newMessage.guild.id,
severity: 1,
});

await this._checkAntiGhostPing(oldMessage, newMessage);
}

private async _checkAntiGhostPing(oldMessage: GuildMessage, newMessage: GuildMessage): Promise<void> {
// List of all users that were mentionned in the old message.
const oldUserMentions = oldMessage.mentions.users.values()
.filter(usr => !usr.bot && usr.id !== newMessage.author.id);
// List of all roles that were mentionned in the old message.
const oldRoleMentions = oldMessage.mentions.roles.values()
.filter(role => !role.managed);
// List of usernames / roles name's that were mentionned in the old message.
const oldMentions = [...oldUserMentions, ...oldRoleMentions];

// List of all users that are mentionned in the new message.
const newUserMentions = newMessage.mentions.users.values()
.filter(usr => !usr.bot && usr.id !== newMessage.author.id);
// List of all roles that are mentionned in the new message.
const newRoleMentions = newMessage.mentions.roles.values()
.filter(role => !role.managed);
// List of usernames / roles name's that are mentionned in the new message.
const newMentions = [...newUserMentions, ...newRoleMentions];

// Filter out all the mentions that were in the previous message *and* in the new message.
const deletedMentions = oldMentions.filter(
oldMention => !newMentions.some(newMention => oldMention.id === newMention.id),
);
if (deletedMentions.length === 0)
return;

// Get all the deleted role mentions
const hasDeletedRoleMentions = oldRoleMentions.some(
oldRoleMention => !newRoleMentions.some(newRoleMention => oldRoleMention.id === newRoleMention.id),
);

// Choose the message (plural if multiple people (or a role) were ghost-ping)
const severalPeopleAffected = deletedMentions.length > 1 || hasDeletedRoleMentions;
const baseMessage = severalPeopleAffected
? messages.ghostPing.alertPlural
: messages.ghostPing.alertSingular;

const botNotificationMessage = await newMessage.channel.send(
pupa(baseMessage, {
mentions: deletedMentions
.map(mention => (mention instanceof User ? mention.username : mention.name))
.join(', '),
user: newMessage.author,
}),
).catch(noop);
if (!botNotificationMessage)
return;

// If a group of people were ghost-ping, we don't want one people to just remove the alert.
if (severalPeopleAffected)
return;

await botNotificationMessage.react(settings.emojis.remove).catch(noop);
const collector = botNotificationMessage
.createReactionCollector({
filter: (r, user) => (r.emoji.id ?? r.emoji.name) === settings.emojis.remove
&& (user.id === deletedMentions[0].id)
&& !user.bot,
}).on('collect', async () => {
collector.stop();
await botNotificationMessage.delete().catch(noop);
});
}
}

0 comments on commit 9b64ff6

Please sign in to comment.