Python-slack-sdk: Submitting modal from views_open() always fails

Created on 5 Jul 2020  路  5Comments  路  Source: slackapi/python-slack-sdk

Description

Describe your issue here.

What type of issue is this? (place an x in one of the [ ])

  • [ ] bug
  • [ ] enhancement (feature request)
  • [x] question
  • [x] documentation related
  • [ ] testing related
  • [ ] discussion

Requirements (place an x in each of the [ ])

  • [x] I've read and understood the Contributing guidelines and have done my best effort to follow them.
  • [x] I've read and agree to the Code of Conduct.
  • [x] I've searched for any related issues and avoided creating a duplicate issue.

Bug Report

Hey- I'm using the python-slackclient v2.7.2 in my Flask app to open a modal and get user input. I followed this guide https://python-slackclient.readthedocs.io/en/latest/basic_usage.html under the section 'Opening a modal'. I followed the exact steps there, but always get the error 'We had some trouble connecting. Try again?' when I try to submit the modal. I've been searching for a solution, but the example seems right- it IS returning a 200 response with an empty body on success. I've tried a bunch of other examples as well, but the form won't submit even though the proper response is being sent in less than 3 seconds

Reproducible in:

slackclient version: 2.7.2

python version: 3.8.2

OS version(s): OSX catalina 10.15.4

Steps to reproduce:

  1. Add the following to an app.py file:
from flask import Flask, request, make_response, Response
from slack import WebClient
from slack.errors import SlackApiError
from slack.signature import SignatureVerifier

import os
import json


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

# Slack client for Web API requests
client = WebClient(SLACK_BOT_TOKEN)

# Flask web server for incoming traffic from Slack
app = Flask(__name__)
signature_verifier = SignatureVerifier(os.environ["SLACK_SIGNING_SECRET"])

@app.route("/", methods=["POST"])
def slack_app():
  if not signature_verifier.is_valid_request(request.get_data(), request.headers):
    return make_response("invalid request", 403)

  if "command" in request.form \
    and request.form["command"] == "/open-modal":
    trigger_id = request.form["trigger_id"]
    try:
      response = client.views_open(
        trigger_id=trigger_id,
        view={
          "type": "modal",
          "callback_id": "modal-id",
          "title": {
            "type": "plain_text",
            "text": "Awesome Modal"
          },
          "submit": {
            "type": "plain_text",
            "text": "Submit"
          },
          "close": {
            "type": "plain_text",
            "text": "Cancel"
          },
          "blocks": [
            {
              "type": "input",
              "block_id": "b-id",
              "label": {
                "type": "plain_text",
                "text": "Input label",
              },
              "element": {
                "action_id": "a-id",
                "type": "plain_text_input",
              }
            }
          ]
        }
      )
      return make_response("", 200)
    except SlackApiError as e:
      code = e.response["error"]
      return make_response(f"Failed to open a modal due to {code}", 200)

  elif "payload" in request.form:
    payload = json.loads(request.form["payload"])
    if payload["type"] == "view_submission" \
      and payload["view"]["callback_id"] == "modal-id":
      submitted_data = payload["view"]["state"]["values"]
      print(submitted_data)  # {'b-id': {'a-id': {'type': 'plain_text_input', 'value': 'your input'}}}
      return make_response("", 200)

  return make_response("", 404)

if __name__ == "__main__":
  # export SLACK_SIGNING_SECRET=***
  # export SLACK_API_TOKEN=xoxb-***
  # export FLASK_ENV=development
  app.run("localhost", 5000)


if __name__ == "__main__":
    app.run()
  1. Set your environment variables.
  2. Run the app with python3 -m flask run
  3. Start ngrok with ngrok http 5000
  4. Create a slash command in your slack app called /open-modal and set the endpoint to the ngrok https endpoint from above.
  5. Invoke /open-modal in slack, enter input, and click Submit
  6. See error

Screen Shot 2020-07-05 at 2 54 04 PM

Expected result:

The form submits successfully and POST's data back to the endpoint..

2x docs question

All 5 comments

Hi, thanks for sharing this!

I'm afraid that you haven't yet set up the Request URL in the Interactivity & Shortcuts section. To receive view submission requests, telling your endpoint URL to the Slack API server beforehand is required. Refer to https://api.slack.com/interactivity/handling#setup for more details.

Also, I will improve this SDK's document to be more friendly for developers. Thanks a lot 馃檱

Now that the document mentions the Slack app configuration that is necessary for running the code snippet, please allow me to close this issue. Thanks for your great feedback here.

@seratch I have the right interactivity endpoint setup and the endpoint can receive the modal id. I am using fastapi not flask btw.

image

image

@app.post("/interactive")
async def interactive(request: Request):
    form = await request.form()
    body = jsonable_encoder(form['payload'])
    dict_payload = json.loads(body)
    print("received callback_id"+dict_payload.get('view').get('callback_id'))
    return ""

I guess the issue seem to be slackclient won't close the modal after the submission somehow?

Hello I have a problem. When loading all the data, the modal sends me the information I need in the backend, but it gives me an error (500) and the modal does not close. Any suggestion?

@app.route('/interactive', methods=['POST'])
def interactive():

payload = json.loads(request.form["payload"])

val_type = payload['type']

@seratch I have the right interactivity endpoint setup and the endpoint can receive the modal id. I am using fastapi not flask btw.

image

image

@app.post("/interactive")
async def interactive(request: Request):
    form = await request.form()
    body = jsonable_encoder(form['payload'])
    dict_payload = json.loads(body)
    print("received callback_id"+dict_payload.get('view').get('callback_id'))
    return ""

I guess the issue seem to be slackclient won't close the modal after the submission somehow?

could you solve it?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

vv-grinko picture vv-grinko  路  3Comments

tinoargentino picture tinoargentino  路  4Comments

juan-vg picture juan-vg  路  5Comments

kompotkot picture kompotkot  路  4Comments

sofya-salmanova picture sofya-salmanova  路  5Comments