poe-js-sdk
Version:
TypeScript SDK for the Path of Exile API
2 lines (1 loc) • 18.1 kB
JavaScript
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("axios");class f extends Error{constructor(t,e){super(t),this.name="PoEApiError",this.code=e.code??void 0,this.status=e.status,this.url=e.url??void 0,this.details=e.details,this.headers=e.headers??void 0}}class m{constructor(t){if(this.rateLimitInfo={},this.nextAvailableAt=0,!t.userAgent?.startsWith("OAuth ")||!/\(contact: .+\)/.test(t.userAgent))throw new Error('User-Agent must start with "OAuth " and include a contact: e.g. "OAuth myapp/1.0.0 (contact: you@example.com)"');this.client=d.create({baseURL:t.baseURL||"https://api.pathofexile.com",headers:{"User-Agent":t.userAgent,...t.accessToken&&{Authorization:`Bearer ${t.accessToken}`}}}),this.client.interceptors?.request?.use&&this.client.interceptors.request.use(async e=>{const s=Date.now();if(this.nextAvailableAt>s){const i=this.nextAvailableAt-s;await new Promise(r=>setTimeout(r,i))}return e}),this.client.interceptors.response.use(e=>(this.updateRateLimitInfo(e),this.updateWaitFromHeaders(e),e),e=>{if(e.response){if(this.updateRateLimitInfo(e.response),this.updateWaitFromHeaders(e.response),e.response.status===429){const i=e.response.headers["retry-after"],r=i?Number.parseInt(i):0;!Number.isNaN(r)&&r>0&&(this.nextAvailableAt=Date.now()+r*1e3)}const s=e.response.data;if(s&&typeof s=="object"&&"error"in s&&s.error){const i=s.error,r=e.response.status,a=e.config?.url,o=e.response.headers,c={status:r,details:s,headers:o};throw a&&(c.url=a),typeof i.code=="number"&&(c.code=i.code),new f(i.message||"API error",c)}}throw e})}updateRateLimitInfo(t){const e=t.headers,s=e["retry-after"],i={};e["x-rate-limit-policy"]&&(i.policy=e["x-rate-limit-policy"]),e["x-rate-limit-rules"]&&(i.rules=e["x-rate-limit-rules"]),e["x-rate-limit-account"]&&(i.account=e["x-rate-limit-account"]),e["x-rate-limit-ip"]&&(i.ip=e["x-rate-limit-ip"]),e["x-rate-limit-client"]&&(i.client=e["x-rate-limit-client"]),e["x-rate-limit-account-state"]&&(i.accountState=e["x-rate-limit-account-state"]),e["x-rate-limit-ip-state"]&&(i.ipState=e["x-rate-limit-ip-state"]),e["x-rate-limit-client-state"]&&(i.clientState=e["x-rate-limit-client-state"]),s&&(i.retryAfter=Number.parseInt(s)),this.rateLimitInfo=i}getRateLimitInfo(){return{...this.rateLimitInfo}}setAccessToken(t){this.client.defaults.headers.Authorization=`Bearer ${t}`}updateWaitFromHeaders(t){const e=t.headers,s=[e["x-rate-limit-account-state"],e["x-rate-limit-ip-state"],e["x-rate-limit-client-state"]].filter(Boolean);for(const i of s){const r=String(i).split(",");for(const a of r){const o=a.split(":");if(o.length===3){const c=Number.parseInt(o[2]??"0");if(!Number.isNaN(c)&&c>0){const h=Date.now()+c*1e3;h>this.nextAvailableAt&&(this.nextAvailableAt=h)}}}}}async getProfile(){return(await this.client.get("/profile")).data}async getLeagues(t){const e=typeof t=="string"||t===void 0?{realm:t}:t,s={};return e?.realm&&(s.realm=e.realm),e&&"type"in e&&e.type&&(s.type=e.type),e&&"season"in e&&e.season&&(s.season=e.season),e&&"limit"in e&&e.limit!==void 0&&(s.limit=e.limit),e&&"offset"in e&&e.offset!==void 0&&(s.offset=e.offset),(await this.client.get("/league",{params:s})).data}async getLeague(t,e){const s=e?{realm:e}:{};return(await this.client.get(`/league/${t}`,{params:s})).data}async getLeagueLadder(t,e){const s={};return e?.realm&&(s.realm=e.realm),e?.offset!==void 0&&(s.offset=e.offset),e?.limit!==void 0&&(s.limit=e.limit),e?.sort&&(s.sort=e.sort),e?.class&&e.sort==="class"&&(s.class=e.class),(await this.client.get(`/league/${t}/ladder`,{params:s})).data}async getLeagueEventLadder(t,e){const s={};return e?.realm&&(s.realm=e.realm),e?.offset!==void 0&&(s.offset=e.offset),e?.limit!==void 0&&(s.limit=e.limit),(await this.client.get(`/league/${t}/event-ladder`,{params:s})).data}async getCharacters(t){const e=t?`/character/${t}`:"/character";return(await this.client.get(e)).data}async getCharacter(t,e){const s=e?`/character/${e}/${t}`:`/character/${t}`;return(await this.client.get(s)).data}async getStashes(t,e){const s=e?`/stash/${e}/${t}`:`/stash/${t}`;return(await this.client.get(s)).data}async getStash(t,e,s,i){const r=i?`/stash/${i}/${t}`:`/stash/${t}`,a=s?`${r}/${e}/${s}`:`${r}/${e}`;return(await this.client.get(a)).data}async getLeagueAccount(t,e){const s=e?`/league-account/${e}/${t}`:`/league-account/${t}`;return(await this.client.get(s)).data}async getPvpMatches(t){const e=typeof t=="string"||t===void 0?{realm:t}:t,s={};return e?.realm&&(s.realm=e.realm),e&&"type"in e&&e.type&&(s.type=e.type),e&&"season"in e&&e.season&&(s.season=e.season),e&&"league"in e&&e.league&&(s.league=e.league),(await this.client.get("/pvp-match",{params:s})).data}async getPvpMatch(t,e){const s=e?{realm:e}:{};return(await this.client.get(`/pvp-match/${t}`,{params:s})).data}async getPvpMatchLadder(t,e){const s={};return e?.realm&&(s.realm=e.realm),e?.limit!==void 0&&(s.limit=e.limit),e?.offset!==void 0&&(s.offset=e.offset),(await this.client.get(`/pvp-match/${t}/ladder`,{params:s})).data}async getPublicStashes(t){const e=t?.realm?`/public-stash-tabs/${t.realm}`:"/public-stash-tabs",s=t?.id?{id:t.id}:{};return(await this.client.get(e,{params:s})).data}async getCurrencyExchange(t,e){let s="/currency-exchange";return t&&(s+=`/${t}`),e&&(s+=`/${e}`),(await this.client.get(s)).data}async getItemFilters(){return(await this.client.get("/item-filter")).data}async getItemFilter(t){return(await this.client.get(`/item-filter/${t}`)).data}async createItemFilter(t,e){return(await this.client.post("/item-filter",t,{params:e?.validate?{validate:!0}:{}})).data}async updateItemFilter(t,e,s){return(await this.client.post(`/item-filter/${t}`,e,{params:s?.validate?{validate:!0}:{}})).data}async getAccountLeagues(t){const e=t?{realm:t}:{};return(await this.client.get("/account/leagues",{params:e})).data}async getGuildStashes(t,e){const s=e?`/guild/${e}/stash/${t}`:`/guild/stash/${t}`;return(await this.client.get(s)).data}async getGuildStash(t,e,s,i){const r=i?`/guild/${i}/stash/${t}`:`/guild/stash/${t}`,a=s?`${r}/${e}/${s}`:`${r}/${e}`;return(await this.client.get(a)).data}}class y{constructor(t){if(t.userAgent&&(!t.userAgent.startsWith("OAuth ")||!/\(contact: .+\)/.test(t.userAgent)))throw new Error('User-Agent must start with "OAuth " and include a contact: e.g. "OAuth myapp/1.0.0 (contact: you@example.com)"');this.client=d.create({baseURL:t.baseURL||"https://www.pathofexile.com/api/trade2",headers:{"Content-Type":"application/json","User-Agent":t.userAgent||"OAuth poe-js-sdk/1.0.0 (contact: change-me@example.com)",Cookie:`POESESSID=${t.poesessid}`,Accept:"*/*",Connection:"keep-alive"}})}async search(t,e,s="pc"){const i=`/search/${s}/${t}`;return(await this.client.post(i,e)).data}async fetch(t,e){const i=`/fetch/${t.slice(0,10).join(",")}?query=${e}`;return(await this.client.get(i)).data}async searchAndFetch(t,e,s=10,i="pc"){const r=await this.search(t,e,i);if(r.result.length===0)return{search:r,items:{result:[]}};const a=await this.fetch(r.result.slice(0,s),r.id);return{search:r,items:a}}async getWhisper(t,e){const s=`/whisper/${t}?query=${e}`;return(await this.client.get(s)).data}}const p={},l=class l{static generatePKCE(){const t=p.randomBytes(32).toString("base64url"),e=p.createHash("sha256").update(t).digest("base64url");return{codeVerifier:t,codeChallenge:e}}static buildAuthUrl(t,e,s){const i=new URLSearchParams({client_id:t.clientId,response_type:"code",redirect_uri:t.redirectUri,scope:t.scopes.join(" "),state:e});return s&&(i.append("code_challenge",s.codeChallenge),i.append("code_challenge_method","S256")),`${this.AUTH_URL}?${i.toString()}`}static async exchangeCodeForToken(t,e,s){const i=new URLSearchParams({client_id:t.clientId,grant_type:"authorization_code",code:e,redirect_uri:t.redirectUri});t.clientSecret&&i.append("client_secret",t.clientSecret),s&&i.append("code_verifier",s);const r=await fetch(this.TOKEN_URL,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:i});if(!r.ok)throw new Error(`Token exchange failed: ${r.statusText}`);return r.json()}static async refreshToken(t,e){const s=new URLSearchParams({client_id:t.clientId,grant_type:"refresh_token",refresh_token:e});t.clientSecret&&s.append("client_secret",t.clientSecret);const i=await fetch(this.TOKEN_URL,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:s});if(!i.ok)throw new Error(`Token refresh failed: ${i.statusText}`);return i.json()}static async getClientCredentialsToken(t){if(!t.clientSecret)throw new Error("Client secret is required for client_credentials grant");const e=new URLSearchParams({client_id:t.clientId,client_secret:t.clientSecret,grant_type:"client_credentials",scope:t.scopes.join(" ")}),s=await fetch(this.TOKEN_URL,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:e});if(!s.ok)throw new Error(`Client credentials failed: ${s.statusText}`);return s.json()}};l.AUTH_URL="https://www.pathofexile.com/oauth/authorize",l.TOKEN_URL="https://www.pathofexile.com/oauth/token";let u=l;class _{constructor(){this.query={query:{stats:[],status:{option:"online"},filters:{}}}}onlineOnly(t=!0){return this.query.query.status={option:t?"online":"any"},this}category(t){return this.query.query.filters?.type_filters||(this.query.query.filters.type_filters={filters:{}}),this.query.query.filters.type_filters.filters.category={option:t},this}rarity(t){return this.query.query.filters?.type_filters||(this.query.query.filters.type_filters={filters:{}}),this.query.query.filters.type_filters.filters.rarity={option:t},this}price(t,e,s){return this.query.query.filters?.trade_filters||(this.query.query.filters.trade_filters={filters:{}}),this.query.query.filters.trade_filters.filters.price={option:t,...e!==void 0&&{min:e},...s!==void 0&&{max:s}},this}account(t){return this.query.query.filters?.trade_filters||(this.query.query.filters.trade_filters={filters:{}}),this.query.query.filters.trade_filters.filters.account={input:t},this}andStats(t){const e={type:"and",filters:t.map(s=>({id:s.id,value:{...s.min!==void 0&&{min:s.min},...s.max!==void 0&&{max:s.max}},disabled:!1}))};return this.query.query.stats.push(e),this}orStats(t){const e={type:"or",filters:t.map(s=>({id:s.id,value:{...s.min!==void 0&&{min:s.min},...s.max!==void 0&&{max:s.max}},disabled:!1}))};return this.query.query.stats.push(e),this}weightedStats(t){const e={type:"weight2",filters:t.map(s=>({id:s.id,value:{weight:s.weight},disabled:!1}))};return this.query.query.stats.push(e),this}build(){return{...this.query}}reset(){return this.query={query:{stats:[],status:{option:"online"},filters:{}}},this}}const g={WEAPON_ONE_HAND_SWORD:"weapon.onesword",WEAPON_TWO_HAND_SWORD:"weapon.twosword",WEAPON_ONE_HAND_AXE:"weapon.oneaxe",WEAPON_TWO_HAND_AXE:"weapon.twoaxe",WEAPON_ONE_HAND_MACE:"weapon.onemace",WEAPON_TWO_HAND_MACE:"weapon.twomace",WEAPON_BOW:"weapon.bow",WEAPON_STAFF:"weapon.staff",WEAPON_WAND:"weapon.wand",WEAPON_DAGGER:"weapon.dagger",WEAPON_CLAW:"weapon.claw",ARMOUR_HELMET:"armour.helmet",ARMOUR_CHEST:"armour.chest",ARMOUR_BOOTS:"armour.boots",ARMOUR_GLOVES:"armour.gloves",ARMOUR_SHIELD:"armour.shield",ACCESSORY_RING:"accessory.ring",ACCESSORY_AMULET:"accessory.amulet",ACCESSORY_BELT:"accessory.belt",GEM_SKILL:"gem.activegem",GEM_SUPPORT:"gem.supportgem",CURRENCY:"currency"},E={CHAOS:"chaos",EXALTED:"exalted",DIVINE:"divine",MIRROR:"mirror",ANCIENT:"ancient",CHROMATIC:"chromatic",JEWELLER:"jeweller",FUSING:"fusing",ALCHEMY:"alchemy",CHISEL:"chisel"},A={CROSSBOW:"weapon.crossbow",FOCUS:"armour.focus",SPEAR:"weapon.spear",FLAIL:"weapon.flail",BUCKLER:"armour.buckler",RUNE_DAGGER:"weapon.runedagger",WARSTAFF:"weapon.warstaff",CLUSTER_JEWEL:"jewel.cluster",ABYSS_JEWEL:"jewel.abyss",HEIST_BLUEPRINT:"heistmission.blueprint",HEIST_CONTRACT:"heistmission.contract",HEIST_TOOL:"heistequipment.heisttool",HEIST_BROOCH:"heistequipment.heistreward",HEIST_GEAR:"heistequipment.heistweapon",HEIST_CLOAK:"heistequipment.heistutility",TRINKET:"accessory.trinket",SANCTUM_RELIC:"sanctum.relic",TINCTURE:"tincture",CHARM:"azmeri.charm"},w={GREATER_TRANSMUTE:"greater-orb-of-transmutation",PERFECT_TRANSMUTE:"perfect-orb-of-transmutation",GREATER_AUG:"greater-orb-of-augmentation",PERFECT_AUG:"perfect-orb-of-augmentation",GREATER_CHAOS:"greater-chaos-orb",PERFECT_CHAOS:"perfect-chaos-orb",CHAOS:"chaos",EXALTED:"exalted",DIVINE:"divine",MIRROR:"mirror",ANCIENT:"ancient",CHROMATIC:"chromatic",JEWELLER:"jeweller",FUSING:"fusing",ALCHEMY:"alchemy",CHISEL:"chisel"},R={LIFE:"explicit.stat_3299347043",ENERGY_SHIELD:"explicit.stat_2901986750",MANA:"explicit.stat_1050105434",FIRE_RES:"explicit.stat_4220027924",COLD_RES:"explicit.stat_3441501978",LIGHTNING_RES:"explicit.stat_1671376347",CHAOS_RES:"explicit.stat_2923486259",ALL_RES:"explicit.stat_3372524247",ADDED_PHYS_DAMAGE:"explicit.stat_1940865751",INCREASED_PHYS_DAMAGE:"explicit.stat_1509134228",ADDED_FIRE_DAMAGE:"explicit.stat_1334060246",ADDED_COLD_DAMAGE:"explicit.stat_2387423236",ADDED_LIGHTNING_DAMAGE:"explicit.stat_1754445556",ATTACK_SPEED:"explicit.stat_681332047",CAST_SPEED:"explicit.stat_2891184298",CRIT_CHANCE:"explicit.stat_587431675",CRIT_MULTI:"explicit.stat_3556824919",MOVEMENT_SPEED:"explicit.stat_2250533757"};function S(n){const t=[];for(const e of n){if(!e)continue;if(t.length===0){t.push({...e,listedTimes:1});continue}const s=t.find((i,r)=>i.listing.account.name===e.listing.account.name&&i.listing.price.currency===e.listing.price.currency&&i.listing.price.amount===e.listing.price.amount||i.listing.account.name===e.listing.account.name&&t.length-r<=2);s?(s.listedTimes+=1,s.priceRange||(s.priceRange={min:s.listing.price.amount,max:s.listing.price.amount}),s.priceRange.min=Math.min(s.priceRange.min,e.listing.price.amount),s.priceRange.max=Math.max(s.priceRange.max,e.listing.price.amount),s.averagePrice=(s.priceRange.min+s.priceRange.max)/2):t.push({...e,listedTimes:1})}return t}class T{constructor(){this.query={query:{stats:[],status:{option:"online"},filters:{}}}}pseudoStats(t){const e={type:"and",filters:t.map(s=>({id:`pseudo.${s.id}`,value:{...s.min!==void 0&&{min:s.min},...s.max!==void 0&&{max:s.max}},disabled:!1}))};return this.query.query.stats.push(e),this}totalResistance(t){return this.pseudoStats([{id:"pseudo.pseudo_total_elemental_resistance",min:t}])}totalLifeES(t){return this.pseudoStats([{id:"pseudo.pseudo_total_life",min:t}])}weaponDPS(t,e,s){const i=[];return t&&i.push({id:"pseudo.pseudo_physical_dps",min:t}),e&&i.push({id:"pseudo.pseudo_elemental_dps",min:e}),s&&i.push({id:"pseudo.pseudo_total_dps",min:s}),this.pseudoStats(i)}itemLevel(t,e){return this.query.query.filters?.misc_filters||(this.query.query.filters.misc_filters={filters:{}}),this.query.query.filters.misc_filters.filters.ilvl={...t!==void 0&&{min:t},...e!==void 0&&{max:e}},this}gemLevel(t,e){return this.query.query.filters?.misc_filters||(this.query.query.filters.misc_filters={filters:{}}),this.query.query.filters.misc_filters.filters.gem_level={...t!==void 0&&{min:t},...e!==void 0&&{max:e}},this}quality(t,e){return this.query.query.filters?.misc_filters||(this.query.query.filters.misc_filters={filters:{}}),this.query.query.filters.misc_filters.filters.quality={...t!==void 0&&{min:t},...e!==void 0&&{max:e}},this}corrupted(t){return this.query.query.filters?.misc_filters||(this.query.query.filters.misc_filters={filters:{}}),this.query.query.filters.misc_filters.filters.corrupted={option:t?"true":"false"},this}influenced(t){this.query.query.filters?.misc_filters||(this.query.query.filters.misc_filters={filters:{}});for(const e of t)this.query.query.filters.misc_filters.filters[e]={option:"true"};return this}build(){return{...this.query}}}class q{constructor(){this.limits=new Map,this.limits.set("search",{requests:[],maxRequests:5,windowMs:5e3}),this.limits.set("fetch",{requests:[],maxRequests:10,windowMs:5e3})}canMakeRequest(t){const e=this.limits.get(t);if(!e)return!0;const s=Date.now();return e.requests=e.requests.filter(i=>s-i<e.windowMs),e.requests.length<e.maxRequests}recordRequest(t){const e=this.limits.get(t);e&&e.requests.push(Date.now())}getWaitTime(t){const e=this.limits.get(t);if(!e||e.requests.length===0)return 0;const s=Math.min(...e.requests),i=e.windowMs-(Date.now()-s);return Math.max(0,i)}}class C{constructor(t,e,s={}){this.offset=0,this.ended=!1,this.entries=[],this.total=0,this.client=t,this.league=e,this.options={limit:200,...s}}async loadFirst(){this.offset=0,this.ended=!1;const t={offset:this.offset};this.options.realm!==void 0&&(t.realm=this.options.realm),this.options.sort!==void 0&&(t.sort=this.options.sort),this.options.class!==void 0&&(t.class=this.options.class),this.options.limit!==void 0&&(t.limit=this.options.limit);const e=await this.client.getLeagueLadder(this.league,t);return this.entries=e.ladder.entries,this.total=e.ladder.total,this.offset=this.entries.length,this.entries.length===0&&(this.ended=!0),e.ladder}async next(){if(this.ended)return;const t={offset:this.offset};this.options.realm!==void 0&&(t.realm=this.options.realm),this.options.sort!==void 0&&(t.sort=this.options.sort),this.options.class!==void 0&&(t.class=this.options.class),this.options.limit!==void 0&&(t.limit=this.options.limit);const e=await this.client.getLeagueLadder(this.league,t),s=e.ladder.entries;if(!s||s.length===0){this.ended=!0;return}return this.entries.push(...s),this.total=e.ladder.total,this.offset+=s.length,s}}async function*x(n,t={}){let e=t.startId;const s=t.idleWaitMs??2e3;for(;;){const i={};t.realm!==void 0&&(i.realm=t.realm),e!==void 0&&(i.id=e);const r=await n.getPublicStashes(i);yield r;const a=r.next_change_id===e;e=r.next_change_id,(r.stashes.length===0||a)&&await new Promise(o=>setTimeout(o,s))}}exports.AdvancedTradeQueryBuilder=T;exports.COMMON_STAT_IDS=R;exports.Currencies=E;exports.ENHANCED_CATEGORIES=A;exports.ENHANCED_CURRENCIES=w;exports.ItemCategories=g;exports.LadderPager=C;exports.OAuthHelper=u;exports.PoEApiClient=m;exports.TradeClient=y;exports.TradeQueryBuilder=_;exports.TradeRateLimiter=q;exports.groupTradeResults=S;exports.publicStashStream=x;