2fcf3e3bf2
Signed-off-by: Markus Birth <markus@birth-online.de>
234 lines
8.7 KiB
Python
Executable File
234 lines
8.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
|
||
print("Started.")
|
||
|
||
import glob
|
||
import re
|
||
import xml.etree.ElementTree as ET
|
||
import xml.dom.minidom
|
||
from datetime import datetime
|
||
from os.path import basename, getsize, isfile, splitext
|
||
from pytz import timezone
|
||
from urllib.parse import quote
|
||
from mutagen.mp4 import MP4
|
||
from rich import print
|
||
from rich.progress import track
|
||
|
||
BASEURL = "https://rpi4.mbirth.uk/wsqk/"
|
||
RFC822 = "%a, %d %b %Y %H:%M:%S %z"
|
||
|
||
TEASER = {
|
||
"Late Night Crew": {
|
||
"title": "The Late Night Crew with Vance Goodman",
|
||
"desc": "Midnight belongs to the night owls of Hawkins. Join The Late Night Crew, 12 to 3 am on The Squawk",
|
||
},
|
||
"s Early Risers": {
|
||
"title": "Mindy's Early Risers",
|
||
"desc": "For the bakers, the night shifters, and the can't-sleep crew - Keeping Hawkins company from 3 to 6 am",
|
||
},
|
||
"Weekend Early Risers": {
|
||
"title": "Mindy's Weekend Early Risers",
|
||
"desc" :"Getting up or just getting in? Keeping Hawkins company from 3 to 6 am",
|
||
},
|
||
"K Wake Up": {
|
||
"title": "The WSQK Wake Up with Vance Goodman",
|
||
"desc": "Playing you Hawkins hottest hits to eat your morning waffles on The Squawk.",
|
||
},
|
||
"Weekend Wake Up": {
|
||
"title": "The Weekend Wake Up with Vance Goodman",
|
||
"desc": "Playing you Hawkins hottest hits to eat your morning waffles on The Squawk.",
|
||
},
|
||
"Rewind At 9": {
|
||
"title": "The REWIND at 9",
|
||
"desc": "The ultimate test, Mindy plays a track, but it's been turned upside down & played backwards, but what is it?",
|
||
},
|
||
"in the Mornings": {
|
||
"title": "Mindy Flare in the Mornings",
|
||
"desc": "Roll through your morning with Mindy, 9 to 12, the heartbeat of Hawkins and the queen of mid-morning hits.",
|
||
},
|
||
"Afternoon Hangout": {
|
||
"title": "The Afternoon Hangout with Vance Goodman",
|
||
"desc": "12 to 4, blasting Hawkins biggest hits straight from the Tower of Power on WSQK The Squawk.",
|
||
},
|
||
"Talk To Tammy": {
|
||
"title": "Talk to Tammy",
|
||
"desc": "Need a hug and some real talk? You gotta problem? You need your mammy? It's time to ... Talk to Tammy",
|
||
},
|
||
"Hawkins Homerun": {
|
||
"title": "The Hawkins Home Run with Mindy Flare",
|
||
"desc": "Clock out and crank up, we're blasting the best drive-time hits from 4 to 7 on WSQK The Squawk.",
|
||
},
|
||
"Weekend Homerun": {
|
||
"title": "The Weekend Homerun With Mindy Flare",
|
||
"desc": "Back from the big game? or out shopping at the Mall? We have best tracks for your weekend afternoon!",
|
||
},
|
||
"Dial-A-Dedication": {
|
||
"title": "Dial-A-Dedication",
|
||
"desc": "Your chance to take over the airwaves every single night at 7 with Vance Goodman, on WSQK, The Squawk",
|
||
},
|
||
"Evenings": {
|
||
"title": "Evenings with Vance Goodman",
|
||
"desc": "Bringing the glow of Hawkins nights alive, 7 to 9 on WSQK The Squawk",
|
||
},
|
||
"Late Nights": {
|
||
"title": "Late Nights with Mindy Flare",
|
||
"desc": "9pm to midnight with relaxing vibes, soft lights, and the hottest night-time hits.",
|
||
},
|
||
"New Year": {
|
||
"title": "The Squawk’s New Year’s Eve Party",
|
||
"desc": "Counting down to New Year across Hawkins, with a BANG!",
|
||
},
|
||
"ʎɐᗡ ʇsɐ⅂ ǝuO": {
|
||
"title": "ʎɐᗡ ʇsɐ⅂ ǝuO",
|
||
"desc": "One Last Day with Vance Goodman and Mindy Flare, broadcasting your Dial A Dedications and keeping the hits blasting until 11pm",
|
||
},
|
||
}
|
||
|
||
def appendTextElement(parent_element, tag_name, text):
|
||
tmp = ET.SubElement(parent_element, tag_name)
|
||
tmp.text = text
|
||
return tmp
|
||
|
||
def secondsToHMS(seconds):
|
||
hours = int(seconds / 3600)
|
||
remainder = seconds % 3600
|
||
minutes = int(remainder / 60)
|
||
seconds = int(remainder % 60)
|
||
return "{:02d}:{:02d}:{:02d}".format(hours, minutes, seconds)
|
||
|
||
def appendMP4Item(parent_element, mp4_filename):
|
||
namenoext = splitext(mp4_filename)[0]
|
||
title = basename(namenoext)
|
||
size = getsize(mp4_filename)
|
||
|
||
duration = MP4(mp4_filename).info.length
|
||
hms_stamp = secondsToHMS(duration)
|
||
#print(repr(duration))
|
||
#print(hms_stamp)
|
||
|
||
# Cut off ".." and audio parent directory
|
||
#file_url = "/".join(mp4_filename.split("/")[2:])
|
||
file_url = mp4_filename
|
||
|
||
# Fix time in title ("16-00-00" --> "04:00pm")
|
||
try:
|
||
(t_hms, t_t) = title.split(" ", 1)
|
||
t_h = int(t_hms[0:2])
|
||
t_ap = "am"
|
||
if t_h>11:
|
||
t_ap = "pm"
|
||
if t_h>12:
|
||
t_h -= 12
|
||
elif t_h==0:
|
||
t_h = 12
|
||
|
||
title = f"{t_h}:{t_hms[3:5]}{t_ap} {t_t}"
|
||
except:
|
||
pass
|
||
|
||
url = BASEURL + quote(file_url)
|
||
txt = namenoext + ".txt"
|
||
|
||
item = ET.SubElement(parent_element, "item")
|
||
|
||
appendTextElement(item, "guid", url)
|
||
appendTextElement(item, "title", title)
|
||
appendTextElement(item, "itunes:duration", hms_stamp)
|
||
|
||
description = ""
|
||
for i in TEASER:
|
||
if i in title:
|
||
description += TEASER[i]["desc"]
|
||
|
||
if isfile(txt):
|
||
f = open(txt, "r")
|
||
desc = f.read()
|
||
desc = desc.replace("\n", "<br />")
|
||
description += "\n\n" + desc
|
||
#appendTextElement(item, "description", desc)
|
||
#appendTextElement(item, "content:encoded", desc)
|
||
|
||
if description:
|
||
appendTextElement(item, "description", description)
|
||
|
||
enc = ET.SubElement(item, "enclosure")
|
||
enc.set("url", url)
|
||
enc.set("length", str(size))
|
||
enc.set("type", "audio/mp4")
|
||
|
||
date = re.search(r"(\d{4})-(\d\d)-(\d\d)", namenoext)
|
||
time = re.search(r"/(\d\d)-(\d\d)-(\d\d) ", namenoext)
|
||
if date:
|
||
if time:
|
||
pubdate = datetime(int(date.group(1)), int(date.group(2)), int(date.group(3)), int(time.group(1)), int(time.group(2)), int(time.group(3)))
|
||
else:
|
||
pubdate = datetime(int(date.group(1)), int(date.group(2)), int(date.group(3)), 23, 59, 59)
|
||
|
||
pubdate = timezone("Europe/London").localize(pubdate)
|
||
appendTextElement(item, "pubDate", pubdate.strftime(RFC822))
|
||
|
||
ET.register_namespace("content", "http://purl.org/rss/1.0/modules/content/")
|
||
ET.register_namespace("atom", "http://www.w3.org/2005/Atom")
|
||
ET.register_namespace("itunes", "http://www.itunes.com/dtds/podcast-1.0.dtd")
|
||
ET.register_namespace("spotify", "http://www.spotify.com/ns/rss")
|
||
ET.register_namespace("psc", "https://podlove.org/simple-chapters/")
|
||
|
||
tree = ET.ElementTree(ET.Element("rss"))
|
||
|
||
root = tree.getroot()
|
||
root.set("version", "2.0")
|
||
root.set("xmlns:content", "http://purl.org/rss/1.0/modules/content/")
|
||
root.set("xmlns:atom", "http://www.w3.org/2005/Atom")
|
||
root.set("xmlns:itunes", "http://www.itunes.com/dtds/podcast-1.0.dtd")
|
||
root.set("xmlns:spotify", "http://www.spotify.com/ns/rss")
|
||
root.set("xmlns:psc", "https://podlove.org/simple-chapters/")
|
||
|
||
channel = ET.SubElement(root, "channel")
|
||
|
||
appendTextElement(channel, "title", "WSQK - The Squawk - 94.5FM")
|
||
appendTextElement(channel, "link", BASEURL + "index.rss2")
|
||
appendTextElement(channel, "copyright", "Netflix & Global Radio")
|
||
appendTextElement(channel, "itunes:author", "Netflix & Global Radio")
|
||
ET.SubElement(channel, "atom:link", {"rel": "self", "type": "application/rss+xml", "href": BASEURL + "index.rss2"})
|
||
appendTextElement(channel, "description", "Introducing Hawkins' own radio station: WSQK 'The Squawk'. From November 24th until January 1st, you will be transported straight into the heart of Hawkins, 24/7.")
|
||
appendTextElement(channel, "language", "en-uk")
|
||
|
||
img = ET.SubElement(channel, "image")
|
||
appendTextElement(img, "url", BASEURL + "rsslogo.jpg")
|
||
appendTextElement(img, "title", "WSQK - The Squawk - 94.5FM")
|
||
appendTextElement(img, "link", BASEURL + "index.rss2")
|
||
appendTextElement(img, "width", "512")
|
||
appendTextElement(img, "height", "512")
|
||
|
||
ET.SubElement(channel, "itunes:category", {"text": "Music"})
|
||
appendTextElement(channel, "itunes:explicit", "No")
|
||
|
||
# <pubDate>Tue, 10 Jun 2003 04:00:00 GMT</pubDate>
|
||
appendTextElement(channel, "lastBuildDate", datetime.now(timezone("Europe/Berlin")).strftime(RFC822)) # RFC 822 format
|
||
appendTextElement(channel, "docs", "http://blogs.law.harvard.edu/tech/rss")
|
||
appendTextElement(channel, "generator", "Handcrafted with love")
|
||
manEd = appendTextElement(channel, "managingEditor", "markus@birth-online.de (Markus Birth)")
|
||
appendTextElement(channel, "webMaster", manEd.text)
|
||
|
||
|
||
print("Scanning for audio files...")
|
||
|
||
for m4a in track(sorted(glob.glob("20*/*.m4a")), description="Parsing audio files..."):
|
||
appendMP4Item(channel, m4a)
|
||
|
||
rawxml = ET.tostring(root, "utf-8")
|
||
reparsed = xml.dom.minidom.parseString(rawxml)
|
||
prettyxml = reparsed.toprettyxml()
|
||
|
||
print("Writing RSS file...")
|
||
|
||
with open("index.rss2", "wt") as f:
|
||
f.write(prettyxml)
|
||
|
||
#tree.write("index.rss2", "utf-8", True)
|
||
|
||
#print(ET.tostring(root, "utf-8").decode("utf-8"))
|
||
|
||
print("All done.")
|