修复了部分日程没有提醒时间的问题。

This commit is contained in:
2026-09-13 21:50:28 +08:00
parent 04fdf3d386
commit 0fef40c7f3
10 changed files with 485 additions and 37 deletions
+74
View File
@@ -110,6 +110,28 @@ export class DavClient {
return 'Basic ' + buffer.from(`${username}:${password}`).toString('base64');
}
/** GET 拉取单个资源的原始 ICS(调试诊断用) */
static async getRaw(url: string, auth: string): Promise<string> {
const httpRequest = http.createHttp();
try {
const resp: http.HttpResponse = await httpRequest.request(url, {
method: http.RequestMethod.GET,
header: {
'Authorization': auth,
'User-Agent': 'SyncCalendar/1.0'
},
connectTimeout: 10000,
readTimeout: 15000
});
if (resp.responseCode >= 200 && resp.responseCode < 300) {
return resp.result as string;
}
return `HTTP ${resp.responseCode}`;
} finally {
httpRequest.destroy();
}
}
/**
* 写权限探测:向日历本 PUT 一个探测资源——
* 2xx → 可写(随后删除探测资源);403/401 等 → 只读;网络异常 → 乐观按可写。
@@ -170,6 +192,58 @@ export class DavClient {
return DavClient.reportComponents(href, auth, 'VEVENT', '');
}
/**
* REPORT calendar-query:仅拉取 href + getetag(不含 calendar-data)。
* 部分服务器(如群晖)的 REPORT calendar-data 会剥离 VALARM 导致提醒丢失,
* 因此数据改为对变更资源逐个 GET 补拉(GET 返回完整 ICS)。
*/
static async reportEtags(href: string, auth: string): Promise<RemoteItem[]> {
const body: string = '<?xml version="1.0" encoding="utf-8"?>' +
'<c:calendar-query xmlns:d="DAV:" xmlns:c="urn:ietf:params:xml:ns:caldav">' +
'<d:prop><d:getetag/></d:prop>' +
'<c:filter><c:comp-filter name="VCALENDAR">' +
'<c:comp-filter name="VEVENT">' +
'</c:comp-filter></c:comp-filter></c:filter></c:calendar-query>';
const httpRequest = http.createHttp();
try {
const resp: http.HttpResponse = await httpRequest.request(href, {
method: 'REPORT' as http.RequestMethod,
header: {
'Authorization': auth,
'Content-Type': 'application/xml; charset=utf-8',
'Depth': '1',
'User-Agent': 'SyncCalendar/1.0'
},
extraData: body,
connectTimeout: 10000,
readTimeout: 30000
});
LogUtil.write(`HTTP REPORT(etag) ${href} → ${resp.responseCode}`);
if (resp.responseCode < 200 || resp.responseCode >= 300) {
throw new Error(`服务器返回状态码 ${resp.responseCode}`);
}
const xml: string = resp.result as string;
const items: RemoteItem[] = [];
const blocks: string[] = xml.split(/<\/[\w-]*:?response>/i);
for (const block of blocks) {
if (!/<[\w-]*:?response[\s>]/i.test(block)) {
continue;
}
const resHref: string = DavClient.extractTag(block, 'href');
if (resHref === '') {
continue;
}
const item = new RemoteItem();
item.href = resHref;
item.etag = DavClient.extractTag(block, 'getetag').replace(/"/g, '');
items.push(item);
}
return items;
} finally {
httpRequest.destroy();
}
}
/** REPORT calendar-query:拉取某日历本内所有 VTODO 待办(不限时间范围,量小) */
static async reportTodos(href: string, auth: string): Promise<RemoteItem[]> {
return DavClient.reportComponents(href, auth, 'VTODO', '');