async def _mention_activity(self, turn_context: TurnContext): mention = Mention( mentioned=turn_context.activity.from_property, text=f"<at>{turn_context.activity.from_property.name}</at>", type="mention", ) reply_activity = MessageFactory.text(f"Hello {mention.text}") reply_activity.entities = [Mention().deserialize(mention.serialize())] await turn_context.send_activity(reply_activity)
def __send(self, text, conversation, mentions=None): logger.info(f"Sending message: {text}") entities = list() if mentions is None: mentions = list() for name in mentions: user_id = self._user_map.get(name) if not user_id: logger.info("User not found: %s" % name) continue mention = Mention(mentioned=ChannelAccount(id=user_id, name=name), text="<at>%s</at>" % name, type="mention") entities.append(mention) credentials = MicrosoftAppCredentials(self._app_id, self._app_password) connector = ConnectorClient(credentials, base_url=self._service_url) reply = Activity( type=ActivityTypes.message, channel_id=self._current_channel, conversation=conversation, from_property=ChannelAccount(id=self._current_bot_id["id"], name=self._current_bot_id["name"]), entities=entities, text=text, service_url=self._service_url) response = connector.conversations.send_to_conversation(reply.conversation.id, reply) logger.info(response)
async def on_message_activity(self, turn_context: TurnContext): mention_data = { "mentioned": turn_context.activity.from_property, "text": f"<at>{turn_context.activity.from_property.name}</at>", "type": "mention", } mention_object = Mention(**mention_data) reply_activity = MessageFactory.text(f"Hello {mention_object.text}") reply_activity.entities = [mention_object] await turn_context.send_activity(reply_activity)
def test_should_remove_at_mention_from_activity(self): activity = Activity( type="message", text="<at>TestOAuth619</at> test activity", recipient=ChannelAccount(id="TestOAuth619"), entities=[ Mention( type="mention", text="<at>TestOAuth619</at>", mentioned=ChannelAccount(name="Bot", id="TestOAuth619"), ) ], ) text = TurnContext.remove_recipient_mention(activity) assert text, " test activity" assert activity.text, " test activity"
def test_should_remove_at_mention_with_regex_characters(self): activity = Activity( type="message", text="<at>Test (*.[]$%#^&?)</at> test activity", recipient=ChannelAccount(id="Test (*.[]$%#^&?)"), entities=[ Entity().deserialize( Mention( type="mention", text="<at>Test (*.[]$%#^&?)</at>", mentioned=ChannelAccount(name="Bot", id="Test (*.[]$%#^&?)"), ).serialize()) ], ) text = TurnContext.remove_recipient_mention(activity) assert text == " test activity" assert activity.text == " test activity"
async def test_should_replicate_activity_data_to_listening_emulator_following_open_and_attach_with_at_mention( self ): inbound_expectation, outbound_expectation, state_expectation = ( False, False, False, ) with requests_mock.Mocker() as mocker: # set up our expectations in nock - each corresponds to a trace message we expect to receive in the emulator def match_response(request): nonlocal inbound_expectation, outbound_expectation, state_expectation r_json = loads(request.text) if r_json.get("type", None) != "trace": return None if r_json.get("value", {}).get("text", None) == "hi": inbound_expectation = True return inbound_expectation if r_json.get("value", {}).get("text", None) == "echo: hi": outbound_expectation = True return outbound_expectation x_property = ( r_json.get("value", {}) .get("user_state", {}) .get("x", {}) .get("property", None) ) y_property = ( r_json.get("value", {}) .get("conversation_state", {}) .get("y", {}) .get("property", None) ) state_expectation = x_property == "hello" and y_property == "world" return state_expectation mocker.post( "https://test.com/v3/conversations/Convo1/activities", additional_matcher=match_response, json={"id": "test"}, status_code=200, ) # create the various storage and middleware objects we will be using storage = MemoryStorage() inspection_state = InspectionState(storage) user_state = UserState(storage) conversation_state = ConversationState(storage) inspection_middleware = InspectionMiddleware( inspection_state, user_state, conversation_state ) # the emulator sends an /INSPECT open command - we can use another adapter here open_activity = MessageFactory.text("/INSPECT open") async def exec_test(turn_context): await inspection_middleware.process_command(turn_context) inspection_adapter = TestAdapter(exec_test, None, True) await inspection_adapter.receive_activity(open_activity) inspection_open_result_activity = inspection_adapter.activity_buffer[0] recipient_id = "bot" attach_command = ( f"<at>{ recipient_id }</at> { inspection_open_result_activity.value }" ) # the logic of teh bot including replying with a message and updating user and conversation state x_prop = user_state.create_property("x") y_prop = conversation_state.create_property("y") async def exec_test2(turn_context): await turn_context.send_activity( MessageFactory.text(f"echo: {turn_context.activity.text}") ) (await x_prop.get(turn_context, {"property": ""}))["property"] = "hello" (await y_prop.get(turn_context, {"property": ""}))["property"] = "world" await user_state.save_changes(turn_context) await conversation_state.save_changes(turn_context) application_adapter = TestAdapter(exec_test2, None, True) # IMPORTANT add the InspectionMiddleware to the adapter that is running our bot application_adapter.use(inspection_middleware) attach_activity = Activity( type=ActivityTypes.message, text=attach_command, recipient=ChannelAccount(id=recipient_id), entities=[ Mention( type="mention", text=f"<at>{recipient_id}</at>", mentioned=ChannelAccount(name="Bot", id=recipient_id), ) ], ) await application_adapter.receive_activity(attach_activity) # the attach command response is a informational message await application_adapter.receive_activity(MessageFactory.text("hi")) # trace activities should be sent to the emulator using the connector and the conversation reference # verify that all our expectations have been met assert inbound_expectation assert outbound_expectation assert state_expectation assert mocker.call_count, 3
async def on_message_activity(self, turn_context: TurnContext): """ Respond to messages sent from the user. """ self._add_conversation_reference(turn_context.activity) global trak_name global trak_allergy_url global trak_careProvider global trak_dob global trak_gender global trak_recordNumber global trak_url global gname global trak_lastUpdated global allergy_data global OAuth_url global r_name global r_urn global r_url global ob_url global r_sender global r_message # Get the state properties from the turn context. welcome_user_state = await self.user_state_accessor.get( turn_context, WelcomeUserState) if not welcome_user_state.did_welcome_user: welcome_user_state.did_welcome_user = True # Will be on first message from user await turn_context.send_activity("Welcome Back !") name = turn_context.activity.from_property.name gname = name await turn_context.send_activity( f"What can I help you with {name} ?") else: # removes mention from the user input in channels or group TurnContext.remove_recipient_mention(turn_context.activity) # Credentials for OAuth2 authorize_url = "https://tcfhirsandbox.intersystems.com.au/oauth2/authorize" token_url = "https://tcfhirsandbox.intersystems.com.au/oauth2/token" state = 'asdasdasdasdasdasasd' scope = 'patient%2F*.read%20launch%2Fpatient' callback_uri = "x-argonaut-app://HealthProviderLogin/" my_redirect = "https://23deef16c21f.ngrok.io/api/auth_code" test_redirect = "https://www.intersystems.com" client_id = '6A605kYem9GmG38Vo6TTzh8IFnjWHZWtRn46K1hoxQY' r_client_id = "2rv9NDv0WFZVS19o3VTZbrMjqX8mjiCFrxab7dknSC0" client_secret = 'POrisHrcdMvUKmaR6Cea0b8jtx-z4ewVWrnaIXASO-H3tB3g5MgPV7Vqty7OP8aEbSGENWRMkeVuJJKZDdG7Pw' new_secret = "UcU7Kzo-6oYRfuCfcL0wUgsiEXQIT2kQOfCqir6wFRdSXjML1y80bJp29_4Q9GqYRXI-5vIswB1KVGIhIiNXjg" #OAuth_url = authorize_url + '?response_type=code&state=' + state + '&client_id=' + r_client_id + '&scope='+scope+'&redirect_uri=' + callback_uri OAuth_url = authorize_url + '?response_type=code&state=' + state + '&client_id=' + client_id + '&scope=' + scope + '&redirect_uri=' + callback_uri # Process data from teams to check if there is input via cards channelData = turn_context.activity.channel_data enter_val = turn_context.activity.value if enter_val != None or "postBack" in channelData: global token try: val = json.dumps(turn_context.activity.value) commandToken = json.loads(val) authorization_code = commandToken['SimpleVal'] data = { 'grant_type': 'authorization_code', 'code': authorization_code, 'redirect_uri': callback_uri } access_token_response = requests.post(token_url, data=data, verify=True, allow_redirects=True, auth=(client_id, client_secret)) tokens = json.loads(access_token_response.text) access_token = tokens['access_token'] token = access_token await turn_context.send_activity(f"Login successful !") return None except: await turn_context.send_activity( f"Authorization Code is Invalid !") # makes the text in lower case and strips of any spaces text = turn_context.activity.text.lower().strip() # splits the user input and makes a list ltxt = text.split(" ") # Use this if cards dosen't work for you, token needs to be entered manually each time it expires. #token = 'IiU-3EAUcBTssUvwh7FcQuM1buLNhAq-Y52r_Bkiemo90m5LG6yx0R-XpWRPwX9bMPdJS4Vt1ynhBMAmsK_k0w' # header for reqesting data from FHIR call_header = { 'accept': 'application/json', 'Authorization': 'Bearer ' + token } # keywords that will be used by the bot to compare the user input and react accordingly if text in ("hello", "hi"): await turn_context.send_activity( f"why would you say {text} again ?") elif text in ("help", "intro"): await self.__send_intro_card(turn_context) elif text in ("login"): await self.__send_oauth_card(turn_context) elif text == "delete": self.list_care_provider.clear() await turn_context.send_activity( "The care provider list is empty now!") elif text == "standard channel": if turn_context.activity.channel_id == Channels.ms_teams: try: graph_token = get_graph_token() standard_channel(graph_token) await turn_context.send_activity( "A standard channel created!") except: await turn_context.send_activity( "This function is only supported in teams/channels!" ) else: await turn_context.send_activity( "This function is only supported in Microsoft Teams") elif text == "private channel": if turn_context.activity.channel_id == Channels.ms_teams: try: graph_token = get_graph_token() members = all_team_members(graph_token)["value"] ids = [] for provider in self.list_care_provider: for member in members: if member["displayName"] == provider['name']: ids.append(member["id"]) ls_member = [] count = 0 for id_number in ids: if count == 0: add = owner_object(id_number) else: add = member_object(id_number) ls_member.append(add) count = count + 1 if len(ls_member) == 0: await turn_context.send_activity( "No provider is received") else: private_channel(graph_token, ls_member) await turn_context.send_activity( "A private channel with the care providers created!" ) except: await turn_context.send_activity( "This function is only supported in teams/channels!" ) else: await turn_context.send_activity( "This function is only supported in Microsoft Teams") elif text in ("patient"): await turn_context.send_activity( 'Please type the patient ID after patient. Eg: "patient 137"' ) elif ltxt[0] == "patient": if ltxt[1] != "0": url = "https://tcfhirsandbox.intersystems.com.au/fhir/dstu2/Patient/" + ltxt[ 1] response = requests.get(url, headers=call_header, verify=True) if response.status_code == 404: await turn_context.send_activity("Patient not found !") elif response.status_code == 401: await turn_context.send_activity( "Your token has expired !") elif response.status_code == 200: r_dict = json.loads(response.text) trak_url = ( f"https://tcfhirsandbox.intersystems.com.au/t2019grxx/csp/system.Home.cls#/Direct/AW.Direct.EPR?RegistrationNo={str(r_dict['identifier'][1]['value'])}" ) ob_url = "https://www.google.com/" try: pat_name = (f"{r_dict['name'][0]['text']}") trak_name = pat_name.upper() except: trak_name = "Couldn't find NAME in database" try: lastUpdated = (f"{r_dict['meta']['lastUpdated']}") utc = (f"{lastUpdated[0:10]} {lastUpdated[12:19]}") trak_lastUpdated = zone_convertor(utc) except: trak_lastUpdated = "No DATE found" try: trak_careProvider = ( f"{r_dict['careProvider'][0]['display']}") except: trak_careProvider = "Couldn't find CARE PROVIDER in database" try: trak_recordNumber = ( f"{r_dict['identifier'][1]['value']}") except: trak_recordNumber = "Couldn't find RECORD NUMBER in database" try: trak_dob = (f"{r_dict['birthDate']}") except: trak_dob = "Couldn't find DOB in database" try: trak_gender = (f"{r_dict['gender']}") except: trak_gender = "GENDER is not disclosed by the patient" trak_allergy_url = ( f"https://tcfhirsandbox.intersystems.com.au/fhir/dstu2/Patient/{ltxt[1]}/AllergyIntolerance" ) allergy_resposne = requests.get(trak_allergy_url, headers=call_header, verify=True) a_dict = json.loads(allergy_resposne.text) a_total = (f"{a_dict['total']}") if a_total != "0": count = int(a_total) index = count - 1 allergy_name = "" allergy_reaction = "" allergy_severity = "" allergy_recordedDate = "" while count != 0: try: allergy_name = allergy_name + ( f"{a_dict['entry'][index]['resource']['substance']['text']}:" ) except: allergy_name = "Unknown" try: allergy_reaction = allergy_reaction + ( f"{a_dict['entry'][index]['resource']['reaction'][0]['manifestation'][0]['text']}:" ) # it is possible that there are more sublist under reaction and manifestation except: allergy_reaction = "No record found" try: allergy_severity = allergy_severity = allergy_severity + ( f"{a_dict['entry'][index]['resource']['reaction'][0]['severity']}:" ) except: allergy_severity = "No record found" try: utc_date = ( f"{a_dict['entry'][index]['resource']['recordedDate']}|" ) dt = utc_date.split("T") t = dt[1].split("+") dt_format = (f"{dt[0]} {t[0]}") allergy_recordedDate = allergy_recordedDate + zone_convertor( dt_format) + "|" except: allergy_recordedDate = "Date Unknown" index = index - 1 count = count - 1 list_name = allergy_name.split(":") list_reaction = allergy_reaction.split(":") list_severity = allergy_severity.split(":") list_date = allergy_recordedDate.split("|") allergy_data = "" total_allergy = int(a_total) list_index = 0 while list_index < total_allergy: allergy_data = allergy_data + ( f"Allergen : {list_name[list_index]}\n\nReaction : {list_reaction[list_index]}\n\nSeverity : {list_severity[list_index]}\n\nRecorded Date : {list_date[list_index]}\n\n-------------------------------------\n\n" ) list_index += 1 else: allergy_data = ( f"{trak_name} have no recorded allergies") await self.__send_about_card(turn_context) else: await turn_context.send_activity( "You are not logged in. Please type 'Login' to start your session !" ) elif ltxt[0] == "mrn": url = "https://tcfhirsandbox.intersystems.com.au/fhir/dstu2/Patient?identifier=" + ltxt[ 1] response = requests.get(url, headers=call_header, verify=True) if response.status_code == 404: await turn_context.send_activity("Patient not found !") elif response.status_code == 401: await turn_context.send_activity("Your token has expired !" ) elif response.status_code == 200: r_dict = json.loads(response.text) trak_url = ( f"https://tcfhirsandbox.intersystems.com.au/t2019grxx/csp/system.Home.cls#/Direct/AW.Direct.EPR?RegistrationNo={ltxt[1]}" ) ob_url = "https://www.google.com/" try: pat_name = ( f"{r_dict['entry'][0]['resource']['name'][0]['text']}" ) trak_name = pat_name.upper() except: trak_name = "Couldn't find NAME in database" try: lastUpdated = ( f"{r_dict['entry'][0]['resource']['meta']['lastUpdated']}" ) utc = (f"{lastUpdated[0:10]} {lastUpdated[12:19]}") trak_lastUpdated = zone_convertor(utc) except: trak_lastUpdated = "No DATE found" try: trak_careProvider = ( f"{r_dict['entry'][0]['resource']['careProvider'][0]['display']}" ) except: trak_careProvider = "Couldn't find CARE PROVIDER in database" try: trak_recordNumber = ( f"{r_dict['entry'][0]['resource']['identifier'][1]['value']}" ) except: trak_recordNumber = "Couldn't find RECORD NUMBER in database" try: trak_dob = ( f"{r_dict['entry'][0]['resource']['birthDate']}") except: trak_dob = "Couldn't find DOB in database" try: trak_gender = ( f"{r_dict['entry'][0]['resource']['gender']}") except: trak_gender = "GENDER is not disclosed by the patient" trak_allergy_url = ( f"https://tcfhirsandbox.intersystems.com.au/fhir/dstu2/Patient/{r_dict['entry'][0]['resource']['id']}/AllergyIntolerance" ) allergy_resposne = requests.get(trak_allergy_url, headers=call_header, verify=True) a_dict = json.loads(allergy_resposne.text) a_total = (f"{a_dict['total']}") if a_total != "0": count = int(a_total) index = count - 1 allergy_name = "" allergy_reaction = "" allergy_severity = "" allergy_recordedDate = "" while count != 0: try: allergy_name = allergy_name + ( f"{a_dict['entry'][index]['resource']['substance']['text']}:" ) except: allergy_name = "Unknown" try: allergy_reaction = allergy_reaction + ( f"{a_dict['entry'][index]['resource']['reaction'][0]['manifestation'][0]['text']}:" ) # it is possible that there are more sublist under reaction and manifestation except: allergy_reaction = "No record found" try: allergy_severity = allergy_severity + ( f"{a_dict['entry'][index]['resource']['reaction'][0]['severity']}:" ) except: allergy_severity = "No record found" try: utc_date = ( f"{a_dict['entry'][index]['resource']['recordedDate']}|" ) date_t = utc_date.split("T") t = date_t[1].split("+") dt_format = (f"{date_t[0]} {t[0]}") allergy_recordedDate = allergy_recordedDate + zone_convertor( dt_format) + "|" except: allergy_recordedDate = "Date Unknown" index = index - 1 count = count - 1 list_name = allergy_name.split(":") list_reaction = allergy_reaction.split(":") list_severity = allergy_severity.split(":") list_date = allergy_recordedDate.split("|") allergy_data = "" total_allergy = int(a_total) list_index = 0 while list_index < total_allergy: allergy_data = allergy_data + ( f"Allergen : {list_name[list_index]}\n\nReaction : {list_reaction[list_index]}\n\nSeverity : {list_severity[list_index]}\n\nRecorded Date : {list_date[list_index]}\n\n-------------------------------------\n\n" ) list_index += 1 else: allergy_data = ( f"{trak_name} have no recorded allergies") await self.__send_about_card(turn_context) else: await turn_context.send_activity( "You are not logged in. Please type 'Login' to start your session !" ) #list all providers elif text in ("provider", "mdt"): global cp_list cp_list = "" for provider in self.list_care_provider: cp_list = cp_list + ( f"{provider['id']} - {provider['name']} \n\n") await self.__send_mdt_card(turn_context) #mention provider in the teams elif text in ("mention", "mention care providers"): if turn_context.activity.channel_id == Channels.ms_teams: try: members = await TeamsInfo.get_team_members(turn_context ) for provider in self.list_care_provider: for member in members: if member.name == provider['name']: mention = Mention( mentioned=member, text=f"<at>{member.name}</at>", type="mention", ) reply_activity = MessageFactory.text( f"{mention.text}") reply_activity.entities = [ Mention().deserialize( mention.serialize()) ] await turn_context.send_activity( reply_activity) except: await turn_context.send_activity( "This function is only supported in teams/channels!" ) else: await turn_context.send_activity( "This function is only supported in Microsoft Teams") elif text in ("result", "results"): r_name = self.dict_results['name'] r_urn = self.dict_results['urn'] r_url = self.dict_results['link'] r_sender = self.dict_results['sender'] r_message = self.dict_results['message'] self.dict_results.clear() await self.__send_result_card(turn_context) else: await turn_context.send_activity( "I am SORRY!, I don't understand that.")