Skip to content

Commit c226a9c

Browse files
committed
Fixed missing attributes Episode, Genres, Ratings. Misc. bug fixes.
1 parent e53453e commit c226a9c

4 files changed

Lines changed: 88 additions & 47 deletions

File tree

custom_components/plex_recently_added/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
"iot_class": "local_polling",
1010
"issue_tracker": "https://github.com/custom-components/sensor.plex_recently_added/issues",
1111
"requirements": [],
12-
"version": "0.5.7"
12+
"version": "0.5.9"
1313
}

custom_components/plex_recently_added/parser.py

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,33 @@ def _stable_signed_path(hass: HomeAssistant, raw_path: str, ttl_minutes: int) ->
3535

3636
def parse_library(root):
3737
output = []
38+
39+
def parse_medium(medium):
40+
data = dict(medium.attrib)
41+
42+
children = {}
43+
44+
for child in medium:
45+
if "tag" in child.attrib:
46+
tag_name = child.tag
47+
tag_value = child.get("tag")
48+
49+
children.setdefault(tag_name, []).append(tag_value)
50+
51+
data.update(children)
52+
53+
return data
54+
3855
for medium in root.findall("Video"):
39-
output.append(medium.attrib)
56+
output.append(parse_medium(medium))
4057

41-
if len(output) == 0:
58+
if not output:
4259
for medium in root.findall("Directory"):
43-
output.append(medium.attrib)
60+
output.append(parse_medium(medium))
4461

45-
if len(output) == 0:
62+
if not output:
4663
for medium in root.findall("Photo"):
47-
output.append(medium.attrib)
64+
output.append(parse_medium(medium))
4865

4966
return output
5067

@@ -90,7 +107,7 @@ def parse_data(hass: HomeAssistant, data, max, base_url, token, identifier, sect
90107
data_output["release"] = '$day, $date $time'
91108
data_output["flag"] = "viewCount" not in item
92109
data_output["title"] = item.get("grandparentTitle", item.get("parentTitle", item.get("title", "")))
93-
if item.get("title", None):
110+
if item.get("title", None) and item.get("type", "unknown") in ("show", "album", "episode"):
94111
data_output["episode"] = item["title"]
95112
else:
96113
data_output["episode"] = ''
@@ -105,8 +122,18 @@ def parse_data(hass: HomeAssistant, data, max, base_url, token, identifier, sect
105122
if int(item.get('duration', 0)) > 0:
106123
data_output["runtime"] = math.floor(int(item["duration"]) / 60000)
107124
data_output["studio"] = item.get("studio", "")
108-
data_output["genres"] = ", ".join([genre['tag'] for genre in item.get('Genre', [])][:3])
109-
data_output["rating"] = ('\N{BLACK STAR} ' + str(item.get("rating"))) if int(float(item.get("rating", 0))) > 0 else ''
125+
plex_genres = item.get('Genre', [])[:3]
126+
if not plex_genres:
127+
plex_genres = (item.get('tmdb_genres') or [])[:3]
128+
data_output["genres"] = ", ".join(plex_genres)
129+
plex_rating = float(item.get("rating") or 0)
130+
tmdb_rating = float(item.get("tmdb_rating") or 0)
131+
if plex_rating > 0:
132+
data_output["rating"] = '\N{BLACK STAR} ' + item.get("rating")
133+
elif tmdb_rating > 0:
134+
data_output["rating"] = '\N{BLACK STAR} ' + str(round(tmdb_rating, 1))
135+
else:
136+
data_output["rating"] = ''
110137
data_output['summary'] = item.get('summary', '')
111138
data_output['trailer'] = item.get('trailer')
112139

custom_components/plex_recently_added/plex_api.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,13 @@ async def update(self):
119119
root = ElementTree.fromstring(sub_sec.text)
120120
parsed_libs = parse_library(root)
121121

122-
# Fetch trailer URLs for each item
122+
# Fetch TMDB data (trailer, rating, genres) for each item
123123
for item in parsed_libs:
124-
item['trailer'] = await get_tmdb_trailer_url(self._hass, item['title'], library['type'])
124+
search_title = item.get('grandparentTitle', item.get('title', ''))
125+
tmdb_data = await get_tmdb_trailer_url(self._hass, search_title, library['type'])
126+
item['trailer'] = tmdb_data['trailer']
127+
item['tmdb_rating'] = tmdb_data['tmdb_rating']
128+
item['tmdb_genres'] = tmdb_data['tmdb_genres']
125129

126130
if library["type"] not in data['all']:
127131
data['all'][library["type"]] = []
@@ -140,7 +144,8 @@ async def update(self):
140144
for item in parsed_data:
141145
if item.get('trailer') is None:
142146
item_type = 'movie' if item.get('episode') == '' else 'show'
143-
item['trailer'] = await get_tmdb_trailer_url(self._hass, item['title'], item_type)
147+
tmdb_data = await get_tmdb_trailer_url(self._hass, item['title'], item_type)
148+
item['trailer'] = tmdb_data['trailer']
144149

145150
data_out[k] = {'data': [DEFAULT_PARSE_DICT] + parsed_data}
146151

Lines changed: 44 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,44 @@
1-
import aiohttp
2-
3-
TMDB_API_KEY = '1f7708bb9a218ab891a5d438b1b63992'
4-
TMDB_SEARCH_URL = 'https://api.themoviedb.org/3/search/{media_type}?api_key={api_key}&query={query}'
5-
TMDB_DETAILS_URL = 'https://api.themoviedb.org/3/{media_type}/{tmdb_id}?api_key={api_key}&append_to_response=videos'
6-
7-
async def get_tmdb_trailer_url(hass, title, media_type):
8-
if media_type == 'show':
9-
media_type = 'tv'
10-
elif media_type == 'movie':
11-
media_type = 'movie'
12-
else:
13-
return None
14-
15-
async with aiohttp.ClientSession() as session:
16-
# Search for the movie or TV show
17-
search_url = TMDB_SEARCH_URL.format(media_type=media_type, api_key=TMDB_API_KEY, query=title)
18-
async with session.get(search_url) as response:
19-
search_data = await response.json()
20-
if not search_data.get('results'):
21-
return None
22-
23-
tmdb_id = search_data['results'][0]['id']
24-
25-
# Get details including videos
26-
details_url = TMDB_DETAILS_URL.format(media_type=media_type, tmdb_id=tmdb_id, api_key=TMDB_API_KEY)
27-
async with session.get(details_url) as response:
28-
details_data = await response.json()
29-
30-
videos = details_data.get('videos', {}).get('results', [])
31-
for video in videos:
32-
if video['type'] == 'Trailer' and video['site'] == 'YouTube':
33-
return f'https://www.youtube.com/watch?v={video["key"]}'
34-
35-
return None
1+
import aiohttp
2+
3+
TMDB_API_KEY = '1f7708bb9a218ab891a5d438b1b63992'
4+
TMDB_SEARCH_URL = 'https://api.themoviedb.org/3/search/{media_type}?api_key={api_key}&query={query}'
5+
TMDB_DETAILS_URL = 'https://api.themoviedb.org/3/{media_type}/{tmdb_id}?api_key={api_key}&append_to_response=videos'
6+
7+
EMPTY_TMDB_RESULT = {'trailer': None, 'tmdb_rating': None, 'tmdb_genres': None}
8+
9+
async def get_tmdb_trailer_url(hass, title, media_type):
10+
if media_type == 'show':
11+
media_type = 'tv'
12+
elif media_type == 'movie':
13+
media_type = 'movie'
14+
else:
15+
return EMPTY_TMDB_RESULT.copy()
16+
17+
async with aiohttp.ClientSession() as session:
18+
# Search for the movie or TV show
19+
search_url = TMDB_SEARCH_URL.format(media_type=media_type, api_key=TMDB_API_KEY, query=title)
20+
async with session.get(search_url) as response:
21+
search_data = await response.json()
22+
if not search_data.get('results'):
23+
return EMPTY_TMDB_RESULT.copy()
24+
25+
tmdb_id = search_data['results'][0]['id']
26+
27+
# Get details including videos
28+
details_url = TMDB_DETAILS_URL.format(media_type=media_type, tmdb_id=tmdb_id, api_key=TMDB_API_KEY)
29+
async with session.get(details_url) as response:
30+
details_data = await response.json()
31+
32+
tmdb_rating = details_data.get('vote_average', 0)
33+
tmdb_genres = [g['name'] for g in details_data.get('genres', [])]
34+
35+
trailer_url = None
36+
videos = details_data.get('videos', {}).get('results', [])
37+
for video in videos:
38+
if video['type'] == 'Trailer' and video['site'] == 'YouTube':
39+
trailer_url = f'https://www.youtube.com/watch?v={video["key"]}'
40+
break
41+
42+
return {'trailer': trailer_url, 'tmdb_rating': tmdb_rating, 'tmdb_genres': tmdb_genres}
43+
44+
return EMPTY_TMDB_RESULT.copy()

0 commit comments

Comments
 (0)