mirror of
https://github.com/arthur-pbty/xiao.git
synced 2026-06-03 23:36:43 +02:00
Remove more commands
This commit is contained in:
@@ -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=
|
||||||
|
|||||||
@@ -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 |
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"airpods": "PRXJ2AM",
|
|
||||||
"airpods-pro": "PWP22AM",
|
|
||||||
"pencil": "PU8F2AM",
|
|
||||||
"ipod": "PVHV2LL",
|
|
||||||
"ipad-pro": "PTEM2LL",
|
|
||||||
"ipad": "PW752LL",
|
|
||||||
"ipad-mini": "PUQX2LL",
|
|
||||||
"ipad-air": "PUUK2LL"
|
|
||||||
}
|
|
||||||
@@ -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"
|
|
||||||
]
|
|
||||||
@@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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"
|
|
||||||
]
|
|
||||||
@@ -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"]
|
|
||||||
]
|
|
||||||
@@ -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"
|
|
||||||
}
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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.');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -54,6 +54,6 @@ module.exports = class CalendarCommand extends Command {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
display += '|';
|
display += '|';
|
||||||
return msg.code(null, display);
|
return msg.say(`\`\`\`\n${display}\n\`\`\``);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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.`);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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: ' ' } });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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}.`);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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}`;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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}>`;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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')}`;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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'])
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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')) {
|
||||||
|
|||||||
@@ -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');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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('( ͡° ͜ʖ ͡°)');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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')] });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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')] });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
Reference in New Issue
Block a user