feat: add oriontv compatible interfaces

This commit is contained in:
shinya
2025-07-08 21:28:44 +08:00
parent d0966f09d6
commit 5a734b944f
6 changed files with 154 additions and 8 deletions

View File

@@ -0,0 +1,59 @@
import { NextResponse } from 'next/server';
export const runtime = 'edge';
// OrionTV 兼容接口
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const imageUrl = searchParams.get('url');
if (!imageUrl) {
return NextResponse.json({ error: 'Missing image URL' }, { status: 400 });
}
try {
const imageResponse = await fetch(imageUrl, {
headers: {
Referer: 'https://movie.douban.com/',
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
},
});
if (!imageResponse.ok) {
return NextResponse.json(
{ error: imageResponse.statusText },
{ status: imageResponse.status }
);
}
const contentType = imageResponse.headers.get('content-type');
if (!imageResponse.body) {
return NextResponse.json(
{ error: 'Image response has no body' },
{ status: 500 }
);
}
// 创建响应头
const headers = new Headers();
if (contentType) {
headers.set('Content-Type', contentType);
}
// 设置缓存头(可选)
headers.set('Cache-Control', 'public, max-age=86400'); // 缓存24小时
// 直接返回图片流
return new Response(imageResponse.body, {
status: 200,
headers,
});
} catch (error) {
return NextResponse.json(
{ error: 'Error fetching image' },
{ status: 500 }
);
}
}

View File

@@ -0,0 +1,72 @@
import { NextResponse } from 'next/server';
import { getAvailableApiSites, getCacheTime } from '@/lib/config';
import { searchFromApi } from '@/lib/downstream';
export const runtime = 'edge';
// OrionTV 兼容接口
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const query = searchParams.get('q');
const resourceId = searchParams.get('resourceId');
if (!query || !resourceId) {
const cacheTime = getCacheTime();
return NextResponse.json(
{ result: null, error: '缺少必要参数: q 或 resourceId' },
{
headers: {
'Cache-Control': `public, max-age=${cacheTime}`,
},
}
);
}
const apiSites = getAvailableApiSites();
try {
// 根据 resourceId 查找对应的 API 站点
const targetSite = apiSites.find((site) => site.key === resourceId);
if (!targetSite) {
return NextResponse.json(
{
error: `未找到指定的视频源: ${resourceId}`,
result: null,
},
{ status: 404 }
);
}
const results = await searchFromApi(targetSite, query);
const result = results.filter((r) => r.title === query);
const cacheTime = getCacheTime();
if (result.length === 0) {
return NextResponse.json(
{
error: '未找到结果',
result: null,
},
{ status: 404 }
);
} else {
return NextResponse.json(
{ result: result },
{
headers: {
'Cache-Control': `public, max-age=${cacheTime}`,
},
}
);
}
} catch (error) {
return NextResponse.json(
{
error: '搜索失败',
result: null,
},
{ status: 500 }
);
}
}

View File

@@ -0,0 +1,21 @@
import { NextResponse } from 'next/server';
import { getAvailableApiSites, getCacheTime } from '@/lib/config';
export const runtime = 'edge';
// OrionTV 兼容接口
export async function GET() {
try {
const apiSites = getAvailableApiSites();
const cacheTime = getCacheTime();
return NextResponse.json(apiSites, {
headers: {
'Cache-Control': `public, max-age=${cacheTime}`,
},
});
} catch (error) {
return NextResponse.json({ error: '获取资源失败' }, { status: 500 });
}
}

View File

@@ -203,7 +203,6 @@ function DoubanPageClient() {
title={item.title}
poster={item.poster}
rate={item.rate}
type={type || 'movie'}
/>
</div>
))}

View File

@@ -197,7 +197,6 @@ function HomeClient() {
title={movie.title}
poster={movie.poster}
rate={movie.rate}
type='movie'
/>
</div>
))}
@@ -243,7 +242,6 @@ function HomeClient() {
title={show.title}
poster={show.poster}
rate={show.rate}
type='tv'
/>
</div>
))}

View File

@@ -10,7 +10,6 @@ interface DemoCardProps {
title: string;
poster: string;
rate?: string;
type?: string;
}
function PlayCircleSolid({
@@ -42,7 +41,7 @@ function PlayCircleSolid({
);
}
const DemoCard = ({ id, title, poster, rate, type }: DemoCardProps) => {
const DemoCard = ({ id, title, poster, rate }: DemoCardProps) => {
const [hover, setHover] = useState(false);
const [isLoaded, setIsLoaded] = useState(false);
const router = useRouter();
@@ -50,9 +49,7 @@ const DemoCard = ({ id, title, poster, rate, type }: DemoCardProps) => {
const handleClick = () => {
router.push(
`/play?title=${encodeURIComponent(
title.trim()
)}&douban_id=${id}&type=${type}`
`/play?title=${encodeURIComponent(title.trim())}&douban_id=${id}`
);
};