Skip to content

Commit 803995b

Browse files
authored
Merge branch 'custom-components:master' into master
2 parents 660301f + 5cdc66c commit 803995b

File tree

7 files changed

+70
-35
lines changed

7 files changed

+70
-35
lines changed

custom_components/plex_recently_added/__init__.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
CONF_NAME,
77
CONF_API_KEY,
88
CONF_HOST,
9-
CONF_PORT,
9+
CONF_PORT,
1010
CONF_SSL
11-
)
11+
)
1212

1313
from .const import (
1414
DOMAIN,
@@ -17,10 +17,8 @@
1717
CONF_SECTION_TYPES,
1818
CONF_SECTION_LIBRARIES,
1919
CONF_EXCLUDE_KEYWORDS,
20-
CONF_ON_DECK,
21-
CONF_VERIFY_SSL
22-
)
23-
20+
CONF_ON_DECK
21+
)
2422

2523
from .coordinator import PlexDataCoordinator
2624
from .helpers import setup_client
@@ -29,7 +27,6 @@
2927
)
3028
from .redirect import ImagesRedirect
3129

32-
3330
PLATFORMS = [
3431
Platform.SENSOR
3532
]
@@ -48,7 +45,6 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
4845
config_entry.data.get(CONF_SECTION_TYPES, []),
4946
config_entry.data.get(CONF_SECTION_LIBRARIES, []),
5047
config_entry.data.get(CONF_EXCLUDE_KEYWORDS, []),
51-
config_entry.data[CONF_VERIFY_SSL],
5248
)
5349
except FailedToLogin as err:
5450
raise ConfigEntryNotReady("Failed to Log-in") from err

custom_components/plex_recently_added/config_flow.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from typing import Any
2-
32
import voluptuous as vol
43

54
from homeassistant.helpers.selector import (
@@ -20,7 +19,7 @@
2019
CONF_HOST,
2120
CONF_PORT,
2221
CONF_SSL
23-
)
22+
)
2423

2524
from .const import (
2625
DOMAIN,
@@ -32,9 +31,8 @@
3231
CONF_EXCLUDE_KEYWORDS,
3332
CONF_SECTION_LIBRARIES_LABEL,
3433
CONF_EXCLUDE_KEYWORDS_LABEL,
35-
CONF_ON_DECK,
36-
CONF_VERIFY_SSL
37-
)
34+
CONF_ON_DECK
35+
)
3836

3937
from .helpers import setup_client
4038
from .plex_api import (
@@ -48,7 +46,6 @@
4846
vol.Required(CONF_PORT, default=32400): vol.All(vol.Coerce(int), vol.Range(min=0)),
4947
vol.Required(CONF_API_KEY): vol.All(str),
5048
vol.Optional(CONF_SSL, default=False): vol.All(bool),
51-
vol.Optional(CONF_VERIFY_SSL, default=True): vol.All(bool),
5249
vol.Optional(CONF_MAX, default=5): vol.All(vol.Coerce(int), vol.Range(min=0)),
5350
vol.Optional(CONF_ON_DECK, default=False): vol.All(bool),
5451
vol.Optional(CONF_SECTION_TYPES, default={"movie", "show"}): SelectSelector(SelectSelectorConfig(options=ALL_SECTION_TYPES, mode=SelectSelectorMode.DROPDOWN ,multiple=True)),
@@ -85,7 +82,6 @@ async def async_step_user(
8582
user_input.get(CONF_SECTION_TYPES, []),
8683
user_input.get(CONF_SECTION_LIBRARIES, []),
8784
user_input.get(CONF_EXCLUDE_KEYWORDS, []),
88-
user_input[CONF_VERIFY_SSL],
8985
)
9086
except FailedToLogin as err:
9187
errors = {'base': 'failed_to_login'}

custom_components/plex_recently_added/helpers.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@ async def setup_client(
1313
section_types: list,
1414
section_libraries: list,
1515
exclude_keywords: list,
16-
verify_ssl: bool,
17-
):
18-
client = PlexApi(hass, name, ssl, token, max, on_deck, host, port, section_types, section_libraries, exclude_keywords, verify_ssl)
16+
):
17+
client = PlexApi(hass, name, ssl, token, max, on_deck, host, port, section_types, section_libraries, exclude_keywords)
1918

2019
await client.update()
2120
return client

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.4.4"
12+
"version": "0.4.8"
1313
}

custom_components/plex_recently_added/parser.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ def parse_data(data, max, base_url, token, identifier, section_key, images_base_
3434

3535
output = []
3636
for item in sorted_data:
37-
thumb = item.get("thumb", item.get("parentThumb", item.get("grandparentThumb", None)))
38-
art = item.get("art", item.get("grandparentArt", None))
37+
media_type_map = {'movie': ('thumb', 'art'), 'episode': ('grandparentThumb', 'grandparentArt')}
38+
thumb_key, art_key = media_type_map.get(item['type'], ('thumb', 'grandparentArt'))
39+
thumb = item.get(thumb_key, item.get("parentThumb", item.get("grandparentThumb", None)))
40+
art = item.get(art_key, item.get("grandparentArt", None))
3941
deep_link_position = -1
4042
if section_key == "artist":
4143
deep_link_position = -2
@@ -68,6 +70,7 @@ def parse_data(data, max, base_url, token, identifier, section_key, images_base_
6870
data_output["genres"] = ", ".join([genre['tag'] for genre in item.get('Genre', [])][:3])
6971
data_output["rating"] = ('\N{BLACK STAR} ' + str(item.get("rating"))) if int(float(item.get("rating", 0))) > 0 else ''
7072
data_output['summary'] = item.get('summary', '')
73+
data_output['trailer'] = item.get('trailer')
7174
data_output["poster"] = (f'{images_base_url}?path={thumb}') if thumb else ""
7275
data_output["fanart"] = (f'{images_base_url}?path={art}') if art else ""
7376
data_output["deep_link"] = deep_link if identifier else None
@@ -90,4 +93,3 @@ def parse_data(data, max, base_url, token, identifier, section_key, images_base_
9093

9194
return output
9295

93-

custom_components/plex_recently_added/plex_api.py

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from homeassistant.core import HomeAssistant
77
from .const import DEFAULT_PARSE_DICT, USER_AGENT, ACCEPTS
88
from .parser import parse_data, parse_library
9-
9+
from .tmdb_api import get_tmdb_trailer_url
1010

1111
def check_headers(response):
1212
if 'text/xml' not in response.headers.get('Content-Type', '') and 'application/xml' not in response.headers.get('Content-Type', ''):
@@ -25,8 +25,7 @@ def __init__(
2525
port: int,
2626
section_types: list,
2727
section_libraries: list,
28-
exclude_keywords: list,
29-
verify_ssl: bool
28+
exclude_keywords: list
3029
):
3130
self._hass = hass
3231
self._ssl = 's' if ssl else ''
@@ -38,9 +37,8 @@ def __init__(
3837
self._section_types = section_types
3938
self._section_libraries = section_libraries
4039
self._exclude_keywords = exclude_keywords
41-
self._verify_ssl = verify_ssl
4240
self._images_base_url = f'/{name.lower() + "_" if len(name) > 0 else ""}plex_recently_added'
43-
41+
4442
async def update(self):
4543
info_url = 'http{0}://{1}:{2}'.format(
4644
self._ssl,
@@ -49,8 +47,6 @@ async def update(self):
4947
)
5048

5149
""" Getting the server identifier """
52-
if not self._verify_ssl:
53-
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
5450
try:
5551
info_res = await self._hass.async_add_executor_job(
5652
requests.get,
@@ -60,7 +56,6 @@ async def update(self):
6056
"User-agent": USER_AGENT,
6157
"Accept": ACCEPTS,
6258
},
63-
"verify":self._verify_ssl,
6459
"timeout":10
6560
}
6661
)
@@ -87,7 +82,6 @@ async def update(self):
8782
"User-agent": USER_AGENT,
8883
"Accept": ACCEPTS,
8984
},
90-
"verify":self._verify_ssl,
9185
"timeout":10
9286
}
9387
)
@@ -117,29 +111,42 @@ async def update(self):
117111
"User-agent": USER_AGENT,
118112
"Accept": ACCEPTS,
119113
},
120-
"verify":self._verify_ssl,
121114
"timeout":10
122115
}
123116
)
124117
check_headers(sub_sec)
125118
root = ElementTree.fromstring(sub_sec.text)
126119
parsed_libs = parse_library(root)
120+
121+
# Fetch trailer URLs for each item
122+
for item in parsed_libs:
123+
item['trailer'] = await get_tmdb_trailer_url(self._hass, item['title'], library['type'])
124+
127125
if library["type"] not in data['all']:
128126
data['all'][library["type"]] = []
129127
data['all'][library["type"]] += parsed_libs
130128
data[library["type"]] += parsed_libs
131129

132130
data_out = {}
133131
for k in data.keys():
134-
data_out[k] = {'data': [DEFAULT_PARSE_DICT] + parse_data(data[k], self._max, info_url, self._token, identifier, k, self._images_base_url, k == "all")}
132+
parsed_data = parse_data(data[k], self._max, info_url, self._token, identifier, k, self._images_base_url, k == "all")
133+
134+
# Ensure trailer URLs are correctly set for the "all" sensor
135+
if k == "all":
136+
for item in parsed_data:
137+
if item.get('trailer') is None:
138+
item_type = 'movie' if item.get('episode') == '' else 'show'
139+
item['trailer'] = await get_tmdb_trailer_url(self._hass, item['title'], item_type)
140+
141+
data_out[k] = {'data': [DEFAULT_PARSE_DICT] + parsed_data}
135142

136143
return {
137144
"data": {**data_out},
138145
"online": True,
139146
"libraries": libs
140147
}
141-
148+
142149

143150
class FailedToLogin(Exception):
144151
"Raised when the Plex user fail to Log-in"
145-
pass
152+
pass
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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

0 commit comments

Comments
 (0)