8.8 KiB
8.8 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, user_setup, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | user_setup | must_haves | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 07-login-auth | 02 | execute | 1 |
|
true |
|
|
Purpose: 支持 JSON Cookie 导入和 ~/.kb_env 文件持久化 Output: kb_workflow/auth/cookie_manager.py 模块 + 单元测试
<execution_context> @/home/starmen1265/.claude/get-shit-done/workflows/execute-plan.md @/home/starmen1265/.claude/get-shit-done/templates/summary.md </execution_context>
@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/07-login-auth/07-CONTEXT.md @.planning/phases/07-login-auth/07-RESEARCH.mdFrom kb_workflow/pipeline/config.py:
class KBSettings(BaseSettings):
zhihu_cookie: SecretStr = Field(default=SecretStr(""), description="知乎 Cookie")
model_config = SettingsConfigDict(
env_file=str(Path.home() / ".kb_env"),
env_file_encoding="utf-8",
env_prefix="KB_",
extra="ignore",
)
@lru_cache
def get_settings() -> KBSettings:
return KBSettings()
Chrome Cookie Editor JSON 格式示例:
[
{"name": "z_c0", "value": "xxx", "domain": ".zhihu.com"},
{"name": "_zap", "value": "yyy", "domain": ".zhihu.com"}
]
目标存储格式 (~/.kb_env):
ZHIHU_COOKIE="z_c0=xxx; _zap=yyy"
- 创建
kb_workflow/auth/cookie_manager.py:
"""Cookie 管理模块
处理 Cookie 的导入、转换和持久化。
"""
import json
from pathlib import Path
from typing import List, Dict, Any
def parse_json_cookies(json_path: str) -> str:
"""从 JSON 文件解析 Cookie 为字符串格式
支持 Chrome Cookie Editor 导出的 JSON 格式:
[{"name": "z_c0", "value": "xxx", "domain": ".zhihu.com"}, ...]
Args:
json_path: JSON 文件路径
Returns:
Cookie 字符串,格式: "name1=value1; name2=value2"
Raises:
ValueError: JSON 格式无效或文件不存在
"""
path = Path(json_path)
if not path.exists():
raise ValueError(f"Cookie file not found: {json_path}")
try:
with open(path, 'r', encoding='utf-8') as f:
cookies = json.load(f)
except json.JSONDecodeError as e:
raise ValueError(f"Invalid JSON format: {e}")
if not isinstance(cookies, list):
raise ValueError("Expected JSON array")
# 过滤知乎域名,转换为 name=value 格式
zhihu_cookies = []
for c in cookies:
if not isinstance(c, dict):
continue
domain = c.get('domain', '')
if 'zhihu.com' in domain:
name = c.get('name', '')
value = c.get('value', '')
if name and value:
zhihu_cookies.append(f"{name}={value}")
return '; '.join(zhihu_cookies)
- 创建
tests/test_auth/test_cookie_import.py:- 使用 tmp_path fixture 创建临时 JSON 文件
- 测试正常解析、域名过滤、空数组、格式错误等情况 pytest tests/test_auth/test_cookie_import.py -x -v
- parse_json_cookies 函数可用
- 4 个单元测试全部通过
- 正确过滤 zhihu.com 域名
from functools import lru_cache
class CookieManager:
"""Cookie 持久化管理器
管理 Cookie 在 ~/.kb_env 文件中的存储和读取。
"""
ENV_FILE_NAME = ".kb_env"
COOKIE_KEY = "ZHIHU_COOKIE"
def __init__(self, env_path: Path = None):
"""初始化管理器
Args:
env_path: 环境文件路径,默认 ~/.kb_env
"""
self.env_path = env_path or (Path.home() / self.ENV_FILE_NAME)
def save_cookie(self, cookie_str: str) -> None:
"""保存 Cookie 到环境文件
格式: ZHIHU_COOKIE="name1=value1; name2=value2"
Args:
cookie_str: Cookie 字符串
"""
# 读取现有内容
lines = []
if self.env_path.exists():
lines = self.env_path.read_text(encoding='utf-8').splitlines()
# 更新或添加 ZHIHU_COOKIE 行
cookie_line = f'{self.COOKIE_KEY}="{cookie_str}"'
found = False
for i, line in enumerate(lines):
if line.startswith(f"{self.COOKIE_KEY}="):
lines[i] = cookie_line
found = True
break
if not found:
lines.append(cookie_line)
# 写回文件,设置权限 600
self.env_path.write_text('\n'.join(lines) + '\n', encoding='utf-8')
self.env_path.chmod(0o600)
# 清除配置缓存
from kb_workflow.pipeline.config import get_settings
get_settings.cache_clear()
def load_cookie(self) -> str:
"""从环境文件加载 Cookie
Returns:
Cookie 字符串,不存在时返回空字符串
"""
if not self.env_path.exists():
return ""
content = self.env_path.read_text(encoding='utf-8')
for line in content.splitlines():
if line.startswith(f"{self.COOKIE_KEY}="):
# 提取引号内的值
value = line[len(f"{self.COOKIE_KEY}="):]
if value.startswith('"') and value.endswith('"'):
value = value[1:-1]
return value
return ""
创建 tests/test_auth/test_cookie_persistence.py:
- 使用 tmp_path fixture 创建临时环境文件
- 测试保存、更新、追加、加载等功能
- 测试文件权限设置
pytest tests/test_auth/test_cookie_persistence.py -x -v
- CookieManager 类可用
- 6 个单元测试全部通过
- Cookie 可正确保存到 ~/.kb_env
- 保存后自动清除配置缓存
<success_criteria>
- parse_json_cookies 函数支持 Chrome Cookie Editor 格式
- CookieManager 类支持保存和加载 Cookie
- ~/.kb_env 文件权限正确设置为 600
- 保存后自动清除 get_settings 缓存
- 10 个单元测试全部通过 </success_criteria>