Skip to content

Commit

Permalink
Switched to using youtube video trailers instead of the native plex t…
Browse files Browse the repository at this point in the history
…railers for consistency with other UMC-compatible integrations
  • Loading branch information
mkanet committed Jun 25, 2024
1 parent cdd6c21 commit 5cdc66c
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 32 deletions.
2 changes: 1 addition & 1 deletion custom_components/plex_recently_added/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
"iot_class": "local_polling",
"issue_tracker": "https://github.com/custom-components/sensor.plex_recently_added/issues",
"requirements": [],
"version": "0.4.7"
"version": "0.4.8"
}
44 changes: 13 additions & 31 deletions custom_components/plex_recently_added/plex_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from homeassistant.core import HomeAssistant
from .const import DEFAULT_PARSE_DICT, USER_AGENT, ACCEPTS
from .parser import parse_data, parse_library

from .tmdb_api import get_tmdb_trailer_url

def check_headers(response):
if 'text/xml' not in response.headers.get('Content-Type', '') and 'application/xml' not in response.headers.get('Content-Type', ''):
Expand Down Expand Up @@ -38,33 +38,6 @@ def __init__(
self._section_libraries = section_libraries
self._exclude_keywords = exclude_keywords
self._images_base_url = f'/{name.lower() + "_" if len(name) > 0 else ""}plex_recently_added'

async def get_trailer_url(self, item_key):
extras_url = f'http{self._ssl}://{self._host}:{self._port}/library/metadata/{item_key}/extras?X-Plex-Token={self._token}'
try:
extras_res = await self._hass.async_add_executor_job(
requests.get,
extras_url,
{
"headers": {
"User-agent": USER_AGENT,
"Accept": ACCEPTS,
},
"timeout": 10
}
)
check_headers(extras_res)
root = ElementTree.fromstring(extras_res.text)

for video in root.findall(".//Video"):
if video.get("type") == "clip" and video.get("subtype") == "trailer":
part = video.find(".//Part")
if part is not None and part.get("key"):
return f'http{self._ssl}://{self._host}:{self._port}{part.get("key")}&X-Plex-Token={self._token}'

except Exception as e:
print(f"Error fetching trailer: {str(e)}")
return None

async def update(self):
info_url = 'http{0}://{1}:{2}'.format(
Expand Down Expand Up @@ -147,7 +120,7 @@ async def update(self):

# Fetch trailer URLs for each item
for item in parsed_libs:
item['trailer'] = await self.get_trailer_url(item['ratingKey'])
item['trailer'] = await get_tmdb_trailer_url(self._hass, item['title'], library['type'])

if library["type"] not in data['all']:
data['all'][library["type"]] = []
Expand All @@ -156,14 +129,23 @@ async def update(self):

data_out = {}
for k in data.keys():
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")}
parsed_data = parse_data(data[k], self._max, info_url, self._token, identifier, k, self._images_base_url, k == "all")

# Ensure trailer URLs are correctly set for the "all" sensor
if k == "all":
for item in parsed_data:
if item.get('trailer') is None:
item_type = 'movie' if item.get('episode') == '' else 'show'
item['trailer'] = await get_tmdb_trailer_url(self._hass, item['title'], item_type)

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

return {
"data": {**data_out},
"online": True,
"libraries": libs
}


class FailedToLogin(Exception):
"Raised when the Plex user fail to Log-in"
Expand Down
35 changes: 35 additions & 0 deletions custom_components/plex_recently_added/tmdb_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import aiohttp

TMDB_API_KEY = '1f7708bb9a218ab891a5d438b1b63992'
TMDB_SEARCH_URL = 'https://api.themoviedb.org/3/search/{media_type}?api_key={api_key}&query={query}'
TMDB_DETAILS_URL = 'https://api.themoviedb.org/3/{media_type}/{tmdb_id}?api_key={api_key}&append_to_response=videos'

async def get_tmdb_trailer_url(hass, title, media_type):
if media_type == 'show':
media_type = 'tv'
elif media_type == 'movie':
media_type = 'movie'
else:
return None

async with aiohttp.ClientSession() as session:
# Search for the movie or TV show
search_url = TMDB_SEARCH_URL.format(media_type=media_type, api_key=TMDB_API_KEY, query=title)
async with session.get(search_url) as response:
search_data = await response.json()
if not search_data.get('results'):
return None

tmdb_id = search_data['results'][0]['id']

# Get details including videos
details_url = TMDB_DETAILS_URL.format(media_type=media_type, tmdb_id=tmdb_id, api_key=TMDB_API_KEY)
async with session.get(details_url) as response:
details_data = await response.json()

videos = details_data.get('videos', {}).get('results', [])
for video in videos:
if video['type'] == 'Trailer' and video['site'] == 'YouTube':
return f'https://www.youtube.com/watch?v={video["key"]}'

return None

0 comments on commit 5cdc66c

Please sign in to comment.