Showing
1 changed file
with
193 additions
and
64 deletions
... | @@ -2,46 +2,147 @@ var express = require('express'); | ... | @@ -2,46 +2,147 @@ var express = require('express'); |
2 | const request = require('request'); | 2 | const request = require('request'); |
3 | const TARGET_URL = 'https://api.line.me/v2/bot/message/reply' | 3 | const TARGET_URL = 'https://api.line.me/v2/bot/message/reply' |
4 | const TOKEN = 'w5i8sURqF5bof6DWeB87n+oCeWrYaFf7a5YZzfzN1jeITIlZ3PcOmZRcdGCo/djTuHhNxybfJ69y7Jex+7tipBNRynngfyWX9CK1L3EupuhnX8rubeCmJda7HvsQWXVo8ZDcwl2aLwXsE3kiYF2qEwdB04t89/1O/w1cDnyilFU=' | 4 | const TOKEN = 'w5i8sURqF5bof6DWeB87n+oCeWrYaFf7a5YZzfzN1jeITIlZ3PcOmZRcdGCo/djTuHhNxybfJ69y7Jex+7tipBNRynngfyWX9CK1L3EupuhnX8rubeCmJda7HvsQWXVo8ZDcwl2aLwXsE3kiYF2qEwdB04t89/1O/w1cDnyilFU=' |
5 | +const SECRET = 'b0b4501ebc2813a2b0e586293a35b466' | ||
5 | const fs = require('fs'); | 6 | const fs = require('fs'); |
6 | const path = require('path'); | 7 | const path = require('path'); |
7 | const HTTPS = require('https'); | 8 | const HTTPS = require('https'); |
8 | const domain = "www.osstest237.ml" | 9 | const domain = "www.osstest237.ml" |
9 | const sslport = 23023; | 10 | const sslport = 23023; |
11 | +const line = require('@line/bot-sdk'); | ||
10 | 12 | ||
11 | const bodyParser = require('body-parser'); | 13 | const bodyParser = require('body-parser'); |
14 | +const { assert } = require('console'); | ||
12 | var app = express(); | 15 | var app = express(); |
13 | app.use(bodyParser.json()); | 16 | app.use(bodyParser.json()); |
14 | 17 | ||
15 | var usingMessage = '' | 18 | var usingMessage = '' |
16 | - | 19 | +var content_id = '' |
17 | app.post('/hook', function (req, res) { | 20 | app.post('/hook', function (req, res) { |
18 | 21 | ||
19 | var eventObj = req.body.events[0]; | 22 | var eventObj = req.body.events[0]; |
20 | - // var source = eventObj.source; | ||
21 | - // var message = eventObj.message; | ||
22 | var text = eventObj.message.text; | 23 | var text = eventObj.message.text; |
23 | 24 | ||
24 | // request log | 25 | // request log |
26 | + if (!(eventObj.message.type == 'image')) { | ||
25 | console.log('======================', new Date() ,'======================'); | 27 | console.log('======================', new Date() ,'======================'); |
26 | console.log('[request]', req.body); | 28 | console.log('[request]', req.body); |
27 | console.log('[request source] ', eventObj.source); | 29 | console.log('[request source] ', eventObj.source); |
28 | console.log('[request message]', eventObj.message); | 30 | console.log('[request message]', eventObj.message); |
31 | + } | ||
32 | + | ||
33 | + if (eventObj.message.type == 'location') { | ||
29 | 34 | ||
30 | - if (text == 'Cfr:Yes') { | 35 | + //위치 받아서 맛집 추천해주는 함수 |
36 | + | ||
37 | + RecommendationResult(eventObj.replyToken); | ||
38 | + res.sendStatus(200); | ||
39 | + } else if (text == 'Cfr:Yes') { | ||
31 | QuickReplyCfrYes(eventObj.replyToken); | 40 | QuickReplyCfrYes(eventObj.replyToken); |
32 | res.sendStatus(200); | 41 | res.sendStatus(200); |
33 | } else if (text == 'Cfr:No') { | 42 | } else if (text == 'Cfr:No') { |
34 | QuickReplyCfrNo(eventObj.replyToken); | 43 | QuickReplyCfrNo(eventObj.replyToken); |
35 | res.sendStatus(200); | 44 | res.sendStatus(200); |
36 | - } else if (eventObj.message.type == 'image') { | 45 | + } else if (text == '랜덤 추천' || text == '위치 기반 추천') { |
37 | - console.log('image url: ', eventObj.message.contentProvider); | 46 | + if (text == '랜덤 추천') { |
38 | - console.log('image url: ', eventObj.message.originalContentUrl); | 47 | + |
39 | - console.log('image url: ', eventObj.message.previewImageUrl); | 48 | + //랜덤으로 맛집 추천해주는 함수 |
40 | - console.log('id:', eventObj.message.id); | 49 | + |
50 | + RecommendationResult(eventObj.replyToken); | ||
41 | res.sendStatus(200); | 51 | res.sendStatus(200); |
42 | } | 52 | } |
43 | else { | 53 | else { |
54 | + SendingLocation(eventObj.replyToken); | ||
55 | + res.sendStatus(200); | ||
56 | + } | ||
57 | + } else if (eventObj.message.type == 'image') { | ||
58 | + content_id = eventObj.message.id; | ||
59 | + const downloadPath = path.join(__dirname, `${content_id}.jpg`); | ||
60 | + downloadContent(content_id, downloadPath); | ||
61 | + | ||
62 | + //사진으로 얼굴 인식해주는 함수 | ||
63 | + | ||
64 | + SendingLocation(eventObj.replyToken); | ||
65 | + res.sendStatus(200); | ||
66 | + } else { | ||
44 | usingMessage = text; | 67 | usingMessage = text; |
68 | + initReply(eventObj.replyToken); | ||
69 | + res.sendStatus(200); | ||
70 | + } | ||
71 | + | ||
72 | +}); | ||
73 | + | ||
74 | +const quickReplyLocation = { | ||
75 | + "items": [ | ||
76 | + { | ||
77 | + "type": "action", | ||
78 | + "action": { | ||
79 | + "type": "location", | ||
80 | + "label": "위치 입력" | ||
81 | + } | ||
82 | + } | ||
83 | + ] | ||
84 | +}; | ||
85 | + | ||
86 | +const quickReplyCfrYes = { | ||
87 | + "items": [ | ||
88 | + { | ||
89 | + "type": "action", | ||
90 | + "action": { | ||
91 | + "type": "cameraRoll", | ||
92 | + "label": "사진 가져오기" | ||
93 | + } | ||
94 | + }, | ||
95 | + { | ||
96 | + "type": "action", | ||
97 | + "action": { | ||
98 | + "type": "camera", | ||
99 | + "label": "사진 찍기" | ||
100 | + } | ||
101 | + }, | ||
102 | + ] | ||
103 | + }; | ||
104 | + | ||
105 | +const quickReplyCfrNo = { | ||
106 | + items: [ | ||
107 | + /* | ||
108 | + { | ||
109 | + "type": "action", | ||
110 | + "action": { | ||
111 | + "type": "message", | ||
112 | + "label": "weather", | ||
113 | + "text": "날씨" | ||
114 | + } | ||
115 | + }, | ||
116 | + { | ||
117 | + "type": "action", | ||
118 | + "action": { | ||
119 | + "type": "message", | ||
120 | + "label": "menu", | ||
121 | + "text": "메뉴" | ||
122 | + } | ||
123 | + }, | ||
124 | + */ | ||
125 | + { | ||
126 | + "type": "action", | ||
127 | + "action": { | ||
128 | + "type": "message", | ||
129 | + "label": "random", | ||
130 | + "text": "랜덤 추천" | ||
131 | + } | ||
132 | + }, | ||
133 | + { | ||
134 | + "type": "action", | ||
135 | + "action": { | ||
136 | + "type": "message", | ||
137 | + "label": "location", | ||
138 | + "text": "위치 기반 추천" | ||
139 | + } | ||
140 | + } | ||
141 | + ] | ||
142 | + }; | ||
143 | + | ||
144 | +//기본 reply | ||
145 | +function initReply (replyToken) { | ||
45 | request.post( | 146 | request.post( |
46 | { | 147 | { |
47 | url: TARGET_URL, | 148 | url: TARGET_URL, |
... | @@ -49,7 +150,7 @@ app.post('/hook', function (req, res) { | ... | @@ -49,7 +150,7 @@ app.post('/hook', function (req, res) { |
49 | 'Authorization': `Bearer ${TOKEN}` | 150 | 'Authorization': `Bearer ${TOKEN}` |
50 | }, | 151 | }, |
51 | json: { | 152 | json: { |
52 | - "replyToken":eventObj.replyToken, | 153 | + "replyToken":replyToken, |
53 | "messages":[ | 154 | "messages":[ |
54 | { | 155 | { |
55 | "type": "sticker", | 156 | "type": "sticker", |
... | @@ -79,43 +180,38 @@ app.post('/hook', function (req, res) { | ... | @@ -79,43 +180,38 @@ app.post('/hook', function (req, res) { |
79 | } | 180 | } |
80 | ] | 181 | ] |
81 | } | 182 | } |
82 | - }, | 183 | + } |
83 | ] | 184 | ] |
84 | } | 185 | } |
85 | },(error, response, body) => { | 186 | },(error, response, body) => { |
86 | console.log(body) | 187 | console.log(body) |
87 | }); | 188 | }); |
88 | - res.sendStatus(200); | 189 | +} |
89 | - } | ||
90 | - | ||
91 | -}); | ||
92 | 190 | ||
93 | -const quickReplyYes = { | 191 | +//위치 입력 reply |
94 | - "items": [ | 192 | +function SendingLocation(replyToken) { |
95 | - { | 193 | + request.post( |
96 | - "type": "action", | ||
97 | - "action": { | ||
98 | - "type": "cameraRoll", | ||
99 | - "label": "사진 가져오기" | ||
100 | - } | ||
101 | - }, | ||
102 | { | 194 | { |
103 | - "type": "action", | 195 | + url: TARGET_URL, |
104 | - "action": { | 196 | + headers: { |
105 | - "type": "camera", | 197 | + 'Authorization': `Bearer ${TOKEN}` |
106 | - "label": "사진 찍기" | ||
107 | - } | ||
108 | }, | 198 | }, |
199 | + json: { | ||
200 | + "replyToken": replyToken, | ||
201 | + "messages": [ | ||
109 | { | 202 | { |
110 | - "type": "action", | 203 | + "type": "text", |
111 | - "action": { | 204 | + "text": "위치를 입력해주세요.", |
112 | - "type": "location", | 205 | + "quickReply": quickReplyLocation |
113 | - "label": "위치" | ||
114 | - } | ||
115 | } | 206 | } |
116 | ] | 207 | ] |
117 | - }; | 208 | + } |
209 | + },(error, response, body) => { | ||
210 | + console.log(body) | ||
211 | + }); | ||
212 | +} | ||
118 | 213 | ||
214 | +//cfr 이용할 때 reply | ||
119 | function QuickReplyCfrYes(replyToken) { | 215 | function QuickReplyCfrYes(replyToken) { |
120 | request.post( | 216 | request.post( |
121 | { | 217 | { |
... | @@ -128,8 +224,8 @@ function QuickReplyCfrYes(replyToken) { | ... | @@ -128,8 +224,8 @@ function QuickReplyCfrYes(replyToken) { |
128 | "messages": [ | 224 | "messages": [ |
129 | { | 225 | { |
130 | "type": "text", | 226 | "type": "text", |
131 | - "text": "사진 입력", | 227 | + "text": "사진을 입력해주세요.", |
132 | - "quickReply": quickReplyYes | 228 | + "quickReply": quickReplyCfrYes |
133 | } | 229 | } |
134 | ] | 230 | ] |
135 | } | 231 | } |
... | @@ -138,36 +234,30 @@ function QuickReplyCfrYes(replyToken) { | ... | @@ -138,36 +234,30 @@ function QuickReplyCfrYes(replyToken) { |
138 | }); | 234 | }); |
139 | } | 235 | } |
140 | 236 | ||
141 | -const quickReplyNo = { | 237 | +//cfr 이용하지 않을 때 reply |
142 | - items: [ | 238 | +function QuickReplyCfrNo (replyToken) { |
143 | - { | 239 | + request.post( |
144 | - "type": "action", | ||
145 | - "action": { | ||
146 | - "type": "message", | ||
147 | - "label": "weather", | ||
148 | - "text": "날씨" | ||
149 | - } | ||
150 | - }, | ||
151 | { | 240 | { |
152 | - "type": "action", | 241 | + url: TARGET_URL, |
153 | - "action": { | 242 | + headers: { |
154 | - "type": "message", | 243 | + 'Authorization': `Bearer ${TOKEN}` |
155 | - "label": "menu", | ||
156 | - "text": "메뉴" | ||
157 | - } | ||
158 | }, | 244 | }, |
245 | + json: { | ||
246 | + "replyToken": replyToken, | ||
247 | + "messages": [ | ||
159 | { | 248 | { |
160 | - "type": "action", | 249 | + "type": "text", |
161 | - "action": { | 250 | + "text": "랜덤 추천 옵션을 선택해주세요.", |
162 | - "type": "message", | 251 | + "quickReply": quickReplyCfrNo |
163 | - "label": "random", | ||
164 | - "text": "랜덤" | ||
165 | - } | ||
166 | } | 252 | } |
167 | ] | 253 | ] |
168 | - }; | 254 | + } |
255 | + },(error, response, body) => { | ||
256 | + console.log(body) | ||
257 | + }); | ||
258 | +} | ||
169 | 259 | ||
170 | -function QuickReplyCfrNo (replyToken) { | 260 | +function RecommendationResult(replyToken) { |
171 | request.post( | 261 | request.post( |
172 | { | 262 | { |
173 | url: TARGET_URL, | 263 | url: TARGET_URL, |
... | @@ -178,9 +268,30 @@ function QuickReplyCfrNo (replyToken) { | ... | @@ -178,9 +268,30 @@ function QuickReplyCfrNo (replyToken) { |
178 | "replyToken": replyToken, | 268 | "replyToken": replyToken, |
179 | "messages": [ | 269 | "messages": [ |
180 | { | 270 | { |
271 | + "type": "imagemap", | ||
272 | + // 이미지 불러올 수 없습니다 뜸 | ||
273 | + "baseUrl": "https://www.flaticon.com/free-icon/food-store_2934069?term=restaurant&page=1&position=7&related_item_id=2934069", | ||
274 | + "altText": "이미지를 누르시면 해당 가게로 이동합니다.", | ||
275 | + "baseSize": { | ||
276 | + "width": 1040, | ||
277 | + "height": 1040 | ||
278 | + }, | ||
279 | + "actions": [ | ||
280 | + { | ||
281 | + "type": "uri", | ||
282 | + "linkUri": `${link}`, // 가게 링크 | ||
283 | + "area": { | ||
284 | + "x":0, | ||
285 | + "y":0, | ||
286 | + "width":1040, | ||
287 | + "height":1040 | ||
288 | + } | ||
289 | + } | ||
290 | + ] | ||
291 | + }, | ||
292 | + { | ||
181 | "type": "text", | 293 | "type": "text", |
182 | - "text": "맛집 추천 옵션 선택", | 294 | + "text": "기타 결과 출력" // 정보 수정 |
183 | - "quickReply": quickReplyNo | ||
184 | } | 295 | } |
185 | ] | 296 | ] |
186 | } | 297 | } |
... | @@ -189,6 +300,24 @@ function QuickReplyCfrNo (replyToken) { | ... | @@ -189,6 +300,24 @@ function QuickReplyCfrNo (replyToken) { |
189 | }); | 300 | }); |
190 | } | 301 | } |
191 | 302 | ||
303 | +//사용자가 보낸 사진 저장 | ||
304 | +const config = ({ | ||
305 | + channelAccessToken: `${TOKEN}`, | ||
306 | + channelSecret: `${SECRET}`, | ||
307 | +}); | ||
308 | + | ||
309 | +const client = new line.Client(config); | ||
310 | +function downloadContent(messageId, downloadPath) { | ||
311 | + return client.getMessageContent(messageId) | ||
312 | + .then((stream) => new Promise((resolve, reject) => { | ||
313 | + const writable = fs.createWriteStream(downloadPath); | ||
314 | + stream.pipe(writable); | ||
315 | + stream.on('end', () => resolve(downloadPath)); | ||
316 | + stream.on('error', reject); | ||
317 | + })); | ||
318 | +} | ||
319 | + | ||
320 | + | ||
192 | try { | 321 | try { |
193 | const option = { | 322 | const option = { |
194 | ca: fs.readFileSync('/etc/letsencrypt/live/' + domain +'/fullchain.pem'), | 323 | ca: fs.readFileSync('/etc/letsencrypt/live/' + domain +'/fullchain.pem'), |
... | @@ -203,4 +332,4 @@ try { | ... | @@ -203,4 +332,4 @@ try { |
203 | } catch (error) { | 332 | } catch (error) { |
204 | console.log('[HTTPS] HTTPS 오류가 발생하였습니다. HTTPS 서버는 실행되지 않습니다.'); | 333 | console.log('[HTTPS] HTTPS 오류가 발생하였습니다. HTTPS 서버는 실행되지 않습니다.'); |
205 | console.log(error); | 334 | console.log(error); |
206 | - } | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
335 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
-
Please register or login to post a comment