Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • funkwhale/funkwhale
  • Luclu7/funkwhale
  • mbothorel/funkwhale
  • EorlBruder/funkwhale
  • tcit/funkwhale
  • JocelynDelalande/funkwhale
  • eneiluj/funkwhale
  • reg/funkwhale
  • ButterflyOfFire/funkwhale
  • m4sk1n/funkwhale
  • wxcafe/funkwhale
  • andybalaam/funkwhale
  • jcgruenhage/funkwhale
  • pblayo/funkwhale
  • joshuaboniface/funkwhale
  • n3ddy/funkwhale
  • gegeweb/funkwhale
  • tohojo/funkwhale
  • emillumine/funkwhale
  • Te-k/funkwhale
  • asaintgenis/funkwhale
  • anoadragon453/funkwhale
  • Sakada/funkwhale
  • ilianaw/funkwhale
  • l4p1n/funkwhale
  • pnizet/funkwhale
  • dante383/funkwhale
  • interfect/funkwhale
  • akhardya/funkwhale
  • svfusion/funkwhale
  • noplanman/funkwhale
  • nykopol/funkwhale
  • roipoussiere/funkwhale
  • Von/funkwhale
  • aurieh/funkwhale
  • icaria36/funkwhale
  • floreal/funkwhale
  • paulwalko/funkwhale
  • comradekingu/funkwhale
  • FurryJulie/funkwhale
  • Legolars99/funkwhale
  • Vierkantor/funkwhale
  • zachhats/funkwhale
  • heyjake/funkwhale
  • sn0w/funkwhale
  • jvoisin/funkwhale
  • gordon/funkwhale
  • Alexander/funkwhale
  • bignose/funkwhale
  • qasim.ali/funkwhale
  • fakegit/funkwhale
  • Kxze/funkwhale
  • stenstad/funkwhale
  • creak/funkwhale
  • Kaze/funkwhale
  • Tixie/funkwhale
  • IISergII/funkwhale
  • lfuelling/funkwhale
  • nhaddag/funkwhale
  • yoasif/funkwhale
  • ifischer/funkwhale
  • keslerm/funkwhale
  • flupe/funkwhale
  • petitminion/funkwhale
  • ariasuni/funkwhale
  • ollie/funkwhale
  • ngaumont/funkwhale
  • techknowlogick/funkwhale
  • Shleeble/funkwhale
  • theflyingfrog/funkwhale
  • jonatron/funkwhale
  • neobrain/funkwhale
  • eorn/funkwhale
  • KokaKiwi/funkwhale
  • u1-liquid/funkwhale
  • marzzzello/funkwhale
  • sirenwatcher/funkwhale
  • newer027/funkwhale
  • codl/funkwhale
  • Zwordi/funkwhale
  • gisforgabriel/funkwhale
  • iuriatan/funkwhale
  • simon/funkwhale
  • bheesham/funkwhale
  • zeoses/funkwhale
  • accraze/funkwhale
  • meliurwen/funkwhale
  • divadsn/funkwhale
  • Etua/funkwhale
  • sdrik/funkwhale
  • Soran/funkwhale
  • kuba-orlik/funkwhale
  • cristianvogel/funkwhale
  • Forceu/funkwhale
  • jeff/funkwhale
  • der_scheibenhacker/funkwhale
  • owlnical/funkwhale
  • jovuit/funkwhale
  • SilverFox15/funkwhale
  • phw/funkwhale
  • mayhem/funkwhale
  • sridhar/funkwhale
  • stromlin/funkwhale
  • rrrnld/funkwhale
  • nitaibezerra/funkwhale
  • jaller94/funkwhale
  • pcouy/funkwhale
  • eduxstad/funkwhale
  • codingHahn/funkwhale
  • captain/funkwhale
  • polyedre/funkwhale
  • leishenailong/funkwhale
  • ccritter/funkwhale
  • lnceballosz/funkwhale
  • fpiesche/funkwhale
  • Fanyx/funkwhale
  • markusblogde/funkwhale
  • Firobe/funkwhale
  • devilcius/funkwhale
  • freaktechnik/funkwhale
  • blopware/funkwhale
  • cone/funkwhale
  • thanksd/funkwhale
  • vachan-maker/funkwhale
  • bbenti/funkwhale
  • tarator/funkwhale
  • prplecake/funkwhale
  • DMarzal/funkwhale
  • lullis/funkwhale
  • hanacgr/funkwhale
  • albjeremias/funkwhale
  • xeruf/funkwhale
  • llelite/funkwhale
  • RoiArthurB/funkwhale
  • cloo/funkwhale
  • nztvar/funkwhale
  • Keunes/funkwhale
  • petitminion/funkwhale-petitminion
  • m-idler/funkwhale
  • SkyLeite/funkwhale
140 results
Select Git revision
Show changes
Showing
with 677 additions and 536 deletions
......@@ -42,7 +42,7 @@ def structure_payload(data):
"status": "ok",
"type": "funkwhale",
"version": "1.16.0",
"openSubsonic": "true",
"openSubsonic": True,
}
payload.update(data)
if "detail" in payload:
......@@ -70,6 +70,7 @@ class SubsonicXMLRenderer(renderers.JSONRenderer):
return super().render(data, accepted_media_type, renderer_context)
final = structure_payload(data)
final["xmlns"] = "http://subsonic.org/restapi"
final["openSubsonic"] = "true"
tree = dict_to_xml_tree("subsonic-response", final)
return b'<?xml version="1.0" encoding="UTF-8"?>\n' + ET.tostring(
tree, encoding="utf-8"
......
......@@ -111,6 +111,9 @@ class GetArtistInfo2Serializer(serializers.Serializer):
if artist.mbid:
payload["musicBrainzId"] = TagValue(artist.mbid)
if artist.attachment_cover:
payload["smallImageUrl"] = TagValue(
artist.attachment_cover.download_url_small_square_crop
)
payload["mediumImageUrl"] = TagValue(
artist.attachment_cover.download_url_medium_square_crop
)
......@@ -226,6 +229,28 @@ class GetSongSerializer(serializers.Serializer):
return get_track_data(track.album, track, uploads[0])
class GetTopSongsSerializer(serializers.Serializer):
def to_representation(self, artist):
top_tracks = (
history_models.Listening.objects.filter(track__artist_credit__artist=artist)
.values("track")
.annotate(listen_count=Count("id"))
.order_by("-listen_count")[: self.context["count"]]
)
if not len(top_tracks):
return {}
top_tracks_instances = []
for track in top_tracks:
track = music_models.Track.objects.get(id=track["track"])
top_tracks_instances.append(track)
return [
get_track_data(track.album, track, track.uploads.all()[0])
for track in top_tracks_instances
]
def get_starred_tracks_data(favorites):
by_track_id = {f.track_id: f for f in favorites}
tracks = (
......@@ -335,15 +360,21 @@ def get_channel_data(channel, uploads):
"id": str(channel.uuid),
"url": channel.get_rss_url(),
"title": channel.artist.name,
"description": channel.artist.description.as_plain_text
"description": (
channel.artist.description.as_plain_text
if channel.artist.description
else "",
"coverArt": f"at-{channel.artist.attachment_cover.uuid}"
else ""
),
"coverArt": (
f"at-{channel.artist.attachment_cover.uuid}"
if channel.artist.attachment_cover
else "",
"originalImageUrl": channel.artist.attachment_cover.url
else ""
),
"originalImageUrl": (
channel.artist.attachment_cover.url
if channel.artist.attachment_cover
else "",
else ""
),
"status": "completed",
}
if uploads:
......@@ -360,12 +391,14 @@ def get_channel_episode_data(upload, channel_id):
"channelId": str(channel_id),
"streamId": upload.track.id,
"title": upload.track.title,
"description": upload.track.description.as_plain_text
if upload.track.description
else "",
"coverArt": f"at-{upload.track.attachment_cover.uuid}"
"description": (
upload.track.description.as_plain_text if upload.track.description else ""
),
"coverArt": (
f"at-{upload.track.attachment_cover.uuid}"
if upload.track.attachment_cover
else "",
else ""
),
"isDir": "false",
"year": upload.track.creation_date.year,
"publishDate": upload.track.creation_date.isoformat(),
......
"""
Documentation of Subsonic API can be found at http://www.subsonic.org/pages/api.jsp
"""
import datetime
import functools
......@@ -90,6 +91,8 @@ def find_object(
}
}
)
except qs.model.MultipleObjectsReturned:
obj = qs.filter(**{model_field: value})[0]
kwargs["obj"] = obj
return func(self, request, *args, **kwargs)
......@@ -260,6 +263,43 @@ class SubsonicViewSet(viewsets.GenericViewSet):
return response.Response(payload, status=200)
# This should return last.fm data but we choose to return the pod top song
@action(
detail=False,
methods=["get", "post"],
url_name="get_top_songs",
url_path="getTopSongs",
)
@find_object(
music_models.Artist.objects.all(),
model_field="artist_credit__artist__name",
field="artist",
filter_playable=True,
cast=str,
)
def get_top_songs(self, request, *args, **kwargs):
artist = kwargs.pop("obj")
data = request.GET or request.POST
try:
count = int(data["count"])
except KeyError:
return response.Response(
{
"error": {
"code": 10,
"message": "required parameter 'count' not present",
}
}
)
# passing with many=true to make the serializer accept the returned list
data = serializers.GetTopSongsSerializer(
[artist], context={"count": count}, many=True
).data
payload = {"topSongs": data[0]}
return response.Response(payload, status=200)
@action(
detail=False,
methods=["get", "post"],
......@@ -289,6 +329,44 @@ class SubsonicViewSet(viewsets.GenericViewSet):
payload = {"album": data}
return response.Response(payload, status=200)
# A clone of get_album (this should return last.fm data but we prefer to send our own metadata)
@action(
detail=False,
methods=["get", "post"],
url_name="get_album_info_2",
url_path="getAlbumInfo2",
)
@find_object(
music_models.Album.objects.with_duration().prefetch_related(
"artist_credit__artist"
),
filter_playable=True,
)
def get_album_info_2(self, request, *args, **kwargs):
album = kwargs.pop("obj")
data = serializers.GetAlbumSerializer(album).data
payload = {"albumInfo": data}
return response.Response(payload, status=200)
# A clone of get_album (this should return last.fm data but we prefer to send our own metadata)
@action(
detail=False,
methods=["get", "post"],
url_name="get_album_info",
url_path="getAlbumInfo",
)
@find_object(
music_models.Album.objects.with_duration().prefetch_related(
"artist_credit__artist"
),
filter_playable=True,
)
def get_album_info(self, request, *args, **kwargs):
album = kwargs.pop("obj")
data = serializers.GetAlbumSerializer(album).data
payload = {"albumInfo": data}
return response.Response(payload, status=200)
@action(detail=False, methods=["get", "post"], url_name="stream", url_path="stream")
@find_object(music_models.Track.objects.all(), filter_playable=True)
def stream(self, request, *args, **kwargs):
......@@ -815,7 +893,7 @@ class SubsonicViewSet(viewsets.GenericViewSet):
.select_related("attachment_cover")
.get(pk=artist_id)
)
except (TypeError, ValueError, music_models.Album.DoesNotExist):
except (TypeError, ValueError, music_models.Artist.DoesNotExist):
return response.Response(
{"error": {"code": 70, "message": "cover art not found."}}
)
......@@ -824,7 +902,7 @@ class SubsonicViewSet(viewsets.GenericViewSet):
try:
attachment_id = id.replace("at-", "")
attachment = common_models.Attachment.objects.get(uuid=attachment_id)
except (TypeError, ValueError, music_models.Album.DoesNotExist):
except (TypeError, ValueError, common_models.Attachment.DoesNotExist):
return response.Response(
{"error": {"code": 70, "message": "cover art not found."}}
)
......
......@@ -471,7 +471,7 @@ def create_user_libraries(user):
uuid=(new_uuid := uuid.uuid4()),
fid=federation_utils.full_url(
reverse(
"federation:music:playlists-detail",
"federation:music:libraries-detail",
kwargs={"uuid": new_uuid},
)
),
......
This diff is collapsed.
[tool.poetry]
name = "funkwhale-api"
version = "1.4.0"
version = "2.0.0-alpha.2"
description = "Funkwhale API"
authors = ["Funkwhale Collective"]
......@@ -25,29 +25,29 @@ exclude = ["tests"]
funkwhale-manage = 'funkwhale_api.main:main'
[tool.poetry.dependencies]
python = "^3.10,<3.14"
python = "^3.11,<3.14"
# Django
dj-rest-auth = "7.0.1"
django = "5.1.5"
django-allauth = "65.3.1"
django = "5.1.6"
django-allauth = "65.4.1"
django-cache-memoize = "0.2.1"
django-cacheops = "==7.1"
django-cleanup = "==9.0.0"
django-cors-headers = "==4.6.0"
django-cors-headers = "==4.7.0"
django-dynamic-preferences = "==1.17.0"
django-environ = "==0.12.0"
django-filter = "==24.3"
django-filter = "==25.1"
django-oauth-toolkit = "3.0.1"
django-redis = "==5.4.0"
django-storages = "==1.14.4"
django-storages = "==1.14.5"
django-versatileimagefield = "==3.1"
djangorestframework = "==3.15.2"
drf-spectacular = "==0.28.0"
markdown = "==3.7"
persisting-theory = "==1.0"
psycopg2-binary = "==2.9.10"
redis = "==5.2.1"
redis = "==6.1.0"
# Django LDAP
django-auth-ldap = "==5.1.0"
......@@ -66,17 +66,17 @@ gunicorn = "==23.0.0"
uvicorn = { version = "==0.34.0", extras = ["standard"] }
# Libs
aiohttp = "3.11.11"
aiohttp = "3.11.12"
arrow = "==1.3.0"
backports-zoneinfo = { version = "==0.2.1", python = "<3.9" }
bleach = "==6.2.0"
boto3 = "==1.35.99"
boto3 = "==1.36.21"
click = "==8.1.8"
cryptography = "==44.0.0"
cryptography = "==44.0.1"
defusedxml = "0.7.1"
feedparser = "==6.0.11"
python-ffmpeg = "==2.0.12"
liblistenbrainz = "==0.5.5"
liblistenbrainz = "==0.5.6"
musicbrainzngs = "==0.7.1"
mutagen = "==1.46.0"
pillow = "==11.1.0"
......@@ -84,47 +84,47 @@ pyld = "==2.0.4"
python-magic = "==0.4.27"
requests = "==2.32.3"
requests-http-message-signatures = "==0.3.1"
sentry-sdk = "==2.20.0"
sentry-sdk = "==2.22.0"
watchdog = "==6.0.0"
troi = "==2025.1.10.0"
troi = "==2025.1.29.0"
lb-matching-tools = "==2024.1.30.1"
unidecode = "==1.3.8"
pycountry = "24.6.1"
# Typesense
typesense = { version = "==0.21.0", optional = true }
typesense = { version = "==1.0.3", optional = true }
# Dependencies pinning
ipython = "==8.31.0"
ipython = "==9.2.0"
pluralizer = "==1.2.0"
service-identity = "==24.2.0"
unicode-slugify = "==0.1.5"
[tool.poetry.group.dev.dependencies]
aioresponses = "==0.7.7"
aioresponses = "==0.7.8"
asynctest = "==0.13.0"
black = "==24.10.0"
coverage = { version = "==7.6.10", extras = ["toml"] }
debugpy = "==1.8.11"
black = "==25.1.0"
coverage = { version = "==7.6.12", extras = ["toml"] }
debugpy = "==1.8.12"
django-coverage-plugin = "==3.1.0"
django-debug-toolbar = "==5.0.1"
factory-boy = "==3.3.1"
faker = "==33.3.1"
flake8 = "==7.1.1"
factory-boy = "==3.3.3"
faker = "==37.1.0"
flake8 = "==7.1.2"
ipdb = "==0.13.13"
pytest = "==8.3.4"
pytest-asyncio = "==0.25.2"
prompt-toolkit = "==3.0.48"
pytest-asyncio = "==0.25.3"
prompt-toolkit = "==3.0.50"
pytest-cov = "==6.0.0"
pytest-django = "==4.9.0"
pytest-django = "==4.10.0"
pytest-env = "==1.1.5"
pytest-mock = "==3.14.0"
pytest-randomly = "==3.16.0"
pytest-sugar = "==1.0.0"
requests-mock = "==1.12.1"
pylint = "==3.3.3"
pylint = "==3.3.4"
pylint-django = "==2.6.1"
django-extensions = "==3.2.3"
django-extensions = "==4.1"
[tool.poetry.extras]
typesense = ["typesense"]
......@@ -135,7 +135,8 @@ build-backend = "poetry.core.masonry.api"
[tool.pylint.master]
load-plugins = ["pylint_django"]
django-settings-module = "config.settings.testing"
django-settings-module = "config.settings.local"
init-hook = 'import os; os.environ.setdefault("FUNKWHALE_URL", "https://test.federation")'
[tool.pylint.messages_control]
disable = [
......
......@@ -230,6 +230,7 @@ def test_channel_serializer_representation(factories, to_api_date):
"rss_url": channel.get_rss_url(),
"url": channel.actor.url,
"downloads_count": 12,
"subscriptions_count": 0,
}
expected["artist"]["description"] = common_serializers.ContentSerializer(
content
......@@ -254,6 +255,7 @@ def test_channel_serializer_external_representation(factories, to_api_date):
"rss_url": channel.get_rss_url(),
"url": channel.actor.url,
"downloads_count": 0,
"subscriptions_count": 0,
}
expected["artist"]["description"] = common_serializers.ContentSerializer(
content
......
......@@ -22,7 +22,7 @@ def test_mutation_fid_is_populated(factories, model, factory_args, namespace):
("music.Artist", "/library/artists/{obj.pk}"),
("music.Album", "/library/albums/{obj.pk}"),
("music.Track", "/library/tracks/{obj.pk}"),
("playlists.Playlist", "/library/playlists/{obj.pk}"),
("playlists.Playlist", "/library/playlists/{obj.uuid}"),
],
)
def test_get_absolute_url(factory_name, factories, expected):
......
......@@ -98,9 +98,10 @@ def test_privacylevel_permission_me(
assert check is expected
# "me" expects true since the object can be private but share with followers
@pytest.mark.parametrize(
"privacy_level,expected",
[("me", False), ("followers", True), ("instance", False), ("everyone", True)],
[("me", True), ("followers", True), ("instance", False), ("everyone", True)],
)
def test_privacylevel_permission_followers(
factories, api_request, anonymous_user, privacy_level, expected, mocker
......
......@@ -195,6 +195,9 @@ def test_attachment_serializer_existing_file(factories, to_api_date):
"urls": {
"source": attachment.url,
"original": federation_utils.full_url(attachment.file.url),
"small_square_crop": federation_utils.full_url(
attachment.file.crop["50x50"].url
),
"medium_square_crop": federation_utils.full_url(
attachment.file.crop["200x200"].url
),
......@@ -225,6 +228,9 @@ def test_attachment_serializer_remote_file(factories, to_api_date):
"urls": {
"source": attachment.url,
"original": federation_utils.full_url(proxy_url + "?next=original"),
"small_square_crop": federation_utils.full_url(
proxy_url + "?next=small_square_crop"
),
"medium_square_crop": federation_utils.full_url(
proxy_url + "?next=medium_square_crop"
),
......
import logging
import pytest
from funkwhale_api.contrib.archivedl import tasks
def test_check_existing_download_task(factories, caplog, mocker):
logger = logging.getLogger("funkwhale_api.contrib.archivedl")
caplog.set_level(logging.INFO)
logger.addHandler(caplog.handler)
upload = factories["music.Upload"](
third_party_provider="archive-dl", import_status="pending"
)
mocker.patch("funkwhale_api.contrib.archivedl.tasks.fetch_json", return_value={})
tasks.archive_download(track_id=upload.track.id, conf={})
assert (
"Upload for this track already exist or is pending. Stopping task"
in caplog.text
)
def test_check_last_third_party_queries(factories, caplog, mocker):
logger = logging.getLogger("funkwhale_api.contrib.archivedl")
caplog.set_level(logging.INFO)
logger.addHandler(caplog.handler)
factories["music.Upload"].create_batch(
size=10, third_party_provider="archive-dl", import_status="pending"
)
track = factories["music.Track"]()
mocker.patch("funkwhale_api.contrib.archivedl.tasks.fetch_json", return_value={})
with pytest.raises(KeyError):
tasks.archive_download(track_id=track.id, conf={})
assert (
"Last archive.org query was too recent. Trying to wait 2 seconds..."
in caplog.text
)
import pytest
from funkwhale_api.audio.serializers import ChannelSerializer
from funkwhale_api.common import serializers as common_serializers
from funkwhale_api.federation import api_serializers, serializers
from funkwhale_api.users import serializers as users_serializers
......@@ -128,6 +129,7 @@ def test_fetch_serializer_no_obj(factories, to_api_date):
"status": fetch.status,
"detail": fetch.detail,
"object": None,
"type": None,
"actor": serializers.APIActorSerializer(fetch.actor).data,
}
......@@ -135,22 +137,28 @@ def test_fetch_serializer_no_obj(factories, to_api_date):
@pytest.mark.parametrize(
"object_factory, expected_type, expected_id",
"object_factory, expected_type, serializer_class",
[
("music.Album", "album", "id"),
("music.Artist", "artist", "id"),
("music.Track", "track", "id"),
("music.Library", "library", "uuid"),
("music.Upload", "upload", "uuid"),
("audio.Channel", "channel", "uuid"),
("federation.Actor", "account", "full_username"),
("music.Album", "album", serializers.AlbumSerializer),
("music.Artist", "artist", serializers.ArtistSerializer),
("music.Track", "track", serializers.TrackSerializer),
("audio.Channel", "channel", ChannelSerializer),
("federation.Actor", "account", serializers.APIActorSerializer),
("playlists.Playlist", "playlist", serializers.PlaylistSerializer),
],
)
def test_fetch_serializer_with_object(
object_factory, expected_type, expected_id, factories, to_api_date
object_factory, expected_type, serializer_class, factories, to_api_date
):
obj = factories[object_factory]()
fetch = factories["federation.Fetch"](object=obj)
# Serialize the object
if serializer_class:
object_data = serializer_class(obj).data
else:
object_data = {"uuid": getattr(obj, "uuid", None)}
expected = {
"id": fetch.pk,
"url": fetch.url,
......@@ -158,7 +166,10 @@ def test_fetch_serializer_with_object(
"fetch_date": None,
"status": fetch.status,
"detail": fetch.detail,
"object": {"type": expected_type, expected_id: getattr(obj, expected_id)},
"object": {
**object_data,
},
"type": expected_type,
"actor": serializers.APIActorSerializer(fetch.actor).data,
}
......@@ -175,6 +186,7 @@ def test_fetch_serializer_unhandled_obj(factories, to_api_date):
"status": fetch.status,
"detail": fetch.detail,
"object": None,
"type": None,
"actor": serializers.APIActorSerializer(fetch.actor).data,
}
......
......@@ -35,6 +35,29 @@ def test_user_can_fetch_library_using_url(mocker, factories, logged_in_api_clien
assert response.data["results"] == [api_serializers.LibrarySerializer(library).data]
def test_user_can_fetch_playlist_library_using_url(
mocker, factories, logged_in_api_client
):
pl_library = factories["music.Library"]()
upload = factories["music.Upload"]()
upload.playlist_libraries.add(pl_library)
mocked_retrieve = mocker.patch(
"funkwhale_api.federation.utils.retrieve_ap_object", return_value=pl_library
)
url = reverse("api:v1:federation:libraries-fetch")
response = logged_in_api_client.post(url, {"fid": pl_library.fid})
assert mocked_retrieve.call_count == 1
args = mocked_retrieve.call_args
assert args[0] == (pl_library.fid,)
assert args[1]["queryset"].model == views.MusicLibraryViewSet.queryset.model
assert args[1]["serializer_class"] == serializers.LibrarySerializer
assert response.status_code == 200
assert response.data["results"] == [
api_serializers.LibrarySerializer(pl_library).data
]
def test_user_can_schedule_library_scan(mocker, factories, logged_in_api_client):
actor = logged_in_api_client.user.create_actor()
library = factories["music.Library"](privacy_level="everyone")
......@@ -243,7 +266,7 @@ def test_can_fetch_using_url_synchronous(
fetch_task = mocker.patch.object(tasks, "fetch", side_effect=fake_task)
url = reverse("api:v1:federation:fetches-list")
data = {"object": object_id}
data = {"object_uri": object_id}
response = logged_in_api_client.post(url, data)
assert response.status_code == 201
......@@ -266,7 +289,7 @@ def test_fetch_duplicate(factories, logged_in_api_client, settings, now):
creation_date=now - datetime.timedelta(seconds=59),
)
url = reverse("api:v1:federation:fetches-list")
data = {"object": object_id}
data = {"object_uri": object_id}
response = logged_in_api_client.post(url, data)
assert response.status_code == 201
assert response.data == api_serializers.FetchSerializer(duplicate).data
......@@ -286,7 +309,7 @@ def test_fetch_duplicate_bypass_with_force(
creation_date=now - datetime.timedelta(seconds=59),
)
url = reverse("api:v1:federation:fetches-list")
data = {"object": object_id, "force": True}
data = {"object_uri": object_id, "force": True}
response = logged_in_api_client.post(url, data)
fetch = actor.fetches.latest("id")
......
......@@ -1268,6 +1268,7 @@ def test_inbox_update_playlist(factories, mocker):
playlist_data = serializers.PlaylistSerializer(playlist_updated).data
playlist_data["id"] = str(playlist.fid)
playlist_updated.delete()
routes.inbox_update_playlist(
{"object": playlist_data},
......
This diff is collapsed.
This diff is collapsed.
File added
This diff is collapsed.