Init
This commit is contained in:
commit
b4031b43f9
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
.env
|
||||
twitch.config
|
||||
|
||||
node_modules/
|
||||
167
bot.js
Normal file
167
bot.js
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
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}`);
|
||||
}
|
||||
1
buttsbot.config
Normal file
1
buttsbot.config
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"timer":120,"limit":10,"ignoredUsers":["StreamElements","Nightbot"]}
|
||||
92
package-lock.json
generated
Normal file
92
package-lock.json
generated
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
{
|
||||
"name": "subathonbot",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "subathonbot",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"moment": "^2.29.1",
|
||||
"tmi.js": "^1.8.3"
|
||||
}
|
||||
},
|
||||
"node_modules/moment": {
|
||||
"version": "2.29.1",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
|
||||
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
|
||||
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==",
|
||||
"engines": {
|
||||
"node": "4.x || >=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tmi.js": {
|
||||
"version": "1.8.3",
|
||||
"resolved": "https://registry.npmjs.org/tmi.js/-/tmi.js-1.8.3.tgz",
|
||||
"integrity": "sha512-1YAO3hwnkpAbUfVlpxcqOHP4Nun/+TqxWE/e/ZKMB6p40ZKczhI03oZW2Qx3pppqWjXz5kSjHdT/vTTfi2gCGQ==",
|
||||
"dependencies": {
|
||||
"node-fetch": "^2.6.1",
|
||||
"ws": "^7.4.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "7.4.6",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
|
||||
"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
|
||||
"engines": {
|
||||
"node": ">=8.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": "^5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"moment": {
|
||||
"version": "2.29.1",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
|
||||
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
|
||||
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
|
||||
},
|
||||
"tmi.js": {
|
||||
"version": "1.8.3",
|
||||
"resolved": "https://registry.npmjs.org/tmi.js/-/tmi.js-1.8.3.tgz",
|
||||
"integrity": "sha512-1YAO3hwnkpAbUfVlpxcqOHP4Nun/+TqxWE/e/ZKMB6p40ZKczhI03oZW2Qx3pppqWjXz5kSjHdT/vTTfi2gCGQ==",
|
||||
"requires": {
|
||||
"node-fetch": "^2.6.1",
|
||||
"ws": "^7.4.3"
|
||||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "7.4.6",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
|
||||
"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
|
||||
"requires": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
package.json
Normal file
15
package.json
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"name": "subathonbot",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"moment": "^2.29.1",
|
||||
"tmi.js": "^1.8.3"
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user