diff --git a/plugins/douyu/__init__.py b/plugins/douyu/__init__.py
new file mode 100644
index 0000000..1a91760
--- /dev/null
+++ b/plugins/douyu/__init__.py
@@ -0,0 +1,4 @@
+from .main import DouyuPlugin
+
+def get_plugin():
+ return DouyuPlugin()
diff --git a/plugins/douyu/config.toml b/plugins/douyu/config.toml
new file mode 100644
index 0000000..57a59b1
--- /dev/null
+++ b/plugins/douyu/config.toml
@@ -0,0 +1,6 @@
+[Douyu]
+enable = true
+command = ["订阅斗鱼", "取消订阅斗鱼", "斗鱼订阅列表"]
+check_interval_minutes = 5
+api_url_template = "https://www.douyu.com/betard/{room_id}"
+user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
diff --git a/plugins/douyu/main.py b/plugins/douyu/main.py
new file mode 100644
index 0000000..c74a2e4
--- /dev/null
+++ b/plugins/douyu/main.py
@@ -0,0 +1,254 @@
+import asyncio
+import json
+from typing import Dict, Any, List, Optional, Tuple, Set
+
+import aiohttp
+from loguru import logger
+
+from base.plugin_common.message_plugin_interface import MessagePluginInterface
+from base.plugin_common.plugin_interface import PluginStatus
+from db.connection import DBConnectionManager
+from utils.decorator.async_job import async_job
+from utils.decorator.plugin_decorators import plugin_stats_decorator
+from utils.decorator.points_decorator import plugin_points_cost
+from utils.robot_cmd.robot_command import Feature, PermissionStatus, GroupBotManager
+from wechat_ipad import WechatAPIClient
+
+
+class DouyuRedisManager:
+ def __init__(self, db_manager: DBConnectionManager):
+ self.redis = db_manager.get_redis_connection()
+ self.prefix = "bot:douyu:"
+
+ def add_group_room(self, group_id: str, room_id: str) -> bool:
+ key = f"{self.prefix}group:{group_id}:rooms"
+ return self.redis.sadd(key, room_id) >= 0
+
+ def remove_group_room(self, group_id: str, room_id: str) -> bool:
+ key = f"{self.prefix}group:{group_id}:rooms"
+ return self.redis.srem(key, room_id) >= 0
+
+ def list_group_rooms(self, group_id: str) -> List[str]:
+ key = f"{self.prefix}group:{group_id}:rooms"
+ rooms = self.redis.smembers(key) or set()
+ result = []
+ for r in rooms:
+ result.append(r.decode("utf-8") if isinstance(r, bytes) else r)
+ return sorted(result)
+
+ def all_subscribed_rooms(self) -> Set[str]:
+ groups = GroupBotManager.get_group_list()
+ rooms: Set[str] = set()
+ for gid in groups:
+ for r in self.list_group_rooms(gid):
+ rooms.add(r)
+ return rooms
+
+ def groups_for_room(self, room_id: str) -> List[str]:
+ groups = GroupBotManager.get_group_list()
+ res = []
+ for gid in groups:
+ if room_id in set(self.list_group_rooms(gid)):
+ res.append(gid)
+ return res
+
+ def get_room_status(self, room_id: str) -> Optional[Dict[str, Any]]:
+ key = f"{self.prefix}room_status:{room_id}"
+ data = self.redis.get(key)
+ if not data:
+ return None
+ if isinstance(data, bytes):
+ data = data.decode("utf-8")
+ try:
+ return json.loads(data)
+ except Exception:
+ return None
+
+ def set_room_status(self, room_id: str, status: Dict[str, Any]) -> bool:
+ key = f"{self.prefix}room_status:{room_id}"
+ return self.redis.set(key, json.dumps(status, ensure_ascii=False), ex=86400)
+
+
+class DouyuPlugin(MessagePluginInterface):
+ FEATURE_KEY = "DOUYU_MONITOR"
+ FEATURE_DESCRIPTION = "🎮 斗鱼开播提醒 [订阅斗鱼 房间号, 取消订阅斗鱼 房间号]"
+
+ @property
+ def name(self) -> str:
+ return "斗鱼直播"
+
+ @property
+ def version(self) -> str:
+ return "1.0.0"
+
+ @property
+ def description(self) -> str:
+ return "斗鱼主播开播下播提醒与群订阅管理"
+
+ @property
+ def author(self) -> str:
+ return "ABOT Team"
+
+ @property
+ def command_prefix(self) -> Optional[str]:
+ return ""
+
+ @property
+ def commands(self) -> List[str]:
+ return self._commands
+
+ @property
+ def feature_key(self) -> Optional[str]:
+ return self.FEATURE_KEY
+
+ @property
+ def feature_description(self) -> Optional[str]:
+ return self.FEATURE_DESCRIPTION
+
+ def __init__(self):
+ super().__init__()
+ self.bot: WechatAPIClient = None
+ self.feature = self.register_feature()
+ self.redis_manager: Optional[DouyuRedisManager] = None
+ self._commands = ["订阅斗鱼", "取消订阅斗鱼", "斗鱼订阅列表"]
+ self._api_template = "https://www.douyu.com/betard/{room_id}"
+ self._user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
+ self._check_interval = 5
+
+ def initialize(self, context: Dict[str, Any]) -> bool:
+ try:
+ dbm = DBConnectionManager.get_instance()
+ self.redis_manager = DouyuRedisManager(dbm)
+ cfg = self._config.get("Douyu", {})
+ self._commands = cfg.get("command", self._commands)
+ self._api_template = cfg.get("api_url_template", self._api_template)
+ self._user_agent = cfg.get("user_agent", self._user_agent)
+ self._check_interval = int(cfg.get("check_interval_minutes", self._check_interval))
+ async_job.every_minutes(self._check_interval)(self._scheduled_check_job)
+ return True
+ except Exception as e:
+ logger.error(f"{self.name} 初始化失败: {e}")
+ return False
+
+ def start(self) -> bool:
+ self.status = PluginStatus.RUNNING
+ return True
+
+ def stop(self) -> bool:
+ self.status = PluginStatus.STOPPED
+ return True
+
+ def can_process(self, message: Dict[str, Any]) -> bool:
+ content = str(message.get("content", "")).strip()
+ if not content:
+ return False
+ for cmd in self._commands:
+ if content.startswith(cmd):
+ return True
+ return False
+
+ @plugin_stats_decorator(plugin_name="斗鱼直播")
+ @plugin_points_cost(1, "斗鱼提醒消耗积分", FEATURE_KEY)
+ async def process_message(self, message: Dict[str, Any]) -> Tuple[bool, Optional[str]]:
+ content = str(message.get("content", "")).strip()
+ sender = message.get("sender")
+ roomid = message.get("roomid", "")
+ gbm: GroupBotManager = message.get("gbm")
+ self.bot: WechatAPIClient = message.get("bot")
+ if roomid and gbm.get_group_permission(roomid, self.feature) == PermissionStatus.DISABLED:
+ return False, "没有权限"
+ if content.startswith("订阅斗鱼"):
+ parts = content.split()
+ if len(parts) < 2:
+ await self.bot.send_text_message(roomid or sender, "请提供房间号,例如:订阅斗鱼 7718843", sender)
+ return True, "命令格式错误"
+ room_id = parts[1].strip()
+ ok = self.redis_manager.add_group_room(roomid or sender, room_id)
+ await self.bot.send_text_message(roomid or sender, f"✅ 已订阅斗鱼房间 {room_id}", sender)
+ return True, "订阅成功" if ok else "订阅失败"
+ if content.startswith("取消订阅斗鱼"):
+ parts = content.split()
+ if len(parts) < 2:
+ await self.bot.send_text_message(roomid or sender, "请提供房间号,例如:取消订阅斗鱼 7718843", sender)
+ return True, "命令格式错误"
+ room_id = parts[1].strip()
+ ok = self.redis_manager.remove_group_room(roomid or sender, room_id)
+ await self.bot.send_text_message(roomid or sender, f"✅ 已取消订阅斗鱼房间 {room_id}", sender)
+ return True, "取消成功" if ok else "取消失败"
+ if content.startswith("斗鱼订阅列表"):
+ rooms = self.redis_manager.list_group_rooms(roomid or sender)
+ if not rooms:
+ await self.bot.send_text_message(roomid or sender, "暂无订阅", sender)
+ return True, "暂无订阅"
+ text = "当前订阅的斗鱼房间:\n" + "\n".join(rooms)
+ await self.bot.send_text_message(roomid or sender, text, sender)
+ return True, "列表已发送"
+ return False, None
+
+ async def _scheduled_check_job(self):
+ try:
+ rooms = self.redis_manager.all_subscribed_rooms()
+ if not rooms:
+ return
+ async with aiohttp.ClientSession() as session:
+ for room_id in rooms:
+ try:
+ url = self._api_template.format(room_id=room_id)
+ headers = {
+ "User-Agent": self._user_agent,
+ "Referer": f"https://www.douyu.com/{room_id}"
+ }
+ async with session.get(url, headers=headers, timeout=aiohttp.ClientTimeout(total=10)) as resp:
+ data = await resp.json(content_type=None)
+ room_info = data.get("room", {}) if isinstance(data, dict) else {}
+ show_status = room_info.get("show_status")
+ nickname = room_info.get("nickname", "")
+ room_name = room_info.get("room_name", "")
+ prev = self.redis_manager.get_room_status(room_id) or {}
+ prev_live = prev.get("is_live")
+ curr_live = True if show_status == 1 else False
+ status_obj = {
+ "is_live": curr_live,
+ "nickname": nickname,
+ "room_name": room_name
+ }
+ self.redis_manager.set_room_status(room_id, status_obj)
+ if prev_live is None and curr_live is False:
+ continue
+ if prev_live is None and curr_live is True:
+ await self._notify_groups_live(room_id, nickname, room_name)
+ continue
+ if prev_live is False and curr_live is True:
+ await self._notify_groups_live(room_id, nickname, room_name)
+ continue
+ if prev_live is True and curr_live is False:
+ await self._notify_groups_offline(room_id, nickname, room_name)
+ continue
+ await asyncio.sleep(0.1)
+ except Exception as e:
+ logger.error(f"斗鱼检查失败: {e}")
+ continue
+ except Exception as e:
+ logger.error(f"斗鱼定时任务异常: {e}")
+
+ async def _notify_groups_live(self, room_id: str, nickname: str, room_name: str):
+ groups = self.redis_manager.groups_for_room(room_id)
+ text = f"斗鱼直播提醒:{nickname} 开播了\n标题:{room_name}\n地址:https://www.douyu.com/{room_id}"
+ for gid in groups:
+ if GroupBotManager.get_group_permission(gid, self.feature) == PermissionStatus.ENABLED:
+ try:
+ await self.bot.send_text_message(gid, text)
+ except Exception as e:
+ logger.error(f"发送斗鱼开播提醒失败: {e}")
+ continue
+
+ async def _notify_groups_offline(self, room_id: str, nickname: str, room_name: str):
+ groups = self.redis_manager.groups_for_room(room_id)
+ text = f"斗鱼直播提醒:{nickname} 下播了\n标题:{room_name}"
+ for gid in groups:
+ if GroupBotManager.get_group_permission(gid, self.feature) == PermissionStatus.ENABLED:
+ try:
+ await self.bot.send_text_message(gid, text)
+ except Exception as e:
+ logger.error(f"发送斗鱼下播提醒失败: {e}")
+ continue
diff --git a/test/douyu.py b/test/douyu.py
new file mode 100644
index 0000000..7d692ca
--- /dev/null
+++ b/test/douyu.py
@@ -0,0 +1,63 @@
+import requests
+import time
+
+# 配置信息
+ROOM_ID = "52876"
+CHECK_INTERVAL = 300 # 5分钟 = 300秒
+HEADERS = {
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
+ "Referer": f"https://www.douyu.com/{ROOM_ID}"
+}
+
+
+class DouyuMonitor:
+ def __init__(self, room_id):
+ self.room_id = room_id
+ self.api_url = f"https://www.douyu.com/betard/{room_id}"
+ self.is_live = False # 记录当前直播状态
+
+ def check_status(self):
+ try:
+ # 发送请求
+ response = requests.get(self.api_url, headers=HEADERS, timeout=10)
+ data = response.json()
+ print(data)
+ # 提取房间信息和状态
+ room_info = data.get("room", {})
+ show_status = room_info.get("show_status") # 1 为开播
+ room_name = room_info.get("room_name", "无标题")
+ nickname = room_info.get("nickname", "未知主播")
+
+ # 逻辑判定
+ if show_status == 1:
+ if not self.is_live:
+ print(f"【通知】主播 {nickname} 开播了!标题:{room_name}")
+ self.send_desktop_notification(nickname, room_name)
+ self.is_live = True
+ else:
+ print(f"[{time.strftime('%H:%M:%S')}] 主播正在直播中...")
+ else:
+ if self.is_live:
+ print(f"[{time.strftime('%H:%M:%S')}] 主播下播了。")
+ self.is_live = False
+ print(f"[{time.strftime('%H:%M:%S')}] 主播尚未开播。")
+
+ except Exception as e:
+ print(f"查询出错: {e}")
+
+ def send_desktop_notification(self, streamer, title):
+ """发送系统桌面通知"""
+ print(f"斗鱼直播提醒: {streamer}" + f"你关注的主播开播啦!\n标题:{title}"
+ )
+
+
+if __name__ == "__main__":
+ monitor = DouyuMonitor(ROOM_ID)
+ print(f"开始监控直播间: {ROOM_ID},每 5 分钟检查一次...")
+
+ while True:
+ monitor.check_status()
+ time.sleep(CHECK_INTERVAL)
+
+
+
diff --git a/utils/wechat/message.txt b/utils/wechat/message.txt
index 83ee44c..2c2b8ef 100644
--- a/utils/wechat/message.txt
+++ b/utils/wechat/message.txt
@@ -1 +1,301 @@
2026-01-19 14:56:28.366 | DEBUG | robot:_wechat_ipad_core:274 - MESSAGE:{'ModUserInfos': None, 'ModContacts': [{'UserName': {'string': '56594698995@chatroom'}, 'NickName': {'string': 'WeChat Robot'}, 'PyInitial': {'string': 'WECHATROBOT'}, 'QuanPin': {'string': 'WeChatRobot'}, 'Sex': 0, 'ImgBuf': {'iLen': 0}, 'BitMask': 4294967295, 'BitVal': 2, 'ImgFlag': 1, 'Remark': {}, 'RemarkPyinitial': {}, 'RemarkQuanPin': {}, 'ContactType': 0, 'RoomInfoCount': 0, 'DomainList': [{}], 'ChatRoomNotify': 0, 'AddContactScene': 0, 'PersonalCard': 0, 'HasWeiXinHdHeadImg': 0, 'VerifyFlag': 0, 'Level': 0, 'Source': 0, 'ChatRoomOwner': 'wxid_b28npmhznnwl12', 'WeiboFlag': 0, 'AlbumStyle': 0, 'AlbumFlag': 0, 'SnsUserInfo': {'SnsFlag': 0, 'SnsBgobjectId': 0, 'SnsFlagEx': 0}, 'CustomizedInfo': {'BrandFlag': 0}, 'AdditionalContactList': {'LinkedinContactItem': {}}, 'ChatroomMaxCount': 10624, 'DeleteFlag': 0, 'Description': '\x08�\x01\x12\x1c\n\x13wxid_b28npmhznnwl120\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_7bpstqonj922120\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_45qclaghhim5220\x01@\x00�\x01\x00\x12\x10\n\x07hengist0\t@\x00�\x01\x00\x12\x1c\n\x13wxid_28vy4rytnl5a120\x01@\x00�\x01\x00\x12\x17\n\rxiehuaping6680�\x10@\x00�\x01\x00\x12\x16\n\rweipeng_Angus0\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_ur8bdioku6k0210\x01@\x00�\x01\x00\x12\x18\n\x0eiversonyanghan0�@@\x00�\x01\x00\x12\x14\n\nq2546693290�@@\x00�\x01\x00\x12\x1c\n\x13wxid_3vsb0fy2idri220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_jcdu1qygioqs220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_gkgrj231lhoa120\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_7dky6wp3hg9u220\x01@\x00�\x01\x00\x12\x17\n\rlzm15114166560�@@\x00�\x01\x00\x12\x1d\n\x13wxid_qgml5g7x6o3r220�@@\x00�\x01\x00\x12\x11\n\x08lw9918260\x01@\x00�\x01\x00\x12\x13\n\nz6143872660\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_613jq8n1n6bg120\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_d52rxumg20z0220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_gkku6w4sg4je220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_8m7go53ytrya220\x01@\x00�\x01\x00\x12\x11\n\x08moyinlgq0\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_gqhxp9ipfxv2220\x01@\x00�\x01\x00\x12\x1d\n\x13wxid_5qfinnohy0yk290�@@\x00�\x01\x00\x12\x1c\n\x13wxid_6q3ar4xb7m19220\t@\x00�\x01\x00\x12\x1c\n\x13wxid_7lrsknh1zvpw220\x01@\x00�\x01\x00\x12\x1c\n\x12wxid_93418234201120�@@\x00�\x01\x00\x12\x1c\n\x13wxid_ovdiwcveyc9x220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_8m3h0yofz6dr220\x01@\x00�\x01\x00\x12\x1d\n\x13wxid_q9g3216s6tdo720�@@\x00�\x01\x00\x12\x10\n\x07fengch10\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_gol6pf6fq4se210\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_8w7uvwatvyhi220\x01@\x00�\x01\x00\x12\x12\n\tjieke62570\x11@\x00�\x01\x00\x12\x1c\n\x13wxid_5rdsdy7uf8th120\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_a0jwxfkuq9o4120\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_z7qkrszzrfu0220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_wcz8ygnlj3kk220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_i0llb0sn41cs210\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_cieka88s98pg290\x01@\x00�\x01\x00\x12\x19\n\x0fweipeng198510120�@@\x00�\x01\x00\x12\x1c\n\x13wxid_nkl05ua5519u210\x01@\x00�\x01\x00\x12\x12\n\txueqiqius0\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_bfxrmdtepwx1120\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_ceqges4ueykg220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_rm8cr2qjf45n120\x11@\x00�\x01\x00\x12\x1c\n\x13wxid_ubo0cy5xh4px220\x01@\x00�\x01\x00\x12\x1d\n\x13wxid_d439rfxsetl2110�@@\x00�\x01\x00\x12\x10\n\x07mumutoy0\x01@\x00�\x01\x00\x12\x14\n\x0bcjl264079640\t@\x00�\x01\x00\x12\x1c\n\x13wxid_751hg5yu70rf220\x01@\x00�\x01\x00\x12\x12\n\ti______ck0\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_c7vgz2gd7uml220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_93d0t3p61s06220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_ascibcwgliyk220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_sj8wz01la47v220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_yl84hx6o9svi220\x01@\x00�\x01\x00\x12\x11\n\x08a78917490\x01@\x00�\x01\x00\x12\x11\n\x07orrinjj0�@@\x00�\x01\x00\x12\x1c\n\x13wxid_f92ilzlsjlka220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_0ycf7d3d506t220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_sqsom5i07fd4220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_cur3larj3ikj120\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_wx4l3fhkudu0220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_1s8pwoa9rl6f210\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_vqkeovas303o220\x01@\x00�\x01\x00\x12\x10\n\x07jundayw0\t@\x00�\x01\x00\x12\x1b\n\x12wxid_71360213601120\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_ljv0fz399msu220\x01@\x00�\x01\x00\x12\x10\n\x07Jyunere0\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_xwemtsyy8fxr220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_0uwy2vxgw57v220\x01@\x00�\x01\x00\x12\x12\n\tqq50005210\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_260emr01m55d220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_yfqkjgku4hgm220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_a7olcpwehqnh220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_72ow1edm3kea220\x01@\x00�\x01\x00\x12\x13\n\nhuage100600\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_01tuau75pj1w220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_rxr1t6rgy663220\x01@\x00�\x01\x00\x12\x11\n\x08rayxu0010\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_7wnuussanu6s210\x11@\x00�\x01\x00\x12\x1c\n\x13wxid_gn9vcg4a5fgp220\x11@\x00�\x01\x00\x12\x1b\n\x12juhuakaipinggai0020\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_royxrybbzq5j220\x01@\x00�\x01\x00\x12\x15\n\x0cxiao813977830\x01@\x00�\x01\x00\x12\x10\n\x07allofee0\t@\x00�\x01\x00\x12\x1c\n\x13wxid_yyo4v1mtwra6220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_p2bos0iwsbg9220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_j846ymvp431j120\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_mn36thj7nujx220\x01@\x00�\x01\x00\x12\x11\n\x08zbigbird0\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_h8e0wsyosnwb220\x01@\x00�\x01\x00\x12\x13\n\nyl199308220\x01@\x00�\x01\x00\x12\x14\n\x0byang_guang_0\x01@\x00�\x01\x00\x12\x16\n\rshoujilei33790\x01@\x00�\x01\x00\x12\x1d\n\x13wxid_pn9dhmuthc2v220�@@\x00�\x01\x00\x12\x1d\n\x13wxid_jn599o1zscbj220�@@\x00�\x01\x00\x12\x1c\n\x13wxid_cjtx8ouwtv9n210\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_vy6sir5dchx4220\x01@\x00�\x01\x00\x12\x10\n\x07cgd93930\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_lmimu17ixpbc210\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_ngux2qfqjmuj220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_kr8wlfz7eb2i220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_y17nryqd5ia3220\x01@\x00�\x01\x00\x12\x1c\n\x12wxid_79173591730120�@@\x00�\x01\x00\x12\x1c\n\x13wxid_neg6p4c62len220\x01@\x00�\x01\x00\x12\x10\n\x07t_glove0\x01@\x00�\x01\x00\x12\x13\n\noooeovlooo0\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_z3ry87638gws320\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_p1oxwu3nd166220\x19@\x00�\x01\x00\x12\x16\n\rcaiwanlingcwl0\x01@\x00�\x01\x00\x12\x10\n\x07anvaest0\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_xxci433b377z210\x01@\x00�\x01\x00\x12\x12\n\tIceCry6130\x01@\x00�\x01\x00\x12\x1d\n\x13wxid_ygk83i2r1son220�@@\x00�\x01\x00\x12\x13\n\nJason223090\x01@\x00�\x01\x00\x12\x11\n\x08Rs_Close0\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_27eirern20rf210\x01@\x00�\x01\x00\x12\x12\n\tyuhai02070\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_w0l2tecoao7s120\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_2ci458bc6nq2220\t@\x00�\x01\x00\x12\x1c\n\x13wxid_q8h65hcwg1au220\x01@\x00�\x01\x00\x12\x1d\n\x13wxid_ncpfzn22lfea220�@@\x00�\x01\x00\x12\x1b\n\x12wxid_29057190613120\x11@\x00�\x01\x00\x12\x17\n\x0etaotaolinangel0\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_0a3mxmfywr8h220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_2lhx7btefa0d220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_7fvd551co49e220\x01@\x00�\x01\x00\x12\x1d\n\x13wxid_ss80k7krfrny210�@@\x00�\x01\x00\x12\x16\n\rAinidechouren0\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_x1ihnent6tja210\x01@\x00�\x01\x00\x12\x1f\n\x13wxid_vprfp0sk2o7y220���\x03@\x00�\x01\x00\x12\x15\n\x0cliu6750613700\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_h8huak2oddw2210\x01@\x00�\x01\x00\x12\x0f\n\x06X-soda0\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_bzfe8nljjiut220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_czirx17x34lm220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_bs86nlwhmblw220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_lvr6jsapco5d220\x01@\x00�\x01\x00\x12\x1d\n\x13wxid_bnhk86sf8kpw220�@@\x00�\x01\x00\x12\x10\n\x07scottuk0\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_y89gujlu6ed4220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_d1l7bybc3bun220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_2pw7xkmr1fqz220\x01@\x00�\x01\x00\x12\x1b\n\x12wxid_76874268763120\x01@\x00�\x01\x00\x12\x10\n\x07wan74260\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_5v7cey0mar9q220\x01@\x00�\x01\x00\x12\x1d\n\x13wxid_t8p67vpimx0d220�@@\x00�\x01\x00\x12\x13\n\nQ8442990350\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_dg5xnz4s39ea210\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_uy2nvj1es6fa220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_pgrtm7al7hja120\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_g4p84xthi1qt220\x01@\x00�\x01\x00\x12\x10\n\x07hecarli0\t@\x00�\x01\x00\x12\x1c\n\x13wxid_kbur705rdkt7220\x01@\x00�\x01\x00\x12\x14\n\x0bchengke19910\x01@\x00�\x01\x00\x12\x15\n\x0cpei3896628320\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_3ndsct6d4dpn220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_gvh0lj2bqgk3120\x01@\x00�\x01\x00\x12\x11\n\x08sencn0010\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_sh3e2dicv2j1220\x11@\x00�\x01\x00\x12\x1d\n\x13wxid_nk2aqc0mrfdb220�@@\x00�\x01\x00\x12\x1c\n\x13wxid_qsodqeep234e220\x01@\x00�\x01\x00\x12\x17\n\x0efengchenhao0020\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_s0aqakkybuek220\x19@\x00�\x01\x00\x12\x1c\n\x12wodeyouxiangyuyuan0�@@\x00�\x01\x00\x12\x1c\n\x13wxid_ukjx9z9wv8sl220\x01@\x00�\x01\x00\x12\x11\n\x08juliy3330\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_0jnwhnvi1u0d220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_01gk363emfno220\x01@\x00�\x01\x00\x12\x10\n\x07NYLiuZC0\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_e6es87wvw19u220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_0c1entrdaiad220\x01@\x00�\x01\x00\x12\x1b\n\x12wxid_19203891960120\t@\x00�\x01\x00\x12\x1c\n\x13wxid_pv09ly03dih2210\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_s6gshn8zhxms720\x01@\x00�\x01\x00\x12\x0f\n\x06fj_cqv0\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_ij6r44u5e438290\x01@\x00�\x01\x00\x12\x1d\n\x13wxid_243qcni3r6z3220�@@\x00�\x01\x00\x12\x1c\n\x13wxid_yrsl9joj8ise220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_7eadcgb6a50a210\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_kiymanw33ec5220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_0uy71ovzj4an220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_cqoaubiun76m220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_10sjbvsfb7wv220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_vg6uoeoprom5210\x01@\x00�\x01\x00\x12\x14\n\x0bmm24lizheng0\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_m7lw5243o1h5220\x01@\x00�\x01\x00\x12\x1c\n\x12wxid_38262282622120�@@\x00�\x01\x00\x12\x1c\n\x13wxid_tee841t4hika220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_ax1e145kufqc220\x01@\x00�\x01\x00\x12\x14\n\x0bwangzi_87880\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_n9o58gpxs1gm220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_y6bh6w5o3jut220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_gvr9a3le939h220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_ppmfbcc7wcaq220\x01@\x00�\x01\x00\x12\x1d\n\x13wxid_xw9hl7rgz4tx220�@@\x00�\x01\x00\x12\x1c\n\x13wxid_l4dl6rd07yk9220\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_s0kclz1rpoek220\x01@\x00�\x01\x00\x12\x11\n\x08depth7100\x01@\x00�\x01\x00\x12\x0f\n\x06cxgwbk0\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_i73nrnun919k120\x01@\x00�\x01\x00\x12\x1c\n\x13wxid_cpc62y9t7ehs220\x01@\x00�\x01\x00\x12\x1b\n\x12wxid_nu7hfab1vn5220\x01@\x00�\x01\x00\x12\x0f\n\x06denbyn0\x01@\x00�\x01\x00\x12\x18\n\x0efletcher0253090�@@\x00�\x01\x00\x12\x1c\n\x13wxid_y7rn91nab9zg220\x01@\x00�\x01\x00\x18\x01"\x00(\x008\x00', 'ChatroomStatus': 13, 'Extflag': 0, 'ChatRoomBusinessType': 0}], 'DelContacts': None, 'ModUserImgs': None, 'FunctionSwitchs': None, 'UserInfoExts': None, 'AddMsgs': None, 'ContinueFlag': 2097408, 'KeyBuf': {'iLen': 354, 'buffer': 'CC8SCAgBELK9zIsDEgQIZRAAEgYIAhDk5B8SBAhmEAASBAgNEAASBQjMARAAEggIAxCOvcyLAxIECGcQABIICAsQtL3MiwMSBAhvEAASBAgEEAASBAhoEAASBAgFEAASBAhpEAASBAgHEAASBAhrEAASBAgIEAASBAhsEAASBAgJEAASBAhtEAASCAgWELG1zIsDEgQIBhAAEgQIehAAEgQIahAAEgQIEBAAEgQIERAAEgQIchAAEggIDhDJgcyLAxIECHAQABIGCBMQreQCEgQIGhAAEgYIGxDk5B8SCAgYEJOrt8sGEggIFxCu+PvKBhIGCBkQ5OQfEgQIChAAEgkIyQEQk6u3ywYSBQjNARAAEgkIygEQq/izywYSCQjLARCbq7fLBhIFCM4BEGUSBQjPARAAEgQIFBAAEgQIFRAAEgkI6AcQ4fu2ywYSCQjpBxCairfLBhIJCNMPEJKTt8sG'}, 'Status': 1, 'Continue': 697507902, 'Time': 1768805787, 'UnknownCmdId': '', 'Remarks': '出现未解析的CmdId类型数据,请联系客服人员处理。'}
+
+
+
+ 正在直播:快乐DOTA!,请点击观看
+
+ 主播: 龚建ZSMJ
+
+
+ view
+ 5
+ 0
+
+ https://m.douyu.com/52876?share_source=1&dyshci=3&app_type=and&fromuid=251679944&dyshid=f0054c8-618d0d36a18ce969bd03163400507111&medium=wx&dyshti=1769070814&type=lv
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+ 3057020100044b3049020100020420fd389002032df7950204f75d06af02046971e0e3042434633435633732632d613231312d346162392d383465382d3066323939333736646261660204051808030201000405004c51e500
+ 5a2d851cd5d8b6f13e628583c1ce9a9c
+ 16402
+ 136
+ 136
+ ef12efd449e398bf428dd0f9f93de2e3
+ ef12efd449e398bf428dd0f9f93de2e3
+ 1
+
+ 0
+
+
+ 2
+
+
+
+
+
+ 0
+
+
+
+ 0
+
+
+
+ 0
+ null
+
+
+
+ 0
+ null
+ null
+
+
+ 0
+ null
+
+
+
+
+
+
+
+
+
+ 5a2d851cd5d8b6f13e628583c1ce9a9c
+
+
+
+
+ 0
+ 0
+
+ 136
+ 136
+ 0
+
+
+ GhQKEnd4NmJlODRkNTMyZjE5MjY5OA==
+
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+
+
+
+ 0
+
+ 0
+
+
+
+ 0
+
+
+
+ -1
+
+
+
+ 0
+ -1
+ 0
+
+
+
+ 0
+ null
+ null
+
+
+ 0
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ false
+
+
+
+ null
+
+
+ 0
+ 0
+ 0
+
+ 0
+
+ Jyunere
+ 0
+
+ 30
+ 斗鱼
+
+
+
\ No newline at end of file
diff --git a/wechat_ipad/models/appmsg_xml.py b/wechat_ipad/models/appmsg_xml.py
index 9f10fcc..16417b3 100644
--- a/wechat_ipad/models/appmsg_xml.py
+++ b/wechat_ipad/models/appmsg_xml.py
@@ -241,3 +241,168 @@ LINK_XML_NEWS = """
"""
+
+DOUYU_MESSAGE_XML ="""
+
+ 正在直播:{title},请点击观看
+ 主播: {liver}
+
+ view
+ 5
+ 0
+
+ https://m.douyu.com/{roomid}?share_source=1&dyshci=3&app_type=and&fromuid=251679944&dyshid=f0054c8-618d0d36a18ce969bd03163400507111&medium=wx&dyshti=1769070814&type=lv
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+ 2
+
+
+
+
+
+ 0
+
+
+
+ 0
+
+
+
+ 0
+ null
+
+
+
+ 0
+ null
+ null
+
+
+ 0
+ null
+
+
+
+
+
+
+
+
+
+ 5a2d851cd5d8b6f13e628583c1ce9a9c
+
+
+
+
+ 0
+ 0
+
+ 136
+ 136
+ 0
+
+
+ GhQKEnd4NmJlODRkNTMyZjE5MjY5OA==
+
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+ 0
+
+
+
+ 0
+
+ 0
+
+
+
+ 0
+
+
+
+ -1
+
+
+
+ 0
+ -1
+ 0
+
+
+
+ 0
+ null
+ null
+
+
+ 0
+
+
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ false
+
+
+
+ null
+
+
+ 0
+ 0
+ 0
+
+ 0
+
+Jyunere
+0
+
+ 30
+ 斗鱼
+
+
+"""