Advertisement
Guest User

main.js

a guest
Aug 12th, 2017
213
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. const bodyParser = require("body-parser");
  2. const express = require("express");
  3. const FBBotFramework = require("fb-bot-framework");
  4. const apiai = require("apiai");
  5. const FB = require("fb");
  6. //const request = require("request");
  7. const request = require("request-promise");
  8. const fetch = require('node-fetch');
  9.  
  10. // Initialization
  11. const app = express();
  12. const bot = new FBBotFramework({
  13.     page_token: "EAAbm8DBtqvsBADOZBFscxGZBmjkCxmwRuAbcUzGnTjZCIPmZBduAFVx35KBmJ7MLbiKxacDGS5jgjGEKzi6eXXJ63nmv1Txa9h4lSZBe0m3hJ8l2Vi9bt6MKMC2PZBrLkdJ3tZCBuMXWFzsCzQMTFhTwrDowZAY9i2BMWxGdmG9DPPqrnondAGF0ZBUptSajuIxEZD",
  14.     verify_token: "punchcard"
  15. });
  16. const agent = apiai("1657993115694d0b9b44f7f5a11040e5");
  17.  
  18. //Variables
  19. var url = "https://punch-card-bot.herokuapp.com";
  20. var userJson = {};
  21. var config = {};
  22.  
  23. // For the tests only
  24. var countPostback1 = 0;
  25. var countPayload1 = 0;
  26.  
  27. var initConfig = {
  28.     "number1": 0,
  29.     "number2": 0,
  30.     "accessToken": "",
  31.     "reply": "",
  32.     "text": "",
  33.     "imageUrl": "",
  34.     "buttons": [],
  35.     "timestamp": 0,
  36.     "body": {},
  37.     "postbackLoopGetStarted": true,
  38.     "postbackLoopTerms": false,
  39.     "postbackLoopQ4": false,
  40.     "payloadLoopCard": false,
  41.     "payloadLoopFreq": false,
  42.     "payloadLoopPunchcards": false,
  43.     "payloadLoopBasket": false,
  44.     //"answerQuestionsButton": false,
  45.     "webviewQ1Count": 0,
  46.     "webviewQ4Count": 0
  47. };
  48.  
  49. // Setup Express middleware for /webhook
  50. app.use("/webhook", bot.middleware());
  51.  
  52. app.use(bodyParser.json());
  53.  
  54. // Set the right port
  55. app.set("port", (process.env.PORT || 5000));
  56. console.log("port:",process.env.PORT);
  57.  
  58. app.use(express.static(__dirname));
  59.  
  60. // Welcome page
  61. app.get("/", (req, res) => {
  62.     res.send("Welcome");
  63. });
  64.  
  65. app.set("views", __dirname + "/views");
  66. app.set("view engine", "pug");
  67.  
  68. bot.setGetStartedButton("get_started");
  69.  
  70. // Setup listener for incoming messages
  71. bot.on("message", (userId, message) => {
  72.  
  73.     console.log("user id:", userId);
  74.     console.log("User text:", message);
  75.  
  76.     /*
  77.     config[userid].timestamp = Date.now();
  78.     console.log("timetamp:", config[userid].timestamp);
  79.     */
  80.  
  81.     // For the tests only
  82.     if (message === "Delete" || message === "delete") {
  83.         reset(userId);
  84.         resetLoop(userId);
  85.         config[userId].webviewQ1Count = 0;
  86.         config[userId].webviewQ4Count = 0;
  87.         userJson = {};
  88.     }
  89.  
  90.     else {
  91.         apiAgent(userId, message);
  92.     }
  93. });
  94.  
  95. // Every quickreply event
  96. bot.on("quickreply", (userId, payload) => {
  97.     console.log("payload1:", payload);
  98.     console.log("countPayload1:", countPayload1);
  99.     countPayload1++;
  100.  
  101.     switch(payload) {
  102.  
  103.         case "payload_yes":
  104.             if (config[userId].payloadLoopCard) {
  105.                 apiAgent(userId, "Yes");
  106.                 config[userId].payloadLoopCard = false;
  107.             }
  108.             break;
  109.  
  110.         case "payload_no":
  111.             if (config[userId].payloadLoopCard) {
  112.                 apiAgent(userId, "No");
  113.                 config[userId].payloadLoopCard = false;
  114.             }
  115.             break;
  116.  
  117.         // TODO: delete useless var
  118.         case "daily":
  119.         case "weekly":
  120.         case "monthly":
  121.             if (config[userId].payloadLoopFreq) {
  122.                 apiAgent(userId, payload);
  123.                 config[userId].payloadLoopFreq = false;
  124.             }
  125.             break;
  126.  
  127.         case "basket_choice1":
  128.         case "basket_choice2":
  129.         case "basket_choice3":
  130.         case "basket_choice4":
  131.             if (config[userId].payloadLoopBasket) {
  132.                 apiAgent(userId, payload);
  133.                 userJson[userId].onboardingQuestions.basketSize = payload;
  134.                 config[userId].payloadLoopBasket = false;
  135.             }
  136.             break;
  137.  
  138.         case "all":
  139.         case "redeemable":
  140.         case "collecting":
  141.             selectPunchcards(userId, payload);
  142.             break;
  143.     }
  144. });
  145.  
  146. // Every postback event
  147. bot.on("postback", (userId, payload) => {
  148.     console.log("postback1:", payload);
  149.     console.log("countPostback1:", countPostback1);
  150.     countPostback1++;
  151.  
  152.     if ((Object.keys(config).length === 0) && (config.constructor === Object)) {
  153.         console.log("create json config");
  154.         config[userId] = initConfig;
  155.     }
  156.  
  157.     if ((Object.keys(userJson).length === 0) && (userJson.constructor === Object)) {
  158.         console.log("create userJson[userId]");
  159.         userJson[userId] = {};
  160.     }
  161.  
  162.     switch (payload) {
  163.  
  164.         case "get_started":
  165.             if (config[userId].postbackLoopGetStarted) {
  166.                 config[userId].postbackLoopGetStarted = false;
  167.                 getStarted(userId);
  168.                 setTimeout( () => {
  169.                     acceptTerms(userId);
  170.                 }, 3500);
  171.  
  172.             }
  173.  
  174.             else {
  175.                 config[userId].reply = "You've already done that :)";
  176.                 bot.sendTextMessage(userId, config[userId].reply);
  177.             }
  178.             break;
  179.  
  180.         case "how_it_works":
  181.             config[userId].reply = "TODO";
  182.             bot.sendTextMessage(userId, config[userId].reply);
  183.             break;
  184.  
  185.         case "contact_supermarket":
  186.             config[userId].reply = "TODO";
  187.             bot.sendTextMessage(userId, config[userId].reply);
  188.             break;
  189.  
  190.         case "logout":
  191.             config[userId].reply = "TODO";
  192.             bot.sendTextMessage(userId, config[userId].reply);
  193.             break;
  194.  
  195.         // For the tests only
  196.         case "start_menu":
  197.             getStarted(userId);
  198.             setTimeout( () => {
  199.                 acceptTerms(userId);
  200.             }, 3500);
  201.             break;
  202.  
  203.         case "reset_json":
  204.             reset(userId);
  205.             resetLoop(userId);
  206.             config[userId].webviewQ1Count = 0;
  207.             config[userId].webviewQ4Count = 0;
  208.             userJson = {};
  209.  
  210.             config[userId].reply = "The user json was reset :)";
  211.             bot.sendTextMessage(userId, config[userId].reply);
  212.             break;
  213.  
  214.         case "questions_menu":
  215.             if ((Object.keys(userJson[userId]).length !== 0) && (userJson[userId].terms === "accepted") && (userJson[userId].cardNumber != undefined)) {
  216.  
  217.                 // Commented only for the test
  218.                 //if ((userJson[userId].onboardingQuestions == undefined) || (Object.keys(userJson[userId].onboardingQuestions).length === 0) || ((userJson[userId].onboardingQuestions.dietPreferences == undefined) || (userJson[userId].onboardingQuestions.dietPreferences.length === 0))) {
  219.                     //TODO: maybe put reset context here
  220.  
  221.                     resetLoop(userId);
  222.                     config[userId].reply = "Now we have only 4 questions for you in order to personnalize your cards.";
  223.                     bot.sendTextMessage(userId, config[userId].reply);
  224.                     config[userId].webviewQ1Count = 0;
  225.                     config[userId].webviewQ4Count = 0;
  226.  
  227.                     setTimeout( () => {
  228.                         config[userId].text = "answer-questions";
  229.                         apiAgent(userId, config[userId].text);
  230.                     }, 2000);
  231.  
  232.                 //}
  233.                 /*
  234.                 else {
  235.                     config[userId].reply = "You have already answered the onboarding questions.";
  236.                     bot.sendTextMessage(userId, config[userId].reply);
  237.                 }
  238.                 */
  239.             }
  240.  
  241.             else {
  242.                 config[userId].reply = "You can't use this button now.";
  243.                 bot.sendTextMessage(userId, config[userId].reply);
  244.             }
  245.             break;
  246.  
  247.         case "punchcards":
  248.             // Commented only for the test
  249.             //if ((Object.keys(userJson[userId]).length !== 0) && (userJson[userId].terms === "accepted") && (userJson[userId].cardNumber != undefined)) {
  250.                 reset(userId);
  251.                 resetLoop(userId);
  252.                 //webviewPunchcards(userId);
  253.                 displayPunchcards(userId, true);
  254.             //}
  255.             /*
  256.             else {
  257.                 config[userId].reply = "You can't use this button now.";
  258.                 bot.sendTextMessage(userId, config[userId].reply);
  259.             }
  260.             */
  261.             break;
  262.  
  263.         case "reset_menu":
  264.             reset(userId);
  265.             resetLoop(userId);
  266.  
  267.             // For the tests only
  268.             config[userId].webviewQ1Count = 0;
  269.             config[userId].webviewQ4Count = 0;
  270.  
  271.             config[userId].reply = "All the contexts and the variables were reset.";
  272.             bot.sendTextMessage(userId, config[userId].reply);
  273.             break;
  274.  
  275.         case "payload_decline":
  276.             if (config[userId].postbackLoopTerms) {
  277.                 config[userId].postbackLoopTerms = false;
  278.                 userJson[userId].terms = "declined";
  279.                 config[userId].reply = "Too bad.";
  280.                 bot.sendTextMessage(userId, config[userId].reply);
  281.  
  282.                 setTimeout( () => {
  283.                     config[userId].reply = "Only by accepting the T&C will you be able to participate through Facebook Messenger.";
  284.                     bot.sendTextMessage(userId, config[userId].reply);
  285.                 }, 1500);
  286.  
  287.                 setTimeout( () => {
  288.                     config[userId].reply = "Do you accept these T&C?";
  289.                     config[userId].buttons = [
  290.                         {
  291.                             "type": "postback",
  292.                             "title": "Decline",
  293.                             "payload": "payload_decline"
  294.                         },
  295.                         {
  296.                             "type": "postback",
  297.                             "title": "Accept",
  298.                             "payload": "payload_accept"
  299.                         }
  300.                     ];
  301.                     bot.sendButtonMessage(userId, config[userId].reply, config[userId].buttons);
  302.                     config[userId].postbackLoopTerms = true;
  303.                 }, 3000);
  304.  
  305.                 config[userId].postbackLoopTerms = false;
  306.             }
  307.             break;
  308.  
  309.         case "payload_accept":
  310.             if (config[userId].postbackLoopTerms) {
  311.                 config[userId].postbackLoopTerms = false;
  312.                 userJson[userId].terms = "accepted";
  313.                 config[userId].reply = "Marvelous :)";
  314.                 bot.sendTextMessage(userId, config[userId].reply);
  315.  
  316.                 setTimeout( () => {
  317.                     config[userId].reply = "Now please enter your loyalty card number so we can retrieve your account details."
  318.                     bot.sendTextMessage(userId, config[userId].reply);
  319.                 }, 1500);
  320.  
  321.                 setTimeout( () => {
  322.                     config[userId].text = "loyalty-card-number";
  323.                     apiAgent(userId, config[userId].text);
  324.                 }, 3500);
  325.  
  326.                 config[userId].postbackLoopTerms = false;
  327.             }
  328.             break;
  329.  
  330.         case "question4":
  331.             if (config[userId].postbackLoopQ4) {
  332.                 console.log("end onboarding");
  333.                 endOnboarding(userId);
  334.                 config[userId].postbackLoopQ4 = false;
  335.                 config[userId].webviewQ4Count = 1;
  336.             }
  337.             break;
  338.     }
  339. });
  340.  
  341. bot.on('attachment', function(userId, attachment){
  342.     console.log("attachment:", attachment);
  343.     /*
  344.     Type image: GIF (.gif in payload.url), image, stickers (payload.sticker_id)
  345.     Type audio: recorder, song file
  346.     Type video: video attached
  347.     Type file: pdf..
  348.     Type location: send the location (with mobile)
  349.     */
  350.  
  351.     switch (attachment[0].type) {
  352.  
  353.         case "location":
  354.             var latitude = attachment[0].payload.coordinates.lat;
  355.             var longitude = attachment[0].payload.coordinates.long;
  356.  
  357.             json = "http://api.openweathermap.org/data/2.5/weather?lat=" + latitude + "&lon=" + longitude + "&appid=9393e4c87b6070958c8611b9f5211c48"
  358.  
  359.             // Retrieve the weather JSON file from the url
  360.             fetch(json)
  361.                 .then((res) => {
  362.                     return res.json();
  363.                 }).then((json) => {
  364.                     var city = json.name;
  365.                     config[userId].reply = city + " is a beautiful city :)"
  366.                     bot.sendTextMessage(userId, config[userId].reply);
  367.                 })
  368.             break;
  369.  
  370.         case "image":
  371.  
  372.             if (attachment[0].payload.sticker_id != undefined){
  373.                 config[userId].reply = "Nice sticker 👍"
  374.                 bot.sendTextMessage(userId, config[userId].reply);
  375.             }
  376.  
  377.             else if (attachment[0].payload.url.search(".gif")) {
  378.                 console.log("gif!");
  379.                 config[userId].imageUrl = "https://media.giphy.com/media/l3HBbltOYjoNq/giphy.gif";
  380.                 bot.sendImageMessage(userId, config[userId].imageUrl);
  381.             }
  382.  
  383.  
  384.  
  385.             else {
  386.                 config[userId].reply = "Nice image!"
  387.                 bot.sendTextMessage(userId, config[userId].reply);
  388.             }
  389.             break;
  390.  
  391.         case "audio":
  392.             config[userId].reply = "Great sound :D"
  393.             bot.sendTextMessage(userId, config[userId].reply);
  394.             break;
  395.  
  396.         case "video":
  397.             config[userId].reply = "Thanks for the video ;)"
  398.             bot.sendTextMessage(userId, config[userId].reply);
  399.             break;
  400.  
  401.         case "file":
  402.             config[userId].reply = "Thanks for sending a file but I can't do anything with that :p"
  403.             bot.sendTextMessage(userId, config[userId].reply);
  404.             break;
  405.  
  406.         case "template":
  407.             config[userId].reply = "I love this webview!"
  408.             bot.sendTextMessage(userId, config[userId].reply);
  409.             break;
  410.  
  411.     }
  412.  
  413.     setTimeout( () => {
  414.         config[userId].text = "no-context";
  415.         apiAgent(userId, config[userId].text);
  416.     }, 1500);
  417.  
  418. });
  419.  
  420. // Make Express listening
  421. app.listen(app.get("port"), () => {
  422.     console.log("Started on port", app.get("port"));
  423. })
  424.  
  425. // Main function: user message event
  426. function apiAgent(userId, message) {
  427.  
  428.     console.log("Message sent to apiai:", message);
  429.  
  430.     // Send text content to the right Api.ai agent
  431.     var requestApiai = agent.textRequest(message, {
  432.         sessionId: userId
  433.     });
  434.  
  435.     /*
  436.     var context = agent.getContextsRequest({sessionId: "2fa6a5073f444164886980acb2e3d15a"})
  437.     console.log("context:", context);
  438.     */
  439.  
  440.     // Reset the count each new message from the bot (in the case the bot sends several answers)
  441.     var count = 0;
  442.  
  443.     // Api.ai agent answers
  444.     requestApiai.on("response", (response) => {
  445.     //console.log("ARGS:", arguments)
  446.     console.log("apiai answer:", response.result.fulfillment);
  447.  
  448.     while (count < response.result.fulfillment.messages.length) {
  449.  
  450.         botAnswer = response.result.fulfillment.messages[count];
  451.         console.log("platform:", botAnswer.platform);
  452.  
  453.         if (botAnswer.platform == "facebook" || botAnswer.platform == undefined) {
  454.  
  455.             // If the answer is a custom payload (type = 4)
  456.             if ((botAnswer.type == 4)) {
  457.                 console.log("answer type 4:", botAnswer.payload);
  458.  
  459.                 var apiaiContext = botAnswer.payload.facebook.attachment.type;
  460.                 console.log("apiaiContext", apiaiContext);
  461.  
  462.                 switch (apiaiContext) {
  463.  
  464.                     // For car number yes/no quick replies
  465.                     case "yes-no":
  466.                         var payloadApi = botAnswer.payload.facebook.attachment.payload;
  467.  
  468.                         if (payloadApi.number1 !== undefined) {
  469.                             config[userId].number1 = payloadApi.number1;
  470.                         }
  471.  
  472.                         console.log("number1:", config[userId].number1);
  473.                         bot.sendQuickReplies(userId, payloadApi.text, payloadApi.quick_reply);
  474.                         config[userId].payloadLoopCard = true;
  475.                         //payloadEvent(userId);
  476.                         break;
  477.  
  478.                     // To confirm the right loyalty card number
  479.                     case "number-confirmation":
  480.                         config[userId].number2 = botAnswer.payload.facebook.attachment.payload.number2;
  481.                         console.log("number2:", config[userId].number2);
  482.  
  483.                         if (config[userId].number1 === config[userId].number2) {
  484.                             userJson[userId].cardNumber = config[userId].number2;
  485.                             //console.log("Json file:", userJson);
  486.  
  487.                             config[userId].imageUrl = "https://media.tenor.com/images/183267efd48bc2a9f176420ab0b9c373/tenor.gif";
  488.                             bot.sendImageMessage(userId, config[userId].imageUrl);
  489.  
  490.                             setTimeout( () => {
  491.                                 config[userId].reply = "Now we have only 4 questions for you in order to personnalize your cards.";
  492.                                 bot.sendTextMessage(userId, config[userId].reply);
  493.                             }, 3000);
  494.  
  495.                             setTimeout( () => {
  496.                                 config[userId].text = "answer-questions";
  497.                                 apiAgent(userId, config[userId].text);
  498.                             }, 5000);
  499.                         }
  500.  
  501.                         else {
  502.                             config[userId].reply = "Oops... You made a mistake, do it again please.";
  503.                             bot.sendTextMessage(userId, config[userId].reply);
  504.  
  505.                             setTimeout( () => {
  506.                                 reset(userId);
  507.                             }, 100);
  508.  
  509.                             setTimeout( () => {
  510.                                 config[userId].text = "loyalty-card-number";
  511.                                 apiAgent(userId, config[userId].text);
  512.                             }, 2000);
  513.                         }
  514.                         userJson[userId].onboardingQuestions = {};
  515.                         break;
  516.  
  517.                     // For punch cards display
  518.                     case "punch-card-display":
  519.                         resetLoop(userId);
  520.                         displayPunchcards(userId, false);
  521.                         break;
  522.  
  523.                     // Onbording questions: question 1
  524.                     case "products-category":
  525.                         resetLoop(userId);
  526.  
  527.                         if (userJson[userId].onboardingQuestions == undefined) {
  528.                             userJson[userId].onboardingQuestions = {};
  529.                         }
  530.  
  531.                         userJson[userId].onboardingQuestions.productsCategory = [];
  532.                         productsCategory = [
  533.                             {
  534.                                 "title": "Question 1: Usually, what do you buy at our stores?",
  535.                                 //"image_url": url + "/public/images/supermarket.jpg",
  536.                                 //"image_url": "http://images.mid-day.com/2013/mar/supermarket.jpg",
  537.                                 "image_url": "https://image.freepik.com/free-vector/supermarket-shelves_23-2147495480.jpg",
  538.                                 "buttons": [
  539.                                     {
  540.                                         "type":"web_url",
  541.                                         "title":"Choose",
  542.                                         "url": url + "/views/question1.html",
  543.                                         "messenger_extensions": true,
  544.                                         "webview_height_ratio": "tall",
  545.                                         "fallback_url": url + "/views/question1.html"
  546.                                     }
  547.                                 ]
  548.                             }
  549.                         ];
  550.  
  551.                         config[userId].reply = "Ok, let's do it! 👍";
  552.                         bot.sendTextMessage(userId, config[userId].reply);
  553.  
  554.                         //Json page to retrieve food data (question 1)
  555.                         app.post("/question1", (req, res) => {
  556.                             res.send({});
  557.                             console.log("req:", req.body);
  558.  
  559.                             if (config[userId].webviewQ1Count === 0) {
  560.  
  561.                                 if (Object.keys(req.body).length === 0 && req.body.constructor === Object) {
  562.                                     config[userId].reply = "Please, select at least one product.";
  563.                                     bot.sendTextMessage(userId, config[userId].reply);
  564.                                 }
  565.  
  566.                                 else {
  567.                                     userJson[userId].onboardingQuestions.productsCategory = [];
  568.  
  569.                                     for (property in req.body) {
  570.                                         //console.log("property:", property);
  571.                                         if (req.body[property]%2 != 0) {
  572.                                             userJson[userId].onboardingQuestions.productsCategory.push(property);
  573.                                         }
  574.                                     }
  575.  
  576.                                     if (userJson[userId].onboardingQuestions.productsCategory.length === 0) {
  577.                                         config[userId].reply = "Please, select some products.";
  578.                                         bot.sendTextMessage(userId, config[userId].reply);
  579.                                     }
  580.  
  581.                                     else {
  582.                                         if (config[userId].webviewQ1Count === 0 ) {
  583.                                             config[userId].webviewQ1Count = 1;
  584.                                             config[userId].text = "question-answered";
  585.                                             apiAgent(userId, config[userId].text);
  586.                                         }
  587.  
  588.                                         /*
  589.                                         else {
  590.                                             config[userId].reply = "You already answered the first question...";
  591.                                             bot.sendTextMessage(userId, config[userId].reply);
  592.                                         }
  593.                                         */
  594.                                     }
  595.                                 }
  596.                             }
  597.                         });
  598.  
  599.                         setTimeout( () => {
  600.                             bot.sendGenericMessage(userId, productsCategory);
  601.                         }, 1500);
  602.                         break;
  603.  
  604.                     // Onbording questions: question 2
  605.                     case "frequency":
  606.                         resetLoop(userId);
  607.                         userJson[userId].onboardingQuestions.frequency = {};
  608.                         var payloadApi = botAnswer.payload.facebook.attachment.payload;
  609.  
  610.                         setTimeout( () => {
  611.                             bot.sendQuickReplies(userId, payloadApi.text, payloadApi.quick_reply);
  612.                             config[userId].payloadLoopFreq = true;
  613.                             //payloadEvent(userId);
  614.                         }, 3000);
  615.                         break;
  616.  
  617.                     case "frequency-answer":
  618.                         var payloadApi = botAnswer.payload.facebook.attachment.payload;
  619.                         var answer = payloadApi.text;
  620.                         console.log("answer:", answer);
  621.  
  622.                         userJson[userId].onboardingQuestions.frequency.unity = answer.toLowerCase();
  623.                         console.log("json here:", userJson);
  624.                         break;
  625.  
  626.                     // Onbording questions: question 3
  627.                     case "basket-size":
  628.                         resetLoop(userId);
  629.                         var payloadApi = botAnswer.payload.facebook.attachment.payload;
  630.  
  631.                         // Last question result
  632.                         userJson[userId].onboardingQuestions.frequency.times = payloadApi.result;
  633.  
  634.                         setTimeout( () => {
  635.                             config[userId].payloadLoopBasket = true;
  636.                             bot.sendQuickReplies(userId, payloadApi.text, payloadApi.quick_reply);
  637.                             //payloadEvent(userId);
  638.                         }, 2000);
  639.                         break;
  640.  
  641.                     case "diet-preferences":
  642.                         resetLoop(userId);
  643.                         config[userId].postbackLoopQ4 = true;
  644.                         userJson[userId].onboardingQuestions.dietPreferences = []
  645.                         dietsPreferences = [
  646.                             {
  647.                                 "title": "Question 4: Do you have any diet preferences or allergies?",
  648.                                 "image_url": "http://21406-presscdn.pagely.netdna-cdn.com/wp-content/uploads/2017/01/healthy-foods.jpg",
  649.                                 "buttons": [
  650.                                     {
  651.                                         "type":"web_url",
  652.                                         "title":"Yes",
  653.                                         "url": url + "/views/question4.html",
  654.                                         "messenger_extensions": true,
  655.                                         "webview_height_ratio": "tall",
  656.                                         "fallback_url": url + "/views/question4.html"
  657.                                     },
  658.                                     {
  659.                                         "type": "postback",
  660.                                         "title": "No",
  661.                                         "payload": "question4"
  662.                                     }
  663.  
  664.                                 ]
  665.                             }
  666.                         ];
  667.  
  668.                         //Json page to retrieve food data (question 1)
  669.                         app.post("/question4", (req, res) => {
  670.                             res.send({});
  671.                             console.log("req:", req.body);
  672.  
  673.                             if (config[userId].webviewQ4Count === 0) {
  674.                                 userJson[userId].onboardingQuestions.dietPreferences = [];
  675.  
  676.                                 for (property in req.body) {
  677.  
  678.                                     if (property === "preferences") {
  679.                                         userJson[userId].onboardingQuestions.dietPreferences.push(req.body[property]);
  680.                                     }
  681.  
  682.                                     else if (property === "allergies") {
  683.                                         userJson[userId].onboardingQuestions.allergies = req.body[property];
  684.                                     }
  685.  
  686.                                     else if (req.body[property]%2 != 0) {
  687.                                         userJson[userId].onboardingQuestions.dietPreferences.push(property);
  688.                                     }
  689.                                 }
  690.  
  691.                                 config[userId].webviewQ4Count = 1;
  692.                                 endOnboarding(userId);
  693.                                 console.log("final json:", userJson[userId]);
  694.                             }
  695.                             //console.log("test json:", userJson[userId]);
  696.                         });
  697.  
  698.                         setTimeout( () => {
  699.                             bot.sendGenericMessage(userId, dietsPreferences);
  700.                         }, 2000);
  701.                         break;
  702.  
  703.                     case "no-context":
  704.                         resetLoop(userId);
  705.                         console.log("json nocontext:", userJson[userId]);
  706.  
  707.                         if (((Object.keys(userJson).length === 0) && (userJson.constructor === Object))
  708.                             || ((Object.keys(userJson[userId]).length === 0) && (userJson[userId].constructor === Object))
  709.                             || (userJson[userId].terms !== "accepted")) {
  710.  
  711.                             config[userId].text = "push-button-fallback";
  712.                             apiAgent(userId, config[userId].text);
  713.  
  714.                             acceptTerms(userId);
  715.                         }
  716.  
  717.                         else if (userJson[userId].cardNumber == undefined) {
  718.                             //config[userId].reply = "You didn't confirm your card number :/ We need it to log you in the right account.";
  719.                             config[userId].reply = "Now please enter your loyalty card number so we can retrieve your account details."
  720.                             bot.sendTextMessage(userId, config[userId].reply);
  721.  
  722.                             setTimeout( () => {
  723.                                 config[userId].text = "loyalty-card-number";
  724.                                 apiAgent(userId, config[userId].text);
  725.                             }, 2000);
  726.                         }
  727.  
  728.                         else if (((Object.keys(userJson[userId].onboardingQuestions).length !== 0) && (userJson[userId].onboardingQuestions.constructor === Object))
  729.                                 && ((userJson[userId].onboardingQuestions.dietPreferences == undefined) || (userJson[userId].onboardingQuestions.dietPreferences.length === 0))) {
  730.  
  731.                             //config[userId].reply = "You didn't finish answering the questions last time :/";
  732.                             config[userId].reply = "Now we have only 4 questions for you in order to personnalize your cards.";
  733.                             bot.sendTextMessage(userId, config[userId].reply);
  734.                             config[userId].webviewQ1Count = 0;
  735.                             config[userId].webviewQ4Count = 0;
  736.  
  737.                             setTimeout( () => {
  738.                                 config[userId].text = "answer-questions";
  739.                                 apiAgent(userId, config[userId].text);
  740.                             }, 2000);
  741.                         }
  742.  
  743.                         else {
  744.                             config[userId].reply = "There isn't any context, use the menu :p";
  745.                             bot.sendTextMessage(userId, config[userId].reply);
  746.                         }
  747.                         /*
  748.                         // TODO: startQuestions(userId)
  749.                         else if () {
  750.                             if ( (config[userId].timestamp - Date.now() > 600000) ) {
  751.                                 config[userId].reply = "Welcome back!"
  752.                             }
  753.                             else {
  754.                                 //reply
  755.                             }
  756.                         }
  757.                         */
  758.                         break;
  759.                     }
  760.                 }
  761.  
  762.                 // If the answer is a text response (type = 0)
  763.                 else if (botAnswer.type == 0) {
  764.                     console.log("answer type 0:", response.result.fulfillment);
  765.                     config[userId].reply = botAnswer.speech;
  766.                     bot.sendTextMessage(userId, config[userId].reply);
  767.                 }
  768.             }
  769.             count++;
  770.         }
  771.  
  772.     })
  773.  
  774.     requestApiai.on("error", (error) => {
  775.         console.log("errooor:", error);
  776.     });
  777.  
  778.     requestApiai.end();
  779. }
  780.  
  781.  
  782. // For request catch error
  783. function catchError(userId, error) {
  784.     console.log("error:", error);
  785.     config[userId].reply = "There was a problem with the request, we apologize for the inconvenience.";
  786.     bot.sendTextMessage(userId, config[userId].reply);
  787. }
  788.  
  789. // To display right text (singular/plurial)
  790. function dayDisplay(number) {
  791.     var day;
  792.     if (number === 0 || number === 1 || number === -1) {
  793.         day = "day";
  794.     }
  795.  
  796.     else {
  797.         day = "days";
  798.     }
  799.  
  800.     return day;
  801. }
  802.  
  803. // Reset apiai contexts
  804. function reset(userId) {
  805.  
  806.     if ((Object.keys(config).length === 0) && (config.constructor === Object)) {
  807.         console.log("create json config1");
  808.         config[userId] = initConfig;
  809.     }
  810.  
  811.     config[userId].text = "reset";
  812.     apiAgent(userId, config[userId].text);
  813. }
  814.  
  815. function resetLoop(userId) {
  816.  
  817.     if ((Object.keys(config).length === 0) && (config.constructor === Object)) {
  818.         console.log("create json config2");
  819.         config[userId] = initConfig;
  820.     }
  821.  
  822.     else {
  823.         // TODO: for loop
  824.         //config[userId].postbackLoopGetStarted = false;
  825.         config[userId].postbackLoopReset = false;
  826.         config[userId].postbackLoopTerms = false;
  827.         config[userId].postbackLoopQ4 = false;
  828.         config[userId].payloadLoopCard = false;
  829.         config[userId].payloadLoopFreq = false;
  830.         config[userId].payloadLoopPunchcards = false;
  831.         config[userId].payloadLoopBasket = false;
  832.     }
  833.  
  834. }
  835.  
  836. function displayPunchcards(userId, quickreply) {
  837.  
  838.     // Retrieve token from the user
  839.     var options = {
  840.         method: "GET",
  841.         url: "https://alfamart-poa-dev.bright-shopper.nl/v1/loyalties/punchcards/tenants/alfamart/programs/punch1/poa/oauth2/token",
  842.         qs: {
  843.             username: "dennis",
  844.             password: "123",
  845.             grant_type: "password"
  846.         }
  847.     };
  848.  
  849.     request(options)
  850.         .then( (body) => {
  851.             config[userId].accessToken = JSON.parse(body).access_token
  852.  
  853.             // Get punch card thanks to the user token
  854.             var options = {
  855.                 method: "GET",
  856.                 url: "https://punch-mock.bright-shopper.nl/v1/loyalties/punchcards/tenants/alfamart/programs/punch1/mock/my/punchcards"
  857.                 /*url: "https://alfamart-poa-dev.bright-shopper.nl/v1/loyalties/punchcards/tenants/alfamart/programs/punch1/poa/participations/596c6e9333cd6616a9d86e0a/punchcards",
  858.                 qs: {
  859.                     listAll: "true"
  860.                 },
  861.                 headers: {
  862.                     authorization: "Bearer " + config[userId].accessToken
  863.                 }*/
  864.             };
  865.  
  866.             request(options)
  867.                 .then( (body) => {
  868.                     //console.log("body punchcard", body);
  869.                     config[userId].body = JSON.parse(body);
  870.  
  871.                     if (config[userId].body.code == "invalid_token") {
  872.                         config[userId].reply = "Invalid Token";
  873.                         bot.sendTextMessage(userId, config[userId].reply);
  874.                     }
  875.  
  876.                     else {
  877.  
  878.                         if (quickreply) {
  879.                             config[userId].reply = "Which cards do you want to display?";
  880.                             config[userId].buttons = [
  881.                                 {
  882.                                     "content_type": "text",
  883.                                     "title": "All",
  884.                                     "payload": "all"
  885.                                 },
  886.                                 {
  887.                                     "content_type": "text",
  888.                                     "title": "Complete",
  889.                                     "payload": "redeemable"
  890.                                 },
  891.                                 {
  892.                                     "content_type": "text",
  893.                                     "title": "In progress",
  894.                                     "payload": "collecting"
  895.                                 }
  896.                             ]
  897.                             bot.sendQuickReplies(userId, config[userId].reply, config[userId].buttons);
  898.                         }
  899.  
  900.                         else {
  901.                             selectPunchcards(userId, "all")
  902.                         }
  903.                     }
  904.                 })
  905.                 .catch( (error) => catchError(userId, error))
  906.         })
  907.         .catch( (error) => catchError(userId, error))
  908. }
  909.  
  910. function selectPunchcards(userId, payload) {
  911.     var b = config[userId].body;
  912.     var punchCards = [];
  913.     var cardNumber = b.punchcards.length;
  914.     //console.log("punchcards number:", cardNumber);
  915.     var sayDay = "day";
  916.  
  917.     for (i=0; i<cardNumber; i++) {
  918.         var num = i.toString();
  919.  
  920.         if (b.punchcards[i].collect != undefined) {
  921.             var dayNumber = b.punchcards[i].collect.daysRemaining;
  922.         }
  923.  
  924.         if (b.punchcards[i].redeem != undefined) {
  925.             var dayNumber = b.punchcards[i].redeem.daysRemaining;
  926.         }
  927.  
  928.         if (payload === "all" ||  payload === b.punchcards[i].status) {
  929.  
  930.             // Send punchcards data to pug file
  931.             if (b.punchcards[i].status === "redeemable") {
  932.                 app.get("/views/punchcards/redeemable/:userId/:num" , function (req, res) {
  933.                     console.log("complete card");
  934.                     console.log("req:", req.params);
  935.                     res.render("punchcards_complete", {});
  936.                 });
  937.  
  938.                 punchCards.push(
  939.                     {
  940.                         "image_url": "https://punch-mock.bright-shopper.nl/" + b.punchcards[i].imageUrl,
  941.                         //"image_url": "https://s3-eu-west-1.amazonaws.com/punchcards-images-dev/" + b.punchcards[i].image,
  942.                         "title": b.punchcards[i].localizedContent["en-us"].title,
  943.                         "subtitle": "Days left to redeem: " + dayNumber + dayDisplay(dayNumber) + ".\nBALANCE: " + b.punchcards[i].punches + "/" + b.punchcards[i].requiredPunches,
  944.                         "buttons": [
  945.                             {
  946.                                 "title": "Open",
  947.                                 "type": "web_url",
  948.                                 "url": url + "/views/punchcards/redeemable/" + userId + "/" + num,
  949.                                 "messenger_extensions": true,
  950.                                 "webview_height_ratio": "tall",
  951.                                 "fallback_url": url + "/views/punchcards/redeemable/" + userId + "/" + num
  952.                             }
  953.                         ]
  954.                     }
  955.                 );
  956.             }
  957.  
  958.             else if (b.punchcards[i].collectMechanism === "products") {
  959.  
  960.                 app.get("/views/punchcards/products/:userId/:num" , function (req, res) {
  961.                     console.log("products");
  962.                     console.log("req:", req.params);
  963.                     var products = b.punchcards[req.params.num].eligibleProducts.previewProducts;
  964.                     for (j=0; j<b.punchcards[req.params.num].eligibleProducts.total; j++) {
  965.                         if (products[j].price.toString().length > 2) {
  966.                             products[j].euros = products[j].price.toString().substr(0, products[j].price.toString().length-2);
  967.                             products[j].cents = products[j].price.toString().substr(-2, products[j].price.toString().length);
  968.  
  969.                         }
  970.                         else {
  971.                             products[j].euros = "0";
  972.                             products[j].cents = products[j].price.toString().substr(0, products[j].price.toString().length);
  973.                         }
  974.                     }
  975.                     res.render("punchcards_products",
  976.                         {
  977.                             title: b.punchcards[req.params.num].localizedContent["en-us"].title,
  978.                             productsList: products
  979.                         });
  980.                 });
  981.  
  982.                 punchCards.push(
  983.                     {
  984.                         "image_url": "https://punch-mock.bright-shopper.nl/" + b.punchcards[i].imageUrl,
  985.                         //"image_url": "https://s3-eu-west-1.amazonaws.com/punchcards-images-dev/" + b.punchcards[i].image,
  986.                         "title": b.punchcards[i].localizedContent["en-us"].title,
  987.                         "subtitle": "Days left to redeem: " + dayNumber + dayDisplay(dayNumber) + ".\nBALANCE: " + b.punchcards[i].punches + "/" + b.punchcards[i].requiredPunches,
  988.                         "buttons": [
  989.                             {
  990.                                 "title": "Open",
  991.                                 "type": "web_url",
  992.                                 "url": url + "/views/punchcards/products/" + userId + "/" + num,
  993.                                 "messenger_extensions": true,
  994.                                 "webview_height_ratio": "tall",
  995.                                 "fallback_url": url + "/views/punchcards/products/" + userId + "/" + num
  996.                             }
  997.                         ]
  998.                     }
  999.                 );
  1000.             }
  1001.  
  1002.             else if (b.punchcards[i].collectMechanism === "money") {
  1003.                 app.get("/views/punchcards/money/:userId/:num" , function (req, res) {
  1004.                     console.log("money");
  1005.                     console.log("req:", req.params);
  1006.                     res.render("punchcards_money",
  1007.                         {
  1008.                             title: b.punchcards[req.params.num].localizedContent["en-us"].title,
  1009.                             subtitle: b.punchcards[req.params.num].moneyBooster.localizedContent["en-us"].title,
  1010.                             body: b.punchcards[req.params.num].moneyBooster.localizedContent["en-us"].body.split("\n\n"),
  1011.                             url: b.punchcards[req.params.num].imageUrl
  1012.                         });
  1013.                 });
  1014.  
  1015.                 punchCards.push(
  1016.                     {
  1017.                         "image_url": "https://punch-mock.bright-shopper.nl/" + b.punchcards[i].imageUrl,
  1018.                         //"image_url": "https://s3-eu-west-1.amazonaws.com/punchcards-images-dev/" + b.punchcards[i].image,
  1019.                         "title": b.punchcards[i].localizedContent["en-us"].title,
  1020.                         "subtitle": "Days left to redeem: " + dayNumber + dayDisplay(dayNumber) + ".\nBALANCE: " + b.punchcards[i].punches + "/" + b.punchcards[i].requiredPunches,
  1021.                         "buttons": [
  1022.                             {
  1023.                                 "title": "Open",
  1024.                                 "type": "web_url",
  1025.                                 "url": url + "/views/punchcards/money/" + userId + "/" + num,
  1026.                                 "messenger_extensions": true,
  1027.                                 "webview_height_ratio": "tall",
  1028.                                 "fallback_url": url + "/views/punchcards/money/" + userId + "/" + num
  1029.                             }
  1030.                         ]
  1031.                     }
  1032.                 );
  1033.             }
  1034.         }
  1035.     }
  1036.  
  1037.     if (punchCards.length > 4) {
  1038.         bot.sendGenericMessage(userId, punchCards);
  1039.         console.log("Punchcards end:", punchCards);
  1040.     }
  1041.  
  1042.     else if (punchCards.length <= 4) {
  1043.         bot.sendListMessage(userId, punchCards);
  1044.         console.log("Punchcards end:", punchCards);
  1045.     }
  1046.  
  1047.     else {
  1048.         config[userId].reply = "You don't have this kind of cards.";
  1049.         bot.sendTextMessage(userId, config[userId].reply);
  1050.     }
  1051. }
  1052.  
  1053. function webviewPunchcards(userId) {
  1054.  
  1055.     // Retrieve token from the user
  1056.     var options = {
  1057.         method: "GET",
  1058.         url: "https://alfamart-poa-dev.bright-shopper.nl/v1/loyalties/punchcards/tenants/alfamart/programs/punch1/poa/oauth2/token",
  1059.         qs: {
  1060.             username: "dennis",
  1061.             password: "123",
  1062.             grant_type: "password"
  1063.         }
  1064.     };
  1065.  
  1066.     request(options)
  1067.         .then( (body) => {
  1068.             config[userId].accessToken = JSON.parse(body).access_token
  1069.  
  1070.             // Get punch card thanks to the user token
  1071.             var options = {
  1072.                 method: "GET",
  1073.                 //url: "https://alfamart-poa-dev.bright-shopper.nl/v1/loyalties/punchcards/tenants/alfamart/programs/punch1/mock/my/punchcards",
  1074.                 url: "https://punch-mock.bright-shopper.nl/v1/loyalties/punchcards/tenants/alfamart/programs/punch1/mock/my/punchcards"
  1075.             };
  1076.  
  1077.             request(options)
  1078.                 .then( (body) => {
  1079.                     //console.log("body punchcard", body);
  1080.                     if (b.code == "invalid_token") {
  1081.                         config[userId].reply = "Invalid Token";
  1082.                         bot.sendTextMessage(userId, config[userId].reply);
  1083.                     }
  1084.  
  1085.                     else {
  1086.                     }
  1087.                 })
  1088.                 .catch( (error) => catchError(userId, error))
  1089.         })
  1090.         .catch( (error) => catchError(userId, error))
  1091. }
  1092.  
  1093. function acceptTerms(userId) {
  1094.  
  1095.     userJson[userId] = {};
  1096.  
  1097.     //Send message to Apiai to push the user pushing one button
  1098.  
  1099.     config[userId].reply = "Before we continue, you must first accept the T&C";
  1100.     config[userId].buttons = [
  1101.         {
  1102.             "type": "web_url",
  1103.             "url": "https://alfamart-punchportalnginx-dev.bright-shopper.nl/index.html?#/",
  1104.             "title": "Terms & Conditions"
  1105.         }
  1106.     ];
  1107.     bot.sendButtonMessage(userId, config[userId].reply, config[userId].buttons);
  1108.  
  1109.  
  1110.     setTimeout( () => {
  1111.         config[userId].reply = "Do you accept these T&C?";
  1112.         config[userId].buttons = [
  1113.             {
  1114.                 "type": "postback",
  1115.                 "title": "Accept",
  1116.                 "payload": "payload_accept"
  1117.             },
  1118.             {
  1119.                 "type": "postback",
  1120.                 "title": "Decline",
  1121.                 "payload": "payload_decline"
  1122.             }
  1123.         ];
  1124.         //bot.sendQuickReplies(userId, config[userId].reply, config[userId].buttons);
  1125.         bot.sendButtonMessage(userId, config[userId].reply, config[userId].buttons);
  1126.     }, 1500);
  1127.  
  1128.     config[userId].postbackLoopTerms = true;
  1129. }
  1130.  
  1131. function endOnboarding(userId) {
  1132.     config[userId].imageUrl = "https://media.giphy.com/media/3oz9ZE2Oo9zRC/giphy.gif";
  1133.     bot.sendImageMessage(userId, config[userId].imageUrl);
  1134.  
  1135.     setTimeout( () => {
  1136.         config[userId].reply = "You finished the onboarding questions! Now here are your punchards.";
  1137.         bot.sendTextMessage(userId, config[userId].reply);
  1138.     }, 2000);
  1139.  
  1140.     setTimeout( () => {
  1141.         displayPunchcards(userId, false);
  1142.     }, 4000);
  1143.  
  1144.     console.log("json:", userJson[userId]);
  1145.  
  1146.     reset(userId);
  1147.     resetLoop(userId);
  1148. }
  1149.  
  1150. function getStarted(userId) {
  1151.     userJson[userId] = {};
  1152.     config[userId] = initConfig;
  1153.     config[userId].text = "push-button-fallback";
  1154.     apiAgent(userId, config[userId].text);
  1155.  
  1156.     FB.setAccessToken("EAAbm8DBtqvsBADOZBFscxGZBmjkCxmwRuAbcUzGnTjZCIPmZBduAFVx35KBmJ7MLbiKxacDGS5jgjGEKzi6eXXJ63nmv1Txa9h4lSZBe0m3hJ8l2Vi9bt6MKMC2PZBrLkdJ3tZCBuMXWFzsCzQMTFhTwrDowZAY9i2BMWxGdmG9DPPqrnondAGF0ZBUptSajuIxEZD");
  1157.     var urlUserId = "/" + userId;
  1158.  
  1159.     FB.api(urlUserId, (res) => {
  1160.  
  1161.         if (!res || res.error) {
  1162.             console.log(!res ? "error occurred" : res.error);
  1163.             return;
  1164.         }
  1165.  
  1166.         //console.log("res:",res);
  1167.         config[userId].reply = "Hi " + res.first_name + "! " + "Welcome to the Punch Card bot :)";
  1168.         bot.sendTextMessage(userId, config[userId].reply);
  1169.  
  1170.     });
  1171.  
  1172.     setTimeout( () => {
  1173.         config[userId].imageUrl = "https://media.giphy.com/media/glEsn20jvC7iE/giphy.gif";
  1174.         bot.sendImageMessage(userId, config[userId].imageUrl);
  1175.     }, 300);
  1176. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement