Code Monkey home page Code Monkey logo

python-message-menu-example's Introduction

Maximizing your Slack app's usefulness

When we think about how bots and humans interact within Slack, we often think of two types of interaction: Notification and Conversation.

The simplest form of Slack integration is to have your app post important information from another service into a slack channel. This works well for a variety of situations, such as package arrival notifications or an alert that one of your servers has caught on fire. Notifications are simple, timely, and informative. When your app is a part of a much more complex workflow, notifications are just a jumping point into another application or process.

As your processes and workflows become more complex, involving several applications across multiple windows, things can get ...complicated.

Message Buttons

Back in June, we released Message Buttons. Using these new interactive elements, developers were able to bring common workflow actions right into the bot's message. Users could not only see the notification message, but take action from inside Slack. This also eased a lot of the complexity with conversational bots. Rather than requiring a user to type a specific confirmation message, you were able to show the user a set of buttons to complete or cancel an action.

Message Buttons demo GIF

While Message Buttons are a great way to increase the usability of your Slack application, there are some limitations. One limitation is the amount of real estate buttons take up. When you have a large set of options, you'll end up with a message that takes up the user's entire chat window or gets truncated.

See our Message Buttons with Node.js tutorial for more information on how to add message buttons to your app.

Message Menus

Today we've released message menus ๐ŸŽ‰

Message menus are the newest interactive feature for Slack apps: clickable dropdown menus that you can add to message attachments. They can have static options, or they can load dynamically. You can build with five types of message menu today, each achieving a different flavor of use case: static menus, user menus, channel menus, conversation menus, and dynamic menus.

Slack message menu example

Read more about how apps are using message menus on our blog.

Adding message menus to your app

In this tutorial, we'll focus on adding dynamic option menus to your app. Here's a summary of how dynamic interactive message menus work:

  1. Post a message containing one or more attachments containing one or more interactive elements
  2. Slack sends a request to your registered Options Load URL containing the context you need to generate relevant menu options. You simply respond to this request with a JSON array of options.
  3. Users click a button or select an option from a menu
  4. A request is sent to your registered Action URL containing all the context you need to understand: who clicked it, which option they clicked, which message callback_id was associated with the message, and the original message inciting the selection
  5. You respond to your Action URL's invocation with a message to replace the original, and/or a new ephemeral message, and/or you utilize the invocation's response_url to update the original message out of band for a limited time.

Let's build it!

๐Ÿ’ก This code is also available as a complete example application on GitHub.

While we're building this example in Python, we haven't forgotten about the Node fans. We've put together a really neat example for Node.js over here ๐ŸŽ‰

For this example, we're going to need Python, the Python Slack client (slackclient) and a webserver (Flask).

First you'll create the basic elements of the app: A Slack client and webserver

from flask import Flask, request, make_response, Response
from slackclient import SlackClient
import json

# Your app's Slack bot user token
SLACK_BOT_TOKEN = os.environ["SLACK_BOT_TOKEN"]

# Slack client for Web API requests
slack_client = SlackClient(SLACK_BOT_TOKEN)

# Flask webserver for incoming traffic from Slack
app = Flask(__name__)

Then we'll add the two endpoints Slack will POST requests to. The first endpoint is where Slack will send a request for items to populate the menu options, we'll call this one message_options.

@app.route("/slack/message_options", methods=["POST"])
def message_options():
    # Parse the request payload
    form_json = json.loads(request.form["payload"])

    menu_options = {
        "options": [
            {
                "text": "Chess",
                "value": "chess"
            },
            {
                "text": "Global Thermonuclear War",
                "value": "war"
            }
        ]
    }

    return Response(json.dumps(menu_options), mimetype='application/json')

The second endpoint you'll need is where Slack will send data when a user makes a selection. We'll call this one message_actions.

@app.route("/slack/message_actions", methods=["POST"])
def message_actions():

    # Parse the request payload
    form_json = json.loads(request.form["payload"])

    # Check to see what the user's selection was and update the message
    selection = form_json["actions"][0]["selected_options"][0]["value"]

    if selection == "war":
        message_text = "The only winning move is not to play.\nHow about a nice game of chess?"
    else:
        message_text = ":horse:"

    response = slack_client.api_call(
      "chat.update",
      channel=form_json["channel"]["id"],
      ts=form_json["message_ts"],
      text=message_text,
      attachments=[]
    )

    return make_response("", 200)

Now that our endpoints are configured, we can build the message containing the menu and send it to a channel.

In order to show the menu, we'll have to build the message attachment which will contain it.

message_attachments = [
    {
        "fallback": "Upgrade your Slack client to use messages like these.",
        "color": "#3AA3E3",
        "attachment_type": "default",
        "callback_id": "menu_options_2319",
        "actions": [
            {
                "name": "games_list",
                "text": "Pick a game...",
                "type": "select",
                "data_source": "external"
            }
        ]
    }
]

Once the attachment JSON is ready, simply post a message to the channel, adding the attachment containing the menu.

slack_client.api_call(
  "chat.postMessage",
  channel="C09EM2073",
  text="Shall we play a game?",
  attachments=message_attachments
)

Take note of the "data_source": "external" attribute in the attachment JSON. This is how Slack knows to pull the menu options from the message_options endpoint we set up above.

slack_client.api_call(
  "chat.postMessage",
  channel="C09EM2073",
  text="Shall we play a game?",
  attachments=attachments_json
)

Support

Need help? Join Bot Developer Hangout and talk to us in #slack-api.

You can also create an Issue right here on GitHub.

python-message-menu-example's People

Contributors

colmdoyle avatar roach avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-message-menu-example's Issues

Darn โ€“ that didnโ€™t work. Only Slack Apps can add interactive elements to messages. Manage your apps here: https://api.slack.com/apps/

Hi, I have a problem that receiving response from the message button, please help.

my ngrok URL is https://46dc7138.ngrok.io, I have set my interactive component URL to https://46dc7138.ngrok.io/slack/actions and in my code @app.route('/slack/actions', methods=['POST']) but I still get the error Darn โ€“ that didnโ€™t work. Only Slack Apps can add interactive elements to messages. Manage your apps here: https://api.slack.com/apps/

Menu options not loading

Hi,

While executing the script I message menus doesn't load.It takes time.
Any suggestions here.

Thanks.

Interactive Messages need a publicly exposed https address for the Request URL

Hello,

I've been working on figuring out the interactive messages in slack for a few days now. I finally found a tutorial that detailed the required steps, including in the developer console. Ultimately I didn't know that I needed to have a publicly exposed server for some URLs and that http wasn't supported on some of them as well. I followed the instructions here to figure this out: https://github.com/howdyai/botkit/blob/master/docs/slack-events-api.md and used ngrok.io to tunnel to my localhost webserver. It'd be awesome of the instructions here included the required steps to get the example to actually function to a private dev box. Which URLs need to be public and so on.

It'd also be nice if something said about the "Request URL" being the same thing as the "Action URL", I'm not sure why there are two names for the same thing, but that isn't intuitive at all. I spent some time trying to figure out what this third URL was. It'd be helpful to mention which lines in the script need to be edited and to which value. I found conflicting information about the channel being plain text channel name or a unique slack internal name. Some examples had the # prepended, others didn't.

Thank you,

Ethan Grinnell

"GET / HTTP/1.1" 404

message with

I am Coffeebot ::robot_face::, and I'm here to help bring you fresh coffee :coffee:

shows up in channel, but nothing happens then.
Terminal and ngrok display:

GET /                          404 NOT FOUND                                                      
GET /favicon.ico               404 NOT FOUND   
GET /slack/message_actions     405 METHOD NOT ALLOWED

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.