Opening Programs
Subscribe to Tech with Tim
In this python voice assistant tutorial I will be showing you how to open programs and applications from python code. Specifically we will create an open a note using notepad.
Importing Modules
We need to start by importing the subprocess module. This will allow us to run processes (like notepad.exe) concurrently with our python script.
import subprocess
Writing Notes
The first step to create a note is to make a function called note(). This function will take some text and create and open a note that contains that text.
def note(text): date = datetime.datetime.now() file_name = str(date).replace(":", "-") + "-note.txt" with open(file_name, "w") as f: f.write(text) subprocess.Popen(["notepad.exe", file_name])
This function will now save a file with a name as the current date. Then open that saved file and show it to the user.
Opening Different Programs
To open different programs all we need to do is find the absolute path to their .exe file. In this example I will show you how we can open sublime text. Hint: Most programs .exe file is saved in your /Program Files on windows
To open sublime text I first find the .exe file which is located here. C:/Program Files\Sublime Text 3\sublime_text.exe
Next I create a variable to store that path and replace the "notepad.exe" with the new variable.
def note(text): date = datetime.datetime.now() file_name = str(date).replace(":", "-") + "-note.txt" with open(file_name, "w") as f: f.write(text) sublime = "C:\Program Files\Sublime Text 3\sublime_text.exe" subprocess.Popen([sublime, file_name])
Calling the Function via Voice
Now that we've created the functionality for our note writing feature we need some way to activate it from the assistant. We follow a similar process to before and start by creating a list of some phrases that we identify with taking a note.
NOTE_STRS = ["make a note", "write this down", "remember this", "type this"]
Next we can loop through all of these and detect if any exists in the audio we get from the user. If the we detect any then we will ask the user what they would like to make a note of and write it down for them.
for phrase in NOTE_STRS: if phrase in text: speak("What would you like me to write down? ") write_down = get_audio() note(write_down) speak("I've made a note of that.")
Full Code
from __future__ import print_function import datetime import pickle import os.path from googleapiclient.discovery import build from google_auth_oauthlib.flow import InstalledAppFlow from google.auth.transport.requests import Request import os import time import pyttsx3 import speech_recognition as sr import pytz import subprocess SCOPES = ['https://www.googleapis.com/auth/calendar.readonly'] MONTHS = ["january", "february", "march", "april", "may", "june","july", "august", "september","october","november", "december"] DAYS = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"] DAY_EXTENTIONS = ["rd", "th", "st", "nd"] def speak(text): engine = pyttsx3.init() engine.say(text) engine.runAndWait() def get_audio(): r = sr.Recognizer() with sr.Microphone() as source: audio = r.listen(source) said = "" try: said = r.recognize_google(audio) print(said) except Exception as e: print("Exception: " + str(e)) return said def authenticate_google(): """Shows basic usage of the Google Calendar API. Prints the start and name of the next 10 events on the user's calendar. """ creds = None if os.path.exists('token.pickle'): with open('token.pickle', 'rb') as token: creds = pickle.load(token) if not creds or not creds.valid: if creds and creds.expired and creds.refresh_token: creds.refresh(Request()) else: flow = InstalledAppFlow.from_client_secrets_file( 'credentials.json', SCOPES) creds = flow.run_local_server(port=0) with open('token.pickle', 'wb') as token: pickle.dump(creds, token) service = build('calendar', 'v3', credentials=creds) return service def get_events(day, service): # Call the Calendar API date = datetime.datetime.combine(day, datetime.datetime.min.time()) end_date = datetime.datetime.combine(day, datetime.datetime.max.time()) utc = pytz.UTC date = date.astimezone(utc) end_date = end_date.astimezone(utc) events_result = service.events().list(calendarId='primary', timeMin=date.isoformat(), timeMax=end_date.isoformat(), singleEvents=True, orderBy='startTime').execute() events = events_result.get('items', []) if not events: speak('No upcoming events found.') else: speak(f"You have {len(events)} events on this day.") for event in events: start = event['start'].get('dateTime', event['start'].get('date')) print(start, event['summary']) 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 = start_time + "pm" speak(event["summary"] + " at " + start_time) def get_date(text): text = text.lower() today = datetime.date.today() if text.count("today") > 0: return today if text.count("tomorrow") > 0: return today + datetime.timedelta(1) day = -1 day_of_week = -1 month = -1 year = today.year for word in text.split(): if word in MONTHS: month = MONTHS.index(word) + 1 elif word in DAYS: day_of_week = DAYS.index(word) elif word.isdigit(): day = int(word) else: for ext in DAY_EXTENTIONS: found = word.find(ext) if found > 0: try: day = int(word[:found]) except: pass # THE NEW PART STARTS HERE if month < today.month and month != -1: # if the month mentioned is before the current month set the year to the next year = year+1 # This is slighlty different from the video but the correct version if month == -1 and day != -1: # if we didn't find a month, but we have a day if day < today.day: month = today.month + 1 else: month = today.month # if we only found a dta of the week if month == -1 and day == -1 and day_of_week != -1: current_day_of_week = today.weekday() dif = day_of_week - current_day_of_week if dif < 0: dif += 7 if text.count("next") >= 1: dif += 7 return today + datetime.timedelta(dif) if day != -1: # FIXED FROM VIDEO return datetime.date(month=month, day=day, year=year) def note(text): date = datetime.datetime.now() file_name = str(date).replace(":", "-") + "-note.txt" with open(file_name, "w") as f: f.write(text) subprocess.Popen(["notepad.exe", file_name]) SERVICE = authenticate_google() print("Start") text = get_audio().lower() CALENDAR_STRS = ["what do i have", "do i have plans", "am i busy"] for phrase in CALENDAR_STRS: if phrase in text: date = get_date(text) if date: get_events(date, SERVICE) else: speak("I didn't quite get that") NOTE_STRS = ["make a note", "write this down", "remember this", "type this"] for phrase in NOTE_STRS: if phrase in text: speak("What would you like me to write down? ") write_down = get_audio() note(write_down) speak("I've made a note of that.")