's'
This commit is contained in:
105
web2.py
105
web2.py
@@ -4,6 +4,7 @@ from pathlib import Path
|
||||
import asyncio
|
||||
import html
|
||||
import os
|
||||
from contextlib import asynccontextmanager
|
||||
from typing import Optional
|
||||
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
@@ -26,8 +27,27 @@ from web2_youtube_oauth import (
|
||||
oauth_status as youtube_oauth_status_snapshot,
|
||||
)
|
||||
from web2_wechat_chatbot import register_wechat_chatbot_routes
|
||||
from web2_client_overview import build_client_overview
|
||||
from web2_relay_pro import (
|
||||
build_relay_live_status,
|
||||
ensure_default_relay_config,
|
||||
first_youtube_pm2_name,
|
||||
get_channel_detail,
|
||||
list_channels_for_pro,
|
||||
read_url_config_for_channel,
|
||||
sync_channel_to_legacy_files,
|
||||
update_channel_key,
|
||||
write_url_config_for_channel,
|
||||
)
|
||||
|
||||
app = FastAPI(title="多进程录制控制台")
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
ensure_default_relay_config(CONFIG_DIR)
|
||||
yield
|
||||
|
||||
|
||||
app = FastAPI(title="多进程录制控制台", lifespan=lifespan)
|
||||
|
||||
# ---------------- 配置(根目录结构) ----------------
|
||||
BASE_DIR = Path(__file__).parent
|
||||
@@ -187,6 +207,89 @@ app.add_middleware(
|
||||
|
||||
register_wechat_chatbot_routes(app, BASE_DIR)
|
||||
|
||||
|
||||
@app.get("/client/overview")
|
||||
async def client_overview():
|
||||
"""Electron 工作台:频道列表、微信摘要(EasyTier 节点由主进程 easytier-cli 查询)。"""
|
||||
return build_client_overview(CONFIG_DIR, BASE_DIR)
|
||||
|
||||
|
||||
# ---------------- Pro 多路转播(每频道独立 URL 文件 + 去重 + 同步 legacy) ----------------
|
||||
|
||||
|
||||
@app.get("/relay_pro/channels")
|
||||
async def relay_pro_channels():
|
||||
return list_channels_for_pro(CONFIG_DIR)
|
||||
|
||||
|
||||
@app.get("/relay_pro/channel_detail")
|
||||
async def relay_pro_channel_detail(channel_id: str = Query(..., description="频道 id,如 ch_0")):
|
||||
d = get_channel_detail(CONFIG_DIR, channel_id)
|
||||
if not d:
|
||||
return JSONResponse({"error": "未找到频道"}, status_code=404)
|
||||
return d
|
||||
|
||||
|
||||
@app.get("/relay_pro/url_config")
|
||||
async def relay_pro_get_url_config(channel_id: str = Query(...)):
|
||||
return {"content": read_url_config_for_channel(CONFIG_DIR, channel_id)}
|
||||
|
||||
|
||||
@app.post("/relay_pro/url_config")
|
||||
async def relay_pro_post_url_config(request: Request, channel_id: str = Query(...)):
|
||||
try:
|
||||
data = await request.json()
|
||||
except Exception:
|
||||
return JSONResponse({"error": "无效的 JSON"}, status_code=400)
|
||||
content = data.get("content", "") if isinstance(data, dict) else ""
|
||||
ok, msg = write_url_config_for_channel(CONFIG_DIR, channel_id, content)
|
||||
if not ok:
|
||||
return JSONResponse({"error": msg}, status_code=400)
|
||||
return {"message": msg}
|
||||
|
||||
|
||||
@app.post("/relay_pro/channel_key")
|
||||
async def relay_pro_save_channel_key(request: Request):
|
||||
try:
|
||||
data = await request.json()
|
||||
except Exception:
|
||||
return JSONResponse({"error": "无效的 JSON"}, status_code=400)
|
||||
if not isinstance(data, dict):
|
||||
return JSONResponse({"error": "无效数据"}, status_code=400)
|
||||
cid = str(data.get("channelId") or data.get("channel_id") or "").strip()
|
||||
key = str(data.get("youtubeKey") or data.get("key") or "")
|
||||
if not cid:
|
||||
return JSONResponse({"error": "缺少 channelId"}, status_code=400)
|
||||
ok, msg = update_channel_key(CONFIG_DIR, cid, key)
|
||||
if not ok:
|
||||
return JSONResponse({"error": msg}, status_code=400)
|
||||
return {"message": msg}
|
||||
|
||||
|
||||
@app.post("/relay_pro/sync_active")
|
||||
async def relay_pro_sync_active(channel_id: str = Query(...)):
|
||||
ok, msg = sync_channel_to_legacy_files(CONFIG_DIR, channel_id)
|
||||
if not ok:
|
||||
return JSONResponse({"error": msg}, status_code=400)
|
||||
return {"message": msg}
|
||||
|
||||
|
||||
@app.get("/relay_pro/live_status")
|
||||
async def relay_pro_live_status():
|
||||
yt = first_youtube_pm2_name([{"script": e["script"]} for e in SCRIPT_ENTRIES])
|
||||
|
||||
async def read_tail(path: str, lines: int) -> str:
|
||||
return await read_log_path(path, lines)
|
||||
|
||||
return await build_relay_live_status(
|
||||
CONFIG_DIR,
|
||||
BASE_DIR,
|
||||
control_get_process_info,
|
||||
read_tail,
|
||||
yt,
|
||||
)
|
||||
|
||||
|
||||
# ---------------- 工具函数 ----------------
|
||||
async def read_log_path(path: str, lines: int) -> str:
|
||||
if not path:
|
||||
|
||||
Reference in New Issue
Block a user