Repo init
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
import { NextResponse } from "next/server"
|
||||
import { getStream } from "@/lib/db"
|
||||
import { startStream, stopStream, restartStream } from "@/lib/supervisor"
|
||||
|
||||
type Ctx = { params: Promise<{ id: string; action: string }> }
|
||||
|
||||
export async function POST(_req: Request, { params }: Ctx) {
|
||||
const { id, action } = await params
|
||||
|
||||
if (!getStream(id)) return NextResponse.json({ error: "não encontrado" }, { status: 404 })
|
||||
|
||||
switch (action) {
|
||||
case "start": startStream(id); break
|
||||
case "stop": stopStream(id); break
|
||||
case "restart": restartStream(id); break
|
||||
default:
|
||||
return NextResponse.json({ error: "ação inválida" }, { status: 400 })
|
||||
}
|
||||
|
||||
return NextResponse.json({ ok: true })
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { NextResponse } from "next/server"
|
||||
import { getStream, saveStream, deleteStream } from "@/lib/db"
|
||||
import { provisionStream, restartStream, removeStream } from "@/lib/supervisor"
|
||||
import type { StreamUpdate } from "@/types/stream"
|
||||
|
||||
type Ctx = { params: Promise<{ id: string }> }
|
||||
|
||||
export async function GET(_req: Request, { params }: Ctx) {
|
||||
const { id } = await params
|
||||
const stream = getStream(id)
|
||||
if (!stream) return NextResponse.json({ error: "não encontrado" }, { status: 404 })
|
||||
return NextResponse.json(stream)
|
||||
}
|
||||
|
||||
export async function PATCH(req: Request, { params }: Ctx) {
|
||||
const { id } = await params
|
||||
const stream = getStream(id)
|
||||
if (!stream) return NextResponse.json({ error: "não encontrado" }, { status: 404 })
|
||||
|
||||
const body = (await req.json()) as StreamUpdate
|
||||
// id e portas não podem ser alterados via PATCH
|
||||
const { id: _id, ...safe } = body as StreamUpdate & { id?: string }
|
||||
void _id
|
||||
|
||||
const updated = { ...stream, ...safe, updatedAt: new Date().toISOString() }
|
||||
saveStream(updated)
|
||||
provisionStream(updated)
|
||||
restartStream(id)
|
||||
|
||||
return NextResponse.json(updated)
|
||||
}
|
||||
|
||||
export async function DELETE(_req: Request, { params }: Ctx) {
|
||||
const { id } = await params
|
||||
if (!getStream(id)) return NextResponse.json({ error: "não encontrado" }, { status: 404 })
|
||||
|
||||
removeStream(id)
|
||||
deleteStream(id)
|
||||
|
||||
return NextResponse.json({ ok: true })
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { NextResponse } from "next/server"
|
||||
import { getStream } from "@/lib/db"
|
||||
import { getStreamStatus } from "@/lib/supervisor"
|
||||
|
||||
type Ctx = { params: Promise<{ id: string }> }
|
||||
|
||||
export async function GET(_req: Request, { params }: Ctx) {
|
||||
const { id } = await params
|
||||
if (!getStream(id)) return NextResponse.json({ error: "não encontrado" }, { status: 404 })
|
||||
return NextResponse.json(getStreamStatus(id))
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { readStreams } from "@/lib/db"
|
||||
|
||||
export async function GET(req: Request) {
|
||||
const { searchParams } = new URL(req.url)
|
||||
const host = searchParams.get("host") ?? "localhost"
|
||||
const port = searchParams.get("port") ?? "8888"
|
||||
|
||||
const streams = readStreams()
|
||||
|
||||
const lines = ["#EXTM3U"]
|
||||
for (const s of streams) {
|
||||
lines.push(`#EXTINF:-1,${s.name}`)
|
||||
lines.push(`http://${host}:${port}/live/${s.id}/index.m3u8`)
|
||||
}
|
||||
|
||||
return new Response(lines.join("\n"), {
|
||||
headers: {
|
||||
"Content-Type": "application/x-mpegurl",
|
||||
"Content-Disposition": 'attachment; filename="decap-stream.m3u"',
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { NextResponse } from "next/server"
|
||||
import { readStreams, saveStream, allocatePorts, getStream } from "@/lib/db"
|
||||
import { provisionStream, startStream } from "@/lib/supervisor"
|
||||
import { STREAM_DEFAULTS, type StreamCreate } from "@/types/stream"
|
||||
|
||||
export async function GET() {
|
||||
return NextResponse.json(readStreams())
|
||||
}
|
||||
|
||||
const SLUG_RE = /^[a-z0-9-]+$/
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const body = (await req.json()) as StreamCreate
|
||||
|
||||
if (!body.id || !SLUG_RE.test(body.id))
|
||||
return NextResponse.json({ error: "id inválido: use apenas letras minúsculas, números e hífen" }, { status: 400 })
|
||||
|
||||
if (!body.name || !body.url)
|
||||
return NextResponse.json({ error: "name e url são obrigatórios" }, { status: 400 })
|
||||
|
||||
if (getStream(body.id))
|
||||
return NextResponse.json({ error: "já existe uma stream com esse id" }, { status: 409 })
|
||||
|
||||
const ports = allocatePorts()
|
||||
const now = new Date().toISOString()
|
||||
|
||||
const stream = {
|
||||
...STREAM_DEFAULTS,
|
||||
...body,
|
||||
...ports,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
}
|
||||
|
||||
saveStream(stream)
|
||||
provisionStream(stream)
|
||||
startStream(stream.id)
|
||||
|
||||
return NextResponse.json(stream, { status: 201 })
|
||||
}
|
||||
Reference in New Issue
Block a user