From a655697b0f16271fff9e7ac0add0cbfc671d5ab9 Mon Sep 17 00:00:00 2001 From: "tv0924@icloud.com" Date: Sun, 8 Jun 2025 21:09:05 +0900 Subject: [PATCH] =?UTF-8?q?[Refactor]=20=ED=94=84=EB=A1=AC=ED=94=84?= =?UTF-8?q?=ED=8A=B8=EB=A5=BC=20=EB=8B=A4=EB=A5=B8=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 + lib/prompt.py | 71 ++++++++++++++++++ main.py | 198 ++++++++++++++++---------------------------------- run.sh | 1 + 4 files changed, 135 insertions(+), 137 deletions(-) create mode 100644 lib/prompt.py diff --git a/.gitignore b/.gitignore index a0378d4..e992bc2 100644 --- a/.gitignore +++ b/.gitignore @@ -78,4 +78,6 @@ $RECYCLE.BIN/ # Windows shortcuts *.lnk +my.sh + # End of https://www.toptal.com/developers/gitignore/api/macos,windows \ No newline at end of file diff --git a/lib/prompt.py b/lib/prompt.py new file mode 100644 index 0000000..26ab2b4 --- /dev/null +++ b/lib/prompt.py @@ -0,0 +1,71 @@ +# Extended planner prompt +extend_planner_system_message = """ +๐ŸŽฏ Mission: Collect Initial SSO Redirect URLs (For Browser Automation) + +โ€ป **์ ˆ๋Œ€๋กœ ๊ตฌ๊ธ€ ๊ฒ€์ƒ‰, Bing ๊ฒ€์ƒ‰ ๋“ฑ ์–ด๋–ค ์™ธ๋ถ€ ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ๋„ ์‚ฌ์šฉํ•˜์ง€ ๋ง๊ณ , ์ฃผ์–ด์ง„ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€ URL์„ ์ง์ ‘ ๋ฐฉ๋ฌธํ•˜์—ฌ ํƒ์ƒ‰ํ•˜์„ธ์š”.** + +0. **์ดˆ๊ธฐ ๋ธ”๋ก(Block) ์ฒดํฌ** + - ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€์— ์ ‘๊ทผํ•˜๋ ค ํ•  ๋•Œ, **ํŽ˜์ด์ง€๊ฐ€ ์ฐจ๋‹จ(blocked)** ๋˜๊ฑฐ๋‚˜ **๋ฐฉํ™”๋ฒฝ, CAPTCHA, ์ ‘๊ทผ ์ œํ•œ** ๋“ฑ์œผ๋กœ ์ธํ•ด ์ •์ƒ์ ์œผ๋กœ ๋กœ๋“œ๋˜์ง€ ์•Š์œผ๋ฉด ์ฆ‰์‹œ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ข…๋ฃŒํ•˜๊ณ  ์•„๋ž˜ JSON๋งŒ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + ```json + [ + { + "provider": "Blocked", + "oauth_uri": "-" + } + ] + ``` + - ์ดํ›„ ๋‹จ๊ณ„๋กœ ์ ˆ๋Œ€ ๋„˜์–ด๊ฐ€์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. + +1. **๋กœ๊ทธ์ธ ํŽ˜์ด์ง€ ํƒ์ƒ‰** + - **ํด๋ผ์ด์–ธํŠธ(๋น„์—”ํ„ฐํ”„๋ผ์ด์ฆˆ) ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€**๋กœ ์ง์ ‘ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. (๊ฒ€์ƒ‰ ์—”์ง„์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฐพ์•„์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.) + - ์ ‘๊ทผ ํ›„ **๊ฐœ์ธ์ •๋ณด/์ฟ ํ‚ค/๋™์˜ ํŒ์—…**์ด ๋œจ๋ฉด, ์ด๋ฅผ ๋ฐ˜๋“œ์‹œ **๋‹ซ๊ฑฐ๋‚˜(Dismiss)** ์ฒ˜๋ฆฌํ•˜๊ณ  ๊ณ„์† ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค. + - (์ด๋ฏธ 0๋‹จ๊ณ„์—์„œ ๋ธ”๋ก ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ–ˆ์œผ๋ฏ€๋กœ, ์ด ๋‹จ๊ณ„์—์„œ๋Š” ํŽ˜์ด์ง€๊ฐ€ ์ •์ƒ ๋กœ๋“œ๋˜์—ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.) + +2. **SSO ๋ฒ„ํŠผ ์‹๋ณ„** + - ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์†Œ์…œ ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ์„ ์ฐพ์Šต๋‹ˆ๋‹ค: + - โ€œContinue with Googleโ€ + - โ€œSign in with GitHubโ€ + - โ€œLogin with Naverโ€ + - โœ… **์‹ค์ œ SSO ๋ฒ„ํŠผ**์ž„์ด ๋ช…ํ™•ํžˆ ํ™•์ธ๋˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค. + - โŒ ์ œ์™ธ ๋Œ€์ƒ: + - โ€œPasskeyโ€ ๊ด€๋ จ ๋ฒ„ํŠผ + - ์•„์ด๋””/๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ๋ž€ + - ์ด๋ฉ”์ผ ๊ธฐ๋ฐ˜ ๋กœ๊ทธ์ธ + - ์ธ์ฆ์„œ, ํœด๋Œ€ํฐ ์ธ์ฆ ๋“ฑ ๋น„-OAuth ๋กœ๊ทธ์ธ ์˜ต์…˜ + +3. **๋ฆฌ๋””๋ ‰์…˜ URL ์บก์ฒ˜** + - ์œ ํšจํ•œ SSO ๋ฒ„ํŠผ์„ ํ•˜๋‚˜ ์ด์ƒ ์ฐพ์•˜๋‹ค๋ฉด, ๊ฐ๊ฐ์˜ ๋ฒ„ํŠผ์„ **์ƒˆ ํƒญ์œผ๋กœ ์—ด๊ธฐ**๋ฅผ ์‹œ๋„ํ•˜๊ฑฐ๋‚˜, ๋ถˆ๊ฐ€๋Šฅํ•  ๊ฒฝ์šฐ **์ง์ ‘ ํด๋ฆญ**ํ•ฉ๋‹ˆ๋‹ค. + - ํด๋ฆญ ํ›„ ์ฒซ ๋ฒˆ์งธ๋กœ **๋ฆฌ๋””๋ ‰์…˜๋œ URL(์ฟผ๋ฆฌ ์ŠคํŠธ๋ง ํฌํ•จ)**์„ ์บก์ฒ˜ํ•ฉ๋‹ˆ๋‹ค. ์ด URL์€: + - โœ… ์˜ˆ์‹œ: `https://example.com/auth/google?include_all_params=...` + - โŒ **OAuth ๊ณต๊ธ‰์ž ์ž์ฒด ์—”๋“œํฌ์ธํŠธ** (์˜ˆ: `https://accounts.google.com/...`)๋Š” ์ˆ˜์ง‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + - ๋งŒ์•ฝ **๋ฐ˜๋ณต ํ–‰๋™(looping)**์ด ๊ฐ์ง€๋  ๊ฒฝ์šฐ(์˜ˆ: ๋™์ผํ•œ ๋ฒ„ํŠผ์„ ์—ฌ๋Ÿฌ ๋ฒˆ ์—ด๊ฑฐ๋‚˜ ํŽ˜์ด์ง€ ๊ฐ„ ๋ฐ˜๋ณต ์ด๋™), ์ฆ‰์‹œ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ข…๋ฃŒํ•˜๊ณ  **๋นˆ ๋ฐฐ์—ด**์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค: + ```json + [] + ``` + - ์ •์ƒ์ ์œผ๋กœ ๋ฆฌ๋””๋ ‰์…˜ URL์„ ํš๋“ํ–ˆ๋‹ค๋ฉด, ์•„๋ž˜ ํ˜•์‹์œผ๋กœ ๊ฒฐ๊ณผ๋ฅผ ์ˆ˜์ง‘ํ•ฉ๋‹ˆ๋‹ค: + ```json + [ + { + "provider": "Google", + "oauth_uri": "https://example.com/auth/google?include_all_params=..." + }, + { + "provider": "GitHub", + "oauth_uri": "https://example.com/auth/github?include_all_params=..." + } + ] + ``` + +4. **SSO ๋ฒ„ํŠผ ๋ฏธ๋ฐœ๊ฒฌ ๋˜๋Š” ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์‹œ** + - ํŽ˜์ด์ง€ ๋‚ด๋ถ€์— ์œ ํšจํ•œ SSO ๋ฒ„ํŠผ์ด ์ „ํ˜€ ์—†๊ฑฐ๋‚˜, ํƒ์ƒ‰ ์ค‘ ์˜ˆ๊ธฐ์น˜ ์•Š์€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ฆ‰์‹œ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ข…๋ฃŒํ•˜๊ณ  **๋นˆ ๋ฐฐ์—ด**์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค: + ```json + [] + ``` + +5. **์ค‘์š” ์‚ฌํ•ญ** + - **๋ฐ˜๋“œ์‹œ** ์œ„์˜ ๋‹จ๊ณ„๋“ค์„ ์ˆœ์„œ๋Œ€๋กœ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋ฉฐ, ๊ฐ ๋‹จ๊ณ„์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ ์ƒํ™ฉ์„ ์ •ํ™•ํžˆ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + - **๋ฐ˜๋ณต ํ–‰๋™**์ด ๊ฐ์ง€๋˜๋ฉด ์ฆ‰์‹œ ๋นˆ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , **๋ธ”๋ก๋œ ํŽ˜์ด์ง€**๋Š” ์ดˆ๊ธฐ ๋‹จ๊ณ„์—์„œ ์ฒ˜๋ฆฌํ•˜์—ฌ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ข…๋ฃŒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. + - **SSO ๋ฒ„ํŠผ์ด ๋ฐœ๊ฒฌ๋˜์ง€ ์•Š๊ฑฐ๋‚˜, ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ์—๋„ ๋นˆ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.** + - **๋ฐ˜๋“œ์‹œ** JSON ํ˜•์‹์œผ๋กœ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜๋ฉฐ, ๋‹ค๋ฅธ ํ˜•์‹์€ ํ—ˆ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + - ์ตœ๋Œ€ํ•œ ํšจ์œจ์ ์ธ ๋‹จ๊ณ„๋กœ ์ง„ํ–‰ํ•˜๋ฉฐ, ๋ถˆํ•„์š”ํ•œ ๋ฐ˜๋ณต์ด๋‚˜ ๊ฒ€์ƒ‰ ์—”์ง„ ์‚ฌ์šฉ์„ ํ”ผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. +""" \ No newline at end of file diff --git a/main.py b/main.py index 5134ff7..db0d2b2 100644 --- a/main.py +++ b/main.py @@ -13,6 +13,7 @@ from browser_use.browser.context import BrowserContext, BrowserContextConfig from lib.browser_config import browser_config_kwargs from lib.is_html import is_html_url from lib.read_txt import read_lines_between +from lib.prompt import extend_planner_system_message load_dotenv() @@ -33,91 +34,15 @@ class OAuth(BaseModel): class OAuthList(BaseModel): oauth_providers: List[OAuth] -# Controller๋Š” ๋งค๋ฒˆ ์ƒˆ๋กœ ์ƒ์„ฑํ•ด๋„ ๋ฌด๋ฐฉํ•ฉ๋‹ˆ๋‹ค. -def make_controller(): - return Controller(output_model=OAuthList) - -# Extended planner prompt -extend_planner_system_message = """ -๐ŸŽฏ Mission: Collect Initial SSO Redirect URLs (For Browser Automation) - -โ€ป **์ ˆ๋Œ€๋กœ ๊ตฌ๊ธ€ ๊ฒ€์ƒ‰, Bing ๊ฒ€์ƒ‰ ๋“ฑ ์–ด๋–ค ์™ธ๋ถ€ ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ๋„ ์‚ฌ์šฉํ•˜์ง€ ๋ง๊ณ , ์ฃผ์–ด์ง„ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€ URL์„ ์ง์ ‘ ๋ฐฉ๋ฌธํ•˜์—ฌ ํƒ์ƒ‰ํ•˜์„ธ์š”.** - -0. **์ดˆ๊ธฐ ๋ธ”๋ก(Block) ์ฒดํฌ** - - ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€์— ์ ‘๊ทผํ•˜๋ ค ํ•  ๋•Œ, **ํŽ˜์ด์ง€๊ฐ€ ์ฐจ๋‹จ(blocked)** ๋˜๊ฑฐ๋‚˜ **๋ฐฉํ™”๋ฒฝ, CAPTCHA, ์ ‘๊ทผ ์ œํ•œ** ๋“ฑ์œผ๋กœ ์ธํ•ด ์ •์ƒ์ ์œผ๋กœ ๋กœ๋“œ๋˜์ง€ ์•Š์œผ๋ฉด ์ฆ‰์‹œ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ข…๋ฃŒํ•˜๊ณ  ์•„๋ž˜ JSON๋งŒ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - ```json - [ - { - "provider": "Blocked", - "oauth_uri": "-" - } - ] - ``` - - ์ดํ›„ ๋‹จ๊ณ„๋กœ ์ ˆ๋Œ€ ๋„˜์–ด๊ฐ€์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. - -1. **๋กœ๊ทธ์ธ ํŽ˜์ด์ง€ ํƒ์ƒ‰** - - **ํด๋ผ์ด์–ธํŠธ(๋น„์—”ํ„ฐํ”„๋ผ์ด์ฆˆ) ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€**๋กœ ์ง์ ‘ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. (๊ฒ€์ƒ‰ ์—”์ง„์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฐพ์•„์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.) - - ์ ‘๊ทผ ํ›„ **๊ฐœ์ธ์ •๋ณด/์ฟ ํ‚ค/๋™์˜ ํŒ์—…**์ด ๋œจ๋ฉด, ์ด๋ฅผ ๋ฐ˜๋“œ์‹œ **๋‹ซ๊ฑฐ๋‚˜(Dismiss)** ์ฒ˜๋ฆฌํ•˜๊ณ  ๊ณ„์† ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค. - - (์ด๋ฏธ 0๋‹จ๊ณ„์—์„œ ๋ธ”๋ก ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ–ˆ์œผ๋ฏ€๋กœ, ์ด ๋‹จ๊ณ„์—์„œ๋Š” ํŽ˜์ด์ง€๊ฐ€ ์ •์ƒ ๋กœ๋“œ๋˜์—ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.) - -2. **SSO ๋ฒ„ํŠผ ์‹๋ณ„** - - ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์†Œ์…œ ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ์„ ์ฐพ์Šต๋‹ˆ๋‹ค: - - โ€œContinue with Googleโ€ - - โ€œSign in with GitHubโ€ - - โ€œLogin with Naverโ€ - - โœ… **์‹ค์ œ SSO ๋ฒ„ํŠผ**์ž„์ด ๋ช…ํ™•ํžˆ ํ™•์ธ๋˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค. - - โŒ ์ œ์™ธ ๋Œ€์ƒ: - - โ€œPasskeyโ€ ๊ด€๋ จ ๋ฒ„ํŠผ - - ์•„์ด๋””/๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ๋ž€ - - ์ด๋ฉ”์ผ ๊ธฐ๋ฐ˜ ๋กœ๊ทธ์ธ - - ์ธ์ฆ์„œ, ํœด๋Œ€ํฐ ์ธ์ฆ ๋“ฑ ๋น„-OAuth ๋กœ๊ทธ์ธ ์˜ต์…˜ - -3. **๋ฆฌ๋””๋ ‰์…˜ URL ์บก์ฒ˜** - - ์œ ํšจํ•œ SSO ๋ฒ„ํŠผ์„ ํ•˜๋‚˜ ์ด์ƒ ์ฐพ์•˜๋‹ค๋ฉด, ๊ฐ๊ฐ์˜ ๋ฒ„ํŠผ์„ **์ƒˆ ํƒญ์œผ๋กœ ์—ด๊ธฐ**๋ฅผ ์‹œ๋„ํ•˜๊ฑฐ๋‚˜, ๋ถˆ๊ฐ€๋Šฅํ•  ๊ฒฝ์šฐ **์ง์ ‘ ํด๋ฆญ**ํ•ฉ๋‹ˆ๋‹ค. - - ํด๋ฆญ ํ›„ ์ฒซ ๋ฒˆ์งธ๋กœ **๋ฆฌ๋””๋ ‰์…˜๋œ URL(์ฟผ๋ฆฌ ์ŠคํŠธ๋ง ํฌํ•จ)**์„ ์บก์ฒ˜ํ•ฉ๋‹ˆ๋‹ค. ์ด URL์€: - - โœ… ์˜ˆ์‹œ: `https://example.com/auth/google?include_all_params=...` - - โŒ **OAuth ๊ณต๊ธ‰์ž ์ž์ฒด ์—”๋“œํฌ์ธํŠธ** (์˜ˆ: `https://accounts.google.com/...`)๋Š” ์ˆ˜์ง‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. - - ๋งŒ์•ฝ **๋ฐ˜๋ณต ํ–‰๋™(looping)**์ด ๊ฐ์ง€๋  ๊ฒฝ์šฐ(์˜ˆ: ๋™์ผํ•œ ๋ฒ„ํŠผ์„ ์—ฌ๋Ÿฌ ๋ฒˆ ์—ด๊ฑฐ๋‚˜ ํŽ˜์ด์ง€ ๊ฐ„ ๋ฐ˜๋ณต ์ด๋™), ์ฆ‰์‹œ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ข…๋ฃŒํ•˜๊ณ  **๋นˆ ๋ฐฐ์—ด**์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค: - ```json - [] - ``` - - ์ •์ƒ์ ์œผ๋กœ ๋ฆฌ๋””๋ ‰์…˜ URL์„ ํš๋“ํ–ˆ๋‹ค๋ฉด, ์•„๋ž˜ ํ˜•์‹์œผ๋กœ ๊ฒฐ๊ณผ๋ฅผ ์ˆ˜์ง‘ํ•ฉ๋‹ˆ๋‹ค: - ```json - [ - { - "provider": "Google", - "oauth_uri": "https://example.com/auth/google?include_all_params=..." - }, - { - "provider": "GitHub", - "oauth_uri": "https://example.com/auth/github?include_all_params=..." - } - ] - ``` - -4. **SSO ๋ฒ„ํŠผ ๋ฏธ๋ฐœ๊ฒฌ ๋˜๋Š” ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์‹œ** - - ํŽ˜์ด์ง€ ๋‚ด๋ถ€์— ์œ ํšจํ•œ SSO ๋ฒ„ํŠผ์ด ์ „ํ˜€ ์—†๊ฑฐ๋‚˜, ํƒ์ƒ‰ ์ค‘ ์˜ˆ๊ธฐ์น˜ ์•Š์€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์ฆ‰์‹œ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ข…๋ฃŒํ•˜๊ณ  **๋นˆ ๋ฐฐ์—ด**์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค: - ```json - [] - ``` - -5. **์ค‘์š” ์‚ฌํ•ญ** - - **๋ฐ˜๋“œ์‹œ** ์œ„์˜ ๋‹จ๊ณ„๋“ค์„ ์ˆœ์„œ๋Œ€๋กœ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋ฉฐ, ๊ฐ ๋‹จ๊ณ„์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ ์ƒํ™ฉ์„ ์ •ํ™•ํžˆ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - - **๋ฐ˜๋ณต ํ–‰๋™**์ด ๊ฐ์ง€๋˜๋ฉด ์ฆ‰์‹œ ๋นˆ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , **๋ธ”๋ก๋œ ํŽ˜์ด์ง€**๋Š” ์ดˆ๊ธฐ ๋‹จ๊ณ„์—์„œ ์ฒ˜๋ฆฌํ•˜์—ฌ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ข…๋ฃŒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. - - **SSO ๋ฒ„ํŠผ์ด ๋ฐœ๊ฒฌ๋˜์ง€ ์•Š๊ฑฐ๋‚˜, ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ์—๋„ ๋นˆ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.** - - **๋ฐ˜๋“œ์‹œ** JSON ํ˜•์‹์œผ๋กœ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜๋ฉฐ, ๋‹ค๋ฅธ ํ˜•์‹์€ ํ—ˆ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. - - ์ตœ๋Œ€ํ•œ ํšจ์œจ์ ์ธ ๋‹จ๊ณ„๋กœ ์ง„ํ–‰ํ•˜๋ฉฐ, ๋ถˆํ•„์š”ํ•œ ๋ฐ˜๋ณต์ด๋‚˜ ๊ฒ€์ƒ‰ ์—”์ง„ ์‚ฌ์šฉ์„ ํ”ผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -""" - # โ”€โ”€ URL๋ณ„๋กœ Browser๋ฅผ ์ƒˆ๋กœ ๋„์šฐ๋Š” ํ•จ์ˆ˜ โ”€โ”€ async def scan_one_url(url: str, skip_html_check: bool = False): - # 1) URL์ด HTML ํŽ˜์ด์ง€์ธ์ง€ ํ™•์ธ - if not is_html_url(url) and not skip_html_check: - print(f"โŒ {url} ์€(๋Š”) HTML์ด ์•„๋‹™๋‹ˆ๋‹ค. ์Šคํ‚ตํ•ฉ๋‹ˆ๋‹ค.") - return - target_url = url if url.startswith("http") else f"https://{url}" print(f"๐Ÿš€ Starting scan for: {target_url}") + + # 1) URL์ด HTML ํŽ˜์ด์ง€์ธ์ง€ ํ™•์ธ + if not is_html_url(target_url) and not skip_html_check: + print(f"โŒ {target_url} ์€(๋Š”) HTML์ด ์•„๋‹™๋‹ˆ๋‹ค. ์Šคํ‚ตํ•ฉ๋‹ˆ๋‹ค.") + return # Backend์— ์Šค์บ” ์‹œ์ž‘์„ ์•Œ๋ฆผ try: @@ -132,46 +57,46 @@ async def scan_one_url(url: str, skip_html_check: bool = False): print(f"โš ๏ธ Backend notification timed out. Continuing without notification.") except Exception as e: print(f"โš ๏ธ Failed to notify backend: {e}") + + # 2) Browser + Context ์ƒ์„ฑ + browser = Browser(config=BrowserConfig(**browser_config_kwargs())) + context = BrowserContext( + browser=browser, + config=BrowserContextConfig( + wait_for_network_idle_page_load_time=3.0, + window_width=1600, + window_height=900, + locale='en-US', + highlight_elements=True, + viewport_expansion=500, + keep_alive=False + ) + ) + + # 3) Agent, Controller ์ƒ์„ฑ + initial_actions = [ + {'open_tab': {'url': target_url, 'wait_for_network_idle': True}}, + ] + + controller = Controller(output_model=OAuthList) + agent = Agent( + browser_context=context, + browser=browser, + initial_actions=initial_actions, + task=f"Navigate to the login page, and collect the OAuth provider buttons and their login URLs. Ignore Passkey.", + llm=ChatGoogleGenerativeAI(model=os.getenv("GOOGLE_MODEL")), + planner_llm=ChatGoogleGenerativeAI(model=os.getenv("GOOGLE_PLANNER_MODEL")), + controller=controller, + extend_planner_system_message=extend_planner_system_message, + retry_delay=60, + ) + try_cnt = 0 while True: - # 2) Browser + Context ์ƒ์„ฑ - browser = Browser(config=BrowserConfig(**browser_config_kwargs())) - context = BrowserContext( - browser=browser, - config=BrowserContextConfig( - wait_for_network_idle_page_load_time=3.0, - window_width=1600, - window_height=900, - locale='en-US', - highlight_elements=True, - viewport_expansion=500, - keep_alive=False - ) - ) - - # 3) Agent, Controller ์ƒ์„ฑ - - initial_actions = [ - {'open_tab': {'url': url}} - ] - - controller = make_controller() - agent = Agent( - browser_context=context, - browser=browser, - initial_actions=initial_actions, - task=f"Navigate to the login page, and collect the OAuth provider buttons and their login URLs. Ignore Passkey.", - llm=ChatGoogleGenerativeAI(model=os.getenv("GOOGLE_MODEL")), - planner_llm=ChatGoogleGenerativeAI(model=os.getenv("GOOGLE_PLANNER_MODEL")), - controller=controller, - extend_planner_system_message=extend_planner_system_message, - retry_delay=60, - ) - try: # 4) ์‹ค์ œ ์Šค์บ” ์‹คํ–‰ response = await agent.run() - final_result = response.final_result() + final_result = response.final_reult() if final_result is None: raise ValueError("final_result()๊ฐ€ None์„ ๋ฐ˜ํ™˜ํ–ˆ์Šต๋‹ˆ๋‹ค.") @@ -202,36 +127,35 @@ async def scan_one_url(url: str, skip_html_check: bool = False): for entry in oauth_entries: writer.writerow([url, entry.provider, entry.oauth_uri]) print(f"โœ… OAuth providers saved to {csv_file}\n") - - # 7) Agent์™€ Browser ๋‹ซ๊ธฐ - await agent.close() # Agent ๋‚ด๋ถ€ ์ž‘์—… ์ •๋ฆฌ - await context.close() # ๋ธŒ๋ผ์šฐ์ € ์ปจํ…์ŠคํŠธ ์ข…๋ฃŒ (ํƒญ/์„ธ์…˜ ๋‹ซ๊ธฐ) - await browser.close() # ์‹ค์ œ ๋ธŒ๋ผ์šฐ์ € ํ”„๋กœ์„ธ์Šค ์ข…๋ฃŒ # ์„ฑ๊ณต์ ์œผ๋กœ ์ฒ˜๋ฆฌํ–ˆ์œผ๋ฏ€๋กœ ๋ฐ˜๋ณต๋ฌธ ํƒˆ์ถœ break except Exception as e: - print(f"โš ๏ธ 429 ์—๋Ÿฌ ๋ฐœ์ƒ, 60์ดˆ ๋Œ€๊ธฐ ํ›„ ์žฌ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค. (URL: {url})") - - # ๋ฆฌ์†Œ์Šค ์ •๋ฆฌ - try: - await agent.close() - except: - pass - try: - await context.close() - except: - pass - try: - await browser.close() - except: - pass + if try_cnt >= 3: + print(f"โŒ {url} ์Šค์บ”์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค. ์—๋Ÿฌ: {e}") + break + try_cnt += 1 + print(f"โš ๏ธ ์—๋Ÿฌ ๋ฐœ์ƒ, 60์ดˆ ๋Œ€๊ธฐ ํ›„ ์žฌ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค. (URL: {url})") # 1๋ถ„ ๋Œ€๊ธฐ await asyncio.sleep(60) # ๋ฐ˜๋ณต๋ฌธ์„ ํ†ตํ•ด ์žฌ์‹œ๋„ continue + + # ๋ฆฌ์†Œ์Šค ์ •๋ฆฌ + try: + await agent.close() + except: + pass + try: + await context.close() + except: + pass + try: + await browser.close() + except: + pass async def loop(filepath: str, start_line: int, end_line: int, skip_html_check: bool = False): # ์ธ์ž๊ฐ’์œผ๋กœ ๋ฐ›์€ ํŒŒ์ผ ๊ฒฝ๋กœ์™€ ์ค„ ๋ฒ”์œ„๋ฅผ ํ†ตํ•ด ๋„๋ฉ”์ธ ๋ฆฌ์ŠคํŠธ ์ƒ์„ฑ @@ -248,7 +172,7 @@ async def loop(filepath: str, start_line: int, end_line: int, skip_html_check: b # scan_one_url์€ ์™ธ๋ถ€์— ์ •์˜๋œ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ผ๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. # ์‹ค์ œ๋กœ scan_one_url์ด ์ •์˜๋œ ์œ„์น˜๋ฅผ importํ•˜๊ฑฐ๋‚˜ # ๋ชจ๋“ˆ ์ˆ˜์ค€์— ๊ตฌํ˜„ํ•ด๋‘์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค. - await scan_one_url(f'http://{url}', skip_html_check=skip_html_check) + await scan_one_url(url, skip_html_check=skip_html_check) def main(): diff --git a/run.sh b/run.sh index ae9d3f6..b78ca57 100755 --- a/run.sh +++ b/run.sh @@ -34,6 +34,7 @@ while [ "$current" -le "$END_LINE" ]; do uv run "$PYTHON_SCRIPT" -f "$DOMAIN_FILE" -s "$current" -e "$chunk_end" -skh $SKH_OPTION current=$(( chunk_end + 1 )) + sleep 1 # 1์ดˆ ๋Œ€๊ธฐ done echo "๋ชจ๋“  ์ฒญํฌ ์ฒ˜๋ฆฌ ์™„๋ฃŒ."