From 7cbb47bc0c94123e7322c353129772613b74544e Mon Sep 17 00:00:00 2001 From: Radical <66682497+Radiicall@users.noreply.github.com> Date: Sun, 2 Jul 2023 00:33:42 +0200 Subject: [PATCH] Cross platform installer/uninstaller (#32) Removed the old install/uninstall scripts Added new cross platform install/uninstall python scripts! Updated the README to reflect changes --- .gitignore | 1 + README.md | 5 +- scripts/install-macos.sh | 196 ---------------------- scripts/install-win.bat | 113 ------------- scripts/installer.py | 328 +++++++++++++++++++++++++++++++++++++ scripts/uninstall-macos.sh | 12 -- scripts/uninstall-win.bat | 54 ------ scripts/uninstaller.py | 55 +++++++ 8 files changed, 388 insertions(+), 376 deletions(-) delete mode 100755 scripts/install-macos.sh delete mode 100644 scripts/install-win.bat create mode 100755 scripts/installer.py delete mode 100755 scripts/uninstall-macos.sh delete mode 100644 scripts/uninstall-win.bat create mode 100755 scripts/uninstaller.py diff --git a/.gitignore b/.gitignore index dae5bcd..4872a8f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ Cargo.lock main.json /pkg +.DS_Store diff --git a/README.md b/README.md index b2ec2b7..31335dd 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,10 @@ Terminal Output: - Discord - Imgur API key (image support without port forwarding) -Installers for Windows and macOS are available. +Windows users will also need vcredist. + +**A cross-platform installer written in Python can be found here, press ctrl+s on the page to download.** +**There's also a cross-platform uninstaller that can be found here.** A fully filled out config would look something like this diff --git a/scripts/install-macos.sh b/scripts/install-macos.sh deleted file mode 100755 index d7ef5fe..0000000 --- a/scripts/install-macos.sh +++ /dev/null @@ -1,196 +0,0 @@ -#!/bin/zsh -# A script to autoamtically install jellyfin-rpc on mac -clear - -# Get the user's server information -vared -p "Jellyfin Server URL (include http/https): " -c jellyfinurl -vared -p "Jellyfin API Key (you can find this at ${jellyfinurl}/web/#!/apikeys.html): " -c jellyfinkey -vared -p "Jellyfin Username: " -c jellyfinuser -echo "" - -echo "The blacklist creation in this script is currently broken" -echo "Check the README for details on how to set it up in the config " - -# Prompt the user for what libraries should be included/blocked -responses=() - -vared -p "Include Movies in Discord Rich Presence? (y/n) " -c moviesEnabled -if [[ $moviesEnabled == [Nn]* ]]; then - responses+=( "movie" ) -fi - -vared -p "Include TV in Discord Rich Presence? (y/n) " -c tvEnabled -if [[ $tvEnabled == [Nn]* ]]; then - responses+=( "episode" ) -fi - -vared -p "Include Music in Discord Rich Presence? (y/n) " -c musicEnabled -if [[ $musicEnabled == [Nn]* ]]; then - responses+=( "music" ) -fi - -vared -p "Include Live TV in Discord Rich Presence? (y/n) " -c livetvEnabled -if [[ $livetvEnabled == [Nn]* ]]; then - responses+=( "livetv" ) -fi - -# Build the blocklist string -if [[ ${#responses} -eq 0 ]]; then - typeBlocklistString='' -else - typeBlocklistString='[' - for i in ${responses[@]}; do - typeBlocklistString+="\"$i\", " - done - typeBlocklistString=${typeBlocklistString%?} - typeBlocklistString=${typeBlocklistString%?} - typeBlocklistString+=']' -fi -echo "" - -# Prompt for libraries to block -echo "Separated by only commas, type the names of any libraries to be excluded from Jellyfin RPC. Press return when finished." -echo "For example, typing 'Anime,Anime Movies' will filter out media from libraries named 'Anime' and 'Anime Movies'." -vared -p "Leave blank to enable all libraries. This will not disable filtering by media type. " -c libBlocklist - -# Build the blocklist string -libBlocklistArray=(${(@s:,:)libBlocklist}) -if [[ ${#libBlocklistArray} -eq 0 ]]; then - libBlocklistString='' -else - libBlocklistString='[' - for i in ${libBlocklistArray[@]}; do - libBlocklistString+="\"$i\", " - done - libBlocklistString=${libBlocklistString%?} - libBlocklistString=${libBlocklistString%?} - libBlocklistString+=']' -fi -echo "" - -# Get discord application ID, or use default if left blank -vared -p "Discord Application ID (leave blank if you're unsure): " -c discordAppId -if [ -z $discordAppId ]; then - discordAppId="1053747938519679018" -fi - -# Enable or disable image uploading -configImagesEnabled="false" -configImgurEnabled="false" -vared -p "Display media images in discord? (y/n) " -c artworkEnabled -if [[ $artworkEnabled == [Yy]* ]]; then - configImagesEnabled="true" - - # Get Imgur client ID & enable Imgur uploading - echo "If the server is not port-forwarded, you must enable uploading artwork to Imgur or images will not work." - vared -p "Upload media images to Imgur to be displayed in discord? Selecting \"n\" suggests that your server is port-forwarded! (y/n) " -c imgurEnabled - if [[ $imgurEnabled == [Yy]* ]]; then - configImgurEnabled="true" - echo "To get an Imgur client ID, go to https://api.imgur.com/oauth2/addclient" - echo "Name can be anything, authorization type must be 'OAuth 2 authorization without a callback URL'" - echo "Press submit to get your client ID" - vared -p "Imgur client ID (): " -c imgurId - fi -fi - -# Put together the config file - -configFileContents="" -configFileContents+="$(cat < ~/.config/jellyfin-rpc/main.json - -# Prompt user to install Jellyfin RPC -vared -p "Download latest release? (y/n) " -c downloadlatest -if [[ $downloadlatest == [Yy]* ]]; then - # download file to binary directory and give execution permissions - curl -o /usr/local/bin/jellyfin-rpc -L https://github.com/Radiicall/jellyfin-rpc/releases/latest/download/jellyfin-rpc-x86_64-darwin - chmod +x /usr/local/bin/jellyfin-rpc - - # Prompt user to enabled Jellyfin RPC running at login - vared -p "Set Jellyfin-RPC to run at login? (y/n) " -c runAtLogin - if [[ $runAtLogin == [Yy]* ]]; then - - if pgrep -xq -- "jellyfin-rpc"; then - killall jellyfin-rpc # Kill jellyfin-rpc if it is running - fi - if launchctl list | grep Jellyfin-RPC &> /dev/null; then - launchctl remove Jellyfin-RPC # Unload Jellyfin-RPC LaunchAgent if it is loaded - fi - - # Create LaunchAgent file - cat > ~/Library/LaunchAgents/jellyfinrpc.local.plist<< EOF - - - - - Label - Jellyfin-RPC - Program - /usr/local/bin/jellyfin-rpc - RunAtLoad - - StandardErrorPath - /tmp/jellyfinrpc.local.stderr.txt - StandardOutPath - /tmp/jellyfinrpc.local.stdout.txt - - -EOF - chmod 644 ~/Library/LaunchAgents/jellyfinrpc.local.plist # Give LaunchAgent proper permissions - launchctl load ~/Library/LaunchAgents/jellyfinrpc.local.plist # Load LaunchAgent - fi - echo "Jellyfin RPC is now set up to start at login." - echo "If needed, you can run Jellyfin RPC at any time by running 'jellyfin-rpc' in a terminal." -fi - -exit \ No newline at end of file diff --git a/scripts/install-win.bat b/scripts/install-win.bat deleted file mode 100644 index 63a5bf7..0000000 --- a/scripts/install-win.bat +++ /dev/null @@ -1,113 +0,0 @@ -@echo off - -REM Set paths -set EXE_PATH=%APPDATA%\jellyfin-rpc\jellyfin-rpc.exe -set JSON_PATH=%APPDATA%\jellyfin-rpc\main.json -set DOWNLOAD_URL=https://github.com/Radiicall/jellyfin-rpc/releases/latest/download/jellyfin-rpc.exe -set DOWNLOAD_DIR=%APPDATA%\jellyfin-rpc - -REM set -set JELLYFIN_URL=https://example.com -set JELLYFIN_API_KEY=abcdef0123456789 -set JELLYFIN_USERNAME=admin -set DISCORD_APPLICATION_ID=1053747938519679018 -set DISCORD_ENABLE_IMAGES=false - -echo =============================================================================== -echo JELLYFIN-RPC INSTALLATION -echo =============================================================================== -echo. - -REM Check if jellyfin-rpc folder exist -if not exist "%DOWNLOAD_DIR%" mkdir "%DOWNLOAD_DIR%" - -REM Check if jellyfin-rpc.exe is present -if exist "%EXE_PATH%" ( - echo jellyfin-rpc.exe is already present. & timeout /t 3 /nobreak >nul -) else ( - REM Downloading jellyfin-rpc binary - echo Downloading jellyfin-rpc binary from GitHub... & timeout /t 3 /nobreak >nul - curl -L %DOWNLOAD_URL% -o "%DOWNLOAD_DIR%\jellyfin-rpc.exe" -) - -rem Prompt the user for input -set /p JELLYFIN_URL=Enter Jellyfin URL "[%JELLYFIN_URL%]": -set /p JELLYFIN_API_KEY=Enter Jellyfin API key "[%JELLYFIN_API_KEY%]": -set /p JELLYFIN_USERNAME=Enter Jellyfin username "[%JELLYFIN_USERNAME%]": -set /p DISCORD_APPLICATION_ID=Enter Discord application ID "[%DISCORD_APPLICATION_ID%]": -set /p IMGUR_CLIENT_ID=Enter Imgur client ID (Leave empty if not using) "[%IMGUR_CLIENT_ID%]": -set /p IMAGES_ENABLE_IMAGES=Enable images (true/false) [%IMAGES_ENABLE_IMAGES%]: -set /p IMAGES_IMGUR_IMAGES=Enable images from Imgur (true/false) [%IMAGES_IMGUR_IMAGES%]: - - - -rem Output the JSON data to the file -echo { > main.json -echo "jellyfin": { >> main.json -echo "url": "%JELLYFIN_URL%", >> main.json -echo "api_key": "%JELLYFIN_API_KEY%", >> main.json -echo "username": "%JELLYFIN_USERNAME%" >> main.json -echo }, >> main.json -echo "discord": { >> main.json -echo "application_id": "%DISCORD_APPLICATION_ID%" >> main.json -echo }, >> main.json -echo "imgur": { >> main.json -echo "client_id": "%IMGUR_CLIENT_ID%" >> main.json -echo }, >> main.json -echo "images": { >> main.json -echo "enable_images": %IMAGES_ENABLE_IMAGES%, >> main.json -echo "imgur_images": %IMAGES_IMGUR_IMAGES% >> main.json -echo } >> main.json -echo } >> main.json - -REM Check if main.json is present -if exist "%JSON_PATH%" ( - echo main.json file is already present & timeout /t 3 /nobreak >nul - del "main.json" -) else ( - move "main.json" "%DOWNLOAD_DIR%\" >nul -) - -REM Check if NSSM is already installed -if exist "%DOWNLOAD_DIR%\nssm-2.24\win64\nssm.exe" ( - echo NSSM is already installed. & timeout /t 3 /nobreak >nul -) else ( - REM Download NSSM installer - echo Downloading and unzipping NSSM installer... & timeout /t 3 /nobreak >nul - curl -L https://nssm.cc/release/nssm-2.24.zip -o nssm.zip - - REM Unzip NSSM - powershell -Command "Expand-Archive -LiteralPath nssm.zip -DestinationPath ." - move /Y "nssm-2.24" "%DOWNLOAD_DIR%\" >nul - echo Deleting unnecessary nssm.zip file - del "nssm.zip" -) - -REM Install NSSM -echo Installing jellyfin-rpc service... & timeout /t 3 /nobreak >nul -%DOWNLOAD_DIR%\nssm-2.24\win64\nssm.exe install jellyfin-rpc "%EXE_PATH%" "-c %JSON_PATH% -i %DOWNLOAD_DIR%\urls.json" - -REM Start the executable using NSSM -echo Starting jellyfin-rpc service... & timeout /t 3 /nobreak >nul -set "psCommand=powershell -Command "Start-Process %DOWNLOAD_DIR%\nssm-2.24\win64\nssm.exe -Verb RunAs -ArgumentList 'start','jellyfin-rpc'"" -powershell -NoProfile -ExecutionPolicy Bypass -Command "%psCommand%" - - -REM Coded by xenoncolt.tk - -REM Check if the service is running -tasklist /fi "imagename eq jellyfin-rpc.exe" | find ":" > nul -if %errorlevel%==0 ( - echo =============================================================================== - echo JELLYFIN-RPC SERVICE IS RUNNING - echo =============================================================================== -) else ( - echo jellyfin-rpc service failed to start. -) -timeout /t 5 - -echo. -echo =============================================================================== -echo INSTALLATION COMPLETE! -echo =============================================================================== -pause >nul diff --git a/scripts/installer.py b/scripts/installer.py new file mode 100755 index 0000000..406f71d --- /dev/null +++ b/scripts/installer.py @@ -0,0 +1,328 @@ +#!/usr/bin/env python3 + +# Thanks to https://github.com/pogmommy for making the original macOS installer +# Thanks to https://github.com/xenoncolt for making the original Windows installer +# Their contributions made this universal script a lot easier to produce. + +import os +import subprocess +import platform +from time import sleep + +path = "" + +if platform.system() != "Windows": + if os.environ.get("XDG_CONFIG_HOME"): + path = os.environ["XDG_CONFIG_HOME"].removesuffix("/") + "/jellyfin-rpc/main.json" + else: + path = os.environ["HOME"].removesuffix("/") + "/.config/jellyfin-rpc/main.json" + + subprocess.run(["mkdir", "-p", path.removesuffix("main.json")]) +else: + path = os.environ["APPDATA"].removesuffix("\\") + "\jellyfin-rpc\main.json" + subprocess.run(["powershell", "-Command", f'mkdir "{path.removesuffix("main.json")}"'], stdout=subprocess.DEVNULL) + +print(""" +Welcome to the Jellyfin-RPC installer +[https://github.com/Radiicall/jellyfin-rpc#Setup] +""") + +current = "" + +if os.path.isfile(path): + print(f"Found existing config: {path}") + while True: + current = input("Use existing config? (y/N): ").lower() + if current == "n" or current == "y" or current == "": + break + print("Invalid input, please type y or n") + +if current == "n" or current == "": + content = "{" + + print("----------Jellyfin----------") + url = input("URL (include http/https): ") + api_key = input("API key: ") + username = input("username: ") + + content += f' "jellyfin": {{ "url": "{url}", "api_key": "{api_key}", "username": "{username}"' + + print("If you dont want anything else you can just press enter through all of these") + + while True: + val = input("Do you want to customize music display? (y/N): ").lower() + + if val == "n" or val == "": + break + elif val != "y": + print("Invalid input, please type y or n") + continue + + print("Enter what you would like to be shown in a comma seperated list") + print("Remember that it will show in the order you type it in") + print("Valid options are year, album and/or genres") + display = input("[Default: genres]: ") + + print("Choose the separator between the artist name and the info") + separator = input("[Default: -]: ") + + if display != "" and separator != "": + content += f', "music": {{ "display": "{display}", "separator": "{separator}" }}' + elif display != "" and separator == "": + content += f', "music": {{ "display": "{display}" }}' + elif display == "" and separator != "": + content += f', "music": {{ "separator": "{separator}" }}' + + break + + while True: + val = input("Do you want to blacklist media types or libraries? (y/N): ").lower() + + if val == "n" or val == "": + content += " }" + break + elif val != "y": + print("Invalid input, please type y or n") + continue + + print("You will first type in what media types to blacklist, this should be a comma separated list WITHOUT SPACES") + print("then after that you can choose what libraries to blacklist, this should ALSO be a comma separated list,") + print("there should be no spaces before or after the commas but there can be spaces in the names of libraries") + sleep(2) + + print("Media types 1/2") + media_types = input("Valid types are music, movie, episode and/or livetv [Default: ]: ").split(",") + + print("Libraries 2/2") + libraries = input("Enter libraries to blacklist [Default: ]: ").split(",") + + content += ', "blacklist": { "media_types": [ ' + for i in media_types: + content += f'"{i}", ' + + content = content.removesuffix(", ") + + content += ' ], "libraries": [' + for i in libraries: + content += f'"{i}", ' + + content = content.removesuffix(", ") + content += " ] } }" + + break + + print("----------Discord----------") + + content += ', "discord": {' + + appid = input("Enter your discord application ID [Default: 1053747938519679018]: ") + if appid != "": + content += f' "application_id": "{appid}"' + + while True: + val = input("Do you want custom buttons? (y/N): ").lower() + + if val == "n" or val == "": + content += " }" + break + elif val != "y": + print("Invalid input, please type y or n") + continue + + if appid != "": + content += "," + + content += ' "buttons": [ ' + + print("If you want one button to continue being dynamic then you have to specifically enter dynamic into both fields") + print("If you dont want any buttons to appear then you can leave everything blank here and it wont show anything.") + + print("Button 1/2") + name = input("Choose what the button will show [Default: dynamic]: ") + url = input("Choose where the button will direct to [Default: dynamic]: ") + + button1 = False + if name != "" and url != "": + content += f'{{ "name": "{name}", "url": "{url}" }}' + button1 = True + + print("Button 2/2") + name = input("Choose what the button will show [Default: dynamic]: ") + url = input("Choose where the button will direct to [Default: dynamic]: ") + + if name != "" and url != "" and button1 == True: + content += ", " + if name != "" and url != "": + content += f'{{ "name": "{name}", "url": "{url}" }}' + + content += " ] }" + break + + print("----------Images----------") + + while True: + val = input("Do you want images? (y/N): ").lower() + + if val == "n" or val == "": + break + elif val != "y": + print("Invalid input, please type y or n") + continue + + val2 = input("Do you want imgur images? (y/N): ").lower() + client_id = "" + + if val2 == "y": + client_id = input("Enter your imgur client id: ") + elif val2 != "n" and val2 != "": + print("Invalid input, please type y or n") + continue + + if val2 == "y": + content += f', "imgur": {{ "client_id": "{client_id}" }}, "images": {{ "enable_images": true, "imgur_images": true }}' + else: + content += f', "images": {{ "enable_images": true }}' + + break + + content += " }" + + print(f"\nPlacing config in '{path}'") + + file = open(path, "w") + file.write(content) + file.close() + + +print("\nDownloading Jellyfin-RPC") + +if platform.system() == "Windows": + path = path.removesuffix("main.json") + subprocess.run(["curl", "-o", path + "jellyfin-rpc.exe", "-L", "https://github.com/Radiicall/jellyfin-rpc/releases/latest/download/jellyfin-rpc.exe"]) + while True: + val = input("Do you want to autostart Jellyfin-RPC at login? (y/N): ").lower() + + if val == "n" or val == "": + break + if val != "y": + print("Invalid input, please type y or n") + continue + + if os.path.isfile(path + "winsw.exe"): + print("The script will prompt for administrator to remove the already installed service") + sleep(1) + subprocess.run[path + "winsw.exe", "uninstall"] + + subprocess.run(["curl", "-o", path + "winsw.exe", "-L", "https://github.com/winsw/winsw/releases/latest/download/WinSW-x64.exe"]) + + content = f""" + jellyfin-rpc + Jellyfin-RPC + This service is running Jellyfin-RPC for rich presence support + {path}jellyfin-rpc.exe + -c {path}main.json -i {path}urls.json +""" + + file = open(path + "winsw.xml", "w") + file.write(content) + file.close() + + print("The program will now ask you for administrator rights twice, this is so the service can be installed!") + print("waiting 5 seconds") + sleep(5) + + subprocess.run([path + "winsw.exe", "install"]) + subprocess.run([path + "winsw.exe", "start"]) + + print("Autostart has been set up, jellyfin-rpc should now launch at login\nas long as there are no issues with the configuration") + +elif platform.system() == "Darwin": + subprocess.run(["curl", "-o", "/usr/local/bin/jellyfin-rpc", "-L", "https://github.com/Radiicall/jellyfin-rpc/releases/latest/download/jellyfin-rpc-x86_64-linux"]) + subprocess.run(["chmod", "+x", "/usr/local/bin/jellyfin-rpc"]) + + while True: + val = input("Do you want to autostart Jellyfin-RPC at login? (y/N): ").lower() + + if val == "n" or val == "": + break + if val != "y": + print("Invalid input, please type y or n") + continue + + if subprocess.run(["pgrep", "-xq", "--", "'jellyfin-rpc'"]).returncode == 0: + subprocess.run(["killall", "jellyfin-rpc"]) + + if "Jellyfin-RPC" in subprocess.Popen("launchctl list", shell=True, stdout=subprocess.PIPE).stdout.read().decode(): + subprocess.run(["launchctl", "remove", "Jellyfin-RPC"]) + + content = """ + + + + Label + Jellyfin-RPC + Program + /usr/local/bin/jellyfin-rpc + RunAtLoad + + StandardErrorPath + /tmp/jellyfinrpc.local.stderr.txt + StandardOutPath + /tmp/jellyfinrpc.local.stdout.txt + +""" + + path = os.environ["HOME"] + "/Library/LaunchAgents/jellyfinrpc.local.plist" + + file = open(path, "w") + file.write(content) + file.close() + + subprocess.run(["chmod", "644", path]) + subprocess.run(["launchctl", "load", path]) + + print("Jellyfin RPC is now set up to start at login.") + print("If needed, you can run Jellyfin RPC at any time by running 'jellyfin-rpc' in a terminal.") + break +else: + subprocess.run(["mkdir", "-p", os.environ["HOME"].removesuffix("/") + "/.local/bin"]) + subprocess.run(["curl", "-o", os.environ["HOME"].removesuffix("/") + "/.local/bin/jellyfin-rpc", "-L", "https://github.com/Radiicall/jellyfin-rpc/releases/latest/download/jellyfin-rpc-x86_64-linux"]) + subprocess.run(["chmod", "+x", os.environ["HOME"].removesuffix("/") + "/.local/bin/jellyfin-rpc"]) + + if os.environ.get("XDG_CONFIG_HOME"): + path = os.environ["XDG_CONFIG_HOME"].removesuffix("/") + "/systemd/user/jellyfin-rpc.service" + else: + path = os.environ["HOME"].removesuffix("/") + "/.config/systemd/user/jellyfin-rpc.service" + + while True: + val = input("Do you want to autostart Jellyfin-RPC at login using Systemd? (y/N): ").lower() + + if val == "n" or val == "": + break + if val != "y": + print("Invalid input, please type y or n") + continue + + print(f"\nSetting up service file in {path}") + + subprocess.run(["mkdir", "-p", path.removesuffix("jellyfin-rpc.service")]) + + content = f"""[Unit] +Description=Jellyfin-RPC Service +Documentation=https://github.com/Radiicall/jellyfin-rpc +After=network.target + +[Service] +Type=simple +ExecStart={os.environ["HOME"].removesuffix("/") + "/.local/bin/jellyfin-rpc"} +Restart=on-failure + +[Install] +WantedBy=default.target""" + + file = open(path, "w") + file.write(content) + file.close() + + subprocess.run(["systemctl", "--user", "daemon-reload"]) + subprocess.run(["systemctl", "--user", "enable", "--now", "jellyfin-rpc.service"]) diff --git a/scripts/uninstall-macos.sh b/scripts/uninstall-macos.sh deleted file mode 100755 index bcea96a..0000000 --- a/scripts/uninstall-macos.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/zsh -# A script to autoamtically uninstall jellyfin-rpc on mac -if pgrep -xq -- "jellyfin-rpc"; then - killall jellyfin-rpc # Kill jellyfin-rpc if it is running -fi -if launchctl list | grep Jellyfin-RPC; then - launchctl remove Jellyfin-RPC # Unload Jellyfin-RPC launchagent if it is loaded -fi -rm ~/Library/LaunchAgents/jellyfinrpc.local.plist #remove launch agent -rm -rf ~/.config/jellyfin-rpc #remove config file -rm /usr/local/bin/jellyfin-rpc #remove binary -echo "Uninstall complete!" diff --git a/scripts/uninstall-win.bat b/scripts/uninstall-win.bat deleted file mode 100644 index b1ffe7e..0000000 --- a/scripts/uninstall-win.bat +++ /dev/null @@ -1,54 +0,0 @@ -@echo off - -REM Check if running with administrator privileges -net session >nul 2>&1 -if %errorlevel% == 0 ( - echo Running with administrator privileges -) else ( - echo ERROR: This batch file must be run with administrator privileges. - echo Please right-click on the batch file and select "Run as administrator" - pause >nul - exit /b -) - - - -echo =============================================================================== -echo JELLYFIN-RPC UNINSTALLATION -echo =============================================================================== -echo. -timeout /t 3 >nul - -REM set path -set NSSM_PATH=%APPDATA%\jellyfin-rpc\nssm-2.24\win64\nssm.exe -set MAIN_PATH=%APPDATA%\jellyfin-rpc - - - -echo Stopping jellyfin-rpc from service & timeout /t 5 >nul -%NSSM_PATH% stop jellyfin-rpc - -timeout /t 2 >nul - -echo =============================================================================== -echo JELLYFIN-RPC STOPPED! -echo =============================================================================== -echo. - - -set /p =Hit ENTER to continue uninstallation... -echo Removing jellyfin-rpc from service... -%NSSM_PATH% remove jellyfin-rpc - -timeout /t 5 >nul - -echo Removing jellyfin-rpc folder... -rd /s /q "%APPDATA%\jellyfin-rpc" -echo jellyfin-rpc folder removed successfully. - -echo. -echo =============================================================================== -echo UNINSTALLATION COMPLETE! -echo =============================================================================== -pause >nul - diff --git a/scripts/uninstaller.py b/scripts/uninstaller.py new file mode 100755 index 0000000..008c161 --- /dev/null +++ b/scripts/uninstaller.py @@ -0,0 +1,55 @@ +import platform +import os +import subprocess +from time import sleep +import shutil + +# Thanks to https://github.com/pogmommy for making the original macOS uninstaller +# Thanks to https://github.com/xenoncolt for making the original Windows uninstaller + +print("Welcome to the Jellyfin-RPC uninstaller") +input("Hit enter to continue...") + +if platform.system() != "Windows": + if os.environ.get("XDG_CONFIG_HOME"): + path = os.environ["XDG_CONFIG_HOME"].removesuffix("/") + "/jellyfin-rpc/" + else: + path = os.environ["HOME"].removesuffix("/") + "/.config/jellyfin-rpc/" +else: + path = os.environ["APPDATA"].removesuffix("\\") + "\\jellyfin-rpc\\" + +if platform.system() == "Windows": + if os.path.isfile(path + "winsw.exe"): + print("The script will ask for admin rights to remove the autostart service") + print("waiting 5 seconds") + sleep(5) + subprocess.run([path + "winsw.exe", "uninstall"]) + + shutil.rmtree(path) +elif platform.system() == "Darwin": + if subprocess.run(["pgrep", "-xq", "--", "'jellyfin-rpc'"]).returncode == 0: + subprocess.run(["killall", "jellyfin-rpc"]) + + if "Jellyfin-RPC" in subprocess.Popen("launchctl list", shell=True, stdout=subprocess.PIPE).stdout.read().decode(): + subprocess.run(["launchctl", "remove", "Jellyfin-RPC"]) + + servicepath = os.environ["HOME"].removesuffix("/") + "/Library/LaunchAgents/jellyfinrpc.local.plist" + if os.path.isfile(servicepath): + os.remove(servicepath) + shutil.rmtree(path) + os.remove("/usr/local/bin/jellyfin-rpc") +else: + if "jellyfin-rpc.service" in subprocess.Popen("systemctl --user list-units", shell=True, stdout=subprocess.PIPE).stdout.read().decode(): + subprocess.run(["systemctl", "--user", "disable", "--now", "jellyfin-rpc.service"]) + + if subprocess.run(["pgrep", "-xq", "--", "'jellyfin-rpc'"]).returncode == 0: + subprocess.run(["killall", "jellyfin-rpc"]) + + servicepath = path.removesuffix("jellyfin-rpc/") + "systemd/user/jellyfin-rpc.service" + if os.path.isfile(servicepath): + subprocess.run(["rm", servicepath]) + shutil.rmtree(path) + os.remove(os.environ["HOME"].removesuffix("/") + "/.local/bin/jellyfin-rpc") + +print("Uninstall complete!") +sleep(5)