选择 Workspace,并在需要时提交 organization/select。
(self, workspace_id: str)
| 2724 | return None |
| 2725 | |
| 2726 | def _select_workspace(self, workspace_id: str) -> Optional[str]: |
| 2727 | """选择 Workspace,并在需要时提交 organization/select。""" |
| 2728 | try: |
| 2729 | select_body = json.dumps({"workspace_id": workspace_id}) |
| 2730 | did = str(self.device_id or self.session.cookies.get("oai-did") or "").strip() |
| 2731 | headers = self._build_json_headers( |
| 2732 | referer="https://auth.openai.com/sign-in-with-chatgpt/codex/consent", |
| 2733 | include_device_id=True, |
| 2734 | did=did, |
| 2735 | ) |
| 2736 | |
| 2737 | response = self.session.post( |
| 2738 | OPENAI_API_ENDPOINTS["select_workspace"], |
| 2739 | headers=headers, |
| 2740 | data=select_body, |
| 2741 | allow_redirects=False, |
| 2742 | ) |
| 2743 | |
| 2744 | location = str(response.headers.get("Location") or "").strip() |
| 2745 | if response.status_code in [301, 302, 303, 307, 308] and location: |
| 2746 | import urllib.parse |
| 2747 | continue_url = urllib.parse.urljoin(OPENAI_API_ENDPOINTS["select_workspace"], location) |
| 2748 | self._log(f"Continue URL (Location): {continue_url[:100]}...") |
| 2749 | return continue_url |
| 2750 | |
| 2751 | if response.status_code != 200: |
| 2752 | self._log(f"选择 workspace 失败: {response.status_code}", "error") |
| 2753 | self._log(f"响应: {response.text[:200]}", "warning") |
| 2754 | return None |
| 2755 | |
| 2756 | payload: Dict[str, Any] = {} |
| 2757 | continue_url = "" |
| 2758 | try: |
| 2759 | payload = response.json() or {} |
| 2760 | continue_url = str(payload.get("continue_url") or "").strip() |
| 2761 | except Exception as json_err: |
| 2762 | body_text = str(response.text or "") |
| 2763 | self._log(f"workspace/select 非 JSON 响应,尝试文本兜底解析: {json_err}", "warning") |
| 2764 | m = re.search(r'"continue_url"\s*:\s*"([^"]+)"', body_text) |
| 2765 | if m: |
| 2766 | continue_url = str(m.group(1) or "").strip() |
| 2767 | if not continue_url: |
| 2768 | m2 = re.search(r"https://auth\.openai\.com/[^\s\"'<>]+", body_text) |
| 2769 | if m2: |
| 2770 | continue_url = str(m2.group(0) or "").strip() |
| 2771 | |
| 2772 | orgs = [] |
| 2773 | if isinstance(payload, dict): |
| 2774 | orgs = (((payload.get("data") or {}).get("orgs")) or []) if isinstance(payload.get("data"), dict) else [] |
| 2775 | |
| 2776 | if orgs: |
| 2777 | first_org = orgs[0] or {} |
| 2778 | org_id = str(first_org.get("id") or "").strip() |
| 2779 | project_id = str((((first_org.get("projects") or [None])[0]) or {}).get("id") or "").strip() |
| 2780 | if org_id: |
| 2781 | org_continue = self._select_organization( |
| 2782 | org_id=org_id, |
| 2783 | project_id=project_id, |