Skip to content
This repository has been archived by the owner on May 18, 2024. It is now read-only.

Added systemd service file and refactored main.py #605

Open
wants to merge 36 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
217a9e3
Added support for local trakt list
jaqb Jul 26, 2023
4719337
Added systemd service file and refactored main.py
KJSain Dec 19, 2023
bf8f53e
Fix issue 578: Reoccurrence of Issue #478: Single Episode Downloads N…
sirstudly Mar 30, 2024
fbd83ed
Resolving issue https://github.com/itsToggle/plex_debrid/issues/638
sirstudly Mar 21, 2024
3c3b2f0
Allow movie matches with year NOT present in title
sirstudly Mar 29, 2024
e15dec2
Fix issue 578: Reoccurrence of Issue #478: Single Episode Downloads N…
sirstudly Mar 30, 2024
b01f8ad
classes.py:deviation(): improve regex matching
sirstudly Apr 2, 2024
613e1c3
Parameterized watchlist loop interval rather than hardcoded 30 minutes
sirstudly Apr 3, 2024
f1d4413
Fix deviation() for season release of:
sirstudly Apr 5, 2024
f777216
Add plex server address help
petern-sc May 10, 2024
3a3c858
"Elfify" the logo
funkypenguin Jul 2, 2024
c678fa1
try to pass oauth details to PD using env vars
funkypenguin Jul 12, 2024
232582d
Added Zilean support
sirstudly Jul 14, 2024
99aac84
Updated docker files
sirstudly Jul 14, 2024
611c4ab
Additional comments and debugging statements
sirstudly Jul 14, 2024
b4d758b
Fix missing originallyAvailableAt on classes::released
sirstudly Jul 14, 2024
86c912a
Parameterized watchlist loop interval rather than hardcoded 30 minutes
sirstudly Apr 3, 2024
29072da
Issue 529: Update default character replacement to better handle punc…
sirstudly Jul 17, 2024
808b518
Fixing zilean support
sirstudly Jul 21, 2024
11655d0
Allow access to host network in docker-compose.yml
sirstudly Jul 21, 2024
b226b1e
Fixing zilean alt matching
sirstudly Jul 21, 2024
b05494d
Fixing zilean alt matching
sirstudly Jul 21, 2024
b43ca9e
Fixing zilean alt matching
sirstudly Jul 21, 2024
9009b43
Added Zilean support
sirstudly Jul 14, 2024
5af1c22
Merge pull request #1 from sirstudly/issue_578
funkypenguin Jul 23, 2024
01704ea
Merge pull request #3 from sirstudly/zilean_support
funkypenguin Jul 23, 2024
d59a66f
Merge pull request #2 from sirstudly/watchlist_loop_param
funkypenguin Jul 23, 2024
617993a
Bump version to v2.96
funkypenguin Jul 23, 2024
9676555
Merge branch 'main' of github.com:elfhosted/plex_debrid
funkypenguin Jul 23, 2024
401a4e0
Issue 529: Update default character replacement to better handle punc…
sirstudly Jul 23, 2024
12c3942
Merge branch 'issue_529'
sirstudly Jul 23, 2024
117b372
Reverting some regex fixes which may not be required?
sirstudly Jul 23, 2024
42af256
Reverting previous commit.. included in branch issue_529
sirstudly Jul 23, 2024
a83717f
Merge pull request #1 from sirstudly/main
KJSain Aug 31, 2024
1a85197
Merge branch 'main' into pr/684
KJSain Aug 31, 2024
827862d
Merge pull request #3 from jaqb/main
KJSain Aug 31, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Unless more-specific rules are added, all PRs require @funkypenguin's approval ;)

* @funkypenguin
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -397,3 +397,6 @@ FodyWeavers.xsd
# JetBrains Rider
*.sln.iml
settings.json

venv*/
.idea/
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
FROM python:3

RUN apt-get update && apt-get install -y vim less

ADD . / ./

RUN pip install -r requirements.txt
Expand Down
15 changes: 12 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -381,11 +381,11 @@ If github is not your cup of tea;
></details>
>
><details>
> <summary><b><u><img src="https://app.plex.tv/desktop/favicon.ico" height="16"> Plex lables:</u></b></summary>
> <summary><b><u><img src="https://app.plex.tv/desktop/favicon.ico" height="16"> Plex labels:</u></b></summary>
>
> - To add automatic version and user lables to your downloaded content, navigate to '/Settings/Library Service/Library update service/Edit/'
> - To add automatic version and user labels to your downloaded content, navigate to '/Settings/Library Service/Library update service/Edit/'
> - This requires a Plex library refresh to be set up aswell (see above).
> - Lables that will be added are: "From: ..." for each user that watchlisted this item, "Version: ..." for each version that was downloaded.
> - Labels that will be added are: "From: ..." for each user that watchlisted this item, "Version: ..." for each version that was downloaded.
>
></details>
>
Expand Down Expand Up @@ -492,6 +492,15 @@ If github is not your cup of tea;
> - You can find a full list of all possible parameters and their respective values at "https://panel.orionoid.com/" in the "Developers" menu, section "API Docs" under "Stream API".
>
></details>
>
><details>
> <summary><b><u>zilean:</u></b></summary>
>
> - Zilean is a service that allows you to search for [DebridMediaManager](https://github.com/debridmediamanager/debrid-media-manager) sourced arr-less content.
> - You can integrate zilean into plex_debrid by navigating to '/Settings/Scraper/Sources/Edit/Add source/zilean'.
> - Details of this project can be found at https://github.com/iPromKnight/zilean
>
></details>

### :arrow_down_small: Debrid Services:

Expand Down
42 changes: 24 additions & 18 deletions content/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,17 +570,17 @@ def deviation(self, year=""):
if regex.search(str(self.year), releases.rename(self.title.replace(str(self.year), '') + ' ' + str(self.year))):
title = title.replace('.' + str(self.year), '')
if year != "":
return '[^A-Za-z0-9]*(' + title + ':?.)\(?\[?(' + str(year) + ')'
return '[^A-Za-z0-9]*(' + title + ':?.)\(?\[?(' + str(self.year) + '|' + str(self.year - 1) + '|' + str(self.year + 1) + ')'
return '(.*?)(' + title + ':?.*)\(?\[?(' + str(year) + ')?'
return '(.*?)(' + title + ':?.*)\(?\[?(' + str(self.year) + '|' + str(self.year - 1) + '|' + str(self.year + 1) + ')?'
else:
title = title.replace('.' + str(self.year), '')
return '[^A-Za-z0-9]*(' + title + ')'
return '(.*?)(' + title + ')'
elif self.type == 'show':
title = title.replace('.' + str(self.year), '')
return '[^A-Za-z0-9]*(' + title + ':?.)(series.|[^A-Za-z0-9]+)?((\(?' + str(self.year) + '\)?.)|(complete.)|(seasons?.[0-9]+.[0-9]?[0-9]?.?)|(S[0-9]+.S?[0-9]?[0-9]?.?)|(S[0-9]+E[0-9]+))'
return '(.*?)(' + title + ':?.)(series.|[^A-Za-z0-9]+)?((\(?' + str(self.year) + '\)?.)|(complete.)|(seasons?.[0-9]+.[0-9]?[0-9]?.?)|(S[0-9]+.S?[0-9]?[0-9]?.?)|(S[0-9]+E[0-9]+))'
elif self.type == 'season':
title = title.replace('.' + str(self.parentYear), '')
return '[^A-Za-z0-9]*(' + title + ':?.)(series.|[^A-Za-z0-9]+)?(\(?' + str(self.parentYear) + '\)?.)?(season.' + str(self.index) + '\.|season.' + str("{:02d}".format(self.index)) + '\.|S' + str("{:02d}".format(self.index)) + '\.)'
return '(.*?)(' + title + ':?.)(series.|[^A-Za-z0-9]+)?(\(?' + str(self.parentYear) + '\)?.)?(season.' + str(self.index) + '[^0-9]|season.' + str("{:02d}".format(self.index)) + '[^0-9]|S' + str("{:02d}".format(self.index)) + '[^0-9])'
elif self.type == 'episode':
title = title.replace('.' + str(self.grandparentYear), '')
try:
Expand All @@ -594,9 +594,9 @@ def deviation(self, year=""):
airdate_formats += [airdate.strftime(
'(%m|%b).*%d.*(%Y|%y)').replace("0", "0?")]
airdate_formats = "(" + ")|(".join(airdate_formats) + ")"
return '[^A-Za-z0-9]*(' + title + ':?.)(series.)?(\(?' + str(self.grandparentYear) + '\)?.)?(S' + str("{:02d}".format(self.parentIndex)) + 'E' + str("{:02d}".format(self.index)) + '.|'+airdate_formats+')'
return '(.*?)(' + title + ':?.)(series.)?(\(?' + str(self.grandparentYear) + '\)?.)?(S' + str("{:02d}".format(self.parentIndex)) + 'E' + str("{:02d}".format(self.index)) + '.|'+airdate_formats+')'
except:
return '[^A-Za-z0-9]*(' + title + ':?.)(series.)?(\(?' + str(self.grandparentYear) + '\)?.)?(S' + str("{:02d}".format(self.parentIndex)) + 'E' + str("{:02d}".format(self.index)) + '.)'
return '(.*?)(' + title + ':?.)(series.)?(\(?' + str(self.grandparentYear) + '\)?.)?(S' + str("{:02d}".format(self.parentIndex)) + 'E' + str("{:02d}".format(self.index)) + '.)'
else:
if hasattr(self, 'alternate_titles'):
title = '(' + '|'.join(self.alternate_titles) + ')'
Expand All @@ -612,22 +612,22 @@ def deviation(self, year=""):
title = title.replace('[', '\[').replace(']', '\]')
if self.type == 'movie':
title = title.replace('.' + str(self.year), '')
return '(.*?)(' + title + '.)(.*?)(' + str(self.year) + '|' + str(self.year - 1) + '|' + str(self.year + 1) + ')'
return '(.*?)(' + title + ')(.*?)(' + str(self.year) + '|' + str(self.year - 1) + '|' + str(self.year + 1) + ')?'
elif self.type == 'show':
title = title.replace('.' + str(self.year), '')
return '(.*?)(' + title + '.)(.*?)('+self.anime_count+'|(complete)|(seasons?[^0-9]?[0-9]+[^A-Z0-9]+S?[0-9]+)|(S[0-9]+[^A-Z0-9]+S?[0-9]+))'
return '(.*?)(' + title + ')(.*?)('+self.anime_count+'|(complete)|(seasons?[^0-9]?[0-9]+[^A-Z0-9]+S?[0-9]+)|(S[0-9]+[^A-Z0-9]+S?[0-9]+))'
elif self.type == 'season':
n = self.index
roman = 'I' if n == 1 else 'II' if n == 2 else 'III' if n == 3 else 'IV' if n == 4 else 'V' if n == 5 else 'VI' if n == 6 else 'VII' if n == 7 else 'VIII' if n == 8 else 'IX' if n == 9 else 'X' if n == 10 else str(
n)
title = title.replace('.' + str(self.parentYear), '')
return '(.*?)(' + title + '.)(.*?)(season[^0-9]?0*' + str(self.index) + '|S0*' + str(self.index) + '(?!E?[0-9])|'+self.anime_count+'|[^A-Z0-9]'+roman+'[^A-Z0-9])'
return '(.*?)(' + title + ')(.*?)(season[^0-9]?0*' + str(self.index) + '|S0*' + str(self.index) + '(?!E?[0-9])|'+self.anime_count+'|[^A-Z0-9]'+roman+'[^A-Z0-9])'
elif self.type == 'episode':
n = self.parentIndex
roman = 'I' if n == 1 else 'II' if n == 2 else 'III' if n == 3 else 'IV' if n == 4 else 'V' if n == 5 else 'VI' if n == 6 else 'VII' if n == 7 else 'VIII' if n == 8 else 'IX' if n == 9 else 'X' if n == 10 else str(
n)
title = title.replace('.' + str(self.grandparentYear), '')
return '(.*?)(' + title + '.)(.*?)((?<!part)[^0-9A-RT-Z\[]0*('+str(self.parentIndex)+'|'+roman+')[^0-9A-DF-Z\[]0*'+str(self.index)+'(?![A-Z0-9]|\])|(?<!part)[^0-9A-Z\[]0*'+self.anime_count+'(?![A-Z0-9]|\]))'
return '(.*?)(' + title + ')(.*?)((?<!part)[^0-9A-RT-Z\[]0*('+str(self.parentIndex)+'|'+roman+')[^0-9A-DF-Z\[]0*'+str(self.index)+'(?![A-Z0-9]|\])|(?<!part)[^0-9A-Z\[]0*'+self.anime_count+'(?![A-Z0-9]|\]))'

def isanime(self):
if 'anime' in self.genre():
Expand Down Expand Up @@ -926,17 +926,19 @@ def watch(self):
retries = int(float(trigger[2]))
if retries == 0:
return

message = 'retrying download in ' + str(
round(int(ui_settings.loop_interval_seconds) / 60)) + 'min for item: ' + self.query() + ' - version/s [' + '],['.join(
names) + ']'
if not self in media.ignore_queue:
self.ignored_count = 1
media.ignore_queue += [self]
ui_print('retrying download in 30min for item: ' + self.query() + ' - version/s [' + '],['.join(
names) + '] - attempt ' + str(self.ignored_count) + '/' + str(retries))
ui_print(message + ' - attempt ' + str(self.ignored_count) + '/' + str(retries))
else:
match = next((x for x in media.ignore_queue if self == x), None)
if match.ignored_count < retries:
match.ignored_count += 1
ui_print('retrying download in 30min for item: ' + self.query() + ' - version/s [' + '],['.join(
names) + '] - attempt ' + str(match.ignored_count) + '/' + str(retries))
ui_print(message + ' - attempt ' + str(match.ignored_count) + '/' + str(retries))
else:
media.ignore_queue.remove(match)
ignore.add(self)
Expand All @@ -949,6 +951,9 @@ def watched(self):

def released(self):
try:
if not hasattr(self, "originallyAvailableAt"):
return False # attribute may not be present

released = datetime.datetime.utcnow(
) - datetime.datetime.strptime(self.originallyAvailableAt, '%Y-%m-%d')
if hasattr(self, "offset_airtime"):
Expand Down Expand Up @@ -1078,7 +1083,7 @@ def available(self):
def collect(self, refresh_=True):
for refresh_service in refresh():
if refresh_service.__module__ == self.__module__ or (self.__module__ in ["content.services.trakt", "releases", "content.services.overseerr", "content.services.plex"] and refresh_service.__module__ in ["content.services.plex", "content.services.jellyfin"]):
if refresh_ or refresh_service.name == "Plex Lables":
if refresh_ or refresh_service.name == "Plex Labels":
refresh_service(self)
elif self.__module__ in ["content.services.plex", "content.services.overseerr"] and refresh_service.__module__ == "content.services.trakt":
try:
Expand Down Expand Up @@ -1366,7 +1371,7 @@ def download(self, retries=0, library=[], parentReleases=[]):
if len(self.Episodes) > 2:
if self.season_pack(scraped_releases):
debrid_downloaded, retry = self.debrid_download()
# if scraper.traditional() or debrid_downloaded:
if scraper.traditional() or debrid_downloaded:
for episode in self.Episodes:
episode.skip_scraping = True
# If there was nothing downloaded, scrape specifically for this season
Expand Down Expand Up @@ -1400,6 +1405,7 @@ def download(self, retries=0, library=[], parentReleases=[]):
if not debrid_downloaded:
for release in self.Releases[:]:
if not regex.match(self.deviation(), release.title, regex.I):
ui_print("[download (show)] " + release.title + " does not match deviation " + self.deviation())
self.Releases.remove(release)
if self.season_pack(scraped_releases):
debrid_downloaded, retry = self.debrid_download()
Expand Down Expand Up @@ -1550,7 +1556,7 @@ def debrid_download(self, force=False):
def files(self):
files = []
if self.type == 'movie':
files = ['(mkv|mp4)']
files = ['(mkv|mp4|avi)']
elif self.type == 'show':
for season in self.Seasons:
for episode in season.Episodes:
Expand Down
26 changes: 17 additions & 9 deletions content/services/plex.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ def logerror(response):

def get(url, timeout=60):
try:
ui_print("[plex] Processing (get): " + url + " ...")
response = session.get(url, headers=headers, timeout=timeout)
logerror(response)
ui_print("done")
response = json.loads(response.content, object_hook=lambda d: SimpleNamespace(**d))
return response
except Exception as e:
Expand All @@ -40,8 +42,10 @@ def get(url, timeout=60):

def post(url, data):
try:
ui_print("[plex] Processing (post): " + url)
response = session.post(url, data=data, headers=headers)
logerror(response)
ui_print("[plex] (post) response: " + repr(response), debug=ui_settings.debug)
response = json.loads(response.content, object_hook=lambda d: SimpleNamespace(**d))
return response
except Exception as e:
Expand Down Expand Up @@ -128,6 +132,8 @@ def add(self, item, user):
elif item.type == 'movie':
self.data.append(movie(item.ratingKey))

# collect all new unique watchlisted items ACROSS ALL USERS by retrieving user watchlists and adding them to self.data
# (then remove any that are no longer in the watchlist which were added in previous runs)
def update(self):
update = False
new_watchlist = []
Expand Down Expand Up @@ -172,6 +178,7 @@ def __init__(self, other):
self.__dict__.update(other.__dict__)
self.EID = setEID(self)
self.Episodes = []
ui_print("[plex] Processing " + self.parentTitle + " " + self.title)
token = users[0][1]
if library.ignore.name in classes.ignore.active:
for user in users:
Expand Down Expand Up @@ -529,7 +536,7 @@ def __new__(cls, element):

class lable(classes.refresh):

name = 'Plex Lables'
name = 'Plex Labels'

def setup(cls, new=False):
ui_cls("Options/Settings/Library Services/Library update services")
Expand Down Expand Up @@ -586,7 +593,7 @@ def call(element):
retries += 1
library_item = next((x for x in current_library if element == x), None)
if library_item == None:
ui_print('[plex] error: couldnt add lables - item: "' + element.query() + '" could not be found on server.')
ui_print('[plex] error: couldnt add labels - item: "' + element.query() + '" could not be found on server.')
return
tags_string = ""
for tag in tags:
Expand All @@ -598,7 +605,7 @@ def call(element):
response = get(url)
library_item.__dict__.update(response.MediaContainer.Metadata[0].__dict__)
except Exception as e:
ui_print("[plex] error: couldnt add lables! Turn on debug printing for more info.")
ui_print("[plex] error: couldnt add labels! Turn on debug printing for more info.")
ui_print(str(e), debug=ui_settings.debug)

def __new__(cls, element):
Expand Down Expand Up @@ -632,12 +639,12 @@ def __new__(cls, element):
if len(tags) == 0:
return
element.post_tags = tags
ui_print('[plex] adding lables: "' + '","'.join(tags) + '" to item: "' + element.query() + '"')
ui_print('[plex] adding labels: "' + '","'.join(tags) + '" to item: "' + element.query() + '"')
results = [None]
t = Thread(target=multi_init, args=(library.lable.call, element, results, 0))
t.start()
except Exception as e:
ui_print("[plex] error: couldnt add lables! Turn on debug printing for more info.")
ui_print("[plex] error: couldnt add labels! Turn on debug printing for more info.")
ui_print(str(e), debug=ui_settings.debug)

class ignore(classes.ignore):
Expand Down Expand Up @@ -791,8 +798,8 @@ def __new__(self,silent=False):
types = ['1'] if Directory.type == "movie" else ['2', '3', '4']
sections += [[Directory.key,types]]
names += [Directory.title]
except:
ui_print("[plex error]: couldnt reach local plex server at: " + library.url + " to determine library sections. Make sure the address is correct, the server is running, and youve set up at least one library.")
except Exception as e:
ui_print("[plex error]: couldnt reach local plex server at: " + library.url + " to determine library sections. Make sure the address is correct, the server is running, and youve set up at least one library. Error:" + e)
if len(sections) == 0:
return list_
if not silent:
Expand Down Expand Up @@ -876,11 +883,12 @@ def __new__(self,silent=False):
episode.grandparentEID = item.EID
except:
ui_print('done')
ui_print("[plex error]: found incorrectly matched library item : " + item.title + " - this item needs a metadata refresh (open plex webui, find item, open item menu, refresh metadata).")
ui_print("[plex error]: found incorrectly matched library item : " + item.title + " - this item needs a metadata refresh (open plex webui, find item, open item menu, refresh metadata).")
ui_print('done')
current_library = copy.deepcopy(list_)
if first_load and updated:
store.save(current_library,"plex","metadata")
ui_print('[plex] saving library cache.')
store.save(current_library,"plex","metadata")
return list_

def search(query, library=[]):
Expand Down
1 change: 1 addition & 0 deletions content/services/textfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def add(self):
with open(library.ignore.path + "ignored.txt",'a') as f:
if not self.query() + '\n' in lines:
f.write(self.query() + '\n')
ui_print("[textfile] added " + self.query() + " to ignore list")
f.close()
if not self in classes.ignore.ignored:
classes.ignore.ignored += [self]
Expand Down
Loading