Spaces:
Sleeping
Sleeping
""" | |
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)) | |
# pylint: disable=invalid-sequence-index | |
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) | |