初始化多平台机器人部署项目 - Telegram/Discord/QQ资源搜索机器人

This commit is contained in:
2026-09-11 11:19:56 +08:00
commit 2253a2d774
21 changed files with 4004 additions and 0 deletions
+18
View File
@@ -0,0 +1,18 @@
# Discord 机器人配置文件
# 复制为 .env 并填入实际值
# Discord Bot Token(必填)
# 获取地址:https://discord.com/developers/applications
DISCORD_TOKEN=your_discord_bot_token_here
# 命令前缀(可选,默认 !
COMMAND_PREFIX=!
# 管理员用户ID(可选,多个用逗号分隔)
ADMIN_IDS=
# 数据库路径(可选,默认 discord_resources.db
DATABASE_PATH=discord_resources.db
# 日志级别(可选,默认 INFO
LOG_LEVEL=INFO
+5
View File
@@ -0,0 +1,5 @@
# Discord机器人配置
DISCORD_TOKEN=your_discord_bot_token_here
# 资源数据库路径(默认使用Telegram采集的数据库)
# RESOURCE_DB_PATH=F:\开源项目\telegram-resource-collector\web_collected.db
+436
View File
@@ -0,0 +1,436 @@
"""
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()
Binary file not shown.
+2
View File
@@ -0,0 +1,2 @@
discord.py>=2.3.0
python-dotenv>=1.0.0
+46
View File
@@ -0,0 +1,46 @@
@echo off
chcp 65001 >nul
echo ========================================
echo Discord资源搜索机器人 - 启动脚本
echo ========================================
echo.
cd /d "%~dp0"
echo [1/3] 检查Python环境...
python --version
if errorlevel 1 (
echo ❌ 未找到Python,请先安装Python 3.8+
pause
exit /b 1
)
echo.
echo [2/3] 检查依赖...
pip show discord.py >nul 2>&1
if errorlevel 1 (
echo 正在安装依赖...
pip install -r requirements.txt
) else (
echo ✅ 依赖已安装
)
echo.
echo [3/3] 检查配置...
if not exist .env (
echo ❌ 未找到.env配置文件
echo 请复制 .env.example 为 .env 并填入DISCORD_TOKEN
pause
exit /b 1
)
echo ✅ 配置文件存在
echo.
echo ========================================
echo 正在启动Discord机器人...
echo ========================================
echo.
python bot.py
pause