-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: personal playlist recommendations
- Loading branch information
Showing
8 changed files
with
149 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||
import 'package:spotube/provider/authentication_provider.dart'; | ||
import 'package:spotube/services/custom_spotify_endpoints/spotify_endpoints.dart'; | ||
|
||
final customSpotifyEndpointProvider = Provider<CustomSpotifyEndpoints>((ref) { | ||
final auth = ref.watch(AuthenticationNotifier.provider); | ||
return CustomSpotifyEndpoints(auth?.accessToken ?? ""); | ||
}); |
83 changes: 83 additions & 0 deletions
83
lib/services/custom_spotify_endpoints/spotify_endpoints.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import 'dart:convert'; | ||
|
||
import 'package:http/http.dart' as http; | ||
|
||
class CustomSpotifyEndpoints { | ||
static const _baseUrl = 'https://api.spotify.com/v1'; | ||
final String accessToken; | ||
final http.Client _client; | ||
|
||
CustomSpotifyEndpoints(this.accessToken) : _client = http.Client(); | ||
|
||
// views API | ||
|
||
/// Get a single view of given genre | ||
/// | ||
/// Currently known genres are: | ||
/// - new-releases-page | ||
/// - made-for-x-hub (it requires authentication) | ||
/// - my-mix-genres (it requires authentication) | ||
/// - artist-seed-mixes (it requires authentication) | ||
/// - my-mix-decades (it requires authentication) | ||
/// - my-mix-moods (it requires authentication) | ||
/// - podcasts-and-more (it requires authentication) | ||
/// - uniquely-yours-in-hub (it requires authentication) | ||
/// - made-for-x-dailymix (it requires authentication) | ||
/// - made-for-x-discovery (it requires authentication) | ||
Future<Map<String, dynamic>> getView( | ||
String view, { | ||
int limit = 20, | ||
int contentLimit = 10, | ||
List<String> types = const [ | ||
"album", | ||
"playlist", | ||
"artist", | ||
"show", | ||
"station", | ||
"episode", | ||
"merch", | ||
"artist_concerts", | ||
"uri_link" | ||
], | ||
String imageStyle = "gradient_overlay", | ||
String includeExternal = "audio", | ||
String? locale, | ||
String? market, | ||
String? country, | ||
}) async { | ||
if (accessToken.isEmpty) { | ||
throw Exception('[CustomSpotifyEndpoints.getView]: accessToken is empty'); | ||
} | ||
|
||
final queryParams = { | ||
'limit': limit.toString(), | ||
'content_limit': contentLimit.toString(), | ||
'types': types.join(','), | ||
'image_style': imageStyle, | ||
'include_external': includeExternal, | ||
'timestamp': DateTime.now().toUtc().toIso8601String(), | ||
if (locale != null) 'locale': locale, | ||
if (market != null) 'market': market, | ||
if (country != null) 'country': country, | ||
}.entries.map((e) => '${e.key}=${e.value}').join('&'); | ||
|
||
final res = await _client.get( | ||
Uri.parse('$_baseUrl/views/$view?$queryParams'), | ||
headers: { | ||
"content-type": "application/json", | ||
"authorization": "Bearer $accessToken", | ||
"accept": "application/json", | ||
}, | ||
); | ||
|
||
if (res.statusCode == 200) { | ||
return jsonDecode(res.body); | ||
} else { | ||
throw Exception( | ||
'[CustomSpotifyEndpoints.getView]: Failed to get view' | ||
'\nStatus code: ${res.statusCode}' | ||
'\nBody: ${res.body}', | ||
); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import 'package:fl_query/fl_query.dart'; | ||
import 'package:fl_query_hooks/fl_query_hooks.dart'; | ||
import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||
import 'package:spotube/provider/authentication_provider.dart'; | ||
import 'package:spotube/provider/custom_spotify_endpoint_provider.dart'; | ||
import 'package:spotube/provider/user_preferences_provider.dart'; | ||
|
||
class ViewsQueries { | ||
const ViewsQueries(); | ||
|
||
Query<Map<String, dynamic>?, dynamic> get( | ||
WidgetRef ref, | ||
String view, | ||
) { | ||
final customSpotify = ref.watch(customSpotifyEndpointProvider); | ||
final auth = ref.watch(AuthenticationNotifier.provider); | ||
final market = ref | ||
.watch(userPreferencesProvider.select((s) => s.recommendationMarket)); | ||
|
||
return useQuery<Map<String, dynamic>?, dynamic>("views/$view", () { | ||
if (auth == null) return null; | ||
return customSpotify.getView(view, market: market, country: market); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters