From c1039650de4b1f7f8a5b40af092fd3fe1bdb4a76 Mon Sep 17 00:00:00 2001 From: 3urobeat <35304405+HerrEurobeat@users.noreply.github.com> Date: Wed, 15 Jan 2020 22:38:47 +0100 Subject: [PATCH] Initial commit of version 2.0 --- README.md | 8 ++- bot.js | 154 ++++++++++++++++++++++++++++++++++++++++++++++++++++ config.json | 12 ++++ quotes.txt | 3 + start.js | 98 +++++++++++++++++++++++++++++++++ 5 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 bot.js create mode 100644 config.json create mode 100644 quotes.txt create mode 100644 start.js diff --git a/README.md b/README.md index ed81707c..a6fa4541 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,8 @@ You can either provide multiple quotes for a random one every time or only one f The start script will start as many bots as you provide login-informations for. If you are planning to build your bot imperium this could be a great place to start from. Continue reading for a detailed setup guide. -**Disclaimer!** > I am not responsible and cannot be held liable for any action the operator/user of this bot uses it for. +**Disclaimer!** > I am not responsible and cannot be held liable for any action the operator/user of this bot uses it for. +If you, the user, download or use this application, you agree that only you are responsible for any action. ## Requirements @@ -39,12 +40,17 @@ Open `config.json` with a text editor. You can customize the values below `versi | ------------- | ---------------- | ----- | | mode | 1 or 2 | Mode 1: All bots you have logininformations provided for will start up and work for themselves. Mode 2: The first logininfo will start a bot and when a comment is requested all accounts you have provided logininfos for will comment under that one profile. | | status | [Status Codes](https://github.com/DoctorMcKay/node-steam-user/blob/master/enums/EPersonaState.js) | Sets your status. (Online, Busy etc.) | +| commentdelay | Delay in ms | Adds a delay between each comment to prevent a cooldown from steam. Default: 5000 +| logindelay | Delay in ms | Adds a delay between each login when the bot is started to prevent a cooldown from steam. Default: 2500 | game | "my game name" | This custom text will be shown on your profile as the name of a game you are playing. | | yourgroup | "link to my group" | Advertise your group with the !group command. Leave it empty (like this: "") to disable the command. | | yourgroup64id | "my group64id" | [How do I get this ID?](https://steamcommunity.com/sharedfiles/filedetails/?id=1344514370) The bot will send a group invite instead of the link to your group from above. If no ID is provided, the bot will send the link from above but no invite. | | owner | "link to my profile" | Advertise your own profile with the !owner command. Leave it empty (like this: "") to disable the command. | +Open `quotes.txt` with a text editor. You can add as many quotes as you want, line by line. **Don't leave an empty line anywhere in this file!** +The bot will choose a random quote for **every** comment. If you only provide one quote, the bot will only use that quote. + The bot(s) is/are now setup. ## Starting the bot diff --git a/bot.js b/bot.js new file mode 100644 index 00000000..0c2069ba --- /dev/null +++ b/bot.js @@ -0,0 +1,154 @@ +//Code by: https://github.com/HerrEurobeat/ + +module.exports.run = async (logOnOptions, loginindex) => { + const SteamUser = require('steam-user'); + const SteamCommunity = require('steamcommunity'); + const SteamID = require('steamid'); + var start = require("./start.js") + const config = require('./config.json'); + const logininfo = require('./logininfo.json'); + var logger = start.logger + + const bot = new SteamUser(); + const community = new SteamCommunity(); + + if (config.mode === 1) var thisbot = `Bot ${loginindex}` + else var thisbot = "Main" + + var loggedininterval = setInterval(() => { //set an interval to check if previous acc is logged on + if(start.accisloggedin === true) { + bot.logOn(logOnOptions) + start.accisloggedin = false; //set to false again + clearInterval(loggedininterval) //stop interval + } + }, 250); + + bot.on('steamGuard', function(domain, callback) { + process.stdout.write(`[${logOnOptions.accountName}] Steam Guard Code: `) + var stdin = process.openStdin(); + + stdin.addListener('data', text => { + var code = text.toString().trim() + callback(code); + + stdin.pause() //stop reading + }) + }); + + //Log in: + bot.on('loggedOn', () => { + start.accisloggedin = true; //set to true to log next account in + bot.setPersona(config.status); + if (config.mode === 1) { //individual mode + bot.gamesPlayed([config.game,730]); //set game for all bots + } else if (config.mode === 2) { //connected mode + if (loginindex === 0) bot.gamesPlayed([config.game,730]); //set game only for the "leader" bot + } + + start.communityobject[loginindex] = community //export this community instance to the communityobject + start.botobject[loginindex] = bot //export this bot instance to the botobject + }); + + bot.on("webSession", (sessionID, cookies) => { + community.setCookies(cookies); + //Accept offline group & friend invites + for (let i = 0; i < Object.keys(bot.myFriends).length; i++) { //Credit: https://dev.doctormckay.com/topic/1694-accept-friend-request-sent-in-offline/ + if (bot.myFriends[Object.keys(bot.myFriends)[i]] == 2) { + bot.addFriend(Object.keys(bot.myFriends)[i]); + logger(`[${thisbot}] Added user while I was offline! User: ` + Object.keys(bot.myFriends)[i]) + bot.chatMessage(Object.keys(bot.myFriends)[i], 'Hello there! Thanks for adding me!\nRequest a free comment with !comment\nType !help for more info!') + bot.inviteToGroup(Object.keys(bot.myFriends)[i], new SteamID(config.yourgroup64id)); + }} + for (let i = 0; i < Object.keys(bot.myGroups).length; i++) { + if (bot.myGroups[Object.keys(bot.myGroups)[i]] == 2) { + bot.respondToGroupInvite(Object.keys(bot.myGroups)[i], true) + logger(`[${thisbot}] Accepted group invite while I was offline: ` + Object.keys(bot.myGroups)[i]) + }} + }); + + //Message interactions + bot.on('friendMessage', function(steamID, message) { + if (loginindex > 0) { + switch(message.toLowerCase()) { + case '!help': + if (config.owner.length > 1) var ownertext = "\nType !owner to check out my owner's profile!"; else var ownertext = ""; + if (config.yourgroup.length > 1) var yourgrouptext = "\n\nJoin my !group"; else var yourgrouptext = ""; + bot.chatMessage(steamID, `Type !comment to get a free comment!\nType !ping for a pong!\nType !about for credit.${ownertext}${yourgrouptext}`) + break; + case '!comment': + community.getSteamUser(bot.steamID, (err, user) => { //check if acc is limited and if yes if requester is on friendlist + if(user.isLimitedAccount && !Object.keys(bot.myFriends).includes(new SteamID(steamID.getSteam3RenderedID()).getSteamID64())) return bot.chatMessage(steamID, "You have to send me a friend request before I can comment on your profile!")}) + community.getSteamUser(steamID, (err, user) => { //check if profile is private + if(user.privacyState !== "public") return bot.chatMessage(steamID, "Your profile seems to be private. Please edit your privacy settings on your profile and try again!") }); + + var randomstring = arr => arr[Math.floor(Math.random() * arr.length)]; + var comment = randomstring(start.quotes); + community.postUserComment(steamID, comment, (error) => { + if(error !== null) { logger(`[${thisbot}] postUserComment error: ${error}`); return; } + logger(`[${thisbot}] Comment: ${comment}`) + if (config.mode === 1) bot.chatMessage(steamID, 'Okay I commented on your profile! If you are a nice person then leave a +rep on my profile!') + else { + var waittime = (Object.keys(logininfo).length * config.commentdelay) / 1000 + var waittimeunit = "seconds" + if (waittime > 120) { var waittime = waittime / 60; var waittimeunit = "minutes" } + if (waittime > 120) { var waittime = waittime / 60; var waittimeunit = "hours" } + bot.chatMessage(steamID, `Estimated wait time for ${Object.keys(logininfo).length} comments: ${Number(Math.round(waittime+'e'+3)+'e-'+3)} ${waittimeunit}.`) } + }) + + if (config.mode === 2) { + start.commenteverywhere(steamID) //Let all other accounts comment if the mode is activated + bot.chatMessage(steamID, `The other ${Object.keys(logininfo).length} comments should follow with a delay of ${config.commentdelay}ms.`) + } + break; + case '!ping': + bot.chatMessage(steamID, 'Pong!') + break; + case '!owner': + if (config.owner.length < 1) return bot.chatMessage(steamID, "I don't know that command. Type !help for more info.") + bot.chatMessage(steamID, "Check my owner's profile: '" + config.owner + "'") + break; + case '!group': + if (config.yourgroup.length < 1 && config.yourgroup64id.length < 1) return bot.chatMessage(steamID, "I don't know that command. Type !help for more info.") //no group info at all? stop. + if (config.yourgroup64id.length > 1) { bot.inviteToGroup(steamID, new SteamID(config.yourgroup64id)); bot.chatMessage(steamID, "I send you an invite! Thanks for joining!"); return; } //id? send invite and stop + bot.chatMessage(steamID, "Join my group here: " + config.yourgroup) //seems like no id has been saved but an url. Send the user the url + break; + case '!about': + if (config.owner.length > 1) var ownertext = config.owner; else var ownertext = "anonymous (no owner link provided)"; + bot.chatMessage(steamID, `This bot was created by 3urobeat.\nGitHub: https://github.com/HerrEurobeat/steam-comment-service-bot \nSteam: https://steamcommunity.com/id/3urobeat \nDisclaimer: I (the developer) am not responsible and cannot be held liable for any action the operator/user of this bot uses it for.\n\nThis instance of the bot is used and operated by: ${ownertext}`) + break; + default: + bot.chatMessage(steamID, "I don't know that command. Type !help for more info.") } + } else { + if (config.mode === 2) { + switch(message.toLowerCase()) { + case '!about': + if (config.owner.length > 1) var ownertext = config.owner; else var ownertext = "anonymous (no owner link provided)"; + bot.chatMessage(steamID, `This bot was created by 3urobeat.\nGitHub: https://github.com/HerrEurobeat/steam-comment-service-bot \nSteam: https://steamcommunity.com/id/3urobeat \nDisclaimer: I (the developer) am not responsible and cannot be held liable for any action the operator/user of this bot uses it for.\n\nThis instance of the bot is used and operated by: ${ownertext}`) + break; + default: + bot.chatMessage(steamID, "This is one account running in a bot cluster.\nPlease add the main bot and send him a !help message.\nIf you want to check out what this is about, type: !about") + }} + } + logger(`[${thisbot}] Friend message from ${steamID.getSteam3RenderedID()}: ${message}`); + }); + + //Friend requests + bot.on('friendRelationship', (steamid, relationship) => { + if (relationship === 2) { + bot.addFriend(steamid); + logger(`[${thisbot}] Added User: ` + steamid) + bot.chatMessage(steamid, 'Hello there! Thanks for adding me!\nRequest a free comment with !comment\nType !help for more info!'); + } + }); + + bot.on('groupRelationship', (steamid, relationship) => { + if (relationship === 2) { + bot.respondToGroupInvite(steamid, true) + logger(`[${thisbot}] Accepted group invite: ` + steamid) + } + }); + + module.exports={ + bot + } +} \ No newline at end of file diff --git a/config.json b/config.json new file mode 100644 index 00000000..9a962d90 --- /dev/null +++ b/config.json @@ -0,0 +1,12 @@ +{ + "version": "2.0", + + "mode": 2, + "status": 1, + "commentdelay": 5000, + "logindelay": 2500, + "game": "!help | 3urobeat", + "yourgroup": "https://steamcommunity.com/groups/3urobeatGroup", + "yourgroup64id": "103582791464712227", + "owner": "https://steamcommunity.com/id/3urobeat/" +} \ No newline at end of file diff --git a/quotes.txt b/quotes.txt new file mode 100644 index 00000000..30e53e73 --- /dev/null +++ b/quotes.txt @@ -0,0 +1,3 @@ +comment1 +comment2 +comment3 \ No newline at end of file diff --git a/start.js b/start.js new file mode 100644 index 00000000..adef162e --- /dev/null +++ b/start.js @@ -0,0 +1,98 @@ +//Code by: https://github.com/HerrEurobeat/ + +var b = require('./bot.js'); +const logininfo = require('./logininfo.json'); +const config = require('./config.json'); +const SteamID = require('steamid'); +var fs = require("fs"); + +var communityobject = new Object(); +var botobject = new Object(); +const d = function d() { return new Date(); } +var bootstart = 0; +var bootstart = d(); + + +//Functions: +var logger = function logger(string) { //Custom logger + console.log(string) + fs.appendFileSync('./output.txt', string.replace(/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]/g, '') + '\n', err => { //Credit: https://github.com/Filirom1/stripcolorcodes + if(err) logger(LOGERR + 'Error: ' + err) }) } + +process.on('unhandledRejection', (reason, p) => { + logger(`Unhandled Rejection! Reason: ${reason.stack}`) }); + +var quotes = new Array(); +var quotes = fs.readFileSync('quotes.txt', 'utf8').split("\n"); //get all quotes from the quotes.txt file into an array + +var commenteverywhere = function commenteverywhere(steamID) { //function to let all bots comment + var failedcomments = new Array(); + Object.keys(communityobject).forEach((k, i) => { + if (i < 1) return; //first account already commented + + communityobject[k].getSteamUser(botobject[k].steamID, (err, user) => { //check if acc is limited and if yes if requester is on friendlist + if(user.isLimitedAccount && !Object.keys(botobject[k].myFriends).includes(new SteamID(steamID.getSteam3RenderedID()).getSteamID64())) return failedcomments.push(botobject[k].steamID.getSteam3RenderedID())}) + communityobject[k].getSteamUser(steamID, (err, user) => { //check if profile is private + if(user.privacyState !== "public") return failedcomments.push(botobject[k].steamID.getSteam3RenderedID())}); + + var randomstring = arr => arr[Math.floor(Math.random() * arr.length)]; + var comment = randomstring(quotes); + setTimeout(() => { + communityobject[k].postUserComment(steamID, comment, (error) => { + if(error !== null) { logger(`[Bot ${k}] postUserComment error: ${error}`); failedcomments.push(botobject[k].steamID.getSteam3RenderedID()); return; } + logger(`[Bot ${k}] Comment: ${comment}`) }) + + if (Object.keys(communityobject).length === i+1) { botobject[0].chatMessage(steamID, `All comments have been sent. Failed: ${failedcomments.length}/${i+1}`) } + }, config.commentdelay * i); //delay every comment + })} + +accisloggedin = true; //var to check if previous acc is logged on (in case steamGuard event gets fired) -> set to true for first account + +module.exports={ + logger, + communityobject, + botobject, + commenteverywhere, + quotes, + accisloggedin } + +//Size of accounts - 1 (first acc logs in instantly) * logindelay -> wait time / 100 -> ms to seconds + 1 tolerance second +logger(`\x1b[34m[${bootstart}]\x1b[0m Logging in... Estimated wait time: ${((config.logindelay * (Object.keys(logininfo).length - 1)) / 1000) + 1} seconds.`) + +//Logging in: +Object.keys(logininfo).forEach((k, i) => { + setTimeout(() => { + var logOnOptions = { + accountName: logininfo[k][0], + password: logininfo[k][1], + promptSteamGuardCode: false, + machineName: "3urobeat's Commment Bot" + }; + b.run(logOnOptions, i); + }, config.logindelay * i); +}) + +if (config.mode !== 1 && config.mode !== 2) { + logger("\x1b[31mThe mode you provided is invalid! Please choose between 1 or 2. Aborting...\x1b[0m") + process.exit(0); } + + +var readyinterval = setInterval(() => { //log startup to console + if (Object.keys(communityobject).length === Object.keys(logininfo).length) { + logger(' ') + logger('*------------------------------------------*') + if (config.mode === 2) logger(`\x1b[34m${logininfo.bot1[0]}\x1b[0m version ${config.version} with ${Object.keys(communityobject).length - 1} accounts logged in.`); + else logger(`Started ${Object.keys(logininfo).length} accounts version ${config.version}.`); + + communityobject[0].getSteamUser(botobject[0].steamID, (err, user) => { //display warning if account is limited + if(user.isLimitedAccount) var limitedacc = "Leader Bot has a \x1b[31mlimited account\x1b[0m!"; + else var limitedacc = "" + logger(`Using Mode ${config.mode}. ${limitedacc}`) + const bootend = d() - bootstart + logger('Ready after ' + bootend + 'ms!') + logger('*------------------------------------------*') + logger(' ') + }) + clearInterval(readyinterval) + } +}, 100); \ No newline at end of file