This commit is contained in:
Dave Miller 2018-10-10 19:02:57 -04:00
Родитель c228bd26cd
Коммит 719a8d9c84
5 изменённых файлов: 119 добавлений и 1 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -24,6 +24,7 @@ wheels/
.installed.cfg .installed.cfg
*.egg *.egg
MANIFEST MANIFEST
config.yml
# PyInstaller # PyInstaller
# Usually these files are written by a python script from a template # Usually these files are written by a python script from a template

Просмотреть файл

@ -1 +1,5 @@
# netops-slackbot # netops-slackbot
This code is loosely based on https://github.com/mattmakai/slack-starterbot and
code the Mozilla Operations Center was already using to interact with
PagerDuty.

3
config.yml.dist Normal file
Просмотреть файл

@ -0,0 +1,3 @@
slack_api_token: NOT_SET
pagerduty_api_token: NOT_SET
pagerduty_oncall_schedule: NOT_SET

103
netops-slackbot.py Executable file
Просмотреть файл

@ -0,0 +1,103 @@
import os
import time
import re
from slackclient import SlackClient
import yaml
with open("config.yml", 'r') as ymlfile:
cfg = yaml.load(ymlfile)
# instantiate Slack client
slack_client = SlackClient(cfg['slack_api_token'])
# starterbot's user ID in Slack: value is assigned after the bot starts up
starterbot_id = None
# constants
RTM_READ_DELAY = 1 # 1 second delay between reading from RTM
EXAMPLE_COMMAND = "do"
MENTION_REGEX = "^<@(|[WU].+?)>(.*)"
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):
"""
Executes bot command if the command is known
"""
# 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!"
if command.startswith("oncall"):
attachments = json.dumps([{
"color": "#36a64f",
"pretext": "The current oncall network engineer is:",
"title": cfg["demo_user"]["name"],
"fields": [{
"title": "IRC",
"value": cfg["demo_user"]["irc"],
"short": "true"
},
{
"title": "Slack",
"value": cfg["demo_user"]["slack"],
"short": "true"
},
{
"title": "Email",
"value": cfg["demo_user"]["email"],
"short": "true"
}],
"thumb_url": cfg["demo_user"]["avatar"]
}]
slack_client.api_call(
"chat.postMessage",
channel = channel,
attachments = attachments)
return
# Sends the response back to the channel
slack_client.api_call(
"chat.postMessage",
channel=channel,
text=response or default_response
)
if __name__ == "__main__":
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_bot_commands(slack_client.rtm_read())
if command:
handle_command(command, channel)
time.sleep(RTM_READ_DELAY)
else:
print("Connection failed. Exception traceback printed above.")

7
requirements.txt Normal file
Просмотреть файл

@ -0,0 +1,7 @@
requests==2.11.1
simplejson==3.10.0
DateTime==4.3
slackclient==1.3.0
websocket-client==0.53.0
zope.interface==4.5.0
yaml