View Javadoc
1   /*
2    * Copyright (c) 2002-2017, Mairie de Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.plugins.chatbot.modules.stationnement.web;
35  
36  import java.io.IOException;
37  import java.util.ArrayList;
38  import java.util.HashMap;
39  import java.util.List;
40  import java.util.Map;
41  import java.util.stream.Collectors;
42  
43  import javax.servlet.ServletException;
44  import javax.servlet.http.HttpServlet;
45  import javax.servlet.http.HttpServletRequest;
46  import javax.servlet.http.HttpServletResponse;
47  
48  import org.apache.commons.io.IOUtils;
49  
50  import com.fasterxml.jackson.databind.JsonNode;
51  import com.fasterxml.jackson.databind.ObjectMapper;
52  
53  import fr.paris.lutece.plugins.chatbot.modules.stationnement.business.NoFeesDay;
54  import fr.paris.lutece.plugins.chatbot.modules.stationnement.business.NoFeesDayHome;
55  import fr.paris.lutece.portal.service.util.AppLogService;
56  import fr.paris.lutece.portal.service.util.AppPropertiesService;
57  import fr.paris.lutece.util.httpaccess.HttpAccess;
58  import fr.paris.lutece.util.httpaccess.HttpAccessException;
59  
60  public class NoFeesDayActionServlet extends HttpServlet
61  {
62  
63      private static final String PROPERTY_TOKEN = "chatbot-stationnement.recast.token";
64  
65      /**
66           *
67           */
68      private static final long serialVersionUID = -2387659805321292879L;
69      
70  //Example input
71  //{
72  //  "conversation": {
73  //    "language": "fr",
74  //    "skill_occurences": 3,
75  //    "skill": "63d3d0d8-7340-4cf3-9292-21596f4acfc9",
76  //    "memory": {
77  //      "location": {
78  //        "confidence": 0.98,
79  //        "raw": "227 rue de bercy paris",
80  //        "place": "ChIJjWtmOwNy5kcRTfOJS7ErxCk",
81  //        "type": "street_address",
82  //        "lng": 2.369777,
83  //        "lat": 48.8464993,
84  //        "formatted": "227 Rue de Bercy, 75012 Paris-12E-Arrondissement, France"
85  //      },
86  //      "date": {
87  //        "confidence": 0.99,
88  //        "raw": "aujourd'hui",
89  //        "state": "relative",
90  //        "chronology": "present",
91  //        "accuracy": "day",
92  //        "iso": "2017-10-27T14:29:02+00:00",
93  //        "formatted": "vendredi 27 octobre 2017 à 14h29m02s (+0000)"
94  //      }
95  //    },
96  //    "skill_stack": [
97  //      "63d3d0d8-7340-4cf3-9292-21596f4acfc9"
98  //    ],
99  //    "conversation_id": "4d07d6a0-8faa-4d87-9e43-d238683ab667"
100 //  },
101 //  "nlp": {
102 //    "status": 200,
103 //    "timestamp": "2017-10-27T14:29:12.939995+00:00",
104 //    "version": "2.10.1",
105 //    "processing_language": "fr",
106 //    "uuid": "89158fd7-11d5-4541-bd04-4d292779cb2d",
107 //    "source": "227 rue de bercy paris",
108 //    "intents": [
109 //      {
110 //        "confidence": 0.54,
111 //        "slug": "freepark"
112 //      }
113 //    ],
114 //    "act": "assert",
115 //    "type": null,
116 //    "sentiment": "neutral",
117 //    "entities": {
118 //      "location": [
119 //        {
120 //          "confidence": 0.98,
121 //          "raw": "227 rue de bercy paris",
122 //          "place": "ChIJjWtmOwNy5kcRTfOJS7ErxCk",
123 //          "type": "street_address",
124 //          "lng": 2.369777,
125 //          "lat": 48.8464993,
126 //          "formatted": "227 Rue de Bercy, 75012 Paris-12E-Arrondissement, France"
127 //        }
128 //      ]
129 //    },
130 //    "language": "fr"
131 //  }
132 //}
133     private static final ObjectMapper mapper = new ObjectMapper();
134     
135     @Override
136     protected void service( HttpServletRequest request, HttpServletResponse response )
137         throws ServletException, IOException
138     {
139         String strBody = IOUtils.toString(request.getReader());
140         AppLogService.info ("Got request:" + strBody);
141         JsonNode actualObj = mapper.readTree(strBody);
142         String strConversionId = actualObj.path("conversation").get("conversation_id").asText();
143         String strDate = actualObj.path("conversation").path("memory").path("date").get("iso").asText();
144         String strDateSql = strDate.substring(0, 10);
145         HttpAccess httpAccess = new HttpAccess(  );
146         Map<String, Object> responseJson = new HashMap<>();
147         List<Object> messages = new ArrayList<>();
148         responseJson.put("messages", messages);
149 
150         Map<String, Object> message = new HashMap<>();
151         messages.add(message);
152 
153         List<NoFeesDay> listNoFeesDays =  NoFeesDayHome.getNoFeesDaysList();
154         String strNoFeeDays = listNoFeesDays.stream()
155             .map(it -> it.getDate().toString() )
156             .collect(Collectors.joining(", "));
157         boolean isEqual = listNoFeesDays.stream().anyMatch(it -> {
158             return it.getDate().toString().equals(strDateSql);
159         });
160 
161         message.put("type", "text");
162         message.put("content", "List des jours fériés : " + strNoFeeDays);
163 
164         message = new HashMap<>();
165         messages.add(message);
166         message.put("type", "text");
167         message.put("content", isEqual ? "Donc oui, c'est gratuit !" : "Donc non, c'est payant...");
168 
169         String strResponseJson = mapper.writeValueAsString( responseJson );
170 
171         Map<String, String> headers = new HashMap<>();
172         String strToken = AppPropertiesService.getProperty( PROPERTY_TOKEN );
173         headers.put( "Authorization", "Token " + strToken);
174 
175 
176         Map<String, String> headersResponse = new HashMap<>();
177         try {
178             //example output
179             //curl -H "Content-type: application/json" -H "Authorization: Token 10791544c2df29868656179a4ba523bb" -XPOST 'https://api.recast.ai/connect/v1/conversations/4d07d6a0-8faa-4d87-9e43-d238683ab667/messages' -d '{"messages": [{ "type": "text", "content": "SEAGULS !"}]}'
180             String strResponse = httpAccess.doPostJSON(
181                     "https://api.recast.ai/connect/v1/conversations/" + strConversionId + "/messages",
182                     strResponseJson, headers, headersResponse);
183             AppLogService.info ("Got reponse " + strResponse) ;
184         } catch (HttpAccessException e) {
185             AppLogService.error ("Error posting message to conversion " + strBody, e);
186 
187         }
188 
189         Map<String, Object> hookResponse = new HashMap<>();
190         Map<String, Object> newMemory = mapper.convertValue(actualObj.path("conversation").get("memory"),  Map.class);
191         newMemory.put("isfreeday", isEqual);
192         hookResponse.put("memory", newMemory);
193         hookResponse.put("memory", newMemory);
194         hookResponse.put("messages", messages);
195 
196         String strFullResponse = mapper.writeValueAsString(hookResponse);
197         AppLogService.info( "Full hook response : " + strFullResponse );
198         response.setHeader( "Content-Type", "application/json" );
199         response.getWriter().print(strFullResponse);
200     }
201 }