const { ActionRowBuilder, AttachmentBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } = require("discord.js"); const { convertTime } = require("../../../functions/timeFormat.js"); const { Classic } = require("musicard"); module.exports = async (client, player, track) => { if (!player) return; const formatString = (str, maxLength) => (str.length > maxLength ? str.substr(0, maxLength - 3) + "..." : str); const trackTitle = formatString(track.title || "Unknown", 30).replace(/ - Topic$/, ""); const trackAuthor = formatString(track.author || "Unknown", 25).replace(/ - Topic$/, ""); const trackDuration = track.isStream ? "LIVE" : convertTime(track.duration); const playerEmoji = client.emoji.player; const musicard = await Classic({ thumbnailImage: `https://img.youtube.com/vi/${track.identifier}/maxresdefault.jpg`, backgroundColor: "#070707", progress: 10, progressBarColor: "#FF7A00", progressColor: "#FF7A00", name: trackTitle, nameColor: "#FF7A00", author: trackAuthor, authorColor: "#FFFFFF", startTime: "0:00", endTime: track.isStream ? "LIVE" : convertTime(track.duration), timeColor: "#FF7A00", }); const buffer = await musicard.build(); const attachment = new AttachmentBuilder(buffer, { name: `musicard.png` }); const trackMsg = new EmbedBuilder() .setAuthor({ name: player.paused ? "Song Paused" : "Now Playing", iconURL: client.user.displayAvatarURL() }) .setColor(client.config.embedColor) .setDescription(`**[${trackTitle} - ${trackAuthor}](${track.uri})**`) .setThumbnail(track.artworkUrl || `https://img.youtube.com/vi/${track.identifier}/maxresdefault.jpg`) .addFields( { name: "Duration", value: `\`${trackDuration}\``, inline: true }, { name: "Requester", value: `${track.requester}`, inline: true }, { name: "Source", value: `${capitalize(track.source)}`, inline: true } ) .setImage("attachment://musicard.png"); const button = new ActionRowBuilder().addComponents( new ButtonBuilder() .setCustomId("pause") .setEmoji(player.paused ? playerEmoji.resume : playerEmoji.pause) .setStyle(player.paused ? ButtonStyle.Primary : ButtonStyle.Secondary), new ButtonBuilder().setCustomId("voldown").setEmoji(playerEmoji.voldown).setStyle(ButtonStyle.Secondary), new ButtonBuilder().setCustomId("volup").setEmoji(playerEmoji.volup).setStyle(ButtonStyle.Secondary), new ButtonBuilder().setCustomId("loop").setEmoji(playerEmoji.loop).setStyle(ButtonStyle.Secondary) ); const button2 = new ActionRowBuilder().addComponents( new ButtonBuilder().setCustomId("shuffle").setEmoji(playerEmoji.shuffle).setStyle(ButtonStyle.Secondary), new ButtonBuilder().setCustomId("prev").setEmoji(playerEmoji.previous).setStyle(ButtonStyle.Secondary), new ButtonBuilder().setCustomId("skip").setEmoji(playerEmoji.skip).setStyle(ButtonStyle.Secondary), new ButtonBuilder().setCustomId("stop").setEmoji(playerEmoji.stop).setStyle(ButtonStyle.Danger) ); const nplaying = await client.channels.cache .get(player.textId) .send({ embeds: [trackMsg], files: [attachment], components: [button, button2] }); player.message = nplaying; const embed = new EmbedBuilder().setColor(client.config.embedColor); const collector = nplaying.createMessageComponentCollector(); collector.on("collect", async (interaction) => { if (!player) return collector.stop(); if (!interaction.member.voice.channel || player.voiceId !== interaction.member.voice.channelId) { embed.setDescription(`You must be in the same voice channel as the bot.`); return interaction.reply({ embeds: [embed], ephemeral: true }); } switch (interaction.customId) { case "pause": player.paused ? player.resume() : player.pause(); button.components[0] .setEmoji(player.paused ? playerEmoji.resume : playerEmoji.pause) .setStyle(player.paused ? ButtonStyle.Primary : ButtonStyle.Secondary); trackMsg.setAuthor({ name: player.paused ? "Song Paused" : "Now Playing", iconURL: client.user.displayAvatarURL(), }); await nplaying.edit({ embeds: [trackMsg], components: [button, button2] }); interaction.deferUpdate(); break; case "prev": if (!player.queue.previous.length) { embed.setDescription(`No previous song in the queue.`); return interaction.reply({ embeds: [embed], ephemeral: true }); } player.previous(); interaction.deferUpdate(); break; case "skip": if (player.queue.isEmpty && !client.data.get("autoplay", player.guildId)) { embed.setDescription(`Queue is empty. Skip not possible.`); return interaction.reply({ embeds: [embed], ephemeral: true }); } player.skip(); interaction.deferUpdate(); break; case "loop": const loopMode = player.loop === "none" ? "song" : player.loop === "song" ? "queue" : "none"; player.setLoop(loopMode); embed.setDescription(`Loop mode has been set to \`${loopMode}\`.`); return interaction.reply({ embeds: [embed], ephemeral: true }); case "shuffle": if (player.queue.isEmpty) { embed.setDescription(`Queue is empty. Shuffle not possible.`); return interaction.reply({ embeds: [embed], ephemeral: true }); } player.queue.shuffle(); embed.setDescription(`Queue has been shuffled.`); return interaction.reply({ embeds: [embed], ephemeral: true }); case "voldown": if (player.volume <= client.config.minVolume) { embed.setDescription(`Volume cannot be lower than \`${client.config.minVolume}%\`.`); return interaction.reply({ embeds: [embed], ephemeral: true }); } player.setVolume(player.volume - 10); embed.setDescription(`Volume has been decreased to \`${player.volume}%\`.`); return interaction.reply({ embeds: [embed], ephemeral: true }); case "volup": if (player.volume >= client.config.maxVolume) { embed.setDescription(`Volume cannot be higher than \`${client.config.maxVolume}%\`.`); return interaction.reply({ embeds: [embed], ephemeral: true }); } player.setVolume(player.volume + 10); embed.setDescription(`Volume has been increased to \`${player.volume}%\`.`); return interaction.reply({ embeds: [embed], ephemeral: true }); case "stop": player.stop(); interaction.deferUpdate(); break; } }); }; function capitalize(string) { return string.charAt(0).toUpperCase() + string.slice(1); }