File indexing completed on 2024-04-14 04:37:59

0001 import re
0002 import json
0003 import time
0004 import os
0005 import subprocess
0006 from mycroft.skills.core import (MycroftSkill,
0007                                  intent_handler, intent_file_handler)
0008 from mycroft.messagebus.message import Message
0009 from mycroft.session import SessionManager
0010 from mycroft.stt import MycroftSTT
0011 from speech_recognition import WavFile, AudioData
0012 
0013 
0014 class Libqmycroft(MycroftSkill):
0015 
0016     def __init__(self):
0017         super(Libqmycroft, self).__init__(name="Libqmycroft")
0018         self.registered_namespaces = []
0019         global set_dyn_name
0020         set_dyn_name = self
0021 
0022     def initialize(self):
0023         self.log.info("Libqmycroft Mock Skill Initalized")
0024         self.add_event(
0025             "mycroft.create.dynamic.skill",
0026             self.handle_dynamic_entry)
0027         self.add_event(
0028             "mycroft.delete.dynamic.skill",
0029             self.handle_dynamic_entry_deregister)
0030         self.add_event(
0031             "mycroft.dynamic.skill.speak",
0032             self.handle_dynamic_skill_speak)
0033         self.add_event(
0034             "libqmycroft.request.transcribe",
0035             self.transcribe_audio)
0036 
0037     def handle_dynamic_entry(self, message):
0038         self.log.info("Got Dynamic Skill Registeration Request")
0039         skill_namespace = message.data.get("namespace")
0040         skill_parameters = message.data.get("parameters")
0041 
0042         if skill_namespace not in self.registered_namespaces:
0043             self.registered_namespaces.append({"namespace": skill_namespace})
0044         else:
0045             # Only inform the application of a possible namespace clash
0046             # Consider all intents part of the same namespace incase of clash
0047             self.bus.emit(
0048                 "mycroft.dynamic.skill.error", {
0049                     "errorString": "Warning Namespace Exist"})
0050 
0051         self.handle_intent_voc_registeration(skill_namespace, skill_parameters)
0052 
0053     def handle_intent_voc_registeration(self, skillnamespace, voc_objects):
0054         filter_namespace = skillnamespace.lower()
0055         filter_namespace = re.sub(
0056             r"[-()\"#/@;:<>{}`+=~|.!?,]", "", filter_namespace)
0057 
0058         for x in voc_objects:
0059             method_to_make = filter_namespace + "_" + x['intent']
0060             vars()[method_to_make] = Libqmycroft.gen_handler_method(
0061                 message=None, namespace=skillnamespace, dynamic_entries=x)
0062             setattr(Libqmycroft, method_to_make, vars()[method_to_make])
0063             method_to_set = getattr(Libqmycroft, method_to_make)
0064 
0065             name = self.skill_id + ":" + x['voc'].rsplit('/', 1)[-1]
0066             self.intent_service.register_padatious_intent(name, x['voc'])
0067             time.sleep(2)
0068             self.add_event(name, method_to_set, 'mycroft.skill.handler')
0069 
0070         time.sleep(2)
0071 
0072     def event_intent_handler_call(self, namespace, dynamic_entries, message):
0073         intent_target = namespace
0074         intent_call = dynamic_entries.get("intent", "")
0075         intent_caller = message
0076         self.bus.emit(Message("mycroft.dynamic.skill.intent",
0077                               {"intent_target": intent_target,
0078                                "intent_call": intent_call,
0079                                "intent_caller": intent_caller}))
0080 
0081     def gen_handler_method(message, namespace=None, dynamic_entries=None):
0082         def _function(message):
0083             global set_dyn_name
0084             Libqmycroft.event_intent_handler_call(
0085                 set_dyn_name, namespace, dynamic_entries, message.data)
0086         return _function
0087 
0088     def handle_dynamic_skill_speak(self, message):
0089         dialog_to_speak = message.data.get("dialog", "")
0090         if dialog_to_speak:
0091             self.speak(dialog_to_speak)
0092 
0093     def handle_dynamic_entry_deregister(self, message):
0094         self.log.info("Got Dynamic Skill Delete Request")
0095         skill_namespace = message.data.get("namespace")
0096         skill_parameters = message.data.get("parameters")
0097         if self.__check_namespace_exist(skill_namespace):
0098             index = self.__get_namespace_index(skill_namespace)
0099             self.registered_namespaces.pop(index)
0100 
0101         filter_namespace = skill_namespace.lower()
0102         filter_namespace = re.sub(
0103             r"[-()\"#/@;:<>{}`+=~|.!?,]", "", filter_namespace)
0104 
0105         for x in skill_parameters:
0106             name = self.skill_id + ":" + x['voc'].rsplit('/', 1)[-1]
0107             self.intent_service.detach_intent(name)
0108 
0109     #Add transcribe support
0110     def transcribe_audio(self, message):
0111         self.log.info("Got Transcribe Request")
0112         stt = MycroftSTT()
0113         request_id = message.data["responseid"]
0114         audio_file = message.data["file"]
0115         audio_wav_file = "/tmp/transcribe_in.wav"
0116         subprocess.call(["sox","-r","16000", "-t", "sw", "-e", "signed", "-c", "1", "-b", "16", audio_file, audio_wav_file])
0117         audio = self.__get_audio_data(audio_wav_file)
0118         text = stt.execute(audio, self.lang)
0119         self.bus.emit(Message("libqmycroft.request.transcribe.result", {"targetResponseId": request_id, "targetResult": text}))
0120 
0121     def __get_audio_data(self, audiofile):
0122         wavfile = WavFile(audiofile)
0123         with wavfile as source:
0124             return AudioData(source.stream.read(), wavfile.SAMPLE_RATE, wavfile.SAMPLE_WIDTH)
0125 
0126     def __check_namespace_exist(self, namespace):
0127         list_namespaces = list(
0128             self.__locate_key(
0129                 self.registered_namespaces,
0130                 'namespace'))
0131         if namespace in list_namespaces:
0132             return True
0133         else:
0134             return False
0135 
0136     def __get_namespace_index(self, namespace):
0137         for i, skill in enumerate(self.registered_namespaces):
0138             if skill['namespace'] == namespace:
0139                 return i
0140         return None
0141 
0142     def __locate_key(self, node, kv):
0143         if isinstance(node, list):
0144             for i in node:
0145                 for x in self.__locate_key(i, kv):
0146                     yield x
0147         elif isinstance(node, dict):
0148             if kv in node:
0149                 yield node[kv]
0150             for j in node.values():
0151                 for x in self.__locate_key(j, kv):
0152                     yield x
0153 
0154 
0155 def create_skill():
0156     return Libqmycroft()