Skip to content

Commit

Permalink
adds method for shortened spotify url expansion
Browse files Browse the repository at this point in the history
  • Loading branch information
hayribakici authored and rinukkusu committed Feb 20, 2024
1 parent fec57d4 commit 21d37f9
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 6 deletions.
4 changes: 4 additions & 0 deletions example/example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ void main() async {
var credentials = SpotifyApiCredentials(keyMap['id'], keyMap['secret']);
var spotify = SpotifyApi(credentials);

print('\nExpannd shortened spotify link of https://spotify.link/hRkBrwub9xb');
var longLink = await spotify.expandLink('https://spotify.link/hRkBrwub9xb');
print(longLink);

print('\nPodcast:');
await spotify.shows
.get('4rOoJ6Egrf8K2IrywzwOMk')
Expand Down
30 changes: 27 additions & 3 deletions lib/src/spotify_base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ abstract class SpotifyApiBase {
);
}

/// Expands shortened spotify [url]
Future<String> expandLink(String url) async => _streamedHeadImpl(url, const {});

Future<String> _get(String path) {
return _getImpl('$_baseUrl/$path', const {});
}
Expand All @@ -174,6 +177,15 @@ abstract class SpotifyApiBase {
return _putImpl('$_baseUrl/$path', const {}, body);
}

Future<String> _streamedHeadImpl(
String url, Map<String, String> headers) async {
return await _requestWrapper(() async {
final request = http.Request('HEAD', Uri.parse(url));
request.headers.addAll(headers);
return (await _client).send(request);
});
}

Future<String> _getImpl(String url, Map<String, String> headers) async {
return await _requestWrapper(() async =>
await (await _client).get(Uri.parse(url), headers: headers));
Expand Down Expand Up @@ -202,14 +214,26 @@ abstract class SpotifyApiBase {
.put(Uri.parse(url), headers: headers, body: body));
}

Future<String> _requestWrapper(Future<http.Response> Function() request,
// the reason we are using [http.BaseResponse] is because
// otherwise we wouldn't be able to access the redirect url from
// BaseResponseWithUrl
Future<String> _requestWrapper(Future<http.BaseResponse> Function() request,
{retryLimit = 5}) async {
for (var i = 0; i < retryLimit; i++) {
while (_shouldWait) {
await Future.delayed(Duration(milliseconds: 500));
}
try {
return handleErrors(await request());
var response = await request();

// distinguish between url redirect responses and body responses
// note, that any response that also contains a redirect url
// will be chosen instead of its body contents
// FIXME: in future releases of http2, the url is a part of the [http.Response] type
if (response case http.BaseResponseWithUrl(:final url)) {
return url.toString();
}
return handleResponseWithBody(response as http.Response);
} on ApiRateException catch (ex) {
if (i == retryLimit - 1) rethrow;
print(
Expand All @@ -226,7 +250,7 @@ abstract class SpotifyApiBase {
return SpotifyApiCredentials._fromClient(await _client);
}

String handleErrors(http.Response response) {
String handleResponseWithBody(http.Response response) {
final responseBody = utf8.decode(response.bodyBytes);
if (response.statusCode >= 400) {
final jsonMap = json.decode(responseBody);
Expand Down
6 changes: 3 additions & 3 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ version: 0.13.1
homepage: https://github.com/rinukkusu/spotify-dart

environment:
sdk: '>=2.18.0 <4.0.0'
sdk: '>=3.0.0 <4.0.0'

dependencies:
http: ^1.1.0
http: ^1.2.0
json_annotation: ^4.8.1
oauth2: ^2.0.0
oauth2: ^2.0.2

dev_dependencies:
lints: ">=2.1.1 <4.0.0"
Expand Down

0 comments on commit 21d37f9

Please sign in to comment.