first commit

This commit is contained in:
tcsenpai 2024-12-07 13:42:27 +01:00
commit 3a6ee79824
6 changed files with 261 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.service
__pycache__

57
README.md Normal file
View File

@ -0,0 +1,57 @@
# flatpak-menu-sync
A simple script to sync flatpak menu entries to dmenu.
## Use case
This script is useful for users who want to use flatpak and dmenu apps like `rofi` or `fuzzel`.
Once a flatpak app is installed, it will automatically appear in dmenu (while keeping the traditional applications).
## Configuration
You have to modify the `flatpak-menu-sync.service.example` file to your needs, then rename it to `flatpak-menu-sync.service`.
For most users, the default miniconda3 path should be in `/home/yourusername/miniconda3/` and thus the example file should be fine.
Remember to set your username in the `ExecStart` line.
## Troubleshooting
If the service doesn't start, check the logs with `journalctl -u flatpak-menu-sync.service`.
### Error: "flatpak-menu-sync.service not found"
This error occurs if the service file was not renamed to `flatpak-menu-sync.service`. Please see the previous section for more information.
### Errors related to the `pyinotify` packages
Please install the `pyinotify` package through your package manager.
Pip should be supported but if it doesn't work, please try:
#### Ubuntu/Debian
```bash
sudo apt install python3-pyinotify
```
#### Arch Linux
```bash
sudo pacman -S python-pyinotify
```
#### Fedora
```bash
sudo dnf install python3-pyinotify
```
And restart the service with `sudo systemctl restart flatpak-menu-sync.service`.
## Installation
Once you have cloned the repository and followed the configuration section, you can run the `integrate.sh` script to install the service.
```bash
./integrate.sh
```
If you prefer, you can manually execute the script with the correct user and miniconda path.

138
flatpak-menu-sync.py Executable file
View File

@ -0,0 +1,138 @@
#!/usr/bin/env python3
import os
import sys
import shutil
import time
import logging
from pathlib import Path
try:
import pyinotify
except ImportError as e:
sys.exit(
f"Error: pyinotify module not found. Please install it using 'sudo apt install python3-pyinotify'\nDetails: {e}"
)
# Configure logging with more detailed error reporting
logging.basicConfig(
level=logging.DEBUG, # Changed to DEBUG for more detailed logs
format="%(asctime)s - %(levelname)s - %(message)s",
handlers=[
logging.FileHandler("/var/log/flatpak-menu-sync.log"),
logging.StreamHandler(sys.stdout), # Also log to stdout
],
)
FLATPAK_DIR = "/var/lib/flatpak/exports/share/applications"
TARGET_DIR = "/usr/share/applications"
def check_directories():
"""Verify that required directories exist and are accessible"""
if not os.path.exists(FLATPAK_DIR):
logging.error(f"Flatpak directory does not exist: {FLATPAK_DIR}")
return False
if not os.path.exists(TARGET_DIR):
logging.error(f"Target directory does not exist: {TARGET_DIR}")
return False
if not os.access(FLATPAK_DIR, os.R_OK):
logging.error(f"Cannot read from Flatpak directory: {FLATPAK_DIR}")
return False
if not os.access(TARGET_DIR, os.W_OK):
logging.error(f"Cannot write to target directory: {TARGET_DIR}")
return False
return True
def sync_desktop_files():
try:
if not check_directories():
return False
# Create target directory if it doesn't exist
Path(TARGET_DIR).mkdir(parents=True, exist_ok=True)
# Get current files in both directories
flatpak_files = set(Path(FLATPAK_DIR).glob("*.desktop"))
target_files = set(Path(TARGET_DIR).glob("org.flatpak.*.desktop"))
# Copy new files
for src_file in flatpak_files:
dst_file = Path(TARGET_DIR) / src_file.name
if not dst_file.exists():
try:
shutil.copy2(src_file, dst_file)
os.chmod(dst_file, 0o644)
logging.info(f"Copied new file: {src_file.name}")
except Exception as e:
logging.error(f"Error copying {src_file.name}: {str(e)}")
# Remove obsolete files
for target_file in target_files:
src_file = Path(FLATPAK_DIR) / target_file.name
if not src_file.exists():
try:
target_file.unlink()
logging.info(f"Removed obsolete file: {target_file.name}")
except Exception as e:
logging.error(f"Error removing {target_file.name}: {str(e)}")
return True
except Exception as e:
logging.error(f"Unexpected error in sync_desktop_files: {str(e)}")
return False
class FlatpakWatcher(pyinotify.ProcessEvent):
def process_IN_CREATE(self, event):
if event.name.endswith(".desktop"):
logging.info(f"New file created: {event.name}")
sync_desktop_files()
def process_IN_DELETE(self, event):
if event.name.endswith(".desktop"):
logging.info(f"File deleted: {event.name}")
sync_desktop_files()
def process_IN_MODIFY(self, event):
if event.name.endswith(".desktop"):
logging.info(f"File modified: {event.name}")
sync_desktop_files()
def main():
try:
logging.info("Flatpak menu sync service started")
if not check_directories():
sys.exit(1)
# Initialize inotify
wm = pyinotify.WatchManager()
mask = pyinotify.IN_CREATE | pyinotify.IN_DELETE | pyinotify.IN_MODIFY
# Create notifier
handler = FlatpakWatcher()
notifier = pyinotify.Notifier(wm, handler)
# Add watch
wdd = wm.add_watch(FLATPAK_DIR, mask)
if FLATPAK_DIR not in wdd or not wdd[FLATPAK_DIR]:
logging.error(f"Failed to add watch for {FLATPAK_DIR}")
sys.exit(1)
# Initial sync
if not sync_desktop_files():
logging.error("Initial sync failed")
sys.exit(1)
logging.info("Starting watch loop")
# Start watching
notifier.loop()
except Exception as e:
logging.error(f"Fatal error in main: {str(e)}")
sys.exit(1)
if __name__ == "__main__":
main()

View File

@ -0,0 +1,17 @@
[Unit]
Description=Flatpak Menu Entry Sync Service
After=flatpak.service
[Service]
Type=simple
ExecStart=/bin/bash -c 'source /home/youruser/miniconda3/bin/activate base && /usr/local/bin/flatpak-menu-sync.py'
Restart=on-failure
RestartSec=5
User=root
Group=root
CPUQuota=20%
MemoryMax=50M
Nice=10
[Install]
WantedBy=multi-user.target

46
integrate.sh Executable file
View File

@ -0,0 +1,46 @@
#!/bin/bash
# Define paths
SCRIPT_PATH="/usr/local/bin/flatpak-menu-sync.py"
SERVICE_PATH="/etc/systemd/system/flatpak-menu-sync.service"
LOG_PATH="/var/log/flatpak-menu-sync.log"
# Copy the Python script
echo "Copying Python script to $SCRIPT_PATH..."
sudo cp flatpak-menu-sync.py $SCRIPT_PATH
sudo chmod +x $SCRIPT_PATH
# Copy the systemd service file
echo "Copying systemd service file to $SERVICE_PATH..."
if [ ! -f flatpak-menu-sync.service ]; then
echo "flatpak-menu-sync.service not found. Please see the example file flatpak-menu-sync.service.example and modify it to your needs, then rename it to flatpak-menu-sync.service and run this script again."
exit 1
fi
sudo cp flatpak-menu-sync.service $SERVICE_PATH || echo "Failed to copy service file. Please check the permissions and try again."
# Reload systemd daemon
echo "Reloading systemd daemon..."
sudo systemctl daemon-reload
# Enable and start the service
echo "Enabling and starting the flatpak-menu-sync service..."
sudo systemctl enable flatpak-menu-sync
sudo systemctl start flatpak-menu-sync
# Create log file if it doesn't exist
if [ ! -f "$LOG_PATH" ]; then
echo "Creating log file at $LOG_PATH..."
sudo touch $LOG_PATH
sudo chown root:root $LOG_PATH
sudo chmod 644 $LOG_PATH
fi
# Check if the service is running
if sudo systemctl is-active flatpak-menu-sync.service > /dev/null 2>&1; then
echo "The flatpak-menu-sync service is now running."
echo "You can check the status of the service with 'systemctl status flatpak-menu-sync.service'"
echo "You can check the logs of the service with 'journalctl -u flatpak-menu-sync.service'"
echo "Happy flatpakbing!"
else
echo "The flatpak-menu-sync service failed to start. Please check the logs for more information."
fi

1
requirements.txt Normal file
View File

@ -0,0 +1 @@
pyinotify