Skip to content

Instantly share code, notes, and snippets.

@crioux
Last active July 7, 2019 18:13
Show Gist options
  • Save crioux/c4a05aca3aa09ca9e0e01233cda3640b to your computer and use it in GitHub Desktop.
Save crioux/c4a05aca3aa09ca9e0e01233cda3640b to your computer and use it in GitHub Desktop.
Plorp Slack Bot
import random
import logging
from slack_tools import conversationsMembers, usersInfo
def command_random(args, channel):
"""Random: Print the list of users in a channel in a random order
"""
resp = conversationsMembers(channel)
logging.warn("response: "+str(resp))
if "ok" not in resp or not resp["ok"]:
return "Can't get member list"
if "response_metadata" in resp and \
"next_cursor" in resp["response_metadata"] and \
resp["response_metadata"]["next_cursor"]!="":
return "Too many members"
members = resp["members"]
random.shuffle(members)
outstr = "Ordering:\n "
for m in members:
userinfo = usersInfo(m)
if "ok" not in userinfo or not userinfo["ok"]:
continue
if "is_bot" in userinfo["user"] and userinfo["user"]["is_bot"]:
continue
if "is_app_user" in userinfo["user"] and userinfo["user"]["is_app_user"]:
continue
usertag = "<@"+m+">"
outstr += " "+usertag+"\n"
logging.warn("output string: " + outstr)
return outstr
"""
PLORP SLACK BOT
"""
import os
import logging
import urllib.parse
import urllib.request
from slack_tools import postMessage
from command_random import command_random
def run_command(cmd, channel):
"""Parse a plorp command
"""
parts = cmd.split(None, 1)
if parts[0] == "random" and channel:
return command_random(parts[1] if len(parts)>=2 else "", channel)
return "plorp"
def handle_message(text):
"""Handle a message.im event
"""
return run_command(text, None)
def handle_mention(text, users, channel):
"""Handle a app_mention event
"""
# ensure this is a prefix mention
text = text.strip()
for user in users:
usertag = "<@"+user+">"
if text.startswith(usertag):
cmd = text[len(usertag):].strip()
# If we have a prefix mention, run the command
return run_command(cmd, channel)
return None
def lambda_handler(data, context):
"""Handle an incoming HTTP request from a Slack chat-bot.
"""
if "challenge" in data:
return data["challenge"]
# Grab the Slack event data.
slack_event = data['event']
# Get the ID of the channel where the message was posted.
channel_id = slack_event["channel"] if "channel" in slack_event else None
# We need to discriminate between events generated by
# the users, which we want to process and handle,
# and those generated by the bot.
if "bot_id" in slack_event:
logging.warn("Ignore bot event")
return "200 OK"
# Respond to messages
output = None
if slack_event["type"].startswith("message"):
# if there is no subtype it's a normal message
if "subtype" not in slack_event:
# Let's see what our command is
output = handle_message(slack_event["text"])
if slack_event["type"]=="app_mention":
# Let's see what our command is
output = handle_mention(slack_event["text"], data["authed_users"], channel_id)
if not output:
logging.warn("Ignore non plorp message")
return "200 OK"
return postMessage(channel_id, output)
{
"swagger": "2.0",
"info": {
"version": "2019-04-26T17:31:02Z",
"title": "plorp"
},
"host": "g3qrsciaae.execute-api.us-east-1.amazonaws.com",
"basePath": "/release",
"schemes": [
"https"
],
"paths": {
"/event-handler": {
"post": {
"produces": [
"application/json"
],
"responses": {
"200": {
"description": "200 response",
"schema": {
"$ref": "#/definitions/Empty"
}
}
},
"x-amazon-apigateway-integration": {
"uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:678462872127:function:handleBotEvent/invocations",
"responses": {
"default": {
"statusCode": "200"
}
},
"passthroughBehavior": "when_no_match",
"httpMethod": "POST",
"contentHandling": "CONVERT_TO_TEXT",
"type": "aws"
}
}
}
},
"definitions": {
"Empty": {
"type": "object",
"title": "Empty Schema"
}
}
}
"""
PLORP SLACK TOOLS
"""
import os
import logging
import urllib.parse
import urllib.request
import json
# Grab the Bot OAuth token from the environment.
BOT_TOKEN = os.environ["BOT_TOKEN"]
# Define the URL of the targeted Slack API resource.
POSTMESSAGE_URL = "https://slack.com/api/chat.postMessage"
CONVERSATIONS_MEMBERS_URL = "https://slack.com/api/conversations.members"
USERS_INFO_URL = "https://slack.com/api/users.info"
def postMessage(channel_id, output):
# Respond to slack API
data = urllib.parse.urlencode(
(
("token", BOT_TOKEN),
("channel", channel_id),
("text", output)
)
)
data = data.encode("ascii")
# Construct the HTTP request that will be sent to the Slack API.
request = urllib.request.Request(
POSTMESSAGE_URL,
data=data,
method="POST"
)
# Add a header mentioning that the text is URL-encoded.
request.add_header(
"Content-Type",
"application/x-www-form-urlencoded"
)
# Fire off the request!
logging.warn("request: "+str(request))
urllib.request.urlopen(request).read()
# Everything went fine.
return "200 OK"
def conversationsMembers(channel_id):
# Respond to slack API
data = urllib.parse.urlencode(
(
("token", BOT_TOKEN),
("channel", channel_id)
)
)
# Construct the HTTP request that will be sent to the Slack API.
request = urllib.request.Request(
CONVERSATIONS_MEMBERS_URL + "?" + data,
method="GET"
)
# Fire off the request!
retjson = urllib.request.urlopen(request).read()
return json.loads(retjson)
def usersInfo(user_id):
# Respond to slack API
data = urllib.parse.urlencode(
(
("token", BOT_TOKEN),
("user", user_id)
)
)
# Construct the HTTP request that will be sent to the Slack API.
request = urllib.request.Request(
USERS_INFO_URL + "?" + data,
method="GET"
)
# Fire off the request!
retjson = urllib.request.urlopen(request).read()
return json.loads(retjson)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment