Esempio n. 1
0
def create_sound_for_remote_track(activity: Activity) -> int:
    sound = Sound()
    sound.title = activity.payload.get("object", {}).get("name", None)
    sound.description = activity.payload.get("object", {}).get("content", None)
    sound.private = False
    sound.transcode_needed = activity.payload.get("object",
                                                  {}).get("transcoded", False)
    if sound.transcode_needed:
        sound.remote_uri = activity.payload.get("object",
                                                {}).get("transcode_url", None)
    else:
        sound.remote_uri = activity.payload.get("object",
                                                {}).get("url",
                                                        {}).get("href", None)
    sound.transcode_state = 0

    # Get user through actor
    sound.user_id = activity.actor.user.id
    sound.activity_id = activity.id
    # custom from AP
    sound.remote_artwork_uri = activity.payload.get("object",
                                                    {}).get("artwork", None)
    sound.genre = activity.payload.get("object", {}).get("genre", None)
    sound.licence = activity.payload.get("object", {}).get("licence",
                                                           {}).get("id", 0)

    if not sound.remote_uri:
        print("Error: track has no remote_uri available")
        return None  # reject if no file available

    # Tags handling. Since it's a new track, no need to do magic tags recalculation.
    tags = [
        t.strip() for t in activity.payload.get("object", {}).get("tags", [])
    ]
    for tag in tags:
        dbt = SoundTag.query.filter(SoundTag.name == tag).first()
        if not dbt:
            dbt = SoundTag(name=tag)
            db.session.add(dbt)
        sound.tags.append(dbt)

    db.session.add(sound)
    db.session.commit()
    return sound.id
Esempio n. 2
0
def upload():
    """
    Create a new track.
    ---
    tags:
        - Tracks
    security:
        - OAuth2:
            - write
    responses:
        200:
            description: Returns the track id and slug.
    """
    errors = {}

    current_user = current_token.user
    if not current_user:
        return jsonify({"error": "Unauthorized"}), 403

    if "file" not in request.files:
        errors["file"] = "No file present"

    if len(errors) > 0:
        return jsonify({"error": errors}), 400

    # Check for user quota already reached
    if current_user.quota_count >= current_user.quota:
        return jsonify({"error": "quota limit reached"}), 507  # Insufficient storage
        # or 509 Bandwitdh Limit Exceeded...

    # Get file, and file size
    file_uploaded = request.files["file"]
    file_uploaded.seek(0, os.SEEK_END)  # ff to the end
    file_size = file_uploaded.tell()
    file_uploaded.seek(0)  # rewind

    if (current_user.quota_count + file_size) > current_user.quota:
        return jsonify({"error": "quota limit reached"}), 507  # Insufficient storage

    # Do the same with the artwork
    if "artwork" in request.files:
        artwork_uploaded = request.files["artwork"]
        artwork_uploaded.seek(0, os.SEEK_END)
        artwork_size = artwork_uploaded.tell()
        artwork_uploaded.seek(0)
        if artwork_size > Reel2bitsDefaults.artwork_size_limit:  # Max size of 2MB
            return jsonify({"error": "artwork too big, 2MB maximum"}), 413  # Request Entity Too Large
    else:
        artwork_uploaded = None

    form = SoundUploadForm()

    if form.validate_on_submit():
        filename_orig = file_uploaded.filename
        filename_hashed = get_hashed_filename(filename_orig)

        # Save the track file
        sounds.save(file_uploaded, folder=current_user.slug, name=filename_hashed)

        rec = Sound()
        rec.filename = filename_hashed
        rec.filename_orig = filename_orig

        # Save the artwork
        if artwork_uploaded:
            artwork_filename = get_hashed_filename(artwork_uploaded.filename)
            artworksounds.save(artwork_uploaded, folder=current_user.slug, name=artwork_filename)
            rec.artwork_filename = artwork_filename

        rec.licence = form.licence.data
        if form.album.data:
            rec.album_id = form.album.data.id
            if not form.album.data.sounds:
                rec.album_order = 0
            else:
                rec.album_order = form.album.data.sounds.count() + 1

        rec.user_id = current_user.id
        if not form.title.data:
            rec.title, _ = splitext(filename_orig)
        else:
            rec.title = form.title.data
        rec.description = form.description.data
        rec.private = form.private.data
        rec.file_size = file_size
        rec.transcode_file_size = 0  # will be filled, if needed in transcoding workflow
        rec.genre = form.genre.data

        # Handle tags
        tags = form.tags.data.split(",")
        # Clean
        tags = [t.strip() for t in tags if t]
        # For each tag get it or create it
        for tag in tags:
            dbt = SoundTag.query.filter(SoundTag.name == tag).first()
            if not dbt:
                dbt = SoundTag(name=tag)
                db.session.add(dbt)
            rec.tags.append(dbt)

        if "flac" in file_uploaded.mimetype or "ogg" in file_uploaded.mimetype or "wav" in file_uploaded.mimetype:
            rec.transcode_state = Sound.TRANSCODE_WAITING
            rec.transcode_needed = True

        db.session.add(rec)

        # recompute user quota
        current_user.quota_count = current_user.quota_count + rec.file_size

        db.session.commit()

        # push the job in queue
        from tasks import upload_workflow

        upload_workflow.delay(rec.id)

        # log
        add_user_log(rec.id, current_user.id, "sounds", "info", "Uploaded {0} -- {1}".format(rec.id, rec.title))

        return jsonify({"id": rec.flake_id, "slug": rec.slug})

    return jsonify({"error": json.dumps(form.errors)}), 400
Esempio n. 3
0
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))
Esempio n. 4
0
def new():
    """
    Create a new album.
    ---
    tags:
        - Albums
    security:
        - OAuth2:
            - write
    responses:
        200:
            description: Returns id and slug.
    """
    current_user = current_token.user
    if not current_user:
        return jsonify({"error": "Unauthorized"}), 403

    # Check artwork file size
    if "artwork" in request.files:
        artwork_uploaded = request.files["artwork"]
        artwork_uploaded.seek(0, os.SEEK_END)
        artwork_size = artwork_uploaded.tell()
        artwork_uploaded.seek(0)
        if artwork_size > Reel2bitsDefaults.artwork_size_limit:
            return jsonify({"error": "artwork too big, 2MB maximum"
                            }), 413  # Request Entity Too Large
    else:
        artwork_uploaded = None

    form = AlbumForm()

    if form.validate_on_submit():
        rec = Album()
        rec.user_id = current_user.id
        rec.title = form.title.data
        rec.private = form.private.data
        rec.description = form.description.data
        rec.genre = form.genre.data

        # Save the artwork
        if artwork_uploaded:
            artwork_filename = get_hashed_filename(artwork_uploaded.filename)
            artworkalbums.save(artwork_uploaded,
                               folder=current_user.slug,
                               name=artwork_filename)
            rec.artwork_filename = artwork_filename

        # Handle tags
        tags = form.tags.data.split(",")
        # Clean
        tags = [t.strip() for t in tags if t]
        # For each tag get it or create it
        for tag in tags:
            dbt = SoundTag.query.filter(SoundTag.name == tag).first()
            if not dbt:
                dbt = SoundTag(name=tag)
                db.session.add(dbt)
            rec.tags.append(dbt)

        db.session.add(rec)
        db.session.commit()

        # log
        add_user_log(rec.id, rec.user_id, "albums", "info",
                     "Created {0} -- {1}".format(rec.id, rec.title))

        return jsonify({"id": rec.flake_id, "slug": rec.slug})

    return jsonify({"error": json.dumps(form.errors)}), 400
Esempio n. 5
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))