mirror of
https://github.com/KuekHaoYang/KVideo.git
synced 2026-08-22 04:03:42 +08:00
feat: Implement IPTV functionality with channel management and player, and add admin account configuration generation.
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Accounts API Route
|
||||
* Returns account list (names + roles, no passwords) for admin visibility
|
||||
*/
|
||||
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
export const runtime = 'edge';
|
||||
|
||||
const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD || '';
|
||||
const ACCESS_PASSWORD = process.env.ACCESS_PASSWORD || '';
|
||||
const ACCOUNTS = process.env.ACCOUNTS || '';
|
||||
|
||||
const effectiveAdminPassword = ADMIN_PASSWORD || ACCESS_PASSWORD;
|
||||
|
||||
interface AccountInfo {
|
||||
name: string;
|
||||
role: 'admin' | 'viewer';
|
||||
}
|
||||
|
||||
function getAccountList(): AccountInfo[] {
|
||||
const accounts: AccountInfo[] = [];
|
||||
|
||||
// Add admin from ADMIN_PASSWORD
|
||||
if (effectiveAdminPassword) {
|
||||
accounts.push({ name: '管理员', role: 'admin' });
|
||||
}
|
||||
|
||||
// Add accounts from ACCOUNTS env var
|
||||
if (ACCOUNTS) {
|
||||
ACCOUNTS.split(',')
|
||||
.map(entry => entry.trim())
|
||||
.filter(entry => entry.length > 0)
|
||||
.forEach(entry => {
|
||||
const parts = entry.split(':');
|
||||
if (parts.length >= 2) {
|
||||
const name = parts[1].trim();
|
||||
const role = parts[2]?.trim() === 'admin' ? 'admin' : 'viewer';
|
||||
if (name) {
|
||||
accounts.push({ name, role });
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return accounts;
|
||||
}
|
||||
|
||||
export async function GET() {
|
||||
const accounts = getAccountList();
|
||||
|
||||
return NextResponse.json({
|
||||
accounts,
|
||||
hasAdminPassword: !!effectiveAdminPassword,
|
||||
hasAccounts: !!ACCOUNTS,
|
||||
totalCount: accounts.length,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* IPTV Proxy API Route
|
||||
* Fetches M3U playlist files to avoid CORS issues
|
||||
*/
|
||||
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
export const runtime = 'edge';
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
const url = request.nextUrl.searchParams.get('url');
|
||||
|
||||
if (!url) {
|
||||
return NextResponse.json({ error: 'Missing url parameter' }, { status: 400 });
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
headers: {
|
||||
'User-Agent': 'Mozilla/5.0 (compatible; KVideo/1.0)',
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
return NextResponse.json(
|
||||
{ error: `Failed to fetch: ${response.status}` },
|
||||
{ status: response.status }
|
||||
);
|
||||
}
|
||||
|
||||
const text = await response.text();
|
||||
|
||||
return new NextResponse(text, {
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Type': 'text/plain; charset=utf-8',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Cache-Control': 'public, max-age=300', // Cache for 5 minutes
|
||||
},
|
||||
});
|
||||
} catch (e) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Failed to fetch M3U playlist' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user