Skip to content

Instantly share code, notes, and snippets.

@SunRed
Last active September 11, 2019 05:36
Show Gist options
  • Save SunRed/5017b5353714b44b804e6179c311fae2 to your computer and use it in GitHub Desktop.
Save SunRed/5017b5353714b44b804e6179c311fae2 to your computer and use it in GitHub Desktop.
Poorly written lurk bot for Twitch in node
var channels = {};
channels.required = [
// Channels you will always lurk in (as long as the list is smaller than config.maxChannels)
];
channels.pool = [
// Channels of which you randomly lurk in whenever the channels get rerolled (config.rerollCronjob)
// These are used to fill the pool of channels up to the config.maxChannels value in case channels.required doesn't reach that value in size
];
module.exports = channels;
var clients = [
// [ "username", "oauthtoken" ],
[ "example", "h4kx832brkd82kf73k5gsd5k238dfh" ],
[ "", "" ],
];
module.exports = clients;
var config = {
rerollCronjob: '0 0 */3 * * *', // Time when reroll/reconnect of channels should happen
maxChannels: 1000, // Maximum channels to join
timezone: 'Europe/Berlin',
rawUserString: 'USER IRC-CLIENT v1.0.4',
debugMode: false,
// Whisper yourself whenever you get mentioned somewhere in a chat you're lurking in using a second account
whisperBot: false,
// whisperBot: {
// name: "",
// oauth: ""
// }
};
module.exports = config;
const tmi = require('tmi.js');
const cron = require('cron');
const clients = require('./clients');
const channels = require('./channels');
const config = require('./config');
const sleep = (waitTimeInMs) => new Promise(resolve => setTimeout(resolve, waitTimeInMs));
const sessions = [];
var whisperBot = false;
if (config.whisperBot) {
whisperBot = new tmi.client({
options: {
debug: false
},
connection: {
cluster: "aws",
reconnect: true,
secure: true
},
identity: {
username: config.whisperBot.name.toLowerCase(),
password: config.whisperBot.oauth
}
});
whisperBot.connect();
}
const clientsJoinChannels = async () => {
// If this is executed by a cronjob we want to disconnect first
if (sessions.length > 0) {
while(sessions.length > 0) {
sessions.shift().disconnect();
}
console.log("Waiting 3 seconds before restarting...");
await sleep(3000);
}
clients.forEach(async credentials => {
let mergedChannelList = [];
let requiredChannelList = channels.required;
let poolChannelList = channels.pool;
// Remove required channels to be included from the pool list to avoid duplicates
// (May not be necessary)
requiredChannelList.forEach(channel => {
for (let i = 0; i < poolChannelList.length; i++) {
if (poolChannelList[i] === channel) {
poolChannelList.splice(i, 1);
}
}
});
mergedChannelList = requiredChannelList.concat(shuffle(poolChannelList));
const options = {
options: {
debug: false
},
connection: {
cluster: "aws",
reconnect: true,
secure: true
},
identity: {
username: credentials[0].toLowerCase(),
password: credentials[1]
},
channels: mergedChannelList.slice(0, config.maxChannels-1)
};
const client = new tmi.client(options);
client.on("message", (channel, userstate, message, self) => {
if (self) return; // Ignore messages from this client
if (!whisperBot) return; // Stop here if no whisper bot has been specified
if (whisperBot.getUsername() === client.getUsername()) return; // Ignore messages for our whisper account because we cannot send ourselves whispers anyway
if (userstate.username === client.getUsername()) return; // Ignore messages from same account as our client
if (userstate["message-type"] === "whisper") return; // Ignore whispers completely
// Send messages to us via whisper if we get mentioned
if (message.toLowerCase().indexOf(client.getUsername()) === -1) return; // We didn't get mentioned in chat
if (config.debugMode) console.log(userstate.username + " mentioned " + client.getUsername() + " in chat. Sending whisper...");
whisperBot.whisper(client.getUsername(), (userstate.mod ? "[M] " : "") + userstate["display-name"] + " mentioned you in channel '" + channel + "' with the following message: " + message);
});
client.on("join", (channel, username, self) => {
if (self && config.debugMode) console.log("Joined channel '" + channel + "' as " + username);
});
client.on("part", (channel, username, self) => {
if (self && config.debugMode) console.log("Left channel '" + channel + "' as " + username);
});
// client.on("connected", (address, port) => {
//
// });
client.on("connecting", (address, port) => {
client.raw(config.rawUserString)
.then((data) => {
if (config.debugMode) console.log("Sent USER command as " + client.getUsername());
}).catch((err) => {
console.log("An error occured while sending USER command: ", err);
});
});
client.on("logon", () => {
console.log("Connected as " + client.getUsername());
if (config.debugMode) {
sleep(3000).then(() => {
client.say(config.whisperBot.name, "HONEYDETECTED Lurk bot reconnected.")
});
}
});
client.on("reconnect", () => {
console.log("Reconnected as " + client.getUsername());
});
client.on("disconnected", (reason) => {
console.log("Disconnected as " + client.getUsername());
});
client.connect();
sessions.push(client);
});
};
const clientsJoinChannelsCronJob = new cron.CronJob(config.rerollCronjob, clientsJoinChannels, null, true, config.timezone, false, true);
const sigs = ['SIGINT', 'SIGTERM', 'SIGQUIT'];
sigs.forEach(sig => {
process.on(sig, () => {
console.log(sig + " received");
clientsJoinChannelsCronJob.stop();
sessions.forEach(client => {
client.disconnect();
});
if (whisperBot) whisperBot.disconnect();
console.log("Waiting 3 seconds before exiting...");
sleep(3000).then(() => {
process.exit(0);
});
});
});
/**
* Fisher-Yates shuffle - Shuffles array in place
* @param {Array} a items An array containing the items.
*/
function shuffle(a) {
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[a[i], a[j]] = [a[j], a[i]];
}
return a;
}
{
"name": "lurkbot-node",
"version": "0.0.3",
"description": "Twitch lurk bot",
"main": "lurkbot.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "SunRed",
"license": "MIT",
"dependencies": {
"cron": "^1.7.2",
"tmi.js": "^1.4.5"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment