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 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 | Description |
134
- |---------|------------------|---------------------------------------------------------------------------|
135
- | String | `id` | Unique ID of the item in the store. |
136
- | String | `name` | Name of the item. |
137
- | String | `description?` | Description of the item. |
138
- | Number | `price` | Price of the item. |
139
- | Number | `stockRemaining` | Amount of stock remaining for the item. |
140
- | Boolean | `unlimitedStock` | Whether the item has unlimited stock. |
141
- | Number | `maxQuantity?` | Max a user can own, or buy at once if not an inventory item. |
142
- | Boolean | `isInventory` | Indicates if the item will be added to a user’s inventory when purchased. |
143
- | Date | `expiresAt?` | Expiration date of the item. |
144
- | Boolean | `isUsable` | Whether the item can be used by the user. |
145
- | Boolean | `isSellable` | Whether the item can be sold by the user. |
146
- | Array | `requirements` | Requirements needed to purchase the item. |
147
- | Array | `actions` | Actions performed when the item is used. |
148
- | String | `emojiUnicode?` | Unicode emoji associated with the item. |
149
- | String | `emojiId?` | Custom emoji ID associated with the item. |
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 | Description |
154
- |-------------------------------------------------|-----------------|-----------------------------------------------|
155
- | String | `itemId` | Unique ID of the item in the inventory. |
156
- | Number | `quantity` | Quantity of the item in the user's inventory. |
157
- | String | `name` | Name of the item. |
158
- | String | `description?` | Description of the item. |
159
- | Boolean | `isUsable` | Whether the item can be used by the user. |
160
- | Boolean | `isSellable` | Whether the item can be sold by the user. |
161
- | [StoreItemRequirement[]](#StoreItemRequirement) | `requirements` | Requirements needed to use the item. |
162
- | [StoreItemAction[]](#StoreItemAction) | `actions` | Actions performed when the item is used. |
163
- | String | `emojiUnicode?` | Unicode emoji associated with the item. |
164
- | String | `emojiId?` | Custom emoji ID associated with the item. |
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
@@ -1,5 +1,12 @@
1
1
  module.exports = {
2
2
  'extends': 'eslint:recommended',
3
+ 'env': {
4
+ 'node': true,
5
+ 'es2020': true
6
+ },
7
+ 'globals': {
8
+ 'fetch': 'readonly'
9
+ },
3
10
  'rules': {
4
11
  'indent': ['error', 4],
5
12
  'linebreak-style': ['error', 'unix'],
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.5.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.axiosInstance(options);
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
- if (axios.isAxiosError(error)) {
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
- rejectWithError(options, data, status, reject) {
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;