openclaw/extensions/whatsapp/src/outbound-adapter.ts
scoootscooob 439c21e078
refactor: remove channel shim directories, point all imports to extensions (#45967)
* refactor: remove channel shim directories, point all imports to extensions

Delete the 6 backward-compat shim directories (src/telegram, src/discord,
src/slack, src/signal, src/imessage, src/web) that were re-exporting from
extensions. Update all 112+ source files to import directly from
extensions/{channel}/src/ instead of through the shims.

Also:
- Move src/channels/telegram/ (allow-from, api) to extensions/telegram/src/
- Fix outbound adapters to use resolveOutboundSendDep (fixes 5 pre-existing TS errors)
- Update cross-extension imports (src/web/media.js → extensions/whatsapp/src/media.js)
- Update vitest, tsdown, knip, labeler, and script configs for new paths
- Update guard test allowlists for extension paths

After this, src/ has zero channel-specific implementation code — only the
generic plugin framework remains.

* fix: update raw-fetch guard allowlist line numbers after shim removal

* refactor: document direct extension channel imports

* test: mock transcript module in delivery helpers
2026-03-14 03:43:07 -07:00

77 lines
2.7 KiB
TypeScript

import { chunkText } from "../../../src/auto-reply/chunk.js";
import { sendTextMediaPayload } from "../../../src/channels/plugins/outbound/direct-text-media.js";
import type { ChannelOutboundAdapter } from "../../../src/channels/plugins/types.js";
import { shouldLogVerbose } from "../../../src/globals.js";
import { resolveOutboundSendDep } from "../../../src/infra/outbound/deliver.js";
import { resolveWhatsAppOutboundTarget } from "../../../src/whatsapp/resolve-outbound-target.js";
import { sendMessageWhatsApp, sendPollWhatsApp } from "./send.js";
function trimLeadingWhitespace(text: string | undefined): string {
return text?.trimStart() ?? "";
}
export const whatsappOutbound: ChannelOutboundAdapter = {
deliveryMode: "gateway",
chunker: chunkText,
chunkerMode: "text",
textChunkLimit: 4000,
pollMaxOptions: 12,
resolveTarget: ({ to, allowFrom, mode }) =>
resolveWhatsAppOutboundTarget({ to, allowFrom, mode }),
sendPayload: async (ctx) => {
const text = trimLeadingWhitespace(ctx.payload.text);
const hasMedia = Boolean(ctx.payload.mediaUrl) || (ctx.payload.mediaUrls?.length ?? 0) > 0;
if (!text && !hasMedia) {
return { channel: "whatsapp", messageId: "" };
}
return await sendTextMediaPayload({
channel: "whatsapp",
ctx: {
...ctx,
payload: {
...ctx.payload,
text,
},
},
adapter: whatsappOutbound,
});
},
sendText: async ({ cfg, to, text, accountId, deps, gifPlayback }) => {
const normalizedText = trimLeadingWhitespace(text);
if (!normalizedText) {
return { channel: "whatsapp", messageId: "" };
}
const send =
resolveOutboundSendDep<typeof sendMessageWhatsApp>(deps, "whatsapp") ??
(await import("./send.js")).sendMessageWhatsApp;
const result = await send(to, normalizedText, {
verbose: false,
cfg,
accountId: accountId ?? undefined,
gifPlayback,
});
return { channel: "whatsapp", ...result };
},
sendMedia: async ({ cfg, to, text, mediaUrl, mediaLocalRoots, accountId, deps, gifPlayback }) => {
const normalizedText = trimLeadingWhitespace(text);
const send =
resolveOutboundSendDep<typeof sendMessageWhatsApp>(deps, "whatsapp") ??
(await import("./send.js")).sendMessageWhatsApp;
const result = await send(to, normalizedText, {
verbose: false,
cfg,
mediaUrl,
mediaLocalRoots,
accountId: accountId ?? undefined,
gifPlayback,
});
return { channel: "whatsapp", ...result };
},
sendPoll: async ({ cfg, to, poll, accountId }) =>
await sendPollWhatsApp(to, poll, {
verbose: shouldLogVerbose(),
accountId: accountId ?? undefined,
cfg,
}),
};