Verbessere die Cover-URL-Generierung durch Verwendung einer sicheren URL-Encoding-Methode und aktualisiere die Sprach- und Datumsformate für bessere Kompatibilität mit RSS-Standards.
This commit is contained in:
@ -121,7 +121,7 @@ class LocalPodcastGenerator:
|
|||||||
# Prüfe ob Cover bereits existiert
|
# Prüfe ob Cover bereits existiert
|
||||||
if cover_path.exists():
|
if cover_path.exists():
|
||||||
# Cover existiert bereits - verwende es einfach (URL-encoded)
|
# Cover existiert bereits - verwende es einfach (URL-encoded)
|
||||||
cover_url = f"{self.base_url}/_audio/{urllib.parse.quote(cover_filename)}"
|
cover_url = f"{self.base_url}/_audio/{self.safe_url_encode(cover_filename)}"
|
||||||
print(f" 🖼️ Cover bereits vorhanden: {cover_filename}")
|
print(f" 🖼️ Cover bereits vorhanden: {cover_filename}")
|
||||||
return cover_url
|
return cover_url
|
||||||
|
|
||||||
@ -193,13 +193,18 @@ class LocalPodcastGenerator:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
# Rückgabe der URL zum Cover (URL-encoded für korrekte Links)
|
# Rückgabe der URL zum Cover (URL-encoded für korrekte Links)
|
||||||
cover_url = f"{self.base_url}/_audio/{urllib.parse.quote(cover_filename)}"
|
cover_url = f"{self.base_url}/_audio/{self.safe_url_encode(cover_filename)}"
|
||||||
return cover_url
|
return cover_url
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" ⚠️ Fehler beim Extrahieren des Covers: {e}")
|
print(f" ⚠️ Fehler beim Extrahieren des Covers: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def safe_url_encode(self, filename):
|
||||||
|
"""Erstellt URL-sichere Dateinamen durch korrektes Encoding."""
|
||||||
|
# Verwende quote_plus für bessere URL-Sicherheit (ersetzt Leerzeichen mit +)
|
||||||
|
return urllib.parse.quote(filename, safe='')
|
||||||
|
|
||||||
def format_duration(self, seconds):
|
def format_duration(self, seconds):
|
||||||
"""Formatiert die Dauer in HH:MM:SS Format."""
|
"""Formatiert die Dauer in HH:MM:SS Format."""
|
||||||
if not seconds:
|
if not seconds:
|
||||||
@ -209,6 +214,14 @@ class LocalPodcastGenerator:
|
|||||||
minutes = (seconds % 3600) // 60
|
minutes = (seconds % 3600) // 60
|
||||||
seconds = seconds % 60
|
seconds = seconds % 60
|
||||||
return f"{hours:02d}:{minutes:02d}:{seconds:02d}"
|
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",
|
def create_rss_feed(self, podcast_title="SERMAN - Organic House Podcast",
|
||||||
podcast_description=None, podcast_author="SERMAN"):
|
podcast_description=None, podcast_author="SERMAN"):
|
||||||
@ -247,13 +260,13 @@ Ich spezialisiere mich auf House Music, die mehr als nur Beats bietet – sie er
|
|||||||
link.text = self.base_url
|
link.text = self.base_url
|
||||||
|
|
||||||
language = ET.SubElement(channel, "language")
|
language = ET.SubElement(channel, "language")
|
||||||
language.text = "de-DE"
|
language.text = "de" # ISO 639-1 Code (nicht de-DE)
|
||||||
|
|
||||||
# Wichtig: lastBuildDate für bessere Erkennung von Updates
|
# Wichtig: lastBuildDate für bessere Erkennung von Updates (RFC 2822 konform)
|
||||||
last_build = ET.SubElement(channel, "lastBuildDate")
|
last_build = ET.SubElement(channel, "lastBuildDate")
|
||||||
last_build.text = datetime.now().strftime('%a, %d %b %Y %H:%M:%S +0000')
|
last_build.text = datetime.now().strftime('%a, %d %b %Y %H:%M:%S +0000')
|
||||||
|
|
||||||
# pubDate für den Channel
|
# pubDate für den Channel (RFC 2822 konform)
|
||||||
channel_pub_date = ET.SubElement(channel, "pubDate")
|
channel_pub_date = ET.SubElement(channel, "pubDate")
|
||||||
channel_pub_date.text = datetime.now().strftime('%a, %d %b %Y %H:%M:%S +0000')
|
channel_pub_date.text = datetime.now().strftime('%a, %d %b %Y %H:%M:%S +0000')
|
||||||
|
|
||||||
@ -334,14 +347,14 @@ Ich spezialisiere mich auf House Music, die mehr als nur Beats bietet – sie er
|
|||||||
|
|
||||||
# GUID (eindeutige ID - verwende Audio-URL)
|
# GUID (eindeutige ID - verwende Audio-URL)
|
||||||
item_guid = ET.SubElement(item, "guid")
|
item_guid = ET.SubElement(item, "guid")
|
||||||
# Die Audio-URL als eindeutige GUID
|
# Die Audio-URL als eindeutige GUID (URL-safe encoded)
|
||||||
audio_url = f"{self.base_url}/_audio/{urllib.parse.quote(metadata['filename'])}"
|
audio_url = f"{self.base_url}/_audio/{self.safe_url_encode(metadata['filename'])}"
|
||||||
item_guid.text = audio_url
|
item_guid.text = audio_url
|
||||||
item_guid.set("isPermaLink", "false")
|
item_guid.set("isPermaLink", "false")
|
||||||
|
|
||||||
# Veröffentlichungsdatum (korrekt formatiert für RSS)
|
# Veröffentlichungsdatum (RFC 2822 konform)
|
||||||
item_pubdate = ET.SubElement(item, "pubDate")
|
item_pubdate = ET.SubElement(item, "pubDate")
|
||||||
# RFC 2822 Format für RSS (mit Timezone)
|
# RFC 2822 Format mit korrekter Timezone
|
||||||
pub_date_formatted = metadata['pub_date'].strftime('%a, %d %b %Y %H:%M:%S +0000')
|
pub_date_formatted = metadata['pub_date'].strftime('%a, %d %b %Y %H:%M:%S +0000')
|
||||||
item_pubdate.text = pub_date_formatted
|
item_pubdate.text = pub_date_formatted
|
||||||
|
|
||||||
@ -351,10 +364,10 @@ Ich spezialisiere mich auf House Music, die mehr als nur Beats bietet – sie er
|
|||||||
enclosure.set("type", "audio/mpeg")
|
enclosure.set("type", "audio/mpeg")
|
||||||
enclosure.set("length", str(metadata['file_size']))
|
enclosure.set("length", str(metadata['file_size']))
|
||||||
|
|
||||||
# Dauer
|
# Dauer (Apple empfiehlt Sekunden als Integer)
|
||||||
if metadata['duration']:
|
if metadata['duration']:
|
||||||
item_duration = ET.SubElement(item, "itunes:duration")
|
item_duration = ET.SubElement(item, "itunes:duration")
|
||||||
item_duration.text = self.format_duration(metadata['duration'])
|
item_duration.text = str(int(metadata['duration'])) # Integer Sekunden für Apple
|
||||||
|
|
||||||
# iTunes-spezifische Tags für bessere Episode-Erkennung
|
# iTunes-spezifische Tags für bessere Episode-Erkennung
|
||||||
itunes_title = ET.SubElement(item, "itunes:title")
|
itunes_title = ET.SubElement(item, "itunes:title")
|
||||||
@ -399,7 +412,8 @@ Ich spezialisiere mich auf House Music, die mehr als nur Beats bietet – sie er
|
|||||||
ET.indent(tree, space=" ", level=0)
|
ET.indent(tree, space=" ", level=0)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
tree.write(self.output_file, encoding='utf-8', xml_declaration=True)
|
# Explizite XML-Deklaration mit UTF-8 encoding
|
||||||
|
tree.write(self.output_file, encoding='UTF-8', xml_declaration=True)
|
||||||
print(f"✅ RSS-Feed erfolgreich erstellt: {self.output_file}")
|
print(f"✅ RSS-Feed erfolgreich erstellt: {self.output_file}")
|
||||||
print(f"📊 Anzahl der Episoden: {len(mp3_files)}")
|
print(f"📊 Anzahl der Episoden: {len(mp3_files)}")
|
||||||
print(f"🌐 Audio-URLs verwenden Basis-URL: {self.base_url}")
|
print(f"🌐 Audio-URLs verwenden Basis-URL: {self.base_url}")
|
||||||
|
Reference in New Issue
Block a user