Add atom->rss conversion

This commit is contained in:
Lucidiot 2021-03-17 15:15:12 +01:00
parent f4f4179261
commit 0664b89dd3
Signed by: lucidiot
GPG Key ID: 3358C1CA6906FB8D
4 changed files with 165 additions and 9 deletions

View File

@ -1,5 +1,8 @@
#!/bin/bash
[ -z "$DIR" ] && DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
xsltproc "$DIR/xslt/feedgen.xsl" "$DIR/itsb.xml" | DIR="$DIR" bash -s -- "$@"
xsltproc "$DIR/xslt/opml.xsl" "$DIR/itsb.xml" > "$DIR/feeds.opml"
xsltproc "$DIR/xslt/html.xsl" "$DIR/itsb.xml" > "$DIR/index.html"
xsltproc "$DIR/xslt/itsb.xsl" "$DIR/itsb.xml" \
| tee \
>(xsltproc "$DIR/xslt/opml.xsl" - > "$DIR/feeds.opml") \
>(xsltproc "$DIR/xslt/html.xsl" - > "$DIR/index.html") \
| xsltproc "$DIR/xslt/feedgen.xsl" - \
| DIR="$DIR" bash -s -- "$@"

72
jq/convert/atom2rss.jq Normal file
View File

@ -0,0 +1,72 @@
# Atom 1.0 to RSS 2.0 converter
# Expects xmltodict JSON output, returns xmltodict-compatible JSON
def ensure_string: if type == "array" then .[0] else . end | if type == "object" then .["#text"] else . end;
def ensure_array: (. // []) | if type == "array" then . else [.] end;
def find_links(rel): [(.link // []) | if type == "array" then .[] else . end | select(.["@rel"] == rel)];
def parse_categories: [
.category
| ensure_array[]
| { "#text": .["@term"] }
+ (if .["@scheme"] then {"@domain": .["@scheme"]} else {} end)
];
def parse_date: (try (.updated // .published) | fromdateiso8601 | strftime("%a, %d %b %Y %T %z")) // [];
{
"rss": {
"@version": "2.0",
"channel": (
.feed as $feed
| .feed
| {
"title": .title,
"link": (find_links("self")[0]["@href"] // .id),
"pubDate": parse_date,
"lastBuildDate": parse_date,
"category": parse_categories,
"generator": (.generator | ensure_string // []),
"description": (.subtitle | ensure_string // []),
"copyright": (.rights | ensure_string // []),
"language": (.["@xml:lang"] | ensure_string // []),
"item": [
.entry[]
| {
"title": .title,
"guid": {
"@isPermaLink": "false",
"#text": .id
},
"link": (find_links("alternate")[0]["@href"]? // []),
"pubDate": parse_date,
"description": ((.summary // .content) | ensure_string | []),
"author": ((
# Pick the first author tag, falling back to the feed's authors if needed
((.author | ensure_array) + ($feed.author | ensure_array))[0] // {}
| if .email then "\(.email) (\(.name))" else .name end
) // []),
"category": parse_categories,
"source": (if .source then {
"@url": .id,
"#text": .title
} else [] end),
"enclosure": [
find_links("enclosure")[]
| {
"@url": .["@href"],
"@type": (.["@type"] | ensure_string // []),
"@length": (.["@length"] | ensure_string // [])
}
]
}
]
}
| . + if ($feed.logo // $feed.icon) then {
"image": {
"title": .title,
"link": .link,
"url": ($feed.logo // $feed.icon)
}
} else {} end
)
}
}

View File

@ -31,7 +31,7 @@
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="/">
<xsl:text><![CDATA[#!/bin/bash
@ -54,7 +54,7 @@ function log {
[ -z "$DIR" ] && DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
log Building to $DIR/feeds
mkdir -p $DIR/feeds
mkdir -p $DIR/feeds/_rss
if ! command -v json2xml >/dev/null 2>&1; then
log "Adding $DIR/bin to PATH"
@ -64,7 +64,7 @@ fi
]]></xsl:text>
<xsl:apply-templates select="//itsb:feed[not(itsb:link)]" />
</xsl:template>
<xsl:template match="itsb:feed[not(itsb:link)]">
<xsl:text>log Building </xsl:text>
<xsl:value-of select="./@id" />
@ -134,7 +134,7 @@ fi
</xsl:call-template>
<xsl:text>'</xsl:text>
</xsl:template>
<xsl:template match="itsb:jq">
<xsl:text>jq \
-L $DIR/jq \
@ -158,7 +158,7 @@ fi
</xsl:call-template>
<xsl:text>'</xsl:text>
</xsl:template>
<xsl:template match="itsb:pup">
<xsl:text>pup '</xsl:text>
<xsl:call-template name="escape">
@ -204,7 +204,7 @@ fi
</xsl:call-template>
<xsl:text>'</xsl:text>
</xsl:template>
<xsl:template match="itsb:shell">
<!-- good luck! -->
<xsl:value-of select="text()" />

81
xslt/itsb.xsl Normal file
View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://tilde.town/~lucidiot/itsb/"
xmlns:itsb="http://tilde.town/~lucidiot/itsb/">
<xsl:output method="xml" />
<!--
Preprocesses the itsb.xml file to autocomplete with converted feeds.
-->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="itsb:feed">
<xsl:copy-of select="." />
<!-- Store attributes in variables to make them accessible in conditionals later on -->
<xsl:variable name="lang" select="@lang" />
<xsl:variable name="type" select="@type" />
<!-- This is an Atom feed and there is no RSS feed: add a conversion -->
<xsl:if test="@format = 'atom' and not(../itsb:feed[((not(@lang) and not($lang)) or @lang = $lang) and ((not(@type) and not($type)) or @type = $type) and (@format = 'rss' or @format = 'rdf')])">
<feed>
<xsl:if test="@lang">
<xsl:attribute name="lang">
<xsl:value-of select="@lang" />
</xsl:attribute>
</xsl:if>
<xsl:if test="@type">
<xsl:attribute name="type">
<xsl:value-of select="@type" />
</xsl:attribute>
</xsl:if>
<xsl:attribute name="id">
<xsl:value-of select="@id" />
<xsl:text>-2rss</xsl:text>
</xsl:attribute>
<xsl:attribute name="format">rss</xsl:attribute>
<xsl:choose>
<xsl:when test="itsb:output">
<shell>
<xsl:text>cat $DIR/feeds/</xsl:text>
<xsl:value-of select="itsb:output/text()" />
</shell>
</xsl:when>
<xsl:otherwise>
<curl>
<url>
<xsl:value-of select="itsb:link/text()" />
</url>
</curl>
</xsl:otherwise>
</xsl:choose>
<xml2json />
<jq path="convert/atom2rss.jq" />
<json2xml />
<output>
<xsl:text>_rss/</xsl:text>
<xsl:choose>
<xsl:when test="itsb:output">
<xsl:value-of select="itsb:output/text()" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@id" />
<xsl:text>.xml</xsl:text>
</xsl:otherwise>
</xsl:choose>
</output>
</feed>
</xsl:if>
</xsl:template>
</xsl:stylesheet>