Compare commits

...

2 Commits

Author SHA1 Message Date
Nix
0014978163
Better fallbacks in the login system 2025-12-10 21:18:42 -03:00
Nixietab
01587aa5e7 simple changes to the version managment menu
Some checks failed
Version Change Action / version-release (push) Has been cancelled
2025-12-08 18:38:54 -03:00
2 changed files with 62 additions and 24 deletions

View File

@ -134,6 +134,8 @@ class AuthenticationThread(QThread):
return j["access_token"], j["refresh_token"] return j["access_token"], j["refresh_token"]
raise Exception("Authentication cancelled by user")
async def _xbl_auth(self, access_token): async def _xbl_auth(self, access_token):
data = { data = {
"Properties": { "Properties": {
@ -223,13 +225,14 @@ class AuthenticationThread(QThread):
self.is_running = False self.is_running = False
class MinecraftAuthenticator(QObject): class MinecraftAuthenticator(QObject):
auth_finished = pyqtSignal(bool) auth_finished = pyqtSignal(bool, str)
def __init__(self, parent=None): def __init__(self, parent=None):
super().__init__(parent) super().__init__(parent)
self.auth_thread = None self.auth_thread = None
self.auth_dialog = None self.auth_dialog = None
self.success = False self.success = False
self.error_message = None
self.username = None self.username = None
# Initialize the launcher to get the correct config path # Initialize the launcher to get the correct config path
@ -242,6 +245,12 @@ class MinecraftAuthenticator(QObject):
# Create accounts.json if it doesn't exist # Create accounts.json if it doesn't exist
if not self.save_to_accounts_json(): if not self.save_to_accounts_json():
self.auth_finished.emit(False, self.error_message)
return
# Check if account is online
if not self.validate_account_type():
self.auth_finished.emit(False, "Cannot authenticate an offline account")
return return
self.auth_thread = AuthenticationThread(username) self.auth_thread = AuthenticationThread(username)
@ -263,9 +272,24 @@ class MinecraftAuthenticator(QObject):
self.auth_thread.stop() self.auth_thread.stop()
def show_error(self, error_msg): def show_error(self, error_msg):
QMessageBox.critical(None, "Error", error_msg) self.error_message = error_msg
self.success = False self.success = False
self.auth_finished.emit(False)
def validate_account_type(self):
try:
accounts_file = Path(self.config_path) / "accounts.json"
if accounts_file.exists():
with open(accounts_file) as f:
config = json.load(f)
if self.username in config["accounts"]:
return config["accounts"][self.username].get("microsoft", False)
return True # New account, will be created as microsoft
except Exception as e:
logger.error(f"Failed to validate account type: {str(e)}")
return False
def save_to_accounts_json(self): def save_to_accounts_json(self):
try: try:
@ -305,7 +329,7 @@ class MinecraftAuthenticator(QObject):
except Exception as e: except Exception as e:
logger.error(f"Failed to initialize account data: {str(e)}") logger.error(f"Failed to initialize account data: {str(e)}")
QMessageBox.critical(None, "Error", f"Failed to initialize account data: {str(e)}") self.error_message = f"Failed to initialize account data: {str(e)}"
return False return False
def on_access_token_received(self, data): def on_access_token_received(self, data):
@ -328,17 +352,15 @@ class MinecraftAuthenticator(QObject):
json.dump(config, f, indent=4) json.dump(config, f, indent=4)
self.success = True self.success = True
QMessageBox.information(None, "Success",
f"Successfully authenticated account: {self.username}")
else: else:
raise Exception("Account not found in configuration") raise Exception("Account not found in configuration")
except Exception as e: except Exception as e:
logger.error(f"Failed to update account data: {str(e)}") logger.error(f"Failed to update account data: {str(e)}")
QMessageBox.critical(None, "Error", f"Failed to update account data: {str(e)}") self.error_message = f"Failed to update account data: {str(e)}"
self.success = False self.success = False
self.auth_finished.emit(self.success) # We don't emit here, we wait for the thread to finish
def on_authentication_finished(self): def on_authentication_finished(self):
if self.auth_dialog is not None: if self.auth_dialog is not None:
@ -350,7 +372,9 @@ class MinecraftAuthenticator(QObject):
self.auth_thread = None self.auth_thread = None
if not self.success: if not self.success:
self.auth_finished.emit(False) self.auth_finished.emit(False, self.error_message)
else:
self.auth_finished.emit(True, f"Successfully authenticated account: {self.username}")
def cleanup(self): def cleanup(self):
if self.auth_dialog is not None: if self.auth_dialog is not None:
@ -363,4 +387,4 @@ class MinecraftAuthenticator(QObject):
def create_authenticator(): def create_authenticator():
"""Factory function to create a new MinecraftAuthenticator instance""" """Factory function to create a new MinecraftAuthenticator instance"""
return MinecraftAuthenticator() return MinecraftAuthenticator()

View File

@ -16,7 +16,7 @@ from healthcheck import HealthCheck
import modulecli import modulecli
import loaddaemon import loaddaemon
from PyQt5.QtWidgets import QApplication, QComboBox, QWidget, QInputDialog, QVBoxLayout, QListWidget, QSpinBox, QFileDialog, QPushButton, QMessageBox, QDialog, QHBoxLayout, QLabel, QLineEdit, QCheckBox, QTabWidget, QFrame, QSpacerItem, QSizePolicy, QMainWindow, QGridLayout, QTextEdit, QListWidget, QListWidgetItem, QMenu from PyQt5.QtWidgets import QApplication, QComboBox, QWidget, QInputDialog, QVBoxLayout, QListWidget, QSpinBox, QFileDialog, QPushButton, QMessageBox, QDialog, QHBoxLayout, QLabel, QLineEdit, QCheckBox, QTabWidget, QFrame, QSpacerItem, QSizePolicy, QMainWindow, QGridLayout, QTextEdit, QListWidget, QListWidgetItem, QMenu, QRadioButton
from PyQt5.QtGui import QFont, QIcon, QColor, QPalette, QMovie, QPixmap, QDesktopServices, QBrush from PyQt5.QtGui import QFont, QIcon, QColor, QPalette, QMovie, QPixmap, QDesktopServices, QBrush
from PyQt5.QtCore import Qt, QObject, pyqtSignal, QThread, QUrl, QMetaObject, Q_ARG, QByteArray, QSize from PyQt5.QtCore import Qt, QObject, pyqtSignal, QThread, QUrl, QMetaObject, Q_ARG, QByteArray, QSize
from datetime import datetime from datetime import datetime
@ -1074,11 +1074,11 @@ class zucaroVersionSelector(QWidget):
logging.error(error_message) logging.error(error_message)
QMessageBox.critical(dialog, "Error", error_message) QMessageBox.critical(dialog, "Error", error_message)
def _on_auth_finished(self, success): def _on_auth_finished(self, success, message):
if success: if success:
QMessageBox.information(self, "Success", "Account authenticated successfully!") QMessageBox.information(self, "Success", message)
else: else:
QMessageBox.critical(self, "Error", "Failed to authenticate account") QMessageBox.critical(self, "Error", message)
# Cleanup # Cleanup
if self.authenticator: if self.authenticator:
@ -1682,11 +1682,13 @@ class ModLoaderAndVersionMenu(QDialog):
title_label.setFont(QFont("Arial", 14)) title_label.setFont(QFont("Arial", 14))
layout.addWidget(title_label) layout.addWidget(title_label)
# Create checkboxes for mod loaders # Create radio buttons for mod loaders
self.forge_checkbox = QCheckBox('Forge') self.forge_checkbox = QRadioButton('Forge')
self.fabric_checkbox = QCheckBox('Fabric') self.fabric_checkbox = QRadioButton('Fabric')
self.quilt_checkbox = QRadioButton('Quilt')
layout.addWidget(self.forge_checkbox) layout.addWidget(self.forge_checkbox)
layout.addWidget(self.fabric_checkbox) layout.addWidget(self.fabric_checkbox)
layout.addWidget(self.quilt_checkbox)
# Create dropdown menu for versions # Create dropdown menu for versions
self.version_combo_mod = QComboBox() self.version_combo_mod = QComboBox()
@ -1695,19 +1697,23 @@ class ModLoaderAndVersionMenu(QDialog):
def update_versions(): def update_versions():
self.version_combo_mod.clear() self.version_combo_mod.clear()
if self.forge_checkbox.isChecked(): if self.forge_checkbox.isChecked():
self.populate_available_releases(self.version_combo_mod, True, False) self.populate_available_releases(self.version_combo_mod, True, False, False)
elif self.fabric_checkbox.isChecked(): elif self.fabric_checkbox.isChecked():
self.populate_available_releases(self.version_combo_mod, False, True) self.populate_available_releases(self.version_combo_mod, False, True, False)
elif self.quilt_checkbox.isChecked():
self.populate_available_releases(self.version_combo_mod, False, False, True)
self.forge_checkbox.clicked.connect(update_versions) self.forge_checkbox.clicked.connect(update_versions)
self.fabric_checkbox.clicked.connect(update_versions) self.fabric_checkbox.clicked.connect(update_versions)
self.quilt_checkbox.clicked.connect(update_versions)
# Create install button # Create install button
install_button = QPushButton('Install') install_button = QPushButton('Install')
install_button.clicked.connect(lambda: self.install_mod_loader( install_button.clicked.connect(lambda: self.install_mod_loader(
self.version_combo_mod.currentText(), self.version_combo_mod.currentText(),
self.forge_checkbox.isChecked(), self.forge_checkbox.isChecked(),
self.fabric_checkbox.isChecked() self.fabric_checkbox.isChecked(),
self.quilt_checkbox.isChecked()
)) ))
layout.addWidget(install_button) layout.addWidget(install_button)
@ -1721,6 +1727,7 @@ class ModLoaderAndVersionMenu(QDialog):
# Create checkboxes for different version types # Create checkboxes for different version types
self.release_checkbox = QCheckBox('Releases') self.release_checkbox = QCheckBox('Releases')
self.release_checkbox.setChecked(True)
self.snapshot_checkbox = QCheckBox('Snapshots') self.snapshot_checkbox = QCheckBox('Snapshots')
self.alpha_checkbox = QCheckBox('Alpha') self.alpha_checkbox = QCheckBox('Alpha')
self.beta_checkbox = QCheckBox('Beta') self.beta_checkbox = QCheckBox('Beta')
@ -1778,6 +1785,9 @@ class ModLoaderAndVersionMenu(QDialog):
# Connect the combo box signal to the update function # Connect the combo box signal to the update function
self.version_combo.currentIndexChanged.connect(self.update_download_button_state) self.version_combo.currentIndexChanged.connect(self.update_download_button_state)
# Initial update
update_versions()
def update_download_button_state(self): def update_download_button_state(self):
self.download_button.setEnabled(self.version_combo.currentIndex() != -1) self.download_button.setEnabled(self.version_combo.currentIndex() != -1)
@ -1788,7 +1798,7 @@ class ModLoaderAndVersionMenu(QDialog):
else: else:
QMessageBox.critical(self, "Error", f"Failed to prepare version {version}.") QMessageBox.critical(self, "Error", f"Failed to prepare version {version}.")
def populate_available_releases(self, version_combo, install_forge, install_fabric): def populate_available_releases(self, version_combo, install_forge, install_fabric, install_quilt):
try: try:
command = "version list --release" command = "version list --release"
output = modulecli.run_command(command) output = modulecli.run_command(command)
@ -1799,7 +1809,7 @@ class ModLoaderAndVersionMenu(QDialog):
logging.error("Error: %s", str(e)) logging.error("Error: %s", str(e))
return return
if install_fabric: if install_fabric or install_quilt:
releases = [version for version in output.splitlines() if version.startswith("1.") and int(version.split('.')[1]) >= 14] releases = [version for version in output.splitlines() if version.startswith("1.") and int(version.split('.')[1]) >= 14]
elif install_forge: elif install_forge:
releases = [version for version in output.splitlines() if version.startswith("1.") and float(version.split('.')[1]) >= 5] releases = [version for version in output.splitlines() if version.startswith("1.") and float(version.split('.')[1]) >= 5]
@ -1809,8 +1819,8 @@ class ModLoaderAndVersionMenu(QDialog):
version_combo.clear() version_combo.clear()
version_combo.addItems(releases) version_combo.addItems(releases)
def install_mod_loader(self, version, install_forge, install_fabric): def install_mod_loader(self, version, install_forge, install_fabric, install_quilt):
if not install_forge and not install_fabric: if not install_forge and not install_fabric and not install_quilt:
QMessageBox.warning(self, "Select Mod Loader", "Please select at least one mod loader.") QMessageBox.warning(self, "Select Mod Loader", "Please select at least one mod loader.")
return return
@ -1819,6 +1829,8 @@ class ModLoaderAndVersionMenu(QDialog):
mod_loader = 'forge' mod_loader = 'forge'
elif install_fabric: elif install_fabric:
mod_loader = 'fabric' mod_loader = 'fabric'
elif install_quilt:
mod_loader = 'quilt'
if not mod_loader: if not mod_loader:
QMessageBox.warning(self, "Select Mod Loader", "Please select at least one mod loader.") QMessageBox.warning(self, "Select Mod Loader", "Please select at least one mod loader.")
@ -1829,6 +1841,8 @@ class ModLoaderAndVersionMenu(QDialog):
command = f"mod loader forge install --game {version}" command = f"mod loader forge install --game {version}"
elif mod_loader == 'fabric': elif mod_loader == 'fabric':
command = f"mod loader fabric install {version}" command = f"mod loader fabric install {version}"
elif mod_loader == 'quilt':
command = f"mod loader quilt install {version}"
modulecli.run_command(command) modulecli.run_command(command)
QMessageBox.information(self, "Success", f"{mod_loader.capitalize()} installed successfully for version {version}!") QMessageBox.information(self, "Success", f"{mod_loader.capitalize()} installed successfully for version {version}!")
except Exception as e: except Exception as e: