Пример #1
0
    async def test_should_not_intercept_oauth_cards_for_empty_token(self):
        first_response = ExpectedReplies(
            activities=[
                SkillDialogTests.create_oauth_card_attachment_activity("https://test")
            ]
        )

        sequence = 0

        async def post_return():
            nonlocal sequence
            if sequence == 0:
                result = InvokeResponse(body=first_response, status=HTTPStatus.OK)
            else:
                result = InvokeResponse(status=HTTPStatus.OK)
            sequence += 1
            return result

        mock_skill_client = self._create_mock_skill_client(None, post_return)
        conversation_state = ConversationState(MemoryStorage())

        dialog_options = SkillDialogTests.create_skill_dialog_options(
            conversation_state, mock_skill_client
        )
        sut = SkillDialog(dialog_options, dialog_id="dialog")
        activity_to_send = SkillDialogTests.create_send_activity()

        client = DialogTestClient(
            "test",
            sut,
            BeginSkillDialogOptions(activity=activity_to_send,),
            conversation_state=conversation_state,
        )

        # Don't add exchangeable token to test adapter

        final_activity = await client.send_activity(MessageFactory.text("irrelevant"))
        self.assertIsNotNone(final_activity)
        self.assertEqual(len(final_activity.attachments), 1)
Пример #2
0
    async def interrupt(self, inner_dc: DialogContext) -> DialogTurnResult:
        LOGGER.debug(msg=f"{CancelAndHelpDialog.__name__}: interrupt")

        if inner_dc.context.activity.type == ActivityTypes.message:
            text = inner_dc.context.activity.text.lower()
            message = Activity(
                type=ActivityTypes.message,
                attachments=[CardFactory.adaptive_card(HelpCard)])

            if text in (Prompts.HELP.value, Prompts.QUESTION_MARK.value):
                await inner_dc.context.send_activity(message)
                return DialogTurnResult(DialogTurnStatus.Waiting)

            if text in (Prompts.CANCEL.value, Prompts.END.value,
                        Prompts.QUIT.value):
                cancel_message = MessageFactory.text(messages.CANCELLED,
                                                     messages.CANCELLED,
                                                     InputHints.ignoring_input)
                await inner_dc.context.send_activity(cancel_message)
                await inner_dc.cancel_all_dialogs()
                return await inner_dc.replace_dialog(self.initial_dialog_id)
        return None
        async def exec_test(turn_context: TurnContext) -> None:
            dialog_context = await dialogs.create_context(turn_context)
            results = await dialog_context.continue_dialog()

            if results.status == DialogTurnStatus.Empty:
                options = PromptOptions(
                    prompt=Activity(type=ActivityTypes.message,
                                    text="Enter a number."),
                    retry_prompt=Activity(
                        type=ActivityTypes.message,
                        text="You must enter a positive number less than 100.",
                    ),
                )
                await dialog_context.prompt("NumberPrompt", options)

            elif results.status == DialogTurnStatus.Complete:
                number_result = int(results.result)
                await turn_context.send_activity(
                    MessageFactory.text(
                        f"Bot received the number '{number_result}'."))

            await conver_state.save_changes(turn_context)
Пример #4
0
    async def confirm_step(
            self, step_context: WaterfallStepContext) -> DialogTurnResult:
        """
        Confirm the information the user has provided.
        :param step_context:
        :return DialogTurnResult:
        """
        booking_details = step_context.options

        # Capture the results of the previous step
        booking_details.budget = step_context.result
        message_text = (
            f"Please confirm, I have you traveling for a { booking_details.budget } budget : "
            f"From { booking_details.origin } to { booking_details.destination } on { booking_details.departure_date }. "
            f"From { booking_details.destination } to { booking_details.origin } on { booking_details.return_date}. "
        )
        prompt_message = MessageFactory.text(message_text, message_text,
                                             InputHints.expecting_input)

        # Offer a YES/NO prompt.
        return await step_context.prompt(ConfirmPrompt.__name__,
                                         PromptOptions(prompt=prompt_message))
Пример #5
0
    async def test_should_throw_on_post_failure(self):
        # This mock client will fail
        mock_skill_client = self._create_mock_skill_client(None, 500)

        conversation_state = ConversationState(MemoryStorage())
        dialog_options = SkillDialogTests.create_skill_dialog_options(
            conversation_state, mock_skill_client
        )

        sut = SkillDialog(dialog_options, "dialog_id")
        activity_to_send = MessageFactory.text(str(uuid.uuid4()))

        client = DialogTestClient(
            "test",
            sut,
            BeginSkillDialogOptions(activity=activity_to_send),
            conversation_state=conversation_state,
        )

        # A send should raise an exception
        with self.assertRaises(Exception):
            await client.send_activity("irrelevant")
Пример #6
0
    async def on_teams_task_module_fetch(
            self, turn_context: TurnContext,
            task_module_request: TaskModuleRequest) -> TaskModuleResponse:
        reply = MessageFactory.text(
            f"OnTeamsTaskModuleFetchAsync TaskModuleRequest: {json.dumps(task_module_request.data)}"
        )
        await turn_context.send_activity(reply)

        # base_response = TaskModuleResponseBase(type='continue')
        card = CardFactory.adaptive_card({
            "version":
            "1.0.0",
            "type":
            "AdaptiveCard",
            "body": [
                {
                    "type": "TextBlock",
                    "text": "Enter Text Here",
                },
                {
                    "type": "Input.Text",
                    "id": "usertext",
                    "placeholder": "add some text and submit",
                    "IsMultiline": "true",
                },
            ],
            "actions": [{
                "type": "Action.Submit",
                "title": "Submit",
            }],
        })

        task_info = TaskModuleTaskInfo(card=card,
                                       title="Adaptive Card: Inputs",
                                       height=200,
                                       width=400)
        continue_response = TaskModuleContinueResponse(type="continue",
                                                       value=task_info)
        return TaskModuleResponse(task=continue_response)
Пример #7
0
    async def choice_card_step(self, step_context: WaterfallStepContext):
        """
        1. Prompts the user if the user is not in the middle of a dialog.
        2. Re-prompts the user when an invalid input is received.
        """
        menu_text = (
            "Which card would you like to see?\n"
            "(1) Adaptive Card\n"
            "(2) Animation Card\n"
            "(3) Audio Card\n"
            "(4) Hero Card\n"
            "(5) Receipt Card\n"
            "(6) Signin Card\n"
            "(7) Thumbnail Card\n"
            "(8) Video Card\n"
            "(9) All Cards"
        )

        # Prompt the user with the configured PromptOptions.
        return await step_context.prompt(
            "TextPrompt", PromptOptions(prompt=MessageFactory.text(menu_text))
        )
        async def exec_test(turn_context: TurnContext):
            dialog_context = await dialogs.create_context(turn_context)

            results: DialogTurnResult = await dialog_context.continue_dialog()

            if results.status == DialogTurnStatus.Empty:
                options = PromptOptions(
                    prompt=Activity(type=ActivityTypes.message,
                                    text="Please confirm."),
                    retry_prompt=Activity(
                        type=ActivityTypes.message,
                        text=
                        "Please confirm, say 'yes' or 'no' or something like that.",
                    ),
                )
                await dialog_context.prompt("ConfirmPrompt", options)
            elif results.status == DialogTurnStatus.Complete:
                message_text = "Confirmed" if results.result else "Not confirmed"
                await turn_context.send_activity(
                    MessageFactory.text(message_text))

            await convo_state.save_changes(turn_context)
Пример #9
0
    async def process_activity(
            self, step_context: WaterfallStepContext) -> DialogTurnResult:
        current_activity_type = step_context.context.activity.type

        # A skill can send trace activities, if needed.
        await step_context.context.send_trace_activity(
            f"{ActivityRouterDialog.__name__}.process_activity()",
            label=f"Got ActivityType: {current_activity_type}",
        )

        if current_activity_type == ActivityTypes.event:
            return await self._on_event_activity(step_context)
        if current_activity_type == ActivityTypes.message:
            return await self._on_message_activity(step_context)
        else:
            # We didn't get an activity type we can handle.
            await step_context.context.send_activity(
                MessageFactory.text(
                    f'Unrecognized ActivityType: "{current_activity_type}".',
                    input_hint=InputHints.ignoring_input,
                ))
            return DialogTurnResult(DialogTurnStatus.Complete)
    async def on_message_activity(self, turn_context: TurnContext):
        await turn_context.send_activity("parent: before child")

        activity = MessageFactory.text("parent to child")
        TurnContext.apply_conversation_reference(
            activity, TurnContext.get_conversation_reference(turn_context.activity)
        )
        activity.delivery_mode = DeliveryModes.expect_replies

        activities = await self.client.post_buffered_activity(
            None,
            "toBotId",
            "http://localhost:3979/api/messages",
            "http://tempuri.org/whatever",
            str(uuid.uuid4()),
            activity,
        )

        if activities:
            await turn_context.send_activities(activities)

        await turn_context.send_activity("parent: after child")
Пример #11
0
    async def on_teams_messaging_extension_query(
        self,
        turn_context: TurnContext,
        query: MessagingExtensionQuery,
    ) -> MessagingExtensionResponse:
        search_query = str(query.parameters[0].value).strip()

        user_configuration = await self.user_config_property.get(
            turn_context, "UserConfiguration")
        if user_configuration is not None and "email" in user_configuration:
            return await self._get_auth_or_search_result(
                turn_context, query, search_query)

        # The user configuration is NOT set to search Email.
        if search_query is None:
            await turn_context.send_activity(
                MessageFactory.text(
                    "You cannot enter a blank string for the search"))
            return

        search_results = self._get_search_results(search_query)

        attachments = []
        for obj in search_results:
            hero_card = HeroCard(title=obj["name"],
                                 tap=CardAction(type="invoke", value=obj))

            attachment = MessagingExtensionAttachment(
                content_type=CardFactory.content_types.hero_card,
                content=HeroCard(title=obj["name"]),
                preview=CardFactory.hero_card(hero_card),
            )
            attachments.append(attachment)
        return MessagingExtensionResponse(
            compose_extension=MessagingExtensionResult(
                type="result",
                attachment_layout="list",
                attachments=attachments))
Пример #12
0
    def list(
        choices: List[Choice],
        text: str = None,
        speak: str = None,
        options: ChoiceFactoryOptions = None,
    ):
        if choices is None:
            choices = []
        if options is None:
            options = ChoiceFactoryOptions()

        if options.include_numbers is None:
            include_numbers = True
        else:
            include_numbers = options.include_numbers

        # Format list of choices
        connector = ""
        txt_builder = [text]
        txt_builder.append("\n\n   ")

        for index, choice in enumerate(choices):
            title = (choice.action.title if choice.action is not None
                     and choice.action.title is not None else choice.value)

            txt_builder.append(connector)
            if include_numbers:
                txt_builder.append(f"{index + 1}")
                txt_builder.append(". ")
            else:
                txt_builder.append("- ")

            txt_builder.append(title)
            connector = "\n   "

        # Return activity with choices as a numbered list.
        txt = "".join(txt_builder)
        return MessageFactory.text(txt, speak, InputHints.expecting_input)
Пример #13
0
    async def on_message_activity(self, turn_context: TurnContext):
        # Forward all activities except EndOfConversation to the active skill.
        if turn_context.activity.type != ActivityTypes.end_of_conversation:
            delivery_mode: str = await self._delivery_mode_property.get(
                turn_context
            )

            if turn_context.activity.text in self._skills_config.SKILLS:
                selected_skill = self._skills_config.SKILLS[turn_context.activity.text]
                v3_bots = ['EchoSkillBotDotNetV3', 'EchoSkillBotJSV3']
                if selected_skill and delivery_mode == DeliveryModes.expect_replies and selected_skill.id.lower() in (id.lower() for id in v3_bots):
                    message = MessageFactory.text("V3 Bots do not support 'expectReplies' delivery mode.")
                    await turn_context.send_activity(message)
                    # Forget delivery mode and skill invocation.
                    await self._delivery_mode_property.delete(turn_context)
                    # Restart setup dialog
                    await self._conversation_state.delete(turn_context)
                    await DialogHelper.run_dialog(
                        self._dialog,
                        turn_context,
                        self._dialog_state_property,
                    )
                    return


            # If there is an active skill
            active_skill: BotFrameworkSkill = await self._active_skill_property.get(
                turn_context
            )
            if active_skill:
                # If there is an active skill, forward the Activity to it.
                await self.__send_to_skill(turn_context, delivery_mode, active_skill)
            else:
                await DialogHelper.run_dialog(
                    self._dialog,
                    turn_context,
                    self._dialog_state_property,
                )
Пример #14
0
    async def item_step(self, step_context: WaterfallStepContext) -> DialogTurnResult:
        """
        If a delivery item has not been provided, prompt for one.
        :param step_context:
        :return DialogTurnResult:
        """
        LOGGER.debug(msg=f"{CreateDeliveryDialog.__name__}: item step.")

        # Create an object in which to collect the delivery information within the dialog.
        step_context.values[Keys.DELIVERY_DIALOG_STATE.value] = Delivery()

        delivery: Delivery = step_context.values[Keys.DELIVERY_DIALOG_STATE.value]

        if delivery.item is None:
            prompt_options = PromptOptions(
                prompt=MessageFactory.text(
                    messages.DELIVERY_ITEM_PROMPT,
                    messages.DELIVERY_ITEM_PROMPT,
                    InputHints.expecting_input
                )
            )
            return await step_context.prompt(TextPrompt.__name__, prompt_options)
        return await step_context.next(delivery.item)
Пример #15
0
    async def confirm_step(
            self, step_context: WaterfallStepContext) -> DialogTurnResult:
        """
        Confirm the information the user has provided.
        :param step_context:
        :return DialogTurnResult:
        """
        booking_details = step_context.options
        self.message_history.add(step_context._turn_context.activity.text)

        # Capture the results of the previous step
        booking_details.budget = step_context.result
        message_text = (
            f"Please confirm, I have you traveling from: { booking_details.origin } to: "
            f"{ booking_details.destination }  "
            f"(start: {booking_details.from_date} end: {booking_details.to_date}) "
            f"for a budget : {booking_details.budget}")
        prompt_message = MessageFactory.text(message_text, message_text,
                                             InputHints.expecting_input)

        # Offer a YES/NO prompt.
        return await step_context.prompt(ConfirmPrompt.__name__,
                                         PromptOptions(prompt=prompt_message))
Пример #16
0
    async def _final_step(
            self, step_context: WaterfallStepContext) -> DialogTurnResult:
        active_skill = await self._active_skill_property.get(
            step_context.context)

        if step_context.result:
            message = f"Skill {active_skill.id} invocation complete."
            message += f" Result: {step_context.result}"
            await step_context.context.send_activity(
                MessageFactory.text(message,
                                    input_hint=InputHints.ignoring_input))

        # Clear the skill selected by the user.
        step_context.values[self._selected_skill_key] = None

        # Clear active skill in state
        await self._active_skill_property.delete(step_context.context)

        # Restart the main dialog with a different message the second time around
        return await step_context.replace_dialog(
            self.initial_dialog_id,
            f'Done with "{active_skill.id}". \n\n What skill would you like to call?',
        )
Пример #17
0
    async def final_step(
            self, step_context: WaterfallStepContext) -> DialogTurnResult:
        """Receives the results of a conversation from the top level dialog and ends the dialog.
        Prompts the user to send any message to restart this dialog.

        Args:
            step_context (WaterfallStepContext): the context for the current dialog turn

        Returns:
            DialogTurnResult: result of calling the end_dialog stack manipulation method.
        """
        # TODO store the UserProfile (gonna need the storage)
        #user_info: UserProfile = step_context.result

        message = f"Чтобы сделать новый запрос, отправьте мне любое сообщение"

        await step_context.context.send_activity(MessageFactory.text(message))

        # TODO store the UserProfile (gonna need the storage)
        #accessor = self.user_state.create_property("UserProfile")
        # await accessor.set(step_context.context, user_info)

        return await step_context.end_dialog()
    async def confirm_step(
            self, step_context: WaterfallStepContext) -> DialogTurnResult:
        """
        Confirm the information the user has provided.
        :param step_context:
        :return DialogTurnResult:
        """
        product_details = step_context.options

        # Capture the results of the previous step
        product_details.cost = cost_cal(step_context.result)

        message_text = (
            #f"请确认:您购买电脑是为了 { product_details.use } 用途。"
            #f"您的预算为:{ product_details.cost['low'] }-{ product_details.cost['high'] }。"
            #f"您的外观需求为:{ product_details.looking}。"
            f"紧张计算中……")
        time.sleep(1)
        calculating_message = MessageFactory.text(message_text, message_text,
                                                  InputHints.ignoring_input)
        await step_context.context.send_activity(calculating_message)

        return await step_context.next(product_details.style)
Пример #19
0
    async def salute(self,
                     step_context: WaterfallStepContext) -> DialogTurnResult:
        LOGGER.debug(msg=f"{SalutationDialog.__name__}: salute")

        dialog_options: {} = step_context.options if step_context.options is not None else {}

        salutation_phase: SalutationPhase = dialog_options.get(
            Keys.SALUTATION_PHASE.value, SalutationPhase.INITIATE)

        message_text = f""
        if salutation_phase == SalutationPhase.INITIATE:
            message_text = f"{messages.HELLO}! {messages.HOW_ARE_YOU_DOING}"

        elif salutation_phase == SalutationPhase.ACKNOWLEDGE:
            message_text = f"{messages.SALUTATION_ACKNOWLEDGEMENT}. {messages.HOW_CAN_I_HELP}"

        elif salutation_phase == SalutationPhase.PROMPT:
            message_text = f"{messages.HOW_CAN_I_HELP}"

        await step_context.context.send_activity(
            MessageFactory.text(message_text, message_text,
                                InputHints.ignoring_input))
        return await step_context.end_dialog(self.id)
Пример #20
0
    async def on_end_of_conversation_activity(self, turn_context: TurnContext):
        # forget skill invocation
        await self._active_skill_property.delete(turn_context)

        eoc_activity_message = f"Received {ActivityTypes.end_of_conversation}.\n\nCode: {turn_context.activity.code}"
        if turn_context.activity.text:
            eoc_activity_message = (eoc_activity_message +
                                    f"\n\nText: {turn_context.activity.text}")

        if turn_context.activity.value:
            eoc_activity_message = (
                eoc_activity_message +
                f"\n\nValue: {turn_context.activity.value}")

        await turn_context.send_activity(eoc_activity_message)

        # We are back
        await turn_context.send_activity(
            MessageFactory.text(
                'Back in the root bot. Say "skill" and I\'ll patch you through'
            ))

        await self._conversation_state.save_changes(turn_context, force=True)
    async def cost_step(
            self, step_context: WaterfallStepContext) -> DialogTurnResult:
        product_details = step_context.options

        # Capture the response to the previous step's prompt
        product_details.color = color_cal(step_context.result)
        if product_details.color:
            with open(
                    os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
                    + '/save/color.txt', 'a+') as f:
                f.write('light')
        else:
            with open(
                    os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
                    + '/save/color.txt', 'a+') as f:
                f.write('deep')
        if product_details.cost is None:
            message_text = "您预期这件衣服是多少元呢(请以xxx-xxx的形式回答)?"
            prompt_message = MessageFactory.text(message_text, message_text,
                                                 InputHints.expecting_input)
            return await step_context.prompt(
                TextPrompt.__name__, PromptOptions(prompt=prompt_message))
        return await step_context.next(product_details.cost)
Пример #22
0
    def _create_mock_skill_client(
        self,
        callback: Callable,
        return_status: Union[Callable, int] = 200,
        expected_replies: List[Activity] = None,
    ) -> BotFrameworkClient:
        mock_client = Mock()
        activity_list = ExpectedReplies(
            activities=expected_replies or [MessageFactory.text("dummy activity")]
        )

        async def mock_post_activity(
            from_bot_id: str,
            to_bot_id: str,
            to_url: str,
            service_url: str,
            conversation_id: str,
            activity: Activity,
        ):
            nonlocal callback, return_status
            if callback:
                await callback(
                    from_bot_id,
                    to_bot_id,
                    to_url,
                    service_url,
                    conversation_id,
                    activity,
                )

            if isinstance(return_status, Callable):
                return await return_status()
            return InvokeResponse(status=return_status, body=activity_list)

        mock_client.post_activity.side_effect = mock_post_activity

        return mock_client
Пример #23
0
    async def act_step(self, step_context: WaterfallStepContext) -> DialogTurnResult:
        if not self._luis_recognizer.is_configured:
            # LUIS is not configured, we just run the BookingDialog path with an empty BookingDetailsInstance.
            return await step_context.begin_dialog(
                self._booking_dialog_id, BookingDetails()
            )

        # Call LUIS and gather any potential booking details. (Note the TurnContext has the response to the prompt.)
        intent, luis_result = await LuisHelper.execute_luis_query(
            self._luis_recognizer, step_context.context
        )

        if intent == Intent.BOOK_FLIGHT.value and luis_result:

            # export luis "understanding" as a trace for performance improvement
            luis_understanding = {}
            luis_understanding["1 - Input"] = step_context.context.activity.text
            luis_understanding["2 - Destination airport"] = luis_result.destination
            luis_understanding["3 - Origin airport"] = luis_result.origin
            luis_understanding["4 - Departure date"] = luis_result.departure_date
            luis_understanding["5 - Return date"] = luis_result.return_date
            luis_understanding["6 - Budget"] = luis_result.budget
            self.telemetry_client.track_trace("Luis understanding", luis_understanding, "INFO")
            
            # Run the BookingDialog giving it whatever details we have from the LUIS call.
            return await step_context.begin_dialog(self._booking_dialog_id, luis_result)

        else:
            didnt_understand_text = (
                "Sorry, I didn't get that. Please try asking in a different way"
            )
            didnt_understand_message = MessageFactory.text(
                didnt_understand_text, didnt_understand_text, InputHints.ignoring_input
            )
            await step_context.context.send_activity(didnt_understand_message)

        return await step_context.next(None)
    async def summary_step(self, step_context: WaterfallStepContext) -> DialogTurnResult:
        student_profile: StudentProfile = await self.student_profile_accessor.get(
            step_context.context, StudentProfile)

        student_profile.name = step_context.values[StudentProfileAttributes.NAME.value]
        student_profile.admission_number = step_context.values[StudentProfileAttributes.ADMISSION_NUMBER.value]
        student_profile.picture = step_context.values[StudentProfileAttributes.PICTURE.value]
        course_units = CourseUnit.search_by_code(self.course.course_units, step_context.result.value)
        student_profile.course_unit = course_units[0] if len(course_units) > 0 else None

        msg = (
            f"Hello {student_profile.name}, your details have been captured as: "
            f"Admission number: {student_profile.admission_number} "
            f"Course unit: {student_profile.course_unit.name} " if student_profile.course_unit else ""
        )

        await step_context.context.send_activity(
            MessageFactory.attachment(
                student_profile.picture, "This is your profile picture."
            )
        )

        await step_context.context.send_activity(MessageFactory.text(msg))
        return await step_context.begin_dialog(CourseQueryDialog.__name__)
    async def loop_step(
            self, step_context: WaterfallStepContext) -> DialogTurnResult:
        selected: List[str] = step_context.values[self.RISK_COUNTRIES_SELECTED]
        dates: List[str] = step_context.values[self.RISK_COUNTRIES_DATES]
        choice: FoundChoice = step_context.result
        done = choice.value == self.DONE_OPTION

        # If they chose a company, add it to the list.
        if not done:
            print("[DEBUG] Appending to risk country list: " + choice.value)
            selected.append(choice.value)
            return await step_context.prompt(
                DateTimePrompt.__name__,
                PromptOptions(prompt=MessageFactory.text(
                    "Wann waren Sie zuletzt in **" + choice.value +
                    "**? Bitte nennen Sie das Datum im Format TT.MM.JJJJ (z.B. 03.03.2020)."
                ), ),
            )

        # If they're done, exit and return their list.
        if done or len(selected) >= len(self.riskcountry_options):
            print("[DEBUG] Risk country selection ending now with " +
                  str([selected, dates]))
            return await step_context.end_dialog([selected, dates])
    async def _on_event_activity(
        self, step_context: WaterfallStepContext
    ) -> DialogTurnResult:
        """
        This method performs different tasks based on the event name.
        """

        activity = step_context.context.activity

        # Resolve what to execute based on the event name.
        if activity.name == "BookFlight":
            return await self._begin_book_flight(step_context)

        if activity.name == "GetWeather":
            return await self._begin_get_weather(step_context)

        # We didn't get an activity name we can handle.
        await step_context.context.send_activity(
            MessageFactory.text(
                f'Unrecognized ActivityName: "{activity.name}".',
                input_hint=InputHints.ignoring_input,
            )
        )
        return DialogTurnResult(DialogTurnStatus.Complete)
Пример #27
0
    async def _send_suggested_actions(self, turn_context: TurnContext):
        reply = MessageFactory.text("Choose your option.")

        reply.suggested_actions = SuggestedActions(
            actions=[
                CardAction(
                    title="Get average performance per score",
                    type=ActionTypes.im_back,
                    value="option_show"
                ),
                CardAction(
                    title="Predict exam score",
                    type=ActionTypes.im_back,
                    value="option_pred"
                ),
                CardAction(
                    title="Get tips for preparation",
                    type=ActionTypes.im_back,
                    value="option_get_rec"
                ),
            ]
        )

        return await turn_context.send_activity(reply)
Пример #28
0
 async def selection_step(
         self, step_context: WaterfallStepContext) -> DialogTurnResult:
     prompt_options = PromptOptions(prompt=MessageFactory.text(self.prompt))
     return await step_context.prompt(NumberPrompt.__name__, prompt_options)
Пример #29
0
    async def _send_oauth_card(self,
                               context: TurnContext,
                               prompt: Union[Activity, str] = None):
        if not isinstance(prompt, Activity):
            prompt = MessageFactory.text(prompt or "", None,
                                         InputHints.accepting_input)
        else:
            prompt.input_hint = prompt.input_hint or InputHints.accepting_input

        prompt.attachments = prompt.attachments or []

        if OAuthPrompt._channel_suppports_oauth_card(
                context.activity.channel_id):
            if not any(att.content_type == CardFactory.content_types.oauth_card
                       for att in prompt.attachments):
                adapter: ExtendedUserTokenProvider = context.adapter
                card_action_type = ActionTypes.signin
                sign_in_resource: SignInUrlResponse = await adapter.get_sign_in_resource_from_user_and_credentials(
                    context,
                    self._settings.oath_app_credentials,
                    self._settings.connection_name,
                    context.activity.from_property.id,
                )
                link = sign_in_resource.sign_in_link
                bot_identity: ClaimsIdentity = context.turn_state.get(
                    BotAdapter.BOT_IDENTITY_KEY)

                # use the SignInLink when in speech channel or bot is a skill or
                # an extra OAuthAppCredentials is being passed in
                if ((bot_identity
                     and SkillValidation.is_skill_claim(bot_identity.claims))
                        or not context.activity.service_url.startswith("http")
                        or self._settings.oath_app_credentials):
                    if context.activity.channel_id == Channels.emulator:
                        card_action_type = ActionTypes.open_url
                elif not OAuthPrompt._channel_requires_sign_in_link(
                        context.activity.channel_id):
                    link = None

                json_token_ex_resource = (
                    sign_in_resource.token_exchange_resource.as_dict()
                    if sign_in_resource.token_exchange_resource else None)
                prompt.attachments.append(
                    CardFactory.oauth_card(
                        OAuthCard(
                            text=self._settings.text,
                            connection_name=self._settings.connection_name,
                            buttons=[
                                CardAction(
                                    title=self._settings.title,
                                    text=self._settings.text,
                                    type=card_action_type,
                                    value=link,
                                )
                            ],
                            token_exchange_resource=json_token_ex_resource,
                        )))
        else:
            if not any(
                    att.content_type == CardFactory.content_types.signin_card
                    for att in prompt.attachments):
                if not hasattr(context.adapter, "get_oauth_sign_in_link"):
                    raise Exception(
                        "OAuthPrompt._send_oauth_card(): get_oauth_sign_in_link() not supported by the current adapter"
                    )

                link = await context.adapter.get_oauth_sign_in_link(
                    context,
                    self._settings.connection_name,
                    None,
                    self._settings.oath_app_credentials,
                )
                prompt.attachments.append(
                    CardFactory.signin_card(
                        SigninCard(
                            text=self._settings.text,
                            buttons=[
                                CardAction(
                                    title=self._settings.title,
                                    value=link,
                                    type=ActionTypes.signin,
                                )
                            ],
                        )))

        # Send prompt
        await context.send_activity(prompt)
Пример #30
0
    async def _send_oauth_card(self,
                               context: TurnContext,
                               prompt: Union[Activity, str] = None):
        if not isinstance(prompt, Activity):
            prompt = MessageFactory.text(prompt or "", None,
                                         InputHints.accepting_input)
        else:
            prompt.input_hint = prompt.input_hint or InputHints.accepting_input

        prompt.attachments = prompt.attachments or []

        if OAuthPrompt._channel_suppports_oauth_card(
                context.activity.channel_id):
            if not any(att.content_type == CardFactory.content_types.oauth_card
                       for att in prompt.attachments):
                link = None
                card_action_type = ActionTypes.signin
                bot_identity: ClaimsIdentity = context.turn_state.get(
                    "BotIdentity")

                # check if it's from streaming connection
                if not context.activity.service_url.startswith("http"):
                    if not hasattr(context.adapter, "get_oauth_sign_in_link"):
                        raise Exception(
                            "OAuthPrompt: get_oauth_sign_in_link() not supported by the current adapter"
                        )
                    link = await context.adapter.get_oauth_sign_in_link(
                        context,
                        self._settings.connection_name,
                        None,
                        self._settings.oath_app_credentials,
                    )
                elif bot_identity and SkillValidation.is_skill_claim(
                        bot_identity.claims):
                    link = await context.adapter.get_oauth_sign_in_link(
                        context,
                        self._settings.connection_name,
                        None,
                        self._settings.oath_app_credentials,
                    )
                    card_action_type = ActionTypes.open_url

                prompt.attachments.append(
                    CardFactory.oauth_card(
                        OAuthCard(
                            text=self._settings.text,
                            connection_name=self._settings.connection_name,
                            buttons=[
                                CardAction(
                                    title=self._settings.title,
                                    text=self._settings.text,
                                    type=card_action_type,
                                    value=link,
                                )
                            ],
                        )))
        else:
            if not any(
                    att.content_type == CardFactory.content_types.signin_card
                    for att in prompt.attachments):
                if not hasattr(context.adapter, "get_oauth_sign_in_link"):
                    raise Exception(
                        "OAuthPrompt.send_oauth_card(): get_oauth_sign_in_link() not supported by the current adapter"
                    )

                link = await context.adapter.get_oauth_sign_in_link(
                    context,
                    self._settings.connection_name,
                    None,
                    self._settings.oath_app_credentials,
                )
                prompt.attachments.append(
                    CardFactory.signin_card(
                        SigninCard(
                            text=self._settings.text,
                            buttons=[
                                CardAction(
                                    title=self._settings.title,
                                    value=link,
                                    type=ActionTypes.signin,
                                )
                            ],
                        )))

        # Send prompt
        await context.send_activity(prompt)