Pepguy commited on
Commit
e70bb3d
·
verified ·
1 Parent(s): d988ffd

Update app.js

Browse files
Files changed (1) hide show
  1. app.js +38 -14
app.js CHANGED
@@ -23,6 +23,7 @@ const log = (tag, ...args) => console.log(`[${new Date().toISOString()}] [${tag}
23
  let pendingCalls = new Map();
24
  let activeLeadIds = new Map();
25
  const incomingCallDebounce = new Map();
 
26
 
27
  // ── MU-LAW VAD ──
28
  const MU_LAW_TABLE = new Int16Array(256);
@@ -111,17 +112,35 @@ app.post("/api/send-sms", async (req, res) => {
111
 
112
  app.post("/dial", async (req, res) => {
113
  const { to, lead_id, action = "manual" } = req.body;
114
- log("DIAL", `Outbound to ${to} (Mode: ${action})`);
 
115
  try {
 
 
 
 
 
 
 
 
 
116
  const response = await fetch("https://api.telnyx.com/v2/calls", {
117
  method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${TELNYX_API_KEY}` },
118
- body: JSON.stringify({ connection_id: TELNYX_CONNECTION_ID, to, from: TELNYX_FROM_NUMBER })
119
  });
 
120
  const data = await response.json();
121
  if (!response.ok) return res.status(400).json({ ok: false, error: data?.errors?.[0]?.detail });
122
 
123
  const ccid = data.data.call_control_id;
124
- pendingCalls.set(ccid, action);
 
 
 
 
 
 
 
125
  if (lead_id) activeLeadIds.set(ccid, lead_id);
126
 
127
  await fetch(`${AI_SERVER_URL}/api/log-outbound`, {
@@ -165,14 +184,15 @@ app.post("/webhook/call", async (req, res) => {
165
  break;
166
 
167
  case "call.answered":
 
168
  if (payload?.client_state) {
169
  const legACallId = Buffer.from(payload.client_state, "base64").toString("ascii");
170
- log("BRIDGING", `Agent picked up! Stopping ringback and Bridging Leg A (${legACallId}) ↔ Leg B (${callId})`);
171
 
172
- // Stop the ringing sound for the customer
173
  await sendTelnyxCmd(legACallId, "playback_stop");
174
 
175
- // Bridge them
176
  await sendTelnyxCmd(callId, "bridge", { call_control_id: legACallId });
177
  break;
178
  }
@@ -181,24 +201,27 @@ app.post("/webhook/call", async (req, res) => {
181
 
182
  await sendTelnyxCmd(callId, "record_start", { format: "mp3", channels: "dual", play_beep: false });
183
 
184
- if (actionType === "manual") {
185
- log("BRIDGING", `Dialing Agent Cell (+2348069234734) for manual takeover...`);
 
 
186
 
187
- // 1. Play ringing to the customer
188
  await sendTelnyxCmd(callId, "playback_start", {
189
  audio_url: "https://actions.telnyx.com/sample-assets/ringback.wav",
190
  target_legs: "self"
191
  });
192
 
193
- // 2. Dial your cell phone
194
- const MY_CELL_NUMBER = "+2347066923490";
195
  await sendTelnyxCmd(null, "dial", {
196
- to: MY_CELL_NUMBER,
197
  from: TELNYX_FROM_NUMBER,
198
  connection_id: TELNYX_CONNECTION_ID,
199
- client_state: Buffer.from(callId).toString("base64")
 
200
  });
201
- } else {
 
202
  log("AI CONNECTING", `Starting stream for ${callId}`);
203
  await sendTelnyxCmd(callId, "playback_start", { audio_url: `http://${req.headers.host}/ambience.mp3`, target_legs: "caller", loop: "infinity" });
204
  await sendTelnyxCmd(callId, "streaming_start", { stream_url: `wss://${req.headers.host}/audio-stream`, stream_track: "inbound_track" });
@@ -236,6 +259,7 @@ app.post("/webhook/call", async (req, res) => {
236
  log("HANGUP", `Call ended. Reason: ${payload.hangup_cause}`);
237
  pendingCalls.delete(callId);
238
  activeLeadIds.delete(callId);
 
239
  await fetch(`${AI_SERVER_URL}/api/call-ended`, {
240
  method: "POST", headers: { "Content-Type": "application/json" },
241
  body: JSON.stringify({ call_control_id: callId })
 
23
  let pendingCalls = new Map();
24
  let activeLeadIds = new Map();
25
  const incomingCallDebounce = new Map();
26
+ const agentDestinations = new Map(); // Stores where to route after Agent answers
27
 
28
  // ── MU-LAW VAD ──
29
  const MU_LAW_TABLE = new Int16Array(256);
 
112
 
113
  app.post("/dial", async (req, res) => {
114
  const { to, lead_id, action = "manual" } = req.body;
115
+ log("DIAL", `Outbound request to ${to} (Mode: ${action})`);
116
+
117
  try {
118
+ let targetNumber = to;
119
+ const MY_CELL_NUMBER = "+2348069234734"; // Your agent number
120
+
121
+ // REVERSE DIALING: If manual, call the agent's cell phone FIRST
122
+ if (action === "manual") {
123
+ targetNumber = MY_CELL_NUMBER;
124
+ log("DIAL", `Reverse dialing: Calling Agent ${MY_CELL_NUMBER} first...`);
125
+ }
126
+
127
  const response = await fetch("https://api.telnyx.com/v2/calls", {
128
  method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${TELNYX_API_KEY}` },
129
+ body: JSON.stringify({ connection_id: TELNYX_CONNECTION_ID, to: targetNumber, from: TELNYX_FROM_NUMBER })
130
  });
131
+
132
  const data = await response.json();
133
  if (!response.ok) return res.status(400).json({ ok: false, error: data?.errors?.[0]?.detail });
134
 
135
  const ccid = data.data.call_control_id;
136
+
137
+ if (action === "manual") {
138
+ pendingCalls.set(ccid, "agent_leg");
139
+ agentDestinations.set(ccid, { to, lead_id }); // Save the lead's number for when you answer
140
+ } else {
141
+ pendingCalls.set(ccid, action);
142
+ }
143
+
144
  if (lead_id) activeLeadIds.set(ccid, lead_id);
145
 
146
  await fetch(`${AI_SERVER_URL}/api/log-outbound`, {
 
184
  break;
185
 
186
  case "call.answered":
187
+ // This block fires when the LEAD finally answers the second leg
188
  if (payload?.client_state) {
189
  const legACallId = Buffer.from(payload.client_state, "base64").toString("ascii");
190
+ log("BRIDGING", `Lead picked up! Stopping ringback and bridging you in instantly...`);
191
 
192
+ // Stop the ringing sound playing in your (the agent's) ear
193
  await sendTelnyxCmd(legACallId, "playback_stop");
194
 
195
+ // Connect you to the lead immediately
196
  await sendTelnyxCmd(callId, "bridge", { call_control_id: legACallId });
197
  break;
198
  }
 
201
 
202
  await sendTelnyxCmd(callId, "record_start", { format: "mp3", channels: "dual", play_beep: false });
203
 
204
+ if (actionType === "agent_leg") {
205
+ // This block fires when YOU answer your cell phone
206
+ const dest = agentDestinations.get(callId);
207
+ log("BRIDGING", `You answered! Now automatically dialing the Lead at ${dest?.to}...`);
208
 
209
+ // Play ringing to you so you know it's dialing the lead
210
  await sendTelnyxCmd(callId, "playback_start", {
211
  audio_url: "https://actions.telnyx.com/sample-assets/ringback.wav",
212
  target_legs: "self"
213
  });
214
 
215
+ // Tell Telnyx to call the lead now
 
216
  await sendTelnyxCmd(null, "dial", {
217
+ to: dest.to,
218
  from: TELNYX_FROM_NUMBER,
219
  connection_id: TELNYX_CONNECTION_ID,
220
+ // We pass your callId so the system knows who to connect the lead to when they answer
221
+ client_state: Buffer.from(callId).toString("base64")
222
  });
223
+
224
+ } else if (actionType === "ai") {
225
  log("AI CONNECTING", `Starting stream for ${callId}`);
226
  await sendTelnyxCmd(callId, "playback_start", { audio_url: `http://${req.headers.host}/ambience.mp3`, target_legs: "caller", loop: "infinity" });
227
  await sendTelnyxCmd(callId, "streaming_start", { stream_url: `wss://${req.headers.host}/audio-stream`, stream_track: "inbound_track" });
 
259
  log("HANGUP", `Call ended. Reason: ${payload.hangup_cause}`);
260
  pendingCalls.delete(callId);
261
  activeLeadIds.delete(callId);
262
+ agentDestinations.delete(callId); // Clean up the map
263
  await fetch(`${AI_SERVER_URL}/api/call-ended`, {
264
  method: "POST", headers: { "Content-Type": "application/json" },
265
  body: JSON.stringify({ call_control_id: callId })