diff --git a/.gitignore b/.gitignore index edd848d..43cf84e 100644 --- a/.gitignore +++ b/.gitignore @@ -9,5 +9,5 @@ wheels/ # Virtual environments .venv -browser/ .env +log_*.log \ No newline at end of file diff --git a/README.md b/README.md index 2768123..bdbdbe3 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ +# 테스트한 영상 +https://f.imnya.ng/.whs/teamproject/ + # 참고하면 좋을만한 것 - [ ] 일부 웹사이트는 사용자의 언어에 따라 OAuth 옵션을 바꾸기도 합니다. - [ ] https://docs.browser-use.com/customize/custom-functions diff --git a/lib/browser_config.py b/lib/browser_config.py index 8066d9d..5e12665 100644 --- a/lib/browser_config.py +++ b/lib/browser_config.py @@ -2,8 +2,11 @@ from browser_use.browser.context import BrowserContextConfig from pathlib import Path import os -def browser_config_kwargs(lang: str = "en_US") -> dict: - browser_config_kwargs = { +from typing import Any + +def browser_config_kwargs(lang: str = "en_US") -> dict[str, Any]: + browser_config_kwargs: dict[str, Any] = { + "keep_alive": True, "browser_type": "chromium", "headless": False, "disable_security": True, diff --git a/main.py b/main.py index a8b91a1..20b4592 100644 --- a/main.py +++ b/main.py @@ -1,76 +1,134 @@ import asyncio import json +import os from typing import List from dotenv import load_dotenv -from browser_use import Agent, Browser, BrowserConfig, Controller -from langchain_openai import ChatOpenAI from pydantic import BaseModel +from langchain_openai import ChatOpenAI +from browser_use import Agent, Browser, BrowserConfig, Controller +from browser_use.browser.context import BrowserContext, BrowserContextConfig from lib.browser_config import browser_config_kwargs -import os -import csv load_dotenv() +# Check environment variables if os.getenv("OPENAI_API_KEY") is None: raise ValueError("OPENAI_API_KEY environment variable not set.") if os.getenv("OPENAI_MODEL") is None: raise ValueError("OPENAI_MODEL environment variable not set.") +if os.getenv("OPENAI_PLANNER_MODEL") is None: + raise ValueError("OPENAI_PLANNER_MODEL environment variable not set.") -browser_config_kwargs = browser_config_kwargs() - +# Configure browser browser = Browser( - config=BrowserConfig(**browser_config_kwargs) + config=BrowserConfig(**browser_config_kwargs()) ) +# Set browser context +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=True + ) +) + +# Output model: each result is one OAuth entry with metadata class OAuth(BaseModel): - source: str provider: str - client_id: str - redirect_uri: str - response_type: str - scope: str oauth_uri: str -class OAuthExists(BaseModel): - oauth_providers: List[str] +class OAuthList(BaseModel): + oauth_providers: List[OAuth] -controller = Controller(output_model=OAuthExists) +controller = Controller(output_model=OAuthList) +# Extended planner prompt extend_planner_system_message = """ -{"oauth_providers": ["GitHub", "Google", "Facebook", "Twitter", "LinkedIn", "GitLab", "Bitbucket", "Discord", "Reddit", "Spotify", "Twitch", "Yahoo", "Amazon", "Microsoft", "Apple", ...]} +🎯 Your mission is to collect the real OAuth login URLs from the website. -The OAuth providers are available on the login page of the website. -The user is interested in the OAuth providers available on the login page of the website. +1. First, go to the website’s **login page**. +2. On the login page, look for OAuth login buttons. These usually say things like **"Continue with Google"**, **"Sign in with GitHub"**, etc. +3. ⚠️ **DO NOT collect or include "Passkey"** — it is NOT an OAuth provider. -Passkey isn't a Oauth provider. Remove it from the list of OAuth providers. +--- + +✅ For EACH OAuth button you find: + +- **Try opening it in a new tab**. If it redirects to an OAuth URL (e.g. `https://accounts.google.com/...`, `https://github.com/login/oauth/...`), copy that **exact final URL**. +- If it **doesn’t open in a new tab**, **click the button** and wait for the redirect to happen. + - As soon as you see the redirected URL with **client_id**, **redirect_uri**, etc., copy that **entire URL without changing or hiding anything**. + - Then come back to the original tab (if needed) and continue with the next provider. + +--- + +💡 **Do not guess** the OAuth URLs — only collect them by actually interacting with the buttons. + +🚫 **Do not redact or mask any part** of the URL, including `client_id`, `redirect_uri`, `state`, or any other parameters. Record them exactly as they appear. + +✅ Return a list of all OAuth providers and their **full raw redirect URLs** in this exact format: + +```json +[ + { + "provider": "Google", + "oauth_uri": "https://accounts.google.com/o/oauth2/v2/auth?client_id=...&redirect_uri=...&...", + }, + { + "provider": "GitHub", + "oauth_uri": "https://github.com/login/oauth/authorize?client_id=...&redirect_uri=...", + } +] +``` """ +# Main async runner async def main(): url = "https://auth0.com" + agent = Agent( + browser_context=context, browser=browser, - task=f"Go to {url}, navigate to the login page, and identify the available OAuth providers. Passkey is not a valid OAuth provider.", - llm=ChatOpenAI( - model=os.getenv("OPENAI_MODEL"), - temperature=0.0 - ), + task=f"Go to {url}, navigate to the login page, and collect the OAuth provider buttons and their login URLs. Ignore Passkey.", + llm=ChatOpenAI(model=os.getenv("OPENAI_MODEL")), + planner_llm=ChatOpenAI(model=os.getenv("OPENAI_PLANNER_MODEL")), controller=controller, extend_planner_system_message=extend_planner_system_message, ) + # Run the agent response = await agent.run() final_result = response.final_result() if final_result is None: raise ValueError("final_result() returned None") - result = json.loads(final_result) - print(result) - - # {"oauth_providers": ["GitHub", "Passkey"]} print - # Clear Terminal - print("\033c", end="") - print(f"🔗: {url}") - for provider in result['oauth_providers']: - print(provider) + + data = json.loads(final_result) + + try: + oauth_entries: List[OAuth] = [OAuth(**entry) for entry in data["oauth_providers"]] + except Exception as e: + raise ValueError(f"Failed to parse result: {e}\nRaw result: {final_result}") + # Clear terminal + #print("\033c", end="") + print("-" * 20) + + print(f"Raw result: {final_result}") + + print(f"🔗 Scanned URL: {url}\n") + print("🔐 Detected OAuth Providers and URLs:") + for entry in oauth_entries: + if "<" in entry.oauth_uri or "..." in entry.oauth_uri: + print(f"⚠️ WARNING: {entry.provider} URL may be masked or incomplete:\n{entry.oauth_uri}\n") + else: + print(f"- {entry.provider}: {entry.oauth_uri}") + + +# Run it asyncio.run(main()) diff --git a/run.ps1 b/run.ps1 new file mode 100644 index 0000000..6e8207c --- /dev/null +++ b/run.ps1 @@ -0,0 +1 @@ +uv run ./main.py \ No newline at end of file diff --git a/test.txt b/test.txt deleted file mode 100644 index 31328d9..0000000 --- a/test.txt +++ /dev/null @@ -1,4 +0,0 @@ -https://accounts.kakao.com/login/?continue=https://daum.net &@imnya.ng# @imnya.ng/#login - - -https://accounts.kakao.com/login/?continue=https://www.daum.net:/%40imnya.ng/#loginy \ No newline at end of file