|
12 | 12 | import json |
13 | 13 | import sys |
14 | 14 | import time |
| 15 | +from os.path import exists |
15 | 16 |
|
16 | 17 | import requests |
| 18 | +from requests.adapters import HTTPAdapter, Retry |
17 | 19 |
|
18 | 20 | # Handle arguments the script is called with |
19 | 21 | parser = argparse.ArgumentParser() |
|
29 | 31 | with open(args.player_file, encoding="utf-8") as player_file: |
30 | 32 | players = json.loads(player_file.read()) |
31 | 33 |
|
32 | | -with open(args.results_file, encoding="utf-8") as results_file: |
33 | | - results = json.loads(results_file.read()) |
| 34 | +# Initalize results to not error if no results file exists yet |
| 35 | +results = [] |
| 36 | + |
| 37 | +# If a results file exists, load it |
| 38 | +if exists(args.results_file): |
| 39 | + with open(args.results_file, encoding="utf-8") as results_file: |
| 40 | + results = json.loads(results_file.read()) |
34 | 41 |
|
35 | 42 | # Retrieve the result set if it exists or create an empty one |
36 | 43 | # We make sure that we get a view of the dictionary so we can modify |
|
39 | 46 | (result for result in results if result["code"] == args.code), None) |
40 | 47 |
|
41 | 48 | if found_item is None: |
| 49 | + print("New code: " + args.code + " adding to results file and processing.") |
42 | 50 | new_item = {"code": args.code, "status": {}} |
43 | 51 | results.append(new_item) |
44 | 52 | result = new_item |
45 | 53 | else: |
46 | 54 | result = found_item |
47 | 55 |
|
48 | 56 | # Some variables that are used to tracking progress |
49 | | -session_counter = 1 |
50 | 57 | counter_successfully_claimed = 0 |
51 | 58 | counter_already_claimed = 0 |
52 | 59 | counter_error = 0 |
|
58 | 65 | "Accept": "application/json"} |
59 | 66 |
|
60 | 67 | i = 0 |
| 68 | + |
| 69 | +# Enable retry login and backoff behavior so if you have a large number of players (> 30) it'll not fail |
| 70 | +# Default rate limits of WOS API is 30 in 1 min. |
| 71 | +r = requests.Session() |
| 72 | +retry_config = Retry(total=5, backoff_factor=1, status_forcelist=[ 429 ], allowed_methods=False) |
| 73 | +r.mount("https://", HTTPAdapter(max_retries=retry_config)) |
| 74 | + |
61 | 75 | for player in players: |
62 | 76 |
|
63 | 77 | # Print progress bar |
|
81 | 95 | # Login the player |
82 | 96 | # It is enough to send the POST request, we don't need to store any cookies/session tokens |
83 | 97 | # to authenticate during the next request |
84 | | - login_request = requests.post( |
| 98 | + login_request = r.post( |
85 | 99 | URL + '/player', data=request_data, headers=HTTP_HEADER, timeout=30) |
86 | 100 | login_response = login_request.json() |
| 101 | + |
| 102 | + # Login failed for user, report, count error and continue gracefully to complete all other players |
87 | 103 | if login_response["msg"] != "success": |
88 | | - print("Login not possible") |
89 | | - sys.exit(1) |
| 104 | + print("Login not possible for player: " + player["original_name"] + " / " + player["id"] + " - validate their player ID. Skipping.") |
| 105 | + counter_error += 1 |
| 106 | + continue |
90 | 107 |
|
91 | 108 | # Create the request data that contains the signature and the code |
92 | 109 | request_data["cdk"] = args.code |
|
96 | 113 | SALT).encode("utf-8")).hexdigest() |
97 | 114 |
|
98 | 115 | # Send the gif code redemption request |
99 | | - redeem_request = requests.post( |
| 116 | + redeem_request = r.post( |
100 | 117 | URL + '/gift_code', data=request_data, headers=HTTP_HEADER, timeout=30) |
101 | 118 | redeem_response = redeem_request.json() |
102 | 119 |
|
|
120 | 137 | print("\nError occurred: " + str(redeem_response)) |
121 | 138 | counter_error += 1 |
122 | 139 |
|
123 | | - # Refresh the webpage every 5 players to avoid getting soft-banned at some point |
124 | | - if session_counter % 5 == 0: |
125 | | - time.sleep(5) |
126 | | - |
127 | | - session_counter += 1 |
128 | | - |
129 | 140 | with open(args.results_file, 'w', encoding="utf-8") as fp: |
130 | 141 | json.dump(results, fp) |
131 | 142 |
|
|
0 commit comments