Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87b4a950f1 | ||
|
|
9f61c7338d | ||
|
|
ffc81dad69 | ||
|
|
7eba46b5cb | ||
|
|
aa177666a5 | ||
|
|
7de7b42fd2 | ||
|
|
03d1fd8019 | ||
|
|
485ec5fe2d | ||
|
|
59bfbd9811 | ||
|
|
1e485b37f8 | ||
|
|
4adf94f24b | ||
|
|
1a0fab36d3 | ||
|
|
a1ef3b5a8d | ||
|
|
0c47ee7119 | ||
|
|
e51cf6e482 | ||
|
|
24d5de813d | ||
|
|
9921b2a355 | ||
|
|
faa378c75e | ||
|
|
26199100dc | ||
|
|
bee854f059 | ||
|
|
73c1ebf3ed | ||
|
|
397dd17429 | ||
|
|
73d18dad92 | ||
|
|
94d63a3fdb | ||
|
|
120d89e8be | ||
|
|
eb5534c61c | ||
|
|
99d217e8f1 | ||
|
|
f7e3f8ae2a | ||
|
|
2cebd2d73d |
@@ -1 +1,15 @@
|
||||
.dockerignore
|
||||
.env
|
||||
.env.sample
|
||||
.git
|
||||
.github
|
||||
.gitignore
|
||||
.idea
|
||||
.vscode
|
||||
|
||||
Dockerfile*
|
||||
README.md
|
||||
|
||||
test
|
||||
|
||||
venv
|
||||
49
.github/workflows/ci.yml
vendored
49
.github/workflows/ci.yml
vendored
@@ -24,25 +24,34 @@ jobs:
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
needs: pytest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- dockerfile: Dockerfile.alpine
|
||||
variant: alpine
|
||||
- dockerfile: Dockerfile.slim
|
||||
variant: slim
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Docker meta
|
||||
id: docker_meta
|
||||
env:
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||
if: "${{ env.DOCKER_USERNAME != '' }}"
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: ${{ secrets.DOCKER_USERNAME }}/jellyplex-watched # list of Docker images to use as base name for tags
|
||||
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' }}
|
||||
tags: |
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=sha
|
||||
type=raw,value=latest,enable=${{ matrix.variant == 'alpine' && github.ref_name == github.event.repository.default_branch }}
|
||||
type=raw,value=dev,enable=${{ matrix.variant == 'alpine' && github.ref_name == 'dev' }}
|
||||
type=raw,value=latest,suffix=-${{ matrix.variant }},enable={{ is_default_branch }}
|
||||
type=ref,event=branch,suffix=-${{ matrix.variant }}
|
||||
type=ref,event=pr,suffix=-${{ matrix.variant }}
|
||||
type=semver,pattern={{ version }},suffix=-${{ matrix.variant }}
|
||||
type=semver,pattern={{ major }}.{{ minor }},suffix=-${{ matrix.variant }}
|
||||
type=sha,suffix=-${{ matrix.variant }}
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -51,30 +60,40 @@ jobs:
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to DockerHub
|
||||
if: "${{ steps.docker_meta.outcome == 'success' }}"
|
||||
env:
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||
if: "${{ env.DOCKER_USERNAME != '' }}"
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_TOKEN }}
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
if: "${{ steps.docker_meta.outcome == 'success' }}"
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build
|
||||
id: build
|
||||
if: "${{ steps.docker_meta.outcome == 'skipped' }}"
|
||||
if: "${{ steps.docker_meta.outputs.tags == '' }}"
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
file: ${{ matrix.dockerfile }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: false
|
||||
tags: jellyplex-watched:action
|
||||
|
||||
- name: Build Push
|
||||
id: build_push
|
||||
if: "${{ steps.docker_meta.outcome == 'success' }}"
|
||||
if: "${{ steps.docker_meta.outputs.tags != '' }}"
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
file: ${{ matrix.dockerfile }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.docker_meta.outputs.tags }}
|
||||
|
||||
41
Dockerfile.alpine
Normal file
41
Dockerfile.alpine
Normal file
@@ -0,0 +1,41 @@
|
||||
FROM python:3-alpine
|
||||
|
||||
ENV DRYRUN 'True'
|
||||
ENV DEBUG 'True'
|
||||
ENV DEBUG_LEVEL 'INFO'
|
||||
ENV SLEEP_DURATION '3600'
|
||||
ENV LOGFILE 'log.log'
|
||||
|
||||
ENV USER_MAPPING ''
|
||||
ENV LIBRARY_MAPPING ''
|
||||
|
||||
ENV PLEX_BASEURL ''
|
||||
ENV PLEX_TOKEN ''
|
||||
ENV PLEX_USERNAME ''
|
||||
ENV PLEX_PASSWORD ''
|
||||
ENV PLEX_SERVERNAME ''
|
||||
|
||||
ENV JELLYFIN_BASEURL ''
|
||||
ENV JELLYFIN_TOKEN ''
|
||||
|
||||
ENV SYNC_FROM_PLEX_TO_JELLYFIN 'True'
|
||||
ENV SYNC_FROM_JELLYFIN_TO_PLEX 'True'
|
||||
ENV SYNC_FROM_PLEX_TO_PLEX 'True'
|
||||
ENV SYNC_FROM_JELLYFIN_TO_JELLYFIN 'True'
|
||||
|
||||
ENV BLACKLIST_LIBRARY ''
|
||||
ENV WHITELIST_LIBRARY ''
|
||||
ENV BLACKLIST_LIBRARY_TYPE ''
|
||||
ENV WHITELIST_LIBRARY_TYPE ''
|
||||
ENV BLACKLIST_USERS ''
|
||||
ENV WHITELIST_USERS ''
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY ./requirements.txt ./
|
||||
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
COPY . .
|
||||
|
||||
CMD ["python", "-u", "main.py"]
|
||||
@@ -32,12 +32,6 @@ ENV WHITELIST_USERS ''
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
build-essential && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY ./requirements.txt ./
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
31
docker-compose.yml
Normal file
31
docker-compose.yml
Normal file
@@ -0,0 +1,31 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
jellyplex-watched:
|
||||
image: luigi311/jellyplex-watched:latest
|
||||
container_name: jellyplex-watched
|
||||
restart: always
|
||||
environment:
|
||||
- DRYRUN=True
|
||||
- DEBUG=True
|
||||
- DEBUG_LEVEL=info
|
||||
- RUN_ONLY_ONCE=False
|
||||
- SLEEP_DURATION=3600
|
||||
- LOGFILE=/tmp/log.log
|
||||
- USER_MAPPING=
|
||||
- LIBRARY_MAPPING={"TV Shows":"Shows"}
|
||||
- BLACKLIST_LIBRARY=
|
||||
- WHITELIST_LIBRARY=
|
||||
- BLACKLIST_LIBRARY_TYPE=
|
||||
- WHITELIST_LIBRARY_TYPE=
|
||||
- BLACKLIST_USERS=
|
||||
- WHITELIST_USERS=
|
||||
- PLEX_BASEURL=
|
||||
- PLEX_TOKEN=
|
||||
- JELLYFIN_BASEURL=
|
||||
- JELLYFIN_TOKEN=
|
||||
- SSL_BYPASS=True
|
||||
- SYNC_FROM_PLEX_TO_JELLYFIN=True
|
||||
- SYNC_FROM_JELLYFIN_TO_PLEX=True
|
||||
- SYNC_FROM_PLEX_TO_PLEX=True
|
||||
- SYNC_FROM_JELLYFIN_TO_JELLYFIN=True
|
||||
@@ -1,4 +1,4 @@
|
||||
plexapi
|
||||
requests
|
||||
python-dotenv
|
||||
aiohttp
|
||||
PlexAPI==4.13.4
|
||||
requests==2.28.2
|
||||
python-dotenv==1.0.0
|
||||
aiohttp==3.8.4
|
||||
|
||||
@@ -11,18 +11,20 @@ def setup_black_white_lists(
|
||||
library_mapping=None,
|
||||
user_mapping=None,
|
||||
):
|
||||
blacklist_library, blacklist_library_type, blacklist_users = setup_black_lists(
|
||||
blacklist_library, blacklist_library_type, blacklist_users = setup_x_lists(
|
||||
blacklist_library,
|
||||
blacklist_library_type,
|
||||
blacklist_users,
|
||||
"White",
|
||||
library_mapping,
|
||||
user_mapping,
|
||||
)
|
||||
|
||||
whitelist_library, whitelist_library_type, whitelist_users = setup_white_lists(
|
||||
whitelist_library, whitelist_library_type, whitelist_users = setup_x_lists(
|
||||
whitelist_library,
|
||||
whitelist_library_type,
|
||||
whitelist_users,
|
||||
"Black",
|
||||
library_mapping,
|
||||
user_mapping,
|
||||
)
|
||||
@@ -36,104 +38,93 @@ def setup_black_white_lists(
|
||||
whitelist_users,
|
||||
)
|
||||
|
||||
|
||||
def setup_black_lists(
|
||||
blacklist_library,
|
||||
blacklist_library_type,
|
||||
blacklist_users,
|
||||
def setup_x_lists(
|
||||
xlist_library,
|
||||
xlist_library_type,
|
||||
xlist_users,
|
||||
xlist_type,
|
||||
library_mapping=None,
|
||||
user_mapping=None,
|
||||
):
|
||||
if blacklist_library:
|
||||
if len(blacklist_library) > 0:
|
||||
blacklist_library = blacklist_library.split(",")
|
||||
blacklist_library = [x.strip() for x in blacklist_library]
|
||||
if xlist_library:
|
||||
if len(xlist_library) > 0:
|
||||
xlist_library = xlist_library.split(",")
|
||||
xlist_library = [x.strip() for x in xlist_library]
|
||||
if library_mapping:
|
||||
temp_library = []
|
||||
for library in blacklist_library:
|
||||
for library in xlist_library:
|
||||
library_other = search_mapping(library_mapping, library)
|
||||
if library_other:
|
||||
temp_library.append(library_other)
|
||||
|
||||
blacklist_library = blacklist_library + temp_library
|
||||
xlist_library = xlist_library + temp_library
|
||||
else:
|
||||
blacklist_library = []
|
||||
logger(f"Blacklist Library: {blacklist_library}", 1)
|
||||
xlist_library = []
|
||||
logger(f"{xlist_type}list Library: {xlist_library}", 1)
|
||||
|
||||
if blacklist_library_type:
|
||||
if len(blacklist_library_type) > 0:
|
||||
blacklist_library_type = blacklist_library_type.split(",")
|
||||
blacklist_library_type = [x.lower().strip() for x in blacklist_library_type]
|
||||
if xlist_library_type:
|
||||
if len(xlist_library_type) > 0:
|
||||
xlist_library_type = xlist_library_type.split(",")
|
||||
xlist_library_type = [x.lower().strip() for x in xlist_library_type]
|
||||
else:
|
||||
blacklist_library_type = []
|
||||
logger(f"Blacklist Library Type: {blacklist_library_type}", 1)
|
||||
xlist_library_type = []
|
||||
logger(f"{xlist_type}list Library Type: {xlist_library_type}", 1)
|
||||
|
||||
if blacklist_users:
|
||||
if len(blacklist_users) > 0:
|
||||
blacklist_users = blacklist_users.split(",")
|
||||
blacklist_users = [x.lower().strip() for x in blacklist_users]
|
||||
if xlist_users:
|
||||
if len(xlist_users) > 0:
|
||||
xlist_users = xlist_users.split(",")
|
||||
xlist_users = [x.lower().strip() for x in xlist_users]
|
||||
if user_mapping:
|
||||
temp_users = []
|
||||
for user in blacklist_users:
|
||||
for user in xlist_users:
|
||||
user_other = search_mapping(user_mapping, user)
|
||||
if user_other:
|
||||
temp_users.append(user_other)
|
||||
|
||||
blacklist_users = blacklist_users + temp_users
|
||||
else:
|
||||
blacklist_users = []
|
||||
logger(f"Blacklist Users: {blacklist_users}", 1)
|
||||
|
||||
return blacklist_library, blacklist_library_type, blacklist_users
|
||||
|
||||
|
||||
def setup_white_lists(
|
||||
whitelist_library,
|
||||
whitelist_library_type,
|
||||
whitelist_users,
|
||||
library_mapping=None,
|
||||
user_mapping=None,
|
||||
):
|
||||
if whitelist_library:
|
||||
if len(whitelist_library) > 0:
|
||||
whitelist_library = whitelist_library.split(",")
|
||||
whitelist_library = [x.strip() for x in whitelist_library]
|
||||
if library_mapping:
|
||||
temp_library = []
|
||||
for library in whitelist_library:
|
||||
library_other = search_mapping(library_mapping, library)
|
||||
if library_other:
|
||||
temp_library.append(library_other)
|
||||
|
||||
whitelist_library = whitelist_library + temp_library
|
||||
else:
|
||||
whitelist_library = []
|
||||
logger(f"Whitelist Library: {whitelist_library}", 1)
|
||||
|
||||
if whitelist_library_type:
|
||||
if len(whitelist_library_type) > 0:
|
||||
whitelist_library_type = whitelist_library_type.split(",")
|
||||
whitelist_library_type = [x.lower().strip() for x in whitelist_library_type]
|
||||
else:
|
||||
whitelist_library_type = []
|
||||
logger(f"Whitelist Library Type: {whitelist_library_type}", 1)
|
||||
|
||||
if whitelist_users:
|
||||
if len(whitelist_users) > 0:
|
||||
whitelist_users = whitelist_users.split(",")
|
||||
whitelist_users = [x.lower().strip() for x in whitelist_users]
|
||||
if user_mapping:
|
||||
temp_users = []
|
||||
for user in whitelist_users:
|
||||
user_other = search_mapping(user_mapping, user)
|
||||
if user_other:
|
||||
temp_users.append(user_other)
|
||||
|
||||
whitelist_users = whitelist_users + temp_users
|
||||
xlist_users = xlist_users + temp_users
|
||||
else:
|
||||
whitelist_users = []
|
||||
xlist_users = []
|
||||
else:
|
||||
whitelist_users = []
|
||||
logger(f"Whitelist Users: {whitelist_users}", 1)
|
||||
xlist_users = []
|
||||
logger(f"{xlist_type}list Users: {xlist_users}", 1)
|
||||
|
||||
return xlist_library, xlist_library_type, xlist_users
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return whitelist_library, whitelist_library_type, whitelist_users
|
||||
|
||||
16
src/main.py
16
src/main.py
@@ -40,15 +40,23 @@ def setup_users(
|
||||
|
||||
# Check if users is none or empty
|
||||
if output_server_1_users is None or len(output_server_1_users) == 0:
|
||||
raise Exception(
|
||||
f"No users found for server 1 {server_1[0]}, users found {users}, filtered users {users_filtered}, server 1 users {server_1[1].users}"
|
||||
logger(
|
||||
f"No users found for server 1 {server_1[0]}, users: {server_1_users}, overlapping users {users}, filtered users {users_filtered}, server 1 users {server_1[1].users}"
|
||||
)
|
||||
|
||||
if output_server_2_users is None or len(output_server_2_users) == 0:
|
||||
raise Exception(
|
||||
f"No users found for server 2 {server_2[0]}, users found {users} filtered users {users_filtered}, server 2 users {server_2[1].users}"
|
||||
logger(
|
||||
f"No users found for server 2 {server_2[0]}, users: {server_2_users}, overlapping users {users} filtered users {users_filtered}, server 2 users {server_2[1].users}"
|
||||
)
|
||||
|
||||
if (
|
||||
output_server_1_users is None
|
||||
or len(output_server_1_users) == 0
|
||||
or output_server_2_users is None
|
||||
or len(output_server_2_users) == 0
|
||||
):
|
||||
raise Exception("No users found for one or both servers")
|
||||
|
||||
logger(f"Server 1 users: {output_server_1_users}", 1)
|
||||
logger(f"Server 2 users: {output_server_2_users}", 1)
|
||||
|
||||
|
||||
12
src/plex.py
12
src/plex.py
@@ -126,7 +126,7 @@ def get_user_library_watched_show(show):
|
||||
|
||||
def get_user_library_watched(user, user_plex, library):
|
||||
try:
|
||||
user_name = user.title.lower()
|
||||
user_name = user.username.lower() if user.username else user.title.lower()
|
||||
user_watched = {}
|
||||
user_watched[user_name] = {}
|
||||
|
||||
@@ -509,10 +509,16 @@ class Plex:
|
||||
user_other = search_mapping(user_mapping, user)
|
||||
|
||||
for index, value in enumerate(self.users):
|
||||
if user.lower() == value.title.lower():
|
||||
username_title = (
|
||||
value.username.lower()
|
||||
if value.username
|
||||
else value.title.lower()
|
||||
)
|
||||
|
||||
if user.lower() == username_title:
|
||||
user = self.users[index]
|
||||
break
|
||||
elif user_other and user_other.lower() == value.title.lower():
|
||||
elif user_other and user_other.lower() == username_title:
|
||||
user = self.users[index]
|
||||
break
|
||||
|
||||
|
||||
14
src/users.py
14
src/users.py
@@ -11,7 +11,11 @@ def generate_user_list(server):
|
||||
|
||||
server_users = []
|
||||
if server_type == "plex":
|
||||
server_users = [x.title.lower() for x in server_connection.users]
|
||||
for user in server_connection.users:
|
||||
server_users.append(
|
||||
user.username.lower() if user.username else user.title.lower()
|
||||
)
|
||||
|
||||
elif server_type == "jellyfin":
|
||||
server_users = [key.lower() for key in server_connection.users.keys()]
|
||||
|
||||
@@ -66,9 +70,13 @@ def generate_server_users(server, users):
|
||||
if server[0] == "plex":
|
||||
server_users = []
|
||||
for plex_user in server[1].users:
|
||||
username_title = (
|
||||
plex_user.username if plex_user.username else plex_user.title
|
||||
)
|
||||
|
||||
if (
|
||||
plex_user.title.lower() in users.keys()
|
||||
or plex_user.title.lower() in users.values()
|
||||
username_title.lower() in users.keys()
|
||||
or username_title.lower() in users.values()
|
||||
):
|
||||
server_users.append(plex_user)
|
||||
elif server[0] == "jellyfin":
|
||||
|
||||
@@ -1 +1 @@
|
||||
pytest
|
||||
pytest==7.3.0
|
||||
|
||||
Reference in New Issue
Block a user