Skip to content

Instantly share code, notes, and snippets.

@samclane
Created December 15, 2017 21:48
Show Gist options
  • Save samclane/ec46234d8fe3c8de3687f14b9605fb4b to your computer and use it in GitHub Desktop.
Save samclane/ec46234d8fe3c8de3687f14b9605fb4b to your computer and use it in GitHub Desktop.
import os
import time
from slackclient import SlackClient
import smartsheet
import re
from tkinter import *
# starterbot's ID as an environment variable
BOT_ID = os.environ.get("BOT_ID")
# smartsheet api access token
SMARTSHEET_API_TOKEN = os.environ.get("SMARTSHEET_ACCESS_TOKEN")
# defaulting to AF4000 feedback; can change later
DEFAULT_SHEET_LIST = [7916954825582468, 2811754464995204, 5065629116983172]
# regex for finding IDs
p = re.compile('.*#(\d*).*')
# constants
AT_BOT = "<@" + BOT_ID + ">"
# instantiate Slack client
slack_client = SlackClient(os.environ.get('SLACK_BOT_TOKEN'))
def initGUI():
root = Tk()
connection_text = StringVar()
connection_text.set("Disconnected")
connection_label = Label(root, textvariable=connection_text)
connection_label.pack()
Label(root, text="Smartsheet Row IDs:").pack()
smartsheet_list = Listbox(root)
for idx, sheetid in enumerate(DEFAULT_SHEET_LIST):
smartsheet_list.insert(idx, sheetid)
smartsheet_list.pack()
sheet_id_add = StringVar()
sheet_id_entry = Entry(root, textvariable=sheet_id_add)
sheet_id_entry.pack(side=LEFT)
add_sheet_button = Button(root, text="+", command=updateSmartSheetList)
add_sheet_button.pack(side=LEFT)
remove_sheet_button = Button(root, text="-", command=lambda smartsheet_list=smartsheet_list: smartsheet_list.delete(ANCHOR))
remove_sheet_button.pack(side=LEFT)
globals().update(locals()) # some real dirty stuff
def updateSmartSheetList():
smartsheet_list.insert(0, sheet_id_add.get())
sheet_list.append(ss.Sheets.get_sheet(sheet_id_add.get()))
print ("Loaded " + str(len(ss.Sheets.get_sheet(sheet_id_add.get()).rows)) + " rows from sheet: " + ss.Sheets.get_sheet(sheet_id_add.get()).name)
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.
"""
response = ""
m = p.match(command)
if m and len(m.group(1)) >= 8:
cell_id = int(m.group(1))
for sheet in sheet_list:
for row in sheet.rows:
if row.id == cell_id:
for cell in row.cells:
for col in sheet.columns:
if col.id == cell.column_id:
response += ("*" + str(col.title) + "*: " + str(cell.display_value)) + "\n"
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
def read_slack_firehose():
command, channel = parse_slack_output(slack_client.rtm_read())
if command and channel:
handle_command(command, channel)
root.after(READ_WEBSOCKET_DELAY, read_slack_firehose)
if __name__ == "__main__":
initGUI()
READ_WEBSOCKET_DELAY = 1 # 1 second delay between reading from firehose
if slack_client.rtm_connect():
print("sawyer-bot connected and running!")
connection_text.set("Connected")
# initialize smartsheet client
ss = smartsheet.Smartsheet(SMARTSHEET_API_TOKEN)
# make sure we don't miss any errors
ss.errors_as_exceptions(True)
# load sheet
sheet_list = []
for sheet_id in DEFAULT_SHEET_LIST:
sheet_list.append(ss.Sheets.get_sheet(sheet_id))
print ("Loaded " + str(len(ss.Sheets.get_sheet(sheet_id).rows)) + " rows from sheet: " + ss.Sheets.get_sheet(sheet_id).name)
root.after(0, read_slack_firehose)
root.mainloop()
else:
print("Connection failed. Invalid Slack token or bot ID?")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment