From b8f093757852ebb3c090189fd7c567176f2f5754 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Thu, 10 Feb 2022 19:12:00 +0900 Subject: [PATCH 1/7] =?UTF-8?q?`Naver`=20=EC=9D=98=20export=20=EB=A5=BC=20?= =?UTF-8?q?=EC=A0=84=EB=B6=80=20named=20export=20=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/naver/index.ts | 8 ++++---- src/app/naver/module.ts | 2 +- src/app/naver/moduleFactory.ts | 6 +++--- src/app/naver/pageInteractor.ts | 3 +-- src/app/naver/service.ts | 6 +++--- src/app/naver/urlChanger.test.ts | 2 +- src/app/naver/urlChanger.ts | 2 +- 7 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/app/naver/index.ts b/src/app/naver/index.ts index 98bde9b..58c7c70 100644 --- a/src/app/naver/index.ts +++ b/src/app/naver/index.ts @@ -1,8 +1,8 @@ import { NaverModule } from "./module"; -import ModuleFactory from "./moduleFactory"; -import URLChanger from "./urlChanger"; -import PageInteractor, { LoginEvent, CaptchaStatus } from "./pageInteractor"; -import Service from "./service"; +import { ModuleFactory } from "./moduleFactory"; +import { URLChanger } from "./urlChanger"; +import { LoginEvent, CaptchaStatus, PageInteractor } from "./pageInteractor"; +import { Service } from "./service"; import { NaverScraper } from "./scraper"; import { NaverParser } from "./parser"; diff --git a/src/app/naver/module.ts b/src/app/naver/module.ts index cf8594c..d8d5132 100644 --- a/src/app/naver/module.ts +++ b/src/app/naver/module.ts @@ -1,6 +1,6 @@ import { URLChanger, PageInteractor, NaverScraper, NaverParser } from "."; -export default interface Module { +export interface NaverModule { readonly urlChanger: URLChanger; readonly pageInteractor: PageInteractor; readonly scraper: NaverScraper; diff --git a/src/app/naver/moduleFactory.ts b/src/app/naver/moduleFactory.ts index 1b32a3a..9bde6d9 100644 --- a/src/app/naver/moduleFactory.ts +++ b/src/app/naver/moduleFactory.ts @@ -1,14 +1,14 @@ import puppeteer from "puppeteer"; import { - Module, + NaverModule, URLChanger, PageInteractor, NaverScraper, NaverParser, } from "."; -export default class ModuleFactory { - static create(page: puppeteer.Page): Module { +export class ModuleFactory { + static create(page: puppeteer.Page): NaverModule { const urlChanger = new URLChanger(page); const pageInteractor = new PageInteractor(page); const scraper = new NaverScraper(); diff --git a/src/app/naver/pageInteractor.ts b/src/app/naver/pageInteractor.ts index d60b611..5cddcf4 100644 --- a/src/app/naver/pageInteractor.ts +++ b/src/app/naver/pageInteractor.ts @@ -1,5 +1,4 @@ import puppeteer from "puppeteer"; -import { ElementParser } from "."; export type LoginEvent = | "success" @@ -12,7 +11,7 @@ export interface CaptchaStatus { readonly question: string; } -export default class PageInteractor { +export class PageInteractor { constructor(private readonly page: puppeteer.Page) { this.page = page; } diff --git a/src/app/naver/service.ts b/src/app/naver/service.ts index 7aec84b..74da153 100644 --- a/src/app/naver/service.ts +++ b/src/app/naver/service.ts @@ -9,11 +9,11 @@ import { mergeMap, takeWhile, } from "rxjs"; -import { Module } from "."; +import { NaverModule } from "."; -export default class Service { +export class Service { cookies?: string; - constructor(private readonly module: Module) { + constructor(private readonly module: NaverModule) { this.module = module; } diff --git a/src/app/naver/urlChanger.test.ts b/src/app/naver/urlChanger.test.ts index ec064ea..1ecc3f8 100644 --- a/src/app/naver/urlChanger.test.ts +++ b/src/app/naver/urlChanger.test.ts @@ -1,4 +1,4 @@ -import URLChanger from "./urlChanger"; +import { URLChanger } from "./urlChanger"; describe("URLChanger", () => { describe("moveToLoginURL", () => { diff --git a/src/app/naver/urlChanger.ts b/src/app/naver/urlChanger.ts index 35b2cbe..2238e8c 100644 --- a/src/app/naver/urlChanger.ts +++ b/src/app/naver/urlChanger.ts @@ -1,6 +1,6 @@ import puppeteer from "puppeteer"; -export default class URLChanger { +export class URLChanger { constructor(private readonly page: puppeteer.Page) { this.page = page; } From af52411de8197efd10f6bd81283bc78e052c261d Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Thu, 10 Feb 2022 19:21:06 +0900 Subject: [PATCH 2/7] =?UTF-8?q?`Naver`=20=EC=95=B1=EC=9D=98=20class=20?= =?UTF-8?q?=EB=93=A4=EC=97=90=20`Naver`=20prefix=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/naver/index.ts | 20 ++++++++++++-------- src/app/naver/module.ts | 11 ++++++++--- src/app/naver/moduleFactory.ts | 10 +++++----- src/app/naver/pageInteractor.ts | 2 +- src/app/naver/service.ts | 2 +- src/app/naver/urlChanger.test.ts | 4 ++-- src/app/naver/urlChanger.ts | 2 +- 7 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/app/naver/index.ts b/src/app/naver/index.ts index 58c7c70..ab4dde9 100644 --- a/src/app/naver/index.ts +++ b/src/app/naver/index.ts @@ -1,17 +1,21 @@ import { NaverModule } from "./module"; -import { ModuleFactory } from "./moduleFactory"; -import { URLChanger } from "./urlChanger"; -import { LoginEvent, CaptchaStatus, PageInteractor } from "./pageInteractor"; -import { Service } from "./service"; +import { NaverModuleFactory } from "./moduleFactory"; +import { NaverURLChanger } from "./urlChanger"; +import { + LoginEvent, + CaptchaStatus, + NaverPageInteractor, +} from "./pageInteractor"; +import { NaverService } from "./service"; import { NaverScraper } from "./scraper"; import { NaverParser } from "./parser"; export { NaverModule, - ModuleFactory, - URLChanger, - PageInteractor, - Service, + NaverModuleFactory, + NaverURLChanger, + NaverPageInteractor, + NaverService, LoginEvent, CaptchaStatus, NaverScraper, diff --git a/src/app/naver/module.ts b/src/app/naver/module.ts index d8d5132..d917a10 100644 --- a/src/app/naver/module.ts +++ b/src/app/naver/module.ts @@ -1,8 +1,13 @@ -import { URLChanger, PageInteractor, NaverScraper, NaverParser } from "."; +import { + NaverURLChanger, + NaverPageInteractor, + NaverScraper, + NaverParser, +} from "."; export interface NaverModule { - readonly urlChanger: URLChanger; - readonly pageInteractor: PageInteractor; + readonly urlChanger: NaverURLChanger; + readonly pageInteractor: NaverPageInteractor; readonly scraper: NaverScraper; readonly parser: NaverParser; } diff --git a/src/app/naver/moduleFactory.ts b/src/app/naver/moduleFactory.ts index 9bde6d9..033409f 100644 --- a/src/app/naver/moduleFactory.ts +++ b/src/app/naver/moduleFactory.ts @@ -1,16 +1,16 @@ import puppeteer from "puppeteer"; import { NaverModule, - URLChanger, - PageInteractor, + NaverURLChanger, + NaverPageInteractor, NaverScraper, NaverParser, } from "."; -export class ModuleFactory { +export class NaverModuleFactory { static create(page: puppeteer.Page): NaverModule { - const urlChanger = new URLChanger(page); - const pageInteractor = new PageInteractor(page); + const urlChanger = new NaverURLChanger(page); + const pageInteractor = new NaverPageInteractor(page); const scraper = new NaverScraper(); const parser = new NaverParser(); diff --git a/src/app/naver/pageInteractor.ts b/src/app/naver/pageInteractor.ts index 5cddcf4..655f922 100644 --- a/src/app/naver/pageInteractor.ts +++ b/src/app/naver/pageInteractor.ts @@ -11,7 +11,7 @@ export interface CaptchaStatus { readonly question: string; } -export class PageInteractor { +export class NaverPageInteractor { constructor(private readonly page: puppeteer.Page) { this.page = page; } diff --git a/src/app/naver/service.ts b/src/app/naver/service.ts index 74da153..ecaae57 100644 --- a/src/app/naver/service.ts +++ b/src/app/naver/service.ts @@ -11,7 +11,7 @@ import { } from "rxjs"; import { NaverModule } from "."; -export class Service { +export class NaverService { cookies?: string; constructor(private readonly module: NaverModule) { this.module = module; diff --git a/src/app/naver/urlChanger.test.ts b/src/app/naver/urlChanger.test.ts index 1ecc3f8..3fe8290 100644 --- a/src/app/naver/urlChanger.test.ts +++ b/src/app/naver/urlChanger.test.ts @@ -1,10 +1,10 @@ -import { URLChanger } from "./urlChanger"; +import { NaverURLChanger } from "./urlChanger"; describe("URLChanger", () => { describe("moveToLoginURL", () => { it("Should move page to login", async () => { // given - const urlChanger = new URLChanger(page); + const urlChanger = new NaverURLChanger(page); const pageSpy = jest.spyOn(page, "goto"); // when diff --git a/src/app/naver/urlChanger.ts b/src/app/naver/urlChanger.ts index 2238e8c..a540f68 100644 --- a/src/app/naver/urlChanger.ts +++ b/src/app/naver/urlChanger.ts @@ -1,6 +1,6 @@ import puppeteer from "puppeteer"; -export class URLChanger { +export class NaverURLChanger { constructor(private readonly page: puppeteer.Page) { this.page = page; } From ff06666e270b9b388bc9d003a2823c55e3949078 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Thu, 10 Feb 2022 19:21:36 +0900 Subject: [PATCH 3/7] =?UTF-8?q?`cSpell`=20=EB=8B=A8=EC=96=B4=EC=9E=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 78664b2..56ef292 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,4 @@ { - "editor.tabSize": 2 + "editor.tabSize": 2, + "cSpell.words": ["captchaimg", "catcha", "Interactor", "networkidle"] } From 5d9ced626c1482d627f40ce3f751a2a21a5c116c Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Thu, 10 Feb 2022 19:28:18 +0900 Subject: [PATCH 4/7] =?UTF-8?q?`rxjs`=20dependency=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 3 +-- src/app/naver/service.ts | 29 +---------------------------- yarn.lock | 12 ------------ 3 files changed, 2 insertions(+), 42 deletions(-) diff --git a/package.json b/package.json index 9a09722..19a8988 100644 --- a/package.json +++ b/package.json @@ -35,8 +35,7 @@ }, "dependencies": { "axios": "^0.25.0", - "puppeteer": "^12.0.1", - "rxjs": "^7.5.2" + "puppeteer": "^12.0.1" }, "devDependencies": { "@babel/core": "^7.16.5", diff --git a/src/app/naver/service.ts b/src/app/naver/service.ts index ecaae57..11bc94a 100644 --- a/src/app/naver/service.ts +++ b/src/app/naver/service.ts @@ -1,14 +1,5 @@ import { PaymentHistory } from "app/common"; import { CommonResponse } from "app/common/types/response"; -import { - concat, - defer, - distinctUntilChanged, - from, - interval, - mergeMap, - takeWhile, -} from "rxjs"; import { NaverModule } from "."; export class NaverService { @@ -23,28 +14,10 @@ export class NaverService { this.cookies = await this.module.pageInteractor.getCookies(); } - interactiveLogin(id: string, password: string, delay?: number) { - const login$ = defer(() => from(this.normalLogin(id, password, delay))); - const loginStatus$ = interval(500) - .pipe(mergeMap(() => this.module.pageInteractor.getLoginStatus())) - .pipe( - distinctUntilChanged(), - takeWhile((loginStatus) => loginStatus !== "success") - ); - const captchaStatus$ = interval(500) - .pipe(mergeMap(() => this.module.pageInteractor.getCaptchaStatus())) - .pipe( - distinctUntilChanged((a, b) => a?.question === b?.question), - takeWhile((captchaStatus) => captchaStatus !== null) - ); - - const result$ = concat(login$, captchaStatus$, loginStatus$); - return result$; - } - private async isResponseValid(response: CommonResponse) { return response.status === 200; } + private async getHistoryResult(response: CommonResponse) { if (!this.isResponseValid(response)) { throw new Error(`Invalid response: ${response.status} ${response.data}`); diff --git a/yarn.lock b/yarn.lock index 8c952eb..d4a9a32 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4215,13 +4215,6 @@ rxjs@^7.1.0: dependencies: tslib "~2.1.0" -rxjs@^7.5.2: - version "7.5.2" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.2.tgz#11e4a3a1dfad85dbf7fb6e33cbba17668497490b" - integrity sha512-PwDt186XaL3QN5qXj/H9DGyHhP3/RYYgZZwqBv9Tv8rsAaiwFH1IsJJlcgD37J7UW5a6O67qX0KWKS3/pu0m4w== - dependencies: - tslib "^2.1.0" - safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -4570,11 +4563,6 @@ tsc@^2.0.3: resolved "https://registry.yarnpkg.com/tsc/-/tsc-2.0.3.tgz#037fe579e3bd67a5cbdaa604b43c6c1991b04bef" integrity sha512-SN+9zBUtrpUcOpaUO7GjkEHgWtf22c7FKbKCA4e858eEM7Qz86rRDpgOU2lBIDf0fLCsEg65ms899UMUIB2+Ow== -tslib@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" - integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== - tslib@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" From c2e923d67761ae621c672c2a2374d9ccdff6d07c Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Thu, 10 Feb 2022 19:28:36 +0900 Subject: [PATCH 5/7] =?UTF-8?q?=EC=98=88=EC=A0=9C=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/naver/printPaymentHistory.ts | 4 +- .../naver/reactivelyPrintPaymentHistory.ts | 73 ------------------- 2 files changed, 2 insertions(+), 75 deletions(-) delete mode 100644 example/naver/reactivelyPrintPaymentHistory.ts diff --git a/example/naver/printPaymentHistory.ts b/example/naver/printPaymentHistory.ts index 7e56ef4..f81841c 100644 --- a/example/naver/printPaymentHistory.ts +++ b/example/naver/printPaymentHistory.ts @@ -15,8 +15,8 @@ const printNaverPayHistory = async (id: string, password: string) => { await page.setViewport({ height: 800, width: 1200 }); await page.setUserAgent(MOBILE_UA); - const module = NaverApp.ModuleFactory.create(page); - const crawlService = new NaverApp.Service(module); + const module = NaverApp.NaverModuleFactory.create(page); + const crawlService = new NaverApp.NaverService(module); await crawlService.normalLogin(id, password, 100); diff --git a/example/naver/reactivelyPrintPaymentHistory.ts b/example/naver/reactivelyPrintPaymentHistory.ts deleted file mode 100644 index 6031ed5..0000000 --- a/example/naver/reactivelyPrintPaymentHistory.ts +++ /dev/null @@ -1,73 +0,0 @@ -import puppeteer from "puppeteer"; -import { NaverApp } from "trackpurchase"; - -import readline from "readline"; -import { concat, defer, filter, from, tap } from "rxjs"; -import { CaptchaStatus } from "trackpurchase/app/naver"; - -const printNaverPayHistory = async (id: string, password: string) => { - const MOBILE_UA = - "Mozilla/5.0 (iPhone; CPU iPhone OS 15_1_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Mobile/15E148 Safari/604.1"; - - const browser = await puppeteer.launch({ - headless: false, - args: ["--start-maximized"], - }); - - const page = await browser.newPage(); - await page.setViewport({ height: 800, width: 1200 }); - await page.setUserAgent(MOBILE_UA); - - const module = NaverApp.ModuleFactory.create(page); - const crawlService = new NaverApp.Service(module); - - const loginEvent$ = crawlService.interactiveLogin(id, password, 100); - const history$ = defer(() => from(crawlService.getHistory())); - const closePage$ = defer(() => from(page.close())); - const closeBrowser$ = defer(() => from(browser.close())); - - const final$ = concat(loginEvent$, history$, closePage$, closeBrowser$).pipe( - tap((event) => { - if (event === "otp-required") { - console.log("스마트폰 앱에서 OTP 인증을 완료해주세요."); - } - }), - tap((event) => { - if (event === "manual-otp-required") { - rl.question("otp code: ", async (code) => { - module.pageInteractor.fillManualOTPInput(code); - }); - } - }), - tap((event) => { - function instanceOfCaptchaStatus(object: any): object is CaptchaStatus { - if (object) { - return "imageData" in object && "question" in object; - } - return false; - } - - if (instanceOfCaptchaStatus(event)) { - console.log(`encodedImage: ${event.imageData}`); - console.log(`question: ${event.question}`); - rl.question("captcha code: ", (code) => { - module.pageInteractor.fillCaptchaInput(code, password); - }); - } - }), - filter((event) => event instanceof Array) - ); - final$.subscribe((event) => { - console.log(event); - }); -}; - -const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout, -}); -rl.question("Naver ID: ", (id) => { - rl.question("Naver Password: ", (password) => { - printNaverPayHistory(id, password); - }); -}); From 237393972e96a4b474f174ee14e1349a39d11b29 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Thu, 10 Feb 2022 19:29:30 +0900 Subject: [PATCH 6/7] =?UTF-8?q?README.md=20=EC=97=90=EC=84=9C=20=EC=98=88?= =?UTF-8?q?=EC=A0=9C=20=EC=BD=94=EB=93=9C=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f59940a..154bb70 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,8 @@ import { NaverApp } from "trackpurchase"; const browser = await puppeteer.launch(); const page = await browser.newPage(); -const module = NaverApp.ModuleFactory.create(page); -const crawlService = new NaverApp.Service(module); +const module = NaverApp.NaverModuleFactory.create(page); +const crawlService = new NaverApp.NaverService(module); await crawlService.normalLogin(id, password, 100); const history = await crawlService.getHistory(); From 582b1b395b6b7e5652d8c6a4f3cdc7c0e839b6f0 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Thu, 10 Feb 2022 19:31:02 +0900 Subject: [PATCH 7/7] 2.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 19a8988..a50fead 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "trackpurchase", - "version": "1.2.0", + "version": "2.0.0", "main": "dist/index.js", "license": "MIT", "repository": {