Remove more commands

This commit is contained in:
Dragon Fire
2024-03-20 21:53:19 -04:00
parent 450ea2b7f5
commit de4098ba6b
79 changed files with 4 additions and 3795 deletions
-20
View File
@@ -24,10 +24,6 @@ SILVER_FISH_EMOJI_ID=
SILVER_FISH_EMOJI_NAME= SILVER_FISH_EMOJI_NAME=
PORTAL_EMOJI_ID= PORTAL_EMOJI_ID=
PORTAL_EMOJI_NAME= PORTAL_EMOJI_NAME=
FLANKER_EMOJI_ID=
FRONT_LINE_EMOJI_ID=
SUPPORT_EMOJI_ID=
DAMAGE_EMOJI_ID=
LOADING_EMOJI_ID= LOADING_EMOJI_ID=
MEGA_EVOLVE_EMOJI_ID= MEGA_EVOLVE_EMOJI_ID=
MEGA_EVOLVE_EMOJI_NAME= MEGA_EVOLVE_EMOJI_NAME=
@@ -37,36 +33,20 @@ NAME_RATER_EMOJI_ID=
ALPHA_VANTAGE_KEY= ALPHA_VANTAGE_KEY=
ANILIST_USERNAME= ANILIST_USERNAME=
BITLY_KEY= BITLY_KEY=
CLEARBIT_KEY=
CLEVERBOT_KEY= CLEVERBOT_KEY=
DEVIANTART_ID= DEVIANTART_ID=
DEVIANTART_SECRET= DEVIANTART_SECRET=
FACEPLUSPLUS_KEY=
FACEPLUSPLUS_SECRET=
FLICKR_KEY=
GIPHY_KEY= GIPHY_KEY=
GITHUB_ACCESS_TOKEN= GITHUB_ACCESS_TOKEN=
GODADDY_KEY=
GODADDY_SECRET=
GOOGLE_KEY=
GOV_KEY= GOV_KEY=
IMGUR_KEY= IMGUR_KEY=
OPENWEATHERMAP_KEY= OPENWEATHERMAP_KEY=
OSU_KEY= OSU_KEY=
PERSONAL_GOOGLE_CALENDAR_ID=
SPOTIFY_KEY= SPOTIFY_KEY=
SPOTIFY_SECRET= SPOTIFY_SECRET=
STACKOVERFLOW_KEY=
TENOR_KEY=
TMDB_KEY= TMDB_KEY=
TUMBLR_KEY=
TWITCH_ID=
TWITCH_SECRET=
TWITTER_KEY=
TWITTER_SECRET=
UNSPLASH_KEY= UNSPLASH_KEY=
USPS_USERID= USPS_USERID=
WATTPAD_KEY=
WEBSTER_KEY= WEBSTER_KEY=
XIAO_GITHUB_REPO_NAME= XIAO_GITHUB_REPO_NAME=
XIAO_GITHUB_REPO_USERNAME= XIAO_GITHUB_REPO_USERNAME=
-3
View File
@@ -20,9 +20,6 @@ blacklist.json
# Tensorflow Models # Tensorflow Models
tf_models/ tf_models/
# Tesseract Trained Data
*.traineddata
# Mac Files # Mac Files
.DS_Store .DS_Store
Binary file not shown.

Before

Width:  |  Height:  |  Size: 578 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 300 KiB

-10
View File
@@ -1,10 +0,0 @@
{
"airpods": "PRXJ2AM",
"airpods-pro": "PWP22AM",
"pencil": "PU8F2AM",
"ipod": "PVHV2LL",
"ipad-pro": "PTEM2LL",
"ipad": "PW752LL",
"ipad-mini": "PUQX2LL",
"ipad-air": "PUUK2LL"
}
-21
View File
@@ -1,21 +0,0 @@
[
"hentai",
"ecchi",
"pantsu",
"hentai_gif",
"ahegao",
"rule34",
"hentaipetgirls",
"uncensoredhentai",
"masturbationhentai",
"animehandbras",
"hentaicleavage",
"sukebei",
"yurigif",
"collarhentai",
"oppai_gif",
"cumhentai",
"hentaimini",
"maidhentai",
"yuri"
]
-18
View File
@@ -1,18 +0,0 @@
{
"Damage": {
"id": "damage",
"display": "Damage"
},
"Flanker": {
"id": "kills",
"display": "Kills"
},
"Front Line": {
"id": "objective_time",
"display": "Objective Time"
},
"Support": {
"id": "healing",
"display": "Healing"
}
}
-32
View File
@@ -1,32 +0,0 @@
[
"nsfw_gifs",
"pussy",
"boobs",
"tits",
"ass",
"asstastic",
"lesbians",
"porn",
"nsfw",
"asiansgonewild",
"adorableporn",
"realgirls",
"holdthemoan",
"tinytits",
"blowjobs",
"pawg",
"gonewild",
"nsfw_plowcam",
"legalteens",
"pornstarlethq",
"biggerthanyouthought",
"onoff",
"shorthairchicks",
"petitegonewild",
"plastt",
"bustypetite",
"cumsluts",
"amateur",
"bbw",
"bbwgw"
]
-19
View File
@@ -1,19 +0,0 @@
[
["soundboard", "alarm.mp3"],
["soundboard", "car-crash.mp3"],
["soundboard", "cat.mp3"],
["soundboard", "cow.mp3"],
["soundboard", "dun-dun-dun.mp3"],
["explosion.mp3"],
["soundboard", "hello-there.mp3"],
["soundboard", "here-we-go-again.mp3"],
["jeopardy.mp3"],
["soundboard", "laugh-track.mp3"],
["soundboard", "nipah.mp3"],
["soundboard", "rooster.mp3"],
["soundboard", "sad-violin.mp3"],
["soundboard", "slow-clap.mp3"],
["whos-that-pokemon.mp3"],
["soundboard", "windows-error.mp3"],
["soundboard", "windows-start-up.mp3"]
]
-77
View File
@@ -1,77 +0,0 @@
{
"sonic": "sonic",
"homer": "homer-simpson",
"spongebob": "spongebob-squarepants",
"schwarzenegger": "arnold-schwarzenegger",
"christopher-lee": "christopher-lee",
"leonard-nimoy": "leonard-nimoy",
"squidward": "squidward",
"obama": "barack-obama",
"bart": "bart-simpson",
"lisa": "lisa-simpson",
"devito": "danny-devito",
"clinton": "bill-clinton",
"bush": "george-w-bush",
"reagan": "ronald-reagan",
"carter": "jimmy-carter",
"nixon": "richard-nixon",
"bill-gates": "bill-gates",
"krabs": "mr-krabs",
"scout": "scout",
"bob-barker": "bob-barker",
"boss": "the-boss",
"craig-ferguson": "craig-ferguson",
"gilbert-gottfried": "gilbert-gottfried",
"jim-cramer": "jim-cramer",
"mitch-mcconnell": "mitch-mcconnell",
"paula-deen": "paula-deen",
"david-attenborough": "david-attenborough",
"tucker-carlson": "tucker-carlson",
"alan-rickman": "alan-rickman",
"ben-shapiro": "ben-shapiro",
"betty-white": "betty-white",
"bill-nye": "bill-nye",
"bryan-cranston": "bryan-cranston",
"crypt-keeper": "crypt-keeper",
"dr-phil": "dr-phil-mcgraw",
"jk-simmons": "j-k-simmons",
"judi-dench": "judi-dench",
"michael-rosen": "michael-rosen",
"neil-degrasse-tyson": "neil-degrasse-tyson",
"palmer-luckey": "palmer-luckey",
"peter-thiel": "peter-thiel",
"richard-ayoade": "richard-ayoade",
"sam-altman": "sam-altman",
"saruman": "christopher-lee",
"snape": "alan-rickman",
"shohreh-aghdashloo": "shohreh-aghdashloo",
"wilford-brimley": "wilford-brimley",
"yugi": "yami-yugi",
"anderson-cooper": "anderson-cooper",
"ben-stein": "ben-stein",
"boomstick": "boomstick",
"james-earl-jones": "james-earl-jones",
"vader": "james-earl-jones",
"david-cross": "david-cross",
"hillary": "hillary-clinton",
"john-oliver": "john-oliver",
"zuckerberg": "mark-zuckerberg",
"moistcr1tikal": "moistcr1tikal",
"mr-rogers": "fred-rogers",
"trump": "donald-trump",
"sarah-palin": "sarah-palin",
"snake": "solid-snake",
"tommy-wiseau": "tommy-wiseau",
"trevor-philips": "trevor-philips",
"tupac-shakur": "tupac-shakur",
"vegeta": "vegeta",
"wizard": "wizard",
"george-takei": "george-takei",
"paul-graham": "paul-graham",
"yoda": "yoda",
"goku": "goku",
"peter-griffin": "peter-griffin",
"obi-wan": "obi-wan-kenobi",
"cartman": "eric-cartman",
"anakin": "anakin-skywalker"
}
-51
View File
@@ -1,51 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const { GODADDY_KEY, GODADDY_SECRET } = process.env;
module.exports = class DomainAvailableCommand extends Command {
constructor(client) {
super(client, {
name: 'domain-available',
aliases: ['domain', 'buy-domain'],
group: 'analyze',
memberName: 'domain-available',
description: 'Determines if a domain is available for purchase.',
credit: [
{
name: 'GoDaddy',
url: 'https://www.godaddy.com/',
reason: 'API',
reasonURL: 'https://developer.godaddy.com/'
}
],
args: [
{
key: 'url',
prompt: 'What URL do you want to test?',
type: 'url'
}
]
});
}
async run(msg, { url }) {
const { type, domain, topLevelDomains } = this.client.parseDomain(url.hostname);
if (type !== this.client.ParseResultType.Listed) return msg.reply('This domain is not supported.');
try {
const { body } = await request
.get('https://api.godaddy.com/v1/domains/available')
.set({ Authorization: `sso-key ${GODADDY_KEY}:${GODADDY_SECRET}` })
.query({
domain: `${domain}.${topLevelDomains.join('.')}`,
checkType: 'FAST',
forTransfer: false
});
if (!body.definitive) return msg.reply('❔ This domain might be available, but I\'m not sure.');
if (body.available) return msg.reply('👍 This domain is available.');
return msg.reply('👎 This domain is taken.');
} catch (err) {
if (err.status === 422) return msg.reply('This domain is not supported.');
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-37
View File
@@ -1,37 +0,0 @@
const Command = require('../../framework/Command');
const { loadImage } = require('canvas');
const request = require('node-superfetch');
const { hasAlpha } = require('../../util/Canvas');
module.exports = class HasTransparencyCommand extends Command {
constructor(client) {
super(client, {
name: 'has-transparency',
aliases: ['has-alpha', 'transparency', 'transparent', 'alpha'],
group: 'analyze',
memberName: 'has-transparency',
description: 'Determines if an image has transparency in it.',
throttling: {
usages: 2,
duration: 10
},
args: [
{
key: 'image',
prompt: 'What image would you like to test?',
type: 'image-or-avatar'
}
]
});
}
async run(msg, { image }) {
try {
const { body } = await request.get(image);
const data = await loadImage(body);
return msg.reply(`This image **${hasAlpha(data) ? 'has' : 'does not have'}** transparency.`);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
+1 -1
View File
@@ -22,7 +22,7 @@ module.exports = class NsfwUrlCommand extends Command {
async run(msg, { url }) { async run(msg, { url }) {
const nsfw = await isUrlNSFW(url, this.client.adultSiteList); const nsfw = await isUrlNSFW(url, this.client.adultSiteList);
if (nsfw === null) return msg.reply('❔ This site sent an error, or just didn\'t respond.'); if (nsfw === null) return msg.reply('❔ This site sent an error, or just didn\'t respond.');
if (!nsfw) return msg.reply('👍 This site is safe!'); if (!nsfw) return msg.reply('👍 This site is SFW!');
return msg.reply('👎 This site is NSFW.'); return msg.reply('👎 This site is NSFW.');
} }
}; };
-55
View File
@@ -1,55 +0,0 @@
const Command = require('../../framework/Command');
const { createWorker } = require('tesseract.js');
const { reactIfAble } = require('../../util/Util');
const { LOADING_EMOJI_ID, SUCCESS_EMOJI_ID, FAILURE_EMOJI_ID } = process.env;
module.exports = class OcrCommand extends Command {
constructor(client) {
super(client, {
name: 'ocr',
aliases: ['tesseract', 'optical-character-recognition'],
group: 'analyze',
memberName: 'ocr',
description: 'Performs Optical Character Recognition on an image.',
throttling: {
usages: 2,
duration: 60
},
args: [
{
key: 'image',
prompt: 'What image would you like to perform OCR on?',
type: 'image-or-avatar'
}
]
});
}
async run(msg, { image }) {
if (image.toLowerCase().endsWith('.gif')) return msg.reply('I cannot read text from GIF images.');
await reactIfAble(msg, this.client.user, LOADING_EMOJI_ID, '💬');
const worker = createWorker();
await worker.load();
await worker.loadLanguage('eng');
await worker.initialize('eng');
let timedOut = false;
const timeout = setTimeout(async () => {
timedOut = true;
await worker.terminate();
await reactIfAble(msg, msg.author, FAILURE_EMOJI_ID, '❌');
await msg.reply('Scanning took longer than 30 seconds, so I\'ve given up.');
}, 30000);
const { data: { text } } = await worker.recognize(image);
if (timedOut) return null;
clearTimeout(timeout);
await worker.terminate();
await reactIfAble(msg, this.client.user, SUCCESS_EMOJI_ID, '✅');
if (!text) return msg.reply('There is no text in this image.');
if (text.length > 2000) {
return msg.reply('The result was over 2000 characters, so here\'s a TXT file.', {
files: [{ attachment: Buffer.from(text), name: 'ocr.txt' }]
});
}
return msg.reply(text);
}
};
-75
View File
@@ -1,75 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const UserAgent = require('user-agents');
const { stripIndents } = require('common-tags');
const { reactIfAble } = require('../../util/Util');
const { LOADING_EMOJI_ID, SUCCESS_EMOJI_ID, FAILURE_EMOJI_ID } = process.env;
const fileTypeRe = /\.(jpe?g|png|gif|jfif|bmp)(\?.+)?$/i;
const notAllowed = ['gif', 'jfif', 'bmp'];
module.exports = class RepostCommand extends Command {
constructor(client) {
super(client, {
name: 'repost',
aliases: ['repost-sleuth'],
group: 'analyze',
memberName: 'repost',
description: 'Checks if an image is a repost.',
credit: [
{
name: 'Reddit Repost Sleuth',
url: 'https://www.repostsleuth.com/',
reason: 'API'
}
],
args: [
{
key: 'image',
prompt: 'What image would you like to check?',
type: 'image-or-avatar'
}
]
});
}
async run(msg, { image }) {
if (notAllowed.includes(image.toLowerCase().match(fileTypeRe)[1])) {
return msg.reply('I cannot analyze images in this format.');
}
try {
await reactIfAble(msg, this.client.user, LOADING_EMOJI_ID, '💬');
const { body } = await request.get(image);
const results = await this.checkImage(body, image);
await reactIfAble(msg, this.client.user, SUCCESS_EMOJI_ID, '✅');
if (results === false) return msg.reply('This image is clean.');
return msg.reply(stripIndents`
This image may be a repost. I've seen it **${results.matches.length + 1}** times.
The closest match is at **${results.closest_match.hamming_match_percent}%** similarity.
${results.closest_match.post.url}
`);
} catch (err) {
await reactIfAble(msg, msg.author, FAILURE_EMOJI_ID, '❌');
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async checkImage(image, fileurl) {
const { body } = await request
.post('https://api.repostsleuth.com/image')
.query({
filter: true,
same_sub: false,
filter_author: false,
only_older: false,
include_crossposts: false,
meme_filter: false,
target_match_percent: 90,
filter_dead_matches: false,
target_days_old: 0
})
.attach('image', image, `image.${fileurl.match(fileTypeRe)[1]}`)
.set({ 'user-agent': new UserAgent().toString() });
if (!body.closest_match) return false;
return body;
}
};
-55
View File
@@ -1,55 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const { version } = require('../../package');
const { GOOGLE_KEY } = process.env;
module.exports = class SafeUrlCommand extends Command {
constructor(client) {
super(client, {
name: 'safe-url',
aliases: ['check-url', 'safe-browsing', 'virus', 'safe-link', 'check-link', 'spoopy-link'],
group: 'analyze',
memberName: 'safe-url',
description: 'Determines if a URL is safe or not.',
credit: [
{
name: 'Google',
url: 'https://www.google.com/',
reason: 'Safe Browsing API',
reasonURL: 'https://developers.google.com/safe-browsing/'
}
],
args: [
{
key: 'url',
prompt: 'What URL do you want to test?',
type: 'url'
}
]
});
}
async run(msg, { url }) {
try {
const { body } = await request
.post('https://safebrowsing.googleapis.com/v4/threatMatches:find')
.query({ key: GOOGLE_KEY })
.send({
client: {
clientId: 'xiao-discord',
clientVersion: version
},
threatInfo: {
threatTypes: ['MALWARE', 'SOCIAL_ENGINEERING'],
platformTypes: ['ANY_PLATFORM'],
threatEntryTypes: ['URL'],
threatEntries: [{ url }]
}
});
if (!body.matches) return msg.reply(`👍 Good to go! This link is safe!`);
return msg.reply('⚠️ This link is unsafe! **Do not click it!** ⚠️');
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-57
View File
@@ -1,57 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const { Message } = require('discord.js');
const { GOOGLE_KEY } = process.env;
module.exports = class ToxicityCommand extends Command {
constructor(client) {
super(client, {
name: 'toxicity',
aliases: ['perspective', 'comment-toxicity', 'toxic'],
group: 'analyze',
memberName: 'toxicity',
description: 'Determines the toxicity of text.',
flags: [
{
key: 'severe',
description: 'Makes the check much less vulnerable to basic swearing.'
}
],
credit: [
{
name: 'Perspective API',
url: 'https://www.perspectiveapi.com/#/',
reason: 'API'
}
],
args: [
{
key: 'text',
prompt: 'What text do you want to test the toxicity of?',
type: 'message|string'
}
]
});
}
async run(msg, { text, flags: { severe } }) {
if (text instanceof Message) text = text.content;
try {
const { body } = await request
.post('https://commentanalyzer.googleapis.com/v1alpha1/comments:analyze')
.query({ key: GOOGLE_KEY })
.send({
comment: { text },
languages: ['en'],
requestedAttributes: severe ? { SEVERE_TOXICITY: {} } : { TOXICITY: {} }
});
const score = severe ? body.attributeScores.SEVERE_TOXICITY : body.attributeScores.TOXICITY;
const toxicity = Math.round(score.summaryScore.value * 100);
if (toxicity >= 70) return msg.reply(`Likely to be perceived as toxic. (${toxicity}%)`);
if (toxicity >= 40) return msg.reply(`Unsure if this will be perceived as toxic. (${toxicity}%)`);
return msg.reply(`Unlikely to be perceived as toxic. (${toxicity}%)`);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-116
View File
@@ -1,116 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const { createCanvas, loadImage } = require('canvas');
const { stripIndents } = require('common-tags');
const { base64, reactIfAble } = require('../../util/Util');
const { LOADING_EMOJI_ID, SUCCESS_EMOJI_ID, FAILURE_EMOJI_ID } = process.env;
module.exports = class WhatAnimeCommand extends Command {
constructor(client) {
super(client, {
name: 'what-anime',
aliases: ['anime-source', 'anime-src', 'trace-moe'],
group: 'analyze',
memberName: 'what-anime',
description: 'Determines what anime a screenshot is from.',
throttling: {
usages: 2,
duration: 30
},
credit: [
{
name: 'WAIT: What Anime Is This?',
url: 'https://trace.moe/',
reason: 'API',
reasonURL: 'https://soruly.github.io/trace.moe/#/'
}
],
args: [
{
key: 'screenshot',
prompt: 'What screenshot do you want to scan?',
type: 'image'
}
]
});
}
async run(msg, { screenshot }) {
try {
await reactIfAble(msg, this.client.user, LOADING_EMOJI_ID, '💬');
const status = await this.fetchRateLimit();
if (!status.status) {
await reactIfAble(msg, msg.author, FAILURE_EMOJI_ID, '❌');
return msg.reply(`Oh no, I'm out of requests! Please wait ${status.refresh} seconds and try again.`);
}
let { body } = await request.get(screenshot);
if (screenshot.endsWith('.gif')) body = await this.convertGIF(body);
const result = await this.search(body, msg.channel.nsfw);
if (result === 'size') {
await reactIfAble(msg, msg.author, FAILURE_EMOJI_ID, '❌');
return msg.reply('Please do not send an image larger than 10MB.');
}
if (result.nsfw && !msg.channel.nsfw) {
await reactIfAble(msg, msg.author, FAILURE_EMOJI_ID, '❌');
return msg.reply('This is from a hentai, and this isn\'t an NSFW channel, pervert.');
}
await reactIfAble(msg, this.client.user, SUCCESS_EMOJI_ID, '✅');
const title = `${result.title}${result.episode ? ` episode ${result.episode}` : ''}`;
return msg.reply(stripIndents`
I'm ${result.prob}% sure this is from ${title}.
${result.prob < 90 ? '_This probablity is rather low, try using a higher quality image._' : ''}
`, result.preview ? { files: [{ attachment: result.preview, name: 'preview.mp4' }] } : {});
} catch (err) {
await reactIfAble(msg, msg.author, FAILURE_EMOJI_ID, '❌');
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async fetchRateLimit() {
try {
const { body } = await request.get('https://trace.moe/api/me');
return { status: body.user_limit > 0, refresh: body.user_limit_ttl };
} catch {
return { status: false, refresh: Infinity };
}
}
async search(file) {
if (Buffer.byteLength(file) > 1e+7) return 'size';
const { body } = await request
.post('https://trace.moe/api/search')
.attach('image', base64(file));
const data = body.docs[0];
return {
prob: Math.round(data.similarity * 100),
episode: data.episode,
title: data.title_english,
preview: await this.fetchPreview(data),
nsfw: data.is_adult
};
}
async fetchPreview(data) {
try {
const { body } = await request
.get(`https://media.trace.moe/video/${data.anilist_id}/${encodeURIComponent(data.filename)}`)
.query({
t: data.at,
token: data.tokenthumb,
mute: true,
size: 'm'
});
return body;
} catch {
return null;
}
}
async convertGIF(image) {
const data = await loadImage(image);
const canvas = createCanvas(data.width, data.height);
const ctx = canvas.getContext('2d');
ctx.drawImage(data, 0, 0);
return canvas.toBuffer();
}
};
-53
View File
@@ -1,53 +0,0 @@
const Command = require('../../framework/Command');
const { MessageEmbed } = require('discord.js');
const request = require('node-superfetch');
module.exports = class MDNCommand extends Command {
constructor(client) {
super(client, {
name: 'mdn',
group: 'code',
memberName: 'mdn',
description: 'Searches MDN for your query.',
clientPermissions: ['EMBED_LINKS'],
credit: [
{
name: 'MDN Web Docs',
url: 'https://developer.mozilla.org/en-US/',
reason: 'API'
}
],
args: [
{
key: 'query',
prompt: 'What article would you like to search for?',
type: 'string',
parse: query => query.replaceAll('#', '.prototype.')
}
]
});
}
async run(msg, { query }) {
try {
const { body } = await request
.get('https://developer.mozilla.org/api/v1/search')
.query({
q: query,
locale: 'en-US',
highlight: false
});
if (!body.documents.length) return msg.say('Could not find any results.');
const data = body.documents[0];
const embed = new MessageEmbed()
.setColor(0x066FAD)
.setAuthor('MDN', 'https://i.imgur.com/DFGXabG.png', 'https://developer.mozilla.org/')
.setURL(`https://developer.mozilla.org${data.mdn_url}`)
.setTitle(data.title)
.setDescription(data.summary);
return msg.embed(embed);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-68
View File
@@ -1,68 +0,0 @@
const Command = require('../../framework/Command');
const moment = require('moment');
const { MessageEmbed } = require('discord.js');
const request = require('node-superfetch');
const { decode: decodeHTML } = require('html-entities');
const { formatNumber, embedURL } = require('../../util/Util');
const { STACKOVERFLOW_KEY } = process.env;
module.exports = class StackOverflowCommand extends Command {
constructor(client) {
super(client, {
name: 'stack-overflow',
group: 'code',
memberName: 'stack-overflow',
description: 'Searches Stack Overflow for your query.',
clientPermissions: ['EMBED_LINKS'],
credit: [
{
name: 'Stack Exchange',
url: 'https://stackexchange.com/',
reason: 'API',
reasonURL: 'https://api.stackexchange.com/docs'
}
],
args: [
{
key: 'query',
prompt: 'What question would you like to search for?',
type: 'string'
}
]
});
}
async run(msg, { query }) {
try {
const { body } = await request
.get('http://api.stackexchange.com/2.2/search/advanced')
.query({
page: 1,
pagesize: 1,
order: 'asc',
sort: 'relevance',
answers: 1,
q: query,
site: 'stackoverflow',
key: STACKOVERFLOW_KEY
});
if (!body.items.length) return msg.say('Could not find any results.');
const data = body.items[0];
const embed = new MessageEmbed()
.setColor(0xF48023)
.setAuthor('Stack Overflow', 'https://i.imgur.com/P2jAgE3.png', 'https://stackoverflow.com/')
.setURL(data.link)
.setTitle(decodeHTML(data.title))
.addField(' ID', data.question_id, true)
.addField(' Asker', embedURL(data.owner.display_name, data.owner.link), true)
.addField(' Views', formatNumber(data.view_count), true)
.addField(' Score', formatNumber(data.score), true)
.addField(' Creation Date', moment.utc(data.creation_date * 1000).format('MM/DD/YYYY h:mm A'), true)
.addField(' Last Activity',
moment.utc(data.last_activity_date * 1000).format('MM/DD/YYYY h:mm A'), true);
return msg.embed(embed);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
@@ -1,53 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const { list } = require('../../util/Util');
const products = require('../../assets/json/apple-engraving');
module.exports = class AppleEngravingCommand extends Command {
constructor(client) {
super(client, {
name: 'apple-engraving',
aliases: ['apple-engrave', 'apple-e', 'a-engrave', 'a-engraving'],
group: 'edit-image-text',
memberName: 'apple-engraving',
description: 'Engraves the text of your choice onto an Apple product.',
details: `**Products:** ${Object.keys(products).join(', ')}`,
credit: [
{
name: 'Apple',
url: 'https://www.apple.com/',
reason: 'API'
}
],
args: [
{
key: 'product',
prompt: `What product do you want to engrave? Either ${list(Object.keys(products), 'or')}.`,
type: 'string',
oneOf: Object.keys(products),
parse: product => product.toLowerCase()
},
{
key: 'text',
prompt: 'What text do you want to engrave?',
type: 'string'
}
]
});
}
async run(msg, { product, text }) {
try {
const { body } = await request
.get(`https://www.apple.com/shop/preview/engrave/${products[product]}/A`)
.query({
th: text,
s: 2,
f: 'font1'
});
return msg.say({ files: [{ attachment: body, name: 'apple-engraving.jpg' }] });
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
+1 -1
View File
@@ -54,6 +54,6 @@ module.exports = class CalendarCommand extends Command {
} }
} }
display += '|'; display += '|';
return msg.code(null, display); return msg.say(`\`\`\`\n${display}\n\`\`\``);
} }
}; };
-68
View File
@@ -1,68 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const { MessageEmbed } = require('discord.js');
const { formatNumber } = require('../../util/Util');
module.exports = class Covid19Command extends Command {
constructor(client) {
super(client, {
name: 'covid-19',
aliases: ['coronavirus', 'corona', 'covid'],
group: 'events',
memberName: 'covid-19',
description: 'Responds with stats for COVID-19.',
clientPermissions: ['EMBED_LINKS'],
credit: [
{
name: 'disease.sh',
url: 'https://disease.sh/',
reason: 'COVID-19 API',
reasonURL: 'https://disease.sh/docs/#/'
}
],
args: [
{
key: 'country',
prompt: 'What country do you want to get the stats for? Type `all` to get world stats.',
type: 'string',
default: 'all',
parse: country => encodeURIComponent(country)
}
]
});
}
async run(msg, { country }) {
try {
const data = await this.fetchStats(country);
const slug = country === 'all' ? null : data.country === 'USA' ? 'us' : data.country.toLowerCase();
const embed = new MessageEmbed()
.setColor(0xA2D84E)
.setAuthor('Worldometers', 'https://i.imgur.com/IoaBMuK.jpg', 'https://www.worldometers.info/coronavirus/')
.setTitle(`Stats for ${country === 'all' ? 'The World' : data.country}`)
.setURL(country === 'all'
? 'https://www.worldometers.info/coronavirus/'
: `https://www.worldometers.info/coronavirus/country/${encodeURIComponent(slug.replace(/ /g, '-'))}/`)
.setThumbnail(country === 'all' ? null : data.countryInfo.flag || null)
.setFooter('Last Updated')
.setTimestamp(data.updated)
.addField(' Total Cases', `${formatNumber(data.cases)} (${formatNumber(data.todayCases)} Today)`, true)
.addField(' Total Deaths', `${formatNumber(data.deaths)} (${formatNumber(data.todayDeaths)} Today)`, true)
.addField(' Total Recoveries',
`${formatNumber(data.recovered)} (${formatNumber(data.todayRecovered)} Today)`, true)
.addField(' Active Cases', formatNumber(data.active), true)
.addField(' Active Critical Cases', formatNumber(data.critical), true)
.addField(' Tests', formatNumber(data.tests), true);
return msg.embed(embed);
} catch (err) {
if (err.status === 404) return msg.say('Country not found or doesn\'t have any cases.');
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async fetchStats(country) {
const { body } = await request
.get(`https://disease.sh/v3/covid-19/${country === 'all' ? 'all' : `countries/${country}`}`);
return body;
}
};
-43
View File
@@ -1,43 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const { decode: decodeHTML } = require('html-entities');
const { MessageEmbed } = require('discord.js');
const { embedURL } = require('../../util/Util');
module.exports = class DoomsdayClockCommand extends Command {
constructor(client) {
super(client, {
name: 'doomsday-clock',
group: 'events',
memberName: 'doomsday-clock',
description: 'Responds with the current time of the Doomsday Clock.',
credit: [
{
name: 'Bulletin of the Atomic Scientists',
url: 'https://thebulletin.org/',
reason: 'Doomsday Clock Data',
reasonURL: 'https://thebulletin.org/doomsday-clock/current-time/'
}
]
});
}
async run(msg) {
try {
const { text } = await request.get('https://thebulletin.org/doomsday-clock/past-statements/');
const time = text.match(/<h3 class="uabb-infobox-title">(.+)<\/h3>/)[1];
const year = text.match(/<h5 class="uabb-infobox-title-prefix">(.+)<\/h5>/)[1];
const description = text.match(/<div class="uabb-infobox-text uabb-text-editor">(.|\n)+<p>(.+)<\/p>/)[2]
.replace(/<a href="(.+)" target="_blank" rel="noopener">(.+)<\/a>/, embedURL('$2', '$1'));
const embed = new MessageEmbed()
.setTitle(`${year}: ${time}`)
.setColor(0x000000)
.setURL('https://thebulletin.org/doomsday-clock/current-time/')
.setAuthor('Bulletin of the Atomic Scientists', undefined, 'https://thebulletin.org/')
.setDescription(decodeHTML(description));
return msg.embed(embed);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-26
View File
@@ -1,26 +0,0 @@
const Command = require('../../framework/Command');
module.exports = class FridayThe13thCommand extends Command {
constructor(client) {
super(client, {
name: 'friday-the-13th',
aliases: ['friday-13th', 'friday-13', 'friday-the-13', 'friday-the-thirteenth', 'friday-thirteenth'],
group: 'events',
memberName: 'friday-the-13th',
description: 'Determines if today is Friday the 13th.',
credit: [
{
name: 'r/IsTodayFridayThe13th',
url: 'https://www.reddit.com/r/IsTodayFridayThe13th/',
reason: 'Concept'
}
]
});
}
run(msg) {
const today = new Date();
const isFridaythe13th = today.getDay() === 5 && today.getDate() === 13;
return msg.say(`Today **is${isFridaythe13th ? '' : ' not'}** Friday the 13th.`);
}
};
-74
View File
@@ -1,74 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const { list, today, tomorrow } = require('../../util/Util');
const { GOOGLE_KEY, PERSONAL_GOOGLE_CALENDAR_ID } = process.env;
const holidayCals = {
USA: 'en.usa#holiday@group.v.calendar.google.com',
Japan: 'en.japanese#holiday@group.v.calendar.google.com',
UK: 'en.uk#holiday@group.v.calendar.google.com',
Australia: 'en.australian#holiday@group.v.calendar.google.com',
Canada: 'en.canadian#holiday@group.v.calendar.google.com'
};
module.exports = class HolidaysCommand extends Command {
constructor(client) {
super(client, {
name: 'holidays',
aliases: ['events', 'google-calendar'],
group: 'events',
memberName: 'holidays',
description: 'Responds with today\'s holidays.',
credit: [
{
name: 'Google',
url: 'https://www.google.com/',
reason: 'Calendar API',
reasonURL: 'https://developers.google.com/calendar/'
}
]
});
}
async run(msg) {
try {
const events = [];
for (const [country, calID] of Object.entries(holidayCals)) {
const standardEvents = await this.fetchHolidays(calID);
if (standardEvents) {
const mapped = standardEvents.map(event => `${event} (${country})`);
events.push(...mapped);
}
}
if (PERSONAL_GOOGLE_CALENDAR_ID) {
const personalEvents = await this.fetchHolidays(PERSONAL_GOOGLE_CALENDAR_ID);
if (personalEvents) events.push(...personalEvents);
}
if (!events.length) return msg.say('There are no holidays today...');
const holidays = list(events.map(event => `**${event}**`));
return msg.say(`Today${events.length === 1 ? ' is' : `'s holidays are`} ${holidays}!`);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async fetchHolidays(id) {
try {
const { body } = await request
.get(`https://www.googleapis.com/calendar/v3/calendars/${encodeURIComponent(id)}/events`)
.query({
maxResults: 20,
orderBy: 'startTime',
singleEvents: true,
timeMax: tomorrow().toISOString(),
timeMin: today().toISOString(),
timeZone: 'UTC',
key: GOOGLE_KEY
});
if (!body.items.length) return null;
return body.items.map(holiday => holiday.summary);
} catch (err) {
if (err.status === 404) return null;
throw err;
}
}
};
-44
View File
@@ -1,44 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const { stripIndents } = require('common-tags');
module.exports = class HumbleBundleCommand extends Command {
constructor(client) {
super(client, {
name: 'humble-bundle',
aliases: ['humble'],
group: 'events',
memberName: 'humble-bundle',
description: 'Responds with the current Humble Bundle.',
credit: [
{
name: 'Humble Bundle',
url: 'https://www.humblebundle.com/',
reason: 'API',
reasonURL: 'https://www.humblebundle.com/developer'
}
]
});
}
async run(msg) {
try {
const { text } = await request.get('https://www.humblebundle.com/androidapp/v2/service_check');
const body = JSON.parse(text);
if (!body.length) return msg.say('There is no bundle right now...');
if (body.length > 1) {
return msg.say(stripIndents`
There are **${body.length}** bundles on right now!
${body.map(bundle => `**${bundle.bundle_name}:** <${bundle.url}>`).join('\n')}
`);
}
const data = body[0];
return msg.say(stripIndents`
The current bundle is **${data.bundle_name}**!
${data.url}
`);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-32
View File
@@ -1,32 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
module.exports = class IssCommand extends Command {
constructor(client) {
super(client, {
name: 'iss',
aliases: ['international-space-station'],
group: 'events',
memberName: 'iss',
description: 'Responds with where the Internation Space Station currently is.',
credit: [
{
name: 'Open Notify',
url: 'http://open-notify.org/',
reason: 'ISS Current Location API',
reasonURL: 'http://open-notify.org/Open-Notify-API/ISS-Location-Now/'
}
]
});
}
async run(msg) {
try {
const { body } = await request.get('http://api.open-notify.org/iss-now.json');
const position = body.iss_position;
return msg.say(`The ISS is currently at **${position.latitude}, ${position.longitude}**.`);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-44
View File
@@ -1,44 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const { MessageEmbed } = require('discord.js');
module.exports = class PeopleInSpaceCommand extends Command {
constructor(client) {
super(client, {
name: 'people-in-space',
aliases: ['space', 'spacemen', 'astronauts', 'spacewomen'],
group: 'events',
memberName: 'people-in-space',
description: 'Responds with the people currently in space.',
clientPermissions: ['EMBED_LINKS'],
credit: [
{
name: 'Open Notify',
url: 'http://open-notify.org/',
reason: 'People in Space API',
reasonURL: 'http://open-notify.org/Open-Notify-API/People-In-Space/'
}
]
});
}
async run(msg) {
try {
const { body } = await request.get('http://api.open-notify.org/astros.json');
const crafts = {};
for (const person of body.people) {
if (crafts[person.craft]) crafts[person.craft].push(person.name);
else crafts[person.craft] = [person.name];
}
const embed = new MessageEmbed()
.setColor(0x2E528E)
.setImage('https://i.imgur.com/m3ooNfl.jpg');
for (const [craft, people] of Object.entries(crafts)) {
embed.addField(` ${craft} (${people.length})`, people.join('\n'), true);
}
return msg.say(`There are currently **${body.number}** people in space!`, embed);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-60
View File
@@ -1,60 +0,0 @@
const Command = require('../../framework/Command');
const { MessageEmbed } = require('discord.js');
const request = require('node-superfetch');
const moment = require('moment');
const { embedURL, formatNumber } = require('../../util/Util');
module.exports = class BotCommand extends Command {
constructor(client) {
super(client, {
name: 'bot',
aliases: ['discord-bot', 'bot-info', 'discord-bot-info'],
group: 'info',
memberName: 'bot',
description: 'Responds with information on a Discord bot.',
clientPermissions: ['EMBED_LINKS'],
credit: [
{
name: 'Discord Bots',
url: 'https://discord.bots.gg/',
reason: 'API'
}
],
args: [
{
key: 'user',
prompt: 'What bot would you like to get information on?',
type: 'user'
}
]
});
}
async run(msg, { user }) {
if (!user.bot) return msg.say('This user is not a bot.');
try {
const { body } = await request.get(`https://discord.bots.gg/api/v1/bots/${user.id}`);
const avatar = body.avatarURL === '/img/bot_icon_placeholder.png'
? 'https://discord.bots.gg/img/bot_icon_placeholder.png'
: body.avatarURL;
const embed = new MessageEmbed()
.setColor(0x000001)
.setTitle(`${body.username} by ${body.owner.username}#${body.owner.discriminator}`)
.setDescription(body.shortDescription)
.setAuthor('Discord Bots', 'https://i.imgur.com/OhZCqVd.jpg', 'https://discord.bots.gg/')
.setThumbnail(avatar)
.setURL(`https://discord.bots.gg/bots/${user.id}`)
.setFooter(user.id)
.addField(' Prefix', body.prefix || '???', true)
.addField(' Library', body.libraryName || '???', true)
.addField(' Servers', body.guildCount ? formatNumber(body.guildCount) : '???', true)
.addField(' Invite', body.botInvite ? embedURL('Here', body.botInvite) : '???', true)
.addField(' Server', body.supportInvite ? embedURL('Here', body.supportInvite) : '???', true)
.addField(' Public List Date', moment.utc(body.addedDate).format('MM/DD/YYYY h:mm A'), true);
return msg.embed(embed);
} catch (err) {
if (err.status === 404) return msg.say('This bot is not publicly listed.');
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-45
View File
@@ -1,45 +0,0 @@
const Command = require('../../framework/Command');
const moment = require('moment');
const { MessageEmbed } = require('discord.js');
const types = {
dm: 'DM',
group: 'Group DM',
text: 'Text Channel',
voice: 'Voice Channel',
category: 'Category',
unknown: 'Unknown'
};
module.exports = class ChannelCommand extends Command {
constructor(client) {
super(client, {
name: 'channel',
aliases: ['channel-info'],
group: 'info',
memberName: 'channel',
description: 'Responds with detailed information on a channel.',
clientPermissions: ['EMBED_LINKS'],
args: [
{
key: 'channel',
prompt: 'Which channel would you like to get information on?',
type: 'channel',
default: msg => msg.channel
}
]
});
}
run(msg, { channel }) {
const embed = new MessageEmbed()
.setColor(0x00AE86)
.addField(' Name', channel.type === 'dm' ? `@${channel.recipient.username}` : channel.name, true)
.addField(' ID', channel.id, true)
.addField(' NSFW', channel.nsfw ? 'Yes' : 'No', true)
.addField(' Category', channel.parent ? channel.parent.name : 'None', true)
.addField(' Type', types[channel.type], true)
.addField(' Creation Date', moment.utc(channel.createdAt).format('MM/DD/YYYY h:mm A'), true)
.addField(' Topic', channel.topic || 'None');
return msg.embed(embed);
}
};
-32
View File
@@ -1,32 +0,0 @@
const Command = require('../../framework/Command');
const { list } = require('../../util/Util');
const types = ['animated', 'regular'];
module.exports = class EmojiListCommand extends Command {
constructor(client) {
super(client, {
name: 'emoji-list',
aliases: ['emojis', 'emotes', 'emote-list'],
group: 'info',
memberName: 'emoji-list',
description: 'Responds with a list of the server\'s custom emoji.',
guildOnly: true,
args: [
{
key: 'type',
prompt: `What type of emoji would you like to view? Either ${list(types, 'or')}.`,
type: 'string',
default: 'regular',
oneOf: types,
parse: type => type.toLowerCase()
}
]
});
}
run(msg, { type }) {
const emojis = msg.guild.emojis.cache.filter(emoji => type === 'animated' ? emoji.animated : !emoji.animated);
if (!emojis.size) return msg.say(`This server has no ${type} custom emoji.`);
return msg.say(emojis.map(emoji => emoji.toString()).sort().join(' '), { split: { char: ' ' } });
}
};
-38
View File
@@ -1,38 +0,0 @@
const Command = require('../../framework/Command');
const moment = require('moment');
const { MessageEmbed } = require('discord.js');
module.exports = class EmojiCommand extends Command {
constructor(client) {
super(client, {
name: 'emoji',
aliases: ['emoji-info', 'emote'],
group: 'info',
memberName: 'emoji',
description: 'Responds with detailed information on an emoji.',
guildOnly: true,
clientPermissions: ['EMBED_LINKS', 'MANAGE_EMOJIS'],
args: [
{
key: 'emoji',
prompt: 'Which emoji would you like to get information on?',
type: 'custom-emoji'
}
]
});
}
async run(msg, { emoji }) {
if (!emoji.author && !emoji.managed) await emoji.fetchAuthor();
const embed = new MessageEmbed()
.setColor(0x00AE86)
.setThumbnail(emoji.url)
.addField(' Name', emoji.name, true)
.addField(' ID', emoji.id, true)
.addField(' Creation Date', moment.utc(emoji.createdAt).format('MM/DD/YYYY h:mm A'), true)
.addField(' Animated?', emoji.animated ? 'Yes' : 'No', true)
.addField(' External?', emoji.managed ? 'Yes' : 'No', true)
.addField(' Added By', emoji.author ? emoji.author.tag : '???', true);
return msg.embed(embed);
}
};
-25
View File
@@ -1,25 +0,0 @@
const Command = require('../../framework/Command');
module.exports = class IDCommand extends Command {
constructor(client) {
super(client, {
name: 'id',
aliases: ['user-id', 'member-id'],
group: 'info',
memberName: 'id',
description: 'Responds with a user\'s ID.',
args: [
{
key: 'user',
prompt: 'Which user do you want to get the ID of?',
type: 'user',
default: msg => msg.author
}
]
});
}
run(msg, { user }) {
return msg.reply(`${user.id === msg.author.id ? 'Your' : `${user.username}'s`} ID is ${user.id}.`);
}
};
-26
View File
@@ -1,26 +0,0 @@
const Command = require('../../framework/Command');
const { shorten } = require('../../util/Util');
module.exports = class MessageSourceCommand extends Command {
constructor(client) {
super(client, {
name: 'message-source',
aliases: ['msg-source', 'message-src', 'msg-src', 'source', 'src'],
group: 'info',
memberName: 'message-source',
description: 'Responds with a codeblock containing a message\'s contents.',
args: [
{
key: 'message',
prompt: 'Which message do you want to get the source of?',
type: 'message'
}
]
});
}
run(msg, { message }) {
if (!message.content) return msg.reply('That message has no content. Maybe it\'s an embed or image?');
return msg.code(null, shorten(message.content, 1990));
}
};
-36
View File
@@ -1,36 +0,0 @@
const Command = require('../../framework/Command');
const { MessageEmbed } = require('discord.js');
module.exports = class MessageCommand extends Command {
constructor(client) {
super(client, {
name: 'message',
aliases: ['message-info', 'msg', 'msg-info'],
group: 'info',
memberName: 'message',
description: 'Responds with detailed information on a message.',
clientPermissions: ['EMBED_LINKS'],
args: [
{
key: 'message',
prompt: 'Which message would you like to get information on?',
type: 'message'
}
]
});
}
run(msg, { message }) {
const hasImage = message.attachments.size && message.attachments.first().width;
const embed = new MessageEmbed()
.setColor(message.member ? message.member.displayHexColor : 0x00AE86)
.setThumbnail(message.author.displayAvatarURL({ format: 'png', dynamic: true }))
.setImage(hasImage ? message.attachments.first().url : null)
.setAuthor(message.author.tag, message.author.displayAvatarURL({ format: 'png', dynamic: true }))
.setDescription(message.content)
.setTimestamp(message.createdAt)
.setFooter(`ID: ${message.id}`)
.addField(' Jump', `[Click Here to Jump](${message.url})`);
return msg.embed(embed);
}
};
-40
View File
@@ -1,40 +0,0 @@
const Command = require('../../framework/Command');
const moment = require('moment');
const { MessageEmbed } = require('discord.js');
const permissions = require('../../assets/json/permission-names');
module.exports = class RoleCommand extends Command {
constructor(client) {
super(client, {
name: 'role',
aliases: ['role-info'],
group: 'info',
memberName: 'role',
description: 'Responds with detailed information on a role.',
guildOnly: true,
clientPermissions: ['EMBED_LINKS'],
args: [
{
key: 'role',
prompt: 'Which role would you like to get information on?',
type: 'role'
}
]
});
}
run(msg, { role }) {
const serialized = role.permissions.serialize();
const perms = Object.keys(permissions).filter(perm => serialized[perm]);
const embed = new MessageEmbed()
.setColor(role.hexColor)
.addField(' Name', role.name, true)
.addField(' ID', role.id, true)
.addField(' Color', role.hexColor.toUpperCase(), true)
.addField(' Creation Date', moment.utc(role.createdAt).format('MM/DD/YYYY h:mm A'), true)
.addField(' Hoisted?', role.hoist ? 'Yes' : 'No', true)
.addField(' Mentionable?', role.mentionable ? 'Yes' : 'No', true)
.addField(' Permissions', perms.map(perm => permissions[perm]).join(', ') || 'None');
return msg.embed(embed);
}
};
-51
View File
@@ -1,51 +0,0 @@
const Command = require('../../framework/Command');
const moment = require('moment');
const { MessageEmbed } = require('discord.js');
const { formatNumber } = require('../../util/Util');
const filterLevels = {
DISABLED: 'Off',
MEMBERS_WITHOUT_ROLES: 'No Role',
ALL_MEMBERS: 'Everyone'
};
const verificationLevels = {
NONE: 'None',
LOW: 'Low',
MEDIUM: 'Medium',
HIGH: 'High',
VERY_HIGH: 'Highest'
};
module.exports = class ServerCommand extends Command {
constructor(client) {
super(client, {
name: 'server',
aliases: ['guild', 'server-info', 'guild-info'],
group: 'info',
memberName: 'server',
description: 'Responds with detailed information on the server.',
guildOnly: true,
clientPermissions: ['EMBED_LINKS']
});
}
async run(msg) {
const owner = await msg.guild.fetchOwner();
const embed = new MessageEmbed()
.setColor(0x00AE86)
.setThumbnail(msg.guild.iconURL({ format: 'png' }))
.addField(' Name', msg.guild.name, true)
.addField(' ID', msg.guild.id, true)
.addField(' Creation Date', moment.utc(msg.guild.createdAt).format('MM/DD/YYYY h:mm A'), true)
.addField(' Owner', owner.user.tag, true)
.addField(' Boost Count', formatNumber(msg.guild.premiumSubscriptionCount || 0), true)
.addField(' Boost Tier', msg.guild.premiumTier ? `Tier ${msg.guild.premiumTier}` : 'None', true)
.addField(' Region', msg.guild.region.toUpperCase(), true)
.addField(' Explicit Filter', filterLevels[msg.guild.explicitContentFilter], true)
.addField(' Verification Level', verificationLevels[msg.guild.verificationLevel], true)
.addField(' Members', formatNumber(msg.guild.memberCount), true)
.addField(' Roles', formatNumber(msg.guild.roles.cache.size), true)
.addField(' Channels',
formatNumber(msg.guild.channels.cache.filter(channel => channel.type !== 'category').size), true);
return msg.embed(embed);
}
};
-72
View File
@@ -1,72 +0,0 @@
const Command = require('../../framework/Command');
const moment = require('moment');
const { MessageEmbed } = require('discord.js');
const { trimArray } = require('../../util/Util');
const flags = {
DISCORD_EMPLOYEE: 'Discord Employee',
PARTNERED_SERVER_OWNER: 'Discord Partner',
BUGHUNTER_LEVEL_1: 'Bug Hunter (Level 1)',
BUGHUNTER_LEVEL_2: 'Bug Hunter (Level 2)',
HYPESQUAD_EVENTS: 'HypeSquad Events',
HOUSE_BRAVERY: 'House of Bravery',
HOUSE_BRILLIANCE: 'House of Brilliance',
HOUSE_BALANCE: 'House of Balance',
EARLY_SUPPORTER: 'Early Supporter',
TEAM_USER: 'Team User',
SYSTEM: 'System',
VERIFIED_BOT: 'Verified Bot',
EARLY_VERIFIED_BOT_DEVELOPER: 'Early Verified Bot Developer'
};
const deprecated = ['DISCORD_PARTNER', 'VERIFIED_DEVELOPER'];
module.exports = class UserCommand extends Command {
constructor(client) {
super(client, {
name: 'user',
aliases: ['user-info', 'member', 'member-info', 'profile', 'who-is', 'who'],
group: 'info',
memberName: 'user',
description: 'Responds with detailed information on a user.',
clientPermissions: ['EMBED_LINKS'],
args: [
{
key: 'user',
prompt: 'Which user would you like to get information on?',
type: 'user',
default: msg => msg.author
}
]
});
}
async run(msg, { user }) {
const userFlags = user.flags ? user.flags.toArray().filter(flag => !deprecated.includes(flag)) : [];
const embed = new MessageEmbed()
.setThumbnail(user.displayAvatarURL({ format: 'png', dynamic: true }))
.setAuthor(user.tag)
.addField(' Discord Join Date', moment.utc(user.createdAt).format('MM/DD/YYYY h:mm A'), true)
.addField(' ID', user.id, true)
.addField(' Bot?', user.bot ? 'Yes' : 'No', true)
.addField(' Flags', userFlags.length ? userFlags.map(flag => flags[flag]).join(', ') : 'None');
if (msg.guild) {
try {
const member = await msg.guild.members.fetch(user.id);
const defaultRole = msg.guild.roles.cache.get(msg.guild.id);
const roles = member.roles.cache
.filter(role => role.id !== defaultRole.id)
.sort((a, b) => b.position - a.position)
.map(role => role.name);
embed
.addField(' Server Join Date', moment.utc(member.joinedAt).format('MM/DD/YYYY h:mm A'), true)
.addField(' Highest Role',
member.roles.highest.id === defaultRole.id ? 'None' : member.roles.highest.name, true)
.addField(' Hoist Role', member.roles.hoist ? member.roles.hoist.name : 'None', true)
.addField(` Roles (${roles.length})`, roles.length ? trimArray(roles, 6).join(', ') : 'None')
.setColor(member.displayHexColor);
} catch {
embed.setFooter('Failed to resolve member, showing basic user information instead.');
}
}
return msg.embed(embed);
}
};
-49
View File
@@ -1,49 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const cheerio = require('cheerio');
module.exports = class AnimeFigureCommand extends Command {
constructor(client) {
super(client, {
name: 'anime-figure',
aliases: ['my-figure-collection', 'mfc', 'figure'],
group: 'search',
memberName: 'anime-figure',
description: 'Searches MyFigureCollection for your query.',
credit: [
{
name: 'MyFigureCollection.net',
url: 'https://myfigurecollection.net/',
reason: 'Figure Data'
}
],
args: [
{
key: 'query',
prompt: 'What figure would you like to search for?',
type: 'string'
}
]
});
}
async run(msg, { query }) {
try {
const location = await this.search(query);
if (!location) return msg.say('Could not find any results.');
return msg.say(location);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async search(query) {
const { text } = await request
.get('https://myfigurecollection.net/browse.v4.php')
.query({ keywords: query });
const $ = cheerio.load(text);
const location = $('span[class="item-icon"]').first().children().first().attr('href');
if (!location) return null;
return `https://myfigurecollection.net${location}`;
}
};
-61
View File
@@ -1,61 +0,0 @@
const Command = require('../../framework/Command');
const { MessageEmbed } = require('discord.js');
const request = require('node-superfetch');
const { shorten, formatNumber } = require('../../util/Util');
const { GOOGLE_KEY } = process.env;
module.exports = class BookCommand extends Command {
constructor(client) {
super(client, {
name: 'book',
aliases: ['google-book', 'google-books'],
group: 'search',
memberName: 'book',
description: 'Searches Google Books for a book.',
clientPermissions: ['EMBED_LINKS'],
credit: [
{
name: 'Google',
url: 'https://www.google.com/',
reason: 'Books API',
reasonURL: 'https://developers.google.com/books/'
}
],
args: [
{
key: 'query',
prompt: 'What book would you like to search for?',
type: 'string'
}
]
});
}
async run(msg, { query }) {
try {
const { body } = await request
.get('https://www.googleapis.com/books/v1/volumes')
.query({
apiKey: GOOGLE_KEY,
q: query,
maxResults: 1,
printType: 'books'
});
if (!body.items) return msg.say('Could not find any results.');
const data = body.items[0].volumeInfo;
const embed = new MessageEmbed()
.setColor(0x4285F4)
.setTitle(data.title)
.setURL(data.previewLink)
.setAuthor('Google Books', 'https://i.imgur.com/N3oHABo.png', 'https://books.google.com/')
.setDescription(data.description ? shorten(data.description) : 'No description available.')
.setThumbnail(data.imageLinks ? data.imageLinks.thumbnail : null)
.addField(' Authors', data.authors && data.authors.length ? data.authors.join(', ') : '???')
.addField(' Publish Date', data.publishedDate || '???', true)
.addField(' Page Count', data.pageCount ? formatNumber(data.pageCount) : '???', true);
return msg.embed(embed);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-68
View File
@@ -1,68 +0,0 @@
const Command = require('../../framework/Command');
const { MessageEmbed } = require('discord.js');
const request = require('node-superfetch');
const { CLEARBIT_KEY } = process.env;
const dragonFireAliases = ['dragonfire535', 'dragon fire', 'dragonfire'];
module.exports = class CompanyCommand extends Command {
constructor(client) {
super(client, {
name: 'company',
aliases: ['clearbit', 'logo', 'company-logo'],
group: 'search',
memberName: 'company',
description: 'Responds with the name and logo of a company.',
credit: [
{
name: 'Clearbit',
url: 'https://clearbit.com/',
reason: 'Autocomplete API',
reasonURL: 'https://dashboard.clearbit.com/docs#autocomplete-api'
}
],
args: [
{
key: 'query',
prompt: 'What company would you like to search for?',
type: 'string'
}
]
});
}
async run(msg, { query }) {
try {
const data = await this.fetchCompany(query);
if (!data) return msg.say('Could not find any results.');
if (!msg.channel.nsfw && this.client.adultSiteList.includes(data.domain)) {
return msg.reply('This site is NSFW.');
}
const embed = new MessageEmbed()
.setTitle(data.name)
.setImage(data.logo)
.setFooter(data.dragonFire ? 'Logo by MissPeahen' : 'Logos provided by Clearbit')
.setURL(data.domain ? `https://${data.domain}` : null)
.setColor(0x00AE86);
return msg.embed(embed);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async fetchCompany(query) {
if (dragonFireAliases.includes(query.toLowerCase())) {
return {
name: 'Dragon Fire',
logo: 'https://i.imgur.com/tHxWaoA.png',
domain: null,
dragonFire: true
};
}
const { body } = await request
.get(`https://autocomplete.clearbit.com/v1/companies/suggest`)
.query({ query })
.set({ Authorization: `Bearer ${CLEARBIT_KEY}` });
if (!body.length) return null;
return body[0];
}
};
-60
View File
@@ -1,60 +0,0 @@
const Command = require('../../framework/Command');
const { MessageEmbed } = require('discord.js');
const request = require('node-superfetch');
const { formatNumber } = require('../../util/Util');
module.exports = class CountryCommand extends Command {
constructor(client) {
super(client, {
name: 'country',
group: 'search',
memberName: 'country',
description: 'Responds with information on a country.',
clientPermissions: ['EMBED_LINKS'],
credit: [
{
name: 'Rest Countries',
url: 'https://restcountries.eu/',
reason: 'API'
}
],
args: [
{
key: 'query',
prompt: 'What country would you like to search for?',
type: 'string'
}
]
});
}
async run(msg, { query }) {
try {
const { body } = await request.get(`https://restcountries.eu/rest/v2/name/${encodeURIComponent(query)}`);
const data = body.find(country => {
const search = query.toLowerCase();
return country.name.toLowerCase() === search
|| country.altSpellings.some(alt => alt.toLowerCase() === search)
|| country.alpha2Code.toLowerCase() === search
|| country.alpha3Code.toLowerCase() === search
|| country.nativeName.toLowerCase() === search;
}) || body[0];
const embed = new MessageEmbed()
.setColor(0x00AE86)
.setTitle(data.name)
.setThumbnail(`https://www.countryflags.io/${data.alpha2Code}/flat/64.png`)
.addField(' Population', formatNumber(data.population), true)
.addField(' Capital', data.capital || 'None', true)
.addField(' Currency', data.currencies[0].symbol, true)
.addField(' Location', data.subregion || data.region, true)
.addField(' Demonym', data.demonym || 'None', true)
.addField(' Native Name', data.nativeName, true)
.addField(' Area', `${formatNumber(data.area)}km`, true)
.addField(' Languages', data.languages.map(lang => lang.name).join('/'));
return msg.embed(embed);
} catch (err) {
if (err.status === 404) return msg.say('Could not find any results.');
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-49
View File
@@ -1,49 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
module.exports = class DanbooruCommand extends Command {
constructor(client) {
super(client, {
name: 'danbooru',
aliases: ['booru'],
group: 'search',
memberName: 'danbooru',
description: 'Responds with an image from Danbooru, with optional query.',
nsfw: true,
credit: [
{
name: 'Danbooru',
url: 'https://danbooru.donmai.us/',
reason: 'API'
}
],
args: [
{
key: 'query',
prompt: 'What image would you like to search for?',
type: 'string',
default: '',
validate: query => {
if (!query.includes(' ')) return true;
return 'Invalid query, please only search for one tag at a time.';
}
}
]
});
}
async run(msg, { query }) {
try {
const { body } = await request
.get('https://danbooru.donmai.us/posts.json')
.query({
tags: `${query} order:random`,
limit: 1
});
if (!body.length || !body[0].file_url) return msg.say('Could not find any results.');
return msg.say(body[0].file_url);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-61
View File
@@ -1,61 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
module.exports = class DerpibooruCommand extends Command {
constructor(client) {
super(client, {
name: 'derpibooru',
aliases: ['derpi'],
group: 'search',
memberName: 'derpibooru',
description: 'Responds with an image from Derpibooru.',
credit: [
{
name: 'Hasbro',
url: 'https://shop.hasbro.com/en-us',
reason: 'Original "My Little Pony: Friendship is Magic" Show',
reasonURL: 'https://mylittlepony.hasbro.com/en-us'
},
{
name: 'Derpibooru',
url: 'https://derpibooru.org/',
reason: 'API',
reasonURL: 'https://www.derpibooru.org/pages/api'
}
],
args: [
{
key: 'query',
prompt: 'What image would you like to search for?',
type: 'string'
}
]
});
}
async run(msg, { query }) {
try {
const url = await this.search(query, msg.channel.nsfw || false);
if (!url) return msg.say('Could not find any results.');
if (url === 'nsfw') return msg.say('The image I found was NSFW, and this isn\'t the channel for that.');
return msg.say(url);
} catch (err) {
if (err.status === 404) return msg.say('Could not find any results.');
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async search(query, nsfw) {
const { body } = await request
.get('https://derpibooru.org/api/v1/json/search')
.query({
q: query,
per_page: 1,
sf: 'random'
});
if (!body || !body.images || !body.images.length) return null;
const image = body.images[0];
if (!image.tags.includes('safe') && !nsfw) return 'nsfw';
return image.representations.full;
}
};
-68
View File
@@ -1,68 +0,0 @@
const Command = require('../../framework/Command');
const { MessageEmbed } = require('discord.js');
const request = require('node-superfetch');
const path = require('path');
const { decode: decodeHTML } = require('html-entities');
module.exports = class EsrbCommand extends Command {
constructor(client) {
super(client, {
name: 'esrb',
aliases: ['game-rating'],
group: 'search',
memberName: 'esrb',
description: 'Searches ESRB for your query.',
clientPermissions: ['EMBED_LINKS'],
credit: [
{
name: 'ESRB',
url: 'https://www.esrb.org/',
reason: 'API'
}
],
args: [
{
key: 'query',
prompt: 'What game would you like to search for?',
type: 'string'
}
]
});
}
async run(msg, { query }) {
try {
const data = await this.search(query);
if (!data) return msg.say('Could not find any results.');
const ratingFile = path.join(__dirname, '..', '..', 'assets', 'images', 'esrb', `${data.rating}.png`);
const embed = new MessageEmbed()
.attachFiles([{ attachment: ratingFile, name: 'rating.png' }])
.setColor(0x1C8CDE)
.setTitle(`${decodeHTML(data.title)} by ${decodeHTML(data.company)}`)
.setDescription(data.descriptors || 'No Descriptors')
.setAuthor('ESRB', 'https://i.imgur.com/29U6Bax.jpg', 'https://www.esrb.org/')
.setThumbnail('attachment://rating.png')
.setURL(`https://www.esrb.org/ratings/${data.certificate}/`);
return msg.embed(embed);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async search(query) {
const { text } = await request
.post('https://www.esrb.org/wp-admin/admin-ajax.php')
.attach({
action: 'search_rating',
'args[searchKeyword]': query,
'args[searchType]': 'All',
'args[pg]': 1,
'args[platform][]': 'All Platforms',
'args[rating][]': 'E,E10+,T,M,AO',
'args[descriptor]': 'All Content'
});
const body = JSON.parse(text);
if (!body.games.length) return null;
return body.games.find(game => game.title.toLowerCase() === query.toLowerCase()) || body.games[0];
}
};
-59
View File
@@ -1,59 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const { isImageNSFW } = require('../../util/Util');
const { FLICKR_KEY } = process.env;
module.exports = class FlickrCommand extends Command {
constructor(client) {
super(client, {
name: 'flickr',
group: 'search',
memberName: 'flickr',
description: 'Searches Flickr for your query.',
throttling: {
usages: 2,
duration: 30
},
credit: [
{
name: 'Flickr',
url: 'https://www.flickr.com/',
reason: 'API',
reasonURL: 'https://www.flickr.com/services/api/'
}
],
args: [
{
key: 'query',
prompt: 'What photo would you like to search for?',
type: 'string'
}
]
});
}
async run(msg, { query }) {
try {
const { body } = await request
.get('https://api.flickr.com/services/rest/')
.query({
api_key: FLICKR_KEY,
format: 'json',
method: 'flickr.photos.search',
text: query,
nojsoncallback: true
});
if (!body.photos.photo.length) return msg.say('Could not find any results.');
const data = body.photos.photo[Math.floor(Math.random() * body.photos.photo.length)];
const url = `https://farm${data.farm}.staticflickr.com/${data.server}/${data.id}_${data.secret}.jpg`;
if (!msg.channel.nsfw) {
const { body: imageBody } = await request.get(url);
const aiDetect = await isImageNSFW(this.client.nsfwModel, imageBody);
if (aiDetect) return msg.reply('Found an NSFW image. Sorry, please try again.');
}
return msg.say(url);
} catch (err) {
return msg.say(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-78
View File
@@ -1,78 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const cheerio = require('cheerio');
const { URLSearchParams, URL } = require('url');
module.exports = class GoogleCommand extends Command {
constructor(client) {
super(client, {
name: 'google',
aliases: ['search'],
group: 'search',
memberName: 'google',
description: 'Searches Google for your query.',
credit: [
{
name: 'Google',
url: 'https://www.google.com/',
reason: 'Search'
},
{
name: 'LMGTFY',
url: 'https://lmgtfy.com/',
reason: 'API'
}
],
args: [
{
key: 'query',
prompt: 'What would you like to search for?',
type: 'string',
validate: query => {
if (encodeURIComponent(query).length < 1950) return true;
return 'Invalid query, your query is too long.';
}
}
]
});
}
async run(msg, { query }) {
let hrefs;
try {
hrefs = await this.search(query, msg.channel.nsfw || false);
} catch {
hrefs = [{ href: `http://lmgtfy.com/?iie=1&q=${encodeURIComponent(query)}`, title: 'LMGTFY' }];
}
if (!hrefs) return msg.say('Could not find any results.');
return msg.say(hrefs.map(href => `${href.title}\n<${href.href}>`).join('\n\n'));
}
async search(query, nsfw) {
const { text } = await request
.get('https://www.google.com/search')
.query({
safe: nsfw ? 'images' : 'active',
pws: 0,
filter: 0,
q: query
})
.set({ 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1' });
const $ = cheerio.load(text);
const links = [];
$('body').find('h3').each((i, h3) => {
if ($(h3).parent()) {
const href = $(h3).parent().attr('href');
if (href) {
const params = new URLSearchParams(href);
const url = new URL(params.get('url'));
if (nsfw || !this.client.adultSiteList.includes(url.host)) {
links.push({ href: url.href, title: $(h3).text() });
}
}
}
});
if (!links.length) return null;
return links.slice(0, 3);
}
};
-38
View File
@@ -1,38 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
module.exports = class HttpDogCommand extends Command {
constructor(client) {
super(client, {
name: 'http-dog',
group: 'search',
memberName: 'http-dog',
description: 'Responds with a dog for an HTTP status code.',
clientPermissions: ['ATTACH_FILES'],
credit: [
{
name: 'HTTP Status Dogs',
url: 'https://httpstatusdogs.com/',
reason: 'API'
}
],
args: [
{
key: 'code',
prompt: 'What code do you want to get the dog of?',
type: 'integer'
}
]
});
}
async run(msg, { code }) {
try {
const { body, headers } = await request.get(`https://httpstatusdogs.com/img/${code}.jpg`);
if (headers['content-type'].includes('text/html')) return msg.say('Could not find any results.');
return msg.say({ files: [{ attachment: body, name: `${code}.jpg` }] });
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-39
View File
@@ -1,39 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
module.exports = class HttpDuckCommand extends Command {
constructor(client) {
super(client, {
name: 'http-duck',
group: 'search',
memberName: 'http-duck',
description: 'Responds with a duck for an HTTP status code.',
clientPermissions: ['ATTACH_FILES'],
credit: [
{
name: 'Random-d.uk',
url: 'https://random-d.uk/',
reason: 'API',
reasonURL: 'https://random-d.uk/http'
}
],
args: [
{
key: 'code',
prompt: 'What code do you want to get the duck of?',
type: 'integer'
}
]
});
}
async run(msg, { code }) {
try {
const { body } = await request.get(`https://random-d.uk/api/http/${code}.jpg`);
return msg.say({ files: [{ attachment: body, name: `${code}.jpg` }] });
} catch (err) {
if (err.status === 404) return msg.say('Could not find any results.');
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-60
View File
@@ -1,60 +0,0 @@
const Command = require('../../framework/Command');
const moment = require('moment');
const { MessageEmbed } = require('discord.js');
const request = require('node-superfetch');
const { shorten, formatNumber } = require('../../util/Util');
module.exports = class KickstarterCommand extends Command {
constructor(client) {
super(client, {
name: 'kickstarter',
group: 'search',
memberName: 'kickstarter',
description: 'Searches Kickstarter for your query.',
clientPermissions: ['EMBED_LINKS'],
credit: [
{
name: 'Kickstarter',
url: 'https://www.kickstarter.com/',
reason: 'API'
}
],
args: [
{
key: 'query',
prompt: 'What project would you like to search for?',
type: 'string'
}
]
});
}
async run(msg, { query }) {
try {
const { body } = await request
.get('https://www.kickstarter.com/projects/search.json')
.query({
search: '',
term: query
});
if (!body.projects.length) return msg.say('Could not find any results.');
const data = body.projects[0];
const embed = new MessageEmbed()
.setColor(0x14E06E)
.setTitle(data.name)
.setURL(data.urls.web.project)
.setAuthor('Kickstarter', 'https://i.imgur.com/EHDlH5t.png', 'https://www.kickstarter.com/')
.setDescription(shorten(data.blurb))
.setThumbnail(data.photo ? data.photo.full : null)
.addField(' Goal', `$${formatNumber(data.goal)}`, true)
.addField(' Pledged', `$${formatNumber(data.pledged)}`, true)
.addField(' Backers', formatNumber(data.backers_count), true)
.addField(' Creator', data.creator.name, true)
.addField(' Creation Date', moment.utc(data.created_at * 1000).format('MM/DD/YYYY h:mm A'), true)
.addField(' Deadline', moment.utc(data.deadline * 1000).format('MM/DD/YYYY h:mm A'), true);
return msg.embed(embed);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-98
View File
@@ -1,98 +0,0 @@
const Command = require('../../framework/Command');
const { MessageEmbed } = require('discord.js');
const request = require('node-superfetch');
const buttons = ['Q', 'W', 'E', 'R'];
module.exports = class LeagueOfLegendsCommand extends Command {
constructor(client) {
super(client, {
name: 'league-of-legends',
aliases: ['league-of-legends-champion', 'league-of-legends-champ', 'league-champ', 'lol-champ'],
group: 'search',
memberName: 'league-of-legends',
description: 'Responds with information on a League of Legends champion.',
clientPermissions: ['EMBED_LINKS'],
credit: [
{
name: 'Riot Games',
url: 'https://www.riotgames.com/en',
reason: 'API',
reasonURL: 'https://developer.riotgames.com/'
}
],
args: [
{
key: 'champion',
prompt: 'What champion would you like to get information on?',
type: 'string',
parse: champion => champion.toLowerCase()
}
]
});
this.version = null;
this.champions = null;
}
async run(msg, { champion }) {
if (champion === 'satan') champion = 'teemo';
try {
if (!this.version) await this.fetchVersion();
const data = await this.fetchChampion(champion);
if (!data) return msg.say('Could not find any results.');
const tips = [].concat(data.allytips, data.enemytips);
const embed = new MessageEmbed()
.setColor(0x002366)
.setAuthor('League of Legends', 'https://i.imgur.com/2JL4Rko.png', 'https://leagueoflegends.com/')
.setTitle(`${data.name} ${data.title}`)
.setDescription(data.blurb)
.setThumbnail(`https://ddragon.leagueoflegends.com/cdn/${this.version}/img/champion/${data.image.full}`)
.addField(' Attack', data.info.attack, true)
.addField(' Defense', data.info.defense, true)
.addField(' Magic', data.info.magic, true)
.addField(' Difficulty', data.info.difficulty, true)
.addField(' HP', `${data.stats.hp} (${data.stats.hpperlevel}/level)`, true)
.addField(' HP Regen', `${data.stats.hpregen} (${data.stats.hpregenperlevel}/level)`, true)
.addField(' MP', `${data.stats.mp} (${data.stats.mpperlevel}/level)`, true)
.addField(' MP Regen', `${data.stats.mpregen} (${data.stats.mpregenperlevel}/level)`, true)
.addField(' Resource', data.partype, true)
.addField(' Armor', `${data.stats.armor} (${data.stats.armorperlevel}/level)`, true)
.addField(' Attack Damage', `${data.stats.attackdamage} (${data.stats.attackdamageperlevel}/level)`, true)
.addField(' Attack Range', data.stats.attackrange, true)
.addField(' Attack Speed', `${data.stats.attackspeed} (${data.stats.attackspeedperlevel}/level)`, true)
.addField(' Crit', `${data.stats.crit} (${data.stats.critperlevel}/level)`, true)
.addField(' Move Speed', data.stats.movespeed, true)
.addField(' Spell Block', `${data.stats.spellblock} (${data.stats.spellblockperlevel}/level)`, true)
.addField(' Passive', data.passive.name, true)
.addField(' Spells', data.spells.map((spell, i) => `${spell.name} (${buttons[i]})`).join('\n'), true);
return msg.say(`Tip: ${tips[Math.floor(Math.random() * tips.length)]}`, { embed });
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async fetchVersion() {
const { body } = await request.get('https://ddragon.leagueoflegends.com/api/versions.json');
[this.version] = body;
setTimeout(() => { this.version = null; }, 3.6e+6);
return body;
}
async fetchChampions() {
if (this.champions && this.champions.version === this.version) return this.champions;
const { body } = await request
.get(`https://ddragon.leagueoflegends.com/cdn/${this.version}/data/en_US/champion.json`);
this.champions = body;
return body;
}
async fetchChampion(champion) {
const champions = await this.fetchChampions();
const name = Object.keys(champions.data).find(key => key.toLowerCase() === champion);
if (!name) return null;
const { id } = champions.data[name];
const { body } = await request
.get(`https://ddragon.leagueoflegends.com/cdn/${this.version}/data/en_US/champion/${id}.json`);
return body.data[id];
}
};
-62
View File
@@ -1,62 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const { shorten } = require('../../util/Util');
// eslint-disable-next-line max-len
const top = '<!-- Usage of azlyrics.com content by any third-party lyrics provider is prohibited by our licensing agreement. Sorry about that. -->';
const bottom = '<!-- MxM banner -->';
const lyricRegex = new RegExp(`${top}(.+)${bottom}`, 'si');
module.exports = class LyricsCommand extends Command {
constructor(client) {
super(client, {
name: 'lyrics',
aliases: ['az-lyrics'],
group: 'search',
memberName: 'lyrics',
description: 'Responds with lyrics to a song.',
credit: [
{
name: 'AZLyrics',
url: 'https://www.azlyrics.com/',
reason: 'Lyrics Data'
}
],
args: [
{
key: 'artist',
prompt: 'What artist would you like to get the lyrics of?',
type: 'string',
parse: artist => artist.replace(/[^A-Za-z0-9]+|^(the )/gi, '').toLowerCase()
},
{
key: 'song',
prompt: 'What song would you like to get the lyrics of?',
type: 'string',
parse: song => song.replace(/[^A-Za-z0-9]+/g, '').toLowerCase()
}
]
});
}
async run(msg, { artist, song }) {
try {
const lyrics = await this.getLyrics(artist, song);
const url = `https://www.azlyrics.com/lyrics/${artist}/${song}.html`;
return msg.say(`${shorten(lyrics, 1750)}\n\n**Read the Rest:** ${url}`);
} catch (err) {
if (err.status === 404) return msg.say('Could not find any results.');
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async getLyrics(artist, song) {
const { text } = await request.get(`https://www.azlyrics.com/lyrics/${artist}/${song}.html`);
const lyrics = text.match(lyricRegex)[1];
return lyrics
.replaceAll('<br>', '')
.replace(/<\/?div>/g, '')
.replace(/<\/?i>/g, '*')
.replace(/<\/?b>/g, '**')
.trim();
}
};
-48
View File
@@ -1,48 +0,0 @@
const Command = require('../../framework/Command');
const { MessageEmbed } = require('discord.js');
const request = require('node-superfetch');
module.exports = class MalBadgesCommand extends Command {
constructor(client) {
super(client, {
name: 'mal-badges',
aliases: ['my-anime-list-badges', 'mal-badge', 'my-anime-list-badge'],
group: 'search',
memberName: 'mal-badges',
description: 'Responds with a MyAnimeList user\'s mal-badges badge.',
credit: [
{
name: 'mal-badges',
url: 'http://www.mal-badges.net/',
reason: 'API'
}
],
args: [
{
key: 'user',
prompt: 'What user would you like to get the badge of?',
type: 'string',
parse: user => encodeURIComponent(user)
}
]
});
}
async run(msg, { user }) {
try {
const { body } = await request.get(`http://www.mal-badges.net/users/${user}/badge`);
const embed = new MessageEmbed()
.attachFiles([{ attachment: body, name: 'badge.png' }])
.setTitle(user)
.setImage('attachment://badge.png')
.setURL(`http://www.mal-badges.net/users/${user}`)
.setColor(0x00ADB5);
return msg.embed(embed);
} catch (err) {
if (err.status === 404 || err.status === 500) {
return msg.say(`Could not find any results. Try updating at <http://www.mal-badges.net/users/${user}>.`);
}
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-60
View File
@@ -1,60 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const { GOOGLE_KEY } = process.env;
module.exports = class MapCommand extends Command {
constructor(client) {
super(client, {
name: 'map',
aliases: ['google-maps', 'google-map'],
group: 'search',
memberName: 'map',
description: 'Responds with a map of a specific location.',
clientPermissions: ['ATTACH_FILES'],
credit: [
{
name: 'Google',
url: 'https://www.google.com/',
reason: 'Maps Static API',
reasonURL: 'https://developers.google.com/maps/documentation/maps-static/intro'
}
],
args: [
{
key: 'zoom',
label: 'zoom level',
prompt: 'What would you like the zoom level to be? Must be a number from 1-20.',
type: 'integer',
min: 1,
max: 20
},
{
key: 'location',
prompt: 'What location would you like to get a map of?',
type: 'string',
validate: location => {
if (encodeURIComponent(location).length < 1950) return true;
return 'Invalid location, your location is too long.';
}
}
]
});
}
async run(msg, { zoom, location }) {
try {
const { body } = await request
.get('https://maps.googleapis.com/maps/api/staticmap')
.query({
center: location,
zoom,
size: '500x500',
key: GOOGLE_KEY
});
const url = `https://www.google.com/maps/search/${encodeURIComponent(location)}`;
return msg.say(`<${url}>`, { files: [{ attachment: body, name: 'map.png' }] });
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-75
View File
@@ -1,75 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const cheerio = require('cheerio');
const { MessageEmbed } = require('discord.js');
const { shorten } = require('../../util/Util');
module.exports = class MayoClinicCommand extends Command {
constructor(client) {
super(client, {
name: 'mayo-clinic',
aliases: ['disease'],
group: 'search',
memberName: 'mayo-clinic',
description: 'Searches Mayo Clinic for your query.',
clientPermissions: ['EMBED_LINKS'],
credit: [
{
name: 'Mayo Clinic',
url: 'https://www.mayoclinic.org/',
reason: 'Disease Data'
}
],
args: [
{
key: 'query',
prompt: 'What disease would you like to search for?',
type: 'string'
}
]
});
}
async run(msg, { query }) {
try {
const location = await this.search(query);
if (!location) return msg.say('Could not find any results.');
const data = await this.fetchDisease(location);
if (typeof data === 'string') return msg.say(`I found a match, but it's not a disease: ${data}`);
const embed = new MessageEmbed()
.setColor(0x0044B3)
.setAuthor('Mayo Clinic', 'https://i.imgur.com/9zdulOS.jpg', 'https://www.mayoclinic.org/')
.setTitle(data.name)
.setDescription(shorten(data.description || 'No description available.'))
.setURL(data.url);
return msg.embed(embed);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async search(query) {
const { text } = await request
.get('https://www.mayoclinic.org/search/search-results')
.query({ q: query });
const $ = cheerio.load(text);
const location = $('ol.navlist').find('li.noimg').first().children().find('a').attr('href');
if (!location) return null;
return location;
}
async fetchDisease(location) {
const { text } = await request.get(location);
const $ = cheerio.load(text);
const header = $('h2').first();
if (header.text() === 'Overview') {
const caption = $('p[class="caption"]').first().next().text().trim();
return {
name: $('h1').first().text().trim(),
url: location,
description: caption || header.next().text().trim()
};
}
return location;
}
};
-107
View File
@@ -1,107 +0,0 @@
const Command = require('../../framework/Command');
const { MessageEmbed } = require('discord.js');
const request = require('node-superfetch');
const moment = require('moment');
const { formatNumber } = require('../../util/Util');
const classStats = require('../../assets/json/paladins');
const { FLANKER_EMOJI_ID, DAMAGE_EMOJI_ID, FRONT_LINE_EMOJI_ID, SUPPORT_EMOJI_ID } = process.env;
module.exports = class PaladinsCommand extends Command {
constructor(client) {
super(client, {
name: 'paladins',
aliases: ['paladins-guru'],
group: 'search',
memberName: 'paladins',
description: 'Responds with information on a Paladins player.',
clientPermissions: ['EMBED_LINKS'],
credit: [
{
name: 'Evil Mojo Games',
url: 'https://www.evilmojogames.com/',
reason: 'Original "Paladins" Game',
reasonURL: 'https://www.paladins.com/'
},
{
name: 'PaladinsGuru',
url: 'https://paladins.guru/',
reason: 'API'
}
],
args: [
{
key: 'player',
prompt: 'What player would you like to get information on?',
type: 'string'
}
]
});
this.champions = null;
}
async run(msg, { player }) {
try {
const search = await this.search(player);
if (!search) return msg.say('Could not find any results.');
const data = await this.fetchPlayer(search.id);
if (!this.champions) await this.fetchChampions();
const champions = data.champions.map(champ => {
const champData = this.champions[champ.id];
const classStat = classStats[champData.class];
const emoji = this.classEmoji(champData.class);
return `${emoji} ${champData.name} (${formatNumber(champ[classStat.id] || 0)} ${classStat.display})`;
});
const embed = new MessageEmbed()
.setColor(0x1E9BAD)
.setAuthor('Paladins Guru', 'https://i.imgur.com/iIAdriK.png', 'https://paladins.guru/')
.setTitle('View Profile on Paladins Guru')
.setURL(`https://paladins.guru/profile/${data.player.id}`)
.addField(' Name', data.player.name, true)
.addField(' ID', data.player.id, true)
.addField(' Level', data.player.level, true)
.addField(' Last Seen', moment.utc(data.player.seen).format('MM/DD/YYYY h:mm A'), true)
.addField(' Region', data.player.region, true)
.addField(' Team', data.player.team || 'Free Agent', true)
.addField(' Top 5 Champions', champions.slice(0, 5).join('\n'));
return msg.embed(embed);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async search(query) {
const { body } = await request
.get('https://api.paladins.guru/v3/search')
.query({
term: query,
type: 'Player'
});
if (!body.length) return null;
return body[0];
}
async fetchPlayer(id) {
const { body } = await request.get(`https://api.paladins.guru/v3/profiles/${id}/summary`);
return body;
}
async fetchChampions() {
if (this.champions) return this.champions;
const { body } = await request.get('https://api.paladins.guru/v3/champions/');
this.champions = body;
setTimeout(() => { this.champions = null; }, 3.6e+6);
return body;
}
classEmoji(className) {
let emojiID;
switch (className) {
case 'Flanker': emojiID = FLANKER_EMOJI_ID; break;
case 'Support': emojiID = SUPPORT_EMOJI_ID; break;
case 'Damage': emojiID = DAMAGE_EMOJI_ID; break;
case 'Front Line': emojiID = FRONT_LINE_EMOJI_ID; break;
}
return `<:${className.replaceAll(' ', '')}:${emojiID}>`;
}
};
-53
View File
@@ -1,53 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const { html } = require('common-tags');
const { shorten } = require('../../util/Util');
module.exports = class PoemCommand extends Command {
constructor(client) {
super(client, {
name: 'poem',
aliases: ['poetry'],
group: 'search',
memberName: 'poem',
description: 'Searches for poems by a specific author.',
credit: [
{
name: 'PoetryDB',
url: 'https://poetrydb.org/index.html',
reason: 'API',
reasonURL: 'https://github.com/thundercomb/poetrydb/blob/master/README.md'
}
],
args: [
{
key: 'author',
prompt: 'What author would you like to get a poem from?',
type: 'string',
parse: author => encodeURIComponent(author)
},
{
key: 'title',
prompt: 'What is the title of the poem you want to get?',
type: 'string',
parse: title => encodeURIComponent(title)
}
]
});
}
async run(msg, { author, title }) {
try {
const { body } = await request.get(`https://poetrydb.org/author,title/${author};${title}`);
if (body.status === 404) return msg.say('Could not find any results.');
const data = body[0];
return msg.say(html`
**${data.title}** by **${data.author}**
${shorten(data.lines.join('\n'), 1750)}
`);
} catch (err) {
if (err.status === 404) return msg.say('Could not find any results.');
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-49
View File
@@ -1,49 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const cheerio = require('cheerio');
module.exports = class PornhubCommand extends Command {
constructor(client) {
super(client, {
name: 'pornhub',
group: 'search',
memberName: 'pornhub',
description: 'Searches Pornhub for your query.',
nsfw: true,
credit: [
{
name: 'Pornhub',
url: 'https://www.pornhub.com/',
reason: 'Video Data'
}
],
args: [
{
key: 'query',
prompt: 'What video would you like to search for?',
type: 'string'
}
]
});
}
async run(msg, { query }) {
try {
const url = await this.search(query);
if (!url) return msg.say('Could not find any results.');
return msg.say(url);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async search(query) {
const { text } = await request
.get(`https://www.pornhub.com/video/search`)
.query({ search: query });
if (text.includes('<div class="noResultsWrapper">')) return null;
const $ = cheerio.load(text);
const video = $('li[class="pcVideoListItem js-pop videoblock videoBox"]').eq(5);
return `https://www.pornhub.com/view_video.php?viewkey=${video.attr('data-video-vkey')}`;
}
};
-60
View File
@@ -1,60 +0,0 @@
const Command = require('../../framework/Command');
const { MessageEmbed } = require('discord.js');
const request = require('node-superfetch');
module.exports = class RecipeCommand extends Command {
constructor(client) {
super(client, {
name: 'recipe',
aliases: ['recipe-puppy'],
group: 'search',
memberName: 'recipe',
description: 'Searches for recipes based on your query.',
clientPermissions: ['EMBED_LINKS'],
credit: [
{
name: 'Recipe Puppy',
url: 'http://www.recipepuppy.com/',
reason: 'API',
reasonURL: 'http://www.recipepuppy.com/about/api/'
}
],
args: [
{
key: 'query',
prompt: 'What recipe would you like to search for?',
type: 'string'
}
]
});
}
async run(msg, { query }) {
try {
const body = await this.fetchRecipe(query);
if (!body.results.length) return msg.say('Could not find any results.');
const recipe = body.results[Math.floor(Math.random() * body.results.length)];
const embed = new MessageEmbed()
.setAuthor('Recipe Puppy', 'https://i.imgur.com/lT94snh.png', 'http://www.recipepuppy.com/')
.setColor(0xC20000)
.setURL(recipe.href)
.setTitle(recipe.title)
.setDescription(`**Ingredients:** ${recipe.ingredients}`)
.setThumbnail(recipe.thumbnail);
return msg.embed(embed);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async fetchRecipe(query) {
try {
const { text } = await request
.get('http://www.recipepuppy.com/api/')
.query({ q: query });
return JSON.parse(text);
} catch (err) {
return JSON.parse(err.text.split('<!DOCTYPE html')[0]);
}
}
};
-81
View File
@@ -1,81 +0,0 @@
const Command = require('../../framework/Command');
const { MessageEmbed } = require('discord.js');
const request = require('node-superfetch');
const { stripIndents } = require('common-tags');
const { shorten } = require('../../util/Util');
module.exports = class RightStufCommand extends Command {
constructor(client) {
super(client, {
name: 'right-stuf',
aliases: ['right-stuf-anime'],
group: 'search',
memberName: 'right-stuf',
description: 'Searches Right Stuf Anime for your query.',
clientPermissions: ['EMBED_LINKS'],
credit: [
{
name: 'Right Stuf Anime',
url: 'https://www.rightstufanime.com/',
reason: 'API'
}
],
args: [
{
key: 'query',
prompt: 'What product would you like to search for?',
type: 'string'
}
]
});
}
async run(msg, { query }) {
try {
const { body } = await request
.get('https://www.rightstufanime.com/api/items')
.query({
country: 'US',
currency: 'USD',
fieldset: 'search',
include: '',
language: 'en',
limit: 1,
pricelevel: 2,
q: query,
sort: 'relevance:asc',
custitem_rs_adult: Boolean(msg.channel.nsfw)
});
if (!body.items.length) return msg.say('Could not find any results.');
const data = body.items[0];
const embed = new MessageEmbed()
.setColor(0xEE3F3C)
.setTitle(data.storedisplayname)
.setURL(`https://www.rightstufanime.com/${data.urlcomponent}`)
.setAuthor('Right Stuf', 'https://i.imgur.com/CTB8Imp.jpg', 'https://www.rightstufanime.com/')
.setDescription(shorten(data.storedescription))
.setThumbnail(this.getImageURL(data))
.addField(' Price', stripIndents`
Retail Price: ${data.pricelevel1_formatted}
Non-Member Price: ${data.pricelevel5_formatted}
Member Price: ${data.pricelevel3_formatted}
`);
return msg.embed(embed);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
getImageURL(item) {
let found = null;
let current = item.itemimages_detail;
while (!found) {
if (current.primary) found = current.primary.url;
if (current.urls) found = current.urls[0].url;
const key = Object.keys(current)[0];
if (!key) break;
current = current[key];
}
return found;
}
};
-74
View File
@@ -1,74 +0,0 @@
const Command = require('../../framework/Command');
const { MessageEmbed } = require('discord.js');
const request = require('node-superfetch');
const UserAgent = require('user-agents');
const { shorten } = require('../../util/Util');
module.exports = class RottenTomatoesCommand extends Command {
constructor(client) {
super(client, {
name: 'rotten-tomatoes',
aliases: ['tomato-meter', 'r-tomatoes'],
group: 'search',
memberName: 'rotten-tomatoes',
description: 'Searches Rotten Tomatoes for your query.',
clientPermissions: ['EMBED_LINKS'],
credit: [
{
name: 'Rotten Tomatoes',
url: 'https://www.rottentomatoes.com/',
reason: 'API'
}
],
args: [
{
key: 'query',
prompt: 'What movie would you like to search for?',
type: 'string'
}
]
});
}
async run(msg, { query }) {
try {
const id = await this.search(query);
if (!id) return msg.say('Could not find any results.');
const data = await this.fetchMovie(id);
const criticScore = data.ratingSummary.allCritics;
const audienceScore = data.ratingSummary.audience;
const embed = new MessageEmbed()
.setColor(0xFFEC02)
.setTitle(`${data.title} (${data.year})`)
.setURL(`https://www.rottentomatoes.com${data.url}`)
.setAuthor('Rotten Tomatoes', 'https://i.imgur.com/Sru8mZ3.jpg', 'https://www.rottentomatoes.com/')
.setDescription(shorten(data.ratingSummary.consensus))
.setThumbnail(data.posters.original)
.addField(' Critic Score', criticScore.meterValue ? `${criticScore.meterValue}%` : '???', true)
.addField(' Audience Score', audienceScore.meterScore ? `${audienceScore.meterScore}%` : '???', true);
return msg.embed(embed);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async search(query) {
const { body } = await request
.get('https://www.rottentomatoes.com/api/private/v2.0/search/')
.query({
limit: 10,
q: query
})
.set({ 'User-Agent': new UserAgent().toString() });
if (!body.movies.length) return null;
const find = body.movies.find(m => m.name.toLowerCase() === query.toLowerCase()) || body.movies[0];
return find.url.replace('/m/', '');
}
async fetchMovie(id) {
const { text } = await request
.get(`https://www.rottentomatoes.com/api/private/v1.0/movies/${id}`)
.set({ 'User-Agent': new UserAgent().toString() });
return JSON.parse(text);
}
};
-49
View File
@@ -1,49 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
module.exports = class SafebooruCommand extends Command {
constructor(client) {
super(client, {
name: 'safebooru',
group: 'search',
memberName: 'safebooru',
description: 'Responds with an image from Safebooru, with optional query.',
credit: [
{
name: 'Safebooru',
url: 'https://safebooru.org/',
reason: 'API'
}
],
args: [
{
key: 'query',
prompt: 'What image would you like to search for?',
type: 'string',
default: ''
}
]
});
}
async run(msg, { query }) {
try {
const { text } = await request
.get('https://safebooru.org/index.php')
.query({
page: 'dapi',
s: 'post',
q: 'index',
json: 1,
tags: query,
limit: 200
});
if (!text) return msg.say('Could not find any results.');
const body = JSON.parse(text);
const data = body[Math.floor(Math.random() * body.length)];
return msg.say(`https://safebooru.org/images/${data.directory}/${data.image}`);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-54
View File
@@ -1,54 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const { stripIndents } = require('common-tags');
module.exports = class SakugabooruCommand extends Command {
constructor(client) {
super(client, {
name: 'sakugabooru',
aliases: ['sakuga'],
group: 'search',
memberName: 'sakugabooru',
description: 'Responds with an image from Sakugabooru, with optional query.',
credit: [
{
name: 'Sakugabooru',
url: 'https://www.sakugabooru.com/',
reason: 'API'
}
],
args: [
{
key: 'query',
prompt: 'What would you like to search for?',
type: 'string',
default: ''
}
]
});
}
async run(msg, { query }) {
try {
const { body } = await request
.get('https://www.sakugabooru.com/post.json')
.query({
tags: query,
limit: 100
});
if (!body.length) return msg.say('Could not find any results.');
const posts = body.filter(post => {
if (!msg.channel.nsfw && (post.rating === 'e' || post.rating === 'q')) return false;
return post.file_url;
});
if (!posts.length) return msg.say('Could not find any results.');
const post = posts[Math.floor(Math.random() * posts.length)];
return msg.say(stripIndents`
${post.tags}
${post.file_url}
`);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-94
View File
@@ -1,94 +0,0 @@
const Command = require('../../framework/Command');
const { MessageEmbed } = require('discord.js');
const request = require('node-superfetch');
const { formatNumber } = require('../../util/Util');
const { ALPHA_VANTAGE_KEY } = process.env;
module.exports = class StocksCommand extends Command {
constructor(client) {
super(client, {
name: 'stocks',
aliases: ['stock', 'alpha-vantage'],
group: 'search',
memberName: 'stocks',
description: 'Responds with the current stocks for a company.',
clientPermissions: ['EMBED_LINKS'],
credit: [
{
name: 'Alpha Vantage',
url: 'https://www.alphavantage.co/',
reason: 'API'
},
{
name: 'Yahoo',
url: 'https://www.yahoo.com/',
reason: 'Finance API'
}
],
args: [
{
key: 'query',
prompt: 'What company would you like to get the stocks of?',
type: 'string'
}
]
});
}
async run(msg, { query }) {
try {
const company = await this.search(query);
if (!company) return msg.say('Could not find any results.');
const stocks = await this.fetchStocks(company.symbol);
if (!stocks) return msg.say('Could not find any results.');
const embed = new MessageEmbed()
.setTitle(`Stocks for ${company.name} (${stocks.symbol.toUpperCase()})`)
.setColor(0x9797FF)
.setFooter('Last Updated')
.setTimestamp(stocks.lastRefresh)
.addField(' Open', `$${formatNumber(stocks.open)}`, true)
.addField(' Close', `$${formatNumber(stocks.close)}`, true)
.addField(' Volume', formatNumber(stocks.volume), true)
.addField(' High', `$${formatNumber(stocks.high)}`, true)
.addField(' Low', `$${formatNumber(stocks.low)}`, true)
.addField('\u200B', '\u200B', true);
return msg.embed(embed);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async search(query) {
const { body } = await request
.get('http://d.yimg.com/autoc.finance.yahoo.com/autoc')
.query({
query,
region: 1,
lang: 'en'
});
if (!body.ResultSet.Result.length) return null;
return body.ResultSet.Result[0];
}
async fetchStocks(symbol) {
const { body } = await request
.get('https://www.alphavantage.co/query')
.query({
function: 'TIME_SERIES_INTRADAY',
symbol,
interval: '1min',
apikey: ALPHA_VANTAGE_KEY
});
if (body['Error Message'] || !body['Time Series (1min)']) return null;
const data = Object.values(body['Time Series (1min)'])[0];
return {
symbol,
open: data['1. open'],
high: data['2. high'],
low: data['3. low'],
close: data['4. close'],
volume: data['5. volume'],
lastRefresh: new Date(body['Meta Data']['3. Last Refreshed'])
};
}
};
-73
View File
@@ -1,73 +0,0 @@
const Command = require('../../framework/Command');
const { MessageEmbed } = require('discord.js');
const request = require('node-superfetch');
const cheerio = require('cheerio');
const { formatNumber } = require('../../util/Util');
module.exports = class StrainCommand extends Command {
constructor(client) {
super(client, {
name: 'strain',
aliases: ['weed', 'marijuana', 'cannabis', 'leafly', 'marijuana-strain', 'weed-strain', 'cannabis-strain'],
group: 'search',
memberName: 'strain',
description: 'Responds with information on a cannabis strain.',
clientPermissions: ['EMBED_LINKS'],
credit: [
{
name: 'Leafly',
url: 'https://www.leafly.com/',
reason: 'API'
}
],
args: [
{
key: 'query',
prompt: 'What strain would you like to search for?',
type: 'string'
}
]
});
}
async run(msg, { query }) {
try {
const strain = await this.search(query);
if (!strain) return msg.say('Could not find any results.');
const effects = Object.values(strain.effects).sort((a, b) => b.score - a.score).slice(0, 3);
const embed = new MessageEmbed()
.setColor(0x017C6A)
.setAuthor('Leafly', 'https://i.imgur.com/KQ0ABhI.png', 'https://www.leafly.com/')
.setTitle(strain.name)
.setThumbnail(strain.nugImage || null)
.setDescription(strain.shortDescriptionPlain || 'No description.')
.setURL(`https://www.leafly.com/strains/${strain.slug}`)
.setFooter(strain.subtitle || 'No alternative names.')
.addField(' Effects', effects.map(effect => effect.name).join(', '))
.addField(' Phenotype', strain.phenotype, true)
.addField(' Rating', `${formatNumber(strain.averageRating)}`, true);
return msg.embed(embed);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async search(query) {
const { text } = await request
.get('https://www.leafly.com/search')
.query({
q: query,
searchCategory: 'strain'
});
const $ = cheerio.load(text);
const data = JSON.parse($('script[id="__NEXT_DATA__"]')[0].children[0].data)
.props
.initialProps
.pageProps
.componentProps
.searchProps
.strain;
if (!data.length) return null;
return data[0];
}
};
-47
View File
@@ -1,47 +0,0 @@
const Command = require('../../framework/Command');
const request = require('node-superfetch');
const { TENOR_KEY } = process.env;
module.exports = class TenorCommand extends Command {
constructor(client) {
super(client, {
name: 'tenor',
group: 'search',
memberName: 'tenor',
description: 'Searches Tenor for your query.',
credit: [
{
name: 'Tenor',
url: 'https://tenor.com/',
reason: 'API',
reasonURL: 'https://tenor.com/gifapi/documentation'
}
],
args: [
{
key: 'query',
prompt: 'What GIF would you like to search for?',
type: 'string'
}
]
});
}
async run(msg, { query }) {
try {
const { body } = await request
.get('https://api.tenor.com/v1/search')
.query({
q: query,
key: TENOR_KEY,
limit: 50,
contentfilter: msg.channel.nsfw ? 'off' : 'high',
media_filter: 'minimal'
});
if (!body.results.length) return msg.say('Could not find any results.');
return msg.say(body.results[Math.floor(Math.random() * body.results.length)].media[0].gif.url);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-54
View File
@@ -1,54 +0,0 @@
const Command = require('../../framework/Command');
const { MessageEmbed } = require('discord.js');
const request = require('node-superfetch');
const { formatNumber } = require('../../util/Util');
const { TUMBLR_KEY } = process.env;
module.exports = class TumblrCommand extends Command {
constructor(client) {
super(client, {
name: 'tumblr',
group: 'search',
memberName: 'tumblr',
description: 'Responds with information on a Tumblr blog.',
clientPermissions: ['EMBED_LINKS'],
credit: [
{
name: 'Tumblr',
url: 'https://www.tumblr.com/',
reason: 'API',
reasonURL: 'https://www.tumblr.com/docs/en/api/v2'
}
],
args: [
{
key: 'blog',
prompt: 'What blog would you like to get information on?',
type: 'string',
parse: blog => encodeURIComponent(blog)
}
]
});
}
async run(msg, { blog }) {
try {
const { body } = await request
.get(`https://api.tumblr.com/v2/blog/${blog}/info`)
.query({ api_key: TUMBLR_KEY });
const data = body.response.blog;
const embed = new MessageEmbed()
.setColor(0x395976)
.setAuthor('Tumblr', 'https://i.imgur.com/ouD9TUY.png', 'https://www.tumblr.com/')
.setThumbnail(`https://api.tumblr.com/v2/blog/${blog}/avatar/512`)
.setURL(data.url)
.setTitle(data.title)
.addField(' Posts', formatNumber(data.total_posts), true)
.addField(' A.M.A.?', data.ask ? 'Yes' : 'No', true);
return msg.embed(embed);
} catch (err) {
if (err.status === 404) return msg.say('Could not find any results.');
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-83
View File
@@ -1,83 +0,0 @@
const Command = require('../../framework/Command');
const moment = require('moment');
const { MessageEmbed } = require('discord.js');
const request = require('node-superfetch');
const { TWITCH_ID, TWITCH_SECRET } = process.env;
module.exports = class TwitchCommand extends Command {
constructor(client) {
super(client, {
name: 'twitch',
group: 'search',
memberName: 'twitch',
description: 'Responds with information on a Twitch user.',
clientPermissions: ['EMBED_LINKS'],
credit: [
{
name: 'Twitch',
url: 'https://www.twitch.tv/',
reason: 'API',
reasonURL: 'https://dev.twitch.tv/'
}
],
args: [
{
key: 'user',
prompt: 'What user would you like to get information on?',
type: 'string'
}
]
});
this.token = null;
}
async run(msg, { user }) {
try {
if (!this.token) await this.fetchToken();
const { body } = await request
.get('https://api.twitch.tv/helix/search/channels')
.set({
Authorization: `Bearer ${this.token}`,
'client-id': TWITCH_ID
})
.query({
query: user,
first: 1
});
if (!body.data.length) return msg.say('Could not find any results.');
const data = body.data[0];
const embed = new MessageEmbed()
.setColor(0x9147FF)
.setAuthor('Twitch', 'https://i.imgur.com/6l1pPMI.jpg', 'https://www.twitch.tv/')
.setThumbnail(data.thumbnail_url || null)
.setURL(`https://twitch.tv/${data.broadcaster_login}`)
.setTitle(data.display_name)
.setDescription(data.is_live ? data.title : 'Not live')
.setFooter(data.id)
.addField(' Live?', data.is_live ? 'Yes' : 'No', true)
.addField(' Start Date', data.is_live
? moment.utc(new Date(data.started_at)).format('MM/DD/YYYY h:mm A')
: '???', true)
.addField(' Game', data.is_live ? data.game_name : '???', true);
return msg.embed(embed);
} catch (err) {
if (err.status === 401) await this.fetchToken();
if (err.status === 404) return msg.say('Could not find any results.');
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async fetchToken() {
const { body } = await request
.post('https://id.twitch.tv/oauth2/token')
.query({
client_id: TWITCH_ID,
client_secret: TWITCH_SECRET,
grant_type: 'client_credentials'
});
this.token = body.access_token;
setTimeout(() => { this.token = null; }, body.expires_in);
return body;
}
};
-86
View File
@@ -1,86 +0,0 @@
const Command = require('../../framework/Command');
const moment = require('moment');
const { MessageEmbed } = require('discord.js');
const request = require('node-superfetch');
const { formatNumber, base64, embedURL } = require('../../util/Util');
const { TWITTER_KEY, TWITTER_SECRET } = process.env;
const retweetRegex = /^RT @([a-zA-Z0-9_]{1,15}):/;
module.exports = class TwitterCommand extends Command {
constructor(client) {
super(client, {
name: 'twitter',
group: 'search',
memberName: 'twitter',
description: 'Responds with information on a Twitter user.',
clientPermissions: ['EMBED_LINKS'],
credit: [
{
name: 'Twitter',
url: 'https://twitter.com/',
reason: 'API',
reasonURL: 'https://developer.twitter.com/en/docs.html'
}
],
args: [
{
key: 'user',
prompt: 'What user would you like to get information on?',
type: 'string'
}
]
});
this.token = null;
}
async run(msg, { user }) {
try {
if (!this.token) await this.fetchToken();
const { body } = await request
.get('https://api.twitter.com/1.1/users/show.json')
.set({ Authorization: `Bearer ${this.token}` })
.query({ screen_name: user });
let latest = body.status;
if (latest) {
const statusUser = body.status.retweeted_status ? body.status.text.match(retweetRegex)[1] : body.screen_name;
const statusID = body.status.retweeted_status ? body.status.retweeted_status.id_str : body.status.id_str;
latest = embedURL(body.status.text, `https://twitter.com/${statusUser}/status/${statusID}`);
} else {
latest = body.protected ? '🔒 Protected' : 'No tweets found.';
}
const embed = new MessageEmbed()
.setColor(0x55ADEE)
.setAuthor('Twitter', 'https://i.imgur.com/QnfcO7y.png', 'https://twitter.com/')
.setThumbnail(body.profile_image_url_https.replace('_normal', ''))
.setURL(`https://twitter.com/${body.screen_name}`)
.setTitle(`${body.name} (@${body.screen_name})`)
.setDescription(body.description)
.addField(' Tweets', formatNumber(body.statuses_count), true)
.addField(' Followers', formatNumber(body.followers_count), true)
.addField(' Following', formatNumber(body.friends_count), true)
.addField(' Protected?', body.protected ? 'Yes' : 'No', true)
.addField(' Verified?', body.verified ? 'Yes' : 'No', true)
.addField(' Creation Date', moment.utc(new Date(body.created_at)).format('MM/DD/YYYY h:mm A'), true)
.addField(' Latest Tweet', latest);
return msg.embed(embed);
} catch (err) {
if (err.status === 401) await this.fetchToken();
if (err.status === 403) return msg.say('This user is either private or suspended.');
if (err.status === 404) return msg.say('Could not find any results.');
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
async fetchToken() {
const { body } = await request
.post('https://api.twitter.com/oauth2/token')
.set({
Authorization: `Basic ${base64(`${TWITTER_KEY}:${TWITTER_SECRET}`)}`,
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
})
.send('grant_type=client_credentials');
this.token = body.access_token;
return body;
}
};
-62
View File
@@ -1,62 +0,0 @@
const Command = require('../../framework/Command');
const moment = require('moment');
const { MessageEmbed } = require('discord.js');
const request = require('node-superfetch');
const { shorten } = require('../../util/Util');
module.exports = class VocadbCommand extends Command {
constructor(client) {
super(client, {
name: 'vocadb',
aliases: ['vocaloid'],
group: 'search',
memberName: 'vocadb',
description: 'Searches VocaDB for your query.',
clientPermissions: ['EMBED_LINKS'],
credit: [
{
name: 'VocaDB',
url: 'https://vocadb.net/',
reason: 'API',
reasonURL: 'https://vocadb.net/swagger/ui/index'
}
],
args: [
{
key: 'query',
prompt: 'What song would you like to search for?',
type: 'string'
}
]
});
}
async run(msg, { query }) {
try {
const { body } = await request
.get('http://vocadb.net/api/songs')
.query({
query,
maxResults: 1,
sort: 'FavoritedTimes',
preferAccurateMatches: true,
nameMatchMode: 'Words',
fields: 'ThumbUrl,Lyrics'
});
if (!body.items.length) return msg.say('Could not find any results.');
const data = body.items[0];
const embed = new MessageEmbed()
.setColor(0x86D2D0)
.setAuthor('VocaDB', 'https://i.imgur.com/6QwraDT.jpg', 'http://vocadb.net/')
.setTitle(data.name)
.setURL(`http://vocadb.net/S/${data.id}`)
.setDescription(data.lyrics.length ? shorten(data.lyrics[0].value) : 'No lyrics available.')
.setThumbnail(data.thumbUrl)
.addField(' Artist', data.artistString)
.addField(' Publish Date', moment.utc(data.publishDate).format('MM/DD/YYYY'), true);
return msg.embed(embed);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
-63
View File
@@ -1,63 +0,0 @@
const Command = require('../../framework/Command');
const moment = require('moment');
const { MessageEmbed } = require('discord.js');
const request = require('node-superfetch');
const { shorten, formatNumber } = require('../../util/Util');
const { WATTPAD_KEY } = process.env;
module.exports = class WattpadCommand extends Command {
constructor(client) {
super(client, {
name: 'wattpad',
group: 'search',
memberName: 'wattpad',
description: 'Searches Wattpad for your query.',
clientPermissions: ['EMBED_LINKS'],
credit: [
{
name: 'Wattpad',
url: 'https://www.wattpad.com/',
reason: 'API',
reasonURL: 'https://www.wattpad.com/developer/docs/api'
}
],
args: [
{
key: 'query',
prompt: 'What book would you like to search for?',
type: 'string'
}
]
});
}
async run(msg, { query }) {
try {
const { body } = await request
.get('https://api.wattpad.com/v4/stories')
.query({
query,
limit: 1
})
.set({ Authorization: `Basic ${WATTPAD_KEY}` });
if (!body.stories.length) return msg.say('Could not find any results.');
const data = body.stories[0];
const embed = new MessageEmbed()
.setColor(0xF89C34)
.setAuthor('Wattpad', 'https://i.imgur.com/lFTXnlz.png', 'https://www.wattpad.com/')
.setURL(data.url)
.setTitle(data.title)
.setDescription(shorten(data.description))
.setThumbnail(data.cover)
.addField(' Creation Date', moment.utc(data.createDate).format('MM/DD/YYYY h:mm A'), true)
.addField(' Author', data.user.name, true)
.addField(' Chapters', formatNumber(data.numParts), true)
.addField(' Reads', formatNumber(data.readCount), true)
.addField(' Votes', formatNumber(data.voteCount), true)
.addField(' Comments', formatNumber(data.commentCount), true);
return msg.embed(embed);
} catch (err) {
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
}
}
};
+1 -1
View File
@@ -52,7 +52,7 @@ module.exports = class YuGiOhCommand extends Command {
.setDescription(data.type === 'Normal Monster' ? `_${shorten(data.desc)}_` : shorten(data.desc)) .setDescription(data.type === 'Normal Monster' ? `_${shorten(data.desc)}_` : shorten(data.desc))
.setAuthor('Yu-Gi-Oh!', 'https://i.imgur.com/AJNBflD.png', 'http://www.yugioh-card.com/') .setAuthor('Yu-Gi-Oh!', 'https://i.imgur.com/AJNBflD.png', 'http://www.yugioh-card.com/')
.setThumbnail(data.card_images[0].image_url) .setThumbnail(data.card_images[0].image_url)
.setFooter(data.id) .setFooter(data.id.toString())
.addField(' Type', data.type, true) .addField(' Type', data.type, true)
.addField(data.type.includes('Monster') ? ' Race' : ' Spell Type', data.race, true); .addField(data.type.includes('Monster') ? ' Race' : ' Spell Type', data.race, true);
if (data.type.includes('Monster')) { if (data.type.includes('Monster')) {
-25
View File
@@ -1,25 +0,0 @@
const Command = require('../../framework/Command');
module.exports = class JustDoItCommand extends Command {
constructor(client) {
super(client, {
name: 'just-do-it',
aliases: ['motivate'],
group: 'single',
memberName: 'just-do-it',
description: 'Sends a link to the "Just Do It!" motivational speech.',
credit: [
{
name: 'MotivaShian',
url: 'https://www.youtube.com/channel/UC0yDCpC_UaXEdL6Zc4715rg',
reason: 'Original Motivational Speech',
reasonURL: 'https://www.youtube.com/watch?v=ZXsQAXx_ao0'
}
]
});
}
run(msg) {
return msg.say('https://www.youtube.com/watch?v=ZXsQAXx_ao0');
}
};
-16
View File
@@ -1,16 +0,0 @@
const Command = require('../../framework/Command');
module.exports = class LennyCommand extends Command {
constructor(client) {
super(client, {
name: 'lenny',
group: 'single',
memberName: 'lenny',
description: 'Responds with the lenny face.'
});
}
run(msg) {
return msg.say('( ͡° ͜ʖ ͡°)');
}
};
-25
View File
@@ -1,25 +0,0 @@
const Command = require('../../framework/Command');
const path = require('path');
module.exports = class SpamCommand extends Command {
constructor(client) {
super(client, {
name: 'spam',
group: 'single',
memberName: 'spam',
description: 'Responds with a picture of Spam.',
clientPermissions: ['ATTACH_FILES'],
credit: [
{
name: 'SPAM Brand',
url: 'https://www.spam.com/',
reason: 'Image'
}
]
});
}
run(msg) {
return msg.say({ files: [path.join(__dirname, '..', '..', 'assets', 'images', 'spam.png')] });
}
};
-26
View File
@@ -1,26 +0,0 @@
const Command = require('../../framework/Command');
const path = require('path');
module.exports = class WynautCommand extends Command {
constructor(client) {
super(client, {
name: 'wynaut',
aliases: ['why-not'],
group: 'single',
memberName: 'wynaut',
description: 'Why not? Wynaut?',
clientPermissions: ['ATTACH_FILES'],
credit: [
{
name: 'Pokémon',
url: 'https://www.pokemon.com/us/',
reason: 'Image, Original Anime'
}
]
});
}
run(msg) {
return msg.say({ files: [path.join(__dirname, '..', '..', 'assets', 'images', 'wynaut.png')] });
}
};
+1 -1
View File
@@ -11,7 +11,7 @@ Reflect.defineProperty(Message.prototype, 'embed', { value: function (embed, opt
} }); } });
Reflect.defineProperty(Message.prototype, 'code', { value: function (lang, content, options) { Reflect.defineProperty(Message.prototype, 'code', { value: function (lang, content, options) {
return this.channel.send({ content, lang, ...options }); return this.channel.send({ content, ...options });
} }); } });
Reflect.defineProperty(Message.prototype, 'direct', { value: function (content, options) { Reflect.defineProperty(Message.prototype, 'direct', { value: function (content, options) {
-1
View File
@@ -81,7 +81,6 @@
"semver": "^7.6.0", "semver": "^7.6.0",
"sherlockjs": "^1.4.2", "sherlockjs": "^1.4.2",
"stackblur-canvas": "^2.7.0", "stackblur-canvas": "^2.7.0",
"tesseract.js": "^5.0.5",
"text-diff": "^1.0.1", "text-diff": "^1.0.1",
"tictactoe-minimax-ai": "github:marianoheller/tic-tac-toe-minimax", "tictactoe-minimax-ai": "github:marianoheller/tic-tac-toe-minimax",
"twemoji-parser": "^14.0.0", "twemoji-parser": "^14.0.0",