File size: 7,703 Bytes
5a4c5de 3894d14 0ceb8b2 3894d14 825ec76 0ceb8b2 3894d14 f655af7 3894d14 f9f3cfb 3894d14 0ceb8b2 3894d14 31f30fb 3894d14 0ceb8b2 3894d14 0ceb8b2 3894d14 0ceb8b2 3894d14 df797a6 3894d14 0ceb8b2 3894d14 0ceb8b2 3894d14 f655af7 3894d14 0ceb8b2 825ec76 3894d14 825ec76 3894d14 825ec76 3894d14 825ec76 3894d14 825ec76 0ceb8b2 825ec76 3894d14 825ec76 c993984 bdcf571 05f3b66 c993984 21b6f04 f9f3cfb 3894d14 c993984 0ceb8b2 34f8d08 0ceb8b2 3894d14 0ceb8b2 3894d14 0ceb8b2 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | # 导入自定义 DNS 库
from dns_resolver import dns_manager
# --- 注入 DNS 补丁 ---
# 必须在所有网络连接尝试之前执行
dns_manager.patch_socket()
import os
import discord
import time
from fastapi import FastAPI
import uvicorn
import asyncio
from threading import Thread
from discord import app_commands, ui
# 导入数据库基础类
from mongo import MongoManager
# 初始化数据库管理器
db_manager = MongoManager(os.getenv("MONGO_URL"), "Main")
# 身份组权限列表
#mod = [1357078628969746462, 1357079285113819146, 1436537252317626449, 1357079707539214417, 1357079889160835183]
# --- 1. FastAPI 保活 ---
app = FastAPI()
# 使用显式的方法定义,并使用 JSONResponse 确保兼容性
@app.api_route("/", methods=["GET", "HEAD"])
async def status():
# 使用 JSONResponse 包装,防止 Starlette 误判
return {"status": "hi"}
def run_flask():
# Hugging Face 默认使用 7860 端口
port = int(os.environ.get('PORT', 7860))
uvicorn.run(app, host='0.0.0.0', port=port)
# --- 2. 辅助函数 ---
def format_pings(role_input: str):
pass
# --- 3. Modal 表单定义 ---
class AnnounceModal(ui.Modal):
def __init__(self, channel: discord.TextChannel, ping_roles_str: str = None):
super().__init__(title="New Announcement")
self.channel = channel
self.ping_roles_str = ping_roles_str
announcement_title = ui.TextInput(label="Title", placeholder="Enter title...", style=discord.TextStyle.short)
announcement_body = ui.TextInput(label="Body", placeholder="Enter message...", style=discord.TextStyle.long)
async def on_submit(self, interaction: discord.Interaction):
content = self.announcement_body.value
pings = self.ping_roles_str
if pings: pass
embed = discord.Embed(
title=self.announcement_title.value,
description=content,
color=discord.Color.red()
)
footer = f"\n\n||{pings}||\n\n---\n**Sent by:** ||{interaction.user.mention}||\n**Time:** <t:{int(time.time())}:f>"
embed.description += footer
await self.channel.send(embed=embed)
await interaction.response.send_message(f"✅ Sent to {self.channel.mention}!", ephemeral=False)
class EditAnnounceModal(ui.Modal):
def __init__(self, message: discord.Message, new_ping_roles_str: str = None):
super().__init__(title="Edit Announcement")
self.message = message
self.new_ping_roles_str = new_ping_roles_str
old_title = message.embeds[0].title if message.embeds else ""
old_body = message.embeds[0].description.split("\n\n---")[0] if message.embeds else ""
self.edit_title = ui.TextInput(label="Title", default=old_title, style=discord.TextStyle.short)
self.edit_body = ui.TextInput(label="Body", default=old_body, style=discord.TextStyle.long)
self.add_item(self.edit_title)
self.add_item(self.edit_body)
async def on_submit(self, interaction: discord.Interaction):
content = self.edit_body.value
pings = self.new_ping_roles_str
if pings: pass
new_embed = discord.Embed(
title=self.edit_title.value,
description=content,
color=discord.Color.blue()
)
footer = f"\n\n||{pings}||\n\n---\n**Edited by:** ||{interaction.user.mention}||\n**Time:** <t:{int(time.time())}:f>"
new_embed.description += footer
await self.message.edit(embed=new_embed)
await interaction.response.send_message(f"✅ Updated announcement {self.message.id} !", ephemeral=False)
# --- 4. 机器人主体 ---
class MyBot(discord.Client):
def __init__(self):
super().__init__(intents=discord.Intents.default())
self.tree = app_commands.CommandTree(self)
async def setup_hook(self):
await self.tree.sync()
print(f"✅ Slash commands synced")
client = MyBot()
client.db = db_manager
# --- 5. 指令定义 ---
@client.tree.command(name="announce", description="Post announcement")
async def announce(interaction: discord.Interaction, channel: discord.TextChannel, role_ids: str = None):
#if not any(role.id in mod for role in interaction.user.roles):
#await interaction.response.send_message("❌ **Access Denied**", ephemeral=True)
#return
await interaction.response.send_modal(AnnounceModal(channel, role_ids))
@client.tree.command(name="announce_edit", description="Edit announcement")
async def announce_edit(interaction: discord.Interaction, channel: discord.TextChannel, message_id: str, new_role_ids: str = None):
#if not any(role.id in mod for role in interaction.user.roles):
#await interaction.response.send_message("❌ **Access Denied**", ephemeral=True)
#return
try:
message = await channel.fetch_message(int(message_id))
await interaction.response.send_modal(EditAnnounceModal(message, new_role_ids))
except Exception as e:
await interaction.response.send_message(f"❌ Error: {e}", ephemeral=False)
@client.tree.command(name="commands", description="Show all avaliable commands")
async def wismer_commands(interaction: discord.Interaction):
await interaction.response.send_message(
'''**Avaliable Commands**:
`/announce`: Post an announcement.
`/announce_edit`: Edit an announcement.''',
ephemeral=False
)
#ADMIN_LOG_CHANNEL_ID = 1468391869686878455
# 允许调用指令的用户名列表(或者 User ID)
ALLOWED_USERS = ["tonydong365"]
# 另一个独立的函数:负责最后的匿名发送
async def send_anonymous_message(channel, content):
await channel.send(content)
@client.tree.command(name="say", description="idk what is this")
@app_commands.describe(content="idk")
async def secret(interaction: discord.Interaction, content: str):
# 1. 读取并核对用户名
current_user = interaction.user.name
# 检查当前用户是否在允许列表中
if current_user not in ALLOWED_USERS:
# 如果不是特定用户,直接回复一个仅自己可见的消息并结束
# 或者干脆不给任何反馈直接 return
await interaction.response.send_message("This is nothing.", ephemeral=True)
return
# 2. 如果是特定用户,先发送一个极其简短的“瞬时响应”来完成交互
# 这样频道里其他人完全看不见
await interaction.response.send_message("指令已确认...", ephemeral=True)
# 3. 立即清理掉这个“瞬时响应”,不留痕迹
await interaction.delete_original_response()
# 4. 调用另一个函数进行“无关联”发送
await send_anonymous_message(interaction.channel, content)
@client.tree.command(name="hi")
async def hi(interaction: discord.Interaction):
await interaction.response.defer(ephemeral=False)
await interaction.followup.send("hi!")
# --- 6. 启动逻辑 ---
async def start_bot():
token = os.getenv('DISCORD_TOKEN')
while True:
try:
print("正在尝试连接 Discord...")
await client.start(token)
except Exception as e:
print(f"❌ 连接失败: {e},15秒后重试...")
# 报错后尝试关闭客户端,清理 aiohttp session 缓存
try:
await client.close()
except:
pass
await asyncio.sleep(15)
if __name__ == "__main__":
# 启动 Web 保活
t = Thread(target=run_flask)
t.daemon = True
t.start()
# 启动机器人异步循环
try:
asyncio.run(start_bot())
except KeyboardInterrupt:
pass
|