oqcrs2
Version:
Please go to: https://twitchapps.com/tmi/ and enter your oauth code into bin/creds.txt
726 lines (678 loc) • 21.5 kB
JavaScript
const tmi = require('tmi.js');
const chalk = require('chalk');
const fs = require('fs');
const {PythonShell} = require ('python-shell');
//#region ###### GLOBAL VARIABLES ######
var game = "";
var CommandsList = [];
var CommandsScripts = {};
var CommandsDesc = {};
var settingGame = false;
let ListOfGames = [];
var isListening = false;
var ListenerNameOption = false;
var isSettingListerName = false;
var isChoosingListner = false;
var isChoosingPresetName = false;
var isValidatingPresetName = false;
var isPresetLoading = false;
var isNormalRunning = true;
var listenerName = "";
var listenersDict = {};
var listenersNamesList = [];
var listenerID = "";
var presetName = "";
var ListOfPresets = [];
var PresetDict = {}
var username = '';
var password = '';
var channels = '';
//#endregion
//#region Client
// const username = 'oq20'
// const password = 'oauth:bwnxrnph0cgank2nik0njnli6f2cgu'
// const channels = 'midgettron2k'
if (fs.existsSync("bin/creds.txt") == false) {
console.log(chalk.bgRed("Please enter credentials into bin/creds.txt"))
process.exit()
}
let creds = "";
var Lines = fs.readFileSync("bin\\creds.txt",'utf8').split("\n");
for(i in Lines){ // reads creds.txt
if(i != 0){
creds = Lines[i].split(",")
console.log(creds.length)
if(creds.length == 2){ // View own channel
username = creds[0];
password = creds[1];
channels = creds[0];
}
if(creds.length == 3){ // View custom channel
username = creds[0];
password = creds[1];
channels = creds[2];
}
}
}
const client = new tmi.Client({
options: { debug: false },
connection: {
secure: true,
reconnect: true
},
identity: {
username: username,
password: password
},
channels: [channels]
});
client.connect();
//#endregion
//#region Get Commands For Game
function getGameScripts(Game){
CommandsList = []
CommandsScripts = {}
try {
var Lines = fs.readFileSync("games\\"+Game+'\\gamescripts.txt','utf8').split("\n")
} catch (error) {
game = ""
console.log(chalk.bgRed("gamescripts.txt not found"))
return
}
for (let line of Lines){
line = line.replace(/\r?\n|\r/g, "");
if(line != ""){
line = line.split(",");
CommandsList.push(line[0])
CommandsScripts[line[0]] = line[1];
CommandsDesc[line[0]] = line[2];
}
}
// Logging
console.log(chalk.white("Command List:", CommandsList))
console.log(chalk.white("Command Dict -- Command : Script"))
prettyJSON(CommandsScripts)
// console.log(chalk.white("Command Desc -- Command : Description"))
// prettyJSON(CommandsDesc)
function prettyJSON(obj) {
console.log(JSON.stringify(obj, null, 4));
}
}
//#endregion
//#region Check If game Is In Focus
function checkGame(game, ScriptName){
var pyshell = new PythonShell("games/"+ game +"\\checkGame.py");
// Verbose on print from python
pyshell.on('message', function (message)
{
if(message == "true"){
runPython(ScriptName)
}
else{
console.log(chalk.red(message));
}
});
// Ends child python script
pyshell.end(function (err,code,signal)
{
if (err) throw err;
if (code != 0)
{
console.log(chalk.red('The exit code was: ' + code));
}
if(signal != null)
{
console.log(chalk.red('The exit signal was: ' + signal));
}
});
}
//#endregion
//#region Runs ScriptName in a python child
function runPython (ScriptName){
var pyshell = new PythonShell("games/"+ game +"\\"+ ScriptName);
// Sends gamename into stdin
// pyshell.send(game);
// Verbose on print from python
pyshell.on('message', function (message)
{
// received a message sent from the Python script (a simple "print" statement)
console.log(chalk.red(message));
});
// Ends child python script
pyshell.end(function (err,code,signal)
{
if (err) throw err;
if (code != 0)
{
console.log(chalk.red('The exit code was: ' + code));
}
if(signal != null)
{
console.log(chalk.red('The exit signal was: ' + signal));
}
console.log(chalk.green("Exited Sucsessfully"))
});
};
//#endregion
//#region Simple logging
function logging (tags, Command, game){
let ts = Date.now();
let date_ob = new Date(ts);
let date = date_ob.getDate();
let month = date_ob.getMonth() + 1;
let year = date_ob.getFullYear();
let hours = date_ob.getUTCHours();
let minutes = date_ob.getUTCMinutes();
var logMessage = "["+year + "-" + month + "-" + date + "-" + hours + ":" +minutes + "] "+`${tags.username}, Activated ` + Command + " in " +game + "\n"
console.log(chalk.yellowBright(logMessage))
fs.appendFile('bin/logging.txt', logMessage, function (err)
{
if (err) return console.log(err);
});
}
//#endregion
//#region general messages
/*
client.on('message', (channel, tags, message, self) => {
// Ignore echoed messages.
if(self) return;
for(let Command of CommandsList){
if(message.toLowerCase() === Command)
{
ScriptName = CommandsScripts[Command]
// Simple Logging
logging(tags, Command, game)
checkGame(game, ScriptName)
}
}
});
*/
//#endregion
//#region Custom Channel Reward Message
client.on('message', (channel, context, tags ,message, self, understate) => {
// Will listen to our set listenerID
if (context["custom-reward-id"] === listenerID) {
console.log(chalk.green("Custom Reward detected"))
for(let Command of CommandsList){
if(tags.toString().toLowerCase() === Command)
{
ScriptName = CommandsScripts[Command]
// Simple Logging
logging(context, Command, game)
checkGame(game, ScriptName)
}
}
}
// Only will run if listening for a new channel reward ID
if(isListening){
console.log(chalk.yellow("ID:") + context["custom-reward-id"])
listenerID = context["custom-reward-id"]
if(listenerName != ""){
console.log(chalk.yellow("ID Found, Adding to bin/customrewardsnames.txt"))
fs.appendFile('bin/customrewardsnames.txt',listenerName + "," +context["custom-reward-id"] + "\n", function (err)
{
if (err) return console.log(err);
});
}
isListening = false;
isSettingListerName = false;
}
});
//#endregion
//#region Console Interface
process.stdin.resume(); // Listens to console
// ###### Commands ######
function menu(){
console.log(chalk.blue(`
:Commands:
help: Veiw this menu
setgame: Select current game
game: View current game
ID: View current listener ID
allgames: list all games
commands: View all commands for a game
listen: Set custom reward to listen for
uselisten: Use an already saved listener
paste: Get paste description for custom reward
save: Save current settings(Including game,gamescripts and custom channel reward)
load: Loads settings (Including game,gamescripts and custom channel reward)
exit`))
}
function SetGame(){
game = "";
console.log("Current Scripts For Games: (Please enter number)");
try {
ListOfGames = fs.readdirSync("games")
} catch (error) {
console.log(chalk.bgRed("games folder not found"))
let v = [null]
return v
}
let k = 0;
for (let i of ListOfGames){
console.log(k+": "+i)
k++
}
console.log(k+": cancel")
process.stdout.write(chalk.yellow("Setting Game To > "));
return ListOfGames
}
function getListeners(){
listenersDict = {}
listenersNamesList = []
var Lines = fs.readFileSync("bin/customrewardsnames.txt",'utf8').split("\n")
let k = 0;
for (let line of Lines){
line = line.replace(/\r?\n|\r/g, "");
if(line != ""){
line = line.split(",");
listenersNamesList.push(line[0])
listenersDict[line[0]] = line[1]
}
}
return listenersNamesList, listenersDict
}
function listallgames(){
try {
ListOfGames = fs.readdirSync("games")
} catch (error) {
console.log(chalk.bgRed("games folder not found"))
}
let k = 0;
for (let i of ListOfGames){
console.log(chalk.white(k+": "+i))
k++
}
return ListOfGames
}
function createPaste(){
var pyshell = new PythonShell("bin/createpaste.py");
// Sends gamename into stdin
for(command of CommandsList){
pyshell.send("c,"+command);
}
let i = 0;
for(command of CommandsList){
pyshell.send("d,"+CommandsDesc[command]);
}
pyshell.send("finish,"+"");
// Verbose on print from python
pyshell.on('message', function (message)
{
// received a message sent from the Python script (a simple "print" statement)
console.log(chalk.blue("Your description for your custom channel reward is:"));
console.log(chalk.white(message));
console.log(chalk.yellow("This is copied to clipboard"));
});
// Ends child python script
pyshell.end(function (err,code,signal)
{
if (err) throw err;
if (code != 0)
{
console.log(chalk.red('The exit code was: ' + code));
}
if(signal != null)
{
console.log(chalk.red('The exit signal was: ' + signal));
}
// console.log(chalk.green("Exited Sucsessfully"))
});
}
function savePreset(presetName){
if (presetName.includes(",")){
console.log(chalk.bgRed("Error, preset name cannot include ','"))
}
else{
preset = presetName + "," + game + "," + listenerName +","+ listenerID + "\n"
fs.appendFile('bin/presets.txt', preset, function (err)
{
if (err) return console.log(err);
});
}
}
function GetAllPresets(){
ListOfPresets = [];
try {
var Lines = fs.readFileSync('bin/presets.txt','utf8').split("\n")
} catch (error) {
game = ""
console.log(chalk.bgRed("bin/presets.txt not found"))
return
}
console.log(chalk.white("Current Saved Presets: (Please Enter Number)"))
let k = 0
for (let line of Lines){
line = line.replace(/\r?\n|\r/g, "");
if(line != ""){
line = line.split(",");
ListOfPresets.push(line[0]);
PresetDict[line[0]] = line[1] + "," + line[3]
console.log(chalk.white(k+ ": Name: " + line[0]))
console.log(chalk.white(" Game: " + line[1]))
if(line[3] != ""){
console.log(chalk.white(" ListenerName: " + line[2]))
}
console.log(chalk.white(" ListenerID: " + line[3]))
k++
}
}
if(k != 0){
console.log(k + ": cancel")
process.stdout.write(chalk.yellow("Preset > "));
}
else{
console.log("No Saved Presets")
return false;
}
}
function GetPresetData(presetName){
let line = PresetDict[presetName].split(",")
game = line[0]
getGameScripts(game)
listenerID =line[1]
}
process.stdin.on('data', function(data)
{
data = data.toString().trim().toLowerCase()
if(isListening == true && data != "cancel"){ // stops user input when listening for custom reward ID
console.log(chalk.red("Listening for custom reaward... (cancel with 'cancel)"))
return
}
//#region Setting game
if(settingGame == true && data == ListOfGames.length && data >= 0 && data != ""){ // Cancel setgame
settingGame = false;
console.log(chalk.blue("Canceling..."))
}
if(settingGame == true){ // Setgame validation
if(data <= ListOfGames.length-1 && data >= 0 && data != ""){
game = ListOfGames[data];
console.log(chalk.green("Set Game To", ListOfGames[data]));
settingGame = false;
isNormalRunning = true;
getGameScripts(game);
}
else{
console.log(chalk.red("Please Enter A Valid Game"))
SetGame()
}
}
//#endregion
//#region Set Listener
if(isSettingListerName == true && ListenerNameOption == false){ // Named listener
listenerName = data;
if(listenerName.includes(",")){
console.log(chalk.bgRed("Error, preset name cannot include ','"))
console.log(chalk.yellow("What would you like to name this listener"));
process.stdout.write(chalk.yellow("> "));
return
}
console.log(chalk.yellow("Naming listener: " + listenerName));
console.log(chalk.yellow("Please go to twitch and redeem your custom channel reward"));
console.log(chalk.blue("Listening for custom reward...."));
isNormalRunning = true;
isSettingListerName = false;
isListening = true;
}
if (ListenerNameOption == true){ // Listen validation
if(data == "n"){
listenerName = "";
console.log(chalk.yellow("Please go to twitch and redeem your custom channel reward"));
console.log(chalk.blue("Listening for custom reward...."));
isNormalRunning = true;
isListening = true;
ListenerNameOption = false;
}
else if(data == "y"){
console.log(chalk.yellow("What would you like to name this listener"));
process.stdout.write(chalk.yellow("> "));
isSettingListerName = true;
ListenerNameOption = false;
}
else {
console.log(chalk.red("Please select (Y/N)"));
}
if(isSettingListerName == false && ListenerNameOption == true){
console.log(chalk.yellow("Would you like to name and save the listener? (Y/N)"))
process.stdout.write(chalk.yellow("> "));
}
}
if(isListening && data == "cancel"){ // Cancel listening
console.log(chalk.blue("Canceling..."))
isListening = false;
isNormalRunning = true;
isSettingListerName = false;
}
//#endregion
//#region Using Listener
if(isChoosingListner == true && data >= 0 &&data <= listenersNamesList.length-1){ // Chose listener
listenerName = listenersNamesList[data];
listenerID = listenersDict[listenerName];
console.log("Changed listener name to: " + listenerName);
console.log("Changed listener ID to: " + listenerID);
isNormalRunning = true;
isChoosingListner = false;
}
if(isChoosingListner == true && data >= 0 && data == listenersNamesList.length && data != ""){ // User canceled choose listener
console.log(chalk.blue("Canceling..."))
isNormalRunning = true;
isChoosingListner = false;
}
if (isChoosingListner == true){ // Displays menu for choosing a listner if user enters wrong
listenersNamesList, listenersDict = getListeners();
console.log(chalk.blue("Listeners"))
k = 0;
for(lisName of listenersNamesList){
console.log(chalk.white(k +": "+ lisName))
k++
}
console.log(chalk.white(k +": cancel"))
console.log("Current saved listeners: (Please enter number)");
process.stdout.write(chalk.yellow("Setting Listener To > "));
}
//#endregion
//#region Saving Preset
if(isChoosingPresetName == true){
if(data == "cancel"){
console.log(chalk.blue("Canceling..."))
isNormalRunning = true;
// isValidatingPresetName = false;
isChoosingPresetName = false;
}
else{
isNormalRunning = true;
isChoosingPresetName = false;
console.log(chalk.blue("Saving preset: " + data + "\nGame: " + game + "\nListenerName: " + listenerName+ "\nListenerID: " + listenerID))
savePreset(data)
}
/* Validation for preset name
else{
presetName = data
console.log(chalk.white("Are you sure you want to name this preset: (Y/N)\n" + data))
process.stdout.write(chalk.yellow("(Y/N) > "));
isValidatingPresetName = true;
isChoosingPresetName = false;
}
}
if(isValidatingPresetName == true){
if(data == "cancel"){
console.log(chalk.blue("Canceling..."))
isNormalRunning = true;
isValidatingPresetName = false
}
else if(data == "y"){
console.log(chalk.blue("Saving preset: " + presetName + "\nGame: " + game + "\nListenerName: " + listenerName+ "\nListenerID: " + listenerID))
savePreset(presetName)
isNormalRunning = true;
isValidatingPresetName = false;
}
else if(data == "n"){
isValidatingPresetName = false;
isChoosingPresetName = true;
console.log(chalk.yellow("What would you like to name this preset?"))
process.stdout.write(chalk.yellow("Preset Name > "));
}
*/
}
//#endregion
//#region Loading Preset
if(isPresetLoading == true){
if(isPresetLoading == true && data == ListOfPresets.length && data >= 0 && data != ""){ // Cancel setgame
isPresetLoading = false;
console.log(chalk.blue("Canceling..."))
isNormalRunning = true;
}
if(isPresetLoading == true){ // Preset number validation
if(data <= ListOfPresets.length-1 && data >= 0 && data != ""){
game = ListOfGames[data];
console.log(chalk.blue("Loading Preset:", ListOfPresets[data]));
isNormalRunning = true;
isPresetLoading = false;
GetPresetData(ListOfPresets[data]);
}
else{
console.log(chalk.red("Please Select A Valid Preset"))
GetAllPresets()
}
}
}
//#endregion
if(isNormalRunning == true){ // Menu commands
if(data == "help"){ // Displays menu
console.clear()
menu()
}
if(data == "exit"){ // exits program, duh
console.log(chalk.greenBright("Exiting Cleanly Thanks For Using OQ's SRS"))
process.exit()
}
if(data == "setgame"){ // Starts set game functions
game = ""
ListOfGames = SetGame()
if(ListOfGames[0] != null){
isNormalRunning = false;
settingGame = true;
}
else{
ListOfGames = []
}
}
if(data == "game"){ // Displays current setgame
console.log(chalk.blue("Current Game =",game))
}
if(data == "id"){ // Displays current ID
console.log(chalk.blue("Current ListenerID =",listenerID))
}
if(data == "allgames"){ // Lists all games in dir games
ListOfGames = listallgames()
}
if(data == "commands"){ // Lists all commands stored in CommandsList
console.log(CommandsList)
}
if(data == "listen"){ // Starts create listener functions
console.log(chalk.yellow("Would you like to name and save the listener? (Y/N)"))
process.stdout.write(chalk.yellow("> "));
isNormalRunning = false;
ListenerNameOption = true;
}
if(data == "uselisten"){ // starts use already set up listener functions
listenersNamesList, listenersDict = getListeners();
console.log(chalk.blue("Listeners"))
k = 0;
for(lisName of listenersNamesList){
console.log(chalk.white(k +": "+ lisName))
k++
}
console.log(chalk.white(k +": cancel"))
isNormalRunning = false;
isChoosingListner = true;
}
if(data == "paste"){ // Runs functions for createing paste description
console.log(chalk.blue("Creating description paste"))
if (game == ""){
console.log(chalk.yellow("Game should be set first"))
}
else{
createPaste()
}
}
if(data == "save"){ // Saves current software settings
if(game == ""){
console.log(chalk.bgRed("Game Is Not Set"))
}
if(listenerID == ""){
console.log(chalk.bgRed("listenerID Is Not Set"))
}
if(game != "" && listenerID != ""){
console.log(chalk.yellow("What would you like to name this preset?"))
process.stdout.write(chalk.yellow("Preset Name > "));
isNormalRunning = false;
isChoosingPresetName = true;
}
}
if(data == "load"){// Loads saved software settings
isNormalRunning = false;
isPresetLoading = true;
let valid = true;
valid = GetAllPresets()
if (valid == false){
isNormalRunning = true;
isPresetLoading = false;
}
}
}
});
console.clear()
// ###### OQ Spam ######
function spam(){
console.log(chalk.yellow(`
.d88888b. .d88888b. .d8888b. 8888888b. .d8888b.
d88P" "Y88b d88P" "Y88b d88P Y88b 888 Y88b d88P Y88b
888 888 888 888 888 888 888 888 Y88b.
888 888 888 888 888 888 d88P "Y888b.
888 888 888 888 888 8888888P" "Y88b.
888 888 888 Y8b 888 888 888 888 T88b "888
Y88b. .d88P Y88b.Y8b88P Y88b d88P 888 T88b Y88b d88P
"Y88888P" "Y888888" "Y8888P" 888 T88b "Y8888P"
Y8b
_____ _ _ _____ _ _____ __ _
/ ____| | | | | __ \\ | | / ____| / _| |
| | | |__ __ _ _ __ _ __ ___| | | |__) |_____ _____ _ __ __| | | (___ ___ | |_| |___ ______ ________
| | | '_ \\ / _ | '_ \\| '_ \\ / _ | | | _ // _ \\ \\ /\\ / / _ | '__/ _ | \\___ \\ / _ \\| _| __\\ \\ /\\ / / _ | '__/ _ \\
| |____| | | | (_| | | | | | | | __| | | | \\ | __/\\ V V | (_| | | | (_| | ____) | (_) | | | |_ \\ V V | (_| | | | __/
\\_____|_| |_|\\__,_|_| |_|_| |_|\\___|_| |_| \\_\\___| \\_/\\_/ \\__,_|_| \\__,_| |_____/ \\___/|_| \\__| \\_/\\_/ \\__,_|_| \\___|
`))
// ###### Contact ######
console.log(chalk.yellow(`
:Contact:
Discord: 【OQ】#2213
Steam: OQTV #115322040
`))
}
// Only spams if its a user
try {
if (fs.existsSync("developer.txt")) {
console.log("Your a developer")
}
else{
spam()
}
} catch(err) {
console.error(err)
}
menu()
//#endregion
/* #region ############################## IDEAS ##############################
EOL = Ease of Life
REQ = Requirement
EOL Add functionality for multiple custom rewards to be used
EOL create better menu
EOL create tutorial mark down
EOL Add ability to set default description paste by user instead of my default "TYPE {commandName} ({commandDesc})"
REQ pip install required modules for python
REQ install modules for this file
EOL remove ability to name reward ID's the same
REQ Play music/ have feedback for stream to know whats happening
EOl Add front end
Including adding the ability to enter creds this way through form
#endregion */