See #1100: clean compat and XXX in the code

environments/review-docs-devel-1399dq/deployments/6607
Agate 2020-08-03 15:47:14 +02:00
rodzic b7f1c02c6f
commit e271851f67
67 zmienionych plików z 203 dodań i 328 usunięć

Wyświetl plik

@ -74,11 +74,6 @@ v1_patterns += [
include(("funkwhale_api.history.urls", "history"), namespace="history"),
),
url(r"^", include(("funkwhale_api.users.api_urls", "users"), namespace="users"),),
# XXX: 1.0: remove this
url(
r"^users/",
include(("funkwhale_api.users.api_urls", "users"), namespace="users-nested"),
),
url(
r"^oauth/",
include(("funkwhale_api.users.oauth.urls", "oauth"), namespace="oauth"),

Wyświetl plik

@ -2,18 +2,13 @@ from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.conf.urls import url
from funkwhale_api.common.auth import TokenAuthMiddleware
from funkwhale_api.instance import consumers
application = ProtocolTypeRouter(
{
# Empty for now (http->django views is added by default)
"websocket": AuthMiddlewareStack(
TokenAuthMiddleware(
URLRouter(
[url("^api/v1/activity$", consumers.InstanceActivityConsumer)]
)
)
URLRouter([url("^api/v1/activity$", consumers.InstanceActivityConsumer)])
)
}
)

Wyświetl plik

@ -169,17 +169,7 @@ os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = env.bool(
"DJANGO_ALLOW_ASYNC_UNSAFE", default="true"
)
# XXX: deprecated, see #186
FEDERATION_ENABLED = env.bool("FEDERATION_ENABLED", default=True)
FEDERATION_HOSTNAME = env("FEDERATION_HOSTNAME", default=FUNKWHALE_HOSTNAME).lower()
# XXX: deprecated, see #186
FEDERATION_COLLECTION_PAGE_SIZE = env.int("FEDERATION_COLLECTION_PAGE_SIZE", default=50)
# XXX: deprecated, see #186
FEDERATION_MUSIC_NEEDS_APPROVAL = env.bool(
"FEDERATION_MUSIC_NEEDS_APPROVAL", default=True
)
# XXX: deprecated, see #186
FEDERATION_ACTOR_FETCH_DELAY = env.int("FEDERATION_ACTOR_FETCH_DELAY", default=60 * 12)
FEDERATION_SERVICE_ACTOR_USERNAME = env(
"FEDERATION_SERVICE_ACTOR_USERNAME", default="service"
)
@ -1129,11 +1119,6 @@ Exemples:
CSRF_USE_SESSIONS = True
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
# Playlist settings
# XXX: deprecated, see #186
PLAYLISTS_MAX_TRACKS = env.int("PLAYLISTS_MAX_TRACKS", default=250)
ACCOUNT_USERNAME_BLACKLIST = [
"funkwhale",
"library",
@ -1170,8 +1155,6 @@ EXTERNAL_REQUESTS_TIMEOUT = env.int("EXTERNAL_REQUESTS_TIMEOUT", default=10)
"""
Default timeout for external requests.
"""
# XXX: deprecated, see #186
API_AUTHENTICATION_REQUIRED = env.bool("API_AUTHENTICATION_REQUIRED", True)
MUSIC_DIRECTORY_PATH = env("MUSIC_DIRECTORY_PATH", default=None)
"""
@ -1285,8 +1268,6 @@ FUNKWHALE_SUPPORT_MESSAGE_DELAY = env.int("FUNKWHALE_SUPPORT_MESSAGE_DELAY", def
"""
Delay in days after signup before we show the "support Funkwhale" message
"""
# XXX Stable release: remove
USE_FULL_TEXT_SEARCH = env.bool("USE_FULL_TEXT_SEARCH", default=True)
MIN_DELAY_BETWEEN_DOWNLOADS_COUNT = env.int(
"MIN_DELAY_BETWEEN_DOWNLOADS_COUNT", default=60 * 60 * 6

Wyświetl plik

@ -1,19 +1,15 @@
from dynamic_preferences import types
from dynamic_preferences.registries import global_preferences_registry
from funkwhale_api.common import preferences
common = types.Section("common")
@global_preferences_registry.register
class APIAutenticationRequired(
preferences.DefaultFromSettingMixin, types.BooleanPreference
):
class APIAutenticationRequired(types.BooleanPreference):
section = common
name = "api_authentication_required"
verbose_name = "API Requires authentication"
setting = "API_AUTHENTICATION_REQUIRED"
default = True
help_text = (
"If disabled, anonymous users will be able to query the API"
"and access music data (as well as other data exposed in the API "

Wyświetl plik

@ -1,6 +1,5 @@
import django_filters
from django import forms
from django.conf import settings
from django.core.serializers.json import DjangoJSONEncoder
from django.db import models
@ -40,7 +39,7 @@ class SearchFilter(django_filters.CharFilter):
def filter(self, qs, value):
if not value:
return qs
if settings.USE_FULL_TEXT_SEARCH and self.fts_search_fields:
if self.fts_search_fields:
query = search.get_fts_query(
value, self.fts_search_fields, model=self.parent.Meta.model
)

Wyświetl plik

@ -113,7 +113,7 @@ def get_spa_html(spa_url):
def get_spa_file(spa_url, name):
if spa_url.startswith("/"):
# XXX: spa_url is an absolute path to index.html, on the local disk.
# spa_url is an absolute path to index.html, on the local disk.
# However, we may want to access manifest.json or other files as well, so we
# strip the filename
path = os.path.join(os.path.dirname(spa_url), name)

Wyświetl plik

@ -299,20 +299,6 @@ class AttachmentSerializer(serializers.Serializer):
urls["medium_square_crop"] = o.download_url_medium_square_crop
return urls
def to_representation(self, o):
repr = super().to_representation(o)
# XXX: BACKWARD COMPATIBILITY
# having the attachment urls in a nested JSON obj is better,
# but we can't do this without breaking clients
# So we extract the urls and include these in the parent payload
repr.update({k: v for k, v in repr["urls"].items() if k != "source"})
# also, our legacy images had lots of variations (400x400, 200x200, 50x50)
# but we removed some of these, so we emulate these by hand (by redirecting)
# to actual, existing attachment variations
repr["square_crop"] = repr["medium_square_crop"]
repr["small_square_crop"] = repr["medium_square_crop"]
return repr
def create(self, validated_data):
return models.Attachment.objects.create(
file=validated_data["file"], actor=validated_data["actor"]

Wyświetl plik

@ -13,8 +13,7 @@ class TrackFavoriteFilter(moderation_filters.HiddenContentFilterSet):
class Meta:
model = models.TrackFavorite
# XXX: 1.0 remove the user filter, we have scope=me now
fields = ["user"]
fields = []
hidden_content_fields_mapping = moderation_filters.USER_FILTER_CONFIG[
"TRACK_FAVORITE"
]

Wyświetl plik

@ -1,8 +1,6 @@
from dynamic_preferences import types
from dynamic_preferences.registries import global_preferences_registry
from funkwhale_api.common import preferences
federation = types.Section("federation")
@ -22,10 +20,10 @@ class MusicCacheDuration(types.IntPreference):
@global_preferences_registry.register
class Enabled(preferences.DefaultFromSettingMixin, types.BooleanPreference):
class Enabled(types.BooleanPreference):
section = federation
name = "enabled"
setting = "FEDERATION_ENABLED"
default = True
verbose_name = "Federation enabled"
help_text = (
"Use this setting to enable or disable federation logic and API" " globally."
@ -33,20 +31,20 @@ class Enabled(preferences.DefaultFromSettingMixin, types.BooleanPreference):
@global_preferences_registry.register
class CollectionPageSize(preferences.DefaultFromSettingMixin, types.IntPreference):
class CollectionPageSize(types.IntPreference):
section = federation
name = "collection_page_size"
setting = "FEDERATION_COLLECTION_PAGE_SIZE"
default = 50
verbose_name = "Federation collection page size"
help_text = "How many items to display in ActivityPub collections."
field_kwargs = {"required": False}
@global_preferences_registry.register
class ActorFetchDelay(preferences.DefaultFromSettingMixin, types.IntPreference):
class ActorFetchDelay(types.IntPreference):
section = federation
name = "actor_fetch_delay"
setting = "FEDERATION_ACTOR_FETCH_DELAY"
default = 60 * 12
verbose_name = "Federation actor fetch delay"
help_text = (
"How many minutes to wait before refetching actors on "

Wyświetl plik

@ -938,8 +938,6 @@ class PaginatedCollectionSerializer(jsonld.JsonLdSerializer):
last = common_utils.set_query_parameter(conf["id"], page=paginator.num_pages)
d = {
"id": conf["id"],
# XXX Stable release: remove the obsolete actor field
"actor": conf["actor"].fid,
"attributedTo": conf["actor"].fid,
"totalItems": paginator.count,
"type": conf.get("type", "Collection"),
@ -1004,9 +1002,8 @@ class LibrarySerializer(PaginatedCollectionSerializer):
"name": library.name,
"summary": library.description,
"page_size": 100,
# XXX Stable release: remove the obsolete actor field
"actor": library.actor,
"attributedTo": library.actor,
"actor": library.actor,
"items": library.uploads.for_federation(),
"type": "Library",
}
@ -1108,8 +1105,6 @@ class CollectionPageSerializer(jsonld.JsonLdSerializer):
],
}
if conf["actor"]:
# XXX Stable release: remove the obsolete actor field
d["actor"] = conf["actor"].fid
d["attributedTo"] = conf["actor"].fid
if page.has_previous():
@ -1297,8 +1292,7 @@ class AlbumSerializer(MusicEntitySerializer):
child=MultipleSerializer(allowed=[BasicActorSerializer, ArtistSerializer]),
min_length=1,
)
# XXX: 1.0 rename to image
cover = ImageSerializer(
image = ImageSerializer(
allowed_mimetypes=["image/*"],
allow_null=True,
required=False,
@ -1306,7 +1300,7 @@ class AlbumSerializer(MusicEntitySerializer):
)
updateable_fields = [
("name", "title"),
("cover", "attachment_cover"),
("image", "attachment_cover"),
("musicbrainzId", "mbid"),
("attributedTo", "attributed_to"),
("released", "release_date"),
@ -1320,7 +1314,7 @@ class AlbumSerializer(MusicEntitySerializer):
{
"released": jsonld.first_val(contexts.FW.released),
"artists": jsonld.first_attr(contexts.FW.artists, "@list"),
"cover": jsonld.first_obj(contexts.FW.cover),
"image": jsonld.first_obj(contexts.AS.image),
},
)
@ -1354,11 +1348,6 @@ class AlbumSerializer(MusicEntitySerializer):
]
include_content(d, instance.description)
if instance.attachment_cover:
d["cover"] = {
"type": "Link",
"href": instance.attachment_cover.download_url_original,
"mediaType": instance.attachment_cover.mimetype or "image/jpeg",
}
include_image(d, instance.attachment_cover)
if self.context.get("include_ap_context", self.parent is None):

Wyświetl plik

@ -218,7 +218,6 @@ def should_redirect_ap_to_html(accept_header, default=True):
"text/html",
]
no_redirect_headers = [
"*/*", # XXX backward compat with older Funkwhale instances that don't send the Accept header
"application/json",
"application/activity+json",
"application/ld+json",

Wyświetl plik

@ -0,0 +1,22 @@
# Generated by Django 3.0.8 on 2020-08-03 12:22
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('moderation', '0005_auto_20200317_0820'),
]
operations = [
migrations.RemoveField(
model_name='userrequest',
name='url',
),
migrations.AlterField(
model_name='userrequest',
name='status',
field=models.CharField(choices=[('pending', 'Pending'), ('refused', 'Refused'), ('approved', 'Approved')], default='pending', max_length=40),
),
]

Wyświetl plik

@ -20,7 +20,6 @@ from django.db.models.signals import post_save, pre_save
from django.dispatch import receiver
from django.urls import reverse
from django.utils import timezone
from versatileimagefield.fields import VersatileImageField
from funkwhale_api import musicbrainz
from funkwhale_api.common import fields
@ -325,10 +324,6 @@ class Album(APIModelMixin):
artist = models.ForeignKey(Artist, related_name="albums", on_delete=models.CASCADE)
release_date = models.DateField(null=True, blank=True, db_index=True)
release_group_id = models.UUIDField(null=True, blank=True)
# XXX: 1.0 clean this uneeded field in favor of attachment_cover
cover = VersatileImageField(
upload_to="albums/covers/%Y/%m/%d", null=True, blank=True
)
attachment_cover = models.ForeignKey(
"common.Attachment",
null=True,

Wyświetl plik

@ -32,10 +32,7 @@ COVER_WRITE_FIELD = common_serializers.RelatedField(
from funkwhale_api.audio import serializers as audio_serializers # NOQA
class CoverField(
common_serializers.NullToEmptDict, common_serializers.AttachmentSerializer
):
# XXX: BACKWARD COMPATIBILITY
class CoverField(common_serializers.AttachmentSerializer):
pass

Wyświetl plik

@ -364,7 +364,7 @@ def federation_audio_track_to_metadata(payload, references):
"mbid": str(payload["album"]["musicbrainzId"])
if payload["album"].get("musicbrainzId")
else None,
"cover_data": get_cover(payload["album"], "cover"),
"cover_data": get_cover(payload["album"], "image"),
"release_date": payload["album"].get("released"),
"tags": [t["name"] for t in payload["album"].get("tags", []) or []],
"artists": [
@ -896,8 +896,6 @@ UPDATE_CONFIG = {
@transaction.atomic
def update_track_metadata(audio_metadata, track):
# XXX: implement this to support updating metadata when an imported files
# is updated by an outside tool (e.g beets).
serializer = metadata.TrackMetadataSerializer(data=audio_metadata)
serializer.is_valid(raise_exception=True)
new_data = serializer.validated_data

Wyświetl plik

@ -797,20 +797,11 @@ class Search(views.APIView):
return Response(results, status=200)
def get_tracks(self, query):
search_fields = [
"mbid",
"title__unaccent",
"album__title__unaccent",
"artist__name__unaccent",
]
if settings.USE_FULL_TEXT_SEARCH:
query_obj = utils.get_fts_query(
query,
fts_fields=["body_text", "album__body_text", "artist__body_text"],
model=models.Track,
)
else:
query_obj = utils.get_query(query, search_fields)
query_obj = utils.get_fts_query(
query,
fts_fields=["body_text", "album__body_text", "artist__body_text"],
model=models.Track,
)
qs = (
models.Track.objects.all()
.filter(query_obj)
@ -828,13 +819,9 @@ class Search(views.APIView):
return common_utils.order_for_search(qs, "title")[: self.max_results]
def get_albums(self, query):
search_fields = ["mbid", "title__unaccent", "artist__name__unaccent"]
if settings.USE_FULL_TEXT_SEARCH:
query_obj = utils.get_fts_query(
query, fts_fields=["body_text", "artist__body_text"], model=models.Album
)
else:
query_obj = utils.get_query(query, search_fields)
query_obj = utils.get_fts_query(
query, fts_fields=["body_text", "artist__body_text"], model=models.Album
)
qs = (
models.Album.objects.all()
.filter(query_obj)
@ -844,11 +831,7 @@ class Search(views.APIView):
return common_utils.order_for_search(qs, "title")[: self.max_results]
def get_artists(self, query):
search_fields = ["mbid", "name__unaccent"]
if settings.USE_FULL_TEXT_SEARCH:
query_obj = utils.get_fts_query(query, model=models.Artist)
else:
query_obj = utils.get_query(query, search_fields)
query_obj = utils.get_fts_query(query, model=models.Artist)
qs = (
models.Artist.objects.all()
.filter(query_obj)

Wyświetl plik

@ -1,16 +1,14 @@
from dynamic_preferences import types
from dynamic_preferences.registries import global_preferences_registry
from funkwhale_api.common import preferences
playlists = types.Section("playlists")
@global_preferences_registry.register
class MaxTracks(preferences.DefaultFromSettingMixin, types.IntegerPreference):
class MaxTracks(types.IntegerPreference):
show_in_api = True
section = playlists
name = "max_tracks"
default = 250
verbose_name = "Max tracks per playlist"
setting = "PLAYLISTS_MAX_TRACKS"
field_kwargs = {"required": False}

Wyświetl plik

@ -31,7 +31,6 @@ class PlaylistFilter(filters.FilterSet):
class Meta:
model = models.Playlist
fields = {
"user": ["exact"],
"name": ["exact", "icontains"],
}

Wyświetl plik

@ -227,7 +227,6 @@ class PlaylistTrack(models.Model):
class Meta:
ordering = ("-playlist", "index")
unique_together = ("playlist", "index")
def delete(self, *args, **kwargs):
playlist = self.playlist

Wyświetl plik

@ -0,0 +1,20 @@
# Generated by Django 3.0.8 on 2020-08-03 12:22
import django.contrib.postgres.fields.jsonb
import django.core.serializers.json
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('radios', '0004_auto_20180107_1813'),
]
operations = [
migrations.AlterField(
model_name='radio',
name='config',
field=django.contrib.postgres.fields.jsonb.JSONField(encoder=django.core.serializers.json.DjangoJSONEncoder),
),
]

Wyświetl plik

@ -0,0 +1,25 @@
# Generated by Django 3.0.8 on 2020-08-03 12:22
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('tags', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='taggeditem',
name='content_type',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tagged_items', to='contenttypes.ContentType', verbose_name='Content type'),
),
migrations.AlterField(
model_name='taggeditem',
name='tag',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tagged_items', to='tags.Tag'),
),
]

Wyświetl plik

@ -1,30 +0,0 @@
import pytest
from rest_framework_jwt.settings import api_settings
from funkwhale_api.common.auth import TokenAuthMiddleware
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
@pytest.mark.parametrize("query_string", [b"token=wrong", b""])
def test_header_anonymous(query_string, factories):
def callback(scope):
assert scope["user"].is_anonymous
scope = {"query_string": query_string}
consumer = TokenAuthMiddleware(callback)
consumer(scope)
def test_header_correct_token(factories):
user = factories["users.User"]()
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
def callback(scope):
assert scope["user"] == user
scope = {"query_string": "token={}".format(token).encode("utf-8")}
consumer = TokenAuthMiddleware(callback)
consumer(scope)

Wyświetl plik

@ -17,7 +17,7 @@ from django import urls
"/api/v1/auth/registration/account-confirm-email/key",
"/api/v1/history/listenings",
"/api/v1/radios/sessions",
"/api/v1/users/users/me",
"/api/v1/users/me",
"/api/v1/federation/follows/library",
"/api/v1/manage/accounts",
"/api/v1/oauth/apps",

Wyświetl plik

@ -201,15 +201,6 @@ def test_attachment_serializer_existing_file(factories, to_api_date):
attachment.file.crop["200x200"].url
),
},
# XXX: BACKWARD COMPATIBILITY
"original": federation_utils.full_url(attachment.file.url),
"medium_square_crop": federation_utils.full_url(
attachment.file.crop["200x200"].url
),
"small_square_crop": federation_utils.full_url(
attachment.file.crop["200x200"].url
),
"square_crop": federation_utils.full_url(attachment.file.crop["200x200"].url),
}
serializer = serializers.AttachmentSerializer(attachment)
@ -237,17 +228,6 @@ def test_attachment_serializer_remote_file(factories, to_api_date):
proxy_url + "?next=medium_square_crop"
),
},
# XXX: BACKWARD COMPATIBILITY
"original": federation_utils.full_url(proxy_url + "?next=original"),
"medium_square_crop": federation_utils.full_url(
proxy_url + "?next=medium_square_crop"
),
"square_crop": federation_utils.full_url(
proxy_url + "?next=medium_square_crop"
),
"small_square_crop": federation_utils.full_url(
proxy_url + "?next=medium_square_crop"
),
}
serializer = serializers.AttachmentSerializer(attachment)

Wyświetl plik

@ -20,10 +20,11 @@ def test_user_can_get_his_favorites(
api_request, factories, logged_in_api_client, client
):
request = api_request.get("/")
logged_in_api_client.user.create_actor()
favorite = factories["favorites.TrackFavorite"](user=logged_in_api_client.user)
factories["favorites.TrackFavorite"]()
url = reverse("api:v1:favorites:tracks-list")
response = logged_in_api_client.get(url, {"user": logged_in_api_client.user.pk})
response = logged_in_api_client.get(url, {"scope": "me"})
expected = [
serializers.UserTrackFavoriteSerializer(
favorite, context={"request": request}

Wyświetl plik

@ -388,7 +388,6 @@ def test_paginated_collection_serializer(factories):
"@context": jsonld.get_default_context(),
"type": "Collection",
"id": conf["id"],
"actor": actor.fid,
"attributedTo": actor.fid,
"totalItems": len(uploads),
"current": conf["id"] + "?page=1",
@ -486,7 +485,6 @@ def test_collection_page_serializer(factories):
"@context": jsonld.get_default_context(),
"type": "CollectionPage",
"id": conf["id"] + "?page=2",
"actor": actor.fid,
"attributedTo": actor.fid,
"totalItems": len(uploads),
"partOf": conf["id"],
@ -521,7 +519,6 @@ def test_music_library_serializer_to_ap(factories):
"id": library.fid,
"name": library.name,
"summary": library.description,
"actor": library.actor.fid,
"attributedTo": library.actor.fid,
"totalItems": 0,
"current": library.fid + "?page=1",
@ -764,11 +761,6 @@ def test_activity_pub_album_serializer_to_ap(factories):
"type": "Album",
"id": album.fid,
"name": album.title,
"cover": {
"type": "Link",
"mediaType": "image/jpeg",
"href": utils.full_url(album.attachment_cover.file.url),
},
"image": {
"type": "Image",
"mediaType": "image/jpeg",
@ -815,7 +807,7 @@ def test_activity_pub_album_serializer_from_ap_create(factories, faker, now):
"type": "Album",
"id": "https://album.example",
"name": faker.sentence(),
"cover": {"type": "Link", "mediaType": "image/jpeg", "href": faker.url()},
"image": {"type": "Link", "mediaType": "image/jpeg", "href": faker.url()},
"musicbrainzId": faker.uuid4(),
"published": now.isoformat(),
"released": released.isoformat(),
@ -839,8 +831,8 @@ def test_activity_pub_album_serializer_from_ap_create(factories, faker, now):
assert str(album.mbid) == payload["musicbrainzId"]
assert album.release_date == released
assert album.artist == artist
assert album.attachment_cover.url == payload["cover"]["href"]
assert album.attachment_cover.mimetype == payload["cover"]["mediaType"]
assert album.attachment_cover.url == payload["image"]["href"]
assert album.attachment_cover.mimetype == payload["image"]["mediaType"]
assert sorted(album.tagged_items.values_list("tag__name", flat=True)) == [
"Punk",
"Rock",
@ -879,7 +871,7 @@ def test_activity_pub_album_serializer_from_ap_update(factories, faker):
"type": "Album",
"id": album.fid,
"name": faker.sentence(),
"cover": {"type": "Link", "mediaType": "image/jpeg", "href": faker.url()},
"image": {"type": "Link", "mediaType": "image/jpeg", "href": faker.url()},
"musicbrainzId": faker.uuid4(),
"published": album.creation_date.isoformat(),
"released": released.isoformat(),
@ -904,8 +896,8 @@ def test_activity_pub_album_serializer_from_ap_update(factories, faker):
assert album.title == payload["name"]
assert str(album.mbid) == payload["musicbrainzId"]
assert album.release_date == released
assert album.attachment_cover.url == payload["cover"]["href"]
assert album.attachment_cover.mimetype == payload["cover"]["mediaType"]
assert album.attachment_cover.url == payload["image"]["href"]
assert album.attachment_cover.mimetype == payload["image"]["mediaType"]
assert sorted(album.tagged_items.values_list("tag__name", flat=True)) == [
"Punk",
"Rock",
@ -996,7 +988,7 @@ def test_activity_pub_track_serializer_from_ap(factories, r_mock, mocker):
"content": "Album summary",
"mediaType": "text/markdown",
"attributedTo": album_attributed_to.fid,
"cover": {
"image": {
"type": "Link",
"href": "https://cover.image/test.png",
"mediaType": "image/png",
@ -1066,8 +1058,8 @@ def test_activity_pub_track_serializer_from_ap(factories, r_mock, mocker):
assert track.attachment_cover.mimetype == data["image"]["mediaType"]
assert album.from_activity == activity
assert album.attachment_cover.url == data["album"]["cover"]["href"]
assert album.attachment_cover.mimetype == data["album"]["cover"]["mediaType"]
assert album.attachment_cover.url == data["album"]["image"]["href"]
assert album.attachment_cover.mimetype == data["album"]["image"]["mediaType"]
assert album.title == data["album"]["name"]
assert album.fid == data["album"]["id"]
assert str(album.mbid) == data["album"]["musicbrainzId"]
@ -1196,7 +1188,7 @@ def test_activity_pub_upload_serializer_from_ap(factories, mocker, r_mock):
"musicbrainzId": str(uuid.uuid4()),
"published": published.isoformat(),
"released": released.isoformat(),
"cover": {
"image": {
"type": "Link",
"href": "https://cover.image/test.png",
"mediaType": "image/png",
@ -1222,7 +1214,7 @@ def test_activity_pub_upload_serializer_from_ap(factories, mocker, r_mock):
],
},
}
r_mock.get(data["track"]["album"]["cover"]["href"], body=io.BytesIO(b"coucou"))
r_mock.get(data["track"]["album"]["image"]["href"], body=io.BytesIO(b"coucou"))
serializer = serializers.UploadSerializer(data=data, context={"activity": activity})
assert serializer.is_valid(raise_exception=True)
@ -1266,7 +1258,7 @@ def test_activity_pub_upload_serializer_from_ap_update(factories, mocker, now, r
"library": library.fid,
"track": serializers.TrackSerializer(upload.track).data,
}
r_mock.get(data["track"]["album"]["cover"]["href"], body=io.BytesIO(b"coucou"))
r_mock.get(data["track"]["album"]["image"]["url"], body=io.BytesIO(b"coucou"))
serializer = serializers.UploadSerializer(upload, data=data)
assert serializer.is_valid(raise_exception=True)
@ -1628,7 +1620,6 @@ def test_channel_actor_outbox_serializer(factories):
"@context": jsonld.get_default_context(),
"type": "OrderedCollection",
"id": channel.actor.outbox_url,
"actor": channel.actor.fid,
"attributedTo": channel.actor.fid,
"totalItems": len(uploads),
"first": channel.actor.outbox_url + "?page=1",

Wyświetl plik

@ -384,11 +384,6 @@ def test_music_upload_detail_private_approved_follow(
("text/html,application/xhtml+xml", True, True),
("text/html,application/json", True, True),
("", True, False),
(
"*/*",
True,
False,
), # XXX: compat with older versions of Funkwhale that miss the Accept header
(None, True, False),
("application/json", True, False),
("application/activity+json", True, False),

Wyświetl plik

@ -196,15 +196,6 @@ def test_album_serializer(factories, to_api_date):
assert serializer.data == expected
def test_album_serializer_empty_cover(factories, to_api_date):
# XXX: BACKWARD COMPATIBILITY
album = factories["music.Album"](attachment_cover=None)
serializer = serializers.AlbumSerializer(album)
assert serializer.data["cover"] == {}
def test_track_serializer(factories, to_api_date):
actor = factories["federation.Actor"]()
upload = factories["music.Upload"](

Wyświetl plik

@ -660,7 +660,7 @@ def test_federation_audio_track_to_metadata(now, mocker):
},
}
],
"cover": {
"image": {
"type": "Link",
"href": "http://cover.test",
"mediaType": "image/png",
@ -713,8 +713,8 @@ def test_federation_audio_track_to_metadata(now, mocker):
"tags": ["AlbumTag"],
"description": {"content_type": "text/plain", "text": "album desc"},
"cover_data": {
"mimetype": serializer.validated_data["album"]["cover"]["mediaType"],
"url": serializer.validated_data["album"]["cover"]["href"],
"mimetype": serializer.validated_data["album"]["image"]["mediaType"],
"url": serializer.validated_data["album"]["image"]["href"],
},
"artists": [
{

Wyświetl plik

@ -1307,9 +1307,7 @@ def test_get_upload_audio_metadata(logged_in_api_client, factories):
assert response.data == serializer.validated_data
@pytest.mark.parametrize("use_fts", [True, False])
def test_search_get(use_fts, settings, logged_in_api_client, factories):
settings.USE_FULL_TEXT_SEARCH = use_fts
def test_search_get(logged_in_api_client, factories):
artist = factories["music.Artist"](name="Foo Fighters")
album = factories["music.Album"](title="Foo Bar")
track = factories["music.Track"](title="Foo Baz")
@ -1332,8 +1330,7 @@ def test_search_get(use_fts, settings, logged_in_api_client, factories):
assert response.data == expected
def test_search_get_fts_advanced(settings, logged_in_api_client, factories):
settings.USE_FULL_TEXT_SEARCH = True
def test_search_get_fts_advanced(logged_in_api_client, factories):
artist1 = factories["music.Artist"](name="Foo Bighters")
artist2 = factories["music.Artist"](name="Bar Fighter")
factories["music.Artist"]()
@ -1353,8 +1350,7 @@ def test_search_get_fts_advanced(settings, logged_in_api_client, factories):
assert response.data == expected
def test_search_get_fts_stop_words(settings, logged_in_api_client, factories):
settings.USE_FULL_TEXT_SEARCH = True
def test_search_get_fts_stop_words(logged_in_api_client, factories):
artist = factories["music.Artist"](name="she")
factories["music.Artist"](name="something else")

Wyświetl plik

@ -720,7 +720,7 @@ User:
type: "string"
example: "Alice Kingsley"
avatar:
$ref: "#/Avatar"
$ref: "#/Attachment"
Me:
type: "object"
@ -767,30 +767,8 @@ Me:
via request headers isn't possible.
The token expires after 3 days by default.
Avatar:
type: "object"
properties:
original:
type: "string"
format: "uri"
description: "Original image URL"
example: "http://yourinstance/media/users/avatars/92/49/60/b3c-4736-43b3-bb5c-ed7a99ac6996.jpg"
square_crop:
type: "string"
format: "uri"
description: "400x400 thumbnail URL"
example: "http://yourinstance/media/__sized__/users/avatars/92/49/60/b3c-4736-43b3-bb5c-ed7a99ac6996-crop-c0-5__0-5-400x400-70.jpg"
small_square_crop:
type: "string"
format: "uri"
description: "50x50 thumbnail URL"
example: "http://yourinstance/media/__sized__/users/avatars/92/49/60/b3c-4736-43b3-bb5c-ed7a99ac6996-crop-c0-5__0-5-50x50-70.jpg"
medium_square_crop:
type: "string"
format: "uri"
description: "200x200 thumbnail URL"
example: "http://yourinstance/media/__sized__/users/avatars/92/49/60/b3c-4736-43b3-bb5c-ed7a99ac6996-crop-c0-5__0-5-200x200-70.jpg"
QuotaStatus:
QuotaStatus:
type: "object"
properties:
max:

Wyświetl plik

@ -296,7 +296,7 @@ paths:
responses:
200:
$ref: "#/responses/200"
/api/v1/users/users/me/:
/api/v1/users/me/:
get:
summary: Retrive profile information
description: |

Wyświetl plik

@ -337,7 +337,7 @@ export default {
},
getCover(albumCover) {
if (albumCover) {
return albumCover.medium_square_crop
return albumCover.urls.medium_square_crop
}
},
getSources (uploads) {

Wyświetl plik

@ -6,8 +6,8 @@
<div class="ui six wide column current-track">
<div class="ui basic segment" id="player">
<template v-if="currentTrack">
<img ref="cover" alt="" v-if="currentTrack.cover && currentTrack.cover.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.cover.medium_square_crop)">
<img ref="cover" alt="" v-else-if="currentTrack.album && currentTrack.album.cover && currentTrack.album.cover.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.album.cover.medium_square_crop)">
<img ref="cover" alt="" v-if="currentTrack.cover && currentTrack.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.cover.urls.medium_square_crop)">
<img ref="cover" alt="" v-else-if="currentTrack.album && currentTrack.album.cover && currentTrack.album.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.album.cover.urls.medium_square_crop)">
<img class="ui image" alt="" v-else src="../assets/audio/default-cover.png">
<h1 class="ui header">
<div class="content ellipsis">
@ -159,8 +159,8 @@
<i class="grip lines icon"></i>
</td>
<td class="image-cell" @click="$store.dispatch('queue/currentIndex', index)">
<img class="ui mini image" alt="" v-if="track.cover && track.cover.original" :src="$store.getters['instance/absoluteUrl'](track.cover.medium_square_crop)">
<img class="ui mini image" alt="" v-else-if="track.album && track.album.cover && track.album.cover.original" :src="$store.getters['instance/absoluteUrl'](track.album.cover.medium_square_crop)">
<img class="ui mini image" alt="" v-if="track.cover && track.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](track.cover.urls.medium_square_crop)">
<img class="ui mini image" alt="" v-else-if="track.album && track.album.cover && track.album.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](track.album.cover.urls.medium_square_crop)">
<img class="ui mini image" alt="" v-else src="../assets/audio/default-cover.png">
</td>
<td colspan="3" @click="$store.dispatch('queue/currentIndex', index)">

Wyświetl plik

@ -78,7 +78,7 @@
</router-link>
<div class="item">
<div class="ui user-dropdown dropdown" >
<img class="ui avatar image" alt="" v-if="$store.state.auth.profile.avatar && $store.state.auth.profile.avatar.square_crop" :src="$store.getters['instance/absoluteUrl']($store.state.auth.profile.avatar.square_crop)" />
<img class="ui avatar image" alt="" v-if="$store.state.auth.profile.avatar && $store.state.auth.profile.avatar.urls.square_crop" :src="$store.getters['instance/absoluteUrl']($store.state.auth.profile.avatar.urls.square_crop)" />
<actor-avatar v-else :actor="{preferred_username: $store.state.auth.username, full_username: $store.state.auth.username}" />
<div class="menu">
<router-link class="item" :to="{name: 'profile.overview', params: {username: $store.state.auth.username}}"><translate translate-context="*/*/*/Noun">Profile</translate></router-link>

Wyświetl plik

@ -1,6 +1,6 @@
<template>
<router-link class="artist-label ui image label" :to="route">
<img :class="[{circular: artist.content_category != 'podcast'}]" alt="" v-if="artist.cover && artist.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](artist.cover.small_square_crop)" />
<img alt="" :class="[{circular: artist.content_category != 'podcast'}]" v-if="artist.cover && artist.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](artist.cover.urls.medium_square_crop)" />
<i :class="[artist.content_category != 'podcast' ? 'circular' : 'bordered', 'inverted violet users icon']" v-else />
{{ artist.name }}
</router-link>

Wyświetl plik

@ -60,7 +60,7 @@ export default {
computed: {
imageUrl () {
if (this.object.artist.cover) {
return this.$store.getters['instance/absoluteUrl'](this.object.artist.cover.medium_square_crop)
return this.$store.getters['instance/absoluteUrl'](this.object.artist.cover.urls.medium_square_crop)
}
},
urlId () {

Wyświetl plik

@ -7,8 +7,8 @@
@click="$router.push({name: 'library.tracks.detail', params: {id: entry.id}})"
alt=""
class="channel-image image"
v-if="cover && cover.original"
v-lazy="$store.getters['instance/absoluteUrl'](cover.square_crop)">
v-if="cover && cover.urls.original"
v-lazy="$store.getters['instance/absoluteUrl'](cover.urls.square_crop)">
<span
@click="$router.push({name: 'library.tracks.detail', params: {id: entry.id}})"
class="channel-image image"
@ -17,8 +17,8 @@
@click="$router.push({name: 'library.tracks.detail', params: {id: entry.id}})"
alt=""
class="channel-image image"
v-else-if="entry.album && entry.album.cover && entry.album.cover.original"
v-lazy="$store.getters['instance/absoluteUrl'](entry.album.cover.square_crop)">
v-else-if="entry.album && entry.album.cover && entry.album.cover.urls.original"
v-lazy="$store.getters['instance/absoluteUrl'](entry.album.cover.urls.square_crop)">
<img
@click="$router.push({name: 'library.tracks.detail', params: {id: entry.id}})"
alt=""

Wyświetl plik

@ -1,10 +1,10 @@
<template>
<div class="channel-serie-card">
<div class="two-images">
<img @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" alt="" v-if="cover.original" v-lazy="$store.getters['instance/absoluteUrl'](cover.square_crop)">
<img @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" alt="" v-else src="../../assets/audio/default-cover.png">
<img @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" alt="" v-if="cover.original" v-lazy="$store.getters['instance/absoluteUrl'](cover.square_crop)">
<img @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" alt="" v-else src="../../assets/audio/default-cover.png">
<img alt="" @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" v-if="cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](cover.urls.square_crop)">
<img alt="" @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" v-else src="../../assets/audio/default-cover.png">
<img alt="" @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" v-if="cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](cover.urls.square_crop)">
<img alt="" @click="$router.push({name: 'library.albums.detail', params: {id: serie.id}})" class="channel-image" v-else src="../../assets/audio/default-cover.png">
</div>
<div class="content ellipsis">
<strong>

Wyświetl plik

@ -10,9 +10,9 @@
<div class="controls track-controls queue-not-focused desktop-and-up">
<div class="ui tiny image" @click.stop.prevent="$router.push({name: 'library.tracks.detail', params: {id: currentTrack.id }})">
<img ref="cover" alt="" v-if="currentTrack.cover && currentTrack.cover.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.cover.medium_square_crop)">
<img ref="cover" alt="" v-else-if="currentTrack.album && currentTrack.album.cover && currentTrack.album.cover.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.album.cover.medium_square_crop)">
<img v-else src="../../assets/audio/default-cover.png" alt="">
<img alt="" ref="cover" v-if="currentTrack.cover && currentTrack.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.cover.urls.medium_square_crop)">
<img alt="" ref="cover" v-else-if="currentTrack.album && currentTrack.album.cover.urls && currentTrack.album.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.album.cover.urls.medium_square_crop)">
<img alt="" v-else src="../../assets/audio/default-cover.png">
</div>
<div @click.stop.prevent="" class="middle aligned content ellipsis">
<strong>
@ -30,9 +30,9 @@
</div>
<div class="controls track-controls queue-not-focused tablet-and-below">
<div class="ui tiny image">
<img ref="cover" alt="" v-if="currentTrack.cover && currentTrack.cover.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.cover.medium_square_crop)">
<img ref="cover" alt="" v-else-if="currentTrack.album && currentTrack.album.cover && currentTrack.album.cover.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.album.cover.medium_square_crop)">
<img v-else src="../../assets/audio/default-cover.png" alt="">
<img alt="" ref="cover" v-if="currentTrack.cover && currentTrack.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.cover.urls.medium_square_crop)">
<img alt="" ref="cover" v-else-if="currentTrack.album && currentTrack.album.cover && currentTrack.album.cover.urls.original" :src="$store.getters['instance/absoluteUrl'](currentTrack.album.cover.urls.medium_square_crop)">
<img alt="" v-else src="../../assets/audio/default-cover.png">
</div>
<div class="middle aligned content ellipsis">
<strong>
@ -738,12 +738,12 @@ export default {
if (this.currentTrack.album) {
metadata.album = this.currentTrack.album.title
metadata.artwork = [
{ src: this.currentTrack.album.cover.original, sizes: '96x96', type: 'image/png' },
{ src: this.currentTrack.album.cover.original, sizes: '128x128', type: 'image/png' },
{ src: this.currentTrack.album.cover.original, sizes: '192x192', type: 'image/png' },
{ src: this.currentTrack.album.cover.original, sizes: '256x256', type: 'image/png' },
{ src: this.currentTrack.album.cover.original, sizes: '384x384', type: 'image/png' },
{ src: this.currentTrack.album.cover.original, sizes: '512x512', type: 'image/png' },
{ src: this.currentTrack.album.cover.urls.original, sizes: '96x96', type: 'image/png' },
{ src: this.currentTrack.album.cover.urls.original, sizes: '128x128', type: 'image/png' },
{ src: this.currentTrack.album.cover.urls.original, sizes: '192x192', type: 'image/png' },
{ src: this.currentTrack.album.cover.urls.original, sizes: '256x256', type: 'image/png' },
{ src: this.currentTrack.album.cover.urls.original, sizes: '384x384', type: 'image/png' },
{ src: this.currentTrack.album.cover.urls.original, sizes: '512x512', type: 'image/png' },
]
}
navigator.mediaSession.metadata = new MediaMetadata(metadata);

Wyświetl plik

@ -2,7 +2,7 @@
<div class="card app-card component-album-card">
<div
@click="$router.push({name: 'library.albums.detail', params: {id: album.id}})"
:class="['ui', 'head-image', 'image', {'default-cover': !album.cover.original}]" v-lazy:background-image="imageUrl">
:class="['ui', 'head-image', 'image', {'default-cover': !album.cover || !album.cover.urls.original}]" v-lazy:background-image="imageUrl">
<play-button :icon-only="true" :is-playable="album.is_playable" :button-classes="['ui', 'circular', 'large', 'vibrant', 'icon', 'button']" :album="album"></play-button>
</div>
<div class="content">
@ -38,8 +38,8 @@ export default {
},
computed: {
imageUrl () {
if (this.album.cover.original) {
return this.$store.getters['instance/absoluteUrl'](this.album.cover.medium_square_crop)
if (this.album.cover && this.album.cover.urls.original) {
return this.$store.getters['instance/absoluteUrl'](this.album.cover.urls.medium_square_crop)
}
}
}

Wyświetl plik

@ -2,7 +2,7 @@
<div class="app-card card">
<div
@click="$router.push({name: 'library.artists.detail', params: {id: artist.id}})"
:class="['ui', 'head-image', 'circular', 'image', {'default-cover': !cover.original}]" v-lazy:background-image="imageUrl">
:class="['ui', 'head-image', 'circular', 'image', {'default-cover': !cover || !cover.urls.original}]" v-lazy:background-image="imageUrl">
<play-button :icon-only="true" :is-playable="artist.is_playable" :button-classes="['ui', 'circular', 'large', 'vibrant', 'icon', 'button']" :artist="artist"></play-button>
</div>
<div class="content">
@ -40,19 +40,19 @@ export default {
computed: {
imageUrl () {
let cover = this.cover
if (cover.original) {
return this.$store.getters['instance/absoluteUrl'](cover.medium_square_crop)
if (cover && cover.urls.original) {
return this.$store.getters['instance/absoluteUrl'](cover.urls.medium_square_crop)
}
},
cover () {
if (this.artist.cover && this.artist.cover.original) {
if (this.artist.cover && this.artist.cover.urls.original) {
return this.artist.cover
}
return this.artist.albums.map((a) => {
return a.cover
}).filter((c) => {
return c && c.original
})[0] || {}
return c && c.urls.original
})[0]
},
}
}

Wyświetl plik

@ -4,8 +4,8 @@
<play-button :class="['basic', {vibrant: currentTrack && isPlaying && track.id === currentTrack.id}, 'icon']" :discrete="true" :is-playable="playable" :track="track"></play-button>
</td>
<td>
<img class="ui mini image" alt="" v-if="track.album && track.album.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](track.album.cover.small_square_crop)">
<img class="ui mini image" alt="" v-else src="../../../assets/audio/default-cover.png">
<img alt="" class="ui mini image" v-if="track.album && track.album.cover && track.album.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](track.album.cover.urls.medium_square_crop)">
<img alt="" class="ui mini image" v-else src="../../../assets/audio/default-cover.png">
</td>
<td colspan="6">
<router-link class="track" :to="{name: 'library.tracks.detail', params: {id: track.id }}">

Wyświetl plik

@ -7,7 +7,7 @@
<div v-if="count > 0" class="ui divided unstackable items">
<div :class="['item', itemClasses]" v-for="object in objects" :key="object.id">
<div class="ui tiny image">
<img alt="" v-if="object.track.album && object.track.album.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](object.track.album.cover.medium_square_crop)">
<img alt="" v-if="object.track.album && object.track.album.cover" v-lazy="$store.getters['instance/absoluteUrl'](object.track.album.cover.urls.medium_square_crop)">
<img alt="" v-else src="../../../assets/audio/default-cover.png">
<play-button class="play-overlay" :icon-only="true" :button-classes="['ui', 'circular', 'tiny', 'vibrant', 'icon', 'button']" :track="object.track"></play-button>
</div>

Wyświetl plik

@ -416,12 +416,12 @@ export default {
this.settings.errors = []
let self = this
let payload = this.settingsValues
let url = `users/users/${this.$store.state.auth.username}/`
let url = `users/${this.$store.state.auth.username}/`
return axios.patch(url, payload).then(
response => {
logger.default.info("Updated settings successfully")
self.settings.success = true
return axios.get("users/users/me/").then(response => {
return axios.get("users/me/").then(response => {
self.$store.dispatch("auth/updateProfile", response.data)
})
},
@ -487,7 +487,7 @@ export default {
this.avatarErrors = []
let self = this
axios
.patch(`users/users/${this.$store.state.auth.username}/`, {avatar: uuid})
.patch(`users/${this.$store.state.auth.username}/`, {avatar: uuid})
.then(
response => {
this.isLoadingAvatar = false
@ -538,7 +538,7 @@ export default {
confirm: true,
password: this.password,
}
axios.delete(`users/users/me/`, {data: payload})
axios.delete(`users/me/`, {data: payload})
.then(
response => {
self.isDeletingAccount = false

Wyświetl plik

@ -87,7 +87,7 @@ export default {
this.errors = []
this.isLoading = true
let self = this
let url = `users/users/${this.$store.state.auth.username}/subsonic-token/`
let url = `users/${this.$store.state.auth.username}/subsonic-token/`
return axios.get(url).then(response => {
self.token = response.data['subsonic_api_token']
self.isLoading = false
@ -102,7 +102,7 @@ export default {
this.errors = []
this.isLoading = true
let self = this
let url = `users/users/${this.$store.state.auth.username}/subsonic-token/`
let url = `users/${this.$store.state.auth.username}/subsonic-token/`
return axios.post(url, {}).then(response => {
self.showToken = true
self.token = response.data['subsonic_api_token']
@ -119,7 +119,7 @@ export default {
this.errors = []
this.isLoading = true
let self = this
let url = `users/users/${this.$store.state.auth.username}/subsonic-token/`
let url = `users/${this.$store.state.auth.username}/subsonic-token/`
return axios.delete(url).then(response => {
self.isLoading = false
self.token = null

Wyświetl plik

@ -347,7 +347,7 @@ export default {
},
fetchQuota () {
let self = this
axios.get('users/users/me/').then((response) => {
axios.get('users/me/').then((response) => {
self.quotaStatus = response.data.quota_status
})
},
@ -391,8 +391,8 @@ export default {
value: c.uuid,
selected: self.channel && self.channel.uuid === c.uuid,
}
if (c.artist.cover && c.artist.cover.small_square_crop) {
let coverUrl = self.$store.getters['instance/absoluteUrl'](c.artist.cover.small_square_crop)
if (c.artist.cover && c.artist.cover.urls.medium_square_crop) {
let coverUrl = self.$store.getters['instance/absoluteUrl'](c.artist.cover.urls.medium_square_crop)
d.image = coverUrl
if (c.artist.content_category === 'podcast') {
d.imageClass = 'ui image'

Wyświetl plik

@ -1,5 +1,5 @@
<template>
<img alt="" v-if="actor.icon && actor.icon.original" :src="actor.icon.small_square_crop" class="ui avatar circular image" />
<img alt="" v-if="actor.icon && actor.icon.urls.original" :src="actor.icon.urls.medium_square_crop" class="ui avatar circular image" />
<span v-else :style="defaultAvatarStyle" class="ui avatar circular label">{{ actor.preferred_username[0]}}</span>
</template>

Wyświetl plik

@ -4,8 +4,8 @@
<img
class="ui tiny circular avatar"
alt=""
v-if="user.avatar && user.avatar.small_square_crop"
v-lazy="$store.getters['instance/absoluteUrl'](user.avatar.small_square_crop)" />
v-if="user.avatar && user.avatar.urls.medium_square_crop"
v-lazy="$store.getters['instance/absoluteUrl'](user.avatar.urls.medium_square_crop)" />
<span v-else :style="defaultAvatarStyle" class="ui circular label">{{ user.username[0]}}</span>
&nbsp;
</template>

Wyświetl plik

@ -11,10 +11,10 @@
<div class="ui two column grid" v-if="isSerie">
<div class="column">
<div class="large two-images">
<img class="channel-image" alt="" v-if="object.cover && object.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.square_crop)">
<img class="channel-image" alt="" v-else src="../../assets/audio/default-cover.png">
<img class="channel-image" alt="" v-if="object.cover && object.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.square_crop)">
<img class="channel-image" alt="" v-else src="../../assets/audio/default-cover.png">
<img alt="" class="channel-image" v-if="object.cover && object.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.urls.square_crop)">
<img alt="" class="channel-image" v-else src="../../assets/audio/default-cover.png">
<img alt="" class="channel-image" v-if="object.cover && object.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.urls.square_crop)">
<img alt="" class="channel-image" v-else src="../../assets/audio/default-cover.png">
</div>
</div>
<div class="ui column right aligned">
@ -53,8 +53,8 @@
</header>
</div>
<div v-else class="ui center aligned text padded basic segment">
<img class="channel-image" alt="" v-if="object.cover && object.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.square_crop)">
<img class="channel-image" alt="" v-else src="../../assets/audio/default-cover.png">
<img alt="" class="channel-image" v-if="object.cover && object.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.urls.square_crop)">
<img alt="" class="channel-image" v-else src="../../assets/audio/default-cover.png">
<div class="ui hidden divider"></div>
<header>
<h2 class="ui header" :title="object.title">

Wyświetl plik

@ -235,12 +235,12 @@ export default {
)
},
cover() {
if (this.object.cover && this.object.cover.original) {
if (this.object.cover && this.object.cover.urls.original) {
return this.object.cover
}
return this.object.albums
.filter(album => {
return album.cover && album.cover.original
return album.cover && album.cover.urls.original
})
.map(album => {
return album.cover
@ -253,12 +253,12 @@ export default {
})
},
headerStyle() {
if (!this.cover || !this.cover.original) {
if (!this.cover || !this.cover.urls.original) {
return ""
}
return (
"background-image: url(" +
this.$store.getters["instance/absoluteUrl"](this.cover.original) +
this.$store.getters["instance/absoluteUrl"](this.cover.urls.original) +
")"
)
},

Wyświetl plik

@ -274,7 +274,7 @@ export default {
fetchQuota () {
let self = this
self.isLoadingQuota = true
axios.get('users/users/me/').then((response) => {
axios.get('users/me/').then((response) => {
self.quotaStatus = response.data.quota_status
self.isLoadingQuota = false
})

Wyświetl plik

@ -264,12 +264,12 @@ export default {
return route.href
},
headerStyle() {
if (!this.cover || !this.cover.original) {
if (!this.cover || !this.cover.urls.original) {
return ""
}
return (
"background-image: url(" +
this.$store.getters["instance/absoluteUrl"](this.cover.original) +
this.$store.getters["instance/absoluteUrl"](this.cover.urls.original) +
")"
)
},

Wyświetl plik

@ -4,7 +4,7 @@
<section class="ui vertical stripe segment">
<div class="ui stackable grid row container">
<div class="six wide column">
<img class="image" alt="" v-if="cover && cover.original" v-lazy="$store.getters['instance/absoluteUrl'](cover.square_crop)">
<img alt="" class="image" v-if="cover && cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](cover.urls.square_crop)">
<template v-if="upload">
<h3 class="ui header">
<translate key="1" v-if="track.artist.content_category === 'music'" translate-context="Content/*/*">Track Details</translate>
@ -223,7 +223,7 @@ export default {
return this.licenseData
},
cover () {
if (this.track.cover && this.track.cover.original) {
if (this.track.cover && this.track.cover.urls.original) {
return this.track.cover
}
if (this.track.album && this.track.album.cover) {

Wyświetl plik

@ -64,7 +64,7 @@
<tr v-for="(plt, index) in plts" :key="`${index}-${plt.track.id}`">
<td class="left aligned">{{ plt.index + 1}}</td>
<td class="center aligned">
<img alt="" class="ui mini image" v-if="plt.track.album && plt.track.album.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](plt.track.album.cover.small_square_crop)">
<img alt="" class="ui mini image" v-if="plt.track.album && plt.track.album.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](plt.track.album.cover.urls.medium_square_crop)">
<img alt="" class="ui mini image" v-else src="../../assets/audio/default-cover.png">
</td>
<td colspan="4">

Wyświetl plik

@ -182,7 +182,7 @@ export default {
fetchProfile ({commit, dispatch, state}) {
return new Promise((resolve, reject) => {
axios.get('users/users/me/').then((response) => {
axios.get('users/me/').then((response) => {
logger.default.info('Successfully fetched user profile')
dispatch('ui/initSettings', response.data.settings, { root: true })
dispatch('updateProfile', response.data).then(() => {

Wyświetl plik

@ -33,7 +33,7 @@ export default {
let playlists = []
let url = 'playlists/'
while (url != null) {
let response = await axios.get(url, {params: {user: userId}})
let response = await axios.get(url, {params: {scope: "me"}})
playlists = [...playlists, ...response.data.results]
url = response.data.next

Wyświetl plik

@ -167,7 +167,7 @@ export default {
}
payload[field] = newDisplayDate
let self = this
axios.patch(`users/users/${this.$store.state.auth.username}/`, payload).then((response) => {
axios.patch(`users/${this.$store.state.auth.username}/`, payload).then((response) => {
self.$store.commit('auth/profilePartialUpdate', response.data)
})
},

Wyświetl plik

@ -9,7 +9,7 @@
<div class="ui column">
<div class="segment-content">
<h2 class="ui header">
<img alt="" v-if="object.artist.cover && object.artist.cover.square_crop" v-lazy="$store.getters['instance/absoluteUrl'](object.artist.cover.square_crop)">
<img alt="" v-if="object.artist.cover && object.artist.cover.urls.square_crop" v-lazy="$store.getters['instance/absoluteUrl'](object.artist.cover.urls.square_crop)">
<img alt="" v-else src="../../assets/audio/default-cover.png">
<div class="content">
{{ object.artist.name | truncate(100) }}

Wyświetl plik

@ -9,7 +9,7 @@
<div class="ui column">
<div class="segment-content">
<h2 class="ui header">
<img alt="" v-if="object.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.square_crop)">
<img alt="" v-if="object.cover.urls.original" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.urls.square_crop)">
<img alt="" v-else src="../../../assets/audio/default-cover.png">
<div class="content">
{{ object.title | truncate(100) }}

Wyświetl plik

@ -9,7 +9,7 @@
<div class="ui column">
<div class="segment-content">
<h2 class="ui header">
<img alt="" v-if="object.cover && object.cover.square_crop" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.square_crop)">
<img alt="" v-if="object.cover && object.cover.urls.square_crop" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.urls.square_crop)">
<img alt="" v-else src="../../../assets/audio/default-cover.png">
<div class="content">
{{ object.name | truncate(100) }}

Wyświetl plik

@ -9,7 +9,7 @@
<div class="ui column">
<div class="segment-content">
<h2 class="ui header">
<img alt="" v-if="object.cover && object.cover.square_crop" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.square_crop)">
<img alt="" v-if="object.cover && object.cover.urls.square_crop" v-lazy="$store.getters['instance/absoluteUrl'](object.cover.urls.square_crop)">
<img alt="" v-else src="../../../assets/audio/default-cover.png">
<div class="content">
{{ object.title | truncate(100) }}

Wyświetl plik

@ -27,7 +27,7 @@
</div>
<h1 class="ui center aligned icon header">
<i v-if="!object.icon" class="circular inverted user success icon"></i>
<img alt="" class="ui big circular image" v-else v-lazy="$store.getters['instance/absoluteUrl'](object.icon.square_crop)" />
<img alt="" class="ui big circular image" v-else v-lazy="$store.getters['instance/absoluteUrl'](object.icon.urls.square_crop)" />
<div class="ellispsis content">
<div class="ui very small hidden divider"></div>
<span>{{ displayName }}</span>
@ -49,7 +49,7 @@
@updated="$emit('updated', $event)"
:content="object.summary"
:field-name="'summary'"
:update-url="`users/users/${$store.state.auth.username}/`"
:update-url="`users/${$store.state.auth.username}/`"
:can-update="$store.state.auth.authenticated && object.full_username === $store.state.auth.fullUsername"></rendered-description>
</div>
</div>

Wyświetl plik

@ -5,7 +5,7 @@
@updated="$emit('updated', $event)"
:content="object.summary"
:field-name="'summary'"
:update-url="`users/users/${$store.state.auth.username}/`"
:update-url="`users/${$store.state.auth.username}/`"
:can-update="$store.state.auth.authenticated && object.full_username === $store.state.auth.fullUsername"></rendered-description>
<div class="ui hidden divider"></div>
</div>

Wyświetl plik

@ -9,7 +9,7 @@
<div class="seven wide column">
<div class="ui two column grid">
<div class="column">
<img alt="" class="huge channel-image" v-if="object.artist.cover" :src="$store.getters['instance/absoluteUrl'](object.artist.cover.medium_square_crop)">
<img alt="" class="huge channel-image" v-if="object.artist.cover" :src="$store.getters['instance/absoluteUrl'](object.artist.cover.urls.medium_square_crop)">
<i v-else class="huge circular inverted users violet icon"></i>
</div>
<div class="ui column right aligned">

Wyświetl plik

@ -114,7 +114,7 @@ export default {
fetch () {
let self = this
self.isLoading = true
axios.get('users/users/me/').then((response) => {
axios.get('users/me/').then((response) => {
self.quotaStatus = response.data.quota_status
self.isLoading = false
})

Wyświetl plik

@ -146,7 +146,7 @@ describe('store/auth', () => {
admin: true
}
}
moxios.stubRequest('users/users/me/', {
moxios.stubRequest('users/me/', {
status: 200,
response: profile
})