Showing
1 changed file
with
335 additions
and
0 deletions
app.js
0 → 100644
| 1 | +const express = require('express'); | ||
| 2 | +const request = require('request'); | ||
| 3 | +const convert = require('xml-js'); | ||
| 4 | + | ||
| 5 | +const TARGET_URL = 'https://api.line.me/v2/bot/message/reply' | ||
| 6 | +const TOKEN = 'z5iy5sMU1W4xZAlwvn0/5x4U+4ZsqI0hKO1ZZNFxUGlNzGBjFg2D1u6/Ij5C/Sbkncx3hyYg7Nfz5JnMD8BG/9Z3TEEHPvy1A2XhkPKs04v0/n6TjH1A3e9X23zYdYmNSGyPn2hDGglgm2p3YmtLSwdB04t89/1O/w1cDnyilFU=' | ||
| 7 | + | ||
| 8 | +var ProductCategoryName ; | ||
| 9 | +var first_url = 'http://apis.data.go.kr/1470000/FoodAdtvInfoService/getFoodAdtvInfoList'; | ||
| 10 | +var first_key ='ofY2ppOq5kBqT5jYPaGsW%2BEy7OR5a1bf5Z9PHvqNKvwO5DSCaU2x2qCj%2FoXnuB1YVbMTlErkHWSMEsR5b7isrw%3D%3D'; | ||
| 11 | + | ||
| 12 | +var second_url ='http://openapi.foodsafetykorea.go.kr/api'; | ||
| 13 | +var second_key ='f8ce3271a2dc4decb83b'; | ||
| 14 | +var filetype ='json'; | ||
| 15 | +var startIndex = 1; | ||
| 16 | +var endIndex = 5; | ||
| 17 | +var simpleResult = true; | ||
| 18 | + | ||
| 19 | + | ||
| 20 | +const fs = require('fs'); | ||
| 21 | +const path = require('path'); | ||
| 22 | +const HTTPS = require('https'); | ||
| 23 | +const domain = "www.foodbot2020.ml" | ||
| 24 | +const sslport = 23023; | ||
| 25 | +const bodyParser = require('body-parser'); | ||
| 26 | +var app = express(); | ||
| 27 | +app.use(bodyParser.json()); | ||
| 28 | + | ||
| 29 | + | ||
| 30 | +function sendOneLineMessage(eventObj, line) | ||
| 31 | +{ | ||
| 32 | + request.post({ | ||
| 33 | + url: TARGET_URL, | ||
| 34 | + headers:{ | ||
| 35 | + 'Authorization': `Bearer ${TOKEN}` | ||
| 36 | + }, | ||
| 37 | + json:{ | ||
| 38 | + "replyToken":eventObj.replyToken, | ||
| 39 | + "messages" :[ | ||
| 40 | + { | ||
| 41 | + "type":"text", | ||
| 42 | + "text": line | ||
| 43 | + } | ||
| 44 | + ] | ||
| 45 | + } | ||
| 46 | + },(error,response,body)=>{ | ||
| 47 | + console.log(body) | ||
| 48 | + }); | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +function helloAndErrorMsg(eventObj){ | ||
| 52 | + request.post({ | ||
| 53 | + url: TARGET_URL, | ||
| 54 | + headers:{ | ||
| 55 | + 'Authorization': `Bearer ${TOKEN}` | ||
| 56 | + }, | ||
| 57 | + json:{ | ||
| 58 | + "replyToken":eventObj.replyToken, | ||
| 59 | + "messages" :[ | ||
| 60 | + { | ||
| 61 | + "type":"text", | ||
| 62 | + "text": "안녕하세요, 식품첨가물 정보를 알려드립니다." | ||
| 63 | + }, | ||
| 64 | + { | ||
| 65 | + "type":"text", | ||
| 66 | + "text": "정확한 식품명을 기입해주세요.\n안내가 필요하신 경우 '안내'라고 입력해주세요." | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + ] | ||
| 70 | + } | ||
| 71 | + },(error,response,body)=>{ | ||
| 72 | + console.log(body) | ||
| 73 | + }); | ||
| 74 | +} | ||
| 75 | + | ||
| 76 | +function prdNameNotFound(eventObj){ | ||
| 77 | + request.post({ | ||
| 78 | + url: TARGET_URL, | ||
| 79 | + headers:{ | ||
| 80 | + 'Authorization': `Bearer ${TOKEN}` | ||
| 81 | + }, | ||
| 82 | + json:{ | ||
| 83 | + "replyToken":eventObj.replyToken, | ||
| 84 | + "messages" :[ | ||
| 85 | + { | ||
| 86 | + "type":"text", | ||
| 87 | + "text": "죄송합니다. \n해당 식품의 정보를 찾을 수 없습니다.\n" | ||
| 88 | + +"정확한 식품명을 기입해주세요.\n" | ||
| 89 | + +"사용 안내가 필요하신 경우 '안내'라고 입력해주세요." | ||
| 90 | + }, | ||
| 91 | + { | ||
| 92 | + "type": "sticker", | ||
| 93 | + "packageId": "11537", | ||
| 94 | + "stickerId": "52002770" | ||
| 95 | + } | ||
| 96 | + ] | ||
| 97 | + } | ||
| 98 | + },(error,response,body)=>{ | ||
| 99 | + console.log(body) | ||
| 100 | + }); | ||
| 101 | +} | ||
| 102 | + | ||
| 103 | +function instruction(eventObj){ | ||
| 104 | + request.post({ | ||
| 105 | + url: TARGET_URL, | ||
| 106 | + headers:{ | ||
| 107 | + 'Authorization': `Bearer ${TOKEN}` | ||
| 108 | + }, | ||
| 109 | + json:{ | ||
| 110 | + "replyToken":eventObj.replyToken, | ||
| 111 | + "messages" :[ | ||
| 112 | + { | ||
| 113 | + "type":"text", | ||
| 114 | + "text": "식품첨가물 정보 알리미 사용 안내입니다." | ||
| 115 | + }, | ||
| 116 | + { | ||
| 117 | + "type":"text", | ||
| 118 | + "text": "사용방법\n" | ||
| 119 | + +"1. 식품명을 '정확하게' 입력해주세요.\n" | ||
| 120 | + +"2. 입력하신 식품명이 식약처 데이터베이스에 존재하는 경우,\n" | ||
| 121 | + +"식품 유형과 첨가물, 첨가물 안전정보에 대해 받아보실 수 있습니다.\n" | ||
| 122 | + +"3. '모드' 명령어를 통해 결과 간단히 보기/자세히 보기 모드를 전환할 수 있습니다.\n" | ||
| 123 | + +"4. 결과 간단히 보기 모드에서는 첨가물과 식품유형을 확인하실 수 있습니다.\n" | ||
| 124 | + +"5. 자세한 결과 보기 모드에서는 위 정보 및 첨가물 안전정보를 확인하실 수 있습니다." | ||
| 125 | + }, | ||
| 126 | + { | ||
| 127 | + "type":"text", | ||
| 128 | + "text": "식품첨가물 정보 알리미가 제공하는 식품첨가물 정보는 식품의약품안전처의 공신력 있는 자료를 바탕으로 만들어졌습니다." | ||
| 129 | + }, | ||
| 130 | + | ||
| 131 | + ] | ||
| 132 | + } | ||
| 133 | + },(error,response,body)=>{ | ||
| 134 | + console.log(body) | ||
| 135 | + }); | ||
| 136 | +} | ||
| 137 | + | ||
| 138 | + | ||
| 139 | +app.post('/hook', function (req, res) { | ||
| 140 | + | ||
| 141 | + var eventObj = req.body.events[0]; | ||
| 142 | + var source = eventObj.source; | ||
| 143 | + var message = eventObj.message; | ||
| 144 | + var message_text = message.text; | ||
| 145 | + | ||
| 146 | + // request log | ||
| 147 | + console.log('======================', new Date() ,'======================'); | ||
| 148 | + console.log('[request]', req.body); | ||
| 149 | + console.log('[request source] ', eventObj.source); | ||
| 150 | + console.log('[request message]', eventObj.message); | ||
| 151 | + | ||
| 152 | + if(message_text =='안내'){ | ||
| 153 | + console.log('[안내 출력]'); | ||
| 154 | + instruction(eventObj); | ||
| 155 | + } | ||
| 156 | + else if(message_text == '모드') | ||
| 157 | + { | ||
| 158 | + console.log("모드를 변경합니다") | ||
| 159 | + simpleResult = !simpleResult; | ||
| 160 | + if(simpleResult) | ||
| 161 | + { | ||
| 162 | + var msg = "결과 간단히 보기 모드 입니다."; | ||
| 163 | + } | ||
| 164 | + else | ||
| 165 | + { | ||
| 166 | + var msg = "자세한 결과 보기 모드입니다. 첨가물의 정보를 확인하실 수 있습니다." | ||
| 167 | + } | ||
| 168 | + | ||
| 169 | + sendOneLineMessage(eventObj, msg); | ||
| 170 | + } | ||
| 171 | + else{ | ||
| 172 | + getfoodinfoByPdtName(eventObj, message_text); | ||
| 173 | + } | ||
| 174 | + | ||
| 175 | + res.sendStatus(200); | ||
| 176 | +}); | ||
| 177 | + | ||
| 178 | +function getfoodinfoByPdtName(eventObj, prdName) | ||
| 179 | +{ | ||
| 180 | + var queryParams = '/' + encodeURIComponent(second_key); | ||
| 181 | + queryParams += '/' + encodeURIComponent('C002'); | ||
| 182 | + queryParams += '/' + encodeURIComponent(filetype); | ||
| 183 | + queryParams += '/' + encodeURIComponent(startIndex); | ||
| 184 | + queryParams += '/' + encodeURIComponent(endIndex); | ||
| 185 | + queryParams += '/' + encodeURIComponent('PRDLST_NM') + '=' + encodeURIComponent(prdName); | ||
| 186 | + | ||
| 187 | + request({ | ||
| 188 | + url: second_url + queryParams, | ||
| 189 | + method: 'GET' | ||
| 190 | + }, function (error, response, body) { | ||
| 191 | + if(error){ | ||
| 192 | + helloAndErrorMsg(oventObj); | ||
| 193 | + console.log('에러입니다.') | ||
| 194 | + } | ||
| 195 | + else{ | ||
| 196 | + var result2 =body; | ||
| 197 | + var resObj2 = eval("("+result2+")"); | ||
| 198 | + var resultCode2 = resObj2.C002.RESULT.CODE; | ||
| 199 | + | ||
| 200 | + console.log("[입력] : ", prdName); | ||
| 201 | + console.log("식품명으로 식품유형과 첨가물 정보를 받아옵니다..."); | ||
| 202 | + | ||
| 203 | + if(resultCode2 == "INFO-200")//'유효하지 않은 입력' | ||
| 204 | + { | ||
| 205 | + console.log("존재하지 않는 식품명입니다."); | ||
| 206 | + prdNameNotFound(eventObj); | ||
| 207 | + } | ||
| 208 | + else if(response.statusCode ==200) | ||
| 209 | + { // 유효한 입력 | ||
| 210 | + var ProductCategory = resObj2.C002.row[0].PRDLST_DCNM; | ||
| 211 | + // 첨가물정보 API가 입력으로 받을 parameter | ||
| 212 | + | ||
| 213 | + //console.log(result); | ||
| 214 | + console.log("성공적으로 정보를 받았습니다.") | ||
| 215 | + console.log("[처리결과] ",resObj2.C002.RESULT.MSG); | ||
| 216 | + console.log("[유형] ", ProductCategory); | ||
| 217 | + console.log("[첨가물] ",resObj2.C002.row[0].RAWMTRL_NM ) | ||
| 218 | + | ||
| 219 | + | ||
| 220 | + | ||
| 221 | + // 다음 API호출 | ||
| 222 | + var queryParams = '?' + encodeURIComponent('ServiceKey') + '=' +first_key; | ||
| 223 | + queryParams += '&' + encodeURIComponent('pc_kor_nm') + '=' + encodeURIComponent(ProductCategory); | ||
| 224 | + | ||
| 225 | + request({ | ||
| 226 | + url: first_url + queryParams, | ||
| 227 | + method: 'GET' | ||
| 228 | + }, function (error, response, body) { | ||
| 229 | + if(error){ | ||
| 230 | + console.log('에러입니다.') | ||
| 231 | + } | ||
| 232 | + else if(response.statusCode ==200) | ||
| 233 | + { | ||
| 234 | + var result1 =body; | ||
| 235 | + var xmltojson = convert.xml2json(result1,{compact:true,spaces:4}); | ||
| 236 | + var resObj1 = eval("("+xmltojson+")"); | ||
| 237 | + var resultItems = resObj1.response.body.items; | ||
| 238 | + | ||
| 239 | + if(Object.keys(resultItems).length != 0) | ||
| 240 | + { | ||
| 241 | + console.log("valid input : 식품 첨가물 정보를 받아옵니다."); | ||
| 242 | + | ||
| 243 | + var responseMessage ='[ ' + resultItems.item[0].PC_KOR_NM._text + ' ]\n'; | ||
| 244 | + //하나의 카테고리에 대한 정보만 받는다고 가정해 반복문 밖으로 뺐습니다. | ||
| 245 | + | ||
| 246 | + for(var i=0 ; i < resultItems.item.length; i ++) | ||
| 247 | + { | ||
| 248 | + //var responseMessage ='[ ' + resultItems.item[i].PC_KOR_NM._text + ' ]\n'; | ||
| 249 | + var addictive = resultItems.item[i].T_KOR_NM._text; | ||
| 250 | + var specVal = resultItems.item[i].SPEC_VAL_SUMUP._text; | ||
| 251 | + var yn = resultItems.item[i].INJRY_YN._text; | ||
| 252 | + responseMessage += addictive + ' : ' + specVal + '['+yn+']'+ '\n'; | ||
| 253 | + } | ||
| 254 | + | ||
| 255 | + | ||
| 256 | + var replyment = | ||
| 257 | + { | ||
| 258 | + "replyToken":eventObj.replyToken, | ||
| 259 | + "messages":[ | ||
| 260 | + { | ||
| 261 | + "type":"text", | ||
| 262 | + "text":prdName +"에 대해 알아볼까요?" | ||
| 263 | + }, | ||
| 264 | + { | ||
| 265 | + "type":"text", | ||
| 266 | + "text":"[유형]\n" + ProductCategory | ||
| 267 | + }, | ||
| 268 | + { | ||
| 269 | + "type":"text", | ||
| 270 | + "text":"[첨가물]\n" + resObj2.C002.row[0].RAWMTRL_NM | ||
| 271 | + } | ||
| 272 | + ] | ||
| 273 | + } | ||
| 274 | + | ||
| 275 | + if(! simpleResult) | ||
| 276 | + { | ||
| 277 | + var moreInfo = | ||
| 278 | + { | ||
| 279 | + "type":"text", | ||
| 280 | + "text":"더 자세한 첨가물 안전 정보\n" +responseMessage | ||
| 281 | + }; | ||
| 282 | + replyment.messages.push(moreInfo); | ||
| 283 | + } | ||
| 284 | + | ||
| 285 | + //메시지 전송 | ||
| 286 | + request.post( | ||
| 287 | + { | ||
| 288 | + url: TARGET_URL, | ||
| 289 | + headers: { | ||
| 290 | + 'Authorization': `Bearer ${TOKEN}` | ||
| 291 | + }, | ||
| 292 | + json: replyment | ||
| 293 | + },(error, response, body) => { | ||
| 294 | + console.log(body) | ||
| 295 | + }); | ||
| 296 | + } | ||
| 297 | + else | ||
| 298 | + { | ||
| 299 | + console.log("Invalid Input : 에러 메시지 전송"); | ||
| 300 | + var responseMessage = "잘못 된 입력입니다. 라벨의 식품유형을 확인하고 다시 입력해주세요."; | ||
| 301 | + } | ||
| 302 | + console.log('[responese message]',responseMessage); | ||
| 303 | + | ||
| 304 | + } | ||
| 305 | + | ||
| 306 | + }); | ||
| 307 | + } | ||
| 308 | + else | ||
| 309 | + { | ||
| 310 | + console.log("입력 이외의 오류가 발생하였습니다."); | ||
| 311 | + } | ||
| 312 | + } | ||
| 313 | + | ||
| 314 | + }); | ||
| 315 | + | ||
| 316 | +} | ||
| 317 | + | ||
| 318 | + | ||
| 319 | + | ||
| 320 | + | ||
| 321 | +try { | ||
| 322 | + const option = { | ||
| 323 | + ca: fs.readFileSync('/etc/letsencrypt/live/' + domain +'/fullchain.pem'), | ||
| 324 | + key: fs.readFileSync(path.resolve(process.cwd(), '/etc/letsencrypt/live/' + domain +'/privkey.pem'), 'utf8').toString(), | ||
| 325 | + cert: fs.readFileSync(path.resolve(process.cwd(), '/etc/letsencrypt/live/' + domain +'/cert.pem'), 'utf8').toString(), | ||
| 326 | + }; | ||
| 327 | + | ||
| 328 | + HTTPS.createServer(option, app).listen(sslport, () => { | ||
| 329 | + console.log(`[HTTPS] Server is started on port ${sslport}`); | ||
| 330 | + }); | ||
| 331 | + } catch (error) { | ||
| 332 | + console.log('[HTTPS] HTTPS 오류가 발생하였습니다. HTTPS 서버는 실행되지 않습니다.'); | ||
| 333 | + console.log(error); | ||
| 334 | + } | ||
| 335 | + | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
-
Please register or login to post a comment