Skip to content

Commit cf3660c

Browse files
committed
fix: filter video content and increase episode limit in podcast feeds
- Filter out video episodes from podcast feeds (audio-only playback) - Show notice when video content is hidden with count - Increase episode limit from 40 to 1000 to show all tracks - Add helper functions: isAudioEpisode, isVideoEpisode, countVideoEpisodes - Display episode count in feed page header Fixes #2
1 parent cee4595 commit cf3660c

File tree

2 files changed

+53
-5
lines changed

2 files changed

+53
-5
lines changed

src/lib/podcastindex.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,10 +196,10 @@ export class PodcastIndexAPI {
196196
return data.items || [];
197197
}
198198

199-
async getFeedEpisodes(feedId: number): Promise<PodcastIndexEpisodesResponse> {
199+
async getFeedEpisodes(feedId: number, max: number = 1000): Promise<PodcastIndexEpisodesResponse> {
200200
const headers = await this.getAuthHeaders();
201201
const response = await fetch(
202-
`${this.baseUrl}/episodes/byfeedid?id=${feedId}&pretty`,
202+
`${this.baseUrl}/episodes/byfeedid?id=${feedId}&max=${max}&pretty`,
203203
{ headers }
204204
);
205205
if (!response.ok) {
@@ -222,3 +222,29 @@ export class PodcastIndexAPI {
222222
}
223223

224224
export const podcastIndexAPI = new PodcastIndexAPI();
225+
226+
// Helper to check if an episode is audio (not video)
227+
export function isAudioEpisode(episode: PodcastIndexEpisode): boolean {
228+
const enclosureType = episode.enclosureType?.toLowerCase() || '';
229+
230+
// Check if it's a video type
231+
const videoTypes = ['video/', 'video/mp4', 'video/webm', 'video/ogg', 'video/quicktime', 'video/x-m4v'];
232+
const isVideo = videoTypes.some(type => enclosureType.startsWith(type) || enclosureType.includes(type));
233+
234+
// Also check the URL for video extensions
235+
const videoExtensions = ['.mp4', '.webm', '.mov', '.m4v', '.avi', '.mkv'];
236+
const url = episode.enclosureUrl?.toLowerCase() || '';
237+
const hasVideoExtension = videoExtensions.some(ext => url.endsWith(ext));
238+
239+
return !isVideo && !hasVideoExtension;
240+
}
241+
242+
// Helper to check if an episode is video
243+
export function isVideoEpisode(episode: PodcastIndexEpisode): boolean {
244+
return !isAudioEpisode(episode);
245+
}
246+
247+
// Count video episodes in a list
248+
export function countVideoEpisodes(episodes: PodcastIndexEpisode[]): number {
249+
return episodes.filter(isVideoEpisode).length;
250+
}

src/pages/PodcastIndexFeedPage.tsx

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ import React from 'react';
22
import { useParams, useNavigate } from 'react-router-dom';
33
import { Button } from '@/components/ui/button';
44
import { Card, CardContent } from '@/components/ui/card';
5-
import { Play, Radio, ArrowLeft } from 'lucide-react';
5+
import { Play, Radio, ArrowLeft, Video } from 'lucide-react';
66
import { Skeleton } from '@/components/ui/skeleton';
77
import { usePodcastIndexFeedEpisodes, usePodcastIndexFeed } from '@/hooks/usePodcastIndex';
88
import { useMusicPlayer } from '@/contexts/MusicPlayerContext';
99
import { podcastIndexEpisodeToUnified } from '@/lib/unifiedTrack';
10+
import { isAudioEpisode, countVideoEpisodes } from '@/lib/podcastindex';
1011

1112
export function PodcastIndexFeedPage() {
1213
const { feedId } = useParams<{ feedId: string }>();
@@ -73,7 +74,10 @@ export function PodcastIndexFeedPage() {
7374
}
7475

7576
const feed = feedData.items[0]; // Get feed info from first episode
76-
const episodes = feedData.items;
77+
const allEpisodes = feedData.items;
78+
const videoCount = countVideoEpisodes(allEpisodes);
79+
// Filter out video episodes - only show audio content
80+
const episodes = allEpisodes.filter(isAudioEpisode);
7781
const unifiedTracks = episodes.map(ep => podcastIndexEpisodeToUnified(ep, feedInfo?.feed));
7882

7983
const handlePlayAll = () => {
@@ -141,7 +145,25 @@ export function PodcastIndexFeedPage() {
141145

142146
{/* Episodes List */}
143147
<div className="px-6 py-8">
144-
<h2 className="text-2xl font-bold mb-6">Episodes</h2>
148+
<div className="flex items-center justify-between mb-6">
149+
<h2 className="text-2xl font-bold">Episodes ({episodes.length})</h2>
150+
</div>
151+
152+
{/* Video content notice */}
153+
{videoCount > 0 && (
154+
<div className="mb-4 p-3 bg-gray-900 border border-gray-800 rounded-lg flex items-center gap-3">
155+
<Video className="h-5 w-5 text-yellow-500 flex-shrink-0" />
156+
<p className="text-sm text-gray-400">
157+
{videoCount} video episode{videoCount > 1 ? 's' : ''} hidden. ZapTrax currently supports audio-only content.
158+
</p>
159+
</div>
160+
)}
161+
162+
{episodes.length === 0 && (
163+
<div className="text-center py-12">
164+
<p className="text-gray-400">This feed only contains video content which is not supported yet.</p>
165+
</div>
166+
)}
145167

146168
<div className="space-y-2">
147169
{episodes.map((episode, index) => {

0 commit comments

Comments
 (0)