diff --git a/CHANGELOG.md b/CHANGELOG.md index e81a198a..c1678126 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,12 @@ # Change Log + +## [4.57.0](https://github.com/plivo/plivo-go/tree/v4.57.0) (2024-11-15) +**Feature - CreateRecordingTranscription, GetRecordingTranscription and DeleteRecordingTranscription feature added** +- Support added to create transcription for recorded calls for which transcription is not available and get API to retrieve and delete API to delete. +- Support for the `type` filter parameter, supported filters are transcription, raw and diarized +- Support for the `transcription_url` and `transcript` parameter in MPC Add Participant. +- Support added for Transcription params in MPC recording and MPC participant recording + ## [4.56.2](https://github.com/plivo/plivo-python/tree/v4.56.2) (2024-10-23) **Feature - FraudCheck param in Create, Get and List Session** - Support for the `fraud_check` parameter in sms verify session request diff --git a/plivo/resources/multipartycall.py b/plivo/resources/multipartycall.py index 59a91140..dbfc99ca 100644 --- a/plivo/resources/multipartycall.py +++ b/plivo/resources/multipartycall.py @@ -63,7 +63,9 @@ def add_participant(self, stop_recording_audio_method='GET', create_mpc_with_single_participant=True, send_digits=None, - send_on_preanswer=False + send_on_preanswer=False, + transcription_url=None, + transcript=False ): return self.client.multi_party_calls.add_participant(role, uuid=self.id, **to_param_dict(self.add_participant, locals())) @@ -74,7 +76,8 @@ def start(self): def stop(self): return self.client.multi_party_calls.stop(uuid=self.id) - def start_recording(self, file_format=None, recording_callback_url=None, recording_callback_method=None): + def start_recording(self, file_format=None, recording_callback_url=None, recording_callback_method=None, + transcription_url=None, transcript=False): return self.client.multi_party_calls.start_recording(uuid=self.id, **to_param_dict(self.add_participant, locals())) @@ -88,7 +91,8 @@ def resume_recording(self): return self.client.multi_party_calls.resume_recording(uuid=self.id) def start_participant_recording(self, participant_id, file_format=None, recording_callback_url=None, - recording_callback_method=None, record_track_type='all'): + recording_callback_method=None, record_track_type='all', + transcription_url=None, transcript=False): return self.client.multi_party_calls.start_participant_recording(participant_id=participant_id, uuid=self.id, **to_param_dict( self.start_participant_recording, @@ -143,7 +147,8 @@ class MultiPartyCallParticipant(SecondaryPlivoResource): _secondary_identifier_string = 'member_id' def start_participant_recording(self, file_format=None, recording_callback_url=None, - recording_callback_method=None, record_track_type='all'): + recording_callback_method=None, record_track_type='all', + transcription_url=None, transcript=False): return self.client.multi_party_calls.start_participant_recording(participant_id=self.secondary_id, uuid=self.id, **to_param_dict( self.start_participant_recording, @@ -400,7 +405,9 @@ def add_participant(self, callback_method=None, create_mpc_with_single_participant=True, send_digits=None, - send_on_preanswer=False + send_on_preanswer=False, + transcription_url=None, + transcript=False ): mpc_id = self.__make_mpc_id(friendly_name, uuid) caller_name = caller_name or from_ @@ -466,7 +473,9 @@ def start_recording(self, recording_callback_url=None, recording_callback_method='POST', callback_url=None, - callback_method=None + callback_method=None, + transcription_url=None, + transcript=False ): mpc_id = self.__make_mpc_id(friendly_name, uuid) return self.client.request('POST', ('MultiPartyCall', mpc_id, 'Record'), @@ -590,7 +599,8 @@ def get_participant(self, participant_id, uuid=None, friendly_name=None, ) def start_participant_recording(self, participant_id, uuid=None, friendly_name=None, file_format='mp3', recording_callback_url=None, recording_callback_method='POST', - callback_url=None, callback_method=None, record_track_type='all'): + callback_url=None, callback_method=None, record_track_type='all', + transcription_url=None, transcript=False): mpc_id = self.__make_mpc_id(friendly_name, uuid) return self.client.request('POST', ('MultiPartyCall', mpc_id, 'Participant', participant_id, 'Record'), self.__clean_identifiers(to_param_dict(self.start_participant_recording, locals())), diff --git a/plivo/resources/transcription.py b/plivo/resources/transcription.py new file mode 100644 index 00000000..5301a7d8 --- /dev/null +++ b/plivo/resources/transcription.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +""" +Recording class - along with its list class +""" + +from plivo.base import (ListResponseObject, PlivoResource, + PlivoResourceInterface) +from plivo.resources.accounts import Subaccount +from plivo.utils import is_valid_time_comparison, to_param_dict +from plivo.utils.validators import * + + +class Transcription(PlivoResource): + _name = 'Transcription' + _identifier_string = 'transcription_id' + + def get_transcription(self): + return self.client.transcriptions.get_transcription(self.id, **to_param_dict(self.get_transcription(), locals())) + + def create_transcription(self): + return self.client.transcriptions.create_transcription(self.id, **to_param_dict(self.create_transcription(), locals())) + + def delete_transcription(self): + return self.client.transcriptions.delete_transcription(self.id, **to_param_dict(self.delete_transcription(), locals())) + + +class Transcriptions(PlivoResourceInterface): + _resource_type = Transcription + + @validate_args(transcription_id=[of_type(six.text_type)] + ) + def get_transcription(self, transcription_id, type=None): + if not type: + return self.client.request( + 'GET', ('Transcription', transcription_id), is_voice_request=True) + else: + return self.client.request( + 'GET', ('Transcription', transcription_id), to_param_dict(self.get_transcription, locals()), is_voice_request=True) + + def create_transcription(self, recording_id, transcription_callback_url=None): + return self.client.request( + 'POST', ('Transcription', recording_id), to_param_dict(self.create_transcription, locals()), is_voice_request=True) + + def delete_transcription(self, transcription_id): + return self.client.request( + 'DELETE', ('Transcription', transcription_id), is_voice_request=True) + + + diff --git a/plivo/rest/client.py b/plivo/rest/client.py index 19c2f24e..378056b9 100644 --- a/plivo/rest/client.py +++ b/plivo/rest/client.py @@ -18,6 +18,7 @@ TollfreeVerifications) from plivo.resources.live_calls import LiveCalls from plivo.resources.maskingsession import MaskingSessions +from plivo.resources.transcription import Transcriptions from plivo.resources.verify_callerid import VerifyCallerids from plivo.resources.profile import Profile from plivo.resources.queued_calls import QueuedCalls @@ -123,6 +124,8 @@ def __init__(self, auth_id=None, auth_token=None, proxies=None, timeout=5): self.voice_retry_count = 0 self.verify_session = Sessions(self) self.verify_callerids = VerifyCallerids(self) + self.transcriptions = Transcriptions(self) + def __enter__(self): return self @@ -210,7 +213,7 @@ def process_response(self, '{url}'.format(url=response.url)) if method == 'DELETE': - if response.status_code not in [200, 204]: + if response.status_code not in [200, 202, 204]: raise PlivoRestError('Resource at {url} could not be ' 'deleted'.format(url=response.url)) diff --git a/plivo/version.py b/plivo/version.py index 54ec96d7..dbc23571 100644 --- a/plivo/version.py +++ b/plivo/version.py @@ -1,2 +1,2 @@ # -*- coding: utf-8 -*- -__version__ = '4.56.2' +__version__ = '4.57.0' diff --git a/setup.py b/setup.py index 13d28646..1a9a12b0 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ setup( name='plivo', - version='4.56.2', + version='4.57.0', description='A Python SDK to make voice calls & send SMS using Plivo and to generate Plivo XML', long_description=long_description, url='https://github.com/plivo/plivo-python', diff --git a/tests/resources/fixtures/transcriptionCreateResponse.json b/tests/resources/fixtures/transcriptionCreateResponse.json new file mode 100644 index 00000000..eccd081b --- /dev/null +++ b/tests/resources/fixtures/transcriptionCreateResponse.json @@ -0,0 +1,4 @@ +{ + "api_id": "c9db3f38-55e8-4d97-93b2-1ece5a342528", + "message": "transcription in progress" +} \ No newline at end of file diff --git a/tests/resources/fixtures/transcriptionDeleteResponse.json b/tests/resources/fixtures/transcriptionDeleteResponse.json new file mode 100644 index 00000000..3b7a1023 --- /dev/null +++ b/tests/resources/fixtures/transcriptionDeleteResponse.json @@ -0,0 +1,4 @@ +{ +"api_id": "47ab0f0d-a7db-4f56-8200-6555cd3194e8", +"message": "request accepted" +} \ No newline at end of file diff --git a/tests/resources/fixtures/transcriptionGetResponse.json b/tests/resources/fixtures/transcriptionGetResponse.json new file mode 100644 index 00000000..d1b33dc4 --- /dev/null +++ b/tests/resources/fixtures/transcriptionGetResponse.json @@ -0,0 +1,9 @@ +{ + "api_id": "f83b30a3-228c-4676-813e-985fcdf61201", + "cost": 0.05, + "rate": 0.05, + "recording_duration_ms": 22780, + "recording_start_ms": 1729761222174, + "status": "success", + "transcription": "\nSpeaker 0: Scan just to be safe. If you notice any error messages, please let me know immediately. They can help us diagnose the issue better. If it continues to freeze, we might need to look into your system performance. I can guide you through checking your task manager if that helps.\n\nSometimes, background processes can use up a lot of resources. I under" +} \ No newline at end of file diff --git a/tests/resources/test_multipartycalls.py b/tests/resources/test_multipartycalls.py index 8d0fe81b..465c0958 100644 --- a/tests/resources/test_multipartycalls.py +++ b/tests/resources/test_multipartycalls.py @@ -190,7 +190,8 @@ def test_add_participant(self): 'start_recording_audio_method': 'GET', 'stop_recording_audio_method': 'GET', 'create_mpc_with_single_participant': True, - 'send_on_preanswer': False + 'send_on_preanswer': False, + 'transcript': False, } add_participant_response = self.client.multi_party_calls.add_participant(friendly_name='Voice', role='agent', @@ -431,7 +432,8 @@ def test_start_recording(self): expected_method='POST', expected_request_body={'file_format': 'wav', 'recording_callback_url': recording_callback_url, - 'recording_callback_method': 'POST'}, + 'recording_callback_method': 'POST', + 'transcript': False}, actual_response=start_recording_response) def test_stop_recording(self): @@ -489,7 +491,8 @@ def test_start_participant_recording(self): expected_request_body={'file_format': 'wav', 'recording_callback_url': recording_callback_url, 'recording_callback_method': 'POST', - 'record_track_type': 'all'}, + 'record_track_type': 'all', + 'transcript': False}, actual_response=start_participant_recording_response) def test_stop_participant_recording(self): diff --git a/tests/resources/test_transcriptions.py b/tests/resources/test_transcriptions.py new file mode 100644 index 00000000..8b9b062f --- /dev/null +++ b/tests/resources/test_transcriptions.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- + +from datetime import datetime + +import plivo +from tests.base import PlivoResourceTestCase +from tests.decorators import with_response + + +class TranscriptionTest(PlivoResourceTestCase): + @with_response(200) + def test_get(self): + + transcription = self.client.transcriptions.get_transcription('e12d05fe-6979-485c-83dc-9276114dba3b') + + self.assertResponseMatches(transcription) + + # Verifying the endpoint hit + self.assertEqual( + 'https://api.plivo.com/v1/Account/MAXXXXXXXXXXXXXXXXXX/Transcription/e12d05fe-6979-485c-83dc-9276114dba3b/', + self.client.current_request.url) + + # Verifying the method used + self.assertEqual('GET', self.client.current_request.method) + + self.assertEqual('\nSpeaker 0: Scan just to be safe. If you notice any error messages, please let me know immediately. They can help us diagnose the issue better. If it continues to freeze, we might need to look into your system performance. I can guide you through checking your task manager if that helps.\n\nSometimes, background processes can use up a lot of resources. I under', transcription.transcription) + + @with_response(201) + def test_create(self): + self.client.transcriptions.create_transcription( + recording_id='8605287e-1e1a-4341-8235-23574357d6f1') + + # self.assertResponseMatches(transcription) + + # Verifying the endpoint hit + # self.assertUrlEqual( + # self.get_voice_url('Transcription', '8605287e-1e1a-4341-8235-23574357d6f1'), self.client.current_request.url) + self.assertEqual( + 'https://api.plivo.com/v1/Account/MAXXXXXXXXXXXXXXXXXX/Transcription/8605287e-1e1a-4341-8235-23574357d6f1/', + self.client.current_request.url) + + # Verifying the method used + self.assertEqual('POST', self.client.current_request.method) + + # self.assertEqual('transcription in progress',transcription.message) + + @with_response(202) + def test_delete(self): + transcription = self.client.transcriptions.delete_transcription( + '8605287e-1e1a-4341-8235-23574357d6f1') + + self.assertResponseMatches(transcription) + + # Verifying the endpoint hit + self.assertEqual( + 'https://api.plivo.com/v1/Account/MAXXXXXXXXXXXXXXXXXX/Transcription/8605287e-1e1a-4341-8235-23574357d6f1/', + self.client.current_request.url) + + # Verifying the method used + self.assertEqual('DELETE', self.client.current_request.method) + + self.assertEqual('request accepted', transcription.message) \ No newline at end of file