Skip to content

Commit

Permalink
Merge branch 'westsurname:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
kanya-approve authored Jul 24, 2024
2 parents 9f9d09b + 8fed74d commit c3399c7
Show file tree
Hide file tree
Showing 18 changed files with 241 additions and 156 deletions.
16 changes: 11 additions & 5 deletions .env.template
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
# ╚══════╝ ╚═════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═╝ ╚══════╝ #
#------------------------------------------------------#

#------------------------------#
# SERVER - PLEX AUTHENTICATION #
#------------------------------#
#--------#
# SERVER #
#--------#

SERVER_DOMAIN=<server_domain>

Expand All @@ -29,8 +29,8 @@ PLEX_SERVER_TV_SHOW_LIBRARY_ID=<plex_server_movie_library_id>
# OVERSEERR - WATCHLIST, PLEX AUTHENTICATION, PLEX REQUEST, RECLAIM SPACE #
#-------------------------------------------------------------------------#

OVERSEERR_HOST="http://overseerr:5055"
OVERSEERR_API_KEY=
OVERSEERR_HOST=<overseerr_host>
OVERSEERR_API_KEY=<overseerr_api_key>

#------------------------------------------------------------------------------------#
# SONARR - BLACKHOLE, REPAIR, IMPORT TORRENT FOLDER, RECLAIM SPACE, ADD NEXT EPISODE #
Expand Down Expand Up @@ -123,6 +123,12 @@ BLACKHOLE_RD_MOUNT_REFRESH_SECONDS=200
BLACKHOLE_WAIT_FOR_TORRENT_TIMEOUT=60
BLACKHOLE_HISTORY_PAGE_SIZE=500

#------------------------------#
# PLEX REQUEST - PLEX REQUEST #
#------------------------------#

PLEX_REQUEST_SSL_PATH=

#-----------------------------------------------------------------------------------------------#
# DISCORD - BLACKHOLE, WATCHLIST, PLEX AUTHENTICATION, PLEX REQUEST, MONITOR RAM, RECLAIM SPACE #
#-----------------------------------------------------------------------------------------------#
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/docker-build-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ jobs:
image: ghcr.io/${{ github.repository }}/plex_request
- dockerfile: ./Dockerfile.scripts
image: ghcr.io/${{ github.repository }}/scripts
- dockerfile: ./Dockerfile.plex_request_nginx
image: ghcr.io/${{ github.repository }}/plex_request_nginx
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.blackhole
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.8-slim
FROM python:3.9-slim

# Metadata labels
LABEL org.opencontainers.image.source="https://github.com/westsurname/scripts"
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.plex_authentication
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.8-slim
FROM python:3.9-slim

# Metadata labels
LABEL org.opencontainers.image.source="https://github.com/westsurname/scripts"
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.plex_request
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.8-slim
FROM python:3.9-slim

# Metadata labels
LABEL org.opencontainers.image.source="https://github.com/westsurname/scripts"
Expand Down
19 changes: 19 additions & 0 deletions Dockerfile.plex_request_nginx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM nginx:alpine

# Metadata labels
LABEL org.opencontainers.image.source="https://github.com/westsurname/scripts"
LABEL org.opencontainers.image.description="Docker image for the plex_request_nginx service"

COPY plex_request_nginx_variables.conf /etc/nginx/templates/10-variables.conf.template
COPY plex_request_nginx.conf /etc/nginx/conf.d/default.conf

RUN if [ -n "$PLEX_REQUEST_SSL_PATH" ]; then \
sed -i '/# SSL_DISABLED_BEGIN/,/# SSL_DISABLED_END/d' /etc/nginx/conf.d/default.conf; \
else \
sed -i '/# SSL_ENABLED_BEGIN/,/# SSL_ENABLED_END/d' /etc/nginx/conf.d/default.conf; \
fi

# Expose port 8000 to the outside world
EXPOSE 8000

CMD ["nginx", "-g", "daemon off;"]
2 changes: 1 addition & 1 deletion Dockerfile.scripts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.8-slim
FROM python:3.9-slim

# Metadata labels
LABEL org.opencontainers.image.source="https://github.com/westsurname/scripts"
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.watchlist
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.8-slim
FROM python:3.9-slim

# Metadata labels
LABEL org.opencontainers.image.source="https://github.com/westsurname/scripts"
Expand Down
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
```
4. Copy `.env.template` to `.env` and populate the (applicable) variables:

- **Server** - Plex Authentication:
- **Server**:
- `SERVER_DOMAIN`: The domain name of your server.

- **Plex** - Watchlist, Plex Authentication, Plex Request, Plex Refresh:
Expand Down Expand Up @@ -85,6 +85,13 @@
- `BLACKHOLE_WAIT_FOR_TORRENT_TIMEOUT`: The timeout in seconds to wait for a torrent to be successful before failing.
- `BLACKHOLE_HISTORY_PAGE_SIZE`: The number of history items to pull at once when attempting to mark a download as failed.
- **Plex Request** - Plex Request:
- `PLEX_REQUEST_SSL_PATH` (Optional): The path to SSL certificates for Plex Request. If provided, this directory should contain the following files:
- `fullchain.pem`: The full certificate chain file.
- `privkey.pem`: The private key file.
- `chain.pem`: The certificate chain file.
- `dhparam.pem`: The Diffie-Hellman parameters file.
- **Discord** - Blackhole, Watchlist, Plex Authentication, Plex Request, Monitor Ram, Reclaim Space:
- `DISCORD_ENABLED`: Set to `true` to enable Discord error notifications.
- `DISCORD_UPDATE_ENABLED`: Set to `true` to enable update notifications as well on Discord.
Expand Down
22 changes: 12 additions & 10 deletions blackhole.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import re
import requests
import asyncio
import uuid
from datetime import datetime
# import urllib
from shared.discord import discordError, discordUpdate
Expand Down Expand Up @@ -47,11 +48,12 @@ def __init__(self, isTorrentOrMagnet, isDotTorrentFile) -> None:
def __init__(self, filename, isRadarr) -> None:
print('filename:', filename)
baseBath = getPath(isRadarr)
uniqueId = str(uuid.uuid4())[:8] # Generate a unique identifier
isDotTorrentFile = filename.casefold().endswith('.torrent')
isTorrentOrMagnet = isDotTorrentFile or filename.casefold().endswith('.magnet')
filenameWithoutExt, _ = os.path.splitext(filename)
filenameWithoutExt, ext = os.path.splitext(filename)
filePath = os.path.join(baseBath, filename)
filePathProcessing = os.path.join(baseBath, 'processing', filename)
filePathProcessing = os.path.join(baseBath, 'processing', f"{filenameWithoutExt}_{uniqueId}{ext}")
folderPathCompleted = os.path.join(baseBath, 'completed', filenameWithoutExt)

self.fileInfo = self.FileInfo(filename, filenameWithoutExt, filePath, filePathProcessing, folderPathCompleted)
Expand Down Expand Up @@ -287,14 +289,13 @@ async def is_accessible(path, timeout=10):
if torbox['enabled']:
torrentConstructors.append(TorboxTorrent if file.torrentInfo.isDotTorrentFile else TorboxMagnet)

onlyLargestFile = isRadarr or bool(re.search(r'S[\d]{2}E[\d]{2}', file.fileInfo.filename))
onlyLargestFile = isRadarr or bool(re.search(r'S[\d]{2}E[\d]{2}(?![\W_][\d]{2}[\W_])', file.fileInfo.filename))
if not blackhole['failIfNotCached']:
torrents = [constructor(f, fileData, file, blackhole['failIfNotCached'], onlyLargestFile) for constructor in torrentConstructors]
results = await asyncio.gather(*(processTorrent(torrent, file, arr) for torrent in torrents))

if not any(results):
for torrent in torrents:
fail(torrent, arr)
await asyncio.gather(*(fail(torrent, arr) for torrent in torrents))
else:
for i, constructor in enumerate(torrentConstructors):
isLast = (i == len(torrentConstructors) - 1)
Expand All @@ -303,7 +304,7 @@ async def is_accessible(path, timeout=10):
if await processTorrent(torrent, file, arr):
break
elif isLast:
fail(torrent, arr)
await fail(torrent, arr)

os.remove(file.fileInfo.filePathProcessing)
except:
Expand All @@ -314,7 +315,7 @@ async def is_accessible(path, timeout=10):

discordError(f"Error processing {file.fileInfo.filenameWithoutExt}", e)

def fail(torrent: TorrentBase, arr: Arr):
async def fail(torrent: TorrentBase, arr: Arr):
_print = globals()['print']

def print(*values: object):
Expand All @@ -323,15 +324,16 @@ def print(*values: object):
print(f"Failing")

torrentHash = torrent.getHash()
history = arr.getHistory(blackhole['historyPageSize'])
history = await asyncio.to_thread(arr.getHistory, blackhole['historyPageSize'])
items = [item for item in history if (item.torrentInfoHash and item.torrentInfoHash.casefold() == torrentHash.casefold()) or cleanFileName(item.sourceTitle.casefold()) == torrent.file.fileInfo.filenameWithoutExt.casefold()]
if not items:
message = "No history items found to mark as failed. Arr will not attempt to grab an alternative."
print(message)
discordError(message, torrent.file.fileInfo.filenameWithoutExt)
for item in items:
else:
# TODO: See if we can fail without blacklisting as cached items constantly changes
arr.failHistoryItem(item.id)
failTasks = [asyncio.to_thread(arr.failHistoryItem, item.id) for item in items]
await asyncio.gather(*failTasks)
print(f"Failed")

def getFiles(isRadarr):
Expand Down
26 changes: 21 additions & 5 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -160,13 +160,11 @@ services:
volumes:
- ./shared/tokens.json:/app/shared/tokens.json
ports:
- 8000:8000
- 8010:8000
env_file:
- .env
environment:
- SERVER_DOMAIN=${SERVER_DOMAIN}:8000
restart: unless-stopped
profiles: [plex_authentication, all]
profiles: [plex_authentication, watchlist, plex_request, all]

plex_request:
build:
Expand All @@ -178,11 +176,29 @@ services:
volumes:
- ./shared/tokens.json:/app/shared/tokens.json
ports:
- 8001:8000
- 8011:8000
env_file:
- .env
restart: unless-stopped
profiles: [plex_request, all]

plex_request_nginx:
build:
context: .
dockerfile: Dockerfile.plex_request_nginx
container_name: plex_request_nginx_service
image: ghcr.io/westsurname/scripts/plex_request_nginx:latest
pull_policy: always
volumes:
- ${PLEX_REQUEST_SSL_PATH:-/dev/null}:${PLEX_REQUEST_SSL_PATH:-/dev/null}:ro
ports:
- 8012:8000
env_file:
- .env
restart: unless-stopped
profiles: [plex_request, all]
depends_on:
- plex_request

networks:
default:
Expand Down
16 changes: 8 additions & 8 deletions plex_authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,14 @@
import json
import urllib.parse
from flask import Flask, jsonify, redirect, url_for
from shared.shared import server, watchlist, plexHeaders, tokensFilename
from shared.shared import watchlist, plexHeaders, tokensFilename
from shared.overseerr import getUserForPlexToken
from shared.plex import getServerToken
from werkzeug.serving import run_simple
from werkzeug.middleware.dispatcher import DispatcherMiddleware

host = server['host']
from werkzeug.middleware.proxy_fix import ProxyFix

# instantiate the app
app = Flask(__name__)
app.config.from_object(__name__)
app.config['SERVER_NAME'] = f"{host}"


@app.route('/', methods=['GET'])
Expand Down Expand Up @@ -42,9 +38,13 @@ def setupComplete(pin):

with open(tokensFilename, 'r+') as tokensFile:
tokens = json.load(tokensFile)
token = tokens.get(user['id'], { 'etag': '' })
token = tokens.get(userId, { 'etag': '' })
token['token'] = authToken
token['serverToken'] = serverToken

if serverToken == authToken:
token['owner'] = True

tokens[userId] = token
tokensFile.seek(0)
json.dump(tokens, tokensFile)
Expand All @@ -54,7 +54,7 @@ def setupComplete(pin):

return jsonify('There was an error, please try again.')

# app.wsgi_app = DispatcherMiddleware(run_simple, {'/plexAuthentication': app.wsgi_app})
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_port=1, x_prefix=1)

if __name__ == '__main__':
app.run('127.0.0.1', 12598)
26 changes: 19 additions & 7 deletions plex_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,11 @@ def requestRatingKey(mediaType, mediaTypeNum, ratingKey, season=None):
print(ratingKey, 'Not in recentRequests')

user = getUserForPlexServerToken(token)
requestItem(user, ratingKey, datetime.now().timestamp(), headers, getSeason=lambda: [int(season)])
metadataHeaders = {
**plexHeaders,
'X-Plex-Token': plex['serverApiKey']
}
requestItem(user, ratingKey, datetime.now().timestamp(), metadataHeaders, getSeason=lambda: [int(season)])

recentlyRequested.append(token)
cache.set(ratingKey, recentlyRequested)
Expand Down Expand Up @@ -140,6 +144,7 @@ def requestRatingKey(mediaType, mediaTypeNum, ratingKey, season=None):
# return response

# response = jsonify(json.loads(blankMediaContainer))
response = Response('', status=204)
response.headers.add('Access-Control-Allow-Origin', 'https://app.plex.tv')

return response
Expand Down Expand Up @@ -180,16 +185,19 @@ def all():
season = request.args.get('season.index', '1' if mediaType == 'show' else None)

if mediaType != 'episode':

metadataHeaders = {
**plexHeaders,
'X-Plex-Token': headers.get('X-Plex-Token', request.args.get('X-Plex-Token'))
'X-Plex-Token': plex['serverApiKey']
}

metadataAllRequest = requests.get(f"{plex['metadataHost']}library/metadata/{guid}", headers=metadataHeaders, params=request.args)
args = dict(request.args)
if 'X-Plex-Token' in args:
del args['X-Plex-Token']

metadataAllRequest = requests.get(f"{plex['metadataHost']}library/metadata/{guid}", headers=metadataHeaders, params=args)
# print(f"{plex['metadataHost']}library/metadata/{guid}")
# print(metadataHeaders)
# print(request.args)
# print(args)
print(metadataAllRequest)
# print(metadataAllRequest.text)
if metadataAllRequest.status_code == 200:
Expand Down Expand Up @@ -271,10 +279,14 @@ def children(id):

metadataHeaders = {
**plexHeaders,
'X-Plex-Token': headers.get('X-Plex-Token', request.args.get('X-Plex-Token'))
'X-Plex-Token': plex['serverApiKey']
}

metadataChildrenRequest = requests.get(f"{plex['metadataHost']}library/metadata/{guid}/children", headers=metadataHeaders, params=request.args)
args = dict(request.args)
if 'X-Plex-Token' in args:
del args['X-Plex-Token']

metadataChildrenRequest = requests.get(f"{plex['metadataHost']}library/metadata/{guid}/children", headers=metadataHeaders, params=args)
print(metadataChildrenRequest)
# print(metadataChildrenRequest.text)
if metadataChildrenRequest.status_code == 200:
Expand Down
Loading

0 comments on commit c3399c7

Please sign in to comment.