~johanvandegriff/live.johanv.xyz

836aedf1794e638ee6c9b4c0eb18fb7db8825499 — Johan Vandegriff 1 year, 1 month ago 67055f6
pull and display youtube chat
3 files changed, 64 insertions(+), 3 deletions(-)

M Dockerfile
M package.json
M server.js
M Dockerfile => Dockerfile +1 -1
@@ 16,7 16,7 @@ COPY nginx.conf /etc/nginx/nginx.conf
COPY package*.json ./

RUN apt-get update -yq \
     && apt-get -yq install curl gnupg ca-certificates \
     && apt-get -yq install curl gnupg ca-certificates apt-utils \
     && curl -L https://deb.nodesource.com/setup_12.x | bash \
     && apt-get update -yq \
     && apt-get install -yq \

M package.json => package.json +2 -1
@@ 15,7 15,8 @@
        "express": "^4.15.2",
        "jquery": "^3.5.1",
        "socket.io": "^2.3.0",
        "tmi.js": "^1.5.0"
        "tmi.js": "^1.5.0",
        "youtube-live-chat": "^1.0.3"
    },
    "devDependencies": {
        "video.js": "^7.8.4"

M server.js => server.js +61 -1
@@ 7,6 7,7 @@ const io = require('socket.io')(server);
const dotenv = require('dotenv'); //for storing secrets in an env file
const tmi = require('tmi.js'); //twitch chat https://dev.twitch.tv/docs/irc
const Dlive = require('dlivetv-api'); //dlive chat https://github.com/lkd70/dlivetv-api
const YouTube = require('youtube-live-chat'); //youtube live chat https://github.com/yuta0801/youtube-live-chat

//expose js libraries to client so they can run in the browser
app.get('/', (req, res) => {res.sendFile(__dirname + '/index.html')});


@@ 118,6 119,8 @@ function handleCommand(commandName1) {
            console.log('An error', error);
        });
        request.end();
    } else if (commandName === "we are live!") {
        connect_to_youtube_if_not_connected(); //TODO make a better mechanism for running this
    } else {
        valid = false;
        console.log(`* Unknown command ${commandName}`);


@@ 134,6 137,7 @@ function rollDice () {
    return Math.floor(Math.random() * sides) + 1;
}


//dlive chat stuff
dotenv.config({ path: '/srv/secret-dlive.env' }) //bot API key and other info
//the /srv/secret-dlive.env file should look like:


@@ 160,6 164,59 @@ bot.on('ChatText', msg => {
    // }
});


//youtube live chat stuff
dotenv.config({ path: '/srv/secret-youtube.env' }) //bot API key and other info
//the /srv/secret-youtube.env file should look like:
//YOUTUBE_CHANNEL_ID=UCmrLaVZneWG3kJyPqp-RFJQ (this is my channel ID, as in https://www.youtube.com/channel/UCmrLaVZneWG3kJyPqp-RFJQ)
//YOUTUBE_API_KEY=blah blah blah
// console.log("YOUTUBE_CHANNEL_ID " + process.env.YOUTUBE_CHANNEL_ID);
// console.log("YOUTUBE_API_KEY " + process.env.YOUTUBE_API_KEY);

var yt; // = new YouTube(process.env.YOUTUBE_CHANNEL_ID, process.env.YOUTUBE_API_KEY);

//the problem is that it fails when there is no livestream, and gives up after 1 attempt
//i solve this by checking every minute for a livestream until it finds one and successfully connects to the chat
// setInterval(function(){ connect_to_youtube_if_not_connected() }, 60000);
//using an interval uses up my api key quota, so instead this function is called when i type "we are live!" in the chat (see handleCommand)
function connect_to_youtube_if_not_connected() {
    if (yt != undefined && yt.liveId != undefined && yt.chatId != undefined) {
        console.log("youtube is already connected");
        iosend("youtube", "connected");
        return;
    }
    iosend("youtube", "trying to connect...");
    console.log("trying to connect to youtube...");

    yt = new YouTube(process.env.YOUTUBE_CHANNEL_ID, process.env.YOUTUBE_API_KEY);

    yt.on('ready', () => {
        iosend("youtube", "connected!");
        console.log('YouTube is ready!');
        console.log("yt.liveId: " + yt.liveId);
        console.log("yt.chatId: " + yt.chatId);
        yt.listen(1000);
    })

    yt.on('message', data => {
        console.log(data.snippet.displayMessage);
        console.log(JSON.stringify(data));
        iosend(data.authorDetails.displayName, data.snippet.displayMessage)
    })

    yt.on('error', error => {
        iosend("youtube", "error connecting to chat");
        console.error("YouTube ERROR");
        console.log(error);
        console.log("yt.liveId: " + yt.liveId);
        console.log("yt.chatId: " + yt.chatId);
    })

}




//start the http server
var default_port = 8080;
server.listen(process.env.PORT || default_port, () => {


@@ 168,7 225,6 @@ server.listen(process.env.PORT || default_port, () => {

//TODO clean up the CSS, make text look good
//TODO add cards instead of links
//TODO pull youtube chat
//TODO only change nickname when email is provided
//TODO save nickname with cookies
//TODO add a README with setup instructions and change package name and version


@@ 177,3 233,7 @@ server.listen(process.env.PORT || default_port, () => {
//TODO obs overlay
//TODO !carl command pass in the rest of the message to the CARL API
//TODO unify the commands
//TODO unify the secret keys
//TODO look at https://github.com/emad-elsaid/restreamer
//TODO look at https://openstreamingplatform.com/
//TODO chat notification sound