UNPKG

warframe-nexus-query

Version:

Query prices form nexus-stats.com and warframe.market.

166 lines (146 loc) 5.26 kB
/** * Summary model for v2 API * Compatible with v1 Summary but with v2 data structures */ import { ASSETS_BASE_URL } from '../constants.js'; export default class SummaryV2 { /** * Create a summary from v2 Item and Order data * @param {Item} item - Item object * @param {Object} orders - Orders object with { buy, sell } * @param {Object} statistics - Statistics object with { buy, sell } */ constructor(item, orders, statistics) { // Basic item info this.name = item.name; this.slug = item.slug; this.thumbnail = item.getThumbUrl(ASSETS_BASE_URL); this.partThumb = item.subIcon ? `${ASSETS_BASE_URL}${item.subIcon}` : this.thumbnail; this.icon = item.getIconUrl(ASSETS_BASE_URL); // Item metadata this.tradingTax = item.tradingTax || 0; this.ducats = item.ducats || 0; this.vosfor = item.vosfor || 0; this.masteryLevel = item.reqMasteryRank; this.tradable = item.tradable; this.vaulted = item.vaulted; // Links and descriptions this.wikiUrl = item.wikiLink; this.description = item.description || ''; this.codex = this.description; // v1 compatibility this.url = `https://warframe.market/items/${item.slug}`; // Tags this.tags = item.tags || []; // Prices and statistics (from v2 orders) this.prices = { soldCount: statistics.sell.orderCount, soldPrice: statistics.sell.median, minimum: statistics.sell.min, maximum: statistics.sell.max, average: statistics.sell.avg, volume: statistics.sell.volume, }; // Store full orders and statistics this.orders = orders; this.statistics = statistics; // Type marker this.type = 'market-v2'; } /** * Get best online sellers * @param {number} limit - Number of sellers to return * @returns {Array<{ingameName: string, platinum: number, quantity: number, status: string, activity: string}>} */ getOnlineSellers(limit = 5) { return this.orders.sell .filter((order) => order.isUserOnline()) .slice(0, limit) .map((order) => ({ ingameName: order.user.ingameName, platinum: order.platinum, quantity: order.quantity, status: order.user.status, activity: order.user.getActivityDescription(), reputation: order.user.reputation, platform: order.user.platform, crossplay: order.user.crossplay, })); } /** * Get best online buyers * @param {number} limit - Number of buyers to return * @returns {Array<{ingameName: string, platinum: number, quantity: number, status: string, activity: string}>} */ getOnlineBuyers(limit = 5) { return this.orders.buy .filter((order) => order.isUserOnline()) .slice(0, limit) .map((order) => ({ ingameName: order.user.ingameName, platinum: order.platinum, quantity: order.quantity, status: order.user.status, activity: order.user.getActivityDescription(), reputation: order.user.reputation, platform: order.user.platform, crossplay: order.user.crossplay, })); } /** * String representation (v1 compatible) * @param {string} opt - Option: 'codex', 'item', 'location', 'all' * @returns {string} */ toString(opt = 'item') { let value = `**${this.name}**\n`; if (opt === 'codex' || opt === 'all') { value += `\`\`\`\nCodex: ${this.codex}\n\`\`\`\n`; } if (opt === 'item' || opt === 'all') { value += '```\n'; if (this.masteryLevel) { value += `Requires: MR ${this.masteryLevel} | `; } value += `Tax: ${this.tradingTax}cr\n`; value += `Item is ${this.tradable ? '' : 'not '}tradable`; if (this.vaulted) { value += ' (VAULTED)'; } value += '\n\n'; // Sell statistics value += `${this.prices.soldCount} sellers (${this.prices.volume} items)\n`; value += `Median: ${this.prices.soldPrice}p | `; value += `Range: ${this.prices.minimum}p - ${this.prices.maximum}p\n`; // Buy statistics (if available) if (this.statistics.buy.orderCount > 0) { value += `\n${this.statistics.buy.orderCount} buyers\n`; value += `Median: ${this.statistics.buy.median}p | `; value += `Range: ${this.statistics.buy.min}p - ${this.statistics.buy.max}p\n`; } value += '```\n'; } if (opt === 'traders' || opt === 'all') { const sellers = this.getOnlineSellers(3); if (sellers.length > 0) { value += '\n**Online Sellers:**\n'; sellers.forEach((seller) => { const statusEmoji = seller.status === 'ingame' ? '🎮' : '🟢'; const activity = seller.activity ? ` (${seller.activity})` : ''; value += `${statusEmoji} ${seller.ingameName} - ${seller.platinum}p x${seller.quantity}${activity}\n`; }); } } value += `\n${this.wikiUrl || this.url}`; return value; } /** * Padding helper (v1 compatibility) * @param {string} str - String to pad * @param {number} length - Target length * @param {string} character - Padding character * @returns {string} */ pad(str, length = 10, character = ' ') { return str.padEnd(length, character); } }