Skip to content

Commit

Permalink
Handle empty or missing JSON fields in the iTunes and PodcastIndex se…
Browse files Browse the repository at this point in the history
…arch results.
  • Loading branch information
amugofjava committed Mar 28, 2024
1 parent 9fedfcc commit dcdceb6
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 34 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.6.9

- Bug fix: handle empty fields from iTunes and PodcastIndex API call results.

## 0.6.8

- BREAKING CHANGE: Language is now a text parameter (2-3 letter code) rather than enum. This is because iTunes largely ignores language, but PodcastIndex can use it for trending podcasts.
Expand Down
24 changes: 11 additions & 13 deletions lib/src/model/item.dart
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,11 @@ class Item {
});

/// Takes our json map and builds a Podcast instance from it.
factory Item.fromJson(
{required Map<String, dynamic>? json,
ResultType type = ResultType.itunes}) {
return type == ResultType.itunes
? _fromItunes(json!)
: _fromPodcastIndex(json!);
factory Item.fromJson({
required Map<String, dynamic>? json,
ResultType type = ResultType.itunes,
}) {
return type == ResultType.itunes ? _fromItunes(json!) : _fromPodcastIndex(json!);
}

static Item _fromItunes(Map<String, dynamic> json) {
Expand All @@ -143,26 +142,25 @@ class Item {
artworkUrl60: json['artworkUrl60'] as String?,
artworkUrl100: json['artworkUrl100'] as String?,
artworkUrl600: json['artworkUrl600'] as String?,
genre: Item._loadGenres(
json['genreIds'].cast<String>(), json['genres'].cast<String>()),
releaseDate: DateTime.parse(json['releaseDate']),
genre: json['genreIds'] == null
? <Genre>[]
: Item._loadGenres(json['genreIds'].cast<String>(), json['genres'].cast<String>()),
releaseDate: DateTime.tryParse(json['releaseDate'] ?? ''),
country: json['country'] as String?,
primaryGenreName: json['primaryGenreName'] as String?,
contentAdvisoryRating: json['contentAdvisoryRating'] as String?,
);
}

static Item _fromPodcastIndex(Map<String, dynamic> json) {
int pubDateSeconds =
json['lastUpdateTime'] ?? DateTime.now().millisecondsSinceEpoch ~/ 1000;
int pubDateSeconds = json['lastUpdateTime'] ?? DateTime.now().millisecondsSinceEpoch ~/ 1000;

var pubDate = Duration(seconds: pubDateSeconds);
var categories = json['categories'];
var genres = <Genre>[];

if (categories != null) {
categories
.forEach((key, value) => genres.add(Genre(int.parse(key), value)));
categories.forEach((key, value) => genres.add(Genre(int.parse(key), value)));
}

return Item(
Expand Down
24 changes: 7 additions & 17 deletions lib/src/search/itunes_search.dart
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,7 @@ final class ITunesSearch extends BaseSearch {
connectTimeout: Duration(milliseconds: timeout),
receiveTimeout: Duration(milliseconds: timeout),
headers: {
'User-Agent': userAgent == null || userAgent.isEmpty
? podcastSearchAgent
: userAgent,
'User-Agent': userAgent == null || userAgent.isEmpty ? podcastSearchAgent : userAgent,
},
),
);
Expand Down Expand Up @@ -116,8 +114,7 @@ final class ITunesSearch extends BaseSearch {
setLastError(e);
}

return SearchResult.fromError(
lastError: lastError ?? '', lastErrorType: lastErrorType);
return SearchResult.fromError(lastError: lastError ?? '', lastErrorType: lastErrorType);
}

/// Fetches the list of top podcasts
Expand Down Expand Up @@ -153,8 +150,7 @@ final class ITunesSearch extends BaseSearch {
setLastError(e);
}

return SearchResult.fromError(
lastError: lastError ?? '', lastErrorType: lastErrorType);
return SearchResult.fromError(lastError: lastError ?? '', lastErrorType: lastErrorType);
}

@override
Expand All @@ -180,8 +176,7 @@ final class ITunesSearch extends BaseSearch {

if (count == 0) {
// ignore: avoid_print
print(
'Warning: Could not find $title via lookup id: $feedApiEndpoint/lookup?id=$id - skipped');
print('Warning: Could not find $title via lookup id: $feedApiEndpoint/lookup?id=$id - skipped');
}

if (count > 0 && results['results'] != null) {
Expand All @@ -197,8 +192,7 @@ final class ITunesSearch extends BaseSearch {
setLastError(e);
}

return SearchResult.fromError(
lastError: lastError ?? '', lastErrorType: lastErrorType);
return SearchResult.fromError(lastError: lastError ?? '', lastErrorType: lastErrorType);
}

/// This internal method constructs a correctly encoded URL which is then
Expand Down Expand Up @@ -249,19 +243,15 @@ final class ITunesSearch extends BaseSearch {
}

String _termParam() {
return term != null && term!.isNotEmpty
? '?term=${Uri.encodeComponent(term!)}'
: '';
return term != null && term!.isNotEmpty ? '?term=${Uri.encodeComponent(term!)}' : '';
}

String _countryParam() {
return _country != Country.none ? '&country=${_country.code}' : '';
}

String _attributeParam() {
return _attribute != Attribute.none
? '&attribute=${Uri.encodeComponent(_attribute!.attribute)}'
: '';
return _attribute != Attribute.none ? '&attribute=${Uri.encodeComponent(_attribute!.attribute)}' : '';
}

String _limitParam() {
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: podcast_search
description: A library for searching for podcasts and parsing podcast RSS feeds. Supports iTunes and PodcastIndex directories, and newer features such as chapters and transcripts.

version: 0.6.8
version: 0.6.9
homepage: https://github.com/amugofjava/podcast_search

environment:
Expand Down
19 changes: 16 additions & 3 deletions test/podcast_search_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ void main() {

setUp(() {
search = Search(
searchProvider: PodcastIndexProvider(
key: 'XXWQEGULBJABVHZUM8NF',
secret: 'KZ2uy4upvq4t3e\$m\$3r2TeFS2fEpFTAaF92xcNdX'),
searchProvider:
PodcastIndexProvider(key: 'XXWQEGULBJABVHZUM8NF', secret: 'KZ2uy4upvq4t3e\$m\$3r2TeFS2fEpFTAaF92xcNdX'),
);
});

Expand All @@ -27,5 +26,19 @@ void main() {

expect(result.resultCount, 1);
});

test('Empty iTunes items result', () async {
final result = Item.fromJson(
json: {},
);

expect(result, isNotNull);
});

test('Empty PodcastIndex items result', () async {
final result = Item.fromJson(json: {}, type: ResultType.podcastIndex);

expect(result, isNotNull);
});
});
}

0 comments on commit dcdceb6

Please sign in to comment.