cleanup base
This commit is contained in:
parent
fac2662025
commit
e7031a29f9
11 changed files with 79 additions and 597 deletions
|
@ -8,7 +8,7 @@
|
||||||
"lib/"
|
"lib/"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "yarn build && cd test && node index.js",
|
"test": "cd test && ts-node index.ts",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"format": "prettier --write \"src/**/*.ts\"",
|
"format": "prettier --write \"src/**/*.ts\"",
|
||||||
"lint": "tslint -p tsconfig.json",
|
"lint": "tslint -p tsconfig.json",
|
||||||
|
@ -71,6 +71,7 @@
|
||||||
"discord.js-docgen": "discordjs/docgen#ts-patch",
|
"discord.js-docgen": "discordjs/docgen#ts-patch",
|
||||||
"jsdoc-babel": "^0.5.0",
|
"jsdoc-babel": "^0.5.0",
|
||||||
"prettier": "^2.2.1",
|
"prettier": "^2.2.1",
|
||||||
|
"ts-node": "^10.0.0",
|
||||||
"tslint": "^6.1.3",
|
"tslint": "^6.1.3",
|
||||||
"tslint-config-prettier": "^1.18.0",
|
"tslint-config-prettier": "^1.18.0",
|
||||||
"typescipt": "^1.0.0",
|
"typescipt": "^1.0.0",
|
||||||
|
|
203
src/Player.ts
203
src/Player.ts
|
@ -1,202 +1 @@
|
||||||
import { EventEmitter } from 'events';
|
export {};
|
||||||
import { Client, Collection, Snowflake, Message, Collector } from 'discord.js';
|
|
||||||
import Util from './utils/Util';
|
|
||||||
import Queue from './Structures/Queue';
|
|
||||||
import Track from './Structures/Track';
|
|
||||||
import PlayerError from './utils/PlayerError';
|
|
||||||
import { ExtractorModel } from './Structures/ExtractorModel';
|
|
||||||
import ytdl from 'discord-ytdl-core';
|
|
||||||
import { PlayerEvents, PlayerErrorEventCodes } from './utils/Constants';
|
|
||||||
|
|
||||||
export class Player extends EventEmitter {
|
|
||||||
public client: Client;
|
|
||||||
public queues = new Collection<Snowflake, Queue>();
|
|
||||||
public Extractors = new Collection<string, ExtractorModel>();
|
|
||||||
private _cooldownsTimeout = new Collection<string, NodeJS.Timeout>();
|
|
||||||
private _resultsCollectors = new Collection<string, Collector<Snowflake, Message>>();
|
|
||||||
|
|
||||||
constructor(client: Client) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
Object.defineProperty(this, 'client', {
|
|
||||||
value: client,
|
|
||||||
enumerable: false
|
|
||||||
});
|
|
||||||
|
|
||||||
Util.alertFFmpeg();
|
|
||||||
}
|
|
||||||
|
|
||||||
public createQueue(message: Message) {
|
|
||||||
return new Promise<Queue>((resolve) => {
|
|
||||||
if (this.queues.has(message.guild.id)) return this.queues.get(message.guild.id);
|
|
||||||
const channel = message.member.voice?.channel;
|
|
||||||
if (!channel)
|
|
||||||
return void this.emit(
|
|
||||||
PlayerEvents.ERROR,
|
|
||||||
new PlayerError(
|
|
||||||
'Voice connection is not available in this server!',
|
|
||||||
PlayerErrorEventCodes.NOT_CONNECTED,
|
|
||||||
message
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
const queue = new Queue(this, message.guild);
|
|
||||||
void this.queues.set(message.guild.id, queue);
|
|
||||||
|
|
||||||
channel
|
|
||||||
.join()
|
|
||||||
.then((connection) => {
|
|
||||||
this.emit(PlayerEvents.CONNECTION_CREATE, message, connection);
|
|
||||||
|
|
||||||
queue.voiceConnection = connection;
|
|
||||||
if (queue.options.setSelfDeaf) connection.voice.setSelfDeaf(true);
|
|
||||||
this.emit(PlayerEvents.QUEUE_CREATE, message, queue);
|
|
||||||
resolve(queue);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
this.queues.delete(message.guild.id);
|
|
||||||
this.emit(
|
|
||||||
PlayerEvents.ERROR,
|
|
||||||
new PlayerError(err.message ?? err, PlayerErrorEventCodes.UNABLE_TO_JOIN, message)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
return queue;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public getQueue(message: Message) {
|
|
||||||
return this.queues.get(message.guild.id) ?? null;
|
|
||||||
}
|
|
||||||
|
|
||||||
async play(message: Message, query: string | Track, firstResult?: boolean): Promise<void> {
|
|
||||||
if (!message) throw new PlayerError('Play function needs message');
|
|
||||||
if (!query) throw new PlayerError('Play function needs search query as a string or Player.Track object');
|
|
||||||
|
|
||||||
if (this._cooldownsTimeout.has(`end_${message.guild.id}`)) {
|
|
||||||
clearTimeout(this._cooldownsTimeout.get(`end_${message.guild.id}`));
|
|
||||||
this._cooldownsTimeout.delete(`end_${message.guild.id}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof query === 'string') query = query.replace(/<(.+)>/g, '$1');
|
|
||||||
let track;
|
|
||||||
|
|
||||||
const queue = this.getQueue(message);
|
|
||||||
|
|
||||||
if (query instanceof Track) track = query;
|
|
||||||
else {
|
|
||||||
if (ytdl.validateURL(query)) {
|
|
||||||
const info = await ytdl.getBasicInfo(query).catch(() => {});
|
|
||||||
if (!info) return void this.emit(PlayerEvents.NO_RESULTS, message, query);
|
|
||||||
if (info.videoDetails.isLiveContent && !queue.options.enableLive)
|
|
||||||
return void this.emit(
|
|
||||||
PlayerEvents.ERROR,
|
|
||||||
new PlayerError('Live video is not enabled!', PlayerErrorEventCodes.LIVE_VIDEO, message)
|
|
||||||
);
|
|
||||||
const lastThumbnail = info.videoDetails.thumbnails[info.videoDetails.thumbnails.length - 1];
|
|
||||||
|
|
||||||
track = new Track(this, {
|
|
||||||
title: info.videoDetails.title,
|
|
||||||
description: info.videoDetails.description,
|
|
||||||
author: info.videoDetails.author.name,
|
|
||||||
url: info.videoDetails.video_url,
|
|
||||||
thumbnail: lastThumbnail.url,
|
|
||||||
duration: Util.buildTimeCode(Util.parseMS(parseInt(info.videoDetails.lengthSeconds) * 1000)),
|
|
||||||
views: parseInt(info.videoDetails.viewCount),
|
|
||||||
requestedBy: message.author,
|
|
||||||
fromPlaylist: false,
|
|
||||||
source: 'youtube',
|
|
||||||
live: Boolean(info.videoDetails.isLiveContent)
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
for (const [_, extractor] of this.Extractors) {
|
|
||||||
if (extractor.validate(query)) {
|
|
||||||
const data = await extractor.handle(query);
|
|
||||||
if (data) {
|
|
||||||
track = new Track(this, {
|
|
||||||
title: data.title,
|
|
||||||
description: data.description,
|
|
||||||
duration: Util.buildTimeCode(Util.parseMS(data.duration)),
|
|
||||||
thumbnail: data.thumbnail,
|
|
||||||
author: data.author,
|
|
||||||
views: data.views,
|
|
||||||
engine: data.engine,
|
|
||||||
source: 'arbitrary',
|
|
||||||
fromPlaylist: false,
|
|
||||||
requestedBy: message.author,
|
|
||||||
url: data.url
|
|
||||||
});
|
|
||||||
|
|
||||||
if (extractor.important) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!track) track = await this.searchTracks(message, query, firstResult);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (track) {
|
|
||||||
if (queue) {
|
|
||||||
const q = queue.addTrack(track);
|
|
||||||
this.emit(PlayerEvents.TRACK_ADD, message, q, q.tracks[q.tracks.length - 1]);
|
|
||||||
} else {
|
|
||||||
const q = queue.addTrack(track);
|
|
||||||
if (q) this.emit(PlayerEvents.TRACK_START, message, q.tracks[0], q);
|
|
||||||
|
|
||||||
// todo: start playing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private searchTracks(message: Message, query: string, firstResult?: boolean): Promise<Track> {
|
|
||||||
return new Promise(async (resolve) => {
|
|
||||||
let tracks: Track[] = [];
|
|
||||||
const queryType = Util.getQueryType(query);
|
|
||||||
|
|
||||||
switch (queryType) {
|
|
||||||
default:
|
|
||||||
tracks = await Util.ytSearch(query, { user: message.author, player: this });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tracks.length < 1) return void this.emit(PlayerEvents.NO_RESULTS, message, query);
|
|
||||||
if (firstResult || tracks.length === 1) return resolve(tracks[0]);
|
|
||||||
|
|
||||||
const collectorString = `${message.author.id}-${message.channel.id}`;
|
|
||||||
const currentCollector = this._resultsCollectors.get(collectorString);
|
|
||||||
if (currentCollector) currentCollector.stop();
|
|
||||||
|
|
||||||
const collector = message.channel.createMessageCollector((m) => m.author.id === message.author.id, {
|
|
||||||
time: 60000
|
|
||||||
});
|
|
||||||
|
|
||||||
this._resultsCollectors.set(collectorString, collector);
|
|
||||||
|
|
||||||
this.emit(PlayerEvents.SEARCH_RESULTS, message, query, tracks, collector);
|
|
||||||
|
|
||||||
collector.on('collect', ({ content }) => {
|
|
||||||
if (content === 'cancel') {
|
|
||||||
collector.stop();
|
|
||||||
return void this.emit(PlayerEvents.SEARCH_CANCEL, message, query, tracks);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isNaN(content) && parseInt(content) >= 1 && parseInt(content) <= tracks.length) {
|
|
||||||
const index = parseInt(content, 10);
|
|
||||||
const track = tracks[index - 1];
|
|
||||||
collector.stop();
|
|
||||||
resolve(track);
|
|
||||||
} else {
|
|
||||||
this.emit(PlayerEvents.SEARCH_INVALID_RESPONSE, message, query, tracks, content, collector);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
collector.on('end', (_, reason) => {
|
|
||||||
if (reason === 'time') {
|
|
||||||
this.emit(PlayerEvents.SEARCH_CANCEL, message, query, tracks);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Player;
|
|
||||||
|
|
|
@ -1,70 +1 @@
|
||||||
import { ExtractorModelData } from '../types/types';
|
export {};
|
||||||
|
|
||||||
class ExtractorModel {
|
|
||||||
name: string;
|
|
||||||
private _raw: any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Model for raw Discord Player extractors
|
|
||||||
* @param {String} extractorName Name of the extractor
|
|
||||||
* @param {Object} data Extractor object
|
|
||||||
*/
|
|
||||||
constructor(extractorName: string, data: any) {
|
|
||||||
/**
|
|
||||||
* The extractor name
|
|
||||||
* @type {String}
|
|
||||||
*/
|
|
||||||
this.name = extractorName;
|
|
||||||
|
|
||||||
Object.defineProperty(this, '_raw', { value: data, configurable: false, writable: false, enumerable: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method to handle requests from `Player.play()`
|
|
||||||
* @param {String} query Query to handle
|
|
||||||
* @returns {Promise<ExtractorModelData>}
|
|
||||||
*/
|
|
||||||
async handle(query: string): Promise<ExtractorModelData> {
|
|
||||||
const data = await this._raw.getInfo(query);
|
|
||||||
if (!data) return null;
|
|
||||||
|
|
||||||
return {
|
|
||||||
title: data.title,
|
|
||||||
duration: data.duration,
|
|
||||||
thumbnail: data.thumbnail,
|
|
||||||
engine: data.engine,
|
|
||||||
views: data.views,
|
|
||||||
author: data.author,
|
|
||||||
description: data.description,
|
|
||||||
url: data.url
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method used by Discord Player to validate query with this extractor
|
|
||||||
* @param {String} query The query to validate
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
validate(query: string): boolean {
|
|
||||||
return Boolean(this._raw.validate(query));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The extractor version
|
|
||||||
* @type {String}
|
|
||||||
*/
|
|
||||||
get version(): string {
|
|
||||||
return this._raw.version ?? '0.0.0';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If player should mark this extractor as important
|
|
||||||
* @type {Boolean}
|
|
||||||
*/
|
|
||||||
get important(): boolean {
|
|
||||||
return Boolean(this._raw.important);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ExtractorModel;
|
|
||||||
export { ExtractorModel };
|
|
||||||
|
|
|
@ -1,11 +1 @@
|
||||||
import Player from '../Player';
|
export {};
|
||||||
|
|
||||||
export class Playlist {
|
|
||||||
player: Player;
|
|
||||||
|
|
||||||
constructor(player: Player, data: any) {
|
|
||||||
Object.defineProperty(this, 'player', { value: player });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Playlist;
|
|
||||||
|
|
|
@ -1,42 +1 @@
|
||||||
import { Guild, Message, VoiceConnection } from 'discord.js';
|
export {};
|
||||||
import { Player } from '../Player';
|
|
||||||
import { PlayerOptions } from '../types/types';
|
|
||||||
import Track from './Track';
|
|
||||||
import { PlayerError } from '../utils/PlayerError';
|
|
||||||
|
|
||||||
export class Queue {
|
|
||||||
player: Player;
|
|
||||||
guild: Guild;
|
|
||||||
firstMessage: Message;
|
|
||||||
options: PlayerOptions = {};
|
|
||||||
tracks: Track[] = [];
|
|
||||||
voiceConnection: VoiceConnection = null;
|
|
||||||
|
|
||||||
constructor(player: Player, guild: Guild) {
|
|
||||||
Object.defineProperty(this, 'player', { value: player, enumerable: false });
|
|
||||||
|
|
||||||
this.guild = guild;
|
|
||||||
}
|
|
||||||
|
|
||||||
get playing() {
|
|
||||||
return this.tracks[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
async play(message: Message, query: string | Track, firstResult?: boolean) {
|
|
||||||
return await this.player.play(message, query, firstResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
addTrack(track: Track) {
|
|
||||||
if (!track || !(track instanceof Track)) throw new PlayerError('No track specified to add to the queue');
|
|
||||||
this.tracks.push(track);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
addTracks(tracks: Track[]) {
|
|
||||||
this.tracks.push(...tracks);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Queue;
|
|
||||||
|
|
|
@ -1,13 +1 @@
|
||||||
import { Message } from 'discord.js';
|
export {};
|
||||||
import { Player } from '../Player';
|
|
||||||
|
|
||||||
export class Track {
|
|
||||||
readonly player: Player;
|
|
||||||
readonly message: Message;
|
|
||||||
|
|
||||||
constructor(player: Player, data: any) {
|
|
||||||
Object.defineProperty(this, 'player', { value: player, enumerable: false });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Track;
|
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
import { DiscordGatewayAdapterCreator, DiscordGatewayAdapterLibraryMethods } from '@discordjs/voice';
|
|
||||||
import {
|
|
||||||
VoiceChannel,
|
|
||||||
Snowflake,
|
|
||||||
Client,
|
|
||||||
Constants,
|
|
||||||
WebSocketShard,
|
|
||||||
Guild,
|
|
||||||
StageChannel,
|
|
||||||
Collection
|
|
||||||
} from 'discord.js';
|
|
||||||
import { GatewayVoiceServerUpdateDispatchData, GatewayVoiceStateUpdateDispatchData } from 'discord-api-types/v8';
|
|
||||||
|
|
||||||
class VoiceAdapter {
|
|
||||||
public client: Client;
|
|
||||||
public adapters = new Collection<Snowflake, DiscordGatewayAdapterLibraryMethods>();
|
|
||||||
public clients = new Set<Client>();
|
|
||||||
public guilds = new Collection<WebSocketShard, Set<Snowflake>>();
|
|
||||||
|
|
||||||
constructor(client: Client) {
|
|
||||||
this.client = client;
|
|
||||||
|
|
||||||
Object.defineProperty(this, 'client', {
|
|
||||||
enumerable: false,
|
|
||||||
writable: true,
|
|
||||||
configurable: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
trackVoiceState() {
|
|
||||||
if (this.clients.has(this.client)) return;
|
|
||||||
this.clients.add(this.client);
|
|
||||||
|
|
||||||
this.client.ws.on('VOICE_STATE_UPDATE', (data: GatewayVoiceServerUpdateDispatchData) => {
|
|
||||||
this.adapters.get(data.guild_id)?.onVoiceServerUpdate(data);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.client.ws.on(Constants.WSEvents.VOICE_STATE_UPDATE, (payload: GatewayVoiceStateUpdateDispatchData) => {
|
|
||||||
if (payload.guild_id && payload.session_id && payload.user_id === this.client.user?.id) {
|
|
||||||
this.adapters.get(payload.guild_id)?.onVoiceStateUpdate(payload);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanupGuilds(shard: WebSocketShard) {
|
|
||||||
const guilds = this.guilds.get(shard);
|
|
||||||
if (guilds) {
|
|
||||||
for (const guildID of guilds.values()) {
|
|
||||||
this.adapters.get(guildID)?.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trackGuild(guild: Guild) {
|
|
||||||
let guilds = this.guilds.get(guild.shard);
|
|
||||||
if (!guilds) {
|
|
||||||
const cleanup = () => this.cleanupGuilds(guild.shard);
|
|
||||||
guild.shard.on('close', cleanup);
|
|
||||||
guild.shard.on('destroyed', cleanup);
|
|
||||||
guilds = new Set();
|
|
||||||
this.guilds.set(guild.shard, guilds);
|
|
||||||
}
|
|
||||||
|
|
||||||
guilds.add(guild.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function createAdapter(channel: VoiceChannel | StageChannel): DiscordGatewayAdapterCreator {
|
|
||||||
return (methods) => {
|
|
||||||
const adapter = new VoiceAdapter(channel.client);
|
|
||||||
adapter.adapters.set(channel.guild.id, methods);
|
|
||||||
adapter.trackVoiceState();
|
|
||||||
adapter.trackGuild(channel.guild);
|
|
||||||
|
|
||||||
return {
|
|
||||||
sendPayload(data) {
|
|
||||||
if (channel.guild.shard.status === Constants.Status.READY) {
|
|
||||||
channel.guild.shard.send(data);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
destroy() {
|
|
||||||
return adapter.adapters.delete(channel.guild.id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
class VoiceSubscriptionManager {}
|
|
10
src/index.ts
10
src/index.ts
|
@ -1,9 +1 @@
|
||||||
export { AudioFilters } from './utils/AudioFilters';
|
export {};
|
||||||
export * as Constants from './utils/Constants';
|
|
||||||
export { ExtractorModel } from './Structures/ExtractorModel';
|
|
||||||
export { Player } from './Player';
|
|
||||||
export { Util } from './utils/Util';
|
|
||||||
export { Track } from './Structures/Track';
|
|
||||||
export { Queue } from './Structures/Queue';
|
|
||||||
export * from './types/types';
|
|
||||||
export { PlayerError } from './utils/PlayerError';
|
|
||||||
|
|
|
@ -1,158 +1 @@
|
||||||
import { downloadOptions } from 'ytdl-core';
|
export {};
|
||||||
import { User } from 'discord.js';
|
|
||||||
import { Readable, Duplex } from 'stream';
|
|
||||||
|
|
||||||
export interface PlayerOptions {
|
|
||||||
leaveOnEnd?: boolean;
|
|
||||||
leaveOnEndCooldown?: number;
|
|
||||||
leaveOnStop?: boolean;
|
|
||||||
leaveOnEmpty?: boolean;
|
|
||||||
leaveOnEmptyCooldown?: number;
|
|
||||||
setSelfDeaf?: boolean;
|
|
||||||
enableLive?: boolean;
|
|
||||||
ytdlDownloadOptions?: downloadOptions;
|
|
||||||
useSafeSearch?: boolean;
|
|
||||||
disableAutoRegister?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type FiltersName = keyof QueueFilters;
|
|
||||||
|
|
||||||
export type TrackSource = 'soundcloud' | 'youtube' | 'arbitrary';
|
|
||||||
|
|
||||||
export interface TrackData {
|
|
||||||
title: string;
|
|
||||||
description: string;
|
|
||||||
author: string;
|
|
||||||
url: string;
|
|
||||||
thumbnail: string;
|
|
||||||
duration: string;
|
|
||||||
views: number;
|
|
||||||
requestedBy: User;
|
|
||||||
fromPlaylist: boolean;
|
|
||||||
source?: TrackSource;
|
|
||||||
engine?: any;
|
|
||||||
live?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type QueueFilters = {
|
|
||||||
bassboost?: boolean;
|
|
||||||
'8D'?: boolean;
|
|
||||||
vaporwave?: boolean;
|
|
||||||
nightcore?: boolean;
|
|
||||||
phaser?: boolean;
|
|
||||||
tremolo?: boolean;
|
|
||||||
vibrato?: boolean;
|
|
||||||
reverse?: boolean;
|
|
||||||
treble?: boolean;
|
|
||||||
normalizer?: boolean;
|
|
||||||
surrounding?: boolean;
|
|
||||||
pulsator?: boolean;
|
|
||||||
subboost?: boolean;
|
|
||||||
karaoke?: boolean;
|
|
||||||
flanger?: boolean;
|
|
||||||
gate?: boolean;
|
|
||||||
haas?: boolean;
|
|
||||||
mcompand?: boolean;
|
|
||||||
mono?: boolean;
|
|
||||||
mstlr?: boolean;
|
|
||||||
mstrr?: boolean;
|
|
||||||
compressor?: boolean;
|
|
||||||
expander?: boolean;
|
|
||||||
softlimiter?: boolean;
|
|
||||||
chorus?: boolean;
|
|
||||||
chorus2d?: boolean;
|
|
||||||
chorus3d?: boolean;
|
|
||||||
fadein?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type QueryType =
|
|
||||||
| 'soundcloud_track'
|
|
||||||
| 'soundcloud_playlist'
|
|
||||||
| 'spotify_song'
|
|
||||||
| 'spotify_album'
|
|
||||||
| 'spotify_playlist'
|
|
||||||
| 'youtube_video'
|
|
||||||
| 'youtube_playlist'
|
|
||||||
| 'vimeo'
|
|
||||||
| 'facebook'
|
|
||||||
| 'reverbnation'
|
|
||||||
| 'attachment'
|
|
||||||
| 'youtube_search';
|
|
||||||
|
|
||||||
export interface ExtractorModelData {
|
|
||||||
title: string;
|
|
||||||
duration: number;
|
|
||||||
thumbnail: string;
|
|
||||||
engine: string | Readable | Duplex;
|
|
||||||
views: number;
|
|
||||||
author: string;
|
|
||||||
description: string;
|
|
||||||
url: string;
|
|
||||||
version?: string;
|
|
||||||
important?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PlayerProgressbarOptions {
|
|
||||||
timecodes?: boolean;
|
|
||||||
queue?: boolean;
|
|
||||||
length?: number;
|
|
||||||
line?: string;
|
|
||||||
indicator?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LyricsData {
|
|
||||||
title: string;
|
|
||||||
id: number;
|
|
||||||
thumbnail: string;
|
|
||||||
image: string;
|
|
||||||
url: string;
|
|
||||||
artist: {
|
|
||||||
name: string;
|
|
||||||
id: number;
|
|
||||||
url: string;
|
|
||||||
image: string;
|
|
||||||
};
|
|
||||||
lyrics?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PlayerStats {
|
|
||||||
uptime: number;
|
|
||||||
connections: number;
|
|
||||||
users: number;
|
|
||||||
queues: number;
|
|
||||||
extractors: number;
|
|
||||||
versions: {
|
|
||||||
ffmpeg: string;
|
|
||||||
node: string;
|
|
||||||
v8: string;
|
|
||||||
};
|
|
||||||
system: {
|
|
||||||
arch: string;
|
|
||||||
platform:
|
|
||||||
| 'aix'
|
|
||||||
| 'android'
|
|
||||||
| 'darwin'
|
|
||||||
| 'freebsd'
|
|
||||||
| 'linux'
|
|
||||||
| 'openbsd'
|
|
||||||
| 'sunos'
|
|
||||||
| 'win32'
|
|
||||||
| 'cygwin'
|
|
||||||
| 'netbsd';
|
|
||||||
cpu: number;
|
|
||||||
memory: {
|
|
||||||
total: string;
|
|
||||||
usage: string;
|
|
||||||
rss: string;
|
|
||||||
arrayBuffers: string;
|
|
||||||
};
|
|
||||||
uptime: number;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TimeData {
|
|
||||||
days: number;
|
|
||||||
hours: number;
|
|
||||||
minutes: number;
|
|
||||||
seconds: number;
|
|
||||||
}
|
|
||||||
|
|
71
yarn.lock
71
yarn.lock
|
@ -994,6 +994,26 @@
|
||||||
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
|
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
|
||||||
integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
|
integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
|
||||||
|
|
||||||
|
"@tsconfig/node10@^1.0.7":
|
||||||
|
version "1.0.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9"
|
||||||
|
integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==
|
||||||
|
|
||||||
|
"@tsconfig/node12@^1.0.7":
|
||||||
|
version "1.0.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.8.tgz#a883d62f049a64fea1e56a6bbe66828d11c6241b"
|
||||||
|
integrity sha512-LM6XwBhjZRls1qJGpiM/It09SntEwe9M0riXRfQ9s6XlJQG0JPGl92ET18LtGeYh/GuOtafIXqwZeqLOd0FNFQ==
|
||||||
|
|
||||||
|
"@tsconfig/node14@^1.0.0":
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2"
|
||||||
|
integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==
|
||||||
|
|
||||||
|
"@tsconfig/node16@^1.0.1":
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.1.tgz#a6ca6a9a0ff366af433f42f5f0e124794ff6b8f1"
|
||||||
|
integrity sha512-FTgBI767POY/lKNDNbIzgAX6miIDBs6NTCbdlDb8TrWovHsSvaVIZDlTqym29C6UqhzwcJx4CYr+AlrMywA0cA==
|
||||||
|
|
||||||
"@types/node@*":
|
"@types/node@*":
|
||||||
version "15.12.2"
|
version "15.12.2"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-15.12.2.tgz#1f2b42c4be7156ff4a6f914b2fb03d05fa84e38d"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-15.12.2.tgz#1f2b42c4be7156ff4a6f914b2fb03d05fa84e38d"
|
||||||
|
@ -1150,6 +1170,11 @@ are-we-there-yet@~1.1.2:
|
||||||
delegates "^1.0.0"
|
delegates "^1.0.0"
|
||||||
readable-stream "^2.0.6"
|
readable-stream "^2.0.6"
|
||||||
|
|
||||||
|
arg@^4.1.0:
|
||||||
|
version "4.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
|
||||||
|
integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
|
||||||
|
|
||||||
argparse@^1.0.7:
|
argparse@^1.0.7:
|
||||||
version "1.0.10"
|
version "1.0.10"
|
||||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
|
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
|
||||||
|
@ -1349,6 +1374,11 @@ browserslist@^4.16.6:
|
||||||
escalade "^3.1.1"
|
escalade "^3.1.1"
|
||||||
node-releases "^1.1.71"
|
node-releases "^1.1.71"
|
||||||
|
|
||||||
|
buffer-from@^1.0.0:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
||||||
|
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
|
||||||
|
|
||||||
builtin-modules@^1.1.1:
|
builtin-modules@^1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
|
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
|
||||||
|
@ -1655,6 +1685,11 @@ core-util-is@~1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||||
|
|
||||||
|
create-require@^1.1.0:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
|
||||||
|
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
|
||||||
|
|
||||||
cross-fetch@~3.1.4:
|
cross-fetch@~3.1.4:
|
||||||
version "3.1.4"
|
version "3.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.4.tgz#9723f3a3a247bf8b89039f3a380a9244e8fa2f39"
|
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.4.tgz#9723f3a3a247bf8b89039f3a380a9244e8fa2f39"
|
||||||
|
@ -2964,6 +2999,11 @@ make-dir@^3.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
semver "^6.0.0"
|
semver "^6.0.0"
|
||||||
|
|
||||||
|
make-error@^1.1.1:
|
||||||
|
version "1.3.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
|
||||||
|
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
|
||||||
|
|
||||||
map-cache@^0.2.2:
|
map-cache@^0.2.2:
|
||||||
version "0.2.2"
|
version "0.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
|
resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
|
||||||
|
@ -3788,6 +3828,14 @@ source-map-resolve@^0.5.0:
|
||||||
source-map-url "^0.4.0"
|
source-map-url "^0.4.0"
|
||||||
urix "^0.1.0"
|
urix "^0.1.0"
|
||||||
|
|
||||||
|
source-map-support@^0.5.17:
|
||||||
|
version "0.5.19"
|
||||||
|
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
|
||||||
|
integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
|
||||||
|
dependencies:
|
||||||
|
buffer-from "^1.0.0"
|
||||||
|
source-map "^0.6.0"
|
||||||
|
|
||||||
source-map-url@^0.4.0:
|
source-map-url@^0.4.0:
|
||||||
version "0.4.1"
|
version "0.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56"
|
resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56"
|
||||||
|
@ -3798,7 +3846,7 @@ source-map@^0.5.0, source-map@^0.5.6:
|
||||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
||||||
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
|
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
|
||||||
|
|
||||||
source-map@^0.6.1, source-map@~0.6.1:
|
source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
|
||||||
version "0.6.1"
|
version "0.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||||
|
@ -4085,6 +4133,22 @@ tr46@^2.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
punycode "^2.1.1"
|
punycode "^2.1.1"
|
||||||
|
|
||||||
|
ts-node@^10.0.0:
|
||||||
|
version "10.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.0.0.tgz#05f10b9a716b0b624129ad44f0ea05dac84ba3be"
|
||||||
|
integrity sha512-ROWeOIUvfFbPZkoDis0L/55Fk+6gFQNZwwKPLinacRl6tsxstTF1DbAcLKkovwnpKMVvOMHP1TIbnwXwtLg1gg==
|
||||||
|
dependencies:
|
||||||
|
"@tsconfig/node10" "^1.0.7"
|
||||||
|
"@tsconfig/node12" "^1.0.7"
|
||||||
|
"@tsconfig/node14" "^1.0.0"
|
||||||
|
"@tsconfig/node16" "^1.0.1"
|
||||||
|
arg "^4.1.0"
|
||||||
|
create-require "^1.1.0"
|
||||||
|
diff "^4.0.1"
|
||||||
|
make-error "^1.1.1"
|
||||||
|
source-map-support "^0.5.17"
|
||||||
|
yn "3.1.1"
|
||||||
|
|
||||||
tslib@^1.13.0, tslib@^1.8.1, tslib@^1.9.0:
|
tslib@^1.13.0, tslib@^1.8.1, tslib@^1.9.0:
|
||||||
version "1.14.1"
|
version "1.14.1"
|
||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
|
||||||
|
@ -4439,6 +4503,11 @@ yargs@^14.0.0:
|
||||||
y18n "^4.0.0"
|
y18n "^4.0.0"
|
||||||
yargs-parser "^15.0.1"
|
yargs-parser "^15.0.1"
|
||||||
|
|
||||||
|
yn@3.1.1:
|
||||||
|
version "3.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
|
||||||
|
integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==
|
||||||
|
|
||||||
youtube-sr@^4.1.4:
|
youtube-sr@^4.1.4:
|
||||||
version "4.1.4"
|
version "4.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/youtube-sr/-/youtube-sr-4.1.4.tgz#5ea646812264a951df7b1f6094f9f7406001dde6"
|
resolved "https://registry.yarnpkg.com/youtube-sr/-/youtube-sr-4.1.4.tgz#5ea646812264a951df7b1f6094f9f7406001dde6"
|
||||||
|
|
Loading…
Reference in a new issue