format
This commit is contained in:
parent
b40c070b2e
commit
073d94e7a9
9 changed files with 244 additions and 211 deletions
112
src/Player.ts
112
src/Player.ts
|
@ -1,19 +1,19 @@
|
||||||
import YouTube from "youtube-sr";
|
import YouTube from 'youtube-sr';
|
||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from 'events';
|
||||||
import { Client, Collection, Snowflake, Collector, Message } from "discord.js";
|
import { Client, Collection, Snowflake, Collector, Message } from 'discord.js';
|
||||||
import { PlayerOptions } from "./types/types";
|
import { PlayerOptions } from './types/types';
|
||||||
import Util from "./utils/Util";
|
import Util from './utils/Util';
|
||||||
import AudioFilters from "./utils/AudioFilters";
|
import AudioFilters from './utils/AudioFilters';
|
||||||
import Queue from "./Structures/Queue";
|
import Queue from './Structures/Queue';
|
||||||
import Track from "./Structures/Track";
|
import Track from './Structures/Track';
|
||||||
import { PlayerEvents } from "./utils/Constants";
|
import { PlayerEvents } from './utils/Constants';
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import spotify from "spotify-url-info";
|
import spotify from 'spotify-url-info';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { Client as SoundCloudClient } from "soundcloud-scraper";
|
import { Client as SoundCloudClient } from 'soundcloud-scraper';
|
||||||
|
|
||||||
const SoundCloud = new SoundCloudClient;
|
const SoundCloud = new SoundCloudClient();
|
||||||
|
|
||||||
export default class Player extends EventEmitter {
|
export default class Player extends EventEmitter {
|
||||||
public client!: Client;
|
public client!: Client;
|
||||||
|
@ -29,7 +29,7 @@ export default class Player extends EventEmitter {
|
||||||
/**
|
/**
|
||||||
* The discord client that instantiated this player
|
* The discord client that instantiated this player
|
||||||
*/
|
*/
|
||||||
Object.defineProperty(this, "client", {
|
Object.defineProperty(this, 'client', {
|
||||||
value: client,
|
value: client,
|
||||||
enumerable: false
|
enumerable: false
|
||||||
});
|
});
|
||||||
|
@ -57,43 +57,55 @@ export default class Player extends EventEmitter {
|
||||||
return AudioFilters;
|
return AudioFilters;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _searchTracks(message: Message, query: string, firstResult?: boolean, isAttachment?: boolean): Promise<Track> {
|
private _searchTracks(
|
||||||
|
message: Message,
|
||||||
|
query: string,
|
||||||
|
firstResult?: boolean,
|
||||||
|
isAttachment?: boolean
|
||||||
|
): Promise<Track> {
|
||||||
return new Promise(async (resolve) => {
|
return new Promise(async (resolve) => {
|
||||||
let tracks: Track[] = [];
|
let tracks: Track[] = [];
|
||||||
let queryType = Util.getQueryType(query);
|
const queryType = Util.getQueryType(query);
|
||||||
|
|
||||||
switch(queryType) {
|
switch (queryType) {
|
||||||
case "soundcloud_track": {
|
case 'soundcloud_track':
|
||||||
const data = await SoundCloud.getSongInfo(query).catch(() => { })
|
{
|
||||||
if (data) {
|
const data = await SoundCloud.getSongInfo(query).catch(() => {});
|
||||||
const track = new Track(this, {
|
if (data) {
|
||||||
title: data.title,
|
const track = new Track(this, {
|
||||||
url: data.url,
|
title: data.title,
|
||||||
duration: Util.durationString(Util.parseMS(data.duration / 1000)),
|
url: data.url,
|
||||||
description: data.description,
|
duration: Util.durationString(Util.parseMS(data.duration / 1000)),
|
||||||
thumbnail: data.thumbnail,
|
description: data.description,
|
||||||
views: data.playCount,
|
thumbnail: data.thumbnail,
|
||||||
author: data.author,
|
views: data.playCount,
|
||||||
requestedBy: message.author,
|
author: data.author,
|
||||||
fromPlaylist: false,
|
requestedBy: message.author,
|
||||||
source: "soundcloud",
|
fromPlaylist: false,
|
||||||
engine: data
|
source: 'soundcloud',
|
||||||
});
|
engine: data
|
||||||
|
});
|
||||||
|
|
||||||
tracks.push(track)
|
tracks.push(track);
|
||||||
}
|
|
||||||
}
|
|
||||||
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 });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
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
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
tracks = await Util.ytSearch(query, { user: message.author, player: this });
|
tracks = await Util.ytSearch(query, { user: message.author, player: this });
|
||||||
}
|
}
|
||||||
|
@ -103,7 +115,7 @@ export default class Player extends EventEmitter {
|
||||||
|
|
||||||
const collectorString = `${message.author.id}-${message.channel.id}`;
|
const collectorString = `${message.author.id}-${message.channel.id}`;
|
||||||
const currentCollector = this._resultsCollectors.get(collectorString);
|
const currentCollector = this._resultsCollectors.get(collectorString);
|
||||||
if (currentCollector) currentCollector.stop()
|
if (currentCollector) currentCollector.stop();
|
||||||
|
|
||||||
const collector = message.channel.createMessageCollector((m) => m.author.id === message.author.id, {
|
const collector = message.channel.createMessageCollector((m) => m.author.id === message.author.id, {
|
||||||
time: 60000
|
time: 60000
|
||||||
|
@ -113,8 +125,8 @@ export default class Player extends EventEmitter {
|
||||||
|
|
||||||
this.emit(PlayerEvents.SEARCH_RESULTS, message, query, tracks, collector);
|
this.emit(PlayerEvents.SEARCH_RESULTS, message, query, tracks, collector);
|
||||||
|
|
||||||
collector.on("collect", ({ content }) => {
|
collector.on('collect', ({ content }) => {
|
||||||
if (content === "cancel") {
|
if (content === 'cancel') {
|
||||||
collector.stop();
|
collector.stop();
|
||||||
return this.emit(PlayerEvents.SEARCH_CANCEL, message, query, tracks);
|
return this.emit(PlayerEvents.SEARCH_CANCEL, message, query, tracks);
|
||||||
}
|
}
|
||||||
|
@ -127,10 +139,10 @@ export default class Player extends EventEmitter {
|
||||||
} else {
|
} else {
|
||||||
this.emit(PlayerEvents.SEARCH_INVALID_RESPONSE, message, query, tracks, content, collector);
|
this.emit(PlayerEvents.SEARCH_INVALID_RESPONSE, message, query, tracks, content, collector);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
collector.on("end", (collected, reason) => {
|
collector.on('end', (collected, reason) => {
|
||||||
if (reason === "time") {
|
if (reason === 'time') {
|
||||||
this.emit(PlayerEvents.SEARCH_CANCEL, message, query, tracks);
|
this.emit(PlayerEvents.SEARCH_CANCEL, message, query, tracks);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { Message, Snowflake, VoiceConnection } from "discord.js";
|
import { Message, Snowflake, VoiceConnection } from 'discord.js';
|
||||||
import AudioFilters from "../utils/AudioFilters";
|
import AudioFilters from '../utils/AudioFilters';
|
||||||
import Player from "../Player";
|
import Player from '../Player';
|
||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from 'events';
|
||||||
import Track from "./Track";
|
import Track from './Track';
|
||||||
import { QueueFilters } from "../types/types";
|
import { QueueFilters } from '../types/types';
|
||||||
|
|
||||||
export default class Queue extends EventEmitter {
|
export default class Queue extends EventEmitter {
|
||||||
public player!: Player;
|
public player!: Player;
|
||||||
|
@ -28,7 +28,7 @@ export default class Queue extends EventEmitter {
|
||||||
/**
|
/**
|
||||||
* The player that instantiated this Queue
|
* The player that instantiated this Queue
|
||||||
*/
|
*/
|
||||||
Object.defineProperty(this, "player", { value: player, enumerable: false });
|
Object.defineProperty(this, 'player', { value: player, enumerable: false });
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID of the guild assigned to this queue
|
* ID of the guild assigned to this queue
|
||||||
|
@ -93,7 +93,7 @@ export default class Queue extends EventEmitter {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.filters = {};
|
this.filters = {};
|
||||||
|
|
||||||
Object.keys(AudioFilters).forEach(fn => {
|
Object.keys(AudioFilters).forEach((fn) => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.filters[fn] = false;
|
this.filters[fn] = false;
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import Player from "../Player";
|
import Player from '../Player';
|
||||||
import { User } from "discord.js";
|
import { User } from 'discord.js';
|
||||||
import { TrackData } from "../types/types";
|
import { TrackData } from '../types/types';
|
||||||
|
|
||||||
export default class Track {
|
export default class Track {
|
||||||
public player!: Player;
|
public player!: Player;
|
||||||
|
@ -19,31 +19,31 @@ export default class Track {
|
||||||
/**
|
/**
|
||||||
* The player that instantiated this Track
|
* The player that instantiated this Track
|
||||||
*/
|
*/
|
||||||
Object.defineProperty(this, "player", { value: player, enumerable: false });
|
Object.defineProperty(this, 'player', { value: player, enumerable: false });
|
||||||
|
|
||||||
void this._patch(data);
|
void this._patch(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _patch(data: TrackData) {
|
private _patch(data: TrackData) {
|
||||||
this.title = data.title ?? "";
|
this.title = data.title ?? '';
|
||||||
this.description = data.description ?? "";
|
this.description = data.description ?? '';
|
||||||
this.author = data.author ?? "";
|
this.author = data.author ?? '';
|
||||||
this.url = data.url ?? "";
|
this.url = data.url ?? '';
|
||||||
this.thumbnail = data.thumbnail ?? "";
|
this.thumbnail = data.thumbnail ?? '';
|
||||||
this.duration = data.duration ?? "";
|
this.duration = data.duration ?? '';
|
||||||
this.views = data.views ?? 0;
|
this.views = data.views ?? 0;
|
||||||
this.requestedBy = data.requestedBy;
|
this.requestedBy = data.requestedBy;
|
||||||
this.fromPlaylist = Boolean(data.fromPlaylist);
|
this.fromPlaylist = Boolean(data.fromPlaylist);
|
||||||
|
|
||||||
// raw
|
// raw
|
||||||
Object.defineProperty(this, "raw", { get: () => data, enumerable: false });
|
Object.defineProperty(this, 'raw', { get: () => data, enumerable: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The queue in which this track is located
|
* The queue in which this track is located
|
||||||
*/
|
*/
|
||||||
get queue() {
|
get queue() {
|
||||||
return this.player.queues.find(q => q.tracks.includes(this));
|
return this.player.queues.find((q) => q.tracks.includes(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -56,7 +56,11 @@ export default class Track {
|
||||||
return t <= 0 ? 1000 : tn * 1000;
|
return t <= 0 ? 1000 : tn * 1000;
|
||||||
};
|
};
|
||||||
|
|
||||||
return this.duration.split(":").reverse().map((m, i) => parseInt(m) * times(60, i)).reduce((a, c) => a + c, 0);
|
return this.duration
|
||||||
|
.split(':')
|
||||||
|
.reverse()
|
||||||
|
.map((m, i) => parseInt(m) * times(60, i))
|
||||||
|
.reduce((a, c) => a + c, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
toString() {
|
toString() {
|
||||||
|
|
14
src/index.ts
14
src/index.ts
|
@ -1,7 +1,7 @@
|
||||||
export * as AudioFilters from "./utils/AudioFilters";
|
export * as AudioFilters from './utils/AudioFilters';
|
||||||
export * as Player from "./Player";
|
export * as Player from './Player';
|
||||||
export * as Util from "./utils/Util";
|
export * as Util from './utils/Util';
|
||||||
export * as Track from "./Structures/Track";
|
export * as Track from './Structures/Track';
|
||||||
export * as Queue from "./Structures/Queue";
|
export * as Queue from './Structures/Queue';
|
||||||
export * from "./types/types";
|
export * from './types/types';
|
||||||
export { version } from "../package.json";
|
export { version } from '../package.json';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { downloadOptions } from "ytdl-core";
|
import { downloadOptions } from 'ytdl-core';
|
||||||
import { User } from "discord.js";
|
import { User } from 'discord.js';
|
||||||
|
|
||||||
export interface PlayerOptions {
|
export interface PlayerOptions {
|
||||||
leaveOnEnd?: boolean;
|
leaveOnEnd?: boolean;
|
||||||
|
@ -14,36 +14,36 @@ export interface PlayerOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FiltersName =
|
export type FiltersName =
|
||||||
| "bassboost"
|
| 'bassboost'
|
||||||
| "8D"
|
| '8D'
|
||||||
| "vaporwave"
|
| 'vaporwave'
|
||||||
| "nightcore"
|
| 'nightcore'
|
||||||
| "phaser"
|
| 'phaser'
|
||||||
| "tremolo"
|
| 'tremolo'
|
||||||
| "vibrato"
|
| 'vibrato'
|
||||||
| "reverse"
|
| 'reverse'
|
||||||
| "treble"
|
| 'treble'
|
||||||
| "normalizer"
|
| 'normalizer'
|
||||||
| "surrounding"
|
| 'surrounding'
|
||||||
| "pulsator"
|
| 'pulsator'
|
||||||
| "subboost"
|
| 'subboost'
|
||||||
| "karaoke"
|
| 'karaoke'
|
||||||
| "flanger"
|
| 'flanger'
|
||||||
| "gate"
|
| 'gate'
|
||||||
| "haas"
|
| 'haas'
|
||||||
| "mcompand"
|
| 'mcompand'
|
||||||
| "mono"
|
| 'mono'
|
||||||
| "mstlr"
|
| 'mstlr'
|
||||||
| "mstrr"
|
| 'mstrr'
|
||||||
| "compressor"
|
| 'compressor'
|
||||||
| "expander"
|
| 'expander'
|
||||||
| "softlimiter"
|
| 'softlimiter'
|
||||||
| "chorus"
|
| 'chorus'
|
||||||
| "chorus2d"
|
| 'chorus2d'
|
||||||
| "chorus3d"
|
| 'chorus3d'
|
||||||
| "fadein";
|
| 'fadein';
|
||||||
|
|
||||||
export type TrackSource = "soundcloud" | "youtube" | "arbitrary";
|
export type TrackSource = 'soundcloud' | 'youtube' | 'arbitrary';
|
||||||
|
|
||||||
export interface TrackData {
|
export interface TrackData {
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -60,46 +60,46 @@ export interface TrackData {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type QueueFilters = {
|
export type QueueFilters = {
|
||||||
"bassboost": boolean;
|
bassboost: boolean;
|
||||||
"8D": boolean;
|
'8D': boolean;
|
||||||
"vaporwave": boolean;
|
vaporwave: boolean;
|
||||||
"nightcore": boolean;
|
nightcore: boolean;
|
||||||
"phaser": boolean;
|
phaser: boolean;
|
||||||
"tremolo": boolean;
|
tremolo: boolean;
|
||||||
"vibrato": boolean;
|
vibrato: boolean;
|
||||||
"reverse": boolean;
|
reverse: boolean;
|
||||||
"treble": boolean;
|
treble: boolean;
|
||||||
"normalizer": boolean;
|
normalizer: boolean;
|
||||||
"surrounding": boolean;
|
surrounding: boolean;
|
||||||
"pulsator": boolean;
|
pulsator: boolean;
|
||||||
"subboost": boolean;
|
subboost: boolean;
|
||||||
"karaoke": boolean;
|
karaoke: boolean;
|
||||||
"flanger": boolean;
|
flanger: boolean;
|
||||||
"gate": boolean;
|
gate: boolean;
|
||||||
"haas": boolean;
|
haas: boolean;
|
||||||
"mcompand": boolean;
|
mcompand: boolean;
|
||||||
"mono": boolean;
|
mono: boolean;
|
||||||
'mstlr': boolean;
|
mstlr: boolean;
|
||||||
"mstrr": boolean;
|
mstrr: boolean;
|
||||||
"compressor": boolean;
|
compressor: boolean;
|
||||||
"expander": boolean;
|
expander: boolean;
|
||||||
"softlimiter": boolean;
|
softlimiter: boolean;
|
||||||
"chorus": boolean;
|
chorus: boolean;
|
||||||
"chorus2d": boolean;
|
chorus2d: boolean;
|
||||||
"chorus3d": boolean;
|
chorus3d: boolean;
|
||||||
"fadein": boolean;
|
fadein: boolean;
|
||||||
}
|
};
|
||||||
|
|
||||||
export type QueryType =
|
export type QueryType =
|
||||||
| "soundcloud_track"
|
| 'soundcloud_track'
|
||||||
| "soundcloud_playlist"
|
| 'soundcloud_playlist'
|
||||||
| "spotify_song"
|
| 'spotify_song'
|
||||||
| "spotify_album"
|
| 'spotify_album'
|
||||||
| "spotify_playlist"
|
| 'spotify_playlist'
|
||||||
| "youtube_video"
|
| 'youtube_video'
|
||||||
| "youtube_playlist"
|
| 'youtube_playlist'
|
||||||
| "vimeo"
|
| 'vimeo'
|
||||||
| "facebook"
|
| 'facebook'
|
||||||
| "reverbnation"
|
| 'reverbnation'
|
||||||
| "attachment"
|
| 'attachment'
|
||||||
| "youtube_search";
|
| 'youtube_search';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { FiltersName } from "../types/types";
|
import { FiltersName } from '../types/types';
|
||||||
|
|
||||||
const FilterList = {
|
const FilterList = {
|
||||||
bassboost: 'bass=g=20',
|
bassboost: 'bass=g=20',
|
||||||
|
@ -47,7 +47,10 @@ const FilterList = {
|
||||||
},
|
},
|
||||||
create(filter?: FiltersName[]) {
|
create(filter?: FiltersName[]) {
|
||||||
if (!filter || !Array.isArray(filter)) return this.toString();
|
if (!filter || !Array.isArray(filter)) return this.toString();
|
||||||
return filter.filter(predicate => typeof predicate === "string").map(m => this[m]).join(",");
|
return filter
|
||||||
|
.filter((predicate) => typeof predicate === 'string')
|
||||||
|
.map((m) => this[m])
|
||||||
|
.join(',');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
export const PlayerEvents = {
|
export const PlayerEvents = {
|
||||||
BOT_DISCONNECT: "botDisconnect",
|
BOT_DISCONNECT: 'botDisconnect',
|
||||||
CHANNEL_EMPTY: "channelEmpty",
|
CHANNEL_EMPTY: 'channelEmpty',
|
||||||
ERROR: "error",
|
ERROR: 'error',
|
||||||
NO_RESULTS: "noResults",
|
NO_RESULTS: 'noResults',
|
||||||
PLAYLIST_ADD: "playlistAdd",
|
PLAYLIST_ADD: 'playlistAdd',
|
||||||
PLAYLIST_PARSE_END: "playlistParseEnd",
|
PLAYLIST_PARSE_END: 'playlistParseEnd',
|
||||||
PLAYLIST_PARSE_START: "playlistParseStart",
|
PLAYLIST_PARSE_START: 'playlistParseStart',
|
||||||
QUEUE_CREATE: "queueCreate",
|
QUEUE_CREATE: 'queueCreate',
|
||||||
QUEUE_END: "queueEnd",
|
QUEUE_END: 'queueEnd',
|
||||||
SEARCH_CANCEL: "searchCancel",
|
SEARCH_CANCEL: 'searchCancel',
|
||||||
SEARCH_INVALID_RESPONSE: "searchInvalidResponse",
|
SEARCH_INVALID_RESPONSE: 'searchInvalidResponse',
|
||||||
SEARCH_RESULTS: "searchResults",
|
SEARCH_RESULTS: 'searchResults',
|
||||||
TRACK_ADD: "trackAdd",
|
TRACK_ADD: 'trackAdd',
|
||||||
TRACK_START: "trackStart",
|
TRACK_START: 'trackStart'
|
||||||
};
|
};
|
|
@ -1,16 +1,16 @@
|
||||||
import { PlayerOptions, QueryType } from "../types/types";
|
import { PlayerOptions, QueryType } from '../types/types';
|
||||||
import { FFmpeg } from "prism-media";
|
import { FFmpeg } from 'prism-media';
|
||||||
import YouTube from "youtube-sr";
|
import YouTube from 'youtube-sr';
|
||||||
import Track from "../Structures/Track";
|
import Track from '../Structures/Track';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { validateURL as SoundcloudValidateURL } from "soundcloud-scraper";
|
import { validateURL as SoundcloudValidateURL } from 'soundcloud-scraper';
|
||||||
|
|
||||||
const spotifySongRegex = (/https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(?:track\/|\?uri=spotify:track:)((\w|-){22})/);
|
const spotifySongRegex = /https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(?:track\/|\?uri=spotify:track:)((\w|-){22})/;
|
||||||
const spotifyPlaylistRegex = (/https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(?:playlist\/|\?uri=spotify:playlist:)((\w|-){22})/);
|
const spotifyPlaylistRegex = /https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(?:playlist\/|\?uri=spotify:playlist:)((\w|-){22})/;
|
||||||
const spotifyAlbumRegex = (/https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(?:album\/|\?uri=spotify:album:)((\w|-){22})/);
|
const spotifyAlbumRegex = /https?:\/\/(?:embed\.|open\.)(?:spotify\.com\/)(?:album\/|\?uri=spotify:album:)((\w|-){22})/;
|
||||||
const vimeoRegex = (/(http|https)?:\/\/(www\.|player\.)?vimeo\.com\/(?:channels\/(?:\w+\/)?|groups\/([^/]*)\/videos\/|video\/|)(\d+)(?:|\/\?)/);
|
const vimeoRegex = /(http|https)?:\/\/(www\.|player\.)?vimeo\.com\/(?:channels\/(?:\w+\/)?|groups\/([^/]*)\/videos\/|video\/|)(\d+)(?:|\/\?)/;
|
||||||
const facebookRegex = (/(https?:\/\/)(www\.|m\.)?(facebook|fb).com\/.*\/videos\/.*/);
|
const facebookRegex = /(https?:\/\/)(www\.|m\.)?(facebook|fb).com\/.*\/videos\/.*/;
|
||||||
const reverbnationRegex = (/https:\/\/(www.)?reverbnation.com\/(.+)\/song\/(.+)/);
|
const reverbnationRegex = /https:\/\/(www.)?reverbnation.com\/(.+)\/song\/(.+)/;
|
||||||
|
|
||||||
export default class Util {
|
export default class Util {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -44,34 +44,40 @@ export default class Util {
|
||||||
|
|
||||||
if (!hasFFmpeg)
|
if (!hasFFmpeg)
|
||||||
console.warn(
|
console.warn(
|
||||||
"[Discord Player] FFmpeg/Avconv not found! Install via \"npm install ffmpeg-static\" or download from https://ffmpeg.org/download.html"
|
'[Discord Player] FFmpeg/Avconv not found! Install via "npm install ffmpeg-static" or download from https://ffmpeg.org/download.html'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getQueryType(query: string): QueryType {
|
static getQueryType(query: string): QueryType {
|
||||||
if (SoundcloudValidateURL(query) && !query.includes("/sets/")) return "soundcloud_track";
|
if (SoundcloudValidateURL(query) && !query.includes('/sets/')) return 'soundcloud_track';
|
||||||
if (SoundcloudValidateURL(query) && query.includes("/sets/")) return "soundcloud_playlist";
|
if (SoundcloudValidateURL(query) && query.includes('/sets/')) return 'soundcloud_playlist';
|
||||||
if (spotifySongRegex.test(query)) return "spotify_song";
|
if (spotifySongRegex.test(query)) return 'spotify_song';
|
||||||
if (spotifyAlbumRegex.test(query)) return "spotify_album";
|
if (spotifyAlbumRegex.test(query)) return 'spotify_album';
|
||||||
if (spotifyPlaylistRegex.test(query)) return "spotify_playlist";
|
if (spotifyPlaylistRegex.test(query)) return 'spotify_playlist';
|
||||||
if (YouTube.validate(query, "VIDEO")) return "youtube_video";
|
if (YouTube.validate(query, 'VIDEO')) return 'youtube_video';
|
||||||
if (YouTube.validate(query, "PLAYLIST")) return "youtube_playlist";
|
if (YouTube.validate(query, 'PLAYLIST')) return 'youtube_playlist';
|
||||||
if (vimeoRegex.test(query)) return "vimeo";
|
if (vimeoRegex.test(query)) return 'vimeo';
|
||||||
if (facebookRegex.test(query)) return "facebook";
|
if (facebookRegex.test(query)) return 'facebook';
|
||||||
if (reverbnationRegex.test(query)) return "reverbnation";
|
if (reverbnationRegex.test(query)) return 'reverbnation';
|
||||||
if (Util.isURL(query)) return "attachment";
|
if (Util.isURL(query)) return 'attachment';
|
||||||
|
|
||||||
return "youtube_search";
|
return 'youtube_search';
|
||||||
}
|
}
|
||||||
|
|
||||||
static isURL(str: string) {
|
static isURL(str: string) {
|
||||||
const urlRegex = '^(?!mailto:)(?:(?:http|https|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$';
|
const urlRegex =
|
||||||
|
'^(?!mailto:)(?:(?:http|https|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$';
|
||||||
const url = new RegExp(urlRegex, 'i');
|
const url = new RegExp(urlRegex, 'i');
|
||||||
return str.length < 2083 && url.test(str);
|
return str.length < 2083 && url.test(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getVimeoID(query: string) {
|
static getVimeoID(query: string) {
|
||||||
return Util.getQueryType(query) === "vimeo" ? query.split("/").filter(x => !!x).pop() : null
|
return Util.getQueryType(query) === 'vimeo'
|
||||||
|
? query
|
||||||
|
.split('/')
|
||||||
|
.filter((x) => !!x)
|
||||||
|
.pop()
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static parseMS(milliseconds: number) {
|
static parseMS(milliseconds: number) {
|
||||||
|
@ -87,28 +93,35 @@ export default class Util {
|
||||||
}
|
}
|
||||||
|
|
||||||
static durationString(durObj: object) {
|
static durationString(durObj: object) {
|
||||||
return Object.values(durObj).map(m => isNaN(m) ? 0 : m ).join(":");
|
return Object.values(durObj)
|
||||||
|
.map((m) => (isNaN(m) ? 0 : m))
|
||||||
|
.join(':');
|
||||||
}
|
}
|
||||||
|
|
||||||
static ytSearch(query: string, options?: any): Promise<Track[]> {
|
static ytSearch(query: string, options?: any): Promise<Track[]> {
|
||||||
return new Promise(async (resolve) => {
|
return new Promise(async (resolve) => {
|
||||||
await YouTube.search(query, {
|
await YouTube.search(query, {
|
||||||
type: "video",
|
type: 'video',
|
||||||
safeSearch: Boolean(options?.player.options.useSafeSearch)
|
safeSearch: Boolean(options?.player.options.useSafeSearch)
|
||||||
})
|
})
|
||||||
.then(results => {
|
.then((results) => {
|
||||||
resolve(results.map((r) => new Track(options?.player, {
|
resolve(
|
||||||
title: r.title,
|
results.map(
|
||||||
description: r.description,
|
(r) =>
|
||||||
author: r.channel.name,
|
new Track(options?.player, {
|
||||||
url: r.url,
|
title: r.title,
|
||||||
thumbnail: r.thumbnail.displayThumbnailURL(),
|
description: r.description,
|
||||||
duration: r.durationFormatted,
|
author: r.channel.name,
|
||||||
views: r.views,
|
url: r.url,
|
||||||
requestedBy: options?.user,
|
thumbnail: r.thumbnail.displayThumbnailURL(),
|
||||||
fromPlaylist: false,
|
duration: r.durationFormatted,
|
||||||
source: "youtube"
|
views: r.views,
|
||||||
})));
|
requestedBy: options?.user,
|
||||||
|
fromPlaylist: false,
|
||||||
|
source: 'youtube'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.catch(() => resolve([]));
|
.catch(() => resolve([]));
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
"object-literal-sort-keys": false,
|
"object-literal-sort-keys": false,
|
||||||
"interface-name": false,
|
"interface-name": false,
|
||||||
"no-empty": false,
|
"no-empty": false,
|
||||||
"no-console": false
|
"no-console": false,
|
||||||
|
"radix": false
|
||||||
},
|
},
|
||||||
"rulesDirectory": []
|
"rulesDirectory": []
|
||||||
}
|
}
|
Loading…
Reference in a new issue