UNPKG

genshin-db

Version:

Genshin Impact v5.8 JSON data. Search and get results in all in-game languages! Sources from the fandom wiki and GenshinData repo.

545 lines (488 loc) 24.8 kB
const fuzzysort = require('fuzzysort'); //const design = require('./design.json'); const language = require('./language.js'); const Folder = require('./folder.js').FoldersEnum; const FolderFormat = require('./folder.js').format; const altnames = require('./altnames.js'); const Options = require('./Options.js'); const { getData, getIndex, addData } = require('./getdata.js'); // object that will be exported const genshin = {}; // Default options const baseoptions = new Options( false, // dumpResult true, // matchNames true, // matchAltNames false, // matchAliases false, // matchCategories false, // verboseCategories ["English"], // queryLanguages "English", // resultLanguage false, // v4Props false // v4PropsOnly ); // returns an array of strings used for autocomplete aka fuzzy searching function buildQueryDict(querylangs, folder, opts) { let dict = opts.matchCategories ? ['names'] : []; for (const lang of querylangs) { const index = getIndex(lang, folder); if (index === undefined) continue; if (opts.matchNames && index.namemap) dict = dict.concat(Object.values(index.namemap)); if (opts.matchAltNames) dict = dict.concat(altnames.getAltNamesList(lang, folder)); if (opts.matchAliases && index.aliases) dict = dict.concat(Object.keys(index.aliases)); if (opts.matchCategories && index.categories) dict = dict.concat(Object.keys(index.categories)); } return dict; } function autocomplete(input, dict, key) { if (key) { let result = fuzzysort.go(input, dict, { limit: 1, key: key })[0]; return result === undefined ? undefined : result.obj; } else { let result = fuzzysort.go(input, dict, { limit: 1 })[0]; return result === undefined ? undefined : result.target; } } /** * Gets rid of unnecessary properties. * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/) * @returns {object} - A well-formatted object that matches the same properties as an Option instance */ function sanitizeOptions(opts) { //Even if opts property is an instance of Options, the type is still 'object' if (!opts || typeof opts !== 'object') return; let sanOpts = {}; ['dumpResult', 'matchNames', 'matchAltNames', 'matchAliases', 'matchCategories', 'verboseCategories', 'v4Props', 'v4PropsOnly'].forEach(prop => { if (typeof opts[prop] === 'boolean') sanOpts[prop] = opts[prop]; }); opts.resultLanguage = language.format(opts.resultLanguage); if (opts.resultLanguage !== undefined) sanOpts.resultLanguage = opts.resultLanguage; opts.queryLanguages = language.format(opts.queryLanguages); if (opts.queryLanguages !== undefined) sanOpts.queryLanguages = Array.isArray(opts.queryLanguages) ? opts.queryLanguages : [opts.queryLanguages]; return sanOpts; } const MatchType = { None: "none", Names: "names", AltNames: "altnames", Aliases: "aliases", Categories: "categories" } // TODO: if folder is undefined, search through every folder /** * @param query {string} * @param folders {string|string[]} * @param opts {object|Options} */ function retrieveData(query, folders, opts, getfilename) { opts = Object.assign({}, baseoptions, sanitizeOptions(opts)); let queryMatch; // the query that we autocompleted let folderMatch; // the folder that the queryMatch matched against if (Array.isArray(folders)) { const qdict = folders.reduce((accum, f) => { return accum.concat(buildQueryDict(opts.queryLanguages, f, opts).map(e => ({ name: e, folder: f }))); }, []); const result = autocomplete("" + query, qdict, 'name'); if (result) { folderMatch = result.folder; queryMatch = result.name; } } else { folderMatch = folders; queryMatch = autocomplete("" + query, buildQueryDict(opts.queryLanguages, folderMatch, opts)); } if (queryMatch === undefined) { // no result; return opts.dumpResult ? getDump(query, folders, undefined, folderMatch, MatchType.None, opts, undefined, undefined) : undefined; } for (let lang of opts.queryLanguages) { let langindex = getIndex(lang, folderMatch); if (langindex === undefined) continue; // check if queryMatch is in .names if (opts.matchNames && langindex.names[queryMatch] !== undefined) { const filename = langindex.names[queryMatch]; if (getfilename) return filename; let result = getData(opts.resultLanguage, folderMatch, filename, opts.v4Props, opts.v4PropsOnly); return opts.dumpResult ? getDump(query, folders, queryMatch, folderMatch, MatchType.Names, opts, filename, result) : result; } // check if queryMatch is in .altnames if (opts.matchAltNames && altnames.getFilename(lang, folderMatch, queryMatch)) { const filename = altnames.getFilename(lang, folderMatch, queryMatch); if (getfilename) return filename; let result = getData(opts.resultLanguage, folderMatch, filename, opts.v4Props, opts.v4PropsOnly); return opts.dumpResult ? getDump(query, folders, queryMatch, folderMatch, MatchType.AltNames, opts, filename, result) : result; } // check if queryMatch is in .aliases if (opts.matchAliases && langindex.aliases[queryMatch] !== undefined) { const filename = langindex.aliases[queryMatch]; if (getfilename) return filename; let result = getData(opts.resultLanguage, folderMatch, filename, opts.v4Props, opts.v4PropsOnly); return opts.dumpResult ? getDump(query, folders, queryMatch, folderMatch, MatchType.Aliases, opts, filename, result) : result; } // check if queryMatch is in .categories or is 'names' if (opts.matchCategories && (queryMatch === 'names' || langindex.categories[queryMatch] !== undefined)) { let reslangindex = getIndex(opts.resultLanguage, folderMatch); if (reslangindex === undefined) return undefined; let tmparr = (queryMatch === 'names') ? Object.keys(reslangindex.namemap) : langindex.categories[queryMatch]; // change the array of filenames into an array of data objects or data names. ignores undefined results if any let result = tmparr.reduce((accum, filename) => { let res = opts.verboseCategories ? getData(opts.resultLanguage, folderMatch, filename, opts.v4Props, opts.v4PropsOnly) : reslangindex.namemap[filename]; if (res !== undefined) accum.push(res); return accum; }, []); return opts.dumpResult ? getDump(query, folders, queryMatch, folderMatch, MatchType.Categories, opts, tmparr, result) : result; } } return opts.dumpResult ? getDump(query, folders, queryMatch, folderMatch, MatchType.None, opts, undefined, undefined) : undefined; } function getDump(query, folders, match, matchfolder, matchtype, options, filename, result) { return { query: query, folder: folders, match: match, matchfolder: matchfolder, matchtype: matchtype, options: JSON.parse(JSON.stringify(options)), filename: filename !== undefined ? JSON.parse(JSON.stringify(filename)) : filename, result: result } } /** * Change default library options * @param {object|Options} options - See [default options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) format * @returns {void} Nothing */ genshin.setOptions = function (options) { Object.assign(baseoptions, sanitizeOptions(options)); } /** * @returns {object} - The library's options */ genshin.getOptions = function () { return JSON.parse(JSON.stringify(baseoptions)); } /** * Get list of possible values for a category property. * @param {string} query - * @param {string|Folder} - * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {array|undefined} - */ genshin.categories = genshin.category = function (query, folder, opts) { if (typeof folder !== 'string' || Folder[folder] === undefined) return undefined; // invalid folder opts = Object.assign({}, baseoptions, sanitizeOptions(opts)); const index = getIndex(opts.resultLanguage, folder); const queryDict = Object.keys(index.properties); if (query === 'names') { return queryDict; } else { let queryMatch = autocomplete("" + query, queryDict); if (queryMatch === undefined) return undefined; return index.properties[queryMatch]; } } /** * Get character(s)' information. * @param {string} query - The name of the character, character title, elements, birthday months [, ...] see [possible query inputs for character(s) method](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - The data found based on the query string and options parameter. */ genshin.characters = genshin.character = function (query, opts) { return retrieveData(query, Folder.characters, opts); } /** * Get outfit's information. * @param {string} query - The name of the outfit, or character name, elements, birthday months [, ...] see [possible query inputs for character(s) method](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - The data found based on the query string and options parameter. */ genshin.outfits = genshin.outfit = function (query, opts) { return retrieveData(query, Folder.outfits, opts); } /** * Get the data about talent(s) for character(s). * @param {string} query - character name or upgrade material. * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - the combat skills and passive skills for a character(s). */ genshin.talents = genshin.talent = function (query, opts) { return retrieveData(query, Folder.talents, opts); } /** * Get data about a weapon(s). * * The returned object also includes a method to calculate the stats of the weapon at each level, namely .stats(). * @param {string} query - Weapon name, type, rarity or ascension material type. * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} The data found based on the query string and options parameter. */ genshin.weapons = genshin.weapon = function (query, opts) { return retrieveData(query, Folder.weapons, opts); } /** * Get data about weapon material type(s). * @param {string} query - Weapon ascension material name, days of the week, region, or domain of forgery. * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - The data found based on the query string and options parameter. */ genshin.weaponmaterialtypes = genshin.weaponmaterialtype = function (query, opts) { return retrieveData(query, Folder.weaponmaterialtypes, opts); } /** * Get data about talent material type(s). * @param {string} query - Talent book name, days of the week, region, or name of domain of mastery. * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - The data found based on the query string and options parameter. */ genshin.talentmaterialtypes = genshin.talentmaterialtype = function (query, opts) { return retrieveData(query, Folder.talentmaterialtypes, opts); } /** * Get data about a material(s). * @param {string} query - Material rairty, type, "WOOD", ingredient, specialty liyue, domain, days of the week, talent books... * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - The data found based on the query string and options parameter. */ genshin.materials = genshin.material = function (query, opts) { return retrieveData(query, Folder.materials, opts); } /** * Get data about an element. * @param {string} query - Name of the element. * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - Data about the element. */ genshin.elements = genshin.element = function (query, opts) { return retrieveData(query, Folder.elements, opts); } /** * Get data about constellation for a character. * @param {string} query - Name of the character. * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - Constellation data for the character. */ genshin.constellations = genshin.constellation = function (query, opts) { return retrieveData(query, Folder.constellations, opts); } /** * Get data about an artifact(s) * @param {string} query - Artifact name or rarity. * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - The data found based on the query string and options parameter. */ genshin.artifacts = genshin.artifact = function (query, opts) { return retrieveData(query, Folder.artifacts, opts); } /** * Get data about a rarity. * @param {string} query - The rarity you want to get information about. * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - The data found based on the query string and options parameter. */ genshin.rarity = function (query, opts) { return retrieveData(query, Folder.rarity, opts); } /** * Get data about a food. * @param {string} query - Recipe name, food rarity, recipe type, food ingredients, buffs or character name with a specialty dish. * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - The data found based on the query string and options parameter. */ genshin.foods = genshin.food = function (query, opts) { return retrieveData(query, Folder.foods, opts); } /** * Get data about a domain. * @param {string} query - Domain name, domain entrance name, domain type, recommended elements or days of the week. * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - The data found based on the query string and options parameter. */ genshin.domains = genshin.domain = function (query, opts) { return retrieveData(query, Folder.domains, opts); } /** * Get data about an enemy or boss. * @param {string} query - Enemy name, enemy type ("COMMON", "ELITE", "BOSS") or enemy category. * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - The data found based on the query string and options parameter. */ genshin.enemies = genshin.enemy = function (query, opts) { return retrieveData(query, Folder.enemies, opts); } /** * Get data about an achievement * @param {string} query - Achievement name, achievement group. * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - The data found based on the query string and options parameter. */ genshin.achievements = genshin.achievement = function (query, opts) { return retrieveData(query, Folder.achievements, opts); } /** * Get data about an achievement group * @param {string} query - Achievement group name. * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - The data found based on the query string and options parameter. */ genshin.achievementgroups = genshin.achievementgroup = function (query, opts) { return retrieveData(query, Folder.achievementgroups, opts); } /** * Get data about a wind glider * @param {string} query - Wind glider name. * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - The data found based on the query string and options parameter. */ genshin.windgliders = genshin.windglider = function (query, opts) { return retrieveData(query, Folder.windgliders, opts); } /** * Get data about animals * @param {string} query - Animal name. * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - The data found based on the query string and options parameter. */ genshin.animals = genshin.animal = genshin.wildlife = function (query, opts) { return retrieveData(query, Folder.animals, opts); } /** * Get data about namecards * @param {string} query - Namecard name * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - The data found based on the query string and options parameter. */ genshin.namecards = genshin.namecard = function (query, opts) { return retrieveData(query, Folder.namecards, opts); } /** * Get data about geographies * @param {string} query - viewpoint name. * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - The data found based on the query string and options parameter. */ genshin.geographies = genshin.geography = genshin.viewpoints = genshin.viewpoint = function (query, opts) { return retrieveData(query, Folder.geographies, opts); } /** * Get data about adventure ranks * @param {string} query - adventure level * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - The data found based on the query string and options parameter. */ genshin.adventureranks = genshin.adventurerank = function (query, opts) { return retrieveData(query, Folder.adventureranks, opts); } /** * Get data about crafting recipes at the crafting bench * @param {string} query - item to craft * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - The data found based on the query string and options parameter. */ genshin.crafts = genshin.craft = function (query, opts) { return retrieveData(query, Folder.crafts, opts); } /** * Get data about emojis * @param {string} query - emoji name to search * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - The data found based on the query string and options parameter. */ genshin.emojis = genshin.emoji = function (query, opts) { return retrieveData(query, Folder.emojis, opts); } /** * Get data about voiceovers for characters * @param {string} query - character name of the voiceover you want to search for * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - The data found based on the query string and options parameter. */ genshin.voiceovers = genshin.voiceover = function (query, opts) { return retrieveData(query, Folder.voiceovers, opts); } genshin.tcgactioncards = genshin.tcgactioncard = function (query, opts) { return retrieveData(query, Folder.tcgactioncards, opts); } genshin.tcgcardbacks = genshin.tcgcardback = function (query, opts) { return retrieveData(query, Folder.tcgcardbacks, opts); } genshin.tcgcardboxes = genshin.tcgcardbox = function (query, opts) { return retrieveData(query, Folder.tcgcardboxes, opts); } genshin.tcgcharactercards = genshin.tcgcharactercard = function (query, opts) { return retrieveData(query, Folder.tcgcharactercards, opts); } genshin.tcgdetailedrules = genshin.tcgdetailedrule = function (query, opts) { return retrieveData(query, Folder.tcgdetailedrules, opts); } genshin.tcgenemycards = genshin.tcgenemycard = function (query, opts) { return retrieveData(query, Folder.tcgenemycards, opts); } genshin.tcgkeywords = genshin.tcgkeyword = function (query, opts) { return retrieveData(query, Folder.tcgkeywords, opts); } genshin.tcglevelrewards = genshin.tcglevelreward = function (query, opts) { return retrieveData(query, Folder.tcglevelrewards, opts); } genshin.tcgstatuseffects = genshin.tcgstatuseffect = function (query, opts) { return retrieveData(query, Folder.tcgstatuseffects, opts); } genshin.tcgsummons = genshin.tcgsummon = function (query, opts) { return retrieveData(query, Folder.tcgsummons, opts); } /** * Get data in any specified folder. * @param {string} folder - Folder name. For example: 'characters'. * @param {object|Options} opts - The library options, see [Valid Options](https://github.com/theBowja/genshin-db/blob/main/readme.md#genshindbsetoptionsopts) * @returns {object} - The data found based on the query string and options parameter. */ genshin.searchFolder = function (folder, query, opts) { folder = FolderFormat(folder); if(typeof folder !== 'string') return undefined; return retrieveData(query, folder, opts); } genshin.searchMultipleFolders = function (folders, query, opts) { folders = FolderFormat(folders); if(!Array.isArray(folders)) return undefined; return retrieveData(query, folders, opts); } genshin.helper = require('./helper.js'); // EXPORT ENUMS genshin.Language = genshin.Languages = language.LanguagesEnum; genshin.Folder = genshin.Folders = Folder; genshin.MatchType = genshin.MatchTypes = MatchType; //TODO: documentate the three methods below /** * * @param {*} language * @param {*} folder * @param {*} altname * @param {*} query * @returns */ genshin.addAltName = function (language, folder, altname, query) { const options = new Options( false, // dumpResult true, // matchNames false, // matchAltNames false, // matchAliases false, // matchCategories false, // verboseCategories [language], // queryLanguages ); const filename = retrieveData(query, folder, options, true); if (filename) return altnames.addAltName(language, folder, altname, filename); else return false; } genshin.removeAltNames = altnames.removeAltNames; genshin.setAltNameLimits = altnames.setLimit; //Class Options will serve as a template for the library's options. genshin.Options = Options; genshin.addData = addData; module.exports = genshin;