├── src ├── bwd │ ├── users_Schema.json │ └── guilds_Schema.json ├── index.js ├── commands │ ├── Music │ │ ├── leave.js │ │ ├── pause.js │ │ ├── restart.js │ │ ├── time.js │ │ ├── prune.js │ │ ├── resume.js │ │ ├── queue.js │ │ ├── add.js │ │ ├── playing.js │ │ ├── autoplay.js │ │ ├── remove.js │ │ ├── skip.js │ │ ├── join.js │ │ ├── volume.js │ │ └── play.js │ └── System │ │ ├── exec.js │ │ └── echo.js ├── lib │ ├── extensions │ │ └── SneyraGuild.js │ ├── structures │ │ ├── MusicCommand.js │ │ └── MusicManager.js │ └── util │ │ └── util.js ├── inhibitors │ └── requireMusic.js └── Sneyra.js ├── .gitignore ├── config.js.example ├── .eslintrc.json ├── .github └── FUNDING.yml ├── package.json ├── LICENSE ├── README.md └── yarn.lock /src/bwd/users_Schema.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | src/bwd/provider/ 3 | .vs/ 4 | config.js 5 | *.heapsnapshot 6 | *.log 7 | -------------------------------------------------------------------------------- /config.js.example: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | token: 'YOUR_BOT_TOKEN', 3 | GOOGLE_SEARCH: 'YOUR_YOUTUBE_API_SEARCH_TOKEN' 4 | }; 5 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "klasa", 3 | "rules": { 4 | "operator-linebreak": ["error", "before", { "overrides": { "+": "after" } }], 5 | "curly": ["error", "multi-or-nest", "consistent"], 6 | "id-length": "off", 7 | "no-bitwise": ["error", { "int32Hint": true }], 8 | "no-cond-assign": "off" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [kyranet] 4 | patreon: kyranet 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | custom: # Replace with a single custom sponsorship URL 9 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | const klasa = require('klasa'); 2 | 3 | module.exports = { 4 | 5 | // Export everything from Klasa 6 | ...klasa, 7 | 8 | // Lib/structures 9 | MusicCommand: require('./lib/structures/MusicCommand'), 10 | MusicManager: require('./lib/structures/MusicManager'), 11 | 12 | util: require('./lib/util/util'), 13 | 14 | config: require('../config'), 15 | 16 | // Export Klasa's util as klasaUtil 17 | klasaUtil: klasa.util 18 | }; 19 | -------------------------------------------------------------------------------- /src/commands/Music/leave.js: -------------------------------------------------------------------------------- 1 | const { MusicCommand } = require('../../index'); 2 | 3 | module.exports = class extends MusicCommand { 4 | 5 | constructor(...args) { 6 | super(...args, { 7 | description: 'Leaves the voice channel.', 8 | requireMusic: true 9 | }); 10 | } 11 | 12 | async run(msg) { 13 | await msg.guild.music.leave(); 14 | return msg.sendMessage(`Successfully left the voice channel ${msg.guild.me.voice.channel}`); 15 | } 16 | 17 | }; 18 | -------------------------------------------------------------------------------- /src/commands/Music/pause.js: -------------------------------------------------------------------------------- 1 | const { MusicCommand } = require('../../index'); 2 | 3 | module.exports = class extends MusicCommand { 4 | 5 | constructor(...args) { 6 | super(...args, { 7 | description: 'Pauses the current song.', 8 | requireMusic: true 9 | }); 10 | } 11 | 12 | async run(msg) { 13 | const { music } = msg.guild; 14 | if (!music.playing) throw 'I am not playing anything...'; 15 | 16 | music.pause(); 17 | return msg.sendMessage('⏸ Paused'); 18 | } 19 | 20 | }; 21 | -------------------------------------------------------------------------------- /src/commands/Music/restart.js: -------------------------------------------------------------------------------- 1 | const { MusicCommand } = require('../../index'); 2 | 3 | module.exports = class extends MusicCommand { 4 | 5 | constructor(...args) { 6 | super(...args, { 7 | permissionLevel: 6, 8 | description: 'Clears the music handler.' 9 | }); 10 | } 11 | 12 | async run(msg) { 13 | msg.guild.music.clear(); 14 | if (msg.guild.me.voice.channel) await msg.guild.me.voice.channel.leave(); 15 | return msg.sendMessage('Successfully restarted the music module.'); 16 | } 17 | 18 | }; 19 | -------------------------------------------------------------------------------- /src/commands/Music/time.js: -------------------------------------------------------------------------------- 1 | const { MusicCommand, util: { showSeconds } } = require('../../index'); 2 | 3 | module.exports = class extends MusicCommand { 4 | 5 | constructor(...args) { 6 | super(...args, { description: 'Check how much time is left for the song to end.' }); 7 | } 8 | 9 | async run(msg) { 10 | const { playing, remaining } = msg.guild.music; 11 | if (!playing) throw `Are you speaking to me? Because my deck is empty...`; 12 | return msg.sendMessage(`🕰 Time remaining: ${showSeconds(remaining)}`); 13 | } 14 | 15 | }; 16 | -------------------------------------------------------------------------------- /src/commands/Music/prune.js: -------------------------------------------------------------------------------- 1 | const { MusicCommand } = require('../../index'); 2 | 3 | module.exports = class extends MusicCommand { 4 | 5 | constructor(...args) { 6 | super(...args, { 7 | description: 'Prune the queue list.', 8 | requireMusic: true 9 | }); 10 | } 11 | 12 | async run(msg) { 13 | const { music } = msg.guild; 14 | 15 | if (music.voiceChannel.members.size > 4) 16 | if (!await msg.hasAtLeastPermissionLevel(5)) throw 'You can\'t execute this command when there are over 4 members. You must be at least a Dj Member.'; 17 | 18 | music.prune(); 19 | return msg.sendMessage(`🗑 Pruned ${music.queue.length}`); 20 | } 21 | 22 | }; 23 | -------------------------------------------------------------------------------- /src/commands/Music/resume.js: -------------------------------------------------------------------------------- 1 | const { MusicCommand } = require('../../index'); 2 | 3 | module.exports = class extends MusicCommand { 4 | 5 | constructor(...args) { 6 | super(...args, { 7 | description: 'Resumes the current song.', 8 | requireMusic: true 9 | }); 10 | } 11 | 12 | async run(msg) { 13 | if (msg.guild.music.idling) throw 'My deck is empty! Give me a disk first so I can lift the spirits in this room!'; 14 | if (msg.guild.music.playing) throw 'Is this song too silent, my friend? Because it is indeed... playing.'; 15 | 16 | msg.guild.music.resume(); 17 | return msg.sendMessage('▶ Resumed'); 18 | } 19 | 20 | }; 21 | -------------------------------------------------------------------------------- /src/lib/extensions/SneyraGuild.js: -------------------------------------------------------------------------------- 1 | const { Structures } = require('discord.js'); 2 | const MusicManager = require('../structures/MusicManager'); 3 | 4 | module.exports = Structures.extend('Guild', Guild => { 5 | /** 6 | * Sneyra's Extended Guild 7 | * @extends {Guild} 8 | */ 9 | class SneyraGuild extends Guild { 10 | 11 | /** 12 | * @param {...*} args Normal D.JS Guild args 13 | */ 14 | constructor(...args) { 15 | super(...args); 16 | 17 | /** 18 | * The MusicManager instance for this client 19 | * @since 2.0.0 20 | * @type {MusicManager} 21 | */ 22 | this.music = new MusicManager(this); 23 | } 24 | 25 | } 26 | 27 | return SneyraGuild; 28 | }); 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sneyra", 3 | "version": "2.0.1", 4 | "description": "Extension of Skyra - Music-only bot.", 5 | "main": "src/Sneyra.js", 6 | "scripts": { 7 | "test:lint": "eslint --fix src" 8 | }, 9 | "author": "kyraNET", 10 | "license": "MIT", 11 | "dependencies": { 12 | "discord.js": "github:discordjs/discord.js", 13 | "fs-nextra": "^0.4.5", 14 | "klasa": "github:dirigeants/klasa", 15 | "node-opus": "^0.3.2", 16 | "rethinkdbdash": "^2.3.31", 17 | "ytdl-core": "^0.29.7", 18 | "ytdl-core-discord": "^1.0.3" 19 | }, 20 | "devDependencies": { 21 | "eslint": "^6.4.0", 22 | "eslint-config-klasa": "github:dirigeants/klasa-lint" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/inhibitors/requireMusic.js: -------------------------------------------------------------------------------- 1 | const { Inhibitor } = require('klasa'); 2 | 3 | module.exports = class extends Inhibitor { 4 | 5 | constructor(...args) { 6 | super(...args, { spamProtection: true }); 7 | } 8 | 9 | async run(msg, cmd) { 10 | if (cmd.requireMusic !== true) return; 11 | 12 | if (msg.channel.type !== 'text') throw 'This command may be only executed in a server.'; 13 | 14 | if (!msg.member.voice.channel) throw 'You are not connected in a voice channel.'; 15 | if (!msg.guild.me.voice.channel) throw 'I am not connected in a voice channel.'; 16 | if (msg.member.voice.channel !== msg.guild.me.voice.channel) throw 'You must be in the same voice channel as me.'; 17 | } 18 | 19 | }; 20 | -------------------------------------------------------------------------------- /src/lib/structures/MusicCommand.js: -------------------------------------------------------------------------------- 1 | const { Command } = require('klasa'); 2 | 3 | class MusicCommand extends Command { 4 | 5 | constructor(client, store, file, core, { requireMusic = false, ...options }) { 6 | // By nature, music commands only run in VoiceChannels, which are in Guilds. 7 | if ('runIn' in options) options.runIn = ['text']; 8 | 9 | super(client, store, file, core, options); 10 | 11 | /** 12 | * Whether this command requires an active VoiceConnection or not 13 | * @since 1.0.0 14 | * @type {boolean} 15 | */ 16 | this.requireMusic = requireMusic; 17 | } 18 | 19 | } 20 | 21 | MusicCommand.YOUTUBE_REGEXP = /^(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/\S*(?:(?:\/e(?:mbed)?)?\/|watch\/?\?(?:\S*?&?v=))|youtu\.be\/)([\w-]{11})(?:[^\w-]|$)/; 22 | 23 | module.exports = MusicCommand; 24 | -------------------------------------------------------------------------------- /src/commands/System/exec.js: -------------------------------------------------------------------------------- 1 | const { Command, util: { exec, codeBlock } } = require('klasa'); 2 | 3 | module.exports = class extends Command { 4 | 5 | constructor(...args) { 6 | super(...args, { 7 | aliases: ['execute'], 8 | description: 'Execute commands in the terminal, use with EXTREME CAUTION.', 9 | guarded: true, 10 | permissionLevel: 10, 11 | usage: '' 12 | }); 13 | } 14 | 15 | async run(msg, [input]) { 16 | const result = await exec(input, { timeout: 'timeout' in msg.flags ? Number(msg.flags.timeout) : 60000 }) 17 | .catch(error => ({ stdout: null, stderr: error })); 18 | const output = result.stdout ? `**\`OUTPUT\`**${codeBlock('prolog', result.stdout)}` : ''; 19 | const outerr = result.stderr ? `**\`ERROR\`**${codeBlock('prolog', result.stderr)}` : ''; 20 | 21 | return msg.sendMessage([output, outerr].join('\n')); 22 | } 23 | 24 | }; 25 | -------------------------------------------------------------------------------- /src/commands/System/echo.js: -------------------------------------------------------------------------------- 1 | const { Command } = require('klasa'); 2 | 3 | module.exports = class extends Command { 4 | 5 | constructor(...args) { 6 | super(...args, { 7 | aliases: ['talk'], 8 | description: 'Make Sneyra talk in another channel.', 9 | permissionLevel: 10, 10 | usage: '[channel:channel] [message:string] [...]', 11 | usageDelim: ' ' 12 | }); 13 | } 14 | 15 | async run(msg, [channel = msg.channel, ...content]) { 16 | if (msg.deletable) msg.delete().catch(() => null); 17 | 18 | const attachment = msg.attachments.size > 0 ? msg.attachments.first().url : null; 19 | content = content.length ? content.join(' ') : ''; 20 | 21 | if (content.length === 0 && !attachment) throw 'I have no content nor attachment to send, please write something.'; 22 | 23 | const options = {}; 24 | if (attachment) options.files = [{ attachment }]; 25 | 26 | return channel.send(content, options); 27 | } 28 | 29 | }; 30 | -------------------------------------------------------------------------------- /src/commands/Music/queue.js: -------------------------------------------------------------------------------- 1 | const { MusicCommand, util: { showSeconds } } = require('../../index'); 2 | 3 | module.exports = class extends MusicCommand { 4 | 5 | constructor(...args) { 6 | super(...args, { description: 'Check the queue list.' }); 7 | } 8 | 9 | async run(msg) { 10 | const { next, queue, autoplay } = msg.guild.music; 11 | const output = []; 12 | for (let i = 0; i < Math.min(queue.length, 10); i++) { 13 | output[i] = [ 14 | `[__\`${String(i + 1).padStart(2, 0)}\`__] *${queue[i].title.replace(/\*/g, '\\*')}* requested by **${queue[i].requester.tag || queue[i].requester}**`, 15 | ` └── (${showSeconds(queue[i].seconds * 1000)})` 16 | ].join('\n'); 17 | } 18 | if (queue.length > 10) output.push(`\nShowing 10 songs of ${queue.length}`); 19 | else if (autoplay) output.push(`\n**AutoPlay**: <${next}>`); 20 | 21 | return msg.sendMessage(output.join('\n')); 22 | } 23 | 24 | }; 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2018 Kyra 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/Sneyra.js: -------------------------------------------------------------------------------- 1 | const { Client } = require('klasa'); 2 | const config = require('../config.js'); 3 | 4 | // Load custom structures 5 | require('./lib/extensions/SneyraGuild'); 6 | 7 | // Modify the permission levels 8 | Client.defaultPermissionLevels 9 | .add(5, (msg) => msg.member && msg.guild.settings.dj && msg.member.roles.has(msg.guild.settings.dj), { fetch: true }) 10 | .add(6, (msg) => msg.member 11 | && ((msg.guild.settings.administrator && msg.member.roles.has(msg.guild.settings.administrator)) 12 | || msg.member.permissions.has('MANAGE_GUILD')), { fetch: true }); 13 | 14 | new Client({ 15 | disabledEvents: [ 16 | 'GUILD_BAN_ADD', 17 | 'GUILD_BAN_REMOVE', 18 | 'TYPING_START', 19 | 'CHANNEL_PINS_UPDATE', 20 | 'PRESENCE_UPDATE', 21 | 'USER_UPDATE', 22 | 'MESSAGE_REACTION_ADD', 23 | 'MESSAGE_REACTION_REMOVE', 24 | 'MESSAGE_REACTION_REMOVE_ALL' 25 | ], 26 | commandEditing: true, 27 | console: { useColor: true, utc: true }, 28 | pieceDefaults: { commands: { deletable: true, promptLimit: 5, quotedStringSupport: true } }, 29 | prefix: 'm!', 30 | presence: { activity: { name: 'Sneyra, help', type: 'LISTENING' } }, 31 | regexPrefix: /^(hey )?sneyra(,|!)/i 32 | }).login(config.token); 33 | -------------------------------------------------------------------------------- /src/commands/Music/add.js: -------------------------------------------------------------------------------- 1 | const { MusicCommand, config: { GOOGLE_SEARCH } } = require('../../index'); 2 | const fetch = require('node-fetch'); 3 | const qs = require('querystring'); 4 | 5 | const URL = 'https://www.googleapis.com/youtube/v3/search?'; 6 | 7 | module.exports = class extends MusicCommand { 8 | 9 | constructor(...args) { 10 | super(...args, { 11 | description: 'Adds a song the the queue.', 12 | usage: '' 13 | }); 14 | } 15 | 16 | async run(msg, [url]) { 17 | const youtubeURL = await this.getURL(url); 18 | if (!youtubeURL) throw 'Not found.'; 19 | 20 | const { music } = msg.guild; 21 | const song = await music.add(msg.author, youtubeURL); 22 | 23 | return msg.sendMessage(`🎵 Added **${song.title}** to the queue 🎶`); 24 | } 25 | 26 | async getURL(url) { 27 | const id = MusicCommand.YOUTUBE_REGEXP.exec(url); 28 | if (id) return `https://youtu.be/${id[1]}`; 29 | 30 | const query = qs.stringify({ 31 | part: 'snippet', 32 | q: url, 33 | key: GOOGLE_SEARCH 34 | }); 35 | const { items } = await fetch(URL + query) 36 | .then(result => result.json()); 37 | 38 | const video = items.find(item => item.id.kind === 'youtube#video'); 39 | return video ? `https://youtu.be/${video.id.videoId}` : null; 40 | } 41 | 42 | }; 43 | -------------------------------------------------------------------------------- /src/commands/Music/playing.js: -------------------------------------------------------------------------------- 1 | const { MusicCommand, util: { splitText, showSeconds } } = require('../../index'); 2 | const { MessageEmbed } = require('discord.js'); 3 | const getInfo = require('util').promisify(require('ytdl-core').getInfo); 4 | 5 | module.exports = class extends MusicCommand { 6 | 7 | constructor(...args) { 8 | super(...args, { description: 'Get information from the current song.' }); 9 | } 10 | 11 | async run(msg) { 12 | const { remaining, queue, playing } = msg.guild.music; 13 | if (!playing) throw `Are you speaking to me? Because my deck is empty...`; 14 | 15 | const [song] = queue; 16 | const info = await getInfo(song.url); 17 | if (!info.author) info.author = {}; 18 | 19 | return msg.sendMessage(new MessageEmbed() 20 | .setColor(12916736) 21 | .setTitle(info.title) 22 | .setURL(`https://youtu.be/${info.vid}`) 23 | .setAuthor(info.author.name || 'Unknown', info.author.avatar || null, info.author.channel_url || null) 24 | .setDescription([ 25 | `**Duration**: ${showSeconds(parseInt(info.length_seconds) * 1000)} [Time remaining: ${showSeconds(remaining)}]`, 26 | `**Description**: ${splitText(info.description, 500)}` 27 | ].join('\n\n')) 28 | .setThumbnail(info.thumbnail_url) 29 | .setTimestamp()); 30 | } 31 | 32 | }; 33 | -------------------------------------------------------------------------------- /src/commands/Music/autoplay.js: -------------------------------------------------------------------------------- 1 | const { MusicCommand } = require('../../index'); 2 | 3 | module.exports = class extends MusicCommand { 4 | 5 | constructor(...args) { 6 | super(...args, { 7 | description: 'Toggle the autoplayer.', 8 | extendedHelp: [ 9 | 'NOTE! This command does not make Sneyra play a song from the nowhere, it tells her whether to play the first', 10 | 'non-duplicated (in a range of 10 songs) song from the related videos she has fetched in the latest added song.', 11 | 'That is to say, Sneyra receives a list of 10-15 related songs, she also saves the 10 previous played songs. If', 12 | 'the song has already been played, it will be skipped and check the next, until finding a song that has not been', 13 | 'played recently. This allows two things:\n- 1: Play music unlimitedly without playing the same song twice.\n- 2:', 14 | 'Find new songs from YouTube.' 15 | ].join(' '), 16 | requireMusic: true 17 | }); 18 | } 19 | 20 | async run(msg) { 21 | const { music } = msg.guild; 22 | const enabled = !music.autoplay; 23 | 24 | music.autoplay = enabled; 25 | 26 | return msg.sendMessage(enabled 27 | ? `Sure thing! I'll keep playing decks until you get bored!` 28 | : `I stopped auto-playing songs, just make sure to give me some songs later!`); 29 | } 30 | 31 | }; 32 | -------------------------------------------------------------------------------- /src/bwd/guilds_Schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "Folder", 3 | "administrator": { 4 | "type": "role", 5 | "array": false, 6 | "default": null, 7 | "min": null, 8 | "max": null, 9 | "sql": "TEXT", 10 | "configurable": true 11 | }, 12 | "disabledCommands": { 13 | "type": "command", 14 | "array": true, 15 | "default": [], 16 | "min": null, 17 | "max": null, 18 | "sql": "TEXT DEFAULT '[]'", 19 | "configurable": true 20 | }, 21 | "dj": { 22 | "type": "role", 23 | "array": false, 24 | "default": null, 25 | "min": null, 26 | "max": null, 27 | "sql": "TEXT", 28 | "configurable": true 29 | }, 30 | "language": { 31 | "type": "language", 32 | "array": false, 33 | "default": "en-US", 34 | "min": null, 35 | "max": null, 36 | "sql": "VARCHAR(5) NOT NULL DEFAULT 'en-US'", 37 | "configurable": true 38 | }, 39 | "prefix": { 40 | "type": "string", 41 | "array": false, 42 | "default": "m!", 43 | "min": 1, 44 | "max": 10, 45 | "sql": "VARCHAR(10) NOT NULL DEFAULT 'm!'", 46 | "configurable": true 47 | }, 48 | "management": { 49 | "type": "Folder", 50 | "embedReply": { 51 | "type": "boolean", 52 | "array": false, 53 | "default": false, 54 | "min": null, 55 | "max": null, 56 | "sql": "TEXT DEFAULT false", 57 | "configurable": true 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/commands/Music/remove.js: -------------------------------------------------------------------------------- 1 | const { MusicCommand } = require('../../index'); 2 | 3 | module.exports = class extends MusicCommand { 4 | 5 | constructor(...args) { 6 | super(...args, { 7 | usage: '', 8 | description: 'Remove a song from the queue list.', 9 | requireMusic: true 10 | }); 11 | } 12 | 13 | async run(msg, [number]) { 14 | if (number <= 0) throw 'Look, I am no expert in maths, but I kinda expected a number equal or bigger than 1...'; 15 | number--; 16 | 17 | const { music } = msg.guild; 18 | if (music.queue.length < number) throw `I tried getting that song for you, but I only have ${music.queue.length} songs in my deck!`; 19 | 20 | const song = music.queue[number]; 21 | if (song.requester.id !== msg.author.id) 22 | if (!await msg.hasAtLeastPermissionLevel(5)) throw DENIED_SONG_REMOVAL; 23 | 24 | music.queue.splice(number, 1); 25 | return msg.sendMessage(`🗑 Removed the song **${song.title}** requested by **${song.requester}**.`); 26 | } 27 | 28 | }; 29 | 30 | // The next line is too long to fit above 31 | const DENIED_SONG_REMOVAL = [ 32 | 'I find it a bit rude to remove somebody else\'s songs from the list... Talk with them kindly, or', 33 | 'shout at a DJ if there is one in this guild, if it ruins the party, then they may consider to remove it!' 34 | ].join(' '); 35 | -------------------------------------------------------------------------------- /src/lib/util/util.js: -------------------------------------------------------------------------------- 1 | const SECOND = 1000; 2 | const MINUTE = SECOND * 60; 3 | const HOUR = MINUTE * 60; 4 | 5 | class Util { 6 | 7 | /** 8 | * Split a string by its latest space character in a range from the character 0 to the selected one. 9 | * @param {string} str The text to split. 10 | * @param {number} length The length of the desired string. 11 | * @returns {string} 12 | * @static 13 | */ 14 | static splitText(str, length) { 15 | const x = str.substring(0, length).lastIndexOf(' '); 16 | const pos = x === -1 ? length : x; 17 | return str.substring(0, pos); 18 | } 19 | 20 | /** 21 | * Show time duration in an un-trimmed h:mm:ss format. 22 | * @param {number} duration Duration in milliseconds. 23 | * @returns {string} 24 | */ 25 | static showSeconds(duration) { 26 | const seconds = Math.floor(duration / SECOND) % 60; 27 | if (duration < MINUTE) return seconds === 1 ? 'a second' : `${seconds} seconds`; 28 | 29 | const minutes = Math.floor(duration / MINUTE) % 60; 30 | let output = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; 31 | if (duration >= HOUR) { 32 | const hours = Math.floor(duration / HOUR); 33 | output = `${hours.toString().padStart(2, '0')}:${output}`; 34 | } 35 | 36 | return output; 37 | } 38 | 39 | } 40 | 41 | module.exports = Util; 42 | -------------------------------------------------------------------------------- /src/commands/Music/skip.js: -------------------------------------------------------------------------------- 1 | const { MusicCommand } = require('../../index'); 2 | 3 | module.exports = class extends MusicCommand { 4 | 5 | constructor(...args) { 6 | super(...args, { 7 | usage: '[force]', 8 | description: 'Skip the current song.', 9 | requireMusic: true 10 | }); 11 | } 12 | 13 | async run(msg, [force]) { 14 | const { music } = msg.guild; 15 | 16 | if (music.queue.length < 1) throw '`❌` | No Songs in the queue to skip!'; 17 | if (music.voiceChannel.members.size > 4) { 18 | if (force) { 19 | if (!await msg.hasAtLeastPermissionLevel(5)) throw 'You can\'t execute this command with the force flag. You must be at least a Moderator Member.'; 20 | } else { 21 | const response = this.handleSkips(music, msg.author.id); 22 | if (response) return msg.sendMessage(response); 23 | } 24 | } 25 | 26 | await msg.sendMessage(`⏭ Skipped ${music.queue[0].title}`); 27 | music.skip(true); 28 | return null; 29 | } 30 | 31 | handleSkips(musicInterface, user) { 32 | if (!musicInterface.queue[0].skips) musicInterface.queue[0].skips = new Set(); 33 | if (musicInterface.queue[0].skips.has(user)) return 'You have already voted to skip this song.'; 34 | musicInterface.queue[0].skips.add(user); 35 | const members = musicInterface.voiceChannel.members.size - 1; 36 | return this.shouldInhibit(members, musicInterface.queue[0].skips.size); 37 | } 38 | 39 | shouldInhibit(total, size) { 40 | if (total <= 3) return true; 41 | return size >= total * 0.4 ? false : `🔸 | Votes: ${size} of ${Math.ceil(total * 0.4)}`; 42 | } 43 | 44 | }; 45 | -------------------------------------------------------------------------------- /src/commands/Music/join.js: -------------------------------------------------------------------------------- 1 | const { MusicCommand } = require('../../index'); 2 | const { Permissions: { FLAGS } } = require('discord.js'); 3 | 4 | module.exports = class extends MusicCommand { 5 | 6 | constructor(...args) { 7 | super(...args, { 8 | aliases: ['connect'], 9 | description: 'Joins the message author\'s voice channel.' 10 | }); 11 | } 12 | 13 | async run(msg) { 14 | if (!msg.member) { 15 | await msg.guild.members.fetch(msg.author.id).catch(() => { 16 | throw 'I am sorry, but Discord did not tell me the information I need, so I do not know what voice channel are you connected to...'; 17 | }); 18 | } 19 | 20 | const voiceChannel = msg.member.voice.channel; 21 | if (!voiceChannel) throw 'You are not connected in a voice channel.'; 22 | if (msg.guild.music.playing) { 23 | const sneyraVoiceChannel = msg.guild.music.voice.channel; 24 | if (voiceChannel.id === sneyraVoiceChannel.id) throw 'Turn on your volume! I am playing music there!'; 25 | throw 'I am sorry, but I am playing music in another channel, perhaps try later or ask nicely to the people who came first to join them!'; 26 | } 27 | this.resolvePermissions(msg, voiceChannel); 28 | 29 | await msg.guild.music.join(voiceChannel); 30 | return msg.sendMessage(`Successfully joined the voice channel ${voiceChannel}`); 31 | } 32 | 33 | resolvePermissions(msg, voiceChannel) { 34 | if (voiceChannel.full) throw 'I cannot join your voice channel, it\'s full... kick somebody with the boot or make room for me!'; 35 | 36 | const permissions = voiceChannel.permissionsFor(msg.guild.me); 37 | if (!permissions.has(FLAGS.CONNECT)) throw 'I do not have enough permissions to connect to your voice channel. I am missing the CONNECT permission.'; 38 | if (!permissions.has(FLAGS.SPEAK)) throw 'I can connect... but not speak. Please turn on this permission so I can emit music.'; 39 | } 40 | 41 | }; 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sneyra 2 | 3 | Sneyra is a music bot (yeah, another bot in this world) built on top of [Klasa](https://github.com/dirigeants/klasa/), and uses [Discord.js](https://github.com/hydrabolt/discord.js) to connect to the Discord API. 4 | 5 | For a most advanced version in TypeScript, please check out [Aelia]. 6 | 7 | [Aelia]: https://github.com/kyranet/Aelia 8 | 9 | ## Features 10 | 11 | - All basic music bot commands, included skip prompting (based on the 40% of users connected to the voice channel, after 4 users). 12 | - An echo command, because, why not? 13 | - Clean code, easy to modify. Fully modular and classbased. 14 | - Full Music Handler interface and caching, make sure she replies 'smartly'! 15 | 16 | ## Requirements 17 | 18 | - `git` command line ([Windows](https://git-scm.com/download/win)|[Linux](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)|[MacOS](https://git-scm.com/download/mac)) installed 19 | - `node` [Version 8.1.0 or higher](https://nodejs.org) 20 | - `ffmpeg`: `npm install --global ffmpeg-binaries` 21 | - `node-opus`: `npm install node-opus` (alternatively you can use opusscript, but it's very bad for production, has memoryleaks and stream/quality issues). 22 | - A **good** network connection. 23 | 24 | ## Downloading 25 | 26 | In a command prompt in your projects folder (wherever that may be) run the following: 27 | 28 | ``` 29 | git clone https://github.com/kyranet/Sneyra 30 | ``` 31 | 32 | Once finished: 33 | 34 | - In the folder from where you ran the git command, run `cd Sneyra` and then run `npm install` 35 | - Rename `config.json.example` to `config.json` 36 | - Edit `config.json` and enter your bot token and the YouTube Search API token. 37 | - **NEVER UPLOAD THIS FILE WITH YOUR TOKENS ANYWHERE, TO DO SO, YOU ARE LETTING OTHER PEOPLE USE THE TOKEN TO DESTROY ALL THE GUILDS YOUR BOT IS IN. IF YOU DID, RESET YOUR TOKEN IN DISCORD'S APPLICATION PAGE**. 38 | -------------------------------------------------------------------------------- /src/commands/Music/volume.js: -------------------------------------------------------------------------------- 1 | const { MusicCommand, klasaUtil: { codeBlock } } = require('../../index'); 2 | 3 | module.exports = class extends MusicCommand { 4 | 5 | constructor(...args) { 6 | super(...args, { 7 | // Disabled until Krypton lands stable 8 | enabled: false, 9 | aliases: ['vol'], 10 | usage: '[control:string]', 11 | description: 'Manage the volume for current song.', 12 | extendedHelp: [ 13 | "Let's break it down!", 14 | '', 15 | "Listen carefully, you use this command by doing either 'volume ++++' or 'volume ----'.", 16 | "The more '+' you write, the more the volume will increment.", 17 | "The more '-' you write, the more the volume will decrease.", 18 | '', 19 | '👌' 20 | ].join('\n'), 21 | requireMusic: true 22 | }); 23 | } 24 | 25 | async run(msg, [vol]) { 26 | const { dispatcher, playing } = msg.guild.music; 27 | if (!playing) throw `The party isn't going on! One shouldn't touch the volume wheel without a song first!`; 28 | 29 | if (!vol) return msg.sendMessage(`📢 Volume: ${Math.round(dispatcher.volume * 50)}%`); 30 | if (/^[+]+$/.test(vol)) { 31 | if (Math.round(dispatcher.volume * 50) >= 100) return msg.sendMessage(`📢 Volume: ${Math.round(dispatcher.volume * 50)}%`); 32 | dispatcher.setVolume(Math.min(((dispatcher.volume * 50) + (2 * (vol.split('+').length - 1))) / 50, 2)); 33 | return msg.sendMessage(`${dispatcher.volume === 2 ? '📢' : '🔊'} Volume: ${Math.round(dispatcher.volume * 50)}%`); 34 | } 35 | 36 | if (/^[-]+$/.test(vol)) { 37 | if (Math.round(dispatcher.volume * 50) <= 0) return msg.sendMessage(`🔇 Volume: ${Math.round(dispatcher.volume * 50)}%`); 38 | dispatcher.setVolume(Math.max(((dispatcher.volume * 50) - (2 * (vol.split('-').length - 1))) / 50, 0)); 39 | return msg.sendMessage(`${dispatcher.volume === 0 ? '🔇' : '🔉'} Volume: ${Math.round(dispatcher.volume * 50)}%`); 40 | } 41 | 42 | throw `This command is quite analogic, but let me show you how you use this command:${codeBlock('', this.extendedHelp)}`; 43 | } 44 | 45 | }; 46 | -------------------------------------------------------------------------------- /src/commands/Music/play.js: -------------------------------------------------------------------------------- 1 | const { MusicCommand, klasaUtil: { sleep } } = require('../../index'); 2 | 3 | module.exports = class extends MusicCommand { 4 | 5 | constructor(...args) { 6 | super(...args, { description: 'Let\'s start the queue!' }); 7 | } 8 | 9 | async run(msg) { 10 | const { music } = msg.guild; 11 | 12 | if (!music.queue.length) 13 | return msg.sendMessage(`Deck's empty my friend, add some songs to the queue with the \`${msg.guild.settings.prefix}add\` command so I can play them.`); 14 | 15 | if (!music.voiceChannel) await this.store.get('join').run(msg); 16 | 17 | if (music.playing) { 18 | return msg.sendMessage('Hey! The disk is already spinning!'); 19 | } else if (music.paused) { 20 | music.resume(); 21 | return msg.sendMessage(`There was a track going on! Playing it back! Now playing: ${music.queue[0].title}!`); 22 | } else { 23 | music.channel = msg.channel; 24 | return this.play(music); 25 | } 26 | } 27 | 28 | async play(music) { 29 | while (music.queue.length) { 30 | const [song] = music.queue; 31 | await music.channel.send(`🎧 Playing: **${song.title}** as requested by: **${song.requester}**`); 32 | await sleep(300); 33 | 34 | try { 35 | if (!await new Promise(async (resolve) => { 36 | (await music.play()) 37 | .on('end', () => { 38 | music.skip(); 39 | resolve(true); 40 | }) 41 | .on('error', (err) => { 42 | music.channel.send('Whoops! This disk broke!'); 43 | music.client.emit('error', err); 44 | music.skip(); 45 | resolve(true); 46 | }) 47 | .once('disconnect', () => { 48 | resolve(false); 49 | }); 50 | })) return; 51 | 52 | // Autofetch if the autoplayer is enabled 53 | if (!music.queue.length && music.autoplay) await this.autoPlayer(music); 54 | } catch (error) { 55 | this.client.emit('error', error); 56 | music.channel.send(error); 57 | music.leave(); 58 | break; 59 | } 60 | } 61 | 62 | if (!music.queue.length) { 63 | music.channel.send('⏹ From 1 to 10, being 1 the worst score and 10 the best, how would you rate the session? It just ended!') 64 | .then(() => music.leave()); 65 | } 66 | } 67 | 68 | autoPlayer(music) { 69 | return music.add('YouTube AutoPlay', music.next); 70 | } 71 | 72 | }; 73 | -------------------------------------------------------------------------------- /src/lib/structures/MusicManager.js: -------------------------------------------------------------------------------- 1 | const { util: { codeBlock } } = require('klasa'); 2 | const ytdl = require('ytdl-core'); 3 | const ytdlDiscord = require('ytdl-core-discord'); 4 | const getInfoAsync = require('util').promisify(ytdl.getInfo); 5 | 6 | class MusicManager { 7 | 8 | /** 9 | * @typedef {Object} MusicManagerSong 10 | * @property {string} url The video id 11 | * @property {string} title The title of the video 12 | * @property {KlasaUser | string} user The user that requested this song 13 | * @property {number} loudness The loudness for this song, reserved for future 14 | * @property {number} seconds The seconds this video lasts 15 | * @property {boolean} opus Whether this video has an Opus stream available or not 16 | */ 17 | 18 | constructor(guild) { 19 | /** 20 | * The Client that manages this instance 21 | * @since 1.0.0 22 | * @type {Sneyra} 23 | * @name MusicManager#client 24 | */ 25 | Object.defineProperty(this, 'client', { value: guild.client }); 26 | 27 | /** 28 | * The SneyraGuild instance that manages this instance 29 | * @since 1.0.0 30 | * @type {SneyraGuild} 31 | * @name MusicManager#guild 32 | */ 33 | Object.defineProperty(this, 'guild', { value: guild }); 34 | 35 | /** 36 | * The ids of the 10 latest played videos 37 | * @since 1.0.0 38 | * @type {string[]} 39 | */ 40 | this.recentlyPlayed = []; 41 | 42 | /** 43 | * The current queue for this manager 44 | * @since 1.0.0 45 | * @type {MusicManagerSong[]} 46 | */ 47 | this.queue = []; 48 | 49 | /** 50 | * The Channel instance where music commands are played at 51 | * @since 1.0.0 52 | * @type {TextChannel} 53 | */ 54 | this.channel = null; 55 | 56 | /** 57 | * Whether autoplayer is enabled or not 58 | * @since 1.0.0 59 | * @type {boolean} 60 | */ 61 | this.autoplay = false; 62 | 63 | /** 64 | * The next song id for autoplayer 65 | * @since 1.0.0 66 | * @type {?string} 67 | */ 68 | this._next = null; 69 | } 70 | 71 | get remaining() { 72 | const { playing, dispatcher } = this; 73 | if (!playing) return null; 74 | const [song] = this.queue; 75 | return (song.seconds * 1000) - dispatcher.streamTime; 76 | } 77 | 78 | /** 79 | * The next video 80 | * @since 1.0.0 81 | * @type {?string} 82 | * @readonly 83 | */ 84 | get next() { 85 | return this._next ? `https://youtu.be/${this._next}` : null; 86 | } 87 | 88 | /** 89 | * The VoiceChannel Sneyra is connected to 90 | * @since 1.0.0 91 | * @type {?VoiceChannel} 92 | * @readonly 93 | */ 94 | get voiceChannel() { 95 | return this.guild.me.voice.channel; 96 | } 97 | 98 | /** 99 | * The VoiceChannel's connection 100 | * @since 1.0.0 101 | * @type {?VoiceConnection} 102 | * @readonly 103 | */ 104 | get connection() { 105 | const { voiceChannel } = this; 106 | return (voiceChannel && voiceChannel.connection) || null; 107 | } 108 | 109 | /** 110 | * The VoiceConnection's dispatcher 111 | * @since 1.0.0 112 | * @type {?StreamDispatcher} 113 | * @readonly 114 | */ 115 | get dispatcher() { 116 | const { connection } = this; 117 | return (connection && connection.dispatcher) || null; 118 | } 119 | 120 | /** 121 | * Whether Sneyra is playing a song or not 122 | * @since 2.0.0 123 | * @type {boolean} 124 | * @readonly 125 | */ 126 | get playing() { 127 | return !this.paused && !this.idling; 128 | } 129 | 130 | /** 131 | * Whether Sneyra has the queue paused or not 132 | * @since 2.0.0 133 | * @type {?boolean} 134 | * @readonly 135 | */ 136 | get paused() { 137 | const { dispatcher } = this; 138 | return dispatcher ? dispatcher.paused : null; 139 | } 140 | 141 | /** 142 | * Whether Sneyra is doing nothing 143 | * @since 2.0.0 144 | * @type {boolean} 145 | * @readonly 146 | */ 147 | get idling() { 148 | return !this.queue.length || !this.dispatcher; 149 | } 150 | 151 | /** 152 | * Add a song to the queue 153 | * @since 1.0.0 154 | * @param {KlasaUser} user The user that requests this song 155 | * @param {string} url The url to add 156 | * @returns {MusicManagerSong} 157 | */ 158 | async add(user, url) { 159 | const song = await getInfoAsync(url).catch((err) => { 160 | this.client.emit('log', err, 'error'); 161 | throw `Something happened with YouTube URL: ${url}\n${codeBlock('', err)}`; 162 | }); 163 | 164 | const metadata = { 165 | url: song.video_id, 166 | title: song.title.replace(/@(here|everyone)/, '@\u200B$1'), 167 | requester: user, 168 | loudness: song.loudness, 169 | seconds: parseInt(song.length_seconds), 170 | opus: song.formats.some(format => format.type === 'audio/webm; codecs="opus"') 171 | }; 172 | 173 | this.queue.push(metadata); 174 | this._next = this.getLink(song.related_videos); 175 | 176 | return metadata; 177 | } 178 | 179 | /** 180 | * Get a link from a playlist, filtering previously played videos 181 | * @since 1.0.0 182 | * @param {Array>} playlist The playlist to check 183 | * @returns {?string} 184 | */ 185 | getLink(playlist) { 186 | for (const song of playlist) { 187 | if (!song.id || this.recentlyPlayed.includes(song.id)) continue; 188 | return song.id; 189 | } 190 | return null; 191 | } 192 | 193 | /** 194 | * Join a voice channel, handling ECONNRESETs 195 | * @since 1.0.0 196 | * @param {VoiceChannel} voiceChannel Join a voice channel 197 | * @returns {Promise} 198 | */ 199 | join(voiceChannel) { 200 | return voiceChannel.join().catch((err) => { 201 | if (String(err).includes('ECONNRESET')) throw 'There was an issue connecting to the voice channel, please try again.'; 202 | this.client.emit('error', err); 203 | throw err; 204 | }); 205 | } 206 | 207 | /** 208 | * Leave the voice channel, reseating all the current data 209 | * @since 1.0.0 210 | * @returns {Promise} 211 | */ 212 | async leave() { 213 | if (!this.voiceChannel) throw 'I already left the voice channel! You might want me to be in one in order to leave it...'; 214 | await this.voiceChannel.leave(); 215 | if (this.voiceChannel) this.forceDisconnect(); 216 | 217 | // Reset the status 218 | return this.clear(); 219 | } 220 | 221 | async play() { 222 | if (!this.voiceChannel) throw 'Where am I supposed to play the music? I am not in a voice channel!'; 223 | if (!this.connection) { 224 | await this.channel.send(`This dj table isn't connected! Let me unplug and plug it again`) 225 | .catch(error => this.client.emit('error', error)); 226 | 227 | const { voiceChannel } = this; 228 | this.forceDisconnect(); 229 | await this.join(voiceChannel); 230 | if (!this.connection) throw 'This dj table is broken! Try again later...'; 231 | } 232 | if (!this.queue.length) throw 'No songs left in the queue!'; 233 | 234 | const [song] = this.queue; 235 | 236 | const stream = await ytdlDiscord(`https://youtu.be/${song.url}`); 237 | 238 | this.connection.play(stream, { 239 | bitrate: this.voiceChannel.bitrate / 1000, 240 | passes: 5, 241 | type: song.opus ? 'opus' : 'unknown', 242 | volume: false 243 | }); 244 | 245 | this.pushPlayed(song.url); 246 | 247 | return this.dispatcher; 248 | } 249 | 250 | pushPlayed(url) { 251 | this.recentlyPlayed.push(url); 252 | if (this.recentlyPlayed.length > 10) this.recentlyPlayed.shift(); 253 | } 254 | 255 | pause() { 256 | const { dispatcher } = this; 257 | if (dispatcher) dispatcher.pause(); 258 | return this; 259 | } 260 | 261 | resume() { 262 | const { dispatcher } = this; 263 | if (dispatcher) dispatcher.resume(); 264 | return this; 265 | } 266 | 267 | skip(force = false) { 268 | const { dispatcher } = this; 269 | if (force && dispatcher) dispatcher.end(); 270 | else this.queue.shift(); 271 | return this; 272 | } 273 | 274 | prune() { 275 | this.queue.length = 0; 276 | return this; 277 | } 278 | 279 | clear() { 280 | this.recentlyPlayed.length = 0; 281 | this.queue.length = 0; 282 | this.channel = null; 283 | this.autoplay = false; 284 | this._next = null; 285 | 286 | return this; 287 | } 288 | 289 | forceDisconnect() { 290 | const { connection } = this; 291 | if (connection) { 292 | connection.disconnect(); 293 | } else { 294 | /* eslint-disable camelcase */ 295 | this.guild.shard.send({ 296 | op: 4, 297 | shard: this.client.shard ? this.client.shard.id : 0, 298 | d: { 299 | guild_id: this.guild.id, 300 | channel_id: null, 301 | self_mute: false, 302 | self_deaf: false 303 | } 304 | }); 305 | /* eslint-enable camelcase */ 306 | } 307 | } 308 | 309 | } 310 | 311 | module.exports = MusicManager; 312 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/code-frame@^7.0.0": 6 | version "7.0.0" 7 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" 8 | integrity sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA== 9 | dependencies: 10 | "@babel/highlight" "^7.0.0" 11 | 12 | "@babel/highlight@^7.0.0": 13 | version "7.0.0" 14 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4" 15 | integrity sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw== 16 | dependencies: 17 | chalk "^2.0.0" 18 | esutils "^2.0.2" 19 | js-tokens "^4.0.0" 20 | 21 | "@discordjs/collection@^0.1.1": 22 | version "0.1.1" 23 | resolved "https://registry.yarnpkg.com/@discordjs/collection/-/collection-0.1.1.tgz#372b126186c3bdf77f32bb284a72d7a75b394323" 24 | integrity sha512-T5AGaxlR2vszMM/a0cKoHFjSCNwE/sON4fW0ZGuLRwbJVdkezsSzy/TYU/IOQqOLTyzEeIh0EjGikrwH5+dUHA== 25 | 26 | abort-controller@^3.0.0: 27 | version "3.0.0" 28 | resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" 29 | integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== 30 | dependencies: 31 | event-target-shim "^5.0.0" 32 | 33 | acorn-jsx@^5.0.2: 34 | version "5.0.2" 35 | resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.2.tgz#84b68ea44b373c4f8686023a551f61a21b7c4a4f" 36 | integrity sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw== 37 | 38 | acorn@^7.0.0: 39 | version "7.0.0" 40 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.0.0.tgz#26b8d1cd9a9b700350b71c0905546f64d1284e7a" 41 | integrity sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ== 42 | 43 | ajv@^6.10.0, ajv@^6.9.1: 44 | version "6.10.0" 45 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" 46 | integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg== 47 | dependencies: 48 | fast-deep-equal "^2.0.1" 49 | fast-json-stable-stringify "^2.0.0" 50 | json-schema-traverse "^0.4.1" 51 | uri-js "^4.2.2" 52 | 53 | ansi-escapes@^3.2.0: 54 | version "3.2.0" 55 | resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" 56 | integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== 57 | 58 | ansi-regex@^3.0.0: 59 | version "3.0.0" 60 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" 61 | integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= 62 | 63 | ansi-regex@^4.1.0: 64 | version "4.1.0" 65 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" 66 | integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== 67 | 68 | ansi-styles@^3.2.0, ansi-styles@^3.2.1: 69 | version "3.2.1" 70 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 71 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 72 | dependencies: 73 | color-convert "^1.9.0" 74 | 75 | argparse@^1.0.7: 76 | version "1.0.10" 77 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 78 | integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== 79 | dependencies: 80 | sprintf-js "~1.0.2" 81 | 82 | astral-regex@^1.0.0: 83 | version "1.0.0" 84 | resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" 85 | integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== 86 | 87 | async-limiter@~1.0.0: 88 | version "1.0.0" 89 | resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" 90 | integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== 91 | 92 | asynckit@^0.4.0: 93 | version "0.4.0" 94 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 95 | integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= 96 | 97 | balanced-match@^1.0.0: 98 | version "1.0.0" 99 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 100 | integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= 101 | 102 | bindings@1: 103 | version "1.5.0" 104 | resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" 105 | integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== 106 | dependencies: 107 | file-uri-to-path "1.0.0" 108 | 109 | bindings@~1.2.1: 110 | version "1.2.1" 111 | resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11" 112 | integrity sha1-FK1hE4EtLTfXLme0ystLtyZQXxE= 113 | 114 | "bluebird@>= 3.0.1": 115 | version "3.5.3" 116 | resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.3.tgz#7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7" 117 | integrity sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw== 118 | 119 | brace-expansion@^1.1.7: 120 | version "1.1.11" 121 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 122 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 123 | dependencies: 124 | balanced-match "^1.0.0" 125 | concat-map "0.0.1" 126 | 127 | callsites@^3.0.0: 128 | version "3.0.0" 129 | resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.0.0.tgz#fb7eb569b72ad7a45812f93fd9430a3e410b3dd3" 130 | integrity sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw== 131 | 132 | chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.2: 133 | version "2.4.2" 134 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 135 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 136 | dependencies: 137 | ansi-styles "^3.2.1" 138 | escape-string-regexp "^1.0.5" 139 | supports-color "^5.3.0" 140 | 141 | chardet@^0.7.0: 142 | version "0.7.0" 143 | resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" 144 | integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== 145 | 146 | cli-cursor@^2.1.0: 147 | version "2.1.0" 148 | resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" 149 | integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= 150 | dependencies: 151 | restore-cursor "^2.0.0" 152 | 153 | cli-width@^2.0.0: 154 | version "2.2.0" 155 | resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" 156 | integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= 157 | 158 | color-convert@^1.9.0: 159 | version "1.9.3" 160 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 161 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 162 | dependencies: 163 | color-name "1.1.3" 164 | 165 | color-name@1.1.3: 166 | version "1.1.3" 167 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 168 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= 169 | 170 | combined-stream@^1.0.6: 171 | version "1.0.7" 172 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828" 173 | integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w== 174 | dependencies: 175 | delayed-stream "~1.0.0" 176 | 177 | commander@^2.9.0: 178 | version "2.19.0" 179 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" 180 | integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== 181 | 182 | concat-map@0.0.1: 183 | version "0.0.1" 184 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 185 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 186 | 187 | cross-spawn@^6.0.5: 188 | version "6.0.5" 189 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" 190 | integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== 191 | dependencies: 192 | nice-try "^1.0.4" 193 | path-key "^2.0.1" 194 | semver "^5.5.0" 195 | shebang-command "^1.2.0" 196 | which "^1.2.9" 197 | 198 | debug@2: 199 | version "2.6.9" 200 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 201 | integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== 202 | dependencies: 203 | ms "2.0.0" 204 | 205 | debug@^4.0.1: 206 | version "4.1.1" 207 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" 208 | integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== 209 | dependencies: 210 | ms "^2.1.1" 211 | 212 | deep-is@~0.1.3: 213 | version "0.1.3" 214 | resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" 215 | integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= 216 | 217 | delayed-stream@~1.0.0: 218 | version "1.0.0" 219 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 220 | integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= 221 | 222 | "discord.js@github:discordjs/discord.js": 223 | version "12.0.0-dev" 224 | uid ea9e1441905e67e2627a6f5e80a8d989d01376c5 225 | resolved "https://codeload.github.com/discordjs/discord.js/tar.gz/ea9e1441905e67e2627a6f5e80a8d989d01376c5" 226 | dependencies: 227 | "@discordjs/collection" "^0.1.1" 228 | abort-controller "^3.0.0" 229 | form-data "^2.3.3" 230 | node-fetch "^2.3.0" 231 | pako "^1.0.8" 232 | prism-media "^1.0.0" 233 | setimmediate "^1.0.5" 234 | tweetnacl "^1.0.1" 235 | ws "^6.1.3" 236 | 237 | doctrine@^3.0.0: 238 | version "3.0.0" 239 | resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" 240 | integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== 241 | dependencies: 242 | esutils "^2.0.2" 243 | 244 | emoji-regex@^7.0.1: 245 | version "7.0.3" 246 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" 247 | integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== 248 | 249 | escape-string-regexp@^1.0.5: 250 | version "1.0.5" 251 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 252 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 253 | 254 | "eslint-config-klasa@github:dirigeants/klasa-lint": 255 | version "0.0.1" 256 | uid "28618d5bf851bffdb6775deb5937acfe2a1af25a" 257 | resolved "https://codeload.github.com/dirigeants/klasa-lint/tar.gz/28618d5bf851bffdb6775deb5937acfe2a1af25a" 258 | 259 | eslint-scope@^5.0.0: 260 | version "5.0.0" 261 | resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" 262 | integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== 263 | dependencies: 264 | esrecurse "^4.1.0" 265 | estraverse "^4.1.1" 266 | 267 | eslint-utils@^1.4.2: 268 | version "1.4.2" 269 | resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.2.tgz#166a5180ef6ab7eb462f162fd0e6f2463d7309ab" 270 | integrity sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q== 271 | dependencies: 272 | eslint-visitor-keys "^1.0.0" 273 | 274 | eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: 275 | version "1.1.0" 276 | resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" 277 | integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== 278 | 279 | eslint@^6.4.0: 280 | version "6.4.0" 281 | resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.4.0.tgz#5aa9227c3fbe921982b2eda94ba0d7fae858611a" 282 | integrity sha512-WTVEzK3lSFoXUovDHEbkJqCVPEPwbhCq4trDktNI6ygs7aO41d4cDT0JFAT5MivzZeVLWlg7vHL+bgrQv/t3vA== 283 | dependencies: 284 | "@babel/code-frame" "^7.0.0" 285 | ajv "^6.10.0" 286 | chalk "^2.1.0" 287 | cross-spawn "^6.0.5" 288 | debug "^4.0.1" 289 | doctrine "^3.0.0" 290 | eslint-scope "^5.0.0" 291 | eslint-utils "^1.4.2" 292 | eslint-visitor-keys "^1.1.0" 293 | espree "^6.1.1" 294 | esquery "^1.0.1" 295 | esutils "^2.0.2" 296 | file-entry-cache "^5.0.1" 297 | functional-red-black-tree "^1.0.1" 298 | glob-parent "^5.0.0" 299 | globals "^11.7.0" 300 | ignore "^4.0.6" 301 | import-fresh "^3.0.0" 302 | imurmurhash "^0.1.4" 303 | inquirer "^6.4.1" 304 | is-glob "^4.0.0" 305 | js-yaml "^3.13.1" 306 | json-stable-stringify-without-jsonify "^1.0.1" 307 | levn "^0.3.0" 308 | lodash "^4.17.14" 309 | minimatch "^3.0.4" 310 | mkdirp "^0.5.1" 311 | natural-compare "^1.4.0" 312 | optionator "^0.8.2" 313 | progress "^2.0.0" 314 | regexpp "^2.0.1" 315 | semver "^6.1.2" 316 | strip-ansi "^5.2.0" 317 | strip-json-comments "^3.0.1" 318 | table "^5.2.3" 319 | text-table "^0.2.0" 320 | v8-compile-cache "^2.0.3" 321 | 322 | espree@^6.1.1: 323 | version "6.1.1" 324 | resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.1.tgz#7f80e5f7257fc47db450022d723e356daeb1e5de" 325 | integrity sha512-EYbr8XZUhWbYCqQRW0duU5LxzL5bETN6AjKBGy1302qqzPaCH10QbRg3Wvco79Z8x9WbiE8HYB4e75xl6qUYvQ== 326 | dependencies: 327 | acorn "^7.0.0" 328 | acorn-jsx "^5.0.2" 329 | eslint-visitor-keys "^1.1.0" 330 | 331 | esprima@^4.0.0: 332 | version "4.0.1" 333 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" 334 | integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== 335 | 336 | esquery@^1.0.1: 337 | version "1.0.1" 338 | resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" 339 | integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== 340 | dependencies: 341 | estraverse "^4.0.0" 342 | 343 | esrecurse@^4.1.0: 344 | version "4.2.1" 345 | resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" 346 | integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== 347 | dependencies: 348 | estraverse "^4.1.0" 349 | 350 | estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: 351 | version "4.2.0" 352 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" 353 | integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= 354 | 355 | esutils@^2.0.2: 356 | version "2.0.2" 357 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" 358 | integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= 359 | 360 | event-target-shim@^5.0.0: 361 | version "5.0.1" 362 | resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" 363 | integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== 364 | 365 | external-editor@^3.0.3: 366 | version "3.0.3" 367 | resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" 368 | integrity sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA== 369 | dependencies: 370 | chardet "^0.7.0" 371 | iconv-lite "^0.4.24" 372 | tmp "^0.0.33" 373 | 374 | fast-deep-equal@^2.0.1: 375 | version "2.0.1" 376 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" 377 | integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= 378 | 379 | fast-json-stable-stringify@^2.0.0: 380 | version "2.0.0" 381 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" 382 | integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= 383 | 384 | fast-levenshtein@~2.0.4: 385 | version "2.0.6" 386 | resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" 387 | integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= 388 | 389 | figures@^2.0.0: 390 | version "2.0.0" 391 | resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" 392 | integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= 393 | dependencies: 394 | escape-string-regexp "^1.0.5" 395 | 396 | file-entry-cache@^5.0.1: 397 | version "5.0.1" 398 | resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" 399 | integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== 400 | dependencies: 401 | flat-cache "^2.0.1" 402 | 403 | file-uri-to-path@1.0.0: 404 | version "1.0.0" 405 | resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" 406 | integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== 407 | 408 | flat-cache@^2.0.1: 409 | version "2.0.1" 410 | resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" 411 | integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== 412 | dependencies: 413 | flatted "^2.0.0" 414 | rimraf "2.6.3" 415 | write "1.0.3" 416 | 417 | flatted@^2.0.0: 418 | version "2.0.0" 419 | resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916" 420 | integrity sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg== 421 | 422 | form-data@^2.3.3: 423 | version "2.3.3" 424 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" 425 | integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== 426 | dependencies: 427 | asynckit "^0.4.0" 428 | combined-stream "^1.0.6" 429 | mime-types "^2.1.12" 430 | 431 | fs-nextra@^0.4.5: 432 | version "0.4.5" 433 | resolved "https://registry.yarnpkg.com/fs-nextra/-/fs-nextra-0.4.5.tgz#0f44a00dd6c0547adaf59ce875e59941d0c70664" 434 | integrity sha512-oY2o6j0izYzJWp2sow21SekkR3qeMZqHV5ZfNFvfKimFU7piw1/AWwiwbcWjuSfwrfCmHyHymWZOyNbKOzew5g== 435 | 436 | fs.realpath@^1.0.0: 437 | version "1.0.0" 438 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 439 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 440 | 441 | functional-red-black-tree@^1.0.1: 442 | version "1.0.1" 443 | resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" 444 | integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= 445 | 446 | glob-parent@^5.0.0: 447 | version "5.0.0" 448 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.0.0.tgz#1dc99f0f39b006d3e92c2c284068382f0c20e954" 449 | integrity sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg== 450 | dependencies: 451 | is-glob "^4.0.1" 452 | 453 | glob@^7.1.3: 454 | version "7.1.3" 455 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" 456 | integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== 457 | dependencies: 458 | fs.realpath "^1.0.0" 459 | inflight "^1.0.4" 460 | inherits "2" 461 | minimatch "^3.0.4" 462 | once "^1.3.0" 463 | path-is-absolute "^1.0.0" 464 | 465 | globals@^11.7.0: 466 | version "11.11.0" 467 | resolved "https://registry.yarnpkg.com/globals/-/globals-11.11.0.tgz#dcf93757fa2de5486fbeed7118538adf789e9c2e" 468 | integrity sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw== 469 | 470 | has-flag@^3.0.0: 471 | version "3.0.0" 472 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 473 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 474 | 475 | html-entities@^1.1.3: 476 | version "1.2.1" 477 | resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" 478 | integrity sha1-DfKTUfByEWNRXfueVUPl9u7VFi8= 479 | 480 | iconv-lite@^0.4.24: 481 | version "0.4.24" 482 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 483 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 484 | dependencies: 485 | safer-buffer ">= 2.1.2 < 3" 486 | 487 | ignore@^4.0.6: 488 | version "4.0.6" 489 | resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" 490 | integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== 491 | 492 | import-fresh@^3.0.0: 493 | version "3.0.0" 494 | resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.0.0.tgz#a3d897f420cab0e671236897f75bc14b4885c390" 495 | integrity sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ== 496 | dependencies: 497 | parent-module "^1.0.0" 498 | resolve-from "^4.0.0" 499 | 500 | imurmurhash@^0.1.4: 501 | version "0.1.4" 502 | resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" 503 | integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= 504 | 505 | inflight@^1.0.4: 506 | version "1.0.6" 507 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 508 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 509 | dependencies: 510 | once "^1.3.0" 511 | wrappy "1" 512 | 513 | inherits@2: 514 | version "2.0.3" 515 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 516 | integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= 517 | 518 | inquirer@^6.4.1: 519 | version "6.5.0" 520 | resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.0.tgz#2303317efc9a4ea7ec2e2df6f86569b734accf42" 521 | integrity sha512-scfHejeG/lVZSpvCXpsB4j/wQNPM5JC8kiElOI0OUTwmc1RTpXr4H32/HOlQHcZiYl2z2VElwuCVDRG8vFmbnA== 522 | dependencies: 523 | ansi-escapes "^3.2.0" 524 | chalk "^2.4.2" 525 | cli-cursor "^2.1.0" 526 | cli-width "^2.0.0" 527 | external-editor "^3.0.3" 528 | figures "^2.0.0" 529 | lodash "^4.17.12" 530 | mute-stream "0.0.7" 531 | run-async "^2.2.0" 532 | rxjs "^6.4.0" 533 | string-width "^2.1.0" 534 | strip-ansi "^5.1.0" 535 | through "^2.3.6" 536 | 537 | is-extglob@^2.1.1: 538 | version "2.1.1" 539 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 540 | integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= 541 | 542 | is-fullwidth-code-point@^2.0.0: 543 | version "2.0.0" 544 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" 545 | integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= 546 | 547 | is-glob@^4.0.0, is-glob@^4.0.1: 548 | version "4.0.1" 549 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" 550 | integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== 551 | dependencies: 552 | is-extglob "^2.1.1" 553 | 554 | is-promise@^2.1.0: 555 | version "2.1.0" 556 | resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" 557 | integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= 558 | 559 | isexe@^2.0.0: 560 | version "2.0.0" 561 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 562 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= 563 | 564 | js-tokens@^4.0.0: 565 | version "4.0.0" 566 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 567 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 568 | 569 | js-yaml@^3.13.1: 570 | version "3.13.1" 571 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" 572 | integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== 573 | dependencies: 574 | argparse "^1.0.7" 575 | esprima "^4.0.0" 576 | 577 | json-schema-traverse@^0.4.1: 578 | version "0.4.1" 579 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 580 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 581 | 582 | json-stable-stringify-without-jsonify@^1.0.1: 583 | version "1.0.1" 584 | resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" 585 | integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= 586 | 587 | "klasa@github:dirigeants/klasa": 588 | version "0.5.0-dev" 589 | uid "06259ba49715230c80b404feef67e19a4f16ba6b" 590 | resolved "https://codeload.github.com/dirigeants/klasa/tar.gz/06259ba49715230c80b404feef67e19a4f16ba6b" 591 | dependencies: 592 | fs-nextra "^0.4.5" 593 | 594 | levn@^0.3.0, levn@~0.3.0: 595 | version "0.3.0" 596 | resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" 597 | integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= 598 | dependencies: 599 | prelude-ls "~1.1.2" 600 | type-check "~0.3.2" 601 | 602 | lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14: 603 | version "4.17.15" 604 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" 605 | integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== 606 | 607 | m3u8stream@^0.6.2: 608 | version "0.6.2" 609 | resolved "https://registry.yarnpkg.com/m3u8stream/-/m3u8stream-0.6.2.tgz#c2c62ddce88156d80378dd59be010c8b8e9d120b" 610 | integrity sha512-WsuM2bd5pPN80xvfrB+1DZqr4M7+kJl8byi6+ZCy6cmVjEiHhmr/desN53Ngsa6Hs13kYumeVgT4wL0oIJ+v6g== 611 | dependencies: 612 | miniget "^1.4.0" 613 | sax "^1.2.4" 614 | 615 | mime-db@~1.38.0: 616 | version "1.38.0" 617 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.38.0.tgz#1a2aab16da9eb167b49c6e4df2d9c68d63d8e2ad" 618 | integrity sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg== 619 | 620 | mime-types@^2.1.12: 621 | version "2.1.22" 622 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.22.tgz#fe6b355a190926ab7698c9a0556a11199b2199bd" 623 | integrity sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog== 624 | dependencies: 625 | mime-db "~1.38.0" 626 | 627 | mimic-fn@^1.0.0: 628 | version "1.2.0" 629 | resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" 630 | integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== 631 | 632 | miniget@^1.4.0, miniget@^1.5.3: 633 | version "1.5.3" 634 | resolved "https://registry.yarnpkg.com/miniget/-/miniget-1.5.3.tgz#d796c7291970d1dfa28b646d9aba3fa6b377c5e8" 635 | integrity sha512-6xiJs3ZGBdrNMlPNlEWirHhY53hSW33nG1Ytub9Cg5+jLhFPn9PGe4FmPZK9WlmDE1N7/8DEL7PGr7r9kbxwgw== 636 | 637 | minimatch@^3.0.4: 638 | version "3.0.4" 639 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 640 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 641 | dependencies: 642 | brace-expansion "^1.1.7" 643 | 644 | minimist@0.0.8: 645 | version "0.0.8" 646 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 647 | integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= 648 | 649 | mkdirp@^0.5.1: 650 | version "0.5.1" 651 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" 652 | integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= 653 | dependencies: 654 | minimist "0.0.8" 655 | 656 | ms@2.0.0: 657 | version "2.0.0" 658 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 659 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= 660 | 661 | ms@^2.1.1: 662 | version "2.1.1" 663 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" 664 | integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== 665 | 666 | mute-stream@0.0.7: 667 | version "0.0.7" 668 | resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" 669 | integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= 670 | 671 | nan@2, nan@^2.14.0: 672 | version "2.14.0" 673 | resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" 674 | integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== 675 | 676 | natural-compare@^1.4.0: 677 | version "1.4.0" 678 | resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" 679 | integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= 680 | 681 | nice-try@^1.0.4: 682 | version "1.0.5" 683 | resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" 684 | integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== 685 | 686 | node-fetch@^2.3.0: 687 | version "2.3.0" 688 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.3.0.tgz#1a1d940bbfb916a1d3e0219f037e89e71f8c5fa5" 689 | integrity sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA== 690 | 691 | node-opus@^0.3.2: 692 | version "0.3.2" 693 | resolved "https://registry.yarnpkg.com/node-opus/-/node-opus-0.3.2.tgz#5a20084e02f86116eadc2c7fd49b233e2260190d" 694 | integrity sha512-o7hKgNncfbgF1j25lCK7cPqs9DEMroP3LWW0BMb/Ismc33cXo7LcaLqS0+/VV+NOotIy43fb7juLg6akflzBEw== 695 | dependencies: 696 | bindings "~1.2.1" 697 | commander "^2.9.0" 698 | nan "^2.14.0" 699 | optionalDependencies: 700 | ogg-packet "^1.0.0" 701 | 702 | ogg-packet@^1.0.0: 703 | version "1.0.0" 704 | resolved "https://registry.yarnpkg.com/ogg-packet/-/ogg-packet-1.0.0.tgz#45b885721ac8f7dd5cf22391d42106ae533ac678" 705 | integrity sha1-RbiFchrI991c8iOR1CEGrlM6xng= 706 | dependencies: 707 | ref-struct "*" 708 | 709 | once@^1.3.0: 710 | version "1.4.0" 711 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 712 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 713 | dependencies: 714 | wrappy "1" 715 | 716 | onetime@^2.0.0: 717 | version "2.0.1" 718 | resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" 719 | integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= 720 | dependencies: 721 | mimic-fn "^1.0.0" 722 | 723 | optionator@^0.8.2: 724 | version "0.8.2" 725 | resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" 726 | integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= 727 | dependencies: 728 | deep-is "~0.1.3" 729 | fast-levenshtein "~2.0.4" 730 | levn "~0.3.0" 731 | prelude-ls "~1.1.2" 732 | type-check "~0.3.2" 733 | wordwrap "~1.0.0" 734 | 735 | os-tmpdir@~1.0.2: 736 | version "1.0.2" 737 | resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" 738 | integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= 739 | 740 | pako@^1.0.8: 741 | version "1.0.10" 742 | resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" 743 | integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw== 744 | 745 | parent-module@^1.0.0: 746 | version "1.0.0" 747 | resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.0.tgz#df250bdc5391f4a085fb589dad761f5ad6b865b5" 748 | integrity sha512-8Mf5juOMmiE4FcmzYc4IaiS9L3+9paz2KOiXzkRviCP6aDmN49Hz6EMWz0lGNp9pX80GvvAuLADtyGfW/Em3TA== 749 | dependencies: 750 | callsites "^3.0.0" 751 | 752 | path-is-absolute@^1.0.0: 753 | version "1.0.1" 754 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 755 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 756 | 757 | path-key@^2.0.1: 758 | version "2.0.1" 759 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" 760 | integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= 761 | 762 | prelude-ls@~1.1.2: 763 | version "1.1.2" 764 | resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" 765 | integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= 766 | 767 | prism-media@^1.0.0, prism-media@^1.0.1: 768 | version "1.0.1" 769 | resolved "https://registry.yarnpkg.com/prism-media/-/prism-media-1.0.1.tgz#3d033c214f9d79ca157bae7985938be65f521c02" 770 | integrity sha512-Unmeibfk7b8wiiQFPlCC0GgCRaAejSpe2ElgfDkMi9ZmsqzeTbUnmiLNjyqONeKK+HMYINYHOgJFox5l7FU7YA== 771 | 772 | progress@^2.0.0: 773 | version "2.0.3" 774 | resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" 775 | integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== 776 | 777 | punycode@^2.1.0: 778 | version "2.1.1" 779 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" 780 | integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== 781 | 782 | ref-struct@*: 783 | version "1.1.0" 784 | resolved "https://registry.yarnpkg.com/ref-struct/-/ref-struct-1.1.0.tgz#5d5ee65ad41cefc3a5c5feb40587261e479edc13" 785 | integrity sha1-XV7mWtQc78Olxf60BYcmHkee3BM= 786 | dependencies: 787 | debug "2" 788 | ref "1" 789 | 790 | ref@1: 791 | version "1.3.5" 792 | resolved "https://registry.yarnpkg.com/ref/-/ref-1.3.5.tgz#0e33f080cdb94a3d95312b2b3b1fd0f82044ca0f" 793 | integrity sha512-2cBCniTtxcGUjDpvFfVpw323a83/0RLSGJJY5l5lcomZWhYpU2cuLdsvYqMixvsdLJ9+sTdzEkju8J8ZHDM2nA== 794 | dependencies: 795 | bindings "1" 796 | debug "2" 797 | nan "2" 798 | 799 | regexpp@^2.0.1: 800 | version "2.0.1" 801 | resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" 802 | integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== 803 | 804 | resolve-from@^4.0.0: 805 | version "4.0.0" 806 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" 807 | integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== 808 | 809 | restore-cursor@^2.0.0: 810 | version "2.0.0" 811 | resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" 812 | integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= 813 | dependencies: 814 | onetime "^2.0.0" 815 | signal-exit "^3.0.2" 816 | 817 | rethinkdbdash@^2.3.31: 818 | version "2.3.31" 819 | resolved "https://registry.yarnpkg.com/rethinkdbdash/-/rethinkdbdash-2.3.31.tgz#fe2f73d1fa6e6f5d96d8e881292013cf6dca914d" 820 | integrity sha512-6nXrKFjdg2Ug0YpdmPWSvyD/2EisHnFNt4FWZ74dcXGK48ievSv+cNFTmVv+KjLi6I9CCf6w4CKZ6yCYTfMfdQ== 821 | dependencies: 822 | bluebird ">= 3.0.1" 823 | 824 | rimraf@2.6.3: 825 | version "2.6.3" 826 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" 827 | integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== 828 | dependencies: 829 | glob "^7.1.3" 830 | 831 | run-async@^2.2.0: 832 | version "2.3.0" 833 | resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" 834 | integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= 835 | dependencies: 836 | is-promise "^2.1.0" 837 | 838 | rxjs@^6.4.0: 839 | version "6.4.0" 840 | resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.4.0.tgz#f3bb0fe7bda7fb69deac0c16f17b50b0b8790504" 841 | integrity sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw== 842 | dependencies: 843 | tslib "^1.9.0" 844 | 845 | "safer-buffer@>= 2.1.2 < 3": 846 | version "2.1.2" 847 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 848 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 849 | 850 | sax@^1.1.3, sax@^1.2.4: 851 | version "1.2.4" 852 | resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" 853 | integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== 854 | 855 | semver@^5.5.0: 856 | version "5.6.0" 857 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" 858 | integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== 859 | 860 | semver@^6.1.2: 861 | version "6.2.0" 862 | resolved "https://registry.yarnpkg.com/semver/-/semver-6.2.0.tgz#4d813d9590aaf8a9192693d6c85b9344de5901db" 863 | integrity sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A== 864 | 865 | setimmediate@^1.0.5: 866 | version "1.0.5" 867 | resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" 868 | integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= 869 | 870 | shebang-command@^1.2.0: 871 | version "1.2.0" 872 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" 873 | integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= 874 | dependencies: 875 | shebang-regex "^1.0.0" 876 | 877 | shebang-regex@^1.0.0: 878 | version "1.0.0" 879 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" 880 | integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= 881 | 882 | signal-exit@^3.0.2: 883 | version "3.0.2" 884 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" 885 | integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= 886 | 887 | slice-ansi@^2.1.0: 888 | version "2.1.0" 889 | resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" 890 | integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== 891 | dependencies: 892 | ansi-styles "^3.2.0" 893 | astral-regex "^1.0.0" 894 | is-fullwidth-code-point "^2.0.0" 895 | 896 | sprintf-js@~1.0.2: 897 | version "1.0.3" 898 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 899 | integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= 900 | 901 | string-width@^2.1.0: 902 | version "2.1.1" 903 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" 904 | integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== 905 | dependencies: 906 | is-fullwidth-code-point "^2.0.0" 907 | strip-ansi "^4.0.0" 908 | 909 | string-width@^3.0.0: 910 | version "3.1.0" 911 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" 912 | integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== 913 | dependencies: 914 | emoji-regex "^7.0.1" 915 | is-fullwidth-code-point "^2.0.0" 916 | strip-ansi "^5.1.0" 917 | 918 | strip-ansi@^4.0.0: 919 | version "4.0.0" 920 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" 921 | integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= 922 | dependencies: 923 | ansi-regex "^3.0.0" 924 | 925 | strip-ansi@^5.1.0, strip-ansi@^5.2.0: 926 | version "5.2.0" 927 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" 928 | integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== 929 | dependencies: 930 | ansi-regex "^4.1.0" 931 | 932 | strip-json-comments@^3.0.1: 933 | version "3.0.1" 934 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" 935 | integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== 936 | 937 | supports-color@^5.3.0: 938 | version "5.5.0" 939 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 940 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 941 | dependencies: 942 | has-flag "^3.0.0" 943 | 944 | table@^5.2.3: 945 | version "5.2.3" 946 | resolved "https://registry.yarnpkg.com/table/-/table-5.2.3.tgz#cde0cc6eb06751c009efab27e8c820ca5b67b7f2" 947 | integrity sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ== 948 | dependencies: 949 | ajv "^6.9.1" 950 | lodash "^4.17.11" 951 | slice-ansi "^2.1.0" 952 | string-width "^3.0.0" 953 | 954 | text-table@^0.2.0: 955 | version "0.2.0" 956 | resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" 957 | integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= 958 | 959 | through@^2.3.6: 960 | version "2.3.8" 961 | resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" 962 | integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= 963 | 964 | tmp@^0.0.33: 965 | version "0.0.33" 966 | resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" 967 | integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== 968 | dependencies: 969 | os-tmpdir "~1.0.2" 970 | 971 | tslib@^1.9.0: 972 | version "1.9.3" 973 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" 974 | integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== 975 | 976 | tweetnacl@^1.0.1: 977 | version "1.0.1" 978 | resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.1.tgz#2594d42da73cd036bd0d2a54683dd35a6b55ca17" 979 | integrity sha512-kcoMoKTPYnoeS50tzoqjPY3Uv9axeuuFAZY9M/9zFnhoVvRfxz9K29IMPD7jGmt2c8SW7i3gT9WqDl2+nV7p4A== 980 | 981 | type-check@~0.3.2: 982 | version "0.3.2" 983 | resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" 984 | integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= 985 | dependencies: 986 | prelude-ls "~1.1.2" 987 | 988 | uri-js@^4.2.2: 989 | version "4.2.2" 990 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" 991 | integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== 992 | dependencies: 993 | punycode "^2.1.0" 994 | 995 | v8-compile-cache@^2.0.3: 996 | version "2.0.3" 997 | resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe" 998 | integrity sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w== 999 | 1000 | which@^1.2.9: 1001 | version "1.3.1" 1002 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" 1003 | integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== 1004 | dependencies: 1005 | isexe "^2.0.0" 1006 | 1007 | wordwrap@~1.0.0: 1008 | version "1.0.0" 1009 | resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" 1010 | integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= 1011 | 1012 | wrappy@1: 1013 | version "1.0.2" 1014 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1015 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 1016 | 1017 | write@1.0.3: 1018 | version "1.0.3" 1019 | resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" 1020 | integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== 1021 | dependencies: 1022 | mkdirp "^0.5.1" 1023 | 1024 | ws@^6.1.3: 1025 | version "6.2.0" 1026 | resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.0.tgz#13806d9913b2a5f3cbb9ba47b563c002cbc7c526" 1027 | integrity sha512-deZYUNlt2O4buFCa3t5bKLf8A7FPP/TVjwOeVNpw818Ma5nk4MLXls2eoEGS39o8119QIYxTrTDoPQ5B/gTD6w== 1028 | dependencies: 1029 | async-limiter "~1.0.0" 1030 | 1031 | ytdl-core-discord@^1.0.3: 1032 | version "1.0.3" 1033 | resolved "https://registry.yarnpkg.com/ytdl-core-discord/-/ytdl-core-discord-1.0.3.tgz#4dbe41d77507ee52fcf184b269e2cb9d7f2262aa" 1034 | integrity sha512-/POaSbStmY+PMRnxz4mVN0Rw9Ktt3zs94j2bRX30vmtdMR1yCz9JbEmRY4ouXJK18k/FjdRs5Bnvinud2hbYGQ== 1035 | dependencies: 1036 | prism-media "^1.0.1" 1037 | ytdl-core "^0.29.1" 1038 | 1039 | ytdl-core@^0.29.1, ytdl-core@^0.29.7: 1040 | version "0.29.7" 1041 | resolved "https://registry.yarnpkg.com/ytdl-core/-/ytdl-core-0.29.7.tgz#e63ce0b086a4543d827499bed22f53fdf4d16af2" 1042 | integrity sha512-mqPuZ1UyspT84lyV1FSU1UAoiQ4H5j52ba3sC1LC43OmL8qNaDIRCGffGlpiakQrc69qsplNWsWEZUF+J5bhJA== 1043 | dependencies: 1044 | html-entities "^1.1.3" 1045 | m3u8stream "^0.6.2" 1046 | miniget "^1.5.3" 1047 | sax "^1.1.3" 1048 | --------------------------------------------------------------------------------