Add /invite
This commit is contained in:
parent
392e58cdca
commit
9c0a78c6be
9 changed files with 109 additions and 254 deletions
27
.profile
27
.profile
|
@ -1,27 +0,0 @@
|
|||
# ~/.profile: executed by the command interpreter for login shells.
|
||||
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
|
||||
# exists.
|
||||
# see /usr/share/doc/bash/examples/startup-files for examples.
|
||||
# the files are located in the bash-doc package.
|
||||
|
||||
# the default umask is set in /etc/profile; for setting the umask
|
||||
# for ssh logins, install and configure the libpam-umask package.
|
||||
#umask 022
|
||||
|
||||
# if running bash
|
||||
if [ -n "$BASH_VERSION" ]; then
|
||||
# include .bashrc if it exists
|
||||
if [ -f "$HOME/.bashrc" ]; then
|
||||
. "$HOME/.bashrc"
|
||||
fi
|
||||
fi
|
||||
|
||||
# set PATH so it includes user's private bin if it exists
|
||||
if [ -d "$HOME/bin" ] ; then
|
||||
PATH="$HOME/bin:$PATH"
|
||||
fi
|
||||
|
||||
# set PATH so it includes user's private bin if it exists
|
||||
if [ -d "$HOME/.local/bin" ] ; then
|
||||
PATH="$HOME/.local/bin:$PATH"
|
||||
fi
|
|
@ -26,5 +26,9 @@ module.exports = [
|
|||
.setName("loop")
|
||||
.setDescription("Makes the queue play from the start when it has finished all the songs.")
|
||||
.toJSON(),
|
||||
new SlashCommandBuilder()
|
||||
.setName("invite")
|
||||
.setDescription("Invite me to your server.")
|
||||
.toJSON(),
|
||||
|
||||
]
|
||||
]
|
||||
|
|
14
index.js
14
index.js
|
@ -80,7 +80,7 @@ client.on("interactionCreate", async interaction => {
|
|||
interaction.followUp("An error has occured, name: " + e.name + ", details in console.");
|
||||
console.log(e);
|
||||
}
|
||||
await interaction.reply({ content: `**${video.title}** playing now. (because you couldn't go to spotify)` });
|
||||
await interaction.reply({ content: `**[${video.title}](${video.url})** playing now. (because you couldn't go to spotify)` });
|
||||
return;
|
||||
} else {
|
||||
serverQueue.songs.push({ title: video.title, url: video.url, requestedBy: interaction.member });
|
||||
|
@ -92,7 +92,7 @@ client.on("interactionCreate", async interaction => {
|
|||
console.log(e);
|
||||
}
|
||||
}
|
||||
await interaction.reply({ content: `**${video.title}** has been added to the queue. it will play when **${serverQueue.songs[serverQueue.index].title}** is done. (Because someone clown came before you)` });
|
||||
await interaction.reply({ content: `**[${video.title}](${video.url})** has been added to the queue. it will play when **${serverQueue.songs[serverQueue.index].title}** is done. (Because someone clown came before you)` });
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -164,7 +164,9 @@ client.on("interactionCreate", async interaction => {
|
|||
await interaction.reply("YES FINALLY YOU RELIEVE ME FROM THIS ENDLESS PLAYING");
|
||||
}
|
||||
} else await interaction.reply({ content: "Nothing is playing, are you an idiot or smth?" });
|
||||
}
|
||||
} else if(interaction.commandName == "invite"){
|
||||
interaction.reply("To invite me to your server, click [here](https://discord.com/api/oauth2/authorize?client_id=914122883473739807&permissions=36716800&scope=bot%20applications.commands).");
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
@ -197,8 +199,8 @@ async function playMusic(serverQueue) {
|
|||
return;
|
||||
}
|
||||
try {
|
||||
let stream = await ytdl(song.url, { filter: "audioonly" });
|
||||
let resource = createAudioResource(stream, { inputType: StreamType.WebmOpus });
|
||||
let stream = await ytdl(song.url, { filter: "audioonly", highWaterMark: 983554432 });
|
||||
let resource = createAudioResource(stream, { inputType: StreamType.Arbitrary });
|
||||
try{
|
||||
player.play(resource);
|
||||
} catch(e){
|
||||
|
@ -232,7 +234,7 @@ async function playMusic(serverQueue) {
|
|||
} else {
|
||||
//serverQueue.songs.shift();
|
||||
serverQueue.index++;
|
||||
serverQueue.textChannel.send({ content: `**${(serverQueue.songs[index+1] || serverQueue.songs[index]).title}** is now playing. (send help)` });
|
||||
if(serverQueue.songs[index+1]) serverQueue.textChannel.send({ content: `**${(serverQueue.songs[index+1]).title}** is now playing. (send help)` });
|
||||
try{
|
||||
playMusic(serverQueue);
|
||||
} catch(e){
|
||||
|
|
8
node_modules/.package-lock.json
generated
vendored
8
node_modules/.package-lock.json
generated
vendored
|
@ -1599,11 +1599,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/ytdl-core": {
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-4.9.1.tgz",
|
||||
"integrity": "sha512-6Jbp5RDhUEozlaJQAR+l8oV8AHsx3WUXxSyPxzE6wOIAaLql7Hjiy0ZM58wZoyj1YEenlEPjEqcJIjKYKxvHtQ==",
|
||||
"version": "4.10.0",
|
||||
"resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-4.10.0.tgz",
|
||||
"integrity": "sha512-RCCoSVTmMeBPH5NFR1fh3nkDU9okvWM0ZdN6plw6I5+vBBZVUEpOt8vjbSgprLRMmGUsmrQZJhvG1CHOat4mLA==",
|
||||
"dependencies": {
|
||||
"m3u8stream": "^0.8.3",
|
||||
"m3u8stream": "^0.8.4",
|
||||
"miniget": "^4.0.0",
|
||||
"sax": "^1.1.3"
|
||||
},
|
||||
|
|
283
node_modules/ytdl-core/lib/sig.js
generated
vendored
283
node_modules/ytdl-core/lib/sig.js
generated
vendored
|
@ -1,228 +1,108 @@
|
|||
const querystring = require('querystring');
|
||||
const Cache = require('./cache');
|
||||
const utils = require('./utils');
|
||||
const vm = require('vm');
|
||||
|
||||
|
||||
// A shared cache to keep track of html5player.js tokens.
|
||||
// A shared cache to keep track of html5player js functions.
|
||||
exports.cache = new Cache();
|
||||
|
||||
|
||||
/**
|
||||
* Extract signature deciphering tokens from html5player file.
|
||||
* Extract signature deciphering and n parameter transform functions from html5player file.
|
||||
*
|
||||
* @param {string} html5playerfile
|
||||
* @param {Object} options
|
||||
* @returns {Promise<Array.<string>>}
|
||||
*/
|
||||
exports.getTokens = (html5playerfile, options) => exports.cache.getOrSet(html5playerfile, async() => {
|
||||
exports.getFunctions = (html5playerfile, options) => exports.cache.getOrSet(html5playerfile, async() => {
|
||||
const body = await utils.exposedMiniget(html5playerfile, options).text();
|
||||
const tokens = exports.extractActions(body);
|
||||
if (!tokens || !tokens.length) {
|
||||
throw Error('Could not extract signature deciphering actions');
|
||||
const functions = exports.extractFunctions(body);
|
||||
if (!functions || !functions.length) {
|
||||
throw Error('Could not extract functions');
|
||||
}
|
||||
exports.cache.set(html5playerfile, tokens);
|
||||
return tokens;
|
||||
exports.cache.set(html5playerfile, functions);
|
||||
return functions;
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Decipher a signature based on action tokens.
|
||||
*
|
||||
* @param {Array.<string>} tokens
|
||||
* @param {string} sig
|
||||
* @returns {string}
|
||||
*/
|
||||
exports.decipher = (tokens, sig) => {
|
||||
sig = sig.split('');
|
||||
for (let i = 0, len = tokens.length; i < len; i++) {
|
||||
let token = tokens[i], pos;
|
||||
switch (token[0]) {
|
||||
case 'r':
|
||||
sig = sig.reverse();
|
||||
break;
|
||||
case 'w':
|
||||
pos = ~~token.slice(1);
|
||||
sig = swapHeadAndPosition(sig, pos);
|
||||
break;
|
||||
case 's':
|
||||
pos = ~~token.slice(1);
|
||||
sig = sig.slice(pos);
|
||||
break;
|
||||
case 'p':
|
||||
pos = ~~token.slice(1);
|
||||
sig.splice(0, pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sig.join('');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Swaps the first element of an array with one of given position.
|
||||
*
|
||||
* @param {Array.<Object>} arr
|
||||
* @param {number} position
|
||||
* @returns {Array.<Object>}
|
||||
*/
|
||||
const swapHeadAndPosition = (arr, position) => {
|
||||
const first = arr[0];
|
||||
arr[0] = arr[position % arr.length];
|
||||
arr[position] = first;
|
||||
return arr;
|
||||
};
|
||||
|
||||
|
||||
const jsVarStr = '[a-zA-Z_\\$][a-zA-Z_0-9]*';
|
||||
const jsSingleQuoteStr = `'[^'\\\\]*(:?\\\\[\\s\\S][^'\\\\]*)*'`;
|
||||
const jsDoubleQuoteStr = `"[^"\\\\]*(:?\\\\[\\s\\S][^"\\\\]*)*"`;
|
||||
const jsQuoteStr = `(?:${jsSingleQuoteStr}|${jsDoubleQuoteStr})`;
|
||||
const jsKeyStr = `(?:${jsVarStr}|${jsQuoteStr})`;
|
||||
const jsPropStr = `(?:\\.${jsVarStr}|\\[${jsQuoteStr}\\])`;
|
||||
const jsEmptyStr = `(?:''|"")`;
|
||||
const reverseStr = ':function\\(a\\)\\{' +
|
||||
'(?:return )?a\\.reverse\\(\\)' +
|
||||
'\\}';
|
||||
const sliceStr = ':function\\(a,b\\)\\{' +
|
||||
'return a\\.slice\\(b\\)' +
|
||||
'\\}';
|
||||
const spliceStr = ':function\\(a,b\\)\\{' +
|
||||
'a\\.splice\\(0,b\\)' +
|
||||
'\\}';
|
||||
const swapStr = ':function\\(a,b\\)\\{' +
|
||||
'var c=a\\[0\\];a\\[0\\]=a\\[b(?:%a\\.length)?\\];a\\[b(?:%a\\.length)?\\]=c(?:;return a)?' +
|
||||
'\\}';
|
||||
const actionsObjRegexp = new RegExp(
|
||||
`var (${jsVarStr})=\\{((?:(?:${
|
||||
jsKeyStr}${reverseStr}|${
|
||||
jsKeyStr}${sliceStr}|${
|
||||
jsKeyStr}${spliceStr}|${
|
||||
jsKeyStr}${swapStr
|
||||
}),?\\r?\\n?)+)\\};`);
|
||||
const actionsFuncRegexp = new RegExp(`${`function(?: ${jsVarStr})?\\(a\\)\\{` +
|
||||
`a=a\\.split\\(${jsEmptyStr}\\);\\s*` +
|
||||
`((?:(?:a=)?${jsVarStr}`}${
|
||||
jsPropStr
|
||||
}\\(a,\\d+\\);)+)` +
|
||||
`return a\\.join\\(${jsEmptyStr}\\)` +
|
||||
`\\}`);
|
||||
const reverseRegexp = new RegExp(`(?:^|,)(${jsKeyStr})${reverseStr}`, 'm');
|
||||
const sliceRegexp = new RegExp(`(?:^|,)(${jsKeyStr})${sliceStr}`, 'm');
|
||||
const spliceRegexp = new RegExp(`(?:^|,)(${jsKeyStr})${spliceStr}`, 'm');
|
||||
const swapRegexp = new RegExp(`(?:^|,)(${jsKeyStr})${swapStr}`, 'm');
|
||||
|
||||
|
||||
/**
|
||||
* Extracts the actions that should be taken to decipher a signature.
|
||||
*
|
||||
* This searches for a function that performs string manipulations on
|
||||
* the signature. We already know what the 3 possible changes to a signature
|
||||
* are in order to decipher it. There is
|
||||
*
|
||||
* * Reversing the string.
|
||||
* * Removing a number of characters from the beginning.
|
||||
* * Swapping the first character with another position.
|
||||
*
|
||||
* Note, `Array#slice()` used to be used instead of `Array#splice()`,
|
||||
* it's kept in case we encounter any older html5player files.
|
||||
*
|
||||
* After retrieving the function that does this, we can see what actions
|
||||
* it takes on a signature.
|
||||
* Extracts the actions that should be taken to decipher a signature
|
||||
* and tranform the n parameter
|
||||
*
|
||||
* @param {string} body
|
||||
* @returns {Array.<string>}
|
||||
*/
|
||||
exports.extractActions = body => {
|
||||
const objResult = actionsObjRegexp.exec(body);
|
||||
const funcResult = actionsFuncRegexp.exec(body);
|
||||
if (!objResult || !funcResult) { return null; }
|
||||
|
||||
const obj = objResult[1].replace(/\$/g, '\\$');
|
||||
const objBody = objResult[2].replace(/\$/g, '\\$');
|
||||
const funcBody = funcResult[1].replace(/\$/g, '\\$');
|
||||
|
||||
let result = reverseRegexp.exec(objBody);
|
||||
const reverseKey = result && result[1]
|
||||
.replace(/\$/g, '\\$')
|
||||
.replace(/\$|^'|^"|'$|"$/g, '');
|
||||
result = sliceRegexp.exec(objBody);
|
||||
const sliceKey = result && result[1]
|
||||
.replace(/\$/g, '\\$')
|
||||
.replace(/\$|^'|^"|'$|"$/g, '');
|
||||
result = spliceRegexp.exec(objBody);
|
||||
const spliceKey = result && result[1]
|
||||
.replace(/\$/g, '\\$')
|
||||
.replace(/\$|^'|^"|'$|"$/g, '');
|
||||
result = swapRegexp.exec(objBody);
|
||||
const swapKey = result && result[1]
|
||||
.replace(/\$/g, '\\$')
|
||||
.replace(/\$|^'|^"|'$|"$/g, '');
|
||||
|
||||
const keys = `(${[reverseKey, sliceKey, spliceKey, swapKey].join('|')})`;
|
||||
const myreg = `(?:a=)?${obj
|
||||
}(?:\\.${keys}|\\['${keys}'\\]|\\["${keys}"\\])` +
|
||||
`\\(a,(\\d+)\\)`;
|
||||
const tokenizeRegexp = new RegExp(myreg, 'g');
|
||||
const tokens = [];
|
||||
while ((result = tokenizeRegexp.exec(funcBody)) !== null) {
|
||||
let key = result[1] || result[2] || result[3];
|
||||
switch (key) {
|
||||
case swapKey:
|
||||
tokens.push(`w${result[4]}`);
|
||||
break;
|
||||
case reverseKey:
|
||||
tokens.push('r');
|
||||
break;
|
||||
case sliceKey:
|
||||
tokens.push(`s${result[4]}`);
|
||||
break;
|
||||
case spliceKey:
|
||||
tokens.push(`p${result[4]}`);
|
||||
break;
|
||||
exports.extractFunctions = body => {
|
||||
const functions = [];
|
||||
const extractManipulations = caller => {
|
||||
const functionName = utils.between(caller, `a=a.split("");`, `.`);
|
||||
if (!functionName) return '';
|
||||
const functionStart = `var ${functionName}={`;
|
||||
const ndx = body.indexOf(functionStart);
|
||||
if (ndx < 0) return '';
|
||||
const subBody = body.slice(ndx + functionStart.length - 1);
|
||||
return `var ${functionName}=${utils.cutAfterJSON(subBody)}`;
|
||||
};
|
||||
const extractDecipher = () => {
|
||||
const functionName = utils.between(body, `a.set("alr","yes");c&&(c=`, `(decodeURIC`);
|
||||
if (functionName && functionName.length) {
|
||||
const functionStart = `${functionName}=function(a)`;
|
||||
const ndx = body.indexOf(functionStart);
|
||||
if (ndx >= 0) {
|
||||
const subBody = body.slice(ndx + functionStart.length);
|
||||
let functionBody = `var ${functionStart}${utils.cutAfterJSON(subBody)}`;
|
||||
functionBody = `${extractManipulations(functionBody)};${functionBody};${functionName}(sig);`;
|
||||
functions.push(functionBody);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tokens;
|
||||
};
|
||||
const extractNCode = () => {
|
||||
const functionName = utils.between(body, `&&(b=a.get("n"))&&(b=`, `(b)`);
|
||||
if (functionName && functionName.length) {
|
||||
const functionStart = `${functionName}=function(a)`;
|
||||
const ndx = body.indexOf(functionStart);
|
||||
if (ndx >= 0) {
|
||||
const subBody = body.slice(ndx + functionStart.length);
|
||||
const functionBody = `var ${functionStart}${utils.cutAfterJSON(subBody)};${functionName}(ncode);`;
|
||||
functions.push(functionBody);
|
||||
}
|
||||
}
|
||||
};
|
||||
extractDecipher();
|
||||
extractNCode();
|
||||
return functions;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Apply decipher and n-transform to individual format
|
||||
*
|
||||
* @param {Object} format
|
||||
* @param {string} sig
|
||||
* @param {vm.Script} decipherScript
|
||||
* @param {vm.Script} nTransformScript
|
||||
*/
|
||||
exports.setDownloadURL = (format, sig) => {
|
||||
let decodedUrl;
|
||||
if (format.url) {
|
||||
decodedUrl = format.url;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
decodedUrl = decodeURIComponent(decodedUrl);
|
||||
} catch (err) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make some adjustments to the final url.
|
||||
const parsedUrl = new URL(decodedUrl);
|
||||
|
||||
// This is needed for a speedier download.
|
||||
// See https://github.com/fent/node-ytdl-core/issues/127
|
||||
parsedUrl.searchParams.set('ratebypass', 'yes');
|
||||
|
||||
if (sig) {
|
||||
// When YouTube provides a `sp` parameter the signature `sig` must go
|
||||
// into the parameter it specifies.
|
||||
// See https://github.com/fent/node-ytdl-core/issues/417
|
||||
parsedUrl.searchParams.set(format.sp || 'signature', sig);
|
||||
}
|
||||
|
||||
format.url = parsedUrl.toString();
|
||||
exports.setDownloadURL = (format, decipherScript, nTransformScript) => {
|
||||
const decipher = url => {
|
||||
const args = querystring.parse(url);
|
||||
if (!args.s || !decipherScript) return args.url;
|
||||
const components = new URL(decodeURIComponent(args.url));
|
||||
components.searchParams.set(args.sp ? args.sp : 'signature',
|
||||
decipherScript.runInNewContext({ sig: decodeURIComponent(args.s) }));
|
||||
return components.toString();
|
||||
};
|
||||
const ncode = url => {
|
||||
const components = new URL(decodeURIComponent(url));
|
||||
const n = components.searchParams.get('n');
|
||||
if (!n || !nTransformScript) return url;
|
||||
components.searchParams.set('n', nTransformScript.runInNewContext({ ncode: n }));
|
||||
return components.toString();
|
||||
};
|
||||
const cipher = !format.url;
|
||||
const url = format.url || format.signatureCipher || format.cipher;
|
||||
format.url = cipher ? ncode(decipher(url)) : ncode(url);
|
||||
delete format.signatureCipher;
|
||||
delete format.cipher;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Applies `sig.decipher()` to all format URL's.
|
||||
* Applies decipher and n parameter transforms to all format URL's.
|
||||
*
|
||||
* @param {Array.<Object>} formats
|
||||
* @param {string} html5player
|
||||
|
@ -230,16 +110,11 @@ exports.setDownloadURL = (format, sig) => {
|
|||
*/
|
||||
exports.decipherFormats = async(formats, html5player, options) => {
|
||||
let decipheredFormats = {};
|
||||
let tokens = await exports.getTokens(html5player, options);
|
||||
let functions = await exports.getFunctions(html5player, options);
|
||||
const decipherScript = functions.length ? new vm.Script(functions[0]) : null;
|
||||
const nTransformScript = functions.length > 1 ? new vm.Script(functions[1]) : null;
|
||||
formats.forEach(format => {
|
||||
let cipher = format.signatureCipher || format.cipher;
|
||||
if (cipher) {
|
||||
Object.assign(format, querystring.parse(cipher));
|
||||
delete format.signatureCipher;
|
||||
delete format.cipher;
|
||||
}
|
||||
const sig = tokens && format.s ? exports.decipher(tokens, format.s) : null;
|
||||
exports.setDownloadURL(format, sig);
|
||||
exports.setDownloadURL(format, decipherScript, nTransformScript);
|
||||
decipheredFormats[format.url] = format;
|
||||
});
|
||||
return decipheredFormats;
|
||||
|
|
4
node_modules/ytdl-core/package.json
generated
vendored
4
node_modules/ytdl-core/package.json
generated
vendored
|
@ -6,7 +6,7 @@
|
|||
"video",
|
||||
"download"
|
||||
],
|
||||
"version": "4.9.1",
|
||||
"version": "4.10.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/fent/node-ytdl-core.git"
|
||||
|
@ -35,7 +35,7 @@
|
|||
"lint:typings:fix": "tslint --fix typings/index.d.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"m3u8stream": "^0.8.3",
|
||||
"m3u8stream": "^0.8.4",
|
||||
"miniget": "^4.0.0",
|
||||
"sax": "^1.1.3"
|
||||
},
|
||||
|
|
1
node_modules/ytdl-core/typings/index.d.ts
generated
vendored
1
node_modules/ytdl-core/typings/index.d.ts
generated
vendored
|
@ -198,6 +198,7 @@ declare module 'ytdl-core' {
|
|||
liveBroadcastDetails?: {
|
||||
isLiveNow: boolean;
|
||||
startTimestamp: string;
|
||||
endTimestamp?: string;
|
||||
};
|
||||
uploadDate: string;
|
||||
}
|
||||
|
|
18
package-lock.json
generated
18
package-lock.json
generated
|
@ -17,7 +17,7 @@
|
|||
"ffmpeg-static": "^4.4.0",
|
||||
"tweetnacl": "^1.0.3",
|
||||
"yt-search": "^2.10.2",
|
||||
"ytdl-core": "^4.9.1"
|
||||
"ytdl-core": "^4.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@derhuerst/http-basic": {
|
||||
|
@ -1615,11 +1615,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/ytdl-core": {
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-4.9.1.tgz",
|
||||
"integrity": "sha512-6Jbp5RDhUEozlaJQAR+l8oV8AHsx3WUXxSyPxzE6wOIAaLql7Hjiy0ZM58wZoyj1YEenlEPjEqcJIjKYKxvHtQ==",
|
||||
"version": "4.10.0",
|
||||
"resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-4.10.0.tgz",
|
||||
"integrity": "sha512-RCCoSVTmMeBPH5NFR1fh3nkDU9okvWM0ZdN6plw6I5+vBBZVUEpOt8vjbSgprLRMmGUsmrQZJhvG1CHOat4mLA==",
|
||||
"dependencies": {
|
||||
"m3u8stream": "^0.8.3",
|
||||
"m3u8stream": "^0.8.4",
|
||||
"miniget": "^4.0.0",
|
||||
"sax": "^1.1.3"
|
||||
},
|
||||
|
@ -2885,11 +2885,11 @@
|
|||
}
|
||||
},
|
||||
"ytdl-core": {
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-4.9.1.tgz",
|
||||
"integrity": "sha512-6Jbp5RDhUEozlaJQAR+l8oV8AHsx3WUXxSyPxzE6wOIAaLql7Hjiy0ZM58wZoyj1YEenlEPjEqcJIjKYKxvHtQ==",
|
||||
"version": "4.10.0",
|
||||
"resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-4.10.0.tgz",
|
||||
"integrity": "sha512-RCCoSVTmMeBPH5NFR1fh3nkDU9okvWM0ZdN6plw6I5+vBBZVUEpOt8vjbSgprLRMmGUsmrQZJhvG1CHOat4mLA==",
|
||||
"requires": {
|
||||
"m3u8stream": "^0.8.3",
|
||||
"m3u8stream": "^0.8.4",
|
||||
"miniget": "^4.0.0",
|
||||
"sax": "^1.1.3"
|
||||
}
|
||||
|
|
|
@ -18,6 +18,6 @@
|
|||
"ffmpeg-static": "^4.4.0",
|
||||
"tweetnacl": "^1.0.3",
|
||||
"yt-search": "^2.10.2",
|
||||
"ytdl-core": "^4.9.1"
|
||||
"ytdl-core": "^4.10.0"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue