完善 python 和 node Demo

This commit is contained in:
Muihd
2025-04-30 22:53:19 +08:00
parent 1835f70b23
commit afc1303f11
11 changed files with 1468 additions and 380 deletions
-291
View File
@@ -1,291 +0,0 @@
# ruff: noqa: F401,F403,F405,E402,F541,E722
import asyncio
import websockets
import json
import os
import ctypes
import sys
import time
import winreg
import tkinter as tk
from tkinter import ttk
import customtkinter
import subprocess
import random
import threading
import atexit
import psutil
import queue
# 创建一个队列
gui_queue = queue.Queue()
# 创建一个线程安全的标志
stop_flag = threading.Event()
def is_admin():
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
def disable_proxy():
internet_settings = winreg.OpenKey(
winreg.HKEY_CURRENT_USER,
r"Software\Microsoft\Windows\CurrentVersion\Internet Settings",
0,
winreg.KEY_ALL_ACCESS,
)
# 设置代理使能为0(禁用)
winreg.SetValueEx(internet_settings, "ProxyEnable", 0, winreg.REG_DWORD, 0)
# 清空代理服务器信息
winreg.SetValueEx(internet_settings, "ProxyServer", 0, winreg.REG_SZ, "")
winreg.CloseKey(internet_settings)
print("Proxy disabled.")
def initGame():
print("Init game.")
pass
class App(customtkinter.CTk):
def __init__(self):
super().__init__()
self.title("dy-barrage-grab-log-window")
self.geometry("800x600")
self.grid_columnconfigure((0, 1), weight=1)
self.grid_rowconfigure(0, weight=1)
self.LogFrame = LogFrame(self)
self.LogFrame.grid(row=0, column=0, sticky="nsew")
class LogFrame(customtkinter.CTkFrame):
def __init__(self, master):
super().__init__(master)
# 创建一个Frame来包含treeview和滚动条
self.tree_frame = ttk.Frame(self)
self.tree_frame.grid(row=0, column=0, sticky="nsew", padx=50, pady=50)
# 创建一个滚动条
self.scrollbar = customtkinter.CTkScrollbar(self.tree_frame)
self.scrollbar.grid(row=0, column=1, sticky="ns")
self.treeview = ttk.Treeview(
self.tree_frame,
columns=("Type", "User ID", "User Nickname", "Content"),
show="headings",
height=20,
yscrollcommand=self.scrollbar.set, # 将滚动条与treeview关联
)
self.treeview.grid(row=0, column=0, sticky="nsew")
# 设置滚动条的命令为移动treeview
self.scrollbar.configure(command=self.treeview.yview)
# 设置列宽
self.treeview.column("Type", width=50)
self.treeview.column("User ID", width=100)
self.treeview.column("User Nickname", width=100)
self.treeview.column("Content", width=450)
self.treeview.heading("Type", text="Type")
self.treeview.heading("User ID", text="User ID")
self.treeview.heading("User Nickname", text="User Nickname")
self.treeview.heading("Content", text="Content")
# 设置不同类型的颜色
self.treeview.tag_configure("type1", foreground="black")
self.treeview.tag_configure("type2", foreground="cyan")
self.treeview.tag_configure("type3", foreground="gold")
self.treeview.tag_configure("type4", foreground="blue")
self.treeview.tag_configure("type5", foreground="red")
self.treeview.tag_configure("type6", foreground="purple")
self.treeview.tag_configure("type7", foreground="green")
self.treeview.tag_configure("type8", foreground="orange")
self.treeview.tag_configure("type9", foreground="gray")
# 添加更多类型的颜色配置...
def display_message(self, message):
parsed_message = json.loads(message)
message_type = parsed_message.get("Type")
data_str = parsed_message.get("Data", "{}")
try:
data = json.loads(data_str)
except json.JSONDecodeError:
print(f"Cannot parse 'Data' as JSON: {data_str}")
return
user = data.get("User", {})
if user is None:
# print(f"'User' is None in 'Data': {data_str}")
user = {"Id": "无", "Nickname": "无"}
user_id = user.get("Id", "")
user_nickname = user.get("Nickname", "")
content = data.get("Content", "")
# 根据类型设置颜色
color_tag = f"type{message_type}"
message_type_str = [
"无",
"弹幕",
"点赞",
"进房",
"关注",
"礼物",
"统计",
"粉团",
"分享",
"下播",
]
self.treeview.insert(
"",
"end",
values=(
message_type_str[message_type],
user_id,
user_nickname,
content,
),
tags=(color_tag,),
)
# async def send_ping(websocket):
# while True:
# try:
# if websocket.open:
# await websocket.ping()
# await asyncio.sleep(5)
# else:
# break
# except websockets.exceptions.ConnectionClosedOK:
# # 连接已关闭,尝试重新连接
# websocket = await websockets.connect("ws://127.0.0.1:8888")
async def receive_messages():
while True:
try:
async with websockets.connect(
"ws://127.0.0.1:8888", ping_timeout=None, ping_interval=None
) as websocket:
while True:
message = await websocket.recv()
if message is not None:
try:
json.loads(message)
app.LogFrame.display_message(message)
except json.JSONDecodeError:
print(
f"Received a message that could not be parsed as JSON: {message}"
)
except (
websockets.ConnectionClosed,
websockets.exceptions.ConnectionClosedError,
websockets.exceptions.ConnectionClosedOK,
) as e:
print(f"Connection closed, retrying...{e}")
continue
except Exception as e:
print(f"An error occurred on ws server: {e}")
continue
def main():
global listener_process
global app
# Check if the process is already running
for proc in psutil.process_iter():
if proc.name() == "WssBarrageServer.exe":
print("The process is already running.")
proc.kill()
time.sleep(1)
# Start a new process
# 将WssBarrageServer.exe放至同目录下dy-barrage-grab文件夹
# 获取当前脚本的绝对路径
script_dir = os.path.dirname(os.path.realpath(__file__))
# 构建WssBarrageServer.exe的绝对路径
exe_path = os.path.join(script_dir, "dy-barrage-grab", "WssBarrageServer.exe")
# 使用绝对路径启动进程
listener_process = subprocess.Popen(exe_path)
# 创建一个新的事件循环
loop = asyncio.new_event_loop()
# 设置这个事件循环为当前线程的事件循环
asyncio.set_event_loop(loop)
app = App()
# 点击关闭按钮时调用的函数
def on_close():
print("Closing...")
# 设置停止标志
stop_flag.set()
# 关闭WssBarrageServer
listener_process.terminate()
# 关闭代理
disable_proxy()
# 退出程序
os._exit(0)
# 设置关闭按钮的回调函数
app.protocol("WM_DELETE_WINDOW", on_close)
# 在事件循环中创建新的异步任务
loop.create_task(receive_messages())
def update():
# 更新Tkinter的界面
app.update()
# 在事件循环中定期调用update方法
loop.call_soon(update)
# 检查队列中是否有任务
while not gui_queue.empty():
# 获取任务并执行
task = gui_queue.get()
task()
# 在事件循环中定期调用update方法
loop.call_soon(update)
try:
# 运行事件循环
loop.run_forever()
except Exception as e:
print(f"An error occurred in loop: {e}")
finally:
# 关闭事件循环
loop.close()
if __name__ == "__main__":
if is_admin():
# 如果已经是管理员权限,那么直接运行你的代码
print("Running as administrator.")
pass
else:
# 如果不是管理员权限,那么以管理员权限重新启动程序
print("Running as non-administrator.")
ctypes.windll.shell32.ShellExecuteW(
None, "runas", sys.executable, " ".join(sys.argv), None, 1
)
# try:
main()
# except Exception as e:
# print(f"An error occurred: {e}")
# finally:
# # 这里结束进程
# listener_process.terminate()
# 注册一个函数,在程序结束时调用
def on_exit():
listener_process.terminate()
atexit.register(on_exit)
+167
View File
@@ -0,0 +1,167 @@
from enum import Enum, IntEnum
from typing import Optional, Dict, Any, List, Union
from dataclasses import dataclass, field
# 枚举类型定义
class PackMsgType(IntEnum):
"""消息类型枚举"""
无 = 0
弹幕消息 = 1
点赞消息 = 2
进直播间 = 3
关注消息 = 4
礼物消息 = 5
直播间统计 = 6
粉丝团消息 = 7
直播间分享 = 8
下播 = 9
class Gender(IntEnum):
"""性别枚举"""
未知 = 0
男 = 1
女 = 2
def to_string(self) -> str:
"""将性别枚举转换为中文字符串"""
if self == Gender.男:
return "男"
elif self == Gender.女:
return "女"
else:
return "妖"
class FansclubType(IntEnum):
"""粉丝团消息类型"""
无 = 0
粉丝团升级 = 1
加入粉丝团 = 2
class ShareType(IntEnum):
"""直播间分享目标"""
未知 = 0
微信 = 1
朋友圈 = 2
微博 = 3
QQ空间 = 4
QQ = 5
抖音好友 = 112
class EnterType(IntEnum):
"""观众的进入方式"""
正常进入 = 0
通过分享进入 = 6
# 数据类定义
@dataclass
class FansClubInfo:
"""粉丝团信息"""
ClubName: str = ""
Level: int = 0
@dataclass
class MsgUser:
"""用户信息"""
Id: int = 0
IsAdmin: bool = False
IsAnchor: bool = False
ShortId: int = 0
DisplayId: str = ""
Nickname: str = "匿名用户"
Level: int = 0
PayLevel: int = 0
Gender: Gender = Gender.未知
HeadImgUrl: str = ""
SecUid: str = ""
FansClub: Optional[FansClubInfo] = None
FollowerCount: int = 0
FollowStatus: int = 0
FollowingCount: int = 0
def gender_to_string(self) -> str:
"""返回性别的中文表示"""
return Gender(self.Gender).to_string()
@dataclass
class RoomAnchorInfo:
"""直播间主播信息"""
UserId: str = ""
SecUid: str = ""
Nickname: str = ""
HeadUrl: str = ""
FollowStatus: int = 0
@dataclass
class Msg:
"""基础消息类"""
MsgId: int = 0
User: MsgUser = field(default_factory=MsgUser)
Owner: Optional[RoomAnchorInfo] = None # 修正字段名称
Content: str = ""
RoomId: str = ""
WebRoomId: str = ""
RoomTitle: str = ""
IsAnonymous: bool = False
Appid: str = ""
@dataclass
class LikeMsg(Msg):
"""点赞消息"""
Count: int = 0
Total: int = 0
@dataclass
class GiftMsg(Msg):
"""礼物消息"""
GiftId: int = 0
GiftName: str = ""
GroupId: int = 0
GiftCount: int = 0
RepeatCount: int = 0
DiamondCount: int = 0 # 抖币价格
Combo: bool = False # 该礼物是否可连击
ImgUrl: str = "" # 礼物图片地址
ToUser: Optional[MsgUser] = None # 送礼目标(连麦直播间有用)
GiftValue: int = 0 # 在原Python代码中使用的礼物价值字段
@dataclass
class MemberMessage(Msg):
"""进入直播间消息"""
CurrentCount: int = 0
EnterTipType: int = 0
@dataclass
class UserSeqMsg(Msg):
"""直播间统计消息"""
OnlineUserCount: int = 0
TotalUserCount: int = 0
TotalUserCountStr: str = "0"
OnlineUserCountStr: str = "0"
@dataclass
class FansclubMsg(Msg):
"""粉丝团消息"""
Type: int = 0 # 粉丝团消息类型,升级1,加入2
Level: int = 0 # 粉丝团等级
FansClubName: str = "" # 粉丝团名称
@dataclass
class ShareMessage(Msg):
"""直播间分享"""
ShareType: ShareType = ShareType.未知
# 全局统计数据类
@dataclass
class LiveStats:
"""直播间统计数据"""
total_likes: int = 0
total_users: int = 0
male_users: int = 0
female_users: int = 0
def reset(self) -> None:
"""重置统计数据"""
self.total_likes = 0
self.total_users = 0
self.male_users = 0
self.female_users = 0
+245
View File
@@ -0,0 +1,245 @@
import asyncio
import websockets
import json
import time
from datetime import datetime
from typing import Dict, Any
from colorama import init, Fore, Style
from entities import (
PackMsgType, Gender, LiveStats, LikeMsg, MemberMessage, UserSeqMsg,
GiftMsg, FansclubMsg, ShareMessage, ShareType
)
from parsers import MessageParser
'''
抖音直播间消息处理脚本
消息类型说明:
1[普通弹幕]|2[点赞消息]|3[进入直播间]|4[关注消息]|5[礼物消息]|6[统计消息]|7[粉丝团消息]|8[直播间分享]|9[下播]
全局统计变量:
Live_Total - 本场点赞数
Live_user - 本场总观看人数
Live_man - 本场男生人数
Live_woman - 本场女生人数
'''
# 初始化彩色输出
init(autoreset=True)
# 颜色定义
COLOR_MAP = {
PackMsgType.弹幕消息: Fore.CYAN, # 青色
PackMsgType.点赞消息: Fore.YELLOW, # 黄色
PackMsgType.进直播间: Fore.GREEN, # 绿色
PackMsgType.关注消息: Fore.MAGENTA, # 洋红色
PackMsgType.礼物消息: Fore.RED, # 红色
PackMsgType.直播间统计: Fore.BLUE, # 蓝色
PackMsgType.粉丝团消息: Fore.LIGHTBLUE_EX, # 浅蓝色
PackMsgType.直播间分享: Fore.LIGHTMAGENTA_EX, # 浅洋红色
PackMsgType.下播: Fore.RED, # 红色
}
# 初始化统计对象
live_stats = LiveStats()
def get_timestamp() -> str:
"""返回当前时间戳,格式:HH:MM:SS"""
return datetime.now().strftime("%H:%M:%S")
def print_colored_message(msg_type: PackMsgType, content: str, author: str = "未知") -> None:
"""打印带颜色的消息"""
color = COLOR_MAP.get(msg_type, Fore.WHITE)
timestamp = get_timestamp()
elapsed_time = "["+author+"]"
print(f"{color}{timestamp} {elapsed_time} {content}{Style.RESET_ALL}")
def get_msg_owner(msg) -> str:
"""统一获取消息所属的主播/房间信息"""
if hasattr(msg, 'Owner') and msg.Owner:
return msg.Owner.Nickname
elif hasattr(msg, 'WebRoomId') and msg.WebRoomId:
return msg.WebRoomId
elif hasattr(msg, 'RoomId') and msg.RoomId:
return msg.RoomId
return "未知"
# 处理函数:弹幕消息
def handle_danmaku(data_dict: Dict[str, Any]) -> None:
"""处理用户发送的弹幕消息"""
msg = MessageParser.parse_danmaku(data_dict)
gender_str = msg.User.gender_to_string()
content = f"[弹幕消息] [{gender_str}] {msg.User.Nickname}: {msg.Content}"
author = get_msg_owner(msg)
print_colored_message(PackMsgType.弹幕消息, content, author)
# 处理函数:点赞消息
def handle_dianzanku(data_dict: Dict[str, Any]) -> None:
"""处理用户点赞消息并更新全局统计"""
like_msg = MessageParser.parse_like(data_dict)
live_stats.total_likes = like_msg.Total
gender_str = like_msg.User.gender_to_string()
content = f"[点赞消息] [{gender_str}] {like_msg.User.Nickname} 为主播点了{like_msg.Count}个赞, 总点赞{like_msg.Total}"
author = get_msg_owner(like_msg)
print_colored_message(PackMsgType.点赞消息, content, author)
# 处理函数:进入直播间
def handle_userentry(data_dict: Dict[str, Any]) -> None:
"""处理用户进入直播间的消息,并根据性别更新统计"""
member_msg = MessageParser.parse_member(data_dict)
# 根据性别更新全局计数
if member_msg.User.Gender == Gender.男:
live_stats.male_users += 1
elif member_msg.User.Gender == Gender.女:
live_stats.female_users += 1
gender_str = member_msg.User.gender_to_string()
content = f"[进直播间] [{gender_str}] {member_msg.User.Nickname} $来了 直播间人数:{member_msg.CurrentCount}"
author = get_msg_owner(member_msg)
print_colored_message(PackMsgType.进直播间, content, author)
# 处理函数:关注消息
def handle_follow(data_dict: Dict[str, Any]) -> None:
"""处理用户关注主播的消息"""
follow_msg = MessageParser.parse_follow(data_dict)
gender_str = follow_msg.User.gender_to_string()
content = f"[关注消息] [{gender_str}] {follow_msg.User.Nickname} 关注了主播"
author = get_msg_owner(follow_msg)
print_colored_message(PackMsgType.关注消息, content, author)
# 处理函数:礼物消息
def handle_gift(data_dict: Dict[str, Any]) -> None:
"""处理用户赠送礼物的消息"""
gift_msg = MessageParser.parse_gift(data_dict)
gender_str = gift_msg.User.gender_to_string()
# 使用DiamondCount或GiftValue作为礼物价值
gift_value = gift_msg.DiamondCount or gift_msg.GiftValue
content = f"[礼物消息] [{gender_str}] {gift_msg.User.Nickname} 送出了 {gift_msg.GiftCount}个{gift_msg.GiftName}, 价值{gift_value}抖币"
author = get_msg_owner(gift_msg)
print_colored_message(PackMsgType.礼物消息, content, author)
# 处理函数:统计消息
def handle_statistics(data_dict: Dict[str, Any]) -> None:
"""处理直播间统计信息"""
stats_msg = MessageParser.parse_statistics(data_dict)
live_stats.total_users = int(stats_msg.TotalUserCount)
content = f"[直播间统计] 当前直播间人数 {stats_msg.OnlineUserCountStr}, 累计直播间人数 {stats_msg.TotalUserCountStr}万"
author = get_msg_owner(stats_msg)
print_colored_message(PackMsgType.直播间统计, content, author)
# 处理函数:粉丝团消息
def handle_fansclub(data_dict: Dict[str, Any]) -> None:
"""处理粉丝团相关消息"""
fansclub_msg = MessageParser.parse_fansclub(data_dict)
gender_str = fansclub_msg.User.gender_to_string()
if fansclub_msg.Type == 1:
action = "升级了"
content = f"[粉丝团消息] [{gender_str}] {fansclub_msg.User.Nickname} {action}{fansclub_msg.FansClubName}粉丝团到{fansclub_msg.Level}级"
else:
action = "加入了"
content = f"[粉丝团消息] [{gender_str}] {fansclub_msg.User.Nickname} {action}{fansclub_msg.FansClubName}粉丝团"
author = get_msg_owner(fansclub_msg)
print_colored_message(PackMsgType.粉丝团消息, content, author)
# 处理函数:直播间分享
def handle_share(data_dict: Dict[str, Any]) -> None:
"""处理用户分享直播间的消息"""
share_msg = MessageParser.parse_share(data_dict)
gender_str = share_msg.User.gender_to_string()
# 获取分享目标类型
share_type_str = share_msg.ShareType.name if hasattr(share_msg.ShareType, 'name') else "未知平台"
content = f"[直播间分享] [{gender_str}] {share_msg.User.Nickname} 分享了直播间到{share_type_str}"
author = get_msg_owner(share_msg)
print_colored_message(PackMsgType.直播间分享, content, author)
# 处理函数:直播结束
def handle_live_exit() -> None:
"""处理直播结束事件,显示并重置统计数据"""
content = f"[下播] 直播结束:累计观看 {live_stats.total_users} 人,累计点赞 {live_stats.total_likes},"\
f"男生 {live_stats.male_users} 女生 {live_stats.female_users}"
print_colored_message(PackMsgType.下播, content, "系统消息")
live_stats.reset()
print(f"直播统计数据已清空~")
async def process_message(message: str) -> None:
"""处理从WebSocket接收到的单条消息"""
try:
data = json.loads(message)
if "Type" not in data:
print("⚠️ 收到无效消息:缺少Type字段")
return
msg_type = PackMsgType(data['Type'])
# 检查是否需要处理Data字段
if msg_type == PackMsgType.下播:
handle_live_exit()
return
if "Data" not in data:
print(f"⚠️ 消息类型 {msg_type.name} 缺少Data字段")
return
try:
data_dict = json.loads(data['Data'])
# 消息处理映射表
handlers = {
PackMsgType.弹幕消息: handle_danmaku,
PackMsgType.点赞消息: handle_dianzanku,
PackMsgType.进直播间: handle_userentry,
PackMsgType.关注消息: handle_follow,
PackMsgType.礼物消息: handle_gift,
PackMsgType.直播间统计: handle_statistics,
PackMsgType.粉丝团消息: handle_fansclub,
PackMsgType.直播间分享: handle_share,
}
# 分发消息到相应处理器
if msg_type in handlers:
handlers[msg_type](data_dict)
except json.JSONDecodeError:
print(f"⚠️ 无法解析Data字段内容:{data['Data'][:100]}...")
except json.JSONDecodeError:
print(f"⚠️ 无效的JSON格式: {message[:100]}...")
except Exception as e:
print(f"❌ 消息处理错误: {str(e)}")
async def connect_and_print() -> None:
"""连接到WebSocket服务器并处理接收到的消息"""
uri = "ws://127.0.0.1:8888"
while True:
try:
print(f"正在连接到服务器 {uri}...")
async with websockets.connect(uri, ping_interval=None) as websocket:
print(f"✅ 已成功连接到服务器 {uri}")
while True:
message = await websocket.recv()
await process_message(message)
except websockets.exceptions.ConnectionClosed as e:
print(f"⚠️ 与服务器的连接已关闭: {e}")
except ConnectionRefusedError:
print(f"❌ 无法连接到服务器 {uri},5秒后重试...")
except Exception as e:
print(f"❌ 发生错误: {str(e)}")
# 连接断开后等待重连
await asyncio.sleep(5)
print("正在尝试重新连接...")
# 程序入口
if __name__ == "__main__":
print("启动抖音直播消息监听...")
asyncio.run(connect_and_print())
+158
View File
@@ -0,0 +1,158 @@
from typing import Dict, Any, Optional
from entities import (
MsgUser, FansClubInfo, Msg, LikeMsg, MemberMessage, UserSeqMsg,
Gender, GiftMsg, FansclubMsg, ShareMessage, RoomAnchorInfo, ShareType
)
# 消息解析器
class MessageParser:
@staticmethod
def parse_user(user_data: Dict[str, Any]) -> MsgUser:
"""解析用户数据"""
user = MsgUser()
if not user_data:
return user
user.Id = user_data.get("Id", 0)
user.IsAdmin = user_data.get("IsAdmin", False)
user.IsAnchor = user_data.get("IsAnchor", False)
user.ShortId = user_data.get("ShortId", 0)
user.DisplayId = user_data.get("DisplayId", "")
user.Nickname = user_data.get("Nickname", "匿名用户")
user.Level = user_data.get("Level", 0)
user.PayLevel = user_data.get("PayLevel", 0)
user.Gender = Gender(user_data.get("Gender", 0))
user.HeadImgUrl = user_data.get("HeadImgUrl", "")
user.SecUid = user_data.get("SecUid", "")
user.FollowerCount = user_data.get("FollowerCount", 0)
user.FollowStatus = user_data.get("FollowStatus", 0)
user.FollowingCount = user_data.get("FollowingCount", 0)
# 解析粉丝团信息
if "FansClub" in user_data and user_data["FansClub"]:
fans_club_data = user_data["FansClub"]
user.FansClub = FansClubInfo(
ClubName=fans_club_data.get("ClubName", ""),
Level=fans_club_data.get("Level", 0)
)
return user
@staticmethod
def parse_anchor_info(owner_data: Dict[str, Any]) -> Optional[RoomAnchorInfo]:
"""解析主播信息"""
if not owner_data:
return None
owner = RoomAnchorInfo()
owner.UserId = owner_data.get("UserId", "")
owner.SecUid = owner_data.get("SecUid", "")
owner.Nickname = owner_data.get("Nickname", "")
owner.HeadUrl = owner_data.get("HeadUrl", "")
owner.FollowStatus = owner_data.get("FollowStatus", 0)
return owner
@staticmethod
def parse_common_msg_fields(data: Dict[str, Any], msg: Msg) -> Msg:
"""解析通用消息字段"""
msg.MsgId = data.get("MsgId", 0)
msg.Content = data.get("Content", "")
msg.RoomId = data.get("RoomId", "")
msg.WebRoomId = data.get("WebRoomId", "")
msg.RoomTitle = data.get("RoomTitle", "")
msg.IsAnonymous = data.get("IsAnonymous", False)
msg.Appid = data.get("Appid", "")
# 解析用户数据
if "User" in data and data["User"]:
msg.User = MessageParser.parse_user(data["User"])
# 解析主播数据,优先使用正确拼写的"Owner"
if "Owner" in data and data["Owner"]:
msg.Owner = MessageParser.parse_anchor_info(data["Owner"])
# 如果没有"Owner"字段才考虑拼写错误的"Onwer"字段,并且确保不是字符串
elif "Onwer" in data and data["Onwer"] and not isinstance(data["Onwer"], str):
msg.Owner = MessageParser.parse_anchor_info(data["Onwer"])
return msg
@staticmethod
def parse_danmaku(data: Dict[str, Any]) -> Msg:
"""解析弹幕消息"""
msg = Msg()
return MessageParser.parse_common_msg_fields(data, msg)
@staticmethod
def parse_like(data: Dict[str, Any]) -> LikeMsg:
"""解析点赞消息"""
like_msg = LikeMsg()
MessageParser.parse_common_msg_fields(data, like_msg)
like_msg.Count = data.get("Count", 0)
like_msg.Total = data.get("Total", 0)
return like_msg
@staticmethod
def parse_member(data: Dict[str, Any]) -> MemberMessage:
"""解析进入直播间消息"""
member_msg = MemberMessage()
MessageParser.parse_common_msg_fields(data, member_msg)
member_msg.CurrentCount = data.get("CurrentCount", 0)
member_msg.EnterTipType = data.get("EnterTipType", 0)
return member_msg
@staticmethod
def parse_gift(data: Dict[str, Any]) -> GiftMsg:
"""解析礼物消息"""
gift_msg = GiftMsg()
MessageParser.parse_common_msg_fields(data, gift_msg)
gift_msg.GiftId = data.get("GiftId", 0)
gift_msg.GiftName = data.get("GiftName", "")
gift_msg.GroupId = data.get("GroupId", 0)
gift_msg.GiftCount = data.get("GiftCount", 0)
gift_msg.RepeatCount = data.get("RepeatCount", 0)
gift_msg.DiamondCount = data.get("DiamondCount", 0)
gift_msg.GiftValue = data.get("GiftValue", 0) # 兼容原有代码
gift_msg.Combo = data.get("Combo", False)
gift_msg.ImgUrl = data.get("ImgUrl", "")
# 解析接收礼物的用户
if "ToUser" in data and data["ToUser"]:
gift_msg.ToUser = MessageParser.parse_user(data["ToUser"])
return gift_msg
@staticmethod
def parse_statistics(data: Dict[str, Any]) -> UserSeqMsg:
"""解析直播间统计消息"""
stats_msg = UserSeqMsg()
MessageParser.parse_common_msg_fields(data, stats_msg)
stats_msg.OnlineUserCount = data.get("OnlineUserCount", 0)
stats_msg.TotalUserCount = data.get("TotalUserCount", 0)
stats_msg.TotalUserCountStr = data.get("TotalUserCountStr", "0")
stats_msg.OnlineUserCountStr = data.get("OnlineUserCountStr", "0")
return stats_msg
@staticmethod
def parse_fansclub(data: Dict[str, Any]) -> FansclubMsg:
"""解析粉丝团消息"""
fansclub_msg = FansclubMsg()
MessageParser.parse_common_msg_fields(data, fansclub_msg)
fansclub_msg.Type = data.get("Type", 0)
fansclub_msg.Level = data.get("Level", 0)
fansclub_msg.FansClubName = data.get("FansClubName", "")
return fansclub_msg
@staticmethod
def parse_share(data: Dict[str, Any]) -> ShareMessage:
"""解析直播间分享消息"""
share_msg = ShareMessage()
MessageParser.parse_common_msg_fields(data, share_msg)
share_msg.ShareType = ShareType(data.get("ShareType", 0))
return share_msg
@staticmethod
def parse_follow(data: Dict[str, Any]) -> Msg:
"""解析关注消息"""
follow_msg = Msg()
return MessageParser.parse_common_msg_fields(data, follow_msg)
+2
View File
@@ -0,0 +1,2 @@
websockets>=10.0
colorama>=0.4.4
-89
View File
@@ -1,89 +0,0 @@
import asyncio
import json
from jsonpath import jsonpath
import websockets
# 1用户发言#2用户点赞#3用户入房#4关注主播#5用户礼物#6人数统计
'''
str(fid[0:2])=="403": #字符串提取方便自定义命令
'''
def msg(data):
global close
load_json_data = json.loads(data.get("Data"))
用户名 = jsonpath(load_json_data, '$.User.Nickname')
用户等级 = jsonpath(load_json_data, '$.User.PayLevel')
粉丝团 = jsonpath(load_json_data, '$.User.FansClub.ClubName')
用户发言 = jsonpath(load_json_data, '$.Content')
if 用户发言[0] == "#关闭":
close = False
else:
print(用户名[0])
print(用户等级[0])
def praise(data): # type2
load_json_data = json.loads(data.get("Data"))
用户点赞 = jsonpath(load_json_data, '$.Content')
print("感谢" + 用户点赞[0])
def welcome(data): # type3
load_json_data = json.loads(data.get("Data"))
用户名 = jsonpath(load_json_data, '$.User.Nickname')
粉丝团 = jsonpath(load_json_data, '$.User.FansClub.ClubName')
if 粉丝团[0] == "Reset":
print("欢迎粉丝:" + 用户名[0])
else:
print("欢迎:" + 用户名[0])
def thank(data): # type5
load_json_data = json.loads(data.get("Data"))
粉丝团 = jsonpath(load_json_data, '$.User.FansClub.ClubName')
用户送礼 = jsonpath(load_json_data, '$.Content')
# txt1 = txt.replace("主播", "黎公子") #字符串替换功能方便拓展功能
if 粉丝团[0] == "Reset":
print("感谢老板:" + 用户送礼[0])
else:
print("感谢:" + 用户送礼[0])
def check(data): # type6
load_json_data = json.loads(data.get("Data"))
房间统计 = jsonpath(load_json_data, '$.Content')
print(房间统计[0])
def check_json(json_data):
Token = json_data.get("Type") # 标签类型
if Token == 1: # 1用户发言
msg(json_data)
elif Token == 2: # 2用户点赞
praise(json_data)
elif Token == 3: # 3用户入房
welcome(json_data)
elif Token == 4: # 感谢关注
print(str(json_data))
elif Token == 5: # 5用户礼物
thank(json_data)
elif Token == 6: # 6人数统计
check(json_data)
else:
print(json_data)
async def main():
global close
async with websockets.connect("ws://127.0.0.1:8888/", ping_interval=None) as ws:
await ws.send("token")
close = True
while close is True:
result = await ws.recv()
check_json(json.loads(result))
await ws.close()
close = True
asyncio.run(main())