detritus-client
Version:
A Typescript NodeJS library to interact with Discord's API, both Rest and Gateway.
616 lines (615 loc) • 24 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.InteractionCommandOptionChoice = exports.InteractionCommandOption = exports.InteractionCommand = void 0;
const Crypto = require("crypto");
const commandratelimit_1 = require("../commandratelimit");
const constants_1 = require("../constants");
const baseset_1 = require("../collections/baseset");
const basecollection_1 = require("../collections/basecollection");
const basestructure_1 = require("../structures/basestructure");
const ON_FUNCTION_NAMES = Object.freeze([
'onDmBlocked',
'onLoadingTrigger',
'onBefore',
'onBeforeRun',
'onCancel',
'onCancelRun',
'onError',
'onPermissionsFail',
'onPermissionsFailClient',
'onRatelimit',
'run',
'onRunError',
'onSuccess',
'onValueError',
]);
const SET_VARIABLE_NAMES = Object.freeze([
'disableDm',
'permissions',
'permissionsClient',
'permissionsIgnoreClientOwner',
'ratelimits',
'triggerLoadingAfter',
'triggerLoadingAsEphemeral',
]);
const keysInteractionCommand = new baseset_1.BaseSet([
constants_1.DiscordKeys.DEFAULT_PERMISSION,
constants_1.DiscordKeys.DESCRIPTION,
constants_1.DiscordKeys.IDS,
constants_1.DiscordKeys.NAME,
constants_1.DiscordKeys.OPTIONS,
constants_1.DiscordKeys.TYPE,
]);
const keysSkipDifferenceInteractionCommand = new baseset_1.BaseSet([
constants_1.DiscordKeys.APPLICATION_ID,
constants_1.DiscordKeys.IDS,
]);
class InteractionCommand extends basestructure_1.Structure {
constructor(data = {}) {
super();
this._keys = keysInteractionCommand;
this._keysSkipDifference = keysSkipDifferenceInteractionCommand;
this.defaultPermission = true;
this.description = '';
this.ids = new basecollection_1.BaseCollection();
this.global = true;
this.name = '';
this.type = constants_1.ApplicationCommandTypes.CHAT_INPUT;
this.metadata = {};
this.ratelimits = [];
if (constants_1.DetritusKeys[constants_1.DiscordKeys.DEFAULT_PERMISSION] in data) {
data[constants_1.DiscordKeys.DEFAULT_PERMISSION] = data[constants_1.DetritusKeys[constants_1.DiscordKeys.DEFAULT_PERMISSION]];
}
this.disableDm = (data.disableDm !== undefined) ? !!data.disableDm : this.disableDm;
this.global = (data.global !== undefined) ? !!data.global : this.global;
this.metadata = Object.assign(this.metadata, data.metadata);
this.permissions = (data.permissions) ? data.permissions.map((x) => BigInt(x)) : undefined;
this.permissionsClient = (data.permissionsClient) ? data.permissionsClient.map((x) => BigInt(x)) : undefined;
this.permissionsIgnoreClientOwner = (data.permissionsIgnoreClientOwner !== undefined) ? !!data.permissionsIgnoreClientOwner : undefined;
this.triggerLoadingAfter = (data.triggerLoadingAfter !== undefined) ? data.triggerLoadingAfter : this.triggerLoadingAfter;
this.triggerLoadingAsEphemeral = (data.triggerLoadingAsEphemeral !== undefined) ? data.triggerLoadingAsEphemeral : this.triggerLoadingAsEphemeral;
if (data.ratelimit) {
this.ratelimits.push(new commandratelimit_1.CommandRatelimit(data.ratelimit, this));
}
if (data.ratelimits) {
for (let rOptions of data.ratelimits) {
if (typeof (rOptions.type) === 'string') {
const rType = (rOptions.type || '').toLowerCase();
if (this.ratelimits.some((ratelimit) => ratelimit.type === rType)) {
throw new Error(`Ratelimit with type ${rType} already exists`);
}
}
this.ratelimits.push(new commandratelimit_1.CommandRatelimit(rOptions, this));
}
}
if (data.guildIds) {
if (data.global === undefined) {
this.global = false;
}
this.guildIds = new baseset_1.BaseSet(data.guildIds);
}
if (data._file) {
this._file = data._file;
}
Object.defineProperties(this, {
_file: { configurable: true, writable: false },
});
this.onDmBlocked = data.onDmBlocked || this.onDmBlocked;
this.onLoadingTrigger = data.onLoadingTrigger || this.onLoadingTrigger;
this.onBefore = data.onBefore || this.onBefore;
this.onBeforeRun = data.onBeforeRun || this.onBeforeRun;
this.onCancel = data.onCancel || this.onCancel;
this.onCancelRun = data.onCancelRun || this.onCancelRun;
this.onError = data.onError || this.onError;
this.onPermissionsFail = data.onPermissionsFail || this.onPermissionsFail;
this.onPermissionsFailClient = data.onPermissionsFailClient || this.onPermissionsFailClient;
this.onRatelimit = data.onRatelimit || this.onRatelimit;
this.run = data.run || this.run;
this.onRunError = data.onRunError || this.onRunError;
this.onSuccess = data.onSuccess || this.onSuccess;
this.onValueError = data.onValueError || this.onValueError;
this.merge(data);
}
get _optionsKey() {
return (this._options) ? this._options.map((x) => x.key).join(':') : '';
}
get fullName() {
return this.name;
}
get hash() {
return Crypto.createHash('md5').update(this.key).digest('hex');
}
get hasRun() {
if (this.isGroup && this._options) {
return this._options.every((option) => option.hasRun);
}
return typeof (this.run) === 'function';
}
get isGroup() {
if (this._options) {
return this._options.some((option) => option.isSubCommand || option.isSubCommandGroup);
}
return false;
}
get isContextCommand() {
return this.isContextCommandMessage || this.isContextCommandUser;
}
get isContextCommandMessage() {
return this.type === constants_1.ApplicationCommandTypes.MESSAGE;
}
get isContextCommandUser() {
return this.type === constants_1.ApplicationCommandTypes.USER;
}
get isSlashCommand() {
return this.type === constants_1.ApplicationCommandTypes.CHAT_INPUT;
}
get key() {
return `${this.name}-${this.description}-${this.type}-${this._optionsKey}`;
}
get length() {
return this.description.length + this.name.length + this.lengthOptions;
}
get lengthOptions() {
if (this._options) {
return this._options.reduce((x, option) => {
return x + option.length;
}, 0);
}
return 0;
}
get options() {
return (this._options) ? this._options.toArray() : this._options;
}
set options(value) {
if (value) {
if (!this._options) {
this._options = new basecollection_1.BaseCollection();
}
this._options.clear();
for (let option of value) {
this._options.set(option.name, option);
}
}
else {
this._options = undefined;
}
}
getInvoker(data) {
if (this.name === data.name) {
if (data.options && data.options.some((option) => option.isSubCommand || option.isSubCommandGroup)) {
return this.getInvokerOption(data.options);
}
return this;
}
return null;
}
getInvokerOption(options) {
if (this._options) {
for (let [name, option] of options) {
if (!this._options.has(name)) {
return null;
}
const x = this._options.get(name);
if (x.isSubCommand || x.isSubCommandGroup) {
return x.getInvoker(option);
}
}
}
return null;
}
_transferValuesToChildren() {
if (this._options) {
for (let [name, option] of this._options) {
option._transferValuesToChildren(this);
}
}
}
mergeValue(key, value) {
switch (key) {
case constants_1.DiscordKeys.IDS:
{
this.ids = new basecollection_1.BaseCollection(value);
}
;
return;
case constants_1.DiscordKeys.OPTIONS:
{
if (value) {
if (!this._options) {
this._options = new basecollection_1.BaseCollection();
}
this._options.clear();
for (let raw of value) {
let option;
if (typeof (raw) === 'function') {
option = new raw();
}
else if (raw instanceof InteractionCommandOption) {
option = raw;
}
else {
option = new InteractionCommandOption(raw);
}
option._transferValuesToChildren(this);
this._options.set(option.name, option);
}
}
else {
this._options = undefined;
}
}
;
return;
}
return super.mergeValue(key, value);
}
}
exports.InteractionCommand = InteractionCommand;
const keysInteractionCommandOption = new baseset_1.BaseSet([
constants_1.DiscordKeys.CHOICES,
constants_1.DiscordKeys.DESCRIPTION,
constants_1.DiscordKeys.NAME,
constants_1.DiscordKeys.OPTIONS,
constants_1.DiscordKeys.REQUIRED,
constants_1.DiscordKeys.TYPE,
]);
class InteractionCommandOption extends basestructure_1.Structure {
constructor(data = {}) {
super();
this._keys = keysInteractionCommandOption;
this.description = '';
this.name = '';
this.type = constants_1.ApplicationCommandOptionTypes.STRING;
this.metadata = {};
this.disableDm = (data.disableDm !== undefined) ? !!data.disableDm : this.disableDm;
this.label = data.label || this.label;
this.metadata = Object.assign(this.metadata, data.metadata);
this.permissions = (data.permissions) ? data.permissions.map((x) => BigInt(x)) : undefined;
this.permissionsClient = (data.permissionsClient) ? data.permissionsClient.map((x) => BigInt(x)) : undefined;
this.permissionsIgnoreClientOwner = (data.permissionsIgnoreClientOwner !== undefined) ? !!data.permissionsIgnoreClientOwner : undefined;
this.triggerLoadingAfter = (data.triggerLoadingAfter !== undefined) ? data.triggerLoadingAfter : this.triggerLoadingAfter;
this.triggerLoadingAsEphemeral = (data.triggerLoadingAsEphemeral !== undefined) ? data.triggerLoadingAsEphemeral : this.triggerLoadingAsEphemeral;
if (data.ratelimit || data.ratelimits) {
if (!this.ratelimits) {
this.ratelimits = [];
}
if (data.ratelimit) {
this.ratelimits.push(new commandratelimit_1.CommandRatelimit(data.ratelimit, this));
}
if (data.ratelimits) {
for (let rOptions of data.ratelimits) {
if (typeof (rOptions.type) === 'string') {
const rType = (rOptions.type || '').toLowerCase();
if (this.ratelimits.some((ratelimit) => ratelimit.type === rType)) {
throw new Error(`Ratelimit with type ${rType} already exists`);
}
}
this.ratelimits.push(new commandratelimit_1.CommandRatelimit(rOptions, this));
}
}
}
if (data.default !== undefined) {
this.default = data.default;
}
if (typeof (data.value) === 'function') {
this.value = data.value;
}
if (data._file) {
this._file = data._file;
}
Object.defineProperties(this, {
_file: { configurable: true, writable: false },
parent: { configurable: true, writable: false },
});
this.onDmBlocked = data.onDmBlocked || this.onDmBlocked;
this.onLoadingTrigger = data.onLoadingTrigger || this.onLoadingTrigger;
this.onBefore = data.onBefore || this.onBefore;
this.onBeforeRun = data.onBeforeRun || this.onBeforeRun;
this.onCancel = data.onCancel || this.onCancel;
this.onCancelRun = data.onCancelRun || this.onCancelRun;
this.onError = data.onError || this.onError;
this.onPermissionsFail = data.onPermissionsFail || this.onPermissionsFail;
this.onPermissionsFailClient = data.onPermissionsFailClient || this.onPermissionsFailClient;
this.onRatelimit = data.onRatelimit || this.onRatelimit;
this.run = data.run || this.run;
this.onRunError = data.onRunError || this.onRunError;
this.onSuccess = data.onSuccess || this.onSuccess;
this.onValueError = data.onValueError || this.onValueError;
if (typeof (this.run) === 'function') {
this.type = constants_1.ApplicationCommandOptionTypes.SUB_COMMAND;
}
this.merge(data);
}
get _choicesKey() {
return (this.choices) ? this.choices.map((x) => x.key).join(':') : '';
}
get _optionsKey() {
return (this._options) ? this._options.map((x) => x.key).join(':') : '';
}
get fullName() {
if (this.parent) {
return `${this.parent.fullName} ${this.name}`;
}
return this.name;
}
get hasRun() {
if (this.isSubCommand) {
return typeof (this.run) === 'function';
}
else if (this.isSubCommandGroup) {
if (this._options) {
return this._options.every((option) => option.hasRun);
}
return false;
}
return true;
}
get isSubCommand() {
return this.type === constants_1.ApplicationCommandOptionTypes.SUB_COMMAND;
}
get isSubCommandGroup() {
return this.type === constants_1.ApplicationCommandOptionTypes.SUB_COMMAND_GROUP;
}
get key() {
return `${this.name}-${this.description}-${this.type}-${!!this.required}-${this._optionsKey}-${this._choicesKey}`;
}
get length() {
return this.description.length + this.name.length + this.lengthOptions;
}
get lengthChoices() {
if (this.choices) {
return this.choices.reduce((x, choice) => {
if (this.type === constants_1.ApplicationCommandOptionTypes.INTEGER) {
return choice.name.length;
}
return choice.length;
}, 0);
}
return 0;
}
get lengthOptions() {
if (this._options) {
return this._options.reduce((x, option) => {
return x + option.length;
}, 0);
}
return 0;
}
get options() {
return (this._options) ? this._options.toArray() : this._options;
}
set options(value) {
if (value) {
if (!this._options) {
this._options = new basecollection_1.BaseCollection();
}
this._options.clear();
for (let option of value) {
option._transferValuesToChildren(this);
this._options.set(option.name, option);
}
if (this._options.some((option) => option.isSubCommand)) {
this.type = constants_1.ApplicationCommandOptionTypes.SUB_COMMAND_GROUP;
}
}
else {
this._options = undefined;
}
}
getInvoker(option) {
if (this.type === option.type && this.name === option.name) {
if (this.isSubCommandGroup) {
if (option.options && this._options) {
for (let [name, x] of option.options) {
if (!this._options.has(name)) {
return null;
}
const localCommand = this._options.get(name);
if (localCommand.isSubCommand || localCommand.isSubCommandGroup) {
return localCommand.getInvoker(x);
}
}
}
}
return this;
}
return null;
}
addChoice(name, value) {
if (!this.choices) {
this.choices = [];
}
let choice;
if (typeof (name) === 'object') {
choice = (name instanceof InteractionCommandOptionChoice) ? name : new InteractionCommandOptionChoice(name);
}
else {
choice = new InteractionCommandOptionChoice({ name, value });
}
this.choices.push(choice);
return choice;
}
addOption(value) {
if (!this.options) {
this.options = [];
}
let option;
if (typeof (value) === 'function') {
option = new value();
}
else if (value instanceof InteractionCommandOption) {
option = value;
}
else {
option = new InteractionCommandOption(value);
}
this.options.push(option);
return option;
}
setChoices(value = []) {
this.mergeValue(constants_1.DiscordKeys.CHOICES, value);
return this;
}
setDescription(value) {
this.mergeValue(constants_1.DiscordKeys.DESCRIPTION, value);
return this;
}
setName(value) {
this.mergeValue(constants_1.DiscordKeys.NAME, value);
return this;
}
setOptions(value = []) {
this.mergeValue(constants_1.DiscordKeys.OPTIONS, value);
return this;
}
setRequired(value) {
this.mergeValue(constants_1.DiscordKeys.REQUIRED, value);
return this;
}
setType(value) {
this.mergeValue(constants_1.DiscordKeys.TYPE, value);
return this;
}
_transferValuesToChildren(parent) {
Object.defineProperty(this, 'parent', { value: parent });
if (this.isSubCommand || this.isSubCommandGroup) {
for (let name of ON_FUNCTION_NAMES) {
if (typeof (this[name]) !== 'function') {
this[name] = parent[name];
}
}
for (let name of SET_VARIABLE_NAMES) {
if (this[name] === undefined) {
switch (name) {
case 'ratelimits':
{
if (parent.ratelimits && parent.ratelimits.length) {
this.ratelimits = [];
for (let ratelimit of parent.ratelimits) {
this.ratelimits.push(new commandratelimit_1.CommandRatelimit(ratelimit, this));
}
}
}
;
break;
default:
{
this[name] = parent[name];
}
;
}
}
}
if (this.isSubCommandGroup && this._options) {
for (let [name, option] of this._options) {
option._transferValuesToChildren(this);
}
}
}
}
mergeValue(key, value) {
switch (key) {
case constants_1.DiscordKeys.CHOICES:
{
if (value) {
if (this.choices) {
this.choices.length = 0;
}
else {
this.choices = [];
}
for (let raw of value) {
const choice = new InteractionCommandOptionChoice(raw);
this.choices.push(choice);
}
}
else {
this.choices = value;
}
}
;
return;
case constants_1.DiscordKeys.OPTIONS:
{
if (value) {
if (!this._options) {
this._options = new basecollection_1.BaseCollection();
}
this._options.clear();
for (let raw of value) {
let option;
if (typeof (raw) === 'function') {
option = new raw();
}
else if (raw instanceof InteractionCommandOption) {
option = raw;
}
else {
option = new InteractionCommandOption(raw);
}
option._transferValuesToChildren(this);
this._options.set(option.name, option);
}
this.type = constants_1.ApplicationCommandOptionTypes.SUB_COMMAND;
if (this._options.some((option) => option.isSubCommand)) {
this.type = constants_1.ApplicationCommandOptionTypes.SUB_COMMAND_GROUP;
}
}
else {
this._options = undefined;
}
}
;
return;
case constants_1.DiscordKeys.TYPE:
{
if (typeof (value) === 'string') {
value = constants_1.ApplicationCommandOptionTypes[value.toUpperCase()];
}
else if (typeof (value) === 'number') {
// pass
}
else {
switch (value) {
case Boolean:
value = constants_1.ApplicationCommandOptionTypes.BOOLEAN;
break;
case Number:
value = constants_1.ApplicationCommandOptionTypes.INTEGER;
break;
case String:
value = constants_1.ApplicationCommandOptionTypes.STRING;
break;
}
}
}
;
break;
}
return super.mergeValue(key, value);
}
}
exports.InteractionCommandOption = InteractionCommandOption;
const keysInteractionCommandOptionChoice = new baseset_1.BaseSet([
constants_1.DiscordKeys.NAME,
constants_1.DiscordKeys.VALUE,
]);
class InteractionCommandOptionChoice extends basestructure_1.Structure {
constructor(data = {}) {
super();
this._keys = keysInteractionCommandOptionChoice;
this.name = '';
this.value = '';
this.merge(data);
}
get key() {
return `${this.name}-${this.value}-${typeof (this.value)}`;
}
get length() {
if (typeof (this.value) === 'string') {
return this.name.length + this.value.length;
}
return this.name.length;
}
}
exports.InteractionCommandOptionChoice = InteractionCommandOptionChoice;