feat: unify account environments and work collection

This commit is contained in:
2026-10-06 13:00:29 +08:00
parent b72727451d
commit 950b23da32
22 changed files with 935 additions and 93 deletions
+32 -1
View File
@@ -744,7 +744,7 @@ def valid_douyin_url(raw: object) -> bool:
if parsed.path == DOUYIN_PROFILE_OTHER_PATH:
return valid_douyin_profile_query(query)
if parsed.path == DOUYIN_WORKS_PATH:
return valid_douyin_api_query(query, "sec_user_id", "max_cursor")
return valid_douyin_works_query(query)
if parsed.path == DOUYIN_WORK_DETAIL_PATH:
return valid_douyin_work_detail_query(query)
if parsed.path == DOUYIN_COMMENTS_PATH:
@@ -773,6 +773,37 @@ def valid_douyin_profile_query(query: dict[str, list[str]]) -> bool:
)
def valid_douyin_works_query(query: dict[str, list[str]]) -> bool:
# Keep the works endpoint pinned to the parameters used by Douyin's web
# profile page; do not let the pagination fix widen the restricted URL surface.
rest = query
if "a_bogus" in query:
if len(query["a_bogus"]) != 1 or not DOUYIN_SIGNATURE_RE.fullmatch(
query["a_bogus"][0]
):
return False
rest = {key: value for key, value in query.items() if key != "a_bogus"}
required = {
"aid": ["6383"],
"device_platform": ["webapp"],
"channel": ["channel_pc_web"],
"count": ["18"],
"locate_query": ["false"],
"show_live_replay_strategy": ["1"],
"need_time_list": ["1"],
"time_list_query": ["0"],
"cut_version": ["1"],
"publish_video_strategy_type": ["2"],
"from_user_page": ["0"],
}
return (
set(rest) == set(required) | {"sec_user_id", "max_cursor"}
and all(rest.get(key) == value for key, value in required.items())
and valid_account_key_query(rest, "sec_user_id")
and numeric_cursor(rest.get("max_cursor"))
)
def valid_douyin_api_query(
query: dict[str, list[str]], account_field: str, cursor_field: str
) -> bool:
+13
View File
@@ -198,6 +198,19 @@ class GatewayValidationTests(unittest.TestCase):
"https://www.douyin.com/aweme/v1/web/user/profile/other/?aid=6383&device_platform=webapp&user_id=1&count=20"
)
)
works_url = (
"https://www.douyin.com/aweme/v1/web/aweme/post/?"
"aid=6383&device_platform=webapp&channel=channel_pc_web&"
"sec_user_id=MS4wLjABAAAA9f_a7k0bzVizLYXlpC7R61EIaqJ8Ordug7yp7AB8fGKuuF8Fzqk5_DM-eutXnPIK&"
"count=18&max_cursor=1746702477000&locate_query=false&"
"show_live_replay_strategy=1&need_time_list=1&time_list_query=0&"
"cut_version=1&publish_video_strategy_type=2&from_user_page=0"
)
self.assertTrue(valid_douyin_url(works_url))
self.assertTrue(valid_douyin_url(works_url + "&a_bogus=abcdefghijklmnop"))
self.assertFalse(valid_douyin_url(works_url + "&unexpected=1"))
self.assertFalse(valid_douyin_url(works_url.replace("count=18", "count=20")))
self.assertFalse(valid_douyin_url(works_url.replace("max_cursor=1746702477000", "max_cursor=-1")))
self.assertFalse(valid_douyin_url("https://www.douyin.com.evil/"))
self.assertTrue(is_douyin_url("https://www.douyin.com/video/123"))
self.assertFalse(is_douyin_url("https://www.douyin.com.evil/video/123"))