UNPKG

efriend

Version:
169 lines (168 loc) 8.58 kB
/** * 한국투자증권 EFriendExpert API * * @file packages/EFriendExpert/efriends/efriend.ts * @version 0.0.1 * @license GNU General Public License v3.0 * @copyright 2017~2023, EFriendExport Community Team * @author gye hyun james kim <pnuskgh@gmail.com> */ import moment from 'moment'; //--- format : YYYYMMDDHHmmss.SSS ZZ - 20191220172919.083 +0900 import { BaseError, ERROR_CODE } from '../common/error/index.js'; import { EFriend_LIMIT } from './efriend.limit.constant.js'; import { TR_TYPE } from './efriend.type.js'; export class EFriendLimit { limit; constructor() { this.limit = this.initialize([]); } getLimit() { return this.limit; } initialize(secrets) { const today = moment().format('YYYY-MM-DD'); const limit = { user: {}, account: {} }; for (const secret of secrets) { if (today <= secret.periodTo) { const limit_user = { accounts_actual: EFriend_LIMIT.user.accounts_actual, accounts_simulated: EFriend_LIMIT.user.accounts_simulated, ws_api: { session: EFriend_LIMIT.ws_api.session, } }; if (typeof (limit.user[secret.userid]) == 'undefined') { limit.user[secret.userid] = limit_user; } else { if (secret.isActual) { limit.user[secret.userid].accounts_actual = limit.user[secret.userid].accounts_actual - 1; if (limit.user[secret.userid].accounts_actual < 0) { throw new BaseError({ code: ERROR_CODE.NOTALLOWED, data: `${secret.userid} accounts_actual limit is over.` }); } } else { limit.user[secret.userid].accounts_simulated = limit.user[secret.userid].accounts_simulated - 1; if (limit.user[secret.userid].accounts_simulated < 0) { throw new BaseError({ code: ERROR_CODE.NOTALLOWED, data: `${secret.userid} accounts_simulated limit is over.` }); } } } const limit_account = { rest_api: { datetime: moment().format('YYYY-MM-DD HH:mm:ss'), api_per_second_actual: EFriend_LIMIT.rest_api.api_per_second_actual, api_per_second_simulated: EFriend_LIMIT.rest_api.api_per_second_simulated, api_tokenP_datetime: moment().subtract(10, 'minutes'), requests: [] }, ws_api: { notifications: [], registrations: [] } }; limit.account[secret.account] = limit_account; } } this.limit = limit; return limit; } async increaseRestApi(secret, trid) { try { let result = true; const limit = this.limit.account[secret.account]; const count = (secret.isActual) ? EFriend_LIMIT.rest_api.api_per_second_actual : EFriend_LIMIT.rest_api.api_per_second_simulated; limit.rest_api.requests.push(moment().format('YYYY-MM-DD HH:mm:ss.SSS')); limit.rest_api.requests = limit.rest_api.requests.filter(req => moment().subtract(1, 'seconds').format('YYYY-MM-DD HH:mm:ss.SSS') < req); console.log(`REST API --- ${secret.userid}, ${secret.account} :: trid - ${trid}, isActual - ${secret.isActual}, count - ${count}, limit - ${limit.rest_api.requests.length}`); while (count < limit.rest_api.requests.length) { await this.sleep(100); console.log(`REST sleep --- ${secret.userid}, ${secret.account} :: trid - ${trid}, isActual - ${secret.isActual}, count - ${count}, limit - ${limit.rest_api.requests.length}`); limit.rest_api.requests = limit.rest_api.requests.filter(req => moment().subtract(1, 'seconds').format('YYYY-MM-DD HH:mm:ss.SSS') < req); } return result; // // console.log(`--- increaseRestApi : trid - ${trid}, isActual - ${secret.isActual}`, limit.rest_api); // const now = moment().format('YYYY-MM-DD HH:mm:ss'); // if (limit.rest_api.datetime != now) { // limit.rest_api.datetime = now; // limit.rest_api.api_per_second_actual = EFriend_LIMIT.rest_api.api_per_second_actual; // limit.rest_api.api_per_second_simulated = EFriend_LIMIT.rest_api.api_per_second_simulated; // } // if (secret.isActual) { // limit.rest_api.api_per_second_actual = limit.rest_api.api_per_second_actual - 1; // if (limit.rest_api.api_per_second_actual < 0) { // // throw new BaseError({ code: ERROR_CODE.NOTALLOWED, data: `${secret.account} account limit is over.` }); // result = false; // } // } else { // limit.rest_api.api_per_second_simulated = limit.rest_api.api_per_second_simulated - 1; // if (limit.rest_api.api_per_second_simulated < 0) { // // throw new BaseError({ code: ERROR_CODE.NOTALLOWED, data: `${secret.account} account limit is over.` }); // result = false // } // } // const countLimit = (secret.isActual) ? limit.rest_api.api_per_second_actual:limit.rest_api.api_per_second_simulated; // console.log(`request ${secret.userid}, ${secret.account} :: trid - ${trid}, isActual - ${secret.isActual}`, countLimit, limit.rest_api.datetime); // this.limit.account[secret.account] = limit; // return result; } catch (ex) { throw ex; } } /** * 주어진 시간만큼 대기 한다. * * @param {number} miliseconds * @return {void} */ async sleep(miliseconds) { const promise = new Promise(function (resolve) { setTimeout(function () { resolve(0); }, miliseconds); }); await promise; } updateSession(userid, count = 1) { let result = true; this.limit.user[userid].ws_api.session = this.limit.user[userid].ws_api.session - count; if (this.limit.user[userid].ws_api.session < 0) { result = false; } console.log(`limit user: ${userid}`, result, this.limit.user[userid]); return result; } updateWsApi(account, trid, tr_type, tr_key) { const item = { tr_id: trid, tr_key: tr_key }; if (['H0STCNI0', 'H0STCNI9', 'H0IFCNI0', 'H0GSCNI0', 'HDFFF2C0'].includes(trid)) { this.limit.account[account].ws_api.notifications = this.limit.account[account].ws_api.notifications.filter(api => (api.tr_id != item.tr_id) || (api.tr_key != item.tr_key)); if (tr_type == TR_TYPE.registration) { this.limit.account[account].ws_api.notifications.push(item); } return ((this.limit.account[account].ws_api.notifications.length < EFriend_LIMIT.ws_api.notifications)); } else { this.limit.account[account].ws_api.registrations = this.limit.account[account].ws_api.registrations.filter(api => (api.tr_id != item.tr_id) || (api.tr_key != item.tr_key)); if (tr_type == TR_TYPE.registration) { this.limit.account[account].ws_api.registrations.push(item); } return ((this.limit.account[account].ws_api.registrations.length) < EFriend_LIMIT.ws_api.registrations); } } setTokenP(secret) { this.limit.account[secret.account].rest_api.api_tokenP_datetime = moment(); } async waitingTokenP(secret, isWaiting = false) { const seconds = moment().diff(this.limit.account[secret.account].rest_api.api_tokenP_datetime, 'seconds'); if (isWaiting) { await this.sleep(((EFriend_LIMIT.rest_api.api_tokenP_seconds + 5) - seconds) * 1000); } else { if (seconds < (EFriend_LIMIT.rest_api.api_tokenP_seconds + 5)) { throw new BaseError({ code: ERROR_CODE.WAITINGERROR, data: `tokenP: waiting - ${seconds}/${EFriend_LIMIT.rest_api.api_tokenP_seconds} seconds.` }); } } } } export default EFriendLimit;