~johanvandegriff/live.johanv.xyz

fd6c11e52b41f4a2359248f1591560ecabd7dc25 — Johan Vandegriff 1 year, 1 month ago 2424dcf
pull and display twitch chat, !boggle command
2 files changed, 99 insertions(+), 9 deletions(-)

M package.json
M server.js
M package.json => package.json +3 -1
@@ 10,9 10,11 @@
    "dependencies": {
        "@types/node": "^14.11.8",
        "color-hash": "^1.0.3",
        "dotenv": "^8.2.0",
        "express": "^4.15.2",
        "jquery": "^3.5.1",
        "socket.io": "^2.3.0"
        "socket.io": "^2.3.0",
        "tmi.js": "^1.5.0"
    },
    "devDependencies": {
        "video.js": "^7.8.4"

M server.js => server.js +96 -8
@@ 2,16 2,38 @@ var express = require('express');
var app = express();
var http = require('http').createServer(app);
var io = require('socket.io')(http);
const tmi = require('tmi.js'); //twitch chat https://dev.twitch.tv/docs/irc

require('dotenv').config({ path: '/srv/secret-twitch.env' }) //bot API key and other info
//the /srv/secret-twitch.env file should look like:
//BOT_USERNAME=jjvantheman (or create a second account for the bot)
//BOT_OATH_TOKEN=oauth:blah blah blah
//BOT_CHANNEL=jjvantheman

// Define configuration options
const opts = {
    identity: {
        username: process.env.BOT_USERNAME,
        password: process.env.BOT_OAUTH_TOKEN
    },
    channels: [process.env.BOT_CHANNEL]
};

//console.log("TWITCH SECRETS " + JSON.stringify(opts));

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

//expose the static dir with CSS and images
app.use('/static', express.static('static'));
//expose the live dir that will be populated by nginx when streaming
app.use('/live', express.static('live'));

//use socket.io to make a simple live chatroom
io.on('connection', (socket) => {
    console.log('a user connected');
    socket.on('disconnect', () => {


@@ 19,16 41,80 @@ io.on('connection', (socket) => {
    });

    socket.on('chat message', (msg) => {
        console.log('message: ' + msg.name + ": " + msg.text);
        io.emit('chat message', msg);
        //emit the message many times for testing CSS
        // msg.text = msg.text+msg.text+msg.text+msg.text+msg.text+msg.text+msg.text+msg.text+msg.text+msg.text+msg.text+msg.text+msg.text+msg.text;
        // for (i=0; i<30; i++) {
        //     io.emit('chat message', msg);
        // }
        iosend(msg.name, msg.text)
        handleCommand(msg.text);
    });
});

function iosend(name, text) {
    console.log('message: ' + name + ": " + text);
    var iomsg = {'name': name, 'text': text};
    io.emit('chat message', iomsg);
    // emit the message many times for testing CSS
    // iomsg.text = iomsg.text+iomsg.text+iomsg.text+iomsg.text+iomsg.text+iomsg.text+iomsg.text+iomsg.text+iomsg.text+iomsg.text+iomsg.text+iomsg.text+
    //              iomsg.text+iomsg.text+iomsg.text+iomsg.text+iomsg.text+iomsg.text+iomsg.text+iomsg.text+iomsg.text+iomsg.text+iomsg.text+iomsg.text;
    // for (i=0; i<30; i++) {
    //     io.emit('chat message', iomsg);
    // }
}

//twitch chat stuff
// Create a client with our options
const client = new tmi.client(opts);
// Register our event handlers (defined below)
client.on('message', onMessageHandler);
client.on('connected', onConnectedHandler);
// Connect to Twitch:
client.connect();

// Called every time the bot connects to Twitch chat
function onConnectedHandler (addr, port) {
    console.log(`* Connected to ${addr}:${port}`);
}
// Called every time a message comes in
function onMessageHandler (target, context, msg, self) {
    console.log("TARGET " + target);
    console.log("CONTEXT " + JSON.stringify(context));
    console.log("MSG " + msg);
    console.log("SELF " + self);

    //copy twitch chat to socket chat
    iosend(context.username, msg);

    if (self) { return; } // Ignore messages from the bot
    handleCommand(msg);
}

function handleCommand(commandName1) {
    // Remove whitespace from chat message
    const commandName = commandName1.trim();

    var valid = true;
    // If the command is known, let's execute it
    if (commandName === '!dice') {
        const num = rollDice();
        //commands sent here will be echoed to the socket chat since they will be detected by onMessageHandler
        client.say(process.env.BOT_CHANNEL, `You rolled a ${num}`);
    } else if (commandName === '!boggle') {
        client.say(process.env.BOT_CHANNEL, `play boggle at https://games.johanv.xyz/boggle`);
    } else {
        valid = false;
        console.log(`* Unknown command ${commandName}`);
    }
    if (valid) {
        console.log(`* Executed ${commandName} command`);
    }
}

// Function called when the "dice" command is issued
function rollDice () {
    const sides = 6;
    return Math.floor(Math.random() * sides) + 1;
}



//start the http server
var default_port = 8080;
http.listen(process.env.PORT || default_port, () => {
    console.log('listening on *:' + (process.env.PORT || default_port));


@@ 36,9 122,11 @@ http.listen(process.env.PORT || default_port, () => {

//TODO clean up the CSS, make text look good
//TODO add cards instead of links
//TODO pull twitch chat
//TODO pull dlive chat
//TODO pull youtube chat
//TODO only change nickname when email is provided
//TODO save nickname with cookies
//TODO add a README with setup instructions
//TODO favicon
//TODO use flexbox for CSS?
//TODO obs overlay