commit 5b4854515c7ec7fd753d2fbc65400a4cbaf65876 Author: Hermes Agent Date: Sat May 23 18:48:48 2026 +0000 Initial Qinglong script classification corpus diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..59d3668 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +# runtime/cache +metadata/collector_cache.json +__pycache__/ +*.pyc + +# keep generated indexes and scripts tracked diff --git a/INDEX.csv b/INDEX.csv new file mode 100644 index 0000000..d900f93 --- /dev/null +++ b/INDEX.csv @@ -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等小程序字段 diff --git a/INDEX.json b/INDEX.json new file mode 100644 index 0000000..27a4072 --- /dev/null +++ b/INDEX.json @@ -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等小程序字段" + } +] \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..18886e5 --- /dev/null +++ b/README.md @@ -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_原文件名_.ext +脚本库/APP版/账密/<项目>/YYYY-MM-DD_原文件名_.ext +脚本库/web版/抓包/<项目>/YYYY-MM-DD_原文件名_.ext +脚本库/web版/账密/<项目>/YYYY-MM-DD_原文件名_.ext +脚本库/微信小程序/协议版/<项目>/YYYY-MM-DD_原文件名_.ext +脚本库/微信小程序/抓包版/<项目>/YYYY-MM-DD_原文件名_.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 +``` diff --git a/collector.py b/collector.py new file mode 100644 index 0000000..2cc1969 --- /dev/null +++ b/collector.py @@ -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_原文件名_.ext\n", + "脚本库/APP版/账密/<项目>/YYYY-MM-DD_原文件名_.ext\n", + "脚本库/web版/抓包/<项目>/YYYY-MM-DD_原文件名_.ext\n", + "脚本库/web版/账密/<项目>/YYYY-MM-DD_原文件名_.ext\n", + "脚本库/微信小程序/协议版/<项目>/YYYY-MM-DD_原文件名_.ext\n", + "脚本库/微信小程序/抓包版/<项目>/YYYY-MM-DD_原文件名_.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() diff --git a/脚本库/APP版/抓包/content/2026-05-19_content_45c4e352.js b/脚本库/APP版/抓包/content/2026-05-19_content_45c4e352.js new file mode 100644 index 0000000..55a142d --- /dev/null +++ b/脚本库/APP版/抓包/content/2026-05-19_content_45c4e352.js @@ -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) 已注入'); +})(); diff --git a/脚本库/web版/抓包/'Cookie',_env_'JUEJIN_COOKIE',_isLong_true_},/2026-05-19_popup_0a4d4983.js b/脚本库/web版/抓包/'Cookie',_env_'JUEJIN_COOKIE',_isLong_true_},/2026-05-19_popup_0a4d4983.js new file mode 100644 index 0000000..a67256b --- /dev/null +++ b/脚本库/web版/抓包/'Cookie',_env_'JUEJIN_COOKIE',_isLong_true_},/2026-05-19_popup_0a4d4983.js @@ -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 ` +
+
+ ${config.name} +
+ ${config.env} + +
+
+
${displayValue}
+
+ `; + }).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(); diff --git a/脚本库/web版/抓包/B站签到/2025-01-11_bilibili_906ceaaa.js b/脚本库/web版/抓包/B站签到/2025-01-11_bilibili_906ceaaa.js new file mode 100644 index 0000000..760b937 --- /dev/null +++ b/脚本库/web版/抓包/B站签到/2025-01-11_bilibili_906ceaaa.js @@ -0,0 +1,663 @@ +// # Source: https://github.com/lksky8/sign-ql/blob/main/invalid/bilibili.js +// # Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/bilibili.js +// # Repo: lksky8/sign-ql +// # Path: invalid/bilibili.js +// # UploadedAt: 2025-01-11T18:49:38Z +// # SHA256: 906ceaaa11d344b7ecc1697e5f028c2999adb32569f3f9fca4feb951f86d3f46 +// # Category: web版/抓包 +// # Evidence: web/H5关键词 + cookie/token/header +// + +/* + 作者:https://github.com/lksky8/sign-ql + 日期:2022-8-3 + 软件:B站签到 + 功能:自动完成每日登录+5经验+1硬币 观看视频+5经验 分享视频+5经验 漫画签到 直播签到 + 可选自动投币,银瓜子换硬币,大会员每月领取B币或其他福利,每月领取大会员漫画福利,月底在 B 币券过期前进行充电等功能 + Cookies:通过扫码获取 + 变量: + #################################################### + export bzck='ck1@ck2 ' 多个账号用 @ 或者 换行 分割 + export bztb="" #true开启随机投币,false关闭随机投币 + export bzdhyb="" #true开启银瓜子兑换硬币 + export bzvipgift="" #B站大会员权益 1为B币劵,2为会员购优惠券,3为漫画福利券,4为会员购运费券每个月28号自动领取(非会员默认跳过任务) + export bzbicd="" #true B币券过期前进行充电,只会在每个月28号运行 + export bzcdmid="" #充电up主id,不填默认自己,只会在每个月28号运行 + export bztbdz="" #投币点赞true 默认不点赞 + #################################################### + 定时一天一次 + aid获取:https://api.bilibili.com/x/web-interface/view?bvid=BVXXXXXXXX(手动填入bvid或者抓包) + cron: 5 10 * * * +*/ +const $ = new Env('B站签到'); +const notify = $.isNode() ? require('./sendNotify') : ''; +const theday = new Date().getDate(); +const {log} = console; +const Notify = 1; //0为关闭通知,1为打开通知,默认为1 +////////////////////// +bzck = process.env.bzck; +mid2 = process.env.bzcdmid; +tb = process.env.bztb; +dhyb = process.env.bzdhyb; +vipgift = process.env.bzvipgift; +bicd = process.env.bzbicd; +tbdz = process.env.bztbdz; +let bzckArr = []; +let msg = ''; + + +!(async () => { + + if (!(await Envs())) + return; + else { + + + + log(`\n\n============================================= \n脚本执行 - 北京时间(UTC+8):${new Date( + new Date().getTime() + new Date().getTimezoneOffset() * 60 * 1000 + + 8 * 60 * 60 * 1000).toLocaleString()} \n=============================================\n`); + + log(`\n=================== 共找到 ${bzckArr.length} 个账号 ===================`) + + for (let index = 0; index < bzckArr.length; index++) { + + let num = index + 1 + log(`\n========= 开始【第 ${num} 个账号】=========\n`) + + cookies = bzckArr[index]; + bili_jct = cookies.match(/bili_jct=(.*?);/)[1] + header = JSON.parse(`{"Connection":"keep-alive","Accept-Encoding":"gzip, deflate, br","Cache-Contro":"max-age=0","Cookie":"${cookies}","User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36","Accept-Language":"zh-cn","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.9"}`); + msg += `\n第${num}个账号运行结果:` + await getinfo(); + if(loginb = 1){ + await getBvid(); + await check_live_status();//查金银瓜子数量 + await doSign(); + await $.wait(5 * 1000); + await live_sign();//直播签到 + await $.wait(5 * 1000); + await manga_sign();//漫画签到 + await $.wait(5 * 1000); + await sharebv();//分享视频 + await $.wait(5 * 1000); + await playbv();//播放视频 + if(tb == 'true'){ + log('已开启随机视频投币功能') + for (var i = 0;i log(e)) + .finally(() => $.done()) +//获取个人信息 +function getinfo() { + return new Promise((resolve) => { + let url = { + url: 'https://api.bilibili.com/x/web-interface/nav', + headers: header, + } + + $.get(url, (err, resp, data) => { + try { + result = JSON.parse(data); + if (result.message == '账号未登录') { + log('B站账号未登录,需要重新获取cookie') + msg += '账号未登录,需要重新获取cookie' + loginb = 0 + } else { + mid = result.data.mid + if(result.data.level_info.next_exp != '--'){ + var exp = parseInt(result.data.level_info.next_exp) - parseInt(result.data.level_info.current_exp) + var needexp = exp.toString() + }else{ + var needexp = '未知' + } + if(result.data.vipStatus == 0){ + bzvip = '正式会员' + var vipdate = '非会员' + }else if(result.data.vipStatus == 1 && result.data.vip_label.label_theme == 'vip'){ + bzvip = '大会员' + var vipdate = getLocalTime(result.data.vipDueDate) + }else if(result.data.vipStatus == 1 && result.data.vip_label.label_theme == 'annual_vip'){ + bzvip = '年度大会员' + var vipdate = getLocalTime(result.data.vipDueDate) + }else if(result.data.vipStatus == 1 && result.data.vip_label.label_theme == 'ten_annual_vip'){ + bzvip = '十年大会员' + var vipdate = getLocalTime(result.data.vipDueDate) + }else if(result.data.vipStatus == 1 && result.data.vip_label.label_theme == 'hundred_annual_vip'){ + bzvip = '百年大会员' + var vipdate = getLocalTime(result.data.vipDueDate) + } + login = 1 + log(`【账号信息】${result.data.uname}(ID:${mid})\n【会员等级】${bzvip}\n【会员到期】${vipdate}\n【账号等级】Lv.${result.data.level_info.current_level}\n【账号经验】${result.data.level_info.current_exp}|还要${needexp}经验可以升级\n【账号资本】硬币${result.data.money}个;B币${result.data.wallet.bcoin_balance}个`) + } + } catch (e) { + $.logErr(e, resp) + } finally { + resolve(); + } + }) + }) +} +/** + * 登录+5经验+1硬币 + */ +function doSign(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: 'https://www.bilibili.com/', + headers: header, + } + $.get(url, async (error, response, data) => { + try { + if (error) { + console.log(`${JSON.stringify(err)}`) + console.log(`${$.name} API请求失败,请检查网路重试`); + } else { + log('【B站每日登录】登录成功+5经验+1硬币') + msg += '\n【B站每日登录】登录成功+5经验+1硬币' + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} +/** + * B站直播签到 + */ +function live_sign(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: 'https://api.live.bilibili.com/xlive/web-ucenter/v1/sign/DoSign', + headers: header, + } + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (error) { + console.log(`${JSON.stringify(error)}`) + console.log(`${$.name} API请求失败,请检查网路重试`); + } else if(result.code == 0){ + log(`【B站直播】签到成功,获得${result.data.text},今天是第${result.data.hadSignDays}天完成签到`) + msg += `\n【B站直播】签到成功,获得${result.data.text},今天是第${result.data.hadSignDays}天完成签到` + }else if(result.code == 1011040 && result.message == '今日已签到过,无法重复签到'){ + log('【B站直播】今日已签到过,无法重复签到') + msg +='\n【B站直播】今日已签到过' + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} +/** + * B站漫画签到 + */ +function manga_sign(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: 'https://manga.bilibili.com/twirp/activity.v1.Activity/ClockIn', + headers: header, + body: 'platform=ios' + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.msg == 'clockin clockin is duplicate') { + log('【B站漫画签到】今日已签到过,无法重复签到') + msg +='\n【B站漫画签到】今日已签到过' + } else if(result.code == 0){ + log('【B站漫画签到】签到成功') + msg += `\n【B站漫画签到】签到成功` + } else{ + log(`${JSON.stringify(error)}`) + log(`${$.name} API请求失败,请检查网路重试`); + msg += `\n【B站漫画签到】签到失败` + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} +/** + * 分享视频 + */ +function sharebv(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: 'https://api.bilibili.com/x/web-interface/share/add', + headers: header, + body: `bvid=${BVid}&csrf=${bili_jct}` + } + $.post(url, async (error, response, data) => { + try { + if (error) { + console.log(`${JSON.stringify(error)}`) + console.log(`${$.name} API请求失败,请检查网路重试`); + } else { + log('【每日分享视频】任务完成+5经验') + msg += '\n【每日分享视频】任务完成+5经验' + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} +/** + * 播放视频 + */ +function playbv(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: 'https://api.bilibili.com/x/click-interface/web/heartbeat', + headers: header, + body: `bvid=${BVid}&csrf=${bili_jct}&played_time=2` + } + $.post(url, async (error, response, data) => { + try { + if (error) { + console.log(`${JSON.stringify(error)}`) + console.log(`${$.name} API请求失败,请检查网路重试`); + } else { + log('【每日观看视频】任务完成+5经验') + msg += '\n【每日观看视频】任务完成+5经验' + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} +/** + * 投币 + */ +function coin_add(id) { + return new Promise((resolve) => { + var dz = getdz(); + let url = { + url: 'https://api.bilibili.com/x/web-interface/coin/add', + headers: { + 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36', + 'content-type': 'application/x-www-form-urlencoded', + 'referer': 'https://www.bilibili.com/video/'+ BVid, + 'cookie': cookies + }, + body: `bvid=${id}&multiply=1&select_like=${dz}&cross_domain=true&csrf=${bili_jct}` + } + $.post(url, async (error, response, data) => { + try { + let result =JSON.parse(data) + if (error) { + console.log(`${JSON.stringify(error)}`) + console.log(`${$.name} API请求失败,请检查网路重试`); + } else if(result.code == 0) { + log('【每日投币】投币成功') + msg += '\n【每日投币】投币成功' + } else if(result.code == 34005) { + log('【每日投币】超过投币上限啦') + msg += '\n【每日投币】超过投币上限啦' + } else if(result.code == -104) { + log('【每日投币】硬币不足无法投币') + msg += '\n【每日投币】硬币不足无法投币' + } else{ + log(result.message) + msg += `\n${result.message}` + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }) + }) +} +//随机取一个bvid +function getBvid(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: 'https://api.bilibili.com/x/web-interface/dynamic/region?pn=3&ps=12&rid=129', + headers: header, + } + $.get(url, async (error, response, data) => { + try { + if (error) { + console.log(`${JSON.stringify(error)}`) + console.log(`${$.name} API请求失败,请检查网路重试`); + } else { + bvid = uniq(data.match(/(BV[A-Za-z0-9]{10})/g)).slice(0,5) + BVid = data.match(/(BV[A-Za-z0-9]{10})/)[0] + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} +//查任务完成状态 +function checktask(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: 'https://api.bilibili.com/x/member/web/exp/reward', + headers: header, + } + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data) + if (error) { + console.log(`${JSON.stringify(error)}`) + console.log(`${$.name} API请求失败,请检查网路重试`); + } else { + log(`每日登录:${result.data.login},每日观看视频:${result.data.watch},每日投币获得:${result.data.coins}/50经验,每日分享视频:${result.data.share}\n有延迟,一般任务完成后过一段时间才会刷新`) + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} +//查金银瓜子状态 +function check_live_status(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: 'https://api.live.bilibili.com/pay/v1/Exchange/getStatus', + headers: header, + } + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data) + if (error) { + console.log(`${JSON.stringify(error)}`) + console.log(`${$.name} API请求失败,请检查网路重试`); + } else { + log(`B站直播金瓜子数:${result.data.gold},银瓜子数:${result.data.silver}`) + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} +//银瓜子换硬币 +function silver2coin(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: 'https://api.live.bilibili.com/xlive/revenue/v1/wallet/silver2coin', + headers: header, + body: `csrf=${bili_jct}` + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data) + if (error) { + console.log(`${JSON.stringify(error)}`) + console.log(`${$.name} API请求失败,请检查网路重试`); + } else if(result.message == '每天最多能兑换 1 个') { + log('【B站银瓜子换硬币】今天已经兑换过了') + msg += '\n【B站银瓜子换硬币】今天已经兑换过了' + } else if(result.message == '兑换成功'){ + log(`【B站银瓜子换硬币】兑换1个硬币成功,剩余银瓜子:${result.data.silver}`) + msg += `\n【B站银瓜子换硬币】兑换1个硬币成功,剩余银瓜子:${result.data.silver}` + } else { + log('【B站银瓜子换硬币】银瓜子不够,兑换失败') + msg += '\n【B站银瓜子换硬币】银瓜子不够,兑换失败' + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} +//大会员每月领福利 +function vip_privilege_receive(timeout = 3 * 1000) { + return new Promise((resolve) => { + let gift = getvipgift(); + let url = { + url: 'https://api.bilibili.com/x/vip/privilege/receive', + headers: header, + body: `type=${gift}&csrf=${bili_jct}` + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data) + if (error) { + console.log(`${JSON.stringify(error)}`) + console.log(`${$.name} API请求失败,请检查网路重试`); + } else if(result.message == '当前非大会员') { + log('【大会员每月领福利】领取失败,当前账号不是大会员') + msg += '\n【大会员每月领福利】领取失败,当前账号不是大会员' + } else if(result.code == 0){ + log(`【大会员每月领福利】兑换奖励成功`) + msg += '\n【大会员每月领福利】兑换奖励成功' + } else if(result.code == 69801) { + log('【大会员每月领福利】你已领取过该权益') + msg += '【大会员每月领福利】你已领取过该权益' + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} +//大会员每月领漫画阅读券 +function vip_manga_reward(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: 'https://manga.bilibili.com/twirp/user.v1.User/GetVipReward', + headers: header, + body: '{"reason_id": 1}' + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data) + if (error) { + console.log(`${JSON.stringify(error)}`) + console.log(`${$.name} API请求失败,请检查网路重试`); + } else if(result.msg == '已经领取过该奖励或者未达到领取条件哦~') { + log('【大会员每月领漫画福利】已经领取过该奖励或者未达到领取条件哦~') + msg += '\n【大会员每月领漫画福利】已经领取过该奖励或者未达到领取条件哦~' + } else if(result.code == 0){ + log(`【大会员每月领漫画福利】兑换奖励成功`) + msg += '\n【大会员每月领漫画福利】兑换奖励成功' + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} +//B币券给指定up主充电,可充自己 +function elec_pay(timeout = 3 * 1000) { + return new Promise((resolve) => { + midd = getcdid(); + let url = { + url: 'http://api.bilibili.com/x/ugcpay/web/v2/trade/elec/pay/quick', + headers: header, + body: `bp_num=2&is_bp_remains_prior=true&up_mid=${midd}&otype=up&oid=${midd}&csrf=${bili_jct}` + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data) + if (result.code == 88214) { + log('【用B币给up主充电】up主未开通充电') + msg += '\n【用B币给up主充电】up主未开通充电' + } else if(result.data.status == 4) { + log(`【用B币给up主充电】充值${result.data.bp_num}个B币并获得${result.data.exp}经验`) + msg += `\n【用B币给up主充电】充了${result.data.bp_num}个B币并获得${result.data.exp}经验` + } else if(result.data.status == -2 || result.data.status == -4){ + log(`【用B币给up主充电】充电失败,B币少于2或者是B币数量不足`) + msg += '\n【用B币给up主充电】充电失败,B币少于2或者是B币数量不足' + } else if(error){ + console.log(`${JSON.stringify(error)}`) + console.log(`${$.name} API请求失败,请检查网路重试`); + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +// ============================================变量检查============================================ \\ +async function Envs() { + if (bzck) { + if (bzck.indexOf("@") != -1) { + bzck.split("@").forEach((item) => { + bzckArr.push(item); + }); + } else if (bzck.indexOf("\n") != -1) { + bzck.split("\n").forEach((item) => { + bzckArr.push(item); + }); + } else { + bzckArr.push(bzck); + } + } else { + log(`\n 【${$.name}】:未填写变量 bzck`) + return; + } + + return true; +} + +// ============================================发送消息============================================ \\ +async function SendMsg(message) { + if (!message) + return; + + if (Notify > 0) { + if ($.isNode()) { + var notify = require('./sendNotify'); + await notify.sendNotify($.name, message); + } else { + $.msg(message); + } + } else { + log(message); + } +} +/** + * 时间戳转日期 + */ +function getLocalTime(nS) { + return new Date(parseInt(nS)).toLocaleString().replace(/:\d{1,2}$/,' '); +} + +function getcdid(){ + if(typeof(mid2) == 'undefined' || mid2 == ''){ + log('检测到没有填写充电up主id,默认为自己充电') + return mid + }else{ + log(`指定为id:${mid2}充电`) + return mid2 + } +} +function getdz(){ + if(tbdz == 'true'){ + return('1') + }else{ + return('0') + } +} +function getvipgift(){ + if(typeof(vipgift) == 'undefined' || vipgift == ''){ + log('检测到没有填写大会员福利,默认选择B币券') + return('1') + }else{ + log(`你选择的福利是:${vipgift}`) + return vipgift + } +} +function uniq(array){ + var temp = []; + for(var i = 0; i < array.length; i++){ + if(temp.indexOf(array[i]) == -1){ + temp.push(array[i]); + } + } + return temp; +} + +/** + * 修改配置文件 + */ +function modify() { + + fs.readFile('/ql/data/config/config.sh','utf8',function(err,dataStr){ + if(err){ + return log('读取文件失败!'+err) + } + else { + var result = dataStr.replace(/regular/g,string); + fs.writeFile('/ql/data/config/config.sh', result, 'utf8', function (err) { + if (err) {return log(err);} + }); + } + }) +} + +function Env(t, e) { "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); class s { constructor(t) { this.env = t } send(t, e = "GET") { t = "string" == typeof t ? { url: t } : t; let s = this.get; return "POST" === e && (s = this.post), new Promise((e, i) => { s.call(this, t, (t, s, r) => { t ? i(t) : e(s) }) }) } get(t) { return this.send.call(this.env, t) } post(t) { return this.send.call(this.env, t, "POST") } } return new class { constructor(t, e) { this.name = t, this.http = new s(this), this.data = null, this.dataFile = "box.dat", this.logs = [], this.isMute = !1, this.isNeedRewrite = !1, this.logSeparator = "\n", this.startTime = (new Date).getTime(), Object.assign(this, e), this.log("", `ߔ䤻this.name}, 开始!`) } isNode() { return "undefined" != typeof module && !!module.exports } isQuanX() { return "undefined" != typeof $task } isSurge() { return "undefined" != typeof $httpClient && "undefined" == typeof $loon } isLoon() { return "undefined" != typeof $loon } toObj(t, e = null) { try { return JSON.parse(t) } catch { return e } } toStr(t, e = null) { try { return JSON.stringify(t) } catch { return e } } getjson(t, e) { let s = e; const i = this.getdata(t); if (i) try { s = JSON.parse(this.getdata(t)) } catch { } return s } setjson(t, e) { try { return this.setdata(JSON.stringify(t), e) } catch { return !1 } } getScript(t) { return new Promise(e => { this.get({ url: t }, (t, s, i) => e(i)) }) } runScript(t, e) { return new Promise(s => { let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); i = i ? i.replace(/\n/g, "").trim() : i; let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; const [o, h] = i.split("@"), n = { url: `http://${h}/v1/scripting/evaluate`, body: { script_text: t, mock_type: "cron", timeout: r }, headers: { "X-Key": o, Accept: "*/*" } }; this.post(n, (t, e, i) => s(i)) }).catch(t => this.logErr(t)) } loaddata() { if (!this.isNode()) return {}; { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e); if (!s && !i) return {}; { const i = s ? t : e; try { return JSON.parse(this.fs.readFileSync(i)) } catch (t) { return {} } } } } writedata() { if (this.isNode()) { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e), r = JSON.stringify(this.data); s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) } } lodash_get(t, e, s) { const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); let r = t; for (const t of i) if (r = Object(r)[t], void 0 === r) return s; return r } lodash_set(t, e, s) { return Object(t) !== t ? t : (Array.isArray(e) || (e = e.toString().match(/[^.[\]]+/g) || []), e.slice(0, -1).reduce((t, s, i) => Object(t[s]) === t[s] ? t[s] : t[s] = Math.abs(e[i + 1]) >> 0 == +e[i + 1] ? [] : {}, t)[e[e.length - 1]] = s, t) } getdata(t) { let e = this.getval(t); if (/^@/.test(t)) { const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : ""; if (r) try { const t = JSON.parse(r); e = t ? this.lodash_get(t, i, "") : e } catch (t) { e = "" } } return e } setdata(t, e) { let s = !1; if (/^@/.test(e)) { const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i), h = i ? "null" === o ? null : o || "{}" : "{}"; try { const e = JSON.parse(h); this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i) } catch (e) { const o = {}; this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i) } } else s = this.setval(t, e); return s } getval(t) { return this.isSurge() || this.isLoon() ? $persistentStore.read(t) : this.isQuanX() ? $prefs.valueForKey(t) : this.isNode() ? (this.data = this.loaddata(), this.data[t]) : this.data && this.data[t] || null } setval(t, e) { return this.isSurge() || this.isLoon() ? $persistentStore.write(t, e) : this.isQuanX() ? $prefs.setValueForKey(t, e) : this.isNode() ? (this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0) : this.data && this.data[e] || null } initGotEnv(t) { this.got = this.got ? this.got : require("got"), this.cktough = this.cktough ? this.cktough : require("tough-cookie"), this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar, t && (t.headers = t.headers ? t.headers : {}, void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar)) } get(t, e = (() => { })) { t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"]), this.isSurge() || this.isLoon() ? (this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.get(t, (t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) })) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { try { if (t.headers["set-cookie"]) { const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar } } catch (t) { this.logErr(t) } }).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => { const { message: s, response: i } = t; e(s, i, i && i.body) })) } post(t, e = (() => { })) { if (t.body && t.headers && !t.headers["Content-Type"] && (t.headers["Content-Type"] = "application/x-www-form-urlencoded"), t.headers && delete t.headers["Content-Length"], this.isSurge() || this.isLoon()) this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.post(t, (t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) }); else if (this.isQuanX()) t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => e(t)); else if (this.isNode()) { this.initGotEnv(t); const { url: s, ...i } = t; this.got.post(s, i).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => { const { message: s, response: i } = t; e(s, i, i && i.body) }) } } time(t, e = null) { const s = e ? new Date(e) : new Date; let i = { "M+": s.getMonth() + 1, "d+": s.getDate(), "H+": s.getHours(), "m+": s.getMinutes(), "s+": s.getSeconds(), "q+": Math.floor((s.getMonth() + 3) / 3), S: s.getMilliseconds() }; /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); for (let e in i) new RegExp("(" + e + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? i[e] : ("00" + i[e]).substr(("" + i[e]).length))); return t } msg(e = t, s = "", i = "", r) { const o = t => { if (!t) return t; if ("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { "open-url": t } : this.isSurge() ? { url: t } : void 0; if ("object" == typeof t) { if (this.isLoon()) { let e = t.openUrl || t.url || t["open-url"], s = t.mediaUrl || t["media-url"]; return { openUrl: e, mediaUrl: s } } if (this.isQuanX()) { let e = t["open-url"] || t.url || t.openUrl, s = t["media-url"] || t.mediaUrl; return { "open-url": e, "media-url": s } } if (this.isSurge()) { let e = t.url || t.openUrl || t["open-url"]; return { url: e } } } }; if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) { let t = ["", "==============ߓ㧳맻懲꧟尟㣽============="]; t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) } } log(...t) { t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator)) } logErr(t, e) { const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) } wait(t) { return new Promise(e => setTimeout(e, t)) } done(t = {}) { const e = (new Date).getTime(), s = (e - this.startTime) / 1e3; this.log("", `ߔ䤻this.name}, 结束! ߕ려{s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) } }(t, e) } diff --git a/脚本库/web版/抓包/notify/2025-01-11_notify_9961f576.py b/脚本库/web版/抓包/notify/2025-01-11_notify_9961f576.py new file mode 100644 index 0000000..d1cbd74 --- /dev/null +++ b/脚本库/web版/抓包/notify/2025-01-11_notify_9961f576.py @@ -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", "
"), + "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() diff --git a/脚本库/web版/抓包/query/2026-05-11_ks_query_848504df.py b/脚本库/web版/抓包/query/2026-05-11_ks_query_848504df.py new file mode 100644 index 0000000..c46af09 --- /dev/null +++ b/脚本库/web版/抓包/query/2026-05-11_ks_query_848504df.py @@ -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() \ No newline at end of file diff --git a/脚本库/web版/抓包/券妈妈时段奖励/2025-01-11_qmm_868f2cd3.js b/脚本库/web版/抓包/券妈妈时段奖励/2025-01-11_qmm_868f2cd3.js new file mode 100644 index 0000000..c1074e6 --- /dev/null +++ b/脚本库/web版/抓包/券妈妈时段奖励/2025-01-11_qmm_868f2cd3.js @@ -0,0 +1,230 @@ +// # Source: https://github.com/lksky8/sign-ql/blob/main/invalid/qmm.js +// # Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/qmm.js +// # Repo: lksky8/sign-ql +// # Path: invalid/qmm.js +// # UploadedAt: 2025-01-11T18:42:58Z +// # SHA256: 868f2cd3002df5797fe7ad064612d6e5bc4b97d168092281a6390b7219643743 +// # Category: web版/抓包 +// # Evidence: web/H5关键词 + cookie/token/header +// + +/* + 作者:https://github.com/lksky8/sign-ql/ + 日期:2023-2-22 + 软件:券妈妈 + 功能:开宝箱 + 抓包:首页左上角 http://app.quanmama.com/ajax/app/UserActionMonitorAjax.ashx 里面的usertoken + 变量:qmm='usertoken@usertoken ' 多个账号用 @ 或者 换行 分割 + 定时每小时一次,默认不推送信息 + +*/ + +//cron: 0 */1 * * * + +const $ = new Env('券妈妈时段奖励'); +const notify = $.isNode() ? require('./sendNotify') : ''; +const md5 = require('md5'); +const {log} = console; +const Notify = 0; //0为关闭通知,1为打开通知,默认为1 +const debug = 0; //0为关闭调试,1为打开调试,默认为0 +////////////////////// +let qmm = process.env.qmm; +let qmmArr = []; +let data = ''; +let msg = ''; + +!(async () => { + + if (!(await Envs())) + return; + else { + + log(`\n\n============================================= \n脚本执行 - 北京时间(UTC+8):${new Date( + new Date().getTime() + new Date().getTimezoneOffset() * 60 * 1000 + + 8 * 60 * 60 * 1000).toLocaleString()} \n=============================================\n`); + + + log(`\n=================== 共找到 ${qmmArr.length} 个账号 ===================`) + + if (debug) { + log(`【debug】 这是你的全部账号数组:\n ${qmmArr}`); + } + + + for (let index = 0; index < qmmArr.length; index++) { + + let num = index + 1 + log(`\n========= 开始【第 ${num} 个账号】=========\n`) + data = qmmArr[index]; + user20 = data.substring(0,20); + time2 = getime(); + sign = md5('f:android_c:575_i:_u:'+user20+'_a:500_k:$App_1379UserAction_t:'+time2).substring(12, 20); + sign2 = md5('f:android_c:575_i:_u:'+user20+'_a:302_k:$App_1379UserAction_t:'+time2).substring(12, 20); + msg += `\n第${num}个账号运行结果:` + log('开始签到'); + await doSign(); + await $.wait(2 * 1000); + await doSign2() + await $.wait(2 * 1000); + + } + await SendMsg(msg); + } + +})() + .catch((e) => log(e)) + .finally(() => $.done()) + + + +/** + * 签到 + */ +function doSign(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://app.quanmama.com/ajax/app/UserActionMonitorAjax.ashx`, + headers: {"Host":"app.quanmama.com","content-length":535,"accept":"application/json, text/javascript, */*; q=0.01","origin":"https://app.quanmama.com","x-requested-with":"XMLHttpRequest","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/77.0.3865.120 MQQBrowser/6.2 TBS/045614 Mobile Safari/537.36; APP_USER/quanmama","sec-fetch-mode":"cors","content-type":"application/x-www-form-urlencoded; charset=UTF-8","sec-fetch-site":"same-origin","accept-encoding":"gzip, deflate, br","accept-language":"zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7"}, + body: `actiontype=500&sign=${sign}&taskSysNo=0&coins=0&signdate=${time2}&f=android&code=575&imei=&usertoken=${data}&v=5.7.5&platform=XiaoMi&type=4&isFromWeb=1`, + } + + if (debug) { + log(`\n【debug】=============== 这是 签到 请求 url ===============`); + log(JSON.stringify(url)); + } + + $.post(url, async (error, response, data) => { + try { + if (debug) { + log(`\n\n【debug】===============这是 签到 返回data==============`); + log(data) + } + + let result = JSON.parse(data); + if (result.error_code == 0) { + log(`4小时宝箱开启成功,获得:${result.data.coins}金币`) + //msg += `\n签到成功,获得:${result.data.count}` + } else if (result['error_msg'] == '您刚开宝箱不久,再等等吧') { + log(`您刚开宝箱不久,再等等吧`) + } else if (result.error_code == 7005) { + log(`4小时宝箱开启失败,需要检查传入数据是否过期`) + await notify.sendNotify('券妈妈', '4小时宝箱开启失败,需要检查传入数据是否失效'); + } else { + log(`4小时宝箱开启失败,原因是:${result['error_msg']}`) + await notify.sendNotify('券妈妈', `4小时宝箱开启失败,原因是:${result['error_msg']}`) + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +function doSign2(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://app.quanmama.com/ajax/app/UserActionMonitorAjax.ashx`, + headers: {"Host":"app.quanmama.com","content-length":535,"accept":"application/json, text/javascript, */*; q=0.01","origin":"https://app.quanmama.com","x-requested-with":"XMLHttpRequest","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/77.0.3865.120 MQQBrowser/6.2 TBS/045614 Mobile Safari/537.36; APP_USER/quanmama","sec-fetch-mode":"cors","content-type":"application/x-www-form-urlencoded; charset=UTF-8","sec-fetch-site":"same-origin","accept-encoding":"gzip, deflate, br","accept-language":"zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7"}, + body: `actiontype=302&sign=${sign2}&taskSysNo=0&coins=0&signdate=${time2}&f=android&code=575&imei=&usertoken=${data}&v=5.7.5&platform=XiaoMi&type=4&isFromWeb=1`, + } + if (debug) { + log(`\n【debug】=============== 这是 签到 请求 url ===============`); + log(JSON.stringify(url)); + } + $.post(url, async (error, response, data) => { + try { + if (debug) { + log(`\n\n【debug】===============这是 签到 返回data==============`); + log(data) + } + let result = JSON.parse(data); + if (result.data.title == '时段奖励') { + log(`1小时宝箱开启成功`) + //msg += `\n签到成功,获得:${result.data.count}` + } else if (result['error_msg'] == '服务异常,请重新尝试!') { + log(`1小时宝箱开启失败,需要检查传入数据是否过期`) + await notify.sendNotify(`券妈妈`, '1小时宝箱开启失败,需要检查传入数据是否过期'); + } else if (result.data.title == '还没到时间哦,再等等吧') { + log(`1小时宝箱还没到时间哦,再等等吧`) + //msg += `\n1小时宝箱开启失败,还没到时间哦,再等等吧` + } else { + log(`1小时宝箱开启失败,原因是:${result['error_msg']}`) + await notify.sendNotify('券妈妈', `1小时宝箱开启失败,原因是:${result['error_msg']}`) + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +// ============================================变量检查============================================ \\ +async function Envs() { + if (qmm) { + if (qmm.indexOf("@") != -1) { + qmm.split("@").forEach((item) => { + qmmArr.push(item); + }); + } else if (qmm.indexOf("\n") != -1) { + qmm.split("\n").forEach((item) => { + qmmArr.push(item); + }); + } else { + qmmArr.push(qmm); + } + } else { + log(`\n 【${$.name}】:未填写变量 qmm`) + return; + } + + return true; +} + +// ============================================发送消息============================================ \\ +async function SendMsg(message) { + if (!message) + return; + + if (Notify > 0) { + if ($.isNode()) { + var notify = require('./sendNotify'); + await notify.sendNotify($.name, message); + } else { + $.msg(message); + } + } else { + log(message); + } +} + +/** + * 获取时间 + */ +function getime() { + var timeString = new Date().toISOString(); + return formattedTime = timeString.replace(/\D/g, '').substring(0,14); +} + +/** + * 修改配置文件 + */ +function modify() { + + fs.readFile('/ql/data/config/config.sh','utf8',function(err,dataStr){ + if(err){ + return log('读取文件失败!'+err) + } + else { + var result = dataStr.replace(/regular/g,string); + fs.writeFile('/ql/data/config/config.sh', result, 'utf8', function (err) { + if (err) {return log(err);} + }); + } + }) +} + +function Env(t, e) { "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); class s { constructor(t) { this.env = t } send(t, e = "GET") { t = "string" == typeof t ? { url: t } : t; let s = this.get; return "POST" === e && (s = this.post), new Promise((e, i) => { s.call(this, t, (t, s, r) => { t ? i(t) : e(s) }) }) } get(t) { return this.send.call(this.env, t) } post(t) { return this.send.call(this.env, t, "POST") } } return new class { constructor(t, e) { this.name = t, this.http = new s(this), this.data = null, this.dataFile = "box.dat", this.logs = [], this.isMute = !1, this.isNeedRewrite = !1, this.logSeparator = "\n", this.startTime = (new Date).getTime(), Object.assign(this, e), this.log("", `🔔${this.name}, 开始!`) } isNode() { return "undefined" != typeof module && !!module.exports } isQuanX() { return "undefined" != typeof $task } isSurge() { return "undefined" != typeof $httpClient && "undefined" == typeof $loon } isLoon() { return "undefined" != typeof $loon } toObj(t, e = null) { try { return JSON.parse(t) } catch { return e } } toStr(t, e = null) { try { return JSON.stringify(t) } catch { return e } } getjson(t, e) { let s = e; const i = this.getdata(t); if (i) try { s = JSON.parse(this.getdata(t)) } catch { } return s } setjson(t, e) { try { return this.setdata(JSON.stringify(t), e) } catch { return !1 } } getScript(t) { return new Promise(e => { this.get({ url: t }, (t, s, i) => e(i)) }) } runScript(t, e) { return new Promise(s => { let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); i = i ? i.replace(/\n/g, "").trim() : i; let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; const [o, h] = i.split("@"), n = { url: `http://${h}/v1/scripting/evaluate`, body: { script_text: t, mock_type: "cron", timeout: r }, headers: { "X-Key": o, Accept: "*/*" } }; this.post(n, (t, e, i) => s(i)) }).catch(t => this.logErr(t)) } loaddata() { if (!this.isNode()) return {}; { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e); if (!s && !i) return {}; { const i = s ? t : e; try { return JSON.parse(this.fs.readFileSync(i)) } catch (t) { return {} } } } } writedata() { if (this.isNode()) { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e), r = JSON.stringify(this.data); s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) } } lodash_get(t, e, s) { const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); let r = t; for (const t of i) if (r = Object(r)[t], void 0 === r) return s; return r } lodash_set(t, e, s) { return Object(t) !== t ? t : (Array.isArray(e) || (e = e.toString().match(/[^.[\]]+/g) || []), e.slice(0, -1).reduce((t, s, i) => Object(t[s]) === t[s] ? t[s] : t[s] = Math.abs(e[i + 1]) >> 0 == +e[i + 1] ? [] : {}, t)[e[e.length - 1]] = s, t) } getdata(t) { let e = this.getval(t); if (/^@/.test(t)) { const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : ""; if (r) try { const t = JSON.parse(r); e = t ? this.lodash_get(t, i, "") : e } catch (t) { e = "" } } return e } setdata(t, e) { let s = !1; if (/^@/.test(e)) { const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i), h = i ? "null" === o ? null : o || "{}" : "{}"; try { const e = JSON.parse(h); this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i) } catch (e) { const o = {}; this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i) } } else s = this.setval(t, e); return s } getval(t) { return this.isSurge() || this.isLoon() ? $persistentStore.read(t) : this.isQuanX() ? $prefs.valueForKey(t) : this.isNode() ? (this.data = this.loaddata(), this.data[t]) : this.data && this.data[t] || null } setval(t, e) { return this.isSurge() || this.isLoon() ? $persistentStore.write(t, e) : this.isQuanX() ? $prefs.setValueForKey(t, e) : this.isNode() ? (this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0) : this.data && this.data[e] || null } initGotEnv(t) { this.got = this.got ? this.got : require("got"), this.cktough = this.cktough ? this.cktough : require("tough-cookie"), this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar, t && (t.headers = t.headers ? t.headers : {}, void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar)) } get(t, e = (() => { })) { t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"]), this.isSurge() || this.isLoon() ? (this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.get(t, (t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) })) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { try { if (t.headers["set-cookie"]) { const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar } } catch (t) { this.logErr(t) } }).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => { const { message: s, response: i } = t; e(s, i, i && i.body) })) } post(t, e = (() => { })) { if (t.body && t.headers && !t.headers["Content-Type"] && (t.headers["Content-Type"] = "application/x-www-form-urlencoded"), t.headers && delete t.headers["Content-Length"], this.isSurge() || this.isLoon()) this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.post(t, (t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) }); else if (this.isQuanX()) t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => e(t)); else if (this.isNode()) { this.initGotEnv(t); const { url: s, ...i } = t; this.got.post(s, i).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => { const { message: s, response: i } = t; e(s, i, i && i.body) }) } } time(t, e = null) { const s = e ? new Date(e) : new Date; let i = { "M+": s.getMonth() + 1, "d+": s.getDate(), "H+": s.getHours(), "m+": s.getMinutes(), "s+": s.getSeconds(), "q+": Math.floor((s.getMonth() + 3) / 3), S: s.getMilliseconds() }; /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); for (let e in i) new RegExp("(" + e + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? i[e] : ("00" + i[e]).substr(("" + i[e]).length))); return t } msg(e = t, s = "", i = "", r) { const o = t => { if (!t) return t; if ("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { "open-url": t } : this.isSurge() ? { url: t } : void 0; if ("object" == typeof t) { if (this.isLoon()) { let e = t.openUrl || t.url || t["open-url"], s = t.mediaUrl || t["media-url"]; return { openUrl: e, mediaUrl: s } } if (this.isQuanX()) { let e = t["open-url"] || t.url || t.openUrl, s = t["media-url"] || t.mediaUrl; return { "open-url": e, "media-url": s } } if (this.isSurge()) { let e = t.url || t.openUrl || t["open-url"]; return { url: e } } } }; if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) { let t = ["", "==============📣系统通知📣=============="]; t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) } } log(...t) { t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator)) } logErr(t, e) { const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) } wait(t) { return new Promise(e => setTimeout(e, t)) } done(t = {}) { const e = (new Date).getTime(), s = (e - this.startTime) / 1e3; this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) } }(t, e) } diff --git a/脚本库/web版/账密/'未知用户',/2026-05-19_juejin_checkin_6f8a138b.js b/脚本库/web版/账密/'未知用户',/2026-05-19_juejin_checkin_6f8a138b.js new file mode 100644 index 0000000..77f6fcc --- /dev/null +++ b/脚本库/web版/账密/'未知用户',/2026-05-19_juejin_checkin_6f8a138b.js @@ -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); +}); diff --git a/脚本库/web版/账密/apply_link.split'id='-1}/2026-03-27_3dmgame_2262c9f7.py b/脚本库/web版/账密/apply_link.split'id='-1}/2026-03-27_3dmgame_2262c9f7.py new file mode 100644 index 0000000..e8ab4dd --- /dev/null +++ b/脚本库/web版/账密/apply_link.split'id='-1}/2026-03-27_3dmgame_2262c9f7.py @@ -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) diff --git a/脚本库/web版/账密/str,_token_str/2025-09-22_PPark_120e7330.py b/脚本库/web版/账密/str,_token_str/2025-09-22_PPark_120e7330.py new file mode 100644 index 0000000..3d7febd --- /dev/null +++ b/脚本库/web版/账密/str,_token_str/2025-09-22_PPark_120e7330.py @@ -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)) diff --git a/脚本库/web版/账密/tyqh/2026-05-23_tyqh_4c779933.py b/脚本库/web版/账密/tyqh/2026-05-23_tyqh_4c779933.py new file mode 100644 index 0000000..be531b5 --- /dev/null +++ b/脚本库/web版/账密/tyqh/2026-05-23_tyqh_4c779933.py @@ -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)) diff --git a/脚本库/web版/账密/url.hostname,/2026-05-11_zsp_video_960b2e28.js b/脚本库/web版/账密/url.hostname,/2026-05-11_zsp_video_960b2e28.js new file mode 100644 index 0000000..da0da26 --- /dev/null +++ b/脚本库/web版/账密/url.hostname,/2026-05-11_zsp_video_960b2e28.js @@ -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); +} diff --git a/脚本库/web版/账密/yxw_appsign/2025-09-28_yxw_appsign_c6d91db1.py b/脚本库/web版/账密/yxw_appsign/2025-09-28_yxw_appsign_c6d91db1.py new file mode 100644 index 0000000..822a7ec --- /dev/null +++ b/脚本库/web版/账密/yxw_appsign/2025-09-28_yxw_appsign_c6d91db1.py @@ -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)) + diff --git a/脚本库/web版/账密/yxw_luckbox/2025-08-21_yxw_luckbox_79511924.py b/脚本库/web版/账密/yxw_luckbox/2025-08-21_yxw_luckbox_79511924.py new file mode 100644 index 0000000..70dbfbf --- /dev/null +++ b/脚本库/web版/账密/yxw_luckbox/2025-08-21_yxw_luckbox_79511924.py @@ -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)) diff --git a/脚本库/web版/账密/中石化加油广东APP签到/2022-07-24_jygd_47493387.js b/脚本库/web版/账密/中石化加油广东APP签到/2022-07-24_jygd_47493387.js new file mode 100644 index 0000000..117c600 --- /dev/null +++ b/脚本库/web版/账密/中石化加油广东APP签到/2022-07-24_jygd_47493387.js @@ -0,0 +1,415 @@ +// # Source: https://github.com/lksky8/sign-ql/blob/main/invalid/jygd.js +// # Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/jygd.js +// # Repo: lksky8/sign-ql +// # Path: invalid/jygd.js +// # UploadedAt: 2022-07-24T02:54:25Z +// # SHA256: 474933874ed61cd8ebd4efed3ee26778f4e3d0290ba16222f9feed61bafb6838 +// # Category: web版/账密 +// # Evidence: web/H5关键词 + username/password/login +// + +/* + 作者:https://github.com/lksky8/sign-ql + 日期:7-11 + 软件:APP分享 + 功能:中石化加油广东APP签到 + 备注:签到活动已结束 + 变量:jygd='账号&密码 ' 多个账号换行 分割 + 定时一天一次 + + cron: 5 10 * * * + */ + +const $ = new Env('中石化加油广东APP签到'); +const notify = $.isNode() ? require('./sendNotify') : ''; +const crypto = require('crypto'); +const NodeRSA = require('node-rsa'); +const {log} = console; +const Notify = 1; //0为关闭通知,1为打开通知,默认为1 +const debug = 1; //0为关闭调试,1为打开调试,默认为0 +////////////////////// +let jygd = process.env.jygd; +let jygdArr = []; +const iv = 'L%n67}G/Mk@k%:~Y' +const clientkey = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnUKx2bWkp7flkIeNpLMwI3SA9217Zo4t9G3kgR4cx2n2UAxN7PZ70Q6wFh9zHq/3NJ8ddkGAVCv0rs7ebBodlkpXBxeTI9OGgZtx3x1GJLVw+nXqNXt51pXJHHaGXFFMAZYPfy9vcWhenQ9YQ+WsBxTIkH2TjvYdXcjlTKp+YnkpNpyXjhAg5VAjWnmJ06kikAOTGGusrgUgtNxDsu9EpAD8HE/Zr+zyUvOjWzGvPV2xr72JRj4pUAL8Df17Qj+t43ujsoLBy4cPdZB/Pru8uJgGSZj7dO8BkBcBu5y+c4Yi9bj07OwMGSMMFnuZCkWZaQ2cTObwodO9pEMd/rl8QwIDAQAB' +let data = ''; +let msg = ''; + +!(async () => { + + if (!(await Envs())) + return; + else { + + + + log(`\n\n============================================= \n脚本执行 - 北京时间(UTC+8):${new Date( + new Date().getTime() + new Date().getTimezoneOffset() * 60 * 1000 + + 8 * 60 * 60 * 1000).toLocaleString()} \n=============================================\n`); + + + log(`\n=================== 共找到 ${jygdArr.length} 个账号 ===================`) + + if (debug) { + log(`【debug】 这是你的全部账号数组:\n ${jygdArr}`); + } + + + for (let index = 0; index < jygdArr.length; index++) { + + + let num = index + 1 + log(`\n========= 开始【第 ${num} 个账号】=========\n`) + + jygd = jygdArr[index].split('&'); + + if (debug) { + log(`\n 【debug】 这是你第 ${num} 账号信息:\n ${data}\n`); + } + + msg += `\n第${num}个账号运行结果:` + log('开始登录'); + await getnewserverkey(); + await $.wait(2 * 1000); + await login(); + await $.wait(2 * 1000); + log('开始签到'); + await doSign(); + + } + await SendMsg(msg); + } + +})() + .catch((e) => log(e)) + .finally(() => $.done()) + + +/** + * 签到 + */ +function doSign(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `https://m.gdoil.cn/webapi/usersign/addusersign`, + headers: { + "Accept-Encoding": "gzip, deflate, br", + "Connection": "keep-alive", + "Accept": "*/*", + "User-Agent": 'jygd_android_'+ accode +'_Mozilla/5.0 (Linux; Android 10; MI 8 Build/QKQ1.190828.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.101 Mobile Safari/537.36_5.4.7', + "Content-Type": "application/x-www-form-urlencoded", + "Host": 'm.gdoil.cn', + "Accept-Language": 'zh-cn' + }, + } + + if (debug) { + log(`\n【debug】=============== 这是 签到 请求 url ===============`); + log(JSON.stringify(url)); + } + + $.post(url, async (error, response, data) => { + try { + if (debug) { + log(`\n\n【debug】===============这是 签到 返回data==============`); + log(data) + } + + let result = JSON.parse(data); + if (result.msg == '插入成功') { + + log(`签到成功,获得:`) + msg += `\n签到成功,获得:` + + } else if (result.msg == '很抱歉,您今天已经签到过了') { + + log(`签到失败,今日已签到`) + msg += `\n签到失败,今日已签到` + + } else { + + log(`签到失败,原因是:${result.msg}`) + msg += `\n签到失败,原因是:${result.msg}` + + } + + + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +/** + * 获取最新数据包 + */ +function getnewserverkey(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `https://m.gdoil.cn/gd/sys/collocateFunctions`, + headers: { + "Accept-Encoding": "gzip, deflate, br", + "Connection": "keep-alive", + "Accept": "*/*", + "User-Agent": "ijygd_android_", + "Content-Type": "application/x-www-form-urlencoded", + "Host": 'm.gdoil.cn', + "Accept-Language": 'zh-Hans-CN;q=1' + }, + body: 'serverkey=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAisPUFQ9b2nstxYMwaAaTKX2mjAKoMDbVuPNItJSREkZa426blKc%252B2grcxG9HwF8Av%252BMccs0UxoNVdRCMnndHMSsWSMXJbK8hZMizNRNVBXGa5X1HQqT65WVpMIIFKpeSvz6wE0PQ1naSg%252F7u5V5NZplZ%252BGJPtxOYNIKMxd%252B69ebt8Xd0W2hhUj%252BwBLosX%252B3mA%252BnnDgaa95qjL6Ax84WFC%252BUq3NtPBgPw0tcSGJfoFgUwCCvnVGpefyYreIxNP2b0%252FmJKL8Oh8zbdLh14fD3waThP7A6AkHyZFi6%252FjqbiTwO3HV75spZsac1SBuZWLhDeZyL0BM2ijnri%252FWQ0QAUqrwIDAQAB&s0OUQNQpaJeq7IpsUxvllA%253D%253D=id3rOfJk0n0Pck4kntbOCA%253D%253D&sign=373764756B81BCB8CCA906E5F6CCCCCC&XDwTDvv1PY2amPINQGWuMA%253D%253D=MizQxeRlF0mogfIzVSuHIRvKwEQPUMnn9hK3ASHG82Ae%252F0WpVsi1BBx3AQZpz7CE&UMPA5UPQq9S4yFFt6BLSCA%253D%253D=toKPsOZPtr%252FpDY%252FjT%252B3WsQ%253D%253D&Mjg%252BT001qTW6f959htWTfA%253D%253D=sgkCYL%252BmpSuE7fQ4rOlOBGsyB%252FgNp5VDTTeIG5ka6%252Fg%253D&isencrypt=1&clientkey=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnUKx2bWkp7flkIeNpLMwI3SA9217Zo4t9G3kgR4cx2n2UAxN7PZ70Q6wFh9zHq%252F3NJ8ddkGAVCv0rs7ebBodlkpXBxeTI9OGgZtx3x1GJLVw%252BnXqNXt51pXJHHaGXFFMAZYPfy9vcWhenQ9YQ%252BWsBxTIkH2TjvYdXcjlTKp%252BYnkpNpyXjhAg5VAjWnmJ06kikAOTGGusrgUgtNxDsu9EpAD8HE%252FZr%252BzyUvOjWzGvPV2xr72JRj4pUAL8Df17Qj%252Bt43ujsoLBy4cPdZB%252FPru8uJgGSZj7dO8BkBcBu5y%252Bc4Yi9bj07OwMGSMMFnuZCkWZaQ2cTObwodO9pEMd%252Frl8QwIDAQAB&nj9PIsw7URBZX23dwlyi', + } + + if (debug) { + log(`\n【debug】=============== 这是 获取数据包 请求 url ===============`); + log(JSON.stringify(url)); + } + + $.post(url, async (error, response, data) => { + try { + if (debug) { + log(`\n\n【debug】===============这是 获取数据包 返回data==============`); + log(data) + } + + if (data != null) { + + data = data.split(','); + let serveraeskey = serverkeydecrypt(data[1])//解密出服务器aeskey + let serverkey = AesDecrypt(data[0],serveraeskey)//用服务器aeskey解密服务器rsa公钥 + let getserverjson = JSON.parse(serverkey);//解密出data第一部分的内容,包含服务器rsa公钥 + let jmaeskey = serverkeyencrypt(getserverjson.data,'yUCpeutYLg11RwFu')//用获取到的服务器rsa公钥加密AESkey + var urlserverrsa1 = encodeURIComponent(getserverjson.data)//url加密服务器rsa公钥 + var urlserverrsa2 = encodeURIComponent(urlserverrsa1) + var urljmaeskey1 = encodeURIComponent(jmaeskey) + var urljmaeskey2 = encodeURIComponent(urljmaeskey1) + let t = timestampMs(); + let time1 = AesEncrypt(`${t}6622572626`,'yUCpeutYLg11RwFu'); + let urltime1 = encodeURIComponent(encodeURIComponent(time1)) + let urltime2 = encodeURIComponent(encodeURIComponent(urltime1)) + let urlclientkey1 = encodeURIComponent(clientkey) + let urlclientkey2 = encodeURIComponent(urlclientkey1) + let md5pass = MD5(`${jygd[1]}`); //MD5加密密码大写 + let jmmd5pass = AesEncrypt(md5pass,'yUCpeutYLg11RwFu') + let urljmmd5pass1 = encodeURIComponent(jmmd5pass) + let urljmmd5pass2 = encodeURIComponent(urljmmd5pass1) + let jmuser = AesEncrypt(`${jygd[0]}`,'yUCpeutYLg11RwFu') + let urljmuser1 = encodeURIComponent(jmuser) + let urljmuser2 = encodeURIComponent(urljmuser1) + let signdata = `wZeKy8G8dbJYgD06vtTgdA===uGOuRotUfSSPdCbUtjb8sQ==&5HHk2cJhjzMvDcu/B5kpGg===KpXZshVgZ0c49gYcubZ5Cg==&XDwTDvv1PY2amPINQGWuMA===${urljmmd5pass1}&e4fsMNonbizjyhEvY/q00w===02FI+9Gn9Ur4tUBCoxcoKg==&wHeo7s49nvTacX2ewH5S+w===T6WarOSE6UG4QCfjDc0PCQ==&ZnvrP+6IyuG29fb+AHGx3A===bFgt8u6JxT7n9Fq6+0HtbN1Vy8V/haNuZTOPBtLzI8k=&Mjg+T001qTW6f959htWTfA==${urltime1}&PebxqIi7YKhNT91eg1Kbqw===/cfnLaSDOiBqXfAI8OcckA==&UMPA5UPQq9S4yFFt6BLSCA===toKPsOZPtr/pDY/jT+3WsQ==&aeskey=${urljmaeskey1}&clientkey=${urlclientkey1}&ptLix3p+b9lkoxVBN5Kcdw===6REGKn9GFbaIc+sT561q0AktJBV8oApRS3PQdCZgXish47K1yzrQLlQTq8CZiHiA&nj9PIsw7URBZX23dwlyi+w==${urljmuser1}&s0OUQNQpaJeq7IpsUxvllA===id3rOfJk0n0Pck4kntbOCA==&isencrypt=1&wBIbaRwOqZj2H/3PAkmITw===JprA988BFmBL/26Fcm09iw==&serverkey=${urlserverrsa1}&dlUm9icrisli8P1XXzF9NA===id3rOfJk0n0Pck4kntbOCA==&key=1e20957112ed5c5c3we73ee6fa631b9w` + let md5sign = MD5(`${signdata}`) + logindata = `e4fsMNonbizjyhEvY%252Fq00w%253D%253D=02FI%252B9Gn9Ur4tUBCoxcoKg%253D%253D&wBIbaRwOqZj2H%252F3PAkmITw%253D%253D=JprA988BFmBL%252F26Fcm09iw%253D%253D&5HHk2cJhjzMvDcu%252FB5kpGg%253D%253D=KpXZshVgZ0c49gYcubZ5Cg%253D%253D&serverkey=${urlserverrsa2}&s0OUQNQpaJeq7IpsUxvllA%253D%253D=id3rOfJk0n0Pck4kntbOCA%253D%253D&sign=${md5sign}&XDwTDvv1PY2amPINQGWuMA%253D%253D=${urljmmd5pass2}&UMPA5UPQq9S4yFFt6BLSCA%253D%253D=toKPsOZPtr%252FpDY%252FjT%252B3WsQ%253D%253D&Mjg%252BT001qTW6f959htWTfA%253D%253D=${urltime2}&isencrypt=1&clientkey=${urlclientkey2}&nj9PIsw7URBZX23dwlyi%252Bw%253D%253D=${urljmuser2}&PebxqIi7YKhNT91eg1Kbqw%253D%253D=%252FcfnLaSDOiBqXfAI8OcckA%253D%253D&wZeKy8G8dbJYgD06vtTgdA%253D%253D=uGOuRotUfSSPdCbUtjb8sQ%253D%253D&dlUm9icrisli8P1XXzF9NA%253D%253D=id3rOfJk0n0Pck4kntbOCA%253D%253D&ptLix3p%252Bb9lkoxVBN5Kcdw%253D%253D=6REGKn9GFbaIc%252BsT561q0AktJBV8oApRS3PQdCZgXish47K1yzrQLlQTq8CZiHiA&aeskey=${urljmaeskey2}&ZnvrP%252B6IyuG29fb%252BAHGx3A%253D%253D=bFgt8u6JxT7n9Fq6%252B0HtbN1Vy8V%252FhaNuZTOPBtLzI8k%253D&wHeo7s49nvTacX2ewH5S%252Bw%253D%253D=T6WarOSE6UG4QCfjDc0PCQ%253D%253D` + + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +/** + * 登录 + */ +function login(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `https://m.gdoil.cn/gd/user/userLogin`, + headers: { + "Accept-Encoding": "gzip, deflate, br", + "Connection": "keep-alive", + "Accept": "*/*", + "User-Agent": "ijygd_android_", + "Content-Type": "application/x-www-form-urlencoded", + "Host": 'm.gdoil.cn', + "Accept-Language": 'zh-Hans-CN;q=1' + }, + body: logindata, + } + + if (debug) { + log(`\n【debug】=============== 这是 登录 请求 url ===============`); + log(JSON.stringify(url)); + } + + $.post(url, async (error, response, data) => { + try { + if (debug) { + log(`\n\n【debug】===============这是 登录 返回data==============`); + log(data) + } + + data = data.split(','); + let loginaeskey = serverkeydecrypt(data[1])//返回aeskey用于解密 + let loginalldata = AesDecrypt(data[0],loginaeskey) + let logindatajson = JSON.parse(loginalldata); + if (logindatajson.accode == null && logindatajson.msg == '用户名或者密码错误') { + + log('获取信息失败,无法登录') + msg += `\n获取信息失败,无法登录` + + } else if(logindatajson.msg == '用户名或者密码错误') { + + log(`【登录失败】用户名或者密码错误 `) + msg += `\n【登陆失败】用户名或者密码错误` + + } else if(logindatajson.msg == '登录成功!') { + + accode = logindatajson.accode + log(`\n账号[${logindatajson.data.nickname}]登录成功,对应手机号:${logindatajson.data.phone}`) + msg += `\n【登陆成功】用户名:${logindatajson.data.nickname}` + } + + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + + +// ============================================变量检查============================================ \\ +async function Envs() { + if (jygd) { + if (jygd.indexOf("\n") != -1) { + jygd.split("\n").forEach((item) => { + jygdArr.push(item); + }); + } else { + jygdArr.push(jygd); + } + } else { + log(`\n 【${$.name}】:未填写变量 jygd`) + return; + } + + return true; +} + +// ============================================发送消息============================================ \\ +async function SendMsg(message) { + if (!message) + return; + + if (Notify > 0) { + if ($.isNode()) { + var notify = require('./sendNotify'); + await notify.sendNotify($.name, message); + } else { + $.msg(message); + } + } else { + log(message); + } +} + +// ===========================================其他设置============================================= \\ +function serverkeydecrypt(str) { + let pem = '-----BEGIN PRIVATE KEY-----MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCdQrHZtaSnt+WQh42kszAjdID3bXtmji30beSBHhzHafZQDE3s9nvRDrAWH3Mer/c0nx12QYBUK/Suzt5sGh2WSlcHF5Mj04aBm3HfHUYktXD6deo1e3nWlckcdoZcUUwBlg9/L29xaF6dD1hD5awHFMiQfZOO9h1dyOVMqn5ieSk2nJeOECDlUCNaeYnTqSKQA5MYa6yuBSC03EOy70SkAPwcT9mv7PJS86NbMa89XbGvvYlGPilQAvwN/XtCP63je6OygsHLhw91kH8+u7y4mAZJmPt07wGQFwG7nL5zhiL1uPTs7AwZIwwWe5kKRZlpDZxM5vCh072kQx3+uXxDAgMBAAECggEAPqhUNGorMKgUz4Ey7mx2wampuOvmPvZnWPxwDwHwdYPCoCJG6iNLMgCoKChftdpmpJDBLFzsxJy+4OeLt4awQzFbe3fpKF0fOoS02jDPwdCJM0HID4cjBFypxK1021OI9RjVE9fSj10GVY3HnUXlRO0C/I8MO+nTyYpB0kocER+VXUoCp4exudp8Fn3ss3Kfj9F2+enuFs9VmyhSlfMZSww+ZwnggQBBHCqKC3QMM8Zj85ZJh6hW6q4TZwMTBmNQRhiO0djTABbADHcyHe3PMZEO8ZABiybfGZSH9wNP/hlSr+b3sXJJ7l4zeoC5vnsaJxcwPbnT8/vs6B5swyWwAQKBgQDNYyDOe23Bi2IVEaER6ajleBGILo1O2+o5a5txK146a/gaiEAtJQ+BhpsB0AZ7g9Cv88oiNltgRTEPB665ktPObiLNQ/Wpl31mHyNe84qnwA3zbh4EInH/aA2Q3L641KPmW4jfP3L7pYD8JUG1TvSrYdqWd9R49F62lYVxMUffnQKBgQDEA31ayH5cMuiB4gCYDraj+LhAIqTgUsH/VxPTLIfK3VBRY6qUl7hmevojhir4Wp+ZAkgjAPcxAz3dwlKUan8aCGXPHTinpTJxxtNqIDZJXn9m6PsXrvRv9LUImbyyyISU+4FD3qFENb/ZHKLKA5UUmEjBPDBpbKyMWeyHdCo1XwKBgDJ1iSjRcCydttIgS6cf9cuyjPQdI8BdDRVgV4cdNYA66HB0SvgMY9vZmxl95ynPP6UKyv1Ox3JGbYAYzhdveDP+IPS3HpK00i0Vt1XrlYQTDhphUmSHpeQuxy5w3TaBn2bH1D+s0e37Qk4wRQ1rQXcdiltvQzcYKnDHGUqu5c6NAoGAArKhmQxFYPN6a782juE09lDICGnxpvy8ms0SAsgMHmipYFVk1aK48QAkTTTdhomIxMxZPdIXlN8cjN7N0CkfEram4BDg5L3LUfGQm1dSJ/RbAImYWx0XVCskCrhC9pr36C0F/G8l/RBYUZ6pRuqBtMTby30OlYTfYxchwEODCTUCgYB+DG+iaZh8gffE6Qph8MbwcmswGRjvKXb03/EKk1BP2FVkGZ5paVUmf6z+h7s1AyotgBki5hsYUwJVmgQ35GwkPqlkoy8bnv5t/Z9Is/9fQr7nqO/aj5BYNS++hXCzBbULa5TEcphhRfg7mMh6AXsaJ3cp7mz6CZZF/c2bc2rgZQ==-----END PRIVATE KEY-----' + let krsa = new NodeRSA(pem); + krsa.setOptions({ encryptionScheme: 'pkcs1' }); + let decryptdata = krsa.decrypt(str, 'utf8'); + return decryptdata +} + +function serverkeyencrypt(s1,s2) { + let public = `-----BEGIN PUBLIC KEY-----${s1}-----END PUBLIC KEY-----` + let jmrsa = new NodeRSA(public); + jmrsa.setOptions({ encryptionScheme: 'pkcs1' }); + let encryptdata = jmrsa.encrypt(s2,'base64','utf8'); + return encryptdata +} + + +function AesEncrypt(data,key) { + + var cipherChunks = []; + var cipher = crypto.createCipheriv('aes-128-cbc', key, iv); + cipher.setAutoPadding(true); + cipherChunks.push(cipher.update(data, 'utf8', 'base64')); + cipherChunks.push(cipher.final('base64')); + return cipherChunks.join(''); +} + + +function AesDecrypt(data,key){ + + var cipherChunks = []; + var decipher = crypto.createDecipheriv('aes-128-cbc', key, iv); + decipher.setAutoPadding(true); + cipherChunks.push(decipher.update(data, 'base64', 'utf8')); + cipherChunks.push(decipher.final('utf8')); + return cipherChunks.join(''); +} + + +function MD5(str) { + let md5 = crypto.createHash('md5'); + return md5.update(str).digest('hex').toUpperCase(); +}; + + +/** + * 随机数生成 + */ +function randomString(e) { + e = e || 32; + var t = "QWERTYUIOPASDFGHJKLZXCVBNM1234567890", + a = t.length, + n = ""; + for (i = 0; i < e; i++) + n += t.charAt(Math.floor(Math.random() * a)); + return n +} + +/** + * 随机整数生成 + */ +function randomInt(min, max) { + return Math.round(Math.random() * (max - min) + min) +} + +/** + * 获取毫秒时间戳 + */ +function timestampMs(){ + return new Date().getTime(); +} + +/** + * 获取秒时间戳 + */ +function timestampS(){ + return Date.parse(new Date())/1000; +} + + + +/** + * 修改配置文件 + */ +function modify() { + + fs.readFile('/ql/data/config/config.sh','utf8',function(err,dataStr){ + if(err){ + return log('读取文件失败!'+err) + } + else { + var result = dataStr.replace(/regular/g,string); + fs.writeFile('/ql/data/config/config.sh', result, 'utf8', function (err) { + if (err) {return log(err);} + }); + } + }) +} + +function Env(t, e) { "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); class s { constructor(t) { this.env = t } send(t, e = "GET") { t = "string" == typeof t ? { url: t } : t; let s = this.get; return "POST" === e && (s = this.post), new Promise((e, i) => { s.call(this, t, (t, s, r) => { t ? i(t) : e(s) }) }) } get(t) { return this.send.call(this.env, t) } post(t) { return this.send.call(this.env, t, "POST") } } return new class { constructor(t, e) { this.name = t, this.http = new s(this), this.data = null, this.dataFile = "box.dat", this.logs = [], this.isMute = !1, this.isNeedRewrite = !1, this.logSeparator = "\n", this.startTime = (new Date).getTime(), Object.assign(this, e), this.log("", `🔔${this.name}, 开始!`) } isNode() { return "undefined" != typeof module && !!module.exports } isQuanX() { return "undefined" != typeof $task } isSurge() { return "undefined" != typeof $httpClient && "undefined" == typeof $loon } isLoon() { return "undefined" != typeof $loon } toObj(t, e = null) { try { return JSON.parse(t) } catch { return e } } toStr(t, e = null) { try { return JSON.stringify(t) } catch { return e } } getjson(t, e) { let s = e; const i = this.getdata(t); if (i) try { s = JSON.parse(this.getdata(t)) } catch { } return s } setjson(t, e) { try { return this.setdata(JSON.stringify(t), e) } catch { return !1 } } getScript(t) { return new Promise(e => { this.get({ url: t }, (t, s, i) => e(i)) }) } runScript(t, e) { return new Promise(s => { let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); i = i ? i.replace(/\n/g, "").trim() : i; let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; const [o, h] = i.split("@"), n = { url: `http://${h}/v1/scripting/evaluate`, body: { script_text: t, mock_type: "cron", timeout: r }, headers: { "X-Key": o, Accept: "*/*" } }; this.post(n, (t, e, i) => s(i)) }).catch(t => this.logErr(t)) } loaddata() { if (!this.isNode()) return {}; { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e); if (!s && !i) return {}; { const i = s ? t : e; try { return JSON.parse(this.fs.readFileSync(i)) } catch (t) { return {} } } } } writedata() { if (this.isNode()) { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e), r = JSON.stringify(this.data); s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) } } lodash_get(t, e, s) { const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); let r = t; for (const t of i) if (r = Object(r)[t], void 0 === r) return s; return r } lodash_set(t, e, s) { return Object(t) !== t ? t : (Array.isArray(e) || (e = e.toString().match(/[^.[\]]+/g) || []), e.slice(0, -1).reduce((t, s, i) => Object(t[s]) === t[s] ? t[s] : t[s] = Math.abs(e[i + 1]) >> 0 == +e[i + 1] ? [] : {}, t)[e[e.length - 1]] = s, t) } getdata(t) { let e = this.getval(t); if (/^@/.test(t)) { const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : ""; if (r) try { const t = JSON.parse(r); e = t ? this.lodash_get(t, i, "") : e } catch (t) { e = "" } } return e } setdata(t, e) { let s = !1; if (/^@/.test(e)) { const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i), h = i ? "null" === o ? null : o || "{}" : "{}"; try { const e = JSON.parse(h); this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i) } catch (e) { const o = {}; this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i) } } else s = this.setval(t, e); return s } getval(t) { return this.isSurge() || this.isLoon() ? $persistentStore.read(t) : this.isQuanX() ? $prefs.valueForKey(t) : this.isNode() ? (this.data = this.loaddata(), this.data[t]) : this.data && this.data[t] || null } setval(t, e) { return this.isSurge() || this.isLoon() ? $persistentStore.write(t, e) : this.isQuanX() ? $prefs.setValueForKey(t, e) : this.isNode() ? (this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0) : this.data && this.data[e] || null } initGotEnv(t) { this.got = this.got ? this.got : require("got"), this.cktough = this.cktough ? this.cktough : require("tough-cookie"), this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar, t && (t.headers = t.headers ? t.headers : {}, void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar)) } get(t, e = (() => { })) { t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"]), this.isSurge() || this.isLoon() ? (this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.get(t, (t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) })) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { try { if (t.headers["set-cookie"]) { const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar } } catch (t) { this.logErr(t) } }).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => { const { message: s, response: i } = t; e(s, i, i && i.body) })) } post(t, e = (() => { })) { if (t.body && t.headers && !t.headers["Content-Type"] && (t.headers["Content-Type"] = "application/x-www-form-urlencoded"), t.headers && delete t.headers["Content-Length"], this.isSurge() || this.isLoon()) this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.post(t, (t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) }); else if (this.isQuanX()) t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => e(t)); else if (this.isNode()) { this.initGotEnv(t); const { url: s, ...i } = t; this.got.post(s, i).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => { const { message: s, response: i } = t; e(s, i, i && i.body) }) } } time(t, e = null) { const s = e ? new Date(e) : new Date; let i = { "M+": s.getMonth() + 1, "d+": s.getDate(), "H+": s.getHours(), "m+": s.getMinutes(), "s+": s.getSeconds(), "q+": Math.floor((s.getMonth() + 3) / 3), S: s.getMilliseconds() }; /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); for (let e in i) new RegExp("(" + e + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? i[e] : ("00" + i[e]).substr(("" + i[e]).length))); return t } msg(e = t, s = "", i = "", r) { const o = t => { if (!t) return t; if ("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { "open-url": t } : this.isSurge() ? { url: t } : void 0; if ("object" == typeof t) { if (this.isLoon()) { let e = t.openUrl || t.url || t["open-url"], s = t.mediaUrl || t["media-url"]; return { openUrl: e, mediaUrl: s } } if (this.isQuanX()) { let e = t["open-url"] || t.url || t.openUrl, s = t["media-url"] || t.mediaUrl; return { "open-url": e, "media-url": s } } if (this.isSurge()) { let e = t.url || t.openUrl || t["open-url"]; return { url: e } } } }; if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) { let t = ["", "==============📣系统通知📣=============="]; t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) } } log(...t) { t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator)) } logErr(t, e) { const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) } wait(t) { return new Promise(e => setTimeout(e, t)) } done(t = {}) { const e = (new Date).getTime(), s = (e - this.startTime) / 1e3; this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) } }(t, e) } diff --git a/脚本库/web版/账密/叮咚买菜/2022-11-17_ddmc_2d78fbea.js b/脚本库/web版/账密/叮咚买菜/2022-11-17_ddmc_2d78fbea.js new file mode 100644 index 0000000..86149cd --- /dev/null +++ b/脚本库/web版/账密/叮咚买菜/2022-11-17_ddmc_2d78fbea.js @@ -0,0 +1,779 @@ +// # Source: https://github.com/lksky8/sign-ql/blob/main/ddmc.js +// # Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/ddmc.js +// # Repo: lksky8/sign-ql +// # Path: ddmc.js +// # UploadedAt: 2022-11-17T13:54:32Z +// # SHA256: 2d78fbea0d710c7d29ad02178c603c97586bc9a5843ccd9f92cd18d6b8157c80 +// # Category: web版/账密 +// # Evidence: web/H5关键词 + username/password/login +// + +/* + 作者:https://github.com/lksky8/sign-ql/ + 日期:2022-10-7 + 软件:叮咚买菜App + 功能:签到-叮咚鱼塘-叮咚果园 + 抓包:打开叮咚鱼塘 → 选 “天天翻牌” → 开启抓包软件 → 返回到APP开始抽奖 →把 http://farm.api.ddxq.mobi/api/v2/lucky-draw-activity/draw? 填入ddmc变量 + 变量: ddmc='https://farm.api.ddxq.mobi/api/v2/lucky-draw-activity/draw?api_version=9.7.3&app_version=1.0.0&app_client_id=3&station_id=XXXXXXXXX&city_number=XXXX&device_token=XXXXXXXXX&device_id=XXXXXXXXX&latitude=XXXXXXXXX&longitude=XXXXXXXXX&gameId=1&uid=XXXXXXXXX&DDXQSESSID=XXXXXXXXXXXXXXX + 注意:变量最后加上cookie DDXQSESSID= 按照格式填写100%有效;旧版不能使用需要更换新的变量;多个账号用 @ 或者 换行 分割 + 定时一天3次 + 鱼塘饲料瓶大于55会停止喂鱼,以免浪费 + 如果出现无法喂鱼情况在手机APP上完成滑动验证 + <<<<<<完成会获得满49元使用的香蕉券,满59元使用的水产券>>>>>> + + cron: 22 7,10,16 * * * +*/ + +const $ = new Env('叮咚买菜'); +const notify = $.isNode() ? require('./sendNotify') : ''; +const {log} = console; +const Notify = 1; //0为关闭通知,1为打开通知,默认为1 +////////////////////// +let ddmc = process.env.ddmc; +let ddmcArr = []; +let data = ''; +let msg = ''; + +!(async () => { + + if (!(await Envs())) + return; + else { + + + + log(`\n\n============================================= \n脚本执行 - 北京时间(UTC+8):${new Date( + new Date().getTime() + new Date().getTimezoneOffset() * 60 * 1000 + + 8 * 60 * 60 * 1000).toLocaleString()} \n=============================================\n`); + + + log(`\n=================== 共找到 ${ddmcArr.length} 个账号 ===================`) + + for (let index = 0; index < ddmcArr.length; index++) { + + let num = index + 1 + log(`\n========= 开始【第 ${num} 个账号】=========\n`) + + data=JSON.parse(JSON.stringify(getRequest(ddmcArr[index]))); + station_id=data.station_id; + CityId=data.city_number; + uid=data.uid; + latitude=data.latitude; + longitude=data.longitude; + device_token=data.device_token; + device_id=data.device_id; + ddmck=data.DDXQSESSID; + header1 = JSON.parse(`{"Accept":"*/*","Accept-Encoding":"gzip, deflate, br","Host":"farm.api.ddxq.mobi","Connection":"keep-alive","Accept-Language":"zh-cn","Origin":"https://game.m.ddxq.mobi","User-Agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 xzone/9.61.1 station_id/${station_id} device_id/${device_id}","cookie":"DDXQSESSID=${ddmck}"}`) + header2 = JSON.parse(`{"Accept":"*/*","Accept-Encoding":"gzip, deflate, br","Host":"farm.api.ddxq.mobi","Connection":"keep-alive","Accept-Language":"zh-cn","Origin":"https://game.m.ddxq.mobi","User-Agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 xzone/9.61.1 station_id/${station_id} device_id/${device_id}","DDMC-GAME-TID":2,"cookie":"DDXQSESSID=${ddmck}"}`) + + msg += `\n第${num}个账号运行结果:` + await checkid(); + await $.wait(1 * 1000); + log('【APP签到】') + await $.wait(1 * 1000); + await doSign(); + await $.wait(1 * 1000); + log('开始鱼塘任务') + await $.wait(1 * 1000); + log('【鱼塘-连续签到】') + await $.wait(1 * 1000); + await doachieve('CONTINUOUS_SIGN',0);//鱼塘连续签到 + await $.wait(1 * 1000); + log('【鱼塘-每日签到】') + await $.wait(1 * 1000); + await doachieve('DAILY_SIGN',0);//鱼塘每日签到 + await $.wait(1 * 1000); + log('【鱼塘-三餐开福袋】') + await $.wait(1 * 1000); + await doachieve('LOTTERY',0);//三餐开福袋7-9 10-12 16-18 + await $.wait(1 * 1000); + log('【鱼塘-去翻牌一次】') + await $.wait(1 * 1000); + await luckydarw(); + await $.wait(1 * 1000); + log('【鱼塘-浏览商品得饲料】') + await $.wait(1 * 1000); + await doachieve('BROWSE_GOODS',0);//鱼塘 + await $.wait(1 * 1000); + log('【鱼塘-浏览宝妈严选得饲料】') + await $.wait(1 * 1000); + await doachieve('BROWSE_GOODS3',0);//鱼塘 + await $.wait(1 * 1000); + await getasklist();//获取鱼塘任务数据 + await $.wait(1 * 1000); + log('【鱼塘-领饲料瓶】') + await $.wait(1 * 1000); + await rewardtask(slpid,0); + await $.wait(1 * 1000); + log('【鱼塘-参与天天翻牌活动】领取奖励') + await $.wait(1 * 1000); + await rewardtask(fpid,0);//完成翻牌任务,鱼塘 + await $.wait(1 * 1000); + log('【果园-去鱼塘喂食一次】领取任务') + await $.wait(1 * 1000); + await gotofeedfish();//领取果园喂鱼任务 + await $.wait(1 * 1000); + await checkfish(); + await $.wait(2 * 1000); + log('开始喂鱼') + if(nofish == 1){ + log('!!!鱼塘没有鱼了!!!') + }else if(parseInt(pid) < 55 || parseInt(newfish) > 10 ){ + for (i = 0; i < 20; i++) { + await feedfish();//喂鱼 + await $.wait(3 * 1000); + if(parseInt(fish) > 55 || parseInt(sl) < 10 || nofish == 1){ + log('无法喂养,可能饲料不足10g或者饲料瓶已经满了或者没有鱼') + break; + } + } + }else{ + log('无法喂养,可能饲料不足10g或者饲料瓶已经满了或者没有鱼') + } + await $.wait(1 * 1000); + await checkfish2(); + await $.wait(1 * 3000); + log('=============================================') + log('开始果园任务') + log('=============================================') + await $.wait(1 * 1000); + log('【果园-连续签到】') + await $.wait(1 * 1000); + await doachieve('CONTINUOUS_SIGN',1); + await $.wait(1 * 1000); + log('【果园-每日签到】') + await $.wait(1 * 1000); + await doachieve('DAILY_SIGN',1); + await $.wait(1 * 1000); + log('【果园-三餐开福袋】') + await $.wait(1 * 1000); + await doachieve('LOTTERY',1);//三餐开福袋7-9 10-12 16-18 + await $.wait(1 * 1000); + log('【去鱼塘喂食一次】领奖励') + await getasklist2(); + await $.wait(1 * 1000); + await rewardtask(fishid2,1); + log('【果园-浏览商品奖水滴】') + await $.wait(1 * 1000); + await doachieve('BROWSE_GOODS',1) + await $.wait(1 * 1000); + await checkwater(); + await $.wait(2 * 1000); + if(nobanana == 1){ + log('!!!农场没有树了!!!') + }else if(parseInt(newater) > 10){ + for (i = 0; i < 10; i++) { + await water();//浇水 + await $.wait(2 * 1000); + if(parseInt(nowater) < 10){ + log('水滴不足10,停止浇水') + break; + } + } + }else{ + log('果园水滴不足10,停止浇水') + } + await $.wait(1 * 1000); + log('领取【浇水10次送水滴】奖励') + await $.wait(1 * 1000); + await doachieve('FEED_N_TIMES',1) + await $.wait(2 * 1000); + await checkwater2(); + await $.wait(2 * 1000); + + } + await SendMsg(msg); + } + +})() + .catch((e) => log(e)) + .finally(() => $.done()) + + +/** + * APP签到 + */ +function doSign(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://sunquan.api.ddxq.mobi/api/v2/user/signin/`, + headers: { + "cookie":`DDXQSESSID=${ddmck}` + }, + body: `api_version=9.7.3&app_version=1.0.0&app_client_id=3&station_id=${station_id}&native_version=9.35.1&city_number=${CityId}&latitude=${latitude}&longitude=${longitude}`, + } + + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.msg == '请求成功' && result.success == true) { + log(`签到成功,获得:${result.data.point}积分,已经签到了${result.data.sign_series}天`) + //msg += `\n签到成功,获得:${result.data.point}积分,已经签到了${result.data.sign_series}天` + } else { + log(`签到失败,原因是:${result.message}`) + msg += '\n签到失败,可能是cookies失效' + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} +/** + * 获取鱼塘任务数据 + */ +function getasklist(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://farm.api.ddxq.mobi/api/v2/task/list?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&app_version=9.58.0&OSVersion=10&CityId=${CityId}&uid=${uid}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng=${longitude}&device_token=${device_token}&gameId=1&cityCode=${CityId}`, + headers: header1, + } + + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + var siliaoping = data.indexOf("HARD_BOX") != -1 + if (result.msg == '请求成功' && result.success == true) { + log('农场-获取任务数据成功') + var tasklist = result.data.userTasks + let fp = tasklist.find(item => item['taskName']==='参与天天翻牌活动') + fpid = fp['userTaskLogId'] + if(siliaoping == true){ + let slp = tasklist.find(item => item['taskCode']==='HARD_BOX') + slpid = slp['userTaskLogId'] + pid= slp.targetRewardRangesVos[0].rewardRanges[0].amountDesc + }else{ + slpid = 0 + pid = 0 + } + + + } else { + log(`获取任务数据失败,可能是cookies失效`) + msg += '\n获取任务数据失败,可能是cookies失效' + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} +//果园 +function getasklist2(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `https://farm.api.ddxq.mobi/api/v2/task/list-orchard?api_version=9.1.0&app_client_id=1&station_id=${station_id}&stationId=${station_id}&native_version=&CityId=${CityId}&OSVersion=14&uid=${uid}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng=${longitude}&device_token=${device_token}&reward=FEED&cityCode=${CityId}`, + headers: header2, + } + + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.msg == '请求成功' && result.success == true) { + log('果园-获取任务数据成功') + let tasklist = result.data.userTasks + let hesuan = tasklist.find(item => item['taskName']==='去鱼塘喂食1次') + fishid2 = hesuan['userTaskLogId'] + } else { + log(`获取任务数据失败,可能是cookies失效`) + msg += '\n获取任务数据失败,可能是cookies失效' + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +/** + * 鱼塘任务 + */ +function doachieve(taskCode,code,timeout = 3 * 1000) { + return new Promise((resolve) => { + if(code == 0){ + ddmcheader=header1 + ddmcurl = `https://farm.api.ddxq.mobi/api/v2/task/achieve?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&app_version=9.58.0&OSVersion=10&CityId=${CityId}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng${latitude}&device_token=${device_token}&gameId=1&taskCode=${taskCode}` + }else{ + ddmcheader=header2 + ddmcurl =`https://farm.api.ddxq.mobi/api/v2/task/achieve?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&app_version=9.58.0&OSVersion=10&CityId=${CityId}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng${latitude}&device_token=${device_token}&taskCode=${taskCode}` + } + let url = { + url: ddmcurl, + headers: ddmcheader, + } + + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (taskCode == 'CONTINUOUS_SIGN' && code == 0 && result.success == true) { + log(`任务完成,获得:${result.data.rewards[0].amount}g饲料`) + } else if(taskCode == 'DAILY_SIGN' && code == 0 && result.success == true) { + log(`任务完成,获得:${result.data.rewards[0].amount}g饲料`) + } else if(taskCode == 'CONTINUOUS_SIGN' && code == 1 && result.success == true) { + log(`任务完成,获得:${result.data.rewards[0].amount}水滴`) + } else if(taskCode == 'DAILY_SIGN' && code == 1 && result.success == true) { + log(`任务完成,获得:${result.data.rewards[0].amount}水滴`) + } else if(result.msg == '今日已完成任务,明日再来吧!') { + log(`任务已完成`) + } else if(result.msg == '你已完成任务,去看看其他任务吧~') { + log(`任务已完成`) + } else if(taskCode == 'LOTTERY' && result.msg == '任务尚未开启,请耐心等待~') { + log('还没到领取时间,请在7-9;10-12;16-18这三个时间段内操作') + } else if(taskCode == 'LOTTERY' && code == 0 && result.success == true) { + log(`任务完成,获得:${result.data.rewards[0].amount}g饲料`) + } else if(taskCode == 'LOTTERY' && code == 1 && result.success == true) { + log(`任务完成,获得:${result.data.rewards[0].amount}水滴`) + } else if(taskCode == 'BROWSE_GOODS' && code == 0 && result.success == true) { + rewardtask(result.data.userTaskLogId,0); + } else if(taskCode == 'BROWSE_GOODS' && code == 1 && result.success == true) { + rewardtask(result.data.userTaskLogId,1); + } else if(taskCode == 'BROWSE_GOODS3' && code == 0 && result.success == true) { + rewardtask(result.data.userTaskLogId,0); + } else if(taskCode == 'FEED_N_TIMES' && result.success == true) { + log(`任务完成,获得:${result.data.rewards[0].amount}水滴`) + } else if(taskCode == 'FEED_N_TIMES' && result.msg == '浇水次数不满足') { + log('浇水不满10次,无法完成任务') + } else if(result.msg == '此任务不可手动完成') { + log('任务需要手动操作') + } else{ + log(`获取任务数据失败,可能是cookies失效`) + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} +function luckydarw(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://farm.api.ddxq.mobi/api/v2/lucky-draw-activity/draw?api_version=9.7.3&app_version=1.0.0&app_client_id=3&station_id=${station_id}&native_version=9.58.0&city_number=${CityId}&device_token=${device_token}&device_id=${device_id}&latitude=${latitude}&longitude=${longitude}&gameId=1&uid=${uid}`, + headers: header1, + } + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.msg == '请求成功' && result.success == true) { + log(`已翻牌并获得:${result.data.chosen.amount}饲料`) + } else { + log('饲料不足,翻牌失败') + msg += '\n饲料不足,翻牌失败' + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +function rewardtask(taskid,code,timeout = 3 * 1000) { + return new Promise((resolve) => { + if(code == 0){ + ddmcheader1=header1 + ddmcurl1 = `http://farm.api.ddxq.mobi/api/v2/task/reward?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&app_version=9.58.0&OSVersion=10&CityId=${CityId}&uid=${uid}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng=${longitude}&device_token=${device_token}&gameId=1&userTaskLogId=${taskid}` + }else{ + ddmcheader1=header2 + ddmcurl1 = `http://farm.api.ddxq.mobi/api/v2/task/reward?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&app_version=9.58.0&OSVersion=10&CityId=${CityId}&uid=${uid}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng=${longitude}&device_token=${device_token}&userTaskLogId=${taskid}` + } + let url = { + url: ddmcurl1, + headers: ddmcheader1, + } + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if(taskid == 0){ + log('暂时没有饲料瓶入口') + }else if (result.msg == '请求成功' && result.success == true) { + log(`任务完成,获得:${result.data.rewards[0].amount}饲料`) + } else if(result.msg == '你已领取奖励,去领其他奖励吧~') { + log('已经领取过该奖励') + } else if(result.msg == '不可领取') { + log('已经领取过该奖励') + } else if(result.msg == '参数无效') { + log('任务不存在或者已完成') + } else { + log('任务失败,可能是cookies失效') + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +function gotofeedfish(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://farm.api.ddxq.mobi/api/v2/task/receive?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&CityId=${CityId}&OSVersion=10&uid=${uid}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng=${longitude}&device_token=&gameId=2&taskCode=FEED_CRAP`, + headers: header2, + } + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.msg == '请求成功' && result.success == true) { + log(`【去鱼塘喂食一次】领取任务成功,等待喂鱼`) + } else if(result.msg == '该任务已经完成了哦'){ + log('【去鱼塘喂食一次】任务已完成') + }else{ + log('【去鱼塘喂食一次】任务失败,可能是cookies失效') + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +function feedfish(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://farm.api.ddxq.mobi/api/v2/props/feed?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&app_version=9.58.0&OSVersion=10&CityId=${CityId}&uid=${uid}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng=${longitude}&device_token=${device_token}&gameId=1&propsId=${fishpropsId}&seedId=${fishseedId}&cityCode=${CityId}&feedPro=0&triggerMultiFeed=1`, + headers: { + "Host": "farm.api.ddxq.mobi", + "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/89.0.4389.72 MQQBrowser/6.2 TBS/045947 Mobile Safari/537.36 xzone/9.58.0 station_id/60dd252dbd8d8c0001eca0e0 OpenTime/"+timestampMs(), + "accept": "*/*", + "origin": "https://game.m.ddxq.mobi", + "x-requested-with": "com.yaya.zone", + "sec-fetch-site": "same-site", + "sec-fetch-mode": "cors", + "sec-fetch-dest": "empty", + "referer": "https://game.m.ddxq.mobi/", + "accept-encoding": "gzip, deflate, br", + "accept-language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7", + "cookie": `DDXQSESSID=${ddmck}` + }, + } + + $.get(url, async (error, response, data) => { + try { + if(error){//406 Not Acceptable + log ('Api请求失败,请登陆APP完成滑动验证') + msg +='\n请登陆APP完成滑动验证完成喂鱼操作' + fish='0' + sl='0' + }else{ + let result = JSON.parse(data); + if (result.success == true && result.data.hardBoxRewardAmountAfterFeed == null) { + log(`喂鱼成功,剩余${result.data.feed.amount}g饲料,${result.data.seed.msg}`) + fish=result.data.hardBoxRewardAmountAfterFeed + sl=result.data.feed.amount + }else if(result.success == true && result.data.hardBoxRewardAmountAfterFeed != null){ + log(`喂鱼成功,剩余${result.data.feed.amount}g饲料,已存储${result.data.hardBoxRewardAmountAfterFeed}g饲料,${result.data.seed.msg}`) + fish=result.data.hardBoxRewardAmountAfterFeed + sl=result.data.feed.amount + } else if(result.msg == '饲料不足10g,请完成任务领饲料~' || result.msg == '今天喂食太多了,休息一下明天再来吧'){ + log('喂鱼失败,饲料不足10g或者达到喂鱼上限') + fish='0' + sl='0' + }else{ + log('喂鱼任务失败,可能是cookies失效') + } + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +function water(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://farm.api.ddxq.mobi/api/v2/props/feed?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&CityId=${CityId}&OSVersion=10&uid=${uid}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng=${longitude}&device_token=${device_token}&propsCode=FEED&seedId=${waterseedId}&propsId=${waterpropsId}`, + headers: header2, + } + + $.get(url, async (error, response, data) => { + try { + if(error){ + log ('Api请求失败,请登陆APP完成滑动验证') + msg +='\n请登陆APP完成滑动验证' + nowater='0' + }else{ + let result = JSON.parse(data); + if (result.msg == '请求成功' && result.success == true) { + nowater=result.data.feed.amount + gyfl = result.data.fertilizerUse.amount + log(`浇水成功,剩余${nowater}水滴,当前肥力:${gyfl},${result.data.msg}`) + if(gyfl < 10){ + log('肥力不足,自动施肥') + await userfeiliao(); + } + } else { + log('浇水失败,可能是水滴不足或者cookies失效') + msg += '\n浇水失败,可能是水滴不足或者cookies失效' + } + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +function userfeiliao(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `https://farm.api.ddxq.mobi/api/v2/props/props-use?api_version=9.1.0&app_client_id=1&station_id=${station_id}&stationId=${station_id}&native_version=&CityId=${CityId}&OSVersion=14&uid=${uid}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng=${longitude}&device_token=${device_token}&propsCode=FERTILIZER&propsId=220910108081811250&seedId=220910108081800250`, + headers: header2, + } + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.msg == '请求成功' && result.success == true) { + log(`施肥成功,剩余${result.data.propsUse.amount}肥料,当前可用肥料:${result.data.propsUseResultVo.amount}`) + } else { + log('肥料不足,施肥失败') + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +function checkwater(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://farm.api.ddxq.mobi/api/v2/userguide/orchard/detail?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&CityId=${CityId}&OSVersion=10&uid=${uid}&latitude=${latitude}&longitude=${longitude}lat=${latitude}&lng=${longitude}&device_token=${device_token}&gameId=2&cityCode=${CityId}`, + headers: header2, + } + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if(data.indexOf("seedId")<0){ + nobanana = 1 + newater=result.data.feed.amount + waterpropsId = result.data.feed.propsId + waterseedId = 0 + log('农场没有香蕉可以种,检查是否已经获得奖励') + msg +='\n农场没有香蕉可以种,检查是否已经获得奖励' + }else if (result.msg == '请求成功' && result.success == true) { + nobanana = 0 + newater=result.data.feed.amount + waterpropsId = result.data.feed.propsId + waterseedId = result.data.baseSeed.seedId + log(`目前果园水滴:${newater}`) + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +function checkwater2(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://farm.api.ddxq.mobi/api/v2/userguide/orchard/detail?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&CityId=${CityId}&OSVersion=10&uid=${uid}&latitude=${latitude}&longitude=${longitude}lat=${latitude}&lng=${longitude}&device_token=${device_token}&gameId=2&cityCode=${CityId}`, + headers: header2, + } + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if(data.indexOf("seedId")<0){ + log('农场没有香蕉可以种,检查是否已经获得奖励') + }else if (result.msg == '请求成功' && result.success == true) { + msg+= `\n【果园】${result.data.baseSeed.msg}` + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +function checkfish(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://farm.api.ddxq.mobi/api/v2/userguide/detail?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&app_version=9.58.0&OSVersion=10&CityId=${CityId}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng=${longitude}&device_token=${device_token}&gameId=1&guideCode=FISHPOND_NEW`, + headers: header1, + } + + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if(data.indexOf("seedId")<0){ + nofish = 1 + newfish=result.data.feed.amount + fishpropsId = result.data.feed.propsId + fishseedId = 0 + fish = 0 + log('鱼塘没有鱼可以喂,检查是否已经获得奖励') + msg +='\n鱼塘没有鱼可以喂,检查是否已经获得奖励' + }else if (result.msg == '请求成功' && result.success == true) { + nofish = 0 + newfish=result.data.feed.amount + fishpropsId = result.data.feed.propsId + fishseedId = result.data.baseSeed.seedId + log(`目前鱼饲料:${newfish}g`) + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +function checkfish2(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://farm.api.ddxq.mobi/api/v2/userguide/detail?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&app_version=9.58.0&OSVersion=10&CityId=${CityId}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng=${longitude}&device_token=${device_token}&gameId=1&guideCode=FISHPOND_NEW`, + headers: header1, + } + + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if(data.indexOf("seedId")<0){ + log('鱼塘没有鱼可以喂,检查是否已经获得奖励') + }else if (result.msg == '请求成功' && result.success == true) { + msg+= `\n【鱼塘】${result.data.baseSeed.msg}` + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +function checkid(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://farm.api.ddxq.mobi/api/v2/friend/list?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&CityId=${CityId}&OSVersion=10&uid=${uid}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng=${longitude}&device_token=${device_token}&gameId=1`, + headers: header1, + } + + $.get(url, async (error, response, data) => { + try { + + let result = JSON.parse(data); + if(result.msg == '您的访问已过期,请重新登录app~' && result.code == 111){ + log('cookie失效了!!!cookie失效了!!!cookie失效了!!!cookie失效了!!!') + msg+='cookie失效了!!!cookie失效了!!!cookie失效了!!!cookie失效了!!!' + + }else if(result.msg == '您的访问已过期,请重新登录' && result.code == 1111){ + log('cookie失效了!!!cookie失效了!!!cookie失效了!!!cookie失效了!!!') + msg+='cookie失效了!!!cookie失效了!!!cookie失效了!!!cookie失效了!!!' + + }else{ + nname=result.data.me.nickName + log(`【账号】${nname}|登录成功,cookie有效`) + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} +// ============================================变量检查============================================ \\ +async function Envs() { + if (ddmc) { + if (ddmc.indexOf("@") != -1) { + ddmc.split("@").forEach((item) => { + ddmcArr.push(item); + }); + } else if (ddmc.indexOf("\n") != -1) { + ddmc.split("\n").forEach((item) => { + ddmcArr.push(item); + }); + } else { + ddmcArr.push(ddmc); + } + } else { + log(`\n 【${$.name}】:未填写变量 ddmc`) + return; + } + return true; +} +// ============================================发送消息============================================ \\ +async function SendMsg(message) { + if (!message) + return; + + if (Notify > 0) { + if ($.isNode()) { + var notify = require('./sendNotify'); + await notify.sendNotify($.name, message); + } else { + $.msg(message); + } + } else { + log(message); + } +} + +function getRequest(url) { + var theRequest = new Object(); + if (url.indexOf("?") != -1) { + var str = url.substr(1); + strs = str.split("&"); + for(var i = 0; i < strs.length; i ++) { + theRequest[strs[i].split("=")[0]]=unescape(strs[i].split("=")[1]); + } + } + return theRequest; +} + + function timestampMs(){ + return new Date().getTime(); + } + +/** + * 修改配置文件 + */ +function modify() { + + fs.readFile('/ql/data/config/config.sh','utf8',function(err,dataStr){ + if(err){ + return log('读取文件失败!'+err) + } + else { + var result = dataStr.replace(/regular/g,string); + fs.writeFile('/ql/data/config/config.sh', result, 'utf8', function (err) { + if (err) {return log(err);} + }); + } + }) +} + +function Env(t, e) { "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); class s { constructor(t) { this.env = t } send(t, e = "GET") { t = "string" == typeof t ? { url: t } : t; let s = this.get; return "POST" === e && (s = this.post), new Promise((e, i) => { s.call(this, t, (t, s, r) => { t ? i(t) : e(s) }) }) } get(t) { return this.send.call(this.env, t) } post(t) { return this.send.call(this.env, t, "POST") } } return new class { constructor(t, e) { this.name = t, this.http = new s(this), this.data = null, this.dataFile = "box.dat", this.logs = [], this.isMute = !1, this.isNeedRewrite = !1, this.logSeparator = "\n", this.startTime = (new Date).getTime(), Object.assign(this, e), this.log("", `🔔${this.name}, 开始!`) } isNode() { return "undefined" != typeof module && !!module.exports } isQuanX() { return "undefined" != typeof $task } isSurge() { return "undefined" != typeof $httpClient && "undefined" == typeof $loon } isLoon() { return "undefined" != typeof $loon } toObj(t, e = null) { try { return JSON.parse(t) } catch { return e } } toStr(t, e = null) { try { return JSON.stringify(t) } catch { return e } } getjson(t, e) { let s = e; const i = this.getdata(t); if (i) try { s = JSON.parse(this.getdata(t)) } catch { } return s } setjson(t, e) { try { return this.setdata(JSON.stringify(t), e) } catch { return !1 } } getScript(t) { return new Promise(e => { this.get({ url: t }, (t, s, i) => e(i)) }) } runScript(t, e) { return new Promise(s => { let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); i = i ? i.replace(/\n/g, "").trim() : i; let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; const [o, h] = i.split("@"), n = { url: `http://${h}/v1/scripting/evaluate`, body: { script_text: t, mock_type: "cron", timeout: r }, headers: { "X-Key": o, Accept: "*/*" } }; this.post(n, (t, e, i) => s(i)) }).catch(t => this.logErr(t)) } loaddata() { if (!this.isNode()) return {}; { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e); if (!s && !i) return {}; { const i = s ? t : e; try { return JSON.parse(this.fs.readFileSync(i)) } catch (t) { return {} } } } } writedata() { if (this.isNode()) { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e), r = JSON.stringify(this.data); s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) } } lodash_get(t, e, s) { const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); let r = t; for (const t of i) if (r = Object(r)[t], void 0 === r) return s; return r } lodash_set(t, e, s) { return Object(t) !== t ? t : (Array.isArray(e) || (e = e.toString().match(/[^.[\]]+/g) || []), e.slice(0, -1).reduce((t, s, i) => Object(t[s]) === t[s] ? t[s] : t[s] = Math.abs(e[i + 1]) >> 0 == +e[i + 1] ? [] : {}, t)[e[e.length - 1]] = s, t) } getdata(t) { let e = this.getval(t); if (/^@/.test(t)) { const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : ""; if (r) try { const t = JSON.parse(r); e = t ? this.lodash_get(t, i, "") : e } catch (t) { e = "" } } return e } setdata(t, e) { let s = !1; if (/^@/.test(e)) { const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i), h = i ? "null" === o ? null : o || "{}" : "{}"; try { const e = JSON.parse(h); this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i) } catch (e) { const o = {}; this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i) } } else s = this.setval(t, e); return s } getval(t) { return this.isSurge() || this.isLoon() ? $persistentStore.read(t) : this.isQuanX() ? $prefs.valueForKey(t) : this.isNode() ? (this.data = this.loaddata(), this.data[t]) : this.data && this.data[t] || null } setval(t, e) { return this.isSurge() || this.isLoon() ? $persistentStore.write(t, e) : this.isQuanX() ? $prefs.setValueForKey(t, e) : this.isNode() ? (this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0) : this.data && this.data[e] || null } initGotEnv(t) { this.got = this.got ? this.got : require("got"), this.cktough = this.cktough ? this.cktough : require("tough-cookie"), this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar, t && (t.headers = t.headers ? t.headers : {}, void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar)) } get(t, e = (() => { })) { t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"]), this.isSurge() || this.isLoon() ? (this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.get(t, (t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) })) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { try { if (t.headers["set-cookie"]) { const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar } } catch (t) { this.logErr(t) } }).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => { const { message: s, response: i } = t; e(s, i, i && i.body) })) } post(t, e = (() => { })) { if (t.body && t.headers && !t.headers["Content-Type"] && (t.headers["Content-Type"] = "application/x-www-form-urlencoded"), t.headers && delete t.headers["Content-Length"], this.isSurge() || this.isLoon()) this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.post(t, (t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) }); else if (this.isQuanX()) t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => e(t)); else if (this.isNode()) { this.initGotEnv(t); const { url: s, ...i } = t; this.got.post(s, i).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => { const { message: s, response: i } = t; e(s, i, i && i.body) }) } } time(t, e = null) { const s = e ? new Date(e) : new Date; let i = { "M+": s.getMonth() + 1, "d+": s.getDate(), "H+": s.getHours(), "m+": s.getMinutes(), "s+": s.getSeconds(), "q+": Math.floor((s.getMonth() + 3) / 3), S: s.getMilliseconds() }; /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); for (let e in i) new RegExp("(" + e + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? i[e] : ("00" + i[e]).substr(("" + i[e]).length))); return t } msg(e = t, s = "", i = "", r) { const o = t => { if (!t) return t; if ("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { "open-url": t } : this.isSurge() ? { url: t } : void 0; if ("object" == typeof t) { if (this.isLoon()) { let e = t.openUrl || t.url || t["open-url"], s = t.mediaUrl || t["media-url"]; return { openUrl: e, mediaUrl: s } } if (this.isQuanX()) { let e = t["open-url"] || t.url || t.openUrl, s = t["media-url"] || t.mediaUrl; return { "open-url": e, "media-url": s } } if (this.isSurge()) { let e = t.url || t.openUrl || t["open-url"]; return { url: e } } } }; if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) { let t = ["", "==============📣系统通知📣=============="]; t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) } } log(...t) { t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator)) } logErr(t, e) { const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) } wait(t) { return new Promise(e => setTimeout(e, t)) } done(t = {}) { const e = (new Date).getTime(), s = (e - this.startTime) / 1e3; this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) } }(t, e) } diff --git a/脚本库/web版/账密/叮咚买菜/2022-11-17_ddmc_2d78fbea_2.js b/脚本库/web版/账密/叮咚买菜/2022-11-17_ddmc_2d78fbea_2.js new file mode 100644 index 0000000..86149cd --- /dev/null +++ b/脚本库/web版/账密/叮咚买菜/2022-11-17_ddmc_2d78fbea_2.js @@ -0,0 +1,779 @@ +// # Source: https://github.com/lksky8/sign-ql/blob/main/ddmc.js +// # Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/ddmc.js +// # Repo: lksky8/sign-ql +// # Path: ddmc.js +// # UploadedAt: 2022-11-17T13:54:32Z +// # SHA256: 2d78fbea0d710c7d29ad02178c603c97586bc9a5843ccd9f92cd18d6b8157c80 +// # Category: web版/账密 +// # Evidence: web/H5关键词 + username/password/login +// + +/* + 作者:https://github.com/lksky8/sign-ql/ + 日期:2022-10-7 + 软件:叮咚买菜App + 功能:签到-叮咚鱼塘-叮咚果园 + 抓包:打开叮咚鱼塘 → 选 “天天翻牌” → 开启抓包软件 → 返回到APP开始抽奖 →把 http://farm.api.ddxq.mobi/api/v2/lucky-draw-activity/draw? 填入ddmc变量 + 变量: ddmc='https://farm.api.ddxq.mobi/api/v2/lucky-draw-activity/draw?api_version=9.7.3&app_version=1.0.0&app_client_id=3&station_id=XXXXXXXXX&city_number=XXXX&device_token=XXXXXXXXX&device_id=XXXXXXXXX&latitude=XXXXXXXXX&longitude=XXXXXXXXX&gameId=1&uid=XXXXXXXXX&DDXQSESSID=XXXXXXXXXXXXXXX + 注意:变量最后加上cookie DDXQSESSID= 按照格式填写100%有效;旧版不能使用需要更换新的变量;多个账号用 @ 或者 换行 分割 + 定时一天3次 + 鱼塘饲料瓶大于55会停止喂鱼,以免浪费 + 如果出现无法喂鱼情况在手机APP上完成滑动验证 + <<<<<<完成会获得满49元使用的香蕉券,满59元使用的水产券>>>>>> + + cron: 22 7,10,16 * * * +*/ + +const $ = new Env('叮咚买菜'); +const notify = $.isNode() ? require('./sendNotify') : ''; +const {log} = console; +const Notify = 1; //0为关闭通知,1为打开通知,默认为1 +////////////////////// +let ddmc = process.env.ddmc; +let ddmcArr = []; +let data = ''; +let msg = ''; + +!(async () => { + + if (!(await Envs())) + return; + else { + + + + log(`\n\n============================================= \n脚本执行 - 北京时间(UTC+8):${new Date( + new Date().getTime() + new Date().getTimezoneOffset() * 60 * 1000 + + 8 * 60 * 60 * 1000).toLocaleString()} \n=============================================\n`); + + + log(`\n=================== 共找到 ${ddmcArr.length} 个账号 ===================`) + + for (let index = 0; index < ddmcArr.length; index++) { + + let num = index + 1 + log(`\n========= 开始【第 ${num} 个账号】=========\n`) + + data=JSON.parse(JSON.stringify(getRequest(ddmcArr[index]))); + station_id=data.station_id; + CityId=data.city_number; + uid=data.uid; + latitude=data.latitude; + longitude=data.longitude; + device_token=data.device_token; + device_id=data.device_id; + ddmck=data.DDXQSESSID; + header1 = JSON.parse(`{"Accept":"*/*","Accept-Encoding":"gzip, deflate, br","Host":"farm.api.ddxq.mobi","Connection":"keep-alive","Accept-Language":"zh-cn","Origin":"https://game.m.ddxq.mobi","User-Agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 xzone/9.61.1 station_id/${station_id} device_id/${device_id}","cookie":"DDXQSESSID=${ddmck}"}`) + header2 = JSON.parse(`{"Accept":"*/*","Accept-Encoding":"gzip, deflate, br","Host":"farm.api.ddxq.mobi","Connection":"keep-alive","Accept-Language":"zh-cn","Origin":"https://game.m.ddxq.mobi","User-Agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 xzone/9.61.1 station_id/${station_id} device_id/${device_id}","DDMC-GAME-TID":2,"cookie":"DDXQSESSID=${ddmck}"}`) + + msg += `\n第${num}个账号运行结果:` + await checkid(); + await $.wait(1 * 1000); + log('【APP签到】') + await $.wait(1 * 1000); + await doSign(); + await $.wait(1 * 1000); + log('开始鱼塘任务') + await $.wait(1 * 1000); + log('【鱼塘-连续签到】') + await $.wait(1 * 1000); + await doachieve('CONTINUOUS_SIGN',0);//鱼塘连续签到 + await $.wait(1 * 1000); + log('【鱼塘-每日签到】') + await $.wait(1 * 1000); + await doachieve('DAILY_SIGN',0);//鱼塘每日签到 + await $.wait(1 * 1000); + log('【鱼塘-三餐开福袋】') + await $.wait(1 * 1000); + await doachieve('LOTTERY',0);//三餐开福袋7-9 10-12 16-18 + await $.wait(1 * 1000); + log('【鱼塘-去翻牌一次】') + await $.wait(1 * 1000); + await luckydarw(); + await $.wait(1 * 1000); + log('【鱼塘-浏览商品得饲料】') + await $.wait(1 * 1000); + await doachieve('BROWSE_GOODS',0);//鱼塘 + await $.wait(1 * 1000); + log('【鱼塘-浏览宝妈严选得饲料】') + await $.wait(1 * 1000); + await doachieve('BROWSE_GOODS3',0);//鱼塘 + await $.wait(1 * 1000); + await getasklist();//获取鱼塘任务数据 + await $.wait(1 * 1000); + log('【鱼塘-领饲料瓶】') + await $.wait(1 * 1000); + await rewardtask(slpid,0); + await $.wait(1 * 1000); + log('【鱼塘-参与天天翻牌活动】领取奖励') + await $.wait(1 * 1000); + await rewardtask(fpid,0);//完成翻牌任务,鱼塘 + await $.wait(1 * 1000); + log('【果园-去鱼塘喂食一次】领取任务') + await $.wait(1 * 1000); + await gotofeedfish();//领取果园喂鱼任务 + await $.wait(1 * 1000); + await checkfish(); + await $.wait(2 * 1000); + log('开始喂鱼') + if(nofish == 1){ + log('!!!鱼塘没有鱼了!!!') + }else if(parseInt(pid) < 55 || parseInt(newfish) > 10 ){ + for (i = 0; i < 20; i++) { + await feedfish();//喂鱼 + await $.wait(3 * 1000); + if(parseInt(fish) > 55 || parseInt(sl) < 10 || nofish == 1){ + log('无法喂养,可能饲料不足10g或者饲料瓶已经满了或者没有鱼') + break; + } + } + }else{ + log('无法喂养,可能饲料不足10g或者饲料瓶已经满了或者没有鱼') + } + await $.wait(1 * 1000); + await checkfish2(); + await $.wait(1 * 3000); + log('=============================================') + log('开始果园任务') + log('=============================================') + await $.wait(1 * 1000); + log('【果园-连续签到】') + await $.wait(1 * 1000); + await doachieve('CONTINUOUS_SIGN',1); + await $.wait(1 * 1000); + log('【果园-每日签到】') + await $.wait(1 * 1000); + await doachieve('DAILY_SIGN',1); + await $.wait(1 * 1000); + log('【果园-三餐开福袋】') + await $.wait(1 * 1000); + await doachieve('LOTTERY',1);//三餐开福袋7-9 10-12 16-18 + await $.wait(1 * 1000); + log('【去鱼塘喂食一次】领奖励') + await getasklist2(); + await $.wait(1 * 1000); + await rewardtask(fishid2,1); + log('【果园-浏览商品奖水滴】') + await $.wait(1 * 1000); + await doachieve('BROWSE_GOODS',1) + await $.wait(1 * 1000); + await checkwater(); + await $.wait(2 * 1000); + if(nobanana == 1){ + log('!!!农场没有树了!!!') + }else if(parseInt(newater) > 10){ + for (i = 0; i < 10; i++) { + await water();//浇水 + await $.wait(2 * 1000); + if(parseInt(nowater) < 10){ + log('水滴不足10,停止浇水') + break; + } + } + }else{ + log('果园水滴不足10,停止浇水') + } + await $.wait(1 * 1000); + log('领取【浇水10次送水滴】奖励') + await $.wait(1 * 1000); + await doachieve('FEED_N_TIMES',1) + await $.wait(2 * 1000); + await checkwater2(); + await $.wait(2 * 1000); + + } + await SendMsg(msg); + } + +})() + .catch((e) => log(e)) + .finally(() => $.done()) + + +/** + * APP签到 + */ +function doSign(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://sunquan.api.ddxq.mobi/api/v2/user/signin/`, + headers: { + "cookie":`DDXQSESSID=${ddmck}` + }, + body: `api_version=9.7.3&app_version=1.0.0&app_client_id=3&station_id=${station_id}&native_version=9.35.1&city_number=${CityId}&latitude=${latitude}&longitude=${longitude}`, + } + + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.msg == '请求成功' && result.success == true) { + log(`签到成功,获得:${result.data.point}积分,已经签到了${result.data.sign_series}天`) + //msg += `\n签到成功,获得:${result.data.point}积分,已经签到了${result.data.sign_series}天` + } else { + log(`签到失败,原因是:${result.message}`) + msg += '\n签到失败,可能是cookies失效' + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} +/** + * 获取鱼塘任务数据 + */ +function getasklist(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://farm.api.ddxq.mobi/api/v2/task/list?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&app_version=9.58.0&OSVersion=10&CityId=${CityId}&uid=${uid}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng=${longitude}&device_token=${device_token}&gameId=1&cityCode=${CityId}`, + headers: header1, + } + + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + var siliaoping = data.indexOf("HARD_BOX") != -1 + if (result.msg == '请求成功' && result.success == true) { + log('农场-获取任务数据成功') + var tasklist = result.data.userTasks + let fp = tasklist.find(item => item['taskName']==='参与天天翻牌活动') + fpid = fp['userTaskLogId'] + if(siliaoping == true){ + let slp = tasklist.find(item => item['taskCode']==='HARD_BOX') + slpid = slp['userTaskLogId'] + pid= slp.targetRewardRangesVos[0].rewardRanges[0].amountDesc + }else{ + slpid = 0 + pid = 0 + } + + + } else { + log(`获取任务数据失败,可能是cookies失效`) + msg += '\n获取任务数据失败,可能是cookies失效' + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} +//果园 +function getasklist2(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `https://farm.api.ddxq.mobi/api/v2/task/list-orchard?api_version=9.1.0&app_client_id=1&station_id=${station_id}&stationId=${station_id}&native_version=&CityId=${CityId}&OSVersion=14&uid=${uid}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng=${longitude}&device_token=${device_token}&reward=FEED&cityCode=${CityId}`, + headers: header2, + } + + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.msg == '请求成功' && result.success == true) { + log('果园-获取任务数据成功') + let tasklist = result.data.userTasks + let hesuan = tasklist.find(item => item['taskName']==='去鱼塘喂食1次') + fishid2 = hesuan['userTaskLogId'] + } else { + log(`获取任务数据失败,可能是cookies失效`) + msg += '\n获取任务数据失败,可能是cookies失效' + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +/** + * 鱼塘任务 + */ +function doachieve(taskCode,code,timeout = 3 * 1000) { + return new Promise((resolve) => { + if(code == 0){ + ddmcheader=header1 + ddmcurl = `https://farm.api.ddxq.mobi/api/v2/task/achieve?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&app_version=9.58.0&OSVersion=10&CityId=${CityId}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng${latitude}&device_token=${device_token}&gameId=1&taskCode=${taskCode}` + }else{ + ddmcheader=header2 + ddmcurl =`https://farm.api.ddxq.mobi/api/v2/task/achieve?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&app_version=9.58.0&OSVersion=10&CityId=${CityId}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng${latitude}&device_token=${device_token}&taskCode=${taskCode}` + } + let url = { + url: ddmcurl, + headers: ddmcheader, + } + + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (taskCode == 'CONTINUOUS_SIGN' && code == 0 && result.success == true) { + log(`任务完成,获得:${result.data.rewards[0].amount}g饲料`) + } else if(taskCode == 'DAILY_SIGN' && code == 0 && result.success == true) { + log(`任务完成,获得:${result.data.rewards[0].amount}g饲料`) + } else if(taskCode == 'CONTINUOUS_SIGN' && code == 1 && result.success == true) { + log(`任务完成,获得:${result.data.rewards[0].amount}水滴`) + } else if(taskCode == 'DAILY_SIGN' && code == 1 && result.success == true) { + log(`任务完成,获得:${result.data.rewards[0].amount}水滴`) + } else if(result.msg == '今日已完成任务,明日再来吧!') { + log(`任务已完成`) + } else if(result.msg == '你已完成任务,去看看其他任务吧~') { + log(`任务已完成`) + } else if(taskCode == 'LOTTERY' && result.msg == '任务尚未开启,请耐心等待~') { + log('还没到领取时间,请在7-9;10-12;16-18这三个时间段内操作') + } else if(taskCode == 'LOTTERY' && code == 0 && result.success == true) { + log(`任务完成,获得:${result.data.rewards[0].amount}g饲料`) + } else if(taskCode == 'LOTTERY' && code == 1 && result.success == true) { + log(`任务完成,获得:${result.data.rewards[0].amount}水滴`) + } else if(taskCode == 'BROWSE_GOODS' && code == 0 && result.success == true) { + rewardtask(result.data.userTaskLogId,0); + } else if(taskCode == 'BROWSE_GOODS' && code == 1 && result.success == true) { + rewardtask(result.data.userTaskLogId,1); + } else if(taskCode == 'BROWSE_GOODS3' && code == 0 && result.success == true) { + rewardtask(result.data.userTaskLogId,0); + } else if(taskCode == 'FEED_N_TIMES' && result.success == true) { + log(`任务完成,获得:${result.data.rewards[0].amount}水滴`) + } else if(taskCode == 'FEED_N_TIMES' && result.msg == '浇水次数不满足') { + log('浇水不满10次,无法完成任务') + } else if(result.msg == '此任务不可手动完成') { + log('任务需要手动操作') + } else{ + log(`获取任务数据失败,可能是cookies失效`) + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} +function luckydarw(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://farm.api.ddxq.mobi/api/v2/lucky-draw-activity/draw?api_version=9.7.3&app_version=1.0.0&app_client_id=3&station_id=${station_id}&native_version=9.58.0&city_number=${CityId}&device_token=${device_token}&device_id=${device_id}&latitude=${latitude}&longitude=${longitude}&gameId=1&uid=${uid}`, + headers: header1, + } + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.msg == '请求成功' && result.success == true) { + log(`已翻牌并获得:${result.data.chosen.amount}饲料`) + } else { + log('饲料不足,翻牌失败') + msg += '\n饲料不足,翻牌失败' + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +function rewardtask(taskid,code,timeout = 3 * 1000) { + return new Promise((resolve) => { + if(code == 0){ + ddmcheader1=header1 + ddmcurl1 = `http://farm.api.ddxq.mobi/api/v2/task/reward?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&app_version=9.58.0&OSVersion=10&CityId=${CityId}&uid=${uid}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng=${longitude}&device_token=${device_token}&gameId=1&userTaskLogId=${taskid}` + }else{ + ddmcheader1=header2 + ddmcurl1 = `http://farm.api.ddxq.mobi/api/v2/task/reward?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&app_version=9.58.0&OSVersion=10&CityId=${CityId}&uid=${uid}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng=${longitude}&device_token=${device_token}&userTaskLogId=${taskid}` + } + let url = { + url: ddmcurl1, + headers: ddmcheader1, + } + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if(taskid == 0){ + log('暂时没有饲料瓶入口') + }else if (result.msg == '请求成功' && result.success == true) { + log(`任务完成,获得:${result.data.rewards[0].amount}饲料`) + } else if(result.msg == '你已领取奖励,去领其他奖励吧~') { + log('已经领取过该奖励') + } else if(result.msg == '不可领取') { + log('已经领取过该奖励') + } else if(result.msg == '参数无效') { + log('任务不存在或者已完成') + } else { + log('任务失败,可能是cookies失效') + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +function gotofeedfish(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://farm.api.ddxq.mobi/api/v2/task/receive?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&CityId=${CityId}&OSVersion=10&uid=${uid}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng=${longitude}&device_token=&gameId=2&taskCode=FEED_CRAP`, + headers: header2, + } + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.msg == '请求成功' && result.success == true) { + log(`【去鱼塘喂食一次】领取任务成功,等待喂鱼`) + } else if(result.msg == '该任务已经完成了哦'){ + log('【去鱼塘喂食一次】任务已完成') + }else{ + log('【去鱼塘喂食一次】任务失败,可能是cookies失效') + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +function feedfish(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://farm.api.ddxq.mobi/api/v2/props/feed?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&app_version=9.58.0&OSVersion=10&CityId=${CityId}&uid=${uid}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng=${longitude}&device_token=${device_token}&gameId=1&propsId=${fishpropsId}&seedId=${fishseedId}&cityCode=${CityId}&feedPro=0&triggerMultiFeed=1`, + headers: { + "Host": "farm.api.ddxq.mobi", + "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/89.0.4389.72 MQQBrowser/6.2 TBS/045947 Mobile Safari/537.36 xzone/9.58.0 station_id/60dd252dbd8d8c0001eca0e0 OpenTime/"+timestampMs(), + "accept": "*/*", + "origin": "https://game.m.ddxq.mobi", + "x-requested-with": "com.yaya.zone", + "sec-fetch-site": "same-site", + "sec-fetch-mode": "cors", + "sec-fetch-dest": "empty", + "referer": "https://game.m.ddxq.mobi/", + "accept-encoding": "gzip, deflate, br", + "accept-language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7", + "cookie": `DDXQSESSID=${ddmck}` + }, + } + + $.get(url, async (error, response, data) => { + try { + if(error){//406 Not Acceptable + log ('Api请求失败,请登陆APP完成滑动验证') + msg +='\n请登陆APP完成滑动验证完成喂鱼操作' + fish='0' + sl='0' + }else{ + let result = JSON.parse(data); + if (result.success == true && result.data.hardBoxRewardAmountAfterFeed == null) { + log(`喂鱼成功,剩余${result.data.feed.amount}g饲料,${result.data.seed.msg}`) + fish=result.data.hardBoxRewardAmountAfterFeed + sl=result.data.feed.amount + }else if(result.success == true && result.data.hardBoxRewardAmountAfterFeed != null){ + log(`喂鱼成功,剩余${result.data.feed.amount}g饲料,已存储${result.data.hardBoxRewardAmountAfterFeed}g饲料,${result.data.seed.msg}`) + fish=result.data.hardBoxRewardAmountAfterFeed + sl=result.data.feed.amount + } else if(result.msg == '饲料不足10g,请完成任务领饲料~' || result.msg == '今天喂食太多了,休息一下明天再来吧'){ + log('喂鱼失败,饲料不足10g或者达到喂鱼上限') + fish='0' + sl='0' + }else{ + log('喂鱼任务失败,可能是cookies失效') + } + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +function water(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://farm.api.ddxq.mobi/api/v2/props/feed?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&CityId=${CityId}&OSVersion=10&uid=${uid}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng=${longitude}&device_token=${device_token}&propsCode=FEED&seedId=${waterseedId}&propsId=${waterpropsId}`, + headers: header2, + } + + $.get(url, async (error, response, data) => { + try { + if(error){ + log ('Api请求失败,请登陆APP完成滑动验证') + msg +='\n请登陆APP完成滑动验证' + nowater='0' + }else{ + let result = JSON.parse(data); + if (result.msg == '请求成功' && result.success == true) { + nowater=result.data.feed.amount + gyfl = result.data.fertilizerUse.amount + log(`浇水成功,剩余${nowater}水滴,当前肥力:${gyfl},${result.data.msg}`) + if(gyfl < 10){ + log('肥力不足,自动施肥') + await userfeiliao(); + } + } else { + log('浇水失败,可能是水滴不足或者cookies失效') + msg += '\n浇水失败,可能是水滴不足或者cookies失效' + } + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +function userfeiliao(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `https://farm.api.ddxq.mobi/api/v2/props/props-use?api_version=9.1.0&app_client_id=1&station_id=${station_id}&stationId=${station_id}&native_version=&CityId=${CityId}&OSVersion=14&uid=${uid}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng=${longitude}&device_token=${device_token}&propsCode=FERTILIZER&propsId=220910108081811250&seedId=220910108081800250`, + headers: header2, + } + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.msg == '请求成功' && result.success == true) { + log(`施肥成功,剩余${result.data.propsUse.amount}肥料,当前可用肥料:${result.data.propsUseResultVo.amount}`) + } else { + log('肥料不足,施肥失败') + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +function checkwater(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://farm.api.ddxq.mobi/api/v2/userguide/orchard/detail?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&CityId=${CityId}&OSVersion=10&uid=${uid}&latitude=${latitude}&longitude=${longitude}lat=${latitude}&lng=${longitude}&device_token=${device_token}&gameId=2&cityCode=${CityId}`, + headers: header2, + } + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if(data.indexOf("seedId")<0){ + nobanana = 1 + newater=result.data.feed.amount + waterpropsId = result.data.feed.propsId + waterseedId = 0 + log('农场没有香蕉可以种,检查是否已经获得奖励') + msg +='\n农场没有香蕉可以种,检查是否已经获得奖励' + }else if (result.msg == '请求成功' && result.success == true) { + nobanana = 0 + newater=result.data.feed.amount + waterpropsId = result.data.feed.propsId + waterseedId = result.data.baseSeed.seedId + log(`目前果园水滴:${newater}`) + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +function checkwater2(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://farm.api.ddxq.mobi/api/v2/userguide/orchard/detail?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&CityId=${CityId}&OSVersion=10&uid=${uid}&latitude=${latitude}&longitude=${longitude}lat=${latitude}&lng=${longitude}&device_token=${device_token}&gameId=2&cityCode=${CityId}`, + headers: header2, + } + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if(data.indexOf("seedId")<0){ + log('农场没有香蕉可以种,检查是否已经获得奖励') + }else if (result.msg == '请求成功' && result.success == true) { + msg+= `\n【果园】${result.data.baseSeed.msg}` + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +function checkfish(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://farm.api.ddxq.mobi/api/v2/userguide/detail?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&app_version=9.58.0&OSVersion=10&CityId=${CityId}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng=${longitude}&device_token=${device_token}&gameId=1&guideCode=FISHPOND_NEW`, + headers: header1, + } + + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if(data.indexOf("seedId")<0){ + nofish = 1 + newfish=result.data.feed.amount + fishpropsId = result.data.feed.propsId + fishseedId = 0 + fish = 0 + log('鱼塘没有鱼可以喂,检查是否已经获得奖励') + msg +='\n鱼塘没有鱼可以喂,检查是否已经获得奖励' + }else if (result.msg == '请求成功' && result.success == true) { + nofish = 0 + newfish=result.data.feed.amount + fishpropsId = result.data.feed.propsId + fishseedId = result.data.baseSeed.seedId + log(`目前鱼饲料:${newfish}g`) + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +function checkfish2(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://farm.api.ddxq.mobi/api/v2/userguide/detail?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&app_version=9.58.0&OSVersion=10&CityId=${CityId}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng=${longitude}&device_token=${device_token}&gameId=1&guideCode=FISHPOND_NEW`, + headers: header1, + } + + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if(data.indexOf("seedId")<0){ + log('鱼塘没有鱼可以喂,检查是否已经获得奖励') + }else if (result.msg == '请求成功' && result.success == true) { + msg+= `\n【鱼塘】${result.data.baseSeed.msg}` + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +function checkid(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://farm.api.ddxq.mobi/api/v2/friend/list?api_version=9.1.0&app_client_id=2&station_id=${station_id}&stationId=${station_id}&native_version=&CityId=${CityId}&OSVersion=10&uid=${uid}&latitude=${latitude}&longitude=${longitude}&lat=${latitude}&lng=${longitude}&device_token=${device_token}&gameId=1`, + headers: header1, + } + + $.get(url, async (error, response, data) => { + try { + + let result = JSON.parse(data); + if(result.msg == '您的访问已过期,请重新登录app~' && result.code == 111){ + log('cookie失效了!!!cookie失效了!!!cookie失效了!!!cookie失效了!!!') + msg+='cookie失效了!!!cookie失效了!!!cookie失效了!!!cookie失效了!!!' + + }else if(result.msg == '您的访问已过期,请重新登录' && result.code == 1111){ + log('cookie失效了!!!cookie失效了!!!cookie失效了!!!cookie失效了!!!') + msg+='cookie失效了!!!cookie失效了!!!cookie失效了!!!cookie失效了!!!' + + }else{ + nname=result.data.me.nickName + log(`【账号】${nname}|登录成功,cookie有效`) + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} +// ============================================变量检查============================================ \\ +async function Envs() { + if (ddmc) { + if (ddmc.indexOf("@") != -1) { + ddmc.split("@").forEach((item) => { + ddmcArr.push(item); + }); + } else if (ddmc.indexOf("\n") != -1) { + ddmc.split("\n").forEach((item) => { + ddmcArr.push(item); + }); + } else { + ddmcArr.push(ddmc); + } + } else { + log(`\n 【${$.name}】:未填写变量 ddmc`) + return; + } + return true; +} +// ============================================发送消息============================================ \\ +async function SendMsg(message) { + if (!message) + return; + + if (Notify > 0) { + if ($.isNode()) { + var notify = require('./sendNotify'); + await notify.sendNotify($.name, message); + } else { + $.msg(message); + } + } else { + log(message); + } +} + +function getRequest(url) { + var theRequest = new Object(); + if (url.indexOf("?") != -1) { + var str = url.substr(1); + strs = str.split("&"); + for(var i = 0; i < strs.length; i ++) { + theRequest[strs[i].split("=")[0]]=unescape(strs[i].split("=")[1]); + } + } + return theRequest; +} + + function timestampMs(){ + return new Date().getTime(); + } + +/** + * 修改配置文件 + */ +function modify() { + + fs.readFile('/ql/data/config/config.sh','utf8',function(err,dataStr){ + if(err){ + return log('读取文件失败!'+err) + } + else { + var result = dataStr.replace(/regular/g,string); + fs.writeFile('/ql/data/config/config.sh', result, 'utf8', function (err) { + if (err) {return log(err);} + }); + } + }) +} + +function Env(t, e) { "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); class s { constructor(t) { this.env = t } send(t, e = "GET") { t = "string" == typeof t ? { url: t } : t; let s = this.get; return "POST" === e && (s = this.post), new Promise((e, i) => { s.call(this, t, (t, s, r) => { t ? i(t) : e(s) }) }) } get(t) { return this.send.call(this.env, t) } post(t) { return this.send.call(this.env, t, "POST") } } return new class { constructor(t, e) { this.name = t, this.http = new s(this), this.data = null, this.dataFile = "box.dat", this.logs = [], this.isMute = !1, this.isNeedRewrite = !1, this.logSeparator = "\n", this.startTime = (new Date).getTime(), Object.assign(this, e), this.log("", `🔔${this.name}, 开始!`) } isNode() { return "undefined" != typeof module && !!module.exports } isQuanX() { return "undefined" != typeof $task } isSurge() { return "undefined" != typeof $httpClient && "undefined" == typeof $loon } isLoon() { return "undefined" != typeof $loon } toObj(t, e = null) { try { return JSON.parse(t) } catch { return e } } toStr(t, e = null) { try { return JSON.stringify(t) } catch { return e } } getjson(t, e) { let s = e; const i = this.getdata(t); if (i) try { s = JSON.parse(this.getdata(t)) } catch { } return s } setjson(t, e) { try { return this.setdata(JSON.stringify(t), e) } catch { return !1 } } getScript(t) { return new Promise(e => { this.get({ url: t }, (t, s, i) => e(i)) }) } runScript(t, e) { return new Promise(s => { let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); i = i ? i.replace(/\n/g, "").trim() : i; let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; const [o, h] = i.split("@"), n = { url: `http://${h}/v1/scripting/evaluate`, body: { script_text: t, mock_type: "cron", timeout: r }, headers: { "X-Key": o, Accept: "*/*" } }; this.post(n, (t, e, i) => s(i)) }).catch(t => this.logErr(t)) } loaddata() { if (!this.isNode()) return {}; { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e); if (!s && !i) return {}; { const i = s ? t : e; try { return JSON.parse(this.fs.readFileSync(i)) } catch (t) { return {} } } } } writedata() { if (this.isNode()) { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e), r = JSON.stringify(this.data); s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) } } lodash_get(t, e, s) { const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); let r = t; for (const t of i) if (r = Object(r)[t], void 0 === r) return s; return r } lodash_set(t, e, s) { return Object(t) !== t ? t : (Array.isArray(e) || (e = e.toString().match(/[^.[\]]+/g) || []), e.slice(0, -1).reduce((t, s, i) => Object(t[s]) === t[s] ? t[s] : t[s] = Math.abs(e[i + 1]) >> 0 == +e[i + 1] ? [] : {}, t)[e[e.length - 1]] = s, t) } getdata(t) { let e = this.getval(t); if (/^@/.test(t)) { const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : ""; if (r) try { const t = JSON.parse(r); e = t ? this.lodash_get(t, i, "") : e } catch (t) { e = "" } } return e } setdata(t, e) { let s = !1; if (/^@/.test(e)) { const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i), h = i ? "null" === o ? null : o || "{}" : "{}"; try { const e = JSON.parse(h); this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i) } catch (e) { const o = {}; this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i) } } else s = this.setval(t, e); return s } getval(t) { return this.isSurge() || this.isLoon() ? $persistentStore.read(t) : this.isQuanX() ? $prefs.valueForKey(t) : this.isNode() ? (this.data = this.loaddata(), this.data[t]) : this.data && this.data[t] || null } setval(t, e) { return this.isSurge() || this.isLoon() ? $persistentStore.write(t, e) : this.isQuanX() ? $prefs.setValueForKey(t, e) : this.isNode() ? (this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0) : this.data && this.data[e] || null } initGotEnv(t) { this.got = this.got ? this.got : require("got"), this.cktough = this.cktough ? this.cktough : require("tough-cookie"), this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar, t && (t.headers = t.headers ? t.headers : {}, void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar)) } get(t, e = (() => { })) { t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"]), this.isSurge() || this.isLoon() ? (this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.get(t, (t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) })) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { try { if (t.headers["set-cookie"]) { const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar } } catch (t) { this.logErr(t) } }).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => { const { message: s, response: i } = t; e(s, i, i && i.body) })) } post(t, e = (() => { })) { if (t.body && t.headers && !t.headers["Content-Type"] && (t.headers["Content-Type"] = "application/x-www-form-urlencoded"), t.headers && delete t.headers["Content-Length"], this.isSurge() || this.isLoon()) this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.post(t, (t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) }); else if (this.isQuanX()) t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => e(t)); else if (this.isNode()) { this.initGotEnv(t); const { url: s, ...i } = t; this.got.post(s, i).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => { const { message: s, response: i } = t; e(s, i, i && i.body) }) } } time(t, e = null) { const s = e ? new Date(e) : new Date; let i = { "M+": s.getMonth() + 1, "d+": s.getDate(), "H+": s.getHours(), "m+": s.getMinutes(), "s+": s.getSeconds(), "q+": Math.floor((s.getMonth() + 3) / 3), S: s.getMilliseconds() }; /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); for (let e in i) new RegExp("(" + e + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? i[e] : ("00" + i[e]).substr(("" + i[e]).length))); return t } msg(e = t, s = "", i = "", r) { const o = t => { if (!t) return t; if ("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { "open-url": t } : this.isSurge() ? { url: t } : void 0; if ("object" == typeof t) { if (this.isLoon()) { let e = t.openUrl || t.url || t["open-url"], s = t.mediaUrl || t["media-url"]; return { openUrl: e, mediaUrl: s } } if (this.isQuanX()) { let e = t["open-url"] || t.url || t.openUrl, s = t["media-url"] || t.mediaUrl; return { "open-url": e, "media-url": s } } if (this.isSurge()) { let e = t.url || t.openUrl || t["open-url"]; return { url: e } } } }; if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) { let t = ["", "==============📣系统通知📣=============="]; t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) } } log(...t) { t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator)) } logErr(t, e) { const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) } wait(t) { return new Promise(e => setTimeout(e, t)) } done(t = {}) { const e = (new Date).getTime(), s = (e - this.startTime) / 1e3; this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) } }(t, e) } diff --git a/脚本库/web版/账密/方舟健客签到/2025-12-07_jksign_b722f903.py b/脚本库/web版/账密/方舟健客签到/2025-12-07_jksign_b722f903.py new file mode 100644 index 0000000..fc56321 --- /dev/null +++ b/脚本库/web版/账密/方舟健客签到/2025-12-07_jksign_b722f903.py @@ -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)) + \ No newline at end of file diff --git a/脚本库/web版/账密/星星充电签到/2025-09-01_xxcd_40e3aef4.py b/脚本库/web版/账密/星星充电签到/2025-09-01_xxcd_40e3aef4.py new file mode 100644 index 0000000..2868ac7 --- /dev/null +++ b/脚本库/web版/账密/星星充电签到/2025-09-01_xxcd_40e3aef4.py @@ -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) + diff --git a/脚本库/web版/账密/星星充电签到/2026-05-23_xxcd_40e3aef4.py b/脚本库/web版/账密/星星充电签到/2026-05-23_xxcd_40e3aef4.py new file mode 100644 index 0000000..3d78f4f --- /dev/null +++ b/脚本库/web版/账密/星星充电签到/2026-05-23_xxcd_40e3aef4.py @@ -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) + diff --git a/脚本库/微信小程序/抓包版/cloud189/2025-09-06_cloud189_7c90c2eb.py b/脚本库/微信小程序/抓包版/cloud189/2025-09-06_cloud189_7c90c2eb.py new file mode 100644 index 0000000..f436c04 --- /dev/null +++ b/脚本库/微信小程序/抓包版/cloud189/2025-09-06_cloud189_7c90c2eb.py @@ -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'(.*?)', response, re.DOTALL).group(1) + user_data = unquote(aes_cbc_decrypt(ciphertext, aes_key, aes_iv)) + # print(user_data) + login_Name = re.search(r'(.*?)', user_data, re.DOTALL).group(1) + session_Key = re.search(r'(.*?)', user_data, re.DOTALL).group(1) + sessionSecret = re.search(r'(.*?)', user_data, re.DOTALL).group(1) + familySessionKey = re.search(r'(.*?)', 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'(.*?)', response, re.DOTALL).group(1)) + log('【天翼云盘】签到成功:' + re.search(r'(.*?)', 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)) + + + + + + + + + + diff --git a/脚本库/微信小程序/抓包版/jtc/2025-10-26_jtc_d7fa5acd.py b/脚本库/微信小程序/抓包版/jtc/2025-10-26_jtc_d7fa5acd.py new file mode 100644 index 0000000..2de0e35 --- /dev/null +++ b/脚本库/微信小程序/抓包版/jtc/2025-10-26_jtc_d7fa5acd.py @@ -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)) diff --git a/脚本库/微信小程序/抓包版/jtc/2025-10-26_jtc_d7fa5acd_2.py b/脚本库/微信小程序/抓包版/jtc/2025-10-26_jtc_d7fa5acd_2.py new file mode 100644 index 0000000..2de0e35 --- /dev/null +++ b/脚本库/微信小程序/抓包版/jtc/2025-10-26_jtc_d7fa5acd_2.py @@ -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)) diff --git a/脚本库/微信小程序/抓包版/快手双端/2026-05-11_ks_dual_aa4fbaa7.js b/脚本库/微信小程序/抓包版/快手双端/2026-05-11_ks_dual_aa4fbaa7.js new file mode 100644 index 0000000..cb4ea91 --- /dev/null +++ b/脚本库/微信小程序/抓包版/快手双端/2026-05-11_ks_dual_aa4fbaa7.js @@ -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); +})(); diff --git a/脚本库/微信小程序/抓包版/滴滴果园/2025-01-11_ddgy_236924d1.js b/脚本库/微信小程序/抓包版/滴滴果园/2025-01-11_ddgy_236924d1.js new file mode 100644 index 0000000..7675277 --- /dev/null +++ b/脚本库/微信小程序/抓包版/滴滴果园/2025-01-11_ddgy_236924d1.js @@ -0,0 +1,999 @@ +// # Source: https://github.com/lksky8/sign-ql/blob/main/invalid/ddgy.js +// # Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/ddgy.js +// # Repo: lksky8/sign-ql +// # Path: invalid/ddgy.js +// # UploadedAt: 2025-01-11T18:50:13Z +// # SHA256: 236924d18d7e9ae58141a6c45bde1b9de748e6e63c8ca805162caf02fb01b362 +// # Category: 微信小程序/抓包版 +// # Evidence: appid/openid/session_key/encryptedData等小程序字段 +// + +/* + 作者:https://github.com/lksky8/sign-ql + 日期:2022-10-8 + 软件:滴滴果园 + 功能:签到,做任务,浇水 + 抓包:随便抓一个包,只要token后面的内容就行"token":"xxxxxxxxxxxxxxxxxxxxxxxx"} + 变量:ddgy='xxxxxxxxxxxxx@xxxxxxxxxxxxx ' 多个账号用 @ 或者 换行 分割 + 注意:必须先完成新手教程 + 浏览周边好去处,查看附近核酸检测点,真香卡 这三个任务第一次是完成不了,第二次会自动完成 + cron: 8 8,12,15 * * * + */ + +const $ = new Env('滴滴果园'); +const notify = $.isNode() ? require('./sendNotify') : ''; +const {log} = console; +const Notify = 1; //0为关闭通知,1为打开通知,默认为1 +const taskarra = [72,41,62,261] +const fdarra = [251,252,253] + +////////////////////// +let ddgy = process.env.ddgy; +let ddgyArr = []; +let data = ''; +let msg = ''; +const header = JSON.parse(`{"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/105.0.5195.136 Mobile Safari/537.36 didi.passenger/6.2.4 FusionKit/2.0.0","Content-Type":"application/json;charset=UTF-8","Accept":"application/json, text/plain, */*"}`) + +!(async () => { + + if (!(await Envs())) + return; + else { + + + + log(`\n\n============================================= \n脚本执行 - 北京时间(UTC+8):${new Date( + new Date().getTime() + new Date().getTimezoneOffset() * 60 * 1000 + + 8 * 60 * 60 * 1000).toLocaleString()} \n=============================================\n`); + + + log(`\n=================== 共找到 ${ddgyArr.length} 个账号 ===================`) + + for (let index = 0; index < ddgyArr.length; index++) { + + let num = index + 1 + log(`\n========= 开始【第 ${num} 个账号】=========\n`) + token = ddgyArr[index]; + msg += `\n第${num}个账号运行结果:` + log('开始签到'); + await doSign(); + await checkwater(); + await getask(); + await $.wait(2 * 1000); + log('开始任务') + for (let i = 0; i < taskarra.length; i++) { + await dotask(taskarra[i]) + await $.wait(2 * 1000); + await award(taskarra[i]) + } + await $.wait(2 * 1000); + log('做【饭点领水滴】任务') + for (let i = 0; i < fdarra.length; i++) { + await award(fdarra[i]) + await $.wait(2 * 1000); + } + log('做【从福利中心浏览滴滴果园】任务') + await accept(255); + await $.wait(3 * 1000); + await doflzx(); + await $.wait(3 * 1000); + await award(255); + log('做【看附近核酸检测点】任务') + await accept(68); + await $.wait(3 * 1000); + await dohesuan(); + await $.wait(3 * 1000); + await award(68); + log('做【浏览真香卡30s】任务') + await accept(65); + await $.wait(3 * 1000); + await dozxk() + await $.wait(2 * 1000); + await award(65) + await $.wait(2 * 1000); + log('做【浏览周边好去处】任务') + await accept(70); + await $.wait(3 * 1000); + await dozb() + await $.wait(2 * 1000); + await award(70) + await $.wait(2 * 1000); + await checkwater(); + await $.wait(2 * 1000); + await collectwater(); + await $.wait(2 * 1000); + if(jscs >= 200){ + log('浇水达到200g获取1袋肥料') + await award(100) + await $.wait(2 * 1000); + }else if(jscs >= 500){ + log('浇水达到500g获取2袋肥料') + await award(101) + await $.wait(2 * 1000); + }else{ + log('浇水次数不足无法领取200g/500g奖励') + } + if(parseInt(sl) > 10){ + for (i = 0; i < 10; i++) { + await water();//浇水 + await $.wait(2 * 1000); + if(parseInt(nowater) < 10){ + log('水滴不足10,停止浇水') + break; + } + } + } + await info(); + } + await SendMsg(msg); + } + +})() + .catch((e) => log(e)) + .finally(() => $.done()) + + +/** + * 签到 + */ +function doSign(timeout = 3 * 1000) { + return new Promise((resolve) => { + var postbody = { + "xbiz": "240301", + "prod_key": "didi-orchard", + "xpsid": "", + "dchn": "O9aM923", + "xoid": "", + "uid": "", + "xenv": "passenger", + "xspm_from": "", + "xpsid_root": "", + "xpsid_from": "", + "xpsid_share": "", + "platform": 1, + "token": `${token}` + } + let url = { + url: 'http://game.xiaojukeji.com/api/game/plant/sign', + headers: header, + body: JSON.stringify(postbody), + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.errmsg == 'success') { + log(`签到成功,今天是第${result.data['sign_times']}天签到,获得:${result.data.rewards[0].name}`) + msg += `\n签到成功,今天是第${result.data['sign_times']}天签到,获得:${result.data.rewards[0].name}` + } else if (result.errmsg == '您今天已经签过到啦') { + log(`签到失败,今日已签到`) + //msg += `\n签到失败,今日已签到` + } else { + log(`签到失败,原因是:${result}`) + msg += `\n签到失败,原因是:${result}` + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +/** + * 获取任务列表 + */ +function getask(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `http://game.xiaojukeji.com/api/game/mission/get?xbiz=240301&prod_key=didi-orchard&xpsid=&dchn=O9aM923&xoid=&uid=&xenv=passenger&xspm_from=&xpsid_root=&xpsid_from=&xpsid_share=&game_id=23&loop=0&platform=1&token=${token}`, + headers: JSON.parse(`{"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/105.0.5195.136 Mobile Safari/537.36 didi.passenger/6.2.4 FusionKit/2.0.0","Content-Type":"application/json;charset=UTF-8"}`), + } + + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.errmsg == 'success') { + log('任务获取成功') + let tasklist = result.data.missions + let b = tasklist.find(item => item['title']==='每日浇水200g') + jscs = b['progress'] + } else { + log(`任务获取失败,原因是:${result}`) + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} +/** + * 接受任务 + */ +function accept(id,timeout = 3 * 1000) { + return new Promise((resolve) => { + var postbody = { + "xbiz": "240301", + "prod_key": "didi-orchard", + "xpsid": "", + "dchn": "O9aM923", + "xoid": "", + "uid": "", + "xenv": "passenger", + "xspm_from": "", + "xpsid_root": "", + "xpsid_from": "", + "xpsid_share": "", + "mission_id": id, + "game_id": 23, + "platform": 1, + "token": `${token}` + } + let url = { + url: 'http://game.xiaojukeji.com/api/game/mission/accept', + headers: header, + body: JSON.stringify(postbody), + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.errmsg != 'success') { + log(`任务接受失败,原因是:${data}`) + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +/** + * 做任务 + */ +function dotask(id,timeout = 3 * 1000) { + return new Promise((resolve) => { + var postbody = { + "xbiz": "240301", + "prod_key": "didi-orchard", + "xpsid": "", + "dchn": "O9aM923", + "xoid": "", + "uid": "", + "xenv": "passenger", + "xspm_from": "", + "xpsid_root": "", + "xpsid_from": "", + "xpsid_share": "", + "mission_id": id, + "game_id": 23, + "platform": 1, + "token": `${token}` + } + let url = { + url: 'https://game.xiaojukeji.com/api/game/mission/update', + headers: header, + body: JSON.stringify(postbody), + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.errmsg == 'success') { + log('任务已提交') + }else if(result.errmsg == '服务内部错误'){ + log('任务已完成不存在或者无法完成,需要手动完成') + } else { + log(`任务失败,原因是:${data}`) + msg += '\n任务失败' + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +/** + * 完成任务 + */ +function award(id,timeout = 3 * 1000) { + return new Promise((resolve) => { + var postbody = { + "xbiz": "240301", + "prod_key": "didi-orchard", + "xpsid": "", + "dchn": "O9aM923", + "xoid": "", + "uid": "", + "xenv": "passenger", + "xspm_from": "", + "xpsid_root": "", + "xpsid_from": "", + "xpsid_share": "", + "mission_id": id, + "game_id": 23, + "platform": 1, + "token": `${token}` + } + let url = { + url: 'http://game.xiaojukeji.com/api/game/mission/award', + headers: header, + body: JSON.stringify(postbody), + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.errmsg == 'success') { + log(`<${result.data.title}>任务完成,获得${result.data.reward[0].count}点${result.data.reward[0].name}`) + } else if (result.errmsg == '对应奖励已领取') { + log(`任务完成,奖励已经领取`) + } else if (result.errmsg == '任务未达到领奖条件') { + log(`任务提交失败`) + } else { + log(`任务失败,原因是:${data}`) + msg += '\n任务失败' + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +/** + * 做核酸 + */ +function dohesuan(timeout = 3 * 1000) { + return new Promise((resolve) => { + var postbody = { + "xbiz": "240000", + "prod_key": "ut-nucleic-acid-test", + "xpsid": "fdd4115c5e704edc8303ac958a8d57b3", + "dchn": "dQnERQO", + "xoid": "gCTBp+hrSmitnuv3eGQUhg", + "uid": 1, + "xenv": "passenger", + "xspm_from": "didi-orchard.none.c10030.none", + "xpsid_root": "53ebf61bb0b048b493f590b49cf06536", + "xpsid_from": "53ebf61bb0b048b493f590b49cf06536", + "xpsid_share": "", + "xpos_from": "%7B%22id%22%3A205%2C%22pk%22%3A%22didi-orchard%22%2C%22idx%22%3A%22none%22%7D", + "web_type": 1, + "token": `${token}`, + "ticket": `${token}`, + "city_id": 11, + "lon": 111, + "lat": 11, + "env": { + "newTicket": `${token}`, + "newAppid": "10000", + "openId": "", + "latitude": "11", + "longitude": "111", + "cityId": "11", + "isHitButton": true, + "isOpenWeb": false, + "ddfp": "f44f15a79a26400afa9f49e44987c310", + "deviceId": "f44f15a79a26400afa9f49e44987c310", + "appVersion": "6.2.4", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 didi.passenger/6.2.4 FusionKit/1.2.20 OffMode/0", + "fromChannel": "1" + }, + "biz": 2 + } + let url = { + url: 'https://gaea.xiaojukeji.com/poi/health/preview/page', + headers: { + "Accept-Encoding": "gzip, deflate, br", + "Host": "gaea.xiaojukeji.com", + "Content-Length": 1623, + "Referer": "https://page.udache.com/", + "Content-Type": "application/json", + "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 didi.passenger/6.2.4 FusionKit/1.2.20 OffMode/0", + "Accept": "application/json, text/plain, */*", + "Accept-Language": "zh-cn", + "Connection": "keep-alive" + }, + body: JSON.stringify(postbody), + } + + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.errmsg == 'ok') { + log('【查看附近核酸检测点】任务浏览成功') + } else { + log(`任务失败,原因是:${data}`) + msg += '\n任务失败' + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +/** + * 做真香卡 + */ +function dozxk(timeout = 3 * 1000) { + return new Promise((resolve) => { + var postbody = { + "xbiz": "240201", + "prod_key": "ut-carowner-service", + "xpsid": "", + "dchn": "YOwwv95", + "xoid": "", + "xenv": "passenger", + "xspm_from": "", + "xpsid_root": "", + "xpsid_from": "", + "xpsid_share": "", + "xpos_from": "", + "platform_type": 1, + "token": `${token}`, + "env": { + "newTicket": `${token}`, + "isOpenWeb": true, + "ticket": `${token}`, + "cityId": "11", + "longitude": "111", + "latitude": "11", + "xAxes": "0", + "yAxes": "0", + "newAppid": "10000", + "isHitButton": true, + "ddfp": "f44f15a79a26400afa9f49e44987c310", + "deviceId": "f44f15a79a26400afa9f49e44987c310", + "appVersion": "6.2.4", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 didi.passenger/6.2.4 FusionKit/1.2.20 OffMode/0", + "fromChannel": "1" + }, + "appversion": "6.2.4", + "city_id": 11, + "version": 2 + } + let url = { + url: 'https://ut.xiaojukeji.com/ut/kappa/api/owner/vip/index', + headers: header, + body: JSON.stringify(postbody), + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.errmsg == 'success') { + log('【浏览真香卡30s】任务浏览成功') + } else { + log(`任务失败,原因是:${data}`) + msg += '\n任务失败' + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +/** + * 福利中心浏览果园 + */ +function doflzx(timeout = 3 * 1000) { + return new Promise((resolve) => { + var postbody = { + "xbiz": "240000", + "prod_key": "welfare-center", + "xpsid": "", + "dchn": "DpQ3dga", + "xoid": "", + "xenv": "passenger", + "xspm_from": "", + "xpsid_root": "", + "xpsid_from": "", + "xpsid_share": "", + "token": `${token}`, + "lat": "11", + "lng": "111", + "platform": "na", + "env": `{\"cityId\":\"11\",\"token\":\"${token}\",\"longitude\":\"111\",\"latitude\":\"11\",\"appid\":\"30004\",\"fromChannel\":\"1\",\"deviceId\":\"f44f15a79a26400afa9f49e44987c310\",\"ddfp\":\"f44f15a79a26400afa9f49e44987c310\",\"appVersion\":\"6.2.4\",\"userAgent\":\"Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 didi.passenger/6.2.4 FusionKit/1.2.20 BottomBar/on OffMode/0\"}`, + "type": "navigation_click", + "data": { + "navigation_type": "didi_garden" + } + } + let url = { + url: 'https://ut.xiaojukeji.com/ut/welfare/api/action/event/report', + headers: header, + body: JSON.stringify(postbody), + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.errmsg == 'success') { + log('【从福利中心浏览滴滴果园】任务成功') + } else { + log(`任务失败,原因是:${data}`) + msg += '\n任务失败' + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +function dozb(timeout = 3 * 1000) { + return new Promise((resolve) => { + var postbody = { + "xbiz": "240000", + "prod_key": "ut-poi-evaluation", + "xpsid": "8b29c3e9b700429998fe26e672299ec9", + "dchn": "djB58ok", + "xoid": "gCTBp+hrSmitnuv3eGQUhg", + "uid": 1, + "xenv": "passenger", + "xspm_from": "didi-orchard.none.c10030.none", + "xpsid_root": "39d678d291b54ebf96a3e625c6177a91", + "xpsid_from": "39d678d291b54ebf96a3e625c6177a91", + "xpsid_share": "", + "xpos_from": "%7B%22id%22%3A205%2C%22pk%22%3A%22didi-orchard%22%2C%22idx%22%3A%22none%22%7D", + "web_type": 1, + "token": `${token}`, + "ticket": `${token}`, + "city_id": 11, + "lon": 111, + "lat": 11, + "env": { + "newTicket": `${token}`, + "newAppid": "10000", + "openId": "", + "latitude": "11", + "longitude": "111", + "cityId": "11", + "isHitButton": true, + "isOpenWeb": false, + "ddfp": "f44f15a79a26400afa9f49e44987c310", + "deviceId": "f44f15a79a26400afa9f49e44987c310", + "appVersion": "6.2.4", + "userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 didi.passenger/6.2.4 FusionKit/1.2.20 OffMode/0", + "fromChannel": "1" + }, + "biz": 3 + } + let url = { + url: 'https://gaea.xiaojukeji.com/poi/health/preview/page', + headers: { + "Accept-Encoding": "gzip, deflate, br", + "Host": "gaea.xiaojukeji.com", + "Content-Length": 1620, + "Referer": "https://page.udache.com/", + "Content-Type": "application/json", + "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 didi.passenger/6.2.4 FusionKit/1.2.20 OffMode/0", + "Accept": "application/json, text/plain, */*", + "Accept-Language": "zh-cn", + "Connection": "keep-alive" + }, + body: JSON.stringify(postbody), + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.errmsg == 'ok') { + log('【浏览周边好去处】任务浏览成功') + } else { + log(`任务失败,原因是:${data}`) + msg += '\n任务失败' + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +/** + * 查询水果是否成熟 + */ +function checkFruits(timeout = 3 * 1000) { + return new Promise((resolve) => { + var postbody = { + "xbiz": "240301", + "prod_key": "didi-orchard", + "xpsid": "", + "dchn": "O9aM923", + "xoid": "", + "uid": "", + "xenv": "passenger", + "xspm_from": "", + "xpsid_root": "", + "xpsid_from": "", + "xpsid_share": "", + "platform": 1, + "token": `${token}` + } + let url = { + url: 'https://game.xiaojukeji.com/api/game/plant/myFruits', + headers: header, + body: JSON.stringify(postbody), + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.data['my_fruits'] == null) { + log('水果还没成熟') + } else { + log(`浇水失败,原因是:${data}`) + msg += `\n浇水失败` + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +/** + * 浇水 + */ +function water(timeout = 3 * 1000) { + return new Promise((resolve) => { + var postbody = { + "xbiz": "240301", + "prod_key": "didi-orchard", + "xpsid": "", + "dchn": "O9aM923", + "xoid": "", + "uid": "", + "xenv": "passenger", + "xspm_from": "", + "xpsid_root": "", + "xpsid_from": "", + "xpsid_share": "", + "is_fast": false, + "water_status": 0, + "platform": 1, + "token": `${token}` + } + let url = { + url: 'https://game.xiaojukeji.com/api/game/plant/watering', + headers: header, + body: JSON.stringify(postbody), + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.errmsg == 'success') { + let w=100 - parseInt(result.data['tree_progress']) + nowater=result.data['pack_water'] + if(result.data['pack_fer'] > 0){ + log('有肥料可用,自动使用') + await yjsf(); + await $.wait(2 * 1000); + } + log(`浇水成功,水滴剩余${nowater}g,差${result.data['next_box_progress']}开宝箱,再浇水${w}%就升级到下一级`) + } else if (result.errmsg == '水滴不足') { + log('浇水失败,水滴不足') + msg += `\n浇水失败,水滴不足` + } else { + log(`浇水失败,原因是:${data}`) + msg += `\n浇水失败` + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +/** + * 一键施肥 + */ +function yjsf(timeout = 3 * 1000) { + return new Promise((resolve) => { + var postbody = { + "xbiz": "240301", + "prod_key": "didi-orchard", + "xpsid": "", + "dchn": "O9aM923", + "xoid": "", + "uid": "", + "xenv": "passenger", + "xspm_from": "", + "xpsid_root": "", + "xpsid_from": "", + "xpsid_share": "", + "count": 1, + "quick": true, + "platform": 1, + "token": `${token}` + } + let url = { + url: 'https://game.xiaojukeji.com/api/game/plant/fertilizer', + headers: header, + body: JSON.stringify(postbody), + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.errmsg == 'success') { + log(`施肥成功,目前肥力:${result.data['tree_nutrient']},剩余饲料${result.data['pack_fer']}袋可用`) + } else { + log(`施肥失败,原因是:${data}`) + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +/** + * 收集水滴 + */ +function collectwater(timeout = 3 * 1000) { + return new Promise((resolve) => { + var postbody = { + "xbiz": "240301", + "prod_key": "didi-orchard", + "xpsid": "", + "dchn": "O9aM923", + "xoid": "", + "uid": "", + "xenv": "passenger", + "xspm_from": "", + "xpsid_root": "", + "xpsid_from": "", + "xpsid_share": "", + "platform": 1, + "token": `${token}` + } + let url = { + url: 'https://game.xiaojukeji.com/api/game/plant/recBucketWater', + headers: header, + body: JSON.stringify(postbody), + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.errmsg == 'success') { + log(`水滴收集成功,获得:${result.data['rec_water']}g`) + } else { + log(`水滴收集失败,原因是:${data}`) + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +/** + * 查水 + */ +function checkwater(timeout = 3 * 1000) { + return new Promise((resolve) => { + var postbody = { + "xbiz": "240301", + "prod_key": "didi-orchard", + "xpsid": "", + "dchn": "O9aM923", + "xoid": "", + "uid": "", + "xenv": "passenger", + "xspm_from": "", + "xpsid_root": "", + "xpsid_from": "", + "xpsid_share": "", + "assist_type": 0, + "encode_uid": "", + "is_old_player": true, + "platform": 1, + "token": `${token}` + } + let url = { + url: 'https://game.xiaojukeji.com/api/game/plant/enter', + headers: header, + body: JSON.stringify(postbody), + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.errmsg == 'success') { + let w=100 - parseInt(result.data['tree_info']['tree_progress']) + sl=result.data['tree_info']['pack_water'] + box = result.data['tree_info']['available_box'] + fl = result.data['tree_info']['tree_nutrient'] + if(box){ + await recCommonBox(); + } + log(`水滴剩余${sl}g,肥料:${fl},差${result.data['tree_info']['next_box_progress']}开宝箱,再浇水${w}%就升级到下一级`) + } else { + log(`数据获取失败,原因是:${data}`) + msg += `\n数据获取失败,原因是:${data}` + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +/** + * 查水2 + */ +function info(timeout = 3 * 1000) { + return new Promise((resolve) => { + var postbody = { + "xbiz": "240301", + "prod_key": "didi-orchard", + "xpsid": "", + "dchn": "O9aM923", + "xoid": "", + "uid": "", + "xenv": "passenger", + "xspm_from": "", + "xpsid_root": "", + "xpsid_from": "", + "xpsid_share": "", + "assist_type": 0, + "encode_uid": "", + "is_old_player": true, + "platform": 1, + "token": `${token}` + } + let url = { + url: 'https://game.xiaojukeji.com/api/game/plant/enter', + headers: header, + body: JSON.stringify(postbody), + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.errmsg == 'success') { + let w=100 - parseInt(result.data['tree_info']['tree_progress']) + log(`果树水滴剩余${result.data['tree_info']['pack_water']}g,肥料:${result.data['tree_info']['tree_nutrient']},差${result.data['tree_info']['next_box_progress']}开宝箱,再浇水${w}%就升级到下一级`); + msg += `\n果树水滴剩余${result.data['tree_info']['pack_water']}g,肥料:${result.data['tree_info']['tree_nutrient']},差${result.data['tree_info']['next_box_progress']}开宝箱,再浇水${w}%就升级到下一级` + } else { + log(`数据获取失败,原因是:${data}`) + msg += `\n数据获取失败,原因是:${data}` + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +/** + * 开宝箱 + */ +function recCommonBox(timeout = 3 * 1000) { + return new Promise((resolve) => { + var postbody = { + "xbiz": "240301", + "prod_key": "didi-orchard", + "xpsid": "", + "dchn": "O9aM923", + "xoid": "", + "uid": "", + "xenv": "passenger", + "xspm_from": "", + "xpsid_root": "", + "xpsid_from": "", + "xpsid_share": "", + "platform": 1, + "token": `${token}` + } + let url = { + url: 'https://game.xiaojukeji.com/api/game/plant/recCommonBox', + headers: header, + body: JSON.stringify(postbody), + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.errmsg == 'success') { + log(`宝箱领取成功,获得${result.data.rewards[0].num}点${result.data.rewards[0].name}`) + }else if(result.errmsg == '对应奖励已领取'){ + log('暂时没有宝箱可以领取') + } else { + log(`宝箱领取失败,原因是:${data}`) + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +// ============================================变量检查============================================ \\ +async function Envs() { + if (ddgy) { + if (ddgy.indexOf("@") != -1) { + ddgy.split("@").forEach((item) => { + ddgyArr.push(item); + }); + } else if (ddgy.indexOf("\n") != -1) { + ddgy.split("\n").forEach((item) => { + ddgyArr.push(item); + }); + } else { + ddgyArr.push(ddgy); + } + } else { + log(`\n 【${$.name}】:未填写变量 ddgy`) + return; + } + + return true; +} + +// ============================================发送消息============================================ \\ +async function SendMsg(message) { + if (!message) + return; + + if (Notify > 0) { + if ($.isNode()) { + var notify = require('./sendNotify'); + await notify.sendNotify($.name, message); + } else { + $.msg(message); + } + } else { + log(message); + } +} +/** + * 修改配置文件 + */ +function modify() { + + fs.readFile('/ql/data/config/config.sh','utf8',function(err,dataStr){ + if(err){ + return log('读取文件失败!'+err) + } + else { + var result = dataStr.replace(/regular/g,string); + fs.writeFile('/ql/data/config/config.sh', result, 'utf8', function (err) { + if (err) {return log(err);} + }); + } + }) +} + +function Env(t, e) { "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); class s { constructor(t) { this.env = t } send(t, e = "GET") { t = "string" == typeof t ? { url: t } : t; let s = this.get; return "POST" === e && (s = this.post), new Promise((e, i) => { s.call(this, t, (t, s, r) => { t ? i(t) : e(s) }) }) } get(t) { return this.send.call(this.env, t) } post(t) { return this.send.call(this.env, t, "POST") } } return new class { constructor(t, e) { this.name = t, this.http = new s(this), this.data = null, this.dataFile = "box.dat", this.logs = [], this.isMute = !1, this.isNeedRewrite = !1, this.logSeparator = "\n", this.startTime = (new Date).getTime(), Object.assign(this, e), this.log("", `🔔${this.name}, 开始!`) } isNode() { return "undefined" != typeof module && !!module.exports } isQuanX() { return "undefined" != typeof $task } isSurge() { return "undefined" != typeof $httpClient && "undefined" == typeof $loon } isLoon() { return "undefined" != typeof $loon } toObj(t, e = null) { try { return JSON.parse(t) } catch { return e } } toStr(t, e = null) { try { return JSON.stringify(t) } catch { return e } } getjson(t, e) { let s = e; const i = this.getdata(t); if (i) try { s = JSON.parse(this.getdata(t)) } catch { } return s } setjson(t, e) { try { return this.setdata(JSON.stringify(t), e) } catch { return !1 } } getScript(t) { return new Promise(e => { this.get({ url: t }, (t, s, i) => e(i)) }) } runScript(t, e) { return new Promise(s => { let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); i = i ? i.replace(/\n/g, "").trim() : i; let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; const [o, h] = i.split("@"), n = { url: `http://${h}/v1/scripting/evaluate`, body: { script_text: t, mock_type: "cron", timeout: r }, headers: { "X-Key": o, Accept: "*/*" } }; this.post(n, (t, e, i) => s(i)) }).catch(t => this.logErr(t)) } loaddata() { if (!this.isNode()) return {}; { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e); if (!s && !i) return {}; { const i = s ? t : e; try { return JSON.parse(this.fs.readFileSync(i)) } catch (t) { return {} } } } } writedata() { if (this.isNode()) { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e), r = JSON.stringify(this.data); s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) } } lodash_get(t, e, s) { const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); let r = t; for (const t of i) if (r = Object(r)[t], void 0 === r) return s; return r } lodash_set(t, e, s) { return Object(t) !== t ? t : (Array.isArray(e) || (e = e.toString().match(/[^.[\]]+/g) || []), e.slice(0, -1).reduce((t, s, i) => Object(t[s]) === t[s] ? t[s] : t[s] = Math.abs(e[i + 1]) >> 0 == +e[i + 1] ? [] : {}, t)[e[e.length - 1]] = s, t) } getdata(t) { let e = this.getval(t); if (/^@/.test(t)) { const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : ""; if (r) try { const t = JSON.parse(r); e = t ? this.lodash_get(t, i, "") : e } catch (t) { e = "" } } return e } setdata(t, e) { let s = !1; if (/^@/.test(e)) { const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i), h = i ? "null" === o ? null : o || "{}" : "{}"; try { const e = JSON.parse(h); this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i) } catch (e) { const o = {}; this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i) } } else s = this.setval(t, e); return s } getval(t) { return this.isSurge() || this.isLoon() ? $persistentStore.read(t) : this.isQuanX() ? $prefs.valueForKey(t) : this.isNode() ? (this.data = this.loaddata(), this.data[t]) : this.data && this.data[t] || null } setval(t, e) { return this.isSurge() || this.isLoon() ? $persistentStore.write(t, e) : this.isQuanX() ? $prefs.setValueForKey(t, e) : this.isNode() ? (this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0) : this.data && this.data[e] || null } initGotEnv(t) { this.got = this.got ? this.got : require("got"), this.cktough = this.cktough ? this.cktough : require("tough-cookie"), this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar, t && (t.headers = t.headers ? t.headers : {}, void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar)) } get(t, e = (() => { })) { t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"]), this.isSurge() || this.isLoon() ? (this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.get(t, (t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) })) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { try { if (t.headers["set-cookie"]) { const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar } } catch (t) { this.logErr(t) } }).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => { const { message: s, response: i } = t; e(s, i, i && i.body) })) } post(t, e = (() => { })) { if (t.body && t.headers && !t.headers["Content-Type"] && (t.headers["Content-Type"] = "application/x-www-form-urlencoded"), t.headers && delete t.headers["Content-Length"], this.isSurge() || this.isLoon()) this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.post(t, (t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) }); else if (this.isQuanX()) t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => e(t)); else if (this.isNode()) { this.initGotEnv(t); const { url: s, ...i } = t; this.got.post(s, i).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => { const { message: s, response: i } = t; e(s, i, i && i.body) }) } } time(t, e = null) { const s = e ? new Date(e) : new Date; let i = { "M+": s.getMonth() + 1, "d+": s.getDate(), "H+": s.getHours(), "m+": s.getMinutes(), "s+": s.getSeconds(), "q+": Math.floor((s.getMonth() + 3) / 3), S: s.getMilliseconds() }; /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); for (let e in i) new RegExp("(" + e + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? i[e] : ("00" + i[e]).substr(("" + i[e]).length))); return t } msg(e = t, s = "", i = "", r) { const o = t => { if (!t) return t; if ("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { "open-url": t } : this.isSurge() ? { url: t } : void 0; if ("object" == typeof t) { if (this.isLoon()) { let e = t.openUrl || t.url || t["open-url"], s = t.mediaUrl || t["media-url"]; return { openUrl: e, mediaUrl: s } } if (this.isQuanX()) { let e = t["open-url"] || t.url || t.openUrl, s = t["media-url"] || t.mediaUrl; return { "open-url": e, "media-url": s } } if (this.isSurge()) { let e = t.url || t.openUrl || t["open-url"]; return { url: e } } } }; if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) { let t = ["", "==============📣系统通知📣=============="]; t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) } } log(...t) { t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator)) } logErr(t, e) { const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) } wait(t) { return new Promise(e => setTimeout(e, t)) } done(t = {}) { const e = (new Date).getTime(), s = (e - this.startTime) / 1e3; this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) } }(t, e) } diff --git a/脚本库/微信小程序/抓包版/索尼中国/2025-01-11_sonybbs_359e1e49.js b/脚本库/微信小程序/抓包版/索尼中国/2025-01-11_sonybbs_359e1e49.js new file mode 100644 index 0000000..093cb10 --- /dev/null +++ b/脚本库/微信小程序/抓包版/索尼中国/2025-01-11_sonybbs_359e1e49.js @@ -0,0 +1,291 @@ +// # Source: https://github.com/lksky8/sign-ql/blob/main/invalid/sonybbs.js +// # Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/sonybbs.js +// # Repo: lksky8/sign-ql +// # Path: invalid/sonybbs.js +// # UploadedAt: 2025-01-11T18:47:31Z +// # SHA256: 359e1e4984589cd0b5363e39c8ff9a566a54f3b5678cee3540b33ac3a546638a +// # Category: 微信小程序/抓包版 +// # Evidence: appid/openid/session_key/encryptedData等小程序字段 +// + +/** + 作者:https://github.com/lksky8/sign-ql + 日期:2022-11-23 + 网站:索尼中国APP + 功能:签到 + 变量:sonybbs='账号&密码' 多个账号用换行分割 + 定时:一天一次 + cron:5 0 * * * + */ + + const $ = new Env('索尼中国'); + const CryptoJS = require("crypto-js"); + const notify = $.isNode() ? require('./sendNotify') : ''; + const {log} = console; + const Notify = 1; //0为关闭通知,1为打开通知,默认为1 + ////////////////////// + let sonybbs = process.env.sonybbs; + let sonybbsArr = []; + let msg = ''; + let token = ''; + let name = ''; + + + !(async () => { + + if (!(await Envs())) + return; + else { + log(`\n\n============================================= \n脚本执行 - 北京时间(UTC+8):${new Date( + new Date().getTime() + new Date().getTimezoneOffset() * 60 * 1000 + + 8 * 60 * 60 * 1000).toLocaleString()} \n=============================================\n`); + + log(`\n=================== 共找到 ${sonybbsArr.length} 个账号 ===================`) + for (let index = 0; index < sonybbsArr.length; index++) { + + let num = index + 1 + log(`\n========= 开始【第 ${num} 个账号】=========\n`) + + sony = sonybbsArr[index].split('&'); + password=getpassword(sony[1]); + + msg += `\n第${num}个账号运行结果:` + + log('【开始登录】'); + await login(); + await $.wait(2 * 1000); + + log('【首页签到】'); + await appsignin(); + await $.wait(2 * 1000); + + log('【社区签到】'); + await bbssignin(); + await $.wait(2 * 1000); + + + log('【查询信息】'); + await info(); + await $.wait(2 * 1000); + + } + + } + await SendMsg(msg); + } + + )() + .catch((e) => log(e)) + .finally(() => $.done()) + + /** + * 登录 + */ + function login(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `https://www.sonystyle.com.cn/mysony/bbsapp/index.php?app=user&ac=api&ts=user_login&api=user`, + headers: { + "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1", + "Content-Type": "multipart/form-data; boundary=----WebKitFormBoundary5pkSjZVXTMJpiM9l", + "Accept-Encoding": "gzip, deflate, br" + }, + //body: `{"channel":"WAP","loginID":"${sony[0]}","password":"${password}"}`, + body: `------WebKitFormBoundary5pkSjZVXTMJpiM9l\nContent-Disposition: form-data; name=\"user_name\"\n\n${sony[0]}\n------WebKitFormBoundary5pkSjZVXTMJpiM9l\nContent-Disposition: form-data; name=\"channel\"\n\nwap\n------WebKitFormBoundary5pkSjZVXTMJpiM9l\nContent-Disposition: form-data; name=\"pwd\"\n\n${password}\n------WebKitFormBoundary5pkSjZVXTMJpiM9l\nContent-Disposition: form-data; name=\"swiperok\"\n\nfalse\n------WebKitFormBoundary5pkSjZVXTMJpiM9l\nContent-Disposition: form-data; name=\"setSessionId\"\n\n\n------WebKitFormBoundary5pkSjZVXTMJpiM9l\nContent-Disposition: form-data; name=\"setToken\"\n\n\n------WebKitFormBoundary5pkSjZVXTMJpiM9l\nContent-Disposition: form-data; name=\"setScene\"\n\nnc_message_h5\n------WebKitFormBoundary5pkSjZVXTMJpiM9l\nContent-Disposition: form-data; name=\"setSig\"\n\n\n------WebKitFormBoundary5pkSjZVXTMJpiM9l--`, + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.msg == '已登录') { + log(`\n账号[${result.data.username}]登录成功`) + token = result.data['access_token']; + name = result.data.username; + } else { + loginBack = 1; + log(`【登录失败】${result.message} `) + msg += `\n【登录失败】${result.message}` + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) + } + + /** + * 查询资产 + */ + function info(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `https://www.sonystyle.com.cn/mysony/bbsapp/index.php?app=user&ac=api&api=user&ts=getUserinfo`, + headers: { + "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1", + "Content-Type": "application/json", + "Authorization": `Bearer ${token}` + }, + body: '', + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.code == 101) { + log(`查询资产失败`) + } else { + log(`账号[${name}]成长值:${result.data.level},等级:${result.data['user_level_text']},社区点数:${result.data.allscore}`) + msg += `\n账号[${name}]成长值:${result.data.level},等级:${result.data['user_level_text']},社区点数:${result.data.allscore}` + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) + } + + /** + * 首页签到 + */ + function appsignin(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `https://www.sonystyle.com.cn/eSolverOmniChannel/account/signupPoints.do?channel=WAP`, + headers: { + "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1", + "Content-Type": "application/json", + "Authorization": `Bearer ${token}` + }, + body: '', + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.resultMsg[0].code == '99') { + log(`账号[${name}]APP首页签到失败:已经签到过了`) + msg += `\n账号[${name}]APP首页签到失败:已经签到过了` + } else { + log(`账号[${name}]APP首页签到成功,今天是第${result.resultData.signupRankingOfDay}个完成签到,目前成长值是:${result.resultData.totalPoints}`) + msg += `\n账号[${name}]APP首页签到成功,今天是第${result.resultData.signupRankingOfDay}个完成签到` + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) + } + + /** + * 社区签到 + */ + function bbssignin(timeout = 3 * 1000) { + return new Promise((resolve) => { + let url = { + url: `https://www.sonystyle.com.cn/mysony/bbsapp/index.php?app=user&ac=api&api=user&ts=signin`, + headers: { + "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1", + "Content-Type": "application/json", + "Authorization": `Bearer ${token}` + }, + body: '', + } + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.code == '112') { + log(`账号[${name}]索尼社区签到失败:已经签到过了`) + msg += `\n账号[${name}]索尼社区签到失败:已经签到过了` + } else { + log(`账号[${name}]索尼社区签到成功,${result.msg}`) + msg += `\n账号[${name}]索尼社区签到成功,${result.msg}` + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) + } +// ============================================变量检查============================================ \\ + async function Envs() { + if (sonybbs) { + if (sonybbs.indexOf("\n") != -1) { + sonybbs.split("\n").forEach((item) => { + sonybbsArr.push(item); + }); + } else { + sonybbsArr.push(sonybbs); + } + } else { + log(`\n 【${$.name}】:未填写变量 sonybbs`) + return; + } + + return true; + } + + // ============================================发送消息============================================ \\ + async function SendMsg(message) { + if (!message) + return; + + if (Notify > 0) { + if ($.isNode()) { + var notify = require('./sendNotify'); + await notify.sendNotify($.name, message); + } else { + $.msg(message); + } + } else { + log(message); + } + } + + /** + * 随机数生成 + */ + function randomString(e) { + e = e || 32; + var t = "QWERTYUIOPASDFGHJKLZXCVBNM1234567890", + a = t.length, + n = ""; + for (i = 0; i < e; i++) + n += t.charAt(Math.floor(Math.random() * a)); + return n + } + + function getpassword(text){ + var key = CryptoJS.enc.Utf8.parse("qydjwjqp4me3rnitdptf7eyznva357fp") + var encryptedData = CryptoJS.AES.encrypt(text, key, { + mode: CryptoJS.mode.ECB, + padding: CryptoJS.pad.Pkcs7 + }); + return encryptedData; + } + + /** + * 修改配置文件 + */ + function modify() { + + fs.readFile('/ql/data/config/config.sh','utf8',function(err,dataStr){ + if(err){ + return log('读取文件失败!'+err) + } + else { + var result = dataStr.replace(/regular/g,string); + fs.writeFile('/ql/data/config/config.sh', result, 'utf8', function (err) { + if (err) {return log(err);} + }); + } + }) + } + + function Env(t, e) { "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); class s { constructor(t) { this.env = t } send(t, e = "GET") { t = "string" == typeof t ? { url: t } : t; let s = this.get; return "POST" === e && (s = this.post), new Promise((e, i) => { s.call(this, t, (t, s, r) => { t ? i(t) : e(s) }) }) } get(t) { return this.send.call(this.env, t) } post(t) { return this.send.call(this.env, t, "POST") } } return new class { constructor(t, e) { this.name = t, this.http = new s(this), this.data = null, this.dataFile = "box.dat", this.logs = [], this.isMute = !1, this.isNeedRewrite = !1, this.logSeparator = "\n", this.startTime = (new Date).getTime(), Object.assign(this, e), this.log("", `🔔${this.name}, 开始!`) } isNode() { return "undefined" != typeof module && !!module.exports } isQuanX() { return "undefined" != typeof $task } isSurge() { return "undefined" != typeof $httpClient && "undefined" == typeof $loon } isLoon() { return "undefined" != typeof $loon } toObj(t, e = null) { try { return JSON.parse(t) } catch { return e } } toStr(t, e = null) { try { return JSON.stringify(t) } catch { return e } } getjson(t, e) { let s = e; const i = this.getdata(t); if (i) try { s = JSON.parse(this.getdata(t)) } catch { } return s } setjson(t, e) { try { return this.setdata(JSON.stringify(t), e) } catch { return !1 } } getScript(t) { return new Promise(e => { this.get({ url: t }, (t, s, i) => e(i)) }) } runScript(t, e) { return new Promise(s => { let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); i = i ? i.replace(/\n/g, "").trim() : i; let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; const [o, h] = i.split("@"), n = { url: `http://${h}/v1/scripting/evaluate`, body: { script_text: t, mock_type: "cron", timeout: r }, headers: { "X-Key": o, Accept: "*/*" } }; this.post(n, (t, e, i) => s(i)) }).catch(t => this.logErr(t)) } loaddata() { if (!this.isNode()) return {}; { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e); if (!s && !i) return {}; { const i = s ? t : e; try { return JSON.parse(this.fs.readFileSync(i)) } catch (t) { return {} } } } } writedata() { if (this.isNode()) { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e), r = JSON.stringify(this.data); s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) } } lodash_get(t, e, s) { const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); let r = t; for (const t of i) if (r = Object(r)[t], void 0 === r) return s; return r } lodash_set(t, e, s) { return Object(t) !== t ? t : (Array.isArray(e) || (e = e.toString().match(/[^.[\]]+/g) || []), e.slice(0, -1).reduce((t, s, i) => Object(t[s]) === t[s] ? t[s] : t[s] = Math.abs(e[i + 1]) >> 0 == +e[i + 1] ? [] : {}, t)[e[e.length - 1]] = s, t) } getdata(t) { let e = this.getval(t); if (/^@/.test(t)) { const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : ""; if (r) try { const t = JSON.parse(r); e = t ? this.lodash_get(t, i, "") : e } catch (t) { e = "" } } return e } setdata(t, e) { let s = !1; if (/^@/.test(e)) { const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i), h = i ? "null" === o ? null : o || "{}" : "{}"; try { const e = JSON.parse(h); this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i) } catch (e) { const o = {}; this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i) } } else s = this.setval(t, e); return s } getval(t) { return this.isSurge() || this.isLoon() ? $persistentStore.read(t) : this.isQuanX() ? $prefs.valueForKey(t) : this.isNode() ? (this.data = this.loaddata(), this.data[t]) : this.data && this.data[t] || null } setval(t, e) { return this.isSurge() || this.isLoon() ? $persistentStore.write(t, e) : this.isQuanX() ? $prefs.setValueForKey(t, e) : this.isNode() ? (this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0) : this.data && this.data[e] || null } initGotEnv(t) { this.got = this.got ? this.got : require("got"), this.cktough = this.cktough ? this.cktough : require("tough-cookie"), this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar, t && (t.headers = t.headers ? t.headers : {}, void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar)) } get(t, e = (() => { })) { t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"]), this.isSurge() || this.isLoon() ? (this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.get(t, (t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) })) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { try { if (t.headers["set-cookie"]) { const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar } } catch (t) { this.logErr(t) } }).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => { const { message: s, response: i } = t; e(s, i, i && i.body) })) } post(t, e = (() => { })) { if (t.body && t.headers && !t.headers["Content-Type"] && (t.headers["Content-Type"] = "application/x-www-form-urlencoded"), t.headers && delete t.headers["Content-Length"], this.isSurge() || this.isLoon()) this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.post(t, (t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) }); else if (this.isQuanX()) t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => e(t)); else if (this.isNode()) { this.initGotEnv(t); const { url: s, ...i } = t; this.got.post(s, i).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => { const { message: s, response: i } = t; e(s, i, i && i.body) }) } } time(t, e = null) { const s = e ? new Date(e) : new Date; let i = { "M+": s.getMonth() + 1, "d+": s.getDate(), "H+": s.getHours(), "m+": s.getMinutes(), "s+": s.getSeconds(), "q+": Math.floor((s.getMonth() + 3) / 3), S: s.getMilliseconds() }; /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); for (let e in i) new RegExp("(" + e + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? i[e] : ("00" + i[e]).substr(("" + i[e]).length))); return t } msg(e = t, s = "", i = "", r) { const o = t => { if (!t) return t; if ("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { "open-url": t } : this.isSurge() ? { url: t } : void 0; if ("object" == typeof t) { if (this.isLoon()) { let e = t.openUrl || t.url || t["open-url"], s = t.mediaUrl || t["media-url"]; return { openUrl: e, mediaUrl: s } } if (this.isQuanX()) { let e = t["open-url"] || t.url || t.openUrl, s = t["media-url"] || t.mediaUrl; return { "open-url": e, "media-url": s } } if (this.isSurge()) { let e = t.url || t.openUrl || t["open-url"]; return { url: e } } } }; if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) { let t = ["", "==============📣系统通知📣=============="]; t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) } } log(...t) { t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator)) } logErr(t, e) { const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) } wait(t) { return new Promise(e => setTimeout(e, t)) } done(t = {}) { const e = (new Date).getTime(), s = (e - this.startTime) / 1e3; this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) } }(t, e) } diff --git a/脚本库/微信小程序/抓包版/统一茄皇-修复版/2023-01-03_tyqh_2fe80596.js b/脚本库/微信小程序/抓包版/统一茄皇-修复版/2023-01-03_tyqh_2fe80596.js new file mode 100644 index 0000000..21afc45 --- /dev/null +++ b/脚本库/微信小程序/抓包版/统一茄皇-修复版/2023-01-03_tyqh_2fe80596.js @@ -0,0 +1,1577 @@ +// # Source: https://github.com/lksky8/sign-ql/blob/main/invalid/tyqh.js +// # Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/tyqh.js +// # Repo: lksky8/sign-ql +// # Path: invalid/tyqh.js +// # UploadedAt: 2023-01-03T11:39:58Z +// # SHA256: 2fe8059609f086f32865e2d2463e2e54b532cae84923ca73cb64cf6d5432509c +// # Category: 微信小程序/抓包版 +// # Evidence: appid/openid/session_key/encryptedData等小程序字段 +// + +/** + 原作者:临渊 + 修改日期:2022-11-15 + 作者:https://github.com/lksky8/sign-ql + 小程序:统一快乐星球 + 入口:活动->种番茄 + 功能:除了助力都能完成 + 抓包:https://apig.xiaoyisz.com/qiehuang/ga/public/api/login 这个登录包里 body 部分的 全部 + 变量:tybody='body@xxxx ' 多个账号用 @ 或者 换行 分割 + 定时一天三次,八个小时一次收取冒险奖励 + cron: 10 12,18 * * * + */ + + const $ = new Env("统一茄皇-修复版"); + const crypto = require('crypto'); + const notify = $.isNode() ? require("./sendNotify") : ""; + const { log } = console; + const Notify = 1; //0为关闭通知,1为打开通知,默认为1 + const uaNum = 21; //随机UA,从0-22随便选一个填上去 + ////////////////////// + let tyau = ""; + let tybody = ($.isNode() ? process.env.tybody : $.getdata("tybody")) || ""; + let UA = ($.isNode() ? process.env.UA : $.getdata("UA")) || ""; + let UAArr = []; + let tybodyArr = []; + let newAuArr = []; + let tyPlantId = ""; + let plantIdArr = []; + let auback = 0; + let data = ""; + let msg = ""; + let taskType = 0; + let taskBack = []; + let taskTypeArr = []; + let taskId = ""; + let taskIdArr = []; + let challengeId = ""; + let adventureId = ""; + let name = ""; + let id = ""; + let idArr = []; + let progress = 0.0; + let plantStage = 0; + let plantStatus = ""; + let helpTaskId = ""; + let helpTaskIdArr = []; + let giveSunshineBack = 0; + let stealFull = false; + + const User_Agents = [ + "Mozilla/5.0 (Linux; Android 10; ONEPLUS A5010 Build/QKQ1.191014.012; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045230 Mobile Safari/537.36", + "Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148", + "Mozilla/5.0 (Linux; Android 9; Mi Note 3 Build/PKQ1.181007.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045131 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; GM1910 Build/QKQ1.190716.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045230 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; 16T Build/PKQ1.190616.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/044942 Mobile Safari/537.36", + "Mozilla/5.0 (iPhone; CPU iPhone OS 13_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148", + "Mozilla/5.0 (iPhone; CPU iPhone OS 13_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148", + "Mozilla/5.0 (iPhone; CPU iPhone OS 14_2 like Mac OS X) AppleWebKit/532.0 (KHTML, like Gecko) CriOS/43.0.823.0 Mobile/65M532 Safari/532.0", + "Mozilla/5.0 (iPod; U; CPU iPhone OS 3_1 like Mac OS X; rw-RW) AppleWebKit/531.9.3 (KHTML, like Gecko) Version/4.0.5 Mobile/8B118 Safari/6531.9.3", + "Mozilla/5.0 (Linux; Android 9; MI 6 Build/PKQ1.190118.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/044942 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 11; Redmi K30 5G Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045511 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; ONEPLUS A6000 Build/QKQ1.190716.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045224 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 9; MHA-AL00 Build/HUAWEIMHA-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/044942 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.0.0; HTC U-3w Build/OPR6.170623.013; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/044942 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; LYA-AL00 Build/HUAWEILYA-AL00L; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045230 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.1.0; MI 8 Build/OPM1.171019.026; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/045131 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; Redmi K20 Pro Premium Edition Build/QKQ1.190825.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045227 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 8.1.0; 16 X Build/OPM1.171019.026; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/6.2 TBS/044942 Mobile Safari/537.36", + "Mozilla/5.0 (Linux; Android 10; M2006J10C Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/77.0.3865.120 MQQBrowser/6.2 TBS/045230 Mobile Safari/537.36", + "Mozilla/5.0 (iPhone; CPU iPhone OS 13_7 like Mac OS X) AppleWebKit/532.0 (KHTML, like Gecko) FxiOS/18.2n0520.0 Mobile/50C216 Safari/532.0", + "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.28(0x18001c29) NetType/WIFI", + "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 MicroMessenger/7.0.9.501 NetType/WIFI MiniProgramEnv/Windows WindowsWechat" + ]; + let ua = User_Agents[uaNum]; + + !(async () => { + if (typeof $request !== "undefined") { + await GetRewrite(); + } else { + if (!(await Envs())) return; + else { + log( + `\n\n============================================= \n脚本执行 - 北京时间(UTC+8):${new Date( + new Date().getTime() + + new Date().getTimezoneOffset() * 60 * 1000 + + 8 * 60 * 60 * 1000 + ).toLocaleString()} \n=============================================\n` + ); + + log( + `\n=================== 共找到 ${tybodyArr.length} 个账号 ===================` + ); + for (let index = 0; index < tybodyArr.length; index++) { + ua = User_Agents[uaNum + index]; + + if (UA) { + if (index >= UAArr.length) { + let i = UAArr.length + randomInt(0, 2); + ua = User_Agents[uaNum + i]; + } else ua = UAArr[index]; + } + + tybody = tybodyArr[index]; + let num = index + 1; + + log(`\n========= 开始【第 ${num} 个账号】=========\n`); + msg += `\n第${num}个账号运行结果:`; + + log("【开始获取AU】"); + await refreshAu(); + await $.wait(2 * 1000); + newAuArr[index] = tyau; + + log("【开始查询任务】"); + await getTask(); + await $.wait(2 * 1000); + helpTaskIdArr[index] = helpTaskId; + + if (auback != 1) { + for (let i = 0; i < 10; i++) { + if (taskBack[i]) { + if (i == 0) { + log(`\n助力任务还未完成,建议执行互助\n`); + } else + log(`【第${i + 1}个任务未完成,开始执行第${i + 1}个任务】`); + await report(i); + if (i == 2) { + await report(i); + await report(i); + await report(i); + await report(i); + } + await $.wait(2 * 1000); + await getDrawPriz(i); + await $.wait(2 * 1000); + } + } + + log("【开始收取阳光】"); + await getSunshine(); + await $.wait(2 * 1000); + + log("【开始进行挑战】"); + await startCallenge(); + await $.wait(2 * 1000); + + log("【开始查询冒险奖励】"); + await queryAdventure(); + await $.wait(2 * 1000); + + log("【开始获取植物详情】"); + await getPlant(index); + await $.wait(2 * 1000); + plantIdArr[index] = tyPlantId; + + log("【开始洒阳光】"); + do { + await giveSunshine(); + await $.wait(2 * 1000); + } while (giveSunshineBack == 1); + + log("【开始获取植物详情】"); + await getPlant(index); + await $.wait(2 * 1000); + + log("【开始偷好友阳光】"); + const stealAll = await stealFriendSunshine(); + msg += `\n共偷取好友阳光${stealAll}g`; + + log("【开始查询信息】"); + await getUserInfo(); + await $.wait(2 * 1000); + + idArr[index] = id; + } + } + await SendMsg(msg); + } + } + })() + .catch((e) => log(e)) + .finally(() => $.done()); + + /** + * 获取AU + */ + function refreshAu(timeout = 2 * 1000) { + let url = { + url: `https://apig.xiaoyisz.com/qiehuang/ga/public/api/login`, + headers: { + Host: "apig.xiaoyisz.com", + "user-agent": `${ua}`, + "Content-Type": "application/json", + }, + body: `${tybody}`, + }; + return new Promise((resolve) => { + $.post( + url, + async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.code == 0) { + log(`获取AU成功`); + tyau = result.data; + } else if (result.code == 500) { + log( + `获取AU失败,请检查你的变量是否正确,如正确更换到环境变量或者配置文件重试` + ); + auback = 1; + } else { + log(`获取AU失败,原因是:${result.message}`); + } + } catch (e) { + log(e); + } finally { + resolve(); + } + }, + timeout + ); + }); + } + + /** + * 偷朋友阳光 + */ + async function stealFriendSunshine(timeout = 2 * 1000) { + //--0 先获取好友列表 + let url = { + url: 'https://apig.xiaoyisz.com/qiehuang/ga/user/friend/list?'+sign()+`&page=1&size=50`, + headers: { + Host: "apig.xiaoyisz.com", + authorization: `${tyau}`, + "user-agent": `${ua}`, + "Content-Type": "application/json", + }, + }; + return new Promise(async (resolve) => { + $.get( + url, + async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.code == 904) { + refreshAu(); + } else if (result.code === 0) { + const { + data: { content }, + } = result; + if (content.length > 0) { + //--1 过滤可偷好友列表 + const stealList = content.filter((it) => it.stealAble); + log("可偷好友列表为", stealList.length); + if (stealList.length > 0) { + //--2 偷 然后汇总偷取的阳光 + const stealNums = await stealList.reduce(async (pre, curt) => { + // 这里是关键,需要 await 前一个 task 执行的结果 + // 实际上每个 reduce 每个循环执行都相当于 new Promise + // 但第二次执行可以拿到上一次执行的结果,也就是上一个 Promise + // 每次执行只要 await 上一个 Promise,即可实现依次执行 + const prev = await pre; + if (stealFull) { + console.log("最多偷取10人,不再偷取"); + return prev; + } else { + const next = await stealSunshine(curt.userId); + await $.wait(2 * 1000); + return prev + next; + } + }, 0); + console.log("偷取的数据", stealNums); + + resolve(stealNums); + } else resolve(0); + } else { + log(`没有好友,退出`); + resolve(0); + } + } else { + log(`遇到错误,原因是:${result.message}`); + resolve(0); + } + } catch (e) { + log(e); + } finally { + resolve(0); + } + }, + timeout + ); + }); + } + /** + * 偷好友阳光 + */ + function stealSunshine(userId, timeout = 2 * 1000) { + return new Promise((resolve) => { + let url = { + url: + 'https://apig.xiaoyisz.com/qiehuang/ga/user/daily/steal?'+sign()+'&friendUserId='+userId, + headers: { + Host: "apig.xiaoyisz.com", + authorization: `${tyau}`, + "user-agent": `${ua}`, + "Content-Type": "application/json", + }, + }; + $.get( + url, + async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.code == 904) { + refreshAu(); + } else if (result.code === 0) { + const { data: stealData } = result; + if (stealData > 0) { + log(`偷到好友阳光 ${stealData}g`); + return resolve(stealData); + } else return resolve(0); + } else { + log(`遇到错误,原因是:${JSON.stringify(result)}`); + stealFull = true; + resolve(0); + } + } catch (e) { + log(e); + stealFull = true; + resolve(0); + } + }, + timeout + ); + }); + } + + /** + * 上报任务 + */ + function report(num) { + let url = { + url: `https://apig.xiaoyisz.com/qiehuang/ga/user/task/report?`+sign()+`&taskType=${taskTypeArr[num]}&attachId=${timestampMs()}&taskId=${taskIdArr[num]}`, + headers: { + Host: "apig.xiaoyisz.com", + authorization: `${tyau}`, + "user-agent": `${ua}`, + "content-type": "application/json", + }, + }; + return new Promise((resolve) => { + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.code == 904) { + refreshAu(); + } + if (result.code == 902) { + auback = 1; + log(`AU失效,请重抓`); + msg += `\nAU失效,请重抓`; + } else if (result.data.status === 1) { + log(`上报任务成功`); + } else if (result.data.status == -2 || result.data.status == 2) { + log(`上报任务失败,可能是已经完成`); + } else { + log(`上报任务失败,原因是:${result.message}`); + } + } catch (e) { + log(e); + } finally { + resolve(); + } + }); + }); + } + + /** + * 领取奖励 + */ + function getDrawPriz(num) { + let url = { + url: `https://apig.xiaoyisz.com/qiehuang/ga/user/task/drawPrize?`+sign()+`&taskId=${taskIdArr[num]}`, + headers: { + Host: "apig.xiaoyisz.com", + authorization: `${tyau}`, + "user-agent": `${ua}`, + "content-type": "application/json", + }, + }; + return new Promise((resolve) => { + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.code == 904) { + refreshAu(); + } + if (result.code == 902) { + auback = 1; + log(`AU失效,请重抓`); + msg += `\nAU失效,请重抓`; + } else if (result.code === 1000) { + log(`任务不是待领取状态`); + } else if (result.code == 0) { + let back = eval(result.data); + log(`[${back.name}]任务领取奖励成功`); + } else { + log(`任务领取奖励失败,原因是:${result.message}`); + } + } catch (e) { + log(e); + } finally { + resolve(); + } + }); + }); + } + + /** + * 获取任务 + */ + function getTask(timeout = 2 * 1000) { + let url = { + url: 'https://apig.xiaoyisz.com/qiehuang/ga/user/task/list?'+sign(), + headers: { + Host: "apig.xiaoyisz.com", + authorization: `${tyau}`, + "user-agent": `${ua}`, + "content-type": "application/json", + }, + }; + return new Promise((resolve) => { + $.get( + url, + async (error, response, data) => { + try { + let result = JSON.parse(data); + let back = eval(result); + if (result.code == 901 || result.code == 902 || result.code == 903) { + auback = 1; + log(`AU错误,可能是获取失败,请更换到环境变量或配置文件重试`); + msg += `\nAU错误,可能是获取失败,请更换到环境变量或配置文件重试`; + } + if (auback != 1 && result.code == 0) { + log(`获取任务列表成功`); + for (let i = 0; i < 10; i++) { + if (i == 0) { + helpTaskId = back.data[i].taskId; + } + taskType = back.data[i].taskType; + taskTypeArr[i] = taskType; + taskId = back.data[i].taskId; + taskIdArr[i] = taskId; + if (back.data[i].completeTimes != back.data[i].retryTimes) { + taskBack[i] = 1; + } + } + } + } catch (e) { + log(e); + } finally { + resolve(); + } + }, + timeout + ); + }); + } + + /** + * 获取植物详情 + */ + function getPlant(num) { + let url = { + url: 'https://apig.xiaoyisz.com/qiehuang/ga/plant/info?'+sign(), + headers: { + Host: "apig.xiaoyisz.com", + authorization: `${tyau}`, + "user-agent": `${ua}`, + "content-type": "application/json", + }, + }; + return new Promise((resolve) => { + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + let back = eval(result); + if (result.code == 904) { + refreshAu(); + } + if (result.data.stage == -1) { + await $.wait(2 * 1000); + getNewPlant(); + } + if (result.code == 0) { + log(`获取植物详情成功`); + tyPlantId = result.data.plantId; + progress = + +result.data.currentSunshineNum / result.data.needSunshineNum; + progress = progress * 100; + progress = progress.toFixed(2); + plantStage = +result.data.stage; + } else log(`获取植物详情失败`); + } catch (e) { + log(e); + } finally { + resolve(); + } + }); + }); + } + + /** + * 开始挑战 + */ + function startCallenge(timeout = 2 * 1000) { + let url = { + url: 'https://apig.xiaoyisz.com/qiehuang/ga/challenge/start?'+sign(), + headers: { + Host: "apig.xiaoyisz.com", + authorization: `${tyau}`, + "user-agent": `${ua}`, + "content-type": "application/json", + }, + }; + return new Promise((resolve) => { + $.get( + url, + async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.code == 904) { + refreshAu(); + } + if (auback != 1 && result.code == 0) { + challengeId = result.data; + reportCallenge(); + $.wait(2 * 1000); + } else if (result.code == 1000) { + log(`开始挑战失败,次数不足`); + } + } catch (e) { + log(e); + } finally { + resolve(); + } + }, + timeout + ); + }); + } + + /** + * 上报挑战 + */ + function reportCallenge(timeout = 2 * 1000) { + let url = { + url: 'https://apig.xiaoyisz.com/qiehuang/ga/challenge/report?'+sign(), + headers: { + Host: "apig.xiaoyisz.com", + authorization: `${tyau}`, + "user-agent": `${ua}`, + "Content-Type": "application/json", + }, + body: `{"battleId":${challengeId},"result":1,"costMillisecond":${randomInt( + 6500, + 12000 + )}}`, + }; + return new Promise((resolve) => { + $.post( + url, + async (error, response, data) => { + try { + let result = JSON.parse(data); + let back = eval(result.data); + if (result.code == 904) { + refreshAu(); + } + if (auback != 1 && result.code == 0) { + log(`挑战成功`); + startCallenge(); + } else log("挑战次数不足"); + } catch (e) { + log(e); + } finally { + resolve(); + } + }, + timeout + ); + }); + } + + /** + * 开始冒险 + */ + function startAdventure(timeout = 2 * 1000) { + let url = { + url: 'https://apig.xiaoyisz.com/qiehuang/ga/user/adventure/start?'+sign(), + headers: { + Host: "apig.xiaoyisz.com", + authorization: `${tyau}`, + "user-agent": `${ua}`, + "content-type": "application/json", + }, + }; + return new Promise((resolve) => { + $.get( + url, + async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.code == 904) { + refreshAu(); + } + if (result.code == 0) { + log("冒险开始成功"); + } else if (result.code == 1000) { + log(`冒险开始失败,可能是上报异常或者当前已有冒险`); + } else log(`${result.message}`); + } catch (e) { + log(e); + } finally { + resolve(); + } + }, + timeout + ); + }); + } + + /** + * 查询冒险 + */ + function queryAdventure(timeout = 2 * 1000) { + let url = { + url: 'https://apig.xiaoyisz.com/qiehuang/ga/user/adventure/info?'+sign()+'&userId=-1&type=2', + headers: { + Host: "apig.xiaoyisz.com", + authorization: `${tyau}`, + "user-agent": `${ua}`, + "content-type": "application/json", + }, + }; + return new Promise((resolve) => { + $.get( + url, + async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.code == 904) { + refreshAu(); + } + if (result.code == 0) { + adventureId = result.data.adventureId; + if (timestampS() >= result.data.endTime) { + reportAdventure(); + } else { + let sleepTime = +result.data.endTime - timestampS(); + if (sleepTime <= 60) { + log(`距离冒险结束小于一分钟,等待${sleepTime}秒后收取冒险奖励`); + await sleep(sleepTime * 1000); + reportAdventure(); + } else + log( + `距离冒险结束还有:${parseInt( + sleepTime / 3600 + )}小时${parseInt((sleepTime % 3600) / 60)}分钟${parseInt( + sleepTime % 60 + )}秒,大于一分钟,不进行等待` + ); + } + } else log("查询上一次冒险失败,可能是未进行"); + } catch (e) { + log(e); + } finally { + resolve(); + } + }, + timeout + ); + }); + } + + /** + * 上报冒险 + */ + function reportAdventure(timeout = 2 * 1000) { + let url = { + url: 'https://apig.xiaoyisz.com/qiehuang/ga/user/adventure/drawPrize?'+sign()+`&adventureId=${adventureId}`, + headers: { + Host: "apig.xiaoyisz.com", + authorization: `${tyau}`, + "user-agent": `${ua}`, + "Content-Type": "application/json", + }, + }; + return new Promise((resolve) => { + $.get( + url, + async (error, response, data) => { + try { + let result = JSON.parse(data); + let back = eval(result.data); + if (result.code == 904) { + refreshAu(); + } + if (result.code == 0) { + log(`冒险收取成功`); + } else if (result.code == 500) { + log(`当前无可收取的冒险`); + } else if (result.code == 1000) { + log(`冒险已收取`); + } else log("冒险未到时间"); + } catch (e) { + log(e); + } finally { + resolve(); + } + }, + timeout + ); + }); + } + + /** + * 洒阳光 + */ + function giveSunshine(timeout = 2 * 1000) { + let url = { + url: 'https://apig.xiaoyisz.com/qiehuang/ga/plant/batchgiveSunshine?'+sign()+`&plantId=${tyPlantId}`, + headers: { + Host: "apig.xiaoyisz.com", + authorization: `${tyau}`, + "user-agent": `${ua}`, + "content-type": "application/json", + }, + }; + return new Promise((resolve) => { + $.get( + url, + async (error, response, data) => { + try { + let result = JSON.parse(data); + let back = eval(result.data); + if (result.code == 904) { + refreshAu(); + } + if (result.message == "已达到收获阶段") { + log("【开始收取植物】"); + $.wait(2 * 1000); + getHarvest(); + } else if (result.message == "plantId错误") { + log(`plantId错误,可能是运行的bug,不用管`); + } else if (result.message == "只能给自己批量洒阳光") { + log("只能给自己批量洒阳光"); + } else if (result.message == "阳光不足") { + log("阳光不足"); + giveSunshineBack = 0; + } else if (result.message != "阳光不足") { + log("洒阳光成功"); + if (back.currentSunshineNum == back.needSunshineNum) { + $.wait(3 * 1000); + upgrade(); + } + giveSunshineBack = 1; + } + } catch (e) { + log(e); + } finally { + resolve(); + } + }, + timeout + ); + }); + } + + /** + * 浇水 + */ + function upgrade(timeout = 2 * 1000) { + let url = { + url: 'https://apig.xiaoyisz.com/qiehuang/ga/plant/upgrade?'+sign()+`&plantId=${tyPlantId}`, + headers: { + Host: "apig.xiaoyisz.com", + authorization: `${tyau}`, + "user-agent": `${ua}`, + "content-type": "application/json", + }, + }; + return new Promise((resolve) => { + $.get( + url, + async (error, response, data) => { + try { + let result = JSON.parse(data); + let back = eval(result.data); + if (result.code == 904) { + refreshAu(); + } + if (result.code == 0) { + log("浇水升级成功"); + } + } catch (e) { + log(e); + } finally { + resolve(); + } + }, + timeout + ); + }); + } + + /** + * 查询番茄余额 + */ + function getTomato(timeout = 2 * 1000) { + let url = { + url: 'https://apig.xiaoyisz.com/qiehuang/ga/user/info?'+sign(), + headers: { + Host: "apig.xiaoyisz.com", + authorization: `${tyau}`, + "user-agent": `${ua}`, + "Content-Type": "application/json", + }, + }; + return new Promise((resolve) => { + $.get( + url, + async (error, response, data) => { + try { + let result = JSON.parse(data); + let back = eval(result.data); + if (result.code == 904) { + refreshAu(); + } + if (result.code == 0) { + if (plantStage == 0) { + plantStatus = "发育期"; + } else if (plantStage == 1) { + plantStatus = "幼苗期"; + } else if (plantStage == 2) { + plantStatus = "开花期"; + } else if (plantStage == 3) { + plantStatus = "结果期"; + } + log( + `查询成功,账号[${name}]番茄余额为:${back.tomatoNum},植物状态为:${plantStatus},进度:${progress}%` + ); + msg += `\n账号[${name}]番茄余额为:${back.tomatoNum},植物状态为:${plantStatus},进度:${progress}%`; + } + } catch (e) { + log(e); + } finally { + resolve(); + } + }, + timeout + ); + }); + } + + /** + * 收取阳光 + */ + function getSunshine(timeout = 2 * 1000) { + let url = { + url: 'https://apig.xiaoyisz.com/qiehuang/ga/user/daily/pickup?'+sign(), + headers: { + Host: "apig.xiaoyisz.com", + authorization: `${tyau}`, + "user-agent": `${ua}`, + "content-type": "application/json", + }, + }; + return new Promise((resolve) => { + $.get( + url, + async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.code == 904) { + refreshAu(); + } + if (result.code == 0) { + log("收取阳光成功"); + } else if (result.code == 1000) { + log("收取阳光失败,无可收取的阳光"); + } else log(`收取失败,原因是:${result.message}`); + } catch (e) { + log(e); + } finally { + resolve(); + } + }, + timeout + ); + }); + } + + /** + * 收植物 + */ + function getHarvest(timeout = 2 * 1000) { + let url = { + url: 'https://apig.xiaoyisz.com/qiehuang/ga/plant/harvest?'+sign()+`&plantId=${tyPlantId}`, + headers: { + Host: "apig.xiaoyisz.com", + authorization: `${tyau}`, + "user-agent": `${ua}`, + "Content-Type": "application/json", + }, + }; + return new Promise((resolve) => { + $.get( + url, + async (error, response, data) => { + try { + let result = JSON.parse(data); + let back = eval(result.data); + if (result.code == 904) { + refreshAu(); + } + if (result.code == 0) { + log(`植物奖励收取成功,获得${back.infos[0].num}个番茄`); + getNewPlant(); + } else if (result.code == 1000) { + log(`植物奖励已收取`); + } else log(`植物奖励收取失败,原因是:${result.message}`); + } catch (e) { + log(e); + } finally { + resolve(); + } + }, + timeout + ); + }); + } + + /** + * 种植物 + */ + function getNewPlant(timeout = 2 * 1000) { + let url = { + url: `https://apig.xiaoyisz.com/qiehuang/ga/plant/start?`+sign(), + headers: { + Host: "apig.xiaoyisz.com", + authorization: `${tyau}`, + "user-agent": `${ua}`, + "Content-Type": "application/json", + }, + }; + return new Promise((resolve) => { + $.get( + url, + async (error, response, data) => { + try { + let result = JSON.parse(data); + let back = eval(result.data); + if (result.code == 904) { + refreshAu(); + } + if (result.code == 0) { + log(`种新的植物成功`); + await $.wait(2 * 1000); + getPlant(); + await $.wait(2 * 1000); + giveSunshine(); + } else if (result.code == 1000) { + log(`种失败,原因是:已种植`); + } else log(`种新的植物失败,原因是:${result.message}`); + } catch (e) { + log(e); + } finally { + resolve(); + } + }, + timeout + ); + }); + } + + /** + * 获取信息 + */ + function getUserInfo(timeout = 2 * 1000) { + let url = { + url: `https://apig.xiaoyisz.com/qiehuang/ga/user/info?`+sign(), + headers: { + Host: "apig.xiaoyisz.com", + authorization: `${tyau}`, + "user-agent": `${ua}`, + "Content-Type": "application/json", + }, + }; + return new Promise((resolve) => { + $.get( + url, + async (error, response, data) => { + try { + let result = JSON.parse(data); + let back = eval(result.data); + if (result.code == 904) { + refreshAu(); + } + if (result.code == 0) { + name = back.nickName; + id = back.id; + await $.wait(2 * 1000); + getTomato(); + } else log(`获取信息失败,原因是:${result.message}`); + } catch (e) { + log(e); + } finally { + resolve(); + } + }, + timeout + ); + }); + } + + // ============================================重写============================================ \\ + async function GetRewrite() { + if ($request.url.indexOf("qiehuang/ga/public/api/login") > -1) { + const ck = $request.body; + if (tybody) { + if (tybody.indexOf(ck) == -1) { + tybody = tybody + "@" + ck; + let tyhz = tyhz + "@" + ck; + $.setdata(tybody, "tybody"); + $.setdata(tybody, "tyhz"); + List = tybody.split("@"); + $.msg( + $.name + + ` 获取第${tybody.length}个 ck 成功: ${ck} ,不用请自行关闭重写!` + ); + } + } else { + $.setdata(ck, "tybody"); + $.msg($.name + ` 获取第1个 ck 成功: ${ck} ,不用请自行关闭重写!`); + } + } + } + + // ============================================变量检查============================================ \\ + async function Envs() { + if (UA) { + if (UA.indexOf("@") != -1) { + UA.split("@").forEach((item) => { + UAArr.push(item); + }); + } else if (UA.indexOf("\n") != -1) { + UA.split("\n").forEach((item) => { + UAArr.push(item); + }); + } else { + UAArr.push(UA); + } + } + if (tybody) { + if (tybody.indexOf("@") != -1) { + tybody.split("@").forEach((item) => { + tybodyArr.push(item); + }); + } else if (tybody.indexOf("\n") != -1) { + tybody.split("\n").forEach((item) => { + tybodyArr.push(item); + }); + } else { + tybodyArr.push(tybody); + } + } else { + log(`\n 【${$.name}】:未填写变量 tybody`); + return; + } + + return true; + } + + // ============================================发送消息============================================ \\ + async function SendMsg(message) { + if (!message) return; + + if (Notify > 0) { + if ($.isNode()) { + var notify = require("./sendNotify"); + await notify.sendNotify($.name, message); + } else { + $.msg(message); + } + } else { + log(message); + } + } + + + /** + * 随机整数生成 + */ + function randomInt(min, max) { + return Math.round(Math.random() * (max - min) + min); + } + + var cryptoPassFunc = function(password) { + const md5 = crypto.createHash('md5'); + return md5.update(password).digest('hex').toUpperCase(); + }; + + function sign(){ + var t = timestampMs(); + return 'timestamp='+t+'&nonce=6M43dZciwRpSiFDY&signature='+cryptoPassFunc('clientKey=IfWu0xwXlWgqkIC7DWn20qpo6a30hXX6&clientSecret=A4rHhUJfMjw2I5CODh5g40Ja1d3Yk1CH&nonce=6M43dZciwRpSiFDY×tamp='+t) + } + /** + * 获取秒时间戳 + */ + function timestampS() { + return Date.parse(new Date()) / 1000; + } + + function timestampMs(){ + return new Date().getTime(); + } + + + /** + * 修改配置文件 + */ + function modify() { + fs.readFile("/ql/data/config/config.sh", "utf8", function (err, dataStr) { + if (err) { + return log("读取文件失败!" + err); + } else { + var result = dataStr.replace( + /tyau="[\w-\s/+@]{0,1000}"/g, + `tyau="${newAuArr[0]}@${newAuArr[1]}@${newAuArr[2]}"` + ); + fs.writeFile("/ql/data/config/config.sh", result, "utf8", function (err) { + if (err) { + return log(err); + } + }); + } + }); + } + + /** + * 休眠 + */ + function sleep(timeout) { + return new Promise((resolve) => setTimeout(resolve, timeout)); + } + + + function Env(t, e) { + "undefined" != typeof process && + JSON.stringify(process.env).indexOf("GITHUB") > -1 && + process.exit(0); + class s { + constructor(t) { + this.env = t; + } + send(t, e = "GET") { + t = "string" == typeof t ? { url: t } : t; + let s = this.get; + return ( + "POST" === e && (s = this.post), + new Promise((e, i) => { + s.call(this, t, (t, s, r) => { + t ? i(t) : e(s); + }); + }) + ); + } + get(t) { + return this.send.call(this.env, t); + } + post(t) { + return this.send.call(this.env, t, "POST"); + } + } + return new (class { + constructor(t, e) { + (this.name = t), + (this.http = new s(this)), + (this.data = null), + (this.dataFile = "box.dat"), + (this.logs = []), + (this.isMute = !1), + (this.isNeedRewrite = !1), + (this.logSeparator = "\n"), + (this.startTime = new Date().getTime()), + Object.assign(this, e), + this.log("", `🔔${this.name}, 开始!`); + } + isNode() { + return "undefined" != typeof module && !!module.exports; + } + isQuanX() { + return "undefined" != typeof $task; + } + isSurge() { + return "undefined" != typeof $httpClient && "undefined" == typeof $loon; + } + isLoon() { + return "undefined" != typeof $loon; + } + toObj(t, e = null) { + try { + return JSON.parse(t); + } catch { + return e; + } + } + toStr(t, e = null) { + try { + return JSON.stringify(t); + } catch { + return e; + } + } + getjson(t, e) { + let s = e; + const i = this.getdata(t); + if (i) + try { + s = JSON.parse(this.getdata(t)); + } catch {} + return s; + } + setjson(t, e) { + try { + return this.setdata(JSON.stringify(t), e); + } catch { + return !1; + } + } + getScript(t) { + return new Promise((e) => { + this.get({ url: t }, (t, s, i) => e(i)); + }); + } + runScript(t, e) { + return new Promise((s) => { + let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); + i = i ? i.replace(/\n/g, "").trim() : i; + let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); + (r = r ? 1 * r : 20), (r = e && e.timeout ? e.timeout : r); + const [o, h] = i.split("@"), + n = { + url: `http://${h}/v1/scripting/evaluate`, + body: { script_text: t, mock_type: "cron", timeout: r }, + headers: { "X-Key": o, Accept: "*/*" }, + }; + this.post(n, (t, e, i) => s(i)); + }).catch((t) => this.logErr(t)); + } + loaddata() { + if (!this.isNode()) return {}; + { + (this.fs = this.fs ? this.fs : require("fs")), + (this.path = this.path ? this.path : require("path")); + const t = this.path.resolve(this.dataFile), + e = this.path.resolve(process.cwd(), this.dataFile), + s = this.fs.existsSync(t), + i = !s && this.fs.existsSync(e); + if (!s && !i) return {}; + { + const i = s ? t : e; + try { + return JSON.parse(this.fs.readFileSync(i)); + } catch (t) { + return {}; + } + } + } + } + writedata() { + if (this.isNode()) { + (this.fs = this.fs ? this.fs : require("fs")), + (this.path = this.path ? this.path : require("path")); + const t = this.path.resolve(this.dataFile), + e = this.path.resolve(process.cwd(), this.dataFile), + s = this.fs.existsSync(t), + i = !s && this.fs.existsSync(e), + r = JSON.stringify(this.data); + s + ? this.fs.writeFileSync(t, r) + : i + ? this.fs.writeFileSync(e, r) + : this.fs.writeFileSync(t, r); + } + } + lodash_get(t, e, s) { + const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); + let r = t; + for (const t of i) if (((r = Object(r)[t]), void 0 === r)) return s; + return r; + } + lodash_set(t, e, s) { + return Object(t) !== t + ? t + : (Array.isArray(e) || (e = e.toString().match(/[^.[\]]+/g) || []), + (e + .slice(0, -1) + .reduce( + (t, s, i) => + Object(t[s]) === t[s] + ? t[s] + : (t[s] = Math.abs(e[i + 1]) >> 0 == +e[i + 1] ? [] : {}), + t + )[e[e.length - 1]] = s), + t); + } + getdata(t) { + let e = this.getval(t); + if (/^@/.test(t)) { + const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), + r = s ? this.getval(s) : ""; + if (r) + try { + const t = JSON.parse(r); + e = t ? this.lodash_get(t, i, "") : e; + } catch (t) { + e = ""; + } + } + return e; + } + setdata(t, e) { + let s = !1; + if (/^@/.test(e)) { + const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), + o = this.getval(i), + h = i ? ("null" === o ? null : o || "{}") : "{}"; + try { + const e = JSON.parse(h); + this.lodash_set(e, r, t), (s = this.setval(JSON.stringify(e), i)); + } catch (e) { + const o = {}; + this.lodash_set(o, r, t), (s = this.setval(JSON.stringify(o), i)); + } + } else s = this.setval(t, e); + return s; + } + getval(t) { + return this.isSurge() || this.isLoon() + ? $persistentStore.read(t) + : this.isQuanX() + ? $prefs.valueForKey(t) + : this.isNode() + ? ((this.data = this.loaddata()), this.data[t]) + : (this.data && this.data[t]) || null; + } + setval(t, e) { + return this.isSurge() || this.isLoon() + ? $persistentStore.write(t, e) + : this.isQuanX() + ? $prefs.setValueForKey(t, e) + : this.isNode() + ? ((this.data = this.loaddata()), + (this.data[e] = t), + this.writedata(), + !0) + : (this.data && this.data[e]) || null; + } + initGotEnv(t) { + (this.got = this.got ? this.got : require("got")), + (this.cktough = this.cktough ? this.cktough : require("tough-cookie")), + (this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar()), + t && + ((t.headers = t.headers ? t.headers : {}), + void 0 === t.headers.Cookie && + void 0 === t.cookieJar && + (t.cookieJar = this.ckjar)); + } + get(t, e = () => {}) { + t.headers && + (delete t.headers["Content-Type"], delete t.headers["Content-Length"]), + this.isSurge() || this.isLoon() + ? (this.isSurge() && + this.isNeedRewrite && + ((t.headers = t.headers || {}), + Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), + $httpClient.get(t, (t, s, i) => { + !t && s && ((s.body = i), (s.statusCode = s.status)), e(t, s, i); + })) + : this.isQuanX() + ? (this.isNeedRewrite && + ((t.opts = t.opts || {}), Object.assign(t.opts, { hints: !1 })), + $task.fetch(t).then( + (t) => { + const { statusCode: s, statusCode: i, headers: r, body: o } = t; + e(null, { status: s, statusCode: i, headers: r, body: o }, o); + }, + (t) => e(t) + )) + : this.isNode() && + (this.initGotEnv(t), + this.got(t) + .on("redirect", (t, e) => { + try { + if (t.headers["set-cookie"]) { + const s = t.headers["set-cookie"] + .map(this.cktough.Cookie.parse) + .toString(); + s && this.ckjar.setCookieSync(s, null), + (e.cookieJar = this.ckjar); + } + } catch (t) { + this.logErr(t); + } + }) + .then( + (t) => { + const { + statusCode: s, + statusCode: i, + headers: r, + body: o, + } = t; + e(null, { status: s, statusCode: i, headers: r, body: o }, o); + }, + (t) => { + const { message: s, response: i } = t; + e(s, i, i && i.body); + } + )); + } + post(t, e = () => {}) { + if ( + (t.body && + t.headers && + !t.headers["Content-Type"] && + (t.headers["Content-Type"] = "application/x-www-form-urlencoded"), + t.headers && delete t.headers["Content-Length"], + this.isSurge() || this.isLoon()) + ) + this.isSurge() && + this.isNeedRewrite && + ((t.headers = t.headers || {}), + Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), + $httpClient.post(t, (t, s, i) => { + !t && s && ((s.body = i), (s.statusCode = s.status)), e(t, s, i); + }); + else if (this.isQuanX()) + (t.method = "POST"), + this.isNeedRewrite && + ((t.opts = t.opts || {}), Object.assign(t.opts, { hints: !1 })), + $task.fetch(t).then( + (t) => { + const { statusCode: s, statusCode: i, headers: r, body: o } = t; + e(null, { status: s, statusCode: i, headers: r, body: o }, o); + }, + (t) => e(t) + ); + else if (this.isNode()) { + this.initGotEnv(t); + const { url: s, ...i } = t; + this.got.post(s, i).then( + (t) => { + const { statusCode: s, statusCode: i, headers: r, body: o } = t; + e(null, { status: s, statusCode: i, headers: r, body: o }, o); + }, + (t) => { + const { message: s, response: i } = t; + e(s, i, i && i.body); + } + ); + } + } + time(t, e = null) { + const s = e ? new Date(e) : new Date(); + let i = { + "M+": s.getMonth() + 1, + "d+": s.getDate(), + "H+": s.getHours(), + "m+": s.getMinutes(), + "s+": s.getSeconds(), + "q+": Math.floor((s.getMonth() + 3) / 3), + S: s.getMilliseconds(), + }; + /(y+)/.test(t) && + (t = t.replace( + RegExp.$1, + (s.getFullYear() + "").substr(4 - RegExp.$1.length) + )); + for (let e in i) + new RegExp("(" + e + ")").test(t) && + (t = t.replace( + RegExp.$1, + 1 == RegExp.$1.length + ? i[e] + : ("00" + i[e]).substr(("" + i[e]).length) + )); + return t; + } + msg(e = t, s = "", i = "", r) { + const o = (t) => { + if (!t) return t; + if ("string" == typeof t) + return this.isLoon() + ? t + : this.isQuanX() + ? { "open-url": t } + : this.isSurge() + ? { url: t } + : void 0; + if ("object" == typeof t) { + if (this.isLoon()) { + let e = t.openUrl || t.url || t["open-url"], + s = t.mediaUrl || t["media-url"]; + return { openUrl: e, mediaUrl: s }; + } + if (this.isQuanX()) { + let e = t["open-url"] || t.url || t.openUrl, + s = t["media-url"] || t.mediaUrl; + return { "open-url": e, "media-url": s }; + } + if (this.isSurge()) { + let e = t.url || t.openUrl || t["open-url"]; + return { url: e }; + } + } + }; + if ( + (this.isMute || + (this.isSurge() || this.isLoon() + ? $notification.post(e, s, i, o(r)) + : this.isQuanX() && $notify(e, s, i, o(r))), + !this.isMuteLog) + ) { + let t = ["", "==============📣系统通知📣=============="]; + t.push(e), + s && t.push(s), + i && t.push(i), + console.log(t.join("\n")), + (this.logs = this.logs.concat(t)); + } + } + log(...t) { + t.length > 0 && (this.logs = [...this.logs, ...t]), + console.log(t.join(this.logSeparator)); + } + logErr(t, e) { + const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); + s + ? this.log("", `❗️${this.name}, 错误!`, t.stack) + : this.log("", `❗️${this.name}, 错误!`, t); + } + wait(t) { + return new Promise((e) => setTimeout(e, t)); + } + done(t = {}) { + const e = new Date().getTime(), + s = (e - this.startTime) / 1e3; + this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), + this.log(), + (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t); + } + })(t, e); + } + diff --git a/脚本库/微信小程序/抓包版/统一茄皇互助/2023-01-03_qhhz_07a8e366.js b/脚本库/微信小程序/抓包版/统一茄皇互助/2023-01-03_qhhz_07a8e366.js new file mode 100644 index 0000000..89e4ec6 --- /dev/null +++ b/脚本库/微信小程序/抓包版/统一茄皇互助/2023-01-03_qhhz_07a8e366.js @@ -0,0 +1,643 @@ +// # Source: https://github.com/lksky8/sign-ql/blob/main/invalid/qhhz.js +// # Raw: https://raw.githubusercontent.com/lksky8/sign-ql/main/invalid/qhhz.js +// # Repo: lksky8/sign-ql +// # Path: invalid/qhhz.js +// # UploadedAt: 2023-01-03T11:38:28Z +// # SHA256: 07a8e366afc33d150d5b2c1d3dde5220e01ffa855b3c568244fe6013a54aae43 +// # Category: 微信小程序/抓包版 +// # Evidence: appid/openid/session_key/encryptedData等小程序字段 +// + +/** + 作者:临渊 + 日期:6-12 + 小程序:统一快乐星球 + 入口:活动->种番茄 + 功能:互助 + 抓包:https://apig.xiaoyisz.com/qiehuang/ga/public/api/login 这个登录包里 body 部分的 全部 + 变量:tyhz='body@xxxx ' 多个账号用 @ 或者 换行 分割 + 定时两个小时一次 + cron: 5 0/2 * * * + + 6-14 更新了AU获取方式,理论上不会过期了 + 6-18 更新了收取植物、种新的植物和推送加上昵称,方便辨认(可能) + 6-22 修复了上报挑战失败、洒阳光失败,更新了种植进度(免得老有人说脚本坏了) + 6-23 更新了助力、助力洒阳光 + 6-25 更新了冒险助力 + 6-26 修复了冒险助力的小bug,建议更改定时两个小时一次 +*/ + +const $ = new Env('统一茄皇互助'); +const crypto = require('crypto'); +const notify = $.isNode() ? require('./sendNotify') : ''; +const {log} = console; +const Notify = 0; //0为关闭通知,1为打开通知,默认为0 +const help = 1; //0为关闭互助,1为打开互助,默认为0 +////////////////////// +let tyau = ''; +let tyhz = ($.isNode() ? process.env.tyhz : $.getdata("tyhz")) || ""; +let tyhzArr = []; +let newAuArr = []; +let tyPlantId = ''; +let plantIdArr = []; +let auback = 0; +let data = ''; +let msg = ''; +let taskType = 0; +let taskTypeArr = []; +let taskId = ''; +let taskIdArr = []; +let adventureId = ''; +let name = ''; +let id = ''; +let idArr = []; +let progress = 0.00; +let plantStage = 0; +let plantStatus = ''; +let helpTaskId = ''; +let helpTaskIdArr = []; +let helpAdventureIdArr = []; + +!(async () => { + + if (!(await Envs())) + return; + else { + + log(`\n\n============================================= \n脚本执行 - 北京时间(UTC+8):${new Date( + new Date().getTime() + new Date().getTimezoneOffset() * 60 * 1000 + + 8 * 60 * 60 * 1000).toLocaleString()} \n=============================================\n`); + + log(`\n=================== 共找到 ${tyhzArr.length} 个账号 ===================`) + + for (let index = 0; index < tyhzArr.length; index++) { + + tyhz = tyhzArr[index]; + let num = index + 1 + + log(`\n========= 开始【第 ${num} 个账号】=========\n`) + + log('【开始获取AU】'); + await refreshAu(); + await $.wait(2 * 1000); + + await queryAdventure(); + await $.wait(5 * 1000); + + await getTask(); + await $.wait(2 * 1000); + + await getPlant(index); + await $.wait(2 * 1000); + + await getUserInfo(); + await $.wait(2 * 1000); + + newAuArr[index] = tyau; + helpTaskIdArr[index] = helpTaskId; + idArr[index] = id; + plantIdArr[index] = tyPlantId; + helpAdventureIdArr[index] = adventureId; + } + if (help) { + log(`【开始互助】`); + for (let num1 = 0; num1 < tyhzArr.length; num1++) { + msg += `\n【第${num1+1}个账号去助力结果】` + log(`【第${num1+1}个账号去助力结果】`) + for(num2 =0;num2 log(e)) + .finally(() => $.done()) + +/** + * 获取AU + */ +function refreshAu(num) { + let url = { + url : `https://apig.xiaoyisz.com/qiehuang/ga/public/api/login`, + headers : { + "Host": "apig.xiaoyisz.com", + "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.28(0x18001c29) NetType/WIFI", + "Content-Type": "application/json" + }, + body : `${tyhz}` + } + return new Promise((resolve) => { + + $.post(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.code == 0) { + log(`获取AU成功`) + tyau = result.data; + } else if (result.code == 500) { + log(`获取AU失败,请检查你的变量是否正确,如正确更换到环境变量或者配置文件重试`) + auback = 1; + } else { + log(`获取AU失败,原因是:${result.message}`) + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }) + }) +} + +/** + * 获取任务 + */ +function getTask(timeout = 2*1000) { + let url = { + url : 'https://apig.xiaoyisz.com/qiehuang/ga/user/task/list?'+sign(), + headers : { + "Host": "apig.xiaoyisz.com", + "authorization": `${tyau}`, + "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.28(0x18001c29) NetType/WIFI", + "content-type": "application/json" + }, + } + return new Promise((resolve) => { + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + let back = eval(result); + if (result.code == 901 ||result.code == 902 ||result.code == 903) { + auback = 1; + log(`AU错误,可能是获取失败,请更换到环境变量或配置文件重试`) + msg += `\nAU错误,可能是获取失败,请更换到环境变量或配置文件重试` + } + + if (auback != 1 && result.code == 0){ + for (let i=0;i<10;i++) { + if (i == 0) { + helpTaskId = back.data[i].taskId; + } + taskType = back.data[i].taskType; + taskTypeArr[i] = taskType; + taskId = back.data[i].taskId; + taskIdArr[i] = taskId; + } + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +/** + * 获取植物详情 + */ +function getPlant(num) { + let url = { + url : 'https://apig.xiaoyisz.com/qiehuang/ga/plant/info?'+sign(), + headers : { + "Host": "apig.xiaoyisz.com", + "authorization": `${tyau}`, + "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.28(0x18001c29) NetType/WIFI", + "content-type": "application/json" + }, + } + return new Promise((resolve) => { + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + let back = eval(result); + if (result.code == 0){ + tyPlantId = result.data.plantId; + progress =+ result.data.currentSunshineNum/result.data.needSunshineNum; + progress = progress*100; + progress = progress.toFixed(2); + plantStage =+ result.data.stage; + } else log(`获取植物详情失败`) + + } catch (e) { + log(e) + } finally { + resolve(); + } + }) + }) +} + + +/** + * 查询番茄余额 + */ +function getTomato(timeout = 2*1000) { + let url = { + url : 'https://apig.xiaoyisz.com/qiehuang/ga/user/info?'+sign(), + headers : { + "Host": "apig.xiaoyisz.com", + "authorization": `${tyau}`, + "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.28(0x18001c29) NetType/WIFI", + "Content-Type": "application/json" + }, + } + return new Promise((resolve) => { + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + let back = eval(result.data); + if (result.code == 0){ + if (plantStage == 0) { + plantStatus = '发育期'; + } else if (plantStage == 1) { + plantStatus = '幼苗期'; + } else if (plantStage == 2) { + plantStatus = '开花期'; + } else if (plantStage == 3) { + plantStatus = '结果期'; + } + log(`查询成功,账号[${name}]番茄余额为:${back.tomatoNum},植物状态为:${plantStatus},进度:${progress}%`) + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +/** + * 获取信息 + */ +function getUserInfo(timeout = 2*1000) { + let url = { + url : `https://apig.xiaoyisz.com/qiehuang/ga/user/info?`+sign(), + headers : { + "Host": "apig.xiaoyisz.com", + "authorization": `${tyau}`, + "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.28(0x18001c29) NetType/WIFI", + "Content-Type": "application/json", + }, + } + return new Promise((resolve) => { + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + let back = eval(result.data); + if (result.code == 0){ + name = back.nickName; + id = back.id; + await $.wait(2 * 1000); + getTomato(); + } else log(`获取信息失败,原因是:${result.message}`) + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +/** + * 互助 (num1助力num2) + */ +function doHelp(num1,num2) { + let url = { + url : 'https://apig.xiaoyisz.com/qiehuang/ga/user/task/report?'+sign()+`&taskType=${taskTypeArr[0]}&attachId=${idArr[num2]}&taskId=${helpTaskIdArr[num1]}`, + headers : { + "Host": "apig.xiaoyisz.com", + "authorization": `${newAuArr[num1]}`, + "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.28(0x18001c29) NetType/WIFI", + "content-type": "application/json" + }, + } + return new Promise((resolve) => { + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.data.status == 1) { + log(`去助力[${result.data.nickName}]成功`) + msg += `\n去助力[${result.data.nickName}]成功` + + } else if (result.data.status == 3) { + log(`助力失败,可能是已助力过`) + msg += `\n助力失败,可能是已助力过` + + } else if (result.data.status == 2) { + log(`助力失败,该用户被助力次数已达上限`) + msg += `\n助力失败,该用户被助力次数已达上限` + } else { + log(`助力失败,原因是:${result.message}`) + msg += `\n助力失败,原因是:${result.message}` + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }) + }) +} + +/** + * 互助洒阳光 (num1助力num2) + */ +function doHelpGiveSunshine(num1,num2) { + let url = { + url : 'https://apig.xiaoyisz.com/qiehuang/ga/plant/giveSunshine?'+sign()+`&plantId=${plantIdArr[num2]}`, + headers : { + "Host": "apig.xiaoyisz.com", + "authorization": `${newAuArr[num1]}`, + "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.28(0x18001c29) NetType/WIFI", + "content-type": "application/json" + }, + } + return new Promise((resolve) => { + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.code == 0) { + log(`助力洒阳光成功`) + msg += `\n助力洒阳光成功` + } else if (result.code == 1000) { + log(`助力洒阳光失败,今日已达上限`) + msg += `\n助力洒阳光失败,今日已达上限` + } else { + log(`助力洒阳光失败,原因是:${result.message}`) + msg += `\n助力洒阳光失败,原因是:${result.message}` + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }) + }) +} + +/** + * 互助冒险 (num1助力num2) + */ +function doHelpAdventure(num1,num2) { + let url = { + url : 'https://apig.xiaoyisz.com/qiehuang/ga/user/adventure/help?'+sign()+`&adventureId=${helpAdventureIdArr[num2]}`, + headers : { + "Host": "apig.xiaoyisz.com", + "authorization": `${newAuArr[num1]}`, + "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.28(0x18001c29) NetType/WIFI", + "content-type": "application/json" + }, + } + return new Promise((resolve) => { + $.get(url, async (error, response, data) => { + try { + let result = eval("("+data+")"); + let back = result.data; + if (result.code == 0) { + log(`去助力冒险成功`) + msg += `\n去助力冒险成功` + } else if (result.code == 1000) { + log(`去助力冒险失败`) + msg += `\n去助力冒险失败` + } else { + log(`去助力冒险失败,原因是:${result.message}`) + msg += `\n去助力冒险失败,原因是:${result.message}` + } + + } catch (e) { + log(e) + } finally { + resolve(); + } + }) + }) +} + +/** + * 查询冒险 + */ +function queryAdventure(timeout = 2*1000) { + let url = { + url : 'https://apig.xiaoyisz.com/qiehuang/ga/user/adventure/info?'+sign()+'&userId=-1&type=2', + headers : { + "Host": "apig.xiaoyisz.com", + "authorization": `${tyau}`, + "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.28(0x18001c29) NetType/WIFI", + "content-type": "application/json" + }, + } + return new Promise((resolve) => { + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.code == 904) { + refreshAu(); + } + if (result.code == 0){ + adventureId = result.data.adventureId; + if (result.data.endTime != null && timestampS() >= result.data.endTime) { + await $.wait(2000); + reportAdventure(); + } else if (result.data.endTime != null && timestampS() < result.data.endTime) { + let sleepTime =+ result.data.endTime - timestampS(); + if (sleepTime <= 600) { + log(`距离冒险结束小于十分钟,等待${sleepTime}秒后收取冒险奖励`) + await $.wait(sleepTime*1000); + reportAdventure(); + } else { + log(`距离冒险结束还有:${parseInt(sleepTime/3600)}小时${parseInt(sleepTime%3600/60)}分钟${parseInt(sleepTime%60)}秒,大于十分钟,不进行等待`) + } + } + } else { + log(`查询上一次冒险失败,原因是:${result.message}`) + } + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +/** + * 上报冒险 + */ +function reportAdventure(timeout = 2*1000) { + let url = { + url : 'https://apig.xiaoyisz.com/qiehuang/ga/user/adventure/drawPrize?'+sign()+`&adventureId=${adventureId}`, + headers : { + "Host": "apig.xiaoyisz.com", + "authorization": `${tyau}`, + "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.28(0x18001c29) NetType/WIFI", + "Content-Type": "application/json", + }, + } + return new Promise((resolve) => { + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + let back = eval(result.data.gaGiftPackageVo); + let adventureType = ''; + if (result.code == 904) { + refreshAu(); + } + if (result.code == 0){ + if (back.infos[0].type == 1) { + adventureType = '番茄' + } else if (back.infos[0].type == 2) { + adventureType = '阳光' + } + log(`冒险收取成功,获得:${back.infos[0].num}${adventureType}`) + await $.wait(3000); + queryAdventure(); + } else if (result.code == 500) { + log(`当前无可收取的冒险`) + } else if (result.code == 1000) { + log(`冒险已收取`) + } else log('冒险未到时间') + + } catch (e) { + log(e) + } finally { + resolve(); + } + }, timeout) + }) +} + +/** + * 开始冒险 + */ +function startAdventure(num) { + let url = { + url : 'https://apig.xiaoyisz.com/qiehuang/ga/user/adventure/start?'+sign(), + headers : { + "Host": "apig.xiaoyisz.com", + "authorization": `${newAuArr[num]}`, + "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.28(0x18001c29) NetType/WIFI", + "content-type": "application/json" + }, + } + return new Promise((resolve) => { + $.get(url, async (error, response, data) => { + try { + let result = JSON.parse(data); + if (result.code == 904) { + refreshAu(); + } + if (result.code == 0){ + log('冒险开始成功') + } else if (result.code ==1000) { + log(`当前已有冒险,不能进行下一次冒险`) + } else log(`${result.message}`) + + } catch (e) { + log(e) + } finally { + resolve(); + } + }) + }) +} +// ============================================变量检查============================================ \\ +async function Envs() { + if (tyhz) { + if (tyhz.indexOf("@") != -1) { + tyhz.split("@").forEach((item) => { + tyhzArr.push(item); + }); + } else if (tyhz.indexOf("\n") != -1){ + tyhz.split("\n").forEach((item) => { + tyhzArr.push(item); + }); + } else { + tyhzArr.push(tyhz); + } + } else { + log(`\n 【${$.name}】:未填写变量 tyhz`) + return ; + } + + return true; +} + +// ============================================发送消息============================================ \\ +async function SendMsg(message) { + if (!message) + return; + if (Notify > 0) { + if ($.isNode()) { + var notify = require('./sendNotify'); + await notify.sendNotify($.name, message); + } else { + $.msg(message); + } + } else { + log(message); + } +} + +var cryptoPassFunc = function(password) { + const md5 = crypto.createHash('md5'); + return md5.update(password).digest('hex').toUpperCase(); +}; + +function sign(){ + var t = timestampMs(); + return 'timestamp='+t+'&nonce=6M43dZciwRpSiFDY&signature='+cryptoPassFunc('clientKey=IfWu0xwXlWgqkIC7DWn20qpo6a30hXX6&clientSecret=A4rHhUJfMjw2I5CODh5g40Ja1d3Yk1CH&nonce=6M43dZciwRpSiFDY×tamp='+t) +} + +function timestampMs(){ + return new Date().getTime(); +} + +function timestampS(){ + return Date.parse(new Date())/1000; +} + +/** + * 修改配置文件 + */ +function modify() { + + fs.readFile('/ql/data/config/config.sh','utf8',function(err,dataStr){ + if(err){ + return log('读取文件失败!'+err) + } + else { + var result = dataStr.replace(/tyau="[\w-\s/+@]{0,1000}"/g,`tyau="${newAuArr[0]}@${newAuArr[1]}@${newAuArr[2]}"`); + fs.writeFile('/ql/data/config/config.sh', result, 'utf8', function (err) { + if (err) {return log(err);} + }); + } + }) +} + +function Env(t, e) { "undefined" != typeof process && JSON.stringify(process.env).indexOf("GITHUB") > -1 && process.exit(0); class s { constructor(t) { this.env = t } send(t, e = "GET") { t = "string" == typeof t ? { url: t } : t; let s = this.get; return "POST" === e && (s = this.post), new Promise((e, i) => { s.call(this, t, (t, s, r) => { t ? i(t) : e(s) }) }) } get(t) { return this.send.call(this.env, t) } post(t) { return this.send.call(this.env, t, "POST") } } return new class { constructor(t, e) { this.name = t, this.http = new s(this), this.data = null, this.dataFile = "box.dat", this.logs = [], this.isMute = !1, this.isNeedRewrite = !1, this.logSeparator = "\n", this.startTime = (new Date).getTime(), Object.assign(this, e), this.log("", `🔔${this.name}, 开始!`) } isNode() { return "undefined" != typeof module && !!module.exports } isQuanX() { return "undefined" != typeof $task } isSurge() { return "undefined" != typeof $httpClient && "undefined" == typeof $loon } isLoon() { return "undefined" != typeof $loon } toObj(t, e = null) { try { return JSON.parse(t) } catch { return e } } toStr(t, e = null) { try { return JSON.stringify(t) } catch { return e } } getjson(t, e) { let s = e; const i = this.getdata(t); if (i) try { s = JSON.parse(this.getdata(t)) } catch { } return s } setjson(t, e) { try { return this.setdata(JSON.stringify(t), e) } catch { return !1 } } getScript(t) { return new Promise(e => { this.get({ url: t }, (t, s, i) => e(i)) }) } runScript(t, e) { return new Promise(s => { let i = this.getdata("@chavy_boxjs_userCfgs.httpapi"); i = i ? i.replace(/\n/g, "").trim() : i; let r = this.getdata("@chavy_boxjs_userCfgs.httpapi_timeout"); r = r ? 1 * r : 20, r = e && e.timeout ? e.timeout : r; const [o, h] = i.split("@"), n = { url: `http://${h}/v1/scripting/evaluate`, body: { script_text: t, mock_type: "cron", timeout: r }, headers: { "X-Key": o, Accept: "*/*" } }; this.post(n, (t, e, i) => s(i)) }).catch(t => this.logErr(t)) } loaddata() { if (!this.isNode()) return {}; { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e); if (!s && !i) return {}; { const i = s ? t : e; try { return JSON.parse(this.fs.readFileSync(i)) } catch (t) { return {} } } } } writedata() { if (this.isNode()) { this.fs = this.fs ? this.fs : require("fs"), this.path = this.path ? this.path : require("path"); const t = this.path.resolve(this.dataFile), e = this.path.resolve(process.cwd(), this.dataFile), s = this.fs.existsSync(t), i = !s && this.fs.existsSync(e), r = JSON.stringify(this.data); s ? this.fs.writeFileSync(t, r) : i ? this.fs.writeFileSync(e, r) : this.fs.writeFileSync(t, r) } } lodash_get(t, e, s) { const i = e.replace(/\[(\d+)\]/g, ".$1").split("."); let r = t; for (const t of i) if (r = Object(r)[t], void 0 === r) return s; return r } lodash_set(t, e, s) { return Object(t) !== t ? t : (Array.isArray(e) || (e = e.toString().match(/[^.[\]]+/g) || []), e.slice(0, -1).reduce((t, s, i) => Object(t[s]) === t[s] ? t[s] : t[s] = Math.abs(e[i + 1]) >> 0 == +e[i + 1] ? [] : {}, t)[e[e.length - 1]] = s, t) } getdata(t) { let e = this.getval(t); if (/^@/.test(t)) { const [, s, i] = /^@(.*?)\.(.*?)$/.exec(t), r = s ? this.getval(s) : ""; if (r) try { const t = JSON.parse(r); e = t ? this.lodash_get(t, i, "") : e } catch (t) { e = "" } } return e } setdata(t, e) { let s = !1; if (/^@/.test(e)) { const [, i, r] = /^@(.*?)\.(.*?)$/.exec(e), o = this.getval(i), h = i ? "null" === o ? null : o || "{}" : "{}"; try { const e = JSON.parse(h); this.lodash_set(e, r, t), s = this.setval(JSON.stringify(e), i) } catch (e) { const o = {}; this.lodash_set(o, r, t), s = this.setval(JSON.stringify(o), i) } } else s = this.setval(t, e); return s } getval(t) { return this.isSurge() || this.isLoon() ? $persistentStore.read(t) : this.isQuanX() ? $prefs.valueForKey(t) : this.isNode() ? (this.data = this.loaddata(), this.data[t]) : this.data && this.data[t] || null } setval(t, e) { return this.isSurge() || this.isLoon() ? $persistentStore.write(t, e) : this.isQuanX() ? $prefs.setValueForKey(t, e) : this.isNode() ? (this.data = this.loaddata(), this.data[e] = t, this.writedata(), !0) : this.data && this.data[e] || null } initGotEnv(t) { this.got = this.got ? this.got : require("got"), this.cktough = this.cktough ? this.cktough : require("tough-cookie"), this.ckjar = this.ckjar ? this.ckjar : new this.cktough.CookieJar, t && (t.headers = t.headers ? t.headers : {}, void 0 === t.headers.Cookie && void 0 === t.cookieJar && (t.cookieJar = this.ckjar)) } get(t, e = (() => { })) { t.headers && (delete t.headers["Content-Type"], delete t.headers["Content-Length"]), this.isSurge() || this.isLoon() ? (this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.get(t, (t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) })) : this.isQuanX() ? (this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => e(t))) : this.isNode() && (this.initGotEnv(t), this.got(t).on("redirect", (t, e) => { try { if (t.headers["set-cookie"]) { const s = t.headers["set-cookie"].map(this.cktough.Cookie.parse).toString(); s && this.ckjar.setCookieSync(s, null), e.cookieJar = this.ckjar } } catch (t) { this.logErr(t) } }).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => { const { message: s, response: i } = t; e(s, i, i && i.body) })) } post(t, e = (() => { })) { if (t.body && t.headers && !t.headers["Content-Type"] && (t.headers["Content-Type"] = "application/x-www-form-urlencoded"), t.headers && delete t.headers["Content-Length"], this.isSurge() || this.isLoon()) this.isSurge() && this.isNeedRewrite && (t.headers = t.headers || {}, Object.assign(t.headers, { "X-Surge-Skip-Scripting": !1 })), $httpClient.post(t, (t, s, i) => { !t && s && (s.body = i, s.statusCode = s.status), e(t, s, i) }); else if (this.isQuanX()) t.method = "POST", this.isNeedRewrite && (t.opts = t.opts || {}, Object.assign(t.opts, { hints: !1 })), $task.fetch(t).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => e(t)); else if (this.isNode()) { this.initGotEnv(t); const { url: s, ...i } = t; this.got.post(s, i).then(t => { const { statusCode: s, statusCode: i, headers: r, body: o } = t; e(null, { status: s, statusCode: i, headers: r, body: o }, o) }, t => { const { message: s, response: i } = t; e(s, i, i && i.body) }) } } time(t, e = null) { const s = e ? new Date(e) : new Date; let i = { "M+": s.getMonth() + 1, "d+": s.getDate(), "H+": s.getHours(), "m+": s.getMinutes(), "s+": s.getSeconds(), "q+": Math.floor((s.getMonth() + 3) / 3), S: s.getMilliseconds() }; /(y+)/.test(t) && (t = t.replace(RegExp.$1, (s.getFullYear() + "").substr(4 - RegExp.$1.length))); for (let e in i) new RegExp("(" + e + ")").test(t) && (t = t.replace(RegExp.$1, 1 == RegExp.$1.length ? i[e] : ("00" + i[e]).substr(("" + i[e]).length))); return t } msg(e = t, s = "", i = "", r) { const o = t => { if (!t) return t; if ("string" == typeof t) return this.isLoon() ? t : this.isQuanX() ? { "open-url": t } : this.isSurge() ? { url: t } : void 0; if ("object" == typeof t) { if (this.isLoon()) { let e = t.openUrl || t.url || t["open-url"], s = t.mediaUrl || t["media-url"]; return { openUrl: e, mediaUrl: s } } if (this.isQuanX()) { let e = t["open-url"] || t.url || t.openUrl, s = t["media-url"] || t.mediaUrl; return { "open-url": e, "media-url": s } } if (this.isSurge()) { let e = t.url || t.openUrl || t["open-url"]; return { url: e } } } }; if (this.isMute || (this.isSurge() || this.isLoon() ? $notification.post(e, s, i, o(r)) : this.isQuanX() && $notify(e, s, i, o(r))), !this.isMuteLog) { let t = ["", "==============📣系统通知📣=============="]; t.push(e), s && t.push(s), i && t.push(i), console.log(t.join("\n")), this.logs = this.logs.concat(t) } } log(...t) { t.length > 0 && (this.logs = [...this.logs, ...t]), console.log(t.join(this.logSeparator)) } logErr(t, e) { const s = !this.isSurge() && !this.isQuanX() && !this.isLoon(); s ? this.log("", `❗️${this.name}, 错误!`, t.stack) : this.log("", `❗️${this.name}, 错误!`, t) } wait(t) { return new Promise(e => setTimeout(e, t)) } done(t = {}) { const e = (new Date).getTime(), s = (e - this.startTime) / 1e3; this.log("", `🔔${this.name}, 结束! 🕛 ${s} 秒`), this.log(), (this.isSurge() || this.isQuanX() || this.isLoon()) && $done(t) } }(t, e) }