예제 #1
0
 def test_calls_activitypub_retrieve_and_parse_content(self, mock_import):
     mock_retrieve = Mock()
     mock_import.return_value = mock_retrieve
     retrieve_remote_content("https://example.com/foobar")
     mock_retrieve.retrieve_and_parse_content.assert_called_once_with(
         id="https://example.com/foobar", guid=None, handle=None, entity_type=None, sender_key_fetcher=None,
     )
예제 #2
0
 def test_calls_diaspora_retrieve_and_parse_content(self, mock_import):
     mock_retrieve = Mock()
     mock_import.return_value = mock_retrieve
     retrieve_remote_content("1234", handle="*****@*****.**", entity_type="post", sender_key_fetcher=sum)
     mock_retrieve.retrieve_and_parse_content.assert_called_once_with(
         id="1234", guid="1234", handle="*****@*****.**", entity_type="post", sender_key_fetcher=sum,
     )
예제 #3
0
 def test_calls_diaspora_retrieve_and_parse_content(self, mock_import):
     mock_retrieve = Mock()
     mock_import.return_value = mock_retrieve
     retrieve_remote_content(
         "diaspora://[email protected]/status_message/1234",
         sender_key_fetcher=sum)
     mock_retrieve.retrieve_and_parse_content.assert_called_once_with(
         "diaspora://[email protected]/status_message/1234",
         sender_key_fetcher=sum,
     )
예제 #4
0
def process_entity_share(entity, profile):
    """Process an entity of type Share."""
    if not entity.entity_type == "Post":
        # TODO: enable shares of replies too
        logger.warning("Ignoring share entity type that is not of type Post")
        return
    try:
        target_content = Content.objects.fed(entity.target_id,
                                             share_of__isnull=True).get()
    except Content.DoesNotExist:
        # Try fetching. If found, process and then try again
        remote_target = retrieve_remote_content(
            entity.target_id,
            guid=entity.target_guid,
            handle=entity.target_handle,
            entity_type=entity.entity_type,
            sender_key_fetcher=sender_key_fetcher,
        )
        if remote_target:
            process_entities([remote_target])
            try:
                target_content = Content.objects.fed(
                    entity.target_id, share_of__isnull=True).get()
            except Content.DoesNotExist:
                logger.warning(
                    "Share target was fetched from remote, but it is still missing locally! Share: %s",
                    entity)
                return
        else:
            logger.warning(
                "No target found for share even after fetching from remote: %s",
                entity)
            return
    values = {
        "text": safe_text_for_markdown(entity.raw_content),
        "author": profile,
        # TODO: ensure visibility constraints depending on shared content?
        "visibility":
        Visibility.PUBLIC if entity.public else Visibility.LIMITED,
        "remote_created": safe_make_aware(entity.created_at, "UTC"),
        "service_label": safe_text(entity.provider_display_name) or "",
    }
    values["text"] = _embed_entity_images_to_post(entity._children,
                                                  values["text"])
    fid = safe_text(entity.id)
    if getattr(entity, "guid", None):
        values["guid"] = safe_text(entity.guid)
    content, created = Content.objects.fed_update_or_create(
        fid, values, extra_lookups={'share_of': target_content})
    _process_mentions(content, entity)
    if created:
        logger.info("Saved share: %s", content)
    else:
        logger.info("Updated share: %s", content)
    # TODO: send participation to the share from the author, if local
    # We probably want that to happen even though our shares are not separate in the stream?
    if target_content.local:
        # We should relay this share entity to participants we know of
        from socialhome.federate.tasks import forward_entity
        django_rq.enqueue(forward_entity, entity, target_content.id)
예제 #5
0
파일: tasks.py 프로젝트: jaywink/socialhome
def process_entity_share(entity, profile):
    """Process an entity of type Share."""
    if not entity.entity_type == "Post":
        # TODO: enable shares of replies too
        logger.warning("Ignoring share entity type that is not of type Post")
        return
    try:
        target_content = Content.objects.fed(entity.target_id, share_of__isnull=True).get()
    except Content.DoesNotExist:
        # Try fetching. If found, process and then try again
        remote_target = retrieve_remote_content(
            entity.target_id,
            guid=entity.target_guid,
            handle=entity.target_handle,
            entity_type=entity.entity_type,
            sender_key_fetcher=sender_key_fetcher,
        )
        if remote_target:
            process_entities([remote_target])
            try:
                target_content = Content.objects.fed(entity.target_id, share_of__isnull=True).get()
            except Content.DoesNotExist:
                logger.warning("Share target was fetched from remote, but it is still missing locally! Share: %s",
                               entity)
                return
        else:
            logger.warning("No target found for share even after fetching from remote: %s", entity)
            return
    values = {
        "text": safe_text_for_markdown(entity.raw_content),
        "author": profile,
        # TODO: ensure visibility constraints depending on shared content?
        "visibility": Visibility.PUBLIC if entity.public else Visibility.LIMITED,
        "remote_created": safe_make_aware(entity.created_at, "UTC"),
        "service_label": safe_text(entity.provider_display_name) or "",
    }
    values["text"] = _embed_entity_images_to_post(entity._children, values["text"])
    fid = safe_text(entity.id)
    if getattr(entity, "guid", None):
        values["guid"] = safe_text(entity.guid)
    content, created = Content.objects.fed_update_or_create(fid, values, extra_lookups={'share_of': target_content})
    _process_mentions(content, entity)
    if created:
        logger.info("Saved share: %s", content)
    else:
        logger.info("Updated share: %s", content)
    # TODO: send participation to the share from the author, if local
    # We probably want that to happen even though our shares are not separate in the stream?
    if target_content.local:
        # We should relay this share entity to participants we know of
        from socialhome.federate.tasks import forward_entity
        django_rq.enqueue(forward_entity, entity, target_content.id)
예제 #6
0
def process_entity_share(entity, profile):
    """Process an entity of type Share."""
    if not entity.entity_type == "Post":
        # TODO: enable shares of replies too
        logger.warning("Ignoring share entity type that is not of type Post")
        return
    try:
        target_content = Content.objects.get(guid=entity.target_guid,
                                             share_of__isnull=True)
    except Content.DoesNotExist:
        # Try fetching. If found, process and then try again
        remote_target = retrieve_remote_content(
            entity.target_id, sender_key_fetcher=sender_key_fetcher)
        if remote_target:
            process_entities([remote_target])
            try:
                target_content = Content.objects.get(guid=entity.target_guid,
                                                     share_of__isnull=True)
            except Content.DoesNotExist:
                logger.warning(
                    "Share target was fetched from remote, but it is still missing locally! Share: %s",
                    entity)
                return
        else:
            logger.warning(
                "No target found for share even after fetching from remote: %s",
                entity)
            return
    if not target_content.author.handle == entity.target_handle:
        logger.warning(
            "Share target handle is different from the author of locally known shared content!"
        )
        return
    values = {
        "text": safe_text_for_markdown(entity.raw_content),
        "author": profile,
        # TODO: ensure visibility constraints depending on shared content?
        "visibility":
        Visibility.PUBLIC if entity.public else Visibility.LIMITED,
        "remote_created": safe_make_aware(entity.created_at, "UTC"),
        "service_label": safe_text(entity.provider_display_name) or "",
    }
    values["text"] = _embed_entity_images_to_post(entity._children,
                                                  values["text"])
    guid = safe_text(entity.guid)
    content, created = Content.objects.update_or_create(
        guid=guid, share_of=target_content, defaults=values)
    if created:
        logger.info("Saved share: %s", content)
    else:
        logger.info("Updated share: %s", content)
예제 #7
0
    def get(self, request, *args, **kwargs):
        """See if we have a direct match. If so redirect, if not, search.

        Try fetching a remote profile if the search term is a handle or fid.
        """
        q = safe_text(request.GET.get("q"))
        if q:
            q = q.strip().lower().strip("@")
        self.q = q
        # Check if direct tag matches
        if q.startswith('#'):
            try:
                tag = Tag.objects.filter(
                    name=q[1:]
                ).annotate(
                    content_count=Count('contents')
                ).filter(
                    content_count__gt=0
                ).get()
            except Tag.DoesNotExist:
                pass
            else:
                return redirect(tag.get_absolute_url())
        # Check if profile matches
        profile = None
        try:
            profile = Profile.objects.visible_for_user(request.user).fed(q).get()
        except Profile.DoesNotExist:
            # Try a remote search
            if is_url(q) or validate_handle(q):
                try:
                    remote_profile = retrieve_remote_profile(q)
                except (AttributeError, ValueError, xml.parsers.expat.ExpatError):
                    # Catch various errors parsing the remote profile
                    return super().get(request, *args, **kwargs)
                if remote_profile and isinstance(remote_profile, base.Profile):
                    profile = Profile.from_remote_profile(remote_profile)
        if profile:
            return redirect(reverse("users:profile-detail", kwargs={"uuid": profile.uuid}))
        # Check if content matches
        content = None
        try:
            content = Content.objects.visible_for_user(request.user).fed(q).get()
        except Content.DoesNotExist:
            # Try a remote search
            if is_url(q):
                try:
                    remote_content = retrieve_remote_content(q)
                except (AttributeError, ValueError):
                    # Catch various errors parsing the remote content
                    return super().get(request, *args, **kwargs)
                if remote_content:
                    process_entities([remote_content])
                    # Try again
                    try:
                        content = Content.objects.visible_for_user(request.user).fed(remote_content.id).get()
                    except Content.DoesNotExist:
                        return super().get(request, *args, **kwargs)
        if content:
            return redirect(reverse("content:view", kwargs={"pk": content.id}))
        try:
            return super().get(request, *args, **kwargs)
        except QueryError:
            # Re-render the form
            messages.warning(self.request, _("Search string is invalid, please try another one."))
            return HttpResponseRedirect(self.get_success_url())