deezer-python-gql 0.18.0__tar.gz → 0.20.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. {deezer_python_gql-0.18.0/deezer_python_gql.egg-info → deezer_python_gql-0.20.0}/PKG-INFO +65 -26
  2. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/README.md +63 -24
  3. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/base_client.py +15 -0
  4. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/__init__.py +119 -0
  5. deezer_python_gql-0.20.0/deezer_python_gql/generated/ban_artist_from_recommendation.py +26 -0
  6. deezer_python_gql-0.20.0/deezer_python_gql/generated/ban_track_from_recommendation.py +26 -0
  7. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/base_client.py +15 -0
  8. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/client.py +639 -74
  9. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/enums.py +10 -0
  10. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/fragments.py +28 -0
  11. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_artist.py +14 -0
  12. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_audiobook.py +1 -0
  13. deezer_python_gql-0.20.0/deezer_python_gql/generated/get_banned_artists.py +51 -0
  14. deezer_python_gql-0.20.0/deezer_python_gql/generated/get_banned_tracks.py +51 -0
  15. deezer_python_gql-0.20.0/deezer_python_gql/generated/get_family.py +34 -0
  16. deezer_python_gql-0.20.0/deezer_python_gql/generated/get_flow_tuner.py +25 -0
  17. deezer_python_gql-0.20.0/deezer_python_gql/generated/get_infinite_track_mix.py +24 -0
  18. deezer_python_gql-0.20.0/deezer_python_gql/generated/get_latest_podcast_episodes.py +27 -0
  19. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_made_for_me.py +1 -0
  20. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_smart_tracklist.py +1 -0
  21. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_track.py +4 -0
  22. deezer_python_gql-0.20.0/deezer_python_gql/generated/get_tracks_by_ids.py +22 -0
  23. deezer_python_gql-0.20.0/deezer_python_gql/generated/set_flow_discovery_tuner.py +20 -0
  24. deezer_python_gql-0.20.0/deezer_python_gql/generated/unban_artist_from_recommendation.py +26 -0
  25. deezer_python_gql-0.20.0/deezer_python_gql/generated/unban_track_from_recommendation.py +26 -0
  26. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0/deezer_python_gql.egg-info}/PKG-INFO +65 -26
  27. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql.egg-info/SOURCES.txt +12 -0
  28. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql.egg-info/requires.txt +1 -1
  29. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/pyproject.toml +7 -2
  30. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/tests/test_client.py +210 -1
  31. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/LICENSE +0 -0
  32. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/MANIFEST.in +0 -0
  33. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/__init__.py +0 -0
  34. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/add_album_to_favorite.py +0 -0
  35. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/add_artist_to_favorite.py +0 -0
  36. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/add_audiobook_to_favorite.py +0 -0
  37. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/add_playlist_to_favorite.py +0 -0
  38. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/add_podcast_to_favorite.py +0 -0
  39. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/add_track_to_favorite.py +0 -0
  40. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/add_tracks_to_playlist.py +0 -0
  41. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/base_model.py +0 -0
  42. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/bookmark_podcast_episode.py +0 -0
  43. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/create_playlist.py +0 -0
  44. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/delete_playlist.py +0 -0
  45. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_album.py +0 -0
  46. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_artist_mix.py +0 -0
  47. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_audiobook_chapter.py +0 -0
  48. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_charts.py +0 -0
  49. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_favorite_albums.py +0 -0
  50. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_favorite_artists.py +0 -0
  51. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_favorite_audiobooks.py +0 -0
  52. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_favorite_playlists.py +0 -0
  53. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_favorite_podcasts.py +0 -0
  54. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_favorite_tracks.py +0 -0
  55. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_flow.py +0 -0
  56. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_flow_batch.py +0 -0
  57. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_flow_config_tracks.py +0 -0
  58. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_flow_configs.py +0 -0
  59. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_livestream.py +0 -0
  60. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_me.py +0 -0
  61. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_music_together_affinity.py +0 -0
  62. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_music_together_group.py +0 -0
  63. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_music_together_groups.py +0 -0
  64. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_personal_tracks.py +0 -0
  65. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_playlist.py +0 -0
  66. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_podcast.py +0 -0
  67. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_podcast_episode.py +0 -0
  68. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_podcast_episode_bookmarks.py +0 -0
  69. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_podcast_episodes_by_ids.py +0 -0
  70. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_recently_played.py +0 -0
  71. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_recommendations.py +0 -0
  72. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_similar_artists.py +0 -0
  73. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_similar_tracks.py +0 -0
  74. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_track_mix.py +0 -0
  75. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_user_charts.py +0 -0
  76. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/get_user_playlists.py +0 -0
  77. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/input_types.py +0 -0
  78. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/mark_as_not_played_podcast_episode.py +0 -0
  79. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/mark_as_played_podcast_episode.py +0 -0
  80. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/music_together_create_group.py +0 -0
  81. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/music_together_generate_group_name.py +0 -0
  82. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/music_together_join_group.py +0 -0
  83. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/music_together_leave_group.py +0 -0
  84. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/music_together_refresh_suggested_tracklist.py +0 -0
  85. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/music_together_update_group_settings.py +0 -0
  86. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/remove_album_from_favorite.py +0 -0
  87. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/remove_artist_from_favorite.py +0 -0
  88. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/remove_audiobook_from_favorite.py +0 -0
  89. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/remove_playlist_from_favorite.py +0 -0
  90. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/remove_podcast_from_favorite.py +0 -0
  91. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/remove_track_from_favorite.py +0 -0
  92. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/remove_tracks_from_playlist.py +0 -0
  93. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/search.py +0 -0
  94. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/search_flows.py +0 -0
  95. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/unbookmark_podcast_episode.py +0 -0
  96. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/generated/update_playlist.py +0 -0
  97. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql/py.typed +0 -0
  98. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql.egg-info/dependency_links.txt +0 -0
  99. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql.egg-info/not-zip-safe +0 -0
  100. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/deezer_python_gql.egg-info/top_level.txt +0 -0
  101. {deezer_python_gql-0.18.0 → deezer_python_gql-0.20.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deezer-python-gql
3
- Version: 0.18.0
3
+ Version: 0.20.0
4
4
  Summary: Async typed Python client for Deezer's Pipe GraphQL API.
5
5
  Author-email: Julian Daberkow <jdaberkow@users.noreply.github.com>
6
6
  License: Apache-2.0
@@ -22,7 +22,7 @@ Requires-Dist: pre-commit-hooks==6.0.0; extra == "test"
22
22
  Requires-Dist: pytest==9.1.1; extra == "test"
23
23
  Requires-Dist: pytest-asyncio==1.4.0; extra == "test"
24
24
  Requires-Dist: pytest-cov==7.1.0; extra == "test"
25
- Requires-Dist: ruff==0.16.8; extra == "test"
25
+ Requires-Dist: ruff==0.16.9; extra == "test"
26
26
  Provides-Extra: dev
27
27
  Requires-Dist: ariadne-codegen[subscriptions]; extra == "dev"
28
28
  Dynamic: license-file
@@ -84,18 +84,18 @@ asyncio.run(main())
84
84
 
85
85
  ### Content Retrieval
86
86
 
87
- | Method | Description |
88
- | --------------------------------------------- | --------------------------------------------------------------- |
89
- | `get_me()` | Current authenticated user |
90
- | `get_track(track_id)` | Full track details — ISRC, media tokens, lyrics, contributors |
91
- | `get_album(album_id)` | Album with cover, label, paginated tracks, fallback |
92
- | `get_artist(artist_id)` | Artist with bio, top tracks, albums (ordered by release date) |
93
- | `get_playlist(playlist_id)` | Playlist with owner, picture, paginated tracks |
94
- | `get_livestream(livestream_id)` | Livestream (radio station) with streaming URLs and codec info |
95
- | `get_podcast(podcast_id)` | Podcast with paginated episodes and rights info |
96
- | `get_podcast_episode(podcast_episode_id)` | Single episode with media URL, codec, and parent podcast ref |
97
- | `get_audiobook(audiobook_id)` | Audiobook with paginated chapters, contributors, and fallback |
98
- | `get_audiobook_chapter(audiobook_chapter_id)` | Chapter with media token, estimated sizes, and streaming rights |
87
+ | Method | Description |
88
+ | --------------------------------------------- | ----------------------------------------------------------------------------------------- |
89
+ | `get_me()` | Current authenticated user |
90
+ | `get_track(track_id)` | Full track details — ISRC, gain, ban state, media tokens, lyrics, contributors |
91
+ | `get_album(album_id)` | Album with cover, label, paginated tracks, fallback |
92
+ | `get_artist(artist_id)` | Artist with bio, social links, hero picture, top tracks, albums (ordered by release date) |
93
+ | `get_playlist(playlist_id)` | Playlist with owner, picture, paginated tracks |
94
+ | `get_livestream(livestream_id)` | Livestream (radio station) with streaming URLs and codec info |
95
+ | `get_podcast(podcast_id)` | Podcast with paginated episodes and rights info |
96
+ | `get_podcast_episode(podcast_episode_id)` | Single episode with media URL, codec, and parent podcast ref |
97
+ | `get_audiobook(audiobook_id)` | Audiobook with UPC, paginated chapters, contributors, and fallback |
98
+ | `get_audiobook_chapter(audiobook_chapter_id)` | Chapter with media token, estimated sizes, and streaming rights |
99
99
 
100
100
  ### Search & Discovery
101
101
 
@@ -106,12 +106,14 @@ asyncio.run(main())
106
106
  | `get_similar_tracks(track_id, nb)` | Recommended tracks based on a given track |
107
107
  | `get_artist_mix(artist_ids, limit)` | Track mix blended from given artists |
108
108
  | `get_track_mix(track_ids, limit)` | Track mix blended around given tracks |
109
+ | `get_infinite_track_mix(track_ids, limit, ...)` | Track IDs for an endless mix, input tracks left out (at least 40, cost ~10000) |
110
+ | `get_tracks_by_ids(ids)` | Several tracks in one request, unknown IDs come back as `None` |
109
111
  | `get_flow()` | User's default Flow with tracks |
110
112
  | `get_flow_batch()` | 4 batches of Flow tracks in one request (via GraphQL aliases) |
111
113
  | `get_flow_configs(moods_first, genres_first)` | Mood & genre flow config lists for discovery |
112
114
  | `get_flow_config_tracks(flow_config_id)` | Tracks for a specific mood/genre flow config |
113
115
  | `get_made_for_me(first)` | "Made For You" SmartTracklist & Flow items |
114
- | `get_smart_tracklist(smart_tracklist_id, first)` | Smart tracklist with paginated tracks |
116
+ | `get_smart_tracklist(smart_tracklist_id, first)` | Smart tracklist with expiry and paginated tracks |
115
117
  | `get_charts(country_code, ...)` | Country charts — tracks, albums, artists, playlists |
116
118
  | `get_recommendations(playlists_first, ...)` | Personalized recommendations across categories |
117
119
  | `get_recently_played(first)` | Recently played mixed content (albums, playlists, artists...) |
@@ -119,17 +121,22 @@ asyncio.run(main())
119
121
 
120
122
  ### Library & Favorites
121
123
 
122
- | Method | Description |
123
- | --------------------------------------------- | ----------------------------------------------------------- |
124
- | `get_favorite_artists(first, after)` | Paginated favorite artists |
125
- | `get_favorite_albums(first, after)` | Paginated favorite albums |
126
- | `get_favorite_tracks(first, after)` | Paginated favorite tracks |
127
- | `get_favorite_playlists(first, after)` | Paginated favorite playlists |
128
- | `get_favorite_podcasts(first, after)` | Paginated favorite podcasts |
129
- | `get_favorite_audiobooks()` | Favorite audiobook IDs with dates (via deprecated endpoint) |
130
- | `get_podcast_episode_bookmarks(first, after)` | Bookmarked podcast episodes with playback position |
131
- | `get_user_playlists(first, after)` | User's own playlists (not just favorites) |
132
- | `get_personal_tracks(first, after)` | User's uploaded/personal tracks (restricted access) |
124
+ | Method | Description |
125
+ | --------------------------------------------- | --------------------------------------------------------------- |
126
+ | `get_favorite_artists(first, after)` | Paginated favorite artists |
127
+ | `get_favorite_albums(first, after)` | Paginated favorite albums |
128
+ | `get_favorite_tracks(first, after)` | Paginated favorite tracks |
129
+ | `get_favorite_playlists(first, after)` | Paginated favorite playlists |
130
+ | `get_favorite_podcasts(first, after)` | Paginated favorite podcasts |
131
+ | `get_favorite_audiobooks()` | Favorite audiobook IDs with dates (via deprecated endpoint) |
132
+ | `get_podcast_episode_bookmarks(first, after)` | Bookmarked podcast episodes with playback position |
133
+ | `get_user_playlists(first, after)` | User's own playlists (not just favorites) |
134
+ | `get_personal_tracks(first, after)` | User's uploaded/personal tracks (restricted access) |
135
+ | `get_latest_podcast_episodes()` | Latest episodes of favorite podcasts (IDs + dates, cost ~15000) |
136
+ | `get_banned_tracks(first, after)` | Tracks banned from recommendations, with ban date |
137
+ | `get_banned_artists(first, after)` | Artists banned from recommendations, with ban date |
138
+ | `get_flow_tuner()` | Flow tuner: `DEFAULT` or `DISCOVERY` |
139
+ | `get_family()` | Deezer Family members, with `isLoggableAs` for usable profiles |
133
140
 
134
141
  ### Music Together (Collaborative Playlists)
135
142
 
@@ -158,6 +165,23 @@ asyncio.run(main())
158
165
  | `add_audiobook_to_favorite(audiobook_id)` | Add audiobook to favorites (deprecated but functional) |
159
166
  | `remove_audiobook_from_favorite(audiobook_id)` | Remove audiobook from favorites (deprecated but functional) |
160
167
 
168
+ ### Recommendation Bans
169
+
170
+ Keep a track or artist out of the user's recommendations (Flow, mixes).
171
+
172
+ | Method | Description |
173
+ | --------------------------------------------- | -------------------------------------- |
174
+ | `ban_track_from_recommendation(track_id)` | Keep track out of recommendations |
175
+ | `unban_track_from_recommendation(track_id)` | Allow track back into recommendations |
176
+ | `ban_artist_from_recommendation(artist_id)` | Keep artist out of recommendations |
177
+ | `unban_artist_from_recommendation(artist_id)` | Allow artist back into recommendations |
178
+
179
+ ### Flow
180
+
181
+ | Method | Description |
182
+ | ------------------------------------------- | --------------------------------------------- |
183
+ | `set_flow_discovery_tuner(discovery_tuner)` | Switch Flow between `DEFAULT` and `DISCOVERY` |
184
+
161
185
  ### Playlist Management
162
186
 
163
187
  | Method | Description |
@@ -263,6 +287,21 @@ If the ARL is rejected (bad or expired), the client raises
263
287
  `GraphQLClientAuthError` — catch it to prompt for a new ARL instead of retrying.
264
288
  Transient server errors raise `GraphQLClientHttpError` instead.
265
289
 
290
+ ### Deezer Family profiles
291
+
292
+ Profiles of a Deezer Family have no ARL of their own, they share the login of the
293
+ Family admin. Pass `account_id` to act as one of them:
294
+
295
+ ```python
296
+ family = (await client.get_family()).family
297
+ profile = next(m for m in family.linked if m.permissions.is_loggable_as)
298
+ profile_client = DeezerGQLClient(arl="ADMIN_ARL", account_id=profile.id)
299
+ ```
300
+
301
+ Members with their own login (independent accounts) are not loggable, they need their
302
+ own ARL. If Deezer does not sign in as the profile, the client raises
303
+ `GraphQLClientAuthError`.
304
+
266
305
  ## License
267
306
 
268
307
  Apache-2.0
@@ -55,18 +55,18 @@ asyncio.run(main())
55
55
 
56
56
  ### Content Retrieval
57
57
 
58
- | Method | Description |
59
- | --------------------------------------------- | --------------------------------------------------------------- |
60
- | `get_me()` | Current authenticated user |
61
- | `get_track(track_id)` | Full track details — ISRC, media tokens, lyrics, contributors |
62
- | `get_album(album_id)` | Album with cover, label, paginated tracks, fallback |
63
- | `get_artist(artist_id)` | Artist with bio, top tracks, albums (ordered by release date) |
64
- | `get_playlist(playlist_id)` | Playlist with owner, picture, paginated tracks |
65
- | `get_livestream(livestream_id)` | Livestream (radio station) with streaming URLs and codec info |
66
- | `get_podcast(podcast_id)` | Podcast with paginated episodes and rights info |
67
- | `get_podcast_episode(podcast_episode_id)` | Single episode with media URL, codec, and parent podcast ref |
68
- | `get_audiobook(audiobook_id)` | Audiobook with paginated chapters, contributors, and fallback |
69
- | `get_audiobook_chapter(audiobook_chapter_id)` | Chapter with media token, estimated sizes, and streaming rights |
58
+ | Method | Description |
59
+ | --------------------------------------------- | ----------------------------------------------------------------------------------------- |
60
+ | `get_me()` | Current authenticated user |
61
+ | `get_track(track_id)` | Full track details — ISRC, gain, ban state, media tokens, lyrics, contributors |
62
+ | `get_album(album_id)` | Album with cover, label, paginated tracks, fallback |
63
+ | `get_artist(artist_id)` | Artist with bio, social links, hero picture, top tracks, albums (ordered by release date) |
64
+ | `get_playlist(playlist_id)` | Playlist with owner, picture, paginated tracks |
65
+ | `get_livestream(livestream_id)` | Livestream (radio station) with streaming URLs and codec info |
66
+ | `get_podcast(podcast_id)` | Podcast with paginated episodes and rights info |
67
+ | `get_podcast_episode(podcast_episode_id)` | Single episode with media URL, codec, and parent podcast ref |
68
+ | `get_audiobook(audiobook_id)` | Audiobook with UPC, paginated chapters, contributors, and fallback |
69
+ | `get_audiobook_chapter(audiobook_chapter_id)` | Chapter with media token, estimated sizes, and streaming rights |
70
70
 
71
71
  ### Search & Discovery
72
72
 
@@ -77,12 +77,14 @@ asyncio.run(main())
77
77
  | `get_similar_tracks(track_id, nb)` | Recommended tracks based on a given track |
78
78
  | `get_artist_mix(artist_ids, limit)` | Track mix blended from given artists |
79
79
  | `get_track_mix(track_ids, limit)` | Track mix blended around given tracks |
80
+ | `get_infinite_track_mix(track_ids, limit, ...)` | Track IDs for an endless mix, input tracks left out (at least 40, cost ~10000) |
81
+ | `get_tracks_by_ids(ids)` | Several tracks in one request, unknown IDs come back as `None` |
80
82
  | `get_flow()` | User's default Flow with tracks |
81
83
  | `get_flow_batch()` | 4 batches of Flow tracks in one request (via GraphQL aliases) |
82
84
  | `get_flow_configs(moods_first, genres_first)` | Mood & genre flow config lists for discovery |
83
85
  | `get_flow_config_tracks(flow_config_id)` | Tracks for a specific mood/genre flow config |
84
86
  | `get_made_for_me(first)` | "Made For You" SmartTracklist & Flow items |
85
- | `get_smart_tracklist(smart_tracklist_id, first)` | Smart tracklist with paginated tracks |
87
+ | `get_smart_tracklist(smart_tracklist_id, first)` | Smart tracklist with expiry and paginated tracks |
86
88
  | `get_charts(country_code, ...)` | Country charts — tracks, albums, artists, playlists |
87
89
  | `get_recommendations(playlists_first, ...)` | Personalized recommendations across categories |
88
90
  | `get_recently_played(first)` | Recently played mixed content (albums, playlists, artists...) |
@@ -90,17 +92,22 @@ asyncio.run(main())
90
92
 
91
93
  ### Library & Favorites
92
94
 
93
- | Method | Description |
94
- | --------------------------------------------- | ----------------------------------------------------------- |
95
- | `get_favorite_artists(first, after)` | Paginated favorite artists |
96
- | `get_favorite_albums(first, after)` | Paginated favorite albums |
97
- | `get_favorite_tracks(first, after)` | Paginated favorite tracks |
98
- | `get_favorite_playlists(first, after)` | Paginated favorite playlists |
99
- | `get_favorite_podcasts(first, after)` | Paginated favorite podcasts |
100
- | `get_favorite_audiobooks()` | Favorite audiobook IDs with dates (via deprecated endpoint) |
101
- | `get_podcast_episode_bookmarks(first, after)` | Bookmarked podcast episodes with playback position |
102
- | `get_user_playlists(first, after)` | User's own playlists (not just favorites) |
103
- | `get_personal_tracks(first, after)` | User's uploaded/personal tracks (restricted access) |
95
+ | Method | Description |
96
+ | --------------------------------------------- | --------------------------------------------------------------- |
97
+ | `get_favorite_artists(first, after)` | Paginated favorite artists |
98
+ | `get_favorite_albums(first, after)` | Paginated favorite albums |
99
+ | `get_favorite_tracks(first, after)` | Paginated favorite tracks |
100
+ | `get_favorite_playlists(first, after)` | Paginated favorite playlists |
101
+ | `get_favorite_podcasts(first, after)` | Paginated favorite podcasts |
102
+ | `get_favorite_audiobooks()` | Favorite audiobook IDs with dates (via deprecated endpoint) |
103
+ | `get_podcast_episode_bookmarks(first, after)` | Bookmarked podcast episodes with playback position |
104
+ | `get_user_playlists(first, after)` | User's own playlists (not just favorites) |
105
+ | `get_personal_tracks(first, after)` | User's uploaded/personal tracks (restricted access) |
106
+ | `get_latest_podcast_episodes()` | Latest episodes of favorite podcasts (IDs + dates, cost ~15000) |
107
+ | `get_banned_tracks(first, after)` | Tracks banned from recommendations, with ban date |
108
+ | `get_banned_artists(first, after)` | Artists banned from recommendations, with ban date |
109
+ | `get_flow_tuner()` | Flow tuner: `DEFAULT` or `DISCOVERY` |
110
+ | `get_family()` | Deezer Family members, with `isLoggableAs` for usable profiles |
104
111
 
105
112
  ### Music Together (Collaborative Playlists)
106
113
 
@@ -129,6 +136,23 @@ asyncio.run(main())
129
136
  | `add_audiobook_to_favorite(audiobook_id)` | Add audiobook to favorites (deprecated but functional) |
130
137
  | `remove_audiobook_from_favorite(audiobook_id)` | Remove audiobook from favorites (deprecated but functional) |
131
138
 
139
+ ### Recommendation Bans
140
+
141
+ Keep a track or artist out of the user's recommendations (Flow, mixes).
142
+
143
+ | Method | Description |
144
+ | --------------------------------------------- | -------------------------------------- |
145
+ | `ban_track_from_recommendation(track_id)` | Keep track out of recommendations |
146
+ | `unban_track_from_recommendation(track_id)` | Allow track back into recommendations |
147
+ | `ban_artist_from_recommendation(artist_id)` | Keep artist out of recommendations |
148
+ | `unban_artist_from_recommendation(artist_id)` | Allow artist back into recommendations |
149
+
150
+ ### Flow
151
+
152
+ | Method | Description |
153
+ | ------------------------------------------- | --------------------------------------------- |
154
+ | `set_flow_discovery_tuner(discovery_tuner)` | Switch Flow between `DEFAULT` and `DISCOVERY` |
155
+
132
156
  ### Playlist Management
133
157
 
134
158
  | Method | Description |
@@ -234,6 +258,21 @@ If the ARL is rejected (bad or expired), the client raises
234
258
  `GraphQLClientAuthError` — catch it to prompt for a new ARL instead of retrying.
235
259
  Transient server errors raise `GraphQLClientHttpError` instead.
236
260
 
261
+ ### Deezer Family profiles
262
+
263
+ Profiles of a Deezer Family have no ARL of their own, they share the login of the
264
+ Family admin. Pass `account_id` to act as one of them:
265
+
266
+ ```python
267
+ family = (await client.get_family()).family
268
+ profile = next(m for m in family.linked if m.permissions.is_loggable_as)
269
+ profile_client = DeezerGQLClient(arl="ADMIN_ARL", account_id=profile.id)
270
+ ```
271
+
272
+ Members with their own login (independent accounts) are not loggable, they need their
273
+ own ARL. If Deezer does not sign in as the profile, the client raises
274
+ `GraphQLClientAuthError`.
275
+
237
276
  ## License
238
277
 
239
278
  Apache-2.0
@@ -123,6 +123,9 @@ class DeezerBaseClient:
123
123
  :param url: GraphQL endpoint URL (defaults to Pipe API).
124
124
  :param session: Optional pre-configured aiohttp.ClientSession.
125
125
  If provided, the caller is responsible for closing it.
126
+ :param account_id: Optional Deezer Family profile to act as. A profile has no
127
+ ARL of its own; it signs in with the ARL of the Family admin. Only profiles
128
+ that ``get_family()`` marks as ``isLoggableAs`` can be used.
126
129
  """
127
130
 
128
131
  PIPE_URL = "https://pipe.deezer.com/api"
@@ -136,9 +139,11 @@ class DeezerBaseClient:
136
139
  arl: str,
137
140
  url: str = PIPE_URL,
138
141
  session: ClientSession | None = None,
142
+ account_id: str | None = None,
139
143
  ) -> None:
140
144
  self.url = url
141
145
  self._arl = arl
146
+ self._account_id = account_id
142
147
  self._session = session
143
148
  self._owns_session = session is None
144
149
  # An external session may be shared by clients for different Deezer accounts.
@@ -347,12 +352,18 @@ class DeezerBaseClient:
347
352
 
348
353
  logger.debug("JWT expired or missing, refreshing from ARL")
349
354
  params = {"jo": "p", "rto": "c", "i": "c"}
355
+ body = None
356
+ if self._account_id:
357
+ # A Family profile signs in with the admin's ARL and its own id
358
+ params["i"] = "p"
359
+ body = {"arl": self._arl, "account_id": self._account_id}
350
360
 
351
361
  session = self._get_session()
352
362
  async with session.post(
353
363
  self.AUTH_URL,
354
364
  params=params,
355
365
  cookies=self._request_cookies(self.AUTH_URL, include_arl=True),
366
+ json=body,
356
367
  timeout=ClientTimeout(total=10),
357
368
  ) as resp:
358
369
  self._store_cookies(resp)
@@ -383,6 +394,10 @@ class DeezerBaseClient:
383
394
  msg = "Unexpected response from auth.deezer.com (invalid or missing JWT)"
384
395
  raise GraphQLClientAuthError(msg) from exc
385
396
 
397
+ if self._account_id and str(payload.get("userId")) != self._account_id:
398
+ msg = f"auth.deezer.com did not sign in as Family profile {self._account_id}"
399
+ raise GraphQLClientAuthError(msg)
400
+
386
401
  self._jwt = jwt
387
402
  self._jwt_expires_at = expires_at
388
403
  logger.debug("JWT acquired, expires at %s", self._jwt_expires_at)
@@ -34,6 +34,16 @@ from .add_tracks_to_playlist import (
34
34
  AddTracksToPlaylistAddTracksToPlaylistPlaylistAddTracksError,
35
35
  AddTracksToPlaylistAddTracksToPlaylistPlaylistAddTracksOutput,
36
36
  )
37
+ from .ban_artist_from_recommendation import (
38
+ BanArtistFromRecommendation,
39
+ BanArtistFromRecommendationBanArtistFromRecommendation,
40
+ BanArtistFromRecommendationBanArtistFromRecommendationArtist,
41
+ )
42
+ from .ban_track_from_recommendation import (
43
+ BanTrackFromRecommendation,
44
+ BanTrackFromRecommendationBanTrackFromRecommendation,
45
+ BanTrackFromRecommendationBanTrackFromRecommendationTrack,
46
+ )
37
47
  from .base_client import DeezerBaseClient
38
48
  from .base_model import BaseModel, Upload
39
49
  from .bookmark_podcast_episode import (
@@ -51,6 +61,8 @@ from .delete_playlist import DeletePlaylist, DeletePlaylistDeletePlaylist
51
61
  from .enums import (
52
62
  AlbumType,
53
63
  AudiobookContributorRoles,
64
+ DiscoveryTuner,
65
+ DiscoveryTunerInput,
54
66
  MusicTogetherRefreshSuggestedTracklistMoodInput,
55
67
  MusicTogetherSuggestedTracklistMoodInput,
56
68
  PodcastEpisodeOrder,
@@ -63,6 +75,7 @@ from .fragments import (
63
75
  AlbumFieldsContributorsEdges,
64
76
  AlbumFieldsContributorsEdgesNodeArtist,
65
77
  AlbumFieldsCover,
78
+ AlbumFieldsSubtypes,
66
79
  ArtistFields,
67
80
  ArtistFieldsBio,
68
81
  ArtistFieldsPicture,
@@ -73,6 +86,8 @@ from .fragments import (
73
86
  AudiobookFieldsContributorsEdges,
74
87
  AudiobookFieldsContributorsEdgesNodeArtist,
75
88
  AudiobookFieldsCover,
89
+ FamilyProfileFields,
90
+ FamilyProfileFieldsPermissions,
76
91
  LivestreamFields,
77
92
  LivestreamFieldsCover,
78
93
  LivestreamFieldsMedia,
@@ -116,6 +131,8 @@ from .get_artist import (
116
131
  GetArtistArtistAlbumsEdges,
117
132
  GetArtistArtistAlbumsEdgesNode,
118
133
  GetArtistArtistAlbumsPageInfo,
134
+ GetArtistArtistHeroPicture,
135
+ GetArtistArtistSocial,
119
136
  GetArtistArtistTopTracks,
120
137
  GetArtistArtistTopTracksEdges,
121
138
  GetArtistArtistTopTracksEdgesNode,
@@ -151,6 +168,24 @@ from .get_audiobook_chapter import (
151
168
  GetAudiobookChapterAudiobookChapterMediaRightsSub,
152
169
  GetAudiobookChapterAudiobookChapterMediaToken,
153
170
  )
171
+ from .get_banned_artists import (
172
+ GetBannedArtists,
173
+ GetBannedArtistsMe,
174
+ GetBannedArtistsMeBannedFromRecommendation,
175
+ GetBannedArtistsMeBannedFromRecommendationArtists,
176
+ GetBannedArtistsMeBannedFromRecommendationArtistsEdges,
177
+ GetBannedArtistsMeBannedFromRecommendationArtistsEdgesNode,
178
+ GetBannedArtistsMeBannedFromRecommendationArtistsPageInfo,
179
+ )
180
+ from .get_banned_tracks import (
181
+ GetBannedTracks,
182
+ GetBannedTracksMe,
183
+ GetBannedTracksMeBannedFromRecommendation,
184
+ GetBannedTracksMeBannedFromRecommendationTracks,
185
+ GetBannedTracksMeBannedFromRecommendationTracksEdges,
186
+ GetBannedTracksMeBannedFromRecommendationTracksEdgesNode,
187
+ GetBannedTracksMeBannedFromRecommendationTracksPageInfo,
188
+ )
154
189
  from .get_charts import (
155
190
  GetCharts,
156
191
  GetChartsCharts,
@@ -172,6 +207,13 @@ from .get_charts import (
172
207
  GetChartsChartsCountryTracksEdgesNode,
173
208
  GetChartsChartsCountryTracksPageInfo,
174
209
  )
210
+ from .get_family import (
211
+ GetFamily,
212
+ GetFamilyMe,
213
+ GetFamilyMeFamily,
214
+ GetFamilyMeFamilyLinked,
215
+ GetFamilyMeFamilyMain,
216
+ )
175
217
  from .get_favorite_albums import (
176
218
  GetFavoriteAlbums,
177
219
  GetFavoriteAlbumsMe,
@@ -270,6 +312,17 @@ from .get_flow_configs import (
270
312
  GetFlowConfigsMeFlowConfigsMoodsEdgesNodeVisualsHardwareSquareIcon,
271
313
  GetFlowConfigsMeFlowConfigsMoodsPageInfo,
272
314
  )
315
+ from .get_flow_tuner import GetFlowTuner, GetFlowTunerMe, GetFlowTunerMeFlowTuner
316
+ from .get_infinite_track_mix import (
317
+ GetInfiniteTrackMix,
318
+ GetInfiniteTrackMixRawInfiniteTrackMix,
319
+ GetInfiniteTrackMixRawInfiniteTrackMixTracks,
320
+ )
321
+ from .get_latest_podcast_episodes import (
322
+ GetLatestPodcastEpisodes,
323
+ GetLatestPodcastEpisodesMe,
324
+ GetLatestPodcastEpisodesMeRawLatestPodcastEpisodes,
325
+ )
273
326
  from .get_livestream import GetLivestream, GetLivestreamLivestream
274
327
  from .get_made_for_me import (
275
328
  GetMadeForMe,
@@ -472,6 +525,7 @@ from .get_track_mix import (
472
525
  GetTrackMixTrackMixTracks,
473
526
  GetTrackMixTrackMixTracksTrack,
474
527
  )
528
+ from .get_tracks_by_ids import GetTracksByIds, GetTracksByIdsTracksByIds
475
529
  from .get_user_charts import (
476
530
  GetUserCharts,
477
531
  GetUserChartsMe,
@@ -631,6 +685,20 @@ from .search_flows import (
631
685
  SearchFlowsSearchResultsFlowConfigsEdgesNodeVisualsHardwareSquareIcon,
632
686
  SearchFlowsSearchResultsFlowConfigsPageInfo,
633
687
  )
688
+ from .set_flow_discovery_tuner import (
689
+ SetFlowDiscoveryTuner,
690
+ SetFlowDiscoveryTunerSetFlowDiscoveryTuner,
691
+ )
692
+ from .unban_artist_from_recommendation import (
693
+ UnbanArtistFromRecommendation,
694
+ UnbanArtistFromRecommendationUnbanArtistFromRecommendation,
695
+ UnbanArtistFromRecommendationUnbanArtistFromRecommendationArtist,
696
+ )
697
+ from .unban_track_from_recommendation import (
698
+ UnbanTrackFromRecommendation,
699
+ UnbanTrackFromRecommendationUnbanTrackFromRecommendation,
700
+ UnbanTrackFromRecommendationUnbanTrackFromRecommendationTrack,
701
+ )
634
702
  from .unbookmark_podcast_episode import (
635
703
  UnbookmarkPodcastEpisode,
636
704
  UnbookmarkPodcastEpisodeUnbookmarkPodcastEpisode,
@@ -668,6 +736,7 @@ __all__ = [
668
736
  "AlbumFieldsContributorsEdges",
669
737
  "AlbumFieldsContributorsEdgesNodeArtist",
670
738
  "AlbumFieldsCover",
739
+ "AlbumFieldsSubtypes",
671
740
  "AlbumType",
672
741
  "ArtistFields",
673
742
  "ArtistFieldsBio",
@@ -680,6 +749,12 @@ __all__ = [
680
749
  "AudiobookFieldsContributorsEdges",
681
750
  "AudiobookFieldsContributorsEdgesNodeArtist",
682
751
  "AudiobookFieldsCover",
752
+ "BanArtistFromRecommendation",
753
+ "BanArtistFromRecommendationBanArtistFromRecommendation",
754
+ "BanArtistFromRecommendationBanArtistFromRecommendationArtist",
755
+ "BanTrackFromRecommendation",
756
+ "BanTrackFromRecommendationBanTrackFromRecommendation",
757
+ "BanTrackFromRecommendationBanTrackFromRecommendationTrack",
683
758
  "BaseModel",
684
759
  "BookmarkPodcastEpisode",
685
760
  "BookmarkPodcastEpisodeBookmarkPodcastEpisode",
@@ -691,6 +766,10 @@ __all__ = [
691
766
  "DeezerGQLClient",
692
767
  "DeletePlaylist",
693
768
  "DeletePlaylistDeletePlaylist",
769
+ "DiscoveryTuner",
770
+ "DiscoveryTunerInput",
771
+ "FamilyProfileFields",
772
+ "FamilyProfileFieldsPermissions",
694
773
  "GetAlbum",
695
774
  "GetAlbumAlbum",
696
775
  "GetAlbumAlbumFallback",
@@ -706,6 +785,8 @@ __all__ = [
706
785
  "GetArtistArtistAlbumsEdges",
707
786
  "GetArtistArtistAlbumsEdgesNode",
708
787
  "GetArtistArtistAlbumsPageInfo",
788
+ "GetArtistArtistHeroPicture",
789
+ "GetArtistArtistSocial",
709
790
  "GetArtistArtistTopTracks",
710
791
  "GetArtistArtistTopTracksEdges",
711
792
  "GetArtistArtistTopTracksEdgesNode",
@@ -734,6 +815,20 @@ __all__ = [
734
815
  "GetAudiobookChapterAudiobookChapterMediaRightsAds",
735
816
  "GetAudiobookChapterAudiobookChapterMediaRightsSub",
736
817
  "GetAudiobookChapterAudiobookChapterMediaToken",
818
+ "GetBannedArtists",
819
+ "GetBannedArtistsMe",
820
+ "GetBannedArtistsMeBannedFromRecommendation",
821
+ "GetBannedArtistsMeBannedFromRecommendationArtists",
822
+ "GetBannedArtistsMeBannedFromRecommendationArtistsEdges",
823
+ "GetBannedArtistsMeBannedFromRecommendationArtistsEdgesNode",
824
+ "GetBannedArtistsMeBannedFromRecommendationArtistsPageInfo",
825
+ "GetBannedTracks",
826
+ "GetBannedTracksMe",
827
+ "GetBannedTracksMeBannedFromRecommendation",
828
+ "GetBannedTracksMeBannedFromRecommendationTracks",
829
+ "GetBannedTracksMeBannedFromRecommendationTracksEdges",
830
+ "GetBannedTracksMeBannedFromRecommendationTracksEdgesNode",
831
+ "GetBannedTracksMeBannedFromRecommendationTracksPageInfo",
737
832
  "GetCharts",
738
833
  "GetChartsCharts",
739
834
  "GetChartsChartsCountry",
@@ -753,6 +848,11 @@ __all__ = [
753
848
  "GetChartsChartsCountryTracksEdges",
754
849
  "GetChartsChartsCountryTracksEdgesNode",
755
850
  "GetChartsChartsCountryTracksPageInfo",
851
+ "GetFamily",
852
+ "GetFamilyMe",
853
+ "GetFamilyMeFamily",
854
+ "GetFamilyMeFamilyLinked",
855
+ "GetFamilyMeFamilyMain",
756
856
  "GetFavoriteAlbums",
757
857
  "GetFavoriteAlbumsMe",
758
858
  "GetFavoriteAlbumsMeUserFavorites",
@@ -831,6 +931,15 @@ __all__ = [
831
931
  "GetFlowMeFlowCover",
832
932
  "GetFlowMeFlowTracks",
833
933
  "GetFlowMeFlowTracksTrack",
934
+ "GetFlowTuner",
935
+ "GetFlowTunerMe",
936
+ "GetFlowTunerMeFlowTuner",
937
+ "GetInfiniteTrackMix",
938
+ "GetInfiniteTrackMixRawInfiniteTrackMix",
939
+ "GetInfiniteTrackMixRawInfiniteTrackMixTracks",
940
+ "GetLatestPodcastEpisodes",
941
+ "GetLatestPodcastEpisodesMe",
942
+ "GetLatestPodcastEpisodesMeRawLatestPodcastEpisodes",
834
943
  "GetLivestream",
835
944
  "GetLivestreamLivestream",
836
945
  "GetMadeForMe",
@@ -1001,6 +1110,8 @@ __all__ = [
1001
1110
  "GetTrackTrackMediaRightsAds",
1002
1111
  "GetTrackTrackMediaRightsSub",
1003
1112
  "GetTrackTrackMediaToken",
1113
+ "GetTracksByIds",
1114
+ "GetTracksByIdsTracksByIds",
1004
1115
  "GetUserCharts",
1005
1116
  "GetUserChartsMe",
1006
1117
  "GetUserChartsMeCharts",
@@ -1140,6 +1251,8 @@ __all__ = [
1140
1251
  "SearchSearchResultsTracksEdgesNodeMediaRights",
1141
1252
  "SearchSearchResultsTracksEdgesNodeMediaRightsSub",
1142
1253
  "SearchSearchResultsTracksPageInfo",
1254
+ "SetFlowDiscoveryTuner",
1255
+ "SetFlowDiscoveryTunerSetFlowDiscoveryTuner",
1143
1256
  "TrackContributorRoles",
1144
1257
  "TrackFields",
1145
1258
  "TrackFieldsAlbum",
@@ -1151,6 +1264,12 @@ __all__ = [
1151
1264
  "TrackFieldsMedia",
1152
1265
  "TrackFieldsMediaRights",
1153
1266
  "TrackFieldsMediaRightsSub",
1267
+ "UnbanArtistFromRecommendation",
1268
+ "UnbanArtistFromRecommendationUnbanArtistFromRecommendation",
1269
+ "UnbanArtistFromRecommendationUnbanArtistFromRecommendationArtist",
1270
+ "UnbanTrackFromRecommendation",
1271
+ "UnbanTrackFromRecommendationUnbanTrackFromRecommendation",
1272
+ "UnbanTrackFromRecommendationUnbanTrackFromRecommendationTrack",
1154
1273
  "UnbookmarkPodcastEpisode",
1155
1274
  "UnbookmarkPodcastEpisodeUnbookmarkPodcastEpisode",
1156
1275
  "UnbookmarkPodcastEpisodeUnbookmarkPodcastEpisodeEpisode",
@@ -0,0 +1,26 @@
1
+ # Generated by ariadne-codegen
2
+ # Source: queries
3
+
4
+ from pydantic import Field
5
+
6
+ from .base_model import BaseModel
7
+
8
+
9
+ class BanArtistFromRecommendation(BaseModel):
10
+ ban_artist_from_recommendation: "BanArtistFromRecommendationBanArtistFromRecommendation" = Field(
11
+ alias="banArtistFromRecommendation"
12
+ )
13
+
14
+
15
+ class BanArtistFromRecommendationBanArtistFromRecommendation(BaseModel):
16
+ status: bool
17
+ artist: "BanArtistFromRecommendationBanArtistFromRecommendationArtist"
18
+
19
+
20
+ class BanArtistFromRecommendationBanArtistFromRecommendationArtist(BaseModel):
21
+ id: str
22
+ name: str
23
+
24
+
25
+ BanArtistFromRecommendation.model_rebuild()
26
+ BanArtistFromRecommendationBanArtistFromRecommendation.model_rebuild()
@@ -0,0 +1,26 @@
1
+ # Generated by ariadne-codegen
2
+ # Source: queries
3
+
4
+ from pydantic import Field
5
+
6
+ from .base_model import BaseModel
7
+
8
+
9
+ class BanTrackFromRecommendation(BaseModel):
10
+ ban_track_from_recommendation: "BanTrackFromRecommendationBanTrackFromRecommendation" = Field(
11
+ alias="banTrackFromRecommendation"
12
+ )
13
+
14
+
15
+ class BanTrackFromRecommendationBanTrackFromRecommendation(BaseModel):
16
+ status: bool
17
+ track: "BanTrackFromRecommendationBanTrackFromRecommendationTrack"
18
+
19
+
20
+ class BanTrackFromRecommendationBanTrackFromRecommendationTrack(BaseModel):
21
+ id: str
22
+ title: str
23
+
24
+
25
+ BanTrackFromRecommendation.model_rebuild()
26
+ BanTrackFromRecommendationBanTrackFromRecommendation.model_rebuild()