mirror of
https://github.com/suyiiyii/nonebot-bison.git
synced 2025-06-06 20:06:12 +08:00
更换哔哩哔哩直播使用的api,添加直播间标题修改时推送直播间的功能 (#128)
* feat(bililive):调整bililive所使用的api与推送消息内容 * feat(bililive):调整功能的实现细节 * test(bililive): 初步完善相关测试 * docs(bililive): 补充文档相关 * change(bililive): 将使用修改配置项以调整订阅的方式调整为使用category * test(bililive): 调整测试,扩大测试范围 * change(bililive):调整Bilibili-live内部的代码实现 * test(bililive):修正测试 * delete(bililive):删除用来测试功能性的临时文件 * change(bililive): 调整代码
This commit is contained in:
parent
710eab42f1
commit
e14fd5bfd7
@ -1,13 +1,17 @@
|
||||
import functools
|
||||
import json
|
||||
import re
|
||||
from copy import deepcopy
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Any, Callable, Optional
|
||||
|
||||
import httpx
|
||||
from httpx import AsyncClient
|
||||
from nonebot.log import logger
|
||||
from typing_extensions import Self
|
||||
|
||||
from ..plugin_config import plugin_config
|
||||
from ..post import Post
|
||||
from ..types import Category, RawPost, Tag, Target
|
||||
from ..utils import SchedulerConfig
|
||||
@ -203,7 +207,7 @@ class Bilibililive(StatusChange):
|
||||
# Date : 2022-5-18 8:54
|
||||
# Description : bilibili开播提醒
|
||||
# E-mail : 1557157806@qq.com
|
||||
categories = {}
|
||||
categories = {1: "开播提醒", 2: "标题更新提醒"}
|
||||
platform_name = "bilibili-live"
|
||||
enable_tag = False
|
||||
enabled = True
|
||||
@ -212,6 +216,37 @@ class Bilibililive(StatusChange):
|
||||
name = "Bilibili直播"
|
||||
has_target = True
|
||||
|
||||
@dataclass
|
||||
class Info:
|
||||
uname: str
|
||||
live_status: int
|
||||
room_id: str
|
||||
title: str
|
||||
cover_from_user: str
|
||||
keyframe: str
|
||||
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
|
||||
|
||||
@classmethod
|
||||
async def get_target_name(
|
||||
cls, client: AsyncClient, target: Target
|
||||
@ -224,40 +259,49 @@ class Bilibililive(StatusChange):
|
||||
return None
|
||||
return res_data["data"]["name"]
|
||||
|
||||
async def get_status(self, target: Target):
|
||||
params = {"mid": target}
|
||||
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
|
||||
res = await self.client.get(
|
||||
"https://api.bilibili.com/x/space/acc/info",
|
||||
"http://api.live.bilibili.com/room/v1/Room/get_status_info_by_uids",
|
||||
params=params,
|
||||
timeout=4.0,
|
||||
)
|
||||
res_dict = json.loads(res.text)
|
||||
if res_dict["code"] == 0:
|
||||
info = {}
|
||||
info["uid"] = res_dict["data"]["mid"]
|
||||
info["uname"] = res_dict["data"]["name"]
|
||||
info["live_state"] = res_dict["data"]["live_room"]["liveStatus"]
|
||||
info["room_id"] = res_dict["data"]["live_room"]["roomid"]
|
||||
info["title"] = res_dict["data"]["live_room"]["title"]
|
||||
info["cover"] = res_dict["data"]["live_room"]["cover"]
|
||||
data = res_dict["data"][target]
|
||||
|
||||
info = self.Info(data)
|
||||
|
||||
return info
|
||||
else:
|
||||
raise self.FetchError()
|
||||
|
||||
def compare_status(self, target: Target, old_status, new_status) -> list[RawPost]:
|
||||
if (
|
||||
new_status["live_state"] != old_status["live_state"]
|
||||
and new_status["live_state"] == 1
|
||||
):
|
||||
return [new_status]
|
||||
def compare_status(
|
||||
self, target: 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 []
|
||||
|
||||
async def parse(self, raw_post: RawPost) -> Post:
|
||||
url = "https://live.bilibili.com/{}".format(raw_post["room_id"])
|
||||
pic = [raw_post["cover"]]
|
||||
target_name = raw_post["uname"]
|
||||
title = raw_post["title"]
|
||||
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
|
||||
return Post(
|
||||
self.name,
|
||||
text=title,
|
||||
|
@ -1,3 +1,3 @@
|
||||
from .post import Post
|
||||
|
||||
__all__ = ["Post"]
|
||||
__all__ = ["Post", "CustomPost"]
|
||||
|
135
tests/platforms/static/bili_live_status.json
vendored
135
tests/platforms/static/bili_live_status.json
vendored
@ -1,114 +1,31 @@
|
||||
{
|
||||
"code": 0,
|
||||
"message": "0",
|
||||
"ttl": 1,
|
||||
"msg": "success",
|
||||
"message": "success",
|
||||
"data": {
|
||||
"mid": 13164144,
|
||||
"name": "魔法Zc目录",
|
||||
"sex": "男",
|
||||
"face": "http://i0.hdslb.com/bfs/face/a84fa10f90f7060d0336384954ee1cde7a8e9bc6.jpg",
|
||||
"face_nft": 0,
|
||||
"sign": "每日18:00~22:00欢乐直播!请勿在任何乌有相关内容中刷Zc,尊重角色;商务合作qq271374252",
|
||||
"rank": 10000,
|
||||
"level": 6,
|
||||
"jointime": 0,
|
||||
"moral": 0,
|
||||
"silence": 0,
|
||||
"coins": 0,
|
||||
"fans_badge": true,
|
||||
"fans_medal": {
|
||||
"show": false,
|
||||
"wear": false,
|
||||
"medal": null
|
||||
},
|
||||
"official": {
|
||||
"role": 1,
|
||||
"title": "bilibili 2021百大UP主、知名游戏UP主、直播高能主播",
|
||||
"desc": "",
|
||||
"type": 0
|
||||
},
|
||||
"vip": {
|
||||
"type": 2,
|
||||
"status": 1,
|
||||
"due_date": 1702051200000,
|
||||
"vip_pay_type": 0,
|
||||
"theme_type": 0,
|
||||
"label": {
|
||||
"path": "",
|
||||
"text": "年度大会员",
|
||||
"label_theme": "annual_vip",
|
||||
"text_color": "#FFFFFF",
|
||||
"bg_style": 1,
|
||||
"bg_color": "#FB7299",
|
||||
"border_color": ""
|
||||
},
|
||||
"avatar_subscript": 1,
|
||||
"nickname_color": "#FB7299",
|
||||
"role": 3,
|
||||
"avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png"
|
||||
},
|
||||
"pendant": {
|
||||
"pid": 3399,
|
||||
"name": "2233幻星集",
|
||||
"image": "http://i0.hdslb.com/bfs/garb/item/20c07ded13498a5b12db99660c766ddd92ecfe31.png",
|
||||
"expire": 0,
|
||||
"image_enhance": "http://i0.hdslb.com/bfs/garb/item/20c07ded13498a5b12db99660c766ddd92ecfe31.png",
|
||||
"image_enhance_frame": ""
|
||||
},
|
||||
"nameplate": {
|
||||
"nid": 1,
|
||||
"name": "黄金殿堂",
|
||||
"image": "http://i2.hdslb.com/bfs/face/82896ff40fcb4e7c7259cb98056975830cb55695.png",
|
||||
"image_small": "http://i0.hdslb.com/bfs/face/627e342851dfda6fe7380c2fa0cbd7fae2e61533.png",
|
||||
"level": "稀有勋章",
|
||||
"condition": "单个自制视频总播放数\u003e=100万"
|
||||
},
|
||||
"user_honour_info": {
|
||||
"mid": 0,
|
||||
"colour": null,
|
||||
"tags": []
|
||||
},
|
||||
"is_followed": true,
|
||||
"top_photo": "http://i2.hdslb.com/bfs/space/853fea2728651588a2cdef0a1e586bcefff8e3d8.png",
|
||||
"theme": {},
|
||||
"sys_notice": {},
|
||||
"live_room": {
|
||||
"roomStatus": 1,
|
||||
"liveStatus": 0,
|
||||
"url": "https://live.bilibili.com/3044248?broadcast_type=0\u0026is_room_feed=1",
|
||||
"title": "【Zc】早朝危机合约!",
|
||||
"cover": "http://i0.hdslb.com/bfs/live/new_room_cover/cf7d4d3b2f336c6dba299644c3af952c5db82612.jpg",
|
||||
"roomid": 3044248,
|
||||
"roundStatus": 1,
|
||||
"broadcast_type": 0,
|
||||
"watched_show": {
|
||||
"switch": true,
|
||||
"num": 13753,
|
||||
"text_small": "1.3万",
|
||||
"text_large": "1.3万人看过",
|
||||
"icon": "https://i0.hdslb.com/bfs/live/a725a9e61242ef44d764ac911691a7ce07f36c1d.png",
|
||||
"icon_location": "",
|
||||
"icon_web": "https://i0.hdslb.com/bfs/live/8d9d0f33ef8bf6f308742752d13dd0df731df19c.png"
|
||||
}
|
||||
},
|
||||
"birthday": "07-21",
|
||||
"school": {
|
||||
"name": ""
|
||||
},
|
||||
"profession": {
|
||||
"name": "",
|
||||
"department": "",
|
||||
"title": "",
|
||||
"is_show": 0
|
||||
},
|
||||
"tags": [
|
||||
"评论区UP主",
|
||||
"目标是星辰大海"
|
||||
],
|
||||
"series": {
|
||||
"user_upgrade_status": 3,
|
||||
"show_upgrade_window": false
|
||||
},
|
||||
"is_senior_member": 1
|
||||
"13164144": {
|
||||
"title": "【Zc】从0挑战到15肉鸽!目前10难度",
|
||||
"room_id": 3044248,
|
||||
"uid": 13164144,
|
||||
"online": 270881,
|
||||
"live_time": 0,
|
||||
"live_status": 2,
|
||||
"short_id": 0,
|
||||
"area": 1,
|
||||
"area_name": "单机联机",
|
||||
"area_v2_id": 235,
|
||||
"area_v2_name": "其他单机",
|
||||
"area_v2_parent_name": "单机游戏",
|
||||
"area_v2_parent_id": 6,
|
||||
"uname": "魔法Zc目录",
|
||||
"face": "https://i0.hdslb.com/bfs/face/a84fa10f90f7060d0336384954ee1cde7a8e9bc6.jpg",
|
||||
"tag_name": "以撒,minecraft,饥荒,彩虹六号,东方",
|
||||
"tags": "明日方舟,搞笑,单机游戏,游戏",
|
||||
"cover_from_user": "https://i0.hdslb.com/bfs/live/new_room_cover/fd357f0f3cbbb48e9acfbcda616b946c2454c56c.jpg",
|
||||
"keyframe": "https://i0.hdslb.com/bfs/live-key-frame/keyframe10170435000003044248mwowx0.jpg",
|
||||
"lock_till": "0000-00-00 00:00:00",
|
||||
"hidden_till": "0000-00-00 00:00:00",
|
||||
"broadcast_type": 0
|
||||
}
|
||||
}
|
||||
}
|
@ -13,13 +13,23 @@ def bili_live(app: App):
|
||||
return platform_manager["bilibili-live"](AsyncClient())
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def dummy_only_status_user_subinfo(app: App):
|
||||
from nonebot_bison.types import User, UserSubInfo
|
||||
|
||||
user = User(123, "group")
|
||||
return UserSubInfo(user=user, categories=[1], tags=[])
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@respx.mock
|
||||
async def test_fetch_bilibili_live_status(bili_live, dummy_user_subinfo):
|
||||
async def test_fetch_bililive_only_status_change(
|
||||
bili_live, dummy_only_status_user_subinfo
|
||||
):
|
||||
mock_bili_live_status = get_json("bili_live_status.json")
|
||||
|
||||
bili_live_router = respx.get(
|
||||
"https://api.bilibili.com/x/space/acc/info?mid=13164144"
|
||||
"http://api.live.bilibili.com/room/v1/Room/get_status_info_by_uids?uids[]=13164144"
|
||||
)
|
||||
bili_live_router.mock(return_value=Response(200, json=mock_bili_live_status))
|
||||
|
||||
@ -27,18 +37,138 @@ async def test_fetch_bilibili_live_status(bili_live, dummy_user_subinfo):
|
||||
bilibili_main_page_router.mock(return_value=Response(200))
|
||||
|
||||
target = "13164144"
|
||||
res = await bili_live.fetch_new_post(target, [dummy_user_subinfo])
|
||||
assert bili_live_router.called
|
||||
res = await bili_live.fetch_new_post(target, [dummy_only_status_user_subinfo])
|
||||
assert bili_live_router.call_count == 1
|
||||
assert len(res) == 0
|
||||
mock_bili_live_status["data"]["live_room"]["liveStatus"] = 1
|
||||
# 直播状态更新
|
||||
mock_bili_live_status["data"][target]["live_status"] = 1
|
||||
bili_live_router.mock(return_value=Response(200, json=mock_bili_live_status))
|
||||
res2 = await bili_live.fetch_new_post(target, [dummy_user_subinfo])
|
||||
res2 = await bili_live.fetch_new_post(target, [dummy_only_status_user_subinfo])
|
||||
post = res2[0][1][0]
|
||||
assert post.target_type == "Bilibili直播"
|
||||
assert post.text == "【Zc】早朝危机合约!"
|
||||
assert post.text == "【Zc】从0挑战到15肉鸽!目前10难度"
|
||||
assert post.url == "https://live.bilibili.com/3044248"
|
||||
assert post.target_name == "魔法Zc目录"
|
||||
assert post.pics == [
|
||||
"http://i0.hdslb.com/bfs/live/new_room_cover/cf7d4d3b2f336c6dba299644c3af952c5db82612.jpg"
|
||||
"https://i0.hdslb.com/bfs/live-key-frame/keyframe10170435000003044248mwowx0.jpg"
|
||||
]
|
||||
assert post.compress == True
|
||||
# 标题变更
|
||||
mock_bili_live_status["data"][target]["title"] = "【Zc】从0挑战到15肉鸽!目前11难度"
|
||||
bili_live_router.mock(return_value=Response(200, json=mock_bili_live_status))
|
||||
res3 = await bili_live.fetch_new_post(target, [dummy_only_status_user_subinfo])
|
||||
assert bili_live_router.call_count == 3
|
||||
assert len(res3[0][1]) == 0
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def dummy_only_title_user_subinfo(app: App):
|
||||
from nonebot_bison.types import User, UserSubInfo
|
||||
|
||||
user = User(123, "group")
|
||||
return UserSubInfo(user=user, categories=[2], tags=[])
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@respx.mock
|
||||
async def test_fetch_bililive_only_title_change(
|
||||
bili_live, dummy_only_title_user_subinfo
|
||||
):
|
||||
mock_bili_live_status = get_json("bili_live_status.json")
|
||||
target = "13164144"
|
||||
|
||||
bili_live_router = respx.get(
|
||||
"http://api.live.bilibili.com/room/v1/Room/get_status_info_by_uids?uids[]=13164144"
|
||||
)
|
||||
bili_live_router.mock(return_value=Response(200, json=mock_bili_live_status))
|
||||
|
||||
bilibili_main_page_router = respx.get("https://www.bilibili.com/")
|
||||
bilibili_main_page_router.mock(return_value=Response(200))
|
||||
|
||||
res = await bili_live.fetch_new_post(target, [dummy_only_title_user_subinfo])
|
||||
assert bili_live_router.call_count == 1
|
||||
assert len(res) == 0
|
||||
# 未开播前标题变更
|
||||
mock_bili_live_status["data"][target]["title"] = "【Zc】从0挑战到15肉鸽!目前11难度"
|
||||
bili_live_router.mock(return_value=Response(200, json=mock_bili_live_status))
|
||||
res0 = await bili_live.fetch_new_post(target, [dummy_only_title_user_subinfo])
|
||||
assert bili_live_router.call_count == 2
|
||||
assert len(res0) == 0
|
||||
# 直播状态更新
|
||||
mock_bili_live_status["data"][target]["live_status"] = 1
|
||||
bili_live_router.mock(return_value=Response(200, json=mock_bili_live_status))
|
||||
res2 = await bili_live.fetch_new_post(target, [dummy_only_title_user_subinfo])
|
||||
assert bili_live_router.call_count == 3
|
||||
assert len(res2[0][1]) == 0
|
||||
# 标题变更
|
||||
mock_bili_live_status["data"][target]["title"] = "【Zc】从0挑战到15肉鸽!目前12难度"
|
||||
bili_live_router.mock(return_value=Response(200, json=mock_bili_live_status))
|
||||
res3 = await bili_live.fetch_new_post(target, [dummy_only_title_user_subinfo])
|
||||
post = res3[0][1][0]
|
||||
assert post.target_type == "Bilibili直播"
|
||||
assert post.text == "【Zc】从0挑战到15肉鸽!目前12难度"
|
||||
assert post.url == "https://live.bilibili.com/3044248"
|
||||
assert post.target_name == "魔法Zc目录"
|
||||
assert post.pics == [
|
||||
"https://i0.hdslb.com/bfs/live-key-frame/keyframe10170435000003044248mwowx0.jpg"
|
||||
]
|
||||
assert post.compress == True
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def dummy_bililive_user_subinfo(app: App):
|
||||
from nonebot_bison.types import User, UserSubInfo
|
||||
|
||||
user = User(123, "group")
|
||||
return UserSubInfo(user=user, categories=[1, 2], tags=[])
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@respx.mock
|
||||
async def test_fetch_bililive_combo(bili_live, dummy_bililive_user_subinfo):
|
||||
mock_bili_live_status = get_json("bili_live_status.json")
|
||||
target = "13164144"
|
||||
|
||||
bili_live_router = respx.get(
|
||||
"http://api.live.bilibili.com/room/v1/Room/get_status_info_by_uids?uids[]=13164144"
|
||||
)
|
||||
bili_live_router.mock(return_value=Response(200, json=mock_bili_live_status))
|
||||
|
||||
bilibili_main_page_router = respx.get("https://www.bilibili.com/")
|
||||
bilibili_main_page_router.mock(return_value=Response(200))
|
||||
|
||||
res = await bili_live.fetch_new_post(target, [dummy_bililive_user_subinfo])
|
||||
assert bili_live_router.call_count == 1
|
||||
assert len(res) == 0
|
||||
# 未开播前标题变更
|
||||
mock_bili_live_status["data"][target]["title"] = "【Zc】从0挑战到15肉鸽!目前11难度"
|
||||
bili_live_router.mock(return_value=Response(200, json=mock_bili_live_status))
|
||||
res0 = await bili_live.fetch_new_post(target, [dummy_bililive_user_subinfo])
|
||||
assert bili_live_router.call_count == 2
|
||||
assert len(res0) == 0
|
||||
# 直播状态更新
|
||||
mock_bili_live_status["data"][target]["live_status"] = 1
|
||||
bili_live_router.mock(return_value=Response(200, json=mock_bili_live_status))
|
||||
res2 = await bili_live.fetch_new_post(target, [dummy_bililive_user_subinfo])
|
||||
post2 = res2[0][1][0]
|
||||
assert post2.target_type == "Bilibili直播"
|
||||
assert post2.text == "【Zc】从0挑战到15肉鸽!目前11难度"
|
||||
assert post2.url == "https://live.bilibili.com/3044248"
|
||||
assert post2.target_name == "魔法Zc目录"
|
||||
assert post2.pics == [
|
||||
"https://i0.hdslb.com/bfs/live-key-frame/keyframe10170435000003044248mwowx0.jpg"
|
||||
]
|
||||
assert post2.compress == True
|
||||
# 标题变更
|
||||
mock_bili_live_status["data"][target]["title"] = "【Zc】从0挑战到15肉鸽!目前12难度"
|
||||
bili_live_router.mock(return_value=Response(200, json=mock_bili_live_status))
|
||||
res3 = await bili_live.fetch_new_post(target, [dummy_bililive_user_subinfo])
|
||||
post3 = res3[0][1][0]
|
||||
assert post3.target_type == "Bilibili直播"
|
||||
assert post3.text == "【Zc】从0挑战到15肉鸽!目前12难度"
|
||||
assert post3.url == "https://live.bilibili.com/3044248"
|
||||
assert post3.target_name == "魔法Zc目录"
|
||||
assert post3.pics == [
|
||||
"https://i0.hdslb.com/bfs/live-key-frame/keyframe10170435000003044248mwowx0.jpg"
|
||||
]
|
||||
assert post3.compress == True
|
||||
|
Loading…
x
Reference in New Issue
Block a user