mirror of
https://github.com/yulinfeng000/blive.git
synced 2025-03-25 16:50:53 +08:00
add global error handle, and update README, add new example for error handle, update msg.py for add new property for SuperChatMsg
This commit is contained in:
parent
0c1f94b4a8
commit
6b3e896dc6
23
README.md
23
README.md
@ -156,6 +156,26 @@ async def show():
|
||||
return list(BLIVER_POOL.keys())
|
||||
```
|
||||
|
||||
|
||||
## 全局异常处理
|
||||
|
||||
全局异常处理分为两个共享级别,分别为类级别和实例级别,在类上注册的异常处理为所有类实例共享,实例级别的异常处理只有实例自身拥有
|
||||
|
||||
```python
|
||||
|
||||
app = BLiver(510)
|
||||
|
||||
@app.catch(ZeroDivisionError)
|
||||
def err_handler(e, app: BLiver):
|
||||
print(f"{app.uname} catch ZeroDivisionError", e)
|
||||
|
||||
@app.on(Events.DANMU_MSG)
|
||||
async def danmu_handler(ctx):
|
||||
1 / 0 # will raise ZeroDivisionError
|
||||
|
||||
azi.run()
|
||||
```
|
||||
|
||||
## 项目简介
|
||||
|
||||
- blive 文件夹为框架代码
|
||||
@ -175,6 +195,9 @@ async def show():
|
||||
- example/with_fastapi.py
|
||||
与fastapi 配合使用的例子
|
||||
|
||||
- example/error_handler.py
|
||||
错误处理的例子
|
||||
|
||||
## TODO
|
||||
|
||||
- 更多的消息操作类(欢迎各位提pr)
|
||||
|
@ -1,3 +1,4 @@
|
||||
from socket import gaierror
|
||||
import sys
|
||||
import json
|
||||
import asyncio
|
||||
@ -74,6 +75,25 @@ class Processor:
|
||||
|
||||
|
||||
class BLiver:
|
||||
_global_catches = {}
|
||||
|
||||
def catch(self, err_type):
|
||||
def _err_handler_wrapper(fn):
|
||||
self.register_error_handler(err_type, fn)
|
||||
|
||||
return _err_handler_wrapper
|
||||
|
||||
@classmethod
|
||||
def register_global_error_handler(cls, err_type, fn):
|
||||
err_handlers = cls._global_catches.get(err_type, [])
|
||||
err_handlers.append(fn)
|
||||
cls._global_catches[err_type] = err_handlers
|
||||
|
||||
def register_error_handler(self, err_type, fn):
|
||||
err_handlers = self._catches.get(err_type, [])
|
||||
err_handlers.append(fn)
|
||||
self._catches[err_type] = err_handlers
|
||||
|
||||
def __init__(self, roomid, uid=0, logger=None, log_level="INFO"):
|
||||
self.roomid = roomid
|
||||
self.uid = uid
|
||||
@ -84,6 +104,7 @@ class BLiver:
|
||||
self.logger.add(sys.stderr, level=log_level)
|
||||
else:
|
||||
self.logger = logger
|
||||
self._catches = {} # to handle errors
|
||||
self._ws: ClientWebSocketResponse = None
|
||||
self.packman = BWS_MsgPackage()
|
||||
self.scheduler = AsyncIOScheduler(timezone="Asia/ShangHai")
|
||||
@ -162,6 +183,7 @@ class BLiver:
|
||||
except (
|
||||
aiohttp.ClientConnectionError,
|
||||
asyncio.TimeoutError,
|
||||
ConnectionError,
|
||||
ConnectionResetError,
|
||||
):
|
||||
self.logger.warning("send heartbeat error, will reconnect ws")
|
||||
@ -185,6 +207,7 @@ class BLiver:
|
||||
aiohttp.ClientConnectionError,
|
||||
asyncio.TimeoutError,
|
||||
ConnectionError,
|
||||
ConnectionResetError,
|
||||
):
|
||||
self.logger.warning(
|
||||
"connect failed, will retry {}, current: {}", retries, i + 1
|
||||
@ -226,6 +249,12 @@ class BLiver:
|
||||
self.logger.warning("ws conn will reconnect")
|
||||
await self.connect()
|
||||
|
||||
# to handler errors
|
||||
except tuple(self._catches.keys()) as e:
|
||||
[eh(e,self) for eh in self._catches.get(type(e), [])]
|
||||
except tuple(BLiver._global_catches.keys()) as e:
|
||||
[eh(e,self) for eh in BLiver._global_catches.get(type(e), [])]
|
||||
|
||||
async def graceful_close(self):
|
||||
await self._ws.close()
|
||||
await self.aio_session.close()
|
||||
|
13
blive/msg.py
13
blive/msg.py
@ -201,6 +201,19 @@ class SuperChatMsg(BaseMsg):
|
||||
@property
|
||||
def time(self):
|
||||
return dict_chain_get(self.body, "data.time")
|
||||
|
||||
@property # 头像
|
||||
def avatar_url(self):
|
||||
return dict_chain_get(self.body, "data.user_info.face")
|
||||
|
||||
@property
|
||||
def anchor_uname(self):
|
||||
return dict_chain_get(self.body, "data.medal_info.anchor_uname")
|
||||
|
||||
@property # 背景色
|
||||
def color(self):
|
||||
return dict_chain_get(self.body, "data.background_bottom_color")
|
||||
|
||||
|
||||
|
||||
class EntryEffectMsg(BaseMsg):
|
||||
|
66
example/error_handler.py
Normal file
66
example/error_handler.py
Normal file
@ -0,0 +1,66 @@
|
||||
"""监听多个直播间的例子"""
|
||||
|
||||
import asyncio
|
||||
from blive import BLiver, Events, BLiverCtx
|
||||
from blive.msg import DanMuMsg
|
||||
|
||||
# 多个对象共用的全局异常处理
|
||||
# 首先定义全局异常处理handler
|
||||
|
||||
|
||||
def global_error_handler(e, app: BLiver):
|
||||
print(f"{app.uname} 全局异常捕获", e)
|
||||
|
||||
|
||||
# 调用类方法注册异常以及其处理函数,需在实例化之前注册,注册后所有BLiver共同拥有该异常处理
|
||||
BLiver.register_global_error_handler(ZeroDivisionError, global_error_handler)
|
||||
|
||||
|
||||
# 定义弹幕事件handler,为了演示异常处理直接在方法中抛出异常
|
||||
async def azi_timeout_error(ctx: BLiverCtx):
|
||||
raise TimeoutError
|
||||
|
||||
|
||||
async def ke_type_error(ctx):
|
||||
raise TypeError
|
||||
|
||||
|
||||
async def zero_division_error(ctx):
|
||||
1 / 0
|
||||
|
||||
|
||||
# 两个直播间
|
||||
ke = BLiver(21716679)
|
||||
azi = BLiver(7983476)
|
||||
|
||||
# 注册handler
|
||||
ke.register_handler(Events.INTERACT_WORD, zero_division_error)
|
||||
azi.register_handler(Events.INTERACT_WORD, zero_division_error)
|
||||
ke.register_handler(Events.DANMU_MSG, ke_type_error)
|
||||
azi.register_handler(Events.DANMU_MSG, azi_timeout_error)
|
||||
|
||||
|
||||
# 类实例级别的异常处理,实例与实例之间不共享
|
||||
ke.register_error_handler(
|
||||
TypeError, lambda e, app: print(f"{app.uname} catch TypeError", e)
|
||||
)
|
||||
|
||||
# 实例级别的异常处理可以用注解方式进行注册
|
||||
@azi.catch(TimeoutError)
|
||||
def azi_handler(e, app):
|
||||
print(f"{app.uname} catch TimeoutError", e)
|
||||
|
||||
|
||||
async def main():
|
||||
|
||||
# 以异步task的形式运行
|
||||
task1 = ke.run_as_task()
|
||||
task2 = azi.run_as_task()
|
||||
|
||||
# await 两个任务
|
||||
await asyncio.gather(*[task1, task2])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.run_until_complete(main())
|
@ -9,7 +9,7 @@ from blive.msg import DanMuMsg
|
||||
async def listen(ctx: BLiverCtx):
|
||||
danmu = DanMuMsg(ctx.body)
|
||||
print(
|
||||
f'\n{danmu.sender.name} ({danmu.sender.medal.medal_name}:{danmu.sender.medal.medal_level}): "{danmu.content}"\n'
|
||||
f'\n【{ctx.bliver.uname}】{danmu.sender.name} ({danmu.sender.medal.medal_name}:{danmu.sender.medal.medal_level}): "{danmu.content}"\n'
|
||||
)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user