|
|
import datetime
|
|
|
import os
|
|
|
import random
|
|
|
import time
|
|
|
|
|
|
import requests
|
|
|
import base64
|
|
|
import json
|
|
|
|
|
|
|
|
|
from notify import send
|
|
|
from notify import sendEmail
|
|
|
|
|
|
# 微信公众号@爱上羊毛侠 二次开发
|
|
|
|
|
|
# 微信公众号@小白技术社首发
|
|
|
|
|
|
# 青龙面板加入环境变量Mt_Version和MTTokenD
|
|
|
# MTTokenD是茅台预约参数,多个请换行,格式'省份,城市,经度,维度,设备id,token,MT-Token-Wap(抓包小茅运)'
|
|
|
# Mt_Version是app版本号如 1.3.6 必填(填最新版本,目前好像没法获取)
|
|
|
# MT-Token-Wap参数是小茅运的领奖励,不需要的话MTTokenD格式改成 省份,城市,经度,维度,设备id,token,''
|
|
|
|
|
|
p_c_map = {}
|
|
|
mt_r = 'clips_OlU6TmFRag5rCXwbNAQ/Tz1SKlN8THcecBp/'
|
|
|
# res_map = {'10213': '贵州茅台酒(癸卯兔年)', '2476': '贵州茅台酒(壬寅虎年)', '2478': '贵州茅台酒(珍品)',
|
|
|
# '10214': '贵州茅台酒(癸卯兔年)x2'}
|
|
|
# 下面定义的是申请哪几个,想申请全部的话把上面注释删掉,把下面的注释掉
|
|
|
res_map = {'10941': '贵州茅台酒(甲辰龙年)',
|
|
|
'10942': '贵州茅台酒(甲辰龙年)x2'}
|
|
|
|
|
|
|
|
|
def mt_add(itemId, shopId, sessionId, userId, token, Device_ID):
|
|
|
MT_K = f'{int(time.time() * 1000)}'
|
|
|
r = requests.get(
|
|
|
f'http://82.157.10.108:8086/get_mtv?DeviceID={Device_ID}&MTk={MT_K}&version={mt_version}&key=yaohuo')
|
|
|
headers = {'User-Agent': 'iPhone 14',
|
|
|
'MT-Token': token,
|
|
|
'MT-Network-Type': 'WIFI', 'MT-User-Tag': '0',
|
|
|
'MT-R': mt_r, 'MT-Lat': '', 'MT-K': MT_K,
|
|
|
'MT-Lng': '', 'MT-Info': '028e7f96f6369cafe1d105579c5b9377', 'MT-APP-Version': mt_version,
|
|
|
'MT-Request-ID': f'{int(time.time() * 1000)}', 'Accept-Language': 'zh-Hans-CN;q=1',
|
|
|
'MT-Device-ID': Device_ID, 'MT-V': r.text,
|
|
|
'MT-Bundle-ID': 'com.moutai.mall',
|
|
|
'mt-lng': lng,
|
|
|
'mt-lat': lat}
|
|
|
d = {"itemInfoList": [{"count": 1, "itemId": str(itemId)}], "sessionId": sessionId, "userId": str(userId),
|
|
|
"shopId": str(shopId)}
|
|
|
r = requests.get('http://82.157.10.108:8086/get_actParam?key=yaohuo&actParam=' + base64.b64encode(
|
|
|
json.dumps(d).replace(' ', '').encode('utf8')).decode())
|
|
|
d['actParam'] = r.text
|
|
|
json_data = d
|
|
|
response = requests.post('https://app.moutai519.com.cn/xhr/front/mall/reservation/add', headers=headers,
|
|
|
json=json_data)
|
|
|
code = response.json().get('code', 0)
|
|
|
if code == 2000:
|
|
|
# 成功
|
|
|
return response.json().get('data', {}).get('successDesc', "未知")
|
|
|
|
|
|
return '申购失败:' + response.json().get('message', "未知原因")
|
|
|
|
|
|
|
|
|
def tongzhi(ss):
|
|
|
user_list = os.getenv('mtec_user', '').split(',')
|
|
|
for user in user_list:
|
|
|
url = 'http://wxpusher.zjiecode.com/api/send/message/?appToken=&content={}&uid={}'.format(
|
|
|
ss, user)
|
|
|
r = requests.get(url)
|
|
|
print(r.text)
|
|
|
|
|
|
|
|
|
def get_session_id(device_id, token):
|
|
|
headers = {
|
|
|
'mt-device-id': device_id,
|
|
|
'mt-user-tag': '0',
|
|
|
'accept': '*/*',
|
|
|
'mt-network-type': 'WIFI',
|
|
|
'mt-token': token,
|
|
|
'mt-bundle-id': 'com.moutai.mall',
|
|
|
'accept-language': 'zh-Hans-CN;q=1',
|
|
|
'mt-request-id': f'{int(time.time() * 1000)}',
|
|
|
'mt-app-version': mt_version,
|
|
|
'user-agent': 'iPhone 14',
|
|
|
'mt-r': mt_r,
|
|
|
'mt-lng': lng,
|
|
|
'mt-lat': lat
|
|
|
}
|
|
|
|
|
|
response = requests.get('https://static.moutai519.com.cn/mt-backend/xhr/front/mall/index/session/get/' + time_keys,
|
|
|
headers=headers)
|
|
|
sessionId = response.json().get('data', {}).get('sessionId')
|
|
|
itemList = response.json().get('data', {}).get('itemList', [])
|
|
|
itemCodes = [item.get('itemCode') for item in itemList]
|
|
|
return sessionId, itemCodes
|
|
|
|
|
|
|
|
|
def get_shop_item(sessionId, itemId, device_id, token, province, city):
|
|
|
headers = {
|
|
|
'mt-device-id': device_id,
|
|
|
'mt-user-tag': '0',
|
|
|
'mt-lat': '',
|
|
|
'accept': '*/*',
|
|
|
'mt-network-type': 'WIFI',
|
|
|
'mt-token': token,
|
|
|
'mt-bundle-id': 'com.moutai.mall',
|
|
|
'accept-language': 'zh-Hans-CN;q=1',
|
|
|
'mt-request-id': f'{int(time.time() * 1000)}',
|
|
|
'mt-r': mt_r,
|
|
|
'mt-app-version': mt_version,
|
|
|
'user-agent': 'iPhone 14',
|
|
|
'mt-lng': lng,
|
|
|
'mt-lat': lat
|
|
|
}
|
|
|
|
|
|
response = requests.get(
|
|
|
'https://static.moutai519.com.cn/mt-backend/xhr/front/mall/shop/list/slim/v3/' + str(
|
|
|
sessionId) + '/' + province + '/' + str(itemId) + '/' + time_keys,
|
|
|
headers=headers)
|
|
|
data = response.json().get('data', {})
|
|
|
shops = data.get('shops', [])
|
|
|
shop_id_ = p_c_map[province][city]
|
|
|
for shop in shops:
|
|
|
if not shop.get('shopId') in shop_id_:
|
|
|
continue
|
|
|
if itemId in str(shop):
|
|
|
if shop.get('shopId') == "132320282001":
|
|
|
print("无锡下级县市continue:itemId:",itemId,"shopId:",shop.get('shopId'))
|
|
|
continue
|
|
|
else:
|
|
|
print("申购详情:itemId:",itemId,"shopId:",shop.get('shopId'))
|
|
|
return shop.get('shopId')
|
|
|
|
|
|
|
|
|
def get_user_id(token, Device_ID):
|
|
|
headers = {
|
|
|
'MT-User-Tag': '0',
|
|
|
'Accept': '*/*',
|
|
|
'MT-Network-Type': 'WIFI',
|
|
|
'MT-Token': token,
|
|
|
'MT-Bundle-ID': 'com.moutai.mall',
|
|
|
'Accept-Language': 'zh-Hans-CN;q=1, en-CN;q=0.9',
|
|
|
'MT-Request-ID': f'{int(time.time() * 1000)}',
|
|
|
'MT-APP-Version': mt_version,
|
|
|
'User-Agent': 'iOS;16.0.1;Apple;iPhone 14 ProMax',
|
|
|
'MT-R': mt_r,
|
|
|
'MT-Device-ID': Device_ID,
|
|
|
'mt-lng': lng,
|
|
|
'mt-lat': lat
|
|
|
}
|
|
|
|
|
|
response = requests.get(
|
|
|
'https://app.moutai519.com.cn/xhr/front/user/info', headers=headers)
|
|
|
userName = response.json().get('data', {}).get('userName')
|
|
|
userId = response.json().get('data', {}).get('userId')
|
|
|
mobile = response.json().get('data', {}).get('mobile')
|
|
|
return userName, userId, mobile
|
|
|
|
|
|
|
|
|
def getUserEnergyAward(device_id, ck):
|
|
|
"""
|
|
|
领取耐力
|
|
|
:return:
|
|
|
"""
|
|
|
|
|
|
cookies = {
|
|
|
'MT-Device-ID-Wap': device_id,
|
|
|
'MT-Token-Wap': ck,
|
|
|
'YX_SUPPORT_WEBP': '1',
|
|
|
}
|
|
|
|
|
|
headers = {
|
|
|
'X-Requested-With': 'XMLHttpRequest',
|
|
|
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_2_1 like Mac OS X)',
|
|
|
'Referer': 'https://h5.moutai519.com.cn/gux/game/main?appConfig=2_1_2',
|
|
|
'Client-User-Agent': 'iOS;15.0.1;Apple;iPhone 12 ProMax',
|
|
|
'MT-R': mt_r,
|
|
|
'Origin': 'https://h5.moutai519.com.cn',
|
|
|
'MT-APP-Version': mt_version,
|
|
|
'MT-Request-ID': f'{int(time.time() * 1000)}',
|
|
|
'Accept-Language': 'zh-CN,zh-Hans;q=0.9',
|
|
|
'MT-Device-ID': device_id,
|
|
|
'Accept': 'application/json, text/javascript, */*; q=0.01',
|
|
|
'mt-lng': lng,
|
|
|
'mt-lat': lat
|
|
|
}
|
|
|
response = requests.post('https://h5.moutai519.com.cn/game/isolationPage/getUserEnergyAward', cookies=cookies,
|
|
|
headers=headers, json={})
|
|
|
return response.json().get('message') if '无法领取奖励' in response.text else "领取奖励成功"
|
|
|
|
|
|
|
|
|
def get_map():
|
|
|
global p_c_map
|
|
|
url = 'https://static.moutai519.com.cn/mt-backend/xhr/front/mall/resource/get'
|
|
|
headers = {
|
|
|
'X-Requested-With': 'XMLHttpRequest',
|
|
|
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_0_1 like Mac OS X)',
|
|
|
'Referer': 'https://h5.moutai519.com.cn/gux/game/main?appConfig=2_1_2',
|
|
|
'Client-User-Agent': 'iOS;16.0.1;Apple;iPhone 14 ProMax',
|
|
|
'MT-R': mt_r,
|
|
|
'Origin': 'https://h5.moutai519.com.cn',
|
|
|
'MT-APP-Version': mt_version,
|
|
|
'MT-Request-ID': f'{int(time.time() * 1000)}{random.randint(1111111, 999999999)}{int(time.time() * 1000)}',
|
|
|
'Accept-Language': 'zh-CN,zh-Hans;q=1',
|
|
|
'MT-Device-ID': f'{int(time.time() * 1000)}{random.randint(1111111, 999999999)}{int(time.time() * 1000)}',
|
|
|
'Accept': 'application/json, text/javascript, */*; q=0.01',
|
|
|
'mt-lng': lng,
|
|
|
'mt-lat': lat
|
|
|
}
|
|
|
res = requests.get(url, headers=headers, )
|
|
|
mtshops = res.json().get('data', {}).get('mtshops_pc', {})
|
|
|
urls = mtshops.get('url')
|
|
|
r = requests.get(urls)
|
|
|
for k, v in dict(r.json()).items():
|
|
|
provinceName = v.get('provinceName')
|
|
|
cityName = v.get('cityName')
|
|
|
if not p_c_map.get(provinceName):
|
|
|
p_c_map[provinceName] = {}
|
|
|
if not p_c_map[provinceName].get(cityName, None):
|
|
|
p_c_map[provinceName][cityName] = [k]
|
|
|
else:
|
|
|
p_c_map[provinceName][cityName].append(k)
|
|
|
return p_c_map
|
|
|
|
|
|
|
|
|
def login(phone, vCode, Device_ID):
|
|
|
"""
|
|
|
|
|
|
:param phone: 手机号
|
|
|
:param vCode: 验证码
|
|
|
:param Device_ID: 设备id
|
|
|
:return:
|
|
|
"""
|
|
|
MT_K = f'{int(time.time() * 1000)}'
|
|
|
r = requests.get(
|
|
|
f'http://82.157.10.108:8086/get_mtv?DeviceID={Device_ID}&MTk={MT_K}&version={mt_version}&key=yaohuo')
|
|
|
headers = {
|
|
|
'MT-Device-ID': Device_ID,
|
|
|
'MT-User-Tag': '0',
|
|
|
'Accept': '*/*',
|
|
|
'MT-Network-Type': 'WIFI',
|
|
|
'MT-Token': '',
|
|
|
'MT-K': MT_K,
|
|
|
'MT-Bundle-ID': 'com.moutai.mall',
|
|
|
'MT-V': r.text,
|
|
|
'User-Agent': 'iOS;16.0.1;Apple;iPhone 14 ProMax',
|
|
|
'Accept-Language': 'zh-Hans-CN;q=1',
|
|
|
'MT-Request-ID': f'{int(time.time() * 1000)}18342',
|
|
|
'MT-R': mt_r,
|
|
|
'MT-APP-Version': mt_version,
|
|
|
}
|
|
|
|
|
|
json_data = {
|
|
|
'ydToken': '',
|
|
|
'mobile': f'{phone}',
|
|
|
'vCode': f'{vCode}',
|
|
|
'ydLogId': '',
|
|
|
}
|
|
|
|
|
|
response = requests.post('https://app.moutai519.com.cn/xhr/front/user/register/login', headers=headers,
|
|
|
json=json_data)
|
|
|
data = response.json().get('data', {})
|
|
|
token = data.get('token')
|
|
|
cookie = data.get('cookie') # MT-Token-Wap
|
|
|
print(Device_ID, token, cookie)
|
|
|
return Device_ID, token, cookie
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
sendEmail('茅台申购开始','茅台申购开始')
|
|
|
mt_tokens = os.getenv("MTTokenD")
|
|
|
mt_version = os.getenv("Mt_Version")
|
|
|
if not mt_tokens:
|
|
|
print('MTToken is null')
|
|
|
exit()
|
|
|
if not mt_version:
|
|
|
print('版本号为空 is null')
|
|
|
exit()
|
|
|
mt_token_list = mt_tokens.split('&')
|
|
|
s = "-------------------总共" + \
|
|
|
str(int(len(mt_token_list))) + \
|
|
|
"个用户-------------------"+'\n'
|
|
|
userCount = 0
|
|
|
if len(mt_token_list) > 0:
|
|
|
for mt_token in mt_token_list:
|
|
|
userCount += 1
|
|
|
print("mt_token:",mt_token)
|
|
|
province, city, lng, lat, device_id, token, ck = mt_token.split(
|
|
|
',')
|
|
|
time_keys = str(
|
|
|
int(time.mktime(datetime.date.today().timetuple())) * 1000)
|
|
|
get_map()
|
|
|
|
|
|
try:
|
|
|
sessionId, itemCodes = get_session_id(device_id, token)
|
|
|
userName, user_id, mobile = get_user_id(token, device_id)
|
|
|
if not user_id:
|
|
|
s += "第"+str(userCount)+"个用户token失效,请重新登录"+'\n'
|
|
|
sendEmail('茅台token失效',s)
|
|
|
continue
|
|
|
s += "第"+str(userCount)+"个用户----------------"+userName + '_' + \
|
|
|
mobile + "开始任务" + "----------------"+'\n'
|
|
|
for itemCode in itemCodes:
|
|
|
name = res_map.get(str(itemCode))
|
|
|
if name:
|
|
|
shop_id = get_shop_item(
|
|
|
sessionId, itemCode, device_id, token, province, city)
|
|
|
res = mt_add(itemCode, str(shop_id), sessionId,
|
|
|
user_id, token, device_id)
|
|
|
s += itemCode + \
|
|
|
'_' + name + '---------------' + res + '\n'
|
|
|
if not ck:
|
|
|
r = getUserEnergyAward(device_id, ck)
|
|
|
s += userName + '_' + mobile + '---------------' + \
|
|
|
"小茅运:" + r + '\n'
|
|
|
s += userName + '_' + mobile + "正常结束任务"+'\n \n'
|
|
|
# 多个用户均执行结束时:统一发送结果邮件
|
|
|
if userCount == len(mt_token_list):
|
|
|
if "失败" in s:
|
|
|
# 替换 申购失败:今天已申购 后再判断是否还有失败的文字
|
|
|
replacedS = s.replace('申购失败:今天已申购', '-')
|
|
|
# 替换完今天已申购的文字后,如果还有失败的文字,说明才是真的失败
|
|
|
if "失败" in replacedS:
|
|
|
sendEmail('茅台申购失败',s)
|
|
|
else:
|
|
|
sendEmail('茅台已申购',s)
|
|
|
else :
|
|
|
sendEmail('茅台申购成功',s)
|
|
|
except Exception as e:
|
|
|
s += userName + '_' + mobile + "异常信息"+e
|
|
|
sendEmail('茅台申购异常结束',s)
|
|
|
send("i茅台申购+小茅运", s)
|