内容
# Proton 日历 Playwright
Proton 日历没有提供公开的 API,这使得与外部工具或 AI 代理集成变得困难。该项目通过使用 **Playwright** 浏览器自动化与 Proton 日历网页界面进行编程交互,提供了 CLI 脚本和 **MCP 服务器**(模型上下文协议),适用于 AI 助手。
Proton 日历的浏览器自动化 - 从命令行或通过 **MCP 服务器**(模型上下文协议)创建事件、读取日程和管理日历。
与任何兼容 MCP 的 AI 客户端(opencode、Claude Desktop 等)配合使用,以便使用自然语言管理日历。
## 快速开始
```bash
# 1. 克隆并设置
git clone <仓库网址>
cd proton-calendar-playwright
python -m venv .venv
source .venv/bin/activate # 或 .venv\Scripts\activate 在 Windows 上
pip install -r requirements.txt
playwright install chromium
# 2. 设置凭证
cp .env.example .env
# 编辑 .env 文件,填写 Proton Mail 用户名和密码
# 3. 一次性身份验证
python auth.py --auto
# 4. 创建事件
python add_event.py --title "团队站会" --date 2026-06-05 --time 09:00 --duration 30
# 5. 读取日程
python read_events.py --days 7
```
## 脚本
| 脚本 | 用途 |
|--------|---------|
| `auth.py` | 登录 Proton 并保存会话 cookie |
| `add_event.py` | 创建日历事件 |
| `read_events.py` | 从日历视图中读取/提取事件 |
| `mcp_server.py` | 将所有操作公开为 MCP 工具 |
### `auth.py` — 身份验证
将 cookie、localStorage 和 IndexedDB 保存到 `auth/state.json`。在使用其他脚本之前需要执行此操作。
```bash
python auth.py --auto # 从 .env 凭证自动填充
python auth.py # 交互式手动登录
```
### `add_event.py` — 创建事件
```bash
python add_event.py --title "会议" --date 2025-12-25 --time 14:00 --duration 60
python add_event.py --title "午餐" # 今天,12:00,60 分钟
```
| 参数 | 必需 | 默认值 | 描述 |
|----------|----------|---------|-------------|
| `--title` | 是 | — | 事件标题 |
| `--date` | 否 | 今天 | 日期(YYYY-MM-DD) |
| `--time` | 否 | 12:00 | 开始时间(HH:MM) |
| `--duration` | 否 | 60 | 时长(分钟) |
批量模式 - 在单个浏览器会话中创建多个事件:
```bash
echo '[{"title": "A", "date": "2026-06-05"}, {"title": "B", "date": "2026-06-06"}]' | python add_event.py --batch
```
### `read_events.py` — 读取事件
```bash
python read_events.py --days 7 # 接下来 7 天
python read_events.py --days 1 # 今天
python read_events.py --date 2026-06-05 # 特定日期(快速 - 直接 URL)
```
| 参数 | 默认值 | 描述 |
|----------|---------|-------------|
| `--days` | 7 | 预测天数 |
| `--date` | — | 特定日期(YYYY-MM-DD),比 `--days` 快 |
## MCP 服务器设置
MCP 服务器允许 AI 助手(opencode、Claude Desktop、Cursor 等)直接控制您的日历。
### 手动启动
```bash
python mcp_server.py
```
### 在 opencode 中配置
添加到项目的 `opencode.json` 中:
```json
{
"mcp": {
"proton-calendar": {
"type": "local",
"command": ["python", "mcp_server.py"],
"cwd": "/path/to/proton-calendar-playwright",
"enabled": true
}
}
}
```
### 在 Claude Desktop 中配置
添加到 `claude_desktop_config.json` 中:
```json
{
"mcpServers": {
"proton-calendar": {
"command": "python",
"args": ["/path/to/proton-calendar-playwright/mcp_server.py"],
"cwd": "/path/to/proton-calendar-playwright"
}
}
}
```
### 可用的 MCP 工具
| 工具 | 描述 | 参数 |
|------|-------------|------------|
| `add_event` | 创建日历事件 | `title`(必需),`date?`,`time?`,`duration?` |
| `add_events_batch` | 在一个浏览器会话中创建多个事件 | `events`(`{title, date?, time?, duration?}` 数组) |
| `read_events` | 列出即将到来的事件 | `days?`(默认 7),`date?`(YYYY-MM-DD) |
| `auth` | 与 Proton 重新身份验证 | `auto?`(默认:true) |
## OpenCode 技能设置
存储库在 `.opencode/skills/` 和 `skills/` 下包含三个技能,这些技能使 opencode 代理对自动化模式有深入的了解:
| 技能 | 位置 | 用途 |
|-------|----------|---------|
| `playwright-testing` | `.opencode/skills/` | 指导编写新的 Playwright 脚本 |
| `proton-automation-developer` | `.opencode/skills/` | 调试、修复和扩展脚本 |
| `proton-calendar-buddy` | `skills/` | 通过 MCP 进行终端用户日历管理 |
在 opencode 中打开此项目时,技能会自动加载。不需要额外的配置。
### 示例提示
配置完成后,您可以询问您的 AI 助手:
**日历管理:**
- "今天我的日历上有什麼?"
- "明天 2 点添加一个牙医预约,持续 1 小时"
- "星期五 3 点我有空吗?"
- "每周星期一 10 点安排一个会议"
- "下周我的日程是怎样的?"
**开发:**
- "编写一个从 Proton 日历中删除事件的脚本"
- "`add_event` 脚本无法找到“保存”按钮 - 调试它"
- "添加对重复事件的支持"
- "创建一个将我的日历导出到 CSV 的脚本"
## 技术细节
### 架构
```
proton-calendar-playwright/
├── auth.py # 登录流程 - 保存会话
├── add_event.py # 事件创建,支持波兰语/英语 UI
├── read_events.py # 通过 DOM 解析提取事件
├── mcp_server.py # MCP 传输层(stdio)
├── skills/
│ └── proton-calendar-buddy/
│ └── SKILL.md # 面向用户的技能
├── .opencode/
│ └── skills/
│ ├── playwright-testing/
│ │ └── SKILL.md # 开发技能,用于编写新脚本
│ └── proton-automation-developer/
│ └── SKILL.md # 开发技能,用于调试/修复
├── requirements.txt
├── .env.example
└── opencode.json # opencode MCP 配置
```
### 工作原理
- **Playwright**(Python 同步 API)启动 Chromium,加载 `auth/state.json` 中保存的会话,并与 Proton 日历 SPA 交互。
- **会话持久性** 使用 `context.storage_state()` 保存 cookie + localStorage + IndexedDB - 不需要在每次运行时重新登录。
- **事件创建** 打开“新建事件”对话框,使用弹性定位策略(`get_by_role` → `get_by_text` → CSS 备用)填写标题/日期/时间/时长,并单击保存。
- **事件读取** 通过直接 URL 导航到周视图(`/u/0/week/YYYY/M/D`),解析页面标题以确定周范围,并使用事件单元格的 x 位置从 DOM 中提取它们以分配正确的日期。
- **MCP 服务器** 使用官方的 `mcp` Python 包(stdio 传输),通过子进程委托给 CLI 脚本。
### 恢复模式
所有脚本都遵循严格的规则,以避免在 Proton 日历的缓慢 SPA 中挂起:
- **无 `networkidle`** - 代替使用 `"load"` 或 `"domcontentloaded"`
- **短超时** - 定位器:3-5 秒,页面加载:10-15 秒
- **渐进式降级** - 所有定位器调用都包装在 try/except 中
- **双语** - 处理英语和波兰语 UI 标签
- **自动关闭模态** - 欢迎/引导模态被点击关闭
- **会话刷新** - 每个操作后重新保存会话状态
- **`finally` 清理** - 浏览器始终关闭,即使出现错误
### 依赖项
- Python 3.10+
- `playwright` - 浏览器自动化
- `python-dotenv` - 凭证加载
- `mcp` - MCP 服务器框架
- Chromium 浏览器(通过 `playwright install chromium` 安装)
## 安全
- **从不提交 `.env`** - 它包含您的 Proton 凭证(已经 gitignored)
- **从不提交 `auth/state.json`** - 它包含您的会话令牌(已经 gitignored)
- `.env.example` 文件仅包含占位值
- 所有脚本都使用环境变量进行凭证管理 - 没有硬编码的秘密
## 故障排除
| 问题 | 修复方法 |
|---------|-----|
| **会话过期** | 再次运行 `python auth.py --auto` |
| **"无法点击..."** | UI 语言已更改 - 将标签文本添加到多语言列表中 |
| **日期未填写** | 尝试波兰语月份格式(例如 `cze` 而不是 `Jun`) |
| **未找到事件** | 周标题解析可能失败 - 检查页面标题格式 |
| **脚本挂起** | Ctrl+C 并重新运行 - 所有脚本都可以安全中断 |
| **批量超时** | 使用 `read_events` 检查已创建的内容,并仅添加缺少的事件 |
| **模态阻止 UI** | 脚本自动关闭欢迎模态。如果卡住,在浏览器中按 `Escape` |