]> git.cworth.org Git - turbot/blob - turbot/interaction.py
Combine actions.py and commands.py into interaction.py
[turbot] / turbot / interaction.py
1 from turbot.blocks import input_block
2 import turbot.sheets
3 import json
4 import re
5 import requests
6 import turbot.rot
7
8 def new_hunt(turb, payload):
9     """Handler for the action of user pressing the new_hunt button"""
10
11     view = {
12         "type": "modal",
13         "private_metadata": "new_hunt",
14         "title": { "type": "plain_text", "text": "New Hunt" },
15         "submit": { "type": "plain_text", "text": "Create" },
16         "blocks": [
17             input_block("Hunt name", "name", "Name of the hunt"),
18             input_block("Hunt ID", "hunt_id",
19                         "Used as puzzle channel prefix "
20                         + "(no spaces nor punctuation)"),
21             input_block("Hunt URL", "url", "External URL of hunt",
22                         optional=True)
23         ],
24     }
25
26     result = turb.slack_client.views_open(trigger_id=payload['trigger_id'],
27                                           view=view)
28     if (result['ok']):
29         submission_handlers[result['view']['id']] = new_hunt_submission
30
31     return {
32         'statusCode': 200,
33         'body': 'OK'
34     }
35
36 def new_hunt_submission(turb, payload):
37     """Handler for the user submitting the new hunt modal
38
39     This is the modal view presented to the user by the new_hunt
40     function above."""
41
42     state = payload['view']['state']['values']
43     name = state['name']['name']['value']
44     hunt_id = state['hunt_id']['hunt_id']['value']
45     url = state['url']['url']['value']
46
47     # Validate that the hunt_id contains no invalid characters
48     if not re.match(r'[_a-zA-Z0-9]+$', hunt_id):
49         print("Hunt ID field is invalid. Attmpting to return a clean error.")
50         return {
51             'statusCode': 200,
52             'headers': {
53                 "Content-Type": "application/json"
54             },
55             'body': json.dumps({
56                 "response_action": "errors",
57                 "errors": {
58                     "hunt_id": "Hunt ID can only contain letters, "
59                     + "numbers, and underscores"
60                 }
61             })
62         }
63
64     # Create a channel for the hunt
65     response = turb.slack_client.conversations_create(name=hunt_id)
66
67     if not response['ok']:
68         print("Error creating channel for hunt {}: {}"
69               .format(name, str(response)))
70         return {
71             'statusCode': 400
72         }
73
74     user_id = payload['user']['id']
75     channel_id = response['channel']['id']
76
77     # Create a sheet for the channel
78     sheet = turbot.sheets.sheets_create(turb, hunt_id)
79
80     # Insert the newly-created hunt into the database
81     hunts_table = turb.db.Table("hunts")
82     hunts_table.put_item(
83         Item={
84             'channel_id': channel_id,
85             "active": True,
86             "name": name,
87             "hunt_id": hunt_id,
88             "url": url,
89             "sheet_url": sheet['url']
90         }
91     )
92
93     # Invite the initiating user to the channel
94     turb.slack_client.conversations_invite(channel=channel_id, users=user_id)
95
96     # Message the channel with the URL of the sheet
97     turb.slack_client.chat_postMessage(channel=channel_id,
98                                        text="Sheet created for this hunt: {}"
99                                        .format(sheet['url']))
100
101     return {
102         'statusCode': 200,
103     }
104
105 def view_submission(turb, payload):
106     """Handler for Slack interactive view submission
107
108     Specifically, those that have a payload type of 'view_submission'"""
109
110     view_id = payload['view']['private_metadata']
111
112     if view_id in submission_handlers:
113         return submission_handlers[view_id](turb, payload)
114
115     print("Error: Unknown view ID: {}".format(view_id))
116     return {
117         'statusCode': 400
118     }
119
120 def rot(turb, body, args):
121     """Implementation of the /rot command
122
123     The args string should be as follows:
124
125         [count|*] String to be rotated
126
127     That is, the first word of the string is an optional number (or
128     the character '*'). If this is a number it indicates an amount to
129     rotate each character in the string. If the count is '*' or is not
130     present, then the string will be rotated through all possible 25
131     values.
132
133     The result of the rotation is returned (with Slack formatting) in
134     the body of the response so that Slack will provide it as a reply
135     to the user who submitted the slash command."""
136
137     channel_name = body['channel_name'][0]
138     response_url = body['response_url'][0]
139     channel_id = body['channel_id'][0]
140
141     result = turbot.rot.rot(args)
142
143     if (channel_name == "directmessage"):
144         requests.post(response_url,
145                       json = {"text": result},
146                       headers = {"Content-type": "application/json"})
147     else:
148         turb.slack_client.chat_postMessage(channel=channel_id, text=result)
149
150     return {
151         'statusCode': 200,
152         'body': ""
153     }
154
155 actions = {
156     "button": {
157         "new_hunt": new_hunt
158     }
159 }
160
161 commands = {
162     "/rot": rot
163 }