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

Commit

Permalink
rapidfuzz, title caching, cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
maykar committed Mar 2, 2021
1 parent 486d9c9 commit cec39c5
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 50 deletions.
19 changes: 11 additions & 8 deletions custom_components/plex_assistant/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@
async def async_setup(hass: HomeAssistant, config: Config):
if DOMAIN in config:
changes_url = "https://github.com/maykar/plex_assistant/blob/master/ver_one_update.md"
message = "Configuration is now handled in the UI, please read the %s for how to migrate " \
"to the new version and more info.%s "
message = (
"Configuration is now handled in the UI, please read the %s for how to migrate "
"to the new version and more info.%s "
)
service_data = {
"title": "Plex Assistant Breaking Changes",
"message": message % (f"[change log]({changes_url})", "."),
Expand Down Expand Up @@ -71,17 +73,17 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
def pa_executor(_server, start_script_keys):
_pa = PlexAssistant(_server, start_script_keys)
get_devices(hass, _pa)
_LOGGER.debug(f"Media titles: {len(_pa.media['all_titles'])}")
return _pa

pa = await hass.async_add_executor_job(pa_executor, server, list(start_script.keys()))

ifttt_listener = await listeners(hass)
hass.data[DOMAIN][entry.entry_id] = {"remove_listener": ifttt_listener}

tts_dir = hass.config.path() + "/www/plex_assist_tts/"
if tts_errors and not os.path.exists(tts_dir):
os.makedirs(tts_dir, mode=0o777)

ifttt_listener = await listeners(hass)
hass.data[DOMAIN][entry.entry_id] = {"remove_listener": ifttt_listener}
entry.add_update_listener(async_reload_entry)

def handle_input(call):
Expand All @@ -108,7 +110,8 @@ def handle_input(call):
return

if pa.media["updated"] < pa.library.search(sort="addedAt:desc", limit=1)[0].addedAt:
pa.update_libraries()
type(pa).media.fget.cache_clear()
_LOGGER.debug(f"Updated Library: {pa.media['updated']}")

device = fuzzy(command["device"] or default_device, pa.device_names)
device = run_start_script(hass, pa, command, start_script, device, default_device)
Expand All @@ -135,12 +138,12 @@ def handle_input(call):
play_tts_error(hass, tts_dir, device["entity_id"], error, lang)
return

_LOGGER.debug("Media: %s", str(media))
_LOGGER.debug("Media: %s", str(media.items))

payload = '%s{"playqueue_id": %s, "type": "%s"}' % (
"plex://" if device["device_type"] in ["cast", "sonos"] else "",
media.playQueueID,
media.playQueueType
media.playQueueType,
)

media_service(hass, device["entity_id"], "play_media", payload)
Expand Down
4 changes: 2 additions & 2 deletions custom_components/plex_assistant/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def get_devices(_self):
if "plex" in info or "cast" in info:
try:
devices.append(_self.hass.states.get(entity.entity_id).attributes.get("friendly_name"))
except:
except AttributeError:
continue
else:
continue
Expand All @@ -24,7 +24,7 @@ def get_devices(_self):
def get_servers(_self):
try:
return [x.title for x in _self.hass.config_entries.async_entries("plex")]
except:
except (KeyError, AttributeError):
return []


Expand Down
56 changes: 26 additions & 30 deletions custom_components/plex_assistant/helpers.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import re
import time
import uuid
import json
import pychromecast

from fuzzywuzzy import fuzz
from fuzzywuzzy import process
from rapidfuzz import fuzz, process
from gtts import gTTS
from json import JSONDecodeError, loads
from homeassistant.components.plex.services import get_plex_server
from homeassistant.exceptions import HomeAssistantError, ServiceNotFound
from homeassistant.core import Context
from pychromecast.controllers.plex import PlexController

Expand All @@ -16,38 +16,34 @@

def fuzzy(media, lib, scorer=fuzz.QRatio):
if isinstance(lib, list) and len(lib) > 0:
return process.extractOne(media, lib, scorer=scorer)
return process.extractOne(media, lib, scorer=scorer) or ["", 0]
return ["", 0]


def process_config_item(options, item_type):
item = options.get(item_type)
if item:
try:
item = json.loads("{" + item + "}")
for i in item.keys():
_LOGGER.debug(f"{item_type} {i}: {item[i]}")
except Exception:
item = {}
return item
return {}
def process_config_item(options, option_type):
option = options.get(option_type)
if not option:
return {}
try:
option = loads("{" + option + "}")
for i in option.keys():
_LOGGER.debug(f"{option_type} {i}: {option[i]}")
except (TypeError, AttributeError, KeyError, JSONDecodeError):
_LOGGER.warning(f"There is a formatting error in the {option_type.replace('_', ' ')} config.")
option = {}
return option


async def get_server(hass, config, server_name):
try:
await hass.helpers.discovery.async_discover(None, None, "plex", config)
return get_plex_server(hass, server_name)._plex_server
except Exception as ex:
if ex.args[0] == "No Plex servers available":
server_name_str = ", the server_name is correct," if server_name else ""
_LOGGER.warning(
"Plex Assistant: Plex server not found. Ensure that you've setup the HA "
f"Plex integration{server_name_str} and the server is reachable. "
)
else:
template = "An exception of type {0} occurred. Arguments:\n{1!r}"
message = template.format(type(ex).__name__, ex.args)
_LOGGER.warning(message)
except HomeAssistantError as error:
server_name_str = ", the server_name is correct," if server_name else ""
_LOGGER.warning(
f"Plex Assistant: {error.args[0]}. Ensure that you've setup the HA "
f"Plex integration{server_name_str} and the server is reachable. "
)


def get_devices(hass, pa):
Expand All @@ -58,7 +54,7 @@ def get_devices(hass, pa):
continue
try:
name = hass.states.get(entity.entity_id).attributes.get("friendly_name")
except Exception:
except AttributeError:
continue
pa.devices[name] = {"entity_id": entity.entity_id, "device_type": dev_type}

Expand All @@ -81,7 +77,7 @@ def ifttt_webhook_callback(event):
listener = hass.bus.async_listen("ifttt_webhook_received", ifttt_webhook_callback)
try:
await hass.services.async_call("conversation", "process", {"text": "tell plex to initialize_plex_intent"})
except Exception:
except ServiceNotFound:
pass
return listener

Expand Down Expand Up @@ -253,14 +249,14 @@ def filter_media(pa, command, media, library):
media = unwatched if unwatched and not command["random"] else media.episodes()[:30]
elif getattr(media, "TYPE", None) == "episode":
episodes = media.show().episodes()
episodes = episodes[episodes.index(media):episodes.index(media) + 30]
episodes = episodes[episodes.index(media) : episodes.index(media) + 30]
media = pa.server.createPlayQueue(episodes, shuffle=int(command["random"]))
elif getattr(media, "TYPE", None) in ["artist", "album"]:
tracks = media.tracks()
media = pa.server.createPlayQueue(tracks, shuffle=int(command["random"]))
elif getattr(media, "TYPE", None) == "track":
tracks = media.album().tracks()
tracks = tracks[tracks.index(media):]
tracks = tracks[tracks.index(media) :]
media = pa.server.createPlayQueue(tracks, shuffle=int(command["random"]))

if getattr(media, "TYPE", None) != "playqueue" and media:
Expand Down
2 changes: 1 addition & 1 deletion custom_components/plex_assistant/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"requirements": [
"gTTs>=2.2.1",
"pychromecast>=8.0.0",
"fuzzywuzzy==0.18.0",
"rapidfuzz==1.1.1",
"plexapi>=4.3.0",
"awesomeversion>=21.2.2"
]
Expand Down
19 changes: 10 additions & 9 deletions custom_components/plex_assistant/plex_assistant.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
from datetime import datetime
from functools import lru_cache


class PlexAssistant:
def __init__(self, server, start_script_keys):
self.server = server
self.library = self.server.library
self.devices = {}
self.media = {}
self.start_script_keys = start_script_keys
self.update_libraries()
self.tv_id = self.get_section_id("show")
self.movie_id = self.get_section_id("movie")
self.music_id = self.get_section_id("artist")
Expand All @@ -30,14 +29,16 @@ def section_id(self):
"track": self.music_id,
}

def update_libraries(self):
self.library.reload()
self.media["all_titles"] = []
@property
@lru_cache()
def media(self):
media_items = {"all_titles": []}
for item in ["show", "movie", "artist", "album", "track"]:
self.media[f"{item}_titles"] = [x.title for x in self.library.search(libtype=item, sort="addedAt:desc")]
self.media["all_titles"] += self.media[f"{item}_titles"]
self.media["playlist_titles"] = [x.title for x in self.server.playlists()]
self.media["updated"] = datetime.now()
media_items[f"{item}_titles"] = [x.title for x in self.library.search(libtype=item, sort="addedAt:desc")]
media_items["all_titles"] += media_items[f"{item}_titles"]
media_items["playlist_titles"] = [x.title for x in self.server.playlists()]
media_items["updated"] = datetime.now()
return media_items

def get_section_id(self, section):
section = self.library.search(libtype=section, limit=1)
Expand Down

0 comments on commit cec39c5

Please sign in to comment.