Compare commits

..

10 commits

10 changed files with 140 additions and 13 deletions

2
.gitignore vendored
View file

@ -1,3 +1,3 @@
node_modules/ node_modules/
package-lock.json package-lock.json
source_output.txt *.txt

View file

@ -1,8 +1,12 @@
# :warning: Hey you! :warning:
This repo contains a new and ongoing project. Currently, this repo works and installs correctly on the 3 systems I tested this on, but there are more features and polishing to be done. With that being said, enjoy!
# `lset`: The **L**inux **S**treamer's **E**ssential **T**oolkit # `lset`: The **L**inux **S**treamer's **E**ssential **T**oolkit
Ever wanted to stream on Linux and *really* don't want to mess with any yucky online services to make your stream worthwhile? Well now you can, using your own self hosted tools! Ever wanted to stream on Linux and *really* don't want to mess with any yucky online services to make your stream worthwhile? Well now you can, using your own self hosted tools!
Here you can find two separate programs: a Node.JS Twitch bot and a Python script for a follower/sub goal. In order to set it up, read the [installing](#installing) section of this README, or you can view the documents for both the [Twitch bot]() and the [Python script]() to set them up separately. Here you can find two separate programs: a Node.JS Twitch bot and a Python script for a follower/sub goal. Both of these scripts stem off the scripts I made for my streams, just heavily altered so they can be configured using JSON files. In order to set it up, read the [installing](#installing) section of this README, or you can view the documents for both the [Twitch bot]() and the [Python script]() to set them up separately.
## Installing ## Installing
@ -24,22 +28,27 @@ python3
pip3 pip3
``` ```
You can install these with the following commands in these distros. You will most likely need to run `sudo` before any of these commands. The following instructions are for Linux (and possibly other \*NIX systems). You can view the installation instructions for macOS and Windows here:
* [macOS](doc/MACOS.md)
* [Windows]() (COMING SOON)
You can install these with the following commands in these distros:
### Ubuntu/Debian ### Ubuntu/Debian
```bash ```bash
# apt install git npm nodejs python3 python3-pip $ sudo apt install git npm nodejs python3 python3-pip
``` ```
### Fedora/CentOS/Other RHEL ### Fedora/CentOS/Other RHEL
```bash ```bash
# yum install git npm nodejs python3 python3-pip # if 'yum' is not found, you should try 'dnf'
$ sudo yum install git npm nodejs python3 python3-pip
``` ```
### Arch/Manjaro ### Arch/Manjaro
```bash ```bash
# pacman -S git npm nodejs python3 python-pip $ sudo pacman -S git npm nodejs python3 python-pip
``` ```
### openSUSE ### openSUSE
```bash ```bash
# zypper install git npm16 nodejs16 python3 python3-pip $ sudo zypper install git npm16 nodejs16 python3 python3-pip
``` ```
### Other Distros/BSD ### Other Distros/BSD
If you fit this description, you probably know what you're doing. If you fit this description, you probably know what you're doing.

0
doc/INSTALL.md Normal file
View file

16
doc/MACOS.md Normal file
View file

@ -0,0 +1,16 @@
# macOS Installation
To install `lset` on macOS, you need to make sure that you have the Command Line Tools installed. The easiest way to make sure they are downloaded is to open the Terminal app and run:
```bash
% git
```
If you have the tools installed, `git` will display a help message. If you don't, a window should appear asking if you would like to install them.
You will also need to install Node.js and npm, both of which can be installed through one package found on the downloads section of the [Node.js Website](https://nodejs.org/en/download/).
Once you have both items installed, you will be able to run the same files (`install.sh` and `run.sh`) as you would on Linux:
```bash
# note: if you use './install.sh' or './run.sh', the read command may not work properly
% sh install.sh
% sh run.sh
```

0
doc/TWITCH-ACC.md Normal file
View file

0
doc/WINDOWS.md Normal file
View file

View file

@ -48,6 +48,7 @@ cd ..
echo echo
echo "install: installing tmi node module for the twitch bot" echo "install: installing tmi node module for the twitch bot"
cd twitch-bot cd twitch-bot
touch mods.txt trusted_users.txt
npm install tmi.js npm install tmi.js
cd .. cd ..

View file

@ -46,29 +46,51 @@ const opts = {
channels: settings.channels channels: settings.channels
}; };
const linkProtection = settings.link_protection;
const bannedUrlEndings = settings.banned_endings;
var modString = ""; var modString = "";
var mods; var mods;
try { try {
modString = fs.readFileSync('mods.txt', 'utf8'); modString = fs.readFileSync('mods.txt', 'utf8');
trustedString = fs.readFileSync('trusted_users.txt', 'utf8');
modString = modString.replace(/(\r\n|\n|\r)/gm, ""); modString = modString.replace(/(\r\n|\n|\r)/gm, "");
trustedString = trustedString.replace(/(\r\n|\n|\r)/gm, "");
console.log('* Loaded mods and trusted users from file.');
mods = modString.split(","); mods = modString.split(",");
trustedUsers = trustedString.split(",");
} catch (err) { } catch (err) {
console.error(err) console.error(err)
} }
var modCommand = false; var modCommand = false;
var message, fullMessage;
function onMessageHandler (target, context, msg, self) { function onMessageHandler (target, context, msg, self) {
if (self) { return; } // Ignore messages from the bot if (self) { return; } // Ignore messages from the bot
const user = context.username; const user = context.username;
// save full message if adding/editing command
fullMessage = msg.trim();
msg = msg.toLowerCase(); msg = msg.toLowerCase();
var message = msg.trim(); message = msg.trim();
// link protection stuff, only enables when true in settings.json
var findUrlEndings = false;
if (linkProtection) {
for (var i=urlEndings.length; i--;) {
if (message.includes(urlEndings[i])) findUrlEndings = true;
else if (message.includes(urlEndings[i].replace('.', '*'))) findUrlEndings = true;
}
}
if (message.charAt(0) === settings.command_char) { if (message.charAt(0) === settings.command_char) {
message = message.substr(1); message = message.substr(1);
valid = commands(target, message, user, mods); valid = commands(target, message, user, mods);
} else { } else {
if (linkProtection && findUrlEndings)
if (!linkProtect())
reactions(target, message, user);
else
reactions(target, message, user); reactions(target, message, user);
} }
} }
@ -115,14 +137,20 @@ function commands (target, commandName, user, mods) {
} }
} }
function modCommands(target, commandName, isMod) { function modCommands(target, commandName, message, isMod) {
var valid = false; var valid = false;
mod_commands.forEach(command => { test_mod_commands = ["addcommand", "editcommand"];
if (message.search(command.command) !== -1) { test_mod_commands.forEach(command => {
if (commandName.search(command) !== -1) {
if (!isMod) { if (!isMod) {
client.say(target, `Only moderators can run this command...`); client.say(target, `Only moderators can run this command...`);
return true; return true;
} else { } else {
if (command === "addcommand") {
createCommand(target);
} else if (command === "editcommand") {
editCommand(target);
}
client.say(target, `${command.reply}`); client.say(target, `${command.reply}`);
valid = true; valid = true;
return true; return true;
@ -132,6 +160,52 @@ function modCommands(target, commandName, isMod) {
return valid; return valid;
} }
function createCommand(target) {
chat_commands.forEach(command => {
if (fullMessage[1].search(command.command) !== -1) {
client.say(target, `The command ${settings.command_char}${fullMessage[1]} already exists. Use !editcommand to change it's contents.`);
return false;
}
});
var command_reply = "";
for (int i = 2; i < fullMessage.length; i++) {
command_reply = command_reply + fullMessage[i] + " ";
}
chat_commands.push(['command': fullMessage[1], 'reply': command_reply]);
try {
const data = JSON.stringify(chat_commands, null, 4);
fs.writeFileSync('commands.json', data);
console.log('* Added command ' + settings.command_char + fullMessage[1]);
client.say(target, `Successfully added command: ${settings.command_char}${fullMessage[1]}`);
} catch (err) {
console.error('An error occured trying to run !addcommand: ' + err);
client.say(target, `Something went wrong adding this command, please try again later.`);
}
}
function editCommand(target) {
chat_commands.forEach(command => {
if (fullMessage[1].search(command.command) !== -1) {
var command_reply = "";
for (int i = 2; i < fullMessage.length; i++) {
command_reply = command_reply + fullMessage[i] + " ";
}
chat_commands[fullMessage[1]] = command_reply;
try {
const data = JSON.stringify(chat_commands, null, 4);
fs.writeFileSync('commands.json', data);
console.log('* Edited command ' + settings.command_char + fullMessage[1]);
client.say(target, `Successfully edited existing command: ${settings.command_char}${fullMessage[1]}`);
} catch (err) {
console.error('An error occured trying to run !editcommand: ' + err);
client.say(target, `Something went wrong editing this command, please try again later.`);
}
return true;
}
});
return false;
}
function reactions (target, message, user) { function reactions (target, message, user) {
reacts.forEach(react => { reacts.forEach(react => {
if (message.search(react.trigger) !== -1) { if (message.search(react.trigger) !== -1) {
@ -140,6 +214,30 @@ function reactions (target, message, user) {
}); });
} }
function linkProtect() {
if (trustedUsers.indexOf(user) === -1) {
if (message.search("http") !== -1 || message.search("www.") !== -1 || findUrlEndings) {
urlAttempt = message;
urlAttemptUser = user;
console.log(`! ${user} tried to post a URL. Warned and timedout for 10 seconds. Message: "${urlAttempt}"`);
client.say(target, `/timeout ${user} 10 Links from untrusted users are deleted as a protection against chat bots.`);
client.say(target, `@${user} Your link was deleted because you haven't been in my chat before. If you have a legitimate link and aren't a bot, let me know!`);
// is a bot, don't go farther
return true;
} else {
trustedString = trustedString + `,${user}`;
trustedString = trustedString.replace(/(\r\n|\n|\r)/gm, "");
trustedUsers.push(user);
fs.writeFile('trusted_users.txt', `${trustedString}`, function (err) {
if (err) return console.log(err);
console.log(`* ${user} is now a trusted chatter.`);
});
// not a bot, move on to reactions
return false;
}
}
}
// Twitch bot initialization // Twitch bot initialization
const client = new tmi.client(opts); const client = new tmi.client(opts);

View file

@ -3,5 +3,8 @@
"bot_token": "enter the token that you generate here", "bot_token": "enter the token that you generate here",
"your_username": "YOUR_username_not_your_bots_username", "your_username": "YOUR_username_not_your_bots_username",
"channels" : [ "enter the channel names for the bot to join", "you can have multiple!" ], "channels" : [ "enter the channel names for the bot to join", "you can have multiple!" ],
"command_char": "!" "command_char": "!",
"link_protection": false,
"banned_endings": [".com", ".org", ".edu", ".gov", ".gg", ".io", ".tv", ".uk", ".net", ".ca", ".de", ".jp", ".fr", ".au", ".us", ".ru", ".ch", ".it", ".nl", ".se", ".no", ".es", ".mil", ".xyz", ".top", ".info"]
} }