mirror of
https://github.com/arthur-pbty/xiao.git
synced 2026-06-06 06:10:49 +02:00
Remove non-working API-based commands, fix bugs
This commit is contained in:
@@ -56,7 +56,7 @@ Xiao is a Discord bot coded in JavaScript with
|
||||
* [Rando Cardrissian](https://github.com/dragonfire535/rando-cardrissian) is a Cards Against Humanity bot, whose features were originally built into Xiao.
|
||||
* [Storyteller](https://github.com/dragonfire535/storyteller) is a Mafia bot made for Discord's 2019 Hack Week, whose features were originally built into Xiao.
|
||||
|
||||
## Commands (349)
|
||||
## Commands (343)
|
||||
### Utility:
|
||||
|
||||
* **eval:** Executes JavaScript code.
|
||||
@@ -175,7 +175,6 @@ Xiao is a Discord bot coded in JavaScript with
|
||||
### Search:
|
||||
|
||||
* **anime:** Searches AniList for your query, getting anime results.
|
||||
* **azur-lane:** Responds with information on an Azur Lane ship.
|
||||
* **book:** Searches Google Books for a book.
|
||||
* **bulbapedia:** Searches Bulbapedia for your query.
|
||||
* **character:** Searches AniList for your query, getting character results.
|
||||
@@ -183,8 +182,6 @@ Xiao is a Discord bot coded in JavaScript with
|
||||
* **define:** Defines a word.
|
||||
* **derpibooru:** Responds with an image from Derpibooru.
|
||||
* **deviantart:** Responds with an image from a DeviantArt section, with optional query.
|
||||
* **docs:** Searches the Discord.js docs for your query.
|
||||
* **esrb:** Searches ESRB for your query.
|
||||
* **flickr:** Searches Flickr for your query.
|
||||
* **giphy:** Searches Giphy for your query.
|
||||
* **github:** Responds with information on a GitHub repository.
|
||||
@@ -198,7 +195,6 @@ Xiao is a Discord bot coded in JavaScript with
|
||||
* **jisho:** Defines a word, but with Japanese.
|
||||
* **kickstarter:** Searches Kickstarter for your query.
|
||||
* **know-your-meme:** Searches Know Your Meme for your query.
|
||||
* **konachan:** Responds with an image from Konachan, with optional query.
|
||||
* **league-of-legends:** Responds with information on a League of Legends champion.
|
||||
* **manga:** Searches AniList for your query, getting manga results.
|
||||
* **map:** Responds with a map of a specific location.
|
||||
@@ -227,7 +223,6 @@ Xiao is a Discord bot coded in JavaScript with
|
||||
* **twitter:** Responds with information on a Twitter user.
|
||||
* **urban:** Defines a word, but with Urban Dictionary.
|
||||
* **usps-tracking:** Gets tracking information for a package shipped via USPS.
|
||||
* **visual-novel:** Responds with information on a Visual Novel.
|
||||
* **vocadb:** Searches VocaDB for your query.
|
||||
* **wattpad:** Searches Wattpad for your query.
|
||||
* **weather:** Responds with weather information for a specific location.
|
||||
@@ -315,7 +310,6 @@ Xiao is a Discord bot coded in JavaScript with
|
||||
* **needs-more-jpeg:** Draws an image or a user's avatar as a low quality JPEG.
|
||||
* **new-password:** Sends a "Weak Password/Strong Password" meme with the passwords of your choice.
|
||||
* **nike-ad:** Sends a "Believe in Something" Nike Ad meme with the text of your choice.
|
||||
* **osu-signature:** Creates a card based on an osu! user's stats.
|
||||
* **pixelize:** Draws an image or a user's avatar pixelized.
|
||||
* **plankton-plan:** Sends a Plankton's Plan meme with steps of your choice.
|
||||
* **pokemon-fusion:** Fuses two Generation I Pokémon together.
|
||||
|
||||
@@ -29,7 +29,7 @@ module.exports = class DoomsdayClockCommand extends Command {
|
||||
.setColor(0x000000)
|
||||
.setURL('https://thebulletin.org/doomsday-clock/current-time/')
|
||||
.setAuthor('Bulletin of the Atomic Scientists', undefined, 'https://thebulletin.org/')
|
||||
.setDescription(description.replace(/<a href="(.+)">(.+)<\/a>/, '[$2]($1)'));
|
||||
.setDescription(description.replace(/<a href="(.+)" target="_blank" rel="noopener">(.+)<\/a>/, '[$2]($1)'));
|
||||
return msg.embed(embed);
|
||||
} catch (err) {
|
||||
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
|
||||
|
||||
@@ -20,7 +20,8 @@ module.exports = class CursedSpongeCommand extends Command {
|
||||
key: 'amount',
|
||||
prompt: 'How many times do you want to duplicate the cursed sponge?',
|
||||
type: 'integer',
|
||||
max: 100
|
||||
max: 100,
|
||||
min: 1
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const request = require('node-superfetch');
|
||||
const { list } = require('../../util/Util');
|
||||
const colors = require('../../assets/json/osu-signature');
|
||||
|
||||
module.exports = class OsuSignatureCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'osu-signature',
|
||||
aliases: ['osu-sig', 'osu-card'],
|
||||
group: 'image-edit',
|
||||
memberName: 'osu-signature',
|
||||
description: 'Creates a card based on an osu! user\'s stats.',
|
||||
details: `**Colors:** ${Object.keys(colors).join(', ')}`,
|
||||
clientPermissions: ['ATTACH_FILES'],
|
||||
credit: [
|
||||
{
|
||||
name: 'osu!',
|
||||
url: 'https://osu.ppy.sh/home'
|
||||
},
|
||||
{
|
||||
name: 'osu!next Signature Generator',
|
||||
url: 'https://lemmmy.pw/osusig/'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'user',
|
||||
prompt: 'What user would you like to create a signature for?',
|
||||
type: 'string'
|
||||
},
|
||||
{
|
||||
key: 'color',
|
||||
prompt: `What color should the signature be? Either ${list(Object.keys(colors), 'or')}.`,
|
||||
type: 'string',
|
||||
default: 'pink',
|
||||
validate: color => {
|
||||
if (colors[color.toLowerCase()]) return true;
|
||||
return `Invalid color, please enter either ${list(Object.keys(colors), 'or')}.`;
|
||||
},
|
||||
parse: color => colors[color.toLowerCase()]
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { user, color }) {
|
||||
try {
|
||||
const { body } = await request
|
||||
.get('https://lemmmy.pw/osusig/sig.php')
|
||||
.query({
|
||||
colour: color,
|
||||
uname: user,
|
||||
pp: 2,
|
||||
flagshadow: '',
|
||||
flagstroke: '',
|
||||
darktriangles: '',
|
||||
opaqueavatar: '',
|
||||
onlineindicator: '',
|
||||
xpbar: ''
|
||||
});
|
||||
return msg.say({ files: [{ attachment: body, name: 'osu-signature.png' }] });
|
||||
} catch (err) {
|
||||
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -20,6 +20,7 @@ module.exports = class MessageSourceCommand extends Command {
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -27,11 +27,11 @@ module.exports = class ServerCommand extends Command {
|
||||
.addField('❯ Region', msg.guild.region.toUpperCase(), true)
|
||||
.addField('❯ Creation Date', moment.utc(msg.guild.createdAt).format('MM/DD/YYYY h:mm A'), true)
|
||||
.addField('❯ Explicit Filter', filterLevels[msg.guild.explicitContentFilter], true)
|
||||
.addField('❯ Verification Level', verificationLevels[msg.guild.verificationLevel], true)
|
||||
.addField('❯ Owner', msg.guild.owner.user.tag, true)
|
||||
.addField('❯ Members', msg.guild.memberCount, true)
|
||||
.addField('❯ Roles', msg.guild.roles.size, true)
|
||||
.addField('❯ Channels', msg.guild.channels.filter(channel => channel.type !== 'category').size, true);
|
||||
.addField('❯ Channels', msg.guild.channels.filter(channel => channel.type !== 'category').size, true)
|
||||
.addField('❯ Verification Level', verificationLevels[msg.guild.verificationLevel], true);
|
||||
return msg.embed(embed);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -40,8 +40,9 @@ module.exports = class UserCommand extends Command {
|
||||
if (msg.channel.type === 'text') {
|
||||
try {
|
||||
const member = await msg.guild.members.fetch(user.id);
|
||||
const defaultRole = msg.guild.roles.get(msg.guild.id);
|
||||
const roles = member.roles
|
||||
.filter(role => role.id !== msg.guild.defaultRole.id)
|
||||
.filter(role => role.id !== defaultRole)
|
||||
.sort((a, b) => b.position - a.position)
|
||||
.map(role => role.name);
|
||||
embed
|
||||
@@ -52,7 +53,7 @@ module.exports = class UserCommand extends Command {
|
||||
.addField('❯ Server Join Date', moment.utc(member.joinedAt).format('MM/DD/YYYY h:mm A'), true)
|
||||
.addField('❯ Nickname', member.nickname || 'None', true)
|
||||
.addField('❯ Highest Role',
|
||||
member.roles.highest.id === msg.guild.defaultRole.id ? 'None' : member.roles.highest.name, true)
|
||||
member.roles.highest.id === defaultRole ? '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, 10).join(', ') : 'None');
|
||||
} catch (err) {
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const { MessageEmbed } = require('discord.js');
|
||||
const request = require('node-superfetch');
|
||||
const { stripIndents } = require('common-tags');
|
||||
const { formatNumber } = require('../../util/Util');
|
||||
|
||||
module.exports = class AzurLaneCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'azur-lane',
|
||||
aliases: ['azur-lane-ship', 'azur'],
|
||||
group: 'search',
|
||||
memberName: 'azur-lane',
|
||||
description: 'Responds with information on an Azur Lane ship.',
|
||||
clientPermissions: ['EMBED_LINKS'],
|
||||
credit: [
|
||||
{
|
||||
name: 'Azur Lane',
|
||||
url: 'https://azurlane.yo-star.com/#/'
|
||||
},
|
||||
{
|
||||
name: 'Unofficial Azur Lane API',
|
||||
url: 'https://al-shipgirls.pw/'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'query',
|
||||
prompt: 'What ship would you like to get information on?',
|
||||
type: 'string'
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { query }) {
|
||||
try {
|
||||
const { body } = await request
|
||||
.get(`https://al-shipgirls.pw/shipyard/ship_info_detailed/`)
|
||||
.query({ search: query });
|
||||
if (!body.length) return msg.say('Could not find any results.');
|
||||
const data = body[0].item;
|
||||
const embed = new MessageEmbed()
|
||||
.setColor(0x1A1917)
|
||||
.setAuthor('Azur Lane', 'https://i.imgur.com/KeGXiZA.jpg', 'https://azurlane.yo-star.com')
|
||||
.setTitle(`${data.names.en} (${data.class} Class)`)
|
||||
.setURL(data.page_url)
|
||||
.setThumbnail(data.icon)
|
||||
.setFooter(`Ship #${data.id}`)
|
||||
.addField('❯ Construction Time', data.construction_time, true)
|
||||
.addField('❯ Rarity', data.rarity, true)
|
||||
.addField('❯ Nationality', data.nationality, true)
|
||||
.addField('❯ Type', data.type, true)
|
||||
.addField('❯ Health', `${formatNumber(data.base.health)} (${formatNumber(data.max.health)} Max)`, true)
|
||||
.addField('❯ Armor', data.base.armor, true)
|
||||
.addField('❯ Reload', `${formatNumber(data.base.reload)} (${formatNumber(data.max.reload)} Max)`, true)
|
||||
.addField('❯ Firepower', `${formatNumber(data.base.firepower)} (${formatNumber(data.max.firepower)} Max)`, true)
|
||||
.addField('❯ Torpedo', `${formatNumber(data.base.torpedo)} (${formatNumber(data.max.torpedo)} Max)`, true)
|
||||
.addField('❯ Evasion', `${formatNumber(data.base.speed)} (${formatNumber(data.max.speed)} Max)`, true)
|
||||
.addField('❯ Anti-Air', `${formatNumber(data.base.anti_air)} (${formatNumber(data.max.anti_air)} Max)`, true)
|
||||
.addField('❯ Anti-Sub', `${formatNumber(data.base.anti_sub)} (${formatNumber(data.max.anti_sub)} Max)`, true)
|
||||
.addField('❯ Aviation', `${formatNumber(data.base.air_power)} (${formatNumber(data.max.air_power)} Max)`, true)
|
||||
.addField('❯ Oil Cost', `${formatNumber(data.base.oil_usage)} (${formatNumber(data.max.oil_usage)} Max)`, true)
|
||||
.addField('❯ Equipment', stripIndents`
|
||||
${data.equipment[0].equipable} (${data.equipment[0].efficiency})
|
||||
${data.equipment[1].equipable} (${data.equipment[1].efficiency})
|
||||
${data.equipment[2].equipable} (${data.equipment[2].efficiency})
|
||||
`)
|
||||
.addField('❯ Images',
|
||||
`${data.images.map(img => `[${img.name}](${img.url})`).join(', ')}, [Chibi](${data.chibi})`);
|
||||
return msg.embed(embed);
|
||||
} catch (err) {
|
||||
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,58 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const request = require('node-superfetch');
|
||||
const branches = ['stable', 'master', 'rpc', 'commando'];
|
||||
|
||||
module.exports = class DocsCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'docs',
|
||||
aliases: ['discord-js-docs', 'djs-docs', 'djs', 'discord-js'],
|
||||
group: 'search',
|
||||
memberName: 'docs',
|
||||
description: 'Searches the Discord.js docs for your query.',
|
||||
clientPermissions: ['EMBED_LINKS'],
|
||||
credit: [
|
||||
{
|
||||
name: 'discord.js',
|
||||
url: 'https://discord.js.org/#/'
|
||||
},
|
||||
{
|
||||
name: 'TeeSeal/discord.js-docs-api',
|
||||
url: 'https://github.com/TeeSeal/discord.js-docs-api'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'query',
|
||||
prompt: 'What would you like to search the docs for?',
|
||||
type: 'string',
|
||||
parse: query => query.toLowerCase()
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { query }) {
|
||||
let project = 'main';
|
||||
let branch = query.split(' ');
|
||||
if (branches.includes(branch[0])) {
|
||||
query = branch.slice(1).join(' ');
|
||||
branch = branch[0];
|
||||
} else {
|
||||
branch = 'master';
|
||||
}
|
||||
if (branch === 'commando' || branch === 'rpc') {
|
||||
project = branch;
|
||||
branch = 'master';
|
||||
}
|
||||
try {
|
||||
const { body } = await request
|
||||
.get(`https://djsdocs.sorta.moe/${project}/${branch}/embed`)
|
||||
.query({ q: query });
|
||||
if (!body) return msg.say('Could not find any results.');
|
||||
return msg.embed(body);
|
||||
} catch (err) {
|
||||
return msg.reply(`Oh no, an error occurred: \`${err.message}\`. Try again later!`);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,77 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const request = require('node-superfetch');
|
||||
const cheerio = require('cheerio');
|
||||
const { MessageEmbed } = require('discord.js');
|
||||
const ratings = {
|
||||
EC: 'Early Childhood',
|
||||
E: 'Everyone',
|
||||
E10plus: 'Everyone 10+',
|
||||
T: 'Teen',
|
||||
M: 'Mature',
|
||||
AO: 'Adults Only'
|
||||
};
|
||||
|
||||
module.exports = class ESRBCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'esrb',
|
||||
group: 'search',
|
||||
memberName: 'esrb',
|
||||
description: 'Searches ESRB for your query.',
|
||||
clientPermissions: ['EMBED_LINKS'],
|
||||
credit: [
|
||||
{
|
||||
name: 'ESRB Ratings',
|
||||
url: 'http://www.esrb.org/'
|
||||
}
|
||||
],
|
||||
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 embed = new MessageEmbed()
|
||||
.setColor(0x231F20)
|
||||
.setAuthor('ESRB', 'https://i.imgur.com/dV2BamF.jpg', 'https://www.esrb.org/')
|
||||
.setTitle(`${data.title} (${data.platforms.join(', ')})`)
|
||||
.setDescription(data.summary || 'No summary available.')
|
||||
.setThumbnail(data.image)
|
||||
.addField('❯ Rating', ratings[data.rating], true)
|
||||
.addField('❯ Content Descriptors', data.descriptors.length ? data.descriptors.join('\n') : 'None', 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.esrb.org/ratings/search.aspx')
|
||||
.query({
|
||||
from: 'home',
|
||||
titleOrPublisher: query
|
||||
});
|
||||
const $ = cheerio.load(text);
|
||||
const result = $('table').first().children().eq(1).children();
|
||||
if (!result.length) return null;
|
||||
const image = result.find('td[data-title="Ratings"]').first().find('img').attr('src');
|
||||
const descriptors = result.find('td[data-title="Content Descriptors"]').first().children().first().text().trim();
|
||||
return {
|
||||
title: result.find('td[data-title="Title"]').first().text().trim(),
|
||||
platforms: result.find('td[data-title="Platforms"]').first().text().trim().split(', '),
|
||||
rating: image.match(/(EC|E|E10plus|T|M|AO)\.png/i)[1],
|
||||
descriptors: descriptors.split(', '),
|
||||
summary: result.find('td[style="border-width: 0 3px 0 0; padding: 10px;"]').first().text().trim() || null,
|
||||
image
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -1,43 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const request = require('node-superfetch');
|
||||
|
||||
module.exports = class KonachanCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'konachan',
|
||||
group: 'search',
|
||||
memberName: 'konachan',
|
||||
description: 'Responds with an image from Konachan, with optional query.',
|
||||
nsfw: true,
|
||||
credit: [
|
||||
{
|
||||
name: 'konachan.com',
|
||||
url: 'https://konachan.com/'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'query',
|
||||
prompt: 'What image would you like to search for?',
|
||||
type: 'string',
|
||||
default: ''
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
async run(msg, { query }) {
|
||||
try {
|
||||
const { body } = await request
|
||||
.get('https://konachan.net/post.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!`);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -39,8 +39,11 @@ module.exports = class MovieCommand extends Command {
|
||||
query
|
||||
});
|
||||
if (!search.body.results.length) return msg.say('Could not find any results.');
|
||||
const find = search.body.results.find(
|
||||
m => m.title.toLowerCase() === query.toLowerCase()
|
||||
) || search.body.results[0];
|
||||
const { body } = await request
|
||||
.get(`https://api.themoviedb.org/3/movie/${search.body.results[0].id}`)
|
||||
.get(`https://api.themoviedb.org/3/movie/${find.id}`)
|
||||
.query({ api_key: TMDB_KEY });
|
||||
const embed = new MessageEmbed()
|
||||
.setColor(0x00D474)
|
||||
|
||||
@@ -32,12 +32,12 @@ module.exports = class NeopetCommand extends Command {
|
||||
key: 'mood',
|
||||
prompt: `What mood should the pet be in? Either ${list(Object.keys(moods), 'or')}.`,
|
||||
type: 'string',
|
||||
default: 'happy',
|
||||
default: 1,
|
||||
validate: mood => {
|
||||
if (moods[mood.toLowerCase()]) return true;
|
||||
return `Invalid mood, please enter either ${list(Object.keys(moods), 'or')}.`;
|
||||
},
|
||||
parse: mood => mood.toLowerCase()
|
||||
parse: mood => moods[mood.toLowerCase()]
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
@@ -39,8 +39,11 @@ module.exports = class TvShowCommand extends Command {
|
||||
query
|
||||
});
|
||||
if (!search.body.results.length) return msg.say('Could not find any results.');
|
||||
const find = search.body.results.find(
|
||||
m => m.title.toLowerCase() === query.toLowerCase()
|
||||
) || search.body.results[0];
|
||||
const { body } = await request
|
||||
.get(`https://api.themoviedb.org/3/tv/${search.body.results[0].id}`)
|
||||
.get(`https://api.themoviedb.org/3/tv/${find.id}`)
|
||||
.query({ api_key: TMDB_KEY });
|
||||
const embed = new MessageEmbed()
|
||||
.setColor(0x00D474)
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
const Command = require('../../structures/Command');
|
||||
const request = require('node-superfetch');
|
||||
const { MessageEmbed } = require('discord.js');
|
||||
const { shorten } = require('../../util/Util');
|
||||
|
||||
module.exports = class VisualNovelCommand extends Command {
|
||||
constructor(client) {
|
||||
super(client, {
|
||||
name: 'visual-novel',
|
||||
aliases: ['vndb', 'vn'],
|
||||
group: 'search',
|
||||
memberName: 'visual-novel',
|
||||
description: 'Responds with information on a Visual Novel.',
|
||||
clientPermissions: ['EMBED_LINKS'],
|
||||
credit: [
|
||||
{
|
||||
name: 'The Visual Novel Database',
|
||||
url: 'https://vndb.org/'
|
||||
}
|
||||
],
|
||||
args: [
|
||||
{
|
||||
key: 'query',
|
||||
prompt: 'What visual novel would you like to get information on?',
|
||||
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.fetchVN(id);
|
||||
const embed = new MessageEmbed()
|
||||
.setColor(0x000407)
|
||||
.setAuthor('VNDB', 'https://i.imgur.com/BIxjIby.png', 'https://vndb.org/')
|
||||
.setTitle(data.title)
|
||||
.setDescription(shorten(data.description || 'No description available.'))
|
||||
.setURL(data.url)
|
||||
.setThumbnail(data.image)
|
||||
.addField('❯ Developer', `[${data.developer.name}](${data.developer.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://vndb.org/v/all')
|
||||
.query({ q: query });
|
||||
const id = text.match(/<a href="\/v([0-9]+)" title=/);
|
||||
if (!id) return null;
|
||||
return id[1];
|
||||
}
|
||||
|
||||
async fetchVN(id) {
|
||||
const { text } = await request.get(`https://vndb.org/v${id}`);
|
||||
const devID = text.match(/<a href="\/p([0-9]+)"/)[1];
|
||||
const developer = await this.fetchDeveloper(devID);
|
||||
const description = text.match(/<h2>Description<\/h2><p>(.+)<\/p><\/td>/)[1]
|
||||
.replace(/<br>/g, '\n')
|
||||
.replace(/<a href="(.+)" rel="nofollow">(.+)<\/a>/g, '[$2]($1)');
|
||||
return {
|
||||
id: id[1],
|
||||
url: `https://vndb.org/v${id}`,
|
||||
title: text.match(/<title>(.+)<\/title>/)[1],
|
||||
developer,
|
||||
description: description === '-' ? null : description,
|
||||
image: text.match(/https:\/\/s.vndb.org\/cv\/[0-9]+\/[0-9]+\.jpg/)[0]
|
||||
};
|
||||
}
|
||||
|
||||
async fetchDeveloper(id) {
|
||||
const { text } = await request.get(`https://vndb.org/p${id}`);
|
||||
return {
|
||||
name: text.match(/<title>(.+)<\/title>/)[1],
|
||||
url: `https://vndb.org/p${id}`
|
||||
};
|
||||
}
|
||||
};
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xiao",
|
||||
"version": "107.9.0",
|
||||
"version": "108.0.0",
|
||||
"description": "Your personal server companion.",
|
||||
"main": "Xiao.js",
|
||||
"scripts": {
|
||||
|
||||
Reference in New Issue
Block a user