mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-08-05 16:58:59 +00:00
Goodbye AppDotNet
This commit is contained in:
parent
3963720414
commit
d90a9aa718
9 changed files with 10 additions and 487 deletions
|
@ -5,10 +5,8 @@ from oauth2_provider import views as op_views
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
url(r'^twitter_connect/?$', views.twitter_connect, name='twitter-connect'),
|
url(r'^twitter_connect/?$', views.twitter_connect, name='twitter-connect'),
|
||||||
url(r'^facebook_connect/?$', views.facebook_connect, name='facebook-connect'),
|
url(r'^facebook_connect/?$', views.facebook_connect, name='facebook-connect'),
|
||||||
url(r'^appdotnet_connect/?$', views.appdotnet_connect, name='appdotnet-connect'),
|
|
||||||
url(r'^twitter_disconnect/?$', views.twitter_disconnect, name='twitter-disconnect'),
|
url(r'^twitter_disconnect/?$', views.twitter_disconnect, name='twitter-disconnect'),
|
||||||
url(r'^facebook_disconnect/?$', views.facebook_disconnect, name='facebook-disconnect'),
|
url(r'^facebook_disconnect/?$', views.facebook_disconnect, name='facebook-disconnect'),
|
||||||
url(r'^appdotnet_disconnect/?$', views.appdotnet_disconnect, name='appdotnet-disconnect'),
|
|
||||||
url(r'^follow_twitter_account/?$', views.follow_twitter_account, name='social-follow-twitter'),
|
url(r'^follow_twitter_account/?$', views.follow_twitter_account, name='social-follow-twitter'),
|
||||||
url(r'^unfollow_twitter_account/?$', views.unfollow_twitter_account, name='social-unfollow-twitter'),
|
url(r'^unfollow_twitter_account/?$', views.unfollow_twitter_account, name='social-unfollow-twitter'),
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ from django.conf import settings
|
||||||
from mongoengine.queryset import NotUniqueError
|
from mongoengine.queryset import NotUniqueError
|
||||||
from mongoengine.queryset import OperationError
|
from mongoengine.queryset import OperationError
|
||||||
from apps.social.models import MSocialServices, MSocialSubscription, MSharedStory
|
from apps.social.models import MSocialServices, MSocialSubscription, MSharedStory
|
||||||
from apps.social.tasks import SyncTwitterFriends, SyncFacebookFriends, SyncAppdotnetFriends
|
from apps.social.tasks import SyncTwitterFriends, SyncFacebookFriends
|
||||||
from apps.reader.models import UserSubscription, UserSubscriptionFolders, RUserStory
|
from apps.reader.models import UserSubscription, UserSubscriptionFolders, RUserStory
|
||||||
from apps.analyzer.models import MClassifierTitle, MClassifierAuthor, MClassifierFeed, MClassifierTag
|
from apps.analyzer.models import MClassifierTitle, MClassifierAuthor, MClassifierFeed, MClassifierTag
|
||||||
from apps.analyzer.models import compute_story_score
|
from apps.analyzer.models import compute_story_score
|
||||||
|
@ -23,7 +23,6 @@ from utils.view_functions import render_to
|
||||||
from utils import urlnorm
|
from utils import urlnorm
|
||||||
from utils import json_functions as json
|
from utils import json_functions as json
|
||||||
from vendor import facebook
|
from vendor import facebook
|
||||||
from vendor import appdotnet
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@render_to('social/social_connect.xhtml')
|
@render_to('social/social_connect.xhtml')
|
||||||
|
@ -145,63 +144,6 @@ def facebook_connect(request):
|
||||||
url = "https://www.facebook.com/dialog/oauth?" + urllib.urlencode(args)
|
url = "https://www.facebook.com/dialog/oauth?" + urllib.urlencode(args)
|
||||||
return {'next': url}
|
return {'next': url}
|
||||||
|
|
||||||
@login_required
|
|
||||||
@render_to('social/social_connect.xhtml')
|
|
||||||
def appdotnet_connect(request):
|
|
||||||
domain = Site.objects.get_current().domain
|
|
||||||
args = {
|
|
||||||
"client_id": settings.APPDOTNET_CLIENTID,
|
|
||||||
"client_secret": settings.APPDOTNET_SECRET,
|
|
||||||
"redirect_uri": "https://" + domain +
|
|
||||||
reverse('appdotnet-connect'),
|
|
||||||
"scope": ["email", "write_post", "follow"],
|
|
||||||
}
|
|
||||||
|
|
||||||
oauth_code = request.REQUEST.get('code')
|
|
||||||
denied = request.REQUEST.get('denied')
|
|
||||||
if denied:
|
|
||||||
logging.user(request, "~BB~FRDenied App.net connect")
|
|
||||||
return {'error': 'Denied! Try connecting again.'}
|
|
||||||
elif oauth_code:
|
|
||||||
try:
|
|
||||||
adn_auth = appdotnet.Appdotnet(**args)
|
|
||||||
response = adn_auth.getAuthResponse(oauth_code)
|
|
||||||
adn_resp = json.decode(response)
|
|
||||||
access_token = adn_resp['access_token']
|
|
||||||
adn_userid = adn_resp['user_id']
|
|
||||||
except (IOError):
|
|
||||||
logging.user(request, "~BB~FRFailed App.net connect")
|
|
||||||
return dict(error="App.net has returned an error. Try connecting again.")
|
|
||||||
|
|
||||||
# Be sure that two people aren't using the same Twitter account.
|
|
||||||
existing_user = MSocialServices.objects.filter(appdotnet_uid=unicode(adn_userid))
|
|
||||||
if existing_user and existing_user[0].user_id != request.user.pk:
|
|
||||||
try:
|
|
||||||
user = User.objects.get(pk=existing_user[0].user_id)
|
|
||||||
logging.user(request, "~BB~FRFailed App.net connect, another user: %s" % user.username)
|
|
||||||
return dict(error=("Another user (%s, %s) has "
|
|
||||||
"already connected with those App.net credentials."
|
|
||||||
% (user.username, user.email or "no email")))
|
|
||||||
except User.DoesNotExist:
|
|
||||||
existing_user.delete()
|
|
||||||
|
|
||||||
social_services = MSocialServices.get_user(request.user.pk)
|
|
||||||
social_services.appdotnet_uid = unicode(adn_userid)
|
|
||||||
social_services.appdotnet_access_token = access_token
|
|
||||||
social_services.syncing_appdotnet = True
|
|
||||||
social_services.save()
|
|
||||||
|
|
||||||
SyncAppdotnetFriends.delay(user_id=request.user.pk)
|
|
||||||
|
|
||||||
logging.user(request, "~BB~FRFinishing App.net connect")
|
|
||||||
return {}
|
|
||||||
else:
|
|
||||||
# Start the OAuth process
|
|
||||||
adn_auth = appdotnet.Appdotnet(**args)
|
|
||||||
auth_url = adn_auth.generateAuthUrl()
|
|
||||||
logging.user(request, "~BB~FRStarting App.net connect")
|
|
||||||
return {'next': auth_url}
|
|
||||||
|
|
||||||
@ajax_login_required
|
@ajax_login_required
|
||||||
def twitter_disconnect(request):
|
def twitter_disconnect(request):
|
||||||
logging.user(request, "~BB~FRDisconnecting Twitter")
|
logging.user(request, "~BB~FRDisconnecting Twitter")
|
||||||
|
@ -218,14 +160,6 @@ def facebook_disconnect(request):
|
||||||
|
|
||||||
return HttpResponseRedirect(reverse('load-user-friends'))
|
return HttpResponseRedirect(reverse('load-user-friends'))
|
||||||
|
|
||||||
@ajax_login_required
|
|
||||||
def appdotnet_disconnect(request):
|
|
||||||
logging.user(request, "~BB~FRDisconnecting App.net")
|
|
||||||
social_services = MSocialServices.objects.get(user_id=request.user.pk)
|
|
||||||
social_services.disconnect_appdotnet()
|
|
||||||
|
|
||||||
return HttpResponseRedirect(reverse('load-user-friends'))
|
|
||||||
|
|
||||||
@ajax_login_required
|
@ajax_login_required
|
||||||
@json.json_view
|
@json.json_view
|
||||||
def follow_twitter_account(request):
|
def follow_twitter_account(request):
|
||||||
|
|
|
@ -29,7 +29,6 @@ from apps.rss_feeds.text_importer import TextImporter
|
||||||
from apps.rss_feeds.page_importer import PageImporter
|
from apps.rss_feeds.page_importer import PageImporter
|
||||||
from apps.profile.models import Profile, MSentEmail
|
from apps.profile.models import Profile, MSentEmail
|
||||||
from vendor import facebook
|
from vendor import facebook
|
||||||
from vendor import appdotnet
|
|
||||||
from vendor import pynliner
|
from vendor import pynliner
|
||||||
from utils import log as logging
|
from utils import log as logging
|
||||||
from utils import json_functions as json
|
from utils import json_functions as json
|
||||||
|
@ -2133,10 +2132,8 @@ class MSharedStory(mongo.DynamicDocument):
|
||||||
|
|
||||||
if service == 'twitter':
|
if service == 'twitter':
|
||||||
posted = social_service.post_to_twitter(self)
|
posted = social_service.post_to_twitter(self)
|
||||||
# elif service == 'facebook':
|
elif service == 'facebook':
|
||||||
# posted = social_service.post_to_facebook(self)
|
posted = social_service.post_to_facebook(self)
|
||||||
elif service == 'appdotnet':
|
|
||||||
posted = social_service.post_to_appdotnet(self)
|
|
||||||
|
|
||||||
if posted:
|
if posted:
|
||||||
self.posted_to_services.append(service)
|
self.posted_to_services.append(service)
|
||||||
|
@ -2390,25 +2387,19 @@ class MSocialServices(mongo.Document):
|
||||||
facebook_friend_ids = mongo.ListField(mongo.StringField())
|
facebook_friend_ids = mongo.ListField(mongo.StringField())
|
||||||
facebook_picture_url = mongo.StringField()
|
facebook_picture_url = mongo.StringField()
|
||||||
facebook_refresh_date = mongo.DateTimeField()
|
facebook_refresh_date = mongo.DateTimeField()
|
||||||
appdotnet_uid = mongo.StringField()
|
|
||||||
appdotnet_access_token= mongo.StringField()
|
|
||||||
appdotnet_friend_ids = mongo.ListField(mongo.StringField())
|
|
||||||
appdotnet_picture_url = mongo.StringField()
|
|
||||||
appdotnet_refresh_date= mongo.DateTimeField()
|
|
||||||
upload_picture_url = mongo.StringField()
|
upload_picture_url = mongo.StringField()
|
||||||
syncing_twitter = mongo.BooleanField(default=False)
|
syncing_twitter = mongo.BooleanField(default=False)
|
||||||
syncing_facebook = mongo.BooleanField(default=False)
|
syncing_facebook = mongo.BooleanField(default=False)
|
||||||
syncing_appdotnet = mongo.BooleanField(default=False)
|
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
'collection': 'social_services',
|
'collection': 'social_services',
|
||||||
'indexes': ['user_id', 'twitter_friend_ids', 'facebook_friend_ids', 'twitter_uid', 'facebook_uid', 'appdotnet_uid'],
|
'indexes': ['user_id', 'twitter_friend_ids', 'facebook_friend_ids', 'twitter_uid', 'facebook_uid'],
|
||||||
'allow_inheritance': False,
|
'allow_inheritance': False,
|
||||||
}
|
}
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
user = User.objects.get(pk=self.user_id)
|
user = User.objects.get(pk=self.user_id)
|
||||||
return "%s (Twitter: %s, FB: %s, ADN: %s)" % (user.username, self.twitter_uid, self.facebook_uid, self.appdotnet_uid)
|
return "%s (Twitter: %s, FB: %s)" % (user.username, self.twitter_uid, self.facebook_uid)
|
||||||
|
|
||||||
def canonical(self):
|
def canonical(self):
|
||||||
user = User.objects.get(pk=self.user_id)
|
user = User.objects.get(pk=self.user_id)
|
||||||
|
@ -2424,11 +2415,6 @@ class MSocialServices(mongo.Document):
|
||||||
'facebook_picture_url': self.facebook_picture_url,
|
'facebook_picture_url': self.facebook_picture_url,
|
||||||
'syncing': self.syncing_facebook,
|
'syncing': self.syncing_facebook,
|
||||||
},
|
},
|
||||||
'appdotnet': {
|
|
||||||
'appdotnet_uid': self.appdotnet_uid,
|
|
||||||
'appdotnet_picture_url': self.appdotnet_picture_url,
|
|
||||||
'syncing': self.syncing_appdotnet,
|
|
||||||
},
|
|
||||||
'gravatar': {
|
'gravatar': {
|
||||||
'gravatar_picture_url': "https://www.gravatar.com/avatar/" + \
|
'gravatar_picture_url': "https://www.gravatar.com/avatar/" + \
|
||||||
hashlib.md5(user.email.lower()).hexdigest()
|
hashlib.md5(user.email.lower()).hexdigest()
|
||||||
|
@ -2491,10 +2477,6 @@ class MSocialServices(mongo.Document):
|
||||||
graph = facebook.GraphAPI(access_token=self.facebook_access_token, version="3.1")
|
graph = facebook.GraphAPI(access_token=self.facebook_access_token, version="3.1")
|
||||||
return graph
|
return graph
|
||||||
|
|
||||||
def appdotnet_api(self):
|
|
||||||
adn_api = appdotnet.Appdotnet(access_token=self.appdotnet_access_token)
|
|
||||||
return adn_api
|
|
||||||
|
|
||||||
def sync_twitter_friends(self):
|
def sync_twitter_friends(self):
|
||||||
user = User.objects.get(pk=self.user_id)
|
user = User.objects.get(pk=self.user_id)
|
||||||
logging.user(user, "~BG~FMTwitter import starting...")
|
logging.user(user, "~BG~FMTwitter import starting...")
|
||||||
|
@ -2638,84 +2620,6 @@ class MSocialServices(mongo.Document):
|
||||||
|
|
||||||
return following
|
return following
|
||||||
|
|
||||||
def sync_appdotnet_friends(self):
|
|
||||||
user = User.objects.get(pk=self.user_id)
|
|
||||||
logging.user(user, "~BG~FMApp.net import starting...")
|
|
||||||
|
|
||||||
api = self.appdotnet_api()
|
|
||||||
if not api:
|
|
||||||
logging.user(user, "~BG~FMApp.net import ~SBfailed~SN: no api access.")
|
|
||||||
self.syncing_appdotnet = False
|
|
||||||
self.save()
|
|
||||||
return
|
|
||||||
|
|
||||||
friend_ids = []
|
|
||||||
has_more_friends = True
|
|
||||||
before_id = None
|
|
||||||
since_id = None
|
|
||||||
while has_more_friends:
|
|
||||||
friends_resp = api.getUserFollowingIds(self.appdotnet_uid,
|
|
||||||
before_id=before_id,
|
|
||||||
since_id=since_id)
|
|
||||||
friends = json.decode(friends_resp)
|
|
||||||
before_id = friends['meta'].get('min_id')
|
|
||||||
since_id = friends['meta'].get('max_id')
|
|
||||||
has_more_friends = friends['meta'].get('more')
|
|
||||||
friend_ids.extend([fid for fid in friends['data']])
|
|
||||||
|
|
||||||
if not friend_ids:
|
|
||||||
logging.user(user, "~BG~FMApp.net import ~SBfailed~SN: no friend_ids.")
|
|
||||||
self.syncing_appdotnet = False
|
|
||||||
self.save()
|
|
||||||
return
|
|
||||||
|
|
||||||
adn_user = json.decode(api.getUser(self.appdotnet_uid))['data']
|
|
||||||
self.appdotnet_picture_url = adn_user['avatar_image']['url']
|
|
||||||
self.appdotnet_username = adn_user['username']
|
|
||||||
self.appdotnet_friend_ids = friend_ids
|
|
||||||
self.appdotnet_refreshed_date = datetime.datetime.utcnow()
|
|
||||||
self.syncing_appdotnet = False
|
|
||||||
self.save()
|
|
||||||
|
|
||||||
profile = MSocialProfile.get_user(self.user_id)
|
|
||||||
profile.bio = profile.bio or adn_user['description']['text']
|
|
||||||
profile.save()
|
|
||||||
profile.count_follows()
|
|
||||||
|
|
||||||
if not profile.photo_url or not profile.photo_service:
|
|
||||||
self.set_photo('appdotnet')
|
|
||||||
|
|
||||||
self.follow_appdotnet_friends()
|
|
||||||
|
|
||||||
def follow_appdotnet_friends(self):
|
|
||||||
social_profile = MSocialProfile.get_user(self.user_id)
|
|
||||||
following = []
|
|
||||||
followers = 0
|
|
||||||
|
|
||||||
if not self.autofollow:
|
|
||||||
return following
|
|
||||||
|
|
||||||
# Follow any friends already on NewsBlur
|
|
||||||
user_social_services = MSocialServices.objects.filter(appdotnet_uid__in=self.appdotnet_friend_ids)
|
|
||||||
for user_social_service in user_social_services:
|
|
||||||
followee_user_id = user_social_service.user_id
|
|
||||||
socialsub = social_profile.follow_user(followee_user_id)
|
|
||||||
if socialsub:
|
|
||||||
following.append(followee_user_id)
|
|
||||||
|
|
||||||
# Friends already on NewsBlur should follow back
|
|
||||||
# following_users = MSocialServices.objects.filter(appdotnet_friend_ids__contains=self.appdotnet_uid)
|
|
||||||
# for following_user in following_users:
|
|
||||||
# if following_user.autofollow:
|
|
||||||
# following_user_profile = MSocialProfile.get_user(following_user.user_id)
|
|
||||||
# following_user_profile.follow_user(self.user_id, check_unfollowed=True)
|
|
||||||
# followers += 1
|
|
||||||
|
|
||||||
user = User.objects.get(pk=self.user_id)
|
|
||||||
logging.user(user, "~BG~FMApp.net import: %s users, now following ~SB%s~SN with ~SB%s~SN follower-backs" % (len(self.appdotnet_friend_ids), len(following), followers))
|
|
||||||
|
|
||||||
return following
|
|
||||||
|
|
||||||
def disconnect_twitter(self):
|
def disconnect_twitter(self):
|
||||||
self.syncing_twitter = False
|
self.syncing_twitter = False
|
||||||
self.twitter_uid = None
|
self.twitter_uid = None
|
||||||
|
@ -2726,11 +2630,6 @@ class MSocialServices(mongo.Document):
|
||||||
self.facebook_uid = None
|
self.facebook_uid = None
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
def disconnect_appdotnet(self):
|
|
||||||
self.syncing_appdotnet = False
|
|
||||||
self.appdotnet_uid = None
|
|
||||||
self.save()
|
|
||||||
|
|
||||||
def set_photo(self, service):
|
def set_photo(self, service):
|
||||||
profile = MSocialProfile.get_user(self.user_id)
|
profile = MSocialProfile.get_user(self.user_id)
|
||||||
if service == 'nothing':
|
if service == 'nothing':
|
||||||
|
@ -2858,21 +2757,6 @@ class MSocialServices(mongo.Document):
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def post_to_appdotnet(self, shared_story):
|
|
||||||
message = shared_story.generate_post_to_service_message(truncate=256)
|
|
||||||
|
|
||||||
try:
|
|
||||||
api = self.appdotnet_api()
|
|
||||||
api.createPost(text=message, links=[{
|
|
||||||
'text': shared_story.decoded_story_title,
|
|
||||||
'url': shared_story.blurblog_permalink()
|
|
||||||
}])
|
|
||||||
except Exception, e:
|
|
||||||
print e
|
|
||||||
return
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
class MInteraction(mongo.Document):
|
class MInteraction(mongo.Document):
|
||||||
user_id = mongo.IntField()
|
user_id = mongo.IntField()
|
||||||
|
|
|
@ -56,12 +56,6 @@ class SyncFacebookFriends(Task):
|
||||||
social_services = MSocialServices.objects.get(user_id=user_id)
|
social_services = MSocialServices.objects.get(user_id=user_id)
|
||||||
social_services.sync_facebook_friends()
|
social_services.sync_facebook_friends()
|
||||||
|
|
||||||
class SyncAppdotnetFriends(Task):
|
|
||||||
|
|
||||||
def run(self, user_id):
|
|
||||||
social_services = MSocialServices.objects.get(user_id=user_id)
|
|
||||||
social_services.sync_appdotnet_friends()
|
|
||||||
|
|
||||||
class SharePopularStories(Task):
|
class SharePopularStories(Task):
|
||||||
name = 'share-popular-stories'
|
name = 'share-popular-stories'
|
||||||
|
|
||||||
|
|
|
@ -660,10 +660,6 @@ def mark_story_as_shared(request):
|
||||||
if post_to_services:
|
if post_to_services:
|
||||||
for service in post_to_services:
|
for service in post_to_services:
|
||||||
if service not in shared_story.posted_to_services:
|
if service not in shared_story.posted_to_services:
|
||||||
if service == 'appdotnet':
|
|
||||||
# XXX TODO: Remove. Only for www->dev.
|
|
||||||
shared_story.post_to_service(service)
|
|
||||||
else:
|
|
||||||
PostToService.delay(shared_story_id=shared_story.id, service=service)
|
PostToService.delay(shared_story_id=shared_story.id, service=service)
|
||||||
|
|
||||||
if shared_story.source_user_id and shared_story.comments:
|
if shared_story.source_user_id and shared_story.comments:
|
||||||
|
|
|
@ -4023,8 +4023,7 @@ body {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.NB-sideoption-share .NB-sideoption-share-crosspost-twitter,
|
.NB-sideoption-share .NB-sideoption-share-crosspost-twitter,
|
||||||
.NB-sideoption-share .NB-sideoption-share-crosspost-facebook,
|
.NB-sideoption-share .NB-sideoption-share-crosspost-facebook {
|
||||||
.NB-sideoption-share .NB-sideoption-share-crosspost-appdotnet {
|
|
||||||
float: left;
|
float: left;
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
|
@ -4041,10 +4040,6 @@ body {
|
||||||
background: transparent url('/media/embed/reader/facebook_service_off.png') no-repeat center center;
|
background: transparent url('/media/embed/reader/facebook_service_off.png') no-repeat center center;
|
||||||
background-size: 12px;
|
background-size: 12px;
|
||||||
}
|
}
|
||||||
.NB-sideoption-share .NB-sideoption-share-crosspost-appdotnet {
|
|
||||||
background: transparent url('/media/embed/reader/appdotnet_service_off.png') no-repeat center center;
|
|
||||||
background-size: 12px;
|
|
||||||
}
|
|
||||||
.NB-sideoption-share .NB-sideoption-share-crosspost-twitter.NB-active,
|
.NB-sideoption-share .NB-sideoption-share-crosspost-twitter.NB-active,
|
||||||
.NB-sideoption-share .NB-sideoption-share-crosspost-twitter:hover {
|
.NB-sideoption-share .NB-sideoption-share-crosspost-twitter:hover {
|
||||||
background: transparent url('/media/embed/reader/twitter_service.png') no-repeat center center;
|
background: transparent url('/media/embed/reader/twitter_service.png') no-repeat center center;
|
||||||
|
@ -4059,13 +4054,6 @@ body {
|
||||||
border-color: #6884CD;
|
border-color: #6884CD;
|
||||||
background-color: rgba(104, 132, 205, .1);
|
background-color: rgba(104, 132, 205, .1);
|
||||||
}
|
}
|
||||||
.NB-sideoption-share .NB-sideoption-share-crosspost-appdotnet.NB-active,
|
|
||||||
.NB-sideoption-share .NB-sideoption-share-crosspost-appdotnet:hover {
|
|
||||||
background: transparent url('/media/embed/reader/appdotnet_service.png') no-repeat center center;
|
|
||||||
background-size: 12px;
|
|
||||||
border-color: #D16857;
|
|
||||||
background-color: rgba(209, 104, 87, .1);
|
|
||||||
}
|
|
||||||
.NB-sideoption-share .NB-sideoption-share-crosspost-text {
|
.NB-sideoption-share .NB-sideoption-share-crosspost-text {
|
||||||
font-size: 9px;
|
font-size: 9px;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
|
|
|
@ -6,8 +6,6 @@ NEWSBLUR.utils = {
|
||||||
return 'Twitter';
|
return 'Twitter';
|
||||||
case 'facebook':
|
case 'facebook':
|
||||||
return 'Facebook';
|
return 'Facebook';
|
||||||
case 'appdotnet':
|
|
||||||
return 'App.net';
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
||||||
"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-twitter" : "toggle_twitter",
|
||||||
"click .NB-sideoption-share-crosspost-facebook" : "toggle_facebook",
|
"click .NB-sideoption-share-crosspost-facebook" : "toggle_facebook",
|
||||||
"click .NB-sideoption-share-crosspost-appdotnet" : "toggle_appdotnet",
|
|
||||||
"keypress .NB-sideoption-share-comments" : "autosize",
|
"keypress .NB-sideoption-share-comments" : "autosize",
|
||||||
"keyup .NB-sideoption-share-comments" : "update_share_button_label",
|
"keyup .NB-sideoption-share-comments" : "update_share_button_label",
|
||||||
"keydown .NB-sideoption-share-comments" : "maybe_close"
|
"keydown .NB-sideoption-share-comments" : "maybe_close"
|
||||||
|
@ -35,8 +34,7 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
||||||
<textarea class="NB-sideoption-share-comments"><%= story.get("shared_comments") %></textarea>\
|
<textarea class="NB-sideoption-share-comments"><%= story.get("shared_comments") %></textarea>\
|
||||||
<% if (!profile.get("private") && \
|
<% if (!profile.get("private") && \
|
||||||
((social_services.twitter && social_services.twitter.twitter_uid) || \
|
((social_services.twitter && social_services.twitter.twitter_uid) || \
|
||||||
(social_services.facebook && social_services.facebook.facebook_uid) || \
|
(social_services.facebook && social_services.facebook.facebook_uid))) { %>\
|
||||||
(social_services.facebook && social_services.facebook.appdotnet_uid))) { %>\
|
|
||||||
<div class="NB-sideoption-share-crosspost">\
|
<div class="NB-sideoption-share-crosspost">\
|
||||||
<% _.each(social_services, function(service, service_name) { %>\
|
<% _.each(social_services, function(service, service_name) { %>\
|
||||||
<% if (service[service_name+"_uid"]) { %>\
|
<% if (service[service_name+"_uid"]) { %>\
|
||||||
|
@ -64,7 +62,6 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
||||||
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 $twitter_button = this.$('.NB-sideoption-share-crosspost-twitter');
|
||||||
var $facebook_button = this.$('.NB-sideoption-share-crosspost-facebook');
|
var $facebook_button = this.$('.NB-sideoption-share-crosspost-facebook');
|
||||||
var $appdotnet_button = this.$('.NB-sideoption-share-crosspost-appdotnet');
|
|
||||||
|
|
||||||
if (options.close ||
|
if (options.close ||
|
||||||
($sideoption.hasClass('NB-active') && !options.resize_open)) {
|
($sideoption.hasClass('NB-active') && !options.resize_open)) {
|
||||||
|
@ -82,7 +79,6 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
||||||
$unshare_button.toggleClass('NB-hidden', !this.model.get("shared"));
|
$unshare_button.toggleClass('NB-hidden', !this.model.get("shared"));
|
||||||
$twitter_button.removeClass('NB-active');
|
$twitter_button.removeClass('NB-active');
|
||||||
$facebook_button.removeClass('NB-active');
|
$facebook_button.removeClass('NB-active');
|
||||||
$appdotnet_button.removeClass('NB-active');
|
|
||||||
this.update_share_button_label();
|
this.update_share_button_label();
|
||||||
this.$('textarea').autosize();
|
this.$('textarea').autosize();
|
||||||
|
|
||||||
|
@ -220,7 +216,6 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
||||||
var $share_menu = $share_button_menu.closest('.NB-sideoption-share');
|
var $share_menu = $share_button_menu.closest('.NB-sideoption-share');
|
||||||
var $twitter_button = this.$('.NB-sideoption-share-crosspost-twitter');
|
var $twitter_button = this.$('.NB-sideoption-share-crosspost-twitter');
|
||||||
var $facebook_button = this.$('.NB-sideoption-share-crosspost-facebook');
|
var $facebook_button = this.$('.NB-sideoption-share-crosspost-facebook');
|
||||||
var $appdotnet_button = this.$('.NB-sideoption-share-crosspost-appdotnet');
|
|
||||||
var $comments_sideoptions = this.$('.NB-sideoption-share-comments');
|
var $comments_sideoptions = this.$('.NB-sideoption-share-comments');
|
||||||
var $comments_menu = $('.NB-sideoption-share-comments', $share_menu);
|
var $comments_menu = $('.NB-sideoption-share-comments', $share_menu);
|
||||||
var comments = _.string.trim((options.source == 'menu' ? $comments_menu : $comments_sideoptions).val());
|
var comments = _.string.trim((options.source == 'menu' ? $comments_menu : $comments_sideoptions).val());
|
||||||
|
@ -236,7 +231,6 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
||||||
var post_to_services = _.compact([
|
var post_to_services = _.compact([
|
||||||
$twitter_button.hasClass('NB-active') && 'twitter',
|
$twitter_button.hasClass('NB-active') && 'twitter',
|
||||||
$facebook_button.hasClass('NB-active') && 'facebook',
|
$facebook_button.hasClass('NB-active') && 'facebook',
|
||||||
$appdotnet_button.hasClass('NB-active') && 'appdotnet'
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$share_button.addClass('NB-saving').addClass('NB-disabled').text('Sharing...');
|
$share_button.addClass('NB-saving').addClass('NB-disabled').text('Sharing...');
|
||||||
|
@ -395,12 +389,6 @@ NEWSBLUR.Views.StoryShareView = Backbone.View.extend({
|
||||||
$facebook_button.toggleClass('NB-active', !$facebook_button.hasClass('NB-active'));
|
$facebook_button.toggleClass('NB-active', !$facebook_button.hasClass('NB-active'));
|
||||||
},
|
},
|
||||||
|
|
||||||
toggle_appdotnet: function() {
|
|
||||||
var $appdotnet_button = this.$('.NB-sideoption-share-crosspost-appdotnet');
|
|
||||||
|
|
||||||
$appdotnet_button.toggleClass('NB-active', !$appdotnet_button.hasClass('NB-active'));
|
|
||||||
},
|
|
||||||
|
|
||||||
maybe_close: function(e) {
|
maybe_close: function(e) {
|
||||||
if (e.which == 27) {
|
if (e.which == 27) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
257
vendor/appdotnet.py
vendored
257
vendor/appdotnet.py
vendored
|
@ -1,257 +0,0 @@
|
||||||
import json
|
|
||||||
import requests
|
|
||||||
|
|
||||||
# To add
|
|
||||||
# - Identity Delegation
|
|
||||||
# - Streams (in dev by app.net)
|
|
||||||
# - Filters (in dev by app.net)
|
|
||||||
|
|
||||||
class Appdotnet:
|
|
||||||
''' Once access has been given, you don't have to pass through the
|
|
||||||
client_id, client_secret, redirect_uri, or scope. These are just
|
|
||||||
to get the authentication token.
|
|
||||||
|
|
||||||
Once authenticated, you can initialise appdotnet with only the
|
|
||||||
access token: ie
|
|
||||||
|
|
||||||
api = Appdotnet(access_token='<insert token here>')
|
|
||||||
'''
|
|
||||||
|
|
||||||
def __init__(self, client_id=None, client_secret=None, redirect_uri=None,
|
|
||||||
scope=None, access_token=None):
|
|
||||||
#for server authentication flow
|
|
||||||
self.client_id = client_id
|
|
||||||
self.client_secret = client_secret
|
|
||||||
self.redirect_uri = redirect_uri
|
|
||||||
self.scope = scope
|
|
||||||
|
|
||||||
self.access_token = access_token
|
|
||||||
|
|
||||||
self.api_anchor = "alpha.app.net" #for when the versions change
|
|
||||||
#anchors currently different
|
|
||||||
self.public_api_anchor = "alpha-api.app.net"
|
|
||||||
|
|
||||||
#scopes provided by app.net API
|
|
||||||
self.allowed_scopes = ['stream', 'email', 'write_post',
|
|
||||||
'follow', 'messages','export']
|
|
||||||
|
|
||||||
def generateAuthUrl(self):
|
|
||||||
url = "https://" + self.api_anchor + "/oauth/authenticate?client_id="+\
|
|
||||||
self.client_id + "&response_type=code&adnview=appstore&redirect_uri=" +\
|
|
||||||
self.redirect_uri + "&scope="
|
|
||||||
|
|
||||||
for scope in self.scope:
|
|
||||||
if scope in self.allowed_scopes:
|
|
||||||
url += scope + " "
|
|
||||||
|
|
||||||
return url
|
|
||||||
|
|
||||||
def getAuthResponse(self, code):
|
|
||||||
#generate POST request
|
|
||||||
url = "https://alpha.app.net/oauth/access_token"
|
|
||||||
post_data = {'client_id':self.client_id,
|
|
||||||
'client_secret':self.client_secret,
|
|
||||||
'grant_type':'authorization_code',
|
|
||||||
'redirect_uri':self.redirect_uri,
|
|
||||||
'code':code}
|
|
||||||
|
|
||||||
r = requests.post(url,data=post_data)
|
|
||||||
|
|
||||||
return r.text
|
|
||||||
|
|
||||||
'''
|
|
||||||
API Calls
|
|
||||||
'''
|
|
||||||
|
|
||||||
#GET REQUESTS
|
|
||||||
def getRequest(self, url, getParameters=None):
|
|
||||||
if not getParameters:
|
|
||||||
getParameters = {}
|
|
||||||
#access token
|
|
||||||
url = url + "?access_token=" + self.access_token
|
|
||||||
|
|
||||||
#if there are any extra get parameters aside from the access_token, append to the url
|
|
||||||
if getParameters != {}:
|
|
||||||
for key, value in getParameters.iteritems():
|
|
||||||
if not value: continue
|
|
||||||
url = url + "&" + key + "=" + unicode(value)
|
|
||||||
print url
|
|
||||||
r = requests.get(url)
|
|
||||||
if r.status_code == requests.codes.ok:
|
|
||||||
return r.text
|
|
||||||
else:
|
|
||||||
j = json.loads(r.text)
|
|
||||||
resp = {'error_code': r.status_code,
|
|
||||||
'message' : j['error']['message']}
|
|
||||||
return json.dumps(resp)
|
|
||||||
|
|
||||||
|
|
||||||
def getUser(self, user_id):
|
|
||||||
url = "https://%s/stream/0/users/%s" % (self.public_api_anchor,
|
|
||||||
user_id)
|
|
||||||
return self.getRequest(url)
|
|
||||||
|
|
||||||
def getUserPosts(self, user_id):
|
|
||||||
url = "https://%s/stream/0/users/%s/posts" % (self.public_api_anchor,
|
|
||||||
user_id)
|
|
||||||
return self.getRequest(url)
|
|
||||||
|
|
||||||
def getUserStars(self, user_id):
|
|
||||||
url = "https://%s/stream/0/users/%s/stars" % (self.public_api_anchor,
|
|
||||||
user_id)
|
|
||||||
return self.getRequest(url)
|
|
||||||
|
|
||||||
def getGlobalStream(self):
|
|
||||||
url = "https://%s/stream/0/posts/stream/global" % self.public_api_anchor
|
|
||||||
return self.getRequest(url)
|
|
||||||
|
|
||||||
def getUserStream(self):
|
|
||||||
url = "https://%s/stream/0/posts/stream" % self.public_api_anchor
|
|
||||||
return self.getRequest(url)
|
|
||||||
|
|
||||||
def getUserMentions(self, user_id):
|
|
||||||
url = "https://%s/stream/0/users/%s/mentions" % (self.public_api_anchor,user_id)
|
|
||||||
return self.getRequest(url)
|
|
||||||
|
|
||||||
def getPost(self, post_id):
|
|
||||||
url = "https://%s/stream/0/posts/%s" % (self.public_api_anchor,post_id)
|
|
||||||
return self.getRequest(url)
|
|
||||||
|
|
||||||
def getReposters(self, post_id):
|
|
||||||
url ="https://%s/stream/0/posts/%s/reposters" % (self.public_api_anchor,post_id)
|
|
||||||
return self.getRequest(url)
|
|
||||||
|
|
||||||
def getStars(self, post_id):
|
|
||||||
url ="https://%s/stream/0/posts/%s/stars" % (self.public_api_anchor,post_id)
|
|
||||||
return self.getRequest(url)
|
|
||||||
|
|
||||||
def getPostReplies(self, post_id):
|
|
||||||
url = "https://%s/stream/0/posts/%s/replies" % (self.public_api_anchor,post_id)
|
|
||||||
return self.getRequest(url)
|
|
||||||
|
|
||||||
def getPostsByTag(self, tag):
|
|
||||||
url = "https://%s/stream/0/posts/tag/%s" % (self.public_api_anchor, tag)
|
|
||||||
return self.getRequest(url)
|
|
||||||
|
|
||||||
def getUserFollowing(self, user_id, since_id=None, before_id=None):
|
|
||||||
url = "https://%s/stream/0/users/%s/following" % (self.public_api_anchor, user_id)
|
|
||||||
return self.getRequest(url, getParameters={
|
|
||||||
'since_id': since_id,
|
|
||||||
'before_id': before_id,
|
|
||||||
})
|
|
||||||
|
|
||||||
def getUserFollowingIds(self, user_id, since_id=None, before_id=None):
|
|
||||||
url = "https://%s/stream/0/users/%s/following/ids" % (self.public_api_anchor, user_id)
|
|
||||||
return self.getRequest(url, getParameters={
|
|
||||||
'since_id': since_id,
|
|
||||||
'before_id': before_id,
|
|
||||||
})
|
|
||||||
|
|
||||||
def getUserFollowers(self, user_id):
|
|
||||||
url = "https://%s/stream/0/users/%s/followers" % (self.public_api_anchor, user_id)
|
|
||||||
return self.getRequest(url)
|
|
||||||
|
|
||||||
def getMutedUsers(self):
|
|
||||||
url = "https://%s/stream/0/users/me/muted" % self.public_api_anchor
|
|
||||||
return self.getRequest(url)
|
|
||||||
|
|
||||||
def searchUsers(self,q):
|
|
||||||
url = "https://%s/stream/0/users/search" % (self.public_api_anchor)
|
|
||||||
return self.getRequest(url,getParameters={'q':q})
|
|
||||||
|
|
||||||
def getCurrentToken(self):
|
|
||||||
url = "https://%s/stream/0/token" % self.public_api_anchor
|
|
||||||
return self.getRequest(url)
|
|
||||||
|
|
||||||
#POST REQUESTS
|
|
||||||
def postRequest(self, url, data=None, headers=None):
|
|
||||||
if not data:
|
|
||||||
data = {}
|
|
||||||
|
|
||||||
if not headers:
|
|
||||||
headers = {}
|
|
||||||
|
|
||||||
headers['Authorization'] = 'Bearer %s' % self.access_token
|
|
||||||
url = url
|
|
||||||
r = requests.post(url,data=json.dumps(data),headers=headers)
|
|
||||||
if r.status_code == requests.codes.ok:
|
|
||||||
return r.text
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
j = json.loads(r.text)
|
|
||||||
resp = {'error_code': r.status_code,
|
|
||||||
'message' : j['error']['message']}
|
|
||||||
return resp
|
|
||||||
except: #generic error
|
|
||||||
print r.text
|
|
||||||
return "{'error':'There was an error'}"
|
|
||||||
|
|
||||||
|
|
||||||
def followUser(self,user_id):
|
|
||||||
url = "https://%s/stream/0/users/%s/follow" % (self.public_api_anchor, user_id)
|
|
||||||
return self.postRequest(url)
|
|
||||||
|
|
||||||
def repostPost(self,post_id):
|
|
||||||
url = "https://%s/stream/0/posts/%s/repost" % (self.public_api_anchor, post_id)
|
|
||||||
return self.postRequest(url)
|
|
||||||
|
|
||||||
def starPost(self,post_id):
|
|
||||||
url = "https://%s/stream/0/posts/%s/star" % (self.public_api_anchor, post_id)
|
|
||||||
return self.postRequest(url)
|
|
||||||
|
|
||||||
def muteUser(self,user_id):
|
|
||||||
url = "https://%s/stream/0/users/%s/mute" % (self.public_api_anchor, user_id)
|
|
||||||
return self.postRequest(url)
|
|
||||||
|
|
||||||
#requires: text
|
|
||||||
#optional: reply_to, annotations, links
|
|
||||||
def createPost(self, text, reply_to = None, annotations=None, links=None):
|
|
||||||
url = "https://%s/stream/0/posts" % self.public_api_anchor
|
|
||||||
if annotations != None:
|
|
||||||
url = url + "?include_annotations=1"
|
|
||||||
|
|
||||||
data = {'text':text}
|
|
||||||
if reply_to != None:
|
|
||||||
data['reply_to'] = reply_to
|
|
||||||
if annotations != None:
|
|
||||||
data['annotations'] = annotations
|
|
||||||
if links != None:
|
|
||||||
data['links'] = links
|
|
||||||
|
|
||||||
return self.postRequest(url,data,headers={'content-type':'application/json'})
|
|
||||||
|
|
||||||
#DELETE request
|
|
||||||
def deleteRequest(self, url):
|
|
||||||
url = url + "?access_token=" + self.access_token
|
|
||||||
r = requests.delete(url)
|
|
||||||
if r.status_code == requests.codes.ok:
|
|
||||||
return r.text
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
j = json.loads(r.text)
|
|
||||||
resp = {'error_code': r.status_code,
|
|
||||||
'message' : j['error']['message']}
|
|
||||||
return resp
|
|
||||||
except: #generic error
|
|
||||||
print r.text
|
|
||||||
return "{'error':'There was an error'}"
|
|
||||||
|
|
||||||
def deletePost(self, post_id):
|
|
||||||
url = "https://%s/stream/0/posts/%s" % (self.public_api_anchor,post_id)
|
|
||||||
return self.deleteRequest(url)
|
|
||||||
|
|
||||||
def unrepostPost(self, post_id):
|
|
||||||
url = "https://%s/stream/0/posts/%s/repost" % (self.public_api_anchor,post_id)
|
|
||||||
return self.deleteRequest(url)
|
|
||||||
|
|
||||||
def unstarPost(self, post_id):
|
|
||||||
url = "https://%s/stream/0/posts/%s/star" % (self.public_api_anchor,post_id)
|
|
||||||
return self.deleteRequest(url)
|
|
||||||
|
|
||||||
def unfollowUser(self, user_id):
|
|
||||||
url = "https://%s/stream/0/users/%s/follow" % (self.public_api_anchor,user_id)
|
|
||||||
return self.deleteRequest(url)
|
|
||||||
|
|
||||||
def unmuteUser(self, user_id):
|
|
||||||
url = "https://%s/stream/0/users/%s/mute" % (self.public_api_anchor,user_id)
|
|
||||||
return self.deleteRequest(url)
|
|
Loading…
Add table
Reference in a new issue