コード例 #1
0
def account_get(username_or_id):
    """
    Returns Account
    ---
    tags:
        - Accounts
    responses:
      200:
        description: Returns Account
        schema:
            $ref: '#/definitions/Account'
    """
    if username_or_id.isdigit():
        # an int is DB ID
        user = User.query.filter(User.id == int(username_or_id)).first()
    else:
        # a string is Local User
        user = User.query.filter(User.name == username_or_id,
                                 User.local.is_(True)).first()

    if not user:
        abort(404)
    if len(user.actor) != 1:
        abort(404)

    relationship = False
    if current_token and current_token.user:
        relationship = to_json_relationship(current_token.user, user)
    account = to_json_account(user, relationship)
    return jsonify(account)
コード例 #2
0
def account_get(username_or_id):
    """
    Returns Account
    ---
    tags:
        - Accounts
    responses:
      200:
        description: Returns Account
        schema:
            $ref: '#/definitions/Account'
    """
    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)
    if len(user.actor) != 1:
        abort(404)

    relationship = False
    if current_token and current_token.user:
        relationship = to_json_relationship(current_token.user, user)
    account = to_json_account(user, relationship)
    return jsonify(account)
コード例 #3
0
ファイル: albums.py プロジェクト: AlexSleepy/reel2bits
def get(username_or_id, albumslug):
    """
    Get album details.
    ---
    tags:
        - Albums
    parameters:
        - name: user_id
          in: path
          type: integer
          required: true
          description: User ID
        - name: albumslug
          in: path
          type: string
          required: true
          description: Album slug
    responses:
        200:
            description: Returns album object.
    """
    # Get logged in user from bearer token, or None if not logged in
    if current_token:
        current_user = current_token.user
    else:
        current_user = None

    # Get the associated User from url fetch
    if username_or_id.isdigit():
        album_user = User.query.filter(User.id == username_or_id).first()
    else:
        album_user = User.query.filter(User.name == username_or_id, User.local.is_(True)).first()
    if not album_user:
        return jsonify({"error": "User not found"}), 404

    if current_user and album_user.id == current_user.id:
        # we have a valid token, and album user is token user, can fetch private
        album = Album.query.filter(Album.slug == albumslug, Album.user_id == album_user.id).first()
    else:
        # only fetch public ones
        album = Album.query.filter(
            Album.slug == albumslug, Album.user_id == album_user.id, Album.private.is_(False)
        ).first()

    if not album:
        return jsonify({"error": "not found"}), 404

    if album.private:
        if current_user:
            if album.user_id != current_user.id:
                return jsonify({"error": "forbidden"}), 403
        else:
            return jsonify({"error": "forbidden"}), 403

    relationship = to_json_relationship(current_user, album.user)
    account = to_json_account(album.user, relationship)
    resp = to_json_album(album, account)

    return jsonify(resp)
コード例 #4
0
def following(user_id):
    """
    Accounts followed by the given account.
    ---
    tags:
        - Accounts
    parameters:
        - name: id
          in: path
          type: integer
          required: true
          description: User ID to follow
        - name: count
          in: query
          type: integer
          required: true
          description: count per page
        - name: page
          in: query
          type: integer
          description: page number
    responses:
      200:
        description: Returns paginated array of Account
        schema:
            $ref: '#/definitions/Account'
    """
    user = User.query.filter(User.id == user_id).first()
    if not user:
        abort(404)

    count = int(request.args.get("count", 20))
    page = int(request.args.get("page", 1))

    q = user.actor[0].followings
    q = q.paginate(page=page, per_page=count)

    followings = []
    for t in q.items:
        # Note: the items are Follower(actor, target)
        # Where actor is `user` since we are asking his followers
        # And target = the user following `user`
        relationship = False
        if current_token and current_token.user:
            relationship = to_json_relationship(current_token.user,
                                                t.target.user)
        account = to_json_account(t.target.user, relationship)
        followings.append(account)

    resp = {
        "page": page,
        "page_size": count,
        "totalItems": q.total,
        "items": followings,
        "totalPages": q.pages
    }
    return jsonify(resp)
コード例 #5
0
def albums():
    """
    User albums timeline.
    ---
    tags:
        - Timelines
    parameters:
        - name: count
          in: query
          type: integer
          required: true
          description: count
        - name: page
          in: query
          type: integer
          description: page number
        - name: user
          in: query
          type: string
          description: the user flake id to get albums list
    responses:
        200:
            description: Returns array of Status
    """
    count = int(request.args.get("count", 20))
    page = int(request.args.get("page", 1))
    user = request.args.get("user", None)
    if not user:
        abort(400)

    user = User.query.filter(User.flake_id == user).first()
    if not user:
        return jsonify({"error": "User does not exist"}), 404

    q = Album.query.order_by(Album.created.desc())

    only_public = True
    if current_token and current_token.user:
        if user.id == current_token.user.id:
            only_public = False

    if only_public:
        q = q.filter(Album.user_id == user.id, Album.private.is_(False))
    else:
        q = q.filter(Album.user_id == current_token.user.id)

    q = q.paginate(page=page, per_page=count)

    albums = []
    for t in q.items:
        relationship = False
        if current_token and current_token.user:
            relationship = to_json_relationship(current_token.user, t.user)
        account = to_json_account(t.user, relationship)
        albums.append(to_json_album(t, account))
    resp = {"page": page, "page_size": count, "totalItems": q.total, "items": albums, "totalPages": q.pages}
    return jsonify(resp)
コード例 #6
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
コード例 #7
0
ファイル: timelines.py プロジェクト: swipswaps/reel2bits
def unprocessed():
    """
    User unprocessed tracks timeline.
    ---
    tags:
        - Timelines
    parameters:
        - name: count
          in: query
          type: integer
          required: true
          description: count
        - name: page
          in: query
          type: integer
          description: page number
    responses:
        200:
            description: Returns array of Status
    """
    user = current_token.user
    if not user:
        return jsonify({"error": "Unauthorized"}), 403

    count = int(request.args.get("count", 20))
    page = int(request.args.get("page", 1))

    q = Sound.query.filter(
        Sound.user_id == user.id,
        Sound.transcode_state.in_(
            (Sound.TRANSCODE_WAITING, Sound.TRANSCODE_PROCESSING,
             Sound.TRANSCODE_ERROR)),
    )

    q = q.order_by(Sound.uploaded.desc())

    q = q.paginate(page=page, per_page=count)

    tracks = []
    for t in q.items:
        relationship = to_json_relationship(current_token.user, t.user)
        account = to_json_account(t.user, relationship)
        tracks.append(to_json_track(t, account))
    resp = {
        "page": page,
        "page_size": count,
        "totalItems": q.total,
        "items": tracks,
        "totalPages": q.pages
    }
    return jsonify(resp)
コード例 #8
0
def reorder(username, albumslug):
    """
    Edit album tracks order.
    ---
    tags:
        - Albums
    security:
        - OAuth2:
            - write
    responses:
        200:
            description: Returns a Status with extra reel2bits params.
    """
    current_user = current_token.user
    if not current_user:
        return jsonify({"error": "Unauthorized"}), 403

    # Get the album
    album = Album.query.filter(Album.user_id == current_user.id,
                               Album.slug == albumslug).first()
    if not album:
        return jsonify({"error": "Not found"}), 404

    pos = 0
    for track in request.json:
        dbt = Sound.query.filter(Sound.flake_id == track["id"],
                                 Sound.album_id == album.id).first()
        if not dbt:
            return jsonify({"error": "Not found"}), 404
        dbt.album_order = pos
        pos += 1
    db.session.commit()

    relationship = to_json_relationship(current_user, album.user)
    account = to_json_account(album.user, relationship)
    resp = to_json_album(album, account)

    return jsonify(resp)
コード例 #9
0
def unfollow(user_id):
    """
    Unfollow an account.
    ---
    tags:
        - Accounts
    parameters:
        - name: id
          in: path
          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.id == user_id).first()
    if not user:
        abort(404)

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

    if user.local:
        actor_me.unfollow(actor_them)
        return jsonify([to_json_relationship(current_user, user)])
    else:
        # We need to initiate a follow request
        # FIXME TODO
        abort(501)
コード例 #10
0
def search():
    """
    Search.
    ---
    tags:
        - Global
    parameters:
        - name: q
          in: query
          type: string
          required: true
          description: search string
    responses:
        200:
            description: fixme.
    """
    # Get logged in user from bearer token, or None if not logged in
    if current_token:
        current_user = current_token.user
    else:
        current_user = None

    s = request.args.get("q", None)
    if not s:
        return jsonify({"error": "No search string provided"}), 400

    # This is the old search endpoint and needs to be improved
    # Especially tracks and accounts needs to be returned in the right format, with the data helpers
    # Users should be searched from known Actors or fetched
    # URI should be searched from known activities or fetched
    # FTS, well, FTS needs to be implemented

    results = {"accounts": [], "sounds": [], "mode": None, "from": None}

    if current_user:
        results["from"] = current_user.name

    # Search for sounds
    # TODO: Implement FTS to get sounds search
    sounds = []

    # Search for accounts
    accounts = []
    is_user_at_account = RE_ACCOUNT.match(s)

    if s.startswith("https://"):
        # Try to match the URI from Activities in database
        results["mode"] = "uri"
        users = Actor.query.filter(Actor.meta_deleted.is_(False),
                                   Actor.url == s).all()
    elif is_user_at_account:
        # It matches [email protected], try to match it locally
        results["mode"] = "acct"
        user = is_user_at_account.group("user")
        instance = is_user_at_account.group("instance")
        users = Actor.query.filter(Actor.meta_deleted.is_(False),
                                   Actor.preferred_username == user,
                                   Actor.domain == instance).all()
    else:
        # It's a FTS search
        results["mode"] = "username"
        # Match actor username in database
        if current_user:
            users = (db.session.query(Actor, Follower).outerjoin(
                Follower,
                and_(Actor.id == Follower.target_id,
                     Follower.actor_id == current_user.actor[0].id)).filter(
                         or_(Actor.preferred_username.contains(s),
                             Actor.name.contains(s))).filter(
                                 not_(Actor.id ==
                                      current_user.actor[0].id)).all())
        else:
            users = (db.session.query(Actor).filter(
                or_(Actor.preferred_username.contains(s),
                    Actor.name.contains(s))).all())

    # Handle the found users
    if len(users) > 0:
        for actor in users:
            relationship = False
            if current_user:
                relationship = to_json_relationship(current_user, actor.user)
            accounts.append(to_json_account(actor.user, relationship))

    if len(accounts) <= 0:
        # Do a webfinger
        # TODO FIXME: We should do this only if https:// or user@account submitted
        # And rework it slightly differently since we needs to backend.fetch_iri() for https:// who
        # can match a Sound and not only an Actor
        current_app.logger.debug(f"webfinger for {s}")
        try:
            remote_actor_url = get_actor_url(s, debug=current_app.debug)
            # We need to get the remote Actor
            backend = ap.get_backend()
            iri = backend.fetch_iri(remote_actor_url)
            if iri:
                # We have fetched an unknown Actor
                # Save it in database and return it properly
                current_app.logger.debug(
                    f"got remote actor URL {remote_actor_url}")

                act = ap.parse_activity(iri)

                fetched_actor, fetched_user = create_remote_actor(act)
                db.session.add(fetched_user)
                db.session.add(fetched_actor)
                db.session.commit()

                relationship = False
                if current_user:
                    relationship = to_json_relationship(
                        current_user, fetched_user)
                accounts.append(to_json_account(fetched_user, relationship))
                results["mode"] = "webfinger"

        except (InvalidURLError, ValueError):
            current_app.logger.exception(f"Invalid AP URL: {s}")
            # Then test fetching as a "normal" Activity ?
    # Finally fill the results dict
    results["accounts"] = accounts

    # FIXME: handle exceptions
    if results["mode"] == "uri" and len(sounds) <= 0:
        backend = ap.get_backend()
        iri = backend.fetch_iri(s)
        if iri:
            # FIXME: Is INBOX the right choice here ?
            backend.save(Box.INBOX, iri)
        # Fetch again, but get it from database
        activity = Activity.query.filter(Activity.url == iri).first()
        if not activity:
            current_app.logger.exception("WTF Activity is not saved")
        else:
            from tasks import create_sound_for_remote_track, upload_workflow

            sound_id = create_sound_for_remote_track(activity)
            sound = Sound.query.filter(Sound.id == sound_id).one()
            upload_workflow.delay(sound.id)

            relationship = False
            if current_user:
                relationship = to_json_relationship(current_user, sound.user)
            acct = to_json_account(sound.user, relationship)
            sounds.append(to_json_track(sound, acct))

    return jsonify({"who": s, "results": results})
コード例 #11
0
def relationships():
    """
    Relationship of the user to the given accounts in regards to following, blocking, muting, etc.
    ---
    tags:
        - Accounts
    definitions:
      Relationship:
        type: object
        properties:
            id:
                type: string
                nullable: false
            following:
                type: boolean
                nullable: false
            followed_by:
                type: boolean
                nullable: false
            blocking:
                type: boolean
                nullable: false
            muting:
                type: boolean
                nullable: false
            muting_notifications:
                type: boolean
                nullable: false
            requested:
                type: boolean
                nullable: false
            domain_blocking:
                type: boolean
                nullable: false
            showing_reblogs:
                type: boolean
                nullable: false
            endorsed:
                type: boolean
                nullable: false
    parameters:
        - name: id
          in: query
          type: array
          required: true
          items:
            type: integer
          description: Array of account IDs
    responses:
      200:
        description: Returns array of Relationship
        schema:
            $ref: '#/definitions/Relationship'
    """
    ids = request.args.getlist("id")
    of_user = current_token.user

    rels = []
    for id in ids:
        against_user = User.query.filter(User.id == id).first()
        if not against_user:
            if len(ids) > 1:
                next
            else:
                return jsonify([])
        rels.append(to_json_relationship(of_user, against_user))
    return jsonify(rels)
コード例 #12
0
def user_statuses(user_id):
    """
    User statuses.
    ---
    tags:
        - Timelines
    parameters:
        - name: count
          in: query
          type: integer
          required: true
          description: count per page
        - name: with_muted
          in: query
          type: boolean
          required: true
          description: with muted users
        - name: page
          in: query
          type: integer
          description: page number
    responses:
        200:
            description: Returns array of Status
    """
    # Caveats: only handle public Sounds since we either federate (public) or no
    count = int(request.args.get("count", 20))
    page = int(request.args.get("page", 1))

    # Get associated user
    user = User.query.filter(User.id == user_id).first()
    if not user:
        abort(404)

    q = db.session.query(Activity, Sound).filter(
        Activity.type == "Create",
        Activity.payload[("object", "type")].astext == "Audio")
    q = q.filter(Activity.meta_deleted.is_(False))

    q = q.filter(Activity.payload["to"].astext.contains(
        "https://www.w3.org/ns/activitystreams#Public"))

    q = q.filter(Activity.actor == user.actor[0].id)

    q = q.join(Sound, Sound.activity_id == Activity.id)
    q = q.order_by(Activity.creation_date.desc())

    q = q.paginate(page=page, per_page=count)

    tracks = []
    for t in q.items:
        if t.Sound:
            relationship = False
            if current_token and current_token.user:
                relationship = to_json_relationship(current_token.user,
                                                    t.Sound.user)
            account = to_json_account(t.Sound.user, relationship)
            tracks.append(to_json_track(t.Sound, account))
        else:
            print(t.Activity)
    resp = {
        "page": page,
        "page_size": count,
        "totalItems": q.total,
        "items": tracks,
        "totalPages": q.pages
    }
    return jsonify(resp)
コード例 #13
0
def edit(username, albumslug):
    """
    Edit album.
    ---
    tags:
        - Albums
    security:
        - OAuth2:
            - write
    parameters:
        - name: username
          in: path
          type: string
          required: true
          description: User username
        - name: albumslug
          in: path
          type: string
          required: true
          description: Album slug
    responses:
        200:
            description: Returns a Status with extra reel2bits params.
    """
    current_user = current_token.user
    if not current_user:
        return jsonify({"error": "Unauthorized"}), 403

    # Get the album
    album = Album.query.filter(Album.user_id == current_user.id,
                               Album.slug == albumslug).first()
    if not album:
        return jsonify({"error": "Not found"}), 404

    description = request.json.get("description")
    private = request.json.get("private")
    title = request.json.get("title")
    genre = request.json.get("genre")
    tags = request.json.get("tags")

    if album.private and not private:
        return jsonify(
            {"error": "Cannot change to private: album already federated"})

    if not title:
        return jsonify({"error": "Album title is required"}), 400

    album.title = title
    album.description = description
    album.genre = genre

    # First remove tags which have been removed
    for tag in album.tags:
        if tag.name not in tags:
            album.tags.remove(tag)

    # Then add the new ones if new
    for tag in tags:
        if tag not in [a.name for a in album.tags]:
            dbt = SoundTag.query.filter(SoundTag.name == tag).first()
            if not dbt:
                dbt = SoundTag(name=tag)
                db.session.add(dbt)
            album.tags.append(dbt)

    # Purge orphaned tags
    for otag in SoundTag.query.filter(
            and_(~SoundTag.sounds.any(), ~SoundTag.albums.any())).all():
        db.session.delete(otag)

    db.session.commit()

    relationship = False
    if current_token and current_token.user:
        relationship = to_json_relationship(current_token.user, album.user)
    account = to_json_account(album.user, relationship)
    return jsonify(to_json_album(album, account))
コード例 #14
0
def unfollow(username_or_id):
    """
    Unfollow an account.
    ---
    tags:
        - Accounts
    parameters:
        - name: id
          in: path
          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.unfollow(actor_them)
        return jsonify([to_json_relationship(current_user, user)])
    else:
        # Get the relation of the follow
        follow_relation = Follower.query.filter(
            Follower.actor_id == actor_me.id, Follower.target_id == actor_them.id
        ).first()
        if not follow_relation:
            return jsonify({"error": "follow relation not found"}), 404

        # Fetch the related Activity of the Follow relation
        accept_activity = Activity.query.filter(Activity.url == follow_relation.activity_url).first()
        if not accept_activity:
            current_app.logger.error(f"cannot find accept activity {follow_relation.activity_url}")
            return jsonify({"error": "cannot found the accept activity"}), 500
        # Then the Activity ID of the ACcept will be the object id
        activity = ap.parse_activity(payload=accept_activity.payload)

        # get the final activity (the Follow one)
        follow_activity = Activity.query.filter(Activity.url == activity.get_object_id()).first()
        if not follow_activity:
            current_app.logger.error(f"cannot find follow activity {activity.get_object_id()}")
            return jsonify({"error": "cannot find follow activity"}), 500

        ap_follow_activity = ap.parse_activity(payload=follow_activity.payload)

        # initiate an Undo of the Follow request
        unfollow = ap_follow_activity.build_undo()
        post_to_outbox(unfollow)
        return jsonify(""), 202
コード例 #15
0
ファイル: tracks.py プロジェクト: reel2bits/reel2bits
def show(username_or_id, soundslug):
    """
    Get track details.
    ---
    tags:
        - Tracks
    parameters:
        - name: user_id
          in: path
          type: integer
          required: true
          description: User ID
        - name: soundslug
          in: path
          type: string
          required: true
          description: Track slug
    responses:
        200:
            description: Returns track details.
    """
    # Get logged in user from bearer token, or None if not logged in
    if current_token:
        current_user = current_token.user
    else:
        current_user = None

    # Get the associated User from url fetch
    track_user = User.query.filter(User.name == username_or_id, User.local.is_(True)).first()
    if not track_user:
        try:
            track_user = User.query.filter(User.flake_id == username_or_id).first()
        except sqlalchemy.exc.DataError:
            return jsonify({"error": "User not found"}), 404
    if not track_user:
        return jsonify({"error": "User not found"}), 404

    if current_user and (track_user.id == current_user.id):
        print("user")
        sound = Sound.query.filter(Sound.slug == soundslug, Sound.user_id == track_user.id).first()
    else:
        print("no user")
        sound = Sound.query.filter(
            Sound.slug == soundslug, Sound.user_id == track_user.id, Sound.transcode_state == Sound.TRANSCODE_DONE
        ).first()

    if not sound:
        print("mmmh")
        return jsonify({"error": "not found"}), 404

    if sound.private:
        if current_user:
            if sound.user_id != current_user.id:
                return jsonify({"error": "forbidden"}), 403
        else:
            return jsonify({"error": "forbidden"}), 403

    relationship = False
    if current_token and current_token.user:
        relationship = to_json_relationship(current_token.user, sound.user)
    account = to_json_account(sound.user, relationship)
    return jsonify(to_json_track(sound, account))
コード例 #16
0
ファイル: tracks.py プロジェクト: reel2bits/reel2bits
def edit(username, soundslug):
    """
    Edit track.
    ---
    tags:
        - Tracks
    security:
        - OAuth2:
            - write
    parameters:
        - name: username
          in: path
          type: string
          required: true
          description: User username
        - name: soundslug
          in: path
          type: string
          required: true
          description: Track slug
    responses:
        200:
            description: Returns a Status with extra reel2bits params.
    """
    current_user = current_token.user
    if not current_user:
        return jsonify({"error": "Unauthorized"}), 403

    # Get the track
    sound = Sound.query.filter(Sound.user_id == current_user.id, Sound.slug == soundslug).first()
    if not sound:
        return jsonify({"error": "Not found"}), 404

    album = request.json.get("album")
    description = request.json.get("description")
    licence = request.json.get("licence")
    private = request.json.get("private")
    title = request.json.get("title")
    genre = request.json.get("genre")
    tags = request.json.get("tags")

    if sound.private and not private:
        return jsonify({"error": "Cannot change to private: track already federated"})

    if not title:
        title, _ = splitext(sound.filename_orig)
    else:
        sound.title = title

    sound.description = description
    sound.licence = licence
    sound.genre = genre

    # First remove tags which have been removed
    for tag in sound.tags:
        if tag.name not in tags:
            sound.tags.remove(tag)

    # Then add the new ones if new
    for tag in tags:
        if tag not in [a.name for a in sound.tags]:
            dbt = SoundTag.query.filter(SoundTag.name == tag).first()
            if not dbt:
                dbt = SoundTag(name=tag)
                db.session.add(dbt)
            sound.tags.append(dbt)

    # Purge orphaned tags
    for otag in SoundTag.query.filter(and_(~SoundTag.sounds.any(), ~SoundTag.albums.any())).all():
        db.session.delete(otag)

    # Fetch album, and associate if owner
    if album and (album != "__None"):
        db_album = Album.query.filter(Album.id == album).first()
        if db_album and (db_album.user_id == current_user.id):
            sound.album_id = db_album.id
            if not db_album.sounds:
                sound.album_order = 0
            else:
                sound.album_order = db_album.sounds.count() + 1
    elif album == "__None":
        sound.album_id = None
        sound.album_order = 0

    db.session.commit()

    # trigger a sound update
    send_update_sound(sound)

    relationship = False
    if current_token and current_token.user:
        relationship = to_json_relationship(current_token.user, sound.user)
    account = to_json_account(sound.user, relationship)
    return jsonify(to_json_track(sound, account))
コード例 #17
0
def public():
    """
    Public or TWKN statuses.
    ---
    tags:
        - Timelines
    parameters:
        - name: count
          in: query
          type: integer
          required: true
          description: count
        - name: with_muted
          in: query
          type: boolean
          required: true
          description: with muted users
        - name: local
          in: query
          type: boolean
          description: local only or TWKN
    responses:
        200:
            description: Returns array of Status
    """
    # Caveats: only handle public Sounds since we either federate (public) or no

    paginated = request.args.get("paginated", False)
    count = int(request.args.get("count", 20))
    local_only = request.args.get("local", False)

    q = db.session.query(Activity, Sound).filter(
        Activity.type == "Create", Activity.payload[("object", "type")].astext == "Audio"
    )
    q = q.filter(Activity.meta_deleted.is_(False))

    if local_only:
        q = q.filter(Activity.local.is_(True))

    q = q.filter(Activity.payload["to"].astext.contains("https://www.w3.org/ns/activitystreams#Public"))

    q = q.join(Sound, Sound.activity_id == Activity.id)
    q = q.order_by(Activity.creation_date.desc())

    if paginated:
        # Render timeline as paginated
        page = int(request.args.get("page", 1))

        q = q.paginate(page=page, per_page=count)

        tracks = []
        for t in q.items:
            if t.Sound:
                # TODO(dashie) FIXME can probably be moved out to the q.filter()
                if not t.Sound.transcode_state == Sound.TRANSCODE_DONE:
                    continue
                relationship = False
                if current_token and current_token.user:
                    relationship = to_json_relationship(current_token.user, t.Sound.user)
                account = to_json_account(t.Sound.user, relationship)
                tracks.append(to_json_track(t.Sound, account))
            else:
                print(t.Activity)
        resp = {"page": page, "page_size": count, "totalItems": q.total, "items": tracks, "totalPages": q.pages}
        return jsonify(resp)
    else:
        # mastoapi compatible
        since_id = request.args.get("since_id")

        # since then we want the timeline
        if since_id:
            q = q.filter(Sound.flake_id > since_id)

        # then limit count
        q = q.limit(count)

        tracks = []
        for t in q.all():
            if t.Sound:
                relationship = False
                if current_token and current_token.user:
                    relationship = to_json_relationship(current_token.user, t.Sound.user)
                account = to_json_account(t.Sound.user, relationship)
                tracks.append(to_json_track(t.Sound, account))
            else:
                print(t.Activity)
        return jsonify(tracks)