@wirecat/cli-memo 0.23.0 → 0.25.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.
Files changed (232) hide show
  1. package/README.md +24 -21
  2. package/dist/actions/actions.d.ts +1 -1
  3. package/dist/actions/actions.d.ts.map +1 -1
  4. package/dist/actions/command.d.ts.map +1 -1
  5. package/dist/actions/command.js +14 -15
  6. package/dist/actions/command.js.map +1 -1
  7. package/dist/agents/command.d.ts.map +1 -1
  8. package/dist/agents/command.js +3 -2
  9. package/dist/agents/command.js.map +1 -1
  10. package/dist/answers/command.d.ts +1 -1
  11. package/dist/answers/command.d.ts.map +1 -1
  12. package/dist/answers/command.js +8 -8
  13. package/dist/answers/command.js.map +1 -1
  14. package/dist/author.d.ts +11 -0
  15. package/dist/author.d.ts.map +1 -0
  16. package/dist/author.js +16 -0
  17. package/dist/author.js.map +1 -0
  18. package/dist/bin/memo.js +6 -4
  19. package/dist/bin/memo.js.map +1 -1
  20. package/dist/config.d.ts +15 -2
  21. package/dist/config.d.ts.map +1 -1
  22. package/dist/config.js +15 -2
  23. package/dist/config.js.map +1 -1
  24. package/dist/context/command.d.ts.map +1 -1
  25. package/dist/context/command.js +4 -4
  26. package/dist/context/command.js.map +1 -1
  27. package/dist/context/context.d.ts +3 -3
  28. package/dist/context/context.d.ts.map +1 -1
  29. package/dist/context/context.js +3 -3
  30. package/dist/context/context.js.map +1 -1
  31. package/dist/discovery/command.d.ts +2 -0
  32. package/dist/discovery/command.d.ts.map +1 -1
  33. package/dist/discovery/command.js +18 -10
  34. package/dist/discovery/command.js.map +1 -1
  35. package/dist/examples.d.ts +5 -0
  36. package/dist/examples.d.ts.map +1 -0
  37. package/dist/examples.js +135 -0
  38. package/dist/examples.js.map +1 -0
  39. package/dist/facts/command.d.ts.map +1 -1
  40. package/dist/facts/command.js +19 -18
  41. package/dist/facts/command.js.map +1 -1
  42. package/dist/install/postinstall.d.ts +7 -0
  43. package/dist/install/postinstall.d.ts.map +1 -0
  44. package/dist/install/postinstall.js +28 -0
  45. package/dist/install/postinstall.js.map +1 -0
  46. package/dist/knowledge/command.d.ts.map +1 -1
  47. package/dist/knowledge/command.js +107 -62
  48. package/dist/knowledge/command.js.map +1 -1
  49. package/dist/knowledge/key-documents.d.ts +29 -0
  50. package/dist/knowledge/key-documents.d.ts.map +1 -0
  51. package/dist/knowledge/key-documents.js +76 -0
  52. package/dist/knowledge/key-documents.js.map +1 -0
  53. package/dist/knowledge/meeting-projects-command.js +4 -4
  54. package/dist/knowledge/meeting-projects-command.js.map +1 -1
  55. package/dist/mail/accounts.d.ts +11 -0
  56. package/dist/mail/accounts.d.ts.map +1 -0
  57. package/dist/mail/accounts.js +26 -0
  58. package/dist/mail/accounts.js.map +1 -0
  59. package/dist/mail/command.d.ts +1 -1
  60. package/dist/mail/command.d.ts.map +1 -1
  61. package/dist/mail/command.js +132 -98
  62. package/dist/mail/command.js.map +1 -1
  63. package/dist/mail/gmail.d.ts +7 -2
  64. package/dist/mail/gmail.d.ts.map +1 -1
  65. package/dist/mail/gmail.js +76 -37
  66. package/dist/mail/gmail.js.map +1 -1
  67. package/dist/mail/headers.d.ts +17 -0
  68. package/dist/mail/headers.d.ts.map +1 -0
  69. package/dist/mail/headers.js +28 -0
  70. package/dist/mail/headers.js.map +1 -0
  71. package/dist/mail/himalaya.d.ts +3 -1
  72. package/dist/mail/himalaya.d.ts.map +1 -1
  73. package/dist/mail/himalaya.js +2 -2
  74. package/dist/mail/himalaya.js.map +1 -1
  75. package/dist/mail/import.d.ts +15 -6
  76. package/dist/mail/import.d.ts.map +1 -1
  77. package/dist/mail/import.js +130 -87
  78. package/dist/mail/import.js.map +1 -1
  79. package/dist/mail/mbox.d.ts +9 -0
  80. package/dist/mail/mbox.d.ts.map +1 -0
  81. package/dist/mail/mbox.js +218 -0
  82. package/dist/mail/mbox.js.map +1 -0
  83. package/dist/mail/messages-command.d.ts +4 -0
  84. package/dist/mail/messages-command.d.ts.map +1 -0
  85. package/dist/mail/messages-command.js +32 -0
  86. package/dist/mail/messages-command.js.map +1 -0
  87. package/dist/mail/parse.d.ts +2 -2
  88. package/dist/mail/parse.d.ts.map +1 -1
  89. package/dist/mail/parse.js +27 -63
  90. package/dist/mail/parse.js.map +1 -1
  91. package/dist/mail/probe.d.ts +31 -0
  92. package/dist/mail/probe.d.ts.map +1 -0
  93. package/dist/mail/probe.js +55 -0
  94. package/dist/mail/probe.js.map +1 -0
  95. package/dist/mail/rules.d.ts +18 -0
  96. package/dist/mail/rules.d.ts.map +1 -0
  97. package/dist/mail/rules.js +26 -0
  98. package/dist/mail/rules.js.map +1 -0
  99. package/dist/mail/source.d.ts +20 -0
  100. package/dist/mail/source.d.ts.map +1 -0
  101. package/dist/mail/source.js +99 -0
  102. package/dist/mail/source.js.map +1 -0
  103. package/dist/mcp/command.js +1 -1
  104. package/dist/mcp/command.js.map +1 -1
  105. package/dist/mcp/knowledge.js +4 -4
  106. package/dist/mcp/knowledge.js.map +1 -1
  107. package/dist/mcp/server.js +11 -11
  108. package/dist/mcp/server.js.map +1 -1
  109. package/dist/mcp/task-relations.d.ts +3 -3
  110. package/dist/mcp/task-relations.d.ts.map +1 -1
  111. package/dist/mcp/task-relations.js +17 -8
  112. package/dist/mcp/task-relations.js.map +1 -1
  113. package/dist/mcp/tool.d.ts +1 -1
  114. package/dist/mcp/tool.d.ts.map +1 -1
  115. package/dist/mcp/vocabulary.d.ts +2 -3
  116. package/dist/mcp/vocabulary.d.ts.map +1 -1
  117. package/dist/mcp/vocabulary.js +23 -18
  118. package/dist/mcp/vocabulary.js.map +1 -1
  119. package/dist/memories/command.d.ts +1 -0
  120. package/dist/memories/command.d.ts.map +1 -1
  121. package/dist/memories/command.js +23 -21
  122. package/dist/memories/command.js.map +1 -1
  123. package/dist/memories/memories.d.ts +1 -1
  124. package/dist/memories/memories.d.ts.map +1 -1
  125. package/dist/notes/about.d.ts +12 -3
  126. package/dist/notes/about.d.ts.map +1 -1
  127. package/dist/notes/about.js +35 -31
  128. package/dist/notes/about.js.map +1 -1
  129. package/dist/notes/bound.d.ts +4 -1
  130. package/dist/notes/bound.d.ts.map +1 -1
  131. package/dist/notes/bound.js +9 -1
  132. package/dist/notes/bound.js.map +1 -1
  133. package/dist/notes/command.d.ts.map +1 -1
  134. package/dist/notes/command.js +18 -61
  135. package/dist/notes/command.js.map +1 -1
  136. package/dist/notes/embed.d.ts +1 -1
  137. package/dist/notes/embed.d.ts.map +1 -1
  138. package/dist/notes/embed.js +1 -1
  139. package/dist/notes/embed.js.map +1 -1
  140. package/dist/notes/folders-command.d.ts.map +1 -1
  141. package/dist/notes/folders-command.js +13 -7
  142. package/dist/notes/folders-command.js.map +1 -1
  143. package/dist/notes/import.d.ts +2 -2
  144. package/dist/notes/import.d.ts.map +1 -1
  145. package/dist/notes/import.js +2 -2
  146. package/dist/notes/import.js.map +1 -1
  147. package/dist/notes/internal.d.ts +1 -1
  148. package/dist/notes/internal.d.ts.map +1 -1
  149. package/dist/notes/links.d.ts +1 -1
  150. package/dist/notes/links.d.ts.map +1 -1
  151. package/dist/notes/list.d.ts +22 -0
  152. package/dist/notes/list.d.ts.map +1 -0
  153. package/dist/notes/list.js +24 -0
  154. package/dist/notes/list.js.map +1 -0
  155. package/dist/notes/search.d.ts +3 -3
  156. package/dist/notes/search.d.ts.map +1 -1
  157. package/dist/notes/search.js +3 -3
  158. package/dist/notes/search.js.map +1 -1
  159. package/dist/options.d.ts +2 -0
  160. package/dist/options.d.ts.map +1 -1
  161. package/dist/options.js +2 -0
  162. package/dist/options.js.map +1 -1
  163. package/dist/people/command.js +3 -3
  164. package/dist/people/command.js.map +1 -1
  165. package/dist/people/identity.d.ts +1 -1
  166. package/dist/people/identity.d.ts.map +1 -1
  167. package/dist/people/identity.js +1 -1
  168. package/dist/people/identity.js.map +1 -1
  169. package/dist/people/notes-map.d.ts +1 -1
  170. package/dist/people/notes-map.d.ts.map +1 -1
  171. package/dist/people/subject.d.ts +1 -1
  172. package/dist/people/subject.d.ts.map +1 -1
  173. package/dist/people/subject.js +1 -1
  174. package/dist/people/subject.js.map +1 -1
  175. package/dist/program.d.ts +5 -0
  176. package/dist/program.d.ts.map +1 -1
  177. package/dist/program.js +35 -4
  178. package/dist/program.js.map +1 -1
  179. package/dist/records/run.d.ts +1 -1
  180. package/dist/records/run.d.ts.map +1 -1
  181. package/dist/records/run.js +1 -1
  182. package/dist/records/run.js.map +1 -1
  183. package/dist/run/auto.d.ts.map +1 -1
  184. package/dist/run/auto.js +11 -13
  185. package/dist/run/auto.js.map +1 -1
  186. package/dist/run/import.d.ts +2 -2
  187. package/dist/run/import.d.ts.map +1 -1
  188. package/dist/run/import.js +71 -28
  189. package/dist/run/import.js.map +1 -1
  190. package/dist/run/lock.d.ts +1 -1
  191. package/dist/run/lock.d.ts.map +1 -1
  192. package/dist/run/lock.js +2 -2
  193. package/dist/run/lock.js.map +1 -1
  194. package/dist/search/command.d.ts +16 -21
  195. package/dist/search/command.d.ts.map +1 -1
  196. package/dist/search/command.js +101 -51
  197. package/dist/search/command.js.map +1 -1
  198. package/dist/store/gone.d.ts +1 -1
  199. package/dist/store/gone.d.ts.map +1 -1
  200. package/dist/store/held.d.ts +1 -1
  201. package/dist/store/held.d.ts.map +1 -1
  202. package/dist/store/scope.d.ts +1 -1
  203. package/dist/store/scope.d.ts.map +1 -1
  204. package/dist/store/scope.js +1 -1
  205. package/dist/store/scope.js.map +1 -1
  206. package/dist/store/source-target.d.ts +1 -1
  207. package/dist/store/source-target.d.ts.map +1 -1
  208. package/dist/store/source-target.js +1 -1
  209. package/dist/store/source-target.js.map +1 -1
  210. package/dist/tags/command.d.ts.map +1 -1
  211. package/dist/tags/command.js +19 -9
  212. package/dist/tags/command.js.map +1 -1
  213. package/dist/tasks/command.d.ts.map +1 -1
  214. package/dist/tasks/command.js +19 -9
  215. package/dist/tasks/command.js.map +1 -1
  216. package/dist/tasks/context.d.ts +2 -2
  217. package/dist/tasks/context.d.ts.map +1 -1
  218. package/dist/tasks/context.js +2 -2
  219. package/dist/tasks/context.js.map +1 -1
  220. package/dist/tasks/relations-command.d.ts.map +1 -1
  221. package/dist/tasks/relations-command.js +9 -22
  222. package/dist/tasks/relations-command.js.map +1 -1
  223. package/dist/version.d.ts +1 -1
  224. package/dist/version.js +1 -1
  225. package/dist/vocabulary/command.d.ts.map +1 -1
  226. package/dist/vocabulary/command.js +45 -33
  227. package/dist/vocabulary/command.js.map +1 -1
  228. package/dist/vocabulary/project.d.ts +1 -1
  229. package/dist/vocabulary/project.d.ts.map +1 -1
  230. package/install/postinstall.mjs +9 -0
  231. package/package.json +9 -4
  232. package/skills/cli-memo/SKILL.md +60 -0
@@ -0,0 +1,218 @@
1
+ import { createReadStream } from "node:fs";
2
+ import { open } from "node:fs/promises";
3
+ import { CliError } from "@wirecat/cli-base";
4
+ import { systemLabel } from "./gmail.js";
5
+ import { field, headersOf, unfold } from "./headers.js";
6
+ const NEWLINE = 10;
7
+ const CR = 13;
8
+ const SEPARATOR = Buffer.from("\nFrom ");
9
+ const MAX_HEADER = 256 * 1024;
10
+ const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
11
+ /** Takeout's own marks, not labels the owner gave: read state and "not in Inbox". */
12
+ const PSEUDO_LABELS = new Set(["Opened", "Unread", "Archived"]);
13
+ /** `Mon Jul 24 10:00:00 +0000 2023`: asctime, with the zone Takeout writes. */
14
+ const separatorDate = (rest) => {
15
+ const match = /(\w{3}) +(\d{1,2}) (\d{2}):(\d{2}):(\d{2})(?: ([+-])(\d{2})(\d{2}))? (\d{4})/.exec(rest);
16
+ if (match === null)
17
+ return undefined;
18
+ const [, month = "", day, hour, minute, second, sign, offsetHours, offsetMinutes, year] = match;
19
+ if (!MONTHS.includes(month))
20
+ return undefined;
21
+ const local = Date.UTC(Number(year), MONTHS.indexOf(month), Number(day), Number(hour), Number(minute), Number(second));
22
+ const offset = sign === undefined ? 0 : (Number(offsetHours) * 60 + Number(offsetMinutes)) * 60_000;
23
+ return local - (sign === "-" ? -offset : offset);
24
+ };
25
+ /** RFC 2047 encoded words, which Takeout uses for labels outside ASCII. */
26
+ const decodeWords = (text) => text
27
+ .replace(/(\?=)\s+(=\?)/g, "$1$2")
28
+ .replace(/=\?([^?]+)\?([bBqQ])\?([^?]*)\?=/g, (_, charset, encoding, data) => {
29
+ const bytes = encoding.toUpperCase() === "B"
30
+ ? Buffer.from(data, "base64")
31
+ : Buffer.from(data
32
+ .replace(/_/g, " ")
33
+ .replace(/=([0-9A-Fa-f]{2})/g, (_hex, hex) => String.fromCharCode(parseInt(hex, 16))), "latin1");
34
+ try {
35
+ return new TextDecoder(charset).decode(bytes);
36
+ }
37
+ catch {
38
+ return bytes.toString("utf8");
39
+ }
40
+ });
41
+ const splitLabels = (value) => {
42
+ const labels = [];
43
+ let current = "";
44
+ let quoted = false;
45
+ for (const c of value) {
46
+ if (c === '"')
47
+ quoted = !quoted;
48
+ else if (c === "," && !quoted) {
49
+ labels.push(current);
50
+ current = "";
51
+ }
52
+ else
53
+ current += c;
54
+ }
55
+ labels.push(current);
56
+ return labels.map((label) => label.trim()).filter(Boolean);
57
+ };
58
+ const entryOf = (separator, header, start, body) => {
59
+ const [, sender = "", rest = ""] = /^From (\S+) ?(.*)$/.exec(separator) ?? [];
60
+ const messageId = /^(\d+)@/.exec(sender)?.[1];
61
+ // The id is what joins this archive to the IMAP account; never invented, so a wrong guess fails here.
62
+ if (messageId === undefined)
63
+ throw new CliError("invalid_response", `the mbox email at byte ${start} has no Gmail message id: its "From " line should read "From <digits>@xxx <date>"`);
64
+ const unfolded = unfold(header);
65
+ const date = separatorDate(rest) ?? Date.parse(field(unfolded, "Date") ?? "");
66
+ if (Number.isNaN(date))
67
+ throw new CliError("invalid_response", `the mbox email at byte ${start} has no readable date`);
68
+ const written = field(unfolded, "X-Gmail-Labels");
69
+ const raw = written === undefined ? undefined : splitLabels(decodeWords(written));
70
+ const labels = raw === undefined ? undefined : [...new Set(raw.filter((name) => !PSEUDO_LABELS.has(name)).map(systemLabel))].sort();
71
+ const seen = raw?.includes("Unread") ? false : raw?.includes("Opened") ? true : undefined;
72
+ const threadId = field(unfolded, "X-GM-THRID")?.trim();
73
+ return {
74
+ item: {
75
+ uid: messageId,
76
+ messageId,
77
+ threadId: threadId || messageId,
78
+ receivedAt: new Date(date).toISOString(),
79
+ ...(labels === undefined ? {} : { labels, flagged: labels.includes("Starred") }),
80
+ ...(seen === undefined ? {} : { seen }),
81
+ headers: headersOf(header),
82
+ },
83
+ start,
84
+ body,
85
+ end: -1,
86
+ };
87
+ };
88
+ /**
89
+ * One pass over the file: a "From " line after a blank line starts an email. Only headers are kept in memory;
90
+ * bodies are skipped with a byte search, so a 20 GB archive costs one read and no more memory than its headers.
91
+ */
92
+ const scan = async (path, chunkSize) => {
93
+ const entries = [];
94
+ let base = 0;
95
+ let pos = 0;
96
+ let bodyFrom = 0;
97
+ let inHeaders = true;
98
+ let separator;
99
+ let start = 0;
100
+ let body = 0;
101
+ let lines = [];
102
+ let headerBytes = 0;
103
+ const take = (buf, eof) => {
104
+ for (;;) {
105
+ if (inHeaders) {
106
+ let nl = buf.indexOf(NEWLINE, pos);
107
+ if (nl === -1) {
108
+ if (!eof || pos >= buf.length)
109
+ return Math.max(0, pos - 2);
110
+ nl = buf.length;
111
+ }
112
+ let line = buf.subarray(pos, nl);
113
+ if (line.at(-1) === CR)
114
+ line = line.subarray(0, -1);
115
+ if (separator === undefined) {
116
+ separator = line.toString("latin1");
117
+ if (!separator.startsWith("From "))
118
+ throw new CliError("validation_error", `${path} is not an mbox file: byte ${base + pos} starts no "From " line`);
119
+ start = base + pos;
120
+ body = base + nl + 1;
121
+ }
122
+ else if (line.length === 0) {
123
+ entries.push(entryOf(separator, Buffer.concat(lines).toString("utf8"), start, body));
124
+ lines = [];
125
+ headerBytes = 0;
126
+ inHeaders = false;
127
+ bodyFrom = nl;
128
+ }
129
+ else if (headerBytes < MAX_HEADER) {
130
+ lines.push(Buffer.from(line), Buffer.from("\n"));
131
+ headerBytes += line.length + 1;
132
+ }
133
+ pos = nl + 1;
134
+ continue;
135
+ }
136
+ const at = buf.indexOf(SEPARATOR, bodyFrom);
137
+ if (at === -1) {
138
+ const next = Math.max(bodyFrom, buf.length - (SEPARATOR.length - 1));
139
+ const keep = Math.max(0, next - 2);
140
+ bodyFrom = next - keep;
141
+ return keep;
142
+ }
143
+ const blank = buf[at - 1] === NEWLINE || (buf[at - 1] === CR && buf[at - 2] === NEWLINE);
144
+ if (!blank) {
145
+ bodyFrom = at + 1;
146
+ continue;
147
+ }
148
+ const last = entries.at(-1);
149
+ if (last)
150
+ last.end = base + at + 1;
151
+ inHeaders = true;
152
+ separator = undefined;
153
+ pos = at + 1;
154
+ }
155
+ };
156
+ let carry = Buffer.alloc(0);
157
+ for await (const chunk of createReadStream(path, { highWaterMark: chunkSize })) {
158
+ const buf = carry.length ? Buffer.concat([carry, chunk]) : chunk;
159
+ const keep = take(buf, false);
160
+ base += keep;
161
+ pos -= keep;
162
+ carry = buf.subarray(keep);
163
+ }
164
+ take(carry, true);
165
+ if (inHeaders && separator !== undefined)
166
+ entries.push(entryOf(separator, Buffer.concat(lines).toString("utf8"), start, body));
167
+ const last = entries.at(-1);
168
+ if (last && last.end === -1)
169
+ last.end = base + carry.length;
170
+ for (const entry of entries)
171
+ entry.item.size = entry.end - entry.start;
172
+ return entries;
173
+ };
174
+ /** The email as Gmail stored it: the blank line mbox adds after it removed, and mboxrd's `>From ` undone. */
175
+ const asStored = (bytes) => {
176
+ const text = bytes.toString("latin1");
177
+ const trimmed = /\r?\n\r?\n$/.test(text) ? text.replace(/\r?\n$/, "") : text;
178
+ return Buffer.from(trimmed.replace(/^>(>*From )/gm, "$1"), "latin1");
179
+ };
180
+ /**
181
+ * A Google Takeout mbox of Gmail: the same message and thread ids IMAP reports, so its emails and the
182
+ * account's IMAP emails are one set. Spam and Trash are left out, as IMAP's All Mail leaves them out.
183
+ */
184
+ export const mboxSource = (path, { chunkSize = 1024 * 1024 } = {}) => {
185
+ let index;
186
+ const indexed = () => {
187
+ index ??= scan(path, chunkSize).then((entries) => new Map(entries.map((entry) => [entry.item.messageId, entry])));
188
+ return index;
189
+ };
190
+ return {
191
+ list: async (since, folder) => [...(await indexed()).values()]
192
+ .filter(({ item }) => Date.parse(item.receivedAt) >= since.getTime() &&
193
+ !item.labels?.some((label) => label === "Spam" || label === "Trash"))
194
+ .map(({ item }) => ({ ...item, folder })),
195
+ fetchRaw: async (items) => {
196
+ const entries = await indexed();
197
+ const handle = await open(path);
198
+ try {
199
+ const read = [];
200
+ for (const item of items) {
201
+ const entry = entries.get(item.messageId);
202
+ if (entry === undefined) {
203
+ read.push(new CliError("not_found", `email ${item.messageId} is not in the mbox file`));
204
+ continue;
205
+ }
206
+ const bytes = Buffer.alloc(entry.end - entry.body);
207
+ await handle.read(bytes, 0, bytes.length, entry.body);
208
+ read.push(asStored(bytes));
209
+ }
210
+ return read;
211
+ }
212
+ finally {
213
+ await handle.close();
214
+ }
215
+ },
216
+ };
217
+ };
218
+ //# sourceMappingURL=mbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mbox.js","sourceRoot":"","sources":["../../src/mail/mbox.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { type Streams } from "@wirecat/cli-base";
2
+ import type { Command } from "commander";
3
+ export declare const messagesCommand: (program: Command, streams: Streams, env: NodeJS.ProcessEnv) => void;
4
+ //# sourceMappingURL=messages-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages-command.d.ts","sourceRoot":"","sources":["../../src/mail/messages-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAI1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAIxC,eAAO,MAAM,eAAe,YAAa,OAAO,WAAW,OAAO,OAAO,MAAM,CAAC,UAAU,KAAG,IAwB5F,CAAA"}
@@ -0,0 +1,32 @@
1
+ import { CliError } from "@wirecat/cli-base";
2
+ import { parseLocator, resolveOutput } from "@wirecat/cli-core";
3
+ import { readMail } from "@wirecat/cli-core/services";
4
+ import { openStore } from "@wirecat/cli-core/store";
5
+ import { whole } from "../options.js";
6
+ import { found } from "../search/command.js";
7
+ export const messagesCommand = (program, streams, env) => {
8
+ const messages = program.command("messages").description("stored emails; tg and max read messenger messages");
9
+ messages
10
+ .command("show")
11
+ .description("one stored email, whole, and the emails of its thread around it")
12
+ .argument("<message>", "the email's msg:email/… reference, as search answers give it")
13
+ .option("--before-n <n>", "also this many earlier emails of its thread", whole, 0)
14
+ .option("--after-n <n>", "also this many later emails of its thread", whole, 0)
15
+ .option("--json", "print JSON")
16
+ .action(async (reference, options) => {
17
+ if (parseLocator(reference).provider !== "email")
18
+ throw new CliError("validation_error", `${reference} is not an email; tg and max show messenger messages`);
19
+ const store = await openStore({ env });
20
+ try {
21
+ const emails = await readMail(store, reference, { before: options.beforeN, after: options.afterN });
22
+ if (options.json)
23
+ resolveOutput({ json: true, streams }).renderer.result(options.beforeN || options.afterN ? { items: emails } : emails[0]);
24
+ else
25
+ streams.data(`${emails.map((email) => found(email, "full")).join("\n\n")}\n`);
26
+ }
27
+ finally {
28
+ await store.close();
29
+ }
30
+ });
31
+ };
32
+ //# sourceMappingURL=messages-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages-command.js","sourceRoot":"","sources":["../../src/mail/messages-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAgB,MAAM,mBAAmB,CAAA;AAC1D,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AAEnD,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AACrC,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAE5C,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAgB,EAAE,OAAgB,EAAE,GAAsB,EAAQ,EAAE;IAClG,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,WAAW,CAAC,mDAAmD,CAAC,CAAA;IAC7G,QAAQ;SACL,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,iEAAiE,CAAC;SAC9E,QAAQ,CAAC,WAAW,EAAE,8DAA8D,CAAC;SACrF,MAAM,CAAC,gBAAgB,EAAE,6CAA6C,EAAE,KAAK,EAAE,CAAC,CAAC;SACjF,MAAM,CAAC,eAAe,EAAE,2CAA2C,EAAE,KAAK,EAAE,CAAC,CAAC;SAC9E,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC;SAC9B,MAAM,CAAC,KAAK,EAAE,SAAiB,EAAE,OAA4D,EAAE,EAAE;QAChG,IAAI,YAAY,CAAC,SAAS,CAAC,CAAC,QAAQ,KAAK,OAAO;YAC9C,MAAM,IAAI,QAAQ,CAAC,kBAAkB,EAAE,GAAG,SAAS,sDAAsD,CAAC,CAAA;QAC5G,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,EAAE,GAAG,EAAE,CAAC,CAAA;QACtC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;YACnG,IAAI,OAAO,CAAC,IAAI;gBACd,aAAa,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,CACpD,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAClE,CAAA;;gBACE,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACpF,CAAC;gBAAS,CAAC;YACT,MAAM,KAAK,CAAC,KAAK,EAAE,CAAA;QACrB,CAAC;IACH,CAAC,CAAC,CAAA;AACN,CAAC,CAAA"}
@@ -17,6 +17,6 @@ export interface ParsedMail {
17
17
  text: string;
18
18
  }
19
19
  export declare const MAX_BODY_CHARS = 1000000;
20
- /** `himalaya --json message read`: the `mail-parser` crate's message, serialised as it is. */
21
- export declare const parseMail: (json: string, maxBodyChars?: number) => ParsedMail;
20
+ /** A raw RFC 5322 message, as IMAP's `BODY[]` holds it. */
21
+ export declare const parseMail: (raw: Uint8Array, maxBodyChars?: number) => Promise<ParsedMail>;
22
22
  //# sourceMappingURL=parse.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/mail/parse.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;IACpB,EAAE,EAAE,OAAO,EAAE,CAAA;IACb,EAAE,EAAE,OAAO,EAAE,CAAA;IACb,GAAG,EAAE,OAAO,EAAE,CAAA;IACd,WAAW,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;KAAE,EAAE,CAAA;IAC1F,IAAI,EAAE,MAAM,CAAA;CACb;AAeD,eAAO,MAAM,cAAc,UAAY,CAAA;AAoCvC,8FAA8F;AAC9F,eAAO,MAAM,SAAS,SAAU,MAAM,4BAAkC,UA2EvE,CAAA"}
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/mail/parse.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,IAAI,EAAE,OAAO,GAAG,IAAI,CAAA;IACpB,EAAE,EAAE,OAAO,EAAE,CAAA;IACb,EAAE,EAAE,OAAO,EAAE,CAAA;IACb,GAAG,EAAE,OAAO,EAAE,CAAA;IACd,WAAW,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;KAAE,EAAE,CAAA;IAC1F,IAAI,EAAE,MAAM,CAAA;CACb;AAGD,eAAO,MAAM,cAAc,UAAY,CAAA;AA6BvC,2DAA2D;AAC3D,eAAO,MAAM,SAAS,QAAe,UAAU,4BAAkC,OAAO,CAAC,UAAU,CAsBlG,CAAA"}
@@ -1,19 +1,10 @@
1
1
  import { CliError } from "@wirecat/cli-base";
2
+ import PostalMime, {} from "postal-mime";
2
3
  // The store cuts a body into pieces itself; this only guards against a pathological one, like a pasted log.
3
4
  export const MAX_BODY_CHARS = 1_000_000;
4
- const addresses = (value) => {
5
- const address = value?.Address;
6
- const list = address !== undefined && "List" in address
7
- ? (address.List ?? [])
8
- : address !== undefined && "Group" in address
9
- ? (address.Group ?? []).flatMap((group) => group.addresses ?? [])
10
- : [];
11
- return list.flatMap(({ address: email, name }) => (email ? [{ email: email.toLowerCase(), name: name ?? null }] : []));
12
- };
13
- const bodyText = (part, kind) => {
14
- const body = part?.body;
15
- return typeof body === "object" && body !== null && typeof body[kind] === "string" ? body[kind] : "";
16
- };
5
+ const addresses = (list) => list
6
+ .flatMap((entry) => entry.group ?? [entry])
7
+ .flatMap(({ address, name }) => (address ? [{ email: address.toLowerCase(), name: name || null }] : []));
17
8
  const htmlToText = (html) => html
18
9
  .replace(/<(script|style)[\s\S]*?<\/\1>/gi, "")
19
10
  .replace(/<br\s*\/?>|<\/(p|div|li|tr|h\d)>/gi, "\n")
@@ -27,60 +18,33 @@ const htmlToText = (html) => html
27
18
  .replace(/[ \t]+\n/g, "\n")
28
19
  .replace(/\n{3,}/g, "\n\n")
29
20
  .trim();
30
- /** `himalaya --json message read`: the `mail-parser` crate's message, serialised as it is. */
31
- export const parseMail = (json, maxBodyChars = MAX_BODY_CHARS) => {
32
- let parsed;
21
+ const bytesOf = (content) => typeof content === "string"
22
+ ? new TextEncoder().encode(content)
23
+ : content instanceof Uint8Array
24
+ ? content
25
+ : new Uint8Array(content);
26
+ /** A raw RFC 5322 message, as IMAP's `BODY[]` holds it. */
27
+ export const parseMail = async (raw, maxBodyChars = MAX_BODY_CHARS) => {
28
+ let email;
33
29
  try {
34
- parsed = JSON.parse(json);
30
+ email = await PostalMime.parse(raw);
35
31
  }
36
- catch {
37
- throw new CliError("invalid_response", "himalaya message read did not answer JSON");
32
+ catch (error) {
33
+ throw new CliError("invalid_response", `unreadable email: ${error instanceof Error ? error.message : error}`);
38
34
  }
39
- if (!parsed || !Array.isArray(parsed.parts) || !Array.isArray(parsed.text_body) || !Array.isArray(parsed.html_body))
40
- throw new CliError("invalid_response", "himalaya returned an incomplete parsed message");
41
- if (parsed.attachments !== undefined && !Array.isArray(parsed.attachments))
42
- throw new CliError("invalid_response", "himalaya returned invalid attachment metadata");
43
- const headers = parsed.parts[0]?.headers ?? [];
44
- const header = (name) => headers.find((item) => item.name === name)?.value;
45
- const subject = header("subject")?.Text ?? null;
46
- const plain = parsed.text_body
47
- .map((index) => bodyText(parsed.parts[index], "Text"))
48
- .join("\n\n")
49
- .trim();
50
- const text = plain || htmlToText(parsed.html_body.map((index) => bodyText(parsed.parts[index], "Html")).join("\n"));
35
+ const text = email.text?.trim() || htmlToText(email.html ?? "");
51
36
  return {
52
- subject,
53
- from: addresses(header("from"))[0] ?? null,
54
- to: addresses(header("to")),
55
- cc: addresses(header("cc")),
56
- bcc: addresses(header("bcc")),
57
- attachments: (parsed.attachments ?? []).slice(0, 50).map((id) => {
58
- const part = parsed.parts[id];
59
- const value = (name) => part?.headers.find((item) => typeof item.name === "string" && item.name.replaceAll("_", "-") === name)?.value;
60
- const type = value("content-type")?.ContentType;
61
- const disposition = value("content-disposition")?.ContentType;
62
- const attrs = [...(disposition?.attributes ?? []), ...(type?.attributes ?? [])];
63
- const name = attrs.find((attr) => ["filename", "name"].includes(attr.name ?? attr.attribute ?? ""))?.value ??
64
- `attachment-${id}`;
65
- const raw = typeof part?.body === "object" && part.body !== null ? (part.body.Binary ?? part.body.InlineBinary) : undefined;
66
- let bytes = null;
67
- if (Array.isArray(raw) &&
68
- raw.length <= 50 * 1024 * 1024 &&
69
- raw.every((byte) => Number.isInteger(byte) && byte >= 0 && byte <= 255))
70
- bytes = Uint8Array.from(raw);
71
- else if (typeof raw === "string" && raw.length <= 70_000_000 && /^[A-Za-z0-9+/]*={0,2}$/.test(raw))
72
- bytes = Buffer.from(raw, "base64");
73
- else if (typeof part?.body === "object" && part.body !== null && typeof part.body.Text === "string")
74
- bytes = new TextEncoder().encode(part.body.Text);
75
- else if (typeof part?.body === "object" && part.body !== null && typeof part.body.Html === "string")
76
- bytes = new TextEncoder().encode(htmlToText(part.body.Html));
77
- return {
78
- id,
79
- name: name.slice(0, 200),
80
- mime: type?.c_type ? `${type.c_type}/${type.c_subtype ?? "octet-stream"}` : null,
81
- bytes,
82
- };
83
- }),
37
+ subject: email.subject ?? null,
38
+ from: addresses(email.from === undefined ? [] : [email.from])[0] ?? null,
39
+ to: addresses(email.to ?? []),
40
+ cc: addresses(email.cc ?? []),
41
+ bcc: addresses(email.bcc ?? []),
42
+ attachments: email.attachments.slice(0, 50).map((part, id) => ({
43
+ id,
44
+ name: (part.filename ?? `attachment-${id}`).slice(0, 200),
45
+ mime: part.mimeType || null,
46
+ bytes: bytesOf(part.content),
47
+ })),
84
48
  text: text.replace(/\r\n?/g, "\n").slice(0, maxBodyChars),
85
49
  };
86
50
  };
@@ -1 +1 @@
1
- {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/mail/parse.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/mail/parse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { Listed } from "./source.js";
2
+ export declare const SUGGEST_RULE: string;
3
+ export interface ProbeGroup {
4
+ /** The sender; for a list, the first sender seen. */
5
+ from: string | null;
6
+ listId: string | null;
7
+ emails: number;
8
+ bytes: number;
9
+ /** Share of emails not read; null when the source does not say. */
10
+ unread: number | null;
11
+ /** Share of emails marked as list or bulk mail. */
12
+ bulk: number;
13
+ firstYear: number;
14
+ lastYear: number;
15
+ /** The owner sent mail to one of the group's senders. */
16
+ replied: boolean;
17
+ suggest: "skip" | null;
18
+ }
19
+ export interface Probe {
20
+ emails: number;
21
+ bytes: number;
22
+ /** Mail the owner sent: not grouped, but its recipients tell who was replied to. */
23
+ sent: number;
24
+ /** Emails whose headers could not be read: not grouped. */
25
+ withoutHeaders: number;
26
+ groups: number;
27
+ items: ProbeGroup[];
28
+ }
29
+ /** Groups mail by List-Id when it has one, else by sender address; largest groups first. */
30
+ export declare const probeMail: (items: Listed[], limit: number) => Probe;
31
+ //# sourceMappingURL=probe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"probe.d.ts","sourceRoot":"","sources":["../../src/mail/probe.ts"],"names":[],"mappings":"AAAA,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;CACvB;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;CACpB;AAMD,4FAA4F;AAC5F,eAAO,MAAM,SAAS,UAAW,MAAM,EAAE,SAAS,MAAM,KAAG,KA6C1D,CAAA"}
@@ -0,0 +1,55 @@
1
+ export const SUGGEST_RULE = "suggest is skip when a group has at least 20 emails, at least 80% of them list or bulk mail " +
2
+ "(List-Id, List-Unsubscribe or Precedence: bulk) and the owner never sent mail to its sender";
3
+ const share = (part, whole) => Math.round((part / whole) * 100) / 100;
4
+ const isSent = (item) => item.labels?.includes("Sent") || /(^|\/)sent\b/i.test(item.folder ?? "");
5
+ /** Groups mail by List-Id when it has one, else by sender address; largest groups first. */
6
+ export const probeMail = (items, limit) => {
7
+ const sent = items.filter(isSent);
8
+ const recipients = new Set(sent.flatMap((item) => item.headers?.to ?? []));
9
+ const groups = new Map();
10
+ let withoutHeaders = 0;
11
+ for (const item of items) {
12
+ if (isSent(item))
13
+ continue;
14
+ const headers = item.headers;
15
+ if (headers === undefined || (headers.from === undefined && headers.listId === undefined)) {
16
+ withoutHeaders++;
17
+ continue;
18
+ }
19
+ const key = headers.listId === undefined ? `from:${headers.from}` : `list:${headers.listId}`;
20
+ const group = groups.get(key);
21
+ if (group)
22
+ group.push(item);
23
+ else
24
+ groups.set(key, [item]);
25
+ }
26
+ const all = [...groups.values()].map((group) => {
27
+ const senders = new Set(group.flatMap((item) => (item.headers?.from === undefined ? [] : [item.headers.from])));
28
+ const known = group.filter((item) => item.seen !== undefined);
29
+ const years = group.map((item) => new Date(item.receivedAt).getUTCFullYear());
30
+ const bulk = share(group.filter((item) => item.headers?.bulk).length, group.length);
31
+ const replied = [...senders].some((sender) => recipients.has(sender));
32
+ return {
33
+ from: [...senders][0] ?? null,
34
+ listId: group[0]?.headers?.listId ?? null,
35
+ emails: group.length,
36
+ bytes: group.reduce((sum, item) => sum + (item.size ?? 0), 0),
37
+ unread: known.length ? share(known.filter((item) => !item.seen).length, known.length) : null,
38
+ bulk,
39
+ firstYear: years.reduce((a, b) => Math.min(a, b)),
40
+ lastYear: years.reduce((a, b) => Math.max(a, b)),
41
+ replied,
42
+ suggest: group.length >= 20 && bulk >= 0.8 && !replied ? "skip" : null,
43
+ };
44
+ });
45
+ all.sort((a, b) => b.emails - a.emails || b.bytes - a.bytes);
46
+ return {
47
+ emails: items.length,
48
+ bytes: items.reduce((sum, item) => sum + (item.size ?? 0), 0),
49
+ sent: sent.length,
50
+ withoutHeaders,
51
+ groups: all.length,
52
+ items: all.slice(0, limit),
53
+ };
54
+ };
55
+ //# sourceMappingURL=probe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"probe.js","sourceRoot":"","sources":["../../src/mail/probe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { MailHeaders } from "./headers.js";
2
+ export interface MailRuleMatch {
3
+ from?: string;
4
+ domain?: string;
5
+ listId?: string;
6
+ }
7
+ export interface MailRule {
8
+ match: MailRuleMatch;
9
+ action: "skip" | "keep";
10
+ reason?: string;
11
+ decidedAt: string;
12
+ }
13
+ /** A domain also matches its subdomains: bulk mail often comes from `mail.` or `news.` of the same domain. */
14
+ export declare const matches: (match: MailRuleMatch, headers: MailHeaders) => boolean;
15
+ /** Any matching keep wins over any matching skip, so a keep for one sender overrides a skip of its domain. */
16
+ export declare const decide: (rules: readonly MailRule[], headers: MailHeaders | undefined) => "skip" | "keep" | undefined;
17
+ export declare const sameMatch: (a: MailRuleMatch, b: MailRuleMatch) => boolean;
18
+ //# sourceMappingURL=rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/mail/rules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,aAAa,CAAA;IACpB,MAAM,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CAClB;AAID,8GAA8G;AAC9G,eAAO,MAAM,OAAO,UAAW,aAAa,WAAW,WAAW,KAAG,OAWpE,CAAA;AAED,8GAA8G;AAC9G,eAAO,MAAM,MAAM,UAAW,SAAS,QAAQ,EAAE,WAAW,WAAW,GAAG,SAAS,KAAG,MAAM,GAAG,MAAM,GAAG,SAKvG,CAAA;AAED,eAAO,MAAM,SAAS,MAAO,aAAa,KAAK,aAAa,KAAG,OAGV,CAAA"}
@@ -0,0 +1,26 @@
1
+ const domainOf = (address) => address.slice(address.lastIndexOf("@") + 1);
2
+ /** A domain also matches its subdomains: bulk mail often comes from `mail.` or `news.` of the same domain. */
3
+ export const matches = (match, headers) => {
4
+ const { from, domain, listId } = match;
5
+ if (from === undefined && domain === undefined && listId === undefined)
6
+ return false;
7
+ const sender = headers.from;
8
+ const host = sender === undefined ? undefined : domainOf(sender);
9
+ const wanted = domain?.toLowerCase();
10
+ return ((from === undefined || sender === from.toLowerCase()) &&
11
+ (wanted === undefined || (host !== undefined && (host === wanted || host.endsWith(`.${wanted}`)))) &&
12
+ (listId === undefined || headers.listId === listId.toLowerCase()));
13
+ };
14
+ /** Any matching keep wins over any matching skip, so a keep for one sender overrides a skip of its domain. */
15
+ export const decide = (rules, headers) => {
16
+ if (headers === undefined)
17
+ return undefined;
18
+ const hits = rules.filter((rule) => matches(rule.match, headers));
19
+ if (hits.some(({ action }) => action === "keep"))
20
+ return "keep";
21
+ return hits.length ? "skip" : undefined;
22
+ };
23
+ export const sameMatch = (a, b) => a.from?.toLowerCase() === b.from?.toLowerCase() &&
24
+ a.domain?.toLowerCase() === b.domain?.toLowerCase() &&
25
+ a.listId?.toLowerCase() === b.listId?.toLowerCase();
26
+ //# sourceMappingURL=rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/mail/rules.ts"],"names":[],"mappings":"AAeA,MAAM,QAAQ,GAAG,CAAC,OAAe,EAAU,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;AAEzF,8GAA8G;AAC9G,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,KAAoB,EAAE,OAAoB,EAAW,EAAE;IAC7E,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAA;IACtC,IAAI,IAAI,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,KAAK,CAAA;IACpF,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAA;IAC3B,MAAM,IAAI,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IAChE,MAAM,MAAM,GAAG,MAAM,EAAE,WAAW,EAAE,CAAA;IACpC,OAAO,CACL,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;QACrD,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;QAClG,CAAC,MAAM,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,CAAC,WAAW,EAAE,CAAC,CAClE,CAAA;AACH,CAAC,CAAA;AAED,8GAA8G;AAC9G,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,KAA0B,EAAE,OAAgC,EAA+B,EAAE;IAClH,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IAC3C,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAA;IACjE,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,KAAK,MAAM,CAAC;QAAE,OAAO,MAAM,CAAA;IAC/D,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAA;AACzC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,CAAgB,EAAE,CAAgB,EAAW,EAAE,CACvE,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE;IAC/C,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE;IACnD,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,CAAA"}
@@ -0,0 +1,20 @@
1
+ import { type Listed } from "./gmail.js";
2
+ import type { Himalaya } from "./himalaya.js";
3
+ export type { Listed };
4
+ /** Everything the import asks of a mail client, so himalaya can be replaced without touching the import. */
5
+ export interface MailSource {
6
+ /**
7
+ * Every message in `folder` received since `since`; all or nothing, since deletions are proved from it.
8
+ * `headers` also reads From, To, Cc and the list fields, for the probe and the owner's rules.
9
+ */
10
+ list(since: Date, folder: string, options?: {
11
+ headers?: boolean;
12
+ }): Promise<Listed[]>;
13
+ /** Each item's raw RFC 5322 bytes, in order; one that could not be read is an Error, not a failed call. */
14
+ fetchRaw(items: Listed[]): Promise<(Uint8Array | Error)[]>;
15
+ }
16
+ export declare const himalayaSource: (run: Himalaya, account: {
17
+ name: string;
18
+ mode?: "gmail" | "imap" | "mbox";
19
+ }) => MailSource;
20
+ //# sourceMappingURL=source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../src/mail/source.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAA6B,MAAM,YAAY,CAAA;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAE7C,YAAY,EAAE,MAAM,EAAE,CAAA;AAEtB,4GAA4G;AAC5G,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IACrF,2GAA2G;IAC3G,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,UAAU,GAAG,KAAK,CAAC,EAAE,CAAC,CAAA;CAC3D;AAiCD,eAAO,MAAM,cAAc,QACpB,QAAQ,WACJ;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAA;CAAE,KAC1D,UA8DF,CAAA"}