Add Guild and CustomActivity auditing
This commit is contained in:
parent
f1767c915c
commit
bc5f7a0473
|
@ -1,5 +1,5 @@
|
|||
import config from '../../config.ts';
|
||||
import { ApplicationCommandOptionTypes, ApplicationCommandTypes, Bot, DiscordEmbedField, Interaction, InteractionResponseTypes } from '../../deps.ts';
|
||||
import { ApplicationCommandOptionTypes, ApplicationCommandTypes, BotWithCache, DiscordEmbedField, Interaction, InteractionResponseTypes } from '../../deps.ts';
|
||||
import { infoColor2, isLFGChannel, somethingWentWrong } from '../commandUtils.ts';
|
||||
import { dbClient } from '../db/client.ts';
|
||||
import { queries } from '../db/common.ts';
|
||||
|
@ -7,8 +7,20 @@ import { CommandDetails } from '../types/commandTypes.ts';
|
|||
import utils from '../utils.ts';
|
||||
import { auditSlashName } from './slashCommandNames.ts';
|
||||
|
||||
type DupeAct = {
|
||||
upperActTitle?: string;
|
||||
upperActSubtitle?: string;
|
||||
dupeCount: number;
|
||||
};
|
||||
|
||||
type DBSizeTable = {
|
||||
table: string;
|
||||
size: number;
|
||||
rows: number;
|
||||
};
|
||||
|
||||
const auditDbName = 'database';
|
||||
const auditCustomActivities = 'custom-activities';
|
||||
const auditCustomActivitiesName = 'custom-activities';
|
||||
const auditGuildName = 'guilds';
|
||||
|
||||
const details: CommandDetails = {
|
||||
|
@ -23,7 +35,7 @@ const details: CommandDetails = {
|
|||
description: `Developer Command: Checks ${config.name}'s DB size.`,
|
||||
},
|
||||
{
|
||||
name: auditCustomActivities,
|
||||
name: auditCustomActivitiesName,
|
||||
type: ApplicationCommandOptionTypes.SubCommand,
|
||||
description: 'Developer Command: Checks for duplicate custom activities.',
|
||||
},
|
||||
|
@ -35,18 +47,18 @@ const details: CommandDetails = {
|
|||
],
|
||||
};
|
||||
|
||||
const execute = async (bot: Bot, interaction: Interaction) => {
|
||||
const execute = async (bot: BotWithCache, interaction: Interaction) => {
|
||||
if (interaction.member && interaction.guildId && interaction.data?.options?.[0].options) {
|
||||
dbClient.execute(queries.callIncCnt('cmd-audit')).catch((e) => utils.commonLoggers.dbError('audit.ts@inc', 'call sproc INC_CNT on', e));
|
||||
const auditName = interaction.data.options[0].name;
|
||||
switch (auditName) {
|
||||
case auditDbName: {
|
||||
// Get DB statistics
|
||||
const auditQuery = await dbClient.query(`SELECT * FROM db_size;`).catch((e) => utils.commonLoggers.dbError('audit.ts@dbSize', 'query', e));
|
||||
const auditQuery: Array<DBSizeTable> = await dbClient.query(`SELECT * FROM db_size;`).catch((e) => utils.commonLoggers.dbError('audit.ts@dbSize', 'query', e));
|
||||
|
||||
// Turn all tables into embed fields, currently only properly will handle 25 tables, but we'll fix that when group up gets 26 tables
|
||||
const embedFields: Array<DiscordEmbedField> = [];
|
||||
auditQuery.forEach((row: any) => {
|
||||
auditQuery.forEach((row) => {
|
||||
embedFields.push({
|
||||
name: `${row.table}`,
|
||||
value: `**Size:** ${row.size} MB
|
||||
|
@ -54,27 +66,129 @@ const execute = async (bot: Bot, interaction: Interaction) => {
|
|||
inline: true,
|
||||
});
|
||||
});
|
||||
bot.helpers.sendInteractionResponse(
|
||||
interaction.id,
|
||||
interaction.token,
|
||||
{
|
||||
bot.helpers
|
||||
.sendInteractionResponse(interaction.id, interaction.token, {
|
||||
type: InteractionResponseTypes.ChannelMessageWithSource,
|
||||
data: {
|
||||
flags: isLFGChannel(interaction.guildId || 0n, interaction.channelId || 0n),
|
||||
embeds: [{
|
||||
embeds: [
|
||||
{
|
||||
color: infoColor2,
|
||||
title: 'Database Audit',
|
||||
description: 'Lists all tables with their current size and row count.',
|
||||
timestamp: new Date().getTime(),
|
||||
fields: embedFields.slice(0, 25),
|
||||
}],
|
||||
},
|
||||
],
|
||||
},
|
||||
).catch((e: Error) => utils.commonLoggers.interactionSendError('audit.ts@dbSize', interaction, e));
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.interactionSendError('audit.ts@dbSize', interaction, e));
|
||||
break;
|
||||
}
|
||||
case auditCustomActivitiesName: {
|
||||
const dupActTitles: Array<DupeAct> = await dbClient.query(
|
||||
`SELECT UPPER(activityTitle) as upperActTitle, COUNT(*) as dupeCount FROM custom_activities GROUP BY upperActTitle HAVING dupeCount > 1;`,
|
||||
).catch((e) => utils.commonLoggers.dbError('audit.ts@customActTitle', 'query', e));
|
||||
const dupActSubTitles: Array<DupeAct> = await dbClient.query(
|
||||
`SELECT UPPER(activitySubtitle) as upperActSubtitle, COUNT(*) as dupeCount FROM custom_activities GROUP BY upperActSubtitle HAVING dupeCount > 1;`,
|
||||
).catch((e) => utils.commonLoggers.dbError('audit.ts@customActSubTitle', 'query', e));
|
||||
const dupActs: Array<DupeAct> = await dbClient
|
||||
.query(
|
||||
`SELECT UPPER(activityTitle) as upperActTitle, UPPER(activitySubtitle) as upperActSubtitle, COUNT(*) as dupeCount FROM custom_activities GROUP BY upperActTitle, upperActSubtitle HAVING dupeCount > 1;`,
|
||||
)
|
||||
.catch((e) => utils.commonLoggers.dbError('audit.ts@customAct', 'query', e));
|
||||
|
||||
bot.helpers
|
||||
.sendInteractionResponse(interaction.id, interaction.token, {
|
||||
type: InteractionResponseTypes.ChannelMessageWithSource,
|
||||
data: {
|
||||
flags: isLFGChannel(interaction.guildId || 0n, interaction.channelId || 0n),
|
||||
content: 'Duplicate Custom Activity Titles, Subtitles, and Activities:',
|
||||
embeds: [
|
||||
{
|
||||
color: infoColor2,
|
||||
title: 'Duplicate Activity Titles:',
|
||||
description: dupActTitles.map((dupAct) => `${dupAct.upperActTitle}: ${dupAct.dupeCount}`).join('\n'),
|
||||
timestamp: new Date().getTime(),
|
||||
},
|
||||
{
|
||||
color: infoColor2,
|
||||
title: 'Duplicate Activity Subtitles:',
|
||||
description: dupActSubTitles.map((dupAct) => `${dupAct.upperActSubtitle}: ${dupAct.dupeCount}`).join('\n'),
|
||||
timestamp: new Date().getTime(),
|
||||
},
|
||||
{
|
||||
color: infoColor2,
|
||||
title: 'Duplicate Activities (Title/Subtitle):',
|
||||
description: dupActs.map((dupAct) => `${dupAct.upperActTitle}/${dupAct.upperActSubtitle}: ${dupAct.dupeCount}`).join('\n'),
|
||||
timestamp: new Date().getTime(),
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.interactionSendError('audit.ts@dbSize', interaction, e));
|
||||
break;
|
||||
}
|
||||
case auditGuildName: {
|
||||
let totalCount = 0;
|
||||
let auditText = '';
|
||||
|
||||
bot.guilds.forEach((guild) => {
|
||||
totalCount += guild.memberCount;
|
||||
auditText += `Guild: ${guild.name} (${guild.id})
|
||||
Owner: ${guild.ownerId}
|
||||
Tot mem: ${guild.memberCount}
|
||||
|
||||
`;
|
||||
});
|
||||
|
||||
const b = await new Blob([auditText as BlobPart], { 'type': 'text' });
|
||||
const tooBig = await new Blob(['tooBig' as BlobPart], { 'type': 'text' });
|
||||
|
||||
bot.helpers
|
||||
.sendInteractionResponse(interaction.id, interaction.token, {
|
||||
type: InteractionResponseTypes.ChannelMessageWithSource,
|
||||
data: {
|
||||
flags: isLFGChannel(interaction.guildId || 0n, interaction.channelId || 0n),
|
||||
embeds: [{
|
||||
color: infoColor2,
|
||||
title: 'Guilds Audit',
|
||||
description: `Shows details of the guilds that ${config.name} serves.
|
||||
|
||||
Please see attached file for audit details on cached guilds and members.`,
|
||||
fields: [
|
||||
{
|
||||
name: 'Total Guilds:',
|
||||
value: `${bot.guilds.size}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Uncached Guilds:',
|
||||
value: `${bot.dispatchedGuildIds.size}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Total Members\n(may be artificially higher if 1 user is in multiple guilds the bot is in):',
|
||||
value: `${totalCount}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Average members per guild:',
|
||||
value: `${(totalCount / bot.guilds.size).toFixed(2)}`,
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
timestamp: new Date().getTime(),
|
||||
}],
|
||||
file: {
|
||||
'blob': b.size > 8388290 ? tooBig : b,
|
||||
'name': 'auditDetails.txt',
|
||||
},
|
||||
},
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.interactionSendError('audit.ts@guilds', interaction, e));
|
||||
break;
|
||||
}
|
||||
case auditCustomActivities:
|
||||
case auditGuildName:
|
||||
default:
|
||||
somethingWentWrong(bot, interaction, `auditNameNotHandled@${auditName}`);
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue