Skip to content

Commit 22715e1

Browse files
author
nataliehuynh
authored
Merge pull request #22 from aymenn/service-tests
Service tests
2 parents 513c984 + 8c02e8e commit 22715e1

File tree

11 files changed

+426
-72
lines changed

11 files changed

+426
-72
lines changed

src/@types/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,9 @@ export interface JoinConferenceParams extends Request {
3636
params: {
3737
conferenceName: string
3838
}
39+
}
40+
41+
export interface ParticipantToDial {
42+
address: string,
43+
proxyAddress: string
3944
}

src/services/inboundCall.service.ts

Lines changed: 14 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
import client from '../twilioClient'
12
import VoiceResponse from "twilio/lib/twiml/VoiceResponse";
23

3-
import { getConversationByAddressPair } from "../utils/getConversationByAddressPair.util";
4-
5-
import client from '../twilioClient'
4+
import {
5+
getConversationByAddressPair,
6+
participantsToDial,
7+
listConversationParticipants,
8+
generateConferenceName
9+
} from "../utils/";
610

711
export const generateTwiml = async (from: string, to: string) => {
812
let response = new VoiceResponse();
@@ -16,33 +20,18 @@ export const generateTwiml = async (from: string, to: string) => {
1620
language: process.env.CALL_ANNOUCEMENT_LANGUAGE as any,
1721
}, process.env.OUT_OF_SESSION_MESSAGE_FOR_CALL);
1822
} 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-
}, [])
23+
const participants = await listConversationParticipants(conversation.conversationSid)
24+
const dialList = participantsToDial(participants, from)
3625

3726
response.say({
3827
voice: process.env.CALL_ANNOUCEMENT_VOICE as any,
3928
language: process.env.CALL_ANNOUCEMENT_LANGUAGE as any
4029
}, process.env.CONNECTING_CALL_ANNOUCEMENT);
4130

42-
if (participantsToDial.length > 1) {
43-
const conferenceName = `${from}_at_${Date.now()}`
31+
if (dialList.length > 1) {
32+
const conferenceName = generateConferenceName(from)
4433

45-
const callPromises = participantsToDial.map(pa => {
34+
const callPromises = dialList.map(pa => {
4635
console.log(`Dialing ${pa.address} from ${pa.proxyAddress}...`);
4736

4837
return client.calls.create({
@@ -52,28 +41,20 @@ export const generateTwiml = async (from: string, to: string) => {
5241
});
5342
});
5443

55-
try {
56-
await Promise.all(callPromises)
57-
} catch(err) {
58-
console.log(err)
59-
throw new Error(err)
60-
}
44+
await Promise.all(callPromises)
6145

6246
const dial = response.dial();
6347
dial.conference({
6448
endConferenceOnExit: true
6549
}, conferenceName);
66-
67-
6850
} else {
69-
const callee = participantsToDial[0]
51+
const callee = dialList[0]
7052
const dial = response.dial({
7153
callerId: callee.proxyAddress
7254
});
7355

7456
dial.number(callee.address);
7557
}
76-
7758
}
7859

7960
return response;

src/services/session.service.ts

Lines changed: 5 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import { type } from "os";
12
import { ActiveProxyAddresses, ProxyBindings } from "../@types/types";
2-
import { listParticipantConversations, addParticipant } from "../utils";
3+
import { listParticipantConversations, retryAddParticipant } from "../utils";
34

45
export const getActiveProxyAddresses = async (phoneNumbers: Array<String>) : Promise<ActiveProxyAddresses> => {
56
let activeConversations = {}
@@ -49,46 +50,12 @@ export const matchAvailableProxyAddresses = async (activeProxyAddresses: ActiveP
4950
}
5051
}
5152

52-
const retryParticipantAdd = async (conversationSid: string, participantAddress: string, proxyAddresses: Array<string>) => {
53-
try {
54-
while(proxyAddresses.length > 0) {
55-
try {
56-
const participant = {
57-
'messagingBinding.address': participantAddress,
58-
'messagingBinding.proxyAddress': proxyAddresses[0]
59-
} as any
60-
61-
return addParticipant(conversationSid, participant)
62-
63-
} catch(err) {
64-
if (err.code === 50416) {
65-
const remainingProxyAddresses = proxyAddresses.shift()
66-
retryParticipantAdd(conversationSid, participantAddress, remainingProxyAddresses as any)
67-
}
68-
console.log(err)
69-
throw new Error(err)
70-
}
71-
}
72-
73-
throw new Error(`No proxy addresses available for ${participantAddress}`)
74-
} catch(err) {
75-
console.log(err)
76-
throw new Error(err)
77-
}
78-
}
79-
8053
export const addParticipantsToConversation = async (conversationSid: string, proxyBindings: ProxyBindings) => {
8154
const promises = []
82-
55+
8356
for (const [participantAddress, proxyAddresses] of Object.entries(proxyBindings)) {
84-
85-
try {
86-
const participantAttempt = retryParticipantAdd(conversationSid, participantAddress, proxyAddresses)
87-
promises.push(participantAttempt)
88-
} catch (err) {
89-
console.log(err)
90-
throw new Error(err)
91-
}
57+
const participantAttempt = retryAddParticipant(conversationSid, participantAddress, proxyAddresses)
58+
promises.push(participantAttempt)
9259
}
9360

9461
try {
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const generateConferenceName = (phoneNumber: string) : string => {
2+
return encodeURIComponent(`${phoneNumber}_at_${Date.now()}`)
3+
}

src/utils/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
export * from "./addParticipant.util";
22
export * from "./createConversation.util";
33
export * from "./deleteConversation.util";
4-
export * from "./listParticipantConversations.util"
4+
export * from "./listParticipantConversations.util"
5+
export * from "./retryAddParticipant.util"
6+
export * from "./listConversationParticipants.util"
7+
export * from "./participantsToDial.util"
8+
export * from "./getConversationByAddressPair.util"
9+
export * from "./generateConferenceName.util"
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import retry from 'async-retry'
2+
import { ParticipantInstance } from 'twilio/lib/rest/conversations/v1/conversation/participant'
3+
import client from '../twilioClient'
4+
5+
export const listConversationParticipants = async (conversation: string) : Promise<ParticipantInstance[]> => {
6+
return retry(async (quit) => {
7+
try {
8+
const participants = await client.conversations
9+
.conversations(conversation)
10+
.participants
11+
.list()
12+
13+
return participants
14+
} catch (err) {
15+
if (err.status !== 429) {
16+
quit(new Error(err));
17+
return;
18+
}
19+
20+
console.log('Re-trying on 429 error');
21+
throw new Error(err);
22+
}
23+
})
24+
25+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { ParticipantInstance } from "twilio/lib/rest/conversations/v1/conversation/participant";
2+
import { ParticipantToDial } from "../@types/types";
3+
4+
export const participantsToDial = (participants: Array<ParticipantInstance>, from: string) : ParticipantToDial[] => {
5+
6+
const output = participants.reduce((result, p) => {
7+
if (p.messagingBinding.type === "sms" && p.messagingBinding.address != from) {
8+
console.log(`Adding ${p.messagingBinding.address} to list of numbers to dial.\n`)
9+
10+
result.push({
11+
address: p.messagingBinding.address,
12+
proxyAddress: p.messagingBinding.proxy_address
13+
})
14+
}
15+
16+
return result;
17+
}, [])
18+
19+
return output;
20+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { addParticipant } from "./addParticipant.util"
2+
3+
export const retryAddParticipant = async (conversationSid: string, participantAddress: string, proxyAddresses: Array<string>) => {
4+
try {
5+
while(proxyAddresses.length > 0) {
6+
try {
7+
const participant = {
8+
'messagingBinding.address': participantAddress,
9+
'messagingBinding.proxyAddress': proxyAddresses[0]
10+
} as any
11+
12+
return addParticipant(conversationSid, participant)
13+
14+
} catch(err) {
15+
if (err.code === 50416) {
16+
const remainingProxyAddresses = proxyAddresses.shift()
17+
retryAddParticipant(conversationSid, participantAddress, remainingProxyAddresses as any)
18+
}
19+
console.log(err)
20+
throw new Error(err)
21+
}
22+
}
23+
24+
throw new Error(`No proxy addresses available for ${participantAddress}`)
25+
} catch(err) {
26+
console.log(err)
27+
throw new Error(err)
28+
}
29+
}

0 commit comments

Comments
 (0)