summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--steamrelationships/sr.py119
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