feat(podcast): Add Podcast 2.0 support and remove external feed dependency; implement internal RSS/Atom/JSON generators and update tests/README

This commit is contained in:
2025-10-31 21:04:50 +00:00
parent 90eb13ee17
commit 31c4460b34
16 changed files with 1667 additions and 81 deletions

View File

@@ -43,6 +43,7 @@ tap.test('should validate iTunes owner email', async () => {
itunesOwner: { name: 'Owner', email: 'not-an-email' },
itunesImage: 'https://example.com/image.jpg',
itunesExplicit: false,
podcastGuid: 'test-validation-guid-001',
});
} catch (error) {
errorThrown = true;
@@ -67,6 +68,7 @@ tap.test('should validate iTunes image URL', async () => {
itunesOwner: { name: 'Owner', email: 'owner@example.com' },
itunesImage: 'not-a-url',
itunesExplicit: false,
podcastGuid: 'test-validation-guid-002',
});
} catch (error) {
errorThrown = true;
@@ -91,6 +93,7 @@ tap.test('should validate iTunes type', async () => {
itunesOwner: { name: 'Owner', email: 'owner@example.com' },
itunesImage: 'https://example.com/image.jpg',
itunesExplicit: false,
podcastGuid: 'test-guid-auto',
itunesType: 'invalid' as any,
});
} catch (error) {
@@ -114,6 +117,7 @@ tap.test('should validate episode audio URL', async () => {
itunesOwner: { name: 'Owner', email: 'owner@example.com' },
itunesImage: 'https://example.com/image.jpg',
itunesExplicit: false,
podcastGuid: 'test-guid-auto',
});
let errorThrown = false;
@@ -151,6 +155,7 @@ tap.test('should validate audio type', async () => {
itunesOwner: { name: 'Owner', email: 'owner@example.com' },
itunesImage: 'https://example.com/image.jpg',
itunesExplicit: false,
podcastGuid: 'test-guid-auto',
});
let errorThrown = false;
@@ -189,6 +194,7 @@ tap.test('should validate audio length', async () => {
itunesOwner: { name: 'Owner', email: 'owner@example.com' },
itunesImage: 'https://example.com/image.jpg',
itunesExplicit: false,
podcastGuid: 'test-guid-auto',
});
let errorThrown = false;
@@ -226,6 +232,7 @@ tap.test('should validate duration', async () => {
itunesOwner: { name: 'Owner', email: 'owner@example.com' },
itunesImage: 'https://example.com/image.jpg',
itunesExplicit: false,
podcastGuid: 'test-guid-auto',
});
let errorThrown = false;
@@ -263,6 +270,7 @@ tap.test('should validate episode type', async () => {
itunesOwner: { name: 'Owner', email: 'owner@example.com' },
itunesImage: 'https://example.com/image.jpg',
itunesExplicit: false,
podcastGuid: 'test-guid-auto',
});
let errorThrown = false;
@@ -301,6 +309,7 @@ tap.test('should validate episode number', async () => {
itunesOwner: { name: 'Owner', email: 'owner@example.com' },
itunesImage: 'https://example.com/image.jpg',
itunesExplicit: false,
podcastGuid: 'test-guid-auto',
});
let errorThrown = false;
@@ -339,6 +348,7 @@ tap.test('should validate season number', async () => {
itunesOwner: { name: 'Owner', email: 'owner@example.com' },
itunesImage: 'https://example.com/image.jpg',
itunesExplicit: false,
podcastGuid: 'test-guid-auto',
});
let errorThrown = false;
@@ -377,6 +387,7 @@ tap.test('should validate duplicate episode IDs', async () => {
itunesOwner: { name: 'Owner', email: 'owner@example.com' },
itunesImage: 'https://example.com/image.jpg',
itunesExplicit: false,
podcastGuid: 'test-guid-auto',
});
const episodeData = {