NewsBlur/apps/feed_import/views.py

280 lines
No EOL
12 KiB
Python

import datetime
import pickle
import base64
import httplib2
from utils import log as logging
from oauth2client.client import OAuth2WebServerFlow, FlowExchangeError
from bson.errors import InvalidStringData
import uuid
from django.contrib.sites.models import Site
# from django.db import IntegrityError
from django.http import HttpResponse, HttpResponseRedirect
from django.conf import settings
from django.core.urlresolvers import reverse
from django.template import RequestContext
from django.contrib.auth import login as login_user
from django.shortcuts import render_to_response
from apps.reader.forms import SignupForm
from apps.reader.models import UserSubscription
from apps.feed_import.models import OAuthToken, GoogleReaderImporter
from apps.feed_import.models import OPMLImporter, OPMLExporter, UploadedOPML
from apps.feed_import.tasks import ProcessOPML, ProcessReaderImport, ProcessReaderStarredImport
from utils import json_functions as json
from utils.user_functions import ajax_login_required, get_user
from utils.feed_functions import TimeoutError
@ajax_login_required
def opml_upload(request):
xml_opml = None
message = "OK"
code = 1
payload = {}
if request.method == 'POST':
if 'file' in request.FILES:
logging.user(request, "~FR~SBOPML upload starting...")
file = request.FILES['file']
xml_opml = str(file.read().decode('utf-8', 'ignore'))
try:
UploadedOPML.objects.create(user_id=request.user.pk, opml_file=xml_opml)
except (UnicodeDecodeError, InvalidStringData):
folders = None
code = -1
message = "There was a Unicode decode error when reading your OPML file."
opml_importer = OPMLImporter(xml_opml, request.user)
try:
folders = opml_importer.try_processing()
except TimeoutError:
folders = None
ProcessOPML.delay(request.user.pk)
feed_count = opml_importer.count_feeds_in_opml()
logging.user(request, "~FR~SBOPML pload took too long, found %s feeds. Tasking..." % feed_count)
payload = dict(folders=folders, delayed=True, feed_count=feed_count)
code = 2
message = ""
except AttributeError:
code = -1
message = "OPML import failed. Couldn't parse XML file."
folders = None
if folders:
code = 1
feeds = UserSubscription.objects.filter(user=request.user).values()
payload = dict(folders=folders, feeds=feeds)
logging.user(request, "~FR~SBOPML Upload: ~SK%s~SN~SB~FR feeds" % (len(feeds)))
request.session['import_from_google_reader'] = False
else:
message = "Attach an .opml file."
code = -1
return HttpResponse(json.encode(dict(message=message, code=code, payload=payload)),
mimetype='text/html')
def opml_export(request):
user = get_user(request)
exporter = OPMLExporter(user)
opml = exporter.process()
now = datetime.datetime.now()
response = HttpResponse(opml, mimetype='text/xml')
response['Content-Disposition'] = 'attachment; filename=NewsBlur Subscriptions - %s' % (
now.strftime('%Y-%m-%d')
)
return response
def reader_authorize(request):
ip = request.META.get('HTTP_X_REAL_IP', None) or request.META.get('REMOTE_ADDR', "")
reader_importer = GoogleReaderImporter(request.user)
if reader_importer.test():
logging.user(request, "~BB~FW~SBSkipping Google Reader import, already tokened")
return render_to_response('social/social_connect.xhtml', {
}, context_instance=RequestContext(request))
domain = Site.objects.get_current().domain
STEP2_URI = "http://%s%s" % (
(domain + '.com') if not domain.endswith('.com') else domain,
reverse('google-reader-callback'),
)
FLOW = OAuth2WebServerFlow(
client_id=settings.GOOGLE_OAUTH2_CLIENTID,
client_secret=settings.GOOGLE_OAUTH2_SECRET,
scope="http://www.google.com/reader/api",
redirect_uri=STEP2_URI,
user_agent='NewsBlur Pro, www.newsblur.com',
approval_prompt="force",
)
logging.user(request, "~BB~FW~SBAuthorize Google Reader import - %s" % (
request.META.get('HTTP_X_REAL_IP', None) or request.META.get('REMOTE_ADDR', ""),
))
authorize_url = FLOW.step1_get_authorize_url(redirect_uri=STEP2_URI)
response = render_to_response('social/social_connect.xhtml', {
'next': authorize_url,
}, context_instance=RequestContext(request))
# Save request token and delete old tokens
auth_token_dict = dict()
if request.user.is_authenticated():
OAuthToken.objects.filter(user=request.user).delete()
auth_token_dict['user'] = request.user
else:
OAuthToken.objects.filter(session_id=request.session.session_key).delete()
OAuthToken.objects.filter(remote_ip=ip).delete()
auth_token_dict['uuid'] = str(uuid.uuid4())
auth_token_dict['session_id'] = request.session.session_key
auth_token_dict['remote_ip'] = ip
OAuthToken.objects.create(**auth_token_dict)
response.set_cookie('newsblur_reader_uuid', str(uuid.uuid4()))
return response
def reader_callback(request):
ip = request.META.get('HTTP_X_REAL_IP', None) or request.META.get('REMOTE_ADDR', "")
domain = Site.objects.get_current().domain
STEP2_URI = "http://%s%s" % (
(domain + '.com') if not domain.endswith('.com') else domain,
reverse('google-reader-callback'),
)
FLOW = OAuth2WebServerFlow(
client_id=settings.GOOGLE_OAUTH2_CLIENTID,
client_secret=settings.GOOGLE_OAUTH2_SECRET,
scope="http://www.google.com/reader/api",
redirect_uri=STEP2_URI,
user_agent='NewsBlur Pro, www.newsblur.com',
)
FLOW.redirect_uri = STEP2_URI
http = httplib2.Http()
http.disable_ssl_certificate_validation = True
try:
credential = FLOW.step2_exchange(request.REQUEST)
except FlowExchangeError:
logging.info(" ***> [%s] Bad token from Google Reader." % (request.user,))
return render_to_response('social/social_connect.xhtml', {
'error': 'There was an error trying to import from Google Reader. Trying again will probably fix the issue.'
}, context_instance=RequestContext(request))
user_token = None
if request.user.is_authenticated():
user_token = OAuthToken.objects.filter(user=request.user).order_by('-created_date')
if not user_token:
user_uuid = request.COOKIES.get('newsblur_reader_uuid')
if user_uuid:
user_token = OAuthToken.objects.filter(uuid=user_uuid).order_by('-created_date')
if not user_token:
session = request.session
if session.session_key:
user_token = OAuthToken.objects.filter(session_id=request.session.session_key).order_by('-created_date')
if not user_token:
user_token = OAuthToken.objects.filter(remote_ip=ip).order_by('-created_date')
if user_token:
user_token = user_token[0]
user_token.credential = base64.b64encode(pickle.dumps(credential))
user_token.session_id = request.session.session_key
user_token.save()
# Fetch imported feeds on next page load
request.session['import_from_google_reader'] = True
logging.user(request, "~BB~FW~SBFinishing Google Reader import - %s" % ip)
if request.user.is_authenticated():
return render_to_response('social/social_connect.xhtml', {}, context_instance=RequestContext(request))
return HttpResponseRedirect(reverse('import-signup'))
@json.json_view
def import_from_google_reader(request):
code = 0
feed_count = 0
starred_count = 0
delayed = False
if request.user.is_authenticated():
reader_importer = GoogleReaderImporter(request.user)
auto_active = bool(request.REQUEST.get('auto_active') or False)
try:
code = reader_importer.try_import_feeds(auto_active=auto_active)
except TimeoutError:
ProcessReaderImport.delay(request.user.pk, auto_active=auto_active)
feed_count = UserSubscription.objects.filter(user=request.user).count()
logging.user(request, "~FR~SBGoogle Reader import took too long, found %s feeds. Tasking..." % feed_count)
delayed = True
code = 2
if 'import_from_google_reader' in request.session:
del request.session['import_from_google_reader']
feed_count = UserSubscription.objects.filter(user=request.user).count()
return dict(code=code, delayed=delayed, feed_count=feed_count, starred_count=starred_count)
@json.json_view
def import_starred_stories_from_google_reader(request):
code = 0
feed_count = 0
starred_count = 0
delayed = False
if request.user.is_authenticated():
reader_importer = GoogleReaderImporter(request.user)
try:
starred_count = reader_importer.try_import_starred_stories()
except TimeoutError:
ProcessReaderStarredImport.delay(request.user.pk)
feed_count = UserSubscription.objects.filter(user=request.user).count()
logging.user(request, "~FR~SBGoogle Reader starred stories import took too long, found %s feeds, %s stories. Tasking..." % (feed_count, starred_count))
delayed = True
code = 2
feed_count = UserSubscription.objects.filter(user=request.user).count()
return dict(code=code, delayed=delayed, feed_count=feed_count, starred_count=starred_count)
def import_signup(request):
ip = request.META.get('HTTP_X_REAL_IP', None) or request.META.get('REMOTE_ADDR', "")
if request.method == "POST":
signup_form = SignupForm(prefix='signup', data=request.POST)
if signup_form.is_valid():
new_user = signup_form.save()
user_token = OAuthToken.objects.filter(user=new_user)
if not user_token:
user_uuid = request.COOKIES.get('newsblur_reader_uuid')
if user_uuid:
user_token = OAuthToken.objects.filter(uuid=user_uuid).order_by('-created_date')
if not user_token:
if request.session.session_key:
user_token = OAuthToken.objects.filter(session_id=request.session.session_key).order_by('-created_date')
if not user_token:
user_token = OAuthToken.objects.filter(remote_ip=ip).order_by('-created_date')
if user_token:
user_token = user_token[0]
user_token.session_id = request.session.session_key
user_token.user = new_user
user_token.save()
login_user(request, new_user)
if request.user.profile.is_premium:
return HttpResponseRedirect(reverse('index'))
url = "https://%s%s" % (Site.objects.get_current().domain,
reverse('stripe-form'))
return HttpResponseRedirect(url)
else:
logging.user(request, "~BR~FW ***> Can't find user token during import/signup. Re-authenticating...")
return HttpResponseRedirect(reverse('google-reader-authorize'))
else:
signup_form = SignupForm(prefix='signup')
return render_to_response('import/signup.xhtml', {
'signup_form': signup_form,
}, context_instance=RequestContext(request))