-
Notifications
You must be signed in to change notification settings - Fork 2
/
bot.py
157 lines (128 loc) · 5.5 KB
/
bot.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import time
from slackclient import SlackClient
import re
import os
from dotenv import load_dotenv
load_dotenv('./.env')
# loggbot's ID as an environment variable
BOT_ID = os.getenv("BOT_ID")
BOT_ID = ''
# constants
AT_BOT = "<@" + BOT_ID + ">"
slack_client = SlackClient(os.getenv("SLACK_ID"))
def append_to_json(text, channel, user):
date = time.strftime("%c")
import json
a_dict = {"user": user, "date": date, "text": text}
data = []
try:
with open('logs/' + channel + '.json') as f:
data = json.load(f)
except IOError:
pass
data.append(a_dict)
with open('logs/' + channel + '.json', 'w') as f:
json.dump(data, f)
def replace_usernames(line):
regex=re.compile(r"<+@+[\w\.-]+>")
occurences=regex.findall(line)
for user in occurences:
try:
user_info = slack_client.api_call("users.info", user=user.replace("<@","").replace(">","")) #so lazy
line=line.replace(user, "@"+user_info['user']['name'])
except:
print("user not found")
return line
def handle_command(command, channel, user, ts):
"""
Receives commands directed at the bot and determines if they
are valid commands. If so, then acts on the commands.
Retrieves some more info from the API if needed.
"""
# Help menu
if command == "?":
web_url = os.getenv("WEB_URL")
if web_url == "":
web_url = "Not set in config"
print(" * Warning: Web URL not set in config.")
# Alright, so we need some kind of a help menu or something.
slack_client.api_call("chat.postMessage", channel=channel,
text="Uhm.. Hei! Okei, dette er enkelt. Alt du trenger gjore er: Tagg meg (@logg) med "
"noe du vil legge i loggen. \n\nF.eks. slik: '@logg Opprettet nye tilganger til "
"Jens fra nedi gata, det var enkelt.'. \nKanskje litt annereledes, men du "
"skjonner tegninga da! \n\nEtterhvert som man logger ting kan loggene leses i "
"nettleseren din her: \n{0}. \n\nLykke til!".format(web_url),
as_user=True)
else:
slack_client.api_call("reactions.add", channel=channel, name="thinking_face", timestamp=ts, as_user=True)
# Create the log stuff
channel_info = slack_client.api_call("channels.info", channel=channel)
user_info = slack_client.api_call("users.info", user=user)
try:
channel_name = channel_info['channel']['name']
except:
private_info = slack_client.api_call("groups.info", channel=channel)
try:
channel_name = private_info['group']['name']
except:
channel_name = channel
try:
user_nick = user_info['user']['name']
except:
user_nick = user
try:
real_name = user_info['user']['profile']['real_name']
except:
real_name = None
if real_name is not None:
user_nick = real_name + " (" + user_nick + ")"
append_to_json(replace_usernames(command), channel_name, user_nick)
# React to the post with the log stuff.
slack_client.api_call("reactions.add", channel=channel, name="memo", timestamp=ts, as_user=True)
slack_client.api_call("reactions.remove", channel=channel, name="thinking_face", timestamp=ts, 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
try:
return output['text'].split(AT_BOT)[1].strip(), \
output['channel'], \
output['user'], \
output['ts']
except:
# Magical thing we fixed via mobile ssh at the crewparty. Needs to be here aswell.
print("[ERROR] Failed to return slack output from function due to invalid response.")
return None, None, None, None
def start_bot():
global BOT_ID, AT_BOT
READ_WEBSOCKET_DELAY = 1 # 1 second delay between reading from firehose
if slack_client.rtm_connect():
print(" * LoggBot is connected to Slack and running!")
if not BOT_ID:
print(" * BOT_ID not set, fetching from slack api")
BOT_ID = slack_client.api_call("auth.test")['user_id']
AT_BOT = "<@" + BOT_ID + ">"
print(" * BOT_ID set to " + BOT_ID)
while True:
command, channel, user, ts = parse_slack_output(slack_client.rtm_read())
# username = request.form.get('user_name')
if command and channel:
handle_command(command, channel, user, ts)
time.sleep(READ_WEBSOCKET_DELAY)
# print(slack_client.rtm_read())
else:
print("Connection failed. Invalid Slack token or bot ID?")
def stop_bot(self):
print("Trying to stop thread")
if self.process is not None:
self.process.terminate()
self.process = None
if __name__ == '__main__':
start_bot()