rogerxavier's picture
Upload 258 files
0aee47a verified
raw
history blame
5.58 kB
"""
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)