""" Discord资源搜索机器人 - 独立数据库版 功能:全局资源搜索、群管理、资源统计、独立数据库 """ import os import sys import sqlite3 import discord from discord.ext import commands from dotenv import load_dotenv # 加载配置 load_dotenv() DISCORD_TOKEN = os.getenv("DISCORD_TOKEN", "") # 独立数据库路径(Discord机器人自己的数据库) BOT_DIR = os.path.dirname(os.path.abspath(__file__)) DB_PATH = os.path.join(BOT_DIR, "discord_resources.db") # 每页显示数量 PAGE_SIZE = 8 # ========== 数据库初始化 ========== def init_db(): """初始化独立数据库""" conn = sqlite3.connect(DB_PATH) c = conn.cursor() # 资源表 c.execute(""" CREATE TABLE IF NOT EXISTS resources ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, tg_link TEXT DEFAULT '', source TEXT DEFAULT '', keyword TEXT DEFAULT '', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) """) # 搜索记录表 c.execute(""" CREATE TABLE IF NOT EXISTS search_log ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER, keyword TEXT, result_count INTEGER, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) """) # 群配置表 c.execute(""" CREATE TABLE IF NOT EXISTS group_config ( guild_id INTEGER PRIMARY KEY, guild_name TEXT, welcome_enabled INTEGER DEFAULT 1, search_enabled INTEGER DEFAULT 1, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) """) conn.commit() conn.close() print(f"✅ 数据库初始化: {DB_PATH}") # ========== 资源搜索功能 ========== def search_resources(keyword, limit=PAGE_SIZE, offset=0): """从独立数据库搜索资源""" if not os.path.exists(DB_PATH): init_db() conn = sqlite3.connect(DB_PATH) conn.row_factory = sqlite3.Row c = conn.cursor() query = """ SELECT id, title, tg_link, source, keyword, created_at FROM resources WHERE title LIKE ? OR keyword LIKE ? OR source LIKE ? ORDER BY (tg_link != '') DESC, created_at DESC LIMIT ? OFFSET ? """ like_keyword = f"%{keyword}%" c.execute(query, (like_keyword, like_keyword, like_keyword, limit, offset)) results = [dict(row) for row in c.fetchall()] c.execute(""" SELECT COUNT(*) FROM resources WHERE title LIKE ? OR keyword LIKE ? OR source LIKE ? """, (like_keyword, like_keyword, like_keyword)) total = c.fetchone()[0] conn.close() return results, total def add_resource(title, tg_link="", source="", keyword=""): """添加资源到数据库""" conn = sqlite3.connect(DB_PATH) c = conn.cursor() c.execute(""" INSERT OR IGNORE INTO resources (title, tg_link, source, keyword) VALUES (?, ?, ?, ?) """, (title, tg_link, source, keyword)) conn.commit() conn.close() def get_stats(): """获取数据库统计""" if not os.path.exists(DB_PATH): init_db() conn = sqlite3.connect(DB_PATH) c = conn.cursor() c.execute("SELECT COUNT(*) FROM resources") total = c.fetchone()[0] c.execute("SELECT COUNT(*) FROM resources WHERE tg_link != ''") with_link = c.fetchone()[0] c.execute("SELECT COUNT(*) FROM search_log") search_count = c.fetchone()[0] conn.close() return {"total": total, "with_link": with_link, "search_count": search_count} def log_search(user_id, keyword, result_count): """记录搜索日志""" conn = sqlite3.connect(DB_PATH) c = conn.cursor() c.execute(""" INSERT INTO search_log (user_id, keyword, result_count) VALUES (?, ?, ?) """, (user_id, keyword, result_count)) conn.commit() conn.close() # ========== 格式化输出 ========== def format_results(results, keyword, total, page=0): """格式化搜索结果""" lines = [] lines.append(f"🔍 搜索「{keyword}」共找到 {total} 条结果") lines.append(f"📄 第 {page+1} 页 / 共 {(total + PAGE_SIZE - 1) // PAGE_SIZE} 页") lines.append("") for i, res in enumerate(results, 1): idx = page * PAGE_SIZE + i title = res.get("title", "")[:80] tg_link = res.get("tg_link", "") source = res.get("source", "") link_icon = "📎" if tg_link else "🔍" lines.append(f"{idx}. {link_icon} {title}") if tg_link: lines.append(f" 🔗 {tg_link}") if source: lines.append(f" 📡 来源: {source}") lines.append("") if total == 0: lines = [f"❌ 未找到与「{keyword}」相关的资源", "", "💡 试试其他关键词"] return "\n".join(lines) # ========== Discord机器人配置 ========== intents = discord.Intents.default() intents.message_content = True intents.members = True bot = commands.Bot(command_prefix='!', intents=intents, help_command=None) # ========== 事件处理 ========== @bot.event async def on_ready(): """机器人启动完成""" init_db() print(f'✅ Discord机器人已登录: {bot.user}') print(f'📊 已连接 {len(bot.guilds)} 个服务器') print(f'💾 数据库: {DB_PATH}') await bot.change_presence(activity=discord.Game(name="资源搜索 | 发关键词自动搜索")) @bot.event async def on_guild_join(guild): """加入新服务器""" conn = sqlite3.connect(DB_PATH) c = conn.cursor() c.execute(""" INSERT OR IGNORE INTO group_config (guild_id, guild_name) VALUES (?, ?) """, (guild.id, guild.name)) conn.commit() conn.close() print(f"➕ 加入新服务器: {guild.name} ({guild.id})") @bot.event async def on_member_join(member): """新成员加入欢迎""" # 检查是否启用欢迎 conn = sqlite3.connect(DB_PATH) c = conn.cursor() c.execute("SELECT welcome_enabled FROM group_config WHERE guild_id = ?", (member.guild.id,)) result = c.fetchone() conn.close() if result and result[0] == 0: return # 查找欢迎频道 welcome_channel = None for channel in member.guild.text_channels: if 'welcome' in channel.name.lower() or '欢迎' in channel.name or 'general' in channel.name.lower(): welcome_channel = channel break if not welcome_channel and member.guild.text_channels: welcome_channel = member.guild.text_channels[0] if welcome_channel: welcome_msg = f""" 👋 欢迎 **{member.mention}** 加入 **{member.guild.name}**! 📋 本机器人功能: • 直接发送关键词即可搜索资源 • `!search 关键词` - 搜索资源 • `!stats` - 查看资源库统计 • `!help` - 查看帮助 💡 试试发送:电影、音乐、软件、游戏 """ await welcome_channel.send(welcome_msg) # ========== 命令处理 ========== @bot.command(name='help') async def cmd_help(ctx): """帮助命令""" help_text = """ 📋 **Discord资源搜索机器人帮助** **🔍 资源搜索:** • 直接发送关键词 - 自动搜索资源库 • `!search 关键词` - 搜索资源 • `!stats` - 查看资源库统计 **⚙️ 群管理:** • `!ping` - 测试机器人状态 • `!serverinfo` - 查看服务器信息 • `!welcome on/off` - 开启/关闭欢迎消息 **💡 使用示例:** • 发送 `电影` - 搜索电影相关资源 • 发送 `无损音乐` - 搜索无损音乐 • 发送 `Adobe` - 搜索Adobe软件 **📊 数据说明:** 本机器人使用独立数据库,资源持续更新中... """ await ctx.send(help_text) @bot.command(name='search') async def cmd_search(ctx, *, keyword: str = None): """搜索资源""" if not keyword: await ctx.send("❌ 请输入搜索关键词\n示例:`!search 电影`") return await do_search(ctx, keyword) @bot.command(name='stats') async def cmd_stats(ctx): """查看资源库统计""" stats = get_stats() total = stats['total'] with_link = stats['with_link'] search_count = stats['search_count'] link_percent = (with_link / total * 100) if total > 0 else 0 stats_text = f""" 📊 **资源库统计** • 📦 总资源数:**{total}** 条 • 🔗 带跳转链接:**{with_link}** 条 • 📈 链接占比:**{link_percent:.1f}%** • 🔍 总搜索次数:**{search_count}** 次 💡 发送关键词即可搜索资源 """ await ctx.send(stats_text) @bot.command(name='ping') async def cmd_ping(ctx): """测试机器人状态""" latency = bot.latency * 1000 await ctx.send(f"🏓 Pong! 延迟: {latency:.0f}ms") @bot.command(name='serverinfo') async def cmd_serverinfo(ctx): """查看服务器信息""" guild = ctx.guild info = f""" 🏰 **服务器信息** • 📛 名称:{guild.name} • 👥 成员数:{guild.member_count} • 📅 创建时间:{guild.created_at.strftime('%Y-%m-%d')} • 💬 频道数:{len(guild.text_channels)} • 🔊 语音频道数:{len(guild.voice_channels)} """ await ctx.send(info) @bot.command(name='welcome') async def cmd_welcome(ctx, action: str = None): """开启/关闭欢迎消息""" if not action or action.lower() not in ['on', 'off']: await ctx.send("❌ 用法:`!welcome on` 或 `!welcome off`") return enabled = 1 if action.lower() == 'on' else 0 conn = sqlite3.connect(DB_PATH) c = conn.cursor() c.execute(""" INSERT OR REPLACE INTO group_config (guild_id, guild_name, welcome_enabled) VALUES (?, ?, ?) """, (ctx.guild.id, ctx.guild.name, enabled)) conn.commit() conn.close() status = "✅ 已开启" if enabled else "❌ 已关闭" await ctx.send(f"{status} 欢迎消息") # ========== 核心搜索功能 ========== async def do_search(ctx, keyword, page=0): """执行搜索并发送结果""" # 显示"正在搜索" search_msg = await ctx.send(f"🔍 正在搜索「{keyword}」...") try: # 搜索资源 results, total = search_resources(keyword, limit=PAGE_SIZE, offset=page * PAGE_SIZE) # 记录搜索日志 log_search(ctx.author.id, keyword, total) # 格式化结果 reply = format_results(results, keyword, total, page=page) # 编辑消息 await search_msg.edit(content=reply) # 分页反应 if total > PAGE_SIZE: await search_msg.add_reaction("⬅️") await search_msg.add_reaction("➡️") except Exception as e: await search_msg.edit(content=f"❌ 搜索失败:{str(e)}") # ========== 全局消息监听 ========== @bot.event async def on_message(message): """处理所有消息 - 全局资源搜索""" # 忽略机器人自己的消息 if message.author == bot.user: return # 处理命令 await bot.process_commands(message) # 如果是命令,不触发全局搜索 if message.content.startswith('!'): return # 忽略太短的消息 if len(message.content.strip()) < 2: return # 忽略包含URL的消息 if 'http://' in message.content or 'https://' in message.content: return # 只在服务器频道触发全局搜索 if message.guild is None: return # 检查是否启用搜索 conn = sqlite3.connect(DB_PATH) c = conn.cursor() c.execute("SELECT search_enabled FROM group_config WHERE guild_id = ?", (message.guild.id,)) result = c.fetchone() conn.close() if result and result[0] == 0: return # 全局资源搜索 keyword = message.content.strip() await do_search(message.channel, keyword) # ========== 主函数 ========== def main(): """主函数""" if not DISCORD_TOKEN: print("❌ 错误:未配置DISCORD_TOKEN") print("请在.env文件中设置DISCORD_TOKEN") print("获取地址:https://discord.com/developers/applications") return print("🚀 正在启动Discord机器人...") bot.run(DISCORD_TOKEN) if __name__ == "__main__": main()