Skip to content

Commit 798aab7

Browse files
added github action to build playlist ever six hours
misc refactoring to build-mfp-index.html.py script added pip requirements.txt file added build-index-html script to package.json added generate public/episodes.json data file when parsing feeds
1 parent 4e2d35e commit 798aab7

9 files changed

Lines changed: 192 additions & 423 deletions

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: "Build index.html"
2+
3+
on:
4+
schedule:
5+
- cron: "* */6 * * *"
6+
push:
7+
branches:
8+
- "main"
9+
10+
permissions:
11+
contents: write
12+
13+
jobs:
14+
update-index-html:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v4
18+
- uses: actions/setup-python@v5
19+
with:
20+
python-version: "3.13"
21+
cache: "pip"
22+
- name: Install dependencies
23+
run: pip install -r requirements.txt
24+
- name: Build mfp index.html and episodes.json and save changes
25+
run: |
26+
python build-mfp-static.py
27+
bash commit-changes.sh

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ A PWA version of [musicforprogramming.net](https://musicforprogramming.net).
44

55
https://mfp-app.pages.dev/
66

7-
pip install feeder
8-
pip install requests
9-
pip install Jinja2
7+
```bash
8+
python -m venv .venv
9+
source .venv/bin/activate
10+
pip install -r requirements.txt
11+
```

build-mfp-index-html.py

Lines changed: 0 additions & 130 deletions
This file was deleted.

build-mfp-static.py

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
from dataclasses import asdict, dataclass, field
2+
from typing import List
3+
import feedparser
4+
import re
5+
import requests
6+
from jinja2 import Environment, FileSystemLoader, select_autoescape
7+
import json
8+
9+
10+
11+
@dataclass
12+
class Episode:
13+
title: str
14+
link: str
15+
pubDate: str
16+
guid: str
17+
tracks: str
18+
links: str
19+
20+
def main():
21+
episodes = []
22+
23+
24+
#
25+
# always fetch RSS feed to get the latest episodes
26+
# this is the safest way to ensure we have the most up-to-date information
27+
#
28+
29+
feed = feedparser.parse("https://musicforprogramming.net/rss.xml")
30+
31+
print(len(feed.entries))
32+
33+
for entry in feed.entries:
34+
episode = Episode(
35+
title=entry.title,
36+
link=entry.link,
37+
pubDate=entry.published,
38+
guid=entry.guid,
39+
tracks="",
40+
links=""
41+
)
42+
episodes.append(episode)
43+
# print(entry.title)
44+
# print(entry.link)
45+
# print(entry.published)
46+
# print(entry.summary)
47+
# print(entry.guid)
48+
# print()
49+
#print(f"""<a href="{entry.guid}">{entry.title.replace("Episode ", "")}</a>""")
50+
51+
#print(episodes)
52+
53+
#
54+
# fetch the tracklist for each episode from the latest client script
55+
# this is the only way I know of to get the tracklist but it is not guaranteed to work
56+
# in the future if the site changes how it works
57+
#
58+
59+
r = requests.get("https://musicforprogramming.net/latest/")
60+
client_script_start = r.text.find("/client/client")
61+
client_script_end = r.text[client_script_start:].find('";s.type')
62+
#print("client_script_start/end: ", client_script_start, client_script_end)
63+
cur_client_script = r.text[client_script_start:client_script_start + client_script_end]
64+
#print("Current client script:", cur_client_script)
65+
66+
r = requests.get("https://musicforprogramming.net" + cur_client_script)
67+
data = r.text
68+
#print(data)
69+
json_start = data.find("const Xt")
70+
json_end = data.find("function Qt(t)")
71+
#print(json_start, json_end)
72+
json_data = data[json_start:json_end].replace("const Xt=[", "").replace("];", "")
73+
#print(json_data)
74+
75+
json_data_regex = r"\{(.*?)\}"
76+
77+
links_regex = r',"links:.*$'
78+
links_http_regex = r'">(.*?)</a>'
79+
80+
json_objects = [o for o in re.findall(json_data_regex, json_data) if 'type:"episode"' in o]
81+
82+
n = len(json_objects)
83+
84+
for json_obj in json_objects:
85+
scrubbed = json_obj.replace("\",", "\",\"") \
86+
.replace(":\"", "\":\"") \
87+
.replace("{slug", "{\"slug") \
88+
.replace(",\"order:", ",\"order\":") \
89+
.replace(",title\"", ",\"title\"") \
90+
.replace("special:!0", "special\":\"!0") \
91+
.replace("!0,file", "!0\",\"file")
92+
print(scrubbed)
93+
94+
links_removed = re.sub(links_regex, " }", scrubbed)
95+
print(links_removed)
96+
97+
tracklist_start = links_removed.find('"tracklist":"')
98+
tracklist_end = links_removed.find('" }')
99+
print(tracklist_start, tracklist_end)
100+
101+
tracks = links_removed[tracklist_start:tracklist_end] \
102+
.replace('"tracklist":"', '') \
103+
.replace('\\n', '') \
104+
.replace('\\t', '') \
105+
.strip() \
106+
.split('<br>')[:-1]
107+
108+
print("Tracks:", tracks)
109+
110+
link_matches = re.findall(links_http_regex, scrubbed[scrubbed.find('"links:'):])
111+
for link in link_matches:
112+
print("Link:", link)
113+
114+
episode = episodes[n - 1]
115+
episode.tracks = json.dumps(tracks)
116+
episode.links = json.dumps(link_matches)
117+
118+
n -= 1
119+
120+
print("\n\n")
121+
122+
123+
print("Episodes:", episodes)
124+
125+
environment = Environment(loader=FileSystemLoader("templates/"), autoescape=select_autoescape())
126+
template = environment.get_template("mfp-template-index.html")
127+
128+
output = template.render(episodes=episodes)
129+
130+
with open("index.html", "w") as f:
131+
f.write(output)
132+
133+
episodes_json = json.dumps([episode.__dict__ for episode in episodes], indent=4)
134+
print("Episodes JSON:", episodes_json)
135+
with open("public/episodes.json", "w") as f:
136+
f.write(episodes_json)
137+
138+
if __name__ == "__main__":
139+
main()
140+
141+

commit-changes.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
git diff --quiet index.html
2+
if [ "$?" -eq 1 ]; then
3+
echo "Changes detected in playlist. Publishing..."
4+
git config user.name "github-actions[bot]"
5+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
6+
git add .
7+
git commit -m "Update mfp-app playlist with latest content."
8+
git push
9+
else
10+
echo "Changes not detected. Skipping..."
11+
fi

0 commit comments

Comments
 (0)