diff --git a/api/funkwhale_api/music/fake_data.py b/api/funkwhale_api/music/fake_data.py index 256545dd4..9f74c1f72 100644 --- a/api/funkwhale_api/music/fake_data.py +++ b/api/funkwhale_api/music/fake_data.py @@ -5,7 +5,9 @@ Populates the database with fake data import logging import random +from funkwhale_api.audio import factories as audio_factories from funkwhale_api.cli import users +from funkwhale_api.favorites import factories as favorites_factories from funkwhale_api.federation import factories as federation_factories from funkwhale_api.history import factories as history_factories from funkwhale_api.music import factories as music_factories @@ -15,7 +17,7 @@ from funkwhale_api.users import models, serializers logger = logging.getLogger(__name__) -def create_data(count=2, super_user_name=None): +def create_data(super_user_name=None): super_user = None if super_user_name: try: @@ -35,7 +37,7 @@ def create_data(count=2, super_user_name=None): in errors[0] ): print( - f"Superuser {super_user_name} already in db. Skipping fake-data creation" + f"Superuser {super_user_name} already in db. Skipping superuser creation" ) super_user = models.User.objects.get(username=super_user_name) continue @@ -43,35 +45,103 @@ def create_data(count=2, super_user_name=None): raise e print(f"Superuser with username {super_user_name} and password `funkwhale`") - library = federation_factories.MusicLibraryFactory( - actor=( - super_user.actor if super_user else federation_factories.ActorFactory() - ), - local=True, + library = federation_factories.MusicLibraryFactory( + actor=(super_user.actor if super_user else federation_factories.ActorFactory()), + local=True, + ) + uploads = music_factories.UploadFactory.create_batch( + size=random.randint(3, 18), + playable=True, + library=library, + local=True, + ) + for upload in uploads[:2]: + history_factories.ListeningFactory( + track=upload.track, actor=upload.library.actor ) - uploads = music_factories.UploadFactory.create_batch( - size=random.randint(3, 18), - playable=True, - library=library, - local=True, + favorites_factories.TrackFavorite( + track=upload.track, actor=upload.library.actor ) - for upload in uploads: - history_factories.ListeningFactory( - track=upload.track, actor=upload.library.actor - ) - print("Created fid", upload.track.fid) - playlist = playlist_factories.PlaylistFactory( - name="playlist test public", - privacy_level="everyone", - actor=( - super_user.actor if super_user else federation_factories.ActorFactory() - ), - ) - playlist_factories.PlaylistTrackFactory(playlist=playlist, track=upload.track) - federation_factories.LibraryFollowFactory.create_batch( - size=random.randint(3, 18), actor=super_user.actor - ) + print("Created fid", upload.track.fid) + + playlist = playlist_factories.PlaylistFactory( + name="playlist test public", + privacy_level="everyone", + actor=(super_user.actor if super_user else federation_factories.ActorFactory()), + ) + playlist_factories.PlaylistTrackFactory(playlist=playlist, track=upload.track) + federation_factories.LibraryFollowFactory.create_batch( + size=random.randint(3, 18), actor=super_user.actor + ) + + # my podcast + my_podcast_library = federation_factories.MusicLibraryFactory( + actor=(super_user.actor if super_user else federation_factories.ActorFactory()), + local=True, + ) + my_podcast_channel = audio_factories.ChannelFactory( + library=my_podcast_library, + attributed_to=super_user.actor, + artist__content_category="podcast", + ) + my_podcast_channel_serie = music_factories.AlbumFactory( + artist_credit__artist=my_podcast_channel.artist + ) + music_factories.TrackFactory.create_batch( + size=random.randint(3, 6), + artist_credit__artist=my_podcast_channel.artist, + album=my_podcast_channel_serie, + ) + + # podcast + podcast_channel = audio_factories.ChannelFactory(artist__content_category="podcast") + podcast_channel_serie = music_factories.AlbumFactory( + artist_credit__artist=podcast_channel.artist + ) + music_factories.TrackFactory.create_batch( + size=random.randint(3, 6), + artist_credit__artist=podcast_channel.artist, + album=podcast_channel_serie, + ) + + audio_factories.SubscriptionFactory( + approved=True, target=podcast_channel.actor, actor=super_user.actor + ) + + # my artist channel + my_artist_library = federation_factories.MusicLibraryFactory( + actor=(super_user.actor if super_user else federation_factories.ActorFactory()), + local=True, + ) + my_artist_channel = audio_factories.ChannelFactory( + library=my_artist_library, + attributed_to=super_user.actor, + artist__content_category="music", + ) + my_artist_channel_serie = music_factories.AlbumFactory( + artist_credit__artist=my_artist_channel.artist + ) + music_factories.TrackFactory.create_batch( + size=random.randint(3, 6), + artist_credit__artist=my_artist_channel.artist, + album=my_artist_channel_serie, + ) + + # artist channel + artist_channel = audio_factories.ChannelFactory(artist__content_category="artist") + artist_channel_serie = music_factories.AlbumFactory( + artist_credit__artist=artist_channel.artist + ) + music_factories.TrackFactory.create_batch( + size=random.randint(3, 6), + artist_credit__artist=artist_channel.artist, + album=artist_channel_serie, + ) + + audio_factories.SubscriptionFactory( + approved=True, target=artist_channel.actor, actor=super_user.actor + ) if __name__ == "__main__": diff --git a/docs/developer/data.md b/docs/developer/data.md new file mode 100644 index 000000000..4fa7234d1 --- /dev/null +++ b/docs/developer/data.md @@ -0,0 +1,6 @@ +# Data structure + +## Channel + +- has a one to one relationship with `Artist`, `Library`, `Actor` (unique to the channel, used for federation), `Actor` (attributed_to, the actor owning the channel). +- can be an Artist channel if the channel.artist.content_category == "music", or a Podcast channel if channel.artist.content_category == "podcast", in which case artist.album are podcast series,and tracks are podcast episodes. diff --git a/docs/developer/setup/docker.md b/docs/developer/setup/docker.md index a23ee46d8..283259ecc 100644 --- a/docs/developer/setup/docker.md +++ b/docs/developer/setup/docker.md @@ -264,18 +264,21 @@ You can create local data to mimic a live environment. Add some fake data to populate the database. The following command creates 25 artists with random albums, tracks, and metadata. ```sh -artists=25 # Adds 25 fake artists -command="from funkwhale_api.music import fake_data; fake_data.create_data($artists)" +command="from funkwhale_api.music import fake_data; fake_data.create_data()" echo $command | docker compose run --rm -T api funkwhale-manage shell -i python ``` This will launch a development funkwhale instance with a super user having `COMPOSE_PROJECT_NAME` as username and `funkwhale` as password. Libraries, listenings and music data will be associated with the superuser : ```sh -export COMPOSE_PROJECT_NAME=node2 ; export VUE_PORT=8882 ; docker compose run --rm api funkwhale-manage migrate ; echo "from funkwhale_api.music import fake_data; fake_data.create_data(super_user_name=\"$COMPOSE_PROJECT_NAME\")" | docker compose run --rm -T api funkwhale-manage shell -i python ; docker compose up +export COMPOSE_PROJECT_NAME=node1 ; export VUE_PORT=8882 ; docker compose run --rm api funkwhale-manage migrate ; echo "from funkwhale_api.music import fake_data; fake_data.create_data(super_user_name=\"$COMPOSE_PROJECT_NAME\")" | docker compose run --rm -T api funkwhale-manage shell -i python ``` +```{note} +Username `funkwhale` is not permitted. You need to export COMPOSE_PROJECT_NAME to make sure it's different from `funkwhale` +``` + ### Lifecycle Recycle individual containers: