From 98a97bc04365db9becb1038f88e10866a829b280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Gl=C3=BCpker?= Date: Fri, 26 Jan 2018 00:47:54 +0100 Subject: Ask SteamAPI for owned games and gamestats in CSGO. This is used in Premade Finder to maybe identify Smurfs. --- SteamAPI.py | 100 ++++++++++++++++++++++++--- main.py | 9 +-- templates/premades_html.jinja | 157 +++++++++++++++++++++++++----------------- 3 files changed, 189 insertions(+), 77 deletions(-) diff --git a/SteamAPI.py b/SteamAPI.py index 87b5c39..1790989 100644 --- a/SteamAPI.py +++ b/SteamAPI.py @@ -193,36 +193,118 @@ class SteamAPI(): return ( jsondata['response']['game_count'], jsondata['response']['games'] ) return None - def getPlayerGameStats(self, steamid, gameid): - """Fetch the list of achievements a person achieved in a game + def getUserstatsForGame(self, steamid, gameid): + """Fetch the available game stats for a player in the specified game. Args: steamid: Steamid of the particular user gameid: Appid of the game we want to check Returns: - Tuple with (number of games, gameinfo [appid, name, playtime_2weeks, playtime_forever, icons]) + dict() with statname and value """ if CACHE: - cache = Caching.readCache('playergamestats', '%s-%s' % (str(steamid), str(gameid)), 24*60*60) + cache = Caching.readCache('usergamestats', '%s-%s' % (str(steamid), str(gameid)), 24*60*60) if cache: - jsondata = json.loads(cache) - return jsondata + cachedata = json.loads(cache) + return cachedata - url = 'http://api.steampowered.com/ISteamUserStats/GetPlayerAchievements/v0001/?key=%s&steamid=%s&appid=%s' % (self.token, str(steamid), str(gameid)) + url = 'http://api.steampowered.com/ISteamUserStats/GetUserStatsForGame/v0001/?key=%s&steamid=%s&appid=%s' % (self.token, str(steamid), str(gameid)) try: response = urlopen(url) data = response.read().decode('utf-8') jsondata = json.loads(data) + statslist = jsondata['playerstats']['stats'] + userstats = dict() + for stat in statslist: + userstats[stat] = statslist[stat]['value'] except HTTPError: # f.e. profile is private + userstats = None + + if userstats: + if CACHE: + cache = Caching.writeCache('usergamestats', '%s-%s' % (str(steamid), str(gameid)), json.dumps(userstats)) + return userstats + return None + + def getMultipleUserUserstatsForGame(self, steamids, gameid): + executor = ThreadPoolExecutor(max_workers=10) + futures = dict() + for steamid in steamids: + futures[steamid] = executor.submit(self.getUserstatsForGame, steamid, gameid) + + result = dict() + for steamid in steamids: + result[steamid] = futures[steamid].result() + + return result + + def getOwnedGames(self, steamid): + """Fetch games owned by a player. + + Args: + steamid: Steamid of the particular user + Returns: + dict() with game_count and games, which contains appid + playtime_forever + """ + if CACHE: + cache = Caching.readCache('userownedgames', '%s' % (str(steamid)), 7*24*60*60) + if cache: + cachedata = json.loads(cache) + return cachedata + + url = 'http://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/?key=%s&steamid=%s' % (self.token, str(steamid)) + try: + response = urlopen(url) + data = response.read().decode('utf-8') + jsondata = json.loads(data) + if 'response' in jsondata: + jsondata = jsondata['response'] + except HTTPError: jsondata = None - if 'playerstats' in jsondata: + if jsondata: if CACHE: - cache = Caching.writeCache('playergamestats', '%s-%s' % (str(steamid), str(gameid)), json.dumps(jsondata)) + cache = Caching.writeCache('userownedgames', '%s' % (str(steamid)), json.dumps(jsondata)) return jsondata return None + def getMultipleUserOwnedGames(self, steamids): + executor = ThreadPoolExecutor(max_workers=10) + futures = dict() + for steamid in steamids: + futures[steamid] = executor.submit(self.getOwnedGames, steamid) + + result = dict() + for steamid in steamids: + result[steamid] = futures[steamid].result() + + return result + + def getDataForPremadefinder(self, steamids): + executor = ThreadPoolExecutor(max_workers=20) + + futures = dict() + futures['profiles'] = executor.submit(self.getProfiles, steamids) + futures['ownedGames'] = dict() + futures['userstats'] = dict() + futures['friends'] = dict() + + for steamid in steamids: + futures['ownedGames'][steamid] = executor.submit(self.getOwnedGames, steamid) + futures['userstats'][steamid] = executor.submit(self.getUserstatsForGame, steamid, 730) + futures['friends'][steamid] = executor.submit(self.getFriends, steamid) + + profiles = futures['profiles'].result() + for steamid in profiles: + profiles[steamid]['_friends'] = futures['friends'][steamid].result() + profiles[steamid]['_userstats'] = futures['userstats'][steamid].result() + profiles[steamid]['_ownedGames'] = futures['ownedGames'][steamid].result() + profiles[steamid]['_ownedPlayedGames'] = len([game for game in profiles[steamid]['_ownedGames']['games'] if game['playtime_forever'] > 0]) + + + return profiles + if __name__ == "__main__": # TODO(andre): Maybe run tests here? print('This is a module.') diff --git a/main.py b/main.py index ae6030b..7577d2d 100755 --- a/main.py +++ b/main.py @@ -135,7 +135,7 @@ def lobby(): @app.route("/premadefinder", methods=['GET', 'POST']) def premades(): steamids = [] - profiles = dict() + premadedata = dict() connections = set() if request.method == 'POST': @@ -150,12 +150,12 @@ def premades(): ) # Ask steam about profiles - profiles = steam.getMultipleFriends(steamids) + premadedata = steam.getDataForPremadefinder(steamids) # Add connection between friends. # Friends are always bidirectional, so we use set and min/max to avoid duplicates for steamid in steamids: - for friend in profiles[steamid]['friends']: + for friend in premadedata[steamid]['_friends']: if friend in steamids: friend_a = min(steamid, friend) friend_b = max(steamid, friend) @@ -163,7 +163,8 @@ def premades(): return render_template('premades_html.jinja', steamids=steamids, - profiles=profiles, + profiles=premadedata, + display_time=display_time, connections=connections ) diff --git a/templates/premades_html.jinja b/templates/premades_html.jinja index 8fc4043..565ef21 100644 --- a/templates/premades_html.jinja +++ b/templates/premades_html.jinja @@ -1,4 +1,5 @@ - + + CS:GO Premadefinder @@ -7,97 +8,125 @@ - - -
- Copy&Paste den Inhalt von 'status' aus der Konsole.
-
-
- -
-
+ +
+ Copy&Paste den Inhalt von 'status' aus der Konsole.
+
+
+ +
+
- {% if steamids %} - + {% if steamids %} + renderer.run() + } +
+
- (Private Profile sind durch eine rote Umrandung gekennzeichnet.) + Steamspiele: Anzahl von Steamspielen mit Spielzeit.
+ Spielzeit: Die aktive Spielzeit in CSGO.
+ Private Profile sind durch einen roten Rahmen gekennzeichnet.
- {% endif %} + {% endif %} - -{# vim: commentstring={#\ %s\ #} -- cgit v1.2.3