Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Deploy Cloudflare Worker

on:
push:
branches:
- main

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v3

- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: 18

- name: Install dependencies
run: pnpm install

- name: Build project
run: pnpm run build

- name: Deploy to Cloudflare Workers
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
run: npx wrangler deploy --config=twilio-neon/wrangler.toml
12 changes: 12 additions & 0 deletions deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash

if [ -z "$CF_API_TOKEN" ]; then
echo "Error: CF_API_TOKEN is not set."
exit 1
fi

export CLOUDFLARE_API_TOKEN="$CF_API_TOKEN"
echo "Exported CLOUDFLARE_API_TOKEN from CF_API_TOKEN"

# Run wrangler deploy with your config
pnpm exec wrangler deploy --config=twilio-neon/wrangler.toml
Empty file added twilio-neon/README.md
Empty file.
28 changes: 28 additions & 0 deletions twilio-neon/cloudflare/inbox-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const handler = {
async fetch(request: Request): Promise<Response> {
const form = await request.formData();
const message = (form.get("Body") || "").toString().toLowerCase();
const sender = form.get("From") || "unknown";

let reply = "🤖 Neon Covenant AI: Reply with 'confirm', 'reschedule', or 'help'.";

if (message.includes("confirm")) {
reply = "✅ Delivery confirmed for Dec 1 at 3pm. Thank you.";
} else if (message.includes("reschedule")) {
reply = "📆 Please reply with your new desired delivery time.";
} else if (message.includes("help")) {
reply = "🧙‍♂️ Support: Visit https://help.neoncovenant.com for assistance.";
}

const twiml = `<Response><Message>${reply}</Message></Response>`;

return new Response(twiml, {
headers: {
"Content-Type": "application/xml",
},
});
},
};

export default handler;

24 changes: 24 additions & 0 deletions twilio-neon/dist/inbox-handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const handler = {
async fetch(request) {
const form = await request.formData();
const message = (form.get("Body") || "").toString().toLowerCase();
const sender = form.get("From") || "unknown";
let reply = "🤖 Neon Covenant AI: Reply with 'confirm', 'reschedule', or 'help'.";
if (message.includes("confirm")) {
reply = "✅ Delivery confirmed for Dec 1 at 3pm. Thank you.";
}
else if (message.includes("reschedule")) {
reply = "📆 Please reply with your new desired delivery time.";
}
else if (message.includes("help")) {
reply = "🧙‍♂️ Support: Visit https://help.neoncovenant.com for assistance.";
}
const twiml = `<Response><Message>${reply}</Message></Response>`;
return new Response(twiml, {
headers: {
"Content-Type": "application/xml",
},
});
},
};
export default handler;
28 changes: 28 additions & 0 deletions twilio-neon/git-auto.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash

# Commit message (customize this)
COMMIT_MSG="chore: finalize modularization, add tests, linting, and deploy workflow"

echo "Adding all changes..."
git add .

echo "Committing with message: $COMMIT_MSG"
git commit -m "$COMMIT_MSG"

echo "Pulling remote changes with rebase..."
git pull --rebase origin main

if [ $? -ne 0 ]; then
echo "Rebase failed. Please resolve conflicts, then run 'git rebase --continue'."
exit 1
fi

echo "Pushing commits to origin/main..."
git push origin main

if [ $? -eq 0 ]; then
echo "Push successful! 🎉"
else
echo "Push failed. Check your network or remote repository status."
fi

28 changes: 28 additions & 0 deletions twilio-neon/inbox-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { createTwilioClient } from './twilioClient';
import { generateReply } from './messageProcessor';

export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const { searchParams } = new URL(request.url);
const body = await request.text();

const params = new URLSearchParams(body);
const incomingMsg = params.get('Body') || '';
const from = params.get('From') || '';

const twilio = createTwilioClient(env.TWILIO_SID, env.TWILIO_TOKEN);
const reply = generateReply(incomingMsg);

try {
await twilio.messages.create({
from: env.TO_WHATSAPP_NUMBER,
to: from,
body: reply,
});
} catch (error) {
return new Response('Failed to send message', { status: 500 });
}

return new Response('OK', { status: 200 });
},
};
7 changes: 7 additions & 0 deletions twilio-neon/messageProcessor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export function generateReply(msg: string): string {
msg = msg.toLowerCase();
if (msg.includes('confirm')) return '✅ Confirmed. Thank you!';
if (msg.includes('reschedule')) return '📆 Let us know a new time.';
if (msg.includes('help')) return '🧠 How can we assist you today?';
return '🤖 Message received. A representative will reply shortly.';
}
19 changes: 19 additions & 0 deletions twilio-neon/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "twilio-neon",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"build": "tsc",
"deploy": "wrangler deploy",
"send": "node scripts/send-whatsapp.js"
},
"dependencies": {
"dotenv": "^16.0.0",
"php": "^1.1.0",
"twilio": "^4.0.0"
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20250618.0",
"typescript": "^5.8.3"
}
}
Empty file.
13 changes: 13 additions & 0 deletions twilio-neon/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"outDir": "dist",
"moduleResolution": "Node",
"esModuleInterop": true,
"strict": true,
"skipLibCheck": true
},
"include": ["cloudflare"]
}

5 changes: 5 additions & 0 deletions twilio-neon/twilioClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Twilio } from 'twilio';

export function createTwilioClient(accountSid: string, authToken: string) {
return new Twilio(accountSid, authToken);
}
18 changes: 18 additions & 0 deletions twilio-neon/wrangler.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name = "twilio-neon"
compatibility_date = "2025-06-18"
main = "./dist/index.mjs" # Or wherever your compiled entry point lives

[build]
command = "npm run build"

[vars]
TWILIO_ACCOUNT_SID = "your_sid_here"
TWILIO_AUTH_TOKEN = "your_token_here"
# Add other environment variables here

[triggers]
# Optional: add for Git-based auto deploys, etc.

[env.production]
name = "twilio-neon-prod"
# Add overrides if you need them in production only
Loading