SteamBot, part 2: 24/7 uptime
В предыдущей статье я рассказал про создание бота для Termux.
Но Термукс - херня собачья, мне лень каждый раз что-то запускать и ставить телефон на зарядку. Нужно что-то иное...
Для настройки нам понадобятся:
- VSCode или любой текстовый редактор (писать в Notepad++ на JS неудобно)
- NodeJS, да-да... да... Вообще, можно и без него, но дебажить легче на ПК.
- SDA он же Steam Desktop Authenticator
- Heroku аккаунт для хостинга бота
- GitHub аккаунт для пушей, потому что мне так удобней
Подготовка
Первым делом создаём аккаунты и качаем SDA, нам же нужен наш токен.
Если SteamGuard привязан к смартфону на Android OS, вот вам памятка:
Ну либо просто отвяжите Guard и прикрепите его к SDA, 15 дней бана на тп
Когда все нужные аккаунты привязаны к SDA, создаём репозиторий на GitHub. Как и куда — найдёте в глобальной.
Клонируете репозиторий на ПК, либо создаете локальный с вашей машины (который потом не забудьте запушить в origin)
Настройка. Ну или вторая подготовка, мне по**й
В этот раз обойдёмся двумя файлами, на ПК запускать нет необходимости, трансферить на смартфон — тоже.
Первый файл, main он же index.js:
const clientBuilder = require('./config'); let clientArray = [] const configsArray = [{ login: "login", password: "pass", sharedSecret: "token", games: [ 381210 // Dead by Daylight ] }, { login: "login2", password: "pass2", sharedSecret: "token2", games: [ 570, // Dota 2 548430, // Deep Rock Galactic 4000, // Gmod ] }] console.log('Bot number: ' + configsArray.length); for (let config of configsArray) { let client = clientBuilder.execute(config); client.doLogin(); clientArray.push(client); } console.log('Running ' + configsArray.length + ' bots.');
Файл выше собран под мои нужды, поэтому в массиве два элемента: первый аккаунт и второй.
Самое интересное для нас - это token, он же sharedSecret. Его мы берём из файлов SDA. Если ставили пароль на SDA, то на время придётся снять.
Внутри находим значение shared_secret и копируем. Это и есть наш token.
Вставляем его в файл, соблюдая синтаксис (кавычки, запятые, скобки). ID нужных игр для значения games берём из раздела "Параметры" желаемой игры.
Заполняем файл config.js. Actually, он должен быть нашим main, но сделать export оказалось проще:
const SteamUser = require('steam-user'); const SteamTotp = require('steam-totp'); let newClient = {}; newClient.execute = function (config) { let client = new SteamUser({ // Никакого SteamGuard, как я и говорил promptSteamGuardCode: false, dataDirectory: "./sentry", singleSentryfile: false }); client.login = config.login; client.password = config.password; client.sharedSecret = config.sharedSecret; client.games = config.games; client.messageReceived = {}; client.on('loggedOn', function (details) { console.log("[" + this.login + "] Logged into Steam as " + client.steamID.getSteam3RenderedID()); client.setPersona(SteamUser.EPersonaState.Snooze); // Set steam status [25-34 for all possible variants] client.gamesPlayed(this.games); }); /* Value-to-name mapping for convenience "0": "Offline", "1": "Online", "2": "Busy", "3": "Away", "4": "Snooze", "5": "LookingToTrade", "6": "LookingToPlay", "7": "Invisible", */ client.on('error', function (err) { console.log("[" + this.login + "] " + err); setTimeout(function () { client.doLogin(); }, 30 * 60 * 1000); // Время в ms, в течение которого бот будет афк. 1000 ms. * 60 sec. * 30 min. = 18000000 ms. = 30 min. Меняем первое значение, если хотим изменить минуты. }); client.doLogin = function () { this.logOn({ "accountName": this.login, "password": this.password }); } client.on('steamGuard', function (domain, callback) { if (!this.sharedSecret) { // Никаких запросов SteamGuard, нам это не подходит. Полная автоматика. console.log("Seems like you forgot about SharedSecret. Terminating the process..."); return; } else { var authCode = SteamTotp.generateAuthCode(this.sharedSecret); console.log("[" + this.login + "] Generated Auth Code: " + authCode); callback(authCode); } }); client.on("friendMessage", function (steamID, message) { console.log("[" + this.login + "] Message from " + steamID + ": " + message); if (!this.messageReceived[steamID]) { // Мягко посылаем нашего другана, у нас тут часы крутятся в конце-то концов. Пусть напишет в другой чат. client.chatMessage(steamID, "[Automated Response] I am idling. DM me in Discord or VK."); this.messageReceived[steamID] = true; } }); client.on('vacBans', function (numBans, appids) { if (numBans > 0) { // Показывает баны аккаунта, если есть. Спасибо тернарному "?" за сокращение строк. console.log("[" + this.login + "] " + numBans + " VAC ban" + (numBans == 1 ? '' : 's') + "." + (appids.length == 0 ? '' : " In apps: " + appids.join(', '))); } }); client.on('accountLimitations', function (limited, communityBanned, locked, canInviteFriends) { var limitations = []; if (limited) { limitations.push('LIMITED'); } if (communityBanned) { limitations.push('COMMUNITY BANNED'); } if (locked) { limitations.push('LOCKED'); } if (limitations.length !== 0) { console.log("[" + this.login + "] Limitations: " + limitations.join(', ') + "."); } }); return client; } module.exports = newClient;
Все нужные функции прокомментированы, изучайте и настраивайте.
3... 2... 1... Push!
Создаём в файловой системе бота файл Procfile
Worker: node . либо Worker: node index.js
Пушим всё это дело в наш репозиторий. Либо через VSCode, либо через Github Dekstop, как вам угодно.
Если кто вдруг не работал с VSCode, то запушить можно через меню в левом углу редактора.
Переходим к Heroku. Надо же бота запустить...
Создаём новое приложение, даём ему название и выбираем сервак, рекомендую Европу, легче пинговать.
Далее коннектим Heroku и GitHub между собой, дабы была возможность автоматически развёртывать новые билды в облако (вдруг список игр решите поменять, в таком случае будет достаточно запушить коммит, Heroku сам соберёт билд)
Добавляем Buildpack во вкладке settings. Нам нужен именно heroku/nodejs
Жмём Enable Automatic Deploys, если хотите автоматизации, о которой я упомянул выше.
Далее Deploy Branch, если не началось развёртывание ветки
Можем запускать бота и следить за его работой через логи
Либо можете подключиться к боту через Heroku CLI, залогинившись командой
heroku login
Если по какой-то причине бот крашнул, заходим во вкладку Resources и переключаем
web => Worker
Если захотите сыграть, но вам высвечивается уведомление "Ваш аккаунт занят" => жмите продолжить, бота кикнет, а каждые 30 минут он будет пробовать повторное подключение.
Т.е. как только вы закончите играть, он вернётся к фарму.
Репозиторий для примера, почему бы и да