music-very-player/src/input_manager.js

101 lines
3.4 KiB
JavaScript

const { Manager } = require('./manager')
const { Playlist } = require('./playlist')
const { GuildAction } = require('./guild_action')
const ONE_SECOND = 1000
/**
* @typedef {Object} Trigger
* @property {RegExp} pattern The pattern that will trigger the trigger
* @property {string} target The target class
* @property {string} action The method to call on trigger
* @property {number} [ttl=3600] The time to live (or timeout) of the trigger, in seconds
* @property {boolean} [user_shared=false] <code>true</code> if anyone can trigger the action, <code>false</code> otherwise
* @property {number} [repeat=1] How many times the trigger should be called
* @property {callback} [on_expire] A function to call if the ttl is reached before being triggered
*/
/**
* InputManager handle message in order to defines which other manager should
* handle it. It uses to do so a mix { target, action } which can be used by
* the GuildsManager.
*
* It also is able to generate Trigger and execute them when some conditions
* are met.
*
* @class
* @extends Manager
*/
class InputManager extends Manager {
#config
#triggers
constructor(gmanager, guild_id, config) {
super(...arguments)
this.#config = config
this.#triggers = []
}
/**
* Generate a {@link GuildAction} which describe a route to a class (Manager) and an action.
*
* @param {Discord.Message} message discord triggers the current event based on this message
* @returns {GuildAction}
*/
async handle_message(message) {
if (message.content.slice(0, this.#config.prefix.length) === this.#config.prefix) {
const [command, ...command_params] = message.content.slice(this.#config.prefix.length).trim().split(/\s+/)
console.error("> command", command)
const command_target_action = this.#config.commands[command]
console.error("> command_target_action", command_target_action)
if (command_target_action) {
return new GuildAction({ ...command_target_action, message, params: command_params })
}
}
const trigger_target_action_idx = this.#triggers.findIndex(t => t.pattern.test(message.content))
// TODO: add user, etc check
if (trigger_target_action_idx > -1) {
const trigger_target_action = this.#triggers[trigger_target_action_idx]
console.error("> trigger_target_action", trigger_target_action)
trigger_target_action.repeat -= 1
if (trigger_target_action.repeat <= 0) {
delete this.#triggers[trigger_target_action_idx]
this.#triggers = this.#triggers.filter(Boolean)
}
const params = message.content
.split(trigger_target_action.pattern)[1]
.trim()
.split(/\s+/)
return new GuildAction({ ...trigger_target_action, message, params: params })
}
return null
}
/**
* @param {Trigger} trigger The trigger to add
*/
add_trigger({ pattern, target, action, ttl = 3600, user_shared = false, repeat = 1, on_expire }) {
const trigger = {
pattern,
target,
action,
ttl,
user_shared,
repeat,
on_expire
}
this.#triggers.push(trigger)
setTimeout(() => {
const idx = this.#triggers.findIndex(t => t === trigger)
delete this.#triggers[idx]
this.#triggers = this.#triggers.filter(Boolean)
if (idx !== -1 && typeof trigger.on_expire === 'function') {
trigger.on_expire(trigger)
}
}, ttl * ONE_SECOND)
}
}
module.exports = { InputManager }