This commit is contained in:
Flatlogic Bot 2026-02-16 06:55:36 +00:00
parent a09afbaf39
commit ca3a32f23e
869 changed files with 124357 additions and 286 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 KiB

View File

@ -1,3 +1,4 @@
DISCORD_TOKEN=MTQ3MTkwOTE5Mzg4Njg1OTI5NA.GlIuXe._ee-bIu9eyIs1uqePNjQbR6vksYgVBseEMW6qs
VC_ID=1457687430189682781
SAHUR_TIME=03:30
CLIENT_ID=1471909193886859294

View File

@ -1184,3 +1184,82 @@ Sign in to confirm youre not a bot
at async stream (/home/ubuntu/executor/workspace/bot/node_modules/play-dl/dist/index.js:7:16453)
at async Object.stream (/home/ubuntu/executor/workspace/bot/node_modules/play-dl/dist/index.js:15:3190)
at async playSong (/home/ubuntu/executor/workspace/bot/index.js:307:24)
[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚙️ enable debug logging with { debug: true }
DisTubeError [INVALID_KEY]: 'ffmpegDefaultArgs' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:25:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚙️ write to custom object with { processEnv: myObject }
DisTubeError [INVALID_KEY]: 'ffmpegDefaultArgs' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:25:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (0) from .env -- tip: 🔐 encrypt with Dotenvx: https://dotenvx.com
DisTubeError [INVALID_KEY]: 'ffmpegDefaultArgs' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:25:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (0) from .env -- tip: 🔐 prevent building .env in docker: https://dotenvx.com/prebuild
DisTubeError [INVALID_KEY]: 'ffmpegDefaultArgs' does not need to be provided in DisTubeOptions
at checkInvalidKey (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1288:25)
at new Options (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:1692:5)
at new DisTube (/home/ubuntu/executor/workspace/bot/node_modules/distube/dist/index.js:2281:20)
at Object.<anonymous> (/home/ubuntu/executor/workspace/bot/index.js:25:17)
at Module._compile (node:internal/modules/cjs/loader:1688:14)
at Object..js (node:internal/modules/cjs/loader:1820:10)
at Module.load (node:internal/modules/cjs/loader:1423:32)
at Function._load (node:internal/modules/cjs/loader:1246:12)
at Object.<anonymous> (/usr/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
at Module._compile (node:internal/modules/cjs/loader:1688:14) {
errorCode: 'INVALID_KEY'
}
[dotenv@17.3.1] injecting env (0) from .env -- tip: 🔐 encrypt with Dotenvx: https://dotenvx.com
[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚙️ override existing env vars with { override: true }
[YtDlpPlugin] This plugin is not the last plugin in distube. This is not recommended.
[2026-02-16T06:07:13.428Z] Ready! Logged in as AsepXiaoQin#6954
Ready! Logged in as AsepXiaoQin#6954
[2026-02-16T06:07:16.679Z] Alarm scheduled at 0 30 03 * * *
Alarm scheduled at 0 30 03 * * *
[dotenv@17.3.1] injecting env (0) from .env -- tip: ⚙️ load multiple .env files with { path: ['.env.local', '.env'] }
[2026-02-16T06:09:00.688Z] Ready! Logged in as AsepXiaoQin#6954
Ready! Logged in as AsepXiaoQin#6954
[2026-02-16T06:09:01.692Z] Alarm scheduled at 0 30 03 * * *
Alarm scheduled at 0 30 03 * * *
[2026-02-16T06:26:38.184Z] Ready! Logged in as AsepXiaoQin#6954
[2026-02-16T06:26:39.697Z] Alarm scheduled at 0 30 03 * * *
[2026-02-16T06:31:52.117Z] Ready! Logged in as AsepXiaoQin#6954
[2026-02-16T06:31:53.091Z] Alarm scheduled at 0 30 03 * * *
[2026-02-16T06:35:19.453Z] Interaction Error: ffmpeg is not installed at 'ffmpeg' path
[2026-02-16T06:35:39.525Z] Interaction Error: ffmpeg is not installed at 'ffmpeg' path
[2026-02-16T06:41:45.266Z] Interaction Error: ffmpeg is not installed at 'ffmpeg' path
[2026-02-16T06:41:55.958Z] Interaction Error: ffmpeg is not installed at 'ffmpeg' path
[2026-02-16T06:49:05.559Z] Ready! Logged in as AsepXiaoQin#6954
[2026-02-16T06:49:05.563Z] FFMPEG Path: /home/ubuntu/executor/workspace/bot/node_modules/ffmpeg-static/ffmpeg
[2026-02-16T06:49:06.586Z] Alarm scheduled at 0 30 03 * * *

View File

@ -1,5 +1,6 @@
const { REST, Routes, SlashCommandBuilder } = require('discord.js');
require('dotenv').config();
const path = require('path');
require('dotenv').config({ path: path.join(__dirname, '.env') });
const commands = [
new SlashCommandBuilder()

View File

@ -1,34 +1,19 @@
require('dotenv').config();
const { Client, GatewayIntentBits, Events } = require('discord.js');
const { joinVoiceChannel, createAudioPlayer, createAudioResource, AudioPlayerStatus, NoSubscriberBehavior, VoiceConnectionStatus, generateDependencyReport, entersState, StreamType } = require('@discordjs/voice');
const { CronJob } = require('cron');
process.env.FFMPEG_PATH = require('ffmpeg-static');
const path = require('path');
const play = require('play-dl');
// Tambahkan folder ffmpeg ke PATH agar yt-dlp bisa menemukannya
const ffmpegDir = path.dirname(process.env.FFMPEG_PATH);
if (!process.env.PATH.includes(ffmpegDir)) {
process.env.PATH = `${ffmpegDir}${path.delimiter}${process.env.PATH}`;
}
require('dotenv').config({ path: path.join(__dirname, '.env') });
const { Client, GatewayIntentBits, Events, EmbedBuilder } = require('discord.js');
const { DisTube } = require('distube');
const { YtDlpPlugin } = require('@distube/yt-dlp');
const { SpotifyPlugin } = require('@distube/spotify');
const { SoundCloudPlugin } = require('@distube/soundcloud');
const { CronJob } = require('cron');
const fs = require('fs');
const libsodium = require('libsodium-wrappers');
const ffmpegPath = require('ffmpeg-static');
const { spawn } = require('child_process');
async function startBot() {
logToFile('Dependency Report:\n' + generateDependencyReport());
await libsodium.ready;
logToFile('Encryption library (libsodium) is ready.');
client.login(process.env.DISCORD_TOKEN);
}
function logToFile(message) {
const logMessage = `[${new Date().toISOString()}] ${message}\n`;
fs.appendFileSync(path.join(__dirname, 'bot.log'), logMessage);
console.log(message);
}
process.on('unhandledRejection', error => {
logToFile(`Unhandled Rejection: ${error.message}\n${error.stack}`);
});
process.on('uncaughtException', error => {
logToFile(`Uncaught Exception: ${error.message}\n${error.stack}`);
});
const client = new Client({
intents: [
@ -39,16 +24,62 @@ const client = new Client({
]
});
const VC_ID = process.env.VC_ID;
const AUDIO_PATH = path.join(__dirname, 'assets/audio/sahur.mp3');
// Initialize DisTube with the requested plugins
const distube = new DisTube(client, {
plugins: [
new SpotifyPlugin(),
new SoundCloudPlugin(),
new YtDlpPlugin() // yt-dlp must be last
],
emitNewSongOnly: true,
emitAddSongWhenCreatingQueue: false,
emitAddListWhenCreatingQueue: false
});
// Global state for music queues
const queues = new Map();
const VC_ID = process.env.VC_ID;
const SAHUR_AUDIO_PATH = path.join(__dirname, 'assets/audio/sahur.mp3');
function logToFile(message) {
const logMessage = `[${new Date().toISOString()}] ${message}\n`;
fs.appendFileSync(path.join(__dirname, 'bot.log'), logMessage);
console.log(message);
}
// Better Error Handling for DisTube
distube
.on('playSong', (queue, song) => {
logToFile(`Playing: ${song.name}`);
const embed = new EmbedBuilder()
.setColor('#00FF00')
.setTitle('🎶 Sedang Memutar')
.setDescription(`**${song.name}**`)
.addFields(
{ name: 'Durasi', value: song.formattedDuration, inline: true },
{ name: 'Platform', value: song.source.toUpperCase(), inline: true }
)
.setThumbnail(song.thumbnail);
queue.textChannel.send({ embeds: [embed] });
})
.on('addSong', (queue, song) => {
queue.textChannel.send(`✅ **${song.name}** ditambahkan ke antrean!`);
})
.on('error', (channel, e) => {
const errorMsg = `DisTube Error: ${e.stack || e.message || e}`;
logToFile(errorMsg);
if (channel && channel.send) channel.send(`❌ Terjadi kesalahan audio: ${e.message.slice(0, 1000)}`);
})
.on('empty', queue => {
if (queue.textChannel) queue.textChannel.send('Voice channel kosong, bot keluar...');
})
.on('searchNoResult', (message, query) => {
if (message.channel) message.channel.send(`❌ Tidak ada hasil untuk: ${query}`);
});
client.once(Events.ClientReady, async c => {
logToFile(`Ready! Logged in as ${c.user.tag}`);
// Sahur Alarm (Jakarta Time)
logToFile(`FFMPEG Path: ${process.env.FFMPEG_PATH}`);
// Sahur Alarm
const sahurTime = process.env.SAHUR_TIME || '30 03 * * *';
let cronTime = sahurTime;
if (sahurTime.includes(':') && !sahurTime.includes('*')) {
@ -61,294 +92,100 @@ client.once(Events.ClientReady, async c => {
logToFile('Sahur alarm triggered!');
const guild = client.guilds.cache.first();
if (!guild) return;
const channel = guild.channels.cache.get(VC_ID);
if (channel) {
playLocal(channel, AUDIO_PATH);
distube.play(channel, SAHUR_AUDIO_PATH, {
skip: true,
textChannel: guild.systemChannel || guild.channels.cache.find(ch => ch.type === 0)
});
}
}, null, true, 'Asia/Jakarta');
logToFile(`Alarm scheduled at ${cronTime}`);
} catch (e) {
logToFile(`Failed to schedule alarm: ${e.message}`);
}
// Auto-join on start if VC_ID is provided
if (VC_ID) {
const guild = client.guilds.cache.first();
if (guild) {
const channel = guild.channels.cache.get(VC_ID);
if (channel) {
logToFile(`Auto-joining VC: ${channel.name}`);
const connection = joinVoiceChannel({
channelId: channel.id,
guildId: guild.id,
adapterCreator: guild.voiceAdapterCreator,
});
setupConnectionListeners(connection);
}
}
}
});
function setupConnectionListeners(connection) {
connection.on(VoiceConnectionStatus.Disconnected, async () => {
logToFile('Disconnected from VC. Attempting to reconnect...');
try {
await Promise.race([
entersState(connection, VoiceConnectionStatus.Signalling, 5_000),
entersState(connection, VoiceConnectionStatus.Connecting, 5_000),
]);
// Reconnected!
} catch (error) {
logToFile(`Reconnection failed: ${error.message}`);
connection.destroy();
}
});
}
// Handle Slash Commands
client.on(Events.InteractionCreate, async interaction => {
if (!interaction.isChatInputCommand()) return;
logToFile(`Interaction received: ${interaction.commandName} from ${interaction.user.tag}`);
const { commandName } = interaction;
const voiceChannel = interaction.member?.voice.channel;
if (['play', 'testsahur', 'skip', 'stop', 'pause', 'resume'].includes(commandName) && !voiceChannel) {
return interaction.reply({ content: 'Kamu harus berada di voice channel!', ephemeral: true });
}
try {
if (commandName === 'join') {
if (!voiceChannel) return interaction.reply({ content: 'Kamu harus di voice channel!', ephemeral: true });
const connection = joinVoiceChannel({
channelId: voiceChannel.id,
guildId: interaction.guild.id,
adapterCreator: interaction.guild.voiceAdapterCreator,
});
setupConnectionListeners(connection);
await interaction.reply('Siap! Sudah join voice channel. 🎧 Bot akan standby di sini.');
}
if (commandName === 'testsahur') {
if (!voiceChannel) return interaction.reply({ content: 'Kamu harus di voice channel!', ephemeral: true });
await interaction.deferReply();
logToFile('Executing /testsahur...');
await interaction.reply('Memainkan suara sahur... 📢');
playLocal(voiceChannel, AUDIO_PATH);
if (!fs.existsSync(SAHUR_AUDIO_PATH)) {
throw new Error(`File tidak ditemukan di: ${SAHUR_AUDIO_PATH}`);
}
await distube.play(voiceChannel, SAHUR_AUDIO_PATH, {
skip: true,
member: interaction.member,
textChannel: interaction.channel
});
await interaction.editReply('📢 Memutar suara Sahur untuk pengetesan!');
}
if (commandName === 'play') {
if (!voiceChannel) return interaction.reply({ content: 'Kamu harus di voice channel!', ephemeral: true });
else if (commandName === 'play') {
const query = interaction.options.getString('query');
await interaction.deferReply();
logToFile(`Executing /play with query: ${query}`);
let serverQueue = queues.get(interaction.guild.id);
if (!serverQueue) {
serverQueue = {
songs: [],
connection: null,
player: createAudioPlayer({
behaviors: { noSubscriber: NoSubscriberBehavior.Play }
}),
if (query.toLowerCase() === 'sahur') {
await distube.play(voiceChannel, SAHUR_AUDIO_PATH, {
skip: true,
member: interaction.member,
textChannel: interaction.channel
};
queues.set(interaction.guild.id, serverQueue);
});
return interaction.editReply('📢 Memainkan audio Sahur lokal...');
}
let songInfo;
// Validate and search
try {
if (query.includes('spotify.com')) {
if (play.sp_validate(query)) {
const sp_data = await play.spotify(query);
if (sp_data.type === 'track') {
const search = await play.search(`${sp_data.name} ${sp_data.artists[0].name}`, { limit: 1 });
songInfo = { title: sp_data.name, url: search[0].url };
} else {
return interaction.editReply('Hanya mendukung link track Spotify untuk saat ini.');
}
}
} else if (query.includes('soundcloud.com')) {
const so_data = await play.soundcloud(query);
songInfo = { title: so_data.name, url: so_data.url };
} else {
const yt_info = await play.search(query, { limit: 1 });
if (yt_info.length === 0) return interaction.editReply('Lagu tidak ditemukan!');
songInfo = { title: yt_info[0].title, url: yt_info[0].url };
}
} catch (err) {
logToFile(`Search error: ${err.message}`);
return interaction.editReply('Gagal mencari lagu. Coba judul yang berbeda.');
}
serverQueue.songs.push(songInfo);
if (serverQueue.songs.length === 1) {
playSong(interaction.guild.id, voiceChannel);
await interaction.editReply(`🎵 Sekarang memutar: **${songInfo.title}**`);
} else {
await interaction.editReply(`✅ **${songInfo.title}** ditambahkan ke antrean.`);
}
await distube.play(voiceChannel, query, {
textChannel: interaction.channel,
member: interaction.member
});
await interaction.editReply(`🔍 Mencari: **${query}**`);
}
if (commandName === 'pause') {
const serverQueue = queues.get(interaction.guild.id);
if (serverQueue) {
serverQueue.player.pause();
return interaction.reply('Musik dipause. ⏸️');
}
interaction.reply('Tidak ada musik yang sedang diputar.');
else if (commandName === 'pause') {
await interaction.deferReply();
distube.pause(interaction.guildId);
await interaction.editReply('Musik dipause. ⏸️');
}
if (commandName === 'resume') {
const serverQueue = queues.get(interaction.guild.id);
if (serverQueue) {
serverQueue.player.unpause();
return interaction.reply('Musik dilanjutkan. ▶️');
}
interaction.reply('Tidak ada musik yang sedang diputar.');
else if (commandName === 'resume') {
await interaction.deferReply();
distube.resume(interaction.guildId);
await interaction.editReply('Musik dilanjutkan. ▶️');
}
if (commandName === 'skip') {
const serverQueue = queues.get(interaction.guild.id);
if (serverQueue) {
serverQueue.player.stop();
return interaction.reply('Lagu dilewati! ⏭️');
}
interaction.reply('Tidak ada musik yang sedang diputar.');
else if (commandName === 'skip') {
await interaction.deferReply();
await distube.skip(interaction.guildId);
await interaction.editReply('Lagu dilewati! ⏭️');
}
if (commandName === 'stop') {
const serverQueue = queues.get(interaction.guild.id);
if (serverQueue) {
serverQueue.songs = [];
serverQueue.player.stop();
return interaction.reply('Musik dihentikan dan antrean dihapus. Bot tetap di channel.');
}
interaction.reply('Bot tidak sedang memutar musik.');
else if (commandName === 'stop') {
await interaction.deferReply();
await distube.stop(interaction.guildId);
await interaction.editReply('Musik dihentikan.');
}
} catch (err) {
logToFile(`Error handling command ${commandName}: ${err.message}`);
if (!interaction.replied && !interaction.deferred) {
await interaction.reply({ content: 'Terjadi kesalahan saat menjalankan command.', ephemeral: true });
} else if (interaction.deferred) {
await interaction.editReply('Terjadi kesalahan saat menjalankan command.');
logToFile(`Command Error (${commandName}): ${err.stack || err.message}`);
if (interaction.deferred || interaction.replied) {
await interaction.editReply(`❌ Error: ${err.message}`);
} else {
await interaction.reply({ content: `❌ Error: ${err.message}`, ephemeral: true });
}
}
});
async function playLocal(channel, filePath) {
logToFile(`Playing local file using ffmpeg-static: ${filePath}`);
if (!fs.existsSync(filePath)) {
logToFile(`Error: File not found at ${filePath}`);
return;
}
const connection = joinVoiceChannel({
channelId: channel.id,
guildId: channel.guild.id,
adapterCreator: channel.guild.voiceAdapterCreator,
});
const player = createAudioPlayer({
behaviors: {
noSubscriber: NoSubscriberBehavior.Play,
},
});
try {
const ffmpegProcess = spawn(ffmpegPath, [
'-i', filePath,
'-f', 's16le',
'-ar', '48000',
'-ac', '2',
'pipe:1'
]);
const resource = createAudioResource(ffmpegProcess.stdout, {
inputType: StreamType.Raw
});
player.play(resource);
connection.subscribe(player);
logToFile(`Successfully started playing with ffmpeg-static: ${filePath}`);
ffmpegProcess.on('error', error => {
logToFile(`FFmpeg process error: ${error.message}`);
});
} catch (error) {
logToFile(`Error creating audio resource with ffmpeg: ${error.message}`);
}
player.on('error', error => {
logToFile(`Audio player error: ${error.message}`);
console.error('Audio Player Error Detail:', error);
});
player.on(AudioPlayerStatus.Playing, () => {
logToFile('Audio player started playing!');
});
player.once(AudioPlayerStatus.Idle, () => {
logToFile('Local audio finished. Staying in channel.');
});
}
async function playSong(guildId, channel) {
const serverQueue = queues.get(guildId);
if (!serverQueue || serverQueue.songs.length === 0) {
return;
}
const song = serverQueue.songs[0];
try {
logToFile(`Fetching stream for: ${song.title}`);
const stream = await play.stream(song.url);
logToFile(`Stream fetched successfully for ${song.title}`);
const resource = createAudioResource(stream.stream, {
inputType: StreamType.Arbitrary
});
if (!serverQueue.connection) {
logToFile(`Creating new connection for guild: ${guildId}`);
serverQueue.connection = joinVoiceChannel({
channelId: channel.id,
guildId: guildId,
adapterCreator: channel.guild.voiceAdapterCreator,
});
setupConnectionListeners(serverQueue.connection);
serverQueue.connection.subscribe(serverQueue.player);
}
serverQueue.player.play(resource);
logToFile(`Now playing: ${song.title}`);
serverQueue.player.once(AudioPlayerStatus.Idle, () => {
logToFile(`Finished playing: ${song.title}`);
serverQueue.songs.shift();
if (serverQueue.songs.length > 0) {
playSong(guildId, channel);
serverQueue.textChannel.send(`🎵 Sekarang memutar: **${serverQueue.songs[0].title}**`);
} else {
logToFile('Queue empty. Staying in channel.');
}
});
serverQueue.player.on('error', error => {
logToFile(`Error in player while playing ${song.title}: ${error.message}`);
console.error('Player Error Detail:', error);
serverQueue.songs.shift();
playSong(guildId, channel);
});
} catch (e) {
logToFile(`Error playing song ${song.title}: ${e.message}`);
console.error('PlaySong Error Detail:', e);
serverQueue.songs.shift();
playSong(guildId, channel);
}
}
startBot();
client.login(process.env.DISCORD_TOKEN);

1
bot/node_modules/.bin/mime generated vendored Symbolic link
View File

@ -0,0 +1 @@
../mime/cli.js

569
bot/node_modules/.package-lock.json generated vendored
View File

@ -202,6 +202,56 @@
"url": "https://github.com/discordjs/discord.js?sponsor"
}
},
"node_modules/@distube/soundcloud": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@distube/soundcloud/-/soundcloud-2.0.4.tgz",
"integrity": "sha512-Uc/1wDDfslu5frieENNudJBYnKmqNESzQ2MxtxpNK5d0vn6ll69g0atvQTtNt2PA4Pc+Glap1AkZXC+xjgiKKQ==",
"license": "MIT",
"dependencies": {
"soundcloud.ts": "^0.6.2"
},
"funding": {
"url": "https://github.com/skick1234/DisTube?sponsor"
},
"peerDependencies": {
"distube": "5"
}
},
"node_modules/@distube/spotify": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@distube/spotify/-/spotify-2.0.2.tgz",
"integrity": "sha512-rIncX05PhedMZuZyhgz7dt9y/nxir9KPmxUo6sBxfITQcztkXlG3r0EhKivp9+BRCQlEBO/GitRTHVwhRKtmLg==",
"license": "MIT",
"dependencies": {
"spotify-uri": "^4.1.0",
"spotify-url-info": "^3.2.15",
"spotify-web-api-node": "^5.0.2",
"undici": "^6.18.2"
},
"funding": {
"url": "https://github.com/skick1234/DisTube?sponsor"
},
"peerDependencies": {
"distube": "5"
}
},
"node_modules/@distube/yt-dlp": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@distube/yt-dlp/-/yt-dlp-2.0.1.tgz",
"integrity": "sha512-9c16lRU6jbyal38UUr5E36+2lp36s0DaJySOtFjuAPgaJkp2xvKvyd+s4rFZSqVQGJO5GOhBiH+HD115SKfKAw==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"dargs": "^7.0.0",
"undici": "^6.18.2"
},
"funding": {
"url": "https://github.com/skick1234/DisTube?sponsor"
},
"peerDependencies": {
"distube": "5"
}
},
"node_modules/@sapphire/async-queue": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.5.tgz",
@ -467,6 +517,12 @@
"node": ">=10"
}
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"license": "MIT"
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@ -489,6 +545,35 @@
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"license": "MIT"
},
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/call-bound": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"get-intrinsic": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
@ -513,6 +598,27 @@
"color-support": "bin.js"
}
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"license": "MIT",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/component-emitter": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
"integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -540,6 +646,12 @@
"integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
"license": "ISC"
},
"node_modules/cookiejar": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz",
"integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==",
"license": "MIT"
},
"node_modules/cron": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/cron/-/cron-2.4.4.tgz",
@ -550,6 +662,15 @@
"luxon": "~3.3.0"
}
},
"node_modules/dargs": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz",
"integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
@ -567,6 +688,15 @@
}
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"license": "MIT",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
@ -618,6 +748,35 @@
"url": "https://github.com/discordjs/discord.js?sponsor"
}
},
"node_modules/distube": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/distube/-/distube-5.2.3.tgz",
"integrity": "sha512-fWdFDR3bH3fbkEthAukUKEpiRWCjt9xfgCCOkJqTCpdjkDx6zGDRFe+ETp8MlGMl7SGFjS0tntXzNF0o4NQSvg==",
"license": "MIT",
"dependencies": {
"tiny-typed-emitter": "^2.1.0",
"undici": "^7.16.0"
},
"engines": {
"node": ">=22.12.0"
},
"funding": {
"url": "https://github.com/skick1234/DisTube?sponsor"
},
"peerDependencies": {
"@discordjs/voice": "*",
"discord.js": "14"
}
},
"node_modules/distube/node_modules/undici": {
"version": "7.22.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-7.22.0.tgz",
"integrity": "sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==",
"license": "MIT",
"engines": {
"node": ">=20.18.1"
}
},
"node_modules/dotenv": {
"version": "17.3.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz",
@ -630,6 +789,20 @@
"url": "https://dotenvx.com"
}
},
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
"es-errors": "^1.3.0",
"gopd": "^1.2.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
@ -645,12 +818,63 @@
"node": ">=6"
}
},
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-object-atoms": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-set-tostringtag": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.6",
"has-tostringtag": "^1.0.2",
"hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"license": "MIT"
},
"node_modules/fast-safe-stringify": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
"integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==",
"license": "MIT"
},
"node_modules/ffmpeg-static": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/ffmpeg-static/-/ffmpeg-static-5.3.0.tgz",
@ -667,6 +891,32 @@
"node": ">=16"
}
},
"node_modules/form-data": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.4.tgz",
"integrity": "sha512-f0cRzm6dkyVYV3nPoooP8XlccPQukegwhAnpoLcXy+X+A8KfpGOoXwDr9FLZd3wzgLaBGQBE3lY93Zm/i1JvIQ==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.2",
"mime-types": "^2.1.35"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/formidable": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz",
"integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==",
"deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau",
"license": "MIT",
"funding": {
"url": "https://ko-fi.com/tunnckoCore/commissions"
}
},
"node_modules/fs-minipass": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
@ -697,6 +947,15 @@
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"license": "ISC"
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/gauge": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
@ -718,6 +977,43 @@
"node": ">=10"
}
},
"node_modules/get-intrinsic": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"es-define-property": "^1.0.1",
"es-errors": "^1.3.0",
"es-object-atoms": "^1.1.1",
"function-bind": "^1.1.2",
"get-proto": "^1.0.1",
"gopd": "^1.2.0",
"has-symbols": "^1.1.0",
"hasown": "^2.0.2",
"math-intrinsics": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.1",
"es-object-atoms": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@ -739,12 +1035,69 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-tostringtag": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"license": "MIT",
"dependencies": {
"has-symbols": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-unicode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
"license": "ISC"
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/himalaya": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/himalaya/-/himalaya-1.1.1.tgz",
"integrity": "sha512-mJLY5tErGWtsw8hO2fJ2vK4IpG6S1AIgVkduRo4FqFJhgI2H3XLzgemRemk45zcnFyxNNpOfrIDle2KcnJM0lA==",
"license": "ISC"
},
"node_modules/http-response-object": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz",
@ -865,6 +1218,57 @@
"semver": "bin/semver.js"
}
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
"integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
"license": "MIT",
"bin": {
"mime": "cli.js"
},
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@ -995,6 +1399,18 @@
"node": ">=0.10.0"
}
},
"node_modules/object-inspect": {
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
"integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@ -1079,6 +1495,21 @@
"node": ">=0.4.0"
}
},
"node_modules/qs": {
"version": "6.15.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz",
"integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.1.0"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
@ -1147,12 +1578,121 @@
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
"license": "ISC"
},
"node_modules/side-channel": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.3",
"side-channel-list": "^1.0.0",
"side-channel-map": "^1.0.1",
"side-channel-weakmap": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-list": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
"integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-map": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.5",
"object-inspect": "^1.13.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-weakmap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.5",
"object-inspect": "^1.13.3",
"side-channel-map": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/signal-exit": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
"license": "ISC"
},
"node_modules/soundcloud.ts": {
"version": "0.6.9",
"resolved": "https://registry.npmjs.org/soundcloud.ts/-/soundcloud.ts-0.6.9.tgz",
"integrity": "sha512-mOUpdtNFPhoz8xwoEQMLY/W6VQeXhAeoWEwaMVZozhb0qKX1IfWcXKr2LyxoDpZgOUovIb+gOx9wHQNj1YcO3w==",
"license": "MIT"
},
"node_modules/spotify-uri": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/spotify-uri/-/spotify-uri-4.1.0.tgz",
"integrity": "sha512-SFpBt8pQqO7DOFBsdUjv3GxGZAKYP7UqcTflfE7h3YL1lynl/6Motq7NERoJJR8eF9kXQRSpcdMmV5ou84rbng==",
"license": "MIT",
"engines": {
"node": ">= 16"
}
},
"node_modules/spotify-url-info": {
"version": "3.2.18",
"resolved": "https://registry.npmjs.org/spotify-url-info/-/spotify-url-info-3.2.18.tgz",
"integrity": "sha512-apL7H8i+zpj3gnVxXrhEa1H6uBORC2iTExjw808/13Z6mBHJvsF6Dt4ZZF9E+J54n2p7KyGRxnpgm4nEvxsxjQ==",
"license": "MIT",
"dependencies": {
"himalaya": "~1.1.0",
"spotify-uri": "~4.1.0"
},
"engines": {
"node": ">= 12"
}
},
"node_modules/spotify-web-api-node": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/spotify-web-api-node/-/spotify-web-api-node-5.0.2.tgz",
"integrity": "sha512-r82dRWU9PMimHvHEzL0DwEJrzFk+SMCVfq249SLt3I7EFez7R+jeoKQd+M1//QcnjqlXPs2am4DFsGk8/GCsrA==",
"license": "MIT",
"dependencies": {
"superagent": "^6.1.0"
}
},
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
@ -1188,6 +1728,29 @@
"node": ">=8"
}
},
"node_modules/superagent": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/superagent/-/superagent-6.1.0.tgz",
"integrity": "sha512-OUDHEssirmplo3F+1HWKUrUjvnQuA+nZI6i/JJBdXb5eq9IyEQwPyPpqND+SSsxf6TygpBEkUjISVRN4/VOpeg==",
"deprecated": "Please upgrade to superagent v10.2.2+, see release notes at https://github.com/forwardemail/superagent/releases/tag/v10.2.2 - maintenance is supported by Forward Email @ https://forwardemail.net",
"license": "MIT",
"dependencies": {
"component-emitter": "^1.3.0",
"cookiejar": "^2.1.2",
"debug": "^4.1.1",
"fast-safe-stringify": "^2.0.7",
"form-data": "^3.0.0",
"formidable": "^1.2.2",
"methods": "^1.1.2",
"mime": "^2.4.6",
"qs": "^6.9.4",
"readable-stream": "^3.6.0",
"semver": "^7.3.2"
},
"engines": {
"node": ">= 7.0.0"
}
},
"node_modules/tar": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
@ -1206,6 +1769,12 @@
"node": ">=10"
}
},
"node_modules/tiny-typed-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz",
"integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==",
"license": "MIT"
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",

85
bot/node_modules/@distube/soundcloud/README.md generated vendored Normal file
View File

@ -0,0 +1,85 @@
<div align="center">
<p>
<a href="https://nodei.co/npm/@distube/soundcloud"><img src="https://nodei.co/npm/@distube/soundcloud.png?downloads=true&downloadRank=true&stars=true"></a>
</p>
<p>
<img alt="npm peer dependency version" src="https://img.shields.io/npm/dependency-version/@distube/soundcloud/peer/distube?style=flat-square">
<img alt="npm" src="https://img.shields.io/npm/dt/@distube/soundcloud?logo=npm&style=flat-square">
<img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/distubejs/extractor-plugins?logo=github&logoColor=white&style=flat-square">
<a href="https://discord.gg/feaDd9h"><img alt="Discord" src="https://img.shields.io/discord/732254550689316914?logo=discord&logoColor=white&style=flat-square"></a>
</p>
<p>
<a href='https://ko-fi.com/skick' target='_blank'><img height='48' src='https://storage.ko-fi.com/cdn/kofi3.png' alt='Buy Me a Coffee at ko-fi.com' /></a>
</p>
</div>
# @distube/soundcloud
A DisTube extractor plugin for supporting SoundCloud.
## Feature
- Using SoundCloud API
- Support SoundCloud tracks, albums and playlists
- Search tracks/playlists on SoundCloud
- Play tracks directly from SoundCloud
## Installation
```sh
npm install @distube/soundcloud@latest
```
## Usage
### Plugin
```ts
import { Client } from "discord.js";
import { DisTube } from "distube";
import { SoundCloudPlugin } from "@distube/soundcloud";
const client = new Client();
const distube = new DisTube(client, {
plugins: [new SoundCloudPlugin()],
});
```
### Search
```ts
const scPlugin = new SoundCloudPlugin();
scPlugin.search("A SoundCloud Playlist", "playlist", 3);
```
## Documentation
### new SoundCloudPlugin([SoundCloudPluginOptions])
- `SoundCloudPluginOptions.clientId` [string] _(optional)_: Your account's client id.
- `SoundCloudPluginOptions.oauthToken` [string] _(optional)_: Your account's oauth token. Used to fetch more data with SoundCloud Go+ account.
- How to get `clientId` and `oauthToken`? [See here](https://github.com/Tenpi/soundcloud.ts#getting-started)
#### Example
```js
new SoundCloudPlugin({
clientId: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
oauthToken: "0-000000-000000000-xxxxxxxxxxxxxx",
});
```
### SoundCloudPlugin#search(query, [type], [limit])
Searches for the given query on SoundCloud.
- Parameters
- `query` [string] Search query.
- `type` [string]: Type of results (`track` or `playlist`). Default is `track`.
- `limit` [integer]: Limit the results. Default is `10`.
- Returns a `Promise<Song[]|Playlist[]>`
- Returns a `Promise<Song[]>` if `type` parameter is `track`
- Returns a `Promise<Playlist[]>` if `type` parameter is `playlist`

31
bot/node_modules/@distube/soundcloud/dist/index.d.mts generated vendored Normal file
View File

@ -0,0 +1,31 @@
import { Soundcloud, SoundcloudTrack, SoundcloudPlaylist } from 'soundcloud.ts';
import { ExtractorPlugin, ResolveOptions, Song, Playlist } from 'distube';
declare enum SearchType {
Track = "track",
Playlist = "playlist"
}
interface SoundCloudPluginOptions {
clientId?: string;
oauthToken?: string;
}
declare class SoundCloudPlugin extends ExtractorPlugin {
soundcloud: Soundcloud;
constructor(options?: SoundCloudPluginOptions);
search<T>(query: string, type?: SearchType.Track, limit?: number, options?: ResolveOptions<T>): Promise<Song<T>[]>;
search<T>(query: string, type: SearchType.Playlist, limit?: number, options?: ResolveOptions<T>): Promise<Playlist<T>[]>;
search<T>(query: string, type?: SearchType, limit?: number, options?: ResolveOptions<T>): Promise<Song<T>[] | Playlist<T>[]>;
validate(url: string): boolean;
resolve<T>(url: string, options: ResolveOptions<T>): Promise<SoundCloudPlaylist<T> | SoundCloudSong<T>>;
getRelatedSongs(song: SoundCloudSong<undefined>): Promise<SoundCloudSong<unknown>[]>;
getStreamURL<T>(song: SoundCloudSong<T>): Promise<string>;
searchSong<T>(query: string, options: ResolveOptions<T>): Promise<Song<T>>;
}
declare class SoundCloudSong<T> extends Song<T> {
constructor(plugin: SoundCloudPlugin, info: SoundcloudTrack, options?: ResolveOptions<T>);
}
declare class SoundCloudPlaylist<T> extends Playlist<T> {
constructor(plugin: SoundCloudPlugin, info: SoundcloudPlaylist, options?: ResolveOptions<T>);
}
export { SearchType, SoundCloudPlugin, type SoundCloudPluginOptions, SoundCloudPlugin as default };

31
bot/node_modules/@distube/soundcloud/dist/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,31 @@
import { Soundcloud, SoundcloudTrack, SoundcloudPlaylist } from 'soundcloud.ts';
import { ExtractorPlugin, ResolveOptions, Song, Playlist } from 'distube';
declare enum SearchType {
Track = "track",
Playlist = "playlist"
}
interface SoundCloudPluginOptions {
clientId?: string;
oauthToken?: string;
}
declare class SoundCloudPlugin extends ExtractorPlugin {
soundcloud: Soundcloud;
constructor(options?: SoundCloudPluginOptions);
search<T>(query: string, type?: SearchType.Track, limit?: number, options?: ResolveOptions<T>): Promise<Song<T>[]>;
search<T>(query: string, type: SearchType.Playlist, limit?: number, options?: ResolveOptions<T>): Promise<Playlist<T>[]>;
search<T>(query: string, type?: SearchType, limit?: number, options?: ResolveOptions<T>): Promise<Song<T>[] | Playlist<T>[]>;
validate(url: string): boolean;
resolve<T>(url: string, options: ResolveOptions<T>): Promise<SoundCloudPlaylist<T> | SoundCloudSong<T>>;
getRelatedSongs(song: SoundCloudSong<undefined>): Promise<SoundCloudSong<unknown>[]>;
getStreamURL<T>(song: SoundCloudSong<T>): Promise<string>;
searchSong<T>(query: string, options: ResolveOptions<T>): Promise<Song<T>>;
}
declare class SoundCloudSong<T> extends Song<T> {
constructor(plugin: SoundCloudPlugin, info: SoundcloudTrack, options?: ResolveOptions<T>);
}
declare class SoundCloudPlaylist<T> extends Playlist<T> {
constructor(plugin: SoundCloudPlugin, info: SoundcloudPlaylist, options?: ResolveOptions<T>);
}
export { SearchType, SoundCloudPlugin, type SoundCloudPluginOptions, SoundCloudPlugin as default };

190
bot/node_modules/@distube/soundcloud/dist/index.js generated vendored Normal file
View File

@ -0,0 +1,190 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var src_exports = {};
__export(src_exports, {
SearchType: () => SearchType,
SoundCloudPlugin: () => SoundCloudPlugin,
default: () => src_default
});
module.exports = __toCommonJS(src_exports);
var import_soundcloud = require("soundcloud.ts");
var import_distube = require("distube");
var isTruthy = /* @__PURE__ */ __name((x) => Boolean(x), "isTruthy");
var SearchType = /* @__PURE__ */ ((SearchType2) => {
SearchType2["Track"] = "track";
SearchType2["Playlist"] = "playlist";
return SearchType2;
})(SearchType || {});
var SoundCloudPlugin = class extends import_distube.ExtractorPlugin {
static {
__name(this, "SoundCloudPlugin");
}
soundcloud;
constructor(options = {}) {
super();
if (typeof options !== "object" || Array.isArray(options)) {
throw new import_distube.DisTubeError("INVALID_TYPE", ["object", "undefined"], options, "SoundCloudPluginOptions");
}
(0, import_distube.checkInvalidKey)(options, ["clientId", "oauthToken"], "SoundCloudPluginOptions");
if (options.clientId && typeof options.clientId !== "string") {
throw new import_distube.DisTubeError("INVALID_TYPE", "string", options.clientId, "clientId");
}
if (options.oauthToken && typeof options.oauthToken !== "string") {
throw new import_distube.DisTubeError("INVALID_TYPE", "string", options.oauthToken, "oauthToken");
}
this.soundcloud = new import_soundcloud.Soundcloud(options.clientId, options.oauthToken);
}
async search(query, type = "track" /* Track */, limit = 10, options = {}) {
if (typeof query !== "string") {
throw new import_distube.DisTubeError("INVALID_TYPE", "string", query, "query");
}
if (!Object.values(SearchType).includes(type)) {
throw new import_distube.DisTubeError("INVALID_TYPE", Object.values(SearchType), type, "type");
}
if (typeof limit !== "number" || limit < 1 || !Number.isInteger(limit)) {
throw new import_distube.DisTubeError("INVALID_TYPE", "natural number", limit, "limit");
}
if (typeof options !== "object" || Array.isArray(options)) {
throw new import_distube.DisTubeError("INVALID_TYPE", "object", options, "ResolveOptions");
}
await this.soundcloud.api.getClientId().catch(() => {
throw new import_distube.DisTubeError(
"SOUNDCLOUD_PLUGIN_NO_CLIENT_ID",
"Cannot find SoundCloud client id automatically. Please provide a client id in the constructor.\nGuide: https://github.com/distubejs/soundcloud#documentation"
);
});
switch (type) {
case "track" /* Track */: {
const data = await this.soundcloud.tracks.search({ q: query, limit });
if (!data?.collection?.length) {
throw new import_distube.DisTubeError("SOUNDCLOUD_PLUGIN_NO_RESULT", `Cannot find any "${query}" ${type} on SoundCloud!`);
}
return data.collection.map((t) => new SoundCloudSong(this, t, options));
}
case "playlist" /* Playlist */: {
const data = await this.soundcloud.playlists.search({ q: query, limit });
const playlists = data.collection;
return (await Promise.all(
playlists.map(async (p) => new SoundCloudPlaylist(this, await this.soundcloud.playlists.fetch(p), options))
)).filter(isTruthy);
}
default:
throw new import_distube.DisTubeError("SOUNDCLOUD_PLUGIN_UNSUPPORTED_TYPE", `${type} search is not supported!`);
}
}
validate(url) {
return /^https?:\/\/(?:(?:www|m)\.)?soundcloud\.com\/(.*)$/.test(url);
}
async resolve(url, options) {
await this.soundcloud.api.getClientId().catch(() => {
throw new import_distube.DisTubeError(
"SOUNDCLOUD_PLUGIN_NO_CLIENT_ID",
"Cannot find SoundCloud client id automatically. Please provide a client id in the constructor.\nGuide: https://github.com/distubejs/soundcloud#documentation"
);
});
const opt = { ...options, source: "soundcloud" };
url = url.replace(/:\/\/(m|www)\./g, "://");
const data = await this.soundcloud.resolve.get(url, true).catch((e) => {
throw new import_distube.DisTubeError("SOUNDCLOUD_PLUGIN_RESOLVE_ERROR", e.message);
});
if (!data || !["track", "playlist"].includes(data.kind)) {
throw new import_distube.DisTubeError("SOUNDCLOUD_PLUGIN_NOT_SUPPORTED", "Only public tracks and playlists are supported.");
}
return data.kind === "playlist" ? new SoundCloudPlaylist(this, await this.soundcloud.playlists.fetch(data), opt) : new SoundCloudSong(this, data, opt);
}
async getRelatedSongs(song) {
if (!song.url) {
throw new import_distube.DisTubeError("SOUNDCLOUD_PLUGIN_INVALID_SONG", "Cannot get related songs from invalid song.");
}
const related = await this.soundcloud.tracks.related(song.url, 10);
return related.filter((t) => t.title).map((t) => new SoundCloudSong(this, t));
}
async getStreamURL(song) {
if (!song.url) {
throw new import_distube.DisTubeError("SOUNDCLOUD_PLUGIN_INVALID_SONG", "Cannot get stream url from invalid song.");
}
const stream = await this.soundcloud.util.streamLink(song.url);
if (!stream) {
throw new import_distube.DisTubeError(
"SOUNDCLOUD_PLUGIN_RATE_LIMITED",
"Reached SoundCloud rate limits\nSee more: https://developers.soundcloud.com/docs/api/rate-limits#play-requests"
);
}
return stream;
}
async searchSong(query, options) {
const songs = await this.search(query, "track" /* Track */, 1, options);
return songs[0];
}
};
var SoundCloudSong = class extends import_distube.Song {
static {
__name(this, "SoundCloudSong");
}
constructor(plugin, info, options = {}) {
super(
{
plugin,
source: "soundcloud",
playFromSource: true,
id: info.id.toString(),
name: info.title,
url: info.permalink_url,
thumbnail: info.artwork_url,
duration: info.duration / 1e3,
views: info.playback_count,
uploader: {
name: info.user?.username,
url: info.user?.permalink_url
},
likes: info.likes_count,
reposts: info.reposts_count
},
options
);
}
};
var SoundCloudPlaylist = class extends import_distube.Playlist {
static {
__name(this, "SoundCloudPlaylist");
}
constructor(plugin, info, options = {}) {
super(
{
source: "soundcloud",
id: info.id.toString(),
name: info.title,
url: info.permalink_url,
thumbnail: info.artwork_url ?? void 0,
songs: info.tracks.map((s) => new SoundCloudSong(plugin, s, options))
},
options
);
}
};
var src_default = SoundCloudPlugin;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
SearchType,
SoundCloudPlugin
});
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

166
bot/node_modules/@distube/soundcloud/dist/index.mjs generated vendored Normal file
View File

@ -0,0 +1,166 @@
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
// src/index.ts
import { Soundcloud } from "soundcloud.ts";
import { DisTubeError, ExtractorPlugin, Playlist, Song, checkInvalidKey } from "distube";
var isTruthy = /* @__PURE__ */ __name((x) => Boolean(x), "isTruthy");
var SearchType = /* @__PURE__ */ ((SearchType2) => {
SearchType2["Track"] = "track";
SearchType2["Playlist"] = "playlist";
return SearchType2;
})(SearchType || {});
var SoundCloudPlugin = class extends ExtractorPlugin {
static {
__name(this, "SoundCloudPlugin");
}
soundcloud;
constructor(options = {}) {
super();
if (typeof options !== "object" || Array.isArray(options)) {
throw new DisTubeError("INVALID_TYPE", ["object", "undefined"], options, "SoundCloudPluginOptions");
}
checkInvalidKey(options, ["clientId", "oauthToken"], "SoundCloudPluginOptions");
if (options.clientId && typeof options.clientId !== "string") {
throw new DisTubeError("INVALID_TYPE", "string", options.clientId, "clientId");
}
if (options.oauthToken && typeof options.oauthToken !== "string") {
throw new DisTubeError("INVALID_TYPE", "string", options.oauthToken, "oauthToken");
}
this.soundcloud = new Soundcloud(options.clientId, options.oauthToken);
}
async search(query, type = "track" /* Track */, limit = 10, options = {}) {
if (typeof query !== "string") {
throw new DisTubeError("INVALID_TYPE", "string", query, "query");
}
if (!Object.values(SearchType).includes(type)) {
throw new DisTubeError("INVALID_TYPE", Object.values(SearchType), type, "type");
}
if (typeof limit !== "number" || limit < 1 || !Number.isInteger(limit)) {
throw new DisTubeError("INVALID_TYPE", "natural number", limit, "limit");
}
if (typeof options !== "object" || Array.isArray(options)) {
throw new DisTubeError("INVALID_TYPE", "object", options, "ResolveOptions");
}
await this.soundcloud.api.getClientId().catch(() => {
throw new DisTubeError(
"SOUNDCLOUD_PLUGIN_NO_CLIENT_ID",
"Cannot find SoundCloud client id automatically. Please provide a client id in the constructor.\nGuide: https://github.com/distubejs/soundcloud#documentation"
);
});
switch (type) {
case "track" /* Track */: {
const data = await this.soundcloud.tracks.search({ q: query, limit });
if (!data?.collection?.length) {
throw new DisTubeError("SOUNDCLOUD_PLUGIN_NO_RESULT", `Cannot find any "${query}" ${type} on SoundCloud!`);
}
return data.collection.map((t) => new SoundCloudSong(this, t, options));
}
case "playlist" /* Playlist */: {
const data = await this.soundcloud.playlists.search({ q: query, limit });
const playlists = data.collection;
return (await Promise.all(
playlists.map(async (p) => new SoundCloudPlaylist(this, await this.soundcloud.playlists.fetch(p), options))
)).filter(isTruthy);
}
default:
throw new DisTubeError("SOUNDCLOUD_PLUGIN_UNSUPPORTED_TYPE", `${type} search is not supported!`);
}
}
validate(url) {
return /^https?:\/\/(?:(?:www|m)\.)?soundcloud\.com\/(.*)$/.test(url);
}
async resolve(url, options) {
await this.soundcloud.api.getClientId().catch(() => {
throw new DisTubeError(
"SOUNDCLOUD_PLUGIN_NO_CLIENT_ID",
"Cannot find SoundCloud client id automatically. Please provide a client id in the constructor.\nGuide: https://github.com/distubejs/soundcloud#documentation"
);
});
const opt = { ...options, source: "soundcloud" };
url = url.replace(/:\/\/(m|www)\./g, "://");
const data = await this.soundcloud.resolve.get(url, true).catch((e) => {
throw new DisTubeError("SOUNDCLOUD_PLUGIN_RESOLVE_ERROR", e.message);
});
if (!data || !["track", "playlist"].includes(data.kind)) {
throw new DisTubeError("SOUNDCLOUD_PLUGIN_NOT_SUPPORTED", "Only public tracks and playlists are supported.");
}
return data.kind === "playlist" ? new SoundCloudPlaylist(this, await this.soundcloud.playlists.fetch(data), opt) : new SoundCloudSong(this, data, opt);
}
async getRelatedSongs(song) {
if (!song.url) {
throw new DisTubeError("SOUNDCLOUD_PLUGIN_INVALID_SONG", "Cannot get related songs from invalid song.");
}
const related = await this.soundcloud.tracks.related(song.url, 10);
return related.filter((t) => t.title).map((t) => new SoundCloudSong(this, t));
}
async getStreamURL(song) {
if (!song.url) {
throw new DisTubeError("SOUNDCLOUD_PLUGIN_INVALID_SONG", "Cannot get stream url from invalid song.");
}
const stream = await this.soundcloud.util.streamLink(song.url);
if (!stream) {
throw new DisTubeError(
"SOUNDCLOUD_PLUGIN_RATE_LIMITED",
"Reached SoundCloud rate limits\nSee more: https://developers.soundcloud.com/docs/api/rate-limits#play-requests"
);
}
return stream;
}
async searchSong(query, options) {
const songs = await this.search(query, "track" /* Track */, 1, options);
return songs[0];
}
};
var SoundCloudSong = class extends Song {
static {
__name(this, "SoundCloudSong");
}
constructor(plugin, info, options = {}) {
super(
{
plugin,
source: "soundcloud",
playFromSource: true,
id: info.id.toString(),
name: info.title,
url: info.permalink_url,
thumbnail: info.artwork_url,
duration: info.duration / 1e3,
views: info.playback_count,
uploader: {
name: info.user?.username,
url: info.user?.permalink_url
},
likes: info.likes_count,
reposts: info.reposts_count
},
options
);
}
};
var SoundCloudPlaylist = class extends Playlist {
static {
__name(this, "SoundCloudPlaylist");
}
constructor(plugin, info, options = {}) {
super(
{
source: "soundcloud",
id: info.id.toString(),
name: info.title,
url: info.permalink_url,
thumbnail: info.artwork_url ?? void 0,
songs: info.tracks.map((s) => new SoundCloudSong(plugin, s, options))
},
options
);
}
};
var src_default = SoundCloudPlugin;
export {
SearchType,
SoundCloudPlugin,
src_default as default
};
//# sourceMappingURL=index.mjs.map

File diff suppressed because one or more lines are too long

76
bot/node_modules/@distube/soundcloud/package.json generated vendored Normal file
View File

@ -0,0 +1,76 @@
{
"name": "@distube/soundcloud",
"version": "2.0.4",
"author": "Skick (https://github.com/skick1234)",
"repository": {
"type": "git",
"url": "git+https://github.com/distubejs/extractor-plugins.git"
},
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"require": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
}
}
},
"devDependencies": {
"@types/node": "^22.8.1",
"discord.js": "^14.16.3",
"distube": "^5.0.2",
"eslint": "^8.57.0",
"eslint-config-distube": "^1.7.1",
"prettier": "^3.3.3",
"tslib": "^2.8.0",
"tsup": "^8.3.5",
"typescript": "^5.6.3"
},
"bugs": {
"url": "https://github.com/distubejs/extractor-plugins/issues"
},
"description": "A DisTube extractor plugin for supporting SoundCloud.",
"directories": {
"lib": "src"
},
"files": [
"dist"
],
"funding": "https://github.com/skick1234/DisTube?sponsor",
"homepage": "https://github.com/distubejs/extractor-plugins/tree/main/packages/soundcloud#readme",
"keywords": [
"distube",
"plugin",
"discord",
"music"
],
"license": "MIT",
"nano-staged": {
"*.ts": [
"prettier --write",
"eslint"
],
"*.{json,yml,yaml}": [
"prettier --write"
]
},
"peerDependencies": {
"distube": "5"
},
"typings": "./dist/index.d.ts",
"dependencies": {
"soundcloud.ts": "^0.6.2"
},
"scripts": {
"format": "prettier --write \"**/*.{js,ts,json,yml,yaml,md}\"",
"lint": "eslint .",
"build": "tsup",
"type": "tsc --noEmit"
}
}

54
bot/node_modules/@distube/spotify/README.md generated vendored Normal file
View File

@ -0,0 +1,54 @@
<div align="center">
<p>
<a href="https://nodei.co/npm/@distube/spotify"><img src="https://nodei.co/npm/@distube/spotify.png?downloads=true&downloadRank=true&stars=true"></a>
</p>
<p>
<a href="https://nodei.co/npm/@distube/spotify"><img alt="npm peer dependency version" src="https://img.shields.io/npm/dependency-version/@distube/spotify/peer/distube?style=flat-square"></a>
<a href="https://nodei.co/npm/@distube/spotify"><img alt="npm" src="https://img.shields.io/npm/dt/@distube/spotify?logo=npm&style=flat-square"></a>
<img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/distubejs/extractor-plugins?logo=github&logoColor=white&style=flat-square">
<a href="https://discord.gg/feaDd9h"><img alt="Discord" src="https://img.shields.io/discord/732254550689316914?logo=discord&logoColor=white&style=flat-square"></a>
</p>
<p>
<a href='https://ko-fi.com/skick' target='_blank'><img height='48' src='https://storage.ko-fi.com/cdn/kofi3.png' alt='Buy Me a Coffee at ko-fi.com' /></a>
</p>
</div>
# @distube/spotify
A DisTube info extractor plugin for supporting Spotify.
[_What is an info extractor plugin?_](https://github.com/skick1234/DisTube/wiki/Projects-Hub#plugins)
## Usage
```js
const Discord = require("discord.js");
const client = new Discord.Client();
const { DisTube } = require("distube");
const { SpotifyPlugin } = require("@distube/spotify");
const distube = new DisTube(client, {
plugins: [new SpotifyPlugin()],
});
```
## Documentation
### SpotifyPlugin([SpotifyPluginOptions])
- `SpotifyPluginOptions.api`: (Optional) Spotify API credentials.
- `SpotifyPluginOptions.api.clientId`: Client ID of your Spotify application (Optional - Used when the plugin cannot get the credentials automatically)
- `SpotifyPluginOptions.api.clientSecret`: Client Secret of your Spotify application (Optional - Used when the plugin cannot get the credentials automatically)
- `SpotifyPluginOptions.api.topTracksCountry`: Country code of the top artist tracks (ISO 3166-1 alpha-2 country code). Default is `US`.
#### Example
```js
new SpotifyPlugin({
api: {
clientId: "SpotifyAppClientID",
clientSecret: "SpotifyAppClientSecret",
topTracksCountry: "VN",
},
});
```

66
bot/node_modules/@distube/spotify/dist/index.d.mts generated vendored Normal file
View File

@ -0,0 +1,66 @@
import * as spotify_uri from 'spotify-uri';
import { InfoExtractorPlugin, ResolveOptions, Song, Playlist as Playlist$1 } from 'distube';
declare const SUPPORTED_TYPES: readonly ["album", "playlist", "track", "artist"];
type Track = {
type: "track";
id: string;
name: string;
artists: {
name: string;
}[];
thumbnail?: string;
duration: number;
};
type DataList = {
type: string;
name: string;
thumbnail?: string;
url: string;
tracks: Track[];
};
type Album = DataList & {
type: "album";
};
type Playlist = DataList & {
type: "playlist";
};
type Artist = DataList & {
type: "artist";
};
type TrackList = Album | Playlist | Artist;
type Data = Track | TrackList;
declare class API {
#private;
private _hasCredentials;
private _expirationTime;
private _tokenAvailable;
topTracksCountry: string;
constructor(clientId?: string, clientSecret?: string, topTracksCountry?: string);
isSupportedTypes(type: string): type is (typeof SUPPORTED_TYPES)[number];
refreshToken(): Promise<void>;
parseUrl(url: string): spotify_uri.ParsedSpotifyUri;
getData(url: `${string}/track/${string}`): Promise<Track>;
getData(url: `${string}/album/${string}`): Promise<Album>;
getData(url: `${string}/playlist/${string}`): Promise<Playlist>;
getData(url: `${string}/artist/${string}`): Promise<Artist>;
getData(url: string): Promise<Data>;
}
type SpotifyPluginOptions = {
api?: {
clientId?: string;
clientSecret?: string;
topTracksCountry?: string;
};
};
declare class SpotifyPlugin extends InfoExtractorPlugin {
api: API;
constructor(options?: SpotifyPluginOptions);
validate(url: string): boolean;
resolve<T>(url: string, options: ResolveOptions<T>): Promise<Song<T> | Playlist$1<T>>;
createSearchQuery<T>(song: Song<T>): string;
getRelatedSongs(): never[];
}
export { SpotifyPlugin, type SpotifyPluginOptions, SpotifyPlugin as default };

66
bot/node_modules/@distube/spotify/dist/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,66 @@
import * as spotify_uri from 'spotify-uri';
import { InfoExtractorPlugin, ResolveOptions, Song, Playlist as Playlist$1 } from 'distube';
declare const SUPPORTED_TYPES: readonly ["album", "playlist", "track", "artist"];
type Track = {
type: "track";
id: string;
name: string;
artists: {
name: string;
}[];
thumbnail?: string;
duration: number;
};
type DataList = {
type: string;
name: string;
thumbnail?: string;
url: string;
tracks: Track[];
};
type Album = DataList & {
type: "album";
};
type Playlist = DataList & {
type: "playlist";
};
type Artist = DataList & {
type: "artist";
};
type TrackList = Album | Playlist | Artist;
type Data = Track | TrackList;
declare class API {
#private;
private _hasCredentials;
private _expirationTime;
private _tokenAvailable;
topTracksCountry: string;
constructor(clientId?: string, clientSecret?: string, topTracksCountry?: string);
isSupportedTypes(type: string): type is (typeof SUPPORTED_TYPES)[number];
refreshToken(): Promise<void>;
parseUrl(url: string): spotify_uri.ParsedSpotifyUri;
getData(url: `${string}/track/${string}`): Promise<Track>;
getData(url: `${string}/album/${string}`): Promise<Album>;
getData(url: `${string}/playlist/${string}`): Promise<Playlist>;
getData(url: `${string}/artist/${string}`): Promise<Artist>;
getData(url: string): Promise<Data>;
}
type SpotifyPluginOptions = {
api?: {
clientId?: string;
clientSecret?: string;
topTracksCountry?: string;
};
};
declare class SpotifyPlugin extends InfoExtractorPlugin {
api: API;
constructor(options?: SpotifyPluginOptions);
validate(url: string): boolean;
resolve<T>(url: string, options: ResolveOptions<T>): Promise<Song<T> | Playlist$1<T>>;
createSearchQuery<T>(song: Song<T>): string;
getRelatedSongs(): never[];
}
export { SpotifyPlugin, type SpotifyPluginOptions, SpotifyPlugin as default };

323
bot/node_modules/@distube/spotify/dist/index.js generated vendored Normal file
View File

@ -0,0 +1,323 @@
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var src_exports = {};
__export(src_exports, {
SpotifyPlugin: () => SpotifyPlugin,
default: () => src_default
});
module.exports = __toCommonJS(src_exports);
// src/API.ts
var import_spotify_url_info = __toESM(require("spotify-url-info"));
var import_spotify_web_api_node = __toESM(require("spotify-web-api-node"));
var import_undici = require("undici");
var import_distube = require("distube");
var import_spotify_uri = require("spotify-uri");
var SUPPORTED_TYPES = ["album", "playlist", "track", "artist"];
var WEB_API = new import_spotify_web_api_node.default();
var INFO = (0, import_spotify_url_info.default)(import_undici.fetch);
var firstWarning1 = true;
var firstWarning2 = true;
var apiError = /* @__PURE__ */ __name((e) => new import_distube.DisTubeError(
"SPOTIFY_API_ERROR",
`The URL is private or unavailable.${e?.body?.error?.message ? `
Details: ${e.body.error.message}` : ""}${e?.statusCode ? `
Status code: ${e.statusCode}.` : ""}`
), "apiError");
var APITrack = class {
static {
__name(this, "APITrack");
}
type;
id;
name;
artists;
thumbnail;
duration;
constructor(info) {
this.type = "track";
this.id = info.id;
this.name = info.name;
this.artists = info.artists;
this.thumbnail = info.album?.images?.[0]?.url;
this.duration = info.duration_ms;
}
};
var mergeAlbumTrack = /* @__PURE__ */ __name((album, track) => {
track.album = album;
return track;
}, "mergeAlbumTrack");
var API = class {
static {
__name(this, "API");
}
_hasCredentials = false;
_expirationTime = 0;
_tokenAvailable = false;
topTracksCountry = "US";
constructor(clientId, clientSecret, topTracksCountry) {
if (clientId && clientSecret) {
this._hasCredentials = true;
WEB_API.setClientId(clientId);
WEB_API.setClientSecret(clientSecret);
}
if (topTracksCountry) {
if (!/^[A-Z]{2}$/.test(topTracksCountry)) throw new Error("Invalid region code");
this.topTracksCountry = topTracksCountry;
}
}
isSupportedTypes(type) {
return SUPPORTED_TYPES.includes(type);
}
async refreshToken() {
if (Date.now() < this._expirationTime) return;
if (this._hasCredentials) {
try {
const { body } = await WEB_API.clientCredentialsGrant();
WEB_API.setAccessToken(body.access_token);
this._expirationTime = Date.now() + body.expires_in * 1e3 - 5e3;
} catch (e) {
if (firstWarning1) {
firstWarning1 = false;
this._hasCredentials = false;
console.warn(e);
console.warn("[SPOTIFY_PLUGIN_API] Cannot get token from your credentials. Try scraping token instead.");
}
}
}
if (!this._hasCredentials) {
const response = await (0, import_undici.fetch)("https://open.spotify.com/");
const body = await response.text();
const token = body.match(/"accessToken":"(.+?)"/)?.[1];
if (!token) {
this._tokenAvailable = false;
if (firstWarning2) {
firstWarning2 = false;
console.warn(
"[SPOTIFY_PLUGIN_API] Cannot get token from scraping. Cannot fetch more than 100 tracks from a playlist or album."
);
}
return;
}
WEB_API.setAccessToken(token);
const expiration = body.match(/"accessTokenExpirationTimestampMs":(\d+)/)?.[1];
if (expiration) this._expirationTime = Number(expiration) - 5e3;
}
this._tokenAvailable = true;
}
parseUrl(url) {
return (0, import_spotify_uri.parse)(url);
}
async getData(url) {
const { type, id } = this.parseUrl(url);
if (!id) throw new import_distube.DisTubeError("SPOTIFY_API_INVALID_URL", "Invalid URL");
if (!this.isSupportedTypes(type)) throw new import_distube.DisTubeError("SPOTIFY_API_UNSUPPORTED_TYPE", "Unsupported URL type");
await this.refreshToken();
if (type === "track") {
if (!this._tokenAvailable) {
return INFO.getData(url);
}
try {
const { body } = await WEB_API.getTrack(id);
return new APITrack(body);
} catch (e) {
throw apiError(e);
}
}
if (!this._tokenAvailable) {
const data = await INFO.getData(url);
const thumbnail = data.coverArt?.sources?.[0]?.url;
return {
type,
name: data.title,
thumbnail,
url,
tracks: data.trackList.map((i) => ({
type: "track",
id: this.parseUrl(i.uri).id,
name: i.title,
artists: [{ name: i.subtitle }],
duration: i.duration,
thumbnail
}))
};
}
try {
const { body } = await WEB_API[type === "album" ? "getAlbum" : type === "playlist" ? "getPlaylist" : "getArtist"](id);
return {
type,
name: body.name,
thumbnail: body.images?.[0]?.url,
url: body.external_urls?.spotify,
tracks: (await this.#getTracks(body)).filter((t) => t?.type === "track").map((t) => new APITrack(t))
};
} catch (e) {
throw apiError(e);
}
}
async #getTracks(data) {
switch (data.type) {
case "artist": {
return (await WEB_API.getArtistTopTracks(data.id, this.topTracksCountry)).body.tracks;
}
case "album": {
const tracks = await this.#getPaginatedItems(data);
return tracks.map((t) => mergeAlbumTrack(data, t));
}
case "playlist": {
return (await this.#getPaginatedItems(data)).map((i) => i.track).filter(import_distube.isTruthy);
}
}
}
async #getPaginatedItems(data) {
const items = data.tracks.items;
const isPlaylist = data.type === "playlist";
const limit = isPlaylist ? 100 : 50;
const method = isPlaylist ? "getPlaylistTracks" : "getAlbumTracks";
while (data.tracks.next) {
await this.refreshToken();
data.tracks = (await WEB_API[method](data.id, { offset: data.tracks.offset + data.tracks.limit, limit })).body;
items.push(...data.tracks.items);
}
return items;
}
};
// src/index.ts
var import_distube2 = require("distube");
var SpotifyPlugin = class extends import_distube2.InfoExtractorPlugin {
static {
__name(this, "SpotifyPlugin");
}
api;
constructor(options = {}) {
super();
if (typeof options !== "object" || Array.isArray(options)) {
throw new import_distube2.DisTubeError("INVALID_TYPE", ["object", "undefined"], options, "SpotifyPluginOptions");
}
(0, import_distube2.checkInvalidKey)(options, ["api"], "SpotifyPluginOptions");
if (options.api !== void 0 && (typeof options.api !== "object" || Array.isArray(options.api))) {
throw new import_distube2.DisTubeError("INVALID_TYPE", ["object", "undefined"], options.api, "api");
} else if (options.api) {
if (options.api.clientId && typeof options.api.clientId !== "string") {
throw new import_distube2.DisTubeError("INVALID_TYPE", "string", options.api.clientId, "SpotifyPluginOptions.api.clientId");
}
if (options.api.clientSecret && typeof options.api.clientSecret !== "string") {
throw new import_distube2.DisTubeError(
"INVALID_TYPE",
"string",
options.api.clientSecret,
"SpotifyPluginOptions.api.clientSecret"
);
}
if (options.api.topTracksCountry && typeof options.api.topTracksCountry !== "string") {
throw new import_distube2.DisTubeError(
"INVALID_TYPE",
"string",
options.api.topTracksCountry,
"SpotifyPluginOptions.api.topTracksCountry"
);
}
}
this.api = new API(options.api?.clientId, options.api?.clientSecret, options.api?.topTracksCountry);
}
validate(url) {
if (typeof url !== "string" || !url.includes("spotify")) return false;
try {
const parsedURL = this.api.parseUrl(url);
if (!parsedURL.type || !this.api.isSupportedTypes(parsedURL.type)) return false;
return true;
} catch (error) {
return false;
}
}
async resolve(url, options) {
const data = await this.api.getData(url);
if (data.type === "track") {
return new import_distube2.Song(
{
plugin: this,
source: "spotify",
playFromSource: false,
name: data.name,
id: data.id,
url: `https://open.spotify.com/track/${data.id}`,
thumbnail: data.thumbnail,
uploader: {
name: data.artists.map((a) => a.name).join(", ")
},
duration: data.duration / 1e3
},
options
);
}
return new import_distube2.Playlist(
{
source: "spotify",
name: data.name,
url: data.url,
thumbnail: data.thumbnail,
songs: data.tracks.map(
(t) => new import_distube2.Song(
{
plugin: this,
source: "spotify",
id: t.id,
playFromSource: false,
name: t.name,
thumbnail: t.thumbnail,
uploader: {
name: t.artists.map((a) => a.name).join(", ")
},
url: `https://open.spotify.com/track/${t.id}`,
duration: t.duration / 1e3
},
options
)
)
},
options
);
}
createSearchQuery(song) {
return `${song.name} ${song.uploader.name}`;
}
getRelatedSongs() {
return [];
}
};
var src_default = SpotifyPlugin;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
SpotifyPlugin
});
//# sourceMappingURL=index.js.map

1
bot/node_modules/@distube/spotify/dist/index.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

288
bot/node_modules/@distube/spotify/dist/index.mjs generated vendored Normal file
View File

@ -0,0 +1,288 @@
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
// src/API.ts
import SpotifyInfo from "spotify-url-info";
import SpotifyWebApi from "spotify-web-api-node";
import { fetch } from "undici";
import { DisTubeError, isTruthy } from "distube";
import { parse as parseSpotifyUri } from "spotify-uri";
var SUPPORTED_TYPES = ["album", "playlist", "track", "artist"];
var WEB_API = new SpotifyWebApi();
var INFO = SpotifyInfo(fetch);
var firstWarning1 = true;
var firstWarning2 = true;
var apiError = /* @__PURE__ */ __name((e) => new DisTubeError(
"SPOTIFY_API_ERROR",
`The URL is private or unavailable.${e?.body?.error?.message ? `
Details: ${e.body.error.message}` : ""}${e?.statusCode ? `
Status code: ${e.statusCode}.` : ""}`
), "apiError");
var APITrack = class {
static {
__name(this, "APITrack");
}
type;
id;
name;
artists;
thumbnail;
duration;
constructor(info) {
this.type = "track";
this.id = info.id;
this.name = info.name;
this.artists = info.artists;
this.thumbnail = info.album?.images?.[0]?.url;
this.duration = info.duration_ms;
}
};
var mergeAlbumTrack = /* @__PURE__ */ __name((album, track) => {
track.album = album;
return track;
}, "mergeAlbumTrack");
var API = class {
static {
__name(this, "API");
}
_hasCredentials = false;
_expirationTime = 0;
_tokenAvailable = false;
topTracksCountry = "US";
constructor(clientId, clientSecret, topTracksCountry) {
if (clientId && clientSecret) {
this._hasCredentials = true;
WEB_API.setClientId(clientId);
WEB_API.setClientSecret(clientSecret);
}
if (topTracksCountry) {
if (!/^[A-Z]{2}$/.test(topTracksCountry)) throw new Error("Invalid region code");
this.topTracksCountry = topTracksCountry;
}
}
isSupportedTypes(type) {
return SUPPORTED_TYPES.includes(type);
}
async refreshToken() {
if (Date.now() < this._expirationTime) return;
if (this._hasCredentials) {
try {
const { body } = await WEB_API.clientCredentialsGrant();
WEB_API.setAccessToken(body.access_token);
this._expirationTime = Date.now() + body.expires_in * 1e3 - 5e3;
} catch (e) {
if (firstWarning1) {
firstWarning1 = false;
this._hasCredentials = false;
console.warn(e);
console.warn("[SPOTIFY_PLUGIN_API] Cannot get token from your credentials. Try scraping token instead.");
}
}
}
if (!this._hasCredentials) {
const response = await fetch("https://open.spotify.com/");
const body = await response.text();
const token = body.match(/"accessToken":"(.+?)"/)?.[1];
if (!token) {
this._tokenAvailable = false;
if (firstWarning2) {
firstWarning2 = false;
console.warn(
"[SPOTIFY_PLUGIN_API] Cannot get token from scraping. Cannot fetch more than 100 tracks from a playlist or album."
);
}
return;
}
WEB_API.setAccessToken(token);
const expiration = body.match(/"accessTokenExpirationTimestampMs":(\d+)/)?.[1];
if (expiration) this._expirationTime = Number(expiration) - 5e3;
}
this._tokenAvailable = true;
}
parseUrl(url) {
return parseSpotifyUri(url);
}
async getData(url) {
const { type, id } = this.parseUrl(url);
if (!id) throw new DisTubeError("SPOTIFY_API_INVALID_URL", "Invalid URL");
if (!this.isSupportedTypes(type)) throw new DisTubeError("SPOTIFY_API_UNSUPPORTED_TYPE", "Unsupported URL type");
await this.refreshToken();
if (type === "track") {
if (!this._tokenAvailable) {
return INFO.getData(url);
}
try {
const { body } = await WEB_API.getTrack(id);
return new APITrack(body);
} catch (e) {
throw apiError(e);
}
}
if (!this._tokenAvailable) {
const data = await INFO.getData(url);
const thumbnail = data.coverArt?.sources?.[0]?.url;
return {
type,
name: data.title,
thumbnail,
url,
tracks: data.trackList.map((i) => ({
type: "track",
id: this.parseUrl(i.uri).id,
name: i.title,
artists: [{ name: i.subtitle }],
duration: i.duration,
thumbnail
}))
};
}
try {
const { body } = await WEB_API[type === "album" ? "getAlbum" : type === "playlist" ? "getPlaylist" : "getArtist"](id);
return {
type,
name: body.name,
thumbnail: body.images?.[0]?.url,
url: body.external_urls?.spotify,
tracks: (await this.#getTracks(body)).filter((t) => t?.type === "track").map((t) => new APITrack(t))
};
} catch (e) {
throw apiError(e);
}
}
async #getTracks(data) {
switch (data.type) {
case "artist": {
return (await WEB_API.getArtistTopTracks(data.id, this.topTracksCountry)).body.tracks;
}
case "album": {
const tracks = await this.#getPaginatedItems(data);
return tracks.map((t) => mergeAlbumTrack(data, t));
}
case "playlist": {
return (await this.#getPaginatedItems(data)).map((i) => i.track).filter(isTruthy);
}
}
}
async #getPaginatedItems(data) {
const items = data.tracks.items;
const isPlaylist = data.type === "playlist";
const limit = isPlaylist ? 100 : 50;
const method = isPlaylist ? "getPlaylistTracks" : "getAlbumTracks";
while (data.tracks.next) {
await this.refreshToken();
data.tracks = (await WEB_API[method](data.id, { offset: data.tracks.offset + data.tracks.limit, limit })).body;
items.push(...data.tracks.items);
}
return items;
}
};
// src/index.ts
import { DisTubeError as DisTubeError2, InfoExtractorPlugin, Playlist, Song, checkInvalidKey } from "distube";
var SpotifyPlugin = class extends InfoExtractorPlugin {
static {
__name(this, "SpotifyPlugin");
}
api;
constructor(options = {}) {
super();
if (typeof options !== "object" || Array.isArray(options)) {
throw new DisTubeError2("INVALID_TYPE", ["object", "undefined"], options, "SpotifyPluginOptions");
}
checkInvalidKey(options, ["api"], "SpotifyPluginOptions");
if (options.api !== void 0 && (typeof options.api !== "object" || Array.isArray(options.api))) {
throw new DisTubeError2("INVALID_TYPE", ["object", "undefined"], options.api, "api");
} else if (options.api) {
if (options.api.clientId && typeof options.api.clientId !== "string") {
throw new DisTubeError2("INVALID_TYPE", "string", options.api.clientId, "SpotifyPluginOptions.api.clientId");
}
if (options.api.clientSecret && typeof options.api.clientSecret !== "string") {
throw new DisTubeError2(
"INVALID_TYPE",
"string",
options.api.clientSecret,
"SpotifyPluginOptions.api.clientSecret"
);
}
if (options.api.topTracksCountry && typeof options.api.topTracksCountry !== "string") {
throw new DisTubeError2(
"INVALID_TYPE",
"string",
options.api.topTracksCountry,
"SpotifyPluginOptions.api.topTracksCountry"
);
}
}
this.api = new API(options.api?.clientId, options.api?.clientSecret, options.api?.topTracksCountry);
}
validate(url) {
if (typeof url !== "string" || !url.includes("spotify")) return false;
try {
const parsedURL = this.api.parseUrl(url);
if (!parsedURL.type || !this.api.isSupportedTypes(parsedURL.type)) return false;
return true;
} catch (error) {
return false;
}
}
async resolve(url, options) {
const data = await this.api.getData(url);
if (data.type === "track") {
return new Song(
{
plugin: this,
source: "spotify",
playFromSource: false,
name: data.name,
id: data.id,
url: `https://open.spotify.com/track/${data.id}`,
thumbnail: data.thumbnail,
uploader: {
name: data.artists.map((a) => a.name).join(", ")
},
duration: data.duration / 1e3
},
options
);
}
return new Playlist(
{
source: "spotify",
name: data.name,
url: data.url,
thumbnail: data.thumbnail,
songs: data.tracks.map(
(t) => new Song(
{
plugin: this,
source: "spotify",
id: t.id,
playFromSource: false,
name: t.name,
thumbnail: t.thumbnail,
uploader: {
name: t.artists.map((a) => a.name).join(", ")
},
url: `https://open.spotify.com/track/${t.id}`,
duration: t.duration / 1e3
},
options
)
)
},
options
);
}
createSearchQuery(song) {
return `${song.name} ${song.uploader.name}`;
}
getRelatedSongs() {
return [];
}
};
var src_default = SpotifyPlugin;
export {
SpotifyPlugin,
src_default as default
};
//# sourceMappingURL=index.mjs.map

1
bot/node_modules/@distube/spotify/dist/index.mjs.map generated vendored Normal file

File diff suppressed because one or more lines are too long

67
bot/node_modules/@distube/spotify/package.json generated vendored Normal file
View File

@ -0,0 +1,67 @@
{
"name": "@distube/spotify",
"version": "2.0.2",
"author": "Skick (https://github.com/skick1234)",
"repository": {
"type": "git",
"url": "git+https://github.com/distubejs/extractor-plugins.git"
},
"main": "./dist/index.js",
"devDependencies": {
"@types/node": "^20.14.2",
"@types/spotify-web-api-node": "^5.0.11",
"discord.js": "^14.15.3",
"distube": "^5.0.2",
"eslint": "^8.57.0",
"eslint-config-distube": "^1.7.0",
"prettier": "^3.3.2",
"tslib": "^2.6.3",
"tsup": "^8.1.0",
"typescript": "^5.4.5"
},
"exports": "./dist/index.js",
"bugs": {
"url": "https://github.com/distubejs/extractor-plugins/issues"
},
"description": "A DisTube extractor plugin for supporting Spotify.",
"directories": {
"lib": "src"
},
"files": [
"dist"
],
"funding": "https://github.com/skick1234/DisTube?sponsor",
"homepage": "https://github.com/distubejs/extractor-plugins/tree/main/packages/soundcloud#readme",
"keywords": [
"distube",
"plugin",
"discord",
"music"
],
"license": "MIT",
"nano-staged": {
"*.ts": [
"prettier --write",
"eslint"
],
"*.{json,yml,yaml}": [
"prettier --write"
]
},
"peerDependencies": {
"distube": "5"
},
"typings": "./dist/index.d.ts",
"dependencies": {
"spotify-uri": "^4.1.0",
"spotify-url-info": "^3.2.15",
"spotify-web-api-node": "^5.0.2",
"undici": "^6.18.2"
},
"scripts": {
"format": "prettier --write \"**/*.{js,ts,json,yml,yaml,md}\"",
"lint": "eslint .",
"build": "tsup",
"type": "tsc --noEmit"
}
}

91
bot/node_modules/@distube/yt-dlp/README.md generated vendored Normal file
View File

@ -0,0 +1,91 @@
<div align="center">
<p>
<a href="https://nodei.co/npm/@distube/yt-dlp"><img src="https://nodei.co/npm/@distube/yt-dlp.png?downloads=true&downloadRank=true&stars=true"></a>
</p>
<p>
<img alt="npm peer dependency version" src="https://img.shields.io/npm/dependency-version/@distube/yt-dlp/peer/distube?style=flat-square">
<img alt="npm" src="https://img.shields.io/npm/dt/@distube/yt-dlp?logo=npm&style=flat-square">
<img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/distubejs/extractor-plugins?logo=github&logoColor=white&style=flat-square">
<a href="https://discord.gg/feaDd9h"><img alt="Discord" src="https://img.shields.io/discord/732254550689316914?logo=discord&logoColor=white&style=flat-square"></a>
</p>
<p>
<a href='https://ko-fi.com/skick' target='_blank'><img height='48' src='https://storage.ko-fi.com/cdn/kofi3.png' alt='Buy Me a Coffee at ko-fi.com' /></a>
</p>
</div>
# @distube/yt-dlp
A DisTube playable extractor plugin using [yt-dlp](https://github.com/yt-dlp/yt-dlp)
[_What is a playable extractor plugin?_](https://github.com/skick1234/DisTube/wiki/Projects-Hub#plugins)
# Feature
- Support [900+ sites](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md) using [yt-dlp](https://github.com/yt-dlp/yt-dlp)
# Requirement
- [python](https://www.python.org/)
# Installation
```sh
npm install @distube/yt-dlp@latest
```
# Usage
```ts
import { DisTube } from "distube";
import { YtDlpPlugin } from "@distube/yt-dlp";
const distube = new DisTube(client, {
plugins: [new YtDlpPlugin({ update: true })],
});
```
# Documentation
### new YtDlpPlugin([YtDlpPluginOptions])
Create a DisTube's `ExtractorPlugin` instance.
- `YtDlpPluginOptions.update` (`boolean`): Default is `true`. Update the yt-dlp binary when the plugin is initialized.
> YtDlpPlugin should be the last plugin in the `plugins` array.
## Environment Variables
- `YTDLP_DISABLE_DOWNLOAD`: Set it to disable download yt-dlp binary.
- `YTDLP_URL`: The URL of the yt-dlp binary to download.
- `YTDLP_DIR`: The directory to download the yt-dlp binary.
- `YTDLP_FILENAME`: The filename of the yt-dlp binary.
## Troubleshooting
### Failed to install (Status code: 403)
Your IP has been rate-limited by GitHub and the plugin cannot get the latest link to the yt-dlp binary.
You can change the download link by using the environment variable `YTDLP_URL`, or disable download by setting `YTDLP_DISABLE_DOWNLOAD` to `true`.
```sh
export YTDLP_URL=https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp
npm install @distube/yt-dlp@latest
```
```sh
export YTDLP_DISABLE_DOWNLOAD=true
npm install @distube/yt-dlp@latest
```
### Failed to run the plugin (Status code: 403)
The plugin cannot download the yt-dlp binary on startup. Same as the previous case.
You can disable download on startup by using `new YtDlpPlugin({ update: false })` or using above solution.
```js
import { DisTube } from "distube";
const distube = new DisTube(client, {
plugins: [new YtDlpPlugin({ update: false })],
});
```

BIN
bot/node_modules/@distube/yt-dlp/bin/yt-dlp generated vendored Executable file

Binary file not shown.

381
bot/node_modules/@distube/yt-dlp/dist/index.d.mts generated vendored Normal file
View File

@ -0,0 +1,381 @@
import { PlayableExtractorPlugin, DisTube, ResolveOptions, Playlist, Song } from 'distube';
import { SpawnOptionsWithoutStdio } from 'node:child_process';
interface YtDlpFlags {
help?: boolean;
version?: boolean;
update?: boolean;
ignoreErrors?: boolean;
abortOnError?: boolean;
dumpUserAgent?: boolean;
listExtractors?: boolean;
extractorDescriptions?: boolean;
forceGenericExtractor?: boolean;
defaultSearch?: string;
ignoreConfig?: boolean;
configLocation?: string;
flatPlaylist?: boolean;
liveFromStart?: boolean;
waitForVideo?: number;
markWatched?: boolean;
noColor?: boolean;
compatOptions?: string;
proxy?: string;
socketTimeout?: number;
sourceAddress?: string;
forceIpv4?: boolean;
forceIpv6?: boolean;
geoVerificationProxy?: string;
geoBypass?: boolean;
geoBypassCountry?: string;
geoBypassIpBlock?: string;
playlistStart?: number;
playlistEnd?: number | "last";
playlistItems?: number | string;
minFilesize?: string;
maxFilesize?: string;
date?: string;
datebefore?: string;
dateafter?: string;
matchFilter?: string;
noPlaylist?: boolean;
yesPlaylist?: boolean;
ageLimit?: number;
downloadArchive?: string;
maxDownloads?: number;
breakOnExisting?: boolean;
breakOnReject?: boolean;
breakPerInput?: boolean;
noBreakPerInput?: boolean;
skipPlaylistAfterErrors?: number;
concurrentFragments?: number;
limitRate?: string;
throttledRate?: string;
retries?: number | "infinite";
fileAccessRetries?: number | "infinite";
skipUnavailableFragments?: boolean;
abortOnUnavailableFragment?: boolean;
keepFragments?: boolean;
bufferSize?: string;
noResizeBuffer?: boolean;
httpChunkSize?: number | string;
playlistReverse?: boolean;
playlistRandom?: boolean;
xattrSetFilesize?: boolean;
hlsUseMpegts?: boolean;
noHlsUseMpegts?: boolean;
downloader?: string;
downloaderArgs?: string;
batchFile?: string;
paths?: string;
output?: string;
outputNaPlaceholder?: string;
restrictFilenames?: boolean;
windowsFilenames?: boolean;
trimFilenames?: boolean;
noOverwrites?: boolean;
continue?: boolean;
noContinue?: boolean;
noPart?: boolean;
noMtime?: boolean;
writeDescription?: boolean;
writeInfoJson?: boolean;
noWritePlaylistMetafiles?: boolean;
noCleanInfojson?: boolean;
writeComments?: boolean;
loadInfoJson?: string;
cookies?: string;
cookiesFromBrowser?: string;
cacheDir?: string;
noCacheDir?: boolean;
rmCacheDir?: boolean;
writeThumbnail?: boolean;
writeAllThumbnails?: boolean;
listThumbnails?: boolean;
writeLink?: boolean;
writeUrlLink?: boolean;
writeWeblocLink?: boolean;
writeDesktopLink?: boolean;
quiet?: boolean;
noWarnings?: boolean;
simulate?: boolean;
ignoreNoFormatsError?: boolean;
skipDownload?: boolean;
print?: string;
printToFile?: string;
dumpJson?: boolean;
dumpSingleJson?: boolean;
forceWriteArchive?: boolean;
newline?: boolean;
verbose?: boolean;
dumpPages?: boolean;
writePages?: boolean;
printTraffic?: boolean;
callHome?: boolean;
encoding?: string;
legacyServerConnect?: boolean;
noCheckCertificate?: boolean;
preferInsecure?: boolean;
userAgent?: string;
referer?: string;
addHeader?: string;
bidiWorkaround?: boolean;
sleepRequests?: number;
sleepInterval?: number;
maxSleepInterval?: number;
sleepSubtitles?: number;
format?: string;
formatSort?: string;
formatSortForce?: boolean;
videoMultistreams?: boolean;
audioMultistreams?: boolean;
preferFreeFormats?: boolean;
checkFormats?: boolean;
checkAllFormats?: boolean;
noCheckFormats?: boolean;
listFormats?: boolean;
mergeOutputFormat?: string;
writeSub?: boolean;
writeAutoSub?: boolean;
listSubs?: boolean;
subFormat?: string;
subLangs?: string;
username?: string;
password?: string;
twofactor?: string;
netrc?: boolean;
videoPassword?: string;
apMso?: string;
apUsername?: string;
apPassword?: string;
apListMso?: boolean;
extractAudio?: boolean;
audioFormat?: string;
audioQuality?: number;
remuxVideo?: string;
recodeVideo?: string;
postprocessorArgs?: string;
keepVideo?: boolean;
noPostOverwrites?: boolean;
embedSubs?: boolean;
embedThumbnail?: boolean;
embedMetadata?: boolean;
embedChapter?: boolean;
embedInfoJson?: boolean;
parseMetadata?: string;
replaceInMetadata?: string | string[];
xattrs?: boolean;
concatPlaylist?: string;
fixup?: string;
ffmpegLocation?: string;
exec?: string;
convertSubs?: string;
convertThumbnails?: string;
splitChapters?: boolean;
removeChapters?: string;
forceKeyframesAtCuts?: boolean;
usePostprocessor?: string;
sponsorblockMark?: string;
sponsorblockRemove?: string;
sponsorblockChapterTitle?: string;
noSponsorblock?: boolean;
sponsorblockApi?: string;
extractorRetries?: number | "infinite";
ignoreDynamicMpd?: boolean;
hlsSplitDiscontinuity?: boolean;
extractorArgs?: string;
[x: string]: any;
}
interface YtDlpFormat {
format_id: string;
format_note: string;
ext: string;
protocol: string;
acodec: string;
vcodec: string;
url: string;
width: number | null;
height: number | null;
fragments: any;
audio_ext: string;
video_ext: string;
format: string;
resolution: string;
http_headers: any;
asr: number;
filesize: number;
source_preference: number;
fps: null;
quality: number;
tbr: number;
language: string;
language_preference: number;
dynamic_range: null;
abr: number;
downloader_options: {
http_chunk_size: number;
};
container: string;
}
interface YtDlpThumbnail {
url: string;
preference: number;
id: string;
height?: number;
width?: number;
resolution?: string;
}
interface YtDlpCaption {
ext: string;
url: string;
name: string;
}
interface YtDlpVideo {
id: string;
title: string;
fulltitle: string;
url: string;
ext: string;
alt_title: string;
description: string;
display_id: string;
uploader: string;
license: string;
creator: string;
timestamp: number;
upload_date: string;
release_timestamp: number;
release_date: string;
modified_timestamp: number;
modified_date: string;
uploader_id: string;
channel: string;
channel_id: string;
channel_follower_count: number;
location: string;
duration: number;
duration_string: string;
view_count: number;
like_count: number;
dislike_count: number;
repost_count: number;
average_rating: number;
comment_count: number;
age_limit: number;
live_status: string;
is_live: boolean;
was_live: boolean;
playable_in_embed: string;
availability: string;
start_time: number;
end_time: number;
format: string;
format_id: string;
format_note: string;
width: number;
height: number;
resolution: string;
tbr: number;
abr: number;
acodec: string;
asr: number;
vbr: number;
fps: number;
dynamic_range: string;
vcodec: string;
container: string;
filesize: number;
filesize_approx: number;
protocol: string;
src: string;
extractor: string;
extractor_key: string;
epoch: number;
autonumber: number;
video_autonumber: number;
n_entries: number;
playlist_id: string;
playlist_title: string;
playlist: string;
playlist_count: number;
playlist_index: number;
playlist_autonumber: number;
playlist_uploader: string;
playlist_uploader_id: string;
webpage_url: string;
webpage_url_basename: string;
webpage_url_domain: string;
original_url: string;
formats: YtDlpFormat[];
thumbnails: YtDlpThumbnail[];
thumbnail: string;
uploader_url: string;
channel_url: string;
categories: string[];
tags: string[];
automatic_captions: Record<string, YtDlpCaption[]>;
subtitles: unknown;
chapters: any[];
requested_subtitles: unknown;
__has_drm: boolean;
requested_downloads: unknown[];
source_preference: number;
quality: number;
language: string;
language_preference: number;
downloader_options: {
http_chunk_size: number;
};
audio_ext: string;
video_ext: string;
http_headers: unknown;
_last_playlist_index: number;
requested_formats: unknown[];
stretched_ratio: unknown;
}
interface YtDlpPlaylist {
uploader: string;
uploader_id: string;
uploader_url: string;
thumbnails: YtDlpThumbnail[];
tags: string[];
view_count: number;
modified_date: string;
playlist_count: number;
channel_follower_count: number | null;
channel: string;
channel_id: string;
channel_url: string;
id: string;
title: string;
description: string;
entries: YtDlpVideo[];
original_url: string;
webpage_url: string;
webpage_url_basename: string;
webpage_url_domain: string;
extractor: string;
extractor_key: string;
epoch: number;
}
type YtDlpResponse = YtDlpVideo | YtDlpPlaylist;
interface YtDlpOptions {
update?: boolean;
}
declare const json: (url: string, flags?: YtDlpFlags, options?: SpawnOptionsWithoutStdio) => Promise<YtDlpResponse>;
declare const download: () => Promise<string>;
declare class YtDlpPlugin extends PlayableExtractorPlugin {
constructor({ update }?: YtDlpOptions);
init(distube: DisTube): void;
validate(): boolean;
resolve<T>(url: string, options: ResolveOptions<T>): Promise<YtDlpSong<T> | Playlist<T>>;
getStreamURL(song: Song): Promise<string>;
getRelatedSongs(): never[];
}
declare class YtDlpSong<T> extends Song<T> {
constructor(plugin: YtDlpPlugin, info: YtDlpVideo, options?: ResolveOptions<T>);
}
export { YtDlpPlugin, download, json };

381
bot/node_modules/@distube/yt-dlp/dist/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,381 @@
import { PlayableExtractorPlugin, DisTube, ResolveOptions, Playlist, Song } from 'distube';
import { SpawnOptionsWithoutStdio } from 'node:child_process';
interface YtDlpFlags {
help?: boolean;
version?: boolean;
update?: boolean;
ignoreErrors?: boolean;
abortOnError?: boolean;
dumpUserAgent?: boolean;
listExtractors?: boolean;
extractorDescriptions?: boolean;
forceGenericExtractor?: boolean;
defaultSearch?: string;
ignoreConfig?: boolean;
configLocation?: string;
flatPlaylist?: boolean;
liveFromStart?: boolean;
waitForVideo?: number;
markWatched?: boolean;
noColor?: boolean;
compatOptions?: string;
proxy?: string;
socketTimeout?: number;
sourceAddress?: string;
forceIpv4?: boolean;
forceIpv6?: boolean;
geoVerificationProxy?: string;
geoBypass?: boolean;
geoBypassCountry?: string;
geoBypassIpBlock?: string;
playlistStart?: number;
playlistEnd?: number | "last";
playlistItems?: number | string;
minFilesize?: string;
maxFilesize?: string;
date?: string;
datebefore?: string;
dateafter?: string;
matchFilter?: string;
noPlaylist?: boolean;
yesPlaylist?: boolean;
ageLimit?: number;
downloadArchive?: string;
maxDownloads?: number;
breakOnExisting?: boolean;
breakOnReject?: boolean;
breakPerInput?: boolean;
noBreakPerInput?: boolean;
skipPlaylistAfterErrors?: number;
concurrentFragments?: number;
limitRate?: string;
throttledRate?: string;
retries?: number | "infinite";
fileAccessRetries?: number | "infinite";
skipUnavailableFragments?: boolean;
abortOnUnavailableFragment?: boolean;
keepFragments?: boolean;
bufferSize?: string;
noResizeBuffer?: boolean;
httpChunkSize?: number | string;
playlistReverse?: boolean;
playlistRandom?: boolean;
xattrSetFilesize?: boolean;
hlsUseMpegts?: boolean;
noHlsUseMpegts?: boolean;
downloader?: string;
downloaderArgs?: string;
batchFile?: string;
paths?: string;
output?: string;
outputNaPlaceholder?: string;
restrictFilenames?: boolean;
windowsFilenames?: boolean;
trimFilenames?: boolean;
noOverwrites?: boolean;
continue?: boolean;
noContinue?: boolean;
noPart?: boolean;
noMtime?: boolean;
writeDescription?: boolean;
writeInfoJson?: boolean;
noWritePlaylistMetafiles?: boolean;
noCleanInfojson?: boolean;
writeComments?: boolean;
loadInfoJson?: string;
cookies?: string;
cookiesFromBrowser?: string;
cacheDir?: string;
noCacheDir?: boolean;
rmCacheDir?: boolean;
writeThumbnail?: boolean;
writeAllThumbnails?: boolean;
listThumbnails?: boolean;
writeLink?: boolean;
writeUrlLink?: boolean;
writeWeblocLink?: boolean;
writeDesktopLink?: boolean;
quiet?: boolean;
noWarnings?: boolean;
simulate?: boolean;
ignoreNoFormatsError?: boolean;
skipDownload?: boolean;
print?: string;
printToFile?: string;
dumpJson?: boolean;
dumpSingleJson?: boolean;
forceWriteArchive?: boolean;
newline?: boolean;
verbose?: boolean;
dumpPages?: boolean;
writePages?: boolean;
printTraffic?: boolean;
callHome?: boolean;
encoding?: string;
legacyServerConnect?: boolean;
noCheckCertificate?: boolean;
preferInsecure?: boolean;
userAgent?: string;
referer?: string;
addHeader?: string;
bidiWorkaround?: boolean;
sleepRequests?: number;
sleepInterval?: number;
maxSleepInterval?: number;
sleepSubtitles?: number;
format?: string;
formatSort?: string;
formatSortForce?: boolean;
videoMultistreams?: boolean;
audioMultistreams?: boolean;
preferFreeFormats?: boolean;
checkFormats?: boolean;
checkAllFormats?: boolean;
noCheckFormats?: boolean;
listFormats?: boolean;
mergeOutputFormat?: string;
writeSub?: boolean;
writeAutoSub?: boolean;
listSubs?: boolean;
subFormat?: string;
subLangs?: string;
username?: string;
password?: string;
twofactor?: string;
netrc?: boolean;
videoPassword?: string;
apMso?: string;
apUsername?: string;
apPassword?: string;
apListMso?: boolean;
extractAudio?: boolean;
audioFormat?: string;
audioQuality?: number;
remuxVideo?: string;
recodeVideo?: string;
postprocessorArgs?: string;
keepVideo?: boolean;
noPostOverwrites?: boolean;
embedSubs?: boolean;
embedThumbnail?: boolean;
embedMetadata?: boolean;
embedChapter?: boolean;
embedInfoJson?: boolean;
parseMetadata?: string;
replaceInMetadata?: string | string[];
xattrs?: boolean;
concatPlaylist?: string;
fixup?: string;
ffmpegLocation?: string;
exec?: string;
convertSubs?: string;
convertThumbnails?: string;
splitChapters?: boolean;
removeChapters?: string;
forceKeyframesAtCuts?: boolean;
usePostprocessor?: string;
sponsorblockMark?: string;
sponsorblockRemove?: string;
sponsorblockChapterTitle?: string;
noSponsorblock?: boolean;
sponsorblockApi?: string;
extractorRetries?: number | "infinite";
ignoreDynamicMpd?: boolean;
hlsSplitDiscontinuity?: boolean;
extractorArgs?: string;
[x: string]: any;
}
interface YtDlpFormat {
format_id: string;
format_note: string;
ext: string;
protocol: string;
acodec: string;
vcodec: string;
url: string;
width: number | null;
height: number | null;
fragments: any;
audio_ext: string;
video_ext: string;
format: string;
resolution: string;
http_headers: any;
asr: number;
filesize: number;
source_preference: number;
fps: null;
quality: number;
tbr: number;
language: string;
language_preference: number;
dynamic_range: null;
abr: number;
downloader_options: {
http_chunk_size: number;
};
container: string;
}
interface YtDlpThumbnail {
url: string;
preference: number;
id: string;
height?: number;
width?: number;
resolution?: string;
}
interface YtDlpCaption {
ext: string;
url: string;
name: string;
}
interface YtDlpVideo {
id: string;
title: string;
fulltitle: string;
url: string;
ext: string;
alt_title: string;
description: string;
display_id: string;
uploader: string;
license: string;
creator: string;
timestamp: number;
upload_date: string;
release_timestamp: number;
release_date: string;
modified_timestamp: number;
modified_date: string;
uploader_id: string;
channel: string;
channel_id: string;
channel_follower_count: number;
location: string;
duration: number;
duration_string: string;
view_count: number;
like_count: number;
dislike_count: number;
repost_count: number;
average_rating: number;
comment_count: number;
age_limit: number;
live_status: string;
is_live: boolean;
was_live: boolean;
playable_in_embed: string;
availability: string;
start_time: number;
end_time: number;
format: string;
format_id: string;
format_note: string;
width: number;
height: number;
resolution: string;
tbr: number;
abr: number;
acodec: string;
asr: number;
vbr: number;
fps: number;
dynamic_range: string;
vcodec: string;
container: string;
filesize: number;
filesize_approx: number;
protocol: string;
src: string;
extractor: string;
extractor_key: string;
epoch: number;
autonumber: number;
video_autonumber: number;
n_entries: number;
playlist_id: string;
playlist_title: string;
playlist: string;
playlist_count: number;
playlist_index: number;
playlist_autonumber: number;
playlist_uploader: string;
playlist_uploader_id: string;
webpage_url: string;
webpage_url_basename: string;
webpage_url_domain: string;
original_url: string;
formats: YtDlpFormat[];
thumbnails: YtDlpThumbnail[];
thumbnail: string;
uploader_url: string;
channel_url: string;
categories: string[];
tags: string[];
automatic_captions: Record<string, YtDlpCaption[]>;
subtitles: unknown;
chapters: any[];
requested_subtitles: unknown;
__has_drm: boolean;
requested_downloads: unknown[];
source_preference: number;
quality: number;
language: string;
language_preference: number;
downloader_options: {
http_chunk_size: number;
};
audio_ext: string;
video_ext: string;
http_headers: unknown;
_last_playlist_index: number;
requested_formats: unknown[];
stretched_ratio: unknown;
}
interface YtDlpPlaylist {
uploader: string;
uploader_id: string;
uploader_url: string;
thumbnails: YtDlpThumbnail[];
tags: string[];
view_count: number;
modified_date: string;
playlist_count: number;
channel_follower_count: number | null;
channel: string;
channel_id: string;
channel_url: string;
id: string;
title: string;
description: string;
entries: YtDlpVideo[];
original_url: string;
webpage_url: string;
webpage_url_basename: string;
webpage_url_domain: string;
extractor: string;
extractor_key: string;
epoch: number;
}
type YtDlpResponse = YtDlpVideo | YtDlpPlaylist;
interface YtDlpOptions {
update?: boolean;
}
declare const json: (url: string, flags?: YtDlpFlags, options?: SpawnOptionsWithoutStdio) => Promise<YtDlpResponse>;
declare const download: () => Promise<string>;
declare class YtDlpPlugin extends PlayableExtractorPlugin {
constructor({ update }?: YtDlpOptions);
init(distube: DisTube): void;
validate(): boolean;
resolve<T>(url: string, options: ResolveOptions<T>): Promise<YtDlpSong<T> | Playlist<T>>;
getStreamURL(song: Song): Promise<string>;
getRelatedSongs(): never[];
}
declare class YtDlpSong<T> extends Song<T> {
constructor(plugin: YtDlpPlugin, info: YtDlpVideo, options?: ResolveOptions<T>);
}
export { YtDlpPlugin, download, json };

228
bot/node_modules/@distube/yt-dlp/dist/index.js generated vendored Normal file
View File

@ -0,0 +1,228 @@
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var src_exports = {};
__export(src_exports, {
YtDlpPlugin: () => YtDlpPlugin,
download: () => download,
json: () => json
});
module.exports = __toCommonJS(src_exports);
// src/wrapper.ts
var import_dargs = __toESM(require("dargs"));
var import_promises = __toESM(require("fs/promises"));
var import_node_child_process = require("child_process");
var import_undici = require("undici");
// src/env.ts
var import_path = __toESM(require("path"));
var e = /* @__PURE__ */ __name((key) => process.env[key], "e");
var YTDLP_DISABLE_DOWNLOAD = !!e("YTDLP_DISABLE_DOWNLOAD");
var YTDLP_URL = e("YTDLP_URL");
var YTDLP_IS_WINDOWS = e("YTDLP_IS_WINDOWS") || process.platform === "win32";
var YTDLP_DIR = e("YTDLP_DIR") || import_path.default.join(__dirname, "..", "bin");
var YTDLP_FILENAME = e("YTDLP_FILENAME") || `yt-dlp${YTDLP_IS_WINDOWS ? ".exe" : ""}`;
var YTDLP_PATH = import_path.default.join(YTDLP_DIR, YTDLP_FILENAME);
// src/wrapper.ts
var makeRequest = /* @__PURE__ */ __name(async (url) => {
const response = await (0, import_undici.request)(url, { headers: { "user-agent": "distube" } });
if (!response.statusCode) throw new Error(`Cannot make requests to '${url}'`);
if (response.statusCode.toString().startsWith("3")) {
if (!response.headers.location || Array.isArray(response.headers.location)) {
throw new Error(`Cannot redirect to '${url}'`);
}
for await (const _chunk of response.body) {
}
return makeRequest(response.headers.location);
}
if (response.statusCode.toString().startsWith("2")) return response;
throw new Error(`${url}
Status code ${response.statusCode.toString()}`);
}, "makeRequest");
var args = /* @__PURE__ */ __name((url, flags = {}) => [url].concat((0, import_dargs.default)(flags, { useEquals: false })).filter(Boolean), "args");
var json = /* @__PURE__ */ __name((url, flags, options) => {
const process2 = (0, import_node_child_process.spawn)(YTDLP_PATH, args(url, flags), options);
return new Promise((resolve, reject) => {
let output = "";
process2.stdout?.on("data", (chunk) => {
output += chunk;
});
process2.stderr?.on("data", (chunk) => {
output += chunk;
});
process2.on("close", (code) => {
if (code === 0) resolve(JSON.parse(output));
else reject(new Error(output));
});
process2.on("error", reject);
});
}, "json");
var binContentTypes = ["binary/octet-stream", "application/octet-stream", "application/x-binary"];
var getBinary = /* @__PURE__ */ __name(async (url) => {
let version = "N/A";
if (!url) {
const defaultFilename = `yt-dlp${YTDLP_IS_WINDOWS ? ".exe" : ""}`;
const defaultUrl = `https://github.com/yt-dlp/yt-dlp/releases/latest/download/${defaultFilename}`;
try {
const response2 = await makeRequest("https://api.github.com/repos/yt-dlp/yt-dlp/releases?per_page=1");
const [{ assets, tag_name }] = await response2.body.json();
const { browser_download_url } = assets.find(
({ name }) => name === `yt-dlp${YTDLP_IS_WINDOWS ? ".exe" : ""}`
);
version = typeof tag_name === "string" ? tag_name : "latest";
url = typeof browser_download_url === "string" ? browser_download_url : defaultUrl;
} catch {
version = "latest";
url = defaultUrl;
}
}
const response = await makeRequest(url);
const contentType = response.headers["content-type"]?.toString();
if (binContentTypes.includes(contentType ?? "")) return { buffer: await response.body.arrayBuffer(), version };
throw new Error(`Unsupported content type: ${contentType}`);
}, "getBinary");
var download = /* @__PURE__ */ __name(() => Promise.all([getBinary(YTDLP_URL), import_promises.default.mkdir(YTDLP_DIR, { recursive: true }).catch(() => void 0)]).then(
([{ buffer, version }]) => {
import_promises.default.writeFile(YTDLP_PATH, Buffer.from(buffer), { mode: 493 });
return version;
}
), "download");
// src/index.ts
var import_distube = require("distube");
var isPlaylist = /* @__PURE__ */ __name((i) => Array.isArray(i.entries), "isPlaylist");
var YtDlpPlugin = class extends import_distube.PlayableExtractorPlugin {
static {
__name(this, "YtDlpPlugin");
}
constructor({ update } = {}) {
super();
if (update ?? true) download().catch(() => void 0);
}
init(distube) {
super.init(distube);
if (this.distube.plugins[this.distube.plugins.length - 1] !== this) {
console.warn(
`[${this.constructor.name}] This plugin is not the last plugin in distube. This is not recommended.`
);
}
}
validate() {
return true;
}
async resolve(url, options) {
const info = await json(url, {
dumpSingleJson: true,
noWarnings: true,
noCallHome: true,
preferFreeFormats: true,
skipDownload: true,
simulate: true
}).catch((e2) => {
throw new import_distube.DisTubeError("YTDLP_ERROR", `${e2.stderr || e2}`);
});
if (isPlaylist(info)) {
if (info.entries.length === 0) throw new import_distube.DisTubeError("YTDLP_ERROR", "The playlist is empty");
return new import_distube.Playlist(
{
source: info.extractor,
songs: info.entries.map((i) => new YtDlpSong(this, i, options)),
id: info.id.toString(),
name: info.title,
url: info.webpage_url,
thumbnail: info.thumbnails?.[0]?.url
},
options
);
}
return new YtDlpSong(this, info, options);
}
async getStreamURL(song) {
if (!song.url) {
throw new import_distube.DisTubeError("YTDLP_PLUGIN_INVALID_SONG", "Cannot get stream url from invalid song.");
}
const info = await json(song.url, {
dumpSingleJson: true,
noWarnings: true,
noCallHome: true,
preferFreeFormats: true,
skipDownload: true,
simulate: true,
format: "ba/ba*"
}).catch((e2) => {
throw new import_distube.DisTubeError("YTDLP_ERROR", `${e2.stderr || e2}`);
});
if (isPlaylist(info)) throw new import_distube.DisTubeError("YTDLP_ERROR", "Cannot get stream URL of a entire playlist");
return info.url;
}
getRelatedSongs() {
return [];
}
};
var YtDlpSong = class extends import_distube.Song {
static {
__name(this, "YtDlpSong");
}
constructor(plugin, info, options = {}) {
super(
{
plugin,
source: info.extractor,
playFromSource: true,
id: info.id,
name: info.title || info.fulltitle,
url: info.webpage_url || info.original_url,
isLive: info.is_live,
thumbnail: info.thumbnail || info.thumbnails?.[0]?.url,
duration: info.is_live ? 0 : info.duration,
uploader: {
name: info.uploader,
url: info.uploader_url
},
views: info.view_count,
likes: info.like_count,
dislikes: info.dislike_count,
reposts: info.repost_count,
ageRestricted: Boolean(info.age_limit) && info.age_limit >= 18
},
options
);
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
YtDlpPlugin,
download,
json
});
//# sourceMappingURL=index.js.map

1
bot/node_modules/@distube/yt-dlp/dist/index.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

198
bot/node_modules/@distube/yt-dlp/dist/index.mjs generated vendored Normal file
View File

@ -0,0 +1,198 @@
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
// ../../node_modules/.pnpm/tsup@8.1.0_postcss@8.4.38_ts-node@10.9.2_@types+node@20.14.2_typescript@5.4.5__typescript@5.4.5/node_modules/tsup/assets/esm_shims.js
import { fileURLToPath } from "url";
import path from "path";
var getFilename = /* @__PURE__ */ __name(() => fileURLToPath(import.meta.url), "getFilename");
var getDirname = /* @__PURE__ */ __name(() => path.dirname(getFilename()), "getDirname");
var __dirname = /* @__PURE__ */ getDirname();
// src/wrapper.ts
import dargs from "dargs";
import fs from "node:fs/promises";
import { spawn } from "node:child_process";
import { request } from "undici";
// src/env.ts
import path2 from "path";
var e = /* @__PURE__ */ __name((key) => process.env[key], "e");
var YTDLP_DISABLE_DOWNLOAD = !!e("YTDLP_DISABLE_DOWNLOAD");
var YTDLP_URL = e("YTDLP_URL");
var YTDLP_IS_WINDOWS = e("YTDLP_IS_WINDOWS") || process.platform === "win32";
var YTDLP_DIR = e("YTDLP_DIR") || path2.join(__dirname, "..", "bin");
var YTDLP_FILENAME = e("YTDLP_FILENAME") || `yt-dlp${YTDLP_IS_WINDOWS ? ".exe" : ""}`;
var YTDLP_PATH = path2.join(YTDLP_DIR, YTDLP_FILENAME);
// src/wrapper.ts
var makeRequest = /* @__PURE__ */ __name(async (url) => {
const response = await request(url, { headers: { "user-agent": "distube" } });
if (!response.statusCode) throw new Error(`Cannot make requests to '${url}'`);
if (response.statusCode.toString().startsWith("3")) {
if (!response.headers.location || Array.isArray(response.headers.location)) {
throw new Error(`Cannot redirect to '${url}'`);
}
for await (const _chunk of response.body) {
}
return makeRequest(response.headers.location);
}
if (response.statusCode.toString().startsWith("2")) return response;
throw new Error(`${url}
Status code ${response.statusCode.toString()}`);
}, "makeRequest");
var args = /* @__PURE__ */ __name((url, flags = {}) => [url].concat(dargs(flags, { useEquals: false })).filter(Boolean), "args");
var json = /* @__PURE__ */ __name((url, flags, options) => {
const process2 = spawn(YTDLP_PATH, args(url, flags), options);
return new Promise((resolve, reject) => {
let output = "";
process2.stdout?.on("data", (chunk) => {
output += chunk;
});
process2.stderr?.on("data", (chunk) => {
output += chunk;
});
process2.on("close", (code) => {
if (code === 0) resolve(JSON.parse(output));
else reject(new Error(output));
});
process2.on("error", reject);
});
}, "json");
var binContentTypes = ["binary/octet-stream", "application/octet-stream", "application/x-binary"];
var getBinary = /* @__PURE__ */ __name(async (url) => {
let version = "N/A";
if (!url) {
const defaultFilename = `yt-dlp${YTDLP_IS_WINDOWS ? ".exe" : ""}`;
const defaultUrl = `https://github.com/yt-dlp/yt-dlp/releases/latest/download/${defaultFilename}`;
try {
const response2 = await makeRequest("https://api.github.com/repos/yt-dlp/yt-dlp/releases?per_page=1");
const [{ assets, tag_name }] = await response2.body.json();
const { browser_download_url } = assets.find(
({ name }) => name === `yt-dlp${YTDLP_IS_WINDOWS ? ".exe" : ""}`
);
version = typeof tag_name === "string" ? tag_name : "latest";
url = typeof browser_download_url === "string" ? browser_download_url : defaultUrl;
} catch {
version = "latest";
url = defaultUrl;
}
}
const response = await makeRequest(url);
const contentType = response.headers["content-type"]?.toString();
if (binContentTypes.includes(contentType ?? "")) return { buffer: await response.body.arrayBuffer(), version };
throw new Error(`Unsupported content type: ${contentType}`);
}, "getBinary");
var download = /* @__PURE__ */ __name(() => Promise.all([getBinary(YTDLP_URL), fs.mkdir(YTDLP_DIR, { recursive: true }).catch(() => void 0)]).then(
([{ buffer, version }]) => {
fs.writeFile(YTDLP_PATH, Buffer.from(buffer), { mode: 493 });
return version;
}
), "download");
// src/index.ts
import { DisTubeError, PlayableExtractorPlugin, Playlist, Song } from "distube";
var isPlaylist = /* @__PURE__ */ __name((i) => Array.isArray(i.entries), "isPlaylist");
var YtDlpPlugin = class extends PlayableExtractorPlugin {
static {
__name(this, "YtDlpPlugin");
}
constructor({ update } = {}) {
super();
if (update ?? true) download().catch(() => void 0);
}
init(distube) {
super.init(distube);
if (this.distube.plugins[this.distube.plugins.length - 1] !== this) {
console.warn(
`[${this.constructor.name}] This plugin is not the last plugin in distube. This is not recommended.`
);
}
}
validate() {
return true;
}
async resolve(url, options) {
const info = await json(url, {
dumpSingleJson: true,
noWarnings: true,
noCallHome: true,
preferFreeFormats: true,
skipDownload: true,
simulate: true
}).catch((e2) => {
throw new DisTubeError("YTDLP_ERROR", `${e2.stderr || e2}`);
});
if (isPlaylist(info)) {
if (info.entries.length === 0) throw new DisTubeError("YTDLP_ERROR", "The playlist is empty");
return new Playlist(
{
source: info.extractor,
songs: info.entries.map((i) => new YtDlpSong(this, i, options)),
id: info.id.toString(),
name: info.title,
url: info.webpage_url,
thumbnail: info.thumbnails?.[0]?.url
},
options
);
}
return new YtDlpSong(this, info, options);
}
async getStreamURL(song) {
if (!song.url) {
throw new DisTubeError("YTDLP_PLUGIN_INVALID_SONG", "Cannot get stream url from invalid song.");
}
const info = await json(song.url, {
dumpSingleJson: true,
noWarnings: true,
noCallHome: true,
preferFreeFormats: true,
skipDownload: true,
simulate: true,
format: "ba/ba*"
}).catch((e2) => {
throw new DisTubeError("YTDLP_ERROR", `${e2.stderr || e2}`);
});
if (isPlaylist(info)) throw new DisTubeError("YTDLP_ERROR", "Cannot get stream URL of a entire playlist");
return info.url;
}
getRelatedSongs() {
return [];
}
};
var YtDlpSong = class extends Song {
static {
__name(this, "YtDlpSong");
}
constructor(plugin, info, options = {}) {
super(
{
plugin,
source: info.extractor,
playFromSource: true,
id: info.id,
name: info.title || info.fulltitle,
url: info.webpage_url || info.original_url,
isLive: info.is_live,
thumbnail: info.thumbnail || info.thumbnails?.[0]?.url,
duration: info.is_live ? 0 : info.duration,
uploader: {
name: info.uploader,
url: info.uploader_url
},
views: info.view_count,
likes: info.like_count,
dislikes: info.dislike_count,
reposts: info.repost_count,
ageRestricted: Boolean(info.age_limit) && info.age_limit >= 18
},
options
);
}
};
export {
YtDlpPlugin,
download,
json
};
//# sourceMappingURL=index.mjs.map

1
bot/node_modules/@distube/yt-dlp/dist/index.mjs.map generated vendored Normal file

File diff suppressed because one or more lines are too long

71
bot/node_modules/@distube/yt-dlp/package.json generated vendored Normal file
View File

@ -0,0 +1,71 @@
{
"name": "@distube/yt-dlp",
"version": "2.0.1",
"author": "Skick",
"repository": {
"type": "git",
"url": "git+https://github.com/distubejs/extractor-plugins.git"
},
"main": "./dist/index.js",
"devDependencies": {
"@types/node": "^20.14.2",
"discord.js": "^14.15.3",
"distube": "^5.0.1",
"eslint": "^8.57.0",
"eslint-config-distube": "^1.7.0",
"is-ci": "^3.0.1",
"prettier": "^3.3.1",
"tslib": "^2.6.3",
"tsup": "^8.1.0",
"typescript": "^5.4.5"
},
"exports": "./dist/index.js",
"bugs": {
"url": "https://github.com/distubejs/extractor-plugins/issues"
},
"description": "A DisTube playable extractor plugin using yt-dlp.",
"directories": {
"lib": "src"
},
"files": [
"dist",
"script"
],
"funding": "https://github.com/skick1234/DisTube?sponsor",
"homepage": "https://github.com/distubejs/extractor-plugins/tree/main/packages/yt-dlp#readme",
"keywords": [
"distube",
"plugin",
"discord",
"music"
],
"license": "MIT",
"nano-staged": {
"*.ts": [
"prettier --write",
"eslint"
],
"*.{json,yml,yaml}": [
"prettier --write"
]
},
"peerDependencies": {
"distube": "5"
},
"typings": "./dist/index.d.ts",
"publishConfig": {
"access": "public",
"provenance": true
},
"dependencies": {
"dargs": "^7.0.0",
"undici": "^6.18.2"
},
"scripts": {
"format": "prettier --write \"**/*.{js,ts,json,yml,yaml,md}\"",
"lint": "eslint .",
"build": "tsup",
"type": "tsc --noEmit",
"postinstall": "is-ci || node script/download.js"
}
}

5
bot/node_modules/@distube/yt-dlp/script/download.js generated vendored Normal file
View File

@ -0,0 +1,5 @@
/* eslint-disable no-console, @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports */
const { YTDLP_DISABLE_DOWNLOAD, download } = require("..");
if (!YTDLP_DISABLE_DOWNLOAD) download().then(v => console.log(`[yt-dlp] Downloaded ${v} version!`));

21
bot/node_modules/asynckit/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 Alex Indigo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

233
bot/node_modules/asynckit/README.md generated vendored Normal file
View File

@ -0,0 +1,233 @@
# asynckit [![NPM Module](https://img.shields.io/npm/v/asynckit.svg?style=flat)](https://www.npmjs.com/package/asynckit)
Minimal async jobs utility library, with streams support.
[![PhantomJS Build](https://img.shields.io/travis/alexindigo/asynckit/v0.4.0.svg?label=browser&style=flat)](https://travis-ci.org/alexindigo/asynckit)
[![Linux Build](https://img.shields.io/travis/alexindigo/asynckit/v0.4.0.svg?label=linux:0.12-6.x&style=flat)](https://travis-ci.org/alexindigo/asynckit)
[![Windows Build](https://img.shields.io/appveyor/ci/alexindigo/asynckit/v0.4.0.svg?label=windows:0.12-6.x&style=flat)](https://ci.appveyor.com/project/alexindigo/asynckit)
[![Coverage Status](https://img.shields.io/coveralls/alexindigo/asynckit/v0.4.0.svg?label=code+coverage&style=flat)](https://coveralls.io/github/alexindigo/asynckit?branch=master)
[![Dependency Status](https://img.shields.io/david/alexindigo/asynckit/v0.4.0.svg?style=flat)](https://david-dm.org/alexindigo/asynckit)
[![bitHound Overall Score](https://www.bithound.io/github/alexindigo/asynckit/badges/score.svg)](https://www.bithound.io/github/alexindigo/asynckit)
<!-- [![Readme](https://img.shields.io/badge/readme-tested-brightgreen.svg?style=flat)](https://www.npmjs.com/package/reamde) -->
AsyncKit provides harness for `parallel` and `serial` iterators over list of items represented by arrays or objects.
Optionally it accepts abort function (should be synchronously return by iterator for each item), and terminates left over jobs upon an error event. For specific iteration order built-in (`ascending` and `descending`) and custom sort helpers also supported, via `asynckit.serialOrdered` method.
It ensures async operations to keep behavior more stable and prevent `Maximum call stack size exceeded` errors, from sync iterators.
| compression | size |
| :----------------- | -------: |
| asynckit.js | 12.34 kB |
| asynckit.min.js | 4.11 kB |
| asynckit.min.js.gz | 1.47 kB |
## Install
```sh
$ npm install --save asynckit
```
## Examples
### Parallel Jobs
Runs iterator over provided array in parallel. Stores output in the `result` array,
on the matching positions. In unlikely event of an error from one of the jobs,
will terminate rest of the active jobs (if abort function is provided)
and return error along with salvaged data to the main callback function.
#### Input Array
```javascript
var parallel = require('asynckit').parallel
, assert = require('assert')
;
var source = [ 1, 1, 4, 16, 64, 32, 8, 2 ]
, expectedResult = [ 2, 2, 8, 32, 128, 64, 16, 4 ]
, expectedTarget = [ 1, 1, 2, 4, 8, 16, 32, 64 ]
, target = []
;
parallel(source, asyncJob, function(err, result)
{
assert.deepEqual(result, expectedResult);
assert.deepEqual(target, expectedTarget);
});
// async job accepts one element from the array
// and a callback function
function asyncJob(item, cb)
{
// different delays (in ms) per item
var delay = item * 25;
// pretend different jobs take different time to finish
// and not in consequential order
var timeoutId = setTimeout(function() {
target.push(item);
cb(null, item * 2);
}, delay);
// allow to cancel "leftover" jobs upon error
// return function, invoking of which will abort this job
return clearTimeout.bind(null, timeoutId);
}
```
More examples could be found in [test/test-parallel-array.js](test/test-parallel-array.js).
#### Input Object
Also it supports named jobs, listed via object.
```javascript
var parallel = require('asynckit/parallel')
, assert = require('assert')
;
var source = { first: 1, one: 1, four: 4, sixteen: 16, sixtyFour: 64, thirtyTwo: 32, eight: 8, two: 2 }
, expectedResult = { first: 2, one: 2, four: 8, sixteen: 32, sixtyFour: 128, thirtyTwo: 64, eight: 16, two: 4 }
, expectedTarget = [ 1, 1, 2, 4, 8, 16, 32, 64 ]
, expectedKeys = [ 'first', 'one', 'two', 'four', 'eight', 'sixteen', 'thirtyTwo', 'sixtyFour' ]
, target = []
, keys = []
;
parallel(source, asyncJob, function(err, result)
{
assert.deepEqual(result, expectedResult);
assert.deepEqual(target, expectedTarget);
assert.deepEqual(keys, expectedKeys);
});
// supports full value, key, callback (shortcut) interface
function asyncJob(item, key, cb)
{
// different delays (in ms) per item
var delay = item * 25;
// pretend different jobs take different time to finish
// and not in consequential order
var timeoutId = setTimeout(function() {
keys.push(key);
target.push(item);
cb(null, item * 2);
}, delay);
// allow to cancel "leftover" jobs upon error
// return function, invoking of which will abort this job
return clearTimeout.bind(null, timeoutId);
}
```
More examples could be found in [test/test-parallel-object.js](test/test-parallel-object.js).
### Serial Jobs
Runs iterator over provided array sequentially. Stores output in the `result` array,
on the matching positions. In unlikely event of an error from one of the jobs,
will not proceed to the rest of the items in the list
and return error along with salvaged data to the main callback function.
#### Input Array
```javascript
var serial = require('asynckit/serial')
, assert = require('assert')
;
var source = [ 1, 1, 4, 16, 64, 32, 8, 2 ]
, expectedResult = [ 2, 2, 8, 32, 128, 64, 16, 4 ]
, expectedTarget = [ 0, 1, 2, 3, 4, 5, 6, 7 ]
, target = []
;
serial(source, asyncJob, function(err, result)
{
assert.deepEqual(result, expectedResult);
assert.deepEqual(target, expectedTarget);
});
// extended interface (item, key, callback)
// also supported for arrays
function asyncJob(item, key, cb)
{
target.push(key);
// it will be automatically made async
// even it iterator "returns" in the same event loop
cb(null, item * 2);
}
```
More examples could be found in [test/test-serial-array.js](test/test-serial-array.js).
#### Input Object
Also it supports named jobs, listed via object.
```javascript
var serial = require('asynckit').serial
, assert = require('assert')
;
var source = [ 1, 1, 4, 16, 64, 32, 8, 2 ]
, expectedResult = [ 2, 2, 8, 32, 128, 64, 16, 4 ]
, expectedTarget = [ 0, 1, 2, 3, 4, 5, 6, 7 ]
, target = []
;
var source = { first: 1, one: 1, four: 4, sixteen: 16, sixtyFour: 64, thirtyTwo: 32, eight: 8, two: 2 }
, expectedResult = { first: 2, one: 2, four: 8, sixteen: 32, sixtyFour: 128, thirtyTwo: 64, eight: 16, two: 4 }
, expectedTarget = [ 1, 1, 4, 16, 64, 32, 8, 2 ]
, target = []
;
serial(source, asyncJob, function(err, result)
{
assert.deepEqual(result, expectedResult);
assert.deepEqual(target, expectedTarget);
});
// shortcut interface (item, callback)
// works for object as well as for the arrays
function asyncJob(item, cb)
{
target.push(item);
// it will be automatically made async
// even it iterator "returns" in the same event loop
cb(null, item * 2);
}
```
More examples could be found in [test/test-serial-object.js](test/test-serial-object.js).
_Note: Since _object_ is an _unordered_ collection of properties,
it may produce unexpected results with sequential iterations.
Whenever order of the jobs' execution is important please use `serialOrdered` method._
### Ordered Serial Iterations
TBD
For example [compare-property](compare-property) package.
### Streaming interface
TBD
## Want to Know More?
More examples can be found in [test folder](test/).
Or open an [issue](https://github.com/alexindigo/asynckit/issues) with questions and/or suggestions.
## License
AsyncKit is licensed under the MIT license.

76
bot/node_modules/asynckit/bench.js generated vendored Normal file
View File

@ -0,0 +1,76 @@
/* eslint no-console: "off" */
var asynckit = require('./')
, async = require('async')
, assert = require('assert')
, expected = 0
;
var Benchmark = require('benchmark');
var suite = new Benchmark.Suite;
var source = [];
for (var z = 1; z < 100; z++)
{
source.push(z);
expected += z;
}
suite
// add tests
.add('async.map', function(deferred)
{
var total = 0;
async.map(source,
function(i, cb)
{
setImmediate(function()
{
total += i;
cb(null, total);
});
},
function(err, result)
{
assert.ifError(err);
assert.equal(result[result.length - 1], expected);
deferred.resolve();
});
}, {'defer': true})
.add('asynckit.parallel', function(deferred)
{
var total = 0;
asynckit.parallel(source,
function(i, cb)
{
setImmediate(function()
{
total += i;
cb(null, total);
});
},
function(err, result)
{
assert.ifError(err);
assert.equal(result[result.length - 1], expected);
deferred.resolve();
});
}, {'defer': true})
// add listeners
.on('cycle', function(ev)
{
console.log(String(ev.target));
})
.on('complete', function()
{
console.log('Fastest is ' + this.filter('fastest').map('name'));
})
// run async
.run({ 'async': true });

6
bot/node_modules/asynckit/index.js generated vendored Normal file
View File

@ -0,0 +1,6 @@
module.exports =
{
parallel : require('./parallel.js'),
serial : require('./serial.js'),
serialOrdered : require('./serialOrdered.js')
};

29
bot/node_modules/asynckit/lib/abort.js generated vendored Normal file
View File

@ -0,0 +1,29 @@
// API
module.exports = abort;
/**
* Aborts leftover active jobs
*
* @param {object} state - current state object
*/
function abort(state)
{
Object.keys(state.jobs).forEach(clean.bind(state));
// reset leftover jobs
state.jobs = {};
}
/**
* Cleans up leftover job by invoking abort function for the provided job id
*
* @this state
* @param {string|number} key - job id to abort
*/
function clean(key)
{
if (typeof this.jobs[key] == 'function')
{
this.jobs[key]();
}
}

34
bot/node_modules/asynckit/lib/async.js generated vendored Normal file
View File

@ -0,0 +1,34 @@
var defer = require('./defer.js');
// API
module.exports = async;
/**
* Runs provided callback asynchronously
* even if callback itself is not
*
* @param {function} callback - callback to invoke
* @returns {function} - augmented callback
*/
function async(callback)
{
var isAsync = false;
// check if async happened
defer(function() { isAsync = true; });
return function async_callback(err, result)
{
if (isAsync)
{
callback(err, result);
}
else
{
defer(function nextTick_callback()
{
callback(err, result);
});
}
};
}

26
bot/node_modules/asynckit/lib/defer.js generated vendored Normal file
View File

@ -0,0 +1,26 @@
module.exports = defer;
/**
* Runs provided function on next iteration of the event loop
*
* @param {function} fn - function to run
*/
function defer(fn)
{
var nextTick = typeof setImmediate == 'function'
? setImmediate
: (
typeof process == 'object' && typeof process.nextTick == 'function'
? process.nextTick
: null
);
if (nextTick)
{
nextTick(fn);
}
else
{
setTimeout(fn, 0);
}
}

75
bot/node_modules/asynckit/lib/iterate.js generated vendored Normal file
View File

@ -0,0 +1,75 @@
var async = require('./async.js')
, abort = require('./abort.js')
;
// API
module.exports = iterate;
/**
* Iterates over each job object
*
* @param {array|object} list - array or object (named list) to iterate over
* @param {function} iterator - iterator to run
* @param {object} state - current job status
* @param {function} callback - invoked when all elements processed
*/
function iterate(list, iterator, state, callback)
{
// store current index
var key = state['keyedList'] ? state['keyedList'][state.index] : state.index;
state.jobs[key] = runJob(iterator, key, list[key], function(error, output)
{
// don't repeat yourself
// skip secondary callbacks
if (!(key in state.jobs))
{
return;
}
// clean up jobs
delete state.jobs[key];
if (error)
{
// don't process rest of the results
// stop still active jobs
// and reset the list
abort(state);
}
else
{
state.results[key] = output;
}
// return salvaged results
callback(error, state.results);
});
}
/**
* Runs iterator over provided job element
*
* @param {function} iterator - iterator to invoke
* @param {string|number} key - key/index of the element in the list of jobs
* @param {mixed} item - job description
* @param {function} callback - invoked after iterator is done with the job
* @returns {function|mixed} - job abort function or something else
*/
function runJob(iterator, key, item, callback)
{
var aborter;
// allow shortcut if iterator expects only two arguments
if (iterator.length == 2)
{
aborter = iterator(item, async(callback));
}
// otherwise go with full three arguments
else
{
aborter = iterator(item, key, async(callback));
}
return aborter;
}

91
bot/node_modules/asynckit/lib/readable_asynckit.js generated vendored Normal file
View File

@ -0,0 +1,91 @@
var streamify = require('./streamify.js')
, defer = require('./defer.js')
;
// API
module.exports = ReadableAsyncKit;
/**
* Base constructor for all streams
* used to hold properties/methods
*/
function ReadableAsyncKit()
{
ReadableAsyncKit.super_.apply(this, arguments);
// list of active jobs
this.jobs = {};
// add stream methods
this.destroy = destroy;
this._start = _start;
this._read = _read;
}
/**
* Destroys readable stream,
* by aborting outstanding jobs
*
* @returns {void}
*/
function destroy()
{
if (this.destroyed)
{
return;
}
this.destroyed = true;
if (typeof this.terminator == 'function')
{
this.terminator();
}
}
/**
* Starts provided jobs in async manner
*
* @private
*/
function _start()
{
// first argument runner function
var runner = arguments[0]
// take away first argument
, args = Array.prototype.slice.call(arguments, 1)
// second argument - input data
, input = args[0]
// last argument - result callback
, endCb = streamify.callback.call(this, args[args.length - 1])
;
args[args.length - 1] = endCb;
// third argument - iterator
args[1] = streamify.iterator.call(this, args[1]);
// allow time for proper setup
defer(function()
{
if (!this.destroyed)
{
this.terminator = runner.apply(null, args);
}
else
{
endCb(null, Array.isArray(input) ? [] : {});
}
}.bind(this));
}
/**
* Implement _read to comply with Readable streams
* Doesn't really make sense for flowing object mode
*
* @private
*/
function _read()
{
}

25
bot/node_modules/asynckit/lib/readable_parallel.js generated vendored Normal file
View File

@ -0,0 +1,25 @@
var parallel = require('../parallel.js');
// API
module.exports = ReadableParallel;
/**
* Streaming wrapper to `asynckit.parallel`
*
* @param {array|object} list - array or object (named list) to iterate over
* @param {function} iterator - iterator to run
* @param {function} callback - invoked when all elements processed
* @returns {stream.Readable#}
*/
function ReadableParallel(list, iterator, callback)
{
if (!(this instanceof ReadableParallel))
{
return new ReadableParallel(list, iterator, callback);
}
// turn on object mode
ReadableParallel.super_.call(this, {objectMode: true});
this._start(parallel, list, iterator, callback);
}

25
bot/node_modules/asynckit/lib/readable_serial.js generated vendored Normal file
View File

@ -0,0 +1,25 @@
var serial = require('../serial.js');
// API
module.exports = ReadableSerial;
/**
* Streaming wrapper to `asynckit.serial`
*
* @param {array|object} list - array or object (named list) to iterate over
* @param {function} iterator - iterator to run
* @param {function} callback - invoked when all elements processed
* @returns {stream.Readable#}
*/
function ReadableSerial(list, iterator, callback)
{
if (!(this instanceof ReadableSerial))
{
return new ReadableSerial(list, iterator, callback);
}
// turn on object mode
ReadableSerial.super_.call(this, {objectMode: true});
this._start(serial, list, iterator, callback);
}

View File

@ -0,0 +1,29 @@
var serialOrdered = require('../serialOrdered.js');
// API
module.exports = ReadableSerialOrdered;
// expose sort helpers
module.exports.ascending = serialOrdered.ascending;
module.exports.descending = serialOrdered.descending;
/**
* Streaming wrapper to `asynckit.serialOrdered`
*
* @param {array|object} list - array or object (named list) to iterate over
* @param {function} iterator - iterator to run
* @param {function} sortMethod - custom sort function
* @param {function} callback - invoked when all elements processed
* @returns {stream.Readable#}
*/
function ReadableSerialOrdered(list, iterator, sortMethod, callback)
{
if (!(this instanceof ReadableSerialOrdered))
{
return new ReadableSerialOrdered(list, iterator, sortMethod, callback);
}
// turn on object mode
ReadableSerialOrdered.super_.call(this, {objectMode: true});
this._start(serialOrdered, list, iterator, sortMethod, callback);
}

37
bot/node_modules/asynckit/lib/state.js generated vendored Normal file
View File

@ -0,0 +1,37 @@
// API
module.exports = state;
/**
* Creates initial state object
* for iteration over list
*
* @param {array|object} list - list to iterate over
* @param {function|null} sortMethod - function to use for keys sort,
* or `null` to keep them as is
* @returns {object} - initial state object
*/
function state(list, sortMethod)
{
var isNamedList = !Array.isArray(list)
, initState =
{
index : 0,
keyedList: isNamedList || sortMethod ? Object.keys(list) : null,
jobs : {},
results : isNamedList ? {} : [],
size : isNamedList ? Object.keys(list).length : list.length
}
;
if (sortMethod)
{
// sort array keys based on it's values
// sort object's keys just on own merit
initState.keyedList.sort(isNamedList ? sortMethod : function(a, b)
{
return sortMethod(list[a], list[b]);
});
}
return initState;
}

141
bot/node_modules/asynckit/lib/streamify.js generated vendored Normal file
View File

@ -0,0 +1,141 @@
var async = require('./async.js');
// API
module.exports = {
iterator: wrapIterator,
callback: wrapCallback
};
/**
* Wraps iterators with long signature
*
* @this ReadableAsyncKit#
* @param {function} iterator - function to wrap
* @returns {function} - wrapped function
*/
function wrapIterator(iterator)
{
var stream = this;
return function(item, key, cb)
{
var aborter
, wrappedCb = async(wrapIteratorCallback.call(stream, cb, key))
;
stream.jobs[key] = wrappedCb;
// it's either shortcut (item, cb)
if (iterator.length == 2)
{
aborter = iterator(item, wrappedCb);
}
// or long format (item, key, cb)
else
{
aborter = iterator(item, key, wrappedCb);
}
return aborter;
};
}
/**
* Wraps provided callback function
* allowing to execute snitch function before
* real callback
*
* @this ReadableAsyncKit#
* @param {function} callback - function to wrap
* @returns {function} - wrapped function
*/
function wrapCallback(callback)
{
var stream = this;
var wrapped = function(error, result)
{
return finisher.call(stream, error, result, callback);
};
return wrapped;
}
/**
* Wraps provided iterator callback function
* makes sure snitch only called once,
* but passes secondary calls to the original callback
*
* @this ReadableAsyncKit#
* @param {function} callback - callback to wrap
* @param {number|string} key - iteration key
* @returns {function} wrapped callback
*/
function wrapIteratorCallback(callback, key)
{
var stream = this;
return function(error, output)
{
// don't repeat yourself
if (!(key in stream.jobs))
{
callback(error, output);
return;
}
// clean up jobs
delete stream.jobs[key];
return streamer.call(stream, error, {key: key, value: output}, callback);
};
}
/**
* Stream wrapper for iterator callback
*
* @this ReadableAsyncKit#
* @param {mixed} error - error response
* @param {mixed} output - iterator output
* @param {function} callback - callback that expects iterator results
*/
function streamer(error, output, callback)
{
if (error && !this.error)
{
this.error = error;
this.pause();
this.emit('error', error);
// send back value only, as expected
callback(error, output && output.value);
return;
}
// stream stuff
this.push(output);
// back to original track
// send back value only, as expected
callback(error, output && output.value);
}
/**
* Stream wrapper for finishing callback
*
* @this ReadableAsyncKit#
* @param {mixed} error - error response
* @param {mixed} output - iterator output
* @param {function} callback - callback that expects final results
*/
function finisher(error, output, callback)
{
// signal end of the stream
// only for successfully finished streams
if (!error)
{
this.push(null);
}
// back to original track
callback(error, output);
}

29
bot/node_modules/asynckit/lib/terminator.js generated vendored Normal file
View File

@ -0,0 +1,29 @@
var abort = require('./abort.js')
, async = require('./async.js')
;
// API
module.exports = terminator;
/**
* Terminates jobs in the attached state context
*
* @this AsyncKitState#
* @param {function} callback - final callback to invoke after termination
*/
function terminator(callback)
{
if (!Object.keys(this.jobs).length)
{
return;
}
// fast forward iteration index
this.index = this.size;
// abort jobs
abort(this);
// send back results we have so far
async(callback)(null, this.results);
}

63
bot/node_modules/asynckit/package.json generated vendored Normal file
View File

@ -0,0 +1,63 @@
{
"name": "asynckit",
"version": "0.4.0",
"description": "Minimal async jobs utility library, with streams support",
"main": "index.js",
"scripts": {
"clean": "rimraf coverage",
"lint": "eslint *.js lib/*.js test/*.js",
"test": "istanbul cover --reporter=json tape -- 'test/test-*.js' | tap-spec",
"win-test": "tape test/test-*.js",
"browser": "browserify -t browserify-istanbul test/lib/browserify_adjustment.js test/test-*.js | obake --coverage | tap-spec",
"report": "istanbul report",
"size": "browserify index.js | size-table asynckit",
"debug": "tape test/test-*.js"
},
"pre-commit": [
"clean",
"lint",
"test",
"browser",
"report",
"size"
],
"repository": {
"type": "git",
"url": "git+https://github.com/alexindigo/asynckit.git"
},
"keywords": [
"async",
"jobs",
"parallel",
"serial",
"iterator",
"array",
"object",
"stream",
"destroy",
"terminate",
"abort"
],
"author": "Alex Indigo <iam@alexindigo.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/alexindigo/asynckit/issues"
},
"homepage": "https://github.com/alexindigo/asynckit#readme",
"devDependencies": {
"browserify": "^13.0.0",
"browserify-istanbul": "^2.0.0",
"coveralls": "^2.11.9",
"eslint": "^2.9.0",
"istanbul": "^0.4.3",
"obake": "^0.1.2",
"phantomjs-prebuilt": "^2.1.7",
"pre-commit": "^1.1.3",
"reamde": "^1.1.0",
"rimraf": "^2.5.2",
"size-table": "^0.2.0",
"tap-spec": "^4.1.1",
"tape": "^4.5.1"
},
"dependencies": {}
}

43
bot/node_modules/asynckit/parallel.js generated vendored Normal file
View File

@ -0,0 +1,43 @@
var iterate = require('./lib/iterate.js')
, initState = require('./lib/state.js')
, terminator = require('./lib/terminator.js')
;
// Public API
module.exports = parallel;
/**
* Runs iterator over provided array elements in parallel
*
* @param {array|object} list - array or object (named list) to iterate over
* @param {function} iterator - iterator to run
* @param {function} callback - invoked when all elements processed
* @returns {function} - jobs terminator
*/
function parallel(list, iterator, callback)
{
var state = initState(list);
while (state.index < (state['keyedList'] || list).length)
{
iterate(list, iterator, state, function(error, result)
{
if (error)
{
callback(error, result);
return;
}
// looks like it's the last one
if (Object.keys(state.jobs).length === 0)
{
callback(null, state.results);
return;
}
});
state.index++;
}
return terminator.bind(state, callback);
}

17
bot/node_modules/asynckit/serial.js generated vendored Normal file
View File

@ -0,0 +1,17 @@
var serialOrdered = require('./serialOrdered.js');
// Public API
module.exports = serial;
/**
* Runs iterator over provided array elements in series
*
* @param {array|object} list - array or object (named list) to iterate over
* @param {function} iterator - iterator to run
* @param {function} callback - invoked when all elements processed
* @returns {function} - jobs terminator
*/
function serial(list, iterator, callback)
{
return serialOrdered(list, iterator, null, callback);
}

75
bot/node_modules/asynckit/serialOrdered.js generated vendored Normal file
View File

@ -0,0 +1,75 @@
var iterate = require('./lib/iterate.js')
, initState = require('./lib/state.js')
, terminator = require('./lib/terminator.js')
;
// Public API
module.exports = serialOrdered;
// sorting helpers
module.exports.ascending = ascending;
module.exports.descending = descending;
/**
* Runs iterator over provided sorted array elements in series
*
* @param {array|object} list - array or object (named list) to iterate over
* @param {function} iterator - iterator to run
* @param {function} sortMethod - custom sort function
* @param {function} callback - invoked when all elements processed
* @returns {function} - jobs terminator
*/
function serialOrdered(list, iterator, sortMethod, callback)
{
var state = initState(list, sortMethod);
iterate(list, iterator, state, function iteratorHandler(error, result)
{
if (error)
{
callback(error, result);
return;
}
state.index++;
// are we there yet?
if (state.index < (state['keyedList'] || list).length)
{
iterate(list, iterator, state, iteratorHandler);
return;
}
// done here
callback(null, state.results);
});
return terminator.bind(state, callback);
}
/*
* -- Sort methods
*/
/**
* sort helper to sort array elements in ascending order
*
* @param {mixed} a - an item to compare
* @param {mixed} b - an item to compare
* @returns {number} - comparison result
*/
function ascending(a, b)
{
return a < b ? -1 : a > b ? 1 : 0;
}
/**
* sort helper to sort array elements in descending order
*
* @param {mixed} a - an item to compare
* @param {mixed} b - an item to compare
* @returns {number} - comparison result
*/
function descending(a, b)
{
return -1 * ascending(a, b);
}

21
bot/node_modules/asynckit/stream.js generated vendored Normal file
View File

@ -0,0 +1,21 @@
var inherits = require('util').inherits
, Readable = require('stream').Readable
, ReadableAsyncKit = require('./lib/readable_asynckit.js')
, ReadableParallel = require('./lib/readable_parallel.js')
, ReadableSerial = require('./lib/readable_serial.js')
, ReadableSerialOrdered = require('./lib/readable_serial_ordered.js')
;
// API
module.exports =
{
parallel : ReadableParallel,
serial : ReadableSerial,
serialOrdered : ReadableSerialOrdered,
};
inherits(ReadableAsyncKit, Readable);
inherits(ReadableParallel, ReadableAsyncKit);
inherits(ReadableSerial, ReadableAsyncKit);
inherits(ReadableSerialOrdered, ReadableAsyncKit);

17
bot/node_modules/call-bind-apply-helpers/.eslintrc generated vendored Normal file
View File

@ -0,0 +1,17 @@
{
"root": true,
"extends": "@ljharb",
"rules": {
"func-name-matching": 0,
"id-length": 0,
"new-cap": [2, {
"capIsNewExceptions": [
"GetIntrinsic",
],
}],
"no-extra-parens": 0,
"no-magic-numbers": 0,
},
}

View File

@ -0,0 +1,12 @@
# These are supported funding model platforms
github: [ljharb]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: npm/call-bind-apply-helpers
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

9
bot/node_modules/call-bind-apply-helpers/.nycrc generated vendored Normal file
View File

@ -0,0 +1,9 @@
{
"all": true,
"check-coverage": false,
"reporter": ["text-summary", "text", "html", "json"],
"exclude": [
"coverage",
"test"
]
}

30
bot/node_modules/call-bind-apply-helpers/CHANGELOG.md generated vendored Normal file
View File

@ -0,0 +1,30 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [v1.0.2](https://github.com/ljharb/call-bind-apply-helpers/compare/v1.0.1...v1.0.2) - 2025-02-12
### Commits
- [types] improve inferred types [`e6f9586`](https://github.com/ljharb/call-bind-apply-helpers/commit/e6f95860a3c72879cb861a858cdfb8138fbedec1)
- [Dev Deps] update `@arethetypeswrong/cli`, `@ljharb/tsconfig`, `@types/tape`, `es-value-fixtures`, `for-each`, `has-strict-mode`, `object-inspect` [`e43d540`](https://github.com/ljharb/call-bind-apply-helpers/commit/e43d5409f97543bfbb11f345d47d8ce4e066d8c1)
## [v1.0.1](https://github.com/ljharb/call-bind-apply-helpers/compare/v1.0.0...v1.0.1) - 2024-12-08
### Commits
- [types] `reflectApply`: fix types [`4efc396`](https://github.com/ljharb/call-bind-apply-helpers/commit/4efc3965351a4f02cc55e836fa391d3d11ef2ef8)
- [Fix] `reflectApply`: oops, Reflect is not a function [`83cc739`](https://github.com/ljharb/call-bind-apply-helpers/commit/83cc7395de6b79b7730bdf092f1436f0b1263c75)
- [Dev Deps] update `@arethetypeswrong/cli` [`80bd5d3`](https://github.com/ljharb/call-bind-apply-helpers/commit/80bd5d3ae58b4f6b6995ce439dd5a1bcb178a940)
## v1.0.0 - 2024-12-05
### Commits
- Initial implementation, tests, readme [`7879629`](https://github.com/ljharb/call-bind-apply-helpers/commit/78796290f9b7430c9934d6f33d94ae9bc89fce04)
- Initial commit [`3f1dc16`](https://github.com/ljharb/call-bind-apply-helpers/commit/3f1dc164afc43285631b114a5f9dd9137b2b952f)
- npm init [`081df04`](https://github.com/ljharb/call-bind-apply-helpers/commit/081df048c312fcee400922026f6e97281200a603)
- Only apps should have lockfiles [`5b9ca0f`](https://github.com/ljharb/call-bind-apply-helpers/commit/5b9ca0fe8101ebfaf309c549caac4e0a017ed930)

21
bot/node_modules/call-bind-apply-helpers/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Jordan Harband
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

62
bot/node_modules/call-bind-apply-helpers/README.md generated vendored Normal file
View File

@ -0,0 +1,62 @@
# call-bind-apply-helpers <sup>[![Version Badge][npm-version-svg]][package-url]</sup>
[![github actions][actions-image]][actions-url]
[![coverage][codecov-image]][codecov-url]
[![dependency status][deps-svg]][deps-url]
[![dev dependency status][dev-deps-svg]][dev-deps-url]
[![License][license-image]][license-url]
[![Downloads][downloads-image]][downloads-url]
[![npm badge][npm-badge-png]][package-url]
Helper functions around Function call/apply/bind, for use in `call-bind`.
The only packages that should likely ever use this package directly are `call-bind` and `get-intrinsic`.
Please use `call-bind` unless you have a very good reason not to.
## Getting started
```sh
npm install --save call-bind-apply-helpers
```
## Usage/Examples
```js
const assert = require('assert');
const callBindBasic = require('call-bind-apply-helpers');
function f(a, b) {
assert.equal(this, 1);
assert.equal(a, 2);
assert.equal(b, 3);
assert.equal(arguments.length, 2);
}
const fBound = callBindBasic([f, 1]);
delete Function.prototype.call;
delete Function.prototype.bind;
fBound(2, 3);
```
## Tests
Clone the repo, `npm install`, and run `npm test`
[package-url]: https://npmjs.org/package/call-bind-apply-helpers
[npm-version-svg]: https://versionbadg.es/ljharb/call-bind-apply-helpers.svg
[deps-svg]: https://david-dm.org/ljharb/call-bind-apply-helpers.svg
[deps-url]: https://david-dm.org/ljharb/call-bind-apply-helpers
[dev-deps-svg]: https://david-dm.org/ljharb/call-bind-apply-helpers/dev-status.svg
[dev-deps-url]: https://david-dm.org/ljharb/call-bind-apply-helpers#info=devDependencies
[npm-badge-png]: https://nodei.co/npm/call-bind-apply-helpers.png?downloads=true&stars=true
[license-image]: https://img.shields.io/npm/l/call-bind-apply-helpers.svg
[license-url]: LICENSE
[downloads-image]: https://img.shields.io/npm/dm/call-bind-apply-helpers.svg
[downloads-url]: https://npm-stat.com/charts.html?package=call-bind-apply-helpers
[codecov-image]: https://codecov.io/gh/ljharb/call-bind-apply-helpers/branch/main/graphs/badge.svg
[codecov-url]: https://app.codecov.io/gh/ljharb/call-bind-apply-helpers/
[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/call-bind-apply-helpers
[actions-url]: https://github.com/ljharb/call-bind-apply-helpers/actions

View File

@ -0,0 +1 @@
export = Reflect.apply;

View File

@ -0,0 +1,10 @@
'use strict';
var bind = require('function-bind');
var $apply = require('./functionApply');
var $call = require('./functionCall');
var $reflectApply = require('./reflectApply');
/** @type {import('./actualApply')} */
module.exports = $reflectApply || bind.call($call, $apply);

View File

@ -0,0 +1,19 @@
import actualApply from './actualApply';
type TupleSplitHead<T extends any[], N extends number> = T['length'] extends N
? T
: T extends [...infer R, any]
? TupleSplitHead<R, N>
: never
type TupleSplitTail<T, N extends number, O extends any[] = []> = O['length'] extends N
? T
: T extends [infer F, ...infer R]
? TupleSplitTail<[...R], N, [...O, F]>
: never
type TupleSplit<T extends any[], N extends number> = [TupleSplitHead<T, N>, TupleSplitTail<T, N>]
declare function applyBind(...args: TupleSplit<Parameters<typeof actualApply>, 2>[1]): ReturnType<typeof actualApply>;
export = applyBind;

10
bot/node_modules/call-bind-apply-helpers/applyBind.js generated vendored Normal file
View File

@ -0,0 +1,10 @@
'use strict';
var bind = require('function-bind');
var $apply = require('./functionApply');
var actualApply = require('./actualApply');
/** @type {import('./applyBind')} */
module.exports = function applyBind() {
return actualApply(bind, $apply, arguments);
};

View File

@ -0,0 +1 @@
export = Function.prototype.apply;

View File

@ -0,0 +1,4 @@
'use strict';
/** @type {import('./functionApply')} */
module.exports = Function.prototype.apply;

View File

@ -0,0 +1 @@
export = Function.prototype.call;

View File

@ -0,0 +1,4 @@
'use strict';
/** @type {import('./functionCall')} */
module.exports = Function.prototype.call;

64
bot/node_modules/call-bind-apply-helpers/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,64 @@
type RemoveFromTuple<
Tuple extends readonly unknown[],
RemoveCount extends number,
Index extends 1[] = []
> = Index["length"] extends RemoveCount
? Tuple
: Tuple extends [infer First, ...infer Rest]
? RemoveFromTuple<Rest, RemoveCount, [...Index, 1]>
: Tuple;
type ConcatTuples<
Prefix extends readonly unknown[],
Suffix extends readonly unknown[]
> = [...Prefix, ...Suffix];
type ExtractFunctionParams<T> = T extends (this: infer TThis, ...args: infer P extends readonly unknown[]) => infer R
? { thisArg: TThis; params: P; returnType: R }
: never;
type BindFunction<
T extends (this: any, ...args: any[]) => any,
TThis,
TBoundArgs extends readonly unknown[],
ReceiverBound extends boolean
> = ExtractFunctionParams<T> extends {
thisArg: infer OrigThis;
params: infer P extends readonly unknown[];
returnType: infer R;
}
? ReceiverBound extends true
? (...args: RemoveFromTuple<P, Extract<TBoundArgs["length"], number>>) => R extends [OrigThis, ...infer Rest]
? [TThis, ...Rest] // Replace `this` with `thisArg`
: R
: <U, RemainingArgs extends RemoveFromTuple<P, Extract<TBoundArgs["length"], number>>>(
thisArg: U,
...args: RemainingArgs
) => R extends [OrigThis, ...infer Rest]
? [U, ...ConcatTuples<TBoundArgs, Rest>] // Preserve bound args in return type
: R
: never;
declare function callBind<
const T extends (this: any, ...args: any[]) => any,
Extracted extends ExtractFunctionParams<T>,
const TBoundArgs extends Partial<Extracted["params"]> & readonly unknown[],
const TThis extends Extracted["thisArg"]
>(
args: [fn: T, thisArg: TThis, ...boundArgs: TBoundArgs]
): BindFunction<T, TThis, TBoundArgs, true>;
declare function callBind<
const T extends (this: any, ...args: any[]) => any,
Extracted extends ExtractFunctionParams<T>,
const TBoundArgs extends Partial<Extracted["params"]> & readonly unknown[]
>(
args: [fn: T, ...boundArgs: TBoundArgs]
): BindFunction<T, Extracted["thisArg"], TBoundArgs, false>;
declare function callBind<const TArgs extends readonly unknown[]>(
args: [fn: Exclude<TArgs[0], Function>, ...rest: TArgs]
): never;
// export as namespace callBind;
export = callBind;

15
bot/node_modules/call-bind-apply-helpers/index.js generated vendored Normal file
View File

@ -0,0 +1,15 @@
'use strict';
var bind = require('function-bind');
var $TypeError = require('es-errors/type');
var $call = require('./functionCall');
var $actualApply = require('./actualApply');
/** @type {(args: [Function, thisArg?: unknown, ...args: unknown[]]) => Function} TODO FIXME, find a way to use import('.') */
module.exports = function callBindBasic(args) {
if (args.length < 1 || typeof args[0] !== 'function') {
throw new $TypeError('a function is required');
}
return $actualApply(bind, $call, args);
};

85
bot/node_modules/call-bind-apply-helpers/package.json generated vendored Normal file
View File

@ -0,0 +1,85 @@
{
"name": "call-bind-apply-helpers",
"version": "1.0.2",
"description": "Helper functions around Function call/apply/bind, for use in `call-bind`",
"main": "index.js",
"exports": {
".": "./index.js",
"./actualApply": "./actualApply.js",
"./applyBind": "./applyBind.js",
"./functionApply": "./functionApply.js",
"./functionCall": "./functionCall.js",
"./reflectApply": "./reflectApply.js",
"./package.json": "./package.json"
},
"scripts": {
"prepack": "npmignore --auto --commentLines=auto",
"prepublish": "not-in-publish || npm run prepublishOnly",
"prepublishOnly": "safe-publish-latest",
"prelint": "evalmd README.md",
"lint": "eslint --ext=.js,.mjs .",
"postlint": "tsc -p . && attw -P",
"pretest": "npm run lint",
"tests-only": "nyc tape 'test/**/*.js'",
"test": "npm run tests-only",
"posttest": "npx npm@'>=10.2' audit --production",
"version": "auto-changelog && git add CHANGELOG.md",
"postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\""
},
"repository": {
"type": "git",
"url": "git+https://github.com/ljharb/call-bind-apply-helpers.git"
},
"author": "Jordan Harband <ljharb@gmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/ljharb/call-bind-apply-helpers/issues"
},
"homepage": "https://github.com/ljharb/call-bind-apply-helpers#readme",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2"
},
"devDependencies": {
"@arethetypeswrong/cli": "^0.17.3",
"@ljharb/eslint-config": "^21.1.1",
"@ljharb/tsconfig": "^0.2.3",
"@types/for-each": "^0.3.3",
"@types/function-bind": "^1.1.10",
"@types/object-inspect": "^1.13.0",
"@types/tape": "^5.8.1",
"auto-changelog": "^2.5.0",
"encoding": "^0.1.13",
"es-value-fixtures": "^1.7.1",
"eslint": "=8.8.0",
"evalmd": "^0.0.19",
"for-each": "^0.3.5",
"has-strict-mode": "^1.1.0",
"in-publish": "^2.0.1",
"npmignore": "^0.3.1",
"nyc": "^10.3.2",
"object-inspect": "^1.13.4",
"safe-publish-latest": "^2.0.0",
"tape": "^5.9.0",
"typescript": "next"
},
"testling": {
"files": "test/index.js"
},
"auto-changelog": {
"output": "CHANGELOG.md",
"template": "keepachangelog",
"unreleased": false,
"commitLimit": false,
"backfillLimit": false,
"hideCredit": true
},
"publishConfig": {
"ignore": [
".github/workflows"
]
},
"engines": {
"node": ">= 0.4"
}
}

View File

@ -0,0 +1,3 @@
declare const reflectApply: false | typeof Reflect.apply;
export = reflectApply;

View File

@ -0,0 +1,4 @@
'use strict';
/** @type {import('./reflectApply')} */
module.exports = typeof Reflect !== 'undefined' && Reflect && Reflect.apply;

63
bot/node_modules/call-bind-apply-helpers/test/index.js generated vendored Normal file
View File

@ -0,0 +1,63 @@
'use strict';
var callBind = require('../');
var hasStrictMode = require('has-strict-mode')();
var forEach = require('for-each');
var inspect = require('object-inspect');
var v = require('es-value-fixtures');
var test = require('tape');
test('callBindBasic', function (t) {
forEach(v.nonFunctions, function (nonFunction) {
t['throws'](
// @ts-expect-error
function () { callBind([nonFunction]); },
TypeError,
inspect(nonFunction) + ' is not a function'
);
});
var sentinel = { sentinel: true };
/** @type {<T, A extends number, B extends number>(this: T, a: A, b: B) => [T | undefined, A, B]} */
var func = function (a, b) {
// eslint-disable-next-line no-invalid-this
return [!hasStrictMode && this === global ? undefined : this, a, b];
};
t.equal(func.length, 2, 'original function length is 2');
/** type {(thisArg: unknown, a: number, b: number) => [unknown, number, number]} */
var bound = callBind([func]);
/** type {((a: number, b: number) => [typeof sentinel, typeof a, typeof b])} */
var boundR = callBind([func, sentinel]);
/** type {((b: number) => [typeof sentinel, number, typeof b])} */
var boundArg = callBind([func, sentinel, /** @type {const} */ (1)]);
// @ts-expect-error
t.deepEqual(bound(), [undefined, undefined, undefined], 'bound func with no args');
// @ts-expect-error
t.deepEqual(func(), [undefined, undefined, undefined], 'unbound func with too few args');
// @ts-expect-error
t.deepEqual(bound(1, 2), [hasStrictMode ? 1 : Object(1), 2, undefined], 'bound func too few args');
// @ts-expect-error
t.deepEqual(boundR(), [sentinel, undefined, undefined], 'bound func with receiver, with too few args');
// @ts-expect-error
t.deepEqual(boundArg(), [sentinel, 1, undefined], 'bound func with receiver and arg, with too few args');
t.deepEqual(func(1, 2), [undefined, 1, 2], 'unbound func with right args');
t.deepEqual(bound(1, 2, 3), [hasStrictMode ? 1 : Object(1), 2, 3], 'bound func with right args');
t.deepEqual(boundR(1, 2), [sentinel, 1, 2], 'bound func with receiver, with right args');
t.deepEqual(boundArg(2), [sentinel, 1, 2], 'bound func with receiver and arg, with right arg');
// @ts-expect-error
t.deepEqual(func(1, 2, 3), [undefined, 1, 2], 'unbound func with too many args');
// @ts-expect-error
t.deepEqual(bound(1, 2, 3, 4), [hasStrictMode ? 1 : Object(1), 2, 3], 'bound func with too many args');
// @ts-expect-error
t.deepEqual(boundR(1, 2, 3), [sentinel, 1, 2], 'bound func with receiver, with too many args');
// @ts-expect-error
t.deepEqual(boundArg(2, 3), [sentinel, 1, 2], 'bound func with receiver and arg, with too many args');
t.end();
});

View File

@ -0,0 +1,9 @@
{
"extends": "@ljharb/tsconfig",
"compilerOptions": {
"target": "es2021",
},
"exclude": [
"coverage",
],
}

13
bot/node_modules/call-bound/.eslintrc generated vendored Normal file
View File

@ -0,0 +1,13 @@
{
"root": true,
"extends": "@ljharb",
"rules": {
"new-cap": [2, {
"capIsNewExceptions": [
"GetIntrinsic",
],
}],
},
}

12
bot/node_modules/call-bound/.github/FUNDING.yml generated vendored Normal file
View File

@ -0,0 +1,12 @@
# These are supported funding model platforms
github: [ljharb]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: npm/call-bound
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

9
bot/node_modules/call-bound/.nycrc generated vendored Normal file
View File

@ -0,0 +1,9 @@
{
"all": true,
"check-coverage": false,
"reporter": ["text-summary", "text", "html", "json"],
"exclude": [
"coverage",
"test"
]
}

42
bot/node_modules/call-bound/CHANGELOG.md generated vendored Normal file
View File

@ -0,0 +1,42 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [v1.0.4](https://github.com/ljharb/call-bound/compare/v1.0.3...v1.0.4) - 2025-03-03
### Commits
- [types] improve types [`e648922`](https://github.com/ljharb/call-bound/commit/e6489222a9e54f350fbf952ceabe51fd8b6027ff)
- [Dev Deps] update `@arethetypeswrong/cli`, `@ljharb/tsconfig`, `@types/tape`, `es-value-fixtures`, `for-each`, `has-strict-mode`, `object-inspect` [`a42a5eb`](https://github.com/ljharb/call-bound/commit/a42a5ebe6c1b54fcdc7997c7dc64fdca9e936719)
- [Deps] update `call-bind-apply-helpers`, `get-intrinsic` [`f529eac`](https://github.com/ljharb/call-bound/commit/f529eac132404c17156bbc23ab2297a25d0f20b8)
## [v1.0.3](https://github.com/ljharb/call-bound/compare/v1.0.2...v1.0.3) - 2024-12-15
### Commits
- [Refactor] use `call-bind-apply-helpers` instead of `call-bind` [`5e0b134`](https://github.com/ljharb/call-bound/commit/5e0b13496df14fb7d05dae9412f088da8d3f75be)
- [Deps] update `get-intrinsic` [`41fc967`](https://github.com/ljharb/call-bound/commit/41fc96732a22c7b7e8f381f93ccc54bb6293be2e)
- [readme] fix example [`79a0137`](https://github.com/ljharb/call-bound/commit/79a0137723f7c6d09c9c05452bbf8d5efb5d6e49)
- [meta] add `sideEffects` flag [`08b07be`](https://github.com/ljharb/call-bound/commit/08b07be7f1c03f67dc6f3cdaf0906259771859f7)
## [v1.0.2](https://github.com/ljharb/call-bound/compare/v1.0.1...v1.0.2) - 2024-12-10
### Commits
- [Dev Deps] update `@arethetypeswrong/cli`, `@ljharb/tsconfig`, `gopd` [`e6a5ffe`](https://github.com/ljharb/call-bound/commit/e6a5ffe849368fe4f74dfd6cdeca1b9baa39e8d5)
- [Deps] update `call-bind`, `get-intrinsic` [`2aeb5b5`](https://github.com/ljharb/call-bound/commit/2aeb5b521dc2b2683d1345c753ea1161de2d1c14)
- [types] improve return type [`1a0c9fe`](https://github.com/ljharb/call-bound/commit/1a0c9fe3114471e7ca1f57d104e2efe713bb4871)
## v1.0.1 - 2024-12-05
### Commits
- Initial implementation, tests, readme, types [`6d94121`](https://github.com/ljharb/call-bound/commit/6d94121a9243602e506334069f7a03189fe3363d)
- Initial commit [`0eae867`](https://github.com/ljharb/call-bound/commit/0eae867334ea025c33e6e91cdecfc9df96680cf9)
- npm init [`71b2479`](https://github.com/ljharb/call-bound/commit/71b2479c6723e0b7d91a6b663613067e98b7b275)
- Only apps should have lockfiles [`c3754a9`](https://github.com/ljharb/call-bound/commit/c3754a949b7f9132b47e2d18c1729889736741eb)
- [actions] skip `npm ls` in node &lt; 10 [`74275a5`](https://github.com/ljharb/call-bound/commit/74275a5186b8caf6309b6b97472bdcb0df4683a8)
- [Dev Deps] add missing peer dep [`1354de8`](https://github.com/ljharb/call-bound/commit/1354de8679413e4ae9c523d85f76fa7a5e032d97)

21
bot/node_modules/call-bound/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Jordan Harband
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

53
bot/node_modules/call-bound/README.md generated vendored Normal file
View File

@ -0,0 +1,53 @@
# call-bound <sup>[![Version Badge][npm-version-svg]][package-url]</sup>
[![github actions][actions-image]][actions-url]
[![coverage][codecov-image]][codecov-url]
[![dependency status][deps-svg]][deps-url]
[![dev dependency status][dev-deps-svg]][dev-deps-url]
[![License][license-image]][license-url]
[![Downloads][downloads-image]][downloads-url]
[![npm badge][npm-badge-png]][package-url]
Robust call-bound JavaScript intrinsics, using `call-bind` and `get-intrinsic`.
## Getting started
```sh
npm install --save call-bound
```
## Usage/Examples
```js
const assert = require('assert');
const callBound = require('call-bound');
const slice = callBound('Array.prototype.slice');
delete Function.prototype.call;
delete Function.prototype.bind;
delete Array.prototype.slice;
assert.deepEqual(slice([1, 2, 3, 4], 1, -1), [2, 3]);
```
## Tests
Clone the repo, `npm install`, and run `npm test`
[package-url]: https://npmjs.org/package/call-bound
[npm-version-svg]: https://versionbadg.es/ljharb/call-bound.svg
[deps-svg]: https://david-dm.org/ljharb/call-bound.svg
[deps-url]: https://david-dm.org/ljharb/call-bound
[dev-deps-svg]: https://david-dm.org/ljharb/call-bound/dev-status.svg
[dev-deps-url]: https://david-dm.org/ljharb/call-bound#info=devDependencies
[npm-badge-png]: https://nodei.co/npm/call-bound.png?downloads=true&stars=true
[license-image]: https://img.shields.io/npm/l/call-bound.svg
[license-url]: LICENSE
[downloads-image]: https://img.shields.io/npm/dm/call-bound.svg
[downloads-url]: https://npm-stat.com/charts.html?package=call-bound
[codecov-image]: https://codecov.io/gh/ljharb/call-bound/branch/main/graphs/badge.svg
[codecov-url]: https://app.codecov.io/gh/ljharb/call-bound/
[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/call-bound
[actions-url]: https://github.com/ljharb/call-bound/actions

94
bot/node_modules/call-bound/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,94 @@
type Intrinsic = typeof globalThis;
type IntrinsicName = keyof Intrinsic | `%${keyof Intrinsic}%`;
type IntrinsicPath = IntrinsicName | `${StripPercents<IntrinsicName>}.${string}` | `%${StripPercents<IntrinsicName>}.${string}%`;
type AllowMissing = boolean;
type StripPercents<T extends string> = T extends `%${infer U}%` ? U : T;
type BindMethodPrecise<F> =
F extends (this: infer This, ...args: infer Args) => infer R
? (obj: This, ...args: Args) => R
: F extends {
(this: infer This1, ...args: infer Args1): infer R1;
(this: infer This2, ...args: infer Args2): infer R2
}
? {
(obj: This1, ...args: Args1): R1;
(obj: This2, ...args: Args2): R2
}
: never
// Extract method type from a prototype
type GetPrototypeMethod<T extends keyof typeof globalThis, M extends string> =
(typeof globalThis)[T] extends { prototype: any }
? M extends keyof (typeof globalThis)[T]['prototype']
? (typeof globalThis)[T]['prototype'][M]
: never
: never
// Get static property/method
type GetStaticMember<T extends keyof typeof globalThis, P extends string> =
P extends keyof (typeof globalThis)[T] ? (typeof globalThis)[T][P] : never
// Type that maps string path to actual bound function or value with better precision
type BoundIntrinsic<S extends string> =
S extends `${infer Obj}.prototype.${infer Method}`
? Obj extends keyof typeof globalThis
? BindMethodPrecise<GetPrototypeMethod<Obj, Method & string>>
: unknown
: S extends `${infer Obj}.${infer Prop}`
? Obj extends keyof typeof globalThis
? GetStaticMember<Obj, Prop & string>
: unknown
: unknown
declare function arraySlice<T>(array: readonly T[], start?: number, end?: number): T[];
declare function arraySlice<T>(array: ArrayLike<T>, start?: number, end?: number): T[];
declare function arraySlice<T>(array: IArguments, start?: number, end?: number): T[];
// Special cases for methods that need explicit typing
interface SpecialCases {
'%Object.prototype.isPrototypeOf%': (thisArg: {}, obj: unknown) => boolean;
'%String.prototype.replace%': {
(str: string, searchValue: string | RegExp, replaceValue: string): string;
(str: string, searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string
};
'%Object.prototype.toString%': (obj: {}) => string;
'%Object.prototype.hasOwnProperty%': (obj: {}, v: PropertyKey) => boolean;
'%Array.prototype.slice%': typeof arraySlice;
'%Array.prototype.map%': <T, U>(array: readonly T[], callbackfn: (value: T, index: number, array: readonly T[]) => U, thisArg?: any) => U[];
'%Array.prototype.filter%': <T>(array: readonly T[], predicate: (value: T, index: number, array: readonly T[]) => unknown, thisArg?: any) => T[];
'%Array.prototype.indexOf%': <T>(array: readonly T[], searchElement: T, fromIndex?: number) => number;
'%Function.prototype.apply%': <T, A extends any[], R>(fn: (...args: A) => R, thisArg: any, args: A) => R;
'%Function.prototype.call%': <T, A extends any[], R>(fn: (...args: A) => R, thisArg: any, ...args: A) => R;
'%Function.prototype.bind%': <T, A extends any[], R>(fn: (...args: A) => R, thisArg: any, ...args: A) => (...remainingArgs: A) => R;
'%Promise.prototype.then%': {
<T, R>(promise: Promise<T>, onfulfilled: (value: T) => R | PromiseLike<R>): Promise<R>;
<T, R>(promise: Promise<T>, onfulfilled: ((value: T) => R | PromiseLike<R>) | undefined | null, onrejected: (reason: any) => R | PromiseLike<R>): Promise<R>;
};
'%RegExp.prototype.test%': (regexp: RegExp, str: string) => boolean;
'%RegExp.prototype.exec%': (regexp: RegExp, str: string) => RegExpExecArray | null;
'%Error.prototype.toString%': (error: Error) => string;
'%TypeError.prototype.toString%': (error: TypeError) => string;
'%String.prototype.split%': (
obj: unknown,
splitter: string | RegExp | {
[Symbol.split](string: string, limit?: number): string[];
},
limit?: number | undefined
) => string[];
}
/**
* Returns a bound function for a prototype method, or a value for a static property.
*
* @param name - The name of the intrinsic (e.g. 'Array.prototype.slice')
* @param {AllowMissing} [allowMissing] - Whether to allow missing intrinsics (default: false)
*/
declare function callBound<K extends keyof SpecialCases | StripPercents<keyof SpecialCases>, S extends IntrinsicPath>(name: K, allowMissing?: AllowMissing): SpecialCases[`%${StripPercents<K>}%`];
declare function callBound<K extends keyof SpecialCases | StripPercents<keyof SpecialCases>, S extends IntrinsicPath>(name: S, allowMissing?: AllowMissing): BoundIntrinsic<S>;
export = callBound;

19
bot/node_modules/call-bound/index.js generated vendored Normal file
View File

@ -0,0 +1,19 @@
'use strict';
var GetIntrinsic = require('get-intrinsic');
var callBindBasic = require('call-bind-apply-helpers');
/** @type {(thisArg: string, searchString: string, position?: number) => number} */
var $indexOf = callBindBasic([GetIntrinsic('%String.prototype.indexOf%')]);
/** @type {import('.')} */
module.exports = function callBoundIntrinsic(name, allowMissing) {
/* eslint no-extra-parens: 0 */
var intrinsic = /** @type {(this: unknown, ...args: unknown[]) => unknown} */ (GetIntrinsic(name, !!allowMissing));
if (typeof intrinsic === 'function' && $indexOf(name, '.prototype.') > -1) {
return callBindBasic(/** @type {const} */ ([intrinsic]));
}
return intrinsic;
};

99
bot/node_modules/call-bound/package.json generated vendored Normal file
View File

@ -0,0 +1,99 @@
{
"name": "call-bound",
"version": "1.0.4",
"description": "Robust call-bound JavaScript intrinsics, using `call-bind` and `get-intrinsic`.",
"main": "index.js",
"exports": {
".": "./index.js",
"./package.json": "./package.json"
},
"sideEffects": false,
"scripts": {
"prepack": "npmignore --auto --commentLines=auto",
"prepublish": "not-in-publish || npm run prepublishOnly",
"prepublishOnly": "safe-publish-latest",
"prelint": "evalmd README.md",
"lint": "eslint --ext=.js,.mjs .",
"postlint": "tsc -p . && attw -P",
"pretest": "npm run lint",
"tests-only": "nyc tape 'test/**/*.js'",
"test": "npm run tests-only",
"posttest": "npx npm@'>=10.2' audit --production",
"version": "auto-changelog && git add CHANGELOG.md",
"postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\""
},
"repository": {
"type": "git",
"url": "git+https://github.com/ljharb/call-bound.git"
},
"keywords": [
"javascript",
"ecmascript",
"es",
"js",
"callbind",
"callbound",
"call",
"bind",
"bound",
"call-bind",
"call-bound",
"function",
"es-abstract"
],
"author": "Jordan Harband <ljharb@gmail.com>",
"funding": {
"url": "https://github.com/sponsors/ljharb"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/ljharb/call-bound/issues"
},
"homepage": "https://github.com/ljharb/call-bound#readme",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"get-intrinsic": "^1.3.0"
},
"devDependencies": {
"@arethetypeswrong/cli": "^0.17.4",
"@ljharb/eslint-config": "^21.1.1",
"@ljharb/tsconfig": "^0.3.0",
"@types/call-bind": "^1.0.5",
"@types/get-intrinsic": "^1.2.3",
"@types/tape": "^5.8.1",
"auto-changelog": "^2.5.0",
"encoding": "^0.1.13",
"es-value-fixtures": "^1.7.1",
"eslint": "=8.8.0",
"evalmd": "^0.0.19",
"for-each": "^0.3.5",
"gopd": "^1.2.0",
"has-strict-mode": "^1.1.0",
"in-publish": "^2.0.1",
"npmignore": "^0.3.1",
"nyc": "^10.3.2",
"object-inspect": "^1.13.4",
"safe-publish-latest": "^2.0.0",
"tape": "^5.9.0",
"typescript": "next"
},
"testling": {
"files": "test/index.js"
},
"auto-changelog": {
"output": "CHANGELOG.md",
"template": "keepachangelog",
"unreleased": false,
"commitLimit": false,
"backfillLimit": false,
"hideCredit": true
},
"publishConfig": {
"ignore": [
".github/workflows"
]
},
"engines": {
"node": ">= 0.4"
}
}

61
bot/node_modules/call-bound/test/index.js generated vendored Normal file
View File

@ -0,0 +1,61 @@
'use strict';
var test = require('tape');
var callBound = require('../');
/** @template {true} T @template U @typedef {T extends U ? T : never} AssertType */
test('callBound', function (t) {
// static primitive
t.equal(callBound('Array.length'), Array.length, 'Array.length yields itself');
t.equal(callBound('%Array.length%'), Array.length, '%Array.length% yields itself');
// static non-function object
t.equal(callBound('Array.prototype'), Array.prototype, 'Array.prototype yields itself');
t.equal(callBound('%Array.prototype%'), Array.prototype, '%Array.prototype% yields itself');
t.equal(callBound('Array.constructor'), Array.constructor, 'Array.constructor yields itself');
t.equal(callBound('%Array.constructor%'), Array.constructor, '%Array.constructor% yields itself');
// static function
t.equal(callBound('Date.parse'), Date.parse, 'Date.parse yields itself');
t.equal(callBound('%Date.parse%'), Date.parse, '%Date.parse% yields itself');
// prototype primitive
t.equal(callBound('Error.prototype.message'), Error.prototype.message, 'Error.prototype.message yields itself');
t.equal(callBound('%Error.prototype.message%'), Error.prototype.message, '%Error.prototype.message% yields itself');
var x = callBound('Object.prototype.toString');
var y = callBound('%Object.prototype.toString%');
// prototype function
t.notEqual(x, Object.prototype.toString, 'Object.prototype.toString does not yield itself');
t.notEqual(y, Object.prototype.toString, '%Object.prototype.toString% does not yield itself');
t.equal(x(true), Object.prototype.toString.call(true), 'call-bound Object.prototype.toString calls into the original');
t.equal(y(true), Object.prototype.toString.call(true), 'call-bound %Object.prototype.toString% calls into the original');
t['throws'](
// @ts-expect-error
function () { callBound('does not exist'); },
SyntaxError,
'nonexistent intrinsic throws'
);
t['throws'](
// @ts-expect-error
function () { callBound('does not exist', true); },
SyntaxError,
'allowMissing arg still throws for unknown intrinsic'
);
t.test('real but absent intrinsic', { skip: typeof WeakRef !== 'undefined' }, function (st) {
st['throws'](
function () { callBound('WeakRef'); },
TypeError,
'real but absent intrinsic throws'
);
st.equal(callBound('WeakRef', true), undefined, 'allowMissing arg avoids exception');
st.end();
});
t.end();
});

10
bot/node_modules/call-bound/tsconfig.json generated vendored Normal file
View File

@ -0,0 +1,10 @@
{
"extends": "@ljharb/tsconfig",
"compilerOptions": {
"target": "ESNext",
"lib": ["es2024"],
},
"exclude": [
"coverage",
],
}

19
bot/node_modules/combined-stream/License generated vendored Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2011 Debuggable Limited <felix@debuggable.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

138
bot/node_modules/combined-stream/Readme.md generated vendored Normal file
View File

@ -0,0 +1,138 @@
# combined-stream
A stream that emits multiple other streams one after another.
**NB** Currently `combined-stream` works with streams version 1 only. There is ongoing effort to switch this library to streams version 2. Any help is welcome. :) Meanwhile you can explore other libraries that provide streams2 support with more or less compatibility with `combined-stream`.
- [combined-stream2](https://www.npmjs.com/package/combined-stream2): A drop-in streams2-compatible replacement for the combined-stream module.
- [multistream](https://www.npmjs.com/package/multistream): A stream that emits multiple other streams one after another.
## Installation
``` bash
npm install combined-stream
```
## Usage
Here is a simple example that shows how you can use combined-stream to combine
two files into one:
``` javascript
var CombinedStream = require('combined-stream');
var fs = require('fs');
var combinedStream = CombinedStream.create();
combinedStream.append(fs.createReadStream('file1.txt'));
combinedStream.append(fs.createReadStream('file2.txt'));
combinedStream.pipe(fs.createWriteStream('combined.txt'));
```
While the example above works great, it will pause all source streams until
they are needed. If you don't want that to happen, you can set `pauseStreams`
to `false`:
``` javascript
var CombinedStream = require('combined-stream');
var fs = require('fs');
var combinedStream = CombinedStream.create({pauseStreams: false});
combinedStream.append(fs.createReadStream('file1.txt'));
combinedStream.append(fs.createReadStream('file2.txt'));
combinedStream.pipe(fs.createWriteStream('combined.txt'));
```
However, what if you don't have all the source streams yet, or you don't want
to allocate the resources (file descriptors, memory, etc.) for them right away?
Well, in that case you can simply provide a callback that supplies the stream
by calling a `next()` function:
``` javascript
var CombinedStream = require('combined-stream');
var fs = require('fs');
var combinedStream = CombinedStream.create();
combinedStream.append(function(next) {
next(fs.createReadStream('file1.txt'));
});
combinedStream.append(function(next) {
next(fs.createReadStream('file2.txt'));
});
combinedStream.pipe(fs.createWriteStream('combined.txt'));
```
## API
### CombinedStream.create([options])
Returns a new combined stream object. Available options are:
* `maxDataSize`
* `pauseStreams`
The effect of those options is described below.
### combinedStream.pauseStreams = `true`
Whether to apply back pressure to the underlaying streams. If set to `false`,
the underlaying streams will never be paused. If set to `true`, the
underlaying streams will be paused right after being appended, as well as when
`delayedStream.pipe()` wants to throttle.
### combinedStream.maxDataSize = `2 * 1024 * 1024`
The maximum amount of bytes (or characters) to buffer for all source streams.
If this value is exceeded, `combinedStream` emits an `'error'` event.
### combinedStream.dataSize = `0`
The amount of bytes (or characters) currently buffered by `combinedStream`.
### combinedStream.append(stream)
Appends the given `stream` to the combinedStream object. If `pauseStreams` is
set to `true, this stream will also be paused right away.
`streams` can also be a function that takes one parameter called `next`. `next`
is a function that must be invoked in order to provide the `next` stream, see
example above.
Regardless of how the `stream` is appended, combined-stream always attaches an
`'error'` listener to it, so you don't have to do that manually.
Special case: `stream` can also be a String or Buffer.
### combinedStream.write(data)
You should not call this, `combinedStream` takes care of piping the appended
streams into itself for you.
### combinedStream.resume()
Causes `combinedStream` to start drain the streams it manages. The function is
idempotent, and also emits a `'resume'` event each time which usually goes to
the stream that is currently being drained.
### combinedStream.pause();
If `combinedStream.pauseStreams` is set to `false`, this does nothing.
Otherwise a `'pause'` event is emitted, this goes to the stream that is
currently being drained, so you can use it to apply back pressure.
### combinedStream.end();
Sets `combinedStream.writable` to false, emits an `'end'` event, and removes
all streams from the queue.
### combinedStream.destroy();
Same as `combinedStream.end()`, except it emits a `'close'` event instead of
`'end'`.
## License
combined-stream is licensed under the MIT license.

208
bot/node_modules/combined-stream/lib/combined_stream.js generated vendored Normal file
View File

@ -0,0 +1,208 @@
var util = require('util');
var Stream = require('stream').Stream;
var DelayedStream = require('delayed-stream');
module.exports = CombinedStream;
function CombinedStream() {
this.writable = false;
this.readable = true;
this.dataSize = 0;
this.maxDataSize = 2 * 1024 * 1024;
this.pauseStreams = true;
this._released = false;
this._streams = [];
this._currentStream = null;
this._insideLoop = false;
this._pendingNext = false;
}
util.inherits(CombinedStream, Stream);
CombinedStream.create = function(options) {
var combinedStream = new this();
options = options || {};
for (var option in options) {
combinedStream[option] = options[option];
}
return combinedStream;
};
CombinedStream.isStreamLike = function(stream) {
return (typeof stream !== 'function')
&& (typeof stream !== 'string')
&& (typeof stream !== 'boolean')
&& (typeof stream !== 'number')
&& (!Buffer.isBuffer(stream));
};
CombinedStream.prototype.append = function(stream) {
var isStreamLike = CombinedStream.isStreamLike(stream);
if (isStreamLike) {
if (!(stream instanceof DelayedStream)) {
var newStream = DelayedStream.create(stream, {
maxDataSize: Infinity,
pauseStream: this.pauseStreams,
});
stream.on('data', this._checkDataSize.bind(this));
stream = newStream;
}
this._handleErrors(stream);
if (this.pauseStreams) {
stream.pause();
}
}
this._streams.push(stream);
return this;
};
CombinedStream.prototype.pipe = function(dest, options) {
Stream.prototype.pipe.call(this, dest, options);
this.resume();
return dest;
};
CombinedStream.prototype._getNext = function() {
this._currentStream = null;
if (this._insideLoop) {
this._pendingNext = true;
return; // defer call
}
this._insideLoop = true;
try {
do {
this._pendingNext = false;
this._realGetNext();
} while (this._pendingNext);
} finally {
this._insideLoop = false;
}
};
CombinedStream.prototype._realGetNext = function() {
var stream = this._streams.shift();
if (typeof stream == 'undefined') {
this.end();
return;
}
if (typeof stream !== 'function') {
this._pipeNext(stream);
return;
}
var getStream = stream;
getStream(function(stream) {
var isStreamLike = CombinedStream.isStreamLike(stream);
if (isStreamLike) {
stream.on('data', this._checkDataSize.bind(this));
this._handleErrors(stream);
}
this._pipeNext(stream);
}.bind(this));
};
CombinedStream.prototype._pipeNext = function(stream) {
this._currentStream = stream;
var isStreamLike = CombinedStream.isStreamLike(stream);
if (isStreamLike) {
stream.on('end', this._getNext.bind(this));
stream.pipe(this, {end: false});
return;
}
var value = stream;
this.write(value);
this._getNext();
};
CombinedStream.prototype._handleErrors = function(stream) {
var self = this;
stream.on('error', function(err) {
self._emitError(err);
});
};
CombinedStream.prototype.write = function(data) {
this.emit('data', data);
};
CombinedStream.prototype.pause = function() {
if (!this.pauseStreams) {
return;
}
if(this.pauseStreams && this._currentStream && typeof(this._currentStream.pause) == 'function') this._currentStream.pause();
this.emit('pause');
};
CombinedStream.prototype.resume = function() {
if (!this._released) {
this._released = true;
this.writable = true;
this._getNext();
}
if(this.pauseStreams && this._currentStream && typeof(this._currentStream.resume) == 'function') this._currentStream.resume();
this.emit('resume');
};
CombinedStream.prototype.end = function() {
this._reset();
this.emit('end');
};
CombinedStream.prototype.destroy = function() {
this._reset();
this.emit('close');
};
CombinedStream.prototype._reset = function() {
this.writable = false;
this._streams = [];
this._currentStream = null;
};
CombinedStream.prototype._checkDataSize = function() {
this._updateDataSize();
if (this.dataSize <= this.maxDataSize) {
return;
}
var message =
'DelayedStream#maxDataSize of ' + this.maxDataSize + ' bytes exceeded.';
this._emitError(new Error(message));
};
CombinedStream.prototype._updateDataSize = function() {
this.dataSize = 0;
var self = this;
this._streams.forEach(function(stream) {
if (!stream.dataSize) {
return;
}
self.dataSize += stream.dataSize;
});
if (this._currentStream && this._currentStream.dataSize) {
this.dataSize += this._currentStream.dataSize;
}
};
CombinedStream.prototype._emitError = function(err) {
this._reset();
this.emit('error', err);
};

25
bot/node_modules/combined-stream/package.json generated vendored Normal file
View File

@ -0,0 +1,25 @@
{
"author": "Felix Geisendörfer <felix@debuggable.com> (http://debuggable.com/)",
"name": "combined-stream",
"description": "A stream that emits multiple other streams one after another.",
"version": "1.0.8",
"homepage": "https://github.com/felixge/node-combined-stream",
"repository": {
"type": "git",
"url": "git://github.com/felixge/node-combined-stream.git"
},
"main": "./lib/combined_stream",
"scripts": {
"test": "node test/run.js"
},
"engines": {
"node": ">= 0.8"
},
"dependencies": {
"delayed-stream": "~1.0.0"
},
"devDependencies": {
"far": "~0.0.7"
},
"license": "MIT"
}

17
bot/node_modules/combined-stream/yarn.lock generated vendored Normal file
View File

@ -0,0 +1,17 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
far@~0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/far/-/far-0.0.7.tgz#01c1fd362bcd26ce9cf161af3938aa34619f79a7"
dependencies:
oop "0.0.3"
oop@0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/oop/-/oop-0.0.3.tgz#70fa405a5650891a194fdc82ca68dad6dabf4401"

24
bot/node_modules/component-emitter/LICENSE generated vendored Normal file
View File

@ -0,0 +1,24 @@
(The MIT License)
Copyright (c) 2014 Component contributors <dev@component.io>
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

74
bot/node_modules/component-emitter/Readme.md generated vendored Normal file
View File

@ -0,0 +1,74 @@
# Emitter [![Build Status](https://travis-ci.org/component/emitter.png)](https://travis-ci.org/component/emitter)
Event emitter component.
## Installation
```
$ component install component/emitter
```
## API
### Emitter(obj)
The `Emitter` may also be used as a mixin. For example
a "plain" object may become an emitter, or you may
extend an existing prototype.
As an `Emitter` instance:
```js
var Emitter = require('emitter');
var emitter = new Emitter;
emitter.emit('something');
```
As a mixin:
```js
var Emitter = require('emitter');
var user = { name: 'tobi' };
Emitter(user);
user.emit('im a user');
```
As a prototype mixin:
```js
var Emitter = require('emitter');
Emitter(User.prototype);
```
### Emitter#on(event, fn)
Register an `event` handler `fn`.
### Emitter#once(event, fn)
Register a single-shot `event` handler `fn`,
removed immediately after it is invoked the
first time.
### Emitter#off(event, fn)
* Pass `event` and `fn` to remove a listener.
* Pass `event` to remove all listeners on that event.
* Pass nothing to remove all listeners on all events.
### Emitter#emit(event, ...)
Emit an `event` with variable option args.
### Emitter#listeners(event)
Return an array of callbacks, or an empty array.
### Emitter#hasListeners(event)
Check if this emitter has `event` handlers.
## License
MIT

175
bot/node_modules/component-emitter/index.js generated vendored Normal file
View File

@ -0,0 +1,175 @@
/**
* Expose `Emitter`.
*/
if (typeof module !== 'undefined') {
module.exports = Emitter;
}
/**
* Initialize a new `Emitter`.
*
* @api public
*/
function Emitter(obj) {
if (obj) return mixin(obj);
};
/**
* Mixin the emitter properties.
*
* @param {Object} obj
* @return {Object}
* @api private
*/
function mixin(obj) {
for (var key in Emitter.prototype) {
obj[key] = Emitter.prototype[key];
}
return obj;
}
/**
* Listen on the given `event` with `fn`.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
* @api public
*/
Emitter.prototype.on =
Emitter.prototype.addEventListener = function(event, fn){
this._callbacks = this._callbacks || {};
(this._callbacks['$' + event] = this._callbacks['$' + event] || [])
.push(fn);
return this;
};
/**
* Adds an `event` listener that will be invoked a single
* time then automatically removed.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
* @api public
*/
Emitter.prototype.once = function(event, fn){
function on() {
this.off(event, on);
fn.apply(this, arguments);
}
on.fn = fn;
this.on(event, on);
return this;
};
/**
* Remove the given callback for `event` or all
* registered callbacks.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
* @api public
*/
Emitter.prototype.off =
Emitter.prototype.removeListener =
Emitter.prototype.removeAllListeners =
Emitter.prototype.removeEventListener = function(event, fn){
this._callbacks = this._callbacks || {};
// all
if (0 == arguments.length) {
this._callbacks = {};
return this;
}
// specific event
var callbacks = this._callbacks['$' + event];
if (!callbacks) return this;
// remove all handlers
if (1 == arguments.length) {
delete this._callbacks['$' + event];
return this;
}
// remove specific handler
var cb;
for (var i = 0; i < callbacks.length; i++) {
cb = callbacks[i];
if (cb === fn || cb.fn === fn) {
callbacks.splice(i, 1);
break;
}
}
// Remove event specific arrays for event types that no
// one is subscribed for to avoid memory leak.
if (callbacks.length === 0) {
delete this._callbacks['$' + event];
}
return this;
};
/**
* Emit `event` with the given args.
*
* @param {String} event
* @param {Mixed} ...
* @return {Emitter}
*/
Emitter.prototype.emit = function(event){
this._callbacks = this._callbacks || {};
var args = new Array(arguments.length - 1)
, callbacks = this._callbacks['$' + event];
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
if (callbacks) {
callbacks = callbacks.slice(0);
for (var i = 0, len = callbacks.length; i < len; ++i) {
callbacks[i].apply(this, args);
}
}
return this;
};
/**
* Return array of callbacks for `event`.
*
* @param {String} event
* @return {Array}
* @api public
*/
Emitter.prototype.listeners = function(event){
this._callbacks = this._callbacks || {};
return this._callbacks['$' + event] || [];
};
/**
* Check if this emitter has `event` handlers.
*
* @param {String} event
* @return {Boolean}
* @api public
*/
Emitter.prototype.hasListeners = function(event){
return !! this.listeners(event).length;
};

28
bot/node_modules/component-emitter/package.json generated vendored Normal file
View File

@ -0,0 +1,28 @@
{
"name": "component-emitter",
"description": "Event emitter",
"version": "1.3.1",
"license": "MIT",
"funding": "https://github.com/sponsors/sindresorhus",
"devDependencies": {
"mocha": "*",
"should": "*"
},
"component": {
"scripts": {
"emitter/index.js": "index.js"
}
},
"main": "index.js",
"repository": {
"type": "git",
"url": "https://github.com/sindresorhus/component-emitter.git"
},
"scripts": {
"test": "make test"
},
"files": [
"index.js",
"LICENSE"
]
}

9
bot/node_modules/cookiejar/LICENSE generated vendored Normal file
View File

@ -0,0 +1,9 @@
The MIT License (MIT)
Copyright (c) 2013 Bradley Meck
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

281
bot/node_modules/cookiejar/cookiejar.js generated vendored Normal file
View File

@ -0,0 +1,281 @@
/* jshint node: true */
(function () {
"use strict";
function CookieAccessInfo(domain, path, secure, script) {
if (this instanceof CookieAccessInfo) {
this.domain = domain || undefined;
this.path = path || "/";
this.secure = !!secure;
this.script = !!script;
return this;
}
return new CookieAccessInfo(domain, path, secure, script);
}
CookieAccessInfo.All = Object.freeze(Object.create(null));
exports.CookieAccessInfo = CookieAccessInfo;
function Cookie(cookiestr, request_domain, request_path) {
if (cookiestr instanceof Cookie) {
return cookiestr;
}
if (this instanceof Cookie) {
this.name = null;
this.value = null;
this.expiration_date = Infinity;
this.path = String(request_path || "/");
this.explicit_path = false;
this.domain = request_domain || null;
this.explicit_domain = false;
this.secure = false; //how to define default?
this.noscript = false; //httponly
if (cookiestr) {
this.parse(cookiestr, request_domain, request_path);
}
return this;
}
return new Cookie(cookiestr, request_domain, request_path);
}
exports.Cookie = Cookie;
Cookie.prototype.toString = function toString() {
var str = [this.name + "=" + this.value];
if (this.expiration_date !== Infinity) {
str.push("expires=" + (new Date(this.expiration_date)).toGMTString());
}
if (this.domain) {
str.push("domain=" + this.domain);
}
if (this.path) {
str.push("path=" + this.path);
}
if (this.secure) {
str.push("secure");
}
if (this.noscript) {
str.push("httponly");
}
return str.join("; ");
};
Cookie.prototype.toValueString = function toValueString() {
return this.name + "=" + this.value;
};
var cookie_str_splitter = /[:](?=\s*[a-zA-Z0-9_\-]+\s*[=])/g;
Cookie.prototype.parse = function parse(str, request_domain, request_path) {
if (this instanceof Cookie) {
if ( str.length > 32768 ) {
console.warn("Cookie too long for parsing (>32768 characters)");
return;
}
var parts = str.split(";").filter(function (value) {
return !!value;
});
var i;
var pair = parts[0].match(/([^=]+)=([\s\S]*)/);
if (!pair) {
console.warn("Invalid cookie header encountered. Header: '"+str+"'");
return;
}
var key = pair[1];
var value = pair[2];
if ( typeof key !== 'string' || key.length === 0 || typeof value !== 'string' ) {
console.warn("Unable to extract values from cookie header. Cookie: '"+str+"'");
return;
}
this.name = key;
this.value = value;
for (i = 1; i < parts.length; i += 1) {
pair = parts[i].match(/([^=]+)(?:=([\s\S]*))?/);
key = pair[1].trim().toLowerCase();
value = pair[2];
switch (key) {
case "httponly":
this.noscript = true;
break;
case "expires":
this.expiration_date = value ?
Number(Date.parse(value)) :
Infinity;
break;
case "path":
this.path = value ?
value.trim() :
"";
this.explicit_path = true;
break;
case "domain":
this.domain = value ?
value.trim() :
"";
this.explicit_domain = !!this.domain;
break;
case "secure":
this.secure = true;
break;
}
}
if (!this.explicit_path) {
this.path = request_path || "/";
}
if (!this.explicit_domain) {
this.domain = request_domain;
}
return this;
}
return new Cookie().parse(str, request_domain, request_path);
};
Cookie.prototype.matches = function matches(access_info) {
if (access_info === CookieAccessInfo.All) {
return true;
}
if (this.noscript && access_info.script ||
this.secure && !access_info.secure ||
!this.collidesWith(access_info)) {
return false;
}
return true;
};
Cookie.prototype.collidesWith = function collidesWith(access_info) {
if ((this.path && !access_info.path) || (this.domain && !access_info.domain)) {
return false;
}
if (this.path && access_info.path.indexOf(this.path) !== 0) {
return false;
}
if (this.explicit_path && access_info.path.indexOf( this.path ) !== 0) {
return false;
}
var access_domain = access_info.domain && access_info.domain.replace(/^[\.]/,'');
var cookie_domain = this.domain && this.domain.replace(/^[\.]/,'');
if (cookie_domain === access_domain) {
return true;
}
if (cookie_domain) {
if (!this.explicit_domain) {
return false; // we already checked if the domains were exactly the same
}
var wildcard = access_domain.indexOf(cookie_domain);
if (wildcard === -1 || wildcard !== access_domain.length - cookie_domain.length) {
return false;
}
return true;
}
return true;
};
function CookieJar() {
var cookies, cookies_list, collidable_cookie;
if (this instanceof CookieJar) {
cookies = Object.create(null); //name: [Cookie]
this.setCookie = function setCookie(cookie, request_domain, request_path) {
var remove, i;
cookie = new Cookie(cookie, request_domain, request_path);
//Delete the cookie if the set is past the current time
remove = cookie.expiration_date <= Date.now();
if (cookies[cookie.name] !== undefined) {
cookies_list = cookies[cookie.name];
for (i = 0; i < cookies_list.length; i += 1) {
collidable_cookie = cookies_list[i];
if (collidable_cookie.collidesWith(cookie)) {
if (remove) {
cookies_list.splice(i, 1);
if (cookies_list.length === 0) {
delete cookies[cookie.name];
}
return false;
}
cookies_list[i] = cookie;
return cookie;
}
}
if (remove) {
return false;
}
cookies_list.push(cookie);
return cookie;
}
if (remove) {
return false;
}
cookies[cookie.name] = [cookie];
return cookies[cookie.name];
};
//returns a cookie
this.getCookie = function getCookie(cookie_name, access_info) {
var cookie, i;
cookies_list = cookies[cookie_name];
if (!cookies_list) {
return;
}
for (i = 0; i < cookies_list.length; i += 1) {
cookie = cookies_list[i];
if (cookie.expiration_date <= Date.now()) {
if (cookies_list.length === 0) {
delete cookies[cookie.name];
}
continue;
}
if (cookie.matches(access_info)) {
return cookie;
}
}
};
//returns a list of cookies
this.getCookies = function getCookies(access_info) {
var matches = [], cookie_name, cookie;
for (cookie_name in cookies) {
cookie = this.getCookie(cookie_name, access_info);
if (cookie) {
matches.push(cookie);
}
}
matches.toString = function toString() {
return matches.join(":");
};
matches.toValueString = function toValueString() {
return matches.map(function (c) {
return c.toValueString();
}).join('; ');
};
return matches;
};
return this;
}
return new CookieJar();
}
exports.CookieJar = CookieJar;
//returns list of cookies that were set correctly. Cookies that are expired and removed are not returned.
CookieJar.prototype.setCookies = function setCookies(cookies, request_domain, request_path) {
cookies = Array.isArray(cookies) ?
cookies :
cookies.split(cookie_str_splitter);
var successful = [],
i,
cookie;
cookies = cookies.map(function(item){
return new Cookie(item, request_domain, request_path);
});
for (i = 0; i < cookies.length; i += 1) {
cookie = cookies[i];
if (this.setCookie(cookie, request_domain, request_path)) {
successful.push(cookie);
}
}
return successful;
};
}());

26
bot/node_modules/cookiejar/package.json generated vendored Normal file
View File

@ -0,0 +1,26 @@
{
"name": "cookiejar",
"version": "2.1.4",
"author": {
"name": "bradleymeck"
},
"main": "cookiejar.js",
"description": "simple persistent cookiejar system",
"files": [
"cookiejar.js"
],
"license": "MIT",
"jshintConfig": {
"node": true
},
"scripts": {
"test": "node tests/test.js"
},
"repository": {
"type": "git",
"url": "https://github.com/bmeck/node-cookiejar.git"
},
"devDependencies": {
"jshint": "^2.9.4"
}
}

60
bot/node_modules/cookiejar/readme.md generated vendored Normal file
View File

@ -0,0 +1,60 @@
# CookieJar
[![NPM version](http://img.shields.io/npm/v/cookiejar.svg)](https://www.npmjs.org/package/cookiejar)
[![devDependency Status](https://david-dm.org/bmeck/node-cookiejar/dev-status.svg)](https://david-dm.org/bmeck/node-cookiejar?type=dev)
Simple robust cookie library
## Exports
### CookieAccessInfo(domain,path,secure,script)
class to determine matching qualities of a cookie
##### Properties
* String domain - domain to match
* String path - path to match
* Boolean secure - access is secure (ssl generally)
* Boolean script - access is from a script
### Cookie(cookiestr_or_cookie, request_domain, request_path)
It turns input into a Cookie (singleton if given a Cookie),
the `request_domain` argument is used to default the domain if it is not explicit in the cookie string,
the `request_path` argument is used to set the path if it is not explicit in a cookie String.
Explicit domains/paths will cascade, implied domains/paths must *exactly* match (see http://en.wikipedia.org/wiki/HTTP_cookie#Domain_and_Pat).
##### Properties
* String name - name of the cookie
* String value - string associated with the cookie
* String domain - domain to match (on a cookie a '.' at the start means a wildcard matching anything ending in the rest)
* Boolean explicit_domain - if the domain was explicitly set via the cookie string
* String path - base path to match (matches any path starting with this '/' is root)
* Boolean explicit_path - if the path was explicitly set via the cookie string
* Boolean noscript - if it should be kept from scripts
* Boolean secure - should it only be transmitted over secure means
* Number expiration_date - number of millis since 1970 at which this should be removed
##### Methods
* `String toString()` - the __set-cookie:__ string for this cookie
* `String toValueString()` - the __cookie:__ string for this cookie
* `Cookie parse(cookiestr, request_domain, request_path)` - parses the string onto this cookie or a new one if called directly
* `Boolean matches(access_info)` - returns true if the access_info allows retrieval of this cookie
* `Boolean collidesWith(cookie)` - returns true if the cookies cannot exist in the same space (domain and path match)
### CookieJar()
class to hold numerous cookies from multiple domains correctly
##### Methods
* `Cookie setCookie(cookie, request_domain, request_path)` - modify (or add if not already-existing) a cookie to the jar
* `Cookie[] setCookies(cookiestr_or_list, request_domain, request_path)` - modify (or add if not already-existing) a large number of cookies to the jar
* `Cookie getCookie(cookie_name,access_info)` - get a cookie with the name and access_info matching
* `Cookie[] getCookies(access_info)` - grab all cookies matching this access_info

158
bot/node_modules/dargs/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,158 @@
declare namespace dargs {
interface Options {
/**
Keys or regex of keys to exclude. Takes precedence over `includes`.
*/
excludes?: ReadonlyArray<string | RegExp>;
/**
Keys or regex of keys to include.
*/
includes?: ReadonlyArray<string | RegExp>;
/**
Maps keys in `input` to an aliased name. Matching keys are converted to arguments with a single dash (`-`) in front of the aliased key and the value in a separate array item. Keys are still affected by `includes` and `excludes`.
*/
aliases?: {[key: string]: string};
/**
Setting this to `false` makes it return the key and value as separate array items instead of using a `=` separator in one item. This can be useful for tools that doesn't support `--foo=bar` style flags.
@default true
@example
```
import dargs = require('dargs');
console.log(dargs({foo: 'bar'}, {useEquals: false}));
// [
// '--foo', 'bar'
// ]
```
*/
useEquals?: boolean;
/**
Make a single character option key `{a: true}` become a short flag `-a` instead of `--a`.
@default true
@example
```
import dargs = require('dargs');
console.log(dargs({a: true}));
//=> ['-a']
console.log(dargs({a: true}, {shortFlag: false}));
//=> ['--a']
```
*/
shortFlag?: boolean;
/**
Exclude `false` values. Can be useful when dealing with strict argument parsers that throw on unknown arguments like `--no-foo`.
@default false
*/
ignoreFalse?: boolean;
/**
By default, camel-cased keys will be hyphenated. Enabling this will bypass the conversion process.
@default false
@example
```
import dargs = require('dargs');
console.log(dargs({fooBar: 'baz'}));
//=> ['--foo-bar', 'baz']
console.log(dargs({fooBar: 'baz'}, {allowCamelCase: true}));
//=> ['--fooBar', 'baz']
```
*/
allowCamelCase?: boolean;
}
}
/**
Reverse [`minimist`](https://github.com/substack/minimist). Convert an object of options into an array of command-line arguments.
@param object - Object to convert to command-line arguments.
@example
```
import dargs = require('dargs');
const input = {
_: ['some', 'option'], // Values in '_' will be appended to the end of the generated argument list
'--': ['separated', 'option'], // Values in '--' will be put at the very end of the argument list after the escape option (`--`)
foo: 'bar',
hello: true, // Results in only the key being used
cake: false, // Prepends `no-` before the key
camelCase: 5, // CamelCase is slugged to `camel-case`
multiple: ['value', 'value2'], // Converted to multiple arguments
pieKind: 'cherry',
sad: ':('
};
const excludes = ['sad', /.*Kind$/]; // Excludes and includes accept regular expressions
const includes = ['camelCase', 'multiple', 'sad', /^pie.+/];
const aliases = {file: 'f'};
console.log(dargs(input, {excludes}));
// [
// '--foo=bar',
// '--hello',
// '--no-cake',
// '--camel-case=5',
// '--multiple=value',
// '--multiple=value2',
// 'some',
// 'option',
// '--',
// 'separated',
// 'option'
// ]
console.log(dargs(input, {excludes, includes}));
// [
// '--camel-case=5',
// '--multiple=value',
// '--multiple=value2'
// ]
console.log(dargs(input, {includes}));
// [
// '--camel-case=5',
// '--multiple=value',
// '--multiple=value2',
// '--pie-kind=cherry',
// '--sad=:('
// ]
console.log(dargs({
foo: 'bar',
hello: true,
file: 'baz'
}, {aliases}));
// [
// '--foo=bar',
// '--hello',
// '-f', 'baz'
// ]
```
*/
declare function dargs(
object: {
'--'?: string[];
_?: string[];
} & {[key: string]: string | boolean | number | readonly string[]},
options?: dargs.Options
): string[];
export = dargs;

120
bot/node_modules/dargs/index.js generated vendored Normal file
View File

@ -0,0 +1,120 @@
'use strict';
const match = (array, value) =>
array.some(x => (x instanceof RegExp ? x.test(value) : x === value));
const dargs = (object, options) => {
const arguments_ = [];
let extraArguments = [];
let separatedArguments = [];
options = {
useEquals: true,
shortFlag: true,
...options
};
const makeArguments = (key, value) => {
const prefix = options.shortFlag && key.length === 1 ? '-' : '--';
const theKey = (options.allowCamelCase ?
key :
key.replace(/[A-Z]/g, '-$&').toLowerCase());
key = prefix + theKey;
if (options.useEquals) {
arguments_.push(key + (value ? `=${value}` : ''));
} else {
arguments_.push(key);
if (value) {
arguments_.push(value);
}
}
};
const makeAliasArg = (key, value) => {
arguments_.push(`-${key}`);
if (value) {
arguments_.push(value);
}
};
for (let [key, value] of Object.entries(object)) {
let pushArguments = makeArguments;
if (Array.isArray(options.excludes) && match(options.excludes, key)) {
continue;
}
if (Array.isArray(options.includes) && !match(options.includes, key)) {
continue;
}
if (typeof options.aliases === 'object' && options.aliases[key]) {
key = options.aliases[key];
pushArguments = makeAliasArg;
}
if (key === '--') {
if (!Array.isArray(value)) {
throw new TypeError(
`Expected key \`--\` to be Array, got ${typeof value}`
);
}
separatedArguments = value;
continue;
}
if (key === '_') {
if (!Array.isArray(value)) {
throw new TypeError(
`Expected key \`_\` to be Array, got ${typeof value}`
);
}
extraArguments = value;
continue;
}
if (value === true) {
pushArguments(key, '');
}
if (value === false && !options.ignoreFalse) {
pushArguments(`no-${key}`);
}
if (typeof value === 'string') {
pushArguments(key, value);
}
if (typeof value === 'number' && !Number.isNaN(value)) {
pushArguments(key, String(value));
}
if (Array.isArray(value)) {
for (const arrayValue of value) {
pushArguments(key, arrayValue);
}
}
}
for (const argument of extraArguments) {
arguments_.push(String(argument));
}
if (separatedArguments.length > 0) {
arguments_.push('--');
}
for (const argument of separatedArguments) {
arguments_.push(String(argument));
}
return arguments_;
};
module.exports = dargs;

Some files were not shown because too many files have changed in this diff Show More