├── 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 |
--------------------------------------------------------------------------------