2024-02-07 10:17:38 +05:30
from config . constants import isInContainer , runtimeDirectory , uid , gid , containerCwd , noRuntimeDirChown
2024-02-07 01:40:41 +05:30
from utils . logging import logger
2023-10-01 19:11:42 +05:30
import os
2024-01-31 21:20:19 +05:30
if isInContainer :
if not os . path . isdir ( runtimeDirectory ) :
2024-02-07 01:40:41 +05:30
logger . error ( f " Runtime directory does not exist. Ensure that it is mounted into the container at { runtimeDirectory } " )
2024-01-31 21:20:19 +05:30
exit ( 1 )
2024-02-10 12:41:18 +05:30
if os . geteuid ( ) == 0 : # pyright: ignore[reportAttributeAccessIssue,reportUnknownMemberType]
2024-02-07 10:17:38 +05:30
if uid == - 1 or gid == - 1 :
logger . warning ( f " Environment variable(s) DRPP_UID and/or DRPP_GID are/is not set. Manually ensure appropriate ownership of { runtimeDirectory } " )
statResult = os . stat ( runtimeDirectory )
uid , gid = statResult . st_uid , statResult . st_gid
else :
if noRuntimeDirChown :
2024-08-30 20:29:02 +05:30
logger . warning ( f " Environment variable DRPP_NO_RUNTIME_DIR_CHOWN is set to true. Manually ensure appropriate ownership of { runtimeDirectory } " )
2024-02-07 10:17:38 +05:30
else :
os . system ( f " chmod 700 { runtimeDirectory } " )
os . system ( f " chown -R { uid } : { gid } { runtimeDirectory } " )
os . system ( f " chown -R { uid } : { gid } { containerCwd } " )
2024-02-10 12:41:18 +05:30
os . setgid ( gid ) # pyright: ignore[reportAttributeAccessIssue,reportUnknownMemberType]
os . setuid ( uid ) # pyright: ignore[reportAttributeAccessIssue,reportUnknownMemberType]
2024-02-07 10:17:38 +05:30
else :
2024-08-30 20:29:02 +05:30
logger . warning ( " Not running as the superuser. Manually ensure appropriate ownership of mounted contents " )
2024-02-10 20:52:27 +05:30
from config . constants import noPipInstall
import sys
if not noPipInstall :
2023-11-05 10:54:45 +05:30
try :
import subprocess
def parsePipPackages ( packagesStr : str ) - > dict [ str , str ] :
2024-02-10 20:52:27 +05:30
return { packageSplit [ 0 ] . lower ( ) : packageSplit [ 1 ] if len ( packageSplit ) > 1 else " " for packageSplit in [ package . split ( " == " ) for package in packagesStr . splitlines ( ) ] }
2023-11-05 10:54:45 +05:30
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 ( ) )
2024-02-10 20:52:27 +05:30
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 )
2023-11-05 10:54:45 +05:30
except Exception as e :
2024-02-07 01:40:41 +05:30
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 " )
2023-10-01 19:11:42 +05:30
2024-08-30 20:29:02 +05:30
from config . constants import dataDirectoryPath , logFilePath , name , version , isInteractive , plexServerNameInput
2023-11-04 23:43:42 +05:30
from core . config import config , loadConfig , saveConfig
from core . discord import DiscordIpcService
2023-11-05 10:54:45 +05:30
from core . plex import PlexAlertListener , initiateAuth , getAuthToken
2023-11-04 23:43:42 +05:30
from typing import Optional
from utils . cache import loadCache
2024-02-07 01:40:41 +05:30
from utils . logging import formatter
2023-11-04 23:43:42 +05:30
from utils . text import formatSeconds
2022-05-11 01:53:12 +05:30
import logging
2023-11-04 23:43:42 +05:30
import models . config
2022-05-11 05:33:51 +05:30
import time
2022-05-11 01:53:12 +05:30
2023-11-05 15:54:36 +05:30
def init ( ) - > None :
2024-02-07 01:40:41 +05:30
if not os . path . isdir ( dataDirectoryPath ) :
os . makedirs ( dataDirectoryPath )
2023-10-01 19:11:42 +05:30
for oldFilePath in [ " config.json " , " cache.json " , " console.log " ] :
if os . path . isfile ( oldFilePath ) :
2023-11-04 23:43:42 +05:30
os . rename ( oldFilePath , os . path . join ( dataDirectoryPath , oldFilePath ) )
2022-05-22 22:33:17 +05:30
loadConfig ( )
if config [ " logging " ] [ " debug " ] :
logger . setLevel ( logging . DEBUG )
if config [ " logging " ] [ " writeToFile " ] :
fileHandler = logging . FileHandler ( logFilePath )
fileHandler . setFormatter ( formatter )
logger . addHandler ( fileHandler )
logger . info ( " %s - v %s " , name , version )
loadCache ( )
2023-11-05 15:54:36 +05:30
def main ( ) - > None :
2023-11-04 23:43:42 +05:30
if not config [ " users " ] :
2023-11-05 01:09:30 +05:30
logger . info ( " No users found in the config file " )
2023-11-05 10:54:45 +05:30
user = authNewUser ( )
2023-11-04 23:43:42 +05:30
if not user :
2024-01-31 21:20:19 +05:30
exit ( 1 )
2023-11-04 23:43:42 +05:30
config [ " users " ] . append ( user )
saveConfig ( )
plexAlertListeners = [ PlexAlertListener ( user [ " token " ] , server ) for user in config [ " users " ] for server in user [ " servers " ] ]
try :
if isInteractive :
while True :
userInput = input ( )
if userInput in [ " exit " , " quit " ] :
raise KeyboardInterrupt
2024-08-31 01:40:46 +05:30
elif userInput == " reload-config " :
loadConfig ( )
print ( " Config reloaded from file " )
else :
print ( " Unrecognised command " )
2023-11-04 23:43:42 +05:30
else :
while True :
time . sleep ( 3600 )
except KeyboardInterrupt :
for plexAlertListener in plexAlertListeners :
plexAlertListener . disconnect ( )
2023-11-05 10:54:45 +05:30
def authNewUser ( ) - > Optional [ models . config . User ] :
id , code , url = initiateAuth ( )
2023-11-04 23:43:42 +05:30
logger . info ( " Open the below URL in your web browser and sign in: " )
2023-11-05 10:54:45 +05:30
logger . info ( url )
2023-11-04 23:43:42 +05:30
time . sleep ( 5 )
for i in range ( 35 ) :
2023-11-05 10:54:45 +05:30
logger . info ( f " Checking whether authentication is successful ( { formatSeconds ( ( i + 1 ) * 5 ) } ) " )
authToken = getAuthToken ( id , code )
if authToken :
2023-11-04 23:43:42 +05:30
logger . info ( " Authentication successful " )
2024-08-30 20:29:02 +05:30
serverName = plexServerNameInput
2023-11-04 23:43:42 +05:30
if not serverName :
2024-08-30 20:29:02 +05:30
if isInteractive :
serverName = input ( " Enter the name of the Plex Media Server to connect to: " )
else :
serverName = " ServerName "
logger . warning ( " Environment variable DRPP_PLEX_SERVER_NAME_INPUT is not set and the environment is non-interactive " )
logger . warning ( " \" ServerName \" will be used as a placeholder for the name of the Plex Media Server to connect to " )
logger . warning ( " Change this by editing the config file and restarting the script " )
2023-11-05 10:54:45 +05:30
return { " token " : authToken , " servers " : [ { " name " : serverName } ] }
2022-05-11 07:49:49 +05:30
time . sleep ( 5 )
2022-05-22 22:33:17 +05:30
else :
2023-11-04 23:43:42 +05:30
logger . info ( f " Authentication timed out ( { formatSeconds ( 180 ) } ) " )
2024-02-07 01:40:41 +05:30
def testIpc ( pipeNumber : int ) - > None :
2023-11-05 15:54:36 +05:30
init ( )
2023-11-04 23:43:42 +05:30
logger . info ( " Testing Discord IPC connection " )
2024-02-07 01:40:41 +05:30
discordIpcService = DiscordIpcService ( pipeNumber )
2023-11-04 23:43:42 +05:30
discordIpcService . connect ( )
discordIpcService . setActivity ( {
" details " : " details " ,
" state " : " state " ,
" assets " : {
" large_text " : " large_text " ,
" large_image " : " logo " ,
" small_text " : " small_text " ,
" small_image " : " playing " ,
} ,
} )
time . sleep ( 15 )
discordIpcService . disconnect ( )
if __name__ == " __main__ " :
2023-11-05 11:43:52 +05:30
mode = sys . argv [ 1 ] if len ( sys . argv ) > 1 else " "
2023-11-05 15:54:36 +05:30
try :
if not mode :
2024-08-30 20:29:02 +05:30
init ( )
2023-11-05 15:54:36 +05:30
main ( )
elif mode == " test-ipc " :
testIpc ( int ( sys . argv [ 2 ] ) if len ( sys . argv ) > 2 else - 1 )
else :
2024-02-07 01:40:41 +05:30
logger . error ( f " Invalid mode: { mode } " )
2023-11-05 15:54:36 +05:30
except KeyboardInterrupt :
pass