Exemplo n.º 1
0
def _get_remote_followers(profile, exclude=None):
    """Get remote followers for a profile."""
    followers = []
    for follower in Profile.objects.filter(following=profile, user__isnull=True):
        if follower.handle != exclude:
            followers.append(generate_diaspora_profile_id(follower.handle, follower.guid))
    return followers
Exemplo n.º 2
0
def send_share(content_id):
    """Handle sending a share of a Content object to the federation layer.

    Currently we only deliver public shares.
    """
    try:
        content = Content.objects.get(id=content_id, visibility=Visibility.PUBLIC, content_type=ContentType.SHARE,
                                      local=True)
    except Content.DoesNotExist:
        logger.warning("No local share found with id %s", content_id)
        return
    entity = make_federable_content(content)
    if entity:
        if settings.DEBUG:
            # Don't send in development mode
            return
        recipients = _get_remote_followers(content.author)
        if not content.share_of.local:
            # Send to original author
            recipients.append(
                generate_diaspora_profile_id(content.share_of.author.handle, content.share_of.author.guid),
            )
        logger.debug("send_share - sending to recipients: %s", recipients)
        handle_send(entity, content.author, recipients)
    else:
        logger.warning("send_share - No entity for %s", content)
Exemplo n.º 3
0
 def test_handle_send_is_called(self, mock_maker, mock_send):
     send_share(self.share.id)
     mock_send.assert_called_once_with(
         "entity",
         self.share.author,
         [generate_diaspora_profile_id(self.content.author.handle, self.content.author.guid)],
     )
Exemplo n.º 4
0
 def test_exclude_is_excluded(self):
     followers = set(_get_remote_followers(self.user.profile, exclude=self.remote_follower.handle))
     self.assertEqual(
         followers,
         {
             generate_diaspora_profile_id(self.remote_follower2.handle, self.remote_follower2.guid),
         }
     )
Exemplo n.º 5
0
 def test_send_reply_to_remote_author(self, mock_make, mock_forward,
                                      mock_sender):
     send_reply(self.reply2.id)
     mock_sender.assert_called_once_with("entity", self.reply2.author, [
         generate_diaspora_profile_id(self.remote_content.author.handle,
                                      self.remote_content.author.guid),
     ])
     self.assertTrue(mock_forward.called is False)
Exemplo n.º 6
0
 def test_limited_profile_retraction_not_sent_to_relay(
         self, mock_make, mock_send):
     send_profile_retraction(self.limited_profile)
     mock_send.assert_called_once_with(
         "entity",
         self.limited_profile,
         [
             generate_diaspora_profile_id(self.remote_profile.handle,
                                          self.remote_profile.guid),
         ],
     )
Exemplo n.º 7
0
 def test_handle_send_is_called(self, mock_make, mock_send):
     send_profile_retraction(self.public_profile)
     mock_send.assert_called_once_with(
         "entity",
         self.public_profile,
         [
             'diaspora://[email protected]/profile/',
             generate_diaspora_profile_id(self.remote_profile.handle,
                                          self.remote_profile.guid),
         ],
     )
Exemplo n.º 8
0
 def test_send_reply__limited_content(self, mock_make, mock_forward,
                                      mock_sender):
     send_reply(self.limited_reply.id)
     mock_sender.assert_called_once_with(
         "entity",
         self.limited_reply.author,
         [(
             generate_diaspora_profile_id(self.remote_profile.handle,
                                          guid=self.remote_profile.guid),
             self.remote_profile.key,
         )],
     )
Exemplo n.º 9
0
 def test_handle_send_is_called__limited_content(self, mock_maker,
                                                 mock_send):
     send_content(self.limited_content.id,
                  recipient_id=self.remote_profile.id)
     mock_send.assert_called_once_with(
         "entity",
         self.limited_content.author,
         [(
             generate_diaspora_profile_id(self.remote_profile.handle,
                                          guid=self.remote_profile.guid),
             self.remote_profile.key,
         )],
     )
Exemplo n.º 10
0
def _get_remote_participants_for_content(target_content, participants=None, exclude=None, include_remote=False):
    """Get remote participants for a target content.

    Look at both replies and shares of target local content. Does a recursive call to get also replies of shares,
    even if those shares are remote.
    """
    if not participants:
        participants = []
    if not include_remote and not target_content.local:
        return participants
    replies = Content.objects.filter(parent_id=target_content.id, visibility=Visibility.PUBLIC, local=False)
    for reply in replies:
        if reply.author.handle != exclude:
            participants.append(generate_diaspora_profile_id(reply.author.handle, reply.author.guid))
    if target_content.content_type == ContentType.CONTENT:
        shares = Content.objects.filter(share_of_id=target_content.id, visibility=Visibility.PUBLIC, local=False)
        for share in shares:
            if share.author.handle != exclude:
                participants.append(generate_diaspora_profile_id(share.author.handle, share.author.guid))
            participants = _get_remote_participants_for_content(
                share, participants, exclude=exclude, include_remote=True
            )
    return participants
Exemplo n.º 11
0
def send_follow_change(profile_id, followed_id, follow):
    """Handle sending of a local follow of a remote profile."""
    try:
        profile = Profile.objects.get(id=profile_id, user__isnull=False)
    except Profile.DoesNotExist:
        logger.warning("send_follow_change - No local profile %s found to send follow with", profile_id)
        return
    try:
        remote_profile = Profile.objects.get(id=followed_id, user__isnull=True)
    except Profile.DoesNotExist:
        logger.warning("send_follow_change - No remote profile %s found to send follow for", followed_id)
        return
    if settings.DEBUG:
        # Don't send in development mode
        return
    entity = base.Follow(handle=profile.handle, target_handle=remote_profile.handle, following=follow)
    recipients = [
        (generate_diaspora_profile_id(remote_profile.handle, remote_profile.guid), remote_profile.key),
     ]
    logger.debug("send_follow_change - sending to recipients: %s", recipients)
    handle_send(entity, profile, recipients)
    # Also trigger a profile send
    send_profile(profile_id, recipients=[generate_diaspora_profile_id(remote_profile.handle, remote_profile.guid)])
Exemplo n.º 12
0
 def test_forward_entity__limited_content(self, mock_send):
     entity = Comment(handle=self.limited_reply.author.handle,
                      guid=self.limited_reply.guid)
     forward_entity(entity, self.limited_content.id)
     mock_send.assert_called_once_with(
         entity,
         self.limited_reply.author, [(
             generate_diaspora_profile_id(
                 self.remote_limited_reply.author.handle,
                 self.remote_limited_reply.author.guid,
             ),
             self.remote_limited_reply.author.key,
         )],
         parent_user=self.limited_content.author)
Exemplo n.º 13
0
    def extract_mentions(self):
        """
        Extract mentions from an entity with ``raw_content``.

        :return: set
        """
        if not hasattr(self, "raw_content"):
            return set()
        mentions = re.findall(r'@{[^;]+; [\w.-]+@[^}]+}', self.raw_content)
        if not mentions:
            return set()
        mentions = {s.split(';')[1].strip(' }') for s in mentions}
        mentions = {generate_diaspora_profile_id(s) for s in mentions}
        return mentions
Exemplo n.º 14
0
def send_reply(content_id):
    """
    Handle sending a Content object that is a reply out via the federation layer.
    """
    try:
        content = Content.objects.get(
            id=content_id,
            visibility__in=(Visibility.PUBLIC, Visibility.LIMITED),
            content_type=ContentType.REPLY,
            local=True,
        )
    except Content.DoesNotExist:
        logger.warning("No content found with id %s", content_id)
        return
    entity = make_federable_content(content)
    if not entity:
        logger.warning("send_reply - No entity for %s", content)
    if settings.DEBUG:
        # Don't send in development mode
        return
    # Send directly (remote parent) or as a relayable (local parent)
    if content.parent.local:
        forward_entity(entity, content.parent.id)
    else:
        # We only need to send to the original author
        parent_author = content.parent.author
        if content.visibility == Visibility.PUBLIC:
            recipients = [
                generate_diaspora_profile_id(parent_author.handle, parent_author.guid),
            ]
        else:
            recipients = [
                (generate_diaspora_profile_id(parent_author.handle, parent_author.guid), parent_author.key),
            ]
        logger.debug("send_reply - sending to recipients: %s", recipients)
        handle_send(entity, content.author, recipients)
Exemplo n.º 15
0
def get_diaspora_profile_by_handle(handle):
    """
    Return a local Profile suitable for the federation library profile using Diaspora handle.
    """
    from socialhome.users.models import Profile  # Circulars
    profile = Profile.objects.select_related('user').only('guid', 'user__username').get(handle=handle)
    profile_path = reverse("users:detail", kwargs={"username": profile.user.username})
    return {
        "id": generate_diaspora_profile_id(handle, profile.guid),
        "profile_path": profile_path,
        # We don't support atom feeds yet, but since diaspora has a bug currently (0.7.3.x),
        # we need to specify something here. Let's use the profile url here too.
        # TODO remove this once diaspora releases the bug fix
        "atom_path": profile_path,
    }
Exemplo n.º 16
0
def send_content(content_id, recipient_id=None):
    """
    Handle sending a Content object out via the federation layer.
    """
    try:
        content = Content.objects.get(
            id=content_id,
            visibility__in=(Visibility.PUBLIC, Visibility.LIMITED),
            content_type=ContentType.CONTENT,
            local=True,
        )
    except Content.DoesNotExist:
        logger.warning("No local content found with id %s", content_id)
        return
    if recipient_id:
        try:
            recipient = Profile.objects.get(id=recipient_id, user__isnull=True)
        except Profile.DoesNotExist:
            logger.warning("No remote recipient found with id %s", recipient_id)
            return
    else:
        recipient = None
    entity = make_federable_content(content)
    if entity:
        if settings.DEBUG:
            # Don't send in development mode
            return
        if recipient:
            recipients = [
                (generate_diaspora_profile_id(recipient.handle, recipient.guid), recipient.key),
            ]
        else:
            recipients = [settings.SOCIALHOME_RELAY_ID]
            recipients.extend(_get_remote_followers(content.author))

        logger.debug("send_content - sending to recipients: %s", recipients)
        handle_send(entity, content.author, recipients)
    else:
        logger.warning("send_content - No entity for %s", content)
Exemplo n.º 17
0
def parse_nodeinfo_document(doc, host):
    result = deepcopy(defaults)
    nodeinfo_version = doc.get('version', '1.0')
    result['host'] = host
    result['name'] = doc.get('metadata', {}).get('nodeName', host)
    result['version'] = doc.get('software', {}).get('version', '')
    result['platform'] = doc.get('software', {}).get('name', 'unknown').lower()
    if nodeinfo_version in ('1.0', '1.1'):
        inbound = doc.get('protocols', {}).get('inbound', [])
        outbound = doc.get('protocols', {}).get('outbound', [])
        protocols = sorted(list(set(inbound + outbound)))
        result['protocols'] = protocols
    else:
        result['protocols'] = doc.get('protocols', [])
    inbound = doc.get('services', {}).get('inbound', [])
    outbound = doc.get('services', {}).get('outbound', [])
    services = sorted(list(set(inbound + outbound)))
    result['services'] = services
    result['open_signups'] = doc.get('openRegistrations', False)
    result['activity']['users']['total'] = int_or_none(
        doc.get('usage', {}).get('users', {}).get('total'))
    result['activity']['users']['half_year'] = int_or_none(
        doc.get('usage', {}).get('users', {}).get('activeHalfyear'))
    monthly = int_or_none(
        doc.get('usage', {}).get('users', {}).get('activeMonth'))
    result['activity']['users']['monthly'] = monthly
    if monthly:
        result['activity']['users']['weekly'] = int(
            monthly * MONTHLY_USERS_WEEKLY_MULTIPLIER)
    result['activity']['local_posts'] = int_or_none(
        doc.get('usage', {}).get('localPosts'))
    result['activity']['local_comments'] = int_or_none(
        doc.get('usage', {}).get('localComments'))
    result['features'] = doc.get('metadata', {})
    admin_handle = doc.get('metadata', {}).get('adminAccount', None)
    if admin_handle:
        result['organization']['account'] = generate_diaspora_profile_id(
            "%s@%s" % (admin_handle, host))
    return result
Exemplo n.º 18
0
def get_profile_by_handle(handle):
    return {
        "id": generate_diaspora_profile_id(handle, "1234"),
        "profile_path": "/profile/1234/",
        "atom_path": "/profile/1234/atom.xml",
    }
Exemplo n.º 19
0
def test_generate_diaspora_profile_id():
    assert generate_diaspora_profile_id(
        "*****@*****.**",
        "1234") == "diaspora://[email protected]/profile/1234"
    assert generate_diaspora_profile_id(
        "*****@*****.**") == "diaspora://[email protected]/profile/"
Exemplo n.º 20
0
 def test_send_to_given_recipients_only(self, mock_federable, mock_send):
     recipients = [generate_diaspora_profile_id(self.remote_profile.handle, self.remote_profile.guid)]
     send_profile(self.profile.id, recipients=recipients)
     mock_send.assert_called_once_with("profile", self.profile, recipients)
Exemplo n.º 21
0
def _get_limited_recipients(sender, content):
    return [
        (generate_diaspora_profile_id(profile.handle, profile.guid), profile.key)
        for profile in content.limited_visibilities.all() if profile.handle != sender
    ]