forked from Shinonome/althea
fixed saved credentials not working, fixed anisette-server-provision not launching on start, small recode
This commit is contained in:
@@ -39,14 +39,8 @@ computer_cpu_platform = platform.machine()
|
|||||||
|
|
||||||
def resource_path(relative_path):
|
def resource_path(relative_path):
|
||||||
global installedcheck
|
global installedcheck
|
||||||
CheckRun10 = subprocess.run(
|
installedcheck = subprocess.run("test -e /usr/lib/althea/althea", shell=True).returncode == 0
|
||||||
f"find /usr/lib/althea/althea > /dev/null 2>&1", shell=True
|
base_path = "/usr/lib/althea" if installedcheck else os.path.abspath(".")
|
||||||
)
|
|
||||||
if CheckRun10.returncode == 0:
|
|
||||||
installedcheck = True
|
|
||||||
base_path = "/usr/lib/althea"
|
|
||||||
else:
|
|
||||||
base_path = os.path.abspath(".")
|
|
||||||
return os.path.join(base_path, relative_path)
|
return os.path.join(base_path, relative_path)
|
||||||
|
|
||||||
|
|
||||||
@@ -88,44 +82,29 @@ def connectioncheck():
|
|||||||
def menu():
|
def menu():
|
||||||
menu = Gtk.Menu()
|
menu = Gtk.Menu()
|
||||||
|
|
||||||
if (notify()) == True:
|
if notify():
|
||||||
command_upd = Gtk.MenuItem(label="Download Update")
|
command_upd = Gtk.MenuItem(label="Download Update")
|
||||||
command_upd.connect("activate", showurl)
|
command_upd.connect("activate", showurl)
|
||||||
menu.append(command_upd)
|
menu.append(command_upd)
|
||||||
|
|
||||||
menu.append(Gtk.SeparatorMenuItem())
|
menu.append(Gtk.SeparatorMenuItem())
|
||||||
|
|
||||||
command_one = Gtk.MenuItem(label="About althea")
|
commands = [
|
||||||
command_one.connect("activate", on_abtdlg)
|
("About althea", on_abtdlg),
|
||||||
menu.append(command_one)
|
("Install AltStore", altstoreinstall),
|
||||||
|
("Install an IPA file", altserverfile),
|
||||||
|
("Pair", lambda x: openwindow(PairWindow)),
|
||||||
|
("Restart AltServer", restartaltserver)
|
||||||
|
]
|
||||||
|
|
||||||
menu.append(Gtk.SeparatorMenuItem())
|
for label, callback in commands:
|
||||||
|
command = Gtk.MenuItem(label=label)
|
||||||
|
command.connect("activate", callback)
|
||||||
|
menu.append(command)
|
||||||
|
menu.append(Gtk.SeparatorMenuItem())
|
||||||
|
|
||||||
command_two = Gtk.MenuItem(label="Install AltStore")
|
if subprocess.run("test -e /usr/lib/althea/althea", shell=True).returncode == 0:
|
||||||
command_two.connect("activate", altstoreinstall)
|
|
||||||
menu.append(command_two)
|
|
||||||
|
|
||||||
command_three = Gtk.MenuItem(label="Install an IPA file")
|
|
||||||
command_three.connect("activate", altserverfile)
|
|
||||||
menu.append(command_three)
|
|
||||||
|
|
||||||
command_four = Gtk.MenuItem(label="Pair")
|
|
||||||
command_four.connect("activate", lambda x: openwindow(PairWindow))
|
|
||||||
menu.append(command_four)
|
|
||||||
|
|
||||||
command_five = Gtk.MenuItem(label="Restart AltServer")
|
|
||||||
command_five.connect("activate", restartaltserver)
|
|
||||||
menu.append(command_five)
|
|
||||||
|
|
||||||
menu.append(Gtk.SeparatorMenuItem())
|
|
||||||
|
|
||||||
CheckRun11 = subprocess.run(f"test -e /usr/lib/althea/althea", shell=True)
|
|
||||||
if CheckRun11.returncode == 0:
|
|
||||||
global command_six
|
global command_six
|
||||||
CheckRun12 = subprocess.run(
|
if subprocess.run("test -e $HOME/.config/autostart/althea.desktop", shell=True).returncode == 0:
|
||||||
f"test -e $HOME/.config/autostart/althea.desktop", shell=True
|
|
||||||
)
|
|
||||||
if CheckRun12.returncode == 0:
|
|
||||||
command_six.set_active(command_six)
|
command_six.set_active(command_six)
|
||||||
command_six.connect("activate", launchatlogin1)
|
command_six.connect("activate", launchatlogin1)
|
||||||
menu.append(command_six)
|
menu.append(command_six)
|
||||||
@@ -230,25 +209,27 @@ def openwindow(window):
|
|||||||
w = window()
|
w = window()
|
||||||
w.show_all()
|
w.show_all()
|
||||||
|
|
||||||
|
def kill_processes():
|
||||||
|
for process in [AltServer, AnisetteServer]:
|
||||||
|
subprocess.run(["killall", process], check=False)
|
||||||
|
|
||||||
def quitit():
|
def quitit():
|
||||||
subprocess.run(f"killall {AltServer}", shell=True)
|
kill_processes()
|
||||||
subprocess.run(f"killall {AnisetteServer}", shell=True)
|
|
||||||
Gtk.main_quit()
|
Gtk.main_quit()
|
||||||
os.kill(os.getpid(), signal.SIGKILL)
|
os.kill(os.getpid(), signal.SIGKILL)
|
||||||
|
|
||||||
def restartaltserver(_):
|
def restartaltserver(_):
|
||||||
subprocess.run(f"killall {AltServer}", shell=True)
|
kill_processes()
|
||||||
subprocess.run(f"killall {AnisetteServer}", shell=True)
|
subprocess.run("idevicepair pair", shell=True, check=False)
|
||||||
subprocess.run("idevicepair pair", shell=True)
|
subprocess.Popen(
|
||||||
subprocess.run(
|
f"{altheapath}/AltServer",
|
||||||
f"""export ALTSERVER_ANISETTE_SERVER='http://127.0.0.1:6969' ; {(altheapath)}/AltServer &""",
|
env=dict(os.environ, ALTSERVER_ANISETTE_SERVER='http://127.0.0.1:6969'),
|
||||||
shell=True,
|
shell=True
|
||||||
)
|
)
|
||||||
|
|
||||||
def winerm():
|
def winerm():
|
||||||
silent_remove(f"{(altheapath)}/log.txt")
|
silent_remove(f"{altheapath}/log.txt")
|
||||||
dialog = Gtk.MessageDialog(
|
dialog = Gtk.MessageDialog(
|
||||||
# transient_for=self,
|
|
||||||
flags=0,
|
flags=0,
|
||||||
message_type=Gtk.MessageType.QUESTION,
|
message_type=Gtk.MessageType.QUESTION,
|
||||||
buttons=Gtk.ButtonsType.YES_NO,
|
buttons=Gtk.ButtonsType.YES_NO,
|
||||||
@@ -256,95 +237,71 @@ def winerm():
|
|||||||
)
|
)
|
||||||
dialog.format_secondary_text("Your login and password have been saved earlier.")
|
dialog.format_secondary_text("Your login and password have been saved earlier.")
|
||||||
response = dialog.run()
|
response = dialog.run()
|
||||||
|
|
||||||
if response == Gtk.ResponseType.YES:
|
if response == Gtk.ResponseType.YES:
|
||||||
global apple_id
|
|
||||||
global password
|
|
||||||
try:
|
try:
|
||||||
with open(f"{(altheapath)}/saved.txt", "r") as f:
|
with open(f"{altheapath}/saved.txt", "r") as f:
|
||||||
for line in f:
|
for line in f:
|
||||||
if 'ł' in line:
|
if 'ł' in line:
|
||||||
|
global apple_id, password, savedcheck
|
||||||
apple_id, password = line.split("ł")
|
apple_id, password = line.split("ł")
|
||||||
|
savedcheck = True
|
||||||
|
Login().on_click_me_clicked1()
|
||||||
break
|
break
|
||||||
else:
|
except (ValueError, FileNotFoundError) as e:
|
||||||
print("Invalid line format:", line)
|
print(f"Error: {e}")
|
||||||
continue
|
|
||||||
print(apple_id, password)
|
|
||||||
global savedcheck
|
|
||||||
savedcheck = True
|
|
||||||
Login().on_click_me_clicked1()
|
|
||||||
except ValueError as e:
|
|
||||||
print("Error reading credentials:", e)
|
|
||||||
except FileNotFoundError as e:
|
|
||||||
print("File not found:", e)
|
|
||||||
else:
|
else:
|
||||||
silent_remove(f"{(altheapath)}/saved.txt")
|
silent_remove(f"{altheapath}/saved.txt")
|
||||||
win3 = Login()
|
Login().show_all()
|
||||||
win3.show_all()
|
|
||||||
dialog.destroy()
|
dialog.destroy()
|
||||||
|
|
||||||
def win1():
|
def win1():
|
||||||
if os.path.isfile(f"{(altheapath)}/saved.txt"):
|
winerm() if os.path.isfile(f"{altheapath}/saved.txt") else openwindow(Login)
|
||||||
winerm()
|
|
||||||
else:
|
|
||||||
openwindow(Login)
|
|
||||||
|
|
||||||
def win2(_):
|
def win2(_):
|
||||||
if os.path.isfile(f"{(altheapath)}/saved.txt"):
|
win1()
|
||||||
winerm()
|
|
||||||
else:
|
|
||||||
openwindow(Login)
|
|
||||||
|
|
||||||
def actionCallback(notification, action, user_data=None):
|
def actionCallback(notification, action, user_data=None):
|
||||||
Gtk.show_uri_on_window(
|
Gtk.show_uri_on_window(None, "https://github.com/vyvir/althea/releases", Gdk.CURRENT_TIME)
|
||||||
None, "https://github.com/vyvir/althea/releases", Gdk.CURRENT_TIME
|
|
||||||
)
|
|
||||||
quitit()
|
quitit()
|
||||||
|
|
||||||
def launchatlogin1(_):
|
def launchatlogin1(_):
|
||||||
global command_six
|
|
||||||
if command_six.get_active():
|
if command_six.get_active():
|
||||||
global AutoStart
|
|
||||||
os.popen(AutoStart).read()
|
os.popen(AutoStart).read()
|
||||||
return True
|
return True
|
||||||
else:
|
silent_remove("$HOME/.config/autostart/althea.desktop")
|
||||||
silent_remove("$HOME/.config/autostart/althea.desktop")
|
return False
|
||||||
return False
|
|
||||||
|
|
||||||
def silent_remove(filename):
|
def silent_remove(filename):
|
||||||
try:
|
try:
|
||||||
os.remove(filename)
|
os.remove(filename)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.errno != errno.ENOENT: # errno.ENOENT = no such file or directory
|
if e.errno != errno.ENOENT:
|
||||||
raise # re-raise exception if a different error occurred
|
raise
|
||||||
|
|
||||||
def altstore_download(value):
|
def altstore_download(value):
|
||||||
# setting the base URL value
|
|
||||||
baseUrl = "https://cdn.altstore.io/file/altstore/apps.json"
|
baseUrl = "https://cdn.altstore.io/file/altstore/apps.json"
|
||||||
|
response = requests.get(baseUrl)
|
||||||
|
|
||||||
# retrieving data from JSON Data
|
if response.status_code == 200:
|
||||||
json_data = requests.get(baseUrl)
|
data = response.json()
|
||||||
if json_data.status_code == 200:
|
|
||||||
data = json_data.json()
|
|
||||||
for app in data['apps']:
|
for app in data['apps']:
|
||||||
if app['name'] == "AltStore":
|
if app['name'] == "AltStore":
|
||||||
if value == "Check":
|
if value == "Check":
|
||||||
size = app['versions'][0]['size']
|
size = app['versions'][0]['size']
|
||||||
return size == os.path.getsize(f'{(altheapath)}/AltStore.ipa')
|
return size == os.path.getsize(f'{altheapath}/AltStore.ipa')
|
||||||
break
|
elif value == "Download":
|
||||||
if value == "Download":
|
|
||||||
latest = app['versions'][0]['downloadURL']
|
latest = app['versions'][0]['downloadURL']
|
||||||
r = requests.get(
|
r = requests.get(latest, allow_redirects=True)
|
||||||
latest,
|
|
||||||
allow_redirects=True,
|
|
||||||
)
|
|
||||||
latest_filename = latest.split('/')[-1]
|
latest_filename = latest.split('/')[-1]
|
||||||
open(f"{(altheapath)}/{(latest_filename)}", "wb").write(r.content)
|
with open(f"{altheapath}/{latest_filename}", "wb") as f:
|
||||||
os.rename(f"{(altheapath)}/{(latest_filename)}", f"{(altheapath)}/AltStore.ipa")
|
f.write(r.content)
|
||||||
subprocess.run(f"chmod 755 {(altheapath)}/AltStore.ipa", shell=True)
|
os.rename(f"{altheapath}/{latest_filename}", f"{altheapath}/AltStore.ipa")
|
||||||
break
|
subprocess.run(["chmod", "755", f"{altheapath}/AltStore.ipa"])
|
||||||
return True
|
return True
|
||||||
else:
|
return False
|
||||||
return False
|
|
||||||
|
|
||||||
def ios_version():
|
def ios_version():
|
||||||
silent_remove(f"{(altheapath)}/ideviceinfo.txt")
|
silent_remove(f"{(altheapath)}/ideviceinfo.txt")
|
||||||
@@ -367,227 +324,221 @@ def ios_version():
|
|||||||
class SplashScreen(Handy.Window):
|
class SplashScreen(Handy.Window):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__(title="Loading")
|
super().__init__(title="Loading")
|
||||||
|
self.setup_window()
|
||||||
|
self.create_ui()
|
||||||
|
self.start_startup_process()
|
||||||
|
|
||||||
|
def setup_window(self):
|
||||||
self.set_resizable(False)
|
self.set_resizable(False)
|
||||||
self.set_default_size(512, 288)
|
self.set_default_size(512, 288)
|
||||||
self.present()
|
self.present()
|
||||||
self.set_position(Gtk.WindowPosition.CENTER_ALWAYS)
|
self.set_position(Gtk.WindowPosition.CENTER_ALWAYS)
|
||||||
self.set_keep_above(True)
|
self.set_keep_above(True)
|
||||||
|
|
||||||
self.mainBox = Gtk.Box(
|
def create_ui(self):
|
||||||
spacing=6,
|
self.mainBox = Gtk.Box(spacing=6, orientation=Gtk.Orientation.VERTICAL)
|
||||||
orientation=Gtk.Orientation.VERTICAL,
|
|
||||||
halign=Gtk.Align.START,
|
|
||||||
valign=Gtk.Align.START,
|
|
||||||
)
|
|
||||||
self.add(self.mainBox)
|
self.add(self.mainBox)
|
||||||
|
|
||||||
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
|
image = self.create_image()
|
||||||
filename=os.path.join("resources/4.png"),
|
|
||||||
width=512,
|
|
||||||
height=288,
|
|
||||||
preserve_aspect_ratio=False,
|
|
||||||
)
|
|
||||||
image = Gtk.Image.new_from_pixbuf(pixbuf)
|
|
||||||
image.show()
|
|
||||||
self.mainBox.pack_start(image, False, True, 0)
|
self.mainBox.pack_start(image, False, True, 0)
|
||||||
|
|
||||||
self.lbl1 = Gtk.Label(label="Starting althea...")
|
self.lbl1 = Gtk.Label(label="Starting althea...")
|
||||||
self.mainBox.pack_start(self.lbl1, False, False, 6)
|
self.mainBox.pack_start(self.lbl1, False, False, 6)
|
||||||
|
|
||||||
self.loadalthea = Gtk.ProgressBar()
|
self.loadalthea = Gtk.ProgressBar()
|
||||||
self.mainBox.pack_start(self.loadalthea, True, True, 0)
|
self.mainBox.pack_start(self.loadalthea, True, True, 0)
|
||||||
|
|
||||||
|
def create_image(self):
|
||||||
|
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
|
||||||
|
filename=os.path.join("resources/4.png"),
|
||||||
|
width=512, height=288, preserve_aspect_ratio=False
|
||||||
|
)
|
||||||
|
image = Gtk.Image.new_from_pixbuf(pixbuf)
|
||||||
|
image.show()
|
||||||
|
return image
|
||||||
|
|
||||||
|
def start_startup_process(self):
|
||||||
self.t = threading.Thread(target=self.startup_process)
|
self.t = threading.Thread(target=self.startup_process)
|
||||||
self.t.start()
|
self.t.start()
|
||||||
self.wait_for_t(self.t)
|
GLib.timeout_add(200, self.check_thread)
|
||||||
|
|
||||||
def wait_for_t(self, t):
|
def check_thread(self):
|
||||||
if not self.t.is_alive():
|
if not self.t.is_alive():
|
||||||
global indicator
|
global indicator
|
||||||
indicator.set_status(appindicator.IndicatorStatus.ACTIVE)
|
indicator.set_status(appindicator.IndicatorStatus.ACTIVE)
|
||||||
self.t.join()
|
self.t.join()
|
||||||
self.destroy()
|
self.destroy()
|
||||||
else:
|
return False
|
||||||
GLib.timeout_add(200, self.wait_for_t, self.t)
|
return True
|
||||||
|
|
||||||
def startup_process(self):
|
def startup_process(self):
|
||||||
self.lbl1.set_text("Checking if anisette-server is already running...")
|
steps = [
|
||||||
self.loadalthea.set_fraction(0.1)
|
(self.check_anisette_server, "Checking if anisette-server is already running...", 0.1),
|
||||||
command = 'curl 127.0.0.1:6969 | grep -q "{"'
|
(self.setup_anisette_server, "Setting up anisette-server if not installed...", 0.3),
|
||||||
CheckRun = subprocess.run(command, shell=True)
|
(self.download_apple_music_apk, "Downloading Apple Music APK if necessary...", 0.4),
|
||||||
if not os.path.isfile(f"{(altheapath)}/anisette-server"):
|
(self.extract_libraries, "Extracting necessary libraries if needed...", 0.5),
|
||||||
self.lbl1.set_text("Downloading anisette-server...")
|
(self.start_anisette_server, "Starting anisette-server...", 0.6),
|
||||||
if computer_cpu_platform == 'x86_64':
|
(self.setup_altserver, "Setting up AltServer if not installed...", 0.8),
|
||||||
r = requests.get(
|
(self.start_altserver, "Starting AltServer...", 1.0)
|
||||||
"https://github.com/vyvir/althea/releases/download/v0.5.0/anisette-server-x86_64",
|
]
|
||||||
allow_redirects=True,
|
|
||||||
)
|
for step, message, progress in steps:
|
||||||
elif computer_cpu_platform == "aarch64":
|
GLib.idle_add(self.lbl1.set_text, message)
|
||||||
#Thanks, Dadoum for the anisette server!
|
GLib.idle_add(self.loadalthea.set_fraction, progress)
|
||||||
#or vyvir, do not forget to upload ur version of server.
|
step()
|
||||||
r = requests.get(
|
|
||||||
"https://github.com/vyvir/althea/releases/download/v0.5.0/anisette-server-aarch64",
|
def check_anisette_server(self):
|
||||||
allow_redirects=True
|
command = 'curl -s 127.0.0.1:6969 | grep -q "{"'
|
||||||
)
|
result = subprocess.run(command, shell=True)
|
||||||
#sorry i dont know what will arm32 output
|
return result.returncode == 0
|
||||||
elif computer_cpu_platform.find('v7') != -1 or computer_cpu_platform.find('ARM') != -1 or computer_cpu_platform.find('hf') != -1:
|
|
||||||
r = requests.get(
|
def setup_anisette_server(self):
|
||||||
"https://github.com/vyvir/althea/releases/download/v0.5.0/anisette-server-armv7",
|
anisette_path = f"{altheapath}/anisette-server"
|
||||||
allow_redirects=True
|
if os.path.isfile(anisette_path):
|
||||||
)
|
print("Anisette server already installed.")
|
||||||
else:
|
return
|
||||||
print('WARNING: YOUR CPU IS NOT SUPPORTED, THE PROGRAM MAY NOT WORK!')
|
print("Installing Anisette server...")
|
||||||
#ooops, just download x86-64 ver
|
urls = {
|
||||||
r = requests.get(
|
'x86_64': "https://github.com/vyvir/althea/releases/download/v0.5.0/anisette-server-x86_64",
|
||||||
"https://github.com/vyvir/althea/releases/download/v0.5.0/anisette-server-x86_64",
|
'aarch64': "https://github.com/vyvir/althea/releases/download/v0.5.0/anisette-server-aarch64",
|
||||||
allow_redirects=True,
|
'armv7': "https://github.com/vyvir/althea/releases/download/v0.5.0/anisette-server-armv7",
|
||||||
)
|
}
|
||||||
open(f"{(altheapath)}/anisette-server", "wb").write(r.content)
|
cpu_url = urls.get(computer_cpu_platform, urls['x86_64'])
|
||||||
subprocess.run(f"chmod +x {(altheapath)}/anisette-server", shell=True)
|
self.download_file(cpu_url, anisette_path)
|
||||||
subprocess.run(f"chmod 755 {(altheapath)}/anisette-server", shell=True)
|
self.run_command(f"chmod +x {anisette_path}")
|
||||||
self.loadalthea.set_fraction(0.2)
|
self.run_command(f"chmod 755 {anisette_path}")
|
||||||
self.lbl1.set_text("Downloading Apple Music APK...")
|
|
||||||
r = requests.get(
|
def download_apple_music_apk(self):
|
||||||
"https://apps.mzstatic.com/content/android-apple-music-apk/applemusic.apk",
|
apk_path = f"{altheapath}/am.apk"
|
||||||
allow_redirects=True,
|
if os.path.isfile(apk_path):
|
||||||
)
|
print("Apple Music APK already downloaded.")
|
||||||
open(f"{(altheapath)}/am.apk", "wb").write(r.content)
|
return
|
||||||
os.makedirs(f"{(altheapath)}/lib/x86_64")
|
print("Downloading Apple Music APK...")
|
||||||
self.loadalthea.set_fraction(0.3)
|
url = "https://apps.mzstatic.com/content/android-apple-music-apk/applemusic.apk"
|
||||||
self.lbl1.set_text("Extracting necessary libraries...")
|
self.download_file(url, apk_path)
|
||||||
CheckRunB = subprocess.run(
|
|
||||||
f'unzip -j "{(altheapath)}/am.apk" "lib/x86_64/libstoreservicescore.so" -d "{(altheapath)}/lib/x86_64"',
|
def extract_libraries(self):
|
||||||
shell=True,
|
lib_path = f"{altheapath}/lib/x86_64/libstoreservicescore.so"
|
||||||
)
|
if os.path.isfile(lib_path):
|
||||||
CheckRunC = subprocess.run(
|
print("Libraries already extracted.")
|
||||||
f'unzip -j "{(altheapath)}/am.apk" "lib/x86_64/libCoreADI.so" -d "{(altheapath)}/lib/x86_64"',
|
return
|
||||||
shell=True,
|
print("Extracting libraries...")
|
||||||
)
|
os.makedirs(f"{altheapath}/lib/x86_64", exist_ok=True)
|
||||||
silent_remove(f"{(altheapath)}/am.apk")
|
self.run_command(f'unzip -j "{altheapath}/am.apk" "lib/x86_64/libstoreservicescore.so" -d "{altheapath}/lib/x86_64"')
|
||||||
self.loadalthea.set_fraction(0.4)
|
self.run_command(f'unzip -j "{altheapath}/am.apk" "lib/x86_64/libCoreADI.so" -d "{altheapath}/lib/x86_64"')
|
||||||
self.lbl1.set_text("Starting anisette-server...")
|
os.remove(f"{altheapath}/am.apk")
|
||||||
subprocess.run(f"cd {(altheapath)} && ./anisette-server &", shell=True)#-n 127.0.0.1 -p 6969 &", shell=True
|
|
||||||
self.loadalthea.set_fraction(0.5)
|
def start_anisette_server(self):
|
||||||
finished = False
|
print("Starting Anisette server...")
|
||||||
while not finished:
|
self.run_command(f"cd {altheapath} && ./anisette-server &")
|
||||||
CheckRun5 = subprocess.run(command, shell=True)
|
for _ in range(30):
|
||||||
if CheckRun5.returncode == 0:
|
if self.check_anisette_server():
|
||||||
finished = True
|
break
|
||||||
else:
|
sleep(1)
|
||||||
sleep(1)
|
|
||||||
if not os.path.isfile(f"{(altheapath)}/AltServer"):
|
|
||||||
self.lbl1.set_text("Downloading AltServer...")
|
|
||||||
self.loadalthea.set_fraction(0.6)
|
|
||||||
|
|
||||||
"""
|
|
||||||
r = requests.get(
|
|
||||||
"https://github.com/NyaMisty/AltServer-Linux/releases/download/v0.0.5/AltServer-x86_64",
|
|
||||||
allow_redirects=True,
|
|
||||||
)
|
|
||||||
"""
|
|
||||||
if computer_cpu_platform == 'AMD64':
|
|
||||||
r = requests.get(
|
|
||||||
"https://github.com/NyaMisty/AltServer-Linux/releases/download/v0.0.5/AltServer-x86_64",
|
|
||||||
allow_redirects=True,
|
|
||||||
)
|
|
||||||
elif computer_cpu_platform == 'aarch64':
|
|
||||||
r = requests.get(
|
|
||||||
"https://github.com/NyaMisty/AltServer-Linux/releases/download/v0.0.5/AltServer-aarch64",
|
|
||||||
allow_redirects=True
|
|
||||||
)
|
|
||||||
elif computer_cpu_platform.find('v7') != -1 or computer_cpu_platform.find('ARM') != -1 or computer_cpu_platform.find('hf') != -1:
|
|
||||||
r = requests.get(
|
|
||||||
"https://github.com/NyaMisty/AltServer-Linux/releases/download/v0.0.5/AltServer-armv7",
|
|
||||||
allow_redirects=True
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
print('WARNING: YOUR CPU IS NOT SUPPORTED, AltServer MAY NOT WORK!')
|
|
||||||
#ooops, just download x86-64 ver
|
|
||||||
r = requests.get(
|
|
||||||
"https://github.com/NyaMisty/AltServer-Linux/releases/download/v0.0.5/AltServer-x86_64",
|
|
||||||
allow_redirects=True,
|
|
||||||
)
|
|
||||||
open(f"{(altheapath)}/AltServer", "wb").write(r.content)
|
|
||||||
subprocess.run(f"chmod +x {(altheapath)}/AltServer", shell=True)
|
|
||||||
subprocess.run(f"chmod 755 {(altheapath)}/AltServer", shell=True)
|
|
||||||
self.loadalthea.set_fraction(0.8)
|
|
||||||
if not os.path.isfile(f"{(altheapath)}/AltStore.ipa"):
|
|
||||||
self.lbl1.set_text("Downloading AltStore...")
|
|
||||||
altstore_download("Download")
|
|
||||||
else:
|
else:
|
||||||
self.lbl1.set_text("Checking latest AltStore version...")
|
print("Failed to start anisette-server")
|
||||||
if not altstore_download("Check"):
|
|
||||||
self.lbl1.set_text("Downloading new version of AltStore...")
|
def setup_altserver(self):
|
||||||
altstore_download("Download")
|
altserver_path = f"{altheapath}/AltServer"
|
||||||
self.lbl1.set_text("Starting AltServer...")
|
if os.path.isfile(altserver_path):
|
||||||
self.loadalthea.set_fraction(1.0)
|
print("AltServer already installed.")
|
||||||
subprocess.run(f"{(altheapath)}/AltServer &", shell=True)
|
return
|
||||||
return 0
|
print("Installing AltServer...")
|
||||||
|
altserver_urls = {
|
||||||
|
'AMD64': "https://github.com/NyaMisty/AltServer-Linux/releases/download/v0.0.5/AltServer-x86_64",
|
||||||
|
'aarch64': "https://github.com/NyaMisty/AltServer-Linux/releases/download/v0.0.5/AltServer-aarch64",
|
||||||
|
'armv7': "https://github.com/NyaMisty/AltServer-Linux/releases/download/v0.0.5/AltServer-armv7",
|
||||||
|
}
|
||||||
|
altserver_url = altserver_urls.get(computer_cpu_platform, altserver_urls['AMD64'])
|
||||||
|
self.download_file(altserver_url, altserver_path)
|
||||||
|
self.run_command(f"chmod +x {altserver_path}")
|
||||||
|
self.run_command(f"chmod 755 {altserver_path}")
|
||||||
|
|
||||||
|
def start_altserver(self):
|
||||||
|
print("Starting AltServer...")
|
||||||
|
self.run_command(f"{altheapath}/AltServer &")
|
||||||
|
|
||||||
|
def download_file(self, url, destination):
|
||||||
|
if os.path.isfile(destination):
|
||||||
|
print(f"File {destination} already exists.")
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
r = requests.get(url, allow_redirects=True)
|
||||||
|
r.raise_for_status()
|
||||||
|
with open(destination, "wb") as f:
|
||||||
|
f.write(r.content)
|
||||||
|
except requests.RequestException as e:
|
||||||
|
print(f"Error downloading file: {e}")
|
||||||
|
|
||||||
|
def run_command(self, command):
|
||||||
|
subprocess.run(command, shell=True)
|
||||||
|
|
||||||
|
|
||||||
class Login(Gtk.Window):#
|
class Login(Gtk.Window):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__(title="Login")
|
super().__init__(title="Login")
|
||||||
|
self.setup_window()
|
||||||
|
self.create_ui()
|
||||||
|
|
||||||
|
def setup_window(self):
|
||||||
self.present()
|
self.present()
|
||||||
self.set_position(Gtk.WindowPosition.CENTER_ALWAYS)
|
self.set_position(Gtk.WindowPosition.CENTER_ALWAYS)
|
||||||
self.set_resizable(False)
|
self.set_resizable(False)
|
||||||
self.set_border_width(10)
|
self.set_border_width(10)
|
||||||
|
|
||||||
|
def create_ui(self):
|
||||||
grid = Gtk.Grid()
|
grid = Gtk.Grid()
|
||||||
self.add(grid)
|
self.add(grid)
|
||||||
|
|
||||||
label = Gtk.Label(label="Apple ID: ")
|
self.entry1 = self.create_entry("Apple ID: ", grid, 0)
|
||||||
label.set_justify(Gtk.Justification.LEFT)
|
self.entry = self.create_password_entry("Password: ", grid, 2)
|
||||||
|
|
||||||
self.entry1 = Gtk.Entry()
|
|
||||||
|
|
||||||
label1 = Gtk.Label(label="Password: ")
|
|
||||||
label1.set_justify(Gtk.Justification.LEFT)
|
|
||||||
|
|
||||||
self.entry = Gtk.Entry()
|
|
||||||
self.entry.set_visibility(False)
|
|
||||||
global icon_name
|
|
||||||
self.entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, icon_name)
|
|
||||||
self.entry.connect("icon-press", self.on_icon_toggled)
|
|
||||||
|
|
||||||
self.button = Gtk.Button.new_with_label("Login")
|
self.button = Gtk.Button.new_with_label("Login")
|
||||||
self.button.connect("clicked", self.on_click_me_clicked)
|
self.button.connect("clicked", self.on_click_me_clicked)
|
||||||
|
|
||||||
grid.add(label)
|
|
||||||
grid.attach(self.entry1, 1, 0, 2, 1)
|
|
||||||
grid.attach_next_to(label1, label, Gtk.PositionType.BOTTOM, 1, 2)
|
|
||||||
grid.attach(self.entry, 1, 2, 1, 1)
|
|
||||||
grid.attach_next_to(self.button, self.entry, Gtk.PositionType.RIGHT, 1, 1)
|
grid.attach_next_to(self.button, self.entry, Gtk.PositionType.RIGHT, 1, 1)
|
||||||
|
|
||||||
silent_remove(f"{(altheapath)}/log.txt")
|
def create_entry(self, label_text, grid, row):
|
||||||
|
label = Gtk.Label(label=label_text)
|
||||||
|
label.set_justify(Gtk.Justification.LEFT)
|
||||||
|
entry = Gtk.Entry()
|
||||||
|
grid.add(label)
|
||||||
|
grid.attach(entry, 1, row, 2, 1)
|
||||||
|
return entry
|
||||||
|
|
||||||
def on_click_me_clicked1(self):
|
def create_password_entry(self, label_text, grid, row):
|
||||||
self.realthread1 = threading.Thread(target=self.onclickmethread)
|
entry = self.create_entry(label_text, grid, row)
|
||||||
self.realthread1.start()
|
entry.set_visibility(False)
|
||||||
GLib.idle_add(self.install_process)
|
entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, "changes-prevent-symbolic")
|
||||||
|
entry.connect("icon-press", self.on_icon_toggled)
|
||||||
|
return entry
|
||||||
|
|
||||||
def on_click_me_clicked(self, button):
|
def on_click_me_clicked(self, button):
|
||||||
silent_remove(f"{(altheapath)}/log.txt")
|
self.save_credentials_dialog()
|
||||||
if not os.path.isfile(f"{(altheapath)}/saved.txt"):
|
self.start_login_process()
|
||||||
self.set_position(Gtk.WindowPosition.CENTER_ALWAYS)
|
|
||||||
|
def save_credentials_dialog(self):
|
||||||
|
if not os.path.isfile(f"{altheapath}/saved.txt"):
|
||||||
dialog = Gtk.MessageDialog(
|
dialog = Gtk.MessageDialog(
|
||||||
transient_for=self,
|
transient_for=self,
|
||||||
flags=0,
|
flags=0,
|
||||||
message_type=Gtk.MessageType.QUESTION,
|
message_type=Gtk.MessageType.QUESTION,
|
||||||
buttons=Gtk.ButtonsType.YES_NO,
|
buttons=Gtk.ButtonsType.YES_NO,
|
||||||
text="Do you want to save your login and password?",
|
text="Do you want to save your login and password?"
|
||||||
)
|
)
|
||||||
dialog.format_secondary_text("This will allow you to login automatically.")
|
dialog.format_secondary_text("This will allow you to log in automatically.")
|
||||||
response = dialog.run()
|
response = dialog.run()
|
||||||
if response == Gtk.ResponseType.YES:
|
if response == Gtk.ResponseType.YES:
|
||||||
apple_id = self.entry1.get_text().lower()
|
self.save_credentials()
|
||||||
password = self.entry.get_text()
|
|
||||||
f = open(f"{(altheapath)}/saved.txt", "x")
|
|
||||||
f.write(apple_id)
|
|
||||||
f.write(":")
|
|
||||||
f.write(password)
|
|
||||||
f.close()
|
|
||||||
dialog.destroy()
|
dialog.destroy()
|
||||||
|
|
||||||
|
def save_credentials(self):
|
||||||
|
apple_id = self.entry1.get_text().lower()
|
||||||
|
password = self.entry.get_text()
|
||||||
|
with open(f"{altheapath}/saved.txt", "w") as f:
|
||||||
|
f.write(f"{apple_id}:{password}")
|
||||||
|
|
||||||
|
def start_login_process(self):
|
||||||
self.entry.set_progress_pulse_step(0.2)
|
self.entry.set_progress_pulse_step(0.2)
|
||||||
# Call self.do_pulse every 100 ms
|
|
||||||
self.timeout_id = GLib.timeout_add(100, self.do_pulse, None)
|
self.timeout_id = GLib.timeout_add(100, self.do_pulse, None)
|
||||||
self.entry.set_editable(False)
|
self.entry.set_editable(False)
|
||||||
self.entry1.set_editable(False)
|
self.entry1.set_editable(False)
|
||||||
@@ -596,30 +547,46 @@ class Login(Gtk.Window):#
|
|||||||
self.realthread1.start()
|
self.realthread1.start()
|
||||||
GLib.idle_add(self.install_process)
|
GLib.idle_add(self.install_process)
|
||||||
|
|
||||||
|
|
||||||
def onclickmethread(self):
|
def onclickmethread(self):
|
||||||
|
global apple_id, password
|
||||||
|
|
||||||
|
if not savedcheck:
|
||||||
|
apple_id = self.entry1.get_text().lower()
|
||||||
|
password = self.entry.get_text()
|
||||||
|
else:
|
||||||
|
with open(f"{altheapath}/saved.txt", "r") as f:
|
||||||
|
saved_data = f.read().strip()
|
||||||
|
if ":" in saved_data:
|
||||||
|
apple_id, password = saved_data.split(":", 1)
|
||||||
|
else:
|
||||||
|
print("Invalid saved credentials format.")
|
||||||
|
return
|
||||||
|
|
||||||
if ios_version() >= "15.0":
|
if ios_version() >= "15.0":
|
||||||
global savedcheck
|
try:
|
||||||
global apple_id
|
UDID = subprocess.check_output("idevice_id -l", shell=True).decode().strip()
|
||||||
global password
|
except subprocess.CalledProcessError as e:
|
||||||
if not savedcheck:
|
print(f"Error obtaining UDID: {e}")
|
||||||
apple_id = self.entry1.get_text().lower()
|
return
|
||||||
password = self.entry.get_text()
|
|
||||||
UDID = subprocess.check_output("idevice_id -l", shell=True).decode().strip()
|
silent_remove(f"{altheapath}/log.txt")
|
||||||
global InsAltStore
|
|
||||||
print(PATH)
|
if os.path.isdir(f'{os.environ["HOME"]}/.adi'):
|
||||||
silent_remove(f"{(altheapath)}/log.txt")
|
rmtree(f'{os.environ["HOME"]}/.adi')
|
||||||
#f = open(f"{(altheapath)}/log.txt", "w")
|
|
||||||
#f.close()
|
InsAltStoreCMD = f"""export ALTSERVER_ANISETTE_SERVER='http://127.0.0.1:6969' ; {AltServer} -u {UDID} -a {apple_id} -p {password} {PATH} > {os.environ["HOME"]}/.local/share/althea/log.txt"""
|
||||||
if os.path.isdir(f'{ os.environ["HOME"] }/.adi'):
|
try:
|
||||||
rmtree(f'{ os.environ["HOME"] }/.adi')
|
global InsAltStore
|
||||||
InsAltStoreCMD = f"""export ALTSERVER_ANISETTE_SERVER='http://127.0.0.1:6969' ; {(AltServer)} -u {UDID} -a {apple_id} -p {password} {PATH} > {("$HOME/.local/share/althea/log.txt")}"""
|
InsAltStore = subprocess.Popen(
|
||||||
InsAltStore = subprocess.Popen(
|
InsAltStoreCMD,
|
||||||
InsAltStoreCMD,
|
stdin=subprocess.PIPE,
|
||||||
stdin=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stdout=subprocess.PIPE,
|
shell=True,
|
||||||
shell=True,
|
)
|
||||||
)
|
except Exception as e:
|
||||||
else: # If the iOS version is lower than 15.0, AltServer-Linux won't run
|
print(f"Error starting subprocess: {e}")
|
||||||
|
else:
|
||||||
global Failmsg
|
global Failmsg
|
||||||
Failmsg = "iOS 15.0 or later is required."
|
Failmsg = "iOS 15.0 or later is required."
|
||||||
dialog2 = DialogExample3(self)
|
dialog2 = DialogExample3(self)
|
||||||
@@ -632,46 +599,39 @@ class Login(Gtk.Window):#
|
|||||||
WarnTime = 0
|
WarnTime = 0
|
||||||
TwoFactorTime = 0
|
TwoFactorTime = 0
|
||||||
global InsAltStore
|
global InsAltStore
|
||||||
|
|
||||||
while Installing:
|
while Installing:
|
||||||
CheckIns = subprocess.run(
|
CheckIns = subprocess.run(
|
||||||
f'grep -F "Could not" {(altheapath)}/log.txt', shell=True
|
f'grep -F "Could not" {altheapath}/log.txt', shell=True
|
||||||
)
|
)
|
||||||
CheckWarn = subprocess.run(
|
CheckWarn = subprocess.run(
|
||||||
f'grep -F "Are you sure you want to continue?" {(altheapath)}/log.txt',
|
f'grep -F "Are you sure you want to continue?" {altheapath}/log.txt', shell=True
|
||||||
shell=True,
|
|
||||||
)
|
)
|
||||||
CheckSuccess = subprocess.run(
|
CheckSuccess = subprocess.run(
|
||||||
f'grep -F "Notify: Installation Succeeded" {(altheapath)}/log.txt',
|
f'grep -F "Notify: Installation Succeeded" {altheapath}/log.txt', shell=True
|
||||||
shell=True,
|
|
||||||
)
|
)
|
||||||
Check2fa = subprocess.run(
|
Check2fa = subprocess.run(
|
||||||
f'grep -F "Enter two factor code" {(altheapath)}/log.txt', shell=True
|
f'grep -F "Enter two factor code" {altheapath}/log.txt', shell=True
|
||||||
)
|
)
|
||||||
|
|
||||||
if CheckIns.returncode == 0:
|
if CheckIns.returncode == 0:
|
||||||
InsAltStore.terminate()
|
InsAltStore.terminate()
|
||||||
Installing = False
|
Installing = False
|
||||||
global Failmsg
|
global Failmsg
|
||||||
Failmsg = subprocess.check_output(
|
Failmsg = subprocess.check_output(f"tail -6 {altheapath}/log.txt", shell=True).decode()
|
||||||
f"tail -6 {(altheapath)}/log.txt", shell=True
|
|
||||||
).decode()
|
|
||||||
dialog2 = DialogExample3(self)
|
dialog2 = DialogExample3(self)
|
||||||
dialog2.run()
|
dialog2.run()
|
||||||
dialog2.destroy()
|
dialog2.destroy()
|
||||||
self.destroy()
|
self.destroy()
|
||||||
|
|
||||||
elif CheckWarn.returncode == 0 and WarnTime == 0:
|
elif CheckWarn.returncode == 0 and WarnTime == 0:
|
||||||
Installing = False
|
Installing = False
|
||||||
word = "Are you sure you want to continue?"
|
word = "Are you sure you want to continue?"
|
||||||
# This fixes an issue where the warn window appears when it shouldn't
|
with open(f"{altheapath}/log.txt", "r") as file:
|
||||||
with open(f"{(altheapath)}/log.txt", "r") as file:
|
|
||||||
# Read all content of the file
|
|
||||||
content = file.read()
|
content = file.read()
|
||||||
# Check if a string present in the file
|
|
||||||
if word in content:
|
if word in content:
|
||||||
global Warnmsg
|
global Warnmsg
|
||||||
Warnmsg = subprocess.check_output(
|
Warnmsg = subprocess.check_output(f"tail -8 {os.environ['HOME']}/.local/share/althea/log.txt", shell=True).decode()
|
||||||
f"tail -8 {('$HOME/.local/share/althea/log.txt')}",
|
|
||||||
shell=True,
|
|
||||||
).decode()
|
|
||||||
dialog1 = DialogExample2(self)
|
dialog1 = DialogExample2(self)
|
||||||
response1 = dialog1.run()
|
response1 = dialog1.run()
|
||||||
if response1 == Gtk.ResponseType.OK:
|
if response1 == Gtk.ResponseType.OK:
|
||||||
@@ -686,13 +646,14 @@ class Login(Gtk.Window):#
|
|||||||
else:
|
else:
|
||||||
WarnTime = 1
|
WarnTime = 1
|
||||||
Installing = True
|
Installing = True
|
||||||
|
|
||||||
elif Check2fa.returncode == 0 and TwoFactorTime == 0:
|
elif Check2fa.returncode == 0 and TwoFactorTime == 0:
|
||||||
Installing = False
|
Installing = False
|
||||||
dialog = DialogExample(self)
|
dialog = DialogExample(self)
|
||||||
response = dialog.run()
|
response = dialog.run()
|
||||||
if response == Gtk.ResponseType.OK:
|
if response == Gtk.ResponseType.OK:
|
||||||
vercode = dialog.entry2.get_text()
|
vercode = dialog.entry2.get_text().strip() + "\n"
|
||||||
vercode = vercode + "\n"
|
print(f"2FA Code: {vercode}")
|
||||||
vercodebytes = bytes(vercode.encode())
|
vercodebytes = bytes(vercode.encode())
|
||||||
InsAltStore.communicate(input=vercodebytes)
|
InsAltStore.communicate(input=vercodebytes)
|
||||||
TwoFactorTime = 1
|
TwoFactorTime = 1
|
||||||
@@ -704,6 +665,7 @@ class Login(Gtk.Window):#
|
|||||||
self.cancel()
|
self.cancel()
|
||||||
dialog.destroy()
|
dialog.destroy()
|
||||||
self.destroy()
|
self.destroy()
|
||||||
|
|
||||||
elif CheckSuccess.returncode == 0:
|
elif CheckSuccess.returncode == 0:
|
||||||
Installing = False
|
Installing = False
|
||||||
self.success()
|
self.success()
|
||||||
@@ -742,10 +704,12 @@ class Login(Gtk.Window):#
|
|||||||
global icon_name
|
global icon_name
|
||||||
if icon_name == "changes-prevent-symbolic":
|
if icon_name == "changes-prevent-symbolic":
|
||||||
icon_name = "changes-allow-symbolic"
|
icon_name = "changes-allow-symbolic"
|
||||||
self.entry.set_visibility(True)
|
visibility = True
|
||||||
elif icon_name == "changes-allow-symbolic":
|
else:
|
||||||
icon_name = "changes-prevent-symbolic"
|
icon_name = "changes-prevent-symbolic"
|
||||||
self.entry.set_visibility(False)
|
visibility = False
|
||||||
|
|
||||||
|
self.entry.set_visibility(visibility)
|
||||||
self.entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, icon_name)
|
self.entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, icon_name)
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -876,16 +840,16 @@ class FileChooserWindow(Gtk.Window):
|
|||||||
dialog.destroy()
|
dialog.destroy()
|
||||||
|
|
||||||
def add_filters(self, dialog):
|
def add_filters(self, dialog):
|
||||||
filter_ipa = Gtk.FileFilter()
|
filters = [
|
||||||
filter_ipa.set_name("IPA files")
|
("IPA files", "*.ipa"),
|
||||||
filter_ipa.add_pattern("*.ipa")
|
("Any files", "*")
|
||||||
dialog.add_filter(filter_ipa)
|
]
|
||||||
|
|
||||||
filter_any = Gtk.FileFilter()
|
|
||||||
filter_any.set_name("Any files")
|
|
||||||
filter_any.add_pattern("*")
|
|
||||||
dialog.add_filter(filter_any)
|
|
||||||
|
|
||||||
|
for name, pattern in filters:
|
||||||
|
filter = Gtk.FileFilter()
|
||||||
|
filter.set_name(name)
|
||||||
|
filter.add_pattern(pattern)
|
||||||
|
dialog.add_filter(filter)
|
||||||
|
|
||||||
class DialogExample(Gtk.Dialog):
|
class DialogExample(Gtk.Dialog):
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
|
|||||||
Reference in New Issue
Block a user