Download app.py from TonyD365/ACSimBot: direct link, hf CLI and curl.
- Browser
- Download file 7.7 kB
-
https://huggingface.co/spaces/TonyD365/ACSimBot/resolve/main/app.py
- Command line
-
hf download hf://spaces/TonyD365/ACSimBot/app.py
-
curl -L -o app.py https://huggingface.co/spaces/TonyD365/ACSimBot/resolve/main/app.py
7.7 kB
| # 导入自定义 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 确保兼容性 | |
| 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. 指令定义 --- | |
| 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)) | |
| 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) | |
| 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) | |
| 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) | |
| 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 | |