queue utils
This commit is contained in:
parent
1d88db1711
commit
2a6d9a74f4
10 changed files with 171 additions and 12 deletions
|
@ -92,7 +92,7 @@ client.on("message", async (message) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const track = await client.player.search(args[0], {
|
const track = await client.player.search(args[0], {
|
||||||
searchEngine: QueryType.YOUTUBE_SEARCH
|
requestedBy: message.author
|
||||||
}).then(x => x.tracks[1]);
|
}).then(x => x.tracks[1]);
|
||||||
if (!track) return void message.reply("Track not found!");
|
if (!track) return void message.reply("Track not found!");
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ client.on("message", async (message) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const track = await client.player.search(args[0], {
|
const track = await client.player.search(args[0], {
|
||||||
searchEngine: QueryType.YOUTUBE_SEARCH
|
requestedBy: message.author
|
||||||
}).then(x => x.tracks[1]);
|
}).then(x => x.tracks[1]);
|
||||||
if (!track) return void message.reply("Track not found!");
|
if (!track) return void message.reply("Track not found!");
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,9 @@ The new update brings new features as well as better management of different thi
|
||||||
```diff
|
```diff
|
||||||
- player.play(message, query);
|
- player.play(message, query);
|
||||||
+ const queue = player.createQueue(message.guild);
|
+ const queue = player.createQueue(message.guild);
|
||||||
+ const song = await player.search(query);
|
+ const song = await player.search(query, {
|
||||||
|
+ requestedBy: message.author
|
||||||
|
});
|
||||||
+
|
+
|
||||||
+ try {
|
+ try {
|
||||||
+ await queue.connect(message.member.voice.channel);
|
+ await queue.connect(message.member.voice.channel);
|
||||||
|
|
|
@ -254,7 +254,24 @@ client.on("interaction", async (interaction) => {
|
||||||
await interaction.defer();
|
await interaction.defer();
|
||||||
const queue = player.getQueue(interaction.guildID);
|
const queue = player.getQueue(interaction.guildID);
|
||||||
if (!queue || !queue.playing) return void interaction.followUp({ content: "❌ | No music is being played!" });
|
if (!queue || !queue.playing) return void interaction.followUp({ content: "❌ | No music is being played!" });
|
||||||
return void interaction.followUp({ content: `🎶 | Current song: **${queue.current.title}**!` });
|
const progress = queue.createProgressBar();
|
||||||
|
const perc = queue.getPlayerTimestamp();
|
||||||
|
|
||||||
|
return void interaction.followUp({
|
||||||
|
embeds: [
|
||||||
|
{
|
||||||
|
title: "Now Playing",
|
||||||
|
description: `🎶 | **${queue.current.title}**! (\`${perc.progress}%\`)`,
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: "\u200b",
|
||||||
|
value: progress
|
||||||
|
}
|
||||||
|
],
|
||||||
|
color: 0xffffff
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
} else if (interaction.commandName === "loop") {
|
} else if (interaction.commandName === "loop") {
|
||||||
await interaction.defer();
|
await interaction.defer();
|
||||||
const queue = player.getQueue(interaction.guildID);
|
const queue = player.getQueue(interaction.guildID);
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@discordjs/opus": "^0.5.3",
|
"@discordjs/opus": "^0.5.3",
|
||||||
"discord-player": "^5.0.0-dev.3fd002187de27ed6dc3398fd8f4f5dfe309ba350",
|
"discord-player": "^5.0.0-dev.1d88db17117d79a26967895675c17f117e52878d",
|
||||||
"discord.js": "^13.0.0-dev.c850ae10270076c4b2e10b130dd8f88eed4ed201"
|
"discord.js": "^13.0.0-dev.c850ae10270076c4b2e10b130dd8f88eed4ed201"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@
|
||||||
"@typescript-eslint/eslint-plugin": "^4.28.0",
|
"@typescript-eslint/eslint-plugin": "^4.28.0",
|
||||||
"@typescript-eslint/parser": "^4.28.0",
|
"@typescript-eslint/parser": "^4.28.0",
|
||||||
"discord-api-types": "^0.18.1",
|
"discord-api-types": "^0.18.1",
|
||||||
"discord.js": "^13.0.0-dev.c850ae10270076c4b2e10b130dd8f88eed4ed201",
|
"discord.js": "^13.0.0-dev.6d3d00b44577a70e840f0187d6894043677c5329",
|
||||||
"discord.js-docgen": "discordjs/docgen#ts-patch",
|
"discord.js-docgen": "discordjs/docgen#ts-patch",
|
||||||
"eslint": "^7.29.0",
|
"eslint": "^7.29.0",
|
||||||
"jsdoc-babel": "^0.5.0",
|
"jsdoc-babel": "^0.5.0",
|
||||||
|
|
|
@ -188,6 +188,7 @@ class Player extends EventEmitter<PlayerEvents> {
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
for (const [_, extractor] of this.extractors) {
|
for (const [_, extractor] of this.extractors) {
|
||||||
|
if (options.blockExtractor) break;
|
||||||
if (!extractor.validate(query)) continue;
|
if (!extractor.validate(query)) continue;
|
||||||
const data = await extractor.handle(query);
|
const data = await extractor.handle(query);
|
||||||
if (data && data.data.length) {
|
if (data && data.data.length) {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Collection, Guild, StageChannel, VoiceChannel } from "discord.js";
|
||||||
import { Player } from "../Player";
|
import { Player } from "../Player";
|
||||||
import { StreamDispatcher } from "../VoiceInterface/BasicStreamDispatcher";
|
import { StreamDispatcher } from "../VoiceInterface/BasicStreamDispatcher";
|
||||||
import Track from "./Track";
|
import Track from "./Track";
|
||||||
import { PlayerOptions, PlayOptions, QueueFilters, QueueRepeatMode } from "../types/types";
|
import { PlayerOptions, PlayerProgressbarOptions, PlayOptions, QueueFilters, QueueRepeatMode } from "../types/types";
|
||||||
import ytdl from "discord-ytdl-core";
|
import ytdl from "discord-ytdl-core";
|
||||||
import { AudioResource, StreamType } from "@discordjs/voice";
|
import { AudioResource, StreamType } from "@discordjs/voice";
|
||||||
import { Util } from "../utils/Util";
|
import { Util } from "../utils/Util";
|
||||||
|
@ -300,6 +300,11 @@ class Queue<T = unknown> {
|
||||||
return NC ? playbackTime * NC : VW ? playbackTime * VW : playbackTime;
|
return NC ? playbackTime * NC : VW ? playbackTime * VW : playbackTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set streamTime(time: number) {
|
||||||
|
this.#watchDestroyed();
|
||||||
|
this.seek(time);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns enabled filters
|
* Returns enabled filters
|
||||||
* @returns {AudioFilters}
|
* @returns {AudioFilters}
|
||||||
|
@ -398,6 +403,138 @@ class Queue<T = unknown> {
|
||||||
this.previousTracks = [];
|
this.previousTracks = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the player
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
stop() {
|
||||||
|
return this.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shuffles this queue
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
shuffle() {
|
||||||
|
if (!this.tracks.length || this.tracks.length < 3) return false;
|
||||||
|
const currentTrack = this.tracks.shift();
|
||||||
|
|
||||||
|
for (let i = this.tracks.length - 1; i > 0; i--) {
|
||||||
|
const j = Math.floor(Math.random() * (i + 1));
|
||||||
|
[this.tracks[i], this.tracks[j]] = [this.tracks[j], this.tracks[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tracks.unshift(currentTrack);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a track from the queue
|
||||||
|
* @param {Track|number} track The track to remove
|
||||||
|
* @returns {Track}
|
||||||
|
*/
|
||||||
|
remove(track: Track | number) {
|
||||||
|
let trackFound: Track = null;
|
||||||
|
if (typeof track === "number") {
|
||||||
|
trackFound = this.tracks[track];
|
||||||
|
if (trackFound) {
|
||||||
|
this.tracks = this.tracks.filter((t) => t._trackID !== trackFound._trackID);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
trackFound = this.tracks.find((s) => s._trackID === track._trackID);
|
||||||
|
if (trackFound) {
|
||||||
|
this.tracks = this.tracks.filter((s) => s._trackID !== trackFound._trackID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return trackFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Jumps to particular track
|
||||||
|
* @param {Track|number} track The track
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
jump(track: Track | number): void {
|
||||||
|
const foundTrack = this.remove(track);
|
||||||
|
if (!foundTrack) throw new Error("Track not found");
|
||||||
|
this.tracks.splice(1, 0, foundTrack);
|
||||||
|
|
||||||
|
return void this.skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {object} PlayerTimestamp
|
||||||
|
* @param {string} current The current progress
|
||||||
|
* @param {string} end The total time
|
||||||
|
* @param {number} progress Progress in %
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns player stream timestamp
|
||||||
|
* @param {boolean} [queue=false] If it should generate timestamp for the queue
|
||||||
|
* @returns {PlayerTimestamp}
|
||||||
|
*/
|
||||||
|
getPlayerTimestamp(queue = false) {
|
||||||
|
const previousTracksTime = this.previousTracks.length > 0 ? this.previousTracks.reduce((p, c) => p + c.durationMS, 0) : 0;
|
||||||
|
const currentStreamTime = queue ? previousTracksTime + this.streamTime : this.streamTime;
|
||||||
|
const totalTracksTime = this.totalTime;
|
||||||
|
const totalTime = queue ? previousTracksTime + totalTracksTime : this.current.durationMS;
|
||||||
|
|
||||||
|
const currentTimecode = Util.buildTimeCode(Util.parseMS(currentStreamTime));
|
||||||
|
const endTimecode = Util.buildTimeCode(Util.parseMS(totalTime));
|
||||||
|
|
||||||
|
return {
|
||||||
|
current: currentTimecode,
|
||||||
|
end: endTimecode,
|
||||||
|
progress: Math.round((currentStreamTime / totalTime) * 100)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates progress bar string
|
||||||
|
* @param {PlayerProgressbarOptions} options The progress bar options
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
createProgressBar(options: PlayerProgressbarOptions = { timecodes: true, queue: false }) {
|
||||||
|
const previousTracksTime = this.previousTracks.length > 0 ? this.previousTracks.reduce((p, c) => p + c.durationMS, 0) : 0;
|
||||||
|
const currentStreamTime = options.queue ? previousTracksTime + this.streamTime : this.streamTime;
|
||||||
|
const totalTracksTime = this.totalTime;
|
||||||
|
const totalTime = options.queue ? previousTracksTime + totalTracksTime : this.current.durationMS;
|
||||||
|
const length = typeof options.length === "number" ? (options.length <= 0 || options.length === Infinity ? 15 : options.length) : 15;
|
||||||
|
|
||||||
|
const index = Math.round((currentStreamTime / totalTime) * length);
|
||||||
|
const indicator = typeof options.indicator === "string" && options.indicator.length > 0 ? options.indicator : "🔘";
|
||||||
|
const line = typeof options.line === "string" && options.line.length > 0 ? options.line : "▬";
|
||||||
|
|
||||||
|
if (index >= 1 && index <= length) {
|
||||||
|
const bar = line.repeat(length - 1).split("");
|
||||||
|
bar.splice(index, 0, indicator);
|
||||||
|
if (options.timecodes) {
|
||||||
|
const timestamp = this.getPlayerTimestamp(options.queue);
|
||||||
|
return `${timestamp.current} ┃ ${bar.join("")} ┃ ${timestamp.end}`;
|
||||||
|
} else {
|
||||||
|
return `${bar.join("")}`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (options.timecodes) {
|
||||||
|
const timestamp = this.getPlayerTimestamp(options.queue);
|
||||||
|
return `${timestamp.current} ┃ ${indicator}${line.repeat(length - 1)} ┃ ${timestamp.end}`;
|
||||||
|
} else {
|
||||||
|
return `${indicator}${line.repeat(length - 1)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Total duration
|
||||||
|
* @type {Number}
|
||||||
|
*/
|
||||||
|
get totalTime(): number {
|
||||||
|
return this.tracks.length > 0 ? this.tracks.map((t) => t.durationMS).reduce((p, c) => p + c) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Play stream in a voice/stage channel
|
* Play stream in a voice/stage channel
|
||||||
* @param {Track} [src] The track to play (if empty, uses first track from the queue)
|
* @param {Track} [src] The track to play (if empty, uses first track from the queue)
|
||||||
|
|
|
@ -337,11 +337,13 @@ export interface PlayOptions {
|
||||||
/**
|
/**
|
||||||
* @typedef {object} SearchOptions
|
* @typedef {object} SearchOptions
|
||||||
* @property {UserResolvable} requestedBy The user who requested this search
|
* @property {UserResolvable} requestedBy The user who requested this search
|
||||||
* @property {QueryType} searchEngine The query search engine
|
* @property {QueryType} [searchEngine=QueryType.AUTO] The query search engine
|
||||||
|
* @property {boolean} [blockExtractor=false] If it should block custom extractors
|
||||||
*/
|
*/
|
||||||
export interface SearchOptions {
|
export interface SearchOptions {
|
||||||
requestedBy: UserResolvable;
|
requestedBy: UserResolvable;
|
||||||
searchEngine?: QueryType;
|
searchEngine?: QueryType;
|
||||||
|
blockExtractor?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2003,10 +2003,10 @@ discord.js-docgen@discordjs/docgen#ts-patch:
|
||||||
tsubaki "^1.3.2"
|
tsubaki "^1.3.2"
|
||||||
yargs "^14.0.0"
|
yargs "^14.0.0"
|
||||||
|
|
||||||
discord.js@^13.0.0-dev.c850ae10270076c4b2e10b130dd8f88eed4ed201:
|
discord.js@^13.0.0-dev.6d3d00b44577a70e840f0187d6894043677c5329:
|
||||||
version "13.0.0-dev.c850ae10270076c4b2e10b130dd8f88eed4ed201"
|
version "13.0.0-dev.6d3d00b44577a70e840f0187d6894043677c5329"
|
||||||
resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-13.0.0-dev.c850ae10270076c4b2e10b130dd8f88eed4ed201.tgz#8790b4f48ed36106ea08d2dc3148ee51ef321497"
|
resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-13.0.0-dev.6d3d00b44577a70e840f0187d6894043677c5329.tgz#7593fc7d86651f65c4e1f6a67802b7b72c532695"
|
||||||
integrity sha512-yp/s0AxcTNtvt9zcZv3kb0szLTFN2rqCoz4hclRE7C3umD7kgvcbF4O+k3RJ1ef6CAlrsZxvept/zYGqIn/dTA==
|
integrity sha512-K2jlMXX4cB8+/6CYh/QywULgUcMSJcR6CycEGnONeCskrejtArCUmiV8dKu20ABv3CeHWgTVN261BQWRTTelRg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@discordjs/collection" "^0.1.6"
|
"@discordjs/collection" "^0.1.6"
|
||||||
"@discordjs/form-data" "^3.0.1"
|
"@discordjs/form-data" "^3.0.1"
|
||||||
|
|
Loading…
Reference in a new issue