Пример #1
0
    def to_internal_value(self, data):
        # Validate when passed as attached object or message attachment
        ret = self.to_internal_attached_value(data)
        if ret:
            return ret

        validated_data = super(MessageSerializer, self).to_internal_value(data)
        attachments = validated_data.get('attachments')
        text = validated_data.get('text')
        errors = OrderedDict()

        if not text and not attachments:
            # Todo: check why having string as the detail results in exception
            # raise serializers.ValidationError("Provide 'text' or 'attachments'")
            raise serializers.ValidationError({'': _("Provide 'text' or 'attachments'")})
        if attachments is not None:
            if isinstance(attachments, list) and len(attachments):
                i = 0
                errors['attachments'] = []
                valid_types = ['shout', 'location', 'profile', 'images', 'videos']
                types = ", ".join(map(str, valid_types))
                for attachment in attachments:
                    attachment_error = None

                    if not any_in(valid_types, attachment):
                        attachment_error = {'': _("Should have any of these properties: %(types)s") % {'types': types}}
                        errors['attachments'].insert(i, attachment_error)
                        i += 1
                        continue

                    if 'location' in attachment:
                        if 'latitude' not in attachment['location'] or 'longitude' not in attachment['location']:
                            attachment_error = {'location': _("location object should have 'latitude' and 'longitude'")}

                    if 'images' in attachment or 'videos' in attachment:
                        images = attachment.get('images')
                        videos = attachment.get('videos')
                        if not (images or videos):
                            attachment_error = {'': _("Should have at least one item in 'images' or 'videos'")}
                        # Todo (mo): passing `partial=False` should take care of videos validations
                        if videos:
                            for v in videos:
                                vs = VideoSerializer(data=v)
                                if not vs.is_valid():
                                    attachment_error = {'videos': unicode(vs.errors)}

                    errors['attachments'].insert(i, attachment_error or None)
                    i += 1
                if not any(errors['attachments']):
                    del errors['attachments']

        if text is not None and text == "" and attachments is None:
            errors['text'] = _("Can not be empty")

        # Todo: Raise errors directly that is fine
        if errors:
            raise serializers.ValidationError(errors)

        return validated_data
Пример #2
0
    def to_internal_value(self, data):
        validated_data = super(ReportSerializer, self).to_internal_value(data)
        attached_object = validated_data['attached_object']

        if not any_in(['attached_profile', 'attached_shout', 'attached_conversation'], attached_object):
            error_tuple = (_("Should have either 'profile', 'shout' or 'conversation'"), ERROR_REASON.REQUIRED)
            raise serializers.ValidationError({'attached_object': error_tuple})

        if 'attached_profile' in attached_object:
            validated_data['type'] = REPORT_TYPE_PROFILE

        elif 'attached_shout' in attached_object:
            validated_data['type'] = REPORT_TYPE_SHOUT

        elif 'attached_conversation' in attached_object:
            validated_data['type'] = REPORT_TYPE_CONVERSATION

        return validated_data
Пример #3
0
def save_message_attachments(message, attachments):
    conversation = message.conversation
    for attachment in attachments:
        # todo: map the content types to models
        if MESSAGE_ATTACHMENT_TYPE_SHOUT.text in attachment:
            object_id = attachment[MESSAGE_ATTACHMENT_TYPE_SHOUT.text]['id']
            content_type = ContentType.objects.get_for_model(Shout)
            ma_type = MESSAGE_ATTACHMENT_TYPE_SHOUT
            MessageAttachment.create(message_id=message.id, conversation_id=conversation.id, content_type=content_type,
                                     object_id=object_id, type=ma_type).save()

        if MESSAGE_ATTACHMENT_TYPE_PROFILE.text in attachment:
            object_id = attachment[MESSAGE_ATTACHMENT_TYPE_PROFILE.text]['id']
            content_type = ContentType.objects.get_for_model(User)
            ma_type = MESSAGE_ATTACHMENT_TYPE_PROFILE
            MessageAttachment.create(message_id=message.id, conversation_id=conversation.id, content_type=content_type,
                                     object_id=object_id, type=ma_type).save()

        if MESSAGE_ATTACHMENT_TYPE_LOCATION.text in attachment:
            location = attachment['location']
            sl = SharedLocation(latitude=location['latitude'], longitude=location['longitude'])
            sl.save()
            object_id = sl.id
            content_type = ContentType.objects.get_for_model(SharedLocation)
            ma_type = MESSAGE_ATTACHMENT_TYPE_LOCATION
            MessageAttachment.create(message=message, conversation=conversation, content_type=content_type,
                                     object_id=object_id, type=ma_type)

        if any_in(['images', 'videos'], attachment):
            ma_type = MESSAGE_ATTACHMENT_TYPE_MEDIA
            images = attachment.get('images', []) or []
            videos = attachment.get('videos', []) or []
            ma = MessageAttachment.create(type=ma_type, message=message, conversation=conversation, images=images)
            for v in videos:
                # todo: better handling
                try:
                    video = Video.create(url=v['url'], thumbnail_url=v['thumbnail_url'], provider=v['provider'],
                                         id_on_provider=v['id_on_provider'], duration=v['duration'])
                    ma.videos.add(video)
                except Exception:
                    error_logger.warn("Error creating video", exc_info=True)
Пример #4
0
    def list(self, request, *args, **kwargs):
        """
        List shouts.
        [Shouts Pagination](https://github.com/shoutit/shoutit-api/wiki/Searching-Shouts#pagination)
        ###Response
        <pre><code>
        {
            "count": 59, // number of results
            "next": null, // next results page url
            "previous": null, // previous results page url
            "results": [] // list of {ShoutSerializer}
            "related_searches": [] // list of keywords related to the current search [currently dummy text is being returned]
        }
        </code></pre>
        ---
        serializer: ShoutSerializer
        parameters:
            - name: search
              description: space or comma separated keywords to search in title, text, tags
              paramType: query
            - name: shout_type
              paramType: query
              defaultValue: all
              enum:
                - request
                - offer
                - all
            - name: country
              paramType: query
            - name: city
              paramType: query
            - name: state
              paramType: query
            - name: category
              description: the category slug
              paramType: query
            - name: tags
              description: space or comma separated tags. returned shouts will contain ALL of them. passing single tag is also possible to list its shouts
              paramType: query
            - name: discover
              description: discover item id to list its shouts
              paramType: query
            - name: profile
              description: profile username to list its shouts
              paramType: query
            - name: min_price
              paramType: query
            - name: max_price
              paramType: query
            - name: down_left_lat
              description: -90 to 90, can not be greater than up_right_lat
              paramType: query
            - name: down_left_lng
              description: -180 to 180, can not be greater than up_right_lng
              paramType: query
            - name: up_right_lat
              description: -90 to 90
              paramType: query
            - name: up_right_lng
              description: -180 to 180
              paramType: query
        """
        shouts = self.filter_queryset(self.get_index_search())
        page = self.paginate_queryset(shouts)
        serializer = self.get_serializer(page, many=True)
        result = self.get_paginated_response(serializer.data)

        # Todo: add actual data
        result.data['web_url'] = settings.SITE_LINK + 'search?src=api'
        result.data['related_searches'] = []

        # Track, skip when requests shouts of a Profile, Tag or Discover
        search_data = getattr(shouts, 'search_data', {})
        if not any_in(['profile', 'tag', 'discover'], search_data.keys()):
            search_data.update({
                'num_results':
                result.data.get('count'),
                'api_client':
                getattr(request, 'api_client', None),
                'api_version':
                request.version,
            })
            event_name = 'search' if 'search' in search_data else 'browse'
            mixpanel_controller.track(request.user.pk, event_name, search_data)
        return result
Пример #5
0
    def list(self, request, *args, **kwargs):
        """
        List shouts.
        [Shouts Pagination](https://docs.google.com/document/d/1Zp9Ks3OwBQbgaDRqaULfMDHB-eg9as6_wHyvrAWa8u0/edit#heading=h.97r3lxfv95pj)
        ###Response
        <pre><code>
        {
          "next": null, // next results page url
          "previous": null, // previous results page url
          "results": [] // list of {ShoutSerializer}
          "related_searches": [] // list of keywords related to the current search [currently dummy text is being returned]
        }
        </code></pre>
        ---
        serializer: ShoutSerializer
        parameters:
            - name: search
              description: space or comma separated keywords to search in title, text, tags
              paramType: query
            - name: shout_type
              paramType: query
              defaultValue: all
              enum:
                - request
                - offer
                - all
            - name: country
              paramType: query
            - name: city
              paramType: query
            - name: min_price
              type: float
              paramType: query
              type: float
            - name: max_price
              paramType: query
            - name: down_left_lat
              description: -90 to 90, can not be greater than up_right_lat
              type: float
              paramType: query
            - name: down_left_lng
              description: -180 to 180, can not be greater than up_right_lng
              type: float
              paramType: query
            - name: up_right_lat
              description: -90 to 90
              type: float
              paramType: query
            - name: up_right_lng
              description: -180 to 180
              type: float
              paramType: query
            - name: category
              description: the category name
              paramType: query
            - name: tags
              description: space or comma separated tags. returned shouts will contain ALL of them. passing single tag is also possible to list its shouts
              paramType: query
            - name: discover
              description: discover item id to list its shouts
              paramType: query
            - name: user
              description: user username to list his shouts
              paramType: query
        """
        shouts = self.filter_queryset(self.get_index_search())
        page = self.paginate_queryset(shouts)
        serializer = self.get_serializer(page, many=True)
        result = self.get_paginated_response(serializer.data)
        result.data['related_searches'] = [
            'HP', 'Laptops', 'Lenovo', 'Macbook Pro'
        ]

        # Track, skip when requests shouts of a Profile, Tag or Discover
        search_data = getattr(shouts, 'search_data', {})
        if not any_in(['user', 'tag', 'discover'], search_data.keys()):
            search_data.update({
                'num_results':
                result.data.get('count'),
                'api_client':
                getattr(request, 'api_client', None),
                'api_version':
                request.version,
            })
            event_name = 'search' if 'search' in search_data else 'browse'
            mixpanel_controller.track(request.user.pk, event_name, search_data)
        return result