-
Notifications
You must be signed in to change notification settings - Fork 147
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
updates code to reflect changes in mattmakai/fullstackpython.com#145
- Loading branch information
Showing
3 changed files
with
49 additions
and
55 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
slackclient==1.0.0 | ||
slackclient>=1.1.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,57 +1,70 @@ | ||
import os | ||
import time | ||
import re | ||
from slackclient import SlackClient | ||
|
||
|
||
# starterbot's ID as an environment variable | ||
BOT_ID = os.environ.get("BOT_ID") | ||
# instantiate Slack client | ||
slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN')) | ||
# starterbot's user ID in Slack: value is assigned after the bot starts up | ||
starterbot_id = None | ||
|
||
# constants | ||
AT_BOT = "<@" + BOT_ID + ">" | ||
RTM_READ_DELAY = 1 # 1 second delay between reading from RTM | ||
EXAMPLE_COMMAND = "do" | ||
MENTION_REGEX = "^<@(|[WU].+)>(.*)" | ||
|
||
# instantiate Slack & Twilio clients | ||
slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN')) | ||
def parse_bot_commands(slack_events): | ||
""" | ||
Parses a list of events coming from the Slack RTM API to find bot commands. | ||
If a bot command is found, this function returns a tuple of command and channel. | ||
If its not found, then this function returns None, None. | ||
""" | ||
for event in slack_events: | ||
if event["type"] == "message" and not "subtype" in event: | ||
user_id, message = parse_direct_mention(event["text"]) | ||
if user_id == starterbot_id: | ||
return message, event["channel"] | ||
return None, None | ||
|
||
def parse_direct_mention(message_text): | ||
""" | ||
Finds a direct mention (a mention that is at the beginning) in message text | ||
and returns the user ID which was mentioned. If there is no direct mention, returns None | ||
""" | ||
matches = re.search(MENTION_REGEX, message_text) | ||
# the first group contains the username, the second group contains the remaining message | ||
return (matches.group(1), matches.group(2).strip()) if matches else (None, None) | ||
|
||
def handle_command(command, channel): | ||
""" | ||
Receives commands directed at the bot and determines if they | ||
are valid commands. If so, then acts on the commands. If not, | ||
returns back what it needs for clarification. | ||
Executes bot command if the command is known | ||
""" | ||
response = "Not sure what you mean. Use the *" + EXAMPLE_COMMAND + \ | ||
"* command with numbers, delimited by spaces." | ||
# Default response is help text for the user | ||
default_response = "Not sure what you mean. Try *{}*.".format(EXAMPLE_COMMAND) | ||
|
||
# Finds and executes the given command, filling in response | ||
response = None | ||
# This is where you start to implement more commands! | ||
if command.startswith(EXAMPLE_COMMAND): | ||
response = "Sure...write some more code then I can do that!" | ||
slack_client.api_call("chat.postMessage", channel=channel, | ||
text=response, as_user=True) | ||
|
||
|
||
def parse_slack_output(slack_rtm_output): | ||
""" | ||
The Slack Real Time Messaging API is an events firehose. | ||
this parsing function returns None unless a message is | ||
directed at the Bot, based on its ID. | ||
""" | ||
output_list = slack_rtm_output | ||
if output_list and len(output_list) > 0: | ||
for output in output_list: | ||
if output and 'text' in output and AT_BOT in output['text']: | ||
# return text after the @ mention, whitespace removed | ||
return output['text'].split(AT_BOT)[1].strip().lower(), \ | ||
output['channel'] | ||
return None, None | ||
|
||
# Sends the response back to the channel | ||
slack_client.api_call( | ||
"chat.postMessage", | ||
channel=channel, | ||
text=response or default_response | ||
) | ||
|
||
if __name__ == "__main__": | ||
READ_WEBSOCKET_DELAY = 1 # 1 second delay between reading from firehose | ||
if slack_client.rtm_connect(): | ||
print("StarterBot connected and running!") | ||
if slack_client.rtm_connect(with_team_state=False): | ||
print("Starter Bot connected and running!") | ||
# Read bot's user ID by calling Web API method `auth.test` | ||
starterbot_id = slack_client.api_call("auth.test")["user_id"] | ||
while True: | ||
command, channel = parse_slack_output(slack_client.rtm_read()) | ||
if command and channel: | ||
command, channel = parse_bot_commands(slack_client.rtm_read()) | ||
if command: | ||
handle_command(command, channel) | ||
time.sleep(READ_WEBSOCKET_DELAY) | ||
time.sleep(RTM_READ_DELAY) | ||
else: | ||
print("Connection failed. Invalid Slack token or bot ID?") | ||
print("Connection failed. Exception traceback printed above.") |