-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbot.py
129 lines (101 loc) · 3.69 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
import re
import logging
import time
import os
from dataclasses import dataclass
from typing import Optional, Dict, Iterable
from dotenv import load_dotenv
from slackclient import SlackClient
EventMapping = Dict[str, str]
logger = logging.getLogger(__name__)
load_dotenv()
SLACK_BOT_TOKEN = os.environ.get('SLACK_BOT_TOKEN')
SLACK_BOT_OAUTH = os.environ.get('SLACK_BOT_OAUTH')
slack_client = SlackClient(SLACK_BOT_OAUTH)
bot_id = None
STANDUP_CHANNELS = {}
@dataclass
class Command:
validator = None
input: str
channel: str
@classmethod
def recognize(cls, event: EventMapping) -> bool:
return len(re.findall(re.compile(cls.validator), event['text'])) > 0
def do(self) -> None:
raise NotImplementedError()
class HelpCommand(Command):
validator = 'help'
def do(self) -> None:
slack_client.api_call(
"chat.postMessage",
channel=self.channel,
text="""
Here are some things I can do:
- type help to see this message
- type "Standup for: <comma separated members list>" to start recording the standup
"""
)
class StartStandupCommand(Command):
validator = '^Standup for:'
def do(self) -> None:
groups = re.findall(re.compile('(?P<names>[a-z0-9\.]*@[a-z\.]*)'), self.input)
members = slack_client.api_call("users.list")['members']
members = [(m['id'], m['profile'].get('email')) for m in members if m['profile'].get('email') in groups]
for id_, email in members:
channel_id = slack_client.api_call(
"conversations.open",
users=[id_]
)['channel']['id']
slack_client.api_call(
"chat.postMessage",
channel=channel_id,
text="""
Hey! It's standup time! Please answer:
1. What are you working on?
2. Do you encounter any problems?
3. What are your plans for later?
"""
)
STANDUP_CHANNELS[channel_id] = {'origin': self.channel, 'author': email, 'response': []}
slack_client.api_call(
"chat.postMessage",
channel=self.channel,
text=f"Be right back! Gathering feedback from {', '.join([m[1] for m in members])}"
)
class RespondStandupCommand(Command):
@classmethod
def recognize(cls, event: EventMapping) -> bool:
return event['channel'] in STANDUP_CHANNELS
def do(self) -> None:
data = STANDUP_CHANNELS.pop(self.channel)
slack_client.api_call(
"chat.postMessage",
channel=data['origin'],
text=f"""
Here is the standup from {data['author']}
{self.input}
"""
)
ALLOWED_COMMANDS = [
HelpCommand,
StartStandupCommand,
RespondStandupCommand
]
def parse_slack_incoming(incoming: Iterable[EventMapping]) -> Optional[Command]:
for event in incoming:
if event['type'] == 'message' and not 'subtype' in event:
for command in ALLOWED_COMMANDS:
if command.recognize(event):
return command(input=event['text'], channel=event['channel'])
if __name__ == '__main__':
if slack_client.rtm_connect(with_team_state=False):
logger.info("StandupBot connected and ready to work!")
bot_id = slack_client.api_call("auth.test")["user_id"]
while True:
command = parse_slack_incoming(slack_client.rtm_read())
if command:
command.do()
time.sleep(1)
else:
logger.error("Something went wrong. Exception traceback printed aboce.")