4
4
from rich .text import Text
5
5
6
6
# Downloader
7
+ from rich .progress import Progress
7
8
from requests .adapters import HTTPAdapter
8
9
from os import remove , system , startfile
9
10
from urllib .request import urlretrieve
10
11
from urllib .parse import urlparse
11
12
from requests import Session
12
- from tqdm import tqdm
13
13
14
14
# Opening web pages
15
15
from webbrowser import open as webopen
28
28
# Exiting from the program
29
29
from sys import exit
30
30
31
+ # Set Console object and version for the updater and UI
31
32
c = Console ()
33
+ VERSION = "4.2"
32
34
33
- VERSION = "4.1"
35
+ ###### HELPER FUNCTIONS
34
36
35
- # Write and start (or not) a file
36
37
def fWrite (run , filename , content ):
38
+ """Write a file
39
+
40
+ Args:
41
+ run (int): Controls if the file will be ran
42
+ filename (str): File name
43
+ content (str): Content of the file
44
+ """
37
45
fp = open (filename , 'w' )
38
46
fp .write (content )
39
47
fp .close ()
40
48
if run == 1 : startfile (filename )
41
49
42
- # Run a command as powershell
43
- def runAsPowershell (command , filename ):
44
- fWrite (1 , f"{ filename } .bat" , r'@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "' + command + '"' )
45
-
46
50
# Clear the display
47
51
def cls ():
48
52
system ('cls' )
49
53
50
- # Print text in a color
51
- def cl (color , text ):
52
- if color == 1 :
53
- return (f'[red]{ text } [/red]' )
54
- elif color == 2 :
54
+ # Color helpers and shi
55
+ class cl ():
56
+ def yellow (text ):
55
57
return (f'[yellow]{ text } [/yellow]' )
56
- else :
57
- return (f'[green]{ text } [/green]' )
58
58
59
- # Printing helper
60
59
class Printer ():
61
- def sys (clr , text ):
62
- if clr == 1 :
63
- c .print (f'[green][✓] { text } [/green]' )
64
- elif clr == 2 :
65
- c .print (f'[yellow][?] { text } [/yellow]' )
66
- else :
67
- c .print (f'[red][✗] { text } [/red]' )
60
+ def green (text ):
61
+ c .print (f'[green][✓] { text } [/green]' )
62
+ def yellow (text ):
63
+ c .print (f'[yellow][?] { text } [/yellow]' )
64
+ def red (text ):
65
+ c .print (f'[red][✗] { text } [/red]' )
68
66
def zpr (text ):
69
67
c .print (f'[blue][>] { text } [/blue]' )
70
68
71
- # Very cool and good looking downloader
72
- def download (url , fnam , name ):
73
- try : # noice
74
- if name == None :
69
+ def download (url : str , fnam : str , name : str ):
70
+ """Downloads a file with progress tracking
71
+
72
+ Args:
73
+ url (string): URL of the file to download
74
+ fnam (string): Filename for the outputted file
75
+ name (string): Name to show during download
76
+ """
77
+ try :
78
+ # None handler (null safety in Python)
79
+ if name is None :
75
80
name = fnam
76
81
77
- # Parse the URL and convert it to https.
82
+ # Force the URL to use HTTPS
78
83
url = (urlparse (url ))._replace (scheme = 'https' ).geturl ()
79
- # nice
84
+
85
+ # Add HTTPAdapter settings to increase download speed
80
86
adapter = HTTPAdapter (max_retries = 3 ,
81
- pool_connections = 20 ,
82
- pool_maxsize = 10 )
87
+ pool_connections = 20 ,
88
+ pool_maxsize = 10 )
83
89
84
90
# Add headers to bypass simple robots.txt blocking
85
91
headers = {'Accept-Encoding' : 'gzip, deflate' ,
86
- 'User-Agent' : 'Mozilla/5.0' ,
87
- 'cache_control ' : 'max-age=600' ,
88
- 'connection ' : 'keep-alive' }
92
+ 'User-Agent' : 'Mozilla/5.0' ,
93
+ 'Cache-Control ' : 'max-age=600' ,
94
+ 'Connection ' : 'keep-alive' }
89
95
90
- # Create a session and make a head request using it
96
+ # Create a new Session object
91
97
session = Session ()
92
98
93
- # Mount the HTTP adapter to the session.
99
+ # Force the URL to use HTTPS and HTTPAdapter options
94
100
session .mount ('https://' , adapter )
95
101
102
+ # Make a head request and get the filesize
96
103
response = session .head (url , headers = headers )
97
-
98
- # Get the total size of the file
99
104
total_size = int (response .headers .get ("content-length" , 0 ))
100
105
106
+ # Actually get the file contents
101
107
r = session .get (url , stream = True , headers = headers )
102
108
103
- progress_bar = tqdm (total = total_size , unit = 'iB' , unit_scale = True , bar_format = '{desc}: {percentage:3.0f}% │ {bar} │ {n_fmt} / {total_fmt} ║ {elapsed} ─ {remaining} │ {rate_fmt}' )
109
+ # Init the progress tracking task and give it an ID
110
+ progress = Progress ()
104
111
105
- with open ( fnam , 'wb' ) as file :
106
- for data in r . iter_content ( 4096 ) :
107
- progress_bar . update ( len ( data ) )
108
- file . write ( data )
109
-
110
- # Close the progress bar and print a message when the download is complete.
111
- progress_bar . close ( )
112
+ # Open the file and write content to it + update the progress bar
113
+ with progress :
114
+ task_id = progress . add_task ( f"[light blue]Downloading { name } ..." , total = total_size )
115
+ with open ( fnam , 'wb' ) as file :
116
+ for data in r . iter_content ( 1024 ):
117
+ file . write ( data )
118
+ progress . update ( task_id , advance = len ( data ) )
112
119
113
120
except KeyboardInterrupt :
114
- progress_bar . close ()
115
- Printer .sys ( 0 , 'Aborting!' )
121
+ # Just remove the file if the download gets cancelled
122
+ Printer .red ( 'Aborting!' )
116
123
remove (fnam )
117
124
118
125
def updater ():
119
- up = latest ("xemulat/XToolBox" )
120
- if VERSION < str (up ):
121
- Printer .zpr (f'New version available: { up } , do you want to update?' )
122
- if yn ():
123
- download ('https://github.com/xemulat/XToolBox/releases/latest/download/XTBox.exe' , f'XTBox.{ up } .exe' , 'XToolBox Update' )
124
- Printer .sys (1 , 'Done!' )
125
- exit (startfile (f'XTBox.{ up } .exe' ))
126
+ """Check for updates
127
+ """
128
+ try :
129
+ up = latest ("nyxiereal/XToolBox" )
130
+ if VERSION < str (up ):
131
+ Printer .zpr (f'New version available: { up } , do you want to update?' )
132
+ if yn ():
133
+ download ('https://github.com/nyxiereal/XToolBox/releases/latest/download/XTBox.exe' , f'XTBox.{ up } .exe' , 'XToolBox Update' )
134
+ Printer .green ('Done!' )
135
+ exit (startfile (f'XTBox.{ up } .exe' ))
136
+ except :
137
+ Printer .green ('Done!' )
126
138
127
139
# function to reduce code when using interpreter() page 97
128
140
def yn (prompt = "" ):
141
+ """Simple yes/no prompt
142
+
143
+ Args:
144
+ prompt (str, optional): Anything you want to display. Defaults to "".
145
+
146
+ Returns:
147
+ bool: Return True or False.
148
+ """
129
149
prompt += f"([green]Y[/green]/[red]n[/red]): "
130
150
goodInput , YNvalue = False , False
131
151
while not goodInput :
@@ -187,6 +207,13 @@ def multiChoose(tool, prompt):
187
207
return index
188
208
189
209
def dl (url , urlr , name ):
210
+ """Helper to download files
211
+
212
+ Args:
213
+ url (str): URL to the file
214
+ urlr (str): File name
215
+ name (str): Name
216
+ """
190
217
# Before downloading files, check if the url contains a version-code
191
218
if '%UBUNTUVERSION%' in url :
192
219
url = url .replace ('%UBUNTUVERSION%' , iScrape .ubuntu ())
@@ -223,20 +250,18 @@ def dl(url, urlr, name):
223
250
if yn (f"Run { urlr } ?" ):
224
251
startfile (urlr )
225
252
except :
226
- Printer .sys ( 0 , "ERROR 3: Can't download file from the server..." )
253
+ Printer .red ( "ERROR 3: Can't download file from the server..." )
227
254
228
255
getpass ("\n ... press ENTER to continue ..." , stream = None )
229
256
pageDisplay (last )
230
257
231
- # runAsPowershell() wrapper
258
+ # Nyaboom dirty fix
232
259
def pwsh (cmd , name ):
233
260
c .print (f"XTBox will run the following command as powershell:\n \t { cmd } " )
234
261
if not yn ("Approve?" ): return
235
- runAsPowershell (cmd , name )
236
-
237
- ###### random stuff
238
- cls ()
262
+ system (cmd )
239
263
264
+ # If it ain't broke, don't fix it!
240
265
def checkforlinks (inp ):
241
266
if r'%GHOSTSPECTRE%' in inp :
242
267
return (iScrape .ghostSpectre ())
@@ -273,7 +298,7 @@ def helpe():
273
298
f"│ 99 │ Exit │\n "
274
299
f"├───────────────────────────────────────────────────────┤\n "
275
300
f"│ Color │ Meaning │\n "
276
- f"│ { cl ( 2 , 'YELLOW' )} │ Advanced Option │\n "
301
+ f"│ { cl . yellow ( 'YELLOW' )} │ Advanced Option │\n "
277
302
f"├───────────────────────────────────────────────────────┤\n "
278
303
f"│ Error │ Explanation │\n "
279
304
f"│ 1 │ File already exists │\n "
@@ -296,25 +321,6 @@ def interpreter(page, prompt="> "):
296
321
# if user inputs 99, exit the program
297
322
if choose == "99" :
298
323
exit ()
299
-
300
- if choose == "peggle" :
301
- download ('http://xemu.top/files/peggle.7z' , 'peggle.7z' , 'Peggle Deluxe' )
302
-
303
- if choose == "fast" :
304
- cls ()
305
- c .print (" .-;':':'-." )
306
- c .print (" {'.'.'.'.'.}" )
307
- c .print (" ) '`." )
308
- c .print (" '-. ._ ,_.-='" )
309
- c .print (" `). ( `);(" )
310
- c .print (" ('. .)(,'.)" )
311
- c .print (" ) ( ,').(" )
312
- c .print (" ( .').'(')." )
313
- c .print (" .) (' ).('" )
314
- c .print (" ' ) ( )." )
315
- c .print (" .'( .)'" )
316
- c .print (" .).'" )
317
- input ('jelelfisg' )
318
324
319
325
# if user inputs h, open help
320
326
if choose == "h" and page != 0 :
@@ -416,8 +422,9 @@ def pageDisplay(page):
416
422
global last , welcome
417
423
last = page
418
424
cls ()
425
+ # Show the predefined "quote" only the first time the program is ran.
419
426
if welcome == 0 :
420
- table = Table (title = f"XToolBox | v{ VERSION } , Made by Xemulated ." , show_footer = True )
427
+ table = Table (title = f"XToolBox | v{ VERSION } , Made by Nyxie ." , show_footer = True )
421
428
welcome = 1
422
429
else :
423
430
table = Table (title = f"XToolBox | { chooseQuotes ()} " , show_footer = True )
@@ -435,11 +442,12 @@ def pageDisplay(page):
435
442
interpreter (page )
436
443
437
444
# init
445
+ cls ()
438
446
updater ()
439
447
welcome = 0
440
448
while True :
441
449
try :
442
450
pageDisplay (1 )
443
- except KeyboardInterrupt : # NICE
451
+ except KeyboardInterrupt :
444
452
print ('bye!' )
445
453
exit ()
0 commit comments