1
1
import os
2
+ import click
3
+ import requests
4
+ import json
2
5
from twilio .rest import Client
3
- from dotenv import load_dotenv
4
- load_dotenv ()
6
+ import dotenv
7
+ dotenv . load_dotenv ()
5
8
6
9
7
10
TWILIO_ACCOUNT_SID = os .getenv ("TWILIO_ACCOUNT_SID" )
8
11
TWILIO_AUTH_TOKEN = os .getenv ("TWILIO_AUTH_TOKEN" )
12
+ TWILIO_PHONE_NUMBER_SID = os .getenv ("TWILIO_PHONE_NUMBER_SID" )
13
+ TWILIO_AUTOPILOT_SID = os .getenv ("TWILIO_AUTOPILOT_SID" )
14
+
15
+ TRELLO_API_KEY = os .getenv ("TRELLO_API_KEY" )
16
+ TRELLO_TOKEN = os .getenv ("TRELLO_TOKEN" )
17
+
18
+ NGROK_URL = os .getenv ("NGROK_URL" )
19
+
20
+
21
+ @click .group ()
22
+ def cli ():
23
+ pass
24
+
25
+
26
+ @cli .command ()
27
+ @click .argument ("board_name" )
28
+ def deploy (board_name ):
29
+ """
30
+ Create all of the Trello board assets.
31
+ """
32
+ # Create Trello Board.
33
+ board = create_trello_board (board_name )
34
+ board_id = board ["id" ]
35
+ dotenv .set_key (".env" , "TRELLO_BOARD_ID" , board_id )
36
+
37
+ # Create Trello lists.
38
+ trello_lists = ["No Show" , "Cancellations" , "Completed" , "Table is Ready" , "Waitlist" ]
39
+ for l in trello_lists :
40
+ create_trello_list (l , board_id )
41
+
42
+ # Create the Trello labels.
43
+ trello_labels = [
44
+ {"label_name" : "FirstNudge" , "label_color" : "green" },
45
+ {"label_name" : "SecondNudge" , "label_color" : "yellow" },
46
+ {"label_name" : "FinalNudge" , "label_color" : "red" },
47
+ {"label_name" : "unverified" , "label_color" : "blue" }
48
+ ]
49
+ for lbl in trello_labels :
50
+ create_trello_label (** lbl , board_id = board_id )
51
+
52
+ # Create the custom fields.
53
+ trello_fields = ["name" , "phone_number" ]
54
+ for field in trello_fields :
55
+ create_custom_fields (field , board_id )
56
+
57
+ # Create the Twilio Studio Flow.
58
+ flow = create_studio_flow ()
59
+
60
+ # Add flow to the our phone number.
61
+ phone = update_phone_incoming_webhook (flow .webhook_url )
62
+
63
+
64
+ @cli .command ()
65
+ @click .argument ("ngrok_url" )
66
+ def update_autopilot_endpoints (ngrok_url ):
67
+ """
68
+ Replace the NGROK_URL placeholders in the Autopilot schema_template.json file with the valid ngrok URL.
69
+
70
+ Writes output to a file schema.json that can be used to create or update your Autopilot bot.
71
+ """
72
+ # Read the schema template.
73
+ schema_template = json .dumps (json .load (open ("schema_template.json" , "r" )))
74
+
75
+ # Replace the <NGROK_URL> occurrences.
76
+ new_schema = json .loads (schema_template .replace ("<NGROK_URL>" , ngrok_url ))
77
+
78
+ json .dump (new_schema , open ("schema.json" , "w" ))
79
+
80
+
81
+ def create_studio_flow ():
82
+ """
83
+ Reads the flow_template.json file and makes replacements in the template for the proper Autopilot SID
84
+ and the NGROK URL being used.
85
+
86
+ New definition is used to create the Twilio Studio Flow. If the Studio flow exists then the existing Flow
87
+ will be updated using the new Studio Flow template.
88
+ """
89
+ # Read and make replacements.
90
+ flow_def = json .dumps (json .load (open ("flow_template.json" , "r" ))).\
91
+ replace ("<AUTOPILOT_SID>" , TWILIO_AUTOPILOT_SID ).\
92
+ replace ("<NGROK_URL>" , NGROK_URL )
93
+
94
+ # Convert to a dictionary representation.
95
+ flow_def = json .loads (flow_def )
96
+
97
+ # Check if the Studio Flow already exists.
98
+ client = Client (TWILIO_ACCOUNT_SID , TWILIO_AUTH_TOKEN )
99
+ flow_sid = os .getenv ("TWILIO_FLOW_SID" )
100
+ if flow_sid == "" :
101
+ # Create the flow with the Twilio API.
102
+ flow = client .studio .flows .create (
103
+ commit_message = 'First draft' ,
104
+ friendly_name = 'mimosa' ,
105
+ status = 'published' ,
106
+ definition = flow_def )
107
+
108
+ # Write Flow SID to the environmental file.
109
+ dotenv .set_key (".env" , "TWILIO_FLOW_SID" , flow .sid )
110
+ else :
111
+ # Update the existing Studio Flow.
112
+ flow = client .studio .flows (flow_sid ).update (
113
+ commit_message = 'Push flow update.' ,
114
+ definition = flow_def
115
+ )
116
+
117
+ return flow
118
+
119
+
120
+ def update_phone_incoming_webhook (flow_webhook ):
121
+ """
122
+ Connects the Twilio Studio Flow to your Twilio phone number.
123
+ """
124
+ client = Client (TWILIO_ACCOUNT_SID , TWILIO_AUTH_TOKEN )
125
+ phone = client .incoming_phone_numbers (TWILIO_PHONE_NUMBER_SID ).\
126
+ update (
127
+ sms_url = flow_webhook
128
+ )
129
+
130
+ return phone
9
131
10
132
11
133
def create_sync_services ():
@@ -15,12 +137,113 @@ def create_sync_services():
15
137
client = Client (TWILIO_ACCOUNT_SID , TWILIO_AUTH_TOKEN )
16
138
17
139
# Create the sync service.
18
- service = client .sync .services .create ()
19
- service_id = service .sid
140
+ service = client .sync .services .create (friendly_name = 'mimosa' )
141
+ response = dotenv . set_key ( ".env" , "TWILIO_SYNC_SID" , service .sid )
20
142
21
143
# Create the Sync Map.
22
- sync_map = client .sync .services (service_id ) \
144
+ sync_map = client .sync .services (service . sid ) \
23
145
.sync_maps \
24
146
.create ()
25
147
26
- return service_id , sync_map .sid
148
+ response = dotenv .set_key (".env" , "TWILIO_SYNC_MAP_SID" , sync_map .sid )
149
+
150
+ return service .sid , sync_map .sid
151
+
152
+
153
+ def create_trello_board (board_name ):
154
+ """
155
+ Creates a blank Trello Board.
156
+ """
157
+ url = "https://api.trello.com/1/boards/"
158
+
159
+ query = {
160
+ 'key' : TRELLO_API_KEY ,
161
+ 'token' : TRELLO_TOKEN ,
162
+ 'name' : board_name ,
163
+ 'defaultLists' : "false" ,
164
+ 'defaultLabels' : "false"
165
+ }
166
+
167
+ response = requests .request (
168
+ "POST" ,
169
+ url ,
170
+ params = query
171
+ )
172
+
173
+ return json .loads (response .text )
174
+
175
+
176
+ def create_trello_label (label_name , label_color , board_id ):
177
+ """
178
+ Create a Trello label for the board.
179
+ """
180
+ url = "https://api.trello.com/1/labels"
181
+
182
+ query = {
183
+ 'key' : TRELLO_API_KEY ,
184
+ 'token' : TRELLO_TOKEN ,
185
+ 'name' : label_name ,
186
+ 'color' : label_color ,
187
+ 'idBoard' : board_id
188
+ }
189
+
190
+ response = requests .request (
191
+ "POST" ,
192
+ url ,
193
+ params = query
194
+ )
195
+
196
+ print (response .text )
197
+
198
+
199
+ def create_trello_list (list_name , board_id ):
200
+ url = "https://api.trello.com/1/lists"
201
+
202
+ query = {
203
+ 'key' : TRELLO_API_KEY ,
204
+ 'token' : TRELLO_TOKEN ,
205
+ 'name' : list_name ,
206
+ 'idBoard' : board_id
207
+ }
208
+
209
+ response = requests .request (
210
+ "POST" ,
211
+ url ,
212
+ params = query
213
+ )
214
+
215
+ print (response .text )
216
+
217
+
218
+ def create_custom_fields (field_name , board_id ):
219
+ """
220
+ """
221
+ url = "https://api.trello.com/1/customFields"
222
+
223
+ headers = {
224
+ "Accept" : "application/json"
225
+ }
226
+
227
+ query = {
228
+ 'key' : TRELLO_API_KEY ,
229
+ 'token' : TRELLO_TOKEN ,
230
+ 'idModel' : board_id ,
231
+ 'modelType' : 'board' ,
232
+ 'type' : 'text' ,
233
+ 'pos' : 1 ,
234
+ 'name' : field_name ,
235
+ 'display_cardFront' : 'false'
236
+ }
237
+
238
+ response = requests .request (
239
+ "POST" ,
240
+ url ,
241
+ headers = headers ,
242
+ params = query
243
+ )
244
+
245
+ print (response .text )
246
+
247
+
248
+ if __name__ == "__main__" :
249
+ cli ()
0 commit comments