Showing
1 changed file
with
217 additions
and
88 deletions
... | @@ -2,95 +2,88 @@ var express = require('express'); | ... | @@ -2,95 +2,88 @@ 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') { | ||
34 | + | ||
35 | + //위치 받아서 맛집 추천해주는 함수 | ||
29 | 36 | ||
30 | - if (text == 'Cfr:Yes') { | 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); |
45 | + } else if (text == '랜덤 추천' || text == '위치 기반 추천') { | ||
46 | + if (text == '랜덤 추천') { | ||
47 | + | ||
48 | + //랜덤으로 맛집 추천해주는 함수 | ||
49 | + | ||
50 | + RecommendationResult(eventObj.replyToken); | ||
51 | + res.sendStatus(200); | ||
52 | + } | ||
53 | + else { | ||
54 | + SendingLocation(eventObj.replyToken); | ||
55 | + res.sendStatus(200); | ||
56 | + } | ||
36 | } else if (eventObj.message.type == 'image') { | 57 | } else if (eventObj.message.type == 'image') { |
37 | - console.log('image url: ', eventObj.message.contentProvider); | 58 | + content_id = eventObj.message.id; |
38 | - console.log('image url: ', eventObj.message.originalContentUrl); | 59 | + const downloadPath = path.join(__dirname, `${content_id}.jpg`); |
39 | - console.log('image url: ', eventObj.message.previewImageUrl); | 60 | + downloadContent(content_id, downloadPath); |
40 | - console.log('id:', eventObj.message.id); | 61 | + |
62 | + //사진으로 얼굴 인식해주는 함수 | ||
63 | + | ||
64 | + SendingLocation(eventObj.replyToken); | ||
41 | res.sendStatus(200); | 65 | res.sendStatus(200); |
42 | - } | 66 | + } else { |
43 | - else { | ||
44 | usingMessage = text; | 67 | usingMessage = text; |
45 | - request.post( | 68 | + initReply(eventObj.replyToken); |
46 | - { | ||
47 | - url: TARGET_URL, | ||
48 | - headers: { | ||
49 | - 'Authorization': `Bearer ${TOKEN}` | ||
50 | - }, | ||
51 | - json: { | ||
52 | - "replyToken":eventObj.replyToken, | ||
53 | - "messages":[ | ||
54 | - { | ||
55 | - "type": "sticker", | ||
56 | - "packageId": "11537", | ||
57 | - "stickerId": "52002738" | ||
58 | - }, | ||
59 | - { | ||
60 | - "type": "text", | ||
61 | - "text": "안녕하세요.\nCFR을 이용한 경기도 맛집 추천봇입니다." | ||
62 | - }, | ||
63 | - { | ||
64 | - "type": "template", | ||
65 | - "altText": "얼굴 인식을 위해 사진을 가져오시겠습니까?", | ||
66 | - "template": { | ||
67 | - "type": "confirm", | ||
68 | - "text": "얼굴 인식을 위해 사진을 가져오시겠습니까?", | ||
69 | - "actions": [ | ||
70 | - { | ||
71 | - "type": "message", | ||
72 | - "label": "Cfr:Yes", | ||
73 | - "text": "Cfr:Yes" | ||
74 | - }, | ||
75 | - { | ||
76 | - "type": "message", | ||
77 | - "label": "Cfr:No", | ||
78 | - "text": "Cfr:No" | ||
79 | - } | ||
80 | - ] | ||
81 | - } | ||
82 | - }, | ||
83 | - ] | ||
84 | - } | ||
85 | - },(error, response, body) => { | ||
86 | - console.log(body) | ||
87 | - }); | ||
88 | res.sendStatus(200); | 69 | res.sendStatus(200); |
89 | } | 70 | } |
90 | 71 | ||
91 | }); | 72 | }); |
92 | 73 | ||
93 | -const quickReplyYes = { | 74 | +const quickReplyLocation = { |
75 | + "items": [ | ||
76 | + { | ||
77 | + "type": "action", | ||
78 | + "action": { | ||
79 | + "type": "location", | ||
80 | + "label": "위치 입력" | ||
81 | + } | ||
82 | + } | ||
83 | + ] | ||
84 | +}; | ||
85 | + | ||
86 | +const quickReplyCfrYes = { | ||
94 | "items": [ | 87 | "items": [ |
95 | { | 88 | { |
96 | "type": "action", | 89 | "type": "action", |
... | @@ -106,40 +99,12 @@ const quickReplyYes = { | ... | @@ -106,40 +99,12 @@ const quickReplyYes = { |
106 | "label": "사진 찍기" | 99 | "label": "사진 찍기" |
107 | } | 100 | } |
108 | }, | 101 | }, |
109 | - { | ||
110 | - "type": "action", | ||
111 | - "action": { | ||
112 | - "type": "location", | ||
113 | - "label": "위치" | ||
114 | - } | ||
115 | - } | ||
116 | ] | 102 | ] |
117 | }; | 103 | }; |
118 | 104 | ||
119 | -function QuickReplyCfrYes(replyToken) { | 105 | +const quickReplyCfrNo = { |
120 | - request.post( | ||
121 | - { | ||
122 | - url: TARGET_URL, | ||
123 | - headers: { | ||
124 | - 'Authorization': `Bearer ${TOKEN}` | ||
125 | - }, | ||
126 | - json: { | ||
127 | - "replyToken": replyToken, | ||
128 | - "messages": [ | ||
129 | - { | ||
130 | - "type": "text", | ||
131 | - "text": "사진 입력", | ||
132 | - "quickReply": quickReplyYes | ||
133 | - } | ||
134 | - ] | ||
135 | - } | ||
136 | - },(error, response, body) => { | ||
137 | - console.log(body) | ||
138 | - }); | ||
139 | -} | ||
140 | - | ||
141 | -const quickReplyNo = { | ||
142 | items: [ | 106 | items: [ |
107 | + /* | ||
143 | { | 108 | { |
144 | "type": "action", | 109 | "type": "action", |
145 | "action": { | 110 | "action": { |
... | @@ -156,17 +121,120 @@ const quickReplyNo = { | ... | @@ -156,17 +121,120 @@ const quickReplyNo = { |
156 | "text": "메뉴" | 121 | "text": "메뉴" |
157 | } | 122 | } |
158 | }, | 123 | }, |
124 | + */ | ||
159 | { | 125 | { |
160 | "type": "action", | 126 | "type": "action", |
161 | "action": { | 127 | "action": { |
162 | "type": "message", | 128 | "type": "message", |
163 | "label": "random", | 129 | "label": "random", |
164 | - "text": "랜덤" | 130 | + "text": "랜덤 추천" |
131 | + } | ||
132 | + }, | ||
133 | + { | ||
134 | + "type": "action", | ||
135 | + "action": { | ||
136 | + "type": "message", | ||
137 | + "label": "location", | ||
138 | + "text": "위치 기반 추천" | ||
165 | } | 139 | } |
166 | } | 140 | } |
167 | ] | 141 | ] |
168 | }; | 142 | }; |
169 | 143 | ||
144 | +//기본 reply | ||
145 | +function initReply (replyToken) { | ||
146 | + request.post( | ||
147 | + { | ||
148 | + url: TARGET_URL, | ||
149 | + headers: { | ||
150 | + 'Authorization': `Bearer ${TOKEN}` | ||
151 | + }, | ||
152 | + json: { | ||
153 | + "replyToken":replyToken, | ||
154 | + "messages":[ | ||
155 | + { | ||
156 | + "type": "sticker", | ||
157 | + "packageId": "11537", | ||
158 | + "stickerId": "52002738" | ||
159 | + }, | ||
160 | + { | ||
161 | + "type": "text", | ||
162 | + "text": "안녕하세요.\nCFR을 이용한 경기도 맛집 추천봇입니다." | ||
163 | + }, | ||
164 | + { | ||
165 | + "type": "template", | ||
166 | + "altText": "얼굴 인식을 위해 사진을 가져오시겠습니까?", | ||
167 | + "template": { | ||
168 | + "type": "confirm", | ||
169 | + "text": "얼굴 인식을 위해 사진을 가져오시겠습니까?", | ||
170 | + "actions": [ | ||
171 | + { | ||
172 | + "type": "message", | ||
173 | + "label": "Cfr:Yes", | ||
174 | + "text": "Cfr:Yes" | ||
175 | + }, | ||
176 | + { | ||
177 | + "type": "message", | ||
178 | + "label": "Cfr:No", | ||
179 | + "text": "Cfr:No" | ||
180 | + } | ||
181 | + ] | ||
182 | + } | ||
183 | + } | ||
184 | + ] | ||
185 | + } | ||
186 | + },(error, response, body) => { | ||
187 | + console.log(body) | ||
188 | + }); | ||
189 | +} | ||
190 | + | ||
191 | +//위치 입력 reply | ||
192 | +function SendingLocation(replyToken) { | ||
193 | + request.post( | ||
194 | + { | ||
195 | + url: TARGET_URL, | ||
196 | + headers: { | ||
197 | + 'Authorization': `Bearer ${TOKEN}` | ||
198 | + }, | ||
199 | + json: { | ||
200 | + "replyToken": replyToken, | ||
201 | + "messages": [ | ||
202 | + { | ||
203 | + "type": "text", | ||
204 | + "text": "위치를 입력해주세요.", | ||
205 | + "quickReply": quickReplyLocation | ||
206 | + } | ||
207 | + ] | ||
208 | + } | ||
209 | + },(error, response, body) => { | ||
210 | + console.log(body) | ||
211 | + }); | ||
212 | +} | ||
213 | + | ||
214 | +//cfr 이용할 때 reply | ||
215 | +function QuickReplyCfrYes(replyToken) { | ||
216 | + request.post( | ||
217 | + { | ||
218 | + url: TARGET_URL, | ||
219 | + headers: { | ||
220 | + 'Authorization': `Bearer ${TOKEN}` | ||
221 | + }, | ||
222 | + json: { | ||
223 | + "replyToken": replyToken, | ||
224 | + "messages": [ | ||
225 | + { | ||
226 | + "type": "text", | ||
227 | + "text": "사진을 입력해주세요.", | ||
228 | + "quickReply": quickReplyCfrYes | ||
229 | + } | ||
230 | + ] | ||
231 | + } | ||
232 | + },(error, response, body) => { | ||
233 | + console.log(body) | ||
234 | + }); | ||
235 | +} | ||
236 | + | ||
237 | +//cfr 이용하지 않을 때 reply | ||
170 | function QuickReplyCfrNo (replyToken) { | 238 | function QuickReplyCfrNo (replyToken) { |
171 | request.post( | 239 | request.post( |
172 | { | 240 | { |
... | @@ -179,8 +247,8 @@ function QuickReplyCfrNo (replyToken) { | ... | @@ -179,8 +247,8 @@ function QuickReplyCfrNo (replyToken) { |
179 | "messages": [ | 247 | "messages": [ |
180 | { | 248 | { |
181 | "type": "text", | 249 | "type": "text", |
182 | - "text": "맛집 추천 옵션 선택", | 250 | + "text": "랜덤 추천 옵션을 선택해주세요.", |
183 | - "quickReply": quickReplyNo | 251 | + "quickReply": quickReplyCfrNo |
184 | } | 252 | } |
185 | ] | 253 | ] |
186 | } | 254 | } |
... | @@ -189,6 +257,67 @@ function QuickReplyCfrNo (replyToken) { | ... | @@ -189,6 +257,67 @@ function QuickReplyCfrNo (replyToken) { |
189 | }); | 257 | }); |
190 | } | 258 | } |
191 | 259 | ||
260 | +function RecommendationResult(replyToken) { | ||
261 | + request.post( | ||
262 | + { | ||
263 | + url: TARGET_URL, | ||
264 | + headers: { | ||
265 | + 'Authorization': `Bearer ${TOKEN}` | ||
266 | + }, | ||
267 | + json: { | ||
268 | + "replyToken": replyToken, | ||
269 | + "messages": [ | ||
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 | + { | ||
293 | + "type": "text", | ||
294 | + "text": "기타 결과 출력" // 정보 수정 | ||
295 | + } | ||
296 | + ] | ||
297 | + } | ||
298 | + },(error, response, body) => { | ||
299 | + console.log(body) | ||
300 | + }); | ||
301 | +} | ||
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