question

Rashad Nasir avatar image
Rashad Nasir asked Rashad Nasir commented

ReadCallRecording Permission

We're attempting to read and save call logs, following this guide: https://medium.com/ringcentral-developers/how-to-get-a-new-call-recording-notification-ee9f2a6e41a0 by @Phong Vu

Our app is in sandbox mode and it DOES have "ReadCallRecording" as a permission.

When we run this:

platform.get(record.recording.contentUri) 

We're getting this error: "In order to call this API endpoint, application needs to have [ReadCallRecording] permission"

Code: CMN-401

We're able to retrieve the contentUri successfully, but the above call is failing.

Any help would be appreciated.

rest api
1 |3000

Up to 8 attachments (including images) can be used with a maximum of 1.0 MiB each and 10.0 MiB total.

Rashad Nasir avatar image
Rashad Nasir answered

Update: seems like it just took a little while to take effect... error stopped occurring with no changes to the code.

1 |3000

Up to 8 attachments (including images) can be used with a maximum of 1.0 MiB each and 10.0 MiB total.

Phong Vu avatar image
Phong Vu answered Rashad Nasir commented

I guess that you just add the missing permission and test it. If that is the case, wait for a few minutes for the system to apply the changes, then try again.

By the way, here is a new code to get new call recording notifications. I will update the tutorial later though.

function presenceEvent(msg){
  var user = {
    extensionId: msg.body.extensionId,
    sessionId: msg.body.activeCalls[0].sessionId,
    telephonyStatus: msg.body.telephonyStatus
  }
  checkTelephonyStatusChange(user)
}

function checkTelephonyStatusChange(user){
  var newUser = true
  for (var i=0; i<usersList.length; i++){
    if (usersList[i].extensionId == user.extensionId){
      console.log("OLD -> NEW: " + usersList[i].telephonyStatus + " -> " + user.telephonyStatus)
      newUser = false
      if (usersList[i].telephonyStatus == "NoCall" && user.telephonyStatus == "Ringing"){
        usersList[i].telephonyStatus = user.telephonyStatus
        console.log("ExtensionId " + usersList[i].extensionId + " has an incoming call")
        break
      }
      if (usersList[i].telephonyStatus == "Ringing" && user.telephonyStatus == "CallConnected"){
        usersList[i].telephonyStatus = user.telephonyStatus
        console.log("ExtensionId " + usersList[i].extensionId + " has a accepted a call")
        break
      }
      if (usersList[i].telephonyStatus == "Ringing" && user.telephonyStatus == "NoCall"){
        usersList[i].telephonyStatus = user.telephonyStatus
        console.log("ExtensionId " + usersList[i].extensionId + " has a missed call")
        break
      }
      if (usersList[i].telephonyStatus == "CallConnected" && user.telephonyStatus == "NoCall"){
        usersList[i].telephonyStatus = user.telephonyStatus
        console.log("ExtensionId " + usersList[i].extensionId + " has a terminated call")
        // wait for about 20 secs then check for call recordings
        var thisUser = usersList[i]
        setTimeout(function(){
          readExtensionCallLogs(thisUser)
        }, 20000)
        break
      }
    }
  }
  if (newUser){
    console.log("NEW USER: " + " -> " + user.telephonyStatus)
    if (user.telephonyStatus == "Ringing"){
      console.log("ExtensionId " + user.extensionId + " has an incoming call")
    }
    usersList.push(user)
  }
}

function readExtensionCallLogs(user){
  var endpoint = '/account/~/extension/'+ user.extensionId +'/call-log'
  var params = {}
  params['sessionId'] = user.sessionId
  platform.get(endpoint, params)
  .then(function(resp){
    async.each(resp.json().records,
      function(record, callback){
        if (record.hasOwnProperty("recording")){
          console.log("THIS CALL HAS A RECORDING: " + record.recording.contentUri)
          saveAudioFile(record)
          callback(null, "done")
        }
      },
      function(err){
        console.log("No call with call recording within this period of time.")
      }
    );
  })
  .catch(function(e){
    var err = e.toString();
    console.log(err)
  })
}


9 comments
1 |3000

Up to 8 attachments (including images) can be used with a maximum of 1.0 MiB each and 10.0 MiB total.

Rashad Nasir avatar image Rashad Nasir commented ·

I'm glad there's an official revision to this, because I had to do some trial and error and already implemented some of this code (e.g. the "hasOwnProperty" check) .

That said, this full revised version is throwing an error, here: msg.body.activeCalls[0].sessionId

TypeError: Cannot read property '0' of undefined

Is there a change to the subscription I should have as well? The data I get from the subscription does not include an "activeCalls" parameter.

Currently only using '/restapi/v1.0/account/~/presence' as an eventFilter.

0 Likes 0 ·
Rashad Nasir avatar image Rashad Nasir Rashad Nasir commented ·

Looks like this has to be used as the eventFilter, your original eventFilter will not provide the activeCalls array:


"/restapi/v1.0/account/~/extension/~/presence?detailedTelephonyState=true"


0 Likes 0 ·
Phong Vu avatar image Phong Vu ♦♦ Rashad Nasir commented ·

Correct!

0 Likes 0 ·
Rashad Nasir avatar image Rashad Nasir Rashad Nasir commented ·

Noticing this behavior:

  1. user calls and there's a call recording - works fine
  2. a user calls back again, no recording is made. the code is still seeing the old sessionId, and it is retrieving the last call recording.

How can that be prevented?

0 Likes 0 ·
Phong Vu avatar image Phong Vu ♦♦ Rashad Nasir commented ·

Sorry, I did not share the function saveAudioFile() where I reset the sessionId. You should reset it after reading the call log.

0 Likes 0 ·
Show more comments

Developer sandbox tools

Using the RingCentral Phone for Desktop, you can dial or receive test calls, send and receive test SMS or Fax messages in your sandbox environment.

Download RingCentral Phone for Desktop:

Tip: switch to the "sandbox mode" before logging in the app:

  • On MacOS: press "fn + command + f2" keys
  • On Windows: press "Ctrl + F2" keys