@wirecat/cli-memo 0.40.0 → 0.42.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/dist/doctor/command.d.ts +1 -1
- package/dist/effects.d.ts.map +1 -1
- package/dist/effects.js +1 -0
- package/dist/effects.js.map +1 -1
- package/dist/examples.d.ts.map +1 -1
- package/dist/examples.js +8 -4
- package/dist/examples.js.map +1 -1
- package/dist/mail/apply.d.ts +7 -0
- package/dist/mail/apply.d.ts.map +1 -1
- package/dist/mail/apply.js +27 -4
- package/dist/mail/apply.js.map +1 -1
- package/dist/mail/bulk.d.ts +8 -0
- package/dist/mail/bulk.d.ts.map +1 -0
- package/dist/mail/bulk.js +4 -0
- package/dist/mail/bulk.js.map +1 -0
- package/dist/mail/command.d.ts.map +1 -1
- package/dist/mail/command.js +123 -44
- package/dist/mail/command.js.map +1 -1
- package/dist/mail/facts.d.ts +10 -0
- package/dist/mail/facts.d.ts.map +1 -0
- package/dist/mail/facts.js +23 -0
- package/dist/mail/facts.js.map +1 -0
- package/dist/mail/filters.d.ts +11 -0
- package/dist/mail/filters.d.ts.map +1 -0
- package/dist/mail/filters.js +150 -0
- package/dist/mail/filters.js.map +1 -0
- package/dist/mail/headers.d.ts +3 -1
- package/dist/mail/headers.d.ts.map +1 -1
- package/dist/mail/headers.js +2 -1
- package/dist/mail/headers.js.map +1 -1
- package/dist/mail/import.d.ts +5 -0
- package/dist/mail/import.d.ts.map +1 -1
- package/dist/mail/import.js +25 -4
- package/dist/mail/import.js.map +1 -1
- package/dist/mail/parse.d.ts +3 -0
- package/dist/mail/parse.d.ts.map +1 -1
- package/dist/mail/parse.js +7 -2
- package/dist/mail/parse.js.map +1 -1
- package/dist/mail/presets.d.ts +31 -0
- package/dist/mail/presets.d.ts.map +1 -0
- package/dist/mail/presets.js +96 -0
- package/dist/mail/presets.js.map +1 -0
- package/dist/mail/probe.d.ts +13 -0
- package/dist/mail/probe.d.ts.map +1 -1
- package/dist/mail/probe.js +17 -1
- package/dist/mail/probe.js.map +1 -1
- package/dist/mail/repair.d.ts +7 -0
- package/dist/mail/repair.d.ts.map +1 -0
- package/dist/mail/repair.js +45 -0
- package/dist/mail/repair.js.map +1 -0
- package/dist/mail/rule-query.d.ts +15 -0
- package/dist/mail/rule-query.d.ts.map +1 -0
- package/dist/mail/rule-query.js +101 -0
- package/dist/mail/rule-query.js.map +1 -0
- package/dist/mail/rule-store.d.ts +3 -5
- package/dist/mail/rule-store.d.ts.map +1 -1
- package/dist/mail/rule-store.js +47 -17
- package/dist/mail/rule-store.js.map +1 -1
- package/dist/mail/rule-tags.d.ts +41 -0
- package/dist/mail/rule-tags.d.ts.map +1 -0
- package/dist/mail/rule-tags.js +88 -0
- package/dist/mail/rule-tags.js.map +1 -0
- package/dist/mail/rules.d.ts +51 -6
- package/dist/mail/rules.d.ts.map +1 -1
- package/dist/mail/rules.js +86 -22
- package/dist/mail/rules.js.map +1 -1
- package/dist/mail/score.d.ts +2 -0
- package/dist/mail/score.d.ts.map +1 -1
- package/dist/mail/score.js +11 -1
- package/dist/mail/score.js.map +1 -1
- package/dist/reasons.d.ts.map +1 -1
- package/dist/reasons.js +6 -0
- package/dist/reasons.js.map +1 -1
- package/dist/run/import.d.ts.map +1 -1
- package/dist/run/import.js +4 -0
- package/dist/run/import.js.map +1 -1
- package/dist/search/command.d.ts.map +1 -1
- package/dist/search/command.js +12 -3
- package/dist/search/command.js.map +1 -1
- package/dist/store/source-target.js +1 -1
- package/dist/store/source-target.js.map +1 -1
- package/dist/tags/command.js +1 -1
- package/dist/tags/command.js.map +1 -1
- package/dist/tasks/command.js +4 -4
- package/dist/tasks/command.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
- package/skills/cli-memo/SKILL.md +8 -2
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { MailFacts } from "./rules.js";
|
|
2
|
+
/**
|
|
3
|
+
* Kinds of mail every mailbox gets, matched by who sends them and how, not by a list of the owner's senders. Mail
|
|
4
|
+
* from someone the owner wrote to never matches a preset, so a real conversation is never caught by one.
|
|
5
|
+
*/
|
|
6
|
+
export declare const PRESETS: {
|
|
7
|
+
readonly social: {
|
|
8
|
+
readonly about: "notifications from social networks";
|
|
9
|
+
readonly domains: readonly ["facebookmail.com", "facebook.com", "linkedin.com", "twitter.com", "x.com", "instagram.com", "vk.com", "ok.ru", "quora.com", "redditmail.com", "pinterest.com", "tiktok.com", "meetup.com", "tumblr.com", "youtube.com"];
|
|
10
|
+
};
|
|
11
|
+
readonly newsletters: {
|
|
12
|
+
readonly about: "mailing lists with an unsubscribe link: List-Id and List-Unsubscribe, or a newsletter service";
|
|
13
|
+
readonly domains: readonly ["substack.com", "mcsv.net", "mailchimpapp.net", "sendinblue.com", "beehiiv.com", "convertkit.com"];
|
|
14
|
+
};
|
|
15
|
+
readonly developer: {
|
|
16
|
+
readonly about: "code hosting, CI, package and error-tracker notifications";
|
|
17
|
+
readonly domains: readonly ["github.com", "gitlab.com", "bitbucket.org", "atlassian.net", "circleci.com", "travis-ci.com", "rollbar.com", "sentry.io", "vercel.com", "netlify.com", "npmjs.com", "docker.com", "heroku.com", "codecov.io", "libraries.io"];
|
|
18
|
+
};
|
|
19
|
+
readonly shopping: {
|
|
20
|
+
readonly about: "shops and promotions, and what Gmail files under Promotions";
|
|
21
|
+
readonly domains: readonly ["aliexpress.com", "aliexpress.ru", "ebay.com", "ozon.ru", "wildberries.ru", "steampowered.com", "booking.com", "zalando.com", "etsy.com", "ikea.com"];
|
|
22
|
+
};
|
|
23
|
+
readonly alerts: {
|
|
24
|
+
readonly about: "monitoring and uptime alerts";
|
|
25
|
+
readonly domains: readonly ["uptimerobot.com", "pingdom.com", "statuscake.com", "pagerduty.com", "opsgenie.com", "newrelic.com", "datadoghq.com", "betteruptime.com", "healthchecks.io"];
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
export type PresetName = keyof typeof PRESETS;
|
|
29
|
+
export declare const PRESET_NAMES: PresetName[];
|
|
30
|
+
export declare const presetMatches: (name: PresetName, facts: MailFacts) => boolean;
|
|
31
|
+
//# sourceMappingURL=presets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../src/mail/presets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAG3C;;;GAGG;AACH,eAAO,MAAM,OAAO;aAClB,MAAM;iBACJ,KAAK,EAAE,oCAAoC;iBAC3C,OAAO,YACL,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,aAAa,EACb,OAAO,EACP,eAAe,EACf,QAAQ,EACR,OAAO,EACP,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,aAAa;;aAGjB,WAAW;iBACT,KAAK,EAAE,+FAA+F;iBACtG,OAAO,YAAG,cAAc,EAAE,UAAU,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,aAAa,EAAE,gBAAgB;;aAE7G,SAAS;iBACP,KAAK,EAAE,2DAA2D;iBAClE,OAAO,YACL,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,eAAe,EACf,cAAc,EACd,eAAe,EACf,aAAa,EACb,WAAW,EACX,YAAY,EACZ,aAAa,EACb,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,cAAc;;aAGlB,QAAQ;iBACN,KAAK,EAAE,6DAA6D;iBACpE,OAAO,YACL,gBAAgB,EAChB,eAAe,EACf,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,aAAa,EACb,UAAU,EACV,UAAU;;aAGd,MAAM;iBACJ,KAAK,EAAE,8BAA8B;iBACrC,OAAO,YACL,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,cAAc,EACd,eAAe,EACf,kBAAkB,EAClB,iBAAiB;;CAGb,CAAA;AAEV,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,OAAO,CAAA;AAE7C,eAAO,MAAM,YAAY,EAA2B,UAAU,EAAE,CAAA;AAEhE,eAAO,MAAM,aAAa,SAAU,UAAU,SAAS,SAAS,KAAG,OASlE,CAAA"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { registrableOf } from "./score.js";
|
|
2
|
+
/**
|
|
3
|
+
* Kinds of mail every mailbox gets, matched by who sends them and how, not by a list of the owner's senders. Mail
|
|
4
|
+
* from someone the owner wrote to never matches a preset, so a real conversation is never caught by one.
|
|
5
|
+
*/
|
|
6
|
+
export const PRESETS = {
|
|
7
|
+
social: {
|
|
8
|
+
about: "notifications from social networks",
|
|
9
|
+
domains: [
|
|
10
|
+
"facebookmail.com",
|
|
11
|
+
"facebook.com",
|
|
12
|
+
"linkedin.com",
|
|
13
|
+
"twitter.com",
|
|
14
|
+
"x.com",
|
|
15
|
+
"instagram.com",
|
|
16
|
+
"vk.com",
|
|
17
|
+
"ok.ru",
|
|
18
|
+
"quora.com",
|
|
19
|
+
"redditmail.com",
|
|
20
|
+
"pinterest.com",
|
|
21
|
+
"tiktok.com",
|
|
22
|
+
"meetup.com",
|
|
23
|
+
"tumblr.com",
|
|
24
|
+
"youtube.com",
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
newsletters: {
|
|
28
|
+
about: "mailing lists with an unsubscribe link: List-Id and List-Unsubscribe, or a newsletter service",
|
|
29
|
+
domains: ["substack.com", "mcsv.net", "mailchimpapp.net", "sendinblue.com", "beehiiv.com", "convertkit.com"],
|
|
30
|
+
},
|
|
31
|
+
developer: {
|
|
32
|
+
about: "code hosting, CI, package and error-tracker notifications",
|
|
33
|
+
domains: [
|
|
34
|
+
"github.com",
|
|
35
|
+
"gitlab.com",
|
|
36
|
+
"bitbucket.org",
|
|
37
|
+
"atlassian.net",
|
|
38
|
+
"circleci.com",
|
|
39
|
+
"travis-ci.com",
|
|
40
|
+
"rollbar.com",
|
|
41
|
+
"sentry.io",
|
|
42
|
+
"vercel.com",
|
|
43
|
+
"netlify.com",
|
|
44
|
+
"npmjs.com",
|
|
45
|
+
"docker.com",
|
|
46
|
+
"heroku.com",
|
|
47
|
+
"codecov.io",
|
|
48
|
+
"libraries.io",
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
shopping: {
|
|
52
|
+
about: "shops and promotions, and what Gmail files under Promotions",
|
|
53
|
+
domains: [
|
|
54
|
+
"aliexpress.com",
|
|
55
|
+
"aliexpress.ru",
|
|
56
|
+
"ebay.com",
|
|
57
|
+
"ozon.ru",
|
|
58
|
+
"wildberries.ru",
|
|
59
|
+
"steampowered.com",
|
|
60
|
+
"booking.com",
|
|
61
|
+
"zalando.com",
|
|
62
|
+
"etsy.com",
|
|
63
|
+
"ikea.com",
|
|
64
|
+
],
|
|
65
|
+
},
|
|
66
|
+
alerts: {
|
|
67
|
+
about: "monitoring and uptime alerts",
|
|
68
|
+
domains: [
|
|
69
|
+
"uptimerobot.com",
|
|
70
|
+
"pingdom.com",
|
|
71
|
+
"statuscake.com",
|
|
72
|
+
"pagerduty.com",
|
|
73
|
+
"opsgenie.com",
|
|
74
|
+
"newrelic.com",
|
|
75
|
+
"datadoghq.com",
|
|
76
|
+
"betteruptime.com",
|
|
77
|
+
"healthchecks.io",
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
export const PRESET_NAMES = Object.keys(PRESETS);
|
|
82
|
+
export const presetMatches = (name, facts) => {
|
|
83
|
+
const { headers } = facts;
|
|
84
|
+
const sender = headers?.from;
|
|
85
|
+
if (sender === undefined || facts.replied)
|
|
86
|
+
return false;
|
|
87
|
+
const domain = registrableOf(sender);
|
|
88
|
+
if (PRESETS[name].domains.includes(domain))
|
|
89
|
+
return true;
|
|
90
|
+
if (name === "newsletters")
|
|
91
|
+
return headers?.listId !== undefined && headers.bulk;
|
|
92
|
+
if (name === "shopping")
|
|
93
|
+
return facts.labels?.includes("Promotions") ?? false;
|
|
94
|
+
return false;
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=presets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.js","sourceRoot":"","sources":["../../src/mail/presets.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE1C;;;GAGG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,MAAM,EAAE;QACN,KAAK,EAAE,oCAAoC;QAC3C,OAAO,EAAE;YACP,kBAAkB;YAClB,cAAc;YACd,cAAc;YACd,aAAa;YACb,OAAO;YACP,eAAe;YACf,QAAQ;YACR,OAAO;YACP,WAAW;YACX,gBAAgB;YAChB,eAAe;YACf,YAAY;YACZ,YAAY;YACZ,YAAY;YACZ,aAAa;SACd;KACF;IACD,WAAW,EAAE;QACX,KAAK,EAAE,+FAA+F;QACtG,OAAO,EAAE,CAAC,cAAc,EAAE,UAAU,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,aAAa,EAAE,gBAAgB,CAAC;KAC7G;IACD,SAAS,EAAE;QACT,KAAK,EAAE,2DAA2D;QAClE,OAAO,EAAE;YACP,YAAY;YACZ,YAAY;YACZ,eAAe;YACf,eAAe;YACf,cAAc;YACd,eAAe;YACf,aAAa;YACb,WAAW;YACX,YAAY;YACZ,aAAa;YACb,WAAW;YACX,YAAY;YACZ,YAAY;YACZ,YAAY;YACZ,cAAc;SACf;KACF;IACD,QAAQ,EAAE;QACR,KAAK,EAAE,6DAA6D;QACpE,OAAO,EAAE;YACP,gBAAgB;YAChB,eAAe;YACf,UAAU;YACV,SAAS;YACT,gBAAgB;YAChB,kBAAkB;YAClB,aAAa;YACb,aAAa;YACb,UAAU;YACV,UAAU;SACX;KACF;IACD,MAAM,EAAE;QACN,KAAK,EAAE,8BAA8B;QACrC,OAAO,EAAE;YACP,iBAAiB;YACjB,aAAa;YACb,gBAAgB;YAChB,eAAe;YACf,cAAc;YACd,cAAc;YACd,eAAe;YACf,kBAAkB;YAClB,iBAAiB;SAClB;KACF;CACO,CAAA;AAIV,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAiB,CAAA;AAEhE,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,IAAgB,EAAE,KAAgB,EAAW,EAAE;IAC3E,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAA;IACzB,MAAM,MAAM,GAAG,OAAO,EAAE,IAAI,CAAA;IAC5B,IAAI,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,OAAO;QAAE,OAAO,KAAK,CAAA;IACvD,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAA;IACpC,IAAK,OAAO,CAAC,IAAI,CAAC,CAAC,OAA6B,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAA;IAC9E,IAAI,IAAI,KAAK,aAAa;QAAE,OAAO,OAAO,EAAE,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,CAAA;IAChF,IAAI,IAAI,KAAK,UAAU;QAAE,OAAO,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,YAAY,CAAC,IAAI,KAAK,CAAA;IAC7E,OAAO,KAAK,CAAA;AACd,CAAC,CAAA"}
|
package/dist/mail/probe.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type PresetName } from "./presets.js";
|
|
1
2
|
import { type DomainAge, type Signal } from "./score.js";
|
|
2
3
|
import type { Listed } from "./source.js";
|
|
3
4
|
export declare const SUGGEST_RULE: string;
|
|
@@ -29,7 +30,19 @@ export interface Probe {
|
|
|
29
30
|
withoutHeaders: number;
|
|
30
31
|
groups: number;
|
|
31
32
|
items: ProbeGroup[];
|
|
33
|
+
/** How much mail each built-in preset would match: proposals the owner may turn into rules. */
|
|
34
|
+
presets: {
|
|
35
|
+
preset: PresetName;
|
|
36
|
+
emails: number;
|
|
37
|
+
groups: number;
|
|
38
|
+
bytes: number;
|
|
39
|
+
}[];
|
|
32
40
|
}
|
|
41
|
+
/** A list's mail is one group whoever sends it; other mail is grouped by sender. */
|
|
42
|
+
export declare const groupKey: (headers: {
|
|
43
|
+
from?: string;
|
|
44
|
+
listId?: string;
|
|
45
|
+
}) => string;
|
|
33
46
|
/** Groups mail by List-Id when it has one, else by sender address; largest groups first. */
|
|
34
47
|
export declare const probeMail: (items: Listed[], limit: number, ages?: ReadonlyMap<string, DomainAge>) => Probe;
|
|
35
48
|
/** The sender domains of the groups worth asking a registry about: not a big mailbox provider, never replied to. */
|
package/dist/mail/probe.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"probe.d.ts","sourceRoot":"","sources":["../../src/mail/probe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAiB,KAAK,MAAM,EAAc,MAAM,YAAY,CAAA;AACnF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,eAAO,MAAM,YAAY,QAEsE,CAAA;AAE/F,MAAM,WAAW,UAAU;IACzB,qDAAqD;IACrD,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,mEAAmE;IACnE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,yDAAyD;IACzD,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,2GAA2G;IAC3G,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,MAAM,WAAW,KAAK;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,oFAAoF;IACpF,IAAI,EAAE,MAAM,CAAA;IACZ,2DAA2D;IAC3D,cAAc,EAAE,MAAM,CAAA;IACtB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,UAAU,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"probe.d.ts","sourceRoot":"","sources":["../../src/mail/probe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,UAAU,EAAiB,MAAM,cAAc,CAAA;AAC3E,OAAO,EAAE,KAAK,SAAS,EAAiB,KAAK,MAAM,EAAc,MAAM,YAAY,CAAA;AACnF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,eAAO,MAAM,YAAY,QAEsE,CAAA;AAE/F,MAAM,WAAW,UAAU;IACzB,qDAAqD;IACrD,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,mEAAmE;IACnE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,yDAAyD;IACzD,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,2GAA2G;IAC3G,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,MAAM,WAAW,KAAK;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,oFAAoF;IACpF,IAAI,EAAE,MAAM,CAAA;IACZ,2DAA2D;IAC3D,cAAc,EAAE,MAAM,CAAA;IACtB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,UAAU,EAAE,CAAA;IACnB,+FAA+F;IAC/F,OAAO,EAAE;QAAE,MAAM,EAAE,UAAU,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CACjF;AAMD,oFAAoF;AACpF,eAAO,MAAM,QAAQ,YAAa;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,KAAG,MACW,CAAA;AAElF,4FAA4F;AAC5F,eAAO,MAAM,SAAS,UAAW,MAAM,EAAE,SAAS,MAAM,SAAQ,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,KAAe,KA2D5G,CAAA;AAED,oHAAoH;AACpH,eAAO,MAAM,YAAY,WAAY,UAAU,EAAE,QAAQ,WAAW,CAAC,MAAM,CAAC,KAAG,MAAM,EAQpF,CAAA"}
|
package/dist/mail/probe.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import { PRESET_NAMES, presetMatches } from "./presets.js";
|
|
1
2
|
import { registrableOf, scoreGroup } from "./score.js";
|
|
2
3
|
export const SUGGEST_RULE = "suggest is skip when a group has at least 20 emails, at least 80% of them list or bulk mail " +
|
|
3
4
|
"(List-Id, List-Unsubscribe or Precedence: bulk) and the owner never sent mail to its sender";
|
|
4
5
|
const share = (part, whole) => Math.round((part / whole) * 100) / 100;
|
|
5
6
|
const isSent = (item) => item.labels?.includes("Sent") || /(^|\/)sent\b/i.test(item.folder ?? "");
|
|
7
|
+
/** A list's mail is one group whoever sends it; other mail is grouped by sender. */
|
|
8
|
+
export const groupKey = (headers) => headers.listId === undefined ? `from:${headers.from}` : `list:${headers.listId}`;
|
|
6
9
|
/** Groups mail by List-Id when it has one, else by sender address; largest groups first. */
|
|
7
10
|
export const probeMail = (items, limit, ages = new Map()) => {
|
|
8
11
|
const sent = items.filter(isSent);
|
|
@@ -17,7 +20,7 @@ export const probeMail = (items, limit, ages = new Map()) => {
|
|
|
17
20
|
withoutHeaders++;
|
|
18
21
|
continue;
|
|
19
22
|
}
|
|
20
|
-
const key = headers
|
|
23
|
+
const key = groupKey(headers);
|
|
21
24
|
const group = groups.get(key);
|
|
22
25
|
if (group)
|
|
23
26
|
group.push(item);
|
|
@@ -44,6 +47,18 @@ export const probeMail = (items, limit, ages = new Map()) => {
|
|
|
44
47
|
...scoreGroup(group, { replied, bulk, ages }),
|
|
45
48
|
};
|
|
46
49
|
});
|
|
50
|
+
const presets = PRESET_NAMES.map((preset) => {
|
|
51
|
+
const hit = [...groups.values()].filter((group) => {
|
|
52
|
+
const replied = group.some((item) => item.headers?.from !== undefined && recipients.has(item.headers.from));
|
|
53
|
+
return presetMatches(preset, { ...group[0], replied });
|
|
54
|
+
});
|
|
55
|
+
return {
|
|
56
|
+
preset,
|
|
57
|
+
emails: hit.reduce((sum, group) => sum + group.length, 0),
|
|
58
|
+
groups: hit.length,
|
|
59
|
+
bytes: hit.reduce((sum, group) => sum + group.reduce((total, item) => total + (item.size ?? 0), 0), 0),
|
|
60
|
+
};
|
|
61
|
+
}).filter(({ emails }) => emails > 0);
|
|
47
62
|
all.sort((a, b) => b.emails - a.emails || b.bytes - a.bytes);
|
|
48
63
|
return {
|
|
49
64
|
emails: items.length,
|
|
@@ -52,6 +67,7 @@ export const probeMail = (items, limit, ages = new Map()) => {
|
|
|
52
67
|
withoutHeaders,
|
|
53
68
|
groups: all.length,
|
|
54
69
|
items: all.slice(0, limit),
|
|
70
|
+
presets,
|
|
55
71
|
};
|
|
56
72
|
};
|
|
57
73
|
/** The sender domains of the groups worth asking a registry about: not a big mailbox provider, never replied to. */
|
package/dist/mail/probe.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"probe.js","sourceRoot":"","sources":["../../src/mail/probe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,aAAa,EAAe,UAAU,EAAE,MAAM,YAAY,CAAA;AAGnF,MAAM,CAAC,MAAM,YAAY,GACvB,8FAA8F;IAC9F,6FAA6F,CAAA;
|
|
1
|
+
{"version":3,"file":"probe.js","sourceRoot":"","sources":["../../src/mail/probe.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { MessageStore } from "@wirecat/cli-core/store";
|
|
2
|
+
/**
|
|
3
|
+
* Once per account: email text saved before memo read an HTML text/plain part as HTML is converted in place, from
|
|
4
|
+
* what the store holds. Runs inside sync, so it holds the import lock like any other write.
|
|
5
|
+
*/
|
|
6
|
+
export declare const repairHtmlText: (store: MessageStore, address: string, now?: number) => Promise<number | undefined>;
|
|
7
|
+
//# sourceMappingURL=repair.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repair.d.ts","sourceRoot":"","sources":["../../src/mail/repair.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAOvE;;;GAGG;AACH,eAAO,MAAM,cAAc,UAClB,YAAY,WACV,MAAM,mBAEd,OAAO,CAAC,MAAM,GAAG,SAAS,CA8B5B,CAAA"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { htmlToText, looksLikeHtml } from "./parse.js";
|
|
2
|
+
import { ENVELOPE } from "./rules.js";
|
|
3
|
+
const REPAIRED = "mail_text_repair";
|
|
4
|
+
const VERSION = "html-text-1";
|
|
5
|
+
/**
|
|
6
|
+
* Once per account: email text saved before memo read an HTML text/plain part as HTML is converted in place, from
|
|
7
|
+
* what the store holds. Runs inside sync, so it holds the import lock like any other write.
|
|
8
|
+
*/
|
|
9
|
+
export const repairHtmlText = async (store, address, now = Date.now()) => {
|
|
10
|
+
const key = { provider: "email", account: address.toLowerCase() };
|
|
11
|
+
if ((await store.syncState(key, REPAIRED))?.value === VERSION)
|
|
12
|
+
return undefined;
|
|
13
|
+
const stored = await store.storedAccount(key).catch(() => null);
|
|
14
|
+
if (stored === null)
|
|
15
|
+
return undefined;
|
|
16
|
+
let repaired = 0;
|
|
17
|
+
for (const { externalId, deleted, mailboxes } of await store.mail.emailRefs({ accountId: stored.id })) {
|
|
18
|
+
if (deleted || mailboxes.some(({ kind }) => kind === ENVELOPE))
|
|
19
|
+
continue;
|
|
20
|
+
const email = await store.mail.email(stored.id, externalId);
|
|
21
|
+
if (email === null || !email.bodyText || !looksLikeHtml(email.bodyText))
|
|
22
|
+
continue;
|
|
23
|
+
const [placed] = await store.mail.inThreads(stored.id, [externalId]);
|
|
24
|
+
if (placed === undefined)
|
|
25
|
+
continue;
|
|
26
|
+
await store.mail.saveThread({
|
|
27
|
+
accountId: stored.id,
|
|
28
|
+
externalId: placed.threadExternalId,
|
|
29
|
+
now,
|
|
30
|
+
emails: [
|
|
31
|
+
{
|
|
32
|
+
externalId,
|
|
33
|
+
subject: email.subject,
|
|
34
|
+
from: email.fromAddress === null ? null : { address: email.fromAddress, name: email.fromName },
|
|
35
|
+
sentAt: email.sentAt,
|
|
36
|
+
bodyText: htmlToText(email.bodyText),
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
});
|
|
40
|
+
repaired++;
|
|
41
|
+
}
|
|
42
|
+
await store.setSyncState(key, REPAIRED, VERSION);
|
|
43
|
+
return repaired;
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=repair.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repair.js","sourceRoot":"","sources":["../../src/mail/repair.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAErC,MAAM,QAAQ,GAAG,kBAAkB,CAAA;AACnC,MAAM,OAAO,GAAG,aAAa,CAAA;AAE7B;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EACjC,KAAmB,EACnB,OAAe,EACf,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,EACa,EAAE;IAC/B,MAAM,GAAG,GAAe,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,WAAW,EAAE,EAAE,CAAA;IAC7E,IAAI,CAAC,MAAM,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,EAAE,KAAK,KAAK,OAAO;QAAE,OAAO,SAAS,CAAA;IAC/E,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;IAC/D,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,SAAS,CAAA;IACrC,IAAI,QAAQ,GAAG,CAAC,CAAA;IAChB,KAAK,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,MAAM,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;QACtG,IAAI,OAAO,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,KAAK,QAAQ,CAAC;YAAE,SAAQ;QACxE,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,UAAU,CAAC,CAAA;QAC3D,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC;YAAE,SAAQ;QACjF,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAA;QACpE,IAAI,MAAM,KAAK,SAAS;YAAE,SAAQ;QAClC,MAAM,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC;YAC1B,SAAS,EAAE,MAAM,CAAC,EAAE;YACpB,UAAU,EAAE,MAAM,CAAC,gBAAgB;YACnC,GAAG;YACH,MAAM,EAAE;gBACN;oBACE,UAAU;oBACV,OAAO,EAAE,KAAK,CAAC,OAAO;oBACtB,IAAI,EAAE,KAAK,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,WAAW,EAAE,IAAI,EAAE,KAAK,CAAC,QAAQ,EAAE;oBAC9F,MAAM,EAAE,KAAK,CAAC,MAAM;oBACpB,QAAQ,EAAE,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC;iBACrC;aACF;SACF,CAAC,CAAA;QACF,QAAQ,EAAE,CAAA;IACZ,CAAC;IACD,MAAM,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAA;IAChD,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { MailAction, MailRuleMatch } from "./rules.js";
|
|
2
|
+
export declare const FILTER_HELP: string;
|
|
3
|
+
/** `from:` as Gmail reads it: one address, a whole domain (`shop.example`, `@shop.example`), or a word it contains. */
|
|
4
|
+
export declare const senderMatch: (value: string) => MailRuleMatch;
|
|
5
|
+
export declare const isAddress: (value: string) => boolean;
|
|
6
|
+
/** The conditions of a rule's --filter query. */
|
|
7
|
+
export declare const filterMatch: (query: string) => MailRuleMatch;
|
|
8
|
+
export declare const ACTION_HELP: string;
|
|
9
|
+
/** `envelope,tag:promo` → the store action, protection and tags. */
|
|
10
|
+
export declare const actionsOf: (value: string) => {
|
|
11
|
+
action: MailAction;
|
|
12
|
+
protect: boolean;
|
|
13
|
+
tags: string[];
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=rule-query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-query.d.ts","sourceRoot":"","sources":["../../src/mail/rule-query.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE3D,eAAO,MAAM,WAAW,QAEwD,CAAA;AAMhF,uHAAuH;AACvH,eAAO,MAAM,WAAW,UAAW,MAAM,KAAG,aAI3C,CAAA;AAED,eAAO,MAAM,SAAS,UAAW,MAAM,YAAwB,CAAA;AAS/D,iDAAiD;AACjD,eAAO,MAAM,WAAW,UAAW,MAAM,KAAG,aAmD3C,CAAA;AAED,eAAO,MAAM,WAAW,QAGoF,CAAA;AAI5G,oEAAoE;AACpE,eAAO,MAAM,SAAS,UAAW,MAAM,KAAG;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAY/F,CAAA"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { CliError } from "@wirecat/cli-base";
|
|
2
|
+
export const FILTER_HELP = "from:<address, domain or word>, to:<address>, subject:<word> (or a bare word), older:<n>d, larger:<size> (5MB, 300KB), has:attachment, label:<name> " +
|
|
3
|
+
'(label:"Two words"), is:unread, is:bulk, score:<n> (at least); all must hold';
|
|
4
|
+
const bad = (why) => new CliError("validation_error", `--filter: ${why}`);
|
|
5
|
+
const ADDRESS = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
6
|
+
/** `from:` as Gmail reads it: one address, a whole domain (`shop.example`, `@shop.example`), or a word it contains. */
|
|
7
|
+
export const senderMatch = (value) => {
|
|
8
|
+
if (ADDRESS.test(value))
|
|
9
|
+
return { from: value.toLowerCase() };
|
|
10
|
+
const domain = value.replace(/^@/, "");
|
|
11
|
+
return /^[a-z0-9-]+(\.[a-z0-9-]+)+$/i.test(domain) ? { domain: domain.toLowerCase() } : { from_contains: value };
|
|
12
|
+
};
|
|
13
|
+
export const isAddress = (value) => ADDRESS.test(value);
|
|
14
|
+
const bytesOf = (value) => {
|
|
15
|
+
const match = /^(\d+(?:\.\d+)?)(b|kb|mb|gb)?$/i.exec(value);
|
|
16
|
+
if (match === null)
|
|
17
|
+
throw bad(`larger:${value} is not a size like 5MB, 300KB or 2048`);
|
|
18
|
+
const unit = { b: 1, kb: 1024, mb: 1024 ** 2, gb: 1024 ** 3 }[(match[2] ?? "b").toLowerCase()];
|
|
19
|
+
return Math.round(Number(match[1]) * unit);
|
|
20
|
+
};
|
|
21
|
+
/** The conditions of a rule's --filter query. */
|
|
22
|
+
export const filterMatch = (query) => {
|
|
23
|
+
const words = [];
|
|
24
|
+
const match = {};
|
|
25
|
+
for (const [, field, quoted, plain, word] of query.matchAll(/(\w+):(?:"([^"]*)"|(\S+))|(\S+)/g)) {
|
|
26
|
+
const value = quoted ?? plain ?? "";
|
|
27
|
+
if (word !== undefined) {
|
|
28
|
+
words.push(word);
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
switch (field?.toLowerCase()) {
|
|
32
|
+
case "from":
|
|
33
|
+
Object.assign(match, senderMatch(value));
|
|
34
|
+
break;
|
|
35
|
+
case "to":
|
|
36
|
+
if (!ADDRESS.test(value))
|
|
37
|
+
throw bad(`to:${value} needs one address, like to:me@example.com`);
|
|
38
|
+
match.to = value.toLowerCase();
|
|
39
|
+
break;
|
|
40
|
+
case "subject":
|
|
41
|
+
words.push(...value.split(/\s+/).filter(Boolean));
|
|
42
|
+
break;
|
|
43
|
+
case "older": {
|
|
44
|
+
const days = /^(\d+)d$/i.exec(value)?.[1];
|
|
45
|
+
if (days === undefined)
|
|
46
|
+
throw bad(`older:${value} needs days, like older:365d`);
|
|
47
|
+
match.older_than_days = Number(days);
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
case "larger":
|
|
51
|
+
match.larger_than_bytes = bytesOf(value);
|
|
52
|
+
break;
|
|
53
|
+
case "has":
|
|
54
|
+
if (!/^attachments?$/i.test(value))
|
|
55
|
+
throw bad(`has:${value}; only has:attachment is known`);
|
|
56
|
+
match.has_attachments = true;
|
|
57
|
+
break;
|
|
58
|
+
case "label":
|
|
59
|
+
match.label = value;
|
|
60
|
+
break;
|
|
61
|
+
case "is":
|
|
62
|
+
if (/^unread$/i.test(value))
|
|
63
|
+
match.unread = true;
|
|
64
|
+
else if (/^bulk$/i.test(value))
|
|
65
|
+
match.bulk = true;
|
|
66
|
+
else
|
|
67
|
+
throw bad(`is:${value}; is:unread and is:bulk are known`);
|
|
68
|
+
break;
|
|
69
|
+
case "score":
|
|
70
|
+
if (!/^-?\d+$/.test(value))
|
|
71
|
+
throw bad(`score:${value} needs a whole number`);
|
|
72
|
+
match.score_at_least = Number(value);
|
|
73
|
+
break;
|
|
74
|
+
default:
|
|
75
|
+
throw bad(`${field}: is not a field; use ${FILTER_HELP}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (words.length)
|
|
79
|
+
match.subject = words.join(" ");
|
|
80
|
+
return match;
|
|
81
|
+
};
|
|
82
|
+
export const ACTION_HELP = "one of skip (never read or store), envelope (store only sender, date, size and labels: counted, out of search, " +
|
|
83
|
+
"cleanable later), keep (store in full even when a skip or envelope rule matches) or protect (keep, and no " +
|
|
84
|
+
"cleanup may ever cut, archive or trash it); add tag:<name> to also tag the mail, e.g. envelope,tag:promo";
|
|
85
|
+
const ACTIONS = ["skip", "envelope", "keep", "protect"];
|
|
86
|
+
/** `envelope,tag:promo` → the store action, protection and tags. */
|
|
87
|
+
export const actionsOf = (value) => {
|
|
88
|
+
const parts = value
|
|
89
|
+
.split(",")
|
|
90
|
+
.map((part) => part.trim())
|
|
91
|
+
.filter(Boolean);
|
|
92
|
+
const tags = parts.filter((part) => part.startsWith("tag:")).map((part) => part.slice(4).trim());
|
|
93
|
+
const actions = parts.filter((part) => !part.startsWith("tag:"));
|
|
94
|
+
if (tags.some((tag) => tag === ""))
|
|
95
|
+
throw new CliError("validation_error", "--do: tag: needs a name, e.g. tag:promo");
|
|
96
|
+
if (actions.length !== 1 || !ACTIONS.includes(actions[0]))
|
|
97
|
+
throw new CliError("validation_error", `--do: choose ${ACTIONS.join(", ")}, plus any tag:<name>`);
|
|
98
|
+
const action = actions[0];
|
|
99
|
+
return { action: action === "protect" ? "keep" : action, protect: action === "protect", tags };
|
|
100
|
+
};
|
|
101
|
+
//# sourceMappingURL=rule-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-query.js","sourceRoot":"","sources":["../../src/mail/rule-query.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,13 +2,11 @@ import type { AccountKey, MessageStore } from "@wirecat/cli-core/store";
|
|
|
2
2
|
import type { MailAccountConfig } from "./accounts.js";
|
|
3
3
|
import { type MailRule, type MailRuleMatch } from "./rules.js";
|
|
4
4
|
export declare const ruleInput: (rule: MailRule, source?: string) => {
|
|
5
|
-
conditions:
|
|
6
|
-
from?: string | undefined;
|
|
7
|
-
domain?: string | undefined;
|
|
8
|
-
list_id?: string | undefined;
|
|
9
|
-
};
|
|
5
|
+
conditions: Record<string, string | number | boolean>;
|
|
10
6
|
actions: {
|
|
11
7
|
store: string;
|
|
8
|
+
tags?: string[] | undefined;
|
|
9
|
+
tags_skipped?: Record<string, string> | undefined;
|
|
12
10
|
};
|
|
13
11
|
protected: boolean;
|
|
14
12
|
source: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule-store.d.ts","sourceRoot":"","sources":["../../src/mail/rule-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAA0B,MAAM,yBAAyB,CAAA;AAE/F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"rule-store.d.ts","sourceRoot":"","sources":["../../src/mail/rule-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAA0B,MAAM,yBAAyB,CAAA;AAE/F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAEtD,OAAO,EAAyD,KAAK,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAA;AAkBrH,eAAO,MAAM,SAAS,SAAU,QAAQ;;;;;;;;;;;CAWtC,CAAA;AAiDF,eAAO,MAAM,UAAU,YAAa,MAAM,KAAG,UAAqE,CAAA;AAMlH;;;;GAIG;AACH,eAAO,MAAM,eAAe,UACnB,YAAY,OACd,MAAM,CAAC,UAAU,OACjB,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,KAC1B,OAAO,CAAC,IAAI,CAuCd,CAAA;AAqBD,uGAAuG;AACvG,eAAO,MAAM,OAAO,UACX,YAAY,WACV,IAAI,CAAC,iBAAiB,EAAE,SAAS,CAAC,OACtC,MAAM,CAAC,UAAU,OACjB,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,KAC1B,OAAO,CAAC,QAAQ,EAAE,CAWpB,CAAA;AAED,eAAO,MAAM,QAAQ,UAAiB,YAAY,WAAW,MAAM,QAAQ,QAAQ,KAAG,OAAO,CAAC,QAAQ,CAIrG,CAAA;AAED,eAAO,MAAM,UAAU,UAAiB,YAAY,WAAW,MAAM,SAAS,aAAa,KAAG,OAAO,CAAC,OAAO,CAI5G,CAAA;AAED,eAAO,MAAM,UAAU,UAAiB,YAAY,WAAW,MAAM;;;GAMlE,CAAA"}
|
package/dist/mail/rule-store.js
CHANGED
|
@@ -1,38 +1,68 @@
|
|
|
1
1
|
import { chmodSync, copyFileSync, existsSync } from "node:fs";
|
|
2
2
|
import { configPath, loadConfig, updateConfig } from "../config.js";
|
|
3
|
-
import {
|
|
3
|
+
import { PRESET_NAMES } from "./presets.js";
|
|
4
|
+
import { conditionKeys, ENVELOPE, envelopeBox } from "./rules.js";
|
|
4
5
|
const STORE_ACTION = { keep: "full", envelope: "envelope", skip: "skip" };
|
|
5
6
|
const ACTION_OF = { full: "keep", envelope: "envelope", skip: "skip" };
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
const LOWER = ["from", "domain", "list_id", "subject"];
|
|
8
|
+
const conditionsOf = (match) => Object.fromEntries(conditionKeys(match).map((key) => {
|
|
9
|
+
const value = match[key];
|
|
10
|
+
return [
|
|
11
|
+
key,
|
|
12
|
+
LOWER.includes(key) && typeof value === "string" ? value.toLowerCase() : value,
|
|
13
|
+
];
|
|
14
|
+
}));
|
|
15
|
+
export const ruleInput = (rule, source = rule.source ?? "owner") => ({
|
|
12
16
|
conditions: conditionsOf(rule.match),
|
|
13
|
-
actions: {
|
|
17
|
+
actions: {
|
|
18
|
+
store: STORE_ACTION[rule.action],
|
|
19
|
+
...(rule.tags?.length ? { tags: rule.tags } : {}),
|
|
20
|
+
...(rule.tags_skipped && Object.keys(rule.tags_skipped).length ? { tags_skipped: rule.tags_skipped } : {}),
|
|
21
|
+
},
|
|
14
22
|
protected: rule.protected === true,
|
|
15
23
|
source,
|
|
16
24
|
reason: rule.reason ?? null,
|
|
17
25
|
decidedAt: Date.parse(rule.decided_at) || Date.now(),
|
|
18
26
|
});
|
|
27
|
+
const KINDS = {
|
|
28
|
+
from: "string",
|
|
29
|
+
from_contains: "string",
|
|
30
|
+
domain: "string",
|
|
31
|
+
to: "string",
|
|
32
|
+
list_id: "string",
|
|
33
|
+
subject: "string",
|
|
34
|
+
older_than_days: "number",
|
|
35
|
+
larger_than_bytes: "number",
|
|
36
|
+
has_attachments: "boolean",
|
|
37
|
+
label: "string",
|
|
38
|
+
unread: "boolean",
|
|
39
|
+
bulk: "boolean",
|
|
40
|
+
score_at_least: "number",
|
|
41
|
+
preset: "string",
|
|
42
|
+
};
|
|
19
43
|
const fromStored = (stored) => {
|
|
20
44
|
const action = ACTION_OF[String(stored.actions.store)];
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
// A condition memo does not know yet, from a newer memo or a preset, is left to that memo rather than misread.
|
|
28
|
-
if (action === undefined || Object.keys(match).length !== Object.keys(stored.conditions).length)
|
|
45
|
+
const entries = Object.entries(stored.conditions);
|
|
46
|
+
// A condition memo does not know yet, from a newer memo, is left to that memo rather than misread.
|
|
47
|
+
const known = entries.every(([key, value]) => key in KINDS &&
|
|
48
|
+
typeof value === KINDS[key] &&
|
|
49
|
+
!(key === "preset" && !PRESET_NAMES.includes(value)));
|
|
50
|
+
if (action === undefined || !known || entries.length === 0)
|
|
29
51
|
return undefined;
|
|
52
|
+
const tags = Array.isArray(stored.actions.tags) ? stored.actions.tags.filter((tag) => typeof tag === "string") : [];
|
|
53
|
+
const skipped = stored.actions.tags_skipped;
|
|
54
|
+
const tagsSkipped = skipped !== null && typeof skipped === "object" && !Array.isArray(skipped)
|
|
55
|
+
? Object.fromEntries(Object.entries(skipped).filter(([, why]) => typeof why === "string"))
|
|
56
|
+
: {};
|
|
30
57
|
return {
|
|
31
58
|
id: stored.id,
|
|
32
|
-
match,
|
|
59
|
+
match: Object.fromEntries(entries),
|
|
33
60
|
action,
|
|
61
|
+
...(tags.length ? { tags: tags } : {}),
|
|
62
|
+
...(Object.keys(tagsSkipped).length ? { tags_skipped: tagsSkipped } : {}),
|
|
34
63
|
...(stored.reason === null ? {} : { reason: stored.reason }),
|
|
35
64
|
...(stored.protected ? { protected: true } : {}),
|
|
65
|
+
...(stored.source === "owner" ? {} : { source: stored.source }),
|
|
36
66
|
decided_at: new Date(stored.decidedAt).toISOString(),
|
|
37
67
|
};
|
|
38
68
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule-store.js","sourceRoot":"","sources":["../../src/mail/rule-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAE7D,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAEnE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAsD,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"rule-store.js","sourceRoot":"","sources":["../../src/mail/rule-store.ts"],"names":[],"mappings":"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"}
|