Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions lib/domain/podcast/podcast.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import 'package:webfeed/domain/media/license.dart';
import 'package:webfeed/domain/podcast/podcast_funding.dart';
import 'package:webfeed/domain/podcast/podcast_guid.dart';
import 'package:webfeed/domain/podcast/podcast_images.dart';
import 'package:webfeed/domain/podcast/podcast_live_item.dart';
import 'package:webfeed/domain/podcast/podcast_location.dart';
import 'package:webfeed/domain/podcast/podcast_locked.dart';
import 'package:webfeed/domain/podcast/podcast_medium.dart';
import 'package:webfeed/domain/podcast/podcast_person.dart';
import 'package:webfeed/domain/podcast/podcast_trailer.dart';
import 'package:webfeed/domain/podcast/podcast_value.dart';
import 'package:webfeed/util/iterable.dart';
import 'package:xml/xml.dart';

class Podcast {
final Locked? locked;
final Funding? funding;
final List<Person> people;
final Location? location;
final List<Trailer> trailers;
final License? license;
final Guid? guid;
final Value? value;
final Medium? medium;
final Images? images;
final List<LiveItem> liveItems;

Podcast({
this.locked,
this.funding,
required this.people,
this.location,
required this.trailers,
this.license,
this.guid,
this.value,
this.medium,
this.images,
required this.liveItems,
});

factory Podcast.parse(XmlElement element) {
return Podcast(
locked: element
.findElements('podcast:locked')
.map((e) => Locked.parse(e))
.firstOrNull,
funding: element
.findElements('podcast:funding')
.map((e) => Funding.parse(e))
.firstOrNull,
people: element
.findElements('podcast:person')
.map((e) => Person.parse(e))
.toList(),
location: element
.findElements('podcast:location')
.map((e) => Location.parse(e))
.firstOrNull,
trailers: element
.findElements('podcast:trailer')
.map((e) => Trailer.parse(e))
.toList(),
license: element
.findElements('podcast:license')
.map((e) => License.parse(e))
.firstOrNull,
guid: element
.findElements('podcast:guid')
.map((e) => Guid.parse(e))
.firstOrNull,
value: element
.findElements('podcast:value')
.map((e) => Value.parse(e))
.firstOrNull,
medium: element
.findElements('podcast:medium')
.map((e) => Medium.parse(e))
.firstOrNull,
images: element
.findElements('podcast:images')
.map((e) => Images.parse(e))
.firstOrNull,
liveItems: element
.findElements('podcast:liveItem')
.map((e) => LiveItem.parse(e))
.toList(),
);
}
}
57 changes: 57 additions & 0 deletions lib/domain/podcast/podcast_alternate_enclosure.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import 'package:webfeed/domain/podcast/podcast_integrity.dart';
import 'package:webfeed/domain/podcast/podcast_source.dart';
import 'package:xml/xml.dart';

// https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md#alternate-enclosure
class AlternateEnclosure {
final String? type;
final int? length;
final int? bitrate;
final int? height;
final String? lang;
final String? title;
final String? rel;
final String? codecs;
final String? default_;
final List<Source> sources;
final List<Integrity> integrities;

AlternateEnclosure({
this.type,
this.length,
this.bitrate,
this.height,
this.lang,
this.title,
this.rel,
this.codecs,
this.default_,
required this.sources,
required this.integrities,
});

factory AlternateEnclosure.parse(XmlElement element) {
final lengthStr = element.getAttribute('length');
final bitrateStr = element.getAttribute('bitrate');
final heightStr = element.getAttribute('height');
return AlternateEnclosure(
type: element.getAttribute('type'),
length: lengthStr == null ? null : int.tryParse(lengthStr),
bitrate: bitrateStr == null ? null : int.tryParse(bitrateStr),
height: heightStr == null ? null : int.tryParse(heightStr),
lang: element.getAttribute('lang'),
title: element.getAttribute('title'),
rel: element.getAttribute('rel'),
codecs: element.getAttribute('codecs'),
default_: element.getAttribute('default'),
sources: element
.findElements('podcast:source')
.map((e) => Source.parse(e))
.toList(),
integrities: element
.findElements('podcast:integrity')
.map((e) => Integrity.parse(e))
.toList(),
);
}
}
19 changes: 19 additions & 0 deletions lib/domain/podcast/podcast_chapters.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'package:xml/xml.dart';

// https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md#chapters
class Chapters {
final String? url;
final String? type;

Chapters({
this.url,
this.type,
});

factory Chapters.parse(XmlElement element) {
return Chapters(
url: element.getAttribute('url'),
type: element.getAttribute('type'),
);
}
}
19 changes: 19 additions & 0 deletions lib/domain/podcast/podcast_content_link.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'package:xml/xml.dart';

// https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md#content-link
class ContentLink {
final String? href;
final String? value;

ContentLink({
this.href,
this.value,
});

factory ContentLink.parse(XmlElement element) {
return ContentLink(
href: element.getAttribute('href'),
value: element.text,
);
}
}
19 changes: 19 additions & 0 deletions lib/domain/podcast/podcast_episode.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'package:xml/xml.dart';

// https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md#episode
class Episode {
final String? display;
final double? value;

Episode({
this.display,
this.value,
});

factory Episode.parse(XmlElement element) {
return Episode(
display: element.getAttribute('display'),
value: double.tryParse(element.text),
);
}
}
19 changes: 19 additions & 0 deletions lib/domain/podcast/podcast_funding.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'package:xml/xml.dart';

// https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md#funding
class Funding {
final String? url;
final String? value;

Funding({
this.url,
this.value,
});

factory Funding.parse(XmlElement element) {
return Funding(
url: element.getAttribute('url'),
value: element.text,
);
}
}
16 changes: 16 additions & 0 deletions lib/domain/podcast/podcast_guid.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import 'package:xml/xml.dart';

// https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md#guid
class Guid {
final String? value;

Guid({
this.value,
});

factory Guid.parse(XmlElement element) {
return Guid(
value: element.text,
);
}
}
31 changes: 31 additions & 0 deletions lib/domain/podcast/podcast_images.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import 'package:xml/xml.dart';

final exp = RegExp(r'([^ ]+) (\d)+w');

class Src {
final String? url;
final int? width;

Src({required this.url, required this.width});
}

// https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md#images
class Images {
final List<Src> srcset;

Images({
required this.srcset,
});

factory Images.parse(XmlElement element) {
return Images(
srcset: element.getAttribute('srcset')?.split(', ').map((e) {
final matches = exp.allMatches(e).toList();
return Src(
url: matches[0].toString(),
width: int.tryParse(matches[1].toString()));
}).toList() ??
[],
);
}
}
19 changes: 19 additions & 0 deletions lib/domain/podcast/podcast_integrity.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'package:xml/xml.dart';

// https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md#integrity
class Integrity {
final String? type;
final String? value;

Integrity({
this.type,
this.value,
});

factory Integrity.parse(XmlElement element) {
return Integrity(
type: element.getAttribute('type'),
value: element.getAttribute('value'),
);
}
}
97 changes: 97 additions & 0 deletions lib/domain/podcast/podcast_item.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import 'package:webfeed/domain/media/license.dart';
import 'package:webfeed/domain/podcast/podcast_alternate_enclosure.dart';
import 'package:webfeed/domain/podcast/podcast_chapters.dart';
import 'package:webfeed/domain/podcast/podcast_content_link.dart';
import 'package:webfeed/domain/podcast/podcast_episode.dart';
import 'package:webfeed/domain/podcast/podcast_images.dart';
import 'package:webfeed/domain/podcast/podcast_location.dart';
import 'package:webfeed/domain/podcast/podcast_person.dart';
import 'package:webfeed/domain/podcast/podcast_season.dart';
import 'package:webfeed/domain/podcast/podcast_soundbite.dart';
import 'package:webfeed/domain/podcast/podcast_transcript.dart';
import 'package:webfeed/domain/podcast/podcast_value.dart';
import 'package:webfeed/util/iterable.dart';
import 'package:xml/xml.dart';

class PodcastItem {
final Transcript? transcript;
final Chapters? chapters;
final List<Soundbite> soundbites;
final List<Person> people;
final Location? location;
final Season? season;
final Episode? episode;
final License? license;
final List<AlternateEnclosure> alternateEnclosures;
final Value? value;
final Images? images;
final List<ContentLink> contentLinks;

PodcastItem({
this.transcript,
this.chapters,
required this.soundbites,
required this.people,
this.location,
this.season,
this.episode,
this.license,
required this.alternateEnclosures,
this.value,
this.images,
required this.contentLinks,
});

factory PodcastItem.parse(XmlElement element) {
return PodcastItem(
transcript: element
.findElements('podcast:transcript')
.map((e) => Transcript.parse(e))
.firstOrNull,
chapters: element
.findElements('podcast:chapters')
.map((e) => Chapters.parse(e))
.firstOrNull,
soundbites: element
.findElements('podcast:soundbite')
.map((e) => Soundbite.parse(e))
.toList(),
people: element
.findElements('podcast:person')
.map((e) => Person.parse(e))
.toList(),
location: element
.findElements('podcast:location')
.map((e) => Location.parse(e))
.firstOrNull,
season: element
.findElements('podcast:season')
.map((e) => Season.parse(e))
.firstOrNull,
episode: element
.findElements('podcast:episode')
.map((e) => Episode.parse(e))
.firstOrNull,
license: element
.findElements('podcast:license')
.map((e) => License.parse(e))
.firstOrNull,
alternateEnclosures: element
.findElements('podcast:alternateEnclosure')
.map((e) => AlternateEnclosure.parse(e))
.toList(),
value: element
.findElements('podcast:value')
.map((e) => Value.parse(e))
.firstOrNull,
images: element
.findElements('podcast:images')
.map((e) => Images.parse(e))
.firstOrNull,
contentLinks: element
.findElements('podcast:contentLink')
.map((e) => ContentLink.parse(e))
.toList(),
);
}
}
Loading