fix message

This commit is contained in:
jxxghp
2024-07-04 18:45:22 +08:00
parent 5f01dd5625
commit 965e40e630
14 changed files with 281 additions and 232 deletions

View File

@@ -1,5 +1,7 @@
from abc import abstractmethod, ABCMeta
from typing import Tuple, Union
from typing import Tuple, Union, Dict, Any, Optional
from app.schemas import Notification, MessageChannel, NotificationConf
class _ModuleBase(metaclass=ABCMeta):
@@ -45,3 +47,48 @@ class _ModuleBase(metaclass=ABCMeta):
模块测试, 返回测试结果和错误信息
"""
pass
class _MessageBase:
"""
消息基类
"""
_channel: MessageChannel = None
_configs: Dict[str, NotificationConf] = {}
_clients: Dict[str, Any] = {}
def get_client(self, name: str) -> Optional[Any]:
"""
获取客户端
"""
if not name:
return None
return self._clients.get(name)
def get_config(self, name: str) -> Optional[NotificationConf]:
"""
获取配置
"""
if not name:
return None
return self._configs.get(name)
def checkMessage(self, message: Notification, source: str) -> bool:
"""
检查消息渠道及消息类型,如不符合则不处理
"""
# 检查消息渠道
if message.channel and message.channel != self._channel:
return False
# 检查消息来源
if message.source and message.source != source:
return False
# 检查消息类型开关
if message.mtype:
conf = self.get_config(source)
if conf:
switchs = conf.switchs or []
if message.mtype.value not in switchs:
return False
return True

View File

@@ -1,20 +1,17 @@
import json
import re
from typing import Optional, Union, List, Tuple, Any, Dict
from typing import Optional, Union, List, Tuple, Any
from app.core.context import MediaInfo, Context
from app.core.config import settings
from app.core.context import MediaInfo, Context
from app.helper.notification import NotificationHelper
from app.log import logger
from app.modules import _ModuleBase
from app.modules import _ModuleBase, _MessageBase
from app.modules.slack.slack import Slack
from app.schemas import MessageChannel, CommingMessage, Notification, NotificationConf
from app.schemas import MessageChannel, CommingMessage, Notification
class SlackModule(_ModuleBase):
_channel = MessageChannel.Telegram
_configs: Dict[str, NotificationConf] = {}
_clients: Dict[str, Slack] = {}
class SlackModule(_ModuleBase, _MessageBase):
def init_module(self) -> None:
"""
@@ -34,18 +31,6 @@ class SlackModule(_ModuleBase):
def get_name() -> str:
return "Slack"
def get_client(self, name: str) -> Optional[Slack]:
"""
获取Telegram客户端
"""
return self._clients.get(name)
def get_config(self, name: str) -> Optional[NotificationConf]:
"""
获取Telegram配置
"""
return self._configs.get(name)
def stop(self):
"""
停止模块
@@ -66,32 +51,14 @@ class SlackModule(_ModuleBase):
def init_setting(self) -> Tuple[str, Union[str, bool]]:
pass
def checkMessage(self, message: Notification, source: str) -> bool:
"""
检查消息渠道及消息类型,如不符合则不处理
"""
# 检查消息渠道
if message.channel and message.channel != self._channel:
return False
# 检查消息来源
if message.source and message.source != source:
return False
# 检查消息类型开关
if message.mtype:
conf = self.get_config(source)
if conf:
switchs = conf.switchs or []
if message.mtype.value not in switchs:
return False
return True
def message_parser(self, body: Any, form: Any,
def message_parser(self, source: str, body: Any, form: Any,
args: Any) -> Optional[CommingMessage]:
"""
解析消息内容,返回字典,注意以下约定值:
userid: 用户ID
username: 用户名
text: 内容
:param source: 消息来源
:param body: 请求体
:param form: 表单
:param args: 参数
@@ -207,11 +174,8 @@ class SlackModule(_ModuleBase):
}
"""
# 来源
source = args.get("source")
if not source:
return None
# 获取客户端
client = self.get_client(source)
client: Slack = self.get_client(source)
if not client:
return None
# 校验token
@@ -260,10 +224,17 @@ class SlackModule(_ModuleBase):
for conf in self._configs.values():
if not self.checkMessage(message, conf.name):
continue
client = self.get_client(conf.name)
targets = message.targets
userid = message.userid
if not userid and targets is not None:
userid = targets.get('slack_userid')
if not userid:
logger.warn(f"用户没有指定 Slack用户ID消息无法发送")
return
client: Slack = self.get_client(conf.name)
if client:
client.send_msg(title=message.title, text=message.text,
image=message.image, userid=message.userid, link=message.link)
image=message.image, userid=userid, link=message.link)
def post_medias_message(self, message: Notification, medias: List[MediaInfo]) -> None:
"""
@@ -275,7 +246,7 @@ class SlackModule(_ModuleBase):
for conf in self._configs.values():
if not self.checkMessage(message, conf.name):
continue
client = self.get_client(conf.name)
client: Slack = self.get_client(conf.name)
if client:
client.send_meidas_msg(title=message.title, medias=medias, userid=message.userid)
@@ -289,7 +260,7 @@ class SlackModule(_ModuleBase):
for conf in self._configs.values():
if not self.checkMessage(message, conf.name):
continue
client = self.get_client(conf.name)
client: Slack = self.get_client(conf.name)
if client:
client.send_torrents_msg(title=message.title, torrents=torrents,
userid=message.userid)

View File

@@ -1,17 +1,14 @@
from typing import Optional, Union, List, Tuple, Any, Dict
from typing import Optional, Union, List, Tuple, Any
from app.core.context import MediaInfo, Context
from app.helper.notification import NotificationHelper
from app.log import logger
from app.modules import _ModuleBase
from app.modules import _ModuleBase, _MessageBase
from app.modules.synologychat.synologychat import SynologyChat
from app.schemas import MessageChannel, CommingMessage, Notification, NotificationConf
from app.schemas import MessageChannel, CommingMessage, Notification
class SynologyChatModule(_ModuleBase):
_channel = MessageChannel.Telegram
_configs: Dict[str, NotificationConf] = {}
_clients: Dict[str, SynologyChat] = {}
class SynologyChatModule(_ModuleBase, _MessageBase):
def init_module(self) -> None:
"""
@@ -31,18 +28,6 @@ class SynologyChatModule(_ModuleBase):
def get_name() -> str:
return "Synology Chat"
def get_client(self, name: str) -> Optional[SynologyChat]:
"""
获取Telegram客户端
"""
return self._clients.get(name)
def get_config(self, name: str) -> Optional[NotificationConf]:
"""
获取Telegram配置
"""
return self._configs.get(name)
def stop(self):
pass
@@ -59,32 +44,14 @@ class SynologyChatModule(_ModuleBase):
def init_setting(self) -> Tuple[str, Union[str, bool]]:
pass
def checkMessage(self, message: Notification, source: str) -> bool:
"""
检查消息渠道及消息类型,如不符合则不处理
"""
# 检查消息渠道
if message.channel and message.channel != self._channel:
return False
# 检查消息来源
if message.source and message.source != source:
return False
# 检查消息类型开关
if message.mtype:
conf = self.get_config(source)
if conf:
switchs = conf.switchs or []
if message.mtype.value not in switchs:
return False
return True
def message_parser(self, body: Any, form: Any,
def message_parser(self, source: str, body: Any, form: Any,
args: Any) -> Optional[CommingMessage]:
"""
解析消息内容,返回字典,注意以下约定值:
userid: 用户ID
username: 用户名
text: 内容
:param source: 消息来源
:param body: 请求体
:param form: 表单
:param args: 参数
@@ -92,10 +59,7 @@ class SynologyChatModule(_ModuleBase):
"""
try:
# 来源
source = args.get("source")
if not source:
return None
client = self.get_client(source)
client: SynologyChat = self.get_client(source)
if not client:
return None
# 解析消息
@@ -129,10 +93,17 @@ class SynologyChatModule(_ModuleBase):
for conf in self._configs.values():
if not self.checkMessage(message, conf.name):
continue
client = self.get_client(conf.name)
targets = message.targets
userid = message.userid
if not userid and targets is not None:
userid = targets.get('synologychat_userid')
if not userid:
logger.warn(f"用户没有指定 SynologyChat用户ID消息无法发送")
return
client: SynologyChat = self.get_client(conf.name)
if client:
client.send_msg(title=message.title, text=message.text,
image=message.image, userid=message.userid, link=message.link)
image=message.image, userid=userid, link=message.link)
def post_medias_message(self, message: Notification, medias: List[MediaInfo]) -> None:
"""
@@ -144,7 +115,7 @@ class SynologyChatModule(_ModuleBase):
for conf in self._configs.values():
if not self.checkMessage(message, conf.name):
continue
client = self.get_client(conf.name)
client: SynologyChat = self.get_client(conf.name)
if client:
client.send_meidas_msg(title=message.title, medias=medias,
userid=message.userid)
@@ -159,7 +130,7 @@ class SynologyChatModule(_ModuleBase):
for conf in self._configs.values():
if not self.checkMessage(message, conf.name):
continue
client = self.get_client(conf.name)
client: SynologyChat = self.get_client(conf.name)
if client:
client.send_torrents_msg(title=message.title, torrents=torrents,
userid=message.userid, link=message.link)

View File

@@ -5,15 +5,12 @@ from app.core.context import MediaInfo, Context
from app.core.config import settings
from app.helper.notification import NotificationHelper
from app.log import logger
from app.modules import _ModuleBase
from app.modules import _ModuleBase, _MessageBase
from app.modules.telegram.telegram import Telegram
from app.schemas import MessageChannel, CommingMessage, Notification, NotificationConf
class TelegramModule(_ModuleBase):
_channel = MessageChannel.Telegram
_configs: Dict[str, NotificationConf] = {}
_clients: Dict[str, Telegram] = {}
class TelegramModule(_ModuleBase, _MessageBase):
def init_module(self) -> None:
"""
@@ -33,18 +30,6 @@ class TelegramModule(_ModuleBase):
def get_name() -> str:
return "Telegram"
def get_client(self, name: str) -> Optional[Telegram]:
"""
获取Telegram客户端
"""
return self._clients.get(name)
def get_config(self, name: str) -> Optional[NotificationConf]:
"""
获取Telegram配置
"""
return self._configs.get(name)
def stop(self):
"""
停止模块
@@ -65,25 +50,6 @@ class TelegramModule(_ModuleBase):
def init_setting(self) -> Tuple[str, Union[str, bool]]:
pass
def checkMessage(self, message: Notification, source: str) -> bool:
"""
检查消息渠道及消息类型,如不符合则不处理
"""
# 检查消息渠道
if message.channel and message.channel != self._channel:
return False
# 检查消息来源
if message.source and message.source != source:
return False
# 检查消息类型开关
if message.mtype:
conf = self.get_config(source)
if conf:
switchs = conf.switchs or []
if message.mtype.value not in switchs:
return False
return True
def message_parser(self, source: str, body: Any, form: Any,
args: Any) -> Optional[CommingMessage]:
"""
@@ -91,7 +57,7 @@ class TelegramModule(_ModuleBase):
userid: 用户ID
username: 用户名
text: 内容
:param source: 消息来源(渠道配置名称)
:param source: 消息来源
:param body: 请求体
:param form: 表单
:param args: 参数
@@ -121,7 +87,7 @@ class TelegramModule(_ModuleBase):
}
"""
# 获取渠道
client = self.get_client(source)
client: Telegram = self.get_client(source)
if not client:
return None
# 获取配置
@@ -173,10 +139,17 @@ class TelegramModule(_ModuleBase):
for conf in self._configs.values():
if not self.checkMessage(message, conf.name):
continue
client = self.get_client(conf.name)
targets = message.targets
userid = message.userid
if not userid and targets is not None:
userid = targets.get('telegram_userid')
if not userid:
logger.warn(f"用户没有指定 Telegram用户ID消息无法发送")
return
client: Telegram = self.get_client(conf.name)
if client:
client.send_msg(title=message.title, text=message.text,
image=message.image, userid=message.userid, link=message.link)
image=message.image, userid=userid, link=message.link)
def post_medias_message(self, message: Notification, medias: List[MediaInfo]) -> None:
"""
@@ -188,7 +161,7 @@ class TelegramModule(_ModuleBase):
for conf in self._configs.values():
if not self.checkMessage(message, conf.name):
continue
client = self.get_client(conf.name)
client: Telegram = self.get_client(conf.name)
if client:
client.send_meidas_msg(title=message.title, medias=medias,
userid=message.userid, link=message.link)
@@ -203,7 +176,7 @@ class TelegramModule(_ModuleBase):
for conf in self._configs.values():
if not self.checkMessage(message, conf.name):
continue
client = self.get_client(conf.name)
client: Telegram = self.get_client(conf.name)
if client:
client.send_torrents_msg(title=message.title, torrents=torrents,
userid=message.userid, link=message.link)

View File

@@ -5,24 +5,25 @@ from app.core.config import settings
from app.core.context import Context, MediaInfo
from app.helper.notification import NotificationHelper
from app.log import logger
from app.modules import _ModuleBase, checkMessage
from app.modules import _ModuleBase, _MessageBase
from app.modules.vocechat.vocechat import VoceChat
from app.schemas import MessageChannel, CommingMessage, Notification
class VoceChatModule(_ModuleBase):
_clients: Dict[str, VoceChat] = {}
class VoceChatModule(_ModuleBase, _MessageBase):
def init_module(self) -> None:
"""
初始化模块
"""
self._clients = {}
clients = NotificationHelper().get_clients()
if not clients:
return
self._configs = {}
self._clients = {}
for client in clients:
if client.type == "vocechat" and client.enabled:
self._configs[client.name] = client
self._clients[client.name] = VoceChat(**client.config)
@staticmethod
@@ -36,22 +37,23 @@ class VoceChatModule(_ModuleBase):
"""
测试模块连接性
"""
state = self.vocechat.get_state()
if state:
return True, ""
return False, "获取VoceChat频道失败"
for name, client in self._clients.items():
state = client.get_state()
if not state:
return False, f"VoceChat {name} 未就续"
return True, ""
def init_setting(self) -> Tuple[str, Union[str, bool]]:
pass
@staticmethod
def message_parser(body: Any, form: Any,
def message_parser(self, source: str, body: Any, form: Any,
args: Any) -> Optional[CommingMessage]:
"""
解析消息内容,返回字典,注意以下约定值:
userid: 用户ID
username: 用户名
text: 内容
:param source: 消息来源
:param body: 请求体
:param form: 表单
:param args: 参数
@@ -73,6 +75,14 @@ class VoceChatModule(_ModuleBase):
"target": { "gid": 2 } //发送给谁gid代表是发送给频道uid代表是发送给个人此时的数据结构举例{"uid":1}
}
"""
# 获取渠道
client: VoceChat = self.get_client(source)
if not client:
return None
# 获取配置
config = self.get_config(source)
if not config:
return None
# 报文体
msg_body = json.loads(body)
# 类型
@@ -90,7 +100,8 @@ class VoceChatModule(_ModuleBase):
content = msg_body.get("detail", {}).get("content")
# 用户ID
gid = msg_body.get("target", {}).get("gid")
if gid and str(gid) == str(settings.VOCECHAT_CHANNEL_ID):
channel_id = config.config.get("channel_id")
if gid and str(gid) == str(channel_id):
# 来自监听频道的消息
userid = f"GID#{gid}"
else:
@@ -106,40 +117,61 @@ class VoceChatModule(_ModuleBase):
logger.error(f"VoceChat消息处理发生错误{str(err)}")
return None
@checkMessage(MessageChannel.VoceChat)
def post_message(self, message: Notification) -> None:
"""
发送消息
:param message: 消息内容
:return: 成功或失败
"""
self.vocechat.send_msg(title=message.title, text=message.text,
userid=message.userid, link=message.link)
for conf in self._configs.values():
if not self.checkMessage(message, conf.name):
continue
targets = message.targets
userid = message.userid
if not message.userid and targets:
userid = targets.get('telegram_userid')
client: VoceChat = self.get_client(conf.name)
if client:
client.send_msg(title=message.title, text=message.text,
userid=userid, link=message.link)
@checkMessage(MessageChannel.VoceChat)
def post_medias_message(self, message: Notification, medias: List[MediaInfo]) -> Optional[bool]:
def post_medias_message(self, message: Notification, medias: List[MediaInfo]) -> None:
"""
发送媒体信息选择列表
:param message: 消息内容
:param medias: 媒体列表
:return: 成功或失败
"""
# 先发送标题
self.vocechat.send_msg(title=message.title, userid=message.userid)
# 再发送内容
return self.vocechat.send_medias_msg(title=message.title, medias=medias,
userid=message.userid, link=message.link)
for conf in self._configs.values():
if not self.checkMessage(message, conf.name):
continue
client: VoceChat = self.get_client(conf.name)
if client:
client.send_msg(title=message.title, userid=message.userid)
client.send_medias_msg(title=message.title, medias=medias,
userid=message.userid, link=message.link)
@checkMessage(MessageChannel.VoceChat)
def post_torrents_message(self, message: Notification, torrents: List[Context]) -> Optional[bool]:
def post_torrents_message(self, message: Notification, torrents: List[Context]) -> None:
"""
发送种子信息选择列表
:param message: 消息内容
:param torrents: 种子列表
:return: 成功或失败
"""
return self.vocechat.send_torrents_msg(title=message.title, torrents=torrents,
userid=message.userid, link=message.link)
for conf in self._configs.values():
if not self.checkMessage(message, conf.name):
continue
targets = message.targets
userid = message.userid
if not userid and targets is not None:
userid = targets.get('vocechat_userid')
if not userid:
logger.warn(f"用户没有指定 VoceChat用户ID消息无法发送")
return
client: VoceChat = self.get_client(conf.name)
if client:
client.send_torrents_msg(title=message.title, torrents=torrents,
userid=userid, link=message.link)
def register_commands(self, commands: Dict[str, dict]):
pass

View File

@@ -5,17 +5,14 @@ from app.core.config import settings
from app.core.context import Context, MediaInfo
from app.helper.notification import NotificationHelper
from app.log import logger
from app.modules import _ModuleBase
from app.modules import _ModuleBase, _MessageBase
from app.modules.wechat.WXBizMsgCrypt3 import WXBizMsgCrypt
from app.modules.wechat.wechat import WeChat
from app.schemas import MessageChannel, CommingMessage, Notification, NotificationConf
from app.schemas import MessageChannel, CommingMessage, Notification
from app.utils.dom import DomUtils
class WechatModule(_ModuleBase):
_channel = MessageChannel.Wechat
_configs: Dict[str, NotificationConf] = {}
_clients: Dict[str, WeChat] = {}
class WechatModule(_ModuleBase, _MessageBase):
def init_module(self) -> None:
"""
@@ -35,18 +32,6 @@ class WechatModule(_ModuleBase):
def get_name() -> str:
return "微信"
def get_client(self, name: str) -> Optional[WeChat]:
"""
获取Telegram客户端
"""
return self._clients.get(name)
def get_config(self, name: str) -> Optional[NotificationConf]:
"""
获取Telegram配置
"""
return self._configs.get(name)
def stop(self):
pass
@@ -63,25 +48,22 @@ class WechatModule(_ModuleBase):
def init_setting(self) -> Tuple[str, Union[str, bool]]:
pass
def message_parser(self, body: Any, form: Any,
def message_parser(self, source: str, body: Any, form: Any,
args: Any) -> Optional[CommingMessage]:
"""
解析消息内容,返回字典,注意以下约定值:
userid: 用户ID
username: 用户名
text: 内容
:param source: 消息来源
:param body: 请求体
:param form: 表单
:param args: 参数
:return: 渠道、消息体
"""
try:
# 消息来源
source = args.get("source")
if not source:
return None
# 获取客户端
client = self.get_client(source)
client: WeChat = self.get_client(source)
if not client:
return None
# URL参数
@@ -168,25 +150,6 @@ class WechatModule(_ModuleBase):
logger.error(f"微信消息处理发生错误:{str(err)}")
return None
def checkMessage(self, message: Notification, source: str) -> bool:
"""
检查消息渠道及消息类型,如不符合则不处理
"""
# 检查消息渠道
if message.channel and message.channel != self._channel:
return False
# 检查消息来源
if message.source and message.source != source:
return False
# 检查消息类型开关
if message.mtype:
conf = self.get_config(source)
if conf:
switchs = conf.switchs or []
if message.mtype.value not in switchs:
return False
return True
def post_message(self, message: Notification) -> None:
"""
发送消息
@@ -196,10 +159,17 @@ class WechatModule(_ModuleBase):
for conf in self._configs.values():
if not self.checkMessage(message, conf.name):
continue
client = self.get_client(conf.name)
targets = message.targets
userid = message.userid
if not userid and targets is not None:
userid = targets.get('wechat_userid')
if not userid:
logger.warn(f"用户没有指定 微信用户ID消息无法发送")
return
client: WeChat = self.get_client(conf.name)
if client:
client.send_msg(title=message.title, text=message.text,
image=message.image, userid=message.userid, link=message.link)
image=message.image, userid=userid, link=message.link)
def post_medias_message(self, message: Notification, medias: List[MediaInfo]) -> None:
"""
@@ -211,7 +181,7 @@ class WechatModule(_ModuleBase):
for conf in self._configs.values():
if not self.checkMessage(message, conf.name):
continue
client = self.get_client(conf.name)
client: WeChat = self.get_client(conf.name)
if client:
# 先发送标题
client.send_msg(title=message.title, userid=message.userid, link=message.link)
@@ -228,7 +198,7 @@ class WechatModule(_ModuleBase):
for conf in self._configs.values():
if not self.checkMessage(message, conf.name):
continue
client = self.get_client(conf.name)
client: WeChat = self.get_client(conf.name)
if client:
client.send_torrents_msg(title=message.title, torrents=torrents,
userid=message.userid, link=message.link)