Last active
January 12, 2022 03:37
-
-
Save chaoskagami/45f4dd70d410105c4710c33cc2637c25 to your computer and use it in GitHub Desktop.
Based on Idle Master's python impl, now 100% more minimal
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python2 | |
from __future__ import print_function | |
import os | |
import sys | |
import platform | |
import io | |
import numpy | |
import requests | |
import signal | |
import cookielib | |
import bs4 | |
import time | |
import re | |
import subprocess | |
import json | |
import datetime | |
import ctypes | |
from ctypes import CDLL | |
from urllib2 import urlopen | |
def steam_api(): | |
if platform.architecture()[0].startswith('32bit'): | |
steam_api = CDLL('./libsteam_api32.so') | |
elif platform.architecture()[0].startswith('64bit'): | |
steam_api = CDLL('./libsteam_api64.so') | |
return steam_api | |
def kill_idler(pid): | |
os.kill(pid, signal.SIGTERM) | |
def stop_idler(): | |
print("Gracefully unloading idler...") | |
sys.exit(0) | |
def spawn_idler(appID): | |
try: | |
pid = os.fork() | |
except: | |
print("Fork failure!") | |
if pid == 0: | |
signal.signal(signal.SIGTERM, stop_idler) | |
os.environ["SteamAppId"] = str(appID) | |
try: | |
os.close(1) | |
os.close(2) | |
steam_api().SteamAPI_Init() | |
while True: | |
time.sleep(60 * 5) | |
sys.exit() | |
except: | |
print("Couldn't initialize Steam API.") | |
sys.exit() | |
return pid | |
def getKey(item): | |
if authData["sort"]=="mostcards" or authData["sort"]=="leastcards": | |
return item[1] | |
elif authData["sort"]=="mostvalue" or authData["sort"]=="leastvalue": | |
return item[2] | |
else: | |
return item[0] | |
def generateCookies(): | |
global authData | |
try: | |
cookies = dict(sessionid=authData["sessionid"], steamLogin=authData["steamLogin"], steamparental=authData["steamparental"]) | |
except: | |
logging.warning("Error setting cookies") | |
sys.exit() | |
return cookies | |
def configure(): | |
global cookies | |
global authData | |
global myProfileURL | |
os.chdir(os.path.abspath(os.path.dirname(sys.argv[0]))) | |
try: | |
authData={} | |
authData["sort"]="" | |
authData["steamparental"]="" | |
authData["hasPlayTime"]="false" | |
execfile("./settings.txt", authData) | |
myProfileURL = "http://steamcommunity.com/profiles/"+authData["steamLogin"][:17] | |
except: | |
print("Error loading config file") | |
sys.exit() | |
if not authData["sessionid"]: | |
print("No sessionid set") | |
sys.exit() | |
if not authData["steamLogin"]: | |
print("No steamLogin set") | |
sys.exit() | |
print("Attempting to fetch badge list...") | |
try: | |
cookies = generateCookies() | |
r = requests.get(myProfileURL+"/badges/",cookies=cookies) | |
except: | |
print("Error reading badge page") | |
sys.exit() | |
def get_app_name(appID): | |
try: | |
api = requests.get("http://store.steampowered.com/api/appdetails/?appids=" + str(appID) + "&filters=basic") | |
api_data = json.loads(api.text) | |
return api_data[str(appID)]["data"]["name"] | |
except: | |
return "App " + str(appID) | |
def get_to_idle(): | |
global cookies | |
global authData | |
global myProfileURL | |
try: | |
r = requests.get(myProfileURL+"/badges/",cookies=cookies) | |
except: | |
print("Error reading badge page") | |
sys.exit() | |
try: | |
badgesLeft = [] | |
badgePageData = bs4.BeautifulSoup(r.text, "lxml") | |
badgeSet = badgePageData.find_all("div",{"class": "badge_title_stats"}) | |
except: | |
print("Error finding drop info") | |
sys.exit() | |
# For profiles with multiple pages | |
try: | |
badgePages = int(badgePageData.find_all("a",{"class": "pagelink"})[-1].text) | |
if badgePages: | |
print(str(badgePages) + " badge pages found. Gathering additional data") | |
currentpage = 2 | |
while currentpage <= badgePages: | |
r = requests.get(myProfileURL+"/badges/?p="+str(currentpage),cookies=cookies) | |
badgePageData = bs4.BeautifulSoup(r.text, "lxml") | |
badgeSet = badgeSet + badgePageData.find_all("div",{"class": "badge_title_stats"}) | |
currentpage = currentpage + 1 | |
except: | |
print("Reading badge page, please wait") | |
userinfo = badgePageData.find("a",{"class": "user_avatar"}) | |
if not userinfo: | |
print("Invalid cookie data, cannot log in to Steam") | |
sys.exit() | |
for badge in badgeSet: | |
try: | |
badge_text = badge.get_text() | |
dropCountInt = int(re.findall("\d+", badge.find_all("span",{"class": "progress_info_bold"})[0].get_text())[0]) | |
has_playtime = re.search("[0-9\.] hrs on record", badge_text) != None | |
if dropCountInt < 1 or (has_playtime == False and authData["hasPlayTime"].lower() == "true") : | |
continue | |
else: | |
# Remaining drops | |
linkGuess = badge.find_parent().find_parent().find_parent().find_all("a")[0]["href"] | |
junk, badgeId = linkGuess.split("/gamecards/",1) | |
badgeId = int(badgeId.replace("/","")) | |
push = [badgeId, dropCountInt, 0, get_app_name(badgeId)] | |
badgesLeft.append(push) | |
except: | |
continue | |
return badgesLeft | |
def get_cards_remain(appID): | |
global cookies | |
global authData | |
global myProfileURL | |
rBadge = requests.get(myProfileURL + "/gamecards/" + str(appID) + "/",cookies=cookies) | |
indBadgeData = bs4.BeautifulSoup(rBadge.text, "lxml") | |
badgeLeftString = indBadgeData.find_all("span",{"class": "progress_info_bold"})[0].contents[0] | |
if "No card drops" in badgeLeftString: | |
dropCountInt = 0 | |
else: | |
dropCountInt, junk = badgeLeftString.split(" ",1) | |
dropCountInt = int(dropCountInt) | |
return dropCountInt | |
if __name__ == '__main__': | |
configure() | |
idle_do = get_to_idle() | |
print("Need to idle " + str(len(idle_do)) + " games:") | |
for app in idle_do: | |
print(" " + str(app[0]) + " - `" + app[3] + "` (" + str(app[1]) + " drops remaining)") | |
for app in idle_do: | |
print("Idling: " + str(app[0]) + " - `" + app[3] + "`") | |
pid = spawn_idler(app[0]) | |
print("Subprocess " + str(pid) + " connected to Steam") | |
remain = get_cards_remain(app[0]) | |
print(str(remain) + " card drops remaining") | |
while remain > 0: | |
sleeptime = 60 * 5 | |
if remain > 1: | |
sleeptime *= 3 | |
print("Sleeping " + str(sleeptime) + " seconds") | |
time.sleep(sleeptime) # 5mins | |
remain = get_cards_remain(app[0]) | |
print(str(remain) + " card drops remaining") | |
print("Idling completed for `" + app[3] + "`") | |
kill_idler(pid) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment