@rich-automation/lotto 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/lib/cjs/apis/dhlottery/getWinningNumbers.js +36 -0
  2. package/lib/cjs/constants/dhlottery.js +9 -0
  3. package/lib/cjs/constants/index.js +13 -0
  4. package/lib/cjs/constants/selectors.js +14 -0
  5. package/lib/cjs/constants/urls.js +9 -0
  6. package/lib/cjs/controllers/factory.js +11 -0
  7. package/lib/cjs/controllers/puppeteer/index.js +77 -0
  8. package/lib/cjs/controllers/puppeteer/puppeteer.page.js +81 -0
  9. package/lib/cjs/index.js +5 -0
  10. package/lib/cjs/logger.js +55 -0
  11. package/lib/cjs/lottoError.js +71 -0
  12. package/lib/cjs/lottoService.js +133 -0
  13. package/lib/cjs/types.js +2 -0
  14. package/lib/cjs/utils/checkWinning.js +37 -0
  15. package/lib/cjs/utils/deferred.js +27 -0
  16. package/lib/cjs/utils/getCheckWinningLink.js +9 -0
  17. package/lib/cjs/utils/getCurrentLottoRound.js +11 -0
  18. package/lib/cjs/utils/invertObject.js +11 -0
  19. package/lib/cjs/utils/lazyRun.js +15 -0
  20. package/lib/cjs/utils/seconds.js +5 -0
  21. package/lib/cjs/utils/validateLottoNumber.js +19 -0
  22. package/lib/cjs/utils/validatePurchaseAvailability.js +26 -0
  23. package/lib/esm/apis/dhlottery/requestBuy.js +11 -0
  24. package/package.json +9 -5
  25. /package/lib/{apis → cjs/apis}/dhlottery/requestBuy.js +0 -0
  26. /package/lib/{apis → esm/apis}/dhlottery/getWinningNumbers.js +0 -0
  27. /package/lib/{constants → esm/constants}/dhlottery.js +0 -0
  28. /package/lib/{constants → esm/constants}/index.js +0 -0
  29. /package/lib/{constants → esm/constants}/selectors.js +0 -0
  30. /package/lib/{constants → esm/constants}/urls.js +0 -0
  31. /package/lib/{controllers → esm/controllers}/factory.js +0 -0
  32. /package/lib/{controllers → esm/controllers}/puppeteer/index.js +0 -0
  33. /package/lib/{controllers → esm/controllers}/puppeteer/puppeteer.page.js +0 -0
  34. /package/lib/{index.js → esm/index.js} +0 -0
  35. /package/lib/{logger.js → esm/logger.js} +0 -0
  36. /package/lib/{lottoError.js → esm/lottoError.js} +0 -0
  37. /package/lib/{lottoService.js → esm/lottoService.js} +0 -0
  38. /package/lib/{types.js → esm/types.js} +0 -0
  39. /package/lib/{utils → esm/utils}/checkWinning.js +0 -0
  40. /package/lib/{utils → esm/utils}/deferred.js +0 -0
  41. /package/lib/{utils → esm/utils}/getCheckWinningLink.js +0 -0
  42. /package/lib/{utils → esm/utils}/getCurrentLottoRound.js +0 -0
  43. /package/lib/{utils → esm/utils}/invertObject.js +0 -0
  44. /package/lib/{utils → esm/utils}/lazyRun.js +0 -0
  45. /package/lib/{utils → esm/utils}/seconds.js +0 -0
  46. /package/lib/{utils → esm/utils}/validateLottoNumber.js +0 -0
  47. /package/lib/{utils → esm/utils}/validatePurchaseAvailability.js +0 -0
  48. /package/lib/{apis → typescript/apis}/dhlottery/getWinningNumbers.d.ts +0 -0
  49. /package/lib/{apis → typescript/apis}/dhlottery/requestBuy.d.ts +0 -0
  50. /package/lib/{constants → typescript/constants}/dhlottery.d.ts +0 -0
  51. /package/lib/{constants → typescript/constants}/index.d.ts +0 -0
  52. /package/lib/{constants → typescript/constants}/selectors.d.ts +0 -0
  53. /package/lib/{constants → typescript/constants}/urls.d.ts +0 -0
  54. /package/lib/{controllers → typescript/controllers}/factory.d.ts +0 -0
  55. /package/lib/{controllers → typescript/controllers}/puppeteer/index.d.ts +0 -0
  56. /package/lib/{controllers → typescript/controllers}/puppeteer/puppeteer.page.d.ts +0 -0
  57. /package/lib/{index.d.ts → typescript/index.d.ts} +0 -0
  58. /package/lib/{logger.d.ts → typescript/logger.d.ts} +0 -0
  59. /package/lib/{lottoError.d.ts → typescript/lottoError.d.ts} +0 -0
  60. /package/lib/{lottoService.d.ts → typescript/lottoService.d.ts} +0 -0
  61. /package/lib/{types.d.ts → typescript/types.d.ts} +0 -0
  62. /package/lib/{utils → typescript/utils}/checkWinning.d.ts +0 -0
  63. /package/lib/{utils → typescript/utils}/deferred.d.ts +0 -0
  64. /package/lib/{utils → typescript/utils}/getCheckWinningLink.d.ts +0 -0
  65. /package/lib/{utils → typescript/utils}/getCurrentLottoRound.d.ts +0 -0
  66. /package/lib/{utils → typescript/utils}/invertObject.d.ts +0 -0
  67. /package/lib/{utils → typescript/utils}/lazyRun.d.ts +0 -0
  68. /package/lib/{utils → typescript/utils}/seconds.d.ts +0 -0
  69. /package/lib/{utils → typescript/utils}/validateLottoNumber.d.ts +0 -0
  70. /package/lib/{utils → typescript/utils}/validatePurchaseAvailability.d.ts +0 -0
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.getWinningNumbers = void 0;
16
+ const axios_1 = __importDefault(require("axios"));
17
+ const lottoError_1 = __importDefault(require("../../lottoError"));
18
+ const getWinningNumbers = (volume) => __awaiter(void 0, void 0, void 0, function* () {
19
+ let res;
20
+ try {
21
+ res = yield axios_1.default.get(`https://www.dhlottery.co.kr/common.do?method=getLottoNumber&drwNo=${volume}`);
22
+ }
23
+ catch (_a) {
24
+ throw lottoError_1.default.NetworkError();
25
+ }
26
+ if (res.data.returnValue == 'success') {
27
+ return toOrderedWinningNumbers(res.data);
28
+ }
29
+ else {
30
+ throw lottoError_1.default.InvalidRound();
31
+ }
32
+ });
33
+ exports.getWinningNumbers = getWinningNumbers;
34
+ function toOrderedWinningNumbers(data) {
35
+ return [data.drwtNo1, data.drwtNo2, data.drwtNo3, data.drwtNo4, data.drwtNo5, data.drwtNo6, data.bnusNo];
36
+ }
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DHLOTTERY = void 0;
4
+ exports.DHLOTTERY = {
5
+ DIALOG: {
6
+ ID_PWD_INCORRECT: '아이디 또는 비밀번호를 잘못 입력하셨습니다',
7
+ TOO_MANY_WRONG_SIGN_IN: '5회 이상 로그인에 실패하였습니다.'
8
+ }
9
+ };
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CONST = void 0;
4
+ exports.CONST = {
5
+ LAZY_RUN_DEFAULT: 1000,
6
+ BROWSER_INIT_RETRY_COUNT: 10,
7
+ BROWSER_INIT_RETRY_TIMEOUT: 1000,
8
+ BROWSER_DESTROY_SAFE_TIMEOUT: 1000,
9
+ BROWSER_PAGE_POPUP_WAIT: 1500,
10
+ BROWSER_PAGE_DIALOG_WAIT: 10000,
11
+ WEEK_TO_MILLISECOND: 604800000,
12
+ THOUSAND_ROUND_DATE: '2022-01-29T11:50:00'
13
+ };
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SELECTORS = void 0;
4
+ exports.SELECTORS = {
5
+ ID_INPUT: '#userId',
6
+ PWD_INPUT: '#article > div:nth-child(2) > div > form > div > div.inner > fieldset > div.form > input[type=password]:nth-child(2)',
7
+ LOGIN_BUTTON: '#article > div:nth-child(2) > div > form > div > div.inner > fieldset > div.form > a',
8
+ PURCHASE_TYPE_RANDOM_BTN: '#tabWay2Buy a#num2',
9
+ PURCHASE_AMOUNT_SELECT: 'select#amoundApply',
10
+ PURCHASE_AMOUNT_CONFIRM_BTN: '#btnSelectNum',
11
+ PURCHASE_BTN: '#btnBuy',
12
+ PURCHASE_CONFIRM_BTN: '#popupLayerConfirm .btns > input[value="확인"]',
13
+ PURCHASE_NUMBER_LIST: '#reportRow .nums'
14
+ };
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.URLS = void 0;
4
+ exports.URLS = {
5
+ MAIN: 'https://dhlottery.co.kr/common.do?method=main',
6
+ LOGIN: 'https://dhlottery.co.kr/user.do?method=login&returnUrl=',
7
+ LOTTO_645: 'https://ol.dhlottery.co.kr/olotto/game/game645.do',
8
+ CHECK_WINNING: 'https://dhlottery.co.kr/qr.do'
9
+ };
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createBrowserController = void 0;
4
+ const puppeteer_1 = require("./puppeteer");
5
+ function createBrowserController(name, configs, logger) {
6
+ switch (name) {
7
+ case 'puppeteer':
8
+ return new puppeteer_1.PuppeteerController(configs, logger);
9
+ }
10
+ }
11
+ exports.createBrowserController = createBrowserController;
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.PuppeteerController = void 0;
16
+ const puppeteer_1 = __importDefault(require("puppeteer"));
17
+ const deferred_1 = require("../../utils/deferred");
18
+ const puppeteer_page_1 = require("./puppeteer.page");
19
+ const constants_1 = require("../../constants");
20
+ class PuppeteerController {
21
+ constructor(configs, logger) {
22
+ this.getBrowser = () => __awaiter(this, void 0, void 0, function* () {
23
+ const p = (0, deferred_1.deferred)();
24
+ if (this.browser) {
25
+ p.resolve(this.browser);
26
+ }
27
+ else {
28
+ let retry = 0;
29
+ const interval = setInterval(() => {
30
+ if (constants_1.CONST.BROWSER_INIT_RETRY_COUNT < retry) {
31
+ clearInterval(interval);
32
+ p.reject(new Error('Browser is not initialized'));
33
+ }
34
+ else if (this.browser) {
35
+ clearInterval(interval);
36
+ p.resolve(this.browser);
37
+ }
38
+ retry++;
39
+ }, constants_1.CONST.BROWSER_INIT_RETRY_TIMEOUT);
40
+ }
41
+ return p.promise;
42
+ });
43
+ this.focus = (pageIndex = -1) => __awaiter(this, void 0, void 0, function* () {
44
+ const browser = yield this.getBrowser();
45
+ const pages = yield browser.pages();
46
+ if (pages.length === 0) {
47
+ const page = yield browser.newPage();
48
+ return new puppeteer_page_1.PuppeteerPage(page);
49
+ }
50
+ else {
51
+ const isWithinRange = Math.max(0, Math.min(pageIndex, pages.length - 1)) === pageIndex;
52
+ const page = pages.at(isWithinRange ? pageIndex : -1);
53
+ if (!page)
54
+ throw new Error('Page is not found');
55
+ return new puppeteer_page_1.PuppeteerPage(page);
56
+ }
57
+ });
58
+ this.close = () => __awaiter(this, void 0, void 0, function* () {
59
+ const browser = yield this.getBrowser();
60
+ return browser.close();
61
+ });
62
+ this.cleanPages = (remainingPageIndex) => __awaiter(this, void 0, void 0, function* () {
63
+ const browser = yield this.getBrowser();
64
+ const pages = yield browser.pages();
65
+ const promises = pages.map((page, index) => __awaiter(this, void 0, void 0, function* () {
66
+ if (!remainingPageIndex.includes(index)) {
67
+ return page.close();
68
+ }
69
+ }));
70
+ yield Promise.all(promises);
71
+ });
72
+ this.configs = configs;
73
+ this.logger = logger;
74
+ puppeteer_1.default.launch(this.configs).then(browser => (this.browser = browser));
75
+ }
76
+ }
77
+ exports.PuppeteerController = PuppeteerController;
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.PuppeteerPage = void 0;
13
+ const deferred_1 = require("../../utils/deferred");
14
+ const lazyRun_1 = require("../../utils/lazyRun");
15
+ class PuppeteerPage {
16
+ constructor(page) {
17
+ this.page = page;
18
+ }
19
+ url() {
20
+ return __awaiter(this, void 0, void 0, function* () {
21
+ return this.page.url();
22
+ });
23
+ }
24
+ goto(url) {
25
+ return __awaiter(this, void 0, void 0, function* () {
26
+ yield this.page.goto(url, { waitUntil: 'load' });
27
+ });
28
+ }
29
+ fill(selector, value) {
30
+ return __awaiter(this, void 0, void 0, function* () {
31
+ yield this.page.type(selector, value.toString());
32
+ });
33
+ }
34
+ click(selector) {
35
+ return __awaiter(this, void 0, void 0, function* () {
36
+ yield this.page.click(selector);
37
+ });
38
+ }
39
+ select(selector, value) {
40
+ return __awaiter(this, void 0, void 0, function* () {
41
+ yield this.page.select(selector, value);
42
+ });
43
+ }
44
+ querySelectorAll(selector, callback) {
45
+ return this.page.$$eval(selector, callback);
46
+ }
47
+ getCookies() {
48
+ return __awaiter(this, void 0, void 0, function* () {
49
+ const cookies = yield this.page.cookies();
50
+ return JSON.stringify(cookies);
51
+ });
52
+ }
53
+ setCookies(cookies) {
54
+ return __awaiter(this, void 0, void 0, function* () {
55
+ const cookieParams = JSON.parse(cookies);
56
+ yield this.page.setCookie(...cookieParams);
57
+ });
58
+ }
59
+ wait(param) {
60
+ return __awaiter(this, void 0, void 0, function* () {
61
+ const p = (0, deferred_1.deferred)();
62
+ if (param === 'idle') {
63
+ yield this.page.waitForNavigation({ waitUntil: 'networkidle0' });
64
+ p.resolve();
65
+ }
66
+ if (param === 'load') {
67
+ yield this.page.waitForNavigation({ waitUntil: 'load' });
68
+ p.resolve();
69
+ }
70
+ if (typeof param === 'number') {
71
+ yield (0, lazyRun_1.lazyRun)(() => __awaiter(this, void 0, void 0, function* () { return p.resolve(); }), param);
72
+ }
73
+ return p.promise;
74
+ });
75
+ }
76
+ on(event, callback) {
77
+ this.page.on(event, callback);
78
+ return () => this.page.off(event, callback);
79
+ }
80
+ }
81
+ exports.PuppeteerPage = PuppeteerPage;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LottoService = void 0;
4
+ var lottoService_1 = require("./lottoService");
5
+ Object.defineProperty(exports, "LottoService", { enumerable: true, get: function () { return lottoService_1.LottoService; } });
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.LogLevel = void 0;
7
+ const dayjs_1 = __importDefault(require("dayjs"));
8
+ const utc_1 = __importDefault(require("dayjs/plugin/utc"));
9
+ const timezone_1 = __importDefault(require("dayjs/plugin/timezone"));
10
+ dayjs_1.default.extend(utc_1.default);
11
+ dayjs_1.default.extend(timezone_1.default);
12
+ var LogLevel;
13
+ (function (LogLevel) {
14
+ LogLevel[LogLevel["NONE"] = -1] = "NONE";
15
+ LogLevel[LogLevel["ERROR"] = 0] = "ERROR";
16
+ LogLevel[LogLevel["WARN"] = 1] = "WARN";
17
+ LogLevel[LogLevel["INFO"] = 2] = "INFO";
18
+ LogLevel[LogLevel["DEBUG"] = 3] = "DEBUG";
19
+ })(LogLevel = exports.LogLevel || (exports.LogLevel = {}));
20
+ class Logger {
21
+ constructor(logLevel = LogLevel.INFO, prefix = '') {
22
+ this._logLevel = logLevel;
23
+ this._prefix = prefix;
24
+ }
25
+ setLogLevel(logLevel) {
26
+ this._logLevel = logLevel;
27
+ }
28
+ get logLevel() {
29
+ return this._logLevel;
30
+ }
31
+ error(...args) {
32
+ if (this._logLevel >= LogLevel.ERROR) {
33
+ console.error(printNow(), this._prefix, ...args);
34
+ }
35
+ }
36
+ warn(...args) {
37
+ if (this._logLevel >= LogLevel.WARN) {
38
+ console.warn(printNow(), this._prefix, ...args);
39
+ }
40
+ }
41
+ info(...args) {
42
+ if (this._logLevel >= LogLevel.INFO) {
43
+ console.info(printNow(), this._prefix, ...args);
44
+ }
45
+ }
46
+ debug(...args) {
47
+ if (this._logLevel >= LogLevel.DEBUG) {
48
+ console.debug(printNow(), this._prefix, ...args);
49
+ }
50
+ }
51
+ }
52
+ exports.default = Logger;
53
+ function printNow() {
54
+ return dayjs_1.default.tz(Date.now(), 'Asia/Seoul').format('YYYY/MM/DD HH:mm:ss');
55
+ }
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const invertObject_1 = require("./utils/invertObject");
4
+ const BaseErrorCode = {
5
+ NETWORK_ERROR: 100001,
6
+ UNKNOWN_ERROR: 199999
7
+ };
8
+ const LoginErrorCode = {
9
+ CREDENTIALS_INCORRECT: 200001,
10
+ INVALID_COOKIE: 200002
11
+ };
12
+ const LottoErrorCode = {
13
+ INVALID_ROUND: 300001,
14
+ INVALID_LOTTO_NUMBER: 300002,
15
+ NOT_AUTHENTICATED: 300003,
16
+ PURCHASE_UNAVAILABLE: 300004
17
+ };
18
+ const ErrorCode = Object.assign(Object.assign(Object.assign({}, BaseErrorCode), LoginErrorCode), LottoErrorCode);
19
+ const ErrorName = (0, invertObject_1.invertObject)(ErrorCode);
20
+ const ErrorMessage = {
21
+ [ErrorCode.NETWORK_ERROR]: '네트워크 에러가 발생했습니다.',
22
+ [ErrorCode.UNKNOWN_ERROR]: '알 수 없는 오류가 발생했습니다.',
23
+ [ErrorCode.CREDENTIALS_INCORRECT]: '아이디 혹은 비밀번호가 일치하지 않습니다.',
24
+ [ErrorCode.INVALID_COOKIE]: '쿠키가 만료됐거나 유효하지 않습니다.',
25
+ [ErrorCode.INVALID_ROUND]: '로또 회차가 올바르지 않습니다.',
26
+ [ErrorCode.INVALID_LOTTO_NUMBER]: '로또 번호가 올바르지 않습니다.',
27
+ [ErrorCode.NOT_AUTHENTICATED]: '인증되지 않았습니다.',
28
+ [ErrorCode.PURCHASE_UNAVAILABLE]: '현재는 로또 구매가 불가능합니다.'
29
+ };
30
+ class LottoError extends Error {
31
+ static NetworkError() {
32
+ return new LottoError(ErrorCode.NETWORK_ERROR);
33
+ }
34
+ static UnknownError() {
35
+ return new LottoError(ErrorCode.UNKNOWN_ERROR);
36
+ }
37
+ static CredentialsIncorrect() {
38
+ return new LottoError(ErrorCode.CREDENTIALS_INCORRECT);
39
+ }
40
+ static InvalidCookies() {
41
+ return new LottoError(ErrorCode.INVALID_COOKIE);
42
+ }
43
+ static InvalidRound() {
44
+ return new LottoError(ErrorCode.INVALID_ROUND);
45
+ }
46
+ static InvalidLottoNumber() {
47
+ return new LottoError(ErrorCode.INVALID_LOTTO_NUMBER);
48
+ }
49
+ static NotAuthenticated() {
50
+ return new LottoError(ErrorCode.NOT_AUTHENTICATED);
51
+ }
52
+ static PurchaseUnavailable() {
53
+ return new LottoError(ErrorCode.PURCHASE_UNAVAILABLE);
54
+ }
55
+ static get code() {
56
+ return ErrorCode;
57
+ }
58
+ static getMessage(code) {
59
+ return ErrorMessage[code];
60
+ }
61
+ static getName(code) {
62
+ return ErrorName[code];
63
+ }
64
+ constructor(code, message) {
65
+ var _a;
66
+ super(message !== null && message !== void 0 ? message : ErrorMessage[code]);
67
+ this.name = (_a = ErrorName[code]) !== null && _a !== void 0 ? _a : 'LottoError';
68
+ this.code = code;
69
+ }
70
+ }
71
+ exports.default = LottoError;
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.LottoService = void 0;
16
+ const lottoError_1 = __importDefault(require("./lottoError"));
17
+ const selectors_1 = require("./constants/selectors");
18
+ const factory_1 = require("./controllers/factory");
19
+ const urls_1 = require("./constants/urls");
20
+ const deferred_1 = require("./utils/deferred");
21
+ const constants_1 = require("./constants");
22
+ const lazyRun_1 = require("./utils/lazyRun");
23
+ const logger_1 = __importDefault(require("./logger"));
24
+ const getCurrentLottoRound_1 = require("./utils/getCurrentLottoRound");
25
+ const validateLottoNumber_1 = require("./utils/validateLottoNumber");
26
+ const getWinningNumbers_1 = require("./apis/dhlottery/getWinningNumbers");
27
+ const checkWinning_1 = require("./utils/checkWinning");
28
+ const validatePurchaseAvailability_1 = require("./utils/validatePurchaseAvailability");
29
+ const getCheckWinningLink_1 = require("./utils/getCheckWinningLink");
30
+ class LottoService {
31
+ constructor(configs) {
32
+ this.context = {
33
+ authenticated: false
34
+ };
35
+ this.destroy = () => __awaiter(this, void 0, void 0, function* () {
36
+ return (0, lazyRun_1.lazyRun)(this.browserController.close, constants_1.CONST.BROWSER_DESTROY_SAFE_TIMEOUT);
37
+ });
38
+ this.signInWithCookie = (cookies) => __awaiter(this, void 0, void 0, function* () {
39
+ // 쿠키 설정 & 페이지 이동
40
+ const page = yield this.browserController.focus(0);
41
+ this.logger.debug('[signInWithCookie]', 'setCookies');
42
+ yield page.setCookies(cookies);
43
+ this.logger.debug('[signInWithCookie]', 'goto', 'login page');
44
+ yield page.goto(urls_1.URLS.LOGIN);
45
+ this.logger.debug('[signInWithCookie]', 'page url', yield page.url());
46
+ // 팝업 제거용
47
+ this.logger.debug('[signInWithCookie]', 'clear popups');
48
+ yield page.wait(constants_1.CONST.BROWSER_PAGE_POPUP_WAIT);
49
+ yield this.browserController.cleanPages([0]);
50
+ // 로그인이 되지 않았으면 에러처리
51
+ if (urls_1.URLS.LOGIN === (yield page.url())) {
52
+ this.logger.info('[signInWithCookie]', 'failure');
53
+ throw lottoError_1.default.InvalidCookies();
54
+ }
55
+ this.logger.info('[signInWithCookie]', 'success');
56
+ this.context.authenticated = true;
57
+ return page.getCookies();
58
+ });
59
+ this.signIn = (id, password) => __awaiter(this, void 0, void 0, function* () {
60
+ const p = (0, deferred_1.deferred)();
61
+ queueMicrotask(() => __awaiter(this, void 0, void 0, function* () {
62
+ // 페이지 이동
63
+ const page = yield this.browserController.focus(0);
64
+ this.logger.debug('[signIn]', 'goto', 'login page');
65
+ yield page.goto(urls_1.URLS.LOGIN);
66
+ this.logger.debug('[signIn]', 'page url', yield page.url());
67
+ const unsubscribe = page.on('response', (response) => __awaiter(this, void 0, void 0, function* () {
68
+ const url = response.url();
69
+ switch (true) {
70
+ // 로그인 실패
71
+ case url.includes(urls_1.URLS.LOGIN.replace('https://', '')): {
72
+ this.logger.info('[signIn]', 'fallback to login page', 'failure');
73
+ unsubscribe();
74
+ p.reject(lottoError_1.default.CredentialsIncorrect());
75
+ break;
76
+ }
77
+ // 로그인 성공
78
+ case url.includes(urls_1.URLS.MAIN.replace('https://', '')): {
79
+ this.logger.info('[signIn]', 'fallback to main page', 'success');
80
+ this.context.authenticated = true;
81
+ unsubscribe();
82
+ this.logger.debug('[signIn]', 'clear popups');
83
+ yield page.wait(constants_1.CONST.BROWSER_PAGE_POPUP_WAIT);
84
+ yield this.browserController.cleanPages([0]);
85
+ const cookies = yield page.getCookies();
86
+ p.resolve(cookies);
87
+ break;
88
+ }
89
+ }
90
+ }));
91
+ // 로그인 시도
92
+ this.logger.debug('[signIn]', 'try login');
93
+ yield page.fill(selectors_1.SELECTORS.ID_INPUT, id);
94
+ yield page.fill(selectors_1.SELECTORS.PWD_INPUT, password);
95
+ yield page.click(selectors_1.SELECTORS.LOGIN_BUTTON);
96
+ }));
97
+ return p.promise;
98
+ });
99
+ this.purchase = (amount = 5) => __awaiter(this, void 0, void 0, function* () {
100
+ if (!this.context.authenticated)
101
+ throw lottoError_1.default.NotAuthenticated();
102
+ (0, validatePurchaseAvailability_1.validatePurchaseAvailability)();
103
+ // move
104
+ const page = yield this.browserController.focus(0);
105
+ yield page.goto(urls_1.URLS.LOTTO_645);
106
+ // click auto button
107
+ yield page.click(selectors_1.SELECTORS.PURCHASE_TYPE_RANDOM_BTN);
108
+ // set and confirm amount
109
+ const amountString = String(Math.max(1, Math.min(5, amount)));
110
+ yield page.select(selectors_1.SELECTORS.PURCHASE_AMOUNT_SELECT, amountString);
111
+ yield page.click(selectors_1.SELECTORS.PURCHASE_AMOUNT_CONFIRM_BTN);
112
+ // click purchase button
113
+ yield page.click(selectors_1.SELECTORS.PURCHASE_BTN);
114
+ yield page.click(selectors_1.SELECTORS.PURCHASE_CONFIRM_BTN);
115
+ yield page.wait(1000);
116
+ // game result
117
+ return page.querySelectorAll(selectors_1.SELECTORS.PURCHASE_NUMBER_LIST, elems => {
118
+ return elems.map(it => Array.from(it.children).map(child => Number(child.innerHTML)));
119
+ });
120
+ });
121
+ this.check = (numbers, round = (0, getCurrentLottoRound_1.getCurrentLottoRound)()) => __awaiter(this, void 0, void 0, function* () {
122
+ (0, validateLottoNumber_1.validateLottoNumber)(numbers);
123
+ const winningNumbers = yield (0, getWinningNumbers_1.getWinningNumbers)(round);
124
+ return (0, checkWinning_1.checkWinning)(numbers, winningNumbers);
125
+ });
126
+ this.getCheckWinningLink = (round, numbers) => {
127
+ return (0, getCheckWinningLink_1.getCheckWinningLink)(round, numbers);
128
+ };
129
+ this.logger = new logger_1.default(configs === null || configs === void 0 ? void 0 : configs.logLevel, '[LottoService]');
130
+ this.browserController = (0, factory_1.createBrowserController)('puppeteer', Object.assign({ headless: false, defaultViewport: { width: 1080, height: 1024 } }, configs), this.logger);
131
+ }
132
+ }
133
+ exports.LottoService = LottoService;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.checkWinning = void 0;
13
+ const checkWinning = (myNumber, winningNumbers) => __awaiter(void 0, void 0, void 0, function* () {
14
+ const mainWinningNumbers = winningNumbers.slice(0, 6);
15
+ const bonusNumber = winningNumbers.at(-1);
16
+ const matchedNumbers = myNumber.filter(n => mainWinningNumbers.includes(n));
17
+ const matchingNumbersCount = matchedNumbers.length;
18
+ let rank = 0;
19
+ if (matchingNumbersCount === 6) {
20
+ rank = 1;
21
+ }
22
+ else if (matchingNumbersCount === 5 && myNumber.includes(bonusNumber)) {
23
+ matchedNumbers.push(bonusNumber);
24
+ rank = 2;
25
+ }
26
+ else if (matchingNumbersCount === 5) {
27
+ rank = 3;
28
+ }
29
+ else if (matchingNumbersCount === 4) {
30
+ rank = 4;
31
+ }
32
+ else if (matchingNumbersCount === 3) {
33
+ rank = 5;
34
+ }
35
+ return { rank, matchedNumbers };
36
+ });
37
+ exports.checkWinning = checkWinning;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deferred = void 0;
4
+ const deferred = () => {
5
+ let state = 'pending';
6
+ let resolve;
7
+ let reject;
8
+ const promise = new Promise((res, rej) => {
9
+ resolve = (value) => {
10
+ state = 'fulfilled';
11
+ res(value);
12
+ };
13
+ reject = (reason) => {
14
+ state = 'rejected';
15
+ rej(reason);
16
+ };
17
+ });
18
+ return {
19
+ get state() {
20
+ return state;
21
+ },
22
+ promise,
23
+ resolve,
24
+ reject
25
+ };
26
+ };
27
+ exports.deferred = deferred;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getCheckWinningLink = void 0;
4
+ const urls_1 = require("../constants/urls");
5
+ function getCheckWinningLink(round, numbers) {
6
+ const nums = numbers.map(it => 'q' + it.map(n => String(n).padStart(2, '0')).join('')).join('');
7
+ return `${urls_1.URLS.CHECK_WINNING}?method=winQr&v=${round}${nums}`;
8
+ }
9
+ exports.getCheckWinningLink = getCheckWinningLink;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getCurrentLottoRound = void 0;
4
+ const constants_1 = require("../constants");
5
+ const getCurrentLottoRound = () => {
6
+ const standardDate = new Date(constants_1.CONST.THOUSAND_ROUND_DATE);
7
+ const now = new Date(global.Date.now());
8
+ const ADDITIONAL_ROUND = Math.floor((now.getTime() - standardDate.getTime()) / constants_1.CONST.WEEK_TO_MILLISECOND);
9
+ return 1000 + ADDITIONAL_ROUND;
10
+ };
11
+ exports.getCurrentLottoRound = getCurrentLottoRound;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.invertObject = void 0;
4
+ function invertObject(obj) {
5
+ const result = {};
6
+ for (const [key, value] of Object.entries(obj)) {
7
+ result[value] = key;
8
+ }
9
+ return result;
10
+ }
11
+ exports.invertObject = invertObject;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.lazyRun = void 0;
4
+ const constants_1 = require("../constants");
5
+ const deferred_1 = require("./deferred");
6
+ function lazyRun(callback, timeout = constants_1.CONST.LAZY_RUN_DEFAULT) {
7
+ const p = (0, deferred_1.deferred)();
8
+ setTimeout(() => {
9
+ callback()
10
+ .then(() => p.resolve())
11
+ .catch((e) => p.reject(e));
12
+ }, timeout);
13
+ return p.promise;
14
+ }
15
+ exports.lazyRun = lazyRun;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.seconds = void 0;
4
+ const seconds = (n) => 1000 * n;
5
+ exports.seconds = seconds;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.validateLottoNumber = void 0;
7
+ const lottoError_1 = __importDefault(require("../lottoError"));
8
+ const validateLottoNumber = (numbers) => {
9
+ const isValid = numbers
10
+ .filter(number => {
11
+ return typeof number === 'number' && Math.max(number, 45) === 45 && Math.min(number, 1) === 1;
12
+ })
13
+ .filter((number, index) => numbers.indexOf(number) === index)
14
+ .filter(number => Number.isInteger(number)).length === 6;
15
+ if (!isValid) {
16
+ throw lottoError_1.default.InvalidLottoNumber();
17
+ }
18
+ };
19
+ exports.validateLottoNumber = validateLottoNumber;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.validatePurchaseAvailability = void 0;
7
+ const dayjs_1 = __importDefault(require("dayjs"));
8
+ const utc_1 = __importDefault(require("dayjs/plugin/utc"));
9
+ const timezone_1 = __importDefault(require("dayjs/plugin/timezone"));
10
+ const lottoError_1 = __importDefault(require("../lottoError"));
11
+ dayjs_1.default.extend(utc_1.default);
12
+ dayjs_1.default.extend(timezone_1.default);
13
+ const getSeoulTime = () => dayjs_1.default.tz(Date.now(), 'Asia/Seoul');
14
+ const resetTime = (dayjs) => dayjs.hour(0).minute(0).second(0).millisecond(0);
15
+ // 평일/일요일: 06:00 ~ 24:00
16
+ // 토요일: 06:00 ~ 20:00
17
+ const validatePurchaseAvailability = () => {
18
+ const now = getSeoulTime();
19
+ const isSaturday = now.day() === 6;
20
+ const openingTime = resetTime(getSeoulTime()).hour(6);
21
+ const closingTime = isSaturday ? resetTime(getSeoulTime()).hour(20) : resetTime(getSeoulTime()).hour(24);
22
+ if (now.isBefore(openingTime) || now.isAfter(closingTime)) {
23
+ throw lottoError_1.default.PurchaseUnavailable();
24
+ }
25
+ };
26
+ exports.validatePurchaseAvailability = validatePurchaseAvailability;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ // POST
3
+ // https://ol.dhlottery.co.kr/olotto/game/execBuy.do
4
+ // form
5
+ // {
6
+ // round: 1066,
7
+ // direct: 172.17.20.52,
8
+ // nBuyAmount: 1000,
9
+ // param: [{"genType": "0","arrGameChoiceNum": null, "alpabet": "A"}]
10
+ // gameCnt:1
11
+ // }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rich-automation/lotto",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Lotto module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -15,9 +15,9 @@
15
15
  "url": "https://github.com/DongGukMon"
16
16
  }
17
17
  ],
18
- "type": "module",
19
- "main": "lib/index.js",
20
- "types": "lib/index.d.ts",
18
+ "main": "lib/cjs/index",
19
+ "module": "lib/esm/index",
20
+ "types": "lib/typescript/index.d.ts",
21
21
  "files": [
22
22
  "lib",
23
23
  "package.json",
@@ -25,8 +25,12 @@
25
25
  ],
26
26
  "packageManager": "yarn@1.22.19",
27
27
  "scripts": {
28
+ "prepack": "yarn build",
28
29
  "start": "ts-node ./example/app",
29
- "build": "rm -rf lib && tsc --build",
30
+ "build": "rm -rf lib && yarn build:cjs && yarn build:esm && yarn build:dts",
31
+ "build:cjs": "tsc --project tsconfig.cjs.json --verbatimModuleSyntax false",
32
+ "build:esm": "tsc --project tsconfig.esm.json",
33
+ "build:dts": "tsc --project tsconfig.json --emitDeclarationOnly --declaration --declarationDir lib/typescript",
30
34
  "test": "jest --forceExit --detectOpenHandles",
31
35
  "install:chrome": "node ./node_modules/puppeteer/install.js",
32
36
  "fix": "yarn fix:eslint && yarn fix:prettier",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes