-
Notifications
You must be signed in to change notification settings - Fork 1
/
bot.js
291 lines (239 loc) · 11.4 KB
/
bot.js
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
var RtmClient = require('@slack/client').RtmClient;
var CLIENT_EVENTS = require('@slack/client').CLIENT_EVENTS;
var RTM_EVENTS = require('@slack/client').RTM_EVENTS;
var pizzapi = require('dominos');
var validateAddress = require('./geocode').validateAddress
var findNearby = require('./index').findNearby
var bestMatch = require('./findBestMatches').findBestMatches
console.log('@slack/client', require('@slack/client'));
var bot_token = process.env.SLACK_BOT_TOKEN;
var rtm = new RtmClient(bot_token);
// mongoose setup
var mongoose = require('mongoose')
mongoose.connection.on('error', function() {
console.log('Oh no! Could not connect to database.')
})
mongoose.connection.on('connected', function() {
console.log('Yay! Connected to database in bot.js')
})
mongoose.connect(process.env.MONGODB_URI)
var models = require('./models/models')
var Order = models.Order
var PaymentPage = models.PaymentPage
// api.ai setup
var apiai = require('apiai');
var app = apiai(process.env.APIAI_CLI);
// email and phone extractors
var extractor = require('phone-number-extractor');
var connected = false
var address = false
var name = false
var email = false
var order = false
var payment = false
var phone = false
var delivery = false
var placeOrder = false
var confirmation = false
var begin = false
var next = false
var customer = {};
var orderObj = {};
var deliveryMethod;
var myStore;
var userIDObj = {};
var route;
var foodCodeArr = [];
var foodNameArr = [];
var botParams = {'address': false, 'category': false, 'email': false, delivery: false, 'phone': false, 'type': false} // address (gmaps), category (pizza, pasta, salads, wings), email, full name, phone #, size, type a.k.a descriptors
var lastPrompt = 'email'; // the last key the bot prompted for
// The client will emit an RTM.AUTHENTICATED event on successful connection, with the `rtm.start` payload
rtm.on(CLIENT_EVENTS.RTM.AUTHENTICATED, (rtmStartData) => {
buildDM(rtmStartData.ims)
for (const c of rtmStartData.channels.concat(rtmStartData.ims)) {
if (c.is_member && c.name ==='test') { route = c.id }
}
console.log(`Logged in as ${rtmStartData.self.name} of team ${rtmStartData.team.name}, but not yet connected to a route`);
});
rtm.on(RTM_EVENTS.MESSAGE, function(response) {
if (response.type !== 'message' || response.user === 'U677DRHT5') return; // response.user === bot's id
dealWithCustomer(response)
});
// you need to wait for the client to fully connect before you can send messages
rtm.on(CLIENT_EVENTS.RTM.RTM_CONNECTION_OPENED, function () {
console.log('client', CLIENT_EVENTS);
rtm.sendMessage("*Here I am, fam!*", route);
connected = true
});
function dealWithCustomer(response) {
console.log(response);
if (response.text.toLowerCase().indexOf('pizza') >= 0 && connected) {
route = userIDObj[response.user]
Order.find({ slackId: response.user }, function(err, foundUser) {
if (err) {
console.log('error in error');
} else {
if (foundUser.length === 0) {
var apiAI = new Promise(function(resolve, reject) {
var request = app.textRequest(response.text, {
sessionId: '123456789',
resetContexts: true
});
request.on('response', function(response) {
// console.log(response.result.parameters);
resolve(response.result.parameters)
});
request.on('error', function(error) {
console.log('error in promise reject');
reject(error)
});
request.end();
})
apiAI.then(function(response) {
// methods that checks which response fields are empty, and sets booleans that are later executed (or not)
for (var key in botParams) {
if (response[key]) {
botParams[key] = response[key];
}
}
rtm.sendMessage('What is your email?', route)
return null
}).catch(function(err) {
console.log('ERROR IN APIAI', err)
})
next = true
email = true
console.log('bottom of APIAI');
return null
} else {
rtm.sendMessage('These are your order details from last time you ordered: ', route)
rtm.sendMessage('*Address:* ' + foundUser[0].orderObj.customer.address.Street + ' ' + foundUser[0].orderObj.customer.address.City + ' ' + foundUser[0].orderObj.customer.address.PostalCode, route)
rtm.sendMessage('*Email:* ' + foundUser[0].orderObj.customer.email + ' *Phone:* ' + foundUser[0].orderObj.customer.phone, route)
rtm.sendMessage('*Order:* ' + foundUser[0].foodNameArr[0] + ' *Delivery Method:* ' + foundUser[0].orderObj.deliveryMethod, route)
rtm.sendMessage('*Would you like to make this order again?*', route)
orderObj = foundUser[0].orderObj
codeArr = foundUser[0].codeArr[0]
foodNameArr = foundUser[0].foodNameArr[0]
begin = false
connected = false
next = false
}
}
})
} else if (next) {
if (! botParams.address) {
var firstDex = response.text.indexOf(':');
var lastDex = response.text.indexOf('|');
botParams[lastPrompt] = response.text.substring(firstDex + 1, lastDex);
var addRes = ['Where should I deliver?', 'Where do you want it delivered?', 'Where ya at?'][Math.floor(Math.random() * 2)]
botParams.address = true;
lastPrompt = 'address'
rtm.sendMessage(addRes, route)
} else if (! botParams.category) {
botParams[lastPrompt] = response.text
var ordRes = ['What are you feeling?', 'What makes you hungry?'][Math.floor(Math.random() * 2)]
lastPrompt = 'category'
botParams.type = true
botParams.category = true
rtm.sendMessage(ordRes, route)
} else if (! botParams.delivery) {
botParams[lastPrompt] = response.text
var delRes = ['Would you like this delivered or would you like to pick it up in person?', 'Will you be eating this at home or in store?'][0]
lastPrompt = 'delivery'
botParams.delivery = true
rtm.sendMessage(delRes, route)
} else if (! botParams.phone) {
botParams[lastPrompt] = response.text
var phoneRes = ['What is your number?', 'What are your digits?', 'What number can I holla at you with?'][Math.floor(Math.random() * 3)]
lastPrompt = 'phone'
botParams.phone = true;
rtm.sendMessage(phoneRes, route)
} else {
extractor.getCandidates(response.text, "US")
.then(function(res){
console.log(res);
botParams.phone = parseInt(res); // [ '0254123123' ]
})
.catch(function(err){
throw err;
});
var finalOrder;
if (typeof botParams.type === 'boolean') {
finalOrder = botParams.category
} else {
finalOrder = botParams.type + ' ' + botParams.category
}
var googleReturn = validateAddress(botParams.address).then(function(result) { // the argument to validateAddress should later be response.text or whatever Jens comes up with
botParams.address = result.split(', ').slice(0, 3).join(', '); // address puts state as postal code...
findNearby(botParams.address).then(function(menuNearest) {
var matchedItem = bestMatch(finalOrder, menuNearest)[0]
console.log(bestMatch(finalOrder, menuNearest))
foodNameArr.push(matchedItem.Name)
foodCodeArr.push(matchedItem.Code)
pizzapi.Util.findNearbyStores(
botParams.address,
deliveryMethod,
function(storeData){
var storeID = storeData.result.Stores[0].StoreID;
orderObj = {
storeID: parseInt(storeID),
deliveryMethod: botParams.delivery, // this may need to be formatted,
customer: {
address: new pizzapi.Address(botParams.address),
email: botParams.email,
phone: botParams.phone
}
}
rtm.sendMessage('*These are your order details:* ', route)
rtm.sendMessage('*Address:* ' + botParams.address, route)
rtm.sendMessage('*Email:* ' + orderObj.customer.email + ' *Phone:* ' + orderObj.customer.phone, route)
rtm.sendMessage('*Order:* ' + foodNameArr[0] + ' *Delivery Method:* ' + orderObj.deliveryMethod, route)
rtm.sendMessage('*Can you confirm this order?*', route)
next = false
return null
}
);
}).catch(function(err) {
console.log('ERROR IN findNearby', err);
})
return result
}).catch(function(err) {
console.log('Error in address fetch', err);
})
}
} else {
if (response.text.toLowerCase().indexOf('yes') >= 0) {
var newPaymentPage = new PaymentPage({ slackId: response.user })
newPaymentPage.save(function(err) {
if (err) {
console.log('error saving new payment page', err);
}
})
var newOrder = new Order({ slackId: response.user, codeArr: foodCodeArr, orderObj: orderObj, foodNameArr: foodNameArr })
newOrder.save(function(err, returnedOrder) {
if (err) {
console.log('error saving new order', err);
} else {
rtm.sendMessage("Sounds delicious! Click this link to confirm credit card details: http://localhost:3000/payment/" + response.user, route)
placeOrder = true
payment = false
}
})
} else {
Order.remove({ slackId: response.user }, function(err) {
if (err) {
console.log('ERROR IN USER REMOVE', err);
}
})
rtm.sendMessage("Oh no! You're going to have to start again so that we can clear your information from our database!", route)
}
}
}
function buildDM(idArr) {
for (var i=0; i < idArr.length; i++) {
var dm = idArr[i].id;
var userId = idArr[i].user;
userIDObj[userId] = dm
}
}
rtm.start();