Here is my brute force of an alpha version of XMLTV export. It is written and tested in BASH on MacOS BugSur, ymwv! It runs for about an hour. I hope to get this down if I can crack the BASH "read" command with spaces, see comments in script.
Here is the script:
#!/bin/bash
JQ=/usr/local/bin/jq
CURL=/usr/bin/curl
ECHO=/bin/echo
CAT=/bin/cat
DATE=/bin/date
# Grab RAW Program Data
RAW_EPG=$($CURL -s http://mac-mini.local:8089/devices/ANY/guide > tmpEPG.dat)
# Start the XMLTV Guide
echo "<tv>"
# Get the Channel Data
CHANNELS=$($CAT "tmpEPG.dat" | $JQ '. | length')
for ((h = 0 ; h < $CHANNELS ; h++)); do
# echo "Starting Channel [${h}] ..."
# Cannot get this to work with Spaces!!!
# I have tried All Combinations of
# IFS="", IFS='', IFS=$"\n" with
# read -r or read
read CHANNEL_ID DISPLAY_NAME1 DISPLAY_NAME2 DESCRIPTION IMAGE NUMBER <<<$($CAT "tmpEPG.dat" | $JQ --arg h $h '.[$h|tonumber] | .Channel.Station, .Channel.Name, .Channel.Number, .Channel.Description, .Channel.Image, .Channel.Number')
# CHANNEL_ID=$($CAT "tmpEPG.dat" | $JQ --arg h $h '.[$h|tonumber] | .Channel.Station')
# DISPLAY_NAME1=$($CAT "tmpEPG.dat" | $JQ --arg h $h '.[$h|tonumber] | .Channel.Name')
# DISPLAY_NAME2=$($CAT "tmpEPG.dat" | $JQ --arg h $h '.[$h|tonumber] | .Channel.Number')
# DESCRIPTION=$($CAT "tmpEPG.dat" | $JQ --arg h $h '.[$h|tonumber] | .Channel.Description')
# IMAGE=$($CAT "tmpEPG.dat" | $JQ --arg h $h '.[$h|tonumber] | .Channel.Image')
# NUMBER=$($CAT "tmpEPG.dat" | $JQ --arg h $h '.[$h|tonumber] | .Channel.Number')
echo " <channel id=${CHANNEL_ID}>"
echo " <display-name>${DISPLAY_NAME1}</display-name>"
echo " <display-name>${DISPLAY_NAME2}</display-name>"
echo " <desc>${DESCRIPTION}</desc>"
echo " <icon src=${IMAGE}/>"
echo " <lcn>${NUMBER}</lcn>"
echo " </channel>"
# Get the Program Data
AIRINGS=$($CAT "tmpEPG.dat" | $JQ --arg h $h '.[$h|tonumber] | .Airings | length')
for ((i = 0 ; i < $AIRINGS ; i++)); do
# echo "Starting Airings [${i}] for Channel [${h}] ..."
# Cannot get this to work with Spaces!!!
# I have tried All Combinations of
# IFS="", IFS='', IFS=$"\n" with
# read -r or read
# read CHANNEL_ID2 TIME DURATION TITLE SUB_TITLE DESCRIPTION2 AIR_DATE CATEGORIES GENRES IMAGE2 SERIESID EPISODE_NUMBER EPISODE_DATE <<<$($CAT "tmpEPG.dat" | $JQ --arg h $h --arg i $i '.[$h|tonumber] | .Airings[$i|tonumber] | .Channel, .Time, .Duration, .Title, .EpisodeTitle, .Summary, .Categories[0], .Genres[0], .Image, .SeriesID, .EpisodeNumber, .OriginalDate')
CHANNEL_ID2=$($CAT "tmpEPG.dat" | $JQ --arg h $h --arg i $i '.[$h|tonumber] | .Airings[$i|tonumber] | .Channel')
TIME=$($CAT "tmpEPG.dat" | $JQ --arg h $h --arg i $i '.[$h|tonumber] | .Airings[$i|tonumber] | .Time')
DURATION=$($CAT "tmpEPG.dat" | $JQ --arg h $h --arg i $i '.[$h|tonumber] | .Airings[$i|tonumber] | .Duration')
END=$((TIME + DURATION))
START_DATETIME=$($DATE -uR -r $TIME +"%Y%m%d%H%M%S +0000")
END_DATETIME=$($DATE -uR -r $END +"%Y%m%d%H%M%S +0000")
TITLE=$($CAT "tmpEPG.dat" | $JQ --arg h $h --arg i $i '.[$h|tonumber] | .Airings[$i|tonumber] | .Title')
SUB_TITLE=$($CAT "tmpEPG.dat" | $JQ --arg h $h --arg i $i '.[$h|tonumber] | .Airings[$i|tonumber] | .EpisodeTitle')
DESCRIPTION2=$($CAT "tmpEPG.dat" | $JQ --arg h $h --arg i $i '.[$h|tonumber] | .Airings[$i|tonumber] | .Summary')
AIR_DATE=$($DATE -uR -r $TIME +"%Y%m%d")
CATEGORIES=$($CAT "tmpEPG.dat" | $JQ --arg h $h --arg i $i '.[$h|tonumber] | .Airings[$i|tonumber] | .Categories[0]')
GENRES=$($CAT "tmpEPG.dat" | $JQ --arg h $h --arg i $i '.[$h|tonumber] | .Airings[$i|tonumber] | .Genres[0]')
IMAGE2=$($CAT "tmpEPG.dat" | $JQ --arg h $h --arg i $i '.[$h|tonumber] | .Airings[$i|tonumber] | .Image')
SERIESID=$($CAT "tmpEPG.dat" | $JQ --arg h $h --arg i $i '.[$h|tonumber] | .Airings[$i|tonumber] | .SeriesID')
if [ -z "${SERIESID##pluto*}" ]
then
SERIESID=${SERIESID//pluto\//}
SYSTEM="pluto"
else
SYSTEM=""
fi
EPISODE_NUMBER=$($CAT "tmpEPG.dat" | $JQ --arg h $h --arg i $i '.[$h|tonumber] | .Airings[$i|tonumber] | .EpisodeNumber')
EPISODE_DATE=$($CAT "tmpEPG.dat" | $JQ --arg h $h --arg i $i '.[$h|tonumber] | .Airings[$i|tonumber] | .OriginalDate')
echo " <programme start=${START_DATETIME} stop=${END_DATETIME} channel=${CHANNEL_ID2}>"
echo " <title lang=\"en\">${TITLE}</title>"
echo " <icon src=${IMAGE2}/>"
echo " <sub-title lang=\"en\">${SUB_TITLE}</sub-title>"
echo " <desc lang=\"en\">${DESCRIPTION2}</desc>"
echo " <date>${AIR_DATE}</date>"
if [ -z "$CATEGORIES" ]
then
echo " <category lang=\"en\">${GENRES}</category>"
else
echo " <category lang=\"en\">${CATEGORIES}</category>"
fi
echo " <series-id system=\"${SYSTEM}\">${SERIESID}</series-id>"
echo " <episode-num system=\"onscreen\">${EPISODE_NUMBER}</episode-num>"
echo " <episode-num system=\"original-air-date\">${EPISODE_DATE}</episode-num>"
echo " </programme>"
done # Getting Program Data
done # Getting Channel Data
# Finish XMLTV Guide
echo "</tv>"