-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from Pyenb:feature/configs
Feature/configs
- Loading branch information
Showing
7 changed files
with
169 additions
and
81 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,10 @@ | ||
build/ | ||
dist/ | ||
app.log | ||
Keychron_mice_updater.spec | ||
innosetup/Keychron_mice_updater_setup.exe | ||
innosetup/Keychron_mice_updater_setup.zip | ||
upx/ | ||
|
||
*.log | ||
*.spec | ||
*.json | ||
|
||
innosetup/*.exe | ||
innosetup/*.zip |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
pyinstaller --onefile --noconsole Keychron_mice_updater.py | ||
pyinstaller --onefile --noconsole -n "Keychron mice updater" -i images/logo.ico --upx-dir=upx/ updater.py |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,31 @@ | ||
#define AppName "Keychron mice updater" | ||
#define ExeName AppName + ".exe" | ||
#define Version "1.1" | ||
#define AppPublisher "Pyenb" | ||
|
||
[Setup] | ||
AppName=Keychron Mice Software Updater | ||
AppVersion=1.0 | ||
DefaultDirName={commonpf}\Keychron Mice Software Updater | ||
DefaultGroupName=Keychron Mice Software Updater | ||
UninstallDisplayIcon={app}\keychron.exe | ||
AppName={#AppName} | ||
AppVersion={#Version} | ||
AppPublisher={#AppPublisher} | ||
DefaultDirName={commonpf}\{#AppName} | ||
DefaultGroupName={#AppName} | ||
UninstallDisplayIcon={app}\{#ExeName} | ||
OutputDir=. | ||
OutputBaseFilename=Keychron_mice_updater_setup | ||
OutputBaseFilename="{#AppName} SETUP" | ||
Compression=lzma | ||
SolidCompression=yes | ||
SetupIconFile=..\images\logo.ico | ||
|
||
[Files] | ||
Source: "..\dist\Keychron_mice_updater.exe"; DestDir: "{app}"; Flags: ignoreversion | ||
Source: "..\dist\{#ExeName}"; DestDir: "{app}"; Flags: ignoreversion | ||
|
||
[Icons] | ||
Name: "{group}\Keychron Mice Software Updater"; Filename: "{app}\Keychron_mice_updater.exe" | ||
Name: "{group}\Uninstall Keychron Mice Software Updater"; Filename: "{uninstallexe}" | ||
Name: "{commonstartup}\Keychron Mice Software Updater"; Filename: "{app}\Keychron_mice_updater.exe"; Tasks: autostart | ||
Name: "{group}\{#AppName}"; Filename: "{app}\{#ExeName}" | ||
Name: "{group}\Uninstall {#AppName}"; Filename: "{uninstallexe}" | ||
Name: "{commonstartup}\{#AppName}"; Filename: "{app}\{#ExeName}"; Tasks: autostart | ||
|
||
[Run] | ||
Filename: "{app}\Keychron_mice_updater.exe"; Description: "Launch the application"; Flags: nowait postinstall skipifsilent | ||
Filename: "{app}\{#ExeName}"; Description: "Launch the application"; Flags: nowait postinstall skipifsilent | ||
|
||
[Tasks] | ||
Name: "autostart"; Description: "Start the application when Windows starts"; GroupDescription: "Additional tasks"; Flags: checkedonce |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
import requests, gdown, zipfile, os, ctypes, tempfile, shutil, subprocess, sys, json, logging | ||
from tkinter import messagebox, filedialog | ||
|
||
def terminate(): | ||
logger.error("Terminating the program") | ||
sys.exit() | ||
|
||
def get_appdata_path(): | ||
appdata_path = os.getenv('APPDATA') | ||
folder_path = os.path.join(appdata_path, 'Keychron mice updater') | ||
|
||
if not os.path.exists(folder_path): | ||
os.makedirs(folder_path) | ||
|
||
return folder_path | ||
|
||
def setup_logger(): | ||
folder_path = get_appdata_path() | ||
log_file_path = os.path.join(folder_path, 'updater.log') | ||
|
||
logging.basicConfig( | ||
filename=log_file_path, | ||
format='%(asctime)s - %(levelname)s - %(filename)s - %(funcName)s - %(lineno)d - %(message)s', | ||
level=logging.INFO, | ||
encoding='utf-8' | ||
) | ||
|
||
logger = logging.getLogger(__name__) | ||
return logger | ||
|
||
logger = setup_logger() | ||
|
||
def config_manager(): | ||
folder_path = get_appdata_path() | ||
config_file = os.path.join(folder_path, "config.json") | ||
|
||
if os.path.exists(config_file): | ||
with open(config_file, "r") as f: | ||
install_path = json.load(f)["install_path"] | ||
if os.path.exists(os.path.join(install_path, 'config.xml')): | ||
return install_path | ||
else: | ||
logger.warning('config.xml not found in install_path') | ||
|
||
install_path = get_install_path() | ||
with open(config_file, "w") as f: | ||
json.dump({"install_path": install_path}, f) | ||
logger.info('install_path written to config.json') | ||
|
||
return install_path | ||
|
||
def get_install_path(): | ||
default_path = r"C:\Program Files (x86)\Keychron" | ||
if not os.path.exists(os.path.join(default_path, 'config.xml')): | ||
logger.warning(f"Keychron software is not installed in the default location: {default_path}") | ||
messagebox.showerror("Error", f"Keychron software is not installed in the default location: {default_path}") | ||
messagebox.showinfo("Info", "Please select the Keychron software installation folder") | ||
install_path = filedialog.askdirectory().replace("/", "\\") | ||
logger.info(f"User selected installation folder: {install_path}") | ||
return install_path | ||
return default_path | ||
|
||
def get_installed_version(install_path): | ||
try: | ||
with open(install_path + "\\config.xml") as f: | ||
installed_version = f.read().split('<software caption="Keychron" version="')[1].split('"')[0] | ||
logger.info(f"Installed version found: {installed_version}") | ||
return installed_version | ||
except Exception as e: | ||
logger.error(f"Failed to get installed version: {e}") | ||
messagebox.showerror("Error", f"Failed to get installed version: {e}") | ||
terminate() | ||
|
||
def get_online_version_and_url(): | ||
try: | ||
download_site = requests.get("https://www.keychron.com/pages/learn-more-how-to-use-keychron-mouse-software").text | ||
download_id = download_site.split('drive.google.com/file/d/')[1].split('/')[0].strip() | ||
download_url = f"https://drive.google.com/uc?id={download_id}" | ||
logging.info(f"Download url obtained: {download_url}") | ||
|
||
online_version = download_site.splitlines() | ||
for line in online_version: | ||
if "Version" in line and "updated on" in line: | ||
online_version = line.split('Version ')[1].split(' ')[0].strip() | ||
logging.info(f"Online version obtained: {online_version}") | ||
break | ||
|
||
return online_version, download_url | ||
except Exception as e: | ||
logging.error(f"Failed to get online version and url: {e}") | ||
messagebox.showerror("Error", f"Failed to get online version and url: {e}") | ||
terminate() | ||
|
||
def download_and_extract_file(download_url, tmp_path): | ||
try: | ||
gdown.download(download_url, tmp_path + '\\Keychron.zip', quiet=True) | ||
with zipfile.ZipFile(tmp_path + '\\Keychron.zip', 'r') as zip_ref: | ||
zip_ref.extractall(tmp_path) | ||
except Exception as e: | ||
logging.error(f"Failed to download and extract file: {e}") | ||
messagebox.showerror("Error", f"Failed to download and extract file: {e}") | ||
terminate() | ||
|
||
def run_exe(tmp_path): | ||
try: | ||
for root, dirs, files in os.walk(tmp_path): | ||
for file in files: | ||
if file.endswith(".exe"): | ||
process = subprocess.Popen([os.path.join(root, file)], shell=True) | ||
process.wait() | ||
except Exception as e: | ||
logger.error(f"Failed to run exe: {e}") | ||
messagebox.showerror("Error", f"Failed to run exe: {e}") | ||
terminate() | ||
|
||
def main(): | ||
logger.info("Starting the updater") | ||
install_path = config_manager() | ||
try: | ||
installed_version = get_installed_version(install_path) | ||
online_version, download_url = get_online_version_and_url() | ||
|
||
if installed_version != online_version: | ||
MessageBox = ctypes.windll.user32.MessageBoxW | ||
result = MessageBox(None, f'Version {online_version} of the Keychron software is available. Do you want to download it?', 'New version available', 1) | ||
if result == 1: | ||
tmp_path = tempfile.mkdtemp() | ||
download_and_extract_file(download_url, tmp_path) | ||
run_exe(tmp_path) | ||
shutil.rmtree(tmp_path) | ||
except Exception as e: | ||
logging.error(f"An error occurred in main function: {e}") | ||
messagebox.showerror("Error", f"An error occurred in main function: {e}") | ||
terminate() | ||
logger.info("Updater finished") | ||
|
||
if __name__ == "__main__": | ||
main() |