Adding new API endpoint: mark_feed_stories_as_read. Refactored mark_story_as_read.

This commit is contained in:
Samuel Clay 2011-11-05 16:25:04 -07:00
parent f821309015
commit c91016a1ce
7 changed files with 110 additions and 44 deletions

View file

@ -6,6 +6,7 @@ from django.db import models, IntegrityError
from django.conf import settings
from django.contrib.auth.models import User
from django.core.cache import cache
from mongoengine.queryset import OperationError
from apps.reader.managers import UserSubscriptionManager
from apps.rss_feeds.models import Feed, MStory, DuplicateFeed
from apps.analyzer.models import MClassifierFeed, MClassifierAuthor, MClassifierTag, MClassifierTitle
@ -140,6 +141,48 @@ class UserSubscription(models.Model):
MUserStory.delete_marked_as_read_stories(self.user.pk, self.feed.pk)
self.save()
def mark_story_ids_as_read(self, story_ids, request=None):
data = dict(code=0, payload=story_ids)
if not request:
request = self.user
if not self.needs_unread_recalc:
self.needs_unread_recalc = True
self.save()
if len(story_ids) > 1:
logging.user(request, "~FYRead %s stories in feed: %s" % (len(story_ids), self.feed))
else:
logging.user(request, "~FYRead story in feed: %s" % (self.feed))
for story_id in story_ids:
try:
story = MStory.objects.get(story_feed_id=self.feed.pk, story_guid=story_id)
except MStory.DoesNotExist:
# Story has been deleted, probably by feed_fetcher.
continue
except MStory.MultipleObjectsReturned:
continue
now = datetime.datetime.utcnow()
date = now if now > story.story_date else story.story_date # For handling future stories
m = MUserStory(story=story, user_id=self.user.pk, feed_id=self.feed.pk, read_date=date, story_id=story_id)
try:
m.save()
except OperationError, e:
original_m = MUserStory.objects.get(story=story, user_id=self.user.pk, feed_id=self.feed.pk)
logging.user(request, "~BRMarked story as read error: %s" % (e))
logging.user(request, "~BRMarked story as read: %s" % (story_id))
logging.user(request, "~BROrigin story as read: %s" % (m.story.story_guid))
logging.user(request, "~BRMarked story id: %s" % (original_m.story_id))
logging.user(request, "~BROrigin story guid: %s" % (original_m.story.story_guid))
logging.user(request, "~BRRead now date: %s, original read: %s, story_date: %s." % (m.read_date, original_m.read_date, story.story_date))
original_m.story_id = story_id
original_m.read_date = date
original_m.save()
return data
def calculate_feed_scores(self, silent=False, stories_db=None):
# now = datetime.datetime.strptime("2009-07-06 22:30:03", "%Y-%m-%d %H:%M:%S")

View file

@ -18,6 +18,7 @@ urlpatterns = patterns('',
url(r'^starred_stories', views.load_starred_stories, name='load-starred-stories'),
url(r'^mark_all_as_read', views.mark_all_as_read, name='mark-all-as-read'),
url(r'^mark_story_as_read', views.mark_story_as_read, name='mark-story-as-read'),
url(r'^mark_feed_stories_as_read', views.mark_feed_stories_as_read, name='mark-feed-stories-as-read'),
url(r'^mark_story_as_unread', views.mark_story_as_unread),
url(r'^mark_story_as_starred', views.mark_story_as_starred),
url(r'^mark_story_as_unstarred', views.mark_story_as_unstarred),

View file

@ -17,7 +17,6 @@ from django.core.validators import email_re
from django.core.mail import EmailMultiAlternatives
from collections import defaultdict
from operator import itemgetter
from mongoengine.queryset import OperationError
from apps.recommendations.models import RecommendedFeed
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
@ -659,43 +658,34 @@ def mark_story_as_read(request):
return dict(code=-1)
else:
return dict(code=-1)
if not usersub.needs_unread_recalc:
usersub.needs_unread_recalc = True
usersub.save()
data = dict(code=0, payload=story_ids)
if len(story_ids) > 1:
logging.user(request, "~FYRead %s stories in feed: %s" % (len(story_ids), usersub.feed))
else:
logging.user(request, "~FYRead story in feed: %s" % (usersub.feed))
for story_id in story_ids:
try:
story = MStory.objects.get(story_feed_id=feed_id, story_guid=story_id)
except MStory.DoesNotExist:
# Story has been deleted, probably by feed_fetcher.
continue
except MStory.MultipleObjectsReturned:
continue
now = datetime.datetime.utcnow()
date = now if now > story.story_date else story.story_date # For handling future stories
m = MUserStory(story=story, user_id=request.user.pk, feed_id=feed_id, read_date=date, story_id=story_id)
try:
m.save()
except OperationError, e:
original_m = MUserStory.objects.get(story=story, user_id=request.user.pk, feed_id=feed_id)
logging.user(request, "~BRMarked story as read error: %s" % (e))
logging.user(request, "~BRMarked story as read: %s / %s" % (story_id, m.story.story_guid))
logging.user(request, "~BROriginal story id: %s / %s" % (original_m.story_id, original_m.story.story_guid))
logging.user(request, "~BRRead now date: %s, original read: %s, story_date: %s." % (m.read_date, original_m.read_date, story.story_date))
original_m.story_id = story_id
original_m.read_date = date
original_m.save()
data = usersub.mark_story_ids_as_read(story_ids, request=request)
return data
@ajax_login_required
@json.json_view
def mark_feed_stories_as_read(request):
feeds_stories = request.REQUEST.get('feeds_stories', {})
for feed_id, story_ids in feeds_stories.items():
try:
usersub = UserSubscription.objects.select_related('feed').get(user=request.user, feed=feed_id)
except (UserSubscription.DoesNotExist, Feed.DoesNotExist):
duplicate_feed = DuplicateFeed.objects.filter(duplicate_feed_id=feed_id)
if duplicate_feed:
try:
usersub = UserSubscription.objects.get(user=request.user,
feed=duplicate_feed[0].feed)
except (UserSubscription.DoesNotExist, Feed.DoesNotExist):
continue
else:
continue
usersub.mark_story_ids_as_read(story_ids)
return dict(code=1)
@ajax_login_required
@json.json_view
def mark_story_as_unread(request):

View file

@ -21,6 +21,8 @@
#define kTableViewRowHeight 65;
#define kTableViewRiverRowHeight 81;
#define kMarkReadActionSheet 1;
#define kSettingsActionSheet 2;
@implementation FeedDetailViewController
@ -613,6 +615,10 @@
}
}
- (void)markFeedsReadWithAllStories:(BOOL)includeHidden {
}
- (IBAction)doOpenMarkReadActionSheet:(id)sender {
UIActionSheet *options = [[UIActionSheet alloc]
initWithTitle:appDelegate.activeFolder
@ -621,17 +627,18 @@
destructiveButtonTitle:nil
otherButtonTitles:nil];
int storyCount = [appDelegate storyCount];
NSString *visibleText = [NSString stringWithFormat:@"Mark %@ %d stor%@ read",
storyCount == 1 ? @"this" : @"these",
storyCount,
storyCount == 1 ? @"y" : @"ies"];
int unreadCount = [[appDelegate activeFeedStoryLocations] count];
NSString *visibleText = [NSString stringWithFormat:@"Mark %@ read",
unreadCount == 1 ?
@"this story as" :
[NSString stringWithFormat:@"these %d stories", unreadCount]];
NSArray *buttonTitles = [NSArray arrayWithObjects:visibleText, @"Mark entire folder read", nil];
for (id title in buttonTitles) {
[options addButtonWithTitle:title];
}
options.cancelButtonIndex = [options addButtonWithTitle:@"Cancel"];
options.tag = kMarkReadActionSheet;
[options showInView:self.view];
[options release];
}
@ -650,13 +657,22 @@
}
options.cancelButtonIndex = [options addButtonWithTitle:@"Cancel"];
options.tag = kSettingsActionSheet;
[options showInView:self.view];
[options release];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
[self confirmDeleteSite];
if (actionSheet.tag == 1) {
if (buttonIndex == 0) {
[self markFeedsReadWithAllStories:NO];
} else if (buttonIndex == 1) {
[self markFeedsReadWithAllStories:YES];
}
} else if (actionSheet.tag == 2) {
if (buttonIndex == 0) {
[self confirmDeleteSite];
}
}
}

View file

@ -15,7 +15,7 @@
// #define BACKGROUND_REFRESH_SECONDS -5
#define BACKGROUND_REFRESH_SECONDS -10*60
// #define NEWSBLUR_URL [NSString stringWithFormat:@"nb.local.host:8000"]
#define NEWSBLUR_URL [NSString stringWithFormat:@"www.newsblur.com"]
#define NEWSBLUR_URL [NSString stringWithFormat:@"nb.local.host:8000"]
// #define NEWSBLUR_URL [NSString stringWithFormat:@"www.newsblur.com"]
#endif

View file

@ -377,7 +377,7 @@ $(document).ready(function() {
<div class="NB-module-item-title">
<span class="NB-raquo">&raquo;</span>
<!-- <a href="#" class="NB-splash-link">Download NewsBlur on the App Store</a> -->
<span class="NB-module-mobile-freeforpremium">Approved, but not Good Enough. Working on v1.1.</span>
<span class="NB-module-mobile-freeforpremium">Approved, but not Good Enough. Working on v1.2.</span>
</div>
</div>
<div class="NB-module-item NB-last {% if user_profile.hide_mobile %}NB-hidden{% endif %}">

View file

@ -228,6 +228,22 @@
required: true
example: "42"
- url: /reader/mark_feed_stories_as_read
method: POST
short_desc: "Mark stories from multiple feeds as read."
long_desc:
- "Marks multiple stories as read."
- "Multiple story ids can be sent at once."
- "Multiple feeds can be sent."
tips:
- "Throttle requests to this endpoint. You don't need to send one request per story."
- "Queue up to 5 stories or once every 10 seconds before firing, whichever comes first."
params:
- key: feeds_stories
desc: "Dictionary of feed_ids to an array of story_ids."
required: true
example: "{<br>12: ['story_id_1', 'story_id_2'],<br>24: ['story_id_3']<br>}"
- url: /reader/mark_story_as_starred
method: POST
short_desc: "Mark a story as starred (saved)."