update db structure to let init work correctly
This commit is contained in:
parent
ef08cd779a
commit
76e007e2e4
|
@ -2,10 +2,11 @@
|
|||
// DATA WILL BE LOST IF DB ALREADY EXISTS, RUN AT OWN RISK
|
||||
|
||||
import config from '../config.ts';
|
||||
import { dbClient } from '../src/db.ts';
|
||||
import dbClient from '../src/db/client.ts';
|
||||
|
||||
console.log('Attempting to create DB');
|
||||
await dbClient.execute(`CREATE SCHEMA IF NOT EXISTS ${config.db.name};`);
|
||||
console.log('test');
|
||||
await dbClient.execute(`USE ${config.db.name}`);
|
||||
console.log('DB created');
|
||||
|
||||
|
|
|
@ -1,28 +1,47 @@
|
|||
// This file will populate the tables with default values
|
||||
|
||||
import config from '../config.ts';
|
||||
import { dbClient } from '../src/db.ts';
|
||||
import dbClient from '../src/db/client.ts';
|
||||
|
||||
console.log('Attempting to populate DB Admin API key');
|
||||
await dbClient.execute('INSERT INTO all_keys(userid,apiKey) values(?,?)', [config.api.admin, config.api.adminKey]).catch((e) => {
|
||||
console.log('Failed to insert into database', e);
|
||||
console.log('Failed to insert into database', e);
|
||||
});
|
||||
console.log('Inesrtion done');
|
||||
|
||||
console.log('Attempting to insert default commands into command_cnt');
|
||||
const commands = ['ping', 'rip', 'rollhelp', 'help', 'info', 'version', 'report', 'stats', 'roll', 'emojis', 'api', 'privacy', 'mention', 'audit', 'heatmap', 'rollDecorators', 'opt-out', 'opt-in'];
|
||||
const commands = [
|
||||
'ping',
|
||||
'rip',
|
||||
'rollhelp',
|
||||
'help',
|
||||
'info',
|
||||
'version',
|
||||
'report',
|
||||
'stats',
|
||||
'roll',
|
||||
'emojis',
|
||||
'api',
|
||||
'privacy',
|
||||
'mention',
|
||||
'audit',
|
||||
'heatmap',
|
||||
'rollDecorators',
|
||||
'opt-out',
|
||||
'opt-in',
|
||||
];
|
||||
for (const command of commands) {
|
||||
await dbClient.execute('INSERT INTO command_cnt(command) values(?)', [command]).catch((e) => {
|
||||
console.log(`Failed to insert ${command} into database`, e);
|
||||
});
|
||||
await dbClient.execute('INSERT INTO command_cnt(command) values(?)', [command]).catch((e) => {
|
||||
console.log(`Failed to insert ${command} into database`, e);
|
||||
});
|
||||
}
|
||||
console.log('Insertion done');
|
||||
|
||||
console.log('Attempting to insert default hours into roll_time_heatmap');
|
||||
for (let i = 0; i <= 23; i++) {
|
||||
await dbClient.execute('INSERT INTO roll_time_heatmap(hour) values(?)', [i]).catch((e) => {
|
||||
console.log(`Failed to insert hour ${i} into database`, e);
|
||||
});
|
||||
await dbClient.execute('INSERT INTO roll_time_heatmap(hour) values(?)', [i]).catch((e) => {
|
||||
console.log(`Failed to insert hour ${i} into database`, e);
|
||||
});
|
||||
}
|
||||
console.log('Insertion done');
|
||||
|
||||
|
|
572
mod.ts
572
mod.ts
|
@ -7,25 +7,26 @@
|
|||
import config from './config.ts';
|
||||
import { DEBUG, DEVMODE, LOCALMODE } from './flags.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
botId,
|
||||
cache,
|
||||
DiscordActivityTypes,
|
||||
DiscordenoGuild,
|
||||
DiscordenoMessage,
|
||||
editBotNickname,
|
||||
editBotStatus,
|
||||
initLog,
|
||||
Intents,
|
||||
// Log4Deno deps
|
||||
log,
|
||||
LT,
|
||||
// Discordeno deps
|
||||
sendMessage,
|
||||
startBot,
|
||||
// Discordeno deps
|
||||
botId,
|
||||
cache,
|
||||
DiscordActivityTypes,
|
||||
DiscordenoGuild,
|
||||
DiscordenoMessage,
|
||||
editBotNickname,
|
||||
editBotStatus,
|
||||
initLog,
|
||||
Intents,
|
||||
// Log4Deno deps
|
||||
log,
|
||||
LT,
|
||||
// Discordeno deps
|
||||
sendMessage,
|
||||
startBot,
|
||||
} from './deps.ts';
|
||||
import api from './src/api.ts';
|
||||
import { dbClient, ignoreList } from './src/db.ts';
|
||||
import dbClient from './src/db/client.ts';
|
||||
import { ignoreList } from './src/db/common.ts';
|
||||
import commands from './src/commands/_index.ts';
|
||||
import intervals from './src/intervals.ts';
|
||||
import { successColor, warnColor } from './src/commandUtils.ts';
|
||||
|
@ -36,283 +37,302 @@ initLog('logs', DEBUG);
|
|||
|
||||
// Start up the Discord Bot
|
||||
startBot({
|
||||
token: LOCALMODE ? config.localtoken : config.token,
|
||||
intents: [Intents.GuildMessages, Intents.DirectMessages, Intents.Guilds],
|
||||
eventHandlers: {
|
||||
ready: () => {
|
||||
log(LT.INFO, `${config.name} Logged in!`);
|
||||
editBotStatus({
|
||||
activities: [{
|
||||
name: 'Booting up . . .',
|
||||
type: DiscordActivityTypes.Game,
|
||||
createdAt: new Date().getTime(),
|
||||
}],
|
||||
status: 'online',
|
||||
});
|
||||
token: LOCALMODE ? config.localtoken : config.token,
|
||||
intents: [Intents.GuildMessages, Intents.DirectMessages, Intents.Guilds],
|
||||
eventHandlers: {
|
||||
ready: () => {
|
||||
log(LT.INFO, `${config.name} Logged in!`);
|
||||
editBotStatus({
|
||||
activities: [
|
||||
{
|
||||
name: 'Booting up . . .',
|
||||
type: DiscordActivityTypes.Game,
|
||||
createdAt: new Date().getTime(),
|
||||
},
|
||||
],
|
||||
status: 'online',
|
||||
});
|
||||
|
||||
// Interval to rotate the status text every 30 seconds to show off more commands
|
||||
setInterval(async () => {
|
||||
log(LT.LOG, 'Changing bot status');
|
||||
try {
|
||||
// Wrapped in try-catch due to hard crash possible
|
||||
editBotStatus({
|
||||
activities: [{
|
||||
name: await intervals.getRandomStatus(),
|
||||
type: DiscordActivityTypes.Game,
|
||||
createdAt: new Date().getTime(),
|
||||
}],
|
||||
status: 'online',
|
||||
});
|
||||
} catch (e) {
|
||||
log(LT.ERROR, `Failed to update status: ${JSON.stringify(e)}`);
|
||||
}
|
||||
}, 30000);
|
||||
// Interval to rotate the status text every 30 seconds to show off more commands
|
||||
setInterval(async () => {
|
||||
log(LT.LOG, 'Changing bot status');
|
||||
try {
|
||||
// Wrapped in try-catch due to hard crash possible
|
||||
editBotStatus({
|
||||
activities: [
|
||||
{
|
||||
name: await intervals.getRandomStatus(),
|
||||
type: DiscordActivityTypes.Game,
|
||||
createdAt: new Date().getTime(),
|
||||
},
|
||||
],
|
||||
status: 'online',
|
||||
});
|
||||
} catch (e) {
|
||||
log(LT.ERROR, `Failed to update status: ${JSON.stringify(e)}`);
|
||||
}
|
||||
}, 30000);
|
||||
|
||||
// Interval to update bot list stats every 24 hours
|
||||
LOCALMODE ? log(LT.INFO, 'updateListStatistics not running') : setInterval(() => {
|
||||
log(LT.LOG, 'Updating all bot lists statistics');
|
||||
intervals.updateListStatistics(botId, cache.guilds.size + cache.dispatchedGuildIds.size);
|
||||
}, 86400000);
|
||||
// Interval to update bot list stats every 24 hours
|
||||
LOCALMODE
|
||||
? log(LT.INFO, 'updateListStatistics not running')
|
||||
: setInterval(() => {
|
||||
log(LT.LOG, 'Updating all bot lists statistics');
|
||||
intervals.updateListStatistics(botId, cache.guilds.size + cache.dispatchedGuildIds.size);
|
||||
}, 86400000);
|
||||
|
||||
// Interval to update hourlyRates every hour
|
||||
setInterval(() => {
|
||||
log(LT.LOG, 'Updating all command hourlyRates');
|
||||
intervals.updateHourlyRates();
|
||||
}, 3600000);
|
||||
// Interval to update hourlyRates every hour
|
||||
setInterval(() => {
|
||||
log(LT.LOG, 'Updating all command hourlyRates');
|
||||
intervals.updateHourlyRates();
|
||||
}, 3600000);
|
||||
|
||||
// Interval to update heatmap.png every hour
|
||||
setInterval(() => {
|
||||
log(LT.LOG, 'Updating heatmap.png');
|
||||
intervals.updateHeatmapPng();
|
||||
}, 3600000);
|
||||
// Interval to update heatmap.png every hour
|
||||
setInterval(() => {
|
||||
log(LT.LOG, 'Updating heatmap.png');
|
||||
intervals.updateHeatmapPng();
|
||||
}, 3600000);
|
||||
|
||||
// setTimeout added to make sure the startup message does not error out
|
||||
setTimeout(() => {
|
||||
LOCALMODE && editBotNickname(config.devServer, `LOCAL - ${config.name}`);
|
||||
LOCALMODE ? log(LT.INFO, 'updateListStatistics not running') : intervals.updateListStatistics(botId, cache.guilds.size + cache.dispatchedGuildIds.size);
|
||||
intervals.updateHourlyRates();
|
||||
intervals.updateHeatmapPng();
|
||||
editBotStatus({
|
||||
activities: [{
|
||||
name: 'Booting Complete',
|
||||
type: DiscordActivityTypes.Game,
|
||||
createdAt: new Date().getTime(),
|
||||
}],
|
||||
status: 'online',
|
||||
});
|
||||
sendMessage(config.logChannel, {
|
||||
embeds: [{
|
||||
title: `${config.name} is now Online`,
|
||||
color: successColor,
|
||||
fields: [
|
||||
{
|
||||
name: 'Version:',
|
||||
value: `${config.version}`,
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('mod.ts:88', 'Startup', e));
|
||||
}, 1000);
|
||||
},
|
||||
guildCreate: (guild: DiscordenoGuild) => {
|
||||
log(LT.LOG, `Handling joining guild ${JSON.stringify(guild)}`);
|
||||
sendMessage(config.logChannel, {
|
||||
embeds: [{
|
||||
title: 'New Guild Joined!',
|
||||
color: successColor,
|
||||
fields: [
|
||||
{
|
||||
name: 'Name:',
|
||||
value: `${guild.name}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Id:',
|
||||
value: `${guild.id}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Member Count:',
|
||||
value: `${guild.memberCount}`,
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('mod.ts:95', 'Join Guild', e));
|
||||
},
|
||||
guildDelete: (guild: DiscordenoGuild) => {
|
||||
log(LT.LOG, `Handling leaving guild ${JSON.stringify(guild)}`);
|
||||
sendMessage(config.logChannel, {
|
||||
embeds: [{
|
||||
title: 'Removed from Guild',
|
||||
color: warnColor,
|
||||
fields: [
|
||||
{
|
||||
name: 'Name:',
|
||||
value: `${guild.name}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Id:',
|
||||
value: `${guild.id}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Member Count:',
|
||||
value: `${guild.memberCount}`,
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('mod.ts:99', 'Leave Guild', e));
|
||||
dbClient.execute('DELETE FROM allowed_guilds WHERE guildid = ? AND banned = 0', [guild.id]).catch((e) => utils.commonLoggers.dbError('mod.ts:100', 'delete from', e));
|
||||
},
|
||||
debug: DEVMODE ? (dmsg) => log(LT.LOG, `Debug Message | ${JSON.stringify(dmsg)}`) : undefined,
|
||||
messageCreate: (message: DiscordenoMessage) => {
|
||||
// Ignore all other bots
|
||||
if (message.isBot) return;
|
||||
// setTimeout added to make sure the startup message does not error out
|
||||
setTimeout(() => {
|
||||
LOCALMODE && editBotNickname(config.devServer, `LOCAL - ${config.name}`);
|
||||
LOCALMODE ? log(LT.INFO, 'updateListStatistics not running') : intervals.updateListStatistics(botId, cache.guilds.size + cache.dispatchedGuildIds.size);
|
||||
intervals.updateHourlyRates();
|
||||
intervals.updateHeatmapPng();
|
||||
editBotStatus({
|
||||
activities: [
|
||||
{
|
||||
name: 'Booting Complete',
|
||||
type: DiscordActivityTypes.Game,
|
||||
createdAt: new Date().getTime(),
|
||||
},
|
||||
],
|
||||
status: 'online',
|
||||
});
|
||||
sendMessage(config.logChannel, {
|
||||
embeds: [
|
||||
{
|
||||
title: `${config.name} is now Online`,
|
||||
color: successColor,
|
||||
fields: [
|
||||
{
|
||||
name: 'Version:',
|
||||
value: `${config.version}`,
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('mod.ts:88', 'Startup', e));
|
||||
}, 1000);
|
||||
},
|
||||
guildCreate: (guild: DiscordenoGuild) => {
|
||||
log(LT.LOG, `Handling joining guild ${JSON.stringify(guild)}`);
|
||||
sendMessage(config.logChannel, {
|
||||
embeds: [
|
||||
{
|
||||
title: 'New Guild Joined!',
|
||||
color: successColor,
|
||||
fields: [
|
||||
{
|
||||
name: 'Name:',
|
||||
value: `${guild.name}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Id:',
|
||||
value: `${guild.id}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Member Count:',
|
||||
value: `${guild.memberCount}`,
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('mod.ts:95', 'Join Guild', e));
|
||||
},
|
||||
guildDelete: (guild: DiscordenoGuild) => {
|
||||
log(LT.LOG, `Handling leaving guild ${JSON.stringify(guild)}`);
|
||||
sendMessage(config.logChannel, {
|
||||
embeds: [
|
||||
{
|
||||
title: 'Removed from Guild',
|
||||
color: warnColor,
|
||||
fields: [
|
||||
{
|
||||
name: 'Name:',
|
||||
value: `${guild.name}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Id:',
|
||||
value: `${guild.id}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Member Count:',
|
||||
value: `${guild.memberCount}`,
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('mod.ts:99', 'Leave Guild', e));
|
||||
dbClient
|
||||
.execute('DELETE FROM allowed_guilds WHERE guildid = ? AND banned = 0', [guild.id])
|
||||
.catch((e) => utils.commonLoggers.dbError('mod.ts:100', 'delete from', e));
|
||||
},
|
||||
debug: DEVMODE ? (dmsg) => log(LT.LOG, `Debug Message | ${JSON.stringify(dmsg)}`) : undefined,
|
||||
messageCreate: (message: DiscordenoMessage) => {
|
||||
// Ignore all other bots
|
||||
if (message.isBot) return;
|
||||
|
||||
// Ignore users who requested to be ignored
|
||||
if (ignoreList.includes(message.authorId) && (!message.content.startsWith(`${config.prefix}opt-in`) || message.guildId !== 0n)) return;
|
||||
// Ignore users who requested to be ignored
|
||||
if (ignoreList.includes(message.authorId) && (!message.content.startsWith(`${config.prefix}opt-in`) || message.guildId !== 0n)) return;
|
||||
|
||||
// Ignore all messages that are not commands
|
||||
if (message.content.indexOf(config.prefix) !== 0) {
|
||||
// Handle @bot messages
|
||||
if (message.mentionedUserIds[0] === botId && (message.content.trim().startsWith(`<@${botId}>`) || message.content.trim().startsWith(`<@!${botId}>`))) {
|
||||
commands.handleMentions(message);
|
||||
}
|
||||
// Ignore all messages that are not commands
|
||||
if (message.content.indexOf(config.prefix) !== 0) {
|
||||
// Handle @bot messages
|
||||
if (message.mentionedUserIds[0] === botId && (message.content.trim().startsWith(`<@${botId}>`) || message.content.trim().startsWith(`<@!${botId}>`))) {
|
||||
commands.handleMentions(message);
|
||||
}
|
||||
|
||||
// return as we are done handling this command
|
||||
return;
|
||||
}
|
||||
// return as we are done handling this command
|
||||
return;
|
||||
}
|
||||
|
||||
log(LT.LOG, `Handling ${config.prefix}command message: ${JSON.stringify(message)}`);
|
||||
log(LT.LOG, `Handling ${config.prefix}command message: ${JSON.stringify(message)}`);
|
||||
|
||||
// Split into standard command + args format
|
||||
const args = message.content.slice(config.prefix.length).trim().split(/[ \n]+/g);
|
||||
const command = args.shift()?.toLowerCase();
|
||||
// Split into standard command + args format
|
||||
const args = message.content
|
||||
.slice(config.prefix.length)
|
||||
.trim()
|
||||
.split(/[ \n]+/g);
|
||||
const command = args.shift()?.toLowerCase();
|
||||
|
||||
// All commands below here
|
||||
// All commands below here
|
||||
|
||||
switch (command) {
|
||||
case 'opt-out':
|
||||
case 'ignore-me':
|
||||
// [[opt-out or [[ignore-me
|
||||
// Tells the bot to add you to the ignore list.
|
||||
commands.optOut(message);
|
||||
break;
|
||||
case 'opt-in':
|
||||
// [[opt-in
|
||||
// Tells the bot to remove you from the ignore list.
|
||||
commands.optIn(message);
|
||||
break;
|
||||
case 'ping':
|
||||
// [[ping
|
||||
// Its a ping test, what else do you want.
|
||||
commands.ping(message);
|
||||
break;
|
||||
case 'rip':
|
||||
case 'memory':
|
||||
// [[rip [[memory
|
||||
// Displays a short message I wanted to include
|
||||
commands.rip(message);
|
||||
break;
|
||||
case 'rollhelp':
|
||||
case 'rh':
|
||||
case 'hr':
|
||||
case '??':
|
||||
// [[rollhelp or [[rh or [[hr or [[??
|
||||
// Help command specifically for the roll command
|
||||
commands.rollHelp(message);
|
||||
break;
|
||||
case 'rolldecorators':
|
||||
case 'rd':
|
||||
case 'dr':
|
||||
case '???':
|
||||
// [[rollDecorators or [[rd or [[dr or [[???
|
||||
// Help command specifically for the roll command decorators
|
||||
commands.rollDecorators(message);
|
||||
break;
|
||||
case 'help':
|
||||
case 'h':
|
||||
case '?':
|
||||
// [[help or [[h or [[?
|
||||
// Help command, prints from help file
|
||||
commands.help(message);
|
||||
break;
|
||||
case 'info':
|
||||
case 'i':
|
||||
// [[info or [[i
|
||||
// Info command, prints short desc on bot and some links
|
||||
commands.info(message);
|
||||
break;
|
||||
case 'privacy':
|
||||
// [[privacy
|
||||
// Privacy command, prints short desc on bot's privacy policy
|
||||
commands.privacy(message);
|
||||
break;
|
||||
case 'version':
|
||||
case 'v':
|
||||
// [[version or [[v
|
||||
// Returns version of the bot
|
||||
commands.version(message);
|
||||
break;
|
||||
case 'report':
|
||||
case 'r':
|
||||
// [[report or [[r (command that failed)
|
||||
// Manually report a failed roll
|
||||
commands.report(message, args);
|
||||
break;
|
||||
case 'stats':
|
||||
case 's':
|
||||
// [[stats or [[s
|
||||
// Displays stats on the bot
|
||||
commands.stats(message);
|
||||
break;
|
||||
case 'api':
|
||||
// [[api arg
|
||||
// API sub commands
|
||||
commands.api(message, args);
|
||||
break;
|
||||
case 'audit':
|
||||
// [[audit arg
|
||||
// Audit sub commands
|
||||
commands.audit(message, args);
|
||||
break;
|
||||
case 'heatmap':
|
||||
case 'hm':
|
||||
// [[heatmap or [[hm
|
||||
// Audit sub commands
|
||||
commands.heatmap(message);
|
||||
break;
|
||||
default:
|
||||
// Non-standard commands
|
||||
if (command?.startsWith('xdy')) {
|
||||
// [[xdydz (aka someone copy pasted the template as a roll)
|
||||
// Help command specifically for the roll command
|
||||
commands.rollHelp(message);
|
||||
} else if (command && (`${command}${args.join('')}`).indexOf(config.postfix) > -1) {
|
||||
// [[roll]]
|
||||
// Dice rolling commence!
|
||||
commands.roll(message, args, command);
|
||||
} else if (command) {
|
||||
// [[emoji or [[emojialias
|
||||
// Check if the unhandled command is an emoji request
|
||||
commands.emoji(message, command);
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
},
|
||||
switch (command) {
|
||||
case 'opt-out':
|
||||
case 'ignore-me':
|
||||
// [[opt-out or [[ignore-me
|
||||
// Tells the bot to add you to the ignore list.
|
||||
commands.optOut(message);
|
||||
break;
|
||||
case 'opt-in':
|
||||
// [[opt-in
|
||||
// Tells the bot to remove you from the ignore list.
|
||||
commands.optIn(message);
|
||||
break;
|
||||
case 'ping':
|
||||
// [[ping
|
||||
// Its a ping test, what else do you want.
|
||||
commands.ping(message);
|
||||
break;
|
||||
case 'rip':
|
||||
case 'memory':
|
||||
// [[rip [[memory
|
||||
// Displays a short message I wanted to include
|
||||
commands.rip(message);
|
||||
break;
|
||||
case 'rollhelp':
|
||||
case 'rh':
|
||||
case 'hr':
|
||||
case '??':
|
||||
// [[rollhelp or [[rh or [[hr or [[??
|
||||
// Help command specifically for the roll command
|
||||
commands.rollHelp(message);
|
||||
break;
|
||||
case 'rolldecorators':
|
||||
case 'rd':
|
||||
case 'dr':
|
||||
case '???':
|
||||
// [[rollDecorators or [[rd or [[dr or [[???
|
||||
// Help command specifically for the roll command decorators
|
||||
commands.rollDecorators(message);
|
||||
break;
|
||||
case 'help':
|
||||
case 'h':
|
||||
case '?':
|
||||
// [[help or [[h or [[?
|
||||
// Help command, prints from help file
|
||||
commands.help(message);
|
||||
break;
|
||||
case 'info':
|
||||
case 'i':
|
||||
// [[info or [[i
|
||||
// Info command, prints short desc on bot and some links
|
||||
commands.info(message);
|
||||
break;
|
||||
case 'privacy':
|
||||
// [[privacy
|
||||
// Privacy command, prints short desc on bot's privacy policy
|
||||
commands.privacy(message);
|
||||
break;
|
||||
case 'version':
|
||||
case 'v':
|
||||
// [[version or [[v
|
||||
// Returns version of the bot
|
||||
commands.version(message);
|
||||
break;
|
||||
case 'report':
|
||||
case 'r':
|
||||
// [[report or [[r (command that failed)
|
||||
// Manually report a failed roll
|
||||
commands.report(message, args);
|
||||
break;
|
||||
case 'stats':
|
||||
case 's':
|
||||
// [[stats or [[s
|
||||
// Displays stats on the bot
|
||||
commands.stats(message);
|
||||
break;
|
||||
case 'api':
|
||||
// [[api arg
|
||||
// API sub commands
|
||||
commands.api(message, args);
|
||||
break;
|
||||
case 'audit':
|
||||
// [[audit arg
|
||||
// Audit sub commands
|
||||
commands.audit(message, args);
|
||||
break;
|
||||
case 'heatmap':
|
||||
case 'hm':
|
||||
// [[heatmap or [[hm
|
||||
// Audit sub commands
|
||||
commands.heatmap(message);
|
||||
break;
|
||||
default:
|
||||
// Non-standard commands
|
||||
if (command?.startsWith('xdy')) {
|
||||
// [[xdydz (aka someone copy pasted the template as a roll)
|
||||
// Help command specifically for the roll command
|
||||
commands.rollHelp(message);
|
||||
} else if (command && `${command}${args.join('')}`.indexOf(config.postfix) > -1) {
|
||||
// [[roll]]
|
||||
// Dice rolling commence!
|
||||
commands.roll(message, args, command);
|
||||
} else if (command) {
|
||||
// [[emoji or [[emojialias
|
||||
// Check if the unhandled command is an emoji request
|
||||
commands.emoji(message, command);
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Start up the command prompt for debug usage
|
||||
if (DEBUG) {
|
||||
utils.cmdPrompt(config.logChannel, config.name);
|
||||
utils.cmdPrompt(config.logChannel, config.name);
|
||||
}
|
||||
|
||||
// Start up the API for rolling from third party apps (like excel macros)
|
||||
if (config.api.enable) {
|
||||
api.start();
|
||||
api.start();
|
||||
}
|
||||
|
|
390
src/api.ts
390
src/api.ts
|
@ -6,217 +6,219 @@
|
|||
|
||||
import config from '../config.ts';
|
||||
import {
|
||||
// Log4Deno deps
|
||||
log,
|
||||
LT,
|
||||
// Log4Deno deps
|
||||
log,
|
||||
LT,
|
||||
} from '../deps.ts';
|
||||
import { dbClient } from './db.ts';
|
||||
import dbClient from './db/client.ts';
|
||||
import endpoints from './endpoints/_index.ts';
|
||||
import stdResp from './endpoints/stdResponses.ts';
|
||||
|
||||
// start() returns nothing
|
||||
// start initializes and runs the entire API for the bot
|
||||
const start = async (): Promise<void> => {
|
||||
const server = Deno.listen({ port: config.api.port });
|
||||
log(LT.INFO, `HTTP api running at: http://localhost:${config.api.port}/`);
|
||||
const server = Deno.listen({ port: config.api.port });
|
||||
log(LT.INFO, `HTTP api running at: http://localhost:${config.api.port}/`);
|
||||
|
||||
// rateLimitTime holds all users with the last time they started a rate limit timer
|
||||
const rateLimitTime = new Map<string, number>();
|
||||
// rateLimitCnt holds the number of times the user has called the api in the current rate limit timer
|
||||
const rateLimitCnt = new Map<string, number>();
|
||||
// rateLimitTime holds all users with the last time they started a rate limit timer
|
||||
const rateLimitTime = new Map<string, number>();
|
||||
// rateLimitCnt holds the number of times the user has called the api in the current rate limit timer
|
||||
const rateLimitCnt = new Map<string, number>();
|
||||
|
||||
// Catching every request made to the server
|
||||
for await (const conn of server) {
|
||||
(async () => {
|
||||
const httpConn = Deno.serveHttp(conn);
|
||||
for await (const requestEvent of httpConn) {
|
||||
const request = requestEvent.request;
|
||||
log(LT.LOG, `Handling request: ${JSON.stringify(request.headers)} | ${JSON.stringify(request.method)} | ${JSON.stringify(request.url)}`);
|
||||
// Check if user is authenticated to be using this API
|
||||
let authenticated = false;
|
||||
let rateLimited = false;
|
||||
let updateRateLimitTime = false;
|
||||
let apiUserid = 0n;
|
||||
let apiUseridStr = '';
|
||||
let apiUserEmail = '';
|
||||
let apiUserDelCode = '';
|
||||
// Catching every request made to the server
|
||||
for await (const conn of server) {
|
||||
(async () => {
|
||||
const httpConn = Deno.serveHttp(conn);
|
||||
for await (const requestEvent of httpConn) {
|
||||
const request = requestEvent.request;
|
||||
log(LT.LOG, `Handling request: ${JSON.stringify(request.headers)} | ${JSON.stringify(request.method)} | ${JSON.stringify(request.url)}`);
|
||||
// Check if user is authenticated to be using this API
|
||||
let authenticated = false;
|
||||
let rateLimited = false;
|
||||
let updateRateLimitTime = false;
|
||||
let apiUserid = 0n;
|
||||
let apiUseridStr = '';
|
||||
let apiUserEmail = '';
|
||||
let apiUserDelCode = '';
|
||||
|
||||
// Check the requests API key
|
||||
if (request.headers.has('X-Api-Key')) {
|
||||
// Get the userid and flags for the specific key
|
||||
const dbApiQuery = await dbClient.query('SELECT userid, email, deleteCode FROM all_keys WHERE apiKey = ? AND active = 1 AND banned = 0', [request.headers.get('X-Api-Key')]);
|
||||
// Check the requests API key
|
||||
if (request.headers.has('X-Api-Key')) {
|
||||
// Get the userid and flags for the specific key
|
||||
const dbApiQuery = await dbClient.query('SELECT userid, email, deleteCode FROM all_keys WHERE apiKey = ? AND active = 1 AND banned = 0', [
|
||||
request.headers.get('X-Api-Key'),
|
||||
]);
|
||||
|
||||
// If only one user returned, is not banned, and is currently active, mark as authenticated
|
||||
if (dbApiQuery.length === 1) {
|
||||
apiUserid = BigInt(dbApiQuery[0].userid);
|
||||
apiUserEmail = dbApiQuery[0].email;
|
||||
apiUserDelCode = dbApiQuery[0].deleteCode;
|
||||
authenticated = true;
|
||||
// If only one user returned, is not banned, and is currently active, mark as authenticated
|
||||
if (dbApiQuery.length === 1) {
|
||||
apiUserid = BigInt(dbApiQuery[0].userid);
|
||||
apiUserEmail = dbApiQuery[0].email;
|
||||
apiUserDelCode = dbApiQuery[0].deleteCode;
|
||||
authenticated = true;
|
||||
|
||||
// Rate limiting inits
|
||||
apiUseridStr = apiUserid.toString();
|
||||
const apiTimeNow = new Date().getTime();
|
||||
// Rate limiting inits
|
||||
apiUseridStr = apiUserid.toString();
|
||||
const apiTimeNow = new Date().getTime();
|
||||
|
||||
// Check if user has sent a request recently
|
||||
if (rateLimitTime.has(apiUseridStr) && (((rateLimitTime.get(apiUseridStr) || 0) + config.api.rateLimitTime) > apiTimeNow)) {
|
||||
// Get current count
|
||||
const currentCnt = rateLimitCnt.get(apiUseridStr) || 0;
|
||||
if (currentCnt < config.api.rateLimitCnt) {
|
||||
// Limit not yet exceeded, update count
|
||||
rateLimitCnt.set(apiUseridStr, currentCnt + 1);
|
||||
} else {
|
||||
// Limit exceeded, prevent API use
|
||||
rateLimited = true;
|
||||
}
|
||||
} else {
|
||||
// Update the maps
|
||||
updateRateLimitTime = true;
|
||||
rateLimitCnt.set(apiUseridStr, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check if user has sent a request recently
|
||||
if (rateLimitTime.has(apiUseridStr) && (rateLimitTime.get(apiUseridStr) || 0) + config.api.rateLimitTime > apiTimeNow) {
|
||||
// Get current count
|
||||
const currentCnt = rateLimitCnt.get(apiUseridStr) || 0;
|
||||
if (currentCnt < config.api.rateLimitCnt) {
|
||||
// Limit not yet exceeded, update count
|
||||
rateLimitCnt.set(apiUseridStr, currentCnt + 1);
|
||||
} else {
|
||||
// Limit exceeded, prevent API use
|
||||
rateLimited = true;
|
||||
}
|
||||
} else {
|
||||
// Update the maps
|
||||
updateRateLimitTime = true;
|
||||
rateLimitCnt.set(apiUseridStr, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!rateLimited) {
|
||||
// Get path and query as a string
|
||||
const [urlPath, tempQ] = request.url.split('?');
|
||||
const path = urlPath.split('api')[1];
|
||||
if (!rateLimited) {
|
||||
// Get path and query as a string
|
||||
const [urlPath, tempQ] = request.url.split('?');
|
||||
const path = urlPath.split('api')[1];
|
||||
|
||||
// Turn the query into a map (if it exists)
|
||||
const query = new Map<string, string>();
|
||||
if (tempQ !== undefined) {
|
||||
tempQ.split('&').forEach((e: string) => {
|
||||
log(LT.LOG, `Parsing request query ${request} ${e}`);
|
||||
const [option, params] = e.split('=');
|
||||
query.set(option.toLowerCase(), params);
|
||||
});
|
||||
}
|
||||
// Turn the query into a map (if it exists)
|
||||
const query = new Map<string, string>();
|
||||
if (tempQ !== undefined) {
|
||||
tempQ.split('&').forEach((e: string) => {
|
||||
log(LT.LOG, `Parsing request query ${request} ${e}`);
|
||||
const [option, params] = e.split('=');
|
||||
query.set(option.toLowerCase(), params);
|
||||
});
|
||||
}
|
||||
|
||||
if (path) {
|
||||
if (authenticated) {
|
||||
// Handle the authenticated request
|
||||
switch (request.method) {
|
||||
case 'GET':
|
||||
switch (path.toLowerCase()) {
|
||||
case '/key':
|
||||
case '/key/':
|
||||
endpoints.get.apiKeyAdmin(requestEvent, query, apiUserid);
|
||||
break;
|
||||
case '/channel':
|
||||
case '/channel/':
|
||||
endpoints.get.apiChannel(requestEvent, query, apiUserid);
|
||||
break;
|
||||
case '/roll':
|
||||
case '/roll/':
|
||||
endpoints.get.apiRoll(requestEvent, query, apiUserid);
|
||||
break;
|
||||
default:
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.NotFound('Auth Get'));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'POST':
|
||||
switch (path.toLowerCase()) {
|
||||
case '/channel/add':
|
||||
case '/channel/add/':
|
||||
endpoints.post.apiChannelAdd(requestEvent, query, apiUserid);
|
||||
break;
|
||||
default:
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.NotFound('Auth Post'));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'PUT':
|
||||
switch (path.toLowerCase()) {
|
||||
case '/key/ban':
|
||||
case '/key/ban/':
|
||||
case '/key/unban':
|
||||
case '/key/unban/':
|
||||
case '/key/activate':
|
||||
case '/key/activate/':
|
||||
case '/key/deactivate':
|
||||
case '/key/deactivate/':
|
||||
endpoints.put.apiKeyManage(requestEvent, query, apiUserid, path);
|
||||
break;
|
||||
case '/channel/ban':
|
||||
case '/channel/ban/':
|
||||
case '/channel/unban':
|
||||
case '/channel/unban/':
|
||||
endpoints.put.apiChannelManageBan(requestEvent, query, apiUserid, path);
|
||||
break;
|
||||
case '/channel/activate':
|
||||
case '/channel/activate/':
|
||||
case '/channel/deactivate':
|
||||
case '/channel/deactivate/':
|
||||
endpoints.put.apiChannelManageActive(requestEvent, query, apiUserid, path);
|
||||
break;
|
||||
default:
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.NotFound('Auth Put'));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'DELETE':
|
||||
switch (path.toLowerCase()) {
|
||||
case '/key/delete':
|
||||
case '/key/delete/':
|
||||
endpoints.delete.apiKeyDelete(requestEvent, query, apiUserid, apiUserEmail, apiUserDelCode);
|
||||
break;
|
||||
default:
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.NotFound('Auth Del'));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.MethodNotAllowed('Auth'));
|
||||
break;
|
||||
}
|
||||
if (path) {
|
||||
if (authenticated) {
|
||||
// Handle the authenticated request
|
||||
switch (request.method) {
|
||||
case 'GET':
|
||||
switch (path.toLowerCase()) {
|
||||
case '/key':
|
||||
case '/key/':
|
||||
endpoints.get.apiKeyAdmin(requestEvent, query, apiUserid);
|
||||
break;
|
||||
case '/channel':
|
||||
case '/channel/':
|
||||
endpoints.get.apiChannel(requestEvent, query, apiUserid);
|
||||
break;
|
||||
case '/roll':
|
||||
case '/roll/':
|
||||
endpoints.get.apiRoll(requestEvent, query, apiUserid);
|
||||
break;
|
||||
default:
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.NotFound('Auth Get'));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'POST':
|
||||
switch (path.toLowerCase()) {
|
||||
case '/channel/add':
|
||||
case '/channel/add/':
|
||||
endpoints.post.apiChannelAdd(requestEvent, query, apiUserid);
|
||||
break;
|
||||
default:
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.NotFound('Auth Post'));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'PUT':
|
||||
switch (path.toLowerCase()) {
|
||||
case '/key/ban':
|
||||
case '/key/ban/':
|
||||
case '/key/unban':
|
||||
case '/key/unban/':
|
||||
case '/key/activate':
|
||||
case '/key/activate/':
|
||||
case '/key/deactivate':
|
||||
case '/key/deactivate/':
|
||||
endpoints.put.apiKeyManage(requestEvent, query, apiUserid, path);
|
||||
break;
|
||||
case '/channel/ban':
|
||||
case '/channel/ban/':
|
||||
case '/channel/unban':
|
||||
case '/channel/unban/':
|
||||
endpoints.put.apiChannelManageBan(requestEvent, query, apiUserid, path);
|
||||
break;
|
||||
case '/channel/activate':
|
||||
case '/channel/activate/':
|
||||
case '/channel/deactivate':
|
||||
case '/channel/deactivate/':
|
||||
endpoints.put.apiChannelManageActive(requestEvent, query, apiUserid, path);
|
||||
break;
|
||||
default:
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.NotFound('Auth Put'));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'DELETE':
|
||||
switch (path.toLowerCase()) {
|
||||
case '/key/delete':
|
||||
case '/key/delete/':
|
||||
endpoints.delete.apiKeyDelete(requestEvent, query, apiUserid, apiUserEmail, apiUserDelCode);
|
||||
break;
|
||||
default:
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.NotFound('Auth Del'));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.MethodNotAllowed('Auth'));
|
||||
break;
|
||||
}
|
||||
|
||||
// Update rate limit details
|
||||
if (updateRateLimitTime) {
|
||||
const apiTimeNow = new Date().getTime();
|
||||
rateLimitTime.set(apiUseridStr, apiTimeNow);
|
||||
}
|
||||
} else if (!authenticated) {
|
||||
// Handle the unathenticated request
|
||||
switch (request.method) {
|
||||
case 'GET':
|
||||
switch (path.toLowerCase()) {
|
||||
case '/key':
|
||||
case '/key/':
|
||||
endpoints.get.apiKey(requestEvent, query);
|
||||
break;
|
||||
case '/heatmap.png':
|
||||
endpoints.get.heatmapPng(requestEvent);
|
||||
break;
|
||||
default:
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.NotFound('NoAuth Get'));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.MethodNotAllowed('NoAuth'));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
requestEvent.respondWith(stdResp.Forbidden('What are you trying to do?'));
|
||||
}
|
||||
} else if (authenticated && rateLimited) {
|
||||
// Alert API user that they are doing this too often
|
||||
requestEvent.respondWith(stdResp.TooManyRequests('Slow down, servers are expensive and this bot is free to use.'));
|
||||
} else {
|
||||
// Alert API user that they shouldn't be doing this
|
||||
requestEvent.respondWith(stdResp.Forbidden('Why are you here?'));
|
||||
}
|
||||
}
|
||||
})();
|
||||
}
|
||||
// Update rate limit details
|
||||
if (updateRateLimitTime) {
|
||||
const apiTimeNow = new Date().getTime();
|
||||
rateLimitTime.set(apiUseridStr, apiTimeNow);
|
||||
}
|
||||
} else if (!authenticated) {
|
||||
// Handle the unathenticated request
|
||||
switch (request.method) {
|
||||
case 'GET':
|
||||
switch (path.toLowerCase()) {
|
||||
case '/key':
|
||||
case '/key/':
|
||||
endpoints.get.apiKey(requestEvent, query);
|
||||
break;
|
||||
case '/heatmap.png':
|
||||
endpoints.get.heatmapPng(requestEvent);
|
||||
break;
|
||||
default:
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.NotFound('NoAuth Get'));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.MethodNotAllowed('NoAuth'));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
requestEvent.respondWith(stdResp.Forbidden('What are you trying to do?'));
|
||||
}
|
||||
} else if (authenticated && rateLimited) {
|
||||
// Alert API user that they are doing this too often
|
||||
requestEvent.respondWith(stdResp.TooManyRequests('Slow down, servers are expensive and this bot is free to use.'));
|
||||
} else {
|
||||
// Alert API user that they shouldn't be doing this
|
||||
requestEvent.respondWith(stdResp.Forbidden('Why are you here?'));
|
||||
}
|
||||
}
|
||||
})();
|
||||
}
|
||||
};
|
||||
|
||||
export default { start };
|
||||
|
|
|
@ -1,74 +1,84 @@
|
|||
import { dbClient, queries } from '../db.ts';
|
||||
import dbClient from '../db/client.ts';
|
||||
import { queries } from '../db/common.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
hasGuildPermissions,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
hasGuildPermissions,
|
||||
} from '../../deps.ts';
|
||||
import apiCommands from './apiCmd/_index.ts';
|
||||
import { failColor } from '../commandUtils.ts';
|
||||
import utils from '../utils.ts';
|
||||
|
||||
export const api = async (message: DiscordenoMessage, args: string[]) => {
|
||||
// Light telemetry to see how many times a command is being run
|
||||
dbClient.execute(queries.callIncCnt('api')).catch((e) => utils.commonLoggers.dbError('apiCmd.ts:16', 'call sproc INC_CNT on', e));
|
||||
// Light telemetry to see how many times a command is being run
|
||||
dbClient.execute(queries.callIncCnt('api')).catch((e) => utils.commonLoggers.dbError('apiCmd.ts:16', 'call sproc INC_CNT on', e));
|
||||
|
||||
// Local apiArg in lowercase
|
||||
const apiArg = (args[0] || 'help').toLowerCase();
|
||||
// Local apiArg in lowercase
|
||||
const apiArg = (args[0] || 'help').toLowerCase();
|
||||
|
||||
// Alert users who DM the bot that this command is for guilds only
|
||||
if (message.guildId === 0n) {
|
||||
message.send({
|
||||
embeds: [{
|
||||
color: failColor,
|
||||
title: 'API commands are only available in guilds.',
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('apiCmd.ts:30', message, e));
|
||||
return;
|
||||
}
|
||||
// Alert users who DM the bot that this command is for guilds only
|
||||
if (message.guildId === 0n) {
|
||||
message
|
||||
.send({
|
||||
embeds: [
|
||||
{
|
||||
color: failColor,
|
||||
title: 'API commands are only available in guilds.',
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.messageSendError('apiCmd.ts:30', message, e));
|
||||
return;
|
||||
}
|
||||
|
||||
// Makes sure the user is authenticated to run the API command
|
||||
if (await hasGuildPermissions(message.authorId, message.guildId, ['ADMINISTRATOR'])) {
|
||||
switch (apiArg) {
|
||||
case 'help':
|
||||
case 'h':
|
||||
// [[api help
|
||||
// Shows API help details
|
||||
apiCommands.help(message);
|
||||
break;
|
||||
case 'allow':
|
||||
case 'block':
|
||||
case 'enable':
|
||||
case 'disable':
|
||||
// [[api allow/block
|
||||
// Lets a guild admin allow or ban API rolls from happening in said guild
|
||||
apiCommands.allowBlock(message, apiArg);
|
||||
break;
|
||||
case 'delete':
|
||||
// [[api delete
|
||||
// Lets a guild admin delete their server from the database
|
||||
apiCommands.deleteGuild(message);
|
||||
break;
|
||||
case 'status':
|
||||
// [[api status
|
||||
// Lets a guild admin check the status of API rolling in said guild
|
||||
apiCommands.status(message);
|
||||
break;
|
||||
case 'show-warn':
|
||||
case 'hide-warn':
|
||||
// [[api show-warn/hide-warn
|
||||
// Lets a guild admin decide if the API warning should be shown on messages from the API
|
||||
apiCommands.showHideWarn(message, apiArg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
message.send({
|
||||
embeds: [{
|
||||
color: failColor,
|
||||
title: 'API commands are powerful and can only be used by guild Owners and Admins.',
|
||||
description: 'For information on how to use the API, please check the GitHub README for more information [here](https://github.com/Burn-E99/TheArtificer).',
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('apiCmd.ts:77', message, e));
|
||||
}
|
||||
// Makes sure the user is authenticated to run the API command
|
||||
if (await hasGuildPermissions(message.authorId, message.guildId, ['ADMINISTRATOR'])) {
|
||||
switch (apiArg) {
|
||||
case 'help':
|
||||
case 'h':
|
||||
// [[api help
|
||||
// Shows API help details
|
||||
apiCommands.help(message);
|
||||
break;
|
||||
case 'allow':
|
||||
case 'block':
|
||||
case 'enable':
|
||||
case 'disable':
|
||||
// [[api allow/block
|
||||
// Lets a guild admin allow or ban API rolls from happening in said guild
|
||||
apiCommands.allowBlock(message, apiArg);
|
||||
break;
|
||||
case 'delete':
|
||||
// [[api delete
|
||||
// Lets a guild admin delete their server from the database
|
||||
apiCommands.deleteGuild(message);
|
||||
break;
|
||||
case 'status':
|
||||
// [[api status
|
||||
// Lets a guild admin check the status of API rolling in said guild
|
||||
apiCommands.status(message);
|
||||
break;
|
||||
case 'show-warn':
|
||||
case 'hide-warn':
|
||||
// [[api show-warn/hide-warn
|
||||
// Lets a guild admin decide if the API warning should be shown on messages from the API
|
||||
apiCommands.showHideWarn(message, apiArg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
message
|
||||
.send({
|
||||
embeds: [
|
||||
{
|
||||
color: failColor,
|
||||
title: 'API commands are powerful and can only be used by guild Owners and Admins.',
|
||||
description:
|
||||
'For information on how to use the API, please check the GitHub README for more information [here](https://github.com/Burn-E99/TheArtificer).',
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.messageSendError('apiCmd.ts:77', message, e));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,42 +1,52 @@
|
|||
import { dbClient } from '../../db.ts';
|
||||
import dbClient from '../../db/client.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
} from '../../../deps.ts';
|
||||
import { generateApiFailed, generateApiSuccess } from '../../commandUtils.ts';
|
||||
import utils from '../../utils.ts';
|
||||
|
||||
export const allowBlock = async (message: DiscordenoMessage, apiArg: string) => {
|
||||
let errorOutInitial = false;
|
||||
const guildQuery = await dbClient.query(`SELECT guildid, channelid FROM allowed_guilds WHERE guildid = ? AND channelid = ?`, [message.guildId, message.channelId]).catch((e0) => {
|
||||
utils.commonLoggers.dbError('allowBlock.ts:15', 'query', e0);
|
||||
message.send(generateApiFailed(apiArg)).catch((e: Error) => utils.commonLoggers.messageSendError('allowBlock.ts:16', message, e));
|
||||
errorOutInitial = true;
|
||||
});
|
||||
if (errorOutInitial) return;
|
||||
let errorOutInitial = false;
|
||||
const guildQuery = await dbClient
|
||||
.query(`SELECT guildid, channelid FROM allowed_guilds WHERE guildid = ? AND channelid = ?`, [message.guildId, message.channelId])
|
||||
.catch((e0) => {
|
||||
utils.commonLoggers.dbError('allowBlock.ts:15', 'query', e0);
|
||||
message.send(generateApiFailed(apiArg)).catch((e: Error) => utils.commonLoggers.messageSendError('allowBlock.ts:16', message, e));
|
||||
errorOutInitial = true;
|
||||
});
|
||||
if (errorOutInitial) return;
|
||||
|
||||
let errorOut = false;
|
||||
if (guildQuery.length === 0) {
|
||||
// Since guild is not in our DB, add it in
|
||||
await dbClient.execute(`INSERT INTO allowed_guilds(guildid,channelid,active) values(?,?,?)`, [message.guildId, message.channelId, (apiArg === 'allow' || apiArg === 'enable') ? 1 : 0]).catch(
|
||||
(e0) => {
|
||||
utils.commonLoggers.dbError('allowBlock:26', 'insert into', e0);
|
||||
message.send(generateApiFailed(apiArg)).catch((e: Error) => utils.commonLoggers.messageSendError('allowBlock.ts:27', message, e));
|
||||
errorOut = true;
|
||||
},
|
||||
);
|
||||
} else {
|
||||
// Since guild is in our DB, update it
|
||||
await dbClient.execute(`UPDATE allowed_guilds SET active = ? WHERE guildid = ? AND channelid = ?`, [(apiArg === 'allow' || apiArg === 'enable') ? 1 : 0, message.guildId, message.channelId]).catch(
|
||||
(e0) => {
|
||||
utils.commonLoggers.dbError('allowBlock.ts:35', 'update', e0);
|
||||
message.send(generateApiFailed(apiArg)).catch((e: Error) => utils.commonLoggers.messageSendError('allowBlock.ts:36', message, e));
|
||||
errorOut = true;
|
||||
},
|
||||
);
|
||||
}
|
||||
if (errorOut) return;
|
||||
let errorOut = false;
|
||||
if (guildQuery.length === 0) {
|
||||
// Since guild is not in our DB, add it in
|
||||
await dbClient
|
||||
.execute(`INSERT INTO allowed_guilds(guildid,channelid,active) values(?,?,?)`, [
|
||||
message.guildId,
|
||||
message.channelId,
|
||||
apiArg === 'allow' || apiArg === 'enable' ? 1 : 0,
|
||||
])
|
||||
.catch((e0) => {
|
||||
utils.commonLoggers.dbError('allowBlock:26', 'insert into', e0);
|
||||
message.send(generateApiFailed(apiArg)).catch((e: Error) => utils.commonLoggers.messageSendError('allowBlock.ts:27', message, e));
|
||||
errorOut = true;
|
||||
});
|
||||
} else {
|
||||
// Since guild is in our DB, update it
|
||||
await dbClient
|
||||
.execute(`UPDATE allowed_guilds SET active = ? WHERE guildid = ? AND channelid = ?`, [
|
||||
apiArg === 'allow' || apiArg === 'enable' ? 1 : 0,
|
||||
message.guildId,
|
||||
message.channelId,
|
||||
])
|
||||
.catch((e0) => {
|
||||
utils.commonLoggers.dbError('allowBlock.ts:35', 'update', e0);
|
||||
message.send(generateApiFailed(apiArg)).catch((e: Error) => utils.commonLoggers.messageSendError('allowBlock.ts:36', message, e));
|
||||
errorOut = true;
|
||||
});
|
||||
}
|
||||
if (errorOut) return;
|
||||
|
||||
// We won't get here if there's any errors, so we know it has bee successful, so report as such
|
||||
message.send(generateApiSuccess(`${apiArg}ed`)).catch((e: Error) => utils.commonLoggers.messageSendError('allowBlock.ts:44', message, e));
|
||||
// We won't get here if there's any errors, so we know it has bee successful, so report as such
|
||||
message.send(generateApiSuccess(`${apiArg}ed`)).catch((e: Error) => utils.commonLoggers.messageSendError('allowBlock.ts:44', message, e));
|
||||
};
|
||||
|
|
|
@ -1,31 +1,39 @@
|
|||
import { dbClient } from '../../db.ts';
|
||||
import dbClient from '../../db/client.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
} from '../../../deps.ts';
|
||||
import { failColor, successColor } from '../../commandUtils.ts';
|
||||
import utils from '../../utils.ts';
|
||||
|
||||
export const deleteGuild = async (message: DiscordenoMessage) => {
|
||||
let errorOut = false;
|
||||
await dbClient.execute(`DELETE FROM allowed_guilds WHERE guildid = ? AND channelid = ?`, [message.guildId, message.channelId]).catch((e0) => {
|
||||
utils.commonLoggers.dbError('deleteGuild.ts:15', 'query', e0);
|
||||
message.send({
|
||||
embeds: [{
|
||||
color: failColor,
|
||||
title: 'Failed to delete this guild from the database.',
|
||||
description: 'If this issue persists, please report this to the developers.',
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('deleteGuild.ts:22', message, e));
|
||||
errorOut = true;
|
||||
});
|
||||
if (errorOut) return;
|
||||
let errorOut = false;
|
||||
await dbClient.execute(`DELETE FROM allowed_guilds WHERE guildid = ? AND channelid = ?`, [message.guildId, message.channelId]).catch((e0) => {
|
||||
utils.commonLoggers.dbError('deleteGuild.ts:15', 'query', e0);
|
||||
message
|
||||
.send({
|
||||
embeds: [
|
||||
{
|
||||
color: failColor,
|
||||
title: 'Failed to delete this guild from the database.',
|
||||
description: 'If this issue persists, please report this to the developers.',
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.messageSendError('deleteGuild.ts:22', message, e));
|
||||
errorOut = true;
|
||||
});
|
||||
if (errorOut) return;
|
||||
|
||||
// We won't get here if there's any errors, so we know it has bee successful, so report as such
|
||||
message.send({
|
||||
embeds: [{
|
||||
color: successColor,
|
||||
title: 'This guild\'s API setting has been removed from The Artifier\'s Database.',
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('deleteGuild.ts:33', message, e));
|
||||
// We won't get here if there's any errors, so we know it has bee successful, so report as such
|
||||
message
|
||||
.send({
|
||||
embeds: [
|
||||
{
|
||||
color: successColor,
|
||||
title: "This guild's API setting has been removed from The Artifier's Database.",
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.messageSendError('deleteGuild.ts:33', message, e));
|
||||
};
|
||||
|
|
|
@ -1,38 +1,48 @@
|
|||
import { dbClient } from '../../db.ts';
|
||||
import dbClient from '../../db/client.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
} from '../../../deps.ts';
|
||||
import { generateApiFailed, generateApiSuccess } from '../../commandUtils.ts';
|
||||
import utils from '../../utils.ts';
|
||||
|
||||
export const showHideWarn = async (message: DiscordenoMessage, apiArg: string) => {
|
||||
let errorOutInitial = false;
|
||||
const guildQuery = await dbClient.query(`SELECT guildid, channelid FROM allowed_guilds WHERE guildid = ? AND channelid = ?`, [message.guildId, message.channelId]).catch((e0) => {
|
||||
utils.commonLoggers.dbError('showHideWarn.ts:15', 'query', e0);
|
||||
message.send(generateApiFailed(`${apiArg} on`)).catch((e: Error) => utils.commonLoggers.messageSendError('showHideWarn.ts:16', message, e));
|
||||
errorOutInitial = true;
|
||||
});
|
||||
if (errorOutInitial) return;
|
||||
let errorOutInitial = false;
|
||||
const guildQuery = await dbClient
|
||||
.query(`SELECT guildid, channelid FROM allowed_guilds WHERE guildid = ? AND channelid = ?`, [message.guildId, message.channelId])
|
||||
.catch((e0) => {
|
||||
utils.commonLoggers.dbError('showHideWarn.ts:15', 'query', e0);
|
||||
message.send(generateApiFailed(`${apiArg} on`)).catch((e: Error) => utils.commonLoggers.messageSendError('showHideWarn.ts:16', message, e));
|
||||
errorOutInitial = true;
|
||||
});
|
||||
if (errorOutInitial) return;
|
||||
|
||||
let errorOut = false;
|
||||
if (guildQuery.length === 0) {
|
||||
// Since guild is not in our DB, add it in
|
||||
await dbClient.execute(`INSERT INTO allowed_guilds(guildid,channelid,hidewarn) values(?,?,?)`, [message.guildId, message.channelId, (apiArg === 'hide-warn') ? 1 : 0]).catch((e0) => {
|
||||
utils.commonLoggers.dbError('showHideWarn.ts:25', 'insert inot', e0);
|
||||
message.send(generateApiFailed(`${apiArg} on`)).catch((e: Error) => utils.commonLoggers.messageSendError('showHideWarn.ts:26', message, e));
|
||||
errorOut = true;
|
||||
});
|
||||
} else {
|
||||
// Since guild is in our DB, update it
|
||||
await dbClient.execute(`UPDATE allowed_guilds SET hidewarn = ? WHERE guildid = ? AND channelid = ?`, [(apiArg === 'hide-warn') ? 1 : 0, message.guildId, message.channelId]).catch((e0) => {
|
||||
utils.commonLoggers.dbError('showHideWarn.ts:32', 'update', e0);
|
||||
message.send(generateApiFailed(`${apiArg} on`)).catch((e: Error) => utils.commonLoggers.messageSendError('showHideWarn.ts:33', message, e));
|
||||
errorOut = true;
|
||||
});
|
||||
}
|
||||
if (errorOut) return;
|
||||
let errorOut = false;
|
||||
if (guildQuery.length === 0) {
|
||||
// Since guild is not in our DB, add it in
|
||||
await dbClient
|
||||
.execute(`INSERT INTO allowed_guilds(guildid,channelid,hidewarn) values(?,?,?)`, [message.guildId, message.channelId, apiArg === 'hide-warn' ? 1 : 0])
|
||||
.catch((e0) => {
|
||||
utils.commonLoggers.dbError('showHideWarn.ts:25', 'insert inot', e0);
|
||||
message.send(generateApiFailed(`${apiArg} on`)).catch((e: Error) => utils.commonLoggers.messageSendError('showHideWarn.ts:26', message, e));
|
||||
errorOut = true;
|
||||
});
|
||||
} else {
|
||||
// Since guild is in our DB, update it
|
||||
await dbClient
|
||||
.execute(`UPDATE allowed_guilds SET hidewarn = ? WHERE guildid = ? AND channelid = ?`, [
|
||||
apiArg === 'hide-warn' ? 1 : 0,
|
||||
message.guildId,
|
||||
message.channelId,
|
||||
])
|
||||
.catch((e0) => {
|
||||
utils.commonLoggers.dbError('showHideWarn.ts:32', 'update', e0);
|
||||
message.send(generateApiFailed(`${apiArg} on`)).catch((e: Error) => utils.commonLoggers.messageSendError('showHideWarn.ts:33', message, e));
|
||||
errorOut = true;
|
||||
});
|
||||
}
|
||||
if (errorOut) return;
|
||||
|
||||
// We won't get here if there's any errors, so we know it has bee successful, so report as such
|
||||
message.send(generateApiSuccess(apiArg)).catch((e: Error) => utils.commonLoggers.messageSendError('showHideWarn.ts:40', message, e));
|
||||
// We won't get here if there's any errors, so we know it has bee successful, so report as such
|
||||
message.send(generateApiSuccess(apiArg)).catch((e: Error) => utils.commonLoggers.messageSendError('showHideWarn.ts:40', message, e));
|
||||
};
|
||||
|
|
|
@ -1,37 +1,43 @@
|
|||
import { dbClient } from '../../db.ts';
|
||||
import dbClient from '../../db/client.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
} from '../../../deps.ts';
|
||||
import { failColor, generateApiStatus } from '../../commandUtils.ts';
|
||||
import utils from '../../utils.ts';
|
||||
|
||||
export const status = async (message: DiscordenoMessage) => {
|
||||
// Get status of guild from the db
|
||||
let errorOut = false;
|
||||
const guildQuery = await dbClient.query(`SELECT active, banned FROM allowed_guilds WHERE guildid = ? AND channelid = ?`, [message.guildId, message.channelId]).catch((e0) => {
|
||||
utils.commonLoggers.dbError('status.ts:16', 'query', e0);
|
||||
message.send({
|
||||
embeds: [{
|
||||
color: failColor,
|
||||
title: 'Failed to check API rolls status for this guild.',
|
||||
description: 'If this issue persists, please report this to the developers.',
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('status.ts:23', message, e));
|
||||
errorOut = true;
|
||||
});
|
||||
if (errorOut) return;
|
||||
// Get status of guild from the db
|
||||
let errorOut = false;
|
||||
const guildQuery = await dbClient
|
||||
.query(`SELECT active, banned FROM allowed_guilds WHERE guildid = ? AND channelid = ?`, [message.guildId, message.channelId])
|
||||
.catch((e0) => {
|
||||
utils.commonLoggers.dbError('status.ts:16', 'query', e0);
|
||||
message
|
||||
.send({
|
||||
embeds: [
|
||||
{
|
||||
color: failColor,
|
||||
title: 'Failed to check API rolls status for this guild.',
|
||||
description: 'If this issue persists, please report this to the developers.',
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.messageSendError('status.ts:23', message, e));
|
||||
errorOut = true;
|
||||
});
|
||||
if (errorOut) return;
|
||||
|
||||
// Check if we got an item back or not
|
||||
if (guildQuery.length > 0) {
|
||||
// Check if guild is banned from using API and return appropriate message
|
||||
if (guildQuery[0].banned) {
|
||||
message.send(generateApiStatus(true, false)).catch((e: Error) => utils.commonLoggers.messageSendError('status.ts:32', message, e));
|
||||
} else {
|
||||
message.send(generateApiStatus(false, guildQuery[0].active)).catch((e: Error) => utils.commonLoggers.messageSendError('status.ts:34', message, e));
|
||||
}
|
||||
} else {
|
||||
// Guild is not in DB, therefore they are blocked
|
||||
message.send(generateApiStatus(false, false)).catch((e: Error) => utils.commonLoggers.messageSendError('status.ts:38', message, e));
|
||||
}
|
||||
// Check if we got an item back or not
|
||||
if (guildQuery.length > 0) {
|
||||
// Check if guild is banned from using API and return appropriate message
|
||||
if (guildQuery[0].banned) {
|
||||
message.send(generateApiStatus(true, false)).catch((e: Error) => utils.commonLoggers.messageSendError('status.ts:32', message, e));
|
||||
} else {
|
||||
message.send(generateApiStatus(false, guildQuery[0].active)).catch((e: Error) => utils.commonLoggers.messageSendError('status.ts:34', message, e));
|
||||
}
|
||||
} else {
|
||||
// Guild is not in DB, therefore they are blocked
|
||||
message.send(generateApiStatus(false, false)).catch((e: Error) => utils.commonLoggers.messageSendError('status.ts:38', message, e));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,48 +1,53 @@
|
|||
import config from '../../config.ts';
|
||||
import { dbClient, queries } from '../db.ts';
|
||||
import dbClient from '../db/client.ts';
|
||||
import { queries } from '../db/common.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
} from '../../deps.ts';
|
||||
import auditCommands from './auditCmd/_index.ts';
|
||||
import { failColor } from '../commandUtils.ts';
|
||||
import utils from '../utils.ts';
|
||||
|
||||
export const audit = async (message: DiscordenoMessage, args: string[]) => {
|
||||
// Light telemetry to see how many times a command is being run
|
||||
dbClient.execute(queries.callIncCnt('audit')).catch((e) => utils.commonLoggers.dbError('audit.ts:16', 'call sproc INC_CNT on', e));
|
||||
// Light telemetry to see how many times a command is being run
|
||||
dbClient.execute(queries.callIncCnt('audit')).catch((e) => utils.commonLoggers.dbError('audit.ts:16', 'call sproc INC_CNT on', e));
|
||||
|
||||
// Local apiArg in lowercase
|
||||
const auditArg = (args[0] || 'help').toLowerCase();
|
||||
// Local apiArg in lowercase
|
||||
const auditArg = (args[0] || 'help').toLowerCase();
|
||||
|
||||
// Makes sure the user is authenticated to run the API command
|
||||
if (message.authorId === config.api.admin) {
|
||||
switch (auditArg) {
|
||||
case 'help':
|
||||
case 'h':
|
||||
// [[audit help or [[audit h
|
||||
// Shows API help details
|
||||
auditCommands.auditHelp(message);
|
||||
break;
|
||||
case 'db':
|
||||
// [[audit db
|
||||
// Shows current DB table sizes
|
||||
auditCommands.auditDB(message);
|
||||
break;
|
||||
case 'guilds':
|
||||
// [[audit guilds
|
||||
// Shows breakdown of guilds and detials on them
|
||||
auditCommands.auditGuilds(message);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
message.send({
|
||||
embeds: [{
|
||||
color: failColor,
|
||||
title: `Audit commands are powerful and can only be used by ${config.name}'s owner.`,
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('audit.ts:51', message, e));
|
||||
}
|
||||
// Makes sure the user is authenticated to run the API command
|
||||
if (message.authorId === config.api.admin) {
|
||||
switch (auditArg) {
|
||||
case 'help':
|
||||
case 'h':
|
||||
// [[audit help or [[audit h
|
||||
// Shows API help details
|
||||
auditCommands.auditHelp(message);
|
||||
break;
|
||||
case 'db':
|
||||
// [[audit db
|
||||
// Shows current DB table sizes
|
||||
auditCommands.auditDB(message);
|
||||
break;
|
||||
case 'guilds':
|
||||
// [[audit guilds
|
||||
// Shows breakdown of guilds and detials on them
|
||||
auditCommands.auditGuilds(message);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
message
|
||||
.send({
|
||||
embeds: [
|
||||
{
|
||||
color: failColor,
|
||||
title: `Audit commands are powerful and can only be used by ${config.name}'s owner.`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.messageSendError('audit.ts:51', message, e));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,42 +1,44 @@
|
|||
import { dbClient } from '../../db.ts';
|
||||
import dbClient from '../../db/client.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
EmbedField,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
EmbedField,
|
||||
} from '../../../deps.ts';
|
||||
import { infoColor2 } from '../../commandUtils.ts';
|
||||
import { compilingStats } from '../../commonEmbeds.ts';
|
||||
import utils from '../../utils.ts';
|
||||
|
||||
export const auditDB = async (message: DiscordenoMessage) => {
|
||||
try {
|
||||
const m = await message.send(compilingStats);
|
||||
try {
|
||||
const m = await message.send(compilingStats);
|
||||
|
||||
// Get DB statistics
|
||||
const auditQuery = await dbClient.query(`SELECT * FROM db_size;`).catch((e) => utils.commonLoggers.dbError('auditDB.ts:19', 'query', e));
|
||||
// Get DB statistics
|
||||
const auditQuery = await dbClient.query(`SELECT * FROM db_size;`).catch((e) => utils.commonLoggers.dbError('auditDB.ts:19', 'query', e));
|
||||
|
||||
// Turn all tables into embed fields, currently only properly will handle 25 tables, but we'll fix that when artificer gets 26 tables
|
||||
const embedFields: Array<EmbedField> = [];
|
||||
auditQuery.forEach((row: any) => {
|
||||
embedFields.push({
|
||||
name: `${row.table}`,
|
||||
value: `**Size:** ${row.size} MB
|
||||
// Turn all tables into embed fields, currently only properly will handle 25 tables, but we'll fix that when artificer gets 26 tables
|
||||
const embedFields: Array<EmbedField> = [];
|
||||
auditQuery.forEach((row: any) => {
|
||||
embedFields.push({
|
||||
name: `${row.table}`,
|
||||
value: `**Size:** ${row.size} MB
|
||||
**Rows:** ${row.rows}`,
|
||||
inline: true,
|
||||
});
|
||||
});
|
||||
inline: true,
|
||||
});
|
||||
});
|
||||
|
||||
// Send the results
|
||||
m.edit({
|
||||
embeds: [{
|
||||
color: infoColor2,
|
||||
title: 'Database Audit',
|
||||
description: 'Lists all tables with their current size and row count.',
|
||||
timestamp: new Date().toISOString(),
|
||||
fields: embedFields,
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageEditError('auditDB.ts:43', message, e));
|
||||
} catch (e) {
|
||||
utils.commonLoggers.messageSendError('auditDB.ts:45', message, e);
|
||||
}
|
||||
// Send the results
|
||||
m.edit({
|
||||
embeds: [
|
||||
{
|
||||
color: infoColor2,
|
||||
title: 'Database Audit',
|
||||
description: 'Lists all tables with their current size and row count.',
|
||||
timestamp: new Date().toISOString(),
|
||||
fields: embedFields,
|
||||
},
|
||||
],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageEditError('auditDB.ts:43', message, e));
|
||||
} catch (e) {
|
||||
utils.commonLoggers.messageSendError('auditDB.ts:45', message, e);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import config from '../../config.ts';
|
||||
import { dbClient, queries } from '../db.ts';
|
||||
import dbClient from '../db/client.ts';
|
||||
import { queries } from '../db/common.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Log4Deno deps
|
||||
log,
|
||||
LT,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Log4Deno deps
|
||||
log,
|
||||
LT,
|
||||
} from '../../deps.ts';
|
||||
import { EmojiConf } from '../mod.d.ts';
|
||||
import utils from '../utils.ts';
|
||||
|
@ -13,28 +14,30 @@ import utils from '../utils.ts';
|
|||
const allEmojiAliases: string[] = [];
|
||||
|
||||
config.emojis.forEach((emji: EmojiConf) => {
|
||||
allEmojiAliases.push(...emji.aliases);
|
||||
allEmojiAliases.push(...emji.aliases);
|
||||
});
|
||||
|
||||
export const emoji = (message: DiscordenoMessage, command: string) => {
|
||||
// shortcut
|
||||
if (allEmojiAliases.indexOf(command)) {
|
||||
// Start looping thru the possible emojis
|
||||
config.emojis.some((emji: EmojiConf) => {
|
||||
log(LT.LOG, `Checking if command was emoji ${JSON.stringify(emji)}`);
|
||||
// If a match gets found
|
||||
if (emji.aliases.indexOf(command || '') > -1) {
|
||||
// Light telemetry to see how many times a command is being run
|
||||
dbClient.execute(queries.callIncCnt('emojis')).catch((e) => utils.commonLoggers.dbError('emojis.ts:28', 'call sproc INC_CNT on', e));
|
||||
// shortcut
|
||||
if (allEmojiAliases.indexOf(command)) {
|
||||
// Start looping thru the possible emojis
|
||||
config.emojis.some((emji: EmojiConf) => {
|
||||
log(LT.LOG, `Checking if command was emoji ${JSON.stringify(emji)}`);
|
||||
// If a match gets found
|
||||
if (emji.aliases.indexOf(command || '') > -1) {
|
||||
// Light telemetry to see how many times a command is being run
|
||||
dbClient.execute(queries.callIncCnt('emojis')).catch((e) => utils.commonLoggers.dbError('emojis.ts:28', 'call sproc INC_CNT on', e));
|
||||
|
||||
// Send the needed emoji
|
||||
message.send(`<${emji.animated ? 'a' : ''}:${emji.name}:${emji.id}>`).catch((e: Error) => utils.commonLoggers.messageSendError('emoji.ts:33', message, e));
|
||||
// And attempt to delete if needed
|
||||
if (emji.deleteSender) {
|
||||
message.delete().catch((e: Error) => utils.commonLoggers.messageDeleteError('emoji.ts:36', message, e));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
// Send the needed emoji
|
||||
message
|
||||
.send(`<${emji.animated ? 'a' : ''}:${emji.name}:${emji.id}>`)
|
||||
.catch((e: Error) => utils.commonLoggers.messageSendError('emoji.ts:33', message, e));
|
||||
// And attempt to delete if needed
|
||||
if (emji.deleteSender) {
|
||||
message.delete().catch((e: Error) => utils.commonLoggers.messageDeleteError('emoji.ts:36', message, e));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,31 +1,38 @@
|
|||
import config from '../../config.ts';
|
||||
import { dbClient, queries } from '../db.ts';
|
||||
import dbClient from '../db/client.ts';
|
||||
import { queries } from '../db/common.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Log4Deno deps
|
||||
log,
|
||||
LT,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Log4Deno deps
|
||||
log,
|
||||
LT,
|
||||
} from '../../deps.ts';
|
||||
import { infoColor1 } from '../commandUtils.ts';
|
||||
import utils from '../utils.ts';
|
||||
|
||||
export const handleMentions = (message: DiscordenoMessage) => {
|
||||
log(LT.LOG, `Handling @mention message: ${JSON.stringify(message)}`);
|
||||
log(LT.LOG, `Handling @mention message: ${JSON.stringify(message)}`);
|
||||
|
||||
// Light telemetry to see how many times a command is being run
|
||||
dbClient.execute(queries.callIncCnt('mention')).catch((e) => utils.commonLoggers.dbError('handleMentions.ts:17', 'call sproc INC_CNT on', e));
|
||||
// Light telemetry to see how many times a command is being run
|
||||
dbClient.execute(queries.callIncCnt('mention')).catch((e) => utils.commonLoggers.dbError('handleMentions.ts:17', 'call sproc INC_CNT on', e));
|
||||
|
||||
message.send({
|
||||
embeds: [{
|
||||
color: infoColor1,
|
||||
title: `Hello! I am ${config.name}!`,
|
||||
fields: [{
|
||||
name: 'I am a bot that specializes in rolling dice and doing basic algebra.',
|
||||
value: `To learn about my available commands, please run \`${config.prefix}help\`.
|
||||
message
|
||||
.send({
|
||||
embeds: [
|
||||
{
|
||||
color: infoColor1,
|
||||
title: `Hello! I am ${config.name}!`,
|
||||
fields: [
|
||||
{
|
||||
name: 'I am a bot that specializes in rolling dice and doing basic algebra.',
|
||||
value: `To learn about my available commands, please run \`${config.prefix}help\`.
|
||||
|
||||
Want me to ignore you? Simply run \`${config.prefix}opt-out\` and ${config.name} will no longer read your messages or respond to you.`,
|
||||
}],
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('handleMentions.ts:30', message, e));
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.messageSendError('handleMentions.ts:30', message, e));
|
||||
};
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { dbClient, queries } from '../db.ts';
|
||||
import dbClient from '../db/client.ts';
|
||||
import { queries } from '../db/common.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
} from '../../deps.ts';
|
||||
import config from '../../config.ts';
|
||||
import { failColor, infoColor2 } from '../commandUtils.ts';
|
||||
|
@ -9,33 +10,41 @@ import utils from '../utils.ts';
|
|||
import intervals from '../intervals.ts';
|
||||
|
||||
export const heatmap = async (message: DiscordenoMessage) => {
|
||||
// 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));
|
||||
// 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({
|
||||
embeds: [{
|
||||
title: 'Roll Heatmap',
|
||||
description: `Over time, this image will show a nice pattern of when rolls are requested the most.
|
||||
if (config.api.enable) {
|
||||
message
|
||||
.send({
|
||||
embeds: [
|
||||
{
|
||||
title: 'Roll Heatmap',
|
||||
description: `Over time, this image will show a nice pattern of when rolls are requested the most.
|
||||
|
||||
Least Rolls: ${intervals.getMinRollCnt()}
|
||||
Most Rolls: ${intervals.getMaxRollCnt()}`,
|
||||
footer: {
|
||||
text: 'Data is shown in US Eastern Time. | This heatmap uses data starting 6/26/2022.',
|
||||
},
|
||||
color: infoColor2,
|
||||
image: {
|
||||
url: `${config.api.publicDomain}api/heatmap.png`,
|
||||
},
|
||||
}],
|
||||
}).catch((e) => utils.commonLoggers.messageSendError('heatmap.ts:21', message, e));
|
||||
} else {
|
||||
message.send({
|
||||
embeds: [{
|
||||
title: 'Roll Heatmap Disabled',
|
||||
description: 'This command requires the bot\'s API to be enabled. If you are the host of this bot, check your `config.ts` file to enable it.',
|
||||
color: failColor,
|
||||
}],
|
||||
}).catch((e) => utils.commonLoggers.messageSendError('heatmap.ts:21', message, e));
|
||||
}
|
||||
footer: {
|
||||
text: 'Data is shown in US Eastern Time. | This heatmap uses data starting 6/26/2022.',
|
||||
},
|
||||
color: infoColor2,
|
||||
image: {
|
||||
url: `${config.api.publicDomain}api/heatmap.png`,
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e) => utils.commonLoggers.messageSendError('heatmap.ts:21', message, e));
|
||||
} else {
|
||||
message
|
||||
.send({
|
||||
embeds: [
|
||||
{
|
||||
title: 'Roll Heatmap Disabled',
|
||||
description: "This command requires the bot's API to be enabled. If you are the host of this bot, check your `config.ts` file to enable it.",
|
||||
color: failColor,
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e) => utils.commonLoggers.messageSendError('heatmap.ts:21', message, e));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,98 +1,102 @@
|
|||
import config from '../../config.ts';
|
||||
import { dbClient, queries } from '../db.ts';
|
||||
import dbClient from '../db/client.ts';
|
||||
import { queries } from '../db/common.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
} from '../../deps.ts';
|
||||
import { infoColor2 } from '../commandUtils.ts';
|
||||
import utils from '../utils.ts';
|
||||
|
||||
export const help = (message: DiscordenoMessage) => {
|
||||
// Light telemetry to see how many times a command is being run
|
||||
dbClient.execute(queries.callIncCnt('help')).catch((e) => utils.commonLoggers.dbError('htlp.ts:15', 'call sproc INC_CNT on', e));
|
||||
// Light telemetry to see how many times a command is being run
|
||||
dbClient.execute(queries.callIncCnt('help')).catch((e) => utils.commonLoggers.dbError('htlp.ts:15', 'call sproc INC_CNT on', e));
|
||||
|
||||
message.send({
|
||||
embeds: [{
|
||||
color: infoColor2,
|
||||
title: 'The Artificer\'s Available Commands:',
|
||||
fields: [
|
||||
{
|
||||
name: `\`${config.prefix}?\``,
|
||||
value: 'This command',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}rollhelp\` or \`${config.prefix}??\``,
|
||||
value: `Details on how to use the roll command, listed as \`${config.prefix}xdy...${config.postfix}\` below`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}rollDecorators\` or \`${config.prefix}???\``,
|
||||
value: `Details on how to use decorators on the roll command`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}api [subcommand]\``,
|
||||
value: `Administrative tools for the bots's API, run \`${config.prefix}api help\` for more details`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}ping\``,
|
||||
value: 'Pings the bot to check connectivity',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}info\``,
|
||||
value: 'Prints some information and links relating to the bot',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}privacy\``,
|
||||
value: 'Prints some information about the Privacy Policy',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}version\``,
|
||||
value: 'Prints the bots version',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}popcat\``,
|
||||
value: 'Popcat',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}report [text]\``,
|
||||
value: 'Report a command that failed to run',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}stats\``,
|
||||
value: 'Statistics on the bot',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}heatmap\``,
|
||||
value: 'Heatmap of when the roll command is run the most',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}opt-out\` or \`${config.prefix}ignore-me\``,
|
||||
value: 'Adds you to an ignore list so the bot will never respond to you',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}opt-in\` **Available via DM ONLY**`,
|
||||
value: 'Removes you from the ignore list',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}xdydzracsq!${config.postfix}\` ...`,
|
||||
value:
|
||||
`Rolls all configs requested, you may repeat the command multiple times in the same message (just ensure you close each roll with \`${config.postfix}\`), run \`${config.prefix}??\` for more details`,
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('help.ts:82', message, e));
|
||||
message
|
||||
.send({
|
||||
embeds: [
|
||||
{
|
||||
color: infoColor2,
|
||||
title: "The Artificer's Available Commands:",
|
||||
fields: [
|
||||
{
|
||||
name: `\`${config.prefix}?\``,
|
||||
value: 'This command',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}rollhelp\` or \`${config.prefix}??\``,
|
||||
value: `Details on how to use the roll command, listed as \`${config.prefix}xdy...${config.postfix}\` below`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}rollDecorators\` or \`${config.prefix}???\``,
|
||||
value: `Details on how to use decorators on the roll command`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}api [subcommand]\``,
|
||||
value: `Administrative tools for the bots's API, run \`${config.prefix}api help\` for more details`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}ping\``,
|
||||
value: 'Pings the bot to check connectivity',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}info\``,
|
||||
value: 'Prints some information and links relating to the bot',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}privacy\``,
|
||||
value: 'Prints some information about the Privacy Policy',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}version\``,
|
||||
value: 'Prints the bots version',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}popcat\``,
|
||||
value: 'Popcat',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}report [text]\``,
|
||||
value: 'Report a command that failed to run',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}stats\``,
|
||||
value: 'Statistics on the bot',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}heatmap\``,
|
||||
value: 'Heatmap of when the roll command is run the most',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}opt-out\` or \`${config.prefix}ignore-me\``,
|
||||
value: 'Adds you to an ignore list so the bot will never respond to you',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}opt-in\` **Available via DM ONLY**`,
|
||||
value: 'Removes you from the ignore list',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: `\`${config.prefix}xdydzracsq!${config.postfix}\` ...`,
|
||||
value: `Rolls all configs requested, you may repeat the command multiple times in the same message (just ensure you close each roll with \`${config.postfix}\`), run \`${config.prefix}??\` for more details`,
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.messageSendError('help.ts:82', message, e));
|
||||
};
|
||||
|
|
|
@ -1,24 +1,29 @@
|
|||
import config from '../../config.ts';
|
||||
import { dbClient, queries } from '../db.ts';
|
||||
import dbClient from '../db/client.ts';
|
||||
import { queries } from '../db/common.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
} from '../../deps.ts';
|
||||
import { infoColor2 } from '../commandUtils.ts';
|
||||
import utils from '../utils.ts';
|
||||
|
||||
export const info = (message: DiscordenoMessage) => {
|
||||
// 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));
|
||||
// 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({
|
||||
embeds: [{
|
||||
color: infoColor2,
|
||||
title: `${config.name}, a Discord bot that specializing in rolling dice and calculating math`,
|
||||
description: `${config.name} is developed by Ean AKA Burn_E99.
|
||||
message
|
||||
.send({
|
||||
embeds: [
|
||||
{
|
||||
color: infoColor2,
|
||||
title: `${config.name}, a Discord bot that specializing in rolling dice and calculating math`,
|
||||
description: `${config.name} is developed by Ean AKA Burn_E99.
|
||||
Additional information can be found on my website [here](https://discord.burne99.com/TheArtificer/).
|
||||
Want to check out my source code? Check it out [here](https://github.com/Burn-E99/TheArtificer).
|
||||
Need help with this bot? Join my support server [here](https://discord.gg/peHASXMZYv).`,
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('info.ts:23', message, e));
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.messageSendError('info.ts:23', message, e));
|
||||
};
|
||||
|
|
|
@ -1,39 +1,48 @@
|
|||
import config from '../../config.ts';
|
||||
import { dbClient, ignoreList, queries } from '../db.ts';
|
||||
import dbClient from '../db/client.ts';
|
||||
import { queries, ignoreList } from '../db/common.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
} from '../../deps.ts';
|
||||
import { failColor, successColor } from '../commandUtils.ts';
|
||||
import utils from '../utils.ts';
|
||||
|
||||
export const optIn = async (message: DiscordenoMessage) => {
|
||||
// Light telemetry to see how many times a command is being run
|
||||
dbClient.execute(queries.callIncCnt('opt-out')).catch((e) => utils.commonLoggers.dbError('optIn.ts:11', 'call sproc INC_CNT on', e));
|
||||
// Light telemetry to see how many times a command is being run
|
||||
dbClient.execute(queries.callIncCnt('opt-out')).catch((e) => utils.commonLoggers.dbError('optIn.ts:11', 'call sproc INC_CNT on', e));
|
||||
|
||||
const idIdx = ignoreList.indexOf(message.authorId);
|
||||
if (idIdx !== -1) {
|
||||
try {
|
||||
ignoreList.splice(idIdx, 1);
|
||||
await dbClient.execute('DELETE FROM ignore_list WHERE userid = ?', [message.authorId]);
|
||||
const idIdx = ignoreList.indexOf(message.authorId);
|
||||
if (idIdx !== -1) {
|
||||
try {
|
||||
ignoreList.splice(idIdx, 1);
|
||||
await dbClient.execute('DELETE FROM ignore_list WHERE userid = ?', [message.authorId]);
|
||||
|
||||
message.reply({
|
||||
embeds: [{
|
||||
color: successColor,
|
||||
title: `${config.name} will now respond to you again.`,
|
||||
description: `If you want ${config.name} to ignore to you again, please run the following command:
|
||||
message
|
||||
.reply({
|
||||
embeds: [
|
||||
{
|
||||
color: successColor,
|
||||
title: `${config.name} will now respond to you again.`,
|
||||
description: `If you want ${config.name} to ignore to you again, please run the following command:
|
||||
|
||||
\`${config.prefix}opt-out\``,
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('optIn.ts:27', message, e));
|
||||
} catch (err) {
|
||||
message.reply({
|
||||
embeds: [{
|
||||
color: failColor,
|
||||
title: 'Opt-In failed',
|
||||
description: 'Please try the command again. If the issue persists, please join the support server, linked in my About Me section.',
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('optIn.ts:27', message, e));
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.messageSendError('optIn.ts:27', message, e));
|
||||
} catch (err) {
|
||||
message
|
||||
.reply({
|
||||
embeds: [
|
||||
{
|
||||
color: failColor,
|
||||
title: 'Opt-In failed',
|
||||
description: 'Please try the command again. If the issue persists, please join the support server, linked in my About Me section.',
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.messageSendError('optIn.ts:27', message, e));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,36 +1,45 @@
|
|||
import config from '../../config.ts';
|
||||
import { dbClient, ignoreList, queries } from '../db.ts';
|
||||
import dbClient from '../db/client.ts';
|
||||
import { queries, ignoreList } from '../db/common.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
} from '../../deps.ts';
|
||||
import { failColor, successColor } from '../commandUtils.ts';
|
||||
import utils from '../utils.ts';
|
||||
|
||||
export const optOut = async (message: DiscordenoMessage) => {
|
||||
// Light telemetry to see how many times a command is being run
|
||||
dbClient.execute(queries.callIncCnt('opt-out')).catch((e) => utils.commonLoggers.dbError('optOut.ts:11', 'call sproc INC_CNT on', e));
|
||||
// Light telemetry to see how many times a command is being run
|
||||
dbClient.execute(queries.callIncCnt('opt-out')).catch((e) => utils.commonLoggers.dbError('optOut.ts:11', 'call sproc INC_CNT on', e));
|
||||
|
||||
try {
|
||||
ignoreList.push(message.authorId);
|
||||
await dbClient.execute('INSERT INTO ignore_list(userid) values(?)', [message.authorId]);
|
||||
try {
|
||||
ignoreList.push(message.authorId);
|
||||
await dbClient.execute('INSERT INTO ignore_list(userid) values(?)', [message.authorId]);
|
||||
|
||||
message.reply({
|
||||
embeds: [{
|
||||
color: successColor,
|
||||
title: `${config.name} will no longer respond to you.`,
|
||||
description: `If you want ${config.name} to respond to you again, please DM ${config.name} the following command:
|
||||
message
|
||||
.reply({
|
||||
embeds: [
|
||||
{
|
||||
color: successColor,
|
||||
title: `${config.name} will no longer respond to you.`,
|
||||
description: `If you want ${config.name} to respond to you again, please DM ${config.name} the following command:
|
||||
|
||||
\`${config.prefix}opt-in\``,
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('optOut.ts:25', message, e));
|
||||
} catch (err) {
|
||||
message.reply({
|
||||
embeds: [{
|
||||
color: failColor,
|
||||
title: 'Opt-Out failed',
|
||||
description: `Please try the command again. If the issue persists, please report this using the \`${config.prefix}report opt-out failed\` command.`,
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('optOut.ts:33', message, e));
|
||||
}
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.messageSendError('optOut.ts:25', message, e));
|
||||
} catch (err) {
|
||||
message
|
||||
.reply({
|
||||
embeds: [
|
||||
{
|
||||
color: failColor,
|
||||
title: 'Opt-Out failed',
|
||||
description: `Please try the command again. If the issue persists, please report this using the \`${config.prefix}report opt-out failed\` command.`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.messageSendError('optOut.ts:33', message, e));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,20 +1,21 @@
|
|||
import { dbClient, queries } from '../db.ts';
|
||||
import dbClient from '../db/client.ts';
|
||||
import { queries } from '../db/common.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
} from '../../deps.ts';
|
||||
import { generatePing } from '../commandUtils.ts';
|
||||
import utils from '../utils.ts';
|
||||
|
||||
export const ping = async (message: DiscordenoMessage) => {
|
||||
// Light telemetry to see how many times a command is being run
|
||||
dbClient.execute(queries.callIncCnt('ping')).catch((e) => utils.commonLoggers.dbError('ping.ts:14', 'call sproc INC_CNT on', e));
|
||||
// Light telemetry to see how many times a command is being run
|
||||
dbClient.execute(queries.callIncCnt('ping')).catch((e) => utils.commonLoggers.dbError('ping.ts:14', 'call sproc INC_CNT on', e));
|
||||
|
||||
// Calculates ping between sending a message and editing it, giving a nice round-trip latency.
|
||||
try {
|
||||
const m = await message.send(generatePing(-1));
|
||||
m.edit(generatePing(m.timestamp - message.timestamp));
|
||||
} catch (e) {
|
||||
utils.commonLoggers.messageSendError('ping.ts:23', message, e);
|
||||
}
|
||||
// Calculates ping between sending a message and editing it, giving a nice round-trip latency.
|
||||
try {
|
||||
const m = await message.send(generatePing(-1));
|
||||
m.edit(generatePing(m.timestamp - message.timestamp));
|
||||
} catch (e) {
|
||||
utils.commonLoggers.messageSendError('ping.ts:23', message, e);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,31 +1,37 @@
|
|||
import config from '../../config.ts';
|
||||
import { dbClient, queries } from '../db.ts';
|
||||
import dbClient from '../db/client.ts';
|
||||
import { queries } from '../db/common.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
} from '../../deps.ts';
|
||||
import { infoColor1 } from '../commandUtils.ts';
|
||||
import utils from '../utils.ts';
|
||||
|
||||
export const privacy = (message: DiscordenoMessage) => {
|
||||
// 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));
|
||||
// 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({
|
||||
embeds: [{
|
||||
color: infoColor1,
|
||||
title: 'Privacy Policy',
|
||||
fields: [{
|
||||
name: 'The Artificer does not track or collect user information via Discord.',
|
||||
value:
|
||||
`The only user submitted information that is stored is submitted via the \`${config.prefix}report\` command. This information is only stored for a short period of time in a location that only the Developer of The Artificer can see.
|
||||
message
|
||||
.send({
|
||||
embeds: [
|
||||
{
|
||||
color: infoColor1,
|
||||
title: 'Privacy Policy',
|
||||
fields: [
|
||||
{
|
||||
name: 'The Artificer does not track or collect user information via Discord.',
|
||||
value: `The only user submitted information that is stored is submitted via the \`${config.prefix}report\` command. This information is only stored for a short period of time in a location that only the Developer of The Artificer can see.
|
||||
|
||||
For more details, please check out the Privacy Policy on the GitHub [here](https://github.com/Burn-E99/TheArtificer/blob/master/PRIVACY.md).
|
||||
|
||||
Terms of Service can also be found on GitHub [here](https://github.com/Burn-E99/TheArtificer/blob/master/TERMS.md).
|
||||
|
||||
Want me to ignore you? Simply run \`${config.prefix}opt-out\` and ${config.name} will no longer read your messages or respond to you.`,
|
||||
}],
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('privacy.ts:33', message, e));
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.messageSendError('privacy.ts:33', message, e));
|
||||
};
|
||||
|
|
|
@ -1,34 +1,43 @@
|
|||
import config from '../../config.ts';
|
||||
import { dbClient, queries } from '../db.ts';
|
||||
import dbClient from '../db/client.ts';
|
||||
import { queries } from '../db/common.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Discordeno deps
|
||||
sendMessage,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Discordeno deps
|
||||
sendMessage,
|
||||
} from '../../deps.ts';
|
||||
import { failColor, generateReport, successColor } from '../commandUtils.ts';
|
||||
import utils from '../utils.ts';
|
||||
|
||||
export const report = (message: DiscordenoMessage, 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));
|
||||
// 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));
|
||||
|
||||
if (args.join(' ')) {
|
||||
sendMessage(config.reportChannel, generateReport(args.join(' '))).catch((e: Error) => utils.commonLoggers.messageSendError('report.ts:22', message, e));
|
||||
message.send({
|
||||
embeds: [{
|
||||
color: successColor,
|
||||
title: 'Failed command has been reported to my developer.',
|
||||
description: `For more in depth support, and information about planned maintenance, please join the support server [here](https://discord.gg/peHASXMZYv).`,
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('report.ts:29', message, e));
|
||||
} else {
|
||||
message.send({
|
||||
embeds: [{
|
||||
color: failColor,
|
||||
title: 'Please provide a short description of what failed',
|
||||
description: 'Providing a short description helps my developer quickly diagnose what went wrong.',
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('report.ts:37', message, e));
|
||||
}
|
||||
if (args.join(' ')) {
|
||||
sendMessage(config.reportChannel, generateReport(args.join(' '))).catch((e: Error) => utils.commonLoggers.messageSendError('report.ts:22', message, e));
|
||||
message
|
||||
.send({
|
||||
embeds: [
|
||||
{
|
||||
color: successColor,
|
||||
title: 'Failed command has been reported to my developer.',
|
||||
description: `For more in depth support, and information about planned maintenance, please join the support server [here](https://discord.gg/peHASXMZYv).`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.messageSendError('report.ts:29', message, e));
|
||||
} else {
|
||||
message
|
||||
.send({
|
||||
embeds: [
|
||||
{
|
||||
color: failColor,
|
||||
title: 'Please provide a short description of what failed',
|
||||
description: 'Providing a short description helps my developer quickly diagnose what went wrong.',
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.messageSendError('report.ts:37', message, e));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,22 +1,27 @@
|
|||
import { dbClient, queries } from '../db.ts';
|
||||
import dbClient from '../db/client.ts';
|
||||
import { queries } from '../db/common.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
} from '../../deps.ts';
|
||||
import { infoColor2 } from '../commandUtils.ts';
|
||||
import utils from '../utils.ts';
|
||||
|
||||
export const rip = (message: DiscordenoMessage) => {
|
||||
// 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));
|
||||
// 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({
|
||||
embeds: [{
|
||||
color: infoColor2,
|
||||
title: 'The Artificer was built in memory of my Grandmother, Babka',
|
||||
description: `With much love, Ean
|
||||
message
|
||||
.send({
|
||||
embeds: [
|
||||
{
|
||||
color: infoColor2,
|
||||
title: 'The Artificer was built in memory of my Grandmother, Babka',
|
||||
description: `With much love, Ean
|
||||
|
||||
December 21, 2020`,
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('rip.ts:26', message, e));
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.messageSendError('rip.ts:26', message, e));
|
||||
};
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import config from '../../config.ts';
|
||||
import { DEVMODE } from '../../flags.ts';
|
||||
import { dbClient, queries } from '../db.ts';
|
||||
import dbClient from '../db/client.ts';
|
||||
import { queries } from '../db/common.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Log4Deno deps
|
||||
log,
|
||||
LT,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Log4Deno deps
|
||||
log,
|
||||
LT,
|
||||
} from '../../deps.ts';
|
||||
import { rollingEmbed, warnColor } from '../commandUtils.ts';
|
||||
import rollFuncs from './roll/_index.ts';
|
||||
|
@ -15,49 +16,51 @@ import { QueuedRoll } from '../mod.d.ts';
|
|||
import utils from '../utils.ts';
|
||||
|
||||
export const roll = async (message: DiscordenoMessage, 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));
|
||||
dbClient.execute(queries.callIncHeatmap(currDateTime)).catch((e) => utils.commonLoggers.dbError('roll.ts:21', 'update', e));
|
||||
// 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));
|
||||
dbClient.execute(queries.callIncHeatmap(currDateTime)).catch((e) => utils.commonLoggers.dbError('roll.ts:21', 'update', e));
|
||||
|
||||
// If DEVMODE is on, only allow this command to be used in the devServer
|
||||
if (DEVMODE && message.guildId !== config.devServer) {
|
||||
message.send({
|
||||
embeds: [{
|
||||
color: warnColor,
|
||||
title: 'Command is in development, please try again later.',
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('roll.ts:30', message, e));
|
||||
return;
|
||||
}
|
||||
// If DEVMODE is on, only allow this command to be used in the devServer
|
||||
if (DEVMODE && message.guildId !== config.devServer) {
|
||||
message
|
||||
.send({
|
||||
embeds: [
|
||||
{
|
||||
color: warnColor,
|
||||
title: 'Command is in development, please try again later.',
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.messageSendError('roll.ts:30', message, e));
|
||||
return;
|
||||
}
|
||||
|
||||
// Rest of this command is in a try-catch to protect all sends/edits from erroring out
|
||||
try {
|
||||
const originalCommand = `${config.prefix}${command} ${args.join(' ')}`;
|
||||
// Rest of this command is in a try-catch to protect all sends/edits from erroring out
|
||||
try {
|
||||
const originalCommand = `${config.prefix}${command} ${args.join(' ')}`;
|
||||
|
||||
const m = await message.reply(rollingEmbed);
|
||||
const m = await message.reply(rollingEmbed);
|
||||
|
||||
// Get modifiers from command
|
||||
const modifiers = rollFuncs.getModifiers(m, args, command, originalCommand);
|
||||
// Get modifiers from command
|
||||
const modifiers = rollFuncs.getModifiers(m, args, command, originalCommand);
|
||||
|
||||
// Return early if the modifiers were invalid
|
||||
if (!modifiers.valid) {
|
||||
return;
|
||||
}
|
||||
// Return early if the modifiers were invalid
|
||||
if (!modifiers.valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Rejoin all of the args and send it into the solver, if solver returns a falsy item, an error object will be substituded in
|
||||
const rollCmd = message.content.substring(2);
|
||||
// Rejoin all of the args and send it into the solver, if solver returns a falsy item, an error object will be substituded in
|
||||
const rollCmd = message.content.substring(2);
|
||||
|
||||
queueRoll(
|
||||
<QueuedRoll> {
|
||||
apiRoll: false,
|
||||
dd: { m, message },
|
||||
rollCmd,
|
||||
modifiers,
|
||||
originalCommand,
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
log(LT.ERROR, `Undandled Error: ${JSON.stringify(e)}`);
|
||||
}
|
||||
queueRoll(<QueuedRoll>{
|
||||
apiRoll: false,
|
||||
dd: { m, message },
|
||||
rollCmd,
|
||||
modifiers,
|
||||
originalCommand,
|
||||
});
|
||||
} catch (e) {
|
||||
log(LT.ERROR, `Undandled Error: ${JSON.stringify(e)}`);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,117 +1,130 @@
|
|||
import config from '../../../config.ts';
|
||||
import { DEVMODE } from '../../../flags.ts';
|
||||
import { dbClient, queries } from '../../db.ts';
|
||||
import dbClient from '../../db/client.ts';
|
||||
import { queries } from '../../db/common.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Log4Deno deps
|
||||
log,
|
||||
LT,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Log4Deno deps
|
||||
log,
|
||||
LT,
|
||||
} from '../../../deps.ts';
|
||||
import { generateRollError } from '../../commandUtils.ts';
|
||||
import { RollModifiers } from '../../mod.d.ts';
|
||||
import utils from '../../utils.ts';
|
||||
|
||||
export const getModifiers = (m: DiscordenoMessage, args: string[], command: string, originalCommand: string): RollModifiers => {
|
||||
const errorType = 'Modifiers invalid:';
|
||||
const modifiers: RollModifiers = {
|
||||
noDetails: false,
|
||||
superNoDetails: false,
|
||||
spoiler: '',
|
||||
maxRoll: false,
|
||||
nominalRoll: false,
|
||||
gmRoll: false,
|
||||
gms: [],
|
||||
order: '',
|
||||
valid: false,
|
||||
count: false,
|
||||
apiWarn: '',
|
||||
};
|
||||
const errorType = 'Modifiers invalid:';
|
||||
const modifiers: RollModifiers = {
|
||||
noDetails: false,
|
||||
superNoDetails: false,
|
||||
spoiler: '',
|
||||
maxRoll: false,
|
||||
nominalRoll: false,
|
||||
gmRoll: false,
|
||||
gms: [],
|
||||
order: '',
|
||||
valid: false,
|
||||
count: false,
|
||||
apiWarn: '',
|
||||
};
|
||||
|
||||
// Check if any of the args are command flags and pull those out into the modifiers object
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
log(LT.LOG, `Checking ${command}${args.join(' ')} for command modifiers ${i}`);
|
||||
let defaultCase = false;
|
||||
switch (args[i].toLowerCase()) {
|
||||
case '-c':
|
||||
modifiers.count = true;
|
||||
break;
|
||||
case '-nd':
|
||||
modifiers.noDetails = true;
|
||||
break;
|
||||
case '-snd':
|
||||
modifiers.superNoDetails = true;
|
||||
break;
|
||||
case '-s':
|
||||
modifiers.spoiler = '||';
|
||||
break;
|
||||
case '-m':
|
||||
modifiers.maxRoll = true;
|
||||
break;
|
||||
case '-n':
|
||||
modifiers.nominalRoll = true;
|
||||
break;
|
||||
case '-gm':
|
||||
modifiers.gmRoll = true;
|
||||
// Check if any of the args are command flags and pull those out into the modifiers object
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
log(LT.LOG, `Checking ${command}${args.join(' ')} for command modifiers ${i}`);
|
||||
let defaultCase = false;
|
||||
switch (args[i].toLowerCase()) {
|
||||
case '-c':
|
||||
modifiers.count = true;
|
||||
break;
|
||||
case '-nd':
|
||||
modifiers.noDetails = true;
|
||||
break;
|
||||
case '-snd':
|
||||
modifiers.superNoDetails = true;
|
||||
break;
|
||||
case '-s':
|
||||
modifiers.spoiler = '||';
|
||||
break;
|
||||
case '-m':
|
||||
modifiers.maxRoll = true;
|
||||
break;
|
||||
case '-n':
|
||||
modifiers.nominalRoll = true;
|
||||
break;
|
||||
case '-gm':
|
||||
modifiers.gmRoll = true;
|
||||
|
||||
// -gm is a little more complex, as we must get all of the GMs that need to be DMd
|
||||
while (((i + 1) < args.length) && args[i + 1].startsWith('<@')) {
|
||||
log(LT.LOG, `Finding all GMs, checking args ${JSON.stringify(args)}`);
|
||||
// Keep looping thru the rest of the args until one does not start with the discord mention code
|
||||
modifiers.gms.push(args[i + 1].replace(/!/g, ''));
|
||||
args.splice(i + 1, 1);
|
||||
}
|
||||
if (modifiers.gms.length < 1) {
|
||||
// If -gm is on and none were found, throw an error
|
||||
m.edit(generateRollError(errorType, 'Must specifiy at least one GM by @mentioning them')).catch((e) => utils.commonLoggers.messageEditError('getModifiers.ts:66', m, e));
|
||||
// -gm is a little more complex, as we must get all of the GMs that need to be DMd
|
||||
while (i + 1 < args.length && args[i + 1].startsWith('<@')) {
|
||||
log(LT.LOG, `Finding all GMs, checking args ${JSON.stringify(args)}`);
|
||||
// Keep looping thru the rest of the args until one does not start with the discord mention code
|
||||
modifiers.gms.push(args[i + 1].replace(/!/g, ''));
|
||||
args.splice(i + 1, 1);
|
||||
}
|
||||
if (modifiers.gms.length < 1) {
|
||||
// If -gm is on and none were found, throw an error
|
||||
m.edit(generateRollError(errorType, 'Must specifiy at least one GM by @mentioning them')).catch((e) =>
|
||||
utils.commonLoggers.messageEditError('getModifiers.ts:66', m, e)
|
||||
);
|
||||
|
||||
if (DEVMODE && config.logRolls) {
|
||||
// If enabled, log rolls so we can verify the bots math
|
||||
dbClient.execute(queries.insertRollLogCmd(0, 1), [originalCommand, 'NoGMsFound', m.id]).catch((e) => utils.commonLoggers.dbError('getModifiers.ts:72', 'insert into', e));
|
||||
}
|
||||
return modifiers;
|
||||
}
|
||||
break;
|
||||
case '-o':
|
||||
// Shift the -o out of the array so the next item is the direction
|
||||
args.splice(i, 1);
|
||||
if (DEVMODE && config.logRolls) {
|
||||
// If enabled, log rolls so we can verify the bots math
|
||||
dbClient
|
||||
.execute(queries.insertRollLogCmd(0, 1), [originalCommand, 'NoGMsFound', m.id])
|
||||
.catch((e) => utils.commonLoggers.dbError('getModifiers.ts:72', 'insert into', e));
|
||||
}
|
||||
return modifiers;
|
||||
}
|
||||
break;
|
||||
case '-o':
|
||||
// Shift the -o out of the array so the next item is the direction
|
||||
args.splice(i, 1);
|
||||
|
||||
if (!args[i] || args[i].toLowerCase()[0] !== 'd' && args[i].toLowerCase()[0] !== 'a') {
|
||||
// If -o is on and asc or desc was not specified, error out
|
||||
m.edit(generateRollError(errorType, 'Must specifiy `a` or `d` to order the rolls ascending or descending')).catch((e) => utils.commonLoggers.messageEditError('getModifiers.ts:81', m, e));
|
||||
if (!args[i] || (args[i].toLowerCase()[0] !== 'd' && args[i].toLowerCase()[0] !== 'a')) {
|
||||
// If -o is on and asc or desc was not specified, error out
|
||||
m.edit(generateRollError(errorType, 'Must specifiy `a` or `d` to order the rolls ascending or descending')).catch((e) =>
|
||||
utils.commonLoggers.messageEditError('getModifiers.ts:81', m, e)
|
||||
);
|
||||
|
||||
if (DEVMODE && config.logRolls) {
|
||||
// If enabled, log rolls so we can verify the bots math
|
||||
dbClient.execute(queries.insertRollLogCmd(0, 1), [originalCommand, 'NoOrderFound', m.id]).catch((e) => utils.commonLoggers.dbError('getModifiers.ts:89', 'insert into', e));
|
||||
}
|
||||
return modifiers;
|
||||
}
|
||||
if (DEVMODE && config.logRolls) {
|
||||
// If enabled, log rolls so we can verify the bots math
|
||||
dbClient
|
||||
.execute(queries.insertRollLogCmd(0, 1), [originalCommand, 'NoOrderFound', m.id])
|
||||
.catch((e) => utils.commonLoggers.dbError('getModifiers.ts:89', 'insert into', e));
|
||||
}
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
modifiers.order = args[i].toLowerCase()[0];
|
||||
break;
|
||||
default:
|
||||
// Default case should not mess with the array
|
||||
defaultCase = true;
|
||||
break;
|
||||
}
|
||||
modifiers.order = args[i].toLowerCase()[0];
|
||||
break;
|
||||
default:
|
||||
// Default case should not mess with the array
|
||||
defaultCase = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!defaultCase) {
|
||||
args.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
if (!defaultCase) {
|
||||
args.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
// maxRoll and nominalRoll cannot both be on, throw an error
|
||||
if (modifiers.maxRoll && modifiers.nominalRoll) {
|
||||
m.edit(generateRollError(errorType, 'Cannot maximise and nominise the roll at the same time')).catch((e) => utils.commonLoggers.messageEditError('getModifiers.ts:106', m, e));
|
||||
// maxRoll and nominalRoll cannot both be on, throw an error
|
||||
if (modifiers.maxRoll && modifiers.nominalRoll) {
|
||||
m.edit(generateRollError(errorType, 'Cannot maximise and nominise the roll at the same time')).catch((e) =>
|
||||
utils.commonLoggers.messageEditError('getModifiers.ts:106', m, e)
|
||||
);
|
||||
|
||||
if (DEVMODE && config.logRolls) {
|
||||
// If enabled, log rolls so we can verify the bots math
|
||||
dbClient.execute(queries.insertRollLogCmd(0, 1), [originalCommand, 'MaxAndNominal', m.id]).catch((e) => utils.commonLoggers.dbError('getModifiers.ts:120', 'insert into', e));
|
||||
}
|
||||
return modifiers;
|
||||
}
|
||||
if (DEVMODE && config.logRolls) {
|
||||
// If enabled, log rolls so we can verify the bots math
|
||||
dbClient
|
||||
.execute(queries.insertRollLogCmd(0, 1), [originalCommand, 'MaxAndNominal', m.id])
|
||||
.catch((e) => utils.commonLoggers.dbError('getModifiers.ts:120', 'insert into', e));
|
||||
}
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
modifiers.valid = true;
|
||||
return modifiers;
|
||||
modifiers.valid = true;
|
||||
return modifiers;
|
||||
};
|
||||
|
|
|
@ -1,71 +1,75 @@
|
|||
import config from '../../config.ts';
|
||||
import { dbClient, queries } from '../db.ts';
|
||||
import dbClient from '../db/client.ts';
|
||||
import { queries } from '../db/common.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
} from '../../deps.ts';
|
||||
import { infoColor2 } from '../commandUtils.ts';
|
||||
import utils from '../utils.ts';
|
||||
|
||||
export const rollDecorators = (message: DiscordenoMessage) => {
|
||||
// Light telemetry to see how many times a command is being run
|
||||
dbClient.execute(queries.callIncCnt('rollDecorators')).catch((e) => utils.commonLoggers.dbError('rollHelp.ts:15', 'call sproc INC_CNT on', e));
|
||||
// Light telemetry to see how many times a command is being run
|
||||
dbClient.execute(queries.callIncCnt('rollDecorators')).catch((e) => utils.commonLoggers.dbError('rollHelp.ts:15', 'call sproc INC_CNT on', e));
|
||||
|
||||
message.send({
|
||||
embeds: [
|
||||
{
|
||||
color: infoColor2,
|
||||
title: 'Roll Command Decorators:',
|
||||
description: `This command also has some useful decorators that can used. These decorators simply need to be placed after all rolls in the message.
|
||||
message
|
||||
.send({
|
||||
embeds: [
|
||||
{
|
||||
color: infoColor2,
|
||||
title: 'Roll Command Decorators:',
|
||||
description: `This command also has some useful decorators that can used. These decorators simply need to be placed after all rolls in the message.
|
||||
|
||||
Examples: \`${config.prefix}d20${config.postfix} -nd\`, \`${config.prefix}d20${config.postfix} -nd -s\`, \`${config.prefix}d20${config.postfix} ${config.prefix}d20${config.postfix} ${config.prefix}d20${config.postfix} -o a\``,
|
||||
fields: [
|
||||
{
|
||||
name: '`-nd` - No Details',
|
||||
value: 'Suppresses all details of the requested roll',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`-snd` - Super No Details',
|
||||
value: 'Suppresses all details of the requested roll and hides no details message',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`-s` - Spoiler',
|
||||
value: 'Spoilers all details of the requested roll',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`-m` - Maximize Roll',
|
||||
value: 'Rolls the theoretical maximum roll, cannot be used with -n',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`-n` - Nominal Roll',
|
||||
value: 'Rolls the theoretical nominal roll, cannot be used with -m',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`-gm @user1 @user2 @usern` - GM Roll',
|
||||
value: 'Rolls the requested roll in GM mode, suppressing all publicly shown results and details and sending the results directly to the specified GMs',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`-c` - Count Rolls',
|
||||
value: 'Shows the Count Embed, containing the count of successful rolls, failed rolls, rerolls, drops, and explosions',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`-o [direction]` - Order Roll',
|
||||
value: `Rolls the requested roll and orders the results in the requested direction
|
||||
fields: [
|
||||
{
|
||||
name: '`-nd` - No Details',
|
||||
value: 'Suppresses all details of the requested roll',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`-snd` - Super No Details',
|
||||
value: 'Suppresses all details of the requested roll and hides no details message',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`-s` - Spoiler',
|
||||
value: 'Spoilers all details of the requested roll',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`-m` - Maximize Roll',
|
||||
value: 'Rolls the theoretical maximum roll, cannot be used with -n',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`-n` - Nominal Roll',
|
||||
value: 'Rolls the theoretical nominal roll, cannot be used with -m',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`-gm @user1 @user2 @usern` - GM Roll',
|
||||
value:
|
||||
'Rolls the requested roll in GM mode, suppressing all publicly shown results and details and sending the results directly to the specified GMs',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`-c` - Count Rolls',
|
||||
value: 'Shows the Count Embed, containing the count of successful rolls, failed rolls, rerolls, drops, and explosions',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`-o [direction]` - Order Roll',
|
||||
value: `Rolls the requested roll and orders the results in the requested direction
|
||||
|
||||
Available directions:
|
||||
\`a\` - Ascending (least to greatest)
|
||||
\`d\` - Descending (greatest to least)`,
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('rollHelp.ts:247', message, e));
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.messageSendError('rollHelp.ts:247', message, e));
|
||||
};
|
||||
|
|
|
@ -1,262 +1,275 @@
|
|||
import config from '../../config.ts';
|
||||
import { dbClient, queries } from '../db.ts';
|
||||
import dbClient from '../db/client.ts';
|
||||
import { queries } from '../db/common.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
} from '../../deps.ts';
|
||||
import { infoColor1, infoColor2, successColor } from '../commandUtils.ts';
|
||||
import utils from '../utils.ts';
|
||||
|
||||
export const rollHelp = (message: DiscordenoMessage) => {
|
||||
// Light telemetry to see how many times a command is being run
|
||||
dbClient.execute(queries.callIncCnt('rollhelp')).catch((e) => utils.commonLoggers.dbError('rollHelp.ts:15', 'call sproc INC_CNT on', e));
|
||||
// Light telemetry to see how many times a command is being run
|
||||
dbClient.execute(queries.callIncCnt('rollhelp')).catch((e) => utils.commonLoggers.dbError('rollHelp.ts:15', 'call sproc INC_CNT on', e));
|
||||
|
||||
message.send({
|
||||
embeds: [
|
||||
{
|
||||
color: infoColor1,
|
||||
title: 'The Artificer\'s Roll Command Details:',
|
||||
description: `You can chain as many of these options as you want, as long as the option does not disallow it.
|
||||
message
|
||||
.send({
|
||||
embeds: [
|
||||
{
|
||||
color: infoColor1,
|
||||
title: "The Artificer's Roll Command Details:",
|
||||
description: `You can chain as many of these options as you want, as long as the option does not disallow it.
|
||||
|
||||
This command also can fully solve math equations with parenthesis.
|
||||
|
||||
The Artificer supports most of the [Roll20 formatting](https://artificer.eanm.dev/roll20). More details and examples can be found [here](https://artificer.eanm.dev/roll20).
|
||||
|
||||
Run \`[[???\` or \`[[rollDecorators\` for details on the roll decorators.`,
|
||||
},
|
||||
{
|
||||
color: infoColor2,
|
||||
title: 'Roll20 Dice Options:',
|
||||
fields: [
|
||||
{
|
||||
name: `\`${config.prefix}xdydzracsq!${config.postfix}\` ...`,
|
||||
value: `Rolls all configs requested, you may repeat the command multiple times in the same message (just ensure you close each roll with \`${config.postfix}\`)`,
|
||||
},
|
||||
{
|
||||
name: '`x` [Optional]',
|
||||
value: `Number of dice to roll, if omitted, 1 is used
|
||||
},
|
||||
{
|
||||
color: infoColor2,
|
||||
title: 'Roll20 Dice Options:',
|
||||
fields: [
|
||||
{
|
||||
name: `\`${config.prefix}xdydzracsq!${config.postfix}\` ...`,
|
||||
value: `Rolls all configs requested, you may repeat the command multiple times in the same message (just ensure you close each roll with \`${config.postfix}\`)`,
|
||||
},
|
||||
{
|
||||
name: '`x` [Optional]',
|
||||
value: `Number of dice to roll, if omitted, 1 is used
|
||||
Additionally, replace \`x\` with \`F\` to roll Fate dice`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`dy` [Required]',
|
||||
value: 'Size of dice to roll, `d20` = 20 sided die',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`dz` or `dlz` [Optional]',
|
||||
value: 'Drops the lowest `z` dice, cannot be used with `kz`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`kz` or `khz` [Optional]',
|
||||
value: 'Keeps the highest `z` dice, cannot be used with `dz`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`dhz` [Optional]',
|
||||
value: 'Drops the highest `z` dice, cannot be used with `kz`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`klz` [Optional]',
|
||||
value: 'Keeps the lowest `z` dice, cannot be used with `dz`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`ra` or `r=q` [Optional]',
|
||||
value: 'Rerolls any rolls that match `a`, `r3` will reroll every die that land on 3, throwing out old rolls, cannot be used with `ro`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`r<q` [Optional]',
|
||||
value: 'Rerolls any rolls that are less than or equal to `a`, `r3` will reroll every die that land on 3, 2, or 1, throwing out old rolls, cannot be used with `ro`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`r>q` [Optional]',
|
||||
value: 'Rerolls any rolls that are greater than or equal to `a`, `r3` will reroll every die that land on 3 or greater, throwing out old rolls, cannot be used with `ro`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`roa` or `ro=q` [Optional]',
|
||||
value: 'Rerolls any rolls that match `a`, `ro3` will reroll each die that lands on 3 ONLY ONE TIME, throwing out old rolls, cannot be used with `r`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`ro<q` [Optional]',
|
||||
value: 'Rerolls any rolls that are less than or equal to `a`, `ro3` will reroll each die that lands on 3, 2, or 1 ONLY ONE TIME, throwing out old rolls, cannot be used with `r`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`ro>q` [Optional]',
|
||||
value: 'Rerolls any rolls that are greater than or equal to `a`, `ro3` will reroll each die that lands on 3 or greater ONLY ONE TIME, throwing out old rolls, cannot be used with `r`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`csq` or `cs=q` [Optional]',
|
||||
value: 'Changes crit score to `q`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`cs<q` [Optional]',
|
||||
value: 'Changes crit score to be less than or equal to `q`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`cs>q` [Optional]',
|
||||
value: 'Changes crit score to be greater than or equal to `q`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`cfq` or `cf=q` [Optional]',
|
||||
value: 'Changes crit fail to `q`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`cf<q` [Optional]',
|
||||
value: 'Changes crit fail to be less than or equal to `q`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`cf>q` [Optional]',
|
||||
value: 'Changes crit fail to be greater than or equal to `q`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!` [Optional]',
|
||||
value: 'Exploding, rolls another `dy` for every crit success',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!o` [Optional]',
|
||||
value: 'Exploding Once, rolls one `dy` for each original crit success',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!p` [Optional]',
|
||||
value: 'Penetrating Explosion, rolls one `dy` for each crit success, but subtracts one from each resulting explosion',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!!` [Optional]',
|
||||
value: 'Compounding Explosion, rolls one `dy` for each crit success, but adds the resulting explosion to the die that caused this explosion',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!=u` [Optional]',
|
||||
value: 'Explode on `u`, rolls another `dy` for every die that lands on `u`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!>u` [Optional]',
|
||||
value: 'Explode on `u` and greater, rolls another `dy` for every die that lands on `u` or greater',
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
color: infoColor2,
|
||||
fields: [
|
||||
{
|
||||
name: '`!<u` [Optional]',
|
||||
value: 'Explode on `u` and under, rolls another `dy` for every die that lands on `u` or less',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!o=u` [Optional]',
|
||||
value: 'Explodes Once on `u`, rolls another `dy` for each original die that landed on `u`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!o>u` [Optional]',
|
||||
value: 'Explode Once on `u` and greater, rolls another `dy` for each original die that landed on `u` or greater',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!o<u` [Optional]',
|
||||
value: 'Explode Once on `u` and under, rolls another `dy` for each original die that landed on `u` or less',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!p=u` [Optional]',
|
||||
value: 'Penetrating Explosion on `u`, rolls one `dy` for each die that lands on `u`, but subtracts one from each resulting explosion',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!p>u` [Optional]',
|
||||
value: 'Penetrating Explosion on `u` and greater, rolls one `dy` for each die that lands on `u` or greater, but subtracts one from each resulting explosion',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!p<u` [Optional]',
|
||||
value: 'Penetrating Explosion on `u` and under, rolls one `dy` for each die that lands on `u` or under, but subtracts one from each resulting explosion',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!!=u` [Optional]',
|
||||
value: 'Compounding Explosion on `u`, rolls one `dy` for each die that lands on `u`, but adds the resulting explosion to the die that caused this explosion',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!!>u` [Optional]',
|
||||
value: 'Compounding Explosion on `u` and greater, rolls one `dy` for each die that lands on `u` or greater, but adds the resulting explosion to the die that caused this explosion',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!!<u` [Optional]',
|
||||
value: 'Compounding Explosion on `u` and under, rolls one `dy` for each die that lands on `u` or under, but adds the resulting explosion to the die that caused this explosion',
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
color: infoColor1,
|
||||
title: 'Custom Dice Options',
|
||||
fields: [
|
||||
{
|
||||
name: 'CWOD Rolling',
|
||||
value: `\`${config.prefix}xcwody${config.postfix}\`
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`dy` [Required]',
|
||||
value: 'Size of dice to roll, `d20` = 20 sided die',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`dz` or `dlz` [Optional]',
|
||||
value: 'Drops the lowest `z` dice, cannot be used with `kz`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`kz` or `khz` [Optional]',
|
||||
value: 'Keeps the highest `z` dice, cannot be used with `dz`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`dhz` [Optional]',
|
||||
value: 'Drops the highest `z` dice, cannot be used with `kz`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`klz` [Optional]',
|
||||
value: 'Keeps the lowest `z` dice, cannot be used with `dz`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`ra` or `r=q` [Optional]',
|
||||
value: 'Rerolls any rolls that match `a`, `r3` will reroll every die that land on 3, throwing out old rolls, cannot be used with `ro`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`r<q` [Optional]',
|
||||
value:
|
||||
'Rerolls any rolls that are less than or equal to `a`, `r3` will reroll every die that land on 3, 2, or 1, throwing out old rolls, cannot be used with `ro`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`r>q` [Optional]',
|
||||
value:
|
||||
'Rerolls any rolls that are greater than or equal to `a`, `r3` will reroll every die that land on 3 or greater, throwing out old rolls, cannot be used with `ro`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`roa` or `ro=q` [Optional]',
|
||||
value:
|
||||
'Rerolls any rolls that match `a`, `ro3` will reroll each die that lands on 3 ONLY ONE TIME, throwing out old rolls, cannot be used with `r`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`ro<q` [Optional]',
|
||||
value:
|
||||
'Rerolls any rolls that are less than or equal to `a`, `ro3` will reroll each die that lands on 3, 2, or 1 ONLY ONE TIME, throwing out old rolls, cannot be used with `r`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`ro>q` [Optional]',
|
||||
value:
|
||||
'Rerolls any rolls that are greater than or equal to `a`, `ro3` will reroll each die that lands on 3 or greater ONLY ONE TIME, throwing out old rolls, cannot be used with `r`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`csq` or `cs=q` [Optional]',
|
||||
value: 'Changes crit score to `q`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`cs<q` [Optional]',
|
||||
value: 'Changes crit score to be less than or equal to `q`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`cs>q` [Optional]',
|
||||
value: 'Changes crit score to be greater than or equal to `q`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`cfq` or `cf=q` [Optional]',
|
||||
value: 'Changes crit fail to `q`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`cf<q` [Optional]',
|
||||
value: 'Changes crit fail to be less than or equal to `q`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`cf>q` [Optional]',
|
||||
value: 'Changes crit fail to be greater than or equal to `q`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!` [Optional]',
|
||||
value: 'Exploding, rolls another `dy` for every crit success',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!o` [Optional]',
|
||||
value: 'Exploding Once, rolls one `dy` for each original crit success',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!p` [Optional]',
|
||||
value: 'Penetrating Explosion, rolls one `dy` for each crit success, but subtracts one from each resulting explosion',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!!` [Optional]',
|
||||
value: 'Compounding Explosion, rolls one `dy` for each crit success, but adds the resulting explosion to the die that caused this explosion',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!=u` [Optional]',
|
||||
value: 'Explode on `u`, rolls another `dy` for every die that lands on `u`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!>u` [Optional]',
|
||||
value: 'Explode on `u` and greater, rolls another `dy` for every die that lands on `u` or greater',
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
color: infoColor2,
|
||||
fields: [
|
||||
{
|
||||
name: '`!<u` [Optional]',
|
||||
value: 'Explode on `u` and under, rolls another `dy` for every die that lands on `u` or less',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!o=u` [Optional]',
|
||||
value: 'Explodes Once on `u`, rolls another `dy` for each original die that landed on `u`',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!o>u` [Optional]',
|
||||
value: 'Explode Once on `u` and greater, rolls another `dy` for each original die that landed on `u` or greater',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!o<u` [Optional]',
|
||||
value: 'Explode Once on `u` and under, rolls another `dy` for each original die that landed on `u` or less',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!p=u` [Optional]',
|
||||
value: 'Penetrating Explosion on `u`, rolls one `dy` for each die that lands on `u`, but subtracts one from each resulting explosion',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!p>u` [Optional]',
|
||||
value:
|
||||
'Penetrating Explosion on `u` and greater, rolls one `dy` for each die that lands on `u` or greater, but subtracts one from each resulting explosion',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!p<u` [Optional]',
|
||||
value:
|
||||
'Penetrating Explosion on `u` and under, rolls one `dy` for each die that lands on `u` or under, but subtracts one from each resulting explosion',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!!=u` [Optional]',
|
||||
value:
|
||||
'Compounding Explosion on `u`, rolls one `dy` for each die that lands on `u`, but adds the resulting explosion to the die that caused this explosion',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!!>u` [Optional]',
|
||||
value:
|
||||
'Compounding Explosion on `u` and greater, rolls one `dy` for each die that lands on `u` or greater, but adds the resulting explosion to the die that caused this explosion',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: '`!!<u` [Optional]',
|
||||
value:
|
||||
'Compounding Explosion on `u` and under, rolls one `dy` for each die that lands on `u` or under, but adds the resulting explosion to the die that caused this explosion',
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
color: infoColor1,
|
||||
title: 'Custom Dice Options',
|
||||
fields: [
|
||||
{
|
||||
name: 'CWOD Rolling',
|
||||
value: `\`${config.prefix}xcwody${config.postfix}\`
|
||||
\`x\` - Number of CWOD dice to roll
|
||||
\`y\` - Difficulty to roll at`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'OVA Rolling',
|
||||
value: `\`${config.prefix}xovady${config.postfix}\`
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'OVA Rolling',
|
||||
value: `\`${config.prefix}xovady${config.postfix}\`
|
||||
\`x\` - Number of OVA dice to roll
|
||||
\`y\` - Size of the die to roll (defaults to 6 if omitted)`,
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
color: successColor,
|
||||
title: 'Results Formatting:',
|
||||
description: 'The results have some formatting applied on them to provide details on what happened during this roll.',
|
||||
fields: [
|
||||
{
|
||||
name: 'Bold',
|
||||
value: 'Critical successes will be **bolded**.',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Underline',
|
||||
value: 'Critical fails will be __underlined__.',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Strikethrough',
|
||||
value: 'Rolls that were dropped or rerolled ~~crossed out~~.',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Exclamation mark (`!`)',
|
||||
value: 'Rolls that were caused by an explosion have an exclamation mark (`!`) after them.',
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('rollHelp.ts:247', message, e));
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
color: successColor,
|
||||
title: 'Results Formatting:',
|
||||
description: 'The results have some formatting applied on them to provide details on what happened during this roll.',
|
||||
fields: [
|
||||
{
|
||||
name: 'Bold',
|
||||
value: 'Critical successes will be **bolded**.',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Underline',
|
||||
value: 'Critical fails will be __underlined__.',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Strikethrough',
|
||||
value: 'Rolls that were dropped or rerolled ~~crossed out~~.',
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: 'Exclamation mark (`!`)',
|
||||
value: 'Rolls that were caused by an explosion have an exclamation mark (`!`) after them.',
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.messageSendError('rollHelp.ts:247', message, e));
|
||||
};
|
||||
|
|
|
@ -1,36 +1,49 @@
|
|||
import { dbClient, queries } from '../db.ts';
|
||||
import dbClient from '../db/client.ts';
|
||||
import { queries } from '../db/common.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
cache,
|
||||
cacheHandlers,
|
||||
DiscordenoMessage,
|
||||
// Discordeno deps
|
||||
cache,
|
||||
cacheHandlers,
|
||||
DiscordenoMessage,
|
||||
} from '../../deps.ts';
|
||||
import { generateStats } from '../commandUtils.ts';
|
||||
import { compilingStats } from '../commonEmbeds.ts';
|
||||
import utils from '../utils.ts';
|
||||
|
||||
export const stats = async (message: DiscordenoMessage) => {
|
||||
// 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));
|
||||
// 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);
|
||||
try {
|
||||
const m = await message.send(compilingStats);
|
||||
|
||||
// Calculate how many times commands have been run
|
||||
const rollQuery = await dbClient.query(`SELECT count, hourlyRate FROM command_cnt WHERE command = "roll";`).catch((e) => utils.commonLoggers.dbError('stats.ts:23', 'query', e));
|
||||
const totalQuery = await dbClient.query(`SELECT SUM(count) as count, SUM(hourlyRate) as hourlyRate FROM command_cnt;`).catch((e) => utils.commonLoggers.dbError('stats.ts:24', 'query', e));
|
||||
const rolls = BigInt(rollQuery[0].count);
|
||||
const rollRate = parseFloat(rollQuery[0].hourlyRate);
|
||||
const total = BigInt(totalQuery[0].count);
|
||||
const totalRate = parseFloat(totalQuery[0].hourlyRate);
|
||||
// Calculate how many times commands have been run
|
||||
const rollQuery = await dbClient
|
||||
.query(`SELECT count, hourlyRate FROM command_cnt WHERE command = "roll";`)
|
||||
.catch((e) => utils.commonLoggers.dbError('stats.ts:23', 'query', e));
|
||||
const totalQuery = await dbClient
|
||||
.query(`SELECT SUM(count) as count, SUM(hourlyRate) as hourlyRate FROM command_cnt;`)
|
||||
.catch((e) => utils.commonLoggers.dbError('stats.ts:24', 'query', e));
|
||||
const rolls = BigInt(rollQuery[0].count);
|
||||
const rollRate = parseFloat(rollQuery[0].hourlyRate);
|
||||
const total = BigInt(totalQuery[0].count);
|
||||
const totalRate = parseFloat(totalQuery[0].hourlyRate);
|
||||
|
||||
const cachedGuilds = await cacheHandlers.size('guilds');
|
||||
const cachedChannels = await cacheHandlers.size('channels');
|
||||
const cachedMembers = await cacheHandlers.size('members');
|
||||
m.edit(generateStats(cachedGuilds + cache.dispatchedGuildIds.size, cachedChannels + cache.dispatchedChannelIds.size, cachedMembers, rolls, total - rolls, rollRate, totalRate - rollRate)).catch((
|
||||
e: Error,
|
||||
) => utils.commonLoggers.messageEditError('stats.ts:38', m, e));
|
||||
} catch (e) {
|
||||
utils.commonLoggers.messageSendError('stats.ts:41', message, e);
|
||||
}
|
||||
const cachedGuilds = await cacheHandlers.size('guilds');
|
||||
const cachedChannels = await cacheHandlers.size('channels');
|
||||
const cachedMembers = await cacheHandlers.size('members');
|
||||
m.edit(
|
||||
generateStats(
|
||||
cachedGuilds + cache.dispatchedGuildIds.size,
|
||||
cachedChannels + cache.dispatchedChannelIds.size,
|
||||
cachedMembers,
|
||||
rolls,
|
||||
total - rolls,
|
||||
rollRate,
|
||||
totalRate - rollRate
|
||||
)
|
||||
).catch((e: Error) => utils.commonLoggers.messageEditError('stats.ts:38', m, e));
|
||||
} catch (e) {
|
||||
utils.commonLoggers.messageSendError('stats.ts:41', message, e);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,20 +1,25 @@
|
|||
import config from '../../config.ts';
|
||||
import { dbClient, queries } from '../db.ts';
|
||||
import dbClient from '../db/client.ts';
|
||||
import { queries } from '../db/common.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
} from '../../deps.ts';
|
||||
import { infoColor1 } from '../commandUtils.ts';
|
||||
import utils from '../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));
|
||||
// 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));
|
||||
|
||||
message.send({
|
||||
embeds: [{
|
||||
color: infoColor1,
|
||||
title: `My current version is ${config.version}`,
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageSendError('version.ts:24', message, e));
|
||||
message
|
||||
.send({
|
||||
embeds: [
|
||||
{
|
||||
color: infoColor1,
|
||||
title: `My current version is ${config.version}`,
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.messageSendError('version.ts:24', message, e));
|
||||
};
|
||||
|
|
30
src/db.ts
30
src/db.ts
|
@ -1,30 +0,0 @@
|
|||
import config from '../config.ts';
|
||||
import { Client } from '../deps.ts';
|
||||
import { LOCALMODE } from '../flags.ts';
|
||||
|
||||
type UserIdObj = {
|
||||
userid: bigint;
|
||||
};
|
||||
|
||||
export const dbClient = await new Client().connect({
|
||||
hostname: LOCALMODE ? config.db.localhost : config.db.host,
|
||||
port: config.db.port,
|
||||
db: config.db.name,
|
||||
username: config.db.username,
|
||||
password: config.db.password,
|
||||
});
|
||||
|
||||
// List of userIds who have requested that the bot ignore them
|
||||
export const ignoreList: Array<bigint> = [];
|
||||
const dbIgnoreList = await dbClient.query('SELECT * FROM ignore_list');
|
||||
dbIgnoreList.forEach((userIdObj: UserIdObj) => {
|
||||
ignoreList.push(userIdObj.userid);
|
||||
});
|
||||
|
||||
export const weekDays = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
|
||||
|
||||
export const queries = {
|
||||
insertRollLogCmd: (api: number, error: number) => `INSERT INTO roll_log(input,result,resultid,api,error) values(?,?,?,${api},${error})`,
|
||||
callIncCnt: (cmdName: string) => `CALL INC_CNT("${cmdName}");`,
|
||||
callIncHeatmap: (dateObj: Date) => `CALL INC_HEATMAP("${weekDays[dateObj.getDay()]}", ${dateObj.getHours()});`,
|
||||
};
|
|
@ -0,0 +1,14 @@
|
|||
import config from '../../config.ts';
|
||||
import { Client } from '../../deps.ts';
|
||||
import { LOCALMODE } from '../../flags.ts';
|
||||
|
||||
const dbClient = await new Client().connect({
|
||||
hostname: LOCALMODE ? config.db.localhost : config.db.host,
|
||||
port: config.db.port,
|
||||
db: config.db.name,
|
||||
username: config.db.username,
|
||||
password: config.db.password,
|
||||
debug: true,
|
||||
});
|
||||
|
||||
export default dbClient;
|
|
@ -0,0 +1,20 @@
|
|||
import dbClient from './client.ts';
|
||||
|
||||
type UserIdObj = {
|
||||
userid: bigint;
|
||||
};
|
||||
|
||||
// List of userIds who have requested that the bot ignore them
|
||||
export const ignoreList: Array<bigint> = [];
|
||||
const dbIgnoreList = await dbClient.query('SELECT * FROM ignore_list');
|
||||
dbIgnoreList.forEach((userIdObj: UserIdObj) => {
|
||||
ignoreList.push(userIdObj.userid);
|
||||
});
|
||||
|
||||
export const weekDays = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
|
||||
|
||||
export const queries = {
|
||||
insertRollLogCmd: (api: number, error: number) => `INSERT INTO roll_log(input,result,resultid,api,error) values(?,?,?,${api},${error})`,
|
||||
callIncCnt: (cmdName: string) => `CALL INC_CNT("${cmdName}");`,
|
||||
callIncHeatmap: (dateObj: Date) => `CALL INC_HEATMAP("${weekDays[dateObj.getDay()]}", ${dateObj.getHours()});`,
|
||||
};
|
|
@ -1,83 +1,89 @@
|
|||
import config from '../../../config.ts';
|
||||
import { dbClient } from '../../db.ts';
|
||||
import dbClient from '../../db/client.ts';
|
||||
import {
|
||||
// nanoid deps
|
||||
nanoid,
|
||||
// Discordeno deps
|
||||
sendMessage,
|
||||
// nanoid deps
|
||||
nanoid,
|
||||
// Discordeno deps
|
||||
sendMessage,
|
||||
} from '../../../deps.ts';
|
||||
import { generateApiDeleteEmail } from '../../commandUtils.ts';
|
||||
import utils from '../../utils.ts';
|
||||
import stdResp from '../stdResponses.ts';
|
||||
|
||||
export const apiKeyDelete = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt, apiUserEmail: string, apiUserDelCode: string) => {
|
||||
if (query.has('user') && ((query.get('user') || '').length > 0) && query.has('email') && ((query.get('email') || '').length > 0)) {
|
||||
if (apiUserid === BigInt(query.get('user') || '0') && apiUserEmail === query.get('email')) {
|
||||
if (query.has('code') && ((query.get('code') || '').length > 0)) {
|
||||
if ((query.get('code') || '') === apiUserDelCode) {
|
||||
// User has recieved their delete code and we need to delete the account now
|
||||
let erroredOut = false;
|
||||
export const apiKeyDelete = async (
|
||||
requestEvent: Deno.RequestEvent,
|
||||
query: Map<string, string>,
|
||||
apiUserid: BigInt,
|
||||
apiUserEmail: string,
|
||||
apiUserDelCode: string
|
||||
) => {
|
||||
if (query.has('user') && (query.get('user') || '').length > 0 && query.has('email') && (query.get('email') || '').length > 0) {
|
||||
if (apiUserid === BigInt(query.get('user') || '0') && apiUserEmail === query.get('email')) {
|
||||
if (query.has('code') && (query.get('code') || '').length > 0) {
|
||||
if ((query.get('code') || '') === apiUserDelCode) {
|
||||
// User has recieved their delete code and we need to delete the account now
|
||||
let erroredOut = false;
|
||||
|
||||
await dbClient.execute('DELETE FROM allowed_channels WHERE userid = ?', [apiUserid]).catch((e) => {
|
||||
utils.commonLoggers.dbError('apiKeyDelete.ts:25', 'insert into', e);
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Channel Clean Failed.'));
|
||||
erroredOut = true;
|
||||
});
|
||||
if (erroredOut) {
|
||||
return;
|
||||
}
|
||||
await dbClient.execute('DELETE FROM allowed_channels WHERE userid = ?', [apiUserid]).catch((e) => {
|
||||
utils.commonLoggers.dbError('apiKeyDelete.ts:25', 'insert into', e);
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Channel Clean Failed.'));
|
||||
erroredOut = true;
|
||||
});
|
||||
if (erroredOut) {
|
||||
return;
|
||||
}
|
||||
|
||||
await dbClient.execute('DELETE FROM all_keys WHERE userid = ?', [apiUserid]).catch((e) => {
|
||||
utils.commonLoggers.dbError('apiKeyDelete.ts:34', 'delete from', e);
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Delete Key Failed.'));
|
||||
erroredOut = true;
|
||||
});
|
||||
if (erroredOut) {
|
||||
return;
|
||||
} else {
|
||||
// Send OK as response to indicate key deletion was successful
|
||||
requestEvent.respondWith(stdResp.OK('You have been removed from the DB, Goodbye.'));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they shouldn't be doing this
|
||||
requestEvent.respondWith(stdResp.Forbidden('Invalid Delete Code.'));
|
||||
}
|
||||
} else {
|
||||
// User does not have their delete code yet, so we need to generate one and email it to them
|
||||
const deleteCode = await nanoid(10);
|
||||
await dbClient.execute('DELETE FROM all_keys WHERE userid = ?', [apiUserid]).catch((e) => {
|
||||
utils.commonLoggers.dbError('apiKeyDelete.ts:34', 'delete from', e);
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Delete Key Failed.'));
|
||||
erroredOut = true;
|
||||
});
|
||||
if (erroredOut) {
|
||||
return;
|
||||
} else {
|
||||
// Send OK as response to indicate key deletion was successful
|
||||
requestEvent.respondWith(stdResp.OK('You have been removed from the DB, Goodbye.'));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they shouldn't be doing this
|
||||
requestEvent.respondWith(stdResp.Forbidden('Invalid Delete Code.'));
|
||||
}
|
||||
} else {
|
||||
// User does not have their delete code yet, so we need to generate one and email it to them
|
||||
const deleteCode = await nanoid(10);
|
||||
|
||||
let erroredOut = false;
|
||||
let erroredOut = false;
|
||||
|
||||
// Execute the DB modification
|
||||
await dbClient.execute('UPDATE all_keys SET deleteCode = ? WHERE userid = ?', [deleteCode, apiUserid]).catch((e) => {
|
||||
utils.commonLoggers.dbError('apiKeyDelete.ts:57', 'update', e);
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Delete Code Failed'));
|
||||
erroredOut = true;
|
||||
});
|
||||
if (erroredOut) {
|
||||
return;
|
||||
}
|
||||
// Execute the DB modification
|
||||
await dbClient.execute('UPDATE all_keys SET deleteCode = ? WHERE userid = ?', [deleteCode, apiUserid]).catch((e) => {
|
||||
utils.commonLoggers.dbError('apiKeyDelete.ts:57', 'update', e);
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Delete Code Failed'));
|
||||
erroredOut = true;
|
||||
});
|
||||
if (erroredOut) {
|
||||
return;
|
||||
}
|
||||
|
||||
// "Send" the email
|
||||
await sendMessage(config.api.email, generateApiDeleteEmail(apiUserEmail, deleteCode)).catch(() => {
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Failed to send email.'));
|
||||
erroredOut = true;
|
||||
});
|
||||
if (erroredOut) {
|
||||
return;
|
||||
} else {
|
||||
// Send API key as response
|
||||
requestEvent.respondWith(stdResp.FailedDependency('Please look for an email containing a Delete Key and run this query again with said key.'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they shouldn't be doing this
|
||||
requestEvent.respondWith(stdResp.Forbidden('You can only delete your own key.'));
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams));
|
||||
}
|
||||
// "Send" the email
|
||||
await sendMessage(config.api.email, generateApiDeleteEmail(apiUserEmail, deleteCode)).catch(() => {
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Failed to send email.'));
|
||||
erroredOut = true;
|
||||
});
|
||||
if (erroredOut) {
|
||||
return;
|
||||
} else {
|
||||
// Send API key as response
|
||||
requestEvent.respondWith(stdResp.FailedDependency('Please look for an email containing a Delete Key and run this query again with said key.'));
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they shouldn't be doing this
|
||||
requestEvent.respondWith(stdResp.Forbidden('You can only delete your own key.'));
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,35 +1,35 @@
|
|||
import { dbClient } from '../../db.ts';
|
||||
import dbClient from '../../db/client.ts';
|
||||
import stdResp from '../stdResponses.ts';
|
||||
import utils from '../../utils.ts';
|
||||
|
||||
export const apiChannel = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt) => {
|
||||
if (query.has('user') && ((query.get('user') || '').length > 0)) {
|
||||
if (apiUserid === BigInt(query.get('user') || '0')) {
|
||||
// Flag to see if there is an error inside the catch
|
||||
let erroredOut = false;
|
||||
if (query.has('user') && (query.get('user') || '').length > 0) {
|
||||
if (apiUserid === BigInt(query.get('user') || '0')) {
|
||||
// Flag to see if there is an error inside the catch
|
||||
let erroredOut = false;
|
||||
|
||||
// Get all channels userid has authorized
|
||||
const dbAllowedChannelQuery = await dbClient.query('SELECT * FROM allowed_channels WHERE userid = ?', [apiUserid]).catch((e) => {
|
||||
utils.commonLoggers.dbError('apiChannel.ts', 'query', e);
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Failed to get channels.'));
|
||||
erroredOut = true;
|
||||
});
|
||||
// Get all channels userid has authorized
|
||||
const dbAllowedChannelQuery = await dbClient.query('SELECT * FROM allowed_channels WHERE userid = ?', [apiUserid]).catch((e) => {
|
||||
utils.commonLoggers.dbError('apiChannel.ts', 'query', e);
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Failed to get channels.'));
|
||||
erroredOut = true;
|
||||
});
|
||||
|
||||
if (erroredOut) {
|
||||
return;
|
||||
} else {
|
||||
// Customized strinification to handle BigInts correctly
|
||||
const returnChannels = JSON.stringify(dbAllowedChannelQuery, (_key, value) => (typeof value === 'bigint' ? value.toString() : value));
|
||||
// Send channel list as response
|
||||
requestEvent.respondWith(stdResp.OK(returnChannels));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they shouldn't be doing this
|
||||
requestEvent.respondWith(stdResp.Forbidden('You can only view your own channels.'));
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams));
|
||||
}
|
||||
if (erroredOut) {
|
||||
return;
|
||||
} else {
|
||||
// Customized strinification to handle BigInts correctly
|
||||
const returnChannels = JSON.stringify(dbAllowedChannelQuery, (_key, value) => (typeof value === 'bigint' ? value.toString() : value));
|
||||
// Send channel list as response
|
||||
requestEvent.respondWith(stdResp.OK(returnChannels));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they shouldn't be doing this
|
||||
requestEvent.respondWith(stdResp.Forbidden('You can only view your own channels.'));
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,52 +1,52 @@
|
|||
import config from '../../../config.ts';
|
||||
import { dbClient } from '../../db.ts';
|
||||
import dbClient from '../../db/client.ts';
|
||||
import {
|
||||
// nanoid deps
|
||||
nanoid,
|
||||
// Discordeno deps
|
||||
sendMessage,
|
||||
// nanoid deps
|
||||
nanoid,
|
||||
// Discordeno deps
|
||||
sendMessage,
|
||||
} from '../../../deps.ts';
|
||||
import { generateApiKeyEmail } from '../../commandUtils.ts';
|
||||
import utils from '../../utils.ts';
|
||||
import stdResp from '../stdResponses.ts';
|
||||
|
||||
export const apiKey = async (requestEvent: Deno.RequestEvent, query: Map<string, string>) => {
|
||||
if ((query.has('user') && ((query.get('user') || '').length > 0)) && (query.has('email') && ((query.get('email') || '').length > 0))) {
|
||||
// Generate new secure key
|
||||
const newKey = await nanoid(25);
|
||||
if (query.has('user') && (query.get('user') || '').length > 0 && query.has('email') && (query.get('email') || '').length > 0) {
|
||||
// Generate new secure key
|
||||
const newKey = await nanoid(25);
|
||||
|
||||
// Flag to see if there is an error inside the catch
|
||||
let erroredOut = false;
|
||||
// Flag to see if there is an error inside the catch
|
||||
let erroredOut = false;
|
||||
|
||||
// Insert new key/user pair into the db
|
||||
await dbClient.execute('INSERT INTO all_keys(userid,apiKey,email) values(?,?,?)', [BigInt(query.get('user') || '0'), newKey, (query.get('email') || '').toLowerCase()]).catch(
|
||||
(e) => {
|
||||
utils.commonLoggers.dbError('apiKey.ts:27', 'insert into', e);
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Failed to store key.'));
|
||||
erroredOut = true;
|
||||
},
|
||||
);
|
||||
// Insert new key/user pair into the db
|
||||
await dbClient
|
||||
.execute('INSERT INTO all_keys(userid,apiKey,email) values(?,?,?)', [BigInt(query.get('user') || '0'), newKey, (query.get('email') || '').toLowerCase()])
|
||||
.catch((e) => {
|
||||
utils.commonLoggers.dbError('apiKey.ts:27', 'insert into', e);
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Failed to store key.'));
|
||||
erroredOut = true;
|
||||
});
|
||||
|
||||
// Exit this case now if catch errored
|
||||
if (erroredOut) {
|
||||
return;
|
||||
}
|
||||
// Exit this case now if catch errored
|
||||
if (erroredOut) {
|
||||
return;
|
||||
}
|
||||
|
||||
// "Send" the email
|
||||
await sendMessage(config.api.email, generateApiKeyEmail(query.get('email') || 'no email', newKey)).catch(() => {
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Failed to send email.'));
|
||||
erroredOut = true;
|
||||
});
|
||||
// "Send" the email
|
||||
await sendMessage(config.api.email, generateApiKeyEmail(query.get('email') || 'no email', newKey)).catch(() => {
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Failed to send email.'));
|
||||
erroredOut = true;
|
||||
});
|
||||
|
||||
if (erroredOut) {
|
||||
return;
|
||||
} else {
|
||||
// Send basic OK to indicate key has been sent
|
||||
requestEvent.respondWith(stdResp.OK('Email Sent.'));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams));
|
||||
}
|
||||
if (erroredOut) {
|
||||
return;
|
||||
} else {
|
||||
// Send basic OK to indicate key has been sent
|
||||
requestEvent.respondWith(stdResp.OK('Email Sent.'));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,42 +1,42 @@
|
|||
import config from '../../../config.ts';
|
||||
import { dbClient } from '../../db.ts';
|
||||
import dbClient from '../../db/client.ts';
|
||||
import {
|
||||
// nanoid deps
|
||||
nanoid,
|
||||
// nanoid deps
|
||||
nanoid,
|
||||
} from '../../../deps.ts';
|
||||
import stdResp from '../stdResponses.ts';
|
||||
import utils from '../../utils.ts';
|
||||
|
||||
export const apiKeyAdmin = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt) => {
|
||||
if ((query.has('user') && ((query.get('user') || '').length > 0)) && (query.has('a') && ((query.get('a') || '').length > 0))) {
|
||||
if (apiUserid === config.api.admin && apiUserid === BigInt(query.get('a') || '0')) {
|
||||
// Generate new secure key
|
||||
const newKey = await nanoid(25);
|
||||
if (query.has('user') && (query.get('user') || '').length > 0 && query.has('a') && (query.get('a') || '').length > 0) {
|
||||
if (apiUserid === config.api.admin && apiUserid === BigInt(query.get('a') || '0')) {
|
||||
// Generate new secure key
|
||||
const newKey = await nanoid(25);
|
||||
|
||||
// Flag to see if there is an error inside the catch
|
||||
let erroredOut = false;
|
||||
// Flag to see if there is an error inside the catch
|
||||
let erroredOut = false;
|
||||
|
||||
// Insert new key/user pair into the db
|
||||
await dbClient.execute('INSERT INTO all_keys(userid,apiKey) values(?,?)', [apiUserid, newKey]).catch((e) => {
|
||||
utils.commonLoggers.dbError('apiKeyAdmin.ts:24', 'insert into', e);
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Failed to store key.'));
|
||||
erroredOut = true;
|
||||
});
|
||||
// Insert new key/user pair into the db
|
||||
await dbClient.execute('INSERT INTO all_keys(userid,apiKey) values(?,?)', [apiUserid, newKey]).catch((e) => {
|
||||
utils.commonLoggers.dbError('apiKeyAdmin.ts:24', 'insert into', e);
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Failed to store key.'));
|
||||
erroredOut = true;
|
||||
});
|
||||
|
||||
// Exit this case now if catch errored
|
||||
if (erroredOut) {
|
||||
return;
|
||||
} else {
|
||||
// Send API key as response
|
||||
requestEvent.respondWith(stdResp.OK(JSON.stringify({ 'key': newKey, 'userid': query.get('user') })));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Only allow the db admin to use this API
|
||||
requestEvent.respondWith(stdResp.Forbidden(stdResp.Strings.restricted));
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams));
|
||||
}
|
||||
// Exit this case now if catch errored
|
||||
if (erroredOut) {
|
||||
return;
|
||||
} else {
|
||||
// Send API key as response
|
||||
requestEvent.respondWith(stdResp.OK(JSON.stringify({ key: newKey, userid: query.get('user') })));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Only allow the db admin to use this API
|
||||
requestEvent.respondWith(stdResp.Forbidden(stdResp.Strings.restricted));
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import config from '../../../config.ts';
|
||||
import { dbClient, queries } from '../../db.ts';
|
||||
import dbClient from '../../db/client.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
cache,
|
||||
// Log4Deno deps
|
||||
log,
|
||||
LT,
|
||||
// Discordeno deps
|
||||
cache,
|
||||
// Log4Deno deps
|
||||
log,
|
||||
LT,
|
||||
} from '../../../deps.ts';
|
||||
import { QueuedRoll, RollModifiers } from '../../mod.d.ts';
|
||||
import utils from '../../utils.ts';
|
||||
|
@ -15,107 +15,116 @@ import stdResp from '../stdResponses.ts';
|
|||
const apiWarning = `The following roll was conducted using my built in API. If someone in this channel did not request this roll, please report API abuse here: <${config.api.supportURL}>`;
|
||||
|
||||
export const apiRoll = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt) => {
|
||||
// Make sure query contains all the needed parts
|
||||
if (
|
||||
(query.has('rollstr') && ((query.get('rollstr') || '').length > 0)) && (query.has('channel') && ((query.get('channel') || '').length > 0)) &&
|
||||
(query.has('user') && ((query.get('user') || '').length > 0))
|
||||
) {
|
||||
if (query.has('n') && query.has('m')) {
|
||||
// Alert API user that they shouldn't be doing this
|
||||
requestEvent.respondWith(stdResp.BadRequest('Cannot have both \'n\' and \'m\'.'));
|
||||
return;
|
||||
}
|
||||
// Make sure query contains all the needed parts
|
||||
if (
|
||||
query.has('rollstr') &&
|
||||
(query.get('rollstr') || '').length > 0 &&
|
||||
query.has('channel') &&
|
||||
(query.get('channel') || '').length > 0 &&
|
||||
query.has('user') &&
|
||||
(query.get('user') || '').length > 0
|
||||
) {
|
||||
if (query.has('n') && query.has('m')) {
|
||||
// Alert API user that they shouldn't be doing this
|
||||
requestEvent.respondWith(stdResp.BadRequest("Cannot have both 'n' and 'm'."));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if user is authenticated to use this endpoint
|
||||
let authorized = false;
|
||||
let hideWarn = false;
|
||||
// Check if user is authenticated to use this endpoint
|
||||
let authorized = false;
|
||||
let hideWarn = false;
|
||||
|
||||
// Check if the db has the requested userid/channelid combo, and that the requested userid matches the userid linked with the api key
|
||||
const dbChannelQuery = await dbClient.query('SELECT active, banned FROM allowed_channels WHERE userid = ? AND channelid = ?', [apiUserid, BigInt(query.get('channel') || '0')]);
|
||||
if (dbChannelQuery.length === 1 && (apiUserid === BigInt(query.get('user') || '0')) && dbChannelQuery[0].active && !dbChannelQuery[0].banned) {
|
||||
// Get the guild from the channel and make sure user is in said guild
|
||||
const guild = cache.channels.get(BigInt(query.get('channel') || ''))?.guild;
|
||||
if (guild && guild.members.get(BigInt(query.get('user') || ''))?.id) {
|
||||
const dbGuildQuery = await dbClient.query('SELECT active, banned, hidewarn FROM allowed_guilds WHERE guildid = ? AND channelid = ?', [
|
||||
guild.id,
|
||||
BigInt(query.get('channel') || '0'),
|
||||
]);
|
||||
// Check if the db has the requested userid/channelid combo, and that the requested userid matches the userid linked with the api key
|
||||
const dbChannelQuery = await dbClient.query('SELECT active, banned FROM allowed_channels WHERE userid = ? AND channelid = ?', [
|
||||
apiUserid,
|
||||
BigInt(query.get('channel') || '0'),
|
||||
]);
|
||||
if (dbChannelQuery.length === 1 && apiUserid === BigInt(query.get('user') || '0') && dbChannelQuery[0].active && !dbChannelQuery[0].banned) {
|
||||
// Get the guild from the channel and make sure user is in said guild
|
||||
const guild = cache.channels.get(BigInt(query.get('channel') || ''))?.guild;
|
||||
if (guild && guild.members.get(BigInt(query.get('user') || ''))?.id) {
|
||||
const dbGuildQuery = await dbClient.query('SELECT active, banned, hidewarn FROM allowed_guilds WHERE guildid = ? AND channelid = ?', [
|
||||
guild.id,
|
||||
BigInt(query.get('channel') || '0'),
|
||||
]);
|
||||
|
||||
// Make sure guild allows API rolls
|
||||
if (dbGuildQuery.length === 1 && dbGuildQuery[0].active && !dbGuildQuery[0].banned) {
|
||||
authorized = true;
|
||||
hideWarn = dbGuildQuery[0].hidewarn;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Make sure guild allows API rolls
|
||||
if (dbGuildQuery.length === 1 && dbGuildQuery[0].active && !dbGuildQuery[0].banned) {
|
||||
authorized = true;
|
||||
hideWarn = dbGuildQuery[0].hidewarn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (authorized) {
|
||||
// Rest of this command is in a try-catch to protect all sends/edits from erroring out
|
||||
try {
|
||||
// Make sure rollCmd is not undefined
|
||||
let rollCmd = query.get('rollstr') || '';
|
||||
const originalCommand = query.get('rollstr');
|
||||
if (authorized) {
|
||||
// Rest of this command is in a try-catch to protect all sends/edits from erroring out
|
||||
try {
|
||||
// Make sure rollCmd is not undefined
|
||||
let rollCmd = query.get('rollstr') || '';
|
||||
const originalCommand = query.get('rollstr');
|
||||
|
||||
if (rollCmd.length === 0) {
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.BadRequest('rollCmd is required.'));
|
||||
if (rollCmd.length === 0) {
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.BadRequest('rollCmd is required.'));
|
||||
|
||||
// Always log API rolls for abuse detection
|
||||
dbClient.execute(queries.insertRollLogCmd(1, 1), [originalCommand, 'EmptyInput', null]).catch((e) => utils.commonLoggers.dbError('apiRoll.ts:65', 'insert', e));
|
||||
return;
|
||||
}
|
||||
// Always log API rolls for abuse detection
|
||||
dbClient
|
||||
.execute(queries.insertRollLogCmd(1, 1), [originalCommand, 'EmptyInput', null])
|
||||
.catch((e) => utils.commonLoggers.dbError('apiRoll.ts:65', 'insert', e));
|
||||
return;
|
||||
}
|
||||
|
||||
if (query.has('o') && (query.get('o')?.toLowerCase() !== 'd' && query.get('o')?.toLowerCase() !== 'a')) {
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.BadRequest('Order must be set to \'a\' or \'d\'.'));
|
||||
if (query.has('o') && query.get('o')?.toLowerCase() !== 'd' && query.get('o')?.toLowerCase() !== 'a') {
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.BadRequest("Order must be set to 'a' or 'd'."));
|
||||
|
||||
// Always log API rolls for abuse detection
|
||||
dbClient.execute(queries.insertRollLogCmd(1, 1), [originalCommand, 'BadOrder', null]).catch((e) => utils.commonLoggers.dbError('apiRoll.ts:66', 'insert', e));
|
||||
return;
|
||||
}
|
||||
// Always log API rolls for abuse detection
|
||||
dbClient
|
||||
.execute(queries.insertRollLogCmd(1, 1), [originalCommand, 'BadOrder', null])
|
||||
.catch((e) => utils.commonLoggers.dbError('apiRoll.ts:66', 'insert', e));
|
||||
return;
|
||||
}
|
||||
|
||||
// Clip off the leading prefix. API calls must be formatted with a prefix at the start to match how commands are sent in Discord
|
||||
rollCmd = rollCmd.substring(rollCmd.indexOf(config.prefix) + 2).replace(/%20/g, ' ');
|
||||
// Clip off the leading prefix. API calls must be formatted with a prefix at the start to match how commands are sent in Discord
|
||||
rollCmd = rollCmd.substring(rollCmd.indexOf(config.prefix) + 2).replace(/%20/g, ' ');
|
||||
|
||||
const modifiers: RollModifiers = {
|
||||
noDetails: query.has('nd'),
|
||||
superNoDetails: query.has('snd'),
|
||||
spoiler: query.has('s') ? '||' : '',
|
||||
maxRoll: query.has('m'),
|
||||
nominalRoll: query.has('n'),
|
||||
gmRoll: query.has('gms'),
|
||||
gms: query.has('gms') ? (query.get('gms') || '').split(',') : [],
|
||||
order: query.has('o') ? (query.get('o')?.toLowerCase() || '') : '',
|
||||
count: query.has('c'),
|
||||
valid: true,
|
||||
apiWarn: hideWarn ? '' : apiWarning,
|
||||
};
|
||||
const modifiers: RollModifiers = {
|
||||
noDetails: query.has('nd'),
|
||||
superNoDetails: query.has('snd'),
|
||||
spoiler: query.has('s') ? '||' : '',
|
||||
maxRoll: query.has('m'),
|
||||
nominalRoll: query.has('n'),
|
||||
gmRoll: query.has('gms'),
|
||||
gms: query.has('gms') ? (query.get('gms') || '').split(',') : [],
|
||||
order: query.has('o') ? query.get('o')?.toLowerCase() || '' : '',
|
||||
count: query.has('c'),
|
||||
valid: true,
|
||||
apiWarn: hideWarn ? '' : apiWarning,
|
||||
};
|
||||
|
||||
// Parse the roll and get the return text
|
||||
await queueRoll(
|
||||
<QueuedRoll> {
|
||||
apiRoll: true,
|
||||
api: { requestEvent, channelId: BigInt(query.get('channel') || '0'), userId: BigInt(query.get('user') || '') },
|
||||
rollCmd,
|
||||
modifiers,
|
||||
originalCommand,
|
||||
},
|
||||
);
|
||||
} catch (err) {
|
||||
// Handle any errors we missed
|
||||
log(LT.ERROR, `Unhandled Error: ${JSON.stringify(err)}`);
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Something went wrong.'));
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(
|
||||
stdResp.Forbidden(
|
||||
`Verify you are a member of the guild you are sending this roll to. If you are, the ${config.name} may not have that registered, please send a message in the guild so ${config.name} can register this. This registration is temporary, so if you see this error again, just poke your server again.`,
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they shouldn't be doing this
|
||||
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams));
|
||||
}
|
||||
// Parse the roll and get the return text
|
||||
await queueRoll(<QueuedRoll>{
|
||||
apiRoll: true,
|
||||
api: { requestEvent, channelId: BigInt(query.get('channel') || '0'), userId: BigInt(query.get('user') || '') },
|
||||
rollCmd,
|
||||
modifiers,
|
||||
originalCommand,
|
||||
});
|
||||
} catch (err) {
|
||||
// Handle any errors we missed
|
||||
log(LT.ERROR, `Unhandled Error: ${JSON.stringify(err)}`);
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Something went wrong.'));
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(
|
||||
stdResp.Forbidden(
|
||||
`Verify you are a member of the guild you are sending this roll to. If you are, the ${config.name} may not have that registered, please send a message in the guild so ${config.name} can register this. This registration is temporary, so if you see this error again, just poke your server again.`
|
||||
)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they shouldn't be doing this
|
||||
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
import {
|
||||
// httpd deps
|
||||
Status,
|
||||
STATUS_TEXT,
|
||||
// httpd deps
|
||||
STATUS_CODE,
|
||||
STATUS_TEXT,
|
||||
} from '../../../deps.ts';
|
||||
|
||||
export const heatmapPng = async (requestEvent: Deno.RequestEvent) => {
|
||||
const file = Deno.readFileSync('./src/endpoints/gets/heatmap.png');
|
||||
const imageHeaders = new Headers();
|
||||
imageHeaders.append('Content-Type', 'image/png');
|
||||
// Send basic OK to indicate key has been sent
|
||||
requestEvent.respondWith(
|
||||
new Response(file, {
|
||||
status: Status.OK,
|
||||
statusText: STATUS_TEXT[Status.OK],
|
||||
headers: imageHeaders,
|
||||
}),
|
||||
);
|
||||
const file = Deno.readFileSync('./src/endpoints/gets/heatmap.png');
|
||||
const imageHeaders = new Headers();
|
||||
imageHeaders.append('Content-Type', 'image/png');
|
||||
// Send basic OK to indicate key has been sent
|
||||
requestEvent.respondWith(
|
||||
new Response(file, {
|
||||
status: STATUS_CODE.OK,
|
||||
statusText: STATUS_TEXT[STATUS_CODE.OK],
|
||||
headers: imageHeaders,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
import { dbClient } from '../../db.ts';
|
||||
import dbClient from '../../db/client.ts';
|
||||
import stdResp from '../stdResponses.ts';
|
||||
import utils from '../../utils.ts';
|
||||
|
||||
export const apiChannelAdd = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt) => {
|
||||
if ((query.has('user') && ((query.get('user') || '').length > 0)) && (query.has('channel') && ((query.get('channel') || '').length > 0))) {
|
||||
if (apiUserid === BigInt(query.get('user') || '0')) {
|
||||
// Flag to see if there is an error inside the catch
|
||||
let erroredOut = false;
|
||||
if (query.has('user') && (query.get('user') || '').length > 0 && query.has('channel') && (query.get('channel') || '').length > 0) {
|
||||
if (apiUserid === BigInt(query.get('user') || '0')) {
|
||||
// Flag to see if there is an error inside the catch
|
||||
let erroredOut = false;
|
||||
|
||||
// Insert new user/channel pair into the db
|
||||
await dbClient.execute('INSERT INTO allowed_channels(userid,channelid) values(?,?)', [apiUserid, BigInt(query.get('channel') || '0')]).catch((e) => {
|
||||
utils.commonLoggers.dbError('apiChannelAdd.ts:17', 'insert into', e);
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Failed to store channel.'));
|
||||
erroredOut = true;
|
||||
});
|
||||
// Insert new user/channel pair into the db
|
||||
await dbClient.execute('INSERT INTO allowed_channels(userid,channelid) values(?,?)', [apiUserid, BigInt(query.get('channel') || '0')]).catch((e) => {
|
||||
utils.commonLoggers.dbError('apiChannelAdd.ts:17', 'insert into', e);
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Failed to store channel.'));
|
||||
erroredOut = true;
|
||||
});
|
||||
|
||||
// Exit this case now if catch errored
|
||||
if (erroredOut) {
|
||||
return;
|
||||
} else {
|
||||
// Send OK to indicate modification was successful
|
||||
requestEvent.respondWith(stdResp.OK('Successfully added channel.'));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they shouldn't be doing this
|
||||
requestEvent.respondWith(stdResp.Forbidden('You can only add channels to your key.'));
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams));
|
||||
}
|
||||
// Exit this case now if catch errored
|
||||
if (erroredOut) {
|
||||
return;
|
||||
} else {
|
||||
// Send OK to indicate modification was successful
|
||||
requestEvent.respondWith(stdResp.OK('Successfully added channel.'));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they shouldn't be doing this
|
||||
requestEvent.respondWith(stdResp.Forbidden('You can only add channels to your key.'));
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,41 +1,44 @@
|
|||
import { dbClient } from '../../db.ts';
|
||||
import dbClient from '../../db/client.ts';
|
||||
import stdResp from '../stdResponses.ts';
|
||||
import utils from '../../utils.ts';
|
||||
|
||||
export const apiChannelManageActive = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt, path: string) => {
|
||||
if ((query.has('channel') && ((query.get('channel') || '').length > 0)) && (query.has('user') && ((query.get('user') || '').length > 0))) {
|
||||
if (apiUserid === BigInt(query.get('user') || '0')) {
|
||||
// Flag to see if there is an error inside the catch
|
||||
let value, erroredOut = false;
|
||||
if (query.has('channel') && (query.get('channel') || '').length > 0 && query.has('user') && (query.get('user') || '').length > 0) {
|
||||
if (apiUserid === BigInt(query.get('user') || '0')) {
|
||||
// Flag to see if there is an error inside the catch
|
||||
let value,
|
||||
erroredOut = false;
|
||||
|
||||
// Determine value to set
|
||||
if (path.toLowerCase().indexOf('de') > 0) {
|
||||
value = 0;
|
||||
} else {
|
||||
value = 1;
|
||||
}
|
||||
// Determine value to set
|
||||
if (path.toLowerCase().indexOf('de') > 0) {
|
||||
value = 0;
|
||||
} else {
|
||||
value = 1;
|
||||
}
|
||||
|
||||
// Update the requested entry
|
||||
await dbClient.execute('UPDATE allowed_channels SET active = ? WHERE userid = ? AND channelid = ?', [value, apiUserid, BigInt(query.get('channel') || '0')]).catch((e) => {
|
||||
utils.commonLoggers.dbError('apiChannelManageActive.ts:25', 'update', e);
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Failed to update channel.'));
|
||||
erroredOut = true;
|
||||
});
|
||||
// Update the requested entry
|
||||
await dbClient
|
||||
.execute('UPDATE allowed_channels SET active = ? WHERE userid = ? AND channelid = ?', [value, apiUserid, BigInt(query.get('channel') || '0')])
|
||||
.catch((e) => {
|
||||
utils.commonLoggers.dbError('apiChannelManageActive.ts:25', 'update', e);
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Failed to update channel.'));
|
||||
erroredOut = true;
|
||||
});
|
||||
|
||||
// Exit this case now if catch errored
|
||||
if (erroredOut) {
|
||||
return;
|
||||
} else {
|
||||
// Send API key as response
|
||||
requestEvent.respondWith(stdResp.OK(`Successfully active to ${value}.`));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they shouldn't be doing this
|
||||
requestEvent.respondWith(stdResp.Forbidden('You can only manage your own channels.'));
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams));
|
||||
}
|
||||
// Exit this case now if catch errored
|
||||
if (erroredOut) {
|
||||
return;
|
||||
} else {
|
||||
// Send API key as response
|
||||
requestEvent.respondWith(stdResp.OK(`Successfully active to ${value}.`));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they shouldn't be doing this
|
||||
requestEvent.respondWith(stdResp.Forbidden('You can only manage your own channels.'));
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,45 +1,52 @@
|
|||
import config from '../../../config.ts';
|
||||
import { dbClient } from '../../db.ts';
|
||||
import dbClient from '../../db/client.ts';
|
||||
import stdResp from '../stdResponses.ts';
|
||||
import utils from '../../utils.ts';
|
||||
|
||||
export const apiChannelManageBan = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt, path: string) => {
|
||||
if (
|
||||
(query.has('a') && ((query.get('a') || '').length > 0)) && (query.has('channel') && ((query.get('channel') || '').length > 0)) &&
|
||||
(query.has('user') && ((query.get('user') || '').length > 0))
|
||||
) {
|
||||
if (apiUserid === config.api.admin && apiUserid === BigInt(query.get('a') || '0')) {
|
||||
// Flag to see if there is an error inside the catch
|
||||
let value, erroredOut = false;
|
||||
if (
|
||||
query.has('a') &&
|
||||
(query.get('a') || '').length > 0 &&
|
||||
query.has('channel') &&
|
||||
(query.get('channel') || '').length > 0 &&
|
||||
query.has('user') &&
|
||||
(query.get('user') || '').length > 0
|
||||
) {
|
||||
if (apiUserid === config.api.admin && apiUserid === BigInt(query.get('a') || '0')) {
|
||||
// Flag to see if there is an error inside the catch
|
||||
let value,
|
||||
erroredOut = false;
|
||||
|
||||
// Determine value to set
|
||||
if (path.toLowerCase().indexOf('un') > 0) {
|
||||
value = 0;
|
||||
} else {
|
||||
value = 1;
|
||||
}
|
||||
// Determine value to set
|
||||
if (path.toLowerCase().indexOf('un') > 0) {
|
||||
value = 0;
|
||||
} else {
|
||||
value = 1;
|
||||
}
|
||||
|
||||
// Execute the DB modification
|
||||
await dbClient.execute('UPDATE allowed_channels SET banned = ? WHERE userid = ? AND channelid = ?', [value, apiUserid, BigInt(query.get('channel') || '0')]).catch((e) => {
|
||||
utils.commonLoggers.dbError('apiChannelManageBan.ts:28', 'update', e);
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Failed to update channel.'));
|
||||
erroredOut = true;
|
||||
});
|
||||
// Execute the DB modification
|
||||
await dbClient
|
||||
.execute('UPDATE allowed_channels SET banned = ? WHERE userid = ? AND channelid = ?', [value, apiUserid, BigInt(query.get('channel') || '0')])
|
||||
.catch((e) => {
|
||||
utils.commonLoggers.dbError('apiChannelManageBan.ts:28', 'update', e);
|
||||
requestEvent.respondWith(stdResp.InternalServerError('Failed to update channel.'));
|
||||
erroredOut = true;
|
||||
});
|
||||
|
||||
// Exit this case now if catch errored
|
||||
if (erroredOut) {
|
||||
return;
|
||||
} else {
|
||||
// Send OK to indicate modification was successful
|
||||
requestEvent.respondWith(stdResp.OK(`Successfully active to ${value}.`));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they shouldn't be doing this
|
||||
requestEvent.respondWith(stdResp.Forbidden(stdResp.Strings.restricted));
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams));
|
||||
}
|
||||
// Exit this case now if catch errored
|
||||
if (erroredOut) {
|
||||
return;
|
||||
} else {
|
||||
// Send OK to indicate modification was successful
|
||||
requestEvent.respondWith(stdResp.OK(`Successfully active to ${value}.`));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they shouldn't be doing this
|
||||
requestEvent.respondWith(stdResp.Forbidden(stdResp.Strings.restricted));
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,51 +1,51 @@
|
|||
import config from '../../../config.ts';
|
||||
import { dbClient } from '../../db.ts';
|
||||
import dbClient from '../../db/client.ts';
|
||||
import stdResp from '../stdResponses.ts';
|
||||
import utils from '../../utils.ts';
|
||||
|
||||
export const apiKeyManage = async (requestEvent: Deno.RequestEvent, query: Map<string, string>, apiUserid: BigInt, path: string) => {
|
||||
if ((query.has('a') && ((query.get('a') || '').length > 0)) && (query.has('user') && ((query.get('user') || '').length > 0))) {
|
||||
if (apiUserid === config.api.admin && apiUserid === BigInt(query.get('a') || '0')) {
|
||||
// Flag to see if there is an error inside the catch
|
||||
let key: string,
|
||||
value: number,
|
||||
erroredOut = false;
|
||||
if (query.has('a') && (query.get('a') || '').length > 0 && query.has('user') && (query.get('user') || '').length > 0) {
|
||||
if (apiUserid === config.api.admin && apiUserid === BigInt(query.get('a') || '0')) {
|
||||
// Flag to see if there is an error inside the catch
|
||||
let key: string,
|
||||
value: number,
|
||||
erroredOut = false;
|
||||
|
||||
// Determine key to edit
|
||||
if (path.toLowerCase().indexOf('ban') > 0) {
|
||||
key = 'banned';
|
||||
} else {
|
||||
key = 'active';
|
||||
}
|
||||
// Determine key to edit
|
||||
if (path.toLowerCase().indexOf('ban') > 0) {
|
||||
key = 'banned';
|
||||
} else {
|
||||
key = 'active';
|
||||
}
|
||||
|
||||
// Determine value to set
|
||||
if (path.toLowerCase().indexOf('de') > 0 || path.toLowerCase().indexOf('un') > 0) {
|
||||
value = 0;
|
||||
} else {
|
||||
value = 1;
|
||||
}
|
||||
// Determine value to set
|
||||
if (path.toLowerCase().indexOf('de') > 0 || path.toLowerCase().indexOf('un') > 0) {
|
||||
value = 0;
|
||||
} else {
|
||||
value = 1;
|
||||
}
|
||||
|
||||
// Execute the DB modification
|
||||
await dbClient.execute('UPDATE all_keys SET ?? = ? WHERE userid = ?', [key, value, apiUserid]).catch((e) => {
|
||||
utils.commonLoggers.dbError('apiKeyManage.ts', 'update', e);
|
||||
requestEvent.respondWith(stdResp.InternalServerError(`Failed to ${key} to ${value}.`));
|
||||
erroredOut = true;
|
||||
});
|
||||
// Execute the DB modification
|
||||
await dbClient.execute('UPDATE all_keys SET ?? = ? WHERE userid = ?', [key, value, apiUserid]).catch((e) => {
|
||||
utils.commonLoggers.dbError('apiKeyManage.ts', 'update', e);
|
||||
requestEvent.respondWith(stdResp.InternalServerError(`Failed to ${key} to ${value}.`));
|
||||
erroredOut = true;
|
||||
});
|
||||
|
||||
// Exit this case now if catch errored
|
||||
if (erroredOut) {
|
||||
return;
|
||||
} else {
|
||||
// Send OK as response to indicate modification was successful
|
||||
requestEvent.respondWith(stdResp.OK(`Successfully ${key} to ${value}.`));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they shouldn't be doing this
|
||||
requestEvent.respondWith(stdResp.Forbidden('You can only manage your own key.'));
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams));
|
||||
}
|
||||
// Exit this case now if catch errored
|
||||
if (erroredOut) {
|
||||
return;
|
||||
} else {
|
||||
// Send OK as response to indicate modification was successful
|
||||
requestEvent.respondWith(stdResp.OK(`Successfully ${key} to ${value}.`));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they shouldn't be doing this
|
||||
requestEvent.respondWith(stdResp.Forbidden('You can only manage your own key.'));
|
||||
}
|
||||
} else {
|
||||
// Alert API user that they messed up
|
||||
requestEvent.respondWith(stdResp.BadRequest(stdResp.Strings.missingParams));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,23 +1,25 @@
|
|||
import {
|
||||
// httpd deps
|
||||
Status,
|
||||
STATUS_TEXT,
|
||||
// httpd deps
|
||||
StatusCode,
|
||||
STATUS_CODE,
|
||||
STATUS_TEXT,
|
||||
} from '../../deps.ts';
|
||||
|
||||
const genericResponse = (customText: string, status: Status) => new Response(customText || STATUS_TEXT[status], { status: status, statusText: STATUS_TEXT[status] });
|
||||
const genericResponse = (customText: string, status: StatusCode) =>
|
||||
new Response(customText || STATUS_TEXT[status], { status: status, statusText: STATUS_TEXT[status] });
|
||||
|
||||
export default {
|
||||
BadRequest: (customText: string) => genericResponse(customText, Status.BadRequest),
|
||||
FailedDependency: (customText: string) => genericResponse(customText, Status.FailedDependency),
|
||||
InternalServerError: (customText: string) => genericResponse(customText, Status.InternalServerError),
|
||||
Forbidden: (customText: string) => genericResponse(customText, Status.Forbidden),
|
||||
MethodNotAllowed: (customText: string) => genericResponse(customText, Status.MethodNotAllowed),
|
||||
NotFound: (customText: string) => genericResponse(customText, Status.NotFound),
|
||||
OK: (customText: string) => genericResponse(customText, Status.OK),
|
||||
RequestTimeout: (customText: string) => genericResponse(customText, Status.RequestTimeout),
|
||||
TooManyRequests: (customText: string) => genericResponse(customText, Status.TooManyRequests),
|
||||
Strings: {
|
||||
missingParams: 'Missing Parameters.',
|
||||
restricted: 'This API is restricted.',
|
||||
},
|
||||
BadRequest: (customText: string) => genericResponse(customText, STATUS_CODE.BadRequest),
|
||||
FailedDependency: (customText: string) => genericResponse(customText, STATUS_CODE.FailedDependency),
|
||||
InternalServerError: (customText: string) => genericResponse(customText, STATUS_CODE.InternalServerError),
|
||||
Forbidden: (customText: string) => genericResponse(customText, STATUS_CODE.Forbidden),
|
||||
MethodNotAllowed: (customText: string) => genericResponse(customText, STATUS_CODE.MethodNotAllowed),
|
||||
NotFound: (customText: string) => genericResponse(customText, STATUS_CODE.NotFound),
|
||||
OK: (customText: string) => genericResponse(customText, STATUS_CODE.OK),
|
||||
RequestTimeout: (customText: string) => genericResponse(customText, STATUS_CODE.RequestTimeout),
|
||||
TooManyRequests: (customText: string) => genericResponse(customText, STATUS_CODE.TooManyRequests),
|
||||
Strings: {
|
||||
missingParams: 'Missing Parameters.',
|
||||
restricted: 'This API is restricted.',
|
||||
},
|
||||
};
|
||||
|
|
309
src/intervals.ts
309
src/intervals.ts
|
@ -5,66 +5,67 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
// Discordeno deps
|
||||
cache,
|
||||
cacheHandlers,
|
||||
// imagescript dep
|
||||
is,
|
||||
// Log4Deno deps
|
||||
log,
|
||||
LT,
|
||||
// Discordeno deps
|
||||
cache,
|
||||
cacheHandlers,
|
||||
// imagescript dep
|
||||
is,
|
||||
// Log4Deno deps
|
||||
log,
|
||||
LT,
|
||||
} from '../deps.ts';
|
||||
import { PastCommandCount } from './mod.d.ts';
|
||||
import { dbClient, weekDays } from './db.ts';
|
||||
import dbClient from './db/client.ts';
|
||||
import { weekDays } from './db/common.ts';
|
||||
import utils from './utils.ts';
|
||||
import config from '../config.ts';
|
||||
|
||||
// getRandomStatus() returns status as string
|
||||
// Gets a new random status for the bot
|
||||
const getRandomStatus = async (): Promise<string> => {
|
||||
let status = '';
|
||||
switch (Math.floor((Math.random() * 4) + 1)) {
|
||||
case 1:
|
||||
status = `${config.prefix}help for commands`;
|
||||
break;
|
||||
case 2:
|
||||
status = `Running V${config.version}`;
|
||||
break;
|
||||
case 3:
|
||||
status = `${config.prefix}info to learn more`;
|
||||
break;
|
||||
default: {
|
||||
const cachedCount = await cacheHandlers.size('guilds');
|
||||
status = `Rolling dice for ${cachedCount + cache.dispatchedGuildIds.size} servers`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
let status = '';
|
||||
switch (Math.floor(Math.random() * 4 + 1)) {
|
||||
case 1:
|
||||
status = `${config.prefix}help for commands`;
|
||||
break;
|
||||
case 2:
|
||||
status = `Running V${config.version}`;
|
||||
break;
|
||||
case 3:
|
||||
status = `${config.prefix}info to learn more`;
|
||||
break;
|
||||
default: {
|
||||
const cachedCount = await cacheHandlers.size('guilds');
|
||||
status = `Rolling dice for ${cachedCount + cache.dispatchedGuildIds.size} servers`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
return status;
|
||||
};
|
||||
|
||||
// updateListStatistics(bot ID, current guild count) returns nothing, posts to botlists
|
||||
// Sends the current server count to all bot list sites we are listed on
|
||||
const updateListStatistics = (botID: bigint, serverCount: number): void => {
|
||||
config.botLists.forEach(async (e) => {
|
||||
try {
|
||||
log(LT.LOG, `Updating statistics for ${JSON.stringify(e)}`);
|
||||
if (e.enabled) {
|
||||
const tempHeaders = new Headers();
|
||||
tempHeaders.append(e.headers[0].header, e.headers[0].value);
|
||||
tempHeaders.append('Content-Type', 'application/json');
|
||||
// ?{} is a template used in config, just need to replace it with the real value
|
||||
const response = await fetch(e.apiUrl.replace('?{bot_id}', botID.toString()), {
|
||||
'method': 'POST',
|
||||
'headers': tempHeaders,
|
||||
'body': JSON.stringify(e.body).replace('"?{server_count}"', serverCount.toString()), // ?{server_count} needs the "" removed from around it aswell to make sure its sent as a number
|
||||
});
|
||||
log(LT.INFO, `Posted server count to ${e.name}. Results: ${JSON.stringify(response)}`);
|
||||
}
|
||||
} catch (err) {
|
||||
log(LT.ERROR, `Failed to update statistics for ${e.name} | Error: ${err.name} - ${err.message}`)
|
||||
}
|
||||
});
|
||||
config.botLists.forEach(async (e) => {
|
||||
try {
|
||||
log(LT.LOG, `Updating statistics for ${JSON.stringify(e)}`);
|
||||
if (e.enabled) {
|
||||
const tempHeaders = new Headers();
|
||||
tempHeaders.append(e.headers[0].header, e.headers[0].value);
|
||||
tempHeaders.append('Content-Type', 'application/json');
|
||||
// ?{} is a template used in config, just need to replace it with the real value
|
||||
const response = await fetch(e.apiUrl.replace('?{bot_id}', botID.toString()), {
|
||||
method: 'POST',
|
||||
headers: tempHeaders,
|
||||
body: JSON.stringify(e.body).replace('"?{server_count}"', serverCount.toString()), // ?{server_count} needs the "" removed from around it aswell to make sure its sent as a number
|
||||
});
|
||||
log(LT.INFO, `Posted server count to ${e.name}. Results: ${JSON.stringify(response)}`);
|
||||
}
|
||||
} catch (err) {
|
||||
log(LT.ERROR, `Failed to update statistics for ${e.name} | Error: ${err.name} - ${err.message}`);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Keep one week of data
|
||||
|
@ -73,141 +74,141 @@ const previousHours: Array<Array<PastCommandCount>> = [];
|
|||
// updateHourlyRates() returns nothing, updates DB directly
|
||||
// Updates the hourlyRate for command usage
|
||||
const updateHourlyRates = async () => {
|
||||
try {
|
||||
const newestHour = await dbClient.query('SELECT command, count FROM command_cnt ORDER BY command;').catch((e) => utils.commonLoggers.dbError('intervals.ts:71', 'query', e));
|
||||
previousHours.push(newestHour);
|
||||
if (previousHours.length > 1) {
|
||||
const oldestHour = previousHours[0];
|
||||
try {
|
||||
const newestHour = await dbClient
|
||||
.query('SELECT command, count FROM command_cnt ORDER BY command;')
|
||||
.catch((e) => utils.commonLoggers.dbError('intervals.ts:71', 'query', e));
|
||||
previousHours.push(newestHour);
|
||||
if (previousHours.length > 1) {
|
||||
const oldestHour = previousHours[0];
|
||||
|
||||
const computedDiff: Array<PastCommandCount> = [];
|
||||
for (let i = 0; i < newestHour.length; i++) {
|
||||
computedDiff.push({
|
||||
command: newestHour[i].command,
|
||||
count: (newestHour[i].count - oldestHour[i].count),
|
||||
});
|
||||
log(LT.LOG, `Updating hourlyRate | Computing diffs: ${JSON.stringify(computedDiff)}`);
|
||||
}
|
||||
const computedDiff: Array<PastCommandCount> = [];
|
||||
for (let i = 0; i < newestHour.length; i++) {
|
||||
computedDiff.push({
|
||||
command: newestHour[i].command,
|
||||
count: newestHour[i].count - oldestHour[i].count,
|
||||
});
|
||||
log(LT.LOG, `Updating hourlyRate | Computing diffs: ${JSON.stringify(computedDiff)}`);
|
||||
}
|
||||
|
||||
// Update DB
|
||||
computedDiff.forEach(async (cmd) => {
|
||||
log(LT.LOG, `Updating hourlyRate | Storing to DB: ${JSON.stringify(cmd)}`);
|
||||
await dbClient.execute(`UPDATE command_cnt SET hourlyRate = ? WHERE command = ?`, [cmd.count / previousHours.length, cmd.command]).catch((e) =>
|
||||
utils.commonLoggers.dbError('intervals.ts:88', 'update', e)
|
||||
);
|
||||
});
|
||||
}
|
||||
// Update DB
|
||||
computedDiff.forEach(async (cmd) => {
|
||||
log(LT.LOG, `Updating hourlyRate | Storing to DB: ${JSON.stringify(cmd)}`);
|
||||
await dbClient
|
||||
.execute(`UPDATE command_cnt SET hourlyRate = ? WHERE command = ?`, [cmd.count / previousHours.length, cmd.command])
|
||||
.catch((e) => utils.commonLoggers.dbError('intervals.ts:88', 'update', e));
|
||||
});
|
||||
}
|
||||
|
||||
if (previousHours.length > hoursToKeep) {
|
||||
previousHours.unshift();
|
||||
}
|
||||
} catch (e) {
|
||||
log(LT.ERROR, `Something went wrong in previousHours interval | Error: ${e.name} - ${e.message}`);
|
||||
}
|
||||
if (previousHours.length > hoursToKeep) {
|
||||
previousHours.unshift();
|
||||
}
|
||||
} catch (e) {
|
||||
log(LT.ERROR, `Something went wrong in previousHours interval | Error: ${e.name} - ${e.message}`);
|
||||
}
|
||||
};
|
||||
|
||||
// getPercentOfRange(min, max, val) returns number
|
||||
// Gets a percent value of where val lies in the min-max range
|
||||
const getPercentOfRange = (minVal: number, maxVal: number, val: number): number => {
|
||||
const localMax = maxVal - minVal;
|
||||
const localVal = val - minVal;
|
||||
const localMax = maxVal - minVal;
|
||||
const localVal = val - minVal;
|
||||
|
||||
return localVal / localMax;
|
||||
return localVal / localMax;
|
||||
};
|
||||
|
||||
// Pixel locations in heatmap-base.png, pixel locations are 0 based
|
||||
// dayPixels holds the left and right (AKA X Coord) pixel locations for each col (ex: [leftPX, rightPX])
|
||||
const dayPixels: Array<Array<number>> = [
|
||||
[72, 159],
|
||||
[163, 260],
|
||||
[264, 359],
|
||||
[363, 497],
|
||||
[501, 608],
|
||||
[612, 686],
|
||||
[690, 800],
|
||||
[72, 159],
|
||||
[163, 260],
|
||||
[264, 359],
|
||||
[363, 497],
|
||||
[501, 608],
|
||||
[612, 686],
|
||||
[690, 800],
|
||||
];
|
||||
// hourPixels holds the top and bottom (AKA Y Coord) pixel locations for each row (ex: [topPX, botPX])
|
||||
const hourPixels: Array<Array<number>> = [
|
||||
[29, 49],
|
||||
[51, 72],
|
||||
[74, 95],
|
||||
[97, 118],
|
||||
[120, 141],
|
||||
[143, 164],
|
||||
[166, 187],
|
||||
[189, 209],
|
||||
[211, 232],
|
||||
[234, 254],
|
||||
[256, 277],
|
||||
[279, 299],
|
||||
[301, 322],
|
||||
[324, 345],
|
||||
[347, 368],
|
||||
[370, 391],
|
||||
[393, 413],
|
||||
[415, 436],
|
||||
[438, 459],
|
||||
[461, 482],
|
||||
[484, 505],
|
||||
[507, 528],
|
||||
[530, 550],
|
||||
[552, 572],
|
||||
[29, 49],
|
||||
[51, 72],
|
||||
[74, 95],
|
||||
[97, 118],
|
||||
[120, 141],
|
||||
[143, 164],
|
||||
[166, 187],
|
||||
[189, 209],
|
||||
[211, 232],
|
||||
[234, 254],
|
||||
[256, 277],
|
||||
[279, 299],
|
||||
[301, 322],
|
||||
[324, 345],
|
||||
[347, 368],
|
||||
[370, 391],
|
||||
[393, 413],
|
||||
[415, 436],
|
||||
[438, 459],
|
||||
[461, 482],
|
||||
[484, 505],
|
||||
[507, 528],
|
||||
[530, 550],
|
||||
[552, 572],
|
||||
];
|
||||
// updateHeatmap() returns nothing, creates new heatmap.png
|
||||
// Updates the heatmap image with latest data from the db
|
||||
let minRollCnt: number;
|
||||
let maxRollCnt: number;
|
||||
const updateHeatmapPng = async () => {
|
||||
const baseHeatmap = Deno.readFileSync('./src/endpoints/gets/heatmap-base.png');
|
||||
const heatmap = await is.decode(baseHeatmap);
|
||||
if (!(heatmap instanceof is.Image)) {
|
||||
return;
|
||||
}
|
||||
// Get latest data from DB
|
||||
const heatmapData = await dbClient.query('SELECT * FROM roll_time_heatmap ORDER BY hour;').catch((e) => utils.commonLoggers.dbError('intervals.ts:148', 'query', e));
|
||||
const baseHeatmap = Deno.readFileSync('./src/endpoints/gets/heatmap-base.png');
|
||||
const heatmap = await is.decode(baseHeatmap);
|
||||
if (!(heatmap instanceof is.Image)) {
|
||||
return;
|
||||
}
|
||||
// Get latest data from DB
|
||||
const heatmapData = await dbClient
|
||||
.query('SELECT * FROM roll_time_heatmap ORDER BY hour;')
|
||||
.catch((e) => utils.commonLoggers.dbError('intervals.ts:148', 'query', e));
|
||||
|
||||
minRollCnt = Infinity;
|
||||
maxRollCnt = 0;
|
||||
// determine min and max values
|
||||
for (const hour of heatmapData) {
|
||||
for (const day of weekDays) {
|
||||
const rollCnt = hour[day];
|
||||
log(LT.LOG, `updateHeatmapPng | finding min/max | min: ${minRollCnt} max: ${maxRollCnt} curr: ${rollCnt}`);
|
||||
if (rollCnt > maxRollCnt) {
|
||||
maxRollCnt = rollCnt;
|
||||
}
|
||||
if (rollCnt < minRollCnt) {
|
||||
minRollCnt = rollCnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
minRollCnt = Infinity;
|
||||
maxRollCnt = 0;
|
||||
// determine min and max values
|
||||
for (const hour of heatmapData) {
|
||||
for (const day of weekDays) {
|
||||
const rollCnt = hour[day];
|
||||
log(LT.LOG, `updateHeatmapPng | finding min/max | min: ${minRollCnt} max: ${maxRollCnt} curr: ${rollCnt}`);
|
||||
if (rollCnt > maxRollCnt) {
|
||||
maxRollCnt = rollCnt;
|
||||
}
|
||||
if (rollCnt < minRollCnt) {
|
||||
minRollCnt = rollCnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply values to image
|
||||
for (let hour = 0; hour < heatmapData.length; hour++) {
|
||||
for (let day = 0; day < weekDays.length; day++) {
|
||||
log(LT.LOG, `updateHeatmapPng | putting ${weekDays[day]} ${hour}:00 into image`);
|
||||
const percent = getPercentOfRange(minRollCnt, maxRollCnt, heatmapData[hour][weekDays[day]]);
|
||||
heatmap.drawBox(
|
||||
dayPixels[day][0] + 1,
|
||||
hourPixels[hour][0] + 1,
|
||||
dayPixels[day][1] - dayPixels[day][0] + 1,
|
||||
hourPixels[hour][1] - hourPixels[hour][0] + 1,
|
||||
is.Image.rgbToColor(
|
||||
255 * (1 - percent),
|
||||
255 * percent,
|
||||
0,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
// Apply values to image
|
||||
for (let hour = 0; hour < heatmapData.length; hour++) {
|
||||
for (let day = 0; day < weekDays.length; day++) {
|
||||
log(LT.LOG, `updateHeatmapPng | putting ${weekDays[day]} ${hour}:00 into image`);
|
||||
const percent = getPercentOfRange(minRollCnt, maxRollCnt, heatmapData[hour][weekDays[day]]);
|
||||
heatmap.drawBox(
|
||||
dayPixels[day][0] + 1,
|
||||
hourPixels[hour][0] + 1,
|
||||
dayPixels[day][1] - dayPixels[day][0] + 1,
|
||||
hourPixels[hour][1] - hourPixels[hour][0] + 1,
|
||||
is.Image.rgbToColor(255 * (1 - percent), 255 * percent, 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Deno.writeFileSync('./src/endpoints/gets/heatmap.png', await heatmap.encode());
|
||||
Deno.writeFileSync('./src/endpoints/gets/heatmap.png', await heatmap.encode());
|
||||
};
|
||||
|
||||
export default {
|
||||
getRandomStatus,
|
||||
updateListStatistics,
|
||||
updateHourlyRates,
|
||||
updateHeatmapPng,
|
||||
getMinRollCnt: () => minRollCnt,
|
||||
getMaxRollCnt: () => maxRollCnt,
|
||||
getRandomStatus,
|
||||
updateListStatistics,
|
||||
updateHourlyRates,
|
||||
updateHeatmapPng,
|
||||
getMinRollCnt: () => minRollCnt,
|
||||
getMaxRollCnt: () => maxRollCnt,
|
||||
};
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
import config from '../../config.ts';
|
||||
import { DEVMODE } from '../../flags.ts';
|
||||
import { dbClient, queries } from '../db.ts';
|
||||
import dbClient from '../db/client.ts';
|
||||
import { queries } from '../db/common.ts';
|
||||
import {
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Log4Deno deps
|
||||
log,
|
||||
LT,
|
||||
// Discordeno deps
|
||||
sendDirectMessage,
|
||||
sendMessage,
|
||||
// Discordeno deps
|
||||
DiscordenoMessage,
|
||||
// Log4Deno deps
|
||||
log,
|
||||
LT,
|
||||
// Discordeno deps
|
||||
sendDirectMessage,
|
||||
sendMessage,
|
||||
} from '../../deps.ts';
|
||||
import { SolvedRoll } from '../solver/solver.d.ts';
|
||||
import { QueuedRoll, RollModifiers } from '../mod.d.ts';
|
||||
|
@ -22,189 +23,208 @@ const rollQueue: Array<QueuedRoll> = [];
|
|||
|
||||
// Handle setting up and calling the rollWorker
|
||||
const handleRollWorker = async (rq: QueuedRoll) => {
|
||||
currentWorkers++;
|
||||
currentWorkers++;
|
||||
|
||||
// gmModifiers used to create gmEmbed (basically just turn off the gmRoll)
|
||||
const gmModifiers = JSON.parse(JSON.stringify(rq.modifiers));
|
||||
gmModifiers.gmRoll = false;
|
||||
// gmModifiers used to create gmEmbed (basically just turn off the gmRoll)
|
||||
const gmModifiers = JSON.parse(JSON.stringify(rq.modifiers));
|
||||
gmModifiers.gmRoll = false;
|
||||
|
||||
const rollWorker = new Worker(new URL('../solver/rollWorker.ts', import.meta.url).href, { type: 'module' });
|
||||
const rollWorker = new Worker(new URL('../solver/rollWorker.ts', import.meta.url).href, { type: 'module' });
|
||||
|
||||
const workerTimeout = setTimeout(async () => {
|
||||
rollWorker.terminate();
|
||||
currentWorkers--;
|
||||
if (rq.apiRoll) {
|
||||
rq.api.requestEvent.respondWith(stdResp.RequestTimeout('Roll took too long to process, try breaking roll down into simpler parts'));
|
||||
} else {
|
||||
rq.dd.m.edit({
|
||||
embeds: [
|
||||
(await generateRollEmbed(
|
||||
rq.dd.message.authorId,
|
||||
<SolvedRoll> {
|
||||
error: true,
|
||||
errorCode: 'TooComplex',
|
||||
errorMsg: 'Error: Roll took too long to process, try breaking roll down into simpler parts',
|
||||
},
|
||||
<RollModifiers> {},
|
||||
)).embed,
|
||||
],
|
||||
}).catch((e) => utils.commonLoggers.messageEditError('rollQueue.ts:51', rq.dd.m, e));
|
||||
}
|
||||
}, config.limits.workerTimeout);
|
||||
const workerTimeout = setTimeout(async () => {
|
||||
rollWorker.terminate();
|
||||
currentWorkers--;
|
||||
if (rq.apiRoll) {
|
||||
rq.api.requestEvent.respondWith(stdResp.RequestTimeout('Roll took too long to process, try breaking roll down into simpler parts'));
|
||||
} else {
|
||||
rq.dd.m
|
||||
.edit({
|
||||
embeds: [
|
||||
(
|
||||
await generateRollEmbed(
|
||||
rq.dd.message.authorId,
|
||||
<SolvedRoll>{
|
||||
error: true,
|
||||
errorCode: 'TooComplex',
|
||||
errorMsg: 'Error: Roll took too long to process, try breaking roll down into simpler parts',
|
||||
},
|
||||
<RollModifiers>{}
|
||||
)
|
||||
).embed,
|
||||
],
|
||||
})
|
||||
.catch((e) => utils.commonLoggers.messageEditError('rollQueue.ts:51', rq.dd.m, e));
|
||||
}
|
||||
}, config.limits.workerTimeout);
|
||||
|
||||
rollWorker.addEventListener('message', async (workerMessage) => {
|
||||
if (workerMessage.data === 'ready') {
|
||||
rollWorker.postMessage({
|
||||
rollCmd: rq.rollCmd,
|
||||
modifiers: rq.modifiers,
|
||||
});
|
||||
return;
|
||||
}
|
||||
let apiErroredOut = false;
|
||||
try {
|
||||
currentWorkers--;
|
||||
clearTimeout(workerTimeout);
|
||||
const returnmsg = workerMessage.data;
|
||||
const pubEmbedDetails = await generateRollEmbed(rq.apiRoll ? rq.api.userId : rq.dd.message.authorId, returnmsg, rq.modifiers);
|
||||
const gmEmbedDetails = await generateRollEmbed(rq.apiRoll ? rq.api.userId : rq.dd.message.authorId, returnmsg, gmModifiers);
|
||||
const countEmbed = generateCountDetailsEmbed(returnmsg.counts);
|
||||
rollWorker.addEventListener('message', async (workerMessage) => {
|
||||
if (workerMessage.data === 'ready') {
|
||||
rollWorker.postMessage({
|
||||
rollCmd: rq.rollCmd,
|
||||
modifiers: rq.modifiers,
|
||||
});
|
||||
return;
|
||||
}
|
||||
let apiErroredOut = false;
|
||||
try {
|
||||
currentWorkers--;
|
||||
clearTimeout(workerTimeout);
|
||||
const returnmsg = workerMessage.data;
|
||||
const pubEmbedDetails = await generateRollEmbed(rq.apiRoll ? rq.api.userId : rq.dd.message.authorId, returnmsg, rq.modifiers);
|
||||
const gmEmbedDetails = await generateRollEmbed(rq.apiRoll ? rq.api.userId : rq.dd.message.authorId, returnmsg, gmModifiers);
|
||||
const countEmbed = generateCountDetailsEmbed(returnmsg.counts);
|
||||
|
||||
// If there was an error, report it to the user in hopes that they can determine what they did wrong
|
||||
if (returnmsg.error) {
|
||||
if (rq.apiRoll) {
|
||||
rq.api.requestEvent.respondWith(stdResp.InternalServerError(returnmsg.errorMsg));
|
||||
} else {
|
||||
rq.dd.m.edit({ embeds: [pubEmbedDetails.embed] });
|
||||
}
|
||||
// If there was an error, report it to the user in hopes that they can determine what they did wrong
|
||||
if (returnmsg.error) {
|
||||
if (rq.apiRoll) {
|
||||
rq.api.requestEvent.respondWith(stdResp.InternalServerError(returnmsg.errorMsg));
|
||||
} else {
|
||||
rq.dd.m.edit({ embeds: [pubEmbedDetails.embed] });
|
||||
}
|
||||
|
||||
if (rq.apiRoll || DEVMODE && config.logRolls) {
|
||||
// If enabled, log rolls so we can see what went wrong
|
||||
dbClient.execute(queries.insertRollLogCmd(rq.apiRoll ? 1 : 0, 1), [rq.originalCommand, returnmsg.errorCode, rq.apiRoll ? null : rq.dd.m.id]).catch((e) =>
|
||||
utils.commonLoggers.dbError('rollQueue.ts:82', 'insert into', e)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let n: DiscordenoMessage | void;
|
||||
// Determine if we are to send a GM roll or a normal roll
|
||||
if (rq.modifiers.gmRoll) {
|
||||
if (rq.apiRoll) {
|
||||
n = await sendMessage(rq.api.channelId, {
|
||||
content: rq.modifiers.apiWarn,
|
||||
embeds: [pubEmbedDetails.embed],
|
||||
}).catch(() => {
|
||||
apiErroredOut = true;
|
||||
rq.api.requestEvent.respondWith(stdResp.InternalServerError('Message failed to send - location 0.'));
|
||||
});
|
||||
} else {
|
||||
// Send the public embed to correct channel
|
||||
rq.dd.m.edit({ embeds: [pubEmbedDetails.embed] });
|
||||
}
|
||||
if (rq.apiRoll || (DEVMODE && config.logRolls)) {
|
||||
// If enabled, log rolls so we can see what went wrong
|
||||
dbClient
|
||||
.execute(queries.insertRollLogCmd(rq.apiRoll ? 1 : 0, 1), [rq.originalCommand, returnmsg.errorCode, rq.apiRoll ? null : rq.dd.m.id])
|
||||
.catch((e) => utils.commonLoggers.dbError('rollQueue.ts:82', 'insert into', e));
|
||||
}
|
||||
} else {
|
||||
let n: DiscordenoMessage | void;
|
||||
// Determine if we are to send a GM roll or a normal roll
|
||||
if (rq.modifiers.gmRoll) {
|
||||
if (rq.apiRoll) {
|
||||
n = await sendMessage(rq.api.channelId, {
|
||||
content: rq.modifiers.apiWarn,
|
||||
embeds: [pubEmbedDetails.embed],
|
||||
}).catch(() => {
|
||||
apiErroredOut = true;
|
||||
rq.api.requestEvent.respondWith(stdResp.InternalServerError('Message failed to send - location 0.'));
|
||||
});
|
||||
} else {
|
||||
// Send the public embed to correct channel
|
||||
rq.dd.m.edit({ embeds: [pubEmbedDetails.embed] });
|
||||
}
|
||||
|
||||
if (!apiErroredOut) {
|
||||
// And message the full details to each of the GMs, alerting roller of every GM that could not be messaged
|
||||
rq.modifiers.gms.forEach(async (gm) => {
|
||||
log(LT.LOG, `Messaging GM ${gm}`);
|
||||
// Attempt to DM the GM and send a warning if it could not DM a GM
|
||||
await sendDirectMessage(BigInt(gm.substring(2, gm.length - 1)), {
|
||||
embeds: rq.modifiers.count ? [gmEmbedDetails.embed, countEmbed] : [gmEmbedDetails.embed],
|
||||
}).then(async () => {
|
||||
// Check if we need to attach a file and send it after the initial details sent
|
||||
if (gmEmbedDetails.hasAttachment) {
|
||||
await sendDirectMessage(BigInt(gm.substring(2, gm.length - 1)), {
|
||||
file: gmEmbedDetails.attachment,
|
||||
}).catch(() => {
|
||||
if (n && rq.apiRoll) {
|
||||
n.reply(generateDMFailed(gm));
|
||||
} else {
|
||||
rq.dd.message.reply(generateDMFailed(gm));
|
||||
}
|
||||
});
|
||||
}
|
||||
}).catch(() => {
|
||||
if (rq.apiRoll && n) {
|
||||
n.reply(generateDMFailed(gm));
|
||||
} else {
|
||||
rq.dd.message.reply(generateDMFailed(gm));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Not a gm roll, so just send normal embed to correct channel
|
||||
if (rq.apiRoll) {
|
||||
n = await sendMessage(rq.api.channelId, {
|
||||
content: rq.modifiers.apiWarn,
|
||||
embeds: rq.modifiers.count ? [pubEmbedDetails.embed, countEmbed] : [pubEmbedDetails.embed],
|
||||
}).catch(() => {
|
||||
apiErroredOut = true;
|
||||
rq.api.requestEvent.respondWith(stdResp.InternalServerError('Message failed to send - location 1.'));
|
||||
});
|
||||
} else {
|
||||
n = await rq.dd.m.edit({
|
||||
embeds: rq.modifiers.count ? [pubEmbedDetails.embed, countEmbed] : [pubEmbedDetails.embed],
|
||||
});
|
||||
}
|
||||
if (!apiErroredOut) {
|
||||
// And message the full details to each of the GMs, alerting roller of every GM that could not be messaged
|
||||
rq.modifiers.gms.forEach(async (gm) => {
|
||||
log(LT.LOG, `Messaging GM ${gm}`);
|
||||
// Attempt to DM the GM and send a warning if it could not DM a GM
|
||||
await sendDirectMessage(BigInt(gm.substring(2, gm.length - 1)), {
|
||||
embeds: rq.modifiers.count ? [gmEmbedDetails.embed, countEmbed] : [gmEmbedDetails.embed],
|
||||
})
|
||||
.then(async () => {
|
||||
// Check if we need to attach a file and send it after the initial details sent
|
||||
if (gmEmbedDetails.hasAttachment) {
|
||||
await sendDirectMessage(BigInt(gm.substring(2, gm.length - 1)), {
|
||||
file: gmEmbedDetails.attachment,
|
||||
}).catch(() => {
|
||||
if (n && rq.apiRoll) {
|
||||
n.reply(generateDMFailed(gm));
|
||||
} else {
|
||||
rq.dd.message.reply(generateDMFailed(gm));
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
if (rq.apiRoll && n) {
|
||||
n.reply(generateDMFailed(gm));
|
||||
} else {
|
||||
rq.dd.message.reply(generateDMFailed(gm));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Not a gm roll, so just send normal embed to correct channel
|
||||
if (rq.apiRoll) {
|
||||
n = await sendMessage(rq.api.channelId, {
|
||||
content: rq.modifiers.apiWarn,
|
||||
embeds: rq.modifiers.count ? [pubEmbedDetails.embed, countEmbed] : [pubEmbedDetails.embed],
|
||||
}).catch(() => {
|
||||
apiErroredOut = true;
|
||||
rq.api.requestEvent.respondWith(stdResp.InternalServerError('Message failed to send - location 1.'));
|
||||
});
|
||||
} else {
|
||||
n = await rq.dd.m.edit({
|
||||
embeds: rq.modifiers.count ? [pubEmbedDetails.embed, countEmbed] : [pubEmbedDetails.embed],
|
||||
});
|
||||
}
|
||||
|
||||
if (pubEmbedDetails.hasAttachment && n) {
|
||||
// Attachment requires you to send a new message
|
||||
n.reply({
|
||||
file: pubEmbedDetails.attachment,
|
||||
});
|
||||
}
|
||||
}
|
||||
if (pubEmbedDetails.hasAttachment && n) {
|
||||
// Attachment requires you to send a new message
|
||||
n.reply({
|
||||
file: pubEmbedDetails.attachment,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (rq.apiRoll && !apiErroredOut) {
|
||||
dbClient.execute(queries.insertRollLogCmd(1, 0), [rq.originalCommand, returnmsg.errorCode, n ? n.id : null]).catch((e) => utils.commonLoggers.dbError('rollQueue.ts:155', 'insert into', e));
|
||||
if (rq.apiRoll && !apiErroredOut) {
|
||||
dbClient
|
||||
.execute(queries.insertRollLogCmd(1, 0), [rq.originalCommand, returnmsg.errorCode, n ? n.id : null])
|
||||
.catch((e) => utils.commonLoggers.dbError('rollQueue.ts:155', 'insert into', e));
|
||||
|
||||
rq.api.requestEvent.respondWith(stdResp.OK(JSON.stringify(
|
||||
rq.modifiers.count
|
||||
? {
|
||||
counts: countEmbed,
|
||||
details: pubEmbedDetails,
|
||||
}
|
||||
: {
|
||||
details: pubEmbedDetails,
|
||||
},
|
||||
)));
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
log(LT.ERROR, `Unddandled Error: ${JSON.stringify(e)}`);
|
||||
if (rq.apiRoll && !apiErroredOut) {
|
||||
rq.api.requestEvent.respondWith(stdResp.InternalServerError(JSON.stringify(e)));
|
||||
}
|
||||
}
|
||||
});
|
||||
rq.api.requestEvent.respondWith(
|
||||
stdResp.OK(
|
||||
JSON.stringify(
|
||||
rq.modifiers.count
|
||||
? {
|
||||
counts: countEmbed,
|
||||
details: pubEmbedDetails,
|
||||
}
|
||||
: {
|
||||
details: pubEmbedDetails,
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
log(LT.ERROR, `Unddandled Error: ${JSON.stringify(e)}`);
|
||||
if (rq.apiRoll && !apiErroredOut) {
|
||||
rq.api.requestEvent.respondWith(stdResp.InternalServerError(JSON.stringify(e)));
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Runs the roll or queues it depending on how many workers are currently running
|
||||
export const queueRoll = async (rq: QueuedRoll) => {
|
||||
if (rq.apiRoll) {
|
||||
handleRollWorker(rq);
|
||||
} else if (!rollQueue.length && currentWorkers < config.limits.maxWorkers) {
|
||||
handleRollWorker(rq);
|
||||
} else {
|
||||
rq.dd.m.edit({
|
||||
embeds: [{
|
||||
color: infoColor2,
|
||||
title: `${config.name} currently has its hands full and has queued your roll.`,
|
||||
description: `There are currently ${currentWorkers + rollQueue.length} rolls ahead of this roll.
|
||||
if (rq.apiRoll) {
|
||||
handleRollWorker(rq);
|
||||
} else if (!rollQueue.length && currentWorkers < config.limits.maxWorkers) {
|
||||
handleRollWorker(rq);
|
||||
} else {
|
||||
rq.dd.m
|
||||
.edit({
|
||||
embeds: [
|
||||
{
|
||||
color: infoColor2,
|
||||
title: `${config.name} currently has its hands full and has queued your roll.`,
|
||||
description: `There are currently ${currentWorkers + rollQueue.length} rolls ahead of this roll.
|
||||
|
||||
The results for this roll will replace this message when it is done.`,
|
||||
}],
|
||||
}).catch((e: Error) => utils.commonLoggers.messageEditError('rollQueue.ts:197', rq.dd.m, e));
|
||||
rollQueue.push(rq);
|
||||
}
|
||||
},
|
||||
],
|
||||
})
|
||||
.catch((e: Error) => utils.commonLoggers.messageEditError('rollQueue.ts:197', rq.dd.m, e));
|
||||
rollQueue.push(rq);
|
||||
}
|
||||
};
|
||||
|
||||
// Checks the queue constantly to make sure the queue stays empty
|
||||
setInterval(async () => {
|
||||
log(LT.LOG, `Checking rollQueue for items, rollQueue length: ${rollQueue.length}, currentWorkers: ${currentWorkers}, config.limits.maxWorkers: ${config.limits.maxWorkers}`);
|
||||
if (rollQueue.length && currentWorkers < config.limits.maxWorkers) {
|
||||
const temp = rollQueue.shift();
|
||||
if (temp) {
|
||||
temp.dd.m.edit(rollingEmbed).catch((e: Error) => utils.commonLoggers.messageEditError('rollQueue.ts:208', temp.dd.m, e));
|
||||
handleRollWorker(temp);
|
||||
}
|
||||
}
|
||||
log(
|
||||
LT.LOG,
|
||||
`Checking rollQueue for items, rollQueue length: ${rollQueue.length}, currentWorkers: ${currentWorkers}, config.limits.maxWorkers: ${config.limits.maxWorkers}`
|
||||
);
|
||||
if (rollQueue.length && currentWorkers < config.limits.maxWorkers) {
|
||||
const temp = rollQueue.shift();
|
||||
if (temp) {
|
||||
temp.dd.m.edit(rollingEmbed).catch((e: Error) => utils.commonLoggers.messageEditError('rollQueue.ts:208', temp.dd.m, e));
|
||||
handleRollWorker(temp);
|
||||
}
|
||||
}
|
||||
}, 1000);
|
||||
|
|
Loading…
Reference in New Issue