"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getPlayerInteraction = exports.getPlayer = void 0; /*eslint prefer-const: "error"*/ const cheerio = __importStar(require("cheerio")); const https_1 = __importDefault(require("https")); const main_1 = require("./util/main"); const Lang = __importStar(require("./lang")); const uniteApiRegex = { //$1 = name, $2 = id ogtitle: /unite api - (.+) \((.*)\)/i, //$1 = level, $2 = rank, $3 = elo/class (rest is found by splitting each line) ogdescription: [ /lv\.(\d+) (\w+) \((\d+)\)/i, /lv\.(\d+) (\w+): class (\d+)/i //other ] }; /** * gets the html of the uniteApi page for the player * @param name name of player * @returns the html of the page through a promise (rejects if the page status is not 200) */ function getHTML(name) { //name = name.replace(/[^\w\d]/g, ''); return new Promise((resolve, reject) => { const init = { host: 'uniteapi.dev', path: `/p/${encodeURIComponent(name)}`, method: 'GET', }; const callback = (response) => { if (response.statusCode !== 200) { reject(`HTTP ERROR ${response.statusCode}: ${response.statusMessage}`); return; } let result = Buffer.alloc(0); response.on('data', chunk => { result = Buffer.concat([result, chunk]); }); response.on('end', () => { resolve(result.toString()); }); }; const req = https_1.default.request(init, callback); req.end(); }); } /** * interprets the html from getHTML() * @param name name of player * @returns player data from site * @throws errorMessage class if the request fails */ function readHTML(html) { const $ = cheerio.load(html), foundData = { name: '', id: '', avatar: '', level: '', rank: '', elo: null, class: null, battles: '', wins: '', winrate: '' }; let metaElems = $('meta').toArray(); //filter down to just ones named "og:..." metaElems = metaElems.filter(el => el.attribs.property?.startsWith('og:')); metaElems.forEach(el => { const attr = el.attribs; if (attr.property === 'og:title') { const data = uniteApiRegex.ogtitle.exec(attr.content); if (data !== null && data.length >= 3) { foundData.name = data[1]; foundData.id = data[2]; } } else if (attr.property === 'og:description') { //all lines let lines = attr.content.split('\n').map(l => l.trim()); const extraLines = []; //ensure first line is correct while ((lines.length > 0) && !/pok.mon unite/i.test(lines[0])) { const line = lines.shift(); if (line !== undefined) extraLines.push(line); } if (lines.length === 0) throw (0, main_1.emsg)('Unable to read data, please try again'); //bring the first lines removed back into the data lines = [ ...lines, ...extraLines.filter(d => d) ]; //first line { //will be only text after "pokemon unite:" const line = lines[0].split(':').slice(1).join(':').trim(), regex = uniteApiRegex.ogdescription; if (regex[0].test(line)) { //is master/has elo const regexData = line.match(regex[0]); if (!regexData || regexData.length < 4) throw (0, main_1.emsg)('Unable to read data, please try again'); foundData.level = regexData[1]; foundData.rank = regexData[2]; foundData.elo = regexData[3]; } else { //is not master/has a class const regexData = line.match(regex[1]); if (!regexData || regexData.length < 4) throw (0, main_1.emsg)('Unable to read data, please try again'); foundData.level = regexData[1]; foundData.rank = regexData[2]; foundData.class = regexData[3]; } } lines.shift(); //rest of lines lines.forEach(line => { const split = line.split(':').map(l => l.trim()), key = split[0].toLowerCase().replace(/[^\w]/g, ''), value = split[1]; switch (key) { case 'battles': foundData.battles = value; break; case 'wins': foundData.wins = value; break; case 'winrate': foundData.winrate = value; break; } }); } }); const imgSrc = $('.player-card-image img').attr('src'); foundData.avatar = imgSrc !== undefined ? imgSrc : ''; foundData.avatar = foundData.avatar.replace('../', 'https://uniteapi.dev/'); return foundData; } /** * verifies the data * @param data uniteApi data * @returns boolean, valid or invalid */ function verifyData(data) { if (data.id.length > 0) return true; return false; } /** * gets player data from uniteApi * @param name name of player * @returns player data */ async function getPlayer(name) { const html = await getHTML(name), data = readHTML(html); if (verifyData(data)) return data; return null; } exports.getPlayer = getPlayer; async function sendPlayerEmbed(interaction, data) { let eloStr; if (data.elo !== null) eloStr = `(${data.elo})`; else eloStr = `Class ${data.class}`; await interaction.editReply(Lang.getEmbed('api.player', { name: data.name, id: data.id, nameEncoded: encodeURIComponent(data.name), avatar: data.avatar, level: data.level, rank: data.rank, elo: eloStr, battles: data.battles, wins: data.wins, winrate: data.winrate })); } /** * calls getPlayer() with the name from the interaction * @param interaction discord interaction * @throws errorMessage class if the user cannot be found */ async function getPlayerInteraction(interaction) { const username = interaction.options.getString('username', true); await interaction.deferReply(); const data = await getPlayer(username); if (data === null) throw (0, main_1.emsg)('api.noUser'); else sendPlayerEmbed(interaction, data); } exports.getPlayerInteraction = getPlayerInteraction;