mirror of
https://github.com/Einundzwanzig-Podcast/einundzwanzig.space.git
synced 2025-12-13 16:26:50 +00:00
Feed: Allow for custom entries
This commit is contained in:
@@ -1,19 +1,55 @@
|
|||||||
{
|
{
|
||||||
"dennis": "0231f73aef9bbdbf69e840640255946264026b56e17701f2d410b08b8b6e5d637a",
|
"dennis": {
|
||||||
"fab": "03f14237bb08f0afcb1ea07eff6b0b41e79294e66888971cccf1f585f5e21bf8f9",
|
"address": "030a58b8653d32b99200a2334cfe913e51dc7d155aa0116c176657a4f1722677a3",
|
||||||
"gigi": "02e12fea95f576a680ec1938b7ed98ef0855eadeced493566877d404e404bfbf52",
|
"customKey": "696969",
|
||||||
"markus": "0286e50ebeaafdf7dc321f6c8cb7e964e236b03ed67494b6337215c5c3c42252f2",
|
"customValue": "1M1LbWGzwPE2qViFPG34"
|
||||||
"daniel": "0201d14101401add234ebe3bc0e3020a39726daadf82bc3fa6b9871c4f5b17ab3f",
|
},
|
||||||
"egge": "02283e063b3121177fe8ed0c88806fe05b38cf5e192ff8c89e3bdc9b4df05dde21",
|
"fab": {
|
||||||
"joko": "03f51df0183b2083d678d867d7441ba7e8dbf1bfdd23729d702b81a8b128e3e876",
|
"address": "03f14237bb08f0afcb1ea07eff6b0b41e79294e66888971cccf1f585f5e21bf8f9"
|
||||||
"kemal": "02e01367e1d7818a7e9a0e8a52badd5c32615e07568dbe0497b6a47f9bef89d6af",
|
},
|
||||||
"ole": "03686128db3100e8a66caa3a50943aa72b80c00b3f8700ec01f3bf2e3657d69d54",
|
"gigi": {
|
||||||
"lassmiranda": "0320dbad5f3f70b095374fc609474f46393ba2c8b216dd7f69b325b482749ae538",
|
"address": "02e12fea95f576a680ec1938b7ed98ef0855eadeced493566877d404e404bfbf52"
|
||||||
"cercatrova": "02e1f391c9f3420fcaf65d45b615ab53034bd4a090036ddfb5703f6825b3b2bb4c",
|
},
|
||||||
"tanksen": "03d07c6075d640e680d54bd5201df087bc1fc56cbc084ab3aed54c3d96a486a919",
|
"markus": {
|
||||||
"gmblr247": "03b33aa7b3416fc7ccc50da498386a16e2577494269ec945177734e5684385cd00",
|
"address": "0286e50ebeaafdf7dc321f6c8cb7e964e236b03ed67494b6337215c5c3c42252f2"
|
||||||
"ben": "02b1278809d2853516d30b9af8d7bb3b1845d1beeed18ee22a9ccaddfe7f30a794",
|
},
|
||||||
"molo": "0355da86ca66c4b41d97b555a0eebb38c2a968b577ab920733aa91a0560751bac8",
|
"daniel": {
|
||||||
"zerofeerouting": "038fe1bd966b5cb0545963490c631eaa1924e2c4c0ea4e7dcb5d4582a1e7f2f1a5",
|
"address": "0201d14101401add234ebe3bc0e3020a39726daadf82bc3fa6b9871c4f5b17ab3f"
|
||||||
"quillie": "0356cf6646a8022cdddee51204415161cb8c2f1a47d3429ebaaa1a2691e09e9c17"
|
},
|
||||||
|
"egge": {
|
||||||
|
"address": "02283e063b3121177fe8ed0c88806fe05b38cf5e192ff8c89e3bdc9b4df05dde21"
|
||||||
|
},
|
||||||
|
"joko": {
|
||||||
|
"address": "03f51df0183b2083d678d867d7441ba7e8dbf1bfdd23729d702b81a8b128e3e876"
|
||||||
|
},
|
||||||
|
"kemal": {
|
||||||
|
"address": "02e01367e1d7818a7e9a0e8a52badd5c32615e07568dbe0497b6a47f9bef89d6af"
|
||||||
|
},
|
||||||
|
"ole": {
|
||||||
|
"address": "03686128db3100e8a66caa3a50943aa72b80c00b3f8700ec01f3bf2e3657d69d54"
|
||||||
|
},
|
||||||
|
"lassmiranda": {
|
||||||
|
"address": "0320dbad5f3f70b095374fc609474f46393ba2c8b216dd7f69b325b482749ae538"
|
||||||
|
},
|
||||||
|
"cercatrova": {
|
||||||
|
"address": "02e1f391c9f3420fcaf65d45b615ab53034bd4a090036ddfb5703f6825b3b2bb4c"
|
||||||
|
},
|
||||||
|
"tanksen": {
|
||||||
|
"address": "03d07c6075d640e680d54bd5201df087bc1fc56cbc084ab3aed54c3d96a486a919"
|
||||||
|
},
|
||||||
|
"gmblr247": {
|
||||||
|
"address": "03b33aa7b3416fc7ccc50da498386a16e2577494269ec945177734e5684385cd00"
|
||||||
|
},
|
||||||
|
"ben": {
|
||||||
|
"address": "02b1278809d2853516d30b9af8d7bb3b1845d1beeed18ee22a9ccaddfe7f30a794"
|
||||||
|
},
|
||||||
|
"molo": {
|
||||||
|
"address": "0355da86ca66c4b41d97b555a0eebb38c2a968b577ab920733aa91a0560751bac8"
|
||||||
|
},
|
||||||
|
"zerofeerouting": {
|
||||||
|
"address": "038fe1bd966b5cb0545963490c631eaa1924e2c4c0ea4e7dcb5d4582a1e7f2f1a5"
|
||||||
|
},
|
||||||
|
"quillie": {
|
||||||
|
"address": "0356cf6646a8022cdddee51204415161cb8c2f1a47d3429ebaaa1a2691e09e9c17"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const { writeFileSync } = require('fs')
|
const { writeFileSync } = require('fs')
|
||||||
const { join, resolve } = require('path')
|
const { join, resolve } = require('path')
|
||||||
const { replacements, slugify, stripHTML } = require('../helpers')
|
const { replacements, slugify, stripHTML } = require('../helpers')
|
||||||
const { masterFeedUrl, publicFeedUrl } = require('../content/meta.json')
|
const { masterFeedUrl, publicFeedUrl } = require('../content/meta.json')
|
||||||
const team = require('../content/team.json')
|
const team = require('../content/team.json')
|
||||||
const nodes = require('../content/nodes.json')
|
const nodes = require('../content/nodes.json')
|
||||||
@@ -11,7 +11,8 @@ const xmlFormat = require('xml-formatter')
|
|||||||
const debug = process.env.CI
|
const debug = process.env.CI
|
||||||
const dir = resolve(__dirname, '..')
|
const dir = resolve(__dirname, '..')
|
||||||
const write = (name, data) => writeFileSync(join(dir, name), data)
|
const write = (name, data) => writeFileSync(join(dir, name), data)
|
||||||
const writeJSON = (name, data) => write(`generated/${name}.json`, JSON.stringify(data, null, 2))
|
const writeJSON = (name, data) =>
|
||||||
|
write(`generated/${name}.json`, JSON.stringify(data, null, 2))
|
||||||
|
|
||||||
const commonOpts = {
|
const commonOpts = {
|
||||||
attributeNamePrefix: '',
|
attributeNamePrefix: '',
|
||||||
@@ -42,7 +43,9 @@ const parseEpisode = e => {
|
|||||||
const title = e.title.__cdata.trim()
|
const title = e.title.__cdata.trim()
|
||||||
const content = replacements(e.description.__cdata).trim()
|
const content = replacements(e.description.__cdata).trim()
|
||||||
const description = stripHTML(content)
|
const description = stripHTML(content)
|
||||||
let [, categoryName = 'News', number, titlePlain] = title.match(/([\w\s]+?)?\s?#(\d+) - (.*)/) || [, , , title]
|
let [, categoryName = 'News', number, titlePlain] = title.match(
|
||||||
|
/([\w\s]+?)?\s?#(\d+) - (.*)/
|
||||||
|
) || [, , , title]
|
||||||
if (!number) categoryName = 'Verschiedenes'
|
if (!number) categoryName = 'Verschiedenes'
|
||||||
if (categoryName === 'Der-Weg') categoryName = 'Der Weg'
|
if (categoryName === 'Der-Weg') categoryName = 'Der Weg'
|
||||||
if (categoryName === 'Buchclub') categoryName = 'Lesestunde'
|
if (categoryName === 'Buchclub') categoryName = 'Lesestunde'
|
||||||
@@ -53,12 +56,36 @@ const parseEpisode = e => {
|
|||||||
const slug = slugify(`${categoryName} ${number || ''} ${titlePlain}`)
|
const slug = slugify(`${categoryName} ${number || ''} ${titlePlain}`)
|
||||||
const date = new Date(e.pubDate)
|
const date = new Date(e.pubDate)
|
||||||
const img = e['itunes:image'].__attr.href
|
const img = e['itunes:image'].__attr.href
|
||||||
const image = ['interview', 'lesestunde', 'verschiedenes'].includes(category) ? img : `/img/cover/${category}.png`
|
const image = ['interview', 'lesestunde', 'verschiedenes'].includes(category)
|
||||||
|
? img
|
||||||
|
: `/img/cover/${category}.png`
|
||||||
const duration = e['itunes:duration']
|
const duration = e['itunes:duration']
|
||||||
const enclosure = e.enclosure.__attr
|
const enclosure = e.enclosure.__attr
|
||||||
const [, participantsString] = firstLine.match(/ - (?:(?:von und )?mit )([^.]*)/i) || []
|
const [, participantsString] =
|
||||||
const participants = participantsString ? participantsString.replace(/(\s*,\s*|\s*und\s*|\s*&\s*)/ig, '%').trim().split('%') : []
|
firstLine.match(/ - (?:(?:von und )?mit )([^.]*)/i) || []
|
||||||
return { block, category, categoryName, number, title, titlePlain, description, content, duration, slug, image, guid, date, enclosure, participants }
|
const participants = participantsString
|
||||||
|
? participantsString
|
||||||
|
.replace(/(\s*,\s*|\s*und\s*|\s*&\s*)/gi, '%')
|
||||||
|
.trim()
|
||||||
|
.split('%')
|
||||||
|
: []
|
||||||
|
return {
|
||||||
|
block,
|
||||||
|
category,
|
||||||
|
categoryName,
|
||||||
|
number,
|
||||||
|
title,
|
||||||
|
titlePlain,
|
||||||
|
description,
|
||||||
|
content,
|
||||||
|
duration,
|
||||||
|
slug,
|
||||||
|
image,
|
||||||
|
guid,
|
||||||
|
date,
|
||||||
|
enclosure,
|
||||||
|
participants
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
;(async () => {
|
;(async () => {
|
||||||
@@ -66,22 +93,43 @@ const parseEpisode = e => {
|
|||||||
const anchorXML = request('GET', masterFeedUrl).getBody('utf8')
|
const anchorXML = request('GET', masterFeedUrl).getBody('utf8')
|
||||||
const xml = anchorXML
|
const xml = anchorXML
|
||||||
.replace(`"${masterFeedUrl}"`, `"${publicFeedUrl}"`)
|
.replace(`"${masterFeedUrl}"`, `"${publicFeedUrl}"`)
|
||||||
.replace('xmlns:anchor="https://anchor.fm/xmlns"', 'xmlns:anchor="https://anchor.fm/xmlns" xmlns:podcast="https://podcastindex.org/namespace/1.0"')
|
.replace(
|
||||||
.replace('<channel>', `<channel>
|
'xmlns:anchor="https://anchor.fm/xmlns"',
|
||||||
<podcast:value type="lightning" method="keysend">
|
'xmlns:anchor="https://anchor.fm/xmlns" xmlns:podcast="https://podcastindex.org/namespace/1.0"'
|
||||||
<podcast:valueRecipient type="node" split="20" name="Dennis" address="${nodes.dennis}" />
|
)
|
||||||
<podcast:valueRecipient type="node" split="20" name="Fab" address="${nodes.fab}" />
|
.replace('<channel>', '<channel><podcast:value></podcast:value>')
|
||||||
<podcast:valueRecipient type="node" split="20" name="Gigi" address="${nodes.gigi}" />
|
|
||||||
<podcast:valueRecipient type="node" split="20" name="Markus" address="${nodes.markus}" />
|
|
||||||
<podcast:valueRecipient type="node" split="20" name="Daniel" address="${nodes.daniel}" />
|
|
||||||
</podcast:value>`)
|
|
||||||
|
|
||||||
const feed = parser.parse(xml)
|
const feed = parser.parse(xml)
|
||||||
const episodes = []
|
const episodes = []
|
||||||
const _noParticipants = [], _noNode = []
|
const _noParticipants = [],
|
||||||
|
_noNode = []
|
||||||
|
const members = [
|
||||||
|
{ name: 'Dennis', ...nodes.dennis },
|
||||||
|
{ name: 'Fab', ...nodes.fab },
|
||||||
|
{ name: 'Gigi', ...nodes.gigi },
|
||||||
|
{ name: 'Markus', ...nodes.markus },
|
||||||
|
{ name: 'Daniel', ...nodes.daniel }
|
||||||
|
]
|
||||||
|
|
||||||
delete feed.rss.channel.author // remove invalid tag
|
// remove invalid tag
|
||||||
|
delete feed.rss.channel.author
|
||||||
|
|
||||||
|
// podcast
|
||||||
|
feed.rss.channel['podcast:value'] = {
|
||||||
|
__attr: {
|
||||||
|
type: 'lightning',
|
||||||
|
method: 'keysend'
|
||||||
|
},
|
||||||
|
'podcast:valueRecipient': members.map(p => ({
|
||||||
|
__attr: {
|
||||||
|
...p,
|
||||||
|
type: 'node',
|
||||||
|
split: Math.round(100 / members.length)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
// episodes
|
||||||
feed.rss.channel.item = feed.rss.channel.item.map(item => {
|
feed.rss.channel.item = feed.rss.channel.item.map(item => {
|
||||||
const episode = parseEpisode(item)
|
const episode = parseEpisode(item)
|
||||||
episodes.push(episode)
|
episodes.push(episode)
|
||||||
@@ -95,17 +143,17 @@ const parseEpisode = e => {
|
|||||||
if (episode.number) {
|
if (episode.number) {
|
||||||
updated['podcast:episode'] = {
|
updated['podcast:episode'] = {
|
||||||
__attr: {
|
__attr: {
|
||||||
display: `${episode.categoryName} #${episode.number}`,
|
display: `${episode.categoryName} #${episode.number}`
|
||||||
},
|
},
|
||||||
'#text': episode.number,
|
'#text': episode.number
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const value = episode.participants.reduce((result, name) => {
|
const value = episode.participants.reduce((result, name) => {
|
||||||
const id = name.toLowerCase()
|
const id = name.toLowerCase()
|
||||||
const address = nodes[id]
|
const node = nodes[id]
|
||||||
if (address) {
|
if (node) {
|
||||||
result.push({ name, address })
|
result.push({ name, ...node })
|
||||||
} else if (debug) {
|
} else if (debug) {
|
||||||
_noNode.push({ episode: episode.slug, name })
|
_noNode.push({ episode: episode.slug, name })
|
||||||
}
|
}
|
||||||
@@ -116,15 +164,15 @@ const parseEpisode = e => {
|
|||||||
updated['podcast:value'] = {
|
updated['podcast:value'] = {
|
||||||
__attr: {
|
__attr: {
|
||||||
type: 'lightning',
|
type: 'lightning',
|
||||||
method: 'keysend',
|
method: 'keysend'
|
||||||
},
|
},
|
||||||
'podcast:valueRecipient': value.map(p => ({
|
'podcast:valueRecipient': value.map(p => ({
|
||||||
__attr: {
|
__attr: {
|
||||||
...p,
|
...p,
|
||||||
type: 'node',
|
type: 'node',
|
||||||
split: Math.round(100 / value.length),
|
split: Math.round(100 / value.length)
|
||||||
},
|
}
|
||||||
})),
|
}))
|
||||||
}
|
}
|
||||||
} else if (debug) {
|
} else if (debug) {
|
||||||
_noParticipants.push({ episode: episode.slug })
|
_noParticipants.push({ episode: episode.slug })
|
||||||
@@ -145,7 +193,7 @@ const parseEpisode = e => {
|
|||||||
people.forEach(p => {
|
people.forEach(p => {
|
||||||
updated['podcast:person'].push({
|
updated['podcast:person'].push({
|
||||||
__attr: {
|
__attr: {
|
||||||
href: `https://twitter.com/${p.twitter}`,
|
href: `https://twitter.com/${p.twitter}`
|
||||||
},
|
},
|
||||||
'#text': p.name
|
'#text': p.name
|
||||||
})
|
})
|
||||||
@@ -163,7 +211,13 @@ const parseEpisode = e => {
|
|||||||
|
|
||||||
const validation = XMLValidator.validate(outputXML)
|
const validation = XMLValidator.validate(outputXML)
|
||||||
if (validation) {
|
if (validation) {
|
||||||
write('dist/feed.xml', xmlFormat(outputXML, { indentation: json2xmlOpts.indentBy, collapseContent: true }))
|
write(
|
||||||
|
'dist/feed.xml',
|
||||||
|
xmlFormat(outputXML, {
|
||||||
|
indentation: json2xmlOpts.indentBy,
|
||||||
|
collapseContent: true
|
||||||
|
})
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
console.error(validation.err)
|
console.error(validation.err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user