UNPKG

feedsmith

Version:

Fast, all‑in‑one feed parser and generator for RSS, Atom, RDF, and JSON Feed, with support for Podcast, iTunes, Dublin Core, and OPML files.

311 lines (310 loc) 11.5 kB
import { isObject, parseArrayOf, parseBoolean, parseDate, parseNumber, parseSingularOf, parseString, parseYesNoBoolean, retrieveText, trimArray, trimObject } from "../../../common/utils.js"; //#region src/namespaces/podcast/parse/utils.ts const whitespaceRegex = /\s+/; const trailingWRegex = /w$/; const parseTranscript = (value) => { if (!isObject(value)) return; return trimObject({ url: parseString(value["@url"]), type: parseString(value["@type"]), language: parseString(value["@language"]), rel: parseString(value["@rel"]) }); }; const parseLocked = (value) => { return trimObject({ value: parseYesNoBoolean(retrieveText(value)), owner: parseString(value?.["@owner"]) }); }; const parseFunding = (value) => { if (!isObject(value)) return; return trimObject({ url: parseString(value["@url"]), display: parseString(value["#text"]) }); }; const parseChapters = (value) => { if (!isObject(value)) return; return trimObject({ url: parseString(value["@url"]), type: parseString(value["@type"]) }); }; const parseSoundbite = (value) => { if (!isObject(value)) return; return trimObject({ startTime: parseNumber(value["@starttime"]), duration: parseNumber(value["@duration"]), display: parseString(retrieveText(value)) }); }; const parsePerson = (value) => { return trimObject({ display: parseString(retrieveText(value)), role: parseString(value?.["@role"]), group: parseString(value?.["@group"]), img: parseString(value?.["@img"]), href: parseString(value?.["@href"]) }); }; const parseLocation = (value) => { return trimObject({ display: parseString(retrieveText(value)), rel: parseString(value?.["@rel"]), geo: parseString(value?.["@geo"]), osm: parseString(value?.["@osm"]), country: parseString(value?.["@country"]) }); }; const parseSeason = (value) => { return trimObject({ number: parseNumber(retrieveText(value)), name: parseString(value?.["@name"]) }); }; const parseEpisode = (value) => { return trimObject({ number: parseNumber(retrieveText(value)), display: parseString(value?.["@display"]) }); }; const parseTrailer = (value) => { if (!isObject(value)) return; return trimObject({ display: parseString(retrieveText(value)), url: parseString(value["@url"]), pubDate: parseDate(value["@pubdate"]), length: parseNumber(value["@length"]), type: parseString(value["@type"]), season: parseNumber(value["@season"]) }); }; const parseLicense = (value) => { return trimObject({ display: parseString(retrieveText(value)), url: parseString(value?.["@url"]) }); }; const parseAlternateEnclosure = (value) => { if (!isObject(value)) return; return trimObject({ type: parseString(value["@type"]), length: parseNumber(value["@length"]), bitrate: parseNumber(value["@bitrate"]), height: parseNumber(value["@height"]), lang: parseString(value["@lang"]), title: parseString(value["@title"]), rel: parseString(value["@rel"]), codecs: parseString(value["@codecs"]), default: parseBoolean(value["@default"]), sources: parseArrayOf(value["podcast:source"], parseSource), integrity: parseSingularOf(value["podcast:integrity"], parseIntegrity) }); }; const parseSource = (value) => { if (!isObject(value)) return; return trimObject({ uri: parseString(value["@uri"]), contentType: parseString(value["@contenttype"]) }); }; const parseIntegrity = (value) => { if (!isObject(value)) return; return trimObject({ type: parseString(value["@type"]), value: parseString(value["@value"]) }); }; const parseValue = (value) => { if (!isObject(value)) return; return trimObject({ type: parseString(value["@type"]), method: parseString(value["@method"]), suggested: parseNumber(value["@suggested"]), valueRecipients: parseArrayOf(value["podcast:valuerecipient"], parseValueRecipient), valueTimeSplits: parseArrayOf(value["podcast:valuetimesplit"], parseValueTimeSplit) }); }; const parseValueRecipient = (value) => { if (!isObject(value)) return; return trimObject({ name: parseString(value["@name"]), customKey: parseString(value["@customkey"]), customValue: parseString(value["@customvalue"]), type: parseString(value["@type"]), address: parseString(value["@address"]), split: parseNumber(value["@split"]), fee: parseBoolean(value["@fee"]) }); }; const parseImage = (value) => { if (!isObject(value)) return; return trimObject({ href: parseString(value["@href"]), alt: parseString(value["@alt"]), aspectRatio: parseString(value["@aspect-ratio"]), width: parseNumber(value["@width"]), height: parseNumber(value["@height"]), type: parseString(value["@type"]), purpose: parseString(value["@purpose"]) }); }; const parseImages = (value) => { const srcset = parseString(value?.["@srcset"]); if (!srcset) return; const images = []; const segments = srcset.split(","); for (const segment of segments) { const [href, width] = segment.trim().split(whitespaceRegex); const image = { href: parseString(href), width: parseNumber(width?.replace(trailingWRegex, "")) }; images.push(image); } return trimArray(images, trimObject); }; const retrieveImages = (value) => { return parseArrayOf(value["podcast:image"], parseImage) ?? parseSingularOf(value["podcast:images"], parseImages); }; const parseLiveItem = (value) => { if (!isObject(value)) return; return trimObject({ ...retrieveItem(value), status: parseString(value["@status"]), start: parseDate(value["@start"]), end: parseDate(value["@end"]), contentLinks: parseArrayOf(value["podcast:contentlink"], parseContentLink) }); }; const parseContentLink = (value) => { if (!isObject(value)) return; return trimObject({ href: parseString(value["@href"]), display: parseString(retrieveText(value)) }); }; const parseSocialInteract = (value) => { if (!isObject(value)) return; return trimObject({ uri: parseString(value["@uri"]), protocol: parseString(value["@protocol"]), accountId: parseString(value["@accountid"]), accountUrl: parseString(value["@accounturl"]), priority: parseNumber(value["@priority"]) }); }; const parseChat = (value) => { if (!isObject(value)) return; return trimObject({ server: parseString(value["@server"]), protocol: parseString(value["@protocol"]), accountId: parseString(value["@accountid"]), space: parseString(value["@space"]) }); }; const parseBlock = (value) => { return trimObject({ value: parseYesNoBoolean(retrieveText(value)), id: parseString(value?.["@id"]) }); }; const parseTxt = (value) => { return trimObject({ display: parseString(retrieveText(value)), purpose: parseString(value?.["@purpose"]) }); }; const parseRemoteItem = (value) => { if (!isObject(value)) return; return trimObject({ feedGuid: parseString(value["@feedguid"]), feedUrl: parseString(value["@feedurl"]), itemGuid: parseString(value["@itemguid"]), medium: parseString(value["@medium"]), title: parseString(value["@title"]) }); }; const parsePodroll = (value) => { if (!isObject(value)) return; return trimObject({ remoteItems: parseArrayOf(value["podcast:remoteitem"], parseRemoteItem) }); }; const parseUpdateFrequency = (value) => { return trimObject({ display: parseString(retrieveText(value)), complete: parseBoolean(value?.["@complete"]), dtstart: parseDate(value?.["@dtstart"]), rrule: parseString(value?.["@rrule"]) }); }; const parsePodping = (value) => { if (!isObject(value)) return; return trimObject({ usesPodping: parseBoolean(value["@usespodping"]) }); }; const parsePublisher = (value) => { if (!isObject(value)) return; return trimObject({ remoteItem: parseSingularOf(value["podcast:remoteitem"], parseRemoteItem) }); }; const parseValueTimeSplit = (value) => { if (!isObject(value)) return; return trimObject({ startTime: parseNumber(value["@starttime"]), duration: parseNumber(value["@duration"]), remoteStartTime: parseNumber(value["@remotestarttime"]), remotePercentage: parseNumber(value["@remotepercentage"]), remoteItem: parseSingularOf(value["podcast:remoteitem"], parseRemoteItem), valueRecipients: parseArrayOf(value["podcast:valuerecipient"], parseValueRecipient) }); }; const retrieveItem = (value) => { if (!isObject(value)) return; return trimObject({ transcripts: parseArrayOf(value["podcast:transcript"], parseTranscript), chapters: parseSingularOf(value["podcast:chapters"], parseChapters), soundbites: parseArrayOf(value["podcast:soundbite"], parseSoundbite), persons: parseArrayOf(value["podcast:person"], parsePerson), locations: parseArrayOf(value["podcast:location"], parseLocation), season: parseSingularOf(value["podcast:season"], parseSeason), episode: parseSingularOf(value["podcast:episode"], parseEpisode), license: parseSingularOf(value["podcast:license"], parseLicense), alternateEnclosures: parseArrayOf(value["podcast:alternateenclosure"], parseAlternateEnclosure), values: parseArrayOf(value["podcast:value"], parseValue), images: retrieveImages(value), socialInteracts: parseArrayOf(value["podcast:socialinteract"], parseSocialInteract), txts: parseArrayOf(value["podcast:txt"], parseTxt), chat: parseSingularOf(value["podcast:chat"], parseChat), location: parseSingularOf(value["podcast:location"], parseLocation), value: parseSingularOf(value["podcast:value"], parseValue), chats: parseArrayOf(value["podcast:chat"], parseChat) }); }; const retrieveFeed = (value) => { if (!isObject(value)) return; return trimObject({ locked: parseSingularOf(value["podcast:locked"], parseLocked), fundings: parseArrayOf(value["podcast:funding"], parseFunding), persons: parseArrayOf(value["podcast:person"], parsePerson), locations: parseArrayOf(value["podcast:location"], parseLocation), trailers: parseArrayOf(value["podcast:trailer"], parseTrailer), license: parseSingularOf(value["podcast:license"], parseLicense), guid: parseSingularOf(value["podcast:guid"], (value) => parseString(retrieveText(value))), values: parseArrayOf(value["podcast:value"], parseValue), medium: parseSingularOf(value["podcast:medium"], (value) => parseString(retrieveText(value))), images: retrieveImages(value), liveItems: parseArrayOf(value["podcast:liveitem"], parseLiveItem), blocks: parseArrayOf(value["podcast:block"], parseBlock), txts: parseArrayOf(value["podcast:txt"], parseTxt), remoteItems: parseArrayOf(value["podcast:remoteitem"], parseRemoteItem), podroll: parseSingularOf(value["podcast:podroll"], parsePodroll), updateFrequency: parseSingularOf(value["podcast:updatefrequency"], parseUpdateFrequency), podping: parseSingularOf(value["podcast:podping"], parsePodping), chat: parseSingularOf(value["podcast:chat"], parseChat), publisher: parseSingularOf(value["podcast:publisher"], parsePublisher), location: parseSingularOf(value["podcast:location"], parseLocation), value: parseSingularOf(value["podcast:value"], parseValue), chats: parseArrayOf(value["podcast:chat"], parseChat) }); }; //#endregion export { parseAlternateEnclosure, parseBlock, parseChapters, parseChat, parseContentLink, parseEpisode, parseFunding, parseImage, parseImages, parseIntegrity, parseLicense, parseLiveItem, parseLocation, parseLocked, parsePerson, parsePodping, parsePodroll, parsePublisher, parseRemoteItem, parseSeason, parseSocialInteract, parseSoundbite, parseSource, parseTrailer, parseTranscript, parseTxt, parseUpdateFrequency, parseValue, parseValueRecipient, parseValueTimeSplit, retrieveFeed, retrieveImages, retrieveItem };