diff --git a/Jarvis/GUI_commands.py b/Jarvis/GUI_commands.py new file mode 100644 index 0000000..c6192c5 --- /dev/null +++ b/Jarvis/GUI_commands.py @@ -0,0 +1,24 @@ +import customtkinter as ctk +import jarvis_GUI +from jarvis_actions import speak +from listen import listen +#import jarvis + + +#change between light mode and dark mode +def change_appearence_mode(new_mode): + ctk.set_appearance_mode(new_mode) + + +#listen for user input (male) +def jarvis_button_click_male(): + print("Listening") + speak("Listening", 'M') + listen('M') + + +#listen for user input (female) +def jarvis_button_click_female(): + print("Listening") + speak("Listening", 'F') + listen('F') diff --git a/Jarvis/__pycache__/GUI_commands.cpython-312.pyc b/Jarvis/__pycache__/GUI_commands.cpython-312.pyc new file mode 100644 index 0000000..f6e686d Binary files /dev/null and b/Jarvis/__pycache__/GUI_commands.cpython-312.pyc differ diff --git a/Jarvis/__pycache__/evaluate_query.cpython-312.pyc b/Jarvis/__pycache__/evaluate_query.cpython-312.pyc new file mode 100644 index 0000000..95f9ceb Binary files /dev/null and b/Jarvis/__pycache__/evaluate_query.cpython-312.pyc differ diff --git a/Jarvis/__pycache__/jarvis.cpython-312.pyc b/Jarvis/__pycache__/jarvis.cpython-312.pyc new file mode 100644 index 0000000..3dcc3e6 Binary files /dev/null and b/Jarvis/__pycache__/jarvis.cpython-312.pyc differ diff --git a/Jarvis/__pycache__/jarvis_GUI.cpython-312.pyc b/Jarvis/__pycache__/jarvis_GUI.cpython-312.pyc new file mode 100644 index 0000000..7984254 Binary files /dev/null and b/Jarvis/__pycache__/jarvis_GUI.cpython-312.pyc differ diff --git a/Jarvis/__pycache__/jarvis_actions.cpython-312.pyc b/Jarvis/__pycache__/jarvis_actions.cpython-312.pyc new file mode 100644 index 0000000..b266c01 Binary files /dev/null and b/Jarvis/__pycache__/jarvis_actions.cpython-312.pyc differ diff --git a/Jarvis/__pycache__/jarvis_gender_class.cpython-312.pyc b/Jarvis/__pycache__/jarvis_gender_class.cpython-312.pyc new file mode 100644 index 0000000..94540a1 Binary files /dev/null and b/Jarvis/__pycache__/jarvis_gender_class.cpython-312.pyc differ diff --git a/Jarvis/__pycache__/jarvis_news.cpython-312.pyc b/Jarvis/__pycache__/jarvis_news.cpython-312.pyc new file mode 100644 index 0000000..f7e19b5 Binary files /dev/null and b/Jarvis/__pycache__/jarvis_news.cpython-312.pyc differ diff --git a/Jarvis/__pycache__/listen.cpython-312.pyc b/Jarvis/__pycache__/listen.cpython-312.pyc new file mode 100644 index 0000000..d4b4361 Binary files /dev/null and b/Jarvis/__pycache__/listen.cpython-312.pyc differ diff --git a/Jarvis/evaluate_query.py b/Jarvis/evaluate_query.py new file mode 100644 index 0000000..44fea32 --- /dev/null +++ b/Jarvis/evaluate_query.py @@ -0,0 +1,176 @@ +#import dependencies +import pyttsx3 +import pywin32_system32 +import datetime +import speech_recognition as sr +import wikipedia +import webbrowser as wb +import os +import random +import pyautogui + +#import jarvis actions +from jarvis_actions import speak +from jarvis_actions import time +from jarvis_actions import date +from jarvis_actions import wishme +from jarvis_actions import screenshot +from jarvis_actions import takecommand + +#import newsreader +from jarvis_news import read_headlines + +#import email function +from jarvis_email import scan_inbox + +#import spotify functionality +from jarvis_spotify import play_song + + +#####################-functions-##################### +def evaluate_query(query, gender): + print(query) + #if the user mentions the time, report what time it is + if "time" in query: + time() + + #if the user mentions the date, report what the date is + elif "date" in query: + date() + + #if the user asks for information about the personal assistant, it is provided + elif "who are you" in query: + speak("I'm JARVIS created by Mr. Kishan and I'm a desktop voice assistant.", gender) + print("I'm JARVIS created by Mr. Kishan and I'm a desktop voice assistant.") + + #if the user asks the assistant how they are, an appropriate response is given + elif "how are you" in query: + speak("I'm fine sir, What about you?", gender) + print("I'm fine sir, What about you?") + + #if the user says that they are fine, then an appropriate response is given + elif "fine" in query: + speak("Glad to hear that sir!!", gender) + print("Glad to hear that sir!!") + + #if the user says that they are good, an appropriate response is given + elif "good" in query: + speak("Glad to hear that sir!!", gender) + print("Glad to hear that sir!!") + + #if the user wishes to recieve a wikipedia summary + elif "wikipedia" in query: + try: + #feedback to let the user know that the assistant is working on it + speak("Ok wait sir, I'm searching...", gender) + + #remove the word wikipedia from the query and produce a result + query = query.replace("wikipedia", "") + result = wikipedia.summary(query, sentences=2) + + #output result + print(result) + speak(result, gender) + except: + #if unsuccessful, inform the user + speak("Can't find this page sir, please ask something else", gender) + + #open youtube.com in default browser + elif "open youtube" in query: + wb.open("youtube.com") + + #open google.com in default browser + elif "open google" in query: + wb.open("google.com") + + #open stack overflow in default browser + elif "open stack overflow" in query: + wb.open("stackoverflow.com") + + #play music from a playlist + elif "play music" in query: + song_dir = os.path.expanduser("~\\Music") + songs = os.listdir(song_dir) + print(songs) + x = len(songs) + y = random.randint(0, x) + os.startfile(os.path.join(song_dir, songs[y])) + + #open the chrome app + elif "open chrome" in query: + #FileNotFoundError causes termination - that is not where chrome is stored on my computer + try: + chromePath = "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe" + os.startfile(chromePath) + + #FileNotFoundError - cannot find chrome in specified location + except FileNotFoundError: + speak("Could not find Chrome on your computer", gender) + print("Could not find Chrome on your computer") + + #open a chrome tab with a google search + elif "search on chrome" in query: + try: + speak("What should I search?") + print("What should I search?") + chromePath = "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe" + search = takecommand() + wb.get(chromePath).open_new_tab(search) + print(search) + + ##FileNotFoundError - cannot find chrome in specified location + except FileNotFoundError: + speak("Could not find Chrome on your computer", gender) + print("Could not find Chrome on your computer") + + except Exception as e: + speak("Can't open now, please try again later.", gender) + print("Can't open now, please try again later.") + + #transcribe a note + elif "remember that" in query: + speak("What should I remember", gender) + data = takecommand() + speak("You said me to remember that" + data, gender) + print("You said me to remember that " + str(data)) + remember = open("data.txt", "w") + remember.write(data) + remember.close() + + #read out transcribed notes + elif "do you remember anything" in query: + remember = open("data.txt", "r") + speak("You told me to remember that" + remember.read(), gender) + print("You told me to remember that " + str(remember)) + + #perform a screesnhsot + elif "screenshot" in query: + screenshot() + speak("I've taken screenshot, please check it", gender) + + #read headlines + elif "headline" in query: + read_headlines(gender) + + elif "headline" not in query: + if "news" in query: + read_headlines(gender) + + #read emails + elif "email" in query: + scan_inbox(gender) + + #play song on spotify + elif "spotify" in query: + print("What song would you like to play?") + speak("What song would you like to play?", gender) + + song = takecommand() + print("Playing", song) + speak(f"Playing {song}", gender) + + play_song(song) + + #end the program + elif "offline" in query: + quit() diff --git a/Jarvis/jarvis.py b/Jarvis/jarvis.py index 4b4ff02..f62a718 100644 --- a/Jarvis/jarvis.py +++ b/Jarvis/jarvis.py @@ -1,175 +1,15 @@ -import pyttsx3 -import pywin32_system32 -import datetime -import speech_recognition as sr -import wikipedia -import webbrowser as wb -import os -import random -import pyautogui +#import jarvis wishme action +from jarvis_actions import wishme -engine = pyttsx3.init() - - -def speak(audio): - engine.say(audio) - engine.runAndWait() - - -def time(): - Time = datetime.datetime.now().strftime("%I:%M:%S") - speak("the current time is") - speak(Time) - print("The current time is ", Time) - - -def date(): - day = int(datetime.datetime.now().day) - month = int(datetime.datetime.now().month) - year = int(datetime.datetime.now().year) - speak("the current date is") - speak(day) - speak(month) - speak(year) - print("The current date is " + str(day) + "/" + str(month) + "/" + str(year)) - - -def wishme(): - print("Welcome back sir!!") - speak("Welcome back sir!!") - - hour = datetime.datetime.now().hour - if 4 <= hour < 12: - speak("Good Morning Sir!!") - print("Good Morning Sir!!") - elif 12 <= hour < 16: - speak("Good Afternoon Sir!!") - print("Good Afternoon Sir!!") - elif 16 <= hour < 24: - speak("Good Evening Sir!!") - print("Good Evening Sir!!") - else: - speak("Good Night Sir, See You Tommorrow") - - speak("Jarvis at your service sir, please tell me how may I help you.") - print("Jarvis at your service sir, please tell me how may I help you.") - - -def screenshot(): - img = pyautogui.screenshot() - img_path = os.path.expanduser("~\\Pictures\\ss.png") - img.save(img_path) - - -def takecommand(): - r = sr.Recognizer() - with sr.Microphone() as source: - print("Listening...") - r.pause_threshold = 1 - audio = r.listen(source) - - try: - print("Recognizing...") - query = r.recognize_google(audio, language="en-in") - print(query) - - except Exception as e: - print(e) - speak("Please say that again") - return "Try Again" - - return query +#import jarvis gui +import jarvis_GUI +#start program if __name__ == "__main__": - wishme() - while True: - query = takecommand().lower() - if "time" in query: - time() - - elif "date" in query: - date() - - elif "who are you" in query: - speak("I'm JARVIS created by Mr. Kishan and I'm a desktop voice assistant.") - print("I'm JARVIS created by Mr. Kishan and I'm a desktop voice assistant.") - - elif "how are you" in query: - speak("I'm fine sir, What about you?") - print("I'm fine sir, What about you?") - - elif "fine" in query: - speak("Glad to hear that sir!!") - print("Glad to hear that sir!!") - - elif "good" in query: - speak("Glad to hear that sir!!") - print("Glad to hear that sir!!") - - elif "wikipedia" in query: - try: - speak("Ok wait sir, I'm searching...") - query = query.replace("wikipedia", "") - result = wikipedia.summary(query, sentences=2) - print(result) - speak(result) - except: - speak("Can't find this page sir, please ask something else") - - elif "open youtube" in query: - wb.open("youtube.com") - - elif "open google" in query: - wb.open("google.com") - - elif "open stack overflow" in query: - wb.open("stackoverflow.com") - - elif "play music" in query: - song_dir = os.path.expanduser("~\\Music") - songs = os.listdir(song_dir) - print(songs) - x = len(songs) - y = random.randint(0, x) - os.startfile(os.path.join(song_dir, songs[y])) - - elif "open chrome" in query: - chromePath = "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe" - os.startfile(chromePath) - - elif "search on chrome" in query: - try: - speak("What should I search?") - print("What should I search?") - chromePath = "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe" - search = takecommand() - wb.get(chromePath).open_new_tab(search) - print(search) - - except Exception as e: - speak("Can't open now, please try again later.") - print("Can't open now, please try again later.") - - - elif "remember that" in query: - speak("What should I remember") - data = takecommand() - speak("You said me to remember that" + data) - print("You said me to remember that " + str(data)) - remember = open("data.txt", "w") - remember.write(data) - remember.close() - - elif "do you remember anything" in query: - remember = open("data.txt", "r") - speak("You told me to remember that" + remember.read()) - print("You told me to remember that " + str(remember)) - - elif "screenshot" in query: - screenshot() - speak("I've taken screenshot, please check it") - + #greet user + #wishme() - elif "offline" in query: - quit() + #instantiate and launch gui window + app = jarvis_GUI.App() + app.mainloop() diff --git a/Jarvis/jarvis_GUI.py b/Jarvis/jarvis_GUI.py new file mode 100644 index 0000000..54556b2 --- /dev/null +++ b/Jarvis/jarvis_GUI.py @@ -0,0 +1,50 @@ +#import dependencies +import customtkinter as ctk + +#import gui commands +#from GUI_commands import change_appearence_mode +#from GUI_commands import jarvis_button_click +#from GUI_commands import get_current_gender +import GUI_commands +change_appearence_mode = GUI_commands.change_appearence_mode +jarvis_button_click_male = GUI_commands.jarvis_button_click_male +jarvis_button_click_female = GUI_commands.jarvis_button_click_female + +#set default settings - dark theme with blue colour theme +ctk.set_appearance_mode("dark") +ctk.set_default_color_theme("blue") + +#create app class +class App(ctk.CTk): + def __init__(self): + super().__init__() + + #create window + #app = ctk.CTk() + self.geometry("500x200") + self.title("Jarvis") + + #create sidebar frame to hold settings + self.sidebar_frame = ctk.CTkFrame(self, width=160, corner_radius=0) + self.sidebar_frame.grid(row=0, column=0, sticky='nsew') + + #create main frame to hold jarvis button + self.main_frame = ctk.CTkFrame(self, width=270) + self.main_frame.grid(row=0, column=1, padx=37) + + #add settings label in sidebar + self.settings_label = ctk.CTkLabel(self.sidebar_frame, text="Settings", font= ctk.CTkFont(size=18)) + self.settings_label.place(x=43, y=10) + + #add light/dark mode dropdown menu with label + self.mode_menu_label = ctk.CTkLabel(self.sidebar_frame, text='Appearence Mode') + self.mode_menu_label.place(x=23, y=115) + self.mode_menu = ctk.CTkOptionMenu(self.sidebar_frame, values=['Dark', 'Light'], command=change_appearence_mode) + self.mode_menu.place(x=10, y=150) + + #add main buttons + self.main_button_male = ctk.CTkButton(self.main_frame, text='Jarvis\n(Male)', height=40, width=100, command=jarvis_button_click_male) + self.main_button_male.place(x=25, y=62.5) + + self.main_button_female = ctk.CTkButton(self.main_frame, text='Jarvis\n(Female)', height=40, width=100, command=jarvis_button_click_female) + self.main_button_female.place(x=150, y=62.5) diff --git a/Jarvis/jarvis_actions.py b/Jarvis/jarvis_actions.py new file mode 100644 index 0000000..c23865e --- /dev/null +++ b/Jarvis/jarvis_actions.py @@ -0,0 +1,95 @@ +#install dependencies +import pyttsx3 +import pywin32_system32 +import datetime +import speech_recognition as sr +import wikipedia +import webbrowser as wb +import os +import random +import pyautogui + + +#instantiate python text to speech engine +engine = pyttsx3.init() + +#######################functions######################## +#text to speach +def speak(audio, gender): + #adjust engine based on provided gender + voices = engine.getProperty('voices') + if gender == 'M': + engine.setProperty('voice', voices[0].id) + if gender == 'F': + engine.setProperty('voice', voices[1].id) + + engine.say(audio) + engine.runAndWait() + + +#read the time +def time(): + Time = datetime.datetime.now().strftime("%I:%M:%S") + speak("the current time is", '') + speak(Time) + print("The current time is ", Time) + + +#say the date +def date(): + day = int(datetime.datetime.now().day) + month = int(datetime.datetime.now().month) + year = int(datetime.datetime.now().year) + speak("the current date is", '') + speak(day) + speak(month) + speak(year) + print("The current date is " + str(day) + "/" + str(month) + "/" + str(year)) + + +#greet the user +def wishme(): + print("Welcome back sir!!") + speak("Welcome back sir!!", '') + + hour = datetime.datetime.now().hour + if 4 <= hour < 12: + speak("Good Morning Sir!!", '') + print("Good Morning Sir!!") + elif 12 <= hour < 16: + speak("Good Afternoon Sir!!", '') + print("Good Afternoon Sir!!") + elif 16 <= hour < 24: + speak("Good Evening Sir!!", '') + print("Good Evening Sir!!") + else: + speak("Good Night Sir, See You Tommorrow", '') + + speak("Jarvis at your service sir, please tell me how may I help you.", '') + print("Jarvis at your service sir, please tell me how may I help you.") + +#take a screenshot +def screenshot(): + img = pyautogui.screenshot() + img_path = os.path.expanduser("~\\Pictures\\ss.png") + img.save(img_path) + + +#receive input +def takecommand(): + r = sr.Recognizer() + with sr.Microphone() as source: + r.pause_threshold = 1 + audio = r.listen(source) + + try: + print("Recognizing...") + query = r.recognize_google(audio, language="en-in") + print(query) + + except Exception as e: + print(e) + speak("Please say that again", '') + return "Try Again" + + return query diff --git a/Jarvis/jarvis_email.py b/Jarvis/jarvis_email.py new file mode 100644 index 0000000..2d16c98 --- /dev/null +++ b/Jarvis/jarvis_email.py @@ -0,0 +1,56 @@ +import win32com.client +from datetime import date +from jarvis_actions import speak + + +#function to read today's unread emails +def read_emails(email_list, num_of_emails, gender): + #announce total number of unread emails + print("You have", num_of_emails, "unread emails") + speak("You have", num_of_emails, "unread emails", gender) + + #if there are no emails from today, then tell the user + if len(email_list) == 0: + print("No emails today") + speak("No emails today", gender) + + else: + for email in email_list: + print(email.subject) + speak(email.subject, gender) + + +#function to scan inbox for emails to read +def scan_inbox(gender): + #interact with Outlook inbox + outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI") + inbox = outlook.GetDefaultFolder(6) + + #get all unread emails + emails = inbox.Items + unread_emails = [] + for e in emails: + if e.unread: + unread_emails.append(e) + + total_unread_emails = len(unread_emails) + + #today's date to compare to email sent date + today = date.today() + todays_year = today.strftime('%Y') + todays_month = today.strftime('%m') + todays_day = today.strftime('%d') + + emails_to_read = [] + #if email was sent today, read + for ue in unread_emails: + email_year = ue.ReceivedTime.year + email_month = ue.ReceivedTime.month + email_day = ue.ReceivedTime.day + + if todays_year == email_year: + if todays_month == email_month: + if todays_day == email_day: + emails_to_read.append(ue) + + read_emails(total_unread_emails, emails_to_read, gender) diff --git a/Jarvis/jarvis_news.py b/Jarvis/jarvis_news.py new file mode 100644 index 0000000..37b556a --- /dev/null +++ b/Jarvis/jarvis_news.py @@ -0,0 +1,21 @@ +#import dependencies +import feedparser + +#import speak function +from jarvis_actions import speak + + +def read_headlines(gender): + #parse news feed + news_feed = feedparser.parse("https://feeds.bbci.co.uk/news/rss.xml?edition=uk") + entries = news_feed.entries + + #output top ten articles + articles = [] + count = 0 + while count < 10: + articles.append(entries[count]) + speak(articles[count].title, gender) + print(articles[count].title,":") + print(articles[count].link) + count += 1 diff --git a/Jarvis/jarvis_spotify.py b/Jarvis/jarvis_spotify.py new file mode 100644 index 0000000..f2b0eaa --- /dev/null +++ b/Jarvis/jarvis_spotify.py @@ -0,0 +1,24 @@ +import spotipy +import webbrowser + + +def play_song(track): + #user will have to input their own details here + username = '' + client_Id = '' + secret = '' + redirect = "http://google.com/callback/" + + #login to spotify using provided details + oauth = spotipy.SpotifyOAuth(client_Id, secret, redirect) + token_dict = oauth.get_access_token() + token = token_dict['access_token'] + spotify = spotipy.Spotify(auth=token) + username = spotify.current_user() + + #find top result from search request and play song + results = spotify.search(track, 1, 0, 'track') + song_dict = results['tracks'] + song_items = song_dict['items'] + song = song_items[0]['external_urls']['spotify'] + webbrowser.open(song) diff --git a/Jarvis/listen.py b/Jarvis/listen.py new file mode 100644 index 0000000..3fd98f3 --- /dev/null +++ b/Jarvis/listen.py @@ -0,0 +1,9 @@ +#import necessary functions +from jarvis_actions import takecommand +from evaluate_query import evaluate_query + + +#listen to user input and process query +def listen(gender): + query = takecommand().lower() + evaluate_query(query, gender) diff --git a/data.txt b/data.txt new file mode 100644 index 0000000..e69de29