박진수

Merge branch 'integration-2nd' into 'master'

2차 통합 완료

2차 통합을 완료했습니다. 고생하셨습니다 다들~!

## 개선사항

* frontend
  * login 후에는 login 창 안보이게 분기
  * 설정을 .env로 편리하게 할 수 있도록 변경
  * `/channels` API로 채널리스트를 받아와서 보여줄 수 있게

* backend
  * 영어채팅은 소켓에서 안 보내기

* tts
  * 재생 작업을 큐잉해서 순차적으로 재생하거나  max time을 지정

See merge request !14
......@@ -3,7 +3,8 @@ import Login from "./Login";
import Body from "./Body";
function App() {
let accessToken = null;
// let accessToken = null;
let accessToken = 1;
return (
<div className="app">
......
......@@ -8,7 +8,7 @@ import { WatchOutlined } from "@material-ui/icons";
import io from 'socket.io-client'
import tts from './tts';
const socket = io.connect("http://localhost:3000")
const socket = io.connect("http://localhost:3303")
socket.on("connect", event=>{
// 테스트용으로 umi0410에게 입장.
// 다른 거 아무거나 채널이름을 넣으면 되겠지만, 그렇게 하고싶으면 백엔드에서 인자설정을 해줘야함.
......@@ -18,6 +18,7 @@ socket.on("connect", event=>{
// 말해야할 메시지가 왔을 때. 이건 따로 Component와 묶지 않아도 알아서 실행됩니다.
socket.on('chat message', (name, msg)=>{
console.log(msg)
console.log("got message")
tts.speak(msg)
})
......
import React from "react";
import "./Login.css";
function Login(){
const OAuthUrl = ""; // oauth 인증용 url
function Login(){
const OAuthUrl = `https://id.twitch.tv/oauth2/authorize?response_type=code&approval_prompt=auto&redirect_uri=http://localhost:3303/join&client_id=2d1gvcqyiyrk180qvnkec2fl23sv1o`; // oauth 인증용 url
return (
<div className="login">
<img
......
SOCKET_PORT=
TOKEN=
PAPAGO_ID=
PAPAGO_SECRET=
BOT_USERNAME=
OAUTH_TOKEN=
HOST_URI = [twitch end point url]
SOCKET_PORT= [backend socket server port]
TWITCH_CLIENT= [twitch dev client id]
TWITCH_SECRET= [twitch dev client id secret]
PAPAGO_ID= [papago client id]
PAPAGO_SECRET= [papago client secret]
BOT_USERNAME= [twitch bot name]
OAUTH_TOKEN= [twitch user oauth token]
......@@ -48,45 +48,23 @@ exports.detectchat = (message, client, io, target) => {
});
}
// exports.trans = (message, lang, io, room) => {
// request.post(
// {
// url: PAPAGO_URL,
// headers: {
// 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
// 'X-Naver-Client-Id': `${PAPAGO_ID}`,
// 'X-Naver-Client-Secret': `${PAPAGO_SECRET}`
// },
// body: `source=${lang}&target=ko&text=` + message,
// json:true
// },(error, response, body) => {
// if(!error && response.statusCode == 200) {
// var Translated = body.message.result.translatedText;
// io.to(room).emit('chat message', "trans", Translated);
// }
// });
// }
// exports.detect = (message,io,room) => {
// request.post(
// {
// url: dPAPAGO_URL,
// headers: {
// 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
// 'X-Naver-Client-Id': `${PAPAGO_ID}`,
// 'X-Naver-Client-Secret': `${PAPAGO_SECRET}`
// },
// body: `query=` + message,
// json:true
// },(error, response, body) => {
// if(!error && response.statusCode == 200) {
// var lang = body.langCode;
// if(lang != 'ko'){
// this.trans(message,lang,io,room)
// }
// }
// });
// }
exports.trans = (message, client,io, target) => {
request.post(
{
url: PAPAGO_URL,
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'X-Naver-Client-Id': `${PAPAGO_ID}`,
'X-Naver-Client-Secret': `${PAPAGO_SECRET}`
},
body: `source=ko&target=en&text=` + message,
json:true
},async (error, response, body) => {
if(!error && response.statusCode == 200) {
var Translated = await body.message.result.translatedText;
client.say(target, "(Trans) "+Translated);
io.to(target.replace('#','')).emit('chat message', "Trans", Translated);
}
});
}
......
......@@ -160,6 +160,14 @@
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
},
"axios": {
"version": "0.21.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.0.tgz",
"integrity": "sha512-fmkJBknJKoZwem3/IKSSLpkdNXZeBu5Q7GA/aRsr2btgrptmSCxi2oFjZHqGdK9DoTil9PIHlPIZw2EcRJXRvw==",
"requires": {
"follow-redirects": "^1.10.0"
}
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
......@@ -488,6 +496,11 @@
"unpipe": "~1.0.0"
}
},
"follow-redirects": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz",
"integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA=="
},
"forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
......
......@@ -11,6 +11,7 @@
"license": "ISC",
"dependencies": {
"cors": "^2.8.5",
"axios": "^0.21.0",
"dotenv": "^8.2.0",
"ejs": "^3.1.5",
"express": "^4.17.1",
......
......@@ -11,6 +11,7 @@ const io = require('socket.io')(http, {
});
const papago = require('./openAPIs/papago_api');
const tmi = require('tmi.js');
// Define configuration options
var opts = {
......@@ -18,17 +19,18 @@ var opts = {
username: process.env.BOT_USERNAME,
password: process.env.OAUTH_TOKEN
},
channels: [
'nnonuu'
]
channels: ["tmwardo"]
};
// Create a client with our options
const client = new tmi.client(opts); //twitch chatbot client
var client = new tmi.client(opts); //twitch chatbot client
var bodyParser = require('body-parser');
const { default: Axios } = require('axios');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.set('view engine', 'ejs');
app.set('views', './testviews');
let room = ['nnonuu', 'bachelorchuckchuck'];
// client.opts.channels;
let a = 0;
......@@ -38,13 +40,59 @@ app.get('/', (req, res) => {
});
app.get('/list',(req,res) => {
res.send(room);
var result = []
for (var i = 0; i<client.channels.length; i++){
result.push(client.channels[i].slice(1))
}
res.send(result)
});
app.post('/jointest',async (req,res)=>{
// requests.post(`https://id.twitch.tv/oauth2/token?client_id=<클라이언트 ID>&client_secret=${process.env.TOKEN}&grant_type=client_credentials`).json()
JoinChannel(req.body.streamer);
res.send(req.body.streamer)
});
console.log(`https://id.twitch.tv/oauth2/authorize?response_type=code&approval_prompt=auto&redirect_uri=${process.env.HOST_URI+':'+process.env.SOCKET_PORT}/join&client_id=${process.env.TWITCH_CLIENT}`)
////////////////////////oauth////////////////////////
const axios = require('axios')
app.get('/oauth',(req,res)=>{
let codeAddr = `https://id.twitch.tv/oauth2/authorize?response_type=code&approval_prompt=auto&redirect_uri=${process.env.HOST_URI+':'+process.env.SOCKET_PORT}/join&client_id=${process.env.TWITCH_CLIENT}`
res.redirect(codeAddr)
});
app.get('/join', async (req,res)=>{
let code = req.query.code
let reqAddr = `https://id.twitch.tv/oauth2/token?client_id=${process.env.TWITCH_CLIENT}&client_secret=${process.env.TWITCH_SECRET}&code=${code}&grant_type=authorization_code&redirect_uri=${process.env.HOST_URI+':'+process.env.SOCKET_PORT}/test`
axios.post(reqAddr).then(resp1=>{
axios.get('https://id.twitch.tv/oauth2/validate',
{
headers:{
Authorization : "Bearer "+ resp1.data.access_token
}
}
).then(resp2=>{
JoinChannel(resp2.data.login)
res.redirect("http://localhost:8000?authenticated=true") // 이거 프론트 유알엘임
})
})
})
app.post('/add',(req,res)=>{
room.append(req.body.streamer);
res.send(req.body.streamer);
app.get('/test',(req,res)=>{
res.send("")
})
////////////////////////oauth////////////////////////
async function JoinChannel(streamer){
await client.action(streamer,'KhuwitchBot 두두등장');
await opts.channels.push('#'+streamer);
await delete client;
client = await new tmi.client(opts);
client.on('message', onMessageHandler);
client.on('connected', onConnectedHandler);
client.connect();
}
io.on('connection', (socket) => {
......@@ -91,8 +139,17 @@ client.connect();
// Called every time a message comes in
function onMessageHandler (target, context, msg, self) {
if (self) { return; } // Ignore messages from the bot
if (msg.startsWith('!')){
if(msg.startsWith('!번역')){
io.to(target.replace('#','')).emit('chat message',context["display-name"],msg.slice(4))
papago.trans(msg.slice(4), client, io, target)
}
}
else if(context["display-name"] == "빵_떡"
|| context["display-name"]=="Nightbot"
|| context["display-name"]=="싹뚝"
|| context["display-name"]=="KhuwitchBot"){
return;
}
else{
io.to(target.replace('#','')).emit('chat message',context["display-name"],msg)
......
......@@ -50,8 +50,8 @@
</head>
<body>
<select>
<option value="tmwardo">tmwardo</option>
<option value="nnonuu">nnonuu</option>
<option value="bachelorchuckchuck">bachelorchuckchuck</option>
</select>
<ul id="messages"></ul>
<form action="">
......@@ -64,7 +64,7 @@
$(() => {
const name = prompt('What your name');
const socket = io();
let room = ['nnonuu', 'bachelorchuckchuck'];
let room = ['tmwardo','nnonuu'];
var streamer = room[0]
let num = 0;
socket.emit('joinRoom', streamer, name);
......@@ -78,11 +78,11 @@
});
$('form').submit(() => {
socket.emit('chat message', streamer, name, $('#m').val());
$('#m').val('');
return false;
});
// $('form').submit(() => {
// socket.emit('chat message', streamer, name, $('#m').val());
// $('#m').val('');
// return false;
// });
socket.on('chat message', (name, msg) => {
$('#messages').append($('<li>').text(name + ' : ' +
......