From 4f246d1874e7aac7b9345d6d747a3d604fa8145c Mon Sep 17 00:00:00 2001 From: miro Date: Fri, 21 Jun 2024 02:15:38 +0100 Subject: [PATCH 1/3] refactor/ocp_modernize return the new OCP MediaEntry/Playlist objects instead of needing to know a json structure --- __init__.py | 91 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 29 deletions(-) diff --git a/__init__.py b/__init__.py index d6f29e3..788a1ab 100644 --- a/__init__.py +++ b/__init__.py @@ -1,8 +1,9 @@ from os.path import join, dirname +from typing import Iterable, Union, List from json_database import JsonStorage from ovos_utils import classproperty -from ovos_utils.ocp import MediaType, PlaybackType +from ovos_utils.ocp import MediaType, PlaybackType, Playlist, PluginStream, dict2entry, MediaEntry from ovos_utils.parse import match_one, MatchStrategy from ovos_utils.process_utils import RuntimeRequirements from ovos_workshop.decorators import ocp_search, ocp_featured_media @@ -93,32 +94,29 @@ def _score(self, phrase, entry, langs=None, base_score=0): # match name _, alias_score = match_one(phrase, entry["aliases"], strategy=MatchStrategy.TOKEN_SORT_RATIO) - entry["match_confidence"] = score + alias_score * 60 + match_confidence = score + alias_score * 60 # match languages if entry["lang"] in langs: - entry["match_confidence"] += 25 # lang bonus + match_confidence += 25 # lang bonus elif any([lang in entry.get("secondary_langs", []) for lang in langs]): - entry["match_confidence"] += 10 # smaller lang bonus + match_confidence += 10 # smaller lang bonus else: - entry["match_confidence"] -= 20 # wrong language penalty + match_confidence -= 20 # wrong language penalty # default news feed gets a nice bonus if entry.get("is_default"): - entry["match_confidence"] += 30 + match_confidence += 30 - return min([entry["match_confidence"], 100]) + return min([match_confidence, 100]) - @ocp_featured_media() - def news_playlist(self): + def read_db(self) -> List[dict]: entries = [] - for lang in self.archive: default_feed = self.langdefaults.get(lang) if lang == self.lang: default_feed = self.settings.get("default_feed") or default_feed - for feed, config in self.archive[lang].items(): if feed == default_feed: config["is_default"] = True @@ -134,8 +132,46 @@ def news_playlist(self): entries.append(config) return entries + @ocp_featured_media() + def news_playlist(self) -> Playlist: + entries = Playlist(title="Latest News (Station Playlist)") + for config in self.read_db(): + if config["uri"].startswith("rss//"): + entries.append(PluginStream( + extractor_id="rss", + stream=config["uri"].split("rss//")[-1], + title=config.get("title"), + image=config.get("image"), + media_type=MediaType.NEWS, + playback=PlaybackType.AUDIO, + skill_icon=self.skill_icon, + skill_id=self.skill_id) + ) + elif config["uri"].startswith("news//"): + entries.append(PluginStream( + extractor_id="news", + stream=config["uri"].split("news//")[-1], + title=config.get("title"), + image=config.get("image"), + media_type=MediaType.NEWS, + playback=PlaybackType.AUDIO, + skill_icon=self.skill_icon, + skill_id=self.skill_id) + ) + else: + entries.append(MediaEntry( + uri=config["uri"], + title=config.get("title"), + image=config.get("image"), + media_type=MediaType.NEWS, + playback=PlaybackType.AUDIO, + skill_icon=self.skill_icon, + skill_id=self.skill_id) + ) + return entries + @ocp_search() - def search_news(self, phrase, media_type): + def search_news(self, phrase, media_type) -> Iterable[Union[Playlist, MediaType, PluginStream]]: """Analyze phrase to see if it is a play-able phrase with this skill. Arguments: @@ -171,31 +207,28 @@ def search_news(self, phrase, media_type): phrase = entities["news_provider"] else: phrase = self.clean_phrase(phrase) + results = [] + # playlist result + if pl and base_score >= 50: + results.append(pl) if entities or media_type == MediaType.NEWS: - for v in pl: + for v in self.read_db(): s = self._score(phrase, v, langs=langs, base_score=base_score) if s <= 50: continue - v["match_confidence"] = min(100, s) + if v["uri"].startswith("news//"): + v["extractor_id"] = "news" + v["stream"] = v["uri"].split("news//")[-1] + elif v["uri"].startswith("rss//"): + v["extractor_id"] = "rss" + v["stream"] = v["uri"].split("rss//")[-1] + v = dict2entry(v) + v.match_confidence = min(100, s) results.append(v) - # playlist result - if pl and base_score >= 50: - results.append({ - "match_confidence": base_score, - "media_type": MediaType.NEWS, - "playlist": pl, - "playback": PlaybackType.AUDIO, - "image": self.skill_icon, - "bg_image": self.skill_icon, - "skill_icon": self.skill_icon, - "title": "Latest News (Station Playlist)", - "skill_id": self.skill_id - }) - - return sorted(results, key=lambda k: k["match_confidence"], reverse=True) + return sorted(results, key=lambda k: k.match_confidence, reverse=True) if __name__ == "__main__": From 1e523fba2faf89753c740a180d447c8b27c35994 Mon Sep 17 00:00:00 2001 From: miro Date: Fri, 21 Jun 2024 14:31:39 +0100 Subject: [PATCH 2/3] fix/allow_ocp_objects MediaEntry/Playlist/PluginStream objects should be allowed in ocp decorators --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index e135e92..73c9534 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,4 +3,4 @@ pytz feedparser~=6.0 ovos-utils~=0.0, >=0.1.0a17 ovos-bus-client>=0.0.9a1 -ovos-workshop>=0.0.16a3 +ovos-workshop>=0.0.16a39 From 681b8be50abb1c97b06fc59371e02df104d902f1 Mon Sep 17 00:00:00 2001 From: miro Date: Fri, 21 Jun 2024 15:53:28 +0100 Subject: [PATCH 3/3] utils 0.0.38 compat --- __init__.py | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/__init__.py b/__init__.py index 788a1ab..603b6ce 100644 --- a/__init__.py +++ b/__init__.py @@ -3,7 +3,7 @@ from json_database import JsonStorage from ovos_utils import classproperty -from ovos_utils.ocp import MediaType, PlaybackType, Playlist, PluginStream, dict2entry, MediaEntry +from ovos_workshop.backwards_compat import MediaType, PlaybackType, Playlist, PluginStream, dict2entry, MediaEntry from ovos_utils.parse import match_one, MatchStrategy from ovos_utils.process_utils import RuntimeRequirements from ovos_workshop.decorators import ocp_search, ocp_featured_media diff --git a/requirements.txt b/requirements.txt index 73c9534..bba78ef 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ beautifulsoup4 pytz feedparser~=6.0 -ovos-utils~=0.0, >=0.1.0a17 +ovos-utils >= 0.0.38 ovos-bus-client>=0.0.9a1 ovos-workshop>=0.0.16a39