示例#1
0
def _feed_subscribe_post(request):
    user = request.user

    url = request.GET.get('url')
    if not url:
        return HttpResponseBadRequest('\'url\' missing')

    url = url_normalize(url)

    feed = None
    try:
        feed = models.Feed.objects.get(feed_url=url)
    except models.Feed.DoesNotExist:
        try:
            feed = _save_feed(url)
        except QueryException as e:
            return HttpResponse(e.message, status=e.httpcode)

    custom_title = request.GET.get('customtitle')

    existing_subscription_list = list(models.SubscribedFeedUserMapping.objects.filter(
        user=user).values_list('feed__feed_url', 'custom_feed_title'))

    existing_feed_urls = frozenset(t[0] for t in existing_subscription_list)
    existing_custom_titles = frozenset(
        t[1] for t in existing_subscription_list if t[1] is not None)

    if custom_title is not None and custom_title in existing_custom_titles:
        return HttpResponse('custom title already used', status=409)

    if feed.feed_url in existing_feed_urls:
        return HttpResponse('user already subscribed', status=409)

    read_mapping_generator = archived_feed_entry_util.read_mapping_generator_fn(
        feed, user)

    with transaction.atomic():
        models.SubscribedFeedUserMapping.objects.create(
            user=user, feed=feed, custom_feed_title=custom_title)

        archived_feed_entry_util.mark_archived_entries(read_mapping_generator)

    return HttpResponse(status=204)
示例#2
0
def _opml_post(request):
    if not request.body:
        return HttpResponseBadRequest('no HTTP body')  # pragma: no cover

    opml_element = None
    try:
        opml_element = defused_fromstring(request.body)
    except defused_ParseError:
        return HttpResponseBadRequest('HTTP body cannot be parsed')

    try:
        opml_util.schema().validate(opml_element)
    except xmlschema.XMLSchemaException:
        return HttpResponseBadRequest('OPML not valid')

    outline_dict = {}

    for outer_outline_element in opml_element.findall('./body/outline'):
        outer_outline_name = outer_outline_element.attrib['title']

        if outer_outline_name not in outline_dict:
            outline_dict[outer_outline_name] = set()

        for outline_element in outer_outline_element.findall('./outline'):
            outline_name = outline_element.attrib['title']
            outline_xml_url = url_normalize(outline_element.attrib['xmlUrl'])

            outline_dict[outer_outline_name].add(
                (outline_name, outline_xml_url))

    existing_subscriptions = set(
        models.SubscribedFeedUserMapping.objects.filter(
            user=request.user).values_list('feed__feed_url', flat=True))

    existing_categories = {
        user_category.text: user_category
        for user_category in models.UserCategory.objects.filter(
            user=request.user)
    }

    existing_category_mappings = {}
    for feed_user_category_mapping in models.FeedUserCategoryMapping.objects.select_related(
            'feed', 'user_category').filter(user_category__user=request.user):
        if feed_user_category_mapping.user_category.text not in existing_category_mappings:
            existing_category_mappings[
                feed_user_category_mapping.user_category.text] = set()

        existing_category_mappings[
            feed_user_category_mapping.user_category.text].add(
                feed_user_category_mapping.feed.feed_url)

    feeds_dict = {}

    feed_subscription_progress_entry = None
    feed_subscription_progress_entry_descriptors = []

    for outer_outline_name, outline_set in outline_dict.items():
        for outline_name, outline_xml_url in outline_set:
            if outline_xml_url not in feeds_dict:
                try:
                    feeds_dict[outline_xml_url] = models.Feed.objects.get(
                        feed_url=outline_xml_url)
                except models.Feed.DoesNotExist:
                    if feed_subscription_progress_entry is None:
                        feed_subscription_progress_entry = models.FeedSubscriptionProgressEntry(
                            user=request.user)

                    feed_subscription_progress_entry_descriptor = models.FeedSubscriptionProgressEntryDescriptor(
                        feed_subscription_progress_entry=
                        feed_subscription_progress_entry,
                        feed_url=outline_xml_url,
                        custom_feed_title=outline_name,
                        user_category_text=outer_outline_name)
                    feed_subscription_progress_entry_descriptors.append(
                        feed_subscription_progress_entry_descriptor)

                    feeds_dict[outline_xml_url] = None

    user_categories = []
    subscribed_feed_user_mappings = []
    feed_user_category_mappings = []

    for outer_outline_name, outline_set in outline_dict.items():
        user_category = existing_categories.get(outer_outline_name)
        if user_category is None:
            user_category = models.UserCategory(user=request.user,
                                                text=outer_outline_name)
            user_categories.append(user_category)
            existing_categories[user_category.text] = user_category

        existing_category_mapping_set = existing_category_mappings.get(
            outer_outline_name)

        if existing_category_mapping_set is None:
            existing_category_mapping_set = set()
            existing_category_mappings[
                outer_outline_name] = existing_category_mapping_set

        for outline_name, outline_xml_url in outline_set:
            feed = feeds_dict[outline_xml_url]
            if feed is not None:
                custom_title = outline_name if outline_name != feed.title else None

                if outline_xml_url not in existing_subscriptions:
                    subscribed_feed_user_mapping = models.SubscribedFeedUserMapping(
                        feed=feed,
                        user=request.user,
                        custom_feed_title=custom_title)
                    subscribed_feed_user_mappings.append(
                        subscribed_feed_user_mapping)
                    existing_subscriptions.add(outline_xml_url)

                if outline_xml_url not in existing_category_mapping_set:
                    feed_user_category_mapping = models.FeedUserCategoryMapping(
                        feed=feed, user_category=user_category)
                    feed_user_category_mappings.append(
                        feed_user_category_mapping)
                    existing_category_mapping_set.add(outline_xml_url)

    with transaction.atomic():
        for user_category in user_categories:
            user_category.save()

        models.SubscribedFeedUserMapping.objects.bulk_create(
            subscribed_feed_user_mappings)
        models.FeedUserCategoryMapping.objects.bulk_create(
            feed_user_category_mappings)

        for feed in feeds_dict.values():
            if feed is not None:
                archived_feed_entry_util.mark_archived_entries(
                    archived_feed_entry_util.read_mapping_generator_fn(
                        feed, request.user))

        if feed_subscription_progress_entry is not None:
            feed_subscription_progress_entry.save()

            models.FeedSubscriptionProgressEntryDescriptor.objects.bulk_create(
                feed_subscription_progress_entry_descriptors)

    if feed_subscription_progress_entry is None:
        return HttpResponse(status=204)
    else:
        content, content_type = query_utils.serialize_content(
            str(feed_subscription_progress_entry.uuid))
        return HttpResponse(content, content_type, status=202)
    def test_read_mapping_generator_fn_morethanmincount(self):
        with self.settings(
                USER_UNREAD_GRACE_INTERVAL=datetime.timedelta(days=-7),
                USER_UNREAD_GRACE_MIN_COUNT=1):
            user = models.User.objects.create(email='*****@*****.**')

            feed = models.Feed.objects.create(
                feed_url='http://example.com/rss.xml',
                title='Sample Feed',
                home_url='http://example.com',
                published_at=datetime.datetime.utcnow(),
                updated_at=None,
                db_updated_at=None)

            feed_entry1 = models.FeedEntry(
                id=None,
                feed=feed,
                created_at=None,
                updated_at=None,
                title='Feed Entry 1 Title',
                url='http://example.com/entry1.html',
                content='Some Entry content',
                author_name='John Doe',
                db_updated_at=None)

            feed_entry2 = models.FeedEntry(
                id=None,
                feed=feed,
                created_at=None,
                updated_at=None,
                title='Feed Entry 2 Title',
                url='http://example.com/entry2.html',
                content='Some Entry content',
                author_name='John Doe',
                db_updated_at=None)

            feed_entry3 = models.FeedEntry(
                id=None,
                feed=feed,
                created_at=None,
                updated_at=None,
                title='Feed Entry 3 Title',
                url='http://example.com/entry3.html',
                content='Some Entry content',
                author_name='John Doe',
                db_updated_at=None)

            feed_entry4 = models.FeedEntry(
                id=None,
                feed=feed,
                created_at=None,
                updated_at=None,
                title='Feed Entry 4 Title',
                url='http://example.com/entry4.html',
                content='Some Entry content',
                author_name='John Doe',
                db_updated_at=None)

            models.FeedEntry.objects.bulk_create(
                [feed_entry1, feed_entry2, feed_entry3, feed_entry4])

            feed_entry1.published_at = user.created_at + \
                settings.USER_UNREAD_GRACE_INTERVAL + \
                datetime.timedelta(days=-1, minutes=-10)
            feed_entry1.save(update_fields=['published_at'])

            feed_entry2.published_at = user.created_at + \
                settings.USER_UNREAD_GRACE_INTERVAL + \
                datetime.timedelta(days=-1, minutes=-20)
            feed_entry2.save(update_fields=['published_at'])

            read_mappings = list(
                archived_feed_entry_util.read_mapping_generator_fn(feed, user))
            self.assertEqual(len(read_mappings), 2)