def update_tasks(self, new_tasks): m = Memory("tasks.json") if m.get_data("tasks_list") is None: m.add_data("tasks_list", new_tasks) else: m.update_data("tasks_list", new_tasks) m.save() self.tasks = new_tasks
def remove_task_from_memory(self, task_name): m = Memory("tasks.json") task_list = m.get_data("tasks_list") if task_list is None: return old_task = filter(lambda x: x["name"] != task_name, task_list) m.update_data("tasks_list", list(old_task)) m.save()
def update_api_key( self, jarvis, ): user_api_key = jarvis.input("Enter New Api-BasketBall.com API_KEY: ", Fore.GREEN) m = Memory("basketball.json") m.update_data("API_KEY", user_api_key) m.save() self.key = user_api_key
def get_api_key(self, jarvis): m = Memory("basketball.json") if m.get_data("API_KEY") is None: user_api_key = jarvis.input("Enter Api-BasketBall.com API_KEY: ", Fore.GREEN) m.add_data("API_KEY", user_api_key) m.save() self.key = user_api_key else: self.key = m.get_data("API_KEY")
class JarvisAPI: """ Jarvis interface for plugins. Plugins will receive a instance of this as the second (non-self) parameter of the exec()-method. Everything Jarvis-related that can't be implemented as a stateless-function in the utilities-package should be implemented here. """ _CONNECTION_ERROR_MSG = "You are not connected to Internet" def __init__(self): self.spinner_running = False self.memory = Memory() self.scheduler = schedule.Scheduler() # Remember voice settings self.enable_voice = self.get_data('enable_voice') self.speech_rate = self.get_data('speech_rate') if not self.speech_rate: self.speech_rate = 120 self.io = DummyIO() # what if the platform does not have any engines, travis doesn't have sapi5 acc to me try: gtts_status = self.get_data('gtts_status') self.speech = create_voice(self, gtts_status, rate=self.speech_rate) except Exception as e: self.say("Voice not supported", self, Fore.RED) self.say(str(e), self, Fore.RED) def say(self, text, color="", speak=True): """ This method give the jarvis the ability to print a text and talk when sound is enable. :param text: the text to print (or talk) :param color: for text - use colorama (https://pypi.org/project/colorama/) e.g. Fore.BLUE :param speak: False-, if text shouldn't be spoken even if speech is enabled """ self.io.say(text, color) if speak: self._speak(text) def input(self, prompt="", color=""): """ Get user input """ self.io.input(prompt, color) def exit(self): """Immediately exit Jarvis""" self.io.exit() def _speak(self, text): if self.enable_voice: self.speech.text_to_speech(text) def input_number(self, prompt="", color="", rtype=float, rmin=None, rmax=None): """ Get user input: As number. Guaranteed only returns number - ask user till correct number entered. :param prompt: Printed to console :param color: Color of prompot :param rtype: type of return value; e.g. float (default) or int :param rmin: Minum of values returned :param rmax: Maximum of values returned """ while True: try: value = rtype(self.input(prompt, color).replace(',', '.')) if (rmin is not None and value < rmin) or (rmax is not None and value > rmax): prompt = "Sorry, needs to be between {} and {}. Try again: ".format(rmin, rmax) else: return value except ValueError: prompt = 'Sorry, needs to be a number. Try again: ' continue def connection_error(self): """Print generic connection error""" if self.is_spinner_running(): self.spinner_stop('') self.say(JarvisAPI._CONNECTION_ERROR_MSG) def notification(self, msg, time_seconds=0): """ Sends notification msg in time_in milliseconds :param msg: Message. Either String (message body) or tuple (headline, message body) :param time_seconds: Time in seconds to wait before showing notification """ if isinstance(msg, tuple): headline, message = msg elif isinstance(msg, str): headline = "Jarvis" message = msg else: raise ValueError("msg not a string or tuple") if time_seconds == 0: notify(headline, message) else: schedule(time_seconds, notify, headline, message) def schedule(self, time_seconds, function, *args): """ Schedules function After time_seconds call function with these parameter: - reference to this JarvisAPI instance - schedule_id (return value of this function) - *args :return: integer, id - use with cancel """ return self.scheduler.create_event( time_seconds, function, self, *args) def cancel(self, schedule_id): """ Cancel event scheduled with schedule :param schedule_id: id returned by schedule """ spinner = SpinnerThread('Cancelling', 0.15) spinner.start() self.scheduler.cancel(schedule_id) spinner.stop() self.say('Cancellation successful', Fore.GREEN) # Voice wrapper def enable_voice(self): """ Use text to speech for every text passed to jarvis.say() """ g = self.get_data('gtts_status') self.speech = create_voice(self, g, rate=120) self.enable_voice = True self.update_data('enable_voice', True) def disable_gtts(self): """ Switch to default speech engine for every text passed to jarvis.say() """ self.update_data('gtts_status', False) def enable_gtts(self): """ Use google text to speech for every text passed to jarvis.say() """ self.update_data('gtts_status', True) g = self.get_data('gtts_status') self.speech = create_voice(self, g, rate=120) def disable_voice(self): """ Stop text to speech output & disable gtts for every text passed to jarvis.say() """ self.disable_gtts() self.enable_voice = False self.update_data('enable_voice', False) def is_voice_enabled(self): """ Returns True/False if voice is enabled/disabled with enable_voice or disable_voice Default: False (disabled) """ return self.enable_voice def change_speech_rate(self, delta): """ Alters the rate of the speech engine by a specified amount and remember the new speech rate. :param delta: Amount of change to apply to speech rate """ self.speech.change_rate(delta) self.update_data('speech_rate', self.speech.rate) # MEMORY WRAPPER def get_data(self, key): """ Get a specific key from memory """ return self.memory.get_data(key) def add_data(self, key, value): """ Add a key and value to memory """ self.memory.add_data(key, value) self.memory.save() def update_data(self, key, value): """ Updates a key with supplied value. """ self.memory.update_data(key, value) self.memory.save() def del_data(self, key): """ Delete a key from memory """ self.memory.del_data(key) self.memory.save() def eval(self, s): """ Simulates typing 's' in Jarvis prompt """ line = self._jarvis.precmd(s) stop = self._jarvis.onecmd(line) stop = self._jarvis.postcmd(stop, line) # TODO def spinner_start(self, message="Starting "): """ Function for starting a spinner when prompted from a plugin and a default message for performing the task """ self.spinner_running = True self.spinner = SpinnerThread(message, 0.15) self.spinner.start() def spinner_stop(self, message="Task executed successfully! ", color=Fore.GREEN): """ Function for stopping the spinner when prompted from a plugin and displaying the message after completing the task """ self.spinner.stop() self.say(message, color) self.spinner_running = False def is_spinner_running(self): return self.spinner_running def get_server(self): return self.io.cmd_interpreter._jarvis.server
class CmdInterpreter(Cmd): # We use this variable at Breakpoint #1. # We use this in order to allow Jarvis say "Hi", only at the first # interaction. # This can be used to store user specific data def __init__(self, first_reaction_text, prompt, directories=[], first_reaction=True, enable_voice=False): """ This constructor contains a dictionary with Jarvis Actions (what Jarvis can do). In alphabetically order. """ Cmd.__init__(self) self.first_reaction = first_reaction self.first_reaction_text = first_reaction_text self.prompt = prompt self.enable_voice = enable_voice # Register do_quit() function to SIGINT signal (Ctrl-C) signal.signal(signal.SIGINT, self.interrupt_handler) self.memory = Memory() self.scheduler = schedule.Scheduler() self.speech = create_voice() self.actions = [ { "check": ("ram", "weather", "time", "forecast") }, "directions", "help", "how_are_you", "near", "pinpoint", "umbrella", { "update": ("location", "system") }, "weather", ] self.fixed_responses = { "what time is it": "clock", "where am i": "pinpoint", "how are you": "how_are_you" } self._api = JarvisAPI(self) self._plugin_manager = PluginManager() for directory in directories: self._plugin_manager.add_directory(directory) self._activate_plugins() def _activate_plugins(self): """Generate do_XXX, help_XXX and (optionally) complete_XXX functions""" for (plugin_name, plugin) in self._plugin_manager.get_all().items(): completions = self._plugin_update_action(plugin, plugin_name) if completions is not None: def complete(completions): def _complete_impl(self, text, line, begidx, endidx): return [i for i in completions if i.startswith(text)] return _complete_impl setattr(CmdInterpreter, "complete_" + plugin_name, complete(completions)) setattr(CmdInterpreter, "do_" + plugin_name, partial(plugin.run, self._api)) setattr(CmdInterpreter, "help_" + plugin_name, partial(self._api.say, plugin.get_doc())) if hasattr(plugin.__class__, "init") and callable( getattr(plugin.__class__, "init")): plugin.init(self._api) def _plugin_update_action(self, plugin, plugin_name): """Return True if completion is available""" complete = plugin.complete() if complete is not None: # add plugin with completion # Dictionary: # { plugin_name : list of completions } complete = [x for x in complete] self.actions.append({plugin_name: complete}) return complete else: # add plugin without completion # plugin name only self.actions.append(plugin_name) return None def close(self): """Closing Jarvis.""" print_say("Goodbye, see you later!", self, Fore.RED) self.scheduler.stop_all() exit() def completedefault(self, text, line, begidx, endidx): """Default completion""" return [i for i in self.actions if i.startswith(text)] def error(self): """Jarvis let you know if an error has occurred.""" print_say("I could not identify your command...", self, Fore.RED) def get_completions(self, command, text): """Returns a list with the completions of a command.""" dict_target = [ item for item in self.actions if type(item) == dict and command in item ][0] completions_list = dict_target[command] return [i for i in completions_list if i.startswith(text) and i != ''] def interrupt_handler(self, signal, frame): """Closes Jarvis on SIGINT signal. (Ctrl-C)""" self.close() def do_calculate(self, s): """Jarvis will get your calculations done!""" tempt = s.replace(" ", "") if len(tempt) > 1: evaluator.calc(tempt, self) else: print_say("Error: Not in correct format", self, Fore.RED) def help_calculate(self): """Print help about calculate command.""" print_say("Jarvis will get your calculations done!", self) print_say("-- Example:", self) print_say("\tcalculate 3 + 5", self) def do_check(self, s): """Checks your system's RAM stats.""" # if s == "ram": if "ram" in s: system("free -lm") # if s == "time" elif "time" in s: timeIn.main(self, s) elif "forecast" in s: forecast.main(self, s) # if s == "weather" elif "weather" in s: try: weatherIn.main(self, s) except ConnectionError: print(CONNECTION_ERROR_MSG) def help_check(self): """Prints check command help.""" print_say("ram: checks your system's RAM stats.", self) print_say("time: checks the current time in any part of the globe.", self) print_say( "weather in *: checks the current weather in any part of the globe.", self) print_say("forecast: checks the weather forecast for the next 7 days.", self) print_say("-- Examples:", self) print_say("\tcheck ram", self) print_say("\tcheck time in Manchester (UK)", self) print_say("\tcheck weather in Canada", self) print_say("\tcheck forecast", self) print_say("\tcheck forecast in Madrid", self) # add here more prints def complete_check(self, text, line, begidx, endidx): """Completions for check command""" return self.get_completions("check", text) def do_directions(self, data): """Get directions about a destination you are interested to.""" try: directions_to.main(data) except ValueError: print("Please enter destination") except ConnectionError: print(CONNECTION_ERROR_MSG) def help_directions(self): """Prints help about directions command""" print_say("Get directions about a destination you are interested to.", self) print_say("-- Example:", self) print_say("\tdirections to the Eiffel Tower", self) def do_how_are_you(self, s): """Jarvis will inform you about his status.""" print_say("I am fine, How about you?", self, Fore.BLUE) def help_how_are_you(self): """Print info about how_are_you command""" print_say("Jarvis will inform you about his status.", self) def do_near(self, data): """Jarvis can find what is near you!""" near_me.main(data) def help_near(self): """Print help about near command.""" print_say("Jarvis can find what is near you!", self) print_say("-- Examples:", self) print_say("\trestaurants near me", self) print_say("\tmuseums near the eiffel tower", self) def do_pinpoint(self, s): """Jarvis will pinpoint your location.""" try: mapps.locate_me() except ConnectionError: print(CONNECTION_ERROR_MSG) def help_pinpoint(self): """Print help about pinpoint command.""" print_say("Jarvis will pinpoint your location.", self) def do_umbrella(self, s): """If you're leaving your place, Jarvis will inform you if you might need an umbrella or not""" s = 'umbrella' try: weather_pinpoint.main(self.memory, self, s) except ConnectionError: print(CONNECTION_ERROR_MSG) def help_umbrella(self): """Print info about umbrella command.""" print_say( "If you're leaving your place, Jarvis will inform you if you might need an umbrella or not.", self, Fore.BLUE) def do_update(self, s): """Updates location or system.""" if "location" in s: location = self.memory.get_data('city') loc_str = str(location) print_say("Your current location is set to " + loc_str, self) print_say("What is your new location?", self) i = input() self.memory.update_data('city', i) self.memory.save() elif "system" in s: update_system() def help_update(self): """Prints help about update command""" print_say("location: Updates location.", self) print_say("system: Updates system.", self) def complete_update(self, text, line, begidx, endidx): """Completions for update command""" return self.get_completions("update", text) def do_weather(self, s): """Get information about today's weather.""" try: word = s.strip() if (len(word) > 1): weatherIn.main(self, s) else: weather_pinpoint.main(self.memory, self, s) except ConnectionError: print(CONNECTION_ERROR_MSG) def help_weather(self): """Prints help about weather command.""" print_say( "Get information about today's weather in your current location.", self)