@the-convocation/venat-module-xiv-market
Advanced tools
Comparing version 0.1.7 to 0.2.0
@@ -6,2 +6,8 @@ # Change Log | ||
# [0.2.0](https://github.com/the-convocation/venat/compare/v0.1.7...v0.2.0) (2022-05-17) | ||
### Features | ||
* add lang parameter on market command ([#59](https://github.com/the-convocation/venat/issues/59)) ([e4518af](https://github.com/the-convocation/venat/commit/e4518afc1a11a4e081dcfed47aecbc8d060c0d03)) | ||
## [0.1.7](https://github.com/the-convocation/venat/compare/v0.1.6...v0.1.7) (2022-05-16) | ||
@@ -8,0 +14,0 @@ |
@@ -25,3 +25,3 @@ "use strict"; | ||
const table_1 = require("table"); | ||
function buildTextTable(listings, worldName) { | ||
function buildTextTable(listings, worldName, startIdx, endIdx) { | ||
return (0, table_1.table)([ | ||
@@ -31,3 +31,3 @@ ['HQ', 'Unit Price', 'Quantity', 'Total', 'World'], | ||
.sort((a, b) => a.pricePerUnit - b.pricePerUnit) | ||
.slice(0, 10) | ||
.slice(startIdx, endIdx) | ||
.map((l) => [ | ||
@@ -45,4 +45,4 @@ l.hq ? 'Yes' : 'No', | ||
async handler(dto) { | ||
const getMarketInfoPartial = (0, listings_1.getMarketInfoByName)(xivapi_1.getItemIdByName, universalis_1.getMarketInfo, this.logger.error); | ||
const marketInfo = await getMarketInfoPartial(dto.item, dto.server); | ||
const getMarketInfoPartial = (0, listings_1.getMarketInfoByName)(xivapi_1.getItemIdByName, universalis_1.getMarketInfo, this.logger.error.bind(this.logger)); | ||
const marketInfo = await getMarketInfoPartial(dto.item, dto.server, dto.lang); | ||
if (typeof marketInfo === 'string') { | ||
@@ -52,5 +52,7 @@ return { content: marketInfo }; | ||
const { lastUploadTime, listings, worldName, dcName, itemName } = marketInfo; | ||
const startIdx = 0; | ||
const endIdx = 10; | ||
const listingsEmbed = new discord_js_1.MessageEmbed() | ||
.setTitle(`Cheapest listings for ${itemName} on ${dcName ?? worldName}`) | ||
.setDescription('```' + buildTextTable(listings, worldName) + '```') | ||
.setDescription('```' + buildTextTable(listings, worldName, startIdx, endIdx) + '```') | ||
.setColor('#a58947') | ||
@@ -57,0 +59,0 @@ .setFooter({ |
import { LookupResult } from '@the-convocation/venat-core'; | ||
import { UniversalisMarketInfo } from './universalis'; | ||
import { XIVAPIItem } from './xivapi'; | ||
export interface MarketListing { | ||
import { XIVAPIItem, XIVAPILanguage } from './xivapi'; | ||
export interface ItemMarketListing { | ||
pricePerUnit: number; | ||
@@ -11,3 +11,3 @@ quantity: number; | ||
} | ||
export interface MarketInfo { | ||
export interface ItemMarketInfo { | ||
itemId: number; | ||
@@ -18,4 +18,13 @@ itemName: string; | ||
lastUploadTime: number; | ||
listings: MarketListing[]; | ||
listings: ItemMarketListing[]; | ||
} | ||
export declare function getMarketInfoByName(getItemIdByName: (itemName: string) => Promise<LookupResult<XIVAPIItem>>, getMarketInfo: (itemId: number, server: string) => Promise<LookupResult<UniversalisMarketInfo>>, logError: (message?: string, stack?: string) => void): (itemName: string, server: string) => Promise<MarketInfo | string>; | ||
export declare type GetItemInfoByName = (itemName: string, lang: XIVAPILanguage) => Promise<LookupResult<XIVAPIItem>>; | ||
export declare type GetItemMarketInfo = (itemId: number, server: string) => Promise<LookupResult<UniversalisMarketInfo>>; | ||
export declare type LogError = (message?: string, stack?: string) => void; | ||
export declare enum Language { | ||
English = 0, | ||
Japanese = 1, | ||
French = 2, | ||
German = 3 | ||
} | ||
export declare function getMarketInfoByName(getItemInfoByName: GetItemInfoByName, getMarketInfo: GetItemMarketInfo, logError: LogError): (itemName: string, server: string, lang: Language) => Promise<ItemMarketInfo | string>; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getMarketInfoByName = void 0; | ||
function getMarketInfoByName(getItemIdByName, getMarketInfo, logError) { | ||
return async (itemName, server) => { | ||
const itemLookup = await getItemIdByName(itemName); | ||
exports.getMarketInfoByName = exports.Language = void 0; | ||
const xivapi_1 = require("./xivapi"); | ||
var Language; | ||
(function (Language) { | ||
Language[Language["English"] = 0] = "English"; | ||
Language[Language["Japanese"] = 1] = "Japanese"; | ||
Language[Language["French"] = 2] = "French"; | ||
Language[Language["German"] = 3] = "German"; | ||
})(Language = exports.Language || (exports.Language = {})); | ||
const xivapiLangMap = new Map([ | ||
[Language.English, xivapi_1.XIVAPILanguage.EN], | ||
[Language.Japanese, xivapi_1.XIVAPILanguage.JA], | ||
[Language.German, xivapi_1.XIVAPILanguage.DE], | ||
[Language.French, xivapi_1.XIVAPILanguage.FR], | ||
]); | ||
function langToXivapi(lang) { | ||
const xivapiLang = xivapiLangMap.get(lang); | ||
if (xivapiLang == null) { | ||
throw new Error(`The language code "${lang}" could not be converted into a Language.`); | ||
} | ||
return xivapiLang; | ||
} | ||
function getMarketInfoByName(getItemInfoByName, getMarketInfo, logError) { | ||
return async (itemName, server, lang) => { | ||
let xivapiLang; | ||
try { | ||
xivapiLang = langToXivapi(lang); | ||
} | ||
catch (err) { | ||
if (!(err instanceof Error)) { | ||
throw err; | ||
} | ||
logError(err.message, err.stack); | ||
xivapiLang = xivapi_1.XIVAPILanguage.EN; | ||
} | ||
const itemLookup = await getItemInfoByName(itemName, xivapiLang); | ||
if (!itemLookup.success) { | ||
logError(itemLookup.err.message, itemLookup.err.stack); | ||
return 'Failed to access XIVAPI; please try again later.'; | ||
return 'The item could not be found; please check your item name spelling and try again.'; | ||
} | ||
if (!itemLookup.success) { | ||
return 'The item could not be found; please check your spelling and try again.'; | ||
const item = itemLookup.value; | ||
const invalidItemSearchCategory = 0; | ||
if (item.ItemSearchCategory.ID == null || | ||
item.ItemSearchCategory.ID == invalidItemSearchCategory) { | ||
return 'The requested item is not marketable.'; | ||
} | ||
const item = itemLookup.value; | ||
const marketLookup = await getMarketInfo(item.ID, server); | ||
if (!marketLookup.success) { | ||
logError(marketLookup.err.message, marketLookup.err.stack); | ||
return 'The item could not be found; please check your spelling of the server and try again.'; | ||
return 'The item could not be found on the market; please check your server spelling and try again.'; | ||
} | ||
if (!marketLookup.success) { | ||
return 'The item could not be found; please check your spelling and try again.'; | ||
} | ||
return { | ||
@@ -24,0 +55,0 @@ ...marketLookup.value, |
@@ -5,2 +5,5 @@ import { LookupResult } from '@the-convocation/venat-core'; | ||
Name: string; | ||
ItemSearchCategory: { | ||
ID: number | null; | ||
}; | ||
} | ||
@@ -10,2 +13,8 @@ export interface XIVAPISearchResponse { | ||
} | ||
export declare function getItemIdByName(name: string): Promise<LookupResult<XIVAPIItem>>; | ||
export declare enum XIVAPILanguage { | ||
EN = "en", | ||
JA = "ja", | ||
DE = "de", | ||
FR = "fr" | ||
} | ||
export declare function getItemIdByName(name: string, lang: XIVAPILanguage): Promise<LookupResult<XIVAPIItem>>; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getItemIdByName = void 0; | ||
exports.getItemIdByName = exports.XIVAPILanguage = void 0; | ||
const axios_1 = require("axios"); | ||
async function getItemIdByName(name) { | ||
var XIVAPILanguage; | ||
(function (XIVAPILanguage) { | ||
XIVAPILanguage["EN"] = "en"; | ||
XIVAPILanguage["JA"] = "ja"; | ||
XIVAPILanguage["DE"] = "de"; | ||
XIVAPILanguage["FR"] = "fr"; | ||
})(XIVAPILanguage = exports.XIVAPILanguage || (exports.XIVAPILanguage = {})); | ||
async function getItemIdByName(name, lang) { | ||
let res; | ||
try { | ||
res = await axios_1.default.get(`https://xivapi.com/search?string=${name}&filters=ItemSearchCategory.ID>8&columns=ID,Name`); | ||
res = await axios_1.default.get(`https://xivapi.com/search?string=${encodeURIComponent(name)}&language=${lang}&indexes=Item&columns=ID,Name,ItemSearchCategory.ID`); | ||
} | ||
@@ -10,0 +17,0 @@ catch (err) { |
@@ -0,4 +1,6 @@ | ||
import { Language } from '../data/listings'; | ||
export declare class MarketDto { | ||
item: string; | ||
lang: Language; | ||
server: string; | ||
} |
@@ -16,4 +16,12 @@ "use strict"; | ||
const venat_core_1 = require("@the-convocation/venat-core"); | ||
const listings_1 = require("../data/listings"); | ||
const langMap = new Map([ | ||
['English', listings_1.Language.English], | ||
['日本語', listings_1.Language.Japanese], | ||
['Deutsch', listings_1.Language.German], | ||
['Français', listings_1.Language.French], | ||
]); | ||
class MarketDto { | ||
item; | ||
lang; | ||
server; | ||
@@ -31,2 +39,12 @@ } | ||
__decorate([ | ||
(0, core_1.Choice)(langMap), | ||
(0, core_1.Param)({ | ||
description: 'The language of the item name to search for.', | ||
name: 'language', | ||
required: true, | ||
type: core_1.ParamType.INTEGER, | ||
}), | ||
__metadata("design:type", Number) | ||
], MarketDto.prototype, "lang", void 0); | ||
__decorate([ | ||
(0, class_transformer_1.Transform)(venat_core_1.cleanText), | ||
@@ -33,0 +51,0 @@ (0, core_1.Param)({ |
{ | ||
"name": "@the-convocation/venat-module-xiv-market", | ||
"version": "0.1.7", | ||
"version": "0.2.0", | ||
"packageManager": "yarn@3.2.1", | ||
@@ -11,3 +11,3 @@ "main": "dist/src/module.js", | ||
"dependencies": { | ||
"@the-convocation/venat-core": "^0.1.7" | ||
"@the-convocation/venat-core": "^0.2.0" | ||
}, | ||
@@ -17,3 +17,3 @@ "publishConfig": { | ||
}, | ||
"gitHead": "ed5d2c3f91ee44b382ee41aac4a774cfcefc5c62" | ||
"gitHead": "dbbdce66a6c25827cd786e833028f9c69fd267cf" | ||
} |
@@ -13,6 +13,11 @@ import { TransformPipe } from '@discord-nestjs/common'; | ||
import { MarketDto } from '../dto/market.dto'; | ||
import { getMarketInfoByName, MarketListing } from '../data/listings'; | ||
import { getMarketInfoByName, ItemMarketListing } from '../data/listings'; | ||
import { table } from 'table'; | ||
function buildTextTable(listings: MarketListing[], worldName?: string): string { | ||
function buildTextTable( | ||
listings: ItemMarketListing[], | ||
worldName: string | null | undefined, | ||
startIdx: number, | ||
endIdx: number, | ||
): string { | ||
return table([ | ||
@@ -22,3 +27,3 @@ ['HQ', 'Unit Price', 'Quantity', 'Total', 'World'], | ||
.sort((a, b) => a.pricePerUnit - b.pricePerUnit) | ||
.slice(0, 10) | ||
.slice(startIdx, endIdx) | ||
.map((l) => [ | ||
@@ -48,5 +53,9 @@ l.hq ? 'Yes' : 'No', | ||
getMarketInfo, | ||
this.logger.error, | ||
this.logger.error.bind(this.logger), | ||
); | ||
const marketInfo = await getMarketInfoPartial(dto.item, dto.server); | ||
const marketInfo = await getMarketInfoPartial( | ||
dto.item, | ||
dto.server, | ||
dto.lang, | ||
); | ||
if (typeof marketInfo === 'string') { | ||
@@ -58,5 +67,11 @@ return { content: marketInfo }; | ||
marketInfo; | ||
const startIdx = 0; | ||
const endIdx = 10; | ||
const listingsEmbed = new MessageEmbed() | ||
.setTitle(`Cheapest listings for ${itemName} on ${dcName ?? worldName}`) | ||
.setDescription('```' + buildTextTable(listings, worldName) + '```') | ||
.setDescription( | ||
'```' + buildTextTable(listings, worldName, startIdx, endIdx) + '```', | ||
) | ||
.setColor('#a58947') | ||
@@ -63,0 +78,0 @@ .setFooter({ |
import { LookupResult } from '@the-convocation/venat-core'; | ||
import { UniversalisMarketInfo } from './universalis'; | ||
import { XIVAPIItem } from './xivapi'; | ||
import { XIVAPIItem, XIVAPILanguage } from './xivapi'; | ||
export interface MarketListing { | ||
export interface ItemMarketListing { | ||
pricePerUnit: number; | ||
@@ -13,3 +13,3 @@ quantity: number; | ||
export interface MarketInfo { | ||
export interface ItemMarketInfo { | ||
itemId: number; | ||
@@ -20,38 +20,97 @@ itemName: string; | ||
lastUploadTime: number; | ||
listings: MarketListing[]; | ||
listings: ItemMarketListing[]; | ||
} | ||
export type GetItemInfoByName = ( | ||
itemName: string, | ||
lang: XIVAPILanguage, | ||
) => Promise<LookupResult<XIVAPIItem>>; | ||
export type GetItemMarketInfo = ( | ||
itemId: number, | ||
server: string, | ||
) => Promise<LookupResult<UniversalisMarketInfo>>; | ||
export type LogError = (message?: string, stack?: string) => void; | ||
export enum Language { | ||
English, | ||
Japanese, | ||
French, | ||
German, | ||
} | ||
const xivapiLangMap = new Map<Language, XIVAPILanguage>([ | ||
[Language.English, XIVAPILanguage.EN], | ||
[Language.Japanese, XIVAPILanguage.JA], | ||
[Language.German, XIVAPILanguage.DE], | ||
[Language.French, XIVAPILanguage.FR], | ||
]); | ||
function langToXivapi(lang: Language): XIVAPILanguage { | ||
const xivapiLang = xivapiLangMap.get(lang); | ||
if (xivapiLang == null) { | ||
throw new Error( | ||
`The language code "${lang}" could not be converted into a Language.`, | ||
); | ||
} | ||
return xivapiLang; | ||
} | ||
/** | ||
* Gets an item's market info using its name and a game server. Requires provider functions for I/O. | ||
* @param getItemInfoByName An async function that returns an item's information by its name and language. | ||
* @param getMarketInfo An async function that returns an item's market info by its item ID and a game server. | ||
* @param logError An error-logging function. | ||
* @returns An async function that returns an item's market info by its name, its language, and a game server. | ||
* If something goes wrong, an error message is returned describing the problem. | ||
*/ | ||
export function getMarketInfoByName( | ||
getItemIdByName: (itemName: string) => Promise<LookupResult<XIVAPIItem>>, | ||
getMarketInfo: ( | ||
itemId: number, | ||
server: string, | ||
) => Promise<LookupResult<UniversalisMarketInfo>>, | ||
logError: (message?: string, stack?: string) => void, | ||
): (itemName: string, server: string) => Promise<MarketInfo | string> { | ||
getItemInfoByName: GetItemInfoByName, | ||
getMarketInfo: GetItemMarketInfo, | ||
logError: LogError, | ||
): ( | ||
itemName: string, | ||
server: string, | ||
lang: Language, | ||
) => Promise<ItemMarketInfo | string> { | ||
return async ( | ||
itemName: string, | ||
server: string, | ||
): Promise<MarketInfo | string> => { | ||
const itemLookup = await getItemIdByName(itemName); | ||
lang: Language, | ||
): Promise<ItemMarketInfo | string> => { | ||
let xivapiLang: XIVAPILanguage; | ||
try { | ||
xivapiLang = langToXivapi(lang); | ||
} catch (err) { | ||
if (!(err instanceof Error)) { | ||
throw err; | ||
} | ||
logError(err.message, err.stack); | ||
xivapiLang = XIVAPILanguage.EN; | ||
} | ||
const itemLookup = await getItemInfoByName(itemName, xivapiLang); | ||
if (!itemLookup.success) { | ||
logError(itemLookup.err.message, itemLookup.err.stack); | ||
return 'Failed to access XIVAPI; please try again later.'; | ||
return 'The item could not be found; please check your item name spelling and try again.'; | ||
} | ||
if (!itemLookup.success) { | ||
return 'The item could not be found; please check your spelling and try again.'; | ||
const item = itemLookup.value; | ||
const invalidItemSearchCategory = 0; | ||
if ( | ||
item.ItemSearchCategory.ID == null || | ||
item.ItemSearchCategory.ID == invalidItemSearchCategory | ||
) { | ||
return 'The requested item is not marketable.'; | ||
} | ||
const item = itemLookup.value; | ||
const marketLookup = await getMarketInfo(item.ID, server); | ||
if (!marketLookup.success) { | ||
logError(marketLookup.err.message, marketLookup.err.stack); | ||
return 'The item could not be found; please check your spelling of the server and try again.'; | ||
return 'The item could not be found on the market; please check your server spelling and try again.'; | ||
} | ||
if (!marketLookup.success) { | ||
return 'The item could not be found; please check your spelling and try again.'; | ||
} | ||
return { | ||
@@ -58,0 +117,0 @@ ...marketLookup.value, |
@@ -7,2 +7,5 @@ import axios, { AxiosResponse } from 'axios'; | ||
Name: string; | ||
ItemSearchCategory: { | ||
ID: number | null; | ||
}; | ||
} | ||
@@ -14,4 +17,12 @@ | ||
export enum XIVAPILanguage { | ||
EN = 'en', | ||
JA = 'ja', | ||
DE = 'de', | ||
FR = 'fr', | ||
} | ||
export async function getItemIdByName( | ||
name: string, | ||
lang: XIVAPILanguage, | ||
): Promise<LookupResult<XIVAPIItem>> { | ||
@@ -21,3 +32,5 @@ let res: AxiosResponse<XIVAPISearchResponse, any>; | ||
res = await axios.get<XIVAPISearchResponse>( | ||
`https://xivapi.com/search?string=${name}&filters=ItemSearchCategory.ID>8&columns=ID,Name`, | ||
`https://xivapi.com/search?string=${encodeURIComponent( | ||
name, | ||
)}&language=${lang}&indexes=Item&columns=ID,Name,ItemSearchCategory.ID`, | ||
); | ||
@@ -24,0 +37,0 @@ } catch (err) { |
@@ -1,5 +0,13 @@ | ||
import { Param } from '@discord-nestjs/core'; | ||
import { Choice, Param, ParamType } from '@discord-nestjs/core'; | ||
import { Transform } from 'class-transformer'; | ||
import { cleanText } from '@the-convocation/venat-core'; | ||
import { Language } from '../data/listings'; | ||
const langMap = new Map<string, Language>([ | ||
['English', Language.English], | ||
['日本語', Language.Japanese], | ||
['Deutsch', Language.German], | ||
['Français', Language.French], | ||
]); | ||
export class MarketDto { | ||
@@ -14,2 +22,11 @@ @Transform(cleanText) | ||
@Choice(langMap) | ||
@Param({ | ||
description: 'The language of the item name to search for.', | ||
name: 'language', | ||
required: true, | ||
type: ParamType.INTEGER, | ||
}) | ||
public lang!: Language; | ||
@Transform(cleanText) | ||
@@ -16,0 +33,0 @@ @Param({ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
244506
674
+ Added@the-convocation/venat-core@0.2.0(transitive)
- Removed@the-convocation/venat-core@0.1.7(transitive)