From d388f4d77e9fef31546e28bc97714cee53bed544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Mielcarek?= Date: Wed, 16 Nov 2022 17:21:34 +0100 Subject: [PATCH] Suite travail sur playlist Spotify. --- Sources/dafl_project_flutter/lib/api/api.dart | 80 ++++++++++++++++--- .../lib/api/in_app_browser.dart | 4 +- .../lib/exceptions/api_exception.dart | 10 ++- .../dafl_project_flutter/lib/model/user.dart | 4 - 4 files changed, 78 insertions(+), 20 deletions(-) diff --git a/Sources/dafl_project_flutter/lib/api/api.dart b/Sources/dafl_project_flutter/lib/api/api.dart index 63f0140..6b0fba4 100644 --- a/Sources/dafl_project_flutter/lib/api/api.dart +++ b/Sources/dafl_project_flutter/lib/api/api.dart @@ -14,19 +14,23 @@ class Api { //for web api get redirectUri => 'https://daflmusic.000webhostapp.com/callback/'; final _scopes = - 'user-read-playback-state user-read-currently-playing user-read-recently-played'; + 'user-read-playback-state user-read-currently-playing user-read-recently-played playlist-modify-public'; late String _state; dynamic _codeVerifier; dynamic _codeChallenge; late String _encodedLogs; final _tokenType = 'Bearer '; late http.Response _response; //use _setResponse() as kind of a private setter + final _playlistName = "Dafl's discovery"; + + //final _playlistName = 'daflmusic'; //from web api String? _code; int? _expiresIn; String? _refreshToken; - String? _accessToken; //use _getToken() as kind of a private getter + String? _accessToken; //use _getAccessToken() as kind of a private getter + String? _idUser; //use _getIdUser() as kind of a private getter //other final _client = http.Client(); @@ -66,14 +70,17 @@ class Api { } _generateCodeChallenge() { - return base64UrlEncode(sha256.convert(utf8.encode(_codeVerifier)).bytes); + return base64Encode(sha256.convert(utf8.encode(_codeVerifier)).bytes) + .replaceAll('+', '-') + .replaceAll('/', '_') + .replaceAll('=', ''); } //session management requestUserAuthorization(Uri url) async { if (url.queryParameters['state'] != _state.toString()) { - throw ApiException(); + throw ApiException('state'); } _code = url.queryParameters['code']; await _requestAccessToken(); @@ -111,8 +118,9 @@ class Api { } _setResponse(value) { - if (value.statusCode != 200) { - throw ApiException(); + int sc = value.statusCode; + if (sc >= 300) { + throw ApiException(sc); } _response = value; } @@ -172,11 +180,15 @@ class Api { decodedResponse['album']['images'][0]['url']); } - addToPLaylist() { - //if playlist DaflMusic doesn't exist + addToPLaylist(String id) async { + var res = await _getPlaylist(); + if (!res) { + await _createPlaylist(); + } + //TODO : add to playlist } - getPlaylist() async { + dynamic _getPlaylist() async { var url = Uri.https('api.spotify.com', 'v1/me/playlists', {'limit': '50'}); var token = await _getAccessToken(); _setResponse(await _client.get(url, headers: { @@ -184,9 +196,51 @@ class Api { 'Content-Type': 'application/json' })); var decodedResponse = jsonDecode(utf8.decode(_response.bodyBytes)) as Map; - dev.log(decodedResponse['items'].toString()); - dev.log(decodedResponse['items'] - .where((element) => element['name'] == 'daflmusic') - .toString()); + var daflplaylist = decodedResponse['items'] + .where((element) => element['name'] == _playlistName) + .toList(); + if (daflplaylist.length == 1) { + return daflplaylist[0]['uri'].substring( + 17); //17 char because format is 'spotify:playlist:MYPLAYLISTID' + } + return false; + } + + _createPlaylist() async { + var token = await _getAccessToken(); + var id = await _getIdUser(); + var url = Uri.https('api.spotify.com', 'v1/users/$id/playlists'); + _setResponse(await _client.post(url, + headers: { + 'Accept': 'application/json', + 'Authorization': '$_tokenType $token', + 'Content-Type': 'application/json' + }, + body: jsonEncode({ + 'name': _playlistName, + 'description': + 'Retrouvez toutes vos découvertes faites sur DaflMusic 🎵', + 'public': 'true' + }))); + var decodedResponse = jsonDecode(utf8.decode(_response.bodyBytes)) as Map; + _idUser = decodedResponse['id']; + } + + Future _getIdUser() async { + if (_idUser == null) { + await _getIdUserApi(); + } + return _idUser!; + } + + _getIdUserApi() async { + var url = Uri.https('api.spotify.com', 'v1/me'); + var token = await _getAccessToken(); + _setResponse(await _client.get(url, headers: { + 'Authorization': '$_tokenType $token', + 'Content-Type': 'application/json' + })); + var decodedResponse = jsonDecode(utf8.decode(_response.bodyBytes)) as Map; + _idUser = decodedResponse['id']; } } diff --git a/Sources/dafl_project_flutter/lib/api/in_app_browser.dart b/Sources/dafl_project_flutter/lib/api/in_app_browser.dart index 5550b7b..edd6737 100644 --- a/Sources/dafl_project_flutter/lib/api/in_app_browser.dart +++ b/Sources/dafl_project_flutter/lib/api/in_app_browser.dart @@ -27,7 +27,9 @@ class MyInAppBrowser extends InAppBrowser { if (url!.origin + url.path == MyApp.api.redirectUri) { try { await MyApp.api.requestUserAuthorization(url); - await MyApp.api.getPlaylist(); + //TODO : finir d'implémenter : addToPlaylist + //var id = await MyApp.api.getCurrentlyPlayingTrack(); + //await MyApp.api.addToPLaylist(id); } on ApiException { // TODO : add notification to show that an error occured } finally { diff --git a/Sources/dafl_project_flutter/lib/exceptions/api_exception.dart b/Sources/dafl_project_flutter/lib/exceptions/api_exception.dart index 53fe102..191f176 100644 --- a/Sources/dafl_project_flutter/lib/exceptions/api_exception.dart +++ b/Sources/dafl_project_flutter/lib/exceptions/api_exception.dart @@ -1,7 +1,13 @@ import 'dart:developer' as dev; class ApiException implements Exception { - ApiException() { - dev.log('Api exception raised'); + final String mess = 'Api exception raised,'; + + ApiException(dynamic code) { + if (code.runtimeType == String) { + dev.log('$mess state verification failed.'); + } else { + dev.log('$mess status code : $code.'); + } } } diff --git a/Sources/dafl_project_flutter/lib/model/user.dart b/Sources/dafl_project_flutter/lib/model/user.dart index 9a47fbf..d1f0697 100644 --- a/Sources/dafl_project_flutter/lib/model/user.dart +++ b/Sources/dafl_project_flutter/lib/model/user.dart @@ -11,10 +11,6 @@ class User { late String usernameDafl; late String passwDafl; - //attributes to link with API - late String usernameAPI; - late String passwAPI; - //attributes with Spotify API late String _id; late Track track;