Skip to content

Commit fbae6f7

Browse files
committed
Add Jellyseerr Support #58
1 parent 2ea7eba commit fbae6f7

File tree

2 files changed

+105
-2
lines changed

2 files changed

+105
-2
lines changed

main.py

+23-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from typing import cast
22
from utils.jellyfin import JellyfinClient
3+
from utils.jellyseerr import JellyseerrClient
34
import pluginlib
45
from loguru import logger
56
from pyaml_env import parse_config
@@ -23,6 +24,14 @@ def main(config):
2324
user_id=config['jellyfin']['user_id']
2425
)
2526

27+
if "jellyseerr" in config:
28+
js_client = JellyseerrClient(
29+
server_url=config['jellyseerr']['server_url'],
30+
api_key=config['jellyseerr']['api_key']
31+
)
32+
else:
33+
js_client = None
34+
2635
# Load plugins
2736
loader = pluginlib.PluginLoader(modules=['plugins'])
2837
plugins = loader.plugins['list_scraper']
@@ -45,15 +54,27 @@ def main(config):
4554
list_info = plugins[plugin_name].get_list(list_id, config['plugins'][plugin_name])
4655

4756
# Find jellyfin collection or create it
48-
collection_id = jf_client.find_collection_with_name_or_create(list_info['name'], list_id, list_info.get("description", None), plugin_name)
57+
collection_id = jf_client.find_collection_with_name_or_create(
58+
list_info['name'],
59+
list_id,
60+
list_info.get("description", None),
61+
plugin_name
62+
)
4963

5064
if config["plugins"][plugin_name].get("clear_collection", False):
5165
# Optionally clear everything from the collection first
5266
jf_client.clear_collection(collection_id)
5367

5468
# Add items to the collection
5569
for item in list_info['items']:
56-
jf_client.add_item_to_collection(collection_id, item, year_filter=config["plugins"][plugin_name].get("year_filter", True))
70+
matched = jf_client.add_item_to_collection(
71+
collection_id,
72+
item,
73+
year_filter=config["plugins"][plugin_name].get("year_filter", True)
74+
)
75+
if not matched and js_client is not None:
76+
js_client.make_request(item)
77+
5778

5879

5980
if __name__ == "__main__":

utils/jellyseerr.py

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import requests
2+
import urllib.parse
3+
from loguru import logger
4+
5+
class JellyseerrClient:
6+
def __init__(self, server_url: str, api_key: str):
7+
# Fix common url issues
8+
if server_url.endswith("/"):
9+
server_url = server_url[:-1] # Remove trailing slash
10+
if not server_url.endswith("/api/v1"):
11+
server_url += "/api/v1"
12+
self.server_url = server_url
13+
self.api_key = api_key
14+
15+
# Check if server is reachable
16+
try:
17+
r = requests.get(self.server_url + "/status")
18+
if r.status_code != 200:
19+
raise Exception("Jellyseerr Server is not reachable")
20+
except requests.exceptions.ConnectionError:
21+
raise Exception("Jellyseerr Server is not reachable")
22+
23+
# Check if api key is valid
24+
r = requests.get(f"{self.server_url}/auth/me")
25+
26+
27+
def make_request(self, item):
28+
'''Request item from jellyseerr'''
29+
30+
# Search for item
31+
r = requests.get(f"{self.server_url}/search", params={
32+
"query": urllib.parse.quote_plus(item["title"])
33+
}, headers={
34+
"X-Api-Key": self.api_key
35+
})
36+
37+
# Find matching item
38+
mediaId = None
39+
for result in r.json()["results"]:
40+
# Try IMDB match first
41+
if "mediaInfo" in result and "ImdbId" in result["mediaInfo"]:
42+
imdb_id = result["mediaInfo"]["ImdbId"]
43+
if imdb_id == item["imdb_id"]:
44+
mediaId = result["id"]
45+
logger.debug(f"Found exact IMDB match for {item['title']}")
46+
break
47+
elif "releaseDate" in result:
48+
# Try year match
49+
release_year = result["releaseDate"].split("-")[0]
50+
if release_year == str(item["release_year"]):
51+
mediaId = result["id"]
52+
logger.debug(f"Found year match for {item['title']}")
53+
break
54+
55+
# Request item if not found
56+
if mediaId is not None:
57+
if "mediaInfo" not in result or result["mediaInfo"]["jellyfinMediaId"] is None:
58+
# If it's not already in Jellyfin
59+
# Request item
60+
r = requests.post(f"{self.server_url}/request", json={
61+
"mediaType": result["mediaType"],
62+
"mediaId": mediaId,
63+
}, headers={
64+
"X-Api-Key": self.api_key
65+
})
66+
logger.info(f"Requested {item['title']} from Jellyseerr")
67+
68+
69+
70+
if __name__ == "__main__":
71+
from pyaml_env import parse_config
72+
config = parse_config("/home/thomas/Documents/Jellyfin-Auto-Collections/config.yaml", default_value=None)
73+
74+
client = JellyseerrClient(
75+
server_url=config["jellyseerr"]["server_url"],
76+
api_key=config["jellyseerr"]["api_key"]
77+
)
78+
client.make_request({
79+
"title": "The Matrix",
80+
"imdb_id": "tt0133093",
81+
"release_year": 1999
82+
})

0 commit comments

Comments
 (0)