Initial Qinglong script classification corpus
This commit is contained in:
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
# runtime/cache
|
||||
metadata/collector_cache.json
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# keep generated indexes and scripts tracked
|
||||
25
INDEX.csv
Normal file
25
INDEX.csv
Normal file
@@ -0,0 +1,25 @@
|
||||
category,project,filename,sha256,source_platform,source_repo,source_path,source_url,raw_url,uploaded_at,saved_path,auth_type,platform_type,evidence
|
||||
APP版/抓包,content,2026-05-19_content_45c4e352.js,45c4e3523ff88ee080e76c2c8b635c4a14657f9f97fa395d368b9bccf09b4bca,GitHub,huwangkeji/juejin_checkin,juejin-extension/content.js,https://github.com/huwangkeji/juejin_checkin/blob/main/juejin-extension/content.js,https://raw.githubusercontent.com/huwangkeji/juejin_checkin/main/juejin-extension/content.js,2026-05-19T14:34:11Z,脚本库/APP版/抓包/content/2026-05-19_content_45c4e352.js,抓包,APP版,cookie/token/authorization/header
|
||||
web版/抓包,"'Cookie',_env_'JUEJIN_COOKIE',_isLong_true_},",2026-05-19_popup_0a4d4983.js,0a4d49831a306fa984f62b0d1b3f26f7fc1274a625d08b5f4622ba94121b8469,GitHub,huwangkeji/juejin_checkin,juejin-extension/popup.js,https://github.com/huwangkeji/juejin_checkin/blob/main/juejin-extension/popup.js,https://raw.githubusercontent.com/huwangkeji/juejin_checkin/main/juejin-extension/popup.js,2026-05-19T14:34:11Z,"脚本库/web版/抓包/'Cookie',_env_'JUEJIN_COOKIE',_isLong_true_},/2026-05-19_popup_0a4d4983.js",抓包,web版,web/H5关键词 + cookie/token/header
|
||||
web版/抓包,B站签到,2025-01-11_bilibili_906ceaaa.js,906ceaaa11d344b7ecc1697e5f028c2999adb32569f3f9fca4feb951f86d3f46,GitHub,lksky8/sign-ql,invalid/bilibili.js,https://github.com/lksky8/sign-ql/blob/main/invalid/bilibili.js,https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/bilibili.js,2025-01-11T18:49:38Z,脚本库/web版/抓包/B站签到/2025-01-11_bilibili_906ceaaa.js,抓包,web版,web/H5关键词 + cookie/token/header
|
||||
web版/抓包,notify,2025-01-11_notify_9961f576.py,9961f57695cfba609fbfda0c314ab632f147c0d068b0f0338eaaa1ef796eedf8,GitHub,lksky8/sign-ql,notify.py,https://github.com/lksky8/sign-ql/blob/main/notify.py,https://raw.githubusercontent.com/lksky8/sign-ql/main/notify.py,2025-01-11T18:39:35Z,脚本库/web版/抓包/notify/2025-01-11_notify_9961f576.py,抓包,web版,web/H5关键词 + cookie/token/header
|
||||
web版/抓包,query,2026-05-11_ks_query_848504df.py,848504df99018b6b2f9d7bac940671dc65777b8d973c1610e2a3111c88d36480,GitHub,DearSong15/ql-scripts,ks_query.py,https://github.com/DearSong15/ql-scripts/blob/main/ks_query.py,https://raw.githubusercontent.com/DearSong15/ql-scripts/main/ks_query.py,2026-05-11T14:51:55Z,脚本库/web版/抓包/query/2026-05-11_ks_query_848504df.py,抓包,web版,web/H5关键词 + cookie/token/header
|
||||
web版/抓包,券妈妈时段奖励,2025-01-11_qmm_868f2cd3.js,868f2cd3002df5797fe7ad064612d6e5bc4b97d168092281a6390b7219643743,GitHub,lksky8/sign-ql,invalid/qmm.js,https://github.com/lksky8/sign-ql/blob/main/invalid/qmm.js,https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/qmm.js,2025-01-11T18:42:58Z,脚本库/web版/抓包/券妈妈时段奖励/2025-01-11_qmm_868f2cd3.js,抓包,web版,web/H5关键词 + cookie/token/header
|
||||
web版/账密,"'未知用户',",2026-05-19_juejin_checkin_6f8a138b.js,6f8a138b51c397220444c9312040dbe3407af5aeed4fa4467a36672aeb8bcfd1,GitHub,huwangkeji/juejin_checkin,juejin_checkin.js,https://github.com/huwangkeji/juejin_checkin/blob/main/juejin_checkin.js,https://raw.githubusercontent.com/huwangkeji/juejin_checkin/main/juejin_checkin.js,2026-05-19T14:34:11Z,"脚本库/web版/账密/'未知用户',/2026-05-19_juejin_checkin_6f8a138b.js",账密,web版,web/H5关键词 + username/password/login
|
||||
web版/账密,apply_link.split'id='-1},2026-03-27_3dmgame_2262c9f7.py,2262c9f7c2d40c8ef9822325fadd2e8ed3c43ba0f609c072a27c49b02edc2eaa,GitHub,lksky8/sign-ql,3dmgame.py,https://github.com/lksky8/sign-ql/blob/main/3dmgame.py,https://raw.githubusercontent.com/lksky8/sign-ql/main/3dmgame.py,2026-03-27T20:17:30Z,脚本库/web版/账密/apply_link.split'id='-1}/2026-03-27_3dmgame_2262c9f7.py,账密,web版,web/H5关键词 + username/password/login
|
||||
web版/账密,"str,_token_str",2025-09-22_PPark_120e7330.py,120e73308bc1ccfb9db8ebd87357364850257a25ba1bc039d67c2967fe6c8e19,GitHub,lksky8/sign-ql,PPark.py,https://github.com/lksky8/sign-ql/blob/main/PPark.py,https://raw.githubusercontent.com/lksky8/sign-ql/main/PPark.py,2025-09-22T11:01:17Z,"脚本库/web版/账密/str,_token_str/2025-09-22_PPark_120e7330.py",账密,web版,web/H5关键词 + username/password/login
|
||||
web版/账密,tyqh,2026-05-23_tyqh_4c779933.py,4c779933563a21d73534721d588cf8fd5aa9e6d6ced3e3b3bb414c91fb576708,GitHub,lksky8/sign-ql,invalid/tyqh.py,https://github.com/lksky8/sign-ql/blob/main/invalid/tyqh.py,https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/tyqh.py,2026-05-23T06:33:20Z,脚本库/web版/账密/tyqh/2026-05-23_tyqh_4c779933.py,账密,web版,web/H5关键词 + username/password/login
|
||||
web版/账密,"url.hostname,",2026-05-11_zsp_video_960b2e28.js,960b2e28799c40a00eb4bd75dcda1e61b3ab747374716073995c75053c3083ee,GitHub,DearSong15/ql-scripts,zsp_video.js,https://github.com/DearSong15/ql-scripts/blob/main/zsp_video.js,https://raw.githubusercontent.com/DearSong15/ql-scripts/main/zsp_video.js,2026-05-11T15:03:30Z,"脚本库/web版/账密/url.hostname,/2026-05-11_zsp_video_960b2e28.js",账密,web版,web/H5关键词 + username/password/login
|
||||
web版/账密,yxw_appsign,2025-09-28_yxw_appsign_c6d91db1.py,c6d91db16e3a84bf5dfc1e2c7d6cb38fb3f6d38f5829d7f496ba308fa7a77a10,GitHub,lksky8/sign-ql,yxw_appsign.py,https://github.com/lksky8/sign-ql/blob/main/yxw_appsign.py,https://raw.githubusercontent.com/lksky8/sign-ql/main/yxw_appsign.py,2025-09-28T06:42:50Z,脚本库/web版/账密/yxw_appsign/2025-09-28_yxw_appsign_c6d91db1.py,账密,web版,web/H5关键词 + username/password/login
|
||||
web版/账密,yxw_luckbox,2025-08-21_yxw_luckbox_79511924.py,7951192443b96cec1fe801de769343a2e080be439b46c9b2bfb4372a4cdfe2e1,GitHub,lksky8/sign-ql,yxw_luckbox.py,https://github.com/lksky8/sign-ql/blob/main/yxw_luckbox.py,https://raw.githubusercontent.com/lksky8/sign-ql/main/yxw_luckbox.py,2025-08-21T12:12:12Z,脚本库/web版/账密/yxw_luckbox/2025-08-21_yxw_luckbox_79511924.py,账密,web版,web/H5关键词 + username/password/login
|
||||
web版/账密,中石化加油广东APP签到,2022-07-24_jygd_47493387.js,474933874ed61cd8ebd4efed3ee26778f4e3d0290ba16222f9feed61bafb6838,GitHub,lksky8/sign-ql,invalid/jygd.js,https://github.com/lksky8/sign-ql/blob/main/invalid/jygd.js,https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/jygd.js,2022-07-24T02:54:25Z,脚本库/web版/账密/中石化加油广东APP签到/2022-07-24_jygd_47493387.js,账密,web版,web/H5关键词 + username/password/login
|
||||
web版/账密,叮咚买菜,2022-11-17_ddmc_2d78fbea_2.js,2d78fbea0d710c7d29ad02178c603c97586bc9a5843ccd9f92cd18d6b8157c80,GitHub,lksky8/sign-ql,ddmc.js,https://github.com/lksky8/sign-ql/blob/main/ddmc.js,https://raw.githubusercontent.com/lksky8/sign-ql/main/ddmc.js,2022-11-17T13:54:32Z,脚本库/web版/账密/叮咚买菜/2022-11-17_ddmc_2d78fbea_2.js,账密,web版,web/H5关键词 + username/password/login
|
||||
web版/账密,方舟健客签到,2025-12-07_jksign_b722f903.py,b722f903ef41b1cab2540fc2a7b84bb51cb2e8d354783a225e3c364b0799a4e6,GitHub,lksky8/sign-ql,jksign.py,https://github.com/lksky8/sign-ql/blob/main/jksign.py,https://raw.githubusercontent.com/lksky8/sign-ql/main/jksign.py,2025-12-07T17:42:50Z,脚本库/web版/账密/方舟健客签到/2025-12-07_jksign_b722f903.py,账密,web版,web/H5关键词 + username/password/login
|
||||
web版/账密,星星充电签到,2025-09-01_xxcd_40e3aef4.py,40e3aef421127efd0fe80201c786cf341993dd4e8318fe4f8456a912aef026e0,GitHub,lksky8/sign-ql,xxcd.py,https://github.com/lksky8/sign-ql/blob/main/xxcd.py,https://raw.githubusercontent.com/lksky8/sign-ql/main/xxcd.py,2025-09-01T15:45:21Z,脚本库/web版/账密/星星充电签到/2025-09-01_xxcd_40e3aef4.py,账密,web版,web/H5关键词 + username/password/login
|
||||
微信小程序/抓包版,cloud189,2025-09-06_cloud189_7c90c2eb.py,7c90c2eb0032873254db7819a42440cd062ae32af3fa537efc7c295c0e1da804,GitHub,lksky8/sign-ql,cloud189.py,https://github.com/lksky8/sign-ql/blob/main/cloud189.py,https://raw.githubusercontent.com/lksky8/sign-ql/main/cloud189.py,2025-09-06T12:51:46Z,脚本库/微信小程序/抓包版/cloud189/2025-09-06_cloud189_7c90c2eb.py,抓包版,微信小程序,appid/openid/session_key/encryptedData等小程序字段
|
||||
微信小程序/抓包版,jtc,2025-10-26_jtc_d7fa5acd_2.py,d7fa5acdc107ddb45fd772c4bb0c9491fd48e8e3d7d18ae5a4286579151676ef,GitHub,lksky8/sign-ql,jtc.py,https://github.com/lksky8/sign-ql/blob/main/jtc.py,https://raw.githubusercontent.com/lksky8/sign-ql/main/jtc.py,2025-10-26T12:24:47Z,脚本库/微信小程序/抓包版/jtc/2025-10-26_jtc_d7fa5acd_2.py,抓包版,微信小程序,appid/openid/session_key/encryptedData等小程序字段
|
||||
微信小程序/抓包版,快手双端,2026-05-11_ks_dual_aa4fbaa7.js,aa4fbaa74f4c00599fa2a8c1e358c99c6f393dc9b180b7c8260162ddd20b1e0f,GitHub,DearSong15/ql-scripts,ks_dual.js,https://github.com/DearSong15/ql-scripts/blob/main/ks_dual.js,https://raw.githubusercontent.com/DearSong15/ql-scripts/main/ks_dual.js,2026-05-11T15:03:30Z,脚本库/微信小程序/抓包版/快手双端/2026-05-11_ks_dual_aa4fbaa7.js,抓包版,微信小程序,appid/openid/session_key/encryptedData等小程序字段
|
||||
微信小程序/抓包版,滴滴果园,2025-01-11_ddgy_236924d1.js,236924d18d7e9ae58141a6c45bde1b9de748e6e63c8ca805162caf02fb01b362,GitHub,lksky8/sign-ql,invalid/ddgy.js,https://github.com/lksky8/sign-ql/blob/main/invalid/ddgy.js,https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/ddgy.js,2025-01-11T18:50:13Z,脚本库/微信小程序/抓包版/滴滴果园/2025-01-11_ddgy_236924d1.js,抓包版,微信小程序,appid/openid/session_key/encryptedData等小程序字段
|
||||
微信小程序/抓包版,索尼中国,2025-01-11_sonybbs_359e1e49.js,359e1e4984589cd0b5363e39c8ff9a566a54f3b5678cee3540b33ac3a546638a,GitHub,lksky8/sign-ql,invalid/sonybbs.js,https://github.com/lksky8/sign-ql/blob/main/invalid/sonybbs.js,https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/sonybbs.js,2025-01-11T18:47:31Z,脚本库/微信小程序/抓包版/索尼中国/2025-01-11_sonybbs_359e1e49.js,抓包版,微信小程序,appid/openid/session_key/encryptedData等小程序字段
|
||||
微信小程序/抓包版,统一茄皇-修复版,2023-01-03_tyqh_2fe80596.js,2fe8059609f086f32865e2d2463e2e54b532cae84923ca73cb64cf6d5432509c,GitHub,lksky8/sign-ql,invalid/tyqh.js,https://github.com/lksky8/sign-ql/blob/main/invalid/tyqh.js,https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/tyqh.js,2023-01-03T11:39:58Z,脚本库/微信小程序/抓包版/统一茄皇-修复版/2023-01-03_tyqh_2fe80596.js,抓包版,微信小程序,appid/openid/session_key/encryptedData等小程序字段
|
||||
微信小程序/抓包版,统一茄皇互助,2023-01-03_qhhz_07a8e366.js,07a8e366afc33d150d5b2c1d3dde5220e01ffa855b3c568244fe6013a54aae43,GitHub,lksky8/sign-ql,invalid/qhhz.js,https://github.com/lksky8/sign-ql/blob/main/invalid/qhhz.js,https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/qhhz.js,2023-01-03T11:38:28Z,脚本库/微信小程序/抓包版/统一茄皇互助/2023-01-03_qhhz_07a8e366.js,抓包版,微信小程序,appid/openid/session_key/encryptedData等小程序字段
|
||||
|
386
INDEX.json
Normal file
386
INDEX.json
Normal file
@@ -0,0 +1,386 @@
|
||||
[
|
||||
{
|
||||
"category": "APP版/抓包",
|
||||
"project": "content",
|
||||
"filename": "2026-05-19_content_45c4e352.js",
|
||||
"sha256": "45c4e3523ff88ee080e76c2c8b635c4a14657f9f97fa395d368b9bccf09b4bca",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "huwangkeji/juejin_checkin",
|
||||
"source_path": "juejin-extension/content.js",
|
||||
"source_url": "https://github.com/huwangkeji/juejin_checkin/blob/main/juejin-extension/content.js",
|
||||
"raw_url": "https://raw.githubusercontent.com/huwangkeji/juejin_checkin/main/juejin-extension/content.js",
|
||||
"uploaded_at": "2026-05-19T14:34:11Z",
|
||||
"saved_path": "脚本库/APP版/抓包/content/2026-05-19_content_45c4e352.js",
|
||||
"auth_type": "抓包",
|
||||
"platform_type": "APP版",
|
||||
"evidence": "cookie/token/authorization/header"
|
||||
},
|
||||
{
|
||||
"category": "web版/抓包",
|
||||
"project": "'Cookie',_env_'JUEJIN_COOKIE',_isLong_true_},",
|
||||
"filename": "2026-05-19_popup_0a4d4983.js",
|
||||
"sha256": "0a4d49831a306fa984f62b0d1b3f26f7fc1274a625d08b5f4622ba94121b8469",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "huwangkeji/juejin_checkin",
|
||||
"source_path": "juejin-extension/popup.js",
|
||||
"source_url": "https://github.com/huwangkeji/juejin_checkin/blob/main/juejin-extension/popup.js",
|
||||
"raw_url": "https://raw.githubusercontent.com/huwangkeji/juejin_checkin/main/juejin-extension/popup.js",
|
||||
"uploaded_at": "2026-05-19T14:34:11Z",
|
||||
"saved_path": "脚本库/web版/抓包/'Cookie',_env_'JUEJIN_COOKIE',_isLong_true_},/2026-05-19_popup_0a4d4983.js",
|
||||
"auth_type": "抓包",
|
||||
"platform_type": "web版",
|
||||
"evidence": "web/H5关键词 + cookie/token/header"
|
||||
},
|
||||
{
|
||||
"category": "web版/抓包",
|
||||
"project": "B站签到",
|
||||
"filename": "2025-01-11_bilibili_906ceaaa.js",
|
||||
"sha256": "906ceaaa11d344b7ecc1697e5f028c2999adb32569f3f9fca4feb951f86d3f46",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "lksky8/sign-ql",
|
||||
"source_path": "invalid/bilibili.js",
|
||||
"source_url": "https://github.com/lksky8/sign-ql/blob/main/invalid/bilibili.js",
|
||||
"raw_url": "https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/bilibili.js",
|
||||
"uploaded_at": "2025-01-11T18:49:38Z",
|
||||
"saved_path": "脚本库/web版/抓包/B站签到/2025-01-11_bilibili_906ceaaa.js",
|
||||
"auth_type": "抓包",
|
||||
"platform_type": "web版",
|
||||
"evidence": "web/H5关键词 + cookie/token/header"
|
||||
},
|
||||
{
|
||||
"category": "web版/抓包",
|
||||
"project": "notify",
|
||||
"filename": "2025-01-11_notify_9961f576.py",
|
||||
"sha256": "9961f57695cfba609fbfda0c314ab632f147c0d068b0f0338eaaa1ef796eedf8",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "lksky8/sign-ql",
|
||||
"source_path": "notify.py",
|
||||
"source_url": "https://github.com/lksky8/sign-ql/blob/main/notify.py",
|
||||
"raw_url": "https://raw.githubusercontent.com/lksky8/sign-ql/main/notify.py",
|
||||
"uploaded_at": "2025-01-11T18:39:35Z",
|
||||
"saved_path": "脚本库/web版/抓包/notify/2025-01-11_notify_9961f576.py",
|
||||
"auth_type": "抓包",
|
||||
"platform_type": "web版",
|
||||
"evidence": "web/H5关键词 + cookie/token/header"
|
||||
},
|
||||
{
|
||||
"category": "web版/抓包",
|
||||
"project": "query",
|
||||
"filename": "2026-05-11_ks_query_848504df.py",
|
||||
"sha256": "848504df99018b6b2f9d7bac940671dc65777b8d973c1610e2a3111c88d36480",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "DearSong15/ql-scripts",
|
||||
"source_path": "ks_query.py",
|
||||
"source_url": "https://github.com/DearSong15/ql-scripts/blob/main/ks_query.py",
|
||||
"raw_url": "https://raw.githubusercontent.com/DearSong15/ql-scripts/main/ks_query.py",
|
||||
"uploaded_at": "2026-05-11T14:51:55Z",
|
||||
"saved_path": "脚本库/web版/抓包/query/2026-05-11_ks_query_848504df.py",
|
||||
"auth_type": "抓包",
|
||||
"platform_type": "web版",
|
||||
"evidence": "web/H5关键词 + cookie/token/header"
|
||||
},
|
||||
{
|
||||
"category": "web版/抓包",
|
||||
"project": "券妈妈时段奖励",
|
||||
"filename": "2025-01-11_qmm_868f2cd3.js",
|
||||
"sha256": "868f2cd3002df5797fe7ad064612d6e5bc4b97d168092281a6390b7219643743",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "lksky8/sign-ql",
|
||||
"source_path": "invalid/qmm.js",
|
||||
"source_url": "https://github.com/lksky8/sign-ql/blob/main/invalid/qmm.js",
|
||||
"raw_url": "https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/qmm.js",
|
||||
"uploaded_at": "2025-01-11T18:42:58Z",
|
||||
"saved_path": "脚本库/web版/抓包/券妈妈时段奖励/2025-01-11_qmm_868f2cd3.js",
|
||||
"auth_type": "抓包",
|
||||
"platform_type": "web版",
|
||||
"evidence": "web/H5关键词 + cookie/token/header"
|
||||
},
|
||||
{
|
||||
"category": "web版/账密",
|
||||
"project": "'未知用户',",
|
||||
"filename": "2026-05-19_juejin_checkin_6f8a138b.js",
|
||||
"sha256": "6f8a138b51c397220444c9312040dbe3407af5aeed4fa4467a36672aeb8bcfd1",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "huwangkeji/juejin_checkin",
|
||||
"source_path": "juejin_checkin.js",
|
||||
"source_url": "https://github.com/huwangkeji/juejin_checkin/blob/main/juejin_checkin.js",
|
||||
"raw_url": "https://raw.githubusercontent.com/huwangkeji/juejin_checkin/main/juejin_checkin.js",
|
||||
"uploaded_at": "2026-05-19T14:34:11Z",
|
||||
"saved_path": "脚本库/web版/账密/'未知用户',/2026-05-19_juejin_checkin_6f8a138b.js",
|
||||
"auth_type": "账密",
|
||||
"platform_type": "web版",
|
||||
"evidence": "web/H5关键词 + username/password/login"
|
||||
},
|
||||
{
|
||||
"category": "web版/账密",
|
||||
"project": "apply_link.split'id='-1}",
|
||||
"filename": "2026-03-27_3dmgame_2262c9f7.py",
|
||||
"sha256": "2262c9f7c2d40c8ef9822325fadd2e8ed3c43ba0f609c072a27c49b02edc2eaa",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "lksky8/sign-ql",
|
||||
"source_path": "3dmgame.py",
|
||||
"source_url": "https://github.com/lksky8/sign-ql/blob/main/3dmgame.py",
|
||||
"raw_url": "https://raw.githubusercontent.com/lksky8/sign-ql/main/3dmgame.py",
|
||||
"uploaded_at": "2026-03-27T20:17:30Z",
|
||||
"saved_path": "脚本库/web版/账密/apply_link.split'id='-1}/2026-03-27_3dmgame_2262c9f7.py",
|
||||
"auth_type": "账密",
|
||||
"platform_type": "web版",
|
||||
"evidence": "web/H5关键词 + username/password/login"
|
||||
},
|
||||
{
|
||||
"category": "web版/账密",
|
||||
"project": "str,_token_str",
|
||||
"filename": "2025-09-22_PPark_120e7330.py",
|
||||
"sha256": "120e73308bc1ccfb9db8ebd87357364850257a25ba1bc039d67c2967fe6c8e19",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "lksky8/sign-ql",
|
||||
"source_path": "PPark.py",
|
||||
"source_url": "https://github.com/lksky8/sign-ql/blob/main/PPark.py",
|
||||
"raw_url": "https://raw.githubusercontent.com/lksky8/sign-ql/main/PPark.py",
|
||||
"uploaded_at": "2025-09-22T11:01:17Z",
|
||||
"saved_path": "脚本库/web版/账密/str,_token_str/2025-09-22_PPark_120e7330.py",
|
||||
"auth_type": "账密",
|
||||
"platform_type": "web版",
|
||||
"evidence": "web/H5关键词 + username/password/login"
|
||||
},
|
||||
{
|
||||
"category": "web版/账密",
|
||||
"project": "tyqh",
|
||||
"filename": "2026-05-23_tyqh_4c779933.py",
|
||||
"sha256": "4c779933563a21d73534721d588cf8fd5aa9e6d6ced3e3b3bb414c91fb576708",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "lksky8/sign-ql",
|
||||
"source_path": "invalid/tyqh.py",
|
||||
"source_url": "https://github.com/lksky8/sign-ql/blob/main/invalid/tyqh.py",
|
||||
"raw_url": "https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/tyqh.py",
|
||||
"uploaded_at": "2026-05-23T06:33:20Z",
|
||||
"saved_path": "脚本库/web版/账密/tyqh/2026-05-23_tyqh_4c779933.py",
|
||||
"auth_type": "账密",
|
||||
"platform_type": "web版",
|
||||
"evidence": "web/H5关键词 + username/password/login"
|
||||
},
|
||||
{
|
||||
"category": "web版/账密",
|
||||
"project": "url.hostname,",
|
||||
"filename": "2026-05-11_zsp_video_960b2e28.js",
|
||||
"sha256": "960b2e28799c40a00eb4bd75dcda1e61b3ab747374716073995c75053c3083ee",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "DearSong15/ql-scripts",
|
||||
"source_path": "zsp_video.js",
|
||||
"source_url": "https://github.com/DearSong15/ql-scripts/blob/main/zsp_video.js",
|
||||
"raw_url": "https://raw.githubusercontent.com/DearSong15/ql-scripts/main/zsp_video.js",
|
||||
"uploaded_at": "2026-05-11T15:03:30Z",
|
||||
"saved_path": "脚本库/web版/账密/url.hostname,/2026-05-11_zsp_video_960b2e28.js",
|
||||
"auth_type": "账密",
|
||||
"platform_type": "web版",
|
||||
"evidence": "web/H5关键词 + username/password/login"
|
||||
},
|
||||
{
|
||||
"category": "web版/账密",
|
||||
"project": "yxw_appsign",
|
||||
"filename": "2025-09-28_yxw_appsign_c6d91db1.py",
|
||||
"sha256": "c6d91db16e3a84bf5dfc1e2c7d6cb38fb3f6d38f5829d7f496ba308fa7a77a10",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "lksky8/sign-ql",
|
||||
"source_path": "yxw_appsign.py",
|
||||
"source_url": "https://github.com/lksky8/sign-ql/blob/main/yxw_appsign.py",
|
||||
"raw_url": "https://raw.githubusercontent.com/lksky8/sign-ql/main/yxw_appsign.py",
|
||||
"uploaded_at": "2025-09-28T06:42:50Z",
|
||||
"saved_path": "脚本库/web版/账密/yxw_appsign/2025-09-28_yxw_appsign_c6d91db1.py",
|
||||
"auth_type": "账密",
|
||||
"platform_type": "web版",
|
||||
"evidence": "web/H5关键词 + username/password/login"
|
||||
},
|
||||
{
|
||||
"category": "web版/账密",
|
||||
"project": "yxw_luckbox",
|
||||
"filename": "2025-08-21_yxw_luckbox_79511924.py",
|
||||
"sha256": "7951192443b96cec1fe801de769343a2e080be439b46c9b2bfb4372a4cdfe2e1",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "lksky8/sign-ql",
|
||||
"source_path": "yxw_luckbox.py",
|
||||
"source_url": "https://github.com/lksky8/sign-ql/blob/main/yxw_luckbox.py",
|
||||
"raw_url": "https://raw.githubusercontent.com/lksky8/sign-ql/main/yxw_luckbox.py",
|
||||
"uploaded_at": "2025-08-21T12:12:12Z",
|
||||
"saved_path": "脚本库/web版/账密/yxw_luckbox/2025-08-21_yxw_luckbox_79511924.py",
|
||||
"auth_type": "账密",
|
||||
"platform_type": "web版",
|
||||
"evidence": "web/H5关键词 + username/password/login"
|
||||
},
|
||||
{
|
||||
"category": "web版/账密",
|
||||
"project": "中石化加油广东APP签到",
|
||||
"filename": "2022-07-24_jygd_47493387.js",
|
||||
"sha256": "474933874ed61cd8ebd4efed3ee26778f4e3d0290ba16222f9feed61bafb6838",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "lksky8/sign-ql",
|
||||
"source_path": "invalid/jygd.js",
|
||||
"source_url": "https://github.com/lksky8/sign-ql/blob/main/invalid/jygd.js",
|
||||
"raw_url": "https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/jygd.js",
|
||||
"uploaded_at": "2022-07-24T02:54:25Z",
|
||||
"saved_path": "脚本库/web版/账密/中石化加油广东APP签到/2022-07-24_jygd_47493387.js",
|
||||
"auth_type": "账密",
|
||||
"platform_type": "web版",
|
||||
"evidence": "web/H5关键词 + username/password/login"
|
||||
},
|
||||
{
|
||||
"category": "web版/账密",
|
||||
"project": "叮咚买菜",
|
||||
"filename": "2022-11-17_ddmc_2d78fbea_2.js",
|
||||
"sha256": "2d78fbea0d710c7d29ad02178c603c97586bc9a5843ccd9f92cd18d6b8157c80",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "lksky8/sign-ql",
|
||||
"source_path": "ddmc.js",
|
||||
"source_url": "https://github.com/lksky8/sign-ql/blob/main/ddmc.js",
|
||||
"raw_url": "https://raw.githubusercontent.com/lksky8/sign-ql/main/ddmc.js",
|
||||
"uploaded_at": "2022-11-17T13:54:32Z",
|
||||
"saved_path": "脚本库/web版/账密/叮咚买菜/2022-11-17_ddmc_2d78fbea_2.js",
|
||||
"auth_type": "账密",
|
||||
"platform_type": "web版",
|
||||
"evidence": "web/H5关键词 + username/password/login"
|
||||
},
|
||||
{
|
||||
"category": "web版/账密",
|
||||
"project": "方舟健客签到",
|
||||
"filename": "2025-12-07_jksign_b722f903.py",
|
||||
"sha256": "b722f903ef41b1cab2540fc2a7b84bb51cb2e8d354783a225e3c364b0799a4e6",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "lksky8/sign-ql",
|
||||
"source_path": "jksign.py",
|
||||
"source_url": "https://github.com/lksky8/sign-ql/blob/main/jksign.py",
|
||||
"raw_url": "https://raw.githubusercontent.com/lksky8/sign-ql/main/jksign.py",
|
||||
"uploaded_at": "2025-12-07T17:42:50Z",
|
||||
"saved_path": "脚本库/web版/账密/方舟健客签到/2025-12-07_jksign_b722f903.py",
|
||||
"auth_type": "账密",
|
||||
"platform_type": "web版",
|
||||
"evidence": "web/H5关键词 + username/password/login"
|
||||
},
|
||||
{
|
||||
"category": "web版/账密",
|
||||
"project": "星星充电签到",
|
||||
"filename": "2025-09-01_xxcd_40e3aef4.py",
|
||||
"sha256": "40e3aef421127efd0fe80201c786cf341993dd4e8318fe4f8456a912aef026e0",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "lksky8/sign-ql",
|
||||
"source_path": "xxcd.py",
|
||||
"source_url": "https://github.com/lksky8/sign-ql/blob/main/xxcd.py",
|
||||
"raw_url": "https://raw.githubusercontent.com/lksky8/sign-ql/main/xxcd.py",
|
||||
"uploaded_at": "2025-09-01T15:45:21Z",
|
||||
"saved_path": "脚本库/web版/账密/星星充电签到/2025-09-01_xxcd_40e3aef4.py",
|
||||
"auth_type": "账密",
|
||||
"platform_type": "web版",
|
||||
"evidence": "web/H5关键词 + username/password/login"
|
||||
},
|
||||
{
|
||||
"category": "微信小程序/抓包版",
|
||||
"project": "cloud189",
|
||||
"filename": "2025-09-06_cloud189_7c90c2eb.py",
|
||||
"sha256": "7c90c2eb0032873254db7819a42440cd062ae32af3fa537efc7c295c0e1da804",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "lksky8/sign-ql",
|
||||
"source_path": "cloud189.py",
|
||||
"source_url": "https://github.com/lksky8/sign-ql/blob/main/cloud189.py",
|
||||
"raw_url": "https://raw.githubusercontent.com/lksky8/sign-ql/main/cloud189.py",
|
||||
"uploaded_at": "2025-09-06T12:51:46Z",
|
||||
"saved_path": "脚本库/微信小程序/抓包版/cloud189/2025-09-06_cloud189_7c90c2eb.py",
|
||||
"auth_type": "抓包版",
|
||||
"platform_type": "微信小程序",
|
||||
"evidence": "appid/openid/session_key/encryptedData等小程序字段"
|
||||
},
|
||||
{
|
||||
"category": "微信小程序/抓包版",
|
||||
"project": "jtc",
|
||||
"filename": "2025-10-26_jtc_d7fa5acd_2.py",
|
||||
"sha256": "d7fa5acdc107ddb45fd772c4bb0c9491fd48e8e3d7d18ae5a4286579151676ef",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "lksky8/sign-ql",
|
||||
"source_path": "jtc.py",
|
||||
"source_url": "https://github.com/lksky8/sign-ql/blob/main/jtc.py",
|
||||
"raw_url": "https://raw.githubusercontent.com/lksky8/sign-ql/main/jtc.py",
|
||||
"uploaded_at": "2025-10-26T12:24:47Z",
|
||||
"saved_path": "脚本库/微信小程序/抓包版/jtc/2025-10-26_jtc_d7fa5acd_2.py",
|
||||
"auth_type": "抓包版",
|
||||
"platform_type": "微信小程序",
|
||||
"evidence": "appid/openid/session_key/encryptedData等小程序字段"
|
||||
},
|
||||
{
|
||||
"category": "微信小程序/抓包版",
|
||||
"project": "快手双端",
|
||||
"filename": "2026-05-11_ks_dual_aa4fbaa7.js",
|
||||
"sha256": "aa4fbaa74f4c00599fa2a8c1e358c99c6f393dc9b180b7c8260162ddd20b1e0f",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "DearSong15/ql-scripts",
|
||||
"source_path": "ks_dual.js",
|
||||
"source_url": "https://github.com/DearSong15/ql-scripts/blob/main/ks_dual.js",
|
||||
"raw_url": "https://raw.githubusercontent.com/DearSong15/ql-scripts/main/ks_dual.js",
|
||||
"uploaded_at": "2026-05-11T15:03:30Z",
|
||||
"saved_path": "脚本库/微信小程序/抓包版/快手双端/2026-05-11_ks_dual_aa4fbaa7.js",
|
||||
"auth_type": "抓包版",
|
||||
"platform_type": "微信小程序",
|
||||
"evidence": "appid/openid/session_key/encryptedData等小程序字段"
|
||||
},
|
||||
{
|
||||
"category": "微信小程序/抓包版",
|
||||
"project": "滴滴果园",
|
||||
"filename": "2025-01-11_ddgy_236924d1.js",
|
||||
"sha256": "236924d18d7e9ae58141a6c45bde1b9de748e6e63c8ca805162caf02fb01b362",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "lksky8/sign-ql",
|
||||
"source_path": "invalid/ddgy.js",
|
||||
"source_url": "https://github.com/lksky8/sign-ql/blob/main/invalid/ddgy.js",
|
||||
"raw_url": "https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/ddgy.js",
|
||||
"uploaded_at": "2025-01-11T18:50:13Z",
|
||||
"saved_path": "脚本库/微信小程序/抓包版/滴滴果园/2025-01-11_ddgy_236924d1.js",
|
||||
"auth_type": "抓包版",
|
||||
"platform_type": "微信小程序",
|
||||
"evidence": "appid/openid/session_key/encryptedData等小程序字段"
|
||||
},
|
||||
{
|
||||
"category": "微信小程序/抓包版",
|
||||
"project": "索尼中国",
|
||||
"filename": "2025-01-11_sonybbs_359e1e49.js",
|
||||
"sha256": "359e1e4984589cd0b5363e39c8ff9a566a54f3b5678cee3540b33ac3a546638a",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "lksky8/sign-ql",
|
||||
"source_path": "invalid/sonybbs.js",
|
||||
"source_url": "https://github.com/lksky8/sign-ql/blob/main/invalid/sonybbs.js",
|
||||
"raw_url": "https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/sonybbs.js",
|
||||
"uploaded_at": "2025-01-11T18:47:31Z",
|
||||
"saved_path": "脚本库/微信小程序/抓包版/索尼中国/2025-01-11_sonybbs_359e1e49.js",
|
||||
"auth_type": "抓包版",
|
||||
"platform_type": "微信小程序",
|
||||
"evidence": "appid/openid/session_key/encryptedData等小程序字段"
|
||||
},
|
||||
{
|
||||
"category": "微信小程序/抓包版",
|
||||
"project": "统一茄皇-修复版",
|
||||
"filename": "2023-01-03_tyqh_2fe80596.js",
|
||||
"sha256": "2fe8059609f086f32865e2d2463e2e54b532cae84923ca73cb64cf6d5432509c",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "lksky8/sign-ql",
|
||||
"source_path": "invalid/tyqh.js",
|
||||
"source_url": "https://github.com/lksky8/sign-ql/blob/main/invalid/tyqh.js",
|
||||
"raw_url": "https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/tyqh.js",
|
||||
"uploaded_at": "2023-01-03T11:39:58Z",
|
||||
"saved_path": "脚本库/微信小程序/抓包版/统一茄皇-修复版/2023-01-03_tyqh_2fe80596.js",
|
||||
"auth_type": "抓包版",
|
||||
"platform_type": "微信小程序",
|
||||
"evidence": "appid/openid/session_key/encryptedData等小程序字段"
|
||||
},
|
||||
{
|
||||
"category": "微信小程序/抓包版",
|
||||
"project": "统一茄皇互助",
|
||||
"filename": "2023-01-03_qhhz_07a8e366.js",
|
||||
"sha256": "07a8e366afc33d150d5b2c1d3dde5220e01ffa855b3c568244fe6013a54aae43",
|
||||
"source_platform": "GitHub",
|
||||
"source_repo": "lksky8/sign-ql",
|
||||
"source_path": "invalid/qhhz.js",
|
||||
"source_url": "https://github.com/lksky8/sign-ql/blob/main/invalid/qhhz.js",
|
||||
"raw_url": "https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/qhhz.js",
|
||||
"uploaded_at": "2023-01-03T11:38:28Z",
|
||||
"saved_path": "脚本库/微信小程序/抓包版/统一茄皇互助/2023-01-03_qhhz_07a8e366.js",
|
||||
"auth_type": "抓包版",
|
||||
"platform_type": "微信小程序",
|
||||
"evidence": "appid/openid/session_key/encryptedData等小程序字段"
|
||||
}
|
||||
]
|
||||
47
README.md
Normal file
47
README.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# 青龙脚本分类库
|
||||
|
||||
本仓库用于归档公开青龙脚本,并按运行端与凭证方式分类。
|
||||
|
||||
## 分类
|
||||
|
||||
- `APP版/抓包`:1 个脚本,1 个项目
|
||||
- `APP版/账密`:0 个脚本,0 个项目
|
||||
- `web版/抓包`:5 个脚本,5 个项目
|
||||
- `web版/账密`:11 个脚本,11 个项目
|
||||
- `微信小程序/协议版`:0 个脚本,0 个项目
|
||||
- `微信小程序/抓包版`:7 个脚本,7 个项目
|
||||
- `未分类`:0 个脚本,0 个项目
|
||||
|
||||
## 目录规则
|
||||
|
||||
```text
|
||||
脚本库/APP版/抓包/<项目>/YYYY-MM-DD_原文件名_<sha8>.ext
|
||||
脚本库/APP版/账密/<项目>/YYYY-MM-DD_原文件名_<sha8>.ext
|
||||
脚本库/web版/抓包/<项目>/YYYY-MM-DD_原文件名_<sha8>.ext
|
||||
脚本库/web版/账密/<项目>/YYYY-MM-DD_原文件名_<sha8>.ext
|
||||
脚本库/微信小程序/协议版/<项目>/YYYY-MM-DD_原文件名_<sha8>.ext
|
||||
脚本库/微信小程序/抓包版/<项目>/YYYY-MM-DD_原文件名_<sha8>.ext
|
||||
```
|
||||
|
||||
## 元数据
|
||||
|
||||
- `INDEX.csv`:脚本索引,含分类、项目、源仓库、源路径、源 URL、上传时间、SHA256。
|
||||
- `INDEX.json`:同上,JSON 格式。
|
||||
- 文件名中的日期优先使用源文件最近一次 commit 时间。
|
||||
- 相同代码以归一化 SHA256 去重。
|
||||
|
||||
## 采集器
|
||||
|
||||
运行:
|
||||
|
||||
```bash
|
||||
python3 collector.py
|
||||
```
|
||||
|
||||
可选环境变量:
|
||||
|
||||
```bash
|
||||
export GITHUB_TOKEN=你的GitHubToken # 可提升 GitHub API 限额
|
||||
export MAX_REPOS_PER_QUERY=20
|
||||
export MAX_FILES_TOTAL=500
|
||||
```
|
||||
764
collector.py
Normal file
764
collector.py
Normal file
@@ -0,0 +1,764 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
公开青龙脚本采集器(多来源首轮版)
|
||||
|
||||
目标:
|
||||
- 从公开代码平台/公开网页入口搜索青龙/QL 脚本;
|
||||
- 按 APP版/抓包、APP版/账密、web版/抓包、web版/账密、微信小程序/协议版、微信小程序/抓包版分类;
|
||||
- 以代码内容 SHA256 去重;
|
||||
- 同项目不同代码放入同一项目目录;
|
||||
- 记录源仓库、源路径、源 URL、上传/提交时间。
|
||||
|
||||
说明:
|
||||
- GitHub 搜索 API 未配置 token 时有限流;可设置 GITHUB_TOKEN 提升额度。
|
||||
- “上传时间”优先取该文件最近一次 commit 的 commit.committer.date;失败时退化为仓库 pushed_at。
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import csv
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
import unicodedata
|
||||
import urllib.parse
|
||||
from dataclasses import dataclass, asdict
|
||||
from pathlib import Path
|
||||
from typing import Dict, Iterable, List, Optional, Tuple
|
||||
|
||||
try:
|
||||
import requests
|
||||
except ModuleNotFoundError: # 便于在新环境直接运行
|
||||
import subprocess
|
||||
import sys as _sys
|
||||
subprocess.check_call([_sys.executable, "-m", "pip", "install", "requests", "-q", "--break-system-packages"])
|
||||
import requests
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
OUT_DIR = ROOT / "脚本库"
|
||||
META_DIR = ROOT / "metadata"
|
||||
INDEX_CSV = ROOT / "INDEX.csv"
|
||||
INDEX_JSON = ROOT / "INDEX.json"
|
||||
README = ROOT / "README.md"
|
||||
CACHE = META_DIR / "collector_cache.json"
|
||||
|
||||
MAX_REPOS_PER_QUERY = int(os.getenv("MAX_REPOS_PER_QUERY", "12"))
|
||||
MAX_FILES_TOTAL = int(os.getenv("MAX_FILES_TOTAL", "260"))
|
||||
REQUEST_SLEEP = float(os.getenv("REQUEST_SLEEP", "0.4"))
|
||||
|
||||
GITHUB_TOKEN = os.getenv("GITHUB_TOKEN", "").strip()
|
||||
SESSION = requests.Session()
|
||||
SESSION.headers.update({
|
||||
"User-Agent": "ql-script-classifier/1.0",
|
||||
"Accept": "application/vnd.github+json",
|
||||
})
|
||||
if GITHUB_TOKEN:
|
||||
SESSION.headers["Authorization"] = f"Bearer {GITHUB_TOKEN}"
|
||||
|
||||
SEARCH_QUERIES = [
|
||||
# 青龙/QL 常用关键词
|
||||
"青龙 脚本 language:JavaScript",
|
||||
"青龙 脚本 language:Python",
|
||||
"qinglong script language:JavaScript",
|
||||
"qinglong script language:Python",
|
||||
"ql repo script language:JavaScript",
|
||||
'"new Env" "cron" language:JavaScript',
|
||||
'"new Env" "青龙" language:JavaScript',
|
||||
'"ql repo" "new Env" language:JavaScript',
|
||||
'"青龙面板" "new Env" language:JavaScript',
|
||||
'"微信小程序" "青龙" language:Python',
|
||||
'"wx_token" "wx_cloud" language:Python',
|
||||
'"getMiniProgramCode" language:Python',
|
||||
'"getMiniProgramCode" language:JavaScript',
|
||||
]
|
||||
|
||||
GITEE_SEARCH_QUERIES = [
|
||||
"青龙 脚本",
|
||||
"new Env 青龙",
|
||||
"wx_token wx_cloud",
|
||||
"getMiniProgramCode",
|
||||
]
|
||||
|
||||
# 其它公开网页入口:只处理公开可访问的代码页/raw 链接;不处理需要登录、私密分享或绕权的网盘。
|
||||
WEB_SEARCH_QUERIES = [
|
||||
'青龙 脚本 "new Env"',
|
||||
'青龙脚本 "ql repo"',
|
||||
'青龙脚本 "wx_token" "wx_cloud"',
|
||||
'青龙脚本 "getMiniProgramCode"',
|
||||
'青龙脚本 site:gitee.com',
|
||||
'青龙脚本 site:gitcode.com',
|
||||
'青龙脚本 site:agit.ai',
|
||||
'青龙脚本 site:raw.githubusercontent.com',
|
||||
]
|
||||
|
||||
VALID_SUFFIXES = {".js", ".py", ".ts", ".sh"}
|
||||
SKIP_PATH_KEYWORDS = {
|
||||
"node_modules", ".git", "dist/", "build/", "package-lock", "yarn.lock",
|
||||
"readme", "license", "docker", "workflow", ".github", "icon", "image", "png", "jpg",
|
||||
}
|
||||
|
||||
CATEGORY_ORDER = [
|
||||
"APP版/抓包",
|
||||
"APP版/账密",
|
||||
"web版/抓包",
|
||||
"web版/账密",
|
||||
"微信小程序/协议版",
|
||||
"微信小程序/抓包版",
|
||||
"未分类",
|
||||
]
|
||||
|
||||
|
||||
@dataclass
|
||||
class Record:
|
||||
category: str
|
||||
project: str
|
||||
filename: str
|
||||
sha256: str
|
||||
source_platform: str
|
||||
source_repo: str
|
||||
source_path: str
|
||||
source_url: str
|
||||
raw_url: str
|
||||
uploaded_at: str
|
||||
saved_path: str
|
||||
auth_type: str
|
||||
platform_type: str
|
||||
evidence: str
|
||||
|
||||
|
||||
def safe_segment(text: str, fallback: str = "unknown", max_len: int = 80) -> str:
|
||||
text = unicodedata.normalize("NFKC", text or "")
|
||||
text = re.sub(r"[\\/:*?\"<>|\s]+", "_", text).strip("._-")
|
||||
text = re.sub(r"_+", "_", text)
|
||||
if not text:
|
||||
text = fallback
|
||||
return text[:max_len]
|
||||
|
||||
|
||||
def normalized_hash(content: str) -> str:
|
||||
# 去 BOM、统一换行、去末尾空白;不删除注释,避免误合并不同版本
|
||||
norm = content.replace("\r\n", "\n").replace("\r", "\n").lstrip("\ufeff")
|
||||
norm = "\n".join(line.rstrip() for line in norm.split("\n")).strip() + "\n"
|
||||
return hashlib.sha256(norm.encode("utf-8", "ignore")).hexdigest()
|
||||
|
||||
|
||||
def github_get(url: str, **kwargs):
|
||||
time.sleep(REQUEST_SLEEP)
|
||||
r = SESSION.get(url, timeout=30, **kwargs)
|
||||
if r.status_code == 403 and "rate limit" in r.text.lower():
|
||||
reset = r.headers.get("X-RateLimit-Reset")
|
||||
print(f"[WARN] GitHub rate limited: {url} reset={reset}")
|
||||
raise RuntimeError("github_rate_limited")
|
||||
if r.status_code >= 400:
|
||||
print(f"[WARN] HTTP {r.status_code}: {url} {r.text[:160]}")
|
||||
return None
|
||||
return r
|
||||
|
||||
|
||||
def search_github_repos() -> List[dict]:
|
||||
repos: Dict[str, dict] = {}
|
||||
for q in SEARCH_QUERIES:
|
||||
url = "https://api.github.com/search/repositories"
|
||||
params = {"q": q, "sort": "updated", "order": "desc", "per_page": MAX_REPOS_PER_QUERY}
|
||||
print(f"[SEARCH] {q}", flush=True)
|
||||
r = github_get(url, params=params)
|
||||
if not r:
|
||||
continue
|
||||
data = r.json()
|
||||
for item in data.get("items", []):
|
||||
full = item.get("full_name")
|
||||
if full and full not in repos:
|
||||
repos[full] = item
|
||||
return list(repos.values())
|
||||
|
||||
|
||||
def generic_get(url: str, **kwargs):
|
||||
time.sleep(REQUEST_SLEEP)
|
||||
headers = kwargs.pop("headers", {}) or {}
|
||||
merged = {"User-Agent": "Mozilla/5.0 ql-script-classifier/1.0", **headers}
|
||||
try:
|
||||
r = SESSION.get(url, timeout=30, headers=merged, **kwargs)
|
||||
if r.status_code >= 400:
|
||||
print(f"[WARN] HTTP {r.status_code}: {url} {r.text[:120]}")
|
||||
return None
|
||||
return r
|
||||
except Exception as e:
|
||||
print(f"[WARN] GET failed: {url} {e}")
|
||||
return None
|
||||
|
||||
|
||||
def search_gitee_repos() -> List[dict]:
|
||||
"""Gitee 公开搜索。API 搜索经常返回空,因此同时解析公开搜索页。"""
|
||||
repos: Dict[str, dict] = {}
|
||||
for q in GITEE_SEARCH_QUERIES:
|
||||
print(f"[GITEE_SEARCH] {q}")
|
||||
# API 尝试
|
||||
api = "https://gitee.com/api/v5/search/repositories"
|
||||
r = generic_get(api, params={"q": q, "page": 1, "per_page": MAX_REPOS_PER_QUERY})
|
||||
if r:
|
||||
try:
|
||||
data = r.json()
|
||||
if isinstance(data, list):
|
||||
for item in data:
|
||||
full = item.get("full_name") or item.get("path_with_namespace")
|
||||
if full:
|
||||
repos[full] = item
|
||||
except Exception:
|
||||
pass
|
||||
# HTML 搜索页尝试
|
||||
html_url = "https://gitee.com/search"
|
||||
# HTML 搜索容易被前端页面拖慢/反爬,默认仅使用 API;如需扩展可后续加入定向种子仓库。
|
||||
return list(repos.values())
|
||||
|
||||
|
||||
def list_gitee_tree(repo: dict) -> List[dict]:
|
||||
full = repo.get("full_name") or repo.get("path_with_namespace")
|
||||
if not full:
|
||||
return []
|
||||
branch = repo.get("default_branch") or "master"
|
||||
for b in [branch, "master", "main"]:
|
||||
api = f"https://gitee.com/api/v5/repos/{urllib.parse.quote(str(full), safe='')}/git/trees/{urllib.parse.quote(str(b))}"
|
||||
r = generic_get(api, params={"recursive": 1})
|
||||
if not r:
|
||||
continue
|
||||
try:
|
||||
data = r.json()
|
||||
tree = data.get("tree") if isinstance(data, dict) else None
|
||||
if isinstance(tree, list):
|
||||
repo["default_branch"] = b
|
||||
return tree
|
||||
except Exception:
|
||||
continue
|
||||
return []
|
||||
|
||||
|
||||
def get_gitee_file_content(repo_full: str, path: str, branch: str) -> Tuple[Optional[str], str, str]:
|
||||
# raw URL 不需要 token 的公开仓库通常可直接访问
|
||||
raw_url = f"https://gitee.com/{repo_full}/raw/{urllib.parse.quote(branch)}/{urllib.parse.quote(path)}"
|
||||
html_url = f"https://gitee.com/{repo_full}/blob/{urllib.parse.quote(branch)}/{urllib.parse.quote(path)}"
|
||||
r = generic_get(raw_url)
|
||||
if r and len(r.content) <= 1024 * 1024:
|
||||
return r.content.decode("utf-8", "ignore"), raw_url, html_url
|
||||
return None, raw_url, html_url
|
||||
|
||||
|
||||
def get_gitee_file_uploaded_at(repo_full: str, path: str, fallback: str) -> str:
|
||||
# Gitee commit API 兼容性不稳定;失败时退化到 repo pushed_at 或空。
|
||||
encoded_repo = urllib.parse.quote(repo_full, safe="")
|
||||
api = f"https://gitee.com/api/v5/repos/{encoded_repo}/commits"
|
||||
r = generic_get(api, params={"path": path, "page": 1, "per_page": 1})
|
||||
if r:
|
||||
try:
|
||||
data = r.json()
|
||||
if isinstance(data, list) and data:
|
||||
c = data[0]
|
||||
return ((c.get("commit") or {}).get("committer") or {}).get("date") or c.get("created_at") or fallback or ""
|
||||
except Exception:
|
||||
pass
|
||||
return fallback or ""
|
||||
|
||||
|
||||
def discover_public_code_links() -> List[dict]:
|
||||
"""通过公开搜索页发现 raw/js/py 链接。使用 DuckDuckGo HTML,无登录。"""
|
||||
links: Dict[str, dict] = {}
|
||||
if os.getenv("ENABLE_WEB_SEARCH", "false").strip().lower() != "true":
|
||||
print("[WEB_SEARCH] disabled; set ENABLE_WEB_SEARCH=true to enable public web search")
|
||||
return []
|
||||
for q in WEB_SEARCH_QUERIES:
|
||||
print(f"[WEB_SEARCH] {q}")
|
||||
url = "https://duckduckgo.com/html/"
|
||||
r = generic_get(url, params={"q": q})
|
||||
if not r:
|
||||
continue
|
||||
html = r.text
|
||||
for m in re.finditer(r'href="([^"]+)"', html):
|
||||
href = m.group(1)
|
||||
href = href.replace("&", "&")
|
||||
if "uddg=" in href:
|
||||
qs = urllib.parse.parse_qs(urllib.parse.urlparse(href).query)
|
||||
href = qs.get("uddg", [href])[0]
|
||||
if not re.search(r"\.(js|py|ts|sh)(\?|$)", href, flags=re.I):
|
||||
continue
|
||||
if not any(host in href for host in ["githubusercontent.com", "gitee.com", "gitcode", "agit.ai", "raw"]):
|
||||
continue
|
||||
links[href] = {"url": href}
|
||||
return list(links.values())
|
||||
|
||||
|
||||
def get_public_link_content(url: str) -> Tuple[Optional[str], str, str, str]:
|
||||
raw_url = url
|
||||
html_url = url
|
||||
# GitHub blob -> raw
|
||||
m = re.match(r"https://github\.com/([^/]+/[^/]+)/blob/([^/]+)/(.+)", url)
|
||||
if m:
|
||||
raw_url = f"https://raw.githubusercontent.com/{m.group(1)}/{m.group(2)}/{m.group(3)}"
|
||||
# Gitee blob -> raw
|
||||
m = re.match(r"https://gitee\.com/([^/]+/[^/]+)/blob/([^/]+)/(.+)", url)
|
||||
if m:
|
||||
raw_url = f"https://gitee.com/{m.group(1)}/raw/{m.group(2)}/{m.group(3)}"
|
||||
r = generic_get(raw_url)
|
||||
if r and len(r.content) <= 1024 * 1024:
|
||||
return r.content.decode("utf-8", "ignore"), raw_url, html_url, ""
|
||||
return None, raw_url, html_url, ""
|
||||
|
||||
|
||||
def list_github_tree(repo: dict) -> List[dict]:
|
||||
full = repo["full_name"]
|
||||
branch = repo.get("default_branch") or "main"
|
||||
url = f"https://api.github.com/repos/{full}/git/trees/{urllib.parse.quote(branch)}?recursive=1"
|
||||
r = github_get(url)
|
||||
if not r:
|
||||
return []
|
||||
data = r.json()
|
||||
return data.get("tree", [])
|
||||
|
||||
|
||||
def is_candidate_path(path: str) -> bool:
|
||||
lower = path.lower()
|
||||
if any(k in lower for k in SKIP_PATH_KEYWORDS):
|
||||
return False
|
||||
if Path(path).suffix.lower() not in VALID_SUFFIXES:
|
||||
return False
|
||||
# 常见脚本路径或文件内容关键词由后续判断;这里不过窄过滤
|
||||
return True
|
||||
|
||||
|
||||
def get_file_content(repo_full: str, path: str, branch: str) -> Tuple[Optional[str], str, str]:
|
||||
encoded = urllib.parse.quote(path, safe="")
|
||||
url = f"https://api.github.com/repos/{repo_full}/contents/{encoded}?ref={urllib.parse.quote(branch)}"
|
||||
r = github_get(url)
|
||||
if not r:
|
||||
return None, "", ""
|
||||
data = r.json()
|
||||
raw_url = data.get("download_url", "")
|
||||
html_url = data.get("html_url", "")
|
||||
content = data.get("content")
|
||||
if data.get("encoding") == "base64" and content:
|
||||
try:
|
||||
b = base64.b64decode(content)
|
||||
if len(b) > 1024 * 1024:
|
||||
return None, raw_url, html_url
|
||||
text = b.decode("utf-8", "ignore")
|
||||
return text, raw_url, html_url
|
||||
except Exception:
|
||||
return None, raw_url, html_url
|
||||
if raw_url:
|
||||
rr = github_get(raw_url)
|
||||
if rr:
|
||||
return rr.text, raw_url, html_url
|
||||
return None, raw_url, html_url
|
||||
|
||||
|
||||
def get_file_uploaded_at(repo_full: str, path: str, fallback: str) -> str:
|
||||
encoded = urllib.parse.quote(path, safe="")
|
||||
url = f"https://api.github.com/repos/{repo_full}/commits?path={encoded}&per_page=1"
|
||||
r = github_get(url)
|
||||
if not r:
|
||||
return fallback or ""
|
||||
arr = r.json()
|
||||
if isinstance(arr, list) and arr:
|
||||
commit = arr[0].get("commit", {})
|
||||
return (commit.get("committer") or {}).get("date") or (commit.get("author") or {}).get("date") or fallback or ""
|
||||
return fallback or ""
|
||||
|
||||
|
||||
def looks_like_ql_script(content: str, path: str) -> bool:
|
||||
lower = content.lower()
|
||||
score = 0
|
||||
keywords = [
|
||||
"new env", "cron:", "ql repo", "青龙", "notify", "sendnotify", "process.env",
|
||||
"requests.", "axios", "got(", "wx_token", "jd_cookie", "cookie", "authorization",
|
||||
"getminiprogramcode", "wx_cloud", "wx.login", "小程序",
|
||||
]
|
||||
for k in keywords:
|
||||
if k in lower:
|
||||
score += 1
|
||||
if Path(path).suffix.lower() in {".js", ".py", ".sh"}:
|
||||
score += 1
|
||||
return score >= 2
|
||||
|
||||
|
||||
def extract_project(content: str, path: str) -> str:
|
||||
patterns = [
|
||||
r"new\s+Env\([\"']([^\"']{2,80})[\"']\)",
|
||||
r"new\s+Env\s*\([`\"]([^`\"]{2,80})[`\"]\)",
|
||||
r"#\s*new\s+Env\([\"']([^\"']{2,80})[\"']\)",
|
||||
r"项目[::]\s*([^\n\r]{2,60})",
|
||||
r"name[::]\s*([^\n\r]{2,60})",
|
||||
]
|
||||
for pat in patterns:
|
||||
m = re.search(pat, content, flags=re.I)
|
||||
if m:
|
||||
name = m.group(1).strip()
|
||||
name = re.sub(r"[【】\[\]()()]", "", name).strip()
|
||||
if name:
|
||||
return safe_segment(name)
|
||||
stem = Path(path).stem
|
||||
stem = re.sub(r"^(ql_|jd_|jx_|ks_|wx_|applet_)", "", stem, flags=re.I)
|
||||
return safe_segment(stem)
|
||||
|
||||
|
||||
def classify(content: str, path: str) -> Tuple[str, str, str, str]:
|
||||
text = content
|
||||
lower = text.lower()
|
||||
evidence = []
|
||||
|
||||
is_wx_protocol = any(k in lower for k in [
|
||||
"getminiprogramcode", "wx_cloud", "wx_token", "miniprogramcode", "养鸡场", "wx.login", "code2session"
|
||||
])
|
||||
is_wx = is_wx_protocol or any(k in lower for k in [
|
||||
"appid", "openid", "session_key", "encrypteddata", "小程序", "wechat/login", "wxappid"
|
||||
])
|
||||
has_pwd = any(k in lower for k in [
|
||||
"password", "passwd", "pwd", "username", "user_name", "account", "账密", "手机号登录", "mobile", "smscode", "验证码"
|
||||
]) and any(k in lower for k in ["login", "登录", "/auth", "/user/login"])
|
||||
has_capture = any(k in lower for k in [
|
||||
"cookie", "authorization", "bearer", "token", "x-token", "session", "抓包", "header", "headers", "ck"
|
||||
])
|
||||
web_hint = any(k in lower for k in [
|
||||
"web", "h5", "pc", "browser", "chrome", "网页登录", "www.", "passport", "csrf"
|
||||
])
|
||||
app_hint = any(k in lower for k in [
|
||||
"app", "android", "ios", "okhttp", "x-requested-with", "user-agent", "deviceid", "imei", "oaid"
|
||||
])
|
||||
|
||||
if is_wx_protocol:
|
||||
evidence.append("getMiniProgramCode/wx_cloud/wx_token/code协议链路")
|
||||
return "微信小程序/协议版", "微信小程序", "协议版", "; ".join(evidence)
|
||||
if is_wx:
|
||||
evidence.append("appid/openid/session_key/encryptedData等小程序字段")
|
||||
return "微信小程序/抓包版", "微信小程序", "抓包版", "; ".join(evidence)
|
||||
|
||||
if web_hint and has_pwd:
|
||||
evidence.append("web/H5关键词 + username/password/login")
|
||||
return "web版/账密", "web版", "账密", "; ".join(evidence)
|
||||
if web_hint and has_capture:
|
||||
evidence.append("web/H5关键词 + cookie/token/header")
|
||||
return "web版/抓包", "web版", "抓包", "; ".join(evidence)
|
||||
if has_pwd:
|
||||
evidence.append("username/password/mobile/login")
|
||||
return "APP版/账密", "APP版", "账密", "; ".join(evidence)
|
||||
if has_capture:
|
||||
evidence.append("cookie/token/authorization/header")
|
||||
return "APP版/抓包", "APP版", "抓包", "; ".join(evidence)
|
||||
if app_hint:
|
||||
evidence.append("APP/Android/iOS/device关键词")
|
||||
return "APP版/抓包", "APP版", "抓包", "; ".join(evidence)
|
||||
return "未分类", "未分类", "未分类", "规则未命中"
|
||||
|
||||
|
||||
def unique_filename(project_dir: Path, uploaded_at: str, original: str, sha: str) -> str:
|
||||
date = (uploaded_at or "unknown")[:10] or "unknown"
|
||||
stem = safe_segment(Path(original).stem, "script", 60)
|
||||
suffix = Path(original).suffix or ".txt"
|
||||
name = f"{date}_{stem}_{sha[:8]}{suffix}"
|
||||
i = 2
|
||||
while (project_dir / name).exists():
|
||||
name = f"{date}_{stem}_{sha[:8]}_{i}{suffix}"
|
||||
i += 1
|
||||
return name
|
||||
|
||||
|
||||
def write_record_file(record: Record, content: str):
|
||||
out_path = ROOT / record.saved_path
|
||||
out_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
header = (
|
||||
f"# Source: {record.source_url}\n"
|
||||
f"# Raw: {record.raw_url}\n"
|
||||
f"# Repo: {record.source_repo}\n"
|
||||
f"# Path: {record.source_path}\n"
|
||||
f"# UploadedAt: {record.uploaded_at}\n"
|
||||
f"# SHA256: {record.sha256}\n"
|
||||
f"# Category: {record.category}\n"
|
||||
f"# Evidence: {record.evidence}\n\n"
|
||||
)
|
||||
if out_path.suffix.lower() == ".py":
|
||||
header = header
|
||||
elif out_path.suffix.lower() in {".js", ".ts"}:
|
||||
header = "// " + header.replace("\n", "\n// ").rstrip("// ") + "\n"
|
||||
elif out_path.suffix.lower() == ".sh":
|
||||
header = header
|
||||
out_path.write_text(header + content, encoding="utf-8", errors="ignore")
|
||||
|
||||
|
||||
def load_seen_hashes() -> set:
|
||||
if INDEX_JSON.exists():
|
||||
try:
|
||||
arr = json.loads(INDEX_JSON.read_text(encoding="utf-8"))
|
||||
return {x.get("sha256") for x in arr if x.get("sha256")}
|
||||
except Exception:
|
||||
return set()
|
||||
return set()
|
||||
|
||||
|
||||
def save_indexes(records: List[Record]):
|
||||
existing = []
|
||||
if INDEX_JSON.exists():
|
||||
try:
|
||||
existing = json.loads(INDEX_JSON.read_text(encoding="utf-8"))
|
||||
except Exception:
|
||||
existing = []
|
||||
by_sha = {x.get("sha256"): x for x in existing if x.get("sha256")}
|
||||
for r in records:
|
||||
by_sha[r.sha256] = asdict(r)
|
||||
arr = sorted(by_sha.values(), key=lambda x: (x.get("category", ""), x.get("project", ""), x.get("uploaded_at", "")))
|
||||
INDEX_JSON.write_text(json.dumps(arr, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
with INDEX_CSV.open("w", newline="", encoding="utf-8-sig") as f:
|
||||
fields = list(asdict(records[0]).keys()) if records else [
|
||||
"category", "project", "filename", "sha256", "source_platform", "source_repo", "source_path",
|
||||
"source_url", "raw_url", "uploaded_at", "saved_path", "auth_type", "platform_type", "evidence"
|
||||
]
|
||||
w = csv.DictWriter(f, fieldnames=fields)
|
||||
w.writeheader()
|
||||
for item in arr:
|
||||
w.writerow(item)
|
||||
|
||||
|
||||
def update_readme():
|
||||
arr = []
|
||||
if INDEX_JSON.exists():
|
||||
arr = json.loads(INDEX_JSON.read_text(encoding="utf-8"))
|
||||
counts = {c: 0 for c in CATEGORY_ORDER}
|
||||
projects = {}
|
||||
for x in arr:
|
||||
counts[x.get("category", "未分类")] = counts.get(x.get("category", "未分类"), 0) + 1
|
||||
projects.setdefault(x.get("category", "未分类"), set()).add(x.get("project", "unknown"))
|
||||
lines = [
|
||||
"# 青龙脚本分类库\n",
|
||||
"\n",
|
||||
"本仓库用于归档公开青龙脚本,并按运行端与凭证方式分类。\n",
|
||||
"\n",
|
||||
"## 分类\n",
|
||||
"\n",
|
||||
]
|
||||
for c in CATEGORY_ORDER:
|
||||
lines.append(f"- `{c}`:{counts.get(c,0)} 个脚本,{len(projects.get(c,set()))} 个项目\n")
|
||||
lines += [
|
||||
"\n",
|
||||
"## 目录规则\n",
|
||||
"\n",
|
||||
"```text\n",
|
||||
"脚本库/APP版/抓包/<项目>/YYYY-MM-DD_原文件名_<sha8>.ext\n",
|
||||
"脚本库/APP版/账密/<项目>/YYYY-MM-DD_原文件名_<sha8>.ext\n",
|
||||
"脚本库/web版/抓包/<项目>/YYYY-MM-DD_原文件名_<sha8>.ext\n",
|
||||
"脚本库/web版/账密/<项目>/YYYY-MM-DD_原文件名_<sha8>.ext\n",
|
||||
"脚本库/微信小程序/协议版/<项目>/YYYY-MM-DD_原文件名_<sha8>.ext\n",
|
||||
"脚本库/微信小程序/抓包版/<项目>/YYYY-MM-DD_原文件名_<sha8>.ext\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"## 元数据\n",
|
||||
"\n",
|
||||
"- `INDEX.csv`:脚本索引,含分类、项目、源仓库、源路径、源 URL、上传时间、SHA256。\n",
|
||||
"- `INDEX.json`:同上,JSON 格式。\n",
|
||||
"- 文件名中的日期优先使用源文件最近一次 commit 时间。\n",
|
||||
"- 相同代码以归一化 SHA256 去重。\n",
|
||||
"\n",
|
||||
"## 采集器\n",
|
||||
"\n",
|
||||
"运行:\n",
|
||||
"\n",
|
||||
"```bash\n",
|
||||
"python3 collector.py\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"可选环境变量:\n",
|
||||
"\n",
|
||||
"```bash\n",
|
||||
"export GITHUB_TOKEN=你的GitHubToken # 可提升 GitHub API 限额\n",
|
||||
"export MAX_REPOS_PER_QUERY=20\n",
|
||||
"export MAX_FILES_TOTAL=500\n",
|
||||
"```\n",
|
||||
]
|
||||
README.write_text("".join(lines), encoding="utf-8")
|
||||
|
||||
|
||||
def add_content_record(
|
||||
records: List[Record],
|
||||
seen: set,
|
||||
content: str,
|
||||
source_platform: str,
|
||||
source_repo: str,
|
||||
source_path: str,
|
||||
source_url: str,
|
||||
raw_url: str,
|
||||
uploaded_at: str,
|
||||
) -> bool:
|
||||
if not content or not looks_like_ql_script(content, source_path):
|
||||
return False
|
||||
sha = normalized_hash(content)
|
||||
if sha in seen:
|
||||
return False
|
||||
category, platform_type, auth_type, evidence = classify(content, source_path)
|
||||
project = extract_project(content, source_path)
|
||||
project_dir = OUT_DIR / category / project
|
||||
fname = unique_filename(project_dir, uploaded_at, Path(source_path).name, sha)
|
||||
saved_path = str((project_dir / fname).relative_to(ROOT))
|
||||
rec = Record(
|
||||
category=category,
|
||||
project=project,
|
||||
filename=fname,
|
||||
sha256=sha,
|
||||
source_platform=source_platform,
|
||||
source_repo=source_repo,
|
||||
source_path=source_path,
|
||||
source_url=source_url,
|
||||
raw_url=raw_url,
|
||||
uploaded_at=uploaded_at,
|
||||
saved_path=saved_path,
|
||||
auth_type=auth_type,
|
||||
platform_type=platform_type,
|
||||
evidence=evidence,
|
||||
)
|
||||
write_record_file(rec, content)
|
||||
records.append(rec)
|
||||
seen.add(sha)
|
||||
print(f" [ADD] {category} / {project} / {fname}")
|
||||
return True
|
||||
|
||||
|
||||
def collect_github(records: List[Record], seen: set, files_done: int) -> int:
|
||||
repos = search_github_repos()
|
||||
print(f"[INFO] github_repos={len(repos)}")
|
||||
for repo in repos:
|
||||
if files_done >= MAX_FILES_TOTAL:
|
||||
break
|
||||
full = repo.get("full_name")
|
||||
if not full:
|
||||
continue
|
||||
full = str(full)
|
||||
branch = str(repo.get("default_branch") or "main")
|
||||
print(f"[GITHUB_REPO] {full}")
|
||||
tree = list_github_tree(repo)
|
||||
candidates = [x for x in tree if x.get("type") == "blob" and is_candidate_path(x.get("path", ""))]
|
||||
candidates.sort(key=lambda x: (
|
||||
0 if re.search(r"(?i)(script|scripts|ql|青龙|jd_|wx_|applet|env)", x.get("path", "")) else 1,
|
||||
len(x.get("path", ""))
|
||||
))
|
||||
for item in candidates[:80]:
|
||||
if files_done >= MAX_FILES_TOTAL:
|
||||
break
|
||||
path = item.get("path", "")
|
||||
content, raw_url, html_url = get_file_content(full, path, branch)
|
||||
uploaded_at = get_file_uploaded_at(full, path, repo.get("pushed_at", "")) if content else ""
|
||||
if add_content_record(records, seen, content or "", "GitHub", full, path, html_url, raw_url, uploaded_at):
|
||||
files_done += 1
|
||||
return files_done
|
||||
|
||||
|
||||
def collect_gitee(records: List[Record], seen: set, files_done: int) -> int:
|
||||
repos = search_gitee_repos()
|
||||
print(f"[INFO] gitee_repos={len(repos)}")
|
||||
for repo in repos:
|
||||
if files_done >= MAX_FILES_TOTAL:
|
||||
break
|
||||
full = repo.get("full_name") or repo.get("path_with_namespace")
|
||||
if not full:
|
||||
continue
|
||||
full = str(full)
|
||||
branch = str(repo.get("default_branch") or "master")
|
||||
print(f"[GITEE_REPO] {full}")
|
||||
tree = list_gitee_tree(repo)
|
||||
branch = str(repo.get("default_branch") or branch)
|
||||
candidates = [x for x in tree if x.get("type") in ("blob", "file") and is_candidate_path(x.get("path", ""))]
|
||||
candidates.sort(key=lambda x: (
|
||||
0 if re.search(r"(?i)(script|scripts|ql|青龙|jd_|wx_|applet|env)", x.get("path", "")) else 1,
|
||||
len(x.get("path", ""))
|
||||
))
|
||||
for item in candidates[:80]:
|
||||
if files_done >= MAX_FILES_TOTAL:
|
||||
break
|
||||
path = item.get("path", "")
|
||||
content, raw_url, html_url = get_gitee_file_content(full, path, branch)
|
||||
uploaded_at = get_gitee_file_uploaded_at(full, path, repo.get("pushed_at", "")) if content else ""
|
||||
if add_content_record(records, seen, content or "", "Gitee", full, path, html_url, raw_url, uploaded_at):
|
||||
files_done += 1
|
||||
return files_done
|
||||
|
||||
|
||||
def collect_public_links(records: List[Record], seen: set, files_done: int) -> int:
|
||||
links = discover_public_code_links()
|
||||
print(f"[INFO] public_links={len(links)}")
|
||||
for item in links:
|
||||
if files_done >= MAX_FILES_TOTAL:
|
||||
break
|
||||
url = item.get("url", "")
|
||||
content, raw_url, html_url, uploaded_at = get_public_link_content(url)
|
||||
source_repo = urllib.parse.urlparse(url).netloc
|
||||
source_path = urllib.parse.urlparse(url).path.strip("/") or Path(url).name
|
||||
if add_content_record(records, seen, content or "", "PublicWeb", source_repo, source_path, html_url, raw_url, uploaded_at):
|
||||
files_done += 1
|
||||
return files_done
|
||||
|
||||
|
||||
|
||||
def rebuild_index_from_files():
|
||||
"""当采集被限流/中断后,可从已落盘脚本头部重建 INDEX。"""
|
||||
records = []
|
||||
for path in OUT_DIR.rglob("*"):
|
||||
if not path.is_file() or path.suffix.lower() not in VALID_SUFFIXES:
|
||||
continue
|
||||
text = path.read_text(encoding="utf-8", errors="ignore")
|
||||
head = "\n".join(text.splitlines()[:12])
|
||||
def pick(name):
|
||||
m = re.search(rf"{name}:\s*(.+)", head)
|
||||
return m.group(1).strip().lstrip("// ").strip() if m else ""
|
||||
rel = str(path.relative_to(ROOT))
|
||||
parts = path.relative_to(OUT_DIR).parts
|
||||
if len(parts) < 4:
|
||||
continue
|
||||
category = f"{parts[0]}/{parts[1]}" if parts[0] in {"APP版", "web版", "微信小程序"} else parts[0]
|
||||
project = parts[2] if len(parts) >= 4 else "unknown"
|
||||
rec = Record(
|
||||
category=category,
|
||||
project=project,
|
||||
filename=path.name,
|
||||
sha256=pick("SHA256") or normalized_hash(text),
|
||||
source_platform="GitHub",
|
||||
source_repo=pick("Repo"),
|
||||
source_path=pick("Path"),
|
||||
source_url=pick("Source"),
|
||||
raw_url=pick("Raw"),
|
||||
uploaded_at=pick("UploadedAt"),
|
||||
saved_path=rel,
|
||||
auth_type=category.split("/")[-1] if "/" in category else "未分类",
|
||||
platform_type=category.split("/")[0] if "/" in category else "未分类",
|
||||
evidence=pick("Evidence"),
|
||||
)
|
||||
records.append(rec)
|
||||
save_indexes(records)
|
||||
update_readme()
|
||||
print(f"[REBUILD] records={len(records)}")
|
||||
|
||||
|
||||
def main():
|
||||
OUT_DIR.mkdir(parents=True, exist_ok=True)
|
||||
META_DIR.mkdir(parents=True, exist_ok=True)
|
||||
seen = load_seen_hashes()
|
||||
records: List[Record] = []
|
||||
files_done = 0
|
||||
try:
|
||||
files_done = collect_github(records, seen, files_done)
|
||||
except RuntimeError as e:
|
||||
if str(e) == "github_rate_limited":
|
||||
print("[WARN] GitHub 限流,跳过 GitHub 剩余采集,继续其它来源")
|
||||
else:
|
||||
raise
|
||||
if files_done < MAX_FILES_TOTAL:
|
||||
files_done = collect_gitee(records, seen, files_done)
|
||||
if files_done < MAX_FILES_TOTAL:
|
||||
files_done = collect_public_links(records, seen, files_done)
|
||||
if records:
|
||||
save_indexes(records)
|
||||
update_readme()
|
||||
elif any(OUT_DIR.rglob("*")):
|
||||
rebuild_index_from_files()
|
||||
else:
|
||||
save_indexes(records)
|
||||
update_readme()
|
||||
print(f"[DONE] added={len(records)} total_files_done={files_done}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
176
脚本库/APP版/抓包/content/2026-05-19_content_45c4e352.js
Normal file
176
脚本库/APP版/抓包/content/2026-05-19_content_45c4e352.js
Normal file
@@ -0,0 +1,176 @@
|
||||
// # Source: https://github.com/huwangkeji/juejin_checkin/blob/main/juejin-extension/content.js
|
||||
// # Raw: https://raw.githubusercontent.com/huwangkeji/juejin_checkin/main/juejin-extension/content.js
|
||||
// # Repo: huwangkeji/juejin_checkin
|
||||
// # Path: juejin-extension/content.js
|
||||
// # UploadedAt: 2026-05-19T14:34:11Z
|
||||
// # SHA256: 45c4e3523ff88ee080e76c2c8b635c4a14657f9f97fa395d368b9bccf09b4bca
|
||||
// # Category: APP版/抓包
|
||||
// # Evidence: cookie/token/authorization/header
|
||||
//
|
||||
|
||||
/**
|
||||
* 掘金参数提取器 - Content Script (MAIN world)
|
||||
* 直接在页面主世界运行,hook 真实的 fetch/XHR,参数存到 sessionStorage
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
if (window.__JUEJIN_EXTRACTOR_HOOKED__) return;
|
||||
window.__JUEJIN_EXTRACTOR_HOOKED__ = true;
|
||||
|
||||
const STORAGE_KEY = '__juejin_extractor_data__';
|
||||
|
||||
function readStored() {
|
||||
try {
|
||||
return JSON.parse(sessionStorage.getItem(STORAGE_KEY) || '{}');
|
||||
} catch (e) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
function writeStored(data) {
|
||||
const existing = readStored();
|
||||
const merged = { ...existing, ...data };
|
||||
try {
|
||||
sessionStorage.setItem(STORAGE_KEY, JSON.stringify(merged));
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
function extractFromUrl(url) {
|
||||
try {
|
||||
const u = new URL(url);
|
||||
if (u.hostname === 'api.juejin.cn' || u.hostname.includes('juejin.cn')) {
|
||||
return {
|
||||
aid: u.searchParams.get('aid') || '',
|
||||
uuid: u.searchParams.get('uuid') || '',
|
||||
msToken: u.searchParams.get('msToken') || '',
|
||||
a_bogus: u.searchParams.get('a_bogus') || '',
|
||||
spider: u.searchParams.get('spider') || '',
|
||||
};
|
||||
}
|
||||
} catch (e) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
function mergeParams(params, cookie) {
|
||||
const data = readStored();
|
||||
let changed = false;
|
||||
|
||||
if (cookie && cookie.length > 10) {
|
||||
data.cookie = cookie;
|
||||
changed = true;
|
||||
}
|
||||
if (params.aid && params.aid !== 'null' && params.aid !== data.aid) {
|
||||
data.aid = params.aid;
|
||||
changed = true;
|
||||
}
|
||||
if (params.uuid && params.uuid.length > 5 && params.uuid !== data.uuid) {
|
||||
data.uuid = params.uuid;
|
||||
changed = true;
|
||||
}
|
||||
if (params.msToken && params.msToken.length > 5 && params.msToken !== data.msToken) {
|
||||
data.msToken = params.msToken;
|
||||
changed = true;
|
||||
}
|
||||
if (params.a_bogus && params.a_bogus.length > 5 && params.a_bogus !== data.a_bogus) {
|
||||
data.a_bogus = params.a_bogus;
|
||||
changed = true;
|
||||
}
|
||||
if (params.spider && params.spider !== data.spider) {
|
||||
data.spider = params.spider;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
data.captureTime = new Date().toLocaleString('zh-CN');
|
||||
writeStored(data);
|
||||
}
|
||||
}
|
||||
|
||||
// ===== Hook fetch =====
|
||||
const _origFetch = window.fetch;
|
||||
window.fetch = function fetchHook(input, init) {
|
||||
try {
|
||||
const url = typeof input === 'string' ? input : (input.url || input.toString());
|
||||
const params = extractFromUrl(url);
|
||||
if (params) {
|
||||
let cookie = '';
|
||||
try { cookie = document.cookie; } catch (e) {}
|
||||
mergeParams(params, cookie);
|
||||
}
|
||||
} catch (e) {}
|
||||
return _origFetch.apply(this, arguments);
|
||||
};
|
||||
|
||||
// ===== Hook XMLHttpRequest =====
|
||||
const _origOpen = XMLHttpRequest.prototype.open;
|
||||
const _origSend = XMLHttpRequest.prototype.send;
|
||||
|
||||
XMLHttpRequest.prototype.open = function(method, url) {
|
||||
this._juejinUrl = url;
|
||||
return _origOpen.apply(this, arguments);
|
||||
};
|
||||
|
||||
XMLHttpRequest.prototype.send = function(body) {
|
||||
try {
|
||||
if (this._juejinUrl) {
|
||||
const params = extractFromUrl(this._juejinUrl);
|
||||
if (params) {
|
||||
let cookie = '';
|
||||
try { cookie = document.cookie; } catch (e) {}
|
||||
mergeParams(params, cookie);
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
return _origSend.apply(this, arguments);
|
||||
};
|
||||
|
||||
// ===== 扫描 performance entries =====
|
||||
function scanPerf() {
|
||||
try {
|
||||
const entries = performance.getEntriesByType('resource');
|
||||
for (const entry of entries) {
|
||||
if (entry.name && entry.name.includes('api.juejin.cn')) {
|
||||
const params = extractFromUrl(entry.name);
|
||||
if (params) {
|
||||
let cookie = '';
|
||||
try { cookie = document.cookie; } catch (e) {}
|
||||
mergeParams(params, cookie);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
scanPerf();
|
||||
let count = 0;
|
||||
const timer = setInterval(() => {
|
||||
scanPerf();
|
||||
count++;
|
||||
if (count >= 20) clearInterval(timer);
|
||||
}, 2000);
|
||||
|
||||
// ===== 页面稳定后主动触发 harmless 请求 =====
|
||||
function triggerCapture() {
|
||||
try {
|
||||
const t = Date.now();
|
||||
_origFetch.call(window,
|
||||
`https://api.juejin.cn/growth_api/v1/get_today_status?aid=2608&t=${t}`,
|
||||
{ credentials: 'include', headers: { 'Accept': 'application/json' } }
|
||||
).catch(() => {});
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
setTimeout(triggerCapture, 1000);
|
||||
setTimeout(triggerCapture, 3000);
|
||||
});
|
||||
} else {
|
||||
setTimeout(triggerCapture, 1000);
|
||||
setTimeout(triggerCapture, 3000);
|
||||
}
|
||||
|
||||
console.log('[掘金参数提取器] Content script (MAIN world) 已注入');
|
||||
})();
|
||||
@@ -0,0 +1,292 @@
|
||||
// # Source: https://github.com/huwangkeji/juejin_checkin/blob/main/juejin-extension/popup.js
|
||||
// # Raw: https://raw.githubusercontent.com/huwangkeji/juejin_checkin/main/juejin-extension/popup.js
|
||||
// # Repo: huwangkeji/juejin_checkin
|
||||
// # Path: juejin-extension/popup.js
|
||||
// # UploadedAt: 2026-05-19T14:34:11Z
|
||||
// # SHA256: 0a4d49831a306fa984f62b0d1b3f26f7fc1274a625d08b5f4622ba94121b8469
|
||||
// # Category: web版/抓包
|
||||
// # Evidence: web/H5关键词 + cookie/token/header
|
||||
//
|
||||
|
||||
/**
|
||||
* 掘金参数提取器 - Popup脚本
|
||||
*/
|
||||
|
||||
// 参数配置:key、显示名、青龙环境变量名
|
||||
const PARAM_CONFIG = [
|
||||
{ key: 'cookie', name: 'Cookie', env: 'JUEJIN_COOKIE', isLong: true },
|
||||
{ key: 'aid', name: 'AID', env: 'JUEJIN_AID', isLong: false },
|
||||
{ key: 'uuid', name: 'UUID', env: 'JUEJIN_UUID', isLong: true },
|
||||
{ key: 'msToken', name: 'msToken', env: 'JUEJIN_MSTOKEN', isLong: true },
|
||||
{ key: 'a_bogus', name: 'a_bogus', env: 'JUEJIN_A_BOGUS', isLong: true },
|
||||
];
|
||||
|
||||
let currentData = null;
|
||||
|
||||
// 加载数据
|
||||
async function loadData() {
|
||||
return new Promise((resolve) => {
|
||||
chrome.storage.local.get('juejinData', (result) => {
|
||||
resolve(result.juejinData || null);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 渲染界面
|
||||
async function render() {
|
||||
currentData = await loadData();
|
||||
|
||||
const emptyState = document.getElementById('emptyState');
|
||||
const paramsList = document.getElementById('paramsList');
|
||||
const actionsBar = document.getElementById('actionsBar');
|
||||
const statusDot = document.getElementById('statusDot');
|
||||
const statusText = document.getElementById('statusText');
|
||||
const captureTime = document.getElementById('captureTime');
|
||||
|
||||
if (!currentData || !currentData.cookie) {
|
||||
// 无数据
|
||||
emptyState.style.display = 'block';
|
||||
paramsList.style.display = 'none';
|
||||
actionsBar.style.display = 'none';
|
||||
statusDot.className = 'status-dot empty';
|
||||
statusText.textContent = '等待捕获...';
|
||||
captureTime.textContent = '';
|
||||
return;
|
||||
}
|
||||
|
||||
// 有数据
|
||||
emptyState.style.display = 'none';
|
||||
paramsList.style.display = 'block';
|
||||
actionsBar.style.display = 'flex';
|
||||
statusDot.className = 'status-dot captured';
|
||||
statusText.textContent = '✅ 参数已捕获';
|
||||
captureTime.textContent = currentData.captureTime || '';
|
||||
|
||||
// 渲染参数列表
|
||||
paramsList.innerHTML = PARAM_CONFIG.map((config) => {
|
||||
const value = currentData[config.key] || '';
|
||||
const isEmpty = !value;
|
||||
const displayValue = isEmpty ? '未捕获到' : value;
|
||||
const valueClass = isEmpty ? 'param-value empty' : 'param-value';
|
||||
|
||||
return `
|
||||
<div class="param-item">
|
||||
<div class="param-header">
|
||||
<span class="param-name">${config.name}</span>
|
||||
<div style="display:flex;align-items:center;gap:6px;">
|
||||
<span class="param-env">${config.env}</span>
|
||||
<button class="copy-btn" data-key="${config.key}" title="复制${config.name}">复制</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="${valueClass}" title="${displayValue}">${displayValue}</div>
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
|
||||
// 绑定复制按钮
|
||||
paramsList.querySelectorAll('.copy-btn').forEach((btn) => {
|
||||
btn.addEventListener('click', () => {
|
||||
const key = btn.dataset.key;
|
||||
const value = currentData[key] || '';
|
||||
copyToClipboard(value, btn);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 复制到剪贴板
|
||||
function copyToClipboard(text, btn) {
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
if (btn) {
|
||||
const original = btn.textContent;
|
||||
btn.textContent = '已复制 ✓';
|
||||
btn.classList.add('copied');
|
||||
setTimeout(() => {
|
||||
btn.textContent = original;
|
||||
btn.classList.remove('copied');
|
||||
}, 1500);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 生成青龙面板环境变量格式
|
||||
function generateQinglongFormat() {
|
||||
if (!currentData) return '';
|
||||
|
||||
const lines = [];
|
||||
lines.push('# 掘金签到脚本 - 青龙面板环境变量');
|
||||
lines.push('# 复制以下内容到青龙面板 -> 环境变量');
|
||||
lines.push('');
|
||||
lines.push(`JUEJIN_COOKIE='${currentData.cookie || ''}'`);
|
||||
lines.push(`JUEJIN_AID='${currentData.aid || '2608'}'`);
|
||||
lines.push(`JUEJIN_UUID='${currentData.uuid || ''}'`);
|
||||
lines.push(`JUEJIN_MSTOKEN='${currentData.msToken || ''}'`);
|
||||
lines.push(`JUEJIN_A_BOGUS='${currentData.a_bogus || ''}'`);
|
||||
lines.push('');
|
||||
lines.push(`# 捕获时间: ${currentData.captureTime || '未知'}`);
|
||||
lines.push('# 参数有效期约30天,过期需重新获取');
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
// 绑定事件
|
||||
document.getElementById('copyAllBtn').addEventListener('click', () => {
|
||||
const text = generateQinglongFormat();
|
||||
copyToClipboard(text, document.getElementById('copyAllBtn'));
|
||||
});
|
||||
|
||||
document.getElementById('goJuejinBtn').addEventListener('click', () => {
|
||||
chrome.tabs.create({ url: 'https://juejin.cn' });
|
||||
});
|
||||
|
||||
document.getElementById('refreshBtn').addEventListener('click', () => {
|
||||
render();
|
||||
});
|
||||
|
||||
// "从当前页面提取"按钮
|
||||
document.getElementById('extractNowBtn').addEventListener('click', async () => {
|
||||
const btn = document.getElementById('extractNowBtn');
|
||||
const originalText = btn.textContent;
|
||||
btn.textContent = '⏳ 提取中...';
|
||||
btn.disabled = true;
|
||||
|
||||
try {
|
||||
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
|
||||
|
||||
if (!tab || !tab.url || !tab.url.includes('juejin.cn')) {
|
||||
alert('请先在掘金网站 (juejin.cn) 页面点击此按钮');
|
||||
btn.textContent = originalText;
|
||||
btn.disabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// 在页面中执行提取脚本:主动发请求 -> 等待 hook 捕获 -> 读取 sessionStorage
|
||||
const results = await chrome.scripting.executeScript({
|
||||
target: { tabId: tab.id, allFrames: false },
|
||||
world: 'MAIN',
|
||||
func: () => {
|
||||
return new Promise((resolve) => {
|
||||
const data = {
|
||||
cookie: '',
|
||||
aid: '',
|
||||
uuid: '',
|
||||
msToken: '',
|
||||
a_bogus: '',
|
||||
spider: '',
|
||||
captureTime: new Date().toLocaleString('zh-CN'),
|
||||
captureUrl: location.href,
|
||||
};
|
||||
|
||||
// 辅助:从 URL 提取参数
|
||||
function extractFromUrl(url) {
|
||||
try {
|
||||
const u = new URL(url);
|
||||
return {
|
||||
aid: u.searchParams.get('aid') || '',
|
||||
uuid: u.searchParams.get('uuid') || '',
|
||||
msToken: u.searchParams.get('msToken') || '',
|
||||
a_bogus: u.searchParams.get('a_bogus') || '',
|
||||
spider: u.searchParams.get('spider') || '',
|
||||
};
|
||||
} catch (e) { return null; }
|
||||
}
|
||||
|
||||
// 1. 获取 cookie
|
||||
try { data.cookie = document.cookie; } catch (e) {}
|
||||
|
||||
// 2. 扫描 performance entries
|
||||
try {
|
||||
const entries = performance.getEntriesByType('resource');
|
||||
for (const entry of entries) {
|
||||
if (entry.name && entry.name.includes('api.juejin.cn')) {
|
||||
const p = extractFromUrl(entry.name);
|
||||
if (p) {
|
||||
if (p.aid) data.aid = p.aid;
|
||||
if (p.uuid && p.uuid.length > 5) data.uuid = p.uuid;
|
||||
if (p.msToken && p.msToken.length > 5) data.msToken = p.msToken;
|
||||
if (p.a_bogus && p.a_bogus.length > 5) data.a_bogus = p.a_bogus;
|
||||
if (p.spider) data.spider = p.spider;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
// 3. 从 content script 的 sessionStorage 读取(如果 content.js 已捕获)
|
||||
try {
|
||||
const stored = JSON.parse(sessionStorage.getItem('__juejin_extractor_data__') || '{}');
|
||||
if (stored.cookie) data.cookie = stored.cookie;
|
||||
if (stored.aid) data.aid = stored.aid;
|
||||
if (stored.uuid) data.uuid = stored.uuid;
|
||||
if (stored.msToken) data.msToken = stored.msToken;
|
||||
if (stored.a_bogus) data.a_bogus = stored.a_bogus;
|
||||
if (stored.spider) data.spider = stored.spider;
|
||||
} catch (e) {}
|
||||
|
||||
// 4. 主动触发一个请求来诱捕参数(content.js 的 MAIN world hook 会捕获)
|
||||
const needsTrigger = !data.uuid || !data.msToken || !data.a_bogus;
|
||||
if (needsTrigger) {
|
||||
try {
|
||||
fetch('https://api.juejin.cn/growth_api/v1/get_today_status?aid=2608', {
|
||||
credentials: 'include',
|
||||
headers: { 'Accept': 'application/json' },
|
||||
}).catch(() => {});
|
||||
fetch('https://api.juejin.cn/user_api/v1/user/get?aid=2608', {
|
||||
credentials: 'include',
|
||||
headers: { 'Accept': 'application/json' },
|
||||
}).catch(() => {});
|
||||
} catch (e) {}
|
||||
|
||||
// 等待 hook 处理后再读取
|
||||
setTimeout(() => {
|
||||
try {
|
||||
const stored2 = JSON.parse(sessionStorage.getItem('__juejin_extractor_data__') || '{}');
|
||||
if (stored2.cookie) data.cookie = stored2.cookie;
|
||||
if (stored2.aid) data.aid = stored2.aid;
|
||||
if (stored2.uuid) data.uuid = stored2.uuid;
|
||||
if (stored2.msToken) data.msToken = stored2.msToken;
|
||||
if (stored2.a_bogus) data.a_bogus = stored2.a_bogus;
|
||||
if (stored2.spider) data.spider = stored2.spider;
|
||||
} catch (e) {}
|
||||
resolve(data);
|
||||
}, 800);
|
||||
} else {
|
||||
resolve(data);
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const extracted = results[0]?.result;
|
||||
if (extracted) {
|
||||
// 合并到已有数据
|
||||
chrome.storage.local.get('juejinData', (result) => {
|
||||
const existing = result.juejinData || {};
|
||||
const merged = {
|
||||
...existing,
|
||||
...Object.fromEntries(
|
||||
Object.entries(extracted).filter(([_, v]) => v && v !== '')
|
||||
),
|
||||
};
|
||||
chrome.storage.local.set({ juejinData: merged }, () => {
|
||||
render();
|
||||
btn.textContent = '✅ 提取完成';
|
||||
setTimeout(() => {
|
||||
btn.textContent = originalText;
|
||||
btn.disabled = false;
|
||||
}, 1500);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
alert('未能从当前页面提取到参数,请刷新页面后重试');
|
||||
btn.textContent = originalText;
|
||||
btn.disabled = false;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
alert('提取失败: ' + e.message);
|
||||
btn.textContent = originalText;
|
||||
btn.disabled = false;
|
||||
}
|
||||
});
|
||||
|
||||
// 初始渲染
|
||||
render();
|
||||
663
脚本库/web版/抓包/B站签到/2025-01-11_bilibili_906ceaaa.js
Normal file
663
脚本库/web版/抓包/B站签到/2025-01-11_bilibili_906ceaaa.js
Normal file
File diff suppressed because one or more lines are too long
574
脚本库/web版/抓包/notify/2025-01-11_notify_9961f576.py
Normal file
574
脚本库/web版/抓包/notify/2025-01-11_notify_9961f576.py
Normal file
@@ -0,0 +1,574 @@
|
||||
# Source: https://github.com/lksky8/sign-ql/blob/main/notify.py
|
||||
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/notify.py
|
||||
# Repo: lksky8/sign-ql
|
||||
# Path: notify.py
|
||||
# UploadedAt: 2025-01-11T18:39:35Z
|
||||
# SHA256: 9961f57695cfba609fbfda0c314ab632f147c0d068b0f0338eaaa1ef796eedf8
|
||||
# Category: web版/抓包
|
||||
# Evidence: web/H5关键词 + cookie/token/header
|
||||
|
||||
#!/usr/bin/env python3
|
||||
# _*_ coding:utf-8 _*_
|
||||
import base64
|
||||
import hashlib
|
||||
import hmac
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import threading
|
||||
import time
|
||||
import urllib.parse
|
||||
|
||||
import requests
|
||||
|
||||
# 原先的 print 函数和主线程的锁
|
||||
_print = print
|
||||
mutex = threading.Lock()
|
||||
|
||||
|
||||
# 定义新的 print 函数
|
||||
def print(text, *args, **kw):
|
||||
"""
|
||||
使输出有序进行,不出现多线程同一时间输出导致错乱的问题。
|
||||
"""
|
||||
with mutex:
|
||||
_print(text, *args, **kw)
|
||||
|
||||
|
||||
# 通知服务
|
||||
# fmt: off
|
||||
push_config = {
|
||||
'HITOKOTO': False, # 启用一言(随机句子)
|
||||
|
||||
'BARK_PUSH': '', # bark IP 或设备码,例:https://api.day.app/DxHcxxxxxRxxxxxxcm/
|
||||
'BARK_ARCHIVE': '', # bark 推送是否存档
|
||||
'BARK_GROUP': '', # bark 推送分组
|
||||
'BARK_SOUND': '', # bark 推送声音
|
||||
'BARK_ICON': '', # bark 推送图标
|
||||
|
||||
'CONSOLE': True, # 控制台输出
|
||||
|
||||
'DD_BOT_SECRET': '', # 钉钉机器人的 DD_BOT_SECRET
|
||||
'DD_BOT_TOKEN': '', # 钉钉机器人的 DD_BOT_TOKEN
|
||||
|
||||
'FSKEY': '', # 飞书机器人的 FSKEY
|
||||
|
||||
'GOBOT_URL': '', # go-cqhttp
|
||||
# 推送到个人QQ:http://127.0.0.1/send_private_msg
|
||||
# 群:http://127.0.0.1/send_group_msg
|
||||
'GOBOT_QQ': '', # go-cqhttp 的推送群或用户
|
||||
# GOBOT_URL 设置 /send_private_msg 时填入 user_id=个人QQ
|
||||
# /send_group_msg 时填入 group_id=QQ群
|
||||
'GOBOT_TOKEN': '', # go-cqhttp 的 access_token
|
||||
|
||||
'GOTIFY_URL': '', # gotify地址,如https://push.example.de:8080
|
||||
'GOTIFY_TOKEN': '', # gotify的消息应用token
|
||||
'GOTIFY_PRIORITY': 0, # 推送消息优先级,默认为0
|
||||
|
||||
'IGOT_PUSH_KEY': '', # iGot 聚合推送的 IGOT_PUSH_KEY
|
||||
|
||||
'PUSH_KEY': '', # server 酱的 PUSH_KEY,兼容旧版与 Turbo 版
|
||||
|
||||
'DEER_KEY': '', # PushDeer 的 PUSHDEER_KEY
|
||||
|
||||
'PUSH_PLUS_TOKEN': '', # push+ 微信推送的用户令牌
|
||||
'PUSH_PLUS_USER': '', # push+ 微信推送的群组编码
|
||||
|
||||
'QMSG_KEY': '', # qmsg 酱的 QMSG_KEY
|
||||
'QMSG_TYPE': '', # qmsg 酱的 QMSG_TYPE
|
||||
|
||||
'QYWX_AM': '', # 企业微信应用
|
||||
|
||||
'QYWX_KEY': '', # 企业微信机器人
|
||||
|
||||
'TG_BOT_TOKEN': '', # tg 机器人的 TG_BOT_TOKEN,例:1407203283:AAG9rt-6RDaaX0HBLZQq0laNOh898iFYaRQ
|
||||
'TG_USER_ID': '', # tg 机器人的 TG_USER_ID,例:1434078534
|
||||
'TG_API_HOST': '', # tg 代理 api
|
||||
'TG_PROXY_AUTH': '', # tg 代理认证参数
|
||||
'TG_PROXY_HOST': '', # tg 机器人的 TG_PROXY_HOST
|
||||
'TG_PROXY_PORT': '', # tg 机器人的 TG_PROXY_PORT
|
||||
}
|
||||
notify_function = []
|
||||
# fmt: on
|
||||
|
||||
# 首先读取 面板变量 或者 github action 运行变量
|
||||
for k in push_config:
|
||||
if os.getenv(k):
|
||||
v = os.getenv(k)
|
||||
push_config[k] = v
|
||||
|
||||
|
||||
def bark(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 bark 推送消息。
|
||||
"""
|
||||
if not push_config.get("BARK_PUSH"):
|
||||
print("bark 服务的 BARK_PUSH 未设置!!\n取消推送")
|
||||
return
|
||||
print("bark 服务启动")
|
||||
|
||||
if push_config.get("BARK_PUSH").startswith("http"):
|
||||
url = f'{push_config.get("BARK_PUSH")}/{urllib.parse.quote_plus(title)}/{urllib.parse.quote_plus(content)}'
|
||||
else:
|
||||
url = f'https://api.day.app/{push_config.get("BARK_PUSH")}/{urllib.parse.quote_plus(title)}/{urllib.parse.quote_plus(content)}'
|
||||
|
||||
bark_params = {
|
||||
"BARK_ARCHIVE": "isArchive",
|
||||
"BARK_GROUP": "group",
|
||||
"BARK_SOUND": "sound",
|
||||
"BARK_ICON": "icon",
|
||||
}
|
||||
params = ""
|
||||
for pair in filter(
|
||||
lambda pairs: pairs[0].startswith("BARK_")
|
||||
and pairs[0] != "BARK_PUSH"
|
||||
and pairs[1]
|
||||
and bark_params.get(pairs[0]),
|
||||
push_config.items(),
|
||||
):
|
||||
params += f"{bark_params.get(pair[0])}={pair[1]}&"
|
||||
if params:
|
||||
url = url + "?" + params.rstrip("&")
|
||||
response = requests.get(url).json()
|
||||
|
||||
if response["code"] == 200:
|
||||
print("bark 推送成功!")
|
||||
else:
|
||||
print("bark 推送失败!")
|
||||
|
||||
|
||||
def console(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 控制台 推送消息。
|
||||
"""
|
||||
print(f"{title}\n\n{content}")
|
||||
|
||||
|
||||
def dingding_bot(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 钉钉机器人 推送消息。
|
||||
"""
|
||||
if not push_config.get("DD_BOT_SECRET") or not push_config.get("DD_BOT_TOKEN"):
|
||||
print("钉钉机器人 服务的 DD_BOT_SECRET 或者 DD_BOT_TOKEN 未设置!!\n取消推送")
|
||||
return
|
||||
print("钉钉机器人 服务启动")
|
||||
|
||||
timestamp = str(round(time.time() * 1000))
|
||||
secret_enc = push_config.get("DD_BOT_SECRET").encode("utf-8")
|
||||
string_to_sign = "{}\n{}".format(timestamp, push_config.get("DD_BOT_SECRET"))
|
||||
string_to_sign_enc = string_to_sign.encode("utf-8")
|
||||
hmac_code = hmac.new(
|
||||
secret_enc, string_to_sign_enc, digestmod=hashlib.sha256
|
||||
).digest()
|
||||
sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
|
||||
url = f'https://oapi.dingtalk.com/robot/send?access_token={push_config.get("DD_BOT_TOKEN")}×tamp={timestamp}&sign={sign}'
|
||||
headers = {"Content-Type": "application/json;charset=utf-8"}
|
||||
data = {"msgtype": "text", "text": {"content": f"{title}\n\n{content}"}}
|
||||
response = requests.post(
|
||||
url=url, data=json.dumps(data), headers=headers, timeout=15
|
||||
).json()
|
||||
|
||||
if not response["errcode"]:
|
||||
print("钉钉机器人 推送成功!")
|
||||
else:
|
||||
print("钉钉机器人 推送失败!")
|
||||
|
||||
|
||||
def feishu_bot(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 飞书机器人 推送消息。
|
||||
"""
|
||||
if not push_config.get("FSKEY"):
|
||||
print("飞书 服务的 FSKEY 未设置!!\n取消推送")
|
||||
return
|
||||
print("飞书 服务启动")
|
||||
|
||||
url = f'https://open.feishu.cn/open-apis/bot/v2/hook/{push_config.get("FSKEY")}'
|
||||
data = {"msg_type": "text", "content": {"text": f"{title}\n\n{content}"}}
|
||||
response = requests.post(url, data=json.dumps(data)).json()
|
||||
|
||||
if response.get("StatusCode") == 0:
|
||||
print("飞书 推送成功!")
|
||||
else:
|
||||
print("飞书 推送失败!错误信息如下:\n", response)
|
||||
|
||||
|
||||
def go_cqhttp(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 go_cqhttp 推送消息。
|
||||
"""
|
||||
if not push_config.get("GOBOT_URL") or not push_config.get("GOBOT_QQ"):
|
||||
print("go-cqhttp 服务的 GOBOT_URL 或 GOBOT_QQ 未设置!!\n取消推送")
|
||||
return
|
||||
print("go-cqhttp 服务启动")
|
||||
|
||||
url = f'{push_config.get("GOBOT_URL")}?access_token={push_config.get("GOBOT_TOKEN")}&{push_config.get("GOBOT_QQ")}&message=标题:{title}\n内容:{content}'
|
||||
response = requests.get(url).json()
|
||||
|
||||
if response["status"] == "ok":
|
||||
print("go-cqhttp 推送成功!")
|
||||
else:
|
||||
print("go-cqhttp 推送失败!")
|
||||
|
||||
|
||||
def gotify(title:str,content:str) -> None:
|
||||
"""
|
||||
使用 gotify 推送消息。
|
||||
"""
|
||||
if not push_config.get("GOTIFY_URL") or not push_config.get("GOTIFY_TOKEN"):
|
||||
print("gotify 服务的 GOTIFY_URL 或 GOTIFY_TOKEN 未设置!!\n取消推送")
|
||||
return
|
||||
print("gotify 服务启动")
|
||||
|
||||
url = f'{push_config.get("GOTIFY_URL")}/message?token={push_config.get("GOTIFY_TOKEN")}'
|
||||
data = {"title": title,"message": content,"priority": push_config.get("GOTIFY_PRIORITY")}
|
||||
response = requests.post(url,data=data).json()
|
||||
|
||||
if response.get("id"):
|
||||
print("gotify 推送成功!")
|
||||
else:
|
||||
print("gotify 推送失败!")
|
||||
|
||||
|
||||
def iGot(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 iGot 推送消息。
|
||||
"""
|
||||
if not push_config.get("IGOT_PUSH_KEY"):
|
||||
print("iGot 服务的 IGOT_PUSH_KEY 未设置!!\n取消推送")
|
||||
return
|
||||
print("iGot 服务启动")
|
||||
|
||||
url = f'https://push.hellyw.com/{push_config.get("IGOT_PUSH_KEY")}'
|
||||
data = {"title": title, "content": content}
|
||||
headers = {"Content-Type": "application/x-www-form-urlencoded"}
|
||||
response = requests.post(url, data=data, headers=headers).json()
|
||||
|
||||
if response["ret"] == 0:
|
||||
print("iGot 推送成功!")
|
||||
else:
|
||||
print(f'iGot 推送失败!{response["errMsg"]}')
|
||||
|
||||
|
||||
def serverJ(title: str, content: str) -> None:
|
||||
"""
|
||||
通过 serverJ 推送消息。
|
||||
"""
|
||||
if not push_config.get("PUSH_KEY"):
|
||||
print("serverJ 服务的 PUSH_KEY 未设置!!\n取消推送")
|
||||
return
|
||||
print("serverJ 服务启动")
|
||||
|
||||
data = {"text": title, "desp": content.replace("\n", "\n\n")}
|
||||
if push_config.get("PUSH_KEY").index("SCT") != -1:
|
||||
url = f'https://sctapi.ftqq.com/{push_config.get("PUSH_KEY")}.send'
|
||||
else:
|
||||
url = f'https://sc.ftqq.com/${push_config.get("PUSH_KEY")}.send'
|
||||
response = requests.post(url, data=data).json()
|
||||
|
||||
if response.get("errno") == 0 or response.get("code") == 0:
|
||||
print("serverJ 推送成功!")
|
||||
else:
|
||||
print(f'serverJ 推送失败!错误码:{response["message"]}')
|
||||
|
||||
|
||||
def pushdeer(title: str, content: str) -> None:
|
||||
"""
|
||||
通过PushDeer 推送消息
|
||||
"""
|
||||
if not push_config.get("DEER_KEY"):
|
||||
print("PushDeer 服务的 DEER_KEY 未设置!!\n取消推送")
|
||||
return
|
||||
print("PushDeer 服务启动")
|
||||
data = {"text": title, "desp": content, "type": "markdown", "pushkey": push_config.get("DEER_KEY")}
|
||||
url = 'https://api2.pushdeer.com/message/push'
|
||||
response = requests.post(url, data=data).json()
|
||||
|
||||
if len(response.get("content").get("result")) > 0:
|
||||
print("PushDeer 推送成功!")
|
||||
else:
|
||||
print("PushDeer 推送失败!错误信息:", response)
|
||||
|
||||
|
||||
def pushplus_bot(title: str, content: str) -> None:
|
||||
"""
|
||||
通过 push+ 推送消息。
|
||||
"""
|
||||
if not push_config.get("PUSH_PLUS_TOKEN"):
|
||||
print("PUSHPLUS 服务的 PUSH_PLUS_TOKEN 未设置!!\n取消推送")
|
||||
return
|
||||
print("PUSHPLUS 服务启动")
|
||||
|
||||
url = "http://www.pushplus.plus/send"
|
||||
data = {
|
||||
"token": push_config.get("PUSH_PLUS_TOKEN"),
|
||||
"title": title,
|
||||
"content": content,
|
||||
"topic": push_config.get("PUSH_PLUS_USER"),
|
||||
}
|
||||
body = json.dumps(data).encode(encoding="utf-8")
|
||||
headers = {"Content-Type": "application/json"}
|
||||
response = requests.post(url=url, data=body, headers=headers).json()
|
||||
|
||||
if response["code"] == 200:
|
||||
print("PUSHPLUS 推送成功!")
|
||||
|
||||
else:
|
||||
|
||||
url_old = "http://pushplus.hxtrip.com/send"
|
||||
headers["Accept"] = "application/json"
|
||||
response = requests.post(url=url_old, data=body, headers=headers).json()
|
||||
|
||||
if response["code"] == 200:
|
||||
print("PUSHPLUS(hxtrip) 推送成功!")
|
||||
|
||||
else:
|
||||
print("PUSHPLUS 推送失败!")
|
||||
|
||||
|
||||
def qmsg_bot(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 qmsg 推送消息。
|
||||
"""
|
||||
if not push_config.get("QMSG_KEY") or not push_config.get("QMSG_TYPE"):
|
||||
print("qmsg 的 QMSG_KEY 或者 QMSG_TYPE 未设置!!\n取消推送")
|
||||
return
|
||||
print("qmsg 服务启动")
|
||||
|
||||
url = f'https://qmsg.zendee.cn/{push_config.get("QMSG_TYPE")}/{push_config.get("QMSG_KEY")}'
|
||||
payload = {"msg": f'{title}\n\n{content.replace("----", "-")}'.encode("utf-8")}
|
||||
response = requests.post(url=url, params=payload).json()
|
||||
|
||||
if response["code"] == 0:
|
||||
print("qmsg 推送成功!")
|
||||
else:
|
||||
print(f'qmsg 推送失败!{response["reason"]}')
|
||||
|
||||
|
||||
def wecom_app(title: str, content: str) -> None:
|
||||
"""
|
||||
通过 企业微信 APP 推送消息。
|
||||
"""
|
||||
if not push_config.get("QYWX_AM"):
|
||||
print("QYWX_AM 未设置!!\n取消推送")
|
||||
return
|
||||
QYWX_AM_AY = re.split(",", push_config.get("QYWX_AM"))
|
||||
if 4 < len(QYWX_AM_AY) > 5:
|
||||
print("QYWX_AM 设置错误!!\n取消推送")
|
||||
return
|
||||
print("企业微信 APP 服务启动")
|
||||
|
||||
corpid = QYWX_AM_AY[0]
|
||||
corpsecret = QYWX_AM_AY[1]
|
||||
touser = QYWX_AM_AY[2]
|
||||
agentid = QYWX_AM_AY[3]
|
||||
try:
|
||||
media_id = QYWX_AM_AY[4]
|
||||
except IndexError:
|
||||
media_id = ""
|
||||
wx = WeCom(corpid, corpsecret, agentid)
|
||||
# 如果没有配置 media_id 默认就以 text 方式发送
|
||||
if not media_id:
|
||||
message = title + "\n\n" + content
|
||||
response = wx.send_text(message, touser)
|
||||
else:
|
||||
response = wx.send_mpnews(title, content, media_id, touser)
|
||||
|
||||
if response == "ok":
|
||||
print("企业微信推送成功!")
|
||||
else:
|
||||
print("企业微信推送失败!错误信息如下:\n", response)
|
||||
|
||||
|
||||
class WeCom:
|
||||
def __init__(self, corpid, corpsecret, agentid):
|
||||
self.CORPID = corpid
|
||||
self.CORPSECRET = corpsecret
|
||||
self.AGENTID = agentid
|
||||
|
||||
def get_access_token(self):
|
||||
url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"
|
||||
values = {
|
||||
"corpid": self.CORPID,
|
||||
"corpsecret": self.CORPSECRET,
|
||||
}
|
||||
req = requests.post(url, params=values)
|
||||
data = json.loads(req.text)
|
||||
return data["access_token"]
|
||||
|
||||
def send_text(self, message, touser="@all"):
|
||||
send_url = (
|
||||
"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token="
|
||||
+ self.get_access_token()
|
||||
)
|
||||
send_values = {
|
||||
"touser": touser,
|
||||
"msgtype": "text",
|
||||
"agentid": self.AGENTID,
|
||||
"text": {"content": message},
|
||||
"safe": "0",
|
||||
}
|
||||
send_msges = bytes(json.dumps(send_values), "utf-8")
|
||||
respone = requests.post(send_url, send_msges)
|
||||
respone = respone.json()
|
||||
return respone["errmsg"]
|
||||
|
||||
def send_mpnews(self, title, message, media_id, touser="@all"):
|
||||
send_url = (
|
||||
"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token="
|
||||
+ self.get_access_token()
|
||||
)
|
||||
send_values = {
|
||||
"touser": touser,
|
||||
"msgtype": "mpnews",
|
||||
"agentid": self.AGENTID,
|
||||
"mpnews": {
|
||||
"articles": [
|
||||
{
|
||||
"title": title,
|
||||
"thumb_media_id": media_id,
|
||||
"author": "Author",
|
||||
"content_source_url": "",
|
||||
"content": message.replace("\n", "<br/>"),
|
||||
"digest": message,
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
send_msges = bytes(json.dumps(send_values), "utf-8")
|
||||
respone = requests.post(send_url, send_msges)
|
||||
respone = respone.json()
|
||||
return respone["errmsg"]
|
||||
|
||||
|
||||
def wecom_bot(title: str, content: str) -> None:
|
||||
"""
|
||||
通过 企业微信机器人 推送消息。
|
||||
"""
|
||||
if not push_config.get("QYWX_KEY"):
|
||||
print("企业微信机器人 服务的 QYWX_KEY 未设置!!\n取消推送")
|
||||
return
|
||||
print("企业微信机器人服务启动")
|
||||
|
||||
url = f"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key={push_config.get('QYWX_KEY')}"
|
||||
headers = {"Content-Type": "application/json;charset=utf-8"}
|
||||
data = {"msgtype": "text", "text": {"content": f"{title}\n\n{content}"}}
|
||||
response = requests.post(
|
||||
url=url, data=json.dumps(data), headers=headers, timeout=15
|
||||
).json()
|
||||
|
||||
if response["errcode"] == 0:
|
||||
print("企业微信机器人推送成功!")
|
||||
else:
|
||||
print("企业微信机器人推送失败!")
|
||||
|
||||
|
||||
def telegram_bot(title: str, content: str) -> None:
|
||||
"""
|
||||
使用 telegram 机器人 推送消息。
|
||||
"""
|
||||
if not push_config.get("TG_BOT_TOKEN") or not push_config.get("TG_USER_ID"):
|
||||
print("tg 服务的 bot_token 或者 user_id 未设置!!\n取消推送")
|
||||
return
|
||||
print("tg 服务启动")
|
||||
|
||||
if push_config.get("TG_API_HOST"):
|
||||
url = f"https://{push_config.get('TG_API_HOST')}/bot{push_config.get('TG_BOT_TOKEN')}/sendMessage"
|
||||
else:
|
||||
url = (
|
||||
f"https://api.telegram.org/bot{push_config.get('TG_BOT_TOKEN')}/sendMessage"
|
||||
)
|
||||
headers = {"Content-Type": "application/x-www-form-urlencoded"}
|
||||
payload = {
|
||||
"chat_id": str(push_config.get("TG_USER_ID")),
|
||||
"text": f"{title}\n\n{content}",
|
||||
"disable_web_page_preview": "true",
|
||||
}
|
||||
proxies = None
|
||||
if push_config.get("TG_PROXY_HOST") and push_config.get("TG_PROXY_PORT"):
|
||||
if push_config.get("TG_PROXY_AUTH") is not None and "@" not in push_config.get(
|
||||
"TG_PROXY_HOST"
|
||||
):
|
||||
push_config["TG_PROXY_HOST"] = (
|
||||
push_config.get("TG_PROXY_AUTH")
|
||||
+ "@"
|
||||
+ push_config.get("TG_PROXY_HOST")
|
||||
)
|
||||
proxyStr = "http://{}:{}".format(
|
||||
push_config.get("TG_PROXY_HOST"), push_config.get("TG_PROXY_PORT")
|
||||
)
|
||||
proxies = {"http": proxyStr, "https": proxyStr}
|
||||
response = requests.post(
|
||||
url=url, headers=headers, params=payload, proxies=proxies
|
||||
).json()
|
||||
|
||||
if response["ok"]:
|
||||
print("tg 推送成功!")
|
||||
else:
|
||||
print("tg 推送失败!")
|
||||
|
||||
|
||||
def one() -> str:
|
||||
"""
|
||||
获取一条一言。
|
||||
:return:
|
||||
"""
|
||||
url = "https://v1.hitokoto.cn/"
|
||||
res = requests.get(url).json()
|
||||
return res["hitokoto"] + " ----" + res["from"]
|
||||
|
||||
|
||||
if push_config.get("BARK_PUSH"):
|
||||
notify_function.append(bark)
|
||||
if push_config.get("CONSOLE"):
|
||||
notify_function.append(console)
|
||||
if push_config.get("DD_BOT_TOKEN") and push_config.get("DD_BOT_SECRET"):
|
||||
notify_function.append(dingding_bot)
|
||||
if push_config.get("FSKEY"):
|
||||
notify_function.append(feishu_bot)
|
||||
if push_config.get("GOBOT_URL") and push_config.get("GOBOT_QQ"):
|
||||
notify_function.append(go_cqhttp)
|
||||
if push_config.get("GOTIFY_URL") and push_config.get("GOTIFY_TOKEN"):
|
||||
notify_function.append(gotify)
|
||||
if push_config.get("IGOT_PUSH_KEY"):
|
||||
notify_function.append(iGot)
|
||||
if push_config.get("PUSH_KEY"):
|
||||
notify_function.append(serverJ)
|
||||
if push_config.get("DEER_KEY"):
|
||||
notify_function.append(pushdeer)
|
||||
if push_config.get("PUSH_PLUS_TOKEN"):
|
||||
notify_function.append(pushplus_bot)
|
||||
if push_config.get("QMSG_KEY") and push_config.get("QMSG_TYPE"):
|
||||
notify_function.append(qmsg_bot)
|
||||
if push_config.get("QYWX_AM"):
|
||||
notify_function.append(wecom_app)
|
||||
if push_config.get("QYWX_KEY"):
|
||||
notify_function.append(wecom_bot)
|
||||
if push_config.get("TG_BOT_TOKEN") and push_config.get("TG_USER_ID"):
|
||||
notify_function.append(telegram_bot)
|
||||
|
||||
|
||||
def send(title: str, content: str) -> None:
|
||||
if not content:
|
||||
print(f"{title} 推送内容为空!")
|
||||
return
|
||||
|
||||
hitokoto = push_config.get("HITOKOTO")
|
||||
|
||||
text = one() if hitokoto else ""
|
||||
content += "\n\n" + text
|
||||
|
||||
ts = [
|
||||
threading.Thread(target=mode, args=(title, content), name=mode.__name__)
|
||||
for mode in notify_function
|
||||
]
|
||||
[t.start() for t in ts]
|
||||
[t.join() for t in ts]
|
||||
|
||||
|
||||
def main():
|
||||
send("title", "content")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
483
脚本库/web版/抓包/query/2026-05-11_ks_query_848504df.py
Normal file
483
脚本库/web版/抓包/query/2026-05-11_ks_query_848504df.py
Normal file
@@ -0,0 +1,483 @@
|
||||
# Source: https://github.com/DearSong15/ql-scripts/blob/main/ks_query.py
|
||||
# Raw: https://raw.githubusercontent.com/DearSong15/ql-scripts/main/ks_query.py
|
||||
# Repo: DearSong15/ql-scripts
|
||||
# Path: ks_query.py
|
||||
# UploadedAt: 2026-05-11T14:51:55Z
|
||||
# SHA256: 848504df99018b6b2f9d7bac940671dc65777b8d973c1610e2a3111c88d36480
|
||||
# Category: web版/抓包
|
||||
# Evidence: web/H5关键词 + cookie/token/header
|
||||
|
||||
import json
|
||||
import os
|
||||
import requests
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
from openpyxl import Workbook
|
||||
from openpyxl.styles import Alignment, Font, PatternFill
|
||||
|
||||
|
||||
|
||||
def print_disclaimer():
|
||||
"""打印免责声明"""
|
||||
print("=" * 60)
|
||||
print("【免责声明】")
|
||||
print("1. 本程序仅为技术学习和个人账号信息查询使用,请勿用于商业用途或非法操作。")
|
||||
print("2. 使用本程序需确保您对所查询的快手账号拥有合法所有权或使用权,严禁查询他人账号信息。")
|
||||
print("3. 快手平台API可能随时变更,导致程序无法正常运行,开发者不保证程序的稳定性和可用性。")
|
||||
print("4. 任何因使用本程序违反快手平台用户协议、法律法规或侵犯他人权益的行为,均由使用者自行承担全部责任。")
|
||||
print("5. 开发者对使用本程序产生的任何直接或间接损失不承担任何法律责任。")
|
||||
print("6. 本程序为临时查询工具,建议您在使用完毕后24小时内删除程序及相关账号配置信息,以保障账号安全。")
|
||||
print("确认了解并同意以上条款后,程序将继续运行...")
|
||||
print("快手极速版以及普通版本cookie有的账号是通用的普通版(kpn=KUAISHOU) 极速版(kpn=NEBULA)更改cookie的kpn即可")
|
||||
print("\n请设置环境变量 ksck,格式为:")
|
||||
print("备注#cookie#salt#ip|端口|用户名|密码|到期日期")
|
||||
print("=" * 60 + "\n")
|
||||
|
||||
|
||||
# 比率映射关系
|
||||
RATIO_MAP = {
|
||||
19: 0.00009,
|
||||
28: 0.00008,
|
||||
37: 0.00007,
|
||||
46: 0.00006,
|
||||
55: 0.00005,
|
||||
64: 0.00004,
|
||||
73: 0.00003,
|
||||
82: 0.00002,
|
||||
91: 0.00001
|
||||
}
|
||||
|
||||
# 读取环境变量中的参数,默认46
|
||||
SELECTED_PARAM = int(os.getenv("RATIO_PARAM", 46))
|
||||
|
||||
|
||||
class KuaishouClient:
|
||||
def __init__(self, index, cookie, remark=""):
|
||||
self.index = index
|
||||
self.remark = remark
|
||||
self.cookie = cookie
|
||||
self.user_name = "未知用户"
|
||||
|
||||
# 余额信息
|
||||
self.coin_balance = 0
|
||||
self.cash_balance = 0
|
||||
self.total_balance = 0
|
||||
|
||||
# 今日和昨日金币
|
||||
self.today_coin = 0
|
||||
self.yesterday_coin = 0
|
||||
|
||||
# 兑换后金额
|
||||
self.today_coin_cash = 0
|
||||
self.yesterday_coin_cash = 0
|
||||
|
||||
# 流水记录
|
||||
self.coin_records = []
|
||||
self.cash_records = []
|
||||
|
||||
# 基础配置
|
||||
self.headers = {
|
||||
'User-Agent': "Mozilla/5.0 (Linux; Android 16; PTP-AN00 Build/HONORPTP-AN00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/139.0.7258.158 Mobile Safari/537.36 Yoda/3.2.17-rc2 Kwai/13.9.30.44872 OS_PRO_BIT/64 MAX_PHY_MEM/15272 KDT/PHONE AZPREFIX/az1 ICFO/0 StatusHT/38 TitleHT/44 NetType/NR ISLP/0 ISDM/0 ISLB/0 locale/zh-cn SHP/2665 SWP/1264 SD/3.5 CT/0 ISLM/0",
|
||||
'Accept-Encoding': "gzip, deflate, br, zstd",
|
||||
'sec-ch-ua-platform': "\"Android\"",
|
||||
'sec-ch-ua': "\"Not;A=Brand\";v=\"99\", \"Android WebView\";v=\"139\", \"Chromium\";v=\"139\"",
|
||||
'sec-ch-ua-mobile': "?1",
|
||||
'X-Requested-With': "com.smile.gifmaker",
|
||||
'Sec-Fetch-Site': "same-origin",
|
||||
'Sec-Fetch-Mode': "cors",
|
||||
'Sec-Fetch-Dest': "empty",
|
||||
'Referer': "https://encourage.kuaishou.com/kwai/profit?tab=coin&layoutType=4",
|
||||
'Accept-Language': "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
|
||||
'Cookie': self.cookie
|
||||
}
|
||||
|
||||
def send_request(self, url, method="get", params=None):
|
||||
"""发送请求"""
|
||||
try:
|
||||
if method == "get":
|
||||
response = requests.get(url, headers=self.headers, params=params, timeout=10)
|
||||
else:
|
||||
response = requests.post(url, headers=self.headers, data=params, timeout=10)
|
||||
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
else:
|
||||
print(f"请求失败,状态码: {response.status_code}")
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"请求异常: {e}")
|
||||
return None
|
||||
|
||||
def query_withdraw_info(self):
|
||||
"""查询提现信息(包含用户名和余额)"""
|
||||
url = "https://encourage.kuaishou.com/rest/wd/encourage/account/withdraw/info"
|
||||
params = {
|
||||
"source": "normal",
|
||||
"imei": "",
|
||||
"oaid": "279b0911-a941-4e80-b5fd-91f1c1ea2644",
|
||||
"idfa": ""
|
||||
}
|
||||
|
||||
result = self.send_request(url, params=params)
|
||||
if result and result.get("result") == 1:
|
||||
data = result.get("data", {})
|
||||
|
||||
# 获取用户名
|
||||
self.user_name = data.get("nickname", "未知用户")
|
||||
|
||||
# 获取账户信息
|
||||
account = data.get("account", {})
|
||||
self.coin_balance = account.get("coinAmount", 0)
|
||||
self.cash_balance = account.get("cashAmount", 0) # 单位:分
|
||||
self.total_balance = account.get("accumulativeAmount", 0) # 单位:分
|
||||
|
||||
return True
|
||||
return False
|
||||
|
||||
def query_cash_records(self):
|
||||
"""查询现金流水记录"""
|
||||
url = "https://encourage.kuaishou.com/rest/wd/encourage/account/detail"
|
||||
params = {
|
||||
"__NS_sig3": "6272350512f90404a43e5b3d3a3b5b3320a219ee1616ba201b5f2d2d2b2b28291636",
|
||||
"sigCatVer": "1",
|
||||
"accountType": "cash",
|
||||
"cursor": ""
|
||||
}
|
||||
|
||||
result = self.send_request(url, params=params)
|
||||
if result and result.get("result") == 1:
|
||||
data = result.get("data", {})
|
||||
records = data.get("datas", [])
|
||||
|
||||
for record in records[:3]:
|
||||
self.cash_records.append({
|
||||
'time': self._format_timestamp(record.get("createTime", 0)),
|
||||
'title': record.get("title", ""),
|
||||
'amount': record.get("displayAmount", "0"),
|
||||
'direction': record.get("direction", "")
|
||||
})
|
||||
return True
|
||||
return False
|
||||
|
||||
def query_coin_records(self):
|
||||
"""查询金币流水记录"""
|
||||
url = "https://encourage.kuaishou.com/rest/wd/encourage/account/detail"
|
||||
params = {
|
||||
"__NS_sig3": "7262251502e91414b42e4a2d2a2b6006895f03fe0606aa3024c33d3d3b3b38390626",
|
||||
"sigCatVer": "1",
|
||||
"accountType": "coin",
|
||||
"cursor": ""
|
||||
}
|
||||
|
||||
result = self.send_request(url, params=params)
|
||||
if result and result.get("result") == 1:
|
||||
data = result.get("data", {})
|
||||
records = data.get("datas", [])
|
||||
|
||||
for record in records[:3]:
|
||||
self.coin_records.append({
|
||||
'time': self._format_timestamp(record.get("createTime", 0)),
|
||||
'title': record.get("title", ""),
|
||||
'amount': record.get("displayAmount", "0"),
|
||||
'direction': record.get("direction", "")
|
||||
})
|
||||
return True
|
||||
return False
|
||||
|
||||
def _format_timestamp(self, timestamp):
|
||||
"""格式化时间戳"""
|
||||
if timestamp:
|
||||
try:
|
||||
dt = datetime.fromtimestamp(timestamp / 1000)
|
||||
return dt.strftime("%Y-%m-%d %H:%M")
|
||||
except:
|
||||
return "未知时间"
|
||||
return "未知时间"
|
||||
|
||||
def calculate_coin_stats(self):
|
||||
"""计算今日和昨日金币收入及兑换后金额"""
|
||||
today = datetime.now().date()
|
||||
yesterday = today - timedelta(days=1)
|
||||
|
||||
self.today_coin = 0
|
||||
self.yesterday_coin = 0
|
||||
|
||||
url = "https://encourage.kuaishou.com/rest/wd/encourage/account/detail"
|
||||
params = {
|
||||
"__NS_sig3": "7262251502e91414b42e4a2d2a2b6006895f03fe0606aa3024c33d3d3b3b38390626",
|
||||
"sigCatVer": "1",
|
||||
"accountType": "coin",
|
||||
"cursor": ""
|
||||
}
|
||||
|
||||
result = self.send_request(url, params=params)
|
||||
if result and result.get("result") == 1:
|
||||
data = result.get("data", {})
|
||||
records = data.get("datas", [])
|
||||
|
||||
for record in records:
|
||||
if record.get("direction") != "IN":
|
||||
continue
|
||||
|
||||
amount = record.get("amount", 0)
|
||||
create_time = record.get("createTime", 0)
|
||||
|
||||
if create_time:
|
||||
record_date = datetime.fromtimestamp(create_time / 1000).date()
|
||||
|
||||
if record_date == today:
|
||||
self.today_coin += amount
|
||||
elif record_date == yesterday:
|
||||
self.yesterday_coin += amount
|
||||
|
||||
# 计算兑换后金额
|
||||
ratio = RATIO_MAP.get(SELECTED_PARAM, 0.00006) # 默认46对应的比率
|
||||
self.today_coin_cash = round(self.today_coin * ratio, 2)
|
||||
self.yesterday_coin_cash = round(self.yesterday_coin * ratio, 2)
|
||||
|
||||
return True
|
||||
|
||||
def query_all_data(self):
|
||||
"""查询所有数据"""
|
||||
print(f"正在查询账号[{self.index}] {self.remark}...")
|
||||
|
||||
# 查询提现信息(包含用户名和余额)
|
||||
if not self.query_withdraw_info():
|
||||
print(f"账号[{self.index}] {self.remark} 提现信息查询失败")
|
||||
return False
|
||||
|
||||
# 查询现金流水
|
||||
if not self.query_cash_records():
|
||||
print(f"账号[{self.index}] {self.remark} 现金流水查询失败")
|
||||
|
||||
# 查询金币流水
|
||||
if not self.query_coin_records():
|
||||
print(f"账号[{self.index}] {self.remark} 金币流水查询失败")
|
||||
|
||||
# 计算金币统计
|
||||
self.calculate_coin_stats()
|
||||
|
||||
return True
|
||||
|
||||
def get_display_data(self):
|
||||
"""获取显示数据"""
|
||||
# 现金余额从分转换为元
|
||||
cash_yuan = self.cash_balance / 100 if self.cash_balance else 0
|
||||
total_yuan = self.total_balance / 100 if self.total_balance else 0
|
||||
|
||||
return {
|
||||
"index": self.index,
|
||||
"user_name": self.user_name,
|
||||
"remark": self.remark,
|
||||
"today_coin": self.today_coin,
|
||||
"yesterday_coin": self.yesterday_coin,
|
||||
"today_coin_cash": self.today_coin_cash,
|
||||
"yesterday_coin_cash": self.yesterday_coin_cash,
|
||||
"coin_balance": self.coin_balance,
|
||||
"cash_balance": round(cash_yuan, 2),
|
||||
"total_balance": round(total_yuan, 2),
|
||||
"coin_records": self.coin_records,
|
||||
"cash_records": self.cash_records,
|
||||
"ratio_param": SELECTED_PARAM
|
||||
}
|
||||
|
||||
|
||||
def load_cookies_from_env():
|
||||
"""从环境变量ksck加载cookie配置,格式:备注#cookie#salt#ip|端口|用户名|密码|到期日期"""
|
||||
cookies = []
|
||||
|
||||
ksck_env = os.getenv('ksck')
|
||||
if not ksck_env:
|
||||
print("未找到环境变量 ksck")
|
||||
return cookies
|
||||
|
||||
lines = ksck_env.strip().split('&')
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
|
||||
parts = line.split('#')
|
||||
if len(parts) < 3:
|
||||
print(f"第{i + 1}行格式错误,跳过: {line}")
|
||||
continue
|
||||
|
||||
remark = parts[0].strip()
|
||||
cookie = parts[1].strip()
|
||||
salt = parts[2].strip() # 暂时不使用
|
||||
|
||||
if not cookie:
|
||||
print(f"第{i + 1}行cookie为空,跳过")
|
||||
continue
|
||||
|
||||
# 不再检查socName,直接添加
|
||||
cookies.append({
|
||||
"cookie": cookie,
|
||||
"remark": remark
|
||||
})
|
||||
|
||||
print(f"从环境变量 ksck 加载了 {len(cookies)} 个账号")
|
||||
return cookies
|
||||
|
||||
|
||||
def create_excel_summary(data_list, filename="快手金币数据汇总.xlsx"):
|
||||
"""创建Excel汇总表格"""
|
||||
wb = Workbook()
|
||||
ws = wb.active
|
||||
ws.title = "金币数据汇总"
|
||||
|
||||
# 设置表头
|
||||
headers = ["序号", "用户名", "备注", "今日金币", "昨日金币", "当前金币",
|
||||
f"今日{SELECTED_PARAM}后(元)", f"昨日{SELECTED_PARAM}后(元)", "当前现金(元)", "累计收益(元)",
|
||||
"最近金币流水", "最近现金流水"]
|
||||
|
||||
for col, header in enumerate(headers, 1):
|
||||
cell = ws.cell(row=1, column=col)
|
||||
cell.value = header
|
||||
cell.font = Font(bold=True)
|
||||
cell.alignment = Alignment(horizontal="center")
|
||||
cell.fill = PatternFill(start_color="E6F3FF", end_color="E6F3FF", fill_type="solid")
|
||||
|
||||
# 填充数据
|
||||
for row, data in enumerate(data_list, 2):
|
||||
ws.cell(row=row, column=1, value=data["index"]).alignment = Alignment(horizontal="center")
|
||||
ws.cell(row=row, column=2, value=data["user_name"])
|
||||
ws.cell(row=row, column=3, value=data["remark"])
|
||||
ws.cell(row=row, column=4, value=data["today_coin"]).alignment = Alignment(horizontal="right")
|
||||
ws.cell(row=row, column=5, value=data["yesterday_coin"]).alignment = Alignment(horizontal="right")
|
||||
ws.cell(row=row, column=6, value=data["coin_balance"]).alignment = Alignment(horizontal="right")
|
||||
ws.cell(row=row, column=7, value=data["today_coin_cash"]).alignment = Alignment(horizontal="right")
|
||||
ws.cell(row=row, column=8, value=data["yesterday_coin_cash"]).alignment = Alignment(horizontal="right")
|
||||
ws.cell(row=row, column=9, value=data["cash_balance"]).alignment = Alignment(horizontal="right")
|
||||
ws.cell(row=row, column=10, value=data["total_balance"]).alignment = Alignment(horizontal="right")
|
||||
|
||||
# 格式化流水记录
|
||||
coin_flow = "\n".join([f"{r['time']} {r['title']} +{r['amount']}" for r in data["coin_records"]])
|
||||
cash_flow = "\n".join([f"{r['time']} {r['title']} {r['amount']}元" for r in data["cash_records"]])
|
||||
|
||||
ws.cell(row=row, column=11, value=coin_flow)
|
||||
ws.cell(row=row, column=12, value=cash_flow)
|
||||
|
||||
# 设置列宽
|
||||
column_widths = {
|
||||
'A': 8, # 序号
|
||||
'B': 20, # 用户名
|
||||
'C': 20, # 备注
|
||||
'D': 12, # 今日金币
|
||||
'E': 12, # 昨日金币
|
||||
'F': 12, # 当前金币
|
||||
'G': 18, # 今日兑换后
|
||||
'H': 18, # 昨日兑换后
|
||||
'I': 15, # 当前现金
|
||||
'J': 15, # 累计收益
|
||||
'K': 30, # 最近金币流水
|
||||
'L': 30 # 最近现金流水
|
||||
}
|
||||
|
||||
for col, width in column_widths.items():
|
||||
ws.column_dimensions[col].width = width
|
||||
|
||||
# 设置行高
|
||||
for row in range(2, len(data_list) + 2):
|
||||
ws.row_dimensions[row].height = 60
|
||||
|
||||
# 保存文件
|
||||
wb.save(filename)
|
||||
print(f"\nExcel表格已生成: {filename}")
|
||||
|
||||
# 打印汇总统计
|
||||
total_today = sum(data["today_coin"] for data in data_list)
|
||||
total_yesterday = sum(data["yesterday_coin"] for data in data_list)
|
||||
total_today_cash = sum(data["today_coin_cash"] for data in data_list)
|
||||
total_yesterday_cash = sum(data["yesterday_coin_cash"] for data in data_list)
|
||||
total_coins = sum(data["coin_balance"] for data in data_list)
|
||||
total_cash = sum(data["cash_balance"] for data in data_list)
|
||||
total_accumulative = sum(data["total_balance"] for data in data_list)
|
||||
|
||||
ratio = RATIO_MAP.get(SELECTED_PARAM, 0.00006)
|
||||
print(f"\n汇总统计 (使用比率参数 {SELECTED_PARAM}, 比率: {ratio}):")
|
||||
print(f"今日金币总数: {total_today}")
|
||||
print(f"今日金币兑换后: {total_today_cash}元")
|
||||
print(f"昨日金币总数: {total_yesterday}")
|
||||
print(f"昨日金币兑换后: {total_yesterday_cash}元")
|
||||
print(f"当前金币总数: {total_coins}")
|
||||
print(f"当前现金总数: {total_cash}元")
|
||||
print(f"累计收益总数: {total_accumulative}元")
|
||||
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
print_disclaimer()
|
||||
print("开始查询快手账号数据...")
|
||||
print("=" * 50)
|
||||
print(f"当前使用比率参数: {SELECTED_PARAM}, 兑换比率: {RATIO_MAP.get(SELECTED_PARAM, 0.00006)}")
|
||||
print("=" * 50)
|
||||
|
||||
# 从环境变量加载cookie配置
|
||||
cookies_config = load_cookies_from_env()
|
||||
|
||||
if not cookies_config:
|
||||
print("错误: 未找到有效的cookie配置")
|
||||
print("\n请设置环境变量 ksck,格式为:")
|
||||
print("备注#cookie#salt#ip|端口|用户名|密码|到期日期")
|
||||
print("每行一个账号,用&分隔,例如:")
|
||||
print("我的账号1#kuaishou.api_st=xxx; token=xxx#salt1#&我的账号2#kuaishou.api_st=yyy; token=yyy#salt2#")
|
||||
return
|
||||
|
||||
all_data = []
|
||||
success_count = 0
|
||||
|
||||
for i, account in enumerate(cookies_config):
|
||||
if not account.get("cookie"):
|
||||
print(f"账号[{i + 1}] cookie为空,跳过")
|
||||
continue
|
||||
|
||||
client = KuaishouClient(
|
||||
index=i + 1,
|
||||
cookie=account["cookie"],
|
||||
remark=account["remark"]
|
||||
)
|
||||
|
||||
if client.query_all_data():
|
||||
data = client.get_display_data()
|
||||
all_data.append(data)
|
||||
success_count += 1
|
||||
|
||||
# 打印单个账号信息
|
||||
print(f"\n账号[{i + 1}] 用户名: {data['user_name']} 备注: {account['remark']} 查询成功:")
|
||||
print(f" 今日金币: {data['today_coin']} → {data['today_coin_cash']}元")
|
||||
print(f" 昨日金币: {data['yesterday_coin']} → {data['yesterday_coin_cash']}元")
|
||||
print(f" 当前金币: {data['coin_balance']}")
|
||||
print(f" 当前现金: {data['cash_balance']}元")
|
||||
print(f" 累计收益: {data['total_balance']}元")
|
||||
|
||||
if data['coin_records']:
|
||||
print(" 最近金币流水:")
|
||||
for record in data['coin_records']:
|
||||
print(f" {record['time']} {record['title']} +{record['amount']}")
|
||||
|
||||
if data['cash_records']:
|
||||
print(" 最近现金流水:")
|
||||
for record in data['cash_records']:
|
||||
print(f" {record['time']} {record['title']} {record['amount']}元")
|
||||
else:
|
||||
print(f"\n账号[{i + 1}] {account['remark']} 查询失败")
|
||||
|
||||
# 添加0.5秒延迟,避免请求过于频繁
|
||||
if i < len(cookies_config) - 1: # 最后一个账号不需要延迟
|
||||
print("等待0.5秒后继续下一个账号...")
|
||||
time.sleep(0.5)
|
||||
|
||||
# 生成Excel表格
|
||||
if all_data:
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
filename = f"快手金币数据汇总_{SELECTED_PARAM}后_{timestamp}.xlsx"
|
||||
create_excel_summary(all_data, filename)
|
||||
print(f"\n成功查询 {success_count}/{len(cookies_config)} 个账号")
|
||||
else:
|
||||
print("没有成功查询到任何账号数据")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
230
脚本库/web版/抓包/券妈妈时段奖励/2025-01-11_qmm_868f2cd3.js
Normal file
230
脚本库/web版/抓包/券妈妈时段奖励/2025-01-11_qmm_868f2cd3.js
Normal file
File diff suppressed because one or more lines are too long
563
脚本库/web版/账密/'未知用户',/2026-05-19_juejin_checkin_6f8a138b.js
Normal file
563
脚本库/web版/账密/'未知用户',/2026-05-19_juejin_checkin_6f8a138b.js
Normal file
@@ -0,0 +1,563 @@
|
||||
// # Source: https://github.com/huwangkeji/juejin_checkin/blob/main/juejin_checkin.js
|
||||
// # Raw: https://raw.githubusercontent.com/huwangkeji/juejin_checkin/main/juejin_checkin.js
|
||||
// # Repo: huwangkeji/juejin_checkin
|
||||
// # Path: juejin_checkin.js
|
||||
// # UploadedAt: 2026-05-19T14:34:11Z
|
||||
// # SHA256: 6f8a138b51c397220444c9312040dbe3407af5aeed4fa4467a36672aeb8bcfd1
|
||||
// # Category: web版/账密
|
||||
// # Evidence: web/H5关键词 + username/password/login
|
||||
//
|
||||
|
||||
/*
|
||||
* @name 掘金自动签到脚本
|
||||
* @description 掘金社区每日签到 + 免费抽奖 + 沾喜气 + Bug消除,支持Cookie自动签到
|
||||
* @namespace https://juejin.cn
|
||||
* @version 1.0.0
|
||||
* @author CodeBuddy
|
||||
*
|
||||
* 【青龙面板使用说明】
|
||||
* 1. 依赖管理 -> NodeJS -> 添加依赖: axios
|
||||
* 2. 环境变量 (必填):
|
||||
* - JUEJIN_COOKIE: 掘金Cookie (从浏览器开发者工具复制)
|
||||
* - JUEJIN_AID: API参数aid (通常为2608)
|
||||
* - JUEJIN_UUID: API参数uuid
|
||||
* - JUEJIN_MSTOKEN: API参数msToken
|
||||
* - JUEJIN_A_BOGUS: API参数a_bogus
|
||||
* 3. 环境变量 (可选):
|
||||
* - JUEJIN_COOKIE_2 ~ JUEJIN_COOKIE_5: 多账号Cookie
|
||||
* - JUEJIN_NOTIFY: 是否推送通知 (默认true)
|
||||
* 4. 定时规则: 30 6 * * * (每天早上6:30执行)
|
||||
*
|
||||
* 【参数获取方式】
|
||||
* 1. 浏览器打开 https://juejin.cn 并登录
|
||||
* 2. 按F12打开开发者工具 -> Network(网络)标签
|
||||
* 3. 刷新页面,找到任意一个 api.juejin.cn 的请求
|
||||
* 4. 在 Request Headers 中复制完整的 Cookie 值
|
||||
* 5. 在 Query String Parameters 中复制 aid, uuid, msToken, a_bogus
|
||||
* 6. 粘贴到青龙面板对应的环境变量中
|
||||
* 7. Cookie和参数有效期约30天,过期后需重新获取
|
||||
*
|
||||
* 【功能列表】
|
||||
* - Cookie自动签到(支持多账号)
|
||||
* - 每日签到
|
||||
* - 免费抽奖
|
||||
* - 沾喜气
|
||||
* - Bug消除
|
||||
* - 查询矿石余额/签到天数/幸运值
|
||||
* - 青龙面板通知推送
|
||||
*/
|
||||
|
||||
const axios = require('axios');
|
||||
|
||||
// ==================== 配置区域 ====================
|
||||
|
||||
const API_BASE = 'https://api.juejin.cn';
|
||||
|
||||
// 请求头
|
||||
const DEFAULT_HEADERS = {
|
||||
'User-Agent':
|
||||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
|
||||
'Referer': 'https://juejin.cn/',
|
||||
'Origin': 'https://juejin.cn',
|
||||
'Content-Type': 'application/json',
|
||||
'sec-ch-ua': '"Not/A)Brand";v="99", "Chromium";v="148"',
|
||||
'sec-ch-ua-mobile': '?0',
|
||||
'sec-ch-ua-platform': '"Windows"',
|
||||
};
|
||||
|
||||
// ==================== 工具函数 ====================
|
||||
|
||||
function log(msg) {
|
||||
const now = new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' });
|
||||
console.log(`[${now}] ${msg}`);
|
||||
}
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建带Cookie和参数的axios实例
|
||||
*/
|
||||
function createApiClient(cookie, params) {
|
||||
const instance = axios.create({
|
||||
baseURL: API_BASE,
|
||||
headers: {
|
||||
...DEFAULT_HEADERS,
|
||||
Cookie: cookie,
|
||||
},
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
// 请求拦截 - 自动添加查询参数
|
||||
instance.interceptors.request.use((config) => {
|
||||
if (params && Object.keys(params).length > 0) {
|
||||
config.params = { ...config.params, ...params };
|
||||
}
|
||||
// POST请求body为空对象
|
||||
if (config.method === 'post' && !config.data) {
|
||||
config.data = {};
|
||||
}
|
||||
return config;
|
||||
});
|
||||
|
||||
// 响应拦截
|
||||
instance.interceptors.response.use(
|
||||
(response) => {
|
||||
const data = response.data;
|
||||
// 处理空响应
|
||||
if (data === '' || data === null || data === undefined) {
|
||||
throw new Error('API返回空响应,可能需要更新参数');
|
||||
}
|
||||
if (typeof data === 'object' && data.err_no !== 0) {
|
||||
throw new Error(`API错误: [${data.err_no}] ${data.err_msg || '未知错误'}`);
|
||||
}
|
||||
return data.data;
|
||||
},
|
||||
(error) => {
|
||||
if (error.response) {
|
||||
const data = error.response.data;
|
||||
if (data && typeof data === 'object' && data.err_no !== undefined) {
|
||||
throw new Error(`API错误: [${data.err_no}] ${data.err_msg || '未知错误'}`);
|
||||
}
|
||||
throw new Error(`HTTP错误: ${error.response.status} ${error.response.statusText}`);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
// ==================== API 调用 ====================
|
||||
|
||||
/**
|
||||
* 检查今日签到状态
|
||||
*/
|
||||
async function getTodayStatus(api) {
|
||||
try {
|
||||
const data = await api.get('/growth_api/v1/get_today_status');
|
||||
return data === true;
|
||||
} catch (e) {
|
||||
log('⚠️ 查询签到状态失败: ' + e.message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行签到
|
||||
*/
|
||||
async function checkIn(api) {
|
||||
try {
|
||||
const data = await api.post('/growth_api/v1/check_in');
|
||||
log('✅ 签到成功!');
|
||||
return { success: true, data };
|
||||
} catch (e) {
|
||||
if (e.message.includes('15001') || e.message.includes('已签到') || e.message.includes('duplicate')) {
|
||||
log('📌 今日已签到,无需重复签到');
|
||||
return { success: true, already: true };
|
||||
}
|
||||
if (e.message.includes('3013')) {
|
||||
log('📌 今日已签到 (3013)');
|
||||
return { success: true, already: true };
|
||||
}
|
||||
if (e.message.includes('空响应')) {
|
||||
log('⚠️ API返回空响应,参数可能已过期,建议重新获取');
|
||||
return { success: false, error: e.message };
|
||||
}
|
||||
log('❌ 签到失败: ' + e.message);
|
||||
return { success: false, error: e.message };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取签到天数统计
|
||||
*/
|
||||
async function getCounts(api) {
|
||||
try {
|
||||
const data = await api.get('/growth_api/v1/get_counts');
|
||||
return data;
|
||||
} catch (e) {
|
||||
log('⚠️ 获取签到统计失败: ' + e.message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前矿石数
|
||||
*/
|
||||
async function getCurrentPoint(api) {
|
||||
try {
|
||||
const data = await api.get('/growth_api/v1/get_cur_point');
|
||||
return data;
|
||||
} catch (e) {
|
||||
log('⚠️ 获取矿石余额失败: ' + e.message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取抽奖配置
|
||||
*/
|
||||
async function getLotteryConfig(api) {
|
||||
try {
|
||||
const data = await api.get('/growth_api/v1/lottery_config/get');
|
||||
return data;
|
||||
} catch (e) {
|
||||
log('⚠️ 获取抽奖配置失败: ' + e.message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 免费抽奖
|
||||
*/
|
||||
async function drawLottery(api) {
|
||||
try {
|
||||
const data = await api.post('/growth_api/v1/lottery/draw');
|
||||
log('🎉 抽奖成功!奖品: ' + (data.lottery_name || '未知'));
|
||||
return { success: true, data };
|
||||
} catch (e) {
|
||||
log('❌ 抽奖失败: ' + e.message);
|
||||
return { success: false, error: e.message };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 沾喜气
|
||||
*/
|
||||
async function dipLucky(api) {
|
||||
try {
|
||||
// 先获取幸运用户列表
|
||||
const luckyUsers = await api.post('/growth_api/v1/lottery_history/global_big', {
|
||||
page_no: 1,
|
||||
page_size: 5,
|
||||
});
|
||||
|
||||
if (luckyUsers && luckyUsers.lotteries && luckyUsers.lotteries.length > 0) {
|
||||
const historyId = luckyUsers.lotteries[0].history_id;
|
||||
const data = await api.post('/growth_api/v1/lottery_lucky/dip_lucky', {
|
||||
lottery_history_id: historyId,
|
||||
});
|
||||
log('🍀 沾喜气成功!幸运值: ' + (data.dip_value || 0));
|
||||
return { success: true, data };
|
||||
}
|
||||
log('⚠️ 暂无可沾喜气的用户');
|
||||
return { success: false };
|
||||
} catch (e) {
|
||||
log('❌ 沾喜气失败: ' + e.message);
|
||||
return { success: false, error: e.message };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取我的幸运值
|
||||
*/
|
||||
async function getMyLucky(api) {
|
||||
try {
|
||||
const data = await api.post('/growth_api/v1/lottery_lucky/my_lucky');
|
||||
return data;
|
||||
} catch (e) {
|
||||
log('⚠️ 获取幸运值失败: ' + e.message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户信息 (验证Cookie有效性)
|
||||
*/
|
||||
async function getUserInfo(api) {
|
||||
try {
|
||||
const data = await api.get('/user_api/v1/user/get');
|
||||
return data;
|
||||
} catch (e) {
|
||||
log('⚠️ Cookie无效或已过期: ' + e.message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Bug消除配置
|
||||
*/
|
||||
async function getBugFixConfig(api) {
|
||||
try {
|
||||
const data = await api.get('/growth_api/v1/bugfix/not_collect');
|
||||
return data;
|
||||
} catch (e) {
|
||||
log('⚠️ 获取Bug配置失败: ' + e.message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 消除Bug
|
||||
*/
|
||||
async function fixBug(api, bugId) {
|
||||
try {
|
||||
const data = await api.post('/growth_api/v1/bugfix/collect', {
|
||||
bug_type: bugId,
|
||||
});
|
||||
log('🐛 Bug消除成功!');
|
||||
return { success: true, data };
|
||||
} catch (e) {
|
||||
log('❌ Bug消除失败: ' + e.message);
|
||||
return { success: false, error: e.message };
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 青龙面板通知 ====================
|
||||
|
||||
/**
|
||||
* 青龙面板通知推送
|
||||
*/
|
||||
async function sendNotify(title, content) {
|
||||
if (process.env.JUEJIN_NOTIFY === 'false') {
|
||||
log('📢 通知已禁用');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 尝试加载青龙面板的通知模块
|
||||
const notifyPath = require('path').join(process.cwd(), 'notify.js');
|
||||
if (require('fs').existsSync(notifyPath)) {
|
||||
const sendNotifyFn = require(notifyPath);
|
||||
if (typeof sendNotifyFn === 'function') {
|
||||
await sendNotifyFn(title, content);
|
||||
log('📢 青龙通知已发送');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试从全局加载
|
||||
try {
|
||||
const { sendNotify: qinglongNotify } = require('qlnotify');
|
||||
await qinglongNotify(title, content);
|
||||
log('📢 青龙通知已发送');
|
||||
return;
|
||||
} catch (e) {
|
||||
// 忽略
|
||||
}
|
||||
|
||||
log('📢 青龙通知模块未找到,仅控制台输出');
|
||||
} catch (e) {
|
||||
log('⚠️ 发送通知失败: ' + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 单个账号签到流程 ====================
|
||||
|
||||
async function runAccount(cookie, params, index) {
|
||||
const prefix = index > 1 ? `[账号${index}] ` : '';
|
||||
log('');
|
||||
log(`${prefix}═══════════════════════════════════════`);
|
||||
log(`${prefix} 开始处理账号 ${index}`);
|
||||
log(`${prefix}═══════════════════════════════════════`);
|
||||
|
||||
if (!cookie || cookie.trim().length === 0) {
|
||||
log(`${prefix}❌ Cookie为空,跳过`);
|
||||
return null;
|
||||
}
|
||||
|
||||
// 创建API客户端
|
||||
const api = createApiClient(cookie, params);
|
||||
|
||||
// 验证Cookie有效性
|
||||
log(`${prefix}🔍 验证Cookie...`);
|
||||
const userInfo = await getUserInfo(api);
|
||||
if (!userInfo) {
|
||||
log(`${prefix}❌ Cookie已失效,请重新获取`);
|
||||
return {
|
||||
success: false,
|
||||
error: 'Cookie已失效',
|
||||
userName: '未知用户',
|
||||
};
|
||||
}
|
||||
|
||||
const userName = userInfo.user_name || userInfo.nick_name || '未知用户';
|
||||
log(`${prefix}✅ Cookie有效!用户: ${userName}`);
|
||||
|
||||
// 签到
|
||||
log(`${prefix}📅 执行签到...`);
|
||||
const todayStatus = await getTodayStatus(api);
|
||||
let signInResult = { success: true, already: todayStatus === true };
|
||||
|
||||
if (todayStatus === true) {
|
||||
log(`${prefix}📌 今日已签到,跳过`);
|
||||
} else if (todayStatus === false) {
|
||||
signInResult = await checkIn(api);
|
||||
if (!signInResult.success) {
|
||||
log(`${prefix}🔄 签到失败,1秒后重试...`);
|
||||
await sleep(1000);
|
||||
signInResult = await checkIn(api);
|
||||
}
|
||||
} else {
|
||||
log(`${prefix}⚠️ 无法查询签到状态,直接尝试签到...`);
|
||||
signInResult = await checkIn(api);
|
||||
}
|
||||
|
||||
// 抽奖
|
||||
log(`${prefix}🎰 执行抽奖...`);
|
||||
const lotteryConfig = await getLotteryConfig(api);
|
||||
let lotteryResult = { success: false };
|
||||
if (lotteryConfig && lotteryConfig.free_count > 0) {
|
||||
log(`${prefix}🎁 有 ${lotteryConfig.free_count} 次免费抽奖机会`);
|
||||
lotteryResult = await drawLottery(api);
|
||||
} else if (lotteryConfig) {
|
||||
log(`${prefix}📌 今日免费抽奖次数已用完`);
|
||||
}
|
||||
|
||||
// 沾喜气
|
||||
log(`${prefix}🍀 沾喜气...`);
|
||||
const dipResult = await dipLucky(api);
|
||||
|
||||
// Bug消除
|
||||
log(`${prefix}🐛 消除Bug...`);
|
||||
const bugConfig = await getBugFixConfig(api);
|
||||
let bugFixResult = { success: false };
|
||||
if (bugConfig && Array.isArray(bugConfig) && bugConfig.length > 0) {
|
||||
const bug = bugConfig[0];
|
||||
log(`${prefix}🔧 发现未消除的Bug: ${bug.bug_type}`);
|
||||
bugFixResult = await fixBug(api, bug.bug_type);
|
||||
} else {
|
||||
log(`${prefix}📌 暂无Bug可消除`);
|
||||
}
|
||||
|
||||
// 查询统计信息
|
||||
log(`${prefix}📊 查询统计...`);
|
||||
const counts = await getCounts(api);
|
||||
const point = await getCurrentPoint(api);
|
||||
const lucky = await getMyLucky(api);
|
||||
|
||||
if (counts) {
|
||||
log(`${prefix}📅 连续签到: ${counts.cont_count || 0} 天`);
|
||||
log(`${prefix}📅 累计签到: ${counts.sum_count || 0} 天`);
|
||||
}
|
||||
if (point !== null) {
|
||||
log(`${prefix}💰 当前矿石: ${point}`);
|
||||
}
|
||||
if (lucky) {
|
||||
log(`${prefix}🍀 幸运值: ${lucky.total_value || 0}`);
|
||||
}
|
||||
|
||||
log(`${prefix}✅ 账号处理完成`);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
userName,
|
||||
signIn: signInResult,
|
||||
lottery: lotteryResult,
|
||||
dip: dipResult,
|
||||
bugFix: bugFixResult,
|
||||
counts,
|
||||
point,
|
||||
lucky,
|
||||
};
|
||||
}
|
||||
|
||||
// ==================== 主流程 ====================
|
||||
|
||||
async function main() {
|
||||
log('═══════════════════════════════════════');
|
||||
log(' 掘金自动签到脚本 v1.0.0');
|
||||
log('═══════════════════════════════════════');
|
||||
|
||||
// 收集所有账号的配置
|
||||
const accounts = [];
|
||||
|
||||
// 主账号
|
||||
const mainCookie = process.env.JUEJIN_COOKIE || '';
|
||||
const mainParams = {
|
||||
aid: process.env.JUEJIN_AID || '2608',
|
||||
uuid: process.env.JUEJIN_UUID || '',
|
||||
msToken: process.env.JUEJIN_MSTOKEN || '',
|
||||
a_bogus: process.env.JUEJIN_A_BOGUS || '',
|
||||
spider: '0',
|
||||
};
|
||||
|
||||
if (mainCookie) {
|
||||
accounts.push({ cookie: mainCookie, params: mainParams });
|
||||
}
|
||||
|
||||
// 多账号支持
|
||||
for (let i = 2; i <= 5; i++) {
|
||||
const cookie = process.env[`JUEJIN_COOKIE_${i}`] || '';
|
||||
if (cookie) {
|
||||
accounts.push({
|
||||
cookie,
|
||||
params: {
|
||||
aid: process.env[`JUEJIN_AID_${i}`] || mainParams.aid,
|
||||
uuid: process.env[`JUEJIN_UUID_${i}`] || '',
|
||||
msToken: process.env[`JUEJIN_MSTOKEN_${i}`] || '',
|
||||
a_bogus: process.env[`JUEJIN_A_BOGUS_${i}`] || '',
|
||||
spider: '0',
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (accounts.length === 0) {
|
||||
log('');
|
||||
log('❌ 未配置Cookie,请设置环境变量 JUEJIN_COOKIE');
|
||||
log('');
|
||||
log('【参数获取方式】');
|
||||
log('1. 浏览器打开 https://juejin.cn 并登录');
|
||||
log('2. 按F12打开开发者工具 -> Network(网络)标签');
|
||||
log('3. 刷新页面,找到任意一个 api.juejin.cn 的请求');
|
||||
log('4. 在 Request Headers 中复制完整的 Cookie 值');
|
||||
log('5. 在 Query String Parameters 中复制 aid, uuid, msToken, a_bogus');
|
||||
log('6. 粘贴到青龙面板对应的环境变量中');
|
||||
log('');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
log(`📱 共配置 ${accounts.length} 个账号`);
|
||||
|
||||
// 执行每个账号的签到
|
||||
const results = [];
|
||||
for (let i = 0; i < accounts.length; i++) {
|
||||
const result = await runAccount(accounts[i].cookie, accounts[i].params, i + 1);
|
||||
if (result) results.push(result);
|
||||
}
|
||||
|
||||
// 生成通知内容
|
||||
log('');
|
||||
log('📢 发送通知...');
|
||||
|
||||
let notifyTitle = '掘金每日签到报告';
|
||||
let notifyContent = '';
|
||||
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
const r = results[i];
|
||||
const prefix = results.length > 1 ? `【账号${i + 1}】` : '';
|
||||
|
||||
if (!r.success) {
|
||||
notifyContent += `${prefix}❌ ${r.userName}: ${r.error}\n`;
|
||||
continue;
|
||||
}
|
||||
|
||||
notifyContent += `${prefix}👤 ${r.userName}\n`;
|
||||
notifyContent += ` 📅 连续签到: ${r.counts?.cont_count || 0} 天\n`;
|
||||
notifyContent += ` 📅 累计签到: ${r.counts?.sum_count || 0} 天\n`;
|
||||
notifyContent += ` 💰 当前矿石: ${r.point ?? '未知'}\n`;
|
||||
notifyContent += ` 🍀 幸运值: ${r.lucky?.total_value || 0}\n`;
|
||||
notifyContent += ` ✅ 签到: ${r.signIn.already ? '今日已签到' : r.signIn.success ? '成功' : '失败'}\n`;
|
||||
notifyContent += ` 🎰 抽奖: ${r.lottery.success ? '成功 - ' + (r.lottery.data?.lottery_name || '') : '未抽奖/失败'}\n`;
|
||||
notifyContent += ` 🍀 沾喜气: ${r.dip.success ? '成功' : '失败'}\n`;
|
||||
notifyContent += ` 🐛 Bug消除: ${r.bugFix.success ? '成功' : '无/失败'}\n`;
|
||||
notifyContent += '\n';
|
||||
}
|
||||
|
||||
await sendNotify(notifyTitle, notifyContent);
|
||||
|
||||
log('');
|
||||
log('═══════════════════════════════════════');
|
||||
log(' 脚本执行完成!');
|
||||
log('═══════════════════════════════════════');
|
||||
}
|
||||
|
||||
// 执行主函数
|
||||
main().catch((error) => {
|
||||
log('💥 脚本异常退出: ' + error.message);
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,352 @@
|
||||
# Source: https://github.com/lksky8/sign-ql/blob/main/3dmgame.py
|
||||
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/3dmgame.py
|
||||
# Repo: lksky8/sign-ql
|
||||
# Path: 3dmgame.py
|
||||
# UploadedAt: 2026-03-27T20:17:30Z
|
||||
# SHA256: 2262c9f7c2d40c8ef9822325fadd2e8ed3c43ba0f609c072a27c49b02edc2eaa
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
"""
|
||||
作者:https://github.com/lksky8/sign-ql/
|
||||
日期:2026-3-28
|
||||
网站:3dmgame论坛签到
|
||||
功能:签到、抽奖,金币可换现金买游戏
|
||||
食用方法:登录论坛后,浏览器F12打开抓包,https://bbs.3dmgame.com/home.php?mod=spacecp&ac=credit&showcredit=1抓这个url请求头的cookie包
|
||||
变量:bbs3dmck='cookie' 多个账号用换行分割
|
||||
定时一天三次
|
||||
青龙需要安装lxml模块
|
||||
cron: 0 9 */8 * * *
|
||||
"""
|
||||
|
||||
import time
|
||||
import requests
|
||||
from lxml import etree
|
||||
import re
|
||||
import random
|
||||
import os
|
||||
|
||||
|
||||
send_msg = ''
|
||||
one_msg = ''
|
||||
|
||||
def Log(cont=''):
|
||||
global send_msg, one_msg
|
||||
if cont:
|
||||
one_msg += f'{cont}\n'
|
||||
send_msg += f'{cont}\n'
|
||||
|
||||
# 发送通知消息
|
||||
def send_notification_message(title):
|
||||
try:
|
||||
from notify import send
|
||||
print("加载通知服务成功!")
|
||||
send(title, send_msg)
|
||||
except Exception as e:
|
||||
print('发送通知消息失败!' + str(e))
|
||||
|
||||
|
||||
class ThreeDMGame:
|
||||
def __init__(self, cookies):
|
||||
headers = {
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.9',
|
||||
'Cache-Control': 'no-cache',
|
||||
'Connection': 'keep-alive',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'Origin': 'https://bbs.3dmgame.com',
|
||||
'Pragma': 'no-cache',
|
||||
'Sec-Fetch-Dest': 'iframe',
|
||||
'Sec-Fetch-Mode': 'navigate',
|
||||
'Sec-Fetch-Site': 'same-origin',
|
||||
'Sec-Fetch-User': '?1',
|
||||
'Upgrade-Insecure-Requests': '1',
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36',
|
||||
'sec-ch-ua': '"Chromium";v="146", "Not-A.Brand";v="24", "Google Chrome";v="146"',
|
||||
'sec-ch-ua-mobile': '?0',
|
||||
'sec-ch-ua-platform': '"Windows"',
|
||||
'Cookie': cookies,
|
||||
}
|
||||
self.session = requests.Session()
|
||||
self.session.headers.update(headers)
|
||||
|
||||
def user_info(self):
|
||||
try:
|
||||
response = self.session.get('https://bbs.3dmgame.com/home.php?mod=spacecp&ac=credit&showcredit=1')
|
||||
html = etree.HTML(response.text)
|
||||
user_id = html.xpath('//*[@id="hd"]/div/div[1]/p/strong/a/text()')[0]
|
||||
points = html.xpath('//*[@id="extcreditmenu"]/text()')[0]
|
||||
gold = html.xpath('//*[@id="ct"]/div[1]/div/ul[2]/li[1]/text()')[0]
|
||||
print(f'用户ID:[{user_id}] {points} 金元:{gold}')
|
||||
Log(f'\n用户ID:[{user_id}] {points} 金元:{gold}')
|
||||
except Exception as e:
|
||||
print('3dmgame论坛用户信息获取失败:', e)
|
||||
Log(f'\n3dmgame论坛用户信息获取失败')
|
||||
|
||||
def task_view(self, t_id):
|
||||
try:
|
||||
response = self.session.get(f'https://bbs.3dmgame.com/home.php?mod=task&do=view&id={t_id}')
|
||||
html = etree.HTML(response.text)
|
||||
task_name = html.xpath('//h1[contains(@class, "xs2") and contains(@class, "ptm") and contains(@class, "pbm")]/text()')[0].strip()
|
||||
if 'do=apply' in response.text:
|
||||
print(f'任务:《{task_name}》 可申请')
|
||||
elif '后可以再次申请' in response.text:
|
||||
print(f'任务:《{task_name}》 未到申请时间')
|
||||
elif '您所在的用户组无法申请此任务' in response.text:
|
||||
print(f'任务:《{task_name}》 您所在的用户组无法申请此任务')
|
||||
elif 'static/image/task/reward.gif' in response.text:
|
||||
print(f'任务:《{task_name}》 任务已完成,待领取奖励')
|
||||
else:
|
||||
print(f'任务:《{task_name}》 未知状态')
|
||||
except Exception as e:
|
||||
print(f'查看任务信息失败:{t_id} {e}')
|
||||
|
||||
def check_task(self):
|
||||
try:
|
||||
response = self.session.get('https://bbs.3dmgame.com/home.php?mod=task')
|
||||
# print(response.text)
|
||||
html = etree.HTML(response.text)
|
||||
task_rows = html.xpath('//div[@class="ptm"]//table//tr')
|
||||
|
||||
# for row in task_rows:
|
||||
# # 提取任务名称
|
||||
# task_name = row.xpath('.//td[2]//h3/a/text()')[0] if row.xpath('.//td[2]//h3/a/text()') else ""
|
||||
#
|
||||
# # 提取任务描述
|
||||
# description = row.xpath('.//td[2]/p/text()')[0] if row.xpath('.//td[2]/p/text()') else ""
|
||||
#
|
||||
# # 提取任务奖励
|
||||
# reward = row.xpath('.//td[3]/text()')[0].strip() if row.xpath('.//td[3]/text()') else ""
|
||||
#
|
||||
# # 提取任务状态(可申请/不可申请)
|
||||
# is_available = len(row.xpath('.//td[4]//img[@alt="apply"]')) > 0
|
||||
#
|
||||
# apply_link = row.xpath('.//td[4]/a[contains(@href, "do=apply")]/@href')[0] if row.xpath('.//td[4]/a[contains(@href, "do=apply")]/@href') else "无可用申请链接"
|
||||
#
|
||||
# print(f"任务名称: {task_name}")
|
||||
# print(f"申请链接: {apply_link}")
|
||||
# print(f"描述: {description}")
|
||||
# print(f"奖励: {reward}")
|
||||
# print(f"是否可申请: {'是' if is_available else '否'}")
|
||||
# print("---")
|
||||
task_list = {}
|
||||
for row in task_rows:
|
||||
task_name = row.xpath('.//td[2]//h3/a/text()')[0] if row.xpath('.//td[2]//h3/a/text()') else ""
|
||||
description = row.xpath('.//td[2]/p/text()')[0] if row.xpath('.//td[2]/p/text()') else ""
|
||||
reward = row.xpath('.//td[3]/text()')[0].strip() if row.xpath('.//td[3]/text()') else ""
|
||||
apply_links = row.xpath('.//td[4]/a[contains(@href, "do=apply")]/@href')
|
||||
|
||||
# 只处理有可用申请链接的任务
|
||||
if apply_links:
|
||||
apply_link = apply_links[0]
|
||||
print(f"任务名称: {task_name}")
|
||||
print(f"描述: {description}")
|
||||
print(f"奖励: {reward}")
|
||||
# print(f"任务id: {apply_link.split('id=')[-1]}")
|
||||
print("-" * 50)
|
||||
task_list.update({task_name: apply_link.split('id=')[-1]})
|
||||
if len(task_list) > 0:
|
||||
print(f'获取到{len(task_list)}个可接任务')
|
||||
for name, link_id in task_list.items():
|
||||
print('*' * 30)
|
||||
print(f'尝试领取任务:{name}')
|
||||
response = self.session.get(f'https://bbs.3dmgame.com/home.php?mod=task&do=apply&id={link_id}')
|
||||
if 'do=draw' in response.text:
|
||||
response = self.session.get(f'https://bbs.3dmgame.com/home.php?mod=task&do=draw&id={link_id}')
|
||||
if '恭喜您,任务已成功完成,您将收到奖励通知,请注意查收' in response.text:
|
||||
print(f'任务:{name} 直接完成')
|
||||
else:
|
||||
print(f'任务:{name} 失败' + response.text)
|
||||
elif '申请此任务需要先完成另一个任务' in response.text:
|
||||
html_message = etree.HTML(response.text)
|
||||
qianzhi_task = html_message.xpath('//div[@id="messagetext"]//p[@class="alert_btnleft"]/a/@href')[0].split("id=")[-1]
|
||||
print(f'任务:{name} 领取失败 | 原因是:前置任务未完成,跳转前置任务id:{qianzhi_task}')
|
||||
self.task_view(qianzhi_task)
|
||||
elif '任务申请成功' in response.text:
|
||||
print(f'任务:{name} 领取成功')
|
||||
elif '不是进行中的任务' in response.text:
|
||||
print(f'任务:{name} 无法直接完成')
|
||||
else:
|
||||
print(f'任务:{name} 领取失败')
|
||||
print(response.text)
|
||||
time.sleep(1)
|
||||
print('-' * 50)
|
||||
else:
|
||||
print('没有可接任务')
|
||||
# Log(f'\n没有可接任务')
|
||||
print('-' * 50)
|
||||
except Exception as e:
|
||||
print(f'检查任务信息失败:{e}')
|
||||
|
||||
def check_task_doing(self):
|
||||
try:
|
||||
response = self.session.get('https://bbs.3dmgame.com/home.php?mod=task&item=doing')
|
||||
# print(response.text)
|
||||
html = etree.HTML(response.text)
|
||||
task_rows = html.xpath('//div[@class="ptm"]//table//tr')
|
||||
task_list = []
|
||||
for row in task_rows:
|
||||
# 提取任务名称
|
||||
task_name = row.xpath('.//td[2]//h3/a/text()')[0] if row.xpath('.//td[2]//h3/a/text()') else ""
|
||||
|
||||
# 提取任务ID
|
||||
task_id = row.xpath('.//td[2]//h3/a/@href')[0].split('id=')[-1] if row.xpath('.//td[2]//h3/a/@href') else ""
|
||||
|
||||
# 提取do=view链接(任务详情链接)
|
||||
# view_link = row.xpath('.//td[2]//h3/a[contains(@href, "do=view")]/@href')[0] if row.xpath('.//td[2]//h3/a[contains(@href, "do=view")]/@href') else ""
|
||||
|
||||
# 提取领取链接(do=draw类型)
|
||||
# draw_links = row.xpath('.//td[4]/p/a[contains(@href, "do=draw")]/@href')[0] if row.xpath('.//td[4]/p/a/@href') else ""
|
||||
print(f"进行中的任务: 《{task_name}》")
|
||||
task_list.append({task_name: task_id})
|
||||
print('-' * 30)
|
||||
if len(task_list) > 0:
|
||||
return task_list
|
||||
else:
|
||||
print('没有进行中的任务')
|
||||
# Log(f'\n没有进行中的任务')
|
||||
return []
|
||||
except Exception as e:
|
||||
print(f'检查任务进行中失败:{e}')
|
||||
|
||||
def do_task(self, tk_list):
|
||||
print(f'获取到{len(tk_list)}个待完成任务')
|
||||
for task_name, task_id in tk_list.items():
|
||||
print(f'尝试完成任务:《{task_name}》')
|
||||
response = self.session.get(f'https://bbs.3dmgame.com/home.php?mod=task&do=view&id={task_id}')
|
||||
if 'static/image/task/reward.gif' in response.text:
|
||||
response = self.session.get(f'https://bbs.3dmgame.com/home.php?mod=task&do=draw&id={task_id}')
|
||||
if '恭喜您,任务已成功完成,您将收到奖励通知,请注意查收' in response.text:
|
||||
print(f'任务:《{task_name}》 完成')
|
||||
else:
|
||||
print(f'任务:《{task_name}》 失败')
|
||||
print(response.text)
|
||||
elif '完成此任务所需条件' in response.text:
|
||||
print(f'任务:《{task_name}》 无完成条件')
|
||||
response = self.session.get(f'https://bbs.3dmgame.com/home.php?mod=task&do=draw&id={task_id}')
|
||||
if '恭喜您,任务已成功完成,您将收到奖励通知,请注意查收' in response.text:
|
||||
print(f'任务:《{task_name}》 完成')
|
||||
else:
|
||||
print(f'任务:《{task_name}》 失败')
|
||||
print(response.text)
|
||||
else:
|
||||
print(f'任务:《{task_name}》 有完成条件')
|
||||
tree = etree.HTML(response.text)
|
||||
tables = tree.xpath("//table[@class='tfm']//td[@class='bbda']/a/@href")[0]
|
||||
# print(tables)
|
||||
reply_td = tree.xpath("//table[@class='tfm']//td[@class='bbda'][contains(., '次')]/text()[normalize-space()]")[1]
|
||||
reply_td = reply_td.replace(' ', '')
|
||||
# print(reply_td)
|
||||
reply_count = re.search(r'(\d+)次', reply_td).group(1) if re.search(r'(\d+)次', reply_td) else "未知"
|
||||
if 'thread' in tables:
|
||||
response = self.session.get(f'https://bbs.3dmgame.com/{tables}')
|
||||
formhash = re.search(r'name="formhash" value="(\w+)"', response.text).group(1)
|
||||
fid_match = re.search(r"fid\s*=\s*parseInt\('(\d+)'\)", response.text).group(1)
|
||||
tid_match = re.search(r"tid\s*=\s*parseInt\('(\d+)'\)", response.text).group(1)
|
||||
print('回复次数:' + reply_count)
|
||||
if int(reply_count) > 5:
|
||||
print('回复次数大于5次,任务跳过')
|
||||
else:
|
||||
for _ in range(int(reply_count)):
|
||||
for i in range(3):
|
||||
result = self.reply(tid_match, fid_match, formhash)
|
||||
if result:
|
||||
break
|
||||
time.sleep(10)
|
||||
time.sleep(35)
|
||||
print(f'已完成任务 《{task_name}》 回复指定文章要求')
|
||||
else:
|
||||
response = self.session.get(f'https://bbs.3dmgame.com/{tables}')
|
||||
result = re.findall(r'mod=redirect&tid=(\d+)&goto', response.text)
|
||||
if len(result) > 0:
|
||||
response = self.session.get(f'https://bbs.3dmgame.com/thread-{random.choice(result)}-1-1.html')
|
||||
formhash = re.search(r'name="formhash" value="(\w+)"', response.text).group(1)
|
||||
fid_match = re.search(r"fid\s*=\s*parseInt\('(\d+)'\)", response.text).group(1)
|
||||
tid_match = re.search(r"tid\s*=\s*parseInt\('(\d+)'\)", response.text).group(1)
|
||||
for _ in range(int(reply_count)):
|
||||
for i in range(3):
|
||||
result = self.reply(tid_match, fid_match, formhash)
|
||||
if result:
|
||||
break
|
||||
time.sleep(10)
|
||||
time.sleep(35)
|
||||
print(f'已完成任务 《{task_name}》 回复指定主题要求')
|
||||
response = self.session.get(f'https://bbs.3dmgame.com/home.php?mod=task&do=draw&id={task_id}')
|
||||
if '恭喜您,任务已成功完成,您将收到奖励通知,请注意查收' in response.text:
|
||||
print(f'任务:《{task_name}》 完成')
|
||||
elif '您已完成该任务的' in response.text:
|
||||
html = etree.HTML(response.text)
|
||||
b = html.xpath('//div[@id="messagetext"]/p/text()')[0]
|
||||
print(f'任务:《{task_name}》 失败:' + b.strip())
|
||||
elif '您还没有开始执行任务,赶快哦' in response.text:
|
||||
print(f'任务:《{task_name}》 失败:因任务特殊跳过该任务')
|
||||
elif '您还没有开始执行任务' in response.text:
|
||||
print(f'任务:《{task_name}》 失败:因任务特殊跳过该任务')
|
||||
else:
|
||||
print(f'任务:《{task_name}》 失败')
|
||||
print(response.text)
|
||||
time.sleep(3)
|
||||
|
||||
def reply(self, tid, fid, formhash):
|
||||
response = requests.get("https://www.mxnzp.com/api/jokes/list?page=1&app_id=vqohyieoq7qklmgp&app_secret=FCc9Uf0h1c0LNkqeLRolebStTGfds3Fx")
|
||||
response_json = response.json()
|
||||
if response_json['code'] == 1 :
|
||||
message = response_json['data']['list'][0]['content']
|
||||
else:
|
||||
message = '我是新玩家,搞不懂' + random.choice(['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'])
|
||||
data = {
|
||||
'file': '',
|
||||
'message': message,
|
||||
'posttime': str(int(time.time())),
|
||||
'formhash': formhash,
|
||||
'usesig': '1',
|
||||
'subject': ' ',
|
||||
}
|
||||
response = self.session.post(f'https://bbs.3dmgame.com/forum.php?mod=post&action=reply&fid={fid}&tid={tid}&extra=page%3D1&replysubmit=yes&infloat=yes&handlekey=fastpost&inajax=1', data=data)
|
||||
if '回复发布成功' in response.text:
|
||||
print('回帖成功,等待35秒后回复下个帖子')
|
||||
return True
|
||||
else:
|
||||
print('回复失败,未知原因')
|
||||
return False
|
||||
|
||||
|
||||
def main(self):
|
||||
self.user_info()
|
||||
print('-' * 50)
|
||||
print('开始做论坛任务-->>>>>>>>')
|
||||
self.check_task()
|
||||
task_list = self.check_task_doing()
|
||||
if task_list:
|
||||
for task in task_list:
|
||||
self.do_task(task)
|
||||
print('等待30秒进行下一个账号')
|
||||
self.session.close()
|
||||
print('*' * 50)
|
||||
time.sleep(30)
|
||||
Log('-' * 30)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
if 'bbs3dmck' in os.environ:
|
||||
bbs3dmck = re.split("@|&", os.environ.get("bbs3dmck"))
|
||||
print(f'查找到{len(bbs3dmck)}个账号\n')
|
||||
else:
|
||||
bbs3dmck = None
|
||||
print('无bbs3dmck变量')
|
||||
Log(f'\n未填入bbs3dmck变量')
|
||||
|
||||
if bbs3dmck:
|
||||
z = 1
|
||||
for ck in bbs3dmck:
|
||||
print(f'登录第{z}个账号')
|
||||
threeDM = ThreeDMGame(ck)
|
||||
threeDM.main()
|
||||
z+= 1
|
||||
except Exception as e:
|
||||
print(e)
|
||||
try:
|
||||
send_notification_message(title='3dmgame论坛签到') # 发送通知
|
||||
except Exception as e:
|
||||
print(e)
|
||||
388
脚本库/web版/账密/str,_token_str/2025-09-22_PPark_120e7330.py
Normal file
388
脚本库/web版/账密/str,_token_str/2025-09-22_PPark_120e7330.py
Normal file
@@ -0,0 +1,388 @@
|
||||
# Source: https://github.com/lksky8/sign-ql/blob/main/PPark.py
|
||||
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/PPark.py
|
||||
# Repo: lksky8/sign-ql
|
||||
# Path: PPark.py
|
||||
# UploadedAt: 2025-09-22T11:01:17Z
|
||||
# SHA256: 120e73308bc1ccfb9db8ebd87357364850257a25ba1bc039d67c2967fe6c8e19
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
"""
|
||||
PP停车签到
|
||||
|
||||
作者:https://github.com/lksky8/sign-ql
|
||||
最后更新日期:2025-9-22
|
||||
食用方法:变量输入export pp_token=账号1#token1&账号2#token2
|
||||
支持多用户运行
|
||||
多用户用&或者@隔开
|
||||
例如账号1:13800000000#eyJhbGciOiJIUzI1NiJ9.eyj 账号2: 139000000000#eyJhbGciOiJIUzI1NiJ9.eyj
|
||||
则变量为
|
||||
export pp_token="13800000000#eyJhbGciOiJIUzI1NiJ9.eyj&13900000000#eyJhbGciOiJIUzI1NiJ9.eyj"
|
||||
每天运行两次否则token会过期
|
||||
|
||||
cron: 0 40 0,12 * * *
|
||||
"""
|
||||
import requests
|
||||
import base64
|
||||
from urllib.parse import quote
|
||||
import json
|
||||
import hashlib
|
||||
import time
|
||||
import os
|
||||
import re
|
||||
|
||||
KEY_ENCRYPT = "2363ECDFC54A5AF12477D3D45333A19F" # key1 用于加密
|
||||
KEY_DECRYPT = "466d67cf8f9810707404fae5ed172b8e" # key2 用于解密
|
||||
WX_ENCRYPT = "riegh^ee:w0fok5je5eeS{eecaes1nep"
|
||||
|
||||
send_msg = ''
|
||||
one_msg = ''
|
||||
|
||||
def Log(cont=''):
|
||||
global send_msg, one_msg
|
||||
if cont:
|
||||
one_msg += f'\n{cont}'
|
||||
send_msg += f'\n{cont}'
|
||||
|
||||
|
||||
|
||||
def send_notification_message(title):
|
||||
try:
|
||||
from notify import send
|
||||
print("加载通知服务成功!")
|
||||
send(title, send_msg)
|
||||
except Exception as e:
|
||||
if e:
|
||||
print('发送通知消息失败!')
|
||||
|
||||
api_headers = {
|
||||
'Host': 'api.660pp.com',
|
||||
'accept': '*/*',
|
||||
'content-type': 'application/x-www-form-urlencoded',
|
||||
'rest_api_type': '1',
|
||||
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Parking/4.3.2 (iOS 16.6.1; iPhone15,2; Build/1312) NetType/WIFI',
|
||||
'accept-language': 'zh_CN',
|
||||
}
|
||||
|
||||
|
||||
|
||||
wx_headers = {
|
||||
'Host': 'user-api.4pyun.com',
|
||||
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090a13) UnifiedPCWindowsWechat(0xf2541022) XWEB/16467',
|
||||
'xweb_xhr': '1',
|
||||
'content-type': 'application/x-www-form-urlencoded',
|
||||
'accept': '*/*',
|
||||
'sec-fetch-site': 'cross-site',
|
||||
'sec-fetch-mode': 'cors',
|
||||
'sec-fetch-dest': 'empty',
|
||||
'referer': 'https://servicewechat.com/wxa204074068ad40ef/879/page-frame.html',
|
||||
'accept-language': 'zh-CN,zh;q=0.9',
|
||||
'priority': 'u=1, i',
|
||||
}
|
||||
|
||||
def transform(bytes_data: bytearray, key: str) -> bytearray:
|
||||
len_key = len(key)
|
||||
len_b = len(bytes_data)
|
||||
for i in range(len_b):
|
||||
index = (len_b - i) % len_key
|
||||
key_byte = ord(key[index])
|
||||
in_byte = bytes_data[i]
|
||||
flipped = in_byte ^ 0xFF
|
||||
bytes_data[i] = key_byte ^ flipped
|
||||
return bytes_data
|
||||
|
||||
def encrypt(arg: str, key: str) -> str:
|
||||
"""加密,对应提供的 encrypt 方法"""
|
||||
bytes_data = bytearray(arg.encode('utf-8'))
|
||||
transformed = transform(bytes_data, key)
|
||||
return base64.b64encode(transformed).decode('utf-8')
|
||||
|
||||
def decrypt(arg: str) -> str:
|
||||
"""解密,对应提供的 decrypt 方法"""
|
||||
bytes_data = bytearray(base64.b64decode(arg))
|
||||
transformed = transform(bytes_data, KEY_DECRYPT)
|
||||
return transformed.decode('utf-8')
|
||||
|
||||
def save_or_update_phone_data(phone_key, new_data, file_path='PPark_data.json'):
|
||||
if os.path.exists(file_path):
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
existing_data = json.load(f)
|
||||
else:
|
||||
existing_data = {}
|
||||
|
||||
if phone_key in existing_data:
|
||||
existing_data[phone_key].update(new_data) # 合并新旧数据
|
||||
print(f"[{phone_key}] 数据已更新!")
|
||||
else:
|
||||
existing_data[phone_key] = new_data # 新增数据
|
||||
print(f"[{phone_key}] 新增数据!")
|
||||
|
||||
with open(file_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(existing_data, f, ensure_ascii=False, indent=4)
|
||||
|
||||
def get_user_ids_and_tokens(file_path='PPark_data.json'):
|
||||
try:
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
phone_data = json.load(f)
|
||||
results = []
|
||||
for phone_key, data in phone_data.items():
|
||||
token = data.get('refresh_token')
|
||||
if token:
|
||||
results.append({
|
||||
'phone_key': phone_key,
|
||||
'refresh_token': token,
|
||||
'user_name': data.get('user_name'),
|
||||
'user_id': data.get('user_id')
|
||||
})
|
||||
return results
|
||||
except FileNotFoundError:
|
||||
print(f"文件 {file_path} 不存在!")
|
||||
return []
|
||||
except json.JSONDecodeError:
|
||||
print(f"文件 {file_path} 格式错误!")
|
||||
return []
|
||||
|
||||
def get_userdata(u):
|
||||
user_phone = u.split('#')[0]
|
||||
user_token = u.split('#')[1]
|
||||
|
||||
try:
|
||||
with open('PPark_data.json', 'r', encoding='utf-8') as f:
|
||||
cache_data = json.load(f)
|
||||
except (FileNotFoundError, json.JSONDecodeError):
|
||||
cache_data = {}
|
||||
|
||||
if user_phone not in cache_data:
|
||||
print(f'[{user_phone}] 不存在于缓存中,尝试初始化数据')
|
||||
init_refresh_token(user_phone,user_token)
|
||||
else:
|
||||
print(f'[{user_phone}] 已存在于缓存中,直接读取数据')
|
||||
refresh_token(user_phone,user_token,cache_data[user_phone]['refresh_token'])
|
||||
old_user_token = cache_data[user_phone]['init_token']
|
||||
if old_user_token != user_token:
|
||||
print(f'[{user_phone}] token已更新,尝试刷新')
|
||||
init_refresh_token(user_phone,user_token)
|
||||
|
||||
|
||||
def md5_encrypt(s: str):
|
||||
return hashlib.md5(s.encode('utf-8')).hexdigest()
|
||||
|
||||
|
||||
def get_user_info(phone: str, token: str):
|
||||
headers = wx_headers.copy()
|
||||
headers['authorization'] = f'Bearer {token}'
|
||||
try:
|
||||
response = requests.get('https://user-api.4pyun.com/rest/2.0/user/whoami',headers=headers)
|
||||
response.raise_for_status()
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '1001':
|
||||
print(f"[{response_json['payload']['nickname']}] 获取用户信息:成功")
|
||||
return response_json['payload']['nickname'], response_json['payload']['identity']
|
||||
else:
|
||||
print(f"[{phone}] 获取用户信息:失败:{response_json}")
|
||||
return None
|
||||
except requests.RequestException as e:
|
||||
print(f"[{phone}] 获取用户信息_请求异常:{e}")
|
||||
except json.JSONDecodeError:
|
||||
print(f"[{phone}] 获取用户信息_响应不是有效的JSON格式")
|
||||
except Exception as e:
|
||||
print(f"[{phone}] 获取用户信息_其他异常:{e}")
|
||||
|
||||
def refresh_token(mobile: str, i_token: str, r_token: str):
|
||||
headers = api_headers.copy()
|
||||
headers['rest_api_token'] = r_token
|
||||
try:
|
||||
response = requests.put('https://api.660pp.com/rest/1.6/user/token', headers=headers)
|
||||
response_json = response.json()
|
||||
# print(response_json)
|
||||
if response_json['code'] == '1001':
|
||||
result = json.loads(decrypt(response_json['result']))
|
||||
print(f"[{mobile}] 刷新token成功")
|
||||
save_or_update_phone_data(mobile,{'init_token': i_token,'refresh_token': result['token']})
|
||||
elif response_json['code'] == '401':
|
||||
print(f"[{mobile}] 刷新token失败:token已失效")
|
||||
Log(f"[{mobile}] 刷新token失败:token已失效")
|
||||
else:
|
||||
print(f"[{mobile}] 刷新token失败:{response_json}")
|
||||
except requests.RequestException as e:
|
||||
print(f"[{mobile}] 刷新token_请求异常:{e}")
|
||||
except json.JSONDecodeError:
|
||||
print(f"[{mobile}] 刷新token_响应不是有效的JSON格式")
|
||||
except Exception as e:
|
||||
print(f"[{mobile}] 刷新token_其他异常:{e}")
|
||||
|
||||
|
||||
def init_refresh_token(mobile: str, token: str):
|
||||
headers = api_headers.copy()
|
||||
headers['rest_api_token'] = token
|
||||
try:
|
||||
response = requests.put('https://api.660pp.com/rest/1.6/user/token', headers=headers)
|
||||
response_json = response.json()
|
||||
# print(response_json)
|
||||
if response_json['code'] == '1001':
|
||||
result = json.loads(decrypt(response_json['result']))
|
||||
user_name, user_id = get_user_info(mobile, token)
|
||||
save_or_update_phone_data(mobile,{'user_name': user_name, 'user_id': user_id, 'init_token': token, 'refresh_token': result['token']})
|
||||
print(f"[{mobile}] 刷新token成功")
|
||||
elif response_json['code'] == '401':
|
||||
print(f"[{mobile}] 刷新token失败:token已失效")
|
||||
Log(f"[{mobile}] 刷新token失败:token已失效")
|
||||
else:
|
||||
print(f"[{mobile}] 刷新token失败:{response_json}")
|
||||
except requests.RequestException as e:
|
||||
print(f"[{mobile}] 刷新token_请求异常:{e}")
|
||||
except json.JSONDecodeError:
|
||||
print(f"[{mobile}] 刷新token_响应不是有效的JSON格式")
|
||||
except Exception as e:
|
||||
print(f"[{mobile}] 刷新token_其他异常:{e}")
|
||||
|
||||
def day_sign(nickname: str, token: str):
|
||||
headers = api_headers.copy()
|
||||
headers['rest_api_token'] = token
|
||||
try:
|
||||
response = requests.get('https://api.660pp.com/rest/1.6/reward/bonus?yc7OyqO6qQ%3D%3D=rL7JhL/NrriG2tPZ2aegog%3D%3D', headers=headers)
|
||||
response.raise_for_status()
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '1001':
|
||||
result = json.loads(decrypt(response_json['result']))
|
||||
message = result['message'].replace('\r\n', '')
|
||||
if '签到获得' in result['message'] or '已连续签到'in result['message']:
|
||||
print(f"[{nickname}] 签到成功:{message} 已累计获得:{result['combo']} 积分")
|
||||
Log(f"[{nickname}] 签到成功:{message} 已累计获得:{result['combo']} 积分")
|
||||
elif message == '您已签到成功' :
|
||||
print(f"[{nickname}] 签到失败:已签到")
|
||||
Log(f"[{nickname}] 已签到")
|
||||
else:
|
||||
print(f"[{nickname}] 签到失败:{message}")
|
||||
Log(f"[{nickname}] 签到失败:{message}")
|
||||
else:
|
||||
print(f"[{nickname}] 获取签到数据失败:{response_json}")
|
||||
except requests.RequestException as e:
|
||||
print(f"[{nickname}] 签到_请求异常:{e}")
|
||||
except json.JSONDecodeError:
|
||||
print(f"[{nickname}] 签到_响应不是有效的JSON格式")
|
||||
except Exception as e:
|
||||
print(f"[{nickname}] 签到_其他异常:{e}")
|
||||
|
||||
def get_task(nickname: str, token: str):
|
||||
headers = wx_headers.copy()
|
||||
headers['authorization'] = f'Bearer {token}'
|
||||
try:
|
||||
response = requests.get('https://user-api.4pyun.com/rest/2.0/bonus/reward/task/list?%2B9Hnx%2FPy=7bL7p%2FqgoK77uPOi%2B8WjqP%2Fw', headers=headers)
|
||||
response.raise_for_status()
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '1001':
|
||||
video_task = [task for task in response_json['payload']['row'] if task['name'] == '看视频得积分'][0]
|
||||
referer_url = video_task['referer_url']
|
||||
print(f'[{nickname}] 获取视频任务数据成功')
|
||||
return referer_url.split('&voucher=')[1]
|
||||
else:
|
||||
print(f"[{nickname}] 获取任务_失败:{response_json}")
|
||||
Log(f"[{nickname}] 获取视频任务数据失败:{response_json}")
|
||||
return None
|
||||
except requests.RequestException as e:
|
||||
print(f"[{nickname}] 获取任务_请求异常:{e}")
|
||||
except json.JSONDecodeError:
|
||||
print(f"[{nickname}] 获取任务_响应不是有效的JSON格式")
|
||||
except Exception as e:
|
||||
print(f"[{nickname}] 获取任务_其他异常:{e}")
|
||||
|
||||
def complete_task(nickname: str, token: str, task_id: str):
|
||||
headers = wx_headers.copy()
|
||||
headers['authorization'] = f'Bearer {token}'
|
||||
headers['content-type'] = 'application/json;charset=utf-8'
|
||||
try:
|
||||
data = '{"app_id":"wxa204074068ad40ef","purpose":"reward:motivate:advertising","voucher":"voucher_data"}'.replace('voucher_data', task_id)
|
||||
encrypt_data = encrypt(data,WX_ENCRYPT)
|
||||
response = requests.post('https://user-api.4pyun.com/rest/2.0/bonus/reward/task/complete', headers=headers, data=encrypt_data)
|
||||
response.raise_for_status()
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '1001':
|
||||
print(f"[{nickname}] 看视频:任务完成")
|
||||
headers['content-type'] = 'application/x-www-form-urlencoded'
|
||||
response = requests.get('https://user-api.4pyun.com/rest/2.0/bonus/reward/acquire?%2B9Hnx%2FPy=7bL7p%2FqgoK77uPOi%2B8WjqP%2Fw&6u%2FT5%2Ffp8w%3D%3D=%2Fv%2Fp%2Fej%2BvsH17qPs9L7xqvir%2FqDo7sjk8fTx', headers=headers)
|
||||
response.raise_for_status()
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '1001':
|
||||
print(f"[{nickname}] 看视频:任务奖励已领取,{response_json['payload']['message']}")
|
||||
Log(f"[{nickname}] 看视频:任务奖励已领取,{response_json['payload']['message']}")
|
||||
elif response_json['message'] == '已达积分领取次数上限':
|
||||
print(f"[{nickname}] 看视频:积分已领取")
|
||||
else:
|
||||
print(f"[{nickname}] 看视频:{response_json['message']}")
|
||||
Log(f"[{nickname}] 看视频:{response_json['message']}")
|
||||
else:
|
||||
print(f"[{nickname}] 看视频任务失败:{response_json}")
|
||||
Log(f"[{nickname}] 看视频任务失败:{response_json}")
|
||||
except requests.RequestException as e:
|
||||
print(f"[{nickname}] 看视频任务_请求异常:{e}")
|
||||
except json.JSONDecodeError:
|
||||
print(f"[{nickname}] 看视频任务_响应不是有效的JSON格式")
|
||||
except Exception as e:
|
||||
print(f"[{nickname}] 看视频任务_其他异常:{e}")
|
||||
|
||||
def reward_balance(nickname: str, token: str, user_id: str):
|
||||
headers = wx_headers.copy()
|
||||
headers['authorization'] = f'Bearer {token}'
|
||||
try:
|
||||
response = requests.get(f'https://user-api.4pyun.com/rest/2.0/reward/balance?rP7%2Fz%2BPx7u8%3D={quote(encrypt(user_id,WX_ENCRYPT))}&7%2BnE5cfz8g%3D%3D={quote(encrypt(user_id,WX_ENCRYPT))}&%2Fbb%2F6P7j4erz=pw%3D%3D', headers=headers)
|
||||
response.raise_for_status()
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '1001':
|
||||
print(f"[{nickname}] 积分余额:{response_json['payload']['balance']}")
|
||||
Log(f"[{nickname}] 积分余额:{response_json['payload']['balance']}")
|
||||
else:
|
||||
print(f"[{nickname}] 获取积分余额_失败:{response_json}")
|
||||
Log(f"[{nickname}] 获取积分余额_失败:{response_json}")
|
||||
except requests.RequestException as e:
|
||||
print(f"[{nickname}] 获取积分余额_请求异常:{e}")
|
||||
except json.JSONDecodeError:
|
||||
print(f"[{nickname}] 获取积分余额_响应不是有效的JSON格式")
|
||||
except Exception as e:
|
||||
print(f"[{nickname}] 获取积分余额_其他异常:{e}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
if 'pp_token' in os.environ:
|
||||
pp_token = re.split("@|&", os.environ.get("pp_token"))
|
||||
print(f'查找到{len(pp_token)}个账号')
|
||||
else:
|
||||
pp_token = []
|
||||
print('请填入pp_token变量')
|
||||
Log('请填入pp_token变量')
|
||||
|
||||
try:
|
||||
if pp_token:
|
||||
for pp_token_item in pp_token:
|
||||
get_userdata(pp_token_item)
|
||||
user_data = get_user_ids_and_tokens()
|
||||
if user_data:
|
||||
print(f"配置缓存中读取到{len(user_data)}个账号")
|
||||
print('*' * 50)
|
||||
z = 1
|
||||
for item in user_data:
|
||||
print('-' * 50)
|
||||
print(f'登录第{z}个账号>>>>>>')
|
||||
phone_key = item.get('phone_key')
|
||||
new_token = item.get('refresh_token')
|
||||
user_name = item.get('user_name')
|
||||
user_id = item.get('user_id')
|
||||
if new_token:
|
||||
day_sign(user_name,new_token)
|
||||
for _ in range(2):
|
||||
voucher = get_task(user_name, new_token)
|
||||
if voucher:
|
||||
complete_task(user_name, new_token, voucher)
|
||||
time.sleep(5)
|
||||
reward_balance(user_name,new_token,user_id)
|
||||
time.sleep(3)
|
||||
Log('-'*30)
|
||||
z += 1
|
||||
else:
|
||||
print("未读取到用户数据,程序退出")
|
||||
exit(0)
|
||||
except Exception as e:
|
||||
print(f'程序异常:{e}')
|
||||
try:
|
||||
send_notification_message(title='PP停车') # 发送通知
|
||||
except Exception as e:
|
||||
print('推送失败:' + str(e))
|
||||
341
脚本库/web版/账密/tyqh/2026-05-23_tyqh_4c779933.py
Normal file
341
脚本库/web版/账密/tyqh/2026-05-23_tyqh_4c779933.py
Normal file
@@ -0,0 +1,341 @@
|
||||
# Source: https://github.com/lksky8/sign-ql/blob/main/invalid/tyqh.py
|
||||
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/tyqh.py
|
||||
# Repo: lksky8/sign-ql
|
||||
# Path: invalid/tyqh.py
|
||||
# UploadedAt: 2026-05-23T06:33:20Z
|
||||
# SHA256: 4c779933563a21d73534721d588cf8fd5aa9e6d6ced3e3b3bb414c91fb576708
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
"""
|
||||
统一茄皇
|
||||
|
||||
作者:https://github.com/lksky8/sign-ql
|
||||
最后更新日期:2025-12-11
|
||||
食用方法:抓包url https://api.zhumanito.cn/api/login 请求体json {"wid":"12345678910"}
|
||||
支持多用户运行
|
||||
多用户用&或者@隔开
|
||||
例如账号1:12345678910 账号2: 12345678911
|
||||
则变量为
|
||||
export tyqh="12345678910@12345678911"
|
||||
|
||||
cron: 11 11 * * *
|
||||
"""
|
||||
|
||||
import requests
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
|
||||
# 推送开关,True为开启,False为关闭
|
||||
sendnotify = True
|
||||
|
||||
send_msg = ''
|
||||
one_msg = ''
|
||||
|
||||
def Log(cont=''):
|
||||
global send_msg, one_msg
|
||||
if cont:
|
||||
one_msg += f'\n{cont}'
|
||||
send_msg += f'\n{cont}'
|
||||
|
||||
def send_notification_message(title):
|
||||
try:
|
||||
from notify import send
|
||||
print("加载通知服务成功!")
|
||||
send(title, send_msg)
|
||||
except Exception as e:
|
||||
if e:
|
||||
print('发送通知消息失败!')
|
||||
|
||||
api_headers = {
|
||||
'Host': 'api.zhumanito.cn',
|
||||
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090a13) UnifiedPCWindowsWechat(0xf2541022) XWEB/16571',
|
||||
'authorization': '',
|
||||
'accept': '*/*',
|
||||
'origin': 'https://h5.zhumanito.cn',
|
||||
'sec-fetch-site': 'same-site',
|
||||
'sec-fetch-mode': 'cors',
|
||||
'sec-fetch-dest': 'empty',
|
||||
'referer': 'https://h5.zhumanito.cn/',
|
||||
'accept-language': 'zh-CN,zh;q=0.9',
|
||||
'priority': 'u=1, i',
|
||||
}
|
||||
|
||||
|
||||
def login(wid):
|
||||
headers = {
|
||||
'Host': 'api.zhumanito.cn',
|
||||
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x63090a13) UnifiedPCWindowsWechat(0xf2541022) XWEB/16571',
|
||||
'content-type': 'application/json;charset=UTF-8',
|
||||
'accept': '*/*',
|
||||
'origin': 'https://h5.zhumanito.cn',
|
||||
'sec-fetch-site': 'same-site',
|
||||
'sec-fetch-mode': 'cors',
|
||||
'sec-fetch-dest': 'empty',
|
||||
'referer': 'https://h5.zhumanito.cn/',
|
||||
'accept-language': 'zh-CN,zh;q=0.9',
|
||||
'priority': 'u=1, i',
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.post('https://api.zhumanito.cn/api/login', headers=headers, json={'wid': wid})
|
||||
response.raise_for_status()
|
||||
response_json = response.json()
|
||||
if response_json['code'] == 200 and response_json['msg'] == '成功':
|
||||
print(f"登录成功,用户ID: {wid},拥有番茄:{response_json['data']['user']['fruit_num']} 个")
|
||||
Log(f"登录成功,用户ID: {wid},拥有番茄:{response_json['data']['user']['fruit_num']} 个")
|
||||
if '"seed_stage":0' in response.text:
|
||||
print(f"未种植番茄")
|
||||
Log(f"未种植番茄")
|
||||
time.sleep(1)
|
||||
seed_tomato(response_json['data']['token'])
|
||||
return response_json['data']['token']
|
||||
else:
|
||||
print(f"用户ID: {wid} 登录失败: {response_json['msg']}")
|
||||
Log(f"用户ID: {wid} 登录失败: {response_json['msg']}")
|
||||
return None
|
||||
except requests.RequestException as e:
|
||||
print(f"获取用户数据网络请求失败: {e}")
|
||||
except ValueError as e:
|
||||
print(f"获取用户数据解析JSON响应失败: {e}")
|
||||
except KeyError as e:
|
||||
print(f"获取用户数据JSON响应中缺少键: {e}")
|
||||
except Exception as e:
|
||||
print(f"获取用户数据时发生未知错误: {e}")
|
||||
|
||||
|
||||
def get_tomato(user_token):
|
||||
headers = api_headers.copy()
|
||||
headers['authorization'] = user_token
|
||||
|
||||
try:
|
||||
response = requests.post('https://api.zhumanito.cn/api/harvest', headers=headers)
|
||||
response.raise_for_status()
|
||||
response_json = response.json()
|
||||
if response_json['code'] == 200 and response_json['msg'] == '成功':
|
||||
print(f"番茄收获成功,获得番茄:{response_json['data']['fruit_up']} 个")
|
||||
Log(f"番茄收获成功,获得番茄:{response_json['data']['fruit_up']} 个")
|
||||
seed_tomato(user_token)
|
||||
else:
|
||||
print(f"收获番茄失败: {response_json['msg']}")
|
||||
Log(f"收获番茄失败: {response_json['msg']}")
|
||||
except requests.RequestException as e:
|
||||
print(f"收获番茄网络请求失败: {e}")
|
||||
except ValueError as e:
|
||||
print(f"收获番茄解析JSON响应失败: {e}")
|
||||
except KeyError as e:
|
||||
print(f"收获番茄JSON响应中缺少键: {e}")
|
||||
except Exception as e:
|
||||
print(f"收获番茄时发生未知错误: {e}")
|
||||
|
||||
|
||||
def seed_tomato(user_token):
|
||||
headers = api_headers.copy()
|
||||
headers['authorization'] = user_token
|
||||
|
||||
try:
|
||||
response = requests.post('https://api.zhumanito.cn/api/seed', headers=headers)
|
||||
response.raise_for_status()
|
||||
response_json = response.json()
|
||||
if response_json['code'] == 200 and response_json['msg'] == '成功':
|
||||
print(f"番茄种植成功")
|
||||
Log(f"番茄种植成功")
|
||||
else:
|
||||
print(f"番茄种植失败: {response_json['msg']}")
|
||||
Log(f"番茄种植失败: {response_json['msg']}")
|
||||
except requests.RequestException as e:
|
||||
print(f"番茄种植网络请求失败: {e}")
|
||||
except ValueError as e:
|
||||
print(f"番茄种植解析JSON响应失败: {e}")
|
||||
except KeyError as e:
|
||||
print(f"番茄种植JSON响应中缺少键: {e}")
|
||||
except Exception as e:
|
||||
print(f"番茄种植时发生未知错误: {e}")
|
||||
|
||||
def get_task(user_token):
|
||||
headers = api_headers.copy()
|
||||
headers['authorization'] = user_token
|
||||
try:
|
||||
response = requests.get('https://api.zhumanito.cn/api/task?', headers=headers)
|
||||
response.raise_for_status()
|
||||
response_json = response.json()
|
||||
if response_json['code'] == 200 and response_json['msg'] == '成功':
|
||||
print(f"获取任务成功")
|
||||
task_lists = []
|
||||
for task_list in response_json['data']['task']:
|
||||
task_name = task_list['content']
|
||||
reward_water = task_list['water_num']
|
||||
reward_sun = task_list['sun_num']
|
||||
if task_list['status'] == 1:
|
||||
print(f"任务: {task_name}, 奖励水: {reward_water}, 奖励阳光: {reward_sun} 已完成")
|
||||
else:
|
||||
print(f"任务: {task_name}, 奖励水: {reward_water}, 奖励阳光: {reward_sun} 未完成")
|
||||
task_lists.append({
|
||||
'task_id': task_list['id'],
|
||||
'task_name': task_name,
|
||||
})
|
||||
return task_lists
|
||||
else:
|
||||
print(f"获取任务失败: {response_json['msg']}")
|
||||
return None
|
||||
except requests.RequestException as e:
|
||||
print(f"获取任务数据网络请求失败: {e}")
|
||||
except ValueError as e:
|
||||
print(f"获取任务数据解析JSON响应失败: {e}")
|
||||
except KeyError as e:
|
||||
print(f"获取任务数据JSON响应中缺少键: {e}")
|
||||
except Exception as e:
|
||||
print(f"获取任务数据时发生未知错误: {e}")
|
||||
|
||||
def get_task_again(user_token):
|
||||
headers = api_headers.copy()
|
||||
headers['authorization'] = user_token
|
||||
try:
|
||||
response = requests.get('https://api.zhumanito.cn/api/task?', headers=headers)
|
||||
response.raise_for_status()
|
||||
response_json = response.json()
|
||||
if response_json['code'] == 200 and response_json['msg'] == '成功':
|
||||
print(f"获取任务成功")
|
||||
for task_list in response_json['data']['task']:
|
||||
task_name = task_list['content']
|
||||
reward_water = task_list['water_num']
|
||||
reward_sun = task_list['sun_num']
|
||||
if task_list['status'] == 1:
|
||||
print(f"任务: {task_name}, 奖励水: {reward_water}, 奖励阳光: {reward_sun} 已完成")
|
||||
Log(f"任务: {task_name}, 奖励水: {reward_water}, 奖励阳光: {reward_sun} 已完成")
|
||||
else:
|
||||
print(f"任务: {task_name}, 奖励水: {reward_water}, 奖励阳光: {reward_sun} 未完成")
|
||||
Log(f"任务: {task_name}, 奖励水: {reward_water}, 奖励阳光: {reward_sun} 未完成")
|
||||
else:
|
||||
print(f"获取任务失败: {response_json['msg']}")
|
||||
Log(f"获取任务失败: {response_json['msg']}")
|
||||
return None
|
||||
except requests.RequestException as e:
|
||||
print(f"获取任务数据网络请求失败: {e}")
|
||||
except ValueError as e:
|
||||
print(f"获取任务数据解析JSON响应失败: {e}")
|
||||
except KeyError as e:
|
||||
print(f"获取任务数据JSON响应中缺少键: {e}")
|
||||
except Exception as e:
|
||||
print(f"获取任务数据时发生未知错误: {e}")
|
||||
|
||||
def task_complete(user_token, task_id,task_name):
|
||||
headers = api_headers.copy()
|
||||
headers['authorization'] = user_token
|
||||
headers['content-type'] = 'application/x-www-form-urlencoded;charset=UTF-8'
|
||||
try:
|
||||
response = requests.post('https://api.zhumanito.cn/api/task/complete', headers=headers, data=f'task_id={task_id}&')
|
||||
response.raise_for_status()
|
||||
response_json = response.json()
|
||||
if response_json['code'] == 200 and response_json['msg'] == '成功':
|
||||
for task_status in response_json['data']['task']:
|
||||
if task_status['task_id'] == task_id and task_status['status']:
|
||||
print(f"任务: {task_name} 成功,剩余水: {response_json['data']['user']['water_num']}, 剩余阳光: {response_json['data']['user']['sun_num']}")
|
||||
else:
|
||||
print(f"任务: {task_name} 失败: {response_json['msg']}")
|
||||
except requests.RequestException as e:
|
||||
print(f"完成任务: {task_name} 时网络请求失败: {e}")
|
||||
except ValueError as e:
|
||||
print(f"完成任务: {task_name} 时解析JSON响应失败: {e}")
|
||||
except KeyError as e:
|
||||
print(f"完成任务: {task_name} 时JSON响应中缺少键: {e}")
|
||||
except Exception as e:
|
||||
print(f"完成任务: {task_name} 时发生未知错误: {e}")
|
||||
|
||||
def water(user_token):
|
||||
headers = api_headers.copy()
|
||||
headers['authorization'] = user_token
|
||||
headers['content-type'] = 'application/x-www-form-urlencoded;charset=UTF-8'
|
||||
try:
|
||||
response = requests.post('https://api.zhumanito.cn/api/water', headers=headers)
|
||||
response.raise_for_status()
|
||||
response_json = response.json()
|
||||
if response_json['code'] == 200 and response_json['msg'] == '成功':
|
||||
print(f"浇水成功,剩余水: {response_json['data']['user']['water_num']}, 剩余阳光: {response_json['data']['user']['sun_num']}")
|
||||
Log(f"浇水成功,剩余水: {response_json['data']['user']['water_num']}, 剩余阳光: {response_json['data']['user']['sun_num']}")
|
||||
return True
|
||||
elif response_json['code'] == 10006 and response_json['msg'] == '能量值不足了,可以坚持做任务获取哦~':
|
||||
print("不够水了")
|
||||
Log("不够水了")
|
||||
return False
|
||||
elif response_json['code'] == 10007 and response_json['msg'] == '今日浇水已达到上限,请明天再来哦~':
|
||||
print("今日浇水次数已达到上限")
|
||||
Log("今日浇水次数已达到上限")
|
||||
return False
|
||||
elif response_json['code'] == 10008 and response_json['msg'] == '已成熟,不必浇灌':
|
||||
print("番茄已成熟,自动收获")
|
||||
Log("番茄已成熟,自动收获")
|
||||
get_tomato(user_token)
|
||||
return True
|
||||
else:
|
||||
print(f"浇水失败: {response_json['msg']}")
|
||||
return False
|
||||
except requests.RequestException as e:
|
||||
print(f"浇水时网络请求失败: {e}")
|
||||
except ValueError as e:
|
||||
print(f"浇水时解析JSON响应失败: {e}")
|
||||
except KeyError as e:
|
||||
print(f"浇水时JSON响应中缺少键: {e}")
|
||||
except Exception as e:
|
||||
print(f"浇水时发生未知错误: {e}")
|
||||
finally:
|
||||
time.sleep(3)
|
||||
|
||||
|
||||
def view_page(wid):
|
||||
headers = {
|
||||
'Host': 'api.zhumanito.cn',
|
||||
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||
'sec-fetch-site': 'same-site',
|
||||
'sec-fetch-dest': 'document',
|
||||
'accept-language': 'zh-CN,zh-Hans;q=0.9',
|
||||
'sec-fetch-mode': 'navigate',
|
||||
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.64(0x1800402b) NetType/WIFI Language/zh_CN miniProgram/wx532ecb3bdaaf92f9',
|
||||
'referer': 'https://h5.zhumanito.cn/',
|
||||
}
|
||||
requests.get(f'https://api.zhumanito.cn/?wid={wid}', headers=headers)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if 'tyqh' in os.environ:
|
||||
tyqh_session = re.split("@|&", os.environ.get("tyqh"))
|
||||
print(f'查找到{len(tyqh_session)}个账号')
|
||||
else:
|
||||
tyqh_session = []
|
||||
|
||||
if tyqh_session:
|
||||
z = 1
|
||||
for wid in tyqh_session:
|
||||
print('*'*50)
|
||||
print(f'开始处理第{z}个账号')
|
||||
Log(f'处理第{z}个账号:')
|
||||
print('-' * 30)
|
||||
token = login(wid)
|
||||
print('-' * 30)
|
||||
all_task = get_task(token)
|
||||
print('-'*30)
|
||||
print('开始做任务')
|
||||
for task in all_task:
|
||||
if task['task_name'] == '浏览指定页面':
|
||||
view_page(wid)
|
||||
print('任务: 浏览指定页面 成功')
|
||||
time.sleep(3)
|
||||
continue
|
||||
task_complete(token, task['task_id'], task['task_name'])
|
||||
time.sleep(3)
|
||||
print('-' * 30)
|
||||
while water(token):
|
||||
pass
|
||||
get_task_again(token)
|
||||
Log('\n')
|
||||
z += 1
|
||||
time.sleep(10)
|
||||
else:
|
||||
print('请填入tyqh变量')
|
||||
Log('请填入tyqh变量')
|
||||
if sendnotify:
|
||||
try:
|
||||
send_notification_message(title='统一茄皇') # 发送通知
|
||||
except Exception as e:
|
||||
print('推送失败:' + str(e))
|
||||
584
脚本库/web版/账密/url.hostname,/2026-05-11_zsp_video_960b2e28.js
Normal file
584
脚本库/web版/账密/url.hostname,/2026-05-11_zsp_video_960b2e28.js
Normal file
@@ -0,0 +1,584 @@
|
||||
// # Source: https://github.com/DearSong15/ql-scripts/blob/main/zsp_video.js
|
||||
// # Raw: https://raw.githubusercontent.com/DearSong15/ql-scripts/main/zsp_video.js
|
||||
// # Repo: DearSong15/ql-scripts
|
||||
// # Path: zsp_video.js
|
||||
// # UploadedAt: 2026-05-11T15:03:30Z
|
||||
// # SHA256: 960b2e28799c40a00eb4bd75dcda1e61b3ab747374716073995c75053c3083ee
|
||||
// # Category: web版/账密
|
||||
// # Evidence: web/H5关键词 + username/password/login
|
||||
//
|
||||
|
||||
//走个码吧,谢谢兄弟们了
|
||||
//后台注册地址https://zsp.99panel.top/#/register?inviteCode=lzwbaleD
|
||||
//前台https://a.zsp55.app/
|
||||
//变量格式:备注#SecretId#SecretKey#deviceld
|
||||
const ENV_NAME = "中视频";
|
||||
const USER_AGENT = "Mozilla/5.0 (Linux; Android 15; 23013RK75C Build/AQ3A.250226.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.260 Mobile Safari/537.36 (Immersed/39.42857) Html5Plus/1.0";
|
||||
const BASE_URL = "https://x1.zsptv.online";
|
||||
|
||||
// 工具函数
|
||||
function wait(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
// HTTP请求函数
|
||||
async function httpRequest(options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = new URL(options.url);
|
||||
const https = url.protocol === 'https:' ? require('https') : require('http');
|
||||
|
||||
const req = https.request({
|
||||
hostname: url.hostname,
|
||||
port: url.port || (url.protocol === 'https:' ? 443 : 80),
|
||||
path: url.pathname + url.search,
|
||||
method: options.method || 'GET',
|
||||
headers: options.headers || {}
|
||||
}, (res) => {
|
||||
let data = '';
|
||||
res.on('data', (chunk) => {
|
||||
data += chunk;
|
||||
});
|
||||
res.on('end', () => {
|
||||
// 调试:记录响应
|
||||
if (res.statusCode === 403) {
|
||||
console.log(`🔍 响应体: ${data.substring(0, 200)}...`);
|
||||
}
|
||||
resolve({
|
||||
statusCode: res.statusCode,
|
||||
headers: res.headers,
|
||||
body: data
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', (err) => {
|
||||
reject(err);
|
||||
});
|
||||
|
||||
if (options.body) {
|
||||
req.write(options.body);
|
||||
}
|
||||
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
|
||||
// Unicode解码函数
|
||||
function decodeUnicode(str) {
|
||||
if (!str) return '';
|
||||
return str.replace(/\\u[\dA-F]{4}/gi,
|
||||
match => String.fromCharCode(parseInt(match.replace(/\\u/g, ''), 16)));
|
||||
}
|
||||
|
||||
// 主函数
|
||||
async function main() {
|
||||
console.log(`🔔 脚本开始运行,时间: ${new Date().toLocaleString()}\n`);
|
||||
|
||||
// 读取环境变量
|
||||
const accounts = loadAccounts();
|
||||
|
||||
if (accounts.length === 0) {
|
||||
console.log("❌ 未找到有效的账号配置,请检查环境变量格式!");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`✅ 找到 ${accounts.length} 个账号\n`);
|
||||
|
||||
// 遍历所有账号
|
||||
for (let i = 0; i < accounts.length; i++) {
|
||||
const account = accounts[i];
|
||||
console.log(`\n📱 开始处理账号 ${i+1}: ${account.remark}`);
|
||||
console.log("=".repeat(30));
|
||||
|
||||
try {
|
||||
await processAccount(account);
|
||||
} catch (error) {
|
||||
console.log(`❌ 处理账号 ${account.remark} 时出错: ${error.message}`);
|
||||
}
|
||||
|
||||
// 账号间延迟
|
||||
if (i < accounts.length - 1) {
|
||||
console.log("\n⏳ 等待5秒后处理下一个账号...");
|
||||
await wait(5000);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n🎉 所有账号处理完成!`);
|
||||
}
|
||||
|
||||
// 加载账号信息
|
||||
function loadAccounts() {
|
||||
const accounts = [];
|
||||
|
||||
// 尝试从不同环境变量名称读取
|
||||
const envNames = ['ZSP', 'AD_WATCH_ACCOUNTS'];
|
||||
let envValue = '';
|
||||
|
||||
for (const envName of envNames) {
|
||||
if (process.env[envName]) {
|
||||
envValue = process.env[envName];
|
||||
console.log(`📋 从环境变量 ${envName} 读取配置`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!envValue) {
|
||||
console.log("⚠️ 请设置环境变量 ZSP 或 AD_WATCH_ACCOUNTS");
|
||||
return accounts;
|
||||
}
|
||||
|
||||
const accountStrs = envValue.split("\n").filter(str => str.trim());
|
||||
|
||||
for (const str of accountStrs) {
|
||||
const parts = str.split("#");
|
||||
if (parts.length >= 4) {
|
||||
accounts.push({
|
||||
remark: parts[0] || "未命名账号",
|
||||
secretId: parts[1],
|
||||
secretKey: parts[2],
|
||||
deviceId: parts[3]
|
||||
});
|
||||
console.log(`✅ 加载账号: ${parts[0] || "未命名账号"}`);
|
||||
} else {
|
||||
console.log(`⚠️ 忽略格式错误的环境变量: ${str}`);
|
||||
}
|
||||
}
|
||||
|
||||
return accounts;
|
||||
}
|
||||
|
||||
// 处理单个账号
|
||||
async function processAccount(account) {
|
||||
// 1. 登录获取token
|
||||
const token = await login(account);
|
||||
if (!token) {
|
||||
console.log("❌ 登录失败,跳过此账号");
|
||||
return;
|
||||
}
|
||||
console.log(`✅ 登录成功,token获取完成`);
|
||||
|
||||
// 2. 检测并执行签到
|
||||
const signed = await checkAndSign(token, account);
|
||||
if (!signed) {
|
||||
console.log("❌ 签到失败,跳过广告任务");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`\n📺 开始执行广告观看任务`);
|
||||
console.log("-".repeat(30));
|
||||
|
||||
let successCount = 0;
|
||||
let failCount = 0;
|
||||
let totalReward = 0;
|
||||
let consecutiveErrors = 0;
|
||||
const maxAds = 50; // 最多执行50次广告任务
|
||||
|
||||
for (let adCount = 0; adCount < maxAds; adCount++) {
|
||||
console.log(`\n🔄 第 ${adCount + 1}/${maxAds} 次广告任务`);
|
||||
|
||||
// 如果连续出现3次错误,重新登录获取新token
|
||||
if (consecutiveErrors >= 3) {
|
||||
console.log("⚠️ 连续3次错误,尝试重新登录...");
|
||||
const newToken = await login(account);
|
||||
if (newToken) {
|
||||
token = newToken;
|
||||
console.log("✅ 重新登录成功,继续任务");
|
||||
consecutiveErrors = 0;
|
||||
} else {
|
||||
console.log("❌ 重新登录失败,跳过此账号");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// 获取广告信息
|
||||
const adInfo = await getNextAd(token, account);
|
||||
if (!adInfo) {
|
||||
console.log(` ⚠️ 获取广告失败`);
|
||||
failCount++;
|
||||
consecutiveErrors++;
|
||||
await wait(3000);
|
||||
continue;
|
||||
}
|
||||
|
||||
console.log(` 📱 广告标题: ${adInfo.title}`);
|
||||
console.log(` ⏱️ 需要观看: ${adInfo.duration}秒`);
|
||||
console.log(` 🪙 预期奖励: ${adInfo.reward || 0}`);
|
||||
|
||||
// 开始播放广告
|
||||
console.log(` ▶️ 开始播放广告...`);
|
||||
const playResult = await claimReward(token, account, adInfo.id, adInfo.duration);
|
||||
|
||||
if (playResult && playResult.success) {
|
||||
console.log(` ✅ 广告观看成功!`);
|
||||
console.log(` 💰 获得奖励: ${playResult.reward || 0}`);
|
||||
|
||||
successCount++;
|
||||
totalReward += parseInt(playResult.reward) || 0;
|
||||
consecutiveErrors = 0; // 重置错误计数
|
||||
|
||||
// 任务间延迟 (避免请求过快)
|
||||
if (adCount < maxAds - 1) {
|
||||
const randomDelay = Math.floor(Math.random() * 3000) + 3000; // 3-6秒随机延迟
|
||||
console.log(` ⏳ 等待${Math.round(randomDelay/1000)}秒后处理下一个广告...`);
|
||||
await wait(randomDelay);
|
||||
}
|
||||
} else {
|
||||
console.log(` ❌ 广告观看失败`);
|
||||
failCount++;
|
||||
consecutiveErrors++;
|
||||
await wait(3000);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.log(` ❌ 广告任务出错: ${error.message}`);
|
||||
failCount++;
|
||||
consecutiveErrors++;
|
||||
await wait(3000);
|
||||
}
|
||||
}
|
||||
|
||||
console.log("\n" + "=".repeat(30));
|
||||
console.log(`📊 任务完成统计:`);
|
||||
console.log(` ✅ 成功: ${successCount} 次`);
|
||||
console.log(` ❌ 失败: ${failCount} 次`);
|
||||
console.log(` 💰 总计奖励: ${totalReward}`);
|
||||
console.log(` 📈 成功率: ${((successCount/maxAds)*100).toFixed(1)}%`);
|
||||
}
|
||||
|
||||
// 登录接口
|
||||
async function login(account) {
|
||||
const url = `${BASE_URL}/api/app/v1/auth/secretKeyLogin`;
|
||||
|
||||
const body = {
|
||||
secretId: account.secretId,
|
||||
secretKey: account.secretKey
|
||||
};
|
||||
|
||||
const headers = {
|
||||
"Accept": "*/*",
|
||||
"User-Agent": USER_AGENT,
|
||||
"app-device": JSON.stringify({
|
||||
"id": account.deviceId,
|
||||
"brand": "xiaomi",
|
||||
"model": "23013RK75C",
|
||||
"platform": "android",
|
||||
"system": "Android 15"
|
||||
}),
|
||||
"Content-Type": "application/json",
|
||||
"Host": "x1.zsptv.online"
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await httpRequest({
|
||||
url: url,
|
||||
method: "POST",
|
||||
headers: headers,
|
||||
body: JSON.stringify(body)
|
||||
});
|
||||
|
||||
if (response.statusCode !== 200) {
|
||||
console.log(`❌ 登录请求失败,状态码: ${response.statusCode}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const data = JSON.parse(response.body);
|
||||
|
||||
if (data.code === 0 && data.data && data.data.token) {
|
||||
return data.data.token;
|
||||
} else {
|
||||
console.log(`❌ 登录失败: ${data.message || "未知错误"}`);
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`❌ 登录请求失败: ${error.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 检测并执行签到
|
||||
async function checkAndSign(token, account) {
|
||||
const url = `${BASE_URL}/api/app/v1/device/userSign`;
|
||||
|
||||
const headers = {
|
||||
"Accept": "*/*",
|
||||
"User-Agent": USER_AGENT,
|
||||
"Authorization": `Bearer ${token}`,
|
||||
"app-device": JSON.stringify({
|
||||
"id": account.deviceId,
|
||||
"brand": "xiaomi",
|
||||
"model": "23013RK75C",
|
||||
"platform": "android",
|
||||
"system": "Android 15"
|
||||
}),
|
||||
"Content-Type": "application/json",
|
||||
"Host": "x1.zsptv.online"
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await httpRequest({
|
||||
url: url,
|
||||
method: "POST",
|
||||
headers: headers,
|
||||
body: "{}"
|
||||
});
|
||||
|
||||
if (response.statusCode !== 200) {
|
||||
console.log(`❌ 签到请求失败,状态码: ${response.statusCode}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
const data = JSON.parse(response.body);
|
||||
|
||||
if (data.code === 0) {
|
||||
const message = decodeUnicode(data.message);
|
||||
console.log(`✅ 签到结果: ${message}`);
|
||||
|
||||
if (data.data) {
|
||||
console.log(` 🪙 获得签到金币: ${data.data.qiandao_money || 0}`);
|
||||
console.log(` 📅 连续签到天数: ${data.data.continuousDays || 1}`);
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
const errorMsg = decodeUnicode(data.message || "未知错误");
|
||||
console.log(`❌ 签到失败: ${errorMsg}`);
|
||||
|
||||
// 如果已签到,也返回true,继续执行广告任务
|
||||
if (errorMsg && errorMsg.includes("已签到")) {
|
||||
console.log(`ℹ️ 今日已签到,继续执行广告任务`);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`❌ 签到请求失败: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取下一个广告
|
||||
async function getNextAd(token, account) {
|
||||
const url = `${BASE_URL}/api/app/v1/ad/next`;
|
||||
|
||||
const headers = {
|
||||
"Accept": "*/*",
|
||||
"User-Agent": USER_AGENT,
|
||||
"Authorization": `Bearer ${token}`,
|
||||
"app-device": JSON.stringify({
|
||||
"id": account.deviceId,
|
||||
"brand": "xiaomi",
|
||||
"model": "23013RK75C",
|
||||
"platform": "android",
|
||||
"system": "Android 15"
|
||||
}),
|
||||
"Content-Type": "application/json",
|
||||
"Host": "x1.zsptv.online"
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await httpRequest({
|
||||
url: url,
|
||||
method: "GET",
|
||||
headers: headers
|
||||
});
|
||||
|
||||
if (response.statusCode !== 200) {
|
||||
console.log(` ❌ 获取广告失败,状态码: ${response.statusCode}`);
|
||||
if (response.body) {
|
||||
const errorData = JSON.parse(response.body);
|
||||
console.log(` 🔍 错误信息: ${errorData.message || "未知错误"}`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const data = JSON.parse(response.body);
|
||||
|
||||
if (data.code === 0 && data.data && data.data.result) {
|
||||
const ad = data.data.result;
|
||||
return {
|
||||
id: ad.id,
|
||||
title: decodeUnicode(ad.title),
|
||||
description: decodeUnicode(ad.description),
|
||||
duration: parseInt(ad.video?.duration || 30), // 默认30秒
|
||||
videoUrl: ad.video?.url || "",
|
||||
playUrl: ad.video?.play_url || "",
|
||||
reward: ad.reward
|
||||
};
|
||||
} else {
|
||||
const errorMsg = decodeUnicode(data.message || "未知错误");
|
||||
console.log(` ❌ 获取广告失败: ${errorMsg}`);
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(` ❌ 获取广告请求失败: ${error.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 观看广告并获取奖励(整合播放和结束确认)
|
||||
async function claimReward(token, account, adId, duration) {
|
||||
const startTime = new Date().toISOString();
|
||||
|
||||
// 1. 开始播放广告
|
||||
console.log(` 📅 播放开始时间: ${startTime}`);
|
||||
const playResult = await startVideoPlay(token, account, adId, startTime);
|
||||
|
||||
if (!playResult || !playResult.playRecordId) {
|
||||
console.log(` ❌ 广告播放开始失败`);
|
||||
return { success: false };
|
||||
}
|
||||
|
||||
console.log(` ✅ 播放开始成功! 记录ID: ${playResult.playRecordId}`);
|
||||
console.log(` 💰 初始奖励: ${playResult.initialReward || 0}`);
|
||||
|
||||
// 2. 等待广告播放时间
|
||||
const waitTime = duration * 1000;
|
||||
console.log(` ⌛ 广告播放中,等待 ${duration} 秒...`);
|
||||
await wait(waitTime);
|
||||
|
||||
// 3. 广告播放结束确认
|
||||
console.log(` ⏹️ 广告播放完成,确认结束...`);
|
||||
const endResult = await endVideoPlay(token, account, playResult.playRecordId);
|
||||
|
||||
if (endResult.success) {
|
||||
console.log(` 🎉 广告观看完整流程完成!`);
|
||||
return {
|
||||
success: true,
|
||||
reward: playResult.reward || 0,
|
||||
playRecordId: playResult.playRecordId
|
||||
};
|
||||
} else {
|
||||
console.log(` ⚠️ 广告观看完成,但结束确认失败`);
|
||||
// 即使结束确认失败,也视为成功(因为已经播放完成)
|
||||
return {
|
||||
success: true,
|
||||
reward: playResult.reward || 0,
|
||||
playRecordId: playResult.playRecordId
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 开始播放广告
|
||||
async function startVideoPlay(token, account, adId, playTime) {
|
||||
const url = `${BASE_URL}/api/app/v1/ad/video/play`;
|
||||
|
||||
const body = {
|
||||
clientIp: "",
|
||||
deviceInfo: {
|
||||
deviceId: account.deviceId,
|
||||
platform: "android"
|
||||
},
|
||||
id: adId.toString(),
|
||||
playTime: playTime
|
||||
};
|
||||
|
||||
const headers = {
|
||||
"Accept": "*/*",
|
||||
"User-Agent": USER_AGENT,
|
||||
"Authorization": `Bearer ${token}`,
|
||||
"app-device": JSON.stringify({
|
||||
"id": account.deviceId,
|
||||
"brand": "xiaomi",
|
||||
"model": "23013RK75C",
|
||||
"platform": "android",
|
||||
"system": "Android 15"
|
||||
}),
|
||||
"Content-Type": "application/json",
|
||||
"Host": "x1.zsptv.online"
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await httpRequest({
|
||||
url: url,
|
||||
method: "POST",
|
||||
headers: headers,
|
||||
body: JSON.stringify(body)
|
||||
});
|
||||
|
||||
if (response.statusCode !== 200) {
|
||||
console.log(` ❌ 开始播放广告失败,状态码: ${response.statusCode}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const data = JSON.parse(response.body);
|
||||
|
||||
if (data.code === 0 && data.data) {
|
||||
return {
|
||||
playRecordId: data.data.id,
|
||||
initialReward: data.data.reward || 0,
|
||||
reward: data.data.reward || 0
|
||||
};
|
||||
} else {
|
||||
console.log(` ❌ 开始播放广告失败: ${data.message || "未知错误"}`);
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(` ❌ 开始播放广告请求失败: ${error.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 结束广告播放
|
||||
async function endVideoPlay(token, account, playRecordId) {
|
||||
const url = `${BASE_URL}/api/app/v1/ad/video/ended`;
|
||||
const endTime = new Date().toISOString();
|
||||
|
||||
const body = {
|
||||
clientIp: "",
|
||||
deviceInfo: {
|
||||
deviceId: account.deviceId,
|
||||
platform: "android"
|
||||
},
|
||||
id: playRecordId.toString(),
|
||||
playTime: endTime
|
||||
};
|
||||
|
||||
const headers = {
|
||||
"Accept": "*/*",
|
||||
"User-Agent": USER_AGENT,
|
||||
"Authorization": `Bearer ${token}`,
|
||||
"app-device": JSON.stringify({
|
||||
"id": account.deviceId,
|
||||
"brand": "xiaomi",
|
||||
"model": "23013RK75C",
|
||||
"platform": "android",
|
||||
"system": "Android 15"
|
||||
}),
|
||||
"Content-Type": "application/json",
|
||||
"Host": "x1.zsptv.online"
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await httpRequest({
|
||||
url: url,
|
||||
method: "POST",
|
||||
headers: headers,
|
||||
body: JSON.stringify(body)
|
||||
});
|
||||
|
||||
if (response.statusCode !== 200) {
|
||||
console.log(` ⚠️ 广告结束确认失败,状态码: ${response.statusCode}`);
|
||||
// 即使结束确认失败,也返回成功(避免403错误导致任务中断)
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
const data = JSON.parse(response.body);
|
||||
|
||||
if (data.code === 0) {
|
||||
return { success: true };
|
||||
} else {
|
||||
console.log(` ⚠️ 广告结束确认返回异常: ${data.message || "未知错误"}`);
|
||||
return { success: false };
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(` ⚠️ 广告结束确认请求失败: ${error.message}`);
|
||||
return { success: false };
|
||||
}
|
||||
}
|
||||
|
||||
// 执行主函数
|
||||
if (require.main === module) {
|
||||
main().catch(console.error);
|
||||
}
|
||||
586
脚本库/web版/账密/yxw_appsign/2025-09-28_yxw_appsign_c6d91db1.py
Normal file
586
脚本库/web版/账密/yxw_appsign/2025-09-28_yxw_appsign_c6d91db1.py
Normal file
@@ -0,0 +1,586 @@
|
||||
# Source: https://github.com/lksky8/sign-ql/blob/main/yxw_appsign.py
|
||||
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/yxw_appsign.py
|
||||
# Repo: lksky8/sign-ql
|
||||
# Path: yxw_appsign.py
|
||||
# UploadedAt: 2025-09-28T06:42:50Z
|
||||
# SHA256: c6d91db16e3a84bf5dfc1e2c7d6cb38fb3f6d38f5829d7f496ba308fa7a77a10
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
'''
|
||||
作者:https://github.com/lksky8/sign-ql/
|
||||
日期:2025-9-28
|
||||
网站:游侠网APP签到
|
||||
功能:签到、抽奖,金币可换现金买游戏,配合金币脚本使用可获得更多金币
|
||||
变量:yxwlogin='账号&密码' 多个账号用@或者#分割
|
||||
定时:一天一次
|
||||
cron:45 8 * * *
|
||||
'''
|
||||
|
||||
from json import JSONDecodeError
|
||||
import requests
|
||||
import hashlib
|
||||
import time
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import datetime
|
||||
|
||||
|
||||
if 'yxwlogin' in os.environ:
|
||||
yxwlogin = re.split("@|#",os.environ.get("yxwlogin"))
|
||||
print(f'查找到{len(yxwlogin)}个账号')
|
||||
else:
|
||||
yxwlogin = []
|
||||
|
||||
|
||||
send_msg = ''
|
||||
one_msg = ''
|
||||
|
||||
def log(cont=''):
|
||||
global send_msg, one_msg
|
||||
if cont:
|
||||
one_msg += f'\n{cont}'
|
||||
send_msg += f'\n{cont}'
|
||||
|
||||
def send_notification_message(title):
|
||||
try:
|
||||
from notify import send
|
||||
print("加载通知服务成功!")
|
||||
send(title, send_msg)
|
||||
except Exception as e:
|
||||
if e:
|
||||
print('发送通知消息失败!')
|
||||
|
||||
api_headers = {
|
||||
'Host': 'api3.ali213.net',
|
||||
'accept': '*/*',
|
||||
'user-agent': 'ali213app',
|
||||
'accept-language': 'zh-Hans-CN;q=1',
|
||||
}
|
||||
|
||||
def get_user_ids_and_tokens(file_path='youxia_data.json'):
|
||||
try:
|
||||
# 1. 读取JSON文件
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
phone_data = json.load(f)
|
||||
|
||||
# 2. 遍历每个手机号
|
||||
results = []
|
||||
for phone_key, data in phone_data.items():
|
||||
user_name = data.get('nickname')
|
||||
user_token = data.get('token')
|
||||
|
||||
if user_name and user_token: # 确保userId和token存在
|
||||
results.append({
|
||||
'phone_key': phone_key,
|
||||
'user_name': user_name,
|
||||
'token': user_token
|
||||
})
|
||||
# print(f"手机号: {phone_key}, userId: {user_id}, token: {token}")
|
||||
|
||||
return results
|
||||
|
||||
except FileNotFoundError:
|
||||
print(f"文件 {file_path} 不存在!")
|
||||
return []
|
||||
except json.JSONDecodeError:
|
||||
print(f"文件 {file_path} 格式错误!")
|
||||
return []
|
||||
|
||||
def save_or_update_phone_data(phone_key, new_data, file_path='youxia_data.json'):
|
||||
if os.path.exists(file_path):
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
existing_data = json.load(f)
|
||||
else:
|
||||
existing_data = {}
|
||||
|
||||
if phone_key in existing_data:
|
||||
existing_data[phone_key].update(new_data) # 合并新旧数据
|
||||
print(f"账号 [{phone_key}] 数据已更新!")
|
||||
else:
|
||||
existing_data[phone_key] = new_data # 新增数据
|
||||
print(f"账号 [{phone_key}] 新增数据!")
|
||||
|
||||
with open(file_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(existing_data, f, ensure_ascii=False, indent=4)
|
||||
|
||||
def get_userdata(u):
|
||||
phone_user = u.split('&')[0]
|
||||
phone_password = u.split('&')[1]
|
||||
|
||||
try:
|
||||
with open('youxia_data.json', 'r', encoding='utf-8') as f:
|
||||
cache_data = json.load(f)
|
||||
except (FileNotFoundError, json.JSONDecodeError):
|
||||
cache_data = {}
|
||||
|
||||
if phone_user not in cache_data:
|
||||
print(f'账号 {phone_user} 不存在于缓存中,尝试初始化数据')
|
||||
login(phone_user, phone_password)
|
||||
else:
|
||||
print(f'账号 {phone_user} 已存在于缓存中,直接读取数据')
|
||||
|
||||
def md5_encode(string):
|
||||
md5 = hashlib.md5()
|
||||
md5.update(string.encode('utf-8'))
|
||||
return md5.hexdigest()
|
||||
|
||||
def check_token(phone,token): # 检查token是否有效,并返回新的token
|
||||
try:
|
||||
response = requests.get(f'https://api3.ali213.net/feedearn/checktoken?token={token}', headers=api_headers)
|
||||
response_json = response.json()
|
||||
if response_json['status'] == 1:
|
||||
print(f'账号 [{phone}] token 有效')
|
||||
save_or_update_phone_data(phone, {'token': response_json['token']})
|
||||
return response_json['token']
|
||||
else:
|
||||
print(f'账号 [{phone}] token 无效')
|
||||
log(f'账号 [{phone}] token 无效\n')
|
||||
return None
|
||||
except JSONDecodeError as e:
|
||||
print(f'账号 [{phone}] 检查token失败: {e}')
|
||||
except Exception as e:
|
||||
print(f'账号 [{phone}] 检查token失败: {e}')
|
||||
|
||||
|
||||
def token_exchanger(token):
|
||||
headers = {
|
||||
'Host': 'api3.ali213.net',
|
||||
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||
'sec-fetch-site': 'none',
|
||||
'sec-fetch-mode': 'navigate',
|
||||
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 ali213app',
|
||||
'accept-language': 'zh-CN,zh-Hans;q=0.9',
|
||||
'sec-fetch-dest': 'document',
|
||||
}
|
||||
|
||||
response = requests.get('https://api3.ali213.net/feedearn/tokenexchanger?token='+token+'&redirectUrl=https://api3.ali213.net/feedearn/luckybox',headers=headers)
|
||||
print(response.text)
|
||||
|
||||
def userinfo(phone,token):
|
||||
try:
|
||||
response = requests.get(f'https://api3.ali213.net/feedearn/userbaseinfo?token={token}', headers=api_headers)
|
||||
response_json = response.json()
|
||||
if '"status":0' in response.text:
|
||||
print(f'账号 [{phone}] 登录过期,需要重新登录')
|
||||
log(f'账号 [{phone}] 登录过期,需要重新登录\n')
|
||||
else:
|
||||
experience = response_json['experience']
|
||||
nextgrade_experience = response_json['nextgrade']['experience']
|
||||
nextgrade_experience_coin = response_json['nextgrade']['coin']
|
||||
money = response_json['money'] / 100
|
||||
# 计算百分比
|
||||
percent = (experience / nextgrade_experience) * 100
|
||||
print(f'账号 [{response_json["nickname"]}] Lv.{response_json["grade"]} 目前金币:{response_json["coins"]} 现金:{money} 剩余{percent:.2f}% 即可升级获得{nextgrade_experience_coin}金币')
|
||||
log(f'账号 [{response_json["nickname"]}] Lv.{response_json["grade"]} 目前金币:{response_json["coins"]} 现金:{money} 剩余{percent:.2f}% 即可升级获得{nextgrade_experience_coin}金币\n')
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'账号 [{phone}] 获取用户信息失败: {e}')
|
||||
except json.JSONDecodeError as e:
|
||||
print(f'账号 [{phone}] 获取用户信息失败: {e}')
|
||||
except Exception as e:
|
||||
print(f'账号 [{phone}] 获取用户信息失败: {e}')
|
||||
|
||||
def check_sign(name,token):
|
||||
try:
|
||||
response = requests.get(f'https://api3.ali213.net/feedearn/signing?action=set&token={token}', headers=api_headers)
|
||||
if r'\u7528\u6237\u672a\u767b\u5f55\u6216\u767b\u5f55\u5df2\u8d85\u65f6' in response.text:
|
||||
print(f'账号 [{name}] 登录过期,需要重新登录')
|
||||
else:
|
||||
response_json = response.json()
|
||||
if response_json['data']['status'] == 1:
|
||||
print(f'账号 [{name}] {response_json["data"]["msg"]},获得金币:{response_json["data"]["coins"]}')
|
||||
log(f'账号 [{name}] {response_json["data"]["msg"]},获得金币:{response_json["data"]["coins"]}\n')
|
||||
elif response_json['data']['status'] == 0:
|
||||
print(f'账号 [{name}] {response_json["data"]["msg"]}')
|
||||
log(f'账号 [{name}] {response_json["data"]["msg"]}\n')
|
||||
else:
|
||||
print(f'账号 [{name}] 签到失败:{response.text}')
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'账号 [{name}] 签到失败[请求]: {e}')
|
||||
except json.JSONDecodeError as e:
|
||||
print(f'账号 [{name}] 签到失败[JSON]: {e}')
|
||||
except Exception as e:
|
||||
print(f'账号 [{name}] 签到失败[其他]: {e}')
|
||||
|
||||
def login(phone, password):
|
||||
headers = {
|
||||
'Host': 'i.ali213.net',
|
||||
'accept': '*/*',
|
||||
'user-agent': 'ali213app',
|
||||
'accept-language': 'zh-Hans-CN;q=1',
|
||||
}
|
||||
time10 = str(int(time.time()))
|
||||
params = {
|
||||
'action': 'login',
|
||||
'from': 'feedearn',
|
||||
'passwd': password,
|
||||
'signature': md5_encode(f'username-{phone}-time-{time10}-passwd-{password}-from-feedearn-action-loginBGg)K6ng4?&x9sCIuO%C2%' + '{@TJ?fnFJ,bZKy/[/EWnw9UsC$@1'),
|
||||
'time': time10,
|
||||
'username': phone,
|
||||
}
|
||||
try:
|
||||
response = requests.get('https://i.ali213.net/api.html', params=params, headers=headers)
|
||||
response.raise_for_status()
|
||||
response_json = response.json()
|
||||
if response_json['status'] == 1 and response_json['msg'] == '登录成功':
|
||||
print('登录成功: ' + response_json['data']['userinfo']['nickname'])
|
||||
log(f'账号 [{response_json["data"]["userinfo"]["nickname"]}] 登录成功\n')
|
||||
new_data = {
|
||||
'uid': response_json['data']['userinfo']['uid'],
|
||||
'nickname': response_json['data']['userinfo']['nickname'],
|
||||
'token': response_json['data']['token'],
|
||||
}
|
||||
save_or_update_phone_data(phone, new_data)
|
||||
elif response_json['status'] == 0:
|
||||
print('登录失败: ' + response_json['msg'])
|
||||
log(f'登录失败: {response_json["msg"]}\n')
|
||||
else:
|
||||
print('登录失败: ' + response_json)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(e)
|
||||
|
||||
def newusercheck(name, token):
|
||||
try:
|
||||
response = requests.get(f'https://api3.ali213.net/feedearn/newusercheck?token={token}', headers=api_headers)
|
||||
response_json = response.json()
|
||||
if response_json['status'] == 1 and response_json['msg'] == '您是老用户,所以还是跳老活动页面吧' or response_json['msg'] == '您参与完新用户活动了,现在去老活动页面吧':
|
||||
# print(f'账号 [{name}] 老用户了,去周签')
|
||||
olduser_sign(name, token)
|
||||
elif response_json['status'] == 3 and response_json['msg'] == '您是最新用户,可以跳最新活动页面了':
|
||||
# print(f'账号 [{name}] 新用户,去首月福利签到')
|
||||
newuser_sign(name, token)
|
||||
else:
|
||||
print(f'账号 [{name}] 未知状态: {response_json}')
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'账号 [{name}] 检查新用户失败[请求]: {e}')
|
||||
except json.JSONDecodeError as e:
|
||||
print(f'账号 [{name}] 检查新用户失败[JSON]: {e}')
|
||||
except Exception as e:
|
||||
print(f'账号 [{name}] 检查新用户失败[其他]: {e}')
|
||||
|
||||
def newuser_sign(name, token):
|
||||
try:
|
||||
response = requests.get(f'https://api3.ali213.net/feedearn/newuseractivitysign?token={token}', headers=api_headers)
|
||||
response_json = response.json()
|
||||
if response_json['status'] == 1:
|
||||
print(f'账号 [{name}] 新用户福利: {response_json["msg"]}')
|
||||
log(f'账号 [{name}] 新用户福利: {response_json["msg"]}\n')
|
||||
newuser_monthsigncheck(name, token)
|
||||
elif response_json['status'] == 0:
|
||||
print(f'账号 [{name}] 新用户福利: {response_json["msg"]}')
|
||||
log(f'账号 [{name}] 新用户福利: {response_json["msg"]}\n')
|
||||
newuser_monthsigncheck(name, token)
|
||||
else:
|
||||
print(f'账号 [{name}] 新用户福利:签到失败 {response.text}')
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'账号 [{name}] 新用户福利签到失败[请求]: {e}')
|
||||
except json.JSONDecodeError as e:
|
||||
print(f'账号 [{name}] 新用户福利签到失败[JSON]: {e}')
|
||||
except Exception as e:
|
||||
print(f'账号 [{name}] 新用户福利签到失败[其他]: {e}')
|
||||
|
||||
def newuser_monthsigncheck(name, token):
|
||||
try:
|
||||
response = requests.get(f'https://api3.ali213.net/feedearn/newusermonthactivity?token={token}', headers=api_headers)
|
||||
response_json = response.json()
|
||||
if response_json['status'] == 1:
|
||||
prize = response_json['data']['prize']
|
||||
today = datetime.datetime.now().strftime('%Y-%m-%d')
|
||||
for item in prize:
|
||||
if item['date'] == today:
|
||||
print(f"账号 [{name}] 【新用户首月福利】 今天({today})的签到信息:")
|
||||
log(f'账号 [{name}] 【新用户首月福利】 今天({today})的签到信息:\n')
|
||||
newuser_kjl(name, token, item['con'], item['tit'], item['typeid'])
|
||||
break
|
||||
else:
|
||||
print('没有获取到当天签到数据')
|
||||
log('没有获取到当天签到数据\n')
|
||||
month_day = response_json["data"]["qztime"].split(',')
|
||||
print(f'账号 [{name}] 【新用户首月福利】已签到: {response_json["data"]["wcday"]}天,已领取{response_json["data"]["totalcoin"]}金币')
|
||||
log(f'账号 [{name}] 【新用户首月福利】已签到: {response_json["data"]["wcday"]}天,已领取{response_json["data"]["totalcoin"]}金币\n')
|
||||
print(f'账号 [{name}] 【新用户首月福利】从{month_day[0]}开始,到{month_day[1]}结束。记得绑定Steam账号才能领取奖励')
|
||||
elif response_json['status'] == 0:
|
||||
print(f'账号 [{name}] 新用户月签查询失败: {response_json["msg"]}')
|
||||
log(f'账号 [{name}] 新用户月签查询失败: {response_json["msg"]}\n')
|
||||
else:
|
||||
print(f'账号 [{name}] 新用户月签查询失败: {response.text}')
|
||||
log(f'账号 [{name}] 新用户月签查询失败: {response.text}\n')
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'账号 [{name}] 新用户月签查询失败[请求]: {e}')
|
||||
except json.JSONDecodeError as e:
|
||||
print(f'账号 [{name}] 新用户月签查询失败[JSON]: {e}')
|
||||
except Exception as e:
|
||||
print(f'账号 [{name}] 新用户月签查询失败[其他]: {e}')
|
||||
|
||||
def olduser_sign(name, token):
|
||||
try:
|
||||
response = requests.get(f'https://api3.ali213.net/feedearn/olduseractivitysign?token={token}', headers=api_headers)
|
||||
response_json = response.json()
|
||||
if response_json['status'] == 1:
|
||||
print(f'账号 [{name}] 老用户福利: {response_json["msg"]}')
|
||||
log(f'账号 [{name}] 老用户福利: {response_json["msg"]}\n')
|
||||
olduser_weeksigncheck(name, user_token)
|
||||
elif response_json['status'] == 0:
|
||||
print(f'账号 [{name}] 老用户福利: {response_json["msg"]}')
|
||||
log(f'账号 [{name}] 老用户福利: {response_json["msg"]}\n')
|
||||
olduser_weeksigncheck(name, user_token)
|
||||
else:
|
||||
print(f'账号 [{name}] 老用户福利:签到失败 {response.text}')
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'账号 [{name}] 老用户福利签到失败[请求]: {e}')
|
||||
except json.JSONDecodeError as e:
|
||||
print(f'账号 [{name}] 老用户福利签到失败[JSON]: {e}')
|
||||
except Exception as e:
|
||||
print(f'账号 [{name}] 老用户福利签到失败[其他]: {e}')
|
||||
|
||||
def olduser_weeksigncheck(name, token):
|
||||
try:
|
||||
response = requests.get(f'https://api3.ali213.net/feedearn/oldusermonthactivity?token={token}', headers=api_headers)
|
||||
response_json = response.json()
|
||||
if response_json['status'] == 1:
|
||||
print(f'账号 [{name}] 【第{response_json["data"]["prizingno"]}阶段】已达成连续签到: {response_json["data"]["signday"]}天')
|
||||
log(f'账号 [{name}] 【第{response_json["data"]["prizingno"]}阶段】已达成连续签到: {response_json["data"]["signday"]}天\n')
|
||||
if response_json["data"]["signday"] == 7:
|
||||
print(f'账号 [{name}] 第七天了,可领取奖励')
|
||||
time.sleep(5)
|
||||
kjl(name, token)
|
||||
elif response_json['status'] == 0:
|
||||
print(f'账号 [{name}] 周签查询失败: {response_json["msg"]}')
|
||||
log(f'账号 [{name}] 周签查询失败: {response_json["msg"]}\n')
|
||||
else:
|
||||
print(f'账号 [{name}] 周签查询失败: {response.text}')
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'账号 [{name}] 周签查询失败[请求]: {e}')
|
||||
except json.JSONDecodeError as e:
|
||||
print(f'账号 [{name}] 周签查询失败[JSON]: {e}')
|
||||
except Exception as e:
|
||||
print(f'账号 [{name}] 周签查询失败[其他]: {e}')
|
||||
|
||||
def kjl(name, token):
|
||||
try:
|
||||
response = requests.get(f'https://api3.ali213.net/feedearn/olduseractivityprizing?token={token}', headers=api_headers)
|
||||
response_json = response.json()
|
||||
if response_json['status'] == 1 and response_json['msg'] == '恭喜中奖':
|
||||
print(f'账号 [{name}] 已领取奖励: 《{response_json["data"]["name"]}》')
|
||||
log(f'账号 [{name}] 已领取奖励: 《{response_json["data"]["name"]}》\n')
|
||||
elif response_json['status'] == 0:
|
||||
print(f'账号 [{name}] 领取奖励失败: {response_json["msg"]}')
|
||||
log(f'账号 [{name}] 领取奖励失败: {response_json["msg"]}\n')
|
||||
else:
|
||||
print(f'账号 [{name}] 领取奖励失败: {response.text}')
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'账号 [{name}] 领取奖励失败[请求]: {e}')
|
||||
except json.JSONDecodeError as e:
|
||||
print(f'账号 [{name}] 领取奖励失败[JSON]: {e}')
|
||||
except Exception as e:
|
||||
print(f'账号 [{name}] 领取奖励失败[其他]: {e}')
|
||||
|
||||
def newuser_kjl(name,token,coin,mem,typeid):
|
||||
try:
|
||||
params = {
|
||||
"coin": coin,
|
||||
"mem": mem,
|
||||
"token": token,
|
||||
"typeid": str(typeid)
|
||||
}
|
||||
response = requests.post("https://api3.ali213.net/feedearn/newuserprizing", params=params, headers=api_headers)
|
||||
response_json = response.json()
|
||||
if response_json['status'] == 1 and response_json['msg'] == '成功':
|
||||
print(f'账号 [{name}] 【新用户首月福利】已领取奖励: {coin}')
|
||||
log(f'账号 [{name}] 【新用户首月福利】已领取奖励: {coin}\n')
|
||||
elif response_json['status'] == 0:
|
||||
print(f'账号 [{name}] 【新用户首月福利】领取奖励失败: {response_json["msg"]}')
|
||||
log(f'账号 [{name}] 【新用户首月福利】领取奖励失败: {response_json["msg"]}\n')
|
||||
else:
|
||||
print(f'账号 [{name}] 【新用户首月福利】领取奖励失败: {response.text}')
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'账号 [{name}] 【新用户首月福利】领取奖励失败[请求]: {e}')
|
||||
except json.JSONDecodeError as e:
|
||||
print(f'账号 [{name}] 【新用户首月福利】领取奖励失败[JSON]: {e}')
|
||||
except Exception as e:
|
||||
print(f'账号 [{name}] 【新用户首月福利】领取奖励失败[其他]: {e}')
|
||||
|
||||
|
||||
def luckbox_cookies(phone, token):
|
||||
headers = {
|
||||
'Host': 'api3.ali213.net',
|
||||
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||
'sec-fetch-site': 'none',
|
||||
'sec-fetch-mode': 'navigate',
|
||||
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 ali213app',
|
||||
'accept-language': 'zh-CN,zh-Hans;q=0.9',
|
||||
'sec-fetch-dest': 'document',
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.get(f'https://api3.ali213.net/feedearn/tokenexchanger?token={token}&redirectUrl=https://api3.ali213.net/feedearn/luckybox', headers=headers)
|
||||
api3AliSSO = response.cookies.get_dict()
|
||||
if api3AliSSO:
|
||||
print(f'账号 [{phone}] 获取神秘宝箱cookies成功')
|
||||
save_or_update_phone_data(phone, api3AliSSO)
|
||||
else:
|
||||
print(f'账号 [{phone}] 获取神秘宝箱cookies失败')
|
||||
log(f'账号 [{phone}] 获取神秘宝箱cookies失败\n')
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'账号 [{phone}] 获取神秘宝箱cookies失败[请求]: {e}')
|
||||
except Exception as e:
|
||||
print(f'账号 [{phone}] 获取神秘宝箱cookies失败[其他]: {e}')
|
||||
|
||||
def usermission(name,token):
|
||||
try:
|
||||
response = requests.get(f'https://api3.ali213.net/feedearn/usermission?token={token}', headers=api_headers)
|
||||
response_json = response.json()
|
||||
if response_json['status'] == 1:
|
||||
print(f'账号 [{name}] 任务查询成功')
|
||||
common_mission = response_json['data']['common']
|
||||
if common_mission:
|
||||
for mission in common_mission:
|
||||
mission_name = mission['title']
|
||||
mission_experience = mission['experience']
|
||||
mission_total = mission['total']
|
||||
mission_prize = mission['prize']
|
||||
print(f'任务名称: {mission_name}, 每日次数: {mission_total}, 奖励经验: {mission_experience}, {mission_prize}')
|
||||
elif response_json['status'] == 0:
|
||||
print(f'账号 [{name}] 任务查询失败: {response_json["msg"]}')
|
||||
else:
|
||||
print(f'账号 [{name}] 任务查询失败: {response.text}')
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'账号 [{name}] 任务查询失败[请求]: {e}')
|
||||
except json.JSONDecodeError as e:
|
||||
print(f'账号 [{name}] 任务查询失败[JSON]: {e}')
|
||||
except Exception as e:
|
||||
print(f'账号 [{name}] 任务查询失败[其他]: {e}')
|
||||
|
||||
def share(name,token,entity_id):
|
||||
try:
|
||||
response = requests.get(f'https://api3.ali213.net/feedearn/sharearticle?channelID=1&entityID={entity_id}&token={token}', headers=api_headers)
|
||||
response_json = response.json()
|
||||
if response_json['status'] == 1:
|
||||
print(f'账号 [{name}] 分享成功,奖励: {response_json["msg"]}金币')
|
||||
elif response_json['status'] == 0:
|
||||
print(f'账号 [{name}] 分享失败: {response_json["msg"]}')
|
||||
else:
|
||||
print(f'账号 [{name}] 分享失败: {response.text}')
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'账号 [{name}] 分享失败[请求]: {e}')
|
||||
except json.JSONDecodeError as e:
|
||||
print(f'账号 [{name}] 分享失败[JSON]: {e}')
|
||||
except Exception as e:
|
||||
print(f'账号 [{name}] 分享失败[其他]: {e}')
|
||||
|
||||
def get_recommendList():
|
||||
try:
|
||||
response = requests.get('https://newapi.ali213.net/app/v1/recommendList?confirmNo=0&keyword=&lastId=&navId=2&pageNo=1&pageNum=10', headers=api_headers)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == 200:
|
||||
print('推荐列表数据获取成功')
|
||||
data = response_json['data']['list']
|
||||
integer_jump_urls = []
|
||||
for item in data:
|
||||
if isinstance(item.get('jumpUrl'), int):
|
||||
integer_jump_urls.append(item['jumpUrl'])
|
||||
return integer_jump_urls
|
||||
else:
|
||||
print('推荐列表数据获取失败')
|
||||
log(f'推荐列表数据获取失败\n')
|
||||
return []
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'推荐列表数据获取失败[请求]: {e}')
|
||||
except json.JSONDecodeError as e:
|
||||
print(f'推荐列表数据获取失败[JSON]: {e}')
|
||||
except Exception as e:
|
||||
print(f'推荐列表数据获取失败[其他]: {e}')
|
||||
|
||||
|
||||
def get_square():
|
||||
try:
|
||||
response = requests.get('https://club.ali213.net/application/forum/square?id=0', headers=api_headers)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == 111 and response_json['msg'] == 'success':
|
||||
print('BBS社区数据获取成功')
|
||||
threadList = response.json()['data']['threadList']
|
||||
thread_id = []
|
||||
for item in threadList:
|
||||
thread_id.append(item['id'])
|
||||
return thread_id
|
||||
else:
|
||||
print('BBS社区数据获取失败')
|
||||
log(f'BBS社区数据获取失败\n')
|
||||
return []
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'BBS社区数据获取失败[请求]: {e}')
|
||||
except json.JSONDecodeError as e:
|
||||
print(f'BBS社区数据获取失败[JSON]: {e}')
|
||||
except Exception as e:
|
||||
print(f'BBS社区数据获取失败[其他]: {e}')
|
||||
|
||||
def readingreward(name,token,threadid):
|
||||
try:
|
||||
response = requests.get(f'https://club.ali213.net/application/thread/readingreward?threadid={threadid}&token={token}', headers=api_headers)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == 111 and response_json['msg'] == 'success':
|
||||
print(f'账号 [{name}] 阅读奖励成功,奖励: {response_json["data"]}金币')
|
||||
elif response_json['code'] == -1 and response_json['msg'] == 'failed':
|
||||
print(f'账号 [{name}] 阅读奖励失败: 已领取过奖励')
|
||||
else:
|
||||
print(f'账号 [{name}] 阅读奖励失败: {response.text}')
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'账号 [{name}] 阅读奖励失败[请求]: {e}')
|
||||
except json.JSONDecodeError as e:
|
||||
print(f'账号 [{name}] 阅读奖励失败[JSON]: {e}')
|
||||
except Exception as e:
|
||||
print(f'账号 [{name}] 阅读奖励失败[其他]: {e}')
|
||||
|
||||
if __name__ == '__main__':
|
||||
print('*'*50)
|
||||
all_user = len(yxwlogin)
|
||||
print(f"检测到环境变量中存在{all_user}个账号")
|
||||
for yxwlogin_item in yxwlogin:
|
||||
get_userdata(yxwlogin_item)
|
||||
|
||||
user_data = get_user_ids_and_tokens()
|
||||
if not user_data:
|
||||
print("未读取到用户数据,程序退出")
|
||||
exit(0)
|
||||
else:
|
||||
print(f"读取到{len(user_data)}个账号")
|
||||
|
||||
recommendList = get_recommendList()
|
||||
square = get_square()
|
||||
print('*'*50)
|
||||
|
||||
for item in user_data:
|
||||
print('-' * 50)
|
||||
log('-' * 35)
|
||||
user_phone = item['phone_key']
|
||||
user_name = item['user_name']
|
||||
user_token = item['token']
|
||||
new_user_token = check_token(user_phone,user_token)
|
||||
if new_user_token:
|
||||
check_sign(user_name, new_user_token)
|
||||
newusercheck(user_name, new_user_token)
|
||||
luckbox_cookies(user_phone, user_token)
|
||||
# usermission(user_name, new_user_token)
|
||||
if recommendList:
|
||||
for entity_id in recommendList:
|
||||
share(user_name, new_user_token, entity_id)
|
||||
time.sleep(1)
|
||||
else:
|
||||
print(f'账号 [{user_phone}] 推荐列表为空')
|
||||
if square:
|
||||
for thread_id in square:
|
||||
readingreward(user_name, new_user_token, thread_id)
|
||||
time.sleep(1)
|
||||
else:
|
||||
print(f'账号 [{user_phone}] BBS社区列表为空')
|
||||
userinfo(user_phone, new_user_token)
|
||||
else:
|
||||
print(f'账号 [{user_phone}] 获取数据失败')
|
||||
continue
|
||||
|
||||
try:
|
||||
send_notification_message(title='游侠网开宝箱') # 发送通知
|
||||
except Exception as e:
|
||||
print('推送失败:' + str(e))
|
||||
|
||||
118
脚本库/web版/账密/yxw_luckbox/2025-08-21_yxw_luckbox_79511924.py
Normal file
118
脚本库/web版/账密/yxw_luckbox/2025-08-21_yxw_luckbox_79511924.py
Normal file
@@ -0,0 +1,118 @@
|
||||
# Source: https://github.com/lksky8/sign-ql/blob/main/yxw_luckbox.py
|
||||
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/yxw_luckbox.py
|
||||
# Repo: lksky8/sign-ql
|
||||
# Path: yxw_luckbox.py
|
||||
# UploadedAt: 2025-08-21T12:12:12Z
|
||||
# SHA256: 7951192443b96cec1fe801de769343a2e080be439b46c9b2bfb4372a4cdfe2e1
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
'''
|
||||
作者:https://github.com/lksky8/sign-ql/
|
||||
日期:2025-8-21
|
||||
软件:游侠网-开宝箱
|
||||
功能:每隔三小时自动开宝箱领取50金币
|
||||
定时:0,5 */3 * * *
|
||||
'''
|
||||
|
||||
import json
|
||||
import requests
|
||||
import time
|
||||
|
||||
send_msg = ''
|
||||
one_msg = ''
|
||||
|
||||
def log(cont=''):
|
||||
global send_msg, one_msg
|
||||
if cont:
|
||||
one_msg += f'{cont}\n'
|
||||
send_msg += f'{cont}\n'
|
||||
|
||||
def send_notification_message(title):
|
||||
try:
|
||||
from notify import send
|
||||
print("加载通知服务成功!")
|
||||
send(title, send_msg)
|
||||
except Exception as e:
|
||||
if e:
|
||||
print('发送通知消息失败!')
|
||||
|
||||
|
||||
def get_user_ids_and_tokens(file_path='youxia_data.json'):
|
||||
try:
|
||||
# 1. 读取JSON文件
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
phone_data = json.load(f)
|
||||
|
||||
# 2. 遍历每个手机号
|
||||
results = []
|
||||
for phone_key, data in phone_data.items():
|
||||
user_name = data.get('nickname')
|
||||
user_token = data.get('token')
|
||||
api3AliSSO_cookie = data.get('api3AliSSO')
|
||||
|
||||
if user_name and user_token: # 确保userId和token存在
|
||||
results.append({
|
||||
'phone_key': phone_key,
|
||||
'user_name': user_name,
|
||||
'api3AliSSO': api3AliSSO_cookie
|
||||
})
|
||||
# print(f"手机号: {phone_key}, userId: {user_id}, token: {token}")
|
||||
|
||||
return results
|
||||
|
||||
except FileNotFoundError:
|
||||
print(f"文件 {file_path} 不存在!")
|
||||
return []
|
||||
except json.JSONDecodeError:
|
||||
print(f"文件 {file_path} 格式错误!")
|
||||
return []
|
||||
|
||||
|
||||
def do_sign(phone, user_name, ck):
|
||||
headers = {
|
||||
"user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 ali213app"
|
||||
}
|
||||
cookies = {
|
||||
"api3AliSSO": ck
|
||||
}
|
||||
try:
|
||||
response = requests.get("https://api3.ali213.net/feedearn/luckybox?action=get", headers=headers,cookies=cookies)
|
||||
response.raise_for_status()
|
||||
response_json = response.json()
|
||||
if response_json['logined']:
|
||||
print(f"账号 [{phone}][{user_name}] 登录成功,CK有效")
|
||||
print(f"账号 [{phone}][{user_name}] {response_json['data']['msg']}")
|
||||
if response_json['data']['status'] == 1 and response_json['data']['msg'] == '领取成功':
|
||||
print(f"账号 [{phone}][{user_name}] 获得{response_json['data']['coins']}金币")
|
||||
else:
|
||||
print(f"账号 [{phone}][{user_name}] 登录失败,CK无效")
|
||||
log(f"账号 [{phone}][{user_name}] 登录失败,CK无效")
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"请求失败: {e}")
|
||||
except json.JSONDecodeError as e:
|
||||
print(f"JSON解析错误: {e}")
|
||||
except Exception as e:
|
||||
print(f"其他错误: {e}")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
user_data = get_user_ids_and_tokens()
|
||||
if not user_data:
|
||||
print("未读取到用户数据,程序退出")
|
||||
exit(0)
|
||||
else:
|
||||
print(f"读取到{len(user_data)}个账号")
|
||||
|
||||
for item in user_data:
|
||||
phone = item['phone_key']
|
||||
user_name = item['user_name']
|
||||
ck = item['api3AliSSO']
|
||||
do_sign(phone, user_name, ck)
|
||||
time.sleep(1)
|
||||
print("-" * 50)
|
||||
|
||||
try:
|
||||
send_notification_message(title='游侠网开宝箱') # 发送通知
|
||||
except Exception as e:
|
||||
print('推送失败:' + str(e))
|
||||
415
脚本库/web版/账密/中石化加油广东APP签到/2022-07-24_jygd_47493387.js
Normal file
415
脚本库/web版/账密/中石化加油广东APP签到/2022-07-24_jygd_47493387.js
Normal file
File diff suppressed because one or more lines are too long
779
脚本库/web版/账密/叮咚买菜/2022-11-17_ddmc_2d78fbea.js
Normal file
779
脚本库/web版/账密/叮咚买菜/2022-11-17_ddmc_2d78fbea.js
Normal file
File diff suppressed because one or more lines are too long
779
脚本库/web版/账密/叮咚买菜/2022-11-17_ddmc_2d78fbea_2.js
Normal file
779
脚本库/web版/账密/叮咚买菜/2022-11-17_ddmc_2d78fbea_2.js
Normal file
File diff suppressed because one or more lines are too long
297
脚本库/web版/账密/方舟健客签到/2025-12-07_jksign_b722f903.py
Normal file
297
脚本库/web版/账密/方舟健客签到/2025-12-07_jksign_b722f903.py
Normal file
@@ -0,0 +1,297 @@
|
||||
# Source: https://github.com/lksky8/sign-ql/blob/main/jksign.py
|
||||
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/jksign.py
|
||||
# Repo: lksky8/sign-ql
|
||||
# Path: jksign.py
|
||||
# UploadedAt: 2025-12-07T17:42:50Z
|
||||
# SHA256: b722f903ef41b1cab2540fc2a7b84bb51cb2e8d354783a225e3c364b0799a4e6
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
"""
|
||||
方舟健客app签到
|
||||
作者:https://github.com/lksky8/sign-ql
|
||||
日期:2025-12-5
|
||||
|
||||
使用方法:APP抓登录包获取refresh_token填入jktoken
|
||||
|
||||
支持多用户运行,多用户用&或者@隔开
|
||||
|
||||
则变量为
|
||||
export jktoken="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9........&eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9........"
|
||||
|
||||
每日签到一次即可
|
||||
cron: 0 5 * * *
|
||||
const $ = new Env("方舟健客签到");
|
||||
"""
|
||||
import time
|
||||
import requests
|
||||
import re
|
||||
import os
|
||||
import datetime
|
||||
import hashlib
|
||||
|
||||
#推送开关,开启为True,关闭为False
|
||||
push_message = True
|
||||
|
||||
|
||||
def md5_encrypt(text):
|
||||
md5_hash = hashlib.md5()
|
||||
md5_hash.update(text.encode('utf-8'))
|
||||
md5_result = md5_hash.hexdigest()
|
||||
return md5_result
|
||||
|
||||
def time13():
|
||||
now = datetime.datetime.now()
|
||||
timestamp_ms = int(now.timestamp() * 1000) + (now.microsecond // 1000)
|
||||
return timestamp_ms
|
||||
|
||||
|
||||
def get_jkx():
|
||||
a = time13() - 1500000000000
|
||||
j = a % 999983
|
||||
j2 = a % 9973
|
||||
h = "6470"
|
||||
md5_1 = md5_encrypt(f"39CC231D-C1F9-48DC-93DA-4CA0EA53C141{j}{h}")
|
||||
md5_2 = md5_encrypt(f"{md5_1}{j2}{h}")
|
||||
return f'{j}#{md5_2}#{j2}#{h}'
|
||||
|
||||
|
||||
api_headers = {
|
||||
'Host': 'acgi.jianke.com',
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
'Sec-Fetch-Site': 'same-site',
|
||||
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
|
||||
'platform': 'APP',
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
'Origin': 'https://app-hybrid.jianke.com',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 jiankeMall/6.47.0 JiankeMall/6.47.0',
|
||||
'Referer': 'https://app-hybrid.jianke.com/',
|
||||
'Content-Type': 'application/json;charset=utf-8',
|
||||
'Sec-Fetch-Dest': 'empty',
|
||||
}
|
||||
|
||||
api_headers2 = {
|
||||
'Host': 'fe-acgi.jianke.com',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 jiankeMall/6.47.0',
|
||||
'versionName': '6.47.0',
|
||||
'X-JK-UDID': '39CC231D-C1F9-48DC-93DA-4CA0EA53C141',
|
||||
'versionCode': '6470',
|
||||
'X-JK-X': get_jkx(),
|
||||
'platform': 'APP',
|
||||
'Accept-Language': 'zh-Hans-CN;q=1',
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
|
||||
send_msg = ''
|
||||
one_msg = ''
|
||||
|
||||
def Log(cont=''):
|
||||
global send_msg, one_msg
|
||||
if cont:
|
||||
one_msg += f'{cont}\n'
|
||||
send_msg += f'{cont}\n'
|
||||
|
||||
|
||||
|
||||
def send_notification_message(title):
|
||||
try:
|
||||
from notify import send
|
||||
print("加载通知服务成功!")
|
||||
send(title, send_msg)
|
||||
except Exception as e:
|
||||
if e:
|
||||
print('发送通知消息失败!')
|
||||
|
||||
|
||||
|
||||
def refresh_token(token):
|
||||
headers = {'Content-Type': 'application/json; charset=utf-8','User-Agent': 'Mozilla/5.0 (Linux; Android 10; MI 8 Build/QKQ1.190828.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.135 Mobile Safari/537.36 jiankeMall/6.26.0(w1080*h2029)','Host': 'acgi.jianke.com','organizationCode': 'app.jianke'}
|
||||
data = {'refreshToken': token }
|
||||
response = requests.post('https://acgi.jianke.com/passport/account/refreshToken', json=data, headers=headers)
|
||||
if '授权失败' in response.text:
|
||||
print('账号刷新token已失效,请重新获取')
|
||||
Log('账号刷新token已失效,请重新获取')
|
||||
return False
|
||||
else:
|
||||
response_json = response.json()
|
||||
if response_json['token_type'] == 'bearer':
|
||||
print("账号token刷新成功,新的access_token已填入:\n" + response_json['access_token'])
|
||||
return response_json['access_token']
|
||||
else:
|
||||
print("Failed to send POST request. Status Code:", response.status_code)
|
||||
print("出错了:", response.text)
|
||||
|
||||
|
||||
def do_sign(new_token,user_name):
|
||||
# headers = api_headers2.copy()
|
||||
# headers['Authorization'] = f'bearer {new_token}'
|
||||
headers = {'Authorization':'bearer ' + new_token,'User-Agent': 'Mozilla/5.0 (Linux; Android 10; MI 8 Build/QKQ1.190828.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/131.0.6778.135 Mobile Safari/537.36 jiankeMall/6.26.0(w1080*h2029)','X-JK-X': get_jkx(),'versionName': '6.47.0','X-JK-UDID': '39CC231D-C1F9-48DC-93DA-4CA0EA53C141'}
|
||||
dl = requests.put('https://acgi.jianke.com/v2/member/signConfig/sign', headers=headers)
|
||||
dl_json = dl.json()
|
||||
if dl.status_code == 200:
|
||||
print(f"[{user_name}] 本次签到获得:{dl_json['coinNum']}金币,今天是本周第{dl_json['cumulativeNum']}天签到")
|
||||
Log(f"\n{user_name}] 本次签到获得:{dl_json['coinNum']}金币,今天是本周第{dl_json['cumulativeNum']}天签到")
|
||||
elif dl_json['message'] == '今日已签到':
|
||||
print(f'[{user_name}] 今天已经签到了')
|
||||
Log(f'\n[{user_name}] 今天已经签到了')
|
||||
else:
|
||||
print("出错了:", dl.text)
|
||||
|
||||
def today_question(new_token,task_id,user_name):
|
||||
headers = api_headers.copy()
|
||||
headers['Authorization'] = f'bearer {new_token}'
|
||||
response = requests.get('https://acgi.jianke.com/support/coin/task/daily-tasks/today-question', headers=headers)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '0' and response_json['message'] == 'success':
|
||||
print(f'[{user_name}]【每日一答】 任务获取成功')
|
||||
question_id = response_json['data']['id']
|
||||
rightChoice = response_json['data']['rightChoice']
|
||||
json_data = {
|
||||
'id': str(task_id),
|
||||
'questionItem': {
|
||||
'id': question_id,
|
||||
'rightChoice': rightChoice,
|
||||
'userChoice': rightChoice,
|
||||
'roundNum': 1,
|
||||
},
|
||||
}
|
||||
response = requests.post('https://acgi.jianke.com/support/coin/task/complete', headers=headers, json=json_data)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '0' and response_json['message'] == 'success':
|
||||
print(f'[{user_name}]【每日一答】 任务完成')
|
||||
Log(f'[{user_name}]【每日一答】 任务完成')
|
||||
else:
|
||||
print(f'[{user_name}]【每日一答】 {response_json["message"]}')
|
||||
Log(f'[{user_name}]【每日一答】 {response_json["message"]}')
|
||||
else:
|
||||
print(f'[{user_name}]【每日一答】 任务获取失败')
|
||||
Log(f'[{user_name}]【每日一答】 任务获取失败')
|
||||
print(response.text)
|
||||
|
||||
def get_today_tasks(new_token, user_name):
|
||||
headers = api_headers.copy()
|
||||
headers['Authorization'] = f'bearer {new_token}'
|
||||
response = requests.get('https://acgi.jianke.com/support/coin/task/daily-tasks', headers=headers)
|
||||
if response.status_code == 200:
|
||||
response_json = response.json()
|
||||
task_list = []
|
||||
for item in response_json['data']:
|
||||
task_id = item['id']
|
||||
task_name = item['taskName']
|
||||
task_list.append({'task_id': task_id, 'task_name': task_name})
|
||||
return task_list
|
||||
else:
|
||||
print(f'{user_name} 获取任务数据失败')
|
||||
print(response.text)
|
||||
return None
|
||||
|
||||
def do_task(new_token,user_name, task_id, task_name):
|
||||
headers = api_headers.copy()
|
||||
headers['Authorization'] = f'bearer {new_token}'
|
||||
json_data = {
|
||||
'id': str(task_id)
|
||||
}
|
||||
response = requests.post('https://acgi.jianke.com/support/coin/task/complete', headers=headers, json=json_data)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '0' and response_json['message'] == 'success':
|
||||
print(f'[{user_name}]【{task_name}】 任务完成')
|
||||
Log(f'[{user_name}]【{task_name}】 任务完成')
|
||||
else:
|
||||
print(f'[{user_name}]【{task_name}】 {response_json["message"]}')
|
||||
Log(f'[{user_name}]【{task_name}】 {response_json["message"]}')
|
||||
|
||||
def task_receive(new_token, user_name, task_id,task_name):
|
||||
headers = api_headers.copy()
|
||||
headers['Authorization'] = f'bearer {new_token}'
|
||||
json_data = {
|
||||
'id': task_id,
|
||||
}
|
||||
response = requests.post('https://acgi.jianke.com/support/coin/task/receive', headers=headers, json=json_data)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '0' and response_json['message'] == 'success':
|
||||
print(f'[{user_name}]【{task_name}】 任务奖励:领取成功')
|
||||
elif response_json['message'] == '奖励领取失败':
|
||||
print(f'[{user_name}]【{task_name}】 任务奖励:领取失败')
|
||||
Log(f'[{user_name}]【{task_name}】 任务奖励:领取失败')
|
||||
else:
|
||||
print('奖励领取失败')
|
||||
print(response.text)
|
||||
|
||||
def get_coin(new_token, user_name):
|
||||
headers = api_headers.copy()
|
||||
headers['Authorization'] = f'bearer {new_token}'
|
||||
response = requests.get('https://acgi.jianke.com/v1/coin/balance', headers=headers)
|
||||
if response.status_code == 200:
|
||||
response_json = response.json()
|
||||
print(f'[{user_name}] 当前健康币:{response_json["balance"]}')
|
||||
Log(f'[{user_name}] 当前健康币:{response_json["balance"]}')
|
||||
else:
|
||||
print('获取金币数失败')
|
||||
print(response.text)
|
||||
|
||||
def get_userinfo(new_token):
|
||||
headers = api_headers2.copy()
|
||||
headers['Authorization'] = f'bearer {new_token}'
|
||||
response = requests.get('https://fe-acgi.jianke.com/v5/userCenter', headers=headers)
|
||||
response_json = response.json()
|
||||
if response_json['statusCode'] == 200:
|
||||
return response_json['data']['memberInfo']['nickName']
|
||||
else:
|
||||
print('获取用户信息失败')
|
||||
print(response.text)
|
||||
return None
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if 'jktoken' in os.environ:
|
||||
jktoken = re.split("@|&", os.environ.get("jktoken"))
|
||||
print(f'查找到{len(jktoken)}个账号')
|
||||
else:
|
||||
jktoken = []
|
||||
print('未填写 jktoken 变量')
|
||||
|
||||
if jktoken:
|
||||
try:
|
||||
z = 1
|
||||
for ck in jktoken:
|
||||
print(f'登录第{z}个账号')
|
||||
print('----------------------\n')
|
||||
access_token = refresh_token(ck)
|
||||
if access_token:
|
||||
user_nickname = get_userinfo(access_token)
|
||||
print(f'[{user_nickname}] 刷新token成功')
|
||||
print('\n开始签到操作>>>>>>>>>>\n')
|
||||
do_sign(access_token, user_nickname)
|
||||
print('\n开始执行任务>>>>>>>>>>\n')
|
||||
task_data = get_today_tasks(access_token, user_nickname)
|
||||
if task_data:
|
||||
for task in task_data:
|
||||
task_id = task['task_id']
|
||||
task_name = task['task_name']
|
||||
# print(f'[{user_nickname}] 开始执行任务:{task_name}')
|
||||
if task_name == '每日一答':
|
||||
today_question(access_token, task_id, user_nickname)
|
||||
time.sleep(1)
|
||||
task_receive(access_token, user_nickname, task_id, task_name)
|
||||
time.sleep(2)
|
||||
continue
|
||||
if task_name == '下单返币':
|
||||
continue
|
||||
if task_name == '打开健客医生App':
|
||||
continue
|
||||
do_task(access_token, user_nickname, task_id, task_name)
|
||||
time.sleep(1)
|
||||
task_receive(access_token, user_nickname, task_id, task_name)
|
||||
time.sleep(3)
|
||||
get_coin(access_token, user_nickname)
|
||||
print('\n----------------------')
|
||||
z = z + 1
|
||||
except Exception as e:
|
||||
print('未知错误:' + str(e))
|
||||
if push_message:
|
||||
try:
|
||||
send_notification_message(title='方舟健客') # 发送通知
|
||||
except Exception as e:
|
||||
print('推送失败:' + str(e))
|
||||
|
||||
389
脚本库/web版/账密/星星充电签到/2025-09-01_xxcd_40e3aef4.py
Normal file
389
脚本库/web版/账密/星星充电签到/2025-09-01_xxcd_40e3aef4.py
Normal file
@@ -0,0 +1,389 @@
|
||||
# Source: https://github.com/lksky8/sign-ql/blob/main/xxcd.py
|
||||
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/xxcd.py
|
||||
# Repo: lksky8/sign-ql
|
||||
# Path: xxcd.py
|
||||
# UploadedAt: 2025-09-01T15:45:21Z
|
||||
# SHA256: 40e3aef421127efd0fe80201c786cf341993dd4e8318fe4f8456a912aef026e0
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
"""
|
||||
星星充电签到
|
||||
作者:https://github.com/lksky8/sign-ql
|
||||
日期:2025-09-01
|
||||
|
||||
使用方法:打开app随便抓一个包,把头部'Authorization'内容填入 export startoken=""
|
||||
另外可以再填入cityid(抓包获取), export starcityid=""可填可不填
|
||||
|
||||
支持多用户运行,多用户用&或者@隔开
|
||||
|
||||
export startoken="eyJ0eXAiOiJKV1QiLCJhbGciOiJIU1NiJ9..&eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1J9.."
|
||||
export starcityid=""
|
||||
|
||||
每天运行一次即可
|
||||
cron: 0 7 * * *
|
||||
const $ = new Env("星星充电签到");
|
||||
"""
|
||||
import requests
|
||||
import re
|
||||
import os
|
||||
import datetime
|
||||
import hashlib
|
||||
import time
|
||||
|
||||
|
||||
if 'startoken' in os.environ:
|
||||
startoken = re.split("@|&",os.environ.get("startoken"))
|
||||
print(f'查找到{len(startoken)}个账号\n')
|
||||
else:
|
||||
startoken =['']
|
||||
print('无startoken变量')
|
||||
|
||||
|
||||
|
||||
if 'starcityid' in os.environ:
|
||||
cityid = os.environ.get("starcityid")
|
||||
print(f'已填入cityid:{cityid}')
|
||||
else:
|
||||
cityid = '440000'
|
||||
print('没有填写cityid,系统默认使用440000')
|
||||
|
||||
|
||||
|
||||
def md5_encrypt(text):
|
||||
md5_hash = hashlib.md5()
|
||||
md5_hash.update(text.encode('utf-8'))
|
||||
md5_result = md5_hash.hexdigest()
|
||||
return md5_result
|
||||
|
||||
def time13():
|
||||
now = datetime.datetime.now()
|
||||
timestamp_ms = int(now.timestamp() * 1000) + (now.microsecond // 1000)
|
||||
return str(timestamp_ms)
|
||||
|
||||
|
||||
def find_task_ids(data):
|
||||
this_week_task_id = None
|
||||
this_month_task_id = None
|
||||
for model in data:
|
||||
for task in model['taskList']:
|
||||
if task['taskName'] == '本周充电任务':
|
||||
this_week_task_id = task['taskId']
|
||||
elif task['taskName'] == '本月充电任务':
|
||||
this_month_task_id = task['taskId']
|
||||
return this_week_task_id, this_month_task_id
|
||||
|
||||
|
||||
send_msg = ''
|
||||
one_msg = ''
|
||||
|
||||
|
||||
def Log(cont=''):
|
||||
global send_msg, one_msg
|
||||
if cont:
|
||||
one_msg += f'{cont}\n'
|
||||
send_msg += f'{cont}\n'
|
||||
|
||||
|
||||
# 发送通知消息
|
||||
def send_notification_message(title):
|
||||
try:
|
||||
from notify import send
|
||||
print("加载通知服务成功!")
|
||||
send(title, send_msg)
|
||||
except Exception as e:
|
||||
if e:
|
||||
print('发送通知消息失败!')
|
||||
|
||||
|
||||
def sign(token):
|
||||
try:
|
||||
timestamp = time13()
|
||||
signature = md5_encrypt(f'nonce=2b4aa7d9-4137-4e51-94e3-7b7355bf202a×tamp={timestamp}&userId=')[0:18].upper()
|
||||
headers = {
|
||||
'Host': 'gateway.starcharge.com',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
|
||||
'Referer': 'https://scm-app-h5.starcharge.com/',
|
||||
'appVersion': '7.40.0',
|
||||
'Origin': 'https://scm-app-h5.starcharge.com',
|
||||
'signature': signature,
|
||||
'Sec-Fetch-Dest': 'empty',
|
||||
'Sec-Fetch-Site': 'same-site',
|
||||
'referrer': 'web',
|
||||
'timestamp': timestamp,
|
||||
'positCity': cityid,
|
||||
'Authorization': token,
|
||||
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
'channel-id': '98',
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
}
|
||||
data = {
|
||||
'nonce': '2b4aa7d9-4137-4e51-94e3-7b7355bf202a',
|
||||
'timestamp': timestamp,
|
||||
'userId': '',
|
||||
}
|
||||
response = requests.post('https://gateway.starcharge.com/apph5/webApiV2/starPoint/sign',headers=headers, data=data)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '200':
|
||||
print(f"签到成功:获得{response_json['data']['basePoint']}积分,已连续签到{response_json['data']['continuousDay']}天")
|
||||
Log(f"签到成功:获得{response_json['data']['basePoint']}积分,已连续签到{response_json['data']['continuousDay']}天")
|
||||
return True
|
||||
elif response_json['code'] == '402':
|
||||
print('用户数据获取失败,重新尝试获取数据')
|
||||
return False
|
||||
else:
|
||||
print("签到失败:", response.text)
|
||||
return False
|
||||
except requests.exceptions.RequestException as e:
|
||||
print("Failed to send POST request. Status Code:", response.status_code)
|
||||
except Exception as e:
|
||||
print("签到出错了:", e)
|
||||
|
||||
|
||||
def Get_list(token):
|
||||
try:
|
||||
timestamp = time13()
|
||||
signature = md5_encrypt(f'city={cityid}&nonce=1b93f289-32ee-4616-a860-5aef04c6c048×tamp={timestamp}&userId=')[0:18].upper()
|
||||
headers = {
|
||||
'Host': 'gateway.starcharge.com',
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
'memberAdType': '0-0',
|
||||
'Authorization': token,
|
||||
'timestamp': timestamp,
|
||||
'appVersion': '7.40.0',
|
||||
'channel-id': '98',
|
||||
'referrer': 'web',
|
||||
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
|
||||
'signature': signature,
|
||||
'positCity': cityid,
|
||||
'Origin': 'https://scm-app-h5.starcharge.com',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_8_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
|
||||
'Referer': 'https://scm-app-h5.starcharge.com/',
|
||||
}
|
||||
response = requests.get(f'https://gateway.starcharge.com/apph5/webApiV2/userTask/model/list?city={cityid}&nonce=1b93f289-32ee-4616-a860-5aef04c6c048',headers=headers)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '200':
|
||||
return response_json['data']
|
||||
else:
|
||||
print("获取任务列表失败:", response.text)
|
||||
return False
|
||||
except requests.exceptions.RequestException as e:
|
||||
print("An error occurred:", e)
|
||||
except Exception as e:
|
||||
print("获取任务列表出错了:", e)
|
||||
|
||||
|
||||
def Do_task(task_id,token):
|
||||
try:
|
||||
timestamp = time13()
|
||||
signature = md5_encrypt(f'nonce=4f63ecd8-e342-4e33-94a4-81bdfd040235&taskId={task_id}&taskType=1×tamp={timestamp}&userId=')[0:18].upper()
|
||||
headers = {
|
||||
'Host': 'gateway.starcharge.com',
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
'memberAdType': '0-0',
|
||||
'Authorization': token,
|
||||
'timestamp': timestamp,
|
||||
'appVersion': '7.40.0',
|
||||
'channel-id': '98',
|
||||
'referrer': 'web',
|
||||
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
|
||||
'signature': signature,
|
||||
'positCity': cityid,
|
||||
'Origin': 'https://scm-app-h5.starcharge.com',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_8_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
|
||||
'Referer': 'https://scm-app-h5.starcharge.com/',
|
||||
}
|
||||
response = requests.get(f'https://gateway.starcharge.com/apph5/webApiV2/userTask/get?taskId={task_id}&taskType=1&nonce=4f63ecd8-e342-4e33-94a4-81bdfd040235', headers=headers)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == None:
|
||||
return response_json['text']
|
||||
elif response_json['code'] == '200' and response_json['text'] == None :
|
||||
return '任务已领取'
|
||||
else:
|
||||
print("做任务:", response.text)
|
||||
return False
|
||||
except requests.exceptions.RequestException as e:
|
||||
print("An error occurred:", e)
|
||||
|
||||
|
||||
def Get_info(token):
|
||||
try:
|
||||
timestamp = time13()
|
||||
signature = md5_encrypt(f'city={cityid}&nonce=b7e92ec1-813f-4ec2-ab8a-e91289604733×tamp={timestamp}&userId=')[0:18].upper()
|
||||
headers = {
|
||||
'Host': 'gateway.starcharge.com',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
|
||||
'Referer': 'https://scm-app-h5.starcharge.com/',
|
||||
'appVersion': '7.40.0',
|
||||
'Origin': 'https://scm-app-h5.starcharge.com',
|
||||
'signature': signature,
|
||||
'Sec-Fetch-Dest': 'empty',
|
||||
'Sec-Fetch-Site': 'same-site',
|
||||
'referrer': 'web',
|
||||
'timestamp': timestamp,
|
||||
'positCity': cityid,
|
||||
'Authorization': token,
|
||||
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
'channel-id': '98',
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
}
|
||||
response = requests.get(f'https://gateway.starcharge.com/apph5/v2/webApiV2/star/point/user?city={cityid}&nonce=b7e92ec1-813f-4ec2-ab8a-e91289604733', headers=headers)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '200':
|
||||
print(f'用户({response_json["data"]["nickName"]})目前金币:{response_json["data"]["points"]}')
|
||||
Log(f'用户({response_json["data"]["nickName"]})目前金币:{response_json["data"]["points"]}\n')
|
||||
else:
|
||||
print('用户数据查询失败:' + response.text)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print("An error occurred:", e)
|
||||
except Exception as e:
|
||||
print("查询用户数据出错了:", e)
|
||||
|
||||
def Get_user_info(token):
|
||||
try:
|
||||
timestamp = time13()
|
||||
signature = md5_encrypt(f'cityCode={cityid}&nonce=b6efee74-2ad5-43b3-bf3f-2435613c7c9d×tamp={timestamp}&userId=')[0:18].upper()
|
||||
headers = {
|
||||
'Host': 'gateway.starcharge.com',
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
'Authorization': token,
|
||||
'timestamp': timestamp,
|
||||
'Sec-Fetch-Site': 'same-site',
|
||||
'appVersion': '7.40.0',
|
||||
'channel-id': '98',
|
||||
'referrer': 'web',
|
||||
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
|
||||
'signature': signature,
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
'Origin': 'https://scm-app-h5.starcharge.com',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
|
||||
'Referer': 'https://scm-app-h5.starcharge.com/',
|
||||
'positCity': cityid,
|
||||
'Sec-Fetch-Dest': 'empty',
|
||||
}
|
||||
response = requests.get(f'https://gateway.starcharge.com/apph5/webApiV2/user/getUserBaseInfo?cityCode={cityid}&nonce=b6efee74-2ad5-43b3-bf3f-2435613c7c9d', headers=headers)
|
||||
response_data = response.json()
|
||||
if response_data['code'] == '200':
|
||||
if response_data['data']['appVipType'] == 1:
|
||||
print(f'用户({response_data["data"]["nickName"]})已开通VIP,到期日:{response_data["data"]["appVipExpiration"]}')
|
||||
vip_sign(token)
|
||||
check_vip_sign(token)
|
||||
else:
|
||||
print(f'用户({response_data["data"]["nickName"]}) 未开通VIP')
|
||||
else:
|
||||
print('查询是否VIP失败:' + response.text)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print("An error occurred:", e)
|
||||
except Exception as e:
|
||||
print("查询是否VIP出错了:", e)
|
||||
|
||||
|
||||
def vip_sign(token):
|
||||
try:
|
||||
timestamp = time13()
|
||||
signature = md5_encrypt('nonce=8f396424-3729-4f50-bf67-bfb8fe38b9c5×tamp='+timestamp+'&userId=')[0:18].upper()
|
||||
headers = {
|
||||
'Host': 'gateway.starcharge.com',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
|
||||
'Referer': 'https://scm-app-h5.starcharge.com/',
|
||||
'appVersion': '7.40.0',
|
||||
'Origin': 'https://scm-app-h5.starcharge.com',
|
||||
'signature': signature,
|
||||
'Sec-Fetch-Dest': 'empty',
|
||||
'Sec-Fetch-Site': 'same-site',
|
||||
'referrer': 'web',
|
||||
'timestamp': timestamp,
|
||||
'positCity': '440600',
|
||||
'Authorization': token,
|
||||
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
'channel-id': '98',
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
}
|
||||
data = {
|
||||
'nonce': '8f396424-3729-4f50-bf67-bfb8fe38b9c5',
|
||||
'timestamp': timestamp,
|
||||
'userId': '',
|
||||
}
|
||||
response = requests.post('https://gateway.starcharge.com/apph5/webApiV2/member/v5/home/sign',headers=headers, data=data).json()
|
||||
if response['code'] == '200':
|
||||
print(f"VIP任务:签到成功")
|
||||
else:
|
||||
print("VIP任务:签到失败" + response['text'])
|
||||
except requests.exceptions.RequestException as e:
|
||||
print("An error occurred:", e)
|
||||
except Exception as e:
|
||||
print("出错了:", e)
|
||||
|
||||
def check_vip_sign(token):
|
||||
try:
|
||||
timestamp = time13()
|
||||
signature = md5_encrypt(f'cycleType=1&nonce=2d3d2147-dbce-42b4-8fa9-9268b4fa580f×tamp={timestamp}&userId=')[0:18].upper()
|
||||
headers = {
|
||||
'Host': 'gateway.starcharge.com',
|
||||
'memberAdType': '0-0',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
|
||||
'Referer': 'https://app-taro.starcharge.com/',
|
||||
'appVersion': '7.40.0',
|
||||
'Origin': 'https://app-taro.starcharge.com',
|
||||
'signature': signature,
|
||||
'Sec-Fetch-Dest': 'empty',
|
||||
'Sec-Fetch-Site': 'same-site',
|
||||
'referrer': 'web',
|
||||
'timestamp': timestamp,
|
||||
'positCity': '440600',
|
||||
'Authorization': token,
|
||||
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
|
||||
'Accept': '*/*',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'channel-id': '98',
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
}
|
||||
response = requests.get(f'https://gateway.starcharge.com/apph5/webApiV2/member/v5/home/sign/records?cycleType=1&nonce=2d3d2147-dbce-42b4-8fa9-9268b4fa580f×tamp={timestamp}&userId=',headers=headers).json()
|
||||
if response['code'] == '200':
|
||||
print(f"VIP任务:已连续签到{response['data']['continuousDays']}天")
|
||||
else:
|
||||
print("VIP任务查询失败" + response)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print("An error occurred:", e)
|
||||
except Exception as e:
|
||||
print("出错了:", e)
|
||||
|
||||
def main():
|
||||
z = 1
|
||||
for ck in startoken:
|
||||
try:
|
||||
print(f'登录第{z}个账号')
|
||||
print('----------------------')
|
||||
print('\n开始签到操作>>>>>>>>>>\n')
|
||||
while True:
|
||||
if sign(ck):
|
||||
break
|
||||
time.sleep(3)
|
||||
print('\n完成日常任务>>>>>>>>>>\n')
|
||||
this_week_id, this_month_id = find_task_ids(Get_list(ck))
|
||||
print("本周充电任务:", Do_task(this_week_id,ck))
|
||||
print("本月充电任务:", Do_task(this_month_id,ck))
|
||||
print('\n获取用户信息>>>>>>>>>>\n')
|
||||
Get_info(ck)
|
||||
Get_user_info(ck)
|
||||
print('\n----------------------')
|
||||
z = z + 1
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
main()
|
||||
except Exception as e:
|
||||
print(e)
|
||||
try:
|
||||
send_notification_message(title='星星充电') # 发送通知
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
389
脚本库/web版/账密/星星充电签到/2026-05-23_xxcd_40e3aef4.py
Normal file
389
脚本库/web版/账密/星星充电签到/2026-05-23_xxcd_40e3aef4.py
Normal file
@@ -0,0 +1,389 @@
|
||||
# Source: https://github.com/lksky8/sign-ql/blob/main/xxcd.py
|
||||
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/xxcd.py
|
||||
# Repo: lksky8/sign-ql
|
||||
# Path: xxcd.py
|
||||
# UploadedAt: 2026-05-23T06:33:21Z
|
||||
# SHA256: 40e3aef421127efd0fe80201c786cf341993dd4e8318fe4f8456a912aef026e0
|
||||
# Category: web版/账密
|
||||
# Evidence: web/H5关键词 + username/password/login
|
||||
|
||||
"""
|
||||
星星充电签到
|
||||
作者:https://github.com/lksky8/sign-ql
|
||||
日期:2025-09-01
|
||||
|
||||
使用方法:打开app随便抓一个包,把头部'Authorization'内容填入 export startoken=""
|
||||
另外可以再填入cityid(抓包获取), export starcityid=""可填可不填
|
||||
|
||||
支持多用户运行,多用户用&或者@隔开
|
||||
|
||||
export startoken="eyJ0eXAiOiJKV1QiLCJhbGciOiJIU1NiJ9..&eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1J9.."
|
||||
export starcityid=""
|
||||
|
||||
每天运行一次即可
|
||||
cron: 0 7 * * *
|
||||
const $ = new Env("星星充电签到");
|
||||
"""
|
||||
import requests
|
||||
import re
|
||||
import os
|
||||
import datetime
|
||||
import hashlib
|
||||
import time
|
||||
|
||||
|
||||
if 'startoken' in os.environ:
|
||||
startoken = re.split("@|&",os.environ.get("startoken"))
|
||||
print(f'查找到{len(startoken)}个账号\n')
|
||||
else:
|
||||
startoken =['']
|
||||
print('无startoken变量')
|
||||
|
||||
|
||||
|
||||
if 'starcityid' in os.environ:
|
||||
cityid = os.environ.get("starcityid")
|
||||
print(f'已填入cityid:{cityid}')
|
||||
else:
|
||||
cityid = '440000'
|
||||
print('没有填写cityid,系统默认使用440000')
|
||||
|
||||
|
||||
|
||||
def md5_encrypt(text):
|
||||
md5_hash = hashlib.md5()
|
||||
md5_hash.update(text.encode('utf-8'))
|
||||
md5_result = md5_hash.hexdigest()
|
||||
return md5_result
|
||||
|
||||
def time13():
|
||||
now = datetime.datetime.now()
|
||||
timestamp_ms = int(now.timestamp() * 1000) + (now.microsecond // 1000)
|
||||
return str(timestamp_ms)
|
||||
|
||||
|
||||
def find_task_ids(data):
|
||||
this_week_task_id = None
|
||||
this_month_task_id = None
|
||||
for model in data:
|
||||
for task in model['taskList']:
|
||||
if task['taskName'] == '本周充电任务':
|
||||
this_week_task_id = task['taskId']
|
||||
elif task['taskName'] == '本月充电任务':
|
||||
this_month_task_id = task['taskId']
|
||||
return this_week_task_id, this_month_task_id
|
||||
|
||||
|
||||
send_msg = ''
|
||||
one_msg = ''
|
||||
|
||||
|
||||
def Log(cont=''):
|
||||
global send_msg, one_msg
|
||||
if cont:
|
||||
one_msg += f'{cont}\n'
|
||||
send_msg += f'{cont}\n'
|
||||
|
||||
|
||||
# 发送通知消息
|
||||
def send_notification_message(title):
|
||||
try:
|
||||
from notify import send
|
||||
print("加载通知服务成功!")
|
||||
send(title, send_msg)
|
||||
except Exception as e:
|
||||
if e:
|
||||
print('发送通知消息失败!')
|
||||
|
||||
|
||||
def sign(token):
|
||||
try:
|
||||
timestamp = time13()
|
||||
signature = md5_encrypt(f'nonce=2b4aa7d9-4137-4e51-94e3-7b7355bf202a×tamp={timestamp}&userId=')[0:18].upper()
|
||||
headers = {
|
||||
'Host': 'gateway.starcharge.com',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
|
||||
'Referer': 'https://scm-app-h5.starcharge.com/',
|
||||
'appVersion': '7.40.0',
|
||||
'Origin': 'https://scm-app-h5.starcharge.com',
|
||||
'signature': signature,
|
||||
'Sec-Fetch-Dest': 'empty',
|
||||
'Sec-Fetch-Site': 'same-site',
|
||||
'referrer': 'web',
|
||||
'timestamp': timestamp,
|
||||
'positCity': cityid,
|
||||
'Authorization': token,
|
||||
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
'channel-id': '98',
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
}
|
||||
data = {
|
||||
'nonce': '2b4aa7d9-4137-4e51-94e3-7b7355bf202a',
|
||||
'timestamp': timestamp,
|
||||
'userId': '',
|
||||
}
|
||||
response = requests.post('https://gateway.starcharge.com/apph5/webApiV2/starPoint/sign',headers=headers, data=data)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '200':
|
||||
print(f"签到成功:获得{response_json['data']['basePoint']}积分,已连续签到{response_json['data']['continuousDay']}天")
|
||||
Log(f"签到成功:获得{response_json['data']['basePoint']}积分,已连续签到{response_json['data']['continuousDay']}天")
|
||||
return True
|
||||
elif response_json['code'] == '402':
|
||||
print('用户数据获取失败,重新尝试获取数据')
|
||||
return False
|
||||
else:
|
||||
print("签到失败:", response.text)
|
||||
return False
|
||||
except requests.exceptions.RequestException as e:
|
||||
print("Failed to send POST request. Status Code:", response.status_code)
|
||||
except Exception as e:
|
||||
print("签到出错了:", e)
|
||||
|
||||
|
||||
def Get_list(token):
|
||||
try:
|
||||
timestamp = time13()
|
||||
signature = md5_encrypt(f'city={cityid}&nonce=1b93f289-32ee-4616-a860-5aef04c6c048×tamp={timestamp}&userId=')[0:18].upper()
|
||||
headers = {
|
||||
'Host': 'gateway.starcharge.com',
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
'memberAdType': '0-0',
|
||||
'Authorization': token,
|
||||
'timestamp': timestamp,
|
||||
'appVersion': '7.40.0',
|
||||
'channel-id': '98',
|
||||
'referrer': 'web',
|
||||
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
|
||||
'signature': signature,
|
||||
'positCity': cityid,
|
||||
'Origin': 'https://scm-app-h5.starcharge.com',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_8_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
|
||||
'Referer': 'https://scm-app-h5.starcharge.com/',
|
||||
}
|
||||
response = requests.get(f'https://gateway.starcharge.com/apph5/webApiV2/userTask/model/list?city={cityid}&nonce=1b93f289-32ee-4616-a860-5aef04c6c048',headers=headers)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '200':
|
||||
return response_json['data']
|
||||
else:
|
||||
print("获取任务列表失败:", response.text)
|
||||
return False
|
||||
except requests.exceptions.RequestException as e:
|
||||
print("An error occurred:", e)
|
||||
except Exception as e:
|
||||
print("获取任务列表出错了:", e)
|
||||
|
||||
|
||||
def Do_task(task_id,token):
|
||||
try:
|
||||
timestamp = time13()
|
||||
signature = md5_encrypt(f'nonce=4f63ecd8-e342-4e33-94a4-81bdfd040235&taskId={task_id}&taskType=1×tamp={timestamp}&userId=')[0:18].upper()
|
||||
headers = {
|
||||
'Host': 'gateway.starcharge.com',
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
'memberAdType': '0-0',
|
||||
'Authorization': token,
|
||||
'timestamp': timestamp,
|
||||
'appVersion': '7.40.0',
|
||||
'channel-id': '98',
|
||||
'referrer': 'web',
|
||||
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
|
||||
'signature': signature,
|
||||
'positCity': cityid,
|
||||
'Origin': 'https://scm-app-h5.starcharge.com',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_8_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
|
||||
'Referer': 'https://scm-app-h5.starcharge.com/',
|
||||
}
|
||||
response = requests.get(f'https://gateway.starcharge.com/apph5/webApiV2/userTask/get?taskId={task_id}&taskType=1&nonce=4f63ecd8-e342-4e33-94a4-81bdfd040235', headers=headers)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == None:
|
||||
return response_json['text']
|
||||
elif response_json['code'] == '200' and response_json['text'] == None :
|
||||
return '任务已领取'
|
||||
else:
|
||||
print("做任务:", response.text)
|
||||
return False
|
||||
except requests.exceptions.RequestException as e:
|
||||
print("An error occurred:", e)
|
||||
|
||||
|
||||
def Get_info(token):
|
||||
try:
|
||||
timestamp = time13()
|
||||
signature = md5_encrypt(f'city={cityid}&nonce=b7e92ec1-813f-4ec2-ab8a-e91289604733×tamp={timestamp}&userId=')[0:18].upper()
|
||||
headers = {
|
||||
'Host': 'gateway.starcharge.com',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
|
||||
'Referer': 'https://scm-app-h5.starcharge.com/',
|
||||
'appVersion': '7.40.0',
|
||||
'Origin': 'https://scm-app-h5.starcharge.com',
|
||||
'signature': signature,
|
||||
'Sec-Fetch-Dest': 'empty',
|
||||
'Sec-Fetch-Site': 'same-site',
|
||||
'referrer': 'web',
|
||||
'timestamp': timestamp,
|
||||
'positCity': cityid,
|
||||
'Authorization': token,
|
||||
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
'channel-id': '98',
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
}
|
||||
response = requests.get(f'https://gateway.starcharge.com/apph5/v2/webApiV2/star/point/user?city={cityid}&nonce=b7e92ec1-813f-4ec2-ab8a-e91289604733', headers=headers)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '200':
|
||||
print(f'用户({response_json["data"]["nickName"]})目前金币:{response_json["data"]["points"]}')
|
||||
Log(f'用户({response_json["data"]["nickName"]})目前金币:{response_json["data"]["points"]}\n')
|
||||
else:
|
||||
print('用户数据查询失败:' + response.text)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print("An error occurred:", e)
|
||||
except Exception as e:
|
||||
print("查询用户数据出错了:", e)
|
||||
|
||||
def Get_user_info(token):
|
||||
try:
|
||||
timestamp = time13()
|
||||
signature = md5_encrypt(f'cityCode={cityid}&nonce=b6efee74-2ad5-43b3-bf3f-2435613c7c9d×tamp={timestamp}&userId=')[0:18].upper()
|
||||
headers = {
|
||||
'Host': 'gateway.starcharge.com',
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
'Authorization': token,
|
||||
'timestamp': timestamp,
|
||||
'Sec-Fetch-Site': 'same-site',
|
||||
'appVersion': '7.40.0',
|
||||
'channel-id': '98',
|
||||
'referrer': 'web',
|
||||
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
|
||||
'signature': signature,
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
'Origin': 'https://scm-app-h5.starcharge.com',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
|
||||
'Referer': 'https://scm-app-h5.starcharge.com/',
|
||||
'positCity': cityid,
|
||||
'Sec-Fetch-Dest': 'empty',
|
||||
}
|
||||
response = requests.get(f'https://gateway.starcharge.com/apph5/webApiV2/user/getUserBaseInfo?cityCode={cityid}&nonce=b6efee74-2ad5-43b3-bf3f-2435613c7c9d', headers=headers)
|
||||
response_data = response.json()
|
||||
if response_data['code'] == '200':
|
||||
if response_data['data']['appVipType'] == 1:
|
||||
print(f'用户({response_data["data"]["nickName"]})已开通VIP,到期日:{response_data["data"]["appVipExpiration"]}')
|
||||
vip_sign(token)
|
||||
check_vip_sign(token)
|
||||
else:
|
||||
print(f'用户({response_data["data"]["nickName"]}) 未开通VIP')
|
||||
else:
|
||||
print('查询是否VIP失败:' + response.text)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print("An error occurred:", e)
|
||||
except Exception as e:
|
||||
print("查询是否VIP出错了:", e)
|
||||
|
||||
|
||||
def vip_sign(token):
|
||||
try:
|
||||
timestamp = time13()
|
||||
signature = md5_encrypt('nonce=8f396424-3729-4f50-bf67-bfb8fe38b9c5×tamp='+timestamp+'&userId=')[0:18].upper()
|
||||
headers = {
|
||||
'Host': 'gateway.starcharge.com',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
|
||||
'Referer': 'https://scm-app-h5.starcharge.com/',
|
||||
'appVersion': '7.40.0',
|
||||
'Origin': 'https://scm-app-h5.starcharge.com',
|
||||
'signature': signature,
|
||||
'Sec-Fetch-Dest': 'empty',
|
||||
'Sec-Fetch-Site': 'same-site',
|
||||
'referrer': 'web',
|
||||
'timestamp': timestamp,
|
||||
'positCity': '440600',
|
||||
'Authorization': token,
|
||||
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
|
||||
'Accept': 'application/json, text/plain, */*',
|
||||
'channel-id': '98',
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
}
|
||||
data = {
|
||||
'nonce': '8f396424-3729-4f50-bf67-bfb8fe38b9c5',
|
||||
'timestamp': timestamp,
|
||||
'userId': '',
|
||||
}
|
||||
response = requests.post('https://gateway.starcharge.com/apph5/webApiV2/member/v5/home/sign',headers=headers, data=data).json()
|
||||
if response['code'] == '200':
|
||||
print(f"VIP任务:签到成功")
|
||||
else:
|
||||
print("VIP任务:签到失败" + response['text'])
|
||||
except requests.exceptions.RequestException as e:
|
||||
print("An error occurred:", e)
|
||||
except Exception as e:
|
||||
print("出错了:", e)
|
||||
|
||||
def check_vip_sign(token):
|
||||
try:
|
||||
timestamp = time13()
|
||||
signature = md5_encrypt(f'cycleType=1&nonce=2d3d2147-dbce-42b4-8fa9-9268b4fa580f×tamp={timestamp}&userId=')[0:18].upper()
|
||||
headers = {
|
||||
'Host': 'gateway.starcharge.com',
|
||||
'memberAdType': '0-0',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148',
|
||||
'Referer': 'https://app-taro.starcharge.com/',
|
||||
'appVersion': '7.40.0',
|
||||
'Origin': 'https://app-taro.starcharge.com',
|
||||
'signature': signature,
|
||||
'Sec-Fetch-Dest': 'empty',
|
||||
'Sec-Fetch-Site': 'same-site',
|
||||
'referrer': 'web',
|
||||
'timestamp': timestamp,
|
||||
'positCity': '440600',
|
||||
'Authorization': token,
|
||||
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
|
||||
'Accept': '*/*',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'channel-id': '98',
|
||||
'Sec-Fetch-Mode': 'cors',
|
||||
}
|
||||
response = requests.get(f'https://gateway.starcharge.com/apph5/webApiV2/member/v5/home/sign/records?cycleType=1&nonce=2d3d2147-dbce-42b4-8fa9-9268b4fa580f×tamp={timestamp}&userId=',headers=headers).json()
|
||||
if response['code'] == '200':
|
||||
print(f"VIP任务:已连续签到{response['data']['continuousDays']}天")
|
||||
else:
|
||||
print("VIP任务查询失败" + response)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print("An error occurred:", e)
|
||||
except Exception as e:
|
||||
print("出错了:", e)
|
||||
|
||||
def main():
|
||||
z = 1
|
||||
for ck in startoken:
|
||||
try:
|
||||
print(f'登录第{z}个账号')
|
||||
print('----------------------')
|
||||
print('\n开始签到操作>>>>>>>>>>\n')
|
||||
while True:
|
||||
if sign(ck):
|
||||
break
|
||||
time.sleep(3)
|
||||
print('\n完成日常任务>>>>>>>>>>\n')
|
||||
this_week_id, this_month_id = find_task_ids(Get_list(ck))
|
||||
print("本周充电任务:", Do_task(this_week_id,ck))
|
||||
print("本月充电任务:", Do_task(this_month_id,ck))
|
||||
print('\n获取用户信息>>>>>>>>>>\n')
|
||||
Get_info(ck)
|
||||
Get_user_info(ck)
|
||||
print('\n----------------------')
|
||||
z = z + 1
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
main()
|
||||
except Exception as e:
|
||||
print(e)
|
||||
try:
|
||||
send_notification_message(title='星星充电') # 发送通知
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
487
脚本库/微信小程序/抓包版/cloud189/2025-09-06_cloud189_7c90c2eb.py
Normal file
487
脚本库/微信小程序/抓包版/cloud189/2025-09-06_cloud189_7c90c2eb.py
Normal file
@@ -0,0 +1,487 @@
|
||||
# Source: https://github.com/lksky8/sign-ql/blob/main/cloud189.py
|
||||
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/cloud189.py
|
||||
# Repo: lksky8/sign-ql
|
||||
# Path: cloud189.py
|
||||
# UploadedAt: 2025-09-06T12:51:46Z
|
||||
# SHA256: 7c90c2eb0032873254db7819a42440cd062ae32af3fa537efc7c295c0e1da804
|
||||
# Category: 微信小程序/抓包版
|
||||
# Evidence: appid/openid/session_key/encryptedData等小程序字段
|
||||
|
||||
"""
|
||||
天翼云盘签到
|
||||
|
||||
作者:https://github.com/lksky8/sign-ql
|
||||
最后更新日期:2025-9-6
|
||||
如脚本无法运行,先在青龙依赖管理的Python里面安装pycryptodome这个包
|
||||
食用方法:打开天翼云盘app抓请求url=api.cloud.189.cn/guns/getPageBanners.action里面accessToken(一般在请求头里)填到变量cloud189_token里面即可
|
||||
支持多用户运行
|
||||
多用户用&或者@隔开
|
||||
例如账号1:10086 账号2: 1008611
|
||||
则变量为
|
||||
export cloud189_token="10086&1008611"
|
||||
|
||||
cron: 50 1,18 * * *
|
||||
"""
|
||||
import requests
|
||||
import time
|
||||
import hmac
|
||||
import hashlib
|
||||
import base64
|
||||
import os
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Util.Padding import pad, unpad
|
||||
from Crypto.Cipher import PKCS1_v1_5
|
||||
import re
|
||||
from urllib.parse import unquote
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
if 'cloud189_token' in os.environ:
|
||||
cloud189_token = re.split("@|&",os.environ.get("cloud189_token"))
|
||||
print(f'查找到{len(cloud189_token)}个账号')
|
||||
else:
|
||||
cloud189_token =['']
|
||||
print('无cloud189_token变量')
|
||||
|
||||
|
||||
|
||||
|
||||
aes_iv = "Zx8dG46ax3Mc8Mj2".encode() # 16 字节
|
||||
aes_key = "bf8395f745c04f23".encode() # 16 字节
|
||||
# RSA_PUBLIC_KEY_PEM = """-----BEGIN PUBLIC KEY-----
|
||||
# MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDaoVRMEdxN2LZj7f0UL/0OMJJj
|
||||
# GuD1OgDRF4WTY1ZCupektwYvS5nU2FelBJ9bV5dv5MVYAp6r9rOkRwE+PEvgwaVP
|
||||
# ghwfNg1ljCkQ2QFNAmwKHF/sjgHsHu94IbYL7MokSETU6Y4d5k+Vm/3qvqxZs8Yf
|
||||
# 1HGx3ojEU6Atxqp/QwIDAQAB
|
||||
# -----END PUBLIC KEY-----"""
|
||||
RSA_PUBLIC_KEY_PEM = """-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDC72L803mNmrQgyvaU
|
||||
t115S5gSHuDcS+nGdqBakHYqFShEwrEaqKsr2Z/7DQt9AobB0ne2vIS
|
||||
UW0tXjhgf5vfl00kT7K+J4j+t3WLkQ6Zwc9KtZHkSW6/fkFSC1EnShP
|
||||
YLsG6rHYa5+wfefOY2P7yEFRsd5DGCqHNWkzOZclsXawIDAQAB
|
||||
-----END PUBLIC KEY-----"""
|
||||
|
||||
# AES CBC 加密函数
|
||||
def aes_cbc_encrypt(plaintext, key, iv):
|
||||
cipher = AES.new(key, AES.MODE_CBC, iv)
|
||||
padded_plaintext = pad(plaintext.encode('utf-8'), AES.block_size)
|
||||
ciphertext = cipher.encrypt(padded_plaintext)
|
||||
return base64.b64encode(ciphertext).decode('utf-8')
|
||||
|
||||
# AES CBC 解密函数
|
||||
def aes_cbc_decrypt(ciphertext, key, iv):
|
||||
ciphertext = base64.b64decode(ciphertext)
|
||||
cipher = AES.new(key, AES.MODE_CBC, iv)
|
||||
padded_plaintext = cipher.decrypt(ciphertext)
|
||||
plaintext = unpad(padded_plaintext, AES.block_size)
|
||||
return plaintext.decode('utf-8')
|
||||
|
||||
def encrypt_aes_key(key):
|
||||
aes_session_key = key.encode('utf-8')
|
||||
rsa_public_key = RSA.import_key(RSA_PUBLIC_KEY_PEM)
|
||||
rsa_cipher = PKCS1_v1_5.new(rsa_public_key)
|
||||
encrypted_aes_key = rsa_cipher.encrypt(aes_session_key)
|
||||
return base64.b64encode(encrypted_aes_key).decode('utf-8')
|
||||
|
||||
|
||||
def md5_encrypt(plaintext):
|
||||
md5_hash = hashlib.md5()
|
||||
md5_hash.update(plaintext.encode('utf-8'))
|
||||
return md5_hash.hexdigest()
|
||||
|
||||
def hmac_sha1_hex(key, message):
|
||||
key_bytes = key.encode('utf-8')
|
||||
message_bytes = message.encode('utf-8')
|
||||
hmac_hash = hmac.new(key_bytes, message_bytes, hashlib.sha1)
|
||||
return hmac_hash.digest().hex()
|
||||
|
||||
def get_task_info(data):
|
||||
task_info = []
|
||||
for task in data["data"]:
|
||||
if not task["status"]: # 只返回未完成的任务
|
||||
task_info.append({
|
||||
"taskId": task["taskId"],
|
||||
"taskName": task["taskName"],
|
||||
})
|
||||
return task_info
|
||||
|
||||
send_msg = ''
|
||||
one_msg = ''
|
||||
|
||||
|
||||
def log(cont=''):
|
||||
global send_msg, one_msg
|
||||
if cont:
|
||||
one_msg += f'{cont}\n'
|
||||
send_msg += f'{cont}\n'
|
||||
|
||||
|
||||
# 发送通知消息
|
||||
def send_notification_message(title):
|
||||
try:
|
||||
from notify import send
|
||||
print("加载通知服务成功!")
|
||||
send(title, send_msg)
|
||||
except Exception as e:
|
||||
if e:
|
||||
print('发送通知消息失败!')
|
||||
|
||||
def generateRsakey():
|
||||
headers = {
|
||||
'Host': 'api.cloud.189.cn',
|
||||
'accept': 'application/json;charset=UTF-8',
|
||||
'accept-language': 'zh-cn',
|
||||
'x-request-id': '26E11B6CBEB94F77A2E5615C20C06113',
|
||||
'date': 'Sun, 22 Jun 2025 14:33:08 GMT',
|
||||
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_8 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Safari/604.1',
|
||||
}
|
||||
|
||||
params = {
|
||||
'clientType': 'TELEIPHONE',
|
||||
'version': '10.3.3',
|
||||
'model': 'iPhone',
|
||||
'osFamily': 'iOS',
|
||||
'osVersion': '15.8.3',
|
||||
'clientSn': '02676BE3DD-8D86-4B4F-A666-749D1D5C9FF8',
|
||||
'returnType': 'JSON',
|
||||
}
|
||||
|
||||
response = requests.get('https://api.cloud.189.cn/security/generateRsaKey.action', params=params, headers=headers).json()
|
||||
return response['pkId']
|
||||
|
||||
|
||||
def get_AccessToken(sessionKey):
|
||||
timestamp_1 = str(int(time.time()))
|
||||
signature = md5_encrypt(f'AppKey=600100422&Timestamp={timestamp_1}&sessionKey={sessionKey}')
|
||||
|
||||
headers = {
|
||||
'Host': 'api.cloud.189.cn',
|
||||
'accept': 'application/json;charset=UTF-8',
|
||||
'sign-type': '1',
|
||||
'timestamp': timestamp_1,
|
||||
'sec-fetch-site': 'same-site',
|
||||
'accept-language': 'zh-CN,zh-Hans;q=0.9',
|
||||
'signature': signature,
|
||||
'sec-fetch-mode': 'cors',
|
||||
'origin': 'https://m.cloud.189.cn',
|
||||
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Ecloud/10.3.3 iOS/16.6.1 clientId/027A8AB808-F7A5-431E-8B37-6BD9559D22D7 clientModel/iPhone proVersion/1.0.5',
|
||||
'appkey': '600100422',
|
||||
'referer': 'https://m.cloud.189.cn/',
|
||||
'sec-fetch-dest': 'empty',
|
||||
}
|
||||
|
||||
params = {
|
||||
'sessionKey': sessionKey,
|
||||
}
|
||||
|
||||
response = requests.get('https://api.cloud.189.cn/open/oauth2/getAccessTokenBySsKey.action', params=params,headers=headers).json()
|
||||
return response['accessToken']
|
||||
|
||||
|
||||
def login4MergedClient(token):
|
||||
timestamp = str(int(time.time()))
|
||||
appsignature = hmac_sha1_hex('fe5734c74c2f96a38157f420b32dc995',f'AppKey=600100885&Operate=POST&RequestURI=/login4MergedClient.action&Timestamp={timestamp}')
|
||||
param = f'isCache=1&jgOpenId=1114a89792bbaa8d350&deviceModel=iPhone%206s%20Plus&exRetryTimes=1&accessToken={token}&networkAccessMode=WIFI&telecomsOperator=&idfa=00000000-0000-0000-0000-000000000000&clientType=TELEIPHONE&version=10.3.3&model=iPhone&osFamily=iOS&osVersion=15.8.3&clientSn=02676BE3DD-8D86-4B4F-A666-749D1D5C9FF8'
|
||||
encrypted_param = aes_cbc_encrypt(param, aes_key, aes_iv)
|
||||
epkey = encrypt_aes_key("bf8395f745c04f23")
|
||||
pkId = generateRsakey()
|
||||
headers = {
|
||||
'Host': 'api.cloud.189.cn',
|
||||
'content-type': 'application/x-www-form-urlencoded',
|
||||
'epver': '2',
|
||||
'accept': '*/*',
|
||||
'epway': '3',
|
||||
'timestamp': timestamp,
|
||||
'appsignature': appsignature,
|
||||
'accept-language': 'zh-CN,zh-Hans;q=0.9',
|
||||
'x-request-id': '26E11B6CBEB94F77A2E5615C20C06113',
|
||||
'epkey': epkey,
|
||||
'appkey': '600100885',
|
||||
'user-agent': 'Cloud189/8 CFNetwork/1410.0.3 Darwin/22.6.0',
|
||||
}
|
||||
|
||||
data = {
|
||||
'pkId': pkId,
|
||||
'param': encrypted_param,
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.post('https://api.cloud.189.cn/login4MergedClient.action', headers=headers, data=data).text
|
||||
ciphertext = re.search(r'<ciphertext>(.*?)</ciphertext>', response, re.DOTALL).group(1)
|
||||
user_data = unquote(aes_cbc_decrypt(ciphertext, aes_key, aes_iv))
|
||||
# print(user_data)
|
||||
login_Name = re.search(r'<loginName>(.*?)</loginName>', user_data, re.DOTALL).group(1)
|
||||
session_Key = re.search(r'<sessionKey>(.*?)</sessionKey>', user_data, re.DOTALL).group(1)
|
||||
sessionSecret = re.search(r'<sessionSecret>(.*?)</sessionSecret>', user_data, re.DOTALL).group(1)
|
||||
familySessionKey = re.search(r'<familySessionKey>(.*?)</familySessionKey>', user_data, re.DOTALL).group(1)
|
||||
return login_Name, session_Key,sessionSecret,familySessionKey
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return False
|
||||
|
||||
|
||||
def day_sign(sS,session_key):
|
||||
gmt_time = datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
|
||||
signature = hmac_sha1_hex(sS,f'SessionKey={session_key}&Operate=GET&RequestURI=/mkt/userSign.action&Date={gmt_time}')
|
||||
|
||||
headers = {
|
||||
'Host': 'api.cloud.189.cn',
|
||||
'x-request-id': '26E11B6CBEB94F77A2E5615C20C06113',
|
||||
'signature': signature,
|
||||
'date': gmt_time,
|
||||
'accept-language': 'zh-cn',
|
||||
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_8_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Ecloud/10.3.3 (iPhone; 02676BE3DD-8D86-4B4F-A666-749D1D5C9FF8; appStore) iOS/15.8.3',
|
||||
'sessionkey': session_key,
|
||||
'accept': '*/*',
|
||||
}
|
||||
|
||||
params = {
|
||||
'clientType': 'TELEIPHONE',
|
||||
'version': '10.3.3',
|
||||
'model': 'iPhone',
|
||||
'osFamily': 'iOS',
|
||||
'osVersion': '15.8.3',
|
||||
'clientSn': '02676BE3DD-8D86-4B4F-A666-749D1D5C9FF8',
|
||||
}
|
||||
|
||||
response = requests.get('https://api.cloud.189.cn/mkt/userSign.action', params=params, headers=headers).text
|
||||
if 'userSignResult' in response:
|
||||
print('【天翼云盘】签到成功:' + re.search(r'<resultTip>(.*?)</resultTip>', response, re.DOTALL).group(1))
|
||||
log('【天翼云盘】签到成功:' + re.search(r'<resultTip>(.*?)</resultTip>', response, re.DOTALL).group(1))
|
||||
else:
|
||||
print('【天翼云盘】签到失败:' + response)
|
||||
log('【天翼云盘】签到失败:' + response)
|
||||
|
||||
def vip_sign(session_key):
|
||||
|
||||
headers = {
|
||||
'Host': 'm.cloud.189.cn',
|
||||
'accept': 'application/json, text/plain, */*',
|
||||
'sec-fetch-site': 'same-origin',
|
||||
'sec-fetch-dest': 'empty',
|
||||
'accept-language': 'zh-CN,zh-Hans;q=0.9',
|
||||
'sec-fetch-mode': 'cors',
|
||||
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_6_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Ecloud/10.3.11 iOS/16.6.1 clientId/027A8AB808-F7A5-431E-8B37-6BD9559D22D7 clientModel/iPhone proVersion/1.0.5',
|
||||
'referer': 'https://m.cloud.189.cn/zt/2025/cloud-space-receive/index.html',
|
||||
}
|
||||
|
||||
|
||||
params = {
|
||||
'noCache': str(int(time.time() *1000)),
|
||||
'activityId': 'ACT2025VIP2T',
|
||||
'sessionKey': session_key,
|
||||
'prizeId': '2T_2025VIP',
|
||||
}
|
||||
|
||||
response = requests.get('https://m.cloud.189.cn/market/drawTargetSpace.action', params=params, headers=headers).json()
|
||||
|
||||
if response['code'] == '0' and response['message'] == '成功':
|
||||
print('【天翼云盘】2T空间月月领:领取成功')
|
||||
log('【天翼云盘】2T空间月月领:领取成功')
|
||||
else:
|
||||
print('【天翼云盘】2T空间月月领:' + response['message'])
|
||||
log('【天翼云盘】2T空间月月领:' + response['message'])
|
||||
|
||||
def ssoLoginMerge(sk,skF,token):
|
||||
print("★" * 35 )
|
||||
session = requests.Session()
|
||||
timestamp = str(int(time.time()))
|
||||
api_headers = {
|
||||
'Host': 'm.cloud.189.cn',
|
||||
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_8_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Ecloud/10.3.3 iOS/15.8.3 clientId/02676BE3DD-8D86-4B4F-A666-749D1D5C9FF8 clientModel/iPhone proVersion/1.0.5',
|
||||
'accept-language': 'zh-CN,zh-Hans;q=0.9',
|
||||
'referer': 'https://m.cloud.189.cn/zt/2024/green-task-system/index.html?uxChannel=10021132000'
|
||||
}
|
||||
session.headers.update(api_headers)
|
||||
|
||||
params = {
|
||||
'sessionKey': sk,
|
||||
'sessionKeyFm': skF,
|
||||
'eAccessToken': token,
|
||||
'redirectUrl': 'https://m.cloud.189.cn/zt/2024/green-task-system/index.html?uxChannel=10021132000',
|
||||
'rand': f'6947_{timestamp}',
|
||||
}
|
||||
# 获取cookie数据
|
||||
session.get('https://m.cloud.189.cn/ssoLoginMerge.action', params=params)
|
||||
|
||||
# 签到
|
||||
params = {
|
||||
'sessionKey': sk,
|
||||
'activityId': 'ACT2024cztx',
|
||||
}
|
||||
|
||||
response = session.get('https://m.cloud.189.cn/market/signInNew.action', params=params)
|
||||
if response.json().get('result'):
|
||||
print('【绿色能量活动】签到成功')
|
||||
log('【绿色能量活动】签到成功')
|
||||
params = {
|
||||
'sessionKey': sk,
|
||||
'activityId': 'ACT2024cztx',
|
||||
}
|
||||
|
||||
response = session.get('https://m.cloud.189.cn/market/signInNewInfo.action', params=params)
|
||||
print('【绿色能量活动】已签到,今天是本周第' + str(response.json().get('data')) + '天签到')
|
||||
else:
|
||||
print('【绿色能量活动】签到失败:' + response.text)
|
||||
log('【绿色能量活动】签到失败:' + response.text)
|
||||
|
||||
print("\n" + "-" * 50)
|
||||
print('【绿色能量活动】获取新人专属任务')
|
||||
params = {
|
||||
'sessionKey': sk,
|
||||
'activityId': 'ACT2024cztx',
|
||||
'random': '0.48929593893531875',
|
||||
'taskType': '1',
|
||||
}
|
||||
|
||||
response = session.get('https://m.cloud.189.cn/market/getGreenTaskList.action', params=params).json()
|
||||
new_task = get_task_info(response)
|
||||
|
||||
if len(new_task) > 0:
|
||||
print('【绿色能量活动】获取到' + str(len(new_task)) + '个未完成新人专属任务')
|
||||
|
||||
for task in new_task:
|
||||
task_id = task["taskId"]
|
||||
task_name = task["taskName"]
|
||||
|
||||
data = {
|
||||
'activityId': 'ACT2024cztx',
|
||||
'sessionKey': sk,
|
||||
'taskId': task_id,
|
||||
}
|
||||
|
||||
response = session.post('https://m.cloud.189.cn/market/doGreenTask.action', data=data)
|
||||
|
||||
if response.json().get('data'):
|
||||
print(f'【绿色能量活动--->新人专属任务】✅ 任务完成: {task_name}')
|
||||
else:
|
||||
print(f'【绿色能量活动--->新人专属任务】⏩ 任务已跳过: {task_name}')
|
||||
time.sleep(1)
|
||||
else:
|
||||
print('【绿色能量活动】新人专属任务已完成,跳过操作')
|
||||
|
||||
print("-" * 50 + "\n")
|
||||
print("-" * 50)
|
||||
print('【绿色能量活动】获取AI任务')
|
||||
params = {
|
||||
'sessionKey': sk,
|
||||
'activityId': 'ACT2024cztx',
|
||||
'random': '0.3382804414050936',
|
||||
'taskType': '2',
|
||||
}
|
||||
|
||||
response = session.get('https://m.cloud.189.cn/market/getGreenTaskList.action', params=params).json()
|
||||
AI_task = get_task_info(response)
|
||||
|
||||
if len(AI_task) > 0:
|
||||
print('【绿色能量活动】获取到' + str(len(AI_task)) + '个未完成日常AI任务')
|
||||
|
||||
for task in AI_task:
|
||||
task_id = task["taskId"]
|
||||
task_name = task["taskName"]
|
||||
data = {
|
||||
'activityId': 'ACT2024cztx',
|
||||
'sessionKey': sk,
|
||||
'taskId': task_id,
|
||||
}
|
||||
response = session.post('https://m.cloud.189.cn/market/doGreenTask.action', data=data)
|
||||
if response.json().get('data'):
|
||||
print(f'【绿色能量活动--->日常AI任务】✅ 任务完成: {task_name} ')
|
||||
else:
|
||||
print(f'【绿色能量活动--->日常AI任务】⏩ 任务已跳过: {task_name} ')
|
||||
time.sleep(1)
|
||||
else:
|
||||
print('【绿色能量活动】日常AI任务已完成,跳过操作')
|
||||
print("-" * 50 + "\n")
|
||||
print("-" * 50)
|
||||
print('【绿色能量活动】获取绿动任务')
|
||||
params = {
|
||||
'sessionKey': sk,
|
||||
'activityId': 'ACT2024cztx',
|
||||
'random': '0.3382804414050936',
|
||||
'taskType': '3',
|
||||
}
|
||||
|
||||
response = session.get('https://m.cloud.189.cn/market/getGreenTaskList.action', params=params).json()
|
||||
AI_task = get_task_info(response)
|
||||
|
||||
if len(AI_task) > 0:
|
||||
print('【绿色能量活动】获取到' + str(len(AI_task)) + '个未完成绿动任务')
|
||||
|
||||
for task in AI_task:
|
||||
task_id = task["taskId"]
|
||||
task_name = task["taskName"]
|
||||
data = {
|
||||
'activityId': 'ACT2024cztx',
|
||||
'sessionKey': sk,
|
||||
'taskId': task_id,
|
||||
}
|
||||
response = session.post('https://m.cloud.189.cn/market/doGreenTask.action', data=data)
|
||||
if response.json().get('data'):
|
||||
print(f'【绿色能量活动--->绿动任务】✅ 任务完成: {task_name} ')
|
||||
else:
|
||||
print(f'【绿色能量活动--->绿动任务】⏩ 任务已跳过: {task_name} ')
|
||||
time.sleep(1)
|
||||
else:
|
||||
print('【绿色能量活动】绿动任务已完成,跳过操作')
|
||||
print("-" * 50 + "\n")
|
||||
|
||||
# 获取绿色能量数据
|
||||
params = {
|
||||
'sessionKey': sk,
|
||||
'activityId': 'ACT2024cztx',
|
||||
}
|
||||
|
||||
response = requests.get('https://m.cloud.189.cn/market/getGreenLevelList.action', params=params).json()
|
||||
print('【绿色能量活动】目前能量:' + str(response['data']['userScore']) + 'g')
|
||||
log('【绿色能量活动】目前能量:' + str(response['data']['userScore']) + 'g'+ "\n")
|
||||
print("★" * 35 + "\n")
|
||||
|
||||
|
||||
def main():
|
||||
z = 1
|
||||
for ck in cloud189_token:
|
||||
try:
|
||||
print('=' * 60 + '\n')
|
||||
print(f'登录第{z}个账号')
|
||||
print('=' * 60 + '\n')
|
||||
login_result = login4MergedClient(ck)
|
||||
print('\n开始签到操作>>>>>>>>>>')
|
||||
if isinstance(login_result, tuple):
|
||||
sessionKey = login_result[1]
|
||||
sessionSecret = login_result[2]
|
||||
login_name = login_result[0]
|
||||
print(f'【{login_name}】登录成功')
|
||||
log(f'【{login_name}】登录成功')
|
||||
print('获取到的临时Session_key:' + sessionKey)
|
||||
day_sign(sessionSecret, sessionKey)
|
||||
vip_sign(sessionKey)
|
||||
print("★" * 35 + "\n")
|
||||
ssoLoginMerge(sessionKey, login_result[3], ck)
|
||||
else:
|
||||
print(f'第{z}个账号:获取sessionKey失败,请检查accessToken是否正确')
|
||||
log(f'第{z}个账号:获取sessionKey失败,请检查accessToken是否正确')
|
||||
|
||||
z = z + 1
|
||||
except Exception as e:
|
||||
print('未知错误' + str(e))
|
||||
# print(get_AccessToken(''))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
try:
|
||||
send_notification_message(title='天翼云盘签到') # 发送通知
|
||||
except Exception as e:
|
||||
print('推送出错:' + str(e))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
540
脚本库/微信小程序/抓包版/jtc/2025-10-26_jtc_d7fa5acd.py
Normal file
540
脚本库/微信小程序/抓包版/jtc/2025-10-26_jtc_d7fa5acd.py
Normal file
@@ -0,0 +1,540 @@
|
||||
# Source: https://github.com/lksky8/sign-ql/blob/main/jtc.py
|
||||
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/jtc.py
|
||||
# Repo: lksky8/sign-ql
|
||||
# Path: jtc.py
|
||||
# UploadedAt: 2025-10-26T12:24:47Z
|
||||
# SHA256: d7fa5acdc107ddb45fd772c4bb0c9491fd48e8e3d7d18ae5a4286579151676ef
|
||||
# Category: 微信小程序/抓包版
|
||||
# Evidence: appid/openid/session_key/encryptedData等小程序字段
|
||||
|
||||
"""
|
||||
捷停车签到
|
||||
|
||||
作者:https://github.com/lksky8/sign-ql
|
||||
最后更新日期:2025-10-26
|
||||
食用方法:打开捷停车app抓请求url=https://sytgate.jslife.com.cn/core-gateway/user/login/verify/token里面的deviceId和token(一般在请求参数里面)在环境变量输入export jtc_token=账号1#deviceId#token1&账号2#deviceId#token2
|
||||
支持多用户运行
|
||||
多用户用&或者@隔开
|
||||
例如账号1:账号1#C5A59624-6666-4682-9876-F8184F3D2CF0#eyJhbGciOiJIUzI1NiJ9.... 账号2#C5A59624-5555-1234-9E41-F8184F3D2CF0#eyJhbGciOiJIUzI1NiJ9....
|
||||
则变量为
|
||||
export jtc_token="账号1#C5A59624-6666-4682-9876-F8184F3D2CF0#eyJhbGciOiJIUzI1NiJ9....&账号2#C5A59624-5555-1234-9E41-F8184F3D2CF0#eyJhbGciOiJIUzI1NiJ9...."
|
||||
|
||||
cron: 12 2 * * *
|
||||
"""
|
||||
import requests
|
||||
import time
|
||||
import hashlib
|
||||
import os
|
||||
import re
|
||||
import uuid
|
||||
import json
|
||||
import random
|
||||
|
||||
|
||||
def generate_nonce():
|
||||
"""生成符合要求的UUID格式字符串"""
|
||||
return str(uuid.uuid4()).upper()
|
||||
|
||||
|
||||
if 'jtc_token' in os.environ:
|
||||
jtc_token = re.split("@|&",os.environ.get("jtc_token"))
|
||||
print(f'查找到{len(jtc_token)}个账号\n')
|
||||
else:
|
||||
jtc_token = []
|
||||
print('无jtc_token变量\n')
|
||||
|
||||
|
||||
send_msg = ''
|
||||
one_msg = ''
|
||||
|
||||
def Log(cont=''):
|
||||
global send_msg, one_msg
|
||||
if cont:
|
||||
one_msg += f'\n{cont}'
|
||||
send_msg += f'\n{cont}'
|
||||
|
||||
|
||||
|
||||
def send_notification_message(title):
|
||||
try:
|
||||
from notify import send
|
||||
print("加载通知服务成功!")
|
||||
send(title, send_msg)
|
||||
except Exception as e:
|
||||
if e:
|
||||
print('发送通知消息失败!')
|
||||
|
||||
api_headers = {
|
||||
'Host': 'sytgate.jslife.com.cn',
|
||||
'Content-Type': 'application/json;charset=utf-8',
|
||||
'applicationVersion': '60406',
|
||||
'Accept': '*/*',
|
||||
'User-Agent': 'JTC/6.4.6 (iPhone; iOS 15.8.3; Scale/3.00)',
|
||||
'Accept-Language': 'zh-Hans-CN;q=1',
|
||||
}
|
||||
|
||||
longitude = f'113.07{random.randint(100, 999)}'
|
||||
latitude = f'22.888624{random.randint(100, 999)}'
|
||||
|
||||
def md5_encrypt(text):
|
||||
return hashlib.md5(text.encode('utf-8')).hexdigest().upper()
|
||||
|
||||
|
||||
def refresh_token(user_phone,user_deviceid,user_token):
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
nonce = generate_nonce() # 生成nonce
|
||||
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&deviceId={user_deviceid}&nonce={nonce}&osType=iOS&signType=MD5×tamp={timestamp}&token={user_token}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
|
||||
json_data = {
|
||||
'deviceId': user_deviceid,
|
||||
'osType': 'iOS',
|
||||
'signType': 'MD5',
|
||||
'applictionType': 'APP',
|
||||
'applictionVersion': '60406',
|
||||
'token': user_token,
|
||||
'timestamp': timestamp,
|
||||
'sign': sign,
|
||||
'nonce': nonce
|
||||
}
|
||||
try:
|
||||
response = requests.post('https://sytgate.jslife.com.cn/core-gateway/user/login/verify/token',headers=api_headers,json=json_data)
|
||||
response_json = response.json()
|
||||
if response_json['resultCode'] == '0' and response_json['message'] == '成功':
|
||||
print(f'[{user_phone}] 刷新token成功')
|
||||
return {'new_token': response_json['obj']['token'], 'new_user_id': response_json['obj']['userId']}
|
||||
elif response_json['resultCode'] == '10011' and response_json['message'] == '用户已在其他平台登录':
|
||||
print(f'[{user_phone}] 刷新token失败:请重新获取token')
|
||||
elif response_json['resultCode'] == '3126' and response_json['message'] == 'token已过期':
|
||||
print(f'[{user_phone}] 刷新token失败:token已过期,请重新获取')
|
||||
return None
|
||||
else:
|
||||
print(f'[{user_phone}] 刷新token失败:{response_json}')
|
||||
return None
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'刷新token发生网络错误: {str(e)}')
|
||||
except (ValueError, KeyError, TypeError) as e:
|
||||
print(f'刷新token发生解析错误: {str(e)}')
|
||||
except Exception as e:
|
||||
print(f'刷新token发生未知错误: {str(e)}')
|
||||
|
||||
def get_coin(token,user_id,user_mobile):
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
nonce = generate_nonce() # 生成nonce
|
||||
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&reqSource=APP_JTC&signType=MD5×tamp={timestamp}&token={token}&userId={user_id}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
|
||||
json_data = {
|
||||
'userId': user_id,
|
||||
'signType': 'MD5',
|
||||
'reqSource': 'APP_JTC',
|
||||
'applictionType': 'APP',
|
||||
'applictionVersion': '60406',
|
||||
'token': token,
|
||||
'timestamp': timestamp,
|
||||
'sign': sign,
|
||||
'nonce': nonce,
|
||||
}
|
||||
try:
|
||||
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/integral/v2/balance/query', headers=api_headers, json=json_data)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '0' and response_json['success']:
|
||||
print(f'[{user_mobile}] 积分:{response_json["data"]["accountAmt"]},可抵扣:{response_json["data"]["deductAmount"]}元')
|
||||
Log(f'[{user_mobile}] 积分:{response_json["data"]["accountAmt"]},可抵扣:{response_json["data"]["deductAmount"]}元')
|
||||
else:
|
||||
print(f'[{user_mobile}] 查询积分失败:{response_json["message"]}')
|
||||
Log(f'[{user_mobile}] 查询积分失败:{response_json["message"]}')
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'查询用户积分发生网络错误: {str(e)}')
|
||||
except (ValueError, KeyError, TypeError) as e:
|
||||
print(f'查询用户积分发生解析错误: {str(e)}')
|
||||
except Exception as e:
|
||||
print(f'查询用户积分发生未知错误: {str(e)}')
|
||||
|
||||
def get_userinfo(token,user_id):
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
nonce = generate_nonce() # 生成nonce
|
||||
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&reqSource=APP_JTC&signType=MD5×tamp={timestamp}&token={token}&userId={user_id}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
|
||||
json_data = {
|
||||
'userId': user_id,
|
||||
'signType': 'MD5',
|
||||
'sign': sign,
|
||||
'charset': 'UTF-8',
|
||||
'reqSource': 'APP_JTC',
|
||||
'applictionType': 'APP',
|
||||
'version': 'V1.0',
|
||||
'token': token,
|
||||
'timestamp': timestamp,
|
||||
'applictionVersion': '60406',
|
||||
'nonce': nonce,
|
||||
}
|
||||
try:
|
||||
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/member/queryUserBenefitInfo',headers=api_headers, json=json_data)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '0' and response_json['success']:
|
||||
if response_json['data']['mobile'] is None:
|
||||
return None
|
||||
else:
|
||||
return response_json['data']['mobile']
|
||||
else:
|
||||
print(f'查询用户信息失败:{response_json["message"]}')
|
||||
return None
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'查询用户信息发生网络错误: {str(e)}')
|
||||
except (ValueError, KeyError, TypeError) as e:
|
||||
print(f'查询用户信息发生解析错误: {str(e)}')
|
||||
except Exception as e:
|
||||
print(f'查询用户信息发生未知错误: {str(e)}')
|
||||
|
||||
|
||||
def do_userinfo(user_id,user_mobile):
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
json_data = {
|
||||
'userId': user_id,
|
||||
'openId': '',
|
||||
'gender': 'MALE',
|
||||
'birthday': '2000-01-01',
|
||||
'province': '广东省',
|
||||
'city': '广州市',
|
||||
'platformType': 'APP_JTC',
|
||||
}
|
||||
try:
|
||||
response = requests.post(f'https://sytgate.jslife.com.cn/core-gateway/user/update/extend-info?t={timestamp}',headers=api_headers, json=json_data)
|
||||
response_json = response.json()
|
||||
if response_json['resultCode'] == '0':
|
||||
print(f'[{user_mobile}] 更新用户信息成功:{user_id}')
|
||||
if response_json['obj']:
|
||||
print(f'[{user_mobile}] 个人信息已完善并获得30停车币')
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'更新用户信息发生网络错误: {str(e)}')
|
||||
except (ValueError, KeyError, TypeError) as e:
|
||||
print(f'更新用户信息发生解析错误: {str(e)}')
|
||||
except Exception as e:
|
||||
print(f'更新用户信息发生未知错误: {str(e)}')
|
||||
|
||||
def query_task(user_token, user_id, user_mobile):
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
nonce = generate_nonce()
|
||||
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&reqSource=APP_JTC&signType=MD5×tamp={timestamp}&token={user_token}&userId={user_id}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
|
||||
json_data = {
|
||||
'osType': 'IOS',
|
||||
'signType': 'MD5',
|
||||
'userId': user_id,
|
||||
'nonce': nonce,
|
||||
'applictionType': 'APP',
|
||||
'reqVersion': 'V2.0',
|
||||
'applictionVersion': '60406',
|
||||
'token': user_token,
|
||||
'timestamp': timestamp,
|
||||
'sign': sign,
|
||||
'platformType': 'APP',
|
||||
}
|
||||
try:
|
||||
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/integral/v2/task/query',headers=api_headers, json=json_data)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '0' and response_json['success']:
|
||||
daily_tasks = [item for item in response_json['data'] if item["taskType"] == "每日任务"]
|
||||
task_list = daily_tasks[0]['taskList']
|
||||
all_tasks = []
|
||||
for task_item in task_list:
|
||||
task_id = task_item['taskNo']
|
||||
task_name = task_item['showTitle']
|
||||
all_tasks.append({
|
||||
'task_id': task_id,
|
||||
'task_name': task_name
|
||||
})
|
||||
print(f'[{user_mobile}] 查询任务成功: 已获取到 {len(task_list)} 个任务')
|
||||
return all_tasks
|
||||
else:
|
||||
print(f'查询任务失败:{response_json["message"]}')
|
||||
return None
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'查询任务发生网络错误: {str(e)}')
|
||||
except (ValueError, KeyError, TypeError) as e:
|
||||
print(f'查询任务发生解析错误: {str(e)}')
|
||||
except Exception as e:
|
||||
print(f'查询任务发生未知错误: {str(e)}')
|
||||
|
||||
def do_task(token,user_id,task_id,task_name,user_mobile):
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
nonce = generate_nonce()
|
||||
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&osType=IOS&platformType=APP&receiveTag=false&reqSource=APP_JTC&signType=MD5&taskNo={task_id}×tamp={timestamp}&token={token}&userId={user_id}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
|
||||
json_data = {
|
||||
'nonce': nonce,
|
||||
'taskNo': task_id,
|
||||
'reqSource': 'APP_JTC',
|
||||
'receiveTag': 'false',
|
||||
'applictionVersion': '60406',
|
||||
'timestamp': timestamp,
|
||||
'osType': 'IOS',
|
||||
'userId': user_id,
|
||||
'applictionType': 'APP',
|
||||
'token': token,
|
||||
'platformType': 'APP',
|
||||
'signType': 'MD5',
|
||||
'sign': sign,
|
||||
}
|
||||
try:
|
||||
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/integral/v2/task/complete',headers=api_headers, json=json_data)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '0' and response_json['success']:
|
||||
print(f'[{user_mobile}]【{task_name}】 任务成功,获得 {response_json["data"]["integralValue"]} 停车币')
|
||||
elif response_json['code'] == '1' or response_json['code'] == 'INTER006':
|
||||
print(f'[{user_mobile}]【{task_name}】 任务失败: {response_json["message"]}')
|
||||
else:
|
||||
print(f'[{user_mobile}]【{task_name}】 任务未知错误')
|
||||
print(response_json)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'完成任务发生网络错误: {str(e)}')
|
||||
except (ValueError, KeyError, TypeError) as e:
|
||||
print(f'完成任务发生解析错误: {str(e)}')
|
||||
except Exception as e:
|
||||
print(f'完成任务发生未知错误: {str(e)}')
|
||||
|
||||
|
||||
def task_report(deviceId,user_id,token,user_mobile):
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
event = '{"referrer":"PersonalCenterPage","pageEventName":"PointsTaskPage"}'
|
||||
nonce = generate_nonce()
|
||||
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&dataSourceType=原生&deviceId={deviceId}&eventName=MoreTaskClick&eventProperty={event}&eventType=activity&latitude={latitude}&longitude={longitude}&netType=NET_WIFI&nonce={nonce}&opSystem=iOS&opSystemVersion=14.6&phoneModel=iPhone10,3&productName=捷停车APP&productVersion=6.4.6&screenResolution=375*812&serviceProviders=未知&signType=MD5×tamp={timestamp}&token={token}&userId={user_id}&GaT92Kf6cbDc1Pea9S720GJnL56A14x3R')
|
||||
json_data = {
|
||||
'dataSourceType': '原生',
|
||||
'eventType': 'activity',
|
||||
'opSystem': 'iOS',
|
||||
'deviceId': deviceId,
|
||||
'opSystemVersion': '14.6',
|
||||
'phoneModel': 'iPhone10,3',
|
||||
'latitude': latitude,
|
||||
'eventName': 'MoreTaskClick',
|
||||
'netType': 'NET_WIFI',
|
||||
'signType': 'MD5',
|
||||
'nonce': nonce,
|
||||
'sign': sign,
|
||||
'token': token,
|
||||
'timestamp': timestamp,
|
||||
'eventProperty': {
|
||||
'referrer': 'PersonalCenterPage',
|
||||
'pageEventName': 'PointsTaskPage',
|
||||
},
|
||||
'longitude': longitude,
|
||||
'serviceProviders': '未知',
|
||||
'applictionVersion': '60406',
|
||||
'screenResolution': '375*812',
|
||||
'productName': '捷停车APP',
|
||||
'applictionType': 'APP',
|
||||
'productVersion': '6.4.6',
|
||||
'userId': user_id,
|
||||
}
|
||||
|
||||
response = requests.post('https://sytgate.jslife.com.cn/data-report-gateway/syt-data-report/receive',headers=api_headers,json=json_data)
|
||||
if response.json()['resultCode'] == '0' and response.json()['success'] :
|
||||
print(f'[{user_mobile}] 任务数据上报成功')
|
||||
else:
|
||||
print(f'[{user_mobile}] 任务数据上报失败')
|
||||
|
||||
def task_report2(deviceId,user_id,user_token,task_name,user_mobile):
|
||||
nonce = generate_nonce()
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
event = json.dumps({"referrer":"PersonalCenterPage","pageEventName":"PointsTaskPage","TaskName":task_name}, separators=(',', ':'))
|
||||
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&dataSourceType=原生&deviceId={deviceId}&eventName=ShowGoToFinish&eventProperty={event}&eventType=activity&latitude={latitude}&longitude={longitude}&netType=NET_WIFI&nonce={nonce}&opSystem=iOS&opSystemVersion=14.6&phoneModel=iPhone10,3&productName=捷停车APP&productVersion=6.4.6&screenResolution=375*812&serviceProviders=未知&signType=MD5×tamp={timestamp}&token={user_token}&userId={user_id}&GaT92Kf6cbDc1Pea9S720GJnL56A14x3R')
|
||||
|
||||
json_data = {
|
||||
'dataSourceType': '原生',
|
||||
'eventType': 'activity',
|
||||
'opSystem': 'iOS',
|
||||
'deviceId': deviceId,
|
||||
'opSystemVersion': '14.6',
|
||||
'phoneModel': 'iPhone10,3',
|
||||
'latitude': latitude,
|
||||
'eventName': 'ShowGoToFinish',
|
||||
'netType': 'NET_WIFI',
|
||||
'signType': 'MD5',
|
||||
'nonce': nonce,
|
||||
'sign': sign,
|
||||
'token': user_token,
|
||||
'timestamp': timestamp,
|
||||
'eventProperty': {
|
||||
'referrer': 'PointsDetailPage',
|
||||
'pageEventName': 'PointsTaskPage',
|
||||
'TaskName': task_name,
|
||||
},
|
||||
'longitude': longitude,
|
||||
'serviceProviders': '未知',
|
||||
'applictionVersion': '60408',
|
||||
'screenResolution': '375*812',
|
||||
'productName': '捷停车APP',
|
||||
'applictionType': 'APP',
|
||||
'productVersion': '6.4.8',
|
||||
'userId': user_id,
|
||||
}
|
||||
response = requests.post('https://sytgate.jslife.com.cn/data-report-gateway/syt-data-report/receive',headers=api_headers,json=json_data)
|
||||
if response.json()['resultCode'] == '0' and response.json()['success'] :
|
||||
print(f'[{user_mobile}] 数据上报成功')
|
||||
else:
|
||||
print(f'[{user_mobile}] 数据上报失败')
|
||||
|
||||
|
||||
def find_report(deviceId,user_id,token,user_mobile):
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
nonce = generate_nonce()
|
||||
event = json.dumps({"referrer":"PointsTaskPage","pageEventName":"FindPreferentialPage"}, separators=(',', ':'))
|
||||
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&dataSourceType=原生&deviceId={deviceId}&eventName=ShowGoToClaim&eventProperty={event}&eventType=activity&latitude={latitude}&longitude={longitude}&netType=NET_WIFI&nonce={nonce}&opSystem=iOS&opSystemVersion=14.6&phoneModel=iPhone10,3&productName=捷停车APP&productVersion=6.4.6&screenResolution=375*812&serviceProviders=未知&signType=MD5×tamp={timestamp}&token={token}&userId={user_id}&GaT92Kf6cbDc1Pea9S720GJnL56A14x3R')
|
||||
json_data = {
|
||||
'dataSourceType': '原生',
|
||||
'eventType': 'activity',
|
||||
'opSystem': 'iOS',
|
||||
'deviceId': deviceId,
|
||||
'opSystemVersion': '14.6',
|
||||
'phoneModel': 'iPhone10,3',
|
||||
'latitude': latitude,
|
||||
'eventName': 'ShowGoToClaim',
|
||||
'netType': 'NET_WIFI',
|
||||
'signType': 'MD5',
|
||||
'nonce': nonce,
|
||||
'sign': sign,
|
||||
'token': token,
|
||||
'timestamp': timestamp,
|
||||
'eventProperty': {
|
||||
'referrer': 'PointsTaskPage',
|
||||
'pageEventName': 'FindPreferentialPage',
|
||||
},
|
||||
'longitude': longitude,
|
||||
'serviceProviders': '未知',
|
||||
'applictionVersion': '60406',
|
||||
'screenResolution': '375*812',
|
||||
'productName': '捷停车APP',
|
||||
'applictionType': 'APP',
|
||||
'productVersion': '6.4.6',
|
||||
'userId': user_id,
|
||||
}
|
||||
try:
|
||||
response = requests.post('https://sytgate.jslife.com.cn/data-report-gateway/syt-data-report/receive',headers=api_headers,json=json_data)
|
||||
if response.json()['resultCode'] == '0' and response.json()['success'] :
|
||||
print(f'[{user_mobile}]【去找优惠】任务数据上报成功')
|
||||
else:
|
||||
print(f'{[user_mobile]}【去找优惠】任务数据上报失败')
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'【去找优惠】任务数据上报发生网络错误: {str(e)}')
|
||||
except (ValueError, KeyError, TypeError) as e:
|
||||
print(f'【去找优惠】任务数据上报发生解析错误: {str(e)}')
|
||||
except Exception as e:
|
||||
print(f'【去找优惠】任务数据上报发生未知错误: {str(e)}')
|
||||
|
||||
|
||||
|
||||
def query_day_sign(token, userid,user_mobile):
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
nonce = generate_nonce()
|
||||
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&signType=MD5×tamp={timestamp}&token={token}&userId={userid}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
|
||||
json_data = {
|
||||
'userId': userid,
|
||||
'signType': 'MD5',
|
||||
'applictionType': 'APP',
|
||||
'applictionVersion': '60406',
|
||||
'token': token,
|
||||
'timestamp': timestamp,
|
||||
'sign': sign,
|
||||
'nonce': nonce,
|
||||
}
|
||||
try:
|
||||
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/integral/v2/sign-in-task/query', headers=api_headers,json=json_data)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '0' and response_json['success']:
|
||||
# print(f'[{user_mobile}] 每日签到查询成功')
|
||||
if not response_json['data']['todaySingInTag']:
|
||||
print(f'[{user_mobile}] 每日签到未完成')
|
||||
task_receive(token,userid,response_json['data']['taskNo'],'每日签到',user_mobile)
|
||||
else:
|
||||
print(f'[{user_mobile}] 每日签到已完成')
|
||||
Log(f'[{user_mobile}] 每日签到已完成')
|
||||
else:
|
||||
print(f'[{user_mobile}] 每日签到查询失败:{response_json["message"]}')
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'查询每日签到发生网络错误: {str(e)}')
|
||||
except (ValueError, KeyError, TypeError) as e:
|
||||
print(f'查询每日签到发生解析错误: {str(e)}')
|
||||
except Exception as e:
|
||||
print(f'查询每日签到发生未知错误: {str(e)}')
|
||||
|
||||
def task_receive(token,userid,task_id,task_name,user_mobile):
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
nonce = generate_nonce()
|
||||
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&osType=IOS&platformType=APP&reqSource=APP_JTC&signType=MD5&taskNo={task_id}×tamp={timestamp}&token={token}&userId={userid}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
|
||||
json_data = {
|
||||
'nonce': nonce,
|
||||
'taskNo': task_id,
|
||||
'reqSource': 'APP_JTC',
|
||||
'applictionVersion': '60406',
|
||||
'timestamp': timestamp,
|
||||
'osType': 'IOS',
|
||||
'userId': userid,
|
||||
'applictionType': 'APP',
|
||||
'token': token,
|
||||
'platformType': 'APP',
|
||||
'signType': 'MD5',
|
||||
'sign': sign,
|
||||
}
|
||||
try:
|
||||
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/integral/v2/task/receive', headers=api_headers, json=json_data)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '0' and response_json['success']:
|
||||
print(f'[{user_mobile}]【{task_name}】 获得 {response_json["data"]} 停车币')
|
||||
Log(f'[{user_mobile}]【{task_name}】 获得 {response_json["data"]} 停车币')
|
||||
else:
|
||||
print(f'[{user_mobile}]【{task_name}】 领取任务奖励失败:{response_json["message"]}')
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'领取任务奖励发生网络错误: {str(e)}')
|
||||
except (ValueError, KeyError, TypeError) as e:
|
||||
print(f'领取任务奖励发生解析错误: {str(e)}')
|
||||
except Exception as e:
|
||||
print(f'领取任务奖励发生未知错误: {str(e)}')
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
if jtc_token:
|
||||
z = 1
|
||||
for item in jtc_token:
|
||||
print('-' * 50)
|
||||
print(f'登录第{z}个账号>>>>>>')
|
||||
phone = item.split('#')[0]
|
||||
device_id = item.split('#')[1]
|
||||
token = item.split('#')[2]
|
||||
user_data = refresh_token(phone, device_id, token)
|
||||
if user_data:
|
||||
new_userid = user_data['new_user_id']
|
||||
new_token = user_data['new_token']
|
||||
query_day_sign(new_token, new_userid, phone)
|
||||
print('-' * 50)
|
||||
task_report(device_id, new_userid, new_token, phone)
|
||||
tasks = query_task(new_token, new_userid, phone)
|
||||
if tasks:
|
||||
for task in tasks:
|
||||
task_report2(device_id, new_userid, new_token, task['task_name'], phone)
|
||||
if task['task_name'] == '看视频':
|
||||
print(f'[{phone}]【看视频】跳过任务')
|
||||
# 破解不了直接跳过
|
||||
continue
|
||||
if task['task_name'] == '去找优惠':
|
||||
find_report(device_id, new_userid, new_token, phone)
|
||||
time.sleep(5)
|
||||
do_task(new_token, new_userid, task['task_id'], task['task_name'], phone)
|
||||
time.sleep(3)
|
||||
task_receive(new_token, new_userid, task['task_id'], task['task_name'], phone)
|
||||
time.sleep(2)
|
||||
# do_userinfo(userid, user_phone)
|
||||
print('-' * 50)
|
||||
get_coin(new_token, new_userid, phone)
|
||||
print('*' * 50)
|
||||
Log('\n')
|
||||
else:
|
||||
print(f'第{z}个账号用户信息获取失败')
|
||||
Log(f'第{z}个账号用户信息获取失败')
|
||||
z += 1
|
||||
else:
|
||||
print('请先填入jtc_token变量')
|
||||
Log('请先填入jtc_token变量')
|
||||
except Exception as e:
|
||||
print(f'发生错误: {str(e)}')
|
||||
try:
|
||||
send_notification_message(title='捷停车') # 发送通知
|
||||
except Exception as e:
|
||||
print('推送失败:' + str(e))
|
||||
540
脚本库/微信小程序/抓包版/jtc/2025-10-26_jtc_d7fa5acd_2.py
Normal file
540
脚本库/微信小程序/抓包版/jtc/2025-10-26_jtc_d7fa5acd_2.py
Normal file
@@ -0,0 +1,540 @@
|
||||
# Source: https://github.com/lksky8/sign-ql/blob/main/jtc.py
|
||||
# Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/jtc.py
|
||||
# Repo: lksky8/sign-ql
|
||||
# Path: jtc.py
|
||||
# UploadedAt: 2025-10-26T12:24:47Z
|
||||
# SHA256: d7fa5acdc107ddb45fd772c4bb0c9491fd48e8e3d7d18ae5a4286579151676ef
|
||||
# Category: 微信小程序/抓包版
|
||||
# Evidence: appid/openid/session_key/encryptedData等小程序字段
|
||||
|
||||
"""
|
||||
捷停车签到
|
||||
|
||||
作者:https://github.com/lksky8/sign-ql
|
||||
最后更新日期:2025-10-26
|
||||
食用方法:打开捷停车app抓请求url=https://sytgate.jslife.com.cn/core-gateway/user/login/verify/token里面的deviceId和token(一般在请求参数里面)在环境变量输入export jtc_token=账号1#deviceId#token1&账号2#deviceId#token2
|
||||
支持多用户运行
|
||||
多用户用&或者@隔开
|
||||
例如账号1:账号1#C5A59624-6666-4682-9876-F8184F3D2CF0#eyJhbGciOiJIUzI1NiJ9.... 账号2#C5A59624-5555-1234-9E41-F8184F3D2CF0#eyJhbGciOiJIUzI1NiJ9....
|
||||
则变量为
|
||||
export jtc_token="账号1#C5A59624-6666-4682-9876-F8184F3D2CF0#eyJhbGciOiJIUzI1NiJ9....&账号2#C5A59624-5555-1234-9E41-F8184F3D2CF0#eyJhbGciOiJIUzI1NiJ9...."
|
||||
|
||||
cron: 12 2 * * *
|
||||
"""
|
||||
import requests
|
||||
import time
|
||||
import hashlib
|
||||
import os
|
||||
import re
|
||||
import uuid
|
||||
import json
|
||||
import random
|
||||
|
||||
|
||||
def generate_nonce():
|
||||
"""生成符合要求的UUID格式字符串"""
|
||||
return str(uuid.uuid4()).upper()
|
||||
|
||||
|
||||
if 'jtc_token' in os.environ:
|
||||
jtc_token = re.split("@|&",os.environ.get("jtc_token"))
|
||||
print(f'查找到{len(jtc_token)}个账号\n')
|
||||
else:
|
||||
jtc_token = []
|
||||
print('无jtc_token变量\n')
|
||||
|
||||
|
||||
send_msg = ''
|
||||
one_msg = ''
|
||||
|
||||
def Log(cont=''):
|
||||
global send_msg, one_msg
|
||||
if cont:
|
||||
one_msg += f'\n{cont}'
|
||||
send_msg += f'\n{cont}'
|
||||
|
||||
|
||||
|
||||
def send_notification_message(title):
|
||||
try:
|
||||
from notify import send
|
||||
print("加载通知服务成功!")
|
||||
send(title, send_msg)
|
||||
except Exception as e:
|
||||
if e:
|
||||
print('发送通知消息失败!')
|
||||
|
||||
api_headers = {
|
||||
'Host': 'sytgate.jslife.com.cn',
|
||||
'Content-Type': 'application/json;charset=utf-8',
|
||||
'applicationVersion': '60406',
|
||||
'Accept': '*/*',
|
||||
'User-Agent': 'JTC/6.4.6 (iPhone; iOS 15.8.3; Scale/3.00)',
|
||||
'Accept-Language': 'zh-Hans-CN;q=1',
|
||||
}
|
||||
|
||||
longitude = f'113.07{random.randint(100, 999)}'
|
||||
latitude = f'22.888624{random.randint(100, 999)}'
|
||||
|
||||
def md5_encrypt(text):
|
||||
return hashlib.md5(text.encode('utf-8')).hexdigest().upper()
|
||||
|
||||
|
||||
def refresh_token(user_phone,user_deviceid,user_token):
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
nonce = generate_nonce() # 生成nonce
|
||||
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&deviceId={user_deviceid}&nonce={nonce}&osType=iOS&signType=MD5×tamp={timestamp}&token={user_token}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
|
||||
json_data = {
|
||||
'deviceId': user_deviceid,
|
||||
'osType': 'iOS',
|
||||
'signType': 'MD5',
|
||||
'applictionType': 'APP',
|
||||
'applictionVersion': '60406',
|
||||
'token': user_token,
|
||||
'timestamp': timestamp,
|
||||
'sign': sign,
|
||||
'nonce': nonce
|
||||
}
|
||||
try:
|
||||
response = requests.post('https://sytgate.jslife.com.cn/core-gateway/user/login/verify/token',headers=api_headers,json=json_data)
|
||||
response_json = response.json()
|
||||
if response_json['resultCode'] == '0' and response_json['message'] == '成功':
|
||||
print(f'[{user_phone}] 刷新token成功')
|
||||
return {'new_token': response_json['obj']['token'], 'new_user_id': response_json['obj']['userId']}
|
||||
elif response_json['resultCode'] == '10011' and response_json['message'] == '用户已在其他平台登录':
|
||||
print(f'[{user_phone}] 刷新token失败:请重新获取token')
|
||||
elif response_json['resultCode'] == '3126' and response_json['message'] == 'token已过期':
|
||||
print(f'[{user_phone}] 刷新token失败:token已过期,请重新获取')
|
||||
return None
|
||||
else:
|
||||
print(f'[{user_phone}] 刷新token失败:{response_json}')
|
||||
return None
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'刷新token发生网络错误: {str(e)}')
|
||||
except (ValueError, KeyError, TypeError) as e:
|
||||
print(f'刷新token发生解析错误: {str(e)}')
|
||||
except Exception as e:
|
||||
print(f'刷新token发生未知错误: {str(e)}')
|
||||
|
||||
def get_coin(token,user_id,user_mobile):
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
nonce = generate_nonce() # 生成nonce
|
||||
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&reqSource=APP_JTC&signType=MD5×tamp={timestamp}&token={token}&userId={user_id}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
|
||||
json_data = {
|
||||
'userId': user_id,
|
||||
'signType': 'MD5',
|
||||
'reqSource': 'APP_JTC',
|
||||
'applictionType': 'APP',
|
||||
'applictionVersion': '60406',
|
||||
'token': token,
|
||||
'timestamp': timestamp,
|
||||
'sign': sign,
|
||||
'nonce': nonce,
|
||||
}
|
||||
try:
|
||||
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/integral/v2/balance/query', headers=api_headers, json=json_data)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '0' and response_json['success']:
|
||||
print(f'[{user_mobile}] 积分:{response_json["data"]["accountAmt"]},可抵扣:{response_json["data"]["deductAmount"]}元')
|
||||
Log(f'[{user_mobile}] 积分:{response_json["data"]["accountAmt"]},可抵扣:{response_json["data"]["deductAmount"]}元')
|
||||
else:
|
||||
print(f'[{user_mobile}] 查询积分失败:{response_json["message"]}')
|
||||
Log(f'[{user_mobile}] 查询积分失败:{response_json["message"]}')
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'查询用户积分发生网络错误: {str(e)}')
|
||||
except (ValueError, KeyError, TypeError) as e:
|
||||
print(f'查询用户积分发生解析错误: {str(e)}')
|
||||
except Exception as e:
|
||||
print(f'查询用户积分发生未知错误: {str(e)}')
|
||||
|
||||
def get_userinfo(token,user_id):
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
nonce = generate_nonce() # 生成nonce
|
||||
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&reqSource=APP_JTC&signType=MD5×tamp={timestamp}&token={token}&userId={user_id}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
|
||||
json_data = {
|
||||
'userId': user_id,
|
||||
'signType': 'MD5',
|
||||
'sign': sign,
|
||||
'charset': 'UTF-8',
|
||||
'reqSource': 'APP_JTC',
|
||||
'applictionType': 'APP',
|
||||
'version': 'V1.0',
|
||||
'token': token,
|
||||
'timestamp': timestamp,
|
||||
'applictionVersion': '60406',
|
||||
'nonce': nonce,
|
||||
}
|
||||
try:
|
||||
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/member/queryUserBenefitInfo',headers=api_headers, json=json_data)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '0' and response_json['success']:
|
||||
if response_json['data']['mobile'] is None:
|
||||
return None
|
||||
else:
|
||||
return response_json['data']['mobile']
|
||||
else:
|
||||
print(f'查询用户信息失败:{response_json["message"]}')
|
||||
return None
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'查询用户信息发生网络错误: {str(e)}')
|
||||
except (ValueError, KeyError, TypeError) as e:
|
||||
print(f'查询用户信息发生解析错误: {str(e)}')
|
||||
except Exception as e:
|
||||
print(f'查询用户信息发生未知错误: {str(e)}')
|
||||
|
||||
|
||||
def do_userinfo(user_id,user_mobile):
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
json_data = {
|
||||
'userId': user_id,
|
||||
'openId': '',
|
||||
'gender': 'MALE',
|
||||
'birthday': '2000-01-01',
|
||||
'province': '广东省',
|
||||
'city': '广州市',
|
||||
'platformType': 'APP_JTC',
|
||||
}
|
||||
try:
|
||||
response = requests.post(f'https://sytgate.jslife.com.cn/core-gateway/user/update/extend-info?t={timestamp}',headers=api_headers, json=json_data)
|
||||
response_json = response.json()
|
||||
if response_json['resultCode'] == '0':
|
||||
print(f'[{user_mobile}] 更新用户信息成功:{user_id}')
|
||||
if response_json['obj']:
|
||||
print(f'[{user_mobile}] 个人信息已完善并获得30停车币')
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'更新用户信息发生网络错误: {str(e)}')
|
||||
except (ValueError, KeyError, TypeError) as e:
|
||||
print(f'更新用户信息发生解析错误: {str(e)}')
|
||||
except Exception as e:
|
||||
print(f'更新用户信息发生未知错误: {str(e)}')
|
||||
|
||||
def query_task(user_token, user_id, user_mobile):
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
nonce = generate_nonce()
|
||||
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&reqSource=APP_JTC&signType=MD5×tamp={timestamp}&token={user_token}&userId={user_id}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
|
||||
json_data = {
|
||||
'osType': 'IOS',
|
||||
'signType': 'MD5',
|
||||
'userId': user_id,
|
||||
'nonce': nonce,
|
||||
'applictionType': 'APP',
|
||||
'reqVersion': 'V2.0',
|
||||
'applictionVersion': '60406',
|
||||
'token': user_token,
|
||||
'timestamp': timestamp,
|
||||
'sign': sign,
|
||||
'platformType': 'APP',
|
||||
}
|
||||
try:
|
||||
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/integral/v2/task/query',headers=api_headers, json=json_data)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '0' and response_json['success']:
|
||||
daily_tasks = [item for item in response_json['data'] if item["taskType"] == "每日任务"]
|
||||
task_list = daily_tasks[0]['taskList']
|
||||
all_tasks = []
|
||||
for task_item in task_list:
|
||||
task_id = task_item['taskNo']
|
||||
task_name = task_item['showTitle']
|
||||
all_tasks.append({
|
||||
'task_id': task_id,
|
||||
'task_name': task_name
|
||||
})
|
||||
print(f'[{user_mobile}] 查询任务成功: 已获取到 {len(task_list)} 个任务')
|
||||
return all_tasks
|
||||
else:
|
||||
print(f'查询任务失败:{response_json["message"]}')
|
||||
return None
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'查询任务发生网络错误: {str(e)}')
|
||||
except (ValueError, KeyError, TypeError) as e:
|
||||
print(f'查询任务发生解析错误: {str(e)}')
|
||||
except Exception as e:
|
||||
print(f'查询任务发生未知错误: {str(e)}')
|
||||
|
||||
def do_task(token,user_id,task_id,task_name,user_mobile):
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
nonce = generate_nonce()
|
||||
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&osType=IOS&platformType=APP&receiveTag=false&reqSource=APP_JTC&signType=MD5&taskNo={task_id}×tamp={timestamp}&token={token}&userId={user_id}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
|
||||
json_data = {
|
||||
'nonce': nonce,
|
||||
'taskNo': task_id,
|
||||
'reqSource': 'APP_JTC',
|
||||
'receiveTag': 'false',
|
||||
'applictionVersion': '60406',
|
||||
'timestamp': timestamp,
|
||||
'osType': 'IOS',
|
||||
'userId': user_id,
|
||||
'applictionType': 'APP',
|
||||
'token': token,
|
||||
'platformType': 'APP',
|
||||
'signType': 'MD5',
|
||||
'sign': sign,
|
||||
}
|
||||
try:
|
||||
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/integral/v2/task/complete',headers=api_headers, json=json_data)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '0' and response_json['success']:
|
||||
print(f'[{user_mobile}]【{task_name}】 任务成功,获得 {response_json["data"]["integralValue"]} 停车币')
|
||||
elif response_json['code'] == '1' or response_json['code'] == 'INTER006':
|
||||
print(f'[{user_mobile}]【{task_name}】 任务失败: {response_json["message"]}')
|
||||
else:
|
||||
print(f'[{user_mobile}]【{task_name}】 任务未知错误')
|
||||
print(response_json)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'完成任务发生网络错误: {str(e)}')
|
||||
except (ValueError, KeyError, TypeError) as e:
|
||||
print(f'完成任务发生解析错误: {str(e)}')
|
||||
except Exception as e:
|
||||
print(f'完成任务发生未知错误: {str(e)}')
|
||||
|
||||
|
||||
def task_report(deviceId,user_id,token,user_mobile):
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
event = '{"referrer":"PersonalCenterPage","pageEventName":"PointsTaskPage"}'
|
||||
nonce = generate_nonce()
|
||||
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&dataSourceType=原生&deviceId={deviceId}&eventName=MoreTaskClick&eventProperty={event}&eventType=activity&latitude={latitude}&longitude={longitude}&netType=NET_WIFI&nonce={nonce}&opSystem=iOS&opSystemVersion=14.6&phoneModel=iPhone10,3&productName=捷停车APP&productVersion=6.4.6&screenResolution=375*812&serviceProviders=未知&signType=MD5×tamp={timestamp}&token={token}&userId={user_id}&GaT92Kf6cbDc1Pea9S720GJnL56A14x3R')
|
||||
json_data = {
|
||||
'dataSourceType': '原生',
|
||||
'eventType': 'activity',
|
||||
'opSystem': 'iOS',
|
||||
'deviceId': deviceId,
|
||||
'opSystemVersion': '14.6',
|
||||
'phoneModel': 'iPhone10,3',
|
||||
'latitude': latitude,
|
||||
'eventName': 'MoreTaskClick',
|
||||
'netType': 'NET_WIFI',
|
||||
'signType': 'MD5',
|
||||
'nonce': nonce,
|
||||
'sign': sign,
|
||||
'token': token,
|
||||
'timestamp': timestamp,
|
||||
'eventProperty': {
|
||||
'referrer': 'PersonalCenterPage',
|
||||
'pageEventName': 'PointsTaskPage',
|
||||
},
|
||||
'longitude': longitude,
|
||||
'serviceProviders': '未知',
|
||||
'applictionVersion': '60406',
|
||||
'screenResolution': '375*812',
|
||||
'productName': '捷停车APP',
|
||||
'applictionType': 'APP',
|
||||
'productVersion': '6.4.6',
|
||||
'userId': user_id,
|
||||
}
|
||||
|
||||
response = requests.post('https://sytgate.jslife.com.cn/data-report-gateway/syt-data-report/receive',headers=api_headers,json=json_data)
|
||||
if response.json()['resultCode'] == '0' and response.json()['success'] :
|
||||
print(f'[{user_mobile}] 任务数据上报成功')
|
||||
else:
|
||||
print(f'[{user_mobile}] 任务数据上报失败')
|
||||
|
||||
def task_report2(deviceId,user_id,user_token,task_name,user_mobile):
|
||||
nonce = generate_nonce()
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
event = json.dumps({"referrer":"PersonalCenterPage","pageEventName":"PointsTaskPage","TaskName":task_name}, separators=(',', ':'))
|
||||
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&dataSourceType=原生&deviceId={deviceId}&eventName=ShowGoToFinish&eventProperty={event}&eventType=activity&latitude={latitude}&longitude={longitude}&netType=NET_WIFI&nonce={nonce}&opSystem=iOS&opSystemVersion=14.6&phoneModel=iPhone10,3&productName=捷停车APP&productVersion=6.4.6&screenResolution=375*812&serviceProviders=未知&signType=MD5×tamp={timestamp}&token={user_token}&userId={user_id}&GaT92Kf6cbDc1Pea9S720GJnL56A14x3R')
|
||||
|
||||
json_data = {
|
||||
'dataSourceType': '原生',
|
||||
'eventType': 'activity',
|
||||
'opSystem': 'iOS',
|
||||
'deviceId': deviceId,
|
||||
'opSystemVersion': '14.6',
|
||||
'phoneModel': 'iPhone10,3',
|
||||
'latitude': latitude,
|
||||
'eventName': 'ShowGoToFinish',
|
||||
'netType': 'NET_WIFI',
|
||||
'signType': 'MD5',
|
||||
'nonce': nonce,
|
||||
'sign': sign,
|
||||
'token': user_token,
|
||||
'timestamp': timestamp,
|
||||
'eventProperty': {
|
||||
'referrer': 'PointsDetailPage',
|
||||
'pageEventName': 'PointsTaskPage',
|
||||
'TaskName': task_name,
|
||||
},
|
||||
'longitude': longitude,
|
||||
'serviceProviders': '未知',
|
||||
'applictionVersion': '60408',
|
||||
'screenResolution': '375*812',
|
||||
'productName': '捷停车APP',
|
||||
'applictionType': 'APP',
|
||||
'productVersion': '6.4.8',
|
||||
'userId': user_id,
|
||||
}
|
||||
response = requests.post('https://sytgate.jslife.com.cn/data-report-gateway/syt-data-report/receive',headers=api_headers,json=json_data)
|
||||
if response.json()['resultCode'] == '0' and response.json()['success'] :
|
||||
print(f'[{user_mobile}] 数据上报成功')
|
||||
else:
|
||||
print(f'[{user_mobile}] 数据上报失败')
|
||||
|
||||
|
||||
def find_report(deviceId,user_id,token,user_mobile):
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
nonce = generate_nonce()
|
||||
event = json.dumps({"referrer":"PointsTaskPage","pageEventName":"FindPreferentialPage"}, separators=(',', ':'))
|
||||
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&dataSourceType=原生&deviceId={deviceId}&eventName=ShowGoToClaim&eventProperty={event}&eventType=activity&latitude={latitude}&longitude={longitude}&netType=NET_WIFI&nonce={nonce}&opSystem=iOS&opSystemVersion=14.6&phoneModel=iPhone10,3&productName=捷停车APP&productVersion=6.4.6&screenResolution=375*812&serviceProviders=未知&signType=MD5×tamp={timestamp}&token={token}&userId={user_id}&GaT92Kf6cbDc1Pea9S720GJnL56A14x3R')
|
||||
json_data = {
|
||||
'dataSourceType': '原生',
|
||||
'eventType': 'activity',
|
||||
'opSystem': 'iOS',
|
||||
'deviceId': deviceId,
|
||||
'opSystemVersion': '14.6',
|
||||
'phoneModel': 'iPhone10,3',
|
||||
'latitude': latitude,
|
||||
'eventName': 'ShowGoToClaim',
|
||||
'netType': 'NET_WIFI',
|
||||
'signType': 'MD5',
|
||||
'nonce': nonce,
|
||||
'sign': sign,
|
||||
'token': token,
|
||||
'timestamp': timestamp,
|
||||
'eventProperty': {
|
||||
'referrer': 'PointsTaskPage',
|
||||
'pageEventName': 'FindPreferentialPage',
|
||||
},
|
||||
'longitude': longitude,
|
||||
'serviceProviders': '未知',
|
||||
'applictionVersion': '60406',
|
||||
'screenResolution': '375*812',
|
||||
'productName': '捷停车APP',
|
||||
'applictionType': 'APP',
|
||||
'productVersion': '6.4.6',
|
||||
'userId': user_id,
|
||||
}
|
||||
try:
|
||||
response = requests.post('https://sytgate.jslife.com.cn/data-report-gateway/syt-data-report/receive',headers=api_headers,json=json_data)
|
||||
if response.json()['resultCode'] == '0' and response.json()['success'] :
|
||||
print(f'[{user_mobile}]【去找优惠】任务数据上报成功')
|
||||
else:
|
||||
print(f'{[user_mobile]}【去找优惠】任务数据上报失败')
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'【去找优惠】任务数据上报发生网络错误: {str(e)}')
|
||||
except (ValueError, KeyError, TypeError) as e:
|
||||
print(f'【去找优惠】任务数据上报发生解析错误: {str(e)}')
|
||||
except Exception as e:
|
||||
print(f'【去找优惠】任务数据上报发生未知错误: {str(e)}')
|
||||
|
||||
|
||||
|
||||
def query_day_sign(token, userid,user_mobile):
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
nonce = generate_nonce()
|
||||
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&signType=MD5×tamp={timestamp}&token={token}&userId={userid}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
|
||||
json_data = {
|
||||
'userId': userid,
|
||||
'signType': 'MD5',
|
||||
'applictionType': 'APP',
|
||||
'applictionVersion': '60406',
|
||||
'token': token,
|
||||
'timestamp': timestamp,
|
||||
'sign': sign,
|
||||
'nonce': nonce,
|
||||
}
|
||||
try:
|
||||
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/integral/v2/sign-in-task/query', headers=api_headers,json=json_data)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '0' and response_json['success']:
|
||||
# print(f'[{user_mobile}] 每日签到查询成功')
|
||||
if not response_json['data']['todaySingInTag']:
|
||||
print(f'[{user_mobile}] 每日签到未完成')
|
||||
task_receive(token,userid,response_json['data']['taskNo'],'每日签到',user_mobile)
|
||||
else:
|
||||
print(f'[{user_mobile}] 每日签到已完成')
|
||||
Log(f'[{user_mobile}] 每日签到已完成')
|
||||
else:
|
||||
print(f'[{user_mobile}] 每日签到查询失败:{response_json["message"]}')
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'查询每日签到发生网络错误: {str(e)}')
|
||||
except (ValueError, KeyError, TypeError) as e:
|
||||
print(f'查询每日签到发生解析错误: {str(e)}')
|
||||
except Exception as e:
|
||||
print(f'查询每日签到发生未知错误: {str(e)}')
|
||||
|
||||
def task_receive(token,userid,task_id,task_name,user_mobile):
|
||||
timestamp = str(int(time.time() * 1000))
|
||||
nonce = generate_nonce()
|
||||
sign = md5_encrypt(f'applictionType=APP&applictionVersion=60406&nonce={nonce}&osType=IOS&platformType=APP&reqSource=APP_JTC&signType=MD5&taskNo={task_id}×tamp={timestamp}&token={token}&userId={userid}&Uvn76f3KgH9jlO9pCxZA12Swr5TeYQ8d')
|
||||
json_data = {
|
||||
'nonce': nonce,
|
||||
'taskNo': task_id,
|
||||
'reqSource': 'APP_JTC',
|
||||
'applictionVersion': '60406',
|
||||
'timestamp': timestamp,
|
||||
'osType': 'IOS',
|
||||
'userId': userid,
|
||||
'applictionType': 'APP',
|
||||
'token': token,
|
||||
'platformType': 'APP',
|
||||
'signType': 'MD5',
|
||||
'sign': sign,
|
||||
}
|
||||
try:
|
||||
response = requests.post('https://sytgate.jslife.com.cn/base-gateway/integral/v2/task/receive', headers=api_headers, json=json_data)
|
||||
response_json = response.json()
|
||||
if response_json['code'] == '0' and response_json['success']:
|
||||
print(f'[{user_mobile}]【{task_name}】 获得 {response_json["data"]} 停车币')
|
||||
Log(f'[{user_mobile}]【{task_name}】 获得 {response_json["data"]} 停车币')
|
||||
else:
|
||||
print(f'[{user_mobile}]【{task_name}】 领取任务奖励失败:{response_json["message"]}')
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f'领取任务奖励发生网络错误: {str(e)}')
|
||||
except (ValueError, KeyError, TypeError) as e:
|
||||
print(f'领取任务奖励发生解析错误: {str(e)}')
|
||||
except Exception as e:
|
||||
print(f'领取任务奖励发生未知错误: {str(e)}')
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
if jtc_token:
|
||||
z = 1
|
||||
for item in jtc_token:
|
||||
print('-' * 50)
|
||||
print(f'登录第{z}个账号>>>>>>')
|
||||
phone = item.split('#')[0]
|
||||
device_id = item.split('#')[1]
|
||||
token = item.split('#')[2]
|
||||
user_data = refresh_token(phone, device_id, token)
|
||||
if user_data:
|
||||
new_userid = user_data['new_user_id']
|
||||
new_token = user_data['new_token']
|
||||
query_day_sign(new_token, new_userid, phone)
|
||||
print('-' * 50)
|
||||
task_report(device_id, new_userid, new_token, phone)
|
||||
tasks = query_task(new_token, new_userid, phone)
|
||||
if tasks:
|
||||
for task in tasks:
|
||||
task_report2(device_id, new_userid, new_token, task['task_name'], phone)
|
||||
if task['task_name'] == '看视频':
|
||||
print(f'[{phone}]【看视频】跳过任务')
|
||||
# 破解不了直接跳过
|
||||
continue
|
||||
if task['task_name'] == '去找优惠':
|
||||
find_report(device_id, new_userid, new_token, phone)
|
||||
time.sleep(5)
|
||||
do_task(new_token, new_userid, task['task_id'], task['task_name'], phone)
|
||||
time.sleep(3)
|
||||
task_receive(new_token, new_userid, task['task_id'], task['task_name'], phone)
|
||||
time.sleep(2)
|
||||
# do_userinfo(userid, user_phone)
|
||||
print('-' * 50)
|
||||
get_coin(new_token, new_userid, phone)
|
||||
print('*' * 50)
|
||||
Log('\n')
|
||||
else:
|
||||
print(f'第{z}个账号用户信息获取失败')
|
||||
Log(f'第{z}个账号用户信息获取失败')
|
||||
z += 1
|
||||
else:
|
||||
print('请先填入jtc_token变量')
|
||||
Log('请先填入jtc_token变量')
|
||||
except Exception as e:
|
||||
print(f'发生错误: {str(e)}')
|
||||
try:
|
||||
send_notification_message(title='捷停车') # 发送通知
|
||||
except Exception as e:
|
||||
print('推送失败:' + str(e))
|
||||
793
脚本库/微信小程序/抓包版/快手双端/2026-05-11_ks_dual_aa4fbaa7.js
Normal file
793
脚本库/微信小程序/抓包版/快手双端/2026-05-11_ks_dual_aa4fbaa7.js
Normal file
@@ -0,0 +1,793 @@
|
||||
// # Source: https://github.com/DearSong15/ql-scripts/blob/main/ks_dual.js
|
||||
// # Raw: https://raw.githubusercontent.com/DearSong15/ql-scripts/main/ks_dual.js
|
||||
// # Repo: DearSong15/ql-scripts
|
||||
// # Path: ks_dual.js
|
||||
// # UploadedAt: 2026-05-11T15:03:30Z
|
||||
// # SHA256: aa4fbaa74f4c00599fa2a8c1e358c99c6f393dc9b180b7c8260162ddd20b1e0f
|
||||
// # Category: 微信小程序/抓包版
|
||||
// # Evidence: appid/openid/session_key/encryptedData等小程序字段
|
||||
//
|
||||
|
||||
//new Env("快手双端")
|
||||
|
||||
const axios = require("axios");
|
||||
const querystring = require("querystring");
|
||||
const { SocksProxyAgent } = require("socks-proxy-agent");
|
||||
const dns = require("dns");
|
||||
dns.setDefaultResultOrder("ipv4first");
|
||||
dns.setServers(["8.8.8.8", "114.114.114.114", "223.5.5.5"]);
|
||||
|
||||
// ==============================================
|
||||
// 自定义签名接口:KUAISHOU=81端口 NEBULA=82端口
|
||||
// ==============================================
|
||||
const SIGN_API_KUAISHOU = "http://127.0.0.1:81"; // 普通版(kpn=KUAISHOU)
|
||||
const SIGN_API_NEBULA = "http://127.0.0.1:82"; // 极速版(kpn=NEBULA)
|
||||
console.log("💡 普通版签名API: " + SIGN_API_KUAISHOU);
|
||||
console.log("💡 极速版签名API: " + SIGN_API_NEBULA);
|
||||
|
||||
// 全局配置(原配置未改动)
|
||||
const CONFIG = {
|
||||
SEARCH_KEYWORDS: process.env.KS_SEARCH_KEYWORDS?.split(",") || ["短剧小说", "热门视频", "美食教程"],
|
||||
DEFAULT_TASKS: process.env.KS_DEFAULT_TASKS?.split(",") || ["box", "look", "food", "search"],
|
||||
CYCLE_ROUNDS: parseInt(process.env.KS_CYCLE_ROUNDS || 0),
|
||||
WATCH_MIN: parseInt(process.env.KS_WATCH_MIN || 30),
|
||||
WATCH_MAX: parseInt(process.env.KS_WATCH_MAX || 40),
|
||||
AD_FAIL_LIMIT: parseInt(process.env.KS_AD_FAIL_LIMIT || 10),
|
||||
CONTINUOUS_1COIN_LIMIT: parseInt(process.env.KS_CONTINUOUS_1COIN_LIMIT || 3),
|
||||
APPEND_REST_INTERVAL: parseInt(process.env.KS_APPEND_INTERVAL || 5),
|
||||
APPEND_REST_MIN: parseInt(process.env.KS_APPEND_MIN || 5000),
|
||||
APPEND_REST_MAX: parseInt(process.env.KS_APPEND_MAX || 10000),
|
||||
LOW_REWARD_THRESHOLD: parseInt(process.env.KS_LOW_REWARD_THRESHOLD || 10),
|
||||
LOW_REWARD_LIMIT: parseInt(process.env.KS_LOW_REWARD_LIMIT || 3),
|
||||
PLATFORM_CONFIG: {
|
||||
KUAISHOU: {
|
||||
name: "KS",
|
||||
accountInfoUrl: "https://encourage.kuaishou.com/rest/wd/encourage/account/basicInfo",
|
||||
host: "encourage.kuaishou.com",
|
||||
appId: "kuaishou",
|
||||
packageName: "com.smile.gifmaker",
|
||||
appName: "快手",
|
||||
displayName: "快手",
|
||||
kpn: "KUAISHOU",
|
||||
adClientKey: "3c2cd3f3",
|
||||
reportClientKey: "3c2cd3f3"
|
||||
},
|
||||
NEBULA: {
|
||||
name: "JSB",
|
||||
accountInfoUrl: "https://nebula.kuaishou.com/rest/n/nebula/activity/earn/overview/basicInfo",
|
||||
host: "nebula.kuaishou.com",
|
||||
appId: "kuaishou_nebula",
|
||||
packageName: "com.kuaishou.nebula",
|
||||
appName: "快手极速版",
|
||||
displayName: "快手极速版",
|
||||
kpn: "NEBULA",
|
||||
adClientKey: "2ac2a76d",
|
||||
reportClientKey: "2ac2a76d"
|
||||
}
|
||||
},
|
||||
TASK_CONFIGS: {
|
||||
KUAISHOU: {
|
||||
box: {
|
||||
name: "宝箱广告",
|
||||
businessId: 604, posId: 20345, subPageId: 100024063,
|
||||
requestSceneType: 1, taskType: 1, pageId: 100011251
|
||||
},
|
||||
look: {
|
||||
name: "看广告得金币",
|
||||
businessId: 671, posId: 24068, subPageId: 100026368,
|
||||
requestSceneType: 1, taskType: 1, pageId: 100011251
|
||||
},
|
||||
food: {
|
||||
name: "饭补广告",
|
||||
businessId: 921, posId: 29742, subPageId: 100029908,
|
||||
requestSceneType: 7, taskType: 2, pageId: 100011251
|
||||
},
|
||||
search: {
|
||||
name: "搜索广告",
|
||||
businessId: 7077, posId: 216267, subPageId: 100161535,
|
||||
pageId: 10014, requestSceneType: 1, taskType: 2,
|
||||
linkUrl: "eyJwYWdlSWQiOjEwMDE0LCJzdWJQYWdlSWQiOjEwMDE2MTUzNSwicG9zSWQiOjIxNjI2NywiYnVzaW5lc3NJZCI6NzA3NywiZXh0UGFyYW1zIjoiYzc4OWI1ZTAzMjMxOTUwZjcyM2ZjMWE1ZGJjYzgwNmYzMDE1OTcyZWE0Mzc2NmNlNDYwNTk2ZDgzMGVjNTE5MDM0OGEwNTlkOTA2NWYwZGY1ZjkwY2YwMjEwMGVhMmQzYzU0YjUyZDBlNGUxY2Q0NmMxN2ExZDU3YmRhY2EyMzVlM2U1NjYzN2JmZGQzMThiZWMzNTgzOWU1YzIxNWUyNzMzY2IyMzQ2ZGQ1NDYyODc1NDdlMjc4OWYxMjZjZWU5NWZhYzg4N2IxMzM2MzBlZTEzYTVmYTlhODYzNDYxODQ5MjM0NDk3ZGY3ZTRmOWYyYzk2ZjQ5YzViMGExNzQ2NGE2MGM0MDg1MzU2NTY2ZDc4NGIxYjY3NzY3MzYzYjg3IiwiY3VzdG9tRGF0YSI6eyJleGl0SW5mbyI6eyJ0b2FzdERlc2MiOm51bGwsInRvYXN0SW1nVXJsIjpudWxsfX0sInBlbmRhbnRUeXBlIjoxLCJkaXNwbGF5VHlwZSI6Miwic2luZ2xlUGFnZUlkIjowLCJzaW5nbGVTdWJQYWdlSWQiOjAsImNoYW5uZWwiOjAsImNvdW50ZG93blJlcG9ydCI6ZmFsc2UsInRoZW1lVHlwZSI6MCwibWl4ZWRBZCI6dHJ1ZSwiZnVsbE1peGVkIjp0cnVlLCJhdXRvUmVwb3J0Ijp0cnVlLCJmcm9tVGFza0NlbnRlciI6dHJ1ZSwic2VhcmNoSW5zcGlyZVNjaGVtZUluZm8iOm51bGwsImFtb3VudCI6MH0="
|
||||
}
|
||||
},
|
||||
NEBULA: {
|
||||
box: {
|
||||
name: "宝箱广告",
|
||||
pageId: 11101, subPageId: 100024064, businessId: 606, posId: 20346,
|
||||
requestSceneType: 1, taskType: 1
|
||||
},
|
||||
look: {
|
||||
name: "看广告得金币",
|
||||
pageId: 11101, subPageId: 100026367, businessId: 672, posId: 24067,
|
||||
requestSceneType: 1, taskType: 1
|
||||
},
|
||||
food: {
|
||||
name: "饭补广告",
|
||||
pageId: 11101, subPageId: 100026367, businessId: 9362, posId: 24067,
|
||||
requestSceneType: 7, taskType: 2
|
||||
},
|
||||
search: {
|
||||
name: "搜索广告",
|
||||
pageId: 11014, subPageId: 100161537, businessId: 7076, posId: 216268,
|
||||
requestSceneType: 1, taskType: 1,
|
||||
linkUrl: "eyJwYWdlSWQiOjExMDE0LCJzdWJQYWdlSWQiOjEwMDE2MTUzNywicG9zSWQiOjIxNjI2OCwiYnVzaW5lc3NJZCI6NzA3NiwiZXh0UGFyYW1zIjoiYjc4OWI1ZTAzMjMxOTUwZjcyM2ZjMWE1ZGJjYzgwNmYzMDE1OTcyZWE0Mzc2NmNlNDYwNTk2ZDgzMGVjNTE5MDM0OGEwNTlkOTA2NWYwZGY1ZjkwY2YwMjEwMGVhMmQzYzU0YjUyZDBlNGUxY2Q0NmMxN2ExZDU3YmRhY2EyMzVlM2U1NjYzN2JmZGQzMThiZWMzNTgzOWU1YzIxNWUyNzMzY2IyMzQ2ZGQ1NDYyODc1NDdlMjc4OWYxMjZjZWU5NWZhYzg4N2IxMzM2MzBlZTEzYTVmYTlhODYzNDYxODQ5MjM0NDk3ZGY3ZTRmOWYyYzk2ZjQ5YzViMGExNzQ2NGE2MGM0MDg1MzU2NTY2ZDc4NGIxYjY3NzY3MzYzYjg3IiwiY3VzdG9tRGF0YSI6eyJleGl0SW5mbyI6eyJ0b2FzdERlc2MiOm51bGwsInRvYXN0SW1nVXJsIjpudWxsfX0sInBlbmRhbnRUeXBlIjoxLCJkaXNwbGF5VHlwZSI6Miwic2luZ2xlUGFnZUlkIjowLCJzaW5nbGVTdWJQYWdlSWQiOjAsImNoYW5uZWwiOjAsImNvdW50ZG93blJlcG9ydCI6ZmFsc2UsInRoZW1lVHlwZSI6MCwibWl4ZWRBZCI6dHJ1ZSwiZnVsbE1peGVkIjp0cnVlLCJhdXRvUmVwb3J0Ijp0cnVlLCJmcm9tVGFza0NlbnRlciI6dHJ1ZSwic2VhcmNoSW5zcGlyZVNjaGVtZUluZm8iOm51bGwsImFtb3VudCI6MH0="
|
||||
},
|
||||
follow: {
|
||||
name: "关注广告",
|
||||
pageId: 11101, subPageId: 100026367, businessId: 672, posId: 24067,
|
||||
requestSceneType: 2, taskType: 1
|
||||
},
|
||||
content: {
|
||||
name: "内容广告",
|
||||
pageId: 11101, subPageId: 100141480, businessId: 7054, posId: 186550,
|
||||
requestSceneType: 1, taskType: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
let localPublicIP = null;
|
||||
|
||||
// ==============================================
|
||||
// 工具函数(原代码未改动)
|
||||
// ==============================================
|
||||
function getTime() {
|
||||
return new Date().toLocaleTimeString("zh-CN", {
|
||||
timeZone: "Asia/Shanghai", hour12: false,
|
||||
hour: "2-digit", minute: "2-digit", second: "2-digit"
|
||||
});
|
||||
}
|
||||
function getProxyTag(useProxy) { return useProxy ? "[代理]" : "[直连]"; }
|
||||
function maskProxyUrl(proxy) {
|
||||
if (!proxy) return null;
|
||||
try {
|
||||
const match = proxy.match(/^(socks5:\/\/)([^:@]+)(?::([^@]+))?@(.+)$/);
|
||||
if (match) {
|
||||
const [, protocol, user, , host] = match;
|
||||
return `${protocol}${user}:***@${host}`;
|
||||
}
|
||||
} catch (e) {}
|
||||
return proxy;
|
||||
}
|
||||
function log(useProxy, appName, msg) {
|
||||
const tag = getProxyTag(useProxy);
|
||||
const app = appName === "快手极速版" ? "快手极速版" : "快手";
|
||||
console.log(`${tag}<${app}>(${getTime()}): ${msg}`);
|
||||
}
|
||||
function print(msg) { console.log(msg); }
|
||||
|
||||
// ==============================================
|
||||
// 网络请求封装(原代码未改动)
|
||||
// ==============================================
|
||||
async function request(options, proxy = null, title = "请求") {
|
||||
try {
|
||||
const axiosOptions = {
|
||||
method: options.method || "GET",
|
||||
url: options.url,
|
||||
headers: options.headers || {},
|
||||
data: options.body || options.form,
|
||||
timeout: options.timeout || 12000,
|
||||
validateStatus: () => true
|
||||
};
|
||||
if (proxy) {
|
||||
const agent = new SocksProxyAgent(proxy, { timeout: 10000, keepAlive: false });
|
||||
axiosOptions.httpAgent = agent;
|
||||
axiosOptions.httpsAgent = agent;
|
||||
} else {
|
||||
axiosOptions.proxy = false;
|
||||
}
|
||||
if (options.form && options.method === "POST" && !axiosOptions.headers["Content-Type"]) {
|
||||
axiosOptions.headers["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8";
|
||||
axiosOptions.data = querystring.stringify(options.form);
|
||||
}
|
||||
const resp = await axios(axiosOptions);
|
||||
return { body: resp.data, status: resp.status };
|
||||
} catch (e) {
|
||||
console.log(`[请求失败] ${title}: ${e.message}`);
|
||||
return { body: null, status: 0 };
|
||||
}
|
||||
}
|
||||
async function checkLocalIP() {
|
||||
print("正在检测本地直连公网IP...");
|
||||
const urls = ["http://icanhazip.com", "http://ipinfo.io/ip", "http://httpbin.org/ip"];
|
||||
for (const url of urls) {
|
||||
try {
|
||||
const res = await axios.get(url, { timeout: 5000, responseType: "text", proxy: false });
|
||||
const ip = res.data.trim().match(/\d+\.\d+\.\d+\.\d+/)?.[0];
|
||||
if (ip) {
|
||||
localPublicIP = ip;
|
||||
print("本地直连公网IP: " + ip);
|
||||
return ip;
|
||||
}
|
||||
} catch (e) { continue; }
|
||||
}
|
||||
print("本地直连公网IP检测失败");
|
||||
process.exit(1);
|
||||
}
|
||||
async function checkProxyIP(proxy) {
|
||||
const urls = ["http://icanhazip.com", "http://ipinfo.io/ip", "http://httpbin.org/ip"];
|
||||
for (const url of urls) {
|
||||
try {
|
||||
const { body } = await request({ method: "GET", url, timeout: 8000 }, proxy, "代理IP检测");
|
||||
if (!body) continue;
|
||||
const ip = body.toString().trim().match(/\d+\.\d+\.\d+\.\d+/)?.[0];
|
||||
if (ip) return ip;
|
||||
} catch (e) { continue; }
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// ==============================================
|
||||
// 签名接口 - 核心修改:按kpn自动切换接口
|
||||
// ==============================================
|
||||
async function getEncSign(base64Data, proxy, appName, remark, kpnType) {
|
||||
// 按kpn选签名接口:KUAISHOU=81 NEBULA=82
|
||||
const SIGN_API_URL = kpnType === "KUAISHOU" ? SIGN_API_KUAISHOU : SIGN_API_NEBULA;
|
||||
try {
|
||||
const { body } = await request({
|
||||
method: "POST",
|
||||
url: SIGN_API_URL + "/encsign",
|
||||
headers: { "Content-Type": "application/json", "User-Agent": "Mozilla/5.0" },
|
||||
body: JSON.stringify({ data: base64Data }),
|
||||
timeout: 15000
|
||||
}, null, `获取加密签名`);
|
||||
if (body && body.status) return body.data;
|
||||
log(proxy, appName, `❌ ${remark} encsign 失败: ${body?.message || body?.error || "无响应"}`);
|
||||
return null;
|
||||
} catch (e) {
|
||||
log(proxy, appName, `❌ ${remark} encsign 异常: ${e.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
async function getNsSign(reqInfo, proxy, appName, remark, kpnType) {
|
||||
// 按kpn选签名接口:KUAISHOU=81 NEBULA=82
|
||||
const SIGN_API_URL = kpnType === "KUAISHOU" ? SIGN_API_KUAISHOU : SIGN_API_NEBULA;
|
||||
try {
|
||||
const payload = {
|
||||
path: reqInfo.urlpath,
|
||||
data: reqInfo.reqdata,
|
||||
salt: reqInfo.salt
|
||||
};
|
||||
const { body } = await request({
|
||||
method: "POST",
|
||||
url: SIGN_API_URL + "/nssig",
|
||||
headers: { "Content-Type": "application/json", "User-Agent": "Mozilla/5.0" },
|
||||
body: JSON.stringify(payload),
|
||||
timeout: 15000
|
||||
}, null, `获取nssig签名`);
|
||||
if (body && body.data) {
|
||||
return {
|
||||
sig: body.data.sig,
|
||||
__NStokensig: body.data.nstokensig,
|
||||
__NS_sig3: body.data.nssig3,
|
||||
__NS_xfalcon: body.data.nssig4 || body.data.xfalcon || ""
|
||||
};
|
||||
}
|
||||
log(proxy, appName, `❌ ${remark} nssig 失败: ${body?.error || body?.message || "无响应"}`);
|
||||
return null;
|
||||
} catch (e) {
|
||||
log(proxy, appName, `❌ ${remark} nssig 异常: ${e.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ==============================================
|
||||
// 账号信息获取(原代码未改动)
|
||||
// ==============================================
|
||||
async function getUserInfo(cookie, platform, proxy) {
|
||||
try {
|
||||
const { body } = await request({
|
||||
method: "GET",
|
||||
url: platform.accountInfoUrl,
|
||||
headers: {
|
||||
Host: platform.host,
|
||||
"User-Agent": "kwai-android aegon/3.56.0",
|
||||
Cookie: cookie,
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
},
|
||||
timeout: 12000
|
||||
}, proxy, "获取账号信息");
|
||||
if (body && body.result === 1 && body.data) {
|
||||
let coin = 0, cash = 0;
|
||||
if (platform.name === "KS") {
|
||||
coin = Number(body.data.coinAmount) || 0;
|
||||
cash = Number(body.data.cashAmountDisplay) || 0;
|
||||
} else {
|
||||
coin = Number(body.data.totalCoin) || 0;
|
||||
cash = Number(body.data.allCash) || 0;
|
||||
}
|
||||
return {
|
||||
nickname: body.data.userData?.nickname || null,
|
||||
totalCoin: coin, allCash: cash,
|
||||
success: true, ckExpired: false
|
||||
};
|
||||
}
|
||||
return { nickname: null, totalCoin: 0, allCash: 0, success: false, ckExpired: true };
|
||||
} catch (e) {
|
||||
return { nickname: null, totalCoin: 0, allCash: 0, success: false, ckExpired: true };
|
||||
}
|
||||
}
|
||||
|
||||
// ==============================================
|
||||
// 账号任务类 - 仅传kpnType到签名函数,其余未改
|
||||
// ==============================================
|
||||
class KuaishouAccount {
|
||||
constructor({ index = 1, salt, cookie, remark = "未命名", proxyUrl = null, tasksToExecute = CONFIG.DEFAULT_TASKS }) {
|
||||
this.index = index;
|
||||
this.salt = salt;
|
||||
this.cookie = cookie;
|
||||
this.remark = remark;
|
||||
this.proxyUrl = proxyUrl;
|
||||
this.platform = this.getPlatformByCookie(cookie);
|
||||
this.kpnType = this.platform.kpn; // 新增:获取kpn类型(KUAISHOU/NEBULA)
|
||||
this.tasksToRun = tasksToExecute.filter(Boolean);
|
||||
this.taskConfigs = CONFIG.TASK_CONFIGS[this.platform.kpn === "NEBULA" ? "NEBULA" : "KUAISHOU"];
|
||||
this.lowRewardCount = 0;
|
||||
this.lowRewardStreak = 0;
|
||||
this.adFailCount = 0;
|
||||
this.continuous1Coin = 0;
|
||||
this.stopAll = false;
|
||||
this.taskStats = {};
|
||||
this.taskLimit = {};
|
||||
this.taskDisabled = {};
|
||||
this.tasksToRun.forEach(task => {
|
||||
this.taskStats[task] = { success: 0, failed: 0, totalReward: 0 };
|
||||
this.taskLimit[task] = false;
|
||||
this.taskDisabled[task] = false;
|
||||
});
|
||||
this.isCycleMode = CONFIG.CYCLE_ROUNDS > 0;
|
||||
this.cycleRounds = CONFIG.CYCLE_ROUNDS;
|
||||
this.currentRound = 0;
|
||||
this.currentTaskIndex = 0;
|
||||
this.parseCookie();
|
||||
this.clientIP = null;
|
||||
}
|
||||
getPlatformByCookie(cookie) {
|
||||
const match = cookie.match(/kpn=([^;]+)/);
|
||||
const kpn = match ? match[1].toUpperCase() : "KUAISHOU";
|
||||
return kpn === "NEBULA" ? CONFIG.PLATFORM_CONFIG.NEBULA : CONFIG.PLATFORM_CONFIG.KUAISHOU;
|
||||
}
|
||||
parseCookie() {
|
||||
try {
|
||||
this.mod = this.cookie.match(/mod=([^;]+)/)?.[1] || "Xiaomi(23116PN5BC)";
|
||||
this.egid = this.cookie.match(/egid=([^;]+)/)?.[1] || "";
|
||||
this.did = this.cookie.match(/did=([^;]+)/)?.[1] || "";
|
||||
this.userId = this.cookie.match(/userId=([^;]+)/)?.[1] || "";
|
||||
this.apiSt = this.cookie.match(/kuaishou\.api_st=([^;]+)/)?.[1] || "";
|
||||
this.appver = this.cookie.match(/appver=([^;]+)/)?.[1] || "13.7.20.10468";
|
||||
this.queryParams = `mod=${this.mod}&appver=${this.appver}&egid=${this.egid}&did=${this.did}`;
|
||||
} catch (e) {
|
||||
log(this.proxyUrl, this.platform.displayName, `${this.remark} 解析cookie失败: ${e.message}`);
|
||||
}
|
||||
}
|
||||
async initIP() {
|
||||
try {
|
||||
if (this.proxyUrl) {
|
||||
log(null, this.platform.displayName, `账号 [${this.remark}] 代理: ${maskProxyUrl(this.proxyUrl)}`);
|
||||
const ip = await checkProxyIP(this.proxyUrl);
|
||||
if (!ip) {
|
||||
this.stopAll = true;
|
||||
log(this.proxyUrl, this.platform.displayName, `${this.remark} 初始化失败:代理IP检测无有效结果`);
|
||||
return;
|
||||
}
|
||||
this.clientIP = ip;
|
||||
log(this.proxyUrl, this.platform.displayName, `${this.remark} 代理出口IP: ${ip}`);
|
||||
} else {
|
||||
if (!localPublicIP) await checkLocalIP();
|
||||
this.clientIP = localPublicIP;
|
||||
}
|
||||
} catch (e) {
|
||||
this.stopAll = true;
|
||||
log(this.proxyUrl, this.platform.displayName, `${this.remark} 初始化失败:${e.message}`);
|
||||
}
|
||||
}
|
||||
async retry(fn, desc, times = 3, delay = 2000) {
|
||||
let cnt = 0;
|
||||
while (cnt < times && !this.stopAll) {
|
||||
try {
|
||||
const res = await fn();
|
||||
if (res) return res;
|
||||
} catch (e) {}
|
||||
cnt++;
|
||||
if (cnt < times && !this.stopAll) await new Promise(r => setTimeout(r, delay));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
getImpExt(task) {
|
||||
if (task.name.includes("搜索")) {
|
||||
const word = CONFIG.SEARCH_KEYWORDS[Math.floor(Math.random() * CONFIG.SEARCH_KEYWORDS.length)];
|
||||
return JSON.stringify({
|
||||
openH5AdCount: 2,
|
||||
sessionLookedCompletedCount: "1",
|
||||
sessionType: "1",
|
||||
searchKey: word,
|
||||
triggerType: "2",
|
||||
disableReportToast: "true",
|
||||
businessEnterAction: "7",
|
||||
neoParams: task.linkUrl || ""
|
||||
});
|
||||
}
|
||||
return "{}";
|
||||
}
|
||||
async getAdInfo(taskKey) {
|
||||
const task = this.taskConfigs[taskKey];
|
||||
if (!task) return null;
|
||||
const adUrl = "/rest/e/reward/mixed/ad";
|
||||
const commonData = {
|
||||
encData: "|encData|",
|
||||
sign: "|sign|",
|
||||
cs: "false",
|
||||
client_key: this.platform.adClientKey,
|
||||
videoModelCrowdTag: "1_23",
|
||||
os: "android",
|
||||
"kuaishou.api_st": this.apiSt,
|
||||
uQaTag: "1##swLdgl:99#ecPp:-9#cmNt:-0#cmHs:-3#cmMnsl:-0"
|
||||
};
|
||||
const deviceData = {
|
||||
earphoneMode: "1", mod: this.mod, appver: this.appver,
|
||||
isp: "CUCC", language: "zh-cn", ud: this.userId,
|
||||
did_tag: "0", net: "WIFI", kcv: "1599", app: "0",
|
||||
kpf: "ANDROID_PHONE", ver: "11.6", android_os: "0",
|
||||
boardPlatform: "pineapple", kpn: this.platform.kpn,
|
||||
androidApiLevel: "35", country_code: "cn", sys: "ANDROID_15",
|
||||
sw: "1080", sh: "2400", abi: "arm64", userRecoBit: "0"
|
||||
};
|
||||
const impData = {
|
||||
appInfo: {
|
||||
appId: this.platform.appId, name: this.platform.appName,
|
||||
packageName: this.platform.packageName, version: this.appver, versionCode: -1
|
||||
},
|
||||
deviceInfo: { osType: 1, osVersion: "15", deviceId: this.did, screenSize: { width: 1080, height: 2249 }, ftt: "" },
|
||||
userInfo: { userId: this.userId, age: 0, gender: "" },
|
||||
impInfo: [{
|
||||
pageId: task.pageId || 100011251,
|
||||
subPageId: task.subPageId,
|
||||
action: 0,
|
||||
browseType: task.name.includes("搜索") ? 4 : 3,
|
||||
impExtData: this.getImpExt(task),
|
||||
mediaExtData: "{}"
|
||||
}]
|
||||
};
|
||||
const base64Imp = Buffer.from(JSON.stringify(impData)).toString("base64");
|
||||
// 传kpnType到签名函数
|
||||
const encSign = await this.retry(
|
||||
() => getEncSign(base64Imp, this.proxyUrl, this.platform.displayName, this.remark, this.kpnType),
|
||||
"获取广告加密签名"
|
||||
);
|
||||
if (!encSign) return null;
|
||||
commonData.encData = encSign.encdata;
|
||||
commonData.sign = encSign.sign;
|
||||
// 传kpnType到签名函数
|
||||
const nsSign = await this.retry(
|
||||
() => getNsSign({
|
||||
urlpath: adUrl,
|
||||
reqdata: querystring.stringify(commonData) + "&" + querystring.stringify(deviceData),
|
||||
salt: this.salt
|
||||
}, this.proxyUrl, this.platform.displayName, this.remark, this.kpnType),
|
||||
"获取广告请求nssig"
|
||||
);
|
||||
if (!nsSign) return null;
|
||||
const reqQuery = {
|
||||
...deviceData,
|
||||
sig: nsSign.sig,
|
||||
__NS_sig3: nsSign.__NS_sig3,
|
||||
__NS_xfalcon: nsSign.__NS_xfalcon,
|
||||
__NStokensig: nsSign.__NStokensig
|
||||
};
|
||||
const finalUrl = "https://api.e.kuaishou.com" + adUrl + "?" + querystring.stringify(reqQuery);
|
||||
const { body } = await request({
|
||||
method: "POST",
|
||||
url: finalUrl,
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
Host: "api.e.kuaishou.com",
|
||||
"User-Agent": "kwai-android aegon/3.56.0",
|
||||
Cookie: this.cookie
|
||||
},
|
||||
form: commonData,
|
||||
timeout: 12000
|
||||
}, this.proxyUrl, "获取广告");
|
||||
if (!body) {
|
||||
this.adFailCount++;
|
||||
if (this.adFailCount >= CONFIG.AD_FAIL_LIMIT) this.stopAll = true;
|
||||
return null;
|
||||
}
|
||||
if (body.errorMsg === "OK" && body.feeds?.[0]?.ad) {
|
||||
const ad = body.feeds[0];
|
||||
const title = (ad.caption || ad.ad?.caption || "").slice(0, 30) + "...";
|
||||
let coin = 0;
|
||||
try {
|
||||
const ext = JSON.parse(ad.ad.extData);
|
||||
coin = Number(ext.awardCoin) || 0;
|
||||
if (coin === 0) {
|
||||
coin = ad.ad.adDataV2?.inspirePersonalize?.awardValue ||
|
||||
ad.ad.adDataV2?.inspireAdInfo?.inspirePersonalize?.neoValue || 0;
|
||||
}
|
||||
} catch (e) {}
|
||||
if (coin === 5) return null;
|
||||
log(this.proxyUrl, this.platform.displayName, `${this.remark} 获取广告成功:${title}`);
|
||||
log(null, this.platform.displayName, `${this.remark} 预计获得: ${coin} 金币`);
|
||||
return {
|
||||
cid: ad.ad.creativeId,
|
||||
llsid: ad.exp_tag?.split("/")?.[1]?.split("_")?.[0] || "",
|
||||
hasRewardEnd: ad.ad.adDataV2?.onceAgainRewardInfo?.hasMore || false,
|
||||
expectedCoins: coin,
|
||||
taskConfig: task
|
||||
};
|
||||
}
|
||||
this.adFailCount++;
|
||||
if (this.adFailCount >= CONFIG.AD_FAIL_LIMIT) this.stopAll = true;
|
||||
return null;
|
||||
}
|
||||
async genReportSign(cid, llsid, task) {
|
||||
try {
|
||||
const bizStr = JSON.stringify({
|
||||
businessId: task.businessId,
|
||||
endTime: Date.now(),
|
||||
extParams: "",
|
||||
mediaScene: "video",
|
||||
neoInfos: [{
|
||||
creativeId: cid, extInfo: "", llsid,
|
||||
requestSceneType: task.requestSceneType,
|
||||
taskType: task.taskType,
|
||||
watchExpId: "", watchStage: 0
|
||||
}],
|
||||
pageId: task.pageId || 100011251,
|
||||
posId: task.posId,
|
||||
reportType: 0,
|
||||
sessionId: "",
|
||||
startTime: Date.now() - 30000,
|
||||
subPageId: task.subPageId
|
||||
});
|
||||
const postData = `bizStr=${encodeURIComponent(bizStr)}&cs=false&client_key=${this.platform.reportClientKey}`;
|
||||
const qs = this.queryParams + "&" + postData;
|
||||
// 传kpnType到签名函数
|
||||
const sign = await this.retry(
|
||||
() => getNsSign({
|
||||
urlpath: "/rest/r/ad/task/report",
|
||||
reqdata: qs,
|
||||
salt: this.salt
|
||||
}, this.proxyUrl, this.platform.displayName, this.remark, this.kpnType),
|
||||
"生成报告签名"
|
||||
);
|
||||
if (!sign) return null;
|
||||
return {
|
||||
sig: sign.sig, sig3: sign.__NS_sig3,
|
||||
xfalcon: sign.__NS_xfalcon, sigtoken: sign.__NStokensig,
|
||||
post: postData
|
||||
};
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
async submitReport(cid, llsid, taskKey, task) {
|
||||
const sign = await this.genReportSign(cid, llsid, task);
|
||||
if (!sign) return { success: false, reward: 0 };
|
||||
const url = "https://api.e.kuaishou.com/rest/r/ad/task/report?" +
|
||||
`${this.queryParams}&sig=${sign.sig}&__NS_sig3=${sign.sig3}&__NS_xfalcon=${sign.xfalcon}&__NStokensig=${sign.sigtoken}`;
|
||||
const { body } = await request({
|
||||
method: "POST",
|
||||
url,
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
Host: "api.e.kuaishou.com",
|
||||
Cookie: this.cookie,
|
||||
"User-Agent": "kwai-android aegon/3.56.0"
|
||||
},
|
||||
form: querystring.parse(sign.post),
|
||||
timeout: 12000
|
||||
}, this.proxyUrl, "提交任务报告");
|
||||
if (!body) return { success: false, reward: 0 };
|
||||
if (body.result === 1) {
|
||||
const coin = Number(body.data?.neoAmount) || 0;
|
||||
this.taskStats[taskKey].totalReward += coin;
|
||||
if (coin === 1) {
|
||||
this.continuous1Coin++;
|
||||
if (this.continuous1Coin >= CONFIG.CONTINUOUS_1COIN_LIMIT) {
|
||||
log(this.proxyUrl, this.platform.displayName, `${this.remark} 连续${CONFIG.CONTINUOUS_1COIN_LIMIT}次1金币,停止任务`);
|
||||
this.stopAll = true;
|
||||
}
|
||||
} else {
|
||||
this.continuous1Coin = 0;
|
||||
}
|
||||
if (coin <= CONFIG.LOW_REWARD_THRESHOLD) {
|
||||
this.lowRewardStreak++;
|
||||
if (this.lowRewardStreak >= CONFIG.LOW_REWARD_LIMIT) {
|
||||
log(this.proxyUrl, this.platform.displayName, `${this.remark} 连续低奖励超限,停止任务`);
|
||||
this.stopAll = true;
|
||||
}
|
||||
} else {
|
||||
this.lowRewardStreak = 0;
|
||||
}
|
||||
return { success: true, reward: coin };
|
||||
}
|
||||
if ([20107, 20108, 1003, 415].includes(body.result)) {
|
||||
return { success: false, reward: 0, limitReached: true };
|
||||
}
|
||||
return { success: false, reward: 0 };
|
||||
}
|
||||
async runTask(taskKey) {
|
||||
if (this.taskDisabled[taskKey] || this.taskLimit[taskKey] || this.stopAll) return { success: false, reward: 0 };
|
||||
let adInfo = null;
|
||||
while (!adInfo && !this.stopAll) {
|
||||
adInfo = await this.getAdInfo(taskKey);
|
||||
if (!adInfo && !this.stopAll) await new Promise(r => setTimeout(r, 3000));
|
||||
}
|
||||
if (!adInfo) {
|
||||
this.taskStats[taskKey].failed++;
|
||||
return { success: false, reward: 0 };
|
||||
}
|
||||
const watchMs = Math.floor(Math.random() * (CONFIG.WATCH_MAX - CONFIG.WATCH_MIN) + CONFIG.WATCH_MIN) * 1000;
|
||||
log(this.proxyUrl, this.platform.displayName, `${this.remark} 观看广告中,等待 ${Math.round(watchMs/1000)} 秒...`);
|
||||
await new Promise(r => setTimeout(r, watchMs));
|
||||
log(this.proxyUrl, this.platform.displayName, `${this.remark} 观看完成,提交任务报告`);
|
||||
const result = await this.submitReport(adInfo.cid, adInfo.llsid, taskKey, adInfo.taskConfig);
|
||||
if (result.success) {
|
||||
this.taskStats[taskKey].success++;
|
||||
log(this.proxyUrl, this.platform.displayName, `${this.remark} ✅ 提交成功!获得 ${result.reward} 金币`);
|
||||
return { success: true, reward: result.reward, hasRewardEnd: adInfo.hasRewardEnd };
|
||||
}
|
||||
if (result.limitReached) this.taskLimit[taskKey] = true;
|
||||
this.taskStats[taskKey].failed++;
|
||||
return { success: false, reward: 0, limitReached: result.limitReached || false };
|
||||
}
|
||||
nextTask() {
|
||||
const available = this.tasksToRun.filter(t => !this.taskLimit[t] && !this.taskDisabled[t]);
|
||||
if (available.length === 0 || this.stopAll) return null;
|
||||
this.currentTaskIndex = (this.currentTaskIndex + 1) % available.length;
|
||||
return available[this.currentTaskIndex];
|
||||
}
|
||||
async restAfterAd(count) {
|
||||
if (count > 0 && count % CONFIG.APPEND_REST_INTERVAL === 0) {
|
||||
const ms = Math.floor(Math.random() * (CONFIG.APPEND_REST_MAX - CONFIG.APPEND_REST_MIN)) + CONFIG.APPEND_REST_MIN;
|
||||
await new Promise(r => setTimeout(r, ms));
|
||||
}
|
||||
}
|
||||
async run() {
|
||||
await this.initIP();
|
||||
if (this.stopAll) {
|
||||
return { success: false, remark: this.remark, platform: this.platform.name, taskCount: 0, totalReward: 0, exitIP: this.clientIP, stopReason: "初始化失败" };
|
||||
}
|
||||
const user = await getUserInfo(this.cookie, this.platform, this.proxyUrl);
|
||||
if (!user.success || user.ckExpired) {
|
||||
log(this.proxyUrl, this.platform.displayName, `${this.remark} Cookie已过期或无效`);
|
||||
return { success: false, remark: this.remark, platform: this.platform.name, taskCount: 0, totalReward: 0, exitIP: this.clientIP, stopReason: "Cookie过期" };
|
||||
}
|
||||
log(this.proxyUrl, this.platform.displayName,
|
||||
`${this.remark} 登录成功 | 昵称: ${user.nickname || "未知"} | 金币: ${user.totalCoin} | 余额: ${user.allCash.toFixed(2)}`);
|
||||
let totalTasks = 0, appendTasks = 0, stopReason = "正常结束";
|
||||
while (!this.stopAll) {
|
||||
if (this.isCycleMode && this.currentRound >= this.cycleRounds) {
|
||||
stopReason = `已完成${this.cycleRounds}轮任务`;
|
||||
break;
|
||||
}
|
||||
const task = this.nextTask();
|
||||
if (!task) { stopReason = "无可用任务"; this.stopAll = true; break; }
|
||||
const res = await this.runTask(task);
|
||||
totalTasks++;
|
||||
if (res.hasRewardEnd) {
|
||||
appendTasks++;
|
||||
await this.restAfterAd(appendTasks);
|
||||
await this.runTask(task);
|
||||
}
|
||||
if (this.adFailCount >= CONFIG.AD_FAIL_LIMIT) { stopReason = "广告获取失败达上限"; this.stopAll = true; }
|
||||
if (this.nextTask() && !this.stopAll) {
|
||||
const delay = Math.floor(Math.random() * 5 + 5) * 1000;
|
||||
await new Promise(r => setTimeout(r, delay));
|
||||
}
|
||||
if (this.isCycleMode && this.currentTaskIndex === this.tasksToRun.length - 1) this.currentRound++;
|
||||
}
|
||||
const totalReward = Object.values(this.taskStats).reduce((s, t) => s + t.totalReward, 0);
|
||||
log(this.proxyUrl, this.platform.displayName,
|
||||
`${this.remark} 结束 | 执行任务: ${totalTasks} | 总获金币: ${totalReward} | 原因: ${stopReason}`);
|
||||
for (const [k, s] of Object.entries(this.taskStats)) {
|
||||
const cfg = this.taskConfigs[k];
|
||||
if (cfg) log(null, this.platform.displayName, ` └ ${cfg.name}: 成功${s.success}次 失败${s.failed}次 奖励${s.totalReward}金币`);
|
||||
}
|
||||
return { success: true, remark: this.remark, platform: this.platform.name, taskCount: totalTasks, appendCount: appendTasks, totalReward, exitIP: this.clientIP, stopReason };
|
||||
}
|
||||
}
|
||||
|
||||
// ==============================================
|
||||
// 账号解析 & 批量执行(原代码未改动)
|
||||
// ==============================================
|
||||
function parseAccountLine(line, index) {
|
||||
if (!line || typeof line !== "string") return null;
|
||||
const parts = line.split("#");
|
||||
if (parts.length < 3) return null;
|
||||
const remark = parts[0].trim() || `账号${index}`;
|
||||
const cookie = parts[1].trim();
|
||||
const salt = parts[2].trim();
|
||||
let proxy = parts[3]?.trim() || null;
|
||||
if (!cookie || !salt) return null;
|
||||
if (proxy && proxy.includes("|")) {
|
||||
const [host, port, user, pwd] = proxy.split("|");
|
||||
proxy = `socks5://${user}:${pwd}@${host}:${port}`;
|
||||
}
|
||||
if (proxy && !/^socks5:\/\//i.test(proxy)) {
|
||||
console.log(`⚠️ 账号${index} 代理格式非socks5,已忽略: ${proxy}`);
|
||||
proxy = null;
|
||||
}
|
||||
return { cookie, salt, remark, proxyUrl: proxy };
|
||||
}
|
||||
function loadAllAccounts() {
|
||||
const accounts = [];
|
||||
const exists = new Set();
|
||||
let index = 1;
|
||||
let proxyCount = 0;
|
||||
const mainCk = process.env.ksck;
|
||||
if (mainCk) {
|
||||
mainCk.split("&").forEach(line => {
|
||||
line = line.trim();
|
||||
if (line && !exists.has(line)) {
|
||||
const acc = parseAccountLine(line, index++);
|
||||
if (acc) { accounts.push(acc); exists.add(line); if (acc.proxyUrl) proxyCount++; }
|
||||
}
|
||||
});
|
||||
}
|
||||
for (let i = 1; i <= 666; i++) {
|
||||
const line = process.env[`ksck${i}`]?.trim();
|
||||
if (line && !exists.has(line)) {
|
||||
const acc = parseAccountLine(line, index++);
|
||||
if (acc) { accounts.push(acc); exists.add(line); if (acc.proxyUrl) proxyCount++; }
|
||||
}
|
||||
}
|
||||
print(`\n✅ 共加载账号: ${accounts.length} 个(其中代理账号: ${proxyCount} 个)`);
|
||||
return accounts;
|
||||
}
|
||||
async function runAccountList(accounts) {
|
||||
const results = [];
|
||||
for (let i = 0; i < accounts.length; i++) {
|
||||
const acc = accounts[i];
|
||||
print(`\n${"=".repeat(60)}`);
|
||||
print(`🚀 开始执行账号 ${i+1}/${accounts.length}: ${acc.remark}`);
|
||||
print(`${"=".repeat(60)}`);
|
||||
const instance = new KuaishouAccount({ ...acc, index: i + 1 });
|
||||
const result = await instance.run();
|
||||
results.push(result);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
function printSummary(results) {
|
||||
print(`\n${"=".repeat(60)}`);
|
||||
print(" 📊 全部账号执行结果汇总");
|
||||
print(`${"=".repeat(60)}`);
|
||||
let totalReward = 0;
|
||||
results.forEach((r, i) => {
|
||||
const tag = r.platform === "JSB" ? "[极速版]" : "[快手 ]";
|
||||
print(`${tag} 账号${i+1} ${r.remark} | 任务数:${r.taskCount} | 金币:${r.totalReward} | ${r.stopReason}`);
|
||||
totalReward += r.totalReward || 0;
|
||||
});
|
||||
print(`${"=".repeat(60)}`);
|
||||
print(` 🎉 全部完成 | 账号数: ${results.length} | 总金币: ${totalReward}`);
|
||||
print(`${"=".repeat(60)}`);
|
||||
}
|
||||
|
||||
// ==============================================
|
||||
// 启动(原代码未改动)
|
||||
// ==============================================
|
||||
print("================================================================================");
|
||||
print(" ⭐ 快手双端脚本 ⭐ ");
|
||||
print(" 支持快手 & 快手极速版 · 无需卡密授权 · 按kpn自动切换签名接口 ");
|
||||
print("================================================================================");
|
||||
print(`\n🎯 默认任务: ${CONFIG.DEFAULT_TASKS.join(", ")}`);
|
||||
print(`⏱ 观看时长: ${CONFIG.WATCH_MIN}-${CONFIG.WATCH_MAX} 秒`);
|
||||
print(`🔄 循环轮数: ${CONFIG.CYCLE_ROUNDS > 0 ? CONFIG.CYCLE_ROUNDS : "无限制"}`);
|
||||
print("\n📋 环境变量说明:");
|
||||
print(" ksck = 账号配置,格式: 备注#cookie#salt#socks5代理(可选)");
|
||||
print(" ksck1~ksck666 = 多账号扩展");
|
||||
print(" KS_DEFAULT_TASKS = 任务列表,逗号分隔,可选: box,look,food,search");
|
||||
print(" KS_CYCLE_ROUNDS = 循环轮数 (0=无限)");
|
||||
print(" KS_WATCH_MIN/MAX = 广告观看秒数范围");
|
||||
print(" KS_LOW_REWARD_THRESHOLD = 低奖励阈值");
|
||||
print(" KS_LOW_REWARD_LIMIT = 连续低奖励停止次数");
|
||||
print("================================================================================\n");
|
||||
(async () => {
|
||||
const accounts = loadAllAccounts();
|
||||
if (accounts.length === 0) {
|
||||
print("❌ 未检测到账号配置,请设置 ksck 环境变量");
|
||||
print(" 格式: 备注#cookie字符串#salt值");
|
||||
print(" 示例: 我的账号#did=xxx;userId=yyy;...#abcdef1234");
|
||||
process.exit(1);
|
||||
}
|
||||
const results = await runAccountList(accounts);
|
||||
printSummary(results);
|
||||
})();
|
||||
999
脚本库/微信小程序/抓包版/滴滴果园/2025-01-11_ddgy_236924d1.js
Normal file
999
脚本库/微信小程序/抓包版/滴滴果园/2025-01-11_ddgy_236924d1.js
Normal file
File diff suppressed because one or more lines are too long
291
脚本库/微信小程序/抓包版/索尼中国/2025-01-11_sonybbs_359e1e49.js
Normal file
291
脚本库/微信小程序/抓包版/索尼中国/2025-01-11_sonybbs_359e1e49.js
Normal file
File diff suppressed because one or more lines are too long
1577
脚本库/微信小程序/抓包版/统一茄皇-修复版/2023-01-03_tyqh_2fe80596.js
Normal file
1577
脚本库/微信小程序/抓包版/统一茄皇-修复版/2023-01-03_tyqh_2fe80596.js
Normal file
File diff suppressed because it is too large
Load Diff
643
脚本库/微信小程序/抓包版/统一茄皇互助/2023-01-03_qhhz_07a8e366.js
Normal file
643
脚本库/微信小程序/抓包版/统一茄皇互助/2023-01-03_qhhz_07a8e366.js
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user