endstone-qqsync-lite-plugin 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- endstone_qqsync_lite_plugin/__init__.py +3 -0
- endstone_qqsync_lite_plugin/client.py +124 -0
- endstone_qqsync_lite_plugin/config_manager.py +64 -0
- endstone_qqsync_lite_plugin/handlers.py +118 -0
- endstone_qqsync_lite_plugin/lib/websockets/__init__.py +236 -0
- endstone_qqsync_lite_plugin/lib/websockets/__main__.py +5 -0
- endstone_qqsync_lite_plugin/lib/websockets/asyncio/__init__.py +0 -0
- endstone_qqsync_lite_plugin/lib/websockets/asyncio/async_timeout.py +282 -0
- endstone_qqsync_lite_plugin/lib/websockets/asyncio/client.py +820 -0
- endstone_qqsync_lite_plugin/lib/websockets/asyncio/compatibility.py +30 -0
- endstone_qqsync_lite_plugin/lib/websockets/asyncio/connection.py +1237 -0
- endstone_qqsync_lite_plugin/lib/websockets/asyncio/messages.py +314 -0
- endstone_qqsync_lite_plugin/lib/websockets/asyncio/router.py +198 -0
- endstone_qqsync_lite_plugin/lib/websockets/asyncio/server.py +981 -0
- endstone_qqsync_lite_plugin/lib/websockets/auth.py +18 -0
- endstone_qqsync_lite_plugin/lib/websockets/cli.py +178 -0
- endstone_qqsync_lite_plugin/lib/websockets/client.py +389 -0
- endstone_qqsync_lite_plugin/lib/websockets/connection.py +12 -0
- endstone_qqsync_lite_plugin/lib/websockets/datastructures.py +187 -0
- endstone_qqsync_lite_plugin/lib/websockets/exceptions.py +473 -0
- endstone_qqsync_lite_plugin/lib/websockets/extensions/__init__.py +4 -0
- endstone_qqsync_lite_plugin/lib/websockets/extensions/base.py +123 -0
- endstone_qqsync_lite_plugin/lib/websockets/extensions/permessage_deflate.py +697 -0
- endstone_qqsync_lite_plugin/lib/websockets/frames.py +430 -0
- endstone_qqsync_lite_plugin/lib/websockets/headers.py +586 -0
- endstone_qqsync_lite_plugin/lib/websockets/http.py +20 -0
- endstone_qqsync_lite_plugin/lib/websockets/http11.py +427 -0
- endstone_qqsync_lite_plugin/lib/websockets/imports.py +100 -0
- endstone_qqsync_lite_plugin/lib/websockets/legacy/__init__.py +11 -0
- endstone_qqsync_lite_plugin/lib/websockets/legacy/auth.py +190 -0
- endstone_qqsync_lite_plugin/lib/websockets/legacy/client.py +705 -0
- endstone_qqsync_lite_plugin/lib/websockets/legacy/exceptions.py +71 -0
- endstone_qqsync_lite_plugin/lib/websockets/legacy/framing.py +225 -0
- endstone_qqsync_lite_plugin/lib/websockets/legacy/handshake.py +158 -0
- endstone_qqsync_lite_plugin/lib/websockets/legacy/http.py +201 -0
- endstone_qqsync_lite_plugin/lib/websockets/legacy/protocol.py +1641 -0
- endstone_qqsync_lite_plugin/lib/websockets/legacy/server.py +1191 -0
- endstone_qqsync_lite_plugin/lib/websockets/protocol.py +758 -0
- endstone_qqsync_lite_plugin/lib/websockets/py.typed +0 -0
- endstone_qqsync_lite_plugin/lib/websockets/server.py +587 -0
- endstone_qqsync_lite_plugin/lib/websockets/speedups.c +222 -0
- endstone_qqsync_lite_plugin/lib/websockets/speedups.cpython-312-x86_64-linux-gnu.so +0 -0
- endstone_qqsync_lite_plugin/lib/websockets/speedups.pyi +1 -0
- endstone_qqsync_lite_plugin/lib/websockets/streams.py +151 -0
- endstone_qqsync_lite_plugin/lib/websockets/sync/__init__.py +0 -0
- endstone_qqsync_lite_plugin/lib/websockets/sync/client.py +648 -0
- endstone_qqsync_lite_plugin/lib/websockets/sync/connection.py +1072 -0
- endstone_qqsync_lite_plugin/lib/websockets/sync/messages.py +345 -0
- endstone_qqsync_lite_plugin/lib/websockets/sync/router.py +192 -0
- endstone_qqsync_lite_plugin/lib/websockets/sync/server.py +763 -0
- endstone_qqsync_lite_plugin/lib/websockets/sync/utils.py +45 -0
- endstone_qqsync_lite_plugin/lib/websockets/typing.py +74 -0
- endstone_qqsync_lite_plugin/lib/websockets/uri.py +225 -0
- endstone_qqsync_lite_plugin/lib/websockets/utils.py +51 -0
- endstone_qqsync_lite_plugin/lib/websockets/version.py +92 -0
- endstone_qqsync_lite_plugin/qqsync_lite_plugin.py +102 -0
- endstone_qqsync_lite_plugin/utils/__init__.py +1 -0
- endstone_qqsync_lite_plugin/utils/imports.py +22 -0
- endstone_qqsync_lite_plugin-0.0.1.dist-info/METADATA +34 -0
- endstone_qqsync_lite_plugin-0.0.1.dist-info/RECORD +62 -0
- endstone_qqsync_lite_plugin-0.0.1.dist-info/WHEEL +4 -0
- endstone_qqsync_lite_plugin-0.0.1.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import json
|
|
3
|
+
from typing import Optional
|
|
4
|
+
from .utils.imports import import_websockets
|
|
5
|
+
|
|
6
|
+
websockets = import_websockets()
|
|
7
|
+
|
|
8
|
+
class WebSocketClient:
|
|
9
|
+
"""WebSocket 客户端,用于与 OneBot WS 交互"""
|
|
10
|
+
|
|
11
|
+
def __init__(self, plugin):
|
|
12
|
+
self.plugin = plugin
|
|
13
|
+
self.logger = plugin.logger
|
|
14
|
+
self.ws = None
|
|
15
|
+
self._running = False
|
|
16
|
+
|
|
17
|
+
async def connect_forever(self):
|
|
18
|
+
"""保持与 OneBot WS 服务的连接"""
|
|
19
|
+
if self._running:
|
|
20
|
+
return
|
|
21
|
+
self._running = True
|
|
22
|
+
|
|
23
|
+
napcat_ws = self.plugin.config_manager.get("napcat_ws")
|
|
24
|
+
access_token = self.plugin.config_manager.get("access_token")
|
|
25
|
+
headers = {"Authorization": f"Bearer {access_token}"} if access_token else {}
|
|
26
|
+
|
|
27
|
+
self.logger.info(f"正在连接 NapCat WS 地址: {napcat_ws}")
|
|
28
|
+
delay = 2
|
|
29
|
+
|
|
30
|
+
while self._running:
|
|
31
|
+
try:
|
|
32
|
+
async with websockets.connect(
|
|
33
|
+
napcat_ws,
|
|
34
|
+
additional_headers=headers,
|
|
35
|
+
ping_interval=20,
|
|
36
|
+
ping_timeout=10,
|
|
37
|
+
close_timeout=10
|
|
38
|
+
) as websocket:
|
|
39
|
+
self.ws = websocket
|
|
40
|
+
self.plugin._current_ws = websocket
|
|
41
|
+
delay = 2 # 连接成功后重置重连延迟
|
|
42
|
+
self.logger.info("已成功连接 NapCat WS")
|
|
43
|
+
|
|
44
|
+
# 发送服务器启动通知
|
|
45
|
+
if self.plugin._send_startup_message:
|
|
46
|
+
if self.plugin.config_manager.get("enable_game_to_qq", True):
|
|
47
|
+
await self.send_group_msg_to_all("[QQSync-Lite] 服务器已启动!")
|
|
48
|
+
self.plugin._send_startup_message = False
|
|
49
|
+
|
|
50
|
+
# 消息接收主循环
|
|
51
|
+
async for message in websocket:
|
|
52
|
+
try:
|
|
53
|
+
data = json.loads(message)
|
|
54
|
+
await self._handle_message(data)
|
|
55
|
+
except Exception as e:
|
|
56
|
+
self.logger.error(f"处理收到的消息时出错: {e}")
|
|
57
|
+
except Exception as e:
|
|
58
|
+
self.ws = None
|
|
59
|
+
self.plugin._current_ws = None
|
|
60
|
+
if self._running:
|
|
61
|
+
self.logger.warning(f"NapCat WS 连接异常或断开: {e},将在 {delay} 秒后重试...")
|
|
62
|
+
await asyncio.sleep(delay)
|
|
63
|
+
delay = min(30, delay * 1.5)
|
|
64
|
+
else:
|
|
65
|
+
break
|
|
66
|
+
|
|
67
|
+
self.logger.info("NapCat WS 客户端已停止运行")
|
|
68
|
+
|
|
69
|
+
async def _handle_message(self, data: dict):
|
|
70
|
+
"""处理来自 OneBot 协议的消息"""
|
|
71
|
+
post_type = data.get("post_type")
|
|
72
|
+
if post_type != "message":
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
message_type = data.get("message_type")
|
|
76
|
+
if message_type != "group":
|
|
77
|
+
return
|
|
78
|
+
|
|
79
|
+
group_id = data.get("group_id")
|
|
80
|
+
target_groups = self.plugin.config_manager.get("target_groups", [])
|
|
81
|
+
target_groups = [int(gid) for gid in target_groups]
|
|
82
|
+
if group_id not in target_groups:
|
|
83
|
+
return
|
|
84
|
+
|
|
85
|
+
raw_message = data.get("raw_message", "")
|
|
86
|
+
sender = data.get("sender", {})
|
|
87
|
+
nickname = sender.get("nickname", "未知")
|
|
88
|
+
card = sender.get("card", "")
|
|
89
|
+
display_name = card if card else nickname
|
|
90
|
+
|
|
91
|
+
# 转发到游戏内
|
|
92
|
+
if self.plugin.config_manager.get("enable_qq_to_game", True):
|
|
93
|
+
from .handlers import handle_qq_message
|
|
94
|
+
await handle_qq_message(self.plugin, group_id, display_name, raw_message)
|
|
95
|
+
|
|
96
|
+
async def send_group_msg_to_all(self, text: str):
|
|
97
|
+
"""广播群消息到所有配置的 QQ 群"""
|
|
98
|
+
if not self.ws or self.ws.state != 1:
|
|
99
|
+
return
|
|
100
|
+
|
|
101
|
+
target_groups = self.plugin.config_manager.get("target_groups", [])
|
|
102
|
+
target_groups = [int(gid) for gid in target_groups]
|
|
103
|
+
|
|
104
|
+
for group_id in target_groups:
|
|
105
|
+
try:
|
|
106
|
+
payload = {
|
|
107
|
+
"action": "send_group_msg",
|
|
108
|
+
"params": {
|
|
109
|
+
"group_id": group_id,
|
|
110
|
+
"message": text
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
await self.ws.send(json.dumps(payload))
|
|
114
|
+
except Exception as e:
|
|
115
|
+
self.logger.error(f"发送群消息到群 {group_id} 失败: {e}")
|
|
116
|
+
|
|
117
|
+
def stop(self):
|
|
118
|
+
"""停止客户端并关闭连接"""
|
|
119
|
+
self._running = False
|
|
120
|
+
if self.ws:
|
|
121
|
+
if self.plugin._loop and self.plugin._loop.is_running():
|
|
122
|
+
asyncio.run_coroutine_threadsafe(self.ws.close(), self.plugin._loop)
|
|
123
|
+
self.ws = None
|
|
124
|
+
self.plugin._current_ws = None
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Any, Dict
|
|
4
|
+
|
|
5
|
+
class ConfigManager:
|
|
6
|
+
"""配置管理器"""
|
|
7
|
+
def __init__(self, data_folder: Path, logger):
|
|
8
|
+
self.data_folder = data_folder
|
|
9
|
+
self.logger = logger
|
|
10
|
+
self.config_file = data_folder / "config.json"
|
|
11
|
+
self._config: Dict[str, Any] = {}
|
|
12
|
+
|
|
13
|
+
self.default_config = {
|
|
14
|
+
"napcat_ws": "ws://127.0.0.1:3001",
|
|
15
|
+
"access_token": "",
|
|
16
|
+
"target_groups": [12345678],
|
|
17
|
+
"group_names": {},
|
|
18
|
+
"enable_qq_to_game": True,
|
|
19
|
+
"enable_game_to_qq": True,
|
|
20
|
+
"enable_join_quit_msg": True,
|
|
21
|
+
"enable_death_msg": True,
|
|
22
|
+
"api_qq_enable": False
|
|
23
|
+
}
|
|
24
|
+
self._load_config()
|
|
25
|
+
|
|
26
|
+
def _load_config(self):
|
|
27
|
+
"""加载配置文件,若不存在则写入默认配置"""
|
|
28
|
+
if not self.config_file.exists():
|
|
29
|
+
self.config_file.parent.mkdir(parents=True, exist_ok=True)
|
|
30
|
+
try:
|
|
31
|
+
with open(self.config_file, "w", encoding="utf-8") as f:
|
|
32
|
+
json.dump(self.default_config, f, indent=2, ensure_ascii=False)
|
|
33
|
+
self.logger.info("已创建默认配置文件 config.json")
|
|
34
|
+
except Exception as e:
|
|
35
|
+
self.logger.error(f"创建默认配置文件失败: {e}")
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
with open(self.config_file, "r", encoding="utf-8") as f:
|
|
39
|
+
self._config = json.load(f)
|
|
40
|
+
except Exception as e:
|
|
41
|
+
self.logger.error(f"读取配置文件失败: {e}")
|
|
42
|
+
self._config = self.default_config.copy()
|
|
43
|
+
|
|
44
|
+
# 合并缺少的默认配置项
|
|
45
|
+
updated = False
|
|
46
|
+
for k, v in self.default_config.items():
|
|
47
|
+
if k not in self._config:
|
|
48
|
+
self._config[k] = v
|
|
49
|
+
updated = True
|
|
50
|
+
|
|
51
|
+
if updated:
|
|
52
|
+
self.save_config()
|
|
53
|
+
|
|
54
|
+
def get(self, key: str, default: Any = None) -> Any:
|
|
55
|
+
"""获取配置项"""
|
|
56
|
+
return self._config.get(key, default)
|
|
57
|
+
|
|
58
|
+
def save_config(self):
|
|
59
|
+
"""保存当前配置到文件"""
|
|
60
|
+
try:
|
|
61
|
+
with open(self.config_file, "w", encoding="utf-8") as f:
|
|
62
|
+
json.dump(self._config, f, indent=2, ensure_ascii=False)
|
|
63
|
+
except Exception as e:
|
|
64
|
+
self.logger.error(f"保存配置文件失败: {e}")
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from endstone.event import event_handler, PlayerChatEvent, PlayerJoinEvent, PlayerQuitEvent, PlayerDeathEvent
|
|
3
|
+
from endstone import ColorFormat
|
|
4
|
+
|
|
5
|
+
# 常用 emoji 字典映射
|
|
6
|
+
EMOJI_MAP = {
|
|
7
|
+
'😀': '[笑脸]', '😁': '[开心]', '😂': '[笑哭]', '🤣': '[大笑]', '😃': '[微笑]',
|
|
8
|
+
'😄': '[开心]', '😅': '[汗笑]', '👍': '[赞]', '👎': '[踩]', '👌': '[OK]',
|
|
9
|
+
'🔥': '[火]', '💯': '[100分]', '❤': '[红心]', '💔': '[心碎]'
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
def clean_and_parse_cq(text: str) -> str:
|
|
13
|
+
"""清理和解析 QQ 消息中的 CQ 码和 Emoji"""
|
|
14
|
+
if not text:
|
|
15
|
+
return ""
|
|
16
|
+
|
|
17
|
+
# 替换已知 emoji
|
|
18
|
+
for emoji, desc in EMOJI_MAP.items():
|
|
19
|
+
text = text.replace(emoji, desc)
|
|
20
|
+
|
|
21
|
+
# 过滤其他未映射 emoji 区段
|
|
22
|
+
emoji_pattern = re.compile(
|
|
23
|
+
r'[\U0001F600-\U0001F64F\U0001F300-\U0001F5FF\U0001F680-\U0001F6FF\U00002600-\U000026FF\U00002700-\U000027BF]+'
|
|
24
|
+
)
|
|
25
|
+
text = emoji_pattern.sub('[表情]', text)
|
|
26
|
+
|
|
27
|
+
# 解析 CQ 码
|
|
28
|
+
def replace_cq(match):
|
|
29
|
+
cq_type = match.group(1)
|
|
30
|
+
cq_map = {
|
|
31
|
+
"image": "[图片]", "video": "[视频]", "record": "[语音]",
|
|
32
|
+
"face": "[表情]", "reply": "[回复]", "forward": "[转发]",
|
|
33
|
+
"file": "[文件]", "share": "[分享]", "location": "[位置]"
|
|
34
|
+
}
|
|
35
|
+
if cq_type in cq_map:
|
|
36
|
+
return cq_map[cq_type]
|
|
37
|
+
elif cq_type == "at":
|
|
38
|
+
params = match.group(2) or ""
|
|
39
|
+
if "qq=all" in params:
|
|
40
|
+
return "@全体成员"
|
|
41
|
+
else:
|
|
42
|
+
qq_match = re.search(r'qq=(\d+)', params)
|
|
43
|
+
return f"@{qq_match.group(1)}" if qq_match else "@某人"
|
|
44
|
+
return "[非文本]"
|
|
45
|
+
|
|
46
|
+
cq_pattern = r'\[CQ:([^,\]]+)(?:,([^\]]*))?\]'
|
|
47
|
+
text = re.sub(cq_pattern, replace_cq, text)
|
|
48
|
+
|
|
49
|
+
# 清理控制字符
|
|
50
|
+
text = re.sub(r'[\x00-\x1f\x7f-\x9f]', '', text)
|
|
51
|
+
return text.strip()
|
|
52
|
+
|
|
53
|
+
async def handle_qq_message(plugin, group_id: int, sender_name: str, raw_message: str):
|
|
54
|
+
"""处理并格式化 QQ 消息转发到游戏"""
|
|
55
|
+
parsed_msg = clean_and_parse_cq(raw_message)
|
|
56
|
+
if not parsed_msg:
|
|
57
|
+
return
|
|
58
|
+
|
|
59
|
+
group_names = plugin.config_manager.get("group_names", {})
|
|
60
|
+
group_name = group_names.get(str(group_id), "")
|
|
61
|
+
|
|
62
|
+
if group_name:
|
|
63
|
+
game_message = f"{ColorFormat.GREEN}[QQ群] {ColorFormat.AQUA}[{group_name}] {sender_name}: {parsed_msg}{ColorFormat.RESET}"
|
|
64
|
+
else:
|
|
65
|
+
game_message = f"{ColorFormat.GREEN}[QQ群] {ColorFormat.AQUA}{sender_name}: {parsed_msg}{ColorFormat.RESET}"
|
|
66
|
+
|
|
67
|
+
plugin.logger.info(f"[QQ群->游戏] {sender_name}: {parsed_msg}")
|
|
68
|
+
|
|
69
|
+
# 主线程安全广播
|
|
70
|
+
def send():
|
|
71
|
+
for player in plugin.server.online_players:
|
|
72
|
+
player.send_message(game_message)
|
|
73
|
+
|
|
74
|
+
plugin.server.scheduler.run_task(plugin, send, delay=1)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class EventHandlers:
|
|
78
|
+
"""游戏事件监听器"""
|
|
79
|
+
def __init__(self, plugin):
|
|
80
|
+
self.plugin = plugin
|
|
81
|
+
|
|
82
|
+
@event_handler
|
|
83
|
+
def on_player_chat(self, event: PlayerChatEvent):
|
|
84
|
+
"""同步游戏内聊天消息到 QQ 群"""
|
|
85
|
+
if event.message.startswith('/'):
|
|
86
|
+
return
|
|
87
|
+
|
|
88
|
+
if self.plugin.config_manager.get("enable_game_to_qq", True):
|
|
89
|
+
chat_msg = f"{event.player.name}: {event.message}"
|
|
90
|
+
self.plugin.send_to_qq(chat_msg)
|
|
91
|
+
|
|
92
|
+
@event_handler
|
|
93
|
+
def on_player_join(self, event: PlayerJoinEvent):
|
|
94
|
+
"""同步玩家加入提示到 QQ 群"""
|
|
95
|
+
if (self.plugin.config_manager.get("enable_game_to_qq", True) and
|
|
96
|
+
self.plugin.config_manager.get("enable_join_quit_msg", True)):
|
|
97
|
+
join_msg = f"[+] 玩家 {event.player.name} 加入了游戏"
|
|
98
|
+
self.plugin.send_to_qq(join_msg)
|
|
99
|
+
|
|
100
|
+
@event_handler
|
|
101
|
+
def on_player_quit(self, event: PlayerQuitEvent):
|
|
102
|
+
"""同步玩家离开提示到 QQ 群"""
|
|
103
|
+
if (self.plugin.config_manager.get("enable_game_to_qq", True) and
|
|
104
|
+
self.plugin.config_manager.get("enable_join_quit_msg", True)):
|
|
105
|
+
quit_msg = f"[-] 玩家 {event.player.name} 离开了游戏"
|
|
106
|
+
self.plugin.send_to_qq(quit_msg)
|
|
107
|
+
|
|
108
|
+
@event_handler
|
|
109
|
+
def on_player_death(self, event: PlayerDeathEvent):
|
|
110
|
+
"""同步玩家死亡提示到 QQ 群"""
|
|
111
|
+
if (self.plugin.config_manager.get("enable_game_to_qq", True) and
|
|
112
|
+
self.plugin.config_manager.get("enable_death_msg", True)):
|
|
113
|
+
try:
|
|
114
|
+
language = event.player.server.language
|
|
115
|
+
death_msg = language.translate(event.death_message, locale="zh_CN")
|
|
116
|
+
self.plugin.send_to_qq(death_msg)
|
|
117
|
+
except Exception as e:
|
|
118
|
+
self.plugin.logger.error(f"处理玩家死亡消息发送失败: {e}")
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
# Importing the typing module would conflict with websockets.typing.
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from .imports import lazy_import
|
|
7
|
+
from .version import version as __version__ # noqa: F401
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
# .asyncio.client
|
|
12
|
+
"connect",
|
|
13
|
+
"unix_connect",
|
|
14
|
+
"ClientConnection",
|
|
15
|
+
# .asyncio.router
|
|
16
|
+
"route",
|
|
17
|
+
"unix_route",
|
|
18
|
+
"Router",
|
|
19
|
+
# .asyncio.server
|
|
20
|
+
"basic_auth",
|
|
21
|
+
"broadcast",
|
|
22
|
+
"serve",
|
|
23
|
+
"unix_serve",
|
|
24
|
+
"ServerConnection",
|
|
25
|
+
"Server",
|
|
26
|
+
# .client
|
|
27
|
+
"ClientProtocol",
|
|
28
|
+
# .datastructures
|
|
29
|
+
"Headers",
|
|
30
|
+
"HeadersLike",
|
|
31
|
+
"MultipleValuesError",
|
|
32
|
+
# .exceptions
|
|
33
|
+
"ConcurrencyError",
|
|
34
|
+
"ConnectionClosed",
|
|
35
|
+
"ConnectionClosedError",
|
|
36
|
+
"ConnectionClosedOK",
|
|
37
|
+
"DuplicateParameter",
|
|
38
|
+
"InvalidHandshake",
|
|
39
|
+
"InvalidHeader",
|
|
40
|
+
"InvalidHeaderFormat",
|
|
41
|
+
"InvalidHeaderValue",
|
|
42
|
+
"InvalidMessage",
|
|
43
|
+
"InvalidOrigin",
|
|
44
|
+
"InvalidParameterName",
|
|
45
|
+
"InvalidParameterValue",
|
|
46
|
+
"InvalidProxy",
|
|
47
|
+
"InvalidProxyMessage",
|
|
48
|
+
"InvalidProxyStatus",
|
|
49
|
+
"InvalidState",
|
|
50
|
+
"InvalidStatus",
|
|
51
|
+
"InvalidUpgrade",
|
|
52
|
+
"InvalidURI",
|
|
53
|
+
"NegotiationError",
|
|
54
|
+
"PayloadTooBig",
|
|
55
|
+
"ProtocolError",
|
|
56
|
+
"ProxyError",
|
|
57
|
+
"SecurityError",
|
|
58
|
+
"WebSocketException",
|
|
59
|
+
# .frames
|
|
60
|
+
"Close",
|
|
61
|
+
"CloseCode",
|
|
62
|
+
"Frame",
|
|
63
|
+
"Opcode",
|
|
64
|
+
# .http11
|
|
65
|
+
"Request",
|
|
66
|
+
"Response",
|
|
67
|
+
# .protocol
|
|
68
|
+
"Protocol",
|
|
69
|
+
"Side",
|
|
70
|
+
"State",
|
|
71
|
+
# .server
|
|
72
|
+
"ServerProtocol",
|
|
73
|
+
# .typing
|
|
74
|
+
"Data",
|
|
75
|
+
"ExtensionName",
|
|
76
|
+
"ExtensionParameter",
|
|
77
|
+
"LoggerLike",
|
|
78
|
+
"StatusLike",
|
|
79
|
+
"Origin",
|
|
80
|
+
"Subprotocol",
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
# When type checking, import non-deprecated aliases eagerly. Else, import on demand.
|
|
84
|
+
if TYPE_CHECKING:
|
|
85
|
+
from .asyncio.client import ClientConnection, connect, unix_connect
|
|
86
|
+
from .asyncio.router import Router, route, unix_route
|
|
87
|
+
from .asyncio.server import (
|
|
88
|
+
Server,
|
|
89
|
+
ServerConnection,
|
|
90
|
+
basic_auth,
|
|
91
|
+
broadcast,
|
|
92
|
+
serve,
|
|
93
|
+
unix_serve,
|
|
94
|
+
)
|
|
95
|
+
from .client import ClientProtocol
|
|
96
|
+
from .datastructures import Headers, HeadersLike, MultipleValuesError
|
|
97
|
+
from .exceptions import (
|
|
98
|
+
ConcurrencyError,
|
|
99
|
+
ConnectionClosed,
|
|
100
|
+
ConnectionClosedError,
|
|
101
|
+
ConnectionClosedOK,
|
|
102
|
+
DuplicateParameter,
|
|
103
|
+
InvalidHandshake,
|
|
104
|
+
InvalidHeader,
|
|
105
|
+
InvalidHeaderFormat,
|
|
106
|
+
InvalidHeaderValue,
|
|
107
|
+
InvalidMessage,
|
|
108
|
+
InvalidOrigin,
|
|
109
|
+
InvalidParameterName,
|
|
110
|
+
InvalidParameterValue,
|
|
111
|
+
InvalidProxy,
|
|
112
|
+
InvalidProxyMessage,
|
|
113
|
+
InvalidProxyStatus,
|
|
114
|
+
InvalidState,
|
|
115
|
+
InvalidStatus,
|
|
116
|
+
InvalidUpgrade,
|
|
117
|
+
InvalidURI,
|
|
118
|
+
NegotiationError,
|
|
119
|
+
PayloadTooBig,
|
|
120
|
+
ProtocolError,
|
|
121
|
+
ProxyError,
|
|
122
|
+
SecurityError,
|
|
123
|
+
WebSocketException,
|
|
124
|
+
)
|
|
125
|
+
from .frames import Close, CloseCode, Frame, Opcode
|
|
126
|
+
from .http11 import Request, Response
|
|
127
|
+
from .protocol import Protocol, Side, State
|
|
128
|
+
from .server import ServerProtocol
|
|
129
|
+
from .typing import (
|
|
130
|
+
Data,
|
|
131
|
+
ExtensionName,
|
|
132
|
+
ExtensionParameter,
|
|
133
|
+
LoggerLike,
|
|
134
|
+
Origin,
|
|
135
|
+
StatusLike,
|
|
136
|
+
Subprotocol,
|
|
137
|
+
)
|
|
138
|
+
else:
|
|
139
|
+
lazy_import(
|
|
140
|
+
globals(),
|
|
141
|
+
aliases={
|
|
142
|
+
# .asyncio.client
|
|
143
|
+
"connect": ".asyncio.client",
|
|
144
|
+
"unix_connect": ".asyncio.client",
|
|
145
|
+
"ClientConnection": ".asyncio.client",
|
|
146
|
+
# .asyncio.router
|
|
147
|
+
"route": ".asyncio.router",
|
|
148
|
+
"unix_route": ".asyncio.router",
|
|
149
|
+
"Router": ".asyncio.router",
|
|
150
|
+
# .asyncio.server
|
|
151
|
+
"basic_auth": ".asyncio.server",
|
|
152
|
+
"broadcast": ".asyncio.server",
|
|
153
|
+
"serve": ".asyncio.server",
|
|
154
|
+
"unix_serve": ".asyncio.server",
|
|
155
|
+
"ServerConnection": ".asyncio.server",
|
|
156
|
+
"Server": ".asyncio.server",
|
|
157
|
+
# .client
|
|
158
|
+
"ClientProtocol": ".client",
|
|
159
|
+
# .datastructures
|
|
160
|
+
"Headers": ".datastructures",
|
|
161
|
+
"HeadersLike": ".datastructures",
|
|
162
|
+
"MultipleValuesError": ".datastructures",
|
|
163
|
+
# .exceptions
|
|
164
|
+
"ConcurrencyError": ".exceptions",
|
|
165
|
+
"ConnectionClosed": ".exceptions",
|
|
166
|
+
"ConnectionClosedError": ".exceptions",
|
|
167
|
+
"ConnectionClosedOK": ".exceptions",
|
|
168
|
+
"DuplicateParameter": ".exceptions",
|
|
169
|
+
"InvalidHandshake": ".exceptions",
|
|
170
|
+
"InvalidHeader": ".exceptions",
|
|
171
|
+
"InvalidHeaderFormat": ".exceptions",
|
|
172
|
+
"InvalidHeaderValue": ".exceptions",
|
|
173
|
+
"InvalidMessage": ".exceptions",
|
|
174
|
+
"InvalidOrigin": ".exceptions",
|
|
175
|
+
"InvalidParameterName": ".exceptions",
|
|
176
|
+
"InvalidParameterValue": ".exceptions",
|
|
177
|
+
"InvalidProxy": ".exceptions",
|
|
178
|
+
"InvalidProxyMessage": ".exceptions",
|
|
179
|
+
"InvalidProxyStatus": ".exceptions",
|
|
180
|
+
"InvalidState": ".exceptions",
|
|
181
|
+
"InvalidStatus": ".exceptions",
|
|
182
|
+
"InvalidUpgrade": ".exceptions",
|
|
183
|
+
"InvalidURI": ".exceptions",
|
|
184
|
+
"NegotiationError": ".exceptions",
|
|
185
|
+
"PayloadTooBig": ".exceptions",
|
|
186
|
+
"ProtocolError": ".exceptions",
|
|
187
|
+
"ProxyError": ".exceptions",
|
|
188
|
+
"SecurityError": ".exceptions",
|
|
189
|
+
"WebSocketException": ".exceptions",
|
|
190
|
+
# .frames
|
|
191
|
+
"Close": ".frames",
|
|
192
|
+
"CloseCode": ".frames",
|
|
193
|
+
"Frame": ".frames",
|
|
194
|
+
"Opcode": ".frames",
|
|
195
|
+
# .http11
|
|
196
|
+
"Request": ".http11",
|
|
197
|
+
"Response": ".http11",
|
|
198
|
+
# .protocol
|
|
199
|
+
"Protocol": ".protocol",
|
|
200
|
+
"Side": ".protocol",
|
|
201
|
+
"State": ".protocol",
|
|
202
|
+
# .server
|
|
203
|
+
"ServerProtocol": ".server",
|
|
204
|
+
# .typing
|
|
205
|
+
"Data": ".typing",
|
|
206
|
+
"ExtensionName": ".typing",
|
|
207
|
+
"ExtensionParameter": ".typing",
|
|
208
|
+
"LoggerLike": ".typing",
|
|
209
|
+
"Origin": ".typing",
|
|
210
|
+
"StatusLike": ".typing",
|
|
211
|
+
"Subprotocol": ".typing",
|
|
212
|
+
},
|
|
213
|
+
deprecated_aliases={
|
|
214
|
+
# deprecated in 9.0 - 2021-09-01
|
|
215
|
+
"framing": ".legacy",
|
|
216
|
+
"handshake": ".legacy",
|
|
217
|
+
"parse_uri": ".uri",
|
|
218
|
+
"WebSocketURI": ".uri",
|
|
219
|
+
# deprecated in 14.0 - 2024-11-09
|
|
220
|
+
# .legacy.auth
|
|
221
|
+
"BasicAuthWebSocketServerProtocol": ".legacy.auth",
|
|
222
|
+
"basic_auth_protocol_factory": ".legacy.auth",
|
|
223
|
+
# .legacy.client
|
|
224
|
+
"WebSocketClientProtocol": ".legacy.client",
|
|
225
|
+
# .legacy.exceptions
|
|
226
|
+
"AbortHandshake": ".legacy.exceptions",
|
|
227
|
+
"InvalidStatusCode": ".legacy.exceptions",
|
|
228
|
+
"RedirectHandshake": ".legacy.exceptions",
|
|
229
|
+
"WebSocketProtocolError": ".legacy.exceptions",
|
|
230
|
+
# .legacy.protocol
|
|
231
|
+
"WebSocketCommonProtocol": ".legacy.protocol",
|
|
232
|
+
# .legacy.server
|
|
233
|
+
"WebSocketServer": ".legacy.server",
|
|
234
|
+
"WebSocketServerProtocol": ".legacy.server",
|
|
235
|
+
},
|
|
236
|
+
)
|
|
File without changes
|