unb-api 1.2.2 → 1.3.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/index.d.ts CHANGED
@@ -37,8 +37,8 @@ declare module 'unb-api' {
37
37
  }
38
38
 
39
39
  export type Balance = {
40
- cash?: number,
41
- bank?: number
40
+ cash?: number | string,
41
+ bank?: number | string
42
42
  }
43
43
 
44
44
  export type Options = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "unb-api",
3
- "version": "1.2.2",
3
+ "version": "1.3.0",
4
4
  "description": "API wrapper for UnbelievaBoat Discord Bot API",
5
5
  "main": "src/index.js",
6
6
  "types": "index.d.ts",
@@ -22,6 +22,6 @@
22
22
  "typescript": "^2.6.2"
23
23
  },
24
24
  "dependencies": {
25
- "axios": "^0.20.0"
25
+ "axios": "^0.21.1"
26
26
  }
27
27
  }
package/src/index.js CHANGED
@@ -1,5 +1,11 @@
1
1
  module.exports = {
2
- version: require('../package').version,
3
- Client: require('./lib/Client'),
4
- User: require('./lib/structures/User')
2
+ version: require('../package').version,
3
+ Client: require('./lib/Client'),
4
+ Constants: require('./lib/Constants'),
5
+ StoreItem: require('./lib/structures/items/StoreItem'),
6
+ StoreItemRequirement: require('./lib/structures/items/StoreItemRequirement'),
7
+ StoreItemAction: require('./lib/structures/items/StoreItemAction'),
8
+ InventoryItem: require('./lib/structures/items/InventoryItem'),
9
+ Permission: require('./lib/structures/Permission'),
10
+ User: require('./lib/structures/User'),
5
11
  };
package/src/lib/Client.js CHANGED
@@ -1,4 +1,5 @@
1
- const { Guild, Permission, User } = require('./structures');
1
+ const { Guild, Permission, User, StoreItem, InventoryItem } = require('./structures');
2
+ const { toSnakeCaseDeep } = require('./util');
2
3
  const RequestHandler = require('./RequestHandler');
3
4
 
4
5
  class Client {
@@ -170,7 +171,173 @@ class Client {
170
171
  if (typeof guildId !== 'string') throw new TypeError('guildId must be a string');
171
172
 
172
173
  return this._request('GET', `applications/@me/guilds/${guildId}`)
173
- .then(data => new Permission(data.permissions));
174
+ .then(data => new Permission(data.permissions));
175
+ }
176
+
177
+ /**
178
+ * Get guild store items.
179
+ *
180
+ * @public
181
+ * @param {string} guildId - Guild ID
182
+ * @param {object} [options] - Options
183
+ * @param {string[]} [options.sort] - Array of properties to sort the items by (id, price, name, stock_remaining, expires_at)
184
+ * @param {number} [options.page] - The page to request
185
+ * @param {number} [options.limit=100] - Maximum number of items to return
186
+ * @param {string} [options.query] - Search for an item by name
187
+ * @throws {TypeError}
188
+ * @returns {Promise<{ items: StoreItem[], page: number, totalPages: number }>}
189
+ *
190
+ * @see {@link https://unbelievaboat-api.readme.io/reference/get-store-items|Get Store Items}
191
+ */
192
+ getItems(guildId, options) {
193
+ if (typeof guildId !== 'string') throw new TypeError('guildId must be a string');
194
+
195
+ return this._request('GET', `guilds/${guildId}/items`, {}, options)
196
+ .then(data => {
197
+ return {
198
+ page: data.page,
199
+ totalPages: data.total_pages,
200
+ items: data.items.map(item => new StoreItem(item)),
201
+ };
202
+ });
203
+ }
204
+
205
+ /**
206
+ * Get a single store item.
207
+ *
208
+ * @public
209
+ * @param {string} guildId - Guild ID
210
+ * @param {string} itemId - Item ID
211
+ * @throws {TypeError}
212
+ * @returns {Promise<StoreItem>}
213
+ *
214
+ * @see {@link https://unbelievaboat-api.readme.io/reference/get-store-item|Get Store Item}
215
+ */
216
+ getItem(guildId, itemId) {
217
+ if (typeof guildId !== 'string') throw new TypeError('guildId must be a string');
218
+ if (typeof itemId !== 'string') throw new TypeError('itemId must be a string');
219
+
220
+ return this._request('GET', `guilds/${guildId}/items/${itemId}`)
221
+ .then(data => new StoreItem(data));
222
+ }
223
+
224
+ /**
225
+ * Edit an item
226
+ *
227
+ * @public
228
+ * @param {string} guildId - Guild ID
229
+ * @param {string} itemId - Item ID
230
+ * @param {StoreItem|object} data - Item properties to edit
231
+ * @param [options]
232
+ * @param [options.cascadeUpdate=false] - Inventory items will also be updated if set to true
233
+ * @returns {Promise<StoreItem>}
234
+ */
235
+ editItem(guildId, itemId, data, options) {
236
+ if (typeof guildId !== 'string') throw new TypeError('guildId must be a string');
237
+ if (typeof itemId !== 'string') throw new TypeError('itemId must be a string');
238
+
239
+ return this._request('PATCH', `guilds/${guildId}/items/${itemId}`, toSnakeCaseDeep(data), toSnakeCaseDeep(options))
240
+ .then(data => new StoreItem(data));
241
+ }
242
+
243
+ /**
244
+ * Delete an item
245
+ * @public
246
+ * @param {string} guildId - Guild ID
247
+ * @param {string} itemId - Item ID
248
+ * @param {object} [options]
249
+ * @param {boolean} [options.cascadeDelete=false] - Inventory items will also be deleted if set to true
250
+ * @returns {Promise<*>}
251
+ */
252
+ deleteItem(guildId, itemId, options) {
253
+ if (typeof guildId !== 'string') throw new TypeError('guildId must be a string');
254
+ if (typeof itemId !== 'string') throw new TypeError('itemId must be a string');
255
+
256
+ return this._request('DELETE', `guilds/${guildId}/items/${itemId}`, {}, toSnakeCaseDeep(options));
257
+ }
258
+
259
+ /**
260
+ * Get a users inventory items
261
+ *
262
+ * @public
263
+ * @param {string} guildId
264
+ * @param {string} userId
265
+ * @param {object} [options] - Options
266
+ * @param {string[]} [options.sort] - Array of properties to sort the items by (item_id, name, quantity)
267
+ * @param {number} [options.page] - The page to request
268
+ * @param {number} [options.limit=100] - Maximum number of items to return
269
+ * @param {string} [options.query] - Search for an item by name
270
+ * @returns {Promise<{totalPages: number, page: number, items: InventoryItem[]}>}
271
+ */
272
+ getInventoryItems(guildId, userId, options) {
273
+ if (typeof guildId !== 'string') throw new TypeError('guildId must be a string');
274
+ if (typeof userId !== 'string') throw new TypeError('itemId must be a string');
275
+
276
+ return this._request('GET', `guilds/${guildId}/users/${userId}/inventory`, {}, options)
277
+ .then(data => {
278
+ return {
279
+ page: data.page,
280
+ totalPages: data.total_pages,
281
+ items: data.items.map(item => new InventoryItem(item)),
282
+ };
283
+ });
284
+ }
285
+
286
+ /**
287
+ * Get a single inventory item for a user
288
+ *
289
+ * @public
290
+ * @param {string} guildId - Guild ID
291
+ * @param {string} userId - User ID
292
+ * @param {string} itemId - Item ID
293
+ * @returns {Promise<{totalPages: number, page: number, items: InventoryItem[]}>}
294
+ */
295
+ getInventoryItem(guildId, userId, itemId) {
296
+ if (typeof guildId !== 'string') throw new TypeError('guildId must be a string');
297
+ if (typeof userId !== 'string') throw new TypeError('userId must be a string');
298
+ if (typeof itemId !== 'string') throw new TypeError('itemId must be a string');
299
+
300
+ return this._request('GET', `guilds/${guildId}/users/${userId}/inventory/${itemId}`)
301
+ .then(data => new InventoryItem(data));
302
+ }
303
+
304
+ /**
305
+ * Add an item to a users inventory
306
+ *
307
+ * @public
308
+ * @param {string} guildId - Guild ID
309
+ * @param {string} userId - User ID
310
+ * @param {string} itemId - Item ID
311
+ * @param {number|string} [quantity=1] - Quantity to add
312
+ * @param {object} [options]
313
+ * @param {string} [options.inventoryUserId] - User ID of the inventory to add the item from (can be used if the item no longer exists in the store or the item settings differ)
314
+ * @returns {Promise<InventoryItem>}
315
+ */
316
+ addInventoryItem(guildId, userId, itemId, quantity, options) {
317
+ if (typeof guildId !== 'string') throw new TypeError('guildId must be a string');
318
+ if (typeof userId !== 'string') throw new TypeError('userId must be a string');
319
+ if (typeof itemId !== 'string') throw new TypeError('itemId must be a string');
320
+
321
+ return this._request('POST', `guilds/${guildId}/users/${userId}/inventory`, toSnakeCaseDeep({ itemId, quantity, options }))
322
+ .then(data => new InventoryItem(data));
323
+ }
324
+
325
+ /**
326
+ * Add an item to a users inventory
327
+ *
328
+ * @public
329
+ * @param {string} guildId - Guild ID
330
+ * @param {string} userId - User ID
331
+ * @param {string} itemId - Item ID
332
+ * @param {number|string} [quantity=1] - Quantity to remove
333
+ * @returns {Promise<*>}
334
+ */
335
+ removeInventoryItem(guildId, userId, itemId, quantity) {
336
+ if (typeof guildId !== 'string') throw new TypeError('guildId must be a string');
337
+ if (typeof userId !== 'string') throw new TypeError('userId must be a string');
338
+ if (typeof itemId !== 'string') throw new TypeError('itemId must be a string');
339
+
340
+ return this._request('DELETE', `guilds/${guildId}/users/${userId}/inventory/${itemId}`, {}, { quantity });
174
341
  }
175
342
 
176
343
  /**
@@ -179,7 +346,7 @@ class Client {
179
346
  * @private
180
347
  * @param {string} method - The http method to use (GET, PUT, PATCH etc.).
181
348
  * @param {string} endpoint - The api endpoint to request.
182
- * @param {object} [data={}] - The data to provide provide to the server.
349
+ * @param {object} [data={}] - The data to provide to the server.
183
350
  * @param {object} [query={}] - The query string options to use in the url.
184
351
  * @returns {Promise<any>} The raw request data.
185
352
  */
@@ -0,0 +1,36 @@
1
+ const Enum = require('./util/Enum');
2
+
3
+ /**
4
+ * Item action type enum
5
+ * @type {Enum}
6
+ */
7
+ module.exports.ItemActionType = new Enum({
8
+ RESPOND: 1,
9
+ ADD_ROLES: 2,
10
+ REMOVE_ROLES: 3,
11
+ ADD_BALANCE: 4,
12
+ REMOVE_BALANCE: 5,
13
+ ADD_ITEMS: 6,
14
+ REMOVE_ITEMS: 7,
15
+ });
16
+
17
+ /**
18
+ * Item requirement type enum
19
+ * @type {Enum}
20
+ */
21
+ module.exports.ItemRequirementType = new Enum({
22
+ ROLE: 1,
23
+ TOTAL_BALANCE: 2,
24
+ ITEM: 3,
25
+ });
26
+
27
+
28
+ /**
29
+ * Item requirement match type enum
30
+ * @type {Enum}
31
+ */
32
+ module.exports.ItemRequirementMatchType = new Enum({
33
+ EVERY: 1,
34
+ AT_LEAST_ONE: 2,
35
+ NONE: 3,
36
+ });
@@ -1,5 +1,5 @@
1
1
  const axios = require('axios');
2
- const Bucket = require('./structures/Bucket');
2
+ const Bucket = require('./util/Bucket');
3
3
  const { APIError, HTTPError } = require('./errors');
4
4
  const MajorParams = ['guilds'];
5
5
 
@@ -47,7 +47,7 @@ class Guild {
47
47
  }
48
48
 
49
49
  get iconURL() {
50
- return this.icon ? `https://cdn.discordapp.com/icons/${this.id}/${this.icon}.png` : null;
50
+ return this.icon ? `https://cdn.discordapp.com/icons/${this.id}/${this.icon}.${this.icon.startsWith("a_") ? "gif" : "png"}` : null;
51
51
  }
52
52
 
53
53
  }
@@ -1,6 +1,9 @@
1
1
  module.exports = {
2
- Bucket: require('./Bucket'),
3
- Guild: require('./Guild'),
4
- Permission: require('./Permission'),
5
- User: require('./User')
2
+ Guild: require('./Guild'),
3
+ StoreItem: require('./items/StoreItem'),
4
+ StoreItemRequirement: require('./items/StoreItemRequirement'),
5
+ StoreItemAction: require('./items/StoreItemAction'),
6
+ InventoryItem: require('./items/InventoryItem'),
7
+ Permission: require('./Permission'),
8
+ User: require('./User'),
6
9
  };
@@ -0,0 +1,21 @@
1
+ const StoreItemRequirement = require('./StoreItemRequirement');
2
+ const StoreItemAction = require('./StoreItemAction');
3
+
4
+ class BaseItem {
5
+ constructor(data) {
6
+ this.name = data.name;
7
+ this.description = data.description;
8
+ this.isUsable = data.is_usable;
9
+ this.isSellable = data.is_sellable;
10
+ this.requirements = data.requirements.map(requirement => new StoreItemRequirement(requirement));
11
+ this.actions = data.actions.map(action => new StoreItemAction(action));
12
+ this.emojiUnicode = data.emoji_unicode;
13
+ this.emojiId = data.emoji_id;
14
+ }
15
+
16
+ get isChicken() {
17
+ return (this.name || '').toLowerCase().includes('chicken');
18
+ }
19
+ }
20
+
21
+ module.exports = BaseItem;
@@ -0,0 +1,11 @@
1
+ const BaseItem = require('./BaseItem');
2
+
3
+ class InventoryItem extends BaseItem {
4
+ constructor(data) {
5
+ super(data);
6
+ this.itemId = data.item_id;
7
+ this.quantity = data.quantity;
8
+ }
9
+ }
10
+
11
+ module.exports = InventoryItem;
@@ -0,0 +1,17 @@
1
+ const BaseItem = require('./BaseItem');
2
+
3
+ class StoreItem extends BaseItem {
4
+ constructor(data) {
5
+ super(data);
6
+ this.id = data.id;
7
+ this.price = parseInt(data.price);
8
+ this.isInventory = data.is_inventory;
9
+ this.stockRemaining = data.stock_remaining;
10
+ this.unlimitedStock = data.unlimited_stock;
11
+ if (data.expires_at) {
12
+ this.expiresAt = new Date(data.expires_at);
13
+ }
14
+ }
15
+ }
16
+
17
+ module.exports = StoreItem;
@@ -0,0 +1,33 @@
1
+ const { ItemActionType } = require('../../Constants');
2
+
3
+ class StoreItemAction {
4
+ constructor(data) {
5
+ this.type = ItemActionType.toString(data.type);
6
+
7
+ switch (this.type) {
8
+ case 'RESPOND':
9
+ this.message = data.message;
10
+ break;
11
+ case 'ADD_ROLES':
12
+ case 'ADD_ITEMS':
13
+ case 'REMOVE_ROLES':
14
+ case 'REMOVE_ITEMS':
15
+ this.ids = data.ids || [];
16
+ break;
17
+ case 'ADD_BALANCE':
18
+ case 'REMOVE_BALANCE':
19
+ this.balance = data.balance;
20
+ break;
21
+ }
22
+ }
23
+
24
+ toJSON() {
25
+ return {
26
+ ...this,
27
+ type: ItemActionType.toNumber(this.type),
28
+ };
29
+ }
30
+
31
+ }
32
+
33
+ module.exports = StoreItemAction;
@@ -0,0 +1,28 @@
1
+ const { ItemRequirementType, ItemRequirementMatchType } = require('../../Constants');
2
+
3
+ class StoreItemRequirement {
4
+ constructor(data) {
5
+ this.type = ItemRequirementType.toString(data.type);
6
+
7
+ switch (this.type) {
8
+ case 'ROLE':
9
+ case 'ITEM':
10
+ this.matchType = ItemRequirementMatchType.toString(data.match_type);
11
+ this.ids = data.ids || [];
12
+ break;
13
+ case 'TOTAL_BALANCE':
14
+ this.balance = data.balance;
15
+ break;
16
+ }
17
+ }
18
+
19
+ toJSON() {
20
+ return {
21
+ ...this,
22
+ type: ItemRequirementType.toNumber(this.type),
23
+ matchType: this.matchType ? ItemRequirementMatchType.toNumber(this.matchType) : undefined,
24
+ };
25
+ }
26
+ }
27
+
28
+ module.exports = StoreItemRequirement;
File without changes
@@ -0,0 +1,71 @@
1
+ class Enum {
2
+ #keys = [];
3
+ #values = [];
4
+
5
+ constructor(object) {
6
+ const result = {};
7
+ for (const [key, value] of Object.entries(object)) {
8
+ if (key === null) continue;
9
+ result[key] = value;
10
+ result[value] = key;
11
+
12
+ this.#keys.push(key);
13
+ this.#values.push(value);
14
+ }
15
+
16
+ this.entries = Object.freeze(result);
17
+ }
18
+
19
+ get keys() {
20
+ return this.#keys;
21
+ }
22
+
23
+ get values() {
24
+ return this.#values;
25
+ }
26
+
27
+ /**
28
+ * Compare if two enum value are equal
29
+ * @param a
30
+ * @param b
31
+ * @returns {boolean}
32
+ */
33
+ equal(a, b) {
34
+ if (!this.entries.hasOwnProperty(a)) return false;
35
+ if (!this.entries.hasOwnProperty(b)) return false;
36
+
37
+ return a === b || this.entries[a] === b;
38
+ }
39
+
40
+ /**
41
+ * Convert an enum value to string
42
+ * @param value
43
+ * @returns {*}
44
+ */
45
+ toString(value) {
46
+ const number = parseInt(value);
47
+ if (isNaN(number)) return value;
48
+ return this.entries[number];
49
+ }
50
+
51
+ /**
52
+ * Convert an enum value to number
53
+ * @param value
54
+ * @returns {number}
55
+ */
56
+ toNumber(value) {
57
+ const number = parseInt(value);
58
+ if (isNaN(number)) return this.entries[value];
59
+ return number;
60
+ }
61
+
62
+ /**
63
+ * Check if a value exists
64
+ * @param value
65
+ */
66
+ exists(value) {
67
+ return !!this.entries[value];
68
+ }
69
+ }
70
+
71
+ module.exports = Enum;
@@ -0,0 +1,21 @@
1
+ module.exports.toSnakeCase = (input) => input.replace(/[A-Z]/g, match => `_${match.toLowerCase()}`);
2
+
3
+ module.exports.toSnakeCaseDeep = (value) => {
4
+ if (value && value.toJSON) {
5
+ value = value.toJSON();
6
+ }
7
+
8
+ if (Array.isArray(value)) {
9
+ return value.map(exports.toSnakeCaseDeep);
10
+ }
11
+
12
+ if (value !== null && typeof value === 'object') {
13
+ let obj = {};
14
+ for (let key of Object.keys(value)) {
15
+ obj[exports.toSnakeCase(key)] = exports.toSnakeCaseDeep(value[key]);
16
+ }
17
+ return obj;
18
+ }
19
+
20
+ return value;
21
+ };