├── .eslintrc.json ├── .github └── workflows │ └── npm-publish.yml ├── .gitignore ├── LICENSE ├── README.md ├── XIVAPI.js ├── lib ├── Lib.js ├── character.js ├── cwl.js ├── data.js ├── freecompany.js ├── linkshell.js ├── pvpteam.js └── search.js ├── package-lock.json ├── package.json ├── resources └── index.js ├── test.js ├── typings ├── index.d.ts └── utils │ ├── achievements.d.ts │ ├── character.d.ts │ ├── cwl.ts │ ├── freecompany.d.ts │ ├── index.d.ts │ ├── item.d.ts │ ├── linkshell.ts │ ├── pvpteam.ts │ └── search.d.ts └── utils.js /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es6": true, 4 | "node": true 5 | }, 6 | "extends": "eslint:recommended", 7 | "parserOptions": { 8 | "ecmaVersion": 2017, 9 | "sourceType": "module" 10 | }, 11 | "rules": { 12 | "indent": [ 13 | "error", 14 | "tab", 15 | { "SwitchCase": 1 } 16 | ], 17 | "linebreak-style": [ 18 | "error", 19 | "unix" 20 | ], 21 | "quotes": [ 22 | "error", 23 | "single" 24 | ], 25 | "semi": [ 26 | "error", 27 | "never" 28 | ], 29 | "no-console": [ 30 | 0 31 | ] 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created 2 | # For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages 3 | 4 | name: Node.js Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v3 15 | - uses: actions/setup-node@v3 16 | with: 17 | node-version: 16 18 | - run: npm ci 19 | 20 | publish-npm: 21 | needs: build 22 | runs-on: ubuntu-latest 23 | steps: 24 | - uses: actions/checkout@v3 25 | - uses: actions/setup-node@v3 26 | with: 27 | node-version: 16 28 | registry-url: https://registry.npmjs.org/ 29 | - run: npm ci 30 | - run: npm publish 31 | env: 32 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 XIVAPI 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xivapi-js 2 | 3 | [![npm version](https://badge.fury.io/js/%40xivapi%2Fjs.svg)](https://badge.fury.io/js/%40xivapi%2Fjs) 4 | [![license](https://img.shields.io/github/license/xivapi/xivapi-js.svg)](LICENSE) 5 | 6 | This is a pure JS wrapper for interacting with [XIVAPI](https://xivapi.com/) and handling all requests in a simple, promise-driven manner. 7 | 8 | ## Installation 9 | 10 | Simply add the module to your node project with `npm`: 11 | ``` 12 | npm i @xivapi/js 13 | ``` 14 | 15 | ## Usage 16 | 17 | Require and initialize the module in your code: 18 | ```js 19 | const XIVAPI = require('@xivapi/js') 20 | const xiv = new XIVAPI() 21 | ``` 22 | 23 | ...and then check out the [wiki](https://github.com/xivapi/xivapi-js/wiki) for usage help! 24 | 25 | If you get really stuck and need some help, or run into any problems/concerns, either open up an issue on github or join the [XIVAPI discord server](https://discord.gg/MFFVHWC) and ping/DM @kaimoe. 26 | 27 | ### Examples: 28 | 29 | Find an item's ID: 30 | ```js 31 | const getID = async () => { 32 | //find item 33 | let res = await xiv.search('Stuffed Khloe') 34 | 35 | //return item ID 36 | return res.Results[0].ID 37 | } 38 | ``` 39 | 40 | Search for an FC and get an list of members: 41 | ```javascript 42 | const getMembers = async () => { 43 | //find the FC with its name and server 44 | let res = await xiv.freecompany.search('My Fun FC', {server: 'Excalibur'}) 45 | 46 | //get the FC ID 47 | let id = res.Results[0].ID 48 | 49 | //get and return fc members 50 | let fc = await xiv.freecompany.get('9231253336202687179', {data: FCM}) 51 | return fc.FreeCompanyMembers 52 | } 53 | ``` 54 | 55 | Check for character ownership using a token we generated and provided to the user: 56 | ```js 57 | const verifyCharacter = async () => { 58 | //find the character with their name and server 59 | let res = await xiv.character.search('Kai Megumi', {server: 'excalibur'}) //case insensitive server names, btw ;) 60 | 61 | //get the character 62 | let char = res.Results[0] 63 | 64 | //return whether or not the character's lodestone bio matches our token 65 | return char.Bio === 'example_token' 66 | } 67 | ``` 68 | 69 | ## Contribute 70 | 71 | Feel free to open up issues/PRs or anything else. 72 | 73 | Just `git clone https://github.com/xivapi/xivapi-js.git`, run `npm i`, and go to town! 74 | 75 | ## License 76 | 77 | This project is open source, under the terms described in the [MIT License](LICENSE). 78 | -------------------------------------------------------------------------------- /XIVAPI.js: -------------------------------------------------------------------------------- 1 | const resources = require('./resources/'), 2 | Search = require('./lib/search'), 3 | Data = require('./lib/data'), 4 | Character = require('./lib/character'), 5 | FreeCompany = require('./lib/freecompany'), 6 | Linkshell = require('./lib/linkshell'), 7 | CWL = require('./lib/cwl'), 8 | PvPTeam = require('./lib/pvpteam') 9 | 10 | class XIVAPI { 11 | /*{ 12 | private_key string undefined optional 13 | language string 'en' optional 14 | snake_case bool false optional 15 | staging bool false optional 16 | verbose bool false optional 17 | } 18 | */ 19 | constructor(options = {}, legacyOptions = {}) { 20 | //handle attempted use of old API key 21 | if(typeof(options) === 'string') { 22 | console.error('[xivapi-js] BREAKING CHANGE:\n\ 23 | The previous API keys for XIVAPI have been phased out, and are no longer mandatory. \ 24 | This means you\'ll have to define your key during initialization slightly differently. \ 25 | See how in https://github.com/xivapi/xivapi-js/releases/tag/v0.1.3.\n\ 26 | **This instance of xivapi-js will run WITHOUT an API key**') 27 | options = legacyOptions 28 | } 29 | 30 | this.endpoint = `https://${options.staging ? 'staging.' : ''}xivapi.com` 31 | if(options.language && !resources.languages.includes(options.language)) 32 | throw Error(`Invalid language given, must be one of: ${resources.languages}`) 33 | 34 | this.globalParams = {} 35 | 36 | for (let x of ['private_key', 'language']) { 37 | if(typeof options[x] !== 'undefined') 38 | this.globalParams[x] = options[x] 39 | } 40 | if(options.snake_case) 41 | this.globalParams.snake_case = 1 42 | 43 | this.verbose = options.verbose 44 | 45 | this.resources = resources 46 | this.utils = require('./utils') 47 | 48 | this.search = Search.bind(this) 49 | this.data = new Data(this) 50 | this.character = new Character(this) 51 | this.freecompany = new FreeCompany(this) 52 | this.linkshell = new Linkshell(this) 53 | this.cwl = new CWL(this) 54 | this.pvpteam = new PvPTeam(this) 55 | } 56 | } 57 | 58 | module.exports = XIVAPI 59 | -------------------------------------------------------------------------------- /lib/Lib.js: -------------------------------------------------------------------------------- 1 | const utils = require('../utils') 2 | 3 | class Lib { 4 | constructor(parent) { 5 | this.parent = parent 6 | 7 | this.req = utils.req.bind(parent) 8 | this.reqJSON = utils.reqJSON.bind(parent) 9 | this.makeCSV = utils.makeCSV 10 | this.throwError = utils.throwError 11 | } 12 | } 13 | 14 | module.exports = Lib 15 | -------------------------------------------------------------------------------- /lib/character.js: -------------------------------------------------------------------------------- 1 | // https://xivapi.com/docs/Character 2 | const Lib = require('./Lib') 3 | 4 | class Character extends Lib { 5 | constructor(parent) { 6 | super(parent) 7 | } 8 | 9 | /* 10 | { 11 | server 12 | page 13 | } 14 | */ 15 | async search(name, params={}) { 16 | if(!name) 17 | throw this.throwError('character.search()', 'a name') 18 | return this.req('/character/search', Object.assign(params, {name})) 19 | } 20 | 21 | /* 22 | { 23 | extended 24 | data 25 | } 26 | */ 27 | async get(id, params={}) { 28 | if(!id) 29 | throw this.throwError('character.get()','an ID') 30 | 31 | return this.req(`/character/${id}`, params) 32 | } 33 | } 34 | 35 | module.exports = Character 36 | -------------------------------------------------------------------------------- /lib/cwl.js: -------------------------------------------------------------------------------- 1 | // https://xivapi.com/docs/Linkshell 2 | const Lib = require('./Lib') 3 | 4 | class CWL extends Lib { 5 | constructor(parent) { 6 | super(parent) 7 | } 8 | 9 | /* 10 | { 11 | server string optional 12 | page int optional 13 | } 14 | */ 15 | async search(name, params={}) { 16 | if(typeof(name) === 'undefined') 17 | throw this.throwError('cwl.search()','a name') 18 | return this.req('/linkshell/crossworld/search', Object.assign(params, {name})) 19 | } 20 | 21 | async get(id) { 22 | if(typeof(id) === 'undefined') 23 | throw this.throwError('cwl.get()', 'an ID') 24 | return this.req(`/linkshell/crossworld/${id}`) 25 | } 26 | } 27 | 28 | module.exports = CWL 29 | -------------------------------------------------------------------------------- /lib/data.js: -------------------------------------------------------------------------------- 1 | // https://xivapi.com/docs/Welcome#section-4 2 | const Lib = require('./Lib') 3 | 4 | class Content extends Lib { 5 | constructor(parent) { 6 | super(parent) 7 | } 8 | 9 | async content() { 10 | return this.req('/content') 11 | } 12 | 13 | /* 14 | { 15 | limit 16 | ids 17 | } 18 | */ 19 | async list(name, params={}) { 20 | if(typeof name==='undefined') 21 | throw this.throwError('data.list()','a name') 22 | 23 | if(params.ids) 24 | params.ids = this.parent.utils.makeCSV(params.ids) 25 | 26 | return this.req(`/${name}`, params) 27 | } 28 | 29 | async get(name, id) { 30 | const missing_params = [] 31 | if(typeof name==='undefined') 32 | missing_params.push('a name') 33 | if(typeof id==='undefined') 34 | missing_params.push('an ID') 35 | if(missing_params.length>0) 36 | throw this.throwError('data.get()', missing_params.join(',')) 37 | 38 | return this.req(`/${name}/${id}`) 39 | } 40 | 41 | servers() { 42 | return this.req('/servers') 43 | } 44 | 45 | datacenters() { 46 | return this.req('/servers/dc') 47 | } 48 | 49 | 50 | } 51 | 52 | module.exports = Content 53 | -------------------------------------------------------------------------------- /lib/freecompany.js: -------------------------------------------------------------------------------- 1 | // https://xivapi.com/docs/Free-Company 2 | const Lib = require('./Lib') 3 | 4 | class FreeCompany extends Lib { 5 | constructor(parent) { 6 | super(parent) 7 | } 8 | 9 | /* 10 | { 11 | server string optional 12 | page int optional 13 | } 14 | */ 15 | async search(name, params={}) { 16 | if(typeof(name) === 'undefined') 17 | throw this.throwError('freecompany.search()','a name') 18 | return this.req('/freecompany/search', Object.assign(params, {name})) 19 | } 20 | 21 | /* 22 | { 23 | extended 24 | data 25 | } 26 | */ 27 | async get(id, params={}) { 28 | if(typeof(id) === 'undefined') 29 | throw this.throwError('freecompany.get()', 'an ID') 30 | 31 | params.data = this.makeCSV(params.data) 32 | 33 | return this.req(`/freecompany/${id}`, params) 34 | } 35 | } 36 | 37 | module.exports = FreeCompany 38 | -------------------------------------------------------------------------------- /lib/linkshell.js: -------------------------------------------------------------------------------- 1 | // https://xivapi.com/docs/Linkshell 2 | const Lib = require('./Lib') 3 | 4 | class Linkshell extends Lib { 5 | constructor(parent) { 6 | super(parent) 7 | } 8 | 9 | /* 10 | { 11 | server string optional 12 | page int optional 13 | } 14 | */ 15 | async search(name, params={}) { 16 | if(typeof(name) === 'undefined') 17 | throw this.throwError('linkshell.search()','a name') 18 | return this.req('/linkshell/search', Object.assign(params, {name})) 19 | } 20 | 21 | async get(id) { 22 | if(typeof(id) === 'undefined') 23 | throw this.throwError('linkshell.get()', 'an ID') 24 | return this.req(`/linkshell/${id}`) 25 | } 26 | } 27 | 28 | module.exports = Linkshell 29 | -------------------------------------------------------------------------------- /lib/pvpteam.js: -------------------------------------------------------------------------------- 1 | // https://xivapi.com/docs/PVP-Team 2 | const Lib = require('./Lib') 3 | 4 | class PvPTeam extends Lib { 5 | constructor(parent) { 6 | super(parent) 7 | } 8 | 9 | /* 10 | { 11 | server string optional 12 | page int optional 13 | } 14 | */ 15 | async search(name, params={}) { 16 | if(typeof name==='undefined') 17 | throw this.throwError('pvpteam.search()', 'a name') 18 | 19 | return this.req('/pvpteam/search',Object.assign(params, {name})) 20 | } 21 | 22 | async get(id) { 23 | if(typeof id==='undefined') 24 | throw this.throwError('pvpteam.get()', 'an ID') 25 | 26 | return this.req(`/pvpteam/${id}`) 27 | } 28 | } 29 | 30 | module.exports = PvPTeam 31 | -------------------------------------------------------------------------------- /lib/search.js: -------------------------------------------------------------------------------- 1 | let { req, reqJSON, makeCSV, throwError } = require('../utils') 2 | 3 | /* 4 | { 5 | filters 6 | lore 7 | 8 | string_column 9 | string_algo 10 | limit 11 | } 12 | */ 13 | module.exports = async function(input, params = {}) { 14 | req = req.bind(this) 15 | reqJSON = reqJSON.bind(this) 16 | 17 | if(typeof(input) === 'undefined') 18 | throw throwError('search()', 'any input') 19 | 20 | let path = params.lore ? '/lore' : '/search' 21 | 22 | switch(typeof(input)) { 23 | // GET method 24 | case 'string': 25 | params.indexes = makeCSV(params.indexes) 26 | return req(path, Object.assign(params, {'string': input})) 27 | 28 | // ElasticSearch JSON method 29 | case 'object': 30 | input.indexes = makeCSV(params.indexes) 31 | input.columns = makeCSV(params.columns) 32 | return reqJSON(path, input) 33 | 34 | default: 35 | throw new Error(`Unexpected input type for search: '${typeof(input)}'`) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@xivapi/js", 3 | "version": "0.4.5", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "@xivapi/js", 9 | "version": "0.4.5", 10 | "license": "MIT", 11 | "dependencies": { 12 | "@root/request": "^1.9.2" 13 | }, 14 | "devDependencies": {} 15 | }, 16 | "node_modules/@root/request": { 17 | "version": "1.9.2", 18 | "resolved": "https://registry.npmjs.org/@root/request/-/request-1.9.2.tgz", 19 | "integrity": "sha512-wVaL9yVV9oDR9UNbPZa20qgY+4Ch6YN8JUkaE4el/uuS5dmhD8Lusm/ku8qJVNtmQA56XLzEDCRS6/vfpiHK2A==" 20 | } 21 | }, 22 | "dependencies": { 23 | "@root/request": { 24 | "version": "1.9.2", 25 | "resolved": "https://registry.npmjs.org/@root/request/-/request-1.9.2.tgz", 26 | "integrity": "sha512-wVaL9yVV9oDR9UNbPZa20qgY+4Ch6YN8JUkaE4el/uuS5dmhD8Lusm/ku8qJVNtmQA56XLzEDCRS6/vfpiHK2A==" 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@xivapi/js", 3 | "version": "0.4.5", 4 | "description": "A Node.JS wrapper for xivapi.com", 5 | "main": "XIVAPI.js", 6 | "directories": { 7 | "lib": "lib" 8 | }, 9 | "dependencies": { 10 | "@root/request": "^1.9.2" 11 | }, 12 | "devDependencies": {}, 13 | "scripts": { 14 | "test": "echo \"Error: no test specified\" && exit 1" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/xivapi/xivapi-js.git" 19 | }, 20 | "keywords": [ 21 | "xivapi", 22 | "ffxiv" 23 | ], 24 | "author": "Kim Kar (https://kai.moe/)", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/xivapi/xivapi-js/issues" 28 | }, 29 | "homepage": "https://github.com/xivapi/xivapi-js#readme", 30 | "types": "./typings/index.d.ts" 31 | } 32 | -------------------------------------------------------------------------------- /resources/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | languages: ['en', 'ja', 'de', 'fr', 'cn', 'kr'] 3 | } 4 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | const XIVAPI = require('./XIVAPI'), 2 | readline = require('readline') 3 | 4 | const xiv = new XIVAPI({ 5 | //snake_case: true, 6 | verbose: true 7 | }) 8 | 9 | let rl = readline.createInterface({ 10 | input: process.stdin, 11 | output: process.stdout, 12 | terminal: false 13 | }).on('line', function (cmd) { 14 | console.log(eval(cmd)) 15 | }) 16 | -------------------------------------------------------------------------------- /typings/index.d.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CharacterGetParams, 3 | CharacterGetResult, 4 | CharacterSearchParams, 5 | CharacterSearchResult, 6 | FreeCompanyGetParams, 7 | FreeCompanyGetResult, 8 | FreeCompanySearchParams, 9 | FreeCompanySearchResult, 10 | LinkshellGetResult, 11 | LinkshellSearchParams, 12 | LinkshellSearchResult, 13 | CWLGetResult, 14 | CWLSearchParams, 15 | CWLSearchResult, 16 | PvPTeamGetResult, 17 | PvPTeamSearchParams, 18 | PvPTeamSearchResult, 19 | SearchIndexResult, 20 | SearchIndexes, 21 | SearchResult, 22 | } from "./utils"; 23 | export * from "./utils"; 24 | 25 | declare module "@xivapi/js" { 26 | type StringAlgo = 27 | | "custom" 28 | | "wildcard" 29 | | "wildcard_plus" 30 | | "fuzzy" 31 | | "term" 32 | | "prefix" 33 | | "match" 34 | | "match_phrase" 35 | | "match_phrase_prefix" 36 | | "multi_match" 37 | | "query_string"; 38 | 39 | interface XIVAPIOptions { 40 | private_key?: string; 41 | language?: "en" | "de" | "fr" | "ja" | "cn" | "ko"; 42 | snake_case?: boolean; 43 | staging?: boolean; 44 | verbose?: boolean; 45 | } 46 | 47 | interface DataSearchParams { 48 | /** 49 | * Search a specific series of indexes separated by commas. 50 | */ 51 | indexes: SearchIndexes[]; 52 | 53 | /** 54 | * Search for lore! This is a special built search endpoint which searches a string through various lore specific content. 55 | * @see https://xivapi.com/docs/Search#lore 56 | */ 57 | lore?: boolean; 58 | 59 | /** 60 | * The column to use in string searches. 61 | * @see https://xivapi.com/docs/Search#filters 62 | */ 63 | filters?: string | string[]; 64 | 65 | /** 66 | * The search algorithm to use for string matching. 67 | * @default "wildcard" 68 | * @see https://xivapi.com/docs/Search 69 | */ 70 | string_algo?: StringAlgo; 71 | 72 | /** 73 | * The column to use in string searches. 74 | */ 75 | string_column?: string; 76 | 77 | /** 78 | * Limit the number of results to show. (from 1 to 100) 79 | */ 80 | limit?: number; 81 | } 82 | 83 | export default class XIVAPI { 84 | private readonly options: XIVAPIOptions; 85 | private readonly endpoint: string; 86 | private readonly globalParams: { [key: string]: string | number }; 87 | 88 | constructor(options: string | XIVAPIOptions); 89 | constructor(options: string | XIVAPIOptions, legacyOptions?: XIVAPIOptions); 90 | 91 | /** 92 | * XIVAPI provides the ability to quickly search all game content via Elasticsearch. 93 | * This search endpoint only searches game content and not: characters, free companies, linkshells or pvp teams. 94 | * Those have their own dedicated search endpoints as they relay to Lodestone. 95 | * @since 0.4.2 96 | * @see https://xivapi.com/docs/Search 97 | * @example 98 | * ```ts 99 | * const xiv = new XIVAPI(); 100 | * await xiv.search("aiming"); // without params 101 | * await xiv.search("aiming", { indexes: ["Item", "Recipe"] }); // with params 102 | * ``` 103 | */ 104 | public search( 105 | input: string, 106 | params?: DataSearchParams 107 | ): Promise; 108 | 109 | /** 110 | * Obtain game content data of Final Fantasy XIV. 111 | * @since 0.4.2 112 | * @see https://xivapi.com/docs/Game-Data 113 | */ 114 | public data: { 115 | /** 116 | * Returns information about a specific object including extended information. 117 | * @since 0.4.2 118 | * @see https://xivapi.com/docs/Game-Data 119 | * @example 120 | * ```ts 121 | * const xiv = new XIVAPI(); 122 | * await xiv.data.get("Item", 1673); 123 | * ``` 124 | */ 125 | get: (name: string, id: string | number) => Promise<{ [key: string]: any }>; 126 | 127 | /** 128 | * Obtain game content data of Final Fantasy XIV. 129 | * @since 0.4.2 130 | * @see https://xivapi.com/docs/Game-Data 131 | * @example 132 | * ```ts 133 | * const xiv = new XIVAPI(); 134 | * await xiv.data.list("Item", { limit: 100 }); // with limit param 135 | * await xiv.data.list("Item", { ids: [1673, 1674] }); // with ids param 136 | * ``` 137 | */ 138 | list: ( 139 | name: keyof typeof SearchIndexes, 140 | params?: { 141 | /** 142 | * Limit the number of items returned by the API. 143 | * @min 100 144 | * @max 3000 145 | */ 146 | limit?: number; 147 | 148 | /** 149 | * Filter the ids down if you want data for a specific series of items. 150 | */ 151 | ids?: number[]; 152 | } 153 | ) => Promise; 154 | 155 | /** 156 | * Returns information about a specific object including extended information. 157 | * @since 0.4.2 158 | * @see https://xivapi.com/docs/Game-Data#servers 159 | */ 160 | servers: () => Promise; 161 | 162 | /** 163 | * Another list of servers grouped by their data center. 164 | * @since 0.4.2 165 | * @see https://xivapi.com/docs/Game-Data#data-center 166 | */ 167 | datacenters: () => Promise<{ [key: string]: string[] }>; 168 | }; 169 | 170 | /** 171 | * Search and retrieve character data from The Lodestone. Providing useful information such as character profile data, minions and mounts obtained, achievements obtained and their relative dates. Character friends, their free company, pvp team and much more! 172 | * @since 0.4.2 173 | * @see https://xivapi.com/docs/Character 174 | */ 175 | public character: { 176 | search: (name: string, params?: CharacterSearchParams) => Promise; 177 | get: (id: string | number, params?: CharacterGetParams) => Promise; 178 | }; 179 | 180 | /** 181 | * Search and retrieve Free Company data from The Lodestone, provides useful information such as profile information and member lists. 182 | * @since 0.4.2 183 | * @see https://xivapi.com/docs/Free-Company 184 | */ 185 | public freecompany: { 186 | search: (name: string, params?: FreeCompanySearchParams) => Promise; 187 | get: (id: string | number, params?: FreeCompanyGetParams) => Promise; 188 | }; 189 | 190 | /** 191 | * Search and retrieve Linkshell data from The Lodestone. 192 | * @since 0.4.2 193 | * @see https://xivapi.com/docs/Linkshell 194 | */ 195 | public linkshell: { 196 | search: (name: string, params?: LinkshellSearchParams) => Promise; 197 | get: (id: string | number) => Promise; 198 | }; 199 | 200 | /** 201 | * Search and retrieve CWL data from The Lodestone. 202 | * @since 0.4.4 203 | * @see https://xivapi.com/docs/Linkshell 204 | */ 205 | public cwl: { 206 | search: (name: string, params?: CWLSearchParams) => Promise; 207 | get: (id: string | number) => Promise; 208 | }; 209 | 210 | /** 211 | * Search and retrieve PVP Team data from The Lodestone. 212 | * @since 0.4.2 213 | * @see https://xivapi.com/docs/PvP-Team 214 | */ 215 | public pvpteam: { 216 | search: (name: string, params?: PvPTeamSearchParams) => Promise; 217 | get: (id: string | number) => Promise; 218 | }; 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /typings/utils/achievements.d.ts: -------------------------------------------------------------------------------- 1 | import { GamePatchData, ItemData, TitleData } from "./item"; 2 | import { SearchResult } from "./search"; 3 | 4 | export interface AchievementsData { 5 | List: { Date: number; ID: number }[]; 6 | Points: number; 7 | } 8 | 9 | export interface AchievementCategoryData { 10 | AchievementsKind: { 11 | ID: number; 12 | Name: string; 13 | Name_de: string; 14 | Name_en: string; 15 | Name_fr: string; 16 | Name_ja: string; 17 | Order: number; 18 | }; 19 | AchievementKindTarget: string; 20 | AchievementKindTargetID: number; 21 | HideCategory: number; 22 | ID: number; 23 | Name: string; 24 | Name_de: string; 25 | Name_en: string; 26 | Name_fr: string; 27 | Name_ja: string; 28 | Order: number; 29 | ShowComplete: number; 30 | } 31 | 32 | export interface AchievementGetResult { 33 | AchievementCategory: AchievementCategoryData; 34 | AchievementCategoryTarget: string; 35 | AchievementCategoryTargetID: number; 36 | AchievementHideCondition: string | null; 37 | AchievementHideConditionTarget: string; 38 | AchievementHideConditionTargetID: number; 39 | AchievementTarget: { ID: number; Type: 1; Value: number } | null; 40 | AchievementTargetID: number | null; 41 | ClassJobRequirements: {}[]; 42 | Data0: number; 43 | Data1: number; 44 | Data2: number; 45 | Data3: number; 46 | Data4: number; 47 | Data5: number; 48 | Data6: number; 49 | Data7: number; 50 | Description: string; 51 | Description_de: string; 52 | Description_en: string; 53 | Description_fr: string; 54 | Description_ja: string; 55 | GameContentLinks: []; 56 | GamePatch: GamePatchData; 57 | ID: number; 58 | Icon: string; 59 | IconHD: string; 60 | ItemID: number; 61 | Item: ItemData | null; 62 | ItemTarget: string; 63 | ItemTargetID: number; 64 | Key: number; 65 | Name: string; 66 | Name_de: string; 67 | Name_en: string; 68 | Name_fr: string; 69 | Name_ja: string; 70 | Order: number; 71 | Patch: number | null; 72 | Points: number; 73 | PostAchievements: []; 74 | PreAchievements: []; 75 | QuestRequirements: {}[]; 76 | QuestRequirementsAll: boolean; 77 | Title: TitleData | null; 78 | TitleTarget: string; 79 | TitleTargetID: number; 80 | Type: number; 81 | Url: string; 82 | } 83 | -------------------------------------------------------------------------------- /typings/utils/character.d.ts: -------------------------------------------------------------------------------- 1 | import { SearchParams, SearchResult } from "./search"; 2 | import { AchievementsData } from "./achievements"; 3 | import { FreeCompanyGetResult } from "./freecompany"; 4 | 5 | type Omit = Pick>; 6 | export interface CharacterSearchParams extends Omit {} 7 | export interface CharacterGetParams { 8 | /** 9 | * If set to 1, the API will return more data in the response by extending out the data IDs to useful objects. 10 | */ 11 | extended?: 1; 12 | 13 | /** 14 | * By default the `Character`, `ClassJobs`, `Minion` and `Mount` data will return, you can request more data using the `data` query. 15 | * @see https://xivapi.com/docs/Character#character 16 | */ 17 | data?: ("AC" | "FR" | "FC" | "FC" | "FCM" | "MIMO" | "PVP")[]; 18 | } 19 | 20 | export interface BasicCharacterData { 21 | Avatar: string; 22 | FeastMatches: number; 23 | ID: number; 24 | Lang: string | null; 25 | Name: string; 26 | Rank: number | null; 27 | RankIcon: string | null; 28 | Server: string; 29 | } 30 | 31 | export interface CharacterSearchResult extends SearchResult { 32 | Results: BasicCharacterData[]; 33 | } 34 | 35 | export interface ClassJobData { 36 | ClassID: number; 37 | ExpLevel: number; 38 | ExpLevelMax: number; 39 | ExpLevelTogo: number; 40 | IsSpecialised: boolean; 41 | JobID: number; 42 | Level: number; 43 | Name: string; 44 | UnlockedState: { 45 | ID: number; 46 | Name: string; 47 | }; 48 | } 49 | 50 | export interface GearData { 51 | Creator: string | null; 52 | Dye: number | null; 53 | ID: number | null; 54 | Materia: number[]; 55 | Mirage: number | null; 56 | } 57 | 58 | export interface GearsetData { 59 | Attributes: { [key: string]: number }; 60 | ClassID: number; 61 | Gear: { 62 | Body: GearData | undefined; 63 | Bracelets: GearData | undefined; 64 | Earrings: GearData | undefined; 65 | Feet: GearData | undefined; 66 | Hands: GearData | undefined; 67 | Head: GearData | undefined; 68 | Legs: GearData | undefined; 69 | MainHand: GearData | undefined; 70 | Necklace: GearData | undefined; 71 | OffHand: GearData | undefined; 72 | Ring1: GearData | undefined; 73 | Ring2: GearData | undefined; 74 | SoulCrystal: GearData | undefined; 75 | }; 76 | GearKey: string; 77 | JobID: number; 78 | Level: number; 79 | } 80 | 81 | export interface CharacterData { 82 | ActiveClassJob: ClassJobData; 83 | Avatar: string; 84 | Bio: string; 85 | ClassJobs: ClassJobData[]; 86 | ClassJobsBozjan: { Level: number | null; Mettle: number | null; Name: string }; 87 | ClassJobsElemental: { 88 | ExpLevel: number; 89 | ExpLevelMax: number; 90 | ExpLevelTogo: number; 91 | Level: number; 92 | Name: string; 93 | }[]; 94 | DC: string; 95 | FreeCompanyId: string | null; 96 | FreeCompanyName: string | null; 97 | GearSet: GearsetData; 98 | Gender: 1 | 2; 99 | GrandCompany: { 100 | NameID: number; 101 | RankID: number; 102 | }; 103 | GuardianDeity: number; 104 | ID: number; 105 | Lang: string | null; 106 | Name: string; 107 | Nameday: string; 108 | ParseDate: number; 109 | Portrait: string; 110 | PvPTeamId: number | null; 111 | Race: number; 112 | Server: string; 113 | Title: number; 114 | TitleTop: boolean; 115 | Town: number; 116 | Tribe: number; 117 | } 118 | 119 | export interface CharacterGetResult { 120 | Achievements: AchievementsData | null; 121 | AchievementsPublic: boolean | null; 122 | Character: CharacterData; 123 | FreeCompany: FreeCompanyGetResult | null; 124 | FreeCompanyMembers: BasicCharacterData[] | null; 125 | Friends: BasicCharacterData[] | null; 126 | FriendsPublic: boolean | null; 127 | Minions: { Icon: string; Name: string }[] | null; 128 | Mounts: { Icon: string; Name: string }[] | null; 129 | PvPTeam: null; 130 | } 131 | -------------------------------------------------------------------------------- /typings/utils/cwl.ts: -------------------------------------------------------------------------------- 1 | import { CharacterSearchResult } from "./character"; 2 | import { SearchParams, SearchResult } from "./search"; 3 | 4 | export interface CWLSearchParams extends SearchParams {} 5 | 6 | export interface CWLSearchResult extends SearchResult { 7 | Results: { 8 | Crest: string[]; 9 | ID: string; 10 | Name: string; 11 | Server: string; 12 | }[]; 13 | } 14 | 15 | export interface CWLGetResult { 16 | CWL: { 17 | ID: string; 18 | Pagination: SearchResult["Pagination"]; 19 | Profile: { 20 | Name: string; 21 | }; 22 | Results: CharacterSearchResult["Results"]; 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /typings/utils/freecompany.d.ts: -------------------------------------------------------------------------------- 1 | import { SearchParams, SearchResult } from "./search"; 2 | 3 | export interface FreeCompanySearchParams extends SearchParams {} 4 | export interface FreeCompanyGetParams { 5 | /** 6 | * If set to 1, the API will return more data in the response by extending out the data IDs to useful objects. 7 | */ 8 | extended?: 1; 9 | 10 | /** 11 | * By default the `Character`, `ClassJobs`, `Minion` and `Mount` data will return, you can request more data using the `data` query. 12 | * @see https://xivapi.com/docs/Character#character 13 | */ 14 | data?: ["FCM"]; 15 | } 16 | 17 | export interface FreeCompanySearchResult extends SearchResult { 18 | Results: { 19 | Crest: string[]; 20 | ID: string; 21 | Name: string; 22 | Server: string; 23 | }[]; 24 | } 25 | 26 | export interface FreeCompanyGetResult { 27 | Active: string; 28 | ActiveMemberCount: number; 29 | Crest: string[]; 30 | DC: string; 31 | Estate: { 32 | Greeting: string; 33 | Name: string; 34 | Plot: string; 35 | }; 36 | Focus: { Icon: string; Name: string; Status: boolean }[]; 37 | Formed: number; 38 | GrandCompany: "Maelstrom" | "Order of the Twin Adder" | "Immortal Flames"; 39 | ID: string; 40 | Name: string; 41 | ParseDate: number; 42 | Rank: string; 43 | Rankings: { 44 | Monthly: number; 45 | Weekly: number; 46 | }; 47 | Recruitment: string; 48 | Reputation: [ 49 | { Name: string; Progress: number; Rank: number }, 50 | { Name: string; Progress: number; Rank: number }, 51 | { Name: string; Progress: number; Rank: number } 52 | ]; 53 | Seeking: { Icon: string; Name: string; Status: boolean }[]; 54 | Server: string; 55 | Slogan: string; 56 | Tag: string; 57 | } 58 | -------------------------------------------------------------------------------- /typings/utils/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from "./character"; 2 | export * from "./freecompany"; 3 | export * from "./linkshell"; 4 | export * from "./cwl"; 5 | export * from "./pvpteam"; 6 | export * from "./search"; 7 | -------------------------------------------------------------------------------- /typings/utils/item.d.ts: -------------------------------------------------------------------------------- 1 | export interface GamePatchData { 2 | Banner: string; 3 | ExName: string; 4 | ExVersion: number; 5 | ID: number; 6 | Name: string; 7 | Name_de: string; 8 | Name_en: string; 9 | Name_fr: string; 10 | Name_ja: string; 11 | Name_kr: string; 12 | ReleaseDate: string; 13 | Version: string; 14 | } 15 | 16 | export interface TitleData { 17 | ID: number; 18 | Icon: string; 19 | IsPrefix: number; 20 | Name: string; 21 | NameFemale: string; 22 | NameFemale_de: string; 23 | NameFemale_en: string; 24 | NameFemale_fr: string; 25 | NameFemale_ja: string; 26 | Name_de: string; 27 | Name_en: string; 28 | Name_fr: string; 29 | Name_ja: string; 30 | Order: number; 31 | } 32 | 33 | export interface ItemActionData { 34 | CondBattle: number; 35 | CondLv: number; 36 | CondPVP: number; 37 | CondPVPOnly: number; 38 | Data0: number; 39 | Data1: number; 40 | Data2: number; 41 | Data3: number; 42 | Data4: number; 43 | Data5: number; 44 | Data6: number; 45 | Data7: number; 46 | Data8: number; 47 | DataHQ0: number; 48 | DataHQ1: number; 49 | DataHQ2: number; 50 | DataHQ3: number; 51 | DataHQ4: number; 52 | DataHQ5: number; 53 | DataHQ6: number; 54 | DataHQ7: number; 55 | DataHQ8: number; 56 | ID: number; 57 | Type: number; 58 | } 59 | 60 | export interface ItemData { 61 | AdditionalData: number; 62 | Adjective: number; 63 | AetherialReduce: number; 64 | AlwaysCollectable: number; 65 | Article: number; 66 | BaseParam0: null; 67 | BaseParam0Target: string; 68 | BaseParam0TargetID: number; 69 | BaseParam1: null; 70 | BaseParam1Target: string; 71 | BaseParam1TargetID: number; 72 | BaseParam2: null; 73 | BaseParam2Target: string; 74 | BaseParam2TargetID: number; 75 | BaseParam3: null; 76 | BaseParam3Target: string; 77 | BaseParam3TargetID: number; 78 | BaseParam4: null; 79 | BaseParam4Target: string; 80 | BaseParam4TargetID: number; 81 | BaseParam5: null; 82 | BaseParam5Target: string; 83 | BaseParam5TargetID: number; 84 | BaseParamModifier: number; 85 | BaseParamSpecial0: null; 86 | BaseParamSpecial0Target: string; 87 | BaseParamSpecial0TargetID: number; 88 | BaseParamSpecial1: null; 89 | BaseParamSpecial1Target: string; 90 | BaseParamSpecial1TargetID: number; 91 | BaseParamSpecial2: null; 92 | BaseParamSpecial2Target: string; 93 | BaseParamSpecial2TargetID: number; 94 | BaseParamSpecial3: null; 95 | BaseParamSpecial3Target: string; 96 | BaseParamSpecial3TargetID: number; 97 | BaseParamSpecial4: null; 98 | BaseParamSpecial4Target: string; 99 | BaseParamSpecial4TargetID: number; 100 | BaseParamSpecial5: null; 101 | BaseParamSpecial5Target: string; 102 | BaseParamSpecial5TargetID: number; 103 | BaseParamValue0: number; 104 | BaseParamValue1: number; 105 | BaseParamValue2: number; 106 | BaseParamValue3: number; 107 | BaseParamValue4: number; 108 | BaseParamValue5: number; 109 | BaseParamValueSpecial0: number; 110 | BaseParamValueSpecial1: number; 111 | BaseParamValueSpecial2: number; 112 | BaseParamValueSpecial3: number; 113 | BaseParamValueSpecial4: number; 114 | BaseParamValueSpecial5: number; 115 | Block: number; 116 | BlockRate: number; 117 | CanBeHq: number; 118 | CastTimeS: number; 119 | ClassJobCategory: null; 120 | ClassJobCategoryTarget: string; 121 | ClassJobCategoryTargetID: number; 122 | ClassJobRepair: null; 123 | ClassJobRepairTarget: string; 124 | ClassJobRepairTargetID: number; 125 | ClassJobUse: null; 126 | ClassJobUseTarget: string; 127 | ClassJobUseTargetID: number; 128 | CooldownS: number; 129 | DamageMag: number; 130 | DamagePhys: number; 131 | DefenseMag: number; 132 | DefensePhys: number; 133 | DelayMs: number; 134 | Description: string; 135 | Description_de: string; 136 | Description_en: string; 137 | Description_fr: string; 138 | Description_ja: string; 139 | Desynth: number; 140 | EquipRestriction: number; 141 | EquipSlotCategory: null; 142 | EquipSlotCategoryTarget: string; 143 | EquipSlotCategoryTargetID: number; 144 | FilterGroup: number; 145 | GrandCompany: null; 146 | GrandCompanyTarget: string; 147 | GrandCompanyTargetID: number; 148 | ID: number; 149 | Icon: string; 150 | IconHD: string; 151 | IconID: number; 152 | IsAdvancedMeldingPermitted: number; 153 | IsCollectable: number; 154 | IsCrestWorthy: number; 155 | IsDyeable: number; 156 | IsGlamourous: number; 157 | IsIndisposable: number; 158 | IsPvP: number; 159 | IsUnique: number; 160 | IsUntradable: number; 161 | ItemAction: ItemActionData; 162 | ItemActionTarget: string; 163 | ItemActionTargetID: string; 164 | ItemGlamour: null; 165 | ItemGlamourTarget: string; 166 | ItemGlamourTargetID: number; 167 | ItemRepair: null; 168 | ItemRepairTarget: string; 169 | ItemRepairTargetID: number; 170 | ItemSearchCategory: null; 171 | ItemSearchCategoryTarget: string; 172 | ItemSearchCategoryTargetID: number; 173 | ItemSeries: null; 174 | ItemSeriesTarget: string; 175 | ItemSeriesTargetID: number; 176 | ItemSortCategory: { 177 | ID: number; 178 | Param: number; 179 | }; 180 | ItemSortCategoryTarget: string; 181 | ItemSortCategoryTargetID: number; 182 | ItemSpecialBonus: null; 183 | ItemSpecialBonusParam: number; 184 | ItemSpecialBonusTarget: string; 185 | ItemSpecialBonusTargetID: number; 186 | ItemUICategory: { 187 | ID: number; 188 | Icon: string; 189 | IconHD: string; 190 | IconID: number; 191 | Name: string; 192 | Name_de: string; 193 | Name_en: string; 194 | Name_fr: string; 195 | Name_ja: string; 196 | OrderMajor: number; 197 | OrderMinor: number; 198 | }; 199 | ItemUICategoryTarget: string; 200 | ItemUICategoryTargetID: number; 201 | LevelEquip: number; 202 | LevelItem: number; 203 | Lot: number; 204 | MateriaSlotCount: number; 205 | MaterializeType: number; 206 | ModelMain: string; 207 | ModelSub: string; 208 | Name: string; 209 | Name_de: string; 210 | Name_en: string; 211 | Name_fr: string; 212 | Name_ja: string; 213 | Plural: string; 214 | Plural_de: string; 215 | Plural_en: string; 216 | Plural_fr: string; 217 | Plural_ja: string; 218 | PossessivePronoun: number; 219 | PriceLow: number; 220 | PriceMid: number; 221 | Pronoun: number; 222 | Rarity: number; 223 | Singular: string; 224 | Singular_de: string; 225 | Singular_en: string; 226 | Singular_fr: string; 227 | Singular_ja: string; 228 | StackSize: number; 229 | StartsWithVowel: number; 230 | SubStatCategory: number; 231 | } 232 | -------------------------------------------------------------------------------- /typings/utils/linkshell.ts: -------------------------------------------------------------------------------- 1 | import { CharacterSearchResult } from "./character"; 2 | import { SearchParams, SearchResult } from "./search"; 3 | 4 | export interface LinkshellSearchParams extends SearchParams {} 5 | 6 | export interface LinkshellSearchResult extends SearchResult { 7 | Results: { 8 | Crest: string[]; 9 | ID: string; 10 | Name: string; 11 | Server: string; 12 | }[]; 13 | } 14 | 15 | export interface LinkshellGetResult { 16 | Linkshell: { 17 | ID: string; 18 | Pagination: SearchResult["Pagination"]; 19 | Profile: { 20 | Name: string; 21 | Server: string; 22 | }; 23 | Results: CharacterSearchResult["Results"]; 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /typings/utils/pvpteam.ts: -------------------------------------------------------------------------------- 1 | import { CharacterSearchResult } from "./character"; 2 | import { SearchParams, SearchResult } from "./search"; 3 | 4 | export interface PvPTeamSearchParams extends SearchParams {} 5 | 6 | export interface PvPTeamSearchResult extends SearchResult { 7 | Results: { 8 | Crest: string[]; 9 | ID: string; 10 | Name: string; 11 | Server: string; 12 | }[]; 13 | } 14 | 15 | export interface PvPTeamGetResult { 16 | PvPTeam: { 17 | ID: string; 18 | Pagination: SearchResult["Pagination"]; 19 | Profile: { 20 | Crest: string[]; 21 | Name: string; 22 | Server: string; 23 | }; 24 | Results: CharacterSearchResult["Results"]; 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /typings/utils/search.d.ts: -------------------------------------------------------------------------------- 1 | export enum SearchIndexes { 2 | "Achievement", 3 | "Title", 4 | "Action", 5 | "CraftAction", 6 | "Trait", 7 | "PvPAction", 8 | "PvPTrait", 9 | "Status", 10 | "BNpcName", 11 | "ENpcResident", 12 | "Companion", 13 | "Mount", 14 | "Leve", 15 | "Emote", 16 | "InstanceContent", 17 | "Item", 18 | "Recipe", 19 | "Fate", 20 | "Quest", 21 | "ContentFinderCondition", 22 | "Balloon", 23 | "BuddyEquip", 24 | "Orchestrion", 25 | "PlaceName", 26 | "Weather", 27 | "World", 28 | "Map", 29 | "lore_finder", 30 | } 31 | 32 | export interface SearchResult { 33 | /** 34 | * The pagination data for the search. 35 | */ 36 | Pagination: { 37 | Page: number; 38 | PageNext: number | null; 39 | PagePrev: number | null; 40 | PageTotal: number; 41 | Results: number; 42 | ResultsPerPage: number; 43 | ResultsTotal: number; 44 | }; 45 | 46 | /** 47 | * The results obtained from the search. 48 | */ 49 | Results: unknown[]; 50 | } 51 | 52 | export interface SearchIndexResult extends SearchResult { 53 | Results: { ID: number; Icon: string | null; Name: string | null; Url: string }[]; 54 | } 55 | 56 | interface SearchParams { 57 | /**- 58 | * The name to search for, you can use `+` for spaces or let the API handle it for you. 59 | */ 60 | name?: string; 61 | 62 | /** 63 | * The server to search against, this is case sensitive. 64 | * @see https://xivapi.com/servers 65 | */ 66 | server?: string; 67 | 68 | /** 69 | * Search or move to a specific page. 70 | */ 71 | page?: number; 72 | } 73 | -------------------------------------------------------------------------------- /utils.js: -------------------------------------------------------------------------------- 1 | const request = require('@root/request') 2 | 3 | module.exports = { 4 | //standard request function 5 | async req(path, params={}) { 6 | let convs = ['snake_case', 'extended'] 7 | for (const c of convs) { 8 | if(typeof params[c] !== 'undefined') 9 | params[c] = params[c] ? 1 : 0 10 | } 11 | 12 | 13 | params = Object.assign({}, this.globalParams, params) 14 | 15 | if(this.verbose) 16 | console.log(`Requesting ${path} with params: `, params) 17 | 18 | return (await request({ 19 | url: `${this.endpoint + path}${Object.keys(params).length > 0 ? `?${new URLSearchParams(params).toString()}` : ''}`, 20 | json: true 21 | })).body 22 | }, 23 | 24 | //JSON request function 25 | async reqJSON(path, body) { 26 | if(this.verbose) 27 | console.log(`Requesting ${path} with body: `, body) 28 | 29 | return (await request({ 30 | method: 'POST', 31 | url: this.endpoint + path, 32 | body: body, 33 | json: true 34 | })).body 35 | }, 36 | 37 | //handle both comma-separated strings, and string arrays, for CSV params 38 | makeCSV(x) { 39 | if(typeof(x) === 'undefined') 40 | return 41 | 42 | if(Array.isArray(x)) 43 | return x.join(',') 44 | if(typeof(x) === 'string') 45 | return x 46 | }, 47 | 48 | throwError(method, param) { 49 | return Error(`xivapi-js: Can't use ${method} without providing ${param}.`) 50 | } 51 | } 52 | --------------------------------------------------------------------------------