discord-multipurpose-bot/commands/admin/music.js
Ayden cb5a906850
Some checks are pending
Docker / build (push) Waiting to run
Feat/Add Music Commands (#1)
* add simple music functionality

* update workflow

* update Dockerfile

* update Dockerfile

* update Dockerfile

* update Dockerfile

* add few more music commands

* add lyrics command

* update lyrics command

* add loop, and add categories to all commands

* change discord status

* seperate distube and change startup console theme

* Update README

* UPDATE LICENSE file

* fix docker compose image, add better error handling for distube and update tagging workflow

* switch to node-alpine image for docker

* switch to node-alpine image for docker

* update ascii

* music commands imporvements, implement live lyrics, some guards and bot leaving on empty

* use ffmpeg package rather than ffmpeg-static
2025-09-21 01:26:18 +01:00

178 lines
5.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const { SlashCommandBuilder, PermissionFlagsBits } = require("discord.js");
const { ensure, set } = require("../../utils/musicSettings");
function ok(s) {
return `${s}`;
}
function err(s) {
return `${s}`;
}
module.exports = {
data: new SlashCommandBuilder()
.setName("music")
.setDescription("Configure music settings for this server.")
.setDefaultMemberPermissions(PermissionFlagsBits.ManageGuild)
.addSubcommand((sc) =>
sc.setName("show").setDescription("Show current music settings.")
)
.addSubcommand((sc) =>
sc
.setName("set")
.setDescription("Set basic music defaults.")
.addIntegerOption((o) =>
o.setName("volume").setDescription("Default volume (0200)")
)
.addBooleanOption((o) =>
o
.setName("autoplay")
.setDescription("Autoplay when queue ends (true/false)")
)
.addIntegerOption((o) =>
o.setName("maxqueue").setDescription("Max queue size (15000)")
)
.addIntegerOption((o) =>
o
.setName("maxplaylist")
.setDescription("Max playlist import size (12000)")
)
)
.addSubcommand((sc) =>
sc
.setName("djrole-add")
.setDescription("Allow a role to use DJ commands.")
.addRoleOption((o) =>
o.setName("role").setDescription("Role").setRequired(true)
)
)
.addSubcommand((sc) =>
sc
.setName("djrole-remove")
.setDescription("Remove a DJ role.")
.addRoleOption((o) =>
o.setName("role").setDescription("Role").setRequired(true)
)
)
.addSubcommand((sc) =>
sc
.setName("channel-allow")
.setDescription(
"Restrict music commands to a text channel (call multiple times)."
)
.addChannelOption((o) =>
o.setName("channel").setDescription("Text channel").setRequired(true)
)
)
.addSubcommand((sc) =>
sc
.setName("channel-remove")
.setDescription("Remove an allowed text channel.")
.addChannelOption((o) =>
o.setName("channel").setDescription("Text channel").setRequired(true)
)
)
.addSubcommand((sc) =>
sc
.setName("channel-clear")
.setDescription("Allow music commands in all text channels.")
),
category: "Admin",
async execute(interaction) {
await interaction.deferReply({ ephemeral: true });
const guildId = interaction.guildId;
const sub = interaction.options.getSubcommand();
const settings = await ensure(guildId);
if (sub === "show") {
const lines = [
`**Default Volume:** ${settings.defaultVolume}%`,
`**Autoplay:** ${settings.autoplay ? "On" : "Off"}`,
`**Max Queue:** ${settings.maxQueue}`,
`**Max Playlist Import:** ${settings.maxPlaylistImport}`,
`**DJ Roles:** ${
settings.djRoleIds.length
? settings.djRoleIds.map((id) => `<@&${id}>`).join(", ")
: "*none*"
}`,
`**Allowed Text Channels:** ${
settings.allowedTextChannelIds.length
? settings.allowedTextChannelIds.map((id) => `<#${id}>`).join(", ")
: "*all*"
}`,
];
return interaction.followUp(lines.join("\n"));
}
// mutate helpers
const update = {};
if (sub === "set") {
const vol = interaction.options.getInteger("volume");
const autoplay = interaction.options.getBoolean("autoplay");
const maxQ = interaction.options.getInteger("maxqueue");
const maxP = interaction.options.getInteger("maxplaylist");
if (vol !== null) {
if (vol < 0 || vol > 200)
return interaction.followUp(err("Volume must be 0200."));
update.defaultVolume = vol;
}
if (autoplay !== null) update.autoplay = autoplay;
if (maxQ !== null) {
if (maxQ < 1 || maxQ > 5000)
return interaction.followUp(err("Max queue must be 15000."));
update.maxQueue = maxQ;
}
if (maxP !== null) {
if (maxP < 1 || maxP > 2000)
return interaction.followUp(err("Max playlist must be 12000."));
update.maxPlaylistImport = maxP;
}
await set(guildId, update);
return interaction.followUp(ok("Settings updated."));
}
if (sub === "djrole-add") {
const role = interaction.options.getRole("role", true);
const setDoc = new Set(settings.djRoleIds || []);
setDoc.add(role.id);
await set(guildId, { djRoleIds: Array.from(setDoc) });
return interaction.followUp(ok(`Added DJ role ${role}.`));
}
if (sub === "djrole-remove") {
const role = interaction.options.getRole("role", true);
const setDoc = new Set(settings.djRoleIds || []);
setDoc.delete(role.id);
await set(guildId, { djRoleIds: Array.from(setDoc) });
return interaction.followUp(ok(`Removed DJ role ${role}.`));
}
if (sub === "channel-allow") {
const ch = interaction.options.getChannel("channel", true);
const setDoc = new Set(settings.allowedTextChannelIds || []);
setDoc.add(ch.id);
await set(guildId, { allowedTextChannelIds: Array.from(setDoc) });
return interaction.followUp(ok(`Allowed ${ch} for music commands.`));
}
if (sub === "channel-remove") {
const ch = interaction.options.getChannel("channel", true);
const setDoc = new Set(settings.allowedTextChannelIds || []);
setDoc.delete(ch.id);
await set(guildId, { allowedTextChannelIds: Array.from(setDoc) });
return interaction.followUp(ok(`Removed ${ch} from allowed channels.`));
}
if (sub === "channel-clear") {
await set(guildId, { allowedTextChannelIds: [] });
return interaction.followUp(
ok("Cleared channel restrictions (music commands allowed everywhere).")
);
}
return interaction.followUp(err("Unknown subcommand."));
},
};