|
"""
|
|
bilibili_api.utils.utils
|
|
|
|
通用工具库。
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import random
|
|
from typing import List, TypeVar
|
|
from ..exceptions import StatementException
|
|
|
|
|
|
def get_api(field: str, *args) -> dict:
|
|
"""
|
|
获取 API。
|
|
|
|
Args:
|
|
field (str): API 所属分类,即 data/api 下的文件名(不含后缀名)
|
|
|
|
Returns:
|
|
dict, 该 API 的内容。
|
|
"""
|
|
path = os.path.abspath(
|
|
os.path.join(
|
|
os.path.dirname(__file__), "..", "data", "api", f"{field.lower()}.json"
|
|
)
|
|
)
|
|
if os.path.exists(path):
|
|
with open(path, encoding="utf8") as f:
|
|
data = json.load(f)
|
|
for arg in args:
|
|
data = data[arg]
|
|
return data
|
|
else:
|
|
return {}
|
|
|
|
|
|
def crack_uid(crc32: str):
|
|
"""
|
|
弹幕中的 CRC32 ID 转换成用户 UID。
|
|
|
|
警告,破解后的 UID 不一定准确,有存在误差,仅供参考。
|
|
|
|
代码翻译自:https://github.com/esterTion/BiliBili_crc2mid。
|
|
|
|
Args:
|
|
crc32 (str): crc32 计算摘要后的 UID。
|
|
|
|
Returns:
|
|
int, 真实用户 UID,不一定准确。
|
|
"""
|
|
__CRCPOLYNOMIAL = 0xEDB88320
|
|
__crctable = [None] * 256
|
|
__index = [None] * 4
|
|
|
|
def __create_table():
|
|
for i in range(256):
|
|
crcreg = i
|
|
for j in range(8):
|
|
if (crcreg & 1) != 0:
|
|
crcreg = __CRCPOLYNOMIAL ^ (crcreg >> 1)
|
|
else:
|
|
crcreg >>= 1
|
|
__crctable[i] = crcreg
|
|
|
|
__create_table()
|
|
|
|
def __crc32(input_):
|
|
if type(input_) != str:
|
|
input_ = str(input_)
|
|
crcstart = 0xFFFFFFFF
|
|
len_ = len(input_)
|
|
for i in range(len_):
|
|
index = (crcstart ^ ord(input_[i])) & 0xFF
|
|
crcstart = (crcstart >> 8) ^ __crctable[index]
|
|
return crcstart
|
|
|
|
def __crc32lastindex(input_):
|
|
if type(input_) != str:
|
|
input_ = str(input_)
|
|
crcstart = 0xFFFFFFFF
|
|
len_ = len(input_)
|
|
index = None
|
|
for i in range(len_):
|
|
index = (crcstart ^ ord(input_[i])) & 0xFF
|
|
crcstart = (crcstart >> 8) ^ __crctable[index]
|
|
return index
|
|
|
|
def __getcrcindex(t):
|
|
for i in range(256):
|
|
if __crctable[i] >> 24 == t:
|
|
return i
|
|
return -1
|
|
|
|
def __deepCheck(i, index):
|
|
tc = 0x00
|
|
str_ = ""
|
|
hash_ = __crc32(i)
|
|
tc = hash_ & 0xFF ^ index[2]
|
|
if not (57 >= tc >= 48):
|
|
return [0]
|
|
str_ += str(tc - 48)
|
|
hash_ = __crctable[index[2]] ^ (hash_ >> 8)
|
|
|
|
tc = hash_ & 0xFF ^ index[1]
|
|
if not (57 >= tc >= 48):
|
|
return [0]
|
|
str_ += str(tc - 48)
|
|
hash_ = __crctable[index[1]] ^ (hash_ >> 8)
|
|
|
|
tc = hash_ & 0xFF ^ index[0]
|
|
if not (57 >= tc >= 48):
|
|
return [0]
|
|
str_ += str(tc - 48)
|
|
hash_ = __crctable[index[0]] ^ (hash_ >> 8)
|
|
|
|
return [1, str_]
|
|
|
|
ht = int(crc32, 16) ^ 0xFFFFFFFF
|
|
i = 3
|
|
while i >= 0:
|
|
__index[3 - i] = __getcrcindex(ht >> (i * 8))
|
|
|
|
snum = __crctable[__index[3 - i]]
|
|
ht ^= snum >> ((3 - i) * 8)
|
|
i -= 1
|
|
for i in range(10000000):
|
|
lastindex = __crc32lastindex(i)
|
|
if lastindex == __index[3]:
|
|
deepCheckData = __deepCheck(i, __index)
|
|
if deepCheckData[0]:
|
|
break
|
|
if i == 10000000:
|
|
return -1
|
|
return str(i) + deepCheckData[1]
|
|
|
|
|
|
def join(seperator: str, array: list):
|
|
"""
|
|
用指定字符连接数组
|
|
|
|
Args:
|
|
seperator (str) : 分隔字符
|
|
|
|
array (list): 数组
|
|
|
|
Returns:
|
|
str: 连接结果
|
|
"""
|
|
return seperator.join(map(lambda x: str(x), array))
|
|
|
|
|
|
ChunkT = TypeVar("ChunkT", List, List)
|
|
|
|
|
|
def chunk(arr: ChunkT, size: int) -> List[ChunkT]:
|
|
if size <= 0:
|
|
raise Exception('Parameter "size" must greater than 0')
|
|
|
|
result = []
|
|
temp = []
|
|
|
|
for i in range(len(arr)):
|
|
temp.append(arr[i])
|
|
|
|
if i % size == size - 1:
|
|
result.append(temp)
|
|
temp = []
|
|
|
|
if temp:
|
|
result.append(temp)
|
|
|
|
return result
|
|
|
|
|
|
def get_deviceid(separator: str = "-", is_lowercase: bool = False) -> str:
|
|
"""
|
|
获取随机 deviceid (dev_id)
|
|
|
|
Args:
|
|
separator (str) : 分隔符 默认为 "-"
|
|
|
|
is_lowercase (bool) : 是否以小写形式 默认为False
|
|
|
|
参考: https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/message/private_msg.md#发送私信web端
|
|
|
|
Returns:
|
|
str: device_id
|
|
"""
|
|
template = ["xxxxxxxx", "xxxx", "4xxx", "yxxx", "xxxxxxxxxxxx"]
|
|
dev_id_group = []
|
|
for i in range(len(template)):
|
|
s = ""
|
|
group = template[i]
|
|
for k in group:
|
|
rand: int = int(16 * random.random())
|
|
if k in "xy":
|
|
if k == "x":
|
|
s += hex(rand)[2:]
|
|
else:
|
|
s += hex(3 & rand | 8)[2:]
|
|
else:
|
|
s += "4"
|
|
dev_id_group.append(s)
|
|
res = join(separator, dev_id_group)
|
|
return res if is_lowercase else res.upper()
|
|
|
|
|
|
def raise_for_statement(statement: bool, msg: str="未满足条件") -> None:
|
|
if not statement:
|
|
raise StatementException(msg=msg)
|
|
|