albion-sdk
Version:
Albion Online API SDK
557 lines (552 loc) • 17.9 kB
JavaScript
// 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
};