├── tzara ├── __init__.py ├── reminder.dat ├── bye.dat ├── confirmations.dat ├── comn_sites.dat ├── check_email.sh ├── confirm.py ├── songs.py ├── pdf.py ├── terminal.py ├── playmovie.py ├── Speech.py ├── files.py ├── database.py ├── converse.py ├── reminder.py ├── main.py ├── firefox.py └── tzara.py ├── requirements.txt ├── setup.py ├── bin └── startup.sh └── README.md /tzara/__init__.py: -------------------------------------------------------------------------------- 1 | from .main import main 2 | -------------------------------------------------------------------------------- /tzara/reminder.dat: -------------------------------------------------------------------------------- 1 | 12/12/2222 - This is the format of a reminder. 2 | -------------------------------------------------------------------------------- /tzara/bye.dat: -------------------------------------------------------------------------------- 1 | bye 2 | cya 3 | by 4 | bi 5 | bye 6 | g'bye 7 | adios 8 | aurevoir 9 | gudbye 10 | gudbi 11 | goodbye 12 | cya later 13 | tata 14 | -------------------------------------------------------------------------------- /tzara/confirmations.dat: -------------------------------------------------------------------------------- 1 | yes 2 | yay 3 | sure 4 | y 5 | ya 6 | ye 7 | ok 8 | k 9 | yup 10 | cool 11 | ay 12 | aye 13 | go ahead 14 | absolutely 15 | fine 16 | -------------------------------------------------------------------------------- /tzara/comn_sites.dat: -------------------------------------------------------------------------------- 1 | gmail-www.gmail.com 2 | facebook-www.facebook.com 3 | twitter-www.twitter.com 4 | ai-www.psychedai.wordpress.com 5 | google-www.google.co.in 6 | quora-www.quora.com 7 | linkedin-www.linkedin.com 8 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | mpg123==1.16.0 2 | nltk==3.0.0 3 | gtts==1.1.6 4 | firefox==51.0.1 5 | audacious==3.4.3 6 | xdotool==3.20140217.1 7 | wmctrol==1.07 8 | guake==0.4.4 9 | xdg-utils==1.1.0~rc1-2ubuntu7-1linuxm all 10 | -------------------------------------------------------------------------------- /tzara/check_email.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | username = "your_email_here" 4 | password = "your_password_here" 5 | echo 6 | curl -u $username:$password --silent "https://mail.google.com/mail/feed/atom" > /path/to/the/file/inbox_details.txt 7 | -------------------------------------------------------------------------------- /tzara/confirm.py: -------------------------------------------------------------------------------- 1 | """ 2 | Gets confirmation. 3 | 4 | """ 5 | import os 6 | 7 | def confirm(reply): 8 | """ 9 | Checks if reply is in confirmation list. 10 | If yes, success. 11 | Else, failure. 12 | """ 13 | f_ok = open(os.getcwd() + "/Text_Files/confirmations.txt", "r") 14 | confirmation_list = f_ok.read().strip().split() 15 | f_ok.close() 16 | return reply.lower() in confirmation_list 17 | -------------------------------------------------------------------------------- /tzara/songs.py: -------------------------------------------------------------------------------- 1 | """ 2 | Plays a song. 3 | """ 4 | from Speech import speak 5 | import os 6 | 7 | def fn_play_song(name): 8 | """ 9 | Plays the given song with Audacious 10 | """ 11 | os.system('find -iname "*'+name+'*"' 12 | '-exec audacious {} + &disown\;') 13 | 14 | def fn_close_song(): 15 | """ 16 | Kills Audacious. 17 | """ 18 | os.system("killall audacious") 19 | speak("Song stopped.") 20 | -------------------------------------------------------------------------------- /tzara/pdf.py: -------------------------------------------------------------------------------- 1 | """ 2 | Opens pdf given filename. 3 | """ 4 | from Speech import speak 5 | import os 6 | 7 | def fn_open_pdf(name): 8 | """ 9 | Opens the pdf using evince. 10 | """ 11 | os.system('find -iname "*' + name + 12 | '*.pdf" -exec evince {} + &disown\;') 13 | speak("There you go! Enjoy reading!") 14 | 15 | def fn_close_pdf(): 16 | """ 17 | Kills evince. 18 | """ 19 | speak("Closing PDF.") 20 | os.system("killall evince") 21 | -------------------------------------------------------------------------------- /tzara/terminal.py: -------------------------------------------------------------------------------- 1 | """ 2 | Opens the terminal. 3 | """ 4 | import os 5 | from Speech import speak 6 | 7 | def terminal(): 8 | """ 9 | Opens the terminal. 10 | """ 11 | speak("You are into the terminal now." 12 | "Type 'exit' when you want to quit.") 13 | while True: 14 | command = raw_input('\033[1m' + 'Username: ' + '\033[0m') #modify 15 | if command.lower() == "exit": 16 | speak("Quit terminal.") 17 | return 18 | else: 19 | os.system(command) 20 | -------------------------------------------------------------------------------- /tzara/playmovie.py: -------------------------------------------------------------------------------- 1 | """ 2 | Plays a movie 3 | """ 4 | from Speech import speak 5 | import os 6 | 7 | def fn_movie(name): 8 | """ 9 | Searches for the movie name in 2 paths. 10 | 11 | If movie is found, plays with vlc. 12 | """ 13 | path_list = ["/path1/", "/path2" 14 | "/path3/"] #modify 15 | for path in path_list: 16 | os.system('find '+ path + ' -iname "*' + name + '*"' 17 | ' -exec vlc --fullscreen {} + & >/dev/null;') 18 | os.system("clear") 19 | speak("Hope you enjoy the movie!!!") 20 | os.system("clear") 21 | 22 | def fn_close_movie(): 23 | """ 24 | Kills vlc 25 | """ 26 | os.system("killall vlc") 27 | speak("Job's done.") 28 | 29 | -------------------------------------------------------------------------------- /tzara/Speech.py: -------------------------------------------------------------------------------- 1 | """ 2 | Speaks input string using the internet. 3 | """ 4 | from gtts import gTTS 5 | import os 6 | 7 | def speak(out_string): 8 | """ 9 | Speaks using gTTs from the internet. 10 | """ 11 | path = os.getcwd() + "/Text_Files/ping_result.txt" 12 | path_os = path.replace(" ", "\ ") 13 | path_os = path_os.replace("(", "\(") 14 | path_os = path_os.replace(")", "\)") 15 | os.system("if ! ping -c 1 www.google.com>/dev/null;" 16 | "then echo fail >"+ path_os +";" 17 | "else echo success>"+ path_os + ";fi;") 18 | f_ping = open(path) 19 | result = f_ping.read().strip().split("\n") 20 | f_ping.close() 21 | print '\033[1m' + 'Tzara: ' + '\033[0m' + out_string 22 | if result[0] == 'success': 23 | tts = gTTS(text = out_string, lang = 'en') 24 | tts.save("hello.mp3") 25 | os.system("mpg321 -q hello.mp3") 26 | -------------------------------------------------------------------------------- /tzara/files.py: -------------------------------------------------------------------------------- 1 | """ 2 | Opens folders 3 | 4 | """ 5 | 6 | import os 7 | from Speech import speak 8 | 9 | def open_folder(name): 10 | """ 11 | Checks if a folder with the given name exists in directory. 12 | If yes, opens it. 13 | """ 14 | name = name.strip() 15 | #os.system("find -type d -iname '*"+name +"*' -exec xdg-open ") 16 | counter = 0 17 | path_1 = os.getcwd() + "/Text_Files/folder.txt" 18 | f_fldr = open(path_1, "r") 19 | for line in f_fldr: 20 | name_list = line.strip().split("-") 21 | if name.lower() == ''.join(name_list[0:1]).lower(): 22 | counter = 1 23 | path = ''.join(name_list[1:2]) 24 | os.system('xdg-open ' + path) 25 | speak("Opened the requested folder.") 26 | break 27 | f_fldr.close() 28 | if counter == 0: 29 | speak("Sorry, but I could not find the folder.") 30 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | from setuptools.command.install import install 3 | import os 4 | 5 | class MyInstall(install): 6 | def run(self): 7 | install.run(self) 8 | path = os.getcwd().replace(" ", "\ ").replace("(","\(").replace(")","\)") + "/bin/" 9 | os.system("chmod +x "+path+"startup.sh") 10 | os.system("sh "+path+"startup.sh") 11 | 12 | 13 | setup(name='Tzara---A-Personal-Assistant', 14 | version='1.1.5', 15 | description='A Virtual Personal Assistant', 16 | url='https://github.com/Suman7495/Tzara---A-Personal-Assistant', 17 | author='Suman Pal', 18 | author_email='suman7495@gmail.com', 19 | license='MIT', 20 | packages=['tzara'], 21 | classifiers=['Development Status :: 4 - Beta', 22 | 'Programming Language :: Python :: 2.7', 23 | ], 24 | scripts=['bin/startup.sh'], 25 | cmdclass={'install': MyInstall}, 26 | ) 27 | 28 | -------------------------------------------------------------------------------- /tzara/database.py: -------------------------------------------------------------------------------- 1 | """ 2 | Creates database to generate sentences. 3 | 4 | """ 5 | import os 6 | from Speech import speak 7 | def database(): 8 | path = os.getcwd() + "/Text_Files/corpora.txt" 9 | f_corpora = open(path,"r") 10 | data = [] 11 | nltk_info_path = os.getcwd() + "/Text_Files/nltk_data_path.txt" 12 | nltk_info_path_os = nltk_info_path.replace(" ","\ ") 13 | nltk_info_path_os = nltk_info_path_os.replace("(", "\(") 14 | nltk_info_path_os = nltk_info_path_os.replace(")", "\)") 15 | if os.path.isfile(nltk_info_path_os) == False: #Checks if nltk_data_path.txt exists. 16 | f_nltk = open (nltk_info_path, "w") 17 | os.system('find / -iname "nltk_data" 2>/dev/null>'+ nltk_info_path_os) 18 | if os.stat(nltk_info_path).st_size == 0: 19 | speak("Please install NTLK. I can't run until then. Goodbye.") 20 | else: 21 | f_nltk.close() 22 | 23 | f_nltk = open (os.getcwd() + "/Text_Files/nltk_data_path.txt", "r") 24 | nltk_data_path = f_nltk.readline().strip() 25 | f_nltk.close() 26 | 27 | for name in f_corpora: 28 | f = open( nltk_data_path + "/corpora/gutenberg/" + name.strip()) 29 | f.seek(0) 30 | data_temp = f.read() 31 | data = data + data_temp.split() 32 | del data_temp 33 | 34 | f_corpora.close() 35 | f.close() 36 | return data 37 | -------------------------------------------------------------------------------- /bin/startup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Initialising setup..." 3 | sudo apt-get update 4 | sudo apt-get upgrade 5 | echo "Installing pip..." 6 | sudo apt-get install python-pip 7 | 8 | echo "Installing gTTS..." 9 | sudo pip install gTTS 10 | 11 | echo "Installing mpg123..." 12 | sudo apt-get install mpg123 13 | 14 | echo "Installing NLTK. This may take a few hours..." 15 | sudo pip install -U nltk 16 | 17 | echo "Installing Firefox Browser..." 18 | sudo apt-get install firefox 19 | 20 | echo "Installing Audacious Music Player..." 21 | sudo apt-get install audacious 22 | 23 | echo "Installing xdotool..." 24 | sudo apt-get install xdotool 25 | 26 | echo "Installing wmctrl..." 27 | sudo apt-get install wmctrl 28 | 29 | echo "Installing Guake Dropdown Terminal..." 30 | sudo apt-get install guake 31 | 32 | echo "Installing xdg-utils..." 33 | sudo apt-get install xdg-utils 34 | 35 | echo "Setting up .desktop file" 36 | 37 | STR="[Desktop Entry] 38 | Encoding=UTF-8 39 | Type=Application 40 | Name=Tzara\n 41 | Comment=A Virtual Personal Assistant 42 | Exec=guake -n guake -t -e 'python /usr/local/lib/python2.7/dist-packages/tzara/main.pyc' guake -r 'Tzara' 43 | Terminal=True 44 | Type=Application 45 | Categories=Application; " 46 | if [ ! -e /usr/share/applications/Tzara.desktop ]; then 47 | echo "Setting up .desktop file" 48 | echo "${STR}" | sudo tee sudo /usr/share/applications/Tzara.desktop > /dev/null 49 | read -n1 -r -p "Press any key to continue..." key 50 | fi 51 | -------------------------------------------------------------------------------- /tzara/converse.py: -------------------------------------------------------------------------------- 1 | """ 2 | Converses using Markov Model 3 | 4 | """ 5 | import nltk 6 | from database import database 7 | import os 8 | 9 | """ 10 | Creates database. 11 | Collects data from Brown Corpus in the NLTK package. 12 | """ 13 | 14 | data = database() 15 | f = open(os.getcwd() + "/Text_Files/data.txt", "w") 16 | for word in data: 17 | f.write(word + " ") 18 | f.close() 19 | del f 20 | 21 | """ 22 | Generates a word given a seed word by using the Markov model 23 | """ 24 | def Markov_generate_unigram(seed): 25 | seed = ''.join(seed) 26 | counter = 1 27 | next_word_list = [] 28 | for i in data: 29 | if seed == i: 30 | next_word_list.append(data[counter]) 31 | counter += 1 32 | if len(next_word_list) == 0: 33 | return nltk.bigrams(["you", "are"]) 34 | cfdist = nltk.FreqDist(next_word_list) 35 | next_word = cfdist.max() 36 | return nltk.bigrams([seed, next_word]) 37 | 38 | """ 39 | Generates bigrams using the Markov process 40 | """ 41 | def Markov_generate_bigrams(tuples): 42 | counter = 1 43 | index_list = [] 44 | data_bigrams = nltk.bigrams(data) 45 | for i in data_bigrams: 46 | if tuples == i: 47 | index_list.append(data[counter+1]) 48 | counter += 1 49 | return index_list 50 | 51 | """ 52 | Receives a sentence. 53 | Returns another one, which was generated by the Markov process. 54 | """ 55 | def converse(raw_sentence): 56 | words_in_sent = raw_sentence.split() 57 | if len(words_in_sent) > 1: 58 | bigrams = nltk.bigrams(words_in_sent) 59 | 60 | else: 61 | bigrams = Markov_generate_unigram(words_in_sent) 62 | 63 | text_len = 20 64 | generated_lines = [] 65 | 66 | for tuples in bigrams: 67 | line = [] 68 | line.append(''.join(tuples[0]).title()+" ") 69 | line.append(''.join(tuples[1])+" ") 70 | for i in range(text_len): 71 | next_words = Markov_generate_bigrams(tuples) 72 | if not next_words: 73 | break 74 | cfdist = nltk.FreqDist(next_words) 75 | next_word = cfdist.max() 76 | line.append(next_word+" ") 77 | new_tuple = (tuples[1], next_word) 78 | del tuples 79 | tuples = new_tuple 80 | 81 | generated_lines.append(line) 82 | 83 | longest_line = '' 84 | for line in generated_lines: 85 | 86 | stri = ''.join(line) 87 | if "." in stri: 88 | truncate_char = "." 89 | elif "?" in stri: 90 | truncate_char = "?" 91 | elif "!" in stri: 92 | truncate_char = "!" 93 | try: 94 | stri = stri[:stri.index(truncate_char)] 95 | except: 96 | pass 97 | if len(line) > len(longest_line): 98 | longest_line = stri.strip()+"." 99 | 100 | return longest_line 101 | -------------------------------------------------------------------------------- /tzara/reminder.py: -------------------------------------------------------------------------------- 1 | from Speech import speak 2 | """ 3 | A REMINDER. 4 | 5 | Functions: Set, Read, Delete. 6 | Possible amelioration: 7 | 1. GUI 8 | 2. In delete function, deletes ALL reminders of a given date without asking. 9 | 10 | """ 11 | import os 12 | 13 | def reminder (): 14 | """ 15 | Initialises the reminder. 16 | """ 17 | speak("You want to: set a new reminder, read reminder, or delete reminder? Type 'q' to quit.") 18 | speak("Input Set or Read or Delete or q.") 19 | inpt = (raw_input('\033[1m'+'Username: '+'\033[0m')).lower() #modify 20 | 21 | while verify_input(INPUT) == False: 22 | speak("Input Set or Read or Delete or q.") 23 | inpt = raw_input('\033[1m'+'Username: '+'\033[0m').lower() #modify 24 | 25 | if inpt == "set": 26 | set_rm() 27 | elif inpt == 'read': 28 | read_rm() 29 | elif inpt == 'delete': 30 | delete_rm() 31 | else: return 32 | 33 | def delete_rm(): 34 | """ 35 | Deletes reminder. 36 | """ 37 | speak("Here are the reminders:") 38 | reminder_path = os.getcwd() + "/Text_Files/reminder.txt" 39 | f = open(reminder_path, "r+") 40 | data = [] 41 | for line in f: 42 | print line 43 | data.append(line) 44 | raw_input() 45 | speak('Please enter the date of the reminder in the following format: ') 46 | print "dd/mm/yyyy" 47 | reminder_date = raw_input('\033[1m'+'Username: '+'\033[0m') #modify 48 | while verify_date(reminder_date) == False: 49 | speak("Sorry, invalid input. Try again") 50 | reminder_date = raw_input('\033[1m' + 'Username: ' + '\033[0m') #modify 51 | 52 | new_data = [] 53 | for line in data: 54 | if reminder_date in line: 55 | continue 56 | new_data.append(line) 57 | f.seek(0) 58 | f.writelines([line for line in new_data]) 59 | f.truncate() 60 | f.close() 61 | 62 | 63 | def set_rm(): 64 | """ 65 | Sets reminder. 66 | """ 67 | speak("Please enter the date of the reminder in the following format: ") 68 | print "dd/mm/yyyy" 69 | reminder_date = raw_input('\033[1m'+'Username: '+'\033[0m') #modify 70 | 71 | while verify_date(reminder_date) == False: 72 | speak("Sorry, invalid input. Try again") 73 | reminder_date = raw_input('\033[1m'+'Username: '+'\033[0m') #modify 74 | speak("Now set the reminder.") 75 | reminder_text = raw_input('\033[1m'+'Username: '+'\033[0m') #modify 76 | reminder_path = os.getcwd() + "/Text_Files/reminder.txt" 77 | with open(reminder_path, "a") as f_reminder: 78 | f_reminder.write(reminder_date + " - " + reminder_text + "\n") 79 | f_reminder.close() 80 | 81 | speak("Reminder successfully set.") 82 | 83 | def read_rm(): 84 | """ 85 | Reads reminders. 86 | """ 87 | reminder_path = os.getcwd() + "/Text_Files/reminder.txt" 88 | f = open(reminder_path, "r") 89 | for line in f: 90 | print line 91 | f.close() 92 | 93 | def verify_input(input_str): 94 | """ 95 | Checks validity of string input. 96 | """ 97 | acceptable_input = ['set','read','delete','q'] 98 | return (input_str in acceptable_input) 99 | 100 | def verify_date(input_str): 101 | """ 102 | Checks validity of date. 103 | """ 104 | if len(input_str) != 10: 105 | return False 106 | if input_str[2] != "/" or input_str[5] != "/": 107 | return False 108 | checks = 0 109 | for i in xrange(1, 32): 110 | if i >= 10: 111 | if str(i) == input_str[:2]: 112 | checks = 1 113 | break 114 | else: 115 | if ('0'+str(i)) == input_str[:2]: 116 | checks = 1 117 | break 118 | 119 | if checks==0: 120 | return False 121 | 122 | for i in xrange(1, 13): 123 | if i>=10: 124 | if str(i) == input_str[3:5]: 125 | checks = 2 126 | break 127 | else: 128 | if ('0'+str(i)) == input_str[3:5]: 129 | checks = 2 130 | break 131 | 132 | if checks == 1: 133 | return False 134 | 135 | for i in xrange(2016, 3000): 136 | if str(i) == input_str[-4:]: 137 | checks = 3 138 | break 139 | if checks == 2: 140 | return False 141 | 142 | 143 | -------------------------------------------------------------------------------- /tzara/main.py: -------------------------------------------------------------------------------- 1 | """ 2 | Tzara - An Intelligent Personal Assistant. 3 | 4 | Main loop. 5 | """ 6 | import time 7 | from tzara import tzara 8 | from Speech import speak 9 | import os 10 | import random 11 | from datetime import datetime 12 | from confirm import confirm 13 | from firefox import ping 14 | 15 | def check_last_update(): 16 | """ 17 | Checks when the system was last updated. 18 | If the system was not updated for the last 2 days, updates system. 19 | """ 20 | update_path = os.getcwd() + "/Text_Files/prev_update.txt" 21 | f_update = open(update_path, 'r+') 22 | prev_date = f_update.read().strip().split("/") 23 | current_date = time.strftime("%d/%m/%Y") 24 | date = current_date.strip().split("/") 25 | if (int(date[0])-int(prev_date[0]) > 2) or \ 26 | (int(date[1])-int(prev_date[1]) > 0) or \ 27 | (int(date[2])-int(prev_date[2]) > 0): 28 | if ping() == 1: 29 | speak("Hey, I just realised that it's been a while that " \ 30 | "your system has been updated.") 31 | speak("Would you like to update system now?") 32 | reply = raw_input('\033[1m'+'Username: '+'\033[0m') #modify 33 | if confirm(reply) == 1: 34 | speak("Please input password to update system.") 35 | os.system("sudo apt-get update && apt-get upgrade") 36 | f_update.seek(0) 37 | f_update.write(current_date) 38 | f_update.truncate() 39 | speak("System successfully updated.") 40 | else: 41 | speak("It's been a while since your system has been updated. " \ 42 | "I can't update it now, since Internet is down.") 43 | f_update.close() 44 | 45 | def check_reminder(): 46 | """ 47 | Checks if you have any reminder set for today. 48 | """ 49 | current_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') 50 | c_year = current_date[0:4] 51 | c_month = current_date[5:7] 52 | c_date = current_date[8:10] 53 | to_del = '' 54 | reminder_path = os.getcwd() + "/Text_Files/reminder.txt" 55 | f_reminder = open(reminder_path, "r+") 56 | for line in f_reminder: 57 | r_date = line[0:2] 58 | if r_date == c_date: 59 | r_month = line[3:5] 60 | if r_month == c_month: 61 | r_year = line[6:10] 62 | if r_year == c_year: 63 | speak("You have a reminder set for today." \ 64 | "This is what it says: \n" + line[11:]) 65 | speak("Would you like me to delete the reminder now?") 66 | reply = raw_input('\033[1m'+'Username '+'\033[0m') #modify 67 | if confirm(reply) == 1: 68 | to_del = line 69 | #TO FINISH 70 | f_reminder.close() 71 | 72 | def main(): 73 | """ 74 | Greets the user. 75 | Checks when the system was last updated. 76 | Checks if there are reminders. 77 | Waits for user input. 78 | If input is "bye" (or similar), quits. 79 | Else passes the user input to the function tzara() stored in tzara.py 80 | """ 81 | greetings_path = os.getcwd() + "/Text_Files/greetings.txt" 82 | f_greetings = open(greetings_path, "r") 83 | greetings_list = f_greetings.read().strip().split("\n") 84 | f_greetings.close() 85 | random_greeting = random.randrange(0, len(greetings_list)) 86 | speak(greetings_list[random_greeting]) 87 | 88 | check_last_update() 89 | check_reminder() 90 | 91 | bye_path = os.getcwd() + "/Text_Files/bye.txt" 92 | f_bye = open(bye_path, "r") 93 | bye_list = f_bye.read().strip().split("\n") 94 | f_bye.close() 95 | bye_list2 = [''.join(bye_list[i])+" tzara" for i in range(0, len(bye_list))] 96 | bye_list3 = [''.join(bye_list[i])+" then" for i in range(0, len(bye_list))] 97 | while 1: 98 | input_string = raw_input('\033[1m'+'Username: '+'\033[0m') #modify 99 | if input_string: 100 | input_string = input_string.lower() 101 | if input_string in bye_list or \ 102 | input_string in bye_list2 or \ 103 | input_string in bye_list3: 104 | time_now = datetime.now().strftime('%Y-%m-%d %H:%M:%S') 105 | if int(time_now[11:13]) > 20 or int(time_now[11:13]) < 4: 106 | speak("Goodnight.") 107 | else: 108 | speak('See you later then! Have a good day!') 109 | return 110 | tzara(input_string) 111 | 112 | if __name__ == "__main__": 113 | main() 114 | -------------------------------------------------------------------------------- /tzara/firefox.py: -------------------------------------------------------------------------------- 1 | """ 2 | Several modules using firefox browser. 3 | 4 | Tasks: 5 | (1) Checks for an Internet connection. 6 | (2) Searches (Google) for a word. 7 | (3) Send emails. 8 | (4) Reads unread mails. 9 | (5) Opens any website. 10 | (6) Closes a tab. 11 | """ 12 | from Speech import speak 13 | from confirm import confirm 14 | import os 15 | 16 | def ping(): 17 | """ 18 | Checks for an Internet connection. 19 | If success, saves "success" in the file mentioned below. 20 | Else, saves "failure". 21 | """ 22 | path = os.getcwd() + "/Text_Files/ping_result.txt" 23 | path_os = path.replace(" ", "\ ") 24 | path_os = path_os.replace("(", "\(") 25 | path_os = path_os.replace(")", "\)") 26 | os.system('guake -n CUR_DIR -e "if ! ping -c 1 ' 27 | 'www.google.com &>/dev/null;' 28 | 'then echo fail >' + path_os + ';' 29 | 'else echo success>'+ path_os + ';fi;clear"') 30 | os.system("guake -s 1") 31 | os.system("guake -s 2 -e exit") 32 | 33 | f_ping = open(path) 34 | result = f_ping.read().strip().split("\n") 35 | result = ''.join(result) 36 | f_ping.close() 37 | if result == 'success': 38 | return 1 39 | else: 40 | speak("Sorry. Internet is down currently.") 41 | return 0 42 | 43 | def fn_search(word): 44 | """ 45 | Calls ping(). 46 | If success: 47 | Searches for the given sentence. 48 | """ 49 | 50 | if ping() == 0: 51 | return 52 | speak('Would you like me to search for "' + word + '"?') 53 | reply = raw_input('\033[1m' + 'Username: ' + '\033[0m') #modify: Change "Username" 54 | if confirm(reply) == 1: 55 | word = word.replace(" ", "+") 56 | search_link = "www.google.co.in/#q=" + word 57 | speak('Cool. Here are the results.') 58 | os.system('guake -n CUR_DIR -e "firefox "' + search_link + 59 | '" & >/dev/null"') 60 | os.system("guake -s 1") 61 | os.system("guake -s 2 -e exit") 62 | return 63 | else: 64 | speak("As you wish.") 65 | return 66 | 67 | def fn_close_tab(): 68 | """ 69 | Closes a firefox tab. 70 | """ 71 | speak('Do you want me to close the current tab?') 72 | reply = raw_input('\033[1m' + 'Username: ' + '\033[0m') #modify: Change "Username" 73 | if confirm(reply) == 1: 74 | os.system('wmctrl -a firefox; xdotool key Ctrl+w;') 75 | else: 76 | speak('Ok') 77 | return 78 | 79 | def fn_open_site(site): 80 | """ 81 | Opens a website on the firefox browswer. 82 | """ 83 | if ping() == 0: 84 | speak("Sorry. Internet is down currently.") 85 | return 86 | if site.endswith(".com") == True: 87 | os.system('guake -n CUR_DIR -e "firefox "'+ site + 88 | '" & >/dev/null"') 89 | speak("Please give me a while to complete the task.") 90 | os.system("guake -s 1") 91 | os.system("guake -s 2 -e exit") 92 | speak("Task successfully completed.") 93 | 94 | else: 95 | os.system('guake -n CUR_DIR -e "firefox "' + site + 96 | '".com & >/dev/null"') 97 | speak("Please give me a while.") 98 | os.system("guake -s 1") 99 | os.system("guake -s 2 -e exit") 100 | speak("Task successfully completed.") 101 | 102 | 103 | def fn_write_mail(name): 104 | """ 105 | If an Internet connection is there: 106 | Checks if the given name exists in directory. 107 | If it does, asks user to write the mail, then send. 108 | Else, asks for a valid email-id. Then asks the user to write. 109 | Else quits. 110 | """ 111 | if ping() == 0: 112 | speak("Sorry. The Internet is down currently.") 113 | return 114 | counter = 0 115 | email_path = os.getcwd() + "/Text_Files/email_id.txt" 116 | f_email = open(email_path) 117 | for line in f_email: 118 | print line 119 | name_list = line.strip().split("-") 120 | if name.lower() == ''.join(name_list[0:1]).lower(): 121 | counter = 1 122 | email_id = ''.join(name_list[1:2]) 123 | speak("Now write the mail. Press Control+D when you are done.") 124 | os.system('mail ' + email_id) 125 | speak("The mail has been sent.") 126 | break 127 | f_email.close() 128 | if counter == 0: 129 | speak("Sorry. The name doesn't exist in the directory." 130 | "You'll have to give me the person's email address" 131 | " for me to mail him. Would you like to do that?") 132 | reply = raw_input('\033[1m' + 'Username: ' + '\033[0m') #modify: Change "Username" 133 | if confirm(reply) == 1: 134 | speak("Ok. Now please enter a valid email address.") 135 | email_id = raw_input('\033[1m' + 'Username: ' + '\033[0m') #modify: Change "Username" 136 | speak("Now write the mail. " 137 | "Press Control+D when you are done.") 138 | os.system('mail ' + email_id) 139 | speak("The mail has been sent.") 140 | 141 | else: 142 | speak("As you wish.") 143 | 144 | def fn_read_mail(): 145 | """ 146 | Checks how many unread mails are there in the inbox. 147 | """ 148 | if ping() == 0: 149 | speak("Sorry. The Internet is down currently.") 150 | return 151 | os.system("/path/to/the/file/check_email.sh") #modify 152 | inbox_path = os.getcwd() + "/Text_Files/inbox_details.txt" 153 | f_inbx = open(inbox_path) 154 | data = f_inbx.read() 155 | f_inbx.close() 156 | unread_mails = int(data[(data.index("") + 11)\ 157 | :data.index("")]) 158 | speak("You have " + str(unread_mails) + " unread mails.") 159 | 160 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tzara - An Intellgent Personal Assistant 2 | 3 | A highly customisable Personal Assistant name Tzara which helps in daily tasks written in Python 2.7. 4 | 5 | ## Tasks: 6 | 7 | 1. Send emails 8 | 9 | 2. Search the internet 10 | 11 | 3. Open and close websites 12 | 13 | 4. Set reminders 14 | 15 | 5. Play movies and songs 16 | 17 | 6. Open documents and pdfs 18 | 19 | 7. Open any application 20 | 21 | 8. Update the system 22 | 23 | 9. Open the terminal 24 | 25 | 10. Converse - basic 26 | 27 | 11. Tell date and time 28 | 29 | 12. Shutdown the system 30 | 31 | ## Getting Started 32 | 33 | These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. 34 | 35 | ## Prerequisites 36 | 37 | 1) Debian or Ubuntu based system. 38 | 39 | 2) Python 2.7 - Installation instructions can be found [here.](https://www.python.org/downloads/) 40 | 41 | 3) Pip 42 | ```bash 43 | sudo apt-get update 44 | sudo apt-get install python-pip 45 | ``` 46 | You could also install Pip following [these instructions.](https://pip.pypa.io/en/stable/installing/) 47 | 48 | 49 | ## Installation 50 | 51 | ### Automatic Package Installation - Recommended (Method 1) 52 | 53 | Open the terminal and input: 54 | ```bash 55 | sudo pip install TzaraIPA 56 | ``` 57 | 58 | ####Note: If your Internet connection is slow, the NLTK package will take several hours to download and install. 59 | Have patience! 60 | 61 | ### Manual Package Installation (Method 2) 62 | 63 | 1) gtts 64 | ```bash 65 | sudo pip install gTTS 66 | ``` 67 | 68 | 2) mpg123 69 | ```bash 70 | sudo apt-get install mpg123 71 | ``` 72 | 73 | 3) NLTK package 74 | ```bash 75 | sudo pip install -U nltk 76 | ``` 77 | Or follow [these instructions.](http://www.nltk.org/install.html) 78 | 79 | 4) Firefox 80 | ```bash 81 | sudo apt-get install firefox 82 | ``` 83 | 84 | 5) Audacious music Player 85 | ```bash 86 | sudo apt-get install audacious 87 | ``` 88 | 89 | 6) xdotool 90 | ```bash 91 | sudo apt-get install xdotool 92 | ``` 93 | 94 | 7) wmctrl 95 | ```bash 96 | sudo apt-get install wmctrl 97 | ``` 98 | 99 | 8) Guake dropdown terminal 100 | ```bash 101 | sudo apt-get install guake 102 | ``` 103 | 104 | 9) xdg-utils 105 | ```bash 106 | sudo apt-get install xdg-utils 107 | ``` 108 | 109 | ## Post Package Installation 110 | 111 | ### Note: 112 | 113 | I have nearly automated the complete installation. Few details remain. But until I update the code, the manual post package installation described below is recommended. 114 | 115 | #### 1) Path setup: 116 | 117 | After having downloaded all files, open EACH ONE and modify according to the instructions provided in the file. 118 | 119 | For example, you may find: 120 | ```python 121 | f_reminder = open("/path/to/the/file/reminder.txt", "r+") 122 | ``` 123 | Replace ```"/path/to/the/file"``` with the actual pathname to the file called ```"reminder.txt"```. 124 | 125 | Thus, in my system, this particular pathname was: 126 | ```python 127 | f_reminder = open("/media/suman/New Volume1/Artificial Intelligence/Personal Assistant/Text_files/reminder.txt", "r+") 128 | ``` 129 | 130 | This will ensure the Personal Assistant is customised only to you. 131 | 132 | #### 2) Email: 133 | 134 | This is particular for Gmail accounts. 135 | 136 | To send emails and read emails, you will need access to your Gmail account. But Gmail will block your email if you don't get a password, as it doesn't recognise the application. 137 | 138 | To obtain a password for Tzara, follow [these instructions.](https://support.google.com/accounts/answer/6010255?hl=en) 139 | 140 | Open ```check_email.sh``` in an editor. 141 | 142 | Replace ```your_email_herr``` with your email-id. E.g. john@gmail.com 143 | 144 | Replace ```your_password_here``` with the new password respectively. Note: the password is NOT your general email account password. It is specific to this application. 145 | 146 | Replace ```/path/to/the/file/``` with the pathname to the file ```inbox_detail.txt``` 147 | 148 | Open the Terminal. Go to the directory containing the script ```check_email.sh``` 149 | 150 | Make the script executable: 151 | 152 | ```bash 153 | chmod u+x check_email.sh 154 | ``` 155 | 156 | #### 3) Setting up .txt files: 157 | 158 | You can modify the following .txt files to personalise Tzara further: 159 | 160 | a) ```bye.txt``` - Add ways to say goodbye. 161 | 162 | b) ```comn_sites.txt``` - Add sites you visit. 163 | 164 | c) ```confirmations.txt``` - Add ways to confirm. 165 | 166 | d) ```corporat.txt``` - List of corpora from where Tzara develops her sentences. Currently from Brown Corpus 167 | 168 | e) ```email_id.txt``` - Add email-ids. E.g. john@gmail.com - Simply say: "Mail John", and Tzara will mail john@gmail.com 169 | 170 | f) ```folder.txt``` - Add folder names and paths you frequently use. E.g. Suppose you go to ```/home/username/Documents``` often. Add ```Documents - /home/username/Documents``` to ```folder.txt```, and then you can simply tell Tzara: ```Open folder documents```, and she will open the correct folder. 171 | 172 | g) ```greetings.txt``` - Add ways for Tzara to greet you. 173 | 174 | ## Deployment 175 | 176 | 1) Open the guake terminal. 177 | 178 | 2) Input the following code: 179 | ```bash 180 | python /path/to/the/file/main.py 181 | ``` 182 | Replace ```/path/to/the/file``` with the pathname to the file ```main.py```. This file initialises Tzara. 183 | 184 | Tzara will greet you with something like: ```Hi, my name is Tzara. How may I help you?``` 185 | 186 | Go on and chat with your newfound friend. 187 | 188 | 3) To give commands, simply chat. For example, if you want Tzara to search for the word "cat" on the Internet, simply type something like: ```Hey Tzara, could you please search for cat.``` or ```Hi, could you please google cat.``` or simply ```google cat```. 189 | 190 | 4) To end chat, type anything like: 191 | ``` 192 | Bye Tzara 193 | ``` 194 | or 195 | 196 | ``` 197 | Cya Tzara 198 | ``` 199 | or simply 200 | ``` 201 | bye 202 | ``` 203 | 204 | ## Authors 205 | 206 | Suman Pal 207 | -------------------------------------------------------------------------------- /tzara/tzara.py: -------------------------------------------------------------------------------- 1 | """ 2 | The core of the Intelligent Personal Assistant 3 | 4 | Finds keywords in the input sentence, 5 | then calls the appropriate functions. 6 | """ 7 | 8 | from nltk.tokenize import word_tokenize 9 | from nltk.corpus import stopwords 10 | from Speech import speak 11 | from files import open_folder 12 | import firefox 13 | from playmovie import fn_movie, fn_close_movie 14 | from songs import fn_play_song, fn_close_song 15 | from pdf import fn_open_pdf, fn_close_pdf 16 | import os 17 | import time, datetime 18 | import reminder 19 | import terminal 20 | from converse import converse 21 | from confirm import confirm 22 | 23 | def tzara(string): 24 | """ 25 | Searches the input string for keywords, or commands. 26 | If keywords are found, it calls appropriate function. 27 | List of functions: 28 | (1) Open (website, pdf, folder, terminal, reminder) 29 | (2) Play (movies, songs) 30 | (3) Tell the time. 31 | (4) Google, or search for a string online. 32 | (5) Close (tab, song, movie, pdf) 33 | (6) Mail (read, send) 34 | (7) Shutdown 35 | (8) Reminder 36 | """ 37 | #Splitting each sentence in a list of words. 38 | word_list = word_tokenize(string) 39 | 40 | #Setting up stop_words: words that are redundant. 41 | stop_words = set(stopwords.words('english')) 42 | 43 | #Creating space for a list of sentences without stop_words. 44 | if "search" not in word_list and "google" not in word_list: 45 | filtered_sentence = [w for w in word_list if not w in stop_words] 46 | else: 47 | filtered_sentence = [w for w in word_list] 48 | 49 | if 'open' in filtered_sentence: 50 | #OPEN WEBSITE 51 | if 'site' in filtered_sentence: 52 | print "in function" 53 | filtered_sentence = [w for w in filtered_sentence \ 54 | if w != "called" and w != "named"] 55 | firefox.fn_open_site( \ 56 | filtered_sentence[filtered_sentence.index('site') + 1]) 57 | elif 'website' in filtered_sentence and \ 58 | filtered_sentence.index('open') \ 59 | < filtered_sentence.index('website'): 60 | firefox.fn_open_site( \ 61 | filtered_sentence[filtered_sentence.index('website') + 1]) 62 | 63 | #OPEN PDF 64 | elif 'pdf' in filtered_sentence and \ 65 | filtered_sentence.index('open') \ 66 | < filtered_sentence.index('pdf'): 67 | filtered_sentence = \ 68 | [w for w in filtered_sentence \ 69 | if w != "called" and w != "named"] 70 | fn_open_pdf(filtered_sentence[filtered_sentence.index('pdf') + 1]) 71 | 72 | #OPEN FOLDER 73 | elif 'folder' in filtered_sentence and \ 74 | filtered_sentence.index('open') \ 75 | < filtered_sentence.index('folder'): 76 | if "called" in string: 77 | pos = string.index("called") + 7 78 | string = string[pos:] 79 | elif "named" in string: 80 | pos = string.index("named") + 6 81 | string = string[pos:] 82 | else: 83 | pos = string.index("folder")+7 84 | string = string[pos:] 85 | open_folder(string) 86 | 87 | #OPEN TERMINAL 88 | elif 'terminal' in filtered_sentence and \ 89 | filtered_sentence.index('open') \ 90 | < filtered_sentence.index('terminal'): 91 | terminal.terminal() 92 | 93 | #OPEN REMINDER 94 | elif 'reminder' in filtered_sentence: 95 | reminder.reminder() 96 | 97 | elif len(filtered_sentence) > 1: 98 | sites_path = os.getcwd() + "/Text_Files/comn_sites.txt" 99 | f_sites = open(sites_path, "r") 100 | for line in f_sites: 101 | name_list = line.strip().split("-") 102 | #if (n.lower()==''.join(name_list[0:1]).lower()): 103 | # counter=1 104 | # email_id=''.join(name_list[1:2]) 105 | pos = filtered_sentence.index('open')+1 106 | if ''.join(filtered_sentence[pos]).lower() \ 107 | in ''.join(name_list[0:1]).lower(): 108 | print ''.join(name_list[1:2]) 109 | firefox.fn_open_site(''.join(name_list[1:2])) 110 | f_sites.close() 111 | 112 | else: 113 | speak("You want me to open something," 114 | "but I'm not sure what. Could you please repeat?") 115 | 116 | elif 'terminal' in filtered_sentence: 117 | speak("Would you like me to open the terminal for you?") 118 | reply = raw_input('\033[1m'+'Username: '+'\033[0m') #modify 119 | if confirm(reply) == 1: 120 | terminal.terminal() 121 | else: 122 | speak("As you wish.") 123 | 124 | elif 'movie' in filtered_sentence: 125 | #PLAY MOVIE 126 | filtered_sentence = [w for w in filtered_sentence \ 127 | if w != "called" and w != "named" and w != "titled"] 128 | pos = filtered_sentence.index('movie') + 1 129 | fn_movie(filtered_sentence[pos]) 130 | 131 | #PLAY SONG 132 | elif 'song' in filtered_sentence and filtered_sentence.index('play') \ 133 | < filtered_sentence.index('song'): 134 | filtered_sentence = [w for w in filtered_sentence \ 135 | if w != "called" and w != "named" and w != "titled"] 136 | pos = filtered_sentence.index('song') + 1 137 | fn_play_song(filtered_sentence[pos]) 138 | 139 | elif 'time' in filtered_sentence: 140 | speak(time.strftime("%A") + " " \ 141 | + str(datetime.datetime.now())[:16]) 142 | 143 | elif 'google' in filtered_sentence: 144 | if len(filtered_sentence) > 1: 145 | pos = filtered_sentence.index('google') + 1 146 | if 'word' in filtered_sentence \ 147 | and filtered_sentence[-1] != 'word': 148 | filtered_sentence = \ 149 | [w for w in filtered_sentence if w != "word"] 150 | 151 | search_string = ''.join(filtered_sentence[pos:]) 152 | firefox.fn_search(search_string) 153 | else: 154 | speak("If you want me to open google, say 'open google'") 155 | speak("If you want me to search for a word," 156 | "say 'google '") 157 | 158 | elif 'search' in filtered_sentence: 159 | if filtered_sentence[-1] == "search": 160 | speak("Enter the word you would like me to search.") 161 | search_string = raw_input('\033[1m' + 'Username: ' + '\033[0m') #modify 162 | firefox.fn_search(search_string) 163 | return 164 | pos = filtered_sentence.index('search') + 1 165 | search_string = " ".join(filtered_sentence[pos:]) 166 | firefox.fn_search(search_string) 167 | 168 | elif 'reminder' in filtered_sentence: 169 | speak("Opening reminder") 170 | reminder.reminder() 171 | 172 | elif 'close' in filtered_sentence: 173 | if 'tab' in filtered_sentence: 174 | firefox.fn_close_tab() 175 | speak('There you go!') 176 | if 'song' in filtered_sentence: 177 | fn_close_song() 178 | if 'movie' in filtered_sentence: 179 | fn_close_movie() 180 | if 'pdf' in filtered_sentence: 181 | fn_close_pdf() 182 | else: 183 | speak("I figure you want me to close something," 184 | "but I'm not sure what!") 185 | 186 | elif 'ping' in filtered_sentence: 187 | firefox.ping() 188 | 189 | elif 'mail' in filtered_sentence: 190 | if 'read' in filtered_sentence or \ 191 | 'unread' in filtered_sentence or \ 192 | 'check' in filtered_sentence or \ 193 | 'see' in filtered_sentence: 194 | firefox.fn_read_mail() 195 | elif filtered_sentence[-1] != 'mail': 196 | pos = filtered_sentence.index('mail') + 1 197 | firefox.fn_write_mail(filtered_sentence[pos]) 198 | elif filtered_sentence[-1] == 'mail': 199 | speak("Whom would you like to mail?") 200 | reply = raw_input('\033[1m' + 'Username: ' + '\033[0m') #modify 201 | firefox.fn_write_mail(reply) 202 | else: 203 | speak("Do you want to mail somebody?" 204 | " Then type: 'mail person's_name'") 205 | speak("Or do you want to read your emails?" 206 | "Then simply type: 'read mail'") 207 | 208 | elif 'shutdown' in filtered_sentence: 209 | speak("Would you like me to shutdown the system?") 210 | reply = raw_input('\033[1m' + 'Username: ' + '\033[0m') #modify 211 | if confirm(reply) == 1: 212 | speak("Shutting down system now. Goodbye!") 213 | os.system("sudo shutdown -h now") 214 | else: 215 | speak("As you wish.") 216 | 217 | else: 218 | speak(converse(string)) 219 | return None 220 | --------------------------------------------------------------------------------