-
Notifications
You must be signed in to change notification settings - Fork 0
/
slackoverflow.py
105 lines (92 loc) · 3.47 KB
/
slackoverflow.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import os
import time
from slackclient import SlackClient
import requests
import subprocess
from webScraper import StackoverflowWebScraper
# instantiate Slack client
slack_client = SlackClient(os.environ["SLACK_API_TOKEN"])
# starterbot's user ID in Slack: value is assigned after the bot starts up
bot_id = None
# instantiate scraper
web_scraper = StackoverflowWebScraper()
# constants
RTM_READ_DELAY = 1 # 1 second delay between reading from RTM
CHARACTER_LIMIT = 200 # character limit for the response.
def reply_thread(thread_ts, channel, response):
title, link, text = response
slack_client.api_call(
"chat.postMessage",
channel=channel,
attachments=[
{
"title": title,
"pretext": link,
"text": text,
"mrkdwn_in": ["text"]
}
],
thread_ts=thread_ts
)
def post_to_channel(channel, response):
title, link, text = response
slack_client.api_call(
"chat.postMessage",
channel=channel,
attachments= [
{
"title": title,
"pretext": link,
"text": text,
"mrkdwn_in": ["text"]
}
]
)
def parse_events(slack_events):
for event in slack_events:
# TODO: Make sure that we at least take care of the obvious edge cases.
if event["type"] == "message":
if "subtype" in event:
# Ignore bot messages
if event["subtype"] == "bot_message":
return
if "text" in event:
message = event["text"]
# If DMing bot
if event["channel"][0] == "D":
response = generate_answer(message, True)
post_to_channel(event["channel"], response)
# If mentioning bot
elif bot_id in message:
message = message.replace("<@{0}>".format(bot_id), "")
response = generate_answer(message, False)
reply_thread(event["ts"], event["channel"], response)
def html_mrkdwn(text):
text = text.replace('<p>', '').replace('</p>', '')
text = text.replace('<b>', '*').replace('</b>', '*')
text = text.replace('<code>', '`').replace('</code>', '`')
text = text.replace('<pre>', '```').replace('</pre>', '```')
text = text.replace('<em>', '_').replace('</em>', '_')
text = text.replace('<strong>', '*').replace('</strong>', '*')
text = text.replace('````', '```')
return text
def generate_answer(message, dm=False):
char_limit = CHARACTER_LIMIT * 3 if dm else CHARACTER_LIMIT
question = web_scraper.get_top_question(message)
response = (
"404", "404", "Couldn't find a matching question on stackoverflow. Try rephrasing your question.")
if question is not None:
answer = web_scraper.get_top_answer(question["question_id"])
response = (question["title"], question["link"],
html_mrkdwn(answer["body"]))
return response
if __name__ == "__main__":
if slack_client.rtm_connect(with_team_state=False):
print("Slack is Overflowing")
# Read bot's user ID by calling Web API method `auth.test`
bot_id = slack_client.api_call("auth.test")["user_id"]
while True:
parse_events(slack_client.rtm_read())
time.sleep(RTM_READ_DELAY)
else:
print("Connection failed. Exception traceback printed above.")