· 6 years ago · Apr 20, 2020, 06:00 PM
1import configparser
2import operator
3import os
4import sys
5import time
6import webbrowser
7from datetime import datetime, timedelta
8
9import pushbullet
10import pyperclip
11import pytesseract
12import requests
13import win32api
14import win32con
15import win32gui
16from PIL import ImageGrab, Image
17from playsound import playsound
18
19
20def Avg(lst: list):
21 if not lst:
22 return 0
23 return sum(lst) / len(lst)
24
25
26# noinspection PyShadowingNames,PyUnusedLocal
27def enum_cb(hwnd, results):
28 winlist.append((hwnd, win32gui.GetWindowText(hwnd)))
29
30
31# noinspection PyShadowingNames
32def write(message, add_time: bool = True, push: int = 0, push_now: bool = False, output: bool = True, overwrite: str = '0'):
33 if output:
34 message = str(message)
35 if add_time:
36 message = datetime.now().strftime('%H:%M:%S') + ': ' + message
37 global last_printed_line
38 splits = last_printed_line.split(b'**')
39 last_key = splits[0]
40 last_string = splits[1].strip(b'\n\r')
41 last_end = splits[-1]
42 if overwrite != '0':
43 ending = console_window['suffix']
44 if last_key == overwrite.encode():
45 if console_window['isatty']:
46 print(' ' * len(last_string.decode()), end=ending)
47 message = console_window['prefix'] + message
48 else:
49 if last_end != b'\n':
50 message = '\n' + message
51 else:
52 ending = '\n'
53 if last_end != b'\n':
54 message = '\n' + message
55
56 last_printed_line = (overwrite + '**' + message + '**' + ending).encode()
57 print(message, end=ending)
58
59 if push >= 3:
60 global note
61 if message:
62 note = note + str(message.strip('\n\r')) + '\n'
63 if push_now:
64 device.push_note('CSGO AUTO ACCEPT', note)
65 note = ''
66
67
68# noinspection PyShadowingNames
69def click(x: int, y: int):
70 win32api.SetCursorPos((x, y))
71 win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, x, y, 0, 0)
72 win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, x, y, 0, 0)
73
74
75# noinspection PyShadowingNames
76def relate_list(l_org, compare_list, relate: operator = operator.le):
77 if not l_org:
78 return False
79 truth_list = []
80 for list_part in compare_list:
81 partial_truth = []
82 for i, val in enumerate(list_part):
83 partial_truth.append(relate(l_org[i], val))
84 truth_list.append(all(partial_truth))
85 l_org = l_org[len(list_part):]
86 return any(truth_list)
87
88
89# noinspection PyShadowingNames
90def color_average(image: Image, compare_list: list):
91 average = []
92 r, g, b = [], [], []
93 data = image.getdata()
94 for i in data:
95 r.append(i[0])
96 g.append(i[1])
97 b.append(i[2])
98
99 rgb = [Avg(r), Avg(g), Avg(b)] * len(compare_list)
100 for part in compare_list:
101 for i, val in enumerate(part):
102 average.append(val - rgb[i])
103 average = list(map(abs, average))
104 return average
105
106
107# noinspection PyShadowingNames
108def getScreenShot(window_id: int, area: tuple = (0, 0, 0, 0)):
109 area = list(area)
110 win32gui.ShowWindow(window_id, win32con.SW_MAXIMIZE)
111 scaled_area = [screen_width / 2560, screen_height / 1440]
112 scaled_area = 2 * scaled_area
113 for i, _ in enumerate(area[-2:], start=len(area) - 2):
114 area[i] += 1
115 for i, val in enumerate(area, start=0):
116 scaled_area[i] = scaled_area[i] * val
117 scaled_area = list(map(int, scaled_area))
118 image = ImageGrab.grab(scaled_area)
119 return image
120
121
122# noinspection PyShadowingNames
123def getAccountsFromCfg():
124 steam_ids = ''
125 for i in config.sections():
126 if i.startswith('Account'):
127 steam_id = config.get(i, 'Steam ID')
128 auth_code = config.get(i, 'Authentication Code')
129 match_token = config.get(i, 'Match Token')
130 steam_ids += steam_id + ','
131 accounts.append({'steam_id': steam_id, 'auth_code': auth_code, 'match_token': match_token})
132
133 steam_ids = steam_ids.lstrip(',').rstrip(',')
134 profiles = requests.get('http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=' + cfg['steam_api_key'] + '&steamids=' + steam_ids).json()['response']['players']
135 name_list = [online_data['personaname'] for local_acc in accounts for online_data in profiles if online_data['steamid'] == local_acc['steam_id']]
136 for num, val in enumerate(accounts):
137 val['name'] = name_list[num]
138
139
140# noinspection PyShadowingNames
141def getOldSharecodes(last_x: int = -1, from_x: str = ''):
142 if last_x >= 0:
143 return []
144 try:
145 last_game = open(appdata_path+'last_game_' + accounts[current_account]['steam_id'] + '.txt', 'r')
146 games = last_game.readlines()
147 last_game.close()
148 except FileNotFoundError:
149 last_game = open(appdata_path+'last_game_' + accounts[current_account]['steam_id'] + '.txt', 'w')
150 last_game.write(accounts[current_account]['match_token'] + '\n')
151 games = [accounts[current_account]['match_token']]
152 last_game.close()
153 last_game = open(appdata_path+'last_game_' + accounts[current_account]['steam_id'] + '.txt', 'w')
154 games = games[-200:]
155 for i, val in enumerate(games):
156 games[i] = 'CSGO' + val.strip('\n').split('CSGO')[1]
157 last_game.write(games[i] + '\n')
158 last_game.close()
159 if from_x:
160 try:
161 return games[(len(games) - games.index(from_x)) * -1:]
162 except ValueError:
163 return []
164 return games[last_x:]
165
166
167# noinspection PyShadowingNames
168def getNewCSGOSharecodes(game_id: str):
169 sharecodes = []
170 next_code = game_id
171 last_game = open(appdata_path+'last_game_' + accounts[current_account]['steam_id'] + '.txt', 'a')
172 while next_code != 'n/a':
173 steam_url = 'https://api.steampowered.com/ICSGOPlayers_730/GetNextMatchSharingCode/v1?key=' + cfg['steam_api_key'] + '&steamid=' + accounts[current_account]['steam_id'] + '&steamidkey=' + accounts[current_account][
174 'auth_code'] + '&knowncode=' + game_id
175 try:
176 next_code = (requests.get(steam_url).json()['result']['nextcode'])
177 except KeyError:
178 write('WRONG Match Token, Authentication Code or Steam ID ')
179 return [{'sharecode': game_id, 'queue_pos': None}]
180
181 if next_code:
182 if next_code != 'n/a':
183 sharecodes.append(next_code)
184 game_id = next_code
185 last_game.write(next_code + '\n')
186 last_game.close()
187 test = [{'sharecode': code, 'queue_pos': None} for code in sharecodes]
188 return test
189
190
191# noinspection PyShadowingNames
192def UpdateCSGOstats(repeater=None, get_all_games=False):
193 all_games, completed_games, not_completed_games, = [], [], []
194
195 if repeater is None:
196 repeater = []
197 if repeater:
198 if get_all_games:
199 sharecodes = [getOldSharecodes(from_x=code['sharecode']) for code in repeater]
200 sharecodes = max(sharecodes, key=len)
201 else:
202 sharecodes = [code['sharecode'] for code in repeater]
203 all_games = [requests.post('https://csgostats.gg/match/upload/ajax', data={'sharecode': sharecode, 'index': '1'}).json() for sharecode in sharecodes]
204 else:
205 num = -1
206 sharecode = getOldSharecodes(num)[0]
207 while True:
208 response = requests.post('https://csgostats.gg/match/upload/ajax', data={'sharecode': sharecode, 'index': '1'})
209 all_games.append(response.json())
210 if response.json()['status'] != 'complete':
211 num -= 1
212 try:
213 sharecode = getOldSharecodes(num)[0]
214 except IndexError:
215 break
216 else:
217 break
218 temp_games = [{'sharecode': game['data']['sharecode']} for game in all_games if game['status'] != 'complete']
219 if temp_games and len(all_games) > 1:
220 all_games = all_games[:-1]
221
222 for game in all_games:
223 if game['status'] == 'complete':
224 completed_games.append(game)
225 else:
226 not_completed_games.append(game)
227
228 queued_games = [{'sharecode': game['data']['sharecode'], 'queue_pos': game['data']['queue_pos']} for game in not_completed_games if game['status'] != 'error']
229 corrupt_games = [{'sharecode': game['data']['sharecode'], 'queue_pos': game['data']['queue_pos']} for game in not_completed_games if game['status'] == 'error']
230
231 global queue_difference, time_table
232 if queued_games:
233 temp_string = ''
234 for i, val in enumerate(queued_games):
235 temp_string += '#' + str(i + 1) + ': in Queue #' + str(val['queue_pos']) + ' - '
236
237 if repeater:
238 current_queue_difference = Avg([last_game['queue_pos'] - game['queue_pos'] for game in queued_games for last_game in repeater if last_game['sharecode'] == game['sharecode'] and last_game['queue_pos'] is not None])
239 if current_queue_difference:
240 queue_difference.append(current_queue_difference / ((time.time() - time_table['time_since_retry']) / 60))
241 queue_difference = queue_difference[-10:]
242 matches_per_min = round(Avg(queue_difference), 1)
243 if isinstance(matches_per_min, float):
244 time_till_done = str(timedelta(seconds=int((queued_games[0]['queue_pos'] / matches_per_min) * 60)))
245 else:
246 time_till_done = '∞:∞:∞'
247 temp_string += str(matches_per_min) + ' matches/min - #1 done in ' + time_till_done
248 temp_string = temp_string.rstrip(' - ')
249 write(temp_string, add_time=False, overwrite='4')
250
251 time_table['time_since_retry'] = time.time()
252 repeater = [game for game in queued_games if game['queue_pos'] < cfg['max_queue_position']]
253 repeater.extend([game for game in corrupt_games])
254
255 if corrupt_games:
256 write('An error occurred in %s game[s].' % len(corrupt_games), overwrite='5')
257
258 if completed_games:
259 for i in completed_games:
260 sharecode = i['data']['sharecode']
261 game_url = i['data']['url']
262 info = ' '.join(i['data']['msg'].replace('-', '').replace('<br />', '. ').split('<')[0].rstrip(' ').split())
263 write('Sharecode: %s' % sharecode, add_time=False, push=push_urgency)
264 write('URL: %s' % game_url, add_time=False, push=push_urgency)
265 write('Status: %s.' % info, add_time=True, push=push_urgency)
266 pyperclip.copy(game_url)
267 write(None, add_time=False, push=push_urgency, push_now=True, output=False)
268 return repeater
269
270
271# noinspection PyShadowingNames,PyUnusedLocal
272def Image_to_Text(image: Image, size: tuple, white_threshold: tuple, arg: str = ''):
273 image_data = image.getdata()
274 pixel_map, image_text = [], ''
275 for y in range(size[1]):
276 for x in range(size[0]):
277 if relate_list(image_data[y * size[0] + x], [white_threshold], relate=operator.ge):
278 pixel_map.append((0, 0, 0))
279 else:
280 pixel_map.append((255, 255, 255))
281 temp_image = Image.new('RGB', (size[0], size[1]))
282 temp_image.putdata(pixel_map)
283 try:
284 image_text = pytesseract.image_to_string(temp_image, timeout=0.3, config=arg)
285 except RuntimeError as timeout_error:
286 pass
287 if image_text:
288 image_text = ' '.join(image_text.replace(': ', ':').split())
289 global truth_table
290 if truth_table['debugging']:
291 image.save(str(cfg['debug_path']) + '\\' + datetime.now().strftime('%H-%M-%S') + '_' + image_text.replace(':', '-') + '.png', format='PNG')
292 temp_image.save(str(cfg['debug_path']) + '\\' + datetime.now().strftime('%H-%M-%S') + '_' + image_text.replace(':', '-') + '_temp.png', format='PNG')
293 return image_text
294 else:
295 return False
296
297
298def getCfgData():
299 try:
300 get_cfg = {'activate_script': int(config.get('HotKeys', 'Activate Script'), 16), 'activate_push_notification': int(config.get('HotKeys', 'Activate Push Notification'), 16),
301 'info_newest_match': int(config.get('HotKeys', 'Get Info on newest Match'), 16),
302 'open_live_tab': int(config.get('HotKeys', 'Live Tab Key'), 16), 'switch_accounts': int(config.get('HotKeys', 'Switch accounts for csgostats.gg'), 16),
303 'end_script': int(config.get('HotKeys', 'End Script'), 16),
304 'screenshot_interval': config.getint('Screenshot', 'Interval'), 'debug_path': config.get('Screenshot', 'Debug Path'), 'steam_api_key': config.get('csgostats.gg', 'API Key'),
305 'last_x_matches': config.getint('csgostats.gg', 'Number of Requests'),
306 'completed_matches': config.getint('csgostats.gg', 'Completed Matches'), 'max_queue_position': config.getint('csgostats.gg', 'Auto-Retrying for queue position below'),
307 'auto_retry_interval': config.getint('csgostats.gg', 'Auto-Retrying-Interval'), 'pushbullet_device_name': config.get('Pushbullet', 'Device Name'), 'pushbullet_api_key': config.get('Pushbullet', 'API Key'),
308 'tesseract_path': config.get('Warmup', 'Tesseract Path'), 'warmup_test_interval': config.getint('Warmup', 'Test Interval'), 'warmup_push_interval': config.get('Warmup', 'Push Interval'),
309 'warmup_no_text_limit': config.getint('Warmup', 'No Text Limit')}
310 return get_cfg
311 # 'imgur_id': config.get('Imgur', 'Client ID'), 'imgur_secret': config.get('Imgur', 'Client Secret'), 'stop_warmup_ocr': int(config.get('HotKeys', 'Stop Warmup OCR'), 16), 'info_multiple_matches': int(config.get('HotKeys', 'Get Info on multiple Matches'), 16),
312 except (configparser.NoOptionError, configparser.NoSectionError, ValueError):
313 write('ERROR IN CONFIG')
314 exit('CHECK FOR NEW CONFIG')
315
316
317# OVERWRITE SETUP
318appdata_path = os.getenv('APPDATA') + '\\CSGO AUTO ACCEPT\\'
319try:
320 os.mkdir(appdata_path)
321except FileExistsError:
322 pass
323last_printed_line = b'0**\n'
324console_window = {}
325if not sys.stdout.isatty():
326 console_window = {'prefix': '\r', 'suffix': '', 'isatty': False}
327else:
328 console_window = {'prefix': '', 'suffix': '\r', 'isatty': True}
329
330# CONFIG HANDLING
331config = configparser.ConfigParser()
332config.read('config.ini')
333cfg = getCfgData()
334device = 0
335
336# ACCOUNT HANDLING, GETTING ACCOUNT NAME
337accounts, current_account = [], 0
338getAccountsFromCfg()
339
340# INITIALIZATION FOR getScreenShot
341screen_width, screen_height = win32api.GetSystemMetrics(0), win32api.GetSystemMetrics(1)
342toplist, winlist = [], []
343hwnd = 0
344
345# BOOLEAN, TIME INITIALIZATION
346truth_table = {'test_for_live_game': False, 'test_for_success': False, 'test_for_warmup': False, 'first_ocr': True, 'testing': False, 'debugging': False, 'first_push': True}
347time_table = {'screenshot_time': time.time(), 'time_since_retry': time.time(), 'warmup_test_timer': time.time(), 'time_searching': time.time()}
348
349# csgostats.gg VAR
350retryer = []
351
352# WARMUP DETECTION SETUP
353pytesseract.pytesseract.tesseract_cmd = cfg['tesseract_path']
354push_times, no_text_found, push_counter = [], 0, 0
355for i in cfg['warmup_push_interval'].split(','):
356 push_times.append(int(i))
357push_times.sort(reverse=True)
358join_warmup_time = push_times[0] + 1
359
360# PUSHBULLET VAR
361note = ''
362push_urgency = 0
363
364write('READY')
365write('Current account is: %s\n' % accounts[current_account]['name'], add_time=False)
366
367while True:
368 if win32api.GetAsyncKeyState(cfg['activate_script']) & 1: # F9 (ACTIVATE / DEACTIVATE SCRIPT)
369 truth_table['test_for_live_game'] = not truth_table['test_for_live_game']
370 write('TESTING: %s' % truth_table['test_for_live_game'], overwrite='1')
371 if truth_table['test_for_live_game']:
372 playsound('sounds/activated_2.mp3')
373 time_table['time_searching'] = time.time()
374 else:
375 playsound('sounds/deactivated.mp3')
376
377 if win32api.GetAsyncKeyState(cfg['activate_push_notification']) & 1: # F8 (ACTIVATE / DEACTIVATE PUSH NOTIFICATION)
378 if not device:
379 try:
380 device = pushbullet.PushBullet(cfg['pushbullet_api_key']).get_device(cfg['pushbullet_device_name'])
381 except (pushbullet.errors.PushbulletError, pushbullet.errors.InvalidKeyError):
382 write('Pushbullet is wrongly configured.\nWrong API Key or DeviceName in config.ini')
383 if device:
384 push_urgency += 1
385 if push_urgency > 3:
386 push_urgency = 0
387 push_info = ['not active', 'only if accepted', 'all game status related information', 'all information (game status/csgostats.gg information)']
388 write('Pushing: %s' % push_info[push_urgency], overwrite='2')
389
390 if win32api.GetAsyncKeyState(cfg['info_newest_match']) & 1: # F7 Key (UPLOAD NEWEST MATCH)
391 write('Uploading / Getting status on newest match')
392 queue_difference = []
393 new_sharecodes = getNewCSGOSharecodes(getOldSharecodes(-1)[0])
394 for new_code in new_sharecodes:
395 retryer.append(new_code) if new_code['sharecode'] not in [old_code['sharecode'] for old_code in retryer] else retryer
396 retryer = UpdateCSGOstats(retryer, get_all_games=True)
397
398 if win32api.GetAsyncKeyState(cfg['open_live_tab']) & 1: # F13 Key (OPEN WEB BROWSER ON LIVE GAME TAB)
399 win32gui.ShowWindow(hwnd, win32con.SW_MAXIMIZE)
400 webbrowser.open_new_tab('https://csgostats.gg/player/' + accounts[current_account]['steam_id'] + '#/live')
401 write('new tab opened', add_time=False)
402 time.sleep(0.5)
403 win32gui.ShowWindow(hwnd, win32con.SW_MAXIMIZE)
404
405 if win32api.GetAsyncKeyState(cfg['switch_accounts']) & 1: # F15 (SWITCH ACCOUNTS)
406 current_account += 1
407 if current_account > len(accounts) - 1:
408 current_account = 0
409 write('current account is: %s' % accounts[current_account]['name'], add_time=False, overwrite='3')
410
411 if win32api.GetAsyncKeyState(cfg['end_script']) & 1: # POS1 (END SCRIPT)
412 write('Exiting Script')
413 break
414
415 if retryer:
416 if time.time() - time_table['time_since_retry'] > cfg['auto_retry_interval']:
417 retryer = UpdateCSGOstats(retryer)
418
419 winlist = []
420 win32gui.EnumWindows(enum_cb, toplist)
421 csgo = [(hwnd, title) for hwnd, title in winlist if 'counter-strike: global offensive' in title.lower()]
422
423 # ONLY CONTINUING IF CSGO IS RUNNING
424 if not csgo:
425 continue
426 hwnd = csgo[0][0]
427
428 # TESTING HERE
429 if win32api.GetAsyncKeyState(0x6F) & 1: # UNBOUND, TEST CODE
430 # truth_table['testing'] = not truth_table['testing']
431 truth_table['debugging'] = not truth_table['debugging']
432 # truth_table['test_for_warmup'] = not truth_table['test_for_warmup']
433 # time_table['warmup_test_timer'] = time.time() + 2
434 write('DEBUGGING: %s\n' % truth_table['debugging'])
435
436 if truth_table['testing']:
437 # time_table['screenshot_time'] = time.time()
438 pass
439 # print('Took: %s ' % str(timedelta(milliseconds=int(time.time(*1000 - time_table['screenshot_time']*1000))))
440 # TESTING ENDS HERE
441
442 if truth_table['test_for_live_game']:
443 if time.time() - time_table['screenshot_time'] < cfg['screenshot_interval']:
444 continue
445 time_table['screenshot_time'] = time.time()
446 img = getScreenShot(hwnd, (1265, 760, 1295, 785))
447 if not img:
448 continue
449 accept_avg = color_average(img, [(76, 176, 80), (89, 203, 94)])
450 if relate_list(accept_avg, [(2, 2, 2), (2, 2, 2)]):
451 write('Trying to Accept', push=push_urgency + 1)
452
453 truth_table['test_for_success'] = True
454 truth_table['test_for_live_game'] = False
455 accept_avg = []
456
457 for _ in range(5):
458 click(int(screen_width / 2), int(screen_height / 1.78))
459 pass
460
461 write('Trying to catch a loading map')
462 playsound('sounds/accept_found.mp3')
463 time_table['screenshot_time'] = time.time()
464
465 if truth_table['test_for_success']:
466 if time.time() - time_table['screenshot_time'] < 40:
467 img = getScreenShot(hwnd, (2435, 65, 2555, 100))
468 not_searching_avg = color_average(img, [(6, 10, 10)])
469 searching_avg = color_average(img, [(6, 163, 97), (4, 63, 35)])
470
471 not_searching = relate_list(not_searching_avg, [(2, 5, 5)])
472 searching = relate_list(searching_avg, [(2.7, 55, 35), (1, 50, 35)])
473
474 img = getScreenShot(hwnd, (467, 1409, 1300, 1417))
475 success_avg = color_average(img, [(21, 123, 169)])
476 success = relate_list(success_avg, [(1, 8, 7)])
477
478 if success:
479 write('Took %s since pressing accept.' % str(timedelta(seconds=int(time.time() - time_table['screenshot_time']))), add_time=False, push=push_urgency + 1)
480 write('Took %s since trying to find a game.' % str(timedelta(seconds=int(time.time() - time_table['time_searching']))), add_time=False, push=push_urgency + 1)
481 write('Game should have started', push=push_urgency + 2, push_now=True)
482 truth_table['test_for_success'] = False
483 truth_table['test_for_warmup'] = True
484 playsound('sounds/done_testing.mp3')
485 time_table['warmup_test_timer'] = time.time() + 5
486 continue
487
488 if any([searching, not_searching]):
489 write('Took: %s ' % str(timedelta(seconds=int(time.time() - time_table['screenshot_time']))), add_time=False, push=push_urgency + 1)
490 write('Game doesnt seem to have started. Continuing to search for accept Button!', push=push_urgency + 1, push_now=True)
491 playsound('sounds/back_to_testing.mp3')
492 truth_table['test_for_success'] = False
493 truth_table['test_for_live_game'] = True
494 continue
495
496 else:
497 write('40 Seconds after accept, did not find loading map nor searching queue')
498 truth_table['test_for_success'] = False
499 # noinspection PyUnboundLocalVariable
500 print(success_avg)
501 # noinspection PyUnboundLocalVariable
502 print(searching_avg)
503 # noinspection PyUnboundLocalVariable
504 print(not_searching_avg)
505 playsound('sounds/fail.mp3')
506 # noinspection PyUnboundLocalVariable
507 img.save(os.path.expanduser('~') + '\\Unknown Error.png')
508
509 if truth_table['test_for_warmup']:
510
511 for i in range(112, 113): # 136
512 win32api.GetAsyncKeyState(i) & 1
513 truth_table['test_for_live_game'] = False
514 while True:
515 keys = []
516 for i in range(112, 113):
517 keys.append(win32api.GetAsyncKeyState(i) & 1)
518 if any(keys):
519 write('Break from warmup-loop')
520 truth_table['test_for_warmup'] = False
521 truth_table['first_ocr'] = True
522 truth_table['first_push'] = True
523 break
524
525 if time.time() - time_table['warmup_test_timer'] >= cfg['warmup_test_interval']:
526 img = getScreenShot(hwnd, (1036, 425, 1525, 456)) # 'WAITING FOR PLAYERS X:XX'
527 img_text = Image_to_Text(img, img.size, (225, 225, 225), arg='--psm 6')
528 time_table['warmup_test_timer'] = time.time()
529 if img_text:
530 time_left = img_text.split()[-1].split(':')
531 # write(img_text, add_time=False)
532 try:
533 time_left = int(time_left[0]) * 60 + int(time_left[1])
534 if truth_table['first_ocr']:
535 join_warmup_time = time_left
536 time_table['screenshot_time'] = time.time()
537 truth_table['first_ocr'] = False
538
539 except (ValueError, IndexError):
540 continue
541
542 time_left_data = timedelta(seconds=int(time.time() - time_table['screenshot_time'])), time.strftime('%H:%M:%S', time.gmtime(abs((join_warmup_time - time_left) - (time.time() - time_table['screenshot_time'])))), img_text
543 write('Time since start: %s - Time Difference: %s - Time left: %s' % (time_left_data[0], time_left_data[1], time_left_data[2]), add_time=False, overwrite='1')
544 if no_text_found > 0:
545 no_text_found -= 1
546
547 if time_left <= push_times[push_counter]:
548 push_counter += 1
549 write('Time since start: %s\nTime Difference: %s\nTime left: %s' % (time_left_data[0], time_left_data[1], time_left_data[2]), push=push_urgency + 1, push_now=True, output=False)
550
551 if truth_table['first_push']:
552 if abs((join_warmup_time - time_left) - (time.time() - time_table['screenshot_time'])) >= 5:
553 truth_table['first_push'] = False
554 write('Match should start in ' + str(time_left) + ' seconds, All players have connected', push=push_urgency + 2, push_now=True)
555
556 else:
557 no_text_found += 1
558
559 if push_counter >= len(push_times):
560 push_counter = 0
561 no_text_found = 0
562 truth_table['test_for_warmup'] = False
563 truth_table['first_ocr'] = True
564 truth_table['first_push'] = True
565 write('Warmup should be over in less then %s seconds!' % push_times[-1], push=push_urgency + 2, push_now=True)
566 break
567
568 if no_text_found >= cfg['warmup_no_text_limit']:
569 push_counter = 0
570 no_text_found = 0
571 truth_table['test_for_warmup'] = False
572 truth_table['first_ocr'] = True
573 truth_table['first_push'] = True
574 write('Did not find any warmup text.', push=push_urgency + 2, push_now=True)
575 break
576if console_window['isatty']:
577 if last_printed_line.split(b'**')[-1] != b'\n':
578 print('')
579exit('ENDED BY USER')