Implement slash commands for most things, some bugfixes and god knows what else

This commit is contained in:
Ean Milligan 2025-07-22 01:19:20 -04:00
parent 633e786d95
commit f1025ce129
30 changed files with 1076 additions and 662 deletions

View File

@ -39,6 +39,7 @@
"events/": "./src/events/",
"utils/": "./src/utils/",
"src/api.ts": "./src/api.ts",
"src/events.ts": "./src/events.ts"
"src/events.ts": "./src/events.ts",
"src/mod.d.ts": "./src/mod.d.ts"
}
}

View File

@ -28,7 +28,7 @@ import utils from 'utils/utils.ts';
const getUserIdForEmbed = (rollRequest: QueuedRoll): bigint => {
if (rollRequest.apiRoll) return rollRequest.api.userId;
if (rollRequest.ddRoll) return rollRequest.dd.originalMessage.authorId;
if (rollRequest.ddRoll) return rollRequest.dd.authorId;
return 0n;
};
@ -227,7 +227,7 @@ Please click on "<@${botId}> *Click to see attachment*" above this message to se
file: pubAttachments,
})
.then((attachmentMsg) => toggleWebView(attachmentMsg, getUserIdForEmbed(rollRequest).toString(), false))
.catch((e) => console.log(e));
.catch((e) => utils.commonLoggers.messageSendError('workerComplete.ts:230', newMsg as DiscordenoMessage, e));
} else {
pubAttachments.forEach((file) => {
newMsg &&
@ -237,7 +237,7 @@ Please click on "<@${botId}> *Click to see attachment*" above this message to se
file,
})
.then((attachmentMsg) => toggleWebView(attachmentMsg, getUserIdForEmbed(rollRequest).toString(), false))
.catch((e) => console.log(e));
.catch((e) => utils.commonLoggers.messageSendError('workerComplete.ts:240', newMsg as DiscordenoMessage, e));
});
}
}
@ -271,7 +271,7 @@ Please click on "<@${botId}> *Click to see attachment*" above this message to se
embeds: [
(
await generateRollEmbed(
rollRequest.dd.originalMessage.authorId,
rollRequest.dd.authorId,
<SolvedRoll> {
error: true,
errorMsg:

View File

@ -28,7 +28,7 @@ export const terminateWorker = async (rollWorker: Worker, rollRequest: QueuedRol
embeds: [
(
await generateRollEmbed(
rollRequest.dd.originalMessage.authorId,
rollRequest.dd.authorId,
<SolvedRoll> {
error: true,
errorCode: 'TooComplex',

View File

@ -26,6 +26,7 @@ interface DDQueuedRoll extends BaseQueuedRoll {
dd: {
myResponse: DiscordenoMessage;
originalMessage: DiscordenoMessage;
authorId: bigint;
};
}
interface TestResultFail {

View File

@ -29,6 +29,9 @@ export const cmdSplitRegex = new RegExp(`(${escapePrefixPostfix(config.prefix)})
// breaks the string on the following: (\*\*) ** for exponents ([+()*/^] for basic algebra (?<![d%])% for breaking on d%%%% dice correctly (?<![rsfop!=<>])- for breaking on - correctly with fate dice) (x\d+(\.\d*)?) x# for variables
export const mathSplitRegex = /(\*\*)|([+()*/^]|(?<![d%])%|(?<![rsfop!=<>])-)|([xy]\d+(\.\d*)?)/g;
// breaks the string on spaces and newlines, but keeps them in the array to allow for recreating the input correctly
export const argSpacesSplitRegex = /([ \n]+)/g;
// Internal is used for recursive text replacement, these will always be the top level as they get replaced with config.prefix/postfix when exiting each level
export const openInternal = '\u2045';
export const closeInternal = '\u2046';

View File

@ -1,24 +1,30 @@
import { alias } from 'commands/aliasCmd.ts';
import { upsertSlashCommands } from '@discordeno';
import { alias, aliasSC } from 'commands/aliasCmd.ts';
import { api } from 'commands/apiCmd.ts';
import { audit } from 'commands/audit.ts';
import { emoji } from 'commands/emoji.ts';
import { handleMentions } from 'commands/handleMentions.ts';
import { heatmap } from 'commands/heatmap.ts';
import { help } from 'commands/help.ts';
import { info } from 'commands/info.ts';
import { heatmap, heatmapSC } from 'commands/heatmap.ts';
import { help, helpSC } from 'commands/help.ts';
import { info, infoSC } from 'commands/info.ts';
import { optIn } from 'commands/optIn.ts';
import { optOut } from 'commands/optOut.ts';
import { ping } from 'commands/ping.ts';
import { privacy } from 'commands/privacy.ts';
import { rip } from 'commands/rip.ts';
import { report } from 'commands/report.ts';
import { roll } from 'commands/roll.ts';
import { privacy, privacySC } from 'commands/privacy.ts';
import { report, reportSC } from 'commands/report.ts';
import { rip, ripSC } from 'commands/rip.ts';
import { roll, rollSC } from 'commands/roll.ts';
import { rollHelp } from 'commands/rollHelp.ts';
import { stats } from 'commands/stats.ts';
import { toggleInline } from 'commands/toggleInline.ts';
import { version } from 'commands/version.ts';
import { stats, statsSC } from 'commands/stats.ts';
import { toggleInline, toggleInlineSC } from 'commands/toggleInline.ts';
import { version, versionSC } from 'commands/version.ts';
export default {
export const announceSlashCommands = () => {
upsertSlashCommands([aliasSC, heatmapSC, helpSC, infoSC, privacySC, reportSC, ripSC, rollSC, statsSC, toggleInlineSC, versionSC]);
};
export const commands = {
alias,
api,
audit,
@ -31,11 +37,25 @@ export default {
optOut,
ping,
privacy,
rip,
report,
rip,
roll,
rollHelp,
stats,
toggleInline,
version,
};
export const slashCommandDetails = {
aliasSC,
heatmapSC,
helpSC,
infoSC,
privacySC,
ripSC,
reportSC,
rollSC,
statsSC,
toggleInlineSC,
versionSC,
};

View File

@ -1,4 +1,4 @@
import { DiscordenoMessage } from '@discordeno';
import { ApplicationCommandOption, CreateGlobalApplicationCommand, DiscordApplicationCommandOptionTypes, DiscordenoMessage } from '@discordeno';
import aliasCommands from 'commands/aliasCmd/_index.ts';
@ -9,11 +9,122 @@ import { queries } from 'db/common.ts';
import { failColor } from 'embeds/colors.ts';
import { SlashCommandInteractionWithGuildId } from 'src/mod.d.ts';
import utils from 'utils/utils.ts';
export const alias = (message: DiscordenoMessage, argSpaces: string[]) => {
const aliasNameOption = (action: string, rename = false): ApplicationCommandOption => ({
type: DiscordApplicationCommandOptionTypes.String,
name: `alias-name${rename ? '-new' : ''}`,
description: `The ${rename ? 'new ' : ''}name of the alias${rename ? '' : `you wish to ${action}`}.`,
required: true,
});
const rollStringOption = (action: string): ApplicationCommandOption => ({
type: DiscordApplicationCommandOptionTypes.String,
name: 'roll-string',
description: `The the full roll string to ${action}.`,
required: true,
});
const verificationCodeOption: ApplicationCommandOption = {
type: DiscordApplicationCommandOptionTypes.String,
name: 'verification-code',
description: 'The four digit confirmation code for deletion. Can be left blank to generate one.',
required: false,
};
const aliasOptions = (guildMode: boolean): ApplicationCommandOption[] => [
{
type: DiscordApplicationCommandOptionTypes.SubCommand,
name: 'help',
description: `Opens the help library to the ${guildMode ? 'Guild' : 'Personal'} Mode Alias System section.`,
},
{
type: DiscordApplicationCommandOptionTypes.SubCommand,
name: 'list-all',
description: `List all available aliases ${guildMode ? 'in this Guild' : 'on your account'}.`,
},
{
type: DiscordApplicationCommandOptionTypes.SubCommand,
name: 'view',
description: `Preview the roll string behind an alias ${guildMode ? 'in this Guild' : 'on your account'}.`,
options: [aliasNameOption('view')],
},
{
type: DiscordApplicationCommandOptionTypes.SubCommand,
name: 'create',
description: `Create a new alias ${guildMode ? 'in this Guild' : 'on your account'}.`,
options: [aliasNameOption('create'), rollStringOption('create')],
},
{
type: DiscordApplicationCommandOptionTypes.SubCommand,
name: 'replace',
description: `Update an alias ${guildMode ? 'in this Guild' : 'on your account'} with a new roll string.`,
options: [aliasNameOption('replace'), rollStringOption('replace the old one with')],
},
{
type: DiscordApplicationCommandOptionTypes.SubCommand,
name: 'rename',
description: `Rename an alias ${guildMode ? 'in this Guild' : 'on your account'}.`,
options: [aliasNameOption('rename'), aliasNameOption('rename', true)],
},
{
type: DiscordApplicationCommandOptionTypes.SubCommand,
name: 'delete-one',
description: `Delete an alias from ${guildMode ? 'this Guild' : 'your account'}.`,
options: [aliasNameOption('delete'), verificationCodeOption],
},
{
type: DiscordApplicationCommandOptionTypes.SubCommand,
name: 'delete-all',
description: `Delete all aliases from ${guildMode ? 'this Guild' : 'your account'}.`,
options: [verificationCodeOption],
},
{
type: DiscordApplicationCommandOptionTypes.SubCommand,
name: 'copy',
description: `Copy an alias from ${guildMode ? 'this Guild' : 'your account'} to ${guildMode ? 'your account' : 'this Guild'}.`,
options: [aliasNameOption(`copy to ${guildMode ? 'your personal account' : 'this guild'}`)],
},
{
type: DiscordApplicationCommandOptionTypes.SubCommand,
name: 'run',
description: `Runs the specified ${guildMode ? 'Guild' : 'Personal'} alias.`,
options: [
aliasNameOption('run'),
{
type: DiscordApplicationCommandOptionTypes.String,
name: 'y-variables',
description: 'A space separated list of numbers. Can be left blank if an alias does not require any.',
required: false,
},
],
},
];
export const aliasSC: CreateGlobalApplicationCommand = {
name: 'alias',
description: 'Custom Roll Alias system, create and use Roll Aliases for easily reusing the same rolls.',
options: [
{
type: DiscordApplicationCommandOptionTypes.SubCommandGroup,
name: 'personal',
description: 'Manage and run Personal aliases.',
options: aliasOptions(false),
},
{
type: DiscordApplicationCommandOptionTypes.SubCommandGroup,
name: 'guild',
description: 'Manage and run Guild aliases.',
options: aliasOptions(true),
},
],
};
export const alias = (msgOrInt: DiscordenoMessage | SlashCommandInteractionWithGuildId, argSpaces: string[]) => {
// Light telemetry to see how many times a command is being run
dbClient.execute(queries.callIncCnt('alias')).catch((e) => utils.commonLoggers.dbError('aliasCmd.ts:16', 'call sproc INC_CNT on', e));
dbClient.execute(queries.callIncCnt('alias')).catch((e) => utils.commonLoggers.dbError('aliasCmd.ts:125', 'call sproc INC_CNT on', e));
// argSpaces will come in with a space or \n before every real arg, so extra shifts exist to remove them
argSpaces.shift();
@ -27,17 +138,15 @@ export const alias = (message: DiscordenoMessage, argSpaces: string[]) => {
argSpaces.shift();
}
if (guildMode && message.guildId === 0n) {
message
.send({
if (guildMode && BigInt(msgOrInt.guildId) === 0n) {
utils.sendOrInteract(msgOrInt, 'aliasCmd.ts:140', {
embeds: [
{
color: failColor,
title: 'Guild Aliases can only be modified from within the desired guild.',
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('aliasCmd.ts:38', message, e));
});
return;
}
@ -46,44 +155,45 @@ export const alias = (message: DiscordenoMessage, argSpaces: string[]) => {
case 'h':
case '?':
case '':
message.send(generateHelpMessage('alias')).catch((e: Error) => utils.commonLoggers.messageSendError('aliasCmd.ts:47', message, e));
utils.sendOrInteract(msgOrInt, 'aliasCmd.ts:156', generateHelpMessage('alias'));
break;
case 'list':
case 'list-all':
aliasCommands.list(message, guildMode);
aliasCommands.list(msgOrInt, guildMode);
break;
case 'add':
case 'create':
case 'set':
aliasCommands.add(message, guildMode, argSpaces);
aliasCommands.add(msgOrInt, guildMode, argSpaces);
break;
case 'update':
case 'replace':
aliasCommands.update(message, guildMode, argSpaces);
aliasCommands.update(msgOrInt, guildMode, argSpaces);
break;
case 'preview':
case 'view':
aliasCommands.view(message, guildMode, argSpaces);
aliasCommands.view(msgOrInt, guildMode, argSpaces);
break;
case 'delete':
case 'remove':
aliasCommands.deleteOne(message, guildMode, argSpaces);
case 'delete-one':
aliasCommands.deleteOne(msgOrInt, guildMode, argSpaces);
break;
case 'delete-all':
case 'remove-all':
aliasCommands.deleteAll(message, guildMode, argSpaces);
aliasCommands.deleteAll(msgOrInt, guildMode, argSpaces);
break;
case 'clone':
case 'copy':
aliasCommands.clone(message, guildMode, argSpaces);
aliasCommands.clone(msgOrInt, guildMode, argSpaces);
break;
case 'rename':
aliasCommands.rename(message, guildMode, argSpaces);
aliasCommands.rename(msgOrInt, guildMode, argSpaces);
break;
case 'run':
case 'execute':
default:
aliasCommands.run(message, guildMode, aliasArg, argSpaces);
aliasCommands.run(msgOrInt, guildMode, aliasArg, argSpaces);
break;
}
};

View File

@ -1,4 +1,5 @@
import { DiscordenoMessage, EmbedField, hasGuildPermissions } from '@discordeno';
import { log, LogTypes as LT } from '@Log4Deno';
import config from '~config';
@ -17,6 +18,8 @@ import dbClient from 'db/client.ts';
import { generateAliasError } from 'embeds/alias.ts';
import { failColor, infoColor1, successColor } from 'embeds/colors.ts';
import { SlashCommandInteractionWithGuildId } from 'src/mod.d.ts';
import utils from 'utils/utils.ts';
interface QueryShape {
@ -31,18 +34,21 @@ const sortYVars = (a: string, b: string) => {
return 0;
};
const handleAddUpdate = async (message: DiscordenoMessage, guildMode: boolean, argSpaces: string[], replaceAlias: boolean) => {
if (guildMode && !(await hasGuildPermissions(message.guildId, message.authorId, ['ADMINISTRATOR']))) {
message
.send({
const handleAddUpdate = async (
msgOrInt: DiscordenoMessage | SlashCommandInteractionWithGuildId,
guildMode: boolean,
argSpaces: string[],
replaceAlias: boolean,
) => {
if (guildMode && !(await hasGuildPermissions(BigInt(msgOrInt.guildId), utils.getAuthorIdFromMessageOrInteraction(msgOrInt), ['ADMINISTRATOR']))) {
utils.sendOrInteract(msgOrInt, 'aliasAddUpdate.ts:43', {
embeds: [
{
color: failColor,
title: `Error: Only Guild Owners and Admins can add/update guild aliases`,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('add.ts:45', message, e));
});
return;
}
@ -50,8 +56,7 @@ const handleAddUpdate = async (message: DiscordenoMessage, guildMode: boolean, a
argSpaces.shift();
if (aliasName.length > config.limits.alias.maxNameLength) {
message
.send({
utils.sendOrInteract(msgOrInt, 'aliasAddUpdate.ts:59', {
embeds: [
{
color: failColor,
@ -60,14 +65,12 @@ const handleAddUpdate = async (message: DiscordenoMessage, guildMode: boolean, a
`\`${aliasName}\` (\`${aliasName.length}\` characters) is longer than the allowed max length of \`${config.limits.alias.maxNameLength}\` characters. Please choose a shorter alias name.`,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('add.ts:64', message, e));
});
return;
}
if (ReservedWords.includes(aliasName?.toLowerCase())) {
message
.send({
utils.sendOrInteract(msgOrInt, 'aliasAddUpdate.ts:74', {
embeds: [
{
color: failColor,
@ -77,8 +80,7 @@ const handleAddUpdate = async (message: DiscordenoMessage, guildMode: boolean, a
You cannot use any of the following reserved words: \`${ReservedWords.join('`, `')}\`.`,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('add.ts:33', message, e));
});
return;
}
@ -86,20 +88,24 @@ You cannot use any of the following reserved words: \`${ReservedWords.join('`, `
const query: QueryShape[] = await dbClient
.query(
`SELECT aliasName FROM aliases WHERE guildid = ? AND userid = ? AND aliasName = ?`,
guildMode ? [message.guildId, 0n, aliasName.toLowerCase()] : [0n, message.authorId, aliasName.toLowerCase()],
guildMode ? [BigInt(msgOrInt.guildId), 0n, aliasName.toLowerCase()] : [0n, utils.getAuthorIdFromMessageOrInteraction(msgOrInt), aliasName.toLowerCase()],
)
.catch((e0) => {
utils.commonLoggers.dbError('add.ts:44', 'query', e0);
message
.send(generateAliasError('DB Query Failed.', `add-q0-${guildMode ? 't' : 'f'}-${aliasName}-${guildMode ? message.guildId : message.authorId}`))
.catch((e: Error) => utils.commonLoggers.messageSendError('add.ts:47', message, e));
utils.sendOrInteract(
msgOrInt,
'aliasAddUpdate.ts:97',
generateAliasError(
'DB Query Failed.',
`add-q0-${guildMode ? 't' : 'f'}-${aliasName}-${guildMode ? BigInt(msgOrInt.guildId) : utils.getAuthorIdFromMessageOrInteraction(msgOrInt)}`,
),
);
errorOut = true;
});
if (errorOut) return;
if (!replaceAlias && query.length) {
message
.send({
utils.sendOrInteract(msgOrInt, 'aliasAddUpdate.ts:109', {
embeds: [
{
color: failColor,
@ -107,12 +113,10 @@ You cannot use any of the following reserved words: \`${ReservedWords.join('`, `
description: 'Please choose a different name for this alias.',
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('add.ts:63', message, e));
});
return;
} else if (replaceAlias && !query.length) {
message
.send({
utils.sendOrInteract(msgOrInt, 'aliasAddUpdate.ts:121', {
embeds: [
{
color: failColor,
@ -124,14 +128,15 @@ If you are trying to update an existing alias, but forgot the name, please run t
\`${config.prefix}ra ${guildMode ? 'guild ' : ''}list\``,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('add.ts:63', message, e));
});
return;
}
const rawRollStr = argSpaces.join('').trim();
const newMsg: DiscordenoMessage | void = await message
.send({
const newMsg: DiscordenoMessage | void = await utils.sendOrInteract(
msgOrInt,
'aliasAddUpdate.ts:139',
{
embeds: [
{
color: infoColor1,
@ -141,13 +146,14 @@ If you are trying to update an existing alias, but forgot the name, please run t
\`${rawRollStr}\``,
},
],
})
.catch((e) => {
utils.commonLoggers.dbError('add.ts:78', 'query', e);
errorOut = true;
});
},
true,
);
if (errorOut || !newMsg) return;
if (!newMsg) {
log(LT.ERROR, `My message didn't send! ${msgOrInt}`);
return;
}
const [modifiers, remainingArgs] = getModifiers(argSpaces);
const failedRollMsg = `The provided roll string (listed below) encountered an error. Please try this roll outside the roll alias system and resolve the error before trying again.
@ -313,25 +319,38 @@ If you are trying to update an existing alias, but forgot the name, please run t
.execute('UPDATE aliases SET rollStr = ?, yVarCnt = ? WHERE guildid = ? AND userid = ? AND aliasName = ?', [
rawRollStr,
modifiers.yVars.size,
guildMode ? message.guildId : 0n,
guildMode ? 0n : message.authorId,
guildMode ? BigInt(msgOrInt.guildId) : 0n,
guildMode ? 0n : utils.getAuthorIdFromMessageOrInteraction(msgOrInt),
aliasName.toLowerCase(),
])
.catch((e0) => {
utils.commonLoggers.dbError('add.ts:169', 'update', e0);
newMsg
.edit(generateAliasError('DB Update Failed.', `add-q1-${guildMode ? 't' : 'f'}-${aliasName}-${guildMode ? message.guildId : message.authorId}`))
.catch((e: Error) => utils.commonLoggers.messageSendError('add.ts:170', message, e));
.edit(
generateAliasError(
'DB Update Failed.',
`add-q1-${guildMode ? 't' : 'f'}-${aliasName}-${guildMode ? BigInt(msgOrInt.guildId) : utils.getAuthorIdFromMessageOrInteraction(msgOrInt)}`,
),
)
.catch((e: Error) => utils.commonLoggers.messageSendError('add.ts:170', msgOrInt, e));
errorOut = true;
});
} else {
const currentAliases: QueryShape[] = await dbClient
.query('SELECT aliasName FROM aliases WHERE guildid = ? AND userid = ?', guildMode ? [message.guildId, 0n] : [0n, message.authorId])
.query(
'SELECT aliasName FROM aliases WHERE guildid = ? AND userid = ?',
guildMode ? [BigInt(msgOrInt.guildId), 0n] : [0n, utils.getAuthorIdFromMessageOrInteraction(msgOrInt)],
)
.catch((e0) => {
utils.commonLoggers.dbError('add.ts:266', 'get count', e0);
newMsg
.edit(generateAliasError('DB Query Failed.', `add-q2-${guildMode ? 't' : 'f'}-${guildMode ? message.guildId : message.authorId}`))
.catch((e: Error) => utils.commonLoggers.messageSendError('add.ts:269', message, e));
.edit(
generateAliasError(
'DB Query Failed.',
`add-q2-${guildMode ? 't' : 'f'}-${guildMode ? BigInt(msgOrInt.guildId) : utils.getAuthorIdFromMessageOrInteraction(msgOrInt)}`,
),
)
.catch((e: Error) => utils.commonLoggers.messageSendError('add.ts:269', msgOrInt, e));
errorOut = true;
});
if (errorOut) return;
@ -339,8 +358,8 @@ If you are trying to update an existing alias, but forgot the name, please run t
if (currentAliases.length < (guildMode ? config.limits.alias.free.guild : config.limits.alias.free.user)) {
await dbClient
.execute('INSERT INTO aliases(guildid,userid,aliasName,rollStr,yVarCnt,premium) values(?,?,?,?,?,?)', [
guildMode ? message.guildId : 0n,
guildMode ? 0n : message.authorId,
guildMode ? BigInt(msgOrInt.guildId) : 0n,
guildMode ? 0n : utils.getAuthorIdFromMessageOrInteraction(msgOrInt),
aliasName.toLowerCase(),
rawRollStr,
modifiers.yVars.size,
@ -349,8 +368,13 @@ If you are trying to update an existing alias, but forgot the name, please run t
.catch((e0) => {
utils.commonLoggers.dbError('add.ts:169', 'insert into', e0);
newMsg
.edit(generateAliasError('DB Insert Failed.', `add-q3-${guildMode ? 't' : 'f'}-${aliasName}-${guildMode ? message.guildId : message.authorId}`))
.catch((e: Error) => utils.commonLoggers.messageSendError('add.ts:187', message, e));
.edit(
generateAliasError(
'DB Insert Failed.',
`add-q3-${guildMode ? 't' : 'f'}-${aliasName}-${guildMode ? BigInt(msgOrInt.guildId) : utils.getAuthorIdFromMessageOrInteraction(msgOrInt)}`,
),
)
.catch((e: Error) => utils.commonLoggers.messageSendError('add.ts:187', msgOrInt, e));
errorOut = true;
});
} else {
@ -386,9 +410,9 @@ If you need this limit raised, please join the [support server](${config.links.s
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('add.ts:321', message, e));
.catch((e: Error) => utils.commonLoggers.messageSendError('add.ts:321', msgOrInt, e));
};
// Using wrappers to limit "magic" booleans
export const add = (message: DiscordenoMessage, guildMode: boolean, argSpaces: string[]) => handleAddUpdate(message, guildMode, argSpaces, false);
export const update = (message: DiscordenoMessage, guildMode: boolean, argSpaces: string[]) => handleAddUpdate(message, guildMode, argSpaces, true);
export const add = (msgOrInt: DiscordenoMessage | SlashCommandInteractionWithGuildId, guildMode: boolean, argSpaces: string[]) => handleAddUpdate(msgOrInt, guildMode, argSpaces, false);
export const update = (msgOrInt: DiscordenoMessage | SlashCommandInteractionWithGuildId, guildMode: boolean, argSpaces: string[]) => handleAddUpdate(msgOrInt, guildMode, argSpaces, true);

View File

@ -7,24 +7,24 @@ import dbClient from 'db/client.ts';
import { generateAliasError } from 'embeds/alias.ts';
import { failColor, successColor, warnColor } from 'embeds/colors.ts';
import { SlashCommandInteractionWithGuildId } from 'src/mod.d.ts';
import utils from 'utils/utils.ts';
const handleDelete = async (message: DiscordenoMessage, guildMode: boolean, argSpaces: string[], deleteAll: boolean) => {
if (guildMode && !(await hasGuildPermissions(message.guildId, message.authorId, ['ADMINISTRATOR']))) {
message
.send({
const handleDelete = async (msgOrInt: DiscordenoMessage | SlashCommandInteractionWithGuildId, guildMode: boolean, argSpaces: string[], deleteAll: boolean) => {
if (guildMode && !(await hasGuildPermissions(BigInt(msgOrInt.guildId), utils.getAuthorIdFromMessageOrInteraction(msgOrInt), ['ADMINISTRATOR']))) {
utils.sendOrInteract(msgOrInt, 'aliasDelete.ts:16', {
embeds: [
{
color: failColor,
title: 'Error: Only Guild Owners and Admins can delete guild aliases',
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('aliasDelete.ts:16', message, e));
});
return;
}
const verificationCode = (guildMode ? message.guildId : message.authorId).toString().slice(-4);
const verificationCode = (guildMode ? BigInt(msgOrInt.guildId) : utils.getAuthorIdFromMessageOrInteraction(msgOrInt)).toString().slice(-4);
const aliasName = (argSpaces.shift() || '').trim();
argSpaces.shift();
const userEnteredVCode = (argSpaces.shift() || '').trim();
@ -32,20 +32,17 @@ const handleDelete = async (message: DiscordenoMessage, guildMode: boolean, argS
if (!deleteAll) {
if (!aliasName) {
message
.send({
utils.sendOrInteract(msgOrInt, 'aliasDelete.ts:36', {
embeds: [
{
color: failColor,
title: 'Error: Please specify one alias to delete',
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('aliasDelete.ts:38', message, e));
});
return;
} else if (!userEnteredVCode) {
message
.send({
utils.sendOrInteract(msgOrInt, 'aliasDelete.ts:47', {
embeds: [
{
color: warnColor,
@ -56,12 +53,10 @@ If you are certain you want to delete \`${aliasName}\` from ${guildMode ? 'this
\`${config.prefix}ra ${guildMode ? 'guild ' : ''}delete ${aliasName} ${verificationCode}\``,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('aliasDelete.ts:54', message, e));
});
return;
} else if (userEnteredVCode !== verificationCode) {
message
.send({
utils.sendOrInteract(msgOrInt, 'aliasDelete.ts:62', {
embeds: [
{
color: failColor,
@ -70,14 +65,13 @@ If you are certain you want to delete \`${aliasName}\` from ${guildMode ? 'this
\`${config.prefix}ra ${guildMode ? 'guild ' : ''}delete ${aliasName} ${verificationCode}\``,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('aliasDelete.ts:70', message, e));
});
return;
} else if (userEnteredVCode === verificationCode) {
const deleteResults = await dbClient
.execute('DELETE FROM aliases WHERE guildid = ? AND userid = ? AND aliasName = ?', [
guildMode ? message.guildId : 0n,
guildMode ? 0n : message.authorId,
guildMode ? BigInt(msgOrInt.guildId) : 0n,
guildMode ? 0n : utils.getAuthorIdFromMessageOrInteraction(msgOrInt),
aliasName,
])
.catch((e) => {
@ -85,12 +79,17 @@ If you are certain you want to delete \`${aliasName}\` from ${guildMode ? 'this
errorOut = true;
});
if (errorOut || !deleteResults) {
message
.send(generateAliasError('Delete failed.', `delete-q0-${guildMode ? 't' : 'f'}-${aliasName}-${guildMode ? message.guildId : message.authorId}`))
.catch((e: Error) => utils.commonLoggers.messageSendError('aliasDelete.ts:86', message, e));
utils.sendOrInteract(
msgOrInt,
'aliasDelete.ts:86',
generateAliasError(
'Delete failed.',
`delete-q0-${guildMode ? 't' : 'f'}-${aliasName}-${guildMode ? BigInt(msgOrInt.guildId) : utils.getAuthorIdFromMessageOrInteraction(msgOrInt)}`,
),
);
return;
} else if (deleteResults.affectedRows) {
message.send({
utils.sendOrInteract(msgOrInt, 'aliasDelete.ts:95', {
embeds: [
{
color: successColor,
@ -100,7 +99,7 @@ If you are certain you want to delete \`${aliasName}\` from ${guildMode ? 'this
],
});
} else {
message.send({
utils.sendOrInteract(msgOrInt, 'aliasDelete.ts:105', {
embeds: [
{
color: warnColor,
@ -114,17 +113,14 @@ Please run \`${config.prefix}ra ${guildMode ? 'guild ' : ''}list\` to view the c
}
return;
} else {
message
.send(generateAliasError('How are you here?', 'deleteOne-how'))
.catch((e: Error) => utils.commonLoggers.messageSendError('aliasDelete.ts:117', message, e));
utils.sendOrInteract(msgOrInt, 'aliasDelete.ts:119', generateAliasError('How are you here?', 'deleteOne-how'));
return;
}
} else {
// We're in deleteAll mode, so aliasName will carry the user verification code.
// Since one wasn't provided, prompt for confirmation
if (!aliasName) {
message
.send({
utils.sendOrInteract(msgOrInt, 'aliasDelete.ts:119', {
embeds: [
{
color: warnColor,
@ -135,12 +131,10 @@ If you are certain you want to delete all aliases for ${guildMode ? 'this guild'
\`${config.prefix}ra ${guildMode ? 'guild ' : ''}delete-all ${verificationCode}\``,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('aliasDelete.ts:137', message, e));
});
return;
} else if (aliasName !== verificationCode) {
message
.send({
utils.sendOrInteract(msgOrInt, 'aliasDelete.ts:142', {
embeds: [
{
color: failColor,
@ -149,23 +143,30 @@ If you are certain you want to delete all aliases for ${guildMode ? 'this guild'
\`${config.prefix}ra ${guildMode ? 'guild ' : ''}delete-all ${verificationCode}\``,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('aliasDelete.ts:70', message, e));
});
return;
} else if (aliasName === verificationCode) {
const deleteResults = await dbClient
.execute('DELETE FROM aliases WHERE guildid = ? AND userid = ?', [guildMode ? message.guildId : 0n, guildMode ? 0n : message.authorId])
.execute('DELETE FROM aliases WHERE guildid = ? AND userid = ?', [
guildMode ? BigInt(msgOrInt.guildId) : 0n,
guildMode ? 0n : utils.getAuthorIdFromMessageOrInteraction(msgOrInt),
])
.catch((e) => {
utils.commonLoggers.dbError('aliasDelete.ts:159', 'delete from aliases', e);
errorOut = true;
});
if (errorOut || !deleteResults) {
message
.send(generateAliasError('Delete failed.', `delete-q1-${guildMode ? 't' : 'f'}-${guildMode ? message.guildId : message.authorId}`))
.catch((e: Error) => utils.commonLoggers.messageSendError('aliasDelete.ts:165', message, e));
utils.sendOrInteract(
msgOrInt,
'aliasDelete.ts:165',
generateAliasError(
'Delete failed.',
`delete-q1-${guildMode ? 't' : 'f'}-${guildMode ? BigInt(msgOrInt.guildId) : utils.getAuthorIdFromMessageOrInteraction(msgOrInt)}`,
),
);
return;
} else if (deleteResults.affectedRows) {
message.send({
utils.sendOrInteract(msgOrInt, 'aliasDelete.ts:174', {
embeds: [
{
color: successColor,
@ -175,7 +176,7 @@ If you are certain you want to delete all aliases for ${guildMode ? 'this guild'
],
});
} else {
message.send({
utils.sendOrInteract(msgOrInt, 'aliasDelete.ts:184', {
embeds: [
{
color: warnColor,
@ -190,14 +191,12 @@ If anything shows up there after running this command, please \`${config.prefix}
}
return;
} else {
message
.send(generateAliasError('How are you here?', 'deleteAll-how'))
.catch((e: Error) => utils.commonLoggers.messageSendError('aliasDelete.ts:194', message, e));
utils.sendOrInteract(msgOrInt, 'aliasDelete.ts:199', generateAliasError('How are you here?', 'deleteAll-how'));
return;
}
}
};
// Using wrappers to limit "magic" booleans
export const deleteOne = (message: DiscordenoMessage, guildMode: boolean, argSpaces: string[]) => handleDelete(message, guildMode, argSpaces, false);
export const deleteAll = (message: DiscordenoMessage, guildMode: boolean, argSpaces: string[]) => handleDelete(message, guildMode, argSpaces, true);
export const deleteOne = (msgOrInt: DiscordenoMessage | SlashCommandInteractionWithGuildId, guildMode: boolean, argSpaces: string[]) => handleDelete(msgOrInt, guildMode, argSpaces, false);
export const deleteAll = (msgOrInt: DiscordenoMessage | SlashCommandInteractionWithGuildId, guildMode: boolean, argSpaces: string[]) => handleDelete(msgOrInt, guildMode, argSpaces, true);

View File

@ -7,6 +7,8 @@ import dbClient from 'db/client.ts';
import { generateAliasError } from 'embeds/alias.ts';
import { failColor, successColor } from 'embeds/colors.ts';
import { SlashCommandInteractionWithGuildId } from 'src/mod.d.ts';
import utils from 'utils/utils.ts';
interface QueryShape {
@ -15,34 +17,30 @@ interface QueryShape {
rollStr: string;
}
export const clone = async (message: DiscordenoMessage, guildMode: boolean, argSpaces: string[]) => {
if (!guildMode && !(await hasGuildPermissions(message.guildId, message.authorId, ['ADMINISTRATOR']))) {
message
.send({
export const clone = async (msgOrInt: DiscordenoMessage | SlashCommandInteractionWithGuildId, guildMode: boolean, argSpaces: string[]) => {
if (!guildMode && !(await hasGuildPermissions(BigInt(msgOrInt.guildId), utils.getAuthorIdFromMessageOrInteraction(msgOrInt), ['ADMINISTRATOR']))) {
utils.sendOrInteract(msgOrInt, 'clone.ts:22', {
embeds: [
{
color: failColor,
title: `Error: Only Guild Owners and Admins can copy a personal alias to a guild aliases`,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('clone.ts:16', message, e));
});
return;
}
const aliasName = (argSpaces.shift() || '').trim().toLowerCase();
if (!aliasName) {
message
.send({
utils.sendOrInteract(msgOrInt, 'clone.ts:37', {
embeds: [
{
color: failColor,
title: `Error: Please specify an alias to copy to ${guildMode ? 'your account' : 'this guild'}`,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('clone.ts:32', message, e));
});
return;
}
@ -50,13 +48,18 @@ export const clone = async (message: DiscordenoMessage, guildMode: boolean, argS
const query: QueryShape[] = await dbClient
.query(
`SELECT aliasName, yVarCnt, rollStr FROM aliases WHERE guildid = ? AND userid = ? AND aliasName = ?`,
guildMode ? [message.guildId, 0n, aliasName] : [0n, message.authorId, aliasName],
guildMode ? [BigInt(msgOrInt.guildId), 0n, aliasName] : [0n, utils.getAuthorIdFromMessageOrInteraction(msgOrInt), aliasName],
)
.catch((e0) => {
utils.commonLoggers.dbError('clone.ts:51', 'query', e0);
message
.send(generateAliasError('DB Query Failed.', `clone-q0-${guildMode ? 't' : 'f'}-${aliasName}-${guildMode ? message.guildId : message.authorId}`))
.catch((e: Error) => utils.commonLoggers.messageSendError('clone.ts:54', message, e));
utils.sendOrInteract(
msgOrInt,
'clone.ts:57',
generateAliasError(
'DB Query Failed.',
`clone-q0-${guildMode ? 't' : 'f'}-${aliasName}-${guildMode ? BigInt(msgOrInt.guildId) : utils.getAuthorIdFromMessageOrInteraction(msgOrInt)}`,
),
);
errorOut = true;
});
if (errorOut) return;
@ -64,8 +67,7 @@ export const clone = async (message: DiscordenoMessage, guildMode: boolean, argS
const details = query[0];
if (!details) {
message
.send({
utils.sendOrInteract(msgOrInt, 'clone.ts:71', {
embeds: [
{
color: failColor,
@ -73,27 +75,30 @@ export const clone = async (message: DiscordenoMessage, guildMode: boolean, argS
description: `Did you mean to run \`${config.prefix}ra ${guildMode ? '' : 'guild '}clone ${aliasName}\`?`,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('clone.ts:73', message, e));
});
}
const targetQuery: QueryShape[] = await dbClient
.query(
`SELECT aliasName, yVarCnt, rollStr FROM aliases WHERE guildid = ? AND userid = ? AND aliasName = ?`,
guildMode ? [0n, message.authorId, aliasName] : [message.guildId, 0n, aliasName],
guildMode ? [0n, utils.getAuthorIdFromMessageOrInteraction(msgOrInt), aliasName] : [BigInt(msgOrInt.guildId), 0n, aliasName],
)
.catch((e0) => {
utils.commonLoggers.dbError('clone.ts:82', 'query', e0);
message
.send(generateAliasError('DB Query Failed.', `clone-q1-${guildMode ? 't' : 'f'}-${aliasName}-${guildMode ? message.guildId : message.authorId}`))
.catch((e: Error) => utils.commonLoggers.messageSendError('clone.ts:85', message, e));
utils.sendOrInteract(
msgOrInt,
'clone.ts:90',
generateAliasError(
'DB Query Failed.',
`clone-q1-${guildMode ? 't' : 'f'}-${aliasName}-${guildMode ? BigInt(msgOrInt.guildId) : utils.getAuthorIdFromMessageOrInteraction(msgOrInt)}`,
),
);
errorOut = true;
});
if (errorOut) return;
if (targetQuery.length) {
message
.send({
utils.sendOrInteract(msgOrInt, 'clone.ts:102', {
embeds: [
{
color: failColor,
@ -101,15 +106,14 @@ export const clone = async (message: DiscordenoMessage, guildMode: boolean, argS
description: `Please delete or rename the ${guildMode ? 'personal' : 'guild'} alias \`${aliasName}\` and try again.`,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('clone.ts:101', message, e));
});
return;
}
await dbClient
.execute(`INSERT INTO aliases(guildid,userid,aliasName,rollStr,yVarCnt,premium) values(?,?,?,?,?,?)`, [
guildMode ? 0n : message.guildId,
guildMode ? message.authorId : 0n,
guildMode ? 0n : BigInt(msgOrInt.guildId),
guildMode ? utils.getAuthorIdFromMessageOrInteraction(msgOrInt) : 0n,
aliasName,
details.rollStr,
details.yVarCnt,
@ -117,15 +121,19 @@ export const clone = async (message: DiscordenoMessage, guildMode: boolean, argS
])
.catch((e0) => {
utils.commonLoggers.dbError('clone.ts:110', 'query', e0);
message
.send(generateAliasError('DB Insert Failed.', `clone-q2-${guildMode ? 't' : 'f'}-${aliasName}-${guildMode ? message.guildId : message.authorId}`))
.catch((e: Error) => utils.commonLoggers.messageSendError('clone.ts:113', message, e));
utils.sendOrInteract(
msgOrInt,
'clone.ts:126',
generateAliasError(
'DB Insert Failed.',
`clone-q2-${guildMode ? 't' : 'f'}-${aliasName}-${guildMode ? BigInt(msgOrInt.guildId) : utils.getAuthorIdFromMessageOrInteraction(msgOrInt)}`,
),
);
errorOut = true;
});
if (errorOut) return;
message
.send({
utils.sendOrInteract(msgOrInt, 'clone.ts:137', {
embeds: [
{
color: successColor,
@ -133,6 +141,5 @@ export const clone = async (message: DiscordenoMessage, guildMode: boolean, argS
description: `\`${aliasName}\` is now available as an alias ${guildMode ? 'on your account' : 'in this guild'}.`,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('clone.ts:132', message, e));
});
};

View File

@ -5,6 +5,8 @@ import dbClient from 'db/client.ts';
import { generateAliasError } from 'embeds/alias.ts';
import { successColor } from 'embeds/colors.ts';
import { SlashCommandInteractionWithGuildId } from 'src/mod.d.ts';
import utils from 'utils/utils.ts';
interface QueryShape {
@ -12,24 +14,28 @@ interface QueryShape {
yVarCnt: number;
}
export const list = async (message: DiscordenoMessage, guildMode: boolean) => {
export const list = async (msgOrInt: DiscordenoMessage | SlashCommandInteractionWithGuildId, guildMode: boolean) => {
let errorOut = false;
const query: QueryShape[] = await dbClient
.query(
`SELECT aliasName, yVarCnt FROM aliases WHERE guildid = ? AND userid = ? ORDER BY createdAt ASC`,
guildMode ? [message.guildId, 0n] : [0n, message.authorId],
guildMode ? [BigInt(msgOrInt.guildId), 0n] : [0n, utils.getAuthorIdFromMessageOrInteraction(msgOrInt)],
)
.catch((e0) => {
utils.commonLoggers.dbError('list.ts:10', 'query', e0);
message
.send(generateAliasError('DB Query Failed.', `list-q0-${guildMode ? 't' : 'f'}-${guildMode ? message.guildId : message.authorId}`))
.catch((e: Error) => utils.commonLoggers.messageSendError('list.ts:11', message, e));
utils.sendOrInteract(
msgOrInt,
'list.ts:26',
generateAliasError(
'DB Query Failed.',
`list-q0-${guildMode ? 't' : 'f'}-${guildMode ? BigInt(msgOrInt.guildId) : utils.getAuthorIdFromMessageOrInteraction(msgOrInt)}`,
),
);
errorOut = true;
});
if (errorOut) return;
message
.send({
utils.sendOrInteract(msgOrInt, 'list.ts:33', {
embeds: [
{
color: successColor,
@ -41,9 +47,5 @@ ${query.map((a) => `\`${a.aliasName}\`${a.yVarCnt ? ` (${a.yVarCnt})` : ''}`).jo
: '',
},
],
})
.catch((e0) => {
utils.commonLoggers.messageSendError('list.ts:39', message, e0);
message.send(generateAliasError('Message Send Failed.', `list-m0-${guildMode ? 't' : 'f'}-${guildMode ? message.guildId : message.authorId}`));
});
};

View File

@ -7,24 +7,24 @@ import dbClient from 'db/client.ts';
import { generateAliasError } from 'embeds/alias.ts';
import { failColor, successColor } from 'embeds/colors.ts';
import { SlashCommandInteractionWithGuildId } from 'src/mod.d.ts';
import utils from 'utils/utils.ts';
interface QueryShape {
aliasName: string;
}
export const rename = async (message: DiscordenoMessage, guildMode: boolean, argSpaces: string[]) => {
if (guildMode && !(await hasGuildPermissions(message.guildId, message.authorId, ['ADMINISTRATOR']))) {
message
.send({
export const rename = async (msgOrInt: DiscordenoMessage | SlashCommandInteractionWithGuildId, guildMode: boolean, argSpaces: string[]) => {
if (guildMode && !(await hasGuildPermissions(BigInt(msgOrInt.guildId), utils.getAuthorIdFromMessageOrInteraction(msgOrInt), ['ADMINISTRATOR']))) {
utils.sendOrInteract(msgOrInt, 'rename.ts:20', {
embeds: [
{
color: failColor,
title: `Error: Only Guild Owners and Admins can rename a guild aliases`,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('rename.ts:25', message, e));
});
return;
}
@ -33,16 +33,14 @@ export const rename = async (message: DiscordenoMessage, guildMode: boolean, arg
const newAliasName = (argSpaces.shift() || '').trim().toLowerCase();
if (!oldAliasName || !newAliasName) {
message
.send({
utils.sendOrInteract(msgOrInt, 'rename.ts:37', {
embeds: [
{
color: failColor,
title: `Error: Please specify both an alias to rename, and the new name to set it to.`,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('rename.ts:32', message, e));
});
return;
}
@ -51,20 +49,24 @@ export const rename = async (message: DiscordenoMessage, guildMode: boolean, arg
const queryOld: QueryShape[] = await dbClient
.query(
`SELECT aliasName FROM aliases WHERE guildid = ? AND userid = ? AND aliasName = ?`,
guildMode ? [message.guildId, 0n, oldAliasName] : [0n, message.authorId, oldAliasName],
guildMode ? [BigInt(msgOrInt.guildId), 0n, oldAliasName] : [0n, utils.getAuthorIdFromMessageOrInteraction(msgOrInt), oldAliasName],
)
.catch((e0) => {
utils.commonLoggers.dbError('rename.ts:44', 'query', e0);
message
.send(generateAliasError('DB Query Failed.', `rename-q0-${guildMode ? 't' : 'f'}-${oldAliasName}-${guildMode ? message.guildId : message.authorId}`))
.catch((e: Error) => utils.commonLoggers.messageSendError('rename.ts:47', message, e));
utils.sendOrInteract(
msgOrInt,
'rename.ts:58',
generateAliasError(
'DB Query Failed.',
`rename-q0-${guildMode ? 't' : 'f'}-${oldAliasName}-${guildMode ? BigInt(msgOrInt.guildId) : utils.getAuthorIdFromMessageOrInteraction(msgOrInt)}`,
),
);
errorOut = true;
});
if (errorOut) return;
if (!queryOld.length) {
message
.send({
utils.sendOrInteract(msgOrInt, 'rename.ts:70', {
embeds: [
{
color: failColor,
@ -73,28 +75,31 @@ export const rename = async (message: DiscordenoMessage, guildMode: boolean, arg
\`${config.prefix}ra ${guildMode ? 'guild ' : ''}list\``,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('add.ts:63', message, e));
});
return;
}
const queryNew: QueryShape[] = await dbClient
.query(
`SELECT aliasName FROM aliases WHERE guildid = ? AND userid = ? AND aliasName = ?`,
guildMode ? [message.guildId, 0n, newAliasName] : [0n, message.authorId, newAliasName],
guildMode ? [BigInt(msgOrInt.guildId), 0n, newAliasName] : [0n, utils.getAuthorIdFromMessageOrInteraction(msgOrInt), newAliasName],
)
.catch((e0) => {
utils.commonLoggers.dbError('rename.ts:44', 'query', e0);
message
.send(generateAliasError('DB Query Failed.', `rename-q1-${guildMode ? 't' : 'f'}-${newAliasName}-${guildMode ? message.guildId : message.authorId}`))
.catch((e: Error) => utils.commonLoggers.messageSendError('rename.ts:47', message, e));
utils.sendOrInteract(
msgOrInt,
'rename.ts:91',
generateAliasError(
'DB Query Failed.',
`rename-q1-${guildMode ? 't' : 'f'}-${newAliasName}-${guildMode ? BigInt(msgOrInt.guildId) : utils.getAuthorIdFromMessageOrInteraction(msgOrInt)}`,
),
);
errorOut = true;
});
if (errorOut) return;
if (queryNew.length) {
message
.send({
utils.sendOrInteract(msgOrInt, 'rename.ts:103', {
embeds: [
{
color: failColor,
@ -102,8 +107,7 @@ export const rename = async (message: DiscordenoMessage, guildMode: boolean, arg
description: 'Please choose a different name for this alias.',
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('add.ts:63', message, e));
});
return;
}
@ -111,25 +115,24 @@ export const rename = async (message: DiscordenoMessage, guildMode: boolean, arg
await dbClient
.execute('UPDATE aliases SET aliasName = ? WHERE guildid = ? AND userid = ? AND aliasName = ?', [
newAliasName,
guildMode ? message.guildId : 0n,
guildMode ? 0n : message.authorId,
guildMode ? BigInt(msgOrInt.guildId) : 0n,
guildMode ? 0n : utils.getAuthorIdFromMessageOrInteraction(msgOrInt),
oldAliasName,
])
.catch((e0) => {
utils.commonLoggers.dbError('rename.ts:169', 'update', e0);
message
.send(
utils.sendOrInteract(
msgOrInt,
'rename.ts:126',
generateAliasError(
'DB Update Failed.',
`rename-q2-${guildMode ? 't' : 'f'}-${oldAliasName}-${newAliasName}-${guildMode ? message.guildId : message.authorId}`,
`rename-q2-${guildMode ? 't' : 'f'}-${oldAliasName}-${newAliasName}-${guildMode ? BigInt(msgOrInt.guildId) : utils.getAuthorIdFromMessageOrInteraction(msgOrInt)}`,
),
)
.catch((e: Error) => utils.commonLoggers.messageSendError('rename.ts:170', message, e));
);
errorOut = true;
});
message
.send({
utils.sendOrInteract(msgOrInt, 'rename.ts:136', {
embeds: [
{
color: successColor,
@ -137,6 +140,5 @@ export const rename = async (message: DiscordenoMessage, guildMode: boolean, arg
description: `\`${newAliasName}\` is now available as an alias ${guildMode ? 'in this guild' : 'on your account'}.`,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('rename.ts:132', message, e));
});
};

View File

@ -14,6 +14,7 @@ export const ReservedWords = Object.freeze([
'view',
'delete',
'remove',
'delete-one',
'delete-all',
'remove-all',
'run',

View File

@ -1,4 +1,5 @@
import { DiscordenoMessage } from '@discordeno';
import { DiscordenoMessage, hasOwnProperty } from '@discordeno';
import { log, LogTypes as LT } from '@Log4Deno';
import config from '~config';
@ -6,7 +7,8 @@ import { getModifiers } from 'artigen/dice/getModifiers.ts';
import { sendRollRequest } from 'artigen/managers/queueManager.ts';
import { generateRollError, rollingEmbed } from 'artigen/utils/embeds.ts';
import { rollingEmbed } from 'artigen/utils/embeds.ts';
import { argSpacesSplitRegex } from 'artigen/utils/escape.ts';
import dbClient from 'db/client.ts';
import { queries } from 'db/common.ts';
@ -14,6 +16,8 @@ import { queries } from 'db/common.ts';
import { generateAliasError } from 'embeds/alias.ts';
import { failColor } from 'embeds/colors.ts';
import { SlashCommandInteractionWithGuildId } from 'src/mod.d.ts';
import utils from 'utils/utils.ts';
interface QueryShape {
@ -22,7 +26,7 @@ interface QueryShape {
rollStr: string;
}
export const run = async (message: DiscordenoMessage, guildMode: boolean, command: string, argSpaces: string[]) => {
export const run = async (msgOrInt: DiscordenoMessage | SlashCommandInteractionWithGuildId, guildMode: boolean, command: string, argSpaces: string[]) => {
let errorOut = false;
const aliasName = (command === 'run' || command === 'execute' ? argSpaces.shift() || '' : command)?.trim().toLowerCase();
const yVars = new Map<string, number>();
@ -37,13 +41,18 @@ export const run = async (message: DiscordenoMessage, guildMode: boolean, comman
let query: QueryShape[] = await dbClient
.query(
`SELECT aliasName, yVarCnt, rollStr FROM aliases WHERE guildid = ? AND userid = ? AND aliasName = ?`,
guildMode ? [message.guildId, 0n, aliasName] : [0n, message.authorId, aliasName],
guildMode ? [BigInt(msgOrInt.guildId), 0n, aliasName] : [0n, utils.getAuthorIdFromMessageOrInteraction(msgOrInt), aliasName],
)
.catch((e0) => {
utils.commonLoggers.dbError('run.ts:30', 'query', e0);
message
.send(generateAliasError('DB Query Failed.', `run-q0-${guildMode ? 't' : 'f'}-${aliasName}-${guildMode ? message.guildId : message.authorId}`))
.catch((e: Error) => utils.commonLoggers.messageSendError('run.ts:33', message, e));
utils.sendOrInteract(
msgOrInt,
'run.ts:47',
generateAliasError(
'DB Query Failed.',
`run-q0-${guildMode ? 't' : 'f'}-${aliasName}-${guildMode ? BigInt(msgOrInt.guildId) : utils.getAuthorIdFromMessageOrInteraction(msgOrInt)}`,
),
);
errorOut = true;
});
if (errorOut) return;
@ -51,12 +60,17 @@ export const run = async (message: DiscordenoMessage, guildMode: boolean, comman
if (!guildMode && !query.length) {
// Didn't find an alias for the user, maybe their doing an implicit guild mode?
query = await dbClient
.query(`SELECT aliasName, yVarCnt, rollStr FROM aliases WHERE guildid = ? AND userid = ? AND aliasName = ?`, [message.guildId, 0n, aliasName])
.query(`SELECT aliasName, yVarCnt, rollStr FROM aliases WHERE guildid = ? AND userid = ? AND aliasName = ?`, [BigInt(msgOrInt.guildId), 0n, aliasName])
.catch((e0) => {
utils.commonLoggers.dbError('run.ts:43', 'query', e0);
message
.send(generateAliasError('DB Query Failed.', `run-q1-${guildMode ? 't' : 'f'}-${aliasName}-${guildMode ? message.guildId : message.authorId}`))
.catch((e: Error) => utils.commonLoggers.messageSendError('run.ts:46', message, e));
utils.sendOrInteract(
msgOrInt,
'run.ts:64',
generateAliasError(
'DB Query Failed.',
`run-q1-${guildMode ? 't' : 'f'}-${aliasName}-${guildMode ? BigInt(msgOrInt.guildId) : utils.getAuthorIdFromMessageOrInteraction(msgOrInt)}`,
),
);
errorOut = true;
});
if (errorOut) return;
@ -64,8 +78,7 @@ export const run = async (message: DiscordenoMessage, guildMode: boolean, comman
const details = query.shift();
if (!details) {
message
.send({
utils.sendOrInteract(msgOrInt, 'run.ts:78', {
embeds: [
{
color: failColor,
@ -73,14 +86,12 @@ export const run = async (message: DiscordenoMessage, guildMode: boolean, comman
description: `Please run \`${config.prefix}ra ${guildMode ? 'guild ' : ''}list\` to view the available aliases.`,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('run.ts:63', message, e));
});
return;
}
if (yVars.size < details.yVarCnt) {
message
.send({
utils.sendOrInteract(msgOrInt, 'run.ts:92', {
embeds: [
{
color: failColor,
@ -89,18 +100,23 @@ export const run = async (message: DiscordenoMessage, guildMode: boolean, comman
\`${details.rollStr}\``.slice(0, 3_000),
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('run.ts:81', message, e));
});
return;
}
const m = await message.reply(rollingEmbed);
const m = await utils.sendOrInteract(msgOrInt, 'run.ts:115', rollingEmbed, true);
if (!m) {
log(LT.ERROR, `My message didn't send! ${msgOrInt}`);
return;
}
const rollStrArgSpaces = details.rollStr.split(/([ \n]+)/g);
const rollStrArgSpaces = details.rollStr.split(argSpacesSplitRegex).filter((x) => x);
const [modifiers, remainingArgs] = getModifiers(rollStrArgSpaces);
if (!modifiers.valid) {
m.edit(generateRollError('Modifiers invalid:', modifiers.error.name, modifiers.error.message)).catch((e) => utils.commonLoggers.messageEditError('run.ts:96', m, e));
// m.edit(generateRollError('Modifiers invalid:', modifiers.error.name, modifiers.error.message)).catch((e) =>
// utils.commonLoggers.messageEditError('run.ts:96', m, e)
// );
return;
}
@ -113,7 +129,11 @@ export const run = async (message: DiscordenoMessage, guildMode: boolean, comman
apiRoll: false,
ddRoll: true,
testRoll: false,
dd: { myResponse: m, originalMessage: message },
dd: {
myResponse: m,
originalMessage: hasOwnProperty(msgOrInt, 'token') ? m : msgOrInt,
authorId: utils.getAuthorIdFromMessageOrInteraction(msgOrInt),
},
rollCmd: remainingArgs.join(''),
modifiers,
originalCommand: details.rollStr,

View File

@ -7,6 +7,8 @@ import dbClient from 'db/client.ts';
import { generateAliasError } from 'embeds/alias.ts';
import { failColor, successColor } from 'embeds/colors.ts';
import { SlashCommandInteractionWithGuildId } from 'src/mod.d.ts';
import utils from 'utils/utils.ts';
interface QueryShape {
@ -15,12 +17,11 @@ interface QueryShape {
rollStr: string;
}
export const view = async (message: DiscordenoMessage, guildMode: boolean, argSpaces: string[]) => {
export const view = async (msgOrInt: DiscordenoMessage | SlashCommandInteractionWithGuildId, guildMode: boolean, argSpaces: string[]) => {
const aliasName = argSpaces.shift();
if (!aliasName) {
message
.send({
utils.sendOrInteract(msgOrInt, 'view.ts:24', {
embeds: [
{
color: failColor,
@ -32,8 +33,7 @@ If you need to see all aliases for ${guildMode ? 'this guild' : 'your account'},
} current aliases.`,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('view.ts:35', message, e));
});
return;
}
@ -41,13 +41,18 @@ If you need to see all aliases for ${guildMode ? 'this guild' : 'your account'},
const query: QueryShape[] = await dbClient
.query(
`SELECT aliasName, yVarCnt, rollStr FROM aliases WHERE guildid = ? AND userid = ? AND aliasName = ?`,
guildMode ? [message.guildId, 0n, aliasName.toLowerCase()] : [0n, message.authorId, aliasName.toLowerCase()],
guildMode ? [BigInt(msgOrInt.guildId), 0n, aliasName.toLowerCase()] : [0n, utils.getAuthorIdFromMessageOrInteraction(msgOrInt), aliasName.toLowerCase()],
)
.catch((e0) => {
utils.commonLoggers.dbError('view.ts:46', 'query', e0);
message
.send(generateAliasError('DB Query Failed.', `view-q0-${guildMode ? 't' : 'f'}-${aliasName}-${guildMode ? message.guildId : message.authorId}`))
.catch((e: Error) => utils.commonLoggers.messageSendError('view.ts:49', message, e));
utils.sendOrInteract(
msgOrInt,
'view.ts:50',
generateAliasError(
'DB Query Failed.',
`view-q0-${guildMode ? 't' : 'f'}-${aliasName}-${guildMode ? BigInt(msgOrInt.guildId) : utils.getAuthorIdFromMessageOrInteraction(msgOrInt)}`,
),
);
errorOut = true;
});
if (errorOut) return;
@ -55,8 +60,7 @@ If you need to see all aliases for ${guildMode ? 'this guild' : 'your account'},
const details = query[0];
if (details) {
message
.send({
utils.sendOrInteract(msgOrInt, 'view.ts:63', {
embeds: [
{
color: successColor,
@ -65,16 +69,9 @@ If you need to see all aliases for ${guildMode ? 'this guild' : 'your account'},
${details.rollStr}`,
},
],
})
.catch((e0) => {
utils.commonLoggers.messageSendError('view.ts:69', message, e0);
message.send(
generateAliasError('Message Send Failed.', `view-m0-${guildMode ? 't' : 'f'}-${aliasName}-${guildMode ? message.guildId : message.authorId}`),
);
});
} else {
message
.send({
utils.sendOrInteract(msgOrInt, 'view.ts:74', {
embeds: [
{
color: failColor,
@ -82,7 +79,6 @@ ${details.rollStr}`,
description: `Did you mean to run \`${config.prefix}ra ${guildMode ? '' : 'guild '}view ${aliasName}\`?`,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('view.ts:85', message, e));
});
}
};

View File

@ -1,4 +1,4 @@
import { DiscordenoMessage } from '@discordeno';
import { CreateGlobalApplicationCommand, DiscordenoMessage, Interaction } from '@discordeno';
import config from '~config';
@ -10,13 +10,17 @@ import { failColor, infoColor2 } from 'embeds/colors.ts';
import intervals from 'utils/intervals.ts';
import utils from 'utils/utils.ts';
export const heatmap = (message: DiscordenoMessage) => {
export const heatmapSC: CreateGlobalApplicationCommand = {
name: 'heatmap',
description: 'Shows a heatmap of when the roll command is run the most.',
};
export const heatmap = (msgOrInt: DiscordenoMessage | Interaction) => {
// Light telemetry to see how many times a command is being run
dbClient.execute(queries.callIncCnt('heatmap')).catch((e) => utils.commonLoggers.dbError('heatmap.ts:14', 'call sproc INC_CNT on', e));
if (config.api.enable) {
message
.send({
utils.sendOrInteract(msgOrInt, 'heatmap.ts:23', {
embeds: [
{
title: 'Roll Heatmap',
@ -33,11 +37,9 @@ Most Rolls: ${intervals.getMaxRollCnt()}`,
},
},
],
})
.catch((e) => utils.commonLoggers.messageSendError('heatmap.ts:21', message, e));
});
} else {
message
.send({
utils.sendOrInteract(msgOrInt, 'heatmap.ts:42', {
embeds: [
{
title: 'Roll Heatmap Disabled',
@ -45,7 +47,6 @@ Most Rolls: ${intervals.getMaxRollCnt()}`,
color: failColor,
},
],
})
.catch((e) => utils.commonLoggers.messageSendError('heatmap.ts:21', message, e));
});
}
};

View File

@ -1,4 +1,6 @@
import { DiscordenoMessage } from '@discordeno';
import { CreateGlobalApplicationCommand, DiscordenoMessage, Interaction } from '@discordeno';
import config from '~config';
import { generateHelpMessage } from 'commands/helpLibrary/generateHelpMessage.ts';
@ -7,8 +9,13 @@ import { queries } from 'db/common.ts';
import utils from 'utils/utils.ts';
export const help = (message: DiscordenoMessage) => {
export const helpSC: CreateGlobalApplicationCommand = {
name: 'help',
description: `Opens ${config.name}'s Help Library.`,
};
export const help = (msgOrInt: DiscordenoMessage | Interaction) => {
// Light telemetry to see how many times a command is being run
dbClient.execute(queries.callIncCnt('help')).catch((e) => utils.commonLoggers.dbError('help.ts:15', 'call sproc INC_CNT on', e));
message.send(generateHelpMessage()).catch((e: Error) => utils.commonLoggers.messageSendError('help.ts:16', message, e));
utils.sendOrInteract(msgOrInt, 'help.ts:20', generateHelpMessage());
};

View File

@ -1,4 +1,4 @@
import { DiscordenoMessage } from '@discordeno';
import { CreateGlobalApplicationCommand, DiscordenoMessage, Interaction } from '@discordeno';
import config from '~config';
@ -9,12 +9,16 @@ import { infoColor2 } from 'embeds/colors.ts';
import utils from 'utils/utils.ts';
export const info = (message: DiscordenoMessage) => {
export const infoSC: CreateGlobalApplicationCommand = {
name: 'info',
description: 'Outputs some information about the bot and its developer.',
};
export const info = (msgOrInt: DiscordenoMessage | Interaction) => {
// Light telemetry to see how many times a command is being run
dbClient.execute(queries.callIncCnt('info')).catch((e) => utils.commonLoggers.dbError('info.ts:12', 'call sproc INC_CNT on', e));
message
.send({
utils.sendOrInteract(msgOrInt, 'info.ts:21', {
embeds: [
{
color: infoColor2,
@ -25,6 +29,5 @@ Want to check out my source code? Check it out [here](${config.links.sourceCode
Need help with this bot? Join my support server [here](${config.links.supportServer}).`,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('info.ts:23', message, e));
});
};

View File

@ -1,4 +1,4 @@
import { DiscordenoMessage } from '@discordeno';
import { CreateGlobalApplicationCommand, DiscordenoMessage, Interaction } from '@discordeno';
import config from '~config';
@ -9,12 +9,16 @@ import { infoColor1 } from 'embeds/colors.ts';
import utils from 'utils/utils.ts';
export const privacy = (message: DiscordenoMessage) => {
export const privacySC: CreateGlobalApplicationCommand = {
name: 'privacy',
description: 'Shows a summary of the Privacy Policy and Terms of Service, along with links to them.',
};
export const privacy = (msgOrInt: DiscordenoMessage | Interaction) => {
// Light telemetry to see how many times a command is being run
dbClient.execute(queries.callIncCnt('privacy')).catch((e) => utils.commonLoggers.dbError('privacy.ts:15', 'call sproc INC_CNT on', e));
message
.send({
utils.sendOrInteract(msgOrInt, 'privacy.ts:21', {
embeds: [
{
color: infoColor1,
@ -34,6 +38,5 @@ Want me to ignore you? Simply run \`${config.prefix}opt-out\` and ${config.name
],
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('privacy.ts:33', message, e));
});
};

View File

@ -1,4 +1,4 @@
import { DiscordenoMessage, sendMessage } from '@discordeno';
import { CreateGlobalApplicationCommand, DiscordApplicationCommandOptionTypes, DiscordenoMessage, Interaction, sendMessage } from '@discordeno';
import config from '~config';
@ -8,9 +8,22 @@ import { queries } from 'db/common.ts';
import { failColor, infoColor2, successColor } from 'embeds/colors.ts';
import utils from 'utils/utils.ts';
export const report = (message: DiscordenoMessage, args: string[]) => {
export const reportSC: CreateGlobalApplicationCommand = {
name: 'report',
description: 'Report an issue or send a feature request to the developer.',
options: [
{
type: DiscordApplicationCommandOptionTypes.String,
name: 'report-text',
description: 'The issue or feature request.',
required: true,
},
],
};
export const report = (msgOrInt: DiscordenoMessage | Interaction, args: string[]) => {
// Light telemetry to see how many times a command is being run
dbClient.execute(queries.callIncCnt('report')).catch((e) => utils.commonLoggers.dbError('report.ts:17', 'call sproc INC_CNT on', e));
dbClient.execute(queries.callIncCnt('report')).catch((e) => utils.commonLoggers.dbError('report.ts:25', 'call sproc INC_CNT on', e));
if (args.join(' ')) {
sendMessage(config.reportChannel, {
@ -21,9 +34,8 @@ export const report = (message: DiscordenoMessage, args: string[]) => {
description: args.join(' ') || 'No message',
},
],
}).catch((e: Error) => utils.commonLoggers.messageSendError('report.ts:22', message, e));
message
.send({
}).catch((e: Error) => utils.commonLoggers.messageSendError('report.ts:36', msgOrInt, e));
utils.sendOrInteract(msgOrInt, 'report.ts:37', {
embeds: [
{
color: successColor,
@ -31,11 +43,9 @@ export const report = (message: DiscordenoMessage, args: string[]) => {
description: `For more in depth support, and information about planned maintenance, please join the support server [here](${config.links.supportServer}).`,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('report.ts:29', message, e));
});
} else {
message
.send({
utils.sendOrInteract(msgOrInt, 'report.ts:48', {
embeds: [
{
color: failColor,
@ -43,7 +53,6 @@ export const report = (message: DiscordenoMessage, args: string[]) => {
description: 'Providing a short description helps my developer quickly diagnose what went wrong.',
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('report.ts:37', message, e));
});
}
};

View File

@ -1,4 +1,4 @@
import { DiscordenoMessage } from '@discordeno';
import { CreateGlobalApplicationCommand, DiscordenoMessage, Interaction } from '@discordeno';
import config from '~config';
@ -9,12 +9,16 @@ import { infoColor2 } from 'embeds/colors.ts';
import utils from 'utils/utils.ts';
export const rip = (message: DiscordenoMessage) => {
export const ripSC: CreateGlobalApplicationCommand = {
name: 'rest-in-peace',
description: 'A short message I wanted to include.',
};
export const rip = (msgOrInt: DiscordenoMessage | Interaction) => {
// Light telemetry to see how many times a command is being run
dbClient.execute(queries.callIncCnt('rip')).catch((e) => utils.commonLoggers.dbError('rip.ts:14', 'call sproc INC_CNT on', e));
message
.send({
utils.sendOrInteract(msgOrInt, 'rip.ts:21', {
embeds: [
{
color: infoColor2,
@ -23,6 +27,5 @@ export const rip = (message: DiscordenoMessage) => {
footer: { text: 'December 21, 2020' },
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('rip.ts:26', message, e));
});
};

View File

@ -1,4 +1,4 @@
import { DiscordenoMessage } from '@discordeno';
import { CreateGlobalApplicationCommand, DiscordApplicationCommandOptionTypes, DiscordenoMessage, hasOwnProperty, Interaction } from '@discordeno';
import { log, LogTypes as LT } from '@Log4Deno';
import config from '~config';
@ -14,7 +14,20 @@ import { queries } from 'db/common.ts';
import utils from 'utils/utils.ts';
export const roll = async (message: DiscordenoMessage, args: string[], command: string) => {
export const rollSC: CreateGlobalApplicationCommand = {
name: 'roll',
description: 'Rolls dice and does math! For help, see the "Dice/Roll/Math Command" section in the /help library.',
options: [
{
type: DiscordApplicationCommandOptionTypes.String,
name: 'roll-string',
description: 'The full roll string to execute.',
required: true,
},
],
};
export const roll = async (msgOrInt: DiscordenoMessage | Interaction, args: string[], command: string) => {
// Light telemetry to see how many times a command is being run
const currDateTime = new Date();
dbClient.execute(queries.callIncCnt('roll')).catch((e) => utils.commonLoggers.dbError('roll.ts:20', 'call sproc INC_CNT on', e));
@ -31,7 +44,10 @@ export const roll = async (message: DiscordenoMessage, args: string[], command:
originalCommand = `${config.prefix}${originalCommand.trim()}`;
}
const m = await message.reply(rollingEmbed);
const m = await utils.sendOrInteract(msgOrInt, 'roll.ts:47', rollingEmbed, true);
if (!m) {
throw new Error("My message didn't send!");
}
// Get modifiers from command
const [modifiers, remainingArgs] = getModifiers(args);
@ -41,7 +57,7 @@ export const roll = async (message: DiscordenoMessage, args: string[], command:
m.edit(generateRollError('Modifiers invalid:', modifiers.error.name, modifiers.error.message)).catch((e) => utils.commonLoggers.messageEditError('roll.ts:50', m, e));
}
let rollCmd = message.content.startsWith(`${config.prefix}r`) ? remainingArgs.join('') : `${command}${remainingArgs.join('')}`;
let rollCmd = (hasOwnProperty(msgOrInt, 'token') ? args.join('') : msgOrInt.content).startsWith(`${config.prefix}r`) ? remainingArgs.join('') : `${command}${remainingArgs.join('')}`;
// Try to ensure the roll is wrapped
if (!rollCmd.includes(config.postfix)) {
@ -55,12 +71,16 @@ export const roll = async (message: DiscordenoMessage, args: string[], command:
apiRoll: false,
ddRoll: true,
testRoll: false,
dd: { myResponse: m, originalMessage: message },
dd: {
authorId: utils.getAuthorIdFromMessageOrInteraction(msgOrInt),
myResponse: m,
originalMessage: hasOwnProperty(msgOrInt, 'token') ? m : msgOrInt,
},
rollCmd,
modifiers,
originalCommand,
});
} catch (e) {
log(LT.ERROR, `Unhandled Error: ${JSON.stringify(e)}`);
log(LT.ERROR, `Unhandled Roll Error: ${JSON.stringify(e)} | msgOrInt: ${JSON.stringify(msgOrInt)} | args: ${JSON.stringify(args)} | command: ${command}`);
}
};

View File

@ -1,4 +1,4 @@
import { cache, cacheHandlers, DiscordenoMessage } from '@discordeno';
import { cache, cacheHandlers, CreateGlobalApplicationCommand, DiscordenoMessage, Interaction } from '@discordeno';
import config from '~config';
@ -10,12 +10,17 @@ import { compilingStats } from 'embeds/common.ts';
import utils from 'utils/utils.ts';
export const stats = async (message: DiscordenoMessage) => {
export const statsSC: CreateGlobalApplicationCommand = {
name: 'stats',
description: 'Shows general statistics on how much the bot is being used.',
};
export const stats = async (msgOrInt: DiscordenoMessage | Interaction) => {
// Light telemetry to see how many times a command is being run
dbClient.execute(queries.callIncCnt('stats')).catch((e) => utils.commonLoggers.dbError('stats.ts:14', 'call sproc INC_CNT on', e));
try {
const m = await message.send(compilingStats);
const m = await utils.sendOrInteract(msgOrInt, 'stats.ts:23', compilingStats, true);
const startTime = new Date().getTime();
// Calculate how many times commands have been run
@ -36,7 +41,7 @@ export const stats = async (message: DiscordenoMessage) => {
const endTime = new Date().getTime();
m.edit({
m?.edit({
embeds: [
{
color: infoColor2,
@ -74,8 +79,8 @@ export const stats = async (message: DiscordenoMessage) => {
},
},
],
}).catch((e: Error) => utils.commonLoggers.messageEditError('stats.ts:38', m, e));
}).catch((e: Error) => utils.commonLoggers.messageEditError('stats.ts:82', m, e));
} catch (e) {
utils.commonLoggers.messageSendError('stats.ts:41', message, e as Error);
utils.commonLoggers.messageSendError('stats.ts:84', msgOrInt, e as Error);
}
};

View File

@ -1,4 +1,4 @@
import { DiscordenoMessage, hasGuildPermissions } from '@discordeno';
import { CreateGlobalApplicationCommand, DiscordApplicationCommandOptionTypes, DiscordenoMessage, hasGuildPermissions, Interaction } from '@discordeno';
import config from '~config';
@ -11,33 +11,59 @@ import { failColor, infoColor1, successColor } from 'embeds/colors.ts';
import utils from 'utils/utils.ts';
export const toggleInline = async (message: DiscordenoMessage, args: string[]) => {
export const toggleInlineSC: CreateGlobalApplicationCommand = {
name: 'toggle-inline-rolls',
description: 'Enable or disable inline rolling for this guild.',
options: [
{
type: DiscordApplicationCommandOptionTypes.SubCommand,
name: 'enable',
description: 'Enables/Allows inline rolling in this guild.',
},
{
type: DiscordApplicationCommandOptionTypes.SubCommand,
name: 'disable',
description: 'Disables/Blocks inline rolling in this guild.',
},
{
type: DiscordApplicationCommandOptionTypes.SubCommand,
name: 'status',
description: 'Gets the current status of inline rolling for this guild.',
},
{
type: DiscordApplicationCommandOptionTypes.SubCommand,
name: 'help',
description: 'Opens the help library to the Toggle Inline help page.',
},
],
};
export const toggleInline = async (msgOrInt: DiscordenoMessage | Interaction, args: string[]) => {
// Light telemetry to see how many times a command is being run
dbClient.execute(queries.callIncCnt('inline')).catch((e) => utils.commonLoggers.dbError('toggleInline.ts:16', 'call sproc INC_CNT on', e));
// Local apiArg in lowercase
const apiArg = (args[0] || '').toLowerCase();
const guildId = BigInt(msgOrInt.guildId ?? '0');
// Alert users who DM the bot that this command is for guilds only
if (message.guildId === 0n) {
message
.send({
if (guildId === 0n) {
utils.sendOrInteract(msgOrInt, 'toggleInline.ts:45', {
embeds: [
{
color: failColor,
title: 'Toggle Inline commands are only available in guilds.',
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('toggleInline.ts:30', message, e));
});
return;
}
let errorOut = false;
const guildQuery = await dbClient.query(`SELECT guildid FROM allow_inline WHERE guildid = ?`, [message.guildId]).catch((e0) => {
const guildQuery = await dbClient.query(`SELECT guildid FROM allow_inline WHERE guildid = ?`, [guildId]).catch((e0) => {
utils.commonLoggers.dbError('toggleInline.ts:36', 'query', e0);
message
.send({
utils.sendOrInteract(msgOrInt, 'toggleInline.ts:59', {
embeds: [
{
color: failColor,
@ -45,39 +71,40 @@ export const toggleInline = async (message: DiscordenoMessage, args: string[]) =
description: 'If this issue persists, please report this to the developers.',
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('toggleInline.ts:47', message, e));
});
errorOut = true;
});
if (errorOut) return;
if (await hasGuildPermissions(message.guildId, message.authorId, ['ADMINISTRATOR'])) {
if (await hasGuildPermissions(guildId, utils.getAuthorIdFromMessageOrInteraction(msgOrInt), ['ADMINISTRATOR'])) {
let enable = false;
switch (apiArg) {
case 'allow':
case 'enable':
enable = true;
await dbClient.execute('INSERT INTO allow_inline(guildid) values(?)', [message.guildId]).catch((e) => {
if (!inlineList.includes(guildId)) {
await dbClient.execute('INSERT INTO allow_inline(guildid) values(?)', [guildId]).catch((e) => {
utils.commonLoggers.dbError('toggleInline.ts:58', 'insert into allow_inline', e);
errorOut = true;
});
if (!errorOut) {
inlineList.push(message.guildId);
inlineList.push(guildId);
}
}
break;
case 'block':
case 'disable':
case 'delete':
await dbClient.execute('DELETE FROM allow_inline WHERE guildid = ?', [message.guildId]).catch((e) => {
await dbClient.execute('DELETE FROM allow_inline WHERE guildid = ?', [guildId]).catch((e) => {
utils.commonLoggers.dbError('toggleInline.ts:65', 'delete from allow_inline', e);
errorOut = true;
});
if (!errorOut && inlineList.indexOf(message.guildId) !== -1) {
inlineList.splice(inlineList.indexOf(message.guildId), 1);
if (!errorOut && inlineList.includes(guildId)) {
inlineList.splice(inlineList.indexOf(guildId), 1);
}
break;
case 'status':
message.send({
utils.sendOrInteract(msgOrInt, 'toggleInline.ts:98', {
embeds: [
{
color: infoColor1,
@ -90,11 +117,11 @@ export const toggleInline = async (message: DiscordenoMessage, args: string[]) =
case 'h':
case 'help':
default:
message.send(generateHelpMessage('inline')).catch((e: Error) => utils.commonLoggers.messageSendError('apiHelp.ts:67', message, e));
utils.sendOrInteract(msgOrInt, 'toggleInline.ts:113', generateHelpMessage('inline'));
return;
}
if (errorOut) {
message.send({
utils.sendOrInteract(msgOrInt, 'toggleInline.ts:117', {
embeds: [
{
color: failColor,
@ -105,7 +132,7 @@ export const toggleInline = async (message: DiscordenoMessage, args: string[]) =
});
return;
}
message.send({
utils.sendOrInteract(msgOrInt, 'toggleInline.ts:128', {
embeds: [
{
color: successColor,
@ -114,15 +141,13 @@ export const toggleInline = async (message: DiscordenoMessage, args: string[]) =
],
});
} else {
message
.send({
utils.sendOrInteract(msgOrInt, 'toggleInline.ts:137', {
embeds: [
{
color: failColor,
title: 'Toggle Inline commands are powerful and can only be used by guild Owners and Admins.',
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('toggleInline.ts:77', message, e));
});
}
};

View File

@ -1,4 +1,4 @@
import { DiscordenoMessage } from '@discordeno';
import { CreateGlobalApplicationCommand, DiscordenoMessage, Interaction } from '@discordeno';
import config from '~config';
@ -9,18 +9,21 @@ import { infoColor1 } from 'embeds/colors.ts';
import utils from 'utils/utils.ts';
export const version = (message: DiscordenoMessage) => {
// Light telemetry to see how many times a command is being run
dbClient.execute(queries.callIncCnt('version')).catch((e) => utils.commonLoggers.dbError('version.ts:15', 'call sproc INC_CNT on', e));
export const versionSC: CreateGlobalApplicationCommand = {
name: 'version',
description: `Gets ${config.name}'s current version`,
};
message
.send({
export const version = (msgOrInt: DiscordenoMessage | Interaction) => {
// Light telemetry to see how many times a command is being run
dbClient.execute(queries.callIncCnt('version')).catch((e) => utils.commonLoggers.dbError('version.ts:14', 'call sproc INC_CNT on', e));
utils.sendOrInteract(msgOrInt, 'version.ts:16', {
embeds: [
{
color: infoColor1,
title: `My current version is ${config.version}`,
},
],
})
.catch((e: Error) => utils.commonLoggers.messageSendError('version.ts:24', message, e));
});
};

View File

@ -1,4 +1,7 @@
import {
ApplicationCommandInteractionDataOptionString,
ApplicationCommandInteractionDataOptionSubCommand,
ApplicationCommandInteractionDataOptionSubCommandGroup,
DiscordenoMessage,
DiscordMessageComponentTypes,
editMessage,
@ -15,6 +18,9 @@ import { log, LogTypes as LT } from '@Log4Deno';
import { repeatRollCustomId } from 'artigen/managers/handler/workerComplete.ts';
import { toggleWebView, webViewCustomId } from 'artigen/utils/embeds.ts';
import { argSpacesSplitRegex } from 'artigen/utils/escape.ts';
import { commands, slashCommandDetails } from 'commands/_index.ts';
import { generateHelpMessage, helpCustomId } from 'commands/helpLibrary/generateHelpMessage.ts';
@ -22,6 +28,8 @@ import { failColor } from 'embeds/colors.ts';
import { messageCreateHandler } from 'events/messageCreate.ts';
import { SlashCommandInteractionWithGuildId } from 'src/mod.d.ts';
import utils from 'utils/utils.ts';
export const InteractionValueSeparator = '\u205a';
@ -76,14 +84,28 @@ export const interactionCreateHandler = async (interaction: Interaction) => {
const ownerId = interaction.data.customId.split(InteractionValueSeparator)[1] ?? 'missingOwnerId';
const userInteractingId = interaction.member?.user.id ?? interaction.user?.id ?? 'missingUserId';
if (ownerId === userInteractingId) {
ackInteraction(interaction);
const botMsg: DiscordenoMessage = await structures.createDiscordenoMessage(interaction.message);
if (botMsg && botMsg.messageReference) {
const rollMsg: DiscordenoMessage = await getMessage(
BigInt(botMsg.messageReference?.channelId ?? '0'),
BigInt(botMsg.messageReference?.messageId ?? '0'),
BigInt(botMsg.messageReference.channelId ?? '0'),
BigInt(botMsg.messageReference.messageId ?? '0'),
);
if (!rollMsg.isBot) {
ackInteraction(interaction);
messageCreateHandler(rollMsg);
} else {
return;
}
}
if (botMsg && botMsg.embeds.length) {
const rollEmbed = botMsg.embeds[0].description ?? '';
const rollStrStartIdx = rollEmbed.indexOf('`') + 1;
const rollStr = rollEmbed.substring(rollStrStartIdx, rollEmbed.indexOf('`', rollStrStartIdx));
commands.roll(interaction, rollStr.split(argSpacesSplitRegex), '');
return;
}
}
sendInteractionResponse(interaction.id, interaction.token, {
type: InteractionResponseTypes.ChannelMessageWithSource,
data: {
@ -97,12 +119,92 @@ export const interactionCreateHandler = async (interaction: Interaction) => {
],
},
}).catch((e) => utils.commonLoggers.messageSendError('interactionCreate.ts:96', interaction, e));
}
return;
}
log(LT.WARN, `UNHANDLED COMPONENT!!! data: ${JSON.stringify(interaction.data)} | Full Interaction: ${JSON.stringify(interaction)}`);
} else if (interaction.type === InteractionTypes.ApplicationCommand && interaction.data) {
switch (interaction.data.name) {
case slashCommandDetails.aliasSC.name: {
// Per the config defined in aliasCmd.ts, there should always be 3 layers to the nesting, with the third's options being the values for the command
// ex: alias => personal/guild => command => [...options]
// Joining them back into one array with spaces between each to match the way the text command works, and since 'alias' will have been shifted out of the array, we start the array with a single spacer
const argSpaces: string[] = [' '];
const guildOrPersonalOpt = (interaction.data.options as ApplicationCommandInteractionDataOptionSubCommandGroup[])?.shift();
if (!guildOrPersonalOpt) break;
if (guildOrPersonalOpt.name === 'guild') {
argSpaces.push('guild', ' ');
}
const commandOpt = (guildOrPersonalOpt.options as ApplicationCommandInteractionDataOptionSubCommand[])?.shift();
if (!commandOpt) break;
argSpaces.push(commandOpt.name);
if (commandOpt.options?.length) {
argSpaces.push(' ');
for (const opt of commandOpt.options) {
argSpaces.push(...opt.value.toString().trim().split(argSpacesSplitRegex));
argSpaces.push(' ');
}
}
const safeInteraction: SlashCommandInteractionWithGuildId = {
guildId: '0',
...interaction,
};
commands.alias(safeInteraction, argSpaces);
return;
}
case slashCommandDetails.heatmapSC.name:
commands.heatmap(interaction);
return;
case slashCommandDetails.helpSC.name:
commands.help(interaction);
return;
case slashCommandDetails.infoSC.name:
commands.info(interaction);
return;
case slashCommandDetails.privacySC.name:
commands.privacy(interaction);
return;
case slashCommandDetails.reportSC.name: {
const option = (interaction.data.options as ApplicationCommandInteractionDataOptionString[])?.shift();
const text = option ? option.value : '';
commands.report(
interaction,
text
.trim()
.split(' ')
.filter((x) => x),
);
return;
}
case slashCommandDetails.ripSC.name:
commands.rip(interaction);
return;
case slashCommandDetails.rollSC.name: {
const option = (interaction.data.options as ApplicationCommandInteractionDataOptionString[])?.shift();
const text = option ? option.value : '';
commands.roll(
interaction,
text
.trim()
.split(argSpacesSplitRegex)
.filter((x) => x),
'',
);
return;
}
case slashCommandDetails.statsSC.name:
commands.stats(interaction);
return;
case slashCommandDetails.toggleInlineSC.name: {
const option = (interaction.data.options as ApplicationCommandInteractionDataOptionSubCommand[])?.shift();
const subCommand = option ? option.name : '';
commands.toggleInline(interaction, [subCommand]);
return;
}
case slashCommandDetails.versionSC.name:
commands.version(interaction);
return;
}
log(LT.WARN, `UNHANDLED APPLICATION COMMAND!!! data: ${JSON.stringify(interaction.data)} | Full Interaction: ${JSON.stringify(interaction)}`);
} else {
log(LT.WARN, `UNHANDLED INTERACTION!!! Missing data! ${JSON.stringify(interaction)} | Full Interaction: ${JSON.stringify(interaction)}`);

View File

@ -3,9 +3,10 @@ import { log, LogTypes as LT } from '@Log4Deno';
import config from '~config';
import commands from 'commands/_index.ts';
import { commands } from 'commands/_index.ts';
import { ignoreList, inlineList } from 'db/common.ts';
import { argSpacesSplitRegex } from 'artigen/utils/escape.ts';
export const messageCreateHandler = (message: DiscordenoMessage) => {
// Ignore all other bots
@ -23,7 +24,14 @@ export const messageCreateHandler = (message: DiscordenoMessage) => {
// Handle inline guilds if allowed
if (inlineList.includes(message.guildId) && message.content.includes(config.prefix) && message.content.includes(config.prefix)) {
commands.roll(message, message.content.trim().split(/([ \n]+)/g), '');
commands.roll(
message,
message.content
.trim()
.split(argSpacesSplitRegex)
.filter((x) => x),
'',
);
}
// return as we are done handling this message
return;
@ -40,7 +48,8 @@ export const messageCreateHandler = (message: DiscordenoMessage) => {
const argSpaces = message.content
.slice(sliceLength)
.trim()
.split(/([ \n]+)/g);
.split(argSpacesSplitRegex)
.filter((x) => x);
const command = args.shift()?.toLowerCase();
argSpaces.shift();

View File

@ -8,6 +8,7 @@ import { successColor } from 'embeds/colors.ts';
import intervals from 'utils/intervals.ts';
import utils from 'utils/utils.ts';
import { announceSlashCommands } from 'commands/_index.ts';
export const readyHandler = () => {
log(LT.INFO, `${config.name} Logged in!`);
@ -66,6 +67,7 @@ export const readyHandler = () => {
LOCALMODE ? log(LT.INFO, 'updateListStatistics not running') : intervals.updateListStatistics(botId, cache.guilds.size + cache.dispatchedGuildIds.size);
intervals.updateHourlyRates();
intervals.updateHeatmapPng();
announceSlashCommands();
editBotStatus({
activities: [
{

5
src/mod.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
import { SlashCommandInteraction } from '@discordeno';
export interface SlashCommandInteractionWithGuildId extends SlashCommandInteraction {
guildId: string;
}

View File

@ -4,7 +4,7 @@
* December 21, 2020
*/
import { log, LogTypes as LT } from '@Log4Deno';
import { DiscordenoMessage, Interaction } from '@discordeno';
import { CreateMessage, DiscordenoMessage, getOriginalInteractionResponse, hasOwnProperty, Interaction, InteractionResponseTypes, sendInteractionResponse } from '@discordeno';
const genericLogger = (level: LT, message: string) => log(level, message);
const messageGetError = (location: string, channelId: bigint | string, messageId: bigint | string, err: Error) =>
@ -17,6 +17,35 @@ const messageDeleteError = (location: string, message: DiscordenoMessage | strin
genericLogger(LT.ERROR, `${location} | Failed to delete message: ${JSON.stringify(message)} | Error: ${err.name} - ${err.message}`);
const dbError = (location: string, type: string, err: Error) => genericLogger(LT.ERROR, `${location} | Failed to ${type} database | Error: ${err.name} - ${err.message}`);
const sendOrInteract = async (
msgOrInt: DiscordenoMessage | Interaction,
callLocation: string,
payload: CreateMessage,
tryGetOriginal = false,
): Promise<void | DiscordenoMessage> => {
let newMsg;
if (hasOwnProperty(msgOrInt, 'token')) {
const interaction = msgOrInt as Interaction;
await sendInteractionResponse(interaction.id, interaction.token, {
type: InteractionResponseTypes.ChannelMessageWithSource,
data: payload,
}).catch((e: Error) => messageSendError(callLocation, interaction, e));
if (tryGetOriginal) newMsg = await getOriginalInteractionResponse(interaction.token);
} else {
newMsg = await msgOrInt.reply(payload).catch((e: Error) => messageSendError(callLocation, msgOrInt, e));
}
return newMsg;
};
const getAuthorIdFromMessageOrInteraction = (msgOrInt: DiscordenoMessage | Interaction): bigint => {
if (hasOwnProperty(msgOrInt, 'token')) {
const interaction = msgOrInt as Interaction;
return BigInt(interaction.member?.user.id ?? interaction.user?.id ?? '0');
} else {
return msgOrInt.authorId;
}
};
export default {
commonLoggers: {
dbError,
@ -25,4 +54,6 @@ export default {
messageGetError,
messageSendError,
},
getAuthorIdFromMessageOrInteraction,
sendOrInteract,
};