Merge pull request #3 from rhearmas/master

finally got this done
This commit is contained in:
carol 2019-12-22 20:17:45 -08:00 committed by GitHub
commit ef4aa19e24
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 615 additions and 36 deletions

View file

@ -1,2 +1,56 @@
# cardboardbot
The official replacement to the old coolAppBot.
<h1 align="center">Cardboard Box</h1>
## Information
**Cardboard Box** is a [Discord](https://discordapp.com) bot for my [**Discord server**](https://discord.gg/4zJ8xqV) powered by [Discord.js](https://discord.js.org). It comes packaged with many utilities and fun stuff, and even some special moderation functions.
**This bot is not suitable for usage outside of my Discord server!** This repository is primarily for issue tracking and global management between my own devices. If you really, *really* want to run it yourself, read the sections below.
## Adding the bot to your guild
Don't want to run the bot yourself? Simply use [this link](https://discordapp.com/oauth2/authorize/?permissions=8&scope=bot&client_id=618576806177538079) to invite it to your own guild. If you prefer to run it under your own bot name, read the section below.
<h1 align="center">Running it yourself</h1>
If you're really wanting to use this bot yourself, let's go over what you need and how to install it.
## Requirements
- `git` command line. Install by clicking your operating system's name in this list:
- [Windows](https://git-scm.com/download/win)
- [Linux](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
- [Macintosh](https://git-scm.com/download/mac)
- `node` version [8.0.0 or higher](https://nodejs.org).
- Your **Discord bot token.** Read the first section of [this page](https://anidiots.guide/getting-started/the-long-version.html) on how to snag it.
## Installation
1. Head on over to your terminal (preferrably **Command Prompt**) and clone the repository.
- If you want to clone to a specific folder, you have two options:
- **`cd` into your desired folder.** For example, if you wanted to clone the repository into Documents, opening the terminal normally and run `cd C:/Users/<user>/Documents`.
- Open the terminal in a specific folder by doing **Shift-Rightclick => Open <Powershell/command terminal> here**.
- After doing either of those steps, clone the repository by running `git clone https://github.com/rhearmas/cardboardbot.git` through your terminal.
2. When `git` has finished, `cd` into the newly-created folder for the repository.
3. Run `npm install`. This installs all the prerequisites for the bot through **Node package manager**, which is bundled with `node`.
- If you get any errors about python or msibuild.exe or binding, read the requirements section again and make sure you've installed **everything**.
4. Run `node setup.js` to get a configuration file added.
## Running the bot
Open your terminal and run `node index.js` inside the folder. Don't forget to `cd` into it if the folder isn't in places like your Desktop.
## Getting it to your server
Generate an OAuth link for your bot. Use [this delicious link](https://finitereality.github.io/permissions-calculator/?v=0) to get your link. It even has a calculator for permissions!
<h1 align="center">Credits</h1>
- [SharpBot, a selfbot for Discord](https://github.com/RayzrDev/SharpBot) was actually my source for most of these cool commands! Huge kudos to [RayzrDev](https://github.com/RayzrDev) for making a cool selfbot.
- This was initially an edit to [GuideBot, the boilerplate example bot in Discord.js](https://github.com/AnIdiotsGuide/guidebot). It has some minor edits to the base code, but most of the basic stuff came from this very example bot.
<h1 align="center">Join me</h1>
If you need a fun server to join, regardless of whether or not you're new to Discord, join now! If you've never used Discord before, don't fret! It only takes a few minutes to sign up and get started.
# https://discord.gg/4zJ8xqV

View file

@ -38,9 +38,9 @@ function randomItem(array) {
exports.run = async (client, message, args, level) => {
message.delete();
if (args.length < 1) {
message.delete();
return (await message.reply("Please specify something to ask of the magic 8-ball!")).delete(5000);
if (!args[0]) {
message.delete();
return (await message.reply("text")).delete(5000);
}
let response = randomItem(responses);

View file

@ -5,7 +5,7 @@ exports.run = async (client, message, args, level) => {
message.delete();
return (await message.channel.send("Please provide some text to clapify")).delete(5000);
}
message.delete();
message.channel.send(args.map(randomizeCase).join(':clap:'));
};

View file

@ -1,22 +0,0 @@
exports.run = async (client, message, args, level) => {
const response = await client.awaitReply(message, "Hey, what's your favorite color?");
if(response !== "black") {
message.reply(`Oh, I really love ${response} too!`);
} else {
message.reply(`you like ${response}? Disgusting.`);
}
}
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "User"
};
exports.help = {
name: "color",
category: "Fun",
description: "Who likes a color?",
usage: "color"
};

View file

@ -25,7 +25,7 @@ exports.run = async (client, message, args, level) => {
message.delete();
return (await message.reply("Please specify something to ask of the magic 8-ball!")).delete(5000);
}
message.delete();
message.channel.send(
args.join(' ')
.split('')

32
commands/Fun/fliptext.js Normal file
View file

@ -0,0 +1,32 @@
const mapping = '¡"#$%⅋,)(*+\'-˙/0ƖᄅƐㄣϛ9ㄥ86:;<=>?@∀qƆpƎℲפHIſʞ˥WNOԀQɹS┴∩ΛMX⅄Z[/]^_`ɐqɔpǝɟƃɥᴉɾʞlɯuodbɹsʇnʌʍxʎz{|}~';
const OFFSET = '!'.charCodeAt(0);
exports.run = async (client, message, args, level) => {
if (args.length < 1) {
message.delete();
message.reply("you didn't specify any text for me to flip!").delete(5000);
}
message.delete();
message.channel.send(
args.join(' ').split('')
.map(c => c.charCodeAt(0) - OFFSET)
.map(c => mapping[c] || ' ')
.reverse().join('')
);
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: ["flip"],
permLevel: "User"
};
exports.help = {
name: "fliptext",
category: "Fun",
description: "Flips text upside down!",
usage: "fliptext <text>"
};

22
commands/Fun/initial.js Normal file
View file

@ -0,0 +1,22 @@
exports.run = async (client, message, args, level) => {
if (!args[0]) {
message.delete();
return (await message.reply("you must input some text to be transformed.")).delete(5000);
}
message.delete();
message.channel.send(args.map(arg => arg[0].toUpperCase() + arg.slice(1).toLowerCase()).join(' '));
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "User"
};
exports.help = {
name: "initial",
category: "Fun",
description: "Transforms the text you insert into Initial Caps.",
usage: "initial <text>"
};

46
commands/Fun/jumbo.js Normal file
View file

@ -0,0 +1,46 @@
exports.run = async (client, message, args, level) => {
if (args.length < 1) {
message.delete();
return (await message.reply("you didn't provide an emoji to enlarge.")).delete(5000);
}
if (args[0].charCodeAt(0) >= 55296) {
message.delete();
return (await message.reply("I can't enlarge Discord's built-in emoji.")).delete(5000);
}
const match = args[0].match(/<:[a-zA-Z0-9_-]+:(\d{18})>/);
if (!match || !match[1]) {
message.delete();
return (await message.reply("please provide a valid emoji.")).delete(5000);
}
const emoji = client.emojis.get(match[1]);
if (!emoji) {
message.delete();
return (await message.reply("I couldn't identify that emoji.")).delete(5000);
}
message.delete();
message.channel.send({
files: [
emoji.url
]
});
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "User"
};
exports.help = {
name: "jumbo",
category: "Fun",
description: "Enlarges an emoji.",
usage: "jumbo <emoji>"
};

100
commands/Fun/leet.js Normal file
View file

@ -0,0 +1,100 @@
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 = async (client, message, args, level) => {
const parsedArgs = client.parseArgs(args, ['e', 't']);
if (parsedArgs.leftover.length < 1) {
message.delete();
return (await message.reply("please provide some text to convert.")).delete(5000);
}
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 = client.randomSelection(extendedLeetReplacements[str.toLowerCase()] || [str]);
selection = client.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.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "User"
};
exports.help = {
name: "leet",
category: "Fun",
description: "Talk like a true gamer.",
usage: "leet <text>"
};

22
commands/Fun/reverse.js Normal file
View file

@ -0,0 +1,22 @@
exports.run = async (client, message, args, level) => {
if (args.length < 1) {
message.delete();
return (await message.reply("text")).delete(5000);
}
message.delete();
message.channel.send(args.join(' ').split('').reverse().join(''));
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "User"
};
exports.help = {
name: "reverse",
category: "Fun",
description: "Reverses the text you insert.",
usage: "reverse <text>"
};

49
commands/Fun/roll.js Normal file
View file

@ -0,0 +1,49 @@
const Roll = require('roll');
const roller = new Roll();
exports.run = async (client, message, args, level) => {
if (!args[0]) {
message.delete();
return (await message.reply("you must specify in dice notation (XdY).")).delete(5000);
}
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]);
message.delete();
let embed = client.embed(
`Total: ${results.result}`,
`${[].concat.apply([], results.rolled).join(', ').substr(0, 1800)}`,
[
{
name: '\u200b',
value: footer
}
]
);
message.channel.send({ embed });
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "User"
};
exports.help = {
name: "roll",
category: "Fun",
description: "Rolls X dice with Y sides. Supports standard dice notation.",
usage: "roll <XdY> [reason]"
};

60
commands/Fun/shoot.js Normal file
View file

@ -0,0 +1,60 @@
const responses = [
'is on a killing spree!',
'just shot someone!',
'murdered an innocent! Grab the sherrif!',
'got a bullseye.',
'wrangled a person!',
'made someone get got!',
'brought a gun to a knife fight.',
'earned someone a closed-casket funeral.',
'shot a weeb!',
'pumped up some kicks!'
];
const critResponses = [
'GOT A HEADSHOT!!',
'HIT A 360 NOSCOPE!!!!',
'EXPLODED A CORPSE WITH A BULLET!!',
'HAS LUCK ON THEIR SIDE!!',
'SENT SOMEONE FLYING HOME!!!!'
];
function randomItem(array) {
return array[Math.floor(Math.random() * array.length)];
}
exports.run = async (client, message, args, level) => {
if (message.mentions.users.size < 1) {
message.delete();
return (await message.reply("gotta mention those people you wanna shoot, ya know.")).delete(5000);
}
let response = randomItem(responses);
let crit = Math.floor(Math.random() * 10);
// console.log(`crit is ${crit}`)
if(crit === 1) {
response = randomItem(critResponses);
}
let output = message.mentions.users.map(m => `**${m}** ${crit === 1 ? ':skull:' : ''}:boom::gun: **${message.author}**`).join('\n');
message.delete();
message.channel.send({
embed: client.embed(`${crit === 1 ? message.author.username.toUpperCase() : message.author.username} ${response}`, output)
});
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "User"
};
exports.help = {
name: "shoot",
category: "Fun",
description: "Shoots yer friendz!",
usage: "shoot <mention>"
};

33
commands/Fun/sigh.js Normal file
View file

@ -0,0 +1,33 @@
const ascii = `
\`\`\`
_______ _________ _________ , ,
/ | / | |
| | | | |
| | | | |
\\_____, | | _______, |________|
\\ | | | | |
| | | | | |
| | | | | |
______/ ____|____ \\________| | |
\u200b
\`\`\`
`;
exports.run = async (client, message, args, level) => {
message.delete();
message.channel.send(ascii);
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "User"
};
exports.help = {
name: "sigh",
category: "Fun",
description: "Siiiiggggghhh...",
usage: "sigh"
};

32
commands/Fun/space.js Normal file
View file

@ -0,0 +1,32 @@
exports.run = async (client, message, args, level) => {
if(!args[0]) {
message.delete();
return (await message.reply("you didn't provide any text to space out!")).delete(5000);
}
let amount = 2;
if(!isNaN(args[0])) {
amount = parseInt(args[0]);
(amount < 1) && (amount = 1);
(amount > 15) && (amount = 15);
args = args.slice(1);
}
message.delete();
message.channel.send(args.join(' '.repeat(amount / 2)).split('').join(' '.repeat(amount)));
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "User"
};
exports.help = {
name: "space",
category: "Fun",
description: "Spaces out text to look all dramatic n' stuff.",
usage: "space [amount] <text>"
};

View file

@ -4,13 +4,21 @@ exports.run = async (client, message, args) => {
msg = args.join(" ");
await message.delete();
if(args.length == 0)
return message.reply("Please insert a valid message.")
.then(msg => {
msg.delete(5000).catch(e => {e})
})
if(args.length === 0) {
return (await message.reply("please insert a valid message.")).delete(5000);
}
let location = message.channel;
guild = message.guild;
if(args[0].startsWith('<#') && args[0].endsWith('>')) {
location = args[0].slice(2, -1);
location = guild.channels.find(c => c.id === location);
msg = msg.slice(args[0].length);
console.log(`msg is ${msg}`)
}
message.channel.send(msg);
location.send(msg);
}
exports.conf = {
@ -24,5 +32,5 @@ exports.help = {
name: "talk",
category: "Fun",
description: "Talk as the bot in the current channel you're in.",
usage: "talk text"
usage: "talk <text>"
};

66
commands/Fun/tiny.js Normal file
View file

@ -0,0 +1,66 @@
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 = async (client, message, args, level) => {
if (!args[0]) {
message.delete();
return (await message.reply("you must provide some text to shrink!")).delete(5000);
}
let output = args.join(' ');
mappings.forEach(replacer => output = output.replace(replacer.regex, replacer.replacement));
message.delete();
message.channel.send(output);
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "User"
};
exports.help = {
name: "tiny",
category: "Fun",
description: "Super tiny text!",
usage: "tiny <text>"
};

58
commands/Fun/xkcd.js Normal file
View file

@ -0,0 +1,58 @@
const got = require('got');
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.run = async (client, message, args, level) => {
let id;
if (args[0] === 'latest') {
id = (await getLatest()).num;
} else {
id = parseInt(args[0]);
if (isNaN(id)) {
id = await getRandom();
}
}
while (id === 404) {
id = await getRandom();
}
const info = await getInfo(id);
message.delete();
message.channel.send({
embed: client.embed(`[${id}] ${info.title}`, '', [], {
image: info.img,
color: [150, 168, 199],
url: `http://xkcd.com/${id}`
}).setFooter(info.alt)
});
};
exports.conf = {
enabled: true,
guildOnly: false,
aliases: [],
permLevel: "User"
};
exports.help = {
name: "xkcd",
category: "Fun",
description: "Fetches random or specific XKCD comics.",
usage: "xkcd [latest|<id>]"
};

View file

@ -18,4 +18,13 @@ exports.help = {
usage: ""
};
*/
/* Basic message auto-deletion
if (!args[0]) {
message.delete();
return (await message.reply("text")).delete(5000);
}
*/

View file

@ -154,6 +154,8 @@ module.exports = (client) => {
client.wait = require("util").promisify(setTimeout);
client.randomSelection = choices => choices[Math.floor(Math.random() * choices.length)];
process.on("uncaughtException", (err) => {
const errorMsg = err.stack.replace(new RegExp(`${__dirname}/`, "g"), "./");
client.logger.error(`Uncaught Exception: ${errorMsg}`);
@ -363,4 +365,6 @@ module.exports = (client) => {
}
});
};
client.quoteRegex = input => `${input}`.replace(/[.?*+^$[\]\\(){}|-]/g, '\\$&');
};

5
package-lock.json generated
View file

@ -608,6 +608,11 @@
"signal-exit": "^3.0.2"
}
},
"roll": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/roll/-/roll-1.2.0.tgz",
"integrity": "sha1-9LlQUZBpVXOe0+8ACkE5VaqwaiI="
},
"run-async": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",

View file

@ -33,6 +33,7 @@
"moment": "^2.24.0",
"moment-duration-format": "^2.3.2",
"recrawl": "^2.0.0",
"roll": "^1.2.0",
"webdict": "^0.3.0"
},
"publishConfig": {