Пример #1
0
def mission_endorsements(request, object_uuid, slug=None):
    # Just check if there are any endorsements either from a Pleb or a Quest
    query = 'MATCH (quest:Quest)-[:EMBARKS_ON]->' \
            '(mission:Mission {object_uuid:"%s"}) ' \
            'WITH quest, mission ' \
            'OPTIONAL MATCH (mission)<-[:ENDORSES]-(endorsement) ' \
            'RETURN endorsement, quest, mission' % object_uuid
    res, _ = db.cypher_query(query)
    # Instead of doing inflation and serialization of all the updates here
    # without pagination lets just indicate if we have any or not and then
    # hit the endpoint to gather the actual updates.
    quest = Quest.inflate(res.one.quest)
    mission_obj = Mission.inflate(res.one.mission)
    return render(
        request, 'mission/endorsements.html', {
            "quest":
            QuestSerializer(quest).data,
            "mission":
            MissionSerializer(mission_obj, context={
                "request": request
            }).data,
            "slug":
            slugify(mission_obj.get_mission_title()),
            "endorsements":
            True if res.one.endorsement else False
        })
Пример #2
0
 def get_mission(self):
     from sb_missions.neo_models import Mission
     query = 'MATCH (g:Giftlist {object_uuid:"%s"})-[:LIST_FOR]->' \
             '(m:Mission) RETURN m' % self.object_uuid
     res, _ = db.cypher_query(query)
     [row[0].pull() for row in res]
     return Mission.inflate(res.one)
Пример #3
0
def mission_updates(request, object_uuid, slug=None):
    # Only need to check that at least one update exists here to mark that
    # updates are available for this mission.
    query = 'MATCH (quest:Quest)-[:EMBARKS_ON]->' \
            '(mission:Mission {object_uuid: "%s"}) ' \
            'WITH quest, mission ' \
            'OPTIONAL MATCH (mission)<-[:ABOUT]-(updates:Update) ' \
            'RETURN quest, mission, ' \
            'CASE WHEN count(updates) > 0 ' \
            'THEN true ELSE false END AS update' % object_uuid
    res, _ = db.cypher_query(query)
    if res.one is None:
        return redirect("404_Error")
    # Instead of doing inflation and serialization of all the updates here
    # without pagination lets just indicate if we have any or not and then
    # hit the endpoint to gather the actual updates.
    quest = Quest.inflate(res.one.quest)
    mission_obj = Mission.inflate(res.one.mission)
    return render(
        request, 'mission/updates.html', {
            "updates":
            res.one.update,
            "mission":
            MissionSerializer(mission_obj, context={
                "request": request
            }).data,
            "slug":
            slugify(mission_obj.get_mission_title()),
            "quest":
            QuestSerializer(quest).data
        })
Пример #4
0
    def repopulate_elasticsearch(self):
        # Profiles
        skip = 0
        while True:
            query = 'MATCH (profile:Pleb) RETURN DISTINCT profile ' \
                    'SKIP %s LIMIT 25' % skip
            skip += 24
            res, _ = db.cypher_query(query)
            if not res.one:
                break
            for profile in [Pleb.inflate(row[0]) for row in res]:
                update_search_object.apply_async(kwargs={
                    "object_uuid": profile.object_uuid,
                    "label": "pleb"
                })

        # Questions
        skip = 0
        while True:
            query = 'MATCH (question:Question) RETURN DISTINCT question ' \
                    'SKIP %s LIMIT 25' % skip
            skip += 24
            res, _ = db.cypher_query(query)
            if not res.one:
                break
            for question in [Question.inflate(row[0]) for row in res]:
                update_search_object.apply_async(kwargs={
                    "object_uuid": question.object_uuid,
                    "label": "question"
                })

        # Quests
        skip = 0
        while True:
            query = 'MATCH (quest:Quest) RETURN DISTINCT quest ' \
                    'SKIP %s LIMIT 25' % skip
            skip += 24
            res, _ = db.cypher_query(query)
            if not res.one:
                break
            for quest in [Quest.inflate(row[0]) for row in res]:
                update_search_object.apply_async(kwargs={
                    "object_uuid": quest.object_uuid,
                    "label": "quest"
                })
        # Missions
        skip = 0
        while True:
            query = 'MATCH (mission:Mission) RETURN DISTINCT mission ' \
                    'SKIP %s LIMIT 25' % skip
            skip += 24
            res, _ = db.cypher_query(query)
            if not res.one:
                break
            for mission in [Mission.inflate(row[0]) for row in res]:
                update_search_object.apply_async(kwargs={
                    "object_uuid": mission.object_uuid,
                    "label": "mission"
                })
Пример #5
0
 def get_mission(self):
     from sb_missions.neo_models import Mission
     query = 'MATCH (o:Order {object_uuid:"%s"})-[:GIFTED_TO]->' \
             '(m:Mission) RETURN m' % self.object_uuid
     res, _ = db.cypher_query(query)
     if res.one:
         res.one.pull()
         return Mission.inflate(res.one)
     return None
Пример #6
0
 def endorsed(self, request, owner_username):
     query = 'MATCH (q:Quest {owner_username:"******"})-' \
             '[:ENDORSES]->(m:Mission) RETURN m' % owner_username
     res, _ = db.cypher_query(query)
     page = self.paginate_queryset(
         [Mission.inflate(mission[0]) for mission in res])
     serializer = self.serializer_class(page, many=True,
                                        context={'request': request})
     return self.get_paginated_response(serializer.data)
Пример #7
0
 def get_missions(self, obj):
     from sb_missions.neo_models import Mission
     from sb_missions.serializers import MissionSerializer
     expand = self.context.get('expand', 'false').lower()
     query = 'MATCH (quest:Quest {owner_username: "******"})-[:EMBARKS_ON]->' \
             '(mission:Mission) RETURN mission' % obj.owner_username
     res, _ = db.cypher_query(query)
     if res.one is None:
         return None
     if expand == 'true':
         return [
             MissionSerializer(Mission.inflate(row[0])).data for row in res
         ]
     return [
         reverse(
             'mission-detail',
             kwargs={'object_uuid': Mission.inflate(row[0]).object_uuid},
             request=self.context.get('request', None)) for row in res
     ]
Пример #8
0
 def migrate_to_new_editor(self):
     skip = 0
     while True:
         query = 'MATCH (m:Mission) RETURN m SKIP %s LIMIT 25' % skip
         skip += 24
         res, _ = db.cypher_query(query)
         if not res.one:
             break
         for mission in [Mission.inflate(row[0]) for row in res]:
             rendered = render_content(
                 markdown.markdown(mission.epic.replace(
                     '&gt;', '>')).replace('<a', '<a target="_blank"'))
             mission.epic = rendered
             mission.temp_epic = rendered
             mission.save()
     skip = 0
     while True:
         query = 'MATCH (m:Question) RETURN m SKIP %s LIMIT 25' % skip
         skip += 24
         res, _ = db.cypher_query(query)
         if not res.one:
             break
         for question in [Question.inflate(row[0]) for row in res]:
             rendered = render_content(
                 markdown.markdown(question.content.replace(
                     '&gt;', '>')).replace('<a', '<a target="_blank"'))
             question.content = rendered
             question.save()
     skip = 0
     while True:
         query = 'MATCH (m:Solution) RETURN m SKIP %s LIMIT 25' % skip
         skip += 24
         res, _ = db.cypher_query(query)
         if not res.one:
             break
         for solution in [Solution.inflate(row[0]) for row in res]:
             rendered = render_content(
                 markdown.markdown(solution.content.replace(
                     '&gt;', '>')).replace('<a', '<a target="_blank"'))
             solution.content = rendered
             solution.save()
     skip = 0
     while True:
         query = 'MATCH (m:Update) RETURN m SKIP %s LIMIT 25' % skip
         skip += 24
         res, _ = db.cypher_query(query)
         if not res.one:
             break
         for update in [Update.inflate(row[0]) for row in res]:
             rendered = render_content(
                 markdown.markdown(update.content.replace(
                     '&gt;', '>')).replace('<a', '<a target="_blank"'))
             update.content = rendered
             update.save()
     cache.set("migrated_to_new_editor", True)
Пример #9
0
 def convert_social_links(self):
     twitter_string = "https://www.twitter.com/"
     facebook_string = "https://www.facebook.com/"
     linkedin_string = "https://www.linkedin.com/in/"
     youtube_string = "https://www.youtube.com/user/"
     skip = 0
     while True:
         query = 'MATCH (q:Quest) RETURN q ' \
                 'SKIP %s LIMIT 25' % skip
         skip += 24
         res, _ = db.cypher_query(query)
         if not res.one:
             break
         try:
             for quest in [Quest.inflate(row[0]) for row in res]:
                 if quest.twitter and twitter_string not in quest.twitter:
                     quest.twitter = "%s%s" % (twitter_string,
                                               quest.twitter)
                 if quest.facebook and facebook_string not in quest.facebook:
                     quest.facebook = "%s%s" % (facebook_string,
                                                quest.facebook)
                 if quest.linkedin and linkedin_string not in quest.linkedin:
                     quest.linkedin = "%s%s" % (linkedin_string,
                                                quest.linkedin)
                 if quest.youtube and youtube_string not in quest.youtube:
                     quest.youtube = "%s%s" % (youtube_string,
                                               quest.youtube)
                 quest.save()
                 cache.delete("%s_quest" % quest.object_uuid)
         except (CypherException, Exception):
             logger.exception("Convert Social Links: ")
             pass
     try:
         res, _ = db.cypher_query('MATCH (a:Mission) RETURN a')
         for mission in [Mission.inflate(row[0]) for row in res]:
             if mission.twitter and twitter_string not in mission.twitter:
                 mission.twitter = "%s%s" % (twitter_string,
                                             mission.twitter)
             if mission.facebook and facebook_string not in mission.facebook:
                 mission.facebook = "%s%s" % (facebook_string,
                                              mission.facebook)
             if mission.linkedin and linkedin_string not in mission.linkedin:
                 mission.linkedin = "%s%s" % (linkedin_string,
                                              mission.linkedin)
             if mission.youtube and youtube_string not in mission.youtube:
                 mission.youtube = "%s%s" % (youtube_string,
                                             mission.youtube)
             mission.save()
             cache.delete("%s_mission" % mission.object_uuid)
     except (CypherException, Exception):
         logger.exception("Convert Social Links: ")
         pass
Пример #10
0
def mission_edit_updates(request, object_uuid, slug=None, edit_id=None):
    query = 'MATCH (update:Update {object_uuid: "%s"})-[:ABOUT]->' \
            '(mission:Mission)<-[:EMBARKS_ON]-(quest:Quest)' \
            'WITH update, mission, quest ' \
            'MATCH (quest)-[:EMBARKS_ON]->(missions:Mission) ' \
            'RETURN mission, quest, update, missions ' \
            'ORDER BY missions.created DESC' % edit_id
    res, _ = db.cypher_query(query)
    if res.one is None:
        return redirect("select_mission")

    missions = [
        MissionSerializer(Mission.inflate(row.missions)).data for row in res
    ]
    mission_obj = Mission.inflate(res.one.mission)
    return render(
        request, 'updates/edit.html', {
            "update": UpdateSerializer(Update.inflate(res.one.update)).data,
            "mission": MissionSerializer(mission_obj).data,
            "slug": slugify(mission_obj.get_mission_title()),
            "quest": QuestSerializer(Quest.inflate(res.one.quest)).data,
            "missions": missions
        })
Пример #11
0
 def get_mission(cls, object_uuid, request=None):
     from sb_missions.neo_models import Mission
     from sb_missions.serializers import MissionSerializer
     mission = cache.get("%s_mission" % object_uuid)
     if mission is None:
         query = 'MATCH (content:SBContent {object_uuid:"%s"})' \
                 '<-[:ASSOCIATED_WITH]-' \
                 '(mission:Mission) RETURN mission' % object_uuid
         res, _ = db.cypher_query(query)
         if res.one:
             mission = MissionSerializer(Mission.inflate(res.one),
                                         context={
                                             "request": request
                                         }).data
             cache.set("%s_mission" % object_uuid, mission)
     return mission
Пример #12
0
def update_search_object(object_uuid,
                         label=None,
                         object_data=None,
                         index="full-search-base"):
    from plebs.serializers import PlebSerializerNeo
    from sb_quests.serializers import QuestSerializer
    from sb_quests.neo_models import Quest
    from sb_missions.serializers import MissionSerializer
    from sb_missions.neo_models import Mission
    from sb_questions.serializers import QuestionSerializerNeo
    from sb_base.neo_models import get_parent_votable_content
    if label is None:
        label = get_parent_votable_content(
            object_uuid).get_child_label().lower()
    logger.critical("Updating Search Object")
    logger.critical({"object_uuid": object_uuid})
    query = 'MATCH (a:%s {object_uuid:"%s"}) RETURN a' % \
            (label.title(), object_uuid)
    res, _ = db.cypher_query(query)
    if res.one:
        res.one.pull()
    else:
        raise update_search_object.retry(exc=DoesNotExist(
            'Object with uuid: %s '
            'does not exist' % object_uuid),
                                         countdown=3,
                                         max_retries=None)
    if label == "question":
        instance = Question.inflate(res.one)
        object_data = QuestionSerializerNeo(instance).data
        if 'mission' in object_data:
            object_data.pop('mission')
        if 'profile' in object_data:
            object_data.pop('profile')
        logger.critical(object_data)
    elif label == "quest":
        instance = Quest.inflate(res.one)
        object_data = QuestSerializer(instance).data
        logger.critical(object_data)
    elif label == "mission":
        instance = Mission.inflate(res.one)
        object_data = MissionSerializer(instance).data
        # Need to pop review_feedback because ES's serializer cannot parse
        # set types.
        # If we don't pop it we receive
        # TypeError("Unable to serialize set([]) (type: <type 'set'>)",))
        # If we can submit a JSON serialized version we can get around this by
        # using:
        # from rest_framework.renderers import JSONRenderer
        # JSONRenderer().render(serializer.data)
        # Also please note python's json.dumps() function runs into this same
        # issue.
        if 'review_feedback' in object_data:
            object_data.pop('review_feedback', None)
        if 'quest' in object_data:
            object_data.pop('quest')
        logger.critical(object_data)
    elif label == "pleb":
        instance = Pleb.inflate(res.one)
        object_data = PlebSerializerNeo(instance).data
        if 'quest' in object_data:
            object_data.pop('quest')
        logger.critical(object_data)
    else:
        # Currently we only need this functionality for Questions as
        # they are the only objects in search that we display votes
        # for in the search interface.
        error_dict = {
            "message": "Search False setup. "
            "Object Data None, Instance not None",
            "instance_label": label,
            "instance_uuid": object_uuid,
        }
        logger.critical(error_dict)
        return False
    try:
        es = Elasticsearch(settings.ELASTIC_SEARCH_HOST)
        res = es.index(index=index,
                       doc_type=object_data['type'],
                       id=object_uuid,
                       body=object_data)
    except (ElasticsearchException, TransportError, ConflictError,
            RequestError) as e:
        logger.exception("Failed to connect to Elasticsearch")
        logger.critical(object_data)
        raise update_search_object.retry(exc=e, countdown=5, max_retries=None)
    except KeyError:
        error_dict = {
            "message": "Search: KeyError False creation",
            "instance_uuid": object_uuid,
            "object_data": object_data
        }
        logger.critical(error_dict)
        return False
    try:
        if instance.search_id is None:
            instance.search_id = res['_id']
            instance.populated_es_index = True
            instance.save()
    except AttributeError:
        pass

    cache.delete("%s_vote_search_update" % object_uuid)
    return res
Пример #13
0
    def get(self, request, object_uuid=None, slug=None):
        # Do a second optional match to get the list of missions,
        # the first is just to make sure we're dealing with the actual
        # owner of the Mission.
        query = 'MATCH (pleb:Pleb {username: "******"})-[:IS_WAGING]->' \
            '(quest:Quest) WITH quest ' \
            'OPTIONAL MATCH (quest)-[:EMBARKS_ON]->(missions:Mission) ' \
            'RETURN missions, quest ' \
            'ORDER BY missions.created DESC' % request.user.username
        res, _ = db.cypher_query(query)
        if res.one is None:
            return redirect("404_Error")
        if res.one.missions is None:
            return redirect("select_mission")
        if object_uuid is None:
            mission_obj = Mission.inflate(res[0].missions)
            return redirect('mission_settings',
                            object_uuid=mission_obj.object_uuid,
                            slug=slug)

        mission_obj = Mission.get(object_uuid)
        if self.template_name == "manage/epic.html" and \
                not mission_obj.saved_for_later and \
                not mission_obj.submitted_for_review:
            if mission_obj.epic is None:
                return redirect('must_finish_epic',
                                object_uuid=mission_obj.object_uuid,
                                slug=slug)
            return redirect("submit_mission_for_review",
                            object_uuid=mission_obj.object_uuid,
                            slug=slug)
        missions = [
            MissionSerializer(Mission.inflate(row.missions)).data
            for row in res
        ]
        quest = Quest.inflate(res.one.quest)
        if mission_obj.owner_username != quest.owner_username:
            return redirect("404_Error")
        onboarding_sort, completed_count = order_tasks(object_uuid)
        if len(onboarding_sort) != 0:
            onboarding_done = int(
                (float(completed_count) / float(len(onboarding_sort))) * 100)
        else:
            onboarding_done = 0
        return render(
            request, self.template_name, {
                "missions":
                missions,
                "mission":
                MissionSerializer(mission_obj, context={
                    "request": request
                }).data,
                "quest":
                QuestSerializer(quest, context={
                    "request": request
                }).data,
                "slug":
                slugify(mission_obj.get_mission_title()),
                "epic_template":
                render_to_string("manage/placeholder_epic.html"),
                "update_placeholder":
                render_to_string("updates/placeholder.html"),
                "onboarding_top_3":
                onboarding_sort[:3],
                "onboarding_rest":
                onboarding_sort[3:],
                "onboarding_done":
                onboarding_done
            })
Пример #14
0
    def newsfeed(self, request):
        """
        The newsfeed endpoint expects to be called on the me endpoint and
        assumes that the request object provided will contain the user the
        newsfeed is being provided to. It is not included as a list_route on
        the me endpoint due to the me endpoint not being a viewset.
        If we transition to that structure it could easily be moved to a
        list_route there.
        Query if we want to grab tags:
        MATCH (a:Pleb {username: "******"})-
                [OWNS_QUESTION]->(questions:Question)-[:TAGGED_AS]->(tags:Tag)
            WHERE questions.to_be_deleted = False AND questions.created > %s
            RETURN questions, tags.name AS tags, NULL as solutions,
                NULL as posts UNION
        MATCH (a)-[manyFriends:FRIENDS_WITH*2 {active: True}]->
                ()-[OWNS_QUESTION]->(questions:Question)-[:TAGGED_AS]->
                (tags:Tag)
            WHERE questions.to_be_deleted = False AND questions.created > %s
            RETURN questions, tags.name AS tags, NULL as posts,
                NULL as solutions UNION

        :param request:
        """
        # This query retrieves all of the current user's posts, solutions,
        # and questions as well as their direct friends posts, solutions,
        # and questions. It then looks for all of their friends friends
        # solutions and questions, combines all of the content and
        # returns the result. The query filters out content scheduled for
        # deletion and only looks for content created more recently than the
        # time provided. The reasoning for not including friends of friends
        # posts is to try and improve privacy. Friends of friends have not
        # actually been accepted potentially as friends by the user and
        # therefore should not have access to information posted on the user's
        # wall which in this case would be their posts.
        # We currently do not sort this query in neo because we are waiting
        # for post processing on unions as a whole to be added as a feature.
        # See Github issue #2725 for updates
        # https://github.com/neo4j/neo4j/issues/2725
        then = (datetime.now(pytz.utc) - timedelta(days=120)).strftime("%s")
        query = \
            '// Retrieve all the current users questions\n' \
            'MATCH (a:Pleb {username: "******"})<-[:OWNED_BY]-' \
            '(questions:Question) ' \
            'WHERE questions.to_be_deleted = False AND questions.created > %s' \
            ' AND questions.is_closed = False ' \
            'RETURN questions, NULL AS solutions, NULL AS posts, ' \
            'questions.created AS created, NULL AS s_question, ' \
            'NULL AS mission, NULL AS updates, NULL AS q_mission, ' \
            'NULL AS news UNION ' \
            '' \
            '// Retrieve all the news articles the user may be \n' \
            '// interested in\n' \
            'MATCH (a:Pleb {username: "******"})-[:INTERESTED_IN]->' \
            '(tag:Tag)<-[:TAGGED_AS]-(news:NewsArticle) ' \
            'WHERE news.published > %s AND news.is_closed = False ' \
            ' RETURN DISTINCT news, NULL AS solutions, NULL AS posts, ' \
            'news.published AS created, NULL AS s_question, ' \
            'NULL AS mission, NULL AS updates, NULL AS q_mission, ' \
            'NULL AS questions UNION ' \
            '' \
            '// Retrieve all the current users solutions\n' \
            'MATCH (a:Pleb {username: "******"})<-' \
            '[:OWNED_BY]-(solutions:Solution)<-' \
            '[:POSSIBLE_ANSWER]-(s_question:Question) ' \
            'WHERE s_question.to_be_deleted = False ' \
            'AND solutions.created > %s' \
            ' AND solutions.is_closed = False ' \
            'AND s_question.is_closed = False ' \
            'RETURN solutions, NULL AS questions, NULL AS posts, ' \
            'solutions.created AS created, s_question AS s_question,' \
            'NULL AS mission, NULL AS updates, NULL AS q_mission, ' \
            'NULL AS news UNION ' \
            '' \
            '// Retrieve all the current users posts\n' \
            'MATCH (a:Pleb {username: "******"})<-[:OWNED_BY]-(posts:Post) ' \
            'WHERE posts.to_be_deleted = False AND posts.created > %s ' \
            'AND posts.is_closed = False ' \
            'RETURN posts, NULL as questions, NULL as solutions, ' \
            'posts.created AS created, NULL AS s_question,' \
            'NULL AS mission, NULL AS updates, NULL AS q_mission, ' \
            'NULL AS news UNION ' \
            '' \
            '// Retrieve all the posts on the current users wall that are \n' \
            '// not owned by the current user \n' \
            'MATCH (a:Pleb {username: "******"})-[:OWNS_WALL]->(w:Wall)' \
            '-[:HAS_POST]->(posts:Post) ' \
            'WHERE NOT (posts)-[:OWNED_BY]->(a) AND ' \
            'posts.to_be_deleted = False AND posts.created > %s ' \
            'AND posts.is_closed = False ' \
            'RETURN posts, NULL as questions, NULL as solutions, ' \
            'posts.created AS created, NULL AS s_question,' \
            'NULL AS mission, NULL AS updates, NULL AS q_mission, ' \
            'NULL AS news UNION ' \
            '' \
            '// Retrieve the missions affecting the given user\n' \
            'MATCH (a:Pleb {username: "******"})-[:LIVES_AT]->(:Address)-' \
            '[:ENCOMPASSED_BY*..]->' \
            '(:Location)<-[:WITHIN]-(mission:Mission {active: true})' \
            '<-[:EMBARKS_ON]-(quest:Quest {active: true}) ' \
            'WHERE NOT((mission)-[:FOCUSED_ON]->(:Position {verified:false}))' \
            ' AND mission.created > %s ' \
            'RETURN mission, NULL AS solutions, NULL AS posts, ' \
            'NULL AS questions, mission.created AS created, ' \
            'NULL AS s_question, NULL AS updates, NULL AS q_mission, ' \
            'NULL AS news UNION ' \
            '' \
            '// Retrieve the mission updates affecting ' \
            '// the given user\n' \
            'MATCH (a:Pleb {username: "******"})-[:LIVES_AT]->(:Address)-' \
            '[:ENCOMPASSED_BY*..]->' \
            '(:Location)<-[:WITHIN]-(q_mission:Mission {active: true})' \
            '<-[:EMBARKS_ON]-(quest:Quest {active: true}) WITH q_mission ' \
            'MATCH (q_mission)<-[:ABOUT]-(updates:Update) ' \
            'WHERE NOT((q_mission)-[:FOCUSED_ON]' \
            '->(:Position {verified:false}))' \
            ' AND updates.created > %s AND updates.is_closed = False ' \
            'RETURN updates, NULL AS solutions, NULL AS posts, ' \
            'NULL AS questions, updates.created AS created, ' \
            'NULL AS s_question, NULL as mission, q_mission, ' \
            'NULL AS news UNION ' \
            '' \
            '// Retrieve all the posts owned by users that the current user ' \
            '// is following \n' \
            'MATCH (a:Pleb {username: "******"})-[r:FOLLOWING {active: True}]->' \
            '(:Pleb)<-[:OWNED_BY]-(posts:Post) ' \
            'WHERE posts.to_be_deleted = False AND ' \
            'posts.created > %s AND posts.is_closed = False ' \
            'RETURN NULL AS solutions, posts AS posts, ' \
            'NULL AS questions, posts.created AS created, ' \
            'NULL AS s_question, NULL AS mission, NULL AS updates, ' \
            'NULL AS q_mission, ' \
            'NULL AS news UNION ' \
            '' \
            '// Retrieve all the users questions that the current user is ' \
            '// following \n' \
            'MATCH (a:Pleb {username: "******"})-[r:FOLLOWING {active: True}]->' \
            '(:Pleb)<-[:OWNED_BY]-(questions:Question) ' \
            'WHERE questions.to_be_deleted = False AND ' \
            'questions.created > %s AND questions.is_closed = False ' \
            'RETURN NULL AS solutions, NULL AS posts, ' \
            'questions AS questions, questions.created AS created, ' \
            'NULL AS s_question, NULL AS mission, NULL AS updates, ' \
            'NULL AS q_mission, ' \
            'NULL AS news UNION ' \
            '' \
            '// Retrieve all the users solutions that the current user is ' \
            '// following \n' \
            'MATCH (a:Pleb {username: "******"})-[r:FOLLOWING {active: True}]->' \
            '(:Pleb)<-[:OWNED_BY]-(solutions:Solution)<-' \
            '[:POSSIBLE_ANSWER]-(s_question:Question) ' \
            'WHERE s_question.to_be_deleted = False AND ' \
            'solutions.created > %s AND solutions.is_closed = False ' \
            'RETURN solutions, NULL AS posts, ' \
            'NULL AS questions, solutions.created AS created, ' \
            's_question as s_question, NULL AS mission, NULL AS updates, ' \
            'NULL AS q_mission, ' \
            'NULL AS news' \
            % (
                request.user.username, then, request.user.username, then,
                request.user.username, then,
                request.user.username, then, request.user.username, then,
                request.user.username, then, request.user.username, then,
                request.user.username, then, request.user.username, then,
                request.user.username, then)
        news = []
        res, _ = db.cypher_query(query)
        # Profiled with ~50 objects and it was still performing under 1 ms.
        # By the time sorting in python becomes an issue the above mentioned
        # ticket should be resolved.
        res = sorted(res, key=attrgetter('created'), reverse=True)
        page = self.paginate_queryset(res)
        for row in page:
            news_article = None
            if row.questions is not None:
                row.questions.pull()
                news_article = QuestionSerializerNeo(Question.inflate(
                    row.questions),
                                                     context={
                                                         'request': request
                                                     }).data
            elif row.solutions is not None:
                row.s_question.pull()
                row.solutions.pull()
                question_data = QuestionSerializerNeo(
                    Question.inflate(row.s_question)).data
                news_article = SolutionSerializerNeo(Solution.inflate(
                    row.solutions),
                                                     context={
                                                         'request': request
                                                     }).data
                news_article['question'] = question_data
            elif row.posts is not None:
                row.posts.pull()
                news_article = PostSerializerNeo(Post.inflate(row.posts),
                                                 context={
                                                     'request': request
                                                 }).data
            elif row.mission is not None:
                row.mission.pull()
                news_article = MissionSerializer(Mission.inflate(row.mission),
                                                 context={
                                                     'request': request
                                                 }).data
                news_article['reputation'] = Pleb.get(
                    username=news_article['owner_username']).reputation
            elif row.updates is not None:
                row.updates.pull()
                row.q_mission.pull()
                news_article = UpdateSerializer(Update.inflate(row.updates),
                                                context={
                                                    'request': request
                                                }).data
                news_article['mission'] = MissionSerializer(
                    Mission.inflate(row.q_mission),
                    context={
                        'request': request
                    }).data
            elif row.news is not None:
                row.news.pull()
                news_article = NewsArticleSerializer(NewsArticle.inflate(
                    row.news),
                                                     context={
                                                         'request': request
                                                     }).data
            news.append(news_article)
        return self.get_paginated_response(news)
Пример #15
0
 def get(self, request, username=None):
     from sb_missions.neo_models import Mission
     from sb_missions.serializers import MissionSerializer
     from sb_missions.utils import order_tasks
     query = 'MATCH (person:Pleb {username: "******"})' \
         '-[r:IS_WAGING]->(quest:Quest) WITH quest ' \
         'OPTIONAL MATCH (quest)-[:EMBARKS_ON]->(missions:Mission) ' \
         'RETURN quest, missions ORDER BY missions.created DESC' % (
             request.user.username)
     try:
         res, _ = db.cypher_query(query)
         if res.one is None:
             return redirect("404_Error")
     except (CypherException, ClientError):
         return redirect("500_Error")
     res.one.quest.pull()
     quest_obj = Quest.inflate(res.one.quest)
     quest_ser = QuestSerializer(quest_obj, context={
         'request': request
     }).data
     quest_ser['account_type'] = quest_obj.account_type
     if res.one.missions is None:
         mission_link = reverse('select_mission')
         mission_active = False
         onboarding_sort = []
         mission_obj = None
         onboarding_done = 0
     else:
         mission_obj = Mission.inflate(res[0].missions)
         mission_link = reverse('mission_settings',
                                kwargs={
                                    "object_uuid":
                                    mission_obj.object_uuid,
                                    "slug":
                                    slugify(mission_obj.get_mission_title())
                                })
         mission_active = mission_obj.active
         onboarding_sort, completed_count = order_tasks(
             mission_obj.object_uuid)
         onboarding_done = int(
             (float(completed_count) / float(len(onboarding_sort))) * 100)
     res, _ = db.cypher_query('MATCH (a:Quest {owner_username: "******"})'
                              '-[:LOCATED_AT]->(b:Address) '
                              'RETURN b' % quest_obj.owner_username)
     if res.one is not None:
         address = Address.inflate(res.one)
     else:
         address = None
     if self.template_name == "manage/quest_banking.html" \
             and address is None:
         return redirect('account_setup')
     if self.template_name == "manage/quest_settings.html":
         return redirect('general_settings')
     return render(
         request, self.template_name, {
             "quest":
             quest_ser,
             "mission_link":
             mission_link,
             "mission_active":
             mission_active,
             "mission":
             MissionSerializer(mission_obj, context={
                 "request": request
             }).data,
             "address":
             address,
             "onboarding_top_3":
             onboarding_sort[:3],
             "onboarding_rest":
             onboarding_sort[3:],
             "onboarding_done":
             onboarding_done
         })