Initial commit
This commit is contained in:
Родитель
c228bd26cd
Коммит
719a8d9c84
|
@ -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.
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
slack_api_token: NOT_SET
|
||||||
|
pagerduty_api_token: NOT_SET
|
||||||
|
pagerduty_oncall_schedule: NOT_SET
|
|
@ -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.")
|
||||||
|
|
|
@ -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
|
Загрузка…
Ссылка в новой задаче