summaryrefslogtreecommitdiff
path: root/client/modules
diff options
context:
space:
mode:
authorschneefux <schneefux+commit@schneefux.xyz>2014-07-23 21:21:17 -0700
committerschneefux <schneefux+commit@schneefux.xyz>2014-07-23 21:21:17 -0700
commit2c55f4da462383ee6c7b89ea44e5c40cd5badf0c (patch)
tree078672f2b221cfb7d0aa765f438002a277914c9f /client/modules
parent8a5e5ed385a5c467260c2f1b20816a66cebfc1c6 (diff)
downloadjasper-client-2c55f4da462383ee6c7b89ea44e5c40cd5badf0c.tar.gz
jasper-client-2c55f4da462383ee6c7b89ea44e5c40cd5badf0c.zip
Google STT works on OS X
Diffstat (limited to 'client/modules')
-rw-r--r--client/modules/Birthday.py64
-rw-r--r--client/modules/Gmail.py136
-rw-r--r--client/modules/HN.py130
-rw-r--r--client/modules/Joke.py63
-rw-r--r--client/modules/Life.py32
-rw-r--r--client/modules/News.py122
-rw-r--r--client/modules/Notifications.py55
-rw-r--r--client/modules/Time.py33
-rw-r--r--client/modules/Unclear.py29
-rw-r--r--client/modules/Weather.py110
-rwxr-xr-xclient/modules/__init__.py0
-rw-r--r--client/modules/app_utils.py123
12 files changed, 0 insertions, 897 deletions
diff --git a/client/modules/Birthday.py b/client/modules/Birthday.py
deleted file mode 100644
index 1388443..0000000
--- a/client/modules/Birthday.py
+++ /dev/null
@@ -1,64 +0,0 @@
-import datetime
-import re
-from facebook import *
-from app_utils import getTimezone
-
-WORDS = ["BIRTHDAY"]
-
-
-def handle(text, mic, profile):
- """
- Responds to user-input, typically speech text, by listing the user's
- Facebook friends with birthdays today.
-
- Arguments:
- text -- user-input, typically transcribed speech
- mic -- used to interact with the user (for both input and output)
- profile -- contains information related to the user (e.g., phone number)
- """
- oauth_access_token = profile['keys']["FB_TOKEN"]
-
- graph = GraphAPI(oauth_access_token)
-
- try:
- results = graph.request(
- "me/friends", args={'fields': 'id,name,birthday'})
- except GraphAPIError:
- mic.say(
- "I have not been authorized to query your Facebook. If you would like to check birthdays in the future, please visit the Jasper dashboard.")
- return
- except:
- mic.say(
- "I apologize, there's a problem with that service at the moment.")
- return
-
- needle = datetime.datetime.now(tz=getTimezone(profile)).strftime("%m/%d")
-
- people = []
- for person in results['data']:
- try:
- if needle in person['birthday']:
- people.append(person['name'])
- except:
- continue
-
- if len(people) > 0:
- if len(people) == 1:
- output = people[0] + " has a birthday today."
- else:
- output = "Your friends with birthdays today are " + \
- ", ".join(people[:-1]) + " and " + people[-1] + "."
- else:
- output = "None of your friends have birthdays today."
-
- mic.say(output)
-
-
-def isValid(text):
- """
- Returns True if the input is related to birthdays.
-
- Arguments:
- text -- user-input, typically transcribed speech
- """
- return bool(re.search(r'birthday', text, re.IGNORECASE))
diff --git a/client/modules/Gmail.py b/client/modules/Gmail.py
deleted file mode 100644
index b401ae6..0000000
--- a/client/modules/Gmail.py
+++ /dev/null
@@ -1,136 +0,0 @@
-import imaplib
-import email
-import re
-from dateutil import parser
-from app_utils import *
-
-WORDS = ["EMAIL", "INBOX"]
-
-
-def getSender(email):
- """
- Returns the best-guess sender of an email.
-
- Arguments:
- email -- the email whose sender is desired
-
- Returns:
- Sender of the email.
- """
- sender = email['From']
- m = re.match(r'(.*)\s<.*>', sender)
- if m:
- return m.group(1)
- return sender
-
-
-def getDate(email):
- return parser.parse(email.get('date'))
-
-
-def getMostRecentDate(emails):
- """
- Returns the most recent date of any email in the list provided.
-
- Arguments:
- emails -- a list of emails to check
-
- Returns:
- Date of the most recent email.
- """
- dates = [getDate(e) for e in emails]
- dates.sort(reverse=True)
- if dates:
- return dates[0]
- return None
-
-
-def fetchUnreadEmails(profile, since=None, markRead=False, limit=None):
- """
- Fetches a list of unread email objects from a user's Gmail inbox.
-
- Arguments:
- profile -- contains information related to the user (e.g., Gmail address)
- since -- if provided, no emails before this date will be returned
- markRead -- if True, marks all returned emails as read in target inbox
-
- Returns:
- A list of unread email objects.
- """
- conn = imaplib.IMAP4_SSL('imap.gmail.com')
- conn.debug = 0
- conn.login(profile['gmail_address'], profile['gmail_password'])
- conn.select(readonly=(not markRead))
-
- msgs = []
- (retcode, messages) = conn.search(None, '(UNSEEN)')
-
- if retcode == 'OK' and messages != ['']:
- numUnread = len(messages[0].split(' '))
- if limit and numUnread > limit:
- return numUnread
-
- for num in messages[0].split(' '):
- # parse email RFC822 format
- ret, data = conn.fetch(num, '(RFC822)')
- msg = email.message_from_string(data[0][1])
-
- if not since or getDate(msg) > since:
- msgs.append(msg)
- conn.close()
- conn.logout()
-
- return msgs
-
-
-def handle(text, mic, profile):
- """
- Responds to user-input, typically speech text, with a summary of
- the user's Gmail inbox, reporting on the number of unread emails
- in the inbox, as well as their senders.
-
- Arguments:
- text -- user-input, typically transcribed speech
- mic -- used to interact with the user (for both input and output)
- profile -- contains information related to the user (e.g., Gmail address)
- """
- try:
- msgs = fetchUnreadEmails(profile, limit=5)
-
- if isinstance(msgs, int):
- response = "You have %d unread emails." % msgs
- mic.say(response)
- return
-
- senders = [getSender(e) for e in msgs]
- except imaplib.IMAP4.error:
- mic.say(
- "I'm sorry. I'm not authenticated to work with your Gmail.")
- return
-
- if not senders:
- mic.say("You have no unread emails.")
- elif len(senders) == 1:
- mic.say("You have one unread email from " + senders[0] + ".")
- else:
- response = "You have %d unread emails" % len(
- senders)
- unique_senders = list(set(senders))
- if len(unique_senders) > 1:
- unique_senders[-1] = 'and ' + unique_senders[-1]
- response += ". Senders include: "
- response += '...'.join(senders)
- else:
- response += " from " + unittest[0]
-
- mic.say(response)
-
-
-def isValid(text):
- """
- Returns True if the input is related to email.
-
- Arguments:
- text -- user-input, typically transcribed speech
- """
- return bool(re.search(r'\bemail\b', text, re.IGNORECASE))
diff --git a/client/modules/HN.py b/client/modules/HN.py
deleted file mode 100644
index 493fa1d..0000000
--- a/client/modules/HN.py
+++ /dev/null
@@ -1,130 +0,0 @@
-import urllib2
-import re
-import random
-from bs4 import BeautifulSoup
-import app_utils
-from semantic.numbers import NumberService
-
-WORDS = ["HACKER", "NEWS", "YES", "NO", "FIRST", "SECOND", "THIRD"]
-
-PRIORITY = 4
-
-URL = 'http://news.ycombinator.com'
-
-
-class HNStory:
-
- def __init__(self, title, URL):
- self.title = title
- self.URL = URL
-
-
-def getTopStories(maxResults=None):
- """
- Returns the top headlines from Hacker News.
-
- Arguments:
- maxResults -- if provided, returns a random sample of size maxResults
- """
- hdr = {'User-Agent': 'Mozilla/5.0'}
- req = urllib2.Request(URL, headers=hdr)
- page = urllib2.urlopen(req).read()
- soup = BeautifulSoup(page)
- matches = soup.findAll('td', class_="title")
- matches = [m.a for m in matches if m.a and m.text != u'More']
- matches = [HNStory(m.text, m['href']) for m in matches]
-
- if maxResults:
- num_stories = min(maxResults, len(matches))
- return random.sample(matches, num_stories)
-
- return matches
-
-
-def handle(text, mic, profile):
- """
- Responds to user-input, typically speech text, with a sample of
- Hacker News's top headlines, sending them to the user over email
- if desired.
-
- Arguments:
- text -- user-input, typically transcribed speech
- mic -- used to interact with the user (for both input and output)
- profile -- contains information related to the user (e.g., phone number)
- """
- mic.say("Pulling up some stories.")
- stories = getTopStories(maxResults=3)
- all_titles = '... '.join(str(idx + 1) + ") " +
- story.title for idx, story in enumerate(stories))
-
- def handleResponse(text):
-
- def extractOrdinals(text):
- output = []
- service = NumberService()
- for w in text.split():
- if w in service.__ordinals__:
- output.append(service.__ordinals__[w])
- return [service.parse(w) for w in output]
-
- chosen_articles = extractOrdinals(text)
- send_all = chosen_articles is [] and app_utils.isPositive(text)
-
- if send_all or chosen_articles:
- mic.say("Sure, just give me a moment")
-
- if profile['prefers_email']:
- body = "<ul>"
-
- def formatArticle(article):
- tiny_url = app_utils.generateTinyURL(article.URL)
-
- if profile['prefers_email']:
- return "<li><a href=\'%s\'>%s</a></li>" % (tiny_url,
- article.title)
- else:
- return article.title + " -- " + tiny_url
-
- for idx, article in enumerate(stories):
- if send_all or (idx + 1) in chosen_articles:
- article_link = formatArticle(article)
-
- if profile['prefers_email']:
- body += article_link
- else:
- if not app_utils.emailUser(profile, SUBJECT="", BODY=article_link):
- mic.say(
- "I'm having trouble sending you these articles. Please make sure that your phone number and carrier are correct on the dashboard.")
- return
-
- # if prefers email, we send once, at the end
- if profile['prefers_email']:
- body += "</ul>"
- if not app_utils.emailUser(profile, SUBJECT="From the Front Page of Hacker News", BODY=body):
- mic.say(
- "I'm having trouble sending you these articles. Please make sure that your phone number and carrier are correct on the dashboard.")
- return
-
- mic.say("All done.")
-
- else:
- mic.say("OK I will not send any articles")
-
- if not profile['prefers_email'] and profile['phone_number']:
- mic.say("Here are some front-page articles. " +
- all_titles + ". Would you like me to send you these? If so, which?")
- handleResponse(mic.activeListen())
-
- else:
- mic.say(
- "Here are some front-page articles. " + all_titles)
-
-
-def isValid(text):
- """
- Returns True if the input is related to Hacker News.
-
- Arguments:
- text -- user-input, typically transcribed speech
- """
- return bool(re.search(r'\b(hack(er)?|HN)\b', text, re.IGNORECASE))
diff --git a/client/modules/Joke.py b/client/modules/Joke.py
deleted file mode 100644
index 52b3eb9..0000000
--- a/client/modules/Joke.py
+++ /dev/null
@@ -1,63 +0,0 @@
-import random
-import re
-
-WORDS = ["JOKE", "KNOCK KNOCK"]
-
-
-def getRandomJoke(filename="../static/text/JOKES.txt"):
- jokeFile = open(filename, "r")
- jokes = []
- start = ""
- end = ""
- for line in jokeFile.readlines():
- line = line.replace("\n", "")
-
- if start == "":
- start = line
- continue
-
- if end == "":
- end = line
- continue
-
- jokes.append((start, end))
- start = ""
- end = ""
-
- jokes.append((start, end))
- joke = random.choice(jokes)
- return joke
-
-
-def handle(text, mic, profile):
- """
- Responds to user-input, typically speech text, by telling a joke.
-
- Arguments:
- text -- user-input, typically transcribed speech
- mic -- used to interact with the user (for both input and output)
- profile -- contains information related to the user (e.g., phone number)
- """
- joke = getRandomJoke()
-
- mic.say("Knock knock")
-
- def firstLine(text):
- mic.say(joke[0])
-
- def punchLine(text):
- mic.say(joke[1])
-
- punchLine(mic.activeListen())
-
- firstLine(mic.activeListen())
-
-
-def isValid(text):
- """
- Returns True if the input is related to jokes/humor.
-
- Arguments:
- text -- user-input, typically transcribed speech
- """
- return bool(re.search(r'\bjoke\b', text, re.IGNORECASE))
diff --git a/client/modules/Life.py b/client/modules/Life.py
deleted file mode 100644
index 2c79ee1..0000000
--- a/client/modules/Life.py
+++ /dev/null
@@ -1,32 +0,0 @@
-import random
-import re
-
-WORDS = ["MEANING", "OF", "LIFE"]
-
-
-def handle(text, mic, profile):
- """
- Responds to user-input, typically speech text, by relaying the
- meaning of life.
-
- Arguments:
- text -- user-input, typically transcribed speech
- mic -- used to interact with the user (for both input and output)
- profile -- contains information related to the user (e.g., phone number)
- """
- messages = ["It's 42, you idiot.",
- "It's 42. How many times do I have to tell you?"]
-
- message = random.choice(messages)
-
- mic.say(message)
-
-
-def isValid(text):
- """
- Returns True if the input is related to the meaning of life.
-
- Arguments:
- text -- user-input, typically transcribed speech
- """
- return bool(re.search(r'\bmeaning of life\b', text, re.IGNORECASE))
diff --git a/client/modules/News.py b/client/modules/News.py
deleted file mode 100644
index 59495a3..0000000
--- a/client/modules/News.py
+++ /dev/null
@@ -1,122 +0,0 @@
-import feedparser
-import app_utils
-import re
-from semantic.numbers import NumberService
-
-WORDS = ["NEWS", "YES", "NO", "FIRST", "SECOND", "THIRD"]
-
-PRIORITY = 3
-
-URL = 'http://news.ycombinator.com'
-
-
-class Article:
-
- def __init__(self, title, URL):
- self.title = title
- self.URL = URL
-
-
-def getTopArticles(maxResults=None):
- d = feedparser.parse("http://news.google.com/?output=rss")
-
- count = 0
- articles = []
- for item in d['items']:
- articles.append(Article(item['title'], item['link'].split("&url=")[1]))
- count += 1
- if maxResults and count > maxResults:
- break
-
- return articles
-
-
-def handle(text, mic, profile):
- """
- Responds to user-input, typically speech text, with a summary of
- the day's top news headlines, sending them to the user over email
- if desired.
-
- Arguments:
- text -- user-input, typically transcribed speech
- mic -- used to interact with the user (for both input and output)
- profile -- contains information related to the user (e.g., phone number)
- """
- mic.say("Pulling up the news")
- articles = getTopArticles(maxResults=3)
- titles = [" ".join(x.title.split(" - ")[:-1]) for x in articles]
- all_titles = "... ".join(str(idx + 1) + ")" +
- title for idx, title in enumerate(titles))
-
- def handleResponse(text):
-
- def extractOrdinals(text):
- output = []
- service = NumberService()
- for w in text.split():
- if w in service.__ordinals__:
- output.append(service.__ordinals__[w])
- return [service.parse(w) for w in output]
-
- chosen_articles = extractOrdinals(text)
- send_all = chosen_articles is [] and app_utils.isPositive(text)
-
- if send_all or chosen_articles:
- mic.say("Sure, just give me a moment")
-
- if profile['prefers_email']:
- body = "<ul>"
-
- def formatArticle(article):
- tiny_url = app_utils.generateTinyURL(article.URL)
-
- if profile['prefers_email']:
- return "<li><a href=\'%s\'>%s</a></li>" % (tiny_url,
- article.title)
- else:
- return article.title + " -- " + tiny_url
-
- for idx, article in enumerate(articles):
- if send_all or (idx + 1) in chosen_articles:
- article_link = formatArticle(article)
-
- if profile['prefers_email']:
- body += article_link
- else:
- if not app_utils.emailUser(profile, SUBJECT="", BODY=article_link):
- mic.say(
- "I'm having trouble sending you these articles. Please make sure that your phone number and carrier are correct on the dashboard.")
- return
-
- # if prefers email, we send once, at the end
- if profile['prefers_email']:
- body += "</ul>"
- if not app_utils.emailUser(profile, SUBJECT="Your Top Headlines", BODY=body):
- mic.say(
- "I'm having trouble sending you these articles. Please make sure that your phone number and carrier are correct on the dashboard.")
- return
-
- mic.say("All set")
-
- else:
-
- mic.say("OK I will not send any articles")
-
- if 'phone_number' in profile:
- mic.say("Here are the current top headlines. " + all_titles +
- ". Would you like me to send you these articles? If so, which?")
- handleResponse(mic.activeListen())
-
- else:
- mic.say(
- "Here are the current top headlines. " + all_titles)
-
-
-def isValid(text):
- """
- Returns True if the input is related to the news.
-
- Arguments:
- text -- user-input, typically transcribed speech
- """
- return bool(re.search(r'\b(news|headline)\b', text, re.IGNORECASE))
diff --git a/client/modules/Notifications.py b/client/modules/Notifications.py
deleted file mode 100644
index fc91da1..0000000
--- a/client/modules/Notifications.py
+++ /dev/null
@@ -1,55 +0,0 @@
-import re
-from facebook import *
-
-
-WORDS = ["FACEBOOK", "NOTIFICATION"]
-
-
-def handle(text, mic, profile):
- """
- Responds to user-input, typically speech text, with a summary of
- the user's Facebook notifications, including a count and details
- related to each individual notification.
-
- Arguments:
- text -- user-input, typically transcribed speech
- mic -- used to interact with the user (for both input and output)
- profile -- contains information related to the user (e.g., phone number)
- """
- oauth_access_token = profile['keys']['FB_TOKEN']
-
- graph = GraphAPI(oauth_access_token)
-
- try:
- results = graph.request("me/notifications")
- except GraphAPIError:
- mic.say(
- "I have not been authorized to query your Facebook. If you would like to check your notifications in the future, please visit the Jasper dashboard.")
- return
- except:
- mic.say(
- "I apologize, there's a problem with that service at the moment.")
-
- if not len(results['data']):
- mic.say("You have no Facebook notifications. ")
- return
-
- updates = []
- for notification in results['data']:
- updates.append(notification['title'])
-
- count = len(results['data'])
- mic.say("You have " + str(count) +
- " Facebook notifications. " + " ".join(updates) + ". ")
-
- return
-
-
-def isValid(text):
- """
- Returns True if the input is related to Facebook notifications.
-
- Arguments:
- text -- user-input, typically transcribed speech
- """
- return bool(re.search(r'\bnotification|Facebook\b', text, re.IGNORECASE))
diff --git a/client/modules/Time.py b/client/modules/Time.py
deleted file mode 100644
index 2fe8a10..0000000
--- a/client/modules/Time.py
+++ /dev/null
@@ -1,33 +0,0 @@
-import datetime
-import re
-from app_utils import getTimezone
-from semantic.dates import DateService
-
-WORDS = ["TIME"]
-
-
-def handle(text, mic, profile):
- """
- Reports the current time based on the user's timezone.
-
- Arguments:
- text -- user-input, typically transcribed speech
- mic -- used to interact with the user (for both input and output)
- profile -- contains information related to the user (e.g., phone number)
- """
-
- tz = getTimezone(profile)
- now = datetime.datetime.now(tz=tz)
- service = DateService()
- response = service.convertTime(now)
- mic.say("It is %s right now." % response)
-
-
-def isValid(text):
- """
- Returns True if input is related to the time.
-
- Arguments:
- text -- user-input, typically transcribed speech
- """
- return bool(re.search(r'\btime\b', text, re.IGNORECASE))
diff --git a/client/modules/Unclear.py b/client/modules/Unclear.py
deleted file mode 100644
index 23ab2ed..0000000
--- a/client/modules/Unclear.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from sys import maxint
-import random
-
-WORDS = []
-
-PRIORITY = -(maxint + 1)
-
-
-def handle(text, mic, profile):
- """
- Reports that the user has unclear or unusable input.
-
- Arguments:
- text -- user-input, typically transcribed speech
- mic -- used to interact with the user (for both input and output)
- profile -- contains information related to the user (e.g., phone number)
- """
-
- messages = ["I'm sorry, could you repeat that?",
- "My apologies, could you try saying that again?",
- "Say that again?", "I beg your pardon?"]
-
- message = random.choice(messages)
-
- mic.say(message)
-
-
-def isValid(text):
- return True
diff --git a/client/modules/Weather.py b/client/modules/Weather.py
deleted file mode 100644
index ad1ac29..0000000
--- a/client/modules/Weather.py
+++ /dev/null
@@ -1,110 +0,0 @@
-import re
-import datetime
-import feedparser
-from app_utils import getTimezone
-from semantic.dates import DateService
-
-WORDS = ["WEATHER", "TODAY", "TOMORROW"]
-
-
-def replaceAcronyms(text):
- """Replaces some commonly-used acronyms for an improved verbal weather report."""
-
- def parseDirections(text):
- words = {
- 'N': 'north',
- 'S': 'south',
- 'E': 'east',
- 'W': 'west',
- }
- output = [words[w] for w in list(text)]
- return ' '.join(output)
- acronyms = re.findall(r'\b([NESW]+)\b', text)
-
- for w in acronyms:
- text = text.replace(w, parseDirections(w))
-
- text = re.sub(r'(\b\d+)F(\b)', '\g<1> Fahrenheit\g<2>', text)
- text = re.sub(r'(\b)mph(\b)', '\g<1>miles per hour\g<2>', text)
- text = re.sub(r'(\b)in\.', '\g<1>inches', text)
-
- return text
-
-
-def getForecast(profile):
- return feedparser.parse("http://rss.wunderground.com/auto/rss_full/"
- + str(profile['location']))['entries']
-
-
-def handle(text, mic, profile):
- """
- Responds to user-input, typically speech text, with a summary of
- the relevant weather for the requested date (typically, weather
- information will not be available for days beyond tomorrow).
-
- Arguments:
- text -- user-input, typically transcribed speech
- mic -- used to interact with the user (for both input and output)
- profile -- contains information related to the user (e.g., phone number)
- """
-
- if not profile['location']:
- mic.say(
- "I'm sorry, I can't seem to access that information. Please make sure that you've set your location on the dashboard.")
- return
-
- tz = getTimezone(profile)
-
- service = DateService(tz=tz)
- date = service.extractDay(text)
- if not date:
- date = datetime.datetime.now(tz=tz)
- weekday = service.__daysOfWeek__[date.weekday()]
-
- if date.weekday() == datetime.datetime.now(tz=tz).weekday():
- date_keyword = "Today"
- elif date.weekday() == (
- datetime.datetime.now(tz=tz).weekday() + 1) % 7:
- date_keyword = "Tomorrow"
- else:
- date_keyword = "On " + weekday
-
- forecast = getForecast(profile)
-
- output = None
-
- for entry in forecast:
- try:
- date_desc = entry['title'].split()[0].strip().lower()
- if date_desc == 'forecast': #For global forecasts
- date_desc = entry['title'].split()[2].strip().lower()
- weather_desc = entry['summary']
-
- elif date_desc == 'current': #For first item of global forecasts
- continue
- else:
- weather_desc = entry['summary'].split('-')[1] #US forecasts
-
- if weekday == date_desc:
- output = date_keyword + \
- ", the weather will be " + weather_desc + "."
- break
- except:
- continue
-
- if output:
- output = replaceAcronyms(output)
- mic.say(output)
- else:
- mic.say(
- "I'm sorry. I can't see that far ahead.")
-
-
-def isValid(text):
- """
- Returns True if the text is related to the weather.
-
- Arguments:
- text -- user-input, typically transcribed speech
- """
- return bool(re.search(r'\b(weathers?|temperature|forecast|outside|hot|cold|jacket|coat|rain)\b', text, re.IGNORECASE))
diff --git a/client/modules/__init__.py b/client/modules/__init__.py
deleted file mode 100755
index e69de29..0000000
--- a/client/modules/__init__.py
+++ /dev/null
diff --git a/client/modules/app_utils.py b/client/modules/app_utils.py
deleted file mode 100644
index 7e39cbf..0000000
--- a/client/modules/app_utils.py
+++ /dev/null
@@ -1,123 +0,0 @@
-import smtplib
-from email.MIMEText import MIMEText
-import urllib2
-import re
-import requests
-from pytz import timezone
-
-
-def sendEmail(SUBJECT, BODY, TO, FROM, SENDER, PASSWORD, SMTP_SERVER):
- """Sends an HTML email."""
- for body_charset in 'US-ASCII', 'ISO-8859-1', 'UTF-8':
- try:
- BODY.encode(body_charset)
- except UnicodeError:
- pass
- else:
- break
- msg = MIMEText(BODY.encode(body_charset), 'html', body_charset)
- msg['From'] = SENDER
- msg['To'] = TO
- msg['Subject'] = SUBJECT
-
- SMTP_PORT = 587
- session = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
- session.starttls()
- session.login(FROM, PASSWORD)
- session.sendmail(SENDER, TO, msg.as_string())
- session.quit()
-
-
-def emailUser(profile, SUBJECT="", BODY=""):
- """
- Sends an email.
-
- Arguments:
- profile -- contains information related to the user (e.g., email address)
- SUBJECT -- subject line of the email
- BODY -- body text of the email
- """
- def generateSMSEmail(profile):
- """Generates an email from a user's phone number based on their carrier."""
- if profile['carrier'] is None or not profile['phone_number']:
- return None
-
- return str(profile['phone_number']) + "@" + profile['carrier']
-
- if profile['prefers_email'] and profile['gmail_address']:
- # add footer
- if BODY:
- BODY = profile['first_name'] + \
- ",<br><br>Here are your top headlines:" + BODY
- BODY += "<br>Sent from your Jasper"
-
- recipient = profile['gmail_address']
- if profile['first_name'] and profile['last_name']:
- recipient = profile['first_name'] + " " + \
- profile['last_name'] + " <%s>" % recipient
- else:
- recipient = generateSMSEmail(profile)
-
- if not recipient:
- return False
-
- try:
- if 'mailgun' in profile:
- user = profile['mailgun']['username']
- password = profile['mailgun']['password']
- server = 'smtp.mailgun.org'
- else:
- user = profile['gmail_address']
- password = profile['gmail_password']
- server = 'smtp.gmail.com'
- sendEmail(SUBJECT, BODY, recipient, user,
- "Jasper <jasper>", password, server)
-
- return True
- except:
- return False
-
-
-def getTimezone(profile):
- """
- Returns the pytz timezone for a given profile.
-
- Arguments:
- profile -- contains information related to the user (e.g., email address)
- """
- try:
- return timezone(profile['timezone'])
- except:
- return None
-
-
-def generateTinyURL(URL):
- """
- Generates a compressed URL.
-
- Arguments:
- URL -- the original URL to-be compressed
- """
- target = "http://tinyurl.com/api-create.php?url=" + URL
- response = urllib2.urlopen(target)
- return response.read()
-
-
-def isNegative(phrase):
- """
- Returns True if the input phrase has a negative sentiment.
-
- Arguments:
- phrase -- the input phrase to-be evaluated
- """
- return bool(re.search(r'\b(no(t)?|don\'t|stop|end)\b', phrase, re.IGNORECASE))
-
-
-def isPositive(phrase):
- """
- Returns True if the input phrase has a positive sentiment.
-
- Arguments:
- phrase -- the input phrase to-be evaluated
- """
- return re.search(r'\b(sure|yes|yeah|go)\b', phrase, re.IGNORECASE)