@telegenta/webclient 3.1.1 → 3.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -39,63 +39,49 @@ and you are ready to go. The client has no external requirements (like jQuery an
39
39
 
40
40
  Before starting, you will need an account on telegenta.com, to create sip accounts and api tokens.
41
41
 
42
- #### Example 1: Simple phone with static account
42
+ Runnable examples live in `demos/`. They load the browser bundle from `../dist/telegenta.min.js`, so
43
+ run `npm run build` first, then serve the directory over https. WebRTC requires a secure context;
44
+ `localhost` counts as secure, but opening a demo as `file://...` does not - media permissions are not
45
+ remembered there, so you will be prompted for the microphone every time.
43
46
 
44
- In this example we will use a normal SIP User account, as it does not require you to use our API service.
47
+ #### Example: phone with a provisioning token
45
48
 
46
- Log into the administration frontend (https://admin.telegenta.com) and create a "SIP User account", this will provide
47
- you with credentials (username and password). Once you have these open the embedded html client provided with this
48
- library /embedded_client/index.html and modify the credentials:
49
+ `demos/phone_client.html` is a complete softphone - start/stop, outbound calls, transfer, listen-in,
50
+ incoming calls and the event client.
49
51
 
50
- ```
51
- // SIP account username and password
52
- var USERNAME='your username';
53
- var PASSWORD='your password';
54
-
55
- window.onload = function () {
56
- ...
57
- ```
58
-
59
- Now open the file (index.html) in your browser. After you have been prompted for permission to use the audio devices,
60
- you should have a working phone.
61
- Note: If you are viewing a file using "file://index.html", it is not considered a secure connection by the browser
62
- and media permissions are not remembered, so you will be prompted every time you open the file.
63
- However, once you move the file to a secure webserver (https), this will no longer be an issue.
64
-
65
- #### Example 2: Using SIP Flex accounts
52
+ First create a static API token in the admin interface
53
+ (https://admin.telegenta.com/integration/access-tokens). Open the demo and paste the token in; it then
66
54
 
67
- When using SIP flex accounts, you need to use our API service to retrieve account information first.
68
- This approach solves the authentication problem and provides you with short-lived sip accounts used in client sessions.
69
- For this example we need a backend service and we provide a simple example in PHP using the built in Webserver.
55
+ 1. requests a short-lived provisioning token with `GET /api/get-call-session/?id=<account id>`, and
56
+ 2. starts the phone with that token:
70
57
 
71
- First go to the admin interface and create following 2 items:
58
+ ```
59
+ const opts = {
60
+ // Enable event client
61
+ connectEventService: true,
72
62
 
73
- 1. SIP Flex account with "flex account identification" set to 'test'
74
- 2. A static api token (https://admin.telegenta.com/integration/access-tokens).
63
+ // Subscribe to detailed information about call after processing
64
+ useCallDataInfoEvent: true,
75
65
 
76
- Now open the file /embedded_client/server.html and insert the API token at the top of the file:
66
+ // Enable incoming calls (you must set a phone number to call the account also)
67
+ register: true,
77
68
 
78
- ```
79
- // Your API Token
80
- $api_auth_token = '<your api token>';
69
+ // Configure client with provision token
70
+ provisionToken: data.provision_token,
71
+ };
81
72
 
82
- // The flex account identification (this is set when configuring your flex accounts)
83
- // It possible to have multiple sip flex accounts with different configurations
84
- $flex_identification = 'test';
85
- ...
73
+ phoneClient.start(opts);
86
74
  ```
87
75
 
88
- Once you have added the token, you can start the php Webserver (requires php v5.4+) like this:
76
+ Issuing the provisioning token from your own backend is the recommended integration: the short-lived
77
+ token is all that reaches the browser, and your API token stays on the server.
89
78
 
90
- ```
91
- cd embedded_client
92
- php -S localhost:9000
93
- ```
79
+ The remaining demos cover narrower cases:
94
80
 
95
- Now open the URL http://localhost:9000/server.php and you should see the phone and be able to perform calls.
96
- Note: If you use any other host than localhost, you won't be able to call because the built in php webserver does not
97
- support secure (https) connections and this is required by the browser to use WebRTC. If needed, you can tunnel to
98
- localhost using your ssh client for testing.
81
+ - `demos/event_client.html` - the event client on its own, without a phone
82
+ - `demos/calldata_available.html` - subscribing to call data after a call completes
83
+ - `demos/add_phone_number.html` - adding a phone number through the API
84
+ - `demos/embedded_config.html` - embedding the admin config pages with a config token
99
85
 
100
86
  ## Approaching the integration
101
87
 
@@ -106,15 +92,10 @@ Depending on how much flexibility you need, you can choose between the following
106
92
  We believe in using standard protocols as much as possible and it will work nicely, but you need to address most
107
93
  of the issues we listed above in the previous section yourself.
108
94
 
109
- 2. Use our free library (lib/telegenta.min.js) and provide your own frontend
110
- This way you just need to handle events and use javascript methods like call, hangup, startRecord, etc..
111
-
112
- 3. Use our complete embedded phone client with frontend.
113
- We have made a simple phone with frontend, which can be easily included in your own project. Just grab the
114
- index.html, style.css and embedded_phone.js and insert it into your own project.
115
- We named the JS and CSS to try and avoid any potential conflicts.
116
- You only need to provide it with credentials or provisioning token (as in the example above) from you backend and
117
- you are set to start calling.
95
+ 2. Use our free library and provide your own frontend.
96
+ Load `dist/telegenta.min.js` in the browser (global `Telegenta`) or import the package in your
97
+ bundler, then handle events and use javascript methods like call, hangup, startRecord, etc..
98
+ `demos/phone_client.html` shows the whole flow end to end.
118
99
 
119
100
  ## Migrating from 2.x
120
101
 
package/dist/telegenta.js CHANGED
@@ -25,23 +25,23 @@ class LogHandler {
25
25
  }
26
26
 
27
27
  debug(...args) {
28
- this._doLog(LOGLVL$1.DEBUG, args);
28
+ this._doLog(LOGLVL.DEBUG, args);
29
29
  }
30
30
 
31
31
  info(...args) {
32
- this._doLog(LOGLVL$1.INFO, args);
32
+ this._doLog(LOGLVL.INFO, args);
33
33
  }
34
34
 
35
35
  warn(...args) {
36
- this._doLog(LOGLVL$1.WARN, args);
36
+ this._doLog(LOGLVL.WARN, args);
37
37
  }
38
38
 
39
39
  warning(...args) {
40
- this._doLog(LOGLVL$1.WARN, args);
40
+ this._doLog(LOGLVL.WARN, args);
41
41
  }
42
42
 
43
43
  error(...args) {
44
- this._doLog(LOGLVL$1.ERROR, args);
44
+ this._doLog(LOGLVL.ERROR, args);
45
45
  }
46
46
 
47
47
  _doLog(level, args) {
@@ -60,19 +60,19 @@ class LogHandler {
60
60
  this.extHandler(LOGLVLSTR[level], args);
61
61
  } else {
62
62
  switch (level) {
63
- case LOGLVL$1.DEBUG:
63
+ case LOGLVL.DEBUG:
64
64
  console.debug(args);
65
65
  break;
66
66
 
67
- case LOGLVL$1.INFO:
67
+ case LOGLVL.INFO:
68
68
  console.info(args);
69
69
  break;
70
70
 
71
- case LOGLVL$1.WARN:
71
+ case LOGLVL.WARN:
72
72
  console.warn(args);
73
73
  break;
74
74
 
75
- case LOGLVL$1.ERROR:
75
+ case LOGLVL.ERROR:
76
76
  console.error(args);
77
77
  break;
78
78
 
@@ -91,7 +91,7 @@ class LogHandler {
91
91
  * @property {number} INFO 2 Informational messages (default)
92
92
  * @property {number} DEBUG 3 Debug messages
93
93
  */
94
- const LOGLVL$1 = {
94
+ const LOGLVL = {
95
95
  DEBUG: 3,
96
96
  INFO: 2,
97
97
  WARN: 1,
@@ -386,7 +386,7 @@ class Request {
386
386
  class Requestor extends EventEmitter {
387
387
  constructor(logger = null) {
388
388
  super();
389
- this.log = logger ? logger : new LogHandler(LOGLVL$1.INFO);
389
+ this.log = logger ? logger : new LogHandler(LOGLVL.INFO);
390
390
  this._pendingRequests = [];
391
391
  }
392
392
 
@@ -401,13 +401,13 @@ class Requestor extends EventEmitter {
401
401
  let msg;
402
402
  try {
403
403
  msg = JSON.parse(message);
404
- } catch (err) {
404
+ } catch {
405
405
  this.log.warning("Unable to parse message: " + message);
406
406
  return;
407
407
  }
408
408
 
409
409
  // Validate msg fields
410
- if (!msg.hasOwnProperty("type") || !msg.hasOwnProperty("id")) {
410
+ if (!Object.hasOwn(msg, "type") || !Object.hasOwn(msg, "id")) {
411
411
  this.log.warning(`Invalid message received: ${msg} - missing type or id`);
412
412
  return;
413
413
  }
@@ -658,7 +658,7 @@ class EventClient {
658
658
  throw new InvalidParameter('You must specify both event spec and callback function');
659
659
  }
660
660
 
661
- if (!eventSpecification.hasOwnProperty('event_name')) {
661
+ if (!Object.hasOwn(eventSpecification, 'event_name')) {
662
662
  throw new InvalidParameter('Your event specification must contain event name');
663
663
  }
664
664
 
@@ -1663,10 +1663,10 @@ class Phone extends EventEmitter {
1663
1663
  this._oscillator2 = null;
1664
1664
 
1665
1665
  // Set default logger
1666
- this.log = logger ? logger : new LogHandler(LOGLVL$1.INFO);
1666
+ this.log = logger ? logger : new LogHandler(LOGLVL.INFO);
1667
1667
 
1668
1668
  // Handle jssip debug logs
1669
- if (this.log.level === LOGLVL$1.DEBUG) {
1669
+ if (this.log.level === LOGLVL.DEBUG) {
1670
1670
  JsSIP.debug.disable('JsSIP:*');
1671
1671
  } else {
1672
1672
  JsSIP.debug.disable('JsSIP:*');
@@ -1741,10 +1741,10 @@ class Phone extends EventEmitter {
1741
1741
 
1742
1742
  // Unpack provisioning token if specified
1743
1743
  if (this._options.provisionToken) {
1744
- let pt = null;
1744
+ let pt;
1745
1745
  try {
1746
1746
  pt = JSON.parse(atob(this._options.provisionToken));
1747
- } catch (err) {
1747
+ } catch {
1748
1748
  throw new InvalidOptions('provisionToken', 'Invalid token');
1749
1749
  }
1750
1750
 
@@ -1820,7 +1820,7 @@ class Phone extends EventEmitter {
1820
1820
  );
1821
1821
  }
1822
1822
 
1823
- let wsSocket = null;
1823
+ let wsSocket;
1824
1824
  try {
1825
1825
  wsSocket = new JsSIP.WebSocketInterface(this._options.wssServer);
1826
1826
  } catch (err) {
@@ -1932,7 +1932,7 @@ class Phone extends EventEmitter {
1932
1932
  try {
1933
1933
  this._eventClient.disconnect();
1934
1934
  delete this._eventClient;
1935
- } catch (e) {
1935
+ } catch {
1936
1936
  this.log.warning('Unable to disconnect event client');
1937
1937
  }
1938
1938
 
@@ -2023,7 +2023,7 @@ class Phone extends EventEmitter {
2023
2023
  */
2024
2024
  getSessionByUUID(uuid) {
2025
2025
  for (let key in this._activeSessions) {
2026
- if (this._activeSessions.hasOwnProperty(key)) {
2026
+ if (Object.hasOwn(this._activeSessions, key)) {
2027
2027
  if (this._activeSessions[key].uuid === uuid) {
2028
2028
  return this._activeSessions[key];
2029
2029
  }
@@ -2048,7 +2048,7 @@ class Phone extends EventEmitter {
2048
2048
  get sessions() {
2049
2049
  let s = [];
2050
2050
  for (let key in this._activeSessions) {
2051
- if (this._activeSessions.hasOwnProperty(key)) {
2051
+ if (Object.hasOwn(this._activeSessions, key)) {
2052
2052
  s.push(this._activeSessions[key]);
2053
2053
  }
2054
2054
  }
@@ -2213,7 +2213,7 @@ class Phone extends EventEmitter {
2213
2213
 
2214
2214
  // Iterate through all active calls and hold them
2215
2215
  for (let key in this._activeSessions) {
2216
- if (this._activeSessions.hasOwnProperty(key)) {
2216
+ if (Object.hasOwn(this._activeSessions, key)) {
2217
2217
  let session = this._activeSessions[key];
2218
2218
  if (session.state === 'ACTIVE') {
2219
2219
  session.hold();
@@ -2287,7 +2287,7 @@ class Phone extends EventEmitter {
2287
2287
  // Return true if there are calls currently connecting
2288
2288
  _checkForConnectingCalls() {
2289
2289
  for (let key in this._activeSessions) {
2290
- if (this._activeSessions.hasOwnProperty(key)) {
2290
+ if (Object.hasOwn(this._activeSessions, key)) {
2291
2291
  let session = this._activeSessions[key];
2292
2292
  if (
2293
2293
  session.state === 'INITIALIZING' ||
@@ -2671,7 +2671,7 @@ class Session extends EventEmitter {
2671
2671
  self.log.info(`Answer call timeout after ${self._answerCallTimeout} seconds`);
2672
2672
  try {
2673
2673
  self.hangup();
2674
- } catch (e) {
2674
+ } catch {
2675
2675
  self.log.info('No active session, ignoring answer call timeout');
2676
2676
  }
2677
2677
  }, self._answerCallTimeout * 1000);
@@ -3742,4 +3742,4 @@ class Session extends EventEmitter {
3742
3742
  }
3743
3743
  }
3744
3744
 
3745
- export { EventClient, EventServiceNotConnected, InvalidMediaDevice, InvalidOptions, InvalidParameter, LOGLVL$1 as LOGLVL, LogHandler, MediaNotPrepared, NoActiveSession, NotAllowed, NotReady, Phone, Request, Requestor, Session, UnableToConnect, browserIsChrome, browserIsEdge, browserIsFirefox, browserIsOpera, browserIsSafari, buildCustomHeaders, compareObjects, createDurationString, createUUID };
3745
+ export { EventClient, EventServiceNotConnected, InvalidMediaDevice, InvalidOptions, InvalidParameter, LOGLVL, LogHandler, MediaNotPrepared, NoActiveSession, NotAllowed, NotReady, Phone, Request, Requestor, Session, UnableToConnect, browserIsChrome, browserIsEdge, browserIsFirefox, browserIsOpera, browserIsSafari, buildCustomHeaders, compareObjects, createDurationString, createUUID };