Create programmatically

How to create buttons & quick replies programmatically in Python

If you are creating your own components, or want to create a custom button type, you can do so using Python3. Both buttons and quick replies use the ButtonElementSpec which can be imported from meya.component.element.

Example

📘

This example is from our demo_app repo which is a great resource for learning about features the Meya platform offers.

First, we’ll create a component that builds a tiles component, then we’ll add a flow that uses our new tile builder.

  1. Create the component in component/tile/ called build.py and copy this code into it:
import random

from dataclasses import dataclass
from meya.button.spec import ButtonElementSpec
from meya.component.element import Component
from meya.component.element import ComponentResponse
from meya.entry import Entry
from meya.tile.spec import TileCell
from meya.tile.spec import TileElementSpec
from typing import List


@dataclass
class BuildTilesComponent(Component):
    async def start(self) -> List[Entry]:
        flow = self.entry.data
        tile_count = flow["tile_count"]
        image = flow["image"]
        title = flow["title"]
        description = flow["description"]
        cell_row_count = flow["cell_row_count"]
        cell_count = flow["cell_count"]
        link_button_count = flow["link_button_count"]
        button_count = flow["button_count"]

        sagan_ipsum = "Circumnavigated how far away ship of the imagination star stuff harvesting star light great turbulent clouds a billion trillion"
        sagan_ipsum_words = sagan_ipsum.split(" ")
        tiles = []
        for _ in range(tile_count):
            rows = []
            for _ in range(cell_row_count):
                cells = []
                for _ in range(cell_count):
                    cells.append(
                        TileCell(
                            cell=random.choice(sagan_ipsum_words).title(),
                            value=random.choice(sagan_ipsum_words).lower(),
                        )
                    )
                rows.append(cells)
            button_offset = (
                tile_count + len(tiles) * link_button_count * button_count
            )
            buttons = []
            for _ in range(link_button_count):
                button = button_offset + len(buttons)
                buttons.append(
                    ButtonElementSpec(
                        text=f"Link button {button}",
                        url=f"https://cataas.com/cat/says/Link%20button%20{button}",
                    )
                )
            for _ in range(button_count):
                button = button_offset + len(buttons)
                buttons.append(
                    ButtonElementSpec(text=f"Button {button}", result=button)
                )
            tile = len(tiles)
            tiles.append(
                TileElementSpec(
                    title=f"Title {tile}" if title else None,
                    description=sagan_ipsum if description else None,
                    result=None if buttons else tile,
                    image={"url": f"https://cataas.com/cat/says/Tile%20{tile}"}
                    if image
                    else None,
                    rows=rows if rows else None,
                    buttons=buttons if buttons else None,
                )
            )
        return self.respond(data=ComponentResponse(tiles))

There’s a lot going on here, but since this guide is focused on buttons and quick replies, pay close attention to lines 47 to 57 where the buttons are created. In this case we’re creating two url buttons and two action buttons per tile. On line 68 the buttons are added to the new tile.

  1. Now create a new flow called build_tile.yaml and copy this code into it:
triggers:
  - keyword: build_tile
    action:
      jump: build
      data:
        layout: row
        button_style: action
        tile_count: 3
        image: true
        title: true
        description: true
        cell_row_count: 2
        cell_count: 2
        link_button_count: 2
        button_count: 2

steps:
  - component.tile.build
  - flow_set: tiles

  - ask: Here are your tiles...
    tiles: (@ flow.tiles)
    button_style: (@ flow.button_style)
    layout: (@ flow.layout )
  - say: Result is (@ flow.result )

Notice that we refer to our new component using the component reference path.

Open the chat simulator in your browser and enter the keyword build_tile to trigger the flow. You should see something like this:

1467