Фиксы

Используем кастомный экстрактор для фикса ошибок discord-player
This commit is contained in:
JonnyBro 2022-08-04 22:06:26 +05:00
parent fd549cd4ff
commit cf171f5ccb
7 changed files with 290 additions and 38 deletions

View file

@ -2,15 +2,17 @@ const { Client, Collection, SlashCommandBuilder, ContextMenuCommandBuilder } = r
{ GiveawaysManager } = require("discord-giveaways"), { GiveawaysManager } = require("discord-giveaways"),
{ Player } = require("discord-player"), { Player } = require("discord-player"),
{ REST } = require("@discordjs/rest"), { REST } = require("@discordjs/rest"),
{ Routes } = require("discord-api-types/v10"); { Routes } = require("discord-api-types/v10"),
{ DiscordTogether } = require("../helpers/discordTogether");
const BaseEvent = require("./BaseEvent.js"), const BaseEvent = require("./BaseEvent.js"),
BaseCommand = require("./BaseCommand.js"), BaseCommand = require("./BaseCommand.js"),
{ DiscordTogether } = require("../helpers/discordTogether"),
AmeClient = require("amethyste-api"), AmeClient = require("amethyste-api"),
path = require("path"), path = require("path"),
fs = require("fs").promises, fs = require("fs").promises,
mongoose = require("mongoose"), mongoose = require("mongoose"),
extractor = require("../helpers/extractor"),
playdl = require("play-dl"),
moment = require("moment"); moment = require("moment");
moment.relativeTimeThreshold("ss", 5); moment.relativeTimeThreshold("ss", 5);
@ -49,11 +51,22 @@ class JaBa extends Client {
this.discordTogether = new DiscordTogether(this); this.discordTogether = new DiscordTogether(this);
this.player = new Player(this, { playdl.getFreeClientID().then((clientID) => {
autoRegisterExtractor: true, playdl.setToken({
leaveOnEnd: true, soundcloud: {
leaveOnStop: true client_id: clientID
}
}); });
});
this.player = new Player(this);
// ytdlOptions: {
// filter: "audioonly",
// highWaterMark: 1 << 30,
// dlChunkSize: 0,
// liveBuffer: 4900
// }
this.player.use("jaba", extractor);
this.player this.player
.on("trackStart", async (queue, track) => { .on("trackStart", async (queue, track) => {

View file

@ -1,5 +1,4 @@
const { SlashCommandBuilder, PermissionsBitField } = require("discord.js"), const { SlashCommandBuilder, PermissionsBitField } = require("discord.js");
{ QueryType } = require("discord-player");
const BaseCommand = require("../../base/BaseCommand"); const BaseCommand = require("../../base/BaseCommand");
class Play extends BaseCommand { class Play extends BaseCommand {
@ -44,7 +43,7 @@ class Play extends BaseCommand {
const searchResult = await client.player.search(query, { const searchResult = await client.player.search(query, {
requestedBy: interaction.user, requestedBy: interaction.user,
searchEngine: query.includes("soundcloud") ? QueryType.SOUNDCLOUD_SEARCH : QueryType.AUTO searchEngine: "jaba"
}).catch(() => {}); }).catch(() => {});
if (!searchResult || !searchResult.tracks.length) return interaction.editReply({ if (!searchResult || !searchResult.tracks.length) return interaction.editReply({
content: interaction.translate("music/play:NO_RESULT", { content: interaction.translate("music/play:NO_RESULT", {
@ -56,19 +55,14 @@ class Play extends BaseCommand {
metadata: { metadata: {
channel: interaction.channel channel: interaction.channel
}, },
ytdlOptions: { leaveOnEnd: true,
filter: "audioonly", leaveOnStop: true,
highWaterMark: 1 << 30, bufferingTimeout: 1000,
dlChunkSize: 0, disableVolume: false,
liveBuffer: 4900 spotifyBridge: false
}
}); });
if (!queue.tracks[0]) {
searchResult.playlist ? queue.addTracks(searchResult.tracks) : queue.addTrack(searchResult.tracks[0]); searchResult.playlist ? queue.addTracks(searchResult.tracks) : queue.addTrack(searchResult.tracks[0]);
} else {
searchResult.playlist ? searchResult.tracks.forEach(track => queue.insert(track)) : queue.insert(searchResult.tracks[0]);
}
try { try {
if (!queue.connection) await queue.connect(interaction.member.voice.channel); if (!queue.connection) await queue.connect(interaction.member.voice.channel);

View file

@ -35,8 +35,8 @@ class Queue extends BaseCommand {
if (!queue) return interaction.error("music/play:NOT_PLAYING"); if (!queue) return interaction.error("music/play:NOT_PLAYING");
const currentTrack = queue.current; const currentTrack = queue.current;
const tracks = queue.tracks.slice(0, 10).map(track => { const tracks = queue.tracks.slice(0, 10).map((track, i) => {
return `${queue.tracks.indexOf(track)}. [${track.title}](${track.url})\n> ${interaction.translate("music/queue:ADDED")} ${track.requestedBy}`; return `${i + 1}. [${track.title}](${track.url})\n> ${interaction.translate("music/queue:ADDED")} ${track.requestedBy}`;
}); });
const embed = new EmbedBuilder() const embed = new EmbedBuilder()

View file

@ -42,13 +42,13 @@ class Skipto extends BaseCommand {
if (!queue) return interaction.error("music/play:NOT_PLAYING"); if (!queue) return interaction.error("music/play:NOT_PLAYING");
if (position < 0) return interaction.error("music/skipto:NO_PREV_SONG"); if (position < 0) return interaction.error("music/skipto:NO_PREV_SONG");
if (queue.tracks[position]) { if (queue.tracks[position - 1]) {
queue.skipTo(queue.tracks[position]); queue.skipTo(queue.tracks[position - 1]);
interaction.success("music/skipto:SUCCESS", { interaction.success("music/skipto:SUCCESS", {
position position: position - 1
}); });
} else return interaction.error("music/skipto:ERROR", { position }); } else return interaction.error("music/skipto:ERROR", { position: position - 1 });
} }
} }

212
helpers/extractor.js Normal file
View file

@ -0,0 +1,212 @@
const playdl = require("play-dl");
const fetch = require("node-fetch");
const { getData, getPreview, getTracks } = require("spotify-url-info")(fetch);
const Youtube = require("youtube-sr").default;
/*
Thanks to: https://github.com/nizewn/Dodong
hello stranger,
as a result of my headaches while dealing with the discord-player extractor API,
what you will see here will mostly be poorly-written code.
this could use modularisation or some cleanup (i might do it once i have free time)
thanks :)
-nize
*/
module.exports = {
important: true,
validate: () => true, // true, since we're also using this for searches when query isnt a valid link
getInfo: async (query) => {
// eslint-disable-next-line no-async-promise-executor, no-unused-vars
return new Promise(async (resolve, reject) => {
try {
// ---- start soundcloud ----
if (["track", "playlist"].includes(await playdl.so_validate(query))) {
const info = await playdl.soundcloud(query);
if (info.type === "track") {
const track = {
title: info.name,
duration: info.durationInMs,
thumbnail: info.thumbnail,
async engine() {
return (await playdl.stream(info.url, { discordPlayerCompatibility: true })).stream;
},
views: 0,
author: info.publisher ? info.publisher.name ?? info.publisher.artist ?? info.publisher.writer_composer ?? null : null,
description: "",
url: info.permalink,
source: "soundcloud-custom"
};
return resolve({ playlist: null, info: [track] });
} else if (info.type === "playlist") {
const trackList = await info.all_tracks();
const tracks = await trackList.map(track => {
return {
title: track.name,
duration: track.durationInMs,
thumbnail: track.thumbnail,
async engine() {
return (await playdl.stream(track.url, { discordPlayerCompatibility: true })).stream;
},
views: 0,
author: track.publisher ? track.publisher.name ?? track.publisher.artist ?? track.publisher.writer_composer ?? null : null,
description: "",
url: track.permalink,
source: "soundcloud-custom"
};
});
const playlist = {
title: info.name,
description: "",
thumbnail: null,
type: "playlist",
source: "soundcloud-custom",
author: info.user,
id: info.id,
url: info.url,
rawPlaylist: info
};
return resolve({ playlist: playlist, info: tracks });
}
}
// ---- end soundcloud ----
// ---- start spotify ----
if (query.includes("open.spotify.com") || query.includes("play.spotify.com")) {
const info = await getPreview(query);
if (info.type === "track") {
const spotifyTrack = await getData(query);
const track = {
title: info.title,
duration: spotifyTrack.duration_ms,
thumbnail: info.image,
async engine() {
return (await playdl.stream(await Youtube.search(`${info.artist} ${info.title} lyric`, {limit: 1, type: "video", safeSearch: true}).then(x => x[0] ? `https://youtu.be/${x[0].id}` : "https://youtu.be/Wch3gJG2GJ4"), { discordPlayerCompatibility : true })).stream;
},
views: 0,
author: info.artist,
description: "",
url: info.link,
source: "spotify-custom"
};
return resolve({ playlist: null, info: [track] });
} else if (["album", "artist", "playlist"].includes(info.type)) {
const trackList = await getTracks(query);
const tracks = trackList.map(track => {
return {
title: track.name,
duration: track.duration_ms,
thumbnail: track.album && track.album.images.length ? track.album.images[0].url : null,
async engine() {
return (await playdl.stream(await Youtube.search(`${track.artists[0].name} ${track.name} lyric`, {limit: 1, type: "video", safeSearch: true}).then(x => x[0] ? `https://youtu.be/${x[0].id}` : "https://youtu.be/Wch3gJG2GJ4"), { discordPlayerCompatibility : true })).stream;
},
views: 0,
author: track.artists ? track.artists[0].name : null,
description: "",
url: track.external_urls.spotify,
source: "spotify-custom"
};
});
const playlist = {
title: info.title,
description: "",
thumbnail: info.image,
type: info.type === "album" ? "album" : "playlist",
source: "spotify-custom",
author: info.artist,
id: null,
url: info.link,
rawPlaylist: info
};
return resolve({ playlist: playlist, info: tracks });
}
}
// ---- end spotify ----
if (query.startsWith("https")) {
query = query.split("&")[0];
}
if (query.startsWith("https") && playdl.yt_validate(query) === "video") {
const info = await Youtube.search(query, {limit: 1, type: "video", safeSearch: true});
if(!info || !info.length)
return resolve({ playlist: null, info: null });
const track = {
title: info[0].title,
duration: info[0].duration,
thumbnail: info[0].thumbnail ? info[0].thumbnail.url : null,
async engine() {
return (await playdl.stream(`https://youtu.be/${info[0].id}`, { discordPlayerCompatibility : true })).stream;
},
views: info[0].views,
author: info[0].channel.name,
description: "",
url: `https://youtu.be/${info[0].id}`,
source: "youtube-custom"
};
return resolve({ playlist: null, info: [track] });
} else if (playdl.yt_validate(query) === "playlist") {
const info = await playdl.playlist_info(query, { incomplete: true });
const trackList = await info.all_videos();
const tracks = trackList.map(track => {
return {
title: track.title,
duration: track.durationInSec * 1000,
thumbnail: track.thumbnails ? track.thumbnails[0] ? track.thumbnails[0].url : null : null,
async engine() {
return (await playdl.stream(await Youtube.search(track.url, {limit: 1, type: "video", safeSearch: true}).then(x => x[0] ? `https://youtu.be/${x[0].id}` : "https://youtu.be/Wch3gJG2GJ4"), { discordPlayerCompatibility : true })).stream;
},
views: track.views,
author: track.channel.name,
description: "",
url: track.url,
source: "youtube-custom"
};
});
const playlist = {
title: info.title,
description: "",
thumbnail: info.thumbnail ? info.thumbnail.url : null,
type: "playlist",
source: "youtube-custom",
author: info.channel.name,
id: info.id,
url: info.url,
rawPlaylist: info
};
return resolve({ playlist: playlist, info: tracks });
}
const search = await Youtube.search(query, { limit: 5, type: "video", safeSearch: true });
if(search && search.length) {
const tracks = search.map(track => {
return {
title: track.title,
duration: track.duration,
thumbnail: track.thumbnail ? track.thumbnail.url : null,
async engine() {
return (await playdl.stream(`https://youtu.be/${track.id}`, { discordPlayerCompatibility: true })).stream;
},
views: track.views,
author: track.channel.name,
description: "",
url: `https://youtu.be/${track.id}`,
source: "youtube-custom"
};
});
return resolve({ playlist: null, info: tracks });
}
return resolve({ playlist: null, info: null });
} catch(error) {
console.log(`Extractor: An error occurred while attempting to resolve ${query} :\n${error}`);
return resolve({ playlist: null, info: null });
}
});
}
};

51
package-lock.json generated
View file

@ -21,7 +21,7 @@
"cron": "^1.7.2", "cron": "^1.7.2",
"discord-api-types": "^0.37.0", "discord-api-types": "^0.37.0",
"discord-giveaways": "^6.0.0", "discord-giveaways": "^6.0.0",
"discord-player": "^5.3.0-dev.3", "discord-player": "^5.3.0",
"discord.js": "^14.1.2", "discord.js": "^14.1.2",
"ejs": "^3.1.3", "ejs": "^3.1.3",
"express": "^4.17.1", "express": "^4.17.1",
@ -36,7 +36,9 @@
"moment": "^2.26.0", "moment": "^2.26.0",
"mongoose": "^5.13.14", "mongoose": "^5.13.14",
"ms": "^2.1.3", "ms": "^2.1.3",
"prism-media": "^1.3.4" "play-dl": "^1.9.5",
"prism-media": "^1.3.4",
"spotify-url-info": "^3.1.2"
}, },
"devDependencies": { "devDependencies": {
"eslint": "^7.5.0" "eslint": "^7.5.0"
@ -1369,9 +1371,9 @@
} }
}, },
"node_modules/discord-player": { "node_modules/discord-player": {
"version": "5.3.0-dev.3", "version": "5.3.0",
"resolved": "https://registry.npmjs.org/discord-player/-/discord-player-5.3.0-dev.3.tgz", "resolved": "https://registry.npmjs.org/discord-player/-/discord-player-5.3.0.tgz",
"integrity": "sha512-rrbEBS4mzCyIGk5S9E5O0XWnC4nub2cmBAFr9pZLH7RWBX4+z2nhAt5VwemgenmW/RJy1rseuZZ75WqJDnrHnw==", "integrity": "sha512-OskERYrsVqNvyq8tKkp3aV3NMY9dP5BhNeyn5NTTDohVd9eEE8P6rZGvxqORJl1OxXCTBLbiojNgLiFNsAIaow==",
"dependencies": { "dependencies": {
"@discordjs/voice": "^0.11.0", "@discordjs/voice": "^0.11.0",
"libsodium-wrappers": "^0.7.10", "libsodium-wrappers": "^0.7.10",
@ -1379,7 +1381,7 @@
"spotify-url-info": "^3.1.2", "spotify-url-info": "^3.1.2",
"tiny-typed-emitter": "^2.1.0", "tiny-typed-emitter": "^2.1.0",
"tslib": "^2.4.0", "tslib": "^2.4.0",
"youtube-sr": "^4.2.0", "youtube-sr": "^4.3.0",
"ytdl-core": "^4.11.0" "ytdl-core": "^4.11.0"
}, },
"funding": { "funding": {
@ -3610,6 +3612,22 @@
"url": "https://github.com/sponsors/Borewit" "url": "https://github.com/sponsors/Borewit"
} }
}, },
"node_modules/play-audio": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/play-audio/-/play-audio-0.5.2.tgz",
"integrity": "sha512-ZAqHUKkQLix2Iga7pPbsf1LpUoBjcpwU93F1l3qBIfxYddQLhxS6GKmS0d3jV8kSVaUbr6NnOEcEMFvuX93SWQ=="
},
"node_modules/play-dl": {
"version": "1.9.5",
"resolved": "https://registry.npmjs.org/play-dl/-/play-dl-1.9.5.tgz",
"integrity": "sha512-tfjBgpU6AD63snK6sXiSuAOi+3iLsqVvsFcvCritOetF/zIo2OcB4BURX+WaQLUmEX3sUJhzP/vqG8SSl7WEpA==",
"dependencies": {
"play-audio": "^0.5.2"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/prelude-ls": { "node_modules/prelude-ls": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@ -5736,9 +5754,9 @@
} }
}, },
"discord-player": { "discord-player": {
"version": "5.3.0-dev.3", "version": "5.3.0",
"resolved": "https://registry.npmjs.org/discord-player/-/discord-player-5.3.0-dev.3.tgz", "resolved": "https://registry.npmjs.org/discord-player/-/discord-player-5.3.0.tgz",
"integrity": "sha512-rrbEBS4mzCyIGk5S9E5O0XWnC4nub2cmBAFr9pZLH7RWBX4+z2nhAt5VwemgenmW/RJy1rseuZZ75WqJDnrHnw==", "integrity": "sha512-OskERYrsVqNvyq8tKkp3aV3NMY9dP5BhNeyn5NTTDohVd9eEE8P6rZGvxqORJl1OxXCTBLbiojNgLiFNsAIaow==",
"requires": { "requires": {
"@discordjs/voice": "^0.11.0", "@discordjs/voice": "^0.11.0",
"libsodium-wrappers": "^0.7.10", "libsodium-wrappers": "^0.7.10",
@ -5746,7 +5764,7 @@
"spotify-url-info": "^3.1.2", "spotify-url-info": "^3.1.2",
"tiny-typed-emitter": "^2.1.0", "tiny-typed-emitter": "^2.1.0",
"tslib": "^2.4.0", "tslib": "^2.4.0",
"youtube-sr": "^4.2.0", "youtube-sr": "^4.3.0",
"ytdl-core": "^4.11.0" "ytdl-core": "^4.11.0"
} }
}, },
@ -7448,6 +7466,19 @@
"resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0-alpha.5.tgz", "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0-alpha.5.tgz",
"integrity": "sha512-pJohF/tDwV3ntnT5+EkUo4E700q/j/OCDuPxtM+5/kFGjyOai/sK4/We4Cy1MB2OiTQliWU5DxPvYIKQAdPqAA==" "integrity": "sha512-pJohF/tDwV3ntnT5+EkUo4E700q/j/OCDuPxtM+5/kFGjyOai/sK4/We4Cy1MB2OiTQliWU5DxPvYIKQAdPqAA=="
}, },
"play-audio": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/play-audio/-/play-audio-0.5.2.tgz",
"integrity": "sha512-ZAqHUKkQLix2Iga7pPbsf1LpUoBjcpwU93F1l3qBIfxYddQLhxS6GKmS0d3jV8kSVaUbr6NnOEcEMFvuX93SWQ=="
},
"play-dl": {
"version": "1.9.5",
"resolved": "https://registry.npmjs.org/play-dl/-/play-dl-1.9.5.tgz",
"integrity": "sha512-tfjBgpU6AD63snK6sXiSuAOi+3iLsqVvsFcvCritOetF/zIo2OcB4BURX+WaQLUmEX3sUJhzP/vqG8SSl7WEpA==",
"requires": {
"play-audio": "^0.5.2"
}
},
"prelude-ls": { "prelude-ls": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",

View file

@ -24,7 +24,7 @@
"cron": "^1.7.2", "cron": "^1.7.2",
"discord-api-types": "^0.37.0", "discord-api-types": "^0.37.0",
"discord-giveaways": "^6.0.0", "discord-giveaways": "^6.0.0",
"discord-player": "^5.3.0-dev.3", "discord-player": "^5.3.0",
"discord.js": "^14.1.2", "discord.js": "^14.1.2",
"ejs": "^3.1.3", "ejs": "^3.1.3",
"express": "^4.17.1", "express": "^4.17.1",
@ -39,7 +39,9 @@
"moment": "^2.26.0", "moment": "^2.26.0",
"mongoose": "^5.13.14", "mongoose": "^5.13.14",
"ms": "^2.1.3", "ms": "^2.1.3",
"prism-media": "^1.3.4" "play-dl": "^1.9.5",
"prism-media": "^1.3.4",
"spotify-url-info": "^3.1.2"
}, },
"devDependencies": { "devDependencies": {
"eslint": "^7.5.0" "eslint": "^7.5.0"