DailyCheckIn抢茅台


发布于

|

分类

前些日子知道了DailyCheckIn这个项目,能将无聊的每日签到工作中解放出来。它里面有抢茅台预约的功能,那么就试试。

安装

哎,萝卜白菜各有所爱吧。比如我就觉得官网上的教程过于详细了,不如直接给个 docker-compose.yaml 直接一把梭跑。

version: "3"
services:
    dailycheckin:
        volumes:
            - /PATH/TO/SOME/FOLDER:/dailycheckin
        restart: always
        image: sitoi/dailycheckin

或者直接一行命令也不是不可以

docker run -v /PATH/TO/SOME/FOLDER:/dailycheckin --restart always sitoi/dailycheckin

用K8s部署的话,大概搞成这样(emm,自从有了K8s集群后,啥啥啥都想K8s解决……明明人家docker compose会更简单…… )

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: dailycheckin
spec:
  resources:
    requests:
      storage: 50Mi
  accessModes:
    - ReadWriteMany
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dailycheckin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: dailycheckin
  template:
    metadata:
      labels:
        app: dailycheckin
    spec:
      containers:
        - name: dailycheckin
          image: sitoi/dailycheckin
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - name: dailycheckin
              mountPath: /dailycheckin
      volumes:
        - name: dailycheckin
          persistentVolumeClaim:
            claimName: dailycheckin

茅台配置

官网教程里面说,需要先申请一个高德地图的开发者账号,然后再运行一个脚本。申请账号是为了获取到当前定位,然后预约离你最近的门店。

我在这里卡住了:我输入手机号,说已被绑定,反正死活不让我开通开发者。

然后看了下官网上提供的脚本,似乎只是需要一个经纬度,和一个文字格式的地址。那么我似乎可以从其他地方获取到这些信息。

首先,来到高德开放平台-坐标拾取器,直接搜索你需要的位置。网页上面写了「游客和未认证开发者仅显示经纬度小数点后2位」,但是茅台脚本里面需要的坐标似乎精度更高一点。没关系,我们打开F12,切换到「网络」tab,再在地图上点击一下你想要的坐标,哎,有个请求,里面列出了详细的信息,精确到了小数点后6位——够用了。

好了,那么那个取获Token的脚本就可以变成这样了:

import hashlib
import json
import time

import requests

GEO_INFO = {
    "province": "",  # 接口的 province 字段直接复制过来
    "city": [],  # 这里如果有看到就填,看不到就空着
    "location": ""  # 接口的location字段直接复制过来
}
ITEM_CODES = ["10941", "10942"]

SALT = "2af72f100c356273d46284f6fd1dfc08"

CURRENT_TIME = str(int(time.time() * 1000))
headers_base = {
    'MT-Lat': '28.499562',
    'MT-K': '1675213490331',
    'MT-Lng': '102.182324',
    'Host': 'app.moutai519.com.cn',
    'MT-User-Tag': '0',
    'Accept': '*/*',
    'MT-Network-Type': 'WIFI',
    'MT-Token': '1',
    'MT-Team-ID': '1',
    'MT-Info': '028e7f96f6369cafe1d105579c5b9377',
    'MT-Device-ID': '2F2075D0-B66C-4287-A903-DBFF6358342A',
    'MT-Bundle-ID': 'com.moutai.mall',
    'Accept-Language': 'en-CN;q=1, zh-Hans-CN;q=0.9',
    'MT-Request-ID': '167560018873318465',
    'MT-APP-Version': '1.3.7',
    'User-Agent': 'iOS;16.3;Apple;?unrecognized?',
    'MT-R': 'clips_OlU6TmFRag5rCXwbNAQ/Tz1SKlN8THcecBp/HGhHdw==',
    'Content-Length': '93',
    'Accept-Encoding': 'gzip, deflate, br',
    'Connection': 'keep-alive',
    'Content-Type': 'application/json',
    'userId': '2'
}

headers = {}
mt_version = json.loads(requests.get("https://itunes.apple.com/cn/lookup?id=1600482450").text)["results"][0]["version"]


# 初始化请求头
def init_headers(user_id: str = "1", token: str = "2", lat: str = "29.83826", lng: str = "119.74375"):
    global headers
    headers = {
        **headers_base,
        "userId": user_id,
        "MT-Token": token,
        "MT-Lat": lat,
        "MT-Lng": lng,
        "MT-APP-Version": mt_version,
    }


def signature(data: dict):
    keys = sorted(data.keys())
    temp_v = ""
    for item in keys:
        temp_v += data[item]
    text = SALT + temp_v + CURRENT_TIME
    hl = hashlib.md5()
    hl.update(text.encode(encoding="utf8"))
    md5 = hl.hexdigest()
    return md5


# 获取登录手机验证码
def get_vcode(mobile: str):
    params = {"mobile": mobile}
    md5 = signature(params)
    params.update({
        "md5": md5,
        "timestamp": CURRENT_TIME,
        "MT-APP-Version": mt_version
    })
    responses = requests.post(
        "https://app.moutai519.com.cn/xhr/front/user/register/vcode",
        json=params,
        headers=headers,
    )
    if responses.status_code != 200:
        print(f"get v_code: "
              f"params: {params}, "
              f"response code: {responses.status_code}, "
              f"response body: {responses.text}")


# 执行登录操作
def login(mobile: str, v_code: str):
    params = {"mobile": mobile, "vCode": v_code, "ydToken": "", "ydLogId": ""}
    md5 = signature(params)
    params.update({
        "md5": md5,
        "timestamp": CURRENT_TIME,
        "MT-APP-Version": mt_version
    })
    responses = requests.post(
        "https://app.moutai519.com.cn/xhr/front/user/register/login",
        json=params,
        headers=headers,
    )
    if responses.status_code != 200:
        print(f"login: "
              f"params: {params}, "
              f"response code: {responses.status_code}, "
              f"response body: {responses.text}")
    rsp_json = responses.json()
    # headers.update({"MT-Token": rsp_json["data"]["token"], "userId": rsp_json["data"]["userId"]})
    return rsp_json["data"]["token"], rsp_json["data"]["userId"]


if __name__ == "__main__":
    items = []
    while True:
        init_headers()
        location_select: dict = GEO_INFO
        province = location_select["province"]
        city = location_select["city"]
        location: str = location_select["location"]

        mobile = input("输入手机号[18888888888]:").strip()
        get_vcode(mobile)
        code = input(f"输入 [{mobile}] 验证码[8888]:").strip()
        token, userId = login(mobile, code)
        item = {
            "city": str(city),
            "lat": location.split(",")[1],
            "lng": location.split(",")[0],
            "mobile": str(mobile),
            "province": province,
            "token": str(token),
            "userid": str(userId),
            "reserve_rule": 0,
            "item_codes": ITEM_CODES,
        }
        items.append(item)
        condition = input("是否继续添加账号[y/n]:").strip()
        if condition.lower() == "n":
            break

    with open("account.json", "w") as f:
        f.write(json.dumps(items, ensure_ascii=False, indent=4))

    print("Done")

好了,安心食用吧。


反正,我是觉得,就是营销做得好。

我是对酒类不感兴趣。不如来瓶可乐。

另外我超烦「签到」这种东西。


评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注