Skip to content

Commit

Permalink
feat: 🎸 add pick up call feature (#49)
Browse files Browse the repository at this point in the history
* feat: 🎸 add pick up call feature

* fix typo

* remove
  • Loading branch information
Hazyzh authored Sep 28, 2022
1 parent c99fa21 commit b603e05
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 11 deletions.
72 changes: 66 additions & 6 deletions src/RingCentralCall.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
import { EventEmitter } from 'events';
import { SDK as RingCentralSDK } from '@ringcentral/sdk';
import { Subscriptions as RingCentralSubscriptions } from '@ringcentral/subscriptions';
import {
Extension,
RingCentralCallControl,
} from 'ringcentral-call-control';
import RingCentralWebPhone from 'ringcentral-web-phone';
import { WebPhoneSession } from 'ringcentral-web-phone/lib/session';
import { InviteOptions, ActiveCallInfo as ActiveCallInfoBase } from 'ringcentral-web-phone/lib/userAgent';
import { RingCentralCallControl, Extension } from 'ringcentral-call-control';
import { Session, events as sessionEvents, directions } from './Session';
import { USER_AGENT } from './userAgent';
import {
ActiveCallInfo as ActiveCallInfoBase,
InviteOptions,
} from 'ringcentral-web-phone/lib/userAgent';

import { SDK as RingCentralSDK } from '@ringcentral/sdk';
import {
Subscriptions as RingCentralSubscriptions,
} from '@ringcentral/subscriptions';

import {
directions,
events as sessionEvents,
Session,
} from './Session';
import { USER_AGENT } from './userAgent';
import { extractHeadersData } from './utils';

export interface MakeCallParams {
Expand All @@ -34,6 +47,17 @@ export interface ActiveCallInfo extends ActiveCallInfoBase {
telephonySessionId: string;
}

export interface IPickUpCallParams {
sessionId: string;
toNumber: string;
fromNumber: string;
serverId: string;
telephonySessionId: string;
sessionDescriptionHandlerOptions: {
constraints?: { audio: boolean, video: boolean }
}
}

export const SUBSCRIPTION_CACHE_KEY = 'rc-call-subscription-key';

export class RingCentralCall extends EventEmitter {
Expand Down Expand Up @@ -119,6 +143,42 @@ export class RingCentralCall extends EventEmitter {
return this._onNewTelephonySession(telephonySession);
}

async pickupInboundCall({
sessionId,
toNumber,
fromNumber,
serverId,
telephonySessionId,
sessionDescriptionHandlerOptions
}: IPickUpCallParams) {
if (!this.webphone) {
throw new Error('Web phone instance is required');
}
if (!this.webphoneRegistered) {
throw new Error('webphone is not registered');
}
const session = this.sessions.find(s => s.id === telephonySessionId);
if (!session) {
throw new Error('call session was not found');
}
const extraHeaders = [
`RC-call-type: inbound-pickup; session-id: ${sessionId}; server-id: ${serverId}`,
];
const inviteOptions = {
sessionDescriptionHandlerOptions,
fromNumber,
extraHeaders,
};
this._webphoneInviteFromSDK = true;
const webphoneSession =
this._webphone &&
this._webphone.userAgent.invite(toNumber, inviteOptions);
session.setWebphoneSession(webphoneSession);
this._webphoneInviteFromSDK = false;
this.emit(events.WEBPHONE_INVITE_SENT, webphoneSession);
return session;
}

_onNewWebPhoneSession(webphoneSession) {
const newSession = new Session({
webphoneSession,
Expand Down
81 changes: 76 additions & 5 deletions test/ringcentral-call.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import { RingCentralCall } from '../src/index';
import { events, SUBSCRIPTION_CACHE_KEY } from '../src/RingCentralCall';
import { directions, events as sessionEvents } from '../src/Session';
import {
events,
SUBSCRIPTION_CACHE_KEY,
} from '../src/RingCentralCall';
import {
directions,
events as sessionEvents,
} from '../src/Session';
import RingCentral from './__mocks__/ringcentral';
import {
Session as TelephonySession,
} from './__mocks__/ringcentral-call-control/lib/Session';
import RingCentralWebPhone from './__mocks__/ringcentral-web-phone';
import { WebPhoneSession } from './__mocks__/ringcentral-web-phone/lib/Session';
import { Session as TelephonySession } from './__mocks__/ringcentral-call-control/lib/Session';
import RingCentral from './__mocks__/ringcentral';
import Subscriptions from './__mocks__/subscriptions';
import { resolve } from 'path';

let rcCall;
let webphone;
Expand All @@ -19,6 +26,23 @@ function timeout(ms) {
});
}

const pickupCallParams = {
"fromNumber": "+18006245555",
"partyId": "p-a4a0d82341f0ez18381c9e55dz38b20000-2",
"serverId": "10.74.13.130.TAM",
"sessionId": "35063587004",
"telephonySessionId": "s-a4a0d82341f0ez18381c9e55dz38b20000",
"toNumber": "+18632152222",
"sessionDescriptionHandlerOptions": {
"constraints": {
"audio": {
"deviceId": "default"
},
"video": false
}
}
}

describe('RingCentral Call ::', () => {
describe('Enable subscription', () => {
beforeEach(() => {
Expand Down Expand Up @@ -84,6 +108,43 @@ describe('RingCentral Call ::', () => {
expect(hasError).toEqual(true);
});

test('should pickup call fail with web phone unregistered', async () => {
let hasError = false
try {
const session = await rcCall.pickupInboundCall(pickupCallParams);
} catch (e) {
hasError = true
}
expect(hasError).toEqual(true);
});

test('should pickup call fail when can not found rc call sessions', async () => {
webphone.userAgent.trigger('registered')
let hasError = false
try {
const session = await rcCall.pickupInboundCall(pickupCallParams);
} catch (e) {
hasError = true
}
expect(hasError).toEqual(true);
});


test('should pickup call succeed', async () => {
webphone.userAgent.trigger('registered');
const telephonySession = new TelephonySession({
id: pickupCallParams.telephonySessionId,
toNumber: pickupCallParams.toNumber,
fromNumber: pickupCallParams.fromNumber,
direction: directions.INBOUND,
});
rcCall.callControl.trigger('new', telephonySession);
expect(rcCall.sessions.length).toEqual(1);
expect(rcCall.sessions[0].webphoneSession).not.toBeDefined();
const session = await rcCall.pickupInboundCall(pickupCallParams);
expect(rcCall.sessions.length).toEqual(1);
expect(rcCall.sessions[0].webphoneSession).toBeDefined();
});
test('should make call successfully with web phone mode', async () => {
webphone.userAgent.trigger('registered')
const session = await rcCall.makeCall(
Expand Down Expand Up @@ -422,6 +483,16 @@ describe('RingCentral Call ::', () => {
expect(error).toEqual('Web phone instance is required');
});

test('should alert message when pickup call without webphone mode', async () => {
let error = null;
try {
const session = await rcCall.pickupInboundCall(pickupCallParams);
} catch (e) {
error = e.message;
}
expect(error).toEqual('Web phone instance is required');
});

test('should call switchCallFromActiveCall fail when no web phone', () => {
let error;
try {
Expand Down

0 comments on commit b603e05

Please sign in to comment.