@libertytools/libertyjs 1.0.1
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/package.json +28 -0
- package/readme.md +359 -0
- package/src/index.js +309 -0
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@libertytools/libertyjs",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "An SDK to help developers create apps for the ER:LC Private Server API.",
|
|
5
|
+
"author": "novix",
|
|
6
|
+
"license": "ISC",
|
|
7
|
+
|
|
8
|
+
"type": "module",
|
|
9
|
+
|
|
10
|
+
"main": "./src/index.js",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": "./src/index.js"
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
"files": [
|
|
16
|
+
"src"
|
|
17
|
+
],
|
|
18
|
+
|
|
19
|
+
"keywords": [
|
|
20
|
+
"erlc",
|
|
21
|
+
"police roleplay community",
|
|
22
|
+
"liberty county"
|
|
23
|
+
],
|
|
24
|
+
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=18"
|
|
27
|
+
}
|
|
28
|
+
}
|
package/readme.md
ADDED
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
# LibertyJS
|
|
2
|
+
|
|
3
|
+
A lightweight SDK for the **ER:LC Private Server API**, designed to simplify requests, enforce rate limits, and provide structured error handling.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
* Automatic **rate limit handling** (GET + POST)
|
|
10
|
+
* Built-in **API key validation**
|
|
11
|
+
* **403 fail-safe** (halts after repeated failures)
|
|
12
|
+
* Optional **webhook integration**
|
|
13
|
+
* Structured **error responses**
|
|
14
|
+
* Automatic **JSON handling for POST requests**
|
|
15
|
+
* Built-in **command validation + argument checking**
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Importing
|
|
20
|
+
|
|
21
|
+
```js
|
|
22
|
+
import LibertyJS from "libertyjs";
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Initialization
|
|
28
|
+
|
|
29
|
+
```js
|
|
30
|
+
const LJS = new LibertyJS({
|
|
31
|
+
SERVER_KEY: process.env.SERVER_KEY,
|
|
32
|
+
PRIVATE_SERVER_API: "https://api.policeroleplay.community/v2/", // optional
|
|
33
|
+
WEBHOOK_URL: process.env.WEBHOOK_URL, // optional
|
|
34
|
+
WEBHOOK_TOKEN: process.env.WEBHOOK_TOKEN // required if WEBHOOK_URL is used
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Configuration Options
|
|
41
|
+
|
|
42
|
+
| Option | Required | Description |
|
|
43
|
+
| -------------------- | -------- | ------------------------------------- |
|
|
44
|
+
| `SERVER_KEY` | ✅ | ER:LC private server API key |
|
|
45
|
+
| `PRIVATE_SERVER_API` | ❌ | Base API URL (defaults to PRC v2) |
|
|
46
|
+
| `WEBHOOK_URL` | ❌ | Webhook base URL |
|
|
47
|
+
| `WEBHOOK_TOKEN` | ⚠️ | Required if `WEBHOOK_URL` is provided |
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
# Methods
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## `getPrivateServerAPI(options, includeInvalid?)`
|
|
56
|
+
|
|
57
|
+
Fetch data from the ER:LC Private Server API.
|
|
58
|
+
|
|
59
|
+
### Example
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
const data = await LJS.getPrivateServerAPI([
|
|
63
|
+
"Players",
|
|
64
|
+
"Staff"
|
|
65
|
+
]);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
### Parameters
|
|
71
|
+
|
|
72
|
+
| Parameter | Type | Description |
|
|
73
|
+
| ---------------- | ---------- | ----------------------------------- |
|
|
74
|
+
| `options` | `string[]` | List of data types to request |
|
|
75
|
+
| `includeInvalid` | `boolean` | Include invalid options in response |
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
### Valid Options
|
|
80
|
+
|
|
81
|
+
* Players
|
|
82
|
+
* Staff
|
|
83
|
+
* JoinLogs
|
|
84
|
+
* Queue
|
|
85
|
+
* KillLogs
|
|
86
|
+
* CommandLogs
|
|
87
|
+
* ModCalls
|
|
88
|
+
* EmergencyCalls
|
|
89
|
+
* Vehicles
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
### Behavior
|
|
94
|
+
|
|
95
|
+
* Automatically appends `/server`
|
|
96
|
+
* Builds query string internally
|
|
97
|
+
* Filters invalid options
|
|
98
|
+
* Waits automatically if rate-limited
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
### Example with Invalid Tracking
|
|
103
|
+
|
|
104
|
+
```js
|
|
105
|
+
const res = await LJS.getPrivateServerAPI(
|
|
106
|
+
["Players", "InvalidOption"],
|
|
107
|
+
true
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
console.log(res);
|
|
111
|
+
/*
|
|
112
|
+
{
|
|
113
|
+
data: {...},
|
|
114
|
+
invalidOptions: ["InvalidOption"]
|
|
115
|
+
}
|
|
116
|
+
*/
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
### Errors
|
|
122
|
+
|
|
123
|
+
#### Invalid Input
|
|
124
|
+
|
|
125
|
+
```js
|
|
126
|
+
{
|
|
127
|
+
error: "invalid_input",
|
|
128
|
+
message: "[LibertyJS.getPrivateServerAPI]: Options must be an array"
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
#### Forbidden (after 2 failures)
|
|
135
|
+
|
|
136
|
+
```js
|
|
137
|
+
{
|
|
138
|
+
error: "forbidden",
|
|
139
|
+
message: "[LibertyJS]: Received a 403 error 2 times, suspending API calls as the server key may be invalid"
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
#### API Error
|
|
146
|
+
|
|
147
|
+
```js
|
|
148
|
+
{
|
|
149
|
+
error: "api-error",
|
|
150
|
+
message: "[LibertyJS]: Encountered an error while attempting to fetch <url>",
|
|
151
|
+
apiResponse: { ... }
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## `sendPrivateServerCommand(commands)`
|
|
158
|
+
|
|
159
|
+
Send one or more commands to the private server.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
### Example
|
|
164
|
+
|
|
165
|
+
```js
|
|
166
|
+
const res = await LJS.sendPrivateServerCommand([
|
|
167
|
+
":h Hello world!",
|
|
168
|
+
":kick PlayerName Spamming"
|
|
169
|
+
]);
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
### Parameters
|
|
175
|
+
|
|
176
|
+
| Parameter | Type | Description |
|
|
177
|
+
| ---------- | ---------- | ------------------------ |
|
|
178
|
+
| `commands` | `string[]` | Array of command strings |
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
### Behavior
|
|
183
|
+
|
|
184
|
+
* Validates:
|
|
185
|
+
|
|
186
|
+
* Command existence
|
|
187
|
+
* Argument count
|
|
188
|
+
* Ignores:
|
|
189
|
+
|
|
190
|
+
* Invalid commands
|
|
191
|
+
* Incorrect argument usage
|
|
192
|
+
* Sends commands **sequentially**
|
|
193
|
+
* Tracks success/failure per command
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
### Response
|
|
198
|
+
|
|
199
|
+
```js
|
|
200
|
+
{
|
|
201
|
+
successes: 2,
|
|
202
|
+
failures: 0,
|
|
203
|
+
failureReasons: []
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
### Failure Example
|
|
210
|
+
|
|
211
|
+
```js
|
|
212
|
+
{
|
|
213
|
+
successes: 1,
|
|
214
|
+
failures: 1,
|
|
215
|
+
failureReasons: [
|
|
216
|
+
{
|
|
217
|
+
command: ":kick Player",
|
|
218
|
+
apiResponse: { ... }
|
|
219
|
+
}
|
|
220
|
+
]
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
### Errors
|
|
227
|
+
|
|
228
|
+
#### Invalid Input
|
|
229
|
+
|
|
230
|
+
```js
|
|
231
|
+
{
|
|
232
|
+
error: "invalid_input",
|
|
233
|
+
message: "[LibertyJS.sendPrivateServerCommand]: Options must be an array"
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
#### Empty Array
|
|
238
|
+
|
|
239
|
+
```js
|
|
240
|
+
{
|
|
241
|
+
error: "invalid_input",
|
|
242
|
+
message: "[LibertyJS.sendPrivateServerCommand]: Options must have at least one item"
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
# Webhook API
|
|
249
|
+
|
|
250
|
+
> Webhooks are accessed via a **nested object**, not top-level methods.
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## `webhook.status()`
|
|
255
|
+
|
|
256
|
+
Check webhook health.
|
|
257
|
+
|
|
258
|
+
### Example
|
|
259
|
+
|
|
260
|
+
```js
|
|
261
|
+
const res = await LJS.webhook.status();
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
### Errors
|
|
267
|
+
|
|
268
|
+
#### Webhook Disabled
|
|
269
|
+
|
|
270
|
+
```js
|
|
271
|
+
{
|
|
272
|
+
error: "webhook_disabled",
|
|
273
|
+
message: "[LibertyJS.webhook.status]: Webhook is not configured"
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## `webhook.events()`
|
|
280
|
+
|
|
281
|
+
Fetch webhook events.
|
|
282
|
+
|
|
283
|
+
### Example
|
|
284
|
+
|
|
285
|
+
```js
|
|
286
|
+
const events = await LJS.webhook.events();
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
### Errors
|
|
292
|
+
|
|
293
|
+
#### Webhook Disabled
|
|
294
|
+
|
|
295
|
+
```js
|
|
296
|
+
{
|
|
297
|
+
error: "webhook_disabled",
|
|
298
|
+
message: "[LibertyJS.webhook.events]: Webhook is not configured"
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
# Internal Behavior
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## Rate Limiting
|
|
309
|
+
|
|
310
|
+
Tracked separately for GET and POST:
|
|
311
|
+
|
|
312
|
+
```js
|
|
313
|
+
{
|
|
314
|
+
get: { limit, remaining, reset },
|
|
315
|
+
post: { limit, remaining, reset }
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
### Details
|
|
322
|
+
|
|
323
|
+
* Uses headers:
|
|
324
|
+
|
|
325
|
+
* `X-RateLimit-Limit`
|
|
326
|
+
* `X-RateLimit-Remaining`
|
|
327
|
+
* `X-RateLimit-Reset`
|
|
328
|
+
* Automatically delays requests when:
|
|
329
|
+
|
|
330
|
+
```
|
|
331
|
+
remaining === 0 && currentTime < reset
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
* Logs:
|
|
335
|
+
|
|
336
|
+
```
|
|
337
|
+
[LibertyJS]: Rate limited (GET/POST). Waiting Xs
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
## Forbidden Protection
|
|
343
|
+
|
|
344
|
+
After **2 consecutive `403` responses**:
|
|
345
|
+
|
|
346
|
+
* All future API calls are blocked
|
|
347
|
+
* Prevents invalid API key spam
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
## Request Handling (`#fetchAPI`)
|
|
352
|
+
|
|
353
|
+
Handles:
|
|
354
|
+
|
|
355
|
+
* Authentication headers (`server-key`)
|
|
356
|
+
* JSON parsing (safe fallback to `null`)
|
|
357
|
+
* Rate limit tracking
|
|
358
|
+
* Error normalization
|
|
359
|
+
* Automatic JSON stringification for POST bodies
|
package/src/index.js
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
export default class LibertyJS {
|
|
2
|
+
#SERVER_KEY;
|
|
3
|
+
#PRIVATE_SERVER_API;
|
|
4
|
+
#useWebhook;
|
|
5
|
+
#WEBHOOK_URL;
|
|
6
|
+
#WEBHOOK_TOKEN;
|
|
7
|
+
#rateLimits;
|
|
8
|
+
#resStatus;
|
|
9
|
+
|
|
10
|
+
constructor({
|
|
11
|
+
SERVER_KEY,
|
|
12
|
+
PRIVATE_SERVER_API = "https://api.policeroleplay.community/v2/",
|
|
13
|
+
WEBHOOK_URL,
|
|
14
|
+
WEBHOOK_TOKEN
|
|
15
|
+
} = {}) {
|
|
16
|
+
if (!SERVER_KEY) {
|
|
17
|
+
throw new Error("[LibertyJS]: SERVER_KEY is required");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
this.#SERVER_KEY = SERVER_KEY;
|
|
21
|
+
this.#PRIVATE_SERVER_API = PRIVATE_SERVER_API;
|
|
22
|
+
|
|
23
|
+
if (WEBHOOK_URL && !WEBHOOK_TOKEN) {
|
|
24
|
+
throw new Error("[LibertyJS]: WEBHOOK_TOKEN is required if you are using a webhook");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
this.#useWebhook = Boolean(WEBHOOK_URL && WEBHOOK_TOKEN);
|
|
28
|
+
|
|
29
|
+
if (WEBHOOK_URL && WEBHOOK_TOKEN) {
|
|
30
|
+
this.#WEBHOOK_URL = WEBHOOK_URL;
|
|
31
|
+
this.#WEBHOOK_TOKEN = WEBHOOK_TOKEN;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
this.#rateLimits = {
|
|
35
|
+
get: { limit: null, remaining: null, reset: null },
|
|
36
|
+
post: { limit: null, remaining: null, reset: null }
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
this.#resStatus = {
|
|
40
|
+
forbiddenErrors: 0
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
#wait(seconds) {
|
|
45
|
+
return new Promise(resolve => setTimeout(resolve, seconds * 1000));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async #fetchAPI(url, options = {}) {
|
|
49
|
+
if (!this.#SERVER_KEY) {
|
|
50
|
+
return {
|
|
51
|
+
error: "invalid_env",
|
|
52
|
+
message: "[LibertyJS]: SERVER_KEY was not provided in a .env file"
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (this.#resStatus.forbiddenErrors >= 2) {
|
|
57
|
+
return {
|
|
58
|
+
error: "forbidden",
|
|
59
|
+
message: "[LibertyJS]: Received a 403 error 2 times, suspending API calls as the server key may be invalid"
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const isPRC = url.startsWith("https://api.policeroleplay.community/");
|
|
64
|
+
const method = (options.method || "GET").toUpperCase();
|
|
65
|
+
|
|
66
|
+
const headers = { ...(options.headers || {}) };
|
|
67
|
+
|
|
68
|
+
let body = options.body;
|
|
69
|
+
if (method === "POST" && body !== undefined) {
|
|
70
|
+
headers["Content-Type"] = "application/json";
|
|
71
|
+
body = typeof body === "string" ? body : JSON.stringify(body);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (isPRC) {
|
|
75
|
+
headers["server-key"] = this.#SERVER_KEY;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const currentTime = Math.floor(Date.now() / 1000);
|
|
79
|
+
|
|
80
|
+
const handleRateLimit = async (rl) => {
|
|
81
|
+
if (rl.reset && rl.remaining === 0 && currentTime < rl.reset) {
|
|
82
|
+
const seconds = Math.max(0, rl.reset - currentTime);
|
|
83
|
+
console.log(`[LibertyJS]: Rate limited (${method}). Waiting ${seconds}s`);
|
|
84
|
+
await this.#wait(seconds);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
if (isPRC) {
|
|
89
|
+
if (method === "GET") await handleRateLimit(this.#rateLimits.get);
|
|
90
|
+
if (method === "POST") await handleRateLimit(this.#rateLimits.post);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const res = await fetch(url, {
|
|
94
|
+
...options,
|
|
95
|
+
method,
|
|
96
|
+
headers,
|
|
97
|
+
body
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
let data;
|
|
101
|
+
try {
|
|
102
|
+
data = await res.json();
|
|
103
|
+
} catch {
|
|
104
|
+
data = null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (!res.ok) {
|
|
108
|
+
if (res.status === 403 && isPRC) {
|
|
109
|
+
this.#resStatus.forbiddenErrors++;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
error: "api-error",
|
|
114
|
+
message: `[LibertyJS]: Encountered an error while attempting to fetch ${url}`,
|
|
115
|
+
apiResponse: data
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (isPRC) {
|
|
120
|
+
const target = method === "GET"
|
|
121
|
+
? this.#rateLimits.get
|
|
122
|
+
: this.#rateLimits.post;
|
|
123
|
+
|
|
124
|
+
target.reset = Number(res.headers.get("X-RateLimit-Reset"));
|
|
125
|
+
target.limit = Number(res.headers.get("X-RateLimit-Limit"));
|
|
126
|
+
target.remaining = Number(res.headers.get("X-RateLimit-Remaining"));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return data;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async getPrivateServerAPI(options = [], includeInvalid = false) {
|
|
133
|
+
const valid = [
|
|
134
|
+
"Players",
|
|
135
|
+
"Staff",
|
|
136
|
+
"JoinLogs",
|
|
137
|
+
"Queue",
|
|
138
|
+
"KillLogs",
|
|
139
|
+
"CommandLogs",
|
|
140
|
+
"ModCalls",
|
|
141
|
+
"EmergencyCalls",
|
|
142
|
+
"Vehicles"
|
|
143
|
+
];
|
|
144
|
+
|
|
145
|
+
if (!Array.isArray(options)) {
|
|
146
|
+
console.error("[LibertyJS.getPrivateServerAPI]: Options must be an array");
|
|
147
|
+
return {
|
|
148
|
+
error: "invalid_input",
|
|
149
|
+
message: "[LibertyJS.getPrivateServerAPI]: Options must be an array"
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const params = [];
|
|
154
|
+
const invalidOptions = [];
|
|
155
|
+
|
|
156
|
+
for (const opt of options) {
|
|
157
|
+
if (valid.includes(opt)) {
|
|
158
|
+
params.push(`${opt}=true`);
|
|
159
|
+
} else {
|
|
160
|
+
console.log(`[LibertyJS]: Invalid option "${String(opt)}"`);
|
|
161
|
+
invalidOptions.push(opt);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const query = params.length ? `?${params.join("&")}` : "";
|
|
166
|
+
const url = this.#PRIVATE_SERVER_API + "server" + query;
|
|
167
|
+
|
|
168
|
+
if (!includeInvalid) {
|
|
169
|
+
return await this.#fetchAPI(url);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
data: await this.#fetchAPI(url),
|
|
174
|
+
invalidOptions
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
async sendPrivateServerCommand(options = []) {
|
|
179
|
+
const url = this.#PRIVATE_SERVER_API + "server/command";
|
|
180
|
+
|
|
181
|
+
const valid = {
|
|
182
|
+
":wanted": ["Player"],
|
|
183
|
+
":time": ["Number"],
|
|
184
|
+
":stopfire": [],
|
|
185
|
+
":respawn": ["Player"],
|
|
186
|
+
":tp": ["Player", "Player"],
|
|
187
|
+
":startnearfire": ["String"],
|
|
188
|
+
":jail": ["Player"],
|
|
189
|
+
":pt": ["Number"],
|
|
190
|
+
":h": ["String"],
|
|
191
|
+
":m": ["String"],
|
|
192
|
+
":pm": ["Player", "String"],
|
|
193
|
+
":refresh": ["Player"],
|
|
194
|
+
":bring": ["Player"],
|
|
195
|
+
":heal": ["Player"],
|
|
196
|
+
":kick": ["Player", "String"],
|
|
197
|
+
":startfire": ["String"],
|
|
198
|
+
":unwanted": ["Player"],
|
|
199
|
+
":prty": ["Number"],
|
|
200
|
+
":stopdumpsterfire": [],
|
|
201
|
+
":helper": ["Player/UserId"],
|
|
202
|
+
":shutdown": [],
|
|
203
|
+
":weather": ["String"],
|
|
204
|
+
":unmod": ["Player/UserId"],
|
|
205
|
+
":unloadlayout": ["String"],
|
|
206
|
+
":unban": ["String"],
|
|
207
|
+
":mod": ["Player/UserId"],
|
|
208
|
+
":ban": ["Player/UserId"],
|
|
209
|
+
":unhelper": ["Player/UserId"],
|
|
210
|
+
":log": ["String"],
|
|
211
|
+
":kill": ["Player"],
|
|
212
|
+
":unadmin": ["Player/UserId"],
|
|
213
|
+
":admin": ["Player/UserId"],
|
|
214
|
+
":loadlayout": ["String"]
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
if (!Array.isArray(options)) {
|
|
218
|
+
console.error("[LibertyJS.sendPrivateServerCommand]: Options must be an array");
|
|
219
|
+
return {
|
|
220
|
+
error: "invalid_input",
|
|
221
|
+
message: "[LibertyJS.sendPrivateServerCommand]: Options must be an array"
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (options.length === 0) {
|
|
226
|
+
console.error("[LibertyJS.sendPrivateServerCommand]: Options must have at least one item");
|
|
227
|
+
return {
|
|
228
|
+
error: "invalid_input",
|
|
229
|
+
message: "[LibertyJS.sendPrivateServerCommand]: Options must have at least one item"
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const commands = [];
|
|
234
|
+
|
|
235
|
+
for (const cmd of options) {
|
|
236
|
+
if (!cmd.startsWith(":")) continue;
|
|
237
|
+
|
|
238
|
+
const parts = cmd.trim().split(" ");
|
|
239
|
+
const name = parts[0];
|
|
240
|
+
const args = parts.slice(1);
|
|
241
|
+
const schema = valid[name];
|
|
242
|
+
|
|
243
|
+
if (!schema) {
|
|
244
|
+
console.error(`[LibertyJS]: Unsupported command "${name}"`);
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const validArgs =
|
|
249
|
+
(schema.at(-1) === "String" && args.length >= schema.length) ||
|
|
250
|
+
(schema.at(-1) !== "String" && args.length === schema.length);
|
|
251
|
+
|
|
252
|
+
if (validArgs) {
|
|
253
|
+
commands.push(cmd);
|
|
254
|
+
} else {
|
|
255
|
+
console.log(`[LibertyJS]: "${name}" requires ${schema.length}${schema.at(-1) === "String" ? "+" : ""} args`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
let successes = 0;
|
|
260
|
+
let failures = 0;
|
|
261
|
+
const failureReasons = [];
|
|
262
|
+
|
|
263
|
+
for (const command of commands) {
|
|
264
|
+
const res = await this.#fetchAPI(url, {
|
|
265
|
+
method: "POST",
|
|
266
|
+
body: command
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
if (!res?.error) {
|
|
270
|
+
successes++;
|
|
271
|
+
} else {
|
|
272
|
+
failures++;
|
|
273
|
+
failureReasons.push({
|
|
274
|
+
command,
|
|
275
|
+
apiResponse: res.apiResponse
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return { successes, failures, failureReasons };
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
webhook = {
|
|
284
|
+
status: async () => {
|
|
285
|
+
if (!this.#useWebhook) {
|
|
286
|
+
return {
|
|
287
|
+
error: "webhook_disabled",
|
|
288
|
+
message: "[LibertyJS.webhook.status]: Webhook is not configured"
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const url = `${this.#WEBHOOK_URL}health`;
|
|
293
|
+
|
|
294
|
+
return await this.#fetchAPI(url, { method: "GET" });
|
|
295
|
+
},
|
|
296
|
+
events: async () => {
|
|
297
|
+
if (!this.#useWebhook) {
|
|
298
|
+
return {
|
|
299
|
+
error: "webhook_disabled",
|
|
300
|
+
message: "[LibertyJS.webhook.events]: Webhook is not configured"
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const url = `${this.#WEBHOOK_URL}webhook/${this.#WEBHOOK_TOKEN}/events`;
|
|
305
|
+
|
|
306
|
+
return await this.#fetchAPI(url, { method: "GET" });
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
}
|