Add claude auto-reply allowlist and verbose hooks
This commit is contained in:
@@ -27,6 +27,7 @@ Small TypeScript CLI to send, monitor, and webhook WhatsApp messages via Twilio.
|
|||||||
- Requires Tailscale Funnel to be enabled for your tailnet/device (admin setting). If it isn’t enabled, the command will exit with instructions; alternatively expose the webhook via your own tunnel and set the Twilio URL manually.
|
- Requires Tailscale Funnel to be enabled for your tailnet/device (admin setting). If it isn’t enabled, the command will exit with instructions; alternatively expose the webhook via your own tunnel and set the Twilio URL manually.
|
||||||
- Polling mode (no webhooks/funnel): `pnpm warelay poll --interval 5 --lookback 10 --verbose`
|
- Polling mode (no webhooks/funnel): `pnpm warelay poll --interval 5 --lookback 10 --verbose`
|
||||||
- Useful fallback if Twilio webhook can’t reach you.
|
- Useful fallback if Twilio webhook can’t reach you.
|
||||||
|
- Still runs config-driven auto-replies (including command-mode/Claude) for new inbound messages.
|
||||||
|
|
||||||
## Config-driven auto-replies
|
## Config-driven auto-replies
|
||||||
|
|
||||||
@@ -51,7 +52,7 @@ Put a JSON5 config at `~/.warelay/warelay.json`. Examples:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
During dev you can run without building: `pnpm dev -- <subcommand>` (e.g. `pnpm dev -- send --to +1...`).
|
During dev you can run without building: `pnpm dev -- <subcommand>` (e.g. `pnpm dev -- send --to +1...`). Auto-replies apply in webhook and polling modes.
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
|
|||||||
16
src/index.ts
16
src/index.ts
@@ -314,6 +314,7 @@ type ReplyMode = "text" | "command";
|
|||||||
|
|
||||||
type WarelayConfig = {
|
type WarelayConfig = {
|
||||||
inbound?: {
|
inbound?: {
|
||||||
|
allowFrom?: string[]; // E.164 numbers allowed to trigger auto-reply (without whatsapp:)
|
||||||
reply?: {
|
reply?: {
|
||||||
mode: ReplyMode;
|
mode: ReplyMode;
|
||||||
text?: string; // for mode=text, can contain {{Body}}
|
text?: string; // for mode=text, can contain {{Body}}
|
||||||
@@ -358,6 +359,18 @@ async function getReplyFromConfig(
|
|||||||
// Choose reply from config: static text or external command stdout.
|
// Choose reply from config: static text or external command stdout.
|
||||||
const cfg = loadConfig();
|
const cfg = loadConfig();
|
||||||
const reply = cfg.inbound?.reply;
|
const reply = cfg.inbound?.reply;
|
||||||
|
|
||||||
|
// Optional allowlist by origin number (E.164 without whatsapp: prefix)
|
||||||
|
const allowFrom = cfg.inbound?.allowFrom;
|
||||||
|
if (Array.isArray(allowFrom) && allowFrom.length > 0) {
|
||||||
|
const from = (ctx.From ?? "").replace(/^whatsapp:/, "");
|
||||||
|
if (!allowFrom.includes(from)) {
|
||||||
|
logVerbose(
|
||||||
|
`Skipping auto-reply: sender ${from || "<unknown>"} not in allowFrom list`,
|
||||||
|
);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!reply) {
|
if (!reply) {
|
||||||
logVerbose("No inbound.reply configured; skipping auto-reply");
|
logVerbose("No inbound.reply configured; skipping auto-reply");
|
||||||
return undefined;
|
return undefined;
|
||||||
@@ -952,7 +965,8 @@ async function monitor(intervalSeconds: number, lookbackMinutes: number) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let keepRunning = true;
|
let keepRunning = true;
|
||||||
process.on("SIGINT", () => {
|
process.once("SIGINT", () => {
|
||||||
|
if (!keepRunning) return;
|
||||||
keepRunning = false;
|
keepRunning = false;
|
||||||
console.log("\n👋 Stopping monitor");
|
console.log("\n👋 Stopping monitor");
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user