UNPKG

@dota2classic/steam-market

Version:
580 lines (579 loc) 25.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const axios_1 = __importDefault(require("axios")); const proxy_string_parser_1 = __importDefault(require("proxy-string-parser")); const currency_codes_1 = __importDefault(require("currency-codes")); const iso_639_1_1 = __importDefault(require("iso-639-1")); const ECurrencyCode_js_1 = require("./types/ECurrencyCode.js"); class SteamMarket { server; sessionId = ''; currency = ECurrencyCode_js_1.ECurrencyCode.USD; digits = 2; units = 100; country = 'US'; language = 'english'; vanityURL = ''; constructor(options) { const { additionalHeaders, httpProxy, socksProxy } = options ?? {}; const proxy = httpProxy ?? socksProxy; if ((httpProxy != null) && (socksProxy != null)) { throw new Error('Cannot specify both socksProxy and httpProxy options'); } this.server = axios_1.default.create({ baseURL: 'https://steamcommunity.com/market', headers: { Host: 'steamcommunity.com', Accept: 'text/html,*/*;q=0.9', 'Accept-Encoding': 'gzip,identity,*;q=0', 'Accept-Charset': 'ISO-8859-1,utf-8,*;q=0.7', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36', ...additionalHeaders }, proxy: (proxy != null) ? (0, proxy_string_parser_1.default)(proxy) : false }); } processAsset(asset) { return { currency: asset.currency, appId: asset.appid, contextId: Number(asset.contextid), id: Number(asset.id), classId: Number(asset.classid), instanceId: Number(asset.instanceid), amount: Number(asset.amount), status: asset.status, originalAmount: Number(asset.original_amount), unownedId: Number(asset.unowned_id), unownedContextId: Number(asset.unowned_contextid), backgroundColor: asset.background_color, iconUrl: asset.icon_url, iconUrlLarge: asset.icon_url_large, descriptions: asset.descriptions, tradable: Boolean(asset.tradable), actions: asset.actions, ownerDescriptions: asset.owner_descriptions, ownerActions: asset.owner_actions, fraudWarnings: asset.fraudwarnings, name: asset.name, nameColor: asset.name_color, type: asset.type, marketName: asset.market_name, marketHashName: asset.market_hash_name, marketFee: asset.market_fee, marketFeeApp: asset.market_fee_app, containedItem: asset.contained_item, marketActions: asset.market_actions, commodity: Boolean(asset.commodity), marketTradableRestriction: asset.market_tradable_restriction, marketMarketableRestriction: asset.market_marketable_restriction, marketable: Boolean(asset.marketable), tags: asset.tags, itemExpiration: asset.item_expiration, marketBuyCountryRestriction: asset.market_buy_country_restriction, marketSellCountryRestriction: asset.market_sell_country_restriction, appIcon: asset.app_icon, owner: Boolean(asset.owner) }; } processAssets(assets) { const array = []; Object.values(assets).forEach((i) => { Object.values(i).forEach((j) => { Object.values(j).forEach((k) => { array.push(this.processAsset(k)); }); }); }); return array; } processListing(listing) { return { listingId: listing.listingid, timeCreated: listing.time_created, asset: this.processAsset(listing.asset), steamIdLister: Number(listing.steamid_lister), price: listing.price, originalPrice: listing.original_price, fee: listing.fee, currencyId: Number(listing.currencyid), convertedPrice: listing.converted_price, convertedFee: listing.converted_fee, convertedCurrencyId: Number(listing.converted_currencyid), status: listing.status, active: listing.active, steamFee: listing.steam_fee, convertedSteamFee: listing.converted_steam_fee, publisherFee: listing.publisher_fee, convertedPublisherFee: listing.converted_publisher_fee, publisherFeePercent: Number(listing.publisher_fee_percent), publisherFeeApp: listing.publisher_fee_app, cancelReason: listing.cancel_reason, itemExpired: listing.item_expired, originalAmountListed: listing.original_amount_listed, originalPricePerUnit: listing.original_price_per_unit, feePerUnit: listing.fee_per_unit, steamFeePerUnit: listing.steam_fee_per_unit, publisherFeePerUnit: listing.publisher_fee_per_unit, convertedPricePerUnit: listing.converted_price_per_unit, convertedFeePerUnit: listing.converted_fee_per_unit, convertedSteamFeePerUnit: listing.converted_steam_fee_per_unit, convertedPublisherFeePerUnit: listing.converted_publisher_fee_per_unit, timeFinishHold: listing.time_finish_hold, timeCreatedStr: listing.time_created_str }; } setCookies(cookies) { const sessionId = cookies.find((cookie) => cookie.split('=')[0] === 'sessionid'); if (sessionId == null) { throw new Error('Invalid cookies value'); } this.sessionId = sessionId.split('=')[1]; this.server.defaults.headers.common.Cookie = cookies.join('; '); } setCurrency(currency) { const info = currency_codes_1.default.code(ECurrencyCode_js_1.ECurrencyCode[currency]); if (info == null) { throw new Error('Invalid currency value'); } this.units = Number(`1${'0'.repeat(info.digits)}`); this.digits = info.digits; this.currency = currency; } setCountry(country) { const language = iso_639_1_1.default.getName(country.toLowerCase()); if (language === '') { throw new Error('Invalid country value'); } this.language = language.toLowerCase(); this.country = country; } setVanityURL(vanityURL) { this.vanityURL = vanityURL; } getCookies() { return this.server.defaults.headers.common.Cookie?.toString().split('; ') ?? []; } getSessionId() { return this.sessionId; } getCurrency() { return this.currency; } getDigits() { return this.digits; } getUnits() { return this.units; } getCountry() { return this.country; } getLanguage() { return this.language; } getVanityURL() { return this.vanityURL; } async search(appId, options) { const { query, start, count, searchDescriptions, sortColumn, sortDir } = options ?? {}; const response = await this.server.get('/search/render', { params: { query: query ?? '', start: start ?? '0', count: count ?? '100', search_descriptions: (searchDescriptions === true) ? '1' : '0', sort_column: sortColumn ?? 'popular', sort_dir: sortDir ?? 'desc', appid: appId, norender: '1' }, headers: { Referer: `https://steamcommunity.com/market/search?appid=${appId}`, 'X-Prototype-Version': '1.7', 'X-Requested-With': 'XMLHttpRequest' } }); return { _data: response.data, success: response.data.success, start: response.data.start, pageSize: response.data.pagesize, totalCount: response.data.total_count, searchData: { query: response.data.searchdata.query, searchDescriptions: response.data.searchdata.search_descriptions, totalCount: response.data.searchdata.total_count, pageSize: response.data.searchdata.pagesize, prefix: response.data.searchdata.prefix, classPrefix: response.data.searchdata.class_prefix }, results: response.data.results.map((result) => ({ name: result.name, hashName: result.hash_name, sellListings: result.sell_listings, sellPrice: result.sell_price, sellPriceText: result.sell_price_text, appIcon: result.app_icon, appName: result.app_name, assetDescription: { appId: result.asset_description.appid, classId: result.asset_description.classid, instanceId: result.asset_description.instanceid, backgroundColor: result.asset_description.background_color, iconUrl: result.asset_description.icon_url, tradable: Boolean(result.asset_description.tradable), name: result.asset_description.name, nameColor: result.asset_description.name_color, type: result.asset_description.type, marketName: result.asset_description.market_name, marketHashName: result.asset_description.market_hash_name, commodity: Boolean(result.asset_description.commodity) }, salePriceText: result.sale_price_text })) }; } async listings(appId, marketHashName) { const response = await this.server.get(`/listings/${appId}/${marketHashName}`, { headers: { Cookie: this.getCookies().filter((cookie) => cookie.split('=')[0] === 'steamLogin').join('; '), Referer: `https://steamcommunity.com/market/search?appid=${appId}` } }); return { _data: response.data, async itemNameId() { const self = await this; const startString = 'Market_LoadOrderSpread('; const endString = ')'; const startPosition = self._data.indexOf(startString, 0); const endPosition = self._data.indexOf(endString, startPosition); if (startPosition === -1 || endPosition === -1) { throw new Error('Value itemNameId not found'); } const itemNameId = self._data.slice(startPosition + startString.length, endPosition).trim(); return Number(itemNameId); }, async priceHistory() { const self = await this; const startString = 'line1='; const endString = ';'; const startPosition = self._data.indexOf(startString, 0); const endPosition = self._data.indexOf(endString, startPosition); if (startPosition === -1 || endPosition === -1) { throw new Error('Value prices not found'); } const slice = self._data.slice(startPosition + startString.length, endPosition).trim(); const json = JSON.parse(slice); const prices = json.map((price) => ({ datetime: price[0], price: price[1], volume: Number(price[2]) })); const prefixStartString = 'strFormatPrefix = "'; const prefixEndString = '";'; const prefixStartPosition = self._data.indexOf(prefixStartString, 0); const prefixEndPosition = self._data.indexOf(prefixEndString, prefixStartPosition); const suffixStartString = 'strFormatSuffix = "'; const suffixEndString = '";'; const suffixStartPosition = self._data.indexOf(suffixStartString, 0); const suffixEndPosition = self._data.indexOf(suffixEndString, suffixStartPosition); if ((prefixStartPosition === -1 || prefixEndPosition === -1) || (suffixStartPosition === -1 || suffixEndPosition === -1)) { throw new Error('Value pricePrefix not found'); } const pricePrefix = self._data.slice(prefixStartPosition + prefixStartString.length, prefixEndPosition).trim(); const priceSuffix = self._data.slice(suffixStartPosition + suffixStartString.length, suffixEndPosition).trim(); return { _data: self._data, success: true, pricePrefix, priceSuffix, prices }; } }; } async itemOrdersHistogram(appId, marketHashName, itemNameId) { const response = await this.server.get('/itemordershistogram', { params: { country: this.country, language: this.language, currency: this.currency, item_nameid: itemNameId, two_factor: '0' }, headers: { Referer: `https://steamcommunity.com/market/listings/${appId}/${encodeURIComponent(marketHashName)}`, 'X-Requested-With': 'XMLHttpRequest' } }); return { _data: response.data, success: Boolean(response.data.success), sellOrderTable: response.data.sell_order_table, sellOrderSummary: response.data.sell_order_summary, buyOrderTable: response.data.buy_order_table, buyOrderSummary: response.data.buy_order_summary, highestBuyOrder: Number((Number(response.data.highest_buy_order) / this.units).toFixed(this.digits)), lowestSellOrder: Number((Number(response.data.lowest_sell_order) / this.units).toFixed(this.digits)), buyOrderGraph: response.data.buy_order_graph.map((buyOrder) => ({ price: buyOrder[0], volume: buyOrder[1], description: buyOrder[2] })), sellOrderGraph: response.data.sell_order_graph.map((sellOrder) => ({ price: sellOrder[0], volume: sellOrder[1], description: sellOrder[2] })), graphMaxY: response.data.graph_max_y, graphMinX: response.data.graph_min_x, graphMaxX: response.data.graph_max_x, pricePrefix: response.data.price_prefix, priceSuffix: response.data.price_suffix }; } async priceOverview(appId, marketHashName) { const response = await this.server.get('/priceoverview', { params: { appid: appId, currency: this.currency, market_hash_name: marketHashName }, headers: { Referer: `https://steamcommunity.com/id/${this.vanityURL}/inventory?modal=1&market=1`, 'X-Prototype-Version': '1.7', 'X-Requested-With': 'XMLHttpRequest' } }); return { _data: response.data, success: response.data.success, lowestPrice: response.data.lowest_price, volume: Number(response.data.volume.split(',').join('')), medianPrice: response.data.median_price }; } async priceHistory(appId, marketHashName) { const response = await this.server.get('/pricehistory', { params: { appid: appId, currency: this.currency, market_hash_name: marketHashName }, headers: { Referer: `https://steamcommunity.com/id/${this.vanityURL}/inventory?modal=1&market=1`, 'X-Prototype-Version': '1.7', 'X-Requested-With': 'XMLHttpRequest' } }); return { _data: response.data, success: response.data.success, pricePrefix: response.data.price_prefix, priceSuffix: response.data.price_suffix, prices: response.data.prices.map((price) => ({ datetime: price[0], price: price[1], volume: Number(price[2]) })) }; } async myListings(start, count) { const response = await this.server.get('/mylistings', { params: { start: start ?? '0', count: count ?? '100', norender: '1' }, headers: { Referer: 'https://steamcommunity.com/market', 'X-Prototype-Version': '1.7', 'X-Requested-With': 'XMLHttpRequest' } }); return { _data: response.data, success: response.data.success, pageSize: response.data.pagesize, totalCount: response.data.total_count, assets: this.processAssets(response.data.assets), start: response.data.start, numActiveListings: response.data.num_active_listings, listings: response.data.listings.map((listing) => this.processListing(listing)), listingsOnHold: response.data.listings_on_hold.map((listing) => this.processListing(listing)), listingsToConfirm: response.data.listings_to_confirm.map((listing) => this.processListing(listing)), buyOrders: response.data.buy_orders.map((buyOrder) => ({ appId: buyOrder.appid, hashName: buyOrder.hash_name, walletCurrency: buyOrder.wallet_currency, price: Number(buyOrder.price), quantity: Number(buyOrder.quantity), quantityRemaining: Number(buyOrder.quantity_remaining), buyOrderId: Number(buyOrder.buy_orderid), description: this.processAsset(buyOrder.description) })) }; } async myHistory(start, count) { const response = await this.server.get('/myhistory', { params: { start: start ?? '0', count: count ?? '100', norender: '1' }, headers: { Referer: 'https://steamcommunity.com/market', 'X-Prototype-Version': '1.7', 'X-Requested-With': 'XMLHttpRequest' } }); return { _data: response.data, success: response.data.success, pageSize: response.data.pagesize, totalCount: response.data.total_count, start: response.data.start, assets: this.processAssets(response.data.assets), events: response.data.events.map((event) => ({ listingId: Number(event.listingid), purchaseId: Number(event.purchaseid), eventType: event.event_type, timeEvent: event.time_event, timeEventFraction: event.time_event_fraction, steamIdActor: Number(event.steamid_actor), dateEvent: event.date_event })), purchases: Object.values(response.data.purchases).map((purchase) => ({ listingId: Number(purchase.listingid), purchaseId: Number(purchase.purchaseid), timeSold: purchase.time_sold, steamIdPurchaser: Number(purchase.steamid_purchaser), needsRollback: purchase.needs_rollback, failed: purchase.failed, asset: this.processAsset(purchase.asset), paidAmount: purchase.paid_amount, paidFee: purchase.paid_fee, currencyId: Number(purchase.currencyid), steamFee: purchase.steam_fee, publisherFee: purchase.publisher_fee, publisherFeePercent: Number(purchase.publisher_fee_percent), publisherFeeApp: purchase.publisher_fee_app, receivedAmount: purchase.received_amount, receivedCurrencyId: Number(purchase.received_currencyid), fundsReturned: purchase.funds_returned, avatarActor: purchase.avatar_actor, personaActor: purchase.persona_actor, fundsHeld: purchase.funds_held, timeFundsHeldUntil: purchase.time_funds_held_until, fundsRevoked: purchase.funds_revoked })), listings: Object.values(response.data.listings).map((listing) => this.processListing(listing)) }; } async createBuyOrder(appId, options) { const { marketHashName, price, amount } = options; const response = await this.server.post('/createbuyorder', { sessionid: this.sessionId, currency: this.currency, appid: appId, market_hash_name: marketHashName, price_total: Number((price * amount) / this.units).toFixed(this.digits), quantity: amount, billing_state: '', save_my_address: '0' }, { headers: { Referer: `https://steamcommunity.com/market/listings/${appId}/${encodeURIComponent(marketHashName)}`, Origin: 'https://steamcommunity.com', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' } }); return { _data: response.data, success: Boolean(response.data.success), buyOrderId: Number(response.data.buy_orderid) }; } async createSellOrder(appId, options) { const { assetId, contextId, price, amount } = options; const response = await this.server.post('/sellitem', { sessionid: this.sessionId, appid: appId, contextid: contextId, assetid: assetId, amount, price: Number((price * this.units).toFixed(this.digits)) }, { headers: { Referer: `https://steamcommunity.com/id/${this.vanityURL}/inventory?modal=1&market=1`, Origin: 'https://steamcommunity.com', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' } }); return { _data: response.data, success: response.data.success, requiresConfirmation: Boolean(response.data.requires_confirmation), needsMobileConfirmation: response.data.needs_mobile_confirmation, needsEmailConfirmation: response.data.needs_email_confirmation, emailDomain: response.data.email_domain }; } async buyOrderStatus(appId, marketHashName, buyOrderId) { const response = await this.server.get('/getbuyorderstatus', { params: { sessionid: this.sessionId, buy_orderid: buyOrderId }, headers: { Referer: `https://steamcommunity.com/market/listings/${appId}/${encodeURIComponent(marketHashName)}`, 'X-Requested-With': 'XMLHttpRequest' } }); return { _data: response.data, success: Boolean(response.data.success), active: Boolean(response.data.active), purchased: response.data.purchased, quantity: response.data.quantity, quantityRemaining: response.data.quantity_remaining, purchases: response.data.purchases }; } async cancelBuyOrder(buyOrderId) { const response = await this.server.post('/cancelbuyorder', { sessionid: this.sessionId, buy_orderid: buyOrderId }, { headers: { Referer: 'https://steamcommunity.com/market', Origin: 'https://steamcommunity.com', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'X-Prototype-Version': '1.7', 'X-Requested-With': 'XMLHttpRequest' } }); return response.data; } async cancelSellOrder(listingId) { const response = await this.server.post(`/removelisting/${listingId}`, { sessionid: this.sessionId }, { headers: { Referer: 'https://steamcommunity.com/market', Origin: 'https://steamcommunity.com', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'X-Prototype-Version': '1.7', 'X-Requested-With': 'XMLHttpRequest' } }); return response.data; } } exports.default = SteamMarket;