use feedparser_rs::parse;
use std::fs;
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== Feed Parser Example: Podcast Feed ===\n");
let feed_path = "examples/feeds/sample_podcast.xml";
let feed_data = fs::read(feed_path)?;
let feed = parse(&feed_data)?;
println!("Feed Version: {}", feed.version);
println!("{}", "=".repeat(60));
display_podcast_metadata(&feed);
println!("\n{}\n", "=".repeat(60));
display_episodes(&feed);
Ok(())
}
fn display_podcast_metadata(feed: &feedparser_rs::ParsedFeed) {
println!("Podcast Metadata:");
println!("{}", "-".repeat(40));
if let Some(title) = &feed.feed.title {
println!("\nTitle: {title}");
}
if let Some(subtitle) = &feed.feed.subtitle {
println!("Subtitle: {subtitle}");
}
if let Some(itunes) = &feed.feed.itunes {
println!("\niTunes Metadata:");
if let Some(author) = &itunes.author {
println!(" Author: {author}");
}
if let Some(owner) = &itunes.owner {
println!(" Owner:");
if let Some(name) = &owner.name {
println!(" Name: {name}");
}
if let Some(email) = &owner.email {
println!(" Email: {email}");
}
}
if let Some(explicit) = itunes.explicit {
println!(" Explicit: {}", if explicit { "YES" } else { "NO" });
}
if let Some(image) = &itunes.image {
println!(" Artwork: {image}");
}
if !itunes.categories.is_empty() {
println!(" Categories:");
for cat in &itunes.categories {
print!(" - {}", cat.text);
if let Some(subcategory) = &cat.subcategory {
print!(" > {subcategory}");
}
println!();
}
}
if let Some(podcast_type) = &itunes.podcast_type {
println!(" Type: {podcast_type}");
}
if itunes
.complete
.as_deref()
.is_some_and(|v| v.eq_ignore_ascii_case("yes"))
{
println!(" Status: Complete (no more episodes will be released)");
}
}
if let Some(podcast) = &feed.feed.podcast {
println!("\nPodcast 2.0 Metadata:");
if !podcast.funding.is_empty() {
println!(" Funding:");
for funding in &podcast.funding {
print!(" - {}", funding.url);
if let Some(message) = &funding.message {
print!(": {message}");
}
println!();
}
}
if !podcast.persons.is_empty() {
println!(" People:");
for person in &podcast.persons {
print!(" - {}", person.name);
if let Some(role) = &person.role {
print!(" [{role}]");
}
if let Some(img) = &person.img {
print!(" (photo: {img})");
}
println!();
}
}
if let Some(value) = &podcast.value {
println!(" Value4Value:");
println!(" Type: {}", value.type_);
println!(" Method: {}", value.method);
if !value.recipients.is_empty() {
println!(" Recipients:");
for recipient in &value.recipients {
if let Some(name) = &recipient.name {
print!(" - {name}");
print!(" ({}%)", recipient.split);
println!();
}
}
}
}
}
}
fn display_episodes(feed: &feedparser_rs::ParsedFeed) {
println!("Episodes ({} total):", feed.entries.len());
println!("{}", "-".repeat(40));
for (i, entry) in feed.entries.iter().enumerate() {
println!("\nEpisode {}:", i + 1);
if let Some(title) = &entry.title {
println!(" Title: {title}");
}
if let Some(link) = &entry.link {
println!(" Link: {link}");
}
if let Some(published) = &entry.published {
println!(" Published: {published}");
}
if !entry.enclosures.is_empty() {
println!(" Audio:");
for enc in &entry.enclosures {
println!(" URL: {}", enc.url);
if let Some(enclosure_type) = &enc.enclosure_type {
println!(" Type: {enclosure_type}");
}
if let Some(length) = &enc.length {
if let Ok(bytes) = length.parse::<u64>() {
#[allow(clippy::cast_precision_loss)]
let mb = bytes as f64 / 1_048_576.0;
println!(" Size: {mb:.2} MB ({bytes} bytes)");
} else {
println!(" Size: {length} bytes");
}
}
}
}
if let Some(itunes) = &entry.itunes {
println!(" iTunes:");
if let Some(duration) = &itunes.duration {
println!(" Duration: {duration}");
}
if let Some(episode_num) = &itunes.episode {
println!(" Episode Number: {episode_num}");
}
if let Some(season) = &itunes.season {
println!(" Season: {season}");
}
if let Some(episode_type) = &itunes.episode_type {
println!(" Episode Type: {episode_type}");
}
if let Some(explicit) = itunes.explicit {
println!(" Explicit: {}", if explicit { "YES" } else { "NO" });
}
}
if let Some(podcast) = &entry.podcast {
println!(" Podcast 2.0:");
if !podcast.transcript.is_empty() {
println!(" Transcripts:");
for transcript in &podcast.transcript {
print!(" - {}", transcript.url);
if let Some(transcript_type) = &transcript.transcript_type {
print!(" ({transcript_type})");
}
if let Some(language) = &transcript.language {
print!(" [{language}]");
}
println!();
}
}
if let Some(chapters) = &podcast.chapters {
println!(" Chapters: {} ({})", chapters.url, chapters.type_);
}
if !podcast.soundbite.is_empty() {
println!(" Soundbites:");
for soundbite in &podcast.soundbite {
let start_time = soundbite.start_time;
let duration = soundbite.duration;
print!(" - {:.1}s - {:.1}s", start_time, start_time + duration);
if let Some(title) = &soundbite.title {
print!(": {title}");
}
println!();
}
}
if !podcast.persons.is_empty() {
println!(" People:");
for person in &podcast.persons {
print!(" - {}", person.name);
if let Some(role) = &person.role {
print!(" ({role})");
}
println!();
}
}
}
}
}