247 lines
10 KiB
Bash
Executable File
247 lines
10 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Configuration directories
|
|
INSTALL_DIR="$HOME/.local/bin"
|
|
APP_DIR="$HOME/.local/share/applications"
|
|
SERVICE_MENU_DIR="$HOME/.local/share/kio/servicemenus"
|
|
LEGACY_SERVICE_MENU_DIR="$HOME/.local/share/kservices5/ServiceMenus"
|
|
|
|
# Check Python 3 and PySide6 dependency
|
|
echo "Checking dependencies..."
|
|
if ! command -v python3 &>/dev/null; then
|
|
echo "Error: Python 3 is required but not found on your system."
|
|
exit 1
|
|
fi
|
|
|
|
if ! python3 -c "import PySide6" &>/dev/null; then
|
|
echo "PySide6 is not installed. Attempting automatic installation..."
|
|
if command -v pip3 &>/dev/null; then
|
|
pip3 install PySide6 || pip3 install --break-system-packages PySide6 || true
|
|
elif command -v pip &>/dev/null; then
|
|
pip install PySide6 || pip install --break-system-packages PySide6 || true
|
|
elif command -v dnf &>/dev/null; then
|
|
echo "Installing python3-pyside6 via dnf..."
|
|
sudo dnf install -y python3-pyside6 || true
|
|
elif command -v apt-get &>/dev/null; then
|
|
echo "Installing python3-pyside6 via apt..."
|
|
sudo apt-get update && sudo apt-get install -y python3-pyside6 || true
|
|
elif command -v pacman &>/dev/null; then
|
|
echo "Installing python-pyside6 via pacman..."
|
|
sudo pacman -S --noconfirm python-pyside6 || true
|
|
elif command -v zypper &>/dev/null; then
|
|
echo "Installing python3-pyside6 via zypper..."
|
|
sudo zypper install -y python3-pyside6 || true
|
|
fi
|
|
fi
|
|
|
|
if ! python3 -c "import PySide6" &>/dev/null; then
|
|
echo "Warning: Could not automatically install PySide6. Please install 'PySide6' via pip or your distro package manager (e.g. python3-pyside6)."
|
|
fi
|
|
|
|
# Create necessary directories
|
|
mkdir -p "$INSTALL_DIR" "$APP_DIR" "$SERVICE_MENU_DIR" "$LEGACY_SERVICE_MENU_DIR"
|
|
|
|
# Clean legacy kde-uploader names
|
|
rm -f "$INSTALL_DIR/kde-uploader" "$INSTALL_DIR/kde-uploader-gui"
|
|
rm -f "$APP_DIR/kde-uploader.desktop" "$APP_DIR/kde-uploader-gui.desktop"
|
|
rm -f "$SERVICE_MENU_DIR/kde-uploader-servicemenu.desktop" "$LEGACY_SERVICE_MENU_DIR/kde-uploader-servicemenu.desktop"
|
|
rm -f "$HOME/.config/autostart/kde-uploader-gui.desktop"
|
|
|
|
# 1. Install the scripts
|
|
cp uploader.sh "$INSTALL_DIR/f0ckm-uploader"
|
|
chmod +x "$INSTALL_DIR/f0ckm-uploader"
|
|
|
|
cp gui.py "$INSTALL_DIR/f0ckm-uploader-gui"
|
|
chmod +x "$INSTALL_DIR/f0ckm-uploader-gui"
|
|
|
|
mkdir -p "$HOME/.local/share/icons/hicolor/scalable/apps"
|
|
mkdir -p "$HOME/.local/share/pixmaps"
|
|
|
|
# Generate multi-resolution PNG icons (32x32, 48x48, 64x64, 128x128, 256x256) for KRunner search compatibility
|
|
python3 -c '
|
|
import os
|
|
from PySide6.QtGui import QImage, QPainter
|
|
from PySide6.QtSvg import QSvgRenderer
|
|
try:
|
|
renderer = QSvgRenderer("icon_app.svg")
|
|
sizes = [32, 48, 64, 128, 256]
|
|
for sz in sizes:
|
|
dir_path = f"'$HOME'/.local/share/icons/hicolor/{sz}x{sz}/apps"
|
|
os.makedirs(dir_path, exist_ok=True)
|
|
img = QImage(sz, sz, QImage.Format_ARGB32)
|
|
img.fill(0)
|
|
p = QPainter(img)
|
|
renderer.render(p)
|
|
p.end()
|
|
img.save(os.path.join(dir_path, "f0ckm-uploader.png"))
|
|
|
|
img_48 = QImage(48, 48, QImage.Format_ARGB32)
|
|
img_48.fill(0)
|
|
p = QPainter(img_48)
|
|
renderer.render(p)
|
|
p.end()
|
|
img_48.save("'$HOME'/.local/share/pixmaps/f0ckm-uploader.png")
|
|
except Exception as e:
|
|
pass
|
|
' &> /dev/null
|
|
|
|
if [ -f icon_app.svg ]; then
|
|
cp icon_app.svg "$INSTALL_DIR/icon_app.svg"
|
|
cp icon_app.svg "$HOME/.local/share/icons/hicolor/scalable/apps/f0ckm-uploader.svg"
|
|
elif [ -f icon.svg ]; then
|
|
cp icon.svg "$HOME/.local/share/icons/hicolor/scalable/apps/f0ckm-uploader.svg"
|
|
fi
|
|
|
|
if [ -f icon.svg ]; then
|
|
cp icon.svg "$INSTALL_DIR/icon.svg"
|
|
fi
|
|
|
|
if [ -f icon_light.svg ]; then
|
|
cp icon_light.svg "$INSTALL_DIR/icon_light.svg"
|
|
fi
|
|
|
|
if [ -f .env ]; then
|
|
cp .env "$INSTALL_DIR/.env"
|
|
fi
|
|
|
|
# Clean up any stale auto-generated desktop entries
|
|
rm -f "$APP_DIR/net.local.spectacle_uploader.sh.desktop"
|
|
|
|
ICON_PATH="f0ckm-uploader"
|
|
|
|
# 2. Install standard application entry (for Spectacle - hidden from main menu)
|
|
sed -e "s|__EXEC_PATH__|$INSTALL_DIR/f0ckm-uploader-gui --spectacle|g" -e "s|__ICON_PATH__|$ICON_PATH|g" f0ckm-uploader.desktop > "$APP_DIR/f0ckm-uploader.desktop"
|
|
chmod +x "$APP_DIR/f0ckm-uploader.desktop"
|
|
|
|
# 3. Install the GUI application entry (visible in main menu)
|
|
sed -e "s|__EXEC_PATH__|$INSTALL_DIR/f0ckm-uploader-gui|g" -e "s|__ICON_PATH__|$ICON_PATH|g" f0ckm-uploader-gui.desktop > "$APP_DIR/f0ckm-uploader-gui.desktop"
|
|
chmod +x "$APP_DIR/f0ckm-uploader-gui.desktop"
|
|
|
|
update-desktop-database "$APP_DIR" &> /dev/null
|
|
xdg-mime default f0ckm-uploader-gui.desktop x-scheme-handler/f0ckm x-scheme-handler/f0ckm-uploader &> /dev/null || true
|
|
gtk-update-icon-cache -f -t "$HOME/.local/share/icons/hicolor" &> /dev/null || true
|
|
kbuildsycoca6 --noincremental &> /dev/null || kbuildsycoca5 --noincremental &> /dev/null || true
|
|
|
|
# 4. Install KDE Service Menu entry (for Dolphin)
|
|
sed "s|__EXEC_PATH__|$INSTALL_DIR/f0ckm-uploader-gui --upload|g" f0ckm-uploader-servicemenu.desktop > "$SERVICE_MENU_DIR/f0ckm-uploader-servicemenu.desktop"
|
|
chmod +x "$SERVICE_MENU_DIR/f0ckm-uploader-servicemenu.desktop"
|
|
sed "s|__EXEC_PATH__|$INSTALL_DIR/f0ckm-uploader-gui --upload|g" f0ckm-uploader-servicemenu.desktop > "$LEGACY_SERVICE_MENU_DIR/f0ckm-uploader-servicemenu.desktop"
|
|
chmod +x "$LEGACY_SERVICE_MENU_DIR/f0ckm-uploader-servicemenu.desktop"
|
|
|
|
# 5. Build and install KDE Purpose plugin (for Gwenview / KDE Share menu)
|
|
if [ -f "purpose_plugin/build_plugin.sh" ]; then
|
|
echo "Building KDE Purpose plugin for Gwenview Share Menu..."
|
|
bash purpose_plugin/build_plugin.sh purpose_plugin &> /dev/null || true
|
|
if [ -f "purpose_plugin/f0ckmpurposeplugin.so" ]; then
|
|
PURPOSE_USER_DIR64="$HOME/.local/lib64/qt6/plugins/kf6/purpose"
|
|
PURPOSE_USER_DIR32="$HOME/.local/lib/qt6/plugins/kf6/purpose"
|
|
mkdir -p "$PURPOSE_USER_DIR64" "$PURPOSE_USER_DIR32"
|
|
cp "purpose_plugin/f0ckmpurposeplugin.so" "$PURPOSE_USER_DIR64/f0ckmpurposeplugin.so"
|
|
cp "purpose_plugin/f0ckmpurposeplugin.so" "$PURPOSE_USER_DIR32/f0ckmpurposeplugin.so"
|
|
|
|
if [ -w "/usr/lib64/qt6/plugins/kf6/purpose" ]; then
|
|
cp "purpose_plugin/f0ckmpurposeplugin.so" "/usr/lib64/qt6/plugins/kf6/purpose/f0ckmpurposeplugin.so" &>/dev/null || true
|
|
elif sudo -n true 2>/dev/null; then
|
|
sudo cp "purpose_plugin/f0ckmpurposeplugin.so" "/usr/lib64/qt6/plugins/kf6/purpose/f0ckmpurposeplugin.so" &>/dev/null || true
|
|
fi
|
|
|
|
ENV_DIR="$HOME/.config/environment.d"
|
|
mkdir -p "$ENV_DIR"
|
|
cat << 'ENVCONF' > "$ENV_DIR/10-qt-plugins.conf"
|
|
QT_PLUGIN_PATH="${HOME}/.local/lib64/qt6/plugins:${HOME}/.local/lib/qt6/plugins:/usr/lib64/qt6/plugins:/usr/lib/qt6/plugins"
|
|
ENVCONF
|
|
|
|
PLASMA_ENV_DIR="$HOME/.config/plasma-workspace/env"
|
|
mkdir -p "$PLASMA_ENV_DIR"
|
|
cat << 'PLASMAENV' > "$PLASMA_ENV_DIR/10-qt-plugins.sh"
|
|
export QT_PLUGIN_PATH="${HOME}/.local/lib64/qt6/plugins:${HOME}/.local/lib/qt6/plugins:${QT_PLUGIN_PATH}:/usr/lib64/qt6/plugins:/usr/lib/qt6/plugins"
|
|
PLASMAENV
|
|
chmod +x "$PLASMA_ENV_DIR/10-qt-plugins.sh"
|
|
|
|
echo " -> Gwenview / KDE Share Menu plugin installed (Upload to f0ckm)"
|
|
fi
|
|
fi
|
|
|
|
# 6. Migrate config to config.json if not present
|
|
CONFIG_DIR="$HOME/.config/f0ckm-uploader"
|
|
CONFIG_FILE="$CONFIG_DIR/config.json"
|
|
if [ ! -f "$CONFIG_FILE" ]; then
|
|
mkdir -p "$CONFIG_DIR"
|
|
# Fallback to the default key in script if no config file is found
|
|
cat <<EOF > "$CONFIG_FILE"
|
|
{
|
|
"api_url": "",
|
|
"api_key": "",
|
|
"default_rating": "",
|
|
"default_tags": "",
|
|
"default_is_oc": false,
|
|
"enable_notifications": true,
|
|
"show_progress_dialog": true,
|
|
"autostart": false
|
|
}
|
|
EOF
|
|
echo "Initial configuration created at $CONFIG_FILE"
|
|
fi
|
|
|
|
# 7. Ensure autostart state matches config.json
|
|
python3 -c '
|
|
import json, os
|
|
try:
|
|
cfg_path = os.path.expanduser("~/.config/f0ckm-uploader/config.json")
|
|
if os.path.exists(cfg_path):
|
|
with open(cfg_path, "r", encoding="utf-8") as f:
|
|
cfg = json.load(f)
|
|
autostart = cfg.get("autostart", False)
|
|
autostart_dir = os.path.expanduser("~/.config/autostart")
|
|
autostart_path = os.path.join(autostart_dir, "f0ckm-uploader-gui.desktop")
|
|
if autostart:
|
|
os.makedirs(autostart_dir, exist_ok=True)
|
|
exec_path = os.path.expanduser("~/.local/bin/f0ckm-uploader-gui")
|
|
content = f"""[Desktop Entry]
|
|
Type=Application
|
|
Name=f0ckm Uploader GUI
|
|
Comment=System tray GUI and settings for f0ckm Uploader
|
|
Exec={exec_path}
|
|
Icon=f0ckm-uploader
|
|
Terminal=false
|
|
Categories=Utility;Network;
|
|
StartupNotify=false
|
|
X-GNOME-Autostart-enabled=true
|
|
"""
|
|
with open(autostart_path, "w", encoding="utf-8") as f:
|
|
f.write(content)
|
|
os.chmod(autostart_path, 0o755)
|
|
print(f"Synced autostart desktop entry: {autostart_path}")
|
|
else:
|
|
if os.path.exists(autostart_path):
|
|
os.remove(autostart_path)
|
|
print(f"Removed autostart desktop entry: {autostart_path}")
|
|
except Exception as e:
|
|
print(f"Warning: could not sync autostart entry: {e}")
|
|
'
|
|
|
|
echo ""
|
|
echo "========================================================"
|
|
echo " f0ckm Uploader Installation Complete!"
|
|
echo "========================================================"
|
|
echo " -> Executable installed: $INSTALL_DIR/f0ckm-uploader-gui"
|
|
echo " -> Dolphin context menu registered (Right-click file -> Actions -> Upload to f0ckm)"
|
|
echo " -> Gwenview / KDE Share menu integration enabled (Upload to f0ckm)"
|
|
echo " -> Spectacle screenshot export integration enabled"
|
|
echo " -> Browser extension helper API ready on http://127.0.0.1:18739"
|
|
echo "========================================================"
|
|
echo ""
|
|
|
|
# Launch GUI to prompt for API settings if API key or URL is not configured yet
|
|
python3 -c '
|
|
import json, os
|
|
cfg_path = os.path.expanduser("~/.config/f0ckm-uploader/config.json")
|
|
if os.path.exists(cfg_path):
|
|
with open(cfg_path) as f:
|
|
cfg = json.load(f)
|
|
if not cfg.get("api_url") or not cfg.get("api_key"):
|
|
print("[!] API Key or URL not configured yet.")
|
|
print(" Launching f0ckm Uploader GUI Settings for initial setup...")
|
|
os.system("'$INSTALL_DIR'/f0ckm-uploader-gui &")
|
|
' || true
|