Merge branch 'master' into develop
This commit is contained in:
commit
c58c74d653
|
@ -1,3 +1,3 @@
|
|||
#!/bin/bash -eux
|
||||
python /app/manage.py collectstatic --noinput
|
||||
gunicorn config.asgi:application -w ${FUNKWHALE_WEB_WORKERS-1} -k uvicorn.workers.UvicornWorker -b 0.0.0.0:5000
|
||||
gunicorn config.asgi:application -w ${FUNKWHALE_WEB_WORKERS-1} -k uvicorn.workers.UvicornWorker -b 0.0.0.0:5000 ${GUNICORN_ARGS-}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import os
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.production")
|
||||
os.environ.setdefault("ASGI_THREADS", "5")
|
||||
|
||||
import django # noqa
|
||||
|
||||
|
|
|
@ -270,7 +270,7 @@ DATABASES = {
|
|||
"default": env.db("DATABASE_URL")
|
||||
}
|
||||
DATABASES["default"]["ATOMIC_REQUESTS"] = True
|
||||
DATABASES["default"]["CONN_MAX_AGE"] = env("DB_CONN_MAX_AGE", default=60 * 60)
|
||||
DATABASES["default"]["CONN_MAX_AGE"] = env("DB_CONN_MAX_AGE", default=60 * 5)
|
||||
|
||||
MIGRATION_MODULES = {
|
||||
# see https://github.com/jazzband/django-oauth-toolkit/issues/634
|
||||
|
|
|
@ -72,7 +72,7 @@ def clean_id3_pictures(apic):
|
|||
|
||||
def get_mp4_tag(f, k):
|
||||
if k == "pictures":
|
||||
return f.get("covr")
|
||||
return f.get("covr", [])
|
||||
raw_value = f.get(k, None)
|
||||
|
||||
if not raw_value:
|
||||
|
|
|
@ -320,6 +320,10 @@ def get_file_path(audio_file):
|
|||
)
|
||||
path = "/music" + audio_file.replace(prefix, "", 1)
|
||||
if path.startswith("http://") or path.startswith("https://"):
|
||||
protocol, remainder = path.split("://", 1)
|
||||
hostname, r_path = remainder.split("/", 1)
|
||||
r_path = urllib.parse.quote(r_path)
|
||||
path = protocol + "://" + hostname + "/" + r_path
|
||||
return (settings.PROTECT_FILES_PATH + "/media/" + path).encode("utf-8")
|
||||
# needed to serve files with % or ? chars
|
||||
path = urllib.parse.quote(path)
|
||||
|
|
|
@ -219,6 +219,11 @@ def test_can_get_metadata_from_m4a_file(field, value):
|
|||
assert data.get(field) == value
|
||||
|
||||
|
||||
def test_get_pictures_m4a_empty():
|
||||
pictures = metadata.get_mp4_tag({}, "pictures")
|
||||
assert metadata.clean_mp4_pictures(pictures) == []
|
||||
|
||||
|
||||
def test_can_get_metadata_from_flac_file_not_crash_if_empty():
|
||||
path = os.path.join(DATA_DIR, "sample.flac")
|
||||
data = metadata.Metadata(path)
|
||||
|
|
|
@ -247,6 +247,18 @@ def test_serve_file_in_place_nginx_encode_url(
|
|||
assert response["X-Accel-Redirect"] == expected
|
||||
|
||||
|
||||
def test_serve_s3_nginx_encode_url(mocker, settings):
|
||||
settings.PROTECT_FILE_PATH = "/_protected/media"
|
||||
settings.REVERSE_PROXY_TYPE = "nginx"
|
||||
audio_file = mocker.Mock(url="https://s3.storage.example/path/to/mp3?aws=signature")
|
||||
|
||||
expected = (
|
||||
b"/_protected/media/https://s3.storage.example/path/to/mp3%3Faws%3Dsignature"
|
||||
)
|
||||
|
||||
assert views.get_file_path(audio_file) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"proxy,serve_path,expected",
|
||||
[
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Added a retry option for failed uploads (#942)
|
|
@ -0,0 +1 @@
|
|||
Fix import crash when importing M4A file with no embedded cover (#946)
|
|
@ -0,0 +1 @@
|
|||
Fixed style glitches in dropdowns
|
|
@ -0,0 +1 @@
|
|||
Reduce the number of simultaneous DB connections under some deployment scenario
|
|
@ -0,0 +1 @@
|
|||
Fix audio serving issues under S3/nginx when signatures are enabled
|
|
@ -47,6 +47,7 @@ Funkwhale packages are available for the following platforms:
|
|||
- `YunoHost 3 <https://yunohost.org/>`_: https://github.com/YunoHost-Apps/funkwhale_ynh (kindly maintained by `@Jibec <https://github.com/Jibec>`_)
|
||||
- ArchLinux (as an AUR package): if you'd rather use a package, check out this alternative installation method on ArchLinux: https://wiki.archlinux.org/index.php/Funkwhale (package and wiki kindly maintained by getzee)
|
||||
- `NixOS <https://github.com/mmai/funkwhale-nixos>`_ (kindly maintained by @mmai)
|
||||
- `Helm chart <https://gitlab.com/ananace/charts/>`_ to install Funkwhale on Kubenertes (kindly maintained by @ananace)
|
||||
|
||||
Project architecture
|
||||
--------------------
|
||||
|
|
|
@ -91,9 +91,20 @@
|
|||
<table class="ui unstackable table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><translate translate-context="Content/Library/Table.Label">Filename</translate></th>
|
||||
<th class="ten wide"><translate translate-context="Content/Library/Table.Label">Filename</translate></th>
|
||||
<th><translate translate-context="Content/*/*/Noun">Size</translate></th>
|
||||
<th><translate translate-context="*/*/*">Status</translate></th>
|
||||
<th><translate translate-context="*/*/*">Actions</translate></th>
|
||||
</tr>
|
||||
<tr v-if="retryableFiles.length > 1">
|
||||
<th class="ten wide"></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th>
|
||||
<button class="ui right floated small basic button" @click.prevent="retry(retryableFiles)">
|
||||
<translate translate-context="Content/Library/Table">Retry failed uploads</translate>
|
||||
</button>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -113,9 +124,20 @@
|
|||
<translate translate-context="Content/Library/Table" key="2">Uploading…</translate>
|
||||
({{ parseInt(file.progress) }}%)
|
||||
</span>
|
||||
<template v-else>
|
||||
<span class="ui label"><translate translate-context="Content/Library/*/Short" key="3">Pending</translate></span>
|
||||
<button class="ui tiny basic red icon button" @click.prevent="$refs.upload.remove(file)"><i class="delete icon"></i></button>
|
||||
<span v-else class="ui label"><translate translate-context="Content/Library/*/Short" key="3">Pending</translate></span>
|
||||
</td>
|
||||
<td>
|
||||
<template v-if="file.error">
|
||||
<button
|
||||
class="ui tiny basic icon right floated button"
|
||||
:title="labels.retry"
|
||||
@click.prevent="retry([file])"
|
||||
v-if="retryableFiles.indexOf(file) > -1">
|
||||
<i class="redo icon"></i>
|
||||
</button>
|
||||
</template>
|
||||
<template v-else-if="!file.success">
|
||||
<button class="ui tiny basic red icon right floated button" @click.prevent="$refs.upload.remove(file)"><i class="delete icon"></i></button>
|
||||
</template>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -251,6 +273,13 @@ export default {
|
|||
self.uploads.objects[event.upload.uuid] = event.upload;
|
||||
self.needsRefresh = true
|
||||
});
|
||||
},
|
||||
retry (files) {
|
||||
files.forEach((file) => {
|
||||
this.$refs.upload.update(file, {error: '', progress: '0.00'})
|
||||
})
|
||||
this.$refs.upload.active = true;
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -274,6 +303,7 @@ export default {
|
|||
server,
|
||||
network,
|
||||
timeout,
|
||||
retry: this.$pgettext('*/*/*/Verb', "Retry"),
|
||||
extension: this.$gettextInterpolate(extension, {
|
||||
extensions: this.supportedExtensions.join(", ")
|
||||
})
|
||||
|
@ -295,6 +325,11 @@ export default {
|
|||
return f.error;
|
||||
}).length;
|
||||
},
|
||||
retryableFiles () {
|
||||
return this.files.filter(f => {
|
||||
return f.error;
|
||||
});
|
||||
},
|
||||
processableFiles() {
|
||||
return (
|
||||
this.uploads.pending +
|
||||
|
@ -342,7 +377,9 @@ export default {
|
|||
uploadedSize () {
|
||||
let uploaded = 0
|
||||
this.files.forEach((f) => {
|
||||
uploaded += f.size * (f.progress / 100)
|
||||
if (!f.error) {
|
||||
uploaded += f.size * (f.progress / 100)
|
||||
}
|
||||
})
|
||||
return uploaded
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue