feat(VoiceInterface): metadata
This commit is contained in:
parent
5d5fd03997
commit
19039f8d9b
5 changed files with 36 additions and 12 deletions
|
@ -1,11 +1,13 @@
|
|||
import { Client, Collection, Guild, Snowflake } from "discord.js";
|
||||
import { TypedEmitter as EventEmitter } from "tiny-typed-emitter";
|
||||
import { Queue } from "./Structures/Queue";
|
||||
import { VoiceUtils } from "./VoiceInterface/VoiceUtils";
|
||||
import { PlayerOptions } from "./types/types";
|
||||
|
||||
class DiscordPlayer extends EventEmitter {
|
||||
public readonly client: Client;
|
||||
public readonly queues = new Collection<Snowflake, Queue>();
|
||||
public readonly voiceUtils = new VoiceUtils();
|
||||
|
||||
constructor(client: Client) {
|
||||
super();
|
||||
|
|
|
@ -9,7 +9,6 @@ class Playlist {
|
|||
this.player = player;
|
||||
this.tracks = tracks ?? [];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { Playlist };
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { Guild, StageChannel, VoiceChannel } from "discord.js";
|
||||
import { Player } from "../Player";
|
||||
import { VoiceUtils } from "../VoiceInterface/VoiceUtils";
|
||||
import { VoiceSubscription } from "../VoiceInterface/VoiceSubscription";
|
||||
import Track from "./Track";
|
||||
import { PlayerOptions } from "../types/types";
|
||||
|
@ -36,10 +35,14 @@ class Queue {
|
|||
);
|
||||
}
|
||||
|
||||
get current() {
|
||||
return this.voiceConnection.audioResource?.metadata ?? this.tracks[0];
|
||||
}
|
||||
|
||||
async joinVoiceChannel(channel: StageChannel | VoiceChannel) {
|
||||
if (!["stage", "voice"].includes(channel.type))
|
||||
throw new TypeError(`Channel type must be voice or stage, got ${channel.type}!`);
|
||||
const connection = await VoiceUtils.connect(channel);
|
||||
const connection = await this.player.voiceUtils.connect(channel);
|
||||
this.voiceConnection = connection;
|
||||
|
||||
return this;
|
||||
|
@ -50,6 +53,10 @@ class Queue {
|
|||
this.voiceConnection.disconnect();
|
||||
this.player.queues.delete(this.guild.id);
|
||||
}
|
||||
|
||||
play() {
|
||||
throw new Error("Not implemented");
|
||||
}
|
||||
}
|
||||
|
||||
export { Queue };
|
||||
|
|
|
@ -12,6 +12,8 @@ import {
|
|||
} from "@discordjs/voice";
|
||||
import { Duplex, Readable } from "stream";
|
||||
import { TypedEmitter as EventEmitter } from "tiny-typed-emitter";
|
||||
import Track from "../Structures/Track";
|
||||
import PlayerError from "../utils/PlayerError";
|
||||
|
||||
export interface VoiceEvents {
|
||||
error: (error: AudioPlayerError) => any;
|
||||
|
@ -24,6 +26,7 @@ class VoiceSubscription extends EventEmitter<VoiceEvents> {
|
|||
public readonly voiceConnection: VoiceConnection;
|
||||
public readonly audioPlayer: AudioPlayer;
|
||||
public connectPromise?: Promise<void>;
|
||||
public audioResource?: AudioResource<Track>;
|
||||
|
||||
constructor(connection: VoiceConnection) {
|
||||
super();
|
||||
|
@ -79,11 +82,13 @@ class VoiceSubscription extends EventEmitter<VoiceEvents> {
|
|||
* @returns {AudioResource}
|
||||
*/
|
||||
createStream(src: Readable | Duplex | string, ops?: { type?: StreamType; data?: any; inlineVolume?: boolean }) {
|
||||
return createAudioResource(src, {
|
||||
this.audioResource = createAudioResource(src, {
|
||||
inputType: ops?.type ?? StreamType.Arbitrary,
|
||||
metadata: ops?.data,
|
||||
inlineVolume: Boolean(ops?.inlineVolume)
|
||||
});
|
||||
|
||||
return this.audioResource;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -119,11 +124,18 @@ class VoiceSubscription extends EventEmitter<VoiceEvents> {
|
|||
* Play stream
|
||||
* @param {AudioResource} resource The audio resource to play
|
||||
*/
|
||||
playStream(resource: AudioResource) {
|
||||
playStream(resource: AudioResource<Track> = this.audioResource) {
|
||||
if (!resource) throw new PlayerError("Audio resource is not available!");
|
||||
if (!this.audioResource && resource) this.audioResource = resource;
|
||||
this.audioPlayer.play(resource);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
get streamTime() {
|
||||
if (!this.audioResource) return 0;
|
||||
return this.audioResource.playbackDuration;
|
||||
}
|
||||
}
|
||||
|
||||
export { VoiceSubscription };
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import { VoiceChannel, StageChannel } from "discord.js";
|
||||
import { VoiceChannel, StageChannel, Collection, Snowflake } from "discord.js";
|
||||
import { entersState, joinVoiceChannel, VoiceConnection, VoiceConnectionStatus } from "@discordjs/voice";
|
||||
import { VoiceSubscription } from "./VoiceSubscription";
|
||||
|
||||
class VoiceUtils {
|
||||
constructor() {
|
||||
throw new Error("Cannot instantiate static class!");
|
||||
}
|
||||
public cache = new Collection<Snowflake, VoiceSubscription>();
|
||||
|
||||
/**
|
||||
* Joins a voice channel
|
||||
|
@ -13,7 +11,7 @@ class VoiceUtils {
|
|||
* @param {({deaf?: boolean;maxTime?: number;})} [options] Join options
|
||||
* @returns {Promise<VoiceSubscription>}
|
||||
*/
|
||||
public static async connect(
|
||||
public async connect(
|
||||
channel: VoiceChannel | StageChannel,
|
||||
options?: {
|
||||
deaf?: boolean;
|
||||
|
@ -29,7 +27,9 @@ class VoiceUtils {
|
|||
|
||||
try {
|
||||
conn = await entersState(conn, VoiceConnectionStatus.Ready, options?.maxTime ?? 20000);
|
||||
return new VoiceSubscription(conn);
|
||||
const sub = new VoiceSubscription(conn);
|
||||
this.cache.set(channel.guild.id, sub);
|
||||
return sub;
|
||||
} catch (err) {
|
||||
conn.destroy();
|
||||
throw err;
|
||||
|
@ -40,10 +40,14 @@ class VoiceUtils {
|
|||
* Disconnects voice connection
|
||||
* @param {VoiceConnection} connection The voice connection
|
||||
*/
|
||||
public static disconnect(connection: VoiceConnection | VoiceSubscription) {
|
||||
public disconnect(connection: VoiceConnection | VoiceSubscription) {
|
||||
if (connection instanceof VoiceSubscription) return connection.voiceConnection.destroy();
|
||||
return connection.destroy();
|
||||
}
|
||||
|
||||
public getConnection(guild: Snowflake) {
|
||||
return this.cache.get(guild);
|
||||
}
|
||||
}
|
||||
|
||||
export { VoiceUtils };
|
||||
|
|
Loading…
Reference in a new issue