diff --git a/Dockerfile b/Dockerfile index 574bb1f..b876a7d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,4 +7,5 @@ COPY requirements.txt . RUN pip install -U -r requirements.txt --no-cache-dir COPY . . ENV DRPP_IS_IN_CONTAINER=true +ENV DRPP_NO_PIP_INSTALL=true ENTRYPOINT ["python", "main.py"] diff --git a/README.md b/README.md index bd666fb..c6bbaa6 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ The config file is stored in a directory named `data`. * `posters` * `enabled` (boolean, default: `false`) - Displays media posters if enabled. Requires `imgurClientID`. * `imgurClientID` (string, default: `""`) - [Obtention Instructions](#obtaining-an-imgur-client-id) - * `maxSize` (int, default: `256`) + * `maxSize` (int, default: `256`) - Maximum width and maximum height to use while downscaling posters before uploading them. * `buttons` (list) - [Information](#buttons) * `label` (string) - The label to be displayed on the button. * `url` (string) - A web address or a [dynamic URL placeholder](#dynamic-button-urls). @@ -64,7 +64,7 @@ The config file is stored in a directory named `data`. Discord can display up to 2 buttons in your Rich Presence. -Due to a strange Discord bug, these buttons are unresponsive or exhibit strange behaviour towards your own clicks, but other users are able to click on them to open their corresponding URLs. +Due to a strange Discord bug, these buttons may be unresponsive or exhibit strange behaviour towards your own clicks, but other users are able to click on them to open their corresponding URLs. #### Dynamic Button URLs @@ -90,8 +90,9 @@ display: posters: enabled: true imgurClientID: 9e9sf637S8bRp4z + maxSize: 256 buttons: - - label: IMDb Link + - label: IMDb url: dynamic:imdb - label: My YouTube Channel url: https://www.youtube.com/channel/me @@ -123,11 +124,12 @@ users: "useRemainingTime": false, "posters": { "enabled": true, - "imgurClientID": "9e9sf637S8bRp4z" + "imgurClientID": "9e9sf637S8bRp4z", + "maxSize": 256 }, "buttons": [ { - "label": "IMDb Link", + "label": "IMDb", "url": "dynamic:imdb" }, { @@ -145,7 +147,6 @@ users: }, { "name": "A Friend's Server", - "listenForUser": "xyz", "whitelistedLibraries": [ "Movies" ] @@ -167,6 +168,7 @@ The "Display current activity as a status message" setting must be enabled in Di ## Configuration - Environment Variables * `DRPP_PLEX_SERVER_NAME_INPUT` - This is used only during the initial setup (when there are no users in the config) as the name of the Plex server to be added to the config file after user authentication. If this isn't set, in interactive environments, the user is prompted for an input, and in non-interactive environments, "ServerName" is used as a placeholder, which can later be changed by editing the config file and restarting the script. +* `DRPP_NO_PIP_INSTALL` - Automatic invocation of pip to install missing dependencies is skipped if this is set to `true`. ## Run with Docker @@ -247,7 +249,7 @@ services: volumes: - ./kasmcord:/run/user/1000 user: "0" - entrypoint: sh -c "chown -R kasm-user:kasm-user /run/user/1000 && su kasm-user -c '/dockerstartup/kasm_default_profile.sh /dockerstartup/vnc_startup.sh /dockerstartup/kasm_startup.sh'" + entrypoint: sh -c "chmod 700 /run/user/1000 && chown -R kasm-user:kasm-user /run/user/1000 && su kasm-user -c '/dockerstartup/kasm_default_profile.sh /dockerstartup/vnc_startup.sh /dockerstartup/kasm_startup.sh'" drpp: container_name: drpp image: ghcr.io/phin05/discord-rich-presence-plex:latest diff --git a/config/constants.py b/config/constants.py index 8fe061a..f95224d 100644 --- a/config/constants.py +++ b/config/constants.py @@ -15,6 +15,7 @@ logFilePath = os.path.join(dataDirectoryPath, "console.log") isUnix = sys.platform in ["linux", "darwin"] processID = os.getpid() isInteractive = sys.stdin and sys.stdin.isatty() +noPipInstall = os.environ.get("DRPP_NO_PIP_INSTALL", "") == "true" isInContainer = os.environ.get("DRPP_IS_IN_CONTAINER", "") == "true" runtimeDirectory = "/run/app" if isInContainer else os.environ.get("XDG_RUNTIME_DIR", os.environ.get("TMPDIR", os.environ.get("TMP", os.environ.get("TEMP", "/tmp")))) ipcPipeBase = runtimeDirectory if isUnix else r"\\?\pipe" diff --git a/main.py b/main.py index f718479..958c11e 100644 --- a/main.py +++ b/main.py @@ -1,7 +1,6 @@ from config.constants import isInContainer, runtimeDirectory, uid, gid, containerCwd, noRuntimeDirChown from utils.logging import logger import os -import sys if isInContainer: if not os.path.isdir(runtimeDirectory): @@ -23,20 +22,24 @@ if isInContainer: os.setuid(uid) # pyright: ignore[reportAttributeAccessIssue,reportUnknownMemberType] else: logger.warning(f"Not running as the superuser. Manually ensure appropriate ownership of mounted contents") -else: + +from config.constants import noPipInstall +import sys + +if not noPipInstall: try: import subprocess def parsePipPackages(packagesStr: str) -> dict[str, str]: - return { packageSplit[0]: packageSplit[1] if len(packageSplit) > 1 else "" for packageSplit in [package.split("==") for package in packagesStr.splitlines()] } + return { packageSplit[0].lower(): packageSplit[1] if len(packageSplit) > 1 else "" for packageSplit in [package.split("==") for package in packagesStr.splitlines()] } pipFreezeResult = subprocess.run([sys.executable, "-m", "pip", "freeze"], stdout = subprocess.PIPE, text = True, check = True) installedPackages = parsePipPackages(pipFreezeResult.stdout) with open("requirements.txt", "r", encoding = "UTF-8") as requirementsFile: requiredPackages = parsePipPackages(requirementsFile.read()) - for packageName, packageVersion in requiredPackages.items(): - if packageName not in installedPackages: - package = f"{packageName}{f'=={packageVersion}' if packageVersion else ''}" - logger.info(f"Installing missing dependency: {package}") - subprocess.run([sys.executable, "-m", "pip", "install", "-U", package], check = True) + for packageName, requiredPackageVersion in requiredPackages.items(): + installedPackageVersion = installedPackages.get(packageName, "none") + if installedPackageVersion != requiredPackageVersion: + logger.info(f"Installing dependency: {packageName} (required: {requiredPackageVersion}, installed: {installedPackageVersion})") + subprocess.run([sys.executable, "-m", "pip", "install", "-U", f"{packageName}=={requiredPackageVersion}"], check = True) except Exception as e: logger.exception("An unexpected error occured during automatic installation of dependencies. Install them manually by running the following command: python -m pip install -U -r requirements.txt")