getting rid of the original sharpbot commands directory
This commit is contained in:
parent
c2e2d75bd5
commit
84bf62a692
65 changed files with 0 additions and 3665 deletions
|
@ -1,42 +0,0 @@
|
|||
const responses = [
|
||||
'Unclear, ask again later',
|
||||
'Soon',
|
||||
'Yes',
|
||||
'Absolutely!',
|
||||
'Never',
|
||||
'Magic 8-ball is currently unavailable, please leave a message after the tone. \\*beep\\*',
|
||||
'When you are ready',
|
||||
'Hopefully',
|
||||
'Hopefully not',
|
||||
'Oh my, why would you even ask that?',
|
||||
'What kind of a question is that?',
|
||||
'Over my dead body!',
|
||||
'Haha, funny joke'
|
||||
];
|
||||
|
||||
function randomItem(array) {
|
||||
return array[Math.floor(Math.random() * array.length)];
|
||||
}
|
||||
|
||||
exports.run = (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'Please specify something to ask of the magic 8-ball!';
|
||||
}
|
||||
|
||||
let response = randomItem(responses);
|
||||
|
||||
const query = args.join(' ');
|
||||
|
||||
if (query.indexOf('ipodtouch0218') > -1 || query.indexOf('233360087979130882') > -1) {
|
||||
response = 'HAH';
|
||||
}
|
||||
|
||||
msg.edit(`${query} :8ball: | **${response}**`);
|
||||
};
|
||||
|
||||
|
||||
exports.info = {
|
||||
name: '8ball',
|
||||
usage: '8ball <question>',
|
||||
description: 'Asks the magic 8-ball a question'
|
||||
};
|
|
@ -1,24 +0,0 @@
|
|||
exports.run = (bot, msg, args) => {
|
||||
let parsed = bot.utils.parseArgs(args, 'd:');
|
||||
|
||||
if (parsed.leftover.length < 1) {
|
||||
throw 'Please provide some emojis to use!';
|
||||
}
|
||||
|
||||
let frames = parsed.leftover;
|
||||
let content = frames.join(' ');
|
||||
|
||||
if (content.indexOf('|') > -1) {
|
||||
frames = content.split('|');
|
||||
}
|
||||
|
||||
let delay = isNaN(parsed.options.d) ? 250 : parsed.options.d;
|
||||
|
||||
bot.utils.playAnimation(msg, delay, frames);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'anim',
|
||||
usage: 'anim [-d <delay>] <emoji> [emoji2] [...]',
|
||||
description: '"Animates" a series of emojis'
|
||||
};
|
|
@ -1,30 +0,0 @@
|
|||
const got = require('got');
|
||||
|
||||
function makeCommand(type, url, transformer) {
|
||||
return {
|
||||
run: async (bot, msg) => {
|
||||
msg.edit(':arrows_counterclockwise:');
|
||||
const { body } = await got(url);
|
||||
|
||||
let file;
|
||||
try {
|
||||
file = transformer(body);
|
||||
} catch (ignore) {
|
||||
return msg.error('Failed to transform image URL!');
|
||||
}
|
||||
|
||||
msg.delete();
|
||||
msg.channel.send({ files: [file] });
|
||||
},
|
||||
info: {
|
||||
name: type,
|
||||
usage: type,
|
||||
description: `Sends a random ${type} image`
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = [
|
||||
makeCommand('cat', 'http://thecatapi.com/api/images/get?format=xml', body => /<url>(.+?)<\/url>/.exec(body)[1]),
|
||||
makeCommand('dog', 'http://random.dog/woof', body => `http://random.dog/${body}`)
|
||||
];
|
|
@ -1,21 +0,0 @@
|
|||
const got = require('got');
|
||||
|
||||
exports.run = async (bot, msg) => {
|
||||
await msg.edit(':arrows_counterclockwise:');
|
||||
const { body } = await got('http://belikebill.azurewebsites.net/billgen-API.php?default=1', { encoding: null });
|
||||
|
||||
await msg.channel.send({
|
||||
file: {
|
||||
attachment: body,
|
||||
name: 'bill.jpg'
|
||||
}
|
||||
});
|
||||
|
||||
msg.delete();
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'bill',
|
||||
usage: 'bill',
|
||||
description: 'Be like Bill!'
|
||||
};
|
|
@ -1,46 +0,0 @@
|
|||
exports.methods = {
|
||||
encode: input => {
|
||||
return input.toString().split('')
|
||||
.map(c => c.charCodeAt(0).toString(2));
|
||||
},
|
||||
decode: input => {
|
||||
let _input = typeof input === 'string' ? input.split(' ') : input;
|
||||
return _input.map(c => parseInt(c, 2))
|
||||
.map(c => String.fromCharCode(c))
|
||||
.join('');
|
||||
}
|
||||
};
|
||||
|
||||
exports.run = (bot, msg, args) => {
|
||||
if (args.length < 2) {
|
||||
throw `Do \`${bot.config.prefix}help binary\` to see how to use this.`;
|
||||
}
|
||||
|
||||
let input = args.slice(1).join(' ');
|
||||
|
||||
if (args[0].match(/^enc(ode(Text)?)?$/i)) {
|
||||
msg.edit(this.methods.encode(input).join(' '));
|
||||
} else if (args[0].match(/^dec(ode(Text)?)?$/i)) {
|
||||
msg.edit(this.methods.decode(input));
|
||||
} else if (args[0].match(/^decToBin$/i)) {
|
||||
if (isNaN(input)) {
|
||||
throw 'Input must be a number!';
|
||||
}
|
||||
|
||||
msg.edit(parseInt(input).toString(2));
|
||||
} else if (args[0].match(/^binToDec$/i)) {
|
||||
if (isNaN(input)) {
|
||||
throw 'Input must be a number!';
|
||||
}
|
||||
|
||||
msg.edit(parseInt(input, 2));
|
||||
} else {
|
||||
throw `Unknown sub command: \`${args[0]}\``;
|
||||
}
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'binary',
|
||||
usage: 'binary <encodeText|decodeText|decToBin|binToDec> <input>',
|
||||
description: 'Convert your input to/from binary'
|
||||
};
|
|
@ -1,15 +0,0 @@
|
|||
const randomizeCase = word => word.split('').map(c => Math.random() > 0.5 ? c.toUpperCase() : c.toLowerCase()).join('');
|
||||
|
||||
exports.run = (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'Please provide some text to clapify';
|
||||
}
|
||||
|
||||
msg.edit(args.map(randomizeCase).join(':clap:'));
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'clap',
|
||||
usage: 'clap <text>',
|
||||
description: 'Clapifies your text'
|
||||
};
|
|
@ -1,59 +0,0 @@
|
|||
exports.run = async (bot, msg, args) => {
|
||||
|
||||
const parsedArgs = bot.utils.parseArgs(args, ['d:', 's:']);
|
||||
|
||||
if (parsedArgs.leftover.length < 1) {
|
||||
throw 'Please provide a secret message';
|
||||
}
|
||||
|
||||
let message = parsedArgs.leftover.join(' ');
|
||||
let delay = isNaN(parsedArgs.options.d) ? 5000 : parseInt(parsedArgs.options.d);
|
||||
delay = (delay < 100) ? 100 : delay;
|
||||
const style = (typeof parsedArgs.options.s === 'string') ? parsedArgs.options.s : 'plain';
|
||||
|
||||
msg.delete();
|
||||
|
||||
switch (style) {
|
||||
case 'embed':
|
||||
message = {
|
||||
embed: bot.utils.embed(
|
||||
`This message self-destructs in ${delay / 1000} seconds.`,
|
||||
message,
|
||||
[],
|
||||
{
|
||||
inline: true,
|
||||
footer: 'Secret Message'
|
||||
}
|
||||
)
|
||||
};
|
||||
break;
|
||||
case 'inline':
|
||||
message = `*This message self-destructs in ${delay / 1000} seconds.*\n${message}`;
|
||||
break;
|
||||
case 'code':
|
||||
message = `*This message self-destructs in ${delay / 1000} seconds.*\n\`\`\`${message}\`\`\``;
|
||||
break;
|
||||
}
|
||||
|
||||
(await msg.channel.send(message)).delete(delay);
|
||||
};
|
||||
|
||||
|
||||
exports.info = {
|
||||
name: 'destruct',
|
||||
usage: 'destruct [-d delay in ms] [-s <embed|inline|code|plain>] <message>',
|
||||
description: 'creates a self-destructing message',
|
||||
options: [
|
||||
{
|
||||
name: '-d',
|
||||
usage: '-d <delay in ms>',
|
||||
description: 'Sets the time (in ms) for the message to be deleted. (Default: 5 seconds)'
|
||||
},
|
||||
{
|
||||
name: '-s',
|
||||
usage: '-s <embed|inline|code|plain>',
|
||||
description: 'Sets the message style (default: plain)'
|
||||
}
|
||||
],
|
||||
credits: '<@140541588915879936>' // Doxylamin#4539
|
||||
};
|
|
@ -1,40 +0,0 @@
|
|||
const mapping = {
|
||||
' ': ' ',
|
||||
'0': ':zero:',
|
||||
'1': ':one:',
|
||||
'2': ':two:',
|
||||
'3': ':three:',
|
||||
'4': ':four:',
|
||||
'5': ':five:',
|
||||
'6': ':six:',
|
||||
'7': ':seven:',
|
||||
'8': ':eight:',
|
||||
'9': ':nine:',
|
||||
'!': ':grey_exclamation:',
|
||||
'?': ':grey_question:',
|
||||
'#': ':hash:',
|
||||
'*': ':asterisk:'
|
||||
};
|
||||
|
||||
'abcdefghijklmnopqrstuvwxyz'.split('').forEach(c => {
|
||||
mapping[c] = mapping[c.toUpperCase()] = ` :regional_indicator_${c}:`;
|
||||
});
|
||||
|
||||
exports.run = (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'You must provide some text to fanceh-fy!';
|
||||
}
|
||||
|
||||
msg.edit(
|
||||
args.join(' ')
|
||||
.split('')
|
||||
.map(c => mapping[c] || c)
|
||||
.join('')
|
||||
);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'fanceh',
|
||||
usage: 'fanceh <text>',
|
||||
description: 'Renders text in big emoji letters'
|
||||
};
|
|
@ -1,52 +0,0 @@
|
|||
const figlet = require('figlet');
|
||||
|
||||
exports.run = (bot, msg, args) => {
|
||||
// -l -- List all fonts
|
||||
// -f <font> -- Set font
|
||||
const parsed = bot.utils.parseArgs(args, ['l', 'f:']);
|
||||
|
||||
if (parsed.options.l) {
|
||||
bot.utils.textUpload(figlet.fontsSync().join('\n')).then(({ url }) => {
|
||||
if (!url) {
|
||||
return msg.error('Failed to upload fonts list!');
|
||||
}
|
||||
|
||||
msg.edit({
|
||||
embed: bot.utils.embed('Available Fonts', `A list of available fonts can be found [here](${url}).`)
|
||||
}).then(m => m.delete(5000));
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (parsed.leftover.length < 1) {
|
||||
throw 'You must provide some text to render!';
|
||||
}
|
||||
|
||||
const options = {};
|
||||
|
||||
if (parsed.options.f) {
|
||||
options.font = parsed.options.f;
|
||||
}
|
||||
|
||||
msg.delete();
|
||||
|
||||
const input = parsed.leftover.join(' ');
|
||||
msg.channel.send(`\`\`\`\n${figlet.textSync(input, options)}\n\`\`\``);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'figlet',
|
||||
usage: 'figlet <text>',
|
||||
description: 'Renders fancy ASCII text',
|
||||
options: [
|
||||
{
|
||||
name: '-f',
|
||||
usage: '-f <font>',
|
||||
description: 'Sets the font to use'
|
||||
},
|
||||
{
|
||||
name: '-l',
|
||||
description: 'Lists all available fonts'
|
||||
}
|
||||
]
|
||||
};
|
|
@ -1,22 +0,0 @@
|
|||
const mapping = '¡"#$%⅋,)(*+\'-˙/0ƖᄅƐㄣϛ9ㄥ86:;<=>?@∀qƆpƎℲפHIſʞ˥WNOԀQɹS┴∩ΛMX⅄Z[/]^_`ɐqɔpǝɟƃɥᴉɾʞlɯuodbɹsʇnʌʍxʎz{|}~';
|
||||
// Start with the character '!'
|
||||
const OFFSET = '!'.charCodeAt(0);
|
||||
|
||||
exports.run = (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'You must provide text to flip!';
|
||||
}
|
||||
|
||||
msg.edit(
|
||||
args.join(' ').split('')
|
||||
.map(c => c.charCodeAt(0) - OFFSET)
|
||||
.map(c => mapping[c] || ' ')
|
||||
.reverse().join('')
|
||||
);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'fliptext',
|
||||
usage: 'fliptext <text>',
|
||||
description: 'Flips your text!'
|
||||
};
|
|
@ -1,29 +0,0 @@
|
|||
const got = require('got');
|
||||
|
||||
// Public API key provided by Giphy for anyone to use.
|
||||
const API_KEY = 'dc6zaTOxFJmzC';
|
||||
|
||||
exports.run = async (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'You must provide something to search for!';
|
||||
}
|
||||
|
||||
const res = await got(`http://api.giphy.com/v1/gifs/random?api_key=${API_KEY}&tag=${encodeURIComponent(args.join(' '))}`, { json: true });
|
||||
|
||||
if (!res || !res.body || !res.body.data) {
|
||||
throw 'Failed to find a GIF that matched your query!';
|
||||
}
|
||||
|
||||
msg.delete();
|
||||
msg.channel.send({
|
||||
embed: bot.utils.embed('', '', [], { image: res.body.data.image_url })
|
||||
});
|
||||
};
|
||||
|
||||
// async function findRandom(query) {}
|
||||
|
||||
exports.info = {
|
||||
name: 'gif',
|
||||
usage: 'gif <query>',
|
||||
description: 'Searches Giphy for GIFs'
|
||||
};
|
|
@ -1,12 +0,0 @@
|
|||
exports.run = function(bot, msg, args) {
|
||||
if (args.length === 0) {
|
||||
throw 'You must input text to be transformed.';
|
||||
}
|
||||
msg.edit(args.map(arg => arg[0].toUpperCase() + arg.slice(1).toLowerCase()).join(' '));
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'initial',
|
||||
usage: 'initial <text>',
|
||||
description: 'Transforms the text you input into Initial Caps'
|
||||
};
|
|
@ -1,34 +0,0 @@
|
|||
exports.run = function (bot, msg, args) {
|
||||
if (args.length < 1) {
|
||||
throw 'Please provide an emoji to enlarge.';
|
||||
}
|
||||
|
||||
if (args[0].charCodeAt(0) >= 55296) {
|
||||
throw 'Cannot enlarge built-in discord emoji.';
|
||||
}
|
||||
|
||||
const match = args[0].match(/<:[a-zA-Z0-9_-]+:(\d{18})>/);
|
||||
|
||||
if (!match || !match[1]) {
|
||||
throw 'Please provide a valid emoji.';
|
||||
}
|
||||
|
||||
const emoji = bot.emojis.get(match[1]);
|
||||
|
||||
if (!emoji) {
|
||||
throw 'That emoji could not be identified!';
|
||||
}
|
||||
|
||||
msg.delete();
|
||||
msg.channel.send({
|
||||
files: [
|
||||
emoji.url
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'jumbo',
|
||||
usage: 'jumbo <emoji>',
|
||||
description: 'Enlarges emojis!'
|
||||
};
|
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
Generating the inverse replacements isnt insanely expensive,
|
||||
but I feel bad repeating an O(n) operation on every call of run
|
||||
*/
|
||||
let _inverseReplacementsCached = null;
|
||||
const getInverseReplacements = replacements => {
|
||||
if (_inverseReplacementsCached) {
|
||||
return _inverseReplacementsCached;
|
||||
}
|
||||
const inverseReplacements = new Map();
|
||||
Object.keys(replacements)
|
||||
.map(letter => {
|
||||
replacements[letter].forEach(replacement => {
|
||||
inverseReplacements.set(new RegExp(global.utils.quoteRegex(replacement), 'gi'), letter);
|
||||
});
|
||||
});
|
||||
|
||||
_inverseReplacementsCached = inverseReplacements;
|
||||
|
||||
return inverseReplacements;
|
||||
};
|
||||
|
||||
exports.run = function (bot, message, args) {
|
||||
const parsedArgs = client.parseArgs(args, ['e', 't']);
|
||||
|
||||
if (parsedArgs.leftover.length < 1) {
|
||||
throw 'Provide text to be leeted.';
|
||||
}
|
||||
|
||||
let parsed;
|
||||
|
||||
if (parsedArgs.options.e) {
|
||||
const extendedLeetReplacements = {
|
||||
'a': ['4', '@', '/-\\', 'Д'],
|
||||
'b': ['ß'],
|
||||
'c': ['¢', '©'],
|
||||
'e': ['3', '€'],
|
||||
'f': ['ph', 'ƒ'],
|
||||
'g': ['6'],
|
||||
'i': ['1', '!'],
|
||||
'l': ['7'],
|
||||
'n': ['И', 'ท'],
|
||||
'q': ['Ø'],
|
||||
'r': ['®', 'Я'],
|
||||
's': ['5', '$', '§'],
|
||||
't': ['†'],
|
||||
'u': ['|_|', 'µ', 'บ'],
|
||||
'v': ['\\/'],
|
||||
'w': ['\\/\\/', 'VV', 'Ш', 'พ'],
|
||||
'x': ['Ж', '×'],
|
||||
'y': ['¥']
|
||||
};
|
||||
|
||||
const inverseReplacements = getInverseReplacements(extendedLeetReplacements);
|
||||
if (parsedArgs.options.t) {
|
||||
parsed = parsedArgs.leftover.join(' ');
|
||||
|
||||
for (let [replacement, origValue] of inverseReplacements) {
|
||||
parsed = parsed.replace(replacement, origValue);
|
||||
}
|
||||
} else {
|
||||
parsed = parsedArgs.leftover
|
||||
.join(' ')
|
||||
.replace(/[a-z]/gi, str => {
|
||||
let selection = bot.utils.randomSelection(extendedLeetReplacements[str.toLowerCase()] || [str]);
|
||||
selection = bot.utils.quoteRegex(selection);
|
||||
return selection;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const simpleLeetReplacements = '4BCD3F6H1JKLMN0PQR57';
|
||||
if (parsedArgs.options.t) {
|
||||
parsed = parsedArgs.leftover.join(' ').replace(/[a-z0-9]/g, function (a) {
|
||||
let foundInReplacements = simpleLeetReplacements.indexOf(a);
|
||||
if (foundInReplacements === -1) {
|
||||
return a;
|
||||
}
|
||||
return String.fromCharCode(97 + foundInReplacements);
|
||||
});
|
||||
} else {
|
||||
parsed = parsedArgs.leftover.join(' ').replace(/[a-z]/g, function f(a) {
|
||||
return simpleLeetReplacements[parseInt(a, 36) - 10] || a.replace(/[a-t]/gi, f);
|
||||
}).toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
message.delete();
|
||||
message.channel.send(parsed);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'leet',
|
||||
usage: 'leet <text>',
|
||||
description: 'Talk like true gamers',
|
||||
options: [
|
||||
{
|
||||
name: '-e',
|
||||
usage: '-e',
|
||||
description: 'Use extended l33t $p3@k'
|
||||
},
|
||||
{
|
||||
name: '-t',
|
||||
usage: '-t',
|
||||
description: 'Translate from leet speak into English'
|
||||
}
|
||||
]
|
||||
};
|
|
@ -1,120 +0,0 @@
|
|||
const got = require('got');
|
||||
let templates = [];
|
||||
|
||||
function getMeme(name) {
|
||||
return templates.find(m => m.name.toLowerCase() === name.toLowerCase());
|
||||
}
|
||||
|
||||
function cleanInput(input) {
|
||||
if (!input) return '';
|
||||
return input.replace(/"/g, '\'\'').replace(/#/g, '~h')
|
||||
.replace(/-/g, '--').replace(/_/g, '__')
|
||||
.replace(/ /g, '_').replace(/\?/g, '~q')
|
||||
.replace(/%/g, '~p').replace(/\//g, '~s');
|
||||
}
|
||||
|
||||
exports.init = () => {
|
||||
got('https://memegen.link/templates/').then(res => {
|
||||
let data = JSON.parse(res.body);
|
||||
templates = [];
|
||||
let promises = [];
|
||||
for (let key in data) {
|
||||
promises.push(_loadMeme(data[key]));
|
||||
}
|
||||
|
||||
Promise.all(promises).then(() => {
|
||||
templates = templates.filter(e => !!e);
|
||||
templates.sort((a, b) => a.name.localeCompare(b.name));
|
||||
}).catch(console.error);
|
||||
}).catch(console.error);
|
||||
|
||||
function _loadMeme(url) {
|
||||
return got(url).then(res => {
|
||||
let singleData = JSON.parse(res.body);
|
||||
|
||||
templates.push({
|
||||
name: url.replace(/https:\/\/memegen\.link\/api\/templates\/(.*)/, '$1'),
|
||||
url: url.replace('/api/templates', ''),
|
||||
styles: singleData.styles
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
exports.run = async (bot, msg, args) => {
|
||||
if (templates.length < 1) {
|
||||
throw 'The memes haven\'t loaded yet!';
|
||||
}
|
||||
|
||||
if (/^(h(elp)?|\?)$/i.test(args[0])) {
|
||||
return bot.commands.get('help').run(bot, msg, 'meme');
|
||||
}
|
||||
|
||||
if (/^(ls|list|s(earch)?)$/i.test(args[0])) {
|
||||
msg.delete();
|
||||
return (await msg.channel.send({
|
||||
embed: bot.utils.embed('Available Memes', '*This message will vanish in 30 seconds*\n\n' + templates.map(meme => `- \`${meme.name}\``).join('\n'))
|
||||
})).delete(30000);
|
||||
}
|
||||
|
||||
if (/^(i(nf(o)?)?)$/i.test(args[0])) {
|
||||
if (args.length < 2) {
|
||||
throw 'You must provide a meme to get info about!';
|
||||
}
|
||||
|
||||
let info = getMeme(args[1]);
|
||||
if (!info) {
|
||||
throw `That is not a valid meme! Do \`${bot.config.prefix}${this.info.name} list\` to see available memes.`;
|
||||
}
|
||||
|
||||
msg.delete();
|
||||
return (await msg.channel.send({
|
||||
embed: bot.utils.embed(`\`${info.name}\``, `Styles: ${info.styles && info.styles.length > 1 ? info.styles.map(s => `\n- \`${s}\``).join('') : 'None'}`)
|
||||
})).delete(15000);
|
||||
}
|
||||
|
||||
let input = args.join(' ');
|
||||
let parts = input.split('|').map(p => p.trim());
|
||||
|
||||
if (parts.length < 3) {
|
||||
throw `No message was provided! Do \`${bot.config.prefix}help ${this.info.name}\` for info on how to use this.`;
|
||||
}
|
||||
|
||||
let meme = getMeme(args[0]);
|
||||
if (!meme) {
|
||||
throw `That is not a valid meme! Do \`${bot.config.prefix}${this.info.name} list\` to see available memes.`;
|
||||
}
|
||||
|
||||
let topText = cleanInput(parts[1]);
|
||||
let bottomText = cleanInput(parts[2]);
|
||||
|
||||
if (!topText || !bottomText) {
|
||||
throw 'Empty message!';
|
||||
}
|
||||
|
||||
let url = `${meme.url}/${cleanInput(parts[1])}/${cleanInput(parts[2])}.jpg`;
|
||||
if (parts[3]) url += `?alt=${encodeURIComponent(parts[3])}`;
|
||||
|
||||
await msg.edit(':arrows_counterclockwise:');
|
||||
await msg.channel.send({
|
||||
files: [
|
||||
{
|
||||
attachment: url,
|
||||
name: parts[0] + '.jpg'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
msg.delete();
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'meme',
|
||||
usage: 'meme list | info <name> | [<name> | <line 1> | <line 2> | [style]]',
|
||||
description: 'Helps you generate meme images with custom text',
|
||||
examples: [
|
||||
'meme info sad-biden',
|
||||
'meme facepalm | please, oh please | rtfm',
|
||||
'meme sad-biden | sad joe biden | doesn\'t have discord | scowl'
|
||||
]
|
||||
};
|
|
@ -1,12 +0,0 @@
|
|||
exports.run = function (bot, msg, args) {
|
||||
if (args.length < 1) {
|
||||
throw 'You must input text to be reversed!';
|
||||
}
|
||||
msg.edit(args.join(' ').split('').reverse().join(''));
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'reverse',
|
||||
usage: 'reverse <text>',
|
||||
description: 'Reverses the text you input'
|
||||
};
|
|
@ -1,41 +0,0 @@
|
|||
const Roll = require('roll');
|
||||
const roller = new Roll();
|
||||
|
||||
exports.run = function (bot, msg, args) {
|
||||
if (args.length < 1) {
|
||||
throw 'You must specify in dice notation (XdY)';
|
||||
}
|
||||
|
||||
let reason = '';
|
||||
let footer = '';
|
||||
|
||||
footer += `:game_die: **${args[0]}**`;
|
||||
if (args.length > 1) {
|
||||
reason = args.splice(1).join(' ');
|
||||
footer += ` | ${reason}`;
|
||||
}
|
||||
|
||||
let results = roller.roll(args[0]);
|
||||
|
||||
msg.delete();
|
||||
|
||||
let embed = bot.utils.embed(
|
||||
`Total: ${results.result}`,
|
||||
`${[].concat.apply([], results.rolled).join(', ').substr(0, 1800)}`,
|
||||
[
|
||||
{
|
||||
name: '\u200b',
|
||||
value: footer
|
||||
}
|
||||
]
|
||||
);
|
||||
|
||||
msg.channel.send({ embed });
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'roll',
|
||||
usage: 'roll XdY <reason>',
|
||||
description: 'rolls X dice with Y sides. Supports standard dice notation',
|
||||
credits: '<@136641861073764352>' // Abyss#0473
|
||||
};
|
|
@ -1,18 +0,0 @@
|
|||
exports.run = function (bot, msg) {
|
||||
if (msg.mentions.users.size < 1) {
|
||||
throw '@mention some people to shoot!';
|
||||
}
|
||||
|
||||
let output = msg.mentions.users.map(m => `**${m}** :gun:`).join('\n');
|
||||
|
||||
msg.delete();
|
||||
msg.channel.send({
|
||||
embed: bot.utils.embed(`${bot.user.username} is on a killing spree!`, output)
|
||||
});
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'shoot',
|
||||
usage: 'shoot <user>',
|
||||
description: 'Shoots yer friendz!'
|
||||
};
|
|
@ -1,24 +0,0 @@
|
|||
const ascii = `
|
||||
\`\`\`
|
||||
_______ _________ _________ , ,
|
||||
/ | / | |
|
||||
| | | | |
|
||||
| | | | |
|
||||
\\_____, | | _______, |________|
|
||||
\\ | | | | |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
______/ ____|____ \\________| | |
|
||||
\u200b
|
||||
\`\`\`
|
||||
`;
|
||||
|
||||
exports.run = function (bot, msg) {
|
||||
msg.edit(ascii);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'sigh',
|
||||
usage: 'sigh',
|
||||
description: 'Dramatic sigh text'
|
||||
};
|
|
@ -1,22 +0,0 @@
|
|||
exports.run = (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'You must provide text to space out!';
|
||||
}
|
||||
|
||||
let amount = 2;
|
||||
|
||||
if (!isNaN(args[0])) {
|
||||
amount = parseInt(args[0]);
|
||||
(amount < 1) && (amount = 1);
|
||||
(amount > 15) && (amount = 15);
|
||||
args = args.slice(1);
|
||||
}
|
||||
|
||||
msg.edit(args.join(' '.repeat(amount / 2)).split('').join(' '.repeat(amount)));
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'space',
|
||||
usage: 'space [amount] <text>',
|
||||
description: 'Spaces out text to look all dramatic n\' stuff'
|
||||
};
|
|
@ -1,57 +0,0 @@
|
|||
const mappings = (function (object) {
|
||||
let output = [];
|
||||
|
||||
for (let key in object) {
|
||||
output.push({
|
||||
regex: new RegExp(key, 'ig'),
|
||||
replacement: object[key]
|
||||
});
|
||||
}
|
||||
|
||||
return output;
|
||||
})({
|
||||
a: '\u1D00',
|
||||
b: '\u0299',
|
||||
c: '\u1D04',
|
||||
d: '\u1D05',
|
||||
e: '\u1D07',
|
||||
f: '\uA730',
|
||||
g: '\u0262',
|
||||
h: '\u029C',
|
||||
i: '\u026A',
|
||||
j: '\u1D0A',
|
||||
k: '\u1D0B',
|
||||
l: '\u029F',
|
||||
m: '\u1D0D',
|
||||
n: '\u0274',
|
||||
o: '\u1D0F',
|
||||
p: '\u1D18',
|
||||
q: '\u0071',
|
||||
r: '\u0280',
|
||||
s: '\uA731',
|
||||
t: '\u1D1B',
|
||||
u: '\u1D1C',
|
||||
v: '\u1D20',
|
||||
w: '\u1D21',
|
||||
x: '\u0078',
|
||||
y: '\u028F',
|
||||
z: '\u1D22'
|
||||
});
|
||||
|
||||
exports.run = (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'You must provide some text to shrink!';
|
||||
}
|
||||
|
||||
let output = args.join(' ');
|
||||
mappings.forEach(replacer => output = output.replace(replacer.regex, replacer.replacement));
|
||||
|
||||
msg.delete();
|
||||
msg.channel.send(output);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'tiny',
|
||||
usage: 'tiny <text>',
|
||||
description: 'Converts your text to tiny letters!'
|
||||
};
|
|
@ -1,52 +0,0 @@
|
|||
const got = require('got');
|
||||
|
||||
exports.run = async (bot, msg, args) => {
|
||||
let id;
|
||||
|
||||
if (args[0] === 'latest') {
|
||||
id = (await getLatest()).num;
|
||||
} else {
|
||||
id = parseInt(args[0]);
|
||||
if (isNaN(id)) {
|
||||
id = await getRandom();
|
||||
}
|
||||
}
|
||||
|
||||
// Avoid the 404 page
|
||||
while (id === 404) {
|
||||
id = await getRandom();
|
||||
}
|
||||
|
||||
const info = await getInfo(id);
|
||||
|
||||
msg.delete();
|
||||
msg.channel.send({
|
||||
embed: bot.utils.embed(`[${id}] ${info.title}`, '', [], {
|
||||
image: info.img,
|
||||
// Color of the XKCD website.
|
||||
color: [150, 168, 199],
|
||||
url: `http://xkcd.com/${id}`
|
||||
}).setFooter(info.alt)
|
||||
});
|
||||
};
|
||||
|
||||
async function getInfo(id) {
|
||||
return (await got(`http://xkcd.com/${id}/info.0.json`, { json: true })).body;
|
||||
}
|
||||
|
||||
async function getLatest() {
|
||||
return (await got('http://xkcd.com/info.0.json', { json: true })).body;
|
||||
}
|
||||
|
||||
async function getRandom() {
|
||||
const latest = await getLatest();
|
||||
const max = latest.num;
|
||||
|
||||
return Math.floor(Math.random() * max);
|
||||
}
|
||||
|
||||
exports.info = {
|
||||
name: 'xkcd',
|
||||
usage: 'xkcd [latest|<id>]',
|
||||
description: 'Fetches random or specific XKCD comics'
|
||||
};
|
|
@ -1,67 +0,0 @@
|
|||
const { RichEmbed } = require('discord.js');
|
||||
|
||||
const rgbToHSL = (red, green, blue) => {
|
||||
let r = red / 255;
|
||||
let g = green / 255;
|
||||
let b = blue / 255;
|
||||
|
||||
let max = Math.max(r, g, b), min = Math.min(r, g, b);
|
||||
let h, s, l = (max + min) / 2;
|
||||
|
||||
if (max == min) {
|
||||
h = s = 0; // achromatic
|
||||
} else {
|
||||
let d = max - min;
|
||||
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
||||
switch (max) {
|
||||
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
|
||||
case g: h = (b - r) / d + 2; break;
|
||||
case b: h = (r - g) / d + 4; break;
|
||||
}
|
||||
h /= 6;
|
||||
}
|
||||
|
||||
h = Math.round(h * 360);
|
||||
s = Math.round(s * 100);
|
||||
l = Math.round(l * 100);
|
||||
|
||||
return { hue: h, saturation: s, lightness: l };
|
||||
};
|
||||
|
||||
const resolveColor = input => {
|
||||
if (input.startsWith('#')) input = input.substr(1);
|
||||
if (input.length === 3) input = input.split('').map(c => c + c).join('');
|
||||
|
||||
let hex = input;
|
||||
let [red, green, blue] = [hex.substr(0, 2), hex.substr(2, 2), hex.substr(4, 2)]
|
||||
.map(value => parseInt(value, 16));
|
||||
let { hue, saturation, lightness } = rgbToHSL(red, green, blue);
|
||||
|
||||
return { hex, red, green, blue, hue, saturation, lightness };
|
||||
};
|
||||
|
||||
exports.run = (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'Please provide a color!';
|
||||
}
|
||||
|
||||
if (!/^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/.test(args[0])) {
|
||||
throw 'The color must be in the format of `#RRGGBB` or `#RGB`!';
|
||||
}
|
||||
|
||||
let color = resolveColor(args[0]);
|
||||
|
||||
msg.delete();
|
||||
msg.channel.send({
|
||||
embed: new RichEmbed()
|
||||
.setDescription(`Hex: \`#${color.hex}\`\nRGB: \`${color.red}, ${color.green}, ${color.blue}\`\nHSL: \`${color.hue}, ${color.saturation}, ${color.lightness}\``)
|
||||
.setImage(`http://placehold.it/500/${color.hex}/${color.hex}`)
|
||||
.setColor(`${color.hex}`)
|
||||
});
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'color',
|
||||
usage: 'color <hex>',
|
||||
description: 'Shows information and a preview of a hex color'
|
||||
};
|
|
@ -1,53 +0,0 @@
|
|||
exports.run = async (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'Please provide an emoji to gather info on!';
|
||||
}
|
||||
|
||||
if (args[0].charCodeAt(0) >= 55296) {
|
||||
msg.delete();
|
||||
|
||||
return (await msg.channel.send({
|
||||
embed: bot.utils.embed(args[0], 'Built-in **Discord** emoji.')
|
||||
})).delete(15000);
|
||||
}
|
||||
|
||||
const match = args[0].match(/<:[a-zA-Z0-9_-]+:(\d{18})>/);
|
||||
|
||||
if (!match || !match[1]) {
|
||||
throw 'Please provide a valid emoji!';
|
||||
}
|
||||
|
||||
const emoji = bot.emojis.get(match[1]);
|
||||
|
||||
if (!emoji) {
|
||||
throw 'That emoji could not be identified.';
|
||||
}
|
||||
|
||||
msg.delete();
|
||||
(await msg.channel.send({
|
||||
embed: bot.utils.embed('', '', [
|
||||
{
|
||||
name: 'Name',
|
||||
value: emoji.name
|
||||
},
|
||||
{
|
||||
name: 'From Guild',
|
||||
value: emoji.guild.name
|
||||
},
|
||||
{
|
||||
name: 'ID',
|
||||
value: emoji.id
|
||||
},
|
||||
{
|
||||
name: 'Download URL',
|
||||
value: emoji.url
|
||||
}
|
||||
], { thumbnail: emoji.url })
|
||||
})).delete(15000);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'emoji',
|
||||
usage: 'emoji <emoji>',
|
||||
description: 'Shows information about an emoji'
|
||||
};
|
|
@ -1,26 +0,0 @@
|
|||
const oneLine = require('common-tags').oneLine;
|
||||
|
||||
exports.run = (bot, msg) => {
|
||||
|
||||
let servers = bot.guilds.array().sort((a, b) => b.memberCount - a.memberCount).map(guild => {
|
||||
return {
|
||||
name: guild.name,
|
||||
value: oneLine`
|
||||
${guild.memberCount} users,
|
||||
${guild.channels.size} channels
|
||||
`
|
||||
};
|
||||
});
|
||||
|
||||
for (let i = 0; i < servers.length / 20; i += 20) {
|
||||
msg.edit('', {
|
||||
embed: bot.utils.embed(`${bot.user.username}'s Servers`, '\u200b', servers.slice(i, i + 20), { inline: true })
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'guilds',
|
||||
usage: 'guilds',
|
||||
description: 'Lists all guilds that you\'re a member of'
|
||||
};
|
|
@ -1,112 +0,0 @@
|
|||
const stripIndents = require('common-tags').stripIndents;
|
||||
|
||||
exports.run = async (bot, msg, args) => {
|
||||
|
||||
let commands = [];
|
||||
let title = 'Categories';
|
||||
|
||||
if (args.length > 0) {
|
||||
if (/^category|type$/i.test(args[0])) {
|
||||
if (args.length < 2) {
|
||||
throw 'You must specify a category!';
|
||||
}
|
||||
|
||||
commands = bot.commands.all(args[1]);
|
||||
title = `${args[1]} Commands`;
|
||||
} else if (/^all|full|every$/i.test(args[0])) {
|
||||
commands = bot.commands.all();
|
||||
title = 'All Commands';
|
||||
} else {
|
||||
let command = bot.commands.get(args[0]);
|
||||
if (!command) {
|
||||
throw `The command '${args[0]}' does not exist!`;
|
||||
}
|
||||
|
||||
commands = [command];
|
||||
title = `Help for \`${command.info.name}\``;
|
||||
}
|
||||
}
|
||||
|
||||
if (commands.length > 0) {
|
||||
let fields = commands.filter(c => !c.info.hidden)
|
||||
.sort((a, b) => a.info.name.localeCompare(b.info.name))
|
||||
.map(c => getHelp(bot, c, commands.length === 1));
|
||||
|
||||
// Temporary workaround for the 2k char limit
|
||||
let maxLength = 1900;
|
||||
let messages = [];
|
||||
|
||||
while (fields.length > 0) {
|
||||
let len = 0;
|
||||
let i = 0;
|
||||
while (len < maxLength) {
|
||||
if (i >= fields.length) {
|
||||
break;
|
||||
}
|
||||
let field = fields[i];
|
||||
len += field.name.length + field.value.length;
|
||||
if (len >= maxLength) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
messages.push({ fields: fields.splice(0, i) });
|
||||
}
|
||||
|
||||
msg.delete().catch(() => { });
|
||||
messages.map(m => m.fields).forEach(async fields => {
|
||||
(await msg.channel.send({
|
||||
embed: bot.utils.embed(title, '_This message will self-destruct in 90 seconds._ :boom:', fields)
|
||||
})).delete(90000);
|
||||
});
|
||||
} else {
|
||||
let categories = bot.commands.categories().sort();
|
||||
(await msg.edit({
|
||||
embed: bot.utils.embed(title, stripIndents`
|
||||
**Available categories:**
|
||||
${categories.map(c => `- __${c}__`).join('\n')}
|
||||
|
||||
**Usage:**
|
||||
Do \`${bot.config.prefix}help category <name>\` for a list of commands in a specific category.
|
||||
Do \`${bot.config.prefix}help all\` for a list of every command available in this bot.
|
||||
Do \`${bot.config.prefix}help <command>\` for **extended** command help and command options.`)
|
||||
})).delete(15000);
|
||||
}
|
||||
};
|
||||
|
||||
const getHelp = (bot, command, single) => {
|
||||
|
||||
let description = stripIndents`
|
||||
**Usage:** \`${bot.config.prefix}${command.info.usage || command.info.name}\`
|
||||
**Description:** ${command.info.description || '<no description>'}
|
||||
**Category:** __${command.info.category}__`;
|
||||
|
||||
if (command.info.credits)
|
||||
description += `\n**Credits:** *${command.info.credits}*`;
|
||||
|
||||
if (single && command.info.examples)
|
||||
description += `\n**Examples:**\n${command.info.examples.map(example => `\`${bot.config.prefix}${example}\``).join('\n')}`;
|
||||
|
||||
if (single && command.info.options instanceof Array) {
|
||||
let options = command.info.options.map(option => {
|
||||
return stripIndents`
|
||||
**${option.name}**
|
||||
*Usage:* \`${option.usage || option.name}\`
|
||||
*Description:* ${option.description}
|
||||
`;
|
||||
});
|
||||
description += `\n**Options:**\n\n${options.join('\n\n')}`;
|
||||
}
|
||||
|
||||
return {
|
||||
name: single ? '\u200b' : command.info.name,
|
||||
value: description
|
||||
};
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'help',
|
||||
usage: 'help all|[command]|[category <name>]',
|
||||
description: 'Shows you help for all commands or just a single command'
|
||||
};
|
|
@ -1,39 +0,0 @@
|
|||
const limitTo = (array, max, joiner) => array.slice(0, max).join(joiner) + (array.length <= max ? '' : '...');
|
||||
|
||||
const inGuild = (guild, user) => !!guild.members.find('id', user.id);
|
||||
|
||||
exports.run = async (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'Please provide a name of a Discord server you are in.';
|
||||
}
|
||||
|
||||
const query = args.join(' ').toLowerCase();
|
||||
// Try to parse by Server Name fist or Server ID
|
||||
const guild = bot.guilds.find(guild => guild.name.toLowerCase() === query || guild.id === query);
|
||||
|
||||
if (!guild) {
|
||||
throw 'That guild could not be found!';
|
||||
}
|
||||
|
||||
const mutual = bot.users.filter(user => inGuild(msg.guild, user) && inGuild(guild, user));
|
||||
|
||||
await msg.edit(':arrows_counterclockwise: Searching...');
|
||||
|
||||
const { url } = await bot.utils.textUpload(mutual.map(user => `- ${user.tag}`).join('\n'));
|
||||
|
||||
msg.delete();
|
||||
(await msg.channel.send({
|
||||
embed: bot.utils.embed(`Mutual members of ${guild.name}`, limitTo(mutual.array().map(user => user.tag), 25, ', '), [
|
||||
{
|
||||
name: 'Full List',
|
||||
value: url
|
||||
}
|
||||
])
|
||||
})).delete(30000);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'mutual',
|
||||
usage: 'mutual <server>',
|
||||
description: 'Finds users who are in a given server that you are in'
|
||||
};
|
|
@ -1,51 +0,0 @@
|
|||
const got = require('got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
exports.run = async (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'Please provide the username of a player.';
|
||||
}
|
||||
|
||||
const username = args[0];
|
||||
|
||||
const uuid = await getUUID(username);
|
||||
if (!uuid) {
|
||||
throw 'That player could not be found.';
|
||||
}
|
||||
|
||||
msg.delete();
|
||||
return msg.channel.send({
|
||||
embed: bot.utils.embed('', '', [
|
||||
{
|
||||
name: 'Username',
|
||||
value: username
|
||||
},
|
||||
{
|
||||
name: 'UUID',
|
||||
value: `\`${uuid}\``
|
||||
},
|
||||
{
|
||||
name: 'Skin',
|
||||
value: `[Download](https://crafatar.com/skins/${uuid}.png)`
|
||||
}
|
||||
], { thumbnail: `https://crafatar.com/avatars/${uuid}.png?size=250&overlay=true` })
|
||||
});
|
||||
};
|
||||
|
||||
async function getUUID(username) {
|
||||
const res = await got(`https://mcuuid.net/?q=${username}`);
|
||||
const $ = cheerio.load(res.body);
|
||||
const input = $('input')[1];
|
||||
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
|
||||
return input.attribs['value'];
|
||||
}
|
||||
|
||||
exports.info = {
|
||||
name: 'playerinfo',
|
||||
usage: 'playerinfo <username>',
|
||||
description: 'Shows information about a Minecraft player'
|
||||
};
|
|
@ -1,80 +0,0 @@
|
|||
const dateFormat = require('dateformat');
|
||||
|
||||
const now = new Date();
|
||||
dateFormat(now, 'dddd, mmmm dS, yyyy, h:MM:ss TT');
|
||||
|
||||
exports.run = async (bot, msg) => {
|
||||
if (!msg.guild) {
|
||||
throw 'This can only be used in a guild!';
|
||||
}
|
||||
|
||||
const millis = new Date().getTime() - msg.guild.createdAt.getTime();
|
||||
const days = millis / 1000 / 60 / 60 / 24;
|
||||
|
||||
const owner = msg.guild.owner.user || {};
|
||||
|
||||
const verificationLevels = ['None', 'Low', 'Medium', 'Insane', 'Extreme'];
|
||||
|
||||
let embed = bot.utils.embed(
|
||||
`${msg.guild.name}`,
|
||||
'***This message will dissappear in 60 seconds.***',
|
||||
[
|
||||
{
|
||||
name: 'Created On',
|
||||
value: `${dateFormat(msg.guild.createdAt)}`,
|
||||
},
|
||||
{
|
||||
name: 'Days Since Creation',
|
||||
value: `${days.toFixed(0)}`,
|
||||
},
|
||||
{
|
||||
name: 'Default Channel',
|
||||
value: `${msg.guild.defaultChannel}`,
|
||||
},
|
||||
{
|
||||
name: 'Region',
|
||||
value: `${msg.guild.region}`,
|
||||
},
|
||||
{
|
||||
name: 'Member Count',
|
||||
value: `${msg.guild.members.filter(m => m.presence.status !== 'offline').size} / ${msg.guild.memberCount}`,
|
||||
},
|
||||
{
|
||||
name: 'Owner',
|
||||
value: `${owner.username || 'None'}`,
|
||||
},
|
||||
{
|
||||
name: 'Text Channels',
|
||||
value: `${msg.guild.channels.filter(m => m.type === 'text').size}`,
|
||||
},
|
||||
{
|
||||
name: 'Voice Channels',
|
||||
value: `${msg.guild.channels.filter(m => m.type === 'voice').size}`,
|
||||
},
|
||||
{
|
||||
name: 'Verification Level',
|
||||
value: `${verificationLevels[msg.guild.verificationLevel]}`,
|
||||
},
|
||||
{
|
||||
name: 'Roles',
|
||||
value: `${msg.guild.roles.size}`,
|
||||
},
|
||||
],
|
||||
{
|
||||
inline: true,
|
||||
footer: `Guild ID: ${msg.guild.id}`
|
||||
}
|
||||
);
|
||||
|
||||
if (msg.guild.iconURL != null) {
|
||||
embed.setThumbnail(`${msg.guild.iconURL}`);
|
||||
}
|
||||
|
||||
(await msg.edit({ embed })).delete(60000);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'serverinfo',
|
||||
usage: 'serverinfo',
|
||||
description: 'Shows info of the server you are in'
|
||||
};
|
|
@ -1,68 +0,0 @@
|
|||
const formatTime = (time) => {
|
||||
let seconds = time[0] + time[1] / 1e9;
|
||||
|
||||
let minutes = Math.floor(seconds / 60);
|
||||
seconds = seconds % 60;
|
||||
|
||||
let hours = Math.floor(minutes / 60);
|
||||
minutes = minutes % 60;
|
||||
return `${hours.toFixed(0)}h ${minutes.toFixed(0)}m ${seconds.toFixed(0)}s`;
|
||||
};
|
||||
|
||||
const activityTypes = [
|
||||
'playing',
|
||||
'streaming',
|
||||
'listening to',
|
||||
'watching',
|
||||
];
|
||||
|
||||
exports.run = async (bot, msg) => {
|
||||
const game = bot.user.presence.game || {};
|
||||
|
||||
(await msg.edit({
|
||||
embed: bot.utils.embed('SharpBot Stats', '***This message will dissappear in 30 seconds.***', [
|
||||
{
|
||||
name: ':outbox_tray: Messages sent',
|
||||
value: bot.managers.stats.get('messages-sent') || 0,
|
||||
},
|
||||
{
|
||||
name: ':inbox_tray: Messages received',
|
||||
value: bot.managers.stats.get('messages-received') || 0,
|
||||
},
|
||||
{
|
||||
name: ':mailbox: Mentions',
|
||||
value: bot.managers.stats.get('mentions') || 0
|
||||
},
|
||||
{
|
||||
name: ':baby: Users',
|
||||
value: `${bot.guilds.reduce((mem, g) => mem += g.memberCount, 0)}`,
|
||||
},
|
||||
{
|
||||
name: ':desktop: Servers',
|
||||
value: `${bot.guilds.size.toLocaleString()}`,
|
||||
},
|
||||
{
|
||||
name: ':keyboard: Channels',
|
||||
value: `${bot.channels.size.toLocaleString()}`,
|
||||
},
|
||||
{
|
||||
name: ':thinking: RAM usage',
|
||||
value: `${(process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2)} MB`,
|
||||
},
|
||||
{
|
||||
name: ':stopwatch: Uptime',
|
||||
value: formatTime(process.hrtime(bot.managers.stats.get('start-time')))
|
||||
},
|
||||
{
|
||||
name: ':video_game: Game',
|
||||
value: (game.name) ? `*${activityTypes[game.type]}* ${game.name} ${game.streaming ? `[(Streaming)](${game.url})` : ''}` : 'none'
|
||||
}
|
||||
], { inline: true })
|
||||
})).delete(30000);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'stats',
|
||||
usage: 'stats',
|
||||
description: 'Shows you stats about SharpBot'
|
||||
};
|
|
@ -1,21 +0,0 @@
|
|||
exports.run = function (bot, msg) {
|
||||
const user = msg.mentions.users.first();
|
||||
if (!user) {
|
||||
throw 'Please mention a user.';
|
||||
}
|
||||
|
||||
const delmsg = bot.deleted.get(user.id);
|
||||
if (!delmsg) {
|
||||
throw 'No recently deleted messages found';
|
||||
}
|
||||
|
||||
bot.deleted.delete(user.id);
|
||||
|
||||
msg.edit(`Undeleted message of ${user.username} in ${delmsg.guild.name} | ${delmsg.channel.name}\n\`\`\`${delmsg.content}\`\`\``);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'undelete',
|
||||
usage: 'undelete <mention of user>',
|
||||
description: 'Undeletes messages'
|
||||
};
|
|
@ -1,84 +0,0 @@
|
|||
const dateFormat = require('dateformat');
|
||||
|
||||
dateFormat('dddd, mmmm dS, yyyy, h:MM:ss TT');
|
||||
|
||||
exports.run = async (bot, msg) => {
|
||||
//Makes sure command is sent in a guild
|
||||
if (!msg.guild) {
|
||||
throw 'This can only be used in a guild!';
|
||||
}
|
||||
|
||||
//Makes sure user mentions a user to get info for
|
||||
if (msg.mentions.users.size < 1) {
|
||||
throw '@mention someone to find the info';
|
||||
}
|
||||
|
||||
let user = msg.mentions.users.first();
|
||||
let member = msg.guild.member(user);
|
||||
|
||||
if (!member) {
|
||||
throw 'That member could not be found!';
|
||||
}
|
||||
|
||||
//How long ago the account was created
|
||||
const millisCreated = new Date().getTime() - user.createdAt.getTime();
|
||||
const daysCreated = millisCreated / 1000 / 60 / 60 / 24;
|
||||
|
||||
//How long about the user joined the server
|
||||
const millisJoined = new Date().getTime() - member.joinedAt.getTime();
|
||||
const daysJoined = millisJoined / 1000 / 60 / 60 / 24;
|
||||
|
||||
// Slice off the first item (the @everyone)
|
||||
let roles = member.roles.array().slice(1).sort((a, b) => a.comparePositionTo(b)).reverse().map(role => role.name);
|
||||
if (roles.length < 1) roles = ['None'];
|
||||
|
||||
let embed = bot.utils.embed(
|
||||
`${user.username}#${msg.mentions.users.first().discriminator}`,
|
||||
'***This message will dissappear in 60 seconds.***',
|
||||
[
|
||||
{
|
||||
name: 'Status',
|
||||
value: `${user.presence.status[0].toUpperCase() + user.presence.status.slice(1)}`,
|
||||
},
|
||||
{
|
||||
name: 'Game',
|
||||
value: `${(user.presence.game && user.presence.game && user.presence.game.name) || 'Not playing a game.'}`,
|
||||
},
|
||||
{
|
||||
name: 'Created On',
|
||||
value: `${dateFormat(user.createdAt)}`,
|
||||
},
|
||||
{
|
||||
name: 'Days Since Creation',
|
||||
value: `${daysCreated.toFixed(0)}`,
|
||||
},
|
||||
{
|
||||
name: 'Joined On',
|
||||
value: `${dateFormat(member.joinedAt)}`,
|
||||
},
|
||||
{
|
||||
name: 'Days Since Joining',
|
||||
value: `${daysJoined.toFixed(0)}`,
|
||||
},
|
||||
{
|
||||
name: 'Roles',
|
||||
value: `${roles.join(', ')}`,
|
||||
inline: false,
|
||||
},
|
||||
],
|
||||
{
|
||||
inline: true,
|
||||
footer: `User ID: ${user.id}`,
|
||||
thumbnail: user.displayAvatarURL
|
||||
}
|
||||
);
|
||||
|
||||
(await msg.edit({ embed })).delete(60000);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'userinfo',
|
||||
usage: 'userinfo <user>',
|
||||
description: 'Shows info about a user'
|
||||
};
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
function hasRole(member, roleName) {
|
||||
return member.roles.map(role => role.name.toLowerCase()).indexOf(roleName.toLowerCase()) > -1;
|
||||
}
|
||||
|
||||
exports.run = async (bot, msg, args) => {
|
||||
if (!msg.guild || !msg.guild.members) {
|
||||
throw 'You must run this command from within a server.';
|
||||
}
|
||||
|
||||
let members = msg.guild.members.array().sort((a, b) => a.user.username.localeCompare(b.user.username));
|
||||
|
||||
if (args.length > 0) {
|
||||
members = members.filter(member => hasRole(member, args[0]));
|
||||
}
|
||||
|
||||
if (members.length < 1) {
|
||||
throw 'No members could be found.';
|
||||
}
|
||||
|
||||
msg.delete();
|
||||
|
||||
let users = members.map(m => `${m.user}${(m.user.bot ? ' [BOT]' : '')}`);
|
||||
const body = users.join('\n');
|
||||
|
||||
if (body.length < 2000) {
|
||||
(await msg.channel.send({
|
||||
embed: bot.utils.embed('', body)
|
||||
})).delete(60000);
|
||||
} else {
|
||||
let raw = members.map(m => `${m.user.username}${m.user.bot ? ' [BOT]' : ''}`).join('\n');
|
||||
|
||||
const { url } = await bot.utils.textUpload(raw);
|
||||
|
||||
let trimmed = body.substr(0, 1500);
|
||||
trimmed = trimmed.slice(0, trimmed.lastIndexOf('\n'));
|
||||
|
||||
msg.channel.send({
|
||||
embed: bot.utils.embed('', trimmed, [{ name: 'Full list', value: url }])
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'users',
|
||||
usage: 'users [role]',
|
||||
description: 'Lists all users on your current server'
|
||||
};
|
|
@ -1,31 +0,0 @@
|
|||
function makeCommand(name, viewName, description, filter) {
|
||||
return {
|
||||
run: async (bot, msg, args) => {
|
||||
let count = parseInt(args[0]) || 1;
|
||||
|
||||
msg.delete();
|
||||
|
||||
const messages = await msg.channel.fetchMessages({ limit: Math.min(count, 100), before: msg.id });
|
||||
const deletable = messages.filter(message => filter(message, bot));
|
||||
|
||||
await Promise.all(
|
||||
deletable.map(m => m.delete())
|
||||
);
|
||||
|
||||
const deleted = deletable.size;
|
||||
|
||||
(await msg.channel.send(`:white_check_mark: ${viewName} \`${deletable.size}\` message${deleted === 1 ? '' : 's'}.`)).delete(2000);
|
||||
},
|
||||
info: {
|
||||
name,
|
||||
usage: `${name} [amount]`,
|
||||
description
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = [
|
||||
makeCommand('purge', 'Purged', 'Deletes a certain number of messages', () => true),
|
||||
makeCommand('prune', 'Pruned', 'Deletes a certain number of messages sent by you', (msg, bot) => msg.author.id === bot.user.id),
|
||||
makeCommand('flush', 'Flushed', 'Deletes a certain number of messages sent by bots', msg => msg.author.bot)
|
||||
];
|
|
@ -1,58 +0,0 @@
|
|||
exports.run = async (bot, msg, args) => {
|
||||
let channel = msg.channel;
|
||||
|
||||
if (args.length < 1) {
|
||||
throw 'You must provide a message ID';
|
||||
}
|
||||
|
||||
if (!/^\d{18}$/.test(args[0])) {
|
||||
throw 'You must provide a valid message ID.';
|
||||
}
|
||||
|
||||
if (args[1] && /^<#\d{18}>$|^\d{18}$/.test(args[1])) {
|
||||
channel = bot.channels.get(args[1].replace(/[<#>]/g, ''));
|
||||
}
|
||||
|
||||
if (!channel) {
|
||||
throw 'That channel could not be found!';
|
||||
}
|
||||
|
||||
const messages = await channel.fetchMessages({ around: args[0], limit: 1 });
|
||||
|
||||
if (!messages || messages.size < 1) {
|
||||
throw 'That message could not be found!';
|
||||
}
|
||||
|
||||
let message = messages.first();
|
||||
|
||||
let options = {
|
||||
timestamp: message.editedTimestamp || message.createdTimestamp,
|
||||
footer: false
|
||||
};
|
||||
|
||||
let attachment = message.attachments.first();
|
||||
|
||||
if (attachment && (attachment.width || attachment.height)) {
|
||||
options.image = attachment.url;
|
||||
}
|
||||
|
||||
let field = '';
|
||||
|
||||
if ((msg.guild || {}).id !== (channel.guild || {}).id) {
|
||||
field = `**in ${(channel.guild || { name: 'DMs' }).name} <#${channel.id}>:**`;
|
||||
} else if (channel.id !== msg.channel.id) {
|
||||
field = `**in <#${channel.id}>:**`;
|
||||
}
|
||||
|
||||
msg.delete();
|
||||
msg.channel.send({
|
||||
embed: bot.utils.embed('', field + '\n\n' + message.toString(), [], options)
|
||||
.setAuthor(message.author.username, message.author.avatarURL)
|
||||
});
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'quote',
|
||||
usage: 'quote <id> [#channel | channel ID]',
|
||||
description: 'Quotes the message with the given ID and channel ID.'
|
||||
};
|
|
@ -1,48 +0,0 @@
|
|||
exports.run = async (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'You must specify what to search for!';
|
||||
}
|
||||
|
||||
let query = args.join(' ');
|
||||
|
||||
await msg.edit(`:arrows_counterclockwise: Searching the last \`100\` messages for \`${query}\``);
|
||||
|
||||
const messages = await msg.channel.fetchMessages({ limit: 100, before: msg.id });
|
||||
|
||||
const results = messages.filter(it => it.cleanContent.toLowerCase().indexOf(query.toLowerCase()) != -1)
|
||||
.sort((a, b) => (a.editedTimestamp || a.createdTimestamp) - (b.editedTimestamp || b.createdTimestamp));
|
||||
|
||||
if (results.length < 1) {
|
||||
throw 'No results found.';
|
||||
}
|
||||
|
||||
const output = results
|
||||
.map(message => `${formatDate(message.createdAt)} ${message.author.username}: ${message.content}`)
|
||||
.join('\n');
|
||||
|
||||
msg.delete();
|
||||
bot.utils.sendLarge(
|
||||
msg.channel,
|
||||
output.replace(/`/g, '\u200b`'),
|
||||
{
|
||||
prefix: '```log\n',
|
||||
suffix: '\n```',
|
||||
delay: 10,
|
||||
cutOn: '\n'
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
function formatDate(date) {
|
||||
return `[${_(date.getDay())}/${_(date.getMonth())}/${_(date.getYear() - 100)}] [${_(date.getHours())}:${_(date.getMinutes())}:${_(date.getSeconds())}]`;
|
||||
}
|
||||
|
||||
function _(number) {
|
||||
return number < 10 ? '0' + number : '' + number;
|
||||
}
|
||||
|
||||
exports.info = {
|
||||
name: 'search',
|
||||
usage: 'search <#> <text>',
|
||||
description: 'Searches a number of messages for some text'
|
||||
};
|
|
@ -1,17 +0,0 @@
|
|||
exports.run = (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'Please provide a prefix to set!';
|
||||
}
|
||||
|
||||
const prefix = args.join(' ');
|
||||
bot.managers.config.set('prefix', prefix);
|
||||
// No point trying to delete this message, the bot will be
|
||||
// rebooting before we have a chance to.
|
||||
msg.edit('Prefix set, rebooting! :ok_hand:');
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'prefix',
|
||||
usage: 'prefix <new prefix>',
|
||||
description: 'Sets the bot prefix'
|
||||
};
|
|
@ -1,68 +0,0 @@
|
|||
const normalizeUrl = require('normalize-url');
|
||||
|
||||
exports.run = async (bot, msg, args) => {
|
||||
let { leftover, options } = bot.utils.parseArgs(args, ['s:', 'w', 'l']);
|
||||
|
||||
if (leftover.length < 1) {
|
||||
if (options.s) {
|
||||
throw 'You must provide a game as well as a stream URL.';
|
||||
}
|
||||
|
||||
bot.user.setActivity(null, {});
|
||||
return msg.edit('Cleared your game! :ok_hand:').then(m => m.delete(3000));
|
||||
}
|
||||
|
||||
let game = leftover.join(' ');
|
||||
let stream = options.s;
|
||||
|
||||
let fields = [];
|
||||
|
||||
let activityOptions = { type: 'PLAYING' };
|
||||
let activityFieldTitle = ':video_game: Game';
|
||||
|
||||
if (stream) {
|
||||
stream = normalizeUrl(`twitch.tv/${stream}`);
|
||||
|
||||
activityOptions.url = stream;
|
||||
activityOptions.type = 'STREAMING';
|
||||
|
||||
fields.push({ name: ':headphones: Stream URL', value: stream });
|
||||
} else if (options.w) {
|
||||
activityOptions.type = 'WATCHING';
|
||||
activityFieldTitle = ':eyes: Watching';
|
||||
} else if (options.l) {
|
||||
activityOptions.type = 'LISTENING';
|
||||
activityFieldTitle = ':sound: Listening to';
|
||||
}
|
||||
|
||||
fields.unshift({ name: activityFieldTitle, value: game });
|
||||
|
||||
bot.user.setActivity(game, activityOptions);
|
||||
|
||||
msg.delete();
|
||||
|
||||
(await msg.channel.send({
|
||||
embed: bot.utils.embed(':ok_hand: Game changed!', '', fields)
|
||||
})).delete(5000);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'setgame',
|
||||
usage: 'setgame <game>',
|
||||
description: 'Sets your game (shows for other people)',
|
||||
options: [
|
||||
{
|
||||
name: '-s',
|
||||
usage: '-s <url>',
|
||||
description: 'Sets your streaming URL to http://twitch.tv/<url>'
|
||||
},
|
||||
{
|
||||
name: '-w',
|
||||
description: 'Sets your game prefix to **Watching**'
|
||||
},
|
||||
{
|
||||
name: '-l',
|
||||
description: 'Sets your game prefix to **Listening to**'
|
||||
}
|
||||
]
|
||||
};
|
|
@ -1,23 +0,0 @@
|
|||
// This command has already been created.
|
||||
|
||||
exports.run = async (bot, msg) => {
|
||||
const user = msg.mentions.users.first();
|
||||
if (!user) {
|
||||
throw 'Please mention the user who you want the avatar from.';
|
||||
}
|
||||
|
||||
if (!user.avatarURL) {
|
||||
throw 'That user does not have an avatar.';
|
||||
}
|
||||
|
||||
msg.delete();
|
||||
(await msg.channel.send({
|
||||
embed: bot.utils.embed(`${user.username}'s Avatar`, `[Download](${user.avatarURL})`, [], { image: user.avatarURL })
|
||||
})).delete(30000);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'avatar',
|
||||
usage: 'avatar <user>',
|
||||
description: 'Gives you the avatar of a user'
|
||||
};
|
|
@ -1,35 +0,0 @@
|
|||
// This command has already been created.
|
||||
|
||||
const math = require('math-expression-evaluator');
|
||||
const stripIndents = require('common-tags').stripIndents;
|
||||
|
||||
exports.run = (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'You must provide a equation to be solved on the calculator';
|
||||
}
|
||||
|
||||
const question = args.join(' ');
|
||||
|
||||
let answer;
|
||||
try {
|
||||
answer = math.eval(question);
|
||||
} catch (err) {
|
||||
throw `Invalid math equation: ${err}`;
|
||||
}
|
||||
|
||||
msg.delete();
|
||||
msg.channel.send({
|
||||
embed: bot.utils.embed('', stripIndents`
|
||||
**Equation:**\n\`\`\`\n${question}\n\`\`\`
|
||||
**Answer:**\n\`\`\`\n${answer}\n\`\`\`
|
||||
`)
|
||||
});
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'calculate',
|
||||
usage: 'calculate <equation>',
|
||||
aliases: ['calc', 'math'],
|
||||
description: 'Calculates any math equation',
|
||||
credits: 'Carbowix',
|
||||
};
|
|
@ -1,55 +0,0 @@
|
|||
// This command has already been created.
|
||||
|
||||
const webdict = require('webdict');
|
||||
|
||||
const makeCommand = method => {
|
||||
return (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'Please provide a word to search!';
|
||||
}
|
||||
|
||||
const parsed = bot.utils.parseArgs(args, ['e']);
|
||||
const word = parsed.leftover.join(' ');
|
||||
|
||||
webdict(method, word).then(res => {
|
||||
let result;
|
||||
if (!res || !res.definition || !res.definition[0]) {
|
||||
result = 'No results found.';
|
||||
} else {
|
||||
result = res.definition[0];
|
||||
}
|
||||
|
||||
if (parsed.options.e) {
|
||||
msg.edit(result);
|
||||
return;
|
||||
}
|
||||
|
||||
msg.delete();
|
||||
msg.channel.send({
|
||||
embed: bot.utils.embed(`:book: ${word}`, result)
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = [
|
||||
{
|
||||
run: makeCommand('dictionary'),
|
||||
info: {
|
||||
name: 'dictionary',
|
||||
aliases: ['dict'],
|
||||
usage: 'dictionary <word>',
|
||||
description: 'Looks a word up in the dictionary.',
|
||||
credits: 'NITEHAWK'
|
||||
}
|
||||
},
|
||||
{
|
||||
run: makeCommand('urbandictionary'),
|
||||
info: {
|
||||
name: 'urban',
|
||||
usage: 'urban <word>',
|
||||
description: 'Looks a word up in the urban dictionary.',
|
||||
credits: 'NITEHAWK'
|
||||
}
|
||||
}
|
||||
];
|
|
@ -1,95 +0,0 @@
|
|||
// This command has already been completed.
|
||||
|
||||
exports.run = (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'You must specify something to embed!';
|
||||
}
|
||||
|
||||
let parsed = bot.utils.parseArgs(args, ['f', 'ft:', 'd', 't:', 'c:', 'r', 'i:', 'a:', 'th:']);
|
||||
|
||||
let color = parsed.options.c;
|
||||
if (parsed.options.r && msg.guild && msg.guild.members) {
|
||||
let member = msg.guild.members.get(msg.author.id);
|
||||
if (member) {
|
||||
color = member.highestRole.hexColor;
|
||||
}
|
||||
}
|
||||
|
||||
if (color) {
|
||||
if (!color.startsWith('#')) {
|
||||
color = `#${color}`;
|
||||
}
|
||||
|
||||
if (!/^#[a-fA-F0-9]{6}$/.test(color)) {
|
||||
throw `Invalid color: \`${color}\`. Please use valid hex format (\`#RRGGBB\`)`;
|
||||
}
|
||||
}
|
||||
|
||||
msg.delete();
|
||||
msg.channel.send({
|
||||
embed: bot.utils.embed(parsed.options.t || '', parsed.leftover.join(' '), [], {
|
||||
footer: parsed.options.f || parsed.options.ft,
|
||||
timestamp: parsed.options.d,
|
||||
color,
|
||||
image: parsed.options.i,
|
||||
author: parsed.options.a,
|
||||
thumbnail: parsed.options.th
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'embed',
|
||||
usage: 'embed [text]',
|
||||
description: 'Sends a message via embeds',
|
||||
examples: [
|
||||
'embed Hello world!',
|
||||
'embed -c #ff0000 Red is my favorite color :heart:',
|
||||
'embed -r -t "Welcome to my server!" I hope you enjoy your time here.'
|
||||
],
|
||||
options: [
|
||||
{
|
||||
name: '-f',
|
||||
description: 'Shows the footer'
|
||||
},
|
||||
{
|
||||
name: '-ft',
|
||||
usage: '-ft <text>',
|
||||
description: 'Sets the footer text (use quotes for multiple words)'
|
||||
},
|
||||
{
|
||||
name: '-d',
|
||||
usage: '-d',
|
||||
description: 'Enables the timestamp (date) in the footer'
|
||||
},
|
||||
{
|
||||
name: '-t',
|
||||
usage: '-t <text>',
|
||||
description: 'Sets the embed title (use quotes for multiple words)'
|
||||
},
|
||||
{
|
||||
name: '-r',
|
||||
description: 'Uses your role color for the embed color'
|
||||
},
|
||||
{
|
||||
name: '-c',
|
||||
usage: '-c <color>',
|
||||
description: 'Sets a hex color for the embed in the format of `#RRGGBB`'
|
||||
},
|
||||
{
|
||||
name: '-i',
|
||||
usage: '-i <url>',
|
||||
description: 'Sets an image for the embed'
|
||||
},
|
||||
{
|
||||
name: '-a',
|
||||
usage: '-a <name>',
|
||||
description: 'Sets the author of the embed'
|
||||
},
|
||||
{
|
||||
name: '-th',
|
||||
usage: '-th <url>',
|
||||
description: 'Sets a thumbnail for the embed'
|
||||
}
|
||||
]
|
||||
};
|
|
@ -1,99 +0,0 @@
|
|||
const stripIndents = require('common-tags').stripIndents;
|
||||
|
||||
exports.run = async (bot, msg, args) => {
|
||||
let parsed = bot.utils.parseArgs(args, ['l:', 'i', 'q']);
|
||||
let lang = parsed.options.l || '';
|
||||
|
||||
let code = parsed.leftover.join(' ');
|
||||
let output;
|
||||
|
||||
try {
|
||||
output = await eval(code);
|
||||
} catch (err) {
|
||||
let message = err;
|
||||
if (err && err.response && err.response.body && err.response.body.message) {
|
||||
message = err.response.body.message;
|
||||
}
|
||||
|
||||
return errorHandler(msg, bot, code, `${message}`);
|
||||
}
|
||||
|
||||
msg.delete();
|
||||
|
||||
if (parsed.options.q) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof output !== 'string') {
|
||||
output = require('util').inspect(output);
|
||||
}
|
||||
|
||||
if (!lang) {
|
||||
lang = 'javascript';
|
||||
}
|
||||
|
||||
output = clean(output).replace(new RegExp(bot.utils.quoteRegex(bot.token), 'g'), 'BOT_TOKEN');
|
||||
|
||||
const displayedOutput = output.length < 1500
|
||||
? `\n\`\`\`${lang}\n${output}\n\`\`\``
|
||||
: `\n${await tryUpload(bot, output)}\n`;
|
||||
|
||||
msg.channel.send({
|
||||
embed: bot.utils.embed('', stripIndents`
|
||||
**Input:**\n\`\`\`js\n${code}\n\`\`\`
|
||||
**Output:**${displayedOutput}
|
||||
`)
|
||||
});
|
||||
|
||||
if (output.length > 1500 && parsed.options.i) {
|
||||
bot.utils.sendLarge(msg.channel, output, {
|
||||
prefix: '```' + lang + '\n',
|
||||
suffix: '```',
|
||||
cutOn: ',',
|
||||
cutAfter: true
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const tryUpload = async (bot, content) => {
|
||||
const { url } = await bot.utils.textUpload(content);
|
||||
if (!url) {
|
||||
throw 'Failed to upload!';
|
||||
}
|
||||
return url;
|
||||
};
|
||||
|
||||
const errorHandler = (msg, bot, code, err) => {
|
||||
msg.delete();
|
||||
msg.channel.send({
|
||||
embed: bot.utils.embed('', `**Input:**\n\`\`\`js\n${code}\n\`\`\`\n:x: **Error!**\n\`\`\`xl\n${clean(err)}\n\`\`\``, [], {
|
||||
color: '#ff0000'
|
||||
})
|
||||
}).then(m => m.delete(15000));
|
||||
};
|
||||
|
||||
// Prevent @mentions, #channels or code blocks inside code blocks.
|
||||
const clean = text => text.replace(/([`@#])/g, '$1\u200b');
|
||||
|
||||
exports.info = {
|
||||
name: 'eval',
|
||||
usage: 'eval <code>',
|
||||
description: 'Evaluates arbitrary JavaScript',
|
||||
options: [
|
||||
{
|
||||
name: '-l',
|
||||
usage: '-l <lang>',
|
||||
description: 'Sets the output code-block syntax language'
|
||||
},
|
||||
{
|
||||
name: '-i',
|
||||
usage: '-i',
|
||||
description: 'Inline extra-long output in addition to uploading to hastebin'
|
||||
},
|
||||
{
|
||||
name: '-q',
|
||||
usage: '-q',
|
||||
description: 'Does not print any output'
|
||||
}
|
||||
]
|
||||
};
|
|
@ -1,130 +0,0 @@
|
|||
const { exec } = require('child_process');
|
||||
const username = require('os').userInfo().username;
|
||||
|
||||
exports.run = async (bot, msg, args) => {
|
||||
let parsed = bot.utils.parseArgs(args, ['r', 'd', 's', 'f', 'w', 'fn:', 'l:']);
|
||||
|
||||
if (parsed.length < 1) {
|
||||
throw 'You must provide a command to run!';
|
||||
}
|
||||
|
||||
if (parsed.options.d) {
|
||||
msg.delete();
|
||||
}
|
||||
|
||||
let ps = exec(parsed.leftover.join(' '));
|
||||
if (!ps) {
|
||||
throw 'Failed to start process!';
|
||||
}
|
||||
|
||||
if (parsed.options.s) {
|
||||
return;
|
||||
}
|
||||
|
||||
let opts = {
|
||||
delay: 10,
|
||||
cutOn: '\n'
|
||||
};
|
||||
|
||||
if (!parsed.options.r) {
|
||||
opts.prefix = `\`\`\`${parsed.options.l || 'bash'}\n`;
|
||||
opts.suffix = '\n```';
|
||||
}
|
||||
|
||||
if (parsed.options.f) {
|
||||
let output = '';
|
||||
|
||||
ps.stdout.on('data', data => output += data.toString());
|
||||
await new Promise(resolve => {
|
||||
ps.once('exit', async () => {
|
||||
if (!output) {
|
||||
return resolve();
|
||||
}
|
||||
|
||||
try {
|
||||
await msg.channel.send({
|
||||
files: [
|
||||
{
|
||||
attachment: output.replace(/^file:\/\//, ''),
|
||||
name: parsed.options.fn
|
||||
}
|
||||
]
|
||||
});
|
||||
} catch (err) {
|
||||
msg.error('Invalid URL/path!');
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
if (parsed.options.w) {
|
||||
let output = '';
|
||||
let handler = data => output += data.toString();
|
||||
|
||||
[ps.stdout, ps.stderr].forEach(stream => stream.on('data', handler));
|
||||
|
||||
await new Promise(resolve => {
|
||||
ps.once('exit', async () => {
|
||||
if (!output) {
|
||||
return resolve();
|
||||
}
|
||||
|
||||
await bot.utils.sendLarge(msg.channel, clean(output), opts);
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
ps.stdout.on('data', data => bot.utils.sendLarge(msg.channel, clean(data), opts));
|
||||
ps.stderr.on('data', data => bot.utils.sendLarge(msg.channel, clean(data), opts));
|
||||
|
||||
await new Promise(resolve => ps.once('exit', resolve));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const clean = function (data) {
|
||||
return `${data}`
|
||||
.replace(/`/g, '\u200b$&')
|
||||
.replace(new RegExp(username, 'g'), '<Hidden>')
|
||||
.replace(/\[[0-9]*m/g, '');
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'exec',
|
||||
usage: 'exec <command>',
|
||||
description: 'Executes a command in the console',
|
||||
options: [
|
||||
{
|
||||
name: '-s',
|
||||
description: 'Runs in silent mode, not showing any console output'
|
||||
},
|
||||
{
|
||||
name: '-l',
|
||||
usage: '-l <lang>',
|
||||
description: 'Sets the language of the outputted code block'
|
||||
},
|
||||
{
|
||||
name: '-r',
|
||||
description: 'Sends the output raw, without any code blocks'
|
||||
},
|
||||
{
|
||||
name: '-d',
|
||||
description: 'Deletes the command message'
|
||||
},
|
||||
{
|
||||
name: '-f',
|
||||
description: 'Interperts the response as a file URL/path to send'
|
||||
},
|
||||
{
|
||||
name: '-fn',
|
||||
usage: '-fn <name>',
|
||||
description: 'Sets the name for the sent file'
|
||||
},
|
||||
{
|
||||
name: '-w',
|
||||
description: 'Wait for the program to finish before sending the output'
|
||||
}
|
||||
]
|
||||
};
|
|
@ -1,75 +0,0 @@
|
|||
const got = require('got');
|
||||
|
||||
exports.run = async (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'You must specify a repository or search term!';
|
||||
}
|
||||
|
||||
const input = args.join(' ');
|
||||
|
||||
if (input.indexOf('/') !== -1) {
|
||||
let repo = safeRepo(input);
|
||||
|
||||
msg.edit(`:arrows_counterclockwise: Loading info for '${repo}'...`);
|
||||
|
||||
const res = await got(`https://api.github.com/repos/${repo}`, { json: true });
|
||||
const json = res.body;
|
||||
if (json.message === 'Not Found') {
|
||||
msg.error('That repository could not be found!');
|
||||
}
|
||||
|
||||
msg.edit({
|
||||
embed: bot.utils.embed('', getInfo(json))
|
||||
});
|
||||
} else {
|
||||
msg.edit(`:arrows_counterclockwise: Searching for '${input}'...`);
|
||||
|
||||
const res = await got(`https://api.github.com/search/repositories?q=${args.join('+')}`, { json: true });
|
||||
const json = res.body;
|
||||
if (json.total_count < 1) {
|
||||
throw `No results found for '${args.join(' ')}'`;
|
||||
}
|
||||
|
||||
msg.delete();
|
||||
msg.channel.send(':white_check_mark: Top 3 results:');
|
||||
|
||||
json.items.slice(0, 3).forEach(item => {
|
||||
msg.channel.send({
|
||||
embed: bot.utils.embed('', getInfo(item))
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function safeRepo(input) {
|
||||
if (input.indexOf('/') === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
let user = input.substr(0, input.indexOf('/'));
|
||||
input = input.substr(input.indexOf('/') + 1);
|
||||
let repo = input.indexOf('/') === -1 ? input : input.substr(0, input.indexOf('/'));
|
||||
return `${user}/${repo}`;
|
||||
}
|
||||
|
||||
function getInfo(json) {
|
||||
return `**${json.full_name}**
|
||||
|
||||
\t**Description:** _${json.description || 'None provided'}_
|
||||
\t**Owner:** [${json.owner.login}](${json.owner.html_url})
|
||||
\t**Primary Language:** \`${json.language}\`
|
||||
|
||||
\t:house: [Home page](${json.html_url}) :small_red_triangle_down: [Downloads](${json.html_url}/releases) :exclamation: [Issues](${json.html_url}/issues)
|
||||
|
||||
\t:negative_squared_cross_mark: \`${json.open_issues_count}\` open issues :star: \`${json.stargazers_count}\` stargazers :eyes: \`${json.subscribers_count || json.watchers_count}\` watchers
|
||||
|
||||
|
||||
\tDo \`git clone ${json.clone_url}\` to clone this repository
|
||||
`;
|
||||
}
|
||||
|
||||
exports.info = {
|
||||
name: 'github',
|
||||
usage: 'github <user/repo>',
|
||||
description: 'Links to a GitHub repository'
|
||||
};
|
|
@ -1,207 +0,0 @@
|
|||
const cheerio = require('cheerio');
|
||||
const got = require('got');
|
||||
const { stringify } = require('querystring');
|
||||
const { RichEmbed } = require('discord.js');
|
||||
|
||||
exports.run = async (bot, msg, args) => {
|
||||
if(args.length < 1) throw 'I need to know what to search...';
|
||||
|
||||
await msg.edit(':arrows_counterclockwise: Googling....');
|
||||
|
||||
const params = {
|
||||
q: args.join(' '),
|
||||
safe: 'on',
|
||||
lr: 'lang_en',
|
||||
hl: 'en'
|
||||
};
|
||||
|
||||
let resp = await got('https://google.com/search?' + stringify(params), { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) Gecko/20100101 Firefox/53.0' }});
|
||||
|
||||
if(resp.statusCode !== 200) throw 'Google didn\'t want to respond somehow';
|
||||
|
||||
const $ = cheerio.load(resp.body);
|
||||
|
||||
const results = [];
|
||||
|
||||
let card = null;
|
||||
|
||||
const cardNode = $('div#rso > div._NId').find('div.vk_c, div.g.mnr-c.g-blk, div.kp-blk');
|
||||
|
||||
if(cardNode && cardNode.length !== 0) {
|
||||
card = this.parseCards($, cardNode);
|
||||
}
|
||||
|
||||
$('.rc > h3 > a').each((i, e) => {
|
||||
const link = $(e).attr('href');
|
||||
const text = $(e).text();
|
||||
if(link) {
|
||||
results.push({ text, link });
|
||||
}
|
||||
});
|
||||
|
||||
if(card) {
|
||||
const value = results.slice(0, 3).map(r => `[${r.text}](${r.link})`).join('\n');
|
||||
if(value) {
|
||||
card.addField(`This is what I also found for: "${params.q}" `, value)
|
||||
.setColor(bot.utils.randomColor())
|
||||
.setURL(`https://google.com/search?q=${encodeURIComponent(params.q)}`);
|
||||
}
|
||||
return await msg.edit({ embed: card });
|
||||
}
|
||||
|
||||
if(results.length === 0) {
|
||||
return await msg.channel.send('Sorry, we didn\'t found any results');
|
||||
}
|
||||
|
||||
const firstentry = `[${results[0].text}](${results[0].link})`;
|
||||
const nexttwo = results.slice(1, 3).map(r => `[${r.text}](${r.link})`).join('\n');
|
||||
|
||||
|
||||
const embed = bot.utils.embed(`Search results for ${args.join(' ')}`, firstentry, [
|
||||
{
|
||||
name: 'More links',
|
||||
value: nexttwo
|
||||
}
|
||||
], { url: `https://google.com/search?q=${encodeURIComponent(params.q)}`});
|
||||
await msg.edit('', {embed: embed});
|
||||
|
||||
};
|
||||
|
||||
exports.parseCards = ($, node) => {
|
||||
const e = new RichEmbed();
|
||||
|
||||
|
||||
//calculator card
|
||||
if(node.find('span.cwclet').first().length > 0) {
|
||||
e.setTitle(':nerd: Calculator');
|
||||
const calculation = node.find('span.cwclet').first().text();
|
||||
let result = node.find('.cwcot').first().text();
|
||||
if(result)
|
||||
result = `${calculation.trim()} ${result.trim()}`;
|
||||
else result = `${calculation} ...`;
|
||||
e.setDescription(result);
|
||||
return e;
|
||||
}
|
||||
|
||||
//unit conversion card
|
||||
if(node.find('input[class*=_eif]').length > 0 && node.find('input[class*=_eif]').first().attr('value').length > 0) {
|
||||
if(node.find('input[class*=_eif]').length === 2) {
|
||||
e.setTitle(':scales: Unit conversion');
|
||||
|
||||
try {
|
||||
const firstvalue = node.find('input[class*=_eif]').eq(0).attr('value');
|
||||
const firstunit = node.find('input[class*=_eif]').eq(0).parent().find('select :selected').text().toLowerCase();
|
||||
const secondvalue = node.find('input[class*=_eif]').eq(1).attr('value');
|
||||
const secondunit = node.find('input[class*=_eif]').eq(1).parent().find('select :selected').text().toLowerCase();
|
||||
e.setDescription(`${firstvalue} ${firstunit} = ${secondvalue} ${secondunit}`);
|
||||
} catch(e) {
|
||||
return;
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//currency converter card
|
||||
if(node.find('.ct-cs').first().length > 0) {
|
||||
e.setTitle(':moneybag: Currency converter');
|
||||
|
||||
try {
|
||||
let firsttext = node.find('.vk_sh.vk_gy.cursrc').text();
|
||||
let secondtext = node.find('.vk_ans.vk_bk.curtgt > span').first().text() + node.find('.vk_ans.vk_bk.curtgt > span').eq(1).text();
|
||||
|
||||
let result = `${firsttext} ${secondtext}`;
|
||||
e.setDescription(result);
|
||||
} catch(e) {
|
||||
return;
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
//generic info card
|
||||
if(node.find('._oDd > ._Tgc').first().length > 0) {
|
||||
e.setDescription(node.find('._oDd > ._Tgc').first().text());
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
//translation card
|
||||
if(node.find('div#tw-ob').first().length > 0) {
|
||||
const srctext = node.find('pre#tw-source-text > span').first().text();
|
||||
let srclang = node.find('select#tw-sl > option:selected').first().text();
|
||||
|
||||
const desttext = node.find('pre#tw-target-text > span').first().text();
|
||||
const destlang = node.find('select#tw-tl > option:selected').first().text();
|
||||
|
||||
if(srclang.includes('detected')) {
|
||||
srclang = srclang.replace(' - detected', '');
|
||||
}
|
||||
|
||||
e.setTitle(':man_with_turban: Translation card');
|
||||
try {
|
||||
e.addField(srclang, srctext, true);
|
||||
e.addField(destlang, desttext, true);
|
||||
} catch(e) {
|
||||
return;
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
//time in card
|
||||
if(node.find('div.vk_bk.vk_ans').first().length > 0) {
|
||||
let time = node.find('div.vk_bk.vk_ans').text();
|
||||
try {
|
||||
e.setTitle(`:alarm_clock: ${node.find('span').text()}`)
|
||||
.setDescription(`${time}`);
|
||||
} catch(e) {
|
||||
return;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
//defenition cards
|
||||
const words = node.find('span[data-dobid=hdw]');
|
||||
if(words.length > 0) {
|
||||
node.find('span[data-dobid=hdw]').each((i, word) => {
|
||||
const root = node.find('span[data-dobid=hdw]').parent().parent();
|
||||
|
||||
const pronunciation = $(root).find('span.lr_dct_ph > span');
|
||||
if(!pronunciation) return true;
|
||||
|
||||
const select = (selector) => $(selector).parent().parent().parent().find('ol.lr_dct_sf_sens')
|
||||
.find('div.lr_dct_sf_sen.vk_txt')
|
||||
.find('div._Jig > div[data-dobid=dfn] > span');
|
||||
|
||||
const lexicalCategory = $(root).find('div.lr_dct_sf_h > i > span');
|
||||
let defenitions = select(root);
|
||||
|
||||
$(lexicalCategory).each((i, category) => {
|
||||
defenitions = select(category);
|
||||
try {
|
||||
let descrip = [`${$(category).text()}`];
|
||||
$(defenitions).each((i, e) => {
|
||||
descrip.push(`${i + 1}. ${$(e).text()}`);
|
||||
});
|
||||
|
||||
if(i === 0) e.addField(`${$(word).text()} / ${$(pronunciation).text()}`, descrip.join('\n'));
|
||||
else e.addField(`${$(word).text()} / ${$(pronunciation).text()}`, descrip.join('\n'));
|
||||
} catch(e) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
exports.info = {
|
||||
name: 'google',
|
||||
usage: 'google <search>',
|
||||
description: 'Searches Google using magic'
|
||||
};
|
|
@ -1,34 +0,0 @@
|
|||
const IMAGE_NAME = /\.(jpe?g|png|gif|webp)$/i;
|
||||
|
||||
exports.run = async (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'Please provide an image URL to send.';
|
||||
}
|
||||
|
||||
msg.delete();
|
||||
|
||||
const url = args[0];
|
||||
let name;
|
||||
|
||||
if (!IMAGE_NAME.test(url)) {
|
||||
name = 'image.png';
|
||||
}
|
||||
|
||||
try {
|
||||
await msg.channel.send({
|
||||
file: {
|
||||
name,
|
||||
attachment: url
|
||||
}
|
||||
});
|
||||
} catch (ignore) {
|
||||
// Using throw inside of a catch doesn't work quite right
|
||||
return msg.error('Failed to send image.');
|
||||
}
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'image',
|
||||
usage: 'image <url>',
|
||||
description: 'Sends an image from a URL'
|
||||
};
|
|
@ -1,38 +0,0 @@
|
|||
const got = require('got');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
exports.run = (bot, msg, args) => {
|
||||
let count = parseInt(args[0]) || 100;
|
||||
let attachments = [];
|
||||
|
||||
msg.channel.fetchMessages({ limit: Math.min(count, 100), before: msg.id }).then(messages => {
|
||||
messages.map(m => {
|
||||
m.attachments.map(attachment => {
|
||||
if (attachment.height) {
|
||||
attachments.push(attachment.url);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
let dir = __dirname + '/../../../out';
|
||||
if (!fs.existsSync(dir)) fs.mkdirSync(dir);
|
||||
|
||||
for (let i = 0; i < attachments.length; i++) download(attachments[i]);
|
||||
|
||||
if (attachments.length === 0) throw 'Couldn\'t find any images.';
|
||||
msg.channel.send(`:white_check_mark: ${attachments.length} images scraped and saved to the "out" folder in the SharpBot folder.`).then(m => { m.delete(10000); });
|
||||
msg.delete();
|
||||
}).catch(msg.error);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'imagedumper',
|
||||
usage: 'imagedumper <amount>',
|
||||
description: 'Grabs all images from the specified amount of messages (max 100)',
|
||||
credits: '<@149916494183137280>' // Liam Bagge#0550
|
||||
};
|
||||
|
||||
function download(url) {
|
||||
let file = fs.createWriteStream(`${__dirname}/../../../out/attachment_${path.basename(url)}`);
|
||||
got.stream(url).pipe(file);
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
exports.run = (bot, msg, args) => {
|
||||
let parsed = bot.utils.parseArgs(args, ['i']);
|
||||
|
||||
if (parsed.leftover.length < 1) {
|
||||
throw 'You must provide something to search for!';
|
||||
}
|
||||
|
||||
const query = encodeURIComponent(parsed.leftover.join(' '));
|
||||
// Are there better ways to do this? Sure. But why not abuse
|
||||
// JavaScript's craziness, and use a truthy/falsy -> 1/0 converter?
|
||||
const internetExplainer = !!parsed.options.i / 1;
|
||||
|
||||
msg.edit(`**Wow!** :arrow_right: http://www.lmgtfy.com/?iie=${internetExplainer}&q=${query}`);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'lmgtfy',
|
||||
usage: 'lmgtfy [search text]',
|
||||
description: 'Links to LMGTFY with the given search text',
|
||||
options: [
|
||||
{
|
||||
name: '-i',
|
||||
description: 'Enables Internet Explainer'
|
||||
}
|
||||
]
|
||||
};
|
|
@ -1,35 +0,0 @@
|
|||
exports.run = async (bot, msg, args) => {
|
||||
let parsed = bot.utils.parseArgs(args, ['o']);
|
||||
|
||||
if (parsed.options.o) {
|
||||
return msg.edit(':stopwatch: Ping').then(m => {
|
||||
let time = msg.editedTimestamp - msg.createdTimestamp;
|
||||
bot.utils.playAnimation(m, 500, [
|
||||
':stopwatch: __P__ing',
|
||||
':stopwatch: __Pi__ng',
|
||||
':stopwatch: __Pin__g',
|
||||
':stopwatch: __Ping__',
|
||||
`:stopwatch: ***Pong!*** \`${time}ms\``
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
await msg.edit(':thinking: Ping');
|
||||
|
||||
const delay = msg.editedTimestamp - msg.createdTimestamp;
|
||||
|
||||
(await msg.edit(`:stopwatch: Pong! \`${delay}ms\``)).delete(5000);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'ping',
|
||||
usage: 'ping [-o]',
|
||||
description: 'Pings the bot',
|
||||
options: [
|
||||
{
|
||||
name: '-o',
|
||||
usage: '-o',
|
||||
description: 'Shows the old ping message (animated)'
|
||||
}
|
||||
]
|
||||
};
|
148
cmds_SharpBot/Utility/react.js
vendored
148
cmds_SharpBot/Utility/react.js
vendored
|
@ -1,148 +0,0 @@
|
|||
const discordEmoji = require('discord-emoji');
|
||||
const emoji = {};
|
||||
|
||||
Object.values(discordEmoji).forEach(value => {
|
||||
Object.keys(value).forEach(key => {
|
||||
emoji[key] = value[key];
|
||||
});
|
||||
});
|
||||
|
||||
const mappings = {
|
||||
'a': [':regional_indicator_a:', ':a:'],
|
||||
'b': [':regional_indicator_b:', ':b:'],
|
||||
'c': [':regional_indicator_c:'],
|
||||
'd': [':regional_indicator_d:'],
|
||||
'e': [':regional_indicator_e:'],
|
||||
'f': [':regional_indicator_f:'],
|
||||
'g': [':regional_indicator_g:', ':compression:'],
|
||||
'h': [':regional_indicator_h:'],
|
||||
'i': [':regional_indicator_i:', ':information_source:'],
|
||||
'j': [':regional_indicator_j:'],
|
||||
'k': [':regional_indicator_k:'],
|
||||
'l': [':regional_indicator_l:'],
|
||||
'm': [':regional_indicator_m:', ':m:'],
|
||||
'n': [':regional_indicator_n:'],
|
||||
'o': [':regional_indicator_o:', ':o2:', ':o:'],
|
||||
'p': [':regional_indicator_p:', ':parking:'],
|
||||
'q': [':regional_indicator_q:'],
|
||||
'r': [':regional_indicator_r:'],
|
||||
's': [':regional_indicator_s:'],
|
||||
't': [':regional_indicator_t:', ':cross:'],
|
||||
'u': [':regional_indicator_u:'],
|
||||
'v': [':regional_indicator_v:'],
|
||||
'w': [':regional_indicator_w:'],
|
||||
'x': [':regional_indicator_x:', ':heavy_multiplication_x:', ':x:', ':negative_squared_cross_mark:'],
|
||||
'y': [':regional_indicator_y:'],
|
||||
'z': [':regional_indicator_z:'],
|
||||
'0': [':zero:'],
|
||||
'1': [':one:'],
|
||||
'2': [':two:'],
|
||||
'3': [':three:'],
|
||||
'4': [':four:'],
|
||||
'5': [':five:'],
|
||||
'6': [':six:'],
|
||||
'7': [':seven:'],
|
||||
'8': [':eight:'],
|
||||
'9': [':nine:'],
|
||||
'!': [':exclamation:', ':grey_exclamation:'],
|
||||
'?': [':question:', ':grey_question:'],
|
||||
'*': [':asterisk:', ':eight_spoked_asterisk:'],
|
||||
'#': [':hash:'],
|
||||
'$': [':heavy_dollar_sign:']
|
||||
};
|
||||
|
||||
function clone(object) {
|
||||
const newObject = {};
|
||||
|
||||
Object.keys(object).forEach(key => {
|
||||
if (object[key] instanceof Array) {
|
||||
newObject[key] = new Array(...object[key]);
|
||||
} else {
|
||||
newObject[key] = object[key];
|
||||
}
|
||||
});
|
||||
|
||||
return newObject;
|
||||
}
|
||||
|
||||
function emojiToUnicode(input) {
|
||||
if (/^:regional_indicator_[a-z]:$/.test(input)) {
|
||||
return String.fromCharCode(55356) + String.fromCharCode(56806 + input.substr(20, 1).charCodeAt(0) - 97);
|
||||
}
|
||||
return emoji[input.slice(1, -1)];
|
||||
}
|
||||
|
||||
function react(message, remaining, allowedMappings) {
|
||||
if (remaining.length < 1) {
|
||||
// We're out of stuff
|
||||
return;
|
||||
}
|
||||
|
||||
const char = remaining.shift().toLowerCase();
|
||||
|
||||
if (!char) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!allowedMappings[char]) {
|
||||
// Not a usable char
|
||||
return;
|
||||
}
|
||||
|
||||
const next = allowedMappings[char].shift();
|
||||
if (!next) {
|
||||
// We have no more mappings available
|
||||
return;
|
||||
}
|
||||
|
||||
message.react(emojiToUnicode(next)).then(() => {
|
||||
react(message, remaining, allowedMappings);
|
||||
});
|
||||
}
|
||||
|
||||
exports.run = (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'You must provide some text to react with.';
|
||||
}
|
||||
|
||||
const fetchOptions = { limit: 1 };
|
||||
if (args[1]) {
|
||||
if (!/\d{18}/.test(args[1])) {
|
||||
throw `${args[1]} is not a valid message ID!`;
|
||||
}
|
||||
|
||||
fetchOptions.around = args[1];
|
||||
} else {
|
||||
fetchOptions.before = msg.id;
|
||||
}
|
||||
|
||||
msg.channel.fetchMessages(fetchOptions).then(messages => {
|
||||
if (messages.length < 1) {
|
||||
return msg.error('Failed to find the message.');
|
||||
}
|
||||
|
||||
const target = messages.first();
|
||||
const allowedMappings = clone(mappings);
|
||||
|
||||
// Remove current reactions from allowed emojis
|
||||
target.reactions.forEach(reaction => {
|
||||
const emoji = reaction.toString();
|
||||
for (const key in allowedMappings) {
|
||||
const index = allowedMappings[key].indexOf(emoji);
|
||||
if (index > -1) {
|
||||
allowedMappings[key].splice(index, 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
msg.delete();
|
||||
|
||||
react(target, args[0].split(''), allowedMappings);
|
||||
}).catch(msg.error);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'react',
|
||||
usage: 'react <text> [message ID]',
|
||||
description: 'Reacts to the last sent message (or another message) with a given text (cannot contain spaces)'
|
||||
};
|
|
@ -1,10 +0,0 @@
|
|||
exports.run = async (bot, msg) => {
|
||||
await msg.edit(':wave: Restarting. Bye!');
|
||||
bot.shutdown(true);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'restart',
|
||||
usage: 'restart',
|
||||
description: 'Restarts the bot'
|
||||
};
|
|
@ -1,37 +0,0 @@
|
|||
exports.run = (bot, msg, args) => {
|
||||
const parsed = bot.utils.parseArgs(args, ['c:']);
|
||||
|
||||
if (parsed.leftover.length < 1) {
|
||||
throw 'You must put something to say!';
|
||||
}
|
||||
|
||||
let channel = msg.channel;
|
||||
if (parsed.options.c) {
|
||||
const id = parsed.options.c.match(/\d{18}/)[0];
|
||||
|
||||
if (!id) {
|
||||
throw 'Invalid channel!';
|
||||
}
|
||||
|
||||
channel = bot.channels.get(id);
|
||||
if (!channel) {
|
||||
throw 'That channel could not be found!';
|
||||
}
|
||||
}
|
||||
|
||||
msg.delete();
|
||||
channel.send(parsed.leftover.join(' '));
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'say',
|
||||
usage: 'say <message>',
|
||||
description: 'Says the message you put. Useful for shortcuts.',
|
||||
options: [
|
||||
{
|
||||
name: '-c',
|
||||
usage: '-c <channel|channel ID>',
|
||||
description: 'Specifies a specific channel to send the message in'
|
||||
}
|
||||
]
|
||||
};
|
|
@ -1,94 +0,0 @@
|
|||
exports.init = bot => {
|
||||
this.storage = bot.storage('shortcuts');
|
||||
};
|
||||
|
||||
const ADD = /^a(dd)?|c(reate)?$/i;
|
||||
const EDIT = /^e(dit)?$/i;
|
||||
const DELETE = /^d(el(ete)?)?|r(em(ove)?)?$/i;
|
||||
const INFO = /^i(nfo)?$/i;
|
||||
|
||||
exports.run = (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
const shortcuts = this.storage.values;
|
||||
|
||||
if (shortcuts.length < 1) {
|
||||
throw 'You have no shortcuts!';
|
||||
}
|
||||
|
||||
const list = shortcuts.map(shortcut => `- \`${shortcut.name}\``).join('\n');
|
||||
|
||||
msg.delete();
|
||||
return bot.utils.sendLarge(msg.channel, `**Shortcuts:**\n${list}`, { cutOn: '\n' });
|
||||
}
|
||||
|
||||
if (ADD.test(args[0]) || EDIT.test(args[0])) {
|
||||
if (args.length < 3) {
|
||||
throw `Usage: \`${bot.config.prefix}shortcut add|edit <id> <command>\``;
|
||||
}
|
||||
|
||||
let id = args[1].toLowerCase();
|
||||
let command = args.slice(2).join(' ');
|
||||
|
||||
// People keep accidentally putting their command prefix in
|
||||
if (command.startsWith(bot.config.prefix)) {
|
||||
command = command.substr(bot.config.prefix.length);
|
||||
}
|
||||
|
||||
const shortcut = this.storage.get(id);
|
||||
if (shortcut && !EDIT.test(args[0])) {
|
||||
throw `The shortcut \`${id}\` already exists!`;
|
||||
}
|
||||
|
||||
this.storage.set(id, { name: id, command });
|
||||
this.storage.save();
|
||||
|
||||
msg.edit(`:white_check_mark: Created shortcut \`${id}\`.`)
|
||||
.then(m => m.delete(5000));
|
||||
} else if (DELETE.test(args[0])) {
|
||||
if (args.length < 2) {
|
||||
throw `Usage: \`${bot.config.prefix}shortcut delete <id>\``;
|
||||
}
|
||||
|
||||
let id = args[1];
|
||||
|
||||
const shortcut = this.storage.get(id);
|
||||
if (!shortcut) {
|
||||
throw `The shortcut \`${id}\` doesn't exist!`;
|
||||
}
|
||||
|
||||
this.storage.set(id);
|
||||
this.storage.save();
|
||||
|
||||
msg.edit(`:white_check_mark: Removed the shortcut \`${id}\`.`)
|
||||
.then(m => m.delete(5000));
|
||||
} else if (INFO.test(args[0])) {
|
||||
if (args.length < 2) {
|
||||
throw `Usage: \`${bot.config.prefix}shortcut info <name>\``;
|
||||
}
|
||||
|
||||
const id = args[1];
|
||||
const shortcut = this.storage.get(id);
|
||||
|
||||
if (!shortcut) {
|
||||
throw `The shortcut \`${id}\` doesn't exist!`;
|
||||
}
|
||||
|
||||
msg.edit(`**Name:** \`${shortcut.name}\`\n\`\`\`xl\n${shortcut.command}\n\`\`\``)
|
||||
.then(m => m.delete(30000));
|
||||
} else {
|
||||
bot.commands.get('help').run(bot, msg, ['shortcuts']);
|
||||
}
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'shortcuts',
|
||||
usage: 'shortcuts [add <name> <command>|edit <name> <command>|delete <name>|info <name>]',
|
||||
description: 'Controls or lists your shortcuts',
|
||||
examples: [
|
||||
'shortcuts add love embed -c #ff0000 <3',
|
||||
'shortcuts edit drpg say #!mine;; say #!forage;; say #!chop;; say #!fish',
|
||||
'shortcuts delete invite',
|
||||
'shortcuts info love',
|
||||
'shortcuts'
|
||||
]
|
||||
};
|
|
@ -1,34 +0,0 @@
|
|||
const got = require('got');
|
||||
|
||||
exports.run = async (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'Please provide a url to shorten!';
|
||||
}
|
||||
|
||||
const url = args.join(' ');
|
||||
|
||||
msg.delete();
|
||||
|
||||
const res = await got(`http://tinyurl.com/api-create.php?url=${encodeURIComponent(url)}`);
|
||||
msg.channel.send({
|
||||
embed: bot.utils.embed('', '', [
|
||||
{
|
||||
name: 'Link',
|
||||
value: url
|
||||
},
|
||||
{
|
||||
name: 'Short URL',
|
||||
value: res.body
|
||||
}
|
||||
])
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'shorturl',
|
||||
aliases: ['short'],
|
||||
usage: 'shorturl <url>',
|
||||
description: 'Shortens a URL',
|
||||
credits: 'xd <@335490180028956673>'
|
||||
};
|
|
@ -1,10 +0,0 @@
|
|||
exports.run = async (bot, msg) => {
|
||||
await msg.edit(':wave: Shutting down. Bye!');
|
||||
bot.shutdown(false);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'shutdown',
|
||||
usage: 'shutdown',
|
||||
description: 'Fully shuts the bot down'
|
||||
};
|
|
@ -1,135 +0,0 @@
|
|||
const RichEmbed = require('discord.js').RichEmbed;
|
||||
const SpotifyWebApi = require('spotify-web-api-node');
|
||||
const SpotifyUriParser = require('spotify-uri');
|
||||
const got = require('got');
|
||||
const spotifyApi = new SpotifyWebApi();
|
||||
|
||||
exports.run = async (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'You must specify a Spotify URI at least!';
|
||||
}
|
||||
|
||||
const response = await got('https://spotify-auth.doxylamin.pw/', { json: true });
|
||||
|
||||
if (response.body.success == true) {
|
||||
spotifyApi.setAccessToken(response.body.access_token);
|
||||
}
|
||||
|
||||
const parsed = bot.utils.parseArgs(args, ['preview']);
|
||||
const spotifyUri = SpotifyUriParser.parse(parsed.leftover.join(' '));
|
||||
|
||||
switch (spotifyUri.type) {
|
||||
case 'track':
|
||||
getTrackEmbed(msg, spotifyUri.id, parsed.options.preview);
|
||||
break;
|
||||
case 'artist':
|
||||
getArtistEmbed(msg, spotifyUri.id, parsed.options.preview);
|
||||
break;
|
||||
case 'playlist':
|
||||
getPlaylistEmbed(msg, spotifyUri.user, spotifyUri.id, parsed.options.preview);
|
||||
break;
|
||||
default:
|
||||
throw 'Sorry, I can\'t parse that type of URI yet.';
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
function getPlaylistEmbed(msg, user, spotifyId, withPreview) {
|
||||
spotifyApi.getPlaylist(user, spotifyId)
|
||||
.then(data => {
|
||||
const apiResponse = data.body;
|
||||
|
||||
const embed = new RichEmbed()
|
||||
.setColor([30, 215, 96])
|
||||
.setThumbnail(apiResponse.images[0].url)
|
||||
.setAuthor('Click to listen on Spotify', 'https://image.flaticon.com/icons/png/512/174/174872.png', apiResponse.external_urls.spotify)
|
||||
.addField('Playlist Name', apiResponse.name, true)
|
||||
.addField('Created by', apiResponse.owner.display_name, true)
|
||||
.addField('Description', apiResponse.description, true)
|
||||
.addField('Public Playlist', ((apiResponse.public) ? 'Yes' : 'No'), true)
|
||||
.addField('Collaborative', ((apiResponse.collaborative) ? 'Yes' : 'No'), true)
|
||||
.addField('Followers', apiResponse.followers.total, true)
|
||||
.addField('Track Count', apiResponse.tracks.total, true);
|
||||
|
||||
msg.edit({ embed });
|
||||
|
||||
if (withPreview) msg.channel.send(`Got spotify? Click below to play! ${apiResponse.external_urls.spotify}`);
|
||||
|
||||
}).catch(err => {
|
||||
throw `Something went wrong! ${err}`;
|
||||
});
|
||||
}
|
||||
|
||||
function getArtistEmbed(msg, spotifyId, withPreview) {
|
||||
spotifyApi.getArtist(spotifyId)
|
||||
.then(data => {
|
||||
const apiResponse = data.body;
|
||||
|
||||
const embed = new RichEmbed()
|
||||
.setColor([30, 215, 96])
|
||||
.setThumbnail(apiResponse.images[0].url)
|
||||
.setAuthor('Click to listen on Spotify', 'https://image.flaticon.com/icons/png/512/174/174872.png', apiResponse.external_urls.spotify)
|
||||
.addField('Artist Name', apiResponse.name, true)
|
||||
.addField('Followers', apiResponse.followers.total.toLocaleString(), true)
|
||||
.addField('Popularity', apiResponse.popularity + '%', true)
|
||||
.addField('Genres', ((apiResponse.genres.length > 0) ? apiResponse.genres.join(', ') : 'unknown'), true);
|
||||
|
||||
msg.edit({ embed });
|
||||
|
||||
if (withPreview) msg.channel.send(`Got spotify? Click below to play! ${apiResponse.external_urls.spotify}`);
|
||||
|
||||
}).catch(err => {
|
||||
throw `Something went wrong! ${err}`;
|
||||
});
|
||||
}
|
||||
|
||||
function getTrackEmbed(msg, spotifyId, withPreview) {
|
||||
spotifyApi.getTrack(spotifyId)
|
||||
.then(data => {
|
||||
const apiResponse = data.body;
|
||||
let artists = apiResponse.artists.map(artist => artist.name);
|
||||
|
||||
const embed = new RichEmbed()
|
||||
.setColor([30, 215, 96])
|
||||
.setThumbnail(apiResponse.album.images[0].url)
|
||||
.setAuthor('Click to listen on Spotify', 'https://image.flaticon.com/icons/png/512/174/174872.png', apiResponse.external_urls.spotify)
|
||||
.addField('Artist', artists.join(', '), true)
|
||||
.addField('Title', apiResponse.name, true)
|
||||
.addField('Length', calculateDuration(apiResponse.duration_ms), true)
|
||||
.addField('Album', apiResponse.album.name, true)
|
||||
.addField('Parental Advisory', ((apiResponse.explicit) ? 'contains explicit lyrics' : 'none applicable'), true)
|
||||
.addField('Availability', `Available in ${apiResponse.available_markets.length} countrys`, true)
|
||||
.addField('Popularity', `${apiResponse.popularity}%`, true);
|
||||
|
||||
msg.edit({ embed });
|
||||
|
||||
if (withPreview) msg.channel.send(`Got spotify? Click below to play! ${apiResponse.external_urls.spotify}`);
|
||||
|
||||
}).catch(err => {
|
||||
throw `Something went wrong! ${err}`;
|
||||
});
|
||||
}
|
||||
|
||||
function calculateDuration(ms) {
|
||||
const minutes = Math.floor(ms / 60000);
|
||||
const seconds = ((ms % 60000) / 1000).toFixed(0);
|
||||
return (seconds == 60 ? (minutes + 1) + ':00' : minutes + ':' + (seconds < 10 ? '0' : '') + seconds);
|
||||
}
|
||||
|
||||
exports.info = {
|
||||
name: 'spotify',
|
||||
usage: 'spotify <url>',
|
||||
description: 'Parses a spotify-uri and outputs its information.',
|
||||
examples: [
|
||||
'spotify spotify:track:5DkCAVqn09WAPOPiphKOUD',
|
||||
'spotify -preview spotify:track:5DkCAVqn09WAPOPiphKOUD',
|
||||
'spotify https://open.spotify.com/track/5DkCAVqn09WAPOPiphKOUD'
|
||||
],
|
||||
options: [
|
||||
{
|
||||
name: '-preview',
|
||||
description: 'Sends another message where discord places it\'s own embedded player'
|
||||
}
|
||||
],
|
||||
credits: '<@140541588915879936>' // Doxylamin#3377
|
||||
};
|
|
@ -1,43 +0,0 @@
|
|||
const validStatuses = [
|
||||
{
|
||||
internal: 'online',
|
||||
display: 'online',
|
||||
emoji: ':zap:'
|
||||
},
|
||||
{
|
||||
internal: 'idle',
|
||||
display: 'idle',
|
||||
emoji: ':beach_umbrella:'
|
||||
},
|
||||
{
|
||||
internal: 'dnd',
|
||||
display: 'do-not-disturb',
|
||||
emoji: ':mute:'
|
||||
},
|
||||
{
|
||||
internal: 'invisible',
|
||||
display: 'invisible',
|
||||
emoji: ':ghost:'
|
||||
}
|
||||
];
|
||||
|
||||
const validStatusRegex = new RegExp(`^(${validStatuses.map(status => status.internal).join('|')})$`);
|
||||
const validStatusString = validStatuses.map(status => `\`${status.internal}\``).join(', ');
|
||||
|
||||
exports.run = async (bot, msg, args) => {
|
||||
if (args.length < 1 || !validStatusRegex.test(args[0])) {
|
||||
throw `Please provide a status to set: ${validStatusString}`;
|
||||
}
|
||||
|
||||
const status = validStatuses.find(status => status.internal === args[0].toLowerCase());
|
||||
|
||||
bot.user.setStatus(status.internal);
|
||||
|
||||
(await msg.edit(`${status.emoji} Set status to ${status.display}.`)).delete(5000);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'status',
|
||||
usage: `status <${validStatuses.map(status => status.internal).join('|')}>`,
|
||||
description: 'Sets your status'
|
||||
};
|
|
@ -1,70 +0,0 @@
|
|||
exports.init = bot => {
|
||||
this.storage = bot.storage('tags');
|
||||
};
|
||||
|
||||
exports.run = async (bot, message, args) => {
|
||||
if (args.length < 1) {
|
||||
throw `Do \`${bot.config.prefix}help tag\` for info on how to use this command.`;
|
||||
}
|
||||
|
||||
const sub = args[0].toLowerCase();
|
||||
args = args.slice(1);
|
||||
|
||||
if (sub === 'list') {
|
||||
const tags = this.storage.values
|
||||
.sort((a, b) => b.used - a.used);
|
||||
|
||||
message.edit(`${tags.map(tag => `**${tag.name}** (${tag.used})`).join('\n')}`, { split: true });
|
||||
} else if (sub === 'add') {
|
||||
if (args.length < 2) {
|
||||
throw 'You must provide a tag name and the tag contents!';
|
||||
}
|
||||
|
||||
let name = args[0];
|
||||
let contents = args.slice(1).join(' ');
|
||||
|
||||
const tag = this.storage.get(name);
|
||||
if (tag) {
|
||||
throw 'That tag already exists!';
|
||||
}
|
||||
|
||||
this.storage.set(name, { name, contents, used: 0 });
|
||||
this.storage.save();
|
||||
|
||||
(await message.edit(`:white_check_mark: The tag \`${name}\` was added.`)).delete(5000);
|
||||
} else if (sub === 'delete') {
|
||||
if (args.length < 1) {
|
||||
throw 'You must provide a tag name to delete!';
|
||||
}
|
||||
|
||||
const name = args[0];
|
||||
|
||||
if (!this.storage.get(name)) {
|
||||
throw 'That tag does not exist!';
|
||||
}
|
||||
|
||||
this.storage.set(name);
|
||||
this.storage.save();
|
||||
|
||||
(await message.edit(`:white_check_mark: The tag \`${name}\` was deleted.`)).delete(5000);
|
||||
} else {
|
||||
const tag = this.storage.get(sub);
|
||||
|
||||
if (!tag) {
|
||||
throw 'That tag does not exist!';
|
||||
}
|
||||
|
||||
message.edit(args.join(' ') + tag.contents);
|
||||
|
||||
tag.used++;
|
||||
|
||||
this.storage.set(sub, tag);
|
||||
this.storage.save();
|
||||
}
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'tag',
|
||||
usage: 'tag <name>|list|add <name> <content>|delete <name>',
|
||||
description: 'Manages your tags'
|
||||
};
|
|
@ -1,40 +0,0 @@
|
|||
function makeCommand(name, displayName, methodName) {
|
||||
return {
|
||||
run: async (bot, msg, args) => {
|
||||
const parsed = bot.utils.parseArgs(args, 'r');
|
||||
|
||||
if (parsed.leftover.length < 1) {
|
||||
throw 'You must have something to upload!';
|
||||
}
|
||||
|
||||
await msg.edit(':arrows_counterclockwise: Uploading...');
|
||||
const { url, rawUrl } = await bot.utils[methodName](parsed.leftover.join(' '));
|
||||
|
||||
if (!url) {
|
||||
throw 'Failed to upload, no key was returned!';
|
||||
}
|
||||
|
||||
if (parsed.options.r) {
|
||||
msg.edit(`:white_check_mark: ${rawUrl}`);
|
||||
} else {
|
||||
msg.edit(`:white_check_mark: ${url}`);
|
||||
}
|
||||
},
|
||||
info: {
|
||||
name,
|
||||
usage: `${name} <text>`,
|
||||
description: `Uploads some text to ${displayName}`,
|
||||
options: [
|
||||
{
|
||||
name: '-r',
|
||||
description: 'Returns the URL for a raw version of your upload'
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = [
|
||||
makeCommand('haste', 'Hastebin', 'hastebinUpload'),
|
||||
makeCommand('ix', 'ix.io', 'ixUpload')
|
||||
];
|
|
@ -1,54 +0,0 @@
|
|||
const got = require('got');
|
||||
|
||||
exports.run = async (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'You must specify a time to convert';
|
||||
}
|
||||
|
||||
let input = args.join(' ');
|
||||
let url = `https://api.duckduckgo.com/?q=${encodeURIComponent(input)}&format=json`;
|
||||
|
||||
await msg.edit(':arrows_counterclockwise: Loading conversion...');
|
||||
|
||||
const res = await got(url, { json: true });
|
||||
|
||||
if (!res || !res.body) {
|
||||
throw 'Could not load data from DDG.';
|
||||
}
|
||||
|
||||
let data = res.body;
|
||||
|
||||
let answer = data['Answer'];
|
||||
let message;
|
||||
|
||||
if (data['AnswerType'] === 'timezone_converter') {
|
||||
msg.delete();
|
||||
|
||||
let matches = input.match(/(.*?)\s*(to|in)\s*(.*)/);
|
||||
let prefix;
|
||||
|
||||
if (matches) {
|
||||
prefix = matches[1];
|
||||
} else {
|
||||
prefix = input;
|
||||
}
|
||||
|
||||
message = bot.utils.embed('', '', [
|
||||
{
|
||||
name: 'Timezone:',
|
||||
value: `${prefix} \u2794 ${answer}`
|
||||
}
|
||||
]);
|
||||
|
||||
msg.channel.send({ embed: message });
|
||||
} else {
|
||||
throw `No conversion found for ${input}`;
|
||||
}
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'timezone',
|
||||
usage: 'timezone <time> to <time>',
|
||||
description: 'converts between timezones, using DuckDuckGo searches',
|
||||
credits: '<@136641861073764352>' // Abyss#0473
|
||||
};
|
|
@ -1,254 +0,0 @@
|
|||
const {stripIndents} = require('common-tags');
|
||||
|
||||
class TodoItem {
|
||||
constructor(description, completed = false) {
|
||||
this.description = description;
|
||||
this.completed = completed;
|
||||
}
|
||||
|
||||
complete(completed = true) {
|
||||
this.completed = completed;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `${this.completed ? ':ballot_box_with_check:' : ':black_square_button: '} ${this.description}`;
|
||||
}
|
||||
|
||||
static fromJSON({description, completed}) {
|
||||
return new TodoItem(description, completed);
|
||||
}
|
||||
}
|
||||
|
||||
class TodoList {
|
||||
constructor(name) {
|
||||
this.name = name;
|
||||
this.items = [];
|
||||
}
|
||||
|
||||
_validateIndex(index) {
|
||||
if (Number.isNaN(index)) {
|
||||
// This will throw the error below
|
||||
index = 0;
|
||||
}
|
||||
index -= 1;
|
||||
if (index < 0 || index > this.items.length) {
|
||||
throw 'Please specify a valid number!';
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
add(description, completed = false) {
|
||||
this.items.push(new TodoItem(description, completed));
|
||||
}
|
||||
|
||||
remove(index) {
|
||||
index = this._validateIndex(index);
|
||||
this.items.splice(index, 1);
|
||||
}
|
||||
|
||||
markComplete(index, completed = true) {
|
||||
index = this._validateIndex(index);
|
||||
this.items[index].complete(completed);
|
||||
}
|
||||
|
||||
toString() {
|
||||
return stripIndents`
|
||||
**List: ${this.name}**
|
||||
**Items:** ${this.items.length === 0 ? 'None' : ''}
|
||||
${this.items.map((item, i) => `${i + 1}. ${item.toString()}`).join('\n')}
|
||||
`;
|
||||
}
|
||||
|
||||
static fromJSON({name, items}) {
|
||||
const todoList = new TodoList(name);
|
||||
todoList.items = items.map(item => TodoItem.fromJSON(item));
|
||||
return todoList;
|
||||
}
|
||||
}
|
||||
|
||||
class TodoLists {
|
||||
constructor(bot) {
|
||||
this._bot = bot;
|
||||
this.storage = bot.storage('todos');
|
||||
this.lists = {};
|
||||
|
||||
const lists = this.storage.get(TodoLists.listsStorageKey);
|
||||
if (!lists) {
|
||||
this.lists = {
|
||||
[TodoLists.mainListName]: new TodoList(TodoLists.mainListName)
|
||||
};
|
||||
} else {
|
||||
Object.keys(lists)
|
||||
.forEach(listName => {
|
||||
this.lists[listName] = TodoList.fromJSON(lists[listName]);
|
||||
});
|
||||
}
|
||||
|
||||
let currentList = this.storage.get(TodoLists.currentListStorageKey);
|
||||
if (!this.getList(currentList)) {
|
||||
currentList = TodoLists.mainListName;
|
||||
}
|
||||
this.currentListName = currentList;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {TodoList}
|
||||
*/
|
||||
getCurrentList() {
|
||||
return this.getList(this.currentListName);
|
||||
}
|
||||
|
||||
save() {
|
||||
this.storage.set(TodoLists.currentListStorageKey, this.currentListName);
|
||||
this.storage.set(TodoLists.listsStorageKey, this.lists);
|
||||
this.storage.save();
|
||||
}
|
||||
|
||||
getList(name) {
|
||||
return this.lists[name];
|
||||
}
|
||||
|
||||
getListNames() {
|
||||
return Object.keys(this.lists);
|
||||
}
|
||||
|
||||
deleteList(name) {
|
||||
if (!this.getList(name)) {
|
||||
throw `List '${name}' does not exist!`;
|
||||
}
|
||||
if (name === TodoLists.mainListName) {
|
||||
throw `List '${name}' cannot be deleted!`;
|
||||
}
|
||||
delete this.lists[name];
|
||||
|
||||
if (this.currentListName === name) {
|
||||
this.switchList(TodoLists.mainListName);
|
||||
}
|
||||
}
|
||||
|
||||
createList(name) {
|
||||
if (this.getList(name)) {
|
||||
throw `List'${name}' already exists!`;
|
||||
}
|
||||
this.lists[name] = new TodoList(name);
|
||||
this.switchList(name);
|
||||
}
|
||||
|
||||
switchList(name) {
|
||||
if (!this.getList(name)) {
|
||||
throw `List '${name}' does not exist!`;
|
||||
}
|
||||
this.currentListName = name;
|
||||
}
|
||||
}
|
||||
|
||||
TodoLists.listsStorageKey = 'lists';
|
||||
TodoLists.currentListStorageKey = 'currentListName';
|
||||
TodoLists.mainListName = 'Main';
|
||||
|
||||
module.exports.run = (bot, msg, args) => {
|
||||
const send = (message, deleteInSeconds = 5, prefix = ':white_check_mark: ') => msg.edit({
|
||||
embed: bot.utils.embed(`Todo List Utility (message will self-destruct in ${deleteInSeconds} seconds)`, `${prefix}${message}`)
|
||||
})
|
||||
.then(m => m.delete(deleteInSeconds * 1000));
|
||||
|
||||
|
||||
if (args.length < 1) {
|
||||
return send(Lists.getCurrentList(), 45, '');
|
||||
}
|
||||
|
||||
const {options, leftover} = bot.utils.parseArgs(args, ['d', 'c', 'i', 'l', 'n', 'r', 's']);
|
||||
let indexOption = parseInt(leftover[0], 10);
|
||||
|
||||
const ensureProperNumberOfArgs = (max, message = 'Expected list item number only', min = 1) => {
|
||||
if (leftover.length > max || leftover.length < min) {
|
||||
throw message;
|
||||
}
|
||||
};
|
||||
|
||||
if (options.c) {
|
||||
ensureProperNumberOfArgs(1);
|
||||
Lists.getCurrentList().markComplete(indexOption);
|
||||
send(`Item ${indexOption} marked complete!`);
|
||||
} else if (options.i) {
|
||||
ensureProperNumberOfArgs(1);
|
||||
Lists.getCurrentList().markComplete(indexOption, false);
|
||||
send(`Item ${indexOption} marked incomplete!`);
|
||||
} else if (options.d) {
|
||||
ensureProperNumberOfArgs(1);
|
||||
Lists.getCurrentList().remove(indexOption);
|
||||
send(`Item ${indexOption} deleted!`);
|
||||
} else if (options.l) {
|
||||
send(`Available lists: ${Lists.getListNames().join(', ')}`, 30);
|
||||
} else if (options.n) {
|
||||
ensureProperNumberOfArgs(1, 'Expected name of new list to be a single word');
|
||||
Lists.createList(leftover[0]);
|
||||
send(`List '${leftover[0]}' created!`);
|
||||
} else if (options.r) {
|
||||
ensureProperNumberOfArgs(1, 'Expected name of list to delete to be a single word');
|
||||
Lists.deleteList(leftover[0]);
|
||||
send(`List '${leftover[0]}' deleted!`);
|
||||
} else if (options.s) {
|
||||
ensureProperNumberOfArgs(1, 'Expected name of chosen list to be a single word');
|
||||
Lists.switchList(leftover[0]);
|
||||
send(`Switched to list '${leftover[0]}'`);
|
||||
} else {
|
||||
Lists.getCurrentList().add(leftover.join(' '));
|
||||
send(`Item '${leftover.join(' ')}' added!`);
|
||||
}
|
||||
|
||||
Lists.save();
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {TodoLists}
|
||||
*/
|
||||
let Lists;
|
||||
module.exports.init = bot => {
|
||||
Lists = new TodoLists(bot);
|
||||
};
|
||||
|
||||
module.exports.info = {
|
||||
name: 'todo',
|
||||
usage: 'todo | todo [options...] <index> | todo <text of item to add>',
|
||||
description: 'Manage a todo list. The command by itself will show the items in the current list.',
|
||||
options: [
|
||||
{
|
||||
name: '-c',
|
||||
usage: '-c ',
|
||||
description: 'Mark an item complete'
|
||||
},
|
||||
{
|
||||
name: '-i',
|
||||
usage: '-i ',
|
||||
description: 'Mark an item incomplete'
|
||||
},
|
||||
{
|
||||
name: '-d',
|
||||
usage: '-d',
|
||||
description: 'Delete an item'
|
||||
},
|
||||
{
|
||||
name: '-l',
|
||||
usage: '-l',
|
||||
description: 'Show all lists'
|
||||
},
|
||||
{
|
||||
name: '-n',
|
||||
usage: '-n ',
|
||||
description: 'Make a new list and set it as the current list'
|
||||
},
|
||||
{
|
||||
name: '-r',
|
||||
usage: '-r ',
|
||||
description: 'Remove a list. If the list being removed is the list currently in use, automatically switches back to the Main list.'
|
||||
},
|
||||
{
|
||||
name: '-s',
|
||||
usage: '-s ',
|
||||
description: 'Switch lists'
|
||||
}
|
||||
]
|
||||
};
|
|
@ -1,55 +0,0 @@
|
|||
const translate = require('google-translate-api');
|
||||
const stripIndents = require('common-tags').stripIndents;
|
||||
|
||||
exports.run = async (bot, msg, args) => {
|
||||
let parsed = bot.utils.parseArgs(args, ['e', 'f:']);
|
||||
|
||||
if (parsed.leftover.length < 2) {
|
||||
throw 'You must provide a language and some text to translate!';
|
||||
}
|
||||
|
||||
let lang = parsed.leftover[0];
|
||||
let input = parsed.leftover.slice(1).join(' ');
|
||||
|
||||
await msg.edit(':arrows_counterclockwise: **Translating your Text...**');
|
||||
let res;
|
||||
|
||||
try {
|
||||
res = await translate(input, { from: parsed.options.f, to: lang });
|
||||
} catch (e) {
|
||||
return msg.error(`Failed to translate: ${e.message}`);
|
||||
}
|
||||
|
||||
if (parsed.options.e) {
|
||||
return msg.edit(res.text);
|
||||
}
|
||||
|
||||
msg.delete();
|
||||
msg.channel.send({
|
||||
embed: bot.utils.embed('', stripIndents`
|
||||
**From:** __\`${parsed.options.f || '[auto]'}\`__
|
||||
**To:** __\`${lang}\`__
|
||||
|
||||
**Input:**\n\`\`\`\n${input}\n\`\`\`
|
||||
**Output:**\n\`\`\`\n${res.text}\n\`\`\`
|
||||
`)
|
||||
});
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'translate',
|
||||
usage: 'translate <lang> <text>',
|
||||
description: 'Translates text from/to any language',
|
||||
credits: 'Carbowix',
|
||||
options: [
|
||||
{
|
||||
name: '-e',
|
||||
description: 'Edits your message with the translation instead of showing an embed'
|
||||
},
|
||||
{
|
||||
name: '-f',
|
||||
usage: '-f <language>',
|
||||
description: 'Sets the `from` language, this is `auto` by default'
|
||||
}
|
||||
]
|
||||
};
|
|
@ -1,70 +0,0 @@
|
|||
const got = require('got');
|
||||
const countries = require('country-data').countries.all;
|
||||
|
||||
const makeURL = (city) => `https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22${encodeURIComponent(city)}%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys`;
|
||||
const celsius = (fahrenheit) => Math.round(((fahrenheit - 32) * 5) / 9);
|
||||
|
||||
const spacer = {
|
||||
name: '\u200b',
|
||||
value: '\u200b',
|
||||
};
|
||||
|
||||
exports.run = async (bot, msg, args) => {
|
||||
if (args.length < 1) {
|
||||
throw 'Please provide a city.';
|
||||
}
|
||||
|
||||
const city = args.join(' ');
|
||||
const res = await got(makeURL(city), { json: true });
|
||||
|
||||
if (!res || !res.body || !res.body.query || !res.body.query.results || !res.body.query.results.channel) {
|
||||
throw 'Failed to load weather info!';
|
||||
}
|
||||
|
||||
const weatherInfo = res.body.query.results.channel;
|
||||
const forecast = weatherInfo.item.forecast[0];
|
||||
|
||||
const countryInfo = countries.find(country => country.name === weatherInfo.location.country);
|
||||
const countryEmoji = countryInfo ? countryInfo.emoji : ':grey_question:';
|
||||
|
||||
const description = `The current temperature in ${weatherInfo.location.city} is ${weatherInfo.item.condition.temp}°F/${celsius(weatherInfo.item.condition.temp)}°C`;
|
||||
|
||||
const embed = bot.utils.embed(`${countryEmoji} ${weatherInfo.item.title}`, description, [
|
||||
{
|
||||
name: 'Condition',
|
||||
value: weatherInfo.item.condition.text
|
||||
},
|
||||
{
|
||||
name: 'Humidity',
|
||||
value: weatherInfo.atmosphere.humidity + '%'
|
||||
},
|
||||
{
|
||||
name: ':wind_blowing_face: Wind',
|
||||
value: `*${weatherInfo.wind.speed}mph* ; direction: *${weatherInfo.wind.direction}°*`
|
||||
},
|
||||
{
|
||||
name: `Forecast for today is *${forecast.text}*`,
|
||||
value: `Highest temp is ${forecast.high}°F/${celsius(forecast.high)}°C, lowest temp is ${forecast.low}°F/${celsius(forecast.low)}°C`,
|
||||
},
|
||||
spacer,
|
||||
spacer,
|
||||
spacer,
|
||||
spacer,
|
||||
{
|
||||
name: ':sunrise: Sunrise',
|
||||
value: weatherInfo.astronomy.sunrise
|
||||
},
|
||||
{
|
||||
name: ':city_sunset: Sunset',
|
||||
value: weatherInfo.astronomy.sunset
|
||||
}
|
||||
], { inline: true });
|
||||
|
||||
msg.edit({ embed });
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: 'weather',
|
||||
usage: 'weather <city>',
|
||||
description: 'Shows weather info for city'
|
||||
};
|
|
@ -1,10 +0,0 @@
|
|||
exports.run = function (bot, msg, args) {
|
||||
// insert code here
|
||||
msg.channel.send(`You typed: ${args.join(' ')}`);
|
||||
};
|
||||
|
||||
exports.info = {
|
||||
name: '',
|
||||
usage: '',
|
||||
description: ''
|
||||
};
|
Loading…
Reference in a new issue