|
|
@ -1,10 +1,8 @@ |
|
|
|
import { DataGatheringService } from '@ghostfolio/api/services/data-gathering.service'; |
|
|
|
import { DataProviderService } from '@ghostfolio/api/services/data-provider.service'; |
|
|
|
import { GhostfolioScraperApiService } from '@ghostfolio/api/services/data-provider/ghostfolio-scraper-api/ghostfolio-scraper-api.service'; |
|
|
|
import { convertFromYahooSymbol } from '@ghostfolio/api/services/data-provider/yahoo-finance/yahoo-finance.service'; |
|
|
|
import { Injectable } from '@nestjs/common'; |
|
|
|
import { Currency } from '@prisma/client'; |
|
|
|
import * as bent from 'bent'; |
|
|
|
import { Currency, DataSource } from '@prisma/client'; |
|
|
|
|
|
|
|
import { LookupItem } from './interfaces/lookup-item.interface'; |
|
|
|
import { SymbolItem } from './interfaces/symbol-item.interface'; |
|
|
@ -27,62 +25,31 @@ export class SymbolService { |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
public async lookup(aQuery = ''): Promise<LookupItem[]> { |
|
|
|
public async lookup(aQuery = ''): Promise<{ items: LookupItem[] }> { |
|
|
|
const query = aQuery.toLowerCase(); |
|
|
|
const results: LookupItem[] = []; |
|
|
|
const results: { items: LookupItem[] } = { items: [] }; |
|
|
|
|
|
|
|
if (!query) { |
|
|
|
return results; |
|
|
|
} |
|
|
|
|
|
|
|
const get = bent( |
|
|
|
`https://query1.finance.yahoo.com/v1/finance/search?q=${query}&lang=en-US®ion=US"esCount=8&newsCount=0&enableFuzzyQuery=false"esQueryId=tss_match_phrase_query&multiQuoteQueryId=multi_quote_single_token_query&newsQueryId=news_cie_vespa&enableCb=true&enableNavLinks=false&enableEnhancedTrivialQuery=true`, |
|
|
|
'GET', |
|
|
|
'json', |
|
|
|
200 |
|
|
|
); |
|
|
|
|
|
|
|
// Add custom symbols
|
|
|
|
const scraperConfigurations = await this.ghostfolioScraperApiService.getScraperConfigurations(); |
|
|
|
scraperConfigurations.forEach((scraperConfiguration) => { |
|
|
|
if (scraperConfiguration.name.toLowerCase().startsWith(query)) { |
|
|
|
results.push({ |
|
|
|
name: scraperConfiguration.name, |
|
|
|
symbol: scraperConfiguration.symbol |
|
|
|
}); |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
try { |
|
|
|
const { quotes } = await get(); |
|
|
|
|
|
|
|
const searchResult = quotes |
|
|
|
.filter(({ isYahooFinance }) => { |
|
|
|
return isYahooFinance; |
|
|
|
}) |
|
|
|
.filter(({ quoteType }) => { |
|
|
|
return ( |
|
|
|
quoteType === 'CRYPTOCURRENCY' || |
|
|
|
quoteType === 'EQUITY' || |
|
|
|
quoteType === 'ETF' |
|
|
|
); |
|
|
|
}) |
|
|
|
.filter(({ quoteType, symbol }) => { |
|
|
|
if (quoteType === 'CRYPTOCURRENCY') { |
|
|
|
// Only allow cryptocurrencies in USD
|
|
|
|
return symbol.includes('USD'); |
|
|
|
} |
|
|
|
const { items } = await this.dataProviderService.search(aQuery); |
|
|
|
results.items = items; |
|
|
|
|
|
|
|
// Add custom symbols
|
|
|
|
const scraperConfigurations = await this.ghostfolioScraperApiService.getScraperConfigurations(); |
|
|
|
scraperConfigurations.forEach((scraperConfiguration) => { |
|
|
|
if (scraperConfiguration.name.toLowerCase().startsWith(query)) { |
|
|
|
results.items.push({ |
|
|
|
dataSource: DataSource.GHOSTFOLIO, |
|
|
|
name: scraperConfiguration.name, |
|
|
|
symbol: scraperConfiguration.symbol |
|
|
|
}); |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
return true; |
|
|
|
}) |
|
|
|
.map(({ longname, shortname, symbol }) => { |
|
|
|
return { |
|
|
|
name: longname || shortname, |
|
|
|
symbol: convertFromYahooSymbol(symbol) |
|
|
|
}; |
|
|
|
}); |
|
|
|
|
|
|
|
return results.concat(searchResult); |
|
|
|
return results; |
|
|
|
} catch (error) { |
|
|
|
console.error(error); |
|
|
|
|
|
|
|