mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2026-10-04 19:29:59 +08:00
update 0.0.6.2
This commit is contained in:
Regular → Executable
+236
-235
@@ -1,235 +1,236 @@
|
||||
from nonebot import on_command
|
||||
from nonebot.typing import T_State
|
||||
from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent, Message
|
||||
from .data_source import (
|
||||
add_live_sub,
|
||||
delete_sub,
|
||||
add_up_sub,
|
||||
add_season_sub,
|
||||
get_media_id,
|
||||
get_sub_status,
|
||||
SubManager,
|
||||
BilibiliSub
|
||||
)
|
||||
from models.level_user import LevelUser
|
||||
from configs.config import Config
|
||||
from utils.utils import get_message_text, is_number, scheduler, get_bot
|
||||
from typing import Optional
|
||||
from services.log import logger
|
||||
from nonebot import Driver
|
||||
import nonebot
|
||||
|
||||
__zx_plugin_name__ = "B站订阅"
|
||||
__plugin_usage__ = """
|
||||
usage:
|
||||
B站直播,番剧,UP动态开播等提醒
|
||||
主播订阅相当于 直播间订阅 + UP订阅
|
||||
指令:[示例Id乱打的,仅做示例]
|
||||
添加订阅 ['主播'/'UP'/'番剧'] [id/链接/番名]
|
||||
删除订阅 [id]
|
||||
查看订阅
|
||||
示例:添加订阅主播 2345344 <-(直播房间id)
|
||||
示例:添加订阅UP 2355543 <-(个人主页id)
|
||||
示例:添加订阅番剧 史莱姆 <-(支持模糊搜索)
|
||||
示例:添加订阅番剧 125344 <-(番剧id)
|
||||
示例:删除订阅 2324344 <-(任意id,通过查看订阅获取)
|
||||
""".strip()
|
||||
__plugin_des__ = "非常便利的B站订阅通知"
|
||||
__plugin_cmd__ = ["添加订阅 [主播/UP/番剧] [id/链接/番名]", "删除订阅 [id]", "查看订阅"]
|
||||
__plugin_version__ = 0.1
|
||||
__plugin_author__ = "HibiKier"
|
||||
__plugin_settings__ = {
|
||||
"level": 5,
|
||||
"default_status": True,
|
||||
"limit_superuser": False,
|
||||
"cmd": ["B站订阅", "b站订阅", "添加订阅", "删除订阅", "查看订阅"],
|
||||
}
|
||||
__plugin_configs__ = {
|
||||
"GROUP_BILIBILI_SUB_LEVEL": {
|
||||
"value": 5,
|
||||
"help": "群内bilibili订阅需要管理的权限",
|
||||
"default_value": 5,
|
||||
}
|
||||
}
|
||||
|
||||
add_sub = on_command("添加订阅", priority=5, block=True)
|
||||
del_sub = on_command("删除订阅", priority=5, block=True)
|
||||
show_sub_info = on_command("查看订阅", priority=5, block=True)
|
||||
|
||||
driver: Driver = nonebot.get_driver()
|
||||
|
||||
|
||||
sub_manager: Optional[SubManager] = None
|
||||
|
||||
|
||||
@driver.on_startup
|
||||
async def _():
|
||||
global sub_manager
|
||||
sub_manager = SubManager()
|
||||
|
||||
|
||||
@add_sub.args_parser
|
||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||
season_data = state["season_data"]
|
||||
msg = get_message_text(event.json())
|
||||
if not is_number(msg) or int(msg) < 1 or int(msg) > len(season_data):
|
||||
await add_sub.reject("Id必须为数字且在范围内!请重新输入...")
|
||||
state["id"] = season_data[int(msg) - 1]["media_id"]
|
||||
|
||||
|
||||
@add_sub.handle()
|
||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||
msg = get_message_text(event.json()).split()
|
||||
if len(msg) < 2:
|
||||
await add_sub.finish("参数不完全,请查看订阅帮助...")
|
||||
sub_type = msg[0]
|
||||
id_ = ""
|
||||
if isinstance(event, GroupMessageEvent):
|
||||
if not await LevelUser.check_level(
|
||||
event.user_id,
|
||||
event.group_id,
|
||||
Config.get_config("bilibili_sub", "GROUP_BILIBILI_SUB_LEVEL"),
|
||||
):
|
||||
await add_sub.finish(
|
||||
f"您的权限不足,群内订阅的需要 {Config.get_config('bilibili_sub', 'GROUP_BILIBILI_SUB_LEVEL')} 级权限..",
|
||||
at_sender=True,
|
||||
)
|
||||
sub_user = f"{event.user_id}:{event.group_id}"
|
||||
else:
|
||||
sub_user = f"{event.user_id}"
|
||||
state["sub_type"] = sub_type
|
||||
state["sub_user"] = sub_user
|
||||
if len(msg) > 1:
|
||||
if "http" in msg[1]:
|
||||
msg[1] = msg[1].split("?")[0]
|
||||
msg[1] = msg[1][:-1] if msg[1][-1] == "/" else msg[1]
|
||||
msg[1] = msg[1].split("/")[-1]
|
||||
id_ = msg[1][2:] if msg[1].startswith("md") else msg[1]
|
||||
if not is_number(id_):
|
||||
if sub_type in ["season", "动漫", "番剧"]:
|
||||
rst = "*以为您找到以下番剧,请输入Id选择:*\n"
|
||||
state["season_data"] = await get_media_id(id_)
|
||||
if len(state["season_data"]) == 0:
|
||||
await add_sub.finish(f"未找到番剧:{msg}")
|
||||
for i, x in enumerate(state["season_data"]):
|
||||
rst += f'{i + 1}.{state["season_data"][x]["title"]}\n----------\n'
|
||||
await add_sub.send("\n".join(rst.split("\n")[:-1]))
|
||||
else:
|
||||
await add_sub.finish("Id 必须为全数字!")
|
||||
else:
|
||||
state["id"] = int(id_)
|
||||
|
||||
|
||||
@add_sub.got("id")
|
||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||
sub_type = state["sub_type"]
|
||||
sub_user = state["sub_user"]
|
||||
id_ = state["id"]
|
||||
if sub_type in ["主播", "直播"]:
|
||||
await add_sub.send(await add_live_sub(id_, sub_user))
|
||||
elif sub_type.lower() in ["up", "用户"]:
|
||||
await add_sub.send(await add_up_sub(id_, sub_user))
|
||||
elif sub_type in ["season", "动漫", "番剧"]:
|
||||
await add_sub.send(await add_season_sub(id_, sub_user))
|
||||
else:
|
||||
await add_sub.finish("参数错误,第一参数必须为:主播/up/番剧!")
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, GROUP "
|
||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||
f" 添加订阅:{sub_type} -> {sub_user} -> {id_}"
|
||||
)
|
||||
|
||||
|
||||
@del_sub.handle()
|
||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||
msg = get_message_text(event.json())
|
||||
if not is_number(msg):
|
||||
await del_sub.finish("Id必须为数字!", at_sender=True)
|
||||
id_ = (
|
||||
f"{event.user_id}:{event.group_id}"
|
||||
if isinstance(event, GroupMessageEvent)
|
||||
else f"{event.user_id}"
|
||||
)
|
||||
if await BilibiliSub.delete_bilibili_sub(int(msg), id_):
|
||||
await del_sub.send(f"删除订阅id:{msg} 成功...")
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, GROUP "
|
||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||
f" 删除订阅 {id_}"
|
||||
)
|
||||
else:
|
||||
await del_sub.send(f"删除订阅id:{msg} 失败...")
|
||||
|
||||
|
||||
@show_sub_info.handle()
|
||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||
id_ = (
|
||||
f"{event.user_id}:{event.group_id}"
|
||||
if isinstance(event, GroupMessageEvent)
|
||||
else f"{event.user_id}"
|
||||
)
|
||||
data = await BilibiliSub.get_sub_data(id_)
|
||||
live_rst = ""
|
||||
up_rst = ""
|
||||
season_rst = ""
|
||||
for x in data:
|
||||
if x.sub_type == "live":
|
||||
live_rst += (
|
||||
f"\t直播间id:{x.sub_id}\n" f"\t名称:{x.uname}\n" f"------------------\n"
|
||||
)
|
||||
if x.sub_type == "up":
|
||||
up_rst += f"\tUP:{x.uname}\n" f"\tuid:{x.uid}\n" f"------------------\n"
|
||||
if x.sub_type == "season":
|
||||
season_rst += (
|
||||
f"\t番名:{x.season_name}\n"
|
||||
f"\t当前集数:{x.season_current_episode}\n"
|
||||
f"------------------\n"
|
||||
)
|
||||
live_rst = "当前订阅的直播:\n" + live_rst if live_rst else live_rst
|
||||
up_rst = "当前订阅的UP:\n" + up_rst if up_rst else up_rst
|
||||
season_rst = "当前订阅的番剧:\n" + season_rst if season_rst else season_rst
|
||||
if not live_rst and not up_rst and not season_rst:
|
||||
live_rst = "您目前没有任何订阅..."
|
||||
await show_sub_info.send(live_rst + up_rst + season_rst)
|
||||
|
||||
|
||||
# 推送
|
||||
@scheduler.scheduled_job(
|
||||
"interval",
|
||||
seconds=30,
|
||||
)
|
||||
async def _():
|
||||
bot = get_bot()
|
||||
sub = None
|
||||
if bot:
|
||||
try:
|
||||
await sub_manager.reload_sub_data()
|
||||
sub = await sub_manager.random_sub_data()
|
||||
if sub:
|
||||
rst = await get_sub_status(sub.sub_id, sub.sub_type)
|
||||
await send_sub_msg(rst, sub, bot)
|
||||
if sub.sub_type == "live":
|
||||
rst = await get_sub_status(sub.sub_id, "up")
|
||||
await send_sub_msg(rst, sub, bot)
|
||||
except Exception as e:
|
||||
logger.error(f"B站订阅推送发生错误 sub_id:{sub.sub_id if sub else 0} {type(e)}:{e}")
|
||||
|
||||
|
||||
async def send_sub_msg(rst: str, sub: BilibiliSub, bot: Bot):
|
||||
"""
|
||||
推送信息
|
||||
:param rst: 回复
|
||||
:param sub: BilibiliSub
|
||||
:param bot: Bot
|
||||
"""
|
||||
if rst:
|
||||
for x in sub.sub_users.split(",")[:-1]:
|
||||
try:
|
||||
if ":" in x:
|
||||
await bot.send_group_msg(
|
||||
group_id=int(x.split(":")[1]), message=Message(rst)
|
||||
)
|
||||
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} {type(e)}:{e}")
|
||||
from nonebot import on_command
|
||||
from nonebot.typing import T_State
|
||||
from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent, Message
|
||||
from .data_source import (
|
||||
add_live_sub,
|
||||
delete_sub,
|
||||
add_up_sub,
|
||||
add_season_sub,
|
||||
get_media_id,
|
||||
get_sub_status,
|
||||
SubManager,
|
||||
BilibiliSub
|
||||
)
|
||||
from models.level_user import LevelUser
|
||||
from configs.config import Config
|
||||
from utils.utils import get_message_text, is_number, scheduler, get_bot
|
||||
from typing import Optional
|
||||
from services.log import logger
|
||||
from nonebot import Driver
|
||||
import nonebot
|
||||
|
||||
__zx_plugin_name__ = "B站订阅"
|
||||
__plugin_usage__ = """
|
||||
usage:
|
||||
B站直播,番剧,UP动态开播等提醒
|
||||
主播订阅相当于 直播间订阅 + UP订阅
|
||||
指令:[示例Id乱打的,仅做示例]
|
||||
添加订阅 ['主播'/'UP'/'番剧'] [id/链接/番名]
|
||||
删除订阅 [id]
|
||||
查看订阅
|
||||
示例:添加订阅主播 2345344 <-(直播房间id)
|
||||
示例:添加订阅UP 2355543 <-(个人主页id)
|
||||
示例:添加订阅番剧 史莱姆 <-(支持模糊搜索)
|
||||
示例:添加订阅番剧 125344 <-(番剧id)
|
||||
示例:删除订阅 2324344 <-(任意id,通过查看订阅获取)
|
||||
""".strip()
|
||||
__plugin_des__ = "非常便利的B站订阅通知"
|
||||
__plugin_cmd__ = ["添加订阅 [主播/UP/番剧] [id/链接/番名]", "删除订阅 [id]", "查看订阅"]
|
||||
__plugin_version__ = 0.1
|
||||
__plugin_author__ = "HibiKier"
|
||||
__plugin_settings__ = {
|
||||
"level": 5,
|
||||
"default_status": True,
|
||||
"limit_superuser": False,
|
||||
"cmd": ["B站订阅", "b站订阅", "添加订阅", "删除订阅", "查看订阅"],
|
||||
}
|
||||
__plugin_configs__ = {
|
||||
"GROUP_BILIBILI_SUB_LEVEL": {
|
||||
"value": 5,
|
||||
"help": "群内bilibili订阅需要管理的权限",
|
||||
"default_value": 5,
|
||||
}
|
||||
}
|
||||
|
||||
add_sub = on_command("添加订阅", priority=5, block=True)
|
||||
del_sub = on_command("删除订阅", priority=5, block=True)
|
||||
show_sub_info = on_command("查看订阅", priority=5, block=True)
|
||||
|
||||
driver: Driver = nonebot.get_driver()
|
||||
|
||||
|
||||
sub_manager: Optional[SubManager] = None
|
||||
|
||||
|
||||
@driver.on_startup
|
||||
async def _():
|
||||
global sub_manager
|
||||
sub_manager = SubManager()
|
||||
|
||||
|
||||
@add_sub.args_parser
|
||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||
season_data = state["season_data"]
|
||||
msg = get_message_text(event.json())
|
||||
if not is_number(msg) or int(msg) < 1 or int(msg) > len(season_data):
|
||||
await add_sub.reject("Id必须为数字且在范围内!请重新输入...")
|
||||
state["id"] = season_data[int(msg) - 1]["media_id"]
|
||||
|
||||
|
||||
@add_sub.handle()
|
||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||
msg = get_message_text(event.json()).split()
|
||||
if len(msg) < 2:
|
||||
await add_sub.finish("参数不完全,请查看订阅帮助...")
|
||||
sub_type = msg[0]
|
||||
id_ = ""
|
||||
if isinstance(event, GroupMessageEvent):
|
||||
if not await LevelUser.check_level(
|
||||
event.user_id,
|
||||
event.group_id,
|
||||
Config.get_config("bilibili_sub", "GROUP_BILIBILI_SUB_LEVEL"),
|
||||
):
|
||||
await add_sub.finish(
|
||||
f"您的权限不足,群内订阅的需要 {Config.get_config('bilibili_sub', 'GROUP_BILIBILI_SUB_LEVEL')} 级权限..",
|
||||
at_sender=True,
|
||||
)
|
||||
sub_user = f"{event.user_id}:{event.group_id}"
|
||||
else:
|
||||
sub_user = f"{event.user_id}"
|
||||
state["sub_type"] = sub_type
|
||||
state["sub_user"] = sub_user
|
||||
if len(msg) > 1:
|
||||
if "http" in msg[1]:
|
||||
msg[1] = msg[1].split("?")[0]
|
||||
msg[1] = msg[1][:-1] if msg[1][-1] == "/" else msg[1]
|
||||
msg[1] = msg[1].split("/")[-1]
|
||||
id_ = msg[1][2:] if msg[1].startswith("md") else msg[1]
|
||||
if not is_number(id_):
|
||||
if sub_type in ["season", "动漫", "番剧"]:
|
||||
rst = "*以为您找到以下番剧,请输入Id选择:*\n"
|
||||
state["season_data"] = await get_media_id(id_)
|
||||
if len(state["season_data"]) == 0:
|
||||
await add_sub.finish(f"未找到番剧:{msg}")
|
||||
for i, x in enumerate(state["season_data"]):
|
||||
rst += f'{i + 1}.{state["season_data"][x]["title"]}\n----------\n'
|
||||
await add_sub.send("\n".join(rst.split("\n")[:-1]))
|
||||
else:
|
||||
await add_sub.finish("Id 必须为全数字!")
|
||||
else:
|
||||
state["id"] = int(id_)
|
||||
|
||||
|
||||
@add_sub.got("id")
|
||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||
sub_type = state["sub_type"]
|
||||
sub_user = state["sub_user"]
|
||||
id_ = state["id"]
|
||||
if sub_type in ["主播", "直播"]:
|
||||
await add_sub.send(await add_live_sub(id_, sub_user))
|
||||
elif sub_type.lower() in ["up", "用户"]:
|
||||
await add_sub.send(await add_up_sub(id_, sub_user))
|
||||
elif sub_type in ["season", "动漫", "番剧"]:
|
||||
await add_sub.send(await add_season_sub(id_, sub_user))
|
||||
else:
|
||||
await add_sub.finish("参数错误,第一参数必须为:主播/up/番剧!")
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, GROUP "
|
||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||
f" 添加订阅:{sub_type} -> {sub_user} -> {id_}"
|
||||
)
|
||||
|
||||
|
||||
@del_sub.handle()
|
||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||
msg = get_message_text(event.json())
|
||||
if not is_number(msg):
|
||||
await del_sub.finish("Id必须为数字!", at_sender=True)
|
||||
id_ = (
|
||||
f"{event.user_id}:{event.group_id}"
|
||||
if isinstance(event, GroupMessageEvent)
|
||||
else f"{event.user_id}"
|
||||
)
|
||||
if await BilibiliSub.delete_bilibili_sub(int(msg), id_):
|
||||
await del_sub.send(f"删除订阅id:{msg} 成功...")
|
||||
logger.info(
|
||||
f"(USER {event.user_id}, GROUP "
|
||||
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
|
||||
f" 删除订阅 {id_}"
|
||||
)
|
||||
else:
|
||||
await del_sub.send(f"删除订阅id:{msg} 失败...")
|
||||
|
||||
|
||||
@show_sub_info.handle()
|
||||
async def _(bot: Bot, event: MessageEvent, state: T_State):
|
||||
id_ = (
|
||||
f"{event.user_id}:{event.group_id}"
|
||||
if isinstance(event, GroupMessageEvent)
|
||||
else f"{event.user_id}"
|
||||
)
|
||||
data = await BilibiliSub.get_sub_data(id_)
|
||||
live_rst = ""
|
||||
up_rst = ""
|
||||
season_rst = ""
|
||||
for x in data:
|
||||
if x.sub_type == "live":
|
||||
live_rst += (
|
||||
f"\t直播间id:{x.sub_id}\n" f"\t名称:{x.uname}\n" f"------------------\n"
|
||||
)
|
||||
if x.sub_type == "up":
|
||||
up_rst += f"\tUP:{x.uname}\n" f"\tuid:{x.uid}\n" f"------------------\n"
|
||||
if x.sub_type == "season":
|
||||
season_rst += (
|
||||
f"\t番名:{x.season_name}\n"
|
||||
f"\t当前集数:{x.season_current_episode}\n"
|
||||
f"------------------\n"
|
||||
)
|
||||
live_rst = "当前订阅的直播:\n" + live_rst if live_rst else live_rst
|
||||
up_rst = "当前订阅的UP:\n" + up_rst if up_rst else up_rst
|
||||
season_rst = "当前订阅的番剧:\n" + season_rst if season_rst else season_rst
|
||||
if not live_rst and not up_rst and not season_rst:
|
||||
live_rst = "您目前没有任何订阅..."
|
||||
await show_sub_info.send(live_rst + up_rst + season_rst)
|
||||
|
||||
|
||||
# 推送
|
||||
@scheduler.scheduled_job(
|
||||
"interval",
|
||||
seconds=30,
|
||||
)
|
||||
async def _():
|
||||
bot = get_bot()
|
||||
sub = None
|
||||
if bot:
|
||||
try:
|
||||
await sub_manager.reload_sub_data()
|
||||
sub = await sub_manager.random_sub_data()
|
||||
if sub:
|
||||
logger.info(f"Bilibili订阅开始检测:{sub.sub_id}")
|
||||
rst = await get_sub_status(sub.sub_id, sub.sub_type)
|
||||
await send_sub_msg(rst, sub, bot)
|
||||
if sub.sub_type == "live":
|
||||
rst = await get_sub_status(sub.sub_id, "up")
|
||||
await send_sub_msg(rst, sub, bot)
|
||||
except Exception as e:
|
||||
logger.error(f"B站订阅推送发生错误 sub_id:{sub.sub_id if sub else 0} {type(e)}:{e}")
|
||||
|
||||
|
||||
async def send_sub_msg(rst: str, sub: BilibiliSub, bot: Bot):
|
||||
"""
|
||||
推送信息
|
||||
:param rst: 回复
|
||||
:param sub: BilibiliSub
|
||||
:param bot: Bot
|
||||
"""
|
||||
if rst:
|
||||
for x in sub.sub_users.split(",")[:-1]:
|
||||
try:
|
||||
if ":" in x:
|
||||
await bot.send_group_msg(
|
||||
group_id=int(x.split(":")[1]), message=Message(rst)
|
||||
)
|
||||
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} {type(e)}:{e}")
|
||||
|
||||
Regular → Executable
+391
-394
@@ -1,394 +1,391 @@
|
||||
from bilibili_api.exceptions.ResponseCodeException import ResponseCodeException
|
||||
from utils.manager import resources_manager
|
||||
from asyncio.exceptions import TimeoutError
|
||||
from .model import BilibiliSub
|
||||
from bilibili_api.live import LiveRoom
|
||||
from bilibili_api import bangumi
|
||||
from utils.message_builder import image
|
||||
from bilibili_api.user import User
|
||||
from bilibili_api import user
|
||||
from typing import Optional
|
||||
from pathlib import Path
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from datetime import datetime
|
||||
from utils.browser import get_browser
|
||||
from services.db_context import db
|
||||
from services.log import logger
|
||||
import aiohttp
|
||||
import random
|
||||
|
||||
|
||||
bilibili_search_url = "https://api.bilibili.com/x/web-interface/search/all/v2"
|
||||
|
||||
dynamic_path = Path(IMAGE_PATH) / "bilibili_sub" / "dynamic"
|
||||
dynamic_path.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
|
||||
resources_manager.add_temp_dir(dynamic_path)
|
||||
|
||||
|
||||
async def add_live_sub(live_id: int, sub_user: str) -> str:
|
||||
"""
|
||||
添加直播订阅
|
||||
:param live_id: 直播房间号
|
||||
:param sub_user: 订阅用户 id # 7384933:private or 7384933:2342344(group)
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
async with db.transaction():
|
||||
try:
|
||||
live = LiveRoom(live_id)
|
||||
live_info = (await live.get_room_info())["room_info"]
|
||||
except ResponseCodeException:
|
||||
return f"未找到房间号Id:{live_id} 的信息,请检查Id是否正确"
|
||||
uid = live_info["uid"]
|
||||
room_id = live_info["room_id"]
|
||||
short_id = live_info["short_id"]
|
||||
title = live_info["title"]
|
||||
live_status = live_info["live_status"]
|
||||
if await BilibiliSub.add_bilibili_sub(
|
||||
room_id,
|
||||
"live",
|
||||
sub_user,
|
||||
uid=uid,
|
||||
live_short_id=short_id,
|
||||
live_status=live_status,
|
||||
):
|
||||
await _get_up_status(live_id)
|
||||
uname = (await BilibiliSub.get_sub(live_id)).uname
|
||||
return (
|
||||
"已成功订阅主播:\n"
|
||||
f"\ttitle:{title}\n"
|
||||
f"\tname: {uname}\n"
|
||||
f"\tlive_id:{live_id}\n"
|
||||
f"\tuid:{uid}"
|
||||
)
|
||||
else:
|
||||
return "添加订阅失败..."
|
||||
except Exception as e:
|
||||
logger.error(f"订阅主播live_id:{live_id} 发生了错误 {type(e)}:{e}")
|
||||
return "添加订阅失败..."
|
||||
|
||||
|
||||
async def add_up_sub(uid: int, sub_user: str) -> str:
|
||||
"""
|
||||
添加订阅 UP
|
||||
:param uid: UP uid
|
||||
:param sub_user: 订阅用户
|
||||
"""
|
||||
try:
|
||||
async with db.transaction():
|
||||
try:
|
||||
u = user.User(uid)
|
||||
user_info = await u.get_user_info()
|
||||
except ResponseCodeException:
|
||||
return f"未找到UpId:{uid} 的信息,请检查Id是否正确"
|
||||
uname = user_info["name"]
|
||||
dynamic_info = await u.get_dynamics(0)
|
||||
dynamic_upload_time = 0
|
||||
if dynamic_info.get("cards"):
|
||||
dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"]
|
||||
video_info = await u.get_videos()
|
||||
latest_video_created = 0
|
||||
if video_info["list"].get("vlist"):
|
||||
latest_video_created = video_info["list"]["vlist"][0]["created"]
|
||||
if await BilibiliSub.add_bilibili_sub(
|
||||
uid,
|
||||
"up",
|
||||
sub_user,
|
||||
uid=uid,
|
||||
uname=uname,
|
||||
dynamic_upload_time=dynamic_upload_time,
|
||||
latest_video_created=latest_video_created,
|
||||
):
|
||||
return "已成功订阅UP:\n" f"\tname: {uname}\n" f"\tuid:{uid}"
|
||||
else:
|
||||
return "添加订阅失败..."
|
||||
except Exception as e:
|
||||
logger.error(f"订阅Up uid:{uid} 发生了错误 {type(e)}:{e}")
|
||||
return "添加订阅失败..."
|
||||
|
||||
|
||||
async def add_season_sub(media_id: int, sub_user: str) -> str:
|
||||
"""
|
||||
添加订阅 UP
|
||||
:param media_id: 番剧 media_id
|
||||
:param sub_user: 订阅用户
|
||||
"""
|
||||
try:
|
||||
async with db.transaction():
|
||||
try:
|
||||
season_info = await bangumi.get_meta(media_id)
|
||||
except ResponseCodeException:
|
||||
return f"未找到media_id:{media_id} 的信息,请检查Id是否正确"
|
||||
season_id = season_info["media"]["season_id"]
|
||||
season_current_episode = season_info["media"]["new_ep"]["index"]
|
||||
season_name = season_info["media"]["title"]
|
||||
if await BilibiliSub.add_bilibili_sub(
|
||||
media_id,
|
||||
"season",
|
||||
sub_user,
|
||||
season_name=season_name,
|
||||
season_id=season_id,
|
||||
season_current_episode=season_current_episode,
|
||||
):
|
||||
return (
|
||||
"已成功订阅番剧:\n"
|
||||
f"\ttitle: {season_name}\n"
|
||||
f"\tcurrent_episode: {season_current_episode}"
|
||||
)
|
||||
else:
|
||||
return "添加订阅失败..."
|
||||
except Exception as e:
|
||||
logger.error(f"订阅番剧 media_id:{media_id} 发生了错误 {type(e)}:{e}")
|
||||
return "添加订阅失败..."
|
||||
|
||||
|
||||
async def delete_sub(sub_id: str, sub_user: str) -> str:
|
||||
"""
|
||||
删除订阅
|
||||
:param sub_id: 订阅 id
|
||||
:param sub_user: 订阅用户 id # 7384933:private or 7384933:2342344(group)
|
||||
"""
|
||||
if await BilibiliSub.delete_bilibili_sub(sub_id, sub_user):
|
||||
return f"已成功取消订阅:{sub_id}"
|
||||
else:
|
||||
return f"取消订阅:{sub_id} 失败,请检查是否订阅过该Id...."
|
||||
|
||||
|
||||
async def get_media_id(keyword: str) -> dict:
|
||||
"""
|
||||
获取番剧的 media_id
|
||||
:param keyword: 番剧名称
|
||||
"""
|
||||
params = {"keyword": keyword}
|
||||
async with aiohttp.ClientSession() as session:
|
||||
for _ in range(3):
|
||||
try:
|
||||
_season_data = {}
|
||||
async with session.get(
|
||||
bilibili_search_url, timeout=5, params=params
|
||||
) as response:
|
||||
if response.status == 200:
|
||||
data = await response.json()
|
||||
if data.get("data"):
|
||||
for item in data["data"]["result"]:
|
||||
if item["result_type"] == "media_bangumi":
|
||||
idx = 0
|
||||
for x in item["data"]:
|
||||
_season_data[idx] = {
|
||||
"media_id": x["media_id"],
|
||||
"title": x["title"]
|
||||
.replace('<em class="keyword">', "")
|
||||
.replace("</em>", ""),
|
||||
}
|
||||
idx += 1
|
||||
return _season_data
|
||||
except TimeoutError:
|
||||
pass
|
||||
return {}
|
||||
|
||||
|
||||
async def get_sub_status(id_: int, sub_type: str) -> Optional[str]:
|
||||
"""
|
||||
获取订阅状态
|
||||
:param id_: 订阅 id
|
||||
:param sub_type: 订阅类型
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
if sub_type == "live":
|
||||
return await _get_live_status(id_)
|
||||
elif sub_type == "up":
|
||||
return await _get_up_status(id_)
|
||||
elif sub_type == "season":
|
||||
return await _get_season_status(id_)
|
||||
except ResponseCodeException:
|
||||
return "获取信息失败...请检查订阅Id是否存在或稍后再试..."
|
||||
# except Exception as e:
|
||||
# logger.error(f"获取订阅状态发生预料之外的错误 id_:{id_} {type(e)}:{e}")
|
||||
# return "发生了预料之外的错误..请稍后再试或联系管理员....."
|
||||
|
||||
|
||||
async def _get_live_status(id_: int) -> Optional[str]:
|
||||
"""
|
||||
获取直播订阅状态
|
||||
:param id_: 直播间 id
|
||||
"""
|
||||
live = LiveRoom(id_)
|
||||
live_info = (await live.get_room_info())["room_info"]
|
||||
title = live_info["title"]
|
||||
room_id = live_info["room_id"]
|
||||
live_status = live_info["live_status"]
|
||||
cover = live_info["cover"]
|
||||
sub = await BilibiliSub.get_sub(id_)
|
||||
if sub.live_status != live_status:
|
||||
await BilibiliSub.update_sub_info(id_, live_status=live_status)
|
||||
if sub.live_status == 0 and live_status == 1:
|
||||
return (
|
||||
f"{image(cover)}\n"
|
||||
f"{sub.uname} 开播啦!\n"
|
||||
f"标题:{title}\n"
|
||||
f"直链:https://live.bilibili.com/{room_id}"
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
async def _get_up_status(id_: int) -> Optional[str]:
|
||||
"""
|
||||
获取用户投稿状态
|
||||
:param id_: 用户 id
|
||||
:return:
|
||||
"""
|
||||
_user = await BilibiliSub.get_sub(id_)
|
||||
u = user.User(_user.uid)
|
||||
user_info = await u.get_user_info()
|
||||
uname = user_info["name"]
|
||||
video_info = await u.get_videos()
|
||||
latest_video_created = 0
|
||||
video = None
|
||||
if _user.uname != uname:
|
||||
await BilibiliSub.update_sub_info(id_, uname=uname)
|
||||
dynamic_img, dynamic_upload_time = await get_user_dynamic(u, _user)
|
||||
if video_info["list"].get("vlist"):
|
||||
video = video_info["list"]["vlist"][0]
|
||||
latest_video_created = video["created"]
|
||||
rst = ""
|
||||
if dynamic_img:
|
||||
await BilibiliSub.update_sub_info(id_, dynamic_upload_time=dynamic_upload_time)
|
||||
rst += f"{uname} 发布了动态!\n" f"{dynamic_img}\n"
|
||||
if _user.latest_video_created != latest_video_created and video:
|
||||
rst = rst + "-------------\n" if rst else rst
|
||||
await BilibiliSub.update_sub_info(
|
||||
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 = None if rst == "-------------\n" else rst
|
||||
return rst
|
||||
|
||||
|
||||
async def _get_season_status(id_) -> Optional[str]:
|
||||
"""
|
||||
获取 番剧 更新状态
|
||||
:param id_: 番剧 id
|
||||
"""
|
||||
season_info = await bangumi.get_meta(id_)
|
||||
title = season_info["media"]["title"]
|
||||
_idx = (await BilibiliSub.get_sub(id_)).season_current_episode
|
||||
new_ep = season_info["media"]["new_ep"]["index"]
|
||||
if new_ep != _idx:
|
||||
await BilibiliSub.update_sub_info(
|
||||
id_, season_current_episode=new_ep, season_update_time=datetime.now()
|
||||
)
|
||||
return (
|
||||
f'{image(season_info["media"]["cover"])}\n'
|
||||
f"[{title}]更新啦\n"
|
||||
f"最新集数:{new_ep}"
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
async def get_user_dynamic(
|
||||
u: User, local_user: BilibiliSub
|
||||
) -> "Optional[MessageSegment], int":
|
||||
"""
|
||||
获取用户动态
|
||||
:param u: 用户类
|
||||
:param local_user: 数据库存储的用户数据
|
||||
:return: 最新动态截图与时间
|
||||
"""
|
||||
dynamic_info = await u.get_dynamics(0)
|
||||
browser = await get_browser()
|
||||
if dynamic_info.get("cards") and browser:
|
||||
dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"]
|
||||
if local_user.dynamic_upload_time != dynamic_upload_time:
|
||||
page = await browser.new_page()
|
||||
await page.goto(
|
||||
f"https://space.bilibili.com/{local_user.uid}/dynamic",
|
||||
wait_until="networkidle",
|
||||
timeout=10000,
|
||||
)
|
||||
await page.set_viewport_size({"width": 2560, "height": 1080})
|
||||
# 删除置顶
|
||||
await page.evaluate(
|
||||
"""
|
||||
xs = document.getElementsByClassName('first-card-with-title');
|
||||
for (x of xs) {
|
||||
x.remove();
|
||||
}
|
||||
"""
|
||||
)
|
||||
card = await page.query_selector(".card")
|
||||
# 截图并保存
|
||||
await card.screenshot(
|
||||
path=dynamic_path / f"{local_user.sub_id}_{dynamic_upload_time}.jpg",
|
||||
timeout=100000,
|
||||
)
|
||||
await page.close()
|
||||
return (
|
||||
image(
|
||||
f"{local_user.sub_id}_{dynamic_upload_time}.jpg",
|
||||
"bilibili_sub/dynamic",
|
||||
),
|
||||
dynamic_upload_time,
|
||||
)
|
||||
return None, None
|
||||
|
||||
|
||||
class SubManager:
|
||||
def __init__(self):
|
||||
self.live_data = []
|
||||
self.up_data = []
|
||||
self.season_data = []
|
||||
self.current_index = -1
|
||||
|
||||
async def reload_sub_data(self):
|
||||
"""
|
||||
重载数据
|
||||
"""
|
||||
if not self.live_data or not self.up_data or not self.season_data:
|
||||
(
|
||||
_live_data,
|
||||
_up_data,
|
||||
_season_data,
|
||||
) = await BilibiliSub.get_all_sub_data()
|
||||
if not self.live_data:
|
||||
self.live_data = _live_data
|
||||
if not self.up_data:
|
||||
self.up_data = _up_data
|
||||
if not self.season_data:
|
||||
self.season_data = _season_data
|
||||
|
||||
async def random_sub_data(self) -> Optional[BilibiliSub]:
|
||||
"""
|
||||
随机获取一条数据
|
||||
:return:
|
||||
"""
|
||||
sub = None
|
||||
if not self.live_data and not self.up_data and not self.season_data:
|
||||
return sub
|
||||
self.current_index += 1
|
||||
if self.current_index == 0:
|
||||
if self.live_data:
|
||||
sub = random.choice(self.live_data)
|
||||
self.live_data.remove(sub)
|
||||
elif self.current_index == 1:
|
||||
if self.up_data:
|
||||
sub = random.choice(self.up_data)
|
||||
self.up_data.remove(sub)
|
||||
elif self.current_index == 2:
|
||||
if self.season_data:
|
||||
sub = random.choice(self.season_data)
|
||||
self.season_data.remove(sub)
|
||||
else:
|
||||
self.current_index = -1
|
||||
if sub:
|
||||
return sub
|
||||
await self.reload_sub_data()
|
||||
return await self.random_sub_data()
|
||||
from bilibili_api.exceptions.ResponseCodeException import ResponseCodeException
|
||||
from utils.manager import resources_manager
|
||||
from asyncio.exceptions import TimeoutError
|
||||
from .model import BilibiliSub
|
||||
from bilibili_api.live import LiveRoom
|
||||
from bilibili_api import bangumi
|
||||
from utils.message_builder import image
|
||||
from bilibili_api.user import User
|
||||
from bilibili_api import user
|
||||
from typing import Optional
|
||||
from pathlib import Path
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from datetime import datetime
|
||||
from utils.browser import get_browser
|
||||
from services.db_context import db
|
||||
from services.log import logger
|
||||
from utils.http_utils import AsyncHttpx
|
||||
import random
|
||||
|
||||
|
||||
bilibili_search_url = "https://api.bilibili.com/x/web-interface/search/all/v2"
|
||||
|
||||
dynamic_path = Path(IMAGE_PATH) / "bilibili_sub" / "dynamic"
|
||||
dynamic_path.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
|
||||
resources_manager.add_temp_dir(dynamic_path)
|
||||
|
||||
|
||||
async def add_live_sub(live_id: int, sub_user: str) -> str:
|
||||
"""
|
||||
添加直播订阅
|
||||
:param live_id: 直播房间号
|
||||
:param sub_user: 订阅用户 id # 7384933:private or 7384933:2342344(group)
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
async with db.transaction():
|
||||
try:
|
||||
live = LiveRoom(live_id)
|
||||
live_info = (await live.get_room_info())["room_info"]
|
||||
except ResponseCodeException:
|
||||
return f"未找到房间号Id:{live_id} 的信息,请检查Id是否正确"
|
||||
uid = live_info["uid"]
|
||||
room_id = live_info["room_id"]
|
||||
short_id = live_info["short_id"]
|
||||
title = live_info["title"]
|
||||
live_status = live_info["live_status"]
|
||||
if await BilibiliSub.add_bilibili_sub(
|
||||
room_id,
|
||||
"live",
|
||||
sub_user,
|
||||
uid=uid,
|
||||
live_short_id=short_id,
|
||||
live_status=live_status,
|
||||
):
|
||||
await _get_up_status(live_id)
|
||||
uname = (await BilibiliSub.get_sub(live_id)).uname
|
||||
return (
|
||||
"已成功订阅主播:\n"
|
||||
f"\ttitle:{title}\n"
|
||||
f"\tname: {uname}\n"
|
||||
f"\tlive_id:{live_id}\n"
|
||||
f"\tuid:{uid}"
|
||||
)
|
||||
else:
|
||||
return "添加订阅失败..."
|
||||
except Exception as e:
|
||||
logger.error(f"订阅主播live_id:{live_id} 发生了错误 {type(e)}:{e}")
|
||||
return "添加订阅失败..."
|
||||
|
||||
|
||||
async def add_up_sub(uid: int, sub_user: str) -> str:
|
||||
"""
|
||||
添加订阅 UP
|
||||
:param uid: UP uid
|
||||
:param sub_user: 订阅用户
|
||||
"""
|
||||
try:
|
||||
async with db.transaction():
|
||||
try:
|
||||
u = user.User(uid)
|
||||
user_info = await u.get_user_info()
|
||||
except ResponseCodeException:
|
||||
return f"未找到UpId:{uid} 的信息,请检查Id是否正确"
|
||||
uname = user_info["name"]
|
||||
dynamic_info = await u.get_dynamics(0)
|
||||
dynamic_upload_time = 0
|
||||
if dynamic_info.get("cards"):
|
||||
dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"]
|
||||
video_info = await u.get_videos()
|
||||
latest_video_created = 0
|
||||
if video_info["list"].get("vlist"):
|
||||
latest_video_created = video_info["list"]["vlist"][0]["created"]
|
||||
if await BilibiliSub.add_bilibili_sub(
|
||||
uid,
|
||||
"up",
|
||||
sub_user,
|
||||
uid=uid,
|
||||
uname=uname,
|
||||
dynamic_upload_time=dynamic_upload_time,
|
||||
latest_video_created=latest_video_created,
|
||||
):
|
||||
return "已成功订阅UP:\n" f"\tname: {uname}\n" f"\tuid:{uid}"
|
||||
else:
|
||||
return "添加订阅失败..."
|
||||
except Exception as e:
|
||||
logger.error(f"订阅Up uid:{uid} 发生了错误 {type(e)}:{e}")
|
||||
return "添加订阅失败..."
|
||||
|
||||
|
||||
async def add_season_sub(media_id: int, sub_user: str) -> str:
|
||||
"""
|
||||
添加订阅 UP
|
||||
:param media_id: 番剧 media_id
|
||||
:param sub_user: 订阅用户
|
||||
"""
|
||||
try:
|
||||
async with db.transaction():
|
||||
try:
|
||||
season_info = await bangumi.get_meta(media_id)
|
||||
except ResponseCodeException:
|
||||
return f"未找到media_id:{media_id} 的信息,请检查Id是否正确"
|
||||
season_id = season_info["media"]["season_id"]
|
||||
season_current_episode = season_info["media"]["new_ep"]["index"]
|
||||
season_name = season_info["media"]["title"]
|
||||
if await BilibiliSub.add_bilibili_sub(
|
||||
media_id,
|
||||
"season",
|
||||
sub_user,
|
||||
season_name=season_name,
|
||||
season_id=season_id,
|
||||
season_current_episode=season_current_episode,
|
||||
):
|
||||
return (
|
||||
"已成功订阅番剧:\n"
|
||||
f"\ttitle: {season_name}\n"
|
||||
f"\tcurrent_episode: {season_current_episode}"
|
||||
)
|
||||
else:
|
||||
return "添加订阅失败..."
|
||||
except Exception as e:
|
||||
logger.error(f"订阅番剧 media_id:{media_id} 发生了错误 {type(e)}:{e}")
|
||||
return "添加订阅失败..."
|
||||
|
||||
|
||||
async def delete_sub(sub_id: str, sub_user: str) -> str:
|
||||
"""
|
||||
删除订阅
|
||||
:param sub_id: 订阅 id
|
||||
:param sub_user: 订阅用户 id # 7384933:private or 7384933:2342344(group)
|
||||
"""
|
||||
if await BilibiliSub.delete_bilibili_sub(int(sub_id), sub_user):
|
||||
return f"已成功取消订阅:{sub_id}"
|
||||
else:
|
||||
return f"取消订阅:{sub_id} 失败,请检查是否订阅过该Id...."
|
||||
|
||||
|
||||
async def get_media_id(keyword: str) -> dict:
|
||||
"""
|
||||
获取番剧的 media_id
|
||||
:param keyword: 番剧名称
|
||||
"""
|
||||
params = {"keyword": keyword}
|
||||
for _ in range(3):
|
||||
try:
|
||||
_season_data = {}
|
||||
response = await AsyncHttpx.get(bilibili_search_url, params=params, timeout=5)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
if data.get("data"):
|
||||
for item in data["data"]["result"]:
|
||||
if item["result_type"] == "media_bangumi":
|
||||
idx = 0
|
||||
for x in item["data"]:
|
||||
_season_data[idx] = {
|
||||
"media_id": x["media_id"],
|
||||
"title": x["title"]
|
||||
.replace('<em class="keyword">', "")
|
||||
.replace("</em>", ""),
|
||||
}
|
||||
idx += 1
|
||||
return _season_data
|
||||
except TimeoutError:
|
||||
pass
|
||||
return {}
|
||||
|
||||
|
||||
async def get_sub_status(id_: int, sub_type: str) -> Optional[str]:
|
||||
"""
|
||||
获取订阅状态
|
||||
:param id_: 订阅 id
|
||||
:param sub_type: 订阅类型
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
if sub_type == "live":
|
||||
return await _get_live_status(id_)
|
||||
elif sub_type == "up":
|
||||
return await _get_up_status(id_)
|
||||
elif sub_type == "season":
|
||||
return await _get_season_status(id_)
|
||||
except ResponseCodeException:
|
||||
return "获取信息失败...请检查订阅Id是否存在或稍后再试..."
|
||||
# except Exception as e:
|
||||
# logger.error(f"获取订阅状态发生预料之外的错误 id_:{id_} {type(e)}:{e}")
|
||||
# return "发生了预料之外的错误..请稍后再试或联系管理员....."
|
||||
|
||||
|
||||
async def _get_live_status(id_: int) -> Optional[str]:
|
||||
"""
|
||||
获取直播订阅状态
|
||||
:param id_: 直播间 id
|
||||
"""
|
||||
live = LiveRoom(id_)
|
||||
live_info = (await live.get_room_info())["room_info"]
|
||||
title = live_info["title"]
|
||||
room_id = live_info["room_id"]
|
||||
live_status = live_info["live_status"]
|
||||
cover = live_info["cover"]
|
||||
sub = await BilibiliSub.get_sub(id_)
|
||||
if sub.live_status != live_status:
|
||||
await BilibiliSub.update_sub_info(id_, live_status=live_status)
|
||||
if sub.live_status == 0 and live_status == 1:
|
||||
return (
|
||||
f"{image(cover)}\n"
|
||||
f"{sub.uname} 开播啦!\n"
|
||||
f"标题:{title}\n"
|
||||
f"直链:https://live.bilibili.com/{room_id}"
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
async def _get_up_status(id_: int) -> Optional[str]:
|
||||
"""
|
||||
获取用户投稿状态
|
||||
:param id_: 用户 id
|
||||
:return:
|
||||
"""
|
||||
_user = await BilibiliSub.get_sub(id_)
|
||||
u = user.User(_user.uid)
|
||||
user_info = await u.get_user_info()
|
||||
uname = user_info["name"]
|
||||
video_info = await u.get_videos()
|
||||
latest_video_created = 0
|
||||
video = None
|
||||
if _user.uname != uname:
|
||||
await BilibiliSub.update_sub_info(id_, uname=uname)
|
||||
dynamic_img, dynamic_upload_time = await get_user_dynamic(u, _user)
|
||||
if video_info["list"].get("vlist"):
|
||||
video = video_info["list"]["vlist"][0]
|
||||
latest_video_created = video["created"]
|
||||
rst = ""
|
||||
if dynamic_img:
|
||||
await BilibiliSub.update_sub_info(id_, dynamic_upload_time=dynamic_upload_time)
|
||||
rst += f"{uname} 发布了动态!\n" f"{dynamic_img}\n"
|
||||
if _user.latest_video_created != latest_video_created and video:
|
||||
rst = rst + "-------------\n" if rst else rst
|
||||
await BilibiliSub.update_sub_info(
|
||||
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 = None if rst == "-------------\n" else rst
|
||||
return rst
|
||||
|
||||
|
||||
async def _get_season_status(id_) -> Optional[str]:
|
||||
"""
|
||||
获取 番剧 更新状态
|
||||
:param id_: 番剧 id
|
||||
"""
|
||||
season_info = await bangumi.get_meta(id_)
|
||||
title = season_info["media"]["title"]
|
||||
_idx = (await BilibiliSub.get_sub(id_)).season_current_episode
|
||||
new_ep = season_info["media"]["new_ep"]["index"]
|
||||
if new_ep != _idx:
|
||||
await BilibiliSub.update_sub_info(
|
||||
id_, season_current_episode=new_ep, season_update_time=datetime.now()
|
||||
)
|
||||
return (
|
||||
f'{image(season_info["media"]["cover"])}\n'
|
||||
f"[{title}]更新啦\n"
|
||||
f"最新集数:{new_ep}"
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
async def get_user_dynamic(
|
||||
u: User, local_user: BilibiliSub
|
||||
) -> "Optional[MessageSegment], int":
|
||||
"""
|
||||
获取用户动态
|
||||
:param u: 用户类
|
||||
:param local_user: 数据库存储的用户数据
|
||||
:return: 最新动态截图与时间
|
||||
"""
|
||||
dynamic_info = await u.get_dynamics(0)
|
||||
browser = await get_browser()
|
||||
if dynamic_info.get("cards") and browser:
|
||||
dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"]
|
||||
if local_user.dynamic_upload_time != dynamic_upload_time:
|
||||
page = await browser.new_page()
|
||||
await page.goto(
|
||||
f"https://space.bilibili.com/{local_user.uid}/dynamic",
|
||||
wait_until="networkidle",
|
||||
timeout=10000,
|
||||
)
|
||||
await page.set_viewport_size({"width": 2560, "height": 1080})
|
||||
# 删除置顶
|
||||
await page.evaluate(
|
||||
"""
|
||||
xs = document.getElementsByClassName('first-card-with-title');
|
||||
for (x of xs) {
|
||||
x.remove();
|
||||
}
|
||||
"""
|
||||
)
|
||||
card = await page.query_selector(".card")
|
||||
# 截图并保存
|
||||
await card.screenshot(
|
||||
path=dynamic_path / f"{local_user.sub_id}_{dynamic_upload_time}.jpg",
|
||||
timeout=100000,
|
||||
)
|
||||
await page.close()
|
||||
return (
|
||||
image(
|
||||
f"{local_user.sub_id}_{dynamic_upload_time}.jpg",
|
||||
"bilibili_sub/dynamic",
|
||||
),
|
||||
dynamic_upload_time,
|
||||
)
|
||||
return None, None
|
||||
|
||||
|
||||
class SubManager:
|
||||
def __init__(self):
|
||||
self.live_data = []
|
||||
self.up_data = []
|
||||
self.season_data = []
|
||||
self.current_index = -1
|
||||
|
||||
async def reload_sub_data(self):
|
||||
"""
|
||||
重载数据
|
||||
"""
|
||||
if not self.live_data or not self.up_data or not self.season_data:
|
||||
(
|
||||
_live_data,
|
||||
_up_data,
|
||||
_season_data,
|
||||
) = await BilibiliSub.get_all_sub_data()
|
||||
if not self.live_data:
|
||||
self.live_data = _live_data
|
||||
if not self.up_data:
|
||||
self.up_data = _up_data
|
||||
if not self.season_data:
|
||||
self.season_data = _season_data
|
||||
|
||||
async def random_sub_data(self) -> Optional[BilibiliSub]:
|
||||
"""
|
||||
随机获取一条数据
|
||||
:return:
|
||||
"""
|
||||
sub = None
|
||||
if not self.live_data and not self.up_data and not self.season_data:
|
||||
return sub
|
||||
self.current_index += 1
|
||||
if self.current_index == 0:
|
||||
if self.live_data:
|
||||
sub = random.choice(self.live_data)
|
||||
self.live_data.remove(sub)
|
||||
elif self.current_index == 1:
|
||||
if self.up_data:
|
||||
sub = random.choice(self.up_data)
|
||||
self.up_data.remove(sub)
|
||||
elif self.current_index == 2:
|
||||
if self.season_data:
|
||||
sub = random.choice(self.season_data)
|
||||
self.season_data.remove(sub)
|
||||
else:
|
||||
self.current_index = -1
|
||||
if sub:
|
||||
return sub
|
||||
await self.reload_sub_data()
|
||||
return await self.random_sub_data()
|
||||
|
||||
Regular → Executable
+249
-249
@@ -1,249 +1,249 @@
|
||||
from services.log import logger
|
||||
from services.db_context import db
|
||||
from datetime import datetime
|
||||
from typing import Optional, List
|
||||
|
||||
|
||||
class BilibiliSub(db.Model):
|
||||
__tablename__ = "bilibili_sub"
|
||||
|
||||
id = db.Column(db.Integer(), primary_key=True)
|
||||
sub_id = db.Column(db.Integer(), nullable=False)
|
||||
sub_type = db.Column(db.String(), nullable=False)
|
||||
# 订阅用户
|
||||
sub_users = db.Column(db.String(), nullable=False)
|
||||
# 直播
|
||||
live_short_id = db.Column(db.Integer())
|
||||
live_status = db.Column(db.Integer)
|
||||
# 主播/UP
|
||||
uid = db.Column(db.BigInteger())
|
||||
uname = db.Column(db.String())
|
||||
latest_video_created = db.Column(db.BigInteger()) # 视频上传时间
|
||||
dynamic_upload_time = db.Column(db.BigInteger(), default=0) # 动态发布时间
|
||||
# 番剧
|
||||
season_name = db.Column(db.String())
|
||||
season_id = db.Column(db.Integer())
|
||||
season_current_episode = db.Column(db.String())
|
||||
season_update_time = db.Column(db.DateTime())
|
||||
|
||||
_idx1 = db.Index("bilibili_sub_idx1", "sub_id", "sub_type", unique=True)
|
||||
|
||||
@classmethod
|
||||
async def add_bilibili_sub(
|
||||
cls,
|
||||
sub_id: int,
|
||||
sub_type: str,
|
||||
sub_user: str,
|
||||
*,
|
||||
live_short_id: Optional[int] = None,
|
||||
live_status: Optional[int] = None,
|
||||
dynamic_upload_time: Optional[int] = None,
|
||||
uid: Optional[int] = None,
|
||||
uname: Optional[str] = None,
|
||||
latest_video_created: Optional[int] = None,
|
||||
season_name: Optional[str] = None,
|
||||
season_id: Optional[int] = None,
|
||||
season_current_episode: Optional[str] = None,
|
||||
season_update_time: Optional[datetime] = None,
|
||||
) -> bool:
|
||||
"""
|
||||
说明:
|
||||
添加订阅
|
||||
参数:
|
||||
:param sub_id: 订阅名称,房间号,番剧号等
|
||||
:param sub_type: 订阅类型
|
||||
:param sub_user: 订阅此条目的用户
|
||||
:param live_short_id: 直接短 id
|
||||
:param live_status: 主播开播状态
|
||||
:param dynamic_upload_time: 主播/UP最新动态时间
|
||||
:param uid: 主播/UP uid
|
||||
:param uname: 用户名称
|
||||
:param latest_video_created: 最新视频上传时间
|
||||
:param season_name: 番剧名称
|
||||
:param season_id: 番剧 season_id
|
||||
:param season_current_episode: 番剧最新集数
|
||||
:param season_update_time: 番剧更新时间
|
||||
"""
|
||||
try:
|
||||
async with db.transaction():
|
||||
query = (
|
||||
await cls.query.where(cls.sub_id == sub_id)
|
||||
.with_for_update()
|
||||
.gino.first()
|
||||
)
|
||||
sub_user = sub_user if sub_user[-1] == "," else f"{sub_user},"
|
||||
if query:
|
||||
if sub_user not in query.sub_users:
|
||||
sub_users = query.sub_users + sub_user
|
||||
await query.update(sub_users=sub_users).apply()
|
||||
else:
|
||||
sub = await cls.create(
|
||||
sub_id=sub_id, sub_type=sub_type, sub_users=sub_user
|
||||
)
|
||||
await sub.update(
|
||||
live_short_id=live_short_id
|
||||
if live_short_id
|
||||
else sub.live_short_id,
|
||||
live_status=live_status if live_status else sub.live_status,
|
||||
dynamic_upload_time=dynamic_upload_time
|
||||
if dynamic_upload_time
|
||||
else sub.dynamic_upload_time,
|
||||
uid=uid if uid else sub.uid,
|
||||
uname=uname if uname else sub.uname,
|
||||
latest_video_created=latest_video_created
|
||||
if latest_video_created
|
||||
else sub.latest_video_created,
|
||||
season_update_time=season_update_time
|
||||
if season_update_time
|
||||
else sub.season_update_time,
|
||||
season_current_episode=season_current_episode
|
||||
if season_current_episode
|
||||
else sub.season_current_episode,
|
||||
season_id=season_id if season_id else sub.season_id,
|
||||
season_name=season_name if season_name else sub.season_name,
|
||||
).apply()
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.info(f"bilibili_sub 添加订阅错误 {type(e)}: {e}")
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def delete_bilibili_sub(cls, sub_id: int, sub_user: str) -> bool:
|
||||
"""
|
||||
说明:
|
||||
删除订阅
|
||||
参数:
|
||||
:param sub_id: 订阅名称
|
||||
:param sub_user: 删除此条目的用户
|
||||
"""
|
||||
try:
|
||||
async with db.transaction():
|
||||
query = (
|
||||
await cls.query.where(
|
||||
(cls.sub_id == sub_id) & (cls.sub_users.contains(sub_user))
|
||||
)
|
||||
.with_for_update()
|
||||
.gino.first()
|
||||
)
|
||||
if not query:
|
||||
return False
|
||||
await query.update(
|
||||
sub_users=query.sub_users.replace(f"{sub_user},", "")
|
||||
).apply()
|
||||
if not query.sub_users.strip():
|
||||
await query.delete()
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.info(f"bilibili_sub 删除订阅错误 {type(e)}: {e}")
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def get_sub(cls, sub_id: int) -> Optional["BilibiliSub"]:
|
||||
"""
|
||||
说明:
|
||||
获取订阅对象
|
||||
参数:
|
||||
:param sub_id: 订阅 id
|
||||
"""
|
||||
return await cls.query.where(cls.sub_id == sub_id).gino.first()
|
||||
|
||||
@classmethod
|
||||
async def get_sub_data(cls, id_: str) -> List["BilibiliSub"]:
|
||||
"""
|
||||
获取 id_ 订阅的所有内容
|
||||
:param id_: id
|
||||
"""
|
||||
query = cls.query.where(cls.sub_users.contains(id_))
|
||||
return await query.gino.all()
|
||||
|
||||
@classmethod
|
||||
async def update_sub_info(
|
||||
cls,
|
||||
sub_id: int,
|
||||
*,
|
||||
live_short_id: Optional[int] = None,
|
||||
live_status: Optional[int] = None,
|
||||
dynamic_upload_time: Optional[int] = None,
|
||||
uid: Optional[int] = None,
|
||||
uname: Optional[str] = None,
|
||||
latest_video_created: Optional[int] = None,
|
||||
season_name: Optional[str] = None,
|
||||
season_id: Optional[int] = None,
|
||||
season_current_episode: Optional[str] = None,
|
||||
season_update_time: Optional[datetime] = None,
|
||||
) -> bool:
|
||||
"""
|
||||
说明:
|
||||
更新订阅信息
|
||||
参数:
|
||||
:param sub_id: 订阅名称,房间号,番剧号等
|
||||
:param live_short_id: 直接短 id
|
||||
:param live_status: 主播开播状态
|
||||
:param dynamic_upload_time: 主播/UP最新动态时间
|
||||
:param uid: 主播/UP uid
|
||||
:param uname: 用户名称
|
||||
:param latest_video_created: 最新视频上传时间
|
||||
:param season_name: 番剧名称
|
||||
:param season_id: 番剧 season_id
|
||||
:param season_current_episode: 番剧最新集数
|
||||
:param season_update_time: 番剧更新时间
|
||||
"""
|
||||
try:
|
||||
async with db.transaction():
|
||||
sub = (
|
||||
await cls.query.where(cls.sub_id == sub_id)
|
||||
.with_for_update()
|
||||
.gino.first()
|
||||
)
|
||||
if sub:
|
||||
await sub.update(
|
||||
live_short_id=live_short_id
|
||||
if live_short_id is not None
|
||||
else sub.live_short_id,
|
||||
live_status=live_status
|
||||
if live_status is not None
|
||||
else sub.live_status,
|
||||
dynamic_upload_time=dynamic_upload_time
|
||||
if dynamic_upload_time is not None
|
||||
else sub.dynamic_upload_time,
|
||||
uid=uid if uid is not None else sub.uid,
|
||||
uname=uname if uname is not None else sub.uname,
|
||||
latest_video_created=latest_video_created
|
||||
if latest_video_created is not None
|
||||
else sub.latest_video_created,
|
||||
season_update_time=season_update_time
|
||||
if season_update_time is not None
|
||||
else sub.season_update_time,
|
||||
season_current_episode=season_current_episode
|
||||
if season_current_episode is not None
|
||||
else sub.season_current_episode,
|
||||
season_id=season_id if season_id is not None else sub.season_id,
|
||||
season_name=season_name
|
||||
if season_name is not None
|
||||
else sub.season_name,
|
||||
).apply()
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.info(f"bilibili_sub 更新订阅错误 {type(e)}: {e}")
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def get_all_sub_data(
|
||||
cls,
|
||||
) -> "List[BilibiliSub], List[BilibiliSub], List[BilibiliSub]":
|
||||
"""
|
||||
说明:
|
||||
分类获取所有数据
|
||||
"""
|
||||
live_data = []
|
||||
up_data = []
|
||||
season_data = []
|
||||
query = await cls.query.gino.all()
|
||||
for x in query:
|
||||
if x.sub_type == "live":
|
||||
live_data.append(x)
|
||||
if x.sub_type == "up":
|
||||
up_data.append(x)
|
||||
if x.sub_type == "season":
|
||||
season_data.append(x)
|
||||
return live_data, up_data, season_data
|
||||
from services.log import logger
|
||||
from services.db_context import db
|
||||
from datetime import datetime
|
||||
from typing import Optional, List
|
||||
|
||||
|
||||
class BilibiliSub(db.Model):
|
||||
__tablename__ = "bilibili_sub"
|
||||
|
||||
id = db.Column(db.Integer(), primary_key=True)
|
||||
sub_id = db.Column(db.Integer(), nullable=False)
|
||||
sub_type = db.Column(db.String(), nullable=False)
|
||||
# 订阅用户
|
||||
sub_users = db.Column(db.String(), nullable=False)
|
||||
# 直播
|
||||
live_short_id = db.Column(db.Integer())
|
||||
live_status = db.Column(db.Integer)
|
||||
# 主播/UP
|
||||
uid = db.Column(db.BigInteger())
|
||||
uname = db.Column(db.String())
|
||||
latest_video_created = db.Column(db.BigInteger()) # 视频上传时间
|
||||
dynamic_upload_time = db.Column(db.BigInteger(), default=0) # 动态发布时间
|
||||
# 番剧
|
||||
season_name = db.Column(db.String())
|
||||
season_id = db.Column(db.Integer())
|
||||
season_current_episode = db.Column(db.String())
|
||||
season_update_time = db.Column(db.DateTime())
|
||||
|
||||
_idx1 = db.Index("bilibili_sub_idx1", "sub_id", "sub_type", unique=True)
|
||||
|
||||
@classmethod
|
||||
async def add_bilibili_sub(
|
||||
cls,
|
||||
sub_id: int,
|
||||
sub_type: str,
|
||||
sub_user: str,
|
||||
*,
|
||||
live_short_id: Optional[int] = None,
|
||||
live_status: Optional[int] = None,
|
||||
dynamic_upload_time: Optional[int] = None,
|
||||
uid: Optional[int] = None,
|
||||
uname: Optional[str] = None,
|
||||
latest_video_created: Optional[int] = None,
|
||||
season_name: Optional[str] = None,
|
||||
season_id: Optional[int] = None,
|
||||
season_current_episode: Optional[str] = None,
|
||||
season_update_time: Optional[datetime] = None,
|
||||
) -> bool:
|
||||
"""
|
||||
说明:
|
||||
添加订阅
|
||||
参数:
|
||||
:param sub_id: 订阅名称,房间号,番剧号等
|
||||
:param sub_type: 订阅类型
|
||||
:param sub_user: 订阅此条目的用户
|
||||
:param live_short_id: 直接短 id
|
||||
:param live_status: 主播开播状态
|
||||
:param dynamic_upload_time: 主播/UP最新动态时间
|
||||
:param uid: 主播/UP uid
|
||||
:param uname: 用户名称
|
||||
:param latest_video_created: 最新视频上传时间
|
||||
:param season_name: 番剧名称
|
||||
:param season_id: 番剧 season_id
|
||||
:param season_current_episode: 番剧最新集数
|
||||
:param season_update_time: 番剧更新时间
|
||||
"""
|
||||
try:
|
||||
async with db.transaction():
|
||||
query = (
|
||||
await cls.query.where(cls.sub_id == sub_id)
|
||||
.with_for_update()
|
||||
.gino.first()
|
||||
)
|
||||
sub_user = sub_user if sub_user[-1] == "," else f"{sub_user},"
|
||||
if query:
|
||||
if sub_user not in query.sub_users:
|
||||
sub_users = query.sub_users + sub_user
|
||||
await query.update(sub_users=sub_users).apply()
|
||||
else:
|
||||
sub = await cls.create(
|
||||
sub_id=sub_id, sub_type=sub_type, sub_users=sub_user
|
||||
)
|
||||
await sub.update(
|
||||
live_short_id=live_short_id
|
||||
if live_short_id
|
||||
else sub.live_short_id,
|
||||
live_status=live_status if live_status else sub.live_status,
|
||||
dynamic_upload_time=dynamic_upload_time
|
||||
if dynamic_upload_time
|
||||
else sub.dynamic_upload_time,
|
||||
uid=uid if uid else sub.uid,
|
||||
uname=uname if uname else sub.uname,
|
||||
latest_video_created=latest_video_created
|
||||
if latest_video_created
|
||||
else sub.latest_video_created,
|
||||
season_update_time=season_update_time
|
||||
if season_update_time
|
||||
else sub.season_update_time,
|
||||
season_current_episode=season_current_episode
|
||||
if season_current_episode
|
||||
else sub.season_current_episode,
|
||||
season_id=season_id if season_id else sub.season_id,
|
||||
season_name=season_name if season_name else sub.season_name,
|
||||
).apply()
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.info(f"bilibili_sub 添加订阅错误 {type(e)}: {e}")
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def delete_bilibili_sub(cls, sub_id: int, sub_user: str) -> bool:
|
||||
"""
|
||||
说明:
|
||||
删除订阅
|
||||
参数:
|
||||
:param sub_id: 订阅名称
|
||||
:param sub_user: 删除此条目的用户
|
||||
"""
|
||||
try:
|
||||
async with db.transaction():
|
||||
query = (
|
||||
await cls.query.where(
|
||||
(cls.sub_id == sub_id) & (cls.sub_users.contains(sub_user))
|
||||
)
|
||||
.with_for_update()
|
||||
.gino.first()
|
||||
)
|
||||
if not query:
|
||||
return False
|
||||
await query.update(
|
||||
sub_users=query.sub_users.replace(f"{sub_user},", "")
|
||||
).apply()
|
||||
if not query.sub_users.strip():
|
||||
await query.delete()
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.info(f"bilibili_sub 删除订阅错误 {type(e)}: {e}")
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def get_sub(cls, sub_id: int) -> Optional["BilibiliSub"]:
|
||||
"""
|
||||
说明:
|
||||
获取订阅对象
|
||||
参数:
|
||||
:param sub_id: 订阅 id
|
||||
"""
|
||||
return await cls.query.where(cls.sub_id == sub_id).gino.first()
|
||||
|
||||
@classmethod
|
||||
async def get_sub_data(cls, id_: str) -> List["BilibiliSub"]:
|
||||
"""
|
||||
获取 id_ 订阅的所有内容
|
||||
:param id_: id
|
||||
"""
|
||||
query = cls.query.where(cls.sub_users.contains(id_))
|
||||
return await query.gino.all()
|
||||
|
||||
@classmethod
|
||||
async def update_sub_info(
|
||||
cls,
|
||||
sub_id: int,
|
||||
*,
|
||||
live_short_id: Optional[int] = None,
|
||||
live_status: Optional[int] = None,
|
||||
dynamic_upload_time: Optional[int] = None,
|
||||
uid: Optional[int] = None,
|
||||
uname: Optional[str] = None,
|
||||
latest_video_created: Optional[int] = None,
|
||||
season_name: Optional[str] = None,
|
||||
season_id: Optional[int] = None,
|
||||
season_current_episode: Optional[str] = None,
|
||||
season_update_time: Optional[datetime] = None,
|
||||
) -> bool:
|
||||
"""
|
||||
说明:
|
||||
更新订阅信息
|
||||
参数:
|
||||
:param sub_id: 订阅名称,房间号,番剧号等
|
||||
:param live_short_id: 直接短 id
|
||||
:param live_status: 主播开播状态
|
||||
:param dynamic_upload_time: 主播/UP最新动态时间
|
||||
:param uid: 主播/UP uid
|
||||
:param uname: 用户名称
|
||||
:param latest_video_created: 最新视频上传时间
|
||||
:param season_name: 番剧名称
|
||||
:param season_id: 番剧 season_id
|
||||
:param season_current_episode: 番剧最新集数
|
||||
:param season_update_time: 番剧更新时间
|
||||
"""
|
||||
try:
|
||||
async with db.transaction():
|
||||
sub = (
|
||||
await cls.query.where(cls.sub_id == sub_id)
|
||||
.with_for_update()
|
||||
.gino.first()
|
||||
)
|
||||
if sub:
|
||||
await sub.update(
|
||||
live_short_id=live_short_id
|
||||
if live_short_id is not None
|
||||
else sub.live_short_id,
|
||||
live_status=live_status
|
||||
if live_status is not None
|
||||
else sub.live_status,
|
||||
dynamic_upload_time=dynamic_upload_time
|
||||
if dynamic_upload_time is not None
|
||||
else sub.dynamic_upload_time,
|
||||
uid=uid if uid is not None else sub.uid,
|
||||
uname=uname if uname is not None else sub.uname,
|
||||
latest_video_created=latest_video_created
|
||||
if latest_video_created is not None
|
||||
else sub.latest_video_created,
|
||||
season_update_time=season_update_time
|
||||
if season_update_time is not None
|
||||
else sub.season_update_time,
|
||||
season_current_episode=season_current_episode
|
||||
if season_current_episode is not None
|
||||
else sub.season_current_episode,
|
||||
season_id=season_id if season_id is not None else sub.season_id,
|
||||
season_name=season_name
|
||||
if season_name is not None
|
||||
else sub.season_name,
|
||||
).apply()
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.info(f"bilibili_sub 更新订阅错误 {type(e)}: {e}")
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def get_all_sub_data(
|
||||
cls,
|
||||
) -> "List[BilibiliSub], List[BilibiliSub], List[BilibiliSub]":
|
||||
"""
|
||||
说明:
|
||||
分类获取所有数据
|
||||
"""
|
||||
live_data = []
|
||||
up_data = []
|
||||
season_data = []
|
||||
query = await cls.query.gino.all()
|
||||
for x in query:
|
||||
if x.sub_type == "live":
|
||||
live_data.append(x)
|
||||
if x.sub_type == "up":
|
||||
up_data.append(x)
|
||||
if x.sub_type == "season":
|
||||
season_data.append(x)
|
||||
return live_data, up_data, season_data
|
||||
|
||||
Regular → Executable
+71
-72
@@ -1,72 +1,71 @@
|
||||
from utils.image_utils import CreateImg
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from pathlib import Path
|
||||
from bilibili_api import user
|
||||
from io import BytesIO
|
||||
import aiohttp
|
||||
|
||||
|
||||
BORDER_PATH = Path(IMAGE_PATH) / 'border'
|
||||
BORDER_PATH.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
async def get_pic(url: str) -> bytes:
|
||||
"""
|
||||
获取图像
|
||||
:param url: 图像链接
|
||||
:return: 图像二进制
|
||||
"""
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(url, timeout=2) as response:
|
||||
return await response.read()
|
||||
|
||||
|
||||
async def create_live_des_image(uid: int, title: str, cover: str, tags: str, des: str):
|
||||
"""
|
||||
生成主播简介图片
|
||||
:param uid: 主播 uid
|
||||
:param title: 直播间标题
|
||||
:param cover: 直播封面
|
||||
:param tags: 直播标签
|
||||
:param des: 直播简介
|
||||
:return:
|
||||
"""
|
||||
u = user.User(uid)
|
||||
user_info = await u.get_user_info()
|
||||
name = user_info['name']
|
||||
sex = user_info['sex']
|
||||
face = user_info['face']
|
||||
sign = user_info['sign']
|
||||
ava = CreateImg(100, 100, background=BytesIO(await get_pic(face)))
|
||||
ava.circle()
|
||||
cover = CreateImg(470, 265, background=BytesIO(await get_pic(cover)))
|
||||
print()
|
||||
|
||||
|
||||
def _create_live_des_image(title: str, cover: CreateImg, tags: str, des: str, user_name: str, sex: str, sign: str, ava: CreateImg):
|
||||
"""
|
||||
生成主播简介图片
|
||||
:param title: 直播间标题
|
||||
:param cover: 直播封面
|
||||
:param tags: 直播标签
|
||||
:param des: 直播简介
|
||||
:param user_name: 主播名称
|
||||
:param sex: 主播性别
|
||||
:param sign: 主播签名
|
||||
:param ava: 主播头像
|
||||
:return:
|
||||
"""
|
||||
border = BORDER_PATH / '0.png'
|
||||
border_img = None
|
||||
if border.exists():
|
||||
border_img = CreateImg(1772, 2657, background=border)
|
||||
bk = CreateImg(1772, 2657, font_size=30)
|
||||
bk.paste(cover, (0, 100), center_type='by_width')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
from utils.image_utils import CreateImg
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from utils.http_utils import AsyncHttpx
|
||||
from pathlib import Path
|
||||
from bilibili_api import user
|
||||
from io import BytesIO
|
||||
|
||||
|
||||
BORDER_PATH = Path(IMAGE_PATH) / "border"
|
||||
BORDER_PATH.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
|
||||
async def get_pic(url: str) -> bytes:
|
||||
"""
|
||||
获取图像
|
||||
:param url: 图像链接
|
||||
:return: 图像二进制
|
||||
"""
|
||||
return (await AsyncHttpx.get(url, timeout=10)).content
|
||||
|
||||
|
||||
async def create_live_des_image(uid: int, title: str, cover: str, tags: str, des: str):
|
||||
"""
|
||||
生成主播简介图片
|
||||
:param uid: 主播 uid
|
||||
:param title: 直播间标题
|
||||
:param cover: 直播封面
|
||||
:param tags: 直播标签
|
||||
:param des: 直播简介
|
||||
:return:
|
||||
"""
|
||||
u = user.User(uid)
|
||||
user_info = await u.get_user_info()
|
||||
name = user_info["name"]
|
||||
sex = user_info["sex"]
|
||||
face = user_info["face"]
|
||||
sign = user_info["sign"]
|
||||
ava = CreateImg(100, 100, background=BytesIO(await get_pic(face)))
|
||||
ava.circle()
|
||||
cover = CreateImg(470, 265, background=BytesIO(await get_pic(cover)))
|
||||
print()
|
||||
|
||||
|
||||
def _create_live_des_image(
|
||||
title: str,
|
||||
cover: CreateImg,
|
||||
tags: str,
|
||||
des: str,
|
||||
user_name: str,
|
||||
sex: str,
|
||||
sign: str,
|
||||
ava: CreateImg,
|
||||
):
|
||||
"""
|
||||
生成主播简介图片
|
||||
:param title: 直播间标题
|
||||
:param cover: 直播封面
|
||||
:param tags: 直播标签
|
||||
:param des: 直播简介
|
||||
:param user_name: 主播名称
|
||||
:param sex: 主播性别
|
||||
:param sign: 主播签名
|
||||
:param ava: 主播头像
|
||||
:return:
|
||||
"""
|
||||
border = BORDER_PATH / "0.png"
|
||||
border_img = None
|
||||
if border.exists():
|
||||
border_img = CreateImg(1772, 2657, background=border)
|
||||
bk = CreateImg(1772, 2657, font_size=30)
|
||||
bk.paste(cover, (0, 100), center_type="by_width")
|
||||
|
||||
Reference in New Issue
Block a user