@flitt/api 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/LICENSE +21 -0
- package/README.md +277 -0
- package/SECURITY.md +15 -0
- package/dist/cjs/client.d.ts +243 -0
- package/dist/cjs/client.d.ts.map +1 -0
- package/dist/cjs/client.js +470 -0
- package/dist/cjs/client.js.map +1 -0
- package/dist/cjs/errors.d.ts +71 -0
- package/dist/cjs/errors.d.ts.map +1 -0
- package/dist/cjs/errors.js +107 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/http.d.ts +53 -0
- package/dist/cjs/http.d.ts.map +1 -0
- package/dist/cjs/http.js +322 -0
- package/dist/cjs/http.js.map +1 -0
- package/dist/cjs/index.d.ts +13 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +31 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/types.d.ts +406 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +7 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cjs/version.d.ts +3 -0
- package/dist/cjs/version.d.ts.map +1 -0
- package/dist/cjs/version.js +6 -0
- package/dist/cjs/version.js.map +1 -0
- package/dist/cjs/webhooks.d.ts +40 -0
- package/dist/cjs/webhooks.d.ts.map +1 -0
- package/dist/cjs/webhooks.js +98 -0
- package/dist/cjs/webhooks.js.map +1 -0
- package/dist/esm/client.d.ts +243 -0
- package/dist/esm/client.d.ts.map +1 -0
- package/dist/esm/client.js +465 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/errors.d.ts +71 -0
- package/dist/esm/errors.d.ts.map +1 -0
- package/dist/esm/errors.js +90 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/http.d.ts +53 -0
- package/dist/esm/http.d.ts.map +1 -0
- package/dist/esm/http.js +310 -0
- package/dist/esm/http.js.map +1 -0
- package/dist/esm/index.d.ts +13 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +9 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/types.d.ts +406 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +6 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/version.d.ts +3 -0
- package/dist/esm/version.d.ts.map +1 -0
- package/dist/esm/version.js +3 -0
- package/dist/esm/version.js.map +1 -0
- package/dist/esm/webhooks.d.ts +40 -0
- package/dist/esm/webhooks.d.ts.map +1 -0
- package/dist/esm/webhooks.js +93 -0
- package/dist/esm/webhooks.js.map +1 -0
- package/package.json +67 -0
- package/src/client.ts +576 -0
- package/src/errors.ts +92 -0
- package/src/http.ts +353 -0
- package/src/index.ts +26 -0
- package/src/types.ts +390 -0
- package/src/version.ts +2 -0
- package/src/webhooks.ts +115 -0
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
import { FlittConfigError, FlittValidationError } from "./errors.js";
|
|
2
|
+
import { isBrowserLike, normalizeBaseUrl, randomKey, resolveFetch, segment, Transport, } from "./http.js";
|
|
3
|
+
export const DEFAULT_BASE_URL = "https://api.flitt.me";
|
|
4
|
+
const API_KEY_FORMAT = /^flt_[A-Za-z0-9_-]{30,120}$/;
|
|
5
|
+
const VOTE_TOKEN_FORMAT = /^flv_[A-Za-z0-9_-]{40,60}$/;
|
|
6
|
+
const INSPECT = Symbol.for("nodejs.util.inspect.custom");
|
|
7
|
+
function envVar(name) {
|
|
8
|
+
const p = globalThis.process;
|
|
9
|
+
return p?.env?.[name];
|
|
10
|
+
}
|
|
11
|
+
function buildTransport(token, opts, unwrapData) {
|
|
12
|
+
if (isBrowserLike() && !opts.dangerouslyAllowBrowser) {
|
|
13
|
+
throw new FlittConfigError("The Flitt client is running in a browser: your secret key would be exposed to every visitor. " +
|
|
14
|
+
"Call Flitt from your server (Node.js, Deno, Bun, a Worker…) or set dangerouslyAllowBrowser: true if you understand the risk.");
|
|
15
|
+
}
|
|
16
|
+
const num = (v, def, min, max, name) => {
|
|
17
|
+
if (v === undefined)
|
|
18
|
+
return def;
|
|
19
|
+
if (!Number.isFinite(v) || v < min || v > max)
|
|
20
|
+
throw new FlittConfigError(`${name} must be between ${min} and ${max}.`);
|
|
21
|
+
return v;
|
|
22
|
+
};
|
|
23
|
+
return new Transport({
|
|
24
|
+
baseUrl: normalizeBaseUrl(opts.baseUrl ?? DEFAULT_BASE_URL),
|
|
25
|
+
token,
|
|
26
|
+
timeoutMs: num(opts.timeoutMs, 15_000, 1, 600_000, "timeoutMs"),
|
|
27
|
+
maxRetries: num(opts.maxRetries, 2, 0, 10, "maxRetries"),
|
|
28
|
+
maxRetryDelayMs: num(opts.maxRetryDelayMs, 30_000, 0, 600_000, "maxRetryDelayMs"),
|
|
29
|
+
fetch: resolveFetch(opts.fetch),
|
|
30
|
+
userAgent: opts.userAgent,
|
|
31
|
+
unwrapData,
|
|
32
|
+
onRateLimit: opts.onRateLimit,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function positiveInt(value, name, max) {
|
|
36
|
+
if (value === undefined)
|
|
37
|
+
return undefined;
|
|
38
|
+
if (!Number.isInteger(value) || value < 1 || value > max)
|
|
39
|
+
throw new FlittConfigError(`${name} must be an integer between 1 and ${max}.`);
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
// ===========================================================================
|
|
43
|
+
// Public API client
|
|
44
|
+
// ===========================================================================
|
|
45
|
+
/**
|
|
46
|
+
* Client of the Flitt Public API v1.
|
|
47
|
+
*
|
|
48
|
+
* ```ts
|
|
49
|
+
* import { Flitt } from "@flitt/api";
|
|
50
|
+
* const flitt = new Flitt({ apiKey: process.env.FLITT_API_KEY });
|
|
51
|
+
* const { data } = await flitt.servers.list();
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export class Flitt {
|
|
55
|
+
#http;
|
|
56
|
+
/** Your account's monthly quota. */
|
|
57
|
+
usage;
|
|
58
|
+
servers;
|
|
59
|
+
players;
|
|
60
|
+
firewall;
|
|
61
|
+
discord;
|
|
62
|
+
commands;
|
|
63
|
+
constructor(options = {}) {
|
|
64
|
+
const apiKey = (options.apiKey ?? envVar("FLITT_API_KEY") ?? "").trim();
|
|
65
|
+
if (!apiKey)
|
|
66
|
+
throw new FlittConfigError("Missing API key: pass { apiKey } or set FLITT_API_KEY.");
|
|
67
|
+
if (!API_KEY_FORMAT.test(apiKey)) {
|
|
68
|
+
throw new FlittConfigError(apiKey.startsWith("flv_")
|
|
69
|
+
? "This is a Vote API token (flv_…): use `new FlittVotes({ token })` instead."
|
|
70
|
+
: "Invalid API key format: Flitt API keys start with flt_ (Profile → API).");
|
|
71
|
+
}
|
|
72
|
+
this.#http = buildTransport(apiKey, options, false);
|
|
73
|
+
const http = this.#http;
|
|
74
|
+
const base = "/v1/public-api";
|
|
75
|
+
this.usage = { get: async (o) => http.request("GET", `${base}/usage`, o) };
|
|
76
|
+
this.servers = new ServersResource(http, base);
|
|
77
|
+
this.players = new PlayersResource(http, base);
|
|
78
|
+
this.firewall = new FirewallResource(http, base);
|
|
79
|
+
this.discord = new DiscordResource(http, base);
|
|
80
|
+
this.commands = new CommandsResource(http, base);
|
|
81
|
+
}
|
|
82
|
+
/** Quota state from the last response (`null` before the first request). */
|
|
83
|
+
get rateLimit() {
|
|
84
|
+
return this.#http.lastRateLimit;
|
|
85
|
+
}
|
|
86
|
+
/** Never prints the key. */
|
|
87
|
+
toJSON() {
|
|
88
|
+
return { client: "Flitt", apiKey: "[redacted]" };
|
|
89
|
+
}
|
|
90
|
+
[INSPECT]() {
|
|
91
|
+
return "Flitt { apiKey: [redacted] }";
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
class ServersResource {
|
|
95
|
+
http;
|
|
96
|
+
base;
|
|
97
|
+
constructor(http, base) {
|
|
98
|
+
this.http = http;
|
|
99
|
+
this.base = base;
|
|
100
|
+
}
|
|
101
|
+
/** Servers you own or are a member of, newest first. `limit`: 1 to 100 (default 25). */
|
|
102
|
+
async list(params = {}, options) {
|
|
103
|
+
return this.http.request("GET", `${this.base}/servers`, {
|
|
104
|
+
...options,
|
|
105
|
+
query: { page: positiveInt(params.page, "page", 1_000_000), limit: positiveInt(params.limit, "limit", 100) },
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/** Iterates over every server, page after page. */
|
|
109
|
+
async *listAll(params = {}, options) {
|
|
110
|
+
for (let page = 1;; page++) {
|
|
111
|
+
const res = await this.list({ ...params, page }, options);
|
|
112
|
+
yield* res.data;
|
|
113
|
+
if (!res.data.length || (res.pagination.pages !== null && page >= res.pagination.pages))
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/** One server. IP, port and addon details are hidden for the VIEWER role. */
|
|
118
|
+
async get(serverId, options) {
|
|
119
|
+
const res = await this.http.request("GET", `${this.base}/servers/${segment(serverId, "serverId")}`, options);
|
|
120
|
+
return res.server;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
class PlayersResource {
|
|
124
|
+
http;
|
|
125
|
+
base;
|
|
126
|
+
constructor(http, base) {
|
|
127
|
+
this.http = http;
|
|
128
|
+
this.base = base;
|
|
129
|
+
}
|
|
130
|
+
/** Players of a server, last joined first. `limit`: 1 to 50 (default 15). */
|
|
131
|
+
async list(serverId, params = {}, options) {
|
|
132
|
+
return this.http.request("GET", `${this.base}/servers/${segment(serverId, "serverId")}/players`, {
|
|
133
|
+
...options,
|
|
134
|
+
query: {
|
|
135
|
+
page: positiveInt(params.page, "page", 1_000_000),
|
|
136
|
+
limit: positiveInt(params.limit, "limit", 50),
|
|
137
|
+
status: params.status,
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/** Iterates over every player of a server. */
|
|
142
|
+
async *listAll(serverId, params = {}, options) {
|
|
143
|
+
const limit = params.limit ?? 50;
|
|
144
|
+
for (let page = 1;; page++) {
|
|
145
|
+
const res = await this.list(serverId, { ...params, limit, page }, options);
|
|
146
|
+
yield* res.players;
|
|
147
|
+
const pages = res.pagination.pages;
|
|
148
|
+
// Edge SDK servers do not report a total: stop on a short page.
|
|
149
|
+
if (!res.players.length || (pages !== null ? page >= pages : res.players.length < limit))
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/** One player, by Flitt player id or by external id (SteamID64, license, UUID…). */
|
|
154
|
+
async get(serverId, playerId, options) {
|
|
155
|
+
const res = await this.http.request("GET", `${this.base}/servers/${segment(serverId, "serverId")}/players/${segment(playerId, "playerId")}`, options);
|
|
156
|
+
return res.player;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
class FirewallResource {
|
|
160
|
+
http;
|
|
161
|
+
base;
|
|
162
|
+
rules;
|
|
163
|
+
constructor(http, base) {
|
|
164
|
+
this.http = http;
|
|
165
|
+
this.base = base;
|
|
166
|
+
this.rules = new FirewallRulesResource(http, base);
|
|
167
|
+
}
|
|
168
|
+
/** Firewall settings and rule counts. */
|
|
169
|
+
async get(serverId, options) {
|
|
170
|
+
return this.http.request("GET", `${this.base}/servers/${segment(serverId, "serverId")}/firewall`, options);
|
|
171
|
+
}
|
|
172
|
+
/** Turns the firewall / VPN blocking on or off, changes the kick message. OWNER or ADMIN. */
|
|
173
|
+
async update(serverId, changes, options) {
|
|
174
|
+
if (changes.kickMessage !== undefined && changes.kickMessage.length > 300)
|
|
175
|
+
throw new FlittConfigError("kickMessage: 300 characters max.");
|
|
176
|
+
await this.http.request("PATCH", `${this.base}/servers/${segment(serverId, "serverId")}/firewall`, { ...options, body: changes });
|
|
177
|
+
}
|
|
178
|
+
/** Latest blocked connections (1 to 200, default 50). */
|
|
179
|
+
async blocks(serverId, params = {}, options) {
|
|
180
|
+
const res = await this.http.request("GET", `${this.base}/servers/${segment(serverId, "serverId")}/firewall/blocks`, {
|
|
181
|
+
...options,
|
|
182
|
+
query: { limit: positiveInt(params.limit, "limit", 200) },
|
|
183
|
+
});
|
|
184
|
+
return res.blocks;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
class FirewallRulesResource {
|
|
188
|
+
http;
|
|
189
|
+
base;
|
|
190
|
+
constructor(http, base) {
|
|
191
|
+
this.http = http;
|
|
192
|
+
this.base = base;
|
|
193
|
+
}
|
|
194
|
+
async list(serverId, query = {}, options) {
|
|
195
|
+
return this.http.request("GET", `${this.base}/servers/${segment(serverId, "serverId")}/firewall/rules`, {
|
|
196
|
+
...options,
|
|
197
|
+
query: {
|
|
198
|
+
q: query.q,
|
|
199
|
+
action: query.action,
|
|
200
|
+
kind: query.kind,
|
|
201
|
+
page: positiveInt(query.page, "page", 1_000_000),
|
|
202
|
+
limit: positiveInt(query.limit, "limit", 100),
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Adds one rule, or up to 100 in one call (e.g. to sync a ban list). OWNER
|
|
208
|
+
* or ADMIN. Partial success is possible: check `errors` in the result.
|
|
209
|
+
*/
|
|
210
|
+
async create(serverId, rules, options) {
|
|
211
|
+
const list = Array.isArray(rules) ? rules : [rules];
|
|
212
|
+
if (!list.length || list.length > 100)
|
|
213
|
+
throw new FlittConfigError("Provide 1 to 100 rules.");
|
|
214
|
+
for (const r of list) {
|
|
215
|
+
if (!r?.value || String(r.value).length > 128)
|
|
216
|
+
throw new FlittConfigError("Each rule needs a value of 1 to 128 characters.");
|
|
217
|
+
if (r.note !== undefined && r.note.length > 120)
|
|
218
|
+
throw new FlittConfigError("note: 120 characters max.");
|
|
219
|
+
}
|
|
220
|
+
return this.http
|
|
221
|
+
.request("POST", `${this.base}/servers/${segment(serverId, "serverId")}/firewall/rules`, {
|
|
222
|
+
...options,
|
|
223
|
+
body: { rules: list },
|
|
224
|
+
})
|
|
225
|
+
.catch((err) => {
|
|
226
|
+
// Every rule refused (duplicates, plan limit…): the API answers 400
|
|
227
|
+
// with the per-rule errors. Return them like a partial success.
|
|
228
|
+
const details = err instanceof FlittValidationError ? err.details : undefined;
|
|
229
|
+
if (details && Array.isArray(details.errors)) {
|
|
230
|
+
return { ok: false, created: Array.isArray(details.created) ? details.created : [], errors: details.errors };
|
|
231
|
+
}
|
|
232
|
+
throw err;
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
/** Removes one rule. */
|
|
236
|
+
async delete(serverId, ruleId, options) {
|
|
237
|
+
await this.http.request("DELETE", `${this.base}/servers/${segment(serverId, "serverId")}/firewall/rules/${segment(ruleId, "ruleId")}`, options);
|
|
238
|
+
}
|
|
239
|
+
/** Removes rules by ids (up to 500) and / or by action / kind. Returns the number deleted. */
|
|
240
|
+
async deleteMany(serverId, filter, options) {
|
|
241
|
+
if (!filter.ids?.length && !filter.action && !filter.kind) {
|
|
242
|
+
throw new FlittConfigError("deleteMany needs ids, action or kind: refusing to delete every rule by accident.");
|
|
243
|
+
}
|
|
244
|
+
if (filter.ids && filter.ids.length > 500)
|
|
245
|
+
throw new FlittConfigError("ids: 500 max per call.");
|
|
246
|
+
const res = await this.http.request("DELETE", `${this.base}/servers/${segment(serverId, "serverId")}/firewall/rules`, {
|
|
247
|
+
...options,
|
|
248
|
+
body: filter,
|
|
249
|
+
});
|
|
250
|
+
return res.deleted;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
class DiscordResource {
|
|
254
|
+
http;
|
|
255
|
+
base;
|
|
256
|
+
constructor(http, base) {
|
|
257
|
+
this.http = http;
|
|
258
|
+
this.base = base;
|
|
259
|
+
}
|
|
260
|
+
/** Discord module state of a server (for API-only setups, without the Flitt bot). */
|
|
261
|
+
async getModule(serverId, options) {
|
|
262
|
+
return this.http.request("GET", `${this.base}/servers/${segment(serverId, "serverId")}/discord`, options);
|
|
263
|
+
}
|
|
264
|
+
/** Turns the addon's Discord module on or off. ADMIN. */
|
|
265
|
+
async setModule(serverId, enabled, options) {
|
|
266
|
+
return this.http.request("PATCH", `${this.base}/servers/${segment(serverId, "serverId")}/discord`, { ...options, body: { enabled: Boolean(enabled) } });
|
|
267
|
+
}
|
|
268
|
+
/** Code a player types in game to link their Discord account (same flow as the bot's /link). */
|
|
269
|
+
async createLinkCode(discordId, options) {
|
|
270
|
+
return this.http.request("POST", `${this.base}/discord/link-codes`, { ...options, body: { discordId: snowflake(discordId) } });
|
|
271
|
+
}
|
|
272
|
+
/** Links of a Discord user or of a game identity, limited to players seen on your servers. */
|
|
273
|
+
async findLinks(query, options) {
|
|
274
|
+
const q = "discordId" in query ? { discordId: snowflake(query.discordId) } : { externalId: String(query.externalId ?? "").trim() };
|
|
275
|
+
if (!("discordId" in q) && !q.externalId)
|
|
276
|
+
throw new FlittConfigError("Provide discordId or externalId.");
|
|
277
|
+
const res = await this.http.request("GET", `${this.base}/discord/links`, { ...options, query: q });
|
|
278
|
+
return res.links;
|
|
279
|
+
}
|
|
280
|
+
/** Links a player you verified yourself. The player must have joined the server. ADMIN. */
|
|
281
|
+
async link(serverId, input, options) {
|
|
282
|
+
const res = await this.http.request("POST", `${this.base}/servers/${segment(serverId, "serverId")}/discord/links`, {
|
|
283
|
+
...options,
|
|
284
|
+
body: { discordId: snowflake(input.discordId), externalId: input.externalId, ...(input.name ? { name: input.name } : {}) },
|
|
285
|
+
});
|
|
286
|
+
return res.link;
|
|
287
|
+
}
|
|
288
|
+
/** Removes the Discord link of a player. ADMIN. */
|
|
289
|
+
async unlink(serverId, externalId, options) {
|
|
290
|
+
const res = await this.http.request("DELETE", `${this.base}/servers/${segment(serverId, "serverId")}/discord/links/${segment(externalId, "externalId")}`, options);
|
|
291
|
+
return res.deleted;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
class CommandsResource {
|
|
295
|
+
http;
|
|
296
|
+
base;
|
|
297
|
+
constructor(http, base) {
|
|
298
|
+
this.http = http;
|
|
299
|
+
this.base = base;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Queues a command for the game server's addon. `chat` and `notify` need the
|
|
303
|
+
* EDITOR role, everything else ADMIN. Set `waitMs` (max 15000) to wait for
|
|
304
|
+
* the addon's answer. Not retried automatically: a retry could run it twice.
|
|
305
|
+
*/
|
|
306
|
+
async send(serverId, input, options) {
|
|
307
|
+
if (input.waitMs !== undefined && (!Number.isInteger(input.waitMs) || input.waitMs < 0 || input.waitMs > 15_000)) {
|
|
308
|
+
throw new FlittConfigError("waitMs must be an integer between 0 and 15000.");
|
|
309
|
+
}
|
|
310
|
+
return this.http.request("POST", `${this.base}/servers/${segment(serverId, "serverId")}/commands`, {
|
|
311
|
+
...options,
|
|
312
|
+
body: { type: input.type, payload: input.payload ?? {}, ...(input.waitMs !== undefined ? { waitMs: input.waitMs } : {}) },
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
/** Message in the game chat. */
|
|
316
|
+
async chat(serverId, text, options) {
|
|
317
|
+
return this.send(serverId, { type: "chat", payload: { text }, waitMs: options?.waitMs }, options);
|
|
318
|
+
}
|
|
319
|
+
/** Private message to one online player. */
|
|
320
|
+
async notify(serverId, externalId, message, options) {
|
|
321
|
+
return this.send(serverId, { type: "notify", payload: { externalId, message }, waitMs: options?.waitMs }, options);
|
|
322
|
+
}
|
|
323
|
+
async kick(serverId, externalId, reason, options) {
|
|
324
|
+
return this.send(serverId, { type: "kick", payload: { externalId, ...(reason ? { reason } : {}) }, waitMs: options?.waitMs }, options);
|
|
325
|
+
}
|
|
326
|
+
/** `durationSeconds`: 0 or omitted = permanent. */
|
|
327
|
+
async ban(serverId, externalId, params = {}, options) {
|
|
328
|
+
return this.send(serverId, { type: "ban", payload: { externalId, ...params }, waitMs: options?.waitMs }, options);
|
|
329
|
+
}
|
|
330
|
+
async unban(serverId, externalId, options) {
|
|
331
|
+
return this.send(serverId, { type: "unban", payload: { externalId }, waitMs: options?.waitMs }, options);
|
|
332
|
+
}
|
|
333
|
+
/** Adds (default) or removes an in-game group (ULX, SAM, CAMI, ace groups, LuckPerms or your hooks). */
|
|
334
|
+
async setGroup(serverId, externalId, group, params = {}, options) {
|
|
335
|
+
return this.send(serverId, { type: "set_group", payload: { externalId, group, add: params.add !== false }, waitMs: options?.waitMs }, options);
|
|
336
|
+
}
|
|
337
|
+
async setName(serverId, externalId, name, options) {
|
|
338
|
+
return this.send(serverId, { type: "set_name", payload: { externalId, name }, waitMs: options?.waitMs }, options);
|
|
339
|
+
}
|
|
340
|
+
/** Current in-game groups of the online players, as reported by the addon. */
|
|
341
|
+
async groups(serverId, options) {
|
|
342
|
+
return this.http.request("GET", `${this.base}/servers/${segment(serverId, "serverId")}/groups`, options);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
function snowflake(value) {
|
|
346
|
+
const v = String(value ?? "").trim();
|
|
347
|
+
if (!/^\d{15,22}$/.test(v))
|
|
348
|
+
throw new FlittConfigError("discordId must be a Discord user id (15 to 22 digits).");
|
|
349
|
+
return v;
|
|
350
|
+
}
|
|
351
|
+
// ===========================================================================
|
|
352
|
+
// Vote API client
|
|
353
|
+
// ===========================================================================
|
|
354
|
+
const IDENTITY_PARAMS = {
|
|
355
|
+
player: "player",
|
|
356
|
+
steamId: "steam_id",
|
|
357
|
+
discordId: "discord_id",
|
|
358
|
+
license: "license",
|
|
359
|
+
uuid: "uuid",
|
|
360
|
+
ip: "ip",
|
|
361
|
+
voteId: "vote_id",
|
|
362
|
+
};
|
|
363
|
+
function identityParams(identity) {
|
|
364
|
+
const given = Object.entries(identity ?? {}).filter(([, v]) => v !== undefined && v !== null && String(v).trim() !== "");
|
|
365
|
+
if (given.length !== 1 || !(given[0][0] in IDENTITY_PARAMS)) {
|
|
366
|
+
throw new FlittConfigError("Identify the player with exactly one of: player, steamId, discordId, license, uuid, ip, voteId.");
|
|
367
|
+
}
|
|
368
|
+
const [key, value] = given[0];
|
|
369
|
+
const v = String(value).trim();
|
|
370
|
+
if (v.length > 128)
|
|
371
|
+
throw new FlittConfigError(`${key} is too long.`);
|
|
372
|
+
return { [IDENTITY_PARAMS[key]]: v };
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Client of the Flitt Vote API: reward voters from your own scripts when the
|
|
376
|
+
* Flitt addon is not installed. One token = one server.
|
|
377
|
+
*
|
|
378
|
+
* ```ts
|
|
379
|
+
* import { FlittVotes } from "@flitt/api";
|
|
380
|
+
* const votes = new FlittVotes({ token: process.env.FLITT_VOTE_TOKEN });
|
|
381
|
+
* const claim = await votes.claim({ player: "Alex_RP" });
|
|
382
|
+
* if (claim.status === "CLAIMED_NOW") giveReward("Alex_RP");
|
|
383
|
+
* ```
|
|
384
|
+
*/
|
|
385
|
+
export class FlittVotes {
|
|
386
|
+
#http;
|
|
387
|
+
constructor(options = {}) {
|
|
388
|
+
const token = (options.token ?? envVar("FLITT_VOTE_TOKEN") ?? "").trim();
|
|
389
|
+
if (!token)
|
|
390
|
+
throw new FlittConfigError("Missing vote token: pass { token } or set FLITT_VOTE_TOKEN.");
|
|
391
|
+
if (!VOTE_TOKEN_FORMAT.test(token)) {
|
|
392
|
+
throw new FlittConfigError(token.startsWith("flt_")
|
|
393
|
+
? "This is a Public API key (flt_…): use `new Flitt({ apiKey })` instead."
|
|
394
|
+
: "Invalid vote token format: vote tokens start with flv_ (Dashboard → your server → Votes → Vote API).");
|
|
395
|
+
}
|
|
396
|
+
this.#http = buildTransport(token, options, true);
|
|
397
|
+
}
|
|
398
|
+
/** Quota state from the last response (120 requests / minute per token). */
|
|
399
|
+
get rateLimit() {
|
|
400
|
+
return this.#http.lastRateLimit;
|
|
401
|
+
}
|
|
402
|
+
/** Whether the player has a vote waiting to be claimed (last 24 h). */
|
|
403
|
+
async check(identity, options) {
|
|
404
|
+
return this.#http.request("GET", "/v1/vote-api/votes/check", { ...options, query: identityParams(identity) });
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Claims the player's oldest unclaimed vote, exactly once across every
|
|
408
|
+
* channel (addon, API, NuVotifier). Give the reward only when `status` is
|
|
409
|
+
* `CLAIMED_NOW`. An idempotency key is generated so automatic retries can
|
|
410
|
+
* never claim twice; pass your own to make your retries safe too.
|
|
411
|
+
*/
|
|
412
|
+
async claim(identity, options) {
|
|
413
|
+
const idempotencyKey = options?.idempotencyKey ?? randomKey();
|
|
414
|
+
if (idempotencyKey.length > 128)
|
|
415
|
+
throw new FlittConfigError("idempotencyKey: 128 characters max.");
|
|
416
|
+
return this.#http.request("POST", "/v1/vote-api/votes/claim", { ...options, body: identityParams(identity), idempotencyKey });
|
|
417
|
+
}
|
|
418
|
+
/** Recent votes, oldest first (up to 30 days back), cursor pagination. */
|
|
419
|
+
async list(params = {}, options) {
|
|
420
|
+
return this.#http.request("GET", "/v1/vote-api/votes", {
|
|
421
|
+
...options,
|
|
422
|
+
query: { since: params.since, limit: positiveInt(params.limit, "limit", 100), cursor: params.cursor },
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
/** Iterates over every vote since `since`. */
|
|
426
|
+
async *listAll(params = {}, options) {
|
|
427
|
+
let cursor;
|
|
428
|
+
for (;;) {
|
|
429
|
+
const res = await this.list({ ...params, cursor }, options);
|
|
430
|
+
yield* res.votes;
|
|
431
|
+
if (!res.nextCursor)
|
|
432
|
+
return;
|
|
433
|
+
cursor = res.nextCursor;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
/** Top voters of a month (`current_month`, `last_month`, `all_time` or `YYYY-MM`). */
|
|
437
|
+
async top(params = {}, options) {
|
|
438
|
+
return this.#http.request("GET", "/v1/vote-api/votes/top", {
|
|
439
|
+
...options,
|
|
440
|
+
query: { period: params.period, limit: positiveInt(params.limit, "limit", 50) },
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
/** Server info: status, votes, ranking, reviews (and stats with `includeStats`). */
|
|
444
|
+
async server(params = {}, options) {
|
|
445
|
+
return this.#http.request("GET", "/v1/vote-api/server", { ...options, query: { include: params.includeStats ? "stats" : undefined } });
|
|
446
|
+
}
|
|
447
|
+
/** Daily, weekly and monthly votes, page views and join clicks. */
|
|
448
|
+
async stats(options) {
|
|
449
|
+
return this.#http.request("GET", "/v1/vote-api/server/stats", options);
|
|
450
|
+
}
|
|
451
|
+
/** Published reviews of the server. */
|
|
452
|
+
async reviews(params = {}, options) {
|
|
453
|
+
return this.#http.request("GET", "/v1/vote-api/server/reviews", {
|
|
454
|
+
...options,
|
|
455
|
+
query: { limit: positiveInt(params.limit, "limit", 50), cursor: params.cursor, sort: params.sort },
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
toJSON() {
|
|
459
|
+
return { client: "FlittVotes", token: "[redacted]" };
|
|
460
|
+
}
|
|
461
|
+
[INSPECT]() {
|
|
462
|
+
return "FlittVotes { token: [redacted] }";
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { RateLimit } from "./types.js";
|
|
2
|
+
/** Base class of every error thrown by this package. */
|
|
3
|
+
export declare class FlittError extends Error {
|
|
4
|
+
constructor(message: string, options?: {
|
|
5
|
+
cause?: unknown;
|
|
6
|
+
});
|
|
7
|
+
}
|
|
8
|
+
/** Invalid options or arguments, detected before any request is sent. */
|
|
9
|
+
export declare class FlittConfigError extends FlittError {
|
|
10
|
+
}
|
|
11
|
+
/** The request never got an HTTP response (DNS, TLS, connection reset…). */
|
|
12
|
+
export declare class FlittConnectionError extends FlittError {
|
|
13
|
+
}
|
|
14
|
+
/** No response within `timeoutMs`. */
|
|
15
|
+
export declare class FlittTimeoutError extends FlittConnectionError {
|
|
16
|
+
}
|
|
17
|
+
/** The caller aborted the request with its AbortSignal. */
|
|
18
|
+
export declare class FlittAbortError extends FlittError {
|
|
19
|
+
}
|
|
20
|
+
export type FlittAPIErrorInit = {
|
|
21
|
+
status: number;
|
|
22
|
+
code: string;
|
|
23
|
+
message: string;
|
|
24
|
+
details?: unknown;
|
|
25
|
+
method: string;
|
|
26
|
+
path: string;
|
|
27
|
+
rateLimit?: RateLimit | null;
|
|
28
|
+
retryAfterMs?: number | null;
|
|
29
|
+
};
|
|
30
|
+
/** The API answered with an error status. Never contains your API key. */
|
|
31
|
+
export declare class FlittAPIError extends FlittError {
|
|
32
|
+
/** HTTP status code. */
|
|
33
|
+
readonly status: number;
|
|
34
|
+
/** Machine-readable code, e.g. `NOT_FOUND`, `PLAN_LIMIT`, `RATE_LIMITED`. */
|
|
35
|
+
readonly code: string;
|
|
36
|
+
/** Extra fields sent by the API, if any. */
|
|
37
|
+
readonly details: unknown;
|
|
38
|
+
/** HTTP method of the failed request. */
|
|
39
|
+
readonly method: string;
|
|
40
|
+
/** Path of the failed request, relative to the base URL (query string removed). */
|
|
41
|
+
readonly path: string;
|
|
42
|
+
/** Quota headers of the failed response, when present. */
|
|
43
|
+
readonly rateLimit: RateLimit | null;
|
|
44
|
+
/** Delay suggested by the API before retrying (Retry-After), in ms. */
|
|
45
|
+
readonly retryAfterMs: number | null;
|
|
46
|
+
constructor(init: FlittAPIErrorInit);
|
|
47
|
+
}
|
|
48
|
+
/** 400: missing, invalid or duplicated parameter. */
|
|
49
|
+
export declare class FlittValidationError extends FlittAPIError {
|
|
50
|
+
}
|
|
51
|
+
/** 401: missing, invalid or revoked API key / vote token. */
|
|
52
|
+
export declare class FlittAuthenticationError extends FlittAPIError {
|
|
53
|
+
}
|
|
54
|
+
/** 403: your plan or your role on the server does not allow this. */
|
|
55
|
+
export declare class FlittPermissionError extends FlittAPIError {
|
|
56
|
+
}
|
|
57
|
+
/** 404: the resource does not exist or does not belong to you. */
|
|
58
|
+
export declare class FlittNotFoundError extends FlittAPIError {
|
|
59
|
+
}
|
|
60
|
+
/** 409: conflict (rule already exists, server inactive…). */
|
|
61
|
+
export declare class FlittConflictError extends FlittAPIError {
|
|
62
|
+
}
|
|
63
|
+
/** 429: quota or rate limit reached. See `retryAfterMs` and `rateLimit.reset`. */
|
|
64
|
+
export declare class FlittRateLimitError extends FlittAPIError {
|
|
65
|
+
}
|
|
66
|
+
/** 5xx: temporary error on Flitt's side. Safe to retry later. */
|
|
67
|
+
export declare class FlittServerError extends FlittAPIError {
|
|
68
|
+
}
|
|
69
|
+
/** Builds the most specific error class for a status code. */
|
|
70
|
+
export declare function apiErrorFor(init: FlittAPIErrorInit): FlittAPIError;
|
|
71
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,wDAAwD;AACxD,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAO3D;AAED,yEAAyE;AACzE,qBAAa,gBAAiB,SAAQ,UAAU;CAAG;AAEnD,4EAA4E;AAC5E,qBAAa,oBAAqB,SAAQ,UAAU;CAAG;AAEvD,sCAAsC;AACtC,qBAAa,iBAAkB,SAAQ,oBAAoB;CAAG;AAE9D,2DAA2D;AAC3D,qBAAa,eAAgB,SAAQ,UAAU;CAAG;AAElD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,CAAC;AAEF,0EAA0E;AAC1E,qBAAa,aAAc,SAAQ,UAAU;IAC3C,wBAAwB;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,yCAAyC;IACzC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,mFAAmF;IACnF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;IACrC,uEAAuE;IACvE,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;gBAEzB,IAAI,EAAE,iBAAiB;CAUpC;AAED,qDAAqD;AACrD,qBAAa,oBAAqB,SAAQ,aAAa;CAAG;AAC1D,6DAA6D;AAC7D,qBAAa,wBAAyB,SAAQ,aAAa;CAAG;AAC9D,qEAAqE;AACrE,qBAAa,oBAAqB,SAAQ,aAAa;CAAG;AAC1D,kEAAkE;AAClE,qBAAa,kBAAmB,SAAQ,aAAa;CAAG;AACxD,6DAA6D;AAC7D,qBAAa,kBAAmB,SAAQ,aAAa;CAAG;AACxD,kFAAkF;AAClF,qBAAa,mBAAoB,SAAQ,aAAa;CAAG;AACzD,iEAAiE;AACjE,qBAAa,gBAAiB,SAAQ,aAAa;CAAG;AAEtD,8DAA8D;AAC9D,wBAAgB,WAAW,CAAC,IAAI,EAAE,iBAAiB,GAAG,aAAa,CAUlE"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/** Base class of every error thrown by this package. */
|
|
2
|
+
export class FlittError extends Error {
|
|
3
|
+
constructor(message, options) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = new.target.name;
|
|
6
|
+
if (options && "cause" in options) {
|
|
7
|
+
Object.defineProperty(this, "cause", { value: options.cause, enumerable: false, configurable: true, writable: true });
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/** Invalid options or arguments, detected before any request is sent. */
|
|
12
|
+
export class FlittConfigError extends FlittError {
|
|
13
|
+
}
|
|
14
|
+
/** The request never got an HTTP response (DNS, TLS, connection reset…). */
|
|
15
|
+
export class FlittConnectionError extends FlittError {
|
|
16
|
+
}
|
|
17
|
+
/** No response within `timeoutMs`. */
|
|
18
|
+
export class FlittTimeoutError extends FlittConnectionError {
|
|
19
|
+
}
|
|
20
|
+
/** The caller aborted the request with its AbortSignal. */
|
|
21
|
+
export class FlittAbortError extends FlittError {
|
|
22
|
+
}
|
|
23
|
+
/** The API answered with an error status. Never contains your API key. */
|
|
24
|
+
export class FlittAPIError extends FlittError {
|
|
25
|
+
/** HTTP status code. */
|
|
26
|
+
status;
|
|
27
|
+
/** Machine-readable code, e.g. `NOT_FOUND`, `PLAN_LIMIT`, `RATE_LIMITED`. */
|
|
28
|
+
code;
|
|
29
|
+
/** Extra fields sent by the API, if any. */
|
|
30
|
+
details;
|
|
31
|
+
/** HTTP method of the failed request. */
|
|
32
|
+
method;
|
|
33
|
+
/** Path of the failed request, relative to the base URL (query string removed). */
|
|
34
|
+
path;
|
|
35
|
+
/** Quota headers of the failed response, when present. */
|
|
36
|
+
rateLimit;
|
|
37
|
+
/** Delay suggested by the API before retrying (Retry-After), in ms. */
|
|
38
|
+
retryAfterMs;
|
|
39
|
+
constructor(init) {
|
|
40
|
+
super(`${init.status} ${init.code}: ${init.message}`);
|
|
41
|
+
this.status = init.status;
|
|
42
|
+
this.code = init.code;
|
|
43
|
+
this.details = init.details;
|
|
44
|
+
this.method = init.method;
|
|
45
|
+
this.path = init.path;
|
|
46
|
+
this.rateLimit = init.rateLimit ?? null;
|
|
47
|
+
this.retryAfterMs = init.retryAfterMs ?? null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** 400: missing, invalid or duplicated parameter. */
|
|
51
|
+
export class FlittValidationError extends FlittAPIError {
|
|
52
|
+
}
|
|
53
|
+
/** 401: missing, invalid or revoked API key / vote token. */
|
|
54
|
+
export class FlittAuthenticationError extends FlittAPIError {
|
|
55
|
+
}
|
|
56
|
+
/** 403: your plan or your role on the server does not allow this. */
|
|
57
|
+
export class FlittPermissionError extends FlittAPIError {
|
|
58
|
+
}
|
|
59
|
+
/** 404: the resource does not exist or does not belong to you. */
|
|
60
|
+
export class FlittNotFoundError extends FlittAPIError {
|
|
61
|
+
}
|
|
62
|
+
/** 409: conflict (rule already exists, server inactive…). */
|
|
63
|
+
export class FlittConflictError extends FlittAPIError {
|
|
64
|
+
}
|
|
65
|
+
/** 429: quota or rate limit reached. See `retryAfterMs` and `rateLimit.reset`. */
|
|
66
|
+
export class FlittRateLimitError extends FlittAPIError {
|
|
67
|
+
}
|
|
68
|
+
/** 5xx: temporary error on Flitt's side. Safe to retry later. */
|
|
69
|
+
export class FlittServerError extends FlittAPIError {
|
|
70
|
+
}
|
|
71
|
+
/** Builds the most specific error class for a status code. */
|
|
72
|
+
export function apiErrorFor(init) {
|
|
73
|
+
const s = init.status;
|
|
74
|
+
if (s === 400 || s === 422)
|
|
75
|
+
return new FlittValidationError(init);
|
|
76
|
+
if (s === 401)
|
|
77
|
+
return new FlittAuthenticationError(init);
|
|
78
|
+
if (s === 403)
|
|
79
|
+
return new FlittPermissionError(init);
|
|
80
|
+
if (s === 404)
|
|
81
|
+
return new FlittNotFoundError(init);
|
|
82
|
+
if (s === 409)
|
|
83
|
+
return new FlittConflictError(init);
|
|
84
|
+
if (s === 429)
|
|
85
|
+
return new FlittRateLimitError(init);
|
|
86
|
+
if (s >= 500)
|
|
87
|
+
return new FlittServerError(init);
|
|
88
|
+
return new FlittAPIError(init);
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=errors.js.map
|