diff --git a/example/Async_API/Audio_API/append_audio_file.py b/example/Async_API/Audio_API/append_audio_file.py index c69bac2..4f5d6ce 100644 --- a/example/Async_API/Audio_API/append_audio_file.py +++ b/example/Async_API/Audio_API/append_audio_file.py @@ -26,3 +26,12 @@ #To get the questions from the conversation #print(conversation_object.get_questions()) + +# To get the analytics from the conversation +#print(conversation_object.get_analytics()) + +# To get the trackers from the conversation +#print(conversation_object.get_trackers()) + +# To get the entities from the conversation +#print(conversation_object.get_entities()) \ No newline at end of file diff --git a/example/Async_API/Audio_API/append_audio_url.py b/example/Async_API/Audio_API/append_audio_url.py index 778272f..6fb9480 100644 --- a/example/Async_API/Audio_API/append_audio_url.py +++ b/example/Async_API/Audio_API/append_audio_url.py @@ -25,4 +25,13 @@ #print(conversation_object.get_topics()) #To get the questions from the conversation -#print(conversation_object.get_questions()) \ No newline at end of file +#print(conversation_object.get_questions()) + +# To get the analytics from the conversation +#print(conversation_object.get_analytics()) + +# To get the trackers from the conversation +#print(conversation_object.get_trackers()) + +# To get the entities from the conversation +#print(conversation_object.get_entities()) \ No newline at end of file diff --git a/example/Async_API/Audio_API/process_audio_file.py b/example/Async_API/Audio_API/process_audio_file.py index 7f2589a..b337d95 100644 --- a/example/Async_API/Audio_API/process_audio_file.py +++ b/example/Async_API/Audio_API/process_audio_file.py @@ -3,8 +3,27 @@ file = "" ''' like this you can pass the parameter +entities = [ + { + "customType": "custom_type", + "text": "entity_name" + } + ] + +trackers = [{ + "name": "tracker_name", + "vocabulary": [ + "vocabulary_1", + "vocabulary_2", + "vocabulary_n" + ] +}] params = { 'name': "Meeting", + "detectEntities": "true", + "enableAllTrackers":"true", + "entities":entities, + 'trackers': trackers, 'enableSpeakerDiarization': "true", "diarizationSpeakerCount": "2", "channelMetadata": [ @@ -48,4 +67,13 @@ #print(conversation_object.get_topics()) #To get the questions from the conversation -#print(conversation_object.get_questions()) \ No newline at end of file +#print(conversation_object.get_questions()) + +# To get the analytics from the conversation +#print(conversation_object.get_analytics()) + +# To get the trackers from the conversation +#print(conversation_object.get_trackers()) + +# To get the entities from the conversation +#print(conversation_object.get_entities()) \ No newline at end of file diff --git a/example/Async_API/Audio_API/process_audio_url.py b/example/Async_API/Audio_API/process_audio_url.py index 40a2430..8cfc80f 100644 --- a/example/Async_API/Audio_API/process_audio_url.py +++ b/example/Async_API/Audio_API/process_audio_url.py @@ -1,9 +1,30 @@ import symbl ''' you can also pass other parameters with the payload + +entities = [ + { + "customType": "custom_type", + "text": "entity_name" + } + ] + +trackers = [{ + "name": "tracker_name", + "vocabulary": [ + "vocabulary_1", + "vocabulary_2", + "vocabulary_n" + ] +}] + payload = { 'url': "", #write the url path of the audio, which you want to process 'name': "TestingMeeting", + "detectEntities": "true", + "enableAllTrackers":"true", + "entities":entities, + 'trackers': trackers, 'enableSpeakerDiarization': "true", 'diarizationSpeakerCount': "2", 'channelMetadata': [ @@ -23,8 +44,8 @@ } ] } -''' +''' payload = {'url': ""} #write the url path of the audio, which you want to process conversation_object = symbl.Audio.process_url(payload=payload) @@ -47,4 +68,13 @@ #print(conversation_object.get_topics()) #To get the questions from the conversation -#print(conversation_object.get_questions()) \ No newline at end of file +#print(conversation_object.get_questions()) + +# To get the analytics from the conversation +#print(conversation_object.get_analytics()) + +# To get the trackers from the conversation +#print(conversation_object.get_trackers()) + +# To get the entities from the conversation +#print(conversation_object.get_entities()) \ No newline at end of file diff --git a/example/Async_API/Text_API/append_text.py b/example/Async_API/Text_API/append_text.py index 01c0ff8..00e1b3e 100644 --- a/example/Async_API/Text_API/append_text.py +++ b/example/Async_API/Text_API/append_text.py @@ -38,4 +38,13 @@ #print(conversation_object.get_topics()) #To get the questions from the conversation -#print(conversation_object.get_questions()) \ No newline at end of file +#print(conversation_object.get_questions()) + +# To get the analytics from the conversation +#print(conversation_object.get_analytics()) + +# To get the trackers from the conversation +#print(conversation_object.get_trackers()) + +# To get the entities from the conversation +#print(conversation_object.get_entities()) \ No newline at end of file diff --git a/example/Async_API/Text_API/process_text.py b/example/Async_API/Text_API/process_text.py index 6bab81e..a446c0a 100644 --- a/example/Async_API/Text_API/process_text.py +++ b/example/Async_API/Text_API/process_text.py @@ -1,7 +1,29 @@ import symbl +#you can add the different vocabulary, which you would like to track +trackers = [{ + "name": "text_tracker", + "vocabulary": [ + "white", + "issues", + "vaccination" + ] +}] payload = { + "name": "TextAPI", # you can update the name of the conversation + + #"trackers": trackers, #To detect the trackers + + #"detectEntities": "true", #To get the entities + + #To define Custom entities + "entities": [ + { + "customType": "identify_org", + "text": "platform" + } + ], "messages": [ { "payload": {"content": "Hi Anthony. I saw your complaints about bad call reception on your mobile phone. Can I know what issues you are currently facing?"}, @@ -48,3 +70,12 @@ # To get the questions from the conversation # print(conversation_object.get_questions()) + +# To get the analytics from the conversation +#print(conversation_object.get_analytics()) + +# To get the trackers from the conversation +#print(conversation_object.get_trackers()) + +# To get the entities from the conversation +#print(conversation_object.get_entities()) \ No newline at end of file diff --git a/example/Async_API/Video_API/append_video_file.py b/example/Async_API/Video_API/append_video_file.py index 3018055..ff1c6fb 100644 --- a/example/Async_API/Video_API/append_video_file.py +++ b/example/Async_API/Video_API/append_video_file.py @@ -26,4 +26,13 @@ #print(conversation_object.get_topics()) #To get the questions from the conversation -#print(conversation_object.get_questions()) \ No newline at end of file +#print(conversation_object.get_questions()) + +# To get the analytics from the conversation +#print(conversation_object.get_analytics()) + +# To get the trackers from the conversation +#print(conversation_object.get_trackers()) + +# To get the entities from the conversation +#print(conversation_object.get_entities()) \ No newline at end of file diff --git a/example/Async_API/Video_API/append_video_url.py b/example/Async_API/Video_API/append_video_url.py index 42b3185..8ecde7d 100644 --- a/example/Async_API/Video_API/append_video_url.py +++ b/example/Async_API/Video_API/append_video_url.py @@ -25,4 +25,13 @@ #print(conversation_object.get_topics()) #To get the questions from the conversation -#print(conversation_object.get_questions()) \ No newline at end of file +#print(conversation_object.get_questions()) + +# To get the analytics from the conversation +#print(conversation_object.get_analytics()) + +# To get the trackers from the conversation +#print(conversation_object.get_trackers()) + +# To get the entities from the conversation +#print(conversation_object.get_entities()) \ No newline at end of file diff --git a/example/Async_API/Video_API/process_video_file.py b/example/Async_API/Video_API/process_video_file.py index 328387c..f6a8638 100644 --- a/example/Async_API/Video_API/process_video_file.py +++ b/example/Async_API/Video_API/process_video_file.py @@ -2,8 +2,27 @@ file = "" ''' like this you can pass the parameter +entities = [ + { + "customType": "custom_type", + "text": "entity_name" + } + ] + +trackers = [{ + "name": "tracker_name", + "vocabulary": [ + "vocabulary_1", + "vocabulary_2", + "vocabulary_n" + ] +}] params = { - 'name': "TestingMeeting", + 'name': "Meeting", + "detectEntities": "true", + "enableAllTrackers":"true", + "entities":entities, + 'trackers': trackers, 'enableSpeakerDiarization': "true", "diarizationSpeakerCount": "2", "channelMetadata": [ @@ -47,4 +66,13 @@ #print(conversation_object.get_topics()) #To get the questions from the conversation -#print(conversation_object.get_questions()) \ No newline at end of file +#print(conversation_object.get_questions()) + +# To get the analytics from the conversation +#print(conversation_object.get_analytics()) + +# To get the trackers from the conversation +#print(conversation_object.get_trackers()) + +# To get the entities from the conversation +#print(conversation_object.get_entities()) \ No newline at end of file diff --git a/example/Async_API/Video_API/process_video_url.py b/example/Async_API/Video_API/process_video_url.py index 562fa03..6054040 100644 --- a/example/Async_API/Video_API/process_video_url.py +++ b/example/Async_API/Video_API/process_video_url.py @@ -2,10 +2,29 @@ ''' you can also pass other parameters with the payload +entities = [ + { + "customType": "custom_type", + "text": "entity_name" + } + ] + +trackers = [{ + "name": "tracker_name", + "vocabulary": [ + "vocabulary_1", + "vocabulary_2", + "vocabulary_n" + ] +}] payload = { 'url': "", #write the url path of the video, which you want to process 'name': "TestingMeeting", + "detectEntities": "true", + "enableAllTrackers":"true", + "entities":entities, + 'trackers': trackers, 'enableSpeakerDiarization': "true", 'diarizationSpeakerCount': "2", 'channelMetadata': [ @@ -26,7 +45,6 @@ ] } - conversation_object = symbl.Video.process_url(payload=payload) ''' @@ -53,4 +71,13 @@ #print(conversation_object.get_topics()) #To get the questions from the conversation -#print(conversation_object.get_questions()) \ No newline at end of file +#print(conversation_object.get_questions()) + +# To get the analytics from the conversation +#print(conversation_object.get_analytics()) + +# To get the trackers from the conversation +#print(conversation_object.get_trackers()) + +# To get the entities from the conversation +#print(conversation_object.get_entities()) \ No newline at end of file diff --git a/example/Conversation_Class/conversation_class.py b/example/Conversation_Class/conversation_class.py index 1da5b59..9cb6e1f 100644 --- a/example/Conversation_Class/conversation_class.py +++ b/example/Conversation_Class/conversation_class.py @@ -1,6 +1,6 @@ import symbl -conversation_id=1234567890 # Update with the conversation Id of your conversation +conversation_id=5180676375576576 # Update with the conversation Id of your conversation print(symbl.Conversations.get_messages(conversation_id)) print(symbl.Conversations.get_conversation(conversation_id)) @@ -8,4 +8,7 @@ print(symbl.Conversations.get_follow_ups(conversation_id)) print(symbl.Conversations.get_members(conversation_id)) print(symbl.Conversations.get_topics(conversation_id)) -print(symbl.Conversations.get_questions(conversation_id)) \ No newline at end of file +print(symbl.Conversations.get_questions(conversation_id)) +print(symbl.Conversations.get_analytics(conversation_id)) +print(symbl.Conversations.get_trackers(conversation_id)) +print(symbl.Conversations.get_entities(conversation_id)) \ No newline at end of file diff --git a/example/Streaming_API/streaming.py b/example/Streaming_API/streaming.py index 0f0c840..d769fa9 100644 --- a/example/Streaming_API/streaming.py +++ b/example/Streaming_API/streaming.py @@ -6,10 +6,22 @@ 'message': lambda message: print('printing the message response ', str(message)) # ,'message_response': lambda message: print('printing the transcription', str(message)) # ,'insight_response': lambda insight: print('printing the insight response ', str(insight)) - # ,'tracker_response': lambda tracker: print('printing the tracker response ', str(tracker)) + #,'tracker_response': lambda tracker: print('printing the tracker response ', str(tracker)) # ,'topic_response': lambda topic: print('printing the topic response ', str(topic)) } + +#To access the Trackers API, you will need to specify 'tracker_response' event +trackers = [{ + "name": "tracker_name", + "vocabulary": [ + "hello", + "vocabulary_2", + "vocabulary_n" + ] +}] + + insight_types = ['question', 'action_item'] speaker = { @@ -18,7 +30,7 @@ } connection_object = symbl.Streaming.start_connection( - insight_types=insight_types, speaker=speaker) + insight_types=insight_types, speaker=speaker,trackers=trackers) connection_object.subscribe(events) @@ -46,4 +58,8 @@ #print(connection_object.conversation.get_topics()) #To get the questions from the conversation -#print(connection_object.conversation.get_questions()) \ No newline at end of file +#print(connection_object.conversation.get_questions()) + +# To get the analytics from the conversation +#print(connection_object.conversation.get_analytics()) + diff --git a/example/Telephony_API/telephony_pstn.py b/example/Telephony_API/telephony_pstn.py index 9d07e0d..ef1274b 100644 --- a/example/Telephony_API/telephony_pstn.py +++ b/example/Telephony_API/telephony_pstn.py @@ -13,7 +13,6 @@ 'transcript_response': lambda transcript: print('printing the transcript response ', str(transcript)) ,'message_response': lambda message: print('printing the message response ', str(message)) #,'insight_response': lambda insight: print('printing the insight response ', str(insight)) - #,'tracker_response': lambda tracker: print('printing the tracker response ', str(tracker)) #,'topic_response': lambda topic: print('printing the topic response ', str(topic)) } @@ -57,3 +56,7 @@ # To get the questions from the meeting # print(connection_object.conversation.get_questions()) + +# To get the analytics from the conversation +#print(connection_object.conversation.get_analytics()) + diff --git a/example/Telephony_API/telephony_sip.py b/example/Telephony_API/telephony_sip.py index 5bd3c0f..e375397 100644 --- a/example/Telephony_API/telephony_sip.py +++ b/example/Telephony_API/telephony_sip.py @@ -7,7 +7,6 @@ 'transcript_response': lambda transcript: print('printing the transcript response ', str(transcript)) ,'message_response': lambda message: print('printing the message response ', str(message)) #,'insight_response': lambda insight: print('printing the insight response ', str(insight)) - #,'tracker_response': lambda tracker: print('printing the tracker response ', str(tracker)) #,'topic_response': lambda topic: print('printing the topic response ', str(topic)) } @@ -39,3 +38,6 @@ # To get the questions from the conversation # print(connection_object.conversation.get_questions()) + +# To get the analytics from the conversation +#print(connection_object.conversation.get_analytics()) diff --git a/requirements.txt b/requirements.txt index 1ec8a11..2a7c5ea 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -symbl_rest >= 1.0.0 +symbl_rest >= 1.0.9 websocket-client >= 0.59.0 sounddevice >= 0.4.1 numpy \ No newline at end of file diff --git a/setup.py b/setup.py index 2393419..8d4a3ce 100644 --- a/setup.py +++ b/setup.py @@ -20,12 +20,12 @@ setup( name="symbl", - version="1.0.14", + version="1.0.15", description="symbl.ai SDK", author_email="info@symbl.ai", url="", keywords=["Symbl.ai SDK"], - install_requires=["symbl_rest >= 1.0.6", "websocket-client >= 0.59.0", "sounddevice >= 0.4.1", "numpy"], + install_requires=["symbl_rest >= 1.0.9", "websocket-client >= 0.59.0", "sounddevice >= 0.4.1", "numpy"], packages=find_packages(), include_package_data=True, long_description="""\ diff --git a/symbl/Conversations.py b/symbl/Conversations.py index ee1db83..b98c9a2 100644 --- a/symbl/Conversations.py +++ b/symbl/Conversations.py @@ -77,3 +77,15 @@ def get_topics(self, parameters={}): def get_conversation(self): return self.__conversation_api.get_conversation(self.__conversation_id, credentials=self.__credentials) + @validate_conversation_id + def get_trackers(self): + return self.__conversation_api.get_trackers(self.__conversation_id, credentials=self.__credentials) + + @validate_conversation_id + def get_entities(self): + return self.__conversation_api.get_entities(self.__conversation_id, credentials=self.__credentials) + + @validate_conversation_id + def get_analytics(self): + return self.__conversation_api.get_analytics(self.__conversation_id, credentials=self.__credentials) + diff --git a/symbl/conversations_api/ConversationsApi.py b/symbl/conversations_api/ConversationsApi.py index 374a299..01ff4a3 100644 --- a/symbl/conversations_api/ConversationsApi.py +++ b/symbl/conversations_api/ConversationsApi.py @@ -1,6 +1,6 @@ from symbl.utils.Helper import correct_boolean_values, dictionary_to_valid_json, initialize_api_client from symbl_rest import ConversationsApi as conversations_api_rest - +from symbl.utils import Helper class ConversationsApi(): @@ -40,3 +40,17 @@ def get_topics(self, conversation_id, credentials=None, parameters={}): @initialize_api_client def get_conversation(self, conversation_id, credentials=None): return self.conversations_api_rest.get_conversation_by_conversation_id(conversation_id) + + @initialize_api_client + def get_trackers(self, conversation_id, credentials=None): + return self.conversations_api_rest.get_trackers_by_conversation_id(conversation_id) + + @initialize_api_client + def get_entities(self, conversation_id, credentials=None): + api_response = self.conversations_api_rest.get_entities_by_conversation_id(conversation_id) + return Helper.parse_entity_response(api_response) if len(api_response.entities)!=0 else api_response + + @initialize_api_client + def get_analytics(self, conversation_id, credentials=None): + return self.conversations_api_rest.get_analytics_by_conversation_id(conversation_id) + diff --git a/symbl/readme.md b/symbl/readme.md index d5bc703..c1fc906 100644 --- a/symbl/readme.md +++ b/symbl/readme.md @@ -123,7 +123,7 @@ You can utilize different functions of Async APIs by directly utilizing `symbl.V >file_path | Mandatory | A valid path to a file >conversation_id | Mandatory | conversationId of a previous conversation to which appending the current conversation >credentials | optional | Don't add this parameter if you have `symbl.conf` file in your home directory or working directory - >content_type | optional | Parameter defining the content_type of video. Acceptable values is [`video/mp4`]. Leave it blank if you're not sure about the content_type of file + >content_type | optional | Parameter defining the content_type of video. Acceptable values is [`application/json`]. Leave it blank if you're not sure about the content_type of file >wait | optional | (by default True) Boolean, Value `False` will execute the function submit_video on a separate thread making it a non-blocking API call (Has callback support) >parameters | optional | (by default {}) Dictionary, Any parameter and it's value can be provided in the dictionary format. For getting a list of value check [here](https://docs.symbl.ai/docs/async-api/overview/video/put-video#query-params) @@ -180,36 +180,50 @@ You can utilize different functions of Async APIs by directly utilizing `symbl.T Conversation object is returned by Async API Text, Audio and Video classes. The conversation object is a shorthand for conversation API and can be utilized for fetching multiple insights. -1. conversation.get_action_items(): +1. conversation_object.get_action_items(): >returns Action Items which are some specific outcomes recognized in the conversation that requires one or more people in the conversation to act in the future -2. conversation.get_follow_ups(): +2. conversation_object.get_follow_ups(): >returns a category of action items with a connotation to follow-up a request or a task like sending an email or making a phone call or booking an appointment or setting up a meeting. -3. conversation.get_members(): +3. conversation_object.get_members(): >returns a list of all the members in a conversation. A Member is referred to as a participant in the conversation that is uniquely identified as a speaker. Identifying different participants in the meetings can be done by implementing speaker separation. -4. conversation.get_messages(): +4. conversation_object.get_messages(): >parameters:- (Optional) dictionary, takes a dictionary of parameters. For list of parameters accepted, please click [here](https://docs.symbl.ai/docs/conversation-api/messages#query-params) > >returns a list of messages (sentences spoken by speakers) in a conversation. You can use this for providing transcription for video conference, meeting or telephone call. -5. conversation.get_questions(): +5. conversation_object.get_questions(): + >returns explicit question or request for information that comes up during the conversation, whether answered or not, is recognized as a question. -6. conversation.get_topics(): +6. conversation_object.get_topics(): >parameters:- (Optional) dictionary, takes a dictionary of parameters. For list of parameters accepted, please click [here](https://docs.symbl.ai/docs/conversation-api/get-topics#query-params) > >returns The most relevant topics of discussion from the conversation that is generated based on the combination of the overall scope of the discussion. -7. conversation.get_conversation(): +7. conversation_object.get_conversation(): >returns the conversation meta-data like meeting name, member name and email, start and end time of the meeting, meeting type and meeting id. + +8. conversation_object.get_entities(conversation_id) + + >provides a functionality to extract entities(custom, location, person, date, number, organization,datetime,daterange, etc ) from the conversation. + +9. conversation_object.get_trackers(conversation_id) + + >returns the occurrence of certain key words or phrases from the conversation. + +10. conversation_object.get_analytics(conversation_id) + + >returns the speaker ratio, talk time, silence, pace and overlap from the conversation. + > >example for demonstrate the use of conversation class > @@ -225,6 +239,10 @@ print(conversation_object.get_follow_ups()) print(conversation_object.get_members()) print(conversation_object.get_topics()) print(conversation_object.get_questions()) +print(conversation_object.get_conversation()) +print(conversation_object.get_analytics()) +print(conversation_object.get_entities()) +print(conversation_object.get_trackers()) ``` # Conversations class @@ -266,6 +284,18 @@ You can utilize different functions of Conversation APIs by directly utilizing ` >returns the conversation meta-data like meeting name, member name and email, start and end time of the meeting, meeting type and meeting id. +8. get_entities(conversation_id) + + >provides a functionality to extract entities(custom, location, person, date, number, organization,datetime,daterange, etc ) from the conversation. + +9. get_trackers(conversation_id) + + >returns the occurrence of certain key words or phrases from the conversation. + +10. get_analytics(conversation_id) + + >returns the speaker ratio, talk time, silence, pace and overlap from the conversation. + >example for demonstrate the use of conversation class > ``` @@ -332,8 +362,7 @@ Based on PSTN and SIP protocols, the Telephony API provides an interface for the > 1. **insight_response**:- generates an event whenever a question or an action_item is found. > 2. **message_response**:- generates an event whenever a transcription is available. > 3. **transcript_response**:- (Part of telephony API only), these are also transcription values, however these will include an isFinal property which will be False initially meaning the transcription are not finalized. - > 4. **tracker_response**:- It will generate an event whenever a tracker is identified in any transcription. - > 5. **topic_response**:- It will generate an event whenever a topic is identified in any transcription. + > 4. **topic_response**:- It will generate an event whenever a topic is identified in any transcription. >by this way you can subscribe the events > @@ -394,7 +423,7 @@ Symbl's Streaming API is based on WebSocket protocol and can be used for real-ti The connection object is returned by telephony API's start_pstn & start_sip or Streaming API' start_connection function. A connection object can be utilized for communicating with Symbl Server through underlying websocket implementation. -1. connection.subscribe({'event': callback, ...}): +1. connection_object.subscribe({'event': callback, ...}): > >**subscribe function can be used with both Telephony as well as Streaming class** > @@ -417,13 +446,13 @@ The connection object is returned by telephony API's start_pstn & start_sip or S 'insight_response': lambda insight: print('printing the insight response ', str(insight))} ``` -2. connection.stop(): +2. connection_object.stop(): > >**stop function can be used with both Telephony as well as Streaming class** > >used to stop the telephony connection. -3. connection.send_audio_from_mic(device=None): +3. connection_object.send_audio_from_mic(device=None): > >**send_audio_from_mic function can be used with Streaming class only** > @@ -433,7 +462,7 @@ The connection object is returned by telephony API's start_pstn & start_sip or S > >If this function is not running correctly, please make sure the sounddevice library is installed correctly and has access to your microphone. For more details, check [here][sound_device-installation] -4. connection.send_audio(data): +4. connection_object.send_audio(data): > >**send_audio function can be used with Streaming class only** > diff --git a/symbl/streaming_api/StreamingApi.py b/symbl/streaming_api/StreamingApi.py index d667cf7..91c9a42 100644 --- a/symbl/streaming_api/StreamingApi.py +++ b/symbl/streaming_api/StreamingApi.py @@ -14,7 +14,7 @@ def __init__(self): pass - def start_connection(self, credentials=None, speaker=None, insight_types=None, config={}): + def start_connection(self, credentials=None, speaker=None, insight_types=None, config={},trackers=None): randomId = bytes(''.join(random.choices(string.ascii_uppercase +string.digits, k=12)), 'utf-8') id = base64.b64encode(randomId).decode("utf-8") url = SYMBL_STREAMING_API_FORMAT.format(id, get_access_token(credentials=credentials)) @@ -38,6 +38,7 @@ def start_connection(self, credentials=None, speaker=None, insight_types=None, c "type": "start_request", "insightTypes": [] if insight_types == None else [] if type(insight_types) != list else insight_types, "speaker": speaker, + "trackers":trackers, "config": config_object } diff --git a/symbl/utils/Helper.py b/symbl/utils/Helper.py index 0e1c615..fbed868 100644 --- a/symbl/utils/Helper.py +++ b/symbl/utils/Helper.py @@ -1,6 +1,8 @@ import json from symbl import AuthenticationToken +import datetime +DATE_FORMAT = '%Y-%m-%d %H:%M:%S' def correct_boolean_values(dictionary: dict): for key in dictionary: @@ -32,4 +34,51 @@ def wrapper(*args, **kw): return function(*args, **kw) - return wrapper \ No newline at end of file + return wrapper + +#verify date format +def verify_date(date): + try: + datetime.datetime.strptime(date, '%Y-%m-%d') + return True + except ValueError: + return False + +#Parse date format +def deserialize_date(strISODateString): + """Deserializes string to date. + :param strISODateString: str. + :return: date. + """ + try: + from datetime import datetime + return datetime.strptime(strISODateString, DATE_FORMAT) + except ImportError: + return strISODateString + except ValueError: + raise Exception( + status=0, + reason="Failed to parse `{0}` as date object".format(strISODateString) + ) + +#This function will remove the None values from the API response, and will also parse the date format +def parse_entity_response(api_response): + api_response=api_response.entities + count = len(api_response) + entity_response=[] + + keys = ['custom_type','end','message_refs','start','type','text','value'] + + for obj in range(0,count): + entity_res = dict() + for key in keys: + val = getattr(api_response[obj],key) + if val is not None: + if key=='value': + if verify_date(val): + val = "".join([val," 00:00:00"]) + val = deserialize_date(val) + entity_res[key]=val + entity_response.append(entity_res) + + return dict(entities=entity_response) \ No newline at end of file diff --git a/tests/conversations_api_test.py b/tests/conversations_api_test.py index b9a3728..76472a7 100644 --- a/tests/conversations_api_test.py +++ b/tests/conversations_api_test.py @@ -49,6 +49,35 @@ def test_get_topics_should_succeed_given_valid_conversation_id(self): with patch("symbl.AuthenticationToken.get_api_client", Mock(return_value="None")), patch("symbl_rest.ConversationsApi.get_topics_by_conversation_id", Mock(return_value=demo_response)): self.assertEqual(demo_response, conversations_api.get_topics("6549352073920512")) + + def test_get_conversation_should_succeed_given_valid_conversation_id(self): + demo_response = SimpleNamespace(**{"id": "5102778889273344","type": "meeting","name": "TestingTextAPI","startTime": "2021-07-27T07:11:04.304Z","endTime": "2021-07-27T07:13:19.184Z","members": [{"id": "461dd687-4341-48a5-9f3a-7f6019d6378c","name": "John","email": "john@example.com"}]}) + conversations_api = ConversationsApi() + + with patch("symbl.AuthenticationToken.get_api_client", Mock(return_value="None")), patch("symbl_rest.ConversationsApi.get_conversation_by_conversation_id", Mock(return_value=demo_response)): + self.assertEqual(demo_response, conversations_api.get_conversation("6549352073920512")) + + def test_get_trackers_should_succeed_given_valid_conversation_id(self): + demo_response = SimpleNamespace(**{ "id": "5243525907087360", "name": "text_tracker", "matches": [ { "messageRefs": [ { "id": "5867975128121344", "text": "I don't know which platform is it, but I came to know that platform.", "offset": 19 }, { "id": "6328818106105856", "text": "So this is a live demo that we are trying to give very we are going to show how the platform detects various insights can do transcription in real time and also the different topics of discussions, which would be generated after the call is over, and they will be an email that will be sent to the inbox.", "offset": 84 } ], "type": "vocabulary", "value": "platform", "insightRefs": [] } ] }) + conversations_api = ConversationsApi() + + with patch("symbl.AuthenticationToken.get_api_client", Mock(return_value="None")), patch("symbl_rest.ConversationsApi.get_trackers_by_conversation_id", Mock(return_value=demo_response)): + self.assertEqual(demo_response, conversations_api.get_trackers("6549352073920512")) + + def test_get_entities_should_succeed_given_valid_conversation_id(self): + demo_response = SimpleNamespace(**{"entities":[{"custom_type":"None","type":"person","value":"richard holmes","text":"richard holmes","end":"None","start":"None","messageRefs":[{"id":"5895830172073984","text":"We need to have the meeting today, and we're going to talk about how to run a product strategy Workshop is by Richard Holmes.","offset":111}]}]}) + conversations_api = ConversationsApi() + + with patch("symbl.AuthenticationToken.get_api_client", Mock(return_value="None")), patch("symbl_rest.ConversationsApi.get_entities_by_conversation_id", Mock(return_value=demo_response)), patch("symbl.utils.Helper.parse_entity_response", Mock(return_value=demo_response)): + self.assertEqual(demo_response, conversations_api.get_entities("6549352073920512")) + + def test_get_analytics_should_succeed_given_valid_conversation_id(self): + demo_response = SimpleNamespace(**{"metrics": [{"type": "total_silence","percent": 0,"seconds": 0},{"type": "total_talk_time","percent": 100,"seconds": 134.88},{"type": "total_overlap","percent": 0,"seconds": 0}],"members": [{"id": "461dd687-4341-48a5-9f3a-7f6019d6378c","name": "John","userId": "john@example.com","pace": {"wpm": 124},"talkTime": {"percentage": 100,"seconds": 134.88},"listenTime": {"percentage": 0,"seconds": 0},"overlap": {}}]}) + conversations_api = ConversationsApi() + + with patch("symbl.AuthenticationToken.get_api_client", Mock(return_value="None")), patch("symbl_rest.ConversationsApi.get_analytics_by_conversation_id", Mock(return_value=demo_response)): + self.assertEqual(demo_response, conversations_api.get_analytics("6549352073920512")) + if __name__ == '__main__': unittest.main() diff --git a/tests/conversations_test.py b/tests/conversations_test.py index cd76237..6d3324b 100644 --- a/tests/conversations_test.py +++ b/tests/conversations_test.py @@ -50,5 +50,42 @@ def test_get_topics_should_succeed_given_valid_conversation_id(self): with patch("symbl.AuthenticationToken.get_api_client", Mock(return_value="None")), patch("symbl.ConversationsApi.get_topics", Mock(return_value=demo_response)): self.assertEqual(demo_response, conversations_object.get_topics()) + def test_get_conversation_should_succeed_given_valid_conversation_id(self): + demo_response = SimpleNamespace(**{"id": "5102778889273344","type": "meeting","name": "TestingTextAPI","startTime": "2021-07-27T07:11:04.304Z","endTime": "2021-07-27T07:13:19.184Z","members": [{"id": "461dd687-4341-48a5-9f3a-7f6019d6378c","name": "John","email": "john@example.com"}]}) + conversations_object = Conversation("6549352073920512") + + with patch("symbl.AuthenticationToken.get_api_client", Mock(return_value="None")), patch("symbl.ConversationsApi.get_conversation", Mock(return_value=demo_response)): + self.assertEqual(demo_response, conversations_object.get_conversation()) + + + def test_get_analytics_should_succeed_given_valid_conversation_id(self): + demo_response = SimpleNamespace(**{"metrics": [{"type": "total_silence","percent": 0,"seconds": 0},{"type": "total_talk_time","percent": 100,"seconds": 134.88},{"type": "total_overlap","percent": 0,"seconds": 0}],"members": [{"id": "461dd687-4341-48a5-9f3a-7f6019d6378c","name": "John","userId": "john@example.com","pace": {"wpm": 124},"talkTime": {"percentage": 100,"seconds": 134.88},"listenTime": {"percentage": 0,"seconds": 0},"overlap": {}}]}) + conversations_object = Conversation("6549352073920512") + + with patch("symbl.AuthenticationToken.get_api_client", Mock(return_value="None")), patch("symbl.ConversationsApi.get_analytics", Mock(return_value=demo_response)): + self.assertEqual(demo_response, conversations_object.get_analytics()) + + def test_get_trackers_should_succeed_given_valid_conversation_id(self): + demo_response = SimpleNamespace(**{ "id": "5243525907087360", "name": "text_tracker", "matches": [ { "messageRefs": [ { "id": "5867975128121344", "text": "I don't know which platform is it, but I came to know that platform.", "offset": 19 }, { "id": "6328818106105856", "text": "So this is a live demo that we are trying to give very we are going to show how the platform detects various insights can do transcription in real time and also the different topics of discussions, which would be generated after the call is over, and they will be an email that will be sent to the inbox.", "offset": 84 } ], "type": "vocabulary", "value": "platform", "insightRefs": [] } ] }) + conversations_object = Conversation("6549352073920512") + + with patch("symbl.AuthenticationToken.get_api_client", Mock(return_value="None")), patch("symbl.ConversationsApi.get_trackers", Mock(return_value=demo_response)): + self.assertEqual(demo_response, conversations_object.get_trackers()) + + def test_get_entities_should_succeed_given_valid_conversation_id(self): + demo_response = SimpleNamespace(**{"entities":[{"custom_type":"None","type":"person","value":"richard holmes","text":"richard holmes","end":"None","start":"None","messageRefs":[{"id":"5895830172073984","text":"We need to have the meeting today, and we're going to talk about how to run a product strategy Workshop is by Richard Holmes.","offset":111}]}]}) + conversations_object = Conversation("6549352073920512") + + with patch("symbl.AuthenticationToken.get_api_client", Mock(return_value="None")), patch("symbl.ConversationsApi.get_entities", Mock(return_value=demo_response)): + self.assertEqual(demo_response, conversations_object.get_entities()) + + def test_get_analytics_should_succeed_given_valid_conversation_id(self): + demo_response = SimpleNamespace(**{"metrics": [{"type": "total_silence","percent": 0,"seconds": 0},{"type": "total_talk_time","percent": 100,"seconds": 134.88},{"type": "total_overlap","percent": 0,"seconds": 0}],"members": [{"id": "461dd687-4341-48a5-9f3a-7f6019d6378c","name": "John","userId": "john@example.com","pace": {"wpm": 124},"talkTime": {"percentage": 100,"seconds": 134.88},"listenTime": {"percentage": 0,"seconds": 0},"overlap": {}}]}) + conversations_object = Conversation("6549352073920512") + + with patch("symbl.AuthenticationToken.get_api_client", Mock(return_value="None")), patch("symbl.ConversationsApi.get_analytics", Mock(return_value=demo_response)): + self.assertEqual(demo_response, conversations_object.get_analytics()) + + if __name__ == '__main__': unittest.main()