Example #1
0
	def __init__(self):
		self._logger = logging.getLogger('ProjectAlice')
		self._logger.info('Starting Project Alice initializer')

		self._confsFile = Path(commons.rootDir(), 'config.py')
		self._confsSample = Path(commons.rootDir(), 'configSample.py')
		self._initFile = Path('/boot/ProjectAlice.yaml')
		self._latest = 1.03
Example #2
0
    def runCmd(self, cmd: str, services: list = None):
        if not Path(commons.rootDir() + '/assistant').exists():
            self._logger.warning(
                f'[{self.name}] Assistant not yet existing, shouldn\'t handle Snips for now'
            )
            return

        if not services:
            services = self._snipsServices

        for service in services:
            if (service == 'snips-asr'
                    and not isinstance(self.ASRManager.asr, SnipsASR)) or (
                        service == 'snips-tts'
                        and not isinstance(self.TTSManager.tts, SnipsTTS)):
                continue

            result = subprocess.run(['sudo', 'systemctl', cmd, service],
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
            if result.returncode == 0:
                self._logger.info(f"[{self.name}] Service {service} {cmd}'ed")
            elif result.returncode == 5:
                pass
            else:
                self._logger.info(
                    f"[{self.name}] Tried to {cmd} the {service} service but it returned with return code {result.returncode}"
                )
Example #3
0
    def uploadToNewDevice(self, uid: str):
        directory = Path(commons.rootDir(), 'trained/hotwords')
        for fiile in directory:
            if (directory / fiile).is_file():
                continue

            self._upload(directory / fiile, uid)
Example #4
0
	def onStartListening(self, session: DialogSession):
		if isinstance(self._asr, SnipsASR):
			return
		else:
			start = time.time()
			result = self._asr.onListen()
			end = time.time()
			processing = float(end - start)

			if result:
				# Stop listener as fast as possible
				self.MqttManager.publish(topic='hermes/asr/stopListening', payload={'sessionId': session.sessionId, 'siteId': session.siteId})

				result = self.LanguageManager.sanitizeNluQuery(result)
				self._logger.debug('[{}] - {} output: "{}"'.format(self.NAME, self._asr.__class__.__name__, result))

				supportedIntents = session.intentFilter or self.ModuleManager.supportedIntents
				intentFilter = [intent.justTopic for intent in supportedIntents if isinstance(intent, Intent) and not intent.protected]

				# Add Global Intents
				intentFilter.append(Intent('GlobalStop').justTopic)

				self.MqttManager.publish(topic='hermes/asr/textCaptured', payload={'sessionId': session.sessionId, 'text': result, 'siteId': session.siteId, 'likelihood': 1, 'seconds': processing})

				self.MqttManager.publish(topic='hermes/nlu/query', payload={'id':session.sessionId, 'input': result, 'intentFilter': intentFilter, 'sessionId': session.sessionId})
			else:
				self.MqttManager.publish(topic='hermes/nlu/intentNotRecognized')
				self.MqttManager.playSound(
					soundFile=Path(commons.rootDir(), 'assistant/custom_dialogue/sound/error.wav'),
					sessionId=uuid.uuid4(),
					absolutePath=True,
					siteId=session.siteId
				)
Example #5
0
    def _loadTTS(self, tts: str, user: User = None) -> TTSEnum:
        try:
            tts = TTSEnum(tts)
        except:
            tts = TTSEnum.SNIPS

        if tts == TTSEnum.SNIPS:
            from core.voice.model.SnipsTTS import SnipsTTS
            self._tts = SnipsTTS(user)
        elif tts == TTSEnum.PICO:
            self._tts = PicoTTS(user)
        elif tts == TTSEnum.MYCROFT:
            if not Path(Path(commons.rootDir()).parent,
                        'mimic/voices').is_dir():
                self._logger.warning(
                    '[{}] Trying to use Mycroft as TTS but files not available, falling back to picotts'
                    .format(self.NAME))
                self._tts = PicoTTS(user)
                tts = TTSEnum.PICO
            else:
                from core.voice.model.MycroftTTS import MycroftTTS
                self._tts = MycroftTTS(user)
        elif tts == TTSEnum.AMAZON:
            from core.voice.model.AmazonTTS import AmazonTTS
            self._tts = AmazonTTS(user)
        elif tts == TTSEnum.GOOGLE:
            from core.voice.model.GoogleTTS import GoogleTTS
            self._tts = GoogleTTS(user)
        else:
            from core.voice.model.SnipsTTS import SnipsTTS
            self._tts = SnipsTTS(user)

        return tts
Example #6
0
    def _addWakewordToSnips(self, path: Path):
        # TODO unhardcode sensitivity
        models: list = self.ConfigManager.getSnipsConfiguration(
            'snips-hotword', 'model', createIfNotExist=True)

        if not isinstance(models, list):
            models = list()

        wakewordName = path.name

        add = True
        copy = models.copy()
        for i, model in enumerate(copy):
            if wakewordName in model:
                models.pop(i)
            elif '/snips_hotword=' in model:
                add = False

        if add:
            models.append(
                str(
                    Path(commons.rootDir(),
                         'trained/hotwords/snips_hotword=0.53')))

        models.append('{}=0.52'.format(str(path)))
        self.ConfigManager.updateSnipsConfiguration('snips-hotword',
                                                    'model',
                                                    models,
                                                    restartSnips=True)

        self._upload(path)
Example #7
0
    def loadModuleConfigurations(self, module: str = ''):
        self._logger.info('[{}] Loading module configurations'.format(
            self.name))

        # Iterate through all modules declared in global config file
        for moduleName in self._aliceConfigurations['modules']:

            if module and moduleName != module:
                continue

            moduleConfigFile = Path(commons.rootDir(), 'modules', moduleName,
                                    'config.json')
            moduleConfigFileExists = moduleConfigFile.exists()

            if not self._aliceConfigurations['modules'][moduleName][
                    'active'] or not moduleConfigFileExists:
                self._modulesConfigurations[moduleName] = {
                    **self._aliceConfigurations['modules'][moduleName]
                }
                continue

            try:
                self._logger.info(
                    '- Loading config file for module {}'.format(moduleName))
                with open(moduleConfigFile) as jsonFile:
                    self._modulesConfigurations[moduleName] = {
                        **json.load(jsonFile),
                        **self._aliceConfigurations['modules'][moduleName]
                    }

            except json.decoder.JSONDecodeError:
                self._logger.error(
                    '- Error in config file for module {}'.format(moduleName))
    def onMessage(self, intent: str, session: DialogSession):
        if intent == self._INTENT_ANSWER_HEADS_OR_TAIL:
            coin = random.choice(['heads', 'tails'])

            SuperManager.getInstance().mqttManager.playSound(
                soundFile=os.path.join(commons.rootDir(), 'modules',
                                       'Minigames', 'sounds', 'coinflip'),
                sessionId='coinflip',
                siteId=session.siteId,
                absolutePath=True)

            redQueen = SuperManager.getInstance(
            ).moduleManager.getModuleInstance('RedQueen')
            redQueen.changeRedQueenStat('happiness', 5)

            if session.slotValue('HeadsOrTails') == coin:
                result = 'flipACoinUserWins'
                redQueen.changeRedQueenStat('frustration', 1)
            else:
                result = 'flipACoinUserLooses'
                redQueen.changeRedQueenStat('frustration', -5)
                redQueen.changeRedQueenStat('hapiness', 5)

            SuperManager.getInstance().mqttManager.continueDialog(
                sessionId=session.sessionId,
                text=SuperManager.getInstance().talkManager.randomTalk(
                    talk=result, module='Minigames').format(
                        SuperManager.getInstance().languageManager.
                        getTranslations(module='Minigames',
                                        key=coin,
                                        toLang=SuperManager.getInstance().
                                        languageManager.activeLanguage)[0]),
                intentFilter=[self._INTENT_ANSWER_YES_OR_NO],
                previousIntent=self._INTENT_PLAY_GAME,
                customData={'askRetry': True})
Example #9
0
 def langSwitch(self, newLang: str, siteId: str):
     self.publish(topic='hermes/asr/textCaptured',
                  payload={'siteId': siteId})
     subprocess.run(
         [commons.rootDir() + '/system/scripts/langSwitch.sh', newLang])
     self.ThreadManager.doLater(interval=3,
                                func=self._confirmLangSwitch,
                                args=[newLang, siteId])
Example #10
0
    def numberIntent(self, intent: str, session: DialogSession):
        number = int(session.slotValue('Number'))
        if number == self._number:

            score = round(time.time() - self._start)
            m, s = divmod(score, 60)
            scoreFormatted = SuperManager.getInstance(
            ).languageManager.getTranslations(
                module='Minigames',
                key='minutesAndSeconds')[0].format(round(m), round(s))

            SuperManager.getInstance().mqttManager.playSound(
                soundFile=os.path.join(commons.rootDir(), 'modules',
                                       'Minigames', 'sounds', 'applause'),
                siteId=session.siteId,
                absolutePath=True)

            SuperManager.getInstance().mqttManager.endDialog(
                sessionId=session.sessionId,
                text=SuperManager.getInstance().talkManager.randomTalk(
                    'guessTheNumberCorrect',
                    'Minigames').format(self._number, self._number))

            textType = 'guessTheNumberScore'
            if session.user != 'unknown' and SuperManager.getInstance(
            ).moduleManager.getModuleInstance('Minigames').checkAndStoreScore(
                    user=session.user, score=score, biggerIsBetter=False):
                textType = 'guessTheNumberNewHighscore'

            SuperManager.getInstance().mqttManager.say(
                client=session.siteId,
                text=SuperManager.getInstance().talkManager.randomTalk(
                    textType, 'Minigames').format(scoreFormatted),
                canBeEnqueued=True)

            SuperManager.getInstance().mqttManager.ask(
                text=SuperManager.getInstance().talkManager.randomTalk(
                    'playAgain', 'Minigames'),
                intentFilter=[self._INTENT_ANSWER_YES_OR_NO],
                previousIntent=self._INTENT_PLAY_GAME,
                customData={
                    'speaker': session.user,
                    'askRetry': True
                })
            return

        textType = 'guessTheNumberLess'
        if number < self._number:
            textType = 'guessTheNumberMore'

        SuperManager.getInstance().mqttManager.continueDialog(
            sessionId=session.sessionId,
            text=SuperManager.getInstance().talkManager.randomTalk(
                textType, 'Minigames'),
            intentFilter=[self._INTENT_ANSWER_NUMBER],
            previousIntent=intent)
    def onStart(self):
        super().onStart()
        if not self.ConfigManager.getAliceConfigByName('webInterfaceActive'):
            self._logger.info(
                f'[{self.name}] Web interface is disabled by settings')
        else:
            langFile = Path(
                commons.rootDir(),
                f'core/interface/languages/{self.LanguageManager.activeLanguage.lower()}.json'
            )

            if not langFile.exists():
                self._logger.warning(
                    f'[{self.name}] Lang "{self.LanguageManager.activeLanguage.lower()}" not found, falling back to "en"'
                )
                langFile = Path(commons.rootDir(),
                                'core/interface/languages/en.json')
            else:
                self._logger.info(
                    f'[{self.name}] Loaded interface in "{self.LanguageManager.activeLanguage.lower()}"'
                )

            with langFile.open('r') as f:
                self._langData = json.load(f)

            for view in self._VIEWS:
                view.register(self.app)

            self.ThreadManager.newThread(
                name='WebInterface',
                target=self.app.run,
                kwargs={
                    'debug':
                    True,
                    'port':
                    int(
                        self.ConfigManager.getAliceConfigByName(
                            'webInterfacePort')),
                    'host':
                    commons.getLocalIp(),
                    'use_reloader':
                    False
                })
Example #12
0
    def playSound(self,
                  soundFile: str,
                  sessionId: str = '',
                  absolutePath: bool = False,
                  siteId: str = 'default',
                  root: str = '',
                  uid: str = ''):
        """
		Plays a sound
		:param uid: a unique id for that sound
		:param absolutePath: bool
		:param sessionId: int a session id
		:param soundFile: str The sound file name
		:param siteId: int Where to play the sound
		:param root: If different from default
		"""

        if not root:
            root = Path(commons.rootDir(), 'system/sounds')
        root = Path(root)

        if not uid:
            uid = str(uuid.uuid4())

        if not sessionId:
            sessionId = str(uuid.uuid4())

        if siteId == 'all':
            deviceList = self.DeviceManager.getDevicesByType(
                'AliceSatellite', connectedOnly=True)
            deviceList.append('default')

            for device in deviceList:
                device = device.replace('@mqtt', '')
                self.playSound(sessionId=sessionId,
                               soundFile=soundFile,
                               absolutePath=absolutePath,
                               siteId=device,
                               root=root)
        else:
            if ' ' in siteId:
                siteId = siteId.replace(' ', '_')

            soundFile = Path(
                soundFile).with_suffix('.wav') if absolutePath else Path(
                    root, soundFile).with_suffix('.wav')

            if not soundFile.exists():
                self._logger.error(
                    "Sound file {} doesn't exist".format(soundFile))
                return

            self._mqttClient.publish(
                'hermes/audioServer/{}/playBytes/{}'.format(siteId, uid),
                payload=bytearray(soundFile.read_bytes()))
    def removeModule(self, moduleName: str):
        if not moduleName in self._modules:
            return
        else:
            self.configureModuleIntents(moduleName, False)
            self.ConfigManager.removeModule(moduleName)
            del self._modules[moduleName]

        shutil.rmtree(Path(commons.rootDir(), 'modules', moduleName))
        # TODO Samkilla cleaning
        self.SnipsConsoleManager.doDownload()
    def playSound(self,
                  soundFilename: str,
                  location: Path = None,
                  sessionId: str = '',
                  siteId: str = constants.DEFAULT_SITE_ID,
                  uid: str = '',
                  suffix: str = '.wav'):

        if not sessionId:
            sessionId = str(uuid.uuid4())

        if not uid:
            uid = str(uuid.uuid4())

        if not location:
            location = Path(commons.rootDir()) / 'system' / 'sounds'
        elif not str(location).startswith('/'):
            location = Path(commons.rootDir()) / location

        if siteId == 'all':
            deviceList = self.DeviceManager.getDevicesByType(
                'AliceSatellite', connectedOnly=True)
            deviceList.append(constants.DEFAULT_SITE_ID)

            for device in deviceList:
                device = device.replace('@mqtt', '')
                self.playSound(soundFilename, location, sessionId, device, uid)
        else:
            if ' ' in siteId:
                siteId = siteId.replace(' ', '_')

            soundFile = Path(location / soundFilename).with_suffix(suffix)

            if not soundFile.exists():
                self._logger.error(
                    f"[{self.name}] Sound file {soundFile} doesn't exist")
                return

            self._mqttClient.publish(constants.TOPIC_PLAY_BYTES.format(
                siteId, uid),
                                     payload=bytearray(soundFile.read_bytes()))
Example #15
0
	def changeFeedbackSound(self, inDialog: bool, siteId: str = 'all'):
		if not Path(commons.rootDir(), 'assistant').exists():
			return

		# Unfortunately we can't yet get rid of the feedback sound because Alice hears herself finishing the sentence and capturing part of it
		if inDialog:
			state = '_ask'
		else:
			state = ''

		subprocess.run(['sudo', 'ln', '-sfn', f'{commons.rootDir()}/system/sounds/{self.LanguageManager.activeLanguage}/start_of_input{state}.wav', f'{commons.rootDir()}/assistant/custom_dialogue/sound/start_of_input.wav'])
		subprocess.run(['sudo', 'ln', '-sfn', f'{commons.rootDir()}/system/sounds/{self.LanguageManager.activeLanguage}/error{state}.wav', f'{commons.rootDir()}/assistant/custom_dialogue/sound/error.wav'])
Example #16
0
    def finalizeWakeword(self):
        self._logger.info('[{}] Finalyzing wakeword'.format(self.name))
        self._state = WakewordManagerState.FINALIZING

        config = {
            'hotword_key': self._wakeword.username.lower(),
            'kind': 'personal',
            'dtw_ref': 0.22,
            'from_mfcc': 1,
            'to_mfcc': 13,
            'band_radius': 10,
            'shift': 10,
            'window_size': 10,
            'sample_rate': 16000,
            'frame_length_ms': 25.0,
            'frame_shift_ms': 10.0,
            'num_mfcc': 13,
            'num_mel_bins': 13,
            'mel_low_freq': 20,
            'cepstral_lifter': 22.0,
            'dither': 0.0,
            'window_type': 'povey',
            'use_energy': False,
            'energy_floor': 0.0,
            'raw_energy': True,
            'preemphasis_coefficient': 0.97,
            'model_version': 1
        }

        path = Path(commons.rootDir(), 'trained/hotwords',
                    self.wakeword.username.lower())

        if path.exists():
            self._logger.warning(
                '[{}] Destination directory for new wakeword already exists, deleting'
                .format(self.name))
            shutil.rmtree(path)

        path.mkdir()

        (path / 'config.json').write_text(json.dumps(config, indent=4))

        for i in range(1, 4):
            shutil.move(Path(tempfile.gettempdir(), '{}.wav'.format(i)),
                        path / '{}.wav'.format(i))

        self._addWakewordToSnips(path)
        self.ThreadManager.newThread(name='SatelliteWakewordUpload',
                                     target=self._upload,
                                     args=[path, self._wakeword.username],
                                     autostart=True)

        self._state = WakewordManagerState.IDLE
    def onStart(self):
        super().onStart()

        self._userEmail = self.ConfigManager.getAliceConfigByName(
            'snipsConsoleLogin')
        self._userPassword = self.ConfigManager.getAliceConfigByName(
            'snipsConsolePassword')

        self._mainProcessor = MainProcessor(self)
        self.initActions()
        self._loadDialogTemplateMapsInConfigManager()

        path = Path(commons.rootDir(), 'var/assistants',
                    self.LanguageManager.activeLanguage)
        if not path.exists() or not [x for x in path.iterdir() if x.is_dir()]:
            self.sync()
Example #18
0
    def onSay(self, session: DialogSession):
        super().onSay(session)

        if not self._text:
            return

        if not self._cacheFile.exists():
            subprocess.run([
                'snips-makers-tts', '--output', self._cacheFile,
                'file://{}/var/voices/cmu_{}_{}.flitevox'.format(
                    commons.rootDir(),
                    SuperManager.getInstance().languageManager.
                    activeCountryCode.lower(), self._voice), self._text
            ])

        self._speak(file=self._cacheFile, session=session)
Example #19
0
    def __init__(self):
        super().__init__()

        os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = str(
            Path(commons.rootDir(), 'credentials/googlecredentials.json'))

        self._client = speech.SpeechClient()
        self._config = types.RecognitionConfig(
            encoding=enums.RecognitionConfig.AudioEncoding.LINEAR16,
            sample_rate_hertz=SuperManager.getInstance(
            ).configManager.getAliceConfigByName('micSampleRate'),
            language_code=SuperManager.getInstance(
            ).languageManager.activeLanguageAndCountryCode)
        self._capableOfArbitraryCapture = True
        self._streamingConfig = types.StreamingRecognitionConfig(
            config=self._config, single_utterance=True, interim_results=False)
Example #20
0
    def _writeToModuleConfigurationFile(moduleName: str, confs: dict):
        """
		Saaves the given configuration into config.py of the Module
		:param moduleName: the targeted module
		:param confs: the dict to save
		"""

        # Don't store "active", "version", "author", "conditions" value in module config file
        misterProper = ['active', 'version', 'author', 'conditions']
        confsCleaned = {
            key: value
            for key, value in confs.items() if key not in misterProper
        }

        moduleConfigFile = Path(commons.rootDir(), 'modules', moduleName,
                                'config.json')
        moduleConfigFile.write_text(json.dumps(confsCleaned, indent=4))
    def _checkForModuleInstall(self):
        self.ThreadManager.newTimer(interval=10,
                                    func=self._checkForModuleInstall,
                                    autoStart=True)

        root = Path(commons.rootDir(), 'system/moduleInstallTickets')
        files = [f for f in root.iterdir() if f.suffix == '.install']

        if  self._busyInstalling.isSet() or \
         not self.InternetManager.online or \
         not files or \
         self.ThreadManager.getEvent('SnipsAssistantDownload').isSet():
            return

        if files:
            self._logger.info(
                f'[{self.name}] Found {len(files)} install ticket(s)')
            self._busyInstalling.set()

            modulesToBoot = list()
            try:
                modulesToBoot = self._installModules(files)
            except Exception as e:
                self._logger.error(
                    f'[{self.name}] Error checking for module install: {e}')
            finally:
                if modulesToBoot:
                    for moduleName, info in modulesToBoot.items():
                        self._modules = self._loadModuleList(
                            moduleToLoad=moduleName, isUpdate=info['update'])

                        try:
                            self.LanguageManager.loadStrings(
                                moduleToLoad=moduleName)
                            self.TalkManager.loadTalks(moduleToLoad=moduleName)
                        except:
                            pass
                    try:
                        self.SamkillaManager.sync(moduleFilter=modulesToBoot)
                    except Exception as esamk:
                        self._logger.error(
                            f'[{self.name}] Failed syncing with remote snips console {esamk}'
                        )
                        raise

                self._busyInstalling.clear()
    def checkForModuleUpdates(self):
        if self.ConfigManager.getAliceConfigByName('stayCompletlyOffline'):
            return

        self._logger.info(f'[{self.name}] Checking for module updates')
        if not self.InternetManager.online:
            self._logger.info(f'[{self.name}] Not connected...')
            return

        availableModules = self.ConfigManager.modulesConfigurations

        i = 0
        for moduleName in self._modules:
            try:
                if moduleName not in availableModules:
                    continue

                req = requests.get(
                    f'https://raw.githubusercontent.com/project-alice-powered-by-snips/ProjectAliceModules/master/PublishedModules/{availableModules[moduleName]["author"]}/{moduleName}/{moduleName}.install'
                )

                remoteFile = req.json()
                if float(remoteFile['version']) > float(
                        availableModules[moduleName]['version']):
                    i += 1

                    if not self.ConfigManager.getAliceConfigByName(
                            'moduleAutoUpdate'):
                        if moduleName in self._modules:
                            self._modules[moduleName][
                                'instance'].updateAvailable = True
                        elif moduleName in self._deactivatedModules:
                            self._deactivatedModules[moduleName][
                                'instance'].updateAvailable = True
                    else:
                        moduleFile = Path(commons.rootDir(),
                                          'system/moduleInstallTickets',
                                          moduleName + '.install')
                        moduleFile.write_text(json.dumps(remoteFile))

            except Exception as e:
                self._logger.warning(
                    f'[{self.name}] Error checking updates for module "{moduleName}": {e}'
                )

        self._logger.info(f'[{self.name}] Found {i} module update(s)')
    def _speakOnSonos(self, text, client):
        if text == '':
            return

        subprocess.call([
            'sudo',
            Path(commons.rootDir(), '/system/scripts/snipsSuperTTS.sh'),
            Path('/share/tmp.wav'), 'amazon',
            self.LanguageManager.activeLanguage, 'US', 'Joanna', 'FEMALE',
            text, '22050'
        ])

        sonosModule = self.ModuleManager.getModuleInstance('Sonos')
        if sonosModule:
            sonosModule.aliceSpeak(client)
        else:
            self._logger.error(
                'Tried to speak on Sonos but Sonos module is disabled or missing'
            )
Example #24
0
    def start(self, session: DialogSession):
        super().start(session)

        SuperManager.getInstance().mqttManager.playSound(
            soundFile=os.path.join(commons.rootDir(), 'modules', 'Minigames',
                                   'sounds', 'rollADice'),
            sessionId='rollADice',
            siteId=session.siteId,
            absolutePath=True)

        redQueen = SuperManager.getInstance().moduleManager.getModuleInstance(
            'RedQueen')
        redQueen.changeRedQueenStat('happiness', 5)

        SuperManager.getInstance().mqttManager.endDialog(
            sessionId=session.sessionId,
            text=SuperManager.getInstance().talkManager.randomTalk(
                talk='rollADiceResult',
                module='Minigames').format(random.randint(1, 6)))
Example #25
0
    def checkForModuleUpdates(self):
        if not self.ConfigManager.getAliceConfigByName('moduleAutoUpdate'):
            return

        self._logger.info('[{}] Checking for module updates'.format(self.name))
        if not self.InternetManager.online:
            self._logger.info('[{}] Not connected...'.format(self.name))
            return

        self._busyInstalling.set()

        availableModules = self.ConfigManager.modulesConfigurations

        i = 0
        for moduleName in self._modules:
            try:
                if moduleName not in availableModules:
                    continue

                req = requests.get(
                    'https://raw.githubusercontent.com/project-alice-powered-by-snips/ProjectAliceModules/master/PublishedModules/{0}/{1}/{1}.install'
                    .format(availableModules[moduleName]['author'],
                            moduleName))

                remoteFile = json.loads(req.content.decode())
                if float(remoteFile['version']) > float(
                        availableModules[moduleName]['version']):
                    i += 1
                    moduleFile = Path(commons.rootDir(),
                                      'system/moduleInstallTickets',
                                      moduleName + '.install')
                    moduleFile.write_text(json.dumps(remoteFile))
                    self._modules[moduleName]['instance'].active = False

            except Exception as e:
                self._logger.warning(
                    '[{}] Error checking updates for module "{}": {}'.format(
                        self.name, moduleName, e))

        self._logger.info('[{}] Found {} module update(s)'.format(
            self.name, i))
        self._busyInstalling.clear()
Example #26
0
    def loadModuleCommands(self, moduleName: str) -> bool:
        commandsMountpoint = Path(commons.rootDir(), 'modules', moduleName,
                                  'console')

        for commandFile in commandsMountpoint.glob('*Command.py'):
            commandClassFile = commandFile.with_suffix(
                '').absolute().as_posix()

            try:
                commandImport = importlib.import_module(
                    'modules.{}.console.{}'.format(moduleName,
                                                   commandClassFile))
                klass = getattr(commandImport, commandClassFile)
                instance = klass()
                self.add(instance)
                return True
            except Exception:
                pass

        return False
Example #27
0
	def onModuleInstalled(self):
		service = f"""\
[Unit]
Description=zigbee2mqtt
After=network.target

[Service]
ExecStart=/usr/bin/npm start
WorkingDirectory=/opt/zigbee2mqtt
StandardOutput=inherit
StandardError=inherit
Restart=always
User={getpass.getuser()}

[Install]
WantedBy=multi-user.target"""

		filepath = Path(commons.rootDir(), 'zigbee2mqtt.service')
		filepath.write_text(service)
		subprocess.run(['sudo', 'mv', str(filepath), '/etc/systemd/system/zigbee2mqtt.service'])
		subprocess.run(['sudo', 'systemctl', 'daemon-reload'])
    def onMessage(self, intent: str, session: DialogSession):
        if intent == self._INTENT_ANSWER_ROCK_PAPER_OR_SCISSORS:
            choices = ['rock', 'paper', 'scissors']
            me = random.choice(choices)

            SuperManager.getInstance().mqttManager.playSound(
                soundFile=os.path.join(commons.rootDir(), 'modules',
                                       'Minigames', 'sounds', 'drum_suspens'),
                siteId=session.siteId,
                absolutePath=True)

            redQueen = SuperManager.getInstance(
            ).moduleManager.getModuleInstance('RedQueen')
            redQueen.changeRedQueenStat('happiness', 5)
            player = session.slotValue('RockPaperOrScissors')
            # tie
            if player == me:
                result = 'rockPaperScissorsTie'
            # player wins
            elif choices[choices.index(player) - 1] == me:
                result = 'rockPaperScissorsWins'
                redQueen.changeRedQueenStat('frustration', 2)
            # alice wins
            else:
                result = 'rockPaperScissorsLooses'
                redQueen.changeRedQueenStat('frustration', -5)
                redQueen.changeRedQueenStat('happiness', 5)

            SuperManager.getInstance().mqttManager.continueDialog(
                sessionId=session.sessionId,
                text=SuperManager.getInstance().talkManager.randomTalk(
                    talk=result, module='Minigames').format(
                        SuperManager.getInstance().languageManager.
                        getTranslations(module='Minigames',
                                        key=me,
                                        toLang=SuperManager.getInstance().
                                        languageManager.activeLanguage)[0]),
                intentFilter=[self._INTENT_ANSWER_YES_OR_NO],
                previousIntent=self._INTENT_PLAY_GAME,
                customData={'askRetry': True})
Example #29
0
class SyslogView(View):
    LOGS = Path(commons.rootDir(), 'var', 'logs', 'logs.log')

    def __init__(self):
        super().__init__()
        self._counter = 0

    def index(self):
        return render_template('syslog.html', langData=self._langData)

    def update(self):
        return jsonify(data=self._getData())

    def refresh(self):
        self._counter = 0
        return self.update()

    def _getData(self) -> list:
        data = self.LOGS.open('r').readlines()
        ret = data[self._counter:]
        self._counter = len(data)
        return ['] -'.join(line.split('] -')[1:]) for line in ret]
Example #30
0
    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()))