@haelp/teto
Version:
A typescript-based controllable TETR.IO client.
192 lines (191 loc) • 8.6 kB
JavaScript
const NodeError = Error;
(function(ChannelAPI) {
class Error1 extends NodeError {
constructor(type, message){
super(`[CH API] ${type}: ${message}`);
}
}
ChannelAPI.Error = Error1;
ChannelAPI.randomSessionID = (length = 20)=>Array.from({
length
}, ()=>[
"qwertyuiop[asdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890"
][Math.floor(Math.random() * (26 + 26 + 10))]).join("");
const config = {
sessionID: ChannelAPI.randomSessionID(),
host: "https://ch.tetr.io/api/",
caching: true
};
ChannelAPI.getConfig = ()=>config;
ChannelAPI.setConfig = (newConfig)=>{
Object.assign(config, newConfig);
};
const cache = {};
ChannelAPI.clearCache = ()=>{
Object.keys(cache).forEach((k)=>delete cache[k]);
};
ChannelAPI.get = async ({ route, args = {
data: {},
format: []
}, query = {}, options = config })=>{
let uri = route;
args.format.forEach((arg)=>{
if (arg in args.data) {
uri = uri.replaceAll(`:${arg}`, args.data[arg]);
} else {
throw new Error1("Argument Error", `Missing argument ${arg.toString()} in route ${route}`);
}
});
Object.keys(query).forEach((key)=>{
uri += `?${key}=${query[key]}`;
});
if (config.caching && cache[uri]) {
if (cache[uri].until > Date.now()) {
return cache[uri].data;
} else {
delete cache[uri];
}
}
let res;
try {
res = await fetch(`${options.host || config.host}${uri}`, {
headers: options.sessionID || config.sessionID ? {
"X-Session-ID": options.sessionID || config.sessionID
} : {}
}).then((r)=>r.json());
if (res.success === false) {
throw new Error1("Server Error", `${res.error.msg} at ${uri}`);
} else {
if (config.caching) {
cache[uri] = {
until: res.cache.cached_until,
data: res.data
};
}
return res.data;
}
} catch (e) {
if (e instanceof Error1) throw e;
throw new Error1("Network Error", `${e.message} at ${uri}`);
}
};
(function(generator) {
generator.empty = (route, res)=>async ()=>{
const r = await ChannelAPI.get({
route
});
if (res) return r[res];
return r;
};
generator.args = (route, res)=>{
const base = route.split("/").filter((v)=>v.startsWith(":")).map((v)=>v.slice(1));
async function getArgs(...args) {
const argData = {};
if (typeof args[0] === "string") {
if (args.length !== base.length) throw new Error1("Argument Error", `Invalid number of arguments for ${route}: Expected ${base.length}, found ${args.length}`);
base.forEach((v, i)=>argData[v] = args[i]);
} else {
base.forEach((v)=>{
if (!(v in args[0])) throw new Error1("Argument Error", `Missing argument ${v.toString()} for ${route}`);
argData[v] = args[0][v];
});
}
const r = await ChannelAPI.get({
route,
args: {
data: argData,
format: base
}
});
if (res) return r[res];
return r;
}
return getArgs;
};
generator.query = (route, res)=>async (query = {})=>{
const r = await ChannelAPI.get({
route,
query: query
});
if (res) return r[res];
return r;
};
generator.argsAndQuery = (route, res)=>{
const base = route.split("/").filter((v)=>v.startsWith(":")).map((v)=>v.slice(1));
async function getArgsAndQuery(...args) {
const argData = {};
let query = {};
if (typeof args[0] === "string") {
if (args.length === base.length + 1 && typeof args[base.length] === "object") {
query = args.pop();
}
if (args.length !== base.length) throw new Error1("Argument Error", `Invalid number of arguments for ${route}: Expected ${base.length}, found ${args.length}`);
base.forEach((v, i)=>argData[v] = args[i]);
} else {
base.forEach((v)=>{
if (!(v in args)) throw new Error1("Argument Error", `Missing argument ${v.toString()} for ${route}`);
argData[v] = args[0][v];
});
if (typeof args[1] === "object") {
query = args[1];
}
}
const r = await ChannelAPI.get({
route,
args: {
data: argData,
format: base
},
query: query
});
if (res) return r[res];
return r;
}
return getArgsAndQuery;
};
})(ChannelAPI.generator || (ChannelAPI.generator = {}));
(function(general) {
general.stats = ChannelAPI.generator.empty("general/stats");
general.activity = ChannelAPI.generator.empty("general/activity", "activity");
})(ChannelAPI.general || (ChannelAPI.general = {}));
(function(users) {
users.get = ChannelAPI.generator.args("users/:user");
(function(summaries) {
summaries.fourtyLines = ChannelAPI.generator.args("users/:user/summaries/40l");
summaries.blitz = ChannelAPI.generator.args("users/:user/summaries/BLITZ");
summaries.quickPlay = ChannelAPI.generator.args("users/:user/summaries/zenith");
summaries.zenith = summaries.quickPlay;
summaries.expertQuickPlay = ChannelAPI.generator.args("users/:user/summaries/zenithex");
summaries.zenthiex = summaries.expertQuickPlay;
summaries.tetraLeague = ChannelAPI.generator.args("users/:user/summaries/league");
summaries.tl = summaries.tetraLeague;
summaries.zen = ChannelAPI.generator.args("users/:user/summaries/zen");
summaries.achievements = ChannelAPI.generator.args("users/:user/summaries/achievements", "achievements");
summaries.all = ChannelAPI.generator.args("users/:user/summaries");
})(users.summaries || (users.summaries = {}));
users.search = ChannelAPI.generator.args("users/search/:query", "users");
users.leaderboard = ChannelAPI.generator.argsAndQuery("users/by/:leaderboard", "entries");
users.lb = users.leaderboard;
users.history = ChannelAPI.generator.argsAndQuery("users/history/:leaderboard/:season", "entries");
users.personalRecords = ChannelAPI.generator.argsAndQuery("users/:user/records/:gamemode/:leaderboard", "entries");
users.records = users.personalRecords;
})(ChannelAPI.users || (ChannelAPI.users = {}));
(function(records) {
records.leaderboard = ChannelAPI.generator.argsAndQuery("/records/:leaderboard", "entries");
records.lb = records.leaderboard;
records.search = ChannelAPI.generator.query("records/search");
})(ChannelAPI.records || (ChannelAPI.records = {}));
(function(news) {
news.all = ChannelAPI.generator.query("news/");
news.latest = ChannelAPI.generator.argsAndQuery("news/:stream", "news");
news.stream = news.latest;
})(ChannelAPI.news || (ChannelAPI.news = {}));
(function(labs) {
labs.scoreflow = ChannelAPI.generator.args("labs/scoreflow/:user/:gamemode");
labs.leagueflow = ChannelAPI.generator.args("labs/leagueflow/:user");
})(ChannelAPI.labs || (ChannelAPI.labs = {}));
ChannelAPI.achievements = ChannelAPI.generator.args("achievements/:k");
})(ChannelAPI || (ChannelAPI = {}));
export { ChannelAPI as CH, ChannelAPI as ch, ChannelAPI as default };
export var ChannelAPI;
//# sourceMappingURL=index.js.map