import logging
import datetime
import threading
import random
from django.shortcuts import render_to_response, get_list_or_404, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.template import RequestContext
from django.db import IntegrityError
from django.core.cache import cache
from django.views.decorators.cache import never_cache
from django.db.models import Q
from django.db.models.aggregates import Count
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
from django.contrib.auth import login
from django.http import HttpResponse, HttpRequest, HttpResponseRedirect
from apps.analyzer.models import ClassifierFeed, ClassifierAuthor, ClassifierTag, ClassifierTitle
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
from apps.reader.models import UserSubscription, UserSubscriptionFolders, UserStory
from apps.reader.forms import SignupForm, LoginForm
try:
from apps.rss_feeds.models import Feed, Story, Tag, StoryAuthor
except:
pass
from utils import json, feedfinder
from utils.user_functions import get_user
SINGLE_DAY = 60*60*24
@never_cache
def index(request):
if request.method == "POST":
if request.POST['submit'] == 'login':
login_form = LoginForm(request.POST, prefix='login')
signup_form = SignupForm(prefix='signup')
else:
login_form = LoginForm(prefix='login')
signup_form = SignupForm(request.POST, prefix='signup')
else:
login_form = LoginForm(prefix='login')
signup_form = SignupForm(prefix='signup')
return render_to_response('reader/feeds.xhtml', {
'login_form': login_form,
'signup_form': signup_form,
}, context_instance=RequestContext(request))
@never_cache
def login(request):
if request.method == "POST":
form = LoginForm(request.POST, prefix='login')
if form.is_valid():
login(request, form.get_user())
return HttpResponseRedirect(reverse('index'))
return index(request)
@never_cache
def signup(request):
if request.method == "POST":
form = SignupForm(prefix='signup', data=request.POST)
if form.is_valid():
new_user = form.save()
login(request, new_user)
return HttpResponseRedirect(reverse('index'))
return index(request)
@never_cache
def logout(request):
print "Logout: %s" % request.user
from django.contrib.auth import logout
logout(request)
return HttpResponseRedirect(reverse('index'))
def load_feeds(request):
user = get_user(request)
feeds = {}
try:
folders = UserSubscriptionFolders.objects.get(user=user)
except UserSubscriptionFolders.DoesNotExist:
data = dict(feeds=[], folders=[])
return HttpResponse(json.encode(data), mimetype='application/json')
user_subs = UserSubscription.objects.select_related('feed').filter(user=user)
for sub in user_subs:
if sub.needs_unread_recalc:
sub.calculate_feed_scores()
feeds[sub.feed.pk] = {
'id': sub.feed.pk,
'feed_title': sub.feed.feed_title,
'feed_link': sub.feed.feed_link,
'ps': sub.unread_count_positive,
'nt': sub.unread_count_neutral,
'ng': sub.unread_count_negative,
}
data = dict(feeds=feeds, folders=json.decode(folders.folders))
return HttpResponse(json.encode(data), mimetype='application/json')
def refresh_feeds(request):
user = get_user(request)
feeds = {}
user_subs = UserSubscription.objects.select_related('feed').filter(user=user)
for sub in user_subs:
if sub.needs_unread_recalc:
sub.calculate_feed_scores()
feeds[sub.feed.pk] = {
'ps': sub.unread_count_positive,
'nt': sub.unread_count_neutral,
'ng': sub.unread_count_negative,
}
return HttpResponse(json.encode(feeds), mimetype='application/json')
def load_single_feed(request):
user = get_user(request)
offset = int(request.REQUEST.get('offset', 0))
limit = int(request.REQUEST.get('limit', 30))
page = int(request.REQUEST.get('page', 0))
if page:
offset = limit * page
feed_id = request.REQUEST['feed_id']
feed = Feed.objects.get(id=feed_id)
force_update = request.GET.get('force_update', False)
stories = feed.get_stories(offset, limit)
if force_update:
feed.update(force_update)
# Get intelligence classifier for user
classifier_feeds = ClassifierFeed.objects.filter(user=user, feed=feed)
classifier_authors = ClassifierAuthor.objects.filter(user=user, feed=feed)
classifier_titles = ClassifierTitle.objects.filter(user=user, feed=feed)
classifier_tags = ClassifierTag.objects.filter(user=user, feed=feed)
usersub = UserSubscription.objects.get(user=user, feed=feed)
# print "Feed: %s %s" % (feed, usersub)
logging.debug("Feed: " + feed.feed_title)
userstory = UserStory.objects.filter(
user=user,
feed=feed.id,
read_date__gt=usersub.mark_read_date
).values()
for story in stories:
for o in userstory:
if o['story_id'] == story.get('id'):
story['opinion'] = o['opinion']
story['read_status'] = (o['read_date'] is not None)
break
if not story.get('read_status') and story['story_date'] < usersub.mark_read_date:
story['read_status'] = 1
elif not story.get('read_status') and story['story_date'] > usersub.last_read_date:
story['read_status'] = 0
story['intelligence'] = {
'feed': apply_classifier_feeds(classifier_feeds, feed),
'author': apply_classifier_authors(classifier_authors, story),
'tags': apply_classifier_tags(classifier_tags, story),
'title': apply_classifier_titles(classifier_titles, story),
}
# logging.debug("Story: %s" % story)
# Intelligence
all_tags = Tag.objects.filter(feed=feed)\
.annotate(stories_count=Count('story'))\
.order_by('-stories_count')[:20]
feed_tags = [(tag.name, tag.stories_count) for tag in all_tags if tag.stories_count > 1]
all_authors = StoryAuthor.objects.filter(feed=feed)\
.annotate(stories_count=Count('story'))\
.order_by('-stories_count')[:20]
feed_authors = [(author.author_name, author.stories_count) for author in all_authors\
if author.stories_count > 1]
classifiers = get_classifiers_for_user(user, feed_id, classifier_feeds,
classifier_authors, classifier_titles, classifier_tags)
context = dict(stories=stories, feed_tags=feed_tags, feed_authors=feed_authors, classifiers=classifiers)
data = json.encode(context)
return HttpResponse(data, mimetype='application/json')
def load_feed_page(request):
feed = Feed.objects.get(id=request.REQUEST.get('feed_id'))
if feed.page_data:
data = feed.page_data
else:
data = "Give it 10 minutes...
Your feed will be here in under 5 minutes (on average).
Soon there will be a progress bar. Until then, take a deep breath."
return HttpResponse(data, mimetype='text/html')
@login_required
def mark_story_as_read(request):
story_ids = request.REQUEST['story_id'].split(',')
feed_id = int(request.REQUEST['feed_id'])
usersub = UserSubscription.objects.get(user=request.user, feed=feed_id)
if not usersub.needs_unread_recalc:
usersub.needs_unread_recalc = True
usersub.save()
data = dict(code=0, payload=story_ids)
for story_id in story_ids:
logging.debug("Marked Read: %s (%s)" % (story_id, feed_id))
m = UserStory(story_id=int(story_id), user=request.user, feed_id=feed_id)
try:
m.save()
data.update({'code': 1})
except IntegrityError, e:
data.update({'code': -1})
return HttpResponse(json.encode(data))
@login_required
def mark_feed_as_read(request):
feed_id = int(request.REQUEST['feed_id'])
feed = Feed.objects.get(id=feed_id)
code = 0
us = UserSubscription.objects.get(feed=feed, user=request.user)
try:
us.mark_feed_read()
except IntegrityError, e:
code = -1
else:
code = 1
data = json.encode(dict(code=code))
# UserStory.objects.filter(user=request.user, feed=feed_id).delete()
return HttpResponse(data)
@login_required
def mark_story_as_like(request):
return mark_story_with_opinion(request, 1)
@login_required
def mark_story_as_dislike(request):
return mark_story_with_opinion(request, -1)
@login_required
def mark_story_with_opinion(request, opinion):
story_id = request.REQUEST['story_id']
story = Story.objects.select_related("story_feed").get(id=story_id)
previous_opinion = UserStory.objects.get(story=story,
user=request.user,
feed=story.story_feed)
if previous_opinion and previous_opinion.opinion != opinion:
previous_opinion.opinion = opinion
data = json.encode(dict(code=0))
previous_opinion.save()
logging.debug("Changed Opinion: " + str(previous_opinion.opinion) + ' ' + str(opinion))
else:
logging.debug("Marked Opinion: " + str(story_id) + ' ' + str(opinion))
m = UserStory(story=story, user=request.user, feed=story.story_feed, opinion=opinion)
data = json.encode(dict(code=0))
try:
m.save()
except:
data = json.encode(dict(code=2))
return HttpResponse(data)
@login_required
def get_read_feed_items(request, username):
feeds = get_list_or_404(Feed)
def _parse_user_info(user):
return {
'user_info': {
'is_anonymous': json.encode(user.is_anonymous()),
'is_authenticated': json.encode(user.is_authenticated()),
'username': json.encode(user.username if user.is_authenticated() else 'Anonymous')
}
}
@login_required
def add_url(request):
code = 0
url = request.POST['url']
folder = request.POST['folder']
feed = None
if url:
feed = Feed.objects.filter(Q(feed_address=url)
| Q(feed_link__icontains=url))
if feed:
feed = feed[0]
else:
feed_finder_url = feedfinder.feed(url)
if feed_finder_url:
try:
feed = Feed.objects.get(feed_address=feed_finder_url)
except Feed.DoesNotExist:
try:
feed = Feed(feed_address=feed_finder_url)
feed.save()
feed.update()
except:
code = -2
message = "This feed has been added, but something went wrong"\
" when downloading it. Maybe the server's busy."
if not feed:
code = -1
message = "That URL does not point to a website or RSS feed."
else:
us, _ = UserSubscription.objects.get_or_create(
feed=feed,
user=request.user,
defaults={'needs_unread_recalc': True}
)
code = 1
message = ""
user_sub_folders_object, created = UserSubscriptionFolders.objects.get_or_create(user=request.user,
defaults={'folders': '[]'}
)
if created:
user_sub_folders = []
else:
user_sub_folders = json.decode(user_sub_folders_object.folders)
user_sub_folders = _add_object_to_folder(feed.pk, folder, user_sub_folders)
user_sub_folders_object.folders = json.encode(user_sub_folders)
user_sub_folders_object.save()
data = dict(code=code, message=message)
return HttpResponse(json.encode(data))
def _add_object_to_folder(obj, folder, folders):
if not folder:
folders.append(obj)
return folders
for k, v in enumerate(folders):
if isinstance(v, dict):
for f_k, f_v in v.items():
if f_k == folder:
f_v.append(obj)
folders[k][f_k] = _add_object_to_folder(obj, folder, f_v)
return folders
@login_required
def add_folder(request):
folder = request.POST['folder']
parent_folder = request.POST['parent_folder']
if folder:
code = 1
message = ""
user_sub_folders_object, _ = UserSubscriptionFolders.objects.get_or_create(user=request.user)
if user_sub_folders_object.folders:
user_sub_folders = json.decode(user_sub_folders_object.folders)
else:
user_sub_folders = []
obj = {folder: []}
user_sub_folders = _add_object_to_folder(obj, parent_folder, user_sub_folders)
user_sub_folders_object.folders = json.encode(user_sub_folders)
user_sub_folders_object.save()
else:
code = -1
message = "Gotta write in a folder name."
data = dict(code=code, message=message)
return HttpResponse(json.encode(data))
@login_required
def delete_feed(request):
feed_id = int(request.POST['feed_id'])
user_sub = get_object_or_404(UserSubscription, user=request.user, feed=feed_id)
user_sub.delete()
user_stories = UserStory.objects.filter(user=request.user, feed=feed_id)
user_stories.delete()
def _find_feed_in_folders(folders):
for k, folder in enumerate(list(folders)):
if isinstance(folder, int):
if folder == feed_id:
print "DEL'ED: %s'th item: %s" % (k, folders)
folders.remove(folder)
elif isinstance(folder, dict):
for f_k, f_v in folder.items():
folders[k][f_k] = _find_feed_in_folders(f_v)
return folders
user_sub_folders_object = UserSubscriptionFolders.objects.get(user=request.user)
user_sub_folders = json.decode(user_sub_folders_object.folders)
user_sub_folders = _find_feed_in_folders(user_sub_folders)
user_sub_folders_object.folders = json.encode(user_sub_folders)
user_sub_folders_object.save()
data = json.encode(dict(code=1))
return HttpResponse(data)