Skip to content

Commit

Permalink
Refactor to extend OVOSSkill
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel McKnight committed Sep 16, 2024
1 parent e3f93e5 commit 6568e37
Showing 1 changed file with 77 additions and 67 deletions.
144 changes: 77 additions & 67 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@
from typing import Optional, Tuple
from bs4 import BeautifulSoup
from time import sleep

from lingua_franca import load_language
from ovos_bus_client import Message
from ovos_bus_client.message import dig_for_message
from ovos_utils import classproperty
from ovos_utils.log import LOG
from ovos_utils.process_utils import RuntimeRequirements
from neon_utils.user_utils import get_user_prefs, get_message_user
from neon_utils.skills.common_query_skill import \
from ovos_workshop.skills.common_query_skill import \
CQSMatchLevel, CommonQuerySkill
from neon_utils import web_utils
from ovos_workshop.decorators import intent_handler
Expand Down Expand Up @@ -84,37 +84,6 @@ def __init__(self, **kwargs):
self._update_event = Event()
CommonQuerySkill.__init__(self, **kwargs)

@classproperty
def runtime_requirements(self):
return RuntimeRequirements(network_before_load=False,
internet_before_load=False,
gui_before_load=False,
requires_internet=True,
requires_network=True,
requires_gui=False,
no_internet_fallback=True,
no_network_fallback=True,
no_gui_fallback=True)

@property
def last_updated(self) -> Optional[datetime.datetime]:
if self.settings.get("lastUpdate"):
return datetime.datetime.strptime(self.settings["lastUpdate"],
'%Y-%m-%d %H:%M:%S.%f')
return None

@property
def ww_enabled(self):
resp = self.bus.wait_for_response(Message("neon.query_wake_words_state"))
if not resp:
LOG.warning("No WW Status reported")
return None
if resp.data.get('enabled', True):
return True
return False

# TODO: Move to __init__ after stable ovos-workshop
def initialize(self):
goodbye_intent = IntentBuilder("CaffeineContentGoodbyeIntent")\
.require("goodbye").build()
self.register_intent(goodbye_intent, self.handle_goodbye_intent)
Expand Down Expand Up @@ -146,6 +115,35 @@ def initialize(self):
# combine them as in get_new_info and add rocket chocolate:
self._add_more_caffeine_data()

@classproperty
def runtime_requirements(self):
return RuntimeRequirements(network_before_load=False,
internet_before_load=False,
gui_before_load=False,
requires_internet=True,
requires_network=True,
requires_gui=False,
no_internet_fallback=True,
no_network_fallback=True,
no_gui_fallback=True)

@property
def last_updated(self) -> Optional[datetime.datetime]:
if self.settings.get("lastUpdate"):
return datetime.datetime.strptime(self.settings["lastUpdate"],
'%Y-%m-%d %H:%M:%S.%f')
return None

@property
def ww_enabled(self):
resp = self.bus.wait_for_response(Message("neon.query_wake_words_state"))
if not resp:
LOG.warning("No WW Status reported")
return None
if resp.data.get('enabled', True):
return True
return False

@intent_handler(IntentBuilder("CaffeineUpdate").require("update_caffeine"))
def handle_caffeine_update(self, message):
self.speak_dialog("updating")
Expand All @@ -164,13 +162,13 @@ def handle_caffeine_intent(self, message):
self.speak_dialog("no_drink_heard")
return

if not self._update_event.isSet():
self.speak_dialog('one_moment', private=True)
if not self._update_event.is_set():
self.speak_dialog('one_moment')
if not self._update_event.wait(30):
LOG.error("Update taking more than 30s, clearing event")
self._update_event.set()
elif get_user_prefs(message)['response_mode'].get('hesitation'):
self.speak_dialog('one_moment', private=True)
self.speak_dialog('one_moment')

if self._drink_in_database(drink):
dialog, results = self._generate_drink_dialog(drink, message)
Expand All @@ -179,35 +177,37 @@ def handle_caffeine_intent(self, message):
else:
self.speak_dialog("not_found", {'drink': drink})

if self.neon_core:
if len(results) == 1:
if self.ww_enabled:
self.speak_dialog("how_about_more",
expect_response=True)
self.enable_intent('CaffeineContentGoodbyeIntent')
self.request_check_timeout(
self.default_intent_timeout,
['CaffeineContentGoodbyeIntent'])
else:
self.speak_dialog("stay_caffeinated")
else:
if self.ask_yesno("more_drinks") == "yes":
self._speak_alternate_results(message, results)
self.speak_dialog("provided_by_caffeinewiz")
else:
self.speak_dialog("stay_caffeinated")
# if self.neon_core:
# if len(results) == 1:
# if self.ww_enabled:
# self.speak_dialog("how_about_more",
# expect_response=True)
# self.enable_intent('CaffeineContentGoodbyeIntent')
# self.request_check_timeout(
# self.default_intent_timeout,
# ['CaffeineContentGoodbyeIntent'])
# else:
# self.speak_dialog("stay_caffeinated")
# else:
# if self.ask_yesno("more_drinks") == "yes":
# self._speak_alternate_results(message, results)
# self.speak_dialog("provided_by_caffeinewiz")
# else:
# self.speak_dialog("stay_caffeinated")
else:
self.speak_dialog("not_found", {'drink': drink})

def CQS_match_query_phrase(self, utt, message: Message = None):
def CQS_match_query_phrase(self, phrase: str):

message = dig_for_message()
try:
# TODO: Language agnostic parsing here
if " of " in utt:
drink = utt.split(" of ", 1)[1]
elif " in " in utt:
drink = utt.split(" in ", 1)[1]
if " of " in phrase:
drink = phrase.split(" of ", 1)[1]
elif " in " in phrase:
drink = phrase.split(" in ", 1)[1]
else:
drink = utt
drink = phrase
drink = self._clean_drink_name(drink)
if not drink:
LOG.debug("No drink matched")
Expand All @@ -225,12 +225,14 @@ def CQS_match_query_phrase(self, utt, message: Message = None):
if not to_speak:
# No dialog generated
return None
if self.voc_match(utt, "caffeine"):
if self.voc_match(phrase, "caffeine"):
LOG.info(f"Query is about caffeine ({phrase})")
conf = CQSMatchLevel.EXACT
elif matched_drink.lower() in utt.lower():
elif matched_drink.lower() in phrase.lower():
# If the exact drink name was matched
# but caffeine not requested, consider this a general match
conf = CQSMatchLevel.GENERAL
LOG.debug(f"Drink ({matched_drink}) is in utterance ({phrase})")
else:
# We didn't match "caffeine" or an exact drink name
# this request isn't for this skill
Expand All @@ -239,12 +241,12 @@ def CQS_match_query_phrase(self, utt, message: Message = None):
LOG.error(e)
LOG.error(drink)
return None
elif drink == utt:
elif drink == phrase:
LOG.debug("No drink extracted from utterance")
return None
else:
LOG.debug(f"No match for: {drink}")
if self.voc_match(utt, "caffeine"):
if self.voc_match(phrase, "caffeine"):
conf = CQSMatchLevel.CATEGORY
results = None
to_speak = self.dialog_renderer.render("not_found",
Expand All @@ -253,7 +255,7 @@ def CQS_match_query_phrase(self, utt, message: Message = None):
return None
LOG.info(f"results={results}, to_speak={to_speak}")
user = get_message_user(message) if message else 'local'
return utt, conf, to_speak, {"user": user,
return phrase, conf, to_speak, {"user": user,
"message": message.serialize() if message
else None,
"results": results}
Expand Down Expand Up @@ -314,7 +316,6 @@ def handle_goodbye_intent(self, message):
# Remove any awaiting confirmation
try:
user = get_message_user(message)
self.actions_to_confirm.pop(user)
except Exception as e:
LOG.error(e)

Expand Down Expand Up @@ -463,8 +464,7 @@ def _normalize_drink_list(drink_list):
try:
# TODO: Check for CW and CI success
if self.from_caffeine_wiz:
self.update_skill_settings({"lastUpdate": str(time_check)},
skill_global=True)
self.update_skill_settings({"lastUpdate": str(time_check)})
if reply:
self.speak_dialog("update_complete")
success = True
Expand All @@ -477,6 +477,16 @@ def _normalize_drink_list(drink_list):
self._update_event.set()
return success

def update_skill_settings(self, new_preferences: dict):
"""
Updates skill settings with the passed new_preferences
:param new_preferences: dict of updated preference values. {key: val}
"""
LOG.debug(f"Update skill settings with new: {new_preferences}")
new_settings = {**self.settings, **new_preferences}
self.settings = new_settings
self.settings.store()

def _clean_drink_name(self, drink: str) -> str:
"""
Normalizes an input drink name and handles known alternative names
Expand Down

0 comments on commit 6568e37

Please sign in to comment.