fnapi-js 1.1.0 → 1.1.2

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
@@ -43,6 +43,9 @@ const creatorCode = await fnApi.sac.get('code');
43
43
  const aesKeys = await fnApi.aes.getKeys();
44
44
  ```
45
45
 
46
+ ## Check out the docs
47
+ - [Documentation](https://github.com/AjaxFNC-YT/fnapi-js/blob/main/src/docs/DOCUMENTATION.md)
48
+
46
49
  ## Available Endpoints
47
50
 
48
51
  - Stats
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fnapi-js",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "Unofficial API Wrapper for https://fortnite-api.com/",
5
5
  "main": "src/index.js",
6
6
  "types": "index.d.ts",
@@ -1,4 +1,4 @@
1
- import RequestFlags from '../enums/requestFlags.js';
1
+ import RequestFlags from '../enums/RequestFlags.js';
2
2
  import SearchOptions from '../types/SearchOptions.js';
3
3
 
4
4
  class Cosmetics {
@@ -1,4 +1,4 @@
1
- import RequestFlags from '../enums/requestFlags.js';
1
+ import RequestFlags from '../enums/RequestFlags.js';
2
2
  import SearchOptions from '../types/SearchOptions.js';
3
3
 
4
4
  class Misc {
@@ -0,0 +1,435 @@
1
+ # FNAPI-JS Documentation
2
+
3
+ FNAPI-JS is an unofficial JavaScript wrapper for the [Fortnite-API.com](https://fortnite-api.com/) service. This library provides easy access to various Fortnite game data including cosmetics, shop, stats, news, and more.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install fnapi-js
9
+ ```
10
+
11
+ ## Getting Started
12
+
13
+ ```javascript
14
+ import { ApiClient, RequestFlags, Enums } from 'fnapi-js';
15
+
16
+ // Initialize the API client
17
+ const client = new ApiClient({
18
+ apiKey: 'your-api-key', // Optional, but required for some endpoints
19
+ timeout: 30000 // Optional, default is 30000ms
20
+ });
21
+
22
+ // Example: Get current shop
23
+ const shop = await client.shop.get();
24
+ console.log(shop);
25
+ ```
26
+
27
+ ## Table of Contents
28
+
29
+ - [API Client](#api-client)
30
+ - [Response Object](#response-object)
31
+ - [Enums](#enums)
32
+ - [Request Flags](#request-flags)
33
+ - [Account Type](#account-type)
34
+ - [Cosmetic Type](#cosmetic-type)
35
+ - [Language](#language)
36
+ - [Match Method](#match-method)
37
+ - [Stats Image](#stats-image)
38
+ - [Time Window](#time-window)
39
+ - [Endpoints](#endpoints)
40
+ - [Cosmetics](#cosmetics)
41
+ - [Shop](#shop)
42
+ - [Stats](#stats)
43
+ - [AES](#aes)
44
+ - [Banners](#banners)
45
+ - [Creator Code](#creator-code)
46
+ - [Map](#map)
47
+ - [News](#news)
48
+ - [Playlists](#playlists)
49
+ - [Misc](#misc)
50
+ - [Search Options](#search-options)
51
+
52
+ ## API Client
53
+
54
+ The `ApiClient` is the main entry point for interacting with the API.
55
+
56
+ ```javascript
57
+ import { ApiClient } from 'fnapi-js';
58
+
59
+ const client = new ApiClient({
60
+ apiKey: 'your-api-key', // Optional, but required for some endpoints
61
+ timeout: 30000, // Optional, default is 30000ms
62
+ headers: {} // Optional, additional headers
63
+ });
64
+ ```
65
+
66
+ ### Methods
67
+
68
+ - `request(method, path, data, options)`: Make a direct API request
69
+ - `setHeader(key, value)`: Set a custom header for all requests
70
+ - `getBaseUrl()`: Get the base URL of the API
71
+
72
+ ## Response Object
73
+
74
+ All API requests return a `Response` object with the following methods:
75
+
76
+ - `status()`: Get the HTTP status code
77
+ - `headers()`: Get the response headers
78
+ - `body()`: Get the response body
79
+ - `isSuccess()`: Check if the request was successful (status code 200-299)
80
+
81
+ ## Enums
82
+
83
+ FNAPI-JS provides several enums to make it easier to work with the API. Import them using:
84
+
85
+ ```javascript
86
+ import { Enums } from 'fnapi-js';
87
+ // Or import specific enums
88
+ import { RequestFlags, AccountType, Language } from 'fnapi-js';
89
+ ```
90
+
91
+ ### Request Flags
92
+
93
+ Request flags can be used to include additional data in responses.
94
+
95
+ ```javascript
96
+ import { RequestFlags } from 'fnapi-js';
97
+
98
+ // Available flags
99
+ const allFlags = RequestFlags.all(); // Include all additional data
100
+ const pathsFlag = RequestFlags.paths(); // Include file paths
101
+ const tagsFlag = RequestFlags.gameplayTags(); // Include gameplay tags
102
+ const historyFlag = RequestFlags.shopHistory(); // Include shop history
103
+ const noFlags = RequestFlags.none(); // No additional data
104
+
105
+ // Combine multiple flags
106
+ const combinedFlags = RequestFlags.multiple(
107
+ RequestFlags.FLAGS.INCLUDE_PATHS,
108
+ RequestFlags.FLAGS.INCLUDE_GAMEPLAY_TAGS
109
+ );
110
+ ```
111
+
112
+ ### Account Type
113
+
114
+ Used for specifying account platforms when fetching player stats.
115
+
116
+ ```javascript
117
+ import { AccountType } from 'fnapi-js';
118
+
119
+ // Available account types
120
+ const epicAccount = AccountType.epic(); // Epic Games account
121
+ const psnAccount = AccountType.psn(); // PlayStation Network account
122
+ const xblAccount = AccountType.xbl(); // Xbox Live account
123
+ ```
124
+
125
+ ### Cosmetic Type
126
+
127
+ Used for specifying cosmetic types when searching for cosmetics.
128
+
129
+ ```javascript
130
+ import { CosmeticType } from 'fnapi-js';
131
+
132
+ // Available cosmetic types
133
+ const outfit = CosmeticType.outfit(); // Character outfits
134
+ const emote = CosmeticType.emote(); // Emotes/dances
135
+ const wrap = CosmeticType.wrap(); // Weapon/vehicle wraps
136
+ const emoji = CosmeticType.emoji(); // Emojis
137
+ const glider = CosmeticType.glider(); // Gliders
138
+ const spray = CosmeticType.spray(); // Sprays
139
+ const loadingscreen = CosmeticType.loadingscreen(); // Loading screens
140
+ const contrail = CosmeticType.contrail(); // Contrails
141
+ const shoes = CosmeticType.shoes(); // Shoes
142
+ const pickaxe = CosmeticType.pickaxe(); // Harvesting tools
143
+ const backpack = CosmeticType.backpack(); // Back blings
144
+ const musicpack = CosmeticType.musicpack(); // Music packs
145
+ const toy = CosmeticType.toy(); // Toys
146
+ const pet = CosmeticType.pet(); // Pets
147
+
148
+ // Vehicle cosmetics
149
+ const vehicleSkin = CosmeticType.vehicleskin(); // Vehicle skins
150
+ const vehicleWheel = CosmeticType.vehiclewheel(); // Vehicle wheels
151
+ const vehicleBooster = CosmeticType.vehiclebooster(); // Vehicle boosters
152
+ const vehicleDriftTrail = CosmeticType.vehicledrifttrail(); // Vehicle drift trails
153
+ const vehicleBody = CosmeticType.vehiclebody(); // Vehicle bodies
154
+
155
+ // LEGO/Building cosmetics
156
+ const junoBuildingProp = CosmeticType.junobuildingprop(); // Decor bundles
157
+ const junoBuildingSet = CosmeticType.junobuildingset(); // Building sets
158
+
159
+ // Musical instruments
160
+ const sparksGuitar = CosmeticType.sparksguitar(); // Guitars
161
+ const sparksBass = CosmeticType.sparksbass(); // Bass guitars
162
+ const sparksDrum = CosmeticType.sparksdrum(); // Drums
163
+ const sparksMic = CosmeticType.sparksmic(); // Microphones
164
+ const sparksKeyboard = CosmeticType.sparkskeyboard(); // Keytars
165
+ const sparksAura = CosmeticType.sparksaura(); // Auras
166
+ ```
167
+
168
+ ### Language
169
+
170
+ Used for specifying language preferences for API responses.
171
+
172
+ ```javascript
173
+ import { Language } from 'fnapi-js';
174
+
175
+ // Available languages
176
+ const english = Language.english(); // English (en)
177
+ const german = Language.german(); // German (de)
178
+ const spanish = Language.spanish(); // Spanish (es)
179
+ const spanishLatinAmerica = Language.spanishLatinAmerica(); // Spanish - Latin America (es-419)
180
+ const french = Language.french(); // French (fr)
181
+ const italian = Language.italian(); // Italian (it)
182
+ const japanese = Language.japanese(); // Japanese (ja)
183
+ const korean = Language.korean(); // Korean (ko)
184
+ const polish = Language.polish(); // Polish (pl)
185
+ const portugueseBrazil = Language.portugueseBrazil(); // Portuguese - Brazil (pt-BR)
186
+ const russian = Language.russian(); // Russian (ru)
187
+ const turkish = Language.turkish(); // Turkish (tr)
188
+ const chineseSimplified = Language.chineseSimplified(); // Chinese - Simplified (zh-Hans)
189
+ const chineseTraditional = Language.chineseTraditional(); // Chinese - Traditional (zh-Hant)
190
+ const arabic = Language.arabic(); // Arabic (ar)
191
+ const indonesian = Language.indonesian(); // Indonesian (id)
192
+ const thai = Language.thai(); // Thai (th)
193
+ const vietnamese = Language.vietnamese(); // Vietnamese (vi)
194
+
195
+ // Get all available languages
196
+ const allLanguages = Language.getAll();
197
+
198
+ // Check if a language code is valid
199
+ const isValid = Language.isValid('en'); // true
200
+ ```
201
+
202
+ ### Match Method
203
+
204
+ Used for specifying how search terms should match when searching for cosmetics.
205
+
206
+ ```javascript
207
+ import { MatchMethod } from 'fnapi-js';
208
+
209
+ // Available match methods
210
+ const fullMatch = MatchMethod.full(); // Exact match (same as exact())
211
+ const exactMatch = MatchMethod.exact(); // Exact match (same as full())
212
+ const containsMatch = MatchMethod.contains(); // Contains the search term
213
+ const startsMatch = MatchMethod.starts(); // Starts with the search term
214
+ const endsMatch = MatchMethod.ends(); // Ends with the search term
215
+ ```
216
+
217
+ ### Stats Image
218
+
219
+ Used for specifying which stats images to include when fetching player stats.
220
+
221
+ ```javascript
222
+ import { StatsImage } from 'fnapi-js';
223
+
224
+ // Available stats image types
225
+ const allImages = StatsImage.all(); // All input types
226
+ const keyboardMouseImages = StatsImage.keyboardMouse(); // Keyboard and mouse only
227
+ const gamepadImages = StatsImage.gamepad(); // Controller only
228
+ const touchImages = StatsImage.touch(); // Touch input only
229
+ const noImages = StatsImage.none(); // No images
230
+ ```
231
+
232
+ ### Time Window
233
+
234
+ Used for specifying the time period when fetching player stats.
235
+
236
+ ```javascript
237
+ import { TimeWindow } from 'fnapi-js';
238
+
239
+ // Available time windows
240
+ const lifetime = TimeWindow.lifetime(); // Lifetime stats
241
+ const season = TimeWindow.season(); // Current season stats
242
+ ```
243
+
244
+ ## Endpoints
245
+
246
+ ### Cosmetics
247
+
248
+ Access Fortnite cosmetic items data.
249
+
250
+ ```javascript
251
+ import { RequestFlags, CosmeticType, SearchOptions, MatchMethod, Language } from 'fnapi-js';
252
+
253
+ // Get all cosmetics with additional data
254
+ const cosmetics = await client.cosmetics.getAll(RequestFlags.all());
255
+
256
+ // Get new cosmetics with file paths
257
+ const newCosmetics = await client.cosmetics.getAllNew(RequestFlags.paths());
258
+
259
+ // Get all music tracks
260
+ const tracks = await client.cosmetics.getAllTracks(RequestFlags.none());
261
+
262
+ // Get all instruments
263
+ const instruments = await client.cosmetics.getAllInstrument(RequestFlags.none());
264
+
265
+ // Get all cars
266
+ const cars = await client.cosmetics.getAllCars(RequestFlags.none());
267
+
268
+ // Get all LEGO items
269
+ const lego = await client.cosmetics.getAllLego(RequestFlags.none());
270
+
271
+ // Get all LEGO kits
272
+ const legoKits = await client.cosmetics.getAllLegoKits(RequestFlags.none());
273
+
274
+ // Get all beans
275
+ const beans = await client.cosmetics.getAllBeans(RequestFlags.none());
276
+
277
+ // Get cosmetic by ID with gameplay tags
278
+ const cosmetic = await client.cosmetics.getById('CID_001_Athena_Commando_F_Default', RequestFlags.gameplayTags());
279
+
280
+ // Search cosmetics using enums
281
+ const searchOptions = new SearchOptions()
282
+ .setLanguage(Language.english())
283
+ .setName('Renegade')
284
+ .setType(CosmeticType.outfit())
285
+ .setMatchMethod(MatchMethod.contains());
286
+
287
+ const searchResults = await client.cosmetics.search(searchOptions, RequestFlags.all(), true);
288
+ ```
289
+
290
+ ### Shop
291
+
292
+ Get the current Fortnite item shop.
293
+
294
+ ```javascript
295
+ // Get current shop
296
+ const shop = await client.shop.get();
297
+ ```
298
+
299
+ ### Stats
300
+
301
+ Get player statistics. Requires an API key.
302
+
303
+ ```javascript
304
+ import { AccountType, TimeWindow, StatsImage } from 'fnapi-js';
305
+
306
+ // Get player stats by name
307
+ const stats = await client.stats.get(
308
+ 'Ninja', // Player name
309
+ AccountType.epic(), // Account type
310
+ TimeWindow.lifetime(), // Time window
311
+ StatsImage.all() // Image type
312
+ );
313
+
314
+ // Get player stats by ID
315
+ const statsById = await client.stats.byId(
316
+ 'player-account-id',
317
+ TimeWindow.season(),
318
+ StatsImage.keyboardMouse()
319
+ );
320
+ ```
321
+
322
+ ### AES
323
+
324
+ Get AES encryption keys used by Fortnite.
325
+
326
+ ```javascript
327
+ // Get current AES keys
328
+ const aes = await client.aes.get();
329
+ // Returns: { build, mainKey, dynamicKeys }
330
+ ```
331
+
332
+ ### Banners
333
+
334
+ Get Fortnite banner icons and colors.
335
+
336
+ ```javascript
337
+ // Get all banners
338
+ const banners = await client.banners.get();
339
+
340
+ // Get all banner colors
341
+ const bannerColors = await client.banners.getColors();
342
+ ```
343
+
344
+ ### Creator Code
345
+
346
+ Look up Support-A-Creator (SAC) codes.
347
+
348
+ ```javascript
349
+ // Get creator code information
350
+ const creatorInfo = await client.sac.get('code-name');
351
+ ```
352
+
353
+ ### Map
354
+
355
+ Get the current Fortnite map data.
356
+
357
+ ```javascript
358
+ // Get current map
359
+ const map = await client.map.get();
360
+ ```
361
+
362
+ ### News
363
+
364
+ Get the current in-game news.
365
+
366
+ ```javascript
367
+ // Get current news
368
+ const news = await client.news.get();
369
+ ```
370
+
371
+ ### Playlists
372
+
373
+ Get information about Fortnite game modes/playlists.
374
+
375
+ ```javascript
376
+ // Get all playlists
377
+ const playlists = await client.playlists.all();
378
+
379
+ // Get playlist by ID
380
+ const playlist = await client.playlists.byId('playlist-id');
381
+ ```
382
+
383
+ ### Misc
384
+
385
+ Utility functions.
386
+
387
+ ```javascript
388
+ // Fix a file path
389
+ const fixedPath = await client.misc.fixPath('FortniteGame/Content/path/to/file');
390
+ ```
391
+
392
+ ## Search Options
393
+
394
+ The `SearchOptions` class provides a fluent interface for building search queries.
395
+
396
+ ```javascript
397
+ import { SearchOptions, Language, MatchMethod, CosmeticType } from 'fnapi-js';
398
+
399
+ const options = new SearchOptions()
400
+ .setLanguage(Language.english()) // Set response language
401
+ .setSearchLanguage(Language.english()) // Set search language
402
+ .setMatchMethod(MatchMethod.contains()) // Match method
403
+ .setId('CID_001') // Search by ID
404
+ .setName('Renegade') // Search by name
405
+ .setDescription('description') // Search by description
406
+ .setType(CosmeticType.outfit()) // Search by type
407
+ .setDisplayType('Outfit') // Search by display type
408
+ .setBackendType('AthenaCharacter') // Search by backend type
409
+ .setRarity('epic') // Search by rarity
410
+ .setDisplayRarity('Epic') // Search by display rarity
411
+ .setBackendRarity('EFortRarity::Epic') // Search by backend rarity
412
+ .setHasSeries(true) // Filter by whether item has a series
413
+ .setSeries('marvel') // Search by series
414
+ .setBackendSeries('Series.Marvel') // Search by backend series
415
+ .setHasSet(true) // Filter by whether item has a set
416
+ .setSet('marvel') // Search by set
417
+ .setSetText('Marvel') // Search by set text
418
+ .setBackendSet('Set.Marvel') // Search by backend set
419
+ .setHasIntroduction(true) // Filter by whether item has introduction data
420
+ .setBackendIntroduction('Chapter2Season4') // Search by backend introduction
421
+ .setIntroductionChapter(2) // Search by introduction chapter
422
+ .setIntroductionSeason(4) // Search by introduction season
423
+ .setHasFeaturedImage(true) // Filter by whether item has featured image
424
+ .setHasVariants(true) // Filter by whether item has variants
425
+ .setHasGameplayTags(true) // Filter by whether item has gameplay tags
426
+ .setGameplayTag('Cosmetics.Source.ItemShop') // Search by gameplay tag
427
+ .setHasMetaTags(true) // Filter by whether item has meta tags
428
+ .setMetaTag('Cosmetics.Filter.Season.10') // Search by meta tag
429
+ .setHasDynamicPakId(true) // Filter by whether item has dynamic pak ID
430
+ .setDynamicPakId('pak-id') // Search by dynamic pak ID
431
+ .setAdded('2020-01-01T00:00:00Z') // Search by added date
432
+ .setAddedSince('2020-01-01T00:00:00Z') // Search by added since date
433
+ .setUnseenFor(30) // Search by unseen for days
434
+ .setLastAppearance('2020-01-01T00:00:00Z'); // Search by last appearance date
435
+ ```
@@ -49,7 +49,7 @@ class CosmeticType {
49
49
  backendValue: 'VehicleCosmetics_Skin'
50
50
  },
51
51
  MUSICPACK: {
52
- value: 'lobby music',
52
+ value: 'music',
53
53
  backendValue: 'AthenaMusicPack'
54
54
  },
55
55
  VEHICLES_WHEEL: {
@@ -0,0 +1,220 @@
1
+
2
+ import { ApiClient, Enums, SearchOptions } from '../index.js'; // if you are using this code, change this to the module name, so: fnapi-js
3
+ import readline from 'readline';
4
+
5
+ const fnApi = new ApiClient({ apiKey: 'api-key here' });
6
+
7
+ const rl = readline.createInterface({
8
+ input: process.stdin,
9
+ output: process.stdout
10
+ });
11
+
12
+ const commands = {
13
+ 'stats': async (args) => {
14
+ const [username] = args;
15
+ if (!username) {
16
+ console.log('Usage: stats <username>');
17
+ return;
18
+ }
19
+ try {
20
+ const stats = await fnApi.stats.get(
21
+ username,
22
+ Enums.accountType.epic(),
23
+ Enums.timeWindow.lifetime(),
24
+ Enums.statsImage.all()
25
+ );
26
+ console.log('Stats:', JSON.stringify(stats, null, 2));
27
+ } catch (error) {
28
+ console.error('Error:', error.message);
29
+ }
30
+ },
31
+ 'help': () => {
32
+ console.log('Available commands:\n' +
33
+ ' stats <username> - Get player stats\n' +
34
+ ' exit - Exit the program\n' +
35
+ ' help - Show this help message\n' +
36
+ ' map - Get the map\n' +
37
+ ' searchcosmetic <name> - Search for a cosmetic\n' +
38
+ ' cosmetics <all|new|tracks|instrument|cars|lego|legokits|beans> - Get cosmetics\n' +
39
+ ' cosmetic <id> - Get a specific cosmetic\n' +
40
+ ' creatorcode <code> - Get a creator code\n' +
41
+ ' aes - Get all aes keys\n' +
42
+ ' banners - Get all banners\n' +
43
+ ' bannerscolors - Get all banner colors\n' +
44
+ ' map - Get the map\n' +
45
+ ' news - Get the news\n' +
46
+ ' playlists - Get all playlists\n' +
47
+ ' shop - Get the shop'
48
+ );
49
+ },
50
+ 'news': async () => {
51
+ try {
52
+ const data = await fnApi.news.get();
53
+ console.log(JSON.stringify(data, null, 2));
54
+ } catch (error) {
55
+ console.error("Error:", error.message);
56
+ }
57
+ },
58
+ 'playlists': async () => {
59
+ try {
60
+ const data = await fnApi.playlists.all();
61
+ console.log(JSON.stringify(data, null, 2));
62
+ } catch (error) {
63
+ console.error("Error:", error.message);
64
+ }
65
+ },
66
+ 'shop': async () => {
67
+ try {
68
+ const data = await fnApi.shop.get();
69
+ console.log(JSON.stringify(data, null, 2));
70
+ } catch (error) {
71
+ console.error("Error:", error.message);
72
+ }
73
+ },
74
+ 'map': async () => {
75
+ try {
76
+ const data = await fnApi.map.get();
77
+ console.log(JSON.stringify(data, null, 2));
78
+ } catch (error) {
79
+ console.error("Error:", error.message);
80
+ }
81
+ },
82
+ 'aes': async () => {
83
+ try {
84
+ const data = await fnApi.aes.get();
85
+ console.log(JSON.stringify(data, null, 2));
86
+ } catch (error) {
87
+ console.error("Error:", error.message);
88
+ }
89
+ },
90
+ 'banners': async () => {
91
+ try {
92
+ const data = await fnApi.banners.get();
93
+ console.log(JSON.stringify(data, null, 2));
94
+ } catch (error) {
95
+ console.error("Error:", error.message);
96
+ }
97
+ },
98
+ 'bannerscolors': async () => {
99
+ try {
100
+ const data = await fnApi.banners.getColors();
101
+ console.log(JSON.stringify(data, null, 2));
102
+ } catch (error) {
103
+ console.error("Error:", error.message);
104
+ }
105
+ },
106
+ 'creatorcode': async (args) => {
107
+ const [code] = args;
108
+ if (!code) {
109
+ console.log('Usage creatorcode <code>')
110
+ return;
111
+ }
112
+
113
+ try {
114
+ const search = await fnApi.sac.get(code);
115
+ console.log('Creator Code:', JSON.stringify(search, null, 2));
116
+ } catch (eorrr) {
117
+ console.error("Error:", eorrr.message);
118
+ }
119
+ },
120
+ 'searchcosmetic': async (args) => {
121
+ const [name] = args;
122
+ if (!name) {
123
+ console.log('Usage: searchcosmetic <name>');
124
+ return;
125
+ }
126
+ try {
127
+ const searchOptions = new SearchOptions()
128
+ .setMatchMethod(Enums.matchMethod.exact())
129
+ .setName(name);
130
+ const cosmetics = await fnApi.cosmetics.search(searchOptions, Enums.requestFlags.multiple(Enums.requestFlags.paths(), Enums.requestFlags.gameplayTags()), false);
131
+ console.log('Cosmetics:', JSON.stringify(cosmetics.body().data, null, 2));
132
+ } catch (error) {
133
+ console.error('Error:', error.message);
134
+ }
135
+ },
136
+ 'cosmetic': async (args) => {
137
+ const [id] = args;
138
+ if (!id) {
139
+ console.log('Usage: cosmetic <id>');
140
+ return;
141
+ }
142
+ try {
143
+ const cosmetic = await fnApi.cosmetics.getById(id, Enums.requestFlags.all());
144
+ console.log('Cosmetic:', JSON.stringify(cosmetic.body().data, null, 2));
145
+ } catch (error) {
146
+ console.error('Error:', error.message);
147
+ }
148
+ },
149
+ 'cosmetics': async (args) => {
150
+ const [type] = args;
151
+ if (!type) {
152
+ console.log('Usage: cosmetics <all|new|tracks|instrument|cars|lego|legokits|beans>');
153
+ return;
154
+ }
155
+ try {
156
+ switch (type) {
157
+ case 'all':
158
+ const cosmetics = await fnApi.cosmetics.getAll(Enums.requestFlags.all());
159
+ console.log('Cosmetics:', JSON.stringify(cosmetics.body().data, null, 2));
160
+ break;
161
+ case 'new':
162
+ const cosmeticsNew = await fnApi.cosmetics.getAllNew(Enums.requestFlags.all());
163
+ console.log('Cosmetics:', JSON.stringify(cosmeticsNew.body().data, null, 2));
164
+ break;
165
+ case 'tracks':
166
+ const cosmeticsTracks = await fnApi.cosmetics.getAllTracks(Enums.requestFlags.all());
167
+ console.log('Cosmetics:', JSON.stringify(cosmeticsTracks.body().data, null, 2));
168
+ break;
169
+ case 'instrument':
170
+ const cosmeticsInstrument = await fnApi.cosmetics.getAllInstrument(Enums.requestFlags.all());
171
+ console.log('Cosmetics:', JSON.stringify(cosmeticsInstrument.body().data, null, 2));
172
+ break;
173
+ case 'cars':
174
+ const cosmeticsCars = await fnApi.cosmetics.getAllCars(Enums.requestFlags.all());
175
+ console.log('Cosmetics:', JSON.stringify(cosmeticsCars.body().data, null, 2));
176
+ break;
177
+ case 'lego':
178
+ const cosmeticsLego = await fnApi.cosmetics.getAllLego(Enums.requestFlags.all());
179
+ console.log('Cosmetics:', JSON.stringify(cosmeticsLego.body().data, null, 2));
180
+ break;
181
+ case 'legokits':
182
+ const cosmeticsLegoKits = await fnApi.cosmetics.getAllLegoKits(Enums.requestFlags.all());
183
+ console.log('Cosmetics:', JSON.stringify(cosmeticsLegoKits.body().data, null, 2));
184
+ break;
185
+ case 'beans':
186
+ const cosmeticsBeans = await fnApi.cosmetics.getAllBeans(Enums.requestFlags.all());
187
+ console.log('Cosmetics:', JSON.stringify(cosmeticsBeans.body().data, null, 2));
188
+ break;
189
+ }
190
+ } catch (error) {
191
+ console.error('Error:', error.message);
192
+ }
193
+ }
194
+ };
195
+
196
+ console.log('Fortnite API CLI - Type "help" for commands');
197
+ rl.setPrompt('FN> ');
198
+ rl.prompt();
199
+
200
+ rl.on('line', async (line) => {
201
+ const [command, ...args] = line.trim().split(' ');
202
+
203
+ if (command === 'exit') {
204
+ rl.close();
205
+ return;
206
+ }
207
+
208
+ if (commands[command]) {
209
+ await commands[command](args);
210
+ } else {
211
+ console.log('Unknown command. Type "help" for available commands');
212
+ }
213
+
214
+ rl.prompt();
215
+ });
216
+
217
+ rl.on('close', () => {
218
+ console.log('\nGoodbye!');
219
+ process.exit(0);
220
+ });
@@ -0,0 +1,63 @@
1
+ const { Client } = require('fnbr');
2
+ const { ApiClient, Enums, SearchOptions } = require('fnapi-js');
3
+ const { SearchSource } = require('jest');
4
+
5
+ const client = new Client();
6
+
7
+ const fnApi = new ApiClient({});
8
+
9
+ const handleCommand = async (m) => {
10
+ // console.log(m.content);
11
+ if (!m.content.startsWith('!')) return;
12
+ const args = m.content.slice(1).split(' ');
13
+ const command = args.shift().toLowerCase();
14
+
15
+ if (command === 'outfit' || command === 'skin') {
16
+ const search = new SearchOptions()
17
+ .setName(`${args.join(' ')}`)
18
+ .setMatchMethod(Enums.matchMethod.contains())
19
+ .setType(Enums.cosmeticType.outfit());
20
+
21
+ const skin = await fnApi.cosmetics.search(search, Enums.requestFlags.paths(), false);
22
+ if (!skin) {
23
+ console.log(`The skin ${args.join(' ')} wasn't found!`);
24
+ return;
25
+ }
26
+
27
+ await m.client.party.me.setOutfit(skin.body().data.id, undefined, undefined);
28
+ await m.reply(`Set the skin to ${skin.body().data.name}!`);
29
+
30
+ } else if (command === 'emote' || command === 'dance') {
31
+
32
+ const search = new SearchOptions()
33
+ .setName(`${args.join(' ')}`)
34
+ .setMatchMethod(Enums.matchMethod.contains())
35
+ .setType(Enums.cosmeticType.emote());
36
+
37
+ const emote = await fnApi.cosmetics.search(search, Enums.requestFlags.paths(), false);
38
+ if (!emote) {
39
+ console.log(`The emote ${args.join(' ')} wasn't found!`);
40
+ return;
41
+ }
42
+
43
+ try {
44
+ await m.client.party.me.setEmote(emote.body().data.id, fnApi.misc.fixPath(emote.body().data.path));
45
+ console.log(`Set the emote to ${emote.body().data.name}!`);
46
+ } catch (error) {
47
+ console.log(error);
48
+ console.log(`Failed to set the emote due to: ${error.message}`);
49
+ }
50
+ }
51
+ };
52
+
53
+ client.on('friend:message', (message) => {
54
+ console.log(`Message from ${message.author.displayName}: ${message.content}`);
55
+
56
+ handleCommand(message);
57
+ });
58
+
59
+ client.on('ready', () => {
60
+ console.log(`Logged in as ${client.user.displayName}`);
61
+ });
62
+
63
+ client.login();
package/src/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import ApiClient from './client/ApiClient.js';
2
2
  import Response from './http/Response.js';
3
- import RequestFlags from './enums/requestFlags.js';
3
+ import RequestFlags from './enums/RequestFlags.js';
4
4
  import Enums from './utils/Enums.js';
5
5
  import SearchOptions from './types/SearchOptions.js';
6
6
 
@@ -1,6 +1,6 @@
1
1
  import CosmeticType from '../enums/CosmeticType.js';
2
2
  import Language from '../enums/Language.js';
3
- import RequestFlags from '../enums/requestFlags.js';
3
+ import RequestFlags from '../enums/RequestFlags.js';
4
4
  import MatchMethod from '../enums/MatchMethod.js';
5
5
  import AccountType from '../enums/AccountType.js';
6
6
  import StatsImage from '../enums/StatsImage.js';