feat(跨平台): 增强跨平台消息互通功能
- 支持合并转发消息解析和展示 - 优化附件处理逻辑,支持文件名和类型识别 - 添加 Discord Embed 卡片支持,提升消息展示效果 - 重构消息格式化和转发逻辑,提高可维护性 - 更新代理配置和日志级别设置
This commit is contained in:
@@ -32,22 +32,30 @@ class DiscordAdapter(discord.Client if DISCORD_AVAILABLE else object):
|
||||
def __init__(self, token: str):
|
||||
if not DISCORD_AVAILABLE:
|
||||
raise ImportError("discord.py 未安装,请运行 `pip install discord.py`")
|
||||
|
||||
# 必须声明 Intents,否则无法读取消息内容
|
||||
intents = discord.Intents.default()
|
||||
intents.message_content = True
|
||||
|
||||
# 检查是否配置了代理
|
||||
self.logger = ModuleLogger("DiscordAdapter")
|
||||
self.token = token
|
||||
self.send_channel = None
|
||||
|
||||
self.proxy = None
|
||||
self.proxy_type = "http"
|
||||
if global_config.discord.proxy:
|
||||
self.proxy = global_config.discord.proxy
|
||||
self.proxy_type = global_config.discord.proxy_type or "http"
|
||||
|
||||
proxy_url = self.proxy
|
||||
if self.proxy_type.lower() in ["socks5", "socks4"]:
|
||||
if not proxy_url.startswith(("socks5://", "socks4://")):
|
||||
proxy_url = f"{self.proxy_type.lower()}://{proxy_url.split('://')[-1]}"
|
||||
|
||||
os.environ["HTTP_PROXY"] = proxy_url
|
||||
os.environ["HTTPS_PROXY"] = proxy_url
|
||||
self.logger.info(f"[DiscordAdapter] 代理已设置: {proxy_url} (类型: {self.proxy_type})")
|
||||
|
||||
intents = discord.Intents.default()
|
||||
intents.message_content = True
|
||||
|
||||
super().__init__(intents=intents)
|
||||
self.token = token
|
||||
self.logger = ModuleLogger("DiscordAdapter")
|
||||
self.send_channel = None
|
||||
|
||||
async def on_ready(self):
|
||||
"""当 Bot 成功连接到 Discord 时触发"""
|
||||
@@ -110,6 +118,7 @@ class DiscordAdapter(discord.Client if DISCORD_AVAILABLE else object):
|
||||
channel_id = data.get("channel_id")
|
||||
content = data.get("content", "")
|
||||
attachments = data.get("attachments", [])
|
||||
embed_data = data.get("embed")
|
||||
|
||||
if channel_id is None:
|
||||
self.logger.error("[DiscordAdapter] 缺少 channel_id")
|
||||
@@ -122,9 +131,38 @@ class DiscordAdapter(discord.Client if DISCORD_AVAILABLE else object):
|
||||
|
||||
self.logger.info(f"[DiscordAdapter] 正在发送消息到频道 {channel_id}")
|
||||
|
||||
# 发送内容和附件(合并为一条消息)
|
||||
if content or attachments:
|
||||
await channel.send(content=content, files=[discord.File(fp=io.BytesIO(requests.get(attachment_url).content), filename=os.path.basename(attachment_url)) for attachment_url in attachments if attachment_url.startswith('http')] if attachments else None)
|
||||
files = []
|
||||
if attachments:
|
||||
proxies = None
|
||||
if self.proxy:
|
||||
proxies = {
|
||||
"http": self.proxy,
|
||||
"https": self.proxy
|
||||
}
|
||||
|
||||
for attachment in attachments:
|
||||
if isinstance(attachment, dict):
|
||||
attachment_url = attachment.get("url", "")
|
||||
filename = attachment.get("filename", "")
|
||||
else:
|
||||
attachment_url = str(attachment)
|
||||
filename = ""
|
||||
|
||||
if attachment_url.startswith('http'):
|
||||
try:
|
||||
response = requests.get(attachment_url, proxies=proxies, timeout=30)
|
||||
if not filename:
|
||||
filename = os.path.basename(attachment_url.split('?')[0]) or "attachment"
|
||||
files.append(discord.File(fp=io.BytesIO(response.content), filename=filename))
|
||||
except Exception as e:
|
||||
self.logger.error(f"[DiscordAdapter] 下载附件失败: {attachment_url}, 错误: {e}")
|
||||
|
||||
embed = None
|
||||
if embed_data:
|
||||
embed = discord.Embed.from_dict(embed_data)
|
||||
|
||||
if content or files or embed:
|
||||
await channel.send(content=content, files=files if files else None, embed=embed)
|
||||
|
||||
self.logger.success(f"[DiscordAdapter] 消息已发送到频道 {channel_id}")
|
||||
|
||||
@@ -139,35 +177,6 @@ class DiscordAdapter(discord.Client if DISCORD_AVAILABLE else object):
|
||||
|
||||
try:
|
||||
self.logger.info("正在连接 Discord...")
|
||||
|
||||
# 如果配置了代理,使用自定义的 ClientSession
|
||||
if self.proxy:
|
||||
import aiohttp
|
||||
proxy_url = self.proxy
|
||||
self.logger.info(f"[DiscordAdapter] 使用代理: {proxy_url} (类型: {self.proxy_type})")
|
||||
|
||||
connector = aiohttp.TCPConnector()
|
||||
session = aiohttp.ClientSession(connector=connector)
|
||||
|
||||
# discord.py 2.0+ 使用 discord.Client 的 connector 参数
|
||||
# 但 discord.Client 不直接支持自定义 connector
|
||||
# 需要使用 discord.AutoShardedClient 或修改内部实现
|
||||
# 这里我们使用 discord.Client 的 __init__ 传递 connector
|
||||
# 但 discord.Client 的 __init__ 不支持 connector 参数
|
||||
# 所以我们需要使用 discord.Client 的 _create_http_client 方法
|
||||
|
||||
# 简单方案:使用环境变量设置代理
|
||||
import os
|
||||
os.environ["HTTP_PROXY"] = proxy_url
|
||||
os.environ["HTTPS_PROXY"] = proxy_url
|
||||
|
||||
self.logger.info("[DiscordAdapter] 代理已设置,正在连接 Discord...")
|
||||
await self.start(self.token)
|
||||
|
||||
# 清理环境变量
|
||||
os.environ.pop("HTTP_PROXY", None)
|
||||
os.environ.pop("HTTPS_PROXY", None)
|
||||
else:
|
||||
await self.start(self.token)
|
||||
await self.start(self.token)
|
||||
except Exception as e:
|
||||
self.logger.error(f"Discord 连接失败: {e}")
|
||||
|
||||
Reference in New Issue
Block a user