79 lines
2.6 KiB
TypeScript
79 lines
2.6 KiB
TypeScript
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
|
|
import { NextRequest, NextResponse } from 'next/server';
|
|
|
|
import { getConfig } from '@/lib/config';
|
|
import { requireFeaturePermission } from '@/lib/permissions';
|
|
|
|
export const runtime = 'nodejs';
|
|
|
|
export async function GET(request: NextRequest) {
|
|
const authResult = await requireFeaturePermission(request, 'live', '无权限访问电视直播');
|
|
if (authResult instanceof NextResponse) return authResult;
|
|
const { searchParams } = new URL(request.url);
|
|
const url = searchParams.get('url');
|
|
const source = searchParams.get('moontv-source');
|
|
|
|
if (!url) {
|
|
return NextResponse.json({ error: 'Missing url' }, { status: 400 });
|
|
}
|
|
const config = await getConfig();
|
|
const liveSource = config.LiveConfig?.find((s: any) => s.key === source);
|
|
if (!liveSource) {
|
|
return NextResponse.json({ error: 'Source not found' }, { status: 404 });
|
|
}
|
|
const ua = liveSource.ua || 'AptvPlayer/1.4.10';
|
|
|
|
try {
|
|
const decodedUrl = decodeURIComponent(url);
|
|
|
|
const response = await fetch(decodedUrl, {
|
|
cache: 'no-cache',
|
|
redirect: 'follow',
|
|
credentials: 'same-origin',
|
|
headers: {
|
|
'User-Agent': ua,
|
|
},
|
|
});
|
|
|
|
if (!response.ok) {
|
|
return NextResponse.json({ error: 'Failed to fetch', message: response.statusText }, { status: 500 });
|
|
}
|
|
|
|
const contentType = response.headers.get('Content-Type') || '';
|
|
const normalizedContentType = contentType.toLowerCase();
|
|
const finalUrl = response.url || decodedUrl;
|
|
const normalizedUrl = finalUrl.toLowerCase().split('?')[0];
|
|
if (response.body) {
|
|
response.body.cancel();
|
|
}
|
|
if (normalizedContentType.includes('video/mp4') || normalizedUrl.endsWith('.mp4')) {
|
|
return NextResponse.json({ success: true, type: 'mp4' }, { status: 200 });
|
|
}
|
|
if (
|
|
normalizedContentType.includes('video/x-flv') ||
|
|
normalizedContentType.includes('video/flv') ||
|
|
normalizedUrl.endsWith('.flv')
|
|
) {
|
|
return NextResponse.json({ success: true, type: 'flv' }, { status: 200 });
|
|
}
|
|
if (
|
|
normalizedContentType.includes('mpegurl') ||
|
|
normalizedContentType.includes('application/vnd.apple') ||
|
|
normalizedUrl.endsWith('.m3u8') ||
|
|
normalizedUrl.endsWith('.m3u')
|
|
) {
|
|
return NextResponse.json({ success: true, type: 'm3u8' }, { status: 200 });
|
|
}
|
|
return NextResponse.json(
|
|
{
|
|
error: 'Unsupported live stream type',
|
|
contentType,
|
|
},
|
|
{ status: 415 }
|
|
);
|
|
} catch (error) {
|
|
return NextResponse.json({ error: 'Failed to fetch', message: error }, { status: 500 });
|
|
}
|
|
}
|