Beispiel #1
0
def _is_local_reply(activity: ap.BaseActivity) -> bool:
    for dest in _to_list(activity.to or []):
        if dest.startswith(config.BASE_URL):
            return True

    for dest in _to_list(activity.cc or []):
        if dest.startswith(config.BASE_URL):
            return True

    return False
Beispiel #2
0
def _is_local_reply(create: ap.Create) -> bool:
    for dest in _to_list(create.to or []):
        if dest.startswith(BASE_URL):
            return True

    for dest in _to_list(create.cc or []):
        if dest.startswith(BASE_URL):
            return True

    return False
Beispiel #3
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,
        }
    )
Beispiel #4
0
 def save(self, box: Box, activity: ap.BaseActivity) -> None:
     """Custom helper for saving an activity to the DB."""
     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},
         }
     )
Beispiel #5
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
            },
        })
Beispiel #6
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,
        },
    })
Beispiel #7
0
def save_reply(activity: ap.BaseActivity, meta: Dict[str, Any] = {}) -> None:
    visibility = ap.get_visibility(activity)
    is_public = False
    if visibility in [ap.Visibility.PUBLIC, ap.Visibility.UNLISTED]:
        is_public = True

    published = activity.published if activity.published else now()
    DB.replies.insert_one({
        "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": activity.get_actor().id,
            MetaKey.PUBLISHED.value: published,
            **meta,
        },
    })
Beispiel #8
0
    def _handle_replies(self, as_actor: ap.Person, create: ap.Create) -> None:
        """Go up to the root reply, store unknown replies in the `threads` DB and set the "meta.thread_root_parent"
        key to make it easy to query a whole thread."""
        in_reply_to = create.get_object().get_in_reply_to()
        if not in_reply_to:
            return

        new_threads = []
        root_reply = in_reply_to
        reply = ap.fetch_remote_activity(root_reply)

        # Ensure the this is a local reply, of a question, with a direct "to" addressing
        if (reply.id.startswith(BASE_URL)
                and reply.has_type(ap.ActivityType.QUESTION.value)
                and _to_list(create.get_object().to)[0].startswith(BASE_URL)
                and not create.is_public()):
            return self._process_question_reply(create, reply)
        elif (create.id.startswith(BASE_URL)
              and reply.has_type(ap.ActivityType.QUESTION.value)
              and not create.is_public()):
            # Keep track of our own votes
            DB.activities.update_one(
                {
                    "activity.object.id": reply.id,
                    "box": "inbox"
                },
                {"$set": {
                    "meta.voted_for": create.get_object().name
                }},
            )
            return None

        creply = DB.activities.find_one_and_update(
            {"activity.object.id": in_reply_to},
            {"$inc": {
                "meta.count_reply": 1,
                "meta.count_direct_reply": 1
            }},
        )
        if not creply:
            # It means the activity is not in the inbox, and not in the outbox, we want to save it
            self.save(Box.REPLIES, reply)
            new_threads.append(reply.id)
            # TODO(tsileo): parses the replies collection and import the replies?

        while reply is not None:
            in_reply_to = reply.get_in_reply_to()
            if not in_reply_to:
                break
            root_reply = in_reply_to
            reply = ap.fetch_remote_activity(root_reply)
            q = {"activity.object.id": root_reply}
            if not DB.activities.count(q):
                self.save(Box.REPLIES, reply)
                new_threads.append(reply.id)

        DB.activities.update_one(
            {"remote_id": create.id},
            {"$set": {
                "meta.thread_root_parent": root_reply
            }})
        DB.activities.update(
            {
                "box": Box.REPLIES.value,
                "remote_id": {
                    "$in": new_threads
                }
            },
            {"$set": {
                "meta.thread_root_parent": root_reply
            }},
        )
def has_type(doc, _types):
    for _type in _to_list(_types):
        if _type in _to_list(doc["type"]):
            return True
    return False