diff --git a/packages/backend/src/auth/google/googleAuth.controller.ts b/packages/backend/src/auth/google/googleAuth.controller.ts index 73f39449..1d460748 100644 --- a/packages/backend/src/auth/google/googleAuth.controller.ts +++ b/packages/backend/src/auth/google/googleAuth.controller.ts @@ -21,7 +21,7 @@ export class GoogleAuthController { @Get('/redirect') @UseGuards(GoogleAuthGuard) async handleRedirect(@Res() response: Response) { - response.redirect('http://localhost:5173'); + response.redirect('/'); } @ApiOperation({ diff --git a/packages/backend/src/scraper/openapi/api/openapiDetailData.api.ts b/packages/backend/src/scraper/openapi/api/openapiDetailData.api.ts index 5f0168bd..118a0b95 100644 --- a/packages/backend/src/scraper/openapi/api/openapiDetailData.api.ts +++ b/packages/backend/src/scraper/openapi/api/openapiDetailData.api.ts @@ -88,6 +88,13 @@ export class OpenapiDetailData extends Openapi { // return result; //} + protected query(stockId: string, code: 'J' = 'J') { + return { + fid_cond_mrkt_div_code: code, + fid_input_iscd: stockId, + }; + } + private async save(saveEntity: StockDetail) { const entity = StockDetail; const manager = this.datasource.manager; @@ -102,11 +109,4 @@ export class OpenapiDetailData extends Openapi { ) .execute(); } - - protected query(stockId: string, code: 'J' = 'J') { - return { - fid_cond_mrkt_div_code: code, - fid_input_iscd: stockId, - }; - } } diff --git a/packages/backend/src/scraper/openapi/api/openapiFluctuationData.api.ts b/packages/backend/src/scraper/openapi/api/openapiFluctuationData.api.ts index 39626588..804b558a 100644 --- a/packages/backend/src/scraper/openapi/api/openapiFluctuationData.api.ts +++ b/packages/backend/src/scraper/openapi/api/openapiFluctuationData.api.ts @@ -10,11 +10,14 @@ import { import { TR_IDS } from '@/scraper/openapi/type/openapiUtil.type'; import { getOpenApi } from '@/scraper/openapi/util/openapiUtil.api'; import { FluctuationRankStock } from '@/stock/domain/FluctuationRankStock.entity'; +import { StockLiveData } from '@/stock/domain/stockLiveData.entity'; +import { Stock } from '@/stock/domain/stock.entity'; @Injectable() export class OpenapiFluctuationData { - private readonly fluctuationUrl: string = + private readonly fluctuationUrl = '/uapi/domestic-stock/v1/ranking/fluctuation'; + private readonly liveUrl = '/uapi/domestic-stock/v1/quotations/inquire-price'; constructor( private readonly openApiToken: OpenapiTokenApi, private readonly datasource: DataSource, @@ -32,12 +35,14 @@ export class OpenapiFluctuationData { async getDecreaseRankStocks(count = 5) { try { if (count === 0) return; + const result = await this.getFluctuationRankApiStocks(false); + const liveResult = await this.getFluctuationRankApiLive(result); await this.datasource.transaction(async (manager) => { - const result = await this.getFluctuationRankApiStocks(false); await this.datasource.manager.delete(FluctuationRankStock, { isRising: false, }); await this.saveFluctuationRankStocks(result, manager); + await this.saveLiveData(liveResult, manager); this.logger.info('decrease rank stocks updated'); }); } catch (error) { @@ -49,12 +54,14 @@ export class OpenapiFluctuationData { async getIncreaseRankStocks(count = 5) { try { if (count === 0) return; + const result = await this.getFluctuationRankApiStocks(true); + const liveResult = await this.getFluctuationRankApiLive(result); await this.datasource.transaction(async (manager) => { - const result = await this.getFluctuationRankApiStocks(true); await this.datasource.manager.delete(FluctuationRankStock, { isRising: true, }); await this.saveFluctuationRankStocks(result, manager); + await this.saveLiveData(liveResult, manager); this.logger.info('increase rank stocks updated'); }); } catch (error) { @@ -76,6 +83,20 @@ export class OpenapiFluctuationData { .execute(); } + private async saveLiveData(data: StockLiveData[], manager: EntityManager) { + return await manager + .getRepository(StockLiveData) + .createQueryBuilder() + .insert() + .into(StockLiveData) + .values(data) + .orUpdate( + ['current_price', 'change_rate', 'volume', 'high', 'low', 'open'], + ['stock_id'], + ) + .execute(); + } + private async getFluctuationRankApiStocks(isRising: boolean) { const query = isRising ? INCREASE_STOCK_QUERY : DECREASE_STOCK_QUERY; const result = await getOpenApi( @@ -85,11 +106,50 @@ export class OpenapiFluctuationData { TR_IDS.FLUCTUATION_DATA, ); - return result.output.map((result: Record) => ({ - rank: result.data_rank, - fluctuationRate: result.prdy_ctrt, - stock: { id: result.stck_shrn_iscd }, - isRising, - })); + return result.output.slice(0, 20).map((result: Record) => { + return { + rank: result.data_rank, + fluctuationRate: result.prdy_ctrt, + stock: { id: result.stck_shrn_iscd }, + isRising, + }; + }); + } + + private async getFluctuationRankApiLive(data: FluctuationRankStock[]) { + const result: StockLiveData[] = []; + for (let i = 0; i < 20; ++i) { + if (i >= data.length) break; + else if (i == 10) + await new Promise((resolve) => setTimeout(resolve, 1000)); + const stockId = data[i].stock.id; + const stockData = await getOpenApi( + this.liveUrl, + (await this.openApiToken.configs())[0], + { + fid_cond_mrkt_div_code: 'J', + fid_input_iscd: stockId, + }, + TR_IDS.LIVE_DATA, + ); + result.push(this.convertToStockLiveData(stockData.output, stockId)); + } + return result; + } + + private convertToStockLiveData( + stockData: Record, + stockId: string, + ): StockLiveData { + const stockLiveData = new StockLiveData(); + stockLiveData.stock = { id: stockId } as Stock; + stockLiveData.currentPrice = parseFloat(stockData.stck_prpr); + stockLiveData.changeRate = parseFloat(stockData.prdy_ctrt); + stockLiveData.volume = parseInt(stockData.acml_vol); + stockLiveData.high = parseFloat(stockData.stck_hgpr); + stockLiveData.low = parseFloat(stockData.stck_lwpr); + stockLiveData.open = parseFloat(stockData.stck_oprc); + stockLiveData.updatedAt = new Date(); + return stockLiveData; } }