Showing
2 changed files
with
33 additions
and
14 deletions
| ... | @@ -2,7 +2,6 @@ const express = require('express'); | ... | @@ -2,7 +2,6 @@ const express = require('express'); |
| 2 | const config = require('./API_config'); | 2 | const config = require('./API_config'); |
| 3 | const line = require('@line/bot-sdk'); | 3 | const line = require('@line/bot-sdk'); |
| 4 | const request = require('request'); | 4 | const request = require('request'); |
| 5 | - | ||
| 6 | const app = express(); | 5 | const app = express(); |
| 7 | 6 | ||
| 8 | //번역 api_url | 7 | //번역 api_url |
| ... | @@ -11,6 +10,15 @@ const translate_api_url = 'https://openapi.naver.com/v1/papago/n2mt'; | ... | @@ -11,6 +10,15 @@ const translate_api_url = 'https://openapi.naver.com/v1/papago/n2mt'; |
| 11 | //언어감지 api_url | 10 | //언어감지 api_url |
| 12 | const languagedetect_api_url = 'https://openapi.naver.com/v1/papago/detectLangs'; | 11 | const languagedetect_api_url = 'https://openapi.naver.com/v1/papago/detectLangs'; |
| 13 | 12 | ||
| 13 | +// API_config.js 의 형태는 다음과 같다. | ||
| 14 | +// const client_id = 'xxxx'; | ||
| 15 | +// const client_secret = 'xxxx'; | ||
| 16 | + | ||
| 17 | +// const line_channel = { | ||
| 18 | +// channelAccessToken: 'xxxx', | ||
| 19 | +// channelSecret: 'xxxx', | ||
| 20 | +// }; | ||
| 21 | + | ||
| 14 | // Naver Auth Key | 22 | // Naver Auth Key |
| 15 | //새로 발급받은 naver papago api id, pw 입력 | 23 | //새로 발급받은 naver papago api id, pw 입력 |
| 16 | const client_id = config.client_id; | 24 | const client_id = config.client_id; |
| ... | @@ -30,15 +38,19 @@ app.get('/', (req, res) => { | ... | @@ -30,15 +38,19 @@ app.get('/', (req, res) => { |
| 30 | 38 | ||
| 31 | // register a webhook handler with middleware | 39 | // register a webhook handler with middleware |
| 32 | app.post('/webhook', line.middleware(line_channel), (req, res) => { | 40 | app.post('/webhook', line.middleware(line_channel), (req, res) => { |
| 33 | - // webhook post 요청에 대해 promises를 전체 수행한다. | 41 | + // webhook 요청에 대해 순차적으로 다음을 수행한다. |
| 34 | // 전체 수행은 순차수행이기 때문에 동기처리 필요 => async await 패턴을 사용한다 | 42 | // 전체 수행은 순차수행이기 때문에 동기처리 필요 => async await 패턴을 사용한다 |
| 35 | const promises = req.body.events.map(async (event) => { | 43 | const promises = req.body.events.map(async (event) => { |
| 44 | + // 메세지의 속성을 확인하고 API connector를 만든다 | ||
| 36 | let api_connector = await api_connect(event); | 45 | let api_connector = await api_connect(event); |
| 46 | + // connector를 통해 언어 감지, 번역 target 언어를 설정한다 | ||
| 37 | let options = await option_maker(api_connector, event); | 47 | let options = await option_maker(api_connector, event); |
| 48 | + // 설정된 source 및 target으로 번역 결과를 저장한다 | ||
| 38 | let result = await receive_result(options, event); | 49 | let result = await receive_result(options, event); |
| 50 | + // 모든 작업이 끝나면 client api를 통해 reply를 진행한다. | ||
| 39 | client.replyMessage(event.replyToken,result); | 51 | client.replyMessage(event.replyToken,result); |
| 40 | }) | 52 | }) |
| 41 | - Promise | 53 | + Promise // promise all은 일괄 수행이 완료될 때 then이 수행된다 |
| 42 | .all(promises) | 54 | .all(promises) |
| 43 | .then((result) => res.json(result)) | 55 | .then((result) => res.json(result)) |
| 44 | .catch((err) => { | 56 | .catch((err) => { |
| ... | @@ -47,14 +59,15 @@ app.post('/webhook', line.middleware(line_channel), (req, res) => { | ... | @@ -47,14 +59,15 @@ app.post('/webhook', line.middleware(line_channel), (req, res) => { |
| 47 | }); | 59 | }); |
| 48 | }); | 60 | }); |
| 49 | 61 | ||
| 50 | -// 이벤트 타입 검사 이후 | ||
| 51 | // language detector api url 및 client id, secret 을 담은 connector를 반환한다. | 62 | // language detector api url 및 client id, secret 을 담은 connector를 반환한다. |
| 52 | const api_connect = (event) => { | 63 | const api_connect = (event) => { |
| 53 | return new Promise((resolve, reject) => { | 64 | return new Promise((resolve, reject) => { |
| 65 | + // 이벤트 타입 검사 | ||
| 54 | if (event.type !== 'message' || event.message.type !== 'text'){ | 66 | if (event.type !== 'message' || event.message.type !== 'text'){ |
| 55 | - //언어 감지 option | 67 | + // 비정상에 대한 reject 처리 |
| 56 | reject(new Error('메세지 혹은, 텍스트가 아닙니다.')); | 68 | reject(new Error('메세지 혹은, 텍스트가 아닙니다.')); |
| 57 | } else { | 69 | } else { |
| 70 | + // 정상요청에 대한 connector 생성 및 resolve | ||
| 58 | resolve({ | 71 | resolve({ |
| 59 | url : languagedetect_api_url, | 72 | url : languagedetect_api_url, |
| 60 | form : {'query': event.message.text}, | 73 | form : {'query': event.message.text}, |
| ... | @@ -74,7 +87,6 @@ const option_maker = (api_connector, event) => { | ... | @@ -74,7 +87,6 @@ const option_maker = (api_connector, event) => { |
| 74 | let detect_body = JSON.parse(response.body); | 87 | let detect_body = JSON.parse(response.body); |
| 75 | //언어 감지가 제대로 됐는지 확인 | 88 | //언어 감지가 제대로 됐는지 확인 |
| 76 | console.log(detect_body.langCode); | 89 | console.log(detect_body.langCode); |
| 77 | - | ||
| 78 | // 3.zh-CN : 중국어 간체 | 90 | // 3.zh-CN : 중국어 간체 |
| 79 | // 4.zh-TW : 중국어 번체 | 91 | // 4.zh-TW : 중국어 번체 |
| 80 | // 5.es : 스페인어 | 92 | // 5.es : 스페인어 |
| ... | @@ -116,16 +128,22 @@ const option_maker = (api_connector, event) => { | ... | @@ -116,16 +128,22 @@ const option_maker = (api_connector, event) => { |
| 116 | checker = false; | 128 | checker = false; |
| 117 | target = 'ko'; | 129 | target = 'ko'; |
| 118 | } | 130 | } |
| 131 | + // 전송된 메세지가 한국어일 경우 default target은 영어이며 설정에 따라 바뀐다. | ||
| 132 | + // 전송된 메세지가 한국어가 아닐 경우 모든 target language는 한국어가 된다. | ||
| 119 | 133 | ||
| 120 | let options = {} | 134 | let options = {} |
| 135 | + // checker란 언어 번역시 옵션의 존재 유뮤이다. 사용자가 영어가 아닌 다른 언어의 번역을 원할 경우 | ||
| 136 | + // 뒤에 옵션 .xx 가 붙게 되며 checker 는 true가 된다. | ||
| 121 | if (checker) | 137 | if (checker) |
| 122 | { | 138 | { |
| 123 | options = { | 139 | options = { |
| 124 | url: translate_api_url, | 140 | url: translate_api_url, |
| 141 | + // checker가 true이면 메세지 끝에 옵션이 붙기 때문에 번역시 이를 무시할 필요가 있다. | ||
| 125 | form: {'source':detect_body.langCode, 'target': target, 'text':event.message.text.slice(0,-3)}, | 142 | form: {'source':detect_body.langCode, 'target': target, 'text':event.message.text.slice(0,-3)}, |
| 126 | headers: {'X-Naver-Client-Id': client_id, 'X-Naver-Client-Secret': client_secret} | 143 | headers: {'X-Naver-Client-Id': client_id, 'X-Naver-Client-Secret': client_secret} |
| 127 | }; | 144 | }; |
| 128 | } | 145 | } |
| 146 | + // 기타 옵션 없는 한 -> 영, 외국어 -> 한글 번역은 checker false | ||
| 129 | else{ | 147 | else{ |
| 130 | options = { | 148 | options = { |
| 131 | url: translate_api_url, | 149 | url: translate_api_url, |
| ... | @@ -133,11 +151,12 @@ const option_maker = (api_connector, event) => { | ... | @@ -133,11 +151,12 @@ const option_maker = (api_connector, event) => { |
| 133 | headers: {'X-Naver-Client-Id': client_id, 'X-Naver-Client-Secret': client_secret} | 151 | headers: {'X-Naver-Client-Id': client_id, 'X-Naver-Client-Secret': client_secret} |
| 134 | } | 152 | } |
| 135 | } | 153 | } |
| 154 | + // 모든 번역 준비를 마친 options 를 resolve 한다 | ||
| 136 | resolve(options); | 155 | resolve(options); |
| 137 | } | 156 | } |
| 138 | else{ | 157 | else{ |
| 139 | - // 예외처리 | 158 | + // language detection에 대한 예외 reject |
| 140 | - reject(new Error("request is failed")); | 159 | + reject(new Error("언어 감지 실패")); |
| 141 | } | 160 | } |
| 142 | }) | 161 | }) |
| 143 | }) | 162 | }) |
| ... | @@ -148,6 +167,7 @@ const option_maker = (api_connector, event) => { | ... | @@ -148,6 +167,7 @@ const option_maker = (api_connector, event) => { |
| 148 | const receive_result = (options, event) => { | 167 | const receive_result = (options, event) => { |
| 149 | return new Promise((resolve, reject) => { | 168 | return new Promise((resolve, reject) => { |
| 150 | var result = { type:'text', text: ''}; | 169 | var result = { type:'text', text: ''}; |
| 170 | + // 번역에 관련된 options 객체를 번역 API로 post요청 | ||
| 151 | request.post(options, (error, response) => { | 171 | request.post(options, (error, response) => { |
| 152 | // Translate API Sucess | 172 | // Translate API Sucess |
| 153 | if(!error && response.statusCode == 200){ | 173 | if(!error && response.statusCode == 200){ |
| ... | @@ -159,17 +179,16 @@ const receive_result = (options, event) => { | ... | @@ -159,17 +179,16 @@ const receive_result = (options, event) => { |
| 159 | resolve(result); | 179 | resolve(result); |
| 160 | } | 180 | } |
| 161 | else{ | 181 | else{ |
| 162 | - // 예외처리 | 182 | + // 번역 정상적으로 불가능시 reject 처리 |
| 163 | - result.text = '언어를 감지할 수 없습니다.'; | 183 | + result.text = '번역할 수 없는 언어입니다.'; |
| 164 | client.replyMessage(event.replyToken,result); | 184 | client.replyMessage(event.replyToken,result); |
| 165 | - reject(new Error("language was not detected")); | 185 | + reject(new Error("번역 실패")); |
| 166 | } | 186 | } |
| 167 | }) | 187 | }) |
| 168 | }) | 188 | }) |
| 169 | } | 189 | } |
| 170 | 190 | ||
| 191 | +// app running | ||
| 171 | app.listen(3000, function () { | 192 | app.listen(3000, function () { |
| 172 | console.log('Linebot listening on port 3000!'); | 193 | console.log('Linebot listening on port 3000!'); |
| 173 | -}); | 194 | +}); |
| 174 | - | ||
| 175 | -// 무조건 3글자 자르면 짧은글 씹힌다 | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
캡처.PNG
deleted
100644 → 0
20.3 KB
-
Please register or login to post a comment