unb-api 1.5.1 → 2.1.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/README.md +35 -29
- package/eslintrc.js +7 -0
- package/index.d.ts +2 -0
- package/package.json +4 -4
- package/src/lib/RequestHandler.js +45 -19
- package/src/lib/structures/items/BaseItem.js +2 -0
package/README.md
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
|
|
11
11
|
`npm install unb-api`
|
|
12
12
|
|
|
13
|
+
Requires Node.js 18 or newer (uses the built-in `fetch`). For older Node.js versions, use `unb-api@1`.
|
|
14
|
+
|
|
13
15
|
## Documentation
|
|
14
16
|
|
|
15
17
|
Full API documentation is located at [https://unbelievaboat.com/api/docs](https://unbelievaboat.com/api/docs)
|
|
@@ -130,38 +132,42 @@ Returns: `Promise<any>`
|
|
|
130
132
|
|
|
131
133
|
#### StoreItem
|
|
132
134
|
|
|
133
|
-
| Type | Property
|
|
134
|
-
|
|
135
|
-
| String | `id`
|
|
136
|
-
| String | `name`
|
|
137
|
-
| String | `description?`
|
|
138
|
-
| Number | `price`
|
|
139
|
-
| Number | `stockRemaining`
|
|
140
|
-
| Boolean | `unlimitedStock`
|
|
141
|
-
| Number | `maxQuantity?`
|
|
142
|
-
| Boolean | `isInventory`
|
|
143
|
-
| Date | `expiresAt?`
|
|
144
|
-
| Boolean | `isUsable`
|
|
145
|
-
| Boolean | `isSellable`
|
|
146
|
-
|
|
|
147
|
-
|
|
|
148
|
-
|
|
|
149
|
-
|
|
|
135
|
+
| Type | Property | Description |
|
|
136
|
+
|---------|-----------------------|---------------------------------------------------------------------------|
|
|
137
|
+
| String | `id` | Unique ID of the item in the store. |
|
|
138
|
+
| String | `name` | Name of the item. |
|
|
139
|
+
| String | `description?` | Description of the item. |
|
|
140
|
+
| Number | `price` | Price of the item. |
|
|
141
|
+
| Number | `stockRemaining` | Amount of stock remaining for the item. |
|
|
142
|
+
| Boolean | `unlimitedStock` | Whether the item has unlimited stock. |
|
|
143
|
+
| Number | `maxQuantity?` | Max a user can own, or buy at once if not an inventory item. |
|
|
144
|
+
| Boolean | `isInventory` | Indicates if the item will be added to a user’s inventory when purchased. |
|
|
145
|
+
| Date | `expiresAt?` | Expiration date of the item. |
|
|
146
|
+
| Boolean | `isUsable` | Whether the item can be used by the user. |
|
|
147
|
+
| Boolean | `isSellable` | Whether the item can be sold by the user. |
|
|
148
|
+
| Boolean | `isReusable` | Whether the item stays in the inventory when used. |
|
|
149
|
+
| Number | `useCooldownSeconds?` | Seconds a user must wait between uses of the item. |
|
|
150
|
+
| Array | `requirements` | Requirements needed to purchase the item. |
|
|
151
|
+
| Array | `actions` | Actions performed when the item is used. |
|
|
152
|
+
| String | `emojiUnicode?` | Unicode emoji associated with the item. |
|
|
153
|
+
| String | `emojiId?` | Custom emoji ID associated with the item. |
|
|
150
154
|
|
|
151
155
|
#### InventoryItem
|
|
152
156
|
|
|
153
|
-
| Type | Property
|
|
154
|
-
|
|
155
|
-
| String | `itemId`
|
|
156
|
-
| Number | `quantity`
|
|
157
|
-
| String | `name`
|
|
158
|
-
| String | `description?`
|
|
159
|
-
| Boolean | `isUsable`
|
|
160
|
-
| Boolean | `isSellable`
|
|
161
|
-
|
|
|
162
|
-
|
|
|
163
|
-
|
|
|
164
|
-
|
|
|
157
|
+
| Type | Property | Description |
|
|
158
|
+
|-------------------------------------------------|-----------------------|----------------------------------------------------|
|
|
159
|
+
| String | `itemId` | Unique ID of the item in the inventory. |
|
|
160
|
+
| Number | `quantity` | Quantity of the item in the user's inventory. |
|
|
161
|
+
| String | `name` | Name of the item. |
|
|
162
|
+
| String | `description?` | Description of the item. |
|
|
163
|
+
| Boolean | `isUsable` | Whether the item can be used by the user. |
|
|
164
|
+
| Boolean | `isSellable` | Whether the item can be sold by the user. |
|
|
165
|
+
| Boolean | `isReusable` | Whether the item stays in the inventory when used. |
|
|
166
|
+
| Number | `useCooldownSeconds?` | Seconds a user must wait between uses of the item. |
|
|
167
|
+
| [StoreItemRequirement[]](#StoreItemRequirement) | `requirements` | Requirements needed to use the item. |
|
|
168
|
+
| [StoreItemAction[]](#StoreItemAction) | `actions` | Actions performed when the item is used. |
|
|
169
|
+
| String | `emojiUnicode?` | Unicode emoji associated with the item. |
|
|
170
|
+
| String | `emojiId?` | Custom emoji ID associated with the item. |
|
|
165
171
|
|
|
166
172
|
#### StoreItemRequirement
|
|
167
173
|
|
package/eslintrc.js
CHANGED
package/index.d.ts
CHANGED
|
@@ -98,6 +98,8 @@ declare module 'unb-api' {
|
|
|
98
98
|
public description?: string;
|
|
99
99
|
public isUsable: boolean;
|
|
100
100
|
public isSellable: boolean;
|
|
101
|
+
public isReusable: boolean;
|
|
102
|
+
public useCooldownSeconds: number | null;
|
|
101
103
|
public requirements: StoreItemRequirement[];
|
|
102
104
|
public actions: StoreItemAction[];
|
|
103
105
|
public emojiUnicode?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "unb-api",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "API wrapper for UnbelievaBoat Discord Bot API",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
],
|
|
17
17
|
"author": "unbelievable",
|
|
18
18
|
"license": "MIT",
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=18"
|
|
21
|
+
},
|
|
19
22
|
"devDependencies": {
|
|
20
23
|
"@types/node": "^10.0.7",
|
|
21
24
|
"eslint": "^6.7.2",
|
|
22
25
|
"typescript": "^2.6.2"
|
|
23
|
-
},
|
|
24
|
-
"dependencies": {
|
|
25
|
-
"axios": "^1.20.0"
|
|
26
26
|
}
|
|
27
27
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const axios = require('axios');
|
|
2
1
|
const Bucket = require('./util/Bucket');
|
|
3
2
|
const { APIError, HTTPError } = require('./errors');
|
|
4
3
|
const MajorParams = ['guilds'];
|
|
@@ -7,13 +6,6 @@ class RequestHandler {
|
|
|
7
6
|
constructor(client) {
|
|
8
7
|
this._client = client;
|
|
9
8
|
this.ratelimits = {};
|
|
10
|
-
this.axiosInstance = axios.create({
|
|
11
|
-
baseURL: this._client.baseURL,
|
|
12
|
-
headers: {
|
|
13
|
-
'Authorization': this._client.token,
|
|
14
|
-
'Content-Type': 'application/json'
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
9
|
}
|
|
18
10
|
|
|
19
11
|
async request(method, endpoint, data = {}, params = {}, _attempts = 0) {
|
|
@@ -32,7 +24,7 @@ class RequestHandler {
|
|
|
32
24
|
};
|
|
33
25
|
|
|
34
26
|
try {
|
|
35
|
-
const { data: responseData, status, headers } = await this.
|
|
27
|
+
const { data: responseData, status, statusText, headers } = await this.fetch(options);
|
|
36
28
|
|
|
37
29
|
// Increase the number of attempts
|
|
38
30
|
++_attempts;
|
|
@@ -44,21 +36,17 @@ class RequestHandler {
|
|
|
44
36
|
resolve(responseData);
|
|
45
37
|
} else if (status === 429) {
|
|
46
38
|
if (_attempts >= this._client.maxRetries) {
|
|
47
|
-
this.rejectWithError(options, responseData, status, reject);
|
|
39
|
+
this.rejectWithError(options, responseData, status, statusText, reject);
|
|
48
40
|
} else {
|
|
49
41
|
this.retryRequest(method, endpoint, data, params, _attempts, headers, resolve, reject);
|
|
50
42
|
}
|
|
51
43
|
} else {
|
|
52
|
-
this.rejectWithError(options, responseData, status, reject);
|
|
44
|
+
this.rejectWithError(options, responseData, status, statusText, reject);
|
|
53
45
|
}
|
|
54
46
|
|
|
55
47
|
callback();
|
|
56
48
|
} catch (error) {
|
|
57
|
-
|
|
58
|
-
this.rejectWithError(options, error.response.data, error.response.status, reject);
|
|
59
|
-
} else {
|
|
60
|
-
reject(error);
|
|
61
|
-
}
|
|
49
|
+
reject(error);
|
|
62
50
|
callback();
|
|
63
51
|
}
|
|
64
52
|
};
|
|
@@ -67,11 +55,49 @@ class RequestHandler {
|
|
|
67
55
|
});
|
|
68
56
|
}
|
|
69
57
|
|
|
70
|
-
|
|
58
|
+
async fetch(options) {
|
|
59
|
+
const url = new URL(`${this._client.baseURL.replace(/\/+$/, '')}${options.url}`);
|
|
60
|
+
for (const [key, value] of Object.entries(options.params || {})) {
|
|
61
|
+
if (value === undefined || value === null) continue;
|
|
62
|
+
if (Array.isArray(value)) {
|
|
63
|
+
for (const v of value) url.searchParams.append(`${key}[]`, v);
|
|
64
|
+
} else {
|
|
65
|
+
url.searchParams.append(key, value);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const response = await fetch(url, {
|
|
70
|
+
method: options.method,
|
|
71
|
+
headers: {
|
|
72
|
+
'Authorization': this._client.token,
|
|
73
|
+
'Content-Type': 'application/json'
|
|
74
|
+
},
|
|
75
|
+
body: ['GET', 'HEAD'].includes(options.method) ? undefined : JSON.stringify(options.data)
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const text = await response.text();
|
|
79
|
+
let data = text;
|
|
80
|
+
if (text) {
|
|
81
|
+
try {
|
|
82
|
+
data = JSON.parse(text);
|
|
83
|
+
} catch (e) {
|
|
84
|
+
// Not JSON (e.g. an HTML error page from a proxy), keep the raw text
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
data,
|
|
90
|
+
status: response.status,
|
|
91
|
+
statusText: response.statusText,
|
|
92
|
+
headers: Object.fromEntries(response.headers)
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
rejectWithError(options, data, status, statusText, reject) {
|
|
71
97
|
if (data && data.message) {
|
|
72
|
-
reject(new APIError(options, { data, status }));
|
|
98
|
+
reject(new APIError(options, { data, status, statusText }));
|
|
73
99
|
} else {
|
|
74
|
-
reject(new HTTPError(options, { data, status }));
|
|
100
|
+
reject(new HTTPError(options, { data, status, statusText }));
|
|
75
101
|
}
|
|
76
102
|
}
|
|
77
103
|
|
|
@@ -7,6 +7,8 @@ class BaseItem {
|
|
|
7
7
|
this.description = data.description;
|
|
8
8
|
this.isUsable = data.is_usable;
|
|
9
9
|
this.isSellable = data.is_sellable;
|
|
10
|
+
this.isReusable = data.is_reusable ?? false;
|
|
11
|
+
this.useCooldownSeconds = data.use_cooldown_seconds ?? null;
|
|
10
12
|
this.requirements = data.requirements.map(requirement => new StoreItemRequirement(requirement));
|
|
11
13
|
this.actions = data.actions.map(action => new StoreItemAction(action));
|
|
12
14
|
this.emojiUnicode = data.emoji_unicode;
|