chore: улучшение архитектуры

This commit is contained in:
protokey committed 2026-09-08 18:16:05 +04:00
1 parent 0f60aa9046
commit 6b1935d78a
4 files changed
+82 -62

No files matched your search

View File
Whitespace-only changes.
+47
View File
@@ -0,0 +1,47 @@
from playwright.async_api import Page
from engine.schemas import ActionRequest
_actions: dict = {}
def register(fun) -> None:
_actions[fun.__name__] = fun
return fun
@register
async def fill(page: Page, act: ActionRequest) -> str | None:
...
@register
async def mouse_move(page: Page, act: ActionRequest) -> str | None:
...
@register
async def click(page: Page, act: ActionRequest) -> str | None:
...
@register
async def wait_for(page: Page, act: ActionRequest) -> str | None:
try:
assert act.selector
await page.wait_for_selector(act.selector, timeout=act.timeout * 1000)
except Exception as e:
return str(e)
else:
return None
async def execute(page: Page, actions: list[ActionRequest]) -> list[str]:
actions_result = []
for act in actions:
try:
await _actions[act.type](page, act)
except Exception as e:
actions_result.append({"type": act.type, "ok": "false", "error": str(e)})
break
return actions_result
+17
View File
@@ -0,0 +1,17 @@
from pydantic import BaseModel
class ActionRequest(BaseModel):
type: str
selector: str | None = None
value: str | None = None
timeout: int | None = None
class SolveRequest(BaseModel):
url: str
proxy: str
actions: list[ActionRequest]
timeout: int | None = None
screen: str = "1280x720"
user_agent: str | None = None
+18 -62
View File
@@ -3,25 +3,10 @@ from datetime import datetime
from camoufox.async_api import AsyncCamoufox
from fastapi import FastAPI
from fastapi import Request
from playwright.async_api import Page
from pydantic import BaseModel
from playwright.async_api import ViewportSize, ProxySettings
class ActionRequest(BaseModel):
type: str
selector: str | None = None
value: str | None = None
timeout: int | None = None
class SolveRequest(BaseModel):
url: str
proxy: str
actions: list[ActionRequest]
timeout: int | None = None
screen: str | None = None
user_agent: str | None = None
captcha: str | None = None
from engine.schemas import SolveRequest
from engine import actions
app = FastAPI()
@@ -32,56 +17,27 @@ async def root():
return {"message": "Hello World"}
async def _fill(page: "Page", act: ActionRequest) -> str | None:
...
async def _mouse_move(page: "Page", act: ActionRequest) -> str | None:
...
async def _click(page: "Page", act: ActionRequest) -> str | None:
...
async def _wait_for(page: Page, act: ActionRequest) -> str | None:
try:
assert act.selector
await page.wait_for_selector(act.selector, timeout=act.timeout * 1000)
except Exception as e:
return str(e)
else:
return None
@app.post("/v1/solve")
async def solve(request: Request, payload: SolveRequest):
api_key = request.headers.get('X-API-Key')
async with AsyncCamoufox() as camoufo:
page = await camoufo.new_page()
# TODO: настройка контекста
scr_w, scr_h = payload.screen.split("x")
scr_size = ViewportSize(width=int(scr_w), height=int(scr_h))
# TODO: распарс proxy-урл и заполнение объекта
# proxy = ProxySettings(socks5://host:port, username, password)
proxy = None
page = await camoufo.new_page(
user_agent=payload.user_agent,
proxy=proxy,
viewport=scr_size,
screen=scr_size,
)
page.set_default_timeout(30_000)
await page.goto(url=payload.url)
actions_result = []
status = True
error = None
for act in payload.actions:
result = await {
"fill": _fill,
"mouse_move": _mouse_move,
"click": _click,
"wait_for": _wait_for,
}[act.type](page, act)
if( ok := result ) is None:
act_log = {"type": act.type, "ok": ok}
else:
act_log = {"type": act.type, "ok": ok, "error": result}
actions_result.append(act_log)
if "error" in act_log:
status = False
error = act_log["error"]
break
actions_result = await actions.execute(page, payload.actions)
status = not "error" in actions_result[-1]
error = ["Something error", None][status]
cookies = await camoufo.cookies()
html = await page.inner_html('html')
await page.screenshot(