livekit-server-sdk
Version:
Server-side SDK for LiveKit
428 lines (393 loc) • 12.8 kB
text/typescript
// SPDX-FileCopyrightText: 2024 LiveKit, Inc.
//
// SPDX-License-Identifier: Apache-2.0
import {
CreateSIPDispatchRuleRequest,
CreateSIPInboundTrunkRequest,
CreateSIPOutboundTrunkRequest,
CreateSIPParticipantRequest,
CreateSIPTrunkRequest,
DeleteSIPDispatchRuleRequest,
DeleteSIPTrunkRequest,
ListSIPDispatchRuleRequest,
ListSIPDispatchRuleResponse,
ListSIPInboundTrunkRequest,
ListSIPInboundTrunkResponse,
ListSIPOutboundTrunkRequest,
ListSIPOutboundTrunkResponse,
ListSIPTrunkRequest,
ListSIPTrunkResponse,
SIPDispatchRule,
SIPDispatchRuleDirect,
SIPDispatchRuleIndividual,
SIPDispatchRuleInfo,
SIPInboundTrunkInfo,
SIPOutboundTrunkInfo,
SIPParticipantInfo,
SIPTransport,
SIPTrunkInfo,
} from '@livekit/protocol';
import ServiceBase from './ServiceBase.js';
import { Rpc, TwirpRpc, livekitPackage } from './TwirpRPC.js';
const svc = 'SIP';
/**
* @deprecated use CreateSipInboundTrunkOptions or CreateSipOutboundTrunkOptions
*/
export interface CreateSipTrunkOptions {
name?: string;
metadata?: string;
inbound_addresses?: string[];
inbound_numbers?: string[];
inbound_username?: string;
inbound_password?: string;
outbound_address?: string;
outbound_username?: string;
outbound_password?: string;
}
export interface CreateSipInboundTrunkOptions {
metadata?: string;
allowed_addresses?: string[];
allowed_numbers?: string[];
auth_username?: string;
auth_password?: string;
}
export interface CreateSipOutboundTrunkOptions {
metadata?: string;
transport: SIPTransport;
auth_username?: string;
auth_password?: string;
}
export interface SipDispatchRuleDirect {
type: 'direct';
roomName: string;
pin?: string;
}
export interface SipDispatchRuleIndividual {
type: 'individual';
roomPrefix: string;
pin?: string;
}
export interface CreateSipDispatchRuleOptions {
name?: string;
metadata?: string;
trunkIds?: string[];
hidePhoneNumber?: boolean;
}
export interface CreateSipParticipantOptions {
participantIdentity?: string;
participantName?: string;
participantMetadata?: string;
dtmf?: string;
playRingtone?: boolean;
hidePhoneNumber?: boolean;
}
/**
* Client to access Egress APIs
*/
export class SipClient extends ServiceBase {
private readonly rpc: Rpc;
/**
* @param host hostname including protocol. i.e. 'https://cluster.livekit.io'
* @param apiKey API Key, can be set in env var LIVEKIT_API_KEY
* @param secret API Secret, can be set in env var LIVEKIT_API_SECRET
*/
constructor(host: string, apiKey?: string, secret?: string) {
super(apiKey, secret);
this.rpc = new TwirpRpc(host, livekitPackage);
}
/**
* @param number phone number of the trunk
* @param opts CreateSipTrunkOptions
* @deprecated use createSipInboundTrunk or createSipOutboundTrunk
*/
async createSipTrunk(number: string, opts?: CreateSipTrunkOptions): Promise<SIPTrunkInfo> {
let inboundAddresses: string[] | undefined;
let inboundNumbers: string[] | undefined;
let inboundUsername: string = '';
let inboundPassword: string = '';
let outboundAddress: string = '';
let outboundUsername: string = '';
let outboundPassword: string = '';
let name: string = '';
let metadata: string = '';
if (opts !== undefined) {
inboundAddresses = opts.inbound_addresses;
inboundNumbers = opts.inbound_numbers;
inboundUsername = opts.inbound_username || '';
inboundPassword = opts.inbound_password || '';
outboundAddress = opts.outbound_address || '';
outboundUsername = opts.outbound_username || '';
outboundPassword = opts.outbound_password || '';
name = opts.name || '';
metadata = opts.metadata || '';
}
const req = new CreateSIPTrunkRequest({
name: name,
metadata: metadata,
inboundAddresses: inboundAddresses,
inboundNumbers: inboundNumbers,
inboundUsername: inboundUsername,
inboundPassword: inboundPassword,
outboundNumber: number,
outboundAddress: outboundAddress,
outboundUsername: outboundUsername,
outboundPassword: outboundPassword,
}).toJson();
const data = await this.rpc.request(
svc,
'CreateSIPTrunk',
req,
await this.authHeader({}, { admin: true }),
);
return SIPTrunkInfo.fromJson(data, { ignoreUnknownFields: true });
}
/**
@param name human-readable name of the trunk
* @param numbers phone numbers of the trunk
* @param opts CreateSipTrunkOptions
*/
async createSipInboundTrunk(
name: string,
numbers: string[],
opts?: CreateSipInboundTrunkOptions,
): Promise<SIPInboundTrunkInfo> {
let allowedAddresses: string[] | undefined;
let allowedNumbers: string[] | undefined;
let authUsername: string = '';
let authPassword: string = '';
let metadata: string = '';
if (opts !== undefined) {
allowedAddresses = opts.allowed_addresses;
allowedNumbers = opts.allowed_numbers;
authUsername = opts.auth_username || '';
authPassword = opts.auth_password || '';
metadata = opts.metadata || '';
}
const req = new CreateSIPInboundTrunkRequest({
trunk: new SIPInboundTrunkInfo({
name: name,
numbers: numbers,
metadata: metadata,
allowedAddresses: allowedAddresses,
allowedNumbers: allowedNumbers,
authUsername: authUsername,
authPassword: authPassword,
}),
}).toJson();
const data = await this.rpc.request(
svc,
'CreateSIPInboundTrunk',
req,
await this.authHeader({}, { admin: true }),
);
return SIPInboundTrunkInfo.fromJson(data, { ignoreUnknownFields: true });
}
/**
* @param name human-readable name of the trunk
* @param address hostname and port of the SIP server to dial
* @param numbers phone numbers of the trunk
* @param opts CreateSipTrunkOptions
*/
async createSipOutboundTrunk(
name: string,
address: string,
numbers: string[],
opts?: CreateSipOutboundTrunkOptions,
): Promise<SIPOutboundTrunkInfo> {
let authUsername: string = '';
let authPassword: string = '';
let transport: SIPTransport = SIPTransport.SIP_TRANSPORT_AUTO;
let metadata: string = '';
if (opts !== undefined) {
authUsername = opts.auth_username || '';
authPassword = opts.auth_password || '';
transport = opts.transport || SIPTransport.SIP_TRANSPORT_AUTO;
metadata = opts.metadata || '';
}
const req = new CreateSIPOutboundTrunkRequest({
trunk: new SIPOutboundTrunkInfo({
name: name,
address: address,
numbers: numbers,
metadata: metadata,
transport: transport,
authUsername: authUsername,
authPassword: authPassword,
}),
}).toJson();
const data = await this.rpc.request(
svc,
'CreateSIPOutboundTrunk',
req,
await this.authHeader({}, { admin: true }),
);
return SIPOutboundTrunkInfo.fromJson(data, { ignoreUnknownFields: true });
}
/**
* @deprecated use listSipInboundTrunk or listSipOutboundTrunk
*/
async listSipTrunk(): Promise<Array<SIPTrunkInfo>> {
const req: Partial<ListSIPTrunkRequest> = {};
const data = await this.rpc.request(
svc,
'ListSIPTrunk',
new ListSIPTrunkRequest(req).toJson(),
await this.authHeader({}, { admin: true }),
);
return ListSIPTrunkResponse.fromJson(data, { ignoreUnknownFields: true }).items ?? [];
}
async listSipInboundTrunk(): Promise<Array<SIPInboundTrunkInfo>> {
const req: Partial<ListSIPInboundTrunkRequest> = {};
const data = await this.rpc.request(
svc,
'ListSIPInboundTrunk',
new ListSIPInboundTrunkRequest(req).toJson(),
await this.authHeader({}, { admin: true }),
);
return ListSIPInboundTrunkResponse.fromJson(data, { ignoreUnknownFields: true }).items ?? [];
}
async listSipOutboundTrunk(): Promise<Array<SIPOutboundTrunkInfo>> {
const req: Partial<ListSIPOutboundTrunkRequest> = {};
const data = await this.rpc.request(
svc,
'ListSIPOutboundTrunk',
new ListSIPOutboundTrunkRequest(req).toJson(),
await this.authHeader({}, { admin: true }),
);
return ListSIPOutboundTrunkResponse.fromJson(data, { ignoreUnknownFields: true }).items ?? [];
}
/**
* @param sipTrunkId sip trunk to delete
*/
async deleteSipTrunk(sipTrunkId: string): Promise<SIPTrunkInfo> {
const data = await this.rpc.request(
svc,
'DeleteSIPTrunk',
new DeleteSIPTrunkRequest({ sipTrunkId }).toJson(),
await this.authHeader({}, { admin: true }),
);
return SIPTrunkInfo.fromJson(data, { ignoreUnknownFields: true });
}
/**
* @param rule sip dispatch rule
* @param opts CreateSipDispatchRuleOptions
*/
async createSipDispatchRule(
rule: SipDispatchRuleDirect | SipDispatchRuleIndividual,
opts?: CreateSipDispatchRuleOptions,
): Promise<SIPDispatchRuleInfo> {
let trunkIds: string[] | undefined;
let hidePhoneNumber: boolean = false;
let name: string = '';
let metadata: string = '';
let ruleProto: SIPDispatchRule | undefined = undefined;
if (opts !== undefined) {
trunkIds = opts.trunkIds;
hidePhoneNumber = opts.hidePhoneNumber || false;
name = opts.name || '';
metadata = opts.metadata || '';
}
if (rule.type == 'direct') {
ruleProto = new SIPDispatchRule({
rule: {
case: 'dispatchRuleDirect',
value: new SIPDispatchRuleDirect({
roomName: rule.roomName,
pin: rule.pin || '',
}),
},
});
} else if (rule.type == 'individual') {
ruleProto = new SIPDispatchRule({
rule: {
case: 'dispatchRuleIndividual',
value: new SIPDispatchRuleIndividual({
roomPrefix: rule.roomPrefix,
pin: rule.pin || '',
}),
},
});
}
const req = new CreateSIPDispatchRuleRequest({
rule: ruleProto,
trunkIds: trunkIds,
hidePhoneNumber: hidePhoneNumber,
name: name,
metadata: metadata,
}).toJson();
const data = await this.rpc.request(
svc,
'CreateSIPDispatchRule',
req,
await this.authHeader({}, { admin: true }),
);
return SIPDispatchRuleInfo.fromJson(data, { ignoreUnknownFields: true });
}
async listSipDispatchRule(): Promise<Array<SIPDispatchRuleInfo>> {
const req: Partial<ListSIPDispatchRuleRequest> = {};
const data = await this.rpc.request(
svc,
'ListSIPDispatchRule',
new ListSIPDispatchRuleRequest(req).toJson(),
await this.authHeader({}, { admin: true }),
);
return ListSIPDispatchRuleResponse.fromJson(data, { ignoreUnknownFields: true }).items ?? [];
}
/**
* @param sipDispatchRuleId sip trunk to delete
*/
async deleteSipDispatchRule(sipDispatchRuleId: string): Promise<SIPDispatchRuleInfo> {
const data = await this.rpc.request(
svc,
'DeleteSIPDispatchRule',
new DeleteSIPDispatchRuleRequest({ sipDispatchRuleId }).toJson(),
await this.authHeader({}, { admin: true }),
);
return SIPDispatchRuleInfo.fromJson(data, { ignoreUnknownFields: true });
}
/**
* @param sipTrunkId sip trunk to use for the call
* @param number number to dial
* @param roomName room to attach the call to
* @param opts CreateSipParticipantOptions
*/
async createSipParticipant(
sipTrunkId: string,
number: string,
roomName: string,
opts?: CreateSipParticipantOptions,
): Promise<SIPParticipantInfo> {
let participantIdentity: string = '';
let participantName: string = '';
let participantMetadata: string = '';
let dtmf: string = '';
let playRingtone: boolean = false;
let hidePhoneNumber: boolean = false;
if (opts !== undefined) {
participantIdentity = opts.participantIdentity || '';
participantName = opts.participantName || '';
participantMetadata = opts.participantMetadata || '';
dtmf = opts.dtmf || '';
playRingtone = opts.playRingtone || false;
hidePhoneNumber = opts.hidePhoneNumber || false;
}
const req = new CreateSIPParticipantRequest({
sipTrunkId: sipTrunkId,
sipCallTo: number,
roomName: roomName,
participantIdentity: participantIdentity,
participantName: participantName,
participantMetadata: participantMetadata,
dtmf: dtmf,
playRingtone: playRingtone,
hidePhoneNumber: hidePhoneNumber,
}).toJson();
const data = await this.rpc.request(
svc,
'CreateSIPParticipant',
req,
await this.authHeader({}, { call: true }),
);
return SIPParticipantInfo.fromJson(data, { ignoreUnknownFields: true });
}
}