mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-04-24 06:49:11 -05:00
This is a surprisingly minor refactor considering how many files it touches, but most of this is only renames. In terms of file renames: - `tools.js` is now `sim/dex.js` - `battle-engine.js` is now `sim/index.js` and its three classes are in `sim/battle.js`, `sim/side.js`, and `sim/pokemon.js` - `prng.js` is now `sim/prng.js` In terms of variable renames: - `Tools` is now `Dex` - `BattleEngine` is now `Sim` - `BattleEngine.Battle` is now `Sim.Battle` - `BattleEngine.BattleSide` is now `Sim.Side` - `BattleEngine.BattlePokemon` is now `Sim.Pokemon`
162 lines
6.8 KiB
JavaScript
162 lines
6.8 KiB
JavaScript
/**
|
|
* TCG & Tabletop: Yugioh wiki plugin
|
|
* This is a command that allows users to search the yugioh wiki for cards. It will display the closest match with a given query, or a separate message if there isn't anything found.
|
|
* By bumbadadabum with help from ascriptmaster, codelegend and the PS development team.
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const http = require('http');
|
|
|
|
function apiRequest(url, onEnd, onError) {
|
|
http.get(url, res => {
|
|
let buffer = '';
|
|
res.setEncoding('utf8');
|
|
res.on('data', data => {
|
|
buffer += data;
|
|
});
|
|
res.on('end', () => {
|
|
onEnd(buffer);
|
|
});
|
|
}).on('error', err => {
|
|
onEnd(err);
|
|
});
|
|
}
|
|
|
|
function mediawikiSearch(domain, query) {
|
|
return new Promise(function (resolve, reject) {
|
|
apiRequest(`http://${domain}/w/api.php?action=query&list=search&format=json&srsearch=${encodeURIComponent(query)}&srwhat=nearmatch`, res => {
|
|
let result;
|
|
try {
|
|
result = JSON.parse(res);
|
|
} catch (e) {
|
|
return reject(e);
|
|
}
|
|
if (!result) return reject(new Error("Malformed data"));
|
|
if (!result.query || !result.query.search || !Array.isArray(result.query.search)) return reject(new Error("Malformed data"));
|
|
if (!result.query.search.length) return reject(new Error("Not found"));
|
|
if (typeof result.query.search[0] !== 'object') return reject(new Error("Malformed data"));
|
|
|
|
return resolve(result.query.search[0]);
|
|
}, reject);
|
|
});
|
|
}
|
|
|
|
function wikiaSearch(subdomain, query) {
|
|
return new Promise(function (resolve, reject) {
|
|
apiRequest(`http://${subdomain}.wikia.com/api/v1/Search/List/?query=${encodeURIComponent(query)}&limit=1`, res => {
|
|
let result;
|
|
try {
|
|
result = JSON.parse(res);
|
|
} catch (e) {
|
|
return reject(e);
|
|
}
|
|
if (!result) return reject(new Error("Malformed data"));
|
|
if (result.exception) return reject(new Error(Dex.getString(result.exception.message) || "Not found"));
|
|
if (!Array.isArray(result.items) || !result.items[0] || typeof result.items[0] !== 'object') return reject(new Error("Malformed data"));
|
|
|
|
return resolve(result.items[0]);
|
|
}, reject);
|
|
});
|
|
}
|
|
function getCardDetails(subdomain, id) {
|
|
return new Promise(function (resolve, reject) {
|
|
apiRequest(`http://${subdomain}.wikia.com/api/v1/Articles/Details?ids=${encodeURIComponent(id)}&abstract=0&width=80&height=115`, res => {
|
|
let result;
|
|
try {
|
|
result = JSON.parse(res);
|
|
} catch (e) {
|
|
return reject(e);
|
|
}
|
|
if (!result) return reject(new Error("Malformed data"));
|
|
if (result.exception) return reject(new Error(Dex.getString(result.exception.message) || "Not found"));
|
|
if (typeof result.items !== 'object' || !result.items[id] || typeof result.items[id] !== 'object') return reject(new Error("Malformed data"));
|
|
|
|
return resolve(result.items[id]);
|
|
}, reject);
|
|
});
|
|
}
|
|
|
|
exports.commands = {
|
|
ygo: 'yugioh',
|
|
yugioh: function (target, room, user) {
|
|
if (!this.canBroadcast()) return;
|
|
if (room.id !== 'tcgtabletop') return this.errorReply("This command can only be used in the TCG & Tabletop room.");
|
|
let subdomain = 'yugioh';
|
|
let query = target.trim();
|
|
|
|
wikiaSearch(subdomain, query).then(data => {
|
|
if (!this.runBroadcast()) return;
|
|
let entryUrl = Dex.getString(data.url);
|
|
let entryTitle = Dex.getString(data.title);
|
|
let id = Dex.getString(data.id);
|
|
let htmlReply = `<strong>Best result for ${Chat.escapeHTML(query)}:</strong><br /><a href="${Chat.escapeHTML(entryUrl)}">${Chat.escapeHTML(entryTitle)}</a>`;
|
|
if (id) {
|
|
getCardDetails(subdomain, id).then(card => {
|
|
let thumb = Dex.getString(card.thumbnail);
|
|
if (thumb) {
|
|
htmlReply = `<table><tr><td style="padding-right:5px;"><img src="${Chat.escapeHTML(thumb)}" width=80 height=115></td><td>${htmlReply}</td></tr></table>`;
|
|
}
|
|
if (!this.broadcasting) return this.sendReply(`|raw|<div class="infobox">${htmlReply}</div>`);
|
|
room.addRaw(`<div class="infobox">${htmlReply}</div>`).update();
|
|
}, () => {
|
|
if (!this.broadcasting) return this.sendReply(`|raw|<div class="infobox">${htmlReply}</div>`);
|
|
room.addRaw(`<div class="infobox">${htmlReply}</div>`).update();
|
|
});
|
|
} else {
|
|
if (!this.broadcasting) return this.sendReply(`|raw|<div class="infobox">${htmlReply}</div>`);
|
|
room.addRaw(`<div class="infobox">${htmlReply}</div>`).update();
|
|
}
|
|
}, err => {
|
|
if (!this.runBroadcast()) return;
|
|
|
|
if (err instanceof SyntaxError || err.message === 'Malformed data') {
|
|
if (!this.broadcasting) return this.sendReply(`Error: Something went wrong in the request: ${err.message}`);
|
|
return room.add(`Error: Something went wrong in the request: ${err.message}`).update();
|
|
} else if (err.message === 'Not found') {
|
|
if (!this.broadcasting) return this.sendReply('|raw|<div class="infobox">No results found.</div>');
|
|
return room.addRaw('<div class="infobox">No results found.</div>').update();
|
|
} else if (err.code === "ENOTFOUND") {
|
|
if (!this.broadcasting) return this.sendReply("Error connecting to the yugioh wiki.");
|
|
return room.add("Error connecting to the yugioh wiki.").update();
|
|
}
|
|
if (!this.broadcasting) return this.sendReply(`Error: ${err.message}`);
|
|
return room.add(`Error: ${err.message}`).update();
|
|
});
|
|
},
|
|
ptcg: function (target, room, user) {
|
|
if (!this.canBroadcast()) return;
|
|
if (room.id !== 'tcgtabletop') return this.errorReply("This command can only be used in the TCG & Tabletop room.");
|
|
let domain = 'bulbapedia.bulbagarden.net';
|
|
let query = `${target.trim()} (TCG)`;
|
|
|
|
mediawikiSearch(domain, query).then(data => {
|
|
if (!this.runBroadcast()) return;
|
|
let snippet = Dex.getString(data.snippet);
|
|
let page = Dex.getString(data.title);
|
|
if (snippet.startsWith('#REDIRECT')) {
|
|
let redir = /\[\[(.+)\]\]/.exec(snippet);
|
|
if (redir) page = redir[1];
|
|
}
|
|
let htmlReply = `<strong>Best result for ${Chat.escapeHTML(target)}:</strong><br /><a href="http://${domain}/wiki/${encodeURIComponent(page)}">${Chat.escapeHTML(page)}</a>`;
|
|
if (!this.broadcasting) return this.sendReply(`|raw|<div class="infobox">${htmlReply}</div>`);
|
|
room.addRaw(`<div class="infobox">${htmlReply}</div>`).update();
|
|
}, err => {
|
|
if (!this.runBroadcast()) return;
|
|
|
|
if (err instanceof SyntaxError || err.message === 'Malformed data') {
|
|
if (!this.broadcasting) return this.sendReply(`Error: Something went wrong in the request: ${err.message}`);
|
|
return room.add(`Error: Something went wrong in the request: ${err.message}`).update();
|
|
} else if (err.message === 'Not found') {
|
|
if (!this.broadcasting) return this.sendReply('|raw|<div class="infobox">No results found.</div>');
|
|
return room.addRaw('<div class="infobox">No results found.</div>').update();
|
|
} else if (err.code === "ENOTFOUND") {
|
|
if (!this.broadcasting) return this.sendReply("Error connecting to bulbapedia.");
|
|
return room.add("Error connecting to bulbapedia.").update();
|
|
}
|
|
if (!this.broadcasting) return this.sendReply(`Error: ${err.message}`);
|
|
return room.add(`Error: ${err.message}`).update();
|
|
});
|
|
},
|
|
};
|