Example #1
0
def save(box: Box, activity: ap.BaseActivity) -> None:
    """Custom helper for saving an activity to the DB."""
    # Set some "type"-related neta
    meta = _meta(activity)
    if box == Box.OUTBOX and activity.has_type(ap.ActivityType.FOLLOW):
        meta[MetaKey.FOLLOW_STATUS.value] = FollowStatus.WAITING.value
    elif activity.has_type(ap.ActivityType.CREATE):
        mentions = []
        obj = activity.get_object()
        for m in obj.get_mentions():
            mentions.append(m.href)
        hashtags = []
        for h in obj.get_hashtags():
            hashtags.append(h.name[1:])  # Strip the #
        meta.update(
            {MetaKey.MENTIONS.value: mentions, MetaKey.HASHTAGS.value: hashtags}
        )

    DB.activities.insert_one(
        {
            "box": box.value,
            "activity": activity.to_dict(),
            "type": _to_list(activity.type),
            "remote_id": activity.id,
            "meta": meta,
        }
    )
Example #2
0
def post_to_inbox(activity: ap.BaseActivity) -> None:
    # Check for Block activity
    actor = activity.get_actor()
    if outbox_is_blocked(actor.id):
        logger.info(
            f"actor {actor!r} is blocked, dropping the received activity {activity!r}"
        )
        return

    # If the message is coming from a Pleroma relay, we process it as a possible reply for a stream activity
    if (
        actor.has_type(ap.ActivityType.APPLICATION)
        and actor.id.endswith("/relay")
        and activity.has_type(ap.ActivityType.ANNOUNCE)
        and not find_one_activity(
            {
                **by_object_id(activity.get_object_id()),
                **by_type(ap.ActivityType.CREATE),
            }
        )
        and not DB.replies.find_one(by_remote_id(activity.get_object_id()))
    ):
        Tasks.process_reply(activity.get_object_id())
        return

    # Hubzilla sends Update with the same ID as the actor, and it poisons the cache
    if (
        activity.has_type(ap.ActivityType.UPDATE)
        and activity.id == activity.get_object_id()
    ):
        # Start a task to update the cached actor
        Tasks.cache_actor(activity.id)
        return

    # Honk forwards activities in a Read, process them as replies
    if activity.has_type(ap.ActivityType.READ):
        Tasks.process_reply(activity.get_object_id())
        return

    # TODO(tsileo): support ignore from Honk

    # Hubzilla forwards activities in a Create, process them as possible replies
    if activity.has_type(ap.ActivityType.CREATE) and server(activity.id) != server(
        activity.get_object_id()
    ):
        Tasks.process_reply(activity.get_object_id())
        return

    if DB.activities.find_one({"box": Box.INBOX.value, "remote_id": activity.id}):
        # The activity is already in the inbox
        logger.info(f"received duplicate activity {activity!r}, dropping it")
        return

    save(Box.INBOX, activity)
    logger.info(f"spawning tasks for {activity!r}")
    if not activity.has_type([ap.ActivityType.DELETE, ap.ActivityType.UPDATE]):
        Tasks.cache_actor(activity.id)
    Tasks.process_new_activity(activity.id)
    Tasks.finish_post_to_inbox(activity.id)
Example #3
0
def _meta(activity: ap.BaseActivity) -> _NewMeta:
    visibility = ap.get_visibility(activity)
    is_public = False
    if visibility in [ap.Visibility.PUBLIC, ap.Visibility.UNLISTED]:
        is_public = True

    object_id = None
    try:
        object_id = activity.get_object_id()
    except Exception:  # TODO(tsileo): should be ValueError, but replies trigger a KeyError on object
        pass

    object_visibility = None
    if activity.has_type(
        [ap.ActivityType.CREATE, ap.ActivityType.ANNOUNCE, ap.ActivityType.LIKE]
    ):
        object_visibility = ap.get_visibility(activity.get_object()).name

    actor_id = activity.get_actor().id

    return {
        MetaKey.UNDO.value: False,
        MetaKey.DELETED.value: False,
        MetaKey.PUBLIC.value: is_public,
        MetaKey.SERVER.value: urlparse(activity.id).netloc,
        MetaKey.VISIBILITY.value: visibility.name,
        MetaKey.ACTOR_ID.value: actor_id,
        MetaKey.OBJECT_ID.value: object_id,
        MetaKey.OBJECT_VISIBILITY.value: object_visibility,
        MetaKey.POLL_ANSWER.value: False,
        MetaKey.PUBLISHED.value: activity.published if activity.published else now(),
    }
Example #4
0
def post_to_outbox(activity: ap.BaseActivity) -> str:
    if activity.has_type(ap.CREATE_TYPES):
        activity = activity.build_create()

    # Assign create a random ID
    obj_id = binascii.hexlify(os.urandom(8)).decode("utf-8")
    uri = activity_url(obj_id)
    activity._data["id"] = uri
    if activity.has_type(ap.ActivityType.CREATE):
        activity._data["object"]["id"] = urljoin(
            BASE_URL, url_for("outbox_activity", item_id=obj_id))
        activity._data["object"]["url"] = urljoin(
            BASE_URL, url_for("note_by_id", note_id=obj_id))
        activity.reset_object_cache()

    save(Box.OUTBOX, activity)
    Tasks.cache_actor(activity.id)
    Tasks.finish_post_to_outbox(activity.id)
    return activity.id
Example #5
0
def post_to_outbox(activity: ap.BaseActivity) -> str:
    if activity.has_type(ap.CREATE_TYPES):
        activity = activity.build_create()

    # Assign create a random ID
    obj_id = back.random_object_id()
    activity.set_id(back.activity_url(obj_id), obj_id)

    back.save(Box.OUTBOX, activity)
    cache_actor.delay(activity.id)
    finish_post_to_outbox.delay(activity.id)
    return activity.id
Example #6
0
def post_to_outbox(activity: ap.BaseActivity) -> str:
    current_app.logger.debug(f"post_to_outbox {activity}")

    if activity.has_type(ap.CREATE_TYPES):
        activity = activity.build_create()

    backend = ap.get_backend()

    # Assign a random ID
    obj_id = backend.random_object_id()
    activity.set_id(backend.activity_url(obj_id), obj_id)

    backend.save(Box.OUTBOX, activity)

    finish_post_to_outbox.delay(activity.id)
    return activity.id
Example #7
0
    def post_to_outbox(self, activity: ap.BaseActivity) -> None:
        if activity.has_type(ap.CREATE_TYPES):
            activity = activity.build_create()

        self.save(Box.OUTBOX, activity)

        # Assign create a random ID
        obj_id = self.random_object_id()
        activity.set_id(self.activity_url(obj_id), obj_id)

        recipients = activity.recipients()
        logger.info(f"recipients={recipients}")
        activity = ap.clean_activity(activity.to_dict())

        payload = json.dumps(activity)
        for recp in recipients:
            logger.debug(f"posting to {recp}")
            self.post_to_remote_inbox(self.get_actor(), payload, recp)
Example #8
0
    def save(self, box: Box, activity: ap.BaseActivity) -> None:
        """Custom helper for saving an activity to the DB."""
        is_public = True
        if activity.has_type(
                ap.ActivityType.CREATE) and not activity.is_public():
            is_public = False

        DB.activities.insert_one({
            "box": box.value,
            "activity": activity.to_dict(),
            "type": _to_list(activity.type),
            "remote_id": activity.id,
            "meta": {
                "undo": False,
                "deleted": False,
                "public": is_public
            },
        })
Example #9
0
def post_to_outbox(activity: ap.BaseActivity) -> str:
    current_app.logger.debug(f"post_to_outbox {activity!r}")

    if activity.has_type(ap.CREATE_TYPES):
        print("BUILD CREATE POST TO OUTBOX")
        activity = activity.build_create()

    backend = ap.get_backend()

    # Assign a random ID
    obj_id = backend.random_object_id()
    activity.set_id(backend.activity_url(obj_id), obj_id)

    backend.save(Box.OUTBOX, activity)

    # Broadcast only if AP is enabled
    if current_app.config["AP_ENABLED"]:
        finish_post_to_outbox.delay(activity.id)
    return activity.id
Example #10
0
def save(box: Box, activity: ap.BaseActivity) -> None:
    """Custom helper for saving an activity to the DB."""
    visibility = ap.get_visibility(activity)
    is_public = False
    if visibility in [ap.Visibility.PUBLIC, ap.Visibility.UNLISTED]:
        is_public = True

    object_id = None
    try:
        object_id = activity.get_object_id()
    except Exception:  # TODO(tsileo): should be ValueError, but replies trigger a KeyError on object
        pass

    object_visibility = None
    if activity.has_type([
            ap.ActivityType.CREATE, ap.ActivityType.ANNOUNCE,
            ap.ActivityType.LIKE
    ]):
        object_visibility = ap.get_visibility(activity.get_object()).name

    actor_id = activity.get_actor().id

    DB.activities.insert_one({
        "box": box.value,
        "activity": activity.to_dict(),
        "type": _to_list(activity.type),
        "remote_id": activity.id,
        "meta": {
            "undo": False,
            "deleted": False,
            "public": is_public,
            "server": urlparse(activity.id).netloc,
            "visibility": visibility.name,
            "actor_id": actor_id,
            "object_id": object_id,
            "object_visibility": object_visibility,
            "poll_answer": False,
        },
    })
Example #11
0
def post_to_inbox(activity: ap.BaseActivity) -> None:
    # Check for Block activity
    actor = activity.get_actor()
    if outbox_is_blocked(actor.id):
        logger.info(
            f"actor {actor!r} is blocked, dropping the received activity {activity!r}"
        )
        return

    if DB.activities.find_one({
            "box": Box.INBOX.value,
            "remote_id": activity.id
    }):
        # The activity is already in the inbox
        logger.info(f"received duplicate activity {activity!r}, dropping it")
        return

    save(Box.INBOX, activity)
    logger.info(f"spawning tasks for {activity!r}")
    if not activity.has_type(ap.ActivityType.DELETE):
        Tasks.cache_actor(activity.id)
    Tasks.process_new_activity(activity.id)
    Tasks.finish_post_to_inbox(activity.id)