def get_unread_gmail_messages(gmail_service): global msg logger.info("Getting unread messages") results = gmail_service.users().messages().list(userId='me', labelIds=["INBOX"], q="is:unread").execute() messages = results.get('messages', []) if not messages: logger.info("Zero messages found") speak(ENGINE, "You have no messages") else: message_count = 0 for message in messages: msg = gmail_service.users().messages().get( userId="me", id=message['id']).execute() message_count += 1 logger.info("%s unread messages found" % str(message_count)) speak(ENGINE, "You have " + str(message_count) + " unread messages") speak(ENGINE, "Would you like to see your messages?") if "yes" in get_audio().lower(): for _ in messages: email_data = msg["payload"]["headers"] for values in email_data: name = values["name"] if name == "From": from_name = values["value"] speak(ENGINE, "You have a new message from: " + from_name) else: speak(ENGINE, "Oki, I won't show it.") mark_as_read(gmail_service, messages) delete_message(gmail_service, messages)
def get_directory_path() -> list: logger.info("Getting directory path.") speak(ENGINE, "OK, all I need is you paste path to your folder") from_path = input("Path to your folder:\n").replace('"', "") if os.path.isdir(from_path): speak(ENGINE, "I found it. Paste a path where you want to copy your folder") to_path = input( "Path to folder where folder will be copied:\n").replace('"', "") if os.path.isdir(to_path): return [from_path, to_path] else: logger.warning( "Getting directory path function ended with warning. User tried to copy folder into file." ) return ["Folder into file"] else: logger.warning( "Getting directory path function ended with warning: Not a folder." ) return ["Not a folder"]
def get_installed_apps_before_begin(): logger.info('Getting installed apps') installed_apps = None if os.path.exists('installed_programs.pickle'): logger.info('File with installed programs was found') with open('installed_programs.pickle', 'rb') as token: installed_apps = pickle.load(token) if not installed_apps: logger.info( 'File with installed programs was not found. Getting installed programs' ) speak( ENGINE, "Hello, my name is Sarah. I am your virtual voice assistant. Give me few seconds to configure settings" ) logger.info("Sarah starts configuration.") installed_apps = get_installed_programs() with open("installed_programs.pickle", "wb") as pickle_file: pickle.dump(installed_apps, pickle_file) logger.info('Installed applications was added to pickle file.') return installed_apps
def open_program(program_name: str): logger.info("Opening program function started") programs = [] installed_apps = get_installed_apps_before_begin() for app in installed_apps: for file in app['files']: if file.lower().__contains__(program_name): programs.append(os.path.join(app['root'], file)) if len(programs) > 1: program_number = None speak( ENGINE, "These are the programs I found. Please enter a number of program." ) for program in programs: print(ntpath.basename(program)) try: program_number = int(input("")) - 1 except ValueError: logger.error( "Number of founded programs was expected. But user provides something else." ) speak(ENGINE, "It is not a number.") try: os.startfile(programs[program_number]) except IndexError: logger.error("Sarah found %s programs, but user tried to open %s" % (len(programs), program_number)) speak(ENGINE, "I think I found fewer programs.") except TypeError as terror: logger.error("Cannot open program. Error is: %s" % terror) pass elif len(programs) == 0: logger.warning("Sarah cannot find any program") speak(ENGINE, "Sorry, I can't find this program.") else: logger.info("Opening %s" % ntpath.basename(programs[0])) speak(ENGINE, "Opening %s" % ntpath.basename(programs[0])) os.startfile(programs[0])
def get_user_info_before_begin(): user_info = None if os.path.exists('user_info.pickle'): logger.info("File with user information was found") with open('user_info.pickle', 'rb') as token: user_info = pickle.load(token) speak(ENGINE, "Hello {}!".format(user_info['first_name'])) if not user_info: logger.info("File with user information was not found") logger.info("Getting some information about user for better work") speak(ENGINE, "What is your name?") first_name = input().capitalize() speak(ENGINE, "What is your surname?") last_name = input().capitalize() speak( ENGINE, "Nice to meet you %s! I will also need your email for sending your messages" % first_name) email = input() while not is_valid_email(email): answers = [ "Please give me correct email", "This email is not correct" ] speak(ENGINE, choices(answers)[0]) email = input() user_info = { "first_name": first_name, "last_name": last_name, "email": email, } with open("user_info.pickle", "wb") as pickle_file: pickle.dump(user_info, pickle_file) logger.info( "Got user information. File with user information was successfully created" ) logger.info("Collected data about user") logger.info("Sarah successfully ended configuration...") return user_info
def delete_message(gmail_service, messages: list): speak(ENGINE, "Would you like to delete these messages?") if "yes" in get_audio().lower(): logger.info("Deleting unread messages") speak(ENGINE, "Ok, I'll delete these messages.") return gmail_service.users().messages().batchDelete( userId="me", body={ "ids": [message["id"] for message in messages] }).execute() else: speak(ENGINE, "Okay, I won't delete these messages.")
def mark_as_read(gmail_service, messages: list): speak(ENGINE, "Would you like to mark these messages as read?") if "yes" in get_audio().lower(): speak(ENGINE, "Ok, I'll mark these messages as read.") logger.info("Marking messages as read") return gmail_service.users().messages().batchModify( userId="me", body={ 'removeLabelIds': ["UNREAD"], 'ids': [message["id"] for message in messages] }).execute() else: speak(ENGINE, "Okay, I won't mark these messages as read.")
def get_file_path() -> list: speak(ENGINE, "OK, all I need is you paste path to your file") from_path = input("Path to your file:\n").replace('"', "") if os.path.isfile(from_path): speak(ENGINE, "I found it. Paste a path where you want to copy your file") to_path = input("Path to folder where file will be copied:\n").replace( '"', "") if os.path.isdir(to_path): return [from_path, to_path] else: logger.warning("Copy function cannot copy file to directory %s " "because it doesn't exist. Creating folder" % to_path) speak(ENGINE, "Folder does not exist. I'll create this folder") os.mkdir(to_path) return [from_path, to_path] else: return ["Not a file"]
def main(): while True: logger.info("Sarah is running.") text = get_audio().lower() if text in WAKE: speak(ENGINE, "Hello, what do you want me to do?") text = get_audio().lower() for phrase in EVENT_CALENDAR_STRS: if phrase in text: create_google_calendar_event(CALENDAR_SERVICE) for phrase in CALENDAR_STRS: if phrase in text: logger.info("Found %s in CALENDAR_STRS" % phrase) date = get_date(text) if date: events = get_google_calendar_events( date, CALENDAR_SERVICE) if not events: logger.info( "Sarah notice that there are no events found.") speak(ENGINE, 'No upcoming events found.') else: logger.info("Sarah found %s events." % len(events)) speak( ENGINE, 'You have %s events on this day' % len(events)) for event in events: start = event['start'].get( 'dateTime', event['start'].get('date')) start_time = str( start.split("T")[1].split("+")[0]) if int(start_time.split(":")[0]) < 12: start_time = start_time + "AM" else: start_time = str( int(start_time.split(":")[0]) - 12) + start_time.split(":")[1] start_time = start_time + "PM" speak(ENGINE, event["summary"] + " at " + start_time) else: speak(ENGINE, "I don't understand") for phrase in NOTE_STRS: if phrase in text: logger.info("Found %s. in NOTE_STRS" % phrase) speak(ENGINE, "What would you like me to write down?") note_text = get_audio().lower() note(note_text) speak(ENGINE, "I've made a note of that.") for phrase in GMAIL_STRS: if phrase in text: logger.info("Found %s in GMAIL_STRS" % phrase) get_unread_gmail_messages(GMAIL_SERVICE) for phrase in SEND_GMAIL_STRS: if phrase in text: logger.info("Found %s in SEND_GMAIL_STRS" % phrase) send_email_message(GMAIL_SERVICE) for phrase in BROWSER_STRS: if phrase in text: logger.info("Found %s in BROWSER_STRS" % phrase) speak(ENGINE, "Which browser?") browser_name = get_audio().lower() open_browser = start_browser(browser_name) if open_browser == "Cannot find this browser": speak(ENGINE, open_browser) else: speak(ENGINE, "I've got it. Just a second") os.system(open_browser) for phrase in MATH_STRS: if phrase in text: logger.info("Found %s in MATH_STRS" % phrase) result = execute_math(phrase, text) if result == "division by zero": speak(ENGINE, "Hmm, division by zero is impossible") else: speak(ENGINE, "it is: %s" % result) for phrase in COPY_STRS: if phrase in text: logger.info("Found %s in COPY_STRS" % phrase) if "copy file" in phrase: path = get_file_path() if len(path) > 1: speak(ENGINE, "On its way...") speak(ENGINE, "Successfully copied") if copy_file( path[0], path[1]) == "OK" else speak( ENGINE, "Cannot copy file because of error") elif path[0] == "Not a file": speak( ENGINE, "Selected item must be a file, but not folder") elif "copy folder" in phrase: path = get_directory_path() if len(path) > 1: speak(ENGINE, "On it way...") speak(ENGINE, "Successfully copied") if copy_directory( path[0], path[1]) == "OK" else speak( ENGINE, "Cannot copy file because of error") elif path[0] == "Folder into file": speak( ENGINE, "Seriously? Do you want to copy folder to file? Think about it" ) elif path[0] == "Not a folder": speak( ENGINE, "Selected item must be a folder, but not file") for phrase in TIME_NOW_STRS: if phrase in text: logger.info("Found %s in TIME_NOW_STRS" % phrase) speak( ENGINE, "Current time is %s" % datetime.datetime.now().strftime('%H:%M')) for phrase in TIMER_STRS: if phrase in text: logger.info("Found %s in TIMER_STRS" % phrase) timer_thread = threading.Thread(target=set_timer, args=(text, )) timer_thread.start() for phrase in OPEN_PROGRAM_STRS: if phrase in text: logger.info("Found %s in OPEN_PROGRAM_STRS" % phrase) print(phrase, text) program_name = text.replace(phrase, '') open_program(program_name) for phrase in STOP: if phrase in text: logger.info("Found %s in STOP" % phrase) to_stop.append(phrase) if len(to_stop) > 0: logger.info("Sarah stops working") speak(ENGINE, random.choice(END_STR)) break
def send_email_message(gmail_service): global email_content speak(ENGINE, "Who do you want to send the letter to?") send_to_user = input("Receiver:\n") while not is_valid_email(send_to_user): speak(ENGINE, "This email is not correct") send_to_user = input("Your email address is:\n") speak(ENGINE, "What is the subject of this letter?") email_subject = input("Email subject:\n") speak( ENGINE, "Okay. Do you want to say or type your message? (Say 'type' or 'say')") user_response = get_audio().lower() if "say" in user_response: speak(ENGINE, "What is the content of this message?") email_content = get_audio().lower() elif "type" in user_response: speak(ENGINE, "What is the content of this message?") email_content = input("Your message below:\n") with open("user_info.pickle", "rb") as openfile: try: user_email = pickle.load(openfile)["email"] except EOFError: print( "Sorry, I don't know your email address. Type below your Google Gmail Address" ) user_email = input("Your email address is:\n") while not is_valid_email(user_email): speak(ENGINE, "This email is not correct") user_email = input("Your email address is:\n") message = MIMEText(email_content) message["to"] = send_to_user message["from"] = user_email message["subject"] = email_subject try: gmail_service.users().messages().send( userId='me', body={ 'raw': base64.urlsafe_b64encode(message.as_bytes()).decode() }).execute() speak(ENGINE, "Your message has been sent.") except errors.MessageError as error: print("An ERROR occurred: %s" % error)
def stop_timer(): speak(ENGINE, "Timer is done!")