feat: base

This commit is contained in:
Snowflake107 2021-06-10 01:12:29 +05:45
parent 311df79adc
commit fac2662025
9 changed files with 116 additions and 18 deletions

View file

@ -66,6 +66,7 @@
"@discordjs/opus": "^0.5.0",
"@types/node": "^14.14.41",
"@types/ws": "^7.4.1",
"discord-api-types": "^0.18.1",
"discord.js": "^13.0.0-dev.dda5ee2e9f0839d3e42d25114ae1b47355cdfd27",
"discord.js-docgen": "discordjs/docgen#ts-patch",
"jsdoc-babel": "^0.5.0",

View file

@ -30,10 +30,15 @@ export class Player extends EventEmitter {
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)
);
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);
@ -57,7 +62,7 @@ export class Player extends EventEmitter {
});
return queue;
})
});
}
public getQueue(message: Message) {
@ -81,7 +86,7 @@ export class Player extends EventEmitter {
if (query instanceof Track) track = query;
else {
if (ytdl.validateURL(query)) {
const info = await ytdl.getBasicInfo(query).catch(() => { });
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(

View file

@ -1,12 +1,11 @@
import Player from "../Player";
import Player from '../Player';
export class Playlist {
player: Player;
constructor(player: Player, data: any) {
Object.defineProperty(this, "player", { value: player });
Object.defineProperty(this, 'player', { value: player });
}
}
export default Playlist;

View file

@ -0,0 +1,89 @@
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);
}
};
};
}

View file

@ -0,0 +1 @@
class VoiceSubscriptionManager {}

View file

@ -17,7 +17,7 @@ export enum PlayerEvents {
SEARCH_RESULTS = 'searchResults',
TRACK_ADD = 'trackAdd',
TRACK_START = 'trackStart'
};
}
export enum PlayerErrorEventCodes {
DEFAULT = 'PlayerError',
@ -28,7 +28,7 @@ export enum PlayerErrorEventCodes {
PARSE_ERROR = 'ParseError',
VIDEO_UNAVAILABLE = 'VideoUnavailable',
MUSIC_STARTING = 'MusicStarting'
};
}
export const PlayerOptions: DP_OPTIONS = {
leaveOnEnd: true,

View file

@ -1,4 +1,4 @@
import { Message } from "discord.js";
import { Message } from 'discord.js';
export default class PlayerError extends Error {
discordMessage: Message;

View file

@ -7,12 +7,15 @@ import { validateURL as SoundcloudValidateURL } from 'soundcloud-scraper';
import { VoiceChannel } from 'discord.js';
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 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 reverbnationRegex = /https:\/\/(www.)?reverbnation.com\/(.+)\/song\/(.+)/;
const attachmentRegex = /^(?:(?:https?|ftp):\/\/)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-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,})))(?::\d{2,5})?(?:\/\S*)?$/;
const attachmentRegex =
/^(?:(?:https?|ftp):\/\/)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-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,})))(?::\d{2,5})?(?:\/\S*)?$/;
export class Util {
/**