Fallback webhook update to incoming phone number when channels sender update fails
This commit is contained in:
85
src/index.ts
85
src/index.ts
@@ -53,6 +53,12 @@ type TwilioRequestResponse = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type IncomingNumber = {
|
||||||
|
sid: string;
|
||||||
|
phoneNumber: string;
|
||||||
|
smsUrl?: string;
|
||||||
|
};
|
||||||
|
|
||||||
type TwilioChannelsSender = {
|
type TwilioChannelsSender = {
|
||||||
sid?: string;
|
sid?: string;
|
||||||
senderId?: string;
|
senderId?: string;
|
||||||
@@ -67,9 +73,19 @@ type TwilioSenderListClient = {
|
|||||||
channel: string;
|
channel: string;
|
||||||
pageSize: number;
|
pageSize: number;
|
||||||
}) => Promise<TwilioChannelsSender[]>;
|
}) => Promise<TwilioChannelsSender[]>;
|
||||||
|
(sid: string): {
|
||||||
|
fetch: () => Promise<TwilioChannelsSender>;
|
||||||
|
update: (params: Record<string, string>) => Promise<unknown>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
incomingPhoneNumbers: {
|
||||||
|
list: (params: { phoneNumber: string; limit?: number }) => Promise<IncomingNumber[]>;
|
||||||
|
(sid: string): {
|
||||||
|
update: (params: Record<string, string>) => Promise<unknown>;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
type TwilioRequester = {
|
type TwilioRequester = {
|
||||||
@@ -726,6 +742,23 @@ async function findWhatsappSenderSid(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function findIncomingNumberSid(client: TwilioSenderListClient, url: string): Promise<string | null> {
|
||||||
|
// Try to locate the underlying phone number and return its SID for webhook fallback.
|
||||||
|
const env = readEnv();
|
||||||
|
const phone = env.whatsappFrom.replace("whatsapp:", "");
|
||||||
|
try {
|
||||||
|
const list = await client.incomingPhoneNumbers.list({ phoneNumber: phone, limit: 2 });
|
||||||
|
if (!list || list.length === 0) return null;
|
||||||
|
if (list.length > 1 && globalVerbose) {
|
||||||
|
console.error(warn("Multiple incoming numbers matched; using the first."));
|
||||||
|
}
|
||||||
|
return list[0]?.sid ?? null;
|
||||||
|
} catch (err) {
|
||||||
|
if (globalVerbose) console.error("incomingPhoneNumbers.list failed", err);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function updateWebhook(
|
async function updateWebhook(
|
||||||
client: ReturnType<typeof createClient>,
|
client: ReturnType<typeof createClient>,
|
||||||
senderSid: string,
|
senderSid: string,
|
||||||
@@ -733,26 +766,42 @@ async function updateWebhook(
|
|||||||
method: "POST" | "GET" = "POST",
|
method: "POST" | "GET" = "POST",
|
||||||
) {
|
) {
|
||||||
// Point Twilio sender webhook at the provided URL.
|
// Point Twilio sender webhook at the provided URL.
|
||||||
await (client as unknown as TwilioRequester)
|
const clientTyped = client as unknown as TwilioSenderListClient;
|
||||||
.request({
|
try {
|
||||||
method: "post",
|
if (clientTyped.messaging?.v2?.channelsSenders) {
|
||||||
uri: `https://messaging.twilio.com/v2/Channels/Senders/${senderSid}`,
|
await clientTyped.messaging.v2.channelsSenders(senderSid).update({
|
||||||
form: {
|
|
||||||
CallbackUrl: url,
|
CallbackUrl: url,
|
||||||
CallbackMethod: method,
|
CallbackMethod: method,
|
||||||
},
|
});
|
||||||
})
|
console.log(success(`✅ Twilio sender webhook set to ${url}`));
|
||||||
.catch((err) => {
|
return;
|
||||||
console.error(danger("Failed to set Twilio webhook."));
|
}
|
||||||
if (globalVerbose) console.error(err);
|
} catch (err) {
|
||||||
console.error(
|
if (globalVerbose)
|
||||||
info(
|
console.error("channelsSenders update failed, will try phone number fallback", err);
|
||||||
"Double-check your sender SID and credentials; you can set TWILIO_SENDER_SID to force a specific sender.",
|
}
|
||||||
),
|
|
||||||
);
|
try {
|
||||||
process.exit(1);
|
const phoneSid = await findIncomingNumberSid(clientTyped, url);
|
||||||
});
|
if (phoneSid) {
|
||||||
console.log(success(`✅ Twilio webhook set to ${url}`));
|
await (clientTyped.incomingPhoneNumbers as any)(phoneSid).update({
|
||||||
|
SmsUrl: url,
|
||||||
|
SmsMethod: method,
|
||||||
|
});
|
||||||
|
console.log(success(`✅ Twilio phone webhook set to ${url}`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
if (globalVerbose) console.error("Incoming number update failed", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error(danger("Failed to set Twilio webhook."));
|
||||||
|
console.error(
|
||||||
|
info(
|
||||||
|
"Double-check your sender SID and credentials; you can set TWILIO_SENDER_SID to force a specific sender.",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function sleep(ms: number) {
|
function sleep(ms: number) {
|
||||||
|
|||||||
Reference in New Issue
Block a user