UNPKG

awry

Version:

An ARI websocket and API client library

448 lines (418 loc) 16.2 kB
import axios from "axios"; /** * REST API Resource for interacting with Asterisk Bridges and the channels * within those bridges. */ export default class BridgesAPI { /** * Create an instance of the Bridges API client, providing access to the * `/bridges` endpoint. * * @param {object} params * @param {string} params.username The username to send with the request. * @param {string} params.password The password to send with the request. * @param {string} params.baseUrl The base url, without trailing slash, * of the root Asterisk ARI endpoint. i.e. 'http://myserver.local:8088/ari'. */ constructor(params = {}) { const { username, password } = params; /** @private */ this._baseUrl = params.baseUrl; /** @private */ this._request = axios.create({ auth: { username, password }, }); } /** * GET /bridges * * List all active bridges in Asterisk. * * @returns {Promise.<Array.<Bridge>>} Resolves with all existing bridges * in Asterisk. */ list() { return this._request({ method: "GET", url: `${this._baseUrl}/bridges`, }); } /** * POST /bridges * * Create a new bridge. This bridge persists until it has been shut down, * or Asterisk has been shut down. * * @param {object} params * @param {string|Array.<string>} [params.type] The attributes to set on the * bridge that determine how the bridge mixes media between its * participants. Possible attributes are 'mixing', 'holding', 'dtmf_events', * and 'proxy_media'. 'dtmf_events' and 'proxy_media' are only valid when * also supplied with 'mixing'. 'holding' and 'mixing' are mutually * exclusive. *Allows multiple values since Asterisk 12.2* * @param {string} [params.name] A name to give to the bridge being created. * @param {string} [params.bridgeId] The unique identifier for the bridge. * *Param available since Asterisk 12.2* * @returns {Promise.<Bridge>} Resolves to the newly created bridge. */ create(params = {}) { const { type, name, bridgeId } = params; return this._request({ method: "POST", url: `${this._baseUrl}/bridges`, params: { name, bridgeId, type: [].concat(type).join(","), }, }); } /** * POST /bridges/{bridgeId} * * Create a new bridge or update an existing one. This bridge persists * until it has been shut down, or Asterisk has been shut down. * * *API available since Asterisk 12.2* * * @param {object} params * @param {string} params.bridgeId The unique identifier for the bridge. * @param {string|Array.<string>} [params.type] The attributes to set on the * bridge that determine how the bridge mixes media between its * participants. Possible attributes are 'mixing', 'holding', 'dtmf_events', * and 'proxy_media'. 'dtmf_events' and 'proxy_media' are only valid when * also supplied with 'mixing'. 'holding' and 'mixing' are mutually * exclusive. * @param {string} [params.name] A name to give to the bridge being created. * @returns {Promise.<Bridge>} Resolves to the newly created bridge. */ createOrUpdate(params = {}) { const { type, name, bridgeId } = params; const id = encodeURIComponent(bridgeId); return this._request({ method: "POST", url: `${this._baseUrl}/bridges/${id}`, params: { name, type: [].concat(type).join(","), }, }); } /** * GET /bridges/{bridgeId} * * Get details of a specific bridge. * * @param {object} params * @param {string} params.bridgeId The identifier of the bridge to retrieve * details for. * @returns {Promise.<Bridge>} Resolves to the details matching the specified * bridgeId. Rejects if the bridge could not be found (status 404). */ get(params = {}) { const { bridgeId } = params; const id = encodeURIComponent(bridgeId); return this._request({ method: "GET", url: `${this._baseUrl}/bridges/${id}`, }); } /** * DELETE /bridges/{bridgeId} * * Shut down a bridge. If any channels are in this bridge, they will be * removed and resume whatever they were doing beforehand. * * @param {object} params * @param {string} params.bridgeId The identifer of the bridge to delete. * @returns {Promise} Resolves if the bridge is successfully deleted. * Rejects if the bridge could not be found (status 404). */ destroy(params = {}) { const { bridgeId } = params; const id = encodeURIComponent(bridgeId); return this._request({ method: "DELETE", url: `${this._baseUrl}/bridges/${id}`, }); } /** * POST /bridges/{bridgeId}/addChannel * * Add a channel to a bridge. * * @param {object} params * @param {string} params.bridgeId The identifer of the bridge to add the * channels to. * @param {string|Array.<string>} params.channel The channel or list of * channels to add to the bridge. * @param {string} [params.role] The channels' role in the bridge. * @return {Promise} Resolves if the channels are successfully added to * the bridge. Rejected if one of the channels is not found (status 400), * the bridge could not be found (status 404), the bridge is not in the * Stasis application (status 409), one of the specified channels is * currently recording (status 409), or one of the channels is not in the * Stasis application (status 422). */ addChannel(params = {}) { const { channel, role, bridgeId } = params; const id = encodeURIComponent(bridgeId); return this._request({ method: "POST", url: `${this._baseUrl}/bridges/${id}/addChannel`, params: { channel: [].concat(channel).join(","), role, }, }); } /** * POST /bridges/{bridgeId}/removeChannel * * Remove a channel from a bridge. * * @param {object} params * @param {string} params.bridgeId The identifier of the bridge to remove * the channels from. * @param {string|Array.<string>} params.channel The channel or list of * channels to remove from the bridge. * @return {Promise} Resolves if the channels are successfully removed from * the bridge. Rejected if one of the channels is not found (status 400), * the bridge could not be found (status 404), the bridge is not in the * Stasis application (status 409), or one of the channels is not in the * bridge (status 422). */ removeChannel(params = {}) { const { channel, bridgeId } = params; const id = encodeURIComponent(bridgeId); return this._request({ method: "POST", url: `${this._baseUrl}/bridges/${id}/removeChannel`, params: { channel: [].concat(channel).join(",") }, }); } /** * POST /bridges/{bridgeId}/moh * * Play music on hold to a bridge or change the music on hold class * that is currently playing. * * @param {object} params * @param {string} params.bridgeId The identifier of the bridge to play * music on hold into. * @param {string} [params.mohClass] The class of music on hold to play. * @returns {Promise} Resolves when the music has successfully started playing * in the bridge. Rejects if the bridge could not be found (status 404) * or the bridge is not in the Stasis application (status 409). */ startMusicOnHold(params = {}) { const { bridgeId, mohClass } = params; const id = encodeURIComponent(bridgeId); return this._request({ method: "POST", url: `${this._baseUrl}/bridges/${id}/moh`, params: { mohClass }, }); } /** * DELETE /bridges/{bridgeId}/moh * * Stop playing music on hold to a bridge. This will only stop music on hold * that had been previously started via ARI. * * @param {object} params * @param {string} params.bridgeId The identifier of the bridge to stop * playing music on hold to. * @returns {Promise} Resolves when the music has successfully stopped playing * in the bridge. Rejects if the bridge could not be found (status 404) * or the bridge is not in the Stasis application (status 409). */ stopMusicOnHold(params = {}) { const { bridgeId } = params; const id = encodeURIComponent(bridgeId); return this._request({ method: "DELETE", url: `${this._baseUrl}/bridges/${id}/moh`, }); } /** * POST /bridges/{bridgeId}/play * * Start playback of media on a bridge. The media URI may be any of a number * of URIs. The currently support URIs are 'sound:', 'recording:', 'number:', * 'digits:', 'characters:', and 'tone:'. This operation creates a playback * resource that can be used to control the playback of media (pause, * rewind, fast-forward, etc.) * * *'tone:' playback uri added in Asterisk 12.3* * * @param {object} params * @param {string} params.bridgeId The identifier of the bridge to play media * into. * @param {string|Array.<string>} params.media The media's URI to play. *Allows * multiple media to be passed since Asterisk 14.0* * @param {string} [params.playbackId] The playback identifier to attach to * the Playback instance. *Param available since Asterisk 12.2* * @param {string} [params.lang] For sounds, the language of the sound to play. * @param {number} [params.offsetms=0] The number of milliseconds to skip from * the beginning of the media before starting playback. Allowed range: 0+ * @param {number} [params.skipms=3000] The number of milliseconds to skip * for forward/reverse operations. Allowed range: 0+ * @returns {Promise.<Playback>} Resolved with the Playback instance when * the playback is successfully started. Rejects when the bridge is not * found (status 404) or the bridge is not in the Stasis application * (status 409). */ play(params = {}) { const { bridgeId, media, playbackId, lang, offsetms = 0, skipms = 3000, } = params; const id = encodeURIComponent(bridgeId); return this._request({ method: "POST", url: `${this._baseUrl}/bridges/${id}/play`, params: { media: [].concat(media).join(","), lang, offsetms, skipms, playbackId, }, }); } /** * POST /bridges/{bridgeId}/play/{playbackId} * * Start playback of media on a bridge. The media URI may be any of a * number of URIs. The currently support URIs are 'sound:', 'recording:', * 'number:', 'digits:', 'characters:', and 'tone:'. This operation creates * a playback resource that can be used to control the playback of media * (pause, rewind, fast-forward, etc.) * * *API available since Asterisk 12.2* * *'tone:' playback uri added in Asterisk 12.3* * * @param {object} params * @param {string} params.bridgeId The identifier of the bridge to play media * into. * @param {string|Array.<string>} params.media The media's URI to play. * *Allows multiple media to be passed since Asterisk 14.0* * @param {string} params.playbackId The playback identifier to attach to * the Playback instance. * @param {string} [params.lang] For sounds, the language of the sound to play. * @param {number} [params.offsetms=0] The number of milliseconds to skip from * the beginning of the media before starting playback. Allowed range: 0+ * @param {number} [params.skipms=3000] The number of milliseconds to skip * for forward/reverse operations. Allowed range: 0+ * @returns {Promise.<Playback>} Resolved with the Playback instance when * the playback is successfully started. Rejects when the bridge is not * found (status 404) or the bridge is not in the Stasis application * (status 409). */ playWithId(params = {}) { const { bridgeId, media, playbackId, lang, offsetms = 0, skipms = 3000, } = params; const id = encodeURIComponent(bridgeId); const playId = encodeURIComponent(playbackId); return this._request({ method: "POST", url: `${this._baseUrl}/bridges/${id}/play/${playId}`, params: { media: [].concat(media).join(","), lang, offsetms, skipms, }, }); } /** * POST /bridges/{bridgeId}/record * * Start a recording. This records the mixed audio from all channels * participating in this bridge. * * @param {object} params * @param {string} params.bridgeId The identifier of the bridge to record. * @param {string} params.name The recordings filename. * @param {string} [params.format=wav] The format to encode the audio in. * @param {number} [params.maxDurationSeconds=0] The maximum duration of * the recording, in seconds. Pass 0 for no limit. Allowed range: 0+ * @param {number} [params.maxSilenceSeconds=0] The maximum duration of * silence, in seconds. Pass 0 for no limit. Allowed range: 0+ * @param {string} [params.ifExists=fail] The action to take if a recording * with the same name already exists. Allowed values: 'fail', 'overwrite', * or 'append'. * @param {boolean} [params.beep=true] Play a beep when recording begins. * @param {string} [params.terminateOn=none] DTMF input to terminate * recording. Allowed values: 'none', 'any', '*', or '#'. * @returns {Promise.<LiveRecording>} Resolves with the created LiveRecording * instance if the recording is successfully started. Rejects if invalid * parameters are passed (status 400), the bridge is not found (status 404), * the bridge is not in the Stasis application (status 409), a recording * with the same name already exists on the system and cannot be overwritten * because it is already in progress or the `ifExists` param is set to 'fail' * (status 409), or the specified format is unknown (status 422). */ record(params = {}) { const { bridgeId, name, format = "wav", maxDurationSeconds = 0, maxSilentSeconds = 0, ifExists = "fail", beep = true, terminateOn = "none", } = params; const id = encodeURIComponent(bridgeId); return this._request({ method: "POST", url: `${this._baseUrl}/bridges/${id}/record`, params: { name, format, maxDurationSeconds, maxSilentSeconds, ifExists, beep, terminateOn, }, }); } } /** * The merging of media from one or more channels. * * @typedef {object} Bridge * @property {string} bridge_class The bridging class. * @property {string} bridge_type The type of bridge technology. * @property {Array.<string>} channels The Ids of channels participating in this bridge. * @property {string} id The unique identifier for this bridge. * @property {string} technology The name of the current bridging technology. * @property {string} name The name the creator gave to this bridge. *Property available since Asterisk 12.1* * @property {string} creator The entity that created the bridge. *Property available since Asterisk 12.1* */ /** * A recording that is in progress. * * @typedef {object} LiveRecording * @property {string} [cause] The cause for the recording failure if it failed. * @property {string} format The recording format (wav, gsm, etc.) * @property {string} name The base name for the recording. * @property {string} state The state the recording is currently in. * @property {string} target_uri The uri for the channel or bridge being recorded. *Property available since Asterisk 12.2* * @property {number} [duration] The duration in seconds of the recording. *Property available since Asterisk 12.5* * @property {number} [talking_duration] The duration of talkin, in seconds, detected in the recording. This is only available if the recording was initiated with a non-zero maxSilenceSeconds. *Property available since Asterisk 12.5* * @property {number} [silence_duration] The duration of silence, in seconds, detected in the recording. This is only available if the recording was initiated with a non-zero maxSilenceSeconds. *Property available since Asterisk 12.5* */