Add /invite

This commit is contained in:
a 2022-01-13 13:08:36 +01:00
parent 392e58cdca
commit 9c0a78c6be
9 changed files with 109 additions and 254 deletions

View file

@ -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

View file

@ -26,5 +26,9 @@ module.exports = [
.setName("loop") .setName("loop")
.setDescription("Makes the queue play from the start when it has finished all the songs.") .setDescription("Makes the queue play from the start when it has finished all the songs.")
.toJSON(), .toJSON(),
new SlashCommandBuilder()
.setName("invite")
.setDescription("Invite me to your server.")
.toJSON(),
] ]

View file

@ -80,7 +80,7 @@ client.on("interactionCreate", async interaction => {
interaction.followUp("An error has occured, name: " + e.name + ", details in console."); interaction.followUp("An error has occured, name: " + e.name + ", details in console.");
console.log(e); 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; return;
} else { } else {
serverQueue.songs.push({ title: video.title, url: video.url, requestedBy: interaction.member }); serverQueue.songs.push({ title: video.title, url: video.url, requestedBy: interaction.member });
@ -92,7 +92,7 @@ client.on("interactionCreate", async interaction => {
console.log(e); 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,6 +164,8 @@ client.on("interactionCreate", async interaction => {
await interaction.reply("YES FINALLY YOU RELIEVE ME FROM THIS ENDLESS PLAYING"); 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 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; return;
} }
try { try {
let stream = await ytdl(song.url, { filter: "audioonly" }); let stream = await ytdl(song.url, { filter: "audioonly", highWaterMark: 983554432 });
let resource = createAudioResource(stream, { inputType: StreamType.WebmOpus }); let resource = createAudioResource(stream, { inputType: StreamType.Arbitrary });
try{ try{
player.play(resource); player.play(resource);
} catch(e){ } catch(e){
@ -232,7 +234,7 @@ async function playMusic(serverQueue) {
} else { } else {
//serverQueue.songs.shift(); //serverQueue.songs.shift();
serverQueue.index++; 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{ try{
playMusic(serverQueue); playMusic(serverQueue);
} catch(e){ } catch(e){

8
node_modules/.package-lock.json generated vendored
View file

@ -1599,11 +1599,11 @@
} }
}, },
"node_modules/ytdl-core": { "node_modules/ytdl-core": {
"version": "4.9.1", "version": "4.10.0",
"resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-4.9.1.tgz", "resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-4.10.0.tgz",
"integrity": "sha512-6Jbp5RDhUEozlaJQAR+l8oV8AHsx3WUXxSyPxzE6wOIAaLql7Hjiy0ZM58wZoyj1YEenlEPjEqcJIjKYKxvHtQ==", "integrity": "sha512-RCCoSVTmMeBPH5NFR1fh3nkDU9okvWM0ZdN6plw6I5+vBBZVUEpOt8vjbSgprLRMmGUsmrQZJhvG1CHOat4mLA==",
"dependencies": { "dependencies": {
"m3u8stream": "^0.8.3", "m3u8stream": "^0.8.4",
"miniget": "^4.0.0", "miniget": "^4.0.0",
"sax": "^1.1.3" "sax": "^1.1.3"
}, },

281
node_modules/ytdl-core/lib/sig.js generated vendored
View file

@ -1,228 +1,108 @@
const querystring = require('querystring'); const querystring = require('querystring');
const Cache = require('./cache'); const Cache = require('./cache');
const utils = require('./utils'); const utils = require('./utils');
const vm = require('vm');
// A shared cache to keep track of html5player js functions.
// A shared cache to keep track of html5player.js tokens.
exports.cache = new Cache(); 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 {string} html5playerfile
* @param {Object} options * @param {Object} options
* @returns {Promise<Array.<string>>} * @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 body = await utils.exposedMiniget(html5playerfile, options).text();
const tokens = exports.extractActions(body); const functions = exports.extractFunctions(body);
if (!tokens || !tokens.length) { if (!functions || !functions.length) {
throw Error('Could not extract signature deciphering actions'); throw Error('Could not extract functions');
} }
exports.cache.set(html5playerfile, tokens); exports.cache.set(html5playerfile, functions);
return tokens; return functions;
}); });
/** /**
* Decipher a signature based on action tokens. * Extracts the actions that should be taken to decipher a signature
* * and tranform the n parameter
* @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.
* *
* @param {string} body * @param {string} body
* @returns {Array.<string>} * @returns {Array.<string>}
*/ */
exports.extractActions = body => { exports.extractFunctions = body => {
const objResult = actionsObjRegexp.exec(body); const functions = [];
const funcResult = actionsFuncRegexp.exec(body); const extractManipulations = caller => {
if (!objResult || !funcResult) { return null; } const functionName = utils.between(caller, `a=a.split("");`, `.`);
if (!functionName) return '';
const obj = objResult[1].replace(/\$/g, '\\$'); const functionStart = `var ${functionName}={`;
const objBody = objResult[2].replace(/\$/g, '\\$'); const ndx = body.indexOf(functionStart);
const funcBody = funcResult[1].replace(/\$/g, '\\$'); if (ndx < 0) return '';
const subBody = body.slice(ndx + functionStart.length - 1);
let result = reverseRegexp.exec(objBody); return `var ${functionName}=${utils.cutAfterJSON(subBody)}`;
const reverseKey = result && result[1] };
.replace(/\$/g, '\\$') const extractDecipher = () => {
.replace(/\$|^'|^"|'$|"$/g, ''); const functionName = utils.between(body, `a.set("alr","yes");c&&(c=`, `(decodeURIC`);
result = sliceRegexp.exec(objBody); if (functionName && functionName.length) {
const sliceKey = result && result[1] const functionStart = `${functionName}=function(a)`;
.replace(/\$/g, '\\$') const ndx = body.indexOf(functionStart);
.replace(/\$|^'|^"|'$|"$/g, ''); if (ndx >= 0) {
result = spliceRegexp.exec(objBody); const subBody = body.slice(ndx + functionStart.length);
const spliceKey = result && result[1] let functionBody = `var ${functionStart}${utils.cutAfterJSON(subBody)}`;
.replace(/\$/g, '\\$') functionBody = `${extractManipulations(functionBody)};${functionBody};${functionName}(sig);`;
.replace(/\$|^'|^"|'$|"$/g, ''); functions.push(functionBody);
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;
} }
} }
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 {Object} format
* @param {string} sig * @param {vm.Script} decipherScript
* @param {vm.Script} nTransformScript
*/ */
exports.setDownloadURL = (format, sig) => { exports.setDownloadURL = (format, decipherScript, nTransformScript) => {
let decodedUrl; const decipher = url => {
if (format.url) { const args = querystring.parse(url);
decodedUrl = format.url; if (!args.s || !decipherScript) return args.url;
} else { const components = new URL(decodeURIComponent(args.url));
return; components.searchParams.set(args.sp ? args.sp : 'signature',
} decipherScript.runInNewContext({ sig: decodeURIComponent(args.s) }));
return components.toString();
try { };
decodedUrl = decodeURIComponent(decodedUrl); const ncode = url => {
} catch (err) { const components = new URL(decodeURIComponent(url));
return; const n = components.searchParams.get('n');
} if (!n || !nTransformScript) return url;
components.searchParams.set('n', nTransformScript.runInNewContext({ ncode: n }));
// Make some adjustments to the final url. return components.toString();
const parsedUrl = new URL(decodedUrl); };
const cipher = !format.url;
// This is needed for a speedier download. const url = format.url || format.signatureCipher || format.cipher;
// See https://github.com/fent/node-ytdl-core/issues/127 format.url = cipher ? ncode(decipher(url)) : ncode(url);
parsedUrl.searchParams.set('ratebypass', 'yes'); delete format.signatureCipher;
delete format.cipher;
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();
}; };
/** /**
* Applies `sig.decipher()` to all format URL's. * Applies decipher and n parameter transforms to all format URL's.
* *
* @param {Array.<Object>} formats * @param {Array.<Object>} formats
* @param {string} html5player * @param {string} html5player
@ -230,16 +110,11 @@ exports.setDownloadURL = (format, sig) => {
*/ */
exports.decipherFormats = async(formats, html5player, options) => { exports.decipherFormats = async(formats, html5player, options) => {
let decipheredFormats = {}; 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 => { formats.forEach(format => {
let cipher = format.signatureCipher || format.cipher; exports.setDownloadURL(format, decipherScript, nTransformScript);
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);
decipheredFormats[format.url] = format; decipheredFormats[format.url] = format;
}); });
return decipheredFormats; return decipheredFormats;

View file

@ -6,7 +6,7 @@
"video", "video",
"download" "download"
], ],
"version": "4.9.1", "version": "4.10.0",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git://github.com/fent/node-ytdl-core.git" "url": "git://github.com/fent/node-ytdl-core.git"
@ -35,7 +35,7 @@
"lint:typings:fix": "tslint --fix typings/index.d.ts" "lint:typings:fix": "tslint --fix typings/index.d.ts"
}, },
"dependencies": { "dependencies": {
"m3u8stream": "^0.8.3", "m3u8stream": "^0.8.4",
"miniget": "^4.0.0", "miniget": "^4.0.0",
"sax": "^1.1.3" "sax": "^1.1.3"
}, },

View file

@ -198,6 +198,7 @@ declare module 'ytdl-core' {
liveBroadcastDetails?: { liveBroadcastDetails?: {
isLiveNow: boolean; isLiveNow: boolean;
startTimestamp: string; startTimestamp: string;
endTimestamp?: string;
}; };
uploadDate: string; uploadDate: string;
} }

18
package-lock.json generated
View file

@ -17,7 +17,7 @@
"ffmpeg-static": "^4.4.0", "ffmpeg-static": "^4.4.0",
"tweetnacl": "^1.0.3", "tweetnacl": "^1.0.3",
"yt-search": "^2.10.2", "yt-search": "^2.10.2",
"ytdl-core": "^4.9.1" "ytdl-core": "^4.10.0"
} }
}, },
"node_modules/@derhuerst/http-basic": { "node_modules/@derhuerst/http-basic": {
@ -1615,11 +1615,11 @@
} }
}, },
"node_modules/ytdl-core": { "node_modules/ytdl-core": {
"version": "4.9.1", "version": "4.10.0",
"resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-4.9.1.tgz", "resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-4.10.0.tgz",
"integrity": "sha512-6Jbp5RDhUEozlaJQAR+l8oV8AHsx3WUXxSyPxzE6wOIAaLql7Hjiy0ZM58wZoyj1YEenlEPjEqcJIjKYKxvHtQ==", "integrity": "sha512-RCCoSVTmMeBPH5NFR1fh3nkDU9okvWM0ZdN6plw6I5+vBBZVUEpOt8vjbSgprLRMmGUsmrQZJhvG1CHOat4mLA==",
"dependencies": { "dependencies": {
"m3u8stream": "^0.8.3", "m3u8stream": "^0.8.4",
"miniget": "^4.0.0", "miniget": "^4.0.0",
"sax": "^1.1.3" "sax": "^1.1.3"
}, },
@ -2885,11 +2885,11 @@
} }
}, },
"ytdl-core": { "ytdl-core": {
"version": "4.9.1", "version": "4.10.0",
"resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-4.9.1.tgz", "resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-4.10.0.tgz",
"integrity": "sha512-6Jbp5RDhUEozlaJQAR+l8oV8AHsx3WUXxSyPxzE6wOIAaLql7Hjiy0ZM58wZoyj1YEenlEPjEqcJIjKYKxvHtQ==", "integrity": "sha512-RCCoSVTmMeBPH5NFR1fh3nkDU9okvWM0ZdN6plw6I5+vBBZVUEpOt8vjbSgprLRMmGUsmrQZJhvG1CHOat4mLA==",
"requires": { "requires": {
"m3u8stream": "^0.8.3", "m3u8stream": "^0.8.4",
"miniget": "^4.0.0", "miniget": "^4.0.0",
"sax": "^1.1.3" "sax": "^1.1.3"
} }

View file

@ -18,6 +18,6 @@
"ffmpeg-static": "^4.4.0", "ffmpeg-static": "^4.4.0",
"tweetnacl": "^1.0.3", "tweetnacl": "^1.0.3",
"yt-search": "^2.10.2", "yt-search": "^2.10.2",
"ytdl-core": "^4.9.1" "ytdl-core": "^4.10.0"
} }
} }