mirror of
https://github.com/EchoZenith/TelegramContactBot.git
synced 2026-02-09 18:05:20 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
819062ae02 | ||
|
|
ae569098f4 |
@@ -13,6 +13,9 @@
|
|||||||
- **全媒体支持**:支持文字、图片、语音、视频、文件、贴纸等多种消息格式。
|
- **全媒体支持**:支持文字、图片、语音、视频、文件、贴纸等多种消息格式。
|
||||||
- **Docker 化部署**:支持 Docker Compose,一键运行,环境隔离,极致稳定。
|
- **Docker 化部署**:支持 Docker Compose,一键运行,环境隔离,极致稳定。
|
||||||
- **欢迎语自定义**:自动处理 `/start` 命令,向首次访问的用户发送个性化引导。
|
- **欢迎语自定义**:自动处理 `/start` 命令,向首次访问的用户发送个性化引导。
|
||||||
|
- **编辑同步**:用户或管理员修改消息,另一端实时同步更新。
|
||||||
|
- **同步删除**:使用 `/del` 指令回复消息,双向撤回内容。
|
||||||
|
- **用户黑名单**:支持 `/ban` 和 `/unban` 功能,轻松拦截骚扰信息。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -88,4 +91,4 @@ python bot.py
|
|||||||
|
|
||||||
### ⚖️ 开源协议
|
### ⚖️ 开源协议
|
||||||
|
|
||||||
本项目基于 [MIT License](https://github.com/EchoZenith/TelegramContactBot/blob/main/LICENSE) 开源。
|
本项目基于 [MIT License](https://github.com/EchoZenith/TelegramContactBot/blob/main/LICENSE) 开源。
|
||||||
|
|||||||
122
bot.py
122
bot.py
@@ -26,11 +26,13 @@ async def init_db():
|
|||||||
# 记录:管理员端消息ID <-> 用户端消息ID <-> 用户ID
|
# 记录:管理员端消息ID <-> 用户端消息ID <-> 用户ID
|
||||||
await db.execute('''CREATE TABLE IF NOT EXISTS msg_pairs
|
await db.execute('''CREATE TABLE IF NOT EXISTS msg_pairs
|
||||||
(admin_msg_id INTEGER PRIMARY KEY, user_msg_id INTEGER, user_id INTEGER)''')
|
(admin_msg_id INTEGER PRIMARY KEY, user_msg_id INTEGER, user_id INTEGER)''')
|
||||||
|
|
||||||
|
await db.execute('''CREATE TABLE IF NOT EXISTS blacklist (user_id INTEGER PRIMARY KEY)''')
|
||||||
await db.commit()
|
await db.commit()
|
||||||
|
|
||||||
|
|
||||||
# 处理 /start 命令
|
# 处理 /start 命令
|
||||||
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
async def handle_start(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||||
user_id = update.effective_chat.id
|
user_id = update.effective_chat.id
|
||||||
keyboard = [[InlineKeyboardButton("🌟 查看项目源码", url=GITHUB_URL)]]
|
keyboard = [[InlineKeyboardButton("🌟 查看项目源码", url=GITHUB_URL)]]
|
||||||
reply_markup = InlineKeyboardMarkup(keyboard)
|
reply_markup = InlineKeyboardMarkup(keyboard)
|
||||||
@@ -40,6 +42,108 @@ async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|||||||
else:
|
else:
|
||||||
await update.message.reply_text("你好,管理员!有人给机器人发消息时,我会转发给你。你直接【回复】该消息即可回信。")
|
await update.message.reply_text("你好,管理员!有人给机器人发消息时,我会转发给你。你直接【回复】该消息即可回信。")
|
||||||
|
|
||||||
|
# 处理 /ban 命令
|
||||||
|
async def handle_ban(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||||
|
if update.effective_chat.id != ADMIN_ID:
|
||||||
|
return
|
||||||
|
|
||||||
|
msg = update.message
|
||||||
|
if not msg.reply_to_message:
|
||||||
|
await msg.reply_text("❌ 请回复一条要封禁的用户消息并输入 /ban")
|
||||||
|
return
|
||||||
|
|
||||||
|
target_id = msg.reply_to_message.message_id
|
||||||
|
|
||||||
|
async with aiosqlite.connect(DB_FILE) as db:
|
||||||
|
# 通过消息 ID 找到对应的用户 ID
|
||||||
|
async with db.execute("SELECT user_id FROM msg_pairs WHERE admin_msg_id = ?", (target_id,)) as cursor:
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
|
||||||
|
if row:
|
||||||
|
user_id = row[0]
|
||||||
|
try:
|
||||||
|
await db.execute("INSERT OR IGNORE INTO blacklist VALUES (?)", (user_id,))
|
||||||
|
await db.commit()
|
||||||
|
await msg.reply_text(f"🚫 用户 `{user_id}` 已被加入黑名单,后续消息将不再转发。", parse_mode='Markdown')
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Ban failed: {e}")
|
||||||
|
else:
|
||||||
|
await msg.reply_text("⚠️ 找不到该消息的用户记录,无法执行封禁。")
|
||||||
|
|
||||||
|
|
||||||
|
# 处理 /unban 命令
|
||||||
|
async def handle_unban(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||||
|
if update.effective_chat.id != ADMIN_ID:
|
||||||
|
return
|
||||||
|
|
||||||
|
msg = update.message
|
||||||
|
if not msg.reply_to_message:
|
||||||
|
await msg.reply_text("❌ 请回复一条要解封的用户消息并输入 /unban")
|
||||||
|
return
|
||||||
|
|
||||||
|
target_id = msg.reply_to_message.message_id
|
||||||
|
|
||||||
|
async with aiosqlite.connect(DB_FILE) as db:
|
||||||
|
# 同样先通过消息 ID 找到对应的用户 ID
|
||||||
|
async with db.execute("SELECT user_id FROM msg_pairs WHERE admin_msg_id = ?", (target_id,)) as cursor:
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
|
||||||
|
if row:
|
||||||
|
user_id = row[0]
|
||||||
|
try:
|
||||||
|
# 从黑名单表中移除
|
||||||
|
await db.execute("DELETE FROM blacklist WHERE user_id = ?", (user_id,))
|
||||||
|
await db.commit()
|
||||||
|
await msg.reply_text(f"✅ 用户 `{user_id}` 已解封,现在可以正常接收其消息。", parse_mode='Markdown')
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Unban failed: {e}")
|
||||||
|
else:
|
||||||
|
await msg.reply_text("⚠️ 找不到该消息的用户记录,无法执行解封。")
|
||||||
|
|
||||||
|
|
||||||
|
# 处理 /del 命令
|
||||||
|
async def handle_delete(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||||
|
# 权限检查:仅限管理员
|
||||||
|
if update.effective_chat.id != ADMIN_ID:
|
||||||
|
return
|
||||||
|
|
||||||
|
message = update.message
|
||||||
|
# 必须是回复某条消息才能执行删除
|
||||||
|
if not message.reply_to_message:
|
||||||
|
await message.reply_text("请回复一条你想删除的消息并输入 /del")
|
||||||
|
return
|
||||||
|
|
||||||
|
target_id = message.reply_to_message.message_id
|
||||||
|
|
||||||
|
async with aiosqlite.connect(DB_FILE) as db:
|
||||||
|
# 查找这条消息对应的用户ID和用户端消息ID
|
||||||
|
async with db.execute(
|
||||||
|
"SELECT user_id, user_msg_id FROM msg_pairs WHERE admin_msg_id = ?",
|
||||||
|
(target_id,)
|
||||||
|
) as cursor:
|
||||||
|
row = await cursor.fetchone()
|
||||||
|
|
||||||
|
if row:
|
||||||
|
user_id, user_msg_id = row
|
||||||
|
try:
|
||||||
|
# 1. 删除用户端的消息
|
||||||
|
await context.bot.delete_message(chat_id=user_id, message_id=user_msg_id)
|
||||||
|
# 2. 删除管理员端的消息
|
||||||
|
await context.bot.delete_message(chat_id=ADMIN_ID, message_id=target_id)
|
||||||
|
# 3. 删除管理员刚才发的 "/del" 命令消息,保持界面整洁
|
||||||
|
await message.delete()
|
||||||
|
|
||||||
|
# 4. 从数据库中移除这条记录
|
||||||
|
await db.execute("DELETE FROM msg_pairs WHERE admin_msg_id = ?", (target_id,))
|
||||||
|
await db.commit()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"同步删除失败: {e}")
|
||||||
|
await message.reply_text(f"删除失败,可能消息已超过48小时或机器人无权限:{e}")
|
||||||
|
else:
|
||||||
|
await message.reply_text("未找到该消息的转发记录,无法同步删除。")
|
||||||
|
|
||||||
|
|
||||||
# 处理同步修改逻辑
|
# 处理同步修改逻辑
|
||||||
async def handle_edit(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
async def handle_edit(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||||
edited_msg = update.edited_message
|
edited_msg = update.edited_message
|
||||||
@@ -107,6 +211,12 @@ async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|||||||
|
|
||||||
# 1. 用户 -> 管理员
|
# 1. 用户 -> 管理员
|
||||||
if user_id != ADMIN_ID:
|
if user_id != ADMIN_ID:
|
||||||
|
# 检查黑名单
|
||||||
|
async with aiosqlite.connect(DB_FILE) as db:
|
||||||
|
async with db.execute("SELECT 1 FROM blacklist WHERE user_id = ?", (user_id,)) as cursor:
|
||||||
|
if await cursor.fetchone():
|
||||||
|
return # 如果在黑名单里,直接无视,不执行后续转发
|
||||||
|
|
||||||
try:
|
try:
|
||||||
forwarded_msg = await context.bot.forward_message(chat_id=ADMIN_ID, from_chat_id=user_id, message_id=message.message_id)
|
forwarded_msg = await context.bot.forward_message(chat_id=ADMIN_ID, from_chat_id=user_id, message_id=message.message_id)
|
||||||
async with aiosqlite.connect(DB_FILE) as db:
|
async with aiosqlite.connect(DB_FILE) as db:
|
||||||
@@ -146,11 +256,17 @@ if __name__ == '__main__':
|
|||||||
application = Application.builder().token(BOT_TOKEN).post_init(post_init).build()
|
application = Application.builder().token(BOT_TOKEN).post_init(post_init).build()
|
||||||
|
|
||||||
# 处理器注册
|
# 处理器注册
|
||||||
application.add_handler(CommandHandler("start", start))
|
application.add_handler(CommandHandler("start", handle_start))
|
||||||
|
# 监听封禁
|
||||||
|
application.add_handler(CommandHandler("ban", handle_ban))
|
||||||
|
# 监听解禁
|
||||||
|
application.add_handler(CommandHandler("unban", handle_unban))
|
||||||
|
# 监听管理员删除消息
|
||||||
|
application.add_handler(CommandHandler("del", handle_delete))
|
||||||
# 监听修改消息的更新
|
# 监听修改消息的更新
|
||||||
application.add_handler(MessageHandler(filters.UpdateType.EDITED_MESSAGE & filters.TEXT, handle_edit))
|
application.add_handler(MessageHandler(filters.UpdateType.EDITED_MESSAGE & filters.TEXT, handle_edit))
|
||||||
# 监听普通消息
|
# 监听普通消息
|
||||||
application.add_handler(MessageHandler(filters.ALL & ~filters.COMMAND, handle_message))
|
application.add_handler(MessageHandler(filters.ALL & ~filters.COMMAND, handle_message))
|
||||||
|
|
||||||
print(f"机器人已启动... 管理员ID: {ADMIN_ID}")
|
print(f"机器人已启动... 管理员ID: {ADMIN_ID}")
|
||||||
application.run_polling()
|
application.run_polling()
|
||||||
|
|||||||
Reference in New Issue
Block a user