const fs = require('fs'); const tmi = require('tmi.js'); const moment = require('moment'); // Twitch bot options const optsFile = fs.readFileSync('twitch.config'); const opts = JSON.parse(optsFile); const client = tmi.client(opts); // Buttsbot options const syllableRegex = /[^aeiouy]*[aeiouy]+(?:[^aeiouy]*$|[^aeiouy](?=[^aeiouy]))?/gi; let configFile = fs.readFileSync('buttsbot.config') let config = JSON.parse(configFile); console.log(`* Startup: Loaded config: ${config}`); let lastMessageButtified = 0; // Client client.on('message', onMessageHandler); client.on('connected', onConnectedHandler); client.connect(); // Helper methods function syllabify(words) { return words.match(syllableRegex); } function randomIntFromInterval(min, max) { // min and max included return Math.floor(Math.random() * (max - min + 1) + min) } function isNumeric(n) { return !isNaN(parseFloat(n)) && isFinite(n); } // Event handlers function onMessageHandler (channel, userstate, message, self) { if (self) { return; } var trimmedMessage = message.trim(); if (trimmedMessage.startsWith("!buttsbot")) { if (userstate['room-id'] === userstate['user-id'] || userstate['mod']) { var parts = trimmedMessage.split(' '); var action = parts[1]; var value = parts[2]; switch (action) { case "config": client.say(channel, "Timer: " + config.timer + " - Limit: " + config.limit + " - Ignored Users: " + config.ignoredUsers.join(', ')); break; case "timer": if (isNumeric(value)) { config.timer = parseInt(value) fs.writeFileSync('buttsbot.config', JSON.stringify(config)); client.say(channel, "Set new timer to " + value + " seconds.") } else { client.say(channel, "Expected a number, got " + value); } break; case "ignore": if (value && value !== "") { console.log(`* ignore: value ok`); value = value.replace("@", ""); if (!config.ignoredUsers.includes(value)) { console.log(`* ignore: value not already ignored`); config.ignoredUsers.push(value); fs.writeFileSync('buttsbot.config', JSON.stringify(config)); } client.say(channel, "User " + value + " will be ignored from now on."); } else { client.say(channel, "Excepted username, got empty value"); } break; case "rmignore": if (value && value !== "") { console.log(`* rmignore: value ok`); value = value.replace("@", ""); if (config.ignoredUsers.includes(value)) { console.log(`* rmignore: value ignored`); let index = config.ignoredUsers.indexOf(value); config.ignoredUsers.splice(index, 1); fs.writeFileSync('buttsbot.config', JSON.stringify(config)); } client.say(channel, "User " + value + " will no longer be ignored."); } else { client.say(channel, "Expected username, got empty value"); } break; case "limit": if (isNumeric(value)) { config.limit = parseInt(value); fs.writeFileSync('buttsbot.config', JSON.stringify(config)); client.say(channel, "Set new limit: 1 butt per " + value + " words"); } else { client.say(channel, "Expected a number, got " + value); } break; default: client.say(channel, "Action '" + action + "' not recognized."); } } else { console.log(`* buttsbot: User not authorized`); } } else { if (config.ignoredUsers.includes(userstate['display-name']) || config.ignoredUsers.includes(userstate['username'])) { console.log(`* User ${userstate['username']} is on the ignore list.`); return; } var checkDate = moment().subtract(config.timer, 'seconds'); if (checkDate < lastMessageButtified) return; if (trimmedMessage.startsWith("!")) return; var words = trimmedMessage.split(' '); var syllables = words.map(syllabify); var buttCount = Math.ceil(words.length / config.limit); var randomNumbersUsed = []; for (var i = 0; i < buttCount; i++) { var random = randomIntFromInterval(1, words.length); while (randomNumbersUsed.includes(random)) random = randomIntFromInterval(1, words.length); randomNumbersUsed.push(random); var word = syllables[random - 1]; if (word) { var randomSyllable = randomIntFromInterval(1, word.length); var firstLetterOfSyllable = word[randomSyllable - 1][0]; word[randomSyllable - 1] = firstLetterOfSyllable == firstLetterOfSyllable.toUpperCase() ? "BUTT" : "butt"; } } var newMessage = ""; syllables.forEach((s) => { if (s != null) newMessage += s.join('') + ' '; }); client.say(channel, newMessage.trim()); lastMessageButtified = moment(); } } function onConnectedHandler (addr, port) { console.log(`* Connected to ${addr}:${port}`); }