@rich-automation/lotto 0.1.7 → 2.0.0

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 (41) hide show
  1. package/README.md +131 -1
  2. package/lib/cjs/constants/index.js +1 -1
  3. package/lib/cjs/controllers/api/index.js +28 -0
  4. package/lib/cjs/controllers/factory.js +20 -6
  5. package/lib/cjs/controllers/playwright/index.js +1 -2
  6. package/lib/cjs/controllers/puppeteer/index.js +2 -6
  7. package/lib/cjs/index.js +9 -3
  8. package/lib/cjs/lottoError.js +6 -1
  9. package/lib/cjs/lottoService.js +21 -9
  10. package/lib/cjs/utils/checkWinning.js +2 -11
  11. package/lib/cjs/utils/getCheckWinningLink.js +1 -1
  12. package/lib/cjs/utils/{getCurrentLottoRound.js → getLastLottoRound.js} +3 -3
  13. package/lib/cjs/utils/getNextLottoRound.js +11 -0
  14. package/lib/esm/constants/index.js +1 -1
  15. package/lib/esm/controllers/api/index.js +25 -0
  16. package/lib/esm/controllers/factory.js +20 -6
  17. package/lib/esm/controllers/playwright/index.js +1 -2
  18. package/lib/esm/controllers/puppeteer/index.js +2 -3
  19. package/lib/esm/controllers/puppeteer/puppeteer.page.js +0 -1
  20. package/lib/esm/index.js +4 -1
  21. package/lib/esm/lottoError.js +6 -1
  22. package/lib/esm/lottoService.js +21 -9
  23. package/lib/esm/utils/checkWinning.js +2 -11
  24. package/lib/esm/utils/getCheckWinningLink.js +1 -1
  25. package/lib/esm/utils/{getCurrentLottoRound.js → getLastLottoRound.js} +1 -1
  26. package/lib/esm/utils/getNextLottoRound.js +7 -0
  27. package/lib/typescript/controllers/api/index.d.ts +13 -0
  28. package/lib/typescript/controllers/factory.d.ts +2 -2
  29. package/lib/typescript/controllers/playwright/index.d.ts +4 -3
  30. package/lib/typescript/controllers/puppeteer/index.d.ts +4 -4
  31. package/lib/typescript/controllers/puppeteer/puppeteer.page.d.ts +1 -1
  32. package/lib/typescript/index.d.ts +4 -1
  33. package/lib/typescript/lottoError.d.ts +4 -1
  34. package/lib/typescript/lottoService.d.ts +4 -4
  35. package/lib/typescript/types.d.ts +10 -7
  36. package/lib/typescript/utils/checkWinning.d.ts +2 -2
  37. package/lib/typescript/utils/getCheckWinningLink.d.ts +1 -1
  38. package/lib/typescript/utils/getLastLottoRound.d.ts +1 -0
  39. package/lib/typescript/utils/getNextLottoRound.d.ts +1 -0
  40. package/package.json +16 -4
  41. package/lib/typescript/utils/getCurrentLottoRound.d.ts +0 -1
package/README.md CHANGED
@@ -1,4 +1,134 @@
1
1
  # @rich-automation/lotto
2
2
 
3
- [![ci](https://github.com/rich-automation/lotto-module/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/rich-automation/lotto-module/actions/workflows/ci.yml)
3
+ [![npm](https://img.shields.io/npm/v/@rich-automation/lotto.svg?style=popout&colorB=yellow)](https://www.npmjs.com/package/@rich-automation/lotto)
4
+ [![ci](https://github.com/rich-automation/lotto-module/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/rich-automation/lotto-module/actions/workflows/ci.yml)
4
5
  [![codecov](https://codecov.io/gh/rich-automation/lotto-module/branch/main/graph/badge.svg?token=18IAW1OW77)](https://codecov.io/gh/rich-automation/lotto-module)
6
+
7
+ `@rich-automation/lotto`는 headless browser를 활용해 JS 환경에서 로또를 자동으로 구매할 수 있는 인터페이스를 제공합니다.
8
+
9
+ ## 설치
10
+
11
+ ```bash
12
+ # npm
13
+ npm install @rich-automation/lotto
14
+
15
+ # yarn
16
+ yarn add @rich-automation/lotto
17
+ ```
18
+
19
+ ## 준비 사항
20
+
21
+ 1. 내부적으로 Playwright 또는 Puppeteer를 사용하므로, Chromium이 사전에 설치되어 있어야 합니다. ([링크](https://github.com/rich-automation/lotto-module/blob/main/package.json#L38-L39))
22
+ 2. 구매는 [동행복권](https://dhlottery.co.kr/common.do?method=main) 사이트에서 진행되며, 예치금 충전 기능은 없으므로 미리 계정에 예치금을 충전해두어야 합니다.
23
+
24
+ ## 사용법
25
+
26
+ ### 기본 설정
27
+
28
+ ```js
29
+ import { LottoService } from '@rich-automation/lotto';
30
+ import { chromium } from 'playwright';
31
+ import puppeteer from 'puppeteer';
32
+
33
+ // playwright 로 시작, 모든 기능 사용 가능
34
+ const lottoService = new LottoService({
35
+ controller: chromium // puppeteer
36
+ });
37
+
38
+ // puppeteer 로 시작, 모든 기능 사용 가능
39
+ const lottoService = new LottoService({
40
+ controller: puppeteer
41
+ });
42
+
43
+ // API 모드로 시작, check / getCheckWinningLink 기능만 사용 가능
44
+ const lottoService = new LottoService({
45
+ controller: 'api'
46
+ });
47
+ ```
48
+
49
+ 옵션 설명:
50
+
51
+ - `controller`: (필수) `puppeteer`, `playwright` 모듈 또는 `"api"`
52
+ - `headless`: 기본값 `false`
53
+ - `defaultViewport`: 기본값 `{ width: 1080, height: 1024 }`
54
+ - `logLevel`: 기본값 `2` (NONE = -1, ERROR = 0, WARN = 1, INFO = 2, DEBUG = 3)
55
+
56
+ ```js
57
+ import { LottoService, LogLevel } from '@rich-automation/lotto';
58
+
59
+ const lottoService = new LottoService({
60
+ controller: chromium,
61
+ headless: true,
62
+ defaultViewport: { width: 1280, height: 720 },
63
+ logLevel: LogLevel.DEBUG
64
+ });
65
+ ```
66
+
67
+ ### 로또 구매
68
+
69
+ ```js
70
+ const ID = '<YOUR_ID>';
71
+ const PWD = '<YOUR_PASSWORD>';
72
+
73
+ await lottoService.signIn(ID, PWD);
74
+
75
+ const numbers = await lottoService.purchase(5);
76
+
77
+ console.log(numbers); // [[ 1, 14, 21, 27, 30, 44 ],[ 4, 5, 27, 29, 40, 44 ],[ 9, 18, 19, 24, 38, 42 ],[ 4, 6, 13, 20, 38, 39 ],[ 8, 9, 10, 19, 32, 40 ]]
78
+ ```
79
+
80
+ ### 당첨 확인
81
+
82
+ 이번 회차 확인:
83
+
84
+ ```js
85
+ import { getLastLottoRound } from '@rich-automation/lotto';
86
+
87
+ const numbers = [
88
+ [1, 2, 3, 4, 5, 6],
89
+ [5, 6, 7, 8, 9, 10]
90
+ ];
91
+
92
+ const currentRound = getLastLottoRound();
93
+
94
+ const result = await lottoService.check(numbers, currentRound);
95
+
96
+ console.log(result); // [{rank:1,matchedNumbers:[1,2,3,4,5,6]},{rank:5,matchedNumbers:[5,6]]
97
+ ```
98
+
99
+ 다음 회차 링크 생성:
100
+
101
+ ```js
102
+ import { getNextLottoRound } from '@rich-automation/lotto';
103
+
104
+ const nextRound = getNextLottoRound();
105
+ const link = lottoService.getCheckWinningLink(numbers, nextRound);
106
+
107
+ console.log(link); // "https://dhlottery.co.kr/qr.do?method=winQr&v=1071q010203040506q050607080910";
108
+ ```
109
+
110
+ ## API
111
+
112
+ ### `signIn(id: string, password: string): Promise<string>`
113
+
114
+ 동행복권 로그인, 성공 시 로그인 쿠키 반환
115
+
116
+ ### `signInWithCookie(cookies: string): Promise<string>`
117
+
118
+ 쿠키 기반 로그인
119
+
120
+ ### `purchase(amount?: number): Promise<number[][]>`
121
+
122
+ 로또 번호 자동 구매 (1~5 게임)
123
+
124
+ ### `check(numbers: number[][], round?: number): Promise<{ rank:number; matchedNumbers:number[] }[]>`
125
+
126
+ (API) 당첨 결과 확인
127
+
128
+ ### `getCheckWinningLink(numbers: number[][], round?: number): string`
129
+
130
+ (API) 당첨 확인 링크 생성
131
+
132
+ ### `destroy(): Promise<void>`
133
+
134
+ 브라우저 인스턴스 종료
@@ -9,5 +9,5 @@ exports.CONST = {
9
9
  BROWSER_PAGE_POPUP_WAIT: 1500,
10
10
  BROWSER_PAGE_DIALOG_WAIT: 10000,
11
11
  WEEK_TO_MILLISECOND: 604800000,
12
- THOUSAND_ROUND_DATE: '2022-01-29T11:50:00'
12
+ THOUSAND_ROUND_DATE: '2022-01-29T11:50:00Z'
13
13
  };
@@ -0,0 +1,28 @@
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.APIModeController = void 0;
13
+ class APIModeController {
14
+ constructor(configs, logger) {
15
+ this.focus = () => __awaiter(this, void 0, void 0, function* () {
16
+ throw new Error('APIModeController does not support focus method');
17
+ });
18
+ this.close = () => __awaiter(this, void 0, void 0, function* () {
19
+ this.logger.warn('APIModeController does not support close method');
20
+ });
21
+ this.cleanPages = () => __awaiter(this, void 0, void 0, function* () {
22
+ this.logger.warn('APIModeController does not support cleanPages method');
23
+ });
24
+ this.logger = logger;
25
+ this.configs = configs;
26
+ }
27
+ }
28
+ exports.APIModeController = APIModeController;
@@ -3,12 +3,26 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createBrowserController = void 0;
4
4
  const puppeteer_1 = require("./puppeteer");
5
5
  const playwright_1 = require("./playwright");
6
- function createBrowserController(name, configs, logger) {
7
- switch (name) {
8
- case 'puppeteer':
9
- return new puppeteer_1.PuppeteerController(configs, logger);
10
- case 'playwright':
11
- return new playwright_1.PlaywrightController(configs, logger);
6
+ const api_1 = require("./api");
7
+ function createBrowserController(configs, logger) {
8
+ if (isAPIMode(configs)) {
9
+ return new api_1.APIModeController(configs, logger);
12
10
  }
11
+ if (isPlaywright(configs)) {
12
+ return new playwright_1.PlaywrightController(configs, logger);
13
+ }
14
+ if (isPuppeteer(configs)) {
15
+ return new puppeteer_1.PuppeteerController(configs, logger);
16
+ }
17
+ throw new Error('Invalid browser controller');
13
18
  }
14
19
  exports.createBrowserController = createBrowserController;
20
+ function isAPIMode(configs) {
21
+ return configs.controller === 'api';
22
+ }
23
+ function isPlaywright(configs) {
24
+ return typeof configs.controller !== 'string' && 'connectOverCDP' in configs.controller;
25
+ }
26
+ function isPuppeteer(configs) {
27
+ return typeof configs.controller !== 'string' && 'executablePath' in configs.controller;
28
+ }
@@ -10,7 +10,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.PlaywrightController = void 0;
13
- const playwright_1 = require("playwright");
14
13
  const deferred_1 = require("../../utils/deferred");
15
14
  const playwright_page_1 = require("./playwright.page");
16
15
  const constants_1 = require("../../constants");
@@ -69,7 +68,7 @@ class PlaywrightController {
69
68
  });
70
69
  this.configs = configs;
71
70
  this.logger = logger;
72
- playwright_1.chromium.launch(this.configs).then((browser) => __awaiter(this, void 0, void 0, function* () {
71
+ this.configs.controller.launch(this.configs).then((browser) => __awaiter(this, void 0, void 0, function* () {
73
72
  this.browser = browser;
74
73
  this.context = yield browser.newContext();
75
74
  }));
@@ -8,12 +8,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
11
  Object.defineProperty(exports, "__esModule", { value: true });
15
12
  exports.PuppeteerController = void 0;
16
- const puppeteer_1 = __importDefault(require("puppeteer"));
17
13
  const deferred_1 = require("../../utils/deferred");
18
14
  const puppeteer_page_1 = require("./puppeteer.page");
19
15
  const constants_1 = require("../../constants");
@@ -71,8 +67,8 @@ class PuppeteerController {
71
67
  });
72
68
  this.configs = configs;
73
69
  this.logger = logger;
74
- puppeteer_1.default
75
- .launch(Object.assign(Object.assign({}, this.configs), { headless: this.configs.headless === true ? 'new' : this.configs.headless }))
70
+ configs.controller
71
+ .launch(Object.assign(Object.assign({}, this.configs), { headless: this.configs.headless === true }))
76
72
  .then((browser) => __awaiter(this, void 0, void 0, function* () {
77
73
  this.browser = browser;
78
74
  }));
package/lib/cjs/index.js CHANGED
@@ -14,11 +14,17 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.LogLevel = exports.getCurrentLottoRound = exports.LottoService = void 0;
17
+ exports.checkWinning = exports.getCheckWinningLink = exports.getNextLottoRound = exports.getLastLottoRound = exports.LogLevel = exports.LottoService = void 0;
18
18
  var lottoService_1 = require("./lottoService");
19
19
  Object.defineProperty(exports, "LottoService", { enumerable: true, get: function () { return lottoService_1.LottoService; } });
20
- var getCurrentLottoRound_1 = require("./utils/getCurrentLottoRound");
21
- Object.defineProperty(exports, "getCurrentLottoRound", { enumerable: true, get: function () { return getCurrentLottoRound_1.getCurrentLottoRound; } });
22
20
  var logger_1 = require("./logger");
23
21
  Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function () { return logger_1.LogLevel; } });
24
22
  __exportStar(require("./types"), exports);
23
+ var getLastLottoRound_1 = require("./utils/getLastLottoRound");
24
+ Object.defineProperty(exports, "getLastLottoRound", { enumerable: true, get: function () { return getLastLottoRound_1.getLastLottoRound; } });
25
+ var getNextLottoRound_1 = require("./utils/getNextLottoRound");
26
+ Object.defineProperty(exports, "getNextLottoRound", { enumerable: true, get: function () { return getNextLottoRound_1.getNextLottoRound; } });
27
+ var getCheckWinningLink_1 = require("./utils/getCheckWinningLink");
28
+ Object.defineProperty(exports, "getCheckWinningLink", { enumerable: true, get: function () { return getCheckWinningLink_1.getCheckWinningLink; } });
29
+ var checkWinning_1 = require("./utils/checkWinning");
30
+ Object.defineProperty(exports, "checkWinning", { enumerable: true, get: function () { return checkWinning_1.checkWinning; } });
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const invertObject_1 = require("./utils/invertObject");
4
4
  const BaseErrorCode = {
5
5
  NETWORK_ERROR: 100001,
6
+ NOT_SUPPORTED: 110000,
6
7
  UNKNOWN_ERROR: 199999
7
8
  };
8
9
  const LoginErrorCode = {
@@ -25,7 +26,8 @@ const ErrorMessage = {
25
26
  [ErrorCode.INVALID_ROUND]: '로또 회차가 올바르지 않습니다.',
26
27
  [ErrorCode.INVALID_LOTTO_NUMBER]: '로또 번호가 올바르지 않습니다.',
27
28
  [ErrorCode.NOT_AUTHENTICATED]: '인증되지 않았습니다.',
28
- [ErrorCode.PURCHASE_UNAVAILABLE]: '현재는 로또 구매가 불가능합니다.'
29
+ [ErrorCode.PURCHASE_UNAVAILABLE]: '현재는 로또 구매가 불가능합니다.',
30
+ [ErrorCode.NOT_SUPPORTED]: '지원되지 않는 기능입니다.'
29
31
  };
30
32
  class LottoError extends Error {
31
33
  static NetworkError() {
@@ -52,6 +54,9 @@ class LottoError extends Error {
52
54
  static PurchaseUnavailable() {
53
55
  return new LottoError(ErrorCode.PURCHASE_UNAVAILABLE);
54
56
  }
57
+ static NotSupported(message) {
58
+ return new LottoError(ErrorCode.NOT_SUPPORTED, message);
59
+ }
55
60
  static get code() {
56
61
  return ErrorCode;
57
62
  }
@@ -21,22 +21,28 @@ const deferred_1 = require("./utils/deferred");
21
21
  const constants_1 = require("./constants");
22
22
  const lazyRun_1 = require("./utils/lazyRun");
23
23
  const logger_1 = __importDefault(require("./logger"));
24
- const getCurrentLottoRound_1 = require("./utils/getCurrentLottoRound");
24
+ const getLastLottoRound_1 = require("./utils/getLastLottoRound");
25
25
  const validateLottoNumber_1 = require("./utils/validateLottoNumber");
26
26
  const getWinningNumbers_1 = require("./apis/dhlottery/getWinningNumbers");
27
27
  const checkWinning_1 = require("./utils/checkWinning");
28
28
  const validatePurchaseAvailability_1 = require("./utils/validatePurchaseAvailability");
29
29
  const getCheckWinningLink_1 = require("./utils/getCheckWinningLink");
30
+ const getNextLottoRound_1 = require("./utils/getNextLottoRound");
30
31
  class LottoService {
31
32
  constructor(configs) {
32
- var _a;
33
33
  this.context = {
34
34
  authenticated: false
35
35
  };
36
36
  this.destroy = () => __awaiter(this, void 0, void 0, function* () {
37
+ if (this.browserController.configs.controller === 'api') {
38
+ throw lottoError_1.default.NotSupported('API mode does not support destroy.');
39
+ }
37
40
  return (0, lazyRun_1.lazyRun)(this.browserController.close, constants_1.CONST.BROWSER_DESTROY_SAFE_TIMEOUT);
38
41
  });
39
42
  this.signInWithCookie = (cookies) => __awaiter(this, void 0, void 0, function* () {
43
+ if (this.browserController.configs.controller === 'api') {
44
+ throw lottoError_1.default.NotSupported('API mode does not support signInWithCookie.');
45
+ }
40
46
  // 쿠키 설정 & 페이지 이동
41
47
  const page = yield this.browserController.focus(0);
42
48
  this.logger.debug('[signInWithCookie]', 'setCookies');
@@ -58,6 +64,9 @@ class LottoService {
58
64
  return page.getCookies();
59
65
  });
60
66
  this.signIn = (id, password) => __awaiter(this, void 0, void 0, function* () {
67
+ if (this.browserController.configs.controller === 'api') {
68
+ throw lottoError_1.default.NotSupported('API mode does not support signIn.');
69
+ }
61
70
  const p = (0, deferred_1.deferred)();
62
71
  queueMicrotask(() => __awaiter(this, void 0, void 0, function* () {
63
72
  // 페이지 이동
@@ -98,6 +107,9 @@ class LottoService {
98
107
  return p.promise;
99
108
  });
100
109
  this.purchase = (amount = 5) => __awaiter(this, void 0, void 0, function* () {
110
+ if (this.browserController.configs.controller === 'api') {
111
+ throw lottoError_1.default.NotSupported('API mode does not support purchase.');
112
+ }
101
113
  if (!this.context.authenticated)
102
114
  throw lottoError_1.default.NotAuthenticated();
103
115
  this.logger.debug('[purchase]', 'validatePurchaseAvailability');
@@ -131,18 +143,18 @@ class LottoService {
131
143
  return elems.map(it => Array.from(it.children).map(child => Number(child.innerHTML)));
132
144
  });
133
145
  });
134
- this.check = (numbers, round = (0, getCurrentLottoRound_1.getCurrentLottoRound)()) => __awaiter(this, void 0, void 0, function* () {
135
- (0, validateLottoNumber_1.validateLottoNumber)(numbers);
146
+ this.check = (numbers, round = (0, getLastLottoRound_1.getLastLottoRound)()) => __awaiter(this, void 0, void 0, function* () {
147
+ numbers.forEach(number => (0, validateLottoNumber_1.validateLottoNumber)(number));
136
148
  this.logger.debug('[check]', 'getWinningNumbers');
137
149
  const winningNumbers = yield (0, getWinningNumbers_1.getWinningNumbers)(round);
138
- return (0, checkWinning_1.checkWinning)(numbers, winningNumbers);
150
+ return numbers.map(game => (0, checkWinning_1.checkWinning)(game, winningNumbers));
139
151
  });
140
- this.getCheckWinningLink = (round, numbers) => {
152
+ this.getCheckWinningLink = (numbers, round = (0, getNextLottoRound_1.getNextLottoRound)()) => {
141
153
  this.logger.debug('[getCheckWinningLink]', 'getCheckWinningLink');
142
- return (0, getCheckWinningLink_1.getCheckWinningLink)(round, numbers);
154
+ return (0, getCheckWinningLink_1.getCheckWinningLink)(numbers, round);
143
155
  };
144
- this.logger = new logger_1.default(configs === null || configs === void 0 ? void 0 : configs.logLevel, '[LottoService]');
145
- this.browserController = (0, factory_1.createBrowserController)((_a = configs === null || configs === void 0 ? void 0 : configs.controller) !== null && _a !== void 0 ? _a : 'playwright', Object.assign({ defaultViewport: { width: 1080, height: 1024 } }, configs), this.logger);
156
+ this.logger = new logger_1.default(configs.logLevel, '[LottoService]');
157
+ this.browserController = (0, factory_1.createBrowserController)(Object.assign({ defaultViewport: { width: 1080, height: 1024 } }, configs), this.logger);
146
158
  }
147
159
  }
148
160
  exports.LottoService = LottoService;
@@ -1,16 +1,7 @@
1
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
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
3
  exports.checkWinning = void 0;
13
- const checkWinning = (myNumber, winningNumbers) => __awaiter(void 0, void 0, void 0, function* () {
4
+ const checkWinning = (myNumber, winningNumbers) => {
14
5
  const mainWinningNumbers = winningNumbers.slice(0, 6);
15
6
  const bonusNumber = winningNumbers.at(-1);
16
7
  const matchedNumbers = myNumber.filter(n => mainWinningNumbers.includes(n));
@@ -33,5 +24,5 @@ const checkWinning = (myNumber, winningNumbers) => __awaiter(void 0, void 0, voi
33
24
  rank = 5;
34
25
  }
35
26
  return { rank, matchedNumbers };
36
- });
27
+ };
37
28
  exports.checkWinning = checkWinning;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getCheckWinningLink = void 0;
4
4
  const urls_1 = require("../constants/urls");
5
- function getCheckWinningLink(round, numbers) {
5
+ function getCheckWinningLink(numbers, round) {
6
6
  const nums = numbers.map(it => 'q' + it.map(n => String(n).padStart(2, '0')).join('')).join('');
7
7
  return `${urls_1.URLS.CHECK_WINNING}?method=winQr&v=${round}${nums}`;
8
8
  }
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getCurrentLottoRound = void 0;
3
+ exports.getLastLottoRound = void 0;
4
4
  const constants_1 = require("../constants");
5
- const getCurrentLottoRound = () => {
5
+ const getLastLottoRound = () => {
6
6
  const standardDate = new Date(constants_1.CONST.THOUSAND_ROUND_DATE);
7
7
  const now = new Date(global.Date.now());
8
8
  const ADDITIONAL_ROUND = Math.floor((now.getTime() - standardDate.getTime()) / constants_1.CONST.WEEK_TO_MILLISECOND);
9
9
  return 1000 + ADDITIONAL_ROUND;
10
10
  };
11
- exports.getCurrentLottoRound = getCurrentLottoRound;
11
+ exports.getLastLottoRound = getLastLottoRound;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getNextLottoRound = void 0;
4
+ const constants_1 = require("../constants");
5
+ const getNextLottoRound = () => {
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) + 1;
9
+ return 1000 + ADDITIONAL_ROUND;
10
+ };
11
+ exports.getNextLottoRound = getNextLottoRound;
@@ -6,5 +6,5 @@ export const CONST = {
6
6
  BROWSER_PAGE_POPUP_WAIT: 1500,
7
7
  BROWSER_PAGE_DIALOG_WAIT: 10000,
8
8
  WEEK_TO_MILLISECOND: 604800000,
9
- THOUSAND_ROUND_DATE: '2022-01-29T11:50:00'
9
+ THOUSAND_ROUND_DATE: '2022-01-29T11:50:00Z'
10
10
  };
@@ -0,0 +1,25 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import {} from '../../logger';
11
+ export class APIModeController {
12
+ constructor(configs, logger) {
13
+ this.focus = () => __awaiter(this, void 0, void 0, function* () {
14
+ throw new Error('APIModeController does not support focus method');
15
+ });
16
+ this.close = () => __awaiter(this, void 0, void 0, function* () {
17
+ this.logger.warn('APIModeController does not support close method');
18
+ });
19
+ this.cleanPages = () => __awaiter(this, void 0, void 0, function* () {
20
+ this.logger.warn('APIModeController does not support cleanPages method');
21
+ });
22
+ this.logger = logger;
23
+ this.configs = configs;
24
+ }
25
+ }
@@ -1,10 +1,24 @@
1
1
  import { PuppeteerController } from './puppeteer';
2
2
  import { PlaywrightController } from './playwright';
3
- export function createBrowserController(name, configs, logger) {
4
- switch (name) {
5
- case 'puppeteer':
6
- return new PuppeteerController(configs, logger);
7
- case 'playwright':
8
- return new PlaywrightController(configs, logger);
3
+ import { APIModeController } from './api';
4
+ export function createBrowserController(configs, logger) {
5
+ if (isAPIMode(configs)) {
6
+ return new APIModeController(configs, logger);
9
7
  }
8
+ if (isPlaywright(configs)) {
9
+ return new PlaywrightController(configs, logger);
10
+ }
11
+ if (isPuppeteer(configs)) {
12
+ return new PuppeteerController(configs, logger);
13
+ }
14
+ throw new Error('Invalid browser controller');
15
+ }
16
+ function isAPIMode(configs) {
17
+ return configs.controller === 'api';
18
+ }
19
+ function isPlaywright(configs) {
20
+ return typeof configs.controller !== 'string' && 'connectOverCDP' in configs.controller;
21
+ }
22
+ function isPuppeteer(configs) {
23
+ return typeof configs.controller !== 'string' && 'executablePath' in configs.controller;
10
24
  }
@@ -7,7 +7,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { chromium } from 'playwright';
11
10
  import { deferred } from '../../utils/deferred';
12
11
  import { PlaywrightPage } from './playwright.page';
13
12
  import { CONST } from '../../constants';
@@ -67,7 +66,7 @@ export class PlaywrightController {
67
66
  });
68
67
  this.configs = configs;
69
68
  this.logger = logger;
70
- chromium.launch(this.configs).then((browser) => __awaiter(this, void 0, void 0, function* () {
69
+ this.configs.controller.launch(this.configs).then((browser) => __awaiter(this, void 0, void 0, function* () {
71
70
  this.browser = browser;
72
71
  this.context = yield browser.newContext();
73
72
  }));
@@ -7,7 +7,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import puppeteer, { Browser } from 'puppeteer';
11
10
  import { deferred } from '../../utils/deferred';
12
11
  import { PuppeteerPage } from './puppeteer.page';
13
12
  import { CONST } from '../../constants';
@@ -66,8 +65,8 @@ export class PuppeteerController {
66
65
  });
67
66
  this.configs = configs;
68
67
  this.logger = logger;
69
- puppeteer
70
- .launch(Object.assign(Object.assign({}, this.configs), { headless: this.configs.headless === true ? 'new' : this.configs.headless }))
68
+ configs.controller
69
+ .launch(Object.assign(Object.assign({}, this.configs), { headless: this.configs.headless === true }))
71
70
  .then((browser) => __awaiter(this, void 0, void 0, function* () {
72
71
  this.browser = browser;
73
72
  }));
@@ -7,7 +7,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { Page } from 'puppeteer';
11
10
  import { deferred } from '../../utils/deferred';
12
11
  import { lazyRun } from '../../utils/lazyRun';
13
12
  export class PuppeteerPage {
package/lib/esm/index.js CHANGED
@@ -1,4 +1,7 @@
1
1
  export { LottoService } from './lottoService';
2
- export { getCurrentLottoRound } from './utils/getCurrentLottoRound';
3
2
  export { LogLevel } from './logger';
4
3
  export * from './types';
4
+ export { getLastLottoRound } from './utils/getLastLottoRound';
5
+ export { getNextLottoRound } from './utils/getNextLottoRound';
6
+ export { getCheckWinningLink } from './utils/getCheckWinningLink';
7
+ export { checkWinning } from './utils/checkWinning';
@@ -1,6 +1,7 @@
1
1
  import { invertObject } from './utils/invertObject';
2
2
  const BaseErrorCode = {
3
3
  NETWORK_ERROR: 100001,
4
+ NOT_SUPPORTED: 110000,
4
5
  UNKNOWN_ERROR: 199999
5
6
  };
6
7
  const LoginErrorCode = {
@@ -23,7 +24,8 @@ const ErrorMessage = {
23
24
  [ErrorCode.INVALID_ROUND]: '로또 회차가 올바르지 않습니다.',
24
25
  [ErrorCode.INVALID_LOTTO_NUMBER]: '로또 번호가 올바르지 않습니다.',
25
26
  [ErrorCode.NOT_AUTHENTICATED]: '인증되지 않았습니다.',
26
- [ErrorCode.PURCHASE_UNAVAILABLE]: '현재는 로또 구매가 불가능합니다.'
27
+ [ErrorCode.PURCHASE_UNAVAILABLE]: '현재는 로또 구매가 불가능합니다.',
28
+ [ErrorCode.NOT_SUPPORTED]: '지원되지 않는 기능입니다.'
27
29
  };
28
30
  export default class LottoError extends Error {
29
31
  static NetworkError() {
@@ -50,6 +52,9 @@ export default class LottoError extends Error {
50
52
  static PurchaseUnavailable() {
51
53
  return new LottoError(ErrorCode.PURCHASE_UNAVAILABLE);
52
54
  }
55
+ static NotSupported(message) {
56
+ return new LottoError(ErrorCode.NOT_SUPPORTED, message);
57
+ }
53
58
  static get code() {
54
59
  return ErrorCode;
55
60
  }
@@ -15,22 +15,28 @@ import { deferred } from './utils/deferred';
15
15
  import { CONST } from './constants';
16
16
  import { lazyRun } from './utils/lazyRun';
17
17
  import Logger, {} from './logger';
18
- import { getCurrentLottoRound } from './utils/getCurrentLottoRound';
18
+ import { getLastLottoRound } from './utils/getLastLottoRound';
19
19
  import { validateLottoNumber } from './utils/validateLottoNumber';
20
20
  import { getWinningNumbers } from './apis/dhlottery/getWinningNumbers';
21
21
  import { checkWinning } from './utils/checkWinning';
22
22
  import { validatePurchaseAvailability } from './utils/validatePurchaseAvailability';
23
23
  import { getCheckWinningLink } from './utils/getCheckWinningLink';
24
+ import { getNextLottoRound } from './utils/getNextLottoRound';
24
25
  export class LottoService {
25
26
  constructor(configs) {
26
- var _a;
27
27
  this.context = {
28
28
  authenticated: false
29
29
  };
30
30
  this.destroy = () => __awaiter(this, void 0, void 0, function* () {
31
+ if (this.browserController.configs.controller === 'api') {
32
+ throw LottoError.NotSupported('API mode does not support destroy.');
33
+ }
31
34
  return lazyRun(this.browserController.close, CONST.BROWSER_DESTROY_SAFE_TIMEOUT);
32
35
  });
33
36
  this.signInWithCookie = (cookies) => __awaiter(this, void 0, void 0, function* () {
37
+ if (this.browserController.configs.controller === 'api') {
38
+ throw LottoError.NotSupported('API mode does not support signInWithCookie.');
39
+ }
34
40
  // 쿠키 설정 & 페이지 이동
35
41
  const page = yield this.browserController.focus(0);
36
42
  this.logger.debug('[signInWithCookie]', 'setCookies');
@@ -52,6 +58,9 @@ export class LottoService {
52
58
  return page.getCookies();
53
59
  });
54
60
  this.signIn = (id, password) => __awaiter(this, void 0, void 0, function* () {
61
+ if (this.browserController.configs.controller === 'api') {
62
+ throw LottoError.NotSupported('API mode does not support signIn.');
63
+ }
55
64
  const p = deferred();
56
65
  queueMicrotask(() => __awaiter(this, void 0, void 0, function* () {
57
66
  // 페이지 이동
@@ -92,6 +101,9 @@ export class LottoService {
92
101
  return p.promise;
93
102
  });
94
103
  this.purchase = (amount = 5) => __awaiter(this, void 0, void 0, function* () {
104
+ if (this.browserController.configs.controller === 'api') {
105
+ throw LottoError.NotSupported('API mode does not support purchase.');
106
+ }
95
107
  if (!this.context.authenticated)
96
108
  throw LottoError.NotAuthenticated();
97
109
  this.logger.debug('[purchase]', 'validatePurchaseAvailability');
@@ -125,17 +137,17 @@ export class LottoService {
125
137
  return elems.map(it => Array.from(it.children).map(child => Number(child.innerHTML)));
126
138
  });
127
139
  });
128
- this.check = (numbers, round = getCurrentLottoRound()) => __awaiter(this, void 0, void 0, function* () {
129
- validateLottoNumber(numbers);
140
+ this.check = (numbers, round = getLastLottoRound()) => __awaiter(this, void 0, void 0, function* () {
141
+ numbers.forEach(number => validateLottoNumber(number));
130
142
  this.logger.debug('[check]', 'getWinningNumbers');
131
143
  const winningNumbers = yield getWinningNumbers(round);
132
- return checkWinning(numbers, winningNumbers);
144
+ return numbers.map(game => checkWinning(game, winningNumbers));
133
145
  });
134
- this.getCheckWinningLink = (round, numbers) => {
146
+ this.getCheckWinningLink = (numbers, round = getNextLottoRound()) => {
135
147
  this.logger.debug('[getCheckWinningLink]', 'getCheckWinningLink');
136
- return getCheckWinningLink(round, numbers);
148
+ return getCheckWinningLink(numbers, round);
137
149
  };
138
- this.logger = new Logger(configs === null || configs === void 0 ? void 0 : configs.logLevel, '[LottoService]');
139
- this.browserController = createBrowserController((_a = configs === null || configs === void 0 ? void 0 : configs.controller) !== null && _a !== void 0 ? _a : 'playwright', Object.assign({ defaultViewport: { width: 1080, height: 1024 } }, configs), this.logger);
150
+ this.logger = new Logger(configs.logLevel, '[LottoService]');
151
+ this.browserController = createBrowserController(Object.assign({ defaultViewport: { width: 1080, height: 1024 } }, configs), this.logger);
140
152
  }
141
153
  }
@@ -1,13 +1,4 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- export const checkWinning = (myNumber, winningNumbers) => __awaiter(void 0, void 0, void 0, function* () {
1
+ export const checkWinning = (myNumber, winningNumbers) => {
11
2
  const mainWinningNumbers = winningNumbers.slice(0, 6);
12
3
  const bonusNumber = winningNumbers.at(-1);
13
4
  const matchedNumbers = myNumber.filter(n => mainWinningNumbers.includes(n));
@@ -30,4 +21,4 @@ export const checkWinning = (myNumber, winningNumbers) => __awaiter(void 0, void
30
21
  rank = 5;
31
22
  }
32
23
  return { rank, matchedNumbers };
33
- });
24
+ };
@@ -1,5 +1,5 @@
1
1
  import { URLS } from '../constants/urls';
2
- export function getCheckWinningLink(round, numbers) {
2
+ export function getCheckWinningLink(numbers, round) {
3
3
  const nums = numbers.map(it => 'q' + it.map(n => String(n).padStart(2, '0')).join('')).join('');
4
4
  return `${URLS.CHECK_WINNING}?method=winQr&v=${round}${nums}`;
5
5
  }
@@ -1,5 +1,5 @@
1
1
  import { CONST } from '../constants';
2
- export const getCurrentLottoRound = () => {
2
+ export const getLastLottoRound = () => {
3
3
  const standardDate = new Date(CONST.THOUSAND_ROUND_DATE);
4
4
  const now = new Date(global.Date.now());
5
5
  const ADDITIONAL_ROUND = Math.floor((now.getTime() - standardDate.getTime()) / CONST.WEEK_TO_MILLISECOND);
@@ -0,0 +1,7 @@
1
+ import { CONST } from '../constants';
2
+ export const getNextLottoRound = () => {
3
+ const standardDate = new Date(CONST.THOUSAND_ROUND_DATE);
4
+ const now = new Date(global.Date.now());
5
+ const ADDITIONAL_ROUND = Math.floor((now.getTime() - standardDate.getTime()) / CONST.WEEK_TO_MILLISECOND) + 1;
6
+ return 1000 + ADDITIONAL_ROUND;
7
+ };
@@ -0,0 +1,13 @@
1
+ import type { BrowserConfigs, BrowserControllerInterface } from '../../types';
2
+ import type { Browser, BrowserContext } from 'playwright';
3
+ import { type LoggerInterface } from '../../logger';
4
+ export declare class APIModeController implements BrowserControllerInterface {
5
+ configs: BrowserConfigs;
6
+ logger: LoggerInterface;
7
+ browser: Browser;
8
+ context: BrowserContext;
9
+ constructor(configs: BrowserConfigs, logger: LoggerInterface);
10
+ focus: () => Promise<never>;
11
+ close: () => Promise<void>;
12
+ cleanPages: () => Promise<void>;
13
+ }
@@ -1,3 +1,3 @@
1
- import type { BrowserConfigs, BrowserControllerInterface } from '../types';
1
+ import type { BrowserConfigs, BrowserController, BrowserControllerInterface } from '../types';
2
2
  import type { LoggerInterface } from '../logger';
3
- export declare function createBrowserController(name: 'puppeteer' | 'playwright', configs: BrowserConfigs, logger: LoggerInterface): BrowserControllerInterface;
3
+ export declare function createBrowserController<T extends BrowserController>(configs: BrowserConfigs<T>, logger: LoggerInterface): BrowserControllerInterface;
@@ -1,13 +1,14 @@
1
1
  import type { BrowserConfigs, BrowserControllerInterface } from '../../types';
2
2
  import type { Browser, BrowserContext } from 'playwright';
3
+ import type { BrowserType } from 'playwright-core';
3
4
  import { PlaywrightPage } from './playwright.page';
4
5
  import { type LoggerInterface } from '../../logger';
5
- export declare class PlaywrightController implements BrowserControllerInterface {
6
- configs: BrowserConfigs;
6
+ export declare class PlaywrightController implements BrowserControllerInterface<BrowserType> {
7
+ configs: BrowserConfigs<BrowserType>;
7
8
  logger: LoggerInterface;
8
9
  browser: Browser;
9
10
  context: BrowserContext;
10
- constructor(configs: BrowserConfigs, logger: LoggerInterface);
11
+ constructor(configs: BrowserConfigs<BrowserType>, logger: LoggerInterface);
11
12
  private getBrowserContext;
12
13
  focus: (pageIndex?: number) => Promise<PlaywrightPage>;
13
14
  close: () => Promise<void>;
@@ -1,12 +1,12 @@
1
1
  import type { BrowserConfigs, BrowserControllerInterface } from '../../types';
2
- import { Browser } from 'puppeteer';
3
2
  import { PuppeteerPage } from './puppeteer.page';
4
3
  import { type LoggerInterface } from '../../logger';
5
- export declare class PuppeteerController implements BrowserControllerInterface {
6
- configs: BrowserConfigs;
4
+ import type { PuppeteerNode, Browser } from 'puppeteer';
5
+ export declare class PuppeteerController implements BrowserControllerInterface<PuppeteerNode> {
6
+ configs: BrowserConfigs<PuppeteerNode>;
7
7
  logger: LoggerInterface;
8
8
  browser: Browser;
9
- constructor(configs: BrowserConfigs, logger: LoggerInterface);
9
+ constructor(configs: BrowserConfigs<PuppeteerNode>, logger: LoggerInterface);
10
10
  private getBrowser;
11
11
  focus: (pageIndex?: number) => Promise<PuppeteerPage>;
12
12
  close: () => Promise<void>;
@@ -1,5 +1,5 @@
1
1
  import type { BrowserPageEvents, BrowserPageInterface, FakeDOMElement, StringifiedCookies } from '../../types';
2
- import { Page } from 'puppeteer';
2
+ import type { Page } from 'puppeteer';
3
3
  import type { LoggerInterface } from '../../logger';
4
4
  export declare class PuppeteerPage implements BrowserPageInterface {
5
5
  page: Page;
@@ -1,4 +1,7 @@
1
1
  export { LottoService } from './lottoService';
2
- export { getCurrentLottoRound } from './utils/getCurrentLottoRound';
3
2
  export { LogLevel } from './logger';
4
3
  export * from './types';
4
+ export { getLastLottoRound } from './utils/getLastLottoRound';
5
+ export { getNextLottoRound } from './utils/getNextLottoRound';
6
+ export { getCheckWinningLink } from './utils/getCheckWinningLink';
7
+ export { checkWinning } from './utils/checkWinning';
@@ -6,6 +6,7 @@ declare const ErrorCode: {
6
6
  CREDENTIALS_INCORRECT: 200001;
7
7
  INVALID_COOKIE: 200002;
8
8
  NETWORK_ERROR: 100001;
9
+ NOT_SUPPORTED: 110000;
9
10
  UNKNOWN_ERROR: 199999;
10
11
  };
11
12
  type ErrorCodeNumber = (typeof ErrorCode)[keyof typeof ErrorCode];
@@ -18,6 +19,7 @@ export default class LottoError extends Error {
18
19
  static InvalidLottoNumber(): LottoError;
19
20
  static NotAuthenticated(): LottoError;
20
21
  static PurchaseUnavailable(): LottoError;
22
+ static NotSupported(message?: string): LottoError;
21
23
  static get code(): {
22
24
  INVALID_ROUND: 300001;
23
25
  INVALID_LOTTO_NUMBER: 300002;
@@ -26,10 +28,11 @@ export default class LottoError extends Error {
26
28
  CREDENTIALS_INCORRECT: 200001;
27
29
  INVALID_COOKIE: 200002;
28
30
  NETWORK_ERROR: 100001;
31
+ NOT_SUPPORTED: 110000;
29
32
  UNKNOWN_ERROR: 199999;
30
33
  };
31
34
  static getMessage(code: ErrorCodeNumber): string;
32
- static getName(code: ErrorCodeNumber): "INVALID_ROUND" | "INVALID_LOTTO_NUMBER" | "NOT_AUTHENTICATED" | "PURCHASE_UNAVAILABLE" | "CREDENTIALS_INCORRECT" | "INVALID_COOKIE" | "NETWORK_ERROR" | "UNKNOWN_ERROR";
35
+ static getName(code: ErrorCodeNumber): "INVALID_ROUND" | "INVALID_LOTTO_NUMBER" | "NOT_AUTHENTICATED" | "PURCHASE_UNAVAILABLE" | "CREDENTIALS_INCORRECT" | "INVALID_COOKIE" | "NETWORK_ERROR" | "NOT_SUPPORTED" | "UNKNOWN_ERROR";
33
36
  code: number;
34
37
  constructor(code: ErrorCodeNumber, message?: string);
35
38
  }
@@ -6,14 +6,14 @@ export declare class LottoService implements LottoServiceInterface {
6
6
  };
7
7
  browserController: BrowserControllerInterface;
8
8
  logger: LoggerInterface;
9
- constructor(configs?: BrowserConfigs);
9
+ constructor(configs: BrowserConfigs);
10
10
  destroy: () => Promise<void>;
11
11
  signInWithCookie: (cookies: string) => Promise<string>;
12
12
  signIn: (id: string, password: string) => Promise<string>;
13
13
  purchase: (amount?: number) => Promise<number[][]>;
14
- check: (numbers: number[], round?: number) => Promise<{
14
+ check: (numbers: number[][], round?: number) => Promise<{
15
15
  rank: number;
16
16
  matchedNumbers: number[];
17
- }>;
18
- getCheckWinningLink: (round: number, numbers: number[][]) => string;
17
+ }[]>;
18
+ getCheckWinningLink: (numbers: number[][], round?: number) => string;
19
19
  }
@@ -1,17 +1,20 @@
1
1
  import type { LogLevel } from './logger';
2
+ import type { PuppeteerNode } from 'puppeteer';
3
+ import type { BrowserType } from 'playwright-core';
2
4
  export interface LottoServiceInterface {
3
5
  destroy(): Promise<void>;
4
6
  signIn(id: string, password: string): Promise<string>;
5
7
  signInWithCookie(cookie: string): Promise<string>;
6
- check(numbers: number[], volume?: number): Promise<{
8
+ check(numbers: number[][], volume?: number): Promise<{
7
9
  rank: number;
8
10
  matchedNumbers: number[];
9
- }>;
11
+ }[]>;
10
12
  purchase(amount: number): Promise<number[][]>;
11
- getCheckWinningLink(round: number, numbers: number[][]): string;
13
+ getCheckWinningLink(numbers: number[][], round: number): string;
12
14
  }
13
- export interface BrowserConfigs {
14
- controller?: 'puppeteer' | 'playwright';
15
+ export type BrowserController = PuppeteerNode | BrowserType | 'api';
16
+ export interface BrowserConfigs<T extends BrowserController = BrowserController> {
17
+ controller: T;
15
18
  logLevel?: LogLevel;
16
19
  headless?: boolean;
17
20
  defaultViewport?: {
@@ -21,8 +24,8 @@ export interface BrowserConfigs {
21
24
  [key: string]: unknown;
22
25
  args?: string[];
23
26
  }
24
- export interface BrowserControllerInterface {
25
- configs: BrowserConfigs;
27
+ export interface BrowserControllerInterface<T extends BrowserController = BrowserController> {
28
+ configs: BrowserConfigs<T>;
26
29
  focus(pageIndex?: number): Promise<BrowserPageInterface>;
27
30
  cleanPages(remainingPageIndex: number[]): Promise<void>;
28
31
  close(): Promise<void>;
@@ -1,4 +1,4 @@
1
- export declare const checkWinning: (myNumber: number[], winningNumbers: number[]) => Promise<{
1
+ export declare const checkWinning: (myNumber: number[], winningNumbers: number[]) => {
2
2
  rank: number;
3
3
  matchedNumbers: number[];
4
- }>;
4
+ };
@@ -1 +1 @@
1
- export declare function getCheckWinningLink(round: number, numbers: number[][]): string;
1
+ export declare function getCheckWinningLink(numbers: number[][], round: number): string;
@@ -0,0 +1 @@
1
+ export declare const getLastLottoRound: () => number;
@@ -0,0 +1 @@
1
+ export declare const getNextLottoRound: () => number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rich-automation/lotto",
3
- "version": "0.1.7",
3
+ "version": "2.0.0",
4
4
  "description": "Lotto module",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -35,7 +35,7 @@
35
35
  "build:esm": "tsc --project tsconfig.esm.json && echo '{\"type\": \"module\"}' > lib/esm/package.json",
36
36
  "build:dts": "tsc --project tsconfig.json --emitDeclarationOnly --declaration --declarationDir lib/typescript",
37
37
  "test": "jest --forceExit --detectOpenHandles",
38
- "install:puppeteer": "node ./node_modules/puppeteer/install.js",
38
+ "install:puppeteer": "node ./node_modules/puppeteer/install.mjs",
39
39
  "install:playwright": "npx playwright install chromium --with-deps",
40
40
  "fix": "yarn fix:eslint && yarn fix:prettier",
41
41
  "fix:eslint": "eslint --fix src --ext js,jsx,ts,tsx ",
@@ -46,11 +46,21 @@
46
46
  "lint:prettier": "prettier --check \"src/**/*.{ts,tsx,js}\""
47
47
  },
48
48
  "dependencies": {
49
- "axios": "^1.3.5",
50
- "dayjs": "^1.11.7",
49
+ "axios": "^1.8.4",
50
+ "dayjs": "^1.11.13"
51
+ },
52
+ "peerDependencies": {
51
53
  "playwright": "^1.35.0",
52
54
  "puppeteer": "^20.5.0"
53
55
  },
56
+ "peerDependenciesMeta": {
57
+ "playwright": {
58
+ "optional": true
59
+ },
60
+ "puppeteer": {
61
+ "optional": true
62
+ }
63
+ },
54
64
  "devDependencies": {
55
65
  "@babel/core": "^7.21.4",
56
66
  "@babel/preset-env": "^7.21.4",
@@ -64,7 +74,9 @@
64
74
  "eslint-config-prettier": "^8.8.0",
65
75
  "eslint-plugin-prettier": "^4.2.1",
66
76
  "jest": "^29.5.0",
77
+ "playwright": "^1.51.1",
67
78
  "prettier": "^2.8.7",
79
+ "puppeteer": "^24.6.1",
68
80
  "release-it": "^15.10.3",
69
81
  "ts-node": "^10.9.1",
70
82
  "typescript": "^5.0.4"
@@ -1 +0,0 @@
1
- export declare const getCurrentLottoRound: () => number;