mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2025-12-14 21:52:56 +08:00
fix🐛: 修正b站订阅
This commit is contained in:
parent
fb26be821b
commit
1130569a20
@ -331,6 +331,10 @@ PS: **ARM平台** 请使用全量版 同时 **如果你的机器 RAM < 1G 可能
|
||||
|
||||
## 更新
|
||||
|
||||
### 2023/9/6
|
||||
|
||||
* 修正b站订阅
|
||||
|
||||
### 2023/8/28
|
||||
|
||||
* 重构`红包`功能, 允许一个群聊中有多个用户发起的红包,发送`开`等命令会开启群中所有条件允许的红包,新增`红包结算排行`,在红包退回或抢完时统计,在`塞红包`时at可以发送专属红包
|
||||
|
||||
@ -70,6 +70,12 @@ __plugin_configs__ = {
|
||||
"default_value": False,
|
||||
"type": bool,
|
||||
},
|
||||
"DOWNLOAD_DYNAMIC_IMAGE": {
|
||||
"value": True,
|
||||
"help": "下载动态中的图片并发送在提醒消息中",
|
||||
"default_value": True,
|
||||
"type": bool,
|
||||
},
|
||||
}
|
||||
|
||||
add_sub = on_command("添加订阅", priority=5, block=True)
|
||||
@ -255,11 +261,11 @@ async def _():
|
||||
if sub:
|
||||
try:
|
||||
logger.debug(f"Bilibili订阅开始检测:{sub.sub_id}")
|
||||
rst = await get_sub_status(sub.sub_id, sub.sub_type)
|
||||
await send_sub_msg(rst or "", sub, bot) # type: ignore
|
||||
rst = await get_sub_status(sub.sub_id, sub.sub_id, sub.sub_type)
|
||||
await send_sub_msg(rst, sub, bot) # type: ignore
|
||||
if sub.sub_type == "live":
|
||||
rst = await get_sub_status(sub.sub_id, "up")
|
||||
await send_sub_msg(rst or "", sub, bot) # type: ignore
|
||||
rst += "\n" + await get_sub_status(sub.uid, sub.sub_id, "up")
|
||||
await send_sub_msg(rst, sub, bot) # type: ignore
|
||||
except Exception as e:
|
||||
logger.error(f"B站订阅推送发生错误 sub_id:{sub.sub_id}", e=e)
|
||||
|
||||
@ -298,4 +304,4 @@ async def send_sub_msg(rst: str, sub: BilibiliSub, bot: Bot):
|
||||
else:
|
||||
await bot.send_private_msg(user_id=int(x), message=Message(rst))
|
||||
except Exception as e:
|
||||
logger.error(f"B站订阅推送发生错误 sub_id:{sub.sub_id}", e=e)
|
||||
logger.error(f"B站订阅推送发生错误 sub_id: {sub.sub_id}", e=e)
|
||||
|
||||
@ -1,22 +1,25 @@
|
||||
import random
|
||||
from asyncio.exceptions import TimeoutError
|
||||
from datetime import datetime
|
||||
from typing import Optional, Tuple
|
||||
from typing import Optional, Tuple, Union
|
||||
|
||||
# from .utils import get_videos
|
||||
from bilireq import dynamic
|
||||
from bilireq.exceptions import ResponseCodeError
|
||||
from bilireq.grpc.dynamic import grpc_get_user_dynamics
|
||||
from bilireq.grpc.protos.bilibili.app.dynamic.v2.dynamic_pb2 import DynamicType
|
||||
from bilireq.live import get_room_info_by_id
|
||||
from bilireq.user import get_videos
|
||||
from nonebot.adapters.onebot.v11 import MessageSegment
|
||||
from nonebot.adapters.onebot.v11 import Message, MessageSegment
|
||||
|
||||
from configs.config import Config
|
||||
from configs.path_config import IMAGE_PATH, TEMP_PATH
|
||||
from services.log import logger
|
||||
from utils.browser import get_browser
|
||||
from utils.http_utils import AsyncHttpx, AsyncPlaywright
|
||||
from utils.manager import resources_manager
|
||||
from utils.message_builder import image
|
||||
from utils.utils import get_bot
|
||||
from utils.utils import get_bot, get_local_proxy
|
||||
|
||||
from .model import BilibiliSub
|
||||
from .utils import get_meta, get_user_card
|
||||
@ -27,6 +30,17 @@ DYNAMIC_PATH = IMAGE_PATH / "bilibili_sub" / "dynamic"
|
||||
DYNAMIC_PATH.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
|
||||
TYPE2MSG = {
|
||||
0: "发布了新动态",
|
||||
DynamicType.forward: "转发了一条动态",
|
||||
DynamicType.word: "发布了新文字动态",
|
||||
DynamicType.draw: "发布了新图文动态",
|
||||
DynamicType.av: "发布了新投稿",
|
||||
DynamicType.article: "发布了新专栏",
|
||||
DynamicType.music: "发布了新音频",
|
||||
}
|
||||
|
||||
|
||||
resources_manager.add_temp_dir(DYNAMIC_PATH)
|
||||
|
||||
|
||||
@ -52,6 +66,15 @@ async def add_live_sub(live_id: str, sub_user: str) -> str:
|
||||
short_id = live_info["short_id"]
|
||||
title = live_info["title"]
|
||||
live_status = live_info["live_status"]
|
||||
try:
|
||||
user_info = await get_user_card(uid)
|
||||
except ResponseCodeError:
|
||||
return f"未找到UpId:{uid} 的信息,请检查Id是否正确"
|
||||
uname = user_info["name"]
|
||||
dynamic_info = await dynamic.get_user_dynamics(int(uid))
|
||||
dynamic_upload_time = 0
|
||||
if dynamic_info.get("cards"):
|
||||
dynamic_upload_time = dynamic_info["cards"][0]["desc"]["dynamic_id"]
|
||||
if await BilibiliSub.sub_handle(
|
||||
room_id,
|
||||
"live",
|
||||
@ -59,11 +82,9 @@ async def add_live_sub(live_id: str, sub_user: str) -> str:
|
||||
uid=uid,
|
||||
live_short_id=short_id,
|
||||
live_status=live_status,
|
||||
uname=uname,
|
||||
dynamic_upload_time=dynamic_upload_time,
|
||||
):
|
||||
try:
|
||||
await _get_up_status(room_id)
|
||||
except Exception as e:
|
||||
logger.error(f"获取主播UP信息失败: {live_id} 错误", e=e)
|
||||
if data := await BilibiliSub.get_or_none(sub_id=room_id):
|
||||
uname = data.uname
|
||||
return (
|
||||
@ -102,11 +123,7 @@ async def add_up_sub(uid: str, sub_user: str) -> str:
|
||||
"""bilibili_api.user库中User类的get_dynamics改为bilireq.dynamic库的get_user_dynamics方法"""
|
||||
dynamic_info = await dynamic.get_user_dynamics(int(uid))
|
||||
if dynamic_info.get("cards"):
|
||||
dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"]
|
||||
"""bilibili_api.user库中User类的get_videos改为bilireq.user库的get_videos方法"""
|
||||
video_info = await get_videos(int(uid))
|
||||
if video_info["list"].get("vlist"):
|
||||
latest_video_created = video_info["list"]["vlist"][0]["created"]
|
||||
dynamic_upload_time = dynamic_info["cards"][0]["desc"]["dynamic_id"]
|
||||
except Exception as e:
|
||||
logger.error(f"订阅Up uid: {uid} 错误", e=e)
|
||||
if await BilibiliSub.sub_handle(
|
||||
@ -204,7 +221,7 @@ async def get_media_id(keyword: str) -> Optional[dict]:
|
||||
return {}
|
||||
|
||||
|
||||
async def get_sub_status(id_: str, sub_type: str) -> Optional[str]:
|
||||
async def get_sub_status(id_: str, sub_id: str, sub_type: str) -> Union[Message, str]:
|
||||
"""
|
||||
获取订阅状态
|
||||
:param id_: 订阅 id
|
||||
@ -214,7 +231,7 @@ async def get_sub_status(id_: str, sub_type: str) -> Optional[str]:
|
||||
if sub_type == "live":
|
||||
return await _get_live_status(id_)
|
||||
elif sub_type == "up":
|
||||
return await _get_up_status(id_)
|
||||
return await _get_up_status(id_, sub_id)
|
||||
elif sub_type == "season":
|
||||
return await _get_season_status(id_)
|
||||
except ResponseCodeError as e:
|
||||
@ -223,9 +240,10 @@ async def get_sub_status(id_: str, sub_type: str) -> Optional[str]:
|
||||
except Exception as e:
|
||||
logger.error(f"获取订阅状态发生预料之外的错误 Id_:{id_}", e=e)
|
||||
# return "发生了预料之外的错误..请稍后再试或联系管理员....."
|
||||
return ""
|
||||
|
||||
|
||||
async def _get_live_status(id_: str) -> Optional[str]:
|
||||
async def _get_live_status(id_: str) -> str:
|
||||
"""
|
||||
获取直播订阅状态
|
||||
:param id_: 直播间 id
|
||||
@ -247,56 +265,94 @@ async def _get_live_status(id_: str) -> Optional[str]:
|
||||
f"标题:{title}\n"
|
||||
f"直链:https://live.bilibili.com/{room_id}"
|
||||
)
|
||||
return None
|
||||
return ""
|
||||
|
||||
|
||||
async def _get_up_status(id_: str) -> Optional[str]:
|
||||
"""
|
||||
获取用户投稿状态
|
||||
:param id_: 订阅 id
|
||||
:return:
|
||||
async def _get_up_status(
|
||||
id_: str, live_id: Optional[str] = None
|
||||
) -> Union[Message, str]:
|
||||
"""获取up动态
|
||||
|
||||
参数:
|
||||
id_: up的id
|
||||
live_id: 直播间id,当订阅直播间时才有.
|
||||
|
||||
返回:
|
||||
Union[Message, str]: 消息
|
||||
"""
|
||||
rst = ""
|
||||
if _user := await BilibiliSub.get_or_none(sub_id=id_):
|
||||
"""bilibili_api.user库中User类的get_user_info改为bilireq.user库的get_user_info方法"""
|
||||
user_info = await get_user_card(_user.uid)
|
||||
uname = user_info["name"]
|
||||
"""bilibili_api.user库中User类的get_videos改为bilireq.user库的get_videos方法"""
|
||||
video_info = await get_videos(int(_user.uid))
|
||||
latest_video_created = 0
|
||||
video = None
|
||||
dividing_line = "\n-------------\n"
|
||||
if _user := await BilibiliSub.get_or_none(sub_id=live_id or id_):
|
||||
dynamics = None
|
||||
dynamic = None
|
||||
uname = ""
|
||||
try:
|
||||
dynamics = (
|
||||
await grpc_get_user_dynamics(int(id_), proxy=get_local_proxy())
|
||||
).list
|
||||
except Exception as e:
|
||||
logger.error("获取动态失败...", target=id_, e=e)
|
||||
if dynamics:
|
||||
uname = dynamics[0].modules[0].module_author.author.name
|
||||
for dyn in dynamics:
|
||||
if int(dyn.extend.dyn_id_str) > _user.dynamic_upload_time:
|
||||
dynamic = dyn
|
||||
break
|
||||
if not dynamic:
|
||||
logger.debug(f"{_user.sub_type}:{id_} 未有任何动态, 已跳过....")
|
||||
return ""
|
||||
if _user.uname != uname:
|
||||
await BilibiliSub.sub_handle(id_, uname=uname)
|
||||
dynamic_img, dynamic_upload_time, link = await get_user_dynamic(
|
||||
_user.uid, _user
|
||||
await BilibiliSub.sub_handle(live_id or id_, uname=uname)
|
||||
dynamic_img, link = await get_user_dynamic(dynamic.extend.dyn_id_str, _user)
|
||||
if not dynamic_img:
|
||||
logger.debug(f"{id_} 未发布新动态或截图失败, 已跳过....")
|
||||
return ""
|
||||
await BilibiliSub.sub_handle(
|
||||
live_id or id_, dynamic_upload_time=int(dynamic.extend.dyn_id_str)
|
||||
)
|
||||
if video_info["list"].get("vlist"):
|
||||
video = video_info["list"]["vlist"][0]
|
||||
latest_video_created = video["created"]
|
||||
if dynamic_img:
|
||||
await BilibiliSub.sub_handle(id_, dynamic_upload_time=dynamic_upload_time)
|
||||
rst += f"{uname} 发布了动态!\n" f"{dynamic_img}\n{link}"
|
||||
if (
|
||||
latest_video_created
|
||||
and _user.latest_video_created
|
||||
and video
|
||||
and _user.latest_video_created < latest_video_created
|
||||
):
|
||||
rst = rst + dividing_line if rst else rst
|
||||
await BilibiliSub.sub_handle(id_, latest_video_created=latest_video_created)
|
||||
rst += (
|
||||
f'{image(video["pic"])}\n'
|
||||
f"{uname} 投稿了新视频啦\n"
|
||||
f'标题:{video["title"]}\n'
|
||||
f'Bvid:{video["bvid"]}\n'
|
||||
f'直链:https://www.bilibili.com/video/{video["bvid"]}'
|
||||
rst += (
|
||||
f"{uname} {TYPE2MSG.get(dynamic.card_type, TYPE2MSG[0])}!\n"
|
||||
+ dynamic_img
|
||||
+ f"\n{link}\n"
|
||||
)
|
||||
video_info = ""
|
||||
if video_list := [
|
||||
module
|
||||
for module in dynamic.modules
|
||||
if str(module.module_dynamic.dyn_archive)
|
||||
]:
|
||||
video = video_list[0].module_dynamic.dyn_archive
|
||||
video_info = (
|
||||
image(video.cover)
|
||||
+ f"标题: {video.title}\nBvid: {video.bvid}\n直链: https://www.bilibili.com/video/{video.bvid}"
|
||||
)
|
||||
rst = None if rst == dividing_line else rst
|
||||
rst += video_info + "\n"
|
||||
download_dynamic_image = Config.get_config(
|
||||
"bilibili_sub", "DOWNLOAD_DYNAMIC_IMAGE"
|
||||
)
|
||||
draw_info = ""
|
||||
if download_dynamic_image and (
|
||||
draw_list := [
|
||||
module.module_dynamic.dyn_draw
|
||||
for module in dynamic.modules
|
||||
if str(module.module_dynamic.dyn_draw)
|
||||
]
|
||||
):
|
||||
idx = 0
|
||||
for draws in draw_list:
|
||||
for draw in list(draws.items):
|
||||
path = (
|
||||
TEMP_PATH
|
||||
/ f"{_user.uid}_{dynamic.extend.dyn_id_str}_draw_{idx}.jpg"
|
||||
)
|
||||
if await AsyncHttpx.download_file(draw.src, path):
|
||||
draw_info += image(path)
|
||||
idx += 1
|
||||
if draw_info:
|
||||
rst += "动态图片\n" + draw_info + "\n"
|
||||
return rst
|
||||
|
||||
|
||||
async def _get_season_status(id_: str) -> Optional[str]:
|
||||
async def _get_season_status(id_: str) -> str:
|
||||
"""
|
||||
获取 番剧 更新状态
|
||||
:param id_: 番剧 id
|
||||
@ -316,36 +372,30 @@ async def _get_season_status(id_: str) -> Optional[str]:
|
||||
f"[{title}]更新啦\n"
|
||||
f"最新集数:{new_ep}"
|
||||
)
|
||||
return None
|
||||
return ""
|
||||
|
||||
|
||||
async def get_user_dynamic(
|
||||
uid: str, local_user: BilibiliSub
|
||||
) -> Tuple[Optional[MessageSegment], int, str]:
|
||||
dynamic_id: str, local_user: BilibiliSub
|
||||
) -> Tuple[Optional[MessageSegment], str]:
|
||||
"""
|
||||
获取用户动态
|
||||
:param uid: 用户uid
|
||||
:param dynamic_id: 动态id
|
||||
:param local_user: 数据库存储的用户数据
|
||||
:return: 最新动态截图与时间
|
||||
"""
|
||||
"""bilibili_api.user库中User类的get_dynamics改为bilireq.dynamic库的get_user_dynamics方法"""
|
||||
dynamic_info = await dynamic.get_user_dynamics(int(uid))
|
||||
if dynamic_info.get("cards"):
|
||||
dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"]
|
||||
dynamic_id = dynamic_info["cards"][0]["desc"]["dynamic_id"]
|
||||
if local_user.dynamic_upload_time < dynamic_upload_time:
|
||||
image = await AsyncPlaywright.screenshot(
|
||||
f"https://t.bilibili.com/{dynamic_id}",
|
||||
DYNAMIC_PATH / f"sub_{local_user.sub_id}.png",
|
||||
".bili-dyn-item__main",
|
||||
wait_until="networkidle",
|
||||
)
|
||||
return (
|
||||
image,
|
||||
dynamic_upload_time,
|
||||
f"https://t.bilibili.com/{dynamic_id}",
|
||||
)
|
||||
return None, 0, ""
|
||||
if local_user.dynamic_upload_time < int(dynamic_id):
|
||||
image = await AsyncPlaywright.screenshot(
|
||||
f"https://t.bilibili.com/{dynamic_id}",
|
||||
DYNAMIC_PATH / f"sub_{local_user.sub_id}.png",
|
||||
".bili-dyn-item__main",
|
||||
wait_until="networkidle",
|
||||
)
|
||||
return (
|
||||
image,
|
||||
f"https://t.bilibili.com/{dynamic_id}",
|
||||
)
|
||||
return None, ""
|
||||
|
||||
|
||||
class SubManager:
|
||||
|
||||
6357
poetry.lock
generated
6357
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@ -36,7 +36,7 @@ dateparser = "^1.1.0"
|
||||
cn2an = "^0.5.16"
|
||||
python-jose = "^3.3.0"
|
||||
python-multipart = "^0.0.5"
|
||||
bilireq = "^0.2.3.post0"
|
||||
bilireq = "^0.2.6"
|
||||
emoji = "^1.7.0"
|
||||
wordcloud = "^1.8.1"
|
||||
rich = "^12.4.3"
|
||||
|
||||
@ -13,7 +13,7 @@ from playwright.async_api import BrowserContext, Page
|
||||
from retrying import retry
|
||||
|
||||
from services.log import logger
|
||||
from utils.user_agent import get_user_agent
|
||||
from utils.user_agent import get_user_agent, get_user_agent_str
|
||||
|
||||
from .browser import get_browser
|
||||
from .message_builder import image
|
||||
@ -218,7 +218,7 @@ class AsyncHttpx:
|
||||
else:
|
||||
logger.error(f"下载 {url} 下载超时.. Path:{path.absolute()}")
|
||||
except Exception as e:
|
||||
logger.error(f"下载 {url} 未知错误 {type(e)}:{e}.. Path:{path.absolute()}")
|
||||
logger.error(f"下载 {url} 错误 Path:{path.absolute()}", e=e)
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
@ -329,6 +329,7 @@ class AsyncPlaywright:
|
||||
] = "networkidle",
|
||||
timeout: Optional[float] = None,
|
||||
type_: Optional[Literal["jpeg", "png"]] = None,
|
||||
user_agent: Optional[str] = None,
|
||||
**kwargs,
|
||||
) -> Optional[MessageSegment]:
|
||||
"""
|
||||
@ -353,7 +354,11 @@ class AsyncPlaywright:
|
||||
element_list = [element]
|
||||
else:
|
||||
element_list = element
|
||||
async with cls.new_page(viewport=viewport_size) as page:
|
||||
async with cls.new_page(
|
||||
viewport=viewport_size,
|
||||
user_agent=user_agent,
|
||||
**kwargs,
|
||||
) as page:
|
||||
await page.goto(url, timeout=timeout, wait_until=wait_until)
|
||||
card = page
|
||||
for e in element_list:
|
||||
|
||||
@ -7,7 +7,7 @@ import uuid
|
||||
from io import BytesIO
|
||||
from math import ceil
|
||||
from pathlib import Path
|
||||
from typing import Awaitable, Callable, List, Literal, Optional, Tuple, Union
|
||||
from typing import Any, Awaitable, Callable, List, Literal, Optional, Tuple, Union
|
||||
|
||||
import cv2
|
||||
import imagehash
|
||||
@ -353,16 +353,16 @@ class BuildImage:
|
||||
:param font_size: 字体大小
|
||||
"""
|
||||
font_ = cls.load_font(font, font_size)
|
||||
return font_.getsize(msg)
|
||||
return font_.getsize(msg) # type: ignore
|
||||
|
||||
def getsize(self, msg: str) -> Tuple[int, int]:
|
||||
def getsize(self, msg: Any) -> Tuple[int, int]:
|
||||
"""
|
||||
说明:
|
||||
获取文字在该图片 font_size 下所需要的空间
|
||||
参数:
|
||||
:param msg: 文字内容
|
||||
"""
|
||||
return self.font.getsize(msg)
|
||||
return self.font.getsize(str(msg)) # type: ignore
|
||||
|
||||
async def apoint(
|
||||
self, pos: Tuple[int, int], fill: Optional[Tuple[int, int, int]] = None
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import random
|
||||
|
||||
|
||||
user_agent = [
|
||||
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
|
||||
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
|
||||
@ -45,3 +44,7 @@ user_agent = [
|
||||
|
||||
def get_user_agent():
|
||||
return {"User-Agent": random.choice(user_agent)}
|
||||
|
||||
|
||||
def get_user_agent_str():
|
||||
return random.choice(user_agent)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user