UNPKG

albion-sdk

Version:
557 lines (552 loc) 17.9 kB
// src/utils.ts function stringifyObjectValues(obj) { return Object.fromEntries( Object.entries(obj).map(([key, value]) => [key, String(value)]) ); } function getErrorMessage(error) { if (typeof error === "string") return error; if (error && typeof error === "object" && "message" in error && typeof error.message === "string") { return error.message; } return "Unable to extract error message"; } // src/fetch.ts function mergeAbortSignals(signalA, signalB) { const controller = new AbortController(); const abort = () => controller.abort(); signalA.addEventListener("abort", abort); signalB.addEventListener("abort", abort); return controller.signal; } function buildURL(baseURL, endpoint, queryParams) { if (!queryParams) return `${baseURL}${endpoint}`; const params = new URLSearchParams( stringifyObjectValues(queryParams) ).toString(); return `${baseURL}${endpoint}${params ? `?${params}` : ""}`; } async function _internal_fetch_status(url, options = {}) { const { signal, timeoutMs } = options; const controller = new AbortController(); const timeoutId = timeoutMs ? setTimeout(() => controller.abort(), timeoutMs) : null; const finalSignal = signal ? mergeAbortSignals(signal, controller.signal) : controller.signal; try { const response = await fetch(url, { signal: finalSignal }); if (timeoutId) clearTimeout(timeoutId); if (!response.ok) { return { status: "offline", message: `Albion status server returned a status code of ${response.status}, the server is most likely down for maintenance` }; } return await response.json(); } catch (e) { if (timeoutId) clearTimeout(timeoutId); if (e instanceof Error && e.name === "AbortError") { throw new AlbionAPIError("Request aborted or timed out"); } if (e instanceof AlbionAPIError) { throw e; } throw new AlbionAPIError( `Unknown error while checking Albion Online server status: ${getErrorMessage(e)}` ); } } async function _internal_fetch(baseURL, endpoint, queryParams, options = {}) { const { signal, timeoutMs } = options; const controller = new AbortController(); const timeoutId = timeoutMs ? setTimeout(() => controller.abort(), timeoutMs) : null; const finalSignal = signal ? mergeAbortSignals(signal, controller.signal) : controller.signal; try { const response = await fetch(buildURL(baseURL, endpoint, queryParams), { signal: finalSignal }); if (timeoutId) clearTimeout(timeoutId); if (!response.ok) { let responseBody; try { responseBody = await response.text(); } catch { } throw new AlbionAPIError( `Albion Online API request failed: ${response.status} ${response.statusText}`, { statusCode: response.status, statusText: response.statusText, url: response.url, responseBody } ); } return await response.json(); } catch (e) { if (timeoutId) clearTimeout(timeoutId); if (e instanceof Error && e.name === "AbortError") { throw new AlbionAPIError("Request aborted or timed out"); } if (e instanceof AlbionAPIError) { throw e; } throw new AlbionAPIError( `Unknown error while fetching from Albion Online API: ${getErrorMessage(e)}` ); } } // src/urls.ts var AMERICAS_API_URL = "https://gameinfo.albiononline.com/api/gameinfo"; var ASIA_API_URL = "https://gameinfo-sgp.albiononline.com/api/gameinfo"; var EUROPE_API_URL = "https://gameinfo-ams.albiononline.com/api/gameinfo"; var AMERICAS_STATUS_URL = "https://serverstatus.albiononline.com"; var ASIA_STATUS_URL = "https://serverstatus-sgp.albiononline.com"; var EUROPE_STATUS_URL = "https://serverstatus-ams.albiononline.com"; var RENDER_API_URL = "https://render.albiononline.com/v1"; // src/sdk.ts var AlbionAPIError = class extends Error { statusCode; statusText; url; responseBody; timestamp; constructor(message, options) { super(message); this.name = "AlbionAPIError"; this.statusCode = options?.statusCode; this.statusText = options?.statusText; this.url = options?.url; this.responseBody = options?.responseBody; this.timestamp = /* @__PURE__ */ new Date(); } }; var AlbionSDK = class _AlbionSDK { #apiURL; #statusURL; #region; #regionInstances = /* @__PURE__ */ new Map(); constructor(region) { this.#region = region || "Americas"; this.#setRegionUrls(this.#region); } #setRegionUrls(region) { switch (region) { case "Americas": this.#apiURL = AMERICAS_API_URL; this.#statusURL = AMERICAS_STATUS_URL; break; case "Asia": this.#apiURL = ASIA_API_URL; this.#statusURL = ASIA_STATUS_URL; break; case "Europe": this.#apiURL = EUROPE_API_URL; this.#statusURL = EUROPE_STATUS_URL; break; default: throw new Error( "Invalid region provided, please use 'Americas', 'Asia', or 'Europe'" ); } } #getRegionInstance(region) { if (!this.#regionInstances.has(region)) { this.#regionInstances.set(region, new _AlbionSDK(region)); } const instance = this.#regionInstances.get(region); if (!instance) { throw new Error(`Failed to create SDK instance for region: ${region}`); } return instance; } get americas() { return this.#getRegionInstance("Americas"); } get asia() { return this.#getRegionInstance("Asia"); } get europe() { return this.#getRegionInstance("Europe"); } async #fetch(endpoint, queryParams, options) { return _internal_fetch(this.#apiURL, endpoint, queryParams, options); } /** * Fetch the current status of the target Albion Online server. * * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getServerStatus(options) { return _internal_fetch_status(this.#statusURL, options); } /** * Fetch details about guilds and players based on an exact starting match of the specified search term. * * @param {string} searchTerm - The term to search for, between 1 and a yet-to-be-defined maximum length. * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async search(searchTerm, options) { return this.#fetch( `/search?q=${searchTerm}`, void 0, options ); } /** * Fetch basic information about a specific player * * @param {string} id - the players id you wish to fetch details about * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getPlayerInfo(id, options) { return this.#fetch(`/players/${id}`, void 0, options); } /** * Fetch the latest 10 kills of a specific player * * @param {string} id - the players id you wish to fetch kills for * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getPlayerLatestKills(id, options) { return this.#fetch( `/players/${id}/kills`, void 0, options ); } /** * Fetch the latest 10 deaths of a specific player * * @param {string} id - the players id you wish to fetch deaths for * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getPlayerLatestDeaths(id, options) { return this.#fetch( `/players/${id}/deaths`, void 0, options ); } /** * Fetch the top kills of a specific player based on kill fame * * @param {string} id - the players id you wish to fetch kills for * @param {TopAndSoloKillsParams} params - the params you wish to use for the request * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getPlayerTopKills(id, params, options) { return this.#fetch( `/players/${id}/topkills`, params, options ); } /** * Fetch the top solo kills of a specific player based on kill fame * * @param {string} id - the players id you wish to fetch kills for * @param {TopAndSoloKillsParams} params - the params you wish to use for the request * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getPlayerTopSoloKills(id, params, options) { return this.#fetch( `/players/${id}/solokills`, params, options ); } /** * Fetch basic information about a specific guild * * @param {string} id - the guilds id you wish to fetch details about * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getGuildInfo(id, options) { return this.#fetch(`/guilds/${id}`, void 0, options); } /** * Fetch detailed information about a specific guild * * @param {string} id - the guilds id you wish to fetch details about * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getGuildDetailedInfo(id, options) { return this.#fetch( `/guilds/${id}/data`, void 0, options ); } /** * Fetch guild member information for a specific guild * * @param {string} id - the guilds id you wish to fetch details about * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getGuildMembers(id, options) { return this.#fetch( `/guilds/${id}/members`, void 0, options ); } /** * Fetch GvG statistics for a specific guild * * @param {string} id - the guilds id you wish to fetch details about * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getGuildGvGStats(id, options) { return this.#fetch(`/guilds/${id}/stats`, void 0, options); } /** * Fetch PvP events between the two specified guilds * * @param {string} firstGuildId - the first guild id you wish to fetch details about * @param {string} secondGuildId - the second guild id you wish to fetch details about * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getGuildFued(firstGuildId, secondGuildId, options) { return this.#fetch( `/guilds/${firstGuildId}/fued/${secondGuildId}`, void 0, options ); } /** * Fetch the latest PvP events for a specific guild * * @param {string} id - the guilds id you wish to fetch details about * @param {PaginationParams} params - the params you wish to use for the request * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getGuildRecentEvents(id, params, options) { return this.#fetch( "/events", { guildId: id, ...params }, options ); } /** * Fetch the latest battles for a specific guild * * @param {string} id - the guilds id you wish to fetch details about * @param {BattleParams} params - the params you wish to use for the request * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getGuildRecentBattles(id, params, options) { return this.#fetch( "/battles", { guildId: id, ...params }, options ); } /** * Fetch the top kills of a specific guild based on kill fame * * @param {string} id - the guilds id you wish to fetch kills for * @param {TopAndSoloKillsParams} params - the params you wish to use for the request * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getGuildTopKills(id, params, options) { return this.#fetch(`/guilds/${id}/top`, params, options); } /** * Fetch the latest GvG matches for a specific guild * * @param {string} id - the guilds id you wish to fetch details about * @param {PaginationParams} params - the params you wish to use for the request * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getGuildRecentMatches(id, params, options) { return this.#fetch( "/guildmatches/past", { guildId: id, ...params }, options ); } /** * Fetch details about a specific GvG match * * @param {string} id - the match id you wish to fetch details about * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getGuildMatchInfo(id, options) { return this.#fetch(`/guildmatches/${id}`, void 0, options); } /** * Fetch information about a specific alliance * * @param {string} id - the alliance id you wish to fetch details about * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getAllianceInfo(id, options) { return this.#fetch(`/alliances/${id}`, void 0, options); } /** * Fetch all latest battles * * @param {BattleParams} params - the params you wish to use for the request * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getRecentBattles(params, options) { return this.#fetch("/battles", params, options); } /** * Fetch information about a specific battle * * @param {string} id - the battle id you wish to fetch details about * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getBattleInfo(id, options) { return this.#fetch(`/battles/${id}`, void 0, options); } /** * Fetch events related to a specific battle * * @param {string} id - the battle id you wish to fetch details about * @param {PaginationParams} params - the params you wish to use for the request * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getBattleEvents(id, params, options) { return this.#fetch(`/battle/${id}`, params, options); } /** * Fetch all latest PvP events * * @param {PaginationParams} params - the params you wish to use for the request * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getRecentEvents(params, options) { return this.#fetch("/events", params, options); } /** * Fetch the latest top kills based on kill fame * * @param {TopAndSoloKillsParams} params - the params you wish to use for the request * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getRecentTopEvents(params, options) { return this.#fetch("/events/killfame", params, options); } /** * Fetch information about a specific event * * @param {string} id - the event id you wish to fetch details about * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getEventInfo(id, options) { return this.#fetch(`/events/${id}`, void 0, options); } /** * Fetch recent 5v5 Crystal League Matches * * @param {PaginationParams} params - the params you wish to use for the request * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getRecentCrystalLeagueMatches(params, options) { return this.#fetch( "/matches/crystalleague", { category: "crystal_league", ...params }, options ); } /** * Fetch recent 20v20 Crystal League Matches * * @param {PaginationParams} params - the params you wish to use for the request * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getRecentCrystalLeagueCityMatches(params, options) { return this.#fetch( "/matches/crystalleague", { category: "crystal_league_city", ...params }, options ); } /** * Fetch all weapon categories * * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getWeaponCategories(options) { return this.#fetch( "/items/_weaponcategories", void 0, options ); } /** * Fetch the item category tree * * @param {AlbionAPIFetchOptions} options - the options you wish to use for the request */ async getItemCategoryTree(options) { return this.#fetch( "/items/_itemCategoryTree", void 0, options ); } }; // src/render.ts function itemIconUrl(item, params) { const { enchantment = 0, ...restParams } = params ?? {}; const urlSearchParams = new URLSearchParams( stringifyObjectValues(restParams) ).toString(); return `${RENDER_API_URL}/item/${item}@${enchantment}.png${urlSearchParams ? `?${urlSearchParams}` : ""}`; } function spellIconUrl(spell, params) { const urlSearchParams = new URLSearchParams( stringifyObjectValues(params ?? {}) ).toString(); return `${RENDER_API_URL}/spell/${spell}.png${urlSearchParams ? `?${urlSearchParams}` : ""}`; } function wardrobeIconUrl(item) { return `${RENDER_API_URL}/wardrobe/${item}.png`; } function destinyBoardIconUrl(node, params) { const urlSearchParams = new URLSearchParams( stringifyObjectValues(params ?? {}) ).toString(); return `${RENDER_API_URL}/destiny/${node}.png${urlSearchParams ? `?${urlSearchParams}` : ""}`; } function guildLogoUrl(params) { const urlSearchParams = new URLSearchParams( stringifyObjectValues(params ?? {}) ).toString(); return `${RENDER_API_URL}/guild/logo.png?${urlSearchParams}`; } export { AMERICAS_API_URL, AMERICAS_STATUS_URL, ASIA_API_URL, ASIA_STATUS_URL, AlbionAPIError, AlbionSDK, EUROPE_API_URL, EUROPE_STATUS_URL, RENDER_API_URL, destinyBoardIconUrl, guildLogoUrl, itemIconUrl, spellIconUrl, wardrobeIconUrl };