mirror of
https://github.com/hansjone/dsh-im-ops.git
synced 2026-10-09 06:30:45 +08:00
Fix WhatsApp connection test delivery without touching DSH sessions.
Send the probe to the bound private-chat target, falling back to Message Yourself via live LID so Baileys no longer reports success while the phone never receives it. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
d8c7671bd7
commit
0bc0992330
5 changed files with 396 additions and 206 deletions
|
|
@ -3,7 +3,7 @@
|
|||
* when Baileys only surfaces opaque @lid identities on the wire.
|
||||
*/
|
||||
|
||||
import { areJidsSameUser, jidDecode } from '@whiskeysockets/baileys';
|
||||
import { areJidsSameUser, jidDecode, jidNormalizedUser } from '@whiskeysockets/baileys';
|
||||
|
||||
function isLidServer(server) {
|
||||
return server === 'lid' || server === 'hosted.lid';
|
||||
|
|
@ -76,6 +76,56 @@ async function lookupLidForPn(socket, pn) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer the live WhatsApp self-chat JID (LID when available) for outbound
|
||||
* probes. Sending only the stored PN often "succeeds" in Baileys but never
|
||||
* syncs into the phone's Message Yourself thread after LID migration.
|
||||
*
|
||||
* @param {{ socket?: object, accountJid: string, lidPnCache?: Map<string, string> }} options
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
export async function resolveWhatsappSelfChatJid({
|
||||
socket,
|
||||
accountJid,
|
||||
lidPnCache,
|
||||
} = {}) {
|
||||
const normalize = (value) => {
|
||||
if (typeof value !== 'string' || !value.trim()) return null;
|
||||
try {
|
||||
return jidNormalizedUser(value.trim()) || value.trim();
|
||||
} catch {
|
||||
return value.trim();
|
||||
}
|
||||
};
|
||||
|
||||
const me = socket?.user;
|
||||
for (const candidate of [me?.lid, me?.id]) {
|
||||
const jid = normalize(candidate);
|
||||
if (jid && isWhatsappLidJid(jid)) return jid;
|
||||
}
|
||||
|
||||
const mapped = await lookupLidForPn(socket, accountJid);
|
||||
const mappedJid = normalize(mapped);
|
||||
if (mappedJid && isWhatsappLidJid(mappedJid)) return mappedJid;
|
||||
|
||||
if (lidPnCache instanceof Map && typeof accountJid === 'string') {
|
||||
for (const [lidUser, pn] of lidPnCache.entries()) {
|
||||
try {
|
||||
if (areJidsSameUser(pn, accountJid) === true && /^\d+$/.test(lidUser)) {
|
||||
return `${lidUser}@lid`;
|
||||
}
|
||||
} catch {
|
||||
// keep scanning
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fallback = normalize(accountJid);
|
||||
if (!fallback) throw new TypeError('WhatsApp account JID is required');
|
||||
return fallback;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Collect local-part tokens for the linked bot account (PN and LID).
|
||||
* Used only to strip trigger @mentions from inbound text — not context injection.
|
||||
|
|
|
|||
|
|
@ -9,11 +9,19 @@ import {
|
|||
|
||||
import { emptyAccessGrant, ensureGroupBucket, normalizeAccessPhone, phoneFromWhatsappJid, resolveAccessAgentPreset } from '../shared/access-grant.mjs';
|
||||
import { splitMessageText } from '../shared/editable-message-stream.mjs';
|
||||
import {
|
||||
connectionTestTarget,
|
||||
} from '../shared/connection-test.mjs';
|
||||
import { t } from '../shared/i18n.mjs';
|
||||
import { ImagePromptError } from '../shared/image-prompt.mjs';
|
||||
import { trackOutboundArtifactProviderPromise } from '../shared/semantic/artifact.mjs';
|
||||
import { createWhatsappBridgeStatus, WhatsappHarnessBridge } from './whatsapp-bridge.mjs';
|
||||
import { enrichWhatsappInboundIdentities, resolveWhatsappGroupSubject, resolveWhatsappGroupSubjects } from './whatsapp-identity.mjs';
|
||||
import {
|
||||
enrichWhatsappInboundIdentities,
|
||||
resolveWhatsappGroupSubject,
|
||||
resolveWhatsappGroupSubjects,
|
||||
resolveWhatsappSelfChatJid,
|
||||
} from './whatsapp-identity.mjs';
|
||||
import {
|
||||
gateWhatsappInbound,
|
||||
loadWhatsappAccessGrant,
|
||||
|
|
@ -865,6 +873,10 @@ export class WhatsappRuntime {
|
|||
return this.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel-direct probe (no Harness / DSH session). Prefer the last bound
|
||||
* private-chat reply target; otherwise Message Yourself via live LID/PN.
|
||||
*/
|
||||
async sendConnectionTest(text) {
|
||||
if (!this.#status.ready || !this.#client) {
|
||||
const error = new Error(t('WhatsApp机器人尚未连接'));
|
||||
|
|
@ -874,13 +886,34 @@ export class WhatsappRuntime {
|
|||
if (typeof text !== 'string' || !text.trim()) {
|
||||
throw new TypeError('WhatsApp connection test text is required');
|
||||
}
|
||||
await this.#client.sendText({
|
||||
jid: this.#config.accountJid,
|
||||
selfChat: true,
|
||||
}, text);
|
||||
const target = await this.#connectionTestSendTarget();
|
||||
await this.#client.sendText(target, text);
|
||||
return { sent: true };
|
||||
}
|
||||
|
||||
async #connectionTestSendTarget() {
|
||||
const remembered = connectionTestTarget(this.#state);
|
||||
const rememberedJid = typeof remembered?.jid === 'string' ? remembered.jid.trim() : '';
|
||||
if (rememberedJid) {
|
||||
let selfChat = remembered.selfChat === true;
|
||||
if (!selfChat) {
|
||||
try {
|
||||
selfChat = areJidsSameUser(rememberedJid, this.#config.accountJid) === true;
|
||||
} catch {
|
||||
selfChat = false;
|
||||
}
|
||||
}
|
||||
// Bound chat only — drop quoted/key so this is a fresh probe, not a reply.
|
||||
return { jid: rememberedJid, selfChat };
|
||||
}
|
||||
const jid = await resolveWhatsappSelfChatJid({
|
||||
socket: this.#session?.socket,
|
||||
accountJid: this.#config.accountJid,
|
||||
lidPnCache: this.#lidPnCache,
|
||||
});
|
||||
return { jid, selfChat: true };
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync WhatsApp group subjects into accessGrant.groups[*].title.
|
||||
* @param {string[]|null|undefined} groupJids
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue