# This is part of Kaylee # -- this code is licensed GPLv3 # Copyright 2015-2017 Clayton G. Hobbs # Portions Copyright 2013 Jezra """Run shell commands that match voice commands This Kaylee plugin can be used to perform the job of `Blather `__. Its configuration is of the following format:: ".shell": { "VOICE_COMMAND": "SHELL_COMMAND", ... } A VOICE_COMMAND may contain any number of the special word ``%d``, which is a stand-in for a spoken number. The spoken number is transformed into a decimal integer which may be substituted into the SHELL_COMMAND any number of times. These substitutions are made by writing ``{INDEX}`` in the SHELL_COMMAND, where INDEX is an integer counting the ``%d`` strings from 0. An example of this type of command is:: "%d is a number": "echo 'the number you said was {0}'" """ import subprocess from . import PluginBase, Handler from ..numbers import NumberParser class Plugin(PluginBase): """Run shell commands that match voice commands""" def __init__(self, config, name): """Initialize the shell plugin""" super().__init__(config, name) self.number_parser = NumberParser() self.commands = self.options for voice_cmd in self.commands.keys(): self.corpus_strings.add(voice_cmd.strip().replace('%d', '')) def get_handler(self, text): """Return whether or not the command can be handled""" if text in self.commands: # If there's an exact match, return a handler for it return ShellHandler(1, self.commands[text]) else: # Otherwise, try substituting numbers numt, nums = self.number_parser.parse_all_numbers(text) if numt in self.commands: # Return a handler if we have a match return ShellHandler(1, self.commands[numt], nums) # Return None if that fails too return None class ShellHandler(Handler): """Handle a voice command that corresponds to a shell command""" def __init__(self, confidence, command, nums=None): """Determine the exact command that will be run""" super().__init__(confidence) if nums is None: self.command = command else: self.command = command.format(*nums) def __call__(self, tts): """Print the command, then run it""" print(self.command) subprocess.call(self.command, shell=True)