· 6 years ago · Mar 24, 2020, 01:20 AM
1import configparser
2import operator
3import os
4import webbrowser
5from datetime import datetime, timedelta
6from time import time
7
8import pushbullet
9import pyperclip
10import requests
11import win32api
12import win32con
13import win32gui
14from PIL import ImageGrab
15from playsound import playsound
16
17
18def Avg(lst):
19 return sum(lst) / len(lst)
20
21
22def enum_cb(hwnd, results):
23 winlist.append((hwnd, win32gui.GetWindowText(hwnd)))
24
25
26def write(message, add_time=True, push=0, push_now=False):
27 if message:
28 if add_time:
29 m = datetime.now().strftime("%H:%M:%S") + ": " + str(message)
30 else:
31 m = message
32 print(m)
33
34 if push >= 3:
35 global note
36 if message:
37 note = note + m + "\n"
38 if push_now:
39 device.push_note("CSGO AUTO ACCEPT", note)
40 note = ""
41
42
43def click(x, y):
44 win32api.SetCursorPos((x, y))
45 win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, x, y, 0, 0)
46 win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, x, y, 0, 0)
47
48
49def relate_list(l_org, l1, l2=[], relate=operator.le):
50 if not l_org:
51 return False
52 truth_list, l3 = [], []
53 for i, val in enumerate(l1, start=0):
54 l3.append(relate(l_org[i], val))
55 truth_list.append(all(l3))
56 l3 = []
57 if l2:
58 for i, val in enumerate(l2, start=3):
59 l3.append(relate(l_org[i], val))
60 truth_list.append(all(l3))
61 return any(truth_list)
62
63
64def color_average(image, compare_list):
65 average = []
66 r, g, b = [], [], []
67 data = image.getdata()
68 for i in data:
69 r.append(i[0])
70 g.append(i[1])
71 b.append(i[2])
72
73 rgb = [Avg(r), Avg(g), Avg(b)] * int(len(compare_list) / 3)
74
75 for i, val in enumerate(compare_list, start=0):
76 average.append(val - rgb[i])
77 average = list(map(abs, average))
78
79 return average
80
81
82def getScreenShot(window_id, area=(0, 0, 0, 0)):
83 area = list(area)
84 scaled_area = [screen_width / 2560, screen_height / 1440]
85 scaled_area = 2 * scaled_area
86 for i, _ in enumerate(area[-2:], start=len(area) - 2):
87 area[i] += 1
88 for i, val in enumerate(area, start=0):
89 scaled_area[i] = scaled_area[i] * val
90 scaled_area = list(map(int, scaled_area))
91 win32gui.ShowWindow(window_id, win32con.SW_MAXIMIZE)
92 image = ImageGrab.grab(scaled_area)
93 return image
94
95
96def getOldSharecodes(num=-1):
97 try:
98 last_game = open("last_game.txt", "r")
99 games = last_game.readlines()
100 last_game.close()
101 except FileNotFoundError:
102 last_game = open("last_game.txt", "w")
103 last_game.write(config.get("csgostats.gg", "Match Token") + "\n")
104 games = [config.get("csgostats.gg", "Match Token")]
105 last_game.close()
106 last_game = open("last_game.txt", "w")
107 games = games[-200:]
108 for i, val in enumerate(games):
109 games[i] = "CSGO" + val.strip("\n").split("CSGO")[1]
110 last_game.write(games[i] + "\n")
111 last_game.close()
112 return games[num:]
113
114
115def getNewCSGOMatches(game_id):
116 sharecodes = []
117 next_code = game_id
118 last_game = open("last_game.txt", "a")
119 while next_code != "n/a":
120 steam_url = "https://api.steampowered.com/ICSGOPlayers_730/GetNextMatchSharingCode/v1?key=" + steam_api_key + "&steamid=" + steam_id + "&steamidkey=" + game_code + "&knowncode=" + game_id
121 try:
122 next_code = (requests.get(steam_url).json()["result"]["nextcode"])
123 except KeyError:
124 write("WRONG GAME_CODE, GAME_ID or STEAM_ID ")
125 return 0
126
127 if next_code:
128 if next_code != "n/a":
129 sharecodes.append(next_code)
130 game_id = next_code
131 last_game.write(next_code + "\n")
132 if sharecodes:
133 return sharecodes
134 else:
135 return [game_id]
136
137
138def UpdateCSGOstats(sharecodes, num_completed=1):
139 completed_games, analyze_games = [], []
140 for val in sharecodes:
141 response = requests.post("https://csgostats.gg/match/upload/ajax", data={'sharecode': val, 'index': '1'})
142 if response.json()["status"] == "complete":
143 completed_games.append(response.json())
144 else:
145 analyze_games.append(response.json())
146 # TEST GAME:
147 # analyze_games = [{'status': 'complete', 'data': {'msg': 'Complete - <a href="/match/7584322">View</a>', 'index': '1', 'sharecode': 'CSGO-7NiMO-RPjvj-MZNWP-9cRdx-vzYUN', 'queue_id': 8081108, 'demo_id': 7584322, 'url': 'https://csgostats.gg/match/7584322'}, 'error': 0}]
148 output = [completed_games[num_completed * -1:], analyze_games]
149 for i in output:
150 for json_dict in i:
151 sharecode = json_dict["data"]["sharecode"]
152 game_url = json_dict["data"]["url"]
153 info = json_dict["data"]["msg"].split("<")[0].replace('-', '').rstrip(" ")
154 write('Sharecode: %s' % sharecode, add_time=False, push=push_urgency)
155 write("URL: %s" % game_url, add_time=False, push=push_urgency)
156 write("Status: %s." % info, add_time=False, push=push_urgency)
157 write(None, add_time=False, push=push_urgency, push_now=True)
158 pyperclip.copy(completed_games[-1]["data"]["url"])
159 return game_url
160
161
162def getHotKeys():
163 get_keys = [int(config.get("HotKeys", "Activate Script"), 16), int(config.get("HotKeys", "Activate Push Notification"), 16), int(config.get("HotKeys", "Get Info on newest Match"), 16),
164 int(config.get("HotKeys", "Get Info on multiple Matches"), 16), int(config.get("HotKeys", "Live Tab Key"), 16),
165 int(config.get("HotKeys", "End Script"), 16)]
166 return get_keys
167
168
169config = configparser.ConfigParser()
170config.read("config.ini")
171
172steam_api_key = config.get("csgostats.gg", "API Key")
173steam_id = config.get("csgostats.gg", "Steam ID")
174game_code = config.get("csgostats.gg", "Game Code")
175
176screenshot_interval = config.getint("Screenshot", "Interval")
177
178keys = getHotKeys()
179
180device = 0
181
182screen_width, screen_height = win32api.GetSystemMetrics(0), win32api.GetSystemMetrics(1)
183toplist, winlist = [], []
184hwnd = 0
185
186test_for_live_game, test_for_success, push_urgency, testing = False, False, False, False
187# accept_avg = []
188
189note = ""
190
191start_time = time()
192write("READY")
193print("\n")
194
195while True:
196 if win32api.GetAsyncKeyState(keys[0]) & 1: # F9 (ACTIVATE / DEACTIVATE SCRIPT)
197 test_for_live_game = not test_for_live_game
198 write("TESTING: %s" % test_for_live_game)
199 if test_for_live_game:
200 playsound('sounds/activated.mp3')
201 time_searching = time()
202 else:
203 playsound('sounds/deactivated.mp3')
204
205 if win32api.GetAsyncKeyState(keys[1]) & 1: # F8 (ACTIVATE / DEACTIVATE PUSH NOTIFICATION)
206 if not device:
207 PushBulletDeviceName = config.get('Pushbullet', 'Device Name')
208 PushBulletAPIKey = config.get('Pushbullet', 'API Key')
209 try:
210 device = pushbullet.PushBullet(PushBulletAPIKey).get_device(PushBulletDeviceName)
211 except pushbullet.errors.PushbulletError or pushbullet.errors.InvalidKeyError:
212 write("Pushbullet is wrongly configured.\nWrong API Key or DeviceName in config.ini")
213 if device:
214 push_urgency += 1
215 if push_urgency > 3:
216 push_urgency = 0
217 push_info = ["not active", "only if accepted", "all game status related information", "all information (game status/csgostats.gg information)"]
218 write("Pushing: %s" % push_info[push_urgency])
219
220 if win32api.GetAsyncKeyState(keys[2]) & 1: # F7 Key (UPLOAD NEWEST MATCH)
221 write("Uploading / Getting status on newest match")
222 pyperclip.copy(UpdateCSGOstats(getNewCSGOMatches(getOldSharecodes()[0])))
223
224 if win32api.GetAsyncKeyState(keys[3]) & 1: # F6 Key (GET INFO ON LAST X MATCHES)
225 last_x_matches = config.getint("csgostats.gg", "Number of Requests")
226 completed_matches = config.getint("csgostats.gg", "Completed Matches")
227 write("Getting Info from last %s matches" % last_x_matches)
228 # write("Outputting %s completed match[es]" % completed_matches, add_time=False)
229 getNewCSGOMatches(getOldSharecodes()[0])
230 UpdateCSGOstats(getOldSharecodes(num=last_x_matches * -1), num_completed=completed_matches)
231
232 if win32api.GetAsyncKeyState(keys[4]) & 1: # F13 Key (OPEN WEB BROWSER ON LIVE GAME TAB)
233 webbrowser.open_new_tab("https://csgostats.gg/player/" + steam_id + "#/live")
234 write("new tab opened", add_time=False)
235
236 if win32api.GetAsyncKeyState(keys[5]) & 1: # POS1/HOME Key
237 write("Exiting Script")
238 break
239
240 winlist = []
241 win32gui.EnumWindows(enum_cb, toplist)
242 csgo = [(hwnd, title) for hwnd, title in winlist if 'counter-strike: global offensive' in title.lower()]
243 if not csgo:
244 continue
245 hwnd = csgo[0][0]
246
247 # TESTING HERE
248 if win32api.GetAsyncKeyState(0x73) & 1: # F5, TEST CODE
249 print("\n")
250 write("Executing TestCode")
251 print("\n")
252 testing = not testing
253
254 if testing:
255 # start_time = time()
256 img = getScreenShot(hwnd, (2435, 65, 2555, 100))
257 not_searching_avg = color_average(img, [6, 10, 10])
258 searching_avg = color_average(img, [6, 163, 97, 4, 63, 35])
259 not_searching = relate_list(not_searching_avg, [2, 5, 5])
260 searching = relate_list(searching_avg, [2.7, 55, 35], l2=[1, 50, 35])
261 img = getScreenShot(hwnd, (467, 1409, 1300, 1417))
262 success_avg = color_average(img, [21, 123, 169])
263 success = relate_list(success_avg, [1, 8, 7])
264 # print("Took: %s " % str(timedelta(milliseconds=int(time()*1000 - start_time*1000))))
265 # TESTING ENDS HERE
266
267 if test_for_live_game:
268 if time() - start_time < screenshot_interval:
269 continue
270 start_time = time()
271 img = getScreenShot(hwnd, (1265, 760, 1295, 785))
272 if not img:
273 continue
274 accept_avg = color_average(img, [76, 176, 80, 90, 203, 95])
275
276 if relate_list(accept_avg, [1, 2, 1], l2=[1, 1, 2]):
277 write("Trying to Accept", push=push_urgency + 1)
278
279 test_for_success = True
280 test_for_live_game = False
281 accept_avg = []
282
283 for _ in range(5):
284 click(int(screen_width / 2), int(screen_height / 1.78))
285 # sleep(0.5)
286 # pass
287
288 write("Trying to catch a loading map")
289 playsound('sounds/accept_found.mp3')
290 start_time = time()
291
292 if test_for_success:
293 if time() - start_time < 40:
294 img = getScreenShot(hwnd, (2435, 65, 2555, 100))
295 not_searching_avg = color_average(img, [6, 10, 10])
296 searching_avg = color_average(img, [6, 163, 97, 4, 63, 35])
297
298 not_searching = relate_list(not_searching_avg, [2, 5, 5])
299 searching = relate_list(searching_avg, [2.7, 55, 35], l2=[1, 50, 35])
300
301 img = getScreenShot(hwnd, (467, 1409, 1300, 1417))
302 success_avg = color_average(img, [21, 123, 169])
303 success = relate_list(success_avg, [1, 8, 7])
304
305 if success:
306 write("Took %s since pressing accept." % str(timedelta(seconds=int(time() - start_time))), add_time=False, push=push_urgency + 1)
307 write("Took %s since trying to find a game." % str(timedelta(seconds=int(time() - time_searching))), add_time=False, push=push_urgency + 1)
308 write("Game should have started", push=push_urgency + 2, push_now=True)
309 test_for_success = False
310 playsound('sounds/done_testing.mp3')
311
312 if any([searching, not_searching]):
313 write("Took: %s " % str(timedelta(seconds=int(time() - start_time))), add_time=False, push=push_urgency + 1)
314 write("Game doesnt seem to have started. Continuing to search for accept Button!", push=push_urgency + 1, push_now=True)
315 playsound('sounds/back_to_testing.mp3')
316 test_for_success = False
317 test_for_live_game = True
318
319 else:
320 write("40 Seconds after accept, did not find loading map nor searching queue")
321 test_for_success = False
322 print(success_avg)
323 print(searching_avg)
324 print(not_searching_avg)
325 playsound('sounds/fail.mp3')
326 img.save(os.path.expanduser("~") + '\\Unknown Error.png')