Merge branch 'master' into dashboard_tweaks

This commit is contained in:
Samuel Clay 2011-04-03 11:56:28 -04:00
commit bc68345cc4
5 changed files with 105 additions and 34 deletions

View file

@ -5,6 +5,7 @@ import re
import mongoengine as mongo
import zlib
import urllib
from pprint import pprint
from collections import defaultdict
from operator import itemgetter
from BeautifulSoup import BeautifulStoneSoup
@ -13,6 +14,7 @@ from django.db import models
from django.db import IntegrityError
from django.core.cache import cache
from django.conf import settings
from django.core.mail import mail_admins
from mongoengine.queryset import OperationError
from mongoengine.base import ValidationError
from apps.rss_feeds.tasks import UpdateFeeds
@ -195,6 +197,12 @@ class Feed(models.Model):
feed_address = feed_address_from_link
if feed_address:
if feed_address.endswith('feedburner.com/atom.xml'):
message = """
%s - %s
""" % (feed_address, pprint(self.feed.__dict__))
mail_admins('Wierdo alert', message, fail_silently=True)
return False
try:
self.feed_address = feed_address
self.next_scheduled_update = datetime.datetime.utcnow()
@ -696,31 +704,32 @@ class Feed(models.Model):
return self.min_to_decay, random_factor
# Use stories per month to calculate next feed update
updates_per_day = self.stories_last_month / 30.0
updates_per_month = self.stories_last_month
# if updates_per_day < 1 and self.num_subscribers > 2:
# updates_per_day = 1
# 0 updates per day = 24 hours
# 1 subscriber:
# 1 update per day = 6 hours
# 2 updates = 3.5 hours
# 4 updates = 2 hours
# 10 updates = 1 hour
# 0 updates per month = 4 hours
# 1 update = 2 hours
# 2 updates = 1.5 hours
# 4 updates = 1 hours
# 10 updates = .5 hour
# 2 subscribers:
# 1 update per day = 4.5 hours
# 10 updates = 55 minutes
updates_per_day_delay = 3 * 60 / max(.25, ((max(0, self.active_subscribers)**.20)
* (updates_per_day**1.5)))
# 1 update per day = 1 hours
# 10 updates = 20 minutes
updates_per_day_delay = 2 * 60 / max(.25, ((max(0, self.active_subscribers)**.15)
* (updates_per_month**1.5)))
if self.premium_subscribers > 0:
updates_per_day_delay /= 6
updates_per_day_delay /= 5
# Lots of subscribers = lots of updates
# 144 hours for 0 subscribers.
# 24 hours for 1 subscriber.
# 7 hours for 2 subscribers.
# 3 hours for 3 subscribers.
# 25 min for 10 subscribers.
# 24 hours for 0 subscribers.
# 4 hours for 1 subscriber.
# .5 hours for 2 subscribers.
# .25 hours for 3 subscribers.
# 1 min for 10 subscribers.
subscriber_bonus = 4 * 60 / max(.167, max(0, self.active_subscribers)**3)
if self.premium_subscribers > 0:
subscriber_bonus /= 6
subscriber_bonus /= 5
slow_punishment = 0
if self.num_subscribers <= 1:
@ -730,7 +739,7 @@ class Feed(models.Model):
slow_punishment = 2 * self.last_load_time
elif self.last_load_time >= 200:
slow_punishment = 6 * self.last_load_time
total = max(6, int(updates_per_day_delay + subscriber_bonus + slow_punishment))
total = max(4, int(updates_per_day_delay + subscriber_bonus + slow_punishment))
# print "[%s] %s (%s-%s), %s, %s: %s" % (self, updates_per_day_delay, updates_per_day, self.num_subscribers, subscriber_bonus, slow_punishment, total)
random_factor = random.randint(0, total) / 4

7
config/ssh.conf Normal file
View file

@ -0,0 +1,7 @@
AddressFamily inet
TCPKeepAlive=yes
ServerAliveInterval=15
ServerAliveCountMax=6
StrictHostKeyChecking=no
Compression=yes
ForwardAgent=yes

19
fabfile.py vendored
View file

@ -16,6 +16,7 @@ from django.conf import settings as django_settings
env.user = 'sclay'
env.roledefs ={
'app': ['app01.newsblur.com'],
'web': ['www.newsblur.com'],
'db': ['db01.newsblur.com', 'db02.newsblur.com', 'db03.newsblur.com'],
'task': ['task01.newsblur.com', 'task02.newsblur.com'],
}
@ -26,6 +27,8 @@ env.roledefs ={
def app():
env.roles = ['app']
def web():
env.roles = ['web']
def db():
env.roles = ['db']
def task():
@ -35,26 +38,33 @@ def task():
# = Deploy =
# ==========
@roles('app')
@roles('web')
def deploy():
with cd('~/newsblur'):
run('git pull')
run('kill -HUP `cat logs/gunicorn.pid`')
run('curl -s http://www.newsblur.com > /dev/null')
with cd('media/js'):
run('rm *.gz')
run('for js in *-compressed-*.js; do gzip -9 $js -c > $js.gz; done;')
with cd('media/css'):
run('rm *.gz')
run('for css in *-compressed-*.css; do gzip -9 $css -c > $css.gz; done;')
@roles('app')
@roles('web')
def deploy_full():
with cd('~/newsblur'):
run('git pull')
run('./manage.py migrate')
run('sudo supervisorctl restart gunicorn')
@roles('app')
@roles('web')
def staging():
with cd('~/staging'):
run('git pull')
run('kill -HUP `cat /var/run/gunicorn/gunicorn_staging.pid`')
@roles('app')
@roles('web')
def staging_full():
with cd('~/staging'):
run('git pull')
@ -177,6 +187,7 @@ def setup_local_files():
put("config/toprc", "./.toprc")
put("config/zshrc", "./.zshrc")
put('config/gitconfig.txt', './.gitconfig')
put('config/ssh.conf', './.ssh/config')
def setup_libxml():
sudo('apt-get -y install libxml2-dev libxslt1-dev python-lxml')

View file

@ -1004,6 +1004,34 @@ background: transparent;
background-color: #00609f;
}
#story_titles .NB-feedbar .feed .NB-feedlist-manage-icon {
opacity: 0;
display: none;
position: absolute;
left: 4px;
top: 0px;
width: 20px;
height: 22px;
cursor: pointer;
background: transparent url('../img/icons/silk/bullet_arrow_right.png') no-repeat 3px 4px;
}
#story_titles .NB-feedbar .feed:hover .NB-feedlist-manage-icon {
display: block;
opacity: 1;
}
#story_titles .NB-feedbar .feed:hover .feed_favicon {
display: none;
}
#story_titles .NB-feedbar .folder_title .NB-feedlist-manage-icon {
background-position: 3px 5px;
}
#story_titles .NB-feedbar .feed .NB-feedlist-manage-icon:hover {
background: transparent url('../img/icons/silk/bullet_arrow_up.png') no-repeat 3px 4px;
}
#story_titles .NB-feedbar .feed .feed_counts {
width: 200px;
position: absolute;

View file

@ -272,7 +272,10 @@
this.locks.iframe_buster_buster = setInterval(function() {
if (prevent_bust > 0) {
prevent_bust -= 2;
if (!self.flags['iframe_view_loaded'] && !self.flags['iframe_view_not_busting'] && self.story_view == 'page' && self.active_feed) {
if (!self.flags['iframe_view_loaded'] &&
!self.flags['iframe_view_not_busting'] &&
_.contains(['page', 'story'], self.story_view) &&
self.active_feed) {
$('.task_view_feed').click();
$('.NB-feed-frame').attr('src', '');
window.top.location = '/reader/buster';
@ -2713,14 +2716,14 @@
}, 1000);
},
load_page_of_feed_stories: function() {
load_page_of_feed_stories: function(hide_loading) {
var $story_titles = this.$s.$story_titles;
var feed_id = $story_titles.data('feed_id');
var page = $story_titles.data('page');
if (!this.flags['opening_feed']) {
this.show_feedbar_loading();
if (!hide_loading) this.show_feedbar_loading();
$story_titles.data('page', page+1);
if (this.active_feed == 'starred') {
this.model.fetch_starred_stories(page+1,
@ -2743,10 +2746,10 @@
if (!$feedbar.length &&
($last.length == 0 ||
($('#story_titles').scrollTop() == 0 &&
$last.position().top + $last.height() < container_height))) {
if (this.counts['page_fill_outs'] < 8) {
$last.position().top + $last.height() + 13 < container_height))) {
if (this.counts['page_fill_outs'] < 6) {
this.counts['page_fill_outs'] += 1;
_.delay(_.bind(this.load_page_of_feed_stories, this), 250);
_.delay(_.bind(this.load_page_of_feed_stories, this, true), 250);
} else {
this.append_story_titles_endbar();
}
@ -3760,8 +3763,12 @@
return $manage_menu;
},
show_manage_menu: function(type, $item) {
show_manage_menu: function(type, $item, options) {
var self = this;
var options = _.extend({
'toplevel': false,
'inverse': false
}, options);
var $manage_menu_container = $('.NB-menu-manage-container');
// NEWSBLUR.log(['show_manage_menu', type, $item, $manage_menu_container.data('item'), $item && $item[0] == $manage_menu_container.data('item')]);
clearTimeout(this.flags.closed_manage_menu);
@ -3784,10 +3791,10 @@
var feed_id, inverse, story_id;
if (type == 'folder') {
feed_id = $('.folder_title_text', $item).eq(0).text();
inverse = $('.folder_title', $item).hasClass("NB-hover-inverse");
inverse = options.inverse || $('.folder_title', $item).hasClass("NB-hover-inverse");
} else if (type == 'feed') {
feed_id = $item && parseInt($item.attr('data-id'), 10);
inverse = $item.hasClass("NB-hover-inverse");
inverse = options.inverse || $item.hasClass("NB-hover-inverse");
} else if (type == 'story') {
story_id = $item.data('story_id') || $item.closest('.NB-feed-story').data('story_id');
if ($item.hasClass('story')) inverse = true;
@ -3795,7 +3802,7 @@
$('.NB-task-manage').tipsy('hide');
$('.NB-task-manage').tipsy('disable');
}
var toplevel = $item.hasClass("NB-toplevel") ||
var toplevel = options.toplevel || $item.hasClass("NB-toplevel") ||
$item.children('.folder_title').hasClass("NB-toplevel");
var $manage_menu = this.make_manage_menu(type, feed_id, story_id, inverse, $item);
$manage_menu_container.empty().append($manage_menu);
@ -4951,6 +4958,15 @@
self.collapse_folder($folder);
}
});
// ============
// = Feed Bar =
// ============
$.targetIs(e, { tagSelector: '.NB-feedbar .NB-feedlist-manage-icon' }, function($t, $p) {
e.preventDefault();
self.show_manage_menu('feed', $t.closest('.feed'), {inverse: true, toplevel: true});
});
$.targetIs(e, { tagSelector: '.NB-feedbar-mark-feed-read' }, function($t, $p){
e.preventDefault();
var feed_id = parseInt($t.closest('.feed').attr('data-id'), 10);
@ -5474,8 +5490,8 @@
var scroll_y = $('#story_titles').scrollTop();
// NEWSBLUR.log(['Story_titles Scroll', full_height, container_offset, visible_height, scroll_y]);
// Fudge factor is simply because it looks better at 3 pixels off.
if ((visible_height + 3) >= full_height) {
// Fudge factor is simply because it looks better at 13 pixels off.
if ((visible_height + 13) >= full_height) {
this.load_page_of_feed_stories();
}
}