-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathhelper.py
201 lines (156 loc) · 5.79 KB
/
helper.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
"""This module contains some common helper functions that the other
modules share.
"""
import os
import platform
import sys
import time
import json
if platform.system() == 'Windows':
import winreg
def load_launcher_json():
"""Loads the launcher.json settings file and creates one if it doesn't
exist.
:return: The settings from launcher.json using json.load().
"""
try:
if os.path.exists('login.json'):
os.rename('login.json', 'launcher.json')
launcher_json = os.path.join(get_launcher_path(), 'launcher.json')
with open(launcher_json, encoding='utf-8') as settings_file:
settings_data = json.load(settings_file)
fix_settings_data(settings_data)
except FileNotFoundError:
# Set a default TTR installation directory
try:
if platform.system() == 'Windows':
reg_key = (r'SOFTWARE\Microsoft\Windows\CurrentVersion'
r'\App Paths\Launcher.exe')
ttr_dir = winreg.QueryValue(winreg.HKEY_LOCAL_MACHINE, reg_key)
ttr_dir = ttr_dir.replace('Launcher.exe', '')
ttr_dir = ttr_dir.rstrip('/\\')
else:
ttr_dir = os.path.join(
get_launcher_path(), 'Toontown Rewritten')
except OSError:
ttr_dir = os.path.join(get_launcher_path(), 'Toontown Rewritten')
# Set default launcher.json content
json_data = {
"accounts": {
},
"launcher": {
"ttr-dir": ttr_dir,
"use-stored-accounts": True,
"display-logging": False
}
}
# Create launcher.json
update_launcher_json(json_data)
# File was created successfully, reload it
settings_data = load_launcher_json()
except json.decoder.JSONDecodeError as ex:
print(f'Badly formatted launcher.json file.\n{ex}')
print('\nIf unsure how to fix, delete the launcher.json file and '
'restart the launcher.')
quit_launcher()
except OSError as ex:
print(f'File IO Error.\n{ex}')
quit_launcher()
return settings_data
def update_launcher_json(settings_data):
"""Updates the launcher.json settings file with the settings_data object.
:param settings_data: The settings from launcher.json using json.load().
"""
# Open file and write json
try:
launcher_json = os.path.join(get_launcher_path(), 'launcher.json')
with open(launcher_json, 'w', encoding='utf-8') as settings_file:
json.dump(settings_data, settings_file, indent=4)
except OSError as ex:
print(f'Failed to write launcher.json.\n{ex}')
quit_launcher()
def fix_settings_data(settings_data):
"""Runs known fixes on settings_data.
Fixes applied:
- Run os.path.expandpath() on ttr-dir if path starts with a ~
:param settings_data: The settings from launcher.json using json.load().
"""
updated = False
ttr_dir = settings_data['launcher']['ttr-dir']
if ttr_dir[0] == '~':
updated = True
settings_data['launcher']['ttr-dir'] = os.path.expanduser(ttr_dir)
if updated:
update_launcher_json(settings_data)
def get_launcher_path():
"""Gets path to the running launcher's directory.
:return: The path to the launcher.
"""
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
launcher_path = os.path.dirname(sys.executable)
else:
launcher_path = os.path.dirname(os.path.abspath(__file__))
return launcher_path
def confirm(text, lower_bound, upper_bound):
"""Helper function for selecting a numerical choice from the end user.
:param text: The text to display in the input prompt.
:param lower_bound: The lowest possible numerical option.
:param upper_bound: The highest possible numerical option.
"""
while True:
try:
selection = int(input(text))
except ValueError:
print('Invalid choice. Try again.')
continue
else:
if selection < lower_bound or selection > upper_bound:
print('Invalid choice. Try again.')
continue
break
return selection
def quit_launcher(ret=0):
"""Nicely quit the launcher.
:param ret: The return value, defaults to 0.
"""
input('Press enter to quit.')
sys.exit(ret)
def retry(count, interval, callback, **kwargs):
"""Wrapper function to try executing a function a certain number of times
at an interval in seconds. To trigger a failed attempt the callback
must return a falsy value or raise an exception. None is not treated as
failure.
:param count: The amount of times to try executing a function.
:param interval: The amount of seconds to wait between each attempt.
:param callback: The callback function.
:param **kwargs: The arguments for the callback function.
:return: The result of the callback.
"""
exception = None
attempt = 0
while attempt < count:
try:
result = callback(**kwargs)
if result is None:
break
if not result:
if attempt < count:
print('Retrying...')
time.sleep(interval)
else:
break
except Exception as ex:
exception = ex
if attempt < count:
print('Retrying...')
time.sleep(interval)
attempt += 1
if exception:
raise exception
return result
def clear():
"""Clear the console"""
if sys.platform == 'win32':
os.system('cls')
else:
os.system('clear')