plaud-notes-to-notion 1.0.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 (91) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/LICENSE +21 -0
  3. package/README.md +102 -0
  4. package/bin/plaud-notes-to-notion.js +16 -0
  5. package/dist/card.d.ts +30 -0
  6. package/dist/card.js +287 -0
  7. package/dist/card.js.map +1 -0
  8. package/dist/cli.d.ts +1 -0
  9. package/dist/cli.js +266 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/config.d.ts +41 -0
  12. package/dist/config.js +85 -0
  13. package/dist/config.js.map +1 -0
  14. package/dist/constants.d.ts +52 -0
  15. package/dist/constants.js +53 -0
  16. package/dist/constants.js.map +1 -0
  17. package/dist/daemon.d.ts +13 -0
  18. package/dist/daemon.js +182 -0
  19. package/dist/daemon.js.map +1 -0
  20. package/dist/format.d.ts +36 -0
  21. package/dist/format.js +108 -0
  22. package/dist/format.js.map +1 -0
  23. package/dist/ingest.d.ts +49 -0
  24. package/dist/ingest.js +205 -0
  25. package/dist/ingest.js.map +1 -0
  26. package/dist/llm.d.ts +65 -0
  27. package/dist/llm.js +177 -0
  28. package/dist/llm.js.map +1 -0
  29. package/dist/lock.d.ts +26 -0
  30. package/dist/lock.js +134 -0
  31. package/dist/lock.js.map +1 -0
  32. package/dist/log.d.ts +14 -0
  33. package/dist/log.js +41 -0
  34. package/dist/log.js.map +1 -0
  35. package/dist/notion.d.ts +86 -0
  36. package/dist/notion.js +254 -0
  37. package/dist/notion.js.map +1 -0
  38. package/dist/paths.d.ts +11 -0
  39. package/dist/paths.js +51 -0
  40. package/dist/paths.js.map +1 -0
  41. package/dist/plaud/callback.d.ts +19 -0
  42. package/dist/plaud/callback.js +162 -0
  43. package/dist/plaud/callback.js.map +1 -0
  44. package/dist/plaud/client.d.ts +55 -0
  45. package/dist/plaud/client.js +246 -0
  46. package/dist/plaud/client.js.map +1 -0
  47. package/dist/plaud/constants.d.ts +18 -0
  48. package/dist/plaud/constants.js +19 -0
  49. package/dist/plaud/constants.js.map +1 -0
  50. package/dist/plaud/errors.d.ts +10 -0
  51. package/dist/plaud/errors.js +32 -0
  52. package/dist/plaud/errors.js.map +1 -0
  53. package/dist/plaud/login.d.ts +17 -0
  54. package/dist/plaud/login.js +89 -0
  55. package/dist/plaud/login.js.map +1 -0
  56. package/dist/plaud/oauth.d.ts +21 -0
  57. package/dist/plaud/oauth.js +197 -0
  58. package/dist/plaud/oauth.js.map +1 -0
  59. package/dist/plaud/pkce.d.ts +3 -0
  60. package/dist/plaud/pkce.js +11 -0
  61. package/dist/plaud/pkce.js.map +1 -0
  62. package/dist/plaud/session.d.ts +23 -0
  63. package/dist/plaud/session.js +77 -0
  64. package/dist/plaud/session.js.map +1 -0
  65. package/dist/plaud/types.d.ts +21 -0
  66. package/dist/plaud/types.js +2 -0
  67. package/dist/plaud/types.js.map +1 -0
  68. package/dist/redact.d.ts +3 -0
  69. package/dist/redact.js +37 -0
  70. package/dist/redact.js.map +1 -0
  71. package/dist/runtime.d.ts +44 -0
  72. package/dist/runtime.js +94 -0
  73. package/dist/runtime.js.map +1 -0
  74. package/dist/scrub.d.ts +17 -0
  75. package/dist/scrub.js +124 -0
  76. package/dist/scrub.js.map +1 -0
  77. package/dist/secrets.d.ts +59 -0
  78. package/dist/secrets.js +220 -0
  79. package/dist/secrets.js.map +1 -0
  80. package/dist/ssn.d.ts +33 -0
  81. package/dist/ssn.js +170 -0
  82. package/dist/ssn.js.map +1 -0
  83. package/dist/state.d.ts +46 -0
  84. package/dist/state.js +23 -0
  85. package/dist/state.js.map +1 -0
  86. package/dist/sync.d.ts +60 -0
  87. package/dist/sync.js +190 -0
  88. package/dist/sync.js.map +1 -0
  89. package/examples/com.plaud-notes-to-notion.plist +34 -0
  90. package/examples/install-launchagent.sh +16 -0
  91. package/package.json +37 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ ## 1.0.0
4
+
5
+ First public release.
6
+
7
+ Polls Plaud and writes Summary and Transcript rows into a Plaud Notes Notion
8
+ database, with SSN and card redaction, participant labeling, and
9
+ Summary→Transcript title/participant sync. Secrets stay in Keychain (macOS)
10
+ or a local file store (Linux); config lives under `~/.plaud-notes-to-notion/`.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Peter Coates
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the Software), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # Plaud Notes to Notion
2
+
3
+ Mac Mini **LaunchAgent** that replaces the two Zapier Zaps
4
+ (*Peter / Tim: Plaud → Notion: Transcript + Summary*). When Plaud finishes a
5
+ recording's summary, it writes two rows into that person's **Plaud Notes**
6
+ Notion database — one `Summary`, one `Transcript` — structured exactly like the
7
+ Zap's rows. Every 5 minutes it also copies **Summary** title/participant edits
8
+ onto the matching **Transcript** row.
9
+
10
+ No Zapier, no extra runtime dependencies (Node ≥ 20 built-ins only).
11
+
12
+ ## What it does (per profile)
13
+
14
+ | Step | Zap step it replaces | Notes |
15
+ | --- | --- | --- |
16
+ | Poll Plaud every **30 s** (deep 30-day scan every 10 min) | 1. Plaud *Transcript & Summary Ready* | Writes only once Plaud has **both** the auto summary and the transcript. Zapier took ~1–2 min. |
17
+ | `Recorded` = recording start, to the minute, true UTC | 2. Date/Time `+5 hours` | The Zap's +5h hid Plaud's Central-time-labelled-UTC bug and would be **1 h off after DST ends**. |
18
+ | **SSN redaction** (summary, transcript, title) | — (new) | Written *and* spoken digits, incl. answers in the next speaker's line. Runs before anything leaves the Mac. |
19
+ | **Card redaction** (summary, transcript, title) | — (new) | Credit/debit card numbers (full, or partial: "ending in", "begins with", "last four of the card", "the 4417 card"), security code (CVV/CVC) and expiration date. Written or spoken; runs before SSN redaction so a card's last four is never labelled an SSN. A full number or 4-digit partial found anywhere in a recording is removed everywhere in it. |
20
+ | Remove `PLAUD NOTE`; pair quotes `“…”` | 3–4. Formatter Text | The Zap turned every `"` into `”`. |
21
+ | Strip Plaud image embeds, `---`, blank lines; split `> **Label:** text` | 5. Code (JavaScript) | Ported verbatim. |
22
+ | Participants via **Claude Haiku 4.5** (default) or **GPT-6 Luna, high effort**, schema-checked JSON | 6. AI by Zapier | Also sees the transcript (names often only appear there) and the database's existing Participant spellings (e.g. `Casey - Bank`). Owner and `Speaker N` labels never listed. |
23
+ | Create **Summary** row (Notion markdown API) | 7. Notion | Block-for-block identical to the Zap's output. |
24
+ | Create **Transcript** row (one plain-text paragraph) | 8. Notion | Exact text — `*`, `_`, `#` in speech can never turn into formatting. |
25
+ | Summary → Transcript sync every **5 min** | Grok *Sync Plaud Transcripts to Summaries* (retired) | Pair by `Recorded` minute; skip ambiguous minutes; full 90-day reconcile daily. |
26
+
27
+ Reliability: per-file state (`~/.plaud-notes-to-notion/state/<profile>.json`) so a
28
+ crash never duplicates or loses a row; labeling retried 6× then falls back to
29
+ Plaud's own title; recordings still generating are re-checked every poll (up to
30
+ 48 h); expired sign-ins raise a macOS notification (at most every 6 h).
31
+
32
+ ## Profiles
33
+
34
+ `~/.plaud-notes-to-notion/config.json` — profiles differ only in *who* and *where*:
35
+
36
+ ```json
37
+ {
38
+ "pollSeconds": 30,
39
+ "syncSeconds": 300,
40
+ "llmModel": "claude-haiku-4-5",
41
+ "profiles": {
42
+ "peter": { "enabled": true, "owner": "Peter", "notionDataSourceId": "<Plaud Notes data source id>", "startAfter": "<cutover ISO time>" },
43
+ "tim": { "enabled": false, "owner": "Tim", "notionDataSourceId": "<Tim's Plaud Notes data source id>", "startAfter": "<cutover ISO time>" }
44
+ }
45
+ }
46
+ ```
47
+
48
+ - `startAfter` — only recordings **uploaded** after this instant are ingested. Set it to the moment the Zap is turned off so nothing is written twice.
49
+ - `ingest` / `syncTranscripts` (default `true`) — switch either half off.
50
+ - `credentials` — use another profile's Keychain secrets (e.g. a test profile that writes to a test database with Peter's sign-in).
51
+ - The daemon re-reads the file when it changes; turning a profile on needs no restart.
52
+
53
+ ### LLM (participant labeling)
54
+
55
+ `llmModel` picks the provider: `claude-*` → Anthropic Messages API (key
56
+ `anthropic`), anything else → OpenAI Responses API (key `openai`). Default is
57
+ `claude-haiku-4-5`.
58
+
59
+ | Want | `config.json` | Key needed |
60
+ | --- | --- | --- |
61
+ | Claude Haiku (default) | omit `llmModel`, or `"llmModel": "claude-haiku-4-5"` | `set-secret anthropic` |
62
+ | Back to GPT-6 Luna | `"llmModel": "gpt-6-luna", "llmEffort": "high"` | `set-secret openai` |
63
+
64
+ `llmEffort` only applies to OpenAI. The daemon picks up an `llmModel` change on
65
+ its next loop (no restart). If the selected model's key is missing, that
66
+ profile pauses (no ingest or sync) until the key is saved — run
67
+ `doctor` first; it names the `set-secret` command.
68
+
69
+ ## Setup (on the Mini, logged-in GUI session)
70
+
71
+ ```bash
72
+ npm install -g plaud-notes-to-notion # or build from a checkout: npm ci && npm run build
73
+ plaud-notes-to-notion login --profile peter # opens Plaud → sign in as that person → Authorize
74
+ plaud-notes-to-notion set-secret notion --profile peter # Notion internal integration secret (paste, hidden)
75
+ plaud-notes-to-notion set-secret anthropic # Anthropic API key (shared; Haiku, the default)
76
+ plaud-notes-to-notion set-secret openai # OpenAI API key (shared; only if llmModel is gpt-*)
77
+ plaud-notes-to-notion doctor --profile peter
78
+ sh "$(npm root -g)/plaud-notes-to-notion/examples/install-launchagent.sh"
79
+ ```
80
+
81
+ The Notion integration needs **Read / Update / Insert** on that person's Plaud
82
+ Notes database (••• → Connections). Secrets live only in Keychain service
83
+ `plaud-notes-to-notion` (accounts `plaud:<profile>`, `notion:<profile>`, `anthropic`, `openai`; a
84
+ profile-specific `anthropic:<profile>` / `openai:<profile>` wins over the shared one).
85
+
86
+ ## Everyday commands
87
+
88
+ ```bash
89
+ plaud-notes-to-notion status # last poll / sync / write per profile
90
+ plaud-notes-to-notion once --profile peter --dry-run # show what would be written, write nothing
91
+ plaud-notes-to-notion sync --profile peter --dry-run # show Transcript fixes, change nothing
92
+ tail -f ~/Library/Logs/plaud-notes-to-notion.log
93
+ ```
94
+
95
+ ## Development
96
+
97
+ ```bash
98
+ npm ci
99
+ npm test && npm run typecheck && npm run build
100
+ ```
101
+
102
+ Tests use made-up SSNs and card numbers only. Never commit tokens, real transcripts or database ids.
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * npm bin entry. Always invokes main — do not rely on dist/cli.js detecting a
4
+ * symlinked argv[1] (that check silently exited 0 on the Mini for EdgeCore).
5
+ */
6
+ import { main } from "../dist/cli.js";
7
+
8
+ main()
9
+ .then((code) => {
10
+ process.exit(code);
11
+ })
12
+ .catch((err) => {
13
+ const message = err instanceof Error && err.message ? err.message : String(err);
14
+ process.stderr.write(`${message}\n`);
15
+ process.exit(1);
16
+ });
package/dist/card.d.ts ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Credit / debit card redaction for Plaud summaries and transcripts.
3
+ *
4
+ * Runs on raw Plaud text before anything leaves the Mini, next to SSN redaction.
5
+ * Removes full card numbers (written or spoken, also when the transcription
6
+ * dropped or added a digit), partial numbers ("ending in 4417", "Visa that
7
+ * begins with 4111", "last four of the card"), the security code (CVV / CVC)
8
+ * and the expiration date. Full numbers and 4-digit partials found anywhere in
9
+ * a recording are removed everywhere in it.
10
+ */
11
+ export declare const CARD_NUMBER_REPLACEMENT = "[card number redacted]";
12
+ export declare const CARD_CODE_REPLACEMENT = "[card code redacted]";
13
+ export declare const CARD_EXPIRY_REPLACEMENT = "[card expiration redacted]";
14
+ export declare function cardDigits(run: string): string;
15
+ export declare function luhn(digits: string): boolean;
16
+ /** Card values to remove everywhere in a recording: full numbers, their last four, and 4-digit partials. */
17
+ export declare function findCardDigits(texts: string[]): Set<string>;
18
+ /** Replace every card detail in this text, plus any number run matching a value found elsewhere in the recording. */
19
+ export declare function redactCards(text: string, cardValues: Set<string>): {
20
+ text: string;
21
+ count: number;
22
+ };
23
+ /**
24
+ * Redact card details across every text of one recording. Values found in one
25
+ * text (e.g. the transcript) are also removed from the others (e.g. the summary).
26
+ */
27
+ export declare function redactCardsAcross<T extends Record<string, string>>(texts: T): {
28
+ texts: T;
29
+ count: number;
30
+ };
package/dist/card.js ADDED
@@ -0,0 +1,287 @@
1
+ /**
2
+ * Credit / debit card redaction for Plaud summaries and transcripts.
3
+ *
4
+ * Runs on raw Plaud text before anything leaves the Mini, next to SSN redaction.
5
+ * Removes full card numbers (written or spoken, also when the transcription
6
+ * dropped or added a digit), partial numbers ("ending in 4417", "Visa that
7
+ * begins with 4111", "last four of the card"), the security code (CVV / CVC)
8
+ * and the expiration date. Full numbers and 4-digit partials found anywhere in
9
+ * a recording are removed everywhere in it.
10
+ */
11
+ import { DIGIT_WORDS, isYearInDate, protectedRanges } from "./ssn.js";
12
+ export const CARD_NUMBER_REPLACEMENT = "[card number redacted]";
13
+ export const CARD_CODE_REPLACEMENT = "[card code redacted]";
14
+ export const CARD_EXPIRY_REPLACEMENT = "[card expiration redacted]";
15
+ const UNIT = "(?:zero|oh|one|two|three|four|five|six|seven|eight|nine)";
16
+ const UNIT_NZ = "(?:one|two|three|four|five|six|seven|eight|nine)";
17
+ const TEEN = "(?:ten|eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen)";
18
+ const TENS = "(?:twenty|thirty|forty|fifty|sixty|seventy|eighty|ninety)";
19
+ const TOKEN = `(?:\\d+|(?:double|triple)[ -]${UNIT}|${TENS}(?:[ -]${UNIT_NZ})?|${TEEN}|${UNIT})`;
20
+ const SEP = "[ \\t,.\\-\\u2013\\u2014/]*";
21
+ /** A run of written or spoken digits on one line ("4111 1111", "forty one eleven", "double four"). */
22
+ const NUMBER_RUN = new RegExp(`(?<![\\w])${TOKEN}(?:${SEP}${TOKEN})*(?![\\w])`, "gi");
23
+ const TEEN_VALUES = {
24
+ ten: "10",
25
+ eleven: "11",
26
+ twelve: "12",
27
+ thirteen: "13",
28
+ fourteen: "14",
29
+ fifteen: "15",
30
+ sixteen: "16",
31
+ seventeen: "17",
32
+ eighteen: "18",
33
+ nineteen: "19"
34
+ };
35
+ const TENS_VALUES = {
36
+ twenty: "2",
37
+ thirty: "3",
38
+ forty: "4",
39
+ fifty: "5",
40
+ sixty: "6",
41
+ seventy: "7",
42
+ eighty: "8",
43
+ ninety: "9"
44
+ };
45
+ /** Words that put a number in card territory. */
46
+ const CARD_WORD = /\b(?:card|visa|master\s?card|amex|american\s+express|discover|debit|credit)\b/gi;
47
+ /** "ending in", "ends with", "begins in", "starting with" — a partial number follows. */
48
+ const PARTIAL_TRIGGER = /\b(?:end(?:s|ing|ed)?|begin(?:s|ning)?|start(?:s|ing)?)(?:\s+(?:in|with))?\b/gi;
49
+ /** "last four (digits) of the/your card" — the answer may land in the next utterance. */
50
+ const LAST_FOUR_TRIGGER = /\blast\s+(?:four|4)(?:\s+(?:digits|numbers))?(?=[^.?!\n]{0,40}\bcard\b)/gi;
51
+ /** A 4-digit run naming a card: "the 4417 card", "my 4417 Visa". */
52
+ const CARD_AFTER = /^[\s`'"“”‘’)]*(?:(?:visa|master\s?card|amex|credit|debit|signature|rewards)\s+)*(?:card|visa|master\s?card|amex)\b/i;
53
+ const CODE_TRIGGER = /\b(?:cvv2?|cvc2?|cid|security\s+code|three[- ]digit\s+code|(?:code|digits|numbers)\s+on\s+the\s+back)\b/gi;
54
+ const EXPIRY_TRIGGER = /\b(?:expiration(?:\s+date)?|expiry(?:\s+date)?|exp\.?(?:\s+date)?|expires?|expir(?:ed|ing)|valid\s+(?:thru|through))(?![\w])/gi;
55
+ const MONTH = "(?:jan(?:uary)?|feb(?:ruary)?|mar(?:ch)?|apr(?:il)?|may|june?|july?|aug(?:ust)?|sep(?:t(?:ember)?)?|oct(?:ober)?|nov(?:ember)?|dec(?:ember)?)";
56
+ /** "30 days", "500 dollars", "5 percent" — an amount, not part of a card. */
57
+ const UNIT_AFTER = /^\s*(?:%|percent|dollars?|bucks|cents?|days?|weeks?|months?|years?|hours?|minutes?)\b/i;
58
+ const ORDINAL_AFTER = /^(?:st|nd|rd|th)\b|^[ \t-]*(?:first|second|third|fourth|fifth|sixth|seventh|eighth|ninth|tenth|eleventh|twelfth|\w+teenth|\w+tieth)\b/i;
59
+ /** Lookahead window after a trigger, long enough to cross into the next utterance. */
60
+ const WINDOW_CHARS = 320;
61
+ const CONTEXT_BEFORE = 200;
62
+ const CONTEXT_AFTER = 80;
63
+ const REPLACEMENT = {
64
+ number: CARD_NUMBER_REPLACEMENT,
65
+ code: CARD_CODE_REPLACEMENT,
66
+ expiry: CARD_EXPIRY_REPLACEMENT
67
+ };
68
+ export function cardDigits(run) {
69
+ let out = "";
70
+ const re = new RegExp(`\\d+|(double|triple)[ -](${UNIT})|(${TENS})(?:[ -](${UNIT_NZ}))?|${TEEN}|${UNIT}`, "gi");
71
+ let m;
72
+ while ((m = re.exec(run))) {
73
+ const word = m[0].toLowerCase();
74
+ if (/^\d+$/.test(word)) {
75
+ out += word;
76
+ }
77
+ else if (m[1]) {
78
+ out += DIGIT_WORDS[m[2].toLowerCase()].repeat(m[1].toLowerCase() === "double" ? 2 : 3);
79
+ }
80
+ else if (m[3]) {
81
+ out += TENS_VALUES[m[3].toLowerCase()] + (m[4] ? DIGIT_WORDS[m[4].toLowerCase()] : "0");
82
+ }
83
+ else {
84
+ out += TEEN_VALUES[word] ?? DIGIT_WORDS[word];
85
+ }
86
+ }
87
+ return out;
88
+ }
89
+ export function luhn(digits) {
90
+ let sum = 0;
91
+ for (let i = 0; i < digits.length; i++) {
92
+ let d = Number(digits[digits.length - 1 - i]);
93
+ if (i % 2 === 1) {
94
+ d *= 2;
95
+ if (d > 9) {
96
+ d -= 9;
97
+ }
98
+ }
99
+ sum += d;
100
+ }
101
+ return sum % 10 === 0;
102
+ }
103
+ function numberRuns(text) {
104
+ const guarded = protectedRanges(text);
105
+ const runs = [];
106
+ NUMBER_RUN.lastIndex = 0;
107
+ let m;
108
+ while ((m = NUMBER_RUN.exec(text))) {
109
+ const start = m.index;
110
+ const end = start + m[0].replace(/[ \t,.\-–—/]+$/, "").length;
111
+ if (guarded.some(([a, b]) => start < b && end > a)) {
112
+ continue;
113
+ }
114
+ const digits = cardDigits(text.slice(start, end));
115
+ if (digits) {
116
+ runs.push({ start, end, digits });
117
+ }
118
+ }
119
+ return runs;
120
+ }
121
+ function matchesOf(text, re) {
122
+ return [...text.matchAll(re)].map((m) => ({ start: m.index, end: m.index + m[0].length }));
123
+ }
124
+ function hasCardContext(text, start, end) {
125
+ return new RegExp(CARD_WORD.source, "i").test(text.slice(Math.max(0, start - CONTEXT_BEFORE), end + CONTEXT_AFTER));
126
+ }
127
+ /** Written card shapes: 4-4-4-4 (or a truncated last group) and Amex 4-6-5. */
128
+ function looksLikeCardShape(raw) {
129
+ return /^\d{4}([ -])\d{4}\1\d{4}(?:\1\d{1,7})?$/.test(raw) || /^\d{4}([ -])\d{6}\1\d{5}$/.test(raw);
130
+ }
131
+ function isAmount(text, run) {
132
+ return text[run.start - 1] === "$" || UNIT_AFTER.test(text.slice(run.end, run.end + 12));
133
+ }
134
+ function isFullNumber(digits) {
135
+ return digits.length >= 12 && digits.length <= 19;
136
+ }
137
+ function numberHit(run) {
138
+ return { start: run.start, end: run.end, kind: "number", spread: run.digits };
139
+ }
140
+ /** A month/year expiration right after the trigger; never a full date with a day. */
141
+ function expiryAfter(text, at, runs) {
142
+ const tail = text.slice(at, at + 120);
143
+ const candidates = [];
144
+ const written = /^[^\d\n]{0,40}?\b(?:0?[1-9]|1[0-2])\s?[/-]\s?(?:\d{4}|\d{2})\b(?!\s?[/-]\s?\d)/.exec(tail);
145
+ if (written) {
146
+ const lead = /^[^\d\n]*/.exec(written[0])[0].length;
147
+ candidates.push({ start: at + lead, end: at + written[0].length, kind: "expiry" });
148
+ }
149
+ const month = new RegExp(`^[^\\n]{0,40}?\\b(${MONTH})\\.?,?(?:\\s+of)?\\s+`, "i").exec(tail);
150
+ if (month) {
151
+ const yearStart = at + month[0].length;
152
+ const run = runs.find((r) => r.start === yearStart);
153
+ if (run && (run.digits.length === 2 || run.digits.length === 4)) {
154
+ const after = text.slice(run.end, run.end + 30);
155
+ const hasDay = ORDINAL_AFTER.test(after) || /^\s*,?\s*(?:of\s+)?(?:\d|(?:twenty|nineteen|two thousand)\b)/i.test(after);
156
+ if (!hasDay) {
157
+ candidates.push({ start: at + month[0].search(new RegExp(`\\b${MONTH}`, "i")), end: run.end, kind: "expiry" });
158
+ }
159
+ }
160
+ }
161
+ const bare = runs.find((r) => r.start >= at && r.start <= at + 40);
162
+ if (bare) {
163
+ const d = bare.digits;
164
+ const mm = d.length === 3 ? Number(d.slice(0, 1)) : Number(d.slice(0, 2));
165
+ if ([3, 4, 6].includes(d.length) && mm >= 1 && mm <= 12 && !ORDINAL_AFTER.test(text.slice(bare.end, bare.end + 30))) {
166
+ candidates.push({ start: bare.start, end: bare.end, kind: "expiry" });
167
+ }
168
+ }
169
+ return candidates.sort((a, b) => a.start - b.start)[0];
170
+ }
171
+ /** Every card detail this one text points at by itself. */
172
+ function scan(text) {
173
+ const runs = numberRuns(text);
174
+ const hits = [];
175
+ for (const run of runs) {
176
+ const raw = text.slice(run.start, run.end);
177
+ if ((isFullNumber(run.digits) && run.digits.length >= 13 && luhn(run.digits)) || looksLikeCardShape(raw)) {
178
+ hits.push(numberHit(run));
179
+ }
180
+ }
181
+ for (const t of matchesOf(text, CARD_WORD)) {
182
+ for (const run of runs) {
183
+ if (run.start >= t.end && run.start <= t.end + WINDOW_CHARS && isFullNumber(run.digits)) {
184
+ hits.push(numberHit(run));
185
+ }
186
+ }
187
+ }
188
+ for (const t of matchesOf(text, PARTIAL_TRIGGER)) {
189
+ const run = runs.find((r) => r.start >= t.end && r.start <= t.end + 30);
190
+ if (!run || run.digits.length < 2 || run.digits.length > 6 || isAmount(text, run) || !hasCardContext(text, t.start, t.end)) {
191
+ continue;
192
+ }
193
+ if (!/^[\s,:;`'"“”‘’(]*(?:(?:in|with|um|uh|number|digits|is|the)\b[\s,:;`'"“”‘’(]*)*$/i.test(text.slice(t.end, run.start))) {
194
+ continue;
195
+ }
196
+ hits.push({ start: run.start, end: run.end, kind: "number", spread: run.digits.length === 4 && !isYearInDate(text, run) ? run.digits : undefined });
197
+ }
198
+ // "this card is the 4417 card", "my 4417 Visa"
199
+ for (const run of runs) {
200
+ if (run.digits.length === 4 && !isYearInDate(text, run) && !isAmount(text, run) && CARD_AFTER.test(text.slice(run.end, run.end + 30))) {
201
+ hits.push(numberHit(run));
202
+ }
203
+ }
204
+ for (const t of matchesOf(text, LAST_FOUR_TRIGGER)) {
205
+ const run = runs.find((r) => r.start >= t.end && r.start <= t.end + WINDOW_CHARS && r.digits.length === 4 && !isYearInDate(text, r));
206
+ if (run) {
207
+ hits.push(numberHit(run));
208
+ }
209
+ }
210
+ for (const t of matchesOf(text, CODE_TRIGGER)) {
211
+ const run = runs.find((r) => r.start >= t.end && r.start <= t.end + 160 && (r.digits.length === 3 || r.digits.length === 4) && !isAmount(text, r));
212
+ if (run) {
213
+ hits.push({ start: run.start, end: run.end, kind: "code" });
214
+ }
215
+ }
216
+ for (const t of matchesOf(text, EXPIRY_TRIGGER)) {
217
+ if (!hasCardContext(text, t.start, t.end)) {
218
+ continue;
219
+ }
220
+ const hit = expiryAfter(text, t.end, runs);
221
+ if (hit) {
222
+ hits.push(hit);
223
+ }
224
+ }
225
+ return hits;
226
+ }
227
+ /** Card values to remove everywhere in a recording: full numbers, their last four, and 4-digit partials. */
228
+ export function findCardDigits(texts) {
229
+ const found = new Set();
230
+ for (const text of texts) {
231
+ for (const hit of scan(text)) {
232
+ if (hit.spread) {
233
+ found.add(hit.spread);
234
+ if (isFullNumber(hit.spread)) {
235
+ found.add(hit.spread.slice(-4));
236
+ }
237
+ }
238
+ }
239
+ }
240
+ return found;
241
+ }
242
+ /** Replace every card detail in this text, plus any number run matching a value found elsewhere in the recording. */
243
+ export function redactCards(text, cardValues) {
244
+ const hits = scan(text);
245
+ if (cardValues.size) {
246
+ for (const run of numberRuns(text)) {
247
+ const known = (cardValues.has(run.digits) && (run.digits.length !== 4 || !isYearInDate(text, run))) ||
248
+ [...cardValues].some((d) => isFullNumber(d) && run.digits.includes(d));
249
+ if (known) {
250
+ hits.push(numberHit(run));
251
+ }
252
+ }
253
+ }
254
+ if (!hits.length) {
255
+ return { text, count: 0 };
256
+ }
257
+ hits.sort((a, b) => a.start - b.start || b.end - a.end);
258
+ let out = "";
259
+ let cursor = 0;
260
+ let count = 0;
261
+ for (const h of hits) {
262
+ if (h.start < cursor) {
263
+ continue;
264
+ }
265
+ out += text.slice(cursor, h.start) + REPLACEMENT[h.kind];
266
+ cursor = h.end;
267
+ count++;
268
+ }
269
+ out += text.slice(cursor);
270
+ return { text: out, count };
271
+ }
272
+ /**
273
+ * Redact card details across every text of one recording. Values found in one
274
+ * text (e.g. the transcript) are also removed from the others (e.g. the summary).
275
+ */
276
+ export function redactCardsAcross(texts) {
277
+ const found = findCardDigits(Object.values(texts));
278
+ let count = 0;
279
+ const out = {};
280
+ for (const [key, value] of Object.entries(texts)) {
281
+ const r = redactCards(value, found);
282
+ out[key] = r.text;
283
+ count += r.count;
284
+ }
285
+ return { texts: out, count };
286
+ }
287
+ //# sourceMappingURL=card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card.js","sourceRoot":"","sources":["../src/card.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function main(argv?: string[]): Promise<number>;