def getTexts(self, module, talk, strType='default') -> list: arr = list() try: module = commons.toCamelCase(module) arr = self._langData[module][ self.LanguageManager.activeLanguage][talk][strType] except KeyError: self._logger.warning( f'[{self.name}] Was asked to return unexisting texts {talk} for module {module} with type {strType}' ) return arr
def _loadModuleList(self, moduleToLoad: str = '', isUpdate: bool = False): if moduleToLoad: modules = self._modules.copy() else: modules = dict() availableModules = self.ConfigManager.modulesConfigurations availableModules = collections.OrderedDict( sorted(availableModules.items())) if Customisation.MODULE_NAME in availableModules: customisationModule = availableModules.pop( Customisation.MODULE_NAME) availableModules[Customisation.MODULE_NAME] = customisationModule for moduleName, module in availableModules.items(): if moduleToLoad and moduleName != moduleToLoad: continue conditionName = '' conditionValue = '' try: if not module['active']: if moduleName in self.NEEDED_MODULES: self._logger.info( "Module {} marked as disable but it shouldn't be". format(moduleName)) SuperManager.getInstance().onStop() break else: self._logger.info( 'Module {} is disabled'.format(moduleName)) continue if 'conditions' in module: for conditionName, conditionValue in module[ 'conditions'].items(): if conditionName == 'lang' and self.LanguageManager.activeLanguage not in conditionValue: raise ModuleNotConditionCompliant elif conditionName == 'online': if conditionValue and self.ConfigManager.getAliceConfigByName( 'stayCompletlyOffline'): raise ModuleNotConditionCompliant elif not conditionValue and not self.ConfigManager.getAliceConfigByName( 'stayCompletlyOffline'): raise ModuleNotConditionCompliant elif conditionName == 'module': for requiredModule in conditionValue: if requiredModule[ 'name'] in availableModules and not availableModules[ requiredModule['name']]['active']: raise ModuleNotConditionCompliant elif requiredModule[ 'name'] not in availableModules: self._logger.info( '[{}] Module {} has another module as dependency, adding download' .format(self.name, moduleName)) subprocess.run([ 'wget', requiredModule['url'], '-O', Path( commons.rootDir(), 'system/moduleInstallTickets/{}.install' .format(requiredModule['name'])) ]) elif conditionName == 'notModule': for excludedModule in conditionValue: author, name = excludedModule.split('/') if name in availableModules and availableModules[ name][ 'author'] == author and availableModules[ name]['active']: raise ModuleNotConditionCompliant elif conditionName == 'asrArbitraryCapture': if conditionValue and not self.ASRManager.asr.capableOfArbitraryCapture: raise ModuleNotConditionCompliant elif conditionName == 'activeManager': for manager in conditionValue: if not manager: continue man = SuperManager.getInstance().getManager( manager) if not man or not man.isActive: raise ModuleNotConditionCompliant if ' ' in moduleName: name = commons.toCamelCase(moduleName) else: name = moduleName moduleInstance = self.importFromModule(moduleName=name, isUpdate=isUpdate) if moduleInstance: modules[moduleInstance.name] = {'instance': moduleInstance} except ModuleStartingFailed as e: self._logger.warning('[{}] Failed loading module: {}'.format( self.name, e)) continue except ModuleNotConditionCompliant: self._logger.info( '[{}] Module {} does not comply to "{}" condition, required "{}"' .format(self.name, moduleName, conditionName, conditionValue)) continue except Exception as e: self._logger.warning( '[{}] Something went wrong loading a module: {}'.format( self.name, e)) continue # noinspection PyTypeChecker return collections.OrderedDict(sorted(modules.items()))
def syncRemoteToLocal(self, runOnAssistantId: str, moduleFilter: list = None, languageFilter: str = None): # Build cache self._ctx.entity.listEntitiesByUserEmail(userEmail=self._ctx.userEmail, returnAllCacheIndexedBy='id') remoteIndexedIntents = self._ctx.intent.listIntentsByUserId( userId=self._ctx.userId, returnAllCacheIndexedBy='id') remoteIndexedSkills = self._ctx.skill.listSkillsByUserId( userId=self._ctx.userId, returnAllCacheIndexedBy='id') hasFork = False # Check for fork and execute fork if needed for assistant in self._ctx.assistant.list( rawResponse=True)['assistants']: if assistant['id'] != runOnAssistantId: continue for skill in assistant['skills']: skillId = skill['id'] if skillId not in remoteIndexedSkills: skillId = self._ctx.assistant.forkAssistantSkill( assistantId=runOnAssistantId, sourceSkillId=skillId) self._ctx.log( f"[Forked] Skill from {skill['id']} to {skillId}") hasFork = True for intent in skill['intents']: intentId = intent['id'] if intentId not in remoteIndexedIntents: intentId = self._ctx.skill.forkSkillIntent( skillId=skillId, sourceIntentId=intentId, userId=self._ctx.userId) self._ctx.log( f"[Forked] Intent from {skill['id']} to {intentId} used in skill {skillId}" ) hasFork = True if hasFork: # Rebuild cache self._ctx.entity.listEntitiesByUserEmail( userEmail=self._ctx.userEmail) self._ctx.intent.listIntentsByUserId(userId=self._ctx.userId) self._ctx.skill.listSkillsByUserId(userId=self._ctx.userId) # Build each module configuration modules = dict() cachedIndexedSkills = self._ctx.skill.listSkillsByUserIdAndAssistantId( userId=self._ctx.userId, assistantId=runOnAssistantId, fromCache=True) for skill in cachedIndexedSkills: moduleName = commons.toCamelCase(string=skill['name'], replaceSepCharacters=True, sepCharacters=('/', '-', '_')) if moduleFilter and moduleName not in moduleFilter: continue modules[moduleName] = { 'module': moduleName, 'icon': EnumSkillImageUrl.urlToResourceKey(skill['imageUrl']), 'description': skill['description'], 'slotTypes': list(), 'intents': list() } moduleSyncState = { 'skillId': skill['id'], 'name': moduleName, 'slotTypes': dict(), 'intents': dict(), 'hash': '' } cachedIndexedIntents = self._ctx.intent.listIntentsByUserIdAndSkillId( userId=self._ctx.userId, skillId=skill['id'], fromCache=True) typeEntityMatching = dict() for intent in cachedIndexedIntents: intentName = intent['name'] if intentName.startswith(skill['name'] + '_'): intentName = intentName.replace(skill['name'] + '_', '') intentName = commons.toCamelCase(string=intentName, replaceSepCharacters=True, sepCharacters=('/', '-', '_')) utterances = list() slots = list() slotIdAndNameMatching = dict() objectUtterances = self._ctx.intent.listUtterancesByIntentId( intentId=intent['id']) for slot in intent['slots']: slotIdAndNameMatching[slot['id']] = slot for objectUtterance in objectUtterances: text = objectUtterance['text'] positionOffset = 0 for hole in objectUtterance['data']: word = hole['text'] start = hole['range']['start'] + positionOffset end = hole['range']['end'] + positionOffset slotName = slotIdAndNameMatching[ hole['slotId']]['name'] slotName = commons.toCamelCase( string=slotName, replaceSepCharacters=True, sepCharacters=('/', '-', '_')) newWord = '{' + word + self._ctx.intent.GLUE_SLOT_WORD + slotName + '}' text = text[:start] + newWord + text[end:] positionOffset += len(newWord) - len(word) utterances.append(text) cachedIndexedEntities = self._ctx.entity.listEntitiesByUserEmailAndIntentId( userEmail=self._ctx.userEmail, intentId=intent['id'], fromCache=True) for entity in cachedIndexedEntities: if entity['id'] in typeEntityMatching: continue values = self._ctx.entity.listEntityValuesByEntityId( entityId=entity['id']) entityName = commons.toCamelCase(string=entity['name'], replaceSepCharacters=True, sepCharacters=('/', '-', '_')) typeEntityMatching[entity['id']] = entityName modules[moduleName]['slotTypes'].append({ 'name': entityName, 'matchingStrictness': entity['matchingStrictness'], 'automaticallyExtensible': entity['automaticallyExtensible'], 'useSynonyms': entity['useSynonyms'], 'values': values }) moduleSyncState['slotTypes'][entityName] = { 'entityId': entity['id'], 'hash': '' } for slot in intent['slots']: slots.append({ 'name': commons.toCamelCase(string=slot['name'], replaceSepCharacters=True, sepCharacters=('/', '-', '_')), 'description': slot['description'], 'required': slot['required'], 'type': slot['entityId'] if slot['entityId'].startswith('snips/') else typeEntityMatching[slot['entityId']], 'missingQuestion': slot['missingQuestion'] }) modules[moduleName]['intents'].append({ 'name': intentName, 'description': intent['description'], 'enabledByDefault': intent['enabledByDefault'], 'utterances': utterances, 'slots': slots }) moduleSyncState['intents'][intentName] = { 'intentId': intent['id'], 'hash': '' } # Persist module configuration moduleConfig = modules[moduleName] moduleIntentsMountpoint = Path(self.SAVED_MODULES_DIR, moduleName, 'dialogTemplate') moduleIntentsMountpoint.mkdir(parents=True, exist_ok=True) moduleIntentsOutputFile = moduleIntentsMountpoint / f'{languageFilter}.json' moduleIntentsOutputFile.write_text( json.dumps(moduleConfig, indent=4, sort_keys=False, ensure_ascii=False)) self._ctx.log(f'[LocalModule] Finished for module {moduleName}')
def _loadModuleList(self, moduleToLoad: str = '', isUpdate: bool = False) -> dict: if moduleToLoad: modules = self._modules.copy() else: modules = dict() availableModules = self.ConfigManager.modulesConfigurations availableModules = collections.OrderedDict( sorted(availableModules.items())) if Customisation.MODULE_NAME in availableModules: customisationModule = availableModules.pop( Customisation.MODULE_NAME) availableModules[Customisation.MODULE_NAME] = customisationModule for moduleName, module in availableModules.items(): if moduleToLoad and moduleName != moduleToLoad: continue try: if not module['active']: if moduleName in self.NEEDED_MODULES: self._logger.info( f"Module {moduleName} marked as disable but it shouldn't be" ) SuperManager.getInstance().onStop() break else: self._logger.info(f'Module {moduleName} is disabled') moduleInstance = self.importFromModule( moduleName=moduleName, isUpdate=False) if moduleInstance: moduleInstance.active = False if moduleName in self.NEEDED_MODULES: moduleInstance.required = True self._deactivatedModules[moduleInstance.name] = { 'instance': moduleInstance } continue self.checkModuleConditions(moduleName, module['conditions'], availableModules) if ' ' in moduleName: name = commons.toCamelCase(moduleName) else: name = moduleName moduleInstance = self.importFromModule(moduleName=name, isUpdate=isUpdate) if moduleInstance: if moduleName in self.NEEDED_MODULES: moduleInstance.required = True modules[moduleInstance.name] = {'instance': moduleInstance} except ModuleStartingFailed as e: self._logger.warning( f'[{self.name}] Failed loading module: {e}') continue except ModuleNotConditionCompliant as e: self._logger.info( f'[{self.name}] Module {moduleName} does not comply to "{e.condition}" condition, required "{e.conditionValue}"' ) continue except Exception as e: self._logger.warning( f'[{self.name}] Something went wrong loading a module: {e}' ) continue # noinspection PyTypeChecker return collections.OrderedDict(sorted(modules.items()))