Search code examples
pythonflaskslack

How to run dialog in slack app with flask?


I am in the middle of creating todo app integreted with Slack. I need to use dialog.open property of slack.

I managed to go through slack api tutorial however can not finally understand how dialogs work in integration with external systems. I created code which runs after slash command in slack. It should open dialog and show it to user, however it doesn't. I printed some parts of code to see what happens inside - looks like whole code works and server returns 200.

@app.route('/helpdesk', methods=['POST'])
def helpdesk():
    print(request.form)

    api_url = 'https://slack.com/api/dialog.open'

    user_id = request.form['user_id']
    trigger_id = request.form['trigger_id']

    dialog = {
    "token": "J1llSAeQAxNyw8yc37xuEsad",
    "trigger_id": trigger_id,
    "dialog": {
        "callback_id": "ryde-46e2b0",
        "title": "Request a Ride",
        "submit_label": "Request",
        "notify_on_cancel": True,
        "state": "Limo",
        "elements": [
            {
                "type": "text",
                "label": "Pickup Location",
                "name": "loc_origin"
            },
            {
                "type": "text",
                "label": "Dropoff Location",
                "name": "loc_destination"
            }
        ]
    }
    }

    print(dialog)
    requests.post(api_url, data=dialog)

    return make_response()

I expect to see dialog window after writing slash command in slack. What I see in prints:

ImmutableMultiDict([('token', 'J1llSAeQAxNyw8yc37xuEsad'), ('team_id', 'TKWQ5QP7Y'), ('team_domain', 'team-learningslack'), ('channel_id', 'CKH7RSZPC'), ('channel_name', 'slackflask'), ('user_id', 'UKN9KU7JM'), ('user_name', 'konrad.marzec1991'), ('command', '/musi'), ('text', ''), ('response_url', 'https://hooks.slack.com/commands/TKWQ5QP7Y/664885241506/ABjpMYmTWrnXpSBoGMpaJtOV'), ('trigger_id', '669947662833.676821839270.6c4bddd1418d3d4f2c8626f7c9accdf7')])

{'token': 'J1llSAeQAxNyw8yc37xuEsad', 'trigger_id': '669947662833.676821839270.6c4bddd1418d3d4f2c8626f7c9accdf7', 'dialog': {'callback_id': 'ryde-46e2b0', 'title': 'Request a Ride', 'submit_label': 'Request', 'notify_on_cancel': True, 'state': 'Limo', 'elements': [{'type': 'text', 'label': 'Pickup Location', 'name': 'loc_origin'}, {'type': 'text', 'label': 'Dropoff Location', 'name': 'loc_destination'}]}}
127.0.0.1 - - [26/Jun/2019 00:15:35] "POST /helpdesk HTTP/1.1" 200 -

Solution

  • You had 2 issues in your code:

    • you need to use an access token, not a verification token in the call to dialog.open
    • you need to send the dialog definition as JSON, not as as form array

    I made these additional changes - Added code for using a slack token defined as environment variable - Use the get() method to access form parameters in from the request - Added code to show the API response from dialog.open

    Here is a corrected version of your code:

    import os
    import requests
    from flask import Flask, json, request
    
    app = Flask(__name__) #create the Flask app
    
    @app.route('/helpdesk', methods=['POST'])
    def helpdesk():
    
        api_url = 'https://slack.com/api/dialog.open'
    
        trigger_id = request.form.get('trigger_id')
    
        dialog = {
            "callback_id": "ryde-46e2b0",
            "title": "Request a Ride",
            "submit_label": "Request",
            "notify_on_cancel": True,
            "state": "Limo",
            "elements": [
                {
                    "type": "text",
                    "label": "Pickup Location",
                    "name": "loc_origin"
                },
                {
                    "type": "text",
                    "label": "Dropoff Location",
                    "name": "loc_destination"
                }
            ]
        }
    
        api_data = {
            "token": os.environ['SLACK_TOKEN'],
            "trigger_id": trigger_id,
            "dialog": json.dumps(dialog)
        }
    
        res = requests.post(api_url, data=api_data)
        print(res.content)
    
        return make_response()
    
    if __name__ == '__main__':
        app.run(debug=True, port=8000) #run app in debug mode on port 8000