ddnet
Version:
A typescript npm package for interacting with data from ddnet.org
147 lines • 4.36 kB
JavaScript
import axios from 'axios';
import { _Schema_releases } from '../../schemas/other/releases.js';
import { DDNetError, dePythonifyTime } from '../../util.js';
import { CacheManager } from './CacheManager.js';
import { Release } from './Release.js';
/**
* Represents DDNet map releases.
*/
export class Releases {
//#region Cache
/**
* Releases responses cache. (12h default TTL)
*/
static cache = new CacheManager('releases-cache', 12 * 60 * 60 * 1000); // 12h ttl
/**
* Sets the TTL (Time-To-Live) for objects in cache.
*/
static setTTL = this.cache.setTTL;
/**
* Clears the {@link Releases.cache}.
*/
static clearCache = this.cache.clearCache;
//#endregion
//#region Declarations
/**
* Raw releases data.
*/
#rawData; // Marked private with vanilla JS syntax for better logging.
/**
* Array with all the map releases.
*/
maps;
//#endregion
/**
* Create a new instance of {@link Releases} from API data.
* Not intended to be used, use {@link new Releases.new} instead.
*/
constructor(
/**
* The raw data for this map.
*/
rawData) {
this.populate(rawData);
}
/**
* Fetch, parse and construct a new {@link Releases} instance.
*/
static async new(
/**
* Wether to bypass the releases data cache.
*/
bypassCache = false) {
const response = await this.makeRequest(bypassCache);
if (response instanceof DDNetError)
throw response;
const parsed = this.parseObject(response.data);
if (!parsed.success)
throw parsed.error;
return new this(parsed.data);
}
/**
* Parse an object using the {@link _Schema_releases releases raw data zod schema}.
*/
static parseObject(
/**
* The object to be parsed.
*/
data) {
const parsed = _Schema_releases.safeParse(data);
if (parsed.success)
return { success: true, data: parsed.data };
return { success: false, error: new DDNetError(parsed.error.message, parsed.error) };
}
/**
* Fetch the releases data from the API.
*/
static async makeRequest(
/**
* Wether to bypass the cache.
*/
force = false) {
const url = 'https://ddnet.org/releases/maps.json';
if (!force) {
if (await this.cache.has(url)) {
const data = await this.cache.get(url);
if (data)
return { data, fromCache: true };
}
}
const response = await axios.get(url).catch((err) => new DDNetError(err.cause?.message, err));
if (response instanceof DDNetError)
return response;
const data = response.data;
if (typeof data === 'string')
return new DDNetError(`Invalid response!`, data);
await this.cache.set(url, data);
return { data, fromCache: false };
}
/**
* Populate the object with the raw releases data.
*/
populate(
/**
* The raw releases data.
*/
rawData) {
this.#rawData = rawData;
this.maps = this.#rawData.map(r => new Release({
name: r.name,
type: r.type,
releaseTimestamp: dePythonifyTime(r.release),
width: r.width,
height: r.height,
tiles: r.tiles,
difficulty: r.difficulty,
points: r.points,
mapper: r.mapper,
thumbnail: r.thumbnail,
web_preview: r.web_preview,
website: r.website
}));
return this;
}
/**
* Refresh the releases data.
*/
async refresh() {
const data = await Releases.makeRequest(true);
if (data instanceof DDNetError)
throw new DDNetError(`Failed to refresh releases`, data);
const parsed = Releases.parseObject(data.data);
if (!parsed.success)
throw new DDNetError(`Failed to refresh releases`, parsed.error);
return this.populate(parsed.data);
}
/**
* Get all the releases of a specific {@link Type}.
*/
getServer(
/**
* The type of the releases.
*/
type) {
return this.maps.filter(m => m.type === type);
}
}
//# sourceMappingURL=Releases.js.map