44from rich .text import Text
55
66# Downloader
7+ from rich .progress import Progress
78from requests .adapters import HTTPAdapter
89from os import remove , system , startfile
910from urllib .request import urlretrieve
1011from urllib .parse import urlparse
1112from requests import Session
12- from tqdm import tqdm
1313
1414# Opening web pages
1515from webbrowser import open as webopen
2828# Exiting from the program
2929from sys import exit
3030
31+ # Set Console object and version for the updater and UI
3132c = Console ()
33+ VERSION = "4.2"
3234
33- VERSION = "4.1"
35+ ###### HELPER FUNCTIONS
3436
35- # Write and start (or not) a file
3637def 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+ """
3745 fp = open (filename , 'w' )
3846 fp .write (content )
3947 fp .close ()
4048 if run == 1 : startfile (filename )
4149
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-
4650# Clear the display
4751def cls ():
4852 system ('cls' )
4953
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 ):
5557 return (f'[yellow]{ text } [/yellow]' )
56- else :
57- return (f'[green]{ text } [/green]' )
5858
59- # Printing helper
6059class 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]' )
6866 def zpr (text ):
6967 c .print (f'[blue][>] { text } [/blue]' )
7068
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 :
7580 name = fnam
7681
77- # Parse the URL and convert it to https.
82+ # Force the URL to use HTTPS
7883 url = (urlparse (url ))._replace (scheme = 'https' ).geturl ()
79- # nice
84+
85+ # Add HTTPAdapter settings to increase download speed
8086 adapter = HTTPAdapter (max_retries = 3 ,
81- pool_connections = 20 ,
82- pool_maxsize = 10 )
87+ pool_connections = 20 ,
88+ pool_maxsize = 10 )
8389
8490 # Add headers to bypass simple robots.txt blocking
8591 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' }
8995
90- # Create a session and make a head request using it
96+ # Create a new Session object
9197 session = Session ()
9298
93- # Mount the HTTP adapter to the session.
99+ # Force the URL to use HTTPS and HTTPAdapter options
94100 session .mount ('https://' , adapter )
95101
102+ # Make a head request and get the filesize
96103 response = session .head (url , headers = headers )
97-
98- # Get the total size of the file
99104 total_size = int (response .headers .get ("content-length" , 0 ))
100105
106+ # Actually get the file contents
101107 r = session .get (url , stream = True , headers = headers )
102108
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 ()
104111
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 ) )
112119
113120 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!' )
116123 remove (fnam )
117124
118125def 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!' )
126138
127139# function to reduce code when using interpreter() page 97
128140def 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+ """
129149 prompt += f"([green]Y[/green]/[red]n[/red]): "
130150 goodInput , YNvalue = False , False
131151 while not goodInput :
@@ -187,6 +207,13 @@ def multiChoose(tool, prompt):
187207 return index
188208
189209def 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+ """
190217 # Before downloading files, check if the url contains a version-code
191218 if '%UBUNTUVERSION%' in url :
192219 url = url .replace ('%UBUNTUVERSION%' , iScrape .ubuntu ())
@@ -223,20 +250,18 @@ def dl(url, urlr, name):
223250 if yn (f"Run { urlr } ?" ):
224251 startfile (urlr )
225252 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..." )
227254
228255 getpass ("\n ... press ENTER to continue ..." , stream = None )
229256 pageDisplay (last )
230257
231- # runAsPowershell() wrapper
258+ # Nyaboom dirty fix
232259def pwsh (cmd , name ):
233260 c .print (f"XTBox will run the following command as powershell:\n \t { cmd } " )
234261 if not yn ("Approve?" ): return
235- runAsPowershell (cmd , name )
236-
237- ###### random stuff
238- cls ()
262+ system (cmd )
239263
264+ # If it ain't broke, don't fix it!
240265def checkforlinks (inp ):
241266 if r'%GHOSTSPECTRE%' in inp :
242267 return (iScrape .ghostSpectre ())
@@ -273,7 +298,7 @@ def helpe():
273298 f"│ 99 │ Exit │\n "
274299 f"├───────────────────────────────────────────────────────┤\n "
275300 f"│ Color │ Meaning │\n "
276- f"│ { cl ( 2 , 'YELLOW' )} │ Advanced Option │\n "
301+ f"│ { cl . yellow ( 'YELLOW' )} │ Advanced Option │\n "
277302 f"├───────────────────────────────────────────────────────┤\n "
278303 f"│ Error │ Explanation │\n "
279304 f"│ 1 │ File already exists │\n "
@@ -296,25 +321,6 @@ def interpreter(page, prompt="> "):
296321 # if user inputs 99, exit the program
297322 if choose == "99" :
298323 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' )
318324
319325 # if user inputs h, open help
320326 if choose == "h" and page != 0 :
@@ -416,8 +422,9 @@ def pageDisplay(page):
416422 global last , welcome
417423 last = page
418424 cls ()
425+ # Show the predefined "quote" only the first time the program is ran.
419426 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 )
421428 welcome = 1
422429 else :
423430 table = Table (title = f"XToolBox | { chooseQuotes ()} " , show_footer = True )
@@ -435,11 +442,12 @@ def pageDisplay(page):
435442 interpreter (page )
436443
437444# init
445+ cls ()
438446updater ()
439447welcome = 0
440448while True :
441449 try :
442450 pageDisplay (1 )
443- except KeyboardInterrupt : # NICE
451+ except KeyboardInterrupt :
444452 print ('bye!' )
445453 exit ()
0 commit comments