mirror of
https://github.com/phin05/discord-rich-presence-plex
synced 2024-11-24 18:43:02 +00:00
Minor refactoring and tweaks
This commit is contained in:
parent
1c72a08041
commit
cf19147b6c
5 changed files with 36 additions and 38 deletions
|
@ -165,7 +165,7 @@ The "Display current activity as a status message" setting must be enabled in Di
|
|||
|
||||
## Configuration - Environment Variables
|
||||
|
||||
* `PLEX_SERVER_NAME` - Name of the Plex Media Server you wish to connect to. Used only during the initial setup (when there are no users in the config) for adding a server to the config after 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_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.
|
||||
|
||||
## Run with Docker
|
||||
|
||||
|
@ -201,7 +201,7 @@ For example, if the environment variable `XDG_RUNTIME_DIR` is set to `/run/user/
|
|||
docker run -v ./drpp:/app/data -v /run/user/1000:/run/app:ro -d --restart unless-stopped --name drpp ghcr.io/phin05/discord-rich-presence-plex:latest
|
||||
```
|
||||
|
||||
If you're running the container for the first time (when there are no users in the config), make sure that the `PLEX_SERVER_NAME` environment variable is set (see the [environment variables](#configuration---environment-variables) section above), and check the container logs for the authentication link.
|
||||
If you're running the container for the first time (when there are no users in the config), make sure that the `DRPP_PLEX_SERVER_NAME_INPUT` environment variable is set (see the [environment variables](#configuration---environment-variables) section above), and check the container logs for the authentication link.
|
||||
|
||||
### Containerised Discord
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ plexClientID = "discord-rich-presence-plex"
|
|||
discordClientID = "413407336082833418"
|
||||
|
||||
dataDirectoryPath = "data"
|
||||
configFilePathRoot = os.path.join(dataDirectoryPath, "config")
|
||||
configFilePathBase = os.path.join(dataDirectoryPath, "config")
|
||||
cacheFilePath = os.path.join(dataDirectoryPath, "cache.json")
|
||||
logFilePath = os.path.join(dataDirectoryPath, "console.log")
|
||||
|
||||
|
@ -16,4 +16,5 @@ isUnix = sys.platform in ["linux", "darwin"]
|
|||
processID = os.getpid()
|
||||
isInteractive = sys.stdin and sys.stdin.isatty()
|
||||
isInContainer = os.environ.get("DRPP_IS_IN_CONTAINER", "") == "true"
|
||||
runtimeDirectory = "/run/app"
|
||||
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"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from config.constants import configFilePathRoot
|
||||
from config.constants import configFilePathBase
|
||||
from utils.dict import copyDict
|
||||
from utils.logging import logger
|
||||
import json
|
||||
|
@ -36,12 +36,12 @@ def loadConfig() -> None:
|
|||
global configFileExtension, configFileType, configFilePath
|
||||
doesFileExist = False
|
||||
for i, (fileExtension, fileType) in enumerate(supportedConfigFileExtensions.items()):
|
||||
doesFileExist = os.path.isfile(f"{configFilePathRoot}.{fileExtension}")
|
||||
doesFileExist = os.path.isfile(f"{configFilePathBase}.{fileExtension}")
|
||||
isFirstItem = i == 0
|
||||
if doesFileExist or isFirstItem:
|
||||
configFileExtension = fileExtension
|
||||
configFileType = fileType
|
||||
configFilePath = f"{configFilePathRoot}.{configFileExtension}"
|
||||
configFilePath = f"{configFilePathBase}.{configFileExtension}"
|
||||
if doesFileExist:
|
||||
break
|
||||
if doesFileExist:
|
||||
|
@ -52,7 +52,7 @@ def loadConfig() -> None:
|
|||
else:
|
||||
loadedConfig = json.load(configFile) or {}
|
||||
except:
|
||||
os.rename(configFilePath, f"{configFilePathRoot}-{time.time():.0f}.{configFileExtension}")
|
||||
os.rename(configFilePath, f"{configFilePathBase}-{time.time():.0f}.{configFileExtension}")
|
||||
logger.exception("Failed to parse the config file. A new one will be created.")
|
||||
else:
|
||||
copyDict(loadedConfig, config)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from config.constants import discordClientID, isUnix, processID, runtimeDirectory
|
||||
from config.constants import discordClientID, isUnix, processID, ipcPipeBase
|
||||
from typing import Any, Optional
|
||||
from utils.logging import logger
|
||||
import asyncio
|
||||
|
@ -10,17 +10,15 @@ import time
|
|||
|
||||
class DiscordIpcService:
|
||||
|
||||
def __init__(self, ipcPipeNumber: Optional[int]):
|
||||
ipcPipeNumber = ipcPipeNumber or -1
|
||||
ipcPipeNumbers = range(10) if ipcPipeNumber == -1 else [ipcPipeNumber]
|
||||
ipcPipeBase = (runtimeDirectory if os.path.isdir(runtimeDirectory) else os.environ.get("XDG_RUNTIME_DIR", os.environ.get("TMPDIR", os.environ.get("TMP", os.environ.get("TEMP", "/tmp"))))) if isUnix else r"\\?\pipe"
|
||||
self.ipcPipes: list[str] = []
|
||||
for ipcPipeNumber in ipcPipeNumbers:
|
||||
pipeFilename = f"discord-ipc-{ipcPipeNumber}"
|
||||
self.ipcPipes.append(os.path.join(ipcPipeBase, pipeFilename))
|
||||
if ipcPipeBase == os.environ.get("XDG_RUNTIME_DIR"):
|
||||
self.ipcPipes.append(os.path.join(ipcPipeBase, "app", "com.discordapp.Discord", pipeFilename))
|
||||
self.ipcPipes.append(os.path.join(ipcPipeBase, ".flatpak", "com.discordapp.Discord", "xdg-run", pipeFilename))
|
||||
def __init__(self, pipeNumber: Optional[int]):
|
||||
pipeNumber = pipeNumber or -1
|
||||
pipeNumbers = range(10) if pipeNumber == -1 else [pipeNumber]
|
||||
self.pipes: list[str] = []
|
||||
for pipeNumber in pipeNumbers:
|
||||
pipeFilename = f"discord-ipc-{pipeNumber}"
|
||||
self.pipes.append(os.path.join(ipcPipeBase, pipeFilename))
|
||||
self.pipes.append(os.path.join(ipcPipeBase, "app", "com.discordapp.Discord", pipeFilename))
|
||||
self.pipes.append(os.path.join(ipcPipeBase, ".flatpak", "com.discordapp.Discord", "xdg-run", pipeFilename))
|
||||
self.loop: Optional[asyncio.AbstractEventLoop] = None
|
||||
self.pipeReader: Optional[asyncio.StreamReader] = None
|
||||
self.pipeWriter: Optional[asyncio.StreamWriter] = None
|
||||
|
@ -29,24 +27,24 @@ class DiscordIpcService:
|
|||
async def handshake(self) -> None:
|
||||
if not self.loop:
|
||||
return
|
||||
for ipcPipe in self.ipcPipes:
|
||||
for pipe in self.pipes:
|
||||
try:
|
||||
if isUnix:
|
||||
self.pipeReader, self.pipeWriter = await asyncio.open_unix_connection(ipcPipe) # pyright: ignore[reportGeneralTypeIssues,reportUnknownMemberType]
|
||||
self.pipeReader, self.pipeWriter = await asyncio.open_unix_connection(pipe) # pyright: ignore[reportGeneralTypeIssues,reportUnknownMemberType]
|
||||
else:
|
||||
self.pipeReader = asyncio.StreamReader()
|
||||
self.pipeWriter = (await self.loop.create_pipe_connection(lambda: asyncio.StreamReaderProtocol(self.pipeReader), ipcPipe))[0] # pyright: ignore[reportGeneralTypeIssues,reportUnknownMemberType]
|
||||
self.pipeWriter = (await self.loop.create_pipe_connection(lambda: asyncio.StreamReaderProtocol(self.pipeReader), pipe))[0] # pyright: ignore[reportGeneralTypeIssues,reportUnknownMemberType]
|
||||
self.write(0, { "v": 1, "client_id": discordClientID })
|
||||
if await self.read():
|
||||
self.connected = True
|
||||
logger.info(f"Connected to Discord IPC pipe {ipcPipe}")
|
||||
logger.info(f"Connected to Discord IPC pipe {pipe}")
|
||||
break
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
except:
|
||||
logger.exception(f"An unexpected error occured while connecting to Discord IPC pipe {ipcPipe}")
|
||||
logger.exception(f"An unexpected error occured while connecting to Discord IPC pipe {pipe}")
|
||||
if not self.connected:
|
||||
logger.error(f"Discord IPC pipe not found (attempted pipes: {', '.join(self.ipcPipes)})")
|
||||
logger.error(f"Discord IPC pipe not found (attempted pipes: {', '.join(self.pipes)})")
|
||||
|
||||
async def read(self) -> Optional[Any]:
|
||||
if not self.pipeReader:
|
||||
|
|
23
main.py
23
main.py
|
@ -1,10 +1,11 @@
|
|||
from config.constants import isInContainer, runtimeDirectory
|
||||
from utils.logging import logger
|
||||
import os
|
||||
import sys
|
||||
|
||||
if isInContainer:
|
||||
if not os.path.isdir(runtimeDirectory):
|
||||
print(f"Runtime directory does not exist. Make sure that it is mounted into the container at {runtimeDirectory}")
|
||||
logger.error(f"Runtime directory does not exist. Ensure that it is mounted into the container at {runtimeDirectory}")
|
||||
exit(1)
|
||||
statResult = os.stat(runtimeDirectory)
|
||||
os.system(f"chown -R {statResult.st_uid}:{statResult.st_gid} {os.path.dirname(os.path.realpath(__file__))}")
|
||||
|
@ -22,12 +23,10 @@ else:
|
|||
for packageName, packageVersion in requiredPackages.items():
|
||||
if packageName not in installedPackages:
|
||||
package = f"{packageName}{f'=={packageVersion}' if packageVersion else ''}"
|
||||
print(f"Installing missing dependency: {package}")
|
||||
logger.info(f"Installing missing dependency: {package}")
|
||||
subprocess.run([sys.executable, "-m", "pip", "install", "-U", package], check = True)
|
||||
except Exception as e:
|
||||
import traceback
|
||||
traceback.print_exception(e)
|
||||
print("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")
|
||||
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")
|
||||
|
||||
from config.constants import dataDirectoryPath, logFilePath, name, version, isInteractive
|
||||
from core.config import config, loadConfig, saveConfig
|
||||
|
@ -35,15 +34,15 @@ from core.discord import DiscordIpcService
|
|||
from core.plex import PlexAlertListener, initiateAuth, getAuthToken
|
||||
from typing import Optional
|
||||
from utils.cache import loadCache
|
||||
from utils.logging import logger, formatter
|
||||
from utils.logging import formatter
|
||||
from utils.text import formatSeconds
|
||||
import logging
|
||||
import models.config
|
||||
import time
|
||||
|
||||
def init() -> None:
|
||||
if not os.path.exists(dataDirectoryPath):
|
||||
os.mkdir(dataDirectoryPath)
|
||||
if not os.path.isdir(dataDirectoryPath):
|
||||
os.makedirs(dataDirectoryPath)
|
||||
for oldFilePath in ["config.json", "cache.json", "console.log"]:
|
||||
if os.path.isfile(oldFilePath):
|
||||
os.rename(oldFilePath, os.path.join(dataDirectoryPath, oldFilePath))
|
||||
|
@ -90,7 +89,7 @@ def authNewUser() -> Optional[models.config.User]:
|
|||
authToken = getAuthToken(id, code)
|
||||
if authToken:
|
||||
logger.info("Authentication successful")
|
||||
serverName = os.environ.get("PLEX_SERVER_NAME")
|
||||
serverName = os.environ.get("DRPP_PLEX_SERVER_NAME_INPUT")
|
||||
if not serverName:
|
||||
serverName = input("Enter the name of the Plex Media Server you wish to connect to: ") if isInteractive else "ServerName"
|
||||
return { "token": authToken, "servers": [{ "name": serverName }] }
|
||||
|
@ -98,10 +97,10 @@ def authNewUser() -> Optional[models.config.User]:
|
|||
else:
|
||||
logger.info(f"Authentication timed out ({formatSeconds(180)})")
|
||||
|
||||
def testIpc(ipcPipeNumber: int) -> None:
|
||||
def testIpc(pipeNumber: int) -> None:
|
||||
init()
|
||||
logger.info("Testing Discord IPC connection")
|
||||
discordIpcService = DiscordIpcService(ipcPipeNumber)
|
||||
discordIpcService = DiscordIpcService(pipeNumber)
|
||||
discordIpcService.connect()
|
||||
discordIpcService.setActivity({
|
||||
"details": "details",
|
||||
|
@ -124,6 +123,6 @@ if __name__ == "__main__":
|
|||
elif mode == "test-ipc":
|
||||
testIpc(int(sys.argv[2]) if len(sys.argv) > 2 else -1)
|
||||
else:
|
||||
print(f"Invalid mode: {mode}")
|
||||
logger.error(f"Invalid mode: {mode}")
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
|
Loading…
Reference in a new issue