Using separate modules to make the code more maintainable.
from dotenv import load_dotenv
load_dotenv('${DEPLOY_DIR}/.turbot.env')
-from turbot import app as application
+from turbot.turbot import app as application
--- /dev/null
+from flask import Blueprint, request, make_response
+from turbot.slack import slack_is_valid_request, slack_send_reply
+import re
+
+rot_route = Blueprint('rot_route', __name__)
+
+def rot_string(str, n=13):
+ """Return a rotated version of a string
+
+ Specifically, this functions returns a version of the input string
+ where each uppercase letter has been advanced 'n' positions in the
+ alphabet (wrapping around). Lowercase letters and any non-alphabetic
+ characters will be unchanged."""
+
+ result = ''
+ for letter in str:
+ if letter.isupper():
+ result += chr(ord("A") + (ord(letter) - ord("A") + n) % 26)
+ else:
+ result += letter
+ return result
+
+@rot_route.route('/rot', methods = ['POST'])
+def rot():
+ """Implements the /rot route for the /rot slash command in Slack
+
+ This implements the /rot command of our Slack bot. The format of this
+ command is as follows:
+
+ /rot [count|*] String to be rotated
+
+ The optional count indicates an amount to rotate each character in the
+ string. If the count is '*' or is not present, then the string will
+ be rotated through all possible 25 values.
+
+ The result of the rotation is provided as a message in Slack. If the
+ slash command was issued in a direct message, the response is made by
+ using the "response_url" from the request. This allows the bot to reply
+ in a direct message that it is not a member of. Otherwise, if the slash
+ command was issued in a channel, the bot will reply in that channel."""
+
+ if not slack_is_valid_request(request):
+ return make_response("invalid request", 403)
+
+ query = request.form.get('text')
+ match = re.match(r'^([0-9]+|\*) (.*)$', query)
+ if (match):
+ try:
+ count = int(match.group(1))
+ except ValueError:
+ count = None
+ text = match.group(2)
+ else:
+ count = None
+ text = query
+
+ text = text.upper()
+
+ reply = "```/rot {} {}\n".format(count if count else '*', text)
+
+ if count:
+ reply += rot_string(text, count)
+ else:
+ reply += "\n".join(["{:02d} ".format(count) + rot_string(text, count)
+ for count in range(1, 26)])
+
+ reply += "```"
+
+ slack_send_reply(request, reply)
+
+ return ""
--- /dev/null
+from flask import current_app
+from slack import WebClient
+from slack.errors import SlackApiError
+from slack.signature import SignatureVerifier
+import os
+import requests
+
+slack_signing_secret = os.environ['SLACK_SIGNING_SECRET']
+slack_bot_token = os.environ['SLACK_BOT_TOKEN']
+
+signature_verifier = SignatureVerifier(slack_signing_secret)
+slack_client = WebClient(slack_bot_token)
+
+def slack_is_valid_request(request):
+ """Returns true if request actually came from Slack.
+
+ By means of checking the requests signature together with the slack
+ signing key.
+
+ Note: If flask is in debug mode, this function will always return true."""
+
+ if current_app.debug:
+ return True
+
+ data = request.get_data()
+ headers = request.headers
+
+ return signature_verifier.is_valid_request(data, headers)
+
+def slack_send_reply(request, text):
+ """Send a Slack message as a reply to a specified request.
+
+ If the request is associated with a direct message, the reply is
+ made by using the "response_url" from the request. Otherwise, the
+ reply will be sent to the channel associated with the request.
+
+ Note: If flask is in debug mode, this function will just print the
+ text to stdout."""
+
+ app = current_app
+ channel_name = request.form.get('channel_name')
+ response_url = request.form.get('response_url')
+ channel = request.form.get('channel_id')
+
+ if (app.debug):
+ print("Sending message to channel '{}': {}".format(channel, text))
+ return
+
+ if (channel_name == "directmessage"):
+ resp = requests.post(response_url,
+ json = {"text": text},
+ headers = {"Content-type": "application/json"})
+ if (resp.status_code != 200):
+ app.logger.error("Error posting request to Slack: " + resp.text)
+ else:
+ try:
+ slack_client.chat_postMessage(channel=channel, text=text)
+ except SlackApiError as e:
+ app.logger.error("Slack API error: " + e.response["error"])
#!/usr/bin/env python3
-from flask import Flask, request, make_response
-
+from flask import Flask
from slackeventsapi import SlackEventAdapter
-from slack import WebClient
-from slack.errors import SlackApiError
-from slack.signature import SignatureVerifier
import os
-import requests
-import re
+from turbot.rot import rot_route
app = Flask(__name__)
+app.register_blueprint(rot_route)
slack_signing_secret = os.environ['SLACK_SIGNING_SECRET']
-slack_bot_token = os.environ['SLACK_BOT_TOKEN']
-
slack_events = SlackEventAdapter(slack_signing_secret, "/slack/events", app)
-signature_verifier = SignatureVerifier(slack_signing_secret)
-slack_client = WebClient(slack_bot_token)
-
-def slack_is_valid_request(request):
- """Returns true if request actually came from Slack.
-
- By means of checking the requests signature together with the slack
- signing key.
-
- Note: If flask is in debug mode, this function will always return true."""
-
- if app.debug:
- return True
-
- data = request.get_data()
- headers = request.headers
-
- return signature_verifier.is_valid_request(data, headers)
-
-def slack_send_reply(request, text):
- """Send a Slack message as a reply to a specified request.
-
- If the request is associated with a direct message, the reply is
- made by using the "response_url" from the request. Otherwise, the
- reply will be sent to the channel associated with the request.
-
- Note: If flask is in debug mode, this function will just print the
- text to stdout."""
-
- channel_name = request.form.get('channel_name')
- response_url = request.form.get('response_url')
- channel = request.form.get('channel_id')
-
- if (app.debug):
- print("Sending message to channel '{}': {}".format(channel, text))
- return
-
- if (channel_name == "directmessage"):
- resp = requests.post(response_url,
- json = {"text": text},
- headers = {"Content-type": "application/json"})
- if (resp.status_code != 200):
- app.logger.error("Error posting request to Slack: " + resp.text)
- else:
- try:
- slack_client.chat_postMessage(channel=channel, text=text)
- except SlackApiError as e:
- app.logger.error("Slack API error: " + e.response["error"])
-
-def rot_string(str, n=13):
- """Return a rotated version of a string
-
- Specifically, this functions returns a version of the input string
- where each uppercase letter has been advanced 'n' positions in the
- alphabet (wrapping around). Lowercase letters and any non-alphabetic
- characters will be unchanged."""
-
- result = ''
- for letter in str:
- if letter.isupper():
- result += chr(ord("A") + (ord(letter) - ord("A") + n) % 26)
- else:
- result += letter
- return result
-
-@app.route('/rot', methods = ['POST'])
-def rot():
- """Implements the /rot route for the /rot slash command in Slack
-
- This implements the /rot command of our Slack bot. The format of this
- command is as follows:
-
- /rot [count|*] String to be rotated
-
- The optional count indicates an amount to rotate each character in the
- string. If the count is '*' or is not present, then the string will
- be rotated through all possible 25 values.
-
- The result of the rotation is provided as a message in Slack. If the
- slash command was issued in a direct message, the response is made by
- using the "response_url" from the request. This allows the bot to reply
- in a direct message that it is not a member of. Otherwise, if the slash
- command was issued in a channel, the bot will reply in that channel."""
-
- if not slack_is_valid_request(request):
- return make_response("invalid request", 403)
-
- query = request.form.get('text')
- match = re.match(r'^([0-9]+|\*) (.*)$', query)
- if (match):
- try:
- count = int(match.group(1))
- except ValueError:
- count = None
- text = match.group(2)
- else:
- count = None
- text = query
-
- text = text.upper()
-
- reply = "```/rot {} {}\n".format(count if count else '*', text)
-
- if count:
- reply += rot_string(text, count)
- else:
- reply += "\n".join(["{:02d} ".format(count) + rot_string(text, count)
- for count in range(1, 26)])
-
- reply += "```"
-
- slack_send_reply(request, reply)
-
- return ""
@slack_events.on("error")
def handle_error(error):