diff options
| author | NW/RL <NWRL@dabikers.online> | 2024-04-01 23:08:44 -0500 |
|---|---|---|
| committer | NW/RL <NWRL@dabikers.online> | 2024-04-01 23:08:44 -0500 |
| commit | e667602620a51576e354de24d0b5b90b726dab9f (patch) | |
| tree | 2c91b8bf0a1a4a83d9bed4ed7167085698480cf3 | |
| parent | 1680e070bdec3700bb9964d21c0523222e48ca9c (diff) | |
Make debugging easier
| -rw-r--r-- | steamrelationships/sr.py | 119 |
1 files changed, 64 insertions, 55 deletions
diff --git a/steamrelationships/sr.py b/steamrelationships/sr.py index 429eec2..22e941e 100644 --- a/steamrelationships/sr.py +++ b/steamrelationships/sr.py | |||
| @@ -10,12 +10,13 @@ class SteamRelationships: | |||
| 10 | scanlist: list = [] # To be populated by recurse() | 10 | scanlist: list = [] # To be populated by recurse() |
| 11 | reqjson: str = "requests.json" | 11 | reqjson: str = "requests.json" |
| 12 | 12 | ||
| 13 | def __init__(self, webapikey: str, timeout: int = 30, reqdelay: float = 0.5, delayrand: float = 1.25, reqsafetybuffer: float = 0.9, reqjson: str = "requests.json") -> None: | 13 | def __init__(self, webapikey: str, timeout: int = 30, timeout_retries: int = 5, reqdelay: float = 0.5, delayrand: float = 1.25, reqsafetybuffer: float = 0.9, reqjson: str = "requests.json") -> None: |
| 14 | """ | 14 | """ |
| 15 | (str/int) webapikey - Steam dev api key required to use Steam's ISteamUser/GetFriendList interface | 15 | (str/int) webapikey - Steam dev api key required to use Steam's ISteamUser/GetFriendList interface |
| 16 | 16 | ||
| 17 | Request Options: | 17 | Request Options: |
| 18 | (int/float) timeout (Default: 30) - Seconds to wait before timing out a request. | 18 | (int) timeout (Default: 30) - Seconds to wait before timing out a request. |
| 19 | (int) timeout_retries (Default: 5) Number of times to retry a request after timing out | ||
| 19 | (float) reqdelay (Default: 0.5) - Default amount of seconds to wait between sending each request to Steam | 20 | (float) reqdelay (Default: 0.5) - Default amount of seconds to wait between sending each request to Steam |
| 20 | (float) delayrand (Default: 1.25) - The max percentage of extra delay to randomly add to each request (1 = no randomness, <1 = randomly shorter, >1 = randomly longer) | 21 | (float) delayrand (Default: 1.25) - The max percentage of extra delay to randomly add to each request (1 = no randomness, <1 = randomly shorter, >1 = randomly longer) |
| 21 | (float) reqsafetybuffer (Default: 0.9) - Highest percent of Steam's API request limit you are willing to run | 22 | (float) reqsafetybuffer (Default: 0.9) - Highest percent of Steam's API request limit you are willing to run |
| @@ -28,11 +29,14 @@ class SteamRelationships: | |||
| 28 | 29 | ||
| 29 | self.webapikey = webapikey | 30 | self.webapikey = webapikey |
| 30 | self.timeout = timeout | 31 | self.timeout = timeout |
| 32 | self.timeout_retries = timeout_retries | ||
| 31 | self.reqdelay = reqdelay | 33 | self.reqdelay = reqdelay |
| 32 | self.delayrand = delayrand | 34 | self.delayrand = delayrand |
| 33 | self.reqsafetybuffer = reqsafetybuffer | 35 | self.reqsafetybuffer = reqsafetybuffer |
| 34 | self.reqjson = reqjson | 36 | self.reqjson = reqjson |
| 35 | 37 | ||
| 38 | |||
| 39 | |||
| 36 | def _readjsonfile(self, filepath: str = "") -> dict: | 40 | def _readjsonfile(self, filepath: str = "") -> dict: |
| 37 | if not filepath: | 41 | if not filepath: |
| 38 | filepath = self.reqjson | 42 | filepath = self.reqjson |
| @@ -48,7 +52,7 @@ class SteamRelationships: | |||
| 48 | 52 | ||
| 49 | # If the file does not exist, create one and slap an empty list in it | 53 | # If the file does not exist, create one and slap an empty list in it |
| 50 | except FileNotFoundError: | 54 | except FileNotFoundError: |
| 51 | print(f"File {filepath} does not exist. Generating empty json file...") | 55 | print(f"[_readjsonfile] File {filepath} does not exist. Generating empty json file...") |
| 52 | try: | 56 | try: |
| 53 | with open(filepath, "w+") as newfile: | 57 | with open(filepath, "w+") as newfile: |
| 54 | json.dump({time.time_ns(): [0, []]}, newfile, indent=4) | 58 | json.dump({time.time_ns(): [0, []]}, newfile, indent=4) |
| @@ -56,12 +60,12 @@ class SteamRelationships: | |||
| 56 | 60 | ||
| 57 | return self._readjsonfile(filepath) | 61 | return self._readjsonfile(filepath) |
| 58 | 62 | ||
| 59 | except: | 63 | except Exception as e: |
| 60 | print("Couldn't create new file") | 64 | print(f"[_readjsonfile] Couldn't create new file ({e})") |
| 61 | return {} | 65 | return {} |
| 62 | 66 | ||
| 63 | except: | 67 | except Exception as e: |
| 64 | print("Other unknown error occured") | 68 | print(f"[_readjsonfile] Other unknown error occured ({e})") |
| 65 | return {} | 69 | return {} |
| 66 | 70 | ||
| 67 | return final | 71 | return final |
| @@ -75,8 +79,8 @@ class SteamRelationships: | |||
| 75 | try: | 79 | try: |
| 76 | jsoncontents = self._readjsonfile(filename) | 80 | jsoncontents = self._readjsonfile(filename) |
| 77 | 81 | ||
| 78 | except: | 82 | except Exception as e: |
| 79 | print(f"Could not get the contents of file {filename}") | 83 | print(f"[_checkrequests] Could not get the contents of file {filename} ({e})") |
| 80 | return -1 | 84 | return -1 |
| 81 | 85 | ||
| 82 | # Check the current date. If over 1 day since last entry, add a new entry. Otherwise, edit the current day's entry [note, 1 day in nanoseconds = (8.64 * (10 ** 13)) ] | 86 | # Check the current date. If over 1 day since last entry, add a new entry. Otherwise, edit the current day's entry [note, 1 day in nanoseconds = (8.64 * (10 ** 13)) ] |
| @@ -92,7 +96,7 @@ class SteamRelationships: | |||
| 92 | jsoncontents[list(jsoncontents.keys())[-1]][1].append(checktime) | 96 | jsoncontents[list(jsoncontents.keys())[-1]][1].append(checktime) |
| 93 | 97 | ||
| 94 | else: | 98 | else: |
| 95 | print(f"Daily request limit reached ({jsoncontents[list(jsoncontents.keys())[-1]][0]}/{CONST.STEAMAPI_MAXREQ * self.reqsafetybuffer}). Please try again tomorrow, or increase \"reqsafetybuffer\" (currently: {self.reqsafetybuffer})") | 99 | print(f"[_checkrequests] Daily request limit reached ({jsoncontents[list(jsoncontents.keys())[-1]][0]}/{CONST.STEAMAPI_MAXREQ * self.reqsafetybuffer}). Please try again tomorrow, or increase \"reqsafetybuffer\" (currently: {self.reqsafetybuffer})") |
| 96 | return 0 | 100 | return 0 |
| 97 | 101 | ||
| 98 | # Update the json file | 102 | # Update the json file |
| @@ -101,68 +105,73 @@ class SteamRelationships: | |||
| 101 | json.dump(jsoncontents, jsonfile, indent=4) | 105 | json.dump(jsoncontents, jsonfile, indent=4) |
| 102 | jsonfile.close() | 106 | jsonfile.close() |
| 103 | 107 | ||
| 104 | except: | 108 | except Exception as e: |
| 105 | print("Could not update json file") | 109 | print("[_checkrequests] Could not update json file ({e})") |
| 106 | return -1 | 110 | return -1 |
| 107 | 111 | ||
| 108 | return jsoncontents[list(jsoncontents.keys())[-1]][0] | 112 | return jsoncontents[list(jsoncontents.keys())[-1]][0] |
| 109 | 113 | ||
| 110 | def _getFriendsList(self, steamid64: str = None) -> dict: | 114 | |
| 111 | # example url: http://api.steampowered.com/ISteamUser/GetFriendList/v0001/?key=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&steamid=76561197960435530&relationship=friend | 115 | |
| 116 | def _getFriendsList(self, steamid64: str, retrys: int = 0) -> dict: | ||
| 112 | if not steamid64: | 117 | if not steamid64: |
| 113 | print("Requested id must not be blank") | 118 | print("[_getFriendsList] No steamid64 given") |
| 114 | return {} | 119 | return {} |
| 115 | 120 | ||
| 116 | # Format url and make a request | 121 | url: str = "https://api.steampowered.com/ISteamUser/GetFriendList/v0001/" |
| 117 | url = "https://api.steampowered.com/ISteamUser/GetFriendList/v0001/" | 122 | options: dict = {"key": self.webapikey, "steamid": steamid64, "format": "json"} |
| 118 | options = {"key": self.webapikey, "steamid": steamid64, "relationship": "friend"} | 123 | result: object = None |
| 124 | |||
| 125 | # Get the result | ||
| 126 | try: | ||
| 127 | result = self.session.get(url, params=options, timeout=self.timeout) | ||
| 119 | 128 | ||
| 120 | # BIG WARNING BIG WARNING BIG WARNING BIG WARNING BIG WARNING BIG WARNING BIG WARNING BIG WARNING BIG WARNING BIG WARNING BIG WARNING # | 129 | except requests.exceptions.Timeout: |
| 121 | # BIG WARNING BIG WARNING BIG WARNING BIG WARNING BIG WARNING BIG WARNING BIG WARNING BIG WARNING BIG WARNING BIG WARNING BIG WARNING # | 130 | print(f"[_getFriendsList] Request timed out (No response for {self.timeout} seconds)") |
| 122 | # BIG WARNING BIG WARNING BIG WARNING BIG WARNING BIG WARNING BIG WARNING BIG WARNING BIG WARNING BIG WARNING BIG WARNING BIG WARNING # | 131 | if retrys <= self.timeout_retries: |
| 132 | print(f"[_getFriendsList] Retrying request... (Attempt {retrys}/{self.timeout_retries})") | ||
| 133 | return self._getFriendsList(steamid64, retrys + 1) | ||
| 123 | 134 | ||
| 124 | # TODO: FIX THIS SO IT DOESN"T EXPLODE EVERYTHING ALL THE TIME | 135 | print("[_getFriendsList] Retry limit reached") |
| 125 | response: object | 136 | return {} |
| 126 | if self._checkrequests() > 0: | ||
| 127 | response = self.session.get(url, params=options, timeout=self.timeout) # GET should be as secure as POST because ssl is being used | ||
| 128 | 137 | ||
| 129 | else: | 138 | except Exception as e: |
| 130 | return None | 139 | print(f"[_getFriendsList] Other error in contacting steam ({e})") |
| 140 | return {} | ||
| 131 | 141 | ||
| 132 | # TODO: Implement proper error checking so that this doesn't just break if someone has a private friends list | 142 | # Error out on request error |
| 133 | if response.status_code == requests.codes.ok: | 143 | if result.status_code != requests.codes.ok: |
| 134 | return response.json() | 144 | print("[_getFriendsList] Got bad status code") |
| 145 | return {} | ||
| 135 | 146 | ||
| 136 | return None | 147 | # Get the json contents from the response |
| 148 | resultjson: dict = {} | ||
| 149 | try: | ||
| 150 | resultjson = result.json() | ||
| 137 | 151 | ||
| 138 | def parseFriendsList(self, friendslist: dict = None) -> list: | 152 | except requests.exceptions.JSONDecodeError: |
| 139 | if not friendslist: | 153 | print("[_getFriendsList] Could not decode json response for some reason") |
| 140 | return None | 154 | return {} |
| 141 | 155 | ||
| 142 | final = [] | 156 | except Exception as e: |
| 143 | for friend in friendslist['friendslist']['friends']: | 157 | print(f"[_getFriendsList] Unknown error in getting json response ({e})") |
| 144 | final.append(friend['steamid']) | 158 | return {} |
| 145 | 159 | ||
| 146 | return final | 160 | return resultjson |
| 147 | 161 | ||
| 148 | # Do a basic scan for a single id | 162 | def _parseFriendsList(self, friendsdict: dict) -> list: |
| 149 | def basic_scan(self, id: str) -> list: | 163 | if not friendsdict: |
| 150 | return self.parseFriendsList(self._getFriendsList(id)) | 164 | print("[_parseFriendsList] Empty friends dict given") |
| 165 | return [] | ||
| 151 | 166 | ||
| 152 | def recursive_scan(self, startid: str, ): | ||
| 153 | scans: dict = {} | ||
| 154 | alreadyscanned: list = [] | ||
| 155 | 167 | ||
| 156 | scans[startid] = self.basic_scan(startid) | 168 | friends: list = [] |
| 157 | alreadyscanned.append(startid) | 169 | try: |
| 158 | 170 | for friend in friendsdict['friendslist']['friends']: | |
| 159 | tempscans: dict = {} | 171 | friends.append(f"{friend}") |
| 160 | for person in scans: | ||
| 161 | for friend in scans[person]: | ||
| 162 | if friend not in alreadyscanned: | ||
| 163 | tempscans[friend] = self.basic_scan(tempscans) | ||
| 164 | alreadyscanned.append(friend) | ||
| 165 | 172 | ||
| 166 | scans.update(tempscans) | 173 | except Exception as e: |
| 174 | print("[_parseFriendsList] Error parsing friendsdict ({e})") | ||
| 175 | friends.clear() | ||
| 167 | 176 | ||
| 168 | return \ No newline at end of file | 177 | return friends \ No newline at end of file |
