Skip to content
1 change: 0 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ commands/emoji.js
commands/eval.js
commands/excuse.js
commands/glape.js
commands/headcount.js
commands/id.js
commands/leaderboard.js
commands/leaveGuild.js
Expand Down
4 changes: 4 additions & 0 deletions botSetup.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ const afkCheck = require('./commands/afkCheck.js');
const vibotChannels = require('./commands/vibotChannels');
const vetVerification = require('./commands/vetVerification');
const verification = require('./commands/verification');
const headcount = require('./commands/headcount');

// Specific Jobs
const { UnbanVet, Unsuspend } = require('./jobs/unban.js');
const { KeyAlert } = require('./jobs/keyAlert.js');
Expand Down Expand Up @@ -136,6 +138,8 @@ async function setup(bot) {

// Initialize the bot's slash commands
iterServers(bot, deployCommands);

await headcount.initialize(bot);
}

const launchFlask = require('./ml/spawnFlask.js');
Expand Down
235 changes: 136 additions & 99 deletions commands/afkCheck.js

Large diffs are not rendered by default.

172 changes: 165 additions & 7 deletions commands/afkTemplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,126 @@ const TemplateButtonChoice = {

// Enum for Button Colors in AFK Templates
const TemplateButtonColors = [1,2,3,4]

/**
* @typedef {import('../data/guildSettings.701483950559985705.cache.json')} Settings
*/
/**
* @typedef EmojiData
* @property {string} tag
* @property {string} name
* @property {string} id
* @property {string} text
* @property {string} guildid
* @property {string} guildname
* @property {boolean} animated
*/
/**
* @typedef ReactData
* @property {string | EmojiData} emote
* @property {boolean} onHeadcount
* @property {number} start
* @property {number} lifetime
*/
/**
* @typedef {{}} UnknownTemplateResult
*/
/**
* @typedef TemplateMatchResult
* @property {{[name: string]: ReactData}} reacts
* @property {string[]} aliases
* @property {string} templateName
* @property {string[]} sectionNames
*/
/**
* @typedef BaseBodyData
* @property {'VC_LESS' | 'VC' | 'STATIC'} vcState
* @property {string} nextPhaseButton
* @property {number} timeLimit
* @property {string?} messsage
*/
/**
* @typedef BodyEmbed
* @property {Discord.ColorResolvable} color
* @property {string?} description
* @property {string?} image
* @property {string[]} thumbnail
*/
/**
* @typedef BodyData
* @property {number} vcState
* @property {string} nextPhaseButton
* @property {number} timeLimit
* @property {string?} messsage
* @property {BodyEmbed?} embed
*/
/**
* @typedef LogOption
* @property {string[]} logName
* @property {string} points
* @property {string?} multiplier
*/
/**
* @typedef TemplateButton
* @property {string?} minRole
* @property {string?} confirmationMessage
* @property {string?} confirmationMedia
* @property {number?} disableStart
* @property {string[]} minStaffRoles
* @property {{[logName: string]: LogOption}} logOptions
* @property {number} limit
* @property {string[]} parent
* @property {boolean} displayName
* @property {boolean} confirm
* @property {boolean} location
* @property {number} start
* @property {number} lifetime
* @property {string} emote
* @property {string | number} [points]
* @property {string} name
* @property {number} type
* @property {number} choice
* @property {number} color
*/
/**
* @typedef TemplateData
* @property {{[name: string]: ReactData}} reacts
* @property {string} templateName
* @property {Discord.DateResolvable} creationDate
* @property {string} name
* @property {string} commandsChannel
* @property {number} startDelay
* @property {number} cap
* @property {number} phases
* @property {number} parentTemplateId
* @property {boolean} capButton
* @property {string} category
* @property {string} templateChannel
* @property {string} statusChannel
* @property {string} activeChannel
* @property {string[]} minViewRaiderRoles
* @property {string[]} minJoinRaiderRoles
* @property {BaseBodyData[]} baseBody
* @property {number} templateId
* @property {boolean} enabled
* @property {string[]} pingRoles
* @property {string} logName
* @property {number} vcOptions
* @property {{[x: string]: string}} partneredStatusChannels
* @property {BodyData[]} body
* @property {{[buttonName: string]: TemplateButton}} buttons
* @property {{[name: string]: ReactData}} reacts
* @property {string[][]} minStaffRoles
*
*/

/**
* @param {Settings} botSettings
* @param {Discord.GuildMember} member
* @param {string} guildId
* @param {string} commandChannel
* @param {string} alias
* @returns {Promise<string[]>} list of matching templates
*/
async function resolveTemplateAlias(botSettings, member, guildId, commandChannel, alias) {
const templateUrl = new URL(settings.config.url)
templateUrl.pathname = `/api/${guildId}/template/${commandChannel}/alias/${alias}`
Expand All @@ -65,6 +184,13 @@ async function resolveTemplateAlias(botSettings, member, guildId, commandChannel
return templateNames
}

/**
* @param {Settings} botSettings
* @param {Discord.GuildMember} member
* @param {string} guildId
* @param {string} commandChannel
* @returns {Promise<TemplateMatchResult[]>}
*/
async function resolveTemplateList(botSettings, member, guildId, commandChannel) {
const templateUrl = new URL(settings.config.url)
templateUrl.pathname = `/api/${guildId}/commandchannel/${commandChannel}/templates`
Expand All @@ -74,6 +200,15 @@ async function resolveTemplateList(botSettings, member, guildId, commandChannel)
return templateNames
}

/**
*
* @param {Settings} botSettings
* @param {Discord.GuildMember} member
* @param {string} guildId
* @param {string} commandChannel
* @param {string} templateName
* @returns {Promise<TemplateData | UnknownTemplateResult | AfkTemplateValidationError>}
*/
async function resolveTemplateName(botSettings, member, guildId, commandChannel, templateName) {
const templateUrl = new URL(settings.config.url)
templateUrl.pathname = `/api/${guildId}/template/${commandChannel}/template/${templateName}`
Expand All @@ -83,6 +218,12 @@ async function resolveTemplateName(botSettings, member, guildId, commandChannel,
return template
}

/**
*
* @param {Discord.Message} message
* @param {string[]} templateNames
* @returns {string}
*/
async function templateNamePrompt(message, templateNames) {
const templateMenu = new Discord.StringSelectMenuBuilder() // If multiple found, give option to choose AFK Template
.setCustomId(`template`)
Expand Down Expand Up @@ -115,15 +256,22 @@ class AfkTemplateValidationError extends Error {
}
}

// Class for Finding, Checking, Loading and Processing Information in an AFK Template
/**
* Class for Finding, Checking, Loading and Processing Information in an AFK Template
*/
class AfkTemplate {
/** @type {TemplateData} */
#template;
/** @type {Discord.Client} */
#bot;
/**@type {Settings} */
#botSettings;
/** @type {Discord.Guild} */
#guild;
#inherit;
/** @type {string} */
#templateName;


/** Constructor for the AFK Template Class
* @param {Discord.Client} bot The client which is running the bot
* @param {Object} botSettings The object holding the settings of the bot
Expand All @@ -134,10 +282,8 @@ class AfkTemplate {
this.#bot = bot
this.#botSettings = bot.settings[guild.id]
this.#guild = guild
this.#inherit = null
this.#template = template
this.#templateName = template.templateName

if (this.#template instanceof AfkTemplateValidationError) throw this.#template
// Validate that the template is OK to use
this.#validateTemplateParameters() // Validate existence of AFK Template parameters
Expand All @@ -164,6 +310,10 @@ class AfkTemplate {
return this.#templateName
}

get template() {
return this.#template
}

// Function for populating child AFK Template parameters in an object from Parent AFK Template object
#populateObjectInherit(template, parentTemplate) {
for (let i in parentTemplate) {
Expand Down Expand Up @@ -369,7 +519,7 @@ class AfkTemplate {
}

#validateTemplateEmote(emote) {
return this.#bot.storedEmojis[emote]
return emote.id || this.#bot.storedEmojis[emote] // headcounts are reusing processed templates, if react[index].emote has an id property, assume it's a processed emote
}

#validateTemplateBoolean(bool) {
Expand Down Expand Up @@ -496,7 +646,15 @@ class AfkTemplate {
}

#processReacts() {
for (let i in this.reacts) this.reacts[i].emote = this.#bot.storedEmojis[this.reacts[i].emote]
for (let i in this.reacts) {
if (this.reacts[i].emote.id) continue;
this.reacts[i].emote = this.#bot.storedEmojis[this.reacts[i].emote]
}
}

getRandomThumbnail() {
const thumbnails = this.processBody()[1].embed.thumbnail
if (thumbnails) return thumbnails[Math.floor(Math.random() * thumbnails.length)]
}
}

Expand Down
Loading