How to pass data received via HTTP POST from a Python Flask script to a separate Python script for processing? How to pass data received via HTTP POST from a Python Flask script to a separate Python script for processing? flask flask

How to pass data received via HTTP POST from a Python Flask script to a separate Python script for processing?


Great Success!

tl;dr:Basically, the solution was to create a Celery task that instantiated the bot instance from the Flask app using the Slack Events API. You set the task to start after the desired input has been entered, promptly return the required Response(200) back to Slack, while in the meantime the bot script (which starts up the RTM API web-socket) launches in parallel.

The nitty gritty:So, as stated above, it turns out that what was required was a queuing service of some sort. I ended up going with Celery for its relative ease at integrating with Heroku (where I host the Slack app) and its easy-to-follow documentation.

Developing your Slack app this way requires setting up and using the Slack Events API to receive the command ("play my_game" in this example) from the Slack channel the message was posted in. The Flask app (app.py) portion of the program listens for this event, and when the input matches up with what you're looking for, it launches the Celery task in parallel (in tasks.py, which instantiates a Bot() instance of bot.py in this example). :) Now the bot can listen and respond using both the Slack RTM API and the Slack Events API. This allows you to build rich applications/services within the Slack framework.

If you are looking to set up something similar, below are my project layout and the important code details. Feel free to use them as a template.

Project Layout:

  • project_name_folder
    • app_folder
      • static_folder
      • templates_folder
      • __init__.py
      • my_app.py
      • bot.py
      • tasks.py
    • Procfile
    • requirements.txt

__init__.py:

from celery import Celeryapp = Celery('tasks')import osapp.conf.update(BROKER_URL=os.environ['RABBITMQ_BIGWIG_URL']) # Heroku Celery broker

my_app.py:

from flask import Flask, request, Response, render_templateimport appfrom app import tasksapp = Flask(__name__)@app.route('/events', methods=['POST'])def events():"""Handles the inbound event of a post to the main Slack channel"""  data = json.loads(request.data)  try:    for k, v in data['event'].iteritems():      ts = data['event']['ts']      channel = data['event']['channel']      user_id = data['event']['user']      team_id = data['team_id']      if 'play my_game' in str(v):        tasks.launch_bot.delay(user_id, channel, ts, team_id) # launch the bot in parallel        return Response(), 200  except Exception as e:    raise

bot.py:

from slackclient import SlackClientclass Bot():  def main():    # opening the Slack web-socket connection    READ_WEBSOCKET_DELAY = 1  # 1 second delay between reading from firehose    if self.slack_client.rtm_connect():      while True:        command, channel, user, ts = self.parse_slack_output()          if command and channel:            if channel not in self.channel_ids_to_name.keys():              # this (most likely) means that this channel is a PM with the bot              self.handle_private_message(command, user, ts)            else:              self.handle_command(command, channel, user, ts)          time.sleep(READ_WEBSOCKET_DELAY)

tasks.py:

import botfrom bot import Botfrom app import app@app.taskdef launch_bot(user_id, channel, ts, team_id):'''Instantiates the necessary objects to play a gameArgs:        [user_id] (str) The id of the user from which the command was sent        [channel] (str) The channel the command was posted in        [ts] (str) The timestamp of the command'''  print "launch_bot(user_id,channel)"  app.control.purge()  bot = Bot()  bot.initialize(user_id, channel)  bot.main()

Procfile (if using Heroku):

web: gunicorn --pythonpath app my_app:appworker: celery -A app.tasks worker -B --loglevel=DEBUG

Please let me know if you are having any issues. This took me a little while to figure out, and I would be happy to help you if you are banging your head on this one.