(adapter, post: Post, body_markdown: str, headed: bool, validate_only: bool)
| 1063 | |
| 1064 | |
| 1065 | def run_adapter(adapter, post: Post, body_markdown: str, headed: bool, validate_only: bool) -> dict[str, Any]: |
| 1066 | from playwright.sync_api import sync_playwright |
| 1067 | |
| 1068 | with sync_playwright() as pw: |
| 1069 | launch_kwargs: dict[str, Any] = {"headless": not headed} |
| 1070 | browser = pw.chromium.launch(**launch_kwargs) |
| 1071 | context_kwargs: dict[str, Any] = { |
| 1072 | "viewport": {"width": 1400, "height": 900}, |
| 1073 | "user_agent": _UA_STR, |
| 1074 | } |
| 1075 | # Adapters that authenticate via a saved Playwright storageState |
| 1076 | # (Hashnode, and historically Medium/DZone) expose a |
| 1077 | # `storage_state_path()` classmethod that returns a path to the |
| 1078 | # decoded JSON. FoojayAdapter logs in with user+password and does |
| 1079 | # not define it. |
| 1080 | storage_state_method = getattr(adapter, "storage_state_path", None) |
| 1081 | if callable(storage_state_method): |
| 1082 | try: |
| 1083 | context_kwargs["storage_state"] = str(storage_state_method()) |
| 1084 | except KeyError as err: |
| 1085 | raise AdapterError( |
| 1086 | f"{adapter.name} needs a storage-state env var: {err}" |
| 1087 | ) from err |
| 1088 | context = browser.new_context(**context_kwargs) |
| 1089 | # Grant clipboard access so navigator.clipboard.writeText() succeeds. |
| 1090 | try: |
| 1091 | context.grant_permissions(["clipboard-read", "clipboard-write"]) |
| 1092 | except Exception: # noqa: BLE001 |
| 1093 | # Firefox and WebKit reject the chromium-only clipboard-* perms. |
| 1094 | # Adapters that need the clipboard fall back to other paths |
| 1095 | # (Quill API, Froala API, execCommand insertHTML), so a refusal |
| 1096 | # here is non-fatal. |
| 1097 | pass |
| 1098 | |
| 1099 | page = context.new_page() |
| 1100 | ctx = AdapterContext(post=post, body_markdown=body_markdown, headed=headed, validate_only=validate_only) |
| 1101 | |
| 1102 | try: |
| 1103 | adapter.login(page) |
| 1104 | result = adapter.submit_draft(page, ctx) |
| 1105 | except Exception as err: # noqa: BLE001 |
| 1106 | shot = _save_screenshot(page, post.slug, f"{adapter.name}-error") |
| 1107 | raise AdapterError(f"{adapter.name} flow failed (screenshot: {shot}): {err}") from err |
| 1108 | finally: |
| 1109 | context.close() |
| 1110 | browser.close() |
| 1111 | return result |
| 1112 | |
| 1113 | |
| 1114 | def parse_args(argv: list[str]) -> argparse.Namespace: |
no test coverage detected