add error callback to allow errors to be shown within discord
This commit is contained in:
parent
891b081791
commit
83ede78a1d
|
@ -54,7 +54,7 @@ function nowPlayingResponse(bot: Bot, interaction: Interaction) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function nowPlayingMessage(bot: Bot, guildId: number) {
|
function nowPlayingMessage(bot: Bot, guildId: BigInt) {
|
||||||
const player = bot.helpers.getPlayer(guildId);
|
const player = bot.helpers.getPlayer(guildId);
|
||||||
return <CreateMessage>{
|
return <CreateMessage>{
|
||||||
embeds: [<Embed>{
|
embeds: [<Embed>{
|
||||||
|
|
|
@ -60,13 +60,14 @@ export async function play(bot: Bot, interaction: Interaction, _args?) {
|
||||||
}
|
}
|
||||||
|
|
||||||
let href;
|
let href;
|
||||||
|
// remove the timestamp from the query
|
||||||
if(parsed_url.href.indexOf("?t=") !== -1) {
|
if(parsed_url.href.indexOf("?t=") !== -1) {
|
||||||
href = parsed_url.href.substring(0, parsed_url.href.indexOf("?"))
|
href = parsed_url.href.substring(0, parsed_url.href.indexOf("?"))
|
||||||
} else {
|
} else {
|
||||||
href = parsed_url.href;
|
href = parsed_url.href;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await player.pushQuery(interaction.user.username, href);
|
const result = await player.pushQuery(interaction.guildId, interaction.user.username, href);
|
||||||
if(result && result[0] && parsed_url.href.indexOf("youtube.com") !== -1 || parsed_url.href.indexOf("youtu.be") !== -1 && result[0].title) {
|
if(result && result[0] && parsed_url.href.indexOf("youtube.com") !== -1 || parsed_url.href.indexOf("youtu.be") !== -1 && result[0].title) {
|
||||||
await editOriginalInteractionResponse(bot, interaction.token, addedToQueueResponse(interaction, result[0].title));
|
await editOriginalInteractionResponse(bot, interaction.token, addedToQueueResponse(interaction, result[0].title));
|
||||||
}
|
}
|
||||||
|
@ -84,72 +85,3 @@ export async function play(bot: Bot, interaction: Interaction, _args?) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*import { exists } from "https://deno.land/std@0.161.0/fs/mod.ts";
|
|
||||||
|
|
||||||
import { configs } from "../configs.ts";
|
|
||||||
import { Bot } from "../deps.ts";
|
|
||||||
import { download, ensureVoiceConnection } from "../utils.ts";
|
|
||||||
import { type Command } from "../types.ts";
|
|
||||||
|
|
||||||
export async function play(bot: Bot, command: Command) {
|
|
||||||
await ensureVoiceConnection(bot, command.guildId);
|
|
||||||
const player = bot.helpers.getPlayer(command.guildId);
|
|
||||||
await player.pushQuery(command.params);
|
|
||||||
await player.play();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*const parsed_url = new URL(url);
|
|
||||||
let video_id = "";
|
|
||||||
|
|
||||||
if(parsed_url.href.indexOf("youtube.com") !== -1) {
|
|
||||||
video_id = parsed_url.search.substring(3);
|
|
||||||
} else if(parsed_url.href.indexOf("youtu.be") === -1) {
|
|
||||||
video_id = parsed_url.pathname.substring(1);
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
status: false,
|
|
||||||
message: "This URL is invalid"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(await exists(`${configs.project_root}/music/`))) {
|
|
||||||
await download(video_id);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
// single video
|
|
||||||
/*
|
|
||||||
URL {
|
|
||||||
href: "https://www.youtube.com/watch?v=DhobsmmyGFs",
|
|
||||||
origin: "https://www.youtube.com",
|
|
||||||
protocol: "https:",
|
|
||||||
username: "",
|
|
||||||
password: "",
|
|
||||||
host: "www.youtube.com",
|
|
||||||
hostname: "www.youtube.com",
|
|
||||||
port: "",
|
|
||||||
pathname: "/watch",
|
|
||||||
hash: "",
|
|
||||||
search: "?v=DhobsmmyGFs"
|
|
||||||
}
|
|
||||||
{
|
|
||||||
endpoint: "stockholm3048.discord.media:443",
|
|
||||||
sessionId: "74d4d31a8f5c507f9852278867d42c05",
|
|
||||||
token: "08b9f3bc65a233d5"
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// playlist
|
|
||||||
/*URL {
|
|
||||||
href: "https://www.youtube.com/playlist?list=PLvNazUnle2rTZO7OVYhhRdzFb9W4xSpNk",
|
|
||||||
origin: "https://www.youtube.com",
|
|
||||||
protocol: "https:",
|
|
||||||
username: "",
|
|
||||||
password: "",
|
|
||||||
host: "www.youtube.com",
|
|
||||||
hostname: "www.youtube.com",
|
|
||||||
port: "",
|
|
||||||
pathname: "/playlist",
|
|
||||||
hash: "",
|
|
||||||
search: "?list=PLvNazUnle2rTZO7OVYhhRdzFb9W4xSpNk"
|
|
||||||
}*/
|
|
|
@ -6,6 +6,7 @@ export type AudioSource = {
|
||||||
data: () =>
|
data: () =>
|
||||||
| Promise<AsyncIterableIterator<Uint8Array>>
|
| Promise<AsyncIterableIterator<Uint8Array>>
|
||||||
| AsyncIterableIterator<Uint8Array>;
|
| AsyncIterableIterator<Uint8Array>;
|
||||||
|
guildId: bigint;
|
||||||
added_by?: string;
|
added_by?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16,6 +17,7 @@ export function createAudioSource(
|
||||||
data: () =>
|
data: () =>
|
||||||
| Promise<AsyncIterableIterator<Uint8Array>>
|
| Promise<AsyncIterableIterator<Uint8Array>>
|
||||||
| AsyncIterableIterator<Uint8Array>,
|
| AsyncIterableIterator<Uint8Array>,
|
||||||
|
guildId: bigint,
|
||||||
added_by?: string
|
added_by?: string
|
||||||
): AudioSource {
|
): AudioSource {
|
||||||
lastId++;
|
lastId++;
|
||||||
|
@ -31,6 +33,7 @@ export function createAudioSource(
|
||||||
return empty();
|
return empty();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
guildId,
|
||||||
added_by
|
added_by
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,6 @@ import { getYoutubeSources } from "./youtube.ts";
|
||||||
|
|
||||||
export type LoadSource = typeof loadLocalOrYoutube;
|
export type LoadSource = typeof loadLocalOrYoutube;
|
||||||
|
|
||||||
export function loadLocalOrYoutube(query: string, added_by?: string) {
|
export function loadLocalOrYoutube(query: string, guildId: bigint, added_by?: string) {
|
||||||
return getYoutubeSources(query, String(added_by));
|
return getYoutubeSources(guildId, String(added_by), query);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,31 +3,35 @@ import { bufferIter } from "../../utils/mod.ts";
|
||||||
import { demux } from "../demux/mod.ts";
|
import { demux } from "../demux/mod.ts";
|
||||||
import { createAudioSource, empty } from "./audio-source.ts";
|
import { createAudioSource, empty } from "./audio-source.ts";
|
||||||
|
|
||||||
export async function getYoutubeSources(added_by?: string, ...queries: string[]) {
|
import { errorMessageCallback, parseYoutubeId } from "../../../utils.ts";
|
||||||
const sources = queries.map((query) => getYoutubeSource(query, added_by));
|
|
||||||
|
export async function getYoutubeSources(guildId: bigint, added_by?: string, ...queries: string[]) {
|
||||||
|
const sources = queries.map((query) => getYoutubeSource(query, guildId, added_by));
|
||||||
const awaitedSources = await Promise.all(sources);
|
const awaitedSources = await Promise.all(sources);
|
||||||
return awaitedSources
|
return awaitedSources
|
||||||
.filter((source) => source !== undefined)
|
.filter((source) => source !== undefined)
|
||||||
.map((source) => source!);
|
.map((source) => source!);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getYoutubeSource(query: string, added_by?: string) {
|
export async function getYoutubeSource(query: string, guildId: bigint, added_by?: string) {
|
||||||
try {
|
try {
|
||||||
|
query = parseYoutubeId(query);
|
||||||
const results = await YouTube.search(query, { limit: 1, type: "video" });
|
const results = await YouTube.search(query, { limit: 1, type: "video" });
|
||||||
if (results.length > 0) {
|
if (results.length > 0) {
|
||||||
const { id, title } = results[0];
|
const { id, title } = results[0];
|
||||||
return createAudioSource(title!, async () => {
|
return createAudioSource(title!, async () => {
|
||||||
try {
|
try {
|
||||||
const stream = await ytDownload(id!, {
|
const stream = await ytDownload(query, {
|
||||||
mimeType: `audio/webm; codecs="opus"`,
|
mimeType: `audio/webm; codecs="opus"`,
|
||||||
});
|
});
|
||||||
return bufferIter(demux(stream));
|
return bufferIter(demux(stream));
|
||||||
} catch {
|
} catch {
|
||||||
console.error("error");
|
errorMessageCallback(guildId, `There was an error trying to play **${title}**:\n
|
||||||
|
something broke in getYoutubeSource`);
|
||||||
console.log(`Failed to play ${title}\n Returning empty stream`);
|
console.log(`Failed to play ${title}\n Returning empty stream`);
|
||||||
return empty();
|
return empty();
|
||||||
}
|
}
|
||||||
}, added_by);
|
}, guildId, added_by);
|
||||||
}
|
}
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
|
@ -9,7 +9,7 @@ export type BotData = {
|
||||||
guildData: Map<bigint, ConnectionData>;
|
guildData: Map<bigint, ConnectionData>;
|
||||||
udpSource: EventSource<[UdpArgs]>;
|
udpSource: EventSource<[UdpArgs]>;
|
||||||
bufferSize: number;
|
bufferSize: number;
|
||||||
loadSource: (query: string, added_by?: string) => AudioSource[] | Promise<AudioSource[]>;
|
loadSource: (query: string, guild_id: bigint, added_by?: string) => AudioSource[] | Promise<AudioSource[]>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ConnectionData = {
|
export type ConnectionData = {
|
||||||
|
|
|
@ -79,24 +79,24 @@ export class QueuePlayer extends Queue<AudioSource> implements Player {
|
||||||
* Interrupts the current song, resumes when finished
|
* Interrupts the current song, resumes when finished
|
||||||
* @param query Loads a universal song (local file or youtube search)
|
* @param query Loads a universal song (local file or youtube search)
|
||||||
*/
|
*/
|
||||||
async interruptQuery(query: string) {
|
async interruptQuery(guildId: bigint, query: string) {
|
||||||
const sources = await this.#loadSource(query as string);
|
const sources = await this.#loadSource(query as string, guildId);
|
||||||
this.#rawPlayer.interrupt(await sources[0].data());
|
this.#rawPlayer.interrupt(await sources[0].data());
|
||||||
}
|
}
|
||||||
|
|
||||||
async pushQuery(added_by?: string, ...queries: string[]) {
|
async pushQuery(guildId: bigint, added_by?: string, ...queries: string[]) {
|
||||||
const sources = [];
|
const sources = [];
|
||||||
for (const query of queries) {
|
for (const query of queries) {
|
||||||
sources.push(...(await this.#loadSource(String(added_by), query as string)));
|
sources.push(...(await this.#loadSource(query as string, guildId, String(added_by))));
|
||||||
this.push(...sources);
|
this.push(...sources);
|
||||||
}
|
}
|
||||||
return sources;
|
return sources;
|
||||||
}
|
}
|
||||||
|
|
||||||
async unshiftQuery(...queries: string[]) {
|
async unshiftQuery(guildId: bigint, ...queries: string[]) {
|
||||||
const sources = [];
|
const sources = [];
|
||||||
for (const query of queries) {
|
for (const query of queries) {
|
||||||
sources.push(...(await this.#loadSource(query as string)));
|
sources.push(...(await this.#loadSource(query as string, guildId)));
|
||||||
this.unshift(...sources);
|
this.unshift(...sources);
|
||||||
}
|
}
|
||||||
return sources;
|
return sources;
|
||||||
|
|
2
main.ts
2
main.ts
|
@ -30,7 +30,7 @@ export const bot = enableAudioPlugin(baseBot);
|
||||||
|
|
||||||
bot.events.ready = async function (bot, payload) {
|
bot.events.ready = async function (bot, payload) {
|
||||||
//await registerCommands(bot);
|
//await registerCommands(bot);
|
||||||
console.log(`${cyan("permanent waves")} is ready to go with session id ${yellow(payload.sessionId)}`);
|
console.log(`${cyan("permanent waves")} is ready to go`);
|
||||||
sessionId = payload.sessionId;
|
sessionId = payload.sessionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
65
utils.ts
65
utils.ts
|
@ -1,9 +1,19 @@
|
||||||
import { ytdl } from "https://deno.land/x/ytdl_core@v0.1.1/mod.ts";
|
|
||||||
import { Bot } from "https://deno.land/x/discordeno@18.0.1/bot.ts";
|
import { Bot } from "https://deno.land/x/discordeno@18.0.1/bot.ts";
|
||||||
import { connectToVoiceChannel } from "https://deno.land/x/discordeno@18.0.1/helpers/guilds/mod.ts";
|
|
||||||
import { configs } from "./configs.ts";
|
import { configs } from "./configs.ts";
|
||||||
import { getChannel, getChannels, getGuild, type BigString, type Embed, type InteractionCallbackData, type InteractionResponse } from "./deps.ts";
|
import {
|
||||||
|
getChannel,
|
||||||
|
getChannels,
|
||||||
|
getGuild,
|
||||||
|
sendMessage,
|
||||||
|
type BigString,
|
||||||
|
type CreateMessage,
|
||||||
|
type Embed,
|
||||||
|
type InteractionCallbackData,
|
||||||
|
type InteractionResponse
|
||||||
|
} from "./deps.ts";
|
||||||
|
import { bot } from "./main.ts";
|
||||||
|
|
||||||
|
import { ConnectionData } from "./discordeno-audio-plugin/mod.ts";
|
||||||
|
|
||||||
export function channelIsAllowed(guild: string, channel: string) {
|
export function channelIsAllowed(guild: string, channel: string) {
|
||||||
if(`${guild}:${channel}` in configs.allowed_text_channels) {
|
if(`${guild}:${channel}` in configs.allowed_text_channels) {
|
||||||
|
@ -13,30 +23,6 @@ export function channelIsAllowed(guild: string, channel: string) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function download(url: string) {
|
|
||||||
try {
|
|
||||||
const stream = await ytdl(url, { filter: "audio" });
|
|
||||||
|
|
||||||
const chunks: Uint8Array[] = [];
|
|
||||||
|
|
||||||
for await (const chunk of stream) {
|
|
||||||
chunks.push(chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
const videoDetails = stream.videoInfo.videoDetails;
|
|
||||||
const blob = new Blob(chunks);
|
|
||||||
const result = await Deno.writeFile(`${configs.project_root}/music/${videoDetails.videoId}.mp3`, new Uint8Array(await blob.arrayBuffer()));
|
|
||||||
return {
|
|
||||||
result: true,
|
|
||||||
message: `Now playing **${videoDetails.title}**`
|
|
||||||
};
|
|
||||||
} catch(err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function ensureVoiceConnection(bot: Bot, guildId: BigString) {
|
export async function ensureVoiceConnection(bot: Bot, guildId: BigString) {
|
||||||
const channels = await getChannels(bot, guildId);
|
const channels = await getChannels(bot, guildId);
|
||||||
const guild = await getGuild(bot, <BigString>guildId);
|
const guild = await getGuild(bot, <BigString>guildId);
|
||||||
|
@ -47,9 +33,9 @@ export async function ensureVoiceConnection(bot: Bot, guildId: BigString) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const channel = await getChannel(bot, channelId);
|
await getChannel(bot, channelId);
|
||||||
try {
|
try {
|
||||||
const connection = await bot.helpers.connectToVoiceChannel(guildId, channelId);
|
await bot.helpers.connectToVoiceChannel(guildId, channelId);
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
|
@ -93,4 +79,23 @@ export const waitingForResponse = <InteractionResponse>{
|
||||||
data: {
|
data: {
|
||||||
content: "waiting for response..."
|
content: "waiting for response..."
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function errorMessage(bot: Bot, guildId: bigint, message: string) {
|
||||||
|
const player = bot.helpers.getPlayer(guildId);
|
||||||
|
return <CreateMessage>{
|
||||||
|
embeds: [<Embed>{
|
||||||
|
color: configs.embed_color,
|
||||||
|
description: message
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function errorMessageCallback(guildId: bigint, message: string) {
|
||||||
|
const channel = await getAllowedTextChannel(bot, guildId);
|
||||||
|
await sendMessage(bot, channel.id, errorMessage(bot, guildId, message));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseYoutubeId(url: string) {
|
||||||
|
return url.substring(url.indexOf("?")+3);
|
||||||
|
}
|
Loading…
Reference in New Issue