app.js 10.4 KB
var papago = require("./papago.js");
var http = require('http');
var fs = require('fs');
var url = require('url');
var testFolder = './data';
var qs = require('querystring');
var path = require('path');
const {google} = require("googleapis");
const service = google.youtube('v3');
const apis = require('./APIs.json');
const apiKey = apis.youtubeAPI; //api키
let videoNum = "TpPwI_Lo0YY"; //비디오 주소(예시)
var videoLang = 'all'; //설정 언어
const serverIP = "http://localhost:3000" //서버의 주소
var commentList = new Array();
var commentNum = 0;
var korNum = 0;
var savednpt = '';
const URLreg1 = new RegExp(/https?:\/\/youtu.be\//);//유튜브에서 제공하는 동영상 공유 기능을 사용하여 얻은 URL 형식
const URLreg2 = new RegExp(/https?:\/\/www.youtube.com\//);//유튜브 주소를 그대로 넣었을 때 URL형식

function showcomment(response, VideoNum){
    let commentDisplay = ''; 
    for(let iterArr = 0; iterArr < commentNum; iterArr++){
        commentDisplay += `
        <div style="margin-top:15px; display:flex">
            <div style="margin-right:10px"> 
                <img class="rounded-circle" src="${commentList[iterArr].image}">
            </div>
            <div>
                <b>${commentList[iterArr].name}</b>
                <p>${commentList[iterArr].text}</p>
            </div>
        </div>
        `;
    }
        let body = `
        <!doctype html>
        <html>
        <head>
            <title>Youtube Comment</title>
            <meta charset="utf-8">
            <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
            <link rel="preconnect" href="https://fonts.googleapis.com">
            <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
            <link href="https://fonts.googleapis.com/css2?family=Permanent+Marker&display=swap" rel="stylesheet">
            <link href="https://fonts.googleapis.com/css2?family=Ubuntu&display=swap" rel="stylesheet">
        </head>
        <body style="margin:5%">
            <h1 style="font-family: 'Permanent Marker', cursive; text-align:center; padding-bottom:1%;"><a href="${serverIP}" style="text-decoration:none; color:inherit;">Youtube Comment Seperator</a></h1>
            <form action="${serverIP}/search" method="get">
                <div class="form-group" style="font-family: 'Ubuntu', sans-serif;">
                    <input type="text" name="videourl" placeholder="Type in video Url" class="form-control" style="margin-bottom:10px;" value=${VideoNum}>
                    <label for="language-select">Choose a language:</label>
                    <select class="form-control" name="languages" id="language-select" style="display:inline-flex;">
                        <option value="all" selected>--Please choose an option--</option>
                        <option value="ko">한국어</option>
                        <option value="en">English</option>
                        <option value="ja">日本語</option>
                        <option value="zh-CN">中國語</option>
                        <option value="es">español</option>
                        <option value="fr">Français</option>
                        <option value="de">Deutsch</option>
                    </select>
                    <p align="right" style="margin-top:1%">
                        <button type="submit" class="btn btn-danger">Display Comments</button>
                    </p>
                </div>
            </form>
            <br>
            <br>
            <div class="embed-responsive embed-responsive-16by9" style="text-align:center">
                <iframe class="embed-responsive-item" width="560" height="315" src="https://www.youtube.com/embed/${VideoNum}" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
            </div>
            <br>
            <div id="liveAlertPlaceholder"></div>
            <a class="btn btn-dark" href="${serverIP}/search?videourl=${VideoNum}&nextpage=${savednpt}&languages=${videoLang}" role="button">Show more comments</a>
            <button type="button" class="btn btn-danger" onclick="alert('Korean Percent: ${Math.floor((korNum/commentNum)*10000)/100}%')">Get Kor Percent</button>
            <br>
            ${commentDisplay}
        </body>
        </html>    
        `;
        response.writeHead(200);
        response.end(body);

}

function loadcomment(ApiKey, VideoNum, npt, n, res){
    return service.commentThreads.list({
        "key":ApiKey,
        "part":[
            "snippet, replies"
        ],
        "videoId":VideoNum,//비디오 주소
        "maxResults" : 100,
        "pageToken" : npt
    }).then(function(response) {
        async function loadAndParse(){
        //console.log("Response", response);
        tempcommentList = new Array();
        tempListLen = 0;
        for(let iter = 0; iter < response.data.pageInfo.totalResults; iter++){
            let templang = papago.getLang(response.data.items[iter].snippet.topLevelComment.snippet.textDisplay)
            let tempComment = {
                'name' : response.data.items[iter].snippet.topLevelComment.snippet.authorDisplayName,
                'image' : response.data.items[iter].snippet.topLevelComment.snippet.authorProfileImageUrl,
                'text' : response.data.items[iter].snippet.topLevelComment.snippet.textDisplay,
                'lang' : templang
            }
            tempcommentList.push(tempComment);
            tempListLen += 1;
            }
            for(let iter = 0; iter < tempListLen; iter++){
                let langPromise = tempcommentList[iter].lang.then(langData=>{
                    return langData;
                });
                templang = await langPromise;
                if(videoLang == 'all' || videoLang == templang){
                    commentList.push(tempcommentList[iter]);
                    if(templang=="ko"){korNum++;}
                    commentNum++;
                }
            }   
        
        //console.log(response.data.items[0].snippet.topLevelComment.snippet.textDisplay);
        //console.log(response.data.items[1].snippet.topLevelComment.snippet.textDisplay);
        npt = response.data.nextPageToken;

        if(npt != null){
            if( n > 1 && commentNum < 100){
                loadcomment(ApiKey, VideoNum, npt, n - 1, res);
            }else{
                savednpt = npt; //만약 댓글을 n번 불러온 후에 댓글이 더 남아있으면 savednpt 갱신
                showcomment(res, VideoNum);
            }
        }else{
            savednpt = '';
            console.log('end page'); // 댓글의 마지막 페이지
            showcomment(res, VideoNum);
        }
        }
        loadAndParse();
    },
    function(err) { console.error("Execute error", err); });
}

var app = http.createServer(function(request,response){ // request는 브라우저가 주는 정보, response는 우리가 브라우저에게 줄 정보
    var _url = request.url; // query string이 담김 ex) /?id=HTML
    var queryData = url.parse(_url, true).query; // query string을 추출하였음 나중에 불러올때는 queryData.(값의 이름)
    var pathname = url.parse(_url,true).pathname;
    var body;
    if(pathname === '/'){
        body = `
        <!doctype html>
        <html>
        <head>
            <title>Youtube Comment</title>
            <meta charset="utf-8">
            <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
            <link rel="preconnect" href="https://fonts.googleapis.com">
            <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
            <link href="https://fonts.googleapis.com/css2?family=Permanent+Marker&display=swap" rel="stylesheet">
            <link href="https://fonts.googleapis.com/css2?family=Ubuntu&display=swap" rel="stylesheet">
        </head>
        <body style="margin:5%">
            <h1 style="font-family: 'Permanent Marker', cursive; text-align:center; padding-bottom:1%;"><a href="${serverIP}" style="text-decoration:none; color:inherit;">Youtube Comment Seperator</a></h1>
            <form action="${serverIP}/search" method="get">
                <div class="form-group" style="font-family: 'Ubuntu', sans-serif;">
                    <input type="text" name="videourl" placeholder="Type in video Url" class="form-control" style="margin-bottom:10px;">
                    <label for="language-select">Choose a language:</label>
                    <select class="form-control" name="languages" id="language-select" style="display:inline-flex;">
                        <option value="all" selected>--Please choose an option--</option>
                        <option value="ko">한국어</option>
                        <option value="en">English</option>
                        <option value="ja">日本語</option>
                        <option value="zh-CN">中國語</option>
                        <option value="es">español</option>
                        <option value="fr">Français</option>
                        <option value="de">Deutsch</option>
                    </select>
                    <p align="right" style="margin-top:1%">
                        <button type="submit" class="btn btn-danger">Display Comments</button>
                    </p>
                </div>
            </form>
        </body>
        </html>    
        `;
        response.writeHead(200);
        response.end(body);
    }
    else if(pathname === '/search'){
        commentList.splice(0);
        commentNum = 0; //코멘트 리스트 초기화
        korNum = 0;

        videoNum = queryData.videourl;
        videoLang = queryData.languages;
        //유튜브 주소를 그대로 넣었을 때 videoNum 추출
        if(URLreg2.test(videoNum)){
            let tempvideoNum = url.parse(videoNum,true).query;
            videoNum = tempvideoNum.v;
        }
        //유튜브 URL공유 기능을 사용하여 얻은 주소를 넣었을 때 videoNum 추출
        videoNum = videoNum.replace(URLreg1,"");
        console.log(videoNum);
        let npt = "";
        if(queryData.nextpage != null) npt = queryData.nextpage
        loadcomment(apiKey,videoNum,npt,5, response);
    }
});
app.listen(3000);