PageRenderTime 23ms CodeModel.GetById 15ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 0ms

/scripts/srcupdatecheck

https://bitbucket.org/kimoto/sushi
#! | 146 lines | 124 code | 22 blank | 0 comment | 0 complexity | 3d6c234a39941a815bd9ecbf05012bac MD5 | raw file
  1#!/usr/bin/python
  2# coding=utf8
  3
  4# srcupdatecheck v13 - part of
  5# NemRun v1.8.6 - john@pointysoftware.net, 07/25/2012
  6
  7# Copyright 2012 john@pointysoftware.net
  8# This program is free software: you can redistribute it and/or modify
  9# it under the terms of the GNU General Public License as published by
 10# the Free Software Foundation, either version 3 of the License, or
 11# (at your option) any later version.
 12
 13# This program is distributed in the hope that it will be useful,
 14# but WITHOUT ANY WARRANTY; without even the implied warranty of
 15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16# GNU General Public License for more details.
 17
 18# You should have received a copy of the GNU General Public License
 19# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 20
 21import time
 22import sys
 23import xml.dom.minidom
 24import re
 25
 26gSteamAPI = 'https://api.steampowered.com'
 27
 28# This supports Python 2.4+ and 3.0+, which requires a few tricks,
 29# and different libraries
 30
 31if (sys.hexversion < 0x03000000):
 32    gPy3k = False
 33    import urllib
 34    import urllib2
 35else:
 36    gPy3k = True
 37    import urllib.request
 38    import urllib.parse
 39
 40if not len(sys.argv) == 2:
 41    print("Usage: ./srcupdatecheck /path/to/steam.inf")
 42    sys.exit(-1)
 43
 44#
 45# Steam API Call
 46#
 47    
 48def SteamAPICall(path, rawargs = {}):
 49    args = rawargs
 50    args['format'] = 'xml'
 51    if gPy3k:
 52        args = '?%s' % (urllib.parse.urlencode(args))
 53    else:
 54        args = '?%s' % (urllib.urlencode(args))
 55    
 56    url = "%s/%s/%s" % (gSteamAPI, path, args)
 57    try:
 58        if gPy3k:
 59            raw = urllib.request.urlopen(url).read().decode()
 60        else:
 61            raw = urllib2.urlopen(url).read()
 62    except Exception:
 63        print("!! API Call failed\n\tURL:\t'%s'" % (url))
 64        return False
 65    
 66    try:
 67        dom = xml.dom.minidom.parseString(raw)
 68    except Exception:
 69        print("!! API Call - Failed to parse XML result\n\tURL:\t'%s'\n=== Raw ===\n%s\n===========" % (url, raw))
 70        return False
 71    
 72    response = dom.getElementsByTagName('response')
 73    if not len(response):
 74        return False
 75    
 76    ret = {}
 77    for c in response[0].childNodes:
 78        if c.nodeType == xml.dom.minidom.Node.ELEMENT_NODE:
 79            if not len(c.childNodes):
 80                ret[c.nodeName] = ""
 81            elif c.childNodes[0].data.lower() == "true":
 82                ret[c.nodeName] = True
 83            elif c.childNodes[0].data.lower() == "false":
 84                ret[c.nodeName] = False
 85            else:
 86                ret[c.nodeName] = c.childNodes[0].data
 87    print("\t -- API Call[%s: %s]\n\t\t%s" % (path, rawargs, ret))
 88    return ret
 89
 90# 1 Up to date, 0 not, -1 call failed
 91# Note that the json returns 'version_is_listable', but valve never uses this,
 92# optional updates don't bump their version # :(
 93def RunCheck(no, appid, ver):
 94    call = SteamAPICall('ISteamApps/UpToDateCheck/v0001', { 'appid': appid, 'version': ver })
 95    if not call or call['success'] != True:
 96        print("[%u] !! API Call did not succeed\n\tRaw:\t%s" % (no, call))
 97        return -1
 98    if call['up_to_date']:
 99        print("[%u] API returned up to date!" % (no))
100        return 1
101    else:
102        print("[%u] API returned out of date - Version %s vs %s" % (no, ver.replace('.', ''), call['required_version']))
103
104#
105# Read PatchVersion from provided steam.inf
106#
107try:
108    steaminf = open(sys.argv[1])
109except IOError:
110    print("File \"%s\" does not exist!" % sys.argv[1])
111    sys.exit(-1)
112
113infblob = steaminf.read()
114verre = re.search('PatchVersion=([^\r\n]+)', infblob)
115appre = re.search('appID=([^\r\n]+)', infblob)
116prodre = re.search('ProductName=([^\r\n]+)', infblob)
117
118if not (verre and appre and prodre):
119    print("Invalid steam.inf file.")
120    sys.exit(-1)
121
122ver = verre.group(1)
123game = prodre.group(1)
124appid = appre.group(1)
125
126print("Found patch version: %s, game: %s, appid: %s" % (ver,game,appid))
127
128# According to Tony, this API call can sometimes return out of date incorrectly (yay!)
129# So we'll keep our stupid try-multiple-times logic
130lastattempt = -1
131attempt = 1
132while True:
133    ret = RunCheck(attempt, appid, ver);
134    if (ret != -1):
135        if (ret == lastattempt):
136            if (ret == 1):
137                print("Confirmed up to date [%u requests]" % (attempt))
138                sys.exit(0)
139            else:
140                print("Confirmed out of date [%u requests]" % (attempt))
141                sys.exit(7)
142    else:
143        # In the case where we're chain-failing for some reason, don't hammer the API
144        time.sleep(5)
145    lastattempt = ret
146    attempt += 1