-
Notifications
You must be signed in to change notification settings - Fork 0
/
dolphindownloader.py
159 lines (131 loc) · 5.61 KB
/
dolphindownloader.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
"""
dolphindownloader v3
A tool which downloads a specified (or the lastest) build of Dolphin Emulator.
"""
import argparse
import os
import re
import shutil
import subprocess
import sys
import requests
from bs4 import BeautifulSoup
class DolphinDownloader():
"""A tool which downloads a specified (or the lastest) build of Dolphin Emulator."""
def __init__(self):
self.link = ""
self.filename = ""
self.build = ""
self.buildname = ""
def getlatestbuild(self):
"""Gets download link and filename of the lastest build of Dolphin."""
print("Checking latest Dolphin build...")
try:
page = requests.get('https://dolphin-emu.org/download')
page.raise_for_status()
except requests.exceptions.RequestException:
print("Failed to connect. Check your internet connection.")
sys.exit(1)
parsed = BeautifulSoup(page.text, "html.parser")
link = parsed.find('a', attrs={'class':"btn always-ltr btn-info win"})['href']
self.link = link
self.filename = os.path.basename(self.link)
self.build = re.findall(r"dolphin-master-(.*)-x64.7z", self.link).pop()
self.buildname = "Dolphin_" + self.build
print("Most recent build is {}.".format(self.build))
def getbuild(self, build):
"""Gets download link and filename of a specified build of Dolphin Emulator."""
self.link = "https://dl.dolphin-emu.org/builds/dolphin-master-{}-x64.7z".format(build)
self.filename = os.path.basename(self.link)
self.build = build
self.buildname = "Dolphin_" + self.build
print("Attempting to download build {}...".format(self.build))
def download(self):
"""Downloads a build of Dolphin."""
link = self.link
filename = self.filename
#check if the build exists
try:
response = requests.get(link, stream=True)
response.raise_for_status()
except requests.exceptions.HTTPError as error:
print(error)
print("That build probably doesn't exist.")
sys.exit(1)
with open(filename, "wb") as archive:
print('Downloading {}...'.format(filename))
total = response.headers.get('content-length')
downloaded = 0
total = int(total)/1024/1024 # in MB
for data in response.iter_content(chunk_size=4096):
downloaded += len(data)/1024/1024 # in MB
archive.write(data)
percent = str(int(100 * downloaded / total)).rjust(3)
percentbar = '[{}]'.format(('=' * int(int(percent)/2)).ljust(50))
progress = f'\r{percent}% {percentbar} {downloaded:.2f}MB/{total:.2f}MB'
sys.stdout.write(progress)
sys.stdout.flush()
print() # to add a newline
def extract(self):
"""Extracts Dolphin .7z archive."""
cmd = ['7za', 'x', '-y', self.filename]
if not os.path.isfile("7za.exe"):
raise FileNotFoundError("Cannot find '7za.exe'.")
print("Extracting {}...".format(self.filename))
process = subprocess.Popen(cmd, stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
process.communicate()
def cleanup(self):
"""Removes unnecessary files."""
os.remove(self.filename)
if os.path.isdir(self.buildname):
shutil.rmtree(self.buildname)
os.rename("Dolphin-x64", self.buildname)
def deleteoldbuilds(self):
"""Deletes old builds."""
print("Deleting old builds...")
for folder in os.listdir():
if folder != self.buildname and folder.startswith("Dolphin_"):
shutil.rmtree(folder)
def run(self):
"""Runs Dolphin."""
subprocess.Popen(os.path.join(self.buildname, "Dolphin.exe"))
def validbuild(build):
"""Check if build inputted is valid."""
regex = re.compile(r'^\d\.(0|5)-\d{1,4}$')
if not regex.match(build):
raise argparse.ArgumentTypeError("Invalid build format. Try something like 5.0-4839.")
return build
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Downloads a (or the lastest) build of Dolphin.')
parser.add_argument("-q", "--quiet", action="store_true", help="disables commandline output")
parser.add_argument("-r", "--run", action="store_true", help="run Dolphin after downloading")
parser.add_argument("-b", "--build", type=validbuild, help="specify build version to download")
parser.add_argument("-d", "--deleteoldbuilds", action="store_true", help="delete old builds")
args = parser.parse_args()
if args.quiet:
sys.stdout = open(os.devnull, 'w')
dolphindownloader = DolphinDownloader()
print("Dolphin Downloader v3")
if args.build:
dolphindownloader.getbuild(args.build)
else:
dolphindownloader.getlatestbuild()
buildfile = os.path.join(dolphindownloader.buildname, ".build")
if os.path.isfile(buildfile):
with open(buildfile, "r") as text:
if text.readline() >= dolphindownloader.build:
print("Dolphin is up to date!")
if args.run:
dolphindownloader.run()
if args.deleteoldbuilds:
dolphindownloader.deleteoldbuilds()
sys.exit(0)
dolphindownloader.download()
dolphindownloader.extract()
dolphindownloader.cleanup()
with open(buildfile, "w") as file:
file.write(dolphindownloader.build)
if args.run:
dolphindownloader.run()
if args.deleteoldbuilds:
dolphindownloader.deleteoldbuilds()