예제 #1
0
def api_follow() -> _Response:
    actor = _user_api_arg("actor")

    q = {
        "box": Box.OUTBOX.value,
        "type": ap.ActivityType.FOLLOW.value,
        "meta.undo": False,
        "activity.object": actor,
    }

    existing = DB.activities.find_one(q)
    if existing:
        return _user_api_response(activity=existing["activity"]["id"])

    follow = ap.Follow(
        actor=MY_PERSON.id,
        object=actor,
        to=[actor],
        cc=[ap.AS_PUBLIC],
        published=now(),
        context=new_context(),
    )
    follow_id = post_to_outbox(follow)

    return _user_api_response(activity=follow_id)
예제 #2
0
def authorize_follow():
    if request.method == "GET":
        return htmlify(
            render_template("authorize_remote_follow.html",
                            profile=request.args.get("profile")))

    csrf.protect()
    actor = get_actor_url(request.form.get("profile"))
    if not actor:
        abort(500)

    q = {
        "box": Box.OUTBOX.value,
        "type": ap.ActivityType.FOLLOW.value,
        "meta.undo": False,
        "activity.object": actor,
    }
    if DB.activities.count(q) > 0:
        return redirect("/following")

    follow = ap.Follow(actor=MY_PERSON.id,
                       object=actor,
                       to=[actor],
                       cc=[ap.AS_PUBLIC],
                       published=now())
    post_to_outbox(follow)

    return redirect("/following")
예제 #3
0
def follow(username_or_id):
    """
    Follow an account.
    ---
    tags:
        - Accounts
    parameters:
        - name: id
          in: query
          type: integer
          required: true
          description: User ID to follow
    responses:
      200:
        description: Returns Relationship
        schema:
            $ref: '#/definitions/Relationship'
    """
    current_user = current_token.user
    if not current_user:
        abort(400)

    user = User.query.filter(User.name == username_or_id,
                             User.local.is_(True)).first()
    if not user:
        try:
            user = User.query.filter(User.flake_id == username_or_id).first()
        except sqlalchemy.exc.DataError:
            abort(404)
    if not user:
        abort(404)

    actor_me = current_user.actor[0]
    actor_them = user.actor[0]

    if user.local:
        actor_me.follow(None, actor_them)
        return jsonify([to_json_relationship(current_user, user)])
    else:
        # We need to initiate a follow request
        # Check if not already following
        rel = Follower.query.filter(
            Follower.actor_id == actor_me.id,
            Follower.target_id == actor_them.id).first()

        if not rel:
            # Initiate a Follow request from actor_me to actor_target
            follow = ap.Follow(actor=actor_me.url, object=actor_them.url)
            post_to_outbox(follow)
            return jsonify(""), 202
        else:
            return jsonify({"error": "already following"}), 409
예제 #4
0
def follow():
    user = request.args.get("user")

    actor_me = current_user.actor[0]

    if user.startswith("https://"):
        actor = Actor.query.filter(Actor.url == user).first()
        if actor:
            local_user = actor.user
        else:
            local_user = None
    else:
        local_user = User.query.filter(User.name == user).first()

    if local_user:
        # Process local follow
        actor_me.follow(None, local_user.actor[0])
        flash(gettext("Follow successful"), "success")
    else:
        # Might be a remote follow

        # 1. Webfinger the user
        try:
            remote_actor_url = get_actor_url(user, debug=current_app.debug)
        except InvalidURLError:
            current_app.logger.exception(f"Invalid webfinger URL: {user}")
            remote_actor_url = None
        # except requests.exceptions.HTTPError:
        #    current_app.logger.exception(f"Invali webfinger URL: {user}")
        #    remote_actor_url = None

        if not remote_actor_url:
            flash(gettext("User not found"), "error")
            return redirect(url_for("bp_users.profile",
                                    name=current_user.name))

        # 2. Check if we have a local user
        actor_target = Actor.query.filter(
            Actor.url == remote_actor_url).first()

        if not actor_target:
            # 2.5 Fetch and save remote actor
            backend = ap.get_backend()
            iri = backend.fetch_iri(remote_actor_url)
            if not iri:
                flash(gettext("User not found"), "error")
                return redirect(url_for("bp_main.home"))
            act = ap.parse_activity(iri)
            actor_target, user_target = create_remote_actor(act)
            db.session.add(user_target)
            db.session.add(actor_target)

        # 2.7 Check if we already have a relation
        rel = Follower.query.filter(
            Follower.actor_id == actor_me.id,
            Follower.target_id == actor_target.id).first()

        if not rel:
            # 3. Initiate a Follow request from actor_me to actor_target
            follow = ap.Follow(actor=actor_me.url, object=actor_target.url)
            post_to_outbox(follow)
            flash(gettext("Follow request have been transmitted"), "success")
        else:
            flash(gettext("You already follow this user", "info"))

    return redirect(url_for("bp_users.profile", name=current_user.name))