app.js 5.02 KB
const express = require('express');
const config = require('./API_config');
const line = require('@line/bot-sdk');
const request = require('request');

const app = express();

//번역 api_url
const translate_api_url = 'https://openapi.naver.com/v1/papago/n2mt';

//언어감지 api_url
const languagedetect_api_url = 'https://openapi.naver.com/v1/papago/detectLangs';

// Naver Auth Key
//새로 발급받은 naver papago api id, pw 입력
const client_id = config.client_id;
const client_secret = config.client_secret;
// Line Channel Access Tocken
const line_channel = config.line_channel;

// create LINE SDK client
const client = new line.Client(line_channel);

// ELB health checker
app.get('/', (req, res) => {
	console.log('ELB health check');
	res.writeHead(200, { "Content-Type": "text/html" });
	res.end();
});

// register a webhook handler with middleware
app.post('/webhook', line.middleware(line_channel), (req, res) => {
	// webhook post 요청에 대해 promises를 전체 수행한다.
	// 전체 수행은 순차수행이기 때문에 동기처리 필요 => async await 패턴을 사용한다
	const promises = req.body.events.map(async (event) => {
		let api_connector = await api_connect(event);
		let options = await option_maker(api_connector, event);
		let result = await receive_result(options, event);
		client.replyMessage(event.replyToken,result);
	})
	Promise
	.all(promises)
	.then((result) => res.json(result))
    	.catch((err) => {
     	 console.error(err);
     	 res.status(200).end();
    });
});

// 이벤트 타입 검사 이후
// language detector api url 및 client id, secret 을 담은 connector를 반환한다.
const api_connect = (event) => {
    return new Promise((resolve, reject) => {
		if (event.type !== 'message' || event.message.type !== 'text'){
		//언어 감지 option
			reject(new Error('메세지 혹은, 텍스트가 아닙니다.'));		
		} else {
			resolve({
				url : languagedetect_api_url,
				form : {'query': event.message.text},
				headers: {'X-Naver-Client-Id': client_id, 'X-Naver-Client-Secret': client_secret}
			});
		}
    })
}

// post 요청으로 api connector를 이용해 language를 분석한 뒤
// source 및 target 설정, 번역 API url을 포함한 options을 반환한다
const option_maker = (api_connector, event) => {
    return new Promise((resolve, reject) => {
		request.post(api_connector, (error,response) => {
    	    console.log(response.statusCode);
        	if(!error && response.statusCode == 200){
				let detect_body = JSON.parse(response.body);
				//언어 감지가 제대로 됐는지 확인
				console.log(detect_body.langCode);

				// 3.zh-CN : 중국어 간체
				// 4.zh-TW : 중국어 번체
				// 5.es : 스페인어
				// 6.fr : 프랑스어
				// 7.vi : 베트남어
				// 8.th : 태국어
				// 9.id : 인도네시아어
				let target = '';
				let checker = true;
				if (detect_body.langCode == 'ko') {
					target = 'en';
					switch (event.message.text.slice(-3)) {
						case '.cn':
							target = 'zh-CN';
							break;
						case '.tw':
							target = 'zh-TW';
							break;
						case '.es':
							target = 'es';
							break;
						case '.fr':
							target = 'fr';
							break;
						case '.vi':
							target = 'vi';
							break;
						case '.th':
							target = 'th';
							break;
						case '.id':
							target = 'id';
							break;
						default:
							checker = false;
							break;
					}
				} else {
					checker = false;
					target = 'ko';
				}

				let options = {}
				if (checker)
				{
					options = {
						url:  translate_api_url,
						form: {'source':detect_body.langCode, 'target': target, 'text':event.message.text.slice(0,-3)},
						headers: {'X-Naver-Client-Id': client_id, 'X-Naver-Client-Secret': client_secret}
					};
				}
				else{
					options = {
						url:  translate_api_url,
						form: {'source':detect_body.langCode, 'target': target, 'text':event.message.text},
						headers: {'X-Naver-Client-Id': client_id, 'X-Naver-Client-Secret': client_secret}
					}
				}
				resolve(options);
			}
			else{
				// 예외처리
				reject(new Error("request is failed"));
			}
		})
    })
}

// options를 받아서 post 요청을 통해 번역을 실행한다.
// response를 JSON parsing 한 뒤 결과 result에 메세지를 담아서 반환한다.
const receive_result = (options, event) => {
  	return new Promise((resolve, reject) => {
		var result = { type:'text', text: ''};
    	request.post(options, (error, response) => {
      	// Translate API Sucess
			if(!error && response.statusCode == 200){
				// JSON
				var objBody = JSON.parse(response.body);
				// Message 잘 찍히는지 확인
				result.text = objBody.message.result.translatedText;
				console.log(result.text);
				resolve(result);
			}
			else{
				// 예외처리
				result.text = '언어를 감지할 수 없습니다.';
				client.replyMessage(event.replyToken,result);
				reject(new Error("language was not detected"));
			}
  		})
	})
}

app.listen(3000, function () {
  console.log('Linebot listening on port 3000!');
});

// 무조건 3글자 자르면 짧은글 씹힌다