Skip to content

Instantly share code, notes, and snippets.

@chaoskagami
Last active January 12, 2022 03:37
Show Gist options
  • Save chaoskagami/45f4dd70d410105c4710c33cc2637c25 to your computer and use it in GitHub Desktop.
Save chaoskagami/45f4dd70d410105c4710c33cc2637c25 to your computer and use it in GitHub Desktop.
Based on Idle Master's python impl, now 100% more minimal
#!/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