const Axios = require('axios') const Cheerio = require('cheerio') const Constants = require('./constants') class Lotto { static #SessionID = undefined static #LottoDirect = undefined static #_request(method, url, data) { const requestOpts = { method, url, data, headers: Constants.DEFAULT_HEADERS, timeout: Constants.DEFAULT_TIMEOUT, } if(this.#SessionID) requestOpts.headers.Cookie = this.#SessionID return Axios(requestOpts).catch(err => err) } static async #_syncSession() { const sessionResponse = await this.#_request('GET', Constants.DEFAULT_SESSION_URL) if(sessionResponse instanceof Error) return sessionResponse if(sessionResponse.request.res.responseUrl === Constants.SYSTEM_CHECK_URL) return new Error('동행복권 사이트가 현재 시스템 점검중입니다.') const sessionId = sessionResponse.headers['set-cookie'] .find(cookieStr => cookieStr.indexOf('JSESSIONID') !== -1) if(!sessionId) return new Error('쿠키가 정상적으로 세팅되지 않았습니다.') this.#SessionID = sessionId } static async #_getRound() { const roundResponse = await this.#_request('GET', Constants.ROUND_INFO_URL) if(roundResponse instanceof Error) return roundResponse const $ = Cheerio.load(roundResponse.data) const lastDrawnRound = parseInt($("strong#lottoDrwNo").text(), 10) const round = lastDrawnRound + 1 return round } static async Login(userId, userPw) { const sessionSyncError = await this.#_syncSession() if(sessionSyncError instanceof Error) return sessionSyncError const loginData = { returnUrl: Constants.MAIN_PAGE_URL, userId, password: userPw, checkSave: 'off', newsEventYn: '', } const loginResult = await this.#_request('POST', Constants.LOGIN_REQUEST_URL, loginData) if(loginResult instanceof Error) return loginResult let $ = Cheerio.load(loginResult.data) /** * 비밀번호 변경 감지 * * 비밀번호가 변경이 될 경우 'https://www.dhlottery.co.kr/userSsl.do?method=pwdPlyChngNoti'로 redirect 됨 * 비밀번호를 유지할 지 변경할 지 고르는 페이지인데, 여기에 있는 chngTgtId 및 pwdChgToken를 추출해서 * * POST 'https://www.dhlottery.co.kr/userSsl.do?method=pspnPwChng' * payload로 chngTgtId, pwdChgToken을 보내면 다음에 하기 처리됨. * * 성공하면 'https://www.dhlottery.co.kr/user.do?method=login&returnUrl=https%3A%2F%2Fwww.dhlottery.co.kr%2Fcommon.do%3Fmethod%3Dmain' * redirect 진행되며, 마지막으로 MAIN_PAGE_URL로 redirect됨 */ const targetInput = $('#chngTgtId') if(targetInput.length !== 0) { const chngTgtId = targetInput.val() const pwdChgToken = $('#pwdChgToken').val() const pwChgNextData = { chngTgtId, pwdChgToken } const pgChgNextResult = await this.#_request('POST', Constants.PW_CHANGE_NEXT_URL, pwChgNextData) if(pgChgNextResult instanceof Error) return pgChgNextResult $ = Cheerio.load(pgChgNextResult.data) } const btnCommonElements = $('a.btn_common') if(btnCommonElements.length > 0) return new Error('로그인에 실패했습니다. 아이디 또는 비밀번호를 확인해주세요.') return true } static async Buy(lotteryInputs = []) { if(lotteryInputs.length === 0) return new Error('구매할 로또 정보를 입력해주세요.') if(lotteryInputs.length > 5) lotteryInputs = lotteryInputs.slice(0, 5) const round = await this.#_getRound() const readySocketResponse = await this.#_request('POST', Constants.BUY_READY_SOCKET_URL) if(readySocketResponse instanceof Error) return readySocketResponse this.#LottoDirect = readySocketResponse.data.ready_ip const requestParams = lotteryInputs.map((lotto, idx) => { return { genType: lotto === 'auto' ? '0' : '1', arrGameChoiceNum: lotto === 'auto' ? null : lotto.sort().map(num => String(num).padStart(2, 0)).join(','), alpabet: String.fromCharCode(65 + idx) } }) const requestData = { round: String(round), direct: this.#LottoDirect, nBuyAmount: `${requestParams.length * 1000}`, param: JSON.stringify(requestParams), gameCnt: `${requestParams.length}`, } const buyResponse = await this.#_request('POST', Constants.BUY_LOTTO_645_URL, requestData) if(buyResponse instanceof Error) return buyResponse const { result } = buyResponse.data if ((result.resultMsg || "FAILURE").toUpperCase() !== "SUCCESS") return new Error(result.resultMsg) return { round: result.buyRound, barcode: Object.keys(result) .filter(k => k.startsWith('barCode')) .map(k => result[k]) .join(' '), cost: result.nBuyAmount, numbers: result.arrGameChoiceNum, message: result.resultMsg, } } } module.exports = Lotto