Podcast downloading with Python and systemd

My favorite radio show airs on Sunday afternoon, and often can't listen to it live. Fortunately the radio station offers a podcast feed so I can catch up and listen to old shows. I set up a systemd user timer (cronjob) on my Linux computer that runs getpodcast to download updates.
Getpodcast configuration
Getpodcast is pretty effective python module, you can create a small python script that contains some simple configuration details and if needed a post-download hook.
pip3 install getpodcast
In this example I added a post-download trigger that adds the new file to a m3u playlist, but you can also use os.system to trigger a command that adds the file to a music player queue.
#! /usr/bin/env python3
# podcast_task.py
import getpodcast
import pathlib
def add_to_playlist(*args, **kwargs):
""" Add new files to a playlist """
newfilename = pathlib.Path(kwargs["newfilename"])
with open("new.m3u", 'a', encoding='utf-8') as playlist:
playlist.write(f"{newfilename}\n")
opt = getpodcast.options(
#date_from='2021-01-01',
root_dir='.',
hooks='validated=add_to_playlist'
)
podcasts = {
"Slacker Station": "https://www.omnycontent.com/d/playlist/c292b3ac-094e-4616-a956-a99800ed54e9/c2b3611e-0597-4e7e-aabb-ac36008131d7/97e83ee0-349f-4444-b17f-ac360081f03e/podcast.rss",
"De M Show": "https://www.omnycontent.com/d/playlist/c292b3ac-094e-4616-a956-a99800ed54e9/28068cad-eb0d-46a1-8b77-abdd00f622c4/bbb709cc-4190-48af-aa70-ac2800e1dfdb/podcast.rss"
}
getpodcast.getpodcast(podcasts, opt)
After verifying the the script does what it is supposed to do in the command shell, it's time to automate it and run it as a systemd service.
Systemd configuration
Systemd is typically used to manage system wide services, but it can also be used for more personal stuff that runs under the local user account.
To do just that, we can create ~/.config/systemd/user and put some files there.
Systemd normally only activates these user jobs when the user is logged in. Since I'm using this on a headless server, I need to enable lingering on the account:
loginctl enable-linger username
Two configuration files are needed, a service that describes what to do, and a timer that triggers the service.
# ~/.config/systemd/user/mypodcaster.service
[Unit]
Description=run getpodcast script
Wants=mypodcaster.timer
[Service]
Type=oneshot
ExecStart=/home/thomas/podcasts/podcast_task.py --run
WorkingDirectory=/home/thomas/podcasts
[Install]
WantedBy=multi-user.target
# ~/.config/systemd/user/mypodcaster.timer
[Unit]
Description=Run podcast service one a day
Requires=mypodcaster.service
[Timer]
Unit=mypodcaster.service
OnCalendar=*-*-* 02:00:00
[Install]
WantedBy=timers.target
To have systemd pick up the newly created configuration, we need to trigger daemon-reload:
systemctl --user daemon-reload
Final check
It's a good idea to check the systemd service before leaving it to the timer:
thomas@elektra:~$ journalctl --user -f -u mypodcaster &
thomas@elektra:~$ systemctl --user start mypodcaster
You can view the output later on using journalctl:
thomas@elektra:~$ journalctl --user -u mypodcaster|tail
Feb 03 20:10:13 elektra getpodcasts.py[1801309]: File: ./De M Show/2020/2020.08.31 De M-show met Marcel Vanthilt (288 16u).mp3:
Feb 03 20:10:13 elektra getpodcasts.py[1801309]: Status:
Feb 03 20:10:13 elektra getpodcasts.py[1801309]: Downloading ...
Feb 03 20:10:13 elektra getpodcasts.py[1801309]: Download complete
Feb 03 20:10:13 elektra getpodcasts.py[1801309]: File validated
Feb 03 20:10:13 elektra systemd[801650]: mypodcaster.service: Succeeded.
Feb 03 20:10:13 elektra systemd[801650]: Finished run getpodcast script.
Feb 04 02:00:06 elektra systemd[801650]: Starting run getpodcast script...
Feb 04 02:18:06 elektra systemd[801650]: mypodcaster.service: Succeeded.
Feb 04 02:18:06 elektra systemd[801650]: Finished run getpodcast script.
Enjoy listening...
Credits
Thanks to @lamitpobus for sharing a script to create fancy screenshot thubnails!
Liked something? Worked on something similar? Let me know what you think on Mastodon!
You can use your Mastodon account to reply to this post.