File size: 4,950 Bytes
c9ecd6c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
da52b9e
c9ecd6c
 
 
 
4df7720
c9ecd6c
 
 
 
 
 
 
 
 
 
 
 
 
da52b9e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c9ecd6c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
da52b9e
 
4df7720
 
da52b9e
 
 
 
 
 
 
 
 
 
4df7720
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import time
import requests
from hashlib import md5
from typing import Union
from urllib.parse import urlencode
from requests_toolbelt.multipart.encoder import MultipartEncoder
import imghdr


class Crypto:
    APPKEY = '4409e2ce8ffd12b8'
    APPSECRET = '59b43e04ad6965f34319062b478f83dd'

    @staticmethod
    def md5(data: Union[str, bytes]) -> str:
        '''generates md5 hex dump of `str` or `bytes`'''
        if type(data) == str:
            return md5(data.encode()).hexdigest()
        return md5(data).hexdigest()

    @staticmethod
    def sign(data: Union[str, dict]) -> str:
        '''salted sign funtion for `dict`(converts to qs then parse) & `str`'''
        if isinstance(data, dict):
            _str = urlencode(data)
        elif type(data) != str:
            raise TypeError
        return Crypto.md5(_str + Crypto.APPSECRET)


class SingableDict(dict):
    @property
    def sorted(self):
        '''returns a alphabetically sorted version of `self`'''
        return dict(sorted(self.items()))

    @property
    def signed(self):
        '''returns our sorted self with calculated `sign` as a new key-value pair at the end'''
        _sorted = self.sorted
        return {**_sorted, 'sign': Crypto.sign(_sorted)}


def get_image_type(file_path):
    with open(file_path, 'rb') as f:
        data = f.read()
    return imghdr.what(None, data)


def get_have_card_id_list(UID, ACCESS_KEY, sid):
    url = "https://api.bilibili.com/x/vas/nftcard/cardlist"
    params = SingableDict(
        {
            "access_key": ACCESS_KEY,
            "act_id": sid,  # 这里默认已经是三体数字藏品卡14,github下载的默认是4,也就是胶囊卡
            "appkey": "4409e2ce8ffd12b8",
            "disable_rcmd": "0",
            "ruid": UID,
            "statistics": "{\"appId\":1,\"platform\":3,\"version\":\"7.9.0\",\"abtest\":\"\"}",
            "ts": int(time.time()),
        }
    ).signed
    response = requests.request("GET", url, params=params)
    data = response.json()
    if data['code'] != 0:
        print(f"获取卡片信息出错,下面是 api 返回:\n{data}")
        return
    # print(data)  # 查询已添加无需再填
    have_card_id_list = {}
    try:
        for round in data['data']['round_list']:
            for card in round['card_list']:
                if card['card_id_list']:
                    print(f"找到付费卡 card_id: {card['card_id_list'][0]['card_id']}\n这个id属于{card['card_name']}")
                    have_card_id_list.update({card['card_name']: card['card_id_list'][0]['card_id']})
        if data["data"]["pre_list"]:
            for i in data["data"]["pre_list"]:
                if card_id_list := i.get("card_id_list"):
                    for j in card_id_list:
                        if card_id := j.get("card_id"):
                            print(f"找到预约卡card_id: {card_id}\n这个 id 属于{i.get('card_name')}")
                            have_card_id_list.update({i.get('card_name'): card_id})
    except Exception as e:
        print(f"处理卡牌列表出错{e.args[0]},下面是 api 返回:\n{data}")
        return {}
    if have_card_id_list:
        print(f"已经找到卡片")
        return have_card_id_list
    else:
        print("没有找到可用的卡片")
        return {}


def set_face(card_id, ACCESS_KEY, img_data):
    api = "https://api.bilibili.com/x/member/app/face/digitalKit/update"
    params = SingableDict(
        {
            "access_key": ACCESS_KEY,
            "appkey": "4409e2ce8ffd12b8",
            "build": "7090300",
            "c_locale": "zh_CN",
            "channel": "xiaomi",
            "disable_rcmd": "0",
            "mobi_app": "android",
            "platform": "android",
            "s_locale": "zh_CN",
            "statistics": "{\"appId\":1,\"platform\":3,\"version\":\"7.9.0\",\"abtest\":\"\"}",
            "ts": int(time.time()),
        }
    ).signed
    m = MultipartEncoder(
        fields={
            'digital_kit_id': str(card_id),
            'face': ('face', img_data, 'application/octet-stream'),
        }
    )
    headers = {
        "Content-Type": m.content_type,
    }
    response = requests.request("POST", api, data=m, headers=headers, params=params)
    if response.json()['code'] != 0:
        return False, response.json()
    return True, '设置头像成功, 请等待审核'


def having_card_id_list(uid, key, sid):
    uid = int(uid)
    access_key = str(key)
    sid = str(sid)

    had_card_id_list = get_have_card_id_list(uid, access_key, sid)  # 根据你所取得的卡card_id进行更改
    if had_card_id_list:
        return True, had_card_id_list, "已找到拥有卡牌"
    return False, {}, "没找到任何card_id ,请确认当前卡组已拥有卡片"


def card_id_set_ava(card_id, key, img_data):
    access_key = str(key)
    result, code = set_face(card_id, access_key, img_data)
    return result, code