diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a5c5bdb..dad43c3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,9 +21,50 @@ jobs: - name: "Run tests" run: pytest -vvv + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: "Install dependencies" + run: | + pip install -r requirements.txt + sudo apt update && sudo apt install -y docker-compose + + - name: "Checkout JellyPlex-Watched-CI" + uses: actions/checkout@v2 + with: + repository: luigi311/JellyPlex-Watched-CI + path: JellyPlex-Watched-CI + + - name: "Start containers" + run: | + export PGID=$(id -g) + export PUID=$(id -u) + + sudo chown -R $PUID:$PGID JellyPlex-Watched-CI + + docker-compose -f JellyPlex-Watched-CI/plex/docker-compose.yml up -d + docker-compose -f JellyPlex-Watched-CI/jellyfin/docker-compose.yml up -d + # Wait for containers to start + sleep 15 + docker-compose -f JellyPlex-Watched-CI/plex/docker-compose.yml logs + docker-compose -f JellyPlex-Watched-CI/jellyfin/docker-compose.yml logs + + - name: "Run tests" + run: | + # Move test/.env to root + mv test/ci.env .env + # Run script + python main.py + + cat mark.log + docker: runs-on: ubuntu-latest - needs: pytest + needs: + - pytest + - test env: DEFAULT_VARIANT: alpine strategy: @@ -44,8 +85,8 @@ jobs: with: images: | ${{ secrets.DOCKER_USERNAME }}/jellyplex-watched,enable=${{ secrets.DOCKER_USERNAME != '' }} - # Do not push to ghcr.io on PRs due to permission issues - ghcr.io/${{ github.repository }},enable=${{ github.event_name != 'pull_request' }} + # Do not push to ghcr.io on PRs due to permission issues, only push if the owner is luigi311 so it doesnt fail on forks + ghcr.io/${{ github.repository }},enable=${{ github.event_name != 'pull_request' && github.repository_owner == 'luigi311'}} tags: | type=raw,value=latest,enable=${{ matrix.variant == env.DEFAULT_VARIANT && github.ref_name == github.event.repository.default_branch }} type=raw,value=dev,enable=${{ matrix.variant == env.DEFAULT_VARIANT && github.ref_name == 'dev' }} diff --git a/requirements.txt b/requirements.txt index 332dbb6..de8801d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ PlexAPI==4.15.5 requests==2.31.0 python-dotenv==1.0.0 -aiohttp==3.8.6 +aiohttp==3.9.0 diff --git a/src/jellyfin.py b/src/jellyfin.py index faaa144..41ddbc9 100644 --- a/src/jellyfin.py +++ b/src/jellyfin.py @@ -100,7 +100,7 @@ async def query(self, query, query_type, session=None, identifiers=None): return await self.query(query, query_type, session, identifiers) results = None - + authorization = ( "MediaBrowser , " 'Client="other", ' @@ -108,8 +108,12 @@ async def query(self, query, query_type, session=None, identifiers=None): 'DeviceId="script", ' 'Version="0.0.0"' ) - headers = {"Accept": "application/json", "X-Emby-Token": self.token, "X-Emby-Authorization": authorization} - + headers = { + "Accept": "application/json", + "X-Emby-Token": self.token, + "X-Emby-Authorization": authorization, + } + if query_type == "get": async with session.get( self.baseurl + query, headers=headers diff --git a/src/main.py b/src/main.py index 562dc46..05b5c96 100644 --- a/src/main.py +++ b/src/main.py @@ -83,17 +83,21 @@ def generate_server_connections(): ) for i, url in enumerate(plex_baseurl): + server = Plex( + baseurl=url.strip(), + token=plex_token[i].strip(), + username=None, + password=None, + servername=None, + ssl_bypass=ssl_bypass, + ) + + logger(f"Plex Server {i} info: {server.info()}", 3) + servers.append( ( "plex", - Plex( - baseurl=url.strip(), - token=plex_token[i].strip(), - username=None, - password=None, - servername=None, - ssl_bypass=ssl_bypass, - ), + server, ) ) @@ -110,17 +114,20 @@ def generate_server_connections(): ) for i, username in enumerate(plex_username): + server = Plex( + baseurl=None, + token=None, + username=username.strip(), + password=plex_password[i].strip(), + servername=plex_servername[i].strip(), + ssl_bypass=ssl_bypass, + ) + + logger(f"Plex Server {i} info: {server.info()}", 3) servers.append( ( "plex", - Plex( - baseurl=None, - token=None, - username=username.strip(), - password=plex_password[i].strip(), - servername=plex_servername[i].strip(), - ssl_bypass=ssl_bypass, - ), + server, ) ) @@ -140,10 +147,14 @@ def generate_server_connections(): baseurl = baseurl.strip() if baseurl[-1] == "/": baseurl = baseurl[:-1] + + server = Jellyfin(baseurl=baseurl, token=jellyfin_token[i].strip()) + + logger(f"Jellyfin Server {i} info: {server.info()}", 3) servers.append( ( "jellyfin", - Jellyfin(baseurl=baseurl, token=jellyfin_token[i].strip()), + server, ) ) diff --git a/test/ci.env b/test/ci.env new file mode 100644 index 0000000..ba9bd28 --- /dev/null +++ b/test/ci.env @@ -0,0 +1,86 @@ +# Global Settings + +## Do not mark any shows/movies as played and instead just output to log if they would of been marked. +DRYRUN = "False" + +## Additional logging information +DEBUG = "True" + +## Debugging level, "info" is default, "debug" is more verbose +DEBUG_LEVEL = "debug" + +## If set to true then the script will only run once and then exit +RUN_ONLY_ONCE = "True" + +## How often to run the script in seconds +SLEEP_DURATION = 10 + +## Log file where all output will be written to +LOG_FILE = "log.log" + +## Mark file where all shows/movies that have been marked as played will be written to +MARK_FILE = "mark.log" + +## Timeout for requests for jellyfin +REQUEST_TIMEOUT = 300 + +## Max threads for processing +MAX_THREADS = 2 + +## Map usernames between servers in the event that they are different, order does not matter +## Comma seperated for multiple options +USER_MAPPING = {"JellyUser":"jellyplex_watched"} + +## Map libraries between servers in the even that they are different, order does not matter +## Comma seperated for multiple options +LIBRARY_MAPPING = { "Shows": "TV Shows" } + + +## Blacklisting/Whitelisting libraries, library types such as Movies/TV Shows, and users. Mappings apply so if the mapping for the user or library exist then both will be excluded. +## Comma seperated for multiple options +#BLACKLIST_LIBRARY = "" +#WHITELIST_LIBRARY = "Movies" +#BLACKLIST_LIBRARY_TYPE = "Series" +#WHITELIST_LIBRARY_TYPE = "Movies, movie" +#BLACKLIST_USERS = "" +WHITELIST_USERS = "jellyplex_watched" + + + +# Plex + +## Recommended to use token as it is faster to connect as it is direct to the server instead of going through the plex servers +## URL of the plex server, use hostname or IP address if the hostname is not resolving correctly +## Comma seperated list for multiple servers +PLEX_BASEURL = "https://localhost:32400" + +## Plex token https://support.plex.tv/articles/204059436-finding-an-authentication-token-x-plex-token/ +## Comma seperated list for multiple servers +PLEX_TOKEN = "mVaCzSyd78uoWkCBzZ_Y" + +## If not using plex token then use username and password of the server admin along with the servername +## Comma seperated for multiple options +#PLEX_USERNAME = "PlexUser, PlexUser2" +#PLEX_PASSWORD = "SuperSecret, SuperSecret2" +#PLEX_SERVERNAME = "Plex Server1, Plex Server2" + +## Skip hostname validation for ssl certificates. +## Set to True if running into ssl certificate errors +SSL_BYPASS = "True" + +## control the direction of syncing. e.g. SYNC_FROM_PLEX_TO_JELLYFIN set to true will cause the updates from plex +## to be updated in jellyfin. SYNC_FROM_PLEX_TO_PLEX set to true will sync updates between multiple plex servers +SYNC_FROM_PLEX_TO_JELLYFIN = "True" +SYNC_FROM_JELLYFIN_TO_PLEX = "True" +SYNC_FROM_PLEX_TO_PLEX = "True" +SYNC_FROM_JELLYFIN_TO_JELLYFIN = "True" + +# Jellyfin + +## Jellyfin server URL, use hostname or IP address if the hostname is not resolving correctly +## Comma seperated list for multiple servers +JELLYFIN_BASEURL = "http://localhost:8096" + +## Jellyfin api token, created manually by logging in to the jellyfin server admin dashboard and creating an api key +## Comma seperated list for multiple servers +JELLYFIN_TOKEN = "d773c4db3ecc4b028fc0904d9694804c"