feat: Auto detect login UID and catch possible exception in auto follow task
This commit is contained in:
@@ -14,7 +14,7 @@ from .datasource import DataSource
|
||||
from .dynamic import dynamic_spider
|
||||
from .server import http_init
|
||||
from .user import User, RelationType
|
||||
from ..exception import LiveException
|
||||
from ..exception import LiveException, ResponseCodeException
|
||||
from ..exception.DataSourceException import DataSourceException
|
||||
from ..exception.RedisException import RedisException
|
||||
from ..utils import redis, config
|
||||
@@ -67,23 +67,64 @@ class StarBot:
|
||||
logger.error("获取 StarBot 最新版本失败")
|
||||
logger.info("开始启动 StarBot")
|
||||
|
||||
# 检查登录凭据完整性
|
||||
logger.info("开始尝试使用登录凭据登录 B 站账号")
|
||||
if config.get("SESSDATA") is None or config.get("BILI_JCT") is None or config.get("BUVID3") is None:
|
||||
logger.info("未配置 B 站登录凭据, 尝试从 credential.json 文件中读取")
|
||||
try:
|
||||
with open("credential.json", "r", encoding="utf-8") as file:
|
||||
credential = json.loads(file.read())
|
||||
config.set("SESSDATA", credential["sessdata"])
|
||||
config.set("BILI_JCT", credential["bili_jct"])
|
||||
config.set("BUVID3", credential["buvid3"])
|
||||
logger.success("成功从 JSON 文件中读取了 B 站登录凭据")
|
||||
except FileNotFoundError:
|
||||
logger.warning("登录凭据 JSON 文件不存在")
|
||||
except UnicodeDecodeError:
|
||||
logger.warning("登录凭据 JSON 文件编码不正确, 请将其转换为 UTF-8 格式编码")
|
||||
except (JSONDecodeError, KeyError):
|
||||
logger.warning("登录凭据 JSON 文件格式不正确")
|
||||
except Exception as ex:
|
||||
logger.warning(f"读取登录凭据 JSON 文件异常 {ex}")
|
||||
|
||||
if config.get("SESSDATA") is None or config.get("BILI_JCT") is None or config.get("BUVID3") is None:
|
||||
logger.error("未配置 B 站登录凭据, 请使用 config.set_credential(sessdata=\"B站账号的sessdata\", "
|
||||
"bili_jct=\"B站账号的bili_jct\", buvid3=\"B站账号的buvid3\") 配置登录 B 站账号所需的登录凭据")
|
||||
return 1
|
||||
|
||||
# 获取账号信息
|
||||
try:
|
||||
response = await request("GET", "https://api.bilibili.com/x/space/v2/myinfo", credential=get_credential())
|
||||
profile = response["profile"]
|
||||
uid = profile["mid"]
|
||||
uname = profile["name"]
|
||||
config.set("LOGIN_UID", uid)
|
||||
logger.opt(colors=True).info(f"<green>B 站账号登录成功, UID: <cyan>{uid}</>, 昵称: <cyan>{uname}</></>")
|
||||
except ResponseCodeException as ex:
|
||||
if ex.code == -101:
|
||||
logger.error("尝试登录 B 站账号失败, 可能的原因为登录凭据填写不正确或已失效, 请检查后重试")
|
||||
return 2
|
||||
except Exception as ex:
|
||||
logger.exception(f"尝试登录 B 站账号失败", ex)
|
||||
return 2
|
||||
|
||||
# 从数据源中加载配置
|
||||
try:
|
||||
await self.__datasource.load()
|
||||
except DataSourceException as ex:
|
||||
logger.error(ex.msg)
|
||||
return 1
|
||||
return 3
|
||||
|
||||
if not self.__datasource.bots:
|
||||
logger.error("数据源配置为空, 请先在数据源中配置完毕后再重新运行")
|
||||
return 2
|
||||
return 4
|
||||
|
||||
# 连接 Redis
|
||||
try:
|
||||
await redis.init()
|
||||
except RedisException as ex:
|
||||
logger.error(ex.msg)
|
||||
return 3
|
||||
return 5
|
||||
|
||||
# 通过 UID 列表批量获取信息
|
||||
info = {}
|
||||
@@ -128,28 +169,6 @@ class StarBot:
|
||||
except asyncio.exceptions.TimeoutError:
|
||||
logger.warning("等待连接所有直播间超时, 请检查是否存在未连接成功的直播间")
|
||||
|
||||
# 未设置登录凭据时尝试从 JSON 文件中读取
|
||||
if config.get("SESSDATA") is None or config.get("BILI_JCT") is None or config.get("BUVID3") is None:
|
||||
logger.info("未设置 B 站登录凭据, 将尝试从 credential.json 文件中读取")
|
||||
try:
|
||||
with open("credential.json", "r", encoding="utf-8") as file:
|
||||
credential = json.loads(file.read())
|
||||
config.set("SESSDATA", credential["sessdata"])
|
||||
config.set("BILI_JCT", credential["bili_jct"])
|
||||
config.set("BUVID3", credential["buvid3"])
|
||||
logger.success("成功从 JSON 文件中读取了 B 站登录凭据")
|
||||
except FileNotFoundError:
|
||||
logger.warning("登录凭据 JSON 文件不存在")
|
||||
except UnicodeDecodeError:
|
||||
logger.warning("登录凭据 JSON 文件编码不正确, 请将其转换为 UTF-8 格式编码")
|
||||
except (JSONDecodeError, KeyError):
|
||||
logger.warning("登录凭据 JSON 文件格式不正确")
|
||||
except Exception as ex:
|
||||
logger.warning(f"读取登录凭据 JSON 文件异常 {ex}")
|
||||
|
||||
if config.get("SESSDATA") is None or config.get("BILI_JCT") is None or config.get("BUVID3") is None:
|
||||
logger.warning("读取 B 站登录凭据失败, 动态推送等部分功能将不可用")
|
||||
|
||||
# 启动动态推送模块
|
||||
asyncio.get_event_loop().create_task(dynamic_spider(self.__datasource))
|
||||
|
||||
@@ -171,14 +190,17 @@ class StarBot:
|
||||
|
||||
# 自动关注打开了动态推送的未关注 UP 主
|
||||
if config.get("AUTO_FOLLOW_OPENED_DYNAMIC_UPDATE_UP"):
|
||||
if config.get("ACCOUNT_UID") is None:
|
||||
logger.warning("未填写 ACCOUNT_UID 配置项, 无法自动关注打开了动态推送的未关注 UP 主, "
|
||||
"请使用 config.set('ACCOUNT_UID', 您的UID) 设置, 或手动关注所有需要动态推送的 UP 主, "
|
||||
"否则无法获取未关注用户的动态更新信息, "
|
||||
"使用 config.set('AUTO_FOLLOW_OPENED_DYNAMIC_UPDATE_UP', False) 可禁用自动关注功能和此警告")
|
||||
else:
|
||||
uid = int(config.get("ACCOUNT_UID"))
|
||||
me = User(uid, get_credential())
|
||||
uid = config.get("LOGIN_UID")
|
||||
me = User(uid, get_credential())
|
||||
|
||||
async def follow_task(uid_set):
|
||||
for u in uid_set:
|
||||
follow_user = User(u, get_credential())
|
||||
await follow_user.modify_relation(RelationType.SUBSCRIBE)
|
||||
await asyncio.sleep(10)
|
||||
logger.success(f"已成功关注了 {len(uid_set)} 个 UP 主")
|
||||
|
||||
try:
|
||||
follows = set()
|
||||
page = 1
|
||||
while True:
|
||||
@@ -190,24 +212,20 @@ class StarBot:
|
||||
|
||||
need_follow_uids = set()
|
||||
for up in self.__datasource.get_up_list():
|
||||
if any(map(lambda d: d.enabled, map(lambda t: t.dynamic_update, up.targets))):
|
||||
if up.uid != uid and any(map(lambda d: d.enabled, map(lambda t: t.dynamic_update, up.targets))):
|
||||
need_follow_uids.add(up.uid)
|
||||
need_follow_uids.difference_update(follows)
|
||||
|
||||
async def follow_task(uid_set):
|
||||
logger.info(f"检测到 {len(uid_set)} 个打开了动态推送但未关注的 UP 主, 启动自动关注任务")
|
||||
for u in uid_set:
|
||||
follow_user = User(u, get_credential())
|
||||
await follow_user.modify_relation(RelationType.SUBSCRIBE)
|
||||
await asyncio.sleep(10)
|
||||
logger.success(f"已成功关注了 {len(uid_set)} 个 UP 主")
|
||||
|
||||
if len(need_follow_uids) > 0:
|
||||
logger.info(f"检测到 {len(need_follow_uids)} 个打开了动态推送但未关注的 UP 主, 启动自动关注任务")
|
||||
asyncio.create_task(follow_task(need_follow_uids))
|
||||
|
||||
# 检测 UID 配置完整性
|
||||
if config.get("ACCOUNT_UID") is None:
|
||||
logger.warning("未填写 ACCOUNT_UID 配置项, 受 B 站风控影响, 将无法获取弹幕相关数据, 请使用 config.set(\"ACCOUNT_UID\", 您的UID) 设置")
|
||||
else:
|
||||
logger.success(f"不存在打开了动态推送但未关注的 UP 主")
|
||||
except ResponseCodeException as ex:
|
||||
if ex.code == 22115 or ex.code == 22007:
|
||||
logger.warning(f"读取登录账号的关注列表失败, 请检查登录凭据是否已失效, 错误信息: {ex.msg}")
|
||||
except Exception as ex:
|
||||
logger.exception(f"读取登录账号的关注列表失败", ex)
|
||||
|
||||
# 检测消息补发配置完整性
|
||||
if config.get("BAN_RESEND") and config.get("MASTER_QQ") is None:
|
||||
@@ -237,7 +255,7 @@ class StarBot:
|
||||
pass
|
||||
else:
|
||||
logger.error(ex)
|
||||
return 4
|
||||
return 6
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
|
||||
@@ -811,9 +811,7 @@ class LiveDanmaku(AsyncEvent):
|
||||
logger.warning(f"直播间 {self.room_display_id} 检测到未知的数据包类型, 无法处理")
|
||||
|
||||
async def __send_verify_data(self, ws: ClientWebSocketResponse, token: str):
|
||||
uid = config.get("ACCOUNT_UID")
|
||||
if uid is None:
|
||||
uid = 0
|
||||
uid = config.get("LOGIN_UID")
|
||||
verify_data = {"uid": uid, "roomid": self.__room_real_id,
|
||||
"protover": 3, "platform": "web", "type": 2, "key": token}
|
||||
data = json.dumps(verify_data).encode()
|
||||
|
||||
@@ -38,8 +38,6 @@ DEFAULT_CONFIG = {
|
||||
"BILI_JCT": None,
|
||||
"BUVID3": None,
|
||||
|
||||
# 以上 Cookie 数据所对应的 B 站账号 UID,自动关注打开了动态推送但没有关注的用户时使用
|
||||
"ACCOUNT_UID": None,
|
||||
# 是否自动关注打开了动态推送但没有关注的用户,推荐打开,否则无法获取未关注用户的动态更新信息
|
||||
"AUTO_FOLLOW_OPENED_DYNAMIC_UPDATE_UP": True,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user