diff --git a/apps/profile/models.py b/apps/profile/models.py index 187968225..7dba40543 100644 --- a/apps/profile/models.py +++ b/apps/profile/models.py @@ -2,19 +2,23 @@ import datetime from django.db import models from django.db import IntegrityError from django.db.utils import DatabaseError -from django.contrib.auth.models import User from django.db.models.signals import post_save -from django.core.mail import mail_admins +from django.conf import settings from django.contrib.auth import authenticate +from django.contrib.auth.models import User +from django.core.mail import mail_admins +from django.core.mail import EmailMultiAlternatives +from django.template.loader import render_to_string +from celery.task import Task from apps.reader.models import UserSubscription from apps.rss_feeds.models import Feed -from paypal.standard.ipn.signals import subscription_signup from apps.rss_feeds.tasks import NewFeeds -from celery.task import Task from utils import log as logging -from vendor.timezones.fields import TimeZoneField from utils.user_functions import generate_secret_token - +from vendor.timezones.fields import TimeZoneField +from vendor.paypal.standard.ipn.signals import subscription_signup + + class Profile(models.Model): user = models.OneToOneField(User, unique=True, related_name="profile") is_premium = models.BooleanField(default=False) @@ -30,7 +34,7 @@ class Profile(models.Model): secret_token = models.CharField(max_length=12, blank=True, null=True) def __unicode__(self): - return "%s" % self.user + return "%s <%s> (Premium: %s)" % (self.user, self.user.email, self.is_premium) def save(self, *args, **kwargs): if not self.secret_token: @@ -95,6 +99,34 @@ NewsBlur""" % {'user': self.user.username, 'feeds': subs.count()} if stale_feeds: stale_feeds = list(set([f.feed.pk for f in stale_feeds])) self.queue_new_feeds(new_feeds=stale_feeds) + + def mail_new_account(self): + if not self.user.email: + return + + user = self.user + text = render_to_string('mail/email_new_account.txt', locals()) + html = render_to_string('mail/email_new_account.xhtml', locals()) + subject = "Welcome to NewsBlur, %s" % (self.user.username) + msg = EmailMultiAlternatives(subject, text, + from_email='NewsBlur <%s>' % settings.HELLO_EMAIL, + to=['%s <%s>' % (user, user.email)]) + msg.attach_alternative(html, "text/html") + msg.send() + + def mail_new_premium(self): + if not self.user.email: + return + + user = self.user + text = render_to_string('mail/email_new_premium.txt', locals()) + html = render_to_string('mail/email_new_premium.xhtml', locals()) + subject = "Thanks for going premium on NewsBlur!" + msg = EmailMultiAlternatives(subject, text, + from_email='NewsBlur <%s>' % settings.HELLO_EMAIL, + to=['%s <%s>' % (user, user.email)]) + msg.attach_alternative(html, "text/html") + msg.send() def create_profile(sender, instance, created, **kwargs): diff --git a/apps/rss_feeds/models.py b/apps/rss_feeds/models.py index 4eb4f97fb..2aa7de35d 100644 --- a/apps/rss_feeds/models.py +++ b/apps/rss_feeds/models.py @@ -8,7 +8,7 @@ import urllib from collections import defaultdict from operator import itemgetter from BeautifulSoup import BeautifulStoneSoup -from nltk.collocations import TrigramCollocationFinder, BigramCollocationFinder, TrigramAssocMeasures, BigramAssocMeasures +# from nltk.collocations import TrigramCollocationFinder, BigramCollocationFinder, TrigramAssocMeasures, BigramAssocMeasures from django.db import models from django.db import IntegrityError from django.core.cache import cache @@ -867,39 +867,39 @@ class Feed(models.Model): self.save() - def calculate_collocations_story_content(self, - collocation_measures=TrigramAssocMeasures, - collocation_finder=TrigramCollocationFinder): - stories = MStory.objects.filter(story_feed_id=self.pk) - story_content = ' '.join([s.story_content for s in stories if s.story_content]) - return self.calculate_collocations(story_content, collocation_measures, collocation_finder) - - def calculate_collocations_story_title(self, - collocation_measures=BigramAssocMeasures, - collocation_finder=BigramCollocationFinder): - stories = MStory.objects.filter(story_feed_id=self.pk) - story_titles = ' '.join([s.story_title for s in stories if s.story_title]) - return self.calculate_collocations(story_titles, collocation_measures, collocation_finder) - - def calculate_collocations(self, content, - collocation_measures=TrigramAssocMeasures, - collocation_finder=TrigramCollocationFinder): - content = re.sub(r'’', '\'', content) - content = re.sub(r'&', '&', content) - try: - content = unicode(BeautifulStoneSoup(content, - convertEntities=BeautifulStoneSoup.HTML_ENTITIES)) - except ValueError, e: - print "ValueError, ignoring: %s" % e - content = re.sub(r']*>', '', content) - content = re.split(r"[^A-Za-z-'&]+", content) - - finder = collocation_finder.from_words(content) - finder.apply_freq_filter(3) - best = finder.nbest(collocation_measures.pmi, 10) - phrases = [' '.join(phrase) for phrase in best] - - return phrases + # def calculate_collocations_story_content(self, + # collocation_measures=TrigramAssocMeasures, + # collocation_finder=TrigramCollocationFinder): + # stories = MStory.objects.filter(story_feed_id=self.pk) + # story_content = ' '.join([s.story_content for s in stories if s.story_content]) + # return self.calculate_collocations(story_content, collocation_measures, collocation_finder) + # + # def calculate_collocations_story_title(self, + # collocation_measures=BigramAssocMeasures, + # collocation_finder=BigramCollocationFinder): + # stories = MStory.objects.filter(story_feed_id=self.pk) + # story_titles = ' '.join([s.story_title for s in stories if s.story_title]) + # return self.calculate_collocations(story_titles, collocation_measures, collocation_finder) + # + # def calculate_collocations(self, content, + # collocation_measures=TrigramAssocMeasures, + # collocation_finder=TrigramCollocationFinder): + # content = re.sub(r'’', '\'', content) + # content = re.sub(r'&', '&', content) + # try: + # content = unicode(BeautifulStoneSoup(content, + # convertEntities=BeautifulStoneSoup.HTML_ENTITIES)) + # except ValueError, e: + # print "ValueError, ignoring: %s" % e + # content = re.sub(r']*>', '', content) + # content = re.split(r"[^A-Za-z-'&]+", content) + # + # finder = collocation_finder.from_words(content) + # finder.apply_freq_filter(3) + # best = finder.nbest(collocation_measures.pmi, 10) + # phrases = [' '.join(phrase) for phrase in best] + # + # return phrases class Meta: db_table="feeds" diff --git a/media/img/reader/iphone_icon.png b/media/img/reader/iphone_icon.png new file mode 100644 index 000000000..8707a3d3b Binary files /dev/null and b/media/img/reader/iphone_icon.png differ diff --git a/settings.py b/settings.py index 052e60916..d25804a95 100644 --- a/settings.py +++ b/settings.py @@ -47,7 +47,7 @@ LOGIN_URL = '/reader/login' # Examples: "http://foo.com/media/", "/media/". ADMIN_MEDIA_PREFIX = '/media/admin/' SECRET_KEY = 'YOUR_SECRET_KEY' -EMAIL_BACKEND = 'django_ses.SESBackend' +EMAIL_BACKEND = 'seacucumber.backend.SESBackend' # =============== @@ -302,6 +302,7 @@ TEST_RUNNER = "utils.testrunner.TestRunner" SESSION_COOKIE_NAME = 'newsblur_sessionid' SESSION_COOKIE_AGE = 60*60*24*365*2 # 2 years SERVER_EMAIL = 'server@newsblur.com' +HELLO_EMAIL = 'hello@newsblur.com' # =========== # = Logging = @@ -322,6 +323,7 @@ INSTALLED_APPS = ( 'django.contrib.admin', 'django_extensions', 'djcelery', + 'seacucumber', 'compress', 'apps.rss_feeds', 'apps.reader', diff --git a/templates/mail/email_base.txt b/templates/mail/email_base.txt new file mode 100644 index 000000000..96162ffbb --- /dev/null +++ b/templates/mail/email_base.txt @@ -0,0 +1,19 @@ +{% block body %}{% endblock body %} + +----------------------------------------------------------------------------- + +Stay up to date and in touch with me, yr. developer, in a few different ways: + + * Follow @samuelclay on Twitter: http://twitter.com/samuelclay + * Follow @newsblur on Twitter: http://twitter.com/newsblur + * Follow the constantly evolving source code on GitHub: http://github.com/samuelclay + +{% block resources_header %}There are a few resources that would make sense to follow if you end up loving NewsBlur:{% endblock resources_header %} + + * Read the NewsBlur Blog: http://blog.newsblur.com + * Get support on NewsBlur's Get Satisfaction: http://getsatisfaction.com/newsblur + * Download the free NewsBlur iPhone app: http://itunes.com/newsblur + +----------------------------------------------------------------------------- + +Don't want to be notified about anything NewsBlur related? Opt-out of emails from NewsBlur: http://www.newsblur.com/optout. \ No newline at end of file diff --git a/templates/mail/email_base.xhtml b/templates/mail/email_base.xhtml index 551d832f6..84e3f3745 100644 --- a/templates/mail/email_base.xhtml +++ b/templates/mail/email_base.xhtml @@ -1,41 +1,66 @@ - + - - - - -
- - - - - - - - + + +
- {% block body %}{% endblock %} -
- - - - - + + +
- Logo_email_black - -

Don't want to be notified about Idea activity? Go to 'My Ac= -count' to update your email settings.
The Bold Italic and The B= -old Italic Logo are registered trademarks of The Bold Italic, 100 Pine St= -reet, Suite 250, San Francisco, CA 94111.

-
+ + - -
+
+ + + + + + + + + + + + +
+ NewsBlur +
+ + {% block body %}{% endblock %} + +

Stay up to date and in touch with me, yr. developer, in a few different ways:

+

+

+

+

{% block resources_header %}There are a few resources that would make sense to follow if you end up loving NewsBlur:{% endblock resources_header %}

+

+

+

+
+ + + + +
+

+ Don't want to be notified about anything NewsBlur related? Opt-out of emails from NewsBlur. +

+
+
+ NewsBlur +
-
-
- + diff --git a/templates/mail/email_new_account.txt b/templates/mail/email_new_account.txt new file mode 100644 index 000000000..f03e5fa22 --- /dev/null +++ b/templates/mail/email_new_account.txt @@ -0,0 +1,7 @@ +{% extends "mail/email_base.txt" %} + +{% block body %}Welcome to NewsBlur, {{ user.username }}. + +OK, firstly, thank you for trying out new software. It's not quite what you're used to, but you might find NewsBlur to be a perfect fit. There's a lot packed into a minimal interface. + +Spend a few days trying out NewsBlur. I hope you end up loving it.{% endblock body %} \ No newline at end of file diff --git a/templates/mail/email_new_account.xhtml b/templates/mail/email_new_account.xhtml index e4cf9ca8d..d9f2b59eb 100644 --- a/templates/mail/email_new_account.xhtml +++ b/templates/mail/email_new_account.xhtml @@ -1,25 +1,9 @@ -{% extends "email_base.xhtml" %} +{% extends "mail/email_base.xhtml" %} {% block body %} - - - - -
- NewsBlur -
-

Welcome, {{ user.name }}.

+

Welcome to NewsBlur, {{ user.username }}.

OK, firstly, thank you for trying out new software. It's not quite what you're used to, but you might find NewsBlur to be a perfect fit. There's a lot packed into a minimal interface.

Spend a few days trying out NewsBlur. I hope you end up loving it.

-

Stay up to date and in touch with me, yr. developer, in a few different ways:

-

-

-

-{% endblock %} \ No newline at end of file +{% endblock %} + +{% block resources_header %}There are a few resources that would make sense to follow if you end up loving NewsBlur:{% endblock resources_header %} \ No newline at end of file diff --git a/templates/mail/email_new_premium.txt b/templates/mail/email_new_premium.txt new file mode 100644 index 000000000..927085c9d --- /dev/null +++ b/templates/mail/email_new_premium.txt @@ -0,0 +1,3 @@ +{% extends "mail/email_base.txt" %} + +{% block body %}Thank you, thank you, thank you!{% endblock body %} \ No newline at end of file diff --git a/templates/mail/email_new_premium.xhtml b/templates/mail/email_new_premium.xhtml new file mode 100644 index 000000000..7cde7df0b --- /dev/null +++ b/templates/mail/email_new_premium.xhtml @@ -0,0 +1,8 @@ +{% extends "mail/email_base.xhtml" %} + +{% block body %} +

Thank you, thank you, thank you!

+

A huge thanks for going premium.

+{% endblock %} + +{% block resources_header %}Now that you're premium, you may want to follow a few resources:{% endblock resources_header %} \ No newline at end of file