Esempio n. 1
0
	def startSkill(self, skillName: str) -> Dict:
		"""
		Starts a skill
		:param skillName:
		:return:
		"""
		if skillName in self._activeSkills:
			skillInstance = self._activeSkills[skillName]
		elif skillName in self._deactivatedSkills or skillName in self._failedSkills:
			if skillName in self._failedSkills:
				skill = self._failedSkills.pop(skillName, None)
			else:
				skill = self._deactivatedSkills.pop(skillName, None)

			try:
				skillInstance = self.instantiateSkill(skillName=skillName)
				self.checkSkillConditions(installer=json.loads(self.getSkillInstallFilePath(skillName=skillName).read_text()))
			except:
				self._failedSkills[skillName] = FailedAliceSkill(json.loads(skill.getResource(f'{skillName}.install').read_text()))
				return dict()

			if skillInstance:
				self.activeSkills[skillName] = skillInstance
			else:
				return dict()
		else:
			self.logWarning(f'Skill "{skillName}" is unknown')
			return dict()

		try:
			skillInstance.onStart()
			if self.ProjectAlice.isBooted:
				skillInstance.onBooted()

			self.broadcast(
				method=constants.EVENT_SKILL_STARTED,
				exceptions=[constants.DUMMY],
				propagateToSkills=True,
				skill=skillName
			)
		except SkillStartingFailed:
			try:
				skillInstance.failedStarting = True
			except:
				self._failedSkills[skillName] = FailedAliceSkill(skillInstance.installer)
		except SkillStartDelayed:
			raise
		except Exception as e:
			self.logError(f'- Couldn\'t start skill "{skillName}". Error: {e}')
			traceback.print_exc()

			try:
				self.deactivateSkill(skillName=skillName)
			except:
				self._activeSkills.pop(skillName, None)
				self._deactivatedSkills.pop(skillName, None)

			self._failedSkills[skillName] = FailedAliceSkill(skillInstance.installer)

		return skillInstance.supportedIntents
Esempio n. 2
0
    def _initSkills(self, loadOnly: str = '', reload: bool = False):
        for skillName, data in self._skillList.items():
            if loadOnly and skillName != loadOnly:
                continue

            self._activeSkills.pop(skillName, None)
            self._failedSkills.pop(skillName, None)
            self._deactivatedSkills.pop(skillName, None)

            try:
                if not data['active']:
                    if skillName in self.NEEDED_SKILLS:
                        self.logInfo(
                            f"Skill {skillName} marked as disabled but it shouldn't be"
                        )
                        self.ProjectAlice.onStop()
                        break

                    self.logInfo(f'Skill {skillName} is disabled')

                if data['active']:
                    self.checkSkillConditions(
                        self._skillList[skillName]['installer'])

                skillInstance = self.instanciateSkill(skillName=skillName,
                                                      reload=reload)
                if skillInstance:
                    if skillName in self.NEEDED_SKILLS:
                        skillInstance.required = True

                    if data['active']:
                        self._activeSkills[skillInstance.name] = skillInstance
                    else:
                        self._deactivatedSkills[skillName] = skillInstance
                else:
                    self._failedSkills[skillName] = FailedAliceSkill(
                        data['installer'])

            except SkillStartingFailed as e:
                self.logWarning(f'Failed loading skill: {e}')
                self._failedSkills[skillName] = FailedAliceSkill(
                    data['installer'])
                continue
            except SkillNotConditionCompliant as e:
                self.logInfo(
                    f'Skill {skillName} does not comply to "{e.condition}" condition, required "{e.conditionValue}"'
                )
                self._failedSkills[skillName] = FailedAliceSkill(
                    data['installer'])
                continue
            except Exception as e:
                self.logWarning(
                    f'Something went wrong loading skill {skillName}: {e}')
                self._failedSkills[skillName] = FailedAliceSkill(
                    data['installer'])
                continue
Esempio n. 3
0
    def _startSkill(self, skillName: str) -> dict:
        if skillName in self._activeSkills:
            skillInstance = self._activeSkills[skillName]
        elif skillName in self._deactivatedSkills:
            self._deactivatedSkills.pop(skillName, None)
            skillInstance = self.instanciateSkill(skillName=skillName)
            if skillInstance:
                self.activeSkills[skillName] = skillInstance
            else:
                return dict()
        elif skillName in self._failedSkills:
            skillInstance = self.instanciateSkill(skillName=skillName)
            if skillInstance:
                self.activeSkills[skillName] = skillInstance
            else:
                return dict()
        else:
            self.logWarning(f'Skill "{skillName}" is unknown')
            return dict()

        try:
            skillInstance.onStart()
            self.broadcast(method=constants.EVENT_SKILL_STARTED,
                           exceptions=[self.name],
                           propagateToSkills=True,
                           skill=self)
        except SkillStartingFailed:
            self._failedSkills[skillName] = FailedAliceSkill(
                self._skillList[skillName]['installer'])
        except SkillStartDelayed:
            raise
        except Exception as e:
            self.logError(f'- Couldn\'t start skill "{skillName}". Error: {e}')

            try:
                self.deactivateSkill(skillName=skillName)
            except:
                self._activeSkills.pop(skillName, None)
                self._deactivatedSkills.pop(skillName, None)

            self._failedSkills[skillName] = FailedAliceSkill(
                self._skillList[skillName]['installer'])

        if skillInstance.widgets:
            self._widgets[skillName] = skillInstance.widgets

        if skillInstance.deviceTypes:
            self.DeviceManager.addDeviceTypes(
                deviceTypes=skillInstance.deviceTypes)

        return skillInstance.supportedIntents
Esempio n. 4
0
	def initSkills(self, onlyInit: str = '', reload: bool = False):
		"""
		Initializing skills by checking their condition compliance and instantiating them.
		Does check if a skill fails and is required
		:param onlyInit: If specified, will only init the given skill name
		:param reload: If the skill is already instantiated, performs a module reload, after an update per example.
		:return:
		"""

		for skillName in self._skillList:
			if onlyInit and skillName != onlyInit:
				continue

			self._activeSkills.pop(skillName, None)
			self._failedSkills.pop(skillName, None)
			self._deactivatedSkills.pop(skillName, None)

			installFilePath = self.getSkillInstallFilePath(skillName=skillName)
			if not installFilePath.exists():
				if skillName in self.NEEDED_SKILLS:
					self.logFatal(f'Cannot find skill install file for skill **{skillName}**. The skill is required to continue')
					return
				else:
					self.logWarning(f'Cannot find skill install file for skill **{skillName}**, skipping.')
					continue
			else:
				installFile = json.loads(installFilePath.read_text())

			try:
				skillActiveState = self.isSkillActive(skillName=skillName)
				if not skillActiveState:
					if skillName in self.NEEDED_SKILLS:
						self.logFatal(f"Skill {skillName} marked as disabled but it cannot be")
						return
					else:
						self.logInfo(f'Skill {skillName} is disabled')
				else:
					self.checkSkillConditions(installFile)

				skillInstance = self.instantiateSkill(skillName=skillName, reload=reload)
				if skillInstance:
					if skillName in self.NEEDED_SKILLS:
						skillInstance.required = True

					if skillActiveState:
						self._activeSkills[skillInstance.name] = skillInstance
					else:
						self._deactivatedSkills[skillName] = skillInstance

					self.ConfigManager.loadCheckAndUpdateSkillConfigurations(skillToLoad=skillName)
				else:
					if skillName in self.NEEDED_SKILLS:
						self.logFatal(f'The skill is required to continue...')
						return
					else:
						self._failedSkills[skillName] = FailedAliceSkill(installFile)
			except SkillNotConditionCompliant as e:
				if self.notCompliantSkill(skillName=skillName, exception=e):
					self._failedSkills[skillName] = FailedAliceSkill(installFile)
					self.changeSkillStateInDB(skillName=skillName, newState=False)
					continue
				else:
					return
			except Exception as e:
				self.logWarning(f'Something went wrong loading skill {skillName}: {e}')
				if skillName in self.NEEDED_SKILLS:
					self.logFatal(f'The skill is required to continue...')
					return
				else:
					self._failedSkills[skillName] = FailedAliceSkill(installFile)
					self.changeSkillStateInDB(skillName=skillName, newState=False)
					continue
Esempio n. 5
0
	def createNewSkill(self, skillDefinition: dict) -> bool:
		try:
			self.logInfo(f'Creating new skill "{skillDefinition["name"]}"')

			skillName = skillDefinition['name'].capitalize()

			localDirectory = Path('/home', getpass.getuser(), f'ProjectAlice/skills/{skillName}')
			if localDirectory.exists():
				raise Exception("Skill name exists locally")

			supportedLanguages = [
				'en'
			]
			if skillDefinition.get('fr', 'false') == 'true':
				supportedLanguages.append('fr')
			if skillDefinition.get('de', 'false') == 'true':
				supportedLanguages.append('de')
			if skillDefinition.get('it', 'false') == 'true':
				supportedLanguages.append('it')
			if skillDefinition.get('pl', 'false') == 'true':
				supportedLanguages.append('pl')
			if skillDefinition.get('pt', 'false') == 'true':
				supportedLanguages.append('pt')
			if skillDefinition.get('pt_br', 'false') == 'true':
				supportedLanguages.append('pt_br')

			conditions = {
				'lang': supportedLanguages
			}

			if skillDefinition.get('conditionOnline', False):
				conditions['online'] = True

			if skillDefinition.get('conditionASRArbitrary', False):
				conditions['asrArbitraryCapture'] = True

			if skillDefinition.get('conditionSkill', []):
				conditions['skill'] = [skill.strip() for skill in skillDefinition['conditionSkill'].split(',')]

			if skillDefinition.get('conditionNotSkill', []):
				conditions['notSkill'] = [skill.strip() for skill in skillDefinition['conditionNotSkill'].split(',')]

			if skillDefinition.get('conditionActiveManager', []):
				conditions['activeManager'] = [manager.strip() for manager in skillDefinition['conditionActiveManager'].split(',')]

			if skillDefinition.get('widgets', []):
				widgets = [self.Commons.toPascalCase(widget).strip() for widget in skillDefinition['widgets'].split(',')]
			else:
				widgets = list()

			if skillDefinition.get('nodes', []):
				scenarioNodes = [self.Commons.toPascalCase(node).strip() for node in skillDefinition['nodes'].split(',')]
			else:
				scenarioNodes = list()

			if skillDefinition.get('devices', []):
				devices = [self.Commons.toPascalCase(device).strip() for device in skillDefinition['devices'].split(',')]
			else:
				devices = list()

			data = {
				'username'          : self.ConfigManager.getAliceConfigByName('githubUsername'),
				'skillName'         : skillName.capitalize(),
				'description'       : skillDefinition['description'],
				'category'          : skillDefinition['category'],
				'speakableName'     : skillDefinition['speakableName'],
				'langs'             : supportedLanguages,
				'createInstructions': skillDefinition.get('instructions', False),
				'pipreq'            : [req.strip() for req in skillDefinition.get('pipreq', "").split(',')],
				'sysreq'            : [req.strip() for req in skillDefinition.get('sysreq', "").split(',')],
				'widgets'           : widgets,
				'scenarioNodes'     : scenarioNodes,
				'devices'           : devices,
				'outputDestination' : str(Path(self.Commons.rootDir()) / 'skills' / skillName),
				'conditions'        : conditions
			}

			dump = Path(f'/tmp/{skillName}.json')
			dump.write_text(json.dumps(data, ensure_ascii=False))

			self.Commons.runSystemCommand(['./venv/bin/pip', 'install', '--upgrade', 'projectalice-sk'])
			self.Commons.runSystemCommand(['./venv/bin/projectalice-sk', 'create', '--file', f'{str(dump)}'])
			self.logInfo(f'Created **{skillName}** skill')

			# todo: ugly..
			data['name'] = data['skillName']
			data['author'] = data['username']
			data['desc'] = data['description']
			# ok, version never filled in frontend and every skill should be created in initial version
			data['version'] = '0.0.1'

			self._failedSkills[skillName] = FailedAliceSkill(data)
			self._skillList[skillName] = {
				'active'   : False,
				'modified' : True,
				'installer': data
			}
			self._failedSkills[skillName].modified = True

			return True
		except Exception as e:
			self.logError(f'Error creating new skill: {e}')
			return False