Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

salien-script-js

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

salien-script-js - npm Package Compare versions

Comparing version 0.0.2 to 0.0.3

cli.js

35

package.json
{
"name": "salien-script-js",
"version": "0.0.2",
"version": "0.0.3",
"description": "Scripting the Steam Salien Sale minigame, the proper way.",

@@ -24,7 +24,16 @@ "keywords": [

"url": "http://southpaw.co.nz/"
},
{
"name": "Resi Respati",
"email": "resir014@gmail.com",
"url": "https://resir014.xyz/"
}
],
"files": [
"src"
"src",
"cli.js"
],
"bin": {
"salien-script-js": "cli.js"
},
"main": "src/index.js",

@@ -35,7 +44,25 @@ "repository": {

},
"scripts": {
"lint": "eslint ./src",
"prepublishOnly": "npm run lint",
"prettier": "prettier --write \"src/**/*.js\""
},
"dependencies": {
"chalk": "^2.4.1",
"dateformat": "^3.0.3",
"delay": "^3.0.0",
"fetch-retry": "^1.2.1"
"fetch-retry": "^1.2.1",
"meow": "^5.0.0"
},
"devDependencies": {}
"devDependencies": {
"eslint": "^5.0.0",
"eslint-config-airbnb-base": "^13.0.0",
"eslint-config-prettier": "^2.9.0",
"eslint-plugin-import": "^2.12.0",
"eslint-plugin-prettier": "^2.6.0",
"prettier": "^1.13.5"
},
"engines": {
"node": ">=10.0.0"
}
}

@@ -5,18 +5,67 @@ # salien-script-js

> A Node.js implementation of https://github.com/SteamDatabase/SalienCheat by [xPaw](https://github.com/xPaw)
> A Node.js implementation of https://github.com/SteamDatabase/SalienCheat by [xPaw](https://github.com/xPaw) with additional features!
[![salien-script-js on npm](https://nodei.co/npm/salien-script-js.png)](https://nodei.co/npm/salien-script-js/)
[![CI Status](https://img.shields.io/travis/South-Paw/salien-script-js/rework.svg)](https://travis-ci.org/South-Paw/salien-script-js)
[![Dependencies](https://david-dm.org/South-Paw/salien-script-js/rework.svg)](https://david-dm.org/South-Paw/salien-script-js/rework)
[![Dev Dependencies](https://david-dm.org/South-Paw/salien-script-js/rework/dev-status.svg)](https://david-dm.org/South-Paw/salien-script-js/rework?type=dev)
---
## How to use this (download repo)
## 🌈 Features
1. Log into Steam in your browser
2. Join https://steamcommunity.com/groups/SteamDB (needed to represent captures)
3. Open https://steamcommunity.com/saliengame/gettoken and find the bit that looks like `"token":"xxxxxxxx"`
4. Create a new file next to `run.js`, call it `token.txt` and paste only the `xxxxxxxx` part of your token in
5. Install the latest version [Node.js](https://nodejs.org/en/)
6. Open command line in the folder
* Tip: ['Shift + Right Click' in explorer -> 'Open Command Line/Powershell here'](http://i.imgur.com/6FJcydX.png)
7. Type `npm i` to get dependencies
8. Run the script by typing `node run.js`
* Easy to install, run and update 🎉
* Same logic as the [PHP version](https://github.com/SteamDatabase/SalienCheat) (we almost have parity) 👽
* Pick your own steam group 👌
* Works well with multiple tokens/scripts 👥
* Name your running scripts 👀
> Note: We'll try our best to keep this version up to date with the PHP and other versions! Suggestions welcome.
---
## 🕹️ How to use this
1. Install [Node.js](https://nodejs.org/en/). (Version 10 and above)
2. Log into [Steam](http://store.steampowered.com/) in your browser.
3. Open the following URL: <https://steamcommunity.com/saliengame/gettoken>. You should be able to find the bit that looks like `"token":"xxxxxxxx"`. Copy whatever is inside the second quotes, (e.g. `xxxxxxxx`).
4. Open PowerShell on Windows. (Tip: Start > Run > type `powershell.exe` > Enter)
5. Run `npm install -g salien-script-js` to install this project.
6. Run the script by typing `salien-script-js --token xxxxxxxx` where `xxxxxxxx` is your token from step 3.
> ### If you appreciate the script, please leave a star ⭐ on the project!
## 😍 How to update the script
1. Close/cancel any running script windows
2. Open PowerShell on Windows.
3. Run `npm update -g salien-script-js`
4. Re-run your scripts using the same command
Easy right?
---
### 👌 Represent your Steam Group (Optional)
If you'd like to represent a specific steam group, simply pass the `--group` option with the ID of the group.
```sh-session
salien-script-js --token xxxxxxxx --group 123456789
```
You can get your group id by going to https://steamcommunity.com/groups/YOUR_GROUP_NAME_HERE/memberslistxml/?xml=1 and replacing `YOUR_GROUP_NAME_HERE` with the group name shown at the end of your groups url.
**You must be a member of a group to represent that group!**
If you'd like to team up with an established larger group please consider using either:
* [100Pals](https://steamcommunity.com/groups/100pals) id: `103582791454524084`
* [SteamDB](https://steamcommunity.com/groups/steamdb) id: `103582791434298690`
### 👥 Multiple tokens/scripts
Simply open another PowerShell window and run `salien-script-js --token yyyyyyyy --name "name of this script"` where `yyyyyyyy` is your other accounts token and `name of this script` if what you'd like to see in the log outputs.
## Advanced: Usage as an npm package

@@ -29,2 +78,4 @@

token: '', // Your token from https://steamcommunity.com/saliengame/gettoken
clan: '', // (optional) Clan id from https://steamcommunity.com/groups/YOUR_GROUP_NAME_HERE/memberslistxml/?xml=1
name: '', // (optional) Name of this instance for logging
};

@@ -34,8 +85,11 @@

salien.run();
salien.init();
```
## Other scripts Salien and languages
## Development
* [PHP version by xPaw](https://github.com/SteamDatabase/SalienCheat) (original)
* [Python version](https://github.com/SteamDatabase/SalienCheat)
Want to help out? Awesome! 👍
Pull the repo and you can run the script with `node cli.js -t TOKEN`.
PRs, suggestions, fixes and improvements all welcome.

770

src/index.js
/**
* MIT License
*
* Copyright (C) 2018 Alex Gabites
* Copyright (c) 2018 Alex Gabites
*

@@ -25,263 +25,721 @@ * Permission is hereby granted, free of charge, to any person obtaining a copy

const chalk = require('chalk');
const dateFormat = require('dateformat');
const delay = require('delay');
const fetch = require('fetch-retry');
const baseUrl = 'https://community.steam-api.com/';
const { version: pkgVersion } = require('../package.json');
const getUrl = (method, params = '') => `${baseUrl}/${method}${params ? '/?' : ''}${params}`;
const logger = (name, ...messages) => {
let message = chalk.white(dateFormat(new Date(), '[HH:MM:ss]'));
const getOptions = (options = {}) => {
return {
retries: 3,
retryDelay: 1000,
headers: {
'Accept': '*/*',
'Origin': 'https://steamcommunity.com',
'Referer': 'https://steamcommunity.com/saliengame/play/',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36',
},
...options,
};
if (name) {
message += ` (${name})`;
}
// eslint-disable-next-line no-console
console.log(message, ...messages);
};
const getScoreForZone = (zone) => {
let score = 0;
// eslint-disable-next-line no-console
const debug = message => console.log(`${JSON.stringify(message, 0, 2)}`);
const asyncForEach = async (_this, array, callback) => {
for (let index = 0; index < array.length; index += 1) {
await callback(array[index], index, array, _this);
}
};
const getDifficultyName = zone => {
const boss = zone.type === 4 ? 'BOSS - ' : '';
switch (zone.difficulty) {
case 1: score = 5; break;
case 2: score = 10; break;
case 3: score = 20; break;
case 3:
return `${boss}Hard`;
case 2:
return `${boss}Medium`;
case 1:
return `${boss}Low`;
default:
return `${boss}${zone.difficulty}`;
}
};
const getScoreForZone = zone => {
let score;
switch (zone.difficulty) {
case 1:
score = 5;
break;
case 2:
score = 10;
break;
case 3:
score = 20;
break;
default:
score = 5;
break;
}
return score * 120;
};
async function getFirstAvailablePlanetId() {
console.log('Attempting to get first open planet...');
class SalienScriptException {
constructor(message) {
this.name = 'SalienScriptException';
this.message = message;
}
}
const request = await fetch(getUrl('ITerritoryControlMinigameService/GetPlanets/v0001', 'active_only=1'), getOptions());
const response = await request.json();
class SalienScriptRestart {
constructor(message) {
this.name = 'SalienScriptRestart';
this.message = message;
}
}
if (!response || !response.response.planets) {
console.log('Didn\'t find any planets.');
class SalienScript {
constructor({ token, clan, name = null }) {
this.token = token;
this.clan = clan;
this.name = name;
return null;
this.maxRetries = 2;
this.defaultDelayMs = 5000;
this.defaultDelaySec = this.defaultDelayMs / 1000;
this.startTime = null;
this.waitTime = 110;
this.hasJoinedClan = false;
this.currentPlanetId = null;
this.steamPlanetId = null;
this.knownPlanetIds = [];
this.knownPlanets = {};
this.skippedPlanets = [];
}
const firstOpen = response.response.planets.filter(planet => !planet.state.captured)[0];
async RequestAPI(method, params, maxRetries, additionalOptions = {}) {
let url = `https://community.steam-api.com/${method}/v0001`;
console.log('First open planet id:', firstOpen.id);
if (params) {
url += '/?';
return firstOpen.id;
};
params.forEach(param => {
url += `${param}&`;
});
async function getPlayerInfo(token) {
console.log('Getting player info...');
url = url.substring(0, url.length - 1);
}
const request = await fetch(getUrl('ITerritoryControlMinigameService/GetPlayerInfo/v0001', `access_token=${token}`), getOptions({ method: 'POST' }));
const response = await request.json();
const options = {
retries: 3,
retryDelay: 1000,
headers: {
Accept: '*/*',
Origin: 'https://steamcommunity.com',
Referer: 'https://steamcommunity.com/saliengame/play/',
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36',
},
...additionalOptions,
};
if (!response || !response.response) {
console.log('Didn\'t get any player info.');
let request;
let response;
let retries = 0;
return null;
}
while (!response && retries < maxRetries) {
try {
logger(this.name, chalk.blue(` Sending ${method}...`));
request = await fetch(url, options);
response = await request.json();
} catch (e) {
// TODO there is some error handling/messaging we could implement here
// see: https://github.com/SteamDatabase/SalienCheat/blob/ac3a28aeb0446ff80cf6a6e1370fd5ef42e75aa2/cheat.php#L533
console.log('Got player info!');
logger(this.name, ` ${chalk.bgRed(`${e.name}:`)} ${chalk.red(`For ${method}`)}`);
debug(e);
return response.response;
};
retries += 1;
async function leaveCurrentGame(token, leaveCurrentPlanet) {
let playerInfo = null;
if (retries < maxRetries) {
logger(this.name, chalk.yellow(` Retrying ${method} in ${this.defaultDelaySec} seconds...`));
} else {
throw new SalienScriptException(`Failed ${method} after ${retries} retries`);
}
while (!playerInfo) {
playerInfo = await getPlayerInfo(token);
await delay(this.defaultDelayMs);
}
}
return response.response;
}
// Please do not change our clanid if you are going to use this script
// If you want to cheat for your own group, come up with up with your own approach, thank you
if (!playerInfo['clan_info']['accountid'] || playerInfo['clan_info']['accountid'] != 4777282) {
await fetch(getUrl('ITerritoryControlMinigameService/RepresentClan/v0001', `clanid=4777282&access_token=${token}`), getOptions({ method: 'POST' }));
async ApiGetPlanets() {
const response = await this.RequestAPI(
'ITerritoryControlMinigameService/GetPlanets',
['active_only=1'],
this.maxRetries,
);
return response.planets;
}
if (playerInfo['active_zone_game']) {
console.log('Leaving `active_zone_game`...');
async ApiGetPlanet(planetId) {
const response = await this.RequestAPI(
'ITerritoryControlMinigameService/GetPlanet',
[`id=${planetId}`, 'language=english'],
this.maxRetries,
);
return response.planets[0];
}
await fetch(getUrl('IMiniGameService/LeaveGame/v0001', `access_token=${token}&gameid=${playerInfo['active_zone_game']}`), getOptions({ method: 'POST' }));
async ApiGetPlayerInfo() {
const response = await this.RequestAPI(
'ITerritoryControlMinigameService/GetPlayerInfo',
[`access_token=${this.token}`],
this.maxRetries,
{ method: 'POST' },
);
return response;
}
console.log('Success!');
async ApiRepresentClan(clanId) {
const response = await this.RequestAPI(
'ITerritoryControlMinigameService/RepresentClan',
[`access_token=${this.token}`, `clanid=${clanId}`],
this.maxRetries,
{ method: 'POST' },
);
return response;
}
if (!playerInfo['active_planet']) {
return 0;
async ApiLeaveGame(gameId) {
const response = await this.RequestAPI(
'IMiniGameService/LeaveGame',
[`access_token=${this.token}`, `gameid=${gameId}`],
this.maxRetries,
{ method: 'POST' },
);
return response;
}
if (leaveCurrentPlanet) {
console.log('Leaving `active_planet`...');
async ApiJoinPlanet(planetId) {
const response = await this.RequestAPI(
'ITerritoryControlMinigameService/JoinPlanet',
[`access_token=${this.token}`, `id=${planetId}`],
this.maxRetries,
{ method: 'POST' },
);
return response;
}
await fetch(getUrl('IMiniGameService/LeaveGame/v0001', `access_token=${token}&gameid=${playerInfo['active_planet']}`), getOptions({ method: 'POST' }));
async ApiJoinZone(zoneId) {
const response = await this.RequestAPI(
'ITerritoryControlMinigameService/JoinZone',
[`access_token=${this.token}`, `zone_position=${zoneId}`],
this.maxRetries,
{ method: 'POST' },
);
return response;
}
console.log('Success!');
async ApiReportScore(score) {
const response = await this.RequestAPI(
'ITerritoryControlMinigameService/ReportScore',
[`access_token=${this.token}`, `score=${score}`, `language=english`],
this.maxRetries,
{ method: 'POST' },
);
return response;
}
return playerInfo['active_planet'];
}
async leaveCurrentGame(leaveCurrentPlanet = 0) {
let playerInfo;
async function joinPlanet(token, planetId) {
console.log('Attempting to join planet id:', planetId);
while (!playerInfo) {
playerInfo = await this.ApiGetPlayerInfo();
}
await fetch(getUrl('ITerritoryControlMinigameService/JoinPlanet/v0001', `id=${planetId}&access_token=${token}`), getOptions({ method: 'POST' }));
if (playerInfo.active_zone_game) {
await this.ApiLeaveGame(playerInfo.active_zone_game);
}
console.log('Joined!');
if (this.clan && !this.hasJoinedClan && playerInfo.clan_info && playerInfo.clan_info.accountid !== this.clan) {
logger(this.name, ` Attempting to join groupId: ${chalk.yellow(this.clan)}`);
return;
}
await this.ApiRepresentClan(this.clan);
async function getFirstAvailableZone(planetId) {
console.log(`Requesting zones for planet ${planetId}...`);
let clanCheckInfo = null;
const request = await fetch(getUrl('ITerritoryControlMinigameService/GetPlanet/v0001', `id=${planetId}`), getOptions());
const response = await request.json();
while (!clanCheckInfo) {
clanCheckInfo = await this.ApiGetPlayerInfo();
}
if (!response.response.planets[0].zones) {
return null;
if (clanCheckInfo.clan_info) {
logger(this.name, ` ${chalk.bgCyan(`Joined group: ${clanCheckInfo.clan_info.name}`)}`);
logger(
this.name,
` ${chalk.yellow("If the name above isn't expected, check if you're actually a member of that group")}`,
);
}
this.hasJoinedClan = true;
}
if (!playerInfo.active_planet) {
return 0;
}
const activePlanet = playerInfo.active_planet;
if (leaveCurrentPlanet > 0 && leaveCurrentPlanet !== activePlanet) {
logger(
this.name,
`Leaving planet ${chalk.yellow(activePlanet)}, because we want to be on ${chalk.yellow(leaveCurrentPlanet)}`,
);
await this.ApiLeaveGame(activePlanet);
}
return activePlanet;
}
let zones = response.response.planets[0].zones;
let cleanZones = [];
let bossZone = null;
async getFirstAvailableZone(planetId) {
let planet;
zones.some(zone => {
if (zone.captured) {
return;
while (!planet) {
planet = await this.ApiGetPlanet(planetId);
}
if (zone.type === 4) {
bossZone = zone;
} else if (zone.type != 3) {
console.log('Unknown zone type:', zone.type);
if (!planet.zones) {
return null;
}
if (zone['capture_progress'] < 0.95) {
const planetName = planet.state.name;
const planetCaptured = planet.state.capture_progress;
const planetPlayers = planet.state.current_players;
const { zones } = planet;
const cleanZones = [];
let hardZones = 0;
let mediumZones = 0;
let easyZones = 0;
let unknownZones = 0;
let toReturn = null;
zones.forEach(zone => {
if (zone.captured) {
return;
}
if (zone.type !== 3) {
logger(this.name, chalk.red(`!! Unknown zone type: ${zone.type}`));
}
// If a zone is close to completion, skip it because Valve does not reward points and replies with 42 NoMatch
if (zone.capture_progress && zone.capture_progress > 0.97) {
return;
}
switch (zone.difficulty) {
case 3:
hardZones += 1;
break;
case 2:
mediumZones += 1;
break;
case 1:
easyZones += 1;
break;
default:
unknownZones += 1;
break;
}
// Always join boss zone
if (zone.type === 4) {
toReturn = {
hardZones,
mediumZones,
easyZones,
unknownZones,
planetPlayers,
planetCaptured,
planetName,
...zone,
};
return;
}
cleanZones.push(zone);
});
if (toReturn) {
return toReturn;
}
})
if (bossZone) {
return bossZone;
if (cleanZones.length < 0) {
return false;
}
cleanZones.sort((a, b) => {
if (b.difficulty === a.difficulty) {
return b.zone_position - a.zone_position;
}
return b.difficulty - a.difficulty;
});
return {
hardZones,
mediumZones,
easyZones,
unknownZones,
planetPlayers,
planetCaptured,
planetName,
...cleanZones[0],
};
}
if (cleanZones.length < 0) {
return null;
async isThereAnyNewPlanets(knownPlanetIds) {
logger(this.name, ' Checking for any new planets...');
let planets;
while (!planets) {
planets = await this.ApiGetPlanets();
}
if (!planets) {
return false;
}
let hasNewPlanet = false;
await planets.forEach(planet => {
if (!knownPlanetIds.includes(planet.id)) {
hasNewPlanet = true;
}
});
return hasNewPlanet;
}
cleanZones.sort((a, b) => {
if (a.difficulty === b.difficulty) {
return b['zone_position'] - a['zone_position'];
async setupGame() {
const planets = await this.ApiGetPlanets();
if (!planets) {
throw new SalienScriptException("Didn't find any planets.");
}
return b.difficulty - a.difficulty;
});
try {
await asyncForEach(this, planets, async (planet, index, array, _this) => {
let zones;
return cleanZones[0];
}
let hardZones = 0;
let mediumZones = 0;
let easyZones = 0;
let unknownZones = 0;
async function joinZone(token, position) {
console.log('Attempting to join zone position:', position);
let hasBossZone = false;
const request = await fetch(getUrl('ITerritoryControlMinigameService/JoinZone/v0001', `zone_position=${position}&access_token=${token}`), getOptions({ method: 'POST' }));
const response = await request.json();
while (!zones) {
zones = await _this.ApiGetPlanet(planet.id);
}
if (!response || !response.response['zone_info']) {
console.log('Failed to join a zone.');
zones.zones.forEach(zone => {
if ((zone.capture_progress && zone.capture_progress > 0.97) || zone.captured) {
return;
}
return null;
}
if (zone.type === 4) {
hasBossZone = true;
} else if (zone.type !== 3) {
logger(this.name, chalk.red(`!! Unknown zone type: ${zone.type}`));
}
console.log('Got player info!');
switch (zone.difficulty) {
case 3:
hardZones += 1;
break;
case 2:
mediumZones += 1;
break;
case 1:
easyZones += 1;
break;
default:
unknownZones += 1;
break;
}
});
return response.response;
}
_this.knownPlanetIds.push(planet.id);
async function reportScore(token, score) {
console.log('Attempting to send score...');
// eslint-disable-next-line no-param-reassign
_this.knownPlanets[planet.id] = {
hardZones,
mediumZones,
easyZones,
unknownZones,
hasBossZone,
...planet,
};
const request = await fetch(getUrl('ITerritoryControlMinigameService/ReportScore/v0001', `access_token=${token}&score=${score}&language=english`), getOptions({ method: 'POST' }));
const response = await request.json();
const capturedPercent = Number(planet.state.capture_progress * 100)
.toFixed(2)
.toString();
if (response.response['new_score']) {
const data = response.response;
const planetName = planet.state.name
.replace('#TerritoryControl_', '')
.split('_')
.join(' ');
console.log(`Score: ${data['old_score']} => ${data['new_score']} (next level: ${data['next_level_score']}) - Current level: ${data['new_level']}`);
}
let logMsg = `>> Planet: ${chalk.green(planet.id)}`;
logMsg += ` - Hard: ${chalk.yellow(hardZones)} - Medium: ${chalk.yellow(mediumZones)}`;
logMsg += ` - Easy: ${chalk.yellow(easyZones)} - Captured: ${chalk.yellow(capturedPercent)}%`;
logMsg += ` - Players: ${chalk.yellow(planet.state.current_players.toLocaleString())}`;
logMsg += ` (${chalk.green(planetName)})`;
return;
}
logger(this.name, logMsg);
class SalienScript {
constructor({ token }) {
this.token = token;
this.currentPlanetId = null;
}
if (unknownZones) {
logger(this.name, `>> Unknown zones found: ${chalk.yellow(unknownZones)}`);
}
async run() {
console.log('This script will not work until you have joined our group:');
console.log('https://steamcommunity.com/groups/SteamDB');
if (hasBossZone) {
// eslint-disable-next-line no-param-reassign
_this.currentPlanetId = planet.id;
while (!this.currentPlanetId) {
this.currentPlanetId = await getFirstAvailablePlanetId();
throw new SalienScriptException('Boss zone found!');
}
});
} catch (e) {
if (e.name === 'SalienScriptException' && e.message === 'Boss zone found!') {
logger(this.name, chalk.green('>> This planet has a boss zone, selecting this planet'));
} else {
debug(e);
throw new SalienScriptException(e.message);
}
}
// FIXME this logic might be able to be cleaned up
const priority = ['hardZones', 'mediumZones', 'easyZones'];
if (!this.currentPlanetId) {
this.knownPlanetIds.sort((a, b) => {
const planetA = this.knownPlanets[a];
const planetB = this.knownPlanets[b];
for (let i = 0; i < priority.length; i += 1) {
const key = priority[i];
if (planetA[key] !== planetB[key]) {
return planetA[key] - planetB[key];
}
}
return Number(planetA.id) - Number(planetB.id);
});
for (let i = 0; i < priority.length; i += 1) {
this.knownPlanetIds.forEach(planetId => {
const planet = this.knownPlanets[planetId];
if (this.skippedPlanets.includes(planetId) || !planet[priority[i]]) {
return;
}
if (!planet.state.captured && !this.currentPlanetId) {
const planetName = planet.state.name
.replace('#TerritoryControl_', '')
.split('_')
.join(' ');
logger(this.name, `>> Selected planet ${chalk.green(planetId)} (${chalk.green(planetName)})`);
this.currentPlanetId = planetId;
}
});
}
if (!this.currentPlanetId) {
console.log('Trying to get another PlanetId in 5 seconds...');
// If there are no planets with hard or medium zones, just return first one
this.currentPlanetId = planets[0].id;
}
}
await delay(5000);
while (this.currentPlanetId !== this.steamPlanetId) {
// Leave current game before trying to switch planets (it will report InvalidState otherwise)
this.steamPlanetId = await this.leaveCurrentGame(this.currentPlanetId);
if (this.currentPlanetId !== this.steamPlanetId) {
await this.ApiJoinPlanet(this.currentPlanetId);
this.steamPlanetId = await this.leaveCurrentGame();
}
}
}
await leaveCurrentGame(this.token, true);
async gameLoop() {
console.log(''); // eslint-disable-line no-console
await joinPlanet(this.token, this.currentPlanetId);
// Scan planets every 10 minutes
if (new Date().getTime() - this.startTime > 600000) {
throw new SalienScriptRestart('!! Re-scanning for new planets');
}
this.currentPlanetId = await leaveCurrentGame(this.token, false);
let zone;
while (true) {
let zone = null;
let joinedZone = null;
while (!zone) {
zone = await this.getFirstAvailableZone(this.currentPlanetId);
}
while (!zone) {
zone = await getFirstAvailableZone(this.currentPlanetId);
if (zone === false) {
this.skippedPlanets.push(this.currentPlanetId);
if (!zone) {
console.log('Trying to get another ZoneId in 5 seconds...');
throw new SalienScriptRestart('!! There are no zones to join in this planet');
}
await delay(5000);
}
const { hardZones, mediumZones, planetCaptured, planetPlayers } = zone;
if (!hardZones) {
if (!mediumZones && new Date().getTime() - this.startTime > this.waitTime * 1000) {
throw new SalienScriptRestart('!! No hard or medium zones on this planet');
}
while (!joinedZone) {
console.log('Attempting to join zone:', zone['zone_position']);
const hasNewPlanet = await this.isThereAnyNewPlanets(this.knownPlanetIds);
joinedZone = await joinZone(this.token, zone['zone_position']);
if (hasNewPlanet) {
throw new SalienScriptRestart('!! Detected a new planet');
}
}
if (!joinedZone) {
console.log('Trying to get another Zone Position in 15 seconds...');
const planetName = zone.planetName
.replace('#TerritoryControl_', '')
.split('_')
.join(' ');
await delay(15000);
}
}
const position = zone.zone_position;
console.log(`Joined zone ${zone['zone_position']} - Captured: ${(zone['capture_progress'] * 100).toFixed(2)}% - Difficulty ${zone.difficulty}`);
zone = null;
console.log('Waiting 120 seconds for game to end...');
while (!zone) {
zone = await this.ApiJoinZone(position);
}
await delay(120000);
if (!zone.zone_info) {
throw new SalienScriptRestart('!! Failed to join a zone');
}
console.log('Game complete!');
const zoneInfo = zone.zone_info;
await reportScore(this.token, getScoreForZone(zone));
const capturedPercent = Number(planetCaptured * 100)
.toFixed(2)
.toString();
let planetLogMsg = `>> Planet ${chalk.green(this.currentPlanetId)} - Captured: ${chalk.yellow(capturedPercent)}%`;
planetLogMsg += ` - Hard: ${chalk.yellow(hardZones)} - Medium: ${chalk.yellow(mediumZones)}`;
planetLogMsg += ` - Players: ${chalk.yellow(planetPlayers.toLocaleString())} (${chalk.green(planetName)})`;
logger(this.name, planetLogMsg);
const capturedProgress = !zoneInfo.capture_progress
? 0
: Number(zoneInfo.capture_progress * 100)
.toFixed(2)
.toString();
let zoneLogMsg = `>> Zone ${chalk.green(zoneInfo.zone_position)} - Captured: ${chalk.yellow(capturedProgress)}%`;
zoneLogMsg += ` - Difficulty: ${chalk.yellow(getDifficultyName(zoneInfo))}`;
logger(this.name, zoneLogMsg);
if (zoneInfo.top_clans) {
logger(this.name, `-- Top Clans:${zoneInfo.top_clans.map(({ name }) => ` ${name}`)}`);
}
};
logger(this.name, ` ${chalk.bgMagenta(`Waiting ${this.waitTime} seconds for round to finish...`)}`);
await delay(this.waitTime * 1000);
const report = await this.ApiReportScore(getScoreForZone(zone));
if (report.new_score) {
const earnedXp = report.new_score - report.old_score;
const nextLevelPercent = ((report.new_score / report.next_level_score) * 100).toFixed(2);
let currentLevelMsg = `>> XP Earned: ${chalk.green(earnedXp.toLocaleString())}`;
currentLevelMsg += ` (${chalk.yellow(report.old_score.toLocaleString())} XP`;
currentLevelMsg += `=> ${chalk.green(report.new_score.toLocaleString())} XP)`;
currentLevelMsg += ` - Current Level: ${chalk.green(report.new_level)} (${nextLevelPercent}% to next)`;
logger(this.name, currentLevelMsg);
const remainingXp = report.next_level_score - report.new_score;
const timeRemaining =
((report.next_level_score - report.new_score) / getScoreForZone(zone)) * (this.waitTime / 60);
const hoursRemaining = Math.floor(timeRemaining / 60);
const minutesRemaining = timeRemaining % 60;
const levelEta = `${hoursRemaining}h ${minutesRemaining}m`;
let nextLevelMsg = `>> Next Level: ${chalk.yellow(report.next_level_score.toLocaleString())} XP`;
nextLevelMsg += `- Remaining: ${chalk.yellow(remainingXp.toLocaleString())} XP - ETA: ${chalk.green(levelEta)}`;
logger(this.name, nextLevelMsg);
}
// Some users get stuck in games after calling ReportScore, so we manually leave to fix this
let leftGame;
while (!leftGame) {
leftGame = await this.leaveCurrentGame(this.currentPlanetId);
}
if (leftGame !== this.currentPlanetId) {
throw new SalienScriptRestart('!! Wrong current planet');
}
}
async init() {
this.startTime = new Date().getTime();
// Reset all variables to default values every time init() is called
this.currentPlanetId = null;
this.knownPlanetIds = [];
this.knownPlanets = {};
this.skippedPlanets = [];
try {
logger(this.name, ` ${chalk.bgGreen(` Started SalienScript | Version: ${pkgVersion} `)}`);
await this.setupGame();
// eslint-disable-next-line no-constant-condition
while (true) {
await this.gameLoop();
}
} catch (e) {
logger(this.name, ` ${chalk.bgRed(`${e.name}:`)} ${chalk.red(e.message)}`);
if (e.name !== 'SalienScriptRestart') {
debug(e);
}
logger(this.name, ` ${chalk.bgMagenta(`Script will restart in ${this.defaultDelaySec} seconds...`)}\n\n`);
await delay(this.defaultDelayMs);
this.init();
}
}
}
module.exports = SalienScript;
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc