Files
DIYgod 9672efd80d fix(json): serialize podcast durations as numeric seconds
Affected files:
- lib/views/json.test.ts
- lib/views/json.ts
2026-10-14 15:07:46 +08:00

71 lines
2.9 KiB
TypeScript

import type { Data, DataItem } from '@/types';
const toDurationInSeconds = (duration: DataItem['itunes_duration']) => {
if (typeof duration === 'number') {
return Number.isFinite(duration) && duration >= 0 ? duration : undefined;
}
if (typeof duration !== 'string') {
return;
}
if (/^\d+(?:\.\d+)?$/.test(duration)) {
const seconds = Number(duration);
return Number.isFinite(seconds) ? seconds : undefined;
}
if (!/^\d+:(?:[0-5]?\d:)?[0-5]?\d(?:\.\d+)?$/.test(duration)) {
return;
}
const seconds = duration.split(':').reduce((total, part) => total * 60 + Number(part), 0);
return Number.isFinite(seconds) ? seconds : undefined;
};
/**
* This function should be used by RSSHub middleware only.
* @param {object} data ctx.state.data
* @returns `JSON.stringify`-ed [JSON Feed](https://www.jsonfeed.org/)
*/
const json = (data: Data) => {
const jsonFeed = {
version: 'https://jsonfeed.org/version/1.1',
title: data.title || 'RSSHub',
home_page_url: data.link || 'https://docs.rsshub.app',
feed_url: data.feedLink,
description: `${data.description || data.title} - Powered by RSSHub`,
icon: data.image,
authors: data.author === undefined || Array.isArray(data.author) ? data.author : [{ name: data.author }],
language: data.language || 'zh-cn',
items: data.item?.map((item) => ({
id: item.guid || item.id || item.link,
url: item.link,
title: item.title,
// content_html and content_text are each optional strings — but one or both must be present
content_html: item.description,
content_text: item.content?.text || (item.description ? undefined : item.title),
summary: item.summary,
image: item.image || item.itunes_item_image,
banner_image: item.banner,
date_published: item.pubDate,
date_modified: item.updated,
authors: item.author === undefined || Array.isArray(item.author) ? item.author : [{ name: item.author }],
tags: item.category === undefined || Array.isArray(item.category) ? item.category : [item.category],
language: item.language,
attachments:
item.attachments ||
(item.enclosure_url
? [
{
url: item.enclosure_url,
mime_type: item.enclosure_type,
title: item.enclosure_title,
size_in_bytes: item.enclosure_length,
duration_in_seconds: toDurationInSeconds(item.itunes_duration),
},
]
: undefined),
_extra: item._extra || undefined,
})),
};
return JSON.stringify(jsonFeed);
};
export default json;