mirror of
https://github.com/BluemediaDev/muse.git
synced 2025-04-12 02:03:55 +02:00
136 lines
4.5 KiB
TypeScript
136 lines
4.5 KiB
TypeScript
import getYouTubeID from 'get-youtube-id';
|
|
import {EmbedBuilder} from 'discord.js';
|
|
import Player, {MediaSource, QueuedSong, STATUS} from '../services/player.js';
|
|
import getProgressBar from './get-progress-bar.js';
|
|
import {prettyTime} from './time.js';
|
|
import {truncate} from './string.js';
|
|
|
|
const PAGE_SIZE = 10;
|
|
|
|
const getMaxSongTitleLength = (title: string) => {
|
|
// eslint-disable-next-line no-control-regex
|
|
const nonASCII = /[^\x00-\x7F]+/;
|
|
return nonASCII.test(title) ? 28 : 48;
|
|
};
|
|
|
|
const getSongTitle = ({title, url, offset, source}: QueuedSong, shouldTruncate = false) => {
|
|
if (source === MediaSource.HLS) {
|
|
return `[${title}](${url})`;
|
|
}
|
|
|
|
const cleanSongTitle = title.replace(/\[.*\]/, '').trim();
|
|
|
|
const songTitle = shouldTruncate ? truncate(cleanSongTitle, getMaxSongTitleLength(cleanSongTitle)) : cleanSongTitle;
|
|
const youtubeId = url.length === 11 ? url : getYouTubeID(url) ?? '';
|
|
|
|
return `[${songTitle}](https://www.youtube.com/watch?v=${youtubeId}${offset === 0 ? '' : '&t=' + String(offset)})`;
|
|
};
|
|
|
|
const getQueueInfo = (player: Player) => {
|
|
const queueSize = player.queueSize();
|
|
if (queueSize === 0) {
|
|
return '-';
|
|
}
|
|
|
|
return queueSize === 1 ? '1 song' : `${queueSize} songs`;
|
|
};
|
|
|
|
const getPlayerUI = (player: Player) => {
|
|
const song = player.getCurrent();
|
|
|
|
if (!song) {
|
|
return '';
|
|
}
|
|
|
|
const position = player.getPosition();
|
|
const button = player.status === STATUS.PLAYING ? '⏹️' : '▶️';
|
|
const progressBar = getProgressBar(15, position / song.length);
|
|
const elapsedTime = song.isLive ? 'live' : `${prettyTime(position)}/${prettyTime(song.length)}`;
|
|
const loop = player.loopCurrentSong ? '🔂' : player.loopCurrentQueue ? '🔁' : '';
|
|
return `${button} ${progressBar} \`[${elapsedTime}]\` 🔉 ${loop}`;
|
|
};
|
|
|
|
export const buildPlayingMessageEmbed = (player: Player): EmbedBuilder => {
|
|
const currentlyPlaying = player.getCurrent();
|
|
|
|
if (!currentlyPlaying) {
|
|
throw new Error('No playing song found');
|
|
}
|
|
|
|
const {artist, thumbnailUrl, requestedBy} = currentlyPlaying;
|
|
const message = new EmbedBuilder();
|
|
message
|
|
.setColor(player.status === STATUS.PLAYING ? 'DarkGreen' : 'DarkRed')
|
|
.setTitle(player.status === STATUS.PLAYING ? 'Now Playing' : 'Paused')
|
|
.setDescription(`
|
|
**${getSongTitle(currentlyPlaying)}**
|
|
Requested by: <@${requestedBy}>\n
|
|
${getPlayerUI(player)}
|
|
`)
|
|
.setFooter({text: `Source: ${artist}`});
|
|
|
|
if (thumbnailUrl) {
|
|
message.setThumbnail(thumbnailUrl);
|
|
}
|
|
|
|
return message;
|
|
};
|
|
|
|
export const buildQueueEmbed = (player: Player, page: number): EmbedBuilder => {
|
|
const currentlyPlaying = player.getCurrent();
|
|
|
|
if (!currentlyPlaying) {
|
|
throw new Error('queue is empty');
|
|
}
|
|
|
|
const queueSize = player.queueSize();
|
|
const maxQueuePage = Math.ceil((queueSize + 1) / PAGE_SIZE);
|
|
|
|
if (page > maxQueuePage) {
|
|
throw new Error('the queue isn\'t that big');
|
|
}
|
|
|
|
const queuePageBegin = (page - 1) * PAGE_SIZE;
|
|
const queuePageEnd = queuePageBegin + PAGE_SIZE;
|
|
const queuedSongs = player
|
|
.getQueue()
|
|
.slice(queuePageBegin, queuePageEnd)
|
|
.map((song, index) => {
|
|
const songNumber = index + 1 + queuePageBegin;
|
|
const duration = song.isLive ? 'live' : prettyTime(song.length);
|
|
|
|
return `\`${songNumber}.\` ${getSongTitle(song, true)} \`[${duration}]\``;
|
|
})
|
|
.join('\n');
|
|
|
|
const {artist, thumbnailUrl, playlist, requestedBy} = currentlyPlaying;
|
|
const playlistTitle = playlist ? `(${playlist.title})` : '';
|
|
const totalLength = player.getQueue().reduce((accumulator, current) => accumulator + current.length, 0);
|
|
|
|
const message = new EmbedBuilder();
|
|
|
|
let description = `**${getSongTitle(currentlyPlaying)}**\n`;
|
|
description += `Requested by: <@${requestedBy}>\n\n`;
|
|
description += `${getPlayerUI(player)}\n\n`;
|
|
|
|
if (player.getQueue().length > 0) {
|
|
description += '**Up next:**\n';
|
|
description += queuedSongs;
|
|
}
|
|
|
|
message
|
|
.setTitle(player.status === STATUS.PLAYING ? `Now Playing ${player.loopCurrentSong ? '(loop on)' : ''}` : 'Queued songs')
|
|
.setColor(player.status === STATUS.PLAYING ? 'DarkGreen' : 'NotQuiteBlack')
|
|
.setDescription(description)
|
|
.addFields([{name: 'In queue', value: getQueueInfo(player), inline: true}, {
|
|
name: 'Total length', value: `${totalLength > 0 ? prettyTime(totalLength) : '-'}`, inline: true,
|
|
}, {name: 'Page', value: `${page} out of ${maxQueuePage}`, inline: true}])
|
|
.setFooter({text: `Source: ${artist} ${playlistTitle}`});
|
|
|
|
if (thumbnailUrl) {
|
|
message.setThumbnail(thumbnailUrl);
|
|
}
|
|
|
|
return message;
|
|
};
|
|
|