A final entry here just to document what my solution is for tying an RSS feed into channels.
First off, I use gPodder to manage the RSS feeds. I run it as the channelsDVR userid ("channels" on my system). Normally this is run non-interactively from a crontab, but I do run the GUI (as "channels") whenever I want to add or manage feeds.
gPodder normally stores its data in ~/gPodder/Downloads, in one directory for each feed. After setting up a new feed, I move its directory from ~/gPodder/Downloads/<rss_feed> to Imports/Video/<rss_feed> in the channelsDVR DVR directory. I then put a symlink in the gPodder/Downloads directory that points to where the directory was moved to. (It turns out that channelsDVR will not follow a symlink to the gPodder directory...)
The script to manage the downloading is in ~/bin/gPodder_download:
#!/bin/bash
# Script to fetch new episodes of podcasts
#
set -e
timeout 10m gpo update >/dev/null
timeout 2h gpo download >/dev/null
I have a crontab set up to run things 4 times per day:
23 3,9,15,21 * * * bin/gPodder_daemon
This actually runs a simple wrapper instead of gPodder_download directly, but if you run the download script from the crontab, it would be a pretty functional feed by itself.
But, I want to pull some metadata from the podcast episodes, so I have a 2nd script that is run by this wrapper (this is gPodder_daemon, invoked from crontab):
#!/bin/bash
# Script periodically run as a daemon
bin/gPodder_download
sleep $(( 5 * 60 )) # Sleep 5 minutes
bin/gPodder_metadata
This wrapper runs the download script, waits 5 minutes (during which time channelsDVR has most likely noticed any new files in it's Videos directory), then runs the metadata script.
The metadata script is more complicated, but the general idea is to ask channelsDVR for info about any files. For each record, we note any files with a group that starts with "videos-" and doesn't have anything set in "Airing.OriginalDate". For these entries, we take note of the filename and the file id.
Then, we look through gPodder's database and select any unplayed episodes. If the filename is one that we had noted, then we populate the date, title, and description with info from the database.
Some care has to be taken to extract the text field from the database as a hex string (to avoid confusing the script with stray delimiters) and newline and " characters have to be escaped to make a valid JSON record. Also, if the description is empty, we try to convert the HTML description into text and use that.
Here's the metadata script:
#!/bin/bash
# Script to copy metadata from gPodder into channelsDVR
CHANNELS=127.0.0.1:8089
DOWNLOADS=/home/channels/gPodder/Downloads
GP_DATABASE=/home/channels/gPodder/Database
declare -A episode
function hex2str {
local in="$1"
local out=""
while [ -n "$in" ]; do
local c=${in:0:2}
in=${in:2}
case $c in
00) ;;
0[aA]) out="$out"'\\n';;
22) out="$out"'\\"';;
5[cC]) out="$out"'\\\\';;
*) out="$out\x$c";;
esac
done
printf "$out"
}
# Query for all episodes in channelsDVR and find those in the video
# group where the date hasn't been set yet. Set the assiciative array
# episode[] to map the path to the file id for any gPodder episodes without
# the metadata defined.
# (Note: use process substitution so the while loop runs in the
# primary process and not a subprocess)
while read id;do read path;read date; read group
[ $date = null ] || continue
eval group=$group
case "$group" in videos-*);; *) continue;; esac
eval path=$path
eval id=$id
episode["$path"]="$id"
done < <(curl -s $CHANNELS/dvr/files \
| jq '.[]|.ID,.Path,.Airing.OriginalDate,.GroupID')
# Query the gPodder database to extract the title and description for
# all "unwatched" episodes. If these map to a file id, then set the
# metadata in channelsDVR
QRY="select download_folder, download_filename, published, "
QRY="$QRY hex(episode.title), hex(episode.description), hex(description_html)"
QRY="$QRY from podcast, episode"
QRY="$QRY where podcast.id = podcast_id and state = 1"
echo "$QRY;" | sqlite3 "$GP_DATABASE" \
| while IFS='|' read folder file pub title desc deschtml
do
id=${episode["$folder/$file"]}
[ -n "$id" ] || continue
if [ -n "$desc" ]; then
desc="$(hex2str $desc)"
else
desc="$(hex2str $deschtml | sed 's/\\n/ /' \
| html2text | sed -z 's/"/\\"/g;s/\n\n*/\\n/g')"
fi
JSON="{ \"Airing\": {"
JSON="$JSON \"OriginalDate\": \"$(date +'%Y-%m-%d' -d@$pub)\","
JSON="$JSON \"EpisodeTitle\": \"$(hex2str $title)\","
JSON="$JSON \"Summary\": \"$desc\"}}"
curl -s --json "$JSON" -X PUT $CHANNELS/dvr/files/"$id" >/dev/null
done