├── README.md ├── account.bat ├── account.py └── saliens.py /README.md: -------------------------------------------------------------------------------- 1 | # Steam-2018-SummerGame 2 | 3 | Python Version. 4 | 5 | Recommend: phuslu/pybuild3 6 | 7 | # Usage 8 | 9 | Use account.py to generate config files.(Each time add an account config to configs folder 10 | 11 | And use saliens.py to farm exp. 12 | 13 | # Features 14 | 15 | * Allow multiple accounts. 16 | * Join zone automaticly. 17 | * Could switch planet. 18 | * Will try upload score when bot meets exploit. (Almost fixed by Valve, but could still upload 10x score at best. 19 | * Fight boss. 20 | 21 | **Will Not Update If Not Necessary** 22 | 23 | **For SChinese Users, Not Tested With English Systems** -------------------------------------------------------------------------------- /account.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | .\runtime\python34.exe account.py 3 | pause -------------------------------------------------------------------------------- /account.py: -------------------------------------------------------------------------------- 1 | #!/bin/python3 2 | # -*- coding: UTF-8 -*- 3 | import os, re, sys, json 4 | 5 | class filelib: 6 | def write(self, path, content, mode='w', encoding="gbk"): 7 | file = open(path, mode, encoding=encoding) 8 | file.write(content) 9 | file.close() 10 | return True 11 | def mkdir(self, dirname): 12 | try: 13 | os.mkdir(dirname) 14 | except: 15 | pass 16 | return True 17 | 18 | def myinput(data): 19 | try: 20 | return input(data[0]) 21 | except: 22 | return input(data[1]) 23 | 24 | def myprint(data): 25 | try: 26 | print(data[0]) 27 | except: 28 | print(data[1]) 29 | 30 | def main(): 31 | name = '' 32 | token = '' 33 | steamid = '' 34 | filelib().mkdir('configs') 35 | while name == "": 36 | name = myinput(['请输入Bot名:', 'Please input bot name:']) 37 | myprint(["访问 https://steamcommunity.com/saliengame/gettoken 以获取token。", "Open https://steamcommunity.com/saliengame/gettoken to get token."]) 38 | while token == "": 39 | token = myinput(['请输入token:', 'Please input token:']) 40 | myprint(["访问 https://steamcommunity.com/my/?xml=1 以获取Steam 64位ID:", "Open https://steamcommunity.com/my/?xml=1 to get your steam 64 id."]) 41 | while steamid == "": 42 | steamid = myinput(["请输入Steam 64位ID:", "Please input Steam 64 ID:"]) 43 | filelib().write('configs/'+name+'.json', json.dumps({"token": token, "steamid": steamid})) 44 | 45 | if __name__ == '__main__': 46 | main() -------------------------------------------------------------------------------- /saliens.py: -------------------------------------------------------------------------------- 1 | #!/bin/python3 2 | # -*- coding: UTF-8 -*- 3 | import os, re, sys, json, requests, time, datetime, random 4 | from multiprocessing.dummy import Pool as ThreadPool 5 | 6 | def findstr(rule, string): 7 | find_str = re.compile(rule) 8 | return find_str.findall(string) 9 | 10 | def getTime(): 11 | return datetime.datetime.now().strftime('%m/%d-%H:%M:%S') 12 | 13 | def getTimestamp(): 14 | return int(time.time()) 15 | 16 | class filelib: 17 | def open(self, path, mode='r', encoding="gbk"): 18 | try: 19 | file = open(path, mode, encoding=encoding) 20 | content = file.read() 21 | file.close() 22 | return content 23 | except: 24 | return False 25 | def write(self, path, content, mode='w', encoding="gbk"): 26 | file = open(path, mode, encoding=encoding) 27 | file.write(content) 28 | file.close() 29 | return True 30 | def mkdir(self, dirname): 31 | try: 32 | os.mkdir(dirname) 33 | except: 34 | pass 35 | return True 36 | def opencfg(self, path): 37 | cont = self.open(path, encoding="utf-8") 38 | if cont: 39 | cont = re.sub('(?= nextHeal: 196 | useHeal = 1 197 | nextHeal = getTimestamp() + 120 198 | self.myprint("%s|Bot: %s|BossFight|UsingHealAbility" % (getTime(), self.name)) 199 | req = weblib().npost(self.apiStart+'/ReportBossDamage/v0001/', 200 | { 201 | "access_token": self.token, 202 | "use_heal_ability": useHeal, 203 | "damage_to_boss": damageToBoss, 204 | "damage_taken": damageTaken 205 | }, 206 | self.name) 207 | eresult = int(findstr('\d+', req[1]["X-eresult"])[0]) 208 | res = json.loads(req[0])["response"] 209 | if eresult == 11: 210 | # self.myprint("%s|Bot: %s|BossFight|InvalidState|RestartInstance" % (getTime(), self.name)) 211 | break 212 | if eresult != 1: 213 | bossFailsAllowed -= 1 214 | if bossFailsAllowed < 1: 215 | # self.myprint("%s|Bot: %s|BossFight|ErrorTooMuch|RestartInstance" % (getTime(), self.name)) 216 | break 217 | if "boss_status" in res: 218 | if "boss_players" not in res["boss_status"]: 219 | self.myprint("%s|Bot: %s|BossFight|Waiting..." % (getTime(), self.name)) 220 | continue 221 | bossStatus = res["boss_status"] 222 | bossPlayers = bossStatus["boss_players"] 223 | myPlayer = None 224 | for player in bossPlayers: 225 | if player["accountid"] == self.accountid: 226 | myPlayer = player 227 | curExp = str(int(self.playerInfo["score"])+int(player["xp_earned"])) 228 | self.myprint("%s|Bot: %s|BossFight|HP: %s/%s|Exp: %s" % (getTime(), self.name, player["hp"], player["max_hp"], curExp)) 229 | break 230 | if "game_over" in res: 231 | if res["game_over"] == True: 232 | self.myprint("%s|Bot: %s|BossFight|GameOver|TotalScore: %s" % (getTime(), self.name, player["xp_earned"])) 233 | break 234 | if "waiting_for_players" in res: 235 | if res["waiting_for_players"] == True: 236 | self.myprint("%s|Bot: %s|BossFight|WaitingForPlayers" % (getTime(), self.name)) 237 | continue 238 | if myPlayer != None: 239 | if int(myPlayer["hp"]) <= 0: 240 | # self.myprint("%s|Bot: %s|BossFight|YouDied|RestartInstance" % (getTime(). self.name)) 241 | break 242 | self.myprint("%s|Bot: %s|BossFight|Lv: %s => %s|Exp Earned: %s" % (getTime(), self.name, myPlayer["level_on_join"], myPlayer["new_level"], myPlayer["xp_earned"])) 243 | self.myprint("%s|Bot: %s|BossFight|Boss HP: %s/%s|Lasers: %s|Team Heals: %s" % (getTime(), self.name, bossStatus["boss_hp"], bossStatus["boss_max_hp"], res["num_laser_uses"], res["num_team_heals"])) 244 | time.sleep(5) 245 | def getJoinInfo(self): 246 | req = weblib().npost(self.apiStart+'/JoinZone/v0001/', 247 | { 248 | "zone_position": self.zone_position, 249 | "access_token": self.token 250 | }, 251 | self.name) 252 | self.joinInfo = json.loads(req[0])["response"] 253 | if "zone_info" in self.joinInfo: 254 | self.joinInfo = self.joinInfo["zone_info"] 255 | self.time = int(getTimestamp() + 110) 256 | self.myprint("%s|Bot: %s|JoinZone: %s|Difficulty: %s" % (getTime(), self.name, self.zone_position, self.difficulty)) 257 | return True 258 | else: 259 | try: 260 | gameid = int(findstr('\d+', req[1]["X-error_message"])[0]) 261 | self.bug(gameid) 262 | return False 263 | except: 264 | if "boss zone" in req[1]["X-error_message"]: 265 | self.skip.append(self.zone_position) 266 | skipped = "|ZoneSkipped" 267 | else: 268 | skipped = "" 269 | # self.myprint("%s|Bot: %s%s|Msg: %s|Retry after 10s..." % (getTime(), self.name, skipped, req[1]["X-error_message"])) 270 | time.sleep(10) 271 | return False 272 | def bug(self, gameid): 273 | # self.myprint("%s|Bot: %s|AlreadyInGame|GameId: %s|BUG???" % (getTime(), self.name, str(gameid))) 274 | stillBug = True 275 | while stillBug == True: 276 | stillBug = self.getScoreInfo(1) 277 | # self.myprint("%s|Bot: %s|AlreadyInGame|GameId: %s|LeaveGame" % (getTime(), self.name, str(gameid))) 278 | self.leaveGame(gameid) 279 | def getScoreInfo(self, errorTime=0): 280 | if errorTime == 0: 281 | self.getBestPlanet() 282 | if self.time != 0: 283 | time.sleep(self.time - getTimestamp()) 284 | self.time = 0 285 | if self.difficulty == 1: 286 | score = 600 287 | elif self.difficulty == 2: 288 | score = 1200 289 | elif self.difficulty == 3: 290 | score = 2400 291 | self.scoreInfo = json.loads(weblib().post(self.apiStart+'/ReportScore/v0001/', 292 | { 293 | "access_token": self.token, 294 | "score": score, 295 | "language": self.language 296 | }, 297 | self.name))["response"] 298 | if "new_score" in self.scoreInfo: 299 | self.myprint("%s|Bot: %s|UploadScore|Exp: %s/%s" % (getTime(), self.name, self.scoreInfo["new_score"], self.scoreInfo["next_level_score"])) 300 | return True 301 | else: 302 | if errorTime > 1: 303 | # self.myprint("%s|Bot: %s|UploadScore|Failed" % (getTime(), self.name)) 304 | return False 305 | else: 306 | time.sleep(1) 307 | self.getScoreInfo(errorTime+1) 308 | def getBestPlanet(self): 309 | if self.help == 1: 310 | availPlanets = json.loads(weblib().get(self.apiStart+'/GetPlanets/v0001/?active_only=1&language='+self.language, self.name))["response"]["planets"] 311 | bestProgress = 0 312 | for planet in availPlanets: 313 | if planet["state"]["capture_progress"] > bestProgress: 314 | bestProgress = planet["state"]["capture_progress"] 315 | self.difficulty = 1 316 | self.bestPlanet = planet["id"] 317 | else: 318 | availPlanets = json.loads(weblib().get(self.apiStart+'/GetPlanets/v0001/?active_only=1&language='+self.language, self.name))["response"]["planets"] 319 | self.availPlanets = [] 320 | for planet in availPlanets: 321 | self.availPlanets.append([planet["id"], self.getZoneInfo(planet["id"])]); 322 | self.difficulty = 0 323 | for planet in self.availPlanets: 324 | if planet[1]>self.difficulty: 325 | self.difficulty = planet[1] 326 | self.bestPlanet = planet[0] 327 | def getZoneInfo(self, planetId): 328 | planetInfo = json.loads(weblib().get(self.apiStart+'/GetPlanet/v0001/?id='+planetId+'&language='+self.language, self.name))["response"]["planets"][0] 329 | zones = planetInfo["zones"] 330 | for zone in zones: 331 | if zone["difficulty"] == 1 and zone["captured"] == False and "top_clans" in zone: 332 | difficulty = 1 333 | break 334 | for zone in zones: 335 | if zone["difficulty"] == 2 and zone["captured"] == False and "top_clans" in zone: 336 | difficulty = 2 337 | break 338 | for zone in zones: 339 | if zone["difficulty"] == 3 and zone["captured"] == False and "top_clans" in zone: 340 | difficulty = 3 341 | break 342 | for zone in zones: 343 | if (zone["type"] == 4) and ("boss_active" in zone): 344 | if zone["boss_active"] == True: 345 | difficulty = 4 346 | break 347 | return difficulty 348 | def getHardZone(self): 349 | if not self.difficulty: 350 | self.difficulty = 3 351 | self.zone_position = -1 352 | zones = self.planetInfo["zones"] 353 | for zone in zones: 354 | if zone["zone_position"] == 0 and "capture_progress" in zone and zone["capture_progress"] == 0: 355 | continue 356 | if "boss_active" in zone and zone["boss_active"] == True: 357 | self.zone_position = zone["zone_position"] 358 | self.myprint("%s|Bot: %s|SelectBossZone: %s" % (getTime(), self.name, self.zone_position)) 359 | break 360 | if zone["difficulty"] == self.difficulty and zone["captured"] == False: 361 | if (self.difficulty == 3 and zone["capture_progress"] < 0.99) or (self.difficulty < 3 and zone["capture_progress"] < 0.95): 362 | self.zone_position = zone["zone_position"] 363 | self.myprint("%s|Bot: %s|SelectZone: %s|Progress: %s" % (getTime(), self.name, self.zone_position, zone["capture_progress"])) 364 | break 365 | if self.zone_position == -1: 366 | # self.myprint("%s|Bot: %s|SwitchPlanet|Getting info..." % (getTime(), self.name)) 367 | self.getBestPlanet() 368 | if "active_planet" in self.playerInfo: 369 | if self.bestPlanet != self.playerInfo["active_planet"]: 370 | self.leavePlanet() 371 | self.joinPlanet(self.bestPlanet) 372 | self.getPlayerInfo() 373 | else: 374 | self.joinPlanet(self.bestPlanet) 375 | self.getPlayerInfo() 376 | self.getPlanetInfo() 377 | self.getHardZone() 378 | def helpOthers(self): 379 | self.myprint("%s|Bot: %s|HelpOthers" % (getTime(), self.name)) 380 | self.difficulty = 1 381 | self.help = 1 382 | self.getBestPlanet() 383 | 384 | def handler(data): 385 | bot = saliens() 386 | try: 387 | bot.loadcfg(data) 388 | except: 389 | pass 390 | # print("%s|Bot: %s|LoadConfig|Error!" % (getTime(), data[0])) 391 | bot.getPlayerInfo() 392 | bot.getBestPlanet() 393 | while True: 394 | if int(bot.playerInfo["level"]) >= 21: 395 | bot.helpOthers() 396 | try: 397 | if "active_planet" in bot.playerInfo: 398 | if bot.bestPlanet != bot.playerInfo["active_planet"]: 399 | bot.leavePlanet() 400 | bot.joinPlanet(bot.bestPlanet) 401 | bot.getPlayerInfo() 402 | else: 403 | bot.joinPlanet(bot.bestPlanet) 404 | bot.getPlayerInfo() 405 | bot.getPlanetInfo() 406 | bot.getHardZone() 407 | if bot.difficulty == 4: 408 | if bot.joinBossZone(): 409 | bot.fightBoss() 410 | continue 411 | if bot.getJoinInfo(): 412 | time.sleep(85) 413 | bot.getScoreInfo() 414 | bot.getPlayerInfo() 415 | if "active_zone_game" in bot.playerInfo: 416 | bot.bug(bot.playerInfo["active_zone_game"]) 417 | else: 418 | bot.getPlayerInfo() 419 | bot.getBestPlanet() 420 | except: 421 | pass 422 | 423 | def main(): 424 | try: 425 | filelib().mkdir('configs') 426 | except: 427 | pass 428 | sys.path.append('configs') 429 | list_dirs = os.walk('configs') 430 | filelists = [] 431 | for root, dirs, files in list_dirs: 432 | for f in files: 433 | path = os.path.join(root, f) 434 | filelists.append([f.split('.')[0], path]) 435 | pool = ThreadPool(len(filelists)+1) 436 | for i in range(0, len(filelists)): 437 | pool.apply_async(handler, args=(filelists[i], )) 438 | pool.close() 439 | pool.join() 440 | 441 | if __name__ == '__main__': 442 | main() --------------------------------------------------------------------------------