3M/cef_3M/endpoints/mediamtx.py
CEF Server 6a69c5a34d add video streaming endpoints
adjust config for bypassing nginx
add communication to ergo
add cachebusting + fixing icons
2024-07-13 00:31:43 +00:00

95 lines
3.1 KiB
Python

from starlette.responses import JSONResponse
from . import router
from fastapi import Request, Depends
from ..auth import decodeJWT, JWTBearer
from ..util import redis, ergo
def pathParts(path):
if len(path) == 2:
channel = None
user, token = path
elif len(path) == 3:
channel, user, token = path
channel = "#" + channel
else:
return None, None, None
return channel, user, token
@router.get("/mediamtx/streams/{channel}", dependencies=[Depends(JWTBearer())])
async def mediamtxChannelStreams(request: Request, channel: str):
inChannel = request.state.jwt.get("channel", "").lower() == "#" + channel.lower()
results = []
for result in redis.scan_iter(f"stream #{channel} *"):
_, channel, user, token = result.decode("utf8").split()
if inChannel or token == "public":
results.append({
"user": user,
"token": token
})
return JSONResponse(status_code=200, content=results)
@router.post("/mediamtx/auth", include_in_schema=False)
async def mediamtxAuth(request: Request):
if request.client.host != "127.0.0.1":
return False
body = await request.json()
jwt = decodeJWT(body["query"][4:])
path = body["path"].split("/")
reading = body["action"] == "read"
channel, user, token = pathParts(path)
if user is None:
return JSONResponse(status_code=400, content={"error": "bad path"})
if " " in token:
return JSONResponse(status_code=400, content={"error": "bad token"})
# the only time we don't care about JWT is if someone is watching a public stream
if reading and token == "public":
return JSONResponse(status_code=200, content={"success": True})
if len(jwt.keys()) == 0:
return JSONResponse(status_code=403, content={"error": "bad jwt"})
# TODO: channel stream permissions
# publishing
if not reading:
if user != jwt["account"]:
return JSONResponse(status_code=403, content={"error": "nuh uh"})
if channel and jwt["channel"] != channel:
return JSONResponse(status_code=403, content={"error": "nuh uh"})
return JSONResponse(status_code=200, content={"success": True})
@router.post("/mediamtx/add", include_in_schema=False)
async def mediamtxAdd(request: Request):
if request.client.host != "127.0.0.1":
return False
body = await request.json()
path = body["env"]["MTX_PATH"].split("/")
parts = [x for x in pathParts(path) if x]
redis.set("stream " + " ".join(parts), parts[2])
if len(parts) == 3:
await ergo.broadcastTo(parts[0], "STREAMSTART", parts[0], parts[1], parts[2])
@router.post("/mediamtx/del", include_in_schema=False)
async def mediamtxDelete(request: Request):
if request.client.host != "127.0.0.1":
return False
body = await request.json()
path = body["env"]["MTX_PATH"].split("/")
parts = [x for x in pathParts(path) if x]
redis.delete("stream " + " ".join(parts))
if len(parts) == 3:
await ergo.broadcastTo(parts[0], "STREAMEND", parts[0], parts[1], parts[2])