dsh-calendar 0.5.4 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -31
- package/README.en.md +39 -1
- package/README.md +41 -1
- package/lib/client.js +1381 -0
- package/lib/index.d.ts +28 -0
- package/lib/index.js +102 -1
- package/lib/settings.d.ts +83 -0
- package/lib/settings.js +139 -0
- package/lib/store.d.ts +10 -0
- package/lib/store.js +42 -0
- package/lib/tools.d.ts +11 -1
- package/lib/tools.js +16 -14
- package/lib/web.d.ts +134 -0
- package/lib/web.js +453 -0
- package/package.json +10 -1
- package/scripts/google-oauth.mjs +276 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,31 +1,52 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.6.0(2026-09-19)
|
|
4
|
+
|
|
5
|
+
- **新增设置页日历面板**:月 / 周 / 议程三种视图;点日程开右侧详情(时间、时长、重复规则的人话、地点、备注、uid),可直接改标题时间、加重复、删除(二次确认);新建支持全天 / 地点 / 备注 / RRULE;保存前做冲突检测。
|
|
6
|
+
- **新增对话页悬浮入口**:右下角 📅 小按钮点开同一个面板(非模态、Esc 关闭)。自绘 root 使用平台 seed 模块表里的 `react-dom/client`,控件优先用官方 `ui-primitives`(Button / Input / Checkbox / Modal / writeClipboard),老宿主缺这些时自动退回自绘控件,面板不会整块消失。
|
|
7
|
+
- **新增网页端后端** `/_dsh/dsh-calendar/settings`(status / list / create / update / delete):与 dsh-email 设置路由同一套安全模型 —— 仅回环地址可达、Host 必须是 localhost 名(挡 DNS rebinding)、写操作要求 `application/json` 且校验 Origin / Sec-Fetch-Site、响应永不回显凭据。
|
|
8
|
+
- 参数校验复用工具层同一套断言(`assertIsoTime` / `assertTimeRange`),校验失败不打扰 CalDAV 服务器;为此把 `asRecord` / `optionalString` / `assertIsoTime` / `assertTimeRange` / `isoNoMillis` / `sortEvents` 变成共享导出,避免两处语义漂移。
|
|
9
|
+
- 未配置 CalDAV 时面板显示引导态与「查看示例」,不再只丢一条报错。
|
|
10
|
+
- **新增面板内连接配置**:面板工具栏的「连接设置」支持 Google / iCloud / Nextcloud / 自建四种服务商。填完先「测试连接」(真去列未来 30 天日程),通过才允许保存;保存时服务端还会再测一次 —— 因此「保存成功」等价于「这套凭据刚才真的连上了」,一个连不上的地址不会被写进配置。密码 / clientSecret / refreshToken 不回填到前端(placeholder 显示「已保存,留空不改」),留空即沿用已存值。
|
|
11
|
+
- 面板配置写入宿主 settings 命名空间 `dsh-calendar`(`src/settings.ts`):**面板没填过的字段仍由 profile 的 `cordis.patch.yml` 兜底**,两份配置共存、老部署零迁移;宿主没有 settings 服务时面板自动退化为只读并说明原因。工具层改为「每次调用现取配置」(`CalendarConfigSource`),所以面板保存后无需重启。
|
|
12
|
+
- 后端新增 `connection` / `testConnection` / `saveConnection` 三个动作;新增依赖 `schemastery`。
|
|
13
|
+
- **修复**:宿主 settings 服务改为**懒接入**(每个请求前 `ctx.get('settings')`)。此前依赖 `ctx.inject(['settings'])` 子 fiber 的时序 —— 插件被重复 apply、或命名空间已被注册时它会静默失效,面板就永远停在「settings 服务不可用」。现在命名空间已被注册也不当作失败:值从 `describe()` 描述符读、写走 provider 的 `replace`,功能完全一致。
|
|
14
|
+
- **修复**:Nextcloud 表单缺 `username`(认证账号)字段,照原表单填完会报「未配置 username」(`user` 是用来拼 URL 的,认证用的是 `username`)。
|
|
15
|
+
- 连接设置表单补齐「怎么拿到这些值」:字段级小字提示 + 可展开的分步说明 + 外链(Google Cloud 凭据页 / OAuth Playground / Apple ID 设置),Nextcloud 的 `user` 与 `username` 也分别写了说明。测试 88 → 102 项。
|
|
16
|
+
- **新增 `scripts/google-oauth.mjs`**:一条命令换 Google refresh token —— 起一次性本地回环回调、自动打开浏览器、收到 code 后换 token 并打印;README(中英)的 Google 段改为用它,`files` 增加 `scripts` 让 npm 包内也带这份脚本。测试 102 → 106 项(含本地假令牌端点的全流程测试)。
|
|
17
|
+
- 该脚本随后加固:**clientId 自检**(拦下控制台列表里被截断显示的那串,避免拿到一张 Google 400 页)、**授权地址预检**(打开浏览器前先问一次 Google,400 就在终端把原因说清楚)、**PKCE(S256)**、以及回调端口的收尾(预检失败/超时/拒绝都不再留下监听)。测试 106 → 111 项。
|
|
18
|
+
- **新增兜底存储**:宿主没有 settings 服务、或命名空间注册失败且无人注册时,连接配置改存插件自己的文件 `$DSH_HOME/data/dsh-calendar/connection.json`(0600,与 dsh-email 的 token 文件同源),面板里会写明「存在哪个文件」而不是笼统一句「不可用」;`/connection` 也会带上 `settingsKind`(settings|file)与 `settingsReason`,便于排查。
|
|
19
|
+
- 文案:兜底存储的说明降级为弹窗底部一行小字(不再是一块看起来像报错的灰条),并改正「密码存在 settings.yaml」的说法 —— 兜底生效时它其实存在 `connection.json`。
|
|
20
|
+
- **修复**:settings 命名空间改为**插件加载时同步注册**。此前是在请求处理里懒注册,而宿主的 `register` 内部会 `ctx.effect(...)`(需要插件的活动作用域),在请求上下文里会失败;失败又被吞掉,于是表现成「面板看着能用,一保存就报 `settings namespace "dsh-calendar" is not registered`」。现在注册发生在 apply 阶段,真实失败会以 `dsh-calendar: …` 警告打到终端;插件被重复 apply 时第二个实例不再注册、直接搭既有注册的车。
|
|
21
|
+
- **修复**:Windows 上打开浏览器改用 `rundll32 url.dll,FileProtocolHandler`。此前用 `cmd /c start <url>`,授权 URL 里的 `&` 被 cmd 当成命令分隔符,浏览器只收到第一段 —— Google 的表现是 `Required parameter is missing: response_type`(预检查不出来,因为脚本自己发的请求是完整的)。换 token 脚本改为**交互式**:直接敲 `node scripts/google-oauth.mjs`,它会依次问 clientId 与 clientSecret,并识别「把文档示例文字当值粘进来」这种情况。
|
|
22
|
+
- CI 增加 `node --check lib/client.js`(网页端源码不走 tsc,只能语法自检)。测试 79 → 88 项。
|
|
23
|
+
|
|
24
|
+
> 完整历史(含详细改动说明)。README 只保留最近几个版本的一句话摘要。
|
|
25
|
+
|
|
26
|
+
## 中文版
|
|
27
|
+
|
|
28
|
+
- **0.5.4(2026-09-18)**:**修复**:①`calendar_update` 重建 VEVENT 会静默丢掉原事件的 ATTENDEE / ORGANIZER / EXDATE / STATUS / CATEGORIES / VALARM(改一次标题就删掉邀请人和提醒),现在改为在原始 VCALENDAR 上做字段级覆盖,并补齐 RFC 5545 必需的 VERSION / PRODID / UID / DTSTAMP;②RECURRENCE-ID 覆盖实例被忽略(被单独改期的实例按原时间+旧标题返回,或被 EXDATE 排掉后整条消失),现在建覆盖映射并在展开时替换对应实例;③`calendar_create` 返回本地拼的 uid 而忽略服务器 `Location`,导致 create 后 update 找不到事件(现在优先取 Location,缺失时回读确认),且 create 的 PUT body 补上 VERSION / PRODID / DTSTAMP。**优化**:重复事件展开预算耗尽时不再静默返回 0 条(DTSTART 在 2010 的每小时系列实测 680ms 且返回空),改为显式报错并提示缩小时间范围或补 COUNT/UNTIL;`calendar_search` 支持 `start` / `end` 并走 timeRange 查询(缺省用有界窗口),不再先整本下载再过滤。测试 68 → 79 项。
|
|
29
|
+
- **0.5.3(2026-09-11)**:复验官方 Harness 0.1.5-rc.1,更新整套同载与真实服务验证记录;运行时代码未变。
|
|
30
|
+
- **0.5.2(2026-09-08)**:补充官方 Harness 0.1.3-alpha.2 的安装、加载与真实 Google 工具调用验证,更新兼容性和 Node 版本要求;运行时代码与 0.5.0 相同。
|
|
31
|
+
- **0.5.1(2026-09-08)**:补充真实 Google OAuth/CalDAV 读取验证、`calendar.readonly` 与 `calendar` 范围对比及 Testing 刷新令牌到期说明;运行时代码与 0.5.0 相同。
|
|
32
|
+
- **0.5.0(2026-09-07)**:修复 Google CalDAV #2:新增 OAuth 凭据与环境变量配置、请求时刷新、取消与代理透传;健康检查区分 Basic/OAuth,修正误导的应用专用密码说明。保留其他服务的 Basic 认证。
|
|
33
|
+
- **0.4.0**:新增 `calendar_health` 自检(离线检查 CalDAV 端点与凭据配置,不验证连接)。
|
|
34
|
+
- **0.3.2**:
|
|
35
|
+
- 修复 `calendar_update` 更新其他字段时丢失 `rrule` 的问题。
|
|
36
|
+
- 更新与新建都会校验 `end >= start`,并拒绝 `2025-02-30` 这类不存在的日期。
|
|
37
|
+
- `calendar_list` / `calendar_search` 输出按开始时间稳定排序;搜索 `limit` clamp 到 1-200。
|
|
38
|
+
- CalDAV 客户端创建失败后清空缓存,下一次调用可自动重试,不再永久复用 rejected promise。
|
|
39
|
+
|
|
40
|
+
## English
|
|
41
|
+
|
|
42
|
+
- **0.5.4 (2026-09-18)**: **Fixes**: (1) `calendar_update` rebuilt the VEVENT and silently dropped ATTENDEE / ORGANIZER / EXDATE / STATUS / CATEGORIES / VALARM — renaming an event deleted its guests and reminders; the update now does field-level replacement on the original VCALENDAR and fills in the RFC 5545 essentials (VERSION / PRODID / UID / DTSTAMP). (2) RECURRENCE-ID overrides were ignored: a moved instance came back with its old time and title, or disappeared entirely when an EXDATE removed the original slot; overrides are now mapped and substituted during expansion. (3) `calendar_create` returned a locally invented uid instead of the server `Location`, so a follow-up update could not find the event (Location is now preferred, with a read-back check when absent), and the create body now carries VERSION / PRODID / DTSTAMP. **Improvements**: an exhausted expansion budget no longer returns an empty result silently (an hourly series starting in 2010 took 680ms and returned nothing) but raises a clear error suggesting a narrower range or COUNT/UNTIL; `calendar_search` accepts `start`/`end` and queries by timeRange instead of downloading the whole calendar first. Tests 68 → 79.
|
|
43
|
+
- **0.5.3 (2026-09-11)**: revalidate official Harness 0.1.5-rc.1 and refresh suite co-load and live-service evidence; runtime code is unchanged.
|
|
44
|
+
- **0.5.2 (2026-09-08)**: document installation, loading and real Google tool execution in official Harness 0.1.3-alpha.2; update compatibility and Node requirements. Runtime code is unchanged from 0.5.0.
|
|
45
|
+
- **0.5.1 (2026-09-08)**: document live Google OAuth/CalDAV read validation, the `calendar.readonly` versus `calendar` scope results and Testing refresh-token expiration. Runtime code is unchanged from 0.5.0.
|
|
46
|
+
- **0.5.0 (2026-09-07)**: fix Google CalDAV #2 with OAuth configuration/environment credentials, request-time refresh, cancellation and proxy forwarding. Make health checks and error guidance authentication-aware; retain Basic authentication for other servers.
|
|
47
|
+
- **0.4.0**: new `calendar_health` self-check (offline endpoint and credential configuration checks, not a connection test).
|
|
48
|
+
- **0.3.2**:
|
|
49
|
+
- Fix `calendar_update` dropping `rrule` while updating other fields.
|
|
50
|
+
- Validate `end >= start` and reject impossible dates such as `2025-02-30`.
|
|
51
|
+
- Sort `calendar_list` / `calendar_search` output by start time and clamp search `limit` to 1-200.
|
|
52
|
+
- Reset the cached CalDAV client after creation failure so the next tool call can retry.
|
package/README.en.md
CHANGED
|
@@ -33,6 +33,21 @@ Then restart the web service. To clean up fully, also remove the plugin entry fr
|
|
|
33
33
|
|
|
34
34
|
## Configuration
|
|
35
35
|
|
|
36
|
+
**Recommended: configure it in the panel (0.6.0+)**
|
|
37
|
+
|
|
38
|
+
Open「Connection」in the panel toolbar, pick a provider, fill in the address and account, hit **Test connection** (it really lists the next 30 days) and then **Save and enable**. The tools pick the new configuration up on their next call — no restart, no YAML editing.
|
|
39
|
+
|
|
40
|
+
What the panel saves lives in your local `settings.yaml` under the `dsh-calendar` namespace (the password is a secret field: no logs, no exports). If the host has no settings service (or the namespace cannot be registered), the connection is stored in the plugin’s own file `$DSH_HOME/data/dsh-calendar/connection.json` (0600) instead, and the panel says which one is in use. **The YAML remains the base layer**: any field the panel never touched still comes from it, so an existing `cordis.patch.yml` setup needs no migration; a headless host without a settings page still configures through YAML only.
|
|
41
|
+
|
|
42
|
+
Per-provider notes:
|
|
43
|
+
|
|
44
|
+
- **iCloud**: `caldavUrl` looks like `https://caldav.icloud.com/<numeric id>/calendars/<calendar id>/`; use an [app-specific password](https://appleid.apple.com/)
|
|
45
|
+
- **Nextcloud / self-hosted**: server URL + username + calendar name (self-hosted: the full collection URL, keep the trailing slash) and an app password
|
|
46
|
+
- **Google**: OAuth only — Google rejects every Basic password, including app passwords; needs `clientId` / `clientSecret` / `refreshToken` / `calendarId`
|
|
47
|
+
|
|
48
|
+
### Or: write YAML (advanced / headless)
|
|
49
|
+
|
|
50
|
+
The fields below mirror the panel form one-to-one; whatever the panel never set comes from here.
|
|
36
51
|
All configuration lives in your profile's cordis.patch.yml; override the `calendar` line by id (overriding replaces that line's config wholesale). Common fields:
|
|
37
52
|
|
|
38
53
|
- `provider`: google | icloud | nextcloud | custom
|
|
@@ -67,7 +82,19 @@ export DSH_CALENDAR_CLIENT_SECRET='your OAuth client secret'
|
|
|
67
82
|
export DSH_CALENDAR_REFRESH_TOKEN='your authorized refresh token'
|
|
68
83
|
```
|
|
69
84
|
|
|
70
|
-
These credentials come from your own Google Cloud OAuth client and a user authorization, not an email app password. Follow the [Google CalDAV setup guide](https://developers.google.com/workspace/calendar/caldav/v2/guide) to enable the API and configure OAuth. Request `https://www.googleapis.com/auth/calendar` for calendar read/write and offline access (`access_type=offline`) to obtain a refresh token; see [Google's offline authorization documentation](https://developers.google.com/identity/protocols/oauth2/web-server#offline).
|
|
85
|
+
These credentials come from your own Google Cloud OAuth client and a user authorization, not an email app password. Follow the [Google CalDAV setup guide](https://developers.google.com/workspace/calendar/caldav/v2/guide) to enable the API and configure OAuth. Request `https://www.googleapis.com/auth/calendar` for calendar read/write and offline access (`access_type=offline`) to obtain a refresh token; see [Google's offline authorization documentation](https://developers.google.com/identity/protocols/oauth2/web-server#offline). Supply an already authorized refresh token, or mint one with the helper below.
|
|
86
|
+
**Getting a refresh token (one command)**: register the client as a **Desktop app**, then:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
cd <plugin directory> # the source checkout, or node_modules/dsh-calendar
|
|
90
|
+
node scripts/google-oauth.mjs --client-id <your clientId> --client-secret <your clientSecret>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The script spins up a **one-shot local callback** (`http://127.0.0.1:<random port>/`), opens the browser for consent, exchanges the code and prints the refresh token — no hand-built URLs, no third-party playground.
|
|
94
|
+
|
|
95
|
+
Paste it into the panel’s「Connection」form (provider Google, calendarId = your Gmail address), or use the `DSH_CALENDAR_CLIENT_ID` / `DSH_CALENDAR_CLIENT_SECRET` / `DSH_CALENDAR_REFRESH_TOKEN` environment variables.
|
|
96
|
+
|
|
97
|
+
> While the OAuth consent screen is still in **Testing**, the refresh token lasts 7 days: hit **Publish app** on the OAuth consent screen to make it permanent (no review needed for personal use).
|
|
71
98
|
|
|
72
99
|
**Google CalDAV scope validation (2026-09-08):** for the same account and calendar, `calendar.readonly` allowed token refresh (200) and collection PROPFIND (207), but the event REPORT returned 403. With the `calendar` scope above, REPORT returned 207; a fresh verification process also refreshed the token and read successfully. Use this CalDAV scope configuration and verify an actual `calendar_list` request: successful token acquisition or collection discovery alone does not prove events are readable. This live test performed reads only; Google write operations were not tested.
|
|
73
100
|
|
|
@@ -140,6 +167,17 @@ If your CalDAV server is not directly reachable from your network (some regional
|
|
|
140
167
|
|
|
141
168
|
The stable event identifier `uid` is the CalDAV href (full object URL); `calendar_update` / `calendar_delete` use it.
|
|
142
169
|
|
|
170
|
+
## Calendar panel in Settings (0.6.0+)
|
|
171
|
+
|
|
172
|
+
Once installed, DSH grows a「Calendar」section in Settings; the chat page also gets a small 📅 button in the bottom-right that opens the same panel (non-modal, Esc closes).
|
|
173
|
+
|
|
174
|
+
- **Three views**: month (6×7 grid, today highlighted, click a cell to create), week (24-hour time grid, overlapping events side by side) and agenda (grouped by day).
|
|
175
|
+
- **Click to edit**: open any event in the right-hand drawer — time, duration, a human-readable repeat rule (`FREQ=WEEKLY;COUNT=6` → "weekly (6 times)"), location, notes, one-click uid copy — then edit or delete (deletion asks twice).
|
|
176
|
+
- **Create**: title, date, start/end, all-day, location, notes, repeat (daily/weekly/monthly/yearly, or a raw RRULE).
|
|
177
|
+
- **Conflict notice**: before saving, overlapping events are listed and you are asked whether to continue.
|
|
178
|
+
- **Configurable from the panel itself**: without a CalDAV account the panel shows guidance whose「Connection」button opens the form (test first, then save); a clearly labelled sample is one click away and never pretends to be your real calendar.
|
|
179
|
+
- **Theme and locale aware**: colours come from the host design tokens (`--dsw-*`), so light/dark themes follow automatically; copy follows Settings → General.
|
|
180
|
+
- **Security**: the panel only talks to the plugin’s own `/_dsh/dsh-calendar/settings`, which is loopback-only and re-checks Host, Origin and Content-Type on writes; credentials are never echoed back.
|
|
143
181
|
## Time and timezone
|
|
144
182
|
|
|
145
183
|
Input and output are uniformly ISO 8601. Timed events are output in UTC (e.g. `2025-01-15T01:00:00Z`); all-day events output `YYYY-MM-DD`. Input may carry a timezone offset (e.g. `2025-01-15T09:00:00+08:00`); the plugin converts to UTC internally for storage.
|
package/README.md
CHANGED
|
@@ -29,6 +29,21 @@ dsh plugin --profile web add dsh-calendar
|
|
|
29
29
|
|
|
30
30
|
## 配置
|
|
31
31
|
|
|
32
|
+
**推荐:在面板里配(0.6.0+)**
|
|
33
|
+
|
|
34
|
+
打开面板右上角的「连接设置」,选服务商 → 填地址与账号 → 点**「测试连接」**(它会真的去列未来 30 天的日程)→ 通过后点「保存并启用」。工具的下一次调用立刻用上新配置,不用重启、不用编辑 YAML。
|
|
35
|
+
|
|
36
|
+
面板写下的值优先存在本机 `settings.yaml` 的 `dsh-calendar` 命名空间里(密码是 secret 字段:不进日志、不进导出);若宿主没有 settings 服务(或命名空间注册失败),自动改存插件自己的文件 `$DSH_HOME/data/dsh-calendar/connection.json`(0600),面板里会明确显示当前存在哪。**YAML 仍然是基座**:面板没填过的字段由它兜底,所以已经用 `cordis.patch.yml` 配好的部署零迁移;纯 headless(没有设置页)的宿主依然只能走 YAML。
|
|
37
|
+
|
|
38
|
+
各服务商要点:
|
|
39
|
+
|
|
40
|
+
- **iCloud**:`caldavUrl` 形如 `https://caldav.icloud.com/<数字ID>/calendars/<日历ID>/`,密码用 [App 专用密码](https://appleid.apple.com/)
|
|
41
|
+
- **Nextcloud / 自建**:服务器地址 + 用户名 + 日历名(自建则给完整集合 URL,结尾的 `/` 别丢),密码用 App 密码
|
|
42
|
+
- **Google**:必须 OAuth,Google 不接受任何 Basic 密码;需要 `clientId` / `clientSecret` / `refreshToken` / `calendarId`
|
|
43
|
+
|
|
44
|
+
### 或者:写 YAML(高级 / headless)
|
|
45
|
+
|
|
46
|
+
下面的字段与面板表单一一对应;面板没设过的字段以这里为准。
|
|
32
47
|
所有配置都在你的 profile 的 cordis.patch.yml 里,按 id 覆盖 `calendar` 行(覆盖整行的 config)。通用字段:
|
|
33
48
|
|
|
34
49
|
- `provider`:google | icloud | nextcloud | custom
|
|
@@ -95,7 +110,21 @@ export DSH_CALENDAR_CLIENT_SECRET='你的 OAuth 客户端密钥'
|
|
|
95
110
|
export DSH_CALENDAR_REFRESH_TOKEN='你授权后取得的 refresh token'
|
|
96
111
|
```
|
|
97
112
|
|
|
98
|
-
凭据必须来自你自己的 Google Cloud OAuth 客户端和一次用户授权,而不是邮箱应用专用密码。按 [Google CalDAV 官方设置说明](https://developers.google.com/workspace/calendar/caldav/v2/guide) 启用 API、配置 OAuth;申请日历读写范围 `https://www.googleapis.com/auth/calendar`,并请求离线访问(`access_type=offline`)以取得刷新令牌,参见 [Google 离线授权说明](https://developers.google.com/identity/protocols/oauth2/web-server#offline)
|
|
113
|
+
凭据必须来自你自己的 Google Cloud OAuth 客户端和一次用户授权,而不是邮箱应用专用密码。按 [Google CalDAV 官方设置说明](https://developers.google.com/workspace/calendar/caldav/v2/guide) 启用 API、配置 OAuth;申请日历读写范围 `https://www.googleapis.com/auth/calendar`,并请求离线访问(`access_type=offline`)以取得刷新令牌,参见 [Google 离线授权说明](https://developers.google.com/identity/protocols/oauth2/web-server#offline)。已有 OAuth 配置的用户可直接填入刷新令牌。
|
|
114
|
+
|
|
115
|
+
**换 refresh token(一条命令)**:客户端类型选「桌面应用」,然后:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
cd <插件目录> # 源码仓库,或 node_modules/dsh-calendar
|
|
119
|
+
node scripts/google-oauth.mjs --client-id 你的clientId --client-secret 你的clientSecret
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
脚本会起一个**一次性本地回调**(`http://127.0.0.1:<随机端口>/`)、打开浏览器让你授权、收到 code 后换成 refresh token 并打印出来 —— 不用手工拼 URL,也不用第三方 Playground。
|
|
123
|
+
|
|
124
|
+
拿到后填进面板「连接设置」(provider 选 Google,calendarId 填你的 Gmail 地址);想走 YAML 的话就用环境变量 `DSH_CALENDAR_CLIENT_ID` / `DSH_CALENDAR_CLIENT_SECRET` / `DSH_CALENDAR_REFRESH_TOKEN`。
|
|
125
|
+
|
|
126
|
+
> 同意屏仍停在「测试」状态时 refresh token 只有 7 天有效:到「OAuth 同意屏幕」点一下「发布应用」即可长期有效(个人自用无需审核)。
|
|
127
|
+
|
|
99
128
|
|
|
100
129
|
**Google CalDAV 范围实测(2026-09-08)**:同一账号与日历使用 `calendar.readonly` 时,令牌刷新返回 200、集合探测 PROPFIND 返回 207,但读取日程 REPORT 返回 403;改为上述 `calendar` 范围后,REPORT 返回 207,重启验证进程后再次刷新和读取也通过。因此,请按这里的 CalDAV 配置申请范围,并用 `calendar_list` 验证真实读取,不能只凭令牌获取成功或集合探测成功判断日程可读。本次真实测试仅执行读取,没有验证 Google 的写入操作。
|
|
101
130
|
|
|
@@ -164,6 +193,17 @@ Nextcloud / 自定义 Basic 服务:检查账号、密码或服务要求的应
|
|
|
164
193
|
|
|
165
194
|
事件稳定标识 `uid` 为 CalDAV href(完整对象 URL),`calendar_update` / `calendar_delete` 使用它。
|
|
166
195
|
|
|
196
|
+
## 设置页里的日历面板(0.6.0+)
|
|
197
|
+
|
|
198
|
+
装好后,DSH 的「设置 → 日历」里会多出一节面板;对话页右下角还有一个 📅 小按钮,点开是同一个面板(非模态,Esc 关闭)。
|
|
199
|
+
|
|
200
|
+
- **三种视图**:月(6×7 网格,今天高亮,点格子直接新建)、周(24 小时时间网格,重叠日程并排显示)、议程(按天分组,最像「接下来要干什么」)。
|
|
201
|
+
- **点开就能改**:点任意日程打开右侧详情 —— 时间、时长、重复规则的人话(`FREQ=WEEKLY;COUNT=6` → 「每周(共 6 次)」)、地点、备注、uid 一键复制;接着「编辑」或「删除」(删除要二次确认)。
|
|
202
|
+
- **新建**:标题、日期、开始/结束、全天、地点、备注、重复(每天/每周/每月/每年,或直接写 RRULE)。
|
|
203
|
+
- **冲突提醒**:保存前若与已有日程重叠,会把重叠的几条列出来问你是否继续。
|
|
204
|
+
- **没配置也能配**:未填 CalDAV 账号时显示引导,点「连接设置」就在面板里把账号填好(先测后存);也可以点「查看示例」先看面板长什么样,示例数据有明确标注,不会冒充你的真实日历。
|
|
205
|
+
- **跟随主题与语言**:配色全部走宿主设计令牌(`--dsw-*`),深浅色主题自动适配;文案跟随 Settings → General 的语言。
|
|
206
|
+
- **安全**:面板只与插件自己的 `/_dsh/dsh-calendar/settings` 通信;该路由仅回环地址可达,写操作还要过 Host / Origin / Content-Type 三道校验,响应里永不回显账号密码。
|
|
167
207
|
## 时间与时区
|
|
168
208
|
|
|
169
209
|
输入输出统一 ISO 8601。定时事件输出为 UTC(如 `2025-01-15T01:00:00Z`),全天事件输出 `YYYY-MM-DD`。输入可带时区偏移(如 `2025-01-15T09:00:00+08:00`),插件内部转 UTC 存储。
|