import { Formatters } from 'discord.js'; import fetch from 'node-fetch'; import { createAudioResource, createAudioPlayer, joinVoiceChannel, NoSubscriberBehavior, AudioPlayerStatus } from '@discordjs/voice'; import { Readable } from 'node:stream'; const { inlineCode } = Formatters; const { Pause } = NoSubscriberBehavior; const { Idle } = AudioPlayerStatus; const base = 'https://api.streamelements.com/kappa/v2/speech?voice=Brian&text='; export default { data: { name: 'tts', description: "Plays the given text in Brian's TTS voice.", options: [ { name: 'text', description: 'The text to play.', required: true, type: 'STRING' } ] }, category: 'fun', async execute(interaction, client) { const { channel: voiceChannel } = interaction.member.voice; if (voiceChannel === null) { await interaction.reply({ content: 'You must be in a voice channel.', ephemeral: true }); return;, } const perms = voiceChannel .permissionsFor(client.user.id) ?.missing(['CONNECT', 'SPEAK']); if (perms?.length) { await interaction.reply({ content: `I must have both of the ${ inlineCode('Connect') } and ${ inlineCode('Speak') } permissions in your voice channel to perform this action.\n\nMissing: ${perms .map( (p) => inlineCode( p .replaceAll('_', ' ') .replace(/\b\w/g, (l) => l.toUpperCase()) ) ) .join(', ')}`, ephemeral: true }); return; } await interaction.deferReply(); const text = encodeURIComponent(interaction.options.getString('text')); const buffer = await fetch(base + text) .then((res) => res.arrayBuffer()) .then((arrayBuffer) => Buffer.from(arrayBuffer)) .catch(() => null); if (buffer === null) { await interaction.followUp({ content: "The StreamElements API doesn't seem to be working currently, try again later.", ephemeral: true }); return; } const connection = await joinVoiceChannel({ channelId: voiceChannel.id, guildId: interaction.guild.id, adapterCreator: interaction.guild.voiceAdapterCreator }); await interaction.followUp({ content: 'Now playing your text.' }); const player = createAudioPlayer({ behaviors: { noSubscriber: Pause } }); connection.subscribe(player); player.play(createAudioResource(Readable.from(buffer))); player.on('error', async () => { await interaction.followUp({ content: 'An error occured while playing your text.' }); player.stop(); connection.destroy(); }); player.on(Idle, () => { player.stop(); connection.destroy(); }); } };