mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-10-17 05:11:57 +08:00
fix(json): serialize podcast durations as numeric seconds
Affected files: - lib/views/json.test.ts - lib/views/json.ts
This commit is contained in:
@@ -3,6 +3,33 @@ import { describe, expect, it } from 'vitest';
|
||||
import jsonView from '@/views/json';
|
||||
|
||||
describe('JSON view', () => {
|
||||
it.each([
|
||||
[65, 65],
|
||||
['65', 65],
|
||||
['0:01:05', 65],
|
||||
['01:02:03', 3723],
|
||||
['90:00', 5400],
|
||||
['0:00:01.5', 1.5],
|
||||
[0, 0],
|
||||
['invalid', undefined],
|
||||
['0:99:00', undefined],
|
||||
[-1, undefined],
|
||||
[Infinity, undefined],
|
||||
])('serializes podcast duration %s as numeric seconds', (duration, seconds) => {
|
||||
const feed = JSON.parse(
|
||||
jsonView({
|
||||
title: 'Podcast',
|
||||
item: [{ title: 'Episode', enclosure_url: 'https://example.com/audio.mp3', enclosure_type: 'audio/mpeg', itunes_duration: duration }],
|
||||
})
|
||||
);
|
||||
const attachment = feed.items[0].attachments[0];
|
||||
if (seconds === undefined) {
|
||||
expect(attachment).not.toHaveProperty('duration_in_seconds');
|
||||
} else {
|
||||
expect(attachment.duration_in_seconds).toBe(seconds);
|
||||
}
|
||||
});
|
||||
|
||||
it('renders summary, authors, tags, attachments, and extras', () => {
|
||||
const jsonOutput = jsonView({
|
||||
title: 'JSON Feed',
|
||||
|
||||
+20
-2
@@ -1,4 +1,22 @@
|
||||
import type { Data } from '@/types';
|
||||
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.
|
||||
@@ -39,7 +57,7 @@ const json = (data: Data) => {
|
||||
mime_type: item.enclosure_type,
|
||||
title: item.enclosure_title,
|
||||
size_in_bytes: item.enclosure_length,
|
||||
duration_in_seconds: item.itunes_duration,
|
||||
duration_in_seconds: toDurationInSeconds(item.itunes_duration),
|
||||
},
|
||||
]
|
||||
: undefined),
|
||||
|
||||
Reference in New Issue
Block a user