proton-mail-bridge-client 2.16.2 → 2.17.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/README.md +149 -12
- package/dist/cli.d.ts +16 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +178 -1
- package/dist/cli.js.map +1 -1
- package/dist/config-env.d.ts +2 -1
- package/dist/config-env.d.ts.map +1 -1
- package/dist/config-env.js +24 -0
- package/dist/config-env.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +180 -11
- package/dist/index.js.map +1 -1
- package/dist/services/account-manager.d.ts +7 -0
- package/dist/services/account-manager.d.ts.map +1 -1
- package/dist/services/account-manager.js +59 -0
- package/dist/services/account-manager.js.map +1 -1
- package/dist/services/audit-service.d.ts +20 -0
- package/dist/services/audit-service.d.ts.map +1 -1
- package/dist/services/audit-service.js +266 -9
- package/dist/services/audit-service.js.map +1 -1
- package/dist/services/autoresponder-service.d.ts +35 -6
- package/dist/services/autoresponder-service.d.ts.map +1 -1
- package/dist/services/autoresponder-service.js +223 -108
- package/dist/services/autoresponder-service.js.map +1 -1
- package/dist/services/brief-service.d.ts +7 -1
- package/dist/services/brief-service.d.ts.map +1 -1
- package/dist/services/brief-service.js +19 -5
- package/dist/services/brief-service.js.map +1 -1
- package/dist/services/category-service.d.ts +91 -0
- package/dist/services/category-service.d.ts.map +1 -0
- package/dist/services/category-service.js +320 -0
- package/dist/services/category-service.js.map +1 -0
- package/dist/services/commitment-service.d.ts.map +1 -1
- package/dist/services/commitment-service.js +9 -3
- package/dist/services/commitment-service.js.map +1 -1
- package/dist/services/contact-service.d.ts +60 -0
- package/dist/services/contact-service.d.ts.map +1 -0
- package/dist/services/contact-service.js +248 -0
- package/dist/services/contact-service.js.map +1 -0
- package/dist/services/delivery-queue-service.d.ts +4 -0
- package/dist/services/delivery-queue-service.d.ts.map +1 -1
- package/dist/services/delivery-queue-service.js +12 -2
- package/dist/services/delivery-queue-service.js.map +1 -1
- package/dist/services/draft-store-service.d.ts.map +1 -1
- package/dist/services/draft-store-service.js +3 -2
- package/dist/services/draft-store-service.js.map +1 -1
- package/dist/services/embedding-service.d.ts +68 -0
- package/dist/services/embedding-service.d.ts.map +1 -0
- package/dist/services/embedding-service.js +465 -0
- package/dist/services/embedding-service.js.map +1 -0
- package/dist/services/event-log-service.d.ts +67 -0
- package/dist/services/event-log-service.d.ts.map +1 -0
- package/dist/services/event-log-service.js +280 -0
- package/dist/services/event-log-service.js.map +1 -0
- package/dist/services/grant-service.d.ts +84 -0
- package/dist/services/grant-service.d.ts.map +1 -0
- package/dist/services/grant-service.js +214 -0
- package/dist/services/grant-service.js.map +1 -0
- package/dist/services/local-index-service.d.ts +18 -1
- package/dist/services/local-index-service.d.ts.map +1 -1
- package/dist/services/local-index-service.js +54 -4
- package/dist/services/local-index-service.js.map +1 -1
- package/dist/services/reply-reminder-service.d.ts +4 -0
- package/dist/services/reply-reminder-service.d.ts.map +1 -1
- package/dist/services/reply-reminder-service.js +22 -2
- package/dist/services/reply-reminder-service.js.map +1 -1
- package/dist/services/rules-service.d.ts +9 -1
- package/dist/services/rules-service.d.ts.map +1 -1
- package/dist/services/rules-service.js +8 -3
- package/dist/services/rules-service.js.map +1 -1
- package/dist/services/sieve-export.d.ts +19 -0
- package/dist/services/sieve-export.d.ts.map +1 -0
- package/dist/services/sieve-export.js +192 -0
- package/dist/services/sieve-export.js.map +1 -0
- package/dist/services/simple-imap-service.d.ts +13 -0
- package/dist/services/simple-imap-service.d.ts.map +1 -1
- package/dist/services/simple-imap-service.js +142 -18
- package/dist/services/simple-imap-service.js.map +1 -1
- package/dist/services/smtp-service.d.ts +1 -0
- package/dist/services/smtp-service.d.ts.map +1 -1
- package/dist/services/smtp-service.js +20 -0
- package/dist/services/smtp-service.js.map +1 -1
- package/dist/services/snooze-service.d.ts +4 -0
- package/dist/services/snooze-service.d.ts.map +1 -1
- package/dist/services/snooze-service.js +12 -3
- package/dist/services/snooze-service.js.map +1 -1
- package/dist/services/template-service.d.ts.map +1 -1
- package/dist/services/template-service.js +3 -2
- package/dist/services/template-service.js.map +1 -1
- package/dist/services/triage-plan-service.d.ts +10 -2
- package/dist/services/triage-plan-service.d.ts.map +1 -1
- package/dist/services/triage-plan-service.js +23 -3
- package/dist/services/triage-plan-service.js.map +1 -1
- package/dist/tools/attachments.js +1 -1
- package/dist/tools/attachments.js.map +1 -1
- package/dist/tools/brief.d.ts.map +1 -1
- package/dist/tools/brief.js +14 -4
- package/dist/tools/brief.js.map +1 -1
- package/dist/tools/categories.d.ts +4 -0
- package/dist/tools/categories.d.ts.map +1 -0
- package/dist/tools/categories.js +269 -0
- package/dist/tools/categories.js.map +1 -0
- package/dist/tools/commitments.d.ts.map +1 -1
- package/dist/tools/commitments.js +6 -2
- package/dist/tools/commitments.js.map +1 -1
- package/dist/tools/contacts.d.ts +6 -0
- package/dist/tools/contacts.d.ts.map +1 -0
- package/dist/tools/contacts.js +295 -0
- package/dist/tools/contacts.js.map +1 -0
- package/dist/tools/context.d.ts +4 -0
- package/dist/tools/context.d.ts.map +1 -1
- package/dist/tools/context.js +3 -0
- package/dist/tools/context.js.map +1 -1
- package/dist/tools/definitions.d.ts +333 -5
- package/dist/tools/definitions.d.ts.map +1 -1
- package/dist/tools/definitions.js +169 -5
- package/dist/tools/definitions.js.map +1 -1
- package/dist/tools/delegation.d.ts +44 -0
- package/dist/tools/delegation.d.ts.map +1 -0
- package/dist/tools/delegation.js +180 -0
- package/dist/tools/delegation.js.map +1 -0
- package/dist/tools/diagnostics.d.ts.map +1 -1
- package/dist/tools/diagnostics.js +6 -0
- package/dist/tools/diagnostics.js.map +1 -1
- package/dist/tools/drafts-support.d.ts +2 -1
- package/dist/tools/drafts-support.d.ts.map +1 -1
- package/dist/tools/drafts-support.js +14 -6
- package/dist/tools/drafts-support.js.map +1 -1
- package/dist/tools/drafts.d.ts.map +1 -1
- package/dist/tools/drafts.js +22 -1
- package/dist/tools/drafts.js.map +1 -1
- package/dist/tools/events.d.ts +47 -0
- package/dist/tools/events.d.ts.map +1 -0
- package/dist/tools/events.js +240 -0
- package/dist/tools/events.js.map +1 -0
- package/dist/tools/reading.d.ts.map +1 -1
- package/dist/tools/reading.js +125 -4
- package/dist/tools/reading.js.map +1 -1
- package/dist/tools/resources.d.ts +4 -0
- package/dist/tools/resources.d.ts.map +1 -1
- package/dist/tools/resources.js +9 -0
- package/dist/tools/resources.js.map +1 -1
- package/dist/tools/rules-runner.d.ts.map +1 -1
- package/dist/tools/rules-runner.js +1 -0
- package/dist/tools/rules-runner.js.map +1 -1
- package/dist/tools/rules.d.ts +9 -0
- package/dist/tools/rules.d.ts.map +1 -1
- package/dist/tools/rules.js +50 -19
- package/dist/tools/rules.js.map +1 -1
- package/dist/tools/sending.d.ts.map +1 -1
- package/dist/tools/sending.js +4 -0
- package/dist/tools/sending.js.map +1 -1
- package/dist/tools/style.d.ts +2 -0
- package/dist/tools/style.d.ts.map +1 -1
- package/dist/tools/style.js +3 -3
- package/dist/tools/style.js.map +1 -1
- package/dist/tools/templates-and-reminders.d.ts +3 -0
- package/dist/tools/templates-and-reminders.d.ts.map +1 -1
- package/dist/tools/templates-and-reminders.js +31 -17
- package/dist/tools/templates-and-reminders.js.map +1 -1
- package/dist/tools/triage.d.ts.map +1 -1
- package/dist/tools/triage.js +33 -11
- package/dist/tools/triage.js.map +1 -1
- package/dist/types/index.d.ts +23 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/account-identity.d.ts.map +1 -1
- package/dist/utils/account-identity.js +3 -2
- package/dist/utils/account-identity.js.map +1 -1
- package/dist/utils/approval.d.ts +133 -0
- package/dist/utils/approval.d.ts.map +1 -0
- package/dist/utils/approval.js +507 -0
- package/dist/utils/approval.js.map +1 -0
- package/dist/utils/atomic-write.d.ts +1 -1
- package/dist/utils/atomic-write.d.ts.map +1 -1
- package/dist/utils/atomic-write.js +10 -3
- package/dist/utils/atomic-write.js.map +1 -1
- package/dist/utils/commitment-phrases.d.ts.map +1 -1
- package/dist/utils/commitment-phrases.js +31 -18
- package/dist/utils/commitment-phrases.js.map +1 -1
- package/dist/utils/contact-text.d.ts +8 -0
- package/dist/utils/contact-text.d.ts.map +1 -0
- package/dist/utils/contact-text.js +24 -0
- package/dist/utils/contact-text.js.map +1 -0
- package/dist/utils/delegation.d.ts +17 -0
- package/dist/utils/delegation.d.ts.map +1 -0
- package/dist/utils/delegation.js +72 -0
- package/dist/utils/delegation.js.map +1 -0
- package/dist/utils/file-lock.d.ts.map +1 -1
- package/dist/utils/file-lock.js +5 -4
- package/dist/utils/file-lock.js.map +1 -1
- package/dist/utils/mail-security.d.ts +9 -1
- package/dist/utils/mail-security.d.ts.map +1 -1
- package/dist/utils/mail-security.js +444 -62
- package/dist/utils/mail-security.js.map +1 -1
- package/dist/utils/ocr.d.ts +24 -0
- package/dist/utils/ocr.d.ts.map +1 -0
- package/dist/utils/ocr.js +109 -0
- package/dist/utils/ocr.js.map +1 -0
- package/dist/utils/office-text-worker.d.ts +2 -0
- package/dist/utils/office-text-worker.d.ts.map +1 -0
- package/dist/utils/office-text-worker.js +17 -0
- package/dist/utils/office-text-worker.js.map +1 -0
- package/dist/utils/office-text.d.ts +32 -0
- package/dist/utils/office-text.d.ts.map +1 -0
- package/dist/utils/office-text.js +540 -0
- package/dist/utils/office-text.js.map +1 -0
- package/dist/utils/pdf-text-worker.js +2 -2
- package/dist/utils/pdf-text-worker.js.map +1 -1
- package/dist/utils/pdf-text.d.ts +10 -0
- package/dist/utils/pdf-text.d.ts.map +1 -1
- package/dist/utils/pdf-text.js +49 -9
- package/dist/utils/pdf-text.js.map +1 -1
- package/dist/utils/png.d.ts +2 -0
- package/dist/utils/png.d.ts.map +1 -0
- package/dist/utils/png.js +26 -0
- package/dist/utils/png.js.map +1 -0
- package/dist/utils/regular-file.d.ts +9 -0
- package/dist/utils/regular-file.d.ts.map +1 -0
- package/dist/utils/regular-file.js +34 -0
- package/dist/utils/regular-file.js.map +1 -0
- package/dist/utils/runtime-policy.d.ts.map +1 -1
- package/dist/utils/runtime-policy.js +2 -0
- package/dist/utils/runtime-policy.js.map +1 -1
- package/dist/utils/safe-write.d.ts +8 -0
- package/dist/utils/safe-write.d.ts.map +1 -0
- package/dist/utils/safe-write.js +46 -0
- package/dist/utils/safe-write.js.map +1 -0
- package/dist/utils/server-state-paths.d.ts +12 -0
- package/dist/utils/server-state-paths.d.ts.map +1 -0
- package/dist/utils/server-state-paths.js +69 -0
- package/dist/utils/server-state-paths.js.map +1 -0
- package/dist/utils/style-profile.d.ts +18 -0
- package/dist/utils/style-profile.d.ts.map +1 -1
- package/dist/utils/style-profile.js +63 -14
- package/dist/utils/style-profile.js.map +1 -1
- package/dist/utils/vcard.d.ts +27 -0
- package/dist/utils/vcard.d.ts.map +1 -0
- package/dist/utils/vcard.js +141 -0
- package/dist/utils/vcard.js.map +1 -0
- package/dist/utils/zip-reader.d.ts +16 -0
- package/dist/utils/zip-reader.d.ts.map +1 -0
- package/dist/utils/zip-reader.js +108 -0
- package/dist/utils/zip-reader.js.map +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import { mkdir } from "node:fs/promises";
|
|
2
|
+
import { readRegularFile } from "../utils/regular-file.js";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { writeFileAtomic } from "../utils/atomic-write.js";
|
|
5
|
+
import { INVISIBLE } from "../utils/contact-text.js";
|
|
6
|
+
import { isFileNotFound, setAsideCorruptStore } from "../utils/corrupt-store.js";
|
|
7
|
+
import { withFileLock } from "../utils/file-lock.js";
|
|
8
|
+
import { InvalidArgumentError } from "../utils/helpers.js";
|
|
9
|
+
import { logger } from "../utils/logger.js";
|
|
10
|
+
import { assessMail } from "../utils/mail-security.js";
|
|
11
|
+
// Proton Mail's own categories (proton.me/support/mail-categories). A user category or label with one of these names
|
|
12
|
+
// is separate from Proton's and is reported as a clash; nothing here can see or change Proton's sorting.
|
|
13
|
+
export const PROTON_CATEGORIES = ["Primary", "Social", "Promotions", "Newsletters", "Transactions", "Updates"];
|
|
14
|
+
export const MAX_CATEGORIES = 30;
|
|
15
|
+
const MAX_LEARNED = 2000;
|
|
16
|
+
const MAX_SUBJECT_SCANNED = 1000;
|
|
17
|
+
const MAX_KEYWORDS_COUNTED = 2;
|
|
18
|
+
export const MIN_SCORE = 2;
|
|
19
|
+
const SCORE = { learned: 10, senderAddress: 6, senderDomain: 5, keyword: 3, automated: 2, knownContact: 4 };
|
|
20
|
+
// Offered only when the user asks for it.
|
|
21
|
+
export const STARTER_CATEGORIES = [
|
|
22
|
+
{
|
|
23
|
+
name: "Receipts",
|
|
24
|
+
description: "Receipts, invoices, orders, bookings and payment confirmations.",
|
|
25
|
+
keywords: ["receipt", "invoice", "order", "payment", "purchase", "booking", "faktur", "rachun", "paragon", "zamówieni", "płatnoś", "rechnung", "quittung", "bestellung", "zahlung"],
|
|
26
|
+
},
|
|
27
|
+
{ name: "Newsletters", description: "Newsletters, digests and other mail you subscribed to.", automated: true, keywords: ["newsletter", "digest", "weekly", "edition"] },
|
|
28
|
+
{
|
|
29
|
+
name: "Social",
|
|
30
|
+
description: "Notifications from social networks.",
|
|
31
|
+
senders: ["@facebookmail.com", "@linkedin.com", "@x.com", "@twitter.com", "@instagram.com", "@redditmail.com", "@discord.com", "@pinterest.com", "@tiktok.com", "@mastodon.social"],
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: "Updates",
|
|
35
|
+
description: "Automatic notices: account and security alerts, shipping, reminders.",
|
|
36
|
+
automated: true,
|
|
37
|
+
keywords: ["alert", "security", "sign-in", "login", "password", "verify", "verification", "confirm", "shipped", "delivery", "reminder", "notification", "powiadomieni", "przesyłk", "benachrichtigung", "lieferung"],
|
|
38
|
+
},
|
|
39
|
+
{ name: "People", description: "Mail written to you by a person.", automated: false, knownContact: true },
|
|
40
|
+
];
|
|
41
|
+
const key = (name) => name.trim().toLowerCase();
|
|
42
|
+
const WORD_CHAR = /[\p{L}\p{N}]/u;
|
|
43
|
+
const CONTROL = /[\u0000-\u001f\u007f]/g;
|
|
44
|
+
/** Keywords that start a word in the subject (case-insensitive), in the order they were defined. */
|
|
45
|
+
function matchingKeywords(keywords, subject) {
|
|
46
|
+
const hay = subject.slice(0, MAX_SUBJECT_SCANNED).toLowerCase();
|
|
47
|
+
const found = [];
|
|
48
|
+
for (const keyword of keywords ?? []) {
|
|
49
|
+
const needle = keyword.toLowerCase();
|
|
50
|
+
for (let at = hay.indexOf(needle); at !== -1; at = hay.indexOf(needle, at + 1)) {
|
|
51
|
+
if (at === 0 || !WORD_CHAR.test(hay[at - 1])) {
|
|
52
|
+
found.push(keyword);
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return found;
|
|
58
|
+
}
|
|
59
|
+
function matchSender(patterns, address) {
|
|
60
|
+
if (!address.includes("@"))
|
|
61
|
+
return undefined;
|
|
62
|
+
const domain = address.slice(address.lastIndexOf("@") + 1);
|
|
63
|
+
const list = patterns ?? [];
|
|
64
|
+
const exact = list.find((pattern) => !pattern.includes("*") && !pattern.startsWith("@") && pattern.toLowerCase() === address);
|
|
65
|
+
if (exact)
|
|
66
|
+
return { pattern: exact, exact: true };
|
|
67
|
+
for (const pattern of list) {
|
|
68
|
+
const lower = pattern.toLowerCase();
|
|
69
|
+
if (!lower.startsWith("@") && !lower.startsWith("*@"))
|
|
70
|
+
continue;
|
|
71
|
+
const wanted = lower.slice(lower.indexOf("@") + 1);
|
|
72
|
+
if (domain === wanted || domain.endsWith(`.${wanted}`))
|
|
73
|
+
return { pattern, exact: false };
|
|
74
|
+
}
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
/** Which category a message belongs to and why. Pure: the same definitions, weights and message give the same verdict. */
|
|
78
|
+
export function classifyMessage(categories, learned, message) {
|
|
79
|
+
const from = message.from.trim().toLowerCase();
|
|
80
|
+
const trustSender = !message.authFailure;
|
|
81
|
+
const weights = new Map(learned.filter((entry) => entry.sender === from).map((entry) => [entry.category, entry.weight]));
|
|
82
|
+
const scored = [];
|
|
83
|
+
for (const category of categories) {
|
|
84
|
+
const reasons = [];
|
|
85
|
+
let score = 0;
|
|
86
|
+
let senderScore = 0;
|
|
87
|
+
const learnedWeight = trustSender ? (weights.get(key(category.name)) ?? 0) : 0;
|
|
88
|
+
if (learnedWeight > 0) {
|
|
89
|
+
score += learnedWeight * SCORE.learned;
|
|
90
|
+
senderScore += learnedWeight * SCORE.learned;
|
|
91
|
+
reasons.push(`you put mail from ${from} in ${category.name} (${learnedWeight} correction${learnedWeight === 1 ? "" : "s"})`);
|
|
92
|
+
}
|
|
93
|
+
if (category.automated !== undefined && message.automated !== undefined) {
|
|
94
|
+
if (category.automated === message.automated) {
|
|
95
|
+
score += SCORE.automated;
|
|
96
|
+
reasons.push(category.automated ? "list or bulk mail (List-Unsubscribe, List-Id or Precedence header)" : "written by a person (no list or bulk headers)");
|
|
97
|
+
}
|
|
98
|
+
else if (learnedWeight === 0) {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (trustSender) {
|
|
103
|
+
const sender = matchSender(category.senders, from);
|
|
104
|
+
if (sender) {
|
|
105
|
+
const points = sender.exact ? SCORE.senderAddress : SCORE.senderDomain;
|
|
106
|
+
score += points;
|
|
107
|
+
senderScore += points;
|
|
108
|
+
reasons.push(`sender ${from} matches ${sender.pattern}`);
|
|
109
|
+
}
|
|
110
|
+
if (category.knownContact && message.knownContact) {
|
|
111
|
+
score += SCORE.knownContact;
|
|
112
|
+
senderScore += SCORE.knownContact;
|
|
113
|
+
reasons.push(`you have written to ${from} before`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
for (const keyword of matchingKeywords(category.keywords, message.subject).slice(0, MAX_KEYWORDS_COUNTED)) {
|
|
117
|
+
score += SCORE.keyword;
|
|
118
|
+
reasons.push(`subject contains "${keyword}"`);
|
|
119
|
+
}
|
|
120
|
+
if (score >= MIN_SCORE)
|
|
121
|
+
scored.push({ name: category.name, score, senderScore, reasons });
|
|
122
|
+
}
|
|
123
|
+
// Highest score wins; a tie goes to the category defined first.
|
|
124
|
+
const ranked = scored.map((entry, index) => ({ ...entry, index })).sort((a, b) => b.score - a.score || a.index - b.index);
|
|
125
|
+
const distrust = message.authFailure ? [`who the sender is was not used: the message failed ${message.authFailure}`] : [];
|
|
126
|
+
const [best, second] = ranked;
|
|
127
|
+
if (!best)
|
|
128
|
+
return { category: null, score: 0, reasons: [...distrust, "no signal of any category matched"], senderBased: false };
|
|
129
|
+
return {
|
|
130
|
+
category: best.name,
|
|
131
|
+
score: best.score,
|
|
132
|
+
reasons: [...best.reasons, ...distrust],
|
|
133
|
+
senderBased: best.senderScore > 0,
|
|
134
|
+
...(second ? { runnerUp: { category: second.name, score: second.score } } : {}),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/** What a failing Authentication-Results says ("dmarc=fail"), or undefined when nothing failed or it is absent. */
|
|
138
|
+
export function authFailureOf(authenticationResults) {
|
|
139
|
+
const failed = [...(authenticationResults ?? "").slice(0, 4000).toLowerCase().matchAll(/\b(dkim|spf|dmarc)=fail\b/g)].map((match) => `${match[1]}=fail`);
|
|
140
|
+
return failed.length ? [...new Set(failed)].join(", ") : undefined;
|
|
141
|
+
}
|
|
142
|
+
/** A note when a category or its label shares a name with one of Proton's own categories. */
|
|
143
|
+
export function protonClash(category) {
|
|
144
|
+
const byName = PROTON_CATEGORIES.find((name) => key(name) === key(category.name));
|
|
145
|
+
const byLabel = category.label ? PROTON_CATEGORIES.find((name) => key(name) === key(category.label)) : undefined;
|
|
146
|
+
if (!byName && !byLabel)
|
|
147
|
+
return undefined;
|
|
148
|
+
const parts = [
|
|
149
|
+
byName ? `Proton Mail has its own "${byName}" category; this one is separate, kept by this server, and Proton's sorting is neither visible nor changed here.` : "",
|
|
150
|
+
byLabel ? `The label "${category.label}" is an ordinary label (Labels/${category.label}), not Proton's ${byLabel} category.` : "",
|
|
151
|
+
];
|
|
152
|
+
return parts.filter(Boolean).join(" ");
|
|
153
|
+
}
|
|
154
|
+
// ---- validation -----------------------------------------------------------------------------------------------
|
|
155
|
+
function text(value, field, max) {
|
|
156
|
+
if (typeof value !== "string")
|
|
157
|
+
throw new InvalidArgumentError(`${field} must be text.`);
|
|
158
|
+
const clean = value.replace(CONTROL, " ").replace(/\s+/g, " ").trim();
|
|
159
|
+
if (clean.length > max)
|
|
160
|
+
throw new InvalidArgumentError(`${field} is longer than ${max} characters.`);
|
|
161
|
+
return clean;
|
|
162
|
+
}
|
|
163
|
+
function list(value, field, maxItems, maxLength) {
|
|
164
|
+
if (!Array.isArray(value) || value.length > maxItems)
|
|
165
|
+
throw new InvalidArgumentError(`${field} must be a list of at most ${maxItems} entries.`);
|
|
166
|
+
const items = value.map((entry) => text(entry, field, maxLength));
|
|
167
|
+
if (items.some((entry) => !entry))
|
|
168
|
+
throw new InvalidArgumentError(`${field} has an empty entry.`);
|
|
169
|
+
return [...new Set(items)];
|
|
170
|
+
}
|
|
171
|
+
// Lookalikes of Latin letters in Cyrillic and Greek (lowercase; the text is lowercased first).
|
|
172
|
+
const CONFUSABLES = new Map(Object.entries({
|
|
173
|
+
"\u0430": "a", "\u0432": "b", "\u0435": "e", "\u043A": "k", "\u043C": "m", "\u043D": "h", "\u043E": "o", "\u0440": "p", "\u0441": "c", "\u0442": "t", "\u0443": "y", "\u0445": "x", "\u0456": "i", "\u0457": "i", "\u0458": "j", "\u0455": "s", "\u0501": "d", "\u04BB": "h", "\u04CF": "l", "\u051B": "q", "\u051D": "w",
|
|
174
|
+
"\u03B1": "a", "\u03B2": "b", "\u03B3": "y", "\u03B5": "e", "\u03B9": "i", "\u03BA": "k", "\u03BD": "v", "\u03BF": "o", "\u03C1": "p", "\u03C4": "t", "\u03C5": "u", "\u03C7": "x",
|
|
175
|
+
}));
|
|
176
|
+
/** Text as the instruction filter should read it: compatibility forms folded, invisible characters dropped, lookalike letters read as Latin. A heuristic: it narrows the common disguises, it does not make the filter complete. */
|
|
177
|
+
function foldForFilter(value) {
|
|
178
|
+
return value.normalize("NFKC").replace(INVISIBLE, "").toLowerCase().replace(/[\u0370-\u03ff\u0400-\u052f]/g, (char) => CONFUSABLES.get(char) ?? char);
|
|
179
|
+
}
|
|
180
|
+
const SENDER_PATTERN = /^(\*?@|[^\s@*]+@)[a-z0-9-]+(\.[a-z0-9-]+)+$/i;
|
|
181
|
+
/**
|
|
182
|
+
* Checks a definition (a new one, or the fields that change on an existing one). An empty list or an empty label
|
|
183
|
+
* clears that field. Text that reads like an instruction to an AI is refused: categories are described in plain words.
|
|
184
|
+
*/
|
|
185
|
+
export function validateCategory(raw, existing) {
|
|
186
|
+
const name = existing?.name ?? text(raw.name, "name", 60);
|
|
187
|
+
if (!name)
|
|
188
|
+
throw new InvalidArgumentError("A category needs a name.");
|
|
189
|
+
const draft = existing ? { ...existing } : { name };
|
|
190
|
+
delete draft.createdAt;
|
|
191
|
+
delete draft.updatedAt;
|
|
192
|
+
if (raw.description !== undefined)
|
|
193
|
+
draft.description = text(raw.description, "description", 300) || undefined;
|
|
194
|
+
if (raw.senders !== undefined) {
|
|
195
|
+
const senders = list(raw.senders, "senders", 50, 100);
|
|
196
|
+
const bad = senders.find((entry) => !SENDER_PATTERN.test(entry));
|
|
197
|
+
if (bad)
|
|
198
|
+
throw new InvalidArgumentError(`senders: "${bad}" is not an address or a domain written as @example.com.`);
|
|
199
|
+
draft.senders = senders.length ? senders : undefined;
|
|
200
|
+
}
|
|
201
|
+
if (raw.keywords !== undefined) {
|
|
202
|
+
const keywords = list(raw.keywords, "keywords", 30, 60);
|
|
203
|
+
draft.keywords = keywords.length ? keywords : undefined;
|
|
204
|
+
}
|
|
205
|
+
for (const field of ["automated", "knownContact"]) {
|
|
206
|
+
if (raw[field] === undefined)
|
|
207
|
+
continue;
|
|
208
|
+
if (typeof raw[field] !== "boolean")
|
|
209
|
+
throw new InvalidArgumentError(`${field} must be true or false.`);
|
|
210
|
+
draft[field] = raw[field];
|
|
211
|
+
}
|
|
212
|
+
if (raw.label !== undefined) {
|
|
213
|
+
const label = text(raw.label, "label", 100).replace(/^Labels\//i, "");
|
|
214
|
+
if (label && (/^\/|\/$/.test(label) || label.split("/").includes("..")))
|
|
215
|
+
throw new InvalidArgumentError("label must be a label name such as Receipts.");
|
|
216
|
+
draft.label = label || undefined;
|
|
217
|
+
}
|
|
218
|
+
const words = foldForFilter([draft.name, draft.description ?? "", draft.label ?? "", ...(draft.keywords ?? [])].join("\n"));
|
|
219
|
+
const verdict = assessMail({ text: words });
|
|
220
|
+
if (verdict.level === "high") {
|
|
221
|
+
throw new InvalidArgumentError(`The category reads like an instruction to an AI (${verdict.reasons.join(" ")}). Describe what mail belongs in it, in plain words.`);
|
|
222
|
+
}
|
|
223
|
+
for (const field of Object.keys(draft))
|
|
224
|
+
if (draft[field] === undefined)
|
|
225
|
+
delete draft[field];
|
|
226
|
+
return draft;
|
|
227
|
+
}
|
|
228
|
+
// ---- store ----------------------------------------------------------------------------------------------------
|
|
229
|
+
export class CategoryService {
|
|
230
|
+
storePath;
|
|
231
|
+
constructor(options) {
|
|
232
|
+
this.storePath = join(options.dataDir, "categories.json");
|
|
233
|
+
}
|
|
234
|
+
async list() {
|
|
235
|
+
return this.load();
|
|
236
|
+
}
|
|
237
|
+
async find(name) {
|
|
238
|
+
return (await this.load()).categories.find((category) => key(category.name) === key(name));
|
|
239
|
+
}
|
|
240
|
+
/** Creates the category, or changes the fields given on the one with that name. */
|
|
241
|
+
async define(raw, now = new Date()) {
|
|
242
|
+
return this.withLock(async () => {
|
|
243
|
+
const state = await this.load();
|
|
244
|
+
const wanted = typeof raw.name === "string" ? key(raw.name) : "";
|
|
245
|
+
const index = state.categories.findIndex((category) => key(category.name) === wanted);
|
|
246
|
+
const existing = index === -1 ? undefined : state.categories[index];
|
|
247
|
+
if (!existing && state.categories.length >= MAX_CATEGORIES)
|
|
248
|
+
throw new InvalidArgumentError(`At most ${MAX_CATEGORIES} categories per account.`);
|
|
249
|
+
const draft = validateCategory(raw, existing);
|
|
250
|
+
const category = existing ? { ...draft, createdAt: existing.createdAt, updatedAt: now.toISOString() } : { ...draft, createdAt: now.toISOString() };
|
|
251
|
+
if (existing)
|
|
252
|
+
state.categories[index] = category;
|
|
253
|
+
else
|
|
254
|
+
state.categories.push(category);
|
|
255
|
+
await this.save(state);
|
|
256
|
+
return { category, created: !existing };
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
/** Adds definitions (the starter set, or another account's), leaving any category with the same name as it is. */
|
|
260
|
+
async addAll(drafts, now = new Date()) {
|
|
261
|
+
return this.withLock(async () => {
|
|
262
|
+
const state = await this.load();
|
|
263
|
+
const added = [];
|
|
264
|
+
const skipped = [];
|
|
265
|
+
for (const draft of drafts) {
|
|
266
|
+
if (state.categories.some((category) => key(category.name) === key(draft.name)) || state.categories.length >= MAX_CATEGORIES) {
|
|
267
|
+
skipped.push(draft.name);
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
state.categories.push({ ...validateCategory({ ...draft }), createdAt: now.toISOString() });
|
|
271
|
+
added.push(draft.name);
|
|
272
|
+
}
|
|
273
|
+
await this.save(state);
|
|
274
|
+
return { added, skipped };
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* A correction: mail from `sender` belongs in `category`. Its weight goes up by one and the sender's weight towards
|
|
279
|
+
* every other category down by one, so the latest correction wins over an older one.
|
|
280
|
+
*/
|
|
281
|
+
async learn(sender, category, now = new Date()) {
|
|
282
|
+
return this.withLock(async () => {
|
|
283
|
+
const state = await this.load();
|
|
284
|
+
const who = sender.trim().toLowerCase();
|
|
285
|
+
const target = key(category);
|
|
286
|
+
const mine = state.learned.filter((entry) => entry.sender === who);
|
|
287
|
+
const others = state.learned.filter((entry) => entry.sender !== who);
|
|
288
|
+
const next = mine.map((entry) => (entry.category === target ? entry : { ...entry, weight: entry.weight - 1 })).filter((entry) => entry.weight > 0);
|
|
289
|
+
const current = next.find((entry) => entry.category === target);
|
|
290
|
+
if (current)
|
|
291
|
+
Object.assign(current, { weight: current.weight + 1, at: now.toISOString() });
|
|
292
|
+
else
|
|
293
|
+
next.push({ sender: who, category: target, weight: 1, at: now.toISOString() });
|
|
294
|
+
// The oldest corrections make room first.
|
|
295
|
+
state.learned = [...others, ...next].sort((a, b) => a.at.localeCompare(b.at)).slice(-MAX_LEARNED);
|
|
296
|
+
await this.save(state);
|
|
297
|
+
return next;
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
async withLock(fn) {
|
|
301
|
+
await mkdir(dirname(this.storePath), { recursive: true, mode: 0o700 });
|
|
302
|
+
return withFileLock(this.storePath, fn);
|
|
303
|
+
}
|
|
304
|
+
async load() {
|
|
305
|
+
try {
|
|
306
|
+
const parsed = JSON.parse(await readRegularFile(this.storePath));
|
|
307
|
+
return { categories: Array.isArray(parsed.categories) ? parsed.categories : [], learned: Array.isArray(parsed.learned) ? parsed.learned : [] };
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
if (isFileNotFound(error))
|
|
311
|
+
return { categories: [], learned: [] };
|
|
312
|
+
setAsideCorruptStore(this.storePath, error, logger, "CategoryService");
|
|
313
|
+
return { categories: [], learned: [] };
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
async save(state) {
|
|
317
|
+
await writeFileAtomic(this.storePath, JSON.stringify(state, null, 2));
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
//# sourceMappingURL=category-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"category-service.js","sourceRoot":"","sources":["../../src/services/category-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commitment-service.d.ts","sourceRoot":"","sources":["../../src/services/commitment-service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"commitment-service.d.ts","sourceRoot":"","sources":["../../src/services/commitment-service.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,QAAQ,CAAC;AACpD,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,WAAW,CAAC;AAE7D,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,mBAAmB,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0GAA0G;IAC1G,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,gBAAgB,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAQD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IAEnC,YAAY,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,EAEvC;IAEK,GAAG,CAAC,KAAK,EAAE;QAAE,SAAS,EAAE,mBAAmB,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,GAAG,OAAa,GAAG,OAAO,CAAC,UAAU,CAAC,CA6B3K;IAEK,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,EAAE,GAAG,OAAa,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAUvG;IAEK,IAAI,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAElC;IAED,wFAAwF;IAClF,eAAe,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAE5C;YAEa,QAAQ;YAKR,IAAI;YAWJ,IAAI;CAGnB"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { mkdir
|
|
2
|
+
import { mkdir } from "node:fs/promises";
|
|
3
|
+
import { readRegularFile } from "../utils/regular-file.js";
|
|
3
4
|
import { dirname, join } from "node:path";
|
|
4
5
|
import { writeFileAtomic } from "../utils/atomic-write.js";
|
|
5
6
|
import { isFileNotFound, setAsideCorruptStore } from "../utils/corrupt-store.js";
|
|
@@ -36,7 +37,12 @@ export class CommitmentService {
|
|
|
36
37
|
createdAt: now.toISOString(),
|
|
37
38
|
status: "open",
|
|
38
39
|
};
|
|
39
|
-
state.items = [...state.items, item]
|
|
40
|
+
state.items = [...state.items, item];
|
|
41
|
+
// At the cap the oldest closed entries go first; an open promise is the point of the ledger.
|
|
42
|
+
while (state.items.length > MAX_ITEMS) {
|
|
43
|
+
const closed = state.items.findIndex((candidate) => candidate.status !== "open");
|
|
44
|
+
state.items.splice(closed === -1 ? 0 : closed, 1);
|
|
45
|
+
}
|
|
40
46
|
await this.save(state);
|
|
41
47
|
return item;
|
|
42
48
|
});
|
|
@@ -66,7 +72,7 @@ export class CommitmentService {
|
|
|
66
72
|
}
|
|
67
73
|
async load() {
|
|
68
74
|
try {
|
|
69
|
-
const parsed = JSON.parse(await
|
|
75
|
+
const parsed = JSON.parse(await readRegularFile(this.storePath));
|
|
70
76
|
return { items: Array.isArray(parsed.items) ? parsed.items : [] };
|
|
71
77
|
}
|
|
72
78
|
catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commitment-service.js","sourceRoot":"","sources":["../../src/services/commitment-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"commitment-service.js","sourceRoot":"","sources":["../../src/services/commitment-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { ProtonMailConfig } from "../types/index.js";
|
|
2
|
+
import { type Logger } from "../utils/logger.js";
|
|
3
|
+
import { type ParsedVCard } from "../utils/vcard.js";
|
|
4
|
+
export interface ContactRecord {
|
|
5
|
+
id: string;
|
|
6
|
+
/** Lowercased; an address belongs to at most one record. */
|
|
7
|
+
addresses: string[];
|
|
8
|
+
displayName?: string;
|
|
9
|
+
org?: string;
|
|
10
|
+
tags?: string[];
|
|
11
|
+
notes?: string;
|
|
12
|
+
createdAt: string;
|
|
13
|
+
updatedAt: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ContactPatch {
|
|
16
|
+
/** null or "" clears it. */
|
|
17
|
+
displayName?: string | null;
|
|
18
|
+
notes?: string | null;
|
|
19
|
+
addTags?: string[];
|
|
20
|
+
removeTags?: string[];
|
|
21
|
+
/** Another address of the same person: its record (if any) is merged into this one. */
|
|
22
|
+
mergeWith?: string;
|
|
23
|
+
/** Split this address out of the person it was merged into. */
|
|
24
|
+
unmerge?: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface ContactImportOutcome {
|
|
27
|
+
added: number;
|
|
28
|
+
updated: number;
|
|
29
|
+
unchanged: number;
|
|
30
|
+
/** Addresses of a card that names a known person but are not that person's yet (or belong to another one); left out. A file never attaches an address to a person: merging is set_contact's mergeWith. First 20; `conflictCount` is the total. */
|
|
31
|
+
conflicts: string[];
|
|
32
|
+
conflictCount: number;
|
|
33
|
+
/** Cards not imported because the store is full. */
|
|
34
|
+
overLimit: number;
|
|
35
|
+
}
|
|
36
|
+
export declare const MAX_CONTACTS = 10000;
|
|
37
|
+
export declare function requireContactAddress(value: string, field?: string): string;
|
|
38
|
+
export declare class ContactService {
|
|
39
|
+
private readonly config;
|
|
40
|
+
private readonly log;
|
|
41
|
+
private readonly storePath;
|
|
42
|
+
private _lock;
|
|
43
|
+
private identityChecked;
|
|
44
|
+
constructor(config: ProtonMailConfig, log?: Logger);
|
|
45
|
+
list(): Promise<ContactRecord[]>;
|
|
46
|
+
tagsFor(address: string): Promise<string[]>;
|
|
47
|
+
/** Applies the patch to the person `address` belongs to. Returns the record now holding `address` (none when nothing is stored for it) and, after an unmerge, the record it was split from. */
|
|
48
|
+
update(address: string, patch: ContactPatch): Promise<{
|
|
49
|
+
contact?: ContactRecord;
|
|
50
|
+
splitFrom?: ContactRecord;
|
|
51
|
+
}>;
|
|
52
|
+
/** Adds the people of a vCard file. Fills only what is not set yet. A card that names a known person never adds an address to them: a file could otherwise give its own address that person's tags (vip changes the autoresponder). */
|
|
53
|
+
importCards(cards: ParsedVCard[]): Promise<ContactImportOutcome>;
|
|
54
|
+
private withLock;
|
|
55
|
+
private load;
|
|
56
|
+
private loadUnlocked;
|
|
57
|
+
private cleanOrphanedTempFiles;
|
|
58
|
+
private save;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=contact-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contact-service.d.ts","sourceRoot":"","sources":["../../src/services/contact-service.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAO1D,OAAO,EAAU,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAwD,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAO3G,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,4DAA4D;IAC5D,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,4BAA4B;IAC5B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,uFAAuF;IACvF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,kPAAkP;IAClP,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;CACnB;AAOD,eAAO,MAAM,YAAY,QAAS,CAAC;AASnC,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,SAAY,GAAG,MAAM,CAI9E;AAgBD,qBAAa,cAAc;IAMvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,GAAG;IANtB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,KAAK,CAAoC;IACjD,OAAO,CAAC,eAAe,CAAS;IAEhC,YACmB,MAAM,EAAE,gBAAgB,EACxB,GAAG,GAAE,MAAe,EAGtC;IAEK,IAAI,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAErC;IAEK,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAIhD;IAED,+LAA+L;IACzL,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC;QAAE,OAAO,CAAC,EAAE,aAAa,CAAC;QAAC,SAAS,CAAC,EAAE,aAAa,CAAA;KAAE,CAAC,CAiElH;IAED,uOAAuO;IACjO,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA6CrE;YAGa,QAAQ;YAUR,IAAI;YAIJ,YAAY;YAoBZ,sBAAsB;YAiBtB,IAAI;CAInB"}
|