Responses: 2. Buttons#

In this tutorial Button class is demonstrated. Buttons are one of Message fields. They can be attached to any message but will only work if the chosen messenger interface supports them.

[1]:
# installing dependencies
%pip install -q dff
Note: you may need to restart the kernel to use updated packages.
[2]:
import dff.script.conditions as cnd
import dff.script.labels as lbl
from dff.script import Context, TRANSITIONS, RESPONSE

from dff.script.core.message import Button, Keyboard, Message
from dff.pipeline import Pipeline
from dff.utils.testing import (
    check_happy_path,
    is_interactive_mode,
    run_interactive_mode,
)
[3]:
def check_button_payload(value: str):
    def payload_check_inner(ctx: Context, _: Pipeline):
        if ctx.last_request.misc is not None:
            return ctx.last_request.misc.get("payload") == value
        else:
            return False

    return payload_check_inner
[4]:
toy_script = {
    "root": {
        "start": {
            RESPONSE: Message(""),
            TRANSITIONS: {
                ("general", "question_1"): cnd.true(),
            },
        },
        "fallback": {RESPONSE: Message("Finishing test")},
    },
    "general": {
        "question_1": {
            RESPONSE: Message(
                **{
                    "text": "Starting test! What's 2 + 2?"
                    " (type in the index of the correct option)",
                    "misc": {
                        "ui": Keyboard(
                            buttons=[
                                Button(text="5", payload="5"),
                                Button(text="4", payload="4"),
                            ]
                        ),
                    },
                }
            ),
            TRANSITIONS: {
                lbl.forward(): check_button_payload("4"),
                ("general", "question_1"): check_button_payload("5"),
            },
        },
        "question_2": {
            RESPONSE: Message(
                **{
                    "text": "Next question: what's 6 * 8?"
                    " (type in the index of the correct option)",
                    "misc": {
                        "ui": Keyboard(
                            buttons=[
                                Button(text="38", payload="38"),
                                Button(text="48", payload="48"),
                            ]
                        ),
                    },
                }
            ),
            TRANSITIONS: {
                lbl.forward(): check_button_payload("48"),
                ("general", "question_2"): check_button_payload("38"),
            },
        },
        "question_3": {
            RESPONSE: Message(
                **{
                    "text": "What's 114 + 115? "
                    "(type in the index of the correct option)",
                    "misc": {
                        "ui": Keyboard(
                            buttons=[
                                Button(text="229", payload="229"),
                                Button(text="283", payload="283"),
                            ]
                        ),
                    },
                }
            ),
            TRANSITIONS: {
                lbl.forward(): check_button_payload("229"),
                ("general", "question_3"): check_button_payload("283"),
            },
        },
        "success": {
            RESPONSE: Message("Success!"),
            TRANSITIONS: {("root", "fallback"): cnd.true()},
        },
    },
}

happy_path = (
    (
        Message("Hi"),
        Message(
            **{
                "text": "Starting test! What's 2 + 2? "
                "(type in the index of the correct option)",
                "misc": {
                    "ui": Keyboard(
                        buttons=[
                            Button(text="5", payload="5"),
                            Button(text="4", payload="4"),
                        ]
                    )
                },
            }
        ),
    ),
    (
        Message("0"),
        Message(
            **{
                "text": "Starting test! What's 2 + 2? "
                "(type in the index of the correct option)",
                "misc": {
                    "ui": Keyboard(
                        buttons=[
                            Button(text="5", payload="5"),
                            Button(text="4", payload="4"),
                        ]
                    ),
                },
            }
        ),
    ),
    (
        Message("1"),
        Message(
            **{
                "text": "Next question: what's 6 * 8? "
                "(type in the index of the correct option)",
                "misc": {
                    "ui": Keyboard(
                        buttons=[
                            Button(text="38", payload="38"),
                            Button(text="48", payload="48"),
                        ]
                    ),
                },
            }
        ),
    ),
    (
        Message("0"),
        Message(
            **{
                "text": "Next question: what's 6 * 8? "
                "(type in the index of the correct option)",
                "misc": {
                    "ui": Keyboard(
                        buttons=[
                            Button(text="38", payload="38"),
                            Button(text="48", payload="48"),
                        ]
                    ),
                },
            }
        ),
    ),
    (
        Message("1"),
        Message(
            **{
                "text": "What's 114 + 115? "
                "(type in the index of the correct option)",
                "misc": {
                    "ui": Keyboard(
                        buttons=[
                            Button(text="229", payload="229"),
                            Button(text="283", payload="283"),
                        ]
                    ),
                },
            }
        ),
    ),
    (
        Message("1"),
        Message(
            **{
                "text": "What's 114 + 115? "
                "(type in the index of the correct option)",
                "misc": {
                    "ui": Keyboard(
                        buttons=[
                            Button(text="229", payload="229"),
                            Button(text="283", payload="283"),
                        ]
                    ),
                },
            }
        ),
    ),
    (Message("0"), Message("Success!")),
    (Message("ok"), Message("Finishing test")),
)


def process_request(ctx: Context):
    ui = (
        ctx.last_response
        and ctx.last_response.misc
        and ctx.last_response.misc.get("ui")
    )
    if ui and ui.buttons:
        try:
            chosen_button = ui.buttons[int(ctx.last_request.text)]
        except (IndexError, ValueError):
            raise ValueError(
                "Type in the index of the correct option "
                "to choose from the buttons."
            )
        ctx.last_request = Message(misc={"payload": chosen_button.payload})
[5]:
pipeline = Pipeline.from_script(
    toy_script,
    start_label=("root", "start"),
    fallback_label=("root", "fallback"),
    pre_services=[process_request],
)

if __name__ == "__main__":
    check_happy_path(
        pipeline,
        happy_path,
    )  # For response object with `happy_path` string comparing,
    # a special `generics_comparer` comparator is used
    if is_interactive_mode():
        run_interactive_mode(pipeline)
(user) >>> text='Hi'
 (bot) <<< text='Starting test! What's 2 + 2? (type in the index of the correct option)' misc='{'ui': {'buttons': [{'text': '5', 'payload': '5'}, {'text': '4', 'payload': '4'}]}}'
(user) >>> text='0'
 (bot) <<< text='Starting test! What's 2 + 2? (type in the index of the correct option)' misc='{'ui': {'buttons': [{'text': '5', 'payload': '5'}, {'text': '4', 'payload': '4'}]}}'
(user) >>> text='1'
 (bot) <<< text='Next question: what's 6 * 8? (type in the index of the correct option)' misc='{'ui': {'buttons': [{'text': '38', 'payload': '38'}, {'text': '48', 'payload': '48'}]}}'
(user) >>> text='0'
 (bot) <<< text='Next question: what's 6 * 8? (type in the index of the correct option)' misc='{'ui': {'buttons': [{'text': '38', 'payload': '38'}, {'text': '48', 'payload': '48'}]}}'
(user) >>> text='1'
 (bot) <<< text='What's 114 + 115? (type in the index of the correct option)' misc='{'ui': {'buttons': [{'text': '229', 'payload': '229'}, {'text': '283', 'payload': '283'}]}}'
(user) >>> text='1'
 (bot) <<< text='What's 114 + 115? (type in the index of the correct option)' misc='{'ui': {'buttons': [{'text': '229', 'payload': '229'}, {'text': '283', 'payload': '283'}]}}'
(user) >>> text='0'
 (bot) <<< text='Success!'
(user) >>> text='ok'
 (bot) <<< text='Finishing test'