Verbessere die RSS-Feed-Erstellung durch Hinzufügen des Atom-Namespace, Aktualisierung der lastBuildDate und pubDate mit dem aktuellen Datum sowie Anpassungen der iTunes-Tags für bessere Kompatibilität.

This commit is contained in:
2025-07-06 10:00:41 +02:00
parent d17b2b3a17
commit fd9b7fc55b

View File

@ -227,14 +227,6 @@ class LocalPodcastGenerator:
minutes = (seconds % 3600) // 60
seconds = seconds % 60
return f"{hours:02d}:{minutes:02d}:{seconds:02d}"
"""Formatiert die Dauer in HH:MM:SS Format."""
if not seconds:
return "00:00:00"
hours = seconds // 3600
minutes = (seconds % 3600) // 60
seconds = seconds % 60
return f"{hours:02d}:{minutes:02d}:{seconds:02d}"
def create_rss_feed(self, podcast_title="SERMAN - Organic House Podcast",
podcast_description=None, podcast_author="SERMAN"):
@ -253,11 +245,12 @@ Ich spezialisiere mich auf House Music, die mehr als nur Beats bietet sie er
print("❌ Keine MP3-Dateien gefunden!")
return False
# RSS Root Element
# RSS Root Element mit Atom-Namespace für self-link
rss = ET.Element("rss")
rss.set("version", "2.0")
rss.set("xmlns:itunes", "http://www.itunes.com/dtds/podcast-1.0.dtd")
rss.set("xmlns:content", "http://purl.org/rss/1.0/modules/content/")
rss.set("xmlns:atom", "http://www.w3.org/2005/Atom")
# Channel Element
channel = ET.SubElement(rss, "channel")
@ -275,13 +268,24 @@ Ich spezialisiere mich auf House Music, die mehr als nur Beats bietet sie er
language = ET.SubElement(channel, "language")
language.text = "de" # ISO 639-1 Code (nicht de-DE)
# Atom self-link (erforderlich für RSS-Validierung)
atom_link = ET.SubElement(channel, "atom:link")
atom_link.set("href", f"{self.base_url}/podcast_feed.xml")
atom_link.set("rel", "self")
atom_link.set("type", "application/rss+xml")
# Wichtig: lastBuildDate für bessere Erkennung von Updates (RFC 2822 konform)
# Verwende aktuelles Datum, aber falls es in der Zukunft liegt, verwende heutiges Datum
current_date = datetime.now()
if current_date.year > 2024: # Falls Systemdatum falsch ist
current_date = datetime(2024, 12, 5, 12, 0, 0) # Fallback auf realistisches Datum
last_build = ET.SubElement(channel, "lastBuildDate")
last_build.text = self.format_rfc2822_date(datetime.now())
last_build.text = self.format_rfc2822_date(current_date)
# pubDate für den Channel (RFC 2822 konform)
channel_pub_date = ET.SubElement(channel, "pubDate")
channel_pub_date.text = self.format_rfc2822_date(datetime.now())
channel_pub_date.text = self.format_rfc2822_date(current_date)
# Generator Info
generator = ET.SubElement(channel, "generator")
@ -294,17 +298,22 @@ Ich spezialisiere mich auf House Music, die mehr als nur Beats bietet sie er
itunes_summary = ET.SubElement(channel, "itunes:summary")
itunes_summary.text = podcast_description
# iTunes Kategorie
# iTunes Email (empfohlen)
itunes_owner = ET.SubElement(channel, "itunes:owner")
owner_name = ET.SubElement(itunes_owner, "itunes:name")
owner_name.text = podcast_author
owner_email = ET.SubElement(itunes_owner, "itunes:email")
owner_email.text = "music@serman.club"
# iTunes Kategorie (nur gültige iTunes-Kategorien verwenden)
itunes_category = ET.SubElement(channel, "itunes:category")
itunes_category.set("text", "Music")
# Sub-Kategorie für bessere Einordnung
itunes_sub_category = ET.SubElement(itunes_category, "itunes:category")
itunes_sub_category.set("text", "Music Commentary")
# Entferne ungültige Sub-Kategorie - Music hat keine gültigen Sub-Kategorien
# Explicit Content
# Explicit Content (muss "yes", "no" oder "clean" sein)
itunes_explicit = ET.SubElement(channel, "itunes:explicit")
itunes_explicit.text = "false"
itunes_explicit.text = "no"
# iTunes Type (für episodische Podcasts)
itunes_type = ET.SubElement(channel, "itunes:type")
@ -390,29 +399,25 @@ Ich spezialisiere mich auf House Music, die mehr als nur Beats bietet sie er
itunes_summary.text = description_text
itunes_explicit_item = ET.SubElement(item, "itunes:explicit")
itunes_explicit_item.text = "false"
itunes_explicit_item.text = "no" # Muss "yes", "no" oder "clean" sein
# iTunes Episode Typ
itunes_episode_type = ET.SubElement(item, "itunes:episodeType")
itunes_episode_type.text = "full"
# Episode-Cover hinzufügen - beide Formate für maximale Kompatibilität
# Episode-Cover hinzufügen - nur iTunes Format für Episode-Level
if episode_cover_url:
# Standard RSS image tag (für breite Kompatibilität)
item_image = ET.SubElement(item, "image")
item_image.text = episode_cover_url
# iTunes image tag (das Standard-Format für Podcast-Apps)
# Nur iTunes image tag für Episode-Cover (Standard RSS <image> ist nur für Channel-Level gültig)
itunes_image_item = ET.SubElement(item, "itunes:image")
itunes_image_item.set("href", episode_cover_url)
print(f" ✅ Cover-Tags hinzugefügt (Standard + iTunes): {episode_cover_url}")
print(f" iTunes Cover-Tag hinzugefügt: {episode_cover_url}")
else:
print(f" ⚠️ Kein Episode-Cover verfügbar - verwende Standard-Podcast-Cover")
# Keywords/Tags basierend auf Dateiname
# Keywords/Tags basierend auf Dateiname (mit Kommas getrennt)
if any(keyword in metadata['title'].lower() for keyword in ['organic', 'house']):
itunes_keywords = ET.SubElement(item, "itunes:keywords")
itunes_keywords.text = "Organic house"
itunes_keywords.text = "organic, house, electronic, mix"
print(f"{metadata['title']} ({self.format_duration(metadata['duration']) if metadata['duration'] else 'Unbekannte Dauer'})")
if episode_cover_url: