mirror of
https://github.com/Ytong825/mao.git
synced 2025-12-16 23:10:06 +08:00
639 lines
26 KiB
Python
639 lines
26 KiB
Python
import hashlib
|
||
import json
|
||
import os
|
||
import random
|
||
import time
|
||
from datetime import datetime
|
||
from urllib.parse import unquote
|
||
import requests
|
||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||
|
||
# 禁用安全请求警告
|
||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||
|
||
# 全局消息变量
|
||
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'
|
||
|
||
# 邀请ID列表
|
||
inviteId = ['076CFC24BDE249BB8E7994DDE85E605F']
|
||
|
||
class SFRunner:
|
||
def __init__(self, info, index):
|
||
global one_msg
|
||
one_msg = ''
|
||
split_info = info.split('@')
|
||
self.url = split_info[0]
|
||
self.index = index + 1
|
||
Log(f"\n🚀 ========== 开始执行第{self.index}个账号 ==========")
|
||
|
||
# 初始化会话
|
||
self.s = requests.session()
|
||
self.s.verify = False
|
||
|
||
# 请求头信息
|
||
self.headers = {
|
||
'Host': 'mcs-mimp-web.sf-express.com',
|
||
'upgrade-insecure-requests': '1',
|
||
'user-agent': 'Mozilla/5.0 (Linux; Android 15; 22061218C Build/AQ3A.241006.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/116.0.0.0 Mobile Safari/537.36 XWEB/1160117 MMWEBSDK/20250503 MMWEBID/6435 MicroMessenger/8.0.61.2861(0x28003D41) WeChat/arm64 Weixin GPVersion/1 NetType/WIFI Language/zh_CN ABI/arm64 miniProgram/wxd4185d00bf7e08ac',
|
||
'accept': 'application/json, text/plain, */*',
|
||
'content-type': 'application/json',
|
||
'sec-fetch-site': 'same-origin',
|
||
'sec-fetch-mode': 'cors',
|
||
'sec-fetch-dest': 'empty',
|
||
'accept-language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7',
|
||
'platform': 'MINI_PROGRAM',
|
||
'channel': '25zqappdb2',
|
||
}
|
||
|
||
# 登录并初始化用户信息
|
||
self.login_res = self.login()
|
||
self.today = datetime.now().strftime('%Y-%m-%d')
|
||
self.activity_code = 'MIDAUTUMN_2025'
|
||
self.recommend_tasks = []
|
||
|
||
def login(self):
|
||
"""用户登录"""
|
||
ress = self.s.get(self.url, headers=self.headers)
|
||
cookies = self.s.cookies.get_dict()
|
||
self.user_id = cookies.get('_login_user_id_', '')
|
||
self.phone = cookies.get('_login_mobile_', '')
|
||
|
||
if self.phone:
|
||
self.mobile = self.phone[:3] + "*" * 4 + self.phone[7:]
|
||
Log(f'✅ 用户【{self.mobile}】登录成功')
|
||
return True
|
||
else:
|
||
Log(f'❌ 获取用户信息失败')
|
||
return False
|
||
|
||
def get_sign(self):
|
||
"""生成签名信息"""
|
||
timestamp = str(int(round(time.time() * 1000)))
|
||
token = 'wwesldfs29aniversaryvdld29'
|
||
sys_code = 'MCS-MIMP-CORE'
|
||
data = f'token={token}×tamp={timestamp}&sysCode={sys_code}'
|
||
signature = hashlib.md5(data.encode()).hexdigest()
|
||
|
||
sign_data = {
|
||
'sysCode': sys_code,
|
||
'timestamp': timestamp,
|
||
'signature': signature
|
||
}
|
||
self.headers.update(sign_data)
|
||
return sign_data
|
||
|
||
def do_request(self, url, data={}, req_type='post'):
|
||
"""通用请求处理"""
|
||
self.get_sign()
|
||
try:
|
||
if req_type.lower() == 'get':
|
||
response = self.s.get(url, headers=self.headers)
|
||
else:
|
||
response = self.s.post(url, headers=self.headers, json=data)
|
||
return response.json()
|
||
except (requests.exceptions.RequestException, json.JSONDecodeError) as e:
|
||
Log(f'请求错误: {str(e)}')
|
||
return None
|
||
|
||
def check_activity_status(self):
|
||
"""检查中秋活动状态"""
|
||
Log('🌙 ====== 查询中秋活动状态 ======')
|
||
try:
|
||
# 选择邀请ID
|
||
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/commonNoLoginPost/~memberNonactivity~midAutumn2025IndexService~index'
|
||
|
||
response = self.do_request(url, payload)
|
||
if response and response.get('success'):
|
||
obj = response.get('obj', {})
|
||
ac_end_time = obj.get('acEndTime', '')
|
||
|
||
if ac_end_time and datetime.now() < datetime.strptime(ac_end_time, "%Y-%m-%d %H:%M:%S"):
|
||
Log(f'🎉 2025中秋活动进行中,结束时间:{ac_end_time}')
|
||
self.activity_code = obj.get('actCode', 'MIDAUTUMN_2025')
|
||
self.recommend_tasks = obj.get('recommendTasks', [])
|
||
return True
|
||
Log('⏰ 2025中秋活动已结束')
|
||
else:
|
||
error_msg = response.get('errorMessage', '无返回') if response else '请求失败'
|
||
Log(f'❌ 查询中秋活动失败: {error_msg}')
|
||
except Exception as e:
|
||
Log(f'⚠️ 活动状态查询错误: {str(e)}')
|
||
return False
|
||
|
||
def play_game(self):
|
||
"""完成中秋游戏任务"""
|
||
Log('🎮 ====== 完成中秋游戏任务 ======')
|
||
try:
|
||
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~midAutumn2025GameService~win'
|
||
|
||
# 请求4次,levelIndex从1到4
|
||
for level in range(1, 5):
|
||
payload = {"levelIndex": level}
|
||
Log(f'🎯 开始游戏关卡 {level}')
|
||
|
||
response = self.do_request(url, payload)
|
||
if response and response.get('success'):
|
||
obj = response.get('obj', {})
|
||
pass_rank = obj.get('passRank', 0)
|
||
exceed_percent = obj.get('exceedPercent', 0)
|
||
current_award = obj.get('currentAward', {})
|
||
currency = current_award.get('currency', '')
|
||
amount = current_award.get('amount', 0)
|
||
Log(f'🎁 奖励: {currency} x{amount}')
|
||
else:
|
||
error_msg = response.get('errorMessage', '无返回') if response else '请求失败'
|
||
Log(f'❌ 游戏关卡 {level} 完成失败: {error_msg}')
|
||
|
||
# 关卡间隔,避免请求过于频繁
|
||
time.sleep(random.randint(5, 15))
|
||
Log(f'✅ 游戏关卡 {level} 完成成功')
|
||
Log(f'📊 排名: {pass_rank}, 超越: {exceed_percent*100:.1f}%')
|
||
|
||
except Exception as e:
|
||
Log(f'⚠️ 游戏任务错误: {str(e)}')
|
||
|
||
def process_tasks(self):
|
||
"""处理中秋活动任务"""
|
||
Log('📋 ====== 处理中秋活动任务 ======')
|
||
try:
|
||
payload = {
|
||
"activityCode": self.activity_code,
|
||
"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 and response.get('success'):
|
||
task_list = response.get('obj', []) or self.recommend_tasks
|
||
|
||
for task in task_list:
|
||
task_name = task.get('val', task.get('taskName', '未知任务'))
|
||
status = task.get('status', 0)
|
||
|
||
if status == 3:
|
||
Log(f'✅ 中秋任务【{task_name}】已完成')
|
||
continue
|
||
|
||
Log(f'🔄 开始完成中秋任务【{task_name}】')
|
||
if task_name == '玩一笔连兔游戏':
|
||
self.play_game()
|
||
continue
|
||
task_code = task.get('key', task.get('taskCode'))
|
||
if task_code:
|
||
self.finish_task(task, task_code)
|
||
time.sleep(2) # 任务间隔,避免请求过于频繁
|
||
|
||
# 完成所有任务后尝试领取倒计时奖励
|
||
self.receive_countdown_reward()
|
||
else:
|
||
error_msg = response.get('errorMessage', '无返回') if response else '请求失败'
|
||
Log(f'❌ 查询中秋任务失败: {error_msg}')
|
||
except Exception as e:
|
||
Log(f'⚠️ 任务处理错误: {str(e)}')
|
||
|
||
def finish_task(self, task, task_code):
|
||
"""完成指定任务"""
|
||
try:
|
||
payload = {'taskCode': task_code}
|
||
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberEs~taskRecord~finishTask'
|
||
|
||
response = self.do_request(url, payload)
|
||
task_name = task.get('val', task.get('taskName', '未知任务'))
|
||
|
||
if response and response.get('success'):
|
||
Log(f'✅ 完成中秋任务【{task_name}】成功')
|
||
self.receive_task_reward(task)
|
||
else:
|
||
error_msg = response.get('errorMessage', '无返回') if response else '请求失败'
|
||
Log(f'❌ 完成中秋任务【{task_name}】失败: {error_msg}')
|
||
except Exception as e:
|
||
Log(f'⚠️ 任务执行错误: {str(e)}')
|
||
|
||
def receive_task_reward(self, task):
|
||
"""领取任务奖励"""
|
||
try:
|
||
payload = {
|
||
'taskType': task.get('taskType', ''),
|
||
'activityCode': self.activity_code,
|
||
'channelType': 'MINI_PROGRAM'
|
||
}
|
||
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~activityTaskService~fetchMixTaskReward'
|
||
|
||
response = self.do_request(url, payload)
|
||
task_name = task.get('val', task.get('taskName', '未知任务'))
|
||
|
||
if response and response.get('success'):
|
||
Log(f'🎁 领取中秋任务【{task_name}】奖励成功')
|
||
else:
|
||
error_msg = response.get('errorMessage', '无返回') if response else '请求失败'
|
||
Log(f'❌ 领取中秋任务【{task_name}】奖励失败: {error_msg}')
|
||
except Exception as e:
|
||
Log(f'⚠️ 奖励领取错误: {str(e)}')
|
||
|
||
def receive_countdown_reward(self):
|
||
"""领取倒计时奖励"""
|
||
Log('⏰ ====== 尝试领取倒计时奖励 ======')
|
||
try:
|
||
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~midAutumn2025BoxService~receiveCountdownReward'
|
||
response = self.do_request(url, {})
|
||
|
||
if response and response.get('success', False):
|
||
Log(f'🎁 领取倒计时奖励成功')
|
||
else:
|
||
error_msg = response.get('errorMessage', '无返回信息') if response else '请求失败'
|
||
Log(f'❌ 领取倒计时奖励失败: {error_msg}')
|
||
except Exception as e:
|
||
Log(f'⚠️ 倒计时奖励领取错误: {str(e)}')
|
||
|
||
def unbox_mystery_boxes(self):
|
||
"""拆盲盒功能"""
|
||
Log('📦 ====== 开始拆盲盒任务 ======')
|
||
try:
|
||
# 循环拆盲盒直到用完所有机会
|
||
while True:
|
||
# 获取当前盲盒状态
|
||
box_status = self.get_box_status()
|
||
if not box_status:
|
||
break
|
||
|
||
remain_chance = box_status.get('remainBoxChance', 0)
|
||
total_box_times = box_status.get('totalBoxTimes', 0)
|
||
level_box_times = box_status.get('levelBoxTimes', 0)
|
||
|
||
Log(f'📊 总拆盲盒次数: {total_box_times}, 当前关卡次数: {level_box_times}, 剩余机会: {remain_chance}')
|
||
|
||
if remain_chance <= 0:
|
||
Log('✅ 所有拆盲盒机会已用完')
|
||
break
|
||
|
||
# 获取当前关卡配置信息
|
||
current_level_config = box_status.get('currentLevelConfig', {})
|
||
current_level = current_level_config.get('level', 1)
|
||
board_length = current_level_config.get('boardLength', 4)
|
||
target_shape_num = current_level_config.get('targetShapeNum', 2)
|
||
|
||
board_status = box_status.get('boardStatus', {})
|
||
target_shapes = board_status.get('t', [])
|
||
board_data = board_status.get('b', '')
|
||
|
||
Log(f'🎯 当前关卡: {current_level}')
|
||
Log(f'🎯 盲盒尺寸: {board_length}x{board_length}')
|
||
Log(f'🎯 目标形状数量: {target_shape_num}')
|
||
Log(f'🎯 需要开启的盲盒总数: {target_shape_num * 4}')
|
||
|
||
# 解析当前盲盒状态
|
||
try:
|
||
if board_data:
|
||
board_matrix = json.loads(board_data)
|
||
else:
|
||
# 初始状态,创建空白盲盒矩阵
|
||
Log('📋 检测到初始状态,创建空白盲盒矩阵')
|
||
board_matrix = []
|
||
for i in range(board_length):
|
||
row = []
|
||
for j in range(board_length):
|
||
row.append({"t": "", "s": "n"})
|
||
board_matrix.append(row)
|
||
except Exception as e:
|
||
Log(f'❌ 解析盲盒状态失败: {str(e)}')
|
||
break
|
||
|
||
# 开始拆当前关卡的盲盒
|
||
level_completed = self.process_unboxing(board_matrix, target_shapes, target_shape_num, board_length)
|
||
|
||
if level_completed:
|
||
Log(f'🎉 关卡 {current_level} 完成!')
|
||
# 等待一下再检查下一关
|
||
time.sleep(random.randint(3, 6))
|
||
else:
|
||
Log(f'❌ 关卡 {current_level} 未完成,停止拆盲盒')
|
||
break
|
||
|
||
# 所有拆盲盒完成后进行抽奖
|
||
final_box_status = self.get_box_status()
|
||
if final_box_status:
|
||
passed_level_list = final_box_status.get('passedLevelList', [])
|
||
self.process_lottery(passed_level_list)
|
||
|
||
except Exception as e:
|
||
Log(f'⚠️ 拆盲盒任务错误: {str(e)}')
|
||
|
||
def get_box_status(self):
|
||
"""获取盲盒状态"""
|
||
Log('📋 获取盲盒状态...')
|
||
try:
|
||
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~midAutumn2025BoxService~boxStatus'
|
||
response = self.do_request(url, {})
|
||
|
||
if response and response.get('success'):
|
||
Log('✅ 获取盲盒状态成功')
|
||
return response.get('obj', {})
|
||
else:
|
||
error_msg = response.get('errorMessage', '无返回') if response else '请求失败'
|
||
Log(f'❌ 获取盲盒状态失败: {error_msg}')
|
||
return None
|
||
except Exception as e:
|
||
Log(f'⚠️ 获取盲盒状态错误: {str(e)}')
|
||
return None
|
||
|
||
def get_unbox_token(self):
|
||
"""获取拆盲盒token"""
|
||
Log('🔑 获取拆盲盒token...')
|
||
try:
|
||
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~midAutumn2025BoxService~unBox'
|
||
response = self.do_request(url, {})
|
||
|
||
if response and response.get('success'):
|
||
obj = response.get('obj', {})
|
||
token = obj.get('token', '')
|
||
empty_box = obj.get('emptyBox', True)
|
||
Log(f'✅ 获取token成功: {token[:8]}...')
|
||
return token, empty_box
|
||
else:
|
||
error_msg = response.get('errorMessage', '无返回') if response else '请求失败'
|
||
Log(f'❌ 获取token失败: {error_msg}')
|
||
return None, None
|
||
except Exception as e:
|
||
Log(f'⚠️ 获取token错误: {str(e)}')
|
||
return None, None
|
||
|
||
def process_unboxing(self, board_matrix, target_shapes, target_shape_num, board_length):
|
||
"""处理拆盲盒逻辑"""
|
||
Log('🎮 开始拆盲盒流程...')
|
||
|
||
# 统计每个形状需要开启的数量
|
||
shape_counts = {}
|
||
for shape in target_shapes:
|
||
shape_type = shape.get('s', '')
|
||
if shape_type:
|
||
shape_counts[shape_type] = 0
|
||
|
||
# 如果没有目标形状,说明是初始状态,需要根据配置创建
|
||
if not shape_counts and target_shape_num > 0:
|
||
Log('📋 初始状态,根据配置创建形状标记')
|
||
# 常见的形状标记,可以根据实际情况调整
|
||
common_shapes = ['O', 'I', 'T', 'L', 'S', 'Z', 'J']
|
||
for i in range(min(target_shape_num, len(common_shapes))):
|
||
shape_counts[common_shapes[i]] = 0
|
||
|
||
# 先处理已经开启但未标记的盲盒
|
||
for i in range(board_length):
|
||
for j in range(board_length):
|
||
cell = board_matrix[i][j]
|
||
if cell.get('s') == 'y':
|
||
# 找到合适的形状标记
|
||
for shape_type in shape_counts:
|
||
if shape_counts[shape_type] < 4:
|
||
cell['t'] = shape_type
|
||
shape_counts[shape_type] += 1
|
||
break
|
||
|
||
# 计算还需要开启的盲盒数量
|
||
total_needed = target_shape_num * 4
|
||
total_opened = sum(shape_counts.values())
|
||
remaining_needed = total_needed - total_opened
|
||
|
||
Log(f'📊 已开启: {total_opened}, 还需开启: {remaining_needed}')
|
||
|
||
# 检查是否已经完成所有盲盒,如果完成则直接报告完成状态
|
||
if total_opened >= total_needed:
|
||
Log(f'🎉 检测到当前关卡已完成所有盲盒 ({total_opened}/{total_needed}),直接提交完成状态')
|
||
success = self.report_unbox(board_matrix, target_shapes, is_final=True, shape_counts=shape_counts)
|
||
if success:
|
||
Log(f'✅ 当前关卡完成状态提交成功')
|
||
return True
|
||
else:
|
||
Log(f'❌ 当前关卡完成状态提交失败')
|
||
return False
|
||
|
||
# 继续开启剩余的盲盒
|
||
opened_count = 0
|
||
for i in range(board_length):
|
||
for j in range(board_length):
|
||
if opened_count >= remaining_needed:
|
||
break
|
||
|
||
cell = board_matrix[i][j]
|
||
if cell.get('s') == 'n' and cell.get('t') == '':
|
||
# 找到需要开启的形状类型
|
||
for shape_type in shape_counts:
|
||
if shape_counts[shape_type] < 4:
|
||
cell['s'] = 'y'
|
||
cell['t'] = shape_type
|
||
shape_counts[shape_type] += 1
|
||
opened_count += 1
|
||
|
||
# 发送开盲盒请求
|
||
is_final = sum(shape_counts.values()) >= total_needed
|
||
success = self.report_unbox(board_matrix, target_shapes, is_final, shape_counts)
|
||
if not success:
|
||
Log('❌ 拆盲盒请求失败,停止当前关卡')
|
||
return False
|
||
time.sleep(random.randint(2, 5))
|
||
|
||
# 如果是最后一个盲盒,返回成功
|
||
if is_final:
|
||
return True
|
||
break
|
||
if opened_count >= remaining_needed:
|
||
break
|
||
|
||
# 检查是否完成了所有需要的盲盒
|
||
total_opened = sum(shape_counts.values())
|
||
if total_opened >= total_needed:
|
||
Log(f'✅ 当前关卡所有盲盒已完成 ({total_opened}/{total_needed})')
|
||
return True
|
||
else:
|
||
Log(f'⚠️ 当前关卡未完成 ({total_opened}/{total_needed})')
|
||
return False
|
||
|
||
def report_unbox(self, board_matrix, target_shapes, is_final=False, shape_counts=None):
|
||
"""报告开盲盒结果"""
|
||
try:
|
||
# 获取token
|
||
token, empty_box = self.get_unbox_token()
|
||
if not token:
|
||
return False
|
||
|
||
# 构建target_shapes,如果原始为空且有shape_counts,则重新构建
|
||
if not target_shapes and shape_counts:
|
||
target_shapes = []
|
||
for shape_type in shape_counts:
|
||
target_shapes.append({"s": shape_type, "p": "j"}) # p值可以是固定的
|
||
|
||
# 构建请求数据
|
||
board_data = json.dumps(board_matrix, separators=(',', ':'))
|
||
payload = {
|
||
"token": token,
|
||
"boardStatus": {
|
||
"b": board_data,
|
||
"t": target_shapes
|
||
},
|
||
"levelPass": is_final,
|
||
"emptyBox": empty_box,
|
||
"taskType": ""
|
||
}
|
||
|
||
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~midAutumn2025BoxService~reportBox'
|
||
response = self.do_request(url, payload)
|
||
|
||
if response and response.get('success'):
|
||
if is_final:
|
||
Log('🎉 完成所有盲盒拆解!')
|
||
else:
|
||
Log('✅ 盲盒拆解成功')
|
||
return True
|
||
else:
|
||
error_msg = response.get('errorMessage', '无返回') if response else '请求失败'
|
||
Log(f'❌ 盲盒拆解失败: {error_msg}')
|
||
return False
|
||
|
||
except Exception as e:
|
||
Log(f'⚠️ 盲盒拆解错误: {str(e)}')
|
||
return False
|
||
|
||
def process_lottery(self, passed_level_list):
|
||
"""处理抽奖功能"""
|
||
# 检查是否启用抽奖功能
|
||
lottery_enabled = os.getenv('S_SFZQ_CJ', 'true').lower() == 'true'
|
||
if not lottery_enabled:
|
||
Log('🎰 ====== 抽奖功能已禁用 ======')
|
||
Log('💡 如需启用抽奖功能,请设置环境变量 S_SFZQ_CJ=true')
|
||
return
|
||
|
||
Log('🎰 ====== 检查抽奖机会 ======')
|
||
try:
|
||
if not passed_level_list:
|
||
Log('📋 没有已通过的关卡信息')
|
||
return
|
||
|
||
# 检查每个关卡的抽奖机会
|
||
lottery_available = False
|
||
for level_info in passed_level_list:
|
||
currency = level_info.get('currency', '')
|
||
balance = level_info.get('balance', 0)
|
||
total_amount = level_info.get('totalAmount', 0)
|
||
|
||
Log(f'📊 关卡【{currency}】- 总奖励: {total_amount}, 剩余抽奖机会: {balance}')
|
||
|
||
if balance > 0:
|
||
lottery_available = True
|
||
# 进行抽奖
|
||
for i in range(balance):
|
||
Log(f'🎯 开始抽奖 - 关卡【{currency}】第{i+1}次')
|
||
self.draw_prize(currency)
|
||
time.sleep(random.randint(2, 4)) # 抽奖间隔
|
||
|
||
if not lottery_available:
|
||
Log('📋 没有可用的抽奖机会')
|
||
|
||
except Exception as e:
|
||
Log(f'⚠️ 抽奖处理错误: {str(e)}')
|
||
|
||
def draw_prize(self, currency):
|
||
"""执行抽奖"""
|
||
try:
|
||
payload = {"currency": currency}
|
||
url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~midAutumn2025LotteryService~prizeDraw'
|
||
|
||
response = self.do_request(url, payload)
|
||
if response and response.get('success'):
|
||
obj = response.get('obj', {})
|
||
gift_bag_name = obj.get('giftBagName', '未知奖品')
|
||
gift_bag_worth = obj.get('giftBagWorth', 0)
|
||
|
||
# 获取奖品详情
|
||
product_list = obj.get('productDTOList', [])
|
||
product_details = []
|
||
for product in product_list:
|
||
product_name = product.get('productName', '')
|
||
amount = product.get('amount', 0)
|
||
if product_name:
|
||
product_details.append(f'{product_name} x{amount}')
|
||
|
||
Log(f'🎉 抽奖成功!获得奖品:【{gift_bag_name}】')
|
||
Log(f'💰 奖品价值:{gift_bag_worth}元')
|
||
if product_details:
|
||
Log(f'📦 奖品详情:{", ".join(product_details)}')
|
||
|
||
else:
|
||
error_msg = response.get('errorMessage', '无返回') if response else '请求失败'
|
||
Log(f'❌ 抽奖失败: {error_msg}')
|
||
|
||
except Exception as e:
|
||
Log(f'⚠️ 抽奖错误: {str(e)}')
|
||
|
||
def run(self):
|
||
"""主运行函数"""
|
||
# 随机等待避免风控
|
||
time.sleep(random.randint(1000, 3000) / 1000.0)
|
||
|
||
if not self.login_res:
|
||
return False
|
||
|
||
# 执行活动任务
|
||
if self.check_activity_status():
|
||
self.process_tasks()
|
||
# 完成任务后拆盲盒
|
||
self.unbox_mystery_boxes()
|
||
|
||
self.send_msg()
|
||
return True
|
||
|
||
def send_msg(self, help=False):
|
||
"""消息推送功能(预留)"""
|
||
pass
|
||
|
||
if __name__ == '__main__':
|
||
APP_NAME = '顺丰速运2025中秋活动'
|
||
ENV_NAME = 'sfsyUrl'
|
||
|
||
print(f'''
|
||
🌙 ========================================
|
||
顺丰速运2025中秋活动自动化脚本
|
||
变量名:sfsyUrl(多账号请换行)
|
||
功能:自动完成中秋活动任务,包括领取倒计时奖励
|
||
抽奖控制:S_SFZQ_CJ(true=抽奖,false=不抽奖,默认false)
|
||
🌙 ========================================
|
||
''')
|
||
|
||
token = os.getenv(ENV_NAME)
|
||
if not token:
|
||
print("❌ 请设置环境变量 sfsyUrl")
|
||
exit(1)
|
||
|
||
# 检查抽奖控制环境变量
|
||
lottery_control = os.getenv('S_SFZQ_CJ', 'false').lower()
|
||
lottery_status = "启用" if lottery_control == 'true' else "禁用"
|
||
print(f"🎰 抽奖功能状态:{lottery_status}")
|
||
if lottery_control not in ['true', 'false']:
|
||
print("⚠️ 环境变量 S_SFZQ_CJ 值无效,将使用默认值 false")
|
||
|
||
# 分割账号信息并进行URL解码
|
||
tokens = token.split('&')
|
||
decoded_tokens = []
|
||
|
||
for token_item in tokens:
|
||
if token_item.strip():
|
||
# 对每个账号信息进行URL解码
|
||
decoded_token = unquote(token_item.strip())
|
||
decoded_tokens.append(decoded_token)
|
||
|
||
print(f"\n🎯 ========== 共获取到{len(decoded_tokens)}个账号 ==========")
|
||
|
||
for index, info in enumerate(decoded_tokens):
|
||
if info.strip():
|
||
if not SFRunner(info, index).run():
|
||
continue
|