diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..2b44ad5 --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +worker: python siricontrol.py diff --git a/README.md b/README.md index 993ad24..8fe0278 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # SiriControl +This is an updated version of SiriControl, which allow to use it in French. Here is a complete tutorial to build your own SiriController and running it on the cloud for free: https://pydathon.medium.com/how-to-build-your-own-virtual-assistant-with-siricontrol-e9d531f05772 + ![SiriControl Demo](https://images.ctfassets.net/tvfg2m04ppj4/1PZVE9xziMv8DlKNKJONts/7264a51ae7c8b59ba2b39b49fb86f0cf/SiriControl.jpg) SiriControl is an open source framework designed with developers in mind. It provides a simple way of using Siri commands by dynamically loading modules created by the user. This means that you can add voice controlled capability to any project, with Siri. @@ -15,3 +17,5 @@ Convinced that SiriControl is awesome? Well, here is the link on how to get started: https://medium.com/@thesanjeetc/bae98aceb586 + + diff --git a/modules/lightoff.py b/modules/lightoff.py new file mode 100644 index 0000000..0661770 --- /dev/null +++ b/modules/lightoff.py @@ -0,0 +1,13 @@ +# This module aim is to trigger a smart plug or bubble to turn it on. + +#You can import any required modules here +import requests + +#This can be anything you want +moduleName = "lightoff" + +#All of the words must be heard in order for this module to be executed +commandWords = ["off", "lights"] + +def execute(command): + requests.get("https://sequematic.com/trigger-custom-webhook/........") diff --git a/modules/lighton.py b/modules/lighton.py new file mode 100644 index 0000000..25ce439 --- /dev/null +++ b/modules/lighton.py @@ -0,0 +1,12 @@ +#You can import any required modules here +import requests + + +#This can be anything you want +moduleName = "lighton" + +#All of the words must be heard in order for this module to be executed +commandWords = ["on", "lights"] + +def execute(command): + requests.get("https://sequematic.com/trigger-custom-webhook/........") diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..06e089b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +requests==2.25.1 +Flask==1.1.1 +Unidecode==1.2.0 +imap-tools==0.37.0 diff --git a/siricontrol.py b/siricontrol.py index edc224c..f4b0b3a 100644 --- a/siricontrol.py +++ b/siricontrol.py @@ -3,7 +3,11 @@ import email import os import pkgutil - +import sys +import subprocess +import unidecode +import requests +from imap_tools import MailBox, AND ########################################## # Add your gmail username and password here @@ -23,23 +27,22 @@ def __init__(self, username, password): print("------------------------------------------------------") print("- SIRI CONTROL -") print("- Created by Sanjeet Chatterjee -") + print("- Adapted by Pydathon -") print("- Website: https://medium.com/@thesanjeetc -") print("------------------------------------------------------") try: self.last_checked = -1 - self.mail = imaplib.IMAP4_SSL("imap.gmail.com", 993) - self.mail.login(username, password) - self.mail.list() - self.mail.select("Notes") - + self.mail = MailBox('imap.gmail.com') + self.mail.login(username, password, initial_folder='Notes') + # Gets last Note id to stop last command from executing - result, uidlist = self.mail.search(None, "ALL") + uidlist = [msg.uid for msg in self.mail.fetch(AND(all=True))] + subjects = [msg.subject for msg in self.mail.fetch(AND(all=True))] try: - self.last_checked = uidlist[0].split()[-1] + self.last_checked = uidlist[-1].split()[-1] except IndexError: pass - self.load() self.handle() except imaplib.IMAP4.error: @@ -72,12 +75,10 @@ def load(self): def fetch_command(self): """Retrieve the last Note created if new id found""" - self.mail.list() - self.mail.select("Notes") - - result, uidlist = self.mail.search(None, "ALL") + uidlist = [msg.uid for msg in self.mail.fetch(AND(all=True))] + subjects = [msg.subject for msg in self.mail.fetch(AND(all=True))] try: - latest_email_id = uidlist[0].split()[-1] + latest_email_id = uidlist[-1].split()[-1] except IndexError: return @@ -85,33 +86,35 @@ def fetch_command(self): return self.last_checked = latest_email_id - result, data = self.mail.fetch(latest_email_id, "(RFC822)") - voice_command = email.message_from_string(data[0][1].decode('utf-8')) - return str(voice_command.get_payload()).lower().strip() + data = subjects[-1] + return data.lower().strip() def handle(self): """Handle new commands - Poll continuously every second and check for new commands. """ print("Fetching commands...") print("\n") while True: + folder_status = self.mail.folder.status('Notes') + nb_messages = folder_status["MESSAGES"] # permet d'actualiser la mailbox try: command = self.fetch_command() if not command: raise ControlException("No command found.") - - print("The word(s) '" + command + "' have been said") + print("The word(s) '" + unidecode.unidecode(str(command).lower()) + "' have been said") for module in self.modules: foundWords = [] for word in module.commandWords: - if str(word) in command: - foundWords.append(str(word)) + #print("command=",unidecode.unidecode(str(command).lower())) + #print("word=", unidecode.unidecode(str(word).lower())) + #print(unidecode.unidecode(str(word).lower()) in unidecode.unidecode(str(command).lower())) + if unidecode.unidecode(str(word).lower()) in unidecode.unidecode(str(command).lower()): + foundWords.append(unidecode.unidecode(str(word).lower())) if len(foundWords) == len(module.commandWords): try: - module.execute(command) + module.execute(unidecode.unidecode(str(command).lower())) print("The module {0} has been executed " "successfully.".format(module.moduleName)) except: @@ -120,6 +123,7 @@ def handle(self): module.moduleName)) else: print("\n") + self.mail.move(self.mail.fetch(), 'notes_old') except (TypeError, ControlException): pass except Exception as exc: