示例#1
0
def _feed_entry_read_post(request, uuid_):
    context = Context()
    context.parse_request(request)
    context.parse_query_dict(request.GET)

    read_feed_entry_user_mapping = None

    with transaction.atomic():
        feed_entry = None
        try:
            feed_entry = models.FeedEntry.objects.get(uuid=uuid_)
        except models.FeedEntry.DoesNotExist:
            return HttpResponseNotFound('feed entry not found')

        try:
            read_feed_entry_user_mapping = models.ReadFeedEntryUserMapping.objects.get(
                feed_entry=feed_entry, user=request.user)
        except models.ReadFeedEntryUserMapping.DoesNotExist:
            read_feed_entry_user_mapping = models.ReadFeedEntryUserMapping.objects.create(
                feed_entry=feed_entry, user=request.user)

    ret_obj = context.format_datetime(read_feed_entry_user_mapping.read_at)

    content, content_type = query_utils.serialize_content(ret_obj)
    return HttpResponse(content, content_type)
示例#2
0
def _user_category_get(request, uuid_):
    context = Context()
    context.parse_request(request)
    context.parse_query_dict(request.GET)

    field_maps = None
    try:
        fields = query_utils.get_fields__query_dict(request.GET)
        field_maps = query_utils.get_field_maps(fields, _OBJECT_NAME)
    except QueryException as e:  # pragma: no cover
        return HttpResponse(e.message, status=e.httpcode)

    user_category = None
    try:
        user_category = models.UserCategory.objects.get(uuid=uuid_,
                                                        user=request.user)
    except models.UserCategory.DoesNotExist:
        return HttpResponseNotFound('user category not found')

    ret_obj = query_utils.generate_return_object(field_maps, user_category,
                                                 context)

    content, content_type = query_utils.serialize_content(ret_obj)

    return HttpResponse(content, content_type)
示例#3
0
def _feed_get(request):
    context = Context()
    context.parse_request(request)
    context.parse_query_dict(request.GET)

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

    url = url_normalize(url)

    field_maps = None
    try:
        fields = query_utils.get_fields__query_dict(request.GET)
        field_maps = query_utils.get_field_maps(fields, _OBJECT_NAME)
    except QueryException as e:  # pragma: no cover
        return HttpResponse(e.message, status=e.httpcode)

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

    ret_obj = query_utils.generate_return_object(field_maps, feed, context)

    content, content_type = query_utils.serialize_content(ret_obj)

    return HttpResponse(content, content_type)
示例#4
0
def _feed_subscription_progress_get(request, uuid_):
    feed_subscription_progress_entry = None
    try:
        feed_subscription_progress_entry = models.FeedSubscriptionProgressEntry.objects.get(
            uuid=uuid_, user=request.user)
    except models.FeedSubscriptionProgressEntry.DoesNotExist:
        return HttpResponseNotFound('progress not found')

    progress_statuses = list(
        models.FeedSubscriptionProgressEntryDescriptor.objects.filter(
            feed_subscription_progress_entry=feed_subscription_progress_entry).
        values_list('is_finished', flat=True))

    total_count = len(progress_statuses)

    finished_count = sum(1 for is_finished in progress_statuses if is_finished)

    ret_obj = {
        'totalCount': total_count,
        'finishedCount': finished_count,
    }
    if feed_subscription_progress_entry.status == models.FeedSubscriptionProgressEntry.NOT_STARTED:
        ret_obj['state'] = 'notstarted'
    elif feed_subscription_progress_entry.status == models.FeedSubscriptionProgressEntry.STARTED:
        ret_obj['state'] = 'started'
    else:
        ret_obj['state'] = 'finished'

    content, content_type = query_utils.serialize_content(ret_obj)

    return HttpResponse(content, content_type)
示例#5
0
def _facebook_login_session_post(request):
    if not request.body:
        return HttpResponseBadRequest('no HTTP body')  # pragma: no cover

    json_ = None
    try:
        json_ = ujson.loads(request.body)
    except ValueError:  # pragma: no cover
        return HttpResponseBadRequest('HTTP body cannot be parsed')

    if type(json_) is not dict:
        return HttpResponseBadRequest('JSON body must be object')  # pragma: no cover

    if 'token' not in json_:
        return HttpResponseBadRequest('\'token\' missing')

    if type(json_['token']) is not str:
        return HttpResponseBadRequest('\'token\' must be string')

    fb_id = None
    fb_email = None
    try:
        fb_id, fb_email = facebook.get_id_and_email(json_['token'])
    except ValueError:  # pragma: no cover
        return HttpResponseBadRequest('bad Facebook token')

    facebook_login = None
    try:
        facebook_login = models.FacebookLogin.objects.get(
            profile_id=fb_id)
    except models.FacebookLogin.DoesNotExist:
        ret_obj = {
            'token': json_['token'],
            'email': fb_email,
        }

        content, content_type = query_utils.serialize_content(ret_obj)
        return HttpResponse(content, content_type, status=422)

    session = models.Session.objects.create(
        user=facebook_login.user,
        expires_at=datetime.datetime.utcnow() + _SESSION_EXPIRY_INTERVAL,
    )

    content, content_type = query_utils.serialize_content(str(session.uuid))
    return HttpResponse(content, content_type)
示例#6
0
    def test_serialize_content(self):
        content, content_type = query_utils.serialize_content({
            'test1': 1,
            'test2': True
        })

        self.assertEqual(content_type, 'application/json')
        self.assertEqual(content, '{"test1":1,"test2":true}')
示例#7
0
def _my_login_session_post(request):
    if not request.body:
        return HttpResponseBadRequest('no HTTP body')  # pragma: no cover

    json_ = None
    try:
        json_ = ujson.loads(request.body)
    except ValueError:  # pragma: no cover
        return HttpResponseBadRequest('HTTP body cannot be parsed')

    if type(json_) is not dict:
        return HttpResponseBadRequest('JSON body must be object')  # pragma: no cover

    if 'email' not in json_:
        return HttpResponseBadRequest('\'email\' missing')

    if type(json_['email']) is not str:
        return HttpResponseBadRequest('\'email\' must be string')

    if 'password' not in json_:
        return HttpResponseBadRequest('\'password\' missing')

    if type(json_['password']) is not str:
        return HttpResponseBadRequest('\'password\' must be string')

    my_login = None
    try:
        my_login = models.MyLogin.objects.get(
            user__email__iexact=json_['email'])
    except models.MyLogin.DoesNotExist:
        return HttpResponseForbidden()

    try:
        password_hasher().verify(my_login.pw_hash, json_['password'])
    except argon2.exceptions.VerifyMismatchError:
        return HttpResponseForbidden()

    session = models.Session.objects.create(
        user=my_login.user,
        expires_at=datetime.datetime.utcnow() + _SESSION_EXPIRY_INTERVAL,
    )

    content, content_type = query_utils.serialize_content(str(session.uuid))
    return HttpResponse(content, content_type)
示例#8
0
def _user_category_post(request):
    context = Context()
    context.parse_request(request)
    context.parse_query_dict(request.GET)

    field_maps = None
    try:
        fields = query_utils.get_fields__query_dict(request.GET)
        field_maps = query_utils.get_field_maps(fields, _OBJECT_NAME)
    except QueryException as e:  # pragma: no cover
        return HttpResponse(e.message, status=e.httpcode)

    if not request.body:
        return HttpResponseBadRequest('no HTTP body')  # pragma: no cover

    json_ = None
    try:
        json_ = ujson.loads(request.body)
    except ValueError:  # pragma: no cover
        return HttpResponseBadRequest('HTTP body cannot be parsed')

    if type(json_) is not dict:
        return HttpResponseBadRequest(
            'JSON body must be object')  # pragma: no cover

    if 'text' not in json_:
        return HttpResponseBadRequest('\'text\' missing')

    if type(json_['text']) is not str:
        return HttpResponseBadRequest('\'text\' must be string')

    user_category = models.UserCategory(user=request.user, text=json_['text'])

    try:
        user_category.save()
    except IntegrityError:
        return HttpResponse('user category already exists', status=409)

    ret_obj = query_utils.generate_return_object(field_maps, user_category,
                                                 context)

    content, content_type = query_utils.serialize_content(ret_obj)

    return HttpResponse(content, content_type)
示例#9
0
def _feed_entries_query_stable_create_post(request):
    cache = caches['stable_query']

    context = Context()
    context.parse_request(request)
    context.parse_query_dict(request.GET)

    if not request.body:
        return HttpResponseBadRequest('no HTTP body')  # pragma: no cover

    json_ = None
    try:
        json_ = ujson.loads(request.body)
    except ValueError:  # pragma: no cover
        return HttpResponseBadRequest('HTTP body cannot be parsed')

    if type(json_) is not dict:
        return HttpResponseBadRequest(
            'JSON body must be object')  # pragma: no cover

    sort = None
    try:
        sort = query_utils.get_sort(json_, _OBJECT_NAME)
    except QueryException as e:  # pragma: no cover
        return HttpResponse(e.message, status=e.httpcode)

    search = None
    try:
        search = query_utils.get_search(context, json_, _OBJECT_NAME)
    except QueryException as e:  # pragma: no cover
        return HttpResponse(e.message, status=e.httpcode)

    token = f'feedentry-{uuid.uuid4().int}'

    cache.set(
        token,
        list(
            models.FeedEntry.annotate_search_vectors(
                models.FeedEntry.objects.all()).filter(*search).order_by(
                    *sort).values_list('uuid', flat=True)))

    content, content_type = query_utils.serialize_content(token)
    return HttpResponse(content, content_type)
示例#10
0
def _user_get(request):
    context = Context()
    context.parse_request(request)
    context.parse_query_dict(request.GET)

    user = request.user

    field_maps = None
    try:
        fields = query_utils.get_fields__query_dict(request.GET)
        field_maps = query_utils.get_field_maps(fields, _OBJECT_NAME)
    except QueryException as e:  # pragma: no cover
        return HttpResponse(e.message, status=e.httpcode)

    ret_obj = query_utils.generate_return_object(field_maps, user, context)

    content, content_type = query_utils.serialize_content(ret_obj)

    return HttpResponse(content, content_type)
示例#11
0
def _feed_entries_query_stable_post(request):
    cache = caches['stable_query']

    context = Context()
    context.parse_request(request)
    context.parse_query_dict(request.GET)

    if not request.body:
        return HttpResponseBadRequest('no HTTP body')  # pragma: no cover

    json_ = None
    try:
        json_ = ujson.loads(request.body)
    except ValueError:  # pragma: no cover
        return HttpResponseBadRequest('HTTP body cannot be parsed')

    if type(json_) is not dict:
        return HttpResponseBadRequest(
            'JSON body must be object')  # pragma: no cover

    token = None
    try:
        token = json_['token']
    except KeyError:
        return HttpResponseBadRequest('\'token\' missing')

    if type(token) is not str:
        return HttpResponseBadRequest('\'token\' must be string')

    if re.search(r'^feedentry-\d+$', token) is None:
        return HttpResponseBadRequest('\'token\' malformed')

    count = None
    try:
        count = query_utils.get_count(json_)
    except QueryException as e:  # pragma: no cover
        return HttpResponse(e.message, status=e.httpcode)

    skip = None
    try:
        skip = query_utils.get_skip(json_)
    except QueryException as e:  # pragma: no cover
        return HttpResponse(e.message, status=e.httpcode)

    field_maps = None
    try:
        fields = query_utils.get_fields__json(json_)
        field_maps = query_utils.get_field_maps(fields, _OBJECT_NAME)
    except QueryException as e:  # pragma: no cover
        return HttpResponse(e.message, status=e.httpcode)

    return_objects = None
    try:
        return_objects = query_utils.get_return_objects(json_)
    except QueryException as e:  # pragma: no cover
        return HttpResponse(e.message, status=e.httpcode)

    return_total_count = None
    try:
        return_total_count = query_utils.get_return_total_count(json_)
    except QueryException as e:  # pragma: no cover
        return HttpResponse(e.message, status=e.httpcode)

    cache.touch(token)
    uuids = cache.get(token, [])

    ret_obj = {}

    if return_objects:
        current_uuids = uuids[skip:skip + count]

        feed_entries = {
            feed_entry.uuid: feed_entry
            for feed_entry in models.FeedEntry.objects.filter(
                uuid__in=current_uuids)
        }

        objs = []
        if len(current_uuids) == len(feed_entries):
            for uuid_ in current_uuids:
                feed_entry = feed_entries[uuid_]
                obj = query_utils.generate_return_object(
                    field_maps, feed_entry, context)
                objs.append(obj)

        ret_obj['objects'] = objs

    if return_total_count:
        ret_obj['totalCount'] = len(uuids)

    content, content_type = query_utils.serialize_content(ret_obj)
    return HttpResponse(content, content_type)
示例#12
0
def _feed_entries_query_post(request):
    context = Context()
    context.parse_request(request)
    context.parse_query_dict(request.GET)

    if not request.body:
        return HttpResponseBadRequest('no HTTP body')  # pragma: no cover

    json_ = None
    try:
        json_ = ujson.loads(request.body)
    except ValueError:  # pragma: no cover
        return HttpResponseBadRequest('HTTP body cannot be parsed')

    if type(json_) is not dict:
        return HttpResponseBadRequest(
            'JSON body must be object')  # pragma: no cover

    count = None
    try:
        count = query_utils.get_count(json_)
    except QueryException as e:  # pragma: no cover
        return HttpResponse(e.message, status=e.httpcode)

    skip = None
    try:
        skip = query_utils.get_skip(json_)
    except QueryException as e:  # pragma: no cover
        return HttpResponse(e.message, status=e.httpcode)

    sort = None
    try:
        sort = query_utils.get_sort(json_, _OBJECT_NAME)
    except QueryException as e:  # pragma: no cover
        return HttpResponse(e.message, status=e.httpcode)

    search = None
    try:
        search = query_utils.get_search(context, json_, _OBJECT_NAME)
    except QueryException as e:  # pragma: no cover
        return HttpResponse(e.message, status=e.httpcode)

    field_maps = None
    try:
        fields = query_utils.get_fields__json(json_)
        field_maps = query_utils.get_field_maps(fields, _OBJECT_NAME)
    except QueryException as e:  # pragma: no cover
        return HttpResponse(e.message, status=e.httpcode)

    return_objects = None
    try:
        return_objects = query_utils.get_return_objects(json_)
    except QueryException as e:  # pragma: no cover
        return HttpResponse(e.message, status=e.httpcode)

    return_total_count = None
    try:
        return_total_count = query_utils.get_return_total_count(json_)
    except QueryException as e:  # pragma: no cover
        return HttpResponse(e.message, status=e.httpcode)

    feed_entries = models.FeedEntry.annotate_search_vectors(
        models.FeedEntry.objects.all()).filter(*search)

    ret_obj = {}

    if return_objects:
        objs = []
        for feed_entry in feed_entries.order_by(*sort)[skip:skip + count]:
            obj = query_utils.generate_return_object(field_maps, feed_entry,
                                                     context)
            objs.append(obj)

        ret_obj['objects'] = objs

    if return_total_count:
        ret_obj['totalCount'] = feed_entries.count()

    content, content_type = query_utils.serialize_content(ret_obj)
    return HttpResponse(content, content_type)
示例#13
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)
示例#14
0
def _explore_get(request):
    # TODO for the time being, this will just be static data (based on my personal OPML for now), because a recommendation engine is quite an endeavour
    section_lookups = [
        {
            'tag': 'Gaming',
            'feeds': [
                {
                    'feed_url': 'http://feeds.feedburner.com/GamasutraFeatureArticles',
                    'image_src': '/assets/images/explore_banner.png',
                },
                {
                    'feed_url': 'http://feeds.wolfire.com/WolfireGames',
                    'image_src': '/assets/images/explore_banner.png',
                },
            ],
        },
        {
            'tag': 'Technology',
            'feeds': [
                {
                    'feed_url': 'http://rss.slashdot.org/Slashdot/slashdot',
                    'image_src': None,
                },
                {
                    'feed_url': 'http://feeds.arstechnica.com/arstechnica/index',
                    'image_src': None,
                },
            ],
        },
        {
            'tag': 'World News',
            'feeds': [
                {
                    'feed_url': 'https://www.ctvnews.ca/rss/ctvnews-ca-top-stories-public-rss-1.822009',
                    'image_src': None,
                },
            ],
        },
        {
            'tag': 'Programming',
            'feeds': [
                {
                    'feed_url': 'http://feeds.feedburner.com/codinghorror',
                    'image_src': None,
                },
                {
                    'feed_url': 'http://feeds.wolfire.com/WolfireGames',
                    'image_src': None,
                },
                {
                    'feed_url': 'http://syndication.thedailywtf.com/TheDailyWtf',
                    'image_src': None,
                },
            ],
        },
        {
            'tag': 'Music',
            'feeds': [
                {
                    'feed_url': 'http://battlehelm.com/feed/',
                    'image_src': '/assets/images/explore_banner.png',
                },
                {
                    'feed_url': 'http://www.theblackplanet.org/feed/',
                    'image_src': '/assets/images/explore_banner.png',
                },
                {
                    'feed_url': 'http://www.angrymetalguy.com/feed/',
                    'image_src': '/assets/images/explore_banner.png',
                },
                {
                    'feed_url': 'http://www.terrorizer.com/feed/',
                    'image_src': '/assets/images/explore_banner.png',
                },
                {
                    'feed_url': 'http://deadrhetoric.com/feed/',
                    'image_src': '/assets/images/explore_banner.png',
                },
            ],
        },
    ]

    ret_obj = []
    for section_lookup in section_lookups:
        feed_objs = []
        for feed_lookup in section_lookup['feeds']:
            feed = None
            try:
                feed = models.Feed.annotate_subscription_data(
                    models.Feed.objects.all(), request.user).get(feed_url=feed_lookup['feed_url'])
            except models.Feed.DoesNotExist:
                continue

            some_feed_entries = list(models.FeedEntry.objects.filter(
                feed=feed, title__isnull=False).order_by('published_at').values_list('title', flat=True)[:5])
            if len(some_feed_entries) < 1:
                continue

            feed_objs.append({
                'name': feed.title,
                'feedUrl': feed.feed_url,
                'homeUrl': feed.home_url,
                'imageSrc': feed_lookup['image_src'],
                'entryTitles': some_feed_entries,
                'isSubscribed': feed.is_subscribed,
            })

        if len(feed_objs) > 0:
            ret_obj.append({
                'tagName': section_lookup['tag'],
                'feeds': feed_objs,
            })

    content, content_type = query_utils.serialize_content(ret_obj)

    return HttpResponse(content, content_type)