mirror of
https://github.com/suyiiyii/nonebot-bison.git
synced 2026-05-09 18:27:56 +08:00
开播提醒推送的图片改为使用直播间封面 (#249)
* ✨ 为bilibili直播添加下播提醒,添加直播分区信息 🚸 开播提醒推送的图片改为使用直播间封面 * ♻️ 使用Enum * 🐛 修复bilibili发送视频动态时不推送视频标题的问题 * 🎨 调整LiveAction的注释和jaccard函数代码位置 * 🚨 修改RawPost类型定义,优化bililive类型显示
This commit is contained in:
@@ -1,22 +1,22 @@
|
||||
import json
|
||||
import re
|
||||
from copy import deepcopy
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Any, Optional
|
||||
from enum import Enum, unique
|
||||
from typing import Any, Literal, Optional
|
||||
|
||||
from httpx import AsyncClient
|
||||
from nonebot.log import logger
|
||||
from pydantic import BaseModel, Field
|
||||
from typing_extensions import Self
|
||||
|
||||
from ..post import Post
|
||||
from ..types import ApiError, Category, RawPost, Tag, Target
|
||||
from ..utils import SchedulerConfig
|
||||
from ..utils import SchedulerConfig, jaccard_text_similarity
|
||||
from .platform import CategoryNotRecognize, CategoryNotSupport, NewMessage, StatusChange
|
||||
|
||||
|
||||
class BilibiliSchedConf(SchedulerConfig):
|
||||
|
||||
name = "bilibili.com"
|
||||
schedule_type = "interval"
|
||||
schedule_setting = {"seconds": 10}
|
||||
@@ -51,7 +51,6 @@ class BilibiliSchedConf(SchedulerConfig):
|
||||
|
||||
|
||||
class Bilibili(NewMessage):
|
||||
|
||||
categories = {
|
||||
1: "一般动态",
|
||||
2: "专栏文章",
|
||||
@@ -148,7 +147,25 @@ class Bilibili(NewMessage):
|
||||
pic = card["image_urls"]
|
||||
elif post_type == 3:
|
||||
# 视频
|
||||
text = card["dynamic"]
|
||||
dynamic = card.get("dynamic", "")
|
||||
title = card["title"]
|
||||
desc = card.get("desc", "")
|
||||
|
||||
if jaccard_text_similarity(desc, dynamic) > 0.8:
|
||||
# 如果视频简介和动态内容相似,就只保留长的那个
|
||||
if len(dynamic) > len(desc):
|
||||
text = f"{dynamic}\n=================\n{title}"
|
||||
else:
|
||||
text = f"{title}\n\n{desc}"
|
||||
else:
|
||||
# 否则就把两个拼起来
|
||||
text = f"""
|
||||
{dynamic}
|
||||
\n=================\n
|
||||
{title}\n\n
|
||||
{desc}
|
||||
"""
|
||||
|
||||
pic = [card["pic"]]
|
||||
elif post_type == 4:
|
||||
# 纯文字
|
||||
@@ -191,21 +208,16 @@ class Bilibili(NewMessage):
|
||||
text = card_content["item"]["content"]
|
||||
orig_type = card_content["item"]["orig_type"]
|
||||
orig = json.loads(card_content["origin"])
|
||||
orig_text, _ = self._get_info(self._do_get_category(orig_type), orig)
|
||||
orig_text, pic = self._get_info(self._do_get_category(orig_type), orig)
|
||||
text += "\n--------------\n"
|
||||
text += orig_text
|
||||
pic = []
|
||||
else:
|
||||
raise CategoryNotSupport(post_type)
|
||||
return Post("bilibili", text=text, url=url, pics=pic, target_name=target_name)
|
||||
|
||||
|
||||
class Bilibililive(StatusChange):
|
||||
# Author : Sichongzou
|
||||
# Date : 2022-5-18 8:54
|
||||
# Description : bilibili开播提醒
|
||||
# E-mail : 1557157806@qq.com
|
||||
categories = {1: "开播提醒", 2: "标题更新提醒"}
|
||||
categories = {1: "开播提醒", 2: "标题更新提醒", 3: "下播提醒"}
|
||||
platform_name = "bilibili-live"
|
||||
enable_tag = False
|
||||
enabled = True
|
||||
@@ -214,36 +226,64 @@ class Bilibililive(StatusChange):
|
||||
name = "Bilibili直播"
|
||||
has_target = True
|
||||
|
||||
@dataclass
|
||||
class Info:
|
||||
uname: str
|
||||
live_status: int
|
||||
room_id: str
|
||||
@unique
|
||||
class LiveStatus(Enum):
|
||||
# 直播状态
|
||||
# 0: 未开播
|
||||
# 1: 正在直播
|
||||
# 2: 轮播中
|
||||
OFF = 0
|
||||
ON = 1
|
||||
CYCLE = 2
|
||||
|
||||
@unique
|
||||
class LiveAction(Enum):
|
||||
# 当前直播行为,由新旧直播状态对比决定
|
||||
# on: 正在直播
|
||||
# off: 未开播
|
||||
# turn_on: 状态变更为正在直播
|
||||
# turn_off: 状态变更为未开播
|
||||
# title_update: 标题更新
|
||||
TURN_ON = "turn_on"
|
||||
TURN_OFF = "turn_off"
|
||||
ON = "on"
|
||||
OFF = "off"
|
||||
TITLE_UPDATE = "title_update"
|
||||
|
||||
class Info(BaseModel):
|
||||
title: str
|
||||
cover_from_user: str
|
||||
keyframe: str
|
||||
category: Category = field(default=Category(0))
|
||||
room_id: int # 直播间号
|
||||
uid: int # 主播uid
|
||||
live_time: int # 开播时间
|
||||
live_status: "Bilibililive.LiveStatus"
|
||||
area_name: str = Field(alias="area_v2_name") # 新版分区名
|
||||
uname: str # 主播名
|
||||
face: str # 头像url
|
||||
cover: str = Field(alias="cover_from_user") # 封面url
|
||||
keyframe: str # 关键帧url,可能会有延迟
|
||||
category: Category = Field(default=Category(0))
|
||||
|
||||
def __init__(self, raw_info: dict):
|
||||
self.__dict__.update(raw_info)
|
||||
|
||||
def is_live_turn_on(self, old_info: Self) -> bool:
|
||||
# 使用 & 判断直播开始
|
||||
# live_status:
|
||||
# 0:关播
|
||||
# 1:直播中
|
||||
# 2:轮播中
|
||||
if self.live_status == 1 and old_info.live_status != self.live_status:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def is_title_update(self, old_info: Self) -> bool:
|
||||
# 使用 ^ 判断直播时标题改变
|
||||
if self.live_status == 1 and old_info.title != self.title:
|
||||
return True
|
||||
|
||||
return False
|
||||
def get_live_action(self, old_info: Self) -> "Bilibililive.LiveAction":
|
||||
status = Bilibililive.LiveStatus
|
||||
action = Bilibililive.LiveAction
|
||||
if (
|
||||
old_info.live_status in [status.OFF, status.CYCLE]
|
||||
and self.live_status == status.ON
|
||||
):
|
||||
return action.TURN_ON
|
||||
elif old_info.live_status == status.ON and self.live_status in [
|
||||
status.OFF,
|
||||
status.CYCLE,
|
||||
]:
|
||||
return action.TURN_OFF
|
||||
elif old_info.live_status == status.ON and self.live_status == status.ON:
|
||||
if old_info.title != self.title:
|
||||
# 开播时通常会改标题,避免短时间推送两次
|
||||
return action.TITLE_UPDATE
|
||||
else:
|
||||
return action.ON
|
||||
else:
|
||||
return action.OFF
|
||||
|
||||
@classmethod
|
||||
async def get_target_name(
|
||||
@@ -259,47 +299,56 @@ class Bilibililive(StatusChange):
|
||||
|
||||
async def get_status(self, target: Target) -> Info:
|
||||
params = {"uids[]": target}
|
||||
# from https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/live/info.md#%E6%89%B9%E9%87%8F%E6%9F%A5%E8%AF%A2%E7%9B%B4%E6%92%AD%E9%97%B4%E7%8A%B6%E6%80%81
|
||||
# https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/live/info.md#批量查询直播间状态
|
||||
res = await self.client.get(
|
||||
"https://api.live.bilibili.com/room/v1/Room/get_status_info_by_uids",
|
||||
params=params,
|
||||
timeout=4.0,
|
||||
)
|
||||
res_dict = json.loads(res.text)
|
||||
res_dict = res.json()
|
||||
|
||||
if res_dict["code"] == 0:
|
||||
data = res_dict["data"][target]
|
||||
|
||||
info = self.Info(data)
|
||||
self.Info.update_forward_refs()
|
||||
info = self.Info.parse_obj(data)
|
||||
|
||||
return info
|
||||
else:
|
||||
raise self.FetchError()
|
||||
|
||||
def compare_status(
|
||||
self, target: Target, old_status: Info, new_status: Info
|
||||
self, _: Target, old_status: Info, new_status: Info
|
||||
) -> list[RawPost]:
|
||||
if new_status.is_live_turn_on(old_status):
|
||||
# 判断开播 运算符左右有顺序要求
|
||||
current_status = deepcopy(new_status)
|
||||
current_status.category = Category(1)
|
||||
return [current_status]
|
||||
elif new_status.is_title_update(old_status):
|
||||
# 判断直播时直播间标题变更 运算符左右有顺序要求
|
||||
current_status = deepcopy(new_status)
|
||||
current_status.category = Category(2)
|
||||
return [current_status]
|
||||
else:
|
||||
return []
|
||||
action = Bilibililive.LiveAction
|
||||
match new_status.get_live_action(old_status):
|
||||
case action.TURN_ON:
|
||||
current_status = deepcopy(new_status)
|
||||
current_status.category = Category(1)
|
||||
return [current_status]
|
||||
case action.TITLE_UPDATE:
|
||||
current_status = deepcopy(new_status)
|
||||
current_status.category = Category(2)
|
||||
return [current_status]
|
||||
case action.TURN_OFF:
|
||||
current_status = deepcopy(new_status)
|
||||
current_status.category = Category(3)
|
||||
return [current_status]
|
||||
case _:
|
||||
return []
|
||||
|
||||
def get_category(self, status: Info) -> Category:
|
||||
assert status.category != Category(0)
|
||||
return status.category
|
||||
|
||||
async def parse(self, raw_info: Info) -> Post:
|
||||
url = "https://live.bilibili.com/{}".format(raw_info.room_id)
|
||||
pic = [raw_info.keyframe]
|
||||
target_name = raw_info.uname
|
||||
title = raw_info.title
|
||||
async def parse(self, raw_post: Info) -> Post:
|
||||
url = "https://live.bilibili.com/{}".format(raw_post.room_id)
|
||||
pic = (
|
||||
[raw_post.cover]
|
||||
if raw_post.category == Category(1)
|
||||
else [raw_post.keyframe]
|
||||
)
|
||||
title = f"[{self.categories[raw_post.category].rstrip('提醒')}] {raw_post.title}"
|
||||
target_name = f"{raw_post.uname} {raw_post.area_name}"
|
||||
return Post(
|
||||
self.name,
|
||||
text=title,
|
||||
@@ -311,7 +360,6 @@ class Bilibililive(StatusChange):
|
||||
|
||||
|
||||
class BilibiliBangumi(StatusChange):
|
||||
|
||||
categories = {}
|
||||
platform_name = "bilibili-bangumi"
|
||||
enable_tag = False
|
||||
|
||||
Reference in New Issue
Block a user