def update(self, instance, validated_data):
     task_param = {
         "object_uuid": instance.object_uuid,
         "label": instance.get_child_label().lower()
     }
     spawn_task(task_func=update_search_object, task_param=task_param)
     return instance
Example #2
0
 def create(self, request, *args, **kwargs):
     wall_pleb = Pleb.get(self.kwargs[self.lookup_field])
     friend_with = wall_pleb.is_friends_with(request.user.username)
     if friend_with is False and wall_pleb.username != request.user.username:
         return Response(
             {"detail": "Sorry you are not friends with this"
              " person."},
             status=status.HTTP_400_BAD_REQUEST)
     serializer = self.get_serializer(data=request.data)
     if serializer.is_valid():
         instance = serializer.save(wall_owner_profile=wall_pleb)
         spawn_task(task_func=spawn_notifications,
                    task_param={
                        "from_pleb":
                        request.user.username,
                        "sb_object":
                        serializer.data['object_uuid'],
                        "url":
                        reverse('single_post_page',
                                kwargs={
                                    "object_uuid":
                                    serializer.data["object_uuid"]
                                }),
                        "to_plebs": [
                            self.kwargs[self.lookup_field],
                        ],
                        "notification_id":
                        str(uuid1()),
                        "action_name":
                        instance.action_name
                    })
         return Response(serializer.data, status=status.HTTP_200_OK)
     return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Example #3
0
 def create(self, request, *args, **kwargs):
     serializer = self.get_serializer(data=request.data,
                                      context={"request": request})
     if serializer.is_valid():
         question = Question.nodes.get(
             object_uuid=self.kwargs[self.lookup_field])
         instance = serializer.save(question=question)
         query = "MATCH (a:Question {object_uuid:'%s'})-[:OWNED_BY]->" \
                 "(b:Pleb) RETURN b" % (self.kwargs[self.lookup_field])
         res, col = db.cypher_query(query)
         question_owner = Pleb.inflate(res[0][0])
         serializer = serializer.data
         to_plebs = [question_owner.username]
         mission = question.get_mission(question.object_uuid)
         if mission:
             to_plebs.append(mission['owner_username'])
         spawn_task(task_func=spawn_notifications, task_param={
             "from_pleb": request.user.username,
             "sb_object": serializer['object_uuid'],
             "url": reverse(
                 'single_solution_page',
                 kwargs={"object_uuid": serializer["object_uuid"]}),
             # TODO discuss notifying all the people who have provided
             # solutions on a given question.
             "to_plebs": to_plebs,
             "notification_id": str(uuid1()),
             'action_name': instance.action_name
         })
         # Not going to add until necessary for search
         # spawn_task(task_func=add_solution_to_search_index,
         #            task_param={"solution": serializer})
         return Response(serializer, status=status.HTTP_200_OK)
     return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Example #4
0
 def create(self, validated_data):
     request, _, _, _, _ = gather_request_data(self.context)
     stripe.api_key = settings.STRIPE_SECRET_KEY
     stripe.api_version = settings.STRIPE_API_VERSION
     donor = Pleb.get(request.user.username)
     token = validated_data.pop('token', None)
     # TODO add payment_method selection support to direct donations
     # this pop is just to allow the donation to save using **validated_data
     validated_data.pop('payment_method', None)
     donation = Donation(owner_username=donor.username,
                         **validated_data).save()
     if not donor.stripe_customer_id:
         customer = stripe.Customer.create(
             description="Customer for %s" % donor.username,
             card=token,
             email=donor.email)
         donor.stripe_customer_id = customer['id']
         donor.save()
         cache.delete(donor.username)
         donor.refresh()
     donor.donations.connect(donation)
     donation.owned_by.connect(donor)
     charge = stripe.Charge.create(
         amount=donation.amount,
         currency="usd",
         customer=donor.stripe_customer_id,
         receipt_email=donor.email,
         description="Donation to Sagebrew from %s" % donor.username
     )
     donation.stripe_charge_id = charge['id']
     donation.save()
     spawn_task(task_func=check_privileges,
                task_param={"username": donor.username})
     return donation
Example #5
0
def spawn_user_updates(username, object_uuid):
    from sb_votes.tasks import vote_object_task
    vote_res = []
    try:
        vote_res.append(get_user_updates(username=username,
                                         object_uuid=object_uuid,
                                         table_name='votes'))
    except JSONResponseError as e:
        raise spawn_user_updates.retry(exc=e, countdown=10,
                                       max_retries=None)
    except(TypeError, IOError, BotoClientError,
           BotoServerError, AWSConnectionError, Exception) as e:
        raise spawn_user_updates.retry(exc=e, countdown=45,
                                       max_retries=None)
    for item in vote_res:
        try:
            item['status'] = int(item['status'])
            task_data = {
                'vote_type': item['status'],
                'current_pleb': username,
                'object_uuid': item['parent_object'],
            }
            spawn_task(task_func=vote_object_task, task_param=task_data)
        except KeyError:
            pass

    return True
Example #6
0
    def migrate_questions(self):
        query = 'MATCH (a:Question) RETURN a'

        res, _ = db.cypher_query(query)
        for question in [Question.inflate(row[0]) for row in res]:
            spawn_task(task_func=create_question_summary_task,
                       task_param={'object_uuid': question.object_uuid})
        self.stdout.write("completed question migration\n", ending='')
Example #7
0
    def create(self, request, *args, **kwargs):
        object_uuid = self.kwargs[self.lookup_field]
        now = str(datetime.now(pytz.utc))
        vote_data = request.data
        serializer = self.get_serializer(data=vote_data,
                                         context={"request": request})
        if not Pleb.get(request.user.username).is_verified:
            return Response(
                {
                    "detail":
                    "Sorry, you cannot vote unless you are verified!",
                    "status":
                    status.HTTP_401_UNAUTHORIZED,
                    "developer_message":
                    "A user can only vote on content "
                    "if they are verified."
                },
                status=status.HTTP_401_UNAUTHORIZED)
        if serializer.is_valid():
            parent_object_uuid = self.kwargs[self.lookup_field]

            vote_status = int(serializer.validated_data['vote_type'])
            handle_vote(parent_object_uuid, vote_status, request.user.username,
                        now)
            async_result = cache.get("%s_%s_vote" %
                                     (request.user.username, object_uuid))
            task_params = {
                "username": request.user.username,
                "object_uuid": object_uuid
            }
            if async_result is not None:
                # if there is already a task lined up,
                # revoke it and spawn a new one
                async_result.revoke()

            # spawn a task which will execute 30 seconds from now
            # potential improvement here is to have a way to detect if the
            new_task = spawn_task(spawn_user_updates,
                                  task_param=task_params,
                                  countdown=30)
            cache.set("%s_%s_vote" % (request.user.username, object_uuid),
                      new_task)
            search_result = cache.get("%s_vote_search_update" % object_uuid)
            if search_result is not None:
                search_result.revoke()
            task_param = {"object_uuid": object_uuid}
            spawned = spawn_task(task_func=update_search_object,
                                 task_param=task_param,
                                 countdown=10)
            cache.set("%s_vote_search_update" % object_uuid, spawned)
            return Response({
                "detail": "Successfully created or modified "
                "vote.",
                "status": status.HTTP_200_OK,
                "developer_message": None
            })
        else:
            return Response(serializer.errors, status=400)
Example #8
0
    def get_queryset(self):
        filter_type = self.request.query_params.get("filter", "general")
        query_param = self.request.query_params.get("query", "")
        search_type_dict = dict(settings.SEARCH_TYPES)
        alchemyapi = AlchemyAPI()
        response = alchemyapi.keywords("text", query_param)
        # this .get on a dict is a temporary work around for the alchemyapi
        # package not having any exception handling, this will keep us safe
        # from key errors caused by us hitting the alchemy endpoint too much
        # and using up our allowed requests
        keywords = response.get('keywords', [])
        # TODO surround ES query with proper exception handling and ensure
        # each one is handled correctly
        es = Elasticsearch(settings.ELASTIC_SEARCH_HOST)
        # TODO run query_param through natural language processor, determine
        # if what they have searched is an email address or a name so that
        # the first search result is that user
        # TODO implement filtering on auto generated keywords from alchemyapi
        if filter_type is None or filter_type == 'general':
            res = es.search(index='full-search-base',
                            size=50,
                            body={
                                "query": {
                                    "multi_match": {
                                        "fields": settings.SEARCH_FIELDS,
                                        "query": query_param,
                                        "fuzziness": "AUTO",
                                        "phrase_slop": 2
                                    }
                                }
                            })
        else:
            try:
                res = es.search(index='full-search-base',
                                size=50,
                                doc_type=search_type_dict[filter_type],
                                body={
                                    "query": {
                                        "multi_match": {
                                            "fields": settings.SEARCH_FIELDS,
                                            "query": query_param,
                                            "fuzziness": "AUTO",
                                            "phrase_slop": 2
                                        }
                                    }
                                })
            except KeyError:
                raise ValidationError("Invalid filter parameter")

        task_param = {
            "username": self.request.user.username,
            "query_param": query_param,
            "keywords": keywords
        }
        # we do not notify users if this task fails to spawn because it is
        # just for us later down the line
        spawn_task(task_func=update_search_query, task_param=task_param)
        return res['hits']['hits']
Example #9
0
 def update(self, instance, validated_data):
     validate_is_owner(self.context.get('request', None), instance)
     instance.content = render_content(
         validated_data.get('content', instance.content))
     instance.last_edited_on = datetime.now(pytz.utc)
     instance.save()
     spawn_task(task_func=create_solution_summary_task,
                task_param={'object_uuid': instance.object_uuid})
     return instance
Example #10
0
 def migrate_solutions(self):
     query = 'MATCH (a:Solution)<-[:POSSIBLE_ANSWER]-(b:Question) ' \
             'SET a.parent_id=b.object_uuid RETURN a'
     res, _ = db.cypher_query(query)
     for solution in [Solution.inflate(row[0]) for row in res]:
         spawn_task(task_func=create_solution_summary_task, task_param={
             'object_uuid': solution.object_uuid
         })
     self.stdout.write("completed solution migration\n", ending='')
 def create(self, validated_data):
     from_user = validated_data.pop('from_user', None)
     to_user = validated_data.pop('to_user', None)
     validated_data['from'] = from_user
     validated_data['to'] = to_user
     spawn_task(task_func=create_email,
                task_param={"message_data": validated_data})
     validated_data['from_user'] = from_user
     validated_data['to_user'] = to_user
     return validated_data
Example #12
0
def connect_to_state_districts(object_uuid):
    try:
        address = Address.nodes.get(object_uuid=object_uuid)
    except (DoesNotExist, Address.DoesNotExist, CypherException, IOError,
            ClientError) as e:
        raise connect_to_state_districts.retry(exc=e,
                                               countdown=3,
                                               max_retries=None)
    try:
        lookup_url = settings.OPENSTATES_DISTRICT_SEARCH_URL % \
            (address.latitude, address.longitude) \
            + "&apikey=53f7bd2a41df42c082bb2f07bd38e6aa"
    except TypeError:
        # in case an address doesn't have a latitude or longitude
        return False
    response = requests.get(
        lookup_url, headers={"content-type": 'application/json; charset=utf8'})
    response_json = response.json()
    try:
        for rep in response_json:
            try:
                sector = 'state_%s' % rep['chamber']
                query = 'MATCH (l:Location {name: "%s", sector:"federal"})-' \
                        '[:ENCOMPASSES]->(district:Location {name:"%s", ' \
                        'sector:"%s"}) RETURN district ' % \
                        (us.states.lookup(address.state).name,
                         rep['district'], sector)
                res, _ = db.cypher_query(query)
            except KeyError:
                return False
            try:
                res = res[0]
            except IndexError as e:
                raise connect_to_state_districts.retry(exc=e,
                                                       countdown=3,
                                                       max_retries=None)
            try:
                state_district = Location.inflate(res.district)
            except (CypherException, ClientError, IOError,
                    CouldNotCommit) as e:
                raise connect_to_state_districts.retry(exc=e,
                                                       countdown=3,
                                                       max_retries=None)
            if state_district not in address.encompassed_by:
                address.encompassed_by.connect(state_district)
        spawn_task(task_func=create_and_attach_state_level_reps,
                   task_param={"rep_data": response_json})
        return True
    except (CypherException, IOError, ClientError, CouldNotCommit) as e:
        raise connect_to_state_districts.retry(exc=e,
                                               countdown=3,
                                               max_retries=None)
 def update(self, instance, validated_data):
     pleb = validated_data.get('pleb', None)
     vote_type = validated_data.get('vote_type', None)
     query = 'MATCH (s:SBContent {object_uuid:"%s"})-[:COUNCIL_VOTE]->' \
             '(p:Pleb) RETURN p' % instance.object_uuid
     res, _ = db.cypher_query(query)
     if not res:
         instance.initial_vote_time = datetime.now(pytz.utc)
         instance.save()
     res = instance.council_vote(vote_type, pleb)
     spawn_task(task_func=update_closed_task,
                task_param={'object_uuid': instance.object_uuid})
     return res
Example #14
0
    def create(self, validated_data):
        request = self.context["request"]
        # Note that DRF requires us to use the source as the key here but
        # tags prior to serializing
        mission = None
        tags = validated_data.pop('get_tags', [])
        owner = Pleb.get(request.user.username)
        mission_id = validated_data.get('mission', '')
        if mission_id:
            mission = Mission.get(mission_id)
        validated_data['owner_username'] = owner.username
        uuid = str(uuid1())
        validated_data['content'] = render_content(
            validated_data.get('content', ""))
        url = reverse('question_detail_page',
                      kwargs={
                          'question_uuid': uuid,
                          "slug": slugify(validated_data['title'])
                      },
                      request=request)
        href = reverse('question-detail',
                       kwargs={'object_uuid': uuid},
                       request=request)
        soup = BeautifulSoup(validated_data['content'], "lxml").get_text()
        question = Question(url=url,
                            href=href,
                            object_uuid=uuid,
                            summary=smart_truncate(soup),
                            **validated_data).save()
        question.owned_by.connect(owner)
        if mission is not None:
            mission.associated_with.connect(question)
        for tag in tags:
            query = 'MATCH (t:Tag {name:"%s"}) WHERE NOT t:AutoTag ' \
                    'RETURN t' % slugify(tag)
            res, _ = db.cypher_query(query)
            if not res.one:
                if (request.user.username == "devon_bleibtrey"
                        or request.user.username == "tyler_wiersing"
                        or owner.reputation >= 1250):
                    tag_obj = Tag(name=slugify(tag)).save()
                    question.tags.connect(tag_obj)
                else:
                    continue
            else:
                tag_obj = Tag.inflate(res.one)
                question.tags.connect(tag_obj)

        spawn_task(task_func=update_tags, task_param={"tags": tags})
        if validated_data.get('external_location_id', None) is not None:
            spawn_task(
                task_func=create_location_tree,
                task_param={"external_id": question.external_location_id})
        spawn_task(task_func=add_auto_tags_to_question_task,
                   task_param={"object_uuid": question.object_uuid})
        spawn_task(task_func=create_question_summary_task,
                   task_param={'object_uuid': question.object_uuid})
        question.refresh()
        cache.set(question.object_uuid, question)
        return question
Example #15
0
 def create(self, request, *args, **kwargs):
     if "tags" in request.data:
         if isinstance(request.data['tags'], basestring):
             request.data['tags'] = request.data['tags'].split(',')
     serializer = self.get_serializer(data=request.data,
                                      context={"request": request})
     if serializer.is_valid():
         instance = serializer.save(mission=request.data.get('mission', ''))
         spawn_task(task_func=update_search_object,
                    task_param={
                        "object_uuid": instance.object_uuid,
                        "label": "question"
                    })
         return Response(serializer.data, status=status.HTTP_201_CREATED)
     return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Example #16
0
def create_location_tree(external_id):
    hierarchy = cache.get(external_id)
    try:
        if hierarchy is None:
            raise KeyError("Could not find external id")
    except KeyError as e:
        raise create_location_tree.retry(exc=e, countdown=10, max_retries=None)
    end_node = parse_google_places(hierarchy['address_components'],
                                   external_id)
    spawn_task(task_func=connect_location_to_element,
               task_param={
                   "element_id": external_id,
                   "location": end_node
               })

    return end_node
Example #17
0
def add_auto_tags(object_uuid, tag_list):
    """
    This function creates the auto generated tag nodes and connects them to the
    post from which they were tagged.

    :param object_uuid
    :param tag_list:
    :return:
    """
    if len(tag_list) < 1:
        return True
    content = TaggableContent.nodes.get(object_uuid=object_uuid)
    response = content.add_auto_tags(tag_list)

    if isinstance(response, Exception) is True:  # pragma: no cover
        # Not covering as we don't have a consistent way of reproducing it
        # currently. - Devon Bleibtrey
        raise add_auto_tags.retry(exc=response, countdown=3, max_retries=None)

    spawned = spawn_task(
        task_func=create_tag_relations,
        task_param={"tag_array": [tag.object_uuid for tag in response]})
    if isinstance(spawned, Exception) is True:  # pragma: no cover
        # Not covering as we don't have a consistent way of reproducing it
        # currently. - Devon Bleibtrey
        raise add_auto_tags.retry(exc=response, countdown=3, max_retries=None)
    return response
Example #18
0
def check_closed_reputation_changes():
    """
    This will be called in a task which is run either everyday or every other
    day and will check which objects need to be closed
    :return:
    """
    try:
        for pleb in Pleb.nodes.all():
            res = pleb.get_total_rep()
            cache.delete(pleb.username)
            if res['previous_rep'] != res['total_rep']:
                spawn_task(task_func=check_privileges,
                           task_param={'username': pleb.username})
        return True
    except (CypherException, IOError, ClientError) as e:
        return e
 def create(self, validated_data):
     # TODO we don't have a way currently to distinguish what a Update is
     # about. Think it'll be based on an attribute submitted by the front
     # end. That will be based on where it's at (make update from Public
     # Office Mission vs Advocate Mission vs Quest vs etc)
     request, _, _, _, _ = gather_request_data(self.context)
     quest = validated_data.pop('quest', None)
     owner = Pleb.get(request.user.username)
     validated_data['owner_username'] = owner.username
     about = validated_data.pop('about', None)
     about_type = validated_data.get('about_type')
     validated_data['content'] = \
         render_content(validated_data.get('content', ''))
     update = Update(**validated_data).save()
     quest.updates.connect(update)
     url = None
     if about_type == 'mission':
         update.mission.connect(about)
         url = reverse('mission_updates',
                       kwargs={
                           'object_uuid': about.object_uuid,
                           'slug': slugify(about.get_mission_title())
                       })
     elif about_type == 'quest':
         update.quest.connect(about)
     cache.delete("%s_updates" % quest.object_uuid)
     task_params = {
         "sb_object":
         update.object_uuid,
         "to_plebs":
         quest.get_followers(),
         "from_pleb":
         request.user.username,
         "notification_id":
         str(uuid1()),
         "url":
         url,
         "action_name":
         "%s %s has made an Update on a Quest you follow!" %
         (request.user.first_name, request.user.last_name),
         "public":
         True
     }
     spawn_task(task_func=spawn_notifications, task_param=task_params)
     return update
Example #20
0
def finalize_citizen_creation(username):
    try:
        pleb = Pleb.get(username=username, cache_buster=True)
    except (DoesNotExist, Exception) as e:
        raise finalize_citizen_creation.retry(exc=e,
                                              countdown=10,
                                              max_retries=None)
    task_list = {}
    task_data = {"object_uuid": pleb.object_uuid, "label": "pleb"}
    task_list["add_object_to_search_index"] = spawn_task(
        task_func=update_search_object, task_param=task_data, countdown=30)
    task_list["check_privileges_task"] = spawn_task(
        task_func=check_privileges,
        task_param={"username": username},
        countdown=20)

    cache.delete(pleb.username)
    return task_list
Example #21
0
 def update(self, instance, validated_data):
     instance.street = validated_data.get('street', instance.street)
     instance.street_additional = validated_data.get(
         'street_additional', instance.street_additional)
     instance.city = validated_data.get("city", instance.city)
     instance.state = us.states.lookup(
         validated_data.get("state", instance.state)).name
     instance.postal_code = validated_data.get("postal_code",
                                               instance.postal_code)
     instance.country = validated_data.get("country", instance.country)
     instance.congressional_district = validated_data.get(
         "congressional_district", instance.congressional_district)
     instance.latitude = validated_data.get("latitude", instance.latitude)
     instance.longitude = validated_data.get("longitude",
                                             instance.longitude)
     instance.save()
     spawn_task(task_func=update_address_location,
                task_param={"object_uuid": instance.object_uuid})
     return instance
Example #22
0
def update_search_query(username, query_param, keywords):
    """
    This task creates a search query node then calls the task to create and
    attach keyword nodes to the search query node

    :param username:
    :param query_param:
    :param keywords:
    :return:
    """
    try:
        res, _ = db.cypher_query("MATCH (a:Pleb {username:'******'}) RETURN a" %
                                 username)
        if res.one:
            res.one.pull()
            pleb = Pleb.inflate(res.one)
        else:
            raise update_search_query.retry(exc=DoesNotExist(
                "Profile with username: "******"%s does not exist" % username),
                                            countdown=3,
                                            max_retries=None)
    except (CypherException, IOError) as e:
        raise update_search_query.retry(exc=e, countdown=3, max_retries=None)
    try:
        search_query = SearchQuery.nodes.get(search_query=query_param)
        if pleb.searches.is_connected(search_query):
            rel = pleb.searches.relationship(search_query)
            rel.times_searched += 1
            rel.last_searched = datetime.now(pytz.utc)
            rel.save()
            return True
        else:
            rel = pleb.searches.connect(search_query)
            rel.save()
            search_query.searched_by.connect(pleb)
            return True
    except (SearchQuery.DoesNotExist, DoesNotExist):
        search_query = SearchQuery(search_query=query_param)
        search_query.save()
        search_query.searched_by.connect(pleb)
        rel = pleb.searches.connect(search_query)
        rel.save()
        for keyword in keywords:
            keyword['query_param'] = query_param
            spawned = spawn_task(task_func=create_keyword, task_param=keyword)
            if isinstance(spawned, Exception) is True:
                return spawned
        return True
    except (CypherException, IOError) as e:
        raise update_search_query.retry(exc=e, countdown=3, max_retries=None)
    except Exception as e:
        raise update_search_query.retry(exc=e, countdown=3, max_retries=None)
Example #23
0
 def set_encompassing(self):
     from .tasks import connect_to_state_districts
     try:
         encompassed_by = Location.nodes.get(name=self.city)
         if Location.get_single_encompassed_by(
                 encompassed_by.object_uuid) != \
                 us.states.lookup(self.state).name:
             # if a location node exists with an incorrect encompassing
             # state
             raise DoesNotExist("This Location does not exist")
     except (Location.DoesNotExist, DoesNotExist):
         encompassed_by = Location(name=self.city, sector="local").save()
         try:
             city_encompassed = Location.nodes.get(
                 name=us.states.lookup(self.state).name)
         except (Location.DoesNotExist, DoesNotExist):
             city_encompassed = Location(name=us.states.lookup(
                 self.state).name,
                                         sector="federal").save()
         if city_encompassed not in encompassed_by.encompassed_by:
             encompassed_by.encompassed_by.connect(city_encompassed)
         if encompassed_by not in city_encompassed.encompasses:
             city_encompassed.encompasses.connect(encompassed_by)
     except (MultipleNodesReturned, Exception):
         query = 'MATCH (l1:Location {name:"%s"})-[:ENCOMPASSED_BY]->' \
                 '(l2:Location {name:"%s"}) RETURN l1' % \
                 (self.city, self.state)
         res, _ = db.cypher_query(query)
         if res.one is not None:
             encompassed_by = Location.inflate(res.one)
         else:
             encompassed_by = None
     if encompassed_by is not None:
         if encompassed_by not in self.encompassed_by:
             self.encompassed_by.connect(encompassed_by)
     # get or create the state level districts and attach them to the
     # address
     spawn_task(task_func=connect_to_state_districts,
                task_param={'object_uuid': self.object_uuid})
     return self
Example #24
0
 def create(self, validated_data):
     request = self.context["request"]
     question = validated_data.pop('question', None)
     owner = Pleb.get(request.user.username)
     validated_data['owner_username'] = owner.username
     uuid = str(uuid1())
     validated_data['content'] = render_content(
         validated_data.get('content', ""))
     href = reverse('solution-detail',
                    kwargs={"object_uuid": uuid},
                    request=request)
     soup = BeautifulSoup(validated_data['content'], "lxml").get_text()
     solution = Solution(url=question.url,
                         href=href,
                         object_uuid=uuid,
                         parent_id=question.object_uuid,
                         summary=smart_truncate(soup),
                         **validated_data).save()
     solution.owned_by.connect(owner)
     question.solutions.connect(solution)
     spawn_task(task_func=create_solution_summary_task,
                task_param={'object_uuid': solution.object_uuid})
     return solution
Example #25
0
 def create(self, request, *args, **kwargs):
     serializer = self.get_serializer(data=request.data)
     if serializer.is_valid():
         pleb = Pleb.get(request.user.username)
         parent_object = SBContent.nodes.get(
             object_uuid=self.kwargs[self.lookup_field])
         instance = serializer.save(owner=pleb, parent_object=parent_object)
         serializer_data = serializer.data
         serializer_data['comment_on'] = reverse(
             '%s-detail' % parent_object.get_child_label().lower(),
             kwargs={'object_uuid': parent_object.object_uuid},
             request=request)
         serializer_data['url'] = parent_object.get_url(request=request)
         notification_id = str(uuid1())
         spawn_task(task_func=spawn_comment_notifications, task_param={
             'from_pleb': request.user.username,
             'parent_object_uuid': self.kwargs[self.lookup_field],
             'object_uuid': instance.object_uuid,
             'notification_id': notification_id,
             'comment_on_comment_id': str(uuid1())
         })
         return Response(serializer_data, status=status.HTTP_200_OK)
     return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Example #26
0
def update_reputation(username):
    try:
        pleb = Pleb.get(username=username, cache_buster=True)
    except (Pleb.DoesNotExist, DoesNotExist, CypherException, IOError) as e:
        raise update_reputation.retry(exc=e, countdown=3, max_retries=None)

    res = pleb.get_total_rep()
    if isinstance(res, Exception):
        raise update_reputation.retry(exc=res, countdown=3, max_retries=None)
    if res['previous_rep'] != res['total_rep']:
        pleb.reputation_update_seen = False
        pleb.save()
        check_priv = spawn_task(task_func=check_privileges,
                                task_param={"username": username})
        cache.delete(username)
        if isinstance(check_priv, Exception):
            raise update_reputation.retry(exc=check_priv,
                                          countdown=3,
                                          max_retries=None)
    return True
Example #27
0
def create_wall_task(username=None):
    from sb_wall.neo_models import Wall
    try:
        query = 'MATCH (pleb:Pleb {username: "******"})' \
                '-[:OWNS_WALL]->(wall:Wall) RETURN wall' % username
        res, _ = db.cypher_query(query)
        if res.one is None:
            wall = Wall(wall_id=str(uuid1())).save()
            query = 'MATCH (pleb:Pleb {username: "******"}),' \
                    '(wall:Wall {wall_id: "%s"}) ' \
                    'CREATE UNIQUE (pleb)-[:OWNS_WALL]->(wall) ' \
                    'RETURN wall' % (username, wall.wall_id)
            res, _ = db.cypher_query(query)
        spawned = spawn_task(task_func=finalize_citizen_creation,
                             task_param={"username": username})
        if isinstance(spawned, Exception) is True:
            raise create_wall_task.retry(exc=spawned,
                                         countdown=3,
                                         max_retries=None)
    except (CypherException, IOError, ClientError) as e:
        raise create_wall_task.retry(exc=e, countdown=3, max_retries=None)
    return spawned
Example #28
0
 def update(self, instance, validated_data):
     # TODO do we want to allow for tags to be changed?
     # I don't think we do because of the tight coupling with Reputation
     # and search. I think it could be exploited too easily.
     """
     When we start doing versioning:
     edit = Question(title=validated_data.get('title', instance.title),
                     content=validated_data.get('content', instance.content))
     edit.save()
     instance.edits.connect(edit)
     edit.edit_to.connect(instance)
     """
     validate_is_owner(self.context.get('request', None), instance)
     instance.title = validated_data.get('title', instance.title)
     instance.content = render_content(
         validated_data.get('content', instance.content))
     instance.last_edited_on = datetime.now(pytz.utc)
     instance.latitude = validated_data.get('latitude', instance.latitude)
     instance.longitude = validated_data.get('longitude',
                                             instance.longitude)
     instance.affected_area = validated_data.get('affected_area',
                                                 instance.affected_area)
     instance.external_location_id = validated_data.get(
         'external_location_id', instance.external_location_id)
     instance.save()
     cache.delete(instance.object_uuid)
     if validated_data.get('external_location_id', None) is not None:
         spawn_task(
             task_func=create_location_tree,
             task_param={"external_id": instance.external_location_id})
     spawn_task(task_func=add_auto_tags_to_question_task,
                task_param={"object_uuid": instance.object_uuid})
     spawn_task(task_func=create_question_summary_task,
                task_param={'object_uuid': instance.object_uuid})
     return super(QuestionSerializerNeo,
                  self).update(instance, validated_data)
Example #29
0
    def create(self, validated_data):
        from sb_gifts.neo_models import Giftlist
        from sb_quests.neo_models import Quest, Position
        request, _, _, _, _ = gather_request_data(self.context)
        query = 'MATCH (quest:Quest {owner_username: "******"}) WITH quest ' \
                'OPTIONAL MATCH (quest)-[:EMBARKS_ON]->' \
                '(mission:Mission) RETURN quest, ' \
                'count(mission) as mission_count' % request.user.username
        res, _ = db.cypher_query(query)
        if res.one is not None:
            quest = Quest.inflate(res.one['quest'])
            if quest.account_type == "free":
                if res.one['mission_count'] >= settings.FREE_MISSIONS:
                    raise serializers.ValidationError(
                        {"detail": "Sorry free Quests can only "
                                   "have 5 Missions.",
                         "developer_message": "",
                         "status_code": status.HTTP_400_BAD_REQUEST})
        else:
            raise serializers.ValidationError(
                {"detail": "We couldn't find a Quest for this "
                           "Mission. Please contact us if this "
                           "problem continues.",
                 "developer_message": "",
                 "status_code": status.HTTP_404_NOT_FOUND})
        add_district = ""
        focus_type = validated_data.get('focus_on_type')
        level = validated_data.get('level')

        # Properly Title the case of the following words in the location name
        location = validated_data.get('location_name')
        if location is not None:
            location = location.replace(
                " Of", " of").replace(" And", " and").replace(" Or", " or")
        focused_on = validated_data.get('focus_name')
        if focus_type == "advocacy":
            focused_on = slugify(focused_on)
        else:
            focused_on = slugify(
                focused_on).title().replace('-', ' ').replace('_', ' ')
        district = validated_data.get('district')
        formatted_location_name = validated_data.get('formatted_location_name')
        # TODO what happens if a moderator makes the mission?
        owner_username = request.user.username
        title = focused_on.title().replace('-', ' ').replace('_', ' ')
        mission = Mission(owner_username=owner_username, level=level,
                          focus_on_type=focus_type,
                          focus_name=focused_on,
                          title=title,
                          wallpaper_pic=static(
                              'images/wallpaper_capitol_2.jpg'),
                          formatted_location_name=formatted_location_name)\
            .save()
        giftlist = Giftlist().save()
        giftlist.mission.connect(mission)
        if focus_type == "position":
            if level == "federal":
                if district:
                    loc_query = '(:Location {name: ' \
                                '"United States of America"})' \
                                '-[:ENCOMPASSES]->(:Location {name: "%s"})' \
                                '-[:ENCOMPASSES]->(location:Location ' \
                                '{name: "%s", sector: "federal"})' % (
                                    location, district)
                elif location and focused_on != "President":
                    loc_query = '(:Location {name: ' \
                                '"United States of America"})' \
                                '-[:ENCOMPASSES]->' \
                                '(location:Location {name: "%s"})' % location
                else:
                    loc_query = '(location:Location {name: ' \
                                '"United States of America"})'
            elif level == "state_upper" or level == "state_lower" \
                    or level == "state":
                parent_location = "location"
                if district:
                    add_district = '-[:ENCOMPASSES]->' \
                                   '(location:Location ' \
                                   '{name: "%s", sector: "%s"})' \
                                   '' % (district, level)
                    parent_location = "b"
                # use sector for level input since we're talking about
                # state_upper and state_lower with the position
                # and level input here only has state, federal, and local
                loc_query = '(a:Location {name: "United States of America"})' \
                            '-[:ENCOMPASSES]->' \
                            '(%s:Location {name: "%s"})%s' % (
                                parent_location, location, add_district)
            else:
                loc_query = '(location:Location {external_id:"%s"})' % location
            query = 'MATCH %s-' \
                    '[:POSITIONS_AVAILABLE]->(position:Position ' \
                    '{name:"%s", level:"%s"}) RETURN position' % \
                    (loc_query, focused_on, level)
            res, _ = db.cypher_query(query)
            if not res.one:
                focused_on = slugify(focused_on).title().replace('-', ' ')\
                    .replace('_', ' ')
                new_position = Position(verified=False, name=focused_on,
                                        level=level,
                                        user_created=True).save()
                query = 'MATCH %s, ' \
                        '(position:Position {object_uuid:"%s"}) ' \
                        'CREATE UNIQUE (position)' \
                        '<-[r:POSITIONS_AVAILABLE]-(location) ' \
                        'RETURN position' % (loc_query,
                                             new_position.object_uuid)
                res, _ = db.cypher_query(query)
            query = 'MATCH %s-' \
                    '[:POSITIONS_AVAILABLE]->' \
                    '(position:Position {name: "%s", level: "%s"}),' \
                    '(mission:Mission {object_uuid: "%s"}),' \
                    '(quest:Quest {owner_username: "******"}) ' \
                    'CREATE UNIQUE (position)<-[:FOCUSED_ON]-' \
                    '(mission)<-[:EMBARKS_ON]-(quest) ' \
                    'WITH quest, location, mission, position ' \
                    'CREATE UNIQUE (location)<-[:WITHIN]-(mission) ' \
                    'RETURN mission' % (
                        loc_query, focused_on, level, mission.object_uuid,
                        owner_username)
            res, _ = db.cypher_query(query)
            mission = Mission.inflate(res.one)
        elif focus_type == "advocacy":
            focused_on = slugify(focused_on)
            try:
                Tag.nodes.get(name=focused_on)
            except (DoesNotExist, Tag.DoesNotExist):
                Tag(name=focused_on).save()
            if level == "local":
                loc_query = '(location:Location {external_id: "%s"}) ' % (
                    location)
            elif level == "state":
                if district:
                    loc_query = '(:Location {name: ' \
                                '"United States of America"})' \
                                '-[:ENCOMPASSES]->(:Location {name: "%s"})' \
                                '-[:ENCOMPASSES]->(location:Location ' \
                                '{name: "%s", sector: "federal"}) ' % (
                                    location, district)
                else:
                    loc_query = '(:Location {name: ' \
                                '"United States of America"})' \
                                '-[:ENCOMPASSES]->' \
                                '(location:Location {name: "%s"}) ' % location
            elif level == "federal":
                if district:
                    loc_query = '(:Location {name: ' \
                                '"United States of America"})' \
                                '-[:ENCOMPASSES]->(:Location {name: "%s"})' \
                                '-[:ENCOMPASSES]->(location:Location ' \
                                '{name: "%s", sector: "federal"}) ' % (
                                    location, district)
                elif location and focused_on != "President":
                    loc_query = '(:Location {name: ' \
                                '"United States of America"})' \
                                '-[:ENCOMPASSES]->' \
                                '(location:Location {name: "%s"}) ' % location
                else:
                    loc_query = '(location:Location {name: ' \
                                '"United States of America"}) '
            else:
                raise serializers.ValidationError(
                    {"detail": "Sorry Could Not Determine Where You're "
                               "advocating. Please try a different "
                               "location or contact us.",
                     "developer_message": "",
                     "status_code": status.HTTP_400_BAD_REQUEST})
            query = 'MATCH (tag:Tag {name: "%s"}), ' \
                    '(quest:Quest {owner_username: "******"}), ' \
                    '(mission:Mission {object_uuid: "%s"}), ' \
                    '%s WITH tag, quest, mission, location ' \
                    'CREATE UNIQUE (tag)<-[:FOCUSED_ON]-(mission)' \
                    '<-[:EMBARKS_ON]-(quest) WITH location, mission ' \
                    'CREATE UNIQUE (mission)-[:WITHIN]->(location) ' \
                    'RETURN mission' % (focused_on,
                                        owner_username, mission.object_uuid,
                                        loc_query)
            res, _ = db.cypher_query(query)
            if res.one is not None:
                mission = Mission.inflate(res.one)
        setup_onboarding(quest, mission)
        spawn_task(task_func=send_reengage_message,
                   task_param={"mission_uuid": mission.object_uuid,
                               "mission_type": focus_type},
                   countdown=900)
        return mission
Example #30
0
def object_vote_notifications(object_uuid, previous_vote_type, new_vote_type,
                              voting_pleb):
    sb_object = get_parent_votable_content(object_uuid)
    try:
        current_pleb = Pleb.get(username=voting_pleb)
    except (DoesNotExist, Pleb.DoesNotExist, CypherException, ClientError,
            IOError) as e:
        raise object_vote_notifications.retry(exc=e, countdown=10,
                                              max_retries=None)
    if new_vote_type != 2 and previous_vote_type != new_vote_type:
        reputation_change = sb_object.down_vote_adjustment
        modifier = "downvoted"
        reputation_message = ""
        if new_vote_type:
            reputation_change = sb_object.up_vote_adjustment
            modifier = "upvoted"
        if reputation_change:
            # using b tag here because a div or p will break the rendering of
            # the notification html due to them not being allowed in a tags
            color = "sb_reputation_notification_change_red"
            if reputation_change > 0:
                color = "sb_reputation_notification_change_green"
            reputation_message = render_to_string(
                'notification_message.html',
                {'color': color, 'reputation_change':
                    "%+d" % reputation_change})
            if sb_object.visibility != "public":
                reputation_message = ""
        public = False
        action_name = " %s %s %s " % ("%s your" % modifier,
                                      sb_object.get_child_label(),
                                      reputation_message)
        titled_content = get_parent_titled_content(sb_object.object_uuid)
        if not isinstance(titled_content, Exception):
            truncate_content = titled_content.title
        else:
            truncate_content = sb_object.content
        if sb_object.visibility == "public":
            action_name = '%s from vote on "%s"' % (reputation_message,
                                                    smart_truncate(
                                                        truncate_content))
            public = True
        if previous_vote_type != new_vote_type and new_vote_type != 2:
            if sb_object.get_child_label().lower() == "comment":
                comment_on = Comment.get_comment_on(sb_object.object_uuid)
                page_type = comment_on.get_child_label().lower()
                object_id = comment_on.object_uuid
            else:
                page_type = sb_object.get_child_label().lower()
                object_id = sb_object.object_uuid
            res = spawn_task(spawn_notifications, task_param={
                'from_pleb': current_pleb.username,
                'to_plebs': [sb_object.owner_username],
                'sb_object': sb_object.object_uuid,
                'notification_id': str(uuid1()),
                'url': reverse(
                    "single_%s_page" % page_type,
                    kwargs={"object_uuid": object_id}),
                'action_name': action_name,
                'public': public
            })
            if isinstance(res, Exception):
                raise object_vote_notifications.retry(exc=res, countdown=10,
                                                      max_retries=None)
    return True