feat: normalize domestic platform semantics
This commit is contained in:
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user