Normalize webhook path, always log inbound, fix Twilio webhook field names, log polling tip

This commit is contained in:
Peter Steinberger
2025-11-24 15:28:27 +01:00
parent 4a7cfbcc7c
commit 4f32120176

View File

@@ -290,6 +290,11 @@ function withWhatsAppPrefix(number: string): string {
return number.startsWith("whatsapp:") ? number : `whatsapp:${number}`; return number.startsWith("whatsapp:") ? number : `whatsapp:${number}`;
} }
function normalizePath(p: string): string {
if (!p.startsWith("/")) return `/${p}`;
return p;
}
const CONFIG_PATH = path.join(os.homedir(), ".warelay", "warelay.json"); const CONFIG_PATH = path.join(os.homedir(), ".warelay", "warelay.json");
const success = chalk.green; const success = chalk.green;
const warn = chalk.yellow; const warn = chalk.yellow;
@@ -470,6 +475,7 @@ async function startWebhook(
autoReply: string | undefined, autoReply: string | undefined,
verbose: boolean, verbose: boolean,
): Promise<import("http").Server> { ): Promise<import("http").Server> {
const normalizedPath = normalizePath(path);
// Start Express webhook; generate replies via config or CLI flag. // Start Express webhook; generate replies via config or CLI flag.
const env = readEnv(); const env = readEnv();
const app = express(); const app = express();
@@ -477,17 +483,18 @@ async function startWebhook(
// Twilio sends application/x-www-form-urlencoded // Twilio sends application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false })); app.use(bodyParser.urlencoded({ extended: false }));
app.use((req, _res, next) => { app.use((req, _res, next) => {
if (verbose) { console.log(chalk.gray(`REQ ${req.method} ${req.url}`));
console.log(chalk.gray(`REQ ${req.method} ${req.url}`));
}
next(); next();
}); });
app.post(path, async (req: Request, res: Response) => { app.post(normalizedPath, async (req: Request, res: Response) => {
const { From, To, Body, MessageSid } = req.body ?? {}; const { From, To, Body, MessageSid } = req.body ?? {};
if (verbose) { console.log(
console.log(`[INBOUND] ${From} -> ${To} (${MessageSid}): ${Body}`); `[INBOUND] ${From ?? "unknown"} -> ${To ?? "unknown"} (${
} MessageSid ?? "no-sid"
})`,
);
if (verbose) console.log(chalk.gray(`Body: ${Body ?? ""}`));
let replyText = autoReply; let replyText = autoReply;
if (!replyText) { if (!replyText) {
@@ -520,6 +527,7 @@ async function startWebhook(
}); });
app.use((_req, res) => { app.use((_req, res) => {
if (verbose) console.log(chalk.yellow(`404 ${_req.method} ${_req.url}`));
res.status(404).send("warelay webhook: not found"); res.status(404).send("warelay webhook: not found");
}); });
@@ -528,7 +536,9 @@ async function startWebhook(
const onListening = () => { const onListening = () => {
cleanup(); cleanup();
console.log(`📥 Webhook listening on http://localhost:${port}${path}`); console.log(
`📥 Webhook listening on http://localhost:${port}${normalizedPath}`,
);
resolve(server); resolve(server);
}; };
@@ -775,9 +785,9 @@ async function updateWebhook(
try { try {
if (clientTyped.messaging?.v2?.channelsSenders) { if (clientTyped.messaging?.v2?.channelsSenders) {
await clientTyped.messaging.v2.channelsSenders(senderSid).update({ await clientTyped.messaging.v2.channelsSenders(senderSid).update({
CallbackUrl: url, callbackUrl: url,
CallbackMethod: method, callbackMethod: method,
}); } as any);
console.log(success(`✅ Twilio sender webhook set to ${url}`)); console.log(success(`✅ Twilio sender webhook set to ${url}`));
return; return;
} }
@@ -790,9 +800,9 @@ async function updateWebhook(
const phoneSid = await findIncomingNumberSid(clientTyped, url); const phoneSid = await findIncomingNumberSid(clientTyped, url);
if (phoneSid) { if (phoneSid) {
await (clientTyped.incomingPhoneNumbers as any)(phoneSid).update({ await (clientTyped.incomingPhoneNumbers as any)(phoneSid).update({
SmsUrl: url, smsUrl: url,
SmsMethod: method, smsMethod: method,
}); } as any);
console.log(success(`✅ Twilio phone webhook set to ${url}`)); console.log(success(`✅ Twilio phone webhook set to ${url}`));
return; return;
} }