documentation

This commit is contained in:
Snowflake107 2021-04-19 19:17:10 +05:45
parent 9e30219f8e
commit 4a345d8097
6 changed files with 249 additions and 55 deletions

View file

@ -80,7 +80,7 @@ export class Player extends EventEmitter {
}
}
static get AudioFilters() {
static get AudioFilters(): typeof AudioFilters {
return AudioFilters;
}
@ -89,7 +89,7 @@ export class Player extends EventEmitter {
* @param extractorName The extractor name
* @param extractor The extractor itself
*/
use(extractorName: string, extractor: any) {
use(extractorName: string, extractor: any): Player {
if (!extractorName) throw new PlayerError('Missing extractor name!', 'PlayerExtractorError');
const methods = ['validate', 'getInfo'];
@ -108,7 +108,7 @@ export class Player extends EventEmitter {
* Remove existing extractor from this player
* @param extractorName The extractor name
*/
unuse(extractorName: string) {
unuse(extractorName: string): boolean {
if (!extractorName) throw new PlayerError('Missing extractor name!', 'PlayerExtractorError');
return this.Extractors.delete(extractorName);
@ -446,7 +446,7 @@ export class Player extends EventEmitter {
* Checks if this player is playing in a server
* @param message The message object
*/
isPlaying(message: Message) {
isPlaying(message: Message): boolean {
return this.queues.some((g) => g.guildID === message.guild.id);
}
@ -454,7 +454,7 @@ export class Player extends EventEmitter {
* Returns guild queue object
* @param message The message object
*/
getQueue(message: Message) {
getQueue(message: Message): Queue {
return this.queues.find((g) => g.guildID === message.guild.id);
}
@ -523,7 +523,7 @@ export class Player extends EventEmitter {
* @param time Time in ms to set
* @alias setPosition
*/
seek(message: Message, time: number) {
seek(message: Message, time: number): Promise<void> {
return this.setPosition(message, time);
}
@ -553,7 +553,7 @@ export class Player extends EventEmitter {
* @param message The message object
* @param channel New voice channel to move to
*/
moveTo(message: Message, channel?: VoiceChannel) {
moveTo(message: Message, channel?: VoiceChannel): boolean {
if (!channel || channel.type !== 'voice') return;
const queue = this.queues.find((g) => g.guildID === message.guild.id);
if (!queue) {
@ -579,7 +579,7 @@ export class Player extends EventEmitter {
* Pause the playback
* @param message The message object
*/
pause(message: Message) {
pause(message: Message): boolean {
const queue = this.getQueue(message);
if (!queue) {
this.emit(PlayerEvents.ERROR, PlayerErrorEventCodes.NOT_PLAYING, message);
@ -599,7 +599,7 @@ export class Player extends EventEmitter {
* Resume the playback
* @param message The message object
*/
resume(message: Message) {
resume(message: Message): boolean {
const queue = this.getQueue(message);
if (!queue) {
this.emit(PlayerEvents.ERROR, PlayerErrorEventCodes.NOT_PLAYING, message);
@ -619,7 +619,7 @@ export class Player extends EventEmitter {
* Stops the player
* @param message The message object
*/
stop(message: Message) {
stop(message: Message): boolean {
const queue = this.getQueue(message);
if (!queue) {
this.emit(PlayerEvents.ERROR, PlayerErrorEventCodes.NOT_PLAYING, message);
@ -644,7 +644,7 @@ export class Player extends EventEmitter {
* @param message The message object
* @param percent The volume percentage/amount to set
*/
setVolume(message: Message, percent: number) {
setVolume(message: Message, percent: number): boolean {
const queue = this.getQueue(message);
if (!queue) {
this.emit(PlayerEvents.ERROR, PlayerErrorEventCodes.NOT_PLAYING, message);
@ -665,7 +665,7 @@ export class Player extends EventEmitter {
* Clears the queue
* @param message The message object
*/
clearQueue(message: Message) {
clearQueue(message: Message): boolean {
const queue = this.getQueue(message);
if (!queue) {
this.emit(PlayerEvents.ERROR, PlayerErrorEventCodes.NOT_PLAYING, message);
@ -681,7 +681,7 @@ export class Player extends EventEmitter {
* Plays previous track
* @param message The message object
*/
back(message: Message) {
back(message: Message): boolean {
const queue = this.getQueue(message);
if (!queue) {
this.emit(PlayerEvents.ERROR, PlayerErrorEventCodes.NOT_PLAYING, message);
@ -704,7 +704,7 @@ export class Player extends EventEmitter {
* @param message The message object
* @param enabled If it should enable the repeat mode
*/
setRepeatMode(message: Message, enabled: boolean) {
setRepeatMode(message: Message, enabled: boolean): boolean {
const queue = this.getQueue(message);
if (!queue) {
this.emit(PlayerEvents.ERROR, PlayerErrorEventCodes.NOT_PLAYING, message);
@ -721,7 +721,7 @@ export class Player extends EventEmitter {
* @param message The message object
* @param enabled If it should enable the loop mode
*/
setLoopMode(message: Message, enabled: boolean) {
setLoopMode(message: Message, enabled: boolean): boolean {
const queue = this.getQueue(message);
if (!queue) {
this.emit(PlayerEvents.ERROR, PlayerErrorEventCodes.NOT_PLAYING, message);
@ -737,7 +737,7 @@ export class Player extends EventEmitter {
* Returns currently playing track
* @param message The message object
*/
nowPlaying(message: Message) {
nowPlaying(message: Message): Track {
const queue = this.getQueue(message);
if (!queue) {
this.emit(PlayerEvents.ERROR, PlayerErrorEventCodes.NOT_PLAYING, message);
@ -751,7 +751,7 @@ export class Player extends EventEmitter {
* Shuffles the queue
* @param message The message object
*/
shuffle(message: Message) {
shuffle(message: Message): Queue {
const queue = this.getQueue(message);
if (!queue) {
this.emit(PlayerEvents.ERROR, PlayerErrorEventCodes.NOT_PLAYING, message);
@ -775,7 +775,7 @@ export class Player extends EventEmitter {
* @param message The message object
* @param track The track object/id to remove
*/
remove(message: Message, track: Track | number) {
remove(message: Message, track: Track | number): Track {
const queue = this.getQueue(message);
if (!queue) {
this.emit(PlayerEvents.ERROR, PlayerErrorEventCodes.NOT_PLAYING, message);
@ -803,7 +803,7 @@ export class Player extends EventEmitter {
* @param message The message object
* @param queueTime If it should make the time code of the whole queue
*/
getTimeCode(message: Message, queueTime?: boolean) {
getTimeCode(message: Message, queueTime?: boolean): { current: string; end: string } {
const queue = this.getQueue(message);
if (!queue) return;
@ -827,7 +827,7 @@ export class Player extends EventEmitter {
* @param message The message object
* @param options Progressbar options
*/
createProgressBar(message: Message, options?: PlayerProgressbarOptions) {
createProgressBar(message: Message, options?: PlayerProgressbarOptions): string {
const queue = this.getQueue(message);
if (!queue) return;
@ -876,14 +876,14 @@ export class Player extends EventEmitter {
* @example const lyrics = await player.lyrics("alan walker faded")
* message.channel.send(lyrics.lyrics);
*/
async lyrics(query: string) {
async lyrics(query: string): Promise<LyricsData> {
const extractor = Util.require('@discord-player/extractor');
if (!extractor) throw new PlayerError("Cannot call 'Player.lyrics()' without '@discord-player/extractor'");
const data = await extractor.Lyrics(query);
if (Array.isArray(data)) return null;
return data as LyricsData;
return data;
}
/**
@ -931,7 +931,7 @@ export class Player extends EventEmitter {
};
}
private _handleVoiceStateUpdate(oldState: VoiceState, newState: VoiceState) {
private _handleVoiceStateUpdate(oldState: VoiceState, newState: VoiceState): void {
const queue = this.queues.find((g) => g.guildID === oldState.guild.id);
if (!queue) return;
@ -964,7 +964,7 @@ export class Player extends EventEmitter {
}
}
private _addTrackToQueue(message: Message, track: Track) {
private _addTrackToQueue(message: Message, track: Track): Queue {
const queue = this.getQueue(message);
if (!queue)
this.emit(
@ -978,7 +978,7 @@ export class Player extends EventEmitter {
return queue;
}
private _addTracksToQueue(message: Message, tracks: Track[]) {
private _addTracksToQueue(message: Message, tracks: Track[]): Queue {
const queue = this.getQueue(message);
if (!queue)
throw new PlayerError(
@ -1174,3 +1174,109 @@ export class Player extends EventEmitter {
}
export default Player;
/**
* Emitted when a track starts
* @event Player#trackStart
* @param {Discord.Message} message
* @param {Track} track
* @param {Queue} queue
*/
/**
* Emitted when a playlist is started
* @event Player#queueCreate
* @param {Discord.Message} message
* @param {Queue} queue
*/
/**
* Emitted when the bot is awaiting search results
* @event Player#searchResults
* @param {Discord.Message} message
* @param {string} query
* @param {Track[]} tracks
* @param {Discord.Collector} collector
*/
/**
* Emitted when the user has sent an invalid response for search results
* @event Player#searchInvalidResponse
* @param {Discord.Message} message
* @param {string} query
* @param {Track[]} tracks
* @param {string} invalidResponse
* @param {Discord.MessageCollector} collector
*/
/**
* Emitted when the bot has stopped awaiting search results (timeout)
* @event Player#searchCancel
* @param {Discord.Message} message
* @param {string} query
* @param {Track[]} tracks
*/
/**
* Emitted when the bot can't find related results to the query
* @event Player#noResults
* @param {Discord.Message} message
* @param {string} query
*/
/**
* Emitted when the bot is disconnected from the channel
* @event Player#botDisconnect
* @param {Discord.Message} message
*/
/**
* Emitted when the channel of the bot is empty
* @event Player#channelEmpty
* @param {Discord.Message} message
* @param {Queue} queue
*/
/**
* Emitted when the queue of the server is ended
* @event Player#queueEnd
* @param {Discord.Message} message
* @param {Queue} queue
*/
/**
* Emitted when a track is added to the queue
* @event Player#trackAdd
* @param {Discord.Message} message
* @param {Queue} queue
* @param {Track} track
*/
/**
* Emitted when a playlist is added to the queue
* @event Player#playlistAdd
* @param {Discord.Message} message
* @param {Queue} queue
* @param {Object} playlist
*/
/**
* Emitted when an error is triggered
* @event Player#error
* @param {string} error It can be `NotConnected`, `UnableToJoin`, `NotPlaying`, `ParseError`, `LiveVideo` or `VideoUnavailable`.
* @param {Discord.Message} message
*/
/**
* Emitted when discord-player attempts to parse playlist contents (mostly soundcloud playlists)
* @event Player#playlistParseStart
* @param {Object} playlist Raw playlist (unparsed)
* @param {Discord.Message} message The message
*/
/**
* Emitted when discord-player finishes parsing playlist contents (mostly soundcloud playlists)
* @event Player#playlistParseEnd
* @param {Object} playlist The playlist data (parsed)
* @param {Discord.Message} message The message
*/

View file

@ -4,13 +4,26 @@ class ExtractorModel {
name: string;
private _raw: any;
/**
* Model for raw Discord Player extractors
* @param extractorName Name of the extractor
* @param data Extractor object
*/
constructor(extractorName: string, data: any) {
/**
* The extractor name
*/
this.name = extractorName;
Object.defineProperty(this, '_raw', { value: data, configurable: false, writable: false, enumerable: false });
}
async handle(query: string) {
/**
* Method to handle requests from `Player.play()`
* @param query Query to handle
*/
async handle(query: string): Promise<ExtractorModelData> {
const data = await this._raw.getInfo(query);
if (!data) return null;
@ -23,18 +36,28 @@ class ExtractorModel {
author: data.author,
description: data.description,
url: data.url
} as ExtractorModelData;
};
}
validate(query: string) {
/**
* Method used by Discord Player to validate query with this extractor
* @param query The query to validate
*/
validate(query: string): boolean {
return Boolean(this._raw.validate(query));
}
get version() {
/**
* The extractor version
*/
get version(): string {
return this._raw.version ?? '0.0.0';
}
get important() {
/**
* If player should mark this extractor as important
*/
get important(): boolean {
return Boolean(this._raw.important);
}
}

View file

@ -26,6 +26,11 @@ export class Queue extends EventEmitter {
public firstMessage: Message;
public autoPlay = false;
/**
* Queue constructor
* @param player The player that instantiated this Queue
* @param message The message object
*/
constructor(player: Player, message: Message) {
super();
@ -91,40 +96,41 @@ export class Queue extends EventEmitter {
*/
this.firstMessage = message;
// @ts-ignore
/**
* The audio filters in this queue
*/
this.filters = {};
Object.keys(AudioFilters).forEach((fn) => {
// @ts-ignore
this.filters[fn] = false;
this.filters[fn as keyof QueueFilters] = false;
});
}
/**
* Currently playing track
*/
get playing() {
get playing(): Track {
return this.tracks[0];
}
/**
* Calculated volume of this queue
*/
get calculatedVolume() {
get calculatedVolume(): number {
return this.filters.normalizer ? this.volume + 70 : this.volume;
}
/**
* Total duration
*/
get totalTime() {
get totalTime(): number {
return this.tracks.length > 0 ? this.tracks.map((t) => t.durationMS).reduce((p, c) => p + c) : 0;
}
/**
* Current stream time
*/
get currentStreamTime() {
get currentStreamTime(): number {
return this.voiceConnection?.dispatcher?.streamTime + this.additionalStreamTime || 0;
}
@ -132,14 +138,14 @@ export class Queue extends EventEmitter {
* Sets audio filters in this player
* @param filters Audio filters to set
*/
setFilters(filters: QueueFilters) {
setFilters(filters: QueueFilters): Promise<void> {
return this.player.setFilters(this.firstMessage, filters);
}
/**
* Returns array of all enabled filters
*/
getFiltersEnabled() {
getFiltersEnabled(): string[] {
const filters: string[] = [];
for (const filter in this.filters) {
@ -152,13 +158,16 @@ export class Queue extends EventEmitter {
/**
* Returns all disabled filters
*/
getFiltersDisabled() {
getFiltersDisabled(): string[] {
const enabled = this.getFiltersEnabled();
return Object.keys(this.filters).filter((f) => !enabled.includes(f));
}
toString() {
/**
* String representation of this Queue
*/
toString(): string {
return `<Queue ${this.guildID}>`;
}
}

View file

@ -1,23 +1,69 @@
import { Player } from '../Player';
import { User } from 'discord.js';
import { TrackData } from '../types/types';
import Queue from './Queue';
export class Track {
/**
* The player that instantiated this Track
*/
public player!: Player;
/**
* Title of this track
*/
public title!: string;
/**
* Description of this track
*/
public description!: string;
/**
* Author of this track
*/
public author!: string;
/**
* Link of this track
*/
public url!: string;
/**
* Thumbnail of this track
*/
public thumbnail!: string;
/**
* Duration of this track
*/
public duration!: string;
/**
* View count of this track
*/
public views!: number;
/**
* Person who requested this track
*/
public requestedBy!: User;
/**
* If this track belongs to a playlist
*/
public fromPlaylist!: boolean;
/**
* Raw data of this track
*/
public raw!: TrackData;
/**
* Track constructor
* @param player The player that instantiated this Track
* @param data Track data
*/
constructor(player: Player, data: TrackData) {
Object.defineProperty(this, 'player', { value: player, enumerable: false });
@ -42,14 +88,14 @@ export class Track {
/**
* The queue in which this track is located
*/
get queue() {
get queue(): Queue {
return this.player.queues.find((q) => q.tracks.includes(this));
}
/**
* The track duration in millisecond
*/
get durationMS() {
get durationMS(): number {
const times = (n: number, t: number) => {
let tn = 1;
for (let i = 0; i < t; i++) tn *= n;
@ -63,7 +109,10 @@ export class Track {
.reduce((a, c) => a + c, 0);
}
toString() {
/**
* String representation of this track
*/
toString(): string {
return `${this.title} by ${this.author}`;
}
}

View file

@ -145,3 +145,10 @@ export interface PlayerStats {
uptime: number;
};
}
export interface TimeData {
days: number;
hours: number;
minutes: number;
seconds: number;
}

View file

@ -1,4 +1,4 @@
import { QueryType } from '../types/types';
import { QueryType, TimeData } from '../types/types';
import { FFmpeg } from 'prism-media';
import YouTube from 'youtube-sr';
import { Track } from '../Structures/Track';
@ -19,7 +19,7 @@ export class Util {
throw new Error(`The ${this.constructor.name} class is static and cannot be instantiated!`);
}
static getFFmpegVersion(force?: boolean) {
static getFFmpegVersion(force?: boolean): string {
try {
const info = FFmpeg.getInfo(Boolean(force));
@ -29,12 +29,12 @@ export class Util {
}
}
static checkFFmpeg(force?: boolean) {
static checkFFmpeg(force?: boolean): boolean {
const version = Util.getFFmpegVersion(force);
return version === null ? false : true;
}
static alertFFmpeg() {
static alertFFmpeg(): void {
const hasFFmpeg = Util.checkFFmpeg();
if (!hasFFmpeg)
@ -59,11 +59,11 @@ export class Util {
return 'youtube_search';
}
static isURL(str: string) {
static isURL(str: string): boolean {
return str.length < 2083 && attachmentRegex.test(str);
}
static getVimeoID(query: string) {
static getVimeoID(query: string): string {
return Util.getQueryType(query) === 'vimeo'
? query
.split('/')
@ -72,7 +72,7 @@ export class Util {
: null;
}
static parseMS(milliseconds: number) {
static parseMS(milliseconds: number): TimeData {
const roundTowardsZero = milliseconds > 0 ? Math.floor : Math.ceil;
return {
@ -83,7 +83,7 @@ export class Util {
};
}
static durationString(durObj: object) {
static durationString(durObj: object): string {
return Object.values(durObj)
.map((m) => (isNaN(m) ? 0 : m))
.join(':');
@ -119,7 +119,7 @@ export class Util {
});
}
static isRepl() {
static isRepl(): boolean {
if ('DP_REPL_NOCHECK' in process.env) return false;
const REPL_IT_PROPS = [
@ -137,11 +137,11 @@ export class Util {
return false;
}
static isVoiceEmpty(channel: VoiceChannel) {
static isVoiceEmpty(channel: VoiceChannel): boolean {
return channel.members.filter((member) => !member.user.bot).size === 0;
}
static buildTimeCode(data: any) {
static buildTimeCode(data: any): string {
const items = Object.keys(data);
const required = ['days', 'hours', 'minutes', 'seconds'];