Spaces:
Runtime error
Runtime error
rdp-studio
commited on
Commit
•
f5e6625
1
Parent(s):
c53e6a1
Create nft.py
Browse files
nft.py
ADDED
@@ -0,0 +1,140 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import time
|
2 |
+
import requests
|
3 |
+
from hashlib import md5
|
4 |
+
from typing import Union
|
5 |
+
from urllib.parse import urlencode
|
6 |
+
from requests_toolbelt.multipart.encoder import MultipartEncoder
|
7 |
+
import imghdr
|
8 |
+
|
9 |
+
|
10 |
+
class Crypto:
|
11 |
+
APPKEY = '4409e2ce8ffd12b8'
|
12 |
+
APPSECRET = '59b43e04ad6965f34319062b478f83dd'
|
13 |
+
|
14 |
+
@staticmethod
|
15 |
+
def md5(data: Union[str, bytes]) -> str:
|
16 |
+
'''generates md5 hex dump of `str` or `bytes`'''
|
17 |
+
if type(data) == str:
|
18 |
+
return md5(data.encode()).hexdigest()
|
19 |
+
return md5(data).hexdigest()
|
20 |
+
|
21 |
+
@staticmethod
|
22 |
+
def sign(data: Union[str, dict]) -> str:
|
23 |
+
'''salted sign funtion for `dict`(converts to qs then parse) & `str`'''
|
24 |
+
if isinstance(data, dict):
|
25 |
+
_str = urlencode(data)
|
26 |
+
elif type(data) != str:
|
27 |
+
raise TypeError
|
28 |
+
return Crypto.md5(_str + Crypto.APPSECRET)
|
29 |
+
|
30 |
+
|
31 |
+
class SingableDict(dict):
|
32 |
+
@property
|
33 |
+
def sorted(self):
|
34 |
+
'''returns a alphabetically sorted version of `self`'''
|
35 |
+
return dict(sorted(self.items()))
|
36 |
+
|
37 |
+
@property
|
38 |
+
def signed(self):
|
39 |
+
'''returns our sorted self with calculated `sign` as a new key-value pair at the end'''
|
40 |
+
_sorted = self.sorted
|
41 |
+
return {**_sorted, 'sign': Crypto.sign(_sorted)}
|
42 |
+
|
43 |
+
|
44 |
+
def get_image_type(file_path):
|
45 |
+
with open(file_path, 'rb') as f:
|
46 |
+
data = f.read()
|
47 |
+
return imghdr.what(None, data)
|
48 |
+
|
49 |
+
|
50 |
+
def get_have_card_id_list(UID, ACCESS_KEY, sid):
|
51 |
+
url = "https://api.bilibili.com/x/vas/nftcard/cardlist"
|
52 |
+
params = SingableDict(
|
53 |
+
{
|
54 |
+
"access_key": ACCESS_KEY,
|
55 |
+
"act_id": sid, # 这里默认已经是三体数字藏品卡14,github下载的默认是4,也就是胶囊卡
|
56 |
+
"appkey": "4409e2ce8ffd12b8",
|
57 |
+
"disable_rcmd": "0",
|
58 |
+
"ruid": UID,
|
59 |
+
"statistics": "{\"appId\":1,\"platform\":3,\"version\":\"7.9.0\",\"abtest\":\"\"}",
|
60 |
+
"ts": int(time.time()),
|
61 |
+
}
|
62 |
+
).signed
|
63 |
+
response = requests.request("GET", url, params=params)
|
64 |
+
data = response.json()
|
65 |
+
if data['code'] != 0:
|
66 |
+
print(f"获取卡片信息出错,下面是 api 返回:\n{data}")
|
67 |
+
return
|
68 |
+
# print(data) # 查询已添加无需再填
|
69 |
+
have_card_id_list = {}
|
70 |
+
try:
|
71 |
+
for round in data['data']['round_list']:
|
72 |
+
for card in round['card_list']:
|
73 |
+
if card['card_id_list']:
|
74 |
+
print(f"找到付费卡 card_id: {card['card_id_list'][0]['card_id']}\n这个id属于{card['card_name']}")
|
75 |
+
have_card_id_list.update({card['card_name']: card['card_id_list'][0]['card_id']})
|
76 |
+
if data["data"]["pre_list"]:
|
77 |
+
for i in data["data"]["pre_list"]:
|
78 |
+
if card_id_list := i.get("card_id_list"):
|
79 |
+
for j in card_id_list:
|
80 |
+
if card_id := j.get("card_id"):
|
81 |
+
print(f"找到预约卡card_id: {card_id}\n这个 id 属于{i.get('card_name')}")
|
82 |
+
have_card_id_list.update({i.get('card_name'): card_id})
|
83 |
+
except Exception as e:
|
84 |
+
print(f"处理卡牌列表出错{e.args[0]},下面是 api 返回:\n{data}")
|
85 |
+
return {}
|
86 |
+
if have_card_id_list:
|
87 |
+
print(f"已经找到卡片")
|
88 |
+
return have_card_id_list
|
89 |
+
else:
|
90 |
+
print("没有找到可用的卡片")
|
91 |
+
return {}
|
92 |
+
|
93 |
+
|
94 |
+
def set_face(card_id, ACCESS_KEY, img_data):
|
95 |
+
api = "https://api.bilibili.com/x/member/app/face/digitalKit/update"
|
96 |
+
params = SingableDict(
|
97 |
+
{
|
98 |
+
"access_key": ACCESS_KEY,
|
99 |
+
"appkey": "4409e2ce8ffd12b8",
|
100 |
+
"build": "7090300",
|
101 |
+
"c_locale": "zh_CN",
|
102 |
+
"channel": "xiaomi",
|
103 |
+
"disable_rcmd": "0",
|
104 |
+
"mobi_app": "android",
|
105 |
+
"platform": "android",
|
106 |
+
"s_locale": "zh_CN",
|
107 |
+
"statistics": "{\"appId\":1,\"platform\":3,\"version\":\"7.9.0\",\"abtest\":\"\"}",
|
108 |
+
"ts": int(time.time()),
|
109 |
+
}
|
110 |
+
).signed
|
111 |
+
m = MultipartEncoder(
|
112 |
+
fields={
|
113 |
+
'digital_kit_id': str(card_id),
|
114 |
+
'face': ('face', img_data, 'application/octet-stream'),
|
115 |
+
}
|
116 |
+
)
|
117 |
+
headers = {
|
118 |
+
"Content-Type": m.content_type,
|
119 |
+
}
|
120 |
+
response = requests.request("POST", api, data=m, headers=headers, params=params)
|
121 |
+
if response.json()['code'] != 0:
|
122 |
+
return False, response.json()
|
123 |
+
return True, '设置头像成功, 请等待审核'
|
124 |
+
|
125 |
+
|
126 |
+
def having_card_id_list(uid, key, sid):
|
127 |
+
uid = int(uid)
|
128 |
+
access_key = str(key)
|
129 |
+
sid = str(sid)
|
130 |
+
|
131 |
+
had_card_id_list = get_have_card_id_list(uid, access_key, sid) # 根据你所取得的卡card_id进行更改
|
132 |
+
if had_card_id_list:
|
133 |
+
return True, had_card_id_list, "已找到拥有卡牌"
|
134 |
+
return False, {}, "没找到任何card_id ,请确认当前卡组已拥有卡片"
|
135 |
+
|
136 |
+
|
137 |
+
def card_id_set_ava(card_id, key, img_data):
|
138 |
+
access_key = str(key)
|
139 |
+
result, code = set_face(card_id, access_key, img_data)
|
140 |
+
return result, code
|