Skip to content

Commit

Permalink
Ping reporter
Browse files Browse the repository at this point in the history
  • Loading branch information
Larsundso committed Feb 4, 2025
1 parent 3a1fe41 commit 0d67f38
Show file tree
Hide file tree
Showing 11 changed files with 233 additions and 4 deletions.
5 changes: 5 additions & 0 deletions src/BaseClient/Other/constants/settingsEditorTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -338,4 +338,9 @@ export default {
botSecret: CT.EditorTypes.BotToken,
allowedUsers: CT.EditorTypes.Users,
},
[CT.SettingNames.PingReporter]: {
roleIds: CT.EditorTypes.Roles,
channelIds: CT.EditorTypes.Channels,
cooldown: CT.EditorTypes.Duration,
},
};
3 changes: 2 additions & 1 deletion src/BaseClient/Other/language/events/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@ import interactionCreate from './logs/interactionCreate.js';
import logs from './logs/logs.js';
import ready from './logs/ready.js';
import vote from './logs/vote.js';
import messageCreate from './messageCreate.js';

export default (t: CT.Language) => ({
...t.JSON.events,
logs: logs(t),
guildMemberUpdate: guildMemberUpdate(t),
guildMemberAdd: guildMemberAdd(t),
censor: t.JSON.events.censor,
ready: ready(t),
vote: vote(t),
appeal: appeal(t),
interactionCreate: interactionCreate(t),
messageCreate: messageCreate(t),
});
15 changes: 15 additions & 0 deletions src/BaseClient/Other/language/events/messageCreate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { Channel, Role, User } from 'discord.js';
import * as CT from '../../../../Typings/Typings.js';

export default (t: CT.Language) => ({
...t.JSON.events.messageCreate,
pingReporter: {
...t.JSON.events.messageCreate.pingReporter,
desc: (role: Role, channel: Channel, user: User) =>
t.stp(t.JSON.events.messageCreate.pingReporter.desc, {
role: t.languageFunction.getRole(role),
channel: t.languageFunction.getChannel(channel, t.channelTypes[channel.type]),
user: t.languageFunction.getUser(user),
}),
},
});
4 changes: 2 additions & 2 deletions src/Commands/SlashCommands/settings/custom-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ export const getEmbeds: CT.SettingsFile<typeof name>['getEmbeds'] = async (
value: settings.token
? client.util.util.makeInlineCode(
`${settings.token.split('.')[0]}.${'*'.repeat(
settings.token.split('.')[1].length,
)}.${'*'.repeat(settings.token.split('.')[2].length)}`,
settings.token.split('.')[1]?.length,
)}.${'*'.repeat(settings.token.split('.')[2]?.length)}`,
)
: language.t.None,
},
Expand Down
106 changes: 106 additions & 0 deletions src/Commands/SlashCommands/settings/roles/ping-reporter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import * as Discord from 'discord.js';
import client from '../../../../BaseClient/Bot/Client.js';
import * as CT from '../../../../Typings/Typings.js';

const name = CT.SettingNames.PingReporter;

export default async (cmd: Discord.ChatInputCommandInteraction) => {
if (!cmd.inCachedGuild()) return;

const language = await client.util.getLanguage(cmd.guild.id);
const lan = language.slashCommands.settings.categories[name];
const { embedParsers, buttonParsers } = client.util.settingsHelpers;
const settings = await client.util.DataBase[CT.SettingsName2TableName[name]]
.findUnique({ where: { guildid: cmd.guildId } })
.then(
(r) =>
r ??
client.util.DataBase[CT.SettingsName2TableName[name]].create({
data: { guildid: cmd.guildId },
}),
);

cmd.reply({
embeds: await getEmbeds(embedParsers, settings, language, lan, cmd.guild),
components: await getComponents(buttonParsers, settings, language),
ephemeral: true,
});
};

export const getEmbeds: CT.SettingsFile<typeof name>['getEmbeds'] = (
embedParsers,
settings,
language,
lan,
) => [
{
author: embedParsers.author(language, lan),
description: `${lan.description}\n${
client.util.constants.tutorials[name as keyof typeof client.util.constants.tutorials]?.length
? `${language.slashCommands.settings.tutorial}\n${client.util.constants.tutorials[
name as keyof typeof client.util.constants.tutorials
].map((t) => `[${t.name}](${t.link})`)}`
: ''
}`,
fields: [
{
name: language.slashCommands.settings.active,
value: embedParsers.boolean(settings?.active, language),
inline: true,
},
{
name: lan.fields.cooldown.name,
value: embedParsers.time(
settings?.cooldown ? Number(settings.cooldown) * 1000 : null,
language,
),
inline: true,
},
{
name: lan.fields.roleIds.name,
value: embedParsers.roles(settings?.roleIds, language),
inline: false,
},
{
name: lan.fields.channelIds.name,
value: embedParsers.channels(settings?.channelIds, language),
inline: false,
},
],
},
];

export const getComponents: CT.SettingsFile<typeof name>['getComponents'] = (
buttonParsers,
settings,
language,
) => [
{
type: Discord.ComponentType.ActionRow,
components: [
buttonParsers.global(language, !!settings?.active, CT.GlobalDescType.Active, name, undefined),
buttonParsers.specific(language, settings?.cooldown, 'cooldown', name, undefined),
],
},
{
type: Discord.ComponentType.ActionRow,
components: [
buttonParsers.specific(
language,
settings?.roleIds,
'roleIds',
name,
undefined,
CT.EditorTypes.Role,
),
buttonParsers.specific(
language,
settings?.channelIds,
'channelIds',
name,
undefined,
CT.EditorTypes.Channel,
),
],
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import notificationThread from './notificationThread.js';
import other from './other.js';
import stickyMessage from './stickyMessage.js';
import tta from './tta.js';
import pingReporter from './pingReporter.js';

import dmLog from './dmLog.js';
import dmResponse from './dmResponse.js';
Expand All @@ -35,6 +36,7 @@ export default async (msg: Discord.Message) => {
antispam(msg);
notificationThread(msg);
customEmbedThread(msg);
pingReporter(msg);

dmResponse(msg);
} else {
Expand Down
66 changes: 66 additions & 0 deletions src/Events/BotEvents/messageEvents/messageCreate/pingReporter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { ButtonStyle, ComponentType, type APIEmbed, type Message } from 'discord.js';
import Redis from '../../../../BaseClient/Bot/Redis.js';

export default async (msg: Message) => {
if (!msg.inGuild()) return;
if (msg.author.bot) return;
if (!msg.mentions.roles.size) return;

const settings = await msg.client.util.DataBase.pingReport.findUnique({
where: {
guildid: msg.guildId,
roleIds: { hasSome: msg.mentions.roles.map((r) => r.id) },
channelIds: { isEmpty: false },
},
});
if (!settings) return;

const mentionedRoles = msg.mentions.roles.filter((r) => settings.roleIds.includes(r.id));
if (!mentionedRoles.size) return;

const cooldownKeys = await Redis.keys(`${process.env.mainId}:ratelimits:*`);
const rolesWithoutCooldown = mentionedRoles.filter(
(r) => !cooldownKeys.find((c) => c.includes(r.id)),
);
if (!rolesWithoutCooldown.size) return;

const language = await msg.client.util.getLanguage(msg.guildId);
const lan = language.events.messageCreate.pingReporter;
const me = await msg.client.util.getBotMemberFromGuild(msg.guild);

rolesWithoutCooldown.forEach((role) => {
const members = role.members.map((m) => m.id);
if (members.length > 100) return;

Redis.setex(`${process.env.mainId}:ratelimits:${role.id}`, Number(settings.cooldown), 'true');

const content = members.map((m) => `<@${m}>`).join(' ');

const embed: APIEmbed = {
author: { name: lan.author },
description: lan.desc(role, msg.channel, msg.author),
color: msg.client.util.getColor(me),
};

msg.client.util.send(
{ id: settings.channelIds, guildId: msg.guildId },
{
content,
embeds: [embed],
components: [
{
type: ComponentType.ActionRow,
components: [
{
type: ComponentType.Button,
style: ButtonStyle.Link,
label: language.t.JumpToMessage,
url: msg.url,
},
],
},
],
},
);
});
};
28 changes: 27 additions & 1 deletion src/Languages/en-GB.json
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,8 @@
"FailedToMentionSomeRolesInThread": "Failed to mention some Roles in Thread",
"SuppressNotifications": "Supress Notifications",
"IsVoiceMessage": "Voice Message",
"ShouldShowLinkNotDiscordWarning": "Should Show Link not Discord Warning"
"ShouldShowLinkNotDiscordWarning": "Should Show Link not Discord Warning",
"HasSnapshot": "Has Snapshot"
},
"reactions": "Reactions",
"components": "Components",
Expand Down Expand Up @@ -826,6 +827,12 @@
},
"interactionCreate": {
"cooldown": "This Command is on Cooldown"
},
"messageCreate": {
"pingReporter": {
"author": "Role Mentioned",
"desc": "> {{role}}> was mentioned by\n> {{user}}> in\n> {{channel}}"
}
}
},
"punishmentAction": {
Expand Down Expand Up @@ -2552,6 +2559,24 @@
"deleted": "{{setting}} Setting deleted"
},
"categories": {
"ping-reporter": {
"name": "Ping-Report",
"description": "Discord's Push-Notification delivery is somewhat unreliable on large servers.\n**Note:** This requires the Role to have less than 100 Members\n\n**How it works**\n> 1. A Member mentions @Staff to notify them\n> -# - On large Servers Discord will go through every Member and check if they are elligible for a Notification at a very slow Rate. Causing up to Hour long Delays on Push-Notifications\n> 2. Ayako sends a Log-Message into your specified Channel along with a @Mention for every of the Roles Members\n> -# - This causes Discord to start a second Notification-Process, but only on the mentioned Members. Making them receive the Push-Notification almost instantly",
"fields": {
"channelIds": {
"name": "Channel",
"desc": "The Channel to send the Ping-Report to"
},
"roleIds": {
"name": "Roles",
"desc": "The Roles to of which the Members to ping"
},
"cooldown": {
"name": "Cooldown",
"desc": "The Cooldown between Ping-Reports"
}
}
},
"linked-roles-deco": {
"name": "Linked-Roles-Decoration",
"apply": {
Expand Down Expand Up @@ -4181,6 +4206,7 @@
}
},
"t": {
"JumpToMessage": "Jump to Message",
"Website": "Website",
"More": "More",
"useDefaultRP": "Please use the Default RP-Commands (`/hug`, `/pat` etc) if enabled\n`/actions` Commands are for DMs and Servers that don't have Ayako added\n\nIf they aren't enabled, consider asking a Server Administrator to enable them via `/rp manager`",
Expand Down
5 changes: 5 additions & 0 deletions src/SlashCommands/Commands/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ export default new Discord.SlashCommandBuilder()
new Discord.SlashCommandSubcommandGroupBuilder()
.setName('roles')
.setDescription(`Everything about ${process.env.mainName}'s Role Management`)
.addSubcommand(
new Discord.SlashCommandSubcommandBuilder()
.setName('ping-reporter')
.setDescription('Ping Members of a Role when a Role is pinged'),
)
.addSubcommand(
new Discord.SlashCommandSubcommandBuilder()
.setName('linked-roles-deco')
Expand Down
1 change: 1 addition & 0 deletions src/Typings/DataBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,5 @@ export interface DataBaseTables {
customclients: Prisma.customclients;
afksettings: Prisma.afksettings;
linkedRolesDeco: Prisma.linkedRolesDeco;
pingReport: Prisma.pingReport;
}
2 changes: 2 additions & 0 deletions src/Typings/Settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ export enum SettingNames {
CustomClient = 'custom-client',
Afk = 'afk',
LinkedRolesDeco = 'linked-roles-deco',
PingReporter = 'ping-reporter',
}

export const SettingsName2TableName = {
Expand Down Expand Up @@ -198,6 +199,7 @@ export const SettingsName2TableName = {
[SettingNames.CustomClient]: 'customclients',
[SettingNames.Afk]: 'afksettings',
[SettingNames.LinkedRolesDeco]: 'linkedRolesDeco',
[SettingNames.PingReporter]: 'pingReport',
} as const;

export type CRUDResult<T extends keyof typeof SettingsName2TableName> = Promise<
Expand Down

0 comments on commit 0d67f38

Please sign in to comment.