1175 lines
42 KiB
TypeScript
1175 lines
42 KiB
TypeScript
import {
|
|
ActionRow,
|
|
botId,
|
|
ButtonComponent,
|
|
ButtonData,
|
|
cache,
|
|
cacheHandlers,
|
|
// MySQL Driver deps
|
|
Client,
|
|
DebugArg,
|
|
deleteMessage,
|
|
DiscordActivityTypes,
|
|
DiscordButtonStyles,
|
|
DiscordenoGuild,
|
|
DiscordenoMessage,
|
|
DiscordInteractionResponseTypes,
|
|
DiscordInteractionTypes,
|
|
editBotNickname,
|
|
editBotStatus,
|
|
Embed,
|
|
getGuild,
|
|
getMessage,
|
|
getUser,
|
|
hasGuildPermissions,
|
|
initLog,
|
|
Intents,
|
|
log,
|
|
// Log4Deno deps
|
|
LT,
|
|
sendDirectMessage,
|
|
sendInteractionResponse,
|
|
sendMessage,
|
|
// Discordeno deps
|
|
startBot,
|
|
} from './deps.ts';
|
|
|
|
import { ActiveLFG, BuildingLFG, GuildCleanChannels, GuildModRoles, GuildPrefixes } from './src/mod.d.ts';
|
|
import intervals from './src/intervals.ts';
|
|
import { LFGActivities } from './src/games.ts';
|
|
import { JoinLeaveType } from './src/lfgHandlers.d.ts';
|
|
import { handleLFGStep, handleMemberJoin, handleMemberLeave, urlToIds } from './src/lfgHandlers.ts';
|
|
import { constantCmds, editBtns, lfgStepQuestions } from './src/constantCmds.ts';
|
|
import { jsonParseBig, jsonStringifyBig } from './src/utils.ts';
|
|
|
|
import { DEBUG, LOCALMODE } from '../flags.ts';
|
|
import config from '../config.ts';
|
|
|
|
// Initialize DB client
|
|
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,
|
|
});
|
|
|
|
// Initialize logging client with folder to use for logs, needs --allow-write set on Deno startup
|
|
initLog('logs', DEBUG);
|
|
log(LT.INFO, `${config.name} Starting up . . .`);
|
|
|
|
// Handle idling out the active builders
|
|
const activeBuilders: Array<BuildingLFG> = [];
|
|
setInterval(() => {
|
|
intervals.buildingTimeout(activeBuilders);
|
|
}, 1000);
|
|
|
|
const activeLFGPosts: Array<ActiveLFG> = jsonParseBig(localStorage.getItem('activeLFGPosts') || '[]');
|
|
log(LT.INFO, `Loaded ${activeLFGPosts.length} activeLFGPosts`);
|
|
setInterval(() => {
|
|
intervals.lfgNotifier(activeLFGPosts);
|
|
}, 60000);
|
|
|
|
const guildPrefixes: Map<bigint, string> = new Map();
|
|
const getGuildPrefixes = await dbClient.query('SELECT * FROM guild_prefix');
|
|
getGuildPrefixes.forEach((g: GuildPrefixes) => {
|
|
guildPrefixes.set(g.guildId, g.prefix);
|
|
});
|
|
|
|
const guildModRoles: Map<bigint, bigint> = new Map();
|
|
const getGuildModRoles = await dbClient.query('SELECT * FROM guild_mod_role');
|
|
getGuildModRoles.forEach((g: GuildModRoles) => {
|
|
guildModRoles.set(g.guildId, g.roleId);
|
|
});
|
|
|
|
const cleanChannels: Map<bigint, Array<bigint>> = new Map();
|
|
const getCleanChannels = await dbClient.query('SELECT * FROM guild_clean_channel');
|
|
getCleanChannels.forEach((g: GuildCleanChannels) => {
|
|
const tempArr = cleanChannels.get(g.guildId) || [];
|
|
tempArr.push(g.channelId);
|
|
cleanChannels.set(g.guildId, tempArr);
|
|
});
|
|
|
|
const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
|
|
|
// 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',
|
|
});
|
|
|
|
// Interval to rotate the status text every 30 seconds to show off more commands
|
|
setInterval(async () => {
|
|
log(LT.LOG, 'Changing bot status');
|
|
try {
|
|
const cachedCount = await cacheHandlers.size('guilds');
|
|
// Wrapped in try-catch due to hard crash possible
|
|
editBotStatus({
|
|
activities: [{
|
|
name: intervals.getRandomStatus(cachedCount),
|
|
type: DiscordActivityTypes.Game,
|
|
createdAt: new Date().getTime(),
|
|
}],
|
|
status: 'online',
|
|
});
|
|
} catch (e) {
|
|
log(LT.ERROR, `Failed to update status: ${jsonStringifyBig(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);
|
|
}, 86400000);
|
|
|
|
// 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);
|
|
editBotStatus({
|
|
activities: [{
|
|
name: 'Booting Complete',
|
|
type: DiscordActivityTypes.Game,
|
|
createdAt: new Date().getTime(),
|
|
}],
|
|
status: 'online',
|
|
});
|
|
sendMessage(config.logChannel, `${config.name} has started, running version ${config.version}.`).catch((e) => {
|
|
log(LT.ERROR, `Failed to send message: ${jsonStringifyBig(e)}`);
|
|
});
|
|
}, 1000);
|
|
},
|
|
guildCreate: (guild: DiscordenoGuild) => {
|
|
log(LT.LOG, `Handling joining guild ${jsonStringifyBig(guild)}`);
|
|
sendMessage(config.logChannel, `New guild joined: ${guild.name} (id: ${guild.id}). This guild has ${guild.memberCount} members!`).catch((e) => {
|
|
log(LT.ERROR, `Failed to send message: ${jsonStringifyBig(e)}`);
|
|
});
|
|
},
|
|
guildDelete: async (guild: DiscordenoGuild) => {
|
|
log(LT.LOG, `Handling leaving guild ${jsonStringifyBig(guild)}`);
|
|
sendMessage(config.logChannel, `I have been removed from: ${guild.name} (id: ${guild.id}).`).catch((e) => {
|
|
log(LT.ERROR, `Failed to send message: ${jsonStringifyBig(e)}`);
|
|
});
|
|
|
|
try {
|
|
await dbClient.execute('DELETE FROM guild_prefix WHERE guildId = ?', [guild.id]);
|
|
await dbClient.execute('DELETE FROM guild_mod_role WHERE guildId = ?', [guild.id]);
|
|
await dbClient.execute('DELETE FROM guild_clean_channel WHERE guildId = ?', [guild.id]);
|
|
} catch (e) {
|
|
log(LT.WARN, `Failed to remove guild from DB: ${jsonStringifyBig(e)}`);
|
|
}
|
|
},
|
|
debug: (dmsg: string | DebugArg, data?: string) => log(LT.LOG, `Debug Message | ${jsonStringifyBig(dmsg)} | ${jsonStringifyBig(data)}`, false),
|
|
messageCreate: async (message: DiscordenoMessage) => {
|
|
// Ignore all other bots
|
|
if (message.isBot) return;
|
|
|
|
const prefix = guildPrefixes.get(message.guildId) || config.prefix;
|
|
|
|
// Handle messages not starting with the prefix
|
|
if (message.content.indexOf(prefix) !== 0) {
|
|
// Mentions
|
|
if (message.mentionedUserIds[0] === botId && (message.content.trim().startsWith(`<@${botId}>`) || message.content.trim().startsWith(`<@!${botId}>`))) {
|
|
// Light telemetry to see how many times a command is being run
|
|
await dbClient.execute(`CALL INC_CNT("prefix");`).catch((e) => {
|
|
log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${jsonStringifyBig(e)}`);
|
|
});
|
|
|
|
if (message.content.trim() === `<@${botId}>` || message.content.trim() === `<@!${botId}>`) {
|
|
message.send({
|
|
embeds: [{
|
|
title: `Hello ${message.member?.username}, and thanks for using Group Up!`,
|
|
fields: [
|
|
{
|
|
name: `My prefix in this guild is: \`${prefix}\``,
|
|
value: 'Mention me with a new prefix to change it.',
|
|
},
|
|
],
|
|
}],
|
|
}).catch((e) => {
|
|
log(LT.WARN, `Failed to send message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
} else if (await hasGuildPermissions(message.guildId, message.authorId, ['ADMINISTRATOR'])) {
|
|
const newPrefix = message.content.replace(`<@!${botId}>`, '').replace(`<@${botId}>`, '').trim();
|
|
|
|
if (newPrefix.length <= 10) {
|
|
let success = true;
|
|
if (guildPrefixes.has(message.guildId)) {
|
|
// Execute the DB update
|
|
await dbClient.execute('UPDATE guild_prefix SET prefix = ? WHERE guildId = ?', [newPrefix, message.guildId]).catch((e) => {
|
|
log(LT.ERROR, `Failed to insert into database: ${jsonStringifyBig(e)}`);
|
|
success = false;
|
|
});
|
|
} else {
|
|
// Execute the DB insertion
|
|
await dbClient.execute('INSERT INTO guild_prefix(guildId,prefix) values(?,?)', [message.guildId, newPrefix]).catch((e) => {
|
|
log(LT.ERROR, `Failed to insert into database: ${jsonStringifyBig(e)}`);
|
|
success = false;
|
|
});
|
|
}
|
|
|
|
if (success) {
|
|
guildPrefixes.set(message.guildId, newPrefix);
|
|
message.send({
|
|
embeds: [{
|
|
fields: [
|
|
{
|
|
name: `My prefix in this guild is now: \`${newPrefix}\``,
|
|
value: 'Mention me with a new prefix to change it.',
|
|
},
|
|
],
|
|
}],
|
|
}).catch((e) => {
|
|
log(LT.WARN, `Failed to send message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
} else {
|
|
message.send({
|
|
embeds: [{
|
|
fields: [
|
|
{
|
|
name: 'Something went wrong!',
|
|
value: `My prefix is still \`${prefix}\`. Please try again, and if the problem persists, please report this to the developers using \`${prefix}report\`.`,
|
|
},
|
|
],
|
|
}],
|
|
}).catch((e) => {
|
|
log(LT.WARN, `Failed to send message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
}
|
|
} else {
|
|
message.send({
|
|
embeds: [{
|
|
fields: [
|
|
{
|
|
name: 'Prefix too long, please set a prefix less than 10 characters long.',
|
|
value: 'Mention me with a new prefix to change it.',
|
|
},
|
|
],
|
|
}],
|
|
}).catch((e) => {
|
|
log(LT.WARN, `Failed to send message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Other
|
|
const activeIdx = activeBuilders.findIndex((x) => (message.channelId === x.channelId && message.authorId === x.userId));
|
|
if (activeIdx > -1) {
|
|
activeBuilders[activeIdx].lastTouch = new Date();
|
|
activeBuilders[activeIdx] = await handleLFGStep(activeBuilders[activeIdx], message.content);
|
|
|
|
if (activeBuilders[activeIdx].step === 'done') {
|
|
if (message.member) {
|
|
const memberJoined = handleMemberJoin(activeBuilders[activeIdx].lfgMsg.embeds[0].fields || [], message.member, false);
|
|
|
|
const newTimestamp = new Date(parseInt(memberJoined.embed[1].value.split('#')[1]));
|
|
const newLfgUid = ALPHABET[Math.floor(Math.random() * 26)] + ALPHABET[Math.floor(Math.random() * 26)];
|
|
|
|
const tempMembers = memberJoined.embed[4].name.split(':')[1].split('/');
|
|
const currentMembers = parseInt(tempMembers[0]);
|
|
const maxMembers = parseInt(tempMembers[1]);
|
|
|
|
if (activeBuilders[activeIdx].editing) {
|
|
if (currentMembers > maxMembers) {
|
|
const currentPeople = memberJoined.embed[4].value.split('\n');
|
|
const newAlts = currentPeople.splice(maxMembers);
|
|
memberJoined.embed[4].value = currentPeople.join('\n') || 'None';
|
|
memberJoined.embed[5].value = `${newAlts.join('\n')}\n${memberJoined.embed[5].value === 'None' ? '' : memberJoined.embed[5].value}`;
|
|
memberJoined.embed[4].name = `Members Joined: ${maxMembers}/${maxMembers}`;
|
|
}
|
|
}
|
|
|
|
await activeBuilders[activeIdx].lfgMsg.edit({
|
|
content: '',
|
|
embeds: [{
|
|
fields: memberJoined.embed,
|
|
footer: {
|
|
text: `Created by: ${message.member.username} | ${newLfgUid}`,
|
|
},
|
|
timestamp: newTimestamp.toISOString(),
|
|
}],
|
|
components: [
|
|
{
|
|
type: 1,
|
|
components: [
|
|
{
|
|
type: 2,
|
|
label: 'Join',
|
|
customId: 'active@join_group',
|
|
style: DiscordButtonStyles.Success,
|
|
},
|
|
{
|
|
type: 2,
|
|
label: 'Leave',
|
|
customId: 'active@leave_group',
|
|
style: DiscordButtonStyles.Danger,
|
|
},
|
|
{
|
|
type: 2,
|
|
label: 'Join as Alternate',
|
|
customId: 'active@alternate_group',
|
|
style: DiscordButtonStyles.Primary,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
}).catch((e) => {
|
|
log(LT.WARN, `Failed to edit message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
|
|
if (activeBuilders[activeIdx]) {
|
|
const activeLFGIdx = activeLFGPosts.findIndex(
|
|
(lfg) => (lfg.channelId === activeBuilders[activeIdx].channelId && lfg.messageId === activeBuilders[activeIdx].lfgMsg.id && lfg.ownerId === activeBuilders[activeIdx].userId),
|
|
);
|
|
if (activeLFGIdx >= 0) {
|
|
activeLFGPosts[activeLFGIdx].lfgUid = newLfgUid;
|
|
activeLFGPosts[activeLFGIdx].lfgTime = newTimestamp.getTime();
|
|
activeLFGPosts[activeLFGIdx].notified = false;
|
|
activeLFGPosts[activeLFGIdx].locked = false;
|
|
} else {
|
|
activeLFGPosts.push({
|
|
messageId: activeBuilders[activeIdx].lfgMsg.id,
|
|
channelId: activeBuilders[activeIdx].lfgMsg.channelId,
|
|
ownerId: message.authorId,
|
|
lfgUid: newLfgUid,
|
|
lfgTime: newTimestamp.getTime(),
|
|
notified: false,
|
|
locked: false,
|
|
});
|
|
}
|
|
localStorage.setItem('activeLFGPosts', jsonStringifyBig(activeLFGPosts));
|
|
}
|
|
}
|
|
|
|
await activeBuilders[activeIdx].questionMsg.delete().catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
activeBuilders.splice(activeIdx, 1);
|
|
}
|
|
await message.delete().catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
return;
|
|
}
|
|
|
|
// Should this get cleaned up?
|
|
const enabledCleanChannels = cleanChannels.get(message.guildId);
|
|
if (enabledCleanChannels && enabledCleanChannels.length && enabledCleanChannels.indexOf(message.channelId) > -1) {
|
|
message.delete('Cleaning Channel').catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
return;
|
|
}
|
|
return;
|
|
} else {
|
|
// User is sending a command, make sure its a lfg command if its being sent in a clean channel
|
|
const enabledCleanChannels = cleanChannels.get(message.guildId);
|
|
if (enabledCleanChannels && enabledCleanChannels.length && enabledCleanChannels.indexOf(message.channelId) > -1 && message.content.indexOf(`${prefix}lfg`) !== 0) {
|
|
message.delete('Cleaning Channel').catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
|
|
log(LT.LOG, `Handling message ${jsonStringifyBig(message)}`);
|
|
|
|
// Split into standard command + args format
|
|
const args = message.content.slice(prefix.length).trim().split(/[ \n]+/g);
|
|
const command = args.shift()?.toLowerCase();
|
|
|
|
// All commands below here
|
|
|
|
if (command === 'lfg') {
|
|
// Light telemetry to see how many times a command is being run
|
|
dbClient.execute(`CALL INC_CNT("lfg");`).catch((e) => {
|
|
log(LT.ERROR, `Failed to call stored procedure INC_CNT: ${jsonStringifyBig(e)}`);
|
|
});
|
|
|
|
const subcmd = (args[0] || 'help').toLowerCase();
|
|
const lfgUid = (args[1] || '').toUpperCase();
|
|
|
|
// Learn how the LFG command works
|
|
if (subcmd === 'help' || subcmd === 'h' || subcmd === '?') {
|
|
message.send(constantCmds.lfgHelp).catch((e) => {
|
|
log(LT.ERROR, `Failed to send message: ${jsonStringifyBig(message)} | ${jsonStringifyBig(e)}`);
|
|
});
|
|
} // Create a new LFG
|
|
else if (subcmd === 'create' || subcmd === 'c') {
|
|
try {
|
|
const lfgMsg = await message.send(`Creating new LFG post for <@${message.authorId}>. Please reply with the requested information and watch as your LFG post gets created!`);
|
|
|
|
const gameButtons: Array<ButtonComponent> = Object.keys(LFGActivities).map((game) => {
|
|
return {
|
|
type: 2,
|
|
label: game,
|
|
customId: `building@set_game#${game}`,
|
|
style: DiscordButtonStyles.Primary,
|
|
};
|
|
});
|
|
|
|
const buttonComps: Array<ActionRow> = [];
|
|
|
|
const temp: Array<ActionRow['components']> = [];
|
|
|
|
gameButtons.forEach((btn, idx) => {
|
|
if (!temp[Math.floor(idx / 5)]) {
|
|
temp[Math.floor(idx / 5)] = [btn];
|
|
} else {
|
|
temp[Math.floor(idx / 5)].push(btn);
|
|
}
|
|
});
|
|
|
|
temp.forEach((btns) => {
|
|
if (btns.length && btns.length <= 5) {
|
|
buttonComps.push({
|
|
type: 1,
|
|
components: btns,
|
|
});
|
|
}
|
|
});
|
|
|
|
const question = await message.send({
|
|
content: lfgStepQuestions.set_game,
|
|
components: buttonComps,
|
|
});
|
|
|
|
activeBuilders.push({
|
|
userId: message.authorId,
|
|
channelId: message.channelId,
|
|
step: 'set_game',
|
|
lfgMsg: lfgMsg,
|
|
questionMsg: question,
|
|
lastTouch: new Date(),
|
|
maxIdle: 60,
|
|
editing: false,
|
|
});
|
|
|
|
message.delete().catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
} catch (e) {
|
|
log(LT.WARN, `LFG failed at step | create | ${jsonStringifyBig(e)}`);
|
|
}
|
|
} // Delete an existing LFG
|
|
else if (subcmd === 'delete' || subcmd === 'd') {
|
|
try {
|
|
// User provided a Uid, use it
|
|
if (lfgUid) {
|
|
const matches = activeLFGPosts.filter((lfg) => (message.authorId === lfg.ownerId && message.channelId === lfg.channelId && lfgUid === lfg.lfgUid));
|
|
|
|
// Found one, delete
|
|
if (matches.length) {
|
|
await deleteMessage(matches[0].channelId, matches[0].messageId, 'User requested LFG to be deleted.').catch((e) => {
|
|
log(LT.WARN, `Failed to find message to delete | ${jsonStringifyBig(e)}`);
|
|
});
|
|
const lfgIdx = activeLFGPosts.findIndex((lfg) => (message.authorId === lfg.ownerId && message.channelId === lfg.channelId && lfgUid === lfg.lfgUid));
|
|
|
|
activeLFGPosts.splice(lfgIdx, 1);
|
|
|
|
localStorage.setItem('activeLFGPosts', jsonStringifyBig(activeLFGPosts));
|
|
|
|
const m = await message.send(constantCmds.lfgDelete3);
|
|
|
|
m.delete('Channel Cleanup', 5000).catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
message.delete('Channel Cleanup', 5000).catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
} // Did not find one
|
|
else {
|
|
const m = await message.send(constantCmds.lfgDelete1);
|
|
|
|
m.delete('Channel Cleanup', 5000).catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
message.delete('Channel Cleanup', 5000).catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
}
|
|
} // User did not provide a Uid, find it automatically
|
|
else {
|
|
const matches = activeLFGPosts.filter((lfg) => (message.authorId === lfg.ownerId && message.channelId === lfg.channelId));
|
|
|
|
// Found one, delete
|
|
if (matches.length === 1) {
|
|
await deleteMessage(matches[0].channelId, matches[0].messageId, 'User requested LFG to be deleted.').catch((e) => {
|
|
log(LT.WARN, `Failed to find message to delete | ${jsonStringifyBig(e)}`);
|
|
});
|
|
const lfgIdx = activeLFGPosts.findIndex((lfg) => (message.authorId === lfg.ownerId && message.channelId === lfg.channelId));
|
|
|
|
activeLFGPosts.splice(lfgIdx, 1);
|
|
|
|
localStorage.setItem('activeLFGPosts', jsonStringifyBig(activeLFGPosts));
|
|
|
|
const m = await message.send(constantCmds.lfgDelete3);
|
|
|
|
m.delete('Channel Cleanup', 5000).catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
message.delete('Channel Cleanup', 5000).catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
} // Found multiple, notify user
|
|
else if (matches.length) {
|
|
const deleteMsg = constantCmds.lfgDelete2;
|
|
const deepCloningFailedSoThisIsTheSolution = constantCmds.lfgDelete2.embeds[0].fields[0].value;
|
|
matches.forEach((mt) => {
|
|
deleteMsg.embeds[0].fields[0].value += `[${mt.lfgUid}](https://discord.com/channels/${message.guildId}/${mt.channelId}/${mt.messageId})\n`;
|
|
});
|
|
|
|
deleteMsg.embeds[0].fields[0].value += '\nThis message will self descruct in 30 seconds.';
|
|
|
|
const m = await message.send(deleteMsg);
|
|
constantCmds.lfgDelete2.embeds[0].fields[0].value = deepCloningFailedSoThisIsTheSolution;
|
|
|
|
m.delete('Channel Cleanup', 30000).catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
message.delete('Channel Cleanup', 30000).catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
} // Found none, notify user you cannot delete other's lfgs
|
|
else {
|
|
const m = await message.send(constantCmds.lfgDelete1);
|
|
|
|
m.delete('Channel Cleanup', 5000).catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
message.delete('Channel Cleanup', 5000).catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
}
|
|
}
|
|
} catch (e) {
|
|
log(LT.WARN, `LFG failed at step | delete | ${jsonStringifyBig(e)}`);
|
|
}
|
|
} // Edit an existing LFG
|
|
else if (subcmd === 'edit' || subcmd === 'e') {
|
|
try {
|
|
// User provided a Uid, use it
|
|
if (lfgUid) {
|
|
const matches = activeLFGPosts.filter((lfg) => (message.authorId === lfg.ownerId && message.channelId === lfg.channelId && lfgUid === lfg.lfgUid));
|
|
|
|
// Found one, edit
|
|
if (matches.length) {
|
|
const lfgMessage = await (await getMessage(matches[0].channelId, matches[0].messageId)).edit({
|
|
content: `Editing new LFG post for <@${matches[0].ownerId}>. Please reply with the requested information and watch as your LFG post gets edited!`,
|
|
});
|
|
const question = await message.send({
|
|
content: 'Please select an item to edit from the buttons below:',
|
|
components: [{
|
|
type: 1,
|
|
components: editBtns,
|
|
}],
|
|
});
|
|
|
|
activeBuilders.push({
|
|
userId: matches[0].ownerId,
|
|
channelId: matches[0].channelId,
|
|
step: 'edit_btn',
|
|
lfgMsg: lfgMessage,
|
|
questionMsg: question,
|
|
lastTouch: new Date(),
|
|
maxIdle: 60,
|
|
editing: true,
|
|
});
|
|
|
|
message.delete().catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
} // Did not find one
|
|
else {
|
|
const m = await message.send(constantCmds.lfgEdit1);
|
|
|
|
m.delete('Channel Cleanup', 5000).catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
message.delete('Channel Cleanup', 5000).catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
}
|
|
} // User did not provide a Uid, find it automatically
|
|
else {
|
|
const matches = activeLFGPosts.filter((lfg) => (message.authorId === lfg.ownerId && message.channelId === lfg.channelId));
|
|
|
|
// Found one, edit
|
|
if (matches.length === 1) {
|
|
const lfgMessage = await (await getMessage(matches[0].channelId, matches[0].messageId)).edit({
|
|
content: `Editing new LFG post for <@${matches[0].ownerId}>. Please reply with the requested information and watch as your LFG post gets edited!`,
|
|
});
|
|
const question = await message.send({
|
|
content: 'Please select an item to edit from the buttons below:',
|
|
components: [{
|
|
type: 1,
|
|
components: editBtns,
|
|
}],
|
|
});
|
|
|
|
activeBuilders.push({
|
|
userId: matches[0].ownerId,
|
|
channelId: matches[0].channelId,
|
|
step: 'edit_btn',
|
|
lfgMsg: lfgMessage,
|
|
questionMsg: question,
|
|
lastTouch: new Date(),
|
|
maxIdle: 60,
|
|
editing: true,
|
|
});
|
|
|
|
message.delete().catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
} // Found multiple, notify user
|
|
else if (matches.length) {
|
|
const deleteMsg = constantCmds.lfgEdit2;
|
|
const deepCloningFailedSoThisIsTheSolution = constantCmds.lfgEdit2.embeds[0].fields[0].value;
|
|
matches.forEach((mt) => {
|
|
deleteMsg.embeds[0].fields[0].value += `[${mt.lfgUid}](https://discord.com/channels/${message.guildId}/${mt.channelId}/${mt.messageId})\n`;
|
|
});
|
|
|
|
deleteMsg.embeds[0].fields[0].value += '\nThis message will self descruct in 30 seconds.';
|
|
|
|
const m = await message.send(deleteMsg);
|
|
constantCmds.lfgEdit2.embeds[0].fields[0].value = deepCloningFailedSoThisIsTheSolution;
|
|
|
|
m.delete('Channel Cleanup', 30000).catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
message.delete('Channel Cleanup', 30000).catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
} // Found none, notify user you cannot edit other's lfgs
|
|
else {
|
|
const m = await message.send(constantCmds.lfgEdit1);
|
|
|
|
m.delete('Channel Cleanup', 5000).catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
message.delete('Channel Cleanup', 5000).catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
}
|
|
}
|
|
} catch (e) {
|
|
log(LT.WARN, `LFG failed at step | edit | ${jsonStringifyBig(e)}`);
|
|
}
|
|
} // Join a LFG on behalf of a user
|
|
// gu!lfg join [url] [join/leave/alternate] [member?]
|
|
else if (subcmd === 'join' || subcmd === 'leave' || subcmd === 'alternate') {
|
|
try {
|
|
const action = subcmd;
|
|
const lfgIds = urlToIds(args[1] || '');
|
|
const memberStr = args[2] || `<@${message.authorId}>`;
|
|
const member = await message.guild?.members.get(BigInt(memberStr.substr(3, memberStr.length - 4)));
|
|
|
|
const modRole = guildModRoles.get(message.guildId) || 0n;
|
|
|
|
// Join yourself (or others if you are a guild mod) to an LFG
|
|
if (lfgIds.guildId === message.guildId && member && (member.id === message.authorId || message.guildMember?.roles.includes(modRole))) {
|
|
const lfgMessage = await getMessage(lfgIds.channelId, lfgIds.messageId);
|
|
|
|
const embeds = lfgMessage.embeds[0].fields || [];
|
|
let results: JoinLeaveType = {
|
|
embed: [],
|
|
success: false,
|
|
full: true,
|
|
justFilled: false,
|
|
};
|
|
let actionResp: string;
|
|
switch (action) {
|
|
case 'join':
|
|
results = handleMemberJoin(embeds, member, false);
|
|
actionResp = 'joined';
|
|
break;
|
|
case 'leave':
|
|
results = handleMemberLeave(embeds, member);
|
|
actionResp = 'left';
|
|
break;
|
|
case 'alternate':
|
|
results = handleMemberJoin(embeds, member, true);
|
|
actionResp = 'joined as alternate';
|
|
break;
|
|
}
|
|
|
|
let resp: string;
|
|
if (results.success && lfgMessage.components) {
|
|
const buttonRow: ActionRow = lfgMessage.components[0] as ActionRow;
|
|
|
|
await lfgMessage.edit({
|
|
embeds: [{
|
|
fields: results.embed,
|
|
footer: lfgMessage.embeds[0].footer,
|
|
timestamp: lfgMessage.embeds[0].timestamp,
|
|
}],
|
|
components: [buttonRow],
|
|
});
|
|
|
|
if (results.justFilled) {
|
|
const thisLFGPost = activeLFGPosts.filter((lfg) => (lfgMessage.id === lfg.messageId && lfgMessage.channelId === lfg.channelId))[0];
|
|
const thisLFG = (await getMessage(thisLFGPost.channelId, thisLFGPost.messageId)).embeds[0].fields || [];
|
|
sendDirectMessage(thisLFGPost.ownerId, {
|
|
embeds: [{
|
|
title: `Hello ${(await getUser(thisLFGPost.ownerId)).username}! Your event in ${
|
|
lfgMessage.guild?.name || (await getGuild(message.guildId, { counts: false, addToCache: false })).name
|
|
} has filled up!`,
|
|
fields: [
|
|
thisLFG[0],
|
|
{
|
|
name: 'Your members are:',
|
|
value: thisLFG[4].value,
|
|
},
|
|
],
|
|
}],
|
|
});
|
|
}
|
|
|
|
resp = `Successfully ${actionResp} LFG.`;
|
|
} else {
|
|
resp = `Failed to ${action} LFG.`;
|
|
}
|
|
|
|
const m = await message.send({
|
|
embeds: [{
|
|
title: resp,
|
|
}],
|
|
});
|
|
|
|
m.delete('Channel Cleanup', 5000).catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
message.delete('Channel Cleanup', 5000).catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
}
|
|
} catch (e) {
|
|
log(LT.WARN, `Member Join/Leave/Alt command failed: ${jsonStringifyBig(message)} | ${jsonStringifyBig(e)}`);
|
|
|
|
const m = await message.send({
|
|
embeds: [{
|
|
title: 'Failed to find LFG.',
|
|
}],
|
|
});
|
|
|
|
m.delete('Channel Cleanup').catch((e) => {
|
|
log(LT.WARN, `Failed to clean up joiner | joining on behalf | ${jsonStringifyBig(e)}`);
|
|
});
|
|
message.delete('Channel Cleanup', 5000).catch((e) => {
|
|
log(LT.WARN, `Failed to clean up joiner | joining on behalf | ${jsonStringifyBig(e)}`);
|
|
});
|
|
}
|
|
} // Sets the mod role
|
|
else if (subcmd === 'set_mod_role' && (await hasGuildPermissions(message.guildId, message.authorId, ['ADMINISTRATOR']))) {
|
|
const mentionedRole = args[1] || '';
|
|
const roleId = BigInt(mentionedRole.substr(3, mentionedRole.length - 4));
|
|
if (message.guild?.roles.has(roleId)) {
|
|
let success = true;
|
|
if (guildModRoles.has(message.guildId)) {
|
|
// Execute the DB update
|
|
await dbClient.execute('UPDATE guild_mod_role SET roleId = ? WHERE guildId = ?', [roleId, message.guildId]).catch((e) => {
|
|
log(LT.ERROR, `Failed to insert into database: ${jsonStringifyBig(e)}`);
|
|
success = false;
|
|
});
|
|
} else {
|
|
// Execute the DB insertion
|
|
await dbClient.execute('INSERT INTO guild_mod_role(guildId,roleId) values(?,?)', [message.guildId, roleId]).catch((e) => {
|
|
log(LT.ERROR, `Failed to insert into database: ${jsonStringifyBig(e)}`);
|
|
success = false;
|
|
});
|
|
}
|
|
|
|
if (success) {
|
|
guildModRoles.set(message.guildId, roleId);
|
|
message.send({
|
|
embeds: [{
|
|
fields: [
|
|
{
|
|
name: 'LFG Mod Role set successfully',
|
|
value: `LFG Mod Role set to ${args[1]}.`,
|
|
},
|
|
],
|
|
}],
|
|
}).catch((e) => {
|
|
log(LT.WARN, `Failed to send message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
} else {
|
|
message.send({
|
|
embeds: [{
|
|
fields: [
|
|
{
|
|
name: 'Something went wrong!',
|
|
value: 'LFG Mod Role has been left unchanged.',
|
|
},
|
|
],
|
|
}],
|
|
}).catch((e) => {
|
|
log(LT.WARN, `Failed to send message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
}
|
|
} else {
|
|
if (guildModRoles.has(message.guildId)) {
|
|
message.send({
|
|
embeds: [{
|
|
fields: [
|
|
{
|
|
name: 'LFG Mod Role is currently set to:',
|
|
value: `<@&${guildModRoles.get(message.guildId)}>`,
|
|
},
|
|
],
|
|
}],
|
|
}).catch((e) => {
|
|
log(LT.WARN, `Failed to send message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
} else {
|
|
message.send({
|
|
embeds: [{
|
|
fields: [
|
|
{
|
|
name: 'There is no LFG Mod Role set for this guild.',
|
|
value: `To set one, run this command again with the role mentioned.\n\nExample: \`${prefix}lfg set_mod_role @newModRole\``,
|
|
},
|
|
],
|
|
}],
|
|
}).catch((e) => {
|
|
log(LT.WARN, `Failed to send message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
}
|
|
}
|
|
} // Sets the channel cleaning up for LFG channels to keep LFG events visible and prevent conversations
|
|
else if (subcmd === 'set_clean_channel' && (await hasGuildPermissions(message.guildId, message.authorId, ['ADMINISTRATOR']))) {
|
|
const cleanSetting = (args[1] || 'list').toLowerCase();
|
|
let success = true;
|
|
if (cleanSetting === 'on') {
|
|
// Execute the DB insertion
|
|
await dbClient.execute('INSERT INTO guild_clean_channel(guildId,channelId) values(?,?)', [message.guildId, message.channelId]).catch((e) => {
|
|
log(LT.ERROR, `Failed to insert into database: ${jsonStringifyBig(e)}`);
|
|
success = false;
|
|
});
|
|
|
|
if (success) {
|
|
const tempArr = cleanChannels.get(message.guildId) || [];
|
|
tempArr.push(message.channelId);
|
|
cleanChannels.set(message.guildId, tempArr);
|
|
|
|
const m = await message.send({
|
|
embeds: [{
|
|
fields: [
|
|
{
|
|
name: 'Channel Cleaning turned ON.',
|
|
value: 'This message will self destruct in 5 seconds.',
|
|
},
|
|
],
|
|
}],
|
|
}).catch((e) => {
|
|
log(LT.WARN, `Failed to send message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
|
|
m && m.delete('Channel Cleanup', 5000).catch((e) => {
|
|
log(LT.WARN, `Failed to clean up | set_clean_channel | ${jsonStringifyBig(e)}`);
|
|
});
|
|
message.delete('Channel Cleanup', 5000).catch((e) => {
|
|
log(LT.WARN, `Failed to clean up | set_clean_channel | ${jsonStringifyBig(e)}`);
|
|
});
|
|
} else {
|
|
message.send({
|
|
embeds: [{
|
|
fields: [
|
|
{
|
|
name: 'Something went wrong!',
|
|
value: 'Channel Clean status left off.',
|
|
},
|
|
],
|
|
}],
|
|
}).catch((e) => {
|
|
log(LT.WARN, `Failed to send message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
}
|
|
} else if (cleanSetting === 'off') {
|
|
// turns clean off for channel
|
|
// Execute the DB insertion
|
|
await dbClient.execute('DELETE FROM guild_clean_channel WHERE guildId = ? AND channelId = ?', [message.guildId, message.channelId]).catch((e) => {
|
|
log(LT.ERROR, `Failed to delete from database: ${jsonStringifyBig(e)}`);
|
|
success = false;
|
|
});
|
|
|
|
if (success) {
|
|
let tempArr = cleanChannels.get(message.guildId) || [];
|
|
tempArr = tempArr.filter((channelId) => channelId !== message.channelId);
|
|
cleanChannels.set(message.guildId, tempArr);
|
|
|
|
const m = await message.send({
|
|
embeds: [{
|
|
fields: [
|
|
{
|
|
name: 'Channel Cleaning turned OFF.',
|
|
value: 'This message will self destruct in 5 seconds.',
|
|
},
|
|
],
|
|
}],
|
|
}).catch((e) => {
|
|
log(LT.WARN, `Failed to send message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
|
|
m && m.delete('Channel Cleanup', 5000).catch((e) => {
|
|
log(LT.WARN, `Failed to clean up | set_clean_channel | ${jsonStringifyBig(e)}`);
|
|
});
|
|
message.delete('Channel Cleanup', 5000).catch((e) => {
|
|
log(LT.WARN, `Failed to clean up | set_clean_channel | ${jsonStringifyBig(e)}`);
|
|
});
|
|
} else {
|
|
message.send({
|
|
embeds: [{
|
|
fields: [
|
|
{
|
|
name: 'Something went wrong!',
|
|
value: 'Channel Clean status left on.',
|
|
},
|
|
],
|
|
}],
|
|
}).catch((e) => {
|
|
log(LT.WARN, `Failed to send message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
}
|
|
} else if (cleanSetting === 'list') {
|
|
// send list of channels with clean on
|
|
let cleanChannelStr = '';
|
|
|
|
for (const channelId of cleanChannels.get(message.guildId) || []) {
|
|
cleanChannelStr += `<#${channelId}>\n`;
|
|
}
|
|
cleanChannelStr = cleanChannelStr.substr(0, cleanChannelStr.length - 1);
|
|
|
|
const tmpEmbed: Embed = {};
|
|
|
|
if (cleanChannelStr) {
|
|
tmpEmbed.fields = [
|
|
{
|
|
name: 'Clean Channels enabled for this guild:',
|
|
value: cleanChannelStr,
|
|
},
|
|
];
|
|
} else {
|
|
tmpEmbed.title = 'No Clean Channels are enabled for this guild.';
|
|
}
|
|
|
|
await message.send({
|
|
embeds: [tmpEmbed],
|
|
}).catch((e) => {
|
|
log(LT.WARN, `Failed to send message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
},
|
|
interactionCreate: async (interact, member) => {
|
|
try {
|
|
if (interact.type === DiscordInteractionTypes.MessageComponent) {
|
|
if (interact.message && interact.data && (interact.data as ButtonData).customId && member) {
|
|
log(LT.INFO, `Handling Button ${(interact.data as ButtonData).customId}`);
|
|
log(LT.LOG, `Button Data | ${jsonStringifyBig(interact)}`);
|
|
|
|
sendInteractionResponse(BigInt(interact.id), interact.token, {
|
|
type: DiscordInteractionResponseTypes.DeferredUpdateMessage,
|
|
});
|
|
|
|
const [handler, stepInfo] = (interact.data as ButtonData).customId.split('@');
|
|
const [action, value] = stepInfo.split('#');
|
|
switch (handler) {
|
|
case 'building': {
|
|
await activeBuilders.some(async (x, i) => {
|
|
if (x.channelId === BigInt(interact.channelId || '0') && member && x.userId === BigInt(member.id)) {
|
|
x.lastTouch = new Date();
|
|
x = await handleLFGStep(x, value);
|
|
|
|
if (x.step === 'done' && x.lfgMsg.components) {
|
|
const currentLFG = (x.lfgMsg.embeds[0].fields || []);
|
|
const newTimestamp = new Date(parseInt(currentLFG[1].value.split('#')[1]));
|
|
const newLfgUid = ALPHABET[Math.floor(Math.random() * 26)] + ALPHABET[Math.floor(Math.random() * 26)];
|
|
|
|
const tempMembers = currentLFG[4].name.split(':')[1].split('/');
|
|
const currentMembers = parseInt(tempMembers[0]);
|
|
const maxMembers = parseInt(tempMembers[1]);
|
|
|
|
const buttonRow: ActionRow = x.lfgMsg.components[0] as ActionRow;
|
|
|
|
if (currentMembers > maxMembers) {
|
|
const currentPeople = currentLFG[4].value.split('\n');
|
|
const newAlts = currentPeople.splice(maxMembers - 1);
|
|
currentLFG[4].value = currentPeople.join('\n');
|
|
currentLFG[5].value = `${newAlts.join('\n')}\n${currentLFG[5].value}`;
|
|
currentLFG[4].name = `Members Joined: ${maxMembers}/${maxMembers}`;
|
|
}
|
|
|
|
await x.lfgMsg.edit({
|
|
content: '',
|
|
embeds: [{
|
|
fields: currentLFG,
|
|
footer: {
|
|
text: `Created by: ${member.username} | ${newLfgUid}`,
|
|
},
|
|
timestamp: newTimestamp.toISOString(),
|
|
}],
|
|
components: [buttonRow],
|
|
});
|
|
|
|
const activeIdx = activeLFGPosts.findIndex((lfg) => (lfg.channelId === x.channelId && lfg.messageId === x.lfgMsg.id && lfg.ownerId === x.userId));
|
|
activeLFGPosts[activeIdx].lfgTime = newTimestamp.getTime();
|
|
activeLFGPosts[activeIdx].lfgUid = newLfgUid;
|
|
localStorage.setItem('activeLFGPosts', jsonStringifyBig(activeLFGPosts));
|
|
|
|
await activeBuilders[i].questionMsg.delete().catch((e) => {
|
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
|
});
|
|
activeBuilders.splice(i, 1);
|
|
} else {
|
|
activeBuilders[i] = x;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
});
|
|
break;
|
|
}
|
|
case 'active': {
|
|
const message = await getMessage(BigInt(interact.channelId || '0'), BigInt(interact.message.id));
|
|
|
|
const embeds = message.embeds[0].fields || [];
|
|
let results: JoinLeaveType = {
|
|
embed: [],
|
|
success: false,
|
|
full: true,
|
|
justFilled: false,
|
|
};
|
|
switch (action) {
|
|
case 'join_group':
|
|
results = handleMemberJoin(embeds, member, false);
|
|
break;
|
|
case 'leave_group':
|
|
results = handleMemberLeave(embeds, member);
|
|
break;
|
|
case 'alternate_group':
|
|
results = handleMemberJoin(embeds, member, true);
|
|
break;
|
|
}
|
|
|
|
if (results.success && message.components) {
|
|
await message.edit({
|
|
embeds: [{
|
|
fields: results.embed,
|
|
footer: message.embeds[0].footer,
|
|
timestamp: message.embeds[0].timestamp,
|
|
}],
|
|
});
|
|
|
|
if (results.justFilled) {
|
|
const thisLFGPost = activeLFGPosts.filter((lfg) => (message.id === lfg.messageId && message.channelId === lfg.channelId))[0];
|
|
const thisLFG = (await getMessage(thisLFGPost.channelId, thisLFGPost.messageId)).embeds[0].fields || [];
|
|
sendDirectMessage(thisLFGPost.ownerId, {
|
|
embeds: [{
|
|
title: `Hello ${(await getUser(thisLFGPost.ownerId)).username}! Your event in ${
|
|
message.guild?.name || (await getGuild(message.guildId, { counts: false, addToCache: false })).name
|
|
} has filled up!`,
|
|
fields: [
|
|
thisLFG[0],
|
|
{
|
|
name: 'Your members are:',
|
|
value: thisLFG[4].value,
|
|
},
|
|
],
|
|
}],
|
|
});
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case 'editing': {
|
|
await activeBuilders.some(async (x, i) => {
|
|
if (x.editing && x.channelId === BigInt(interact.channelId || '0') && member && x.userId === BigInt(member.id)) {
|
|
x.step = action;
|
|
x.lastTouch = new Date();
|
|
let nextQuestion = '';
|
|
const nextComponents: Array<ActionRow> = [];
|
|
switch (action) {
|
|
case 'set_game': {
|
|
nextQuestion = lfgStepQuestions.set_game;
|
|
|
|
const gameButtons: Array<ButtonComponent> = Object.keys(LFGActivities).map((game) => {
|
|
return {
|
|
type: 2,
|
|
label: game,
|
|
customId: `building@set_game#${game}`,
|
|
style: DiscordButtonStyles.Primary,
|
|
};
|
|
});
|
|
|
|
const temp: Array<ActionRow['components']> = [];
|
|
|
|
gameButtons.forEach((btn, idx) => {
|
|
if (!temp[Math.floor(idx / 5)]) {
|
|
temp[Math.floor(idx / 5)] = [btn];
|
|
} else {
|
|
temp[Math.floor(idx / 5)].push(btn);
|
|
}
|
|
});
|
|
|
|
temp.forEach((btns) => {
|
|
if (btns.length && btns.length <= 5) {
|
|
nextComponents.push({
|
|
type: 1,
|
|
components: btns,
|
|
});
|
|
}
|
|
});
|
|
break;
|
|
}
|
|
case 'set_time': {
|
|
nextQuestion = 'Please enter the time of the activity:';
|
|
break;
|
|
}
|
|
case 'set_desc': {
|
|
nextQuestion = 'Please enter a description for the activity. Enter `none` to skip:';
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
x.questionMsg = await x.questionMsg.edit({
|
|
content: nextQuestion,
|
|
components: nextComponents,
|
|
});
|
|
|
|
activeBuilders[i] = x;
|
|
|
|
return true;
|
|
}
|
|
});
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
log(LT.ERROR, `Interaction failed: ${jsonStringifyBig(interact)} | ${jsonStringifyBig(member)} | ${jsonStringifyBig(e)}`);
|
|
}
|
|
},
|
|
},
|
|
});
|