|
@ -12,6 +12,7 @@ import { |
|
|
MarketState |
|
|
MarketState |
|
|
} from '../../interfaces/interfaces'; |
|
|
} from '../../interfaces/interfaces'; |
|
|
import { PrismaService } from '../../prisma.service'; |
|
|
import { PrismaService } from '../../prisma.service'; |
|
|
|
|
|
import { ScraperConfig } from './interfaces/scraper-config.interface'; |
|
|
|
|
|
|
|
|
@Injectable() |
|
|
@Injectable() |
|
|
export class GhostfolioScraperApiService implements DataProviderInterface { |
|
|
export class GhostfolioScraperApiService implements DataProviderInterface { |
|
@ -29,7 +30,7 @@ export class GhostfolioScraperApiService implements DataProviderInterface { |
|
|
try { |
|
|
try { |
|
|
const symbol = aSymbols[0]; |
|
|
const symbol = aSymbols[0]; |
|
|
|
|
|
|
|
|
const scraperConfig = await this.getScraperConfig(symbol); |
|
|
const scraperConfig = await this.getScraperConfigurationBySymbol(symbol); |
|
|
|
|
|
|
|
|
const { marketPrice } = await this.prisma.marketData.findFirst({ |
|
|
const { marketPrice } = await this.prisma.marketData.findFirst({ |
|
|
orderBy: { |
|
|
orderBy: { |
|
@ -70,15 +71,17 @@ export class GhostfolioScraperApiService implements DataProviderInterface { |
|
|
try { |
|
|
try { |
|
|
const symbol = aSymbols[0]; |
|
|
const symbol = aSymbols[0]; |
|
|
|
|
|
|
|
|
const scraperConfig = await this.getScraperConfig(symbol); |
|
|
const scraperConfiguration = await this.getScraperConfigurationBySymbol( |
|
|
|
|
|
symbol |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
const get = bent(scraperConfig?.url, 'GET', 'string', 200, {}); |
|
|
const get = bent(scraperConfiguration?.url, 'GET', 'string', 200, {}); |
|
|
|
|
|
|
|
|
const html = await get(); |
|
|
const html = await get(); |
|
|
const $ = cheerio.load(html); |
|
|
const $ = cheerio.load(html); |
|
|
|
|
|
|
|
|
const value = this.extractNumberFromString( |
|
|
const value = this.extractNumberFromString( |
|
|
$(scraperConfig?.selector).text() |
|
|
$(scraperConfiguration?.selector).text() |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
return { |
|
|
return { |
|
@ -95,18 +98,7 @@ export class GhostfolioScraperApiService implements DataProviderInterface { |
|
|
return {}; |
|
|
return {}; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private extractNumberFromString(aString: string): number { |
|
|
public async getScraperConfigurations(): Promise<ScraperConfig[]> { |
|
|
try { |
|
|
|
|
|
const [numberString] = aString.match( |
|
|
|
|
|
GhostfolioScraperApiService.NUMERIC_REGEXP |
|
|
|
|
|
); |
|
|
|
|
|
return parseFloat(numberString.trim()); |
|
|
|
|
|
} catch { |
|
|
|
|
|
return undefined; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private async getScraperConfig(aSymbol: string) { |
|
|
|
|
|
try { |
|
|
try { |
|
|
const { |
|
|
const { |
|
|
value: scraperConfigString |
|
|
value: scraperConfigString |
|
@ -117,11 +109,27 @@ export class GhostfolioScraperApiService implements DataProviderInterface { |
|
|
where: { key: 'SCRAPER_CONFIG' } |
|
|
where: { key: 'SCRAPER_CONFIG' } |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
return JSON.parse(scraperConfigString).find((item) => { |
|
|
return JSON.parse(scraperConfigString); |
|
|
return item.symbol === aSymbol; |
|
|
|
|
|
}); |
|
|
|
|
|
} catch {} |
|
|
} catch {} |
|
|
|
|
|
|
|
|
return {}; |
|
|
return []; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private extractNumberFromString(aString: string): number { |
|
|
|
|
|
try { |
|
|
|
|
|
const [numberString] = aString.match( |
|
|
|
|
|
GhostfolioScraperApiService.NUMERIC_REGEXP |
|
|
|
|
|
); |
|
|
|
|
|
return parseFloat(numberString.trim()); |
|
|
|
|
|
} catch { |
|
|
|
|
|
return undefined; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private async getScraperConfigurationBySymbol(aSymbol: string) { |
|
|
|
|
|
const scraperConfigurations = await this.getScraperConfigurations(); |
|
|
|
|
|
return scraperConfigurations.find((scraperConfiguration) => { |
|
|
|
|
|
return scraperConfiguration.symbol === aSymbol; |
|
|
|
|
|
}); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|