Created
May 11, 2025 10:36
-
-
Save SWORDIntel/856bf0fb0951129ddd53dcbff0bd6583 to your computer and use it in GitHub Desktop.
Intergrate an appimage interactively w/shortcut creation and perms
This file contains hidden or 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
#!/usr/bin/env python3 | |
import npyscreen | |
import os | |
import stat | |
import shutil | |
from pathlib import Path | |
import subprocess | |
import logging | |
from datetime import datetime | |
# Setup logging | |
logging.basicConfig( | |
filename=f'appimage_helper_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log', | |
level=logging.INFO, | |
format='%(asctime)s - %(levelname)s - %(message)s' | |
) | |
class AppImageHelper: | |
def __init__(self): | |
self.home = Path.home() | |
self.programs_dir = self.home / "Programs" | |
self.desktop_dir = self.home / "Desktop" | |
self.local_apps_dir = self.home / ".local/share/applications" | |
self.local_icons_dir = self.home / ".local/share/icons/hicolor/256x256/apps" | |
def get_appimages(self): | |
"""Scan for AppImage files in the Programs directory.""" | |
try: | |
return list(self.programs_dir.glob("*.AppImage")) | |
except Exception as e: | |
logging.error(f"Error scanning for AppImages: {e}") | |
return [] | |
def extract_icon(self, appimage_path): | |
"""Extract icon from AppImage.""" | |
try: | |
# Create temporary directory for extraction | |
temp_dir = Path("/tmp/appimage_icon_extract") | |
temp_dir.mkdir(exist_ok=True) | |
# Extract icon using AppImage's built-in mechanism | |
cmd = [str(appimage_path), "--appimage-extract", "*.png"] | |
subprocess.run(cmd, cwd=temp_dir, capture_output=True) | |
# Find the largest icon file | |
icons = list(temp_dir.rglob("*.png")) | |
if icons: | |
icon = max(icons, key=lambda x: os.path.getsize(x)) | |
return icon | |
return None | |
except Exception as e: | |
logging.error(f"Error extracting icon: {e}") | |
return None | |
def create_desktop_entry(self, appimage_path, icon_path=None): | |
"""Create .desktop file for the AppImage.""" | |
try: | |
app_name = appimage_path.stem | |
desktop_entry = f"""[Desktop Entry] | |
Name={app_name} | |
Exec={appimage_path} | |
Type=Application | |
Categories=Utility; | |
Terminal=false | |
""" | |
if icon_path: | |
desktop_entry += f"Icon={icon_path}\n" | |
# Create .desktop file in local applications directory | |
self.local_apps_dir.mkdir(parents=True, exist_ok=True) | |
desktop_file = self.local_apps_dir / f"{app_name.lower()}.desktop" | |
desktop_file.write_text(desktop_entry) | |
# Create symbolic link on desktop | |
desktop_shortcut = self.desktop_dir / f"{app_name.lower()}.desktop" | |
if desktop_shortcut.exists(): | |
desktop_shortcut.unlink() | |
desktop_shortcut.symlink_to(desktop_file) | |
# Make desktop file executable | |
desktop_file.chmod(desktop_file.stat().st_mode | stat.S_IEXEC) | |
desktop_shortcut.chmod(desktop_shortcut.stat().st_mode | stat.S_IEXEC) | |
return True | |
except Exception as e: | |
logging.error(f"Error creating desktop entry: {e}") | |
return False | |
class AppImageSelector(npyscreen.NPSAppManaged): | |
def onStart(self): | |
self.helper = AppImageHelper() | |
self.addForm("MAIN", MainForm, name="AppImage Helper") | |
class MainForm(npyscreen.ActionForm): | |
def create(self): | |
self.appimages = self.parentApp.helper.get_appimages() | |
# Show instructions | |
self.add(npyscreen.TitleText, name="Select AppImage to integrate:", editable=False) | |
# Create selection widget | |
self.appimage_select = self.add(npyscreen.TitleSelectOne, | |
name="Available AppImages", | |
max_height=10, | |
values=[str(p.name) for p in self.appimages], | |
scroll_exit=True) | |
def on_ok(self): | |
if not self.appimage_select.value: | |
npyscreen.notify_confirm("Please select an AppImage file.", "Error") | |
return | |
selected_index = self.appimage_select.value[0] | |
appimage_path = self.appimages[selected_index] | |
# Make AppImage executable | |
try: | |
appimage_path.chmod(appimage_path.stat().st_mode | stat.S_IEXEC) | |
except Exception as e: | |
logging.error(f"Error making AppImage executable: {e}") | |
npyscreen.notify_confirm(f"Error making AppImage executable: {e}", "Error") | |
return | |
# Extract icon | |
icon_path = self.parentApp.helper.extract_icon(appimage_path) | |
if icon_path: | |
try: | |
# Copy icon to system location | |
self.parentApp.helper.local_icons_dir.mkdir(parents=True, exist_ok=True) | |
icon_dest = self.parentApp.helper.local_icons_dir / f"{appimage_path.stem}.png" | |
shutil.copy2(icon_path, icon_dest) | |
icon_path = icon_dest | |
except Exception as e: | |
logging.error(f"Error copying icon: {e}") | |
icon_path = None | |
# Create desktop entry | |
if self.parentApp.helper.create_desktop_entry(appimage_path, icon_path): | |
npyscreen.notify_confirm("AppImage successfully integrated!", "Success") | |
else: | |
npyscreen.notify_confirm("Error creating desktop entry.", "Error") | |
self.parentApp.switchForm(None) | |
def on_cancel(self): | |
self.parentApp.switchForm(None) | |
def main(): | |
try: | |
app = AppImageSelector() | |
app.run() | |
except Exception as e: | |
logging.error(f"Application error: {e}") | |
print(f"Error: {e}") | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment