Skip to content

Commit 3644230

Browse files
committed
Merge branch 'master' of github.com:aymenn/masked-comms-app into tests
2 parents c54fb5c + c532ef9 commit 3644230

19 files changed

+253
-153
lines changed

.env.example

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ NUMBER_POOL=["+1234567890","+2345678901"]
44
CALL_ANNOUCEMENT_VOICE=
55
CALL_ANNOUCEMENT_LANGUAGE=
66
OUT_OF_SESSION_MESSAGE_FOR_CALL=
7-
CONNECTING_CALL_ANNOUCEMENT=
7+
CONNECTING_CALL_ANNOUCEMENT=
8+
DOMAIN=

index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import express from "express";
33
import createError from "http-errors";
44
import logger from "morgan";
55
import router from "./src/routes";
6+
import bodyParser from 'body-parser';
67

78
const PORT = process.env.PORT || 3000;
89

@@ -16,6 +17,7 @@ if (app.get("env") === "development") {
1617
app.use(logger("dev"));
1718
}
1819

20+
app.use(bodyParser.json())
1921
app.use(express.json());
2022
app.use(express.urlencoded({ extended: true }));
2123

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"dependencies": {
33
"async-retry": "^1.3.3",
4+
"body-parser": "^1.20.0",
45
"cors": "^2.8.5",
56
"dotenv": "^16.0.1",
67
"express": "^4.18.1",

src/@types/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ export interface ConversationsPostEventBody {
2020
}
2121

2222
export interface ActiveProxyAddresses {
23-
[key: string]: Array<string>;
23+
[key: string]: Array<String>;
2424
}
2525

2626
export interface ProxyBindings {
27-
[key: string]: string;
27+
[key: string]: Array<string>;
2828
}
2929

3030
export interface ConversationParticipant {

src/controllers/conversationsPreEvent.ts

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/controllers/inboundCall.ts

Lines changed: 4 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,14 @@
11
import type { Request, Response } from "express";
2-
import VoiceResponse from "twilio/lib/twiml/VoiceResponse";
3-
4-
import { getConversationByAddressPair } from "../utils/getConversationByAddressPair.util";
5-
6-
import client from '../twilioClient'
7-
8-
const generateTwiml = async (to: string, from: string) => {
9-
let response = new VoiceResponse();
10-
11-
const conversation = await getConversationByAddressPair(from, to)
12-
13-
if (!conversation) {
14-
console.log(`No active session (conversation) for ${from}.`)
15-
response.say({
16-
voice: process.env.CALL_ANNOUCEMENT_VOICE as any,
17-
language: process.env.CALL_ANNOUCEMENT_LANGUAGE as any,
18-
}, process.env.OUT_OF_SESSION_MESSAGE_FOR_CALL);
19-
} else {
20-
const participants = await client.conversations
21-
.conversations(conversation.conversationSid)
22-
.participants
23-
.list()
24-
25-
const participantsToDial = participants.reduce((result, p) => {
26-
if (p.messagingBinding.type === "sms" && p.messagingBinding.address != from) {
27-
console.log(`Adding ${p.messagingBinding.address} to list of numbers to dial.\n`)
28-
29-
result.push({
30-
address: p.messagingBinding.address,
31-
proxyAddress: p.messagingBinding.proxy_address
32-
})
33-
}
34-
35-
return result;
36-
}, [])
37-
38-
response.say({
39-
voice: process.env.CALL_ANNOUCEMENT_VOICE as any,
40-
language: process.env.CALL_ANNOUCEMENT_LANGUAGE as any
41-
}, process.env.CONNECTING_CALL_ANNOUCEMENT);
42-
43-
if (participantsToDial.length > 1) {
44-
const conferenceName = `${from}_at_${Date.now()}`
45-
46-
const callPromises = participantsToDial.map(pa => {
47-
console.log(`Dialing ${pa.address} from ${pa.proxyAddress}...`);
48-
49-
return client.calls.create({
50-
url: `https://${process.env.DOMAIN}/join-conference?conferenceName=${encodeURIComponent(conferenceName)}`,
51-
to: pa.address,
52-
from: pa.proxyAddress
53-
});
54-
});
55-
56-
await Promise.all(callPromises)
57-
58-
const dial = response.dial();
59-
dial.conference({
60-
endConferenceOnExit: true
61-
}, conferenceName);
62-
63-
64-
} else {
65-
const callee = participantsToDial[0]
66-
const dial = response.dial({
67-
callerId: callee.messagingBinding.proxy_address
68-
});
69-
70-
dial.number(callee.messagingBinding.address);
71-
}
72-
73-
}
74-
75-
return response;
76-
77-
}
2+
import { generateTwiml } from "../services/inboundCall.service";
783

794
export const post = async (
805
req: Request,
816
res: Response
827
) => {
83-
const { body } = req.body;
84-
const { to, from } = body;
8+
const from = req.body.From
9+
const to = req.body.Called
8510

86-
const twiml = await generateTwiml(to, from);
11+
const twiml = await generateTwiml(from, to);
8712

8813
res.set('Content-Type', 'text/xml')
8914
res.send(twiml.toString())

src/controllers/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
export * as conversationsPostEvent from "./conversationsPostEvent";
2-
export * as conversationsPreEvent from "./conversationsPreEvent";
32
export * as inboundCall from "./inboundCall";
43
export * as session from "./session";
54
export * as joinConference from "./joinConference"

src/controllers/session.ts

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,24 @@ export const post = async (
1212
req: Request<{}, {}, SessionPostBody>,
1313
res: Response
1414
) => {
15-
console.log(req.body);
16-
const phoneNumbers = req.body.addresses;
17-
const activeProxyAddresses = await getActiveProxyAddresses(phoneNumbers);
18-
const proxyAddresses = await matchAvailableProxyAddresses(activeProxyAddresses);
19-
const conversation = await createConversation(req.body)
2015

2116
try {
22-
await addParticipantsToConversation(conversation.sid, proxyAddresses)
23-
res.setHeader('content-type', 'application/json');
24-
console.log(conversation)
25-
return res.status(200).send(`${JSON.stringify(conversation)}`);
17+
const phoneNumbers = req.body.addresses;
18+
const activeProxyAddresses = await getActiveProxyAddresses(phoneNumbers);
19+
const proxyAddresses = await matchAvailableProxyAddresses(activeProxyAddresses);
20+
const conversation = await createConversation(req.body)
21+
22+
try {
23+
await addParticipantsToConversation(conversation.sid, proxyAddresses)
24+
res.setHeader('content-type', 'application/json');
25+
return res.status(200).send(`${JSON.stringify(conversation)}`);
26+
} catch(err) {
27+
await deleteConversation(conversation.sid);
28+
return res.status(500).send(`${conversation.sid} failed to create session: ${err}`)
29+
}
30+
2631
} catch(err) {
27-
await deleteConversation(conversation.sid);
28-
return res.status(500).send(`${conversation.sid} failed to create session: ${err}`)
29-
}
32+
return res.status(500).send(`Failed to create session: ${err}`)
33+
}
34+
3035
};

src/routes/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import * as controllers from "../controllers";
33

44
const router = Router();
55

6-
router.post("/conversations-pre-event", controllers.conversationsPreEvent.post);
76
router.post("/conversations-post-event", controllers.conversationsPostEvent.post);
87

98
router.post("/inbound-call", controllers.inboundCall.post);
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import VoiceResponse from "twilio/lib/twiml/VoiceResponse";
2+
3+
import { getConversationByAddressPair } from "../utils/getConversationByAddressPair.util";
4+
5+
import client from '../twilioClient'
6+
7+
export const generateTwiml = async (from: string, to: string) => {
8+
let response = new VoiceResponse();
9+
10+
const conversation = await getConversationByAddressPair(from, to)
11+
12+
if (!conversation) {
13+
console.log(`No active session (conversation) for ${from}.`)
14+
response.say({
15+
voice: process.env.CALL_ANNOUCEMENT_VOICE as any,
16+
language: process.env.CALL_ANNOUCEMENT_LANGUAGE as any,
17+
}, process.env.OUT_OF_SESSION_MESSAGE_FOR_CALL);
18+
} else {
19+
const participants = await client.conversations
20+
.conversations(conversation.conversationSid)
21+
.participants
22+
.list()
23+
24+
const participantsToDial = participants.reduce((result, p) => {
25+
if (p.messagingBinding.type === "sms" && p.messagingBinding.address != from) {
26+
console.log(`Adding ${p.messagingBinding.address} to list of numbers to dial.\n`)
27+
28+
result.push({
29+
address: p.messagingBinding.address,
30+
proxyAddress: p.messagingBinding.proxy_address
31+
})
32+
}
33+
34+
return result;
35+
}, [])
36+
37+
response.say({
38+
voice: process.env.CALL_ANNOUCEMENT_VOICE as any,
39+
language: process.env.CALL_ANNOUCEMENT_LANGUAGE as any
40+
}, process.env.CONNECTING_CALL_ANNOUCEMENT);
41+
42+
if (participantsToDial.length > 1) {
43+
const conferenceName = `${from}_at_${Date.now()}`
44+
45+
const callPromises = participantsToDial.map(pa => {
46+
console.log(`Dialing ${pa.address} from ${pa.proxyAddress}...`);
47+
48+
return client.calls.create({
49+
url: `https://${process.env.DOMAIN}/join-conference?conferenceName=${encodeURIComponent(conferenceName)}`,
50+
to: pa.address,
51+
from: pa.proxyAddress
52+
});
53+
});
54+
55+
try {
56+
await Promise.all(callPromises)
57+
} catch(err) {
58+
console.log(err)
59+
throw new Error(err)
60+
}
61+
62+
const dial = response.dial();
63+
dial.conference({
64+
endConferenceOnExit: true
65+
}, conferenceName);
66+
67+
68+
} else {
69+
const callee = participantsToDial[0]
70+
const dial = response.dial({
71+
callerId: callee.proxyAddress
72+
});
73+
74+
dial.number(callee.address);
75+
}
76+
77+
}
78+
79+
return response;
80+
}

0 commit comments

Comments
 (0)