Skip to content

Commit 867134d

Browse files
committed
Improve support for PC2.0 chapters. Fix formatting.
1 parent ac620c6 commit 867134d

File tree

12 files changed

+100
-41
lines changed

12 files changed

+100
-41
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.5.5
2+
3+
- Improve PC2.0 chapter support.
4+
15
## 0.5.4
26

37
- Add support for PC2.0 Transcripts (json/srt/subrip);

lib/src/model/attribute.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ enum Attribute {
1616
const Attribute({
1717
required this.attribute,
1818
});
19-
19+
2020
final String attribute;
2121
}
22-

lib/src/model/item.dart

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,12 @@ class Item {
113113
});
114114

115115
/// Takes our json map and builds a Podcast instance from it.
116-
factory Item.fromJson({required Map<String, dynamic>? json, ResultType type = ResultType.itunes}) {
117-
return type == ResultType.itunes ? _fromItunes(json!) : _fromPodcastIndex(json!);
116+
factory Item.fromJson(
117+
{required Map<String, dynamic>? json,
118+
ResultType type = ResultType.itunes}) {
119+
return type == ResultType.itunes
120+
? _fromItunes(json!)
121+
: _fromPodcastIndex(json!);
118122
}
119123

120124
static Item _fromItunes(Map<String, dynamic> json) {
@@ -139,7 +143,8 @@ class Item {
139143
artworkUrl60: json['artworkUrl60'] as String?,
140144
artworkUrl100: json['artworkUrl100'] as String?,
141145
artworkUrl600: json['artworkUrl600'] as String?,
142-
genre: Item._loadGenres(json['genreIds'].cast<String>(), json['genres'].cast<String>()),
146+
genre: Item._loadGenres(
147+
json['genreIds'].cast<String>(), json['genres'].cast<String>()),
143148
releaseDate: DateTime.parse(json['releaseDate']),
144149
country: json['country'] as String?,
145150
primaryGenreName: json['primaryGenreName'] as String?,
@@ -148,14 +153,16 @@ class Item {
148153
}
149154

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

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

157163
if (categories != null) {
158-
categories.forEach((key, value) => genres.add(Genre(int.parse(key), value)));
164+
categories
165+
.forEach((key, value) => genres.add(Genre(int.parse(key), value)));
159166
}
160167

161168
return Item(

lib/src/model/language.dart

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
// MIT license that can be found in the LICENSE file.
33

44
/// An Enum that provides a list of the languages the iTunes API currently supports.
5-
enum Language{
5+
enum Language {
66
none(code: ''),
77
enUs(code: 'en_us'),
88
jaJp(code: 'en_us');
99

10-
const Language({required this.code,});
10+
const Language({
11+
required this.code,
12+
});
1113

1214
final String code;
13-
}
15+
}

lib/src/model/podcast.dart

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// MIT license that can be found in the LICENSE file.
33

44
import 'dart:async';
5+
import 'dart:convert';
56
import 'dart:io';
67

78
import 'package:dart_rss/dart_rss.dart';
@@ -73,7 +74,8 @@ class Podcast {
7374
connectTimeout: timeout,
7475
receiveTimeout: timeout,
7576
headers: {
76-
'User-Agent': userAgent.isEmpty ? '$podcastSearchAgent' : '$userAgent',
77+
'User-Agent':
78+
userAgent.isEmpty ? '$podcastSearchAgent' : '$userAgent',
7779
},
7880
),
7981
);
@@ -192,11 +194,14 @@ class Podcast {
192194
),
193195
);
194196

195-
if (episode.chapters!.chapters.isNotEmpty && !episode.chapters!.loaded && !forceReload) {
197+
if (episode.chapters!.chapters.isNotEmpty &&
198+
!episode.chapters!.loaded &&
199+
!forceReload) {
196200
try {
197201
final response = await client.get(episode.chapters!.url);
198202

199-
if (response.statusCode == 200 && response.data is Map<String, dynamic>) {
203+
if (response.statusCode == 200 &&
204+
response.data is Map<String, dynamic>) {
200205
_loadChapters(response, episode.chapters!);
201206
}
202207
} on DioError catch (e) {
@@ -236,7 +241,8 @@ class Podcast {
236241
final jsonParser = JsonParser();
237242

238243
try {
239-
final response = await client.get(transcriptUrl.url, options: Options(responseType: ResponseType.plain));
244+
final response = await client.get(transcriptUrl.url,
245+
options: Options(responseType: ResponseType.plain));
240246

241247
/// What type of transcript are we loading here?
242248
if (transcriptUrl.type == TranscriptFormat.subrip) {
@@ -285,8 +291,11 @@ class Podcast {
285291

286292
try {
287293
final response = await client.get(url);
288-
if (response.statusCode == 200 && response.data is Map<String, dynamic>) {
294+
295+
if (response.statusCode == 200) {
289296
_loadChapters(response, chapters);
297+
} else {
298+
throw PodcastFailedException('Failed to download chapters file');
290299
}
291300
} on DioError catch (e) {
292301
switch (e.type) {
@@ -306,7 +315,14 @@ class Podcast {
306315
}
307316

308317
static void _loadChapters(Response response, Chapters c) {
309-
final data = Map<String, dynamic>.from(response.data);
318+
Map<String, dynamic> data;
319+
320+
if (response.data is String) {
321+
data = jsonDecode(response.data);
322+
} else {
323+
data = Map.from(response.data);
324+
}
325+
310326
final chapters = data['chapters'] ?? [];
311327

312328
c.headers = ChapterHeaders(
@@ -350,7 +366,9 @@ class Podcast {
350366
title: chapter['title'] ?? '',
351367
startTime: startTime ?? 0.0,
352368
endTime: endTime ?? 0.0,
353-
toc: (chapter['toc'] != null && (chapter['toc'] as bool?) == false) ? false : true),
369+
toc: (chapter['toc'] != null && (chapter['toc'] as bool?) == false)
370+
? false
371+
: true),
354372
);
355373
}
356374
}

lib/src/model/search_result.dart

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ enum ErrorType {
1010
connection,
1111
timeout,
1212
}
13+
1314
enum ResultType {
1415
itunes,
1516
podcastIndex,
@@ -61,10 +62,13 @@ class SearchResult {
6162
processedTime = DateTime.now(),
6263
items = [];
6364

64-
factory SearchResult.fromJson({required dynamic json, ResultType type = ResultType.itunes}) {
65+
factory SearchResult.fromJson(
66+
{required dynamic json, ResultType type = ResultType.itunes}) {
6567
/// Did we get an error message?
6668
if (json['errorMessage'] != null) {
67-
return SearchResult.fromError(lastError: json['errorMessage'] ?? '', lastErrorType: ErrorType.failed);
69+
return SearchResult.fromError(
70+
lastError: json['errorMessage'] ?? '',
71+
lastErrorType: ErrorType.failed);
6872
}
6973

7074
var dataStart = startTagMap[type];
@@ -73,10 +77,13 @@ class SearchResult {
7377
/// Fetch the results from the JSON data.
7478
final items = json[dataStart] == null
7579
? null
76-
: (json[dataStart] as List).cast<Map<String, dynamic>>().map((Map<String, dynamic> item) {
80+
: (json[dataStart] as List)
81+
.cast<Map<String, dynamic>>()
82+
.map((Map<String, dynamic> item) {
7783
return Item.fromJson(json: item, type: type);
7884
}).toList();
7985

80-
return SearchResult(resultCount: json[dataCount] ?? 0, items: items ?? <Item>[]);
86+
return SearchResult(
87+
resultCount: json[dataCount] ?? 0, items: items ?? <Item>[]);
8188
}
8289
}

lib/src/search/base_search.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import 'package:dio/dio.dart';
22
import 'package:podcast_search/podcast_search.dart';
33

4-
const podcastSearchAgent = 'podcast_search/0.4.0 https://github.com/amugofjava/anytime_podcast_player';
4+
const podcastSearchAgent =
5+
'podcast_search/0.4.0 https://github.com/amugofjava/anytime_podcast_player';
56

67
abstract class BaseSearch {
78
/// Contains the type of error returning from the search. If no error occurred it

lib/src/search/itunes_search.dart

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ class ITunesSearch extends BaseSearch {
7777
connectTimeout: timeout,
7878
receiveTimeout: timeout,
7979
headers: {
80-
'User-Agent': userAgent == null || userAgent.isEmpty ? '$podcastSearchAgent' : '$userAgent',
80+
'User-Agent': userAgent == null || userAgent.isEmpty
81+
? '$podcastSearchAgent'
82+
: '$userAgent',
8183
},
8284
),
8385
);
@@ -114,7 +116,8 @@ class ITunesSearch extends BaseSearch {
114116
setLastError(e);
115117
}
116118

117-
return SearchResult.fromError(lastError: lastError ?? '', lastErrorType: lastErrorType);
119+
return SearchResult.fromError(
120+
lastError: lastError ?? '', lastErrorType: lastErrorType);
118121
}
119122

120123
/// Fetches the list of top podcasts
@@ -150,7 +153,8 @@ class ITunesSearch extends BaseSearch {
150153
setLastError(e);
151154
}
152155

153-
return SearchResult.fromError(lastError: lastError ?? '', lastErrorType: lastErrorType);
156+
return SearchResult.fromError(
157+
lastError: lastError ?? '', lastErrorType: lastErrorType);
154158
}
155159

156160
@override
@@ -166,7 +170,8 @@ class ITunesSearch extends BaseSearch {
166170
for (var entry in entries) {
167171
var id = entry['id']['attributes']['im:id'];
168172

169-
final response = await _client.get(feedApiEndpoint + '/lookup?id=$id');
173+
final response =
174+
await _client.get(feedApiEndpoint + '/lookup?id=$id');
170175
final results = json.decode(response.data);
171176

172177
if (results['results'] != null) {
@@ -182,7 +187,8 @@ class ITunesSearch extends BaseSearch {
182187
setLastError(e);
183188
}
184189

185-
return SearchResult.fromError(lastError: lastError ?? '', lastErrorType: lastErrorType);
190+
return SearchResult.fromError(
191+
lastError: lastError ?? '', lastErrorType: lastErrorType);
186192
}
187193

188194
/// This internal method constructs a correctly encoded URL which is then
@@ -233,15 +239,19 @@ class ITunesSearch extends BaseSearch {
233239
}
234240

235241
String _termParam() {
236-
return term != null && term!.isNotEmpty ? '?term=' + Uri.encodeComponent(term!) : '';
242+
return term != null && term!.isNotEmpty
243+
? '?term=' + Uri.encodeComponent(term!)
244+
: '';
237245
}
238246

239247
String _countryParam() {
240248
return _country != Country.none ? '&country=' + _country.code : '';
241249
}
242250

243251
String _attributeParam() {
244-
return _attribute != Attribute.none ? '&attribute=' + Uri.encodeComponent(_attribute!.attribute) : '';
252+
return _attribute != Attribute.none
253+
? '&attribute=' + Uri.encodeComponent(_attribute!.attribute)
254+
: '';
245255
}
246256

247257
String _limitParam() {

lib/src/search/podcast_index_search.dart

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@ import 'package:podcast_search/src/search/base_search.dart';
1313
/// that have been added before making a call to iTunes. The results are unpacked
1414
/// and stored as Item instances and wrapped in a SearchResult.
1515
class PodcastIndexSearch extends BaseSearch {
16-
static String searchApiEndpoint = 'https://api.podcastindex.org/api/1.0/search';
17-
static String trendingApiEndpoint = 'https://api.podcastindex.org/api/1.0/podcasts/trending';
18-
static String genreApiEndpoint = 'https://api.podcastindex.org/api/1.0/categories/list';
16+
static String searchApiEndpoint =
17+
'https://api.podcastindex.org/api/1.0/search';
18+
static String trendingApiEndpoint =
19+
'https://api.podcastindex.org/api/1.0/podcasts/trending';
20+
static String genreApiEndpoint =
21+
'https://api.podcastindex.org/api/1.0/categories/list';
1922

2023
static const _genres = <String>[
2124
'After-Shows',
@@ -186,7 +189,9 @@ class PodcastIndexSearch extends BaseSearch {
186189
'X-Auth-Date': newUnixTime,
187190
'X-Auth-Key': podcastIndexProvider.key,
188191
'Authorization': digest.toString(),
189-
'User-Agent': userAgent == null || userAgent!.isEmpty ? '$podcastSearchAgent' : '$userAgent',
192+
'User-Agent': userAgent == null || userAgent!.isEmpty
193+
? '$podcastSearchAgent'
194+
: '$userAgent',
190195
},
191196
),
192197
);
@@ -213,12 +218,14 @@ class PodcastIndexSearch extends BaseSearch {
213218
try {
214219
var response = await _client.get(_buildSearchUrl(queryParams!));
215220

216-
return SearchResult.fromJson(json: response.data, type: ResultType.podcastIndex);
221+
return SearchResult.fromJson(
222+
json: response.data, type: ResultType.podcastIndex);
217223
} on DioError catch (e) {
218224
setLastError(e);
219225
}
220226

221-
return SearchResult.fromError(lastError: _lastError ?? '', lastErrorType: _lastErrorType);
227+
return SearchResult.fromError(
228+
lastError: _lastError ?? '', lastErrorType: _lastErrorType);
222229
}
223230

224231
/// Fetches the list of top podcasts
@@ -245,12 +252,14 @@ class PodcastIndexSearch extends BaseSearch {
245252
'max': limit,
246253
}..addAll(queryParams));
247254

248-
return SearchResult.fromJson(json: response.data, type: ResultType.podcastIndex);
255+
return SearchResult.fromJson(
256+
json: response.data, type: ResultType.podcastIndex);
249257
} on DioError catch (e) {
250258
setLastError(e);
251259
}
252260

253-
return SearchResult.fromError(lastError: _lastError ?? '', lastErrorType: _lastErrorType);
261+
return SearchResult.fromError(
262+
lastError: _lastError ?? '', lastErrorType: _lastErrorType);
254263
}
255264

256265
@override

lib/src/utils/srt_parser.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ class SrtParser {
4949
milliseconds: endTimeMilliseconds,
5050
);
5151

52-
var subtitle = Subtitle(index: index, start: startTime, end: endTime, data: text ?? '');
52+
var subtitle = Subtitle(
53+
index: index, start: startTime, end: endTime, data: text ?? '');
5354

5455
subtitles.add(subtitle);
5556
}

0 commit comments

Comments
 (0)