def _update_attachment_streams(self, activity: Activity) -> List[object]: if not activity or not activity.attachments: return None def validate_int_list(obj: object) -> bool: if not isinstance(obj, list): return False return all(isinstance(element, int) for element in obj) stream_attachments = [ attachment for attachment in activity.attachments if validate_int_list(attachment.content) ] if stream_attachments: activity.attachments = [ attachment for attachment in activity.attachments if not validate_int_list(attachment.content) ] # TODO: validate StreamContent parallel return [ StreamContent( attachment.content, headers={"Content-Type": attachment.content_type}, ) for attachment in stream_attachments ] return None
async def _handle_outgoing_attachment(self, turn_context: TurnContext): reply = Activity(type=ActivityTypes.message) first_char = turn_context.activity.text[0] if first_char == "1": reply.text = "This is an inline attachment." reply.attachments = [self._get_inline_attachment()] elif first_char == "2": reply.text = "This is an internet attachment." reply.attachments = [self._get_internet_attachment()] elif first_char == "3": reply.text = "This is an uploaded attachment." reply.attachments = [await self._get_upload_attachment(turn_context)] else: reply.text = "Your input was not recognized, please try again." await turn_context.send_activity(reply)
async def _send_welcome_message(self, turn_context: TurnContext): """ Greet the user and give them instructions on how to interact with the bot. :param turn_context: :return: """ reply = Activity(type=ActivityTypes.message) reply.text = "Hello and welcome! \n\n Send photo of the handwrited spiral to get probability of PD" reply.attachments = [await self._get_spiral_example(turn_context)] await turn_context.send_activity(reply)
async def create_reply_activity(request_activity: Activity, text: str, attachment: Attachment = None) -> Activity: activity = Activity( type=ActivityTypes.message, channel_id=request_activity.channel_id, conversation=request_activity.conversation, recipient=request_activity.from_property, from_property=request_activity.recipient, text=text, service_url=request_activity.service_url) if attachment: activity.attachments = [attachment] return activity
async def func(turn_context: TurnContext): reply = Activity(type=ActivityTypes.message) if body.image: attachment = Attachment( name="person.png", content_type="image/png", content_url=f"data:image/png;base64,{body.image}", ) reply.attachments = [attachment] reply.text = '\U0001F3E0 Qualcuno è tornato a casa ma non so chi sia.' await turn_context.send_activity(reply)
def append_choices(self, prompt: Activity, channel_id: str, choices: object, style: object, options : object = None ) -> Activity: # Get base prompt text (if any) text = prompt.text if prompt != None and not prompt.text == False else '' # Create temporary msg # TODO: fix once ChoiceFactory complete def inline() -> Activity: return ChoiceFactory.inline(choices, text, None, options) def list_style() -> Activity: return ChoiceFactory.list_style(choices, text, None, options) def suggested_action() -> Activity: return ChoiceFactory.suggested_action(choices, text) def hero_card() -> Activity: return ChoiceFactory.hero_card(choices, text) def list_style_none() -> Activity: activity = Activity() activity.text = text return activity def default() -> Activity: return ChoiceFactory.for_channel(channel_id, choices, text, None, options) switcher = { # ListStyle.inline 1: inline, 2: list_style, 3: suggested_action, 4: hero_card, 5: list_style_none } msg = switcher.get(style, default)() # Update prompt with text, actions and attachments if not prompt: # clone the prompt the set in the options (note ActivityEx has Properties so this is the safest mechanism) prompt = copy.copy(prompt) prompt.text = msg.text if (msg.suggested_actions != None and msg.suggested_actions.actions != None and len(msg.suggested_actions.actions) > 0): prompt.suggested_actions = msg.suggested_actions if msg.attachments != None and len(msg.attachments) > 0: prompt.attachments = msg.attachments return prompt else: # TODO: Update to InputHints.ExpectingInput; msg.input_hint = None return msg
def create_reply_activity(self, request_activity, activity_type, text=None, attachment=None): activity = Activity(type=activity_type, channel_id=request_activity.channel_id, conversation=request_activity.conversation, recipient=request_activity.from_property, from_property=request_activity.recipient, service_url=request_activity.service_url) if text: activity.text = text if attachment: activity.attachments = [attachment] return activity
def append_choices( self, prompt: Activity, channel_id: str, choices: List[Choice], style: ListStyle, options: ChoiceFactoryOptions = None, ) -> Activity: """ Composes an output activity containing a set of choices. :param prompt: The prompt to append the user's choice to :type prompt: :param channel_id: Id of the channel the prompt is being sent to :type channel_id: str :param: choices: List of choices to append :type choices: :class:`List` :param: style: Configured style for the list of choices :type style: :class:`ListStyle` :param: options: Optional formatting options to use when presenting the choices :type style: :class:`ChoiceFactoryOptions` :return: A task representing the asynchronous operation .. remarks:: If the task is successful, the result contains the updated activity. When overridden in a derived class, appends choices to the activity when the user is prompted for input. This is an helper function to compose an output activity containing a set of choices. """ # Get base prompt text (if any) text = prompt.text if prompt is not None and prompt.text else "" # Create temporary msg # TODO: fix once ChoiceFactory complete def inline() -> Activity: return ChoiceFactory.inline(choices, text, None, options) def list_style() -> Activity: return ChoiceFactory.list_style(choices, text, None, options) def suggested_action() -> Activity: return ChoiceFactory.suggested_action(choices, text) def hero_card() -> Activity: return ChoiceFactory.hero_card(choices, text) def list_style_none() -> Activity: activity = Activity(type=ActivityTypes.message) activity.text = text return activity def default() -> Activity: return ChoiceFactory.for_channel(channel_id, choices, text, None, options) # Maps to values in ListStyle Enum switcher = { 0: list_style_none, 1: default, 2: inline, 3: list_style, 4: suggested_action, 5: hero_card, } msg = switcher.get(int(style.value), default)() # Update prompt with text, actions and attachments if prompt: # clone the prompt the set in the options (note ActivityEx has Properties so this is the safest mechanism) prompt = copy.copy(prompt) prompt.text = msg.text if (msg.suggested_actions is not None and msg.suggested_actions.actions is not None and msg.suggested_actions.actions): prompt.suggested_actions = msg.suggested_actions if msg.attachments: if prompt.attachments: prompt.attachments.extend(msg.attachments) else: prompt.attachments = msg.attachments return prompt # TODO: Update to InputHints.ExpectingInput; msg.input_hint = None return msg
def append_choices( self, prompt: Activity, channel_id: str, choices: List[Choice], style: ListStyle, options: ChoiceFactoryOptions = None, ) -> Activity: """ Helper function to compose an output activity containing a set of choices. Parameters: ----------- prompt: The prompt to append the user's choice to. channel_id: ID of the channel the prompt is being sent to. choices: List of choices to append. style: Configured style for the list of choices. options: (Optional) options to configure the underlying `ChoiceFactory` call. """ # Get base prompt text (if any) text = prompt.text if prompt is not None and prompt.text else "" # Create temporary msg # TODO: fix once ChoiceFactory complete def inline() -> Activity: return ChoiceFactory.inline(choices, text, None, options) def list_style() -> Activity: return ChoiceFactory.list_style(choices, text, None, options) def suggested_action() -> Activity: return ChoiceFactory.suggested_action(choices, text) def hero_card() -> Activity: return ChoiceFactory.hero_card(choices, text) def list_style_none() -> Activity: activity = Activity(type=ActivityTypes.message) activity.text = text return activity def default() -> Activity: return ChoiceFactory.for_channel(channel_id, choices, text, None, options) # Maps to values in ListStyle Enum switcher = { 0: list_style_none, 1: default, 2: inline, 3: list_style, 4: suggested_action, 5: hero_card, } msg = switcher.get(int(style.value), default)() # Update prompt with text, actions and attachments if not prompt: # clone the prompt the set in the options (note ActivityEx has Properties so this is the safest mechanism) prompt = copy.copy(prompt) prompt.text = msg.text if (msg.suggested_actions is not None and msg.suggested_actions.actions is not None and msg.suggested_actions.actions): prompt.suggested_actions = msg.suggested_actions if msg.attachments is not None and msg.attachments: prompt.attachments = msg.attachments return prompt # TODO: Update to InputHints.ExpectingInput; msg.input_hint = None return msg
async def loop_step(self, step_context: WaterfallStepContext): country = step_context.values["country"].capitalize() # If they chose an option execute script if step_context.result.value == 'Covid-19 Cases': await step_context.context.send_activity( MessageFactory.text("Wait a moment...")) querystring = {"country": "{}".format(country)} response = requests.request("GET", url, headers=headers, params=querystring) response_json = json.loads(response.text) new_cases = response_json['response'][0]['cases']['new'] active_cases = response_json['response'][0]['cases']['active'] recovered_cases = response_json['response'][0]['cases'][ 'recovered'] await step_context.context.send_activity( MessageFactory.text(f"COVID-19 Cases from {country} \n\n" f"New Cases {new_cases} \n\n" f"Active Cases {active_cases} \n\n" f"Recovered Cases {recovered_cases} \n\n")) reply = Activity(type=ActivityTypes.message) reply.attachments = [self._get_inline_attachment(country)] await step_context.context.send_activity(reply) if step_context.result.value == 'Covid-19 Deaths': await step_context.context.send_activity( MessageFactory.text("Wait a moment...")) querystring = {"country": "{}".format(country)} response = requests.request("GET", url, headers=headers, params=querystring) response_json = json.loads(response.text) new_deaths = response_json['response'][0]['deaths']['new'] m_deaths = response_json['response'][0]['deaths']['1M_pop'] total_deaths = response_json['response'][0]['deaths']['total'] await step_context.context.send_activity( MessageFactory.text(f"COVID-19 Deaths from {country} \n\n" f"New Deaths {new_deaths} \n\n" f"1M_pop Deaths {m_deaths} \n\n" f"Total Deaths {total_deaths} \n\n")) if step_context.result.value == 'Covid-19 Tests': await step_context.context.send_activity( MessageFactory.text("Wait a moment...")) querystring = {"country": "{}".format(country)} response = requests.request("GET", url, headers=headers, params=querystring) response_json = json.loads(response.text) m_tests = response_json['response'][0]['tests']['1M_pop'] total_tests = response_json['response'][0]['tests']['total'] await step_context.context.send_activity( MessageFactory.text(f"COVID-19 PCR Tests from {country} \n\n" f"New Tests {m_tests} \n\n" f"Total PCR Tests {total_tests} \n\n")) if step_context.result.value == 'Covid-19 Twitter': await step_context.context.send_activity( MessageFactory.text( "Obtaining last tweets in your country related to COVID-19 wait a moment..." )) result = [] query = f'{country} AND covid OR covid-19 OR coronavirus OR Covid-19' for tweet in tweepy.Cursor(api.search, q=query).items(5): reply = MessageFactory.list([]) reply.attachments.append(self.create_tweet_card(tweet)) await step_context.context.send_activity(reply) if step_context.result.value == 'Covid-19 Meme': # show covid meme reply = MessageFactory.list([]) reply.attachments.append(self.create_hero_card()) await step_context.context.send_activity(reply) # If they're done, exit and return their list. elif step_context.result.value == 'Done': return await step_context.end_dialog() # Otherwise, repeat this dialog, passing in the selections from this iteration. return await step_context.replace_dialog(ReviewSelectionDialog.__name__ )
def append_choices(self, prompt: Activity, channel_id: str, choices: object, style: object, options: object = None) -> Activity: """ Helper function to compose an output activity containing a set of choices. Parameters: ----------- prompt: The prompt to append the user's choice to. channel_id: ID of the channel the prompt is being sent to. choices: List of choices to append. style: Configured style for the list of choices. options: (Optional) options to configure the underlying `ChoiceFactory` call. """ # Get base prompt text (if any) text = prompt.text if prompt != None and not prompt.text == False else '' # Create temporary msg # TODO: fix once ChoiceFactory complete def inline() -> Activity: return ChoiceFactory.inline(choices, text, None, options) def list_style() -> Activity: return ChoiceFactory.list_style(choices, text, None, options) def suggested_action() -> Activity: return ChoiceFactory.suggested_action(choices, text) def hero_card() -> Activity: return ChoiceFactory.hero_card(choices, text) def list_style_none() -> Activity: activity = Activity() activity.text = text return activity def default() -> Activity: return ChoiceFactory.for_channel(channel_id, choices, text, None, options) switcher = { # ListStyle.inline 1: inline, 2: list_style, 3: suggested_action, 4: hero_card, 5: list_style_none } msg = switcher.get(style, default)() # Update prompt with text, actions and attachments if not prompt: # clone the prompt the set in the options (note ActivityEx has Properties so this is the safest mechanism) prompt = copy.copy(prompt) prompt.text = msg.text if (msg.suggested_actions != None and msg.suggested_actions.actions != None and len(msg.suggested_actions.actions) > 0): prompt.suggested_actions = msg.suggested_actions if msg.attachments != None and len(msg.attachments) > 0: prompt.attachments = msg.attachments return prompt else: # TODO: Update to InputHints.ExpectingInput; msg.input_hint = None return msg
async def loop_step(self, step_context: WaterfallStepContext): country = step_context.values["country"].capitalize() # If they chose an option execute script if step_context.result.value == 'Covid-19 Cases': await step_context.context.send_activity(MessageFactory.text("Wait a moment...")) querystring = {"country":"{}".format(country)} response = requests.request("GET", url, headers=headers, params=querystring) response_json = json.loads(response.text) new_cases = response_json['response'][0]['cases']['new'] active_cases = response_json['response'][0]['cases']['active'] recovered_cases = response_json['response'][0]['cases']['recovered'] await step_context.context.send_activity( MessageFactory.text( f"COVID-19 Cases from {country} \n\n" f"New Cases {new_cases} \n\n" f"Active Cases {active_cases} \n\n" f"Recovered Cases {recovered_cases} \n\n" ) ) reply = Activity(type=ActivityTypes.message) reply.attachments = [self._get_inline_attachment(country)] await step_context.context.send_activity(reply) if step_context.result.value == 'Covid-19 Deaths': await step_context.context.send_activity(MessageFactory.text("Wait a moment...")) querystring = {"country":"{}".format(country)} response = requests.request("GET", url, headers=headers, params=querystring) response_json = json.loads(response.text) new_deaths = response_json['response'][0]['deaths']['new'] m_deaths = response_json['response'][0]['deaths']['1M_pop'] total_deaths = response_json['response'][0]['deaths']['total'] await step_context.context.send_activity( MessageFactory.text( f"COVID-19 Deaths from {country} \n\n" f"New Deaths {new_deaths} \n\n" f"1M_pop Deaths {m_deaths} \n\n" f"Total Deaths {total_deaths} \n\n" ) ) if step_context.result.value == 'Covid-19 Tests': await step_context.context.send_activity(MessageFactory.text("Wait a moment...")) querystring = {"country":"{}".format(country)} response = requests.request("GET", url, headers=headers, params=querystring) response_json = json.loads(response.text) m_tests = response_json['response'][0]['tests']['1M_pop'] total_tests = response_json['response'][0]['tests']['total'] await step_context.context.send_activity( MessageFactory.text( f"COVID-19 PCR Tests from {country} \n\n" f"New Tests {m_tests} \n\n" f"Total PCR Tests {total_tests} \n\n" ) ) # If they're done, exit and return their list. elif step_context.result.value == 'Done': return await step_context.end_dialog() # Otherwise, repeat this dialog, passing in the selections from this iteration. return await step_context.replace_dialog(StatsSelectionDialog.__name__)
async def _fill_out_user_profile(self, flow: ConversationFlow, profile: UserProfile, turn_context: TurnContext): # Begins flow process user_input = turn_context.activity.text.strip() # Ask for date; starts conversation flow if flow.last_question_asked == Question.NONE: await turn_context.send_activity( MessageFactory.text( "Let's get started. What date and time would you like to book your movie for?" )) flow.last_question_asked = Question.DATE # Validate date; ask for movie selection elif flow.last_question_asked == Question.DATE: # This is where date must be bound to profile.date validate_result = self._validate_date(user_input) if not validate_result.is_valid: await turn_context.send_activity( MessageFactory.text(validate_result.message)) else: profile.date = validate_result.value await turn_context.send_activity( MessageFactory.text( f"Great! We have a good selection of movies showing at {profile.date}" )) await turn_context.send_activity( MessageFactory.text( "Which movie would you like to watch? Please type the name of the movie as your reply." )) # movies attachment message = Activity(type=ActivityTypes.message) message.text = "Moana, Once Upon a Time in Hollywood, Ready Player One, Sicario, The Girl With the Dragon Tattoo." message.attachments = [self._get_inline_attachment()] await turn_context.send_activity(message) flow.last_question_asked = Question.MOVIE # Validate movie; ask for seat reservations elif flow.last_question_asked == Question.MOVIE: ## This is where movie must be bound to profile.movie validate_result = self._validate_movie(user_input) if not validate_result.is_valid: await turn_context.send_activity( MessageFactory.text(validate_result.message)) else: profile.movie = validate_result.value await turn_context.send_activity( MessageFactory.text( f"Sounds good! {profile.movie} is a great pick!")) await turn_context.send_activity( MessageFactory.text("How many seats are you reserving?")) flow.last_question_asked = Question.SEATS # Validate seats; ask about row preferences elif flow.last_question_asked == Question.SEATS: validate_result = self._validate_seats(user_input) if not validate_result.is_valid: await turn_context.send_activity( MessageFactory.text(validate_result.message)) else: profile.seats = validate_result.value await turn_context.send_activity( MessageFactory.text( f"You are booking {profile.seats} seats.")) await turn_context.send_activity( MessageFactory.text( "What is your row preference? There are 50 rows in our theater." )) flow.last_question_asked = Question.PREFERENCE # Validate preferences; ask about email elif flow.last_question_asked == Question.PREFERENCE: validate_result = self._validate_preference(user_input) if not validate_result.is_valid: await turn_context.send_activity( MessageFactory.text(validate_result.message)) else: profile.preference = validate_result.value await turn_context.send_activity( MessageFactory.text( f"Your row preference has been set as {profile.preference}" )) await turn_context.send_activity( MessageFactory.text( "Please enter your email for booking confirmation.")) flow.last_question_asked = Question.EMAIL # Validate email, confirm by displaying all info, wrap up w/ NONE elif flow.last_question_asked == Question.EMAIL: validate_result = self._validate_email(user_input) if not validate_result.is_valid: await turn_context.send_activity( MessageFactory.text(validate_result.message)) else: profile.email = validate_result.value await turn_context.send_activity( MessageFactory.text( f"You have now completed the booking process.")) await turn_context.send_activity( MessageFactory.text( f"Booking for {profile.email}: {profile.movie} on {profile.date}" )) await turn_context.send_activity( MessageFactory.text( f"You are reserving {profile.seats} seats in row {profile.preference}" )) await turn_context.send_activity( MessageFactory.text("Type anything to run the bot again.")) flow.last_question_asked = Question.NONE #End of flow, able to restart again