This commit is contained in:
Ytong
2025-10-11 00:28:26 +08:00
parent 97de431c89
commit 996a72f2a9
16 changed files with 1007 additions and 3812 deletions

File diff suppressed because one or more lines are too long

View File

@@ -1,66 +0,0 @@
# --------------------------------注释区--------------------------------
# 可口可乐
# 有问题请及时联系大大鸣 v:xolag29638099 (有其他想要的脚本也可以联系,尽量试着写一写)
# 抓任意请求体的Authorization: 把值全部塞进去
# 变量:yymkckl_ 多号: #分割
#
# --------------------------------一般不动区-------------------------------
# _ooOoo_
# o8888888o
# 88" . "88
# (| -_- |)
# O\ = /O
# ____/`---'\____
# . ' \\| |// `.
# / \\||| : |||// \
# / _||||| -:- |||||- \
# | | \\\ - /// | |
# | \_| ''\---/'' | |
# \ .-\__ `-` ___/-. /
# ___`. .' /--.--\ `. . __
# ."" '< `.___\_<|>_/___.' >'"".
# | | : `- \`.;`\ _ /`;.`/ - ` : | |
# \ \ `-. \_ __\ /__ _/ .-` / /
# ======`-.____`-.___\_____/___.-`____.-'======
# `=---='
#
# .............................................
# 佛祖保佑 永无BUG
# 佛祖镇楼 BUG辟邪
# 佛曰:
# 写字楼里写字间,写字间里程序员;
# 程序人员写程序,又拿程序换酒钱。
# 酒醒只在网上坐,酒醉还来网下眠;
# 酒醉酒醒日复日,网上网下年复年。
# 但愿老死电脑间,不愿鞠躬老板前;
# 奔驰宝马贵者趣,公交自行程序员。
# 别人笑我忒疯癫,我笑自己命太贱;
# 不见满街漂亮妹,哪个归得程序员?
#
# --------------------------------代码区--------------------------------
# -*- coding: utf-8 -*-
import zlib, base64, marshal, hashlib
def xor_decrypt(data: bytes, key: str) -> bytes:
key_bytes = key.encode()
return bytes(a ^ key_bytes[i % len(key_bytes)] for i, a in enumerate(data))
def decrypt():
data = "N~5nJSrQ=Ol&dAx5`!!%MF^)J9NyS{34pp6%DgNeA>^1*W=_g)Ve>WvSY~>z*uuavBTX)1l%4-eJ7b@p=cLz!oDj6)(wcsblCg#BFfxhRY$TEE@&iG;heH5dI!LsF(ap}!v6xPqP5(N%Xp61AZ+`?a<xkAZE!<6t5$DpD<SIOje?5KLq$mc%10DhNx)7JqdlYEhqkz_b@+=d}G&^b(Gf>cjGH~HIXR3JJ<_H8?{9xS>K%Dc1rbt#q05-v8jT}o#uc+>O@q$7fZEDK`NLGuiZHMbpY@{buE3<Csq0c_FL)M9`a|+!d<hDF4*XY}M7ujNHs*UFR>c$YdAR#YP=)WwV<L$)5b|a?)p?}3oU`bLvNYP618c6(R_KC(4(#_WJ?6c6H(Lv!KJ~s6uB<ggs4pJoj<Wf|qDZ7D}=V{jZF=pzD-Nha)gz=BPf&7jA@kaQ;V=f^l9oR?hbl|I%B8uv@VnClj^o+2xQKpo0=g|%I+yL-by_q?YtvQzN)Jrb3mxL(mLQjN%q2YA_6uu$g4BkyeK!fb4r5V07z6r(;lx!>#!PDdm7xxKr)2LD8F{QAZS~XG2b=|P5rMcnVCd3g0<Y8`!|MVTB^}w={8Il#&F_ZYz>vtl&hQP6`;TFevz)TBj5!%I`)+v8Lp6t9?UI1pgm^l(94-d8J$090<D@clwy!?{|eO|3#rWGac!P;v(i<BHaA*zX|sX3CtIgpW5z(Qx<h7Zx|9LhZ;>(A8yi!n<umM$0QVD25<>ng&0oeZ5%N~un+tBVPu(_C`k?AfEzAe5#OhCOgxPg<CC9bH;;Bk*&FK}?i!C2AtLnejNhPIMptEX=vK7jrDoK@X_T4uWvbMjVd2031qzU8*nA%@e3wYinn&t!^7J)tOk;>nU%rikivA<+L2o{Z}Wclo3BIvs5-CLb^#DZK{1Gb`=OQm8@!{=BiyE014i<NSRn~(hZkTy~LuyP<EAAnH|#EH!GMNZRYcK0%TDIPPWAKlsNwsqT13w-c*M?+CagS?<in2c%rFBoCtB%gm!e#>WOi^ax|;8K1AAtz?+bXxHp#Fcp|6yOss7_YTLO>?q_u<Wb7>V(Dw_VB6W-uU(ZzqM9{km4UM7T1nkKW9Z%7n6}SSM-<mDXA%A@8)G&EkcAx7>M{7ACv8UJwER{pIe*pz7*I5)E%Q=={UrZ-en<9$M%MrdwU#_@ZnD0fGQvG}8RDP3L?O=j(tr3AGhJwKnH{51C&JmUkd?eqsH-hK6dqeYT;=?Ko+&DWQlzJ2<XZ+3os<bkNQi`)c22dnw)IELGnjgM`V%gePT?RRsTh=l+o)DvlR7vf6T0bg697E=OQABa#ET_gFgi`z!I8X%o<Ivd0yWGIt<_+?^x4mnSgvp-XHQi{vf<JYBqY^8TpEGfiCxj4}fI(0Yyo0`=JJbEu+y08G{r)Eh3G-V#ml`O|_gt#aFiB1G^_D;sl0-F!z^*Y>om~L=z-VpfSgt(=h9()_Te<&Yg`?u!>^8-Pj!hq@%?NjoC%_R|aCy}9Xl!|j^z__+_<?igC5$u7Vr|mz^{Xl4elW(xpERab(t%ynh3pv^4uMwmwoG)4GaP^NChp<3SMBTYKmU^{IE3S<AB*^`B!d)LN-sM!#BNHPtWqx>zBK+X<8GqUXbvA?dOvdoI}I~fIYFCwCA{~6xos?VxIXiJcpDftYfYrK+_}-GQtM$iUHnW+1V4zYS2+_Q>7ILvi2c{nw-txkK$I3`0P5d^1_Xyy%FVE8-zlHefUd)|0K=}=^k|Jl0RpG28SD$&|ERMz`vujNo3uRjx8AB|G~u2kc_63()IyAE&R+Gb79ij3UNL&3-P5f7FKb`7e+OWaPQ0I^IL7+pO(*PKtw2W(bwPZ!Ixrq>A~mqM^d9O;!tEn}3W)$Z16@w}2H`aa`4TEo-hZ;oPxKr`bO-b%ORu}JjV|Tux0}U4+S8qynK{>!o}Ackj2LE(<Pv$GdWuZx=1krkXugM4x=_zqLg`$WfniBY88Vlio<F)MUtH{dG{I~~Y?nc?)oNFOXh7D}Z1mK-0A~Gr?<}=FBKcd^NWB|VeE5Vn0=xt|RJs9ktN1YN&;<f@J^f)8lSKARgli(`2`Z{WCW1RkvX_V|w_7&=<`d`gL~fPS+Z)}RAB<+DF5!%b*R7#ad32{}VjS#k%8e#vQA4V|+#+O89nz}~Ul&iGJIDrhj>C){IJNyruZjS_E*stm!E187?#f%nC9e9gb>8SC&ni#?J$yr79RqDt2qw=49%PExX_qn8KKm*1R=}eT*Nr?~7df6Bi}#@l@by7qhlNu5)3BJG=!=ktuM)9<9mVyA8Cta4#)V$?Ku+{pal_F0R$w&xW;=RUiD`Q(oy;%6J+nc)T?QLsHIkPg+YoBJEFp{kr=TPLxn*qmw_4{AlB2i>ezYfAKS#=4^yN*a2SIPMerBKSs&a!L5fpM_>Mju`M_SzHWb8ScS`4wOVK^R96|TspM&{Vjp;wT<LgQ>kGggy|B{|ORor~=x1pZcM^q97HZj=T5FfQu1KzxAp=+-H?L!@kFKU)R^!{q=n@a1A8j$=-kFPxlTW^`W7xlc`?@h<kEB%C<oUfv@RF@Go90HU<9m6@g9Gu+IzT|G1F=}6%Waa>KkSJ?{B6({;zrc94fm6xH=-Drd^HVJq`JjWZsmBI}Xk@a|K2)x1lesUjSdu!UQ4R3FooVs0`w>t0cC4)y)UbDjwWWJpsHI~pm*@p?;wYRuKFlq-pK@06~=O|w^^LN9>CD%WoHZ$aKi@{s#&Z~h1zB;8RRK%d5%8QL#9n?JlY+!0eLaVyA<dJlDaBEzh1!qXmkrzl7f$9n2e|Vie_cP+~cb1sm$U-jH&YZDW-MgW?XpM4{WGl+4Zzi|rRD}F)LagvN>n_neo)uC#3}bRbR>Eu<gD+>tyHJfyAf%wUUPKEm0y{r>SE_-fU6PuQP;QX~k8%6^B`OlPMFWC%lPDIWXSrO|w+zV"
key = "2yb72Bs8mw2l6bIvQTNChZXeI0zEm4nN"
checksum = "af450e4ab1326652"
# Verify checksum
if hashlib.sha256(data.encode()).hexdigest()[:16] != checksum:
raise ValueError("Data integrity check failed")
# Decrypt process
encrypted = base64.b85decode(data)
compressed = xor_decrypt(encrypted, key)
marshalled = zlib.decompress(compressed)
return marshal.loads(marshalled)
exec(decrypt())

View File

@@ -1,870 +0,0 @@
/*
* @Author: 梁 && fang_liang_liang@foxmail.com
* @Date: 2024-11-20 09:44:59
* @Description:
* @FilePath: \薅羊毛\整理\大为健康类\大为健康-闲鱼_流年忘返.js
* @LastEditTime: 2024-11-20 14:30:05
* @LastEditors: 梁 && fang_liang_liang@foxmail.com
*/
let uid = ""
let Authorization = ""
let openid = "odrFI6snMa2Hz5cJRFlbPL8UGSDs";
let userList = [
{
"uid": "2642697",
"Authorization": "4aad85e5dee2a48224c88ab1502e2fdb",
"baseUrl": "http://zj.zjdtxt.com",
"openid": "oIlr36POgYKS11GxIotZ65B4wBxE",
"n": -1
},
{
"uid": "2642693",
"Authorization": "d620c2753b3f36d54aa961511af51626",
"baseUrl": "http://zj.zjdtxt.com",
"openid": "oIlr36GFMyn0GAj5om8_4XvpGfuM",
// "n": 1
},
{
"uid": "2642699",
"Authorization": "2227d84e69b17eaea5705c0cbed2b226",
"baseUrl": "http://zj.zjdtxt.com",
"openid": "oIlr36HIfmXKr6Tqtvng8heig4cg",
"n": -2
}
]
//1-101
var ids = [
"1648253549",
"1648345794",
"1648345844",
"1648345898",
"1648345948",
"1648601047",
"1648601104",
"1648690708",
"1648690760",
"1648773869",
"1648773920",
"1648864166",
"1648864224",
"1648948085",
"1648948298",
"1649036286",
"1649036333",
"1649122153",
"1649122201",
"1649208292",
"1649208346",
"1649293148",
"1649293200",
"1649381557",
"1649381603",
"1649466389",
"1649466479",
"1649554232",
"1649554303",
"1649643342",
"1649644432",
"1649726396",
"1649726457",
"1649813326",
"1649813374",
"1649900408",
"1649900458",
"1649900513",
"1649900570",
"1650070603",
"1650070720",
"1650156593",
"1650156645",
"1650244102",
"1650244165",
"1650329764",
"1650329833",
"1650419820",
"1650419872",
"1650506926",
"1650506977",
"1650507028",
"1650631610",
"1650768071",
"1650768127",
"1650852250",
"1650852303",
"1650852348",
"1650852406",
"1651030589",
"1651030679",
"1651030731",
"1651030785",
"1651030838",
"1651279411",
"1651279460",
"1651279506",
"1651279557",
"1651279644",
"1651366150",
"1651366201",
"1651366333",
"1651572539",
"1651621672",
"1651621726",
"1651621775",
// "1651621841",
// "1651621900",
// "1651621946",
// "1651793454",
// "1683787666",
// "1683787955",
// "1683788198",
"1651621995",
"1683792536",
"1683792594",
"1683792654",
"1651793454",
"1651793506",
"1651793554",
"1651793606",
"1652135053",
"1652135102",
"1652135175",
"1652135226",
"1652135281",
"1652135364",
"1652135427",
"1652135477",
"1652135538",
"1652135586",
"1652135639",
"1652135717",
// "1683794533",
// "1683795077",
"1652686593",
"1652772165",
"1652857801",
"1651366202",
"1649908355",
"1648864167",
"1648864168",
"1658733397",
"1658977296",
"1658976306",
"1686276155",
"1686276302",
"1686276388",
"1652946870",
"1686276615",
"1653033427",
"1653120639",
"1653205253",
]
const $ = new Env('大为健康');
const axios = require('axios');
const qs = require('qs');
const { json } = require("express");
let loginstatus = 0
let status = 0
let count_money_num = ``
let baseUrl = ""
var headers = {
'Authorization': Authorization,
'User-Agent': 'Mozilla/5.0 (Linux; Android 12; 22041211AC Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/111.0.5563.116 Mobile Safari/537.36 XWEB/5317 MMWEBSDK/20230805 MMWEBID/2593 MicroMessenger/8.0.41.2441(0x28002951) WeChat/arm64 Weixin NetType/WIFI Language/zh_CN ABI/arm64',
'Content-Type': 'application/x-www-form-urlencoded',
'Referer': 'http://hb3.hbdtxt.com/',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
'Cookie': 's342b0066=tme797db1if1i4qlq1i0d7dv13'
}
let nickname = ""
//个人信息 期数查询
async function login() {
// huodong_id=1648253549&store_id=296&noneedlogin=0&openid=oy-5j6tgNZwFf-WQkc3RD39ihp-Y&api_type=h5&uid=2079189
let data = qs.stringify({
"huodong_id": 1648253549,
"store_id": 296,
"noneedlogin": 0,
"openid": openid,
'api_type': 'h5',
'uid': uid
})
let config = {
url: baseUrl + '/api/index/index',
method: 'post',
headers: headers,
data: data
}
try {
const response = await axios(config);
let response_data = response.data
//console.log(response_data)
let code = response_data.code
if (code == 1) {
nickname = response_data.user.nickname //昵称
count_money_num = response_data.user.count_money_num //答题期数
count_money = response_data.user.count_money / 100 //累计金额
console.log(`登录成功!昵称:` + nickname + ` 答题期数:` + count_money_num + ` 累计获得红包:` + count_money + ``)
loginstatus = 1
} else {
console.log(uid + ` 登录失败!原因:` + JSON.stringify(response_data))
}
return count_money_num
} catch (error) {
console.error(error);
}
}
//题目
async function hh(huodong_id) {
let data = qs.stringify({
'huodong_id': huodong_id,
"store_id": 296,
"noneedlogin": 0,
"openid": openid,
'api_type': 'h5',
'uid': uid
})
let config = {
url: baseUrl + '/api/index/index',
method: 'post',
headers: headers,
data: data
}
try {
const response = await axios(config);
let response_data = response.data
// console.log(response_data)
let code = response_data.code
if (response_data.huodong == null) {
console.log(huodong_id)
}
let share_title = response_data.huodong.share_title
console.log(huodong_id + ":" + share_title)
// return
if (code == 777) {
console.log(response_data)
}
let msg = response_data.msg
let canyu_status = response_data.canyu_status
let is_can = response_data.is_can
let huodong = response_data.huodong
let wentilist = response_data.wentilist
let modified_wentilist = []
for (let question of wentilist) {
let daan = JSON.parse(question["daan"])[0];
for (let option of question["xuanxiang"]) {
if (option["xuhao"] === daan) {
option["xuanzhong"] = 1;
} else {
option["xuanzhong"] = 0;
}
}
modified_wentilist.push(question)
//console.log(modified_wentilist)
}
return modified_wentilist
} catch (error) {
console.error(error);
}
}
//答题
async function dt(a, huodong_id) {
var data = qs.stringify({
'wentilist': a,
'huodong_id': huodong_id,
'uuid': uid,
"openid": openid,
'api_type': 'h5',
'uid': uid
});
var config = {
method: 'post',
url: baseUrl + '/api/index/dati',
headers: headers,
data: data
};
axios(config)
.then(function (response) {
// console.log(JSON.stringify(response.data));
if (response.data.msg == "今日可领取红包次数已达上限!") {
//{"code":0,"msg":"今日可领取红包次数已达上限!"}
console.log(`${nickname}:今日可领取红包次数已达上限`)
status = 1
return
} else if (response.data.msg == "答题成功") {
console.log(`${nickname}:答题成功,获得红包:` + response.data.money + `故事id${huodong_id}`)
} else {
console.log(`${nickname}:` + JSON.stringify(response.data));
}
})
.catch(function (error) {
console.log(error);
});
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function main() {
init()
await login()
if (loginstatus === 1) {
// console.log(`===========开始答题===========`)
let index = count_money_num
index = (index * 1) - (n * 1 + 1)
console.log('index: ', index);
for (; index < ids.length; index++) {
// await $.wait(5 * 1000);
let aa = await hh(ids[index])
return
// await $.wait(5 * 1000); //
await dt(JSON.stringify(aa), ids[index])
// await $.wait(5 * 1000);
return
// if (status === 1) {
// userList.splice(currentIndex, 1)
// return;
// }
}
} else {
// userList.splice(currentIndex, 1)
}
}
function init() {
loginstatus = 0
status = 0
count_money_num = ``
headers = {
'Authorization': Authorization,
'User-Agent': 'Mozilla/5.0 (Linux; Android 12; 22041211AC Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/111.0.5563.116 Mobile Safari/537.36 XWEB/5317 MMWEBSDK/20230805 MMWEBID/2593 MicroMessenger/8.0.41.2441(0x28002951) WeChat/arm64 Weixin NetType/WIFI Language/zh_CN ABI/arm64',
'Content-Type': 'application/x-www-form-urlencoded',
'Referer': 'http://hb3.hbdtxt.com/',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
'Cookie': 's342b0066=tme797db1if1i4qlq1i0d7dv13'
}
}
// 只跑一个
async function runOne(id) {
currentIndex = 0;
while (currentIndex < userList.length) {
uid = userList[currentIndex].uid
Authorization = userList[currentIndex].Authorization
baseUrl = userList[currentIndex].baseUrl ?? "https://xb2.xbdtxt.com"
openid = userList[currentIndex].openid
init()
await login()
// await $.wait(30 * 1000);
let aa = await hh(id)
// return
// await $.wait(30 * 1000); //
await dt(JSON.stringify(aa), id)
// await $.wait(30 * 1000);
currentIndex++
}
}
// "1648253549",
// "1648345794",
// "1648345844",
// "1648345898",
// "1648345948",
// "1648601047",
// "1648601104",
// "1648690708",
// "1648690760",
// "1648773869",
// 1652135427:李盛学人生故事第91期
// 登录成功!昵称:随心 答题期数11 累计获得红包8.69元
// 1652135477:李盛学人生故事第92期
// (async ()=>{
// for(let id of ids){
// await runOne(id)
// }
// })()
//1648948298,1649036286,1649036333,1649122153,1649122201,1649208292
// ids = [1648773920, 1648864166, 1648864224, 1648948085, 1648948298]
// runOne(ids[ids.length - 1])
// 1648253549
// let currentIndex = 0;
// (async () => {
// while (userList.length > 0) {
// currentIndex = currentIndex % userList.length
// uid = userList[currentIndex].uid
// Authorization = userList[currentIndex].Authorization
// let time = new Date().getTime()
// let diff = userList[currentIndex].date + 1000 * 60 * 45 - time
// if (diff > 0) {
// await $.wait(diff)
// }
// await main()
// userList[currentIndex].date = new Date().getTime()
// currentIndex++
// }
// })()
let n = null;
(async () => {
for (let user of userList) {
uid = user.uid
Authorization = user.Authorization
baseUrl = user.baseUrl ?? "https://xb2.xbdtxt.com"
openid = user.openid
n = user.n ?? -1
// https://xb2.xbdtxt.com
await main()
await sheep(5)
}
})()
function sheep(n) {
return new Promise(resolve => {
setTimeout(() => {
resolve()
}, n * 1000)
})
}
// 没有执行过
// let arr = [1652135427, 1650244102, 1651621900, 1648601104, 1648690708, 1649466389, 1649900570, 1649208346, 1649036333, 1651793454, 1650156593, 1651279411, 1652135477, 1651621946, 1651621948, 1651030589, 1650244165, 1648690760, 1648948298, 1650070603, 1651793506, 1651279460, 1683794533, 1650156645, 1651621995, 1650419820, 1648253549, 1649466479, 1652135538, 1683795077, 1652135053, 1651793554, 1651279506, 1651030679, 1650419872, 1652135586, 1650329764, 1650506926, 1683787955, 1649381557, 1652135102, 1650070720, 1648345794, 1651279557, 1651793606, 1650768071, 1651030731, 1652135639, 1650506977, 1649381603, 1650329833, 1648773869, 1648345844, 1650768127, 1651030785, 1651366150, 1652135175, 1650507028, 1651279644, 1648773920, 1652135717, 1651621672, 1648345898, 1651030838, 1649554232, 1651366201, 1652135226, 1651572539, 1649813326, 1649643342, 1649293148, 1648345948, 1651621726, 1649122153, 1652135281, 1648948085, 1649900408, 1649813374, 1649554303, 1651621775, 1649293200, 1649644432, 1683787666, 1649122201, 1650852250, 1648782240, 1683788198, 1648864166, 1649900458, 1650631610, 1649726396, 1651366333, 1652135364, 1652135366, 1650852303, 1651621841, 1648601047, 1648864224, 1649900513, 1649208292, 1649726457, 1650852348, 1649036286, 1649908355, 1648864167,
// 1648864168, 1648253492, 1652686593, 1652772165, 1652857801, 1652946870, 1658976306, 1660278818, 1653033427,
// 1653120639, 1653205253, 1653462997,
// 1653377016, 1653289687, 1653550213,
// 1653636769, 1684131759, 1684131980,
// 1684132071, 1684132158, 1684132221,
// 1684132444, 1684132620, 1684132565,
// 1684132510, 1651366202, 1661473785,
// 1661472999, 1679039978, 1679040349,
// 1679040576, 1658733397, 1656911476,
// 1657181681, 1684132893, 1684132735,
// 1684132789]
// ; (async () => {
// for (let i = 0; i < arr.length; i++) {
// await runOne(arr[i])
// }
// })()
// 李院士分享养生神器-太极玉枕
// 登录成功!昵称:木之心 答题期数121 累计获得红包85.46元
// 木之心:答题成功获得红包0.42元
// 听故事还能得红包 赶快单击收听
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) {
// console.log(`等待${t / 1000 / 60}分钟`);
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)
}

View File

@@ -1,575 +0,0 @@
import time
import os
import json
import numpy as np
import urllib3
import re
import subprocess
import socket
import traceback
from datetime import datetime
# 禁用SSL警告
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# 日志颜色
COLOR_CODES = {
"RED": "38;5;124",
"GREEN": "38;5;22",
"BLUE": "38;5;19",
"YELLOW": "38;5;130",
"PURPLE": "38;5;92",
"BOLD": "1"
}
def color_text(text, color_code):
"""为文本添加颜色"""
return f"\033[{color_code}m{text}\033[0m"
def log_base(msg, color, emoji):
"""基础日志函数"""
time_str = datetime.now().strftime('%H:%M:%S')
time_colored = color_text(time_str, color)
print(f"{time_colored} {emoji} {msg}")
def log_info(msg, emoji="🌸"):
log_base(msg, COLOR_CODES['BLUE'], emoji)
def log_success(msg, emoji=""):
log_base(msg, COLOR_CODES['GREEN'], emoji)
def log_warning(msg, emoji="⚠️"):
log_base(msg, COLOR_CODES['YELLOW'], emoji)
def log_error(msg, emoji=""):
log_base(msg, COLOR_CODES['RED'], emoji)
def log_debug(data, emoji="🔍"):
"""调试日志"""
time_str = datetime.now().strftime('%H:%M:%S')
time_colored = color_text(time_str, COLOR_CODES['BLUE'])
if isinstance(data, (dict, list)):
print(f"{time_colored} {emoji} 调试数据:\n{json.dumps(data, indent=2, ensure_ascii=False)}")
else:
print(f"{time_colored} {emoji} {data}")
class AccountResult:
"""账号处理结果"""
def __init__(self):
self.total_accounts = 0
self.success_count = 0
self.fail_count = 0
self.rewards = {}
self.details = {}
def add_success(self, wx_openid, remark, reward):
self.success_count += 1
self.rewards[wx_openid] = reward
self.details[wx_openid] = {'remark': remark, 'reward': reward, 'status': '成功'}
def add_fail(self, wx_openid, remark):
self.fail_count += 1
self.rewards[wx_openid] = 0.0
self.details[wx_openid] = {'remark': remark, 'reward': 0.0, 'status': '失败'}
def total_reward(self):
return sum(self.rewards.values())
class Config:
"""配置类"""
def __init__(self):
self.XL_HOST = os.getenv("XL_HOST", "").strip()
self.XL_ID = os.getenv("XL_ID", "").strip()
self.XL_USER_LIST = [user.strip() for user in os.getenv("xlwy", "").split("&") if user.strip()]
self.XL_MIN_SEGMENT = int(os.getenv("XL_MIN_SEGMENT", "300"))
self.XL_MAX_SEGMENT = int(os.getenv("XL_MAX_SEGMENT", "1800"))
self.XL_TIMEOUT = int(os.getenv("XL_TIMEOUT", "30"))
self.XL_RETRY = int(os.getenv("XL_RETRY", "5"))
self.XL_DELAY_MIN = int(os.getenv("XL_DELAY_MIN", "5"))
self.XL_DELAY_MAX = int(os.getenv("XL_DELAY_MAX", "15"))
def validate_config(cfg):
"""验证配置"""
errors = []
if not cfg.XL_HOST:
errors.append("缺少域名(XL_HOST)")
if not cfg.XL_ID:
errors.append("缺少课程ID(XL_ID)")
if not cfg.XL_USER_LIST:
errors.append("账号列表为空")
elif any(len(u.split('#')) != 2 for u in cfg.XL_USER_LIST):
errors.append("账号格式错误: 应为 wx_openid#备注")
if cfg.XL_DELAY_MIN > cfg.XL_DELAY_MAX:
errors.append("延迟时间设置错误")
return errors
def random_delay(min_sec=0.5, max_sec=2.0):
"""生成随机延迟"""
delay = np.random.uniform(min_sec, max_sec)
actions = ["喝奶茶", "数星星", "和云朵聊天", "抓蝴蝶", "整理花园"]
action = np.random.choice(actions)
log_info(f"{action}中... ({delay:.2f}秒)")
time.sleep(delay)
return delay
def parse_video_time(time_str):
"""解析视频时长"""
try:
hms, _ = time_str.split('.')
hours, mins, secs = hms.split(':')
return int(hours)*3600 + int(mins)*60 + int(secs)
except:
log_warning("视频时长解析失败,使用默认值(3600秒)")
return 3600
def curl_request(method, url, headers=None, data=None):
"""使用curl执行HTTP请求"""
# 构建curl命令
cmd = ["curl", "-s", "-i", "-X", method, "--http1.1", "--tlsv1.2", "--tls-max", "1.2", "-k"]
# 添加请求头
if headers:
for key, value in headers.items():
cmd.append("-H")
cmd.append(f"{key}: {value}")
# 添加请求体
if data:
cmd.append("-d")
cmd.append(json.dumps(data))
# 添加URL
cmd.append(url)
# 执行命令
try:
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
if result.returncode != 0:
log_debug(f"curl命令失败: {' '.join(cmd)}")
log_debug(f"错误信息: {result.stderr}")
return {"error": f"curl错误: {result.returncode}", "stderr": result.stderr}
# 解析响应
response_text = result.stdout
# 尝试多种方式查找头部结束位置
header_end = -1
possible_delimiters = ["\r\n\r\n", "\n\n", "\r\r"]
for delimiter in possible_delimiters:
header_end = response_text.find(delimiter)
if header_end != -1:
break
if header_end == -1:
# 如果找不到标准分隔符,尝试查找第一个空行
lines = response_text.splitlines()
for i, line in enumerate(lines):
if not line.strip(): # 空行
header_end = sum(len(line) + 1 for line in lines[:i]) - 1
break
if header_end == -1:
# 如果还是找不到,返回整个响应
return {"error": "无法解析响应头", "raw_response": response_text}
headers_text = response_text[:header_end]
body_text = response_text[header_end+len(delimiter):]
# 解析状态码
status_line = headers_text.splitlines()[0]
try:
status_code = int(status_line.split(" ")[1])
except (IndexError, ValueError):
status_code = 0
# 解析JSON响应
try:
json_data = json.loads(body_text)
return {"status_code": status_code, "data": json_data}
except:
return {"status_code": status_code, "data": body_text}
except subprocess.TimeoutExpired:
return {"error": "请求超时"}
except Exception as e:
return {"error": f"请求异常: {str(e)}"}
def simulate_watch_time(wx_openid, headers, user_activity_id, xlhost, cfg, video_time):
"""模拟观看视频时间"""
log_info(f"视频时长: {video_time//60}{video_time%60}")
segments = []
remaining = video_time
# 分段逻辑
while remaining > 0:
max_seg = min(cfg.XL_MAX_SEGMENT, remaining)
min_seg_candidate = max(cfg.XL_MIN_SEGMENT, remaining // 3)
min_seg = min(min_seg_candidate, max_seg)
if min_seg >= max_seg:
segment = max_seg
else:
segment = np.random.randint(min_seg, max_seg + 1)
segments.append(segment)
remaining -= segment
if len(segments) >=2 and remaining < cfg.XL_MIN_SEGMENT:
segments[-1] += remaining
remaining = 0
if len(segments) > 1:
first = segments.pop(0)
np.random.shuffle(segments)
segments.insert(0, first)
# 学习描述词
study_actions = ["听课", "学习", "吸收知识", "做笔记", "思考"]
for idx, sec in enumerate(segments, 1):
action = np.random.choice(study_actions)
for attempt in range(cfg.XL_RETRY):
try:
if idx > 1:
random_delay(0.3, 1.2)
# 使用curl发送请求
url = f"https://{xlhost}/api-user/v1/activityWatchVideo"
data = {"userActivityId": user_activity_id, "second": sec}
response = curl_request("POST", url, headers, data)
if "error" in response:
raise Exception(response["error"])
if response.get("data", {}).get("status") == "success":
total_sec = sum(segments[:idx])
minutes, seconds = divmod(total_sec, 60)
log_success(f"{action}中 | 第{idx}节 | 累计: {minutes}{seconds}")
break
else:
log_warning(f"请求失败 | 尝试{attempt+1}/{cfg.XL_RETRY}")
except Exception as e:
log_warning(f"错误: {str(e)} | 尝试{attempt+1}/{cfg.XL_RETRY}")
time.sleep(np.random.uniform(0.5, 1.5))
return video_time
def check_dns_resolution(host):
"""检查DNS解析"""
try:
socket.gethostbyname(host)
return True
except socket.gaierror:
return False
def check_network_connection():
"""检查网络连接"""
try:
socket.create_connection(("8.8.8.8", 53), timeout=5)
return True
except OSError:
return False
def parse_reward_amount(response):
"""解析奖励金额(增强版)"""
# 1. 尝试从常见字段中解析
reward_fields = ["red_money", "award", "money", "reward"]
# 检查响应中的data字段
data = response.get("data", {})
if isinstance(data, dict):
for field in reward_fields:
if field in data:
try:
return float(data[field])
except (TypeError, ValueError):
pass
# 2. 尝试从响应体中直接解析
for field in reward_fields:
if field in response:
try:
return float(response[field])
except (TypeError, ValueError):
pass
# 3. 尝试从消息中解析金额
message = response.get("message", "")
if message:
# 增强匹配模式:匹配各种金额格式
patterns = [
r'[\d.,]+元', # 匹配"12.34元"
r'[\d.,]+', # 匹配纯数字
r'¥([\d.,]+)' # 匹配"¥12.34"
]
for pattern in patterns:
match = re.search(pattern, message)
if match:
try:
# 移除逗号和小数点后的非数字字符
amount_str = match.group().replace(',', '').replace('', '').replace('¥', '')
return float(amount_str)
except ValueError:
continue
# 4. 最后尝试从整个响应体中搜索
if "data" in response and isinstance(response["data"], str):
for pattern in patterns:
match = re.search(pattern, response["data"])
if match:
try:
amount_str = match.group().replace(',', '').replace('', '').replace('¥', '')
return float(amount_str)
except ValueError:
continue
return 0.0
def main():
"""主函数"""
try:
print(f"\n{color_text('🌈 小丽魔法教室启动', COLOR_CODES['PURPLE'])}")
cfg = Config()
# 配置信息
log_info(f"域名: {cfg.XL_HOST}")
log_info(f"课程ID: {cfg.XL_ID}")
log_info(f"账号数: {len(cfg.XL_USER_LIST)}")
# 验证配置
if errors := validate_config(cfg):
for err in errors:
log_error(err)
exit(1)
# 网络检查
if not check_network_connection():
log_error("网络连接失败")
exit(1)
else:
log_success("网络正常")
# DNS检查
if not check_dns_resolution(cfg.XL_HOST):
log_error(f"域名解析失败: {cfg.XL_HOST}")
exit(1)
else:
log_success(f"域名解析成功: {cfg.XL_HOST}")
result = AccountResult()
result.total_accounts = len(cfg.XL_USER_LIST)
log_info(f"{color_text('开始处理账号', COLOR_CODES['PURPLE'])}")
log_info(f"延迟间隔: {cfg.XL_DELAY_MIN}-{cfg.XL_DELAY_MAX}")
for idx, user in enumerate(cfg.XL_USER_LIST, 1):
parts = user.split('#')
if len(parts) != 2:
log_error(f"账号格式错误: {user}")
result.add_fail("", "")
continue
wx_openid, remark = parts
current_reward = 0.0
log_info(f"\n{color_text(f'处理账号 {idx}/{result.total_accounts}', COLOR_CODES['PURPLE'])}")
log_info(f"ID尾号: {wx_openid[-4:]} | 备注: {remark}")
try:
headers = {
"Host": cfg.XL_HOST,
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
"Content-Type": "application/json",
"Referer": f"https://{cfg.XL_HOST}/activity/index.html?id={cfg.XL_ID}&code=0&state=STATE"
}
# Token获取
token = None
for retry in range(cfg.XL_RETRY):
try:
url = f"https://{cfg.XL_HOST}/api-user/v2/getToken"
data = {"wx_openid": wx_openid, "id": cfg.XL_ID}
response = curl_request("POST", url, headers, data)
if "error" in response:
raise Exception(response["error"])
token_data = response.get("data", {})
if response.get("status_code") == 200 and token_data.get("status") == "success":
token = token_data["data"]["token"]
headers["Authorization"] = f"Bearer {token}"
log_success(f"Token获取成功 ({token[:6]}...)")
random_delay(1.0, 3.0)
break
else:
log_error(f"Token获取失败: {token_data.get('message', '未知错误')}")
except Exception as e:
log_warning(f"Token请求错误: {str(e)}")
if retry < cfg.XL_RETRY - 1:
time.sleep(2)
if not token:
result.add_fail(wx_openid, remark)
continue
# 获取活动详情
random_delay(0.5, 1.5)
url = f"https://{cfg.XL_HOST}/api-user/v2/activityDetatil?id={cfg.XL_ID}&withMaterial=1"
response = curl_request("GET", url, headers)
if "error" in response:
log_error(f"活动详情获取失败: {response['error']}")
result.add_fail(wx_openid, remark)
continue
detail_data = response.get("data", {})
if response.get("status_code") != 200 or "data" not in detail_data:
log_error(f"活动详情错误: HTTP {response.get('status_code')}")
result.add_fail(wx_openid, remark)
continue
# 检查是否已领取奖励
join_info = detail_data.get("meta", {}).get("joinInfo", {})
if join_info.get("is_receive_award", 0) == 1:
current_reward = float(join_info.get("red_money", 0))
result.add_success(wx_openid, remark, current_reward)
log_success(f"已领取奖励: ¥{current_reward:.2f}")
continue
# 解析视频信息
activity_data = detail_data.get("data", {})
media_info = activity_data.get("media", {})
video_time_str = media_info.get("media_v_time", "01:00:00.000")
video_total_sec = parse_video_time(video_time_str)
# 解析答案
material_detail = activity_data.get("materialDetail", {})
questions = material_detail.get("questions", [])
answer_keys = []
valid_questions = 0
for q_idx, question in enumerate(questions):
answers = question.get("answer", [])
correct_index = None
# 查找正确答案
for i, a in enumerate(answers):
if a.get("result") == "1":
correct_index = i
break
if correct_index is None:
for i, a in enumerate(answers):
if "正确答案" in a.get("item", ""):
correct_index = i
break
if correct_index is not None:
answer_keys.append(f"{q_idx}_{correct_index}")
valid_questions += 1
log_success(f"{q_idx+1}题: 答案{correct_index}")
else:
log_warning(f"{q_idx+1}题: 使用默认答案")
answer_keys.append(f"{q_idx}_0")
valid_questions += 1
# 确保至少有一个有效答案
if valid_questions == 0:
log_error("所有题目解析失败")
result.add_fail(wx_openid, remark)
continue
# 上报观影时间
user_activity_id = join_info.get("userActivityId")
if not user_activity_id:
log_error("活动ID缺失")
result.add_fail(wx_openid, remark)
continue
total_time = simulate_watch_time(wx_openid, headers, user_activity_id, cfg.XL_HOST, cfg, video_total_sec)
# 完成观影
random_delay(0.5, 2.0)
url = f"https://{cfg.XL_HOST}/api-user/v1/activityWatchVideoOver"
data = {"userActivityId": user_activity_id}
response = curl_request("POST", url, headers, data)
log_success(f"学习完成! 时长: {total_time//60}")
# 领取奖励
random_delay(1.0, 2.0)
activity_id = activity_data.get("activity_id", cfg.XL_ID)
try:
url = f"https://{cfg.XL_HOST}/api-user/v1/receiveAwardAndWatchOver"
data = {
"activity_id": activity_id,
"answers": answer_keys
}
response = curl_request("POST", url, headers, data)
if "error" in response:
raise Exception(response["error"])
reward_data = response.get("data", {})
# 处理奖励结果
if response.get("status_code") == 200:
if reward_data.get("status") in ["success", "领取成功"]:
# 使用增强的奖励解析函数
current_reward = parse_reward_amount(reward_data)
if current_reward > 0:
result.add_success(wx_openid, remark, current_reward)
log_success(f"获得奖励: ¥{current_reward:.2f}")
else:
# 如果还是解析失败,打印调试信息
log_warning("未能解析奖励金额")
log_debug(f"奖励响应数据: {reward_data}")
result.add_success(wx_openid, remark, 0.0)
log_success(f"奖励领取成功,但金额未知")
else:
result.add_fail(wx_openid, remark)
log_error(f"领取失败: {reward_data.get('message', '未知错误')}")
else:
result.add_fail(wx_openid, remark)
log_error(f"HTTP错误: {response.get('status_code')}")
except Exception as e:
result.add_fail(wx_openid, remark)
log_error(f"领取异常: {str(e)}")
except Exception as e:
result.add_fail(wx_openid, remark)
log_error(f"账号处理异常: {str(e)}")
log_debug(traceback.format_exc())
# 账号间随机延迟
if idx < len(cfg.XL_USER_LIST):
delay = np.random.randint(cfg.XL_DELAY_MIN, cfg.XL_DELAY_MAX + 1)
log_info(f"等待 {delay}秒...")
time.sleep(delay)
# 结果汇总
log_info(f"\n{color_text('处理结果', COLOR_CODES['PURPLE'])}")
log_info(f"总账号: {result.total_accounts}")
log_success(f"成功: {result.success_count}")
if result.fail_count > 0:
log_error(f"失败: {result.fail_count}")
log_success(f"总奖励: ¥{result.total_reward():.2f}")
# 详细结果
log_info(f"\n{color_text('账号详情', COLOR_CODES['PURPLE'])}")
for wx_openid, info in result.details.items():
status = color_text(info['status'], COLOR_CODES['GREEN'] if info['status'] == '成功' else COLOR_CODES['RED'])
reward_text = f"¥{info['reward']:.2f}" if info['reward'] > 0 else "未获取"
log_info(f"ID尾号: {wx_openid[-4:]} | 备注: {info['remark']} | 状态: {status} | 奖励: {reward_text}")
log_info(f"\n{color_text('🎉 处理完成', COLOR_CODES['PURPLE'])}")
except Exception as e:
log_error(f"系统错误: {str(e)}")
log_debug(traceback.format_exc())
if __name__ == "__main__":
main()

View File

@@ -1,618 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 抓包下面链接的passToken和userId填在脚本的后面
# https://account.xiaomi.com/pass/serviceLogin?callback=https%3A%2F%2Fapi.jr.airstarfinance.net%2Fsts%3Fsign%3D1dbHuyAmee0NAZ2xsRw5vhdVQQ8%253D%26followup%3Dhttps%253A%252F%252Fm.jr.airstarfinance.net%252Fmp%252Fapi%252Flogin%253Ffrom%253Dmipay_indexicon_TVcard%2526deepLinkEnable%253Dfalse%2526requestUrl%253Dhttps%25253A%25252F%25252Fm.jr.airstarfinance.net%25252Fmp%25252Factivity%25252FvideoActivity%25253Ffrom%25253Dmipay_indexicon_TVcard%252526_noDarkMode%25253Dtrue%252526_transparentNaviBar%25253Dtrue%252526cUserId%25253Dusyxgr5xjumiQLUoAKTOgvi858Q%252526_statusBarHeight%25253D137&sid=jrairstar&_group=DEFAULT&_snsNone=true&_loginType=ticket
"""
小米钱包自动任务脚本 - 环境变量版
功能:执行每日任务获取视频会员天数
特点:
1. 显示总收益和每日收益
2. 预估兑换会员所需天数
3. 明确标识无效账号
5. 总天数30天计算
6. 添加自动兑换会员功能10点抢兑
7.添加日志ID打码功能
8.添加通知功能
"""
import os
import sys
import time
import requests
import urllib3
from datetime import datetime, timedelta
from typing import Optional, Dict, Any, Union
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# 环境变量名称
ENV_NAME = "xmqb"
# 目标兑换天数
TARGET_DAYS = 30
# ==================== 自动兑换功能设置 ====================
# 总开关:是否开启自动兑换功能 (True/False)
AUTO_EXCHANGE_SWITCH = True
# 兑换会员类型 (目前支持: iqiyi/tencent/youku/mango)
EXCHANGE_TYPE = "iqiyi"
# =======================================================
# 青龙通知变量名称(带中文注释)
NOTIFY_ENV_NAMES = [
# 常用通知服务
"PUSH_KEY", # Server酱推送
"BARK_PUSH", # Bark推送
"BARK_SOUND", # Bark声音
"DD_BOT_ACCESS_TOKEN", # 钉钉机器人Token
"DD_BOT_SECRET", # 钉钉机器人Secret
"FSKEY", # 飞书机器人Key
"QYWX_AM", # 企业微信应用消息
"QYWX_KEY", # 企业微信机器人
"TG_BOT_TOKEN", # Telegram机器人Token
"TG_USER_ID", # Telegram用户ID
"PUSH_PLUS_TOKEN", # PushPlus推送Token
"PUSH_PLUS_USER", # PushPlus推送群组
# 其他通知服务
"CONSOLE", # 控制台输出
"GOBOT_URL", # go-cqhttp地址
"GOBOT_QQ", # go-cqhttp推送QQ号
"GOBOT_TOKEN", # go-cqhttp推送Token
"GOTIFY_URL", # Gotify地址
"GOTIFY_TOKEN", # Gotify令牌
"IGOT_PUSH_KEY", # iGot推送Key
"QMSG_KEY", # Qmsg推送Key
"QMSG_TYPE", # Qmsg推送类型
"QQ_SKEY", # QQ推送Skey
"QQ_MODE", # QQ推送模式
"TG_PROXY_AUTH", # Telegram代理认证
"TG_PROXY_HOST", # Telegram代理主机
"TG_PROXY_PORT", # Telegram代理端口
"TG_API_HOST", # Telegram API地址
"TENCENTBOT_SECRET_ID", # 腾讯云机器人SecretId
"TENCENTBOT_SECRETKEY", # 腾讯云机器人SecretKey
"TENCENTBOT_REGION", # 腾讯云机器人区域
"TENCENTBOT_SESSIONID", # 腾讯云机器人SessionId
"TENCENTBOT_PARAMETERS", # 腾讯云机器人参数
"DEER_KEY", # PushDeer推送Key
"MI_PUSH", # 小米推送
# 邮件通知
"SMTP_SERVER", # SMTP服务器
"SMTP_PORT", # SMTP端口
"SMTP_USER", # SMTP用户
"SMTP_PASSWORD", # SMTP密码
"SMTP_FROM", # 发件人邮箱
"SMTP_TO", # 收件人邮箱
"SMTP_SSL", # 是否使用SSL
"SMTP_HTML", # 是否使用HTML格式
"SMTP_ATTACHMENTS" # 邮件附件
]
class RnlRequest:
def __init__(self, cookies: Union[str, dict]):
self.session = requests.Session()
self._base_headers = {
'Host': 'm.jr.airstarfinance.net',
'User-Agent': 'Mozilla/5.0 (Linux; U; Android 14; zh-CN; M2012K11AC Build/UKQ1.230804.001; AppBundle/com.mipay.wallet; AppVersionName/6.89.1.5275.2323; AppVersionCode/20577595; MiuiVersion/stable-V816.0.13.0.UMNCNXM; DeviceId/alioth; NetworkType/WIFI; mix_version; WebViewVersion/118.0.0.0) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 XiaoMi/MiuiBrowser/4.3',
}
self.update_cookies(cookies)
def request(
self,
method: str,
url: str,
params: Optional[Dict[str, Any]] = None,
data: Optional[Union[Dict[str, Any], str, bytes]] = None,
json: Optional[Dict[str, Any]] = None,
**kwargs
) -> Optional[Dict[str, Any]]:
headers = {**self._base_headers, **kwargs.pop('headers', {})}
try:
resp = self.session.request(
verify=False,
method=method.upper(),
url=url,
params=params,
data=data,
json=json,
headers=headers,
**kwargs
)
resp.raise_for_status()
return resp.json()
except:
return None
def update_cookies(self, cookies: Union[str, dict]) -> None:
if cookies:
if isinstance(cookies, str):
dict_cookies = self._parse_cookies(cookies)
else:
dict_cookies = cookies
self.session.cookies.update(dict_cookies)
self._base_headers['Cookie'] = self.dict_cookie_to_string(dict_cookies)
@staticmethod
def _parse_cookies(cookies_str: str) -> Dict[str, str]:
return dict(
item.strip().split('=', 1)
for item in cookies_str.split(';')
if '=' in item
)
@staticmethod
def dict_cookie_to_string(cookie_dict):
cookie_list = []
for key, value in cookie_dict.items():
cookie_list.append(f"{key}={value}")
return "; ".join(cookie_list)
def get(self, url: str, params: Optional[Dict[str, Any]] = None, **kwargs) -> Optional[Dict[str, Any]]:
return self.request('GET', url, params=params, **kwargs)
def post(self, url: str, data: Optional[Union[Dict[str, Any], str, bytes]] = None,
json: Optional[Dict[str, Any]] = None, **kwargs) -> Optional[Dict[str, Any]]:
return self.request('POST', url, data=data, json=json, **kwargs)
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.session.close()
class RNL:
def __init__(self, c):
self.t_id = None
self.activity_code = '2211-videoWelfare'
self.rr = RnlRequest(c)
self.total_days = 0.0
self.today_gain = 0.0
self.exchanged = False # 记录是否已兑换
self.has_exchanged_before = False # 记录是否曾经兑换过
def get_task_list(self):
data = {'activityCode': self.activity_code}
try:
response = self.rr.post(
'https://m.jr.airstarfinance.net/mp/api/generalActivity/getTaskList',
data=data,
)
if response and response['code'] == 0:
return [task for task in response['value']['taskInfoList'] if '浏览组浏览任务' in task['taskName']]
except:
pass
return None
def get_task(self, task_code):
try:
data = {
'activityCode': self.activity_code,
'taskCode': task_code,
'jrairstar_ph': '98lj8puDf9Tu/WwcyMpVyQ==',
}
response = self.rr.post(
'https://m.jr.airstarfinance.net/mp/api/generalActivity/getTask',
data=data,
)
if response and response['code'] == 0:
return response['value']['taskInfo']['userTaskId']
except:
pass
return None
def complete_task(self, task_id, t_id, brows_click_urlId):
try:
url = f'https://m.jr.airstarfinance.net/mp/api/generalActivity/completeTask?activityCode={self.activity_code}&app=com.mipay.wallet&isNfcPhone=true&channel=mipay_indexicon_TVcard&deviceType=2&system=1&visitEnvironment=2&userExtra=%7B%22platformType%22:1,%22com.miui.player%22:%224.27.0.4%22,%22com.miui.video%22:%22v2024090290(MiVideo-UN)%22,%22com.mipay.wallet%22:%226.83.0.5175.2256%22%7D&taskId={task_id}&browsTaskId={t_id}&browsClickUrlId={brows_click_urlId}&clickEntryType=undefined&festivalStatus=0'
response = self.rr.get(url)
if response and response['code'] == 0:
return response['value']
except:
pass
return None
def receive_award(self, user_task_id):
try:
url = f'https://m.jr.airstarfinance.net/mp/api/generalActivity/luckDraw?imei=&device=manet&appLimit=%7B%22com.qiyi.video%22:false,%22com.youku.phone%22:true,%22com.tencent.qqlive%22:true,%22com.hunantv.imgo.activity%22:true,%22com.cmcc.cmvideo%22:false,%22com.sankuai.meituan%22:true,%22com.anjuke.android.app%22:false,%22com.tal.abctimelibrary%22:false,%22com.lianjia.beike%22:false,%22com.kmxs.reader%22:true,%22com.jd.jrapp%22:false,%22com.smile.gifmaker%22:true,%22com.kuaishou.nebula%22:false%7D&activityCode={self.activity_code}&userTaskId={user_task_id}&app=com.mipay.wallet&isNfcPhone=true&channel=mipay_indexicon_TVcard&deviceType=2&system=1&visitEnvironment=2&userExtra=%7B%22platformType%22:1,%22com.miui.player%22:%224.27.0.4%22,%22com.miui.video%22:%22v2024090290(MiVideo-UN)%22,%22com.mipay.wallet%22:%226.83.0.5175.2256%22%7D'
response = self.rr.get(url)
if response and response['code'] == 0:
return int(response.get('value', {}).get('value', 0))
except:
pass
return 0
def query_user_info(self):
"""查询用户总天数和今日收益"""
try:
# 查询总天数
total_res = self.rr.get('https://m.jr.airstarfinance.net/mp/api/generalActivity/queryUserGoldRichSum?app=com.mipay.wallet&deviceType=2&system=1&visitEnvironment=2&userExtra={"platformType":1,"com.miui.player":"4.27.0.4","com.miui.video":"v2024090290(MiVideo-UN)","com.mipay.wallet":"6.83.0.5175.2256"}&activityCode=2211-videoWelfare')
if total_res and total_res['code'] == 0:
self.total_days = int(total_res['value']) / 100
# 查询当天记录
self.today_gain = 0.0
current_date = datetime.now().strftime("%Y-%m-%d")
history_res = self.rr.get(
f'https://m.jr.airstarfinance.net/mp/api/generalActivity/queryUserJoinList?&userExtra=%7B%22platformType%22:1,%22com.miui.player%22:%224.27.0.4%22,%22com.miui.video%22:%22v2024090290(MiVideo-UN)%22,%22com.mipay.wallet%22:%226.83.0.5175.2256%22%7D&activityCode={self.activity_code}&pageNum=1&pageSize=20',
)
if history_res and history_res['code'] == 0:
for record in history_res['value']['data']:
if record['createTime'].startswith(current_date):
self.today_gain += int(record['value']) / 100
# 检查是否曾经兑换过
self.has_exchanged_before = self.check_exchange_history()
return True
except:
return False
def check_exchange_history(self):
"""检查兑换历史记录,判断是否曾经兑换过"""
try:
# 查询兑换记录
history_res = self.rr.get(
f'https://m.jr.airstarfinance.net/mp/api/generalActivity/queryUserExchangeList?activityCode={self.activity_code}&pageNum=1&pageSize=20',
)
if history_res and history_res['code'] == 0:
# 如果有兑换记录,则说明曾经兑换过
return len(history_res['value']['data']) > 0
except:
pass
return False
def run_tasks(self):
"""执行任务并返回是否有效账号"""
# 查询用户信息
if not self.query_user_info():
return False, "无法查询账户信息"
# 记录初始今日收益
initial_gain = self.today_gain
# 获取任务列表
tasks = self.get_task_list()
if not tasks:
return False, "无法获取任务列表"
# 执行任务
for i, task in enumerate(tasks[:2]): # 只执行前两个任务
try:
t_id = task['generalActivityUrlInfo']['id']
self.t_id = t_id
except:
t_id = self.t_id or ""
task_id = task.get('taskId', "")
task_code = task.get('taskCode', "")
brows_click_url_id = task['generalActivityUrlInfo'].get('browsClickUrlId', "")
# 等待
time.sleep(13)
# 完成任务
user_task_id = self.complete_task(
task_id=task_id,
t_id=t_id,
brows_click_urlId=brows_click_url_id,
)
if not user_task_id:
user_task_id = self.get_task(task_code=task_code)
time.sleep(2)
# 领取奖励
if user_task_id:
award_value = self.receive_award(user_task_id=user_task_id)
if award_value > 0:
# 更新今日收益
self.today_gain += award_value / 100
time.sleep(2)
# 更新用户信息
self.query_user_info()
# 计算本次获得的收益
gain_this_run = self.today_gain - initial_gain
# 计算预估天数
remaining_days = TARGET_DAYS - self.total_days
if gain_this_run > 0 and remaining_days > 0:
estimated_days = remaining_days / gain_this_run
else:
estimated_days = 0
# 有效账号
return True, {
"total_days": self.total_days,
"today_gain": self.today_gain,
"gain_this_run": gain_this_run,
"estimated_days": estimated_days,
"has_exchanged_before": self.has_exchanged_before
}
def exchange_member(self, phone: str) -> bool:
"""兑换会员"""
try:
# 检查是否已兑换过
if self.exchanged:
print("⚠️ 该账号今日已兑换过,跳过")
return False
# 兑换请求
url = f"https://m.jr.airstarfinance.net/mp/api/generalActivity/exchange?activityCode={self.activity_code}&exchangeCode={EXCHANGE_TYPE}&phone={phone}&app=com.mipay.wallet&deviceType=2&system=1&visitEnvironment=2&userExtra=%7B%22platformType%22:1%7D"
response = self.rr.get(url)
if response:
if response.get('code') == 0:
self.exchanged = True
return True
else:
# 如果返回了错误消息,显示具体错误
print(f"兑换失败: {response.get('message', '缺货补货中')}")
else:
# 提示缺货补货中
print("兑换失败: 缺货补货中,明天再试")
except Exception as e:
print(f"兑换请求异常: {str(e)}")
return False
def get_xiaomi_cookies(pass_token, user_id):
"""获取小米钱包cookies"""
login_url = 'https://account.xiaomi.com/pass/serviceLogin?callback=https%3A%2F%2Fapi.jr.airstarfinance.net%2Fsts%3Fsign%3D1dbHuyAmee0NAZ2xsRw5vhdVQQ8%253D%26followup%3Dhttps%253A%252F%252Fm.jr.airstarfinance.net%252Fmp%252Fapi%252Flogin%253Ffrom%253Dmipay_indexicon_TVcard%2526deepLinkEnable%253Dfalse%2526requestUrl%253Dhttps%25253A%25252F%25252Fm.jr.airstarfinance.net%25252Fmp%25252Factivity%25252FvideoActivity%25253Ffrom%25253Dmipay_indexicon_TVcard%252526_noDarkMode%25253Dtrue%252526_transparentNaviBar%25253Dtrue%252526cUserId%25253Dusyxgr5xjumiQLUoAKTOgvi858Q%252526_statusBarHeight%25253D137&sid=jrairstar&_group=DEFAULT&_snsNone=true&_loginType=ticket'
headers = {
'user-agent': 'Mozilla/5.0 (Linux; U; Android 14; zh-CN; M2012K11AC Build/UKQ1.230804.001) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.127 Mobile Safari/537.36 XiaoMi/MiuiBrowser/4.3',
'cookie': f'passToken={pass_token}; userId={user_id};'
}
try:
session = requests.Session()
session.get(url=login_url, headers=headers, verify=False, timeout=10)
cookies = session.cookies.get_dict()
if 'cUserId' in cookies and 'serviceToken' in cookies:
return f"cUserId={cookies.get('cUserId')};jrairstar_serviceToken={cookies.get('serviceToken')}"
except:
pass
return None
def format_days(days):
"""格式化天数显示(保留一位小数)"""
# 直接显示天数,不转换为分钟
return f"{days:.1f}"
def mask_user_id(user_id):
"""格式化用户ID显示只显示前三位和后三位中间用星号代替"""
if len(user_id) <= 6:
# 如果ID长度小于等于6全部显示星号
return '*' * len(user_id)
# 显示前3位 + 6个星号 + 后3位
return user_id[:3] + '*' * 6 + user_id[-3:]
def send_notification(title, content):
"""发送青龙面板通知"""
# 检查是否有通知环境变量设置
has_notify = False
for env_name in NOTIFY_ENV_NAMES:
if os.getenv(env_name):
has_notify = True
break
if not has_notify:
print("⚠️ 未检测到通知环境变量设置")
print("如需接收通知,请在青龙面板的环境变量中设置任意支持的通知变量")
print("支持的变量名称请查看脚本中的NOTIFY_ENV_NAMES列表带中文注释")
return
# 尝试导入通知模块
try:
from notify import send
send(title, content)
print("✅ 通知已发送")
except ImportError:
print("⚠️ 无法导入通知模块,请确保在青龙面板中运行")
except Exception as e:
print(f"⚠️ 发送通知失败: {str(e)}")
def main():
# 环境变量检测
env_value = os.getenv(ENV_NAME)
if not env_value:
print(f"❌ 环境变量 {ENV_NAME} 未设置")
print("请在青龙面板中添加环境变量格式passToken1&userId1@passToken2&userId2")
sys.exit(1)
# 解析账号信息
accounts = []
account_strs = env_value.split('@')
for acc_str in account_strs:
if '&' not in acc_str:
print(f"⚠️ 账号格式错误: {acc_str},跳过")
continue
parts = acc_str.split('&', 1)
if len(parts) != 2:
print(f"⚠️ 账号格式错误: {acc_str},跳过")
continue
pass_token, user_id = parts
accounts.append({
'passToken': pass_token.strip(),
'userId': user_id.strip()
})
if not accounts:
print("❌ 未找到有效账号信息")
sys.exit(1)
print(f"✅ 找到 {len(accounts)} 个账号")
print(f"⏱️ 目标兑换天数: {TARGET_DAYS}")
print(f"🔌 自动兑换功能: {'已开启' if AUTO_EXCHANGE_SWITCH else '已关闭'}")
if AUTO_EXCHANGE_SWITCH:
print(f"📱 兑换会员类型: {EXCHANGE_TYPE}")
print(f"🎯 兑换条件: 总天数≥7天且从未兑换过")
print("=" * 60)
# 获取兑换手机号环境变量
exchange_phones = []
exchange_phones_str = os.getenv("EXCHANGE_PHONES", "")
if exchange_phones_str:
exchange_phones = exchange_phones_str.split('@')
print(f"📱 找到 {len(exchange_phones)} 个兑换手机号")
else:
print("⚠️ 未设置兑换手机号环境变量 EXCHANGE_PHONES")
# 执行每个账号的任务
valid_count = 0
exchange_count = 0
account_results = [] # 存储每个账号的执行结果
for idx, account in enumerate(accounts):
user_id = account.get('userId', '未知')
masked_id = mask_user_id(user_id) # 获取脱敏后的用户ID
print(f"\n▶️ 开始账号 {idx+1}/{len(accounts)} (ID: {masked_id})")
# 获取 cookies
start_time = time.time()
cookies = get_xiaomi_cookies(
account.get('passToken', ''),
account.get('userId', '')
)
if not cookies:
print("❌ 无效账号 - 登录失败")
account_results.append(f"{masked_id} - 登录失败")
continue
# 执行任务
try:
rnl = RNL(cookies)
is_valid, result = rnl.run_tasks()
if not is_valid:
print("❌ 无效账号 - 无法获取任务")
account_results.append(f"{masked_id} - 无效账号")
continue
# 有效账号计数
valid_count += 1
# 输出结果
elapsed = time.time() - start_time
print(f"✅ 账号有效 - 任务完成")
print(f"⏱️ 耗时: {elapsed:.1f}")
print(f"💎 当前总天数: {format_days(result['total_days'])}")
print(f"📈 今日总收益: {format_days(result['today_gain'])}") # 直接显示小数形式的天数
if result['gain_this_run'] > 0:
print(f"🎁 本次获得: {format_days(result['gain_this_run'])}")
# 计算预估天数
if result['estimated_days'] > 0:
print(f"⏳ 预估兑换: 约 {result['estimated_days']:.1f} 天后可兑换会员")
else:
print("🎉 恭喜!已达成兑换目标")
else:
print(" 今日已无任务可完成")
# 进度条
progress = min(100, result['total_days'] / TARGET_DAYS * 100)
print(f"\n📊 进度: [{('=' * int(progress//5)).ljust(20)}] {progress:.1f}%")
print(f"🎯 目标: {TARGET_DAYS}天 | 剩余: {max(0, TARGET_DAYS - result['total_days']):.1f}")
# 显示兑换历史状态
if result['has_exchanged_before']:
print(" 该账号曾经兑换过会员")
else:
print(" 该账号从未兑换过会员")
# ================ 自动兑换功能 ================
exchange_status = "未尝试兑换"
if AUTO_EXCHANGE_SWITCH:
# 获取当前时间UTC+8
beijing_time = datetime.utcnow() + timedelta(hours=8)
current_hour = beijing_time.hour
# 检查兑换条件:
# 1. 总天数≥7天
# 2. 从未兑换过
# 3. 当前时间是10点
if (result['total_days'] >= 7 and
not result['has_exchanged_before'] and
current_hour == 10):
# 获取手机号
phone = ""
if idx < len(exchange_phones) and exchange_phones[idx]:
phone = exchange_phones[idx].strip()
print(f"⏰ 检测到10点满足兑换条件≥7天且首次兑换开始兑换{EXCHANGE_TYPE}会员到手机: {phone}")
# 执行兑换
if rnl.exchange_member(phone):
exchange_count += 1
print(f"🎉 {EXCHANGE_TYPE}会员兑换成功!")
exchange_status = "兑换成功"
else:
print("⚠️ 兑换失败,请检查日志")
exchange_status = "兑换失败"
else:
print(f"⚠️ 未找到对应的兑换手机号,无法兑换{EXCHANGE_TYPE}会员")
exchange_status = "无手机号"
else:
# 显示不兑换的原因
reasons = []
if result['total_days'] < 7:
reasons.append(f"总天数不足7天当前{result['total_days']:.1f}天)")
if result['has_exchanged_before']:
reasons.append("该账号已兑换过会员")
if current_hour != 10:
reasons.append(f"当前时间 {beijing_time.strftime('%H:%M')} 非10点")
if reasons:
print(f" 不满足兑换条件: {''.join(reasons)}")
exchange_status = "条件不满足"
# ===========================================
# 记录账号结果
account_results.append(
f"{masked_id} | 总天数: {format_days(result['total_days'])} | "
f"今日收益: {format_days(result['today_gain'])} | "
f"状态: {exchange_status}"
)
except Exception as e:
print(f"⚠️ 执行异常: {str(e)}")
account_results.append(f"{masked_id} - 执行异常")
print(f"🔚 账号 {masked_id} 处理完成")
print("-" * 50)
time.sleep(3)
# 最终统计
print("\n" + "=" * 60)
print(f"✅ 任务完成 - 有效账号: {valid_count}/{len(accounts)}")
print(f"🎁 成功兑换会员: {exchange_count}")
print(f"⏰ 执行时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print("=" * 60)
# 构建通知内容
title = "小米钱包任务完成"
content = [
f"📊 账号总数: {len(accounts)}",
f"✅ 有效账号: {valid_count}",
f"🎁 兑换成功: {exchange_count}",
f"⏰ 执行时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
"",
"📋 账号详情:"
]
content.extend(account_results)
# 发送通知
send_notification(title, "\n".join(content))
if __name__ == "__main__":
main()

48
快手App免费版.py Normal file
View File

@@ -0,0 +1,48 @@
# 当前脚本来自于http://script.345yun.cn脚本库下载
"""
KSP_JBDH # True或False 金币是否自动兑换为余额
KSP_JBSU # 写数字 检测到金币低于多少会自动切换did
KSP_DID # True或False 检测到金币过低是否自动切换did
KSP_YC # 20,30 每次任务延迟多少到多少秒
KSP_JBMAX # 写数字 最高金币数量
KSP_BF # True或False 是否开启并发
KSP_BFMS # 1或者2 并发模式
KSP_YXCS # 运行次数 每个账号最多看多少次广告停止
KSP_Card # 快手卡密 卡密设置为Yzyxmm 免费使用!!!!!
ksck # 备注#ck#salt#任务id#ip|port|username|password
# 任务id详解 0饭补 1我不知道 2 200广 3 宝箱广告 4 混合模式(每次随机)
# socket5地址http://www.gzsk5.com/#/register?invitation=Yzyxmm&shareid=4365r/月)
# 一键取ck https://www.123912.com/s/VKFJjv-z7anA
"""
import sys
import requests
import base64
import os
if not os.path.exists('kspt.so'):
print('正在加载so文件.....')
version_str = sys.version.split()[0]
if version_str.startswith("3.10"):
v = '310'
print(f'当前python版本为3.10')
elif version_str.startswith("3.11"):
v = '311'
print(f'当前python版本为3.11')
else:
print(f"当前python版本不受支持")
exit(0)
url = 'http://yi100.top:3029/ks'
data = {
'type': v
}
response = requests.post(url, json=data)
print(response.text)
file_data = base64.b64decode(response.text.encode('utf-8'))
# 写入目标文件
with open('kspt.so', 'wb') as file:
file.write(file_data)
print('so文件加载成功')
import kspt
# 当前脚本来自于http://script.345yun.cn脚本库下载

263
快手so.py Normal file
View File

@@ -0,0 +1,263 @@
# 当前脚本来自于http://script.345yun.cn脚本库下载
import urllib3
import sys
import os
import requests
import platform
import re
# 禁用SSL证书验证警告
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# 版本文件名称
VERSION_FILE = "so_version.txt"
# 服务器版本号获取地址(这里使用示例地址,实际应替换为真实地址)
VERSION_CHECK_URL = "http://43.143.175.165:8888/down/j8cKIDC0gB6E.txt" # 服务器应返回简单版本号如"1.2"
# 首次运行的初始版本
INITIAL_VERSION = "1.1"
def check_python_version():
"""检查Python版本是否符合 3.10.x ~ 3.11.x 要求"""
version = sys.version_info
if not (version >= (3, 10) and version < (3, 12)):
current_version = f"{version.major}.{version.minor}.{version.micro}"
print(f"\n【❌ Python版本检查失败】")
print(f"当前版本:{current_version}")
print(f"必须版本3.10.x ~ 3.11.x")
sys.exit(1)
print(f"【✅ Python版本检查通过】当前版本{version.major}.{version.minor}.{version.micro}")
def check_system_architecture():
"""检查系统架构是否为支持的 x86_64 或 arm64"""
system = platform.system().lower()
machine = platform.machine().lower()
supported_arch = ["x86_64", "amd64", "arm64", "aarch64"]
arch_map = {"amd64": "x86_64", "aarch64": "arm64"}
arch = arch_map.get(machine, machine)
if machine not in supported_arch:
print(f"\n【❌ 系统架构检查失败】")
print(f"当前环境:{system.capitalize()} 系统 | 架构:{machine}(映射后:{arch}")
print(f"支持架构x86_64含amd64、arm64含aarch64")
sys.exit(1)
print(f"\n【✅ 系统架构检查通过】")
print(f"操作系统:{platform.system()} {platform.release()}")
print(f"CPU架构{machine}(标准映射:{arch}")
return arch
def get_local_version():
"""获取本地so文件版本"""
if not os.path.exists(VERSION_FILE):
# 首次运行,设置初始版本
with open(VERSION_FILE, "w") as f:
f.write(INITIAL_VERSION)
return INITIAL_VERSION
try:
with open(VERSION_FILE, "r") as f:
version = f.read().strip()
# 简单验证版本格式
if re.match(r"^\d+\.\d+$", version):
return version
# 格式不正确,使用初始版本
return INITIAL_VERSION
except Exception:
return INITIAL_VERSION
def get_server_version():
"""从服务器获取最新版本号"""
try:
# print("\n【🔍 检查服务器版本...】")
response = requests.get(
VERSION_CHECK_URL,
timeout=10,
verify=False,
headers={"User-Agent": "Mozilla/5.0"}
)
response.raise_for_status()
version = response.text.strip()
# 验证版本格式
if re.match(r"^\d+\.\d+$", version):
# print(f"服务器最新版本:{version}")
return version
else:
print(f"【⚠️ 服务器版本格式不正确:{version}")
return None
except Exception as e:
print(f"【⚠️ 获取服务器版本失败:{str(e)}")
return None
def version_needs_update(local_ver, server_ver):
"""比较版本号,判断是否需要更新"""
if not server_ver:
return False
try:
local_parts = list(map(int, local_ver.split('.')))
server_parts = list(map(int, server_ver.split('.')))
# 比较主版本号
if server_parts[0] > local_parts[0]:
return True
# 主版本号相同,比较次版本号
if server_parts[0] == local_parts[0] and server_parts[1] > local_parts[1]:
return True
return False
except Exception:
return False
def update_local_version(new_version):
"""更新本地版本记录"""
try:
with open(VERSION_FILE, "w") as f:
f.write(new_version)
return True
except Exception as e:
print(f"【⚠️ 更新本地版本记录失败:{str(e)}")
return False
def download_so_file(url, target_path):
"""从指定URL下载so文件支持进度显示与失败清理"""
try:
print(f"\n【📥 开始下载so文件】")
print(f"源地址:{url}")
print(f"保存路径:{os.path.abspath(target_path)}")
response = requests.get(
url,
stream=True,
timeout=60,
verify=False,
headers={"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36"}
)
response.raise_for_status()
total_size = int(response.headers.get("Content-Length", 0))
downloaded_size = 0
chunk_size = 8192
with open(target_path, "wb") as f:
for chunk in response.iter_content(chunk_size=chunk_size):
if chunk:
f.write(chunk)
downloaded_size += len(chunk)
if total_size > 0:
progress = (downloaded_size / total_size) * 100
print(f"下载进度:{progress:.1f}% | {downloaded_size}/{total_size} 字节", end="\r")
if total_size > 0:
print(f"下载进度100.0% | {downloaded_size}/{total_size} 字节")
print(f"【✅ so文件下载完成】已保存为{target_path}")
return True
except requests.exceptions.HTTPError as e:
error_msg = f"HTTP错误{e.response.status_code} {e.response.reason}"
if e.response.status_code == 403:
error_msg += "(可能是链接权限不足,建议加群获取最新链接)"
elif e.response.status_code == 404:
error_msg += "(文件不存在,链接可能已失效)"
except requests.exceptions.ConnectionError:
error_msg = "网络连接失败"
except requests.exceptions.Timeout:
error_msg = "下载超时"
except Exception as e:
error_msg = f"未知错误:{str(e)}"
print(f"\n【❌ so文件下载失败】")
print(f"错误详情:{error_msg}")
print(f"请加群获取帮助https://t.me/+pGksv96SJjVjZTQ1")
if os.path.exists(target_path):
os.remove(target_path)
sys.exit(1)
def main():
# 终端颜色配置
GREEN = "\033[32m"
RED = "\033[31m"
YELLOW = "\033[33m"
BLUE = "\033[34m"
RESET = "\033[0m"
# 1. 打印加群提示
print(f"{GREEN}="*50)
print(f" 加群获取白嫖卡密 | 问题反馈")
print(f"{BLUE} 交流群链接https://t.me/+pGksv96SJjVjZTQ1")
print(f"{GREEN}="*50 + RESET)
# 2. 执行环境检查
print(f"\n{YELLOW}【🔍 开始环境兼容性检查】{RESET}")
check_python_version()
check_system_architecture()
print(f"\n{YELLOW}【✅ 所有环境检查通过】{RESET}")
# 3. 版本检查与更新逻辑
target_so_name = "kuaishou_task.so"
# remote_so_url = "http://43.143.175.165:8888/down/AYcHZSpwaLax.so"
remote_so_url = "http://43.143.175.165:8888/down/nouh4Neo1IjV.so"
local_version = get_local_version()
# print(f"\n【📌 本地so版本{local_version}】")
server_version = get_server_version()
# 处理版本比较结果
if not server_version:
print("【⚠️ 无法获取服务器版本,将使用本地版本(如存在)】")
if not os.path.exists(target_so_name):
print("【ℹ️ 未发现本地so文件将进行下载】")
download_so_file(remote_so_url, target_so_name)
update_local_version(local_version) # 使用当前本地版本
else:
if version_needs_update(local_version, server_version):
print(f"【🔄 发现新版本 {server_version},正在更新...】")
# 下载并替换文件
if os.path.exists(target_so_name):
os.remove(target_so_name)
download_so_file(remote_so_url, target_so_name)
# 更新版本记录
update_local_version(server_version)
else:
print(f"【✅ 本地版本 {local_version} 已是最新,无需更新】")
# 如果本地文件不存在,即使版本相同也下载
if not os.path.exists(target_so_name):
print("【ℹ️ 未发现本地so文件将下载当前版本】")
download_so_file(remote_so_url, target_so_name)
# 4. 导入并执行快手任务
try:
print(f"\n{YELLOW}【🚀 开始执行快手任务】{RESET}")
import kuaishou_task
result = kuaishou_task.run_main()
print(f"\n{GREEN}【🎉 任务执行完成】{RESET}")
print(f"任务执行结果:{result}")
except ImportError as e:
print(f"\n{RED}【❌ 导入kuaishou_task失败】{RESET}")
print(f"错误详情:{str(e)}")
print("可能原因及解决方案:")
print(" 1. so文件与系统架构不兼容")
print(" 2. so文件损坏重新运行脚本尝试下载")
sys.exit(1)
except Exception as e:
print(f"\n{RED}【❌ 执行快手任务失败】{RESET}")
print(f"错误详情:{str(e)}")
print("建议:加群反馈错误信息,获取技术支持")
sys.exit(1)
if __name__ == "__main__":
main()
# 当前脚本来自于http://script.345yun.cn脚本库下载

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

27
甬派阅读5.9.py Normal file

File diff suppressed because one or more lines are too long

26
甬音5.9.py Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,163 +0,0 @@
# 当前脚本来自于http://script.345yun.cn脚本库下载
import os
import urllib.request
import sys
import time
import platform
class SystemChecker:
@staticmethod
def is_arm_architecture():
"""检测是否为ARM架构"""
machine = platform.machine().lower()
arm_patterns = [
'arm', 'aarch', 'arm64', 'aarch64',
'armv7', 'armv8', 'armhf'
]
return any(pattern in machine for pattern in arm_patterns)
@staticmethod
def is_amd_architecture():
"""检测是否为AMD/x86架构"""
machine = platform.machine().lower()
amd_patterns = [
'x86_64', 'amd64', 'x86', 'i386', 'i686',
'amd', 'intel', 'x64'
]
return any(pattern in machine for pattern in amd_patterns)
@staticmethod
def is_supported_architecture():
"""检测是否支持ARM或AMD架构"""
return SystemChecker.is_arm_architecture() or SystemChecker.is_amd_architecture()
@staticmethod
def is_linux_supported():
"""检测是否为Linux且支持ARM或AMD架构"""
return SystemChecker.is_supported_architecture()
@staticmethod
def get_architecture_type():
"""获取具体的架构类型"""
if SystemChecker.is_arm_architecture():
return 'arm'
elif SystemChecker.is_amd_architecture():
return 'amd'
else:
return 'unknown'
@staticmethod
def get_detailed_info():
return {
'os': platform.system(),
'architecture': platform.machine(),
'arch_type': SystemChecker.get_architecture_type()
}
checker = SystemChecker()
if checker.is_linux_supported():
pass
else:
info = checker.get_detailed_info()
print(f'当前系统不支持,当前系统类型: {info["os"]},系统架构: {info["architecture"]}')
exit(1)
def get_architecture():
"""获取系统架构"""
arch = platform.machine().lower()
if 'arm' in arch or 'aarch' in arch:
return 'arm'
elif 'x86' in arch or 'amd' in arch or 'i386' in arch or 'i686' in arch:
return 'amd'
else:
return arch
current_arch = get_architecture()
####################使用教程区####################
#需安装依赖requests[socks]
#广告类型1为普通广告 2为200广(已单独剔出)3为宝箱广告其他值为以上全部执行,默认全部执行
# 抓包 ck和salt
# 格式1备注#Cookie#salt#广告类型(备注#Cookie#salt#1,3)
# 格式2备注#Cookie#salt#广告类型#sock5
#广告类型为列表模式,使用英文逗号隔开,填什么就指定跑什么
# socks5存在则使用代理反之
# socks代理选择参数可填可不填 格式ip|port|username|password
# ck变量ksck, 填写上面两种格式ck均可多号新建变量即可
# 并发变量KSP_BF, 设置为False为关闭并发默认开启
# 卡密变量KSP_Card 填写脚本打印出来的卡密即可
# 金币自动兑换变量KSP_JBDH 默认关闭True开启
# 运行延迟变量KSP_YC 默认30,45格式为【最低,最高】,中间英文逗号隔开
# 运行次数变量KSP_YXCS 默认200
# 金币控制变量KSP_JBMAX 默认500000
# 广告模式变量KSP_ADMS 默认为1(正常广告)设置2为追加(理论默认即可)
# 自动更换did变量KSP_DID 默认关闭True开启(实测不好用)
# 自动更换did金币数量变量KSP_JBSU 低于多少尝试更换did默认1000自动更换开启生效
def GET_SO():
PythonV = sys.version_info
if PythonV.major == 3 and PythonV.minor == 10:
PythonV = '10'
print('当前Python版本为3.10 开始安装...')
elif PythonV.major == 3 and PythonV.minor == 11:
PythonV = '11'
print('当前Python版本为3.11 开始安装...')
else:
return False, f'不支持的Python版本{sys.version}'
try:
mirrors = [
f'https://raw.bgithub.xyz/BIGOSTK/pyso/refs/heads/main/ksadp_{current_arch}_{PythonV}.so',
f'https://gh-proxy.com/https://raw.githubusercontent.com/BIGOSTK/pyso/main/ksadp_{current_arch}_{PythonV}.so',
f'https://raw.githubusercontent.com/BIGOSTK/pyso/main/ksadp_{current_arch}_{PythonV}.so',
f'https://raw.bgithub.xyz/BIGOSTK/pyso/main/ksadp_{current_arch}_{PythonV}.so'
]
last_error = None
for url in mirrors:
try:
print(f'尝试从 {url} 下载...')
with urllib.request.urlopen(url, timeout=15) as response:
if response.status == 200:
with open('./ksadp.so', 'wb') as out_file:
out_file.write(response.read())
print('下载成功')
return True, None
except Exception as e:
last_error = e
print(f'下载失败: {e}')
time.sleep(1)
return False, f'所有镜像尝试失败: {last_error}'
except Exception as e:
return False, e
def main():
if not os.path.exists('./ksadp.so'):
success, error = GET_SO()
if not success:
print(f'无法获取ksadp.so: {error}')
return
try:
import ksadp
ksadp.main()
except ImportError as e:
print(f'导入ksadp模块失败: {e}')
except Exception as e:
print(f'执行ksadp.main()时出错: {e}')
if __name__ == '__main__':
main()
# 当前脚本来自于http://script.345yun.cn脚本库下载

643
顺丰1.2.py Normal file
View File

@@ -0,0 +1,643 @@
# 当前脚本来自于http://script.345yun.cn脚本库下载
import hashlib
import json
import os
import random
import time
from datetime import datetime, timedelta
from sys import exit
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
from urllib.parse import unquote
# 禁用安全请求警告
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
PROXY_API_URL = os.getenv('SF_PROXY_API_URL', '') # 从环境变量获取代理API地址
def get_proxy():
try:
if not PROXY_API_URL:
print('⚠️ 未配置代理API地址将不使用代理')
return None
response = requests.get(PROXY_API_URL, timeout=10)
if response.status_code == 200:
proxy_text = response.text.strip()
if ':' in proxy_text:
proxy = f'http://{proxy_text}'
return {
'http': proxy,
'https': proxy
}
print(f'❌ 获取代理失败: {response.text}')
return None
except Exception as e:
print(f'❌ 获取代理异常: {str(e)}')
return None
send_msg = ''
one_msg = ''
def Log(cont=''):
global send_msg, one_msg
print(cont)
if cont:
one_msg += f'{cont}\n'
send_msg += f'{cont}\n'
inviteId = ['']
class RUN:
def __init__(self, info, index):
global one_msg
one_msg = ''
split_info = info.split('@')
url = split_info[0]
len_split_info = len(split_info)
last_info = split_info[len_split_info - 1]
self.send_UID = None
if len_split_info > 0 and "UID_" in last_info:
self.send_UID = last_info
self.index = index + 1
self.proxy = get_proxy()
if self.proxy:
print(f"✅ 成功获取代理: {self.proxy['http']}")
self.s = requests.session()
self.s.verify = False
if self.proxy:
self.s.proxies = self.proxy
self.headers = {
'Host': 'mcs-mimp-web.sf-express.com',
'upgrade-insecure-requests': '1',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36 NetType/WIFI MicroMessenger/7.0.20.1781(0x6700143B) WindowsWechat(0x63090551) XWEB/6945 Flue',
'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',
'sec-fetch-site': 'none',
'sec-fetch-mode': 'navigate',
'sec-fetch-user': '?1',
'sec-fetch-dest': 'document',
'accept-language': 'zh-CN,zh',
'platform': 'MINI_PROGRAM',
}
self.login_res = self.login(url)
self.all_logs = []
self.today = datetime.now().strftime('%Y-%m-%d')
self.member_day_black = False
self.member_day_red_packet_drew_today = False
self.member_day_red_packet_map = {}
self.max_level = 8
self.packet_threshold = 1 << (self.max_level - 1)
self.totalPoint = 0
def get_deviceId(self, characters='abcdef0123456789'):
result = ''
for char in 'xxxxxxxx-xxxx-xxxx':
if char == 'x':
result += random.choice(characters)
elif char == 'X':
result += random.choice(characters).upper()
else:
result += char
return result
def login(self, sfurl):
try:
decoded_url = unquote(sfurl)
ress = self.s.get(decoded_url, headers=self.headers)
self.user_id = self.s.cookies.get_dict().get('_login_user_id_', '')
self.phone = self.s.cookies.get_dict().get('_login_mobile_', '')
self.mobile = self.phone[:3] + "*" * 4 + self.phone[7:] if self.phone else ''
if self.phone:
Log(f'👤 账号{self.index}:【{self.mobile}】登陆成功')
return True
else:
Log(f'❌ 账号{self.index}获取用户信息失败')
return False
except Exception as e:
Log(f'❌ 登录异常: {str(e)}')
return False
def getSign(self):
timestamp = str(int(round(time.time() * 1000)))
token = 'wwesldfs29aniversaryvdld29'
sysCode = 'MCS-MIMP-CORE'
data = f'token={token}&timestamp={timestamp}&sysCode={sysCode}'
signature = hashlib.md5(data.encode()).hexdigest()
data = {
'sysCode': sysCode,
'timestamp': timestamp,
'signature': signature
}
self.headers.update(data)
return data
def do_request(self, url, data={}, req_type='post', max_retries=3):
self.getSign()
retry_count = 0
while retry_count < max_retries:
try:
if req_type.lower() == 'get':
response = self.s.get(url, headers=self.headers, timeout=30)
elif req_type.lower() == 'post':
response = self.s.post(url, headers=self.headers, json=data, timeout=30)
else:
raise ValueError('Invalid req_type: %s' % req_type)
response.raise_for_status()
try:
res = response.json()
return res
except json.JSONDecodeError as e:
print(f'JSON解析失败: {str(e)}, 响应内容: {response.text[:200]}')
retry_count += 1
if retry_count < max_retries:
print(f'正在进行第{retry_count + 1}次重试...')
time.sleep(2)
continue
return None
except requests.exceptions.RequestException as e:
retry_count += 1
if retry_count < max_retries:
print(f'请求失败,正在切换代理重试 ({retry_count}/{max_retries}): {str(e)}')
self.proxy = get_proxy()
if self.proxy:
print(f"✅ 成功获取新代理: {self.proxy['http']}")
self.s.proxies = self.proxy
time.sleep(2)
else:
print('请求最终失败:', e)
return None
return None
def sign(self):
print(f'🎯 开始执行签到')
json_data = {"comeFrom": "vioin", "channelFrom": "WEIXIN"}
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~integralTaskSignPlusService~automaticSignFetchPackage'
response = self.do_request(url, data=json_data)
if response.get('success') == True:
count_day = response.get('obj', {}).get('countDay', 0)
if response.get('obj') and response['obj'].get('integralTaskSignPackageVOList'):
packet_name = response["obj"]["integralTaskSignPackageVOList"][0]["packetName"]
Log(f'✨ 签到成功,获得【{packet_name}】,本周累计签到【{count_day + 1}】天')
else:
Log(f'📝 今日已签到,本周累计签到【{count_day + 1}】天')
else:
print(f'❌ 签到失败!原因:{response.get("errorMessage")}')
def superWelfare_receiveRedPacket(self):
print(f'🎁 超值福利签到')
json_data = {
'channel': 'czflqdlhbxcx'
}
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberActLengthy~redPacketActivityService~superWelfare~receiveRedPacket'
response = self.do_request(url, data=json_data)
if response.get('success') == True:
gift_list = response.get('obj', {}).get('giftList', [])
if response.get('obj', {}).get('extraGiftList', []):
gift_list.extend(response['obj']['extraGiftList'])
gift_names = ', '.join([gift['giftName'] for gift in gift_list])
receive_status = response.get('obj', {}).get('receiveStatus')
status_message = '领取成功' if receive_status == 1 else '已领取过'
Log(f'🎉 超值福利签到[{status_message}]: {gift_names}')
else:
error_message = response.get('errorMessage') or json.dumps(response) or '无返回'
print(f'❌ 超值福利签到失败: {error_message}')
def get_SignTaskList(self, END=False):
if not END: print(f'🎯 开始获取签到任务列表')
json_data = {
'channelType': '1',
'deviceId': self.get_deviceId(),
}
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~integralTaskStrategyService~queryPointTaskAndSignFromES'
response = self.do_request(url, data=json_data)
if response.get('success') == True and response.get('obj') != []:
self.totalPoint = response["obj"]["totalPoint"]
if END:
Log(f'💰 当前积分:【{self.totalPoint}')
return
Log(f'💰 执行前积分:【{self.totalPoint}')
for task in response["obj"]["taskTitleLevels"]:
self.taskId = task["taskId"]
self.taskCode = task["taskCode"]
self.strategyId = task["strategyId"]
self.title = task["title"]
status = task["status"]
skip_title = ['用行业模板寄件下单', '去新增一个收件偏好', '参与积分活动']
if status == 3:
print(f'{self.title}-已完成')
continue
if self.title in skip_title:
print(f'⏭️ {self.title}-跳过')
continue
else:
# print("taskId:", taskId)
# print("taskCode:", taskCode)
# print("----------------------")
self.doTask()
time.sleep(3)
self.receiveTask()
def doTask(self):
print(f'🎯 开始去完成【{self.title}】任务')
json_data = {
'taskCode': self.taskCode,
}
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonRoutePost/memberEs/taskRecord/finishTask'
response = self.do_request(url, data=json_data)
if response.get('success') == True:
print(f'✨ 【{self.title}】任务-已完成')
else:
print(f'❌ 【{self.title}】任务-{response.get("errorMessage")}')
def receiveTask(self):
print(f'🎁 开始领取【{self.title}】任务奖励')
json_data = {
"strategyId": self.strategyId,
"taskId": self.taskId,
"taskCode": self.taskCode,
"deviceId": self.get_deviceId()
}
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~integralTaskStrategyService~fetchIntegral'
response = self.do_request(url, data=json_data)
if response.get('success') == True:
print(f'✨ 【{self.title}】任务奖励领取成功!')
else:
print(f'❌ 【{self.title}】任务-{response.get("errorMessage")}')
def EAR_END_2023_TaskList(self):
print('\n🎭 开始年终集卡任务')
json_data = {
"activityCode": "YEAREND_2024",
"channelType": "MINI_PROGRAM"
}
self.headers['channel'] = '24nzdb'
self.headers['platform'] = 'MINI_PROGRAM'
self.headers['syscode'] = 'MCS-MIMP-CORE'
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~activityTaskService~taskList'
response = self.do_request(url, data=json_data)
if response.get('success') == True:
for item in response["obj"]:
self.title = item["taskName"]
self.taskType = item["taskType"]
status = item["status"]
if status == 3:
print(f'✨ 【{self.taskType}】-已完成')
continue
if self.taskType == 'INTEGRAL_EXCHANGE':
print(f'⚠️ 积分兑换任务暂不支持')
elif self.taskType == 'CLICK_MY_SETTING':
self.taskCode = item["taskCode"]
self.addDeliverPrefer()
if "taskCode" in item:
self.taskCode = item["taskCode"]
self.doTask()
time.sleep(3)
self.receiveTask()
else:
print(f'⚠️ 暂时不支持【{self.title}】任务')
def addDeliverPrefer(self):
print(f'>>>开始【{self.title}】任务')
json_data = {
"country": "中国",
"countryCode": "A000086000",
"province": "北京市",
"provinceCode": "A110000000",
"city": "北京市",
"cityCode": "A111000000",
"county": "东城区",
"countyCode": "A110101000",
"address": "1号楼1单元101",
"latitude": "",
"longitude": "",
"memberId": "",
"locationCode": "010",
"zoneCode": "CN",
"postCode": "",
"takeWay": "7",
"callBeforeDelivery": 'false',
"deliverTag": "2,3,4,1",
"deliverTagContent": "",
"startDeliverTime": "",
"selectCollection": 'false',
"serviceName": "",
"serviceCode": "",
"serviceType": "",
"serviceAddress": "",
"serviceDistance": "",
"serviceTime": "",
"serviceTelephone": "",
"channelCode": "RW11111",
"taskId": self.taskId,
"extJson": "{\"noDeliverDetail\":[]}"
}
url = 'https://ucmp.sf-express.com/cx-wechat-member/member/deliveryPreference/addDeliverPrefer'
response = self.do_request(url, data=json_data)
if response.get('success') == True:
print('新增一个收件偏好,成功')
else:
print(f'>【{self.title}】任务-{response.get("errorMessage")}')
def member_day_index(self):
print('🎭 会员日活动')
try:
invite_user_id = random.choice([invite for invite in inviteId if invite != self.user_id])
payload = {'inviteUserId': invite_user_id}
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~memberDayIndexService~index'
response = self.do_request(url, data=payload)
if response.get('success'):
lottery_num = response.get('obj', {}).get('lotteryNum', 0)
can_receive_invite_award = response.get('obj', {}).get('canReceiveInviteAward', False)
if can_receive_invite_award:
self.member_day_receive_invite_award(invite_user_id)
self.member_day_red_packet_status()
Log(f'🎁 会员日可以抽奖{lottery_num}')
for _ in range(lottery_num):
self.member_day_lottery()
if self.member_day_black:
return
self.member_day_task_list()
if self.member_day_black:
return
self.member_day_red_packet_status()
else:
error_message = response.get('errorMessage', '无返回')
Log(f'📝 查询会员日失败: {error_message}')
if '没有资格参与活动' in error_message:
self.member_day_black = True
Log('📝 会员日任务风控')
except Exception as e:
print(e)
def member_day_receive_invite_award(self, invite_user_id):
try:
payload = {'inviteUserId': invite_user_id}
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~memberDayIndexService~receiveInviteAward'
response = self.do_request(url, payload)
if response.get('success'):
product_name = response.get('obj', {}).get('productName', '空气')
Log(f'🎁 会员日奖励: {product_name}')
else:
error_message = response.get('errorMessage', '无返回')
Log(f'📝 领取会员日奖励失败: {error_message}')
if '没有资格参与活动' in error_message:
self.member_day_black = True
Log('📝 会员日任务风控')
except Exception as e:
print(e)
def member_day_lottery(self):
try:
payload = {}
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~memberDayLotteryService~lottery'
response = self.do_request(url, payload)
if response.get('success'):
product_name = response.get('obj', {}).get('productName', '空气')
Log(f'🎁 会员日抽奖: {product_name}')
else:
error_message = response.get('errorMessage', '无返回')
Log(f'📝 会员日抽奖失败: {error_message}')
if '没有资格参与活动' in error_message:
self.member_day_black = True
Log('📝 会员日任务风控')
except Exception as e:
print(e)
def member_day_task_list(self):
try:
payload = {'activityCode': 'MEMBER_DAY', 'channelType': 'MINI_PROGRAM'}
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~activityTaskService~taskList'
response = self.do_request(url, payload)
if response.get('success'):
task_list = response.get('obj', [])
for task in task_list:
if task['status'] == 1:
if self.member_day_black:
return
self.member_day_fetch_mix_task_reward(task)
for task in task_list:
if task['status'] == 2:
if self.member_day_black:
return
if task['taskType'] in ['SEND_SUCCESS', 'INVITEFRIENDS_PARTAKE_ACTIVITY', 'OPEN_SVIP',
'OPEN_NEW_EXPRESS_CARD', 'OPEN_FAMILY_CARD', 'CHARGE_NEW_EXPRESS_CARD',
'INTEGRAL_EXCHANGE']:
pass
else:
for _ in range(task['restFinishTime']):
if self.member_day_black:
return
self.member_day_finish_task(task)
else:
error_message = response.get('errorMessage', '无返回')
Log('📝 查询会员日任务失败: ' + error_message)
if '没有资格参与活动' in error_message:
self.member_day_black = True
Log('📝 会员日任务风控')
except Exception as e:
print(e)
def member_day_finish_task(self, task):
try:
payload = {'taskCode': task['taskCode']}
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberEs~taskRecord~finishTask'
response = self.do_request(url, payload)
if response.get('success'):
Log('📝 完成会员日任务[' + task['taskName'] + ']成功')
self.member_day_fetch_mix_task_reward(task)
else:
error_message = response.get('errorMessage', '无返回')
Log('📝 完成会员日任务[' + task['taskName'] + ']失败: ' + error_message)
if '没有资格参与活动' in error_message:
self.member_day_black = True
Log('📝 会员日任务风控')
except Exception as e:
print(e)
def member_day_fetch_mix_task_reward(self, task):
try:
payload = {'taskType': task['taskType'], 'activityCode': 'MEMBER_DAY', 'channelType': 'MINI_PROGRAM'}
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~activityTaskService~fetchMixTaskReward'
response = self.do_request(url, payload)
if response.get('success'):
Log('🎁 领取会员日任务[' + task['taskName'] + ']奖励成功')
else:
error_message = response.get('errorMessage', '无返回')
Log('📝 领取会员日任务[' + task['taskName'] + ']奖励失败: ' + error_message)
if '没有资格参与活动' in error_message:
self.member_day_black = True
Log('📝 会员日任务风控')
except Exception as e:
print(e)
def member_day_receive_red_packet(self, hour):
try:
payload = {'receiveHour': hour}
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~memberDayTaskService~receiveRedPacket'
response = self.do_request(url, payload)
if response.get('success'):
print(f'🎁 会员日领取{hour}点红包成功')
else:
error_message = response.get('errorMessage', '无返回')
print(f'📝 会员日领取{hour}点红包失败: {error_message}')
if '没有资格参与活动' in error_message:
self.member_day_black = True
Log('📝 会员日任务风控')
except Exception as e:
print(e)
def member_day_red_packet_status(self):
try:
payload = {}
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~memberDayPacketService~redPacketStatus'
response = self.do_request(url, payload)
if response.get('success'):
packet_list = response.get('obj', {}).get('packetList', [])
for packet in packet_list:
self.member_day_red_packet_map[packet['level']] = packet['count']
for level in range(1, self.max_level):
count = self.member_day_red_packet_map.get(level, 0)
while count >= 2:
self.member_day_red_packet_merge(level)
count -= 2
packet_summary = []
remaining_needed = 0
for level, count in self.member_day_red_packet_map.items():
if count == 0:
continue
packet_summary.append(f"[{level}级]X{count}")
int_level = int(level)
if int_level < self.max_level:
remaining_needed += 1 << (int_level - 1)
Log("📝 会员日合成列表: " + ", ".join(packet_summary))
if self.member_day_red_packet_map.get(self.max_level):
Log(f"🎁 会员日已拥有[{self.max_level}级]红包X{self.member_day_red_packet_map[self.max_level]}")
self.member_day_red_packet_draw(self.max_level)
else:
remaining = self.packet_threshold - remaining_needed
Log(f"📝 会员日距离[{self.max_level}级]红包还差: [1级]红包X{remaining}")
else:
error_message = response.get('errorMessage', '无返回')
Log(f'📝 查询会员日合成失败: {error_message}')
if '没有资格参与活动' in error_message:
self.member_day_black = True
Log('📝 会员日任务风控')
except Exception as e:
print(e)
def member_day_red_packet_merge(self, level):
try:
# for key,level in enumerate(self.member_day_red_packet_map):
# pass
payload = {'level': level, 'num': 2}
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~memberDayPacketService~redPacketMerge'
response = self.do_request(url, payload)
if response.get('success'):
Log(f'🎁 会员日合成: [{level}级]红包X2 -> [{level + 1}级]红包')
self.member_day_red_packet_map[level] -= 2
if not self.member_day_red_packet_map.get(level + 1):
self.member_day_red_packet_map[level + 1] = 0
self.member_day_red_packet_map[level + 1] += 1
else:
error_message = response.get('errorMessage', '无返回')
Log(f'📝 会员日合成两个[{level}级]红包失败: {error_message}')
if '没有资格参与活动' in error_message:
self.member_day_black = True
Log('📝 会员日任务风控')
except Exception as e:
print(e)
def member_day_red_packet_draw(self, level):
try:
payload = {'level': str(level)}
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~memberDayPacketService~redPacketDraw'
response = self.do_request(url, payload)
if response and response.get('success'):
coupon_names = [item['couponName'] for item in response.get('obj', [])] or []
Log(f"🎁 会员日提取[{level}级]红包: {', '.join(coupon_names) or '空气'}")
else:
error_message = response.get('errorMessage') if response else "无返回"
Log(f"📝 会员日提取[{level}级]红包失败: {error_message}")
if "没有资格参与活动" in error_message:
self.memberDay_black = True
print("📝 会员日任务风控")
except Exception as e:
print(e)
def main(self):
global one_msg
wait_time = random.randint(1000, 3000) / 1000.0
time.sleep(wait_time)
one_msg = ''
if not self.login_res: return False
self.sign()
self.superWelfare_receiveRedPacket()
self.get_SignTaskList()
self.get_SignTaskList(True)
current_date = datetime.now().day
if 26 <= current_date <= 28:
self.member_day_index()
else:
print('⏰ 未到指定时间不执行会员日任务\n==================================\n')
return True
def main():
ENV_NAME = 'sfsyUrl'
local_version = '2025.10.08'
token = os.getenv(ENV_NAME)
if not token:
print(f"❌ 未找到环境变量 {ENV_NAME},请检查配置")
return
tokens = token.split('&')
tokens = [t.strip() for t in tokens if t.strip()]
if len(tokens) == 0:
print(f"❌ 环境变量 {ENV_NAME} 为空或格式错误")
return
print(f"==================================")
print(f"🎉 呆呆粉丝后援会996374999")
print(f"🚚 顺丰速运脚本 v{local_version}")
print(f"📱 共获取到{len(tokens)}个账号")
print(f"😣 修改By:呆呆呆呆")
print(f"==================================")
for index, infos in enumerate(tokens):
run_result = RUN(infos, index).main()
if not run_result: continue
if __name__ == '__main__':
main()
# 当前脚本来自于http://script.345yun.cn脚本库下载