From 65c2750dadd22e49433736219bb22a04730a6f28 Mon Sep 17 00:00:00 2001 From: 64Core Date: Mon, 20 Mar 2023 19:36:12 -0500 Subject: [PATCH] There was an issue preventing downloads of titles you owned that contained free demo content Added key pair caching code to support faster checking of owned single downloads load_game was condensed as the ownership check no longer occurs inside it Key pair caching can also be used for issue #67 --- itchiodl/game.py | 5 ++- itchiodl/library.py | 75 +++++++++++++++++++++++++++++++-------------- 2 files changed, 56 insertions(+), 24 deletions(-) diff --git a/itchiodl/game.py b/itchiodl/game.py index 55b5641..b560644 100644 --- a/itchiodl/game.py +++ b/itchiodl/game.py @@ -63,7 +63,10 @@ def load_downloads(self, token): headers={"Authorization": token}, ) j = r.json() - for d in j["uploads"]: + # This converts a null j.uploads into an empty dictionary and uses the safer .get accessor + if j.get("uploads") is None: + j.update({"uploads": []}) + for d in j.get("uploads"): self.downloads.append(d) def download(self, token, platform): diff --git a/itchiodl/library.py b/itchiodl/library.py index 1132735..20f7fa8 100644 --- a/itchiodl/library.py +++ b/itchiodl/library.py @@ -4,7 +4,7 @@ import threading import requests from bs4 import BeautifulSoup - +from os.path import exists from itchiodl.game import Game from itchiodl.utils import NoDownloadError @@ -16,6 +16,7 @@ def __init__(self, login, jobs=4): self.login = login self.games = [] self.jobs = jobs + self.key_pairs = {} def load_game_page(self, page): """Load a page of games via the API""" @@ -40,8 +41,52 @@ def load_owned_games(self): break page += 1 + def load_game_page_keys(self, page): + """Load a page of game keys via the API""" + duplicates = 0 + print("Loading page", page) + r = requests.get( + f"https://api.itch.io/profile/owned-keys?page={page}", + headers={"Authorization": self.login}, + ) + j = json.loads(r.text) + + for s in j["owned_keys"]: + if str(s.get("game_id")) in self.key_pairs: + duplicates+=1 + # The duplicate download key check assumes that a consecutive + # string of ten identical game ids indicates the list has not changed + # Duplicate game keys can happen if you buy multiple bundles containing the same item + # print("duplicate game ID", s["game_id"]) # Old debug line + if duplicates > 9 and exists("key_pairs.json"): + print("Assuming that the owned keys have not changed") + return 0 + else: + self.key_pairs.update({str(s["game_id"]):s["id"]}) + duplicates = 0 + + return len(j["owned_keys"]) + + def load_owned_keys(self): + """Load game_id:download_id pairs only and stores them in the library.keyPairs dictionary""" + page = 1 + if exists("key_pairs.json"): + infile = open("key_pairs.json","r") + self.key_pairs.update(json.loads(infile.read())) + infile.close() + while True: + n = self.load_game_page_keys(page) + if n == 0: + break + page += 1 + + outfile = open("key_pairs.json", "w") + json.dump(self.key_pairs,outfile,indent=0) + outfile.close() + def load_game(self, publisher, title): """Load a game by publisher and title""" + self.load_owned_keys() rsp = requests.get( f"https://{publisher}.itch.io/{title}/data.json", headers={"Authorization": self.login}, @@ -49,30 +94,14 @@ def load_game(self, publisher, title): j = json.loads(rsp.text) game_id = j["id"] gsp = requests.get( - f"https://api.itch.io/games/{game_id}/uploads", + f"https://api.itch.io/games/{game_id}", headers={"Authorization": self.login}, ) - k = gsp.json() - if k != {"uploads": {}}: - self.games.append(Game(k)) - return - print(f"{title} is a purchased game.") - i = 1 - while self.games == []: - j = self.load_game_page(i) - - self.games = [ - x - for x in self.games - if x.link == f"https://{publisher}.itch.io/{title}" - ] - - if j == 0: - break - i += 1 - - if self.games == []: - print(f"Cannot find {title} in owned keys, you may not own it.") + k = json.loads(gsp.text) + game = Game(k) + game.id = self.key_pairs.get(str(game_id), False) + game.game_id = game_id + self.games.append(game) def load_games(self, publisher): """Load all games by publisher"""