Stop was advancing the queue, history overwrote the day file, and slash commands often never replied; soundboard clips now mix on top of the current track. Co-authored-by: Cursor <cursoragent@cursor.com>
133 lines
4.5 KiB
TypeScript
133 lines
4.5 KiB
TypeScript
import {
|
|
AutocompleteInteraction,
|
|
CacheType,
|
|
ChatInputCommandInteraction,
|
|
SlashCommandBuilder,
|
|
} from 'discord.js';
|
|
import {
|
|
addSound,
|
|
buildSoundboardMessage,
|
|
listSounds,
|
|
playById,
|
|
removeSound,
|
|
} from '../soundboard';
|
|
|
|
const name = "soundboard"
|
|
|
|
function register() {
|
|
return new SlashCommandBuilder()
|
|
.setName(name)
|
|
.setDescription('Soundboard — dźwięki na wierzchu muzyki')
|
|
.addSubcommand((sub) => sub
|
|
.setName("add")
|
|
.setDescription("Dodaj dźwięk (max 10s)")
|
|
.addAttachmentOption((option) => option
|
|
.setName("file")
|
|
.setDescription("Krótki plik audio")
|
|
.setRequired(true))
|
|
.addStringOption((option) => option
|
|
.setName("description")
|
|
.setDescription("Krótki opis na przycisku")
|
|
.setRequired(true)
|
|
.setMaxLength(40))
|
|
.addStringOption((option) => option
|
|
.setName("emoji")
|
|
.setDescription("Emoji do przycisku")
|
|
.setRequired(true)
|
|
.setMaxLength(32)))
|
|
.addSubcommand((sub) => sub
|
|
.setName("list")
|
|
.setDescription("Pokaż soundboard do klikania"))
|
|
.addSubcommand((sub) => sub
|
|
.setName("play")
|
|
.setDescription("Puść dźwięk z listy")
|
|
.addStringOption((option) => option
|
|
.setName("sound")
|
|
.setDescription("Który dźwięk")
|
|
.setRequired(true)
|
|
.setAutocomplete(true)))
|
|
.addSubcommand((sub) => sub
|
|
.setName("remove")
|
|
.setDescription("Usuń dźwięk")
|
|
.addStringOption((option) => option
|
|
.setName("sound")
|
|
.setDescription("Który dźwięk")
|
|
.setRequired(true)
|
|
.setAutocomplete(true)))
|
|
}
|
|
|
|
export async function handleSoundboardAutocomplete(interaction: AutocompleteInteraction<CacheType>) {
|
|
const focused = interaction.options.getFocused().toLowerCase();
|
|
const choices = listSounds()
|
|
.filter((sound) =>
|
|
sound.description.toLowerCase().includes(focused) ||
|
|
sound.emoji.includes(focused) ||
|
|
sound.id.startsWith(focused)
|
|
)
|
|
.slice(0, 25)
|
|
.map((sound) => ({
|
|
name: `${sound.emoji} ${sound.description}`.slice(0, 100),
|
|
value: sound.id,
|
|
}));
|
|
await interaction.respond(choices);
|
|
}
|
|
|
|
async function execute(interaction: ChatInputCommandInteraction<CacheType>) {
|
|
const sub = interaction.options.getSubcommand();
|
|
try {
|
|
if (sub === "add") {
|
|
await interaction.deferReply();
|
|
const file = interaction.options.getAttachment("file", true);
|
|
const description = interaction.options.getString("description", true);
|
|
const emoji = interaction.options.getString("emoji", true);
|
|
const sound = await addSound({
|
|
attachment: file,
|
|
description,
|
|
emoji,
|
|
user: interaction.user.username,
|
|
});
|
|
await interaction.editReply(`Dodane: ${sound.emoji} **${sound.description}**`);
|
|
return;
|
|
}
|
|
|
|
if (sub === "list") {
|
|
await interaction.reply(buildSoundboardMessage(0));
|
|
return;
|
|
}
|
|
|
|
if (sub === "play") {
|
|
await interaction.deferReply({ ephemeral: true });
|
|
const id = interaction.options.getString("sound", true);
|
|
const sound = await playById(id, interaction);
|
|
await interaction.editReply(`${sound.emoji} ${sound.description}`);
|
|
return;
|
|
}
|
|
|
|
if (sub === "remove") {
|
|
await interaction.deferReply({ ephemeral: true });
|
|
const id = interaction.options.getString("sound", true);
|
|
const removed = removeSound(id);
|
|
if (!removed) {
|
|
await interaction.editReply("Nie ma takiego dźwięku");
|
|
return;
|
|
}
|
|
await interaction.editReply(`Usunięte: ${removed.emoji} ${removed.description}`);
|
|
return;
|
|
}
|
|
} catch (error) {
|
|
console.error(error);
|
|
const message = error instanceof Error ? error.message : "Coś poszło nie tak :/";
|
|
if (interaction.deferred || interaction.replied) {
|
|
await interaction.editReply(message);
|
|
} else {
|
|
await interaction.reply({ content: message, ephemeral: true });
|
|
}
|
|
}
|
|
}
|
|
|
|
export default {
|
|
name,
|
|
register,
|
|
execute
|
|
}
|