feat: normalize domestic platform semantics

This commit is contained in:
kris
2026-03-23 08:49:32 +08:00
parent caf51bc293
commit 70e4652996

View File

@@ -167,7 +167,7 @@ class AssistantUpdateRequest(BaseModel):
class GenerateCopyRequest(BaseModel):
brief: str
platform: str = "抖音"
platform: str = "douyin"
audience: str = "创业者"
extra_requirements: str = ""
knowledge_base_ids: list[str] = Field(default_factory=list)
@@ -1064,6 +1064,53 @@ def fallback_transcript_from_text(title: str, content: str) -> str:
return f"标题:{title}\n\n正文:\n{content.strip()}"
DOMESTIC_PLATFORMS = {"douyin", "xiaohongshu", "bilibili", "kuaishou", "wechat_video"}
PLATFORM_ALIASES = {
"抖音": "douyin",
"douyin": "douyin",
"小红书": "xiaohongshu",
"xiaohongshu": "xiaohongshu",
"哔哩哔哩": "bilibili",
"b站": "bilibili",
"bilibili": "bilibili",
"快手": "kuaishou",
"kuaishou": "kuaishou",
"微信视频号": "wechat_video",
"视频号": "wechat_video",
"wechat_video": "wechat_video",
"youtube": "youtube",
}
PLATFORM_LABELS = {
"douyin": "抖音",
"xiaohongshu": "小红书",
"bilibili": "哔哩哔哩",
"kuaishou": "快手",
"wechat_video": "微信视频号",
}
def normalize_platform_slug(value: str | None, *, allow_blank: bool = True) -> str:
normalized = str(value or "").strip().lower()
if not normalized:
return "" if allow_blank else "douyin"
normalized = PLATFORM_ALIASES.get(normalized, normalized)
return normalized
def ensure_domestic_platform(value: str | None, *, allow_blank: bool = True) -> str:
normalized = normalize_platform_slug(value, allow_blank=allow_blank)
if not normalized:
return ""
if normalized not in DOMESTIC_PLATFORMS:
raise HTTPException(status_code=400, detail=f"Unsupported platform for domestic build: {value}")
return normalized
def platform_label(platform: str | None) -> str:
normalized = normalize_platform_slug(platform, allow_blank=True)
return PLATFORM_LABELS.get(normalized, normalized or "抖音")
def infer_platform_from_url(source_url: str) -> str:
normalized = source_url.strip().lower()
if "bilibili.com" in normalized or "b23.tv" in normalized:
@@ -1080,8 +1127,6 @@ def infer_platform_from_url(source_url: str) -> str:
return "kuaishou"
if "channels.weixin.qq.com" in normalized or "mp.weixin.qq.com/s" in normalized:
return "wechat_video"
if "youtube.com" in normalized or "youtu.be" in normalized:
return "youtube"
return ""
@@ -1883,6 +1928,8 @@ def dashboard(account: dict[str, Any] = Depends(require_approved)) -> dict[str,
"assistants": assistants,
"recent_jobs": jobs,
"model_profiles": model_profiles,
"supported_platforms": sorted(DOMESTIC_PLATFORMS),
"domestic_build": True,
}
@@ -1916,27 +1963,35 @@ def create_project(request: ProjectCreateRequest, account: dict[str, Any] = Depe
@app.get("/v2/content-sources")
def list_content_sources(
project_id: str | None = Query(default=None),
platform: str | None = Query(default=None),
account: dict[str, Any] = Depends(require_approved),
) -> list[dict[str, Any]]:
normalized_platform = ensure_domestic_platform(platform, allow_blank=True)
clauses = ["user_id = ?"]
params: list[Any] = [account["id"]]
if project_id:
resolve_target_project(account["id"], project_id, username=account["username"])
rows = db.fetch_all(
"SELECT * FROM content_sources WHERE user_id = ? AND project_id = ? ORDER BY created_at DESC",
(account["id"], project_id),
)
else:
rows = db.fetch_all("SELECT * FROM content_sources WHERE user_id = ? ORDER BY created_at DESC", (account["id"],))
clauses.append("project_id = ?")
params.append(project_id)
if normalized_platform:
clauses.append("platform = ?")
params.append(normalized_platform)
rows = db.fetch_all(
f"SELECT * FROM content_sources WHERE {' AND '.join(clauses)} ORDER BY created_at DESC",
tuple(params),
)
return [content_source_payload(row) for row in rows]
@app.post("/v2/content-sources")
def create_content_source_api(request: ContentSourceCreateRequest, account: dict[str, Any] = Depends(require_approved)) -> dict[str, Any]:
project = resolve_target_project(account["id"], request.project_id or None, username=account["username"])
normalized_platform = ensure_domestic_platform(request.platform or infer_platform_from_url(request.source_url), allow_blank=True)
row = create_content_source(
account_id=account["id"],
project_id=project["id"],
source_kind=request.source_kind.strip(),
platform=request.platform.strip(),
platform=normalized_platform,
handle=request.handle.strip(),
source_url=request.source_url.strip(),
title=request.title.strip(),
@@ -1964,7 +2019,10 @@ async def create_content_source_sync_job(
source_url = (request.source_url or (source_row or {}).get("source_url") or "").strip()
if not source_url:
raise HTTPException(status_code=400, detail="source_url or content_source_id is required")
platform = (request.platform or (source_row or {}).get("platform") or infer_platform_from_url(source_url)).strip()
platform = ensure_domestic_platform(
request.platform or (source_row or {}).get("platform") or infer_platform_from_url(source_url),
allow_blank=False,
)
handle = (request.handle or (source_row or {}).get("handle") or "").strip()
source_title = (
request.title.strip()
@@ -2133,6 +2191,7 @@ def create_review(request: ReviewCreateRequest, account: dict[str, Any] = Depend
if not title:
title = f"{project['name']} 复盘"
timestamp = utc_now()
normalized_platform = ensure_domestic_platform(request.platform, allow_blank=False)
db.execute(
"""
INSERT INTO publish_reviews (
@@ -2148,7 +2207,7 @@ def create_review(request: ReviewCreateRequest, account: dict[str, Any] = Depend
source_job["id"] if source_job else None,
(assistant or {}).get("id") or None,
title,
request.platform or "douyin",
normalized_platform or "douyin",
request.content_type or "video",
request.publish_url.strip(),
request.published_at.strip(),
@@ -2172,6 +2231,11 @@ def update_review(review_id: str, request: ReviewUpdateRequest, account: dict[st
if request.assistant_id is not None:
assistant = resolve_target_assistant(account["id"], request.assistant_id or None, current.get("project_id", ""))
assistant_id = (assistant or {}).get("id") or None
normalized_platform = (
ensure_domestic_platform(request.platform, allow_blank=False)
if request.platform is not None
else current.get("platform", "douyin")
)
db.execute(
"""
UPDATE publish_reviews
@@ -2182,7 +2246,7 @@ def update_review(review_id: str, request: ReviewUpdateRequest, account: dict[st
""",
(
request.title if request.title is not None else current.get("title", ""),
request.platform if request.platform is not None else current.get("platform", "douyin"),
normalized_platform,
request.content_type if request.content_type is not None else current.get("content_type", "video"),
request.publish_url if request.publish_url is not None else current.get("publish_url", ""),
request.published_at if request.published_at is not None else current.get("published_at", ""),
@@ -2599,10 +2663,11 @@ async def generate_copy(assistant_id: str, request: GenerateCopyRequest, account
prompt_excerpt = "\n\n".join(excerpts)[:6000]
system_prompt = assistant.get("system_prompt") or "你是文案助手。"
generation_goal = assistant.get("generation_goal") or "生成短视频文案。"
normalized_platform = ensure_domestic_platform(request.platform, allow_blank=False)
user_prompt = (
f"任务目标:{generation_goal}\n"
f"创作需求:{request.brief}\n"
f"平台:{request.platform}\n"
f"平台:{platform_label(normalized_platform)}\n"
f"受众:{request.audience}\n"
f"额外要求:{request.extra_requirements or ''}\n\n"
f"参考知识库素材:\n{prompt_excerpt or '暂无参考素材,请按通用短视频结构输出。'}\n\n"