@sjawhar/whatsapp-mcp 2.0.0 → 2.2.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 (114) hide show
  1. package/dist/db.d.ts +28 -1
  2. package/dist/db.d.ts.map +1 -1
  3. package/dist/db.js +153 -30
  4. package/dist/db.js.map +1 -1
  5. package/dist/http-server.d.ts +8 -0
  6. package/dist/http-server.d.ts.map +1 -0
  7. package/dist/http-server.js +198 -0
  8. package/dist/http-server.js.map +1 -0
  9. package/dist/import-contacts.d.ts +6 -3
  10. package/dist/import-contacts.d.ts.map +1 -1
  11. package/dist/import-contacts.js +28 -14
  12. package/dist/import-contacts.js.map +1 -1
  13. package/dist/index.js +192 -26
  14. package/dist/index.js.map +1 -1
  15. package/dist/resources.d.ts +16 -0
  16. package/dist/resources.d.ts.map +1 -0
  17. package/dist/resources.js +84 -0
  18. package/dist/resources.js.map +1 -0
  19. package/dist/tools.d.ts.map +1 -1
  20. package/dist/tools.js +38 -15
  21. package/dist/tools.js.map +1 -1
  22. package/dist/whatsapp.d.ts +13 -1
  23. package/dist/whatsapp.d.ts.map +1 -1
  24. package/dist/whatsapp.js +167 -31
  25. package/dist/whatsapp.js.map +1 -1
  26. package/package.json +5 -1
  27. package/dist/__tests__/connection.test.d.ts +0 -2
  28. package/dist/__tests__/connection.test.d.ts.map +0 -1
  29. package/dist/__tests__/connection.test.js +0 -105
  30. package/dist/__tests__/connection.test.js.map +0 -1
  31. package/dist/__tests__/disconnect.test.d.ts +0 -2
  32. package/dist/__tests__/disconnect.test.d.ts.map +0 -1
  33. package/dist/__tests__/disconnect.test.js +0 -166
  34. package/dist/__tests__/disconnect.test.js.map +0 -1
  35. package/dist/__tests__/download-media.test.d.ts +0 -2
  36. package/dist/__tests__/download-media.test.d.ts.map +0 -1
  37. package/dist/__tests__/download-media.test.js +0 -110
  38. package/dist/__tests__/download-media.test.js.map +0 -1
  39. package/dist/__tests__/failures/connection-failures.test.d.ts +0 -2
  40. package/dist/__tests__/failures/connection-failures.test.d.ts.map +0 -1
  41. package/dist/__tests__/failures/connection-failures.test.js +0 -146
  42. package/dist/__tests__/failures/connection-failures.test.js.map +0 -1
  43. package/dist/__tests__/failures/edge-cases.test.d.ts +0 -2
  44. package/dist/__tests__/failures/edge-cases.test.d.ts.map +0 -1
  45. package/dist/__tests__/failures/edge-cases.test.js +0 -121
  46. package/dist/__tests__/failures/edge-cases.test.js.map +0 -1
  47. package/dist/__tests__/failures/resource-failures.test.d.ts +0 -2
  48. package/dist/__tests__/failures/resource-failures.test.d.ts.map +0 -1
  49. package/dist/__tests__/failures/resource-failures.test.js +0 -136
  50. package/dist/__tests__/failures/resource-failures.test.js.map +0 -1
  51. package/dist/__tests__/failures/security-failures.test.d.ts +0 -2
  52. package/dist/__tests__/failures/security-failures.test.d.ts.map +0 -1
  53. package/dist/__tests__/failures/security-failures.test.js +0 -0
  54. package/dist/__tests__/failures/security-failures.test.js.map +0 -1
  55. package/dist/__tests__/helpers/fake-baileys.d.ts +0 -52
  56. package/dist/__tests__/helpers/fake-baileys.d.ts.map +0 -1
  57. package/dist/__tests__/helpers/fake-baileys.js +0 -60
  58. package/dist/__tests__/helpers/fake-baileys.js.map +0 -1
  59. package/dist/__tests__/helpers/mcp-test-client.d.ts +0 -9
  60. package/dist/__tests__/helpers/mcp-test-client.d.ts.map +0 -1
  61. package/dist/__tests__/helpers/mcp-test-client.js +0 -40
  62. package/dist/__tests__/helpers/mcp-test-client.js.map +0 -1
  63. package/dist/__tests__/helpers/test-db.d.ts +0 -4
  64. package/dist/__tests__/helpers/test-db.d.ts.map +0 -1
  65. package/dist/__tests__/helpers/test-db.js +0 -32
  66. package/dist/__tests__/helpers/test-db.js.map +0 -1
  67. package/dist/__tests__/integration/chat-navigation.test.d.ts +0 -2
  68. package/dist/__tests__/integration/chat-navigation.test.d.ts.map +0 -1
  69. package/dist/__tests__/integration/chat-navigation.test.js +0 -171
  70. package/dist/__tests__/integration/chat-navigation.test.js.map +0 -1
  71. package/dist/__tests__/integration/contacts-flow.test.d.ts +0 -2
  72. package/dist/__tests__/integration/contacts-flow.test.d.ts.map +0 -1
  73. package/dist/__tests__/integration/contacts-flow.test.js +0 -144
  74. package/dist/__tests__/integration/contacts-flow.test.js.map +0 -1
  75. package/dist/__tests__/integration/media-flow.test.d.ts +0 -2
  76. package/dist/__tests__/integration/media-flow.test.d.ts.map +0 -1
  77. package/dist/__tests__/integration/media-flow.test.js +0 -225
  78. package/dist/__tests__/integration/media-flow.test.js.map +0 -1
  79. package/dist/__tests__/integration/search-flow.test.d.ts +0 -2
  80. package/dist/__tests__/integration/search-flow.test.d.ts.map +0 -1
  81. package/dist/__tests__/integration/search-flow.test.js +0 -44
  82. package/dist/__tests__/integration/search-flow.test.js.map +0 -1
  83. package/dist/__tests__/integration/send-message.test.d.ts +0 -2
  84. package/dist/__tests__/integration/send-message.test.d.ts.map +0 -1
  85. package/dist/__tests__/integration/send-message.test.js +0 -160
  86. package/dist/__tests__/integration/send-message.test.js.map +0 -1
  87. package/dist/__tests__/lock-file.test.d.ts +0 -2
  88. package/dist/__tests__/lock-file.test.d.ts.map +0 -1
  89. package/dist/__tests__/lock-file.test.js +0 -63
  90. package/dist/__tests__/lock-file.test.js.map +0 -1
  91. package/dist/__tests__/medium-fixes.test.d.ts +0 -2
  92. package/dist/__tests__/medium-fixes.test.d.ts.map +0 -1
  93. package/dist/__tests__/medium-fixes.test.js +0 -141
  94. package/dist/__tests__/medium-fixes.test.js.map +0 -1
  95. package/dist/__tests__/rate-limit.test.d.ts +0 -2
  96. package/dist/__tests__/rate-limit.test.d.ts.map +0 -1
  97. package/dist/__tests__/rate-limit.test.js +0 -193
  98. package/dist/__tests__/rate-limit.test.js.map +0 -1
  99. package/dist/__tests__/send-file.test.d.ts +0 -2
  100. package/dist/__tests__/send-file.test.d.ts.map +0 -1
  101. package/dist/__tests__/send-file.test.js +0 -237
  102. package/dist/__tests__/send-file.test.js.map +0 -1
  103. package/dist/__tests__/smoke.test.d.ts +0 -2
  104. package/dist/__tests__/smoke.test.d.ts.map +0 -1
  105. package/dist/__tests__/smoke.test.js +0 -28
  106. package/dist/__tests__/smoke.test.js.map +0 -1
  107. package/dist/__tests__/transcribe.test.d.ts +0 -2
  108. package/dist/__tests__/transcribe.test.d.ts.map +0 -1
  109. package/dist/__tests__/transcribe.test.js +0 -71
  110. package/dist/__tests__/transcribe.test.js.map +0 -1
  111. package/dist/__tests__/zombie.test.d.ts +0 -2
  112. package/dist/__tests__/zombie.test.d.ts.map +0 -1
  113. package/dist/__tests__/zombie.test.js +0 -145
  114. package/dist/__tests__/zombie.test.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"search-flow.test.js","sourceRoot":"","sources":["../../../src/__tests__/integration/search-flow.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=send-message.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"send-message.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/integration/send-message.test.ts"],"names":[],"mappings":""}
@@ -1,160 +0,0 @@
1
- import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
2
- import { Client } from "@modelcontextprotocol/sdk/client/index.js";
3
- import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";
4
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
- import { createFakeBaileysSocket } from "../helpers/fake-baileys.js";
6
- import { closeTestDb, seedTestDb, setupTestDb } from "../helpers/test-db.js";
7
- const mockState = vi.hoisted(() => ({
8
- sockets: [],
9
- }));
10
- vi.mock("@whiskeysockets/baileys", () => ({
11
- default: vi.fn(() => {
12
- const socket = createFakeBaileysSocket();
13
- mockState.sockets.push(socket);
14
- return socket;
15
- }),
16
- DisconnectReason: {
17
- loggedOut: 401,
18
- connectionReplaced: 440,
19
- },
20
- fetchLatestBaileysVersion: vi.fn(async () => ({ version: [2, 3000, 0] })),
21
- downloadMediaMessage: vi.fn(),
22
- getContentType: vi.fn(),
23
- initAuthCreds: vi.fn(() => ({})),
24
- BufferJSON: {
25
- replacer: (_key, value) => value,
26
- reviver: (_key, value) => value,
27
- },
28
- proto: {
29
- Message: {
30
- AppStateSyncKeyData: {
31
- fromObject: (value) => value,
32
- },
33
- },
34
- },
35
- }));
36
- function parseToolJson(result) {
37
- const text = result.content?.find((entry) => entry.type === "text")?.text || "";
38
- try {
39
- return JSON.parse(text);
40
- }
41
- catch {
42
- return text;
43
- }
44
- }
45
- describe("integration: send_message", () => {
46
- const originalMinInterval = process.env.MIN_SEND_INTERVAL_MS;
47
- const originalJitter = process.env.SEND_JITTER_MS;
48
- let server;
49
- let client;
50
- let closeWhatsApp;
51
- beforeAll(async () => {
52
- process.env.MIN_SEND_INTERVAL_MS = "150";
53
- process.env.SEND_JITTER_MS = "0";
54
- await setupTestDb();
55
- seedTestDb();
56
- const whatsapp = await import("../../whatsapp.js");
57
- closeWhatsApp = whatsapp.closeWhatsApp;
58
- await whatsapp.initWhatsApp();
59
- const socket = mockState.sockets.at(-1);
60
- if (!socket)
61
- throw new Error("Expected fake Baileys socket");
62
- socket.emitConnectionOpen();
63
- server = new McpServer({ name: "whatsapp-test", version: "1.0.0" });
64
- const { registerTools } = await import("../../tools.js");
65
- registerTools(server);
66
- const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
67
- client = new Client({ name: "whatsapp-test-client", version: "1.0.0" });
68
- await Promise.all([server.connect(serverTransport), client.connect(clientTransport)]);
69
- });
70
- afterAll(async () => {
71
- await Promise.all([client?.close(), server?.close()]);
72
- await closeWhatsApp?.();
73
- closeTestDb();
74
- if (originalMinInterval === undefined) {
75
- delete process.env.MIN_SEND_INTERVAL_MS;
76
- }
77
- else {
78
- process.env.MIN_SEND_INTERVAL_MS = originalMinInterval;
79
- }
80
- if (originalJitter === undefined) {
81
- delete process.env.SEND_JITTER_MS;
82
- }
83
- else {
84
- process.env.SEND_JITTER_MS = originalJitter;
85
- }
86
- });
87
- it("returns preview when confirmed=false", async () => {
88
- const socket = mockState.sockets.at(-1);
89
- if (!socket)
90
- throw new Error("Expected fake Baileys socket");
91
- const before = socket.sentMessages.length;
92
- const result = (await client.callTool({
93
- name: "send_message",
94
- arguments: {
95
- jid: "15550001111@s.whatsapp.net",
96
- text: "Preview only",
97
- confirmed: false,
98
- },
99
- }));
100
- const payload = parseToolJson(result);
101
- expect(result.isError).toBeFalsy();
102
- expect(payload).toMatchObject({
103
- status: "confirmation_required",
104
- jid: "15550001111@s.whatsapp.net",
105
- phone: "15550001111",
106
- message: "Preview only",
107
- });
108
- expect(socket.sentMessages.length).toBe(before);
109
- });
110
- it("sends when confirmed=true", async () => {
111
- const socket = mockState.sockets.at(-1);
112
- if (!socket)
113
- throw new Error("Expected fake Baileys socket");
114
- const result = (await client.callTool({
115
- name: "send_message",
116
- arguments: {
117
- jid: "15550001111@s.whatsapp.net",
118
- text: "Actually send this",
119
- confirmed: true,
120
- },
121
- }));
122
- const payload = parseToolJson(result);
123
- expect(result.isError).toBeFalsy();
124
- expect(payload).toMatchObject({
125
- success: true,
126
- to: "15550001111@s.whatsapp.net",
127
- messageId: expect.any(String),
128
- });
129
- expect(socket.sentMessages.at(-1)).toMatchObject({
130
- jid: "15550001111@s.whatsapp.net",
131
- content: { text: "Actually send this" },
132
- });
133
- });
134
- it("applies rate limiting delay for second rapid send", async () => {
135
- const firstResult = (await client.callTool({
136
- name: "send_message",
137
- arguments: {
138
- jid: "15550001111@s.whatsapp.net",
139
- text: "first rapid",
140
- confirmed: true,
141
- },
142
- }));
143
- expect(firstResult.isError).toBeFalsy();
144
- const started = Date.now();
145
- const secondResult = (await client.callTool({
146
- name: "send_message",
147
- arguments: {
148
- jid: "15550001111@s.whatsapp.net",
149
- text: "second rapid",
150
- confirmed: true,
151
- },
152
- }));
153
- const elapsed = Date.now() - started;
154
- const payload = parseToolJson(secondResult);
155
- expect(secondResult.isError).toBeFalsy();
156
- expect(payload.success).toBe(true);
157
- expect(elapsed).toBeGreaterThanOrEqual(120);
158
- });
159
- });
160
- //# sourceMappingURL=send-message.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"send-message.test.js","sourceRoot":"","sources":["../../../src/__tests__/integration/send-message.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=lock-file.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"lock-file.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/lock-file.test.ts"],"names":[],"mappings":""}
@@ -1,63 +0,0 @@
1
- import fs from "node:fs";
2
- import os from "node:os";
3
- import path from "node:path";
4
- import { afterEach, beforeEach, describe, expect, it } from "vitest";
5
- import { acquireWhatsAppLock, releaseWhatsAppLock } from "../lock.js";
6
- describe("lock file", () => {
7
- let tmpDir;
8
- let lockFile;
9
- beforeEach(() => {
10
- tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "wa-lock-test-"));
11
- lockFile = path.join(tmpDir, ".whatsapp.lock");
12
- });
13
- afterEach(() => {
14
- // Clean up: release if owned, then remove temp dir
15
- try {
16
- releaseWhatsAppLock(lockFile);
17
- }
18
- catch { }
19
- fs.rmSync(tmpDir, { recursive: true, force: true });
20
- });
21
- it("acquires lock on first call and writes current PID", () => {
22
- expect(acquireWhatsAppLock(lockFile)).toBe(true);
23
- expect(fs.existsSync(lockFile)).toBe(true);
24
- const pid = parseInt(fs.readFileSync(lockFile, "utf-8").trim(), 10);
25
- expect(pid).toBe(process.pid);
26
- });
27
- it("two rapid calls — exactly one succeeds", () => {
28
- const first = acquireWhatsAppLock(lockFile);
29
- const second = acquireWhatsAppLock(lockFile);
30
- expect(first).toBe(true);
31
- expect(second).toBe(false);
32
- });
33
- it("stale lock with dead PID — new process takes over", () => {
34
- fs.mkdirSync(path.dirname(lockFile), { recursive: true });
35
- fs.writeFileSync(lockFile, "99999999");
36
- const result = acquireWhatsAppLock(lockFile);
37
- expect(result).toBe(true);
38
- const pid = parseInt(fs.readFileSync(lockFile, "utf-8").trim(), 10);
39
- expect(pid).toBe(process.pid);
40
- });
41
- it("release removes the lock file when owned by current PID", () => {
42
- acquireWhatsAppLock(lockFile);
43
- expect(fs.existsSync(lockFile)).toBe(true);
44
- releaseWhatsAppLock(lockFile);
45
- expect(fs.existsSync(lockFile)).toBe(false);
46
- });
47
- it("release is safe when no lock file exists", () => {
48
- expect(() => releaseWhatsAppLock(lockFile)).not.toThrow();
49
- });
50
- it("release does not remove lock owned by different PID", () => {
51
- fs.mkdirSync(path.dirname(lockFile), { recursive: true });
52
- fs.writeFileSync(lockFile, "99999999");
53
- releaseWhatsAppLock(lockFile);
54
- // File should still exist — not our PID
55
- expect(fs.existsSync(lockFile)).toBe(true);
56
- });
57
- it("creates parent directories if they don't exist", () => {
58
- const nested = path.join(tmpDir, "deep", "nested", ".whatsapp.lock");
59
- expect(acquireWhatsAppLock(nested)).toBe(true);
60
- expect(fs.existsSync(nested)).toBe(true);
61
- });
62
- });
63
- //# sourceMappingURL=lock-file.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"lock-file.test.js","sourceRoot":"","sources":["../../src/__tests__/lock-file.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=medium-fixes.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"medium-fixes.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/medium-fixes.test.ts"],"names":[],"mappings":""}
@@ -1,141 +0,0 @@
1
- import { afterAll, beforeAll, describe, expect, it } from "vitest";
2
- import { closeTestDb, seedTestDb, setupTestDb } from "./helpers/test-db.js";
3
- import { createMcpTestClient } from "./helpers/mcp-test-client.js";
4
- // ─── Fix 1: JID device suffix stripping ─────────────────────────────
5
- describe("toJid — device suffix stripping", () => {
6
- let toJid;
7
- beforeAll(async () => {
8
- const utils = await import("../utils.js");
9
- toJid = utils.toJid;
10
- });
11
- it("strips device suffix from phone JID", () => {
12
- expect(toJid("1234567890:5@s.whatsapp.net")).toBe("1234567890@s.whatsapp.net");
13
- });
14
- it("strips multi-digit device suffix", () => {
15
- expect(toJid("9876543210:42@s.whatsapp.net")).toBe("9876543210@s.whatsapp.net");
16
- });
17
- it("passes through normal phone JID unchanged", () => {
18
- expect(toJid("1234567890@s.whatsapp.net")).toBe("1234567890@s.whatsapp.net");
19
- });
20
- it("passes through group JID unchanged", () => {
21
- expect(toJid("123456789-987654321@g.us")).toBe("123456789-987654321@g.us");
22
- });
23
- it("passes through LID JID unchanged", () => {
24
- expect(toJid("12345@lid")).toBe("12345@lid");
25
- });
26
- it("normalizes bare phone number to JID", () => {
27
- expect(toJid("1234567890")).toBe("1234567890@s.whatsapp.net");
28
- });
29
- it("strips + prefix from phone number", () => {
30
- expect(toJid("+1234567890")).toBe("1234567890@s.whatsapp.net");
31
- });
32
- });
33
- // ─── Fix 2: Search LIKE wildcard escaping ────────────────────────────
34
- describe("searchMessages — LIKE wildcard escaping", () => {
35
- let dbModule;
36
- beforeAll(async () => {
37
- await setupTestDb();
38
- seedTestDb();
39
- dbModule = await import("../db.js");
40
- // Insert messages with specific content for wildcard tests
41
- const db = dbModule.getDb();
42
- db.prepare("INSERT INTO messages (id, chat_jid, from_me, type, text, timestamp, has_media) VALUES (?, ?, ?, ?, ?, ?, ?)").run("msg-percent", "15550001111@s.whatsapp.net", 0, "text", "100% done", 1700000010, 0);
43
- db.prepare("INSERT INTO messages (id, chat_jid, from_me, type, text, timestamp, has_media) VALUES (?, ?, ?, ?, ?, ?, ?)").run("msg-underscore", "15550001111@s.whatsapp.net", 0, "text", "use_snake_case", 1700000020, 0);
44
- db.prepare("INSERT INTO messages (id, chat_jid, from_me, type, text, timestamp, has_media) VALUES (?, ?, ?, ?, ?, ?, ?)").run("msg-normal", "15550001111@s.whatsapp.net", 0, "text", "normal message", 1700000030, 0);
45
- });
46
- afterAll(() => {
47
- closeTestDb();
48
- });
49
- it("searching '%' does NOT match all messages", () => {
50
- const results = dbModule.searchMessages("%");
51
- // Should only match messages containing a literal "%" character
52
- expect(results.length).toBeLessThanOrEqual(1);
53
- if (results.length > 0) {
54
- expect(results.every((r) => typeof r.text === "string" && r.text.includes("%"))).toBe(true);
55
- }
56
- });
57
- it("searching '_' does NOT match single characters", () => {
58
- const results = dbModule.searchMessages("_");
59
- // Should only match messages containing a literal "_" character
60
- for (const r of results) {
61
- expect(typeof r.text === "string" && r.text.includes("_")).toBe(true);
62
- }
63
- });
64
- it("finds messages with literal % in text", () => {
65
- const results = dbModule.searchMessages("100%");
66
- expect(results.length).toBeGreaterThanOrEqual(1);
67
- expect(results.some((r) => r.text === "100% done")).toBe(true);
68
- });
69
- it("finds messages with literal _ in text", () => {
70
- const results = dbModule.searchMessages("snake_case");
71
- expect(results.length).toBeGreaterThanOrEqual(1);
72
- expect(results.some((r) => r.text === "use_snake_case")).toBe(true);
73
- });
74
- it("normal substring search still works", () => {
75
- const results = dbModule.searchMessages("normal");
76
- expect(results.length).toBeGreaterThanOrEqual(1);
77
- expect(results.some((r) => r.text === "normal message")).toBe(true);
78
- });
79
- });
80
- // ─── Fix 3: VCF path containment ────────────────────────────────────
81
- describe("importContactsFromVcf — path containment", () => {
82
- let importContactsFromVcf;
83
- let Database;
84
- beforeAll(async () => {
85
- const mod = await import("../import-contacts.js");
86
- importContactsFromVcf = mod.importContactsFromVcf;
87
- const dbMod = await import("better-sqlite3");
88
- Database = (dbMod.default ?? dbMod);
89
- });
90
- it("rejects /etc/passwd as VCF path", () => {
91
- // Create a minimal in-memory DB with schema
92
- const db = new Database(":memory:");
93
- db.exec(`
94
- CREATE TABLE IF NOT EXISTS chats (jid TEXT PRIMARY KEY, name TEXT, conversation_ts INTEGER DEFAULT 0, unread_count INTEGER DEFAULT 0);
95
- CREATE TABLE IF NOT EXISTS contacts (jid TEXT PRIMARY KEY, name TEXT, notify TEXT);
96
- `);
97
- expect(() => importContactsFromVcf(db, "/etc/passwd")).toThrow(/VCF path not allowed/);
98
- db.close();
99
- });
100
- it("rejects path traversal attempts", () => {
101
- const db = new Database(":memory:");
102
- db.exec(`
103
- CREATE TABLE IF NOT EXISTS chats (jid TEXT PRIMARY KEY, name TEXT, conversation_ts INTEGER DEFAULT 0, unread_count INTEGER DEFAULT 0);
104
- CREATE TABLE IF NOT EXISTS contacts (jid TEXT PRIMARY KEY, name TEXT, notify TEXT);
105
- `);
106
- expect(() => importContactsFromVcf(db, "../../../etc/shadow")).toThrow(/VCF path not allowed/);
107
- db.close();
108
- });
109
- });
110
- // ─── Fix 4: list_chats limit passthrough ─────────────────────────────
111
- describe("list_chats — limit passthrough to DB", () => {
112
- let client;
113
- beforeAll(async () => {
114
- // Re-setup DB for MCP client tests (clean state)
115
- await setupTestDb();
116
- const dbModule = await import("../db.js");
117
- const db = dbModule.getDb();
118
- // Seed 10 chats with messages
119
- for (let i = 1; i <= 10; i++) {
120
- const jid = `1555000${String(i).padStart(4, "0")}@s.whatsapp.net`;
121
- db.prepare("INSERT OR REPLACE INTO chats (jid, name, conversation_ts, unread_count) VALUES (?, ?, ?, ?)").run(jid, `Contact ${i}`, 1700000000 + i * 100, 0);
122
- db.prepare("INSERT OR REPLACE INTO messages (id, chat_jid, from_me, type, text, timestamp, has_media) VALUES (?, ?, ?, ?, ?, ?, ?)").run(`msg-${i}`, jid, 0, "text", `Message from contact ${i}`, 1700000000 + i * 100, 0);
123
- }
124
- client = await createMcpTestClient();
125
- });
126
- afterAll(async () => {
127
- await client?.close();
128
- closeTestDb();
129
- });
130
- it("returns at most `limit` chats from DB", async () => {
131
- const result = await client.callTool("list_chats", { limit: 5 });
132
- expect(Array.isArray(result)).toBe(true);
133
- expect(result.length).toBeLessThanOrEqual(5);
134
- });
135
- it("returns more chats with higher limit", async () => {
136
- const result = await client.callTool("list_chats", { limit: 100 });
137
- expect(Array.isArray(result)).toBe(true);
138
- expect(result.length).toBeGreaterThanOrEqual(10);
139
- });
140
- });
141
- //# sourceMappingURL=medium-fixes.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"medium-fixes.test.js","sourceRoot":"","sources":["../../src/__tests__/medium-fixes.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=rate-limit.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rate-limit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/rate-limit.test.ts"],"names":[],"mappings":""}
@@ -1,193 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
- import { createFakeBaileysSocket } from "./helpers/fake-baileys.js";
3
- import { closeTestDb, seedTestDb, setupTestDb } from "./helpers/test-db.js";
4
- const mockState = vi.hoisted(() => ({
5
- sockets: [],
6
- }));
7
- vi.mock("@whiskeysockets/baileys", () => ({
8
- default: vi.fn(() => {
9
- const socket = createFakeBaileysSocket();
10
- mockState.sockets.push(socket);
11
- return socket;
12
- }),
13
- DisconnectReason: {
14
- loggedOut: 401,
15
- connectionClosed: 428,
16
- connectionReplaced: 440,
17
- badSession: 500,
18
- unavailableService: 503,
19
- restartRequired: 515,
20
- connectionLost: 408,
21
- forbidden: 403,
22
- multideviceMismatch: 411,
23
- },
24
- fetchLatestBaileysVersion: vi.fn(async () => ({ version: [2, 3000, 0] })),
25
- downloadMediaMessage: vi.fn(),
26
- getContentType: vi.fn(),
27
- initAuthCreds: vi.fn(() => ({})),
28
- BufferJSON: {
29
- replacer: (_key, value) => value,
30
- reviver: (_key, value) => value,
31
- },
32
- proto: {
33
- Message: {
34
- AppStateSyncKeyData: {
35
- fromObject: (value) => value,
36
- },
37
- },
38
- },
39
- }));
40
- function latestSocket() {
41
- const socket = mockState.sockets.at(-1);
42
- if (!socket)
43
- throw new Error("No fake socket was created");
44
- return socket;
45
- }
46
- describe("SendRateLimiter", () => {
47
- beforeEach(() => {
48
- vi.useFakeTimers();
49
- });
50
- afterEach(() => {
51
- vi.useRealTimers();
52
- });
53
- it("delays when called rapidly", async () => {
54
- const { SendRateLimiter } = await import("../whatsapp.js");
55
- const limiter = new SendRateLimiter(3000, 0); // no jitter for deterministic test
56
- // First call: no delay (lastSendTimestamp is 0)
57
- const start = Date.now();
58
- const p1 = limiter.throttle();
59
- await vi.advanceTimersByTimeAsync(0);
60
- await p1;
61
- const afterFirst = Date.now();
62
- // Second call immediately: should delay by ~3000ms
63
- const p2 = limiter.throttle();
64
- // Should NOT have resolved yet
65
- let resolved = false;
66
- p2.then(() => { resolved = true; });
67
- await vi.advanceTimersByTimeAsync(2999);
68
- expect(resolved).toBe(false);
69
- await vi.advanceTimersByTimeAsync(1);
70
- await p2;
71
- expect(Date.now() - afterFirst).toBeGreaterThanOrEqual(3000);
72
- });
73
- it("does not delay when enough time has elapsed", async () => {
74
- const { SendRateLimiter } = await import("../whatsapp.js");
75
- const limiter = new SendRateLimiter(3000, 0);
76
- await limiter.throttle();
77
- // Advance well past the interval
78
- vi.advanceTimersByTime(5000);
79
- const before = Date.now();
80
- const p2 = limiter.throttle();
81
- // Should resolve almost immediately (no setTimeout needed)
82
- await vi.advanceTimersByTimeAsync(0);
83
- await p2;
84
- // Elapsed should be minimal (just jitter=0)
85
- expect(Date.now() - before).toBeLessThan(100);
86
- });
87
- it("adds random jitter to delay", async () => {
88
- const { SendRateLimiter } = await import("../whatsapp.js");
89
- // First call: no jitter. Second call: jitter = 0.5 * 2000 = 1000ms
90
- vi.spyOn(Math, "random").mockReturnValueOnce(0).mockReturnValueOnce(0.5);
91
- const limiter = new SendRateLimiter(3000, 2000);
92
- await limiter.throttle();
93
- // Second call: should delay 3000ms (min interval) + 1000ms (jitter) = 4000ms
94
- const p2 = limiter.throttle();
95
- let resolved = false;
96
- p2.then(() => { resolved = true; });
97
- await vi.advanceTimersByTimeAsync(3999);
98
- expect(resolved).toBe(false);
99
- await vi.advanceTimersByTimeAsync(1);
100
- await p2;
101
- expect(resolved).toBe(true);
102
- vi.spyOn(Math, "random").mockRestore();
103
- });
104
- it("always adds jitter even when enough time elapsed", async () => {
105
- const { SendRateLimiter } = await import("../whatsapp.js");
106
- vi.spyOn(Math, "random").mockReturnValueOnce(0).mockReturnValueOnce(0.5);
107
- const limiter = new SendRateLimiter(3000, 2000);
108
- await limiter.throttle();
109
- vi.advanceTimersByTime(10000); // well past min interval
110
- // Jitter = 0.5 * 2000 = 1000ms delay even though min interval passed
111
- const p2 = limiter.throttle();
112
- let resolved = false;
113
- p2.then(() => { resolved = true; });
114
- await vi.advanceTimersByTimeAsync(999);
115
- expect(resolved).toBe(false);
116
- await vi.advanceTimersByTimeAsync(1);
117
- await p2;
118
- expect(resolved).toBe(true);
119
- vi.spyOn(Math, "random").mockRestore();
120
- });
121
- });
122
- describe("rate limiting integration", () => {
123
- const originalMinInterval = process.env.MIN_SEND_INTERVAL_MS;
124
- const originalJitter = process.env.SEND_JITTER_MS;
125
- beforeEach(async () => {
126
- vi.resetModules();
127
- vi.useFakeTimers();
128
- mockState.sockets.length = 0;
129
- process.env.MIN_SEND_INTERVAL_MS = "3000";
130
- process.env.SEND_JITTER_MS = "0"; // no jitter for predictable integration tests
131
- await setupTestDb();
132
- seedTestDb();
133
- });
134
- afterEach(async () => {
135
- const whatsapp = await import("../whatsapp.js");
136
- await whatsapp.closeWhatsApp();
137
- closeTestDb();
138
- vi.useRealTimers();
139
- if (originalMinInterval === undefined) {
140
- delete process.env.MIN_SEND_INTERVAL_MS;
141
- }
142
- else {
143
- process.env.MIN_SEND_INTERVAL_MS = originalMinInterval;
144
- }
145
- if (originalJitter === undefined) {
146
- delete process.env.SEND_JITTER_MS;
147
- }
148
- else {
149
- process.env.SEND_JITTER_MS = originalJitter;
150
- }
151
- });
152
- it("delays second rapid send_message by at least MIN_SEND_INTERVAL_MS", async () => {
153
- const whatsapp = await import("../whatsapp.js");
154
- await whatsapp.initWhatsApp();
155
- const socket = latestSocket();
156
- socket.emitConnectionOpen();
157
- // First send — should go immediately
158
- const p1 = whatsapp.sendTextMessage("15550001111", "first");
159
- await vi.advanceTimersByTimeAsync(0);
160
- await p1;
161
- // Second send immediately — should be delayed
162
- const p2 = whatsapp.sendTextMessage("15550001111", "second");
163
- let secondDone = false;
164
- p2.then(() => { secondDone = true; });
165
- // At 2999ms, should NOT be done
166
- await vi.advanceTimersByTimeAsync(2999);
167
- expect(secondDone).toBe(false);
168
- // At 3000ms, should complete
169
- await vi.advanceTimersByTimeAsync(1);
170
- await p2;
171
- expect(secondDone).toBe(true);
172
- });
173
- it("respects env var configuration for MIN_SEND_INTERVAL_MS", async () => {
174
- // Already set MIN_SEND_INTERVAL_MS=3000 and SEND_JITTER_MS=0 in beforeEach
175
- // This test validates the module reads them
176
- const whatsapp = await import("../whatsapp.js");
177
- await whatsapp.initWhatsApp();
178
- const socket = latestSocket();
179
- socket.emitConnectionOpen();
180
- const p1 = whatsapp.sendTextMessage("15550001111", "a");
181
- await vi.advanceTimersByTimeAsync(0);
182
- await p1;
183
- const p2 = whatsapp.sendTextMessage("15550001111", "b");
184
- let done = false;
185
- p2.then(() => { done = true; });
186
- await vi.advanceTimersByTimeAsync(2500);
187
- expect(done).toBe(false);
188
- await vi.advanceTimersByTimeAsync(500);
189
- await p2;
190
- expect(done).toBe(true);
191
- });
192
- });
193
- //# sourceMappingURL=rate-limit.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rate-limit.test.js","sourceRoot":"","sources":["../../src/__tests__/rate-limit.test.ts"],"names":[],"mappings":"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"}