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()