Files
ghbot/twitch.js
2018-09-12 07:43:10 -07:00

192 lines
6.8 KiB
JavaScript
Executable File

/**
* GHBot4Twitch
*/
// @TODO: Make the bot aware of what video is current active
// @TODO: Change video playlist source on an interval
// Import modules
const irc = require('irc');
const OBSWebSocket = require('obs-websocket-js');
// Read internal configuration
let config = require('./config.json');
let twitchChat;
const init = (config) => {
let botChannel = '#' + config.twitch.username.toLowerCase();
// Connect to OBS Websocket
const obs = new OBSWebSocket();
console.log(`Connecting to OBS...`);
obs.connect({ address: config.obs.websocket.address, password: config.obs.websocket.password })
.then(() => {
console.log(`Success! We're connected to OBS!`);
//obs.getSourcesList().then(data => {console.log(data.sources)}).catch(console.error);
twitchInit(config, obs);
})
.catch(err => {
console.log(err);
});
obs.on('error', err => {
console.error('OBS socket error:', err);
});
const twitchInit = (config, obs) => {
console.log('Connecting to Twitch...');
// Connect to Twitch IRC server with the Bot
let twitchChat = new irc.Client(config.twitch.ircServer, config.twitch.username, {
password: config.twitch.oauth,
autoRejoin: true,
retryCount: 10,
channels: config.twitch.channels,
debug: config.debug
});
// Also connect with an editor account
let editorChat = new irc.Client(config.twitch.ircServer, config.twitch.editorLogin.username, {
password: config.twitch.editorLogin.oauth,
autoRejoin: true,
retryCount: 10,
channels: config.twitch.channels,
debug: config.debug
});
// Set up event listeners for Twitch
twitchChat.addListener('message', (from, to, message) => {
// Ignore everything from blacklisted users
if (config.twitch.blacklistedUsers.includes(from)) return;
// Listen for commands that start with the designated prefix
if (message.startsWith(config.twitch.cmdPrefix)) {
let commandParts = message.slice(config.twitch.cmdPrefix.length).split(' ');
let commandNoPrefix = commandParts[0] || '';
// Listen for specific commands from admins
if (config.twitch.admins.includes(from) || from === config.twitch.username.toLowerCase()) {
if (commandNoPrefix === 'show' || commandNoPrefix === 'hide') {
let newVisibility = (commandNoPrefix === 'show');
let visibleTerm = (newVisibility ? 'visible' : 'hidden');
let target = commandParts[1] || false;
if (!target) {
twitchChat.say(to, `A scene item name is required!`);
return;
}
let sceneItem = {"item": target};
let sceneOrGroup = commandParts[2] || false;
if (sceneOrGroup !== false) {
sceneItem["scene-name"] = sceneOrGroup;
}
obs.getSceneItemProperties(sceneItem)
.then(data => {
if (data.visible === newVisibility) {
twitchChat.say(to, `This scene item is already ${visibleTerm}. DerpHam`);
} else {
sceneItem.visible = newVisibility;
obs.setSceneItemProperties(sceneItem)
.then(res => {
twitchChat.say(to, `${target} is now ${visibleTerm}.`);
})
.catch(console.error);
}
})
.catch(err => {
twitchChat.say(to, JSON.stringify(err));
});
} else if (commandNoPrefix === 'auw') {
obs.setSceneItemProperties({"item": "everybody-wow", "visible": true})
.then(res => {
// fade out headphone audio
/*for (i = 100; i >= 0; i--) {
obs.setVolume({"source": "headphones", "volume": i/100});
}*/
// @TODO: send command to mute the songrequest audio
editorChat.say(to, '!volume 0');
twitchChat.say(to, 'Everybody OwenWow');
// hide the source after a certain amount of time (248s in this case)
setTimeout(() => {
obs.setSceneItemProperties({"item": "everybody-wow", "visible": false})
.then(res => {
// fade in headphone audio
/*for (i = 1; i <= 100; i++) {
obs.setVolume({"source": "headphones", "volume": i/100});
}*/
// @TODO: send command to unmute the songrequest audio
editorChat.say(to, '!volume 75');
twitchChat.say(to, 'OwenWow');
}).catch(console.error);
}, 248000);
}).catch(console.error);
} else if (commandNoPrefix === 'switch') {
let target = commandParts[1] || false;
if (!target) {
twitchChat.say(to, `A scene name is required!`);
return;
}
obs.getCurrentScene()
.then(data => {
if (data.name === target) {
twitchChat.say(to, `That scene is already active! DerpHam`);
} else {
obs.setCurrentScene({"scene-name": target})
.then(() => {twitchChat.say(to, `${target} is now active`)})
.catch(console.error);
}
})
.catch(console.error);
} else if (commandNoPrefix === 'reboot') {
console.log('Received request from admin to reboot...');
twitchChat.say(to, 'Rebooting...');
process.exit(0);
}
}
}
});
twitchChat.addListener('error', message => {
if (message.command != 'err_unknowncommand') {
console.error('error from Twitch IRC Server: ', message);
}
});
editorChat.addListener('error', message => {
if (message.command != 'err_unknowncommand') {
console.error('error from Twitch IRC Server: ', message);
}
});
twitchChat.addListener('registered', message => {
console.log(`Connected to ${message.server}`);
});
twitchChat.addListener('join', (channel, nick, message) => {
if (nick === config.twitch.username) {
console.log(`Joined channel ${channel}`);
}
});
twitchChat.addListener('part', (channel, nick, message) => {
if (nick === config.twitch.username) {
console.log(`Left channel ${channel}`);
}
});
twitchChat.addListener('motd', motd => {
console.log(`Received MOTD: ${motd}`);
});
}
}
init(config);
// catches Promise errors
process.on('unhandledRejection', console.error);