Merge branch 'master' of github.com:samuelclay/NewsBlur

* 'master' of github.com:samuelclay/NewsBlur:
  Renaming static.tar to static.tgz to reflect its gzippedness.
  Fixing ghost unread counts on folder when last story in a feed is read.
  Fixing link to scipy-superpack. (Thanks @boursier)
  Handling negative feature page bug. Also showing server errors on bad emails.
  Fixing missing username in dupe USF.
  Handling errors on river in client. Also fixing starred stories.
  Suppressing error on starring an already starred story.
  Re-enabling mobile site. /m/
  Fixing typo in aggressive feed fetching.
  No longer being aggressive about finding a feed's correct address if it returns a 400 or 500 error code, unless it is still the first run or an exception refresh.
  Adding SSL to nginx conf.
This commit is contained in:
Samuel Clay 2012-01-23 20:15:07 -08:00
commit 9fa63ab8a2
10 changed files with 83 additions and 47 deletions

View file

@ -84,7 +84,7 @@ command will automatically do this for you, but Mac OS X needs to have it instal
Not the easiest to get installed. If you are running Mac OS X, you have a few options:
* Use the [Superpack by Chris Fonnesbeck](http://stronginference.com/scipy-superpack/)
* Use the [Superpack by Chris Fonnesbeck](http://fonnesbeck.github.com/ScipySuperpack/)
* Use MacPorts: `sudo port install py26-numpy py26-scipy`
* Install from source (grueling): [http://www.scipy.org/Download](http://www.scipy.org/Download)

View file

@ -20,5 +20,5 @@ class UserSubscriptionManager(models.Manager):
kwargs['feed'] = feed
elif 'feed__pk' in kwargs:
kwargs['feed__pk'] = feed.pk
logging.debug(" ---> [%s] ~BRFound dupe UserSubscription: ~SB%s (%s)" % (kwargs['user'].username, feed, feed_id))
logging.debug(" ---> [%s] ~BRFound dupe UserSubscription: ~SB%s (%s)" % (getattr(kwargs.get('user'), 'username'), feed, feed_id))
return super(UserSubscriptionManager, self).get(*args, **kwargs)

View file

@ -1,5 +1,6 @@
import datetime
import time
import boto
from django.shortcuts import render_to_response, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.template import RequestContext
@ -561,7 +562,7 @@ def load_river_stories(request):
try:
mstories = [story.value for story in mstories if story and story.value]
except OperationFailure, e:
raise e
return dict(error=str(e), code=-1)
mstories = sorted(mstories, cmp=lambda x, y: cmp(story_score(y, days_to_keep_unreads),
story_score(x, days_to_keep_unreads)))
@ -927,7 +928,7 @@ def add_feature(request):
@json.json_view
def load_features(request):
user = get_user(request)
page = int(request.REQUEST.get('page', 0))
page = max(int(request.REQUEST.get('page', 0)), 0)
logging.user(request, "~FBBrowse features: ~SBPage #%s" % (page+1))
features = Feature.objects.all()[page*3:(page+1)*3+1].values()
features = [{
@ -1065,8 +1066,14 @@ def mark_story_as_starred(request):
if k is not None and v is not None])
now = datetime.datetime.now()
story_values = dict(user_id=request.user.pk, starred_date=now, **story_db)
MStarredStory.objects.create(**story_values)
logging.user(request, "~FCStarring: ~SB%s" % (story[0].story_title[:50]))
starred_story, created = MStarredStory.objects.get_or_create(
story_guid=story_values.pop('story_guid'),
user_id=story_values.pop('user_id'),
defaults=story_values)
if created:
logging.user(request, "~FCStarring: ~SB%s" % (story[0].story_title[:50]))
else:
logging.user(request, "~FC~BRAlready stared:~SN~FC ~SB%s" % (story[0].story_title[:50]))
else:
code = -1
@ -1077,7 +1084,7 @@ def mark_story_as_starred(request):
def mark_story_as_unstarred(request):
code = 1
story_id = request.POST['story_id']
starred_story = MStarredStory.objects(user_id=request.user.pk, story_guid=story_id)
if starred_story:
logging.user(request, "~FCUnstarring: ~SB%s" % (starred_story[0].story_title[:50]))
@ -1124,7 +1131,11 @@ def send_story_email(request):
cc=['%s <%s>' % (from_name, from_email)],
headers={'Reply-To': '%s <%s>' % (from_name, from_email)})
msg.attach_alternative(html, "text/html")
msg.send()
try:
msg.send()
except boto.ses.connection.ResponseError, e:
code = -1
message = "Email error: %s" % str(e)
logging.user(request, '~BMSharing story by email: ~FY~SB%s~SN~BM~FY/~SB%s' %
(story['story_title'][:50], feed.feed_title[:50]))

View file

@ -73,19 +73,19 @@ javascripts:
- media/js/newsblur/reader_tutorial.js
- media/js/newsblur/about.js
- media/js/newsblur/faq.js
# mobile:
# - media/js/jquery-1.7.js
# - media/js/mobile/jquery.mobile-1.0b1.js
# - media/js/jquery.ajaxmanager.3.js
# - media/js/underscore.js
# - media/js/underscore.string.js
# - media/js/inflector.js
# - media/js/jquery.json.js
# - media/js/jquery.easing.js
# - media/js/jquery.newsblur.js
# - media/js/newsblur/reader_utils.js
# - media/js/newsblur/assetmodel.js
# - media/js/mobile/newsblur/mobile_workspace.js
mobile:
- media/js/jquery-1.7.1.js
- media/js/mobile/jquery.mobile-1.0b1.js
- media/js/jquery.ajaxmanager.3.js
- media/js/underscore.js
- media/js/underscore.string.js
- media/js/inflector.js
- media/js/jquery.json.js
- media/js/jquery.easing.js
- media/js/jquery.newsblur.js
- media/js/newsblur/reader_utils.js
- media/js/newsblur/assetmodel.js
- media/js/mobile/newsblur/mobile_workspace.js
paypal:
- media/js/newsblur/paypal_return.js
bookmarklet:
@ -104,6 +104,9 @@ stylesheets:
- media/css/jquery-ui/jquery.theme.css
- media/css/jquery.tipsy.css
- media/css/*.css
mobile:
- media/css/mobile/jquery.mobile-1.0b1.css
- media/css/mobile/mobile.css
bookmarklet:
- media/css/bookmarklet/reset.css
- media/css/modals.css

View file

@ -1,24 +1,31 @@
server {
server_name newsblur.com;
rewrite ^(.*) http://www.newsblur.com$1 permanent;
rewrite ^(.*) https://www.newsblur.com$1 permanent;
}
upstream app_server {
server 127.0.0.1:8000 fail_timeout=10 max_fails=3 ;
server app02.newsblur.com:80 fail_timeout=10 max_fails=3;
# server db01.newsblur.com:80 fail_timeout=10 max_fails=3 down;
server app02.newsblur.com:80 fail_timeout=10 max_fails=3 down;
}
# limit_req_zone $remote_addr zone=one:10m rate=200r/m;
# limit_req zone=one burst=200 nodelay;
server {
listen 80;
server_name www.newsblur.com;
rewrite ^ https://$server_name$request_uri? permanent;
}
server {
listen 80 default;
listen 443;
ssl on;
ssl_certificate /home/sclay/newsblur/config/certificates/newsblur_cert.crt;
ssl_certificate_key /home/sclay/newsblur/config/certificates/newsblur_cert.crt;
client_max_body_size 4M;
server_name www.newsblur.com;
if ($host = 'newsblur.com') {
rewrite ^/(.*)$ http://www.newsblur.com/$1 permanent;
rewrite ^/(.*)$ https://www.newsblur.com/$1 permanent;
}
error_page 503 @maintenance;

10
fabfile.py vendored
View file

@ -149,15 +149,15 @@ def kill_celery():
def compress_assets():
local('jammit -c assets.yml --base-url http://www.newsblur.com --output static')
local('tar -czf static.tar static/*')
local('tar -czf static.tgz static/*')
def transfer_assets():
put('static.tar', '%s/static/' % env.NEWSBLUR_PATH)
run('tar -xzf static/static.tar')
run('rm -f static/static.tar')
put('static.tgz', '%s/static/' % env.NEWSBLUR_PATH)
run('tar -xzf static/static.tgz')
run('rm -f static/static.tgz')
def cleanup_assets():
local('rm -f static.tar')
local('rm -f static.tgz')
# ===========
# = Backups =

View file

@ -87,8 +87,10 @@ NEWSBLUR.AssetModel.Reader.prototype = {
},
success: function(o) {
// NEWSBLUR.log(['make_request 1', o]);
if ($.isFunction(callback)) {
if (o && o.code < 0 && error_callback) {
error_callback(o);
} else if ($.isFunction(callback)) {
callback(o);
}
},

View file

@ -2022,7 +2022,7 @@
$('.task_view_page', this.$s.$taskbar).addClass('NB-disabled');
var explicit_view_setting = this.model.view_setting(this.active_feed);
if (!explicit_view_setting) {
if (!explicit_view_setting || explicit_view_setting == 'page') {
explicit_view_setting = 'feed';
}
this.set_correct_story_view_for_feed(this.active_feed, explicit_view_setting);
@ -2542,7 +2542,8 @@
}, 400);
});
if (this.model.preference('folder_counts') || !$feed.is(':visible')) {
if (this.model.preference('folder_counts') ||
$feed.parents('li.folder').filter('.NB-folder-collapsed').length) {
var $folder_title = $feed.closest('li.folder:visible').children('.folder_title');
var $children = $folder_title.closest('li.folder').children('ul.folder, .feed');
this.show_collapsed_folder_count($folder_title, $children);
@ -5504,8 +5505,9 @@
$module.addClass('NB-loading');
if (direction == -1 && !this.counts['feature_page']) {
if (direction == -1 && this.counts['feature_page'] <= 0) {
$module.removeClass('NB-loading');
this.counts['feature_page'] = 0;
return;
}
if (direction == 1 && this.flags['features_last_page']) {

View file

@ -122,8 +122,14 @@ NEWSBLUR.ReaderSendEmail.prototype = _.extend({}, NEWSBLUR.Modal.prototype, {
error: function(data) {
var $error = $('.NB-modal-error', this.$modal);
var $save = $('input[type=submit]', this.$modal);
$error.show();
$error.text("There was a issue on the backend with sending your email. Sorry about this! It has been noted and will be fixed soon. You should probably send this manually now.");
if (!data) {
$error.text("There was a issue on the backend with sending your email. Sorry about this! It has been noted and will be fixed soon. You should probably send this manually now.");
} else {
$('.NB-error', this.$modal).html(data.message).fadeIn(500);
}
$save.removeClass('NB-disabled').val('Send this story');
$('.NB-modal-loading', this.$modal).removeClass('NB-active');
},

View file

@ -11,7 +11,6 @@ from utils import feedparser
from utils.story_functions import pre_process_story
from utils import log as logging
from utils.feed_functions import timelimit, TimeoutError, mail_feed_error_to_admin, utf8encode
from utils.story_functions import bunch
import time
import datetime
import traceback
@ -96,7 +95,7 @@ class ProcessFeed:
def refresh_feed(self):
self.feed = Feed.objects.using('default').get(pk=self.feed_id)
def process(self, first_run=True):
def process(self):
""" Downloads and parses a feed.
"""
self.refresh_feed()
@ -109,7 +108,6 @@ class ProcessFeed:
# logging.debug(u' ---> [%d] Processing %s' % (self.feed.id, self.feed.feed_title))
self.feed.fetched_once = True
self.feed.last_update = datetime.datetime.utcnow()
if hasattr(self.fpf, 'status'):
@ -131,8 +129,9 @@ class ProcessFeed:
if self.fpf.status in (302, 301):
if not self.fpf.href.endswith('feedburner.com/atom.xml'):
self.feed.feed_address = self.fpf.href
if first_run:
if not self.feed.fetched_once:
self.feed.has_feed_exception = True
self.feed.fetched_once = True
self.feed.schedule_feed_fetch_immediately()
if not self.fpf.entries:
self.feed.save()
@ -140,8 +139,10 @@ class ProcessFeed:
return FEED_ERRHTTP, ret_values
if self.fpf.status >= 400:
logging.debug(" ---> [%-30s] HTTP Status code: %s. Checking address..." % (unicode(self.feed)[:30], self.fpf.status))
fixed_feed = self.feed.check_feed_link_for_feed_address()
logging.debug(" ---> [%-30s] HTTP Status code: %s.%s Checking address..." % (unicode(self.feed)[:30], self.fpf.status, ' Not' if self.feed.fetched_once else ''))
fixed_feed = None
if not self.feed.fetched_once:
fixed_feed = self.feed.check_feed_link_for_feed_address()
if not fixed_feed:
self.feed.save_feed_history(self.fpf.status, "HTTP Error")
else:
@ -153,7 +154,9 @@ class ProcessFeed:
if self.fpf.bozo and isinstance(self.fpf.bozo_exception, feedparser.NonXMLContentType):
logging.debug(" ---> [%-30s] Feed is Non-XML. %s entries.%s Checking address..." % (unicode(self.feed)[:30], len(self.fpf.entries), ' Not' if self.fpf.entries else ''))
if not self.fpf.entries:
fixed_feed = self.feed.check_feed_link_for_feed_address()
fixed_feed = None
if not self.feed.fetched_once:
fixed_feed = self.feed.check_feed_link_for_feed_address()
if not fixed_feed:
self.feed.save_feed_history(502, 'Non-xml feed', self.fpf.bozo_exception)
else:
@ -164,7 +167,9 @@ class ProcessFeed:
elif self.fpf.bozo and isinstance(self.fpf.bozo_exception, xml.sax._exceptions.SAXException):
logging.debug(" ---> [%-30s] Feed has SAX/XML parsing issues. %s entries.%s Checking address..." % (unicode(self.feed)[:30], len(self.fpf.entries), ' Not' if self.fpf.entries else ''))
if not self.fpf.entries:
fixed_feed = self.feed.check_feed_link_for_feed_address()
fixed_feed = None
if not self.feed.fetched_once:
fixed_feed = self.feed.check_feed_link_for_feed_address()
if not fixed_feed:
self.feed.save_feed_history(503, 'SAX Exception', self.fpf.bozo_exception)
else: