mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-09-18 21:50:56 +00:00
Adding new API endpoint: mark_feed_stories_as_read. Refactored mark_story_as_read.
This commit is contained in:
parent
f821309015
commit
c91016a1ce
7 changed files with 110 additions and 44 deletions
|
@ -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")
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -377,7 +377,7 @@ $(document).ready(function() {
|
|||
<div class="NB-module-item-title">
|
||||
<span class="NB-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 %}">
|
||||
|
|
|
@ -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)."
|
||||
|
|
Loading…
Add table
Reference in a new issue