-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathindex.js
More file actions
173 lines (156 loc) · 6.41 KB
/
Copy pathindex.js
File metadata and controls
173 lines (156 loc) · 6.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
import { readdir, unlink, rmdir } from 'node:fs/promises';
import { existsSync as exists } from 'node:fs';
import { join } from 'node:path';
import md from 'node-md-config';
import promiseTimeout from './lib/promiseTimeout.js';
import Settings from './lib/Settings.js';
import Creator from './lib/AttachmentCreator.js';
import { normalizePriceCheckRanks } from './lib/priceCheckOptions.js';
import { MarketFetcherV2 } from './lib/market/v2/index.js';
export default class PriceCheckQuerier {
#useV2 = false;
/**
* Creates an instance representing a WarframeNexusStats data object
* @constructor
*/
constructor({ logger = console, marketCache = undefined, skipMarket = false }) {
this.settings = new Settings();
this.logger = logger;
this.skipMarket = skipMarket;
this.marketFetcher = marketCache;
if (!skipMarket) {
try {
this.#useV2 = process.env.WARFRAME_MARKET_API_VERSION === 'v2';
/**
* Fetch market data
* @type {MarketFetcher|MarketFetcherV2}
*/
if (this.#useV2) {
this.logger.debug('Using Warframe Market API v2');
this.marketFetcher = new MarketFetcherV2({ logger });
this.apiVersion = 'v2';
} else {
this.logger.info('Using Warframe Market API v1');
this.logger.warn('Api v1 is deprecated and impossible to use');
this.marketFetcher = new MarketFetcherV2({ logger });
this.apiVersion = 'v2';
}
} catch (e) {
this.logger.error(`couldn't set up market fetcher: ${e.message}`);
}
}
/**
* Attachment creator for generating attachments
* @type {Creator}
*/
this.creator = new Creator();
}
/**
* Lookup a list of results for a query
* @param {string} query Query to search the nexus-stats database against
* @param {string} [platform='pc'] Platform to query price data for. One of 'pc', 'ps4', 'xb1'
* @param {Object} [options={}] Optional market order filters (rank, ranks, rankLt, etc.)
* @returns {Promise<Array<NexusItem>>} a Promise of an array of Item objects
*/
async priceCheckQuery(query, platform = 'pc', options = {}) {
this.logger.info(`state:\n\tskipMarket: ${this.skipMarket}\n\tquery: ${query}\n\tplatform: ${platform}`);
if (!query) {
throw new Error('This funtcion requires a query to be provided');
}
// eslint-disable-next-line no-param-reassign
platform = this.settings.lookupAlias(platform.toLowerCase());
const ranks = normalizePriceCheckRanks(options);
const { ranks: _ignoredRanks, ...baseOptions } = options;
let attachments = [];
/* istanbul ignore else */
if (this.marketFetcher && !this.skipMarket) {
this.logger.info(`querying market for ${query} on ${platform}`);
try {
const marketPlatform = this.settings.lookupAlias(platform, true);
const rankResults = await Promise.all(
ranks.map(async (rank) => {
const rankOptions = {
...baseOptions,
platform: marketPlatform,
};
if (rank !== undefined) rankOptions.rank = rank;
const marketPromise = this.marketFetcher.queryMarket(query, rankOptions);
return promiseTimeout(this.settings.timeouts.market, marketPromise);
})
);
attachments = rankResults.flat();
} catch (e) {
this.logger.error(`Couldn't process ${query} on warframe.market... time out.`);
}
} else {
this.logger.info('No market fetcher, skipping market');
}
return attachments;
}
/**
* Lookup a list of results for a query
* @param {string} query Query to search the nexus-stats database against
* @param {Object[]} [priorResults] results provided from a prior search
* @param {string} [platform='pc'] Platform to query price data for. One of 'pc', 'ps4', 'xb1'
* @param {Object} [options={}] Optional market order filters (rank, ranks, rankLt, etc.)
* @returns {Promise<string>} a Promise of a string containing the results of the query
*/
async priceCheckQueryString(query, priorResults, platform = 'pc', options = {}) {
const components = priorResults || (await this.priceCheckQuery(query, platform, options));
const tokens = [`[${platform.toUpperCase()}] ${query}`];
components.slice(0, 4).forEach((component) => {
tokens.push(`${md.lineEnd}${component.toString()}`);
});
let componentsToReturnString = `${md.codeMulti}${tokens.join()}${md.blockEnd}`;
componentsToReturnString = components.length > 0 ? componentsToReturnString : this.settings.defaultString;
return componentsToReturnString;
}
/**
* Lookup a list of results for a query
* @param {string} query Query to search the nexus-stats database against
* @param {Object[]} [priorResults] results provided from a prior search
* @param {string} [platform='pc'] Platform to query price data for. One of 'pc', 'ps4', 'xb1'
* @param {Object} [options={}] Optional market order filters (rank, ranks, rankLt, etc.)
* @returns {Promise<Array<Object>>} a Promise of an array of attachment objects
*/
async priceCheckQueryAttachment(query, priorResults, platform = 'pc', options = {}) {
const components = priorResults || (await this.priceCheckQuery(query, platform, options));
const realPlatform = this.settings.lookupAlias(platform);
const attachment = this.creator.attachmentFromComponents(components, query, realPlatform);
return [attachment];
}
/**
* Stop updating caches
*/
async stopUpdating() {
/* istanbul ignore else */
if (!this.skipMarket && this.marketFetcher) {
// v1 API uses marketCache
if (this.marketFetcher.marketCache) {
this.marketFetcher.marketCache.stop();
} else if (typeof this.marketFetcher.stop === 'function') {
// v2 API has stop() method
this.marketFetcher.stop();
}
} else {
this.logger.log('no market fetcher, or skipMarket was true');
}
if (exists(`${global.__basedir}/tmp`)) {
const files = await readdir(`${global.__basedir}/tmp`);
let allSuccess = true;
await Promise.all(
files.map(async (file) => {
try {
await unlink(join(global.__basedir, 'tmp', file));
} catch (e) {
allSuccess = false;
this.logger.debug(`Couldn't delete ${file}`);
}
})
);
if (allSuccess) {
await rmdir(`${global.__basedir}/tmp`);
}
}
}
}