コード例 #1
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(),
    }
コード例 #2
0
ファイル: api.py プロジェクト: duoduoffff/microblog.pub
def api_like() -> _Response:
    note = _user_api_get_note()

    to: List[str] = []
    cc: List[str] = []

    note_visibility = ap.get_visibility(note)

    if note_visibility == ap.Visibility.PUBLIC:
        to = [ap.AS_PUBLIC]
        cc = [ID + "/followers", note.get_actor().id]
    elif note_visibility == ap.Visibility.UNLISTED:
        to = [ID + "/followers", note.get_actor().id]
        cc = [ap.AS_PUBLIC]
    else:
        to = [note.get_actor().id]

    like = ap.Like(
        object=note.id,
        actor=MY_PERSON.id,
        to=to,
        cc=cc,
        published=now(),
        context=new_context(note),
    )

    like_id = post_to_outbox(like)

    return _user_api_response(activity=like_id)
コード例 #3
0
def task_cache_actor() -> _Response:
    task = p.parse(flask.request)
    app.logger.info(f"task={task!r}")
    iri = task.payload["iri"]
    try:
        activity = ap.fetch_remote_activity(iri)
        app.logger.info(f"activity={activity!r}")

        # Reload the actor without caching (in case it got upated)
        actor = ap.fetch_remote_activity(activity.get_actor().id,
                                         no_cache=True)

        # Fetch the Open Grah metadata if it's a `Create`
        if activity.has_type(ap.ActivityType.CREATE):
            obj = activity.get_object()
            links = opengraph.links_from_note(obj.to_dict())
            if links:
                Tasks.fetch_og_meta(iri)

                # Send Webmentions only if it's from the outbox, and public
                if (is_from_outbox(obj)
                        and ap.get_visibility(obj) == ap.Visibility.PUBLIC):
                    Tasks.send_webmentions(activity, links)

        if activity.has_type(ap.ActivityType.FOLLOW):
            if actor.id == config.ID:
                # It's a new following, cache the "object" (which is the actor we follow)
                DB.activities.update_one(
                    by_remote_id(iri),
                    upsert({
                        MetaKey.OBJECT:
                        activity.get_object().to_dict(embed=True)
                    }),
                )

        # Cache the actor info
        update_cached_actor(actor)

        app.logger.info(f"actor cached for {iri}")
        if not activity.has_type(
            [ap.ActivityType.CREATE, ap.ActivityType.ANNOUNCE]):
            return ""

        if activity.get_object()._data.get(
                "attachment", []) or activity.get_object().has_type(
                    ap.ActivityType.VIDEO):
            Tasks.cache_attachments(iri)

    except (ActivityGoneError, ActivityNotFoundError):
        DB.activities.update_one({"remote_id": iri},
                                 {"$set": {
                                     "meta.deleted": True
                                 }})
        app.logger.exception(
            f"flagging activity {iri} as deleted, no actor caching")
    except Exception as err:
        app.logger.exception(f"failed to cache actor for {iri}")
        raise TaskError() from err

    return ""
コード例 #4
0
ファイル: admin.py プロジェクト: sorpaas/microblogpub
def admin_new() -> _Response:
    reply_id = None
    content = ""
    thread: List[Any] = []
    print(request.args)
    default_visibility = None  # ap.Visibility.PUBLIC
    if request.args.get("reply"):
        data = DB.activities.find_one(
            {"activity.object.id": request.args.get("reply")})
        if data:
            reply = ap.parse_activity(data["activity"])
        else:
            obj = ap.get_backend().fetch_iri(request.args.get("reply"))
            data = dict(meta=_meta(ap.parse_activity(obj)),
                        activity=dict(object=obj))
            data["_id"] = obj["id"]
            data["remote_id"] = obj["id"]
            reply = ap.parse_activity(data["activity"]["object"])
        # Fetch the post visibility, in case it's follower only
        default_visibility = ap.get_visibility(reply)
        # If it's public, we default the reply to unlisted
        if default_visibility == ap.Visibility.PUBLIC:
            default_visibility = ap.Visibility.UNLISTED

        reply_id = reply.id
        if reply.ACTIVITY_TYPE == ap.ActivityType.CREATE:
            reply_id = reply.get_object().id

        actor = reply.get_actor()
        domain = urlparse(actor.id).netloc
        # FIXME(tsileo): if reply of reply, fetch all participants
        content = f"@{actor.preferredUsername}@{domain} "
        if reply.has_type(ap.ActivityType.CREATE):
            reply = reply.get_object()
        for mention in reply.get_mentions():
            if mention.href in [actor.id, ID]:
                continue
            m = ap.fetch_remote_activity(mention.href)
            if m.has_type(ap.ACTOR_TYPES):
                d = urlparse(m.id).netloc
                content += f"@{m.preferredUsername}@{d} "

        thread = _build_thread(data)

    return htmlify(
        render_template(
            "new.html",
            reply=reply_id,
            content=content,
            thread=thread,
            default_visibility=default_visibility,
            visibility=ap.Visibility,
            emojis=config.EMOJIS.split(" "),
            custom_emojis=sorted(
                [ap.Emoji(**dat) for name, dat in EMOJIS_BY_NAME.items()],
                key=lambda e: e.name,
            ),
        ))
コード例 #5
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,
        },
    })
コード例 #6
0
ファイル: api.py プロジェクト: duoduoffff/microblog.pub
def api_boost() -> _Response:
    note = _user_api_get_note()

    # Ensures the note visibility allow us to build an Announce (in respect to the post visibility)
    if ap.get_visibility(note) not in [ap.Visibility.PUBLIC, ap.Visibility.UNLISTED]:
        abort(400)

    announce = ap.Announce(
        actor=MY_PERSON.id,
        object=note.id,
        to=[MY_PERSON.followers, note.attributedTo],
        cc=[ap.AS_PUBLIC],
        published=now(),
        context=new_context(note),
    )
    announce_id = post_to_outbox(announce)

    return _user_api_response(activity=announce_id)
コード例 #7
0
ファイル: activitypub.py プロジェクト: sorpaas/microblogpub
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,
        },
    })