@moxxy/plugin-channel-whatsapp 0.41.3 → 0.42.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"pair-flow.d.ts","sourceRoot":"","sources":["../src/pair-flow.ts"],"names":[],"mappings":"AAEA,OAAO,EAA0B,KAAK,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAUnF;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,wBAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,CAkGxF"}
1
+ {"version":3,"file":"pair-flow.d.ts","sourceRoot":"","sources":["../src/pair-flow.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAU1E;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,wBAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,CAqFxF"}
package/dist/pair-flow.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { log, outro, spinner } from '@clack/prompts';
2
2
  import QRCode from 'qrcode';
3
- import { exitAfterPairRequested } from '@moxxy/sdk';
3
+ import { finishPairing } from '@moxxy/sdk';
4
4
  import { WhatsAppChannel } from './channel.js';
5
5
  import { CONSENT_REQUIRED_MESSAGE } from './consent.js';
6
6
  import { ensureConsentInteractive } from './consent-prompt.js';
@@ -83,26 +83,13 @@ export async function runWhatsAppPairFlow(ctx) {
83
83
  spin.start('Waiting for the scan (the QR refreshes periodically)...');
84
84
  const ownerJid = await paired;
85
85
  spin.stop(`Linked as ${ownerJid}. Your Note-to-Self chat now talks to moxxy.`);
86
- if (exitAfterPairRequested(ctx)) {
87
- // Orchestrated pairing (`moxxy onboard`): hand control back — the caller
88
- // starts the channel under its own service afterwards. Our SIGINT
89
- // handlers would `process.exit` the orchestrator, so drop them first.
90
- unsubscribeConnect();
91
- process.removeListener('SIGINT', onSignal);
92
- process.removeListener('SIGTERM', onSignal);
93
- await stopChannel();
94
- return 0;
95
- }
96
- log.info('Channel is running. Press Ctrl+C to stop.');
97
- try {
98
- await handle.running;
99
- return 0;
100
- }
101
- finally {
102
- unsubscribeConnect();
103
- process.removeListener('SIGINT', onSignal);
104
- process.removeListener('SIGTERM', onSignal);
105
- }
86
+ // Drop the pairing-only handlers first: their `process.exit` would otherwise
87
+ // cut the real channel (or an orchestrator) short. The linked credentials are
88
+ // persisted, so the restarted channel reconnects without a new QR.
89
+ unsubscribeConnect();
90
+ process.removeListener('SIGINT', onSignal);
91
+ process.removeListener('SIGTERM', onSignal);
92
+ return finishPairing(ctx, stopChannel);
106
93
  }
107
94
  /** Render the rotating pairing payload as a scannable terminal QR. */
108
95
  async function printPairQr(payload) {
@@ -1 +1 @@
1
- {"version":3,"file":"pair-flow.js","sourceRoot":"","sources":["../src/pair-flow.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pair-flow.js","sourceRoot":"","sources":["../src/pair-flow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAiC,MAAM,YAAY,CAAC;AAE1E,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,uEAAuE;AACvE,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;AAC3D,MAAM,GAAG,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEtE;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,GAA6B;IACrE,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,KAAmB,CAAC;IAE3C,yEAAyE;IACzE,IAAI,CAAC,CAAC,MAAM,wBAAwB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QAC7C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,wBAAwB,IAAI,CAAC,CAAC;QACtD,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;IAC5B,MAAM,OAAO,GAAG,IAAI,eAAe,CAAC;QAClC,KAAK;QACL,MAAM,EAAE,GAAG,CAAC,IAAI,CAAC,MAAe;KACjC,CAAC,CAAC;IACH,OAAO,CAAC,qBAAqB,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAE1D,uDAAuD;IACvD,IAAI,aAAa,GAAwC,IAAI,CAAC;IAC9D,MAAM,MAAM,GAAG,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;QAC7C,aAAa,GAAG,OAAO,CAAC;IAC1B,CAAC,CAAC,CAAC;IACH,MAAM,iBAAiB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE,EAAE;QACtD,aAAa,EAAE,CAAC,QAAQ,CAAC,CAAC;QAC1B,aAAa,GAAG,IAAI,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAE5D,MAAM,WAAW,GAAG,KAAK,IAAmB,EAAE;QAC5C,iBAAiB,EAAE,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,YAAY;QACd,CAAC;IACH,CAAC,CAAC;IAEF,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACtB,GAAG,CAAC,IAAI,CACN,2GAA2G,CAC5G,CAAC;QACF,MAAM,WAAW,EAAE,CAAC;QACpB,OAAO,CAAC,CAAC;IACX,CAAC;IAED,8DAA8D;IAC9D,IAAI,MAAM,GAAkB,IAAI,CAAC;IACjC,MAAM,QAAQ,GAAG,KAAK,IAAmB,EAAE;QACzC,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC;QAC9B,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,MAAM;YAAE,OAAO;QACjC,MAAM,GAAG,EAAE,CAAC;QACZ,MAAM,WAAW,CAAC,EAAE,CAAC,CAAC;QACtB,GAAG,CAAC,IAAI,CACN,2FAA2F,CAC5F,CAAC;IACJ,CAAC,CAAC;IACF,MAAM,kBAAkB,GAAG,MAAM,CAAC,eAAe,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,QAAQ,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAChG,MAAM,QAAQ,EAAE,CAAC;IAEjB,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,MAAM,QAAQ,GAAG,KAAK,IAAmB,EAAE;QACzC,IAAI,QAAQ;YAAE,OAAO;QACrB,QAAQ,GAAG,IAAI,CAAC;QAChB,kBAAkB,EAAE,CAAC;QACrB,MAAM,WAAW,EAAE,CAAC;QACpB,MAAM,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IACF,MAAM,QAAQ,GAAG,GAAS,EAAE,CAAC,KAAK,QAAQ,EAAE,CAAC;IAC7C,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACjC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAElC,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,IAAI,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;IACtE,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC;IAC9B,IAAI,CAAC,IAAI,CAAC,aAAa,QAAQ,8CAA8C,CAAC,CAAC;IAE/E,6EAA6E;IAC7E,8EAA8E;IAC9E,mEAAmE;IACnE,kBAAkB,EAAE,CAAC;IACrB,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC3C,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC5C,OAAO,aAAa,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;AACzC,CAAC;AAED,sEAAsE;AACtE,KAAK,UAAU,WAAW,CAAC,OAAe;IACxC,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,IAAI,CAAC;QACH,EAAE,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACzE,CAAC;IAAC,MAAM,CAAC;QACP,EAAE,GAAG,EAAE,CAAC;IACV,CAAC;IACD,6EAA6E;IAC7E,sEAAsE;IACtE,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACnC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moxxy/plugin-channel-whatsapp",
3
- "version": "0.41.3",
3
+ "version": "0.42.1",
4
4
  "description": "WhatsApp channel for moxxy via Baileys (UNOFFICIAL WhatsApp Web protocol — violates WhatsApp's Terms of Service; the linked number can be banned, use a secondary number). QR device-link pairing, JID allow-list, voice-note transcription, dedicated isolated runner.",
5
5
  "keywords": [
6
6
  "moxxy",
@@ -75,18 +75,18 @@
75
75
  "@whiskeysockets/baileys": "^6.7.21",
76
76
  "qrcode": "^1.5.4",
77
77
  "zod": "^3.25.76",
78
- "@moxxy/core": "0.41.3",
79
- "@moxxy/plugin-vault": "0.41.3",
80
- "@moxxy/sdk": "0.41.3",
81
- "@moxxy/channel-kit": "0.41.3"
78
+ "@moxxy/channel-kit": "0.42.1",
79
+ "@moxxy/core": "0.42.1",
80
+ "@moxxy/plugin-vault": "0.42.1",
81
+ "@moxxy/sdk": "0.42.1"
82
82
  },
83
83
  "devDependencies": {
84
- "@types/node": "^22.10.0",
84
+ "@types/node": "^22.20.5",
85
85
  "@types/qrcode": "^1.5.5",
86
86
  "typescript": "^6.0.3",
87
- "vitest": "^4.1.11",
88
- "@moxxy/mode-default": "0.41.3",
89
- "@moxxy/testing": "0.0.70",
87
+ "vitest": "^5.0.3",
88
+ "@moxxy/mode-default": "0.42.1",
89
+ "@moxxy/testing": "0.0.72",
90
90
  "@moxxy/tsconfig": "0.0.0",
91
91
  "@moxxy/vitest-preset": "0.0.0"
92
92
  },
@@ -2,6 +2,7 @@ import { promises as fs } from 'node:fs';
2
2
  import * as os from 'node:os';
3
3
  import * as path from 'node:path';
4
4
  import { afterEach, beforeEach, describe, expect, it } from 'vitest';
5
+ import { posixFileModes } from '@moxxy/vitest-preset/platform';
5
6
  import {
6
7
  createFileAuthStorage,
7
8
  createWhatsAppAuthState,
@@ -10,6 +11,7 @@ import {
10
11
  type BaileysAuthBridge,
11
12
  type WhatsAppAuthStorage,
12
13
  } from './auth-state.js';
14
+ import { removeDir } from '@moxxy/vitest-preset/fs';
13
15
 
14
16
  // A trivial bridge: identity JSON (no Buffer categories), fresh creds counter.
15
17
  function fakeBridge(): BaileysAuthBridge {
@@ -83,7 +85,7 @@ describe('createFileAuthStorage', () => {
83
85
  dir = await fs.mkdtemp(path.join(os.tmpdir(), 'wa-auth-'));
84
86
  });
85
87
  afterEach(async () => {
86
- await fs.rm(dir, { recursive: true, force: true });
88
+ await removeDir(dir);
87
89
  });
88
90
 
89
91
  it('writes 0600 files and clears the whole dir', async () => {
@@ -94,7 +96,7 @@ describe('createFileAuthStorage', () => {
94
96
 
95
97
  const file = path.join(dir, 'auth', 'creds.json');
96
98
  const mode = (await fs.stat(file)).mode & 0o777;
97
- expect(mode).toBe(0o600);
99
+ if (posixFileModes) expect(mode).toBe(0o600);
98
100
 
99
101
  await storage.clear();
100
102
  expect(await storage.read('creds')).toBeNull();
@@ -18,6 +18,7 @@ import type {
18
18
  } from './socket.js';
19
19
  import { createFileAuthStorage } from './auth-state.js';
20
20
  import { WHATSAPP_CONSENT_ENV } from './keys.js';
21
+ import { removeDir } from '@moxxy/vitest-preset/fs';
21
22
 
22
23
  const OWNER = '15550000000@s.whatsapp.net';
23
24
  const FRIEND = '15551111111@s.whatsapp.net';
@@ -115,7 +116,7 @@ afterEach(async () => {
115
116
  // a single rm can race it (ENOTEMPTY). Retry briefly, then give up.
116
117
  for (let i = 0; i < 5; i++) {
117
118
  try {
118
- await fs.rm(tmp, { recursive: true, force: true });
119
+ await removeDir(tmp);
119
120
  break;
120
121
  } catch {
121
122
  await new Promise((r) => setTimeout(r, 20));
package/src/pair-flow.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { log, outro, spinner } from '@clack/prompts';
2
2
  import QRCode from 'qrcode';
3
- import { exitAfterPairRequested, type ChannelSubcommandContext } from '@moxxy/sdk';
3
+ import { finishPairing, type ChannelSubcommandContext } from '@moxxy/sdk';
4
4
  import type { VaultStore } from '@moxxy/plugin-vault';
5
5
  import { WhatsAppChannel } from './channel.js';
6
6
  import { CONSENT_REQUIRED_MESSAGE } from './consent.js';
@@ -97,26 +97,13 @@ export async function runWhatsAppPairFlow(ctx: ChannelSubcommandContext): Promis
97
97
  const ownerJid = await paired;
98
98
  spin.stop(`Linked as ${ownerJid}. Your Note-to-Self chat now talks to moxxy.`);
99
99
 
100
- if (exitAfterPairRequested(ctx)) {
101
- // Orchestrated pairing (`moxxy onboard`): hand control back — the caller
102
- // starts the channel under its own service afterwards. Our SIGINT
103
- // handlers would `process.exit` the orchestrator, so drop them first.
104
- unsubscribeConnect();
105
- process.removeListener('SIGINT', onSignal);
106
- process.removeListener('SIGTERM', onSignal);
107
- await stopChannel();
108
- return 0;
109
- }
110
-
111
- log.info('Channel is running. Press Ctrl+C to stop.');
112
- try {
113
- await handle.running;
114
- return 0;
115
- } finally {
116
- unsubscribeConnect();
117
- process.removeListener('SIGINT', onSignal);
118
- process.removeListener('SIGTERM', onSignal);
119
- }
100
+ // Drop the pairing-only handlers first: their `process.exit` would otherwise
101
+ // cut the real channel (or an orchestrator) short. The linked credentials are
102
+ // persisted, so the restarted channel reconnects without a new QR.
103
+ unsubscribeConnect();
104
+ process.removeListener('SIGINT', onSignal);
105
+ process.removeListener('SIGTERM', onSignal);
106
+ return finishPairing(ctx, stopChannel);
120
107
  }
121
108
 
122
109
  /** Render the rotating pairing payload as a scannable terminal QR. */
@@ -11,6 +11,7 @@ import {
11
11
  WHATSAPP_CONSENT_KEY,
12
12
  WHATSAPP_OWNER_JID_KEY,
13
13
  } from './keys.js';
14
+ import { removeDir } from '@moxxy/vitest-preset/fs';
14
15
 
15
16
  let tmp: string;
16
17
  let vault: VaultStore;
@@ -46,7 +47,7 @@ beforeEach(async () => {
46
47
  });
47
48
 
48
49
  afterEach(async () => {
49
- await fs.rm(tmp, { recursive: true, force: true });
50
+ await removeDir(tmp);
50
51
  process.stdout.write = origOut;
51
52
  process.stderr.write = origErr;
52
53
  if (origHome === undefined) delete process.env.MOXXY_HOME;