mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-08-05 16:58:59 +00:00
Adding post to twitter/facebook during share. Also adding email for new followers, which includes common followers and common followings.
This commit is contained in:
parent
63988e9e15
commit
16781c6450
12 changed files with 234 additions and 24 deletions
|
@ -34,7 +34,8 @@ try:
|
||||||
from apps.rss_feeds.models import Feed, MFeedPage, DuplicateFeed, MStory, MStarredStory, FeedLoadtime
|
from apps.rss_feeds.models import Feed, MFeedPage, DuplicateFeed, MStory, MStarredStory, FeedLoadtime
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
from apps.social.models import MSharedStory, MSocialProfile, MSocialSubscription, MActivity
|
from apps.social.models import MSharedStory, MSocialProfile, MSocialServices
|
||||||
|
from apps.social.models import MSocialSubscription, MActivity
|
||||||
from apps.social.views import load_social_page
|
from apps.social.views import load_social_page
|
||||||
from utils import json_functions as json
|
from utils import json_functions as json
|
||||||
from utils.user_functions import get_user, ajax_login_required
|
from utils.user_functions import get_user, ajax_login_required
|
||||||
|
@ -223,6 +224,7 @@ def load_feeds(request):
|
||||||
}
|
}
|
||||||
social_feeds = MSocialSubscription.feeds(**social_params)
|
social_feeds = MSocialSubscription.feeds(**social_params)
|
||||||
social_profile = MSocialProfile.profile(user.pk)
|
social_profile = MSocialProfile.profile(user.pk)
|
||||||
|
social_services = MSocialServices.profile(user.pk)
|
||||||
|
|
||||||
user.profile.dashboard_date = datetime.datetime.now()
|
user.profile.dashboard_date = datetime.datetime.now()
|
||||||
user.profile.save()
|
user.profile.save()
|
||||||
|
@ -231,6 +233,7 @@ def load_feeds(request):
|
||||||
'feeds': feeds.values() if version == 2 else feeds,
|
'feeds': feeds.values() if version == 2 else feeds,
|
||||||
'social_feeds': social_feeds,
|
'social_feeds': social_feeds,
|
||||||
'social_profile': social_profile,
|
'social_profile': social_profile,
|
||||||
|
'social_services': social_services,
|
||||||
'folders': json.decode(folders.folders),
|
'folders': json.decode(folders.folders),
|
||||||
'starred_count': starred_count,
|
'starred_count': starred_count,
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ from vendor import facebook
|
||||||
from vendor import tweepy
|
from vendor import tweepy
|
||||||
from utils import log as logging
|
from utils import log as logging
|
||||||
from utils.feed_functions import relative_timesince
|
from utils.feed_functions import relative_timesince
|
||||||
|
from utils.story_functions import truncate_chars
|
||||||
from utils import json_functions as json
|
from utils import json_functions as json
|
||||||
|
|
||||||
RECOMMENDATIONS_LIMIT = 5
|
RECOMMENDATIONS_LIMIT = 5
|
||||||
|
@ -272,6 +273,15 @@ class MSocialProfile(mongo.Document):
|
||||||
return self.photo_url
|
return self.photo_url
|
||||||
return settings.MEDIA_URL + 'img/reader/default_profile_photo.png'
|
return settings.MEDIA_URL + 'img/reader/default_profile_photo.png'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def email_photo_url(self):
|
||||||
|
if self.photo_url:
|
||||||
|
if self.photo_url.startswith('//'):
|
||||||
|
self.photo_url = 'http:' + self.photo_url
|
||||||
|
return self.photo_url
|
||||||
|
domain = Site.objects.get_current().domain
|
||||||
|
return 'http://' + domain + settings.MEDIA_URL + 'img/reader/default_profile_photo.png'
|
||||||
|
|
||||||
def to_json(self, compact=False, include_follows=False, common_follows_with_user=None):
|
def to_json(self, compact=False, include_follows=False, common_follows_with_user=None):
|
||||||
# domain = Site.objects.get_current().domain
|
# domain = Site.objects.get_current().domain
|
||||||
domain = Site.objects.get_current().domain.replace('www', 'dev')
|
domain = Site.objects.get_current().domain.replace('www', 'dev')
|
||||||
|
@ -376,6 +386,9 @@ class MSocialProfile(mongo.Document):
|
||||||
socialsub.needs_unread_recalc = True
|
socialsub.needs_unread_recalc = True
|
||||||
socialsub.save()
|
socialsub.save()
|
||||||
|
|
||||||
|
from apps.social.tasks import EmailNewFollower
|
||||||
|
EmailNewFollower.delay(follower_user_id=self.user_id, followee_user_id=user_id)
|
||||||
|
|
||||||
def is_following_user(self, user_id):
|
def is_following_user(self, user_id):
|
||||||
return user_id in self.following_user_ids
|
return user_id in self.following_user_ids
|
||||||
|
|
||||||
|
@ -426,6 +439,43 @@ class MSocialProfile(mongo.Document):
|
||||||
|
|
||||||
return follows_inter, follows_diff
|
return follows_inter, follows_diff
|
||||||
|
|
||||||
|
def send_email_for_new_follower(self, follower_user_id):
|
||||||
|
user = User.objects.get(pk=self.user_id)
|
||||||
|
if not user.email or not user.profile.send_emails:
|
||||||
|
return
|
||||||
|
|
||||||
|
follower_profile = MSocialProfile.objects.get(user_id=follower_user_id)
|
||||||
|
photo_url = follower_profile.profile_photo_url
|
||||||
|
if 'graph.facebook.com' in photo_url:
|
||||||
|
follower_profile.photo_url = photo_url + '?type=large'
|
||||||
|
elif 'twimg' in photo_url:
|
||||||
|
follower_profile.photo_url = photo_url.replace('_normal', '')
|
||||||
|
|
||||||
|
common_followers, _ = self.common_follows(follower_user_id, direction='followers')
|
||||||
|
common_followings, _ = self.common_follows(follower_user_id, direction='following')
|
||||||
|
common_followers.remove(self.user_id)
|
||||||
|
common_followings.remove(self.user_id)
|
||||||
|
common_followers = MSocialProfile.profiles(common_followers)
|
||||||
|
common_followings = MSocialProfile.profiles(common_followings)
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'user': user,
|
||||||
|
'follower_profile': follower_profile,
|
||||||
|
'common_followers': common_followers,
|
||||||
|
'common_followings': common_followings,
|
||||||
|
}
|
||||||
|
|
||||||
|
text = render_to_string('mail/email_new_follower.txt', data)
|
||||||
|
html = render_to_string('mail/email_new_follower.xhtml', data)
|
||||||
|
subject = "%s is now following your Blurblog on NewsBlur!" % follower_profile.username
|
||||||
|
msg = EmailMultiAlternatives(subject, text,
|
||||||
|
from_email='NewsBlur <%s>' % settings.HELLO_EMAIL,
|
||||||
|
to=['%s <%s>' % (user.username, user.email)])
|
||||||
|
msg.attach_alternative(html, "text/html")
|
||||||
|
msg.send()
|
||||||
|
|
||||||
|
logging.user(user, "~BB~FM~SBSending email for new follower: %s" % follower_profile.username)
|
||||||
|
|
||||||
def save_feed_story_history_statistics(self):
|
def save_feed_story_history_statistics(self):
|
||||||
"""
|
"""
|
||||||
Fills in missing months between earlier occurances and now.
|
Fills in missing months between earlier occurances and now.
|
||||||
|
@ -870,6 +920,7 @@ class MSharedStory(mongo.Document):
|
||||||
story_permalink = mongo.StringField()
|
story_permalink = mongo.StringField()
|
||||||
story_guid = mongo.StringField(unique_with=('user_id',))
|
story_guid = mongo.StringField(unique_with=('user_id',))
|
||||||
story_tags = mongo.ListField(mongo.StringField(max_length=250))
|
story_tags = mongo.ListField(mongo.StringField(max_length=250))
|
||||||
|
posted_to_services = mongo.ListField(mongo.StringField(max_length=20))
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
'collection': 'shared_stories',
|
'collection': 'shared_stories',
|
||||||
|
@ -1130,6 +1181,40 @@ class MSharedStory(mongo.Document):
|
||||||
|
|
||||||
return stories, profiles
|
return stories, profiles
|
||||||
|
|
||||||
|
def blurblog_permalink(self):
|
||||||
|
profile = MSocialProfile.objects.get(user_id=self.user_id)
|
||||||
|
return "http://%s.%s/story/%s" % (
|
||||||
|
profile.username_slug,
|
||||||
|
Site.objects.get_current().domain.replace('www', 'dev'),
|
||||||
|
self.guid_hash[:6]
|
||||||
|
)
|
||||||
|
|
||||||
|
def generate_post_to_service_message(self):
|
||||||
|
message = self.comments
|
||||||
|
if not message or len(message) < 1:
|
||||||
|
message = self.story_title
|
||||||
|
|
||||||
|
message = truncate_chars(message, 116)
|
||||||
|
message += " " + self.blurblog_permalink()
|
||||||
|
print message
|
||||||
|
|
||||||
|
return message
|
||||||
|
|
||||||
|
def post_to_service(self, service):
|
||||||
|
if service in self.posted_to_services:
|
||||||
|
return
|
||||||
|
|
||||||
|
message = self.generate_post_to_service_message()
|
||||||
|
social_service = MSocialServices.objects.get(user_id=self.user_id)
|
||||||
|
if service == 'twitter':
|
||||||
|
posted = social_service.post_to_twitter(message)
|
||||||
|
elif service == 'facebook':
|
||||||
|
posted = social_service.post_to_facebook(message)
|
||||||
|
|
||||||
|
if posted:
|
||||||
|
self.posted_to_services.append(service)
|
||||||
|
self.save()
|
||||||
|
|
||||||
|
|
||||||
class MSocialServices(mongo.Document):
|
class MSocialServices(mongo.Document):
|
||||||
user_id = mongo.IntField()
|
user_id = mongo.IntField()
|
||||||
|
@ -1179,6 +1264,14 @@ class MSocialServices(mongo.Document):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def profile(cls, user_id):
|
||||||
|
try:
|
||||||
|
profile = cls.objects.get(user_id=user_id)
|
||||||
|
except cls.DoesNotExist:
|
||||||
|
return {}
|
||||||
|
return profile.to_json()
|
||||||
|
|
||||||
def twitter_api(self):
|
def twitter_api(self):
|
||||||
twitter_consumer_key = settings.TWITTER_CONSUMER_KEY
|
twitter_consumer_key = settings.TWITTER_CONSUMER_KEY
|
||||||
twitter_consumer_secret = settings.TWITTER_CONSUMER_SECRET
|
twitter_consumer_secret = settings.TWITTER_CONSUMER_SECRET
|
||||||
|
@ -1326,6 +1419,25 @@ class MSocialServices(mongo.Document):
|
||||||
profile.save()
|
profile.save()
|
||||||
return profile
|
return profile
|
||||||
|
|
||||||
|
def post_to_twitter(self, message):
|
||||||
|
try:
|
||||||
|
api = self.twitter_api()
|
||||||
|
api.update_status(status=message)
|
||||||
|
except tweepy.TweepError, e:
|
||||||
|
print e
|
||||||
|
return
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def post_to_facebook(self, message):
|
||||||
|
try:
|
||||||
|
api = self.facebook_api()
|
||||||
|
api.put_wall_post(message=message)
|
||||||
|
except facebook.GraphAPIError, e:
|
||||||
|
print e
|
||||||
|
return
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
class MInteraction(mongo.Document):
|
class MInteraction(mongo.Document):
|
||||||
user_id = mongo.IntField()
|
user_id = mongo.IntField()
|
||||||
|
|
|
@ -10,6 +10,7 @@ from django.conf import settings
|
||||||
from apps.rss_feeds.models import MStory, Feed, MStarredStory
|
from apps.rss_feeds.models import MStory, Feed, MStarredStory
|
||||||
from apps.social.models import MSharedStory, MSocialServices, MSocialProfile, MSocialSubscription, MCommentReply
|
from apps.social.models import MSharedStory, MSocialServices, MSocialProfile, MSocialSubscription, MCommentReply
|
||||||
from apps.social.models import MRequestInvite, MInteraction, MActivity
|
from apps.social.models import MRequestInvite, MInteraction, MActivity
|
||||||
|
from apps.social.tasks import PostToService
|
||||||
from apps.analyzer.models import MClassifierTitle, MClassifierAuthor, MClassifierFeed, MClassifierTag
|
from apps.analyzer.models import MClassifierTitle, MClassifierAuthor, MClassifierFeed, MClassifierTag
|
||||||
from apps.analyzer.models import apply_classifier_titles, apply_classifier_feeds, apply_classifier_authors, apply_classifier_tags
|
from apps.analyzer.models import apply_classifier_titles, apply_classifier_feeds, apply_classifier_authors, apply_classifier_tags
|
||||||
from apps.analyzer.models import get_classifiers_for_user, sort_classifiers_by_feed
|
from apps.analyzer.models import get_classifiers_for_user, sort_classifiers_by_feed
|
||||||
|
@ -239,6 +240,7 @@ def mark_story_as_shared(request):
|
||||||
story_id = request.POST['story_id']
|
story_id = request.POST['story_id']
|
||||||
comments = request.POST.get('comments', '')
|
comments = request.POST.get('comments', '')
|
||||||
source_user_id = request.POST.get('source_user_id')
|
source_user_id = request.POST.get('source_user_id')
|
||||||
|
post_to_services = request.POST.getlist('post_to_services')
|
||||||
|
|
||||||
story = MStory.objects(story_feed_id=feed_id, story_guid=story_id).limit(1).first()
|
story = MStory.objects(story_feed_id=feed_id, story_guid=story_id).limit(1).first()
|
||||||
if not story:
|
if not story:
|
||||||
|
@ -279,6 +281,11 @@ def mark_story_as_shared(request):
|
||||||
story = stories[0]
|
story = stories[0]
|
||||||
story['shared_comments'] = shared_story['comments'] or ""
|
story['shared_comments'] = shared_story['comments'] or ""
|
||||||
|
|
||||||
|
if post_to_services:
|
||||||
|
for service in post_to_services:
|
||||||
|
if service not in shared_story.posted_to_services:
|
||||||
|
PostToService.delay(shared_story_id=shared_story.id, service=service)
|
||||||
|
|
||||||
return {'code': code, 'story': story, 'user_profiles': profiles}
|
return {'code': code, 'story': story, 'user_profiles': profiles}
|
||||||
|
|
||||||
@ajax_login_required
|
@ajax_login_required
|
||||||
|
|
|
@ -2428,12 +2428,34 @@ background: transparent;
|
||||||
text-shadow: 0 1px 0 #F6F6F6;
|
text-shadow: 0 1px 0 #F6F6F6;
|
||||||
color: #202020;
|
color: #202020;
|
||||||
}
|
}
|
||||||
.NB-sideoption-share .NB-sideoption-share-optional {
|
.NB-sideoption-share .NB-sideoption-share-crosspost {
|
||||||
text-transform: uppercase;
|
margin-right: -4px;
|
||||||
|
}
|
||||||
|
.NB-sideoption-share .NB-sideoption-share-crosspost-twitter,
|
||||||
|
.NB-sideoption-share .NB-sideoption-share-crosspost-facebook {
|
||||||
float: right;
|
float: right;
|
||||||
color: #808080;
|
width: 16px;
|
||||||
font-size: 10px;
|
height: 16px;
|
||||||
text-shadow: 0 1px 0 #F6F6F6;
|
margin: 0 0 0 6px;
|
||||||
|
opacity: .4;
|
||||||
|
cursor: pointer;
|
||||||
|
-webkit-filter: grayscale(100%);
|
||||||
|
}
|
||||||
|
.NB-sideoption-share .NB-sideoption-share-crosspost-twitter:hover,
|
||||||
|
.NB-sideoption-share .NB-sideoption-share-crosspost-facebook:hover {
|
||||||
|
opacity: .7;
|
||||||
|
-webkit-filter: none;
|
||||||
|
}
|
||||||
|
.NB-sideoption-share .NB-sideoption-share-crosspost-twitter.NB-active,
|
||||||
|
.NB-sideoption-share .NB-sideoption-share-crosspost-facebook.NB-active {
|
||||||
|
opacity: 1;
|
||||||
|
-webkit-filter: none;
|
||||||
|
}
|
||||||
|
.NB-sideoption-share .NB-sideoption-share-crosspost-twitter {
|
||||||
|
background: transparent url('/media/embed/reader/twitter_icon.png') no-repeat 0 0;
|
||||||
|
}
|
||||||
|
.NB-sideoption-share .NB-sideoption-share-crosspost-facebook {
|
||||||
|
background: transparent url('/media/embed/reader/facebook_icon.png') no-repeat 0 0;
|
||||||
}
|
}
|
||||||
.NB-sideoption-share .NB-sideoption-share-comments {
|
.NB-sideoption-share .NB-sideoption-share-comments {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
@ -19,6 +19,7 @@ NEWSBLUR.AssetModel = Backbone.Router.extend({
|
||||||
this.friends = {};
|
this.friends = {};
|
||||||
this.profile = {};
|
this.profile = {};
|
||||||
this.user_profile = new NEWSBLUR.Models.User();
|
this.user_profile = new NEWSBLUR.Models.User();
|
||||||
|
this.social_services = {};
|
||||||
this.user_profiles = new NEWSBLUR.Collections.Users();
|
this.user_profiles = new NEWSBLUR.Collections.Users();
|
||||||
this.follower_profiles = new NEWSBLUR.Collections.Users();
|
this.follower_profiles = new NEWSBLUR.Collections.Users();
|
||||||
this.following_profiles = new NEWSBLUR.Collections.Users();
|
this.following_profiles = new NEWSBLUR.Collections.Users();
|
||||||
|
@ -216,7 +217,8 @@ NEWSBLUR.AssetModel = Backbone.Router.extend({
|
||||||
}, callback);
|
}, callback);
|
||||||
},
|
},
|
||||||
|
|
||||||
mark_story_as_shared: function(story_id, feed_id, comments, source_user_id, callback, error_callback) {
|
mark_story_as_shared: function(story_id, feed_id, comments, source_user_id, post_to_services,
|
||||||
|
callback, error_callback) {
|
||||||
var pre_callback = _.bind(function(data) {
|
var pre_callback = _.bind(function(data) {
|
||||||
if (data.user_profiles) {
|
if (data.user_profiles) {
|
||||||
this.add_user_profiles(data.user_profiles);
|
this.add_user_profiles(data.user_profiles);
|
||||||
|
@ -231,7 +233,8 @@ NEWSBLUR.AssetModel = Backbone.Router.extend({
|
||||||
story_id: story_id,
|
story_id: story_id,
|
||||||
feed_id: feed_id,
|
feed_id: feed_id,
|
||||||
comments: comments,
|
comments: comments,
|
||||||
source_user_id: source_user_id
|
source_user_id: source_user_id,
|
||||||
|
post_to_services: post_to_services
|
||||||
}, pre_callback, error_callback);
|
}, pre_callback, error_callback);
|
||||||
} else {
|
} else {
|
||||||
error_callback();
|
error_callback();
|
||||||
|
@ -292,6 +295,7 @@ NEWSBLUR.AssetModel = Backbone.Router.extend({
|
||||||
self.starred_count = subscriptions.starred_count;
|
self.starred_count = subscriptions.starred_count;
|
||||||
self.social_feeds.reset(subscriptions.social_feeds);
|
self.social_feeds.reset(subscriptions.social_feeds);
|
||||||
self.user_profile.set(subscriptions.social_profile);
|
self.user_profile.set(subscriptions.social_profile);
|
||||||
|
self.social_services = subscriptions.social_services;
|
||||||
|
|
||||||
if (!_.isEqual(self.favicons, {})) {
|
if (!_.isEqual(self.favicons, {})) {
|
||||||
self.feeds.each(function(feed) {
|
self.feeds.each(function(feed) {
|
||||||
|
|
|
@ -47,7 +47,8 @@ NEWSBLUR.Views.StoryDetailView = Backbone.View.extend({
|
||||||
model: this.model,
|
model: this.model,
|
||||||
el: this.el
|
el: this.el
|
||||||
}).template({
|
}).template({
|
||||||
story: this.model
|
story: this.model,
|
||||||
|
social_services: NEWSBLUR.assets.social_services
|
||||||
});
|
});
|
||||||
this.$el.html(this.template(params));
|
this.$el.html(this.template(params));
|
||||||
this.toggle_classes();
|
this.toggle_classes();
|
||||||
|
|
|
@ -4,6 +4,8 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
||||||
"click .NB-feed-story-share" : "toggle_feed_story_share_dialog",
|
"click .NB-feed-story-share" : "toggle_feed_story_share_dialog",
|
||||||
"click .NB-sideoption-share-save" : "mark_story_as_shared",
|
"click .NB-sideoption-share-save" : "mark_story_as_shared",
|
||||||
"click .NB-sideoption-share-unshare" : "mark_story_as_unshared",
|
"click .NB-sideoption-share-unshare" : "mark_story_as_unshared",
|
||||||
|
"click .NB-sideoption-share-crosspost-twitter" : "toggle_twitter",
|
||||||
|
"click .NB-sideoption-share-crosspost-facebook" : "toggle_facebook",
|
||||||
"keyup .NB-sideoption-share-comments" : "update_share_button_label"
|
"keyup .NB-sideoption-share-comments" : "update_share_button_label"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -13,7 +15,8 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
this.$el.html(this.template({
|
this.$el.html(this.template({
|
||||||
story: this.model
|
story: this.model,
|
||||||
|
social_services: NEWSBLUR.assets.social_services
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
@ -23,7 +26,14 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
||||||
<div class="NB-sideoption-share-wrapper">\
|
<div class="NB-sideoption-share-wrapper">\
|
||||||
<div class="NB-sideoption-share">\
|
<div class="NB-sideoption-share">\
|
||||||
<div class="NB-sideoption-share-wordcount"></div>\
|
<div class="NB-sideoption-share-wordcount"></div>\
|
||||||
<div class="NB-sideoption-share-optional">Optional</div>\
|
<div class="NB-sideoption-share-crosspost">\
|
||||||
|
<% if (social_services.twitter.twitter_uid) { %>\
|
||||||
|
<div class="NB-sideoption-share-crosspost-twitter"></div>\
|
||||||
|
<% } %>\
|
||||||
|
<% if (social_services.facebook.facebook_uid) { %>\
|
||||||
|
<div class="NB-sideoption-share-crosspost-facebook"></div>\
|
||||||
|
<% } %>\
|
||||||
|
</div>\
|
||||||
<div class="NB-sideoption-share-title">Comments:</div>\
|
<div class="NB-sideoption-share-title">Comments:</div>\
|
||||||
<textarea class="NB-sideoption-share-comments"><%= story.get("shared_comments") %></textarea>\
|
<textarea class="NB-sideoption-share-comments"><%= story.get("shared_comments") %></textarea>\
|
||||||
<div class="NB-menu-manage-story-share-save NB-modal-submit-green NB-sideoption-share-save NB-modal-submit-button">Share</div>\
|
<div class="NB-menu-manage-story-share-save NB-modal-submit-green NB-sideoption-share-save NB-modal-submit-button">Share</div>\
|
||||||
|
@ -41,6 +51,8 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
||||||
var $comment_input = this.$('.NB-sideoption-share-comments');
|
var $comment_input = this.$('.NB-sideoption-share-comments');
|
||||||
var $story_comments = this.$('.NB-feed-story-comments');
|
var $story_comments = this.$('.NB-feed-story-comments');
|
||||||
var $unshare_button = this.$('.NB-sideoption-share-unshare');
|
var $unshare_button = this.$('.NB-sideoption-share-unshare');
|
||||||
|
var $twitter_button = this.$('.NB-sideoption-share-crosspost-twitter');
|
||||||
|
var $facebook_button = this.$('.NB-sideoption-share-crosspost-facebook');
|
||||||
|
|
||||||
if (options.close ||
|
if (options.close ||
|
||||||
($sideoption.hasClass('NB-active') && !options.resize_open)) {
|
($sideoption.hasClass('NB-active') && !options.resize_open)) {
|
||||||
|
@ -71,8 +83,11 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Open/resize
|
// Open/resize
|
||||||
|
this.$('.NB-error').remove();
|
||||||
$sideoption.addClass('NB-active');
|
$sideoption.addClass('NB-active');
|
||||||
$unshare_button.toggleClass('NB-hidden', !this.model.get("shared"));
|
$unshare_button.toggleClass('NB-hidden', !this.model.get("shared"));
|
||||||
|
$twitter_button.toggleClass('NB-active', !!NEWSBLUR.assets.preference('post_to_twitter'));
|
||||||
|
$facebook_button.toggleClass('NB-active', !!NEWSBLUR.assets.preference('post_to_facebook'));
|
||||||
var $share_clone = $share.clone();
|
var $share_clone = $share.clone();
|
||||||
var full_height = $share_clone.css({
|
var full_height = $share_clone.css({
|
||||||
'height': 'auto',
|
'height': 'auto',
|
||||||
|
@ -135,10 +150,14 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
||||||
var comments = _.string.trim((options.source == 'menu' ? $comments_menu : $comments_sideoptions).val());
|
var comments = _.string.trim((options.source == 'menu' ? $comments_menu : $comments_sideoptions).val());
|
||||||
var feed = NEWSBLUR.assets.get_feed(NEWSBLUR.reader.active_feed);
|
var feed = NEWSBLUR.assets.get_feed(NEWSBLUR.reader.active_feed);
|
||||||
var source_user_id = feed && feed.get('user_id');
|
var source_user_id = feed && feed.get('user_id');
|
||||||
|
var post_to_services = _.compact([
|
||||||
|
NEWSBLUR.assets.preference('post_to_twitter') && 'twitter',
|
||||||
|
NEWSBLUR.assets.preference('post_to_facebook') && 'facebook'
|
||||||
|
]);
|
||||||
|
|
||||||
$share_button.addClass('NB-saving').addClass('NB-disabled').text('Sharing...');
|
$share_button.addClass('NB-saving').addClass('NB-disabled').text('Sharing...');
|
||||||
$share_button_menu.addClass('NB-saving').addClass('NB-disabled').text('Sharing...');
|
$share_button_menu.addClass('NB-saving').addClass('NB-disabled').text('Sharing...');
|
||||||
NEWSBLUR.assets.mark_story_as_shared(this.model.id, this.model.get('story_feed_id'), comments, source_user_id, _.bind(this.post_share_story, this, true), _.bind(function(data) {
|
NEWSBLUR.assets.mark_story_as_shared(this.model.id, this.model.get('story_feed_id'), comments, source_user_id, post_to_services, _.bind(this.post_share_story, this, true), _.bind(function(data) {
|
||||||
this.post_share_error(data, true);
|
this.post_share_error(data, true);
|
||||||
}, this));
|
}, this));
|
||||||
|
|
||||||
|
@ -242,6 +261,30 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
||||||
count_selected_words_when_sharing_story: function($feed_story) {
|
count_selected_words_when_sharing_story: function($feed_story) {
|
||||||
var $wordcount = $('.NB-sideoption-share-wordcount', $feed_story);
|
var $wordcount = $('.NB-sideoption-share-wordcount', $feed_story);
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
toggle_twitter: function() {
|
||||||
|
var $twitter_button = this.$('.NB-sideoption-share-crosspost-twitter');
|
||||||
|
|
||||||
|
if (NEWSBLUR.assets.preference('post_to_twitter')) {
|
||||||
|
NEWSBLUR.assets.preference('post_to_twitter', false);
|
||||||
|
} else {
|
||||||
|
NEWSBLUR.assets.preference('post_to_twitter', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$twitter_button.toggleClass('NB-active', NEWSBLUR.assets.preference('post_to_twitter'));
|
||||||
|
},
|
||||||
|
|
||||||
|
toggle_facebook: function() {
|
||||||
|
var $facebook_button = this.$('.NB-sideoption-share-crosspost-facebook');
|
||||||
|
|
||||||
|
if (NEWSBLUR.assets.preference('post_to_facebook')) {
|
||||||
|
NEWSBLUR.assets.preference('post_to_facebook', false);
|
||||||
|
} else {
|
||||||
|
NEWSBLUR.assets.preference('post_to_facebook', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$facebook_button.toggleClass('NB-active', NEWSBLUR.assets.preference('post_to_facebook'));
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
|
@ -1,16 +1,17 @@
|
||||||
{% block body %}{% endblock body %}
|
{% block body %}{% endblock body %}
|
||||||
|
|
||||||
- Samuel Clay, @samuelclay
|
- Samuel & Roy
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
Stay up to date and in touch with me, yr. developer, in a few different ways:
|
NewsBlur is your social news reader with intelligence. A new sound of an old instrument.
|
||||||
|
|
||||||
|
Stay up to date and in touch with us, yr. developers, in a few different ways:
|
||||||
|
|
||||||
* Follow @samuelclay on Twitter: http://twitter.com/samuelclay/
|
|
||||||
* Follow @newsblur on Twitter: http://twitter.com/newsblur/
|
* Follow @newsblur on Twitter: http://twitter.com/newsblur/
|
||||||
* Follow @samuelclay on GitHub: http://github.com/samuelclay/
|
* Follow @samuelclay on GitHub: http://github.com/samuelclay/
|
||||||
|
|
||||||
{% block resources_header %}There are a few resources you can use if you end up loving NewsBlur:{% endblock resources_header %}
|
{% block resources_header %}To get the most out of NewsBlur, here are a few resources:{% endblock resources_header %}
|
||||||
|
|
||||||
* Read the NewsBlur Blog: http://blog.newsblur.com
|
* Read the NewsBlur Blog: http://blog.newsblur.com
|
||||||
* Get support on NewsBlur's Get Satisfaction: http://getsatisfaction.com/newsblur/
|
* Get support on NewsBlur's Get Satisfaction: http://getsatisfaction.com/newsblur/
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
{% block body %}{% endblock %}
|
{% block body %}{% endblock %}
|
||||||
|
|
||||||
<p style="line-height:20px;">- Samuel Clay, <a href="http://twitter.com/samuelclay" style="text-decoration:none">@samuelclay</a></p>
|
<p style="line-height:20px;clear: both;">- Samuel & Roy</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -28,22 +28,22 @@
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<p style="line-height:20px;">Stay up to date and in touch with me, yr. developer, in a few different ways:</p>
|
<p style="line-height:20px;">NewsBlur is your social news reader with intelligence. A new sound of an old instrument.</p>
|
||||||
|
<p style="line-height:20px;">Stay up to date and in touch with us, yr. developers, in a few different ways:</p>
|
||||||
<p style="line-height: 20px;">
|
<p style="line-height: 20px;">
|
||||||
<ul style="list-style: none;">
|
<ul style="list-style: none;">
|
||||||
<li style="line-height:22px;"><a href="http://twitter.com/samuelclay/" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/reader/twitter_icon.png" style="width:16px;height:16px;vertical-align:top;padding-top:3px;"> Follow @samuelclay on Twitter</a>.</li>
|
|
||||||
<li style="line-height:22px;"><a href="http://twitter.com/newsblur/" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/reader/twitter.png" style="width:16px;height:16px;vertical-align:top;padding-top:3px;"> Follow @newsblur on Twitter</a>.</li>
|
<li style="line-height:22px;"><a href="http://twitter.com/newsblur/" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/reader/twitter.png" style="width:16px;height:16px;vertical-align:top;padding-top:3px;"> Follow @newsblur on Twitter</a>.</li>
|
||||||
<li style="line-height:22px;"><a href="http://github.com/samuelclay/" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/reader/github_icon.png" style="width:16px;height:16px;vertical-align:top;padding-top:3px;"> Follow @samuelclay on GitHub</a>. ← I live on props.</li>
|
<li style="line-height:22px;"><a href="http://github.com/samuelclay/" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/reader/github_icon.png" style="width:16px;height:16px;vertical-align:top;padding-top:3px;"> Follow @samuelclay on GitHub</a>.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</p>
|
</p>
|
||||||
<p style="line-height: 20px;">{% block resources_header %}There are a couple resources you can use if you end up loving NewsBlur:{% endblock resources_header %}</p>
|
<p style="line-height: 20px;">{% block resources_header %}To get the most out of NewsBlur, here are a few resources:{% endblock resources_header %}</p>
|
||||||
<p style="line-height: 20px;">
|
<p style="line-height: 20px;">
|
||||||
<ul style="list-style: none;">
|
<ul style="list-style: none;">
|
||||||
<li style="line-height:22px;"><a href="http://blog.newsblur.com" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/favicon.png" style="width:16px;height:16px;vertical-align:top;padding-top:3px;"> Read the NewsBlur Blog</a>.</li>
|
<li style="line-height:22px;"><a href="http://blog.newsblur.com" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/favicon.png" style="width:16px;height:16px;vertical-align:top;padding-top:3px;"> Read the NewsBlur Blog</a>.</li>
|
||||||
<li style="line-height:22px;"><a href="http://getsatisfaction.com/newsblur/" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/reader/getsatisfaction.png" style="width:16px;height:16px;vertical-align:top;padding-top:3px;"> Get support on NewsBlur's Get Satisfaction</a>.</li>
|
<li style="line-height:22px;"><a href="http://getsatisfaction.com/newsblur/" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/reader/getsatisfaction.png" style="width:16px;height:16px;vertical-align:top;padding-top:3px;"> Get support on NewsBlur's Get Satisfaction</a>.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</p>
|
</p>
|
||||||
<p style="line-height: 20px;">There's plenty of ways to use NewsBlur beyond the website:</p>
|
<p style="line-height: 20px;">There's plenty of ways to use NewsBlur beyond the web:</p>
|
||||||
<p style="line-height: 20px;">
|
<p style="line-height: 20px;">
|
||||||
<ul style="list-style: none;">
|
<ul style="list-style: none;">
|
||||||
<li style="line-height:22px;"><a href="http://www.newsblur.com/iphone/" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/reader/iphone_icon.png" style="width:16px;height:16px;vertical-align:top;padding-top:3px;"> Download the free iPhone App</a>.</li>
|
<li style="line-height:22px;"><a href="http://www.newsblur.com/iphone/" style="text-decoration:none"><img src="http://www.newsblur.com/media/img/reader/iphone_icon.png" style="width:16px;height:16px;vertical-align:top;padding-top:3px;"> Download the free iPhone App</a>.</li>
|
||||||
|
|
|
@ -6,3 +6,5 @@
|
||||||
<p style="line-height: 20px;">Spend a few days trying out NewsBlur. I hope you end up loving it.</p>
|
<p style="line-height: 20px;">Spend a few days trying out NewsBlur. I hope you end up loving it.</p>
|
||||||
<p style="line-height: 20px;">If you really do love using NewsBlur you should purchase a fancy <b>premium account</b> for only $12/year (nights and weekends and all major public holidays included). You get to support an independent developer, help feed his dog, and contribute to the long-term health of NewsBlur.</p>
|
<p style="line-height: 20px;">If you really do love using NewsBlur you should purchase a fancy <b>premium account</b> for only $12/year (nights and weekends and all major public holidays included). You get to support an independent developer, help feed his dog, and contribute to the long-term health of NewsBlur.</p>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block resources_header %}There are a couple resources you can use if you end up loving NewsBlur:{% endblock resources_header %}
|
|
@ -337,6 +337,10 @@
|
||||||
user_id of the original sharer.
|
user_id of the original sharer.
|
||||||
optional: true
|
optional: true
|
||||||
example: "128"
|
example: "128"
|
||||||
|
- key: post_to_services
|
||||||
|
desc: "List of services to cross-post to. Can be 'twitter' and/or 'facebook'."
|
||||||
|
optional: true
|
||||||
|
example: "['twitter', 'facebook']"
|
||||||
- url: /social/unshare_story
|
- url: /social/unshare_story
|
||||||
method: POST
|
method: POST
|
||||||
short_desc: "Remove a shared story from user's blurblog."
|
short_desc: "Remove a shared story from user's blurblog."
|
||||||
|
|
|
@ -146,7 +146,6 @@ class bunch(dict):
|
||||||
else:
|
else:
|
||||||
self.__setitem__(item, value)
|
self.__setitem__(item, value)
|
||||||
|
|
||||||
|
|
||||||
class MLStripper(HTMLParser):
|
class MLStripper(HTMLParser):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.reset()
|
self.reset()
|
||||||
|
@ -160,3 +159,15 @@ def strip_tags(html):
|
||||||
s = MLStripper()
|
s = MLStripper()
|
||||||
s.feed(html)
|
s.feed(html)
|
||||||
return s.get_data()
|
return s.get_data()
|
||||||
|
|
||||||
|
def truncate_chars(value, max_length):
|
||||||
|
if len(value) <= max_length:
|
||||||
|
return value
|
||||||
|
|
||||||
|
truncd_val = value[:max_length]
|
||||||
|
if value[max_length] != " ":
|
||||||
|
rightmost_space = truncd_val.rfind(" ")
|
||||||
|
if rightmost_space != -1:
|
||||||
|
truncd_val = truncd_val[:rightmost_space]
|
||||||
|
|
||||||
|
return truncd_val + "..."
|
Loading…
Add table
Reference in a new issue