@haelp/teto
Version:
A typescript-based controllable TETR.IO client.
188 lines (178 loc) • 6.18 kB
text/typescript
import { type APIDefaults } from ".";
import { pack } from "..";
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
export type Res<T = any> =
| { success: false; error: { msg: string; [key: string]: any } }
| ({ success: true } & T);
export const basic = (defaults: APIDefaults) => {
return {
get: async <T = any>({
token,
uri,
headers = {},
json = false
}: {
token?: string | null;
uri: string;
headers?: Record<string, string>;
json?: boolean;
}): Promise<Res<T>> => {
let res: Response;
try {
res = await fetch(`https://tetr.io/api/${uri}`, {
headers: {
Accept: json
? "application/json"
: "application/vnd.osk.theorypack",
"User-Agent": defaults.userAgent,
cookie: `${defaults.turnstile ? "cf_clearance=" + defaults.turnstile : ""}`,
Authorization:
token === null ? undefined : `Bearer ${token || defaults.token}`,
...headers
} as any
});
} catch (err: any) {
throw new Error(`Fetch failed on GET to ${uri}: ${err.message || err}`);
}
const copy = res.clone();
try {
return json
? ((await res.json()) as Res<T>)
: pack.unpack(Buffer.from(await res.arrayBuffer()));
} catch {
if (res.status === 429)
throw new Error(`Rate limit (429) on GET to ${uri}`);
else {
try {
await fs.readdir(path.join(os.homedir(), ".trianglejs", "errors"));
} catch {
await fs.mkdir(path.join(os.homedir(), ".trianglejs", "errors"), {
recursive: true
});
}
const now = Date.now();
const text = await copy.text();
await fs.writeFile(
path.join(os.homedir(), ".trianglejs", "errors", `${now}.html`),
text
);
if (copy.status === 404) throw new Error(`404 on GET to ${uri}`);
if (text.includes("<title>Server error</title>"))
throw new Error(
`The TETR.IO Servers are currently unavailable. Check https://status.osk.sh for updates. You can view more information at ${path.join(
os.homedir(),
".trianglejs",
"errors",
`${now}.html`
)}`
);
if (text.includes("<title>Maintenance</title>"))
throw new Error(
`The TETR.IO Servers are under maintanence. Check https://status.osk.sh for updates. You can view more information at ${path.join(
os.homedir(),
".trianglejs",
"errors",
`${now}.html`
)}`
);
else
throw new Error(
`An error occured. This was likely because it the request was blocked by Cloudflare Turnstile on GET to ${uri}. Try passing in a turnstile token. View the error at ${path.join(
os.homedir(),
".trianglejs",
"errors",
`${now}.html`
)}`
);
}
}
},
post: async <T = any>({
token,
uri,
body,
headers = {},
json = false
}: {
token?: string;
uri: string;
body: Record<string, any>;
headers?: Record<string, string>;
json?: boolean;
}): Promise<Res<T>> => {
let res: Response;
try {
res = await fetch(`https://tetr.io/api/${uri}`, {
method: "POST",
//@ts-ignore
body: json ? JSON.stringify(body) : pack.pack(body),
headers: {
Accept: json
? "application/json"
: "application/vnd.osk.theorypack",
"User-Agent": defaults.userAgent,
cookie: `${defaults.turnstile ? "cf_clearance=" + defaults.turnstile : ""}`,
"Content-Type": json
? "application/json"
: "application/vnd.osk.theorypack",
Authorization:
token === null ? undefined : `Bearer ${token || defaults.token}`,
...headers
} as any
});
} catch (err: any) {
throw new Error(
`Fetch failed on POST to ${uri}: ${err.message || err}`
);
}
const copy = res.clone();
try {
return json
? ((await res.json()) as Res<T>)
: pack.unpack(Buffer.from(await res.arrayBuffer()));
} catch {
if (res.status === 429)
throw new Error(`Rate limit (429) on GET to ${uri}`);
else {
try {
await fs.readdir(path.join(os.homedir(), ".trianglejs", "errors"));
} catch {
await fs.mkdir(path.join(os.homedir(), ".trianglejs", "errors"), {
recursive: true
});
}
const now = Date.now();
const text = await copy.text();
await fs.writeFile(
path.join(os.homedir(), ".trianglejs", "errors", `${now}.html`),
text
);
console.log(text);
if (copy.status === 404) throw new Error(`404 on POST to ${uri}`);
if (text.includes("<title>Maintenance</title>"))
throw new Error(
`The TETR.IO Servers are under maintanence. Check https://status.osk.sh for updates. You can view more information at ${path.join(
os.homedir(),
".trianglejs",
"errors",
`${now}.html`
)}`
);
else
throw new Error(
`An error occured. This was likely because the request was blocked by Cloudflare Turnstile on GET to ${uri}. Try passing in a turnstile token. View the error at ${path.join(
os.homedir(),
".trianglejs",
"errors",
`${now}.html`
)}`
);
}
}
}
};
};
export type Get = ReturnType<typeof basic>["get"];
export type Post = ReturnType<typeof basic>["post"];