class CommandHandler: def __init__(self): self.speaker = AssistantSpeaker() self.weatherCommand = WeatherCommand() self.meetingCommand = MeetingCommand() self.remindMeetingsCommand = RemindMeetingsCommand() self.allCommandsCommand = AllCommandsCommand() self.changeParameterCommand = ChangeParametersCommand() self.helpCommand = HelpCommand() self.timeCommand = TimeCommand() def executeCommand(self, sentenceSaidByUser): print(sentenceSaidByUser) # for testing purposes, we're just using the default API key # to use another API key, use `r.recognize_google(audio, key="GOOGLE_SPEECH_RECOGNITION_API_KEY")` # instead of `r.recognize_google(audio)` if (sentenceSaidByUser == "weather"): self.weatherCommand.executeCommand() elif (sentenceSaidByUser == "all commands"): self.allCommandsCommand.executeCommand() elif (sentenceSaidByUser == "save meeting"): self.meetingCommand.executeCommand() elif (sentenceSaidByUser == "remind meetings"): self.remindMeetingsCommand.executeCommand() elif (sentenceSaidByUser == "change parameters"): self.changeParameterCommand.executeCommand() elif (sentenceSaidByUser == "help"): self.helpCommand.executeCommand() elif (sentenceSaidByUser == "time"): self.timeCommand.executeCommand() else: self.speaker.say( "Sorry, I don't recognize this command. To get all the available commands, say all commands." ) print("I don't understand")
class WeatherCommand: def __init__(self): self.speaker = AssistantSpeaker() def executeCommand(self): self.speaker.say("Looking for the current temperature in Montreal") # Need to specify the headless option otherwise selenium will open # a chrome window and we don't want that # Cannot use urllib here because span content is dynamic options = webdriver.ChromeOptions() options.add_argument(Constants.DRIVER_ARGUMENT) driver = webdriver.Chrome(executable_path=Constants.DRIVER_EXEC_PATH, chrome_options=options) driver.get(Constants.WEATHER_URL) # Use beautiful soup to parse the html page to speed up the process # Beautiful soup has a faster parser than Selenium beautiful_soup = BeautifulSoup(driver.page_source, Constants.BEAUTIFUL_SOUP_PARSER) spanWithTemperature = beautiful_soup.find_all('span', {'class': 'temp'})[0] print(spanWithTemperature.text) self.speaker.say("The temperature is currently " + spanWithTemperature.text + "degree") print('Quit driver') # Important to close the driver to avoid having multiple chrome tasks # opened at the same time driver.quit()
class AllCommandsCommand: def __init__(self): self.speaker = AssistantSpeaker() def executeCommand(self): self.speaker.say("The available commands are : All commands, Change parameters, Help, Time, Save meeting, Remind meetings and Weather. For more informations about a command, say help.")
class StartActionThread(QThread): signal = pyqtSignal('PyQt_PyObject') def __init__(self, command=None): QThread.__init__(self) self.speaker = AssistantSpeaker() self.listener = AssistantListener() self.commandHandler = CommandHandler() self.command = command def run(self): if self.command is None: self.speaker.say("Tell me your command") self.command = self.listener.listen() # -1 means a WaitTimeoutException occured if (self.command == -1): self.speaker.say("Sorry, I could not understand the command") else: self.commandHandler.executeCommand(self.command) self.signal.emit("finished")
class TimeCommand: def __init__(self): self.speaker = AssistantSpeaker() self.listener = AssistantListener() def executeCommand(self): self.speaker.say("For which city do you want the current time ?") city = self.listener.listen() if city == -1: self.speaker.say( "Sorry I did not understand the name of the city.") return -1 print(city) self.speaker.say( "Please wait while I'm looking for the current time in " + city) print("Prepare Selenium webdriver to get the time") string_current_time_city = self.getTimeFromWebSite(city) self.speaker.say("In " + city + " it is " + string_current_time_city + " o'clock.") def getTimeFromWebSite(self, city): options = webdriver.ChromeOptions() options.add_argument(Constants.DRIVER_ARGUMENT) driver = webdriver.Chrome(executable_path=Constants.DRIVER_EXEC_PATH, chrome_options=options) driver.get(Constants.TIME_URL + city) # Use beautifulSoup to parse the source page for better performance soup = BeautifulSoup(driver.page_source, Constants.BEAUTIFUL_SOUP_PARSER) answer = soup.find('td', id='p0') print('Quit driver') # Important to close the driver to avoid having multiple chrome tasks # opened at the same time driver.quit() # Date is with format 'Day Hour:Minute AM' splited_answer = answer.text.split() return splited_answer[1] + ' ' + splited_answer[2]
class RemindMeetingsCommand: def __init__(self): self.speaker = AssistantSpeaker() self.listener = AssistantListener() self.dateFormat = Constants.MEETING_DATE_FORMAT self.appJsonFile = JsonFileUtil(Constants.APP_PROPERTIES_FILENAME, Constants.APP_PROPERTIES_PATH) self.meetingJsonFile = JsonFileUtil(Constants.MEETING_FILENAME, Constants.MEETING_FILEPATH) self.intervalMeetingReminderKey = Constants.APP_PROP_INTERVALMEETING_PARAM # The app_properties file contain all the properties for the app # Return the number of days before a meeting we want the reminder to be triggered def getIntervalMeetingReminder(self): appProperties = self.getJsonDataFromJsonFile(self.jsonAppFilePath, self.jsonAppFileName) return appProperties[self.intervalMeetingReminderKey] def remindScheduledMeetings(self, numberOfDaysBeforeMeetingReminder): currentDate = datetime.date.today() maximumDateForReminder = currentDate + datetime.timedelta( days=int(numberOfDaysBeforeMeetingReminder)) meetings = self.meetingJsonFile.getData() for meetingKey in meetings: meetingDateTime = datetime.datetime.strptime( meetingKey, self.dateFormat) meetingDate = meetingDateTime.date() # The date comparison can only be made on datetime.date objects and not on datetime.datetime! if (maximumDateForReminder >= meetingDate and meetingDate >= currentDate): meetingValue = self.meetingJsonFile.getValue(meetingKey) self.speaker.say(meetingValue + ' is due for ' + meetingKey) self.speaker.say("All the meetings coming in the next " + numberOfDaysBeforeMeetingReminder + " days have been said") def executeCommand(self): self.speaker.say("Reminding the upcoming meetings.") numberOfDaysBeforeMeetingReminder = self.appJsonFile.getValue( self.intervalMeetingReminderKey) self.remindScheduledMeetings(numberOfDaysBeforeMeetingReminder)
class HelpCommand: def __init__(self): self.speaker = AssistantSpeaker() self.listener = AssistantListener() def executeCommand(self): self.speaker.say("For which command do you need help ?") command_for_help = self.listener.listen() if command_for_help == 'weather': self.speaker.say("Simply say weather and you will have the current temperature in Montreal.") elif command_for_help == 'change parameters': self.speaker.say("After saying the command name, you will be ask to say the parameter name and the parameter value.") elif command_for_help == 'time': self.speaker.say("After saying the command name, you will be ask to say the name of the city. You will then hear the current time of the most likely city found.") elif command_for_help == 'all commands': self.speaker.say("Give all the available commands in the application.") elif command_for_help == 'remind meetings': self.speaker.say("The assistant will say all the upcoming meetings the the user. All the meetings from today plus the days interval specified in the interval meeting reminder application parameter will be reminded.") elif command_for_help == 'save meeting': self.speaker.say("For saving a meeting, you need too give, when it is asked, the year, the month (using number from 1 to 12), the day (using number from 1 to 31), the hour (using number from 0 to 24), the minute (using number from 0 to 60) and the meeting content") else: self.speaker.say("Sorry this command doesn't exist. For a list of all available commands, say All commands.")
class MeetingCommand: def __init__(self): self.speaker = AssistantSpeaker() self.listener = AssistantListener() self.dateFormat = Constants.MEETING_DATE_FORMAT self.meetingJsonFile = JsonFileUtil(Constants.MEETING_FILENAME, Constants.MEETING_FILEPATH) def getMeetingDateFromUser(self): dateIsValid = False while(dateIsValid is not True): year = self.getDateElement("year"); month = self.getDateElement("month"); day = self.getDateElement("day"); hour = self.getDateElement("hour"); minute = self.getDateElement("minute"); try: dateOfMeeting = datetime.datetime(year, month, day, hour, minute) dateIsValid = True except ValueError: self.speaker.say("The given date was invalid, please record it again") dateIsValid = False print(dateOfMeeting) return dateOfMeeting def getDateElement(self, elementOfDate): dateElement = -1 # listener.listen return -1 if there is a Waittimeout error while(dateElement == -1): self.speaker.say("What is the number of the " + elementOfDate + " for the meeting ?") dateElement = self.listener.listen() try: dateElement = int(dateElement) except ValueError: self.speaker.say("The given " + elementOfDate + " is not valid.") dateElement = -1 print("Element of date is " + str(dateElement)) return dateElement def getMeetingSubjectFromUser(self): # listener.listen return -1 if there is a Waittimeout error subjectOfMeeting = -1 while(subjectOfMeeting == -1): self.speaker.say("Please say what you want to remember at this date") subjectOfMeeting = self.listener.listen() print(subjectOfMeeting) return subjectOfMeeting def saveNewMeeting(self, dateOfMeeting, subjectOfMeeting): currentJsonData = self.meetingJsonFile.getData() dateOfMeetingInString = dateOfMeeting.strftime(self.dateFormat) if dateOfMeetingInString not in currentJsonData: currentJsonData[dateOfMeetingInString] = subjectOfMeeting else: currentMeetingsForDate = currentJsonData[dateOfMeetingInString] currentJsonData[dateOfMeetingInString] = currentMeetingsForDate + " and you also have " + subjectOfMeeting with open(Constants.MEETING_FILENAME, 'w+') as file: json.dump(currentJsonData, file, ensure_ascii=False) self.speaker.say("Meeting successfully saved") def executeCommand(self): self.speaker.say("Let's save a meeting!") dateOfMeeting = self.getMeetingDateFromUser() subjectOfMeeting = self.getMeetingSubjectFromUser() self.saveNewMeeting(dateOfMeeting, subjectOfMeeting)