Skip to content

Commit

Permalink
Improve support for PC2.0 chapters. Fix formatting.
Browse files Browse the repository at this point in the history
  • Loading branch information
amugofjava committed Apr 20, 2023
1 parent ac620c6 commit 867134d
Show file tree
Hide file tree
Showing 12 changed files with 100 additions and 41 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.5.5

- Improve PC2.0 chapter support.

## 0.5.4

- Add support for PC2.0 Transcripts (json/srt/subrip);
Expand Down
3 changes: 1 addition & 2 deletions lib/src/model/attribute.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ enum Attribute {
const Attribute({
required this.attribute,
});

final String attribute;
}

17 changes: 12 additions & 5 deletions lib/src/model/item.dart
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,12 @@ 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 @@ -139,7 +143,8 @@ 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>()),
genre: Item._loadGenres(
json['genreIds'].cast<String>(), json['genres'].cast<String>()),
releaseDate: DateTime.parse(json['releaseDate']),
country: json['country'] as String?,
primaryGenreName: json['primaryGenreName'] as String?,
Expand All @@ -148,14 +153,16 @@ class Item {
}

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
8 changes: 5 additions & 3 deletions lib/src/model/language.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
// MIT license that can be found in the LICENSE file.

/// An Enum that provides a list of the languages the iTunes API currently supports.
enum Language{
enum Language {
none(code: ''),
enUs(code: 'en_us'),
jaJp(code: 'en_us');

const Language({required this.code,});
const Language({
required this.code,
});

final String code;
}
}
32 changes: 25 additions & 7 deletions lib/src/model/podcast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// MIT license that can be found in the LICENSE file.

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:dart_rss/dart_rss.dart';
Expand Down Expand Up @@ -73,7 +74,8 @@ class Podcast {
connectTimeout: timeout,
receiveTimeout: timeout,
headers: {
'User-Agent': userAgent.isEmpty ? '$podcastSearchAgent' : '$userAgent',
'User-Agent':
userAgent.isEmpty ? '$podcastSearchAgent' : '$userAgent',
},
),
);
Expand Down Expand Up @@ -192,11 +194,14 @@ class Podcast {
),
);

if (episode.chapters!.chapters.isNotEmpty && !episode.chapters!.loaded && !forceReload) {
if (episode.chapters!.chapters.isNotEmpty &&
!episode.chapters!.loaded &&
!forceReload) {
try {
final response = await client.get(episode.chapters!.url);

if (response.statusCode == 200 && response.data is Map<String, dynamic>) {
if (response.statusCode == 200 &&
response.data is Map<String, dynamic>) {
_loadChapters(response, episode.chapters!);
}
} on DioError catch (e) {
Expand Down Expand Up @@ -236,7 +241,8 @@ class Podcast {
final jsonParser = JsonParser();

try {
final response = await client.get(transcriptUrl.url, options: Options(responseType: ResponseType.plain));
final response = await client.get(transcriptUrl.url,
options: Options(responseType: ResponseType.plain));

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

try {
final response = await client.get(url);
if (response.statusCode == 200 && response.data is Map<String, dynamic>) {

if (response.statusCode == 200) {
_loadChapters(response, chapters);
} else {
throw PodcastFailedException('Failed to download chapters file');
}
} on DioError catch (e) {
switch (e.type) {
Expand All @@ -306,7 +315,14 @@ class Podcast {
}

static void _loadChapters(Response response, Chapters c) {
final data = Map<String, dynamic>.from(response.data);
Map<String, dynamic> data;

if (response.data is String) {
data = jsonDecode(response.data);
} else {
data = Map.from(response.data);
}

final chapters = data['chapters'] ?? [];

c.headers = ChapterHeaders(
Expand Down Expand Up @@ -350,7 +366,9 @@ class Podcast {
title: chapter['title'] ?? '',
startTime: startTime ?? 0.0,
endTime: endTime ?? 0.0,
toc: (chapter['toc'] != null && (chapter['toc'] as bool?) == false) ? false : true),
toc: (chapter['toc'] != null && (chapter['toc'] as bool?) == false)
? false
: true),
);
}
}
Expand Down
15 changes: 11 additions & 4 deletions lib/src/model/search_result.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ enum ErrorType {
connection,
timeout,
}

enum ResultType {
itunes,
podcastIndex,
Expand Down Expand Up @@ -61,10 +62,13 @@ class SearchResult {
processedTime = DateTime.now(),
items = [];

factory SearchResult.fromJson({required dynamic json, ResultType type = ResultType.itunes}) {
factory SearchResult.fromJson(
{required dynamic json, ResultType type = ResultType.itunes}) {
/// Did we get an error message?
if (json['errorMessage'] != null) {
return SearchResult.fromError(lastError: json['errorMessage'] ?? '', lastErrorType: ErrorType.failed);
return SearchResult.fromError(
lastError: json['errorMessage'] ?? '',
lastErrorType: ErrorType.failed);
}

var dataStart = startTagMap[type];
Expand All @@ -73,10 +77,13 @@ class SearchResult {
/// Fetch the results from the JSON data.
final items = json[dataStart] == null
? null
: (json[dataStart] as List).cast<Map<String, dynamic>>().map((Map<String, dynamic> item) {
: (json[dataStart] as List)
.cast<Map<String, dynamic>>()
.map((Map<String, dynamic> item) {
return Item.fromJson(json: item, type: type);
}).toList();

return SearchResult(resultCount: json[dataCount] ?? 0, items: items ?? <Item>[]);
return SearchResult(
resultCount: json[dataCount] ?? 0, items: items ?? <Item>[]);
}
}
3 changes: 2 additions & 1 deletion lib/src/search/base_search.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import 'package:dio/dio.dart';
import 'package:podcast_search/podcast_search.dart';

const podcastSearchAgent = 'podcast_search/0.4.0 https://github.com/amugofjava/anytime_podcast_player';
const podcastSearchAgent =
'podcast_search/0.4.0 https://github.com/amugofjava/anytime_podcast_player';

abstract class BaseSearch {
/// Contains the type of error returning from the search. If no error occurred it
Expand Down
24 changes: 17 additions & 7 deletions lib/src/search/itunes_search.dart
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ class ITunesSearch extends BaseSearch {
connectTimeout: timeout,
receiveTimeout: timeout,
headers: {
'User-Agent': userAgent == null || userAgent.isEmpty ? '$podcastSearchAgent' : '$userAgent',
'User-Agent': userAgent == null || userAgent.isEmpty
? '$podcastSearchAgent'
: '$userAgent',
},
),
);
Expand Down Expand Up @@ -114,7 +116,8 @@ 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 @@ -150,7 +153,8 @@ class ITunesSearch extends BaseSearch {
setLastError(e);
}

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

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

final response = await _client.get(feedApiEndpoint + '/lookup?id=$id');
final response =
await _client.get(feedApiEndpoint + '/lookup?id=$id');
final results = json.decode(response.data);

if (results['results'] != null) {
Expand All @@ -182,7 +187,8 @@ 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 @@ -233,15 +239,19 @@ 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
25 changes: 17 additions & 8 deletions lib/src/search/podcast_index_search.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ import 'package:podcast_search/src/search/base_search.dart';
/// that have been added before making a call to iTunes. The results are unpacked
/// and stored as Item instances and wrapped in a SearchResult.
class PodcastIndexSearch extends BaseSearch {
static String searchApiEndpoint = 'https://api.podcastindex.org/api/1.0/search';
static String trendingApiEndpoint = 'https://api.podcastindex.org/api/1.0/podcasts/trending';
static String genreApiEndpoint = 'https://api.podcastindex.org/api/1.0/categories/list';
static String searchApiEndpoint =
'https://api.podcastindex.org/api/1.0/search';
static String trendingApiEndpoint =
'https://api.podcastindex.org/api/1.0/podcasts/trending';
static String genreApiEndpoint =
'https://api.podcastindex.org/api/1.0/categories/list';

static const _genres = <String>[
'After-Shows',
Expand Down Expand Up @@ -186,7 +189,9 @@ class PodcastIndexSearch extends BaseSearch {
'X-Auth-Date': newUnixTime,
'X-Auth-Key': podcastIndexProvider.key,
'Authorization': digest.toString(),
'User-Agent': userAgent == null || userAgent!.isEmpty ? '$podcastSearchAgent' : '$userAgent',
'User-Agent': userAgent == null || userAgent!.isEmpty
? '$podcastSearchAgent'
: '$userAgent',
},
),
);
Expand All @@ -213,12 +218,14 @@ class PodcastIndexSearch extends BaseSearch {
try {
var response = await _client.get(_buildSearchUrl(queryParams!));

return SearchResult.fromJson(json: response.data, type: ResultType.podcastIndex);
return SearchResult.fromJson(
json: response.data, type: ResultType.podcastIndex);
} on DioError catch (e) {
setLastError(e);
}

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

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

return SearchResult.fromJson(json: response.data, type: ResultType.podcastIndex);
return SearchResult.fromJson(
json: response.data, type: ResultType.podcastIndex);
} on DioError catch (e) {
setLastError(e);
}

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

@override
Expand Down
3 changes: 2 additions & 1 deletion lib/src/utils/srt_parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ class SrtParser {
milliseconds: endTimeMilliseconds,
);

var subtitle = Subtitle(index: index, start: startTime, end: endTime, data: text ?? '');
var subtitle = Subtitle(
index: index, start: startTime, end: endTime, data: text ?? '');

subtitles.add(subtitle);
}
Expand Down
5 changes: 3 additions & 2 deletions lib/src/utils/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,8 @@ class Utils {

static const _allowablePatterns = {
// Mon, 03 Jun 2019 10:00:00 PDT (type 1)
'([A-Za-z]{3}), ([0-9]{1,2}) ([A-Za-z]*) ([0-9]{4}) ([0-9][0-9]:[0-9][0-9]:[0-9][0-9]) ([A-Za-z]{3})': 1,
'([A-Za-z]{3}), ([0-9]{1,2}) ([A-Za-z]*) ([0-9]{4}) ([0-9][0-9]:[0-9][0-9]:[0-9][0-9]) ([A-Za-z]{3})':
1,

// Mon, 03 Jun 2019 10:00:00 +02:30 (type 2)
'([A-Za-z]{3}), ([0-9]{1,2}) ([A-Za-z]*) ([0-9]{4}) ([0-9][0-9]:[0-9][0-9]:[0-9][0-9]) ([\+|\-][0-9][0-9]:[0-9][0-9])':
Expand Down Expand Up @@ -233,7 +234,7 @@ class Utils {
/// timezone code, so this will probably suffice for a large proportion of dates in that
/// format. Hopefully, most pubDate values will use a UTC offset instead.
static DateTime? parseRFC2822Date(String date) {
var result;
DateTime? result;

_allowablePatterns.forEach((k, v) {
final exp = RegExp(k);
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, parsing podcast RSS feeds and obtaining episodes details. Supports searching via iTunes and PodcastIndex (preview).

version: 0.5.4
version: 0.5.5
homepage: https://github.com/amugofjava/podcast_search

environment:
Expand Down

0 comments on commit 867134d

Please sign in to comment.