s
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import configparser
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
@@ -304,6 +305,56 @@ def _sync_youtube_pro_runtime_files(process: str) -> list[str]:
|
||||
return errors
|
||||
|
||||
|
||||
def _normalize_textarea_content(text: str) -> str:
|
||||
return (text or "").replace("\r\n", "\n").replace("\r", "\n").lstrip("\ufeff")
|
||||
|
||||
|
||||
def _extract_stream_key_from_youtube_ini(text: str) -> str:
|
||||
parser = configparser.ConfigParser()
|
||||
try:
|
||||
parser.read_string(_normalize_textarea_content(text) or "[youtube]\n")
|
||||
except (configparser.Error, TypeError, ValueError):
|
||||
return ""
|
||||
if not parser.has_section("youtube"):
|
||||
return ""
|
||||
for key_name in ("key", "stream_key"):
|
||||
value = str(parser.get("youtube", key_name, fallback="") or "").strip()
|
||||
if value and not value.startswith("#"):
|
||||
return value
|
||||
return ""
|
||||
|
||||
|
||||
def _persist_youtube_pro_channel_edits(
|
||||
process: str,
|
||||
*,
|
||||
url_content: str | None = None,
|
||||
youtube_ini_content: str | None = None,
|
||||
) -> bool:
|
||||
channels = get_youtube_pro_channels()
|
||||
if not channels:
|
||||
return False
|
||||
target = (process or "").strip()
|
||||
if not target:
|
||||
return False
|
||||
updated = False
|
||||
next_channels: list[dict[str, Any]] = []
|
||||
for channel in channels:
|
||||
row = dict(channel) if isinstance(channel, dict) else {}
|
||||
if channel_pm2_name(row) != target:
|
||||
next_channels.append(row)
|
||||
continue
|
||||
if url_content is not None:
|
||||
row["urlLines"] = _normalize_textarea_content(url_content)
|
||||
updated = True
|
||||
if youtube_ini_content is not None:
|
||||
row["streamKey"] = _extract_stream_key_from_youtube_ini(youtube_ini_content)
|
||||
updated = True
|
||||
next_channels.append(row)
|
||||
if updated:
|
||||
set_youtube_pro_channels(next_channels)
|
||||
return updated
|
||||
|
||||
|
||||
def _validate_youtube_runtime_files(process: str) -> list[str]:
|
||||
return validate_youtube_runtime_files(BASE_DIR, CONFIG_DIR, process, get_youtube_pro_channels())
|
||||
|
||||
@@ -501,6 +552,12 @@ app.add_middleware(
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
_NO_STORE_HEADERS = {
|
||||
"Cache-Control": "no-store, max-age=0, must-revalidate",
|
||||
"Pragma": "no-cache",
|
||||
"Expires": "0",
|
||||
}
|
||||
|
||||
|
||||
class ProcessNameBody(BaseModel):
|
||||
process: str = Field(..., min_length=1, max_length=160)
|
||||
@@ -1050,22 +1107,21 @@ async def get_config(process: str = Query(..., description="进程名")):
|
||||
{"error": "仅 YouTube / 抖音→YouTube 类脚本支持 youtube.ini 编辑"}, status_code=400
|
||||
)
|
||||
|
||||
sync_errors = _sync_youtube_pro_runtime_files(process)
|
||||
if sync_errors:
|
||||
return JSONResponse({"error": "; ".join(sync_errors)}, status_code=400)
|
||||
|
||||
config_file = CONFIG_DIR / rel
|
||||
if not config_file.is_file():
|
||||
sync_errors = _sync_youtube_pro_runtime_files(process)
|
||||
if sync_errors:
|
||||
return JSONResponse({"error": "; ".join(sync_errors)}, status_code=400)
|
||||
legacy = CONFIG_DIR / "youtube.ini"
|
||||
if legacy.is_file():
|
||||
try:
|
||||
return {"content": legacy.read_text(encoding="utf-8")}
|
||||
return JSONResponse({"content": legacy.read_text(encoding="utf-8")}, headers=_NO_STORE_HEADERS)
|
||||
except OSError as e:
|
||||
return JSONResponse({"error": f"读取失败: {str(e)}"}, status_code=500)
|
||||
return {"content": f"# {rel} 尚未创建,保存后将写入磁盘\n"}
|
||||
return JSONResponse({"content": f"# {rel} 尚未创建,保存后将写入磁盘\n"}, headers=_NO_STORE_HEADERS)
|
||||
try:
|
||||
content = config_file.read_text(encoding="utf-8")
|
||||
return {"content": content}
|
||||
return JSONResponse({"content": content}, headers=_NO_STORE_HEADERS)
|
||||
except OSError as e:
|
||||
return JSONResponse({"error": f"读取失败: {str(e)}"}, status_code=500)
|
||||
|
||||
@@ -1086,7 +1142,8 @@ async def save_config(request: Request, process: str = Query(..., description="
|
||||
|
||||
try:
|
||||
governed_save_managed_file("app-config", rel, content)
|
||||
return {"message": "配置保存成功"}
|
||||
_persist_youtube_pro_channel_edits(process, youtube_ini_content=content)
|
||||
return JSONResponse({"message": "配置保存成功"}, headers=_NO_STORE_HEADERS)
|
||||
except OSError as e:
|
||||
return JSONResponse({"error": f"保存失败: {str(e)}"}, status_code=500)
|
||||
|
||||
@@ -1100,23 +1157,22 @@ async def get_url_config(process: str = Query(..., description="进程名")):
|
||||
status_code=400,
|
||||
)
|
||||
|
||||
sync_errors = _sync_youtube_pro_runtime_files(process)
|
||||
if sync_errors:
|
||||
return JSONResponse({"error": "; ".join(sync_errors)}, status_code=400)
|
||||
|
||||
rel = managed_url_config_relpath(process)
|
||||
config_file = CONFIG_DIR / rel
|
||||
if not config_file.is_file():
|
||||
sync_errors = _sync_youtube_pro_runtime_files(process)
|
||||
if sync_errors:
|
||||
return JSONResponse({"error": "; ".join(sync_errors)}, status_code=400)
|
||||
legacy = CONFIG_DIR / "URL_config.ini"
|
||||
if legacy.is_file():
|
||||
try:
|
||||
return {"content": legacy.read_text(encoding="utf-8")}
|
||||
return JSONResponse({"content": legacy.read_text(encoding="utf-8")}, headers=_NO_STORE_HEADERS)
|
||||
except OSError as e:
|
||||
return JSONResponse({"error": f"读取失败: {str(e)}"}, status_code=500)
|
||||
return {"content": f"# {rel} 尚未创建,保存后将写入磁盘\n"}
|
||||
return JSONResponse({"content": f"# {rel} 尚未创建,保存后将写入磁盘\n"}, headers=_NO_STORE_HEADERS)
|
||||
try:
|
||||
content = config_file.read_text(encoding="utf-8")
|
||||
return {"content": content}
|
||||
return JSONResponse({"content": content}, headers=_NO_STORE_HEADERS)
|
||||
except OSError as e:
|
||||
return JSONResponse({"error": f"读取失败: {str(e)}"}, status_code=500)
|
||||
|
||||
@@ -1140,7 +1196,8 @@ async def save_url_config(request: Request, process: str = Query(..., descriptio
|
||||
try:
|
||||
rel = managed_url_config_relpath(process)
|
||||
governed_save_managed_file("app-config", rel, content)
|
||||
return {"message": "配置保存成功"}
|
||||
_persist_youtube_pro_channel_edits(process, url_content=content)
|
||||
return JSONResponse({"message": "配置保存成功"}, headers=_NO_STORE_HEADERS)
|
||||
except OSError as e:
|
||||
return JSONResponse({"error": f"保存失败: {str(e)}"}, status_code=500)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user