Group Up V0.4.0
Lotta changes, compiled from months ago. In short: 2 new tables for handling new features Now runs latest DD on latest Deno Auto-clean Alternate=>Joined auto-promote Join on behalf of someone else bugfixes!
This commit is contained in:
parent
c0d9abbe70
commit
f244c1891e
|
@ -1,2 +1,4 @@
|
||||||
config.ts
|
config.ts
|
||||||
logs
|
logs
|
||||||
|
|
||||||
|
db/update.ts
|
||||||
|
|
|
@ -8,5 +8,8 @@
|
||||||
"spellright.language": [
|
"spellright.language": [
|
||||||
"en"
|
"en"
|
||||||
],
|
],
|
||||||
"spellright.documentTypes": []
|
"spellright.documentTypes": [],
|
||||||
|
"deno.suggest.imports.hosts": {
|
||||||
|
"https://deno.land": true
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
export const config = {
|
export const config = {
|
||||||
"name": "Group Up", // Name of the bot
|
"name": "Group Up", // Name of the bot
|
||||||
"version": "0.2.3", // Version of the bot
|
"version": "0.3.2", // Version of the bot
|
||||||
"token": "the_bot_token", // Discord API Token for this bot
|
"token": "the_bot_token", // Discord API Token for this bot
|
||||||
"localtoken": "local_testing_token", // Discord API Token for a secondary OPTIONAL testing bot, THIS MUST BE DIFFERENT FROM "token"
|
"localtoken": "local_testing_token", // Discord API Token for a secondary OPTIONAL testing bot, THIS MUST BE DIFFERENT FROM "token"
|
||||||
"prefix": "[[", // Prefix for all commands
|
"prefix": "gu!", // Prefix for all commands
|
||||||
"db": { // Settings for the MySQL database, this is required for use with the API, if you do not want to set this up, you will need to rip all code relating to the DB out of the bot
|
"db": { // Settings for the MySQL database, this is required for use with the API, if you do not want to set this up, you will need to rip all code relating to the DB out of the bot
|
||||||
"host": "", // IP address for the db, usually localhost
|
"host": "", // IP address for the db, usually localhost
|
||||||
"localhost": "", // IP address for a secondary OPTIONAL local testing DB, usually also is localhost, but depends on your dev environment
|
"localhost": "", // IP address for a secondary OPTIONAL local testing DB, usually also is localhost, but depends on your dev environment
|
||||||
|
|
|
@ -26,6 +26,8 @@ console.log("Attempt to drop all tables");
|
||||||
await dbClient.execute(`DROP PROCEDURE IF EXISTS INC_CNT;`);
|
await dbClient.execute(`DROP PROCEDURE IF EXISTS INC_CNT;`);
|
||||||
await dbClient.execute(`DROP TABLE IF EXISTS command_cnt;`);
|
await dbClient.execute(`DROP TABLE IF EXISTS command_cnt;`);
|
||||||
await dbClient.execute(`DROP TABLE IF EXISTS guild_prefix;`);
|
await dbClient.execute(`DROP TABLE IF EXISTS guild_prefix;`);
|
||||||
|
await dbClient.execute(`DROP TABLE IF EXISTS guild_mod_role;`);
|
||||||
|
await dbClient.execute(`DROP TABLE IF EXISTS guild_clean_channel;`);
|
||||||
console.log("Tables dropped");
|
console.log("Tables dropped");
|
||||||
|
|
||||||
console.log("Attempting to create table command_cnt");
|
console.log("Attempting to create table command_cnt");
|
||||||
|
@ -63,5 +65,26 @@ await dbClient.execute(`
|
||||||
`);
|
`);
|
||||||
console.log("Table created");
|
console.log("Table created");
|
||||||
|
|
||||||
|
console.log("Attempting to create table guild_mod_role");
|
||||||
|
await dbClient.execute(`
|
||||||
|
CREATE TABLE guild_mod_role (
|
||||||
|
guildId bigint unsigned NOT NULL,
|
||||||
|
roleId bigint unsigned NOT NULL,
|
||||||
|
PRIMARY KEY (guildid),
|
||||||
|
UNIQUE KEY guild_mod_role_guildid_UNIQUE (guildid)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
`);
|
||||||
|
console.log("Table created");
|
||||||
|
|
||||||
|
console.log("Attempting to create table guild_clean_channel");
|
||||||
|
await dbClient.execute(`
|
||||||
|
CREATE TABLE guild_clean_channel (
|
||||||
|
guildId bigint unsigned NOT NULL,
|
||||||
|
channelId bigint unsigned NOT NULL,
|
||||||
|
PRIMARY KEY (guildid, channelId)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
`);
|
||||||
|
console.log("Table created");
|
||||||
|
|
||||||
await dbClient.close();
|
await dbClient.close();
|
||||||
console.log("Done!");
|
console.log("Done!");
|
||||||
|
|
16
deps.ts
16
deps.ts
|
@ -1,18 +1,18 @@
|
||||||
// All external dependancies are to be loaded here to make updating dependancy versions much easier
|
// All external dependancies are to be loaded here to make updating dependancy versions much easier
|
||||||
export {
|
export {
|
||||||
startBot, editBotStatus, editBotNickname,
|
startBot, editBotStatus, editBotNickname,
|
||||||
Intents, DiscordActivityTypes, DiscordButtonStyles, DiscordInteractionTypes,
|
Intents, DiscordActivityTypes, DiscordButtonStyles, DiscordInteractionTypes, DiscordInteractionResponseTypes,
|
||||||
sendMessage, sendDirectMessage, sendInteractionResponse, getMessage, deleteMessage,
|
sendMessage, sendDirectMessage, sendInteractionResponse, getMessage, deleteMessage,
|
||||||
|
getGuild, getUser,
|
||||||
hasGuildPermissions,
|
hasGuildPermissions,
|
||||||
cache, botId, structures
|
cache, botId, structures, cacheHandlers
|
||||||
} from "https://deno.land/x/discordeno@11.0.0-rc.5/mod.ts";
|
} from "https://deno.land/x/discordeno@12.0.1/mod.ts";
|
||||||
|
|
||||||
export type {
|
export type {
|
||||||
DiscordenoMessage, DiscordenoMember, DiscordenoGuild, CreateMessage, Interaction, ButtonComponent, ActionRow, EmbedField
|
DiscordenoMessage, DiscordenoMember, DiscordenoGuild, ButtonData, DebugArg,
|
||||||
} from "https://deno.land/x/discordeno@11.0.0-rc.5/mod.ts"; // https://deno.land/x/discordeno@11.0.0-rc.5/mod.ts
|
CreateMessage, Interaction, ButtonComponent, ActionRow, Embed, EmbedField
|
||||||
|
} from "https://deno.land/x/discordeno@12.0.1/mod.ts";
|
||||||
|
|
||||||
export { Client } from "https://deno.land/x/mysql@v2.9.0/mod.ts";
|
export { Client } from "https://deno.land/x/mysql@v2.10.1/mod.ts";
|
||||||
|
|
||||||
export { LogTypes as LT, initLog, log } from "https://raw.githubusercontent.com/Burn-E99/Log4Deno/V1.1.0/mod.ts";
|
export { LogTypes as LT, initLog, log } from "https://raw.githubusercontent.com/Burn-E99/Log4Deno/V1.1.0/mod.ts";
|
||||||
|
|
||||||
export { nanoid } from "https://deno.land/x/nanoid@v3.0.0/mod.ts";
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import config from "../config.ts";
|
||||||
|
|
||||||
export const constantCmds = {
|
export const constantCmds = {
|
||||||
help: {
|
help: {
|
||||||
embed: {
|
embeds: [{
|
||||||
title: `${config.name} Help`,
|
title: `${config.name} Help`,
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
|
@ -32,10 +32,10 @@ export const constantCmds = {
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}]
|
||||||
},
|
},
|
||||||
lfgHelp: {
|
lfgHelp: {
|
||||||
embed: {
|
embeds: [{
|
||||||
title: `${config.name} LFG Help`,
|
title: `${config.name} LFG Help`,
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
|
@ -74,10 +74,10 @@ export const constantCmds = {
|
||||||
inline: true
|
inline: true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}]
|
||||||
},
|
},
|
||||||
info: {
|
info: {
|
||||||
embed: {
|
embeds: [{
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: "Group Up, the LFG bot",
|
name: "Group Up, the LFG bot",
|
||||||
|
@ -86,67 +86,67 @@ export const constantCmds = {
|
||||||
Need help with this bot? Join my support server [here](https://discord.gg/peHASXMZYv).`
|
Need help with this bot? Join my support server [here](https://discord.gg/peHASXMZYv).`
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}]
|
||||||
},
|
},
|
||||||
version: {
|
version: {
|
||||||
embed: {
|
embeds: [{
|
||||||
title: `My current version is ${config.version}`
|
title: `My current version is ${config.version}`
|
||||||
}
|
}]
|
||||||
},
|
},
|
||||||
report: {
|
report: {
|
||||||
embed: {
|
embeds: [{
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: "Failed command has been reported to my developer.",
|
name: "Failed command has been reported to my developer.",
|
||||||
value: "For more in depth support, and information about planned maintenance, please join the support server [here](https://discord.gg/peHASXMZYv)."
|
value: "For more in depth support, and information about planned maintenance, please join the support server [here](https://discord.gg/peHASXMZYv)."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}]
|
||||||
},
|
},
|
||||||
lfgDelete1: {
|
lfgDelete1: {
|
||||||
embed: {
|
embeds: [{
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: "Could not find any LFGs to delete.",
|
name: "Could not find any LFGs to delete.",
|
||||||
value: "Make sure you are the owner of the LFG and are running this command in the same channel as the LFG"
|
value: "Make sure you are the owner of the LFG and are running this command in the same channel as the LFG"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}]
|
||||||
},
|
},
|
||||||
lfgDelete2: {
|
lfgDelete2: {
|
||||||
embed: {
|
embeds: [{
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: `Multiple LFGs found, please run this command again with the two character ID of the LFG you wish to delete.\n\nExample: \`${config.prefix}lfg delete XX\``,
|
name: `Multiple LFGs found, please run this command again with the two character ID of the LFG you wish to delete.\n\nExample: \`${config.prefix}lfg delete XX\``,
|
||||||
value: "Click on the two character IDs below to view the LFG:\n"
|
value: "Click on the two character IDs below to view the LFG:\n"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}]
|
||||||
},
|
},
|
||||||
lfgDelete3: {
|
lfgDelete3: {
|
||||||
embed: {
|
embeds: [{
|
||||||
title: "LFG deleted."
|
title: "LFG deleted."
|
||||||
}
|
}]
|
||||||
},
|
},
|
||||||
lfgEdit1: {
|
lfgEdit1: {
|
||||||
embed: {
|
embeds: [{
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: "Could not find any LFGs to edit.",
|
name: "Could not find any LFGs to edit.",
|
||||||
value: "Make sure you are the owner of the LFG and are running this command in the same channel as the LFG"
|
value: "Make sure you are the owner of the LFG and are running this command in the same channel as the LFG"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}]
|
||||||
},
|
},
|
||||||
lfgEdit2: {
|
lfgEdit2: {
|
||||||
embed: {
|
embeds: [{
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: `Multiple LFGs found, please run this command again with the two character ID of the LFG you wish to edit.\n\nExample: \`${config.prefix}lfg edit XX\``,
|
name: `Multiple LFGs found, please run this command again with the two character ID of the LFG you wish to edit.\n\nExample: \`${config.prefix}lfg edit XX\``,
|
||||||
value: "Click on the two character IDs below to view the LFG:\n"
|
value: "Click on the two character IDs below to view the LFG:\n"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ export const LFGActivities = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Among Us": {
|
"Among Us": {
|
||||||
"Vanilla": 10,
|
"Vanilla": 15,
|
||||||
"Modded": 10
|
"Modded": 15
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,18 +2,20 @@ import {
|
||||||
// Discordeno deps
|
// Discordeno deps
|
||||||
cache,
|
cache,
|
||||||
sendMessage, getMessage, deleteMessage, sendDirectMessage,
|
sendMessage, getMessage, deleteMessage, sendDirectMessage,
|
||||||
|
getGuild,
|
||||||
|
|
||||||
// Log4Deno deps
|
// Log4Deno deps
|
||||||
LT, log
|
LT, log
|
||||||
} from "../deps.ts";
|
} from "../deps.ts";
|
||||||
|
|
||||||
|
import { jsonStringifyBig } from "./utils.ts";
|
||||||
import { BuildingLFG, ActiveLFG } from "./mod.d.ts";
|
import { BuildingLFG, ActiveLFG } from "./mod.d.ts";
|
||||||
|
|
||||||
import config from "../config.ts";
|
import config from "../config.ts";
|
||||||
|
|
||||||
// getRandomStatus() returns status as string
|
// getRandomStatus() returns status as string
|
||||||
// Gets a new random status for the bot
|
// Gets a new random status for the bot
|
||||||
const getRandomStatus = (): string => {
|
const getRandomStatus = (cachedGuilds: number): string => {
|
||||||
let status = "";
|
let status = "";
|
||||||
switch (Math.floor((Math.random() * 5) + 1)) {
|
switch (Math.floor((Math.random() * 5) + 1)) {
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -29,7 +31,7 @@ const getRandomStatus = (): string => {
|
||||||
status = "Mention me to check my prefix!";
|
status = "Mention me to check my prefix!";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
status = `Running LFGs in ${cache.guilds.size} servers`;
|
status = `Running LFGs in ${cachedGuilds + cache.dispatchedGuildIds.size} servers`;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +43,7 @@ const getRandomStatus = (): string => {
|
||||||
const updateListStatistics = (botID: BigInt, serverCount: number): void => {
|
const updateListStatistics = (botID: BigInt, serverCount: number): void => {
|
||||||
config.botLists.forEach(async e => {
|
config.botLists.forEach(async e => {
|
||||||
if (e.enabled) {
|
if (e.enabled) {
|
||||||
log(LT.LOG, `Updating statistics for ${JSON.stringify(e)}`);
|
log(LT.LOG, `Updating statistics for ${jsonStringifyBig(e)}`);
|
||||||
try {
|
try {
|
||||||
const tempHeaders = new Headers();
|
const tempHeaders = new Headers();
|
||||||
tempHeaders.append(e.headers[0].header, e.headers[0].value);
|
tempHeaders.append(e.headers[0].header, e.headers[0].value);
|
||||||
|
@ -50,12 +52,12 @@ const updateListStatistics = (botID: BigInt, serverCount: number): void => {
|
||||||
const response = await fetch(e.apiUrl.replace("?{bot_id}", botID.toString()), {
|
const response = await fetch(e.apiUrl.replace("?{bot_id}", botID.toString()), {
|
||||||
"method": 'POST',
|
"method": 'POST',
|
||||||
"headers": tempHeaders,
|
"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
|
"body": jsonStringifyBig(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)}`);
|
log(LT.INFO, `Posted server count to ${e.name}. Results: ${jsonStringifyBig(response)}`);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
log(LT.WARN, `Failed to post statistics to ${e.name} | ${JSON.stringify(e)}`);
|
log(LT.WARN, `Failed to post statistics to ${e.name} | ${jsonStringifyBig(e)}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -65,26 +67,29 @@ const buildingTimeout = async (activeBuilders: Array<BuildingLFG>): Promise<void
|
||||||
const currentTime = new Date().getTime();
|
const currentTime = new Date().getTime();
|
||||||
for (let i = 0; i < activeBuilders.length; i++) {
|
for (let i = 0; i < activeBuilders.length; i++) {
|
||||||
if (activeBuilders[i].lastTouch.getTime() + (activeBuilders[i].maxIdle * 1000) < currentTime) {
|
if (activeBuilders[i].lastTouch.getTime() + (activeBuilders[i].maxIdle * 1000) < currentTime) {
|
||||||
activeBuilders[i].questionMsg.delete();
|
activeBuilders[i].questionMsg.delete().catch(e => {
|
||||||
|
log(LT.WARN, `Failed to clean up active builder | edit | ${activeBuilders[i].userId}-${activeBuilders[i].channelId} | ${jsonStringifyBig(e)}`);
|
||||||
|
});
|
||||||
if (activeBuilders[i].editing) {
|
if (activeBuilders[i].editing) {
|
||||||
activeBuilders[i].lfgMsg.edit({
|
activeBuilders[i].lfgMsg.edit({
|
||||||
content: ""
|
content: ""
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
log(LT.WARN, `Failed to clean up active builder | edit | ${activeBuilders[i].userId}-${activeBuilders[i].channelId} | ${JSON.stringify(e)}`);
|
log(LT.WARN, `Failed to clean up active builder | edit | ${activeBuilders[i].userId}-${activeBuilders[i].channelId} | ${jsonStringifyBig(e)}`);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
activeBuilders[i].lfgMsg.delete().catch(e => {
|
activeBuilders[i].lfgMsg.delete().catch(e => {
|
||||||
log(LT.WARN, `Failed to clean up active builder | delete | ${activeBuilders[i].userId}-${activeBuilders[i].channelId} | ${JSON.stringify(e)}`);
|
log(LT.WARN, `Failed to clean up active builder | delete | ${activeBuilders[i].userId}-${activeBuilders[i].channelId} | ${jsonStringifyBig(e)}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const m = await sendMessage(activeBuilders[i].channelId, `<@${activeBuilders[i].userId}>, your LFG ${activeBuilders[i].editing ? "editing" : "creation"} has timed out. Please try again.`);
|
const m = await sendMessage(activeBuilders[i].channelId, `<@${activeBuilders[i].userId}>, your LFG ${activeBuilders[i].editing ? "editing" : "creation"} has timed out. Please try again.`);
|
||||||
setTimeout(() => {
|
|
||||||
m.delete();
|
m.delete("Channel Cleanup", 30000).catch(e =>{
|
||||||
}, 30000);
|
log(LT.WARN, `Failed to delete message | ${jsonStringifyBig(e)}`);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
log(LT.WARN, `Failed to clean up active builder | ${activeBuilders[i].userId}-${activeBuilders[i].channelId} | ${JSON.stringify(e)}`);
|
log(LT.WARN, `Failed to clean up active builder | ${activeBuilders[i].userId}-${activeBuilders[i].channelId} | ${jsonStringifyBig(e)}`);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
activeBuilders.splice(i, 1);
|
activeBuilders.splice(i, 1);
|
||||||
|
@ -92,10 +97,10 @@ const buildingTimeout = async (activeBuilders: Array<BuildingLFG>): Promise<void
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const lfgNotifier = async (activeLFGPosts: Array<ActiveLFG>): Promise<void> => {
|
const lfgNotifier = async (activeLFGPosts: Array<ActiveLFG>): Promise<void> => {
|
||||||
log(LT.INFO, "Checking for LFG posts to notify/delete/lock")
|
log(LT.INFO, "Checking for LFG posts to notify/delete/lock");
|
||||||
const tenMin = 10 * 60 * 1000;
|
const tenMin = 10 * 60 * 1000;
|
||||||
const now = new Date().getTime();
|
const now = new Date().getTime();
|
||||||
for (let i = 0; i < activeLFGPosts.length; i++) {
|
for (let i = 0; i < activeLFGPosts.length; i++) {
|
||||||
|
@ -106,7 +111,7 @@ const lfgNotifier = async (activeLFGPosts: Array<ActiveLFG>): Promise<void> => {
|
||||||
const message = await getMessage(activeLFGPosts[i].channelId, activeLFGPosts[i].messageId);
|
const message = await getMessage(activeLFGPosts[i].channelId, activeLFGPosts[i].messageId);
|
||||||
const lfg = message.embeds[0].fields || [];
|
const lfg = message.embeds[0].fields || [];
|
||||||
const lfgActivity = `${lfg[0].name.substr(0, lfg[0].name.length - 1)} - ${lfg[0].value}`;
|
const lfgActivity = `${lfg[0].name.substr(0, lfg[0].name.length - 1)} - ${lfg[0].value}`;
|
||||||
const guildName = message.guild?.name || "unknown";
|
const guildName = message.guild?.name || (await getGuild(message.guildId, {counts:false, addToCache: false})).name;
|
||||||
const members = lfg[4].value;
|
const members = lfg[4].value;
|
||||||
let editMsg = "";
|
let editMsg = "";
|
||||||
members.split("\n").forEach(async m => {
|
members.split("\n").forEach(async m => {
|
||||||
|
@ -115,7 +120,7 @@ const lfgNotifier = async (activeLFGPosts: Array<ActiveLFG>): Promise<void> => {
|
||||||
const userId = BigInt(tmpId.substr(0, tmpId.length - 1));
|
const userId = BigInt(tmpId.substr(0, tmpId.length - 1));
|
||||||
editMsg += `<@${userId}>, `;
|
editMsg += `<@${userId}>, `;
|
||||||
await sendDirectMessage(userId, {
|
await sendDirectMessage(userId, {
|
||||||
embed: {
|
embeds: [{
|
||||||
title: `Hello ${name}! Your event in ${guildName} starts in less than 10 minutes.`,
|
title: `Hello ${name}! Your event in ${guildName} starts in less than 10 minutes.`,
|
||||||
fields: [
|
fields: [
|
||||||
lfg[0],
|
lfg[0],
|
||||||
|
@ -124,7 +129,7 @@ const lfgNotifier = async (activeLFGPosts: Array<ActiveLFG>): Promise<void> => {
|
||||||
value: members
|
value: members
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -137,7 +142,7 @@ const lfgNotifier = async (activeLFGPosts: Array<ActiveLFG>): Promise<void> => {
|
||||||
activeLFGPosts[i].notified = true;
|
activeLFGPosts[i].notified = true;
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
log(LT.WARN, `Failed to find LFG ${activeLFGPosts[i].ownerId}-${activeLFGPosts[i].lfgUid} | ${JSON.stringify(err)}`);
|
log(LT.WARN, `Failed to find LFG ${activeLFGPosts[i].ownerId}-${activeLFGPosts[i].lfgUid} | ${jsonStringifyBig(err)}`);
|
||||||
|
|
||||||
activeLFGPosts.splice(i, 1);
|
activeLFGPosts.splice(i, 1);
|
||||||
i--;
|
i--;
|
||||||
|
@ -145,7 +150,7 @@ const lfgNotifier = async (activeLFGPosts: Array<ActiveLFG>): Promise<void> => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock LFG from editing/Joining/Leaving
|
// Lock LFG from editing/Joining/Leaving
|
||||||
if (!activeLFGPosts[i].locked && activeLFGPosts[i].lfgTime < now) {
|
else if (!activeLFGPosts[i].locked && activeLFGPosts[i].lfgTime < now) {
|
||||||
log(LT.INFO, `Locking LFG ${activeLFGPosts[i].ownerId}-${activeLFGPosts[i].lfgUid}`);
|
log(LT.INFO, `Locking LFG ${activeLFGPosts[i].ownerId}-${activeLFGPosts[i].lfgUid}`);
|
||||||
try {
|
try {
|
||||||
const message = await getMessage(activeLFGPosts[i].channelId, activeLFGPosts[i].messageId);
|
const message = await getMessage(activeLFGPosts[i].channelId, activeLFGPosts[i].messageId);
|
||||||
|
@ -157,7 +162,7 @@ const lfgNotifier = async (activeLFGPosts: Array<ActiveLFG>): Promise<void> => {
|
||||||
activeLFGPosts[i].locked = true;
|
activeLFGPosts[i].locked = true;
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
log(LT.WARN, `Failed to find LFG ${activeLFGPosts[i].ownerId}-${activeLFGPosts[i].lfgUid} | ${JSON.stringify(err)}`);
|
log(LT.WARN, `Failed to find LFG ${activeLFGPosts[i].ownerId}-${activeLFGPosts[i].lfgUid} | ${jsonStringifyBig(err)}`);
|
||||||
|
|
||||||
activeLFGPosts.splice(i, 1);
|
activeLFGPosts.splice(i, 1);
|
||||||
i--;
|
i--;
|
||||||
|
@ -165,19 +170,17 @@ const lfgNotifier = async (activeLFGPosts: Array<ActiveLFG>): Promise<void> => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete old LFG post
|
// Delete old LFG post
|
||||||
if (activeLFGPosts[i].lfgTime < (now - tenMin)) {
|
else if (activeLFGPosts[i].lfgTime < (now - tenMin)) {
|
||||||
log(LT.INFO, `Deleting LFG ${activeLFGPosts[i].ownerId}-${activeLFGPosts[i].lfgUid}`);
|
log(LT.INFO, `Deleting LFG ${activeLFGPosts[i].ownerId}-${activeLFGPosts[i].lfgUid}`);
|
||||||
await deleteMessage(activeLFGPosts[i].channelId, activeLFGPosts[i].messageId, "LFG post expired").catch(e => {
|
await deleteMessage(activeLFGPosts[i].channelId, activeLFGPosts[i].messageId, "LFG post expired").catch(e => {
|
||||||
log(LT.WARN, `Failed to delete LFG ${activeLFGPosts[i].ownerId}-${activeLFGPosts[i].lfgUid} | ${JSON.stringify(e)}`);
|
log(LT.WARN, `Failed to delete LFG ${activeLFGPosts[i].ownerId}-${activeLFGPosts[i].lfgUid} | ${jsonStringifyBig(e)}`);
|
||||||
});
|
});
|
||||||
activeLFGPosts.splice(i, 1);
|
activeLFGPosts.splice(i, 1);
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
localStorage.setItem("activeLFGPosts", JSON.stringify(activeLFGPosts, (_key, value) =>
|
localStorage.setItem("activeLFGPosts", jsonStringifyBig(activeLFGPosts));
|
||||||
typeof value === "bigint" ? value.toString() + "n" : value
|
};
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
export default { getRandomStatus, updateListStatistics, buildingTimeout, lfgNotifier };
|
export default { getRandomStatus, updateListStatistics, buildingTimeout, lfgNotifier };
|
||||||
|
|
|
@ -5,5 +5,12 @@ import {
|
||||||
export type JoinLeaveType = {
|
export type JoinLeaveType = {
|
||||||
embed: EmbedField[],
|
embed: EmbedField[],
|
||||||
success: boolean,
|
success: boolean,
|
||||||
full: boolean
|
full: boolean,
|
||||||
|
justFilled: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UrlIds = {
|
||||||
|
guildId: bigint,
|
||||||
|
channelId: bigint,
|
||||||
|
messageId: bigint
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,12 @@ import {
|
||||||
LT, log
|
LT, log
|
||||||
} from "../deps.ts";
|
} from "../deps.ts";
|
||||||
|
|
||||||
import { JoinLeaveType } from "./lfgHandlers.d.ts";
|
import { JoinLeaveType, UrlIds } from "./lfgHandlers.d.ts";
|
||||||
import { BuildingLFG } from "./mod.d.ts";
|
import { BuildingLFG } from "./mod.d.ts";
|
||||||
import { LFGActivities } from "./games.ts";
|
import { LFGActivities } from "./games.ts";
|
||||||
import { determineTZ } from "./timeUtils.ts";
|
import { determineTZ } from "./timeUtils.ts";
|
||||||
import { lfgStepQuestions } from "./constantCmds.ts";
|
import { lfgStepQuestions } from "./constantCmds.ts";
|
||||||
|
import { jsonStringifyBig } from "./utils.ts";
|
||||||
|
|
||||||
export const handleLFGStep = async (wipLFG: BuildingLFG, input: string): Promise<BuildingLFG> => {
|
export const handleLFGStep = async (wipLFG: BuildingLFG, input: string): Promise<BuildingLFG> => {
|
||||||
const currentLFG = (wipLFG.lfgMsg.embeds[0] || { fields: undefined }).fields || [
|
const currentLFG = (wipLFG.lfgMsg.embeds[0] || { fields: undefined }).fields || [
|
||||||
|
@ -225,7 +226,8 @@ export const handleLFGStep = async (wipLFG: BuildingLFG, input: string): Promise
|
||||||
let lfgDate = `${today.getMonth() + 1}/${today.getDate()}`,
|
let lfgDate = `${today.getMonth() + 1}/${today.getDate()}`,
|
||||||
lfgTime = "",
|
lfgTime = "",
|
||||||
lfgTZ = "",
|
lfgTZ = "",
|
||||||
lfgPeriod = "";
|
lfgPeriod = "",
|
||||||
|
overrodeTZ = false;
|
||||||
|
|
||||||
input.split(" ").forEach(c => {
|
input.split(" ").forEach(c => {
|
||||||
if (c.includes("/")) {
|
if (c.includes("/")) {
|
||||||
|
@ -258,14 +260,14 @@ export const handleLFGStep = async (wipLFG: BuildingLFG, input: string): Promise
|
||||||
} else if (c.match(/^\d/)) {
|
} else if (c.match(/^\d/)) {
|
||||||
const tzIdx = c.search(/[a-zA-Z]/);
|
const tzIdx = c.search(/[a-zA-Z]/);
|
||||||
lfgTime = c.substr(0, tzIdx);
|
lfgTime = c.substr(0, tzIdx);
|
||||||
lfgTZ = determineTZ(c.substr(tzIdx));
|
[lfgTZ, overrodeTZ] = determineTZ(c.substr(tzIdx));
|
||||||
} else {
|
} else {
|
||||||
lfgTZ = determineTZ(c);
|
[lfgTZ, overrodeTZ] = determineTZ(c);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!lfgTZ) {
|
if (!lfgTZ) {
|
||||||
lfgTZ = determineTZ("ET");
|
[lfgTZ, overrodeTZ] = determineTZ("ET");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lfgTime.includes(":")) {
|
if (!lfgTime.includes(":")) {
|
||||||
|
@ -324,9 +326,9 @@ export const handleLFGStep = async (wipLFG: BuildingLFG, input: string): Promise
|
||||||
try {
|
try {
|
||||||
if (editFlag) {
|
if (editFlag) {
|
||||||
wipLFG.lfgMsg = await wipLFG.lfgMsg.edit({
|
wipLFG.lfgMsg = await wipLFG.lfgMsg.edit({
|
||||||
embed: {
|
embeds: [{
|
||||||
fields: currentLFG
|
fields: currentLFG
|
||||||
}
|
}]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,7 +338,7 @@ export const handleLFGStep = async (wipLFG: BuildingLFG, input: string): Promise
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
log(LT.WARN, `Failed to edit active builder | ${wipLFG.userId}-${wipLFG.channelId} | ${JSON.stringify(e)}`);
|
log(LT.WARN, `Failed to edit active builder | ${wipLFG.userId}-${wipLFG.channelId} | ${jsonStringifyBig(e)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return wipLFG;
|
return wipLFG;
|
||||||
|
@ -344,6 +346,7 @@ export const handleLFGStep = async (wipLFG: BuildingLFG, input: string): Promise
|
||||||
|
|
||||||
export const handleMemberJoin = (lfg: EmbedField[], member: DiscordenoMember, alternate: boolean): JoinLeaveType => {
|
export const handleMemberJoin = (lfg: EmbedField[], member: DiscordenoMember, alternate: boolean): JoinLeaveType => {
|
||||||
let success = false;
|
let success = false;
|
||||||
|
let justFilled = false;
|
||||||
|
|
||||||
const userStr = `${member.username} - <@${member.id}>`;
|
const userStr = `${member.username} - <@${member.id}>`;
|
||||||
|
|
||||||
|
@ -352,6 +355,7 @@ export const handleMemberJoin = (lfg: EmbedField[], member: DiscordenoMember, al
|
||||||
const maxMembers = parseInt(tempMembers[1]);
|
const maxMembers = parseInt(tempMembers[1]);
|
||||||
|
|
||||||
if (alternate && !lfg[5].value.includes(member.id.toString())) {
|
if (alternate && !lfg[5].value.includes(member.id.toString())) {
|
||||||
|
// remove from joined list
|
||||||
if (lfg[4].value.includes(member.id.toString())) {
|
if (lfg[4].value.includes(member.id.toString())) {
|
||||||
const tempArr = lfg[4].value.split("\n");
|
const tempArr = lfg[4].value.split("\n");
|
||||||
const memberIdx = tempArr.findIndex(m => m.includes(member.id.toString()));
|
const memberIdx = tempArr.findIndex(m => m.includes(member.id.toString()));
|
||||||
|
@ -371,11 +375,12 @@ export const handleMemberJoin = (lfg: EmbedField[], member: DiscordenoMember, al
|
||||||
}
|
}
|
||||||
|
|
||||||
success = true;
|
success = true;
|
||||||
} else if (!alternate &¤tMembers < maxMembers && !lfg[4].value.includes(member.id.toString())) {
|
} else if (!alternate && currentMembers < maxMembers && !lfg[4].value.includes(member.id.toString())) {
|
||||||
|
// remove from alternate list
|
||||||
if (lfg[5].value.includes(member.id.toString())) {
|
if (lfg[5].value.includes(member.id.toString())) {
|
||||||
const tempArr = lfg[5].value.split("\n");
|
const tempArr = lfg[5].value.split("\n");
|
||||||
const memberIdx = tempArr.findIndex(m => m.includes(member.id.toString()));
|
const memberIdx = tempArr.findIndex(m => m.includes(member.id.toString()));
|
||||||
tempArr.splice(memberIdx, 1)
|
tempArr.splice(memberIdx, 1);
|
||||||
lfg[5].value = tempArr.join("\n") || "None";
|
lfg[5].value = tempArr.join("\n") || "None";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,16 +390,34 @@ export const handleMemberJoin = (lfg: EmbedField[], member: DiscordenoMember, al
|
||||||
lfg[4].value += `\n${userStr}`;
|
lfg[4].value += `\n${userStr}`;
|
||||||
}
|
}
|
||||||
currentMembers++;
|
currentMembers++;
|
||||||
|
justFilled = currentMembers === maxMembers;
|
||||||
|
|
||||||
lfg[4].name = `Members Joined: ${currentMembers}/${maxMembers}`;
|
lfg[4].name = `Members Joined: ${currentMembers}/${maxMembers}`;
|
||||||
|
|
||||||
success = true;
|
success = true;
|
||||||
|
} else if (!alternate && currentMembers === maxMembers && !lfg[4].value.includes(member.id.toString())) {
|
||||||
|
// update user in alternate list to include the * to make them autojoin
|
||||||
|
if (lfg[5].value.includes(member.id.toString())) {
|
||||||
|
const tempArr = lfg[5].value.split("\n");
|
||||||
|
const memberIdx = tempArr.findIndex(m => m.includes(member.id.toString()));
|
||||||
|
tempArr[memberIdx] = `${tempArr[memberIdx]} *`;
|
||||||
|
lfg[5].value = tempArr.join("\n");
|
||||||
|
} else {
|
||||||
|
if (lfg[5].value === "None") {
|
||||||
|
lfg[5].value = `${userStr} *`;
|
||||||
|
} else {
|
||||||
|
lfg[5].value += `\n${userStr} *`;
|
||||||
|
}
|
||||||
|
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
embed: lfg,
|
embed: lfg,
|
||||||
success: success,
|
success: success,
|
||||||
full: currentMembers === maxMembers
|
full: currentMembers === maxMembers,
|
||||||
|
justFilled: justFilled
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -413,10 +436,25 @@ export const handleMemberLeave = (lfg: EmbedField[], member: DiscordenoMember):
|
||||||
tempArr.splice(memberIdx, 1);
|
tempArr.splice(memberIdx, 1);
|
||||||
lfg[4].value = tempArr.join("\n") || "None";
|
lfg[4].value = tempArr.join("\n") || "None";
|
||||||
|
|
||||||
if (currentMembers) {
|
if (lfg[5].value.includes("*")) {
|
||||||
currentMembers--;
|
// find first * user and move them to the joined list
|
||||||
|
const tempArr2 = lfg[5].value.split("\n");
|
||||||
|
const memberToMoveIdx = tempArr2.findIndex(m => m.includes("*"))
|
||||||
|
let memberToMove = tempArr2[memberToMoveIdx];
|
||||||
|
memberToMove = memberToMove.substr(0, memberToMove.length - 2);
|
||||||
|
tempArr.push(memberToMove);
|
||||||
|
lfg[4].value = tempArr.join("\n") || "None";
|
||||||
|
|
||||||
|
// Remove them from the alt list
|
||||||
|
tempArr2.splice(memberToMoveIdx, 1);
|
||||||
|
lfg[5].value = tempArr2.join("\n") || "None";
|
||||||
|
} else {
|
||||||
|
// update count since no users were marked as *
|
||||||
|
if (currentMembers) {
|
||||||
|
currentMembers--;
|
||||||
|
}
|
||||||
|
lfg[4].name = `Members Joined: ${currentMembers}/${maxMembers}`;
|
||||||
}
|
}
|
||||||
lfg[4].name = `Members Joined: ${currentMembers}/${maxMembers}`;
|
|
||||||
|
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
|
@ -433,6 +471,25 @@ export const handleMemberLeave = (lfg: EmbedField[], member: DiscordenoMember):
|
||||||
return {
|
return {
|
||||||
embed: lfg,
|
embed: lfg,
|
||||||
success: success,
|
success: success,
|
||||||
full: currentMembers === maxMembers
|
full: currentMembers === maxMembers,
|
||||||
|
justFilled: false
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const urlToIds = (url: string): UrlIds => {
|
||||||
|
const strIds = {
|
||||||
|
guildId: "",
|
||||||
|
channelId: "",
|
||||||
|
messageId: ""
|
||||||
|
};
|
||||||
|
|
||||||
|
url = url.toLowerCase();
|
||||||
|
|
||||||
|
[strIds.guildId, strIds.channelId, strIds.messageId] = url.substr((url.indexOf("channels") + 9)).split("/");
|
||||||
|
|
||||||
|
return {
|
||||||
|
guildId: BigInt(strIds.guildId),
|
||||||
|
channelId: BigInt(strIds.channelId),
|
||||||
|
messageId: BigInt(strIds.messageId)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,10 +28,12 @@ export type GuildPrefixes = {
|
||||||
prefix: string
|
prefix: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// TEMP
|
export type GuildModRoles = {
|
||||||
export interface ButtonData {
|
guildId: bigint,
|
||||||
/** with the value you defined for this component */
|
roleId: bigint
|
||||||
customId: string;
|
}
|
||||||
/** The type of this component */
|
|
||||||
componentType: 2;
|
export type GuildCleanChannels = {
|
||||||
|
guildId: bigint,
|
||||||
|
channelId: bigint
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,22 @@
|
||||||
export const determineTZ = (tz: string): string => {
|
export const determineTZ = (tz: string, userOverride = false): [string, boolean] => {
|
||||||
tz = tz.toUpperCase();
|
tz = tz.toUpperCase();
|
||||||
|
|
||||||
if (tz === "ET" || tz === "CT" || tz === "MT" || tz === "PT") {
|
let overrode = false;
|
||||||
|
const shortHandUSTZ = (tz === "ET" || tz === "CT" || tz === "MT" || tz === "PT");
|
||||||
|
const fullUSTZ = (tz.length === 3 && (tz.startsWith("E") || tz.startsWith("C") || tz.startsWith("M") || tz.startsWith("P")) && (tz.endsWith("DT") || tz.endsWith("ST")));
|
||||||
|
|
||||||
|
if (!userOverride && (shortHandUSTZ || fullUSTZ)) {
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
const jan = new Date(today.getFullYear(), 0, 1);
|
const jan = new Date(today.getFullYear(), 0, 1);
|
||||||
const jul = new Date(today.getFullYear(), 6, 1);
|
const jul = new Date(today.getFullYear(), 6, 1);
|
||||||
if (today.getTimezoneOffset() < Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset())) {
|
if (today.getTimezoneOffset() < Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset())) {
|
||||||
|
if (tz.includes("S")) overrode = true;
|
||||||
tz = `${tz.substr(0, 1)}DT`;
|
tz = `${tz.substr(0, 1)}DT`;
|
||||||
} else {
|
} else {
|
||||||
|
if (tz.includes("D")) overrode = true;
|
||||||
tz = `${tz.substr(0, 1)}ST`;
|
tz = `${tz.substr(0, 1)}ST`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tz;
|
return [tz, overrode];
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
export const jsonParseBig = (input: string) => {
|
||||||
|
return JSON.parse(input, (_key, value) => {
|
||||||
|
if (typeof value === "string" && /^\d+n$/.test(value)) {
|
||||||
|
return BigInt(value.substr(0, value.length - 1));
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const jsonStringifyBig = (input: any) => {
|
||||||
|
return JSON.stringify(input, (_key, value) =>
|
||||||
|
typeof value === "bigint" ? value.toString() + "n" : value
|
||||||
|
);
|
||||||
|
};
|
Loading…
Reference in New Issue