diff --git a/.env.example b/.env.example index 44a7aeaf..895f30a1 100644 --- a/.env.example +++ b/.env.example @@ -24,10 +24,6 @@ SILVER_FISH_EMOJI_ID= SILVER_FISH_EMOJI_NAME= PORTAL_EMOJI_ID= PORTAL_EMOJI_NAME= -FLANKER_EMOJI_ID= -FRONT_LINE_EMOJI_ID= -SUPPORT_EMOJI_ID= -DAMAGE_EMOJI_ID= LOADING_EMOJI_ID= MEGA_EVOLVE_EMOJI_ID= MEGA_EVOLVE_EMOJI_NAME= @@ -37,36 +33,20 @@ NAME_RATER_EMOJI_ID= ALPHA_VANTAGE_KEY= ANILIST_USERNAME= BITLY_KEY= -CLEARBIT_KEY= CLEVERBOT_KEY= DEVIANTART_ID= DEVIANTART_SECRET= -FACEPLUSPLUS_KEY= -FACEPLUSPLUS_SECRET= -FLICKR_KEY= GIPHY_KEY= GITHUB_ACCESS_TOKEN= -GODADDY_KEY= -GODADDY_SECRET= -GOOGLE_KEY= GOV_KEY= IMGUR_KEY= OPENWEATHERMAP_KEY= OSU_KEY= -PERSONAL_GOOGLE_CALENDAR_ID= SPOTIFY_KEY= SPOTIFY_SECRET= -STACKOVERFLOW_KEY= -TENOR_KEY= TMDB_KEY= -TUMBLR_KEY= -TWITCH_ID= -TWITCH_SECRET= -TWITTER_KEY= -TWITTER_SECRET= UNSPLASH_KEY= USPS_USERID= -WATTPAD_KEY= WEBSTER_KEY= XIAO_GITHUB_REPO_NAME= XIAO_GITHUB_REPO_USERNAME= diff --git a/.gitignore b/.gitignore index 69d6b2b5..cbd08ab6 100644 --- a/.gitignore +++ b/.gitignore @@ -20,9 +20,6 @@ blacklist.json # Tensorflow Models tf_models/ -# Tesseract Trained Data -*.traineddata - # Mac Files .DS_Store diff --git a/assets/images/spam.png b/assets/images/spam.png deleted file mode 100644 index 6f515fd6..00000000 Binary files a/assets/images/spam.png and /dev/null differ diff --git a/assets/images/wynaut.png b/assets/images/wynaut.png deleted file mode 100644 index 0e01f76b..00000000 Binary files a/assets/images/wynaut.png and /dev/null differ diff --git a/assets/json/apple-engraving.json b/assets/json/apple-engraving.json deleted file mode 100644 index 35d4e63c..00000000 --- a/assets/json/apple-engraving.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "airpods": "PRXJ2AM", - "airpods-pro": "PWP22AM", - "pencil": "PU8F2AM", - "ipod": "PVHV2LL", - "ipad-pro": "PTEM2LL", - "ipad": "PW752LL", - "ipad-mini": "PUQX2LL", - "ipad-air": "PUUK2LL" -} diff --git a/assets/json/hentai.json b/assets/json/hentai.json deleted file mode 100644 index b4fa1721..00000000 --- a/assets/json/hentai.json +++ /dev/null @@ -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" -] diff --git a/assets/json/paladins.json b/assets/json/paladins.json deleted file mode 100644 index 5334f231..00000000 --- a/assets/json/paladins.json +++ /dev/null @@ -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" - } -} diff --git a/assets/json/porn.json b/assets/json/porn.json deleted file mode 100644 index 0df965fc..00000000 --- a/assets/json/porn.json +++ /dev/null @@ -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" -] diff --git a/assets/json/soundboard.json b/assets/json/soundboard.json deleted file mode 100644 index f410d1c9..00000000 --- a/assets/json/soundboard.json +++ /dev/null @@ -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"] -] diff --git a/assets/json/vocodes.json b/assets/json/vocodes.json deleted file mode 100644 index 9ebbd3fa..00000000 --- a/assets/json/vocodes.json +++ /dev/null @@ -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" -} diff --git a/commands/analyze/domain-available.js b/commands/analyze/domain-available.js deleted file mode 100644 index 1c3665f4..00000000 --- a/commands/analyze/domain-available.js +++ /dev/null @@ -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!`); - } - } -}; diff --git a/commands/analyze/has-transparency.js b/commands/analyze/has-transparency.js deleted file mode 100644 index 072363d2..00000000 --- a/commands/analyze/has-transparency.js +++ /dev/null @@ -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!`); - } - } -}; diff --git a/commands/analyze/nsfw-url.js b/commands/analyze/nsfw-url.js index 5bfbf58c..9e92b3f9 100644 --- a/commands/analyze/nsfw-url.js +++ b/commands/analyze/nsfw-url.js @@ -22,7 +22,7 @@ module.exports = class NsfwUrlCommand extends Command { async run(msg, { url }) { 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) return msg.reply('π This site is safe!'); + if (!nsfw) return msg.reply('π This site is SFW!'); return msg.reply('π This site is NSFW.'); } }; diff --git a/commands/analyze/ocr.js b/commands/analyze/ocr.js deleted file mode 100644 index 2686209d..00000000 --- a/commands/analyze/ocr.js +++ /dev/null @@ -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); - } -}; diff --git a/commands/analyze/repost.js b/commands/analyze/repost.js deleted file mode 100644 index 958279ff..00000000 --- a/commands/analyze/repost.js +++ /dev/null @@ -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; - } -}; diff --git a/commands/analyze/safe-url.js b/commands/analyze/safe-url.js deleted file mode 100644 index e59bc3c6..00000000 --- a/commands/analyze/safe-url.js +++ /dev/null @@ -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!`); - } - } -}; diff --git a/commands/analyze/toxicity.js b/commands/analyze/toxicity.js deleted file mode 100644 index 6e155188..00000000 --- a/commands/analyze/toxicity.js +++ /dev/null @@ -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!`); - } - } -}; diff --git a/commands/analyze/what-anime.js b/commands/analyze/what-anime.js deleted file mode 100644 index 53ae7272..00000000 --- a/commands/analyze/what-anime.js +++ /dev/null @@ -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(); - } -}; diff --git a/commands/code/mdn.js b/commands/code/mdn.js deleted file mode 100644 index 370f1561..00000000 --- a/commands/code/mdn.js +++ /dev/null @@ -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!`); - } - } -}; diff --git a/commands/code/stack-overflow.js b/commands/code/stack-overflow.js deleted file mode 100644 index 7f73b9ce..00000000 --- a/commands/code/stack-overflow.js +++ /dev/null @@ -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!`); - } - } -}; diff --git a/commands/edit-image-text/apple-engraving.js b/commands/edit-image-text/apple-engraving.js deleted file mode 100644 index 74866fee..00000000 --- a/commands/edit-image-text/apple-engraving.js +++ /dev/null @@ -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!`); - } - } -}; diff --git a/commands/events/calendar.js b/commands/events/calendar.js index bc43be3d..94db39ec 100644 --- a/commands/events/calendar.js +++ b/commands/events/calendar.js @@ -54,6 +54,6 @@ module.exports = class CalendarCommand extends Command { } } display += '|'; - return msg.code(null, display); + return msg.say(`\`\`\`\n${display}\n\`\`\``); } }; diff --git a/commands/events/covid-19.js b/commands/events/covid-19.js deleted file mode 100644 index 76c2eb50..00000000 --- a/commands/events/covid-19.js +++ /dev/null @@ -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; - } -}; diff --git a/commands/events/doomsday-clock.js b/commands/events/doomsday-clock.js deleted file mode 100644 index 6fff068f..00000000 --- a/commands/events/doomsday-clock.js +++ /dev/null @@ -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(/