discord-player-play-dl/src/Player.ts

151 lines
5.5 KiB
TypeScript
Raw Normal View History

2021-04-06 17:58:46 +05:00
import YouTube from 'youtube-sr';
import { EventEmitter } from 'events';
import { Client, Collection, Snowflake, Collector, Message } from 'discord.js';
import { PlayerOptions } from './types/types';
import Util from './utils/Util';
import AudioFilters from './utils/AudioFilters';
import Queue from './Structures/Queue';
import Track from './Structures/Track';
import { PlayerEvents } from './utils/Constants';
2021-04-06 17:55:29 +05:00
// @ts-ignore
2021-04-06 17:58:46 +05:00
import spotify from 'spotify-url-info';
2021-04-06 17:55:29 +05:00
// @ts-ignore
2021-04-06 17:58:46 +05:00
import { Client as SoundCloudClient } from 'soundcloud-scraper';
2021-04-06 17:55:29 +05:00
2021-04-06 17:58:46 +05:00
const SoundCloud = new SoundCloudClient();
2021-04-04 22:36:40 +05:00
export default class Player extends EventEmitter {
public client!: Client;
public options: PlayerOptions;
2021-04-06 17:55:29 +05:00
public filters: typeof AudioFilters;
public queues: Collection<Snowflake, Queue>;
private _resultsCollectors: Collection<string, Collector<Snowflake, Message>>;
private _cooldownsTimeout: Collection<string, NodeJS.Timeout>;
2021-04-04 22:36:40 +05:00
constructor(client: Client, options?: PlayerOptions) {
super();
/**
* The discord client that instantiated this player
*/
2021-04-06 17:58:46 +05:00
Object.defineProperty(this, 'client', {
2021-04-04 22:36:40 +05:00
value: client,
enumerable: false
});
/**
* The player options
*/
this.options = Object.assign({}, Util.DefaultPlayerOptions, options ?? {});
// check FFmpeg
void Util.alertFFmpeg();
2021-04-06 17:55:29 +05:00
/**
* The audio filters
*/
this.filters = AudioFilters;
/**
* Player queues
*/
this.queues = new Collection();
}
static get AudioFilters() {
return AudioFilters;
}
2021-04-06 17:58:46 +05:00
private _searchTracks(
message: Message,
query: string,
2021-04-06 17:59:07 +05:00
firstResult?: boolean
2021-04-06 17:58:46 +05:00
): Promise<Track> {
2021-04-06 17:55:29 +05:00
return new Promise(async (resolve) => {
let tracks: Track[] = [];
2021-04-06 17:58:46 +05:00
const queryType = Util.getQueryType(query);
switch (queryType) {
case 'soundcloud_track':
{
const data = await SoundCloud.getSongInfo(query).catch(() => {});
if (data) {
const track = new Track(this, {
title: data.title,
url: data.url,
duration: Util.durationString(Util.parseMS(data.duration / 1000)),
description: data.description,
thumbnail: data.thumbnail,
views: data.playCount,
author: data.author,
requestedBy: message.author,
fromPlaylist: false,
source: 'soundcloud',
engine: data
});
tracks.push(track);
}
2021-04-06 17:55:29 +05:00
}
2021-04-06 17:58:46 +05:00
break;
case 'spotify_song':
{
const matchSpotifyURL = query.match(
/https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(?:track\/|\?uri=spotify:track:)((\w|-){22})/
);
if (matchSpotifyURL) {
const spotifyData = await spotify.getPreview(query).catch(() => {});
if (spotifyData) {
tracks = await Util.ytSearch(`${spotifyData.artist} - ${spotifyData.title}`, {
user: message.author,
player: this
});
}
2021-04-06 17:55:29 +05:00
}
}
2021-04-06 17:58:46 +05:00
break;
2021-04-06 17:55:29 +05:00
default:
tracks = await Util.ytSearch(query, { user: message.author, player: this });
}
if (tracks.length < 1) return this.emit(PlayerEvents.NO_RESULTS, message, query);
if (firstResult) return resolve(tracks[0]);
const collectorString = `${message.author.id}-${message.channel.id}`;
const currentCollector = this._resultsCollectors.get(collectorString);
2021-04-06 17:58:46 +05:00
if (currentCollector) currentCollector.stop();
2021-04-06 17:55:29 +05:00
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);
2021-04-06 17:58:46 +05:00
collector.on('collect', ({ content }) => {
if (content === 'cancel') {
2021-04-06 17:55:29 +05:00
collector.stop();
return 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);
}
2021-04-06 17:58:46 +05:00
});
2021-04-06 17:55:29 +05:00
2021-04-06 17:58:46 +05:00
collector.on('end', (collected, reason) => {
if (reason === 'time') {
2021-04-06 17:55:29 +05:00
this.emit(PlayerEvents.SEARCH_CANCEL, message, query, tracks);
}
});
});
2021-04-04 22:36:40 +05:00
}
2021-04-04 22:44:45 +05:00
}