Compare commits

..

3 commits

Author SHA1 Message Date
murm
9be36e7199 removed music commands 2023-03-18 20:01:28 -04:00
murm
76bc07543d removed soundboard cmds 2023-03-18 20:00:51 -04:00
murm
102c3f097b added help cmd, and helper function to misc 2023-03-18 20:00:37 -04:00
27 changed files with 37 additions and 618 deletions

View file

@ -1,15 +1,35 @@
// import { Constants } from "oceanic.js"; // import { Constants } from "oceanic.js";
// import database from "../../utils/database.js"; // import database from "../../utils/database.js";
// import * as collections from "../../utils/collections.js"; import * as collections from "../../utils/collections.js";
// import { random } from "../../utils/misc.js"; import { htmlescape } from "../../utils/misc.js";
// import paginator from "../../utils/pagination/pagination.js"; // import paginator from "../../utils/pagination/pagination.js";
// import * as help from "../../utils/help.js"; import * as help from "../../utils/help.js";
import Command from "../../classes/command.js"; import Command from "../../classes/command.js";
// const tips = ["You can change the bot's prefix using the prefix command.", "Image commands also work with images previously posted in that channel.", "You can use the tags commands to save things for later use.", "You can visit https://esmbot.net/help.html for a web version of this command list.", "You can view a command's aliases by putting the command name after the help command (e.g. help image).", "Parameters wrapped in [] are required, while parameters wrapped in {} are optional.", "esmBot is hosted and paid for completely out-of-pocket by the main developer. If you want to support development, please consider donating! https://patreon.com/TheEssem"]; // const tips = ["You can change the bot's prefix using the prefix command.", "Image commands also work with images previously posted in that channel.", "You can use the tags commands to save things for later use.", "You can visit https://esmbot.net/help.html for a web version of this command list.", "You can view a command's aliases by putting the command name after the help command (e.g. help image).", "Parameters wrapped in [] are required, while parameters wrapped in {} are optional.", "esmBot is hosted and paid for completely out-of-pocket by the main developer. If you want to support development, please consider donating! https://patreon.com/TheEssem"];
class HelpCommand extends Command { class HelpCommand extends Command {
async run() { async run() {
return { html: "<h1>There are no mrmBot Docs Yet</h1>In the meantime, please refer to https://esmbot.net/help.html" }; let html;
if (this.args.length !== 0) {
if (collections.commands.has(this.args[0].toLowerCase())) {
const command = collections.aliases.get(this.args[0].toLowerCase()) ?? this.args[0].toLowerCase();
const info = collections.info.get(command);
// TODO: room-specific prefix
const prefix = htmlescape(process.env.PREFIX);
html = `<h3><ins>mrmBot Help</ins></h3><h6><code>${prefix}${command}</code></h6>${htmlescape(info.description)}`
return { html: html }
}
if (help.categories[this.args[0].toLowerCase()]) {
}
}
html = `<h2>mrmBot Help</h2><table><tr><th>Command</th><th>Description</th></tr>`
for (const [command] of collections.commands) {
const description = collections.info.get(command).description;
html = html + `<tr><td>${command}</td><td>${description}</td></tr>`
}
html = html + "</table>"
return { html: html }
// return { html: "<h1>There are no mrmBot Docs Yet</h1>In the meantime, please refer to https://esmbot.net/help.html" };
} }

View file

@ -1,60 +0,0 @@
import { players } from "../../utils/soundplayer.js";
import MusicCommand from "../../classes/musicCommand.js";
class HostCommand extends MusicCommand {
async run() {
this.success = false;
if (!this.guild) return "This command only works in servers!";
if (!this.member.voiceState) return "You need to be in a voice channel first!";
if (!this.guild.voiceStates.has(this.client.user.id)) return "I'm not in a voice channel!";
if (!this.connection) return "I haven't completely connected yet!";
if (this.connection.host !== this.author && !process.env.OWNER.split(",").includes(this.connection.host)) return "Only the current voice session host can choose another host!";
const input = this.options.user ?? this.args.join(" ");
if (input?.trim()) {
let user;
if (this.type === "classic") {
const getUser = this.message.mentions.users.length >= 1 ? this.message.mentions.users[0] : this.client.users.get(input);
if (getUser) {
user = getUser;
} else if (input.match(/^<?[@#]?[&!]?\d+>?$/) && input >= 21154535154122752n) {
try {
user = await this.client.rest.users.get(input);
} catch {
// no-op
}
} else {
const userRegex = new RegExp(input.split(" ").join("|"), "i");
const member = this.client.users.find(element => {
return userRegex.test(element.username);
});
user = member;
}
} else {
user = input;
}
if (!user) return "I can't find that user!";
if (user.bot) return "This is illegal, you know.";
const member = this.guild.members.get(user.id);
if (!member) return "That user isn't in this server!";
const object = this.connection;
object.host = member.id;
players.set(this.guildID, object);
this.success = true;
return `🔊 ${member.mention} is the new voice channel host.`;
} else {
const member = this.guild.members.get(players.get(this.guild.id).host);
this.success = true;
return `🔊 The current voice channel host is **${member?.username}#${member?.discriminator}**.`;
}
}
static flags = [{
name: "user",
type: 6,
description: "The user you want the new host to be"
}];
static description = "Gets or changes the host of the current voice session";
static aliases = ["sethost"];
}
export default HostCommand;

View file

@ -1,23 +0,0 @@
import { players } from "../../utils/soundplayer.js";
import MusicCommand from "../../classes/musicCommand.js";
class LoopCommand extends MusicCommand {
async run() {
this.success = false;
if (!this.guild) return "This command only works in servers!";
if (!this.member.voiceState) return "You need to be in a voice channel first!";
if (!this.guild.voiceStates.has(this.client.user.id)) return "I'm not in a voice channel!";
if (!this.connection) return "I haven't completely connected yet!";
if (this.connection.host !== this.author && !this.member.permissions.has("MANAGE_CHANNELS")) return "Only the current voice session host can loop the music!";
const object = this.connection;
object.loop = !object.loop;
players.set(this.guild.id, object);
this.success = true;
return object.loop ? "🔊 The player is now looping." : "🔊 The player is no longer looping.";
}
static description = "Loops the music";
static aliases = ["toggleloop", "repeat"];
}
export default LoopCommand;

View file

@ -1,48 +0,0 @@
import Command from "../../classes/command.js";
import { commands, aliases, info, categories } from "../../utils/collections.js";
// all-in-one music command
class MusicAIOCommand extends Command {
async run() {
let cmd = this.type === "classic" ? this.args[0] : this.optionsArray[0].name;
if (cmd === "music" || this.constructor.aliases.includes(cmd)) return "https://esmbot.net/robotdance.gif";
// await this.acknowledge();
if (this.type === "classic") {
this.origOptions.args.shift();
} else {
this.origOptions.interaction.data.options.raw = this.origOptions.interaction.data.options.raw[0].options;
}
if (aliases.has(cmd)) cmd = aliases.get(cmd);
if (commands.has(cmd) && info.get(cmd).category === "music") {
const command = commands.get(cmd);
const inst = new command(this.client, this.origOptions);
const result = await inst.run();
this.success = inst.success;
return result;
} else {
this.success = false;
return "That isn't a valid music command!";
}
}
static postInit() {
this.flags = [];
for (const cmd of categories.get("music")) {
if (cmd === "music") continue;
const cmdInfo = info.get(cmd);
this.flags.push({
name: cmd,
type: 1,
description: cmdInfo.description,
options: cmdInfo.flags
});
}
return this;
}
static description = "Handles music playback";
static aliases = ["m"];
static directAllowed = false;
}
export default MusicAIOCommand;

View file

@ -1,51 +0,0 @@
import format from "format-duration";
import MusicCommand from "../../classes/musicCommand.js";
class NowPlayingCommand extends MusicCommand {
async run() {
this.success = false;
if (!this.guild) return "This command only works in servers!";
if (!this.member.voiceState) return "You need to be in a voice channel first!";
if (!this.guild.voiceStates.has(this.client.user.id)) return "I'm not in a voice channel!";
if (!this.connection) return "I haven't completely connected yet!";
const player = this.connection.player;
if (!player) return "I'm not playing anything!";
const track = await player.node.rest.decode(player.track);
const parts = Math.floor((player.position / track.length) * 10);
this.success = true;
return {
embeds: [{
color: 16711680,
author: {
name: "Now Playing",
iconURL: this.client.user.avatarURL()
},
fields: [{
name: " Title",
value: track.title ? track.title : "Unknown"
},
{
name: "🎤 Artist",
value: track.author ? track.author : "Unknown"
},
{
name: "💬 Channel",
value: (this.guild.channels.get(this.member.voiceState.channelID) ?? await this.client.rest.channels.get(this.member.voiceState.channelID)).name
},
{
name: "🌐 Node",
value: player.node ? player.node.name : "Unknown"
},
{
name: `${"▬".repeat(parts)}🔘${"▬".repeat(10 - parts)}`,
value: `${format(player.position)}/${track.isStream ? "∞" : format(track.length)}`
}]
}]
};
}
static description = "Shows the currently playing song";
static aliases = ["playing", "np", "current"];
}
export default NowPlayingCommand;

View file

@ -1,41 +0,0 @@
import { play } from "../../utils/soundplayer.js";
import MusicCommand from "../../classes/musicCommand.js";
const prefixes = ["scsearch:", "spsearch:", "sprec:", "amsearch:", "dzsearch:", "dzisrc:"];
if (process.env.YT_DISABLED !== "true") prefixes.push("ytsearch:", "ytmsearch:");
class PlayCommand extends MusicCommand {
async run() {
const input = this.options.query ?? this.args.join(" ");
if (!input && ((!this.message || this.message?.attachments.size <= 0))) {
this.success = false;
return "You need to provide what you want to play!";
}
let query = input ? input.trim() : "";
const attachment = this.type === "classic" ? this.message.attachments.first() : null;
if (query.startsWith("||") && query.endsWith("||")) {
query = query.substring(2, query.length - 2);
}
if (query.startsWith("<") && query.endsWith(">")) {
query = query.substring(1, query.length - 1);
}
try {
const url = new URL(query);
return play(this.client, url, { channel: this.channel, member: this.member, type: this.type, interaction: this.interaction }, true);
} catch {
const search = prefixes.some(v => query.startsWith(v)) ? query : !query && attachment ? attachment.url : (process.env.YT_DISABLED !== "true" ? `ytsearch:${query}` : `dzsearch:${query}`);
return play(this.client, search, { channel: this.channel, member: this.member, type: this.type, interaction: this.interaction }, true);
}
}
static flags = [{
name: "query",
type: 3,
description: "An audio search query or URL",
required: true
}];
static description = "Plays a song or adds it to the queue";
static aliases = ["p"];
static arguments = ["[url]"];
}
export default PlayCommand;

View file

@ -1,65 +0,0 @@
import { request } from "undici";
import format from "format-duration";
import { nodes } from "../../utils/soundplayer.js";
import paginator from "../../utils/pagination/pagination.js";
import MusicCommand from "../../classes/musicCommand.js";
class QueueCommand extends MusicCommand {
async run() {
this.success = false;
if (!this.guild) return "This command only works in servers!";
if (!this.member.voiceState) return "You need to be in a voice channel first!";
if (!this.guild.voiceStates.has(this.client.user.id)) return "I'm not in a voice channel!";
if (!this.channel.permissionsOf(this.client.user.id.toString()).has("EMBED_LINKS")) return "I don't have the `Embed Links` permission!";
const player = this.connection;
if (!player) return "I haven't completely connected yet!";
const node = nodes.filter((val) => val.name === player.player.node.name)[0];
const tracks = await request(`http://${node.url}/decodetracks`, { method: "POST", body: JSON.stringify(this.queue), headers: { authorization: node.auth, "content-type": "application/json" } }).then(res => res.body.json());
const trackList = [];
const firstTrack = tracks.shift();
for (const [i, track] of tracks.entries()) {
trackList.push(`${i + 1}. ${track.info.author !== "" ? track.info.author : "(blank)"} - **${track.info.title !== "" ? track.info.title : "(blank)"}** (${track.info.isStream ? "∞" : format(track.info.length)})`);
}
const pageSize = 5;
const embeds = [];
const groups = trackList.map((item, index) => {
return index % pageSize === 0 ? trackList.slice(index, index + pageSize) : null;
}).filter(Boolean);
if (groups.length === 0) groups.push("del");
for (const [i, value] of groups.entries()) {
embeds.push({
embeds: [{
author: {
name: "Queue",
iconURL: this.client.user.avatarURL()
},
color: 16711680,
footer: {
text: `Page ${i + 1} of ${groups.length}`
},
fields: [{
name: "🎶 Now Playing",
value: `${firstTrack.info.author !== "" ? firstTrack.info.author : "(blank)"} - **${firstTrack.info.title !== "" ? firstTrack.info.title : "(blank)"}** (${firstTrack.info.isStream ? "∞" : format(firstTrack.info.length)})`
}, {
name: "🔁 Looping?",
value: player.loop ? "Yes" : "No"
}, {
name: "🌐 Node",
value: player.player.node ? player.player.node.name : "Unknown"
}, {
name: "🗒️ Queue",
value: value !== "del" ? value.join("\n") : "There's nothing in the queue!"
}]
}]
});
}
if (embeds.length === 0) return "There's nothing in the queue!";
this.success = true;
return paginator(this.client, { type: this.type, message: this.message, interaction: this.interaction, channel: this.channel, author: this.author }, embeds);
}
static description = "Shows the current queue";
static aliases = ["q"];
}
export default QueueCommand;

View file

@ -1,33 +0,0 @@
import { queues } from "../../utils/soundplayer.js";
import MusicCommand from "../../classes/musicCommand.js";
class RemoveCommand extends MusicCommand {
async run() {
this.success = false;
if (!this.guild) return "This command only works in servers!";
if (!this.member.voiceState) return "You need to be in a voice channel first!";
if (!this.guild.voiceStates.has(this.client.user.id)) return "I'm not in a voice channel!";
if (!this.connection) return "I haven't completely connected yet!";
if (this.connection.host !== this.author && !process.env.OWNER.split(",").includes(this.connection.host)) return "Only the current voice session host can remove songs from the queue!";
const pos = parseInt(this.options.position ?? this.args[0]);
if (isNaN(pos) || pos > this.queue.length || pos < 1) return "That's not a valid position!";
const removed = this.queue.splice(pos, 1);
if (removed.length === 0) return "That's not a valid position!";
const track = await this.connection.player.node.rest.decode(removed[0]);
queues.set(this.guildID, this.queue);
this.success = true;
return `🔊 The song \`${track.title ? track.title : "(blank)"}\` has been removed from the queue.`;
}
static flags = [{
name: "position",
type: 4,
description: "The queue position you want to remove",
min_value: 1,
required: true
}];
static description = "Removes a song from the queue";
static aliases = ["rm"];
}
export default RemoveCommand;

View file

@ -1,38 +0,0 @@
import MusicCommand from "../../classes/musicCommand.js";
class SeekCommand extends MusicCommand {
async run() {
this.success = false;
if (!this.guild) return "This command only works in servers!";
if (!this.member.voiceState) return "You need to be in a voice channel first!";
if (!this.guild.voiceStates.has(this.client.user.id)) return "I'm not in a voice channel!";
if (!this.connection) return "I haven't completely connected yet!";
if (this.connection.host !== this.author) return "Only the current voice session host can seek the music!";
const player = this.connection.player;
const track = await player.node.rest.decode(player.track);
if (!track.isSeekable) return "This track isn't seekable!";
const pos = this.options.position ?? this.args[0];
let seconds;
if (typeof pos === "string" && pos.includes(":")) {
seconds = +(pos.split(":").reduce((acc, time) => (60 * acc) + +time));
} else {
seconds = parseFloat(pos);
}
if (isNaN(seconds) || (seconds * 1000) > track.length || (seconds * 1000) < 0) return "That's not a valid position!";
player.seekTo(seconds * 1000);
this.success = true;
return `🔊 Seeked track to ${seconds} second(s).`;
}
static flags = [{
name: "position",
type: 3,
description: "Seek to this position",
required: true
}];
static description = "Seeks to a different position in the music";
static aliases = ["pos"];
static arguments = ["[seconds]"];
}
export default SeekCommand;

View file

@ -1,23 +0,0 @@
import { players } from "../../utils/soundplayer.js";
import MusicCommand from "../../classes/musicCommand.js";
class ShuffleCommand extends MusicCommand {
async run() {
this.success = false;
if (!this.guild) return "This command only works in servers!";
if (!this.member.voiceState) return "You need to be in a voice channel first!";
if (!this.guild.voiceStates.has(this.client.user.id)) return "I'm not in a voice channel!";
if (!this.connection) return "I haven't completely connected yet!";
if (this.connection.host !== this.author) return "Only the current voice session host can shuffle the music!";
const object = this.connection;
object.shuffle = !object.shuffle;
players.set(this.guildID, object);
this.success = true;
return object.shuffle ? "🔊 The player is now shuffling." : "🔊 The player is no longer shuffling.";
}
static description = "Shuffles the music";
static aliases = ["toggleshuffle"];
}
export default ShuffleCommand;

View file

@ -1,41 +0,0 @@
import { skipVotes } from "../../utils/soundplayer.js";
import MusicCommand from "../../classes/musicCommand.js";
class SkipCommand extends MusicCommand {
async run() {
this.success = false;
if (!this.guild) return "This command only works in servers!";
if (!this.member.voiceState) return "You need to be in a voice channel first!";
if (!this.guild.voiceStates.has(this.client.user.id)) return "I'm not in a voice channel!";
const player = this.connection;
if (!player) return "I haven't completely connected yet!";
if (player.host !== this.author && !this.member.permissions.has("MANAGE_CHANNELS")) {
const votes = skipVotes.get(this.guild.id) ?? { count: 0, ids: [], max: Math.min(3, player.voiceChannel.voiceMembers.filter((i) => i.id !== this.client.user.id && !i.bot).length) };
if (votes.ids.includes(this.author)) return "You've already voted to skip!";
const newObject = {
count: votes.count + 1,
ids: [...votes.ids, this.author].filter(item => !!item),
max: votes.max
};
if (votes.count + 1 === votes.max) {
await player.player.stopTrack(this.guild.id);
skipVotes.set(this.guild.id, { count: 0, ids: [], max: Math.min(3, player.voiceChannel.voiceMembers.filter((i) => i.id !== this.client.user.id && !i.bot).length) });
this.success = true;
if (this.type === "application") return "🔊 The current song has been skipped.";
} else {
skipVotes.set(this.guild.id, newObject);
this.success = true;
return `🔊 Voted to skip song (${votes.count + 1}/${votes.max} people have voted).`;
}
} else {
await player.player.stopTrack();
this.success = true;
if (this.type === "application") return "🔊 The current song has been skipped.";
}
}
static description = "Skips the current song";
static aliases = ["forceskip", "s"];
}
export default SkipCommand;

View file

@ -1,28 +0,0 @@
import { manager, players, queues } from "../../utils/soundplayer.js";
import MusicCommand from "../../classes/musicCommand.js";
class StopCommand extends MusicCommand {
async run() {
this.success = false;
if (!this.guild) return "This command only works in servers!";
if (!this.member.voiceState) return "You need to be in a voice channel first!";
if (!this.guild.voiceStates.has(this.client.user.id)) return "I'm not in a voice channel!";
if (!this.connection) {
await manager.getNode().leaveChannel(this.guild.id);
this.success = true;
return "🔊 The current voice channel session has ended.";
}
if (this.connection.host !== this.author && !this.member.permissions.has("MANAGE_CHANNELS")) return "Only the current voice session host can stop the music!";
const connection = this.connection.player;
connection.node.leaveChannel(this.guild.id);
players.delete(this.guild.id);
queues.delete(this.guild.id);
this.success = true;
return `🔊 The voice channel session in \`${this.connection.voiceChannel.name}\` has ended.`;
}
static description = "Stops the music";
static aliases = ["disconnect"];
}
export default StopCommand;

View file

@ -1,21 +0,0 @@
import MusicCommand from "../../classes/musicCommand.js";
class ToggleCommand extends MusicCommand {
async run() {
this.success = false;
if (!this.guild) return "This command only works in servers!";
if (!this.member.voiceState) return "You need to be in a voice channel first!";
if (!this.guild.voiceStates.has(this.client.user.id)) return "I'm not in a voice channel!";
if (!this.connection) return "I haven't completely connected yet!";
if (this.connection.host !== this.author && !this.member.permissions.has("MANAGE_CHANNELS")) return "Only the current voice session host can pause/resume the music!";
const player = this.connection.player;
player.setPaused(!player.paused ? true : false);
this.success = true;
return `🔊 The player has been ${player.paused ? "paused" : "resumed"}.`;
}
static description = "Pauses/resumes the current song";
static aliases = ["pause", "resume"];
}
export default ToggleCommand;

View file

@ -1,9 +0,0 @@
import SoundboardCommand from "../../classes/soundboardCommand.js";
class BoiCommand extends SoundboardCommand {
static file = "./assets/audio/boi.ogg";
static description = "Plays the \"boi\" sound effect";
static aliases = ["boy", "neutron", "hugh"];
}
export default BoiCommand;

View file

@ -1,9 +0,0 @@
import SoundboardCommand from "../../classes/soundboardCommand.js";
class BoomCommand extends SoundboardCommand {
static file = "./assets/audio/boom.ogg";
static description = "Plays the Vine boom sound effect";
static aliases = ["thud", "vine"];
}
export default BoomCommand;

View file

@ -1,9 +0,0 @@
import SoundboardCommand from "../../classes/soundboardCommand.js";
class BruhCommand extends SoundboardCommand {
static file = "./assets/audio/bruh.ogg";
static description = "Plays the \"bruh\" sound effect";
static aliases = ["bro"];
}
export default BruhCommand;

View file

@ -1,9 +0,0 @@
import SoundboardCommand from "../../classes/soundboardCommand.js";
class DamnDanielCommand extends SoundboardCommand {
static file = "./assets/audio/damndaniel.ogg";
static description = "Plays the \"damn daniel\" sound effect";
static aliases = ["daniel", "damn"];
}
export default DamnDanielCommand;

View file

@ -1,8 +0,0 @@
import SoundboardCommand from "../../classes/soundboardCommand.js";
class ExplosionCommand extends SoundboardCommand {
static file = "./assets/audio/explosion.ogg";
static description = "Plays an explosion sound effect";
}
export default ExplosionCommand;

View file

@ -1,9 +0,0 @@
import SoundboardCommand from "../../classes/soundboardCommand.js";
class FakePingCommand extends SoundboardCommand {
static file = "./assets/audio/ping.ogg";
static description = "Plays a Discord ping sound effect";
static aliases = ["notification", "notif"];
}
export default FakePingCommand;

View file

@ -1,9 +0,0 @@
import SoundboardCommand from "../../classes/soundboardCommand.js";
class FartCommand extends SoundboardCommand {
static file = "./assets/audio/fart.ogg";
static description = "Plays a fart sound effect";
static aliases = ["toot"];
}
export default FartCommand;

View file

@ -1,9 +0,0 @@
import SoundboardCommand from "../../classes/soundboardCommand.js";
class FartReverbCommand extends SoundboardCommand {
static file = "./assets/audio/fart2.ogg";
static description = "Plays a fart sound effect with extra reverb";
static aliases = ["fart2"];
}
export default FartReverbCommand;

View file

@ -1,9 +0,0 @@
import SoundboardCommand from "../../classes/soundboardCommand.js";
class FBICommand extends SoundboardCommand {
static file = "./assets/audio/fbi.ogg";
static description = "Plays the \"FBI OPEN UP\" sound effect";
static aliases = ["openup"];
}
export default FBICommand;

View file

@ -1,9 +0,0 @@
import SoundboardCommand from "../../classes/soundboardCommand.js";
class MailCommand extends SoundboardCommand {
static file = "./assets/audio/mail.ogg";
static description = "Plays the \"You've got mail\" sound effect";
static aliases = ["yougotmail", "youvegotmail", "aol"];
}
export default MailCommand;

View file

@ -1,9 +0,0 @@
import SoundboardCommand from "../../classes/soundboardCommand.js";
class OofCommand extends SoundboardCommand {
static file = "./assets/audio/oof.ogg";
static description = "Plays the Roblox \"oof\" sound";
static aliases = ["roblox", "commitdie"];
}
export default OofCommand;

View file

@ -1,35 +0,0 @@
import { play } from "../../utils/soundplayer.js";
import Command from "../../classes/command.js";
import { sounds, info } from "../../utils/collections.js";
// all-in-one soundboard command
class SoundboardAIOCommand extends Command {
async run() {
const soundName = this.type === "classic" ? this.args[0] : this.optionsArray[0].name;
if (!sounds.has(soundName)) {
this.success = false;
return "You need to provide a sound to play!";
}
const name = sounds.get(soundName);
// await this.acknowledge();
return await play(this.client, name, { channel: this.channel, member: this.member, type: this.type, interaction: this.interaction });
}
static postInit() {
this.flags = [];
for (const sound of sounds.keys()) {
this.flags.push({
name: sound,
type: 1,
description: info.get(sound).description
});
}
return this;
}
static description = "Plays a sound effect";
static aliases = ["sound", "sb"];
static directAllowed = false;
}
export default SoundboardAIOCommand;

View file

@ -1,9 +0,0 @@
import SoundboardCommand from "../../classes/soundboardCommand.js";
class WinXPCommand extends SoundboardCommand {
static file = "./assets/audio/winxp.ogg";
static description = "Plays the Windows XP startup sound";
static aliases = ["windows", "xp"];
}
export default WinXPCommand;

View file

@ -20,6 +20,8 @@ const optionalReplace = (token) => {
return token === undefined || token === "" ? "" : (token === "true" || token === "false" ? token : "<redacted>"); return token === undefined || token === "" ? "" : (token === "true" || token === "false" ? token : "<redacted>");
}; };
// clean(text) to clean message of any private info or mentions // clean(text) to clean message of any private info or mentions
export function clean(text) { export function clean(text) {
if (typeof text !== "string") if (typeof text !== "string")
@ -63,6 +65,17 @@ export async function activityChanger(bot) {
setTimeout(() => activityChanger(bot), 900000); setTimeout(() => activityChanger(bot), 900000);
} }
export function htmlescape (s) {
let lookup = {
'&': "&amp;",
'"': "&quot;",
'\'': "&apos;",
'<': "&lt;",
'>': "&gt;"
};
return s.replace( /[&"'<>]/g, c => lookup[c] );
}
export async function checkBroadcast(bot) { export async function checkBroadcast(bot) {
if (!db) { if (!db) {
return; return;