Ver código fonte

refactor itunes

master
Wito Chandra 6 anos atrás
pai
commit
9a843763fe
14 arquivos alterados com 157 adições e 218 exclusões
  1. +103
    -0
      lib/domain/itunes/itunes.dart
  2. +4
    -4
      lib/domain/itunes/itunes_category.dart
  3. +16
    -0
      lib/domain/itunes/itunes_episode_type.dart
  4. +4
    -4
      lib/domain/itunes/itunes_image.dart
  5. +5
    -6
      lib/domain/itunes/itunes_owner.dart
  6. +14
    -0
      lib/domain/itunes/itunes_type.dart
  7. +3
    -4
      lib/domain/rss_feed.dart
  8. +3
    -3
      lib/domain/rss_item.dart
  9. +0
    -89
      lib/domain/rss_item_itunes.dart
  10. +0
    -67
      lib/domain/rss_itunes.dart
  11. +0
    -19
      lib/domain/rss_itunes_episode_type.dart
  12. +0
    -17
      lib/domain/rss_itunes_type.dart
  13. +1
    -1
      lib/util/xml.dart
  14. +4
    -4
      test/rss_test.dart

+ 103
- 0
lib/domain/itunes/itunes.dart Ver arquivo

@@ -0,0 +1,103 @@
import 'package:webfeed/domain/itunes/itunes_category.dart';
import 'package:webfeed/domain/itunes/itunes_episode_type.dart';
import 'package:webfeed/domain/itunes/itunes_image.dart';
import 'package:webfeed/domain/itunes/itunes_owner.dart';
import 'package:webfeed/domain/itunes/itunes_type.dart';
import 'package:webfeed/util/xml.dart';
import 'package:xml/xml.dart';

class Itunes {
final String author;
final String summary;
final bool explicit;
final String title;
final String subtitle;
final ItunesOwner owner;
final List<String> keywords;
final ItunesImage image;
final List<ItunesCategory> categories;
final ItunesType type;
final String newFeedUrl;
final bool block;
final bool complete;
final int episode;
final int season;
final Duration duration;
final ItunesEpisodeType episodeType;

Itunes({
this.author,
this.summary,
this.explicit,
this.title,
this.subtitle,
this.owner,
this.keywords,
this.image,
this.categories,
this.type,
this.newFeedUrl,
this.block,
this.complete,
this.episode,
this.season,
this.duration,
this.episodeType,
});

factory Itunes.parse(XmlElement element) {
if (element == null) {
return null;
}
var episodeStr = findElementOrNull(element, 'itunes:episode')?.text?.trim();
var seasonStr = findElementOrNull(element, 'itunes:season')?.text?.trim();
var durationStr =
findElementOrNull(element, 'itunes:duration')?.text?.trim();
return Itunes(
author: findElementOrNull(element, 'itunes:author')?.text?.trim(),
summary: findElementOrNull(element, 'itunes:summary')?.text?.trim(),
explicit: parseBoolLiteral(element, 'itunes:explicit'),
title: findElementOrNull(element, 'itunes:title')?.text?.trim(),
subtitle: findElementOrNull(element, 'itunes:subtitle')?.text?.trim(),
owner: ItunesOwner.parse(findElementOrNull(element, 'itunes:owner')),
keywords: findElementOrNull(element, 'itunes:keywords')
?.text
?.split(',')
?.map((keyword) => keyword.trim())
?.toList(),
image: ItunesImage.parse(findElementOrNull(element, 'itunes:image')),
categories: findAllDirectElementsOrNull(element, 'itunes:category')
.map((ele) => ItunesCategory.parse(ele))
.toList(),
type: newItunesType(findElementOrNull(element, 'itunes:type')),
newFeedUrl:
findElementOrNull(element, 'itunes:new-feed-url')?.text?.trim(),
block: parseBoolLiteral(element, 'itunes:block'),
complete: parseBoolLiteral(element, 'itunes:complete'),
episode: episodeStr == null ? null : int.parse(episodeStr),
season: seasonStr == null ? null : int.parse(seasonStr),
duration: durationStr == null ? null : _parseDuration(durationStr),
episodeType: newItunesEpisodeType(
findElementOrNull(element, 'itunes:episodeType')),
);
}

static Duration _parseDuration(String s) {
var hours = 0;
var minutes = 0;
var seconds = 0;
var parts = s.split(':');
if (parts.length > 2) {
hours = int.parse(parts[parts.length - 3]);
}
if (parts.length > 1) {
minutes = int.parse(parts[parts.length - 2]);
}
seconds = int.parse(parts[parts.length - 1]);
return Duration(
hours: hours,
minutes: minutes,
seconds: seconds,
);
}
}

lib/domain/rss_itunes_category.dart → lib/domain/itunes/itunes_category.dart Ver arquivo

@@ -1,12 +1,12 @@
import 'package:xml/xml.dart';

class RssItunesCategory {
class ItunesCategory {
final String category;
final List<String> subCategories;

RssItunesCategory({this.category, this.subCategories});
ItunesCategory({this.category, this.subCategories});

factory RssItunesCategory.parse(XmlElement element) {
factory ItunesCategory.parse(XmlElement element) {
if (element == null) return null;

Iterable<XmlElement> subCategories;
@@ -15,7 +15,7 @@ class RssItunesCategory {
} on StateError {
subCategories = null;
}
return RssItunesCategory(
return ItunesCategory(
category: element.getAttribute('text')?.trim(),
subCategories: subCategories
?.map((ele) => ele.getAttribute('text')?.trim())

+ 16
- 0
lib/domain/itunes/itunes_episode_type.dart Ver arquivo

@@ -0,0 +1,16 @@
import 'package:xml/xml.dart';

enum ItunesEpisodeType { full, trailer, bonus, unknown }

ItunesEpisodeType newItunesEpisodeType(XmlElement element) {
switch (element?.text) {
case 'full':
return ItunesEpisodeType.full;
case 'trailer':
return ItunesEpisodeType.trailer;
case 'bonus':
return ItunesEpisodeType.bonus;
default:
return ItunesEpisodeType.unknown;
}
}

lib/domain/rss_itunes_image.dart → lib/domain/itunes/itunes_image.dart Ver arquivo

@@ -1,13 +1,13 @@
import 'package:xml/xml.dart';

class RssItunesImage {
class ItunesImage {
final String href;

RssItunesImage({this.href});
ItunesImage({this.href});

factory RssItunesImage.parse(XmlElement element) {
factory ItunesImage.parse(XmlElement element) {
if (element == null) return null;
return RssItunesImage(
return ItunesImage(
href: element.getAttribute('href')?.trim(),
);
}

lib/domain/rss_itunes_owner.dart → lib/domain/itunes/itunes_owner.dart Ver arquivo

@@ -1,16 +1,15 @@
import 'package:webfeed/util/xml.dart';
import 'package:xml/xml.dart';

import '../util/xml.dart';

class RssItunesOwner {
class ItunesOwner {
final String name;
final String email;

RssItunesOwner({this.name, this.email});
ItunesOwner({this.name, this.email});

factory RssItunesOwner.parse(XmlElement element) {
factory ItunesOwner.parse(XmlElement element) {
if (element == null) return null;
return RssItunesOwner(
return ItunesOwner(
name: findElementOrNull(element, 'itunes:name')?.text?.trim(),
email: findElementOrNull(element, 'itunes:email')?.text?.trim(),
);

+ 14
- 0
lib/domain/itunes/itunes_type.dart Ver arquivo

@@ -0,0 +1,14 @@
import 'package:xml/xml.dart';

enum ItunesType { episodic, serial, unknown }

ItunesType newItunesType(XmlElement element) {
switch (element?.text) {
case 'episodic':
return ItunesType.episodic;
case 'serial':
return ItunesType.serial;
default:
return ItunesType.unknown;
}
}

+ 3
- 4
lib/domain/rss_feed.dart Ver arquivo

@@ -1,6 +1,7 @@
import 'dart:core';

import 'package:webfeed/domain/dublin_core/dublin_core.dart';
import 'package:webfeed/domain/itunes/itunes.dart';
import 'package:webfeed/domain/rss_category.dart';
import 'package:webfeed/domain/rss_cloud.dart';
import 'package:webfeed/domain/rss_image.dart';
@@ -8,8 +9,6 @@ import 'package:webfeed/domain/rss_item.dart';
import 'package:webfeed/util/xml.dart';
import 'package:xml/xml.dart';

import 'rss_itunes.dart';

class RssFeed {
final String title;
final String author;
@@ -32,7 +31,7 @@ class RssFeed {
final String webMaster;
final int ttl;
final DublinCore dc;
final RssItunes itunes;
final Itunes itunes;

RssFeed({
this.title,
@@ -102,7 +101,7 @@ class RssFeed {
webMaster: findElementOrNull(channelElement, 'webMaster')?.text,
ttl: int.tryParse(findElementOrNull(channelElement, 'ttl')?.text ?? '0'),
dc: DublinCore.parse(channelElement),
itunes: RssItunes.parse(channelElement),
itunes: Itunes.parse(channelElement),
);
}
}

+ 3
- 3
lib/domain/rss_item.dart Ver arquivo

@@ -1,9 +1,9 @@
import 'package:webfeed/domain/dublin_core/dublin_core.dart';
import 'package:webfeed/domain/itunes/itunes.dart';
import 'package:webfeed/domain/media/media.dart';
import 'package:webfeed/domain/rss_category.dart';
import 'package:webfeed/domain/rss_content.dart';
import 'package:webfeed/domain/rss_enclosure.dart';
import 'package:webfeed/domain/rss_item_itunes.dart';
import 'package:webfeed/domain/rss_source.dart';
import 'package:webfeed/util/datetime.dart';
import 'package:webfeed/util/xml.dart';
@@ -24,7 +24,7 @@ class RssItem {
final Media media;
final RssEnclosure enclosure;
final DublinCore dc;
final RssItemItunes itunes;
final Itunes itunes;

RssItem({
this.title,
@@ -60,7 +60,7 @@ class RssItem {
media: Media.parse(element),
enclosure: RssEnclosure.parse(findElementOrNull(element, 'enclosure')),
dc: DublinCore.parse(element),
itunes: RssItemItunes.parse(element),
itunes: Itunes.parse(element),
);
}
}

+ 0
- 89
lib/domain/rss_item_itunes.dart Ver arquivo

@@ -1,89 +0,0 @@
import 'package:webfeed/util/xml.dart';
import 'package:xml/xml.dart';

import 'rss_itunes_category.dart';
import 'rss_itunes_episode_type.dart';
import 'rss_itunes_image.dart';

class RssItemItunes {
final String title;
final int episode;
final int season;
final Duration duration;
final RssItunesEpisodeType episodeType;
final String author;
final String summary;
final bool explicit;
final String subtitle;
final List<String> keywords;
final RssItunesImage image;
final RssItunesCategory category;
final bool block;

RssItemItunes({
this.title,
this.episode,
this.season,
this.duration,
this.episodeType,
this.author,
this.summary,
this.explicit,
this.subtitle,
this.keywords,
this.image,
this.category,
this.block,
});

factory RssItemItunes.parse(XmlElement element) {
if (element == null) {
return null;
}
var episodeStr = findElementOrNull(element, 'itunes:episode')?.text?.trim();
var seasonStr = findElementOrNull(element, 'itunes:season')?.text?.trim();
var durationStr =
findElementOrNull(element, 'itunes:duration')?.text?.trim();

return RssItemItunes(
title: findElementOrNull(element, 'itunes:title')?.text?.trim(),
episode: episodeStr == null ? null : int.parse(episodeStr),
season: seasonStr == null ? null : int.parse(seasonStr),
duration: durationStr == null ? null : parseDuration(durationStr),
episodeType: newRssItunesEpisodeType(
findElementOrNull(element, 'itunes:episodeType')),
author: findElementOrNull(element, 'itunes:author')?.text?.trim(),
summary: findElementOrNull(element, 'itunes:summary')?.text?.trim(),
explicit: parseBoolLiteral(element, 'itunes:explicit'),
subtitle: findElementOrNull(element, 'itunes:subtitle')?.text?.trim(),
keywords: findElementOrNull(element, 'itunes:keywords')
?.text
?.split(',')
?.map((keyword) => keyword.trim())
?.toList(),
image: RssItunesImage.parse(findElementOrNull(element, 'itunes:image')),
category: RssItunesCategory.parse(
findElementOrNull(element, 'itunes:category')),
block: parseBoolLiteral(element, 'itunes:block'),
);
}
}

Duration parseDuration(String s) {
var hours = 0;
var minutes = 0;
var seconds = 0;
var parts = s.split(':');
if (parts.length > 2) {
hours = int.parse(parts[parts.length - 3]);
}
if (parts.length > 1) {
minutes = int.parse(parts[parts.length - 2]);
}
seconds = int.parse(parts[parts.length - 1]);
return Duration(
hours: hours,
minutes: minutes,
seconds: seconds,
);
}

+ 0
- 67
lib/domain/rss_itunes.dart Ver arquivo

@@ -1,67 +0,0 @@
import 'package:webfeed/util/xml.dart';
import 'package:xml/xml.dart';

import 'rss_itunes_category.dart';
import 'rss_itunes_image.dart';
import 'rss_itunes_owner.dart';
import 'rss_itunes_type.dart';

class RssItunes {
final String author;
final String summary;
final bool explicit;
final String title;
final String subtitle;
final RssItunesOwner owner;
final List<String> keywords;
final RssItunesImage image;
final List<RssItunesCategory> categories;
final RssItunesType type;
final String newFeedUrl;
final bool block;
final bool complete;

RssItunes({
this.author,
this.summary,
this.explicit,
this.title,
this.subtitle,
this.owner,
this.keywords,
this.image,
this.categories,
this.type,
this.newFeedUrl,
this.block,
this.complete,
});

factory RssItunes.parse(XmlElement element) {
if (element == null) {
return null;
}
return RssItunes(
author: findElementOrNull(element, 'itunes:author')?.text?.trim(),
summary: findElementOrNull(element, 'itunes:summary')?.text?.trim(),
explicit: parseBoolLiteral(element, 'itunes:explicit'),
title: findElementOrNull(element, 'itunes:title')?.text?.trim(),
subtitle: findElementOrNull(element, 'itunes:subtitle')?.text?.trim(),
owner: RssItunesOwner.parse(findElementOrNull(element, 'itunes:owner')),
keywords: findElementOrNull(element, 'itunes:keywords')
?.text
?.split(',')
?.map((keyword) => keyword.trim())
?.toList(),
image: RssItunesImage.parse(findElementOrNull(element, 'itunes:image')),
categories: findAllDirectElementsOrNull(element, 'itunes:category')
.map((ele) => RssItunesCategory.parse(ele))
.toList(),
type: newRssItunesType(findElementOrNull(element, 'itunes:type')),
newFeedUrl:
findElementOrNull(element, 'itunes:new-feed-url')?.text?.trim(),
block: parseBoolLiteral(element, 'itunes:block'),
complete: parseBoolLiteral(element, 'itunes:complete'),
);
}
}

+ 0
- 19
lib/domain/rss_itunes_episode_type.dart Ver arquivo

@@ -1,19 +0,0 @@
import 'package:xml/xml.dart';

enum RssItunesEpisodeType { full, trailer, bonus }

RssItunesEpisodeType newRssItunesEpisodeType(XmlElement element) {
// "full" is default type
if (element == null) return RssItunesEpisodeType.full;

switch (element.text) {
case 'full':
return RssItunesEpisodeType.full;
case 'trailer':
return RssItunesEpisodeType.trailer;
case 'bonus':
return RssItunesEpisodeType.bonus;
default:
return null;
}
}

+ 0
- 17
lib/domain/rss_itunes_type.dart Ver arquivo

@@ -1,17 +0,0 @@
import 'package:xml/xml.dart';

enum RssItunesType { episodic, serial }

RssItunesType newRssItunesType(XmlElement element) {
// 'episodic' is default type
if (element == null) return RssItunesType.episodic;

switch (element.text) {
case 'episodic':
return RssItunesType.episodic;
case 'serial':
return RssItunesType.serial;
default:
return null;
}
}

+ 1
- 1
lib/util/xml.dart Ver arquivo

@@ -22,6 +22,6 @@ List<XmlElement> findAllDirectElementsOrNull(XmlElement element, String name,

bool parseBoolLiteral(XmlElement element, String tagName) {
var v = findElementOrNull(element, tagName)?.text?.toLowerCase()?.trim();
if (v == null) return null;
if (v == null) return false;
return ['yes', 'true'].contains(v);
}

+ 4
- 4
test/rss_test.dart Ver arquivo

@@ -2,8 +2,8 @@ import 'dart:core';
import 'dart:io';

import 'package:test/test.dart';
import 'package:webfeed/domain/rss_itunes_episode_type.dart';
import 'package:webfeed/domain/rss_itunes_type.dart';
import 'package:webfeed/domain/itunes/itunes_episode_type.dart';
import 'package:webfeed/domain/itunes/itunes_type.dart';
import 'package:webfeed/webfeed.dart';

void main() {
@@ -344,13 +344,13 @@ void main() {
}
}
expect(feed.itunes.title, 'Go Time');
expect(feed.itunes.type, RssItunesType.serial);
expect(feed.itunes.type, ItunesType.serial);
expect(feed.itunes.newFeedUrl, 'wubawuba');
expect(feed.itunes.block, true);
expect(feed.itunes.complete, true);

var item = feed.items[0];
expect(item.itunes.episodeType, RssItunesEpisodeType.full);
expect(item.itunes.episodeType, ItunesEpisodeType.full);
expect(item.itunes.episode, 1);
expect(item.itunes.season, 1);
expect(item.itunes.image.href,


Carregando…
Cancelar
Salvar