mirror of
https://github.com/viq/NewsBlur.git
synced 2025-09-18 21:43:31 +00:00
Adding share keys and comment keys to redis, in order to distinguish between the two.
This commit is contained in:
parent
71ffc79680
commit
c0fa6b263e
6 changed files with 146 additions and 42 deletions
|
@ -51,45 +51,57 @@ class MSharedStory(mongo.Document):
|
|||
|
||||
r = redis.Redis(connection_pool=settings.REDIS_POOL)
|
||||
share_key = "S:%s:%s" % (self.story_feed_id, self.guid_hash)
|
||||
r.sadd(share_key, self.user_id)
|
||||
comment_key = "C:%s:%s" % (self.story_feed_id, self.guid_hash)
|
||||
if self.has_comments:
|
||||
r.sadd(share_key, self.user_id)
|
||||
r.sadd(comment_key, self.user_id)
|
||||
else:
|
||||
r.srem(share_key, self.user_id)
|
||||
r.srem(comment_key, self.user_id)
|
||||
|
||||
super(MSharedStory, self).save(*args, **kwargs)
|
||||
|
||||
author = MSocialProfile.objects.get(user_id=self.user_id)
|
||||
author.count()
|
||||
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
r = redis.Redis(connection_pool=settings.REDIS_POOL)
|
||||
share_key = "S:%s:%s" % (self.story_feed_id, self.guid_hash)
|
||||
r.srem(share_key, self.user_id)
|
||||
|
||||
super(MSharedStory, self).delete(*args, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def sync_redis(cls):
|
||||
r = redis.Redis(connection_pool=settings.REDIS_POOL)
|
||||
for story in cls.objects.all():
|
||||
share_key = "S:%s:%s" % (story.story_feed_id, story.guid_hash)
|
||||
comment_key = "C:%s:%s" % (story.story_feed_id, story.guid_hash)
|
||||
r.sadd(share_key, story.user_id)
|
||||
if story.has_comments:
|
||||
r.sadd(share_key, story.user_id)
|
||||
r.sadd(comment_key, story.user_id)
|
||||
else:
|
||||
r.srem(share_key, story.user_id)
|
||||
r.srem(comment_key, story.user_id)
|
||||
|
||||
def comments_with_author(self, full=False):
|
||||
def comments_with_author(self, compact=False, full=False):
|
||||
comments = {
|
||||
'user_id': self.user_id,
|
||||
'comments': self.comments,
|
||||
'shared_date': relative_timesince(self.shared_date),
|
||||
}
|
||||
if full:
|
||||
if full or compact:
|
||||
author = MSocialProfile.objects.get(user_id=self.user_id)
|
||||
comments['author'] = author.to_json()
|
||||
comments['author'] = author.to_json(compact=compact, full=full)
|
||||
return comments
|
||||
|
||||
@classmethod
|
||||
def stories_with_comments(cls, stories, user):
|
||||
r = redis.Redis(connection_pool=settings.REDIS_POOL)
|
||||
friend_key = "F:%s:F" % (user.pk)
|
||||
for story in stories:
|
||||
if story['comment_count']:
|
||||
share_key = "S:%s:%s" % (story['story_feed_id'], story['guid_hash'])
|
||||
friend_key = "F:%s:F" % (user.pk)
|
||||
friends_with_comments = r.sinter(share_key, friend_key)
|
||||
comment_key = "C:%s:%s" % (story['story_feed_id'], story['guid_hash'])
|
||||
friends_with_comments = r.sinter(comment_key, friend_key)
|
||||
shared_stories = []
|
||||
if friends_with_comments:
|
||||
params = {
|
||||
'story_guid': story['id'],
|
||||
|
@ -97,11 +109,23 @@ class MSharedStory(mongo.Document):
|
|||
'user_id__in': friends_with_comments,
|
||||
}
|
||||
shared_stories = cls.objects.filter(**params)
|
||||
story['comments'] = []
|
||||
for shared_story in shared_stories:
|
||||
story['comments'].append(shared_story.comments_with_author())
|
||||
story['comment_count_public'] = story['comment_count'] - len(shared_stories)
|
||||
story['comment_count_shared'] = len(shared_stories)
|
||||
story['comments'] = []
|
||||
for shared_story in shared_stories:
|
||||
story['comments'].append(shared_story.comments_with_author(compact=True))
|
||||
story['comment_count_public'] = story['comment_count'] - len(shared_stories)
|
||||
story['comment_count_friends'] = len(shared_stories)
|
||||
if story['share_count']:
|
||||
share_key = "S:%s:%s" % (story['story_feed_id'], story['guid_hash'])
|
||||
friends_with_shares = r.sinter(share_key, friend_key)
|
||||
profiles = []
|
||||
if friends_with_shares:
|
||||
profiles = MSocialProfile.objects.filter(user_id__in=friends_with_shares)
|
||||
story['shared_by_friends'] = []
|
||||
for profile in profiles:
|
||||
story['shared_by_friends'].append(profile.to_json(compact=True))
|
||||
story['share_count_public'] = story['share_count'] - len(profiles)
|
||||
story['share_count_friends'] = len(profiles)
|
||||
|
||||
return stories
|
||||
|
||||
|
||||
|
@ -154,19 +178,26 @@ class MSocialProfile(mongo.Document):
|
|||
follower_key = "F:%s:f" % (user_id)
|
||||
r.sadd(follower_key, profile.user_id)
|
||||
|
||||
def to_json(self, full=False):
|
||||
params = {
|
||||
'user_id': self.user_id,
|
||||
'username': self.username,
|
||||
'photo_url': self.photo_url,
|
||||
'bio': self.bio,
|
||||
'location': self.location,
|
||||
'website': self.website,
|
||||
'subscription_count': self.subscription_count,
|
||||
'shared_stories_count': self.shared_stories_count,
|
||||
'following_count': self.following_count,
|
||||
'follower_count': self.follower_count,
|
||||
}
|
||||
def to_json(self, compact=False, full=False):
|
||||
if compact:
|
||||
params = {
|
||||
'user_id': self.user_id,
|
||||
'username': self.username,
|
||||
'photo_url': self.photo_url
|
||||
}
|
||||
else:
|
||||
params = {
|
||||
'user_id': self.user_id,
|
||||
'username': self.username,
|
||||
'photo_url': self.photo_url,
|
||||
'bio': self.bio,
|
||||
'location': self.location,
|
||||
'website': self.website,
|
||||
'subscription_count': self.subscription_count,
|
||||
'shared_stories_count': self.shared_stories_count,
|
||||
'following_count': self.following_count,
|
||||
'follower_count': self.follower_count,
|
||||
}
|
||||
if full:
|
||||
params['photo_service'] = self.photo_service
|
||||
params['following_user_ids'] = self.following_user_ids
|
||||
|
|
|
@ -22,10 +22,11 @@ from vendor import tweepy
|
|||
def story_comments(request):
|
||||
feed_id = int(request.POST['feed_id'])
|
||||
story_id = request.POST['story_id']
|
||||
full = bool(request.POST.get('full', True))
|
||||
full = request.POST.get('full', False)
|
||||
compact = request.POST.get('compact', False)
|
||||
|
||||
shared_stories = MSharedStory.objects.filter(story_feed_id=feed_id, story_guid=story_id)
|
||||
comments = [s.comments_with_author(full=full) for s in shared_stories]
|
||||
comments = [s.comments_with_author(compact=compact, full=full) for s in shared_stories]
|
||||
|
||||
return {'comments': comments}
|
||||
|
||||
|
|
|
@ -1984,6 +1984,10 @@ background: transparent;
|
|||
padding: 1px 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
#story_pane .NB-story-comments-shares-teaser-wrapper {
|
||||
border-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
#story_pane .NB-story-comments-public-teaser {
|
||||
background-color: #B1B6B4;
|
||||
color: white;
|
||||
|
@ -1992,6 +1996,21 @@ background: transparent;
|
|||
text-transform: uppercase;
|
||||
font-size: 10px;
|
||||
padding: 2px 12px;
|
||||
overflow: hidden;
|
||||
-webkit-transition: all .12s ease-out;
|
||||
-moz-transition: all .12s ease-out;
|
||||
-o-transition: all .12s ease-out;
|
||||
-ms-transition: all .12s ease-out;
|
||||
}
|
||||
#story_pane .NB-story-comments-shares-teaser {
|
||||
background-color: #E3E9E7;
|
||||
color: #202020;
|
||||
text-shadow: 0 1px 0 #FFF;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
font-size: 10px;
|
||||
padding: 2px 12px;
|
||||
overflow: hidden;
|
||||
-webkit-transition: all .12s ease-out;
|
||||
-moz-transition: all .12s ease-out;
|
||||
-o-transition: all .12s ease-out;
|
||||
|
@ -2006,6 +2025,23 @@ background: transparent;
|
|||
padding: 0 1px;
|
||||
font-size: 12px;
|
||||
}
|
||||
#story_pane .NB-story-share-profiles {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#story_pane .NB-story-share-profile {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
}
|
||||
#story_pane .NB-story-share-profile .NB-user-avatar {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
float: left;
|
||||
}
|
||||
#story_pane .NB-story-share-profile .NB-user-username {
|
||||
float: left;
|
||||
}
|
||||
#story_pane .NB-story-comment .NB-story-comment-content {
|
||||
clear: both;
|
||||
padding: 0 0 6px 0;
|
||||
|
|
|
@ -968,7 +968,8 @@ NEWSBLUR.AssetModel.Reader.prototype = {
|
|||
load_public_story_comments: function(story_id, feed_id, callback) {
|
||||
this.make_request('/social/comments', {
|
||||
'story_id': story_id,
|
||||
'feed_id': feed_id
|
||||
'feed_id': feed_id,
|
||||
'compact': true
|
||||
}, callback);
|
||||
},
|
||||
|
||||
|
|
|
@ -3730,7 +3730,7 @@
|
|||
])
|
||||
]),
|
||||
$.make('div', { className: 'NB-feed-story-content' }, this.make_story_content(story.story_content)),
|
||||
(story.comment_count && $.make('div', { className: 'NB-feed-story-comments' }, this.make_story_share_comments(story))),
|
||||
((story.comment_count || story.share_count) && $.make('div', { className: 'NB-feed-story-comments' }, this.make_story_share_comments(story))),
|
||||
$.make('div', { className: 'NB-feed-story-sideoptions-container' }, [
|
||||
$.make('div', { className: 'NB-sideoption NB-feed-story-train' }, [
|
||||
$.make('div', { className: 'NB-sideoption-icon'}, ' '),
|
||||
|
@ -4080,12 +4080,33 @@
|
|||
// ==================
|
||||
|
||||
make_story_share_comments: function(story) {
|
||||
var self = this;
|
||||
var $comments = $([]);
|
||||
console.log(["story", story]);
|
||||
console.log(["story shared: ", story]);
|
||||
|
||||
// var $share = $.make('div', { className: 'NB-story-comments-sharers' }, 'Shared by: ');
|
||||
|
||||
if (story.comment_count_shared) {
|
||||
if (story.share_count) {
|
||||
var $public_teaser = $.make('div', { className: 'NB-story-comments-shares-teaser-wrapper' }, [
|
||||
$.make('div', { className: 'NB-story-comments-shares-teaser' }, [
|
||||
(story.share_count && $.make('div', { className: 'NB-right' }, [
|
||||
'Shared by ',
|
||||
$.make('b', story.share_count),
|
||||
' ',
|
||||
Inflector.pluralize('person', story.share_count)
|
||||
])),
|
||||
(story.share_count_friends && $.make('span', [
|
||||
'Shared by: ',
|
||||
$.make('div', { className: 'NB-story-share-profiles' },
|
||||
_.map(story.shared_by_friends, function(profile) { return self.make_story_share_profile(profile); })
|
||||
)
|
||||
]))
|
||||
])
|
||||
]);
|
||||
$comments.push($public_teaser);
|
||||
}
|
||||
|
||||
if (story.comment_count_friends) {
|
||||
_.each(story.comments, _.bind(function(comment) {
|
||||
var $comment = this.make_story_share_comment(comment);
|
||||
$comments.push($comment);
|
||||
|
@ -4110,11 +4131,8 @@
|
|||
},
|
||||
|
||||
make_story_share_comment: function(comment) {
|
||||
console.log(["make_story_share_comment", comment, this.model.following_profiles, this.model.following_profiles.find(comment.user_id)]);
|
||||
var user = this.model.following_profiles.find(comment.user_id);
|
||||
if (!user) {
|
||||
user = new NEWSBLUR.Models.User(comment.author);
|
||||
}
|
||||
console.log(["make_story_share_comment", comment]);
|
||||
var user = new NEWSBLUR.Models.User(comment.author);
|
||||
|
||||
var $comment = $.make('div', { className: 'NB-story-comment' }, [
|
||||
$.make('div', { className: 'NB-user-avatar' }, [
|
||||
|
@ -4130,6 +4148,19 @@
|
|||
return $comment;
|
||||
},
|
||||
|
||||
make_story_share_profile: function(profile) {
|
||||
var user = new NEWSBLUR.Models.User(profile);
|
||||
|
||||
var $profile = $.make('div', { className: 'NB-story-share-profile' }, [
|
||||
$.make('div', { className: 'NB-user-avatar' }, [
|
||||
$.make('img', { src: user.get('photo_url') })
|
||||
]),
|
||||
$.make('div', { className: 'NB-user-username' }, user.get('username'))
|
||||
]);
|
||||
|
||||
return $profile;
|
||||
},
|
||||
|
||||
load_public_story_comments: function(story_id) {
|
||||
var story = this.model.get_story(story_id);
|
||||
this.model.load_public_story_comments(story_id, story.story_feed_id, _.bind(function(data) {
|
||||
|
|
|
@ -116,6 +116,7 @@ def relative_timesince(value):
|
|||
return u''
|
||||
|
||||
chunks = (
|
||||
(60 * 60 * 24, lambda n: ungettext('day', 'days', n)),
|
||||
(60 * 60, lambda n: ungettext('hour', 'hours', n)),
|
||||
(60, lambda n: ungettext('minute', 'minutes', n))
|
||||
)
|
||||
|
@ -153,7 +154,7 @@ def format_relative_date(date, future=False):
|
|||
'' if future else 'ago')
|
||||
elif datetime.timedelta(minutes=60) <= diff < datetime.timedelta(minutes=90):
|
||||
return "1 hour %s" % ('' if future else 'ago')
|
||||
elif diff >= datetime.timedelta(minutes=90):
|
||||
elif diff < datetime.timedelta(hours=24):
|
||||
dec = (diff.seconds / 60 + 15) % 60
|
||||
if dec >= 30:
|
||||
return "%s.5 hours %s" % ((((diff.seconds / 60) + 15) / 60),
|
||||
|
@ -161,7 +162,10 @@ def format_relative_date(date, future=False):
|
|||
else:
|
||||
return "%s hours %s" % ((((diff.seconds / 60) + 15) / 60),
|
||||
'' if future else 'ago')
|
||||
|
||||
else:
|
||||
days = ((diff.seconds / 60) / 60 / 24)
|
||||
return "%s day%s %s" % (days, '' if days == 1 else 's', '' if future else 'ago')
|
||||
|
||||
def add_object_to_folder(obj, folder, folders, parent='', added=False):
|
||||
if not folder and not parent and obj not in folders:
|
||||
folders.append(obj)
|
||||
|
|
Loading…
Add table
Reference in a new issue