mirror of
https://github.com/arthur-pbty/xiao.git
synced 2026-06-24 02:15:10 +02:00
Remove more commands
This commit is contained in:
@@ -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 }) {
|
||||
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.');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user