165 lines
5.9 KiB
Python
165 lines
5.9 KiB
Python
"""气氛组 + 小游戏 handler"""
|
|
import asyncio
|
|
import logging
|
|
|
|
from telegram import Update
|
|
from telegram.ext import ApplicationHandlerStop, ContextTypes, CommandHandler, MessageHandler, filters
|
|
|
|
from db.models import Action
|
|
from services.game_service import (
|
|
get_trivia_question, check_trivia_answer,
|
|
get_leaderboard, daily_checkin,
|
|
)
|
|
|
|
logger = logging.getLogger("spam_guard")
|
|
|
|
# 关键词触发
|
|
TRIGGER_REACTIONS = {
|
|
"谢谢": "👍❤️",
|
|
"感谢": "👍❤️🎉",
|
|
"哈哈": "😂",
|
|
"笑死": "😂💀",
|
|
"牛逼": "🔥💪",
|
|
"nb": "🔥💪",
|
|
"666": "🔥",
|
|
"晚安": "🌙✨",
|
|
}
|
|
|
|
|
|
async def handle_trigger(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|
"""关键词触发气氛组"""
|
|
msg = update.effective_message
|
|
if not msg or not msg.text:
|
|
return
|
|
|
|
text = msg.text.strip()
|
|
for keyword, emoji in TRIGGER_REACTIONS.items():
|
|
if text == keyword or text.startswith(keyword):
|
|
try:
|
|
await msg.react(emoji)
|
|
except Exception:
|
|
pass
|
|
break
|
|
|
|
|
|
async def cmd_checkin(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|
"""每日签到"""
|
|
user = update.effective_user
|
|
result = await daily_checkin(user.id, user.username or user.first_name)
|
|
if result["ok"]:
|
|
reply = await update.message.reply_text(
|
|
f"✅ 签到成功!\n"
|
|
f"📊 积分: {result['score']}\n"
|
|
f"🔥 连续签到: {result['streak']} 天\n"
|
|
f"🎁 签到奖励: +{result['bonus']} 分"
|
|
)
|
|
else:
|
|
reply = await update.message.reply_text("❌ 你今天已经签到过了")
|
|
asyncio.create_task(auto_delete(update.message, seconds=60))
|
|
asyncio.create_task(auto_delete(reply, seconds=60))
|
|
|
|
|
|
async def cmd_trivia(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|
"""收割机知识答题"""
|
|
q = await get_trivia_question()
|
|
text = f"❓ {q['q']}\n\n"
|
|
for i, opt in enumerate(q["opts"], 1):
|
|
text += f"{i}. {opt}\n"
|
|
text += f"\n💡 请回复序号或答案文字"
|
|
context.user_data["trivia_answer"] = q["a"]
|
|
context.user_data["trivia_options"] = q["opts"]
|
|
reply = await update.message.reply_text(text)
|
|
asyncio.create_task(auto_delete(update.message, seconds=60))
|
|
asyncio.create_task(auto_delete(reply, seconds=60))
|
|
|
|
|
|
async def cmd_score(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|
"""查看积分"""
|
|
from db.models import GameScore
|
|
user = update.effective_user
|
|
scores = await GameScore.filter(user_id=user.id).all()
|
|
if not scores:
|
|
reply = await update.message.reply_text("📊 你还没有积分记录\n💡 签到 /checkin 或答题 /trivia 开始赚积分")
|
|
else:
|
|
text = "📊 你的积分\n━━━━━━━━━━━━\n"
|
|
for s in scores:
|
|
text += f"🎮 {s.game_type}: {s.score} 分 (胜率 {s.wins}/{s.total})\n"
|
|
reply = await update.message.reply_text(text)
|
|
asyncio.create_task(auto_delete(update.message, seconds=60))
|
|
asyncio.create_task(auto_delete(reply, seconds=60))
|
|
|
|
|
|
async def cmd_rank(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|
"""排行榜"""
|
|
top = await get_leaderboard("trivia", 10)
|
|
if not top:
|
|
reply = await update.message.reply_text("🏆 暂无排行数据")
|
|
else:
|
|
text = "🏆 知识答题排行榜\n━━━━━━━━━━━━━━━━━━\n"
|
|
medals = ["🥇", "🥈", "🥉"]
|
|
for i, s in enumerate(top):
|
|
medal = medals[i] if i < 3 else f" {i+1}."
|
|
text += f"{medal} @{s.username or s.user_id} — {s.score} 分\n"
|
|
reply = await update.message.reply_text(text)
|
|
asyncio.create_task(auto_delete(update.message, seconds=60))
|
|
asyncio.create_task(auto_delete(reply, seconds=60))
|
|
|
|
|
|
async def handle_trivia_answer(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|
"""处理 /trivia 后的用户答题。"""
|
|
msg = update.effective_message
|
|
user = update.effective_user
|
|
if not msg or not msg.text or not user or user.is_bot:
|
|
return
|
|
|
|
correct_answer = context.user_data.get("trivia_answer")
|
|
options = context.user_data.get("trivia_options") or []
|
|
if not correct_answer:
|
|
return
|
|
|
|
raw_answer = msg.text.strip()
|
|
answer = raw_answer
|
|
if raw_answer.isdigit():
|
|
idx = int(raw_answer) - 1
|
|
if 0 <= idx < len(options):
|
|
answer = options[idx]
|
|
|
|
result = await check_trivia_answer(user.id, user.username or user.first_name or str(user.id), answer, correct_answer)
|
|
context.user_data.pop("trivia_answer", None)
|
|
context.user_data.pop("trivia_options", None)
|
|
|
|
if result["correct"]:
|
|
text = (
|
|
"✅ 回答正确!\n"
|
|
f"🎯 正确答案:{correct_answer}\n"
|
|
f"📊 当前积分:{result['score']}\n"
|
|
f"🔥 连击:{result['streak']}"
|
|
)
|
|
else:
|
|
text = (
|
|
"❌ 回答错误\n"
|
|
f"🎯 正确答案:{correct_answer}\n"
|
|
f"📊 当前积分:{result['score']}"
|
|
)
|
|
reply = await msg.reply_text(text)
|
|
asyncio.create_task(auto_delete(msg, seconds=60))
|
|
asyncio.create_task(auto_delete(reply, seconds=60))
|
|
raise ApplicationHandlerStop
|
|
|
|
|
|
async def auto_delete(message, seconds=60):
|
|
try:
|
|
await asyncio.sleep(seconds)
|
|
await message.delete()
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
def register_fun(app):
|
|
app.add_handler(CommandHandler("checkin", cmd_checkin, filters.ChatType.GROUPS))
|
|
app.add_handler(CommandHandler("trivia", cmd_trivia, filters.ChatType.GROUPS))
|
|
app.add_handler(CommandHandler("score", cmd_score, filters.ChatType.GROUPS))
|
|
app.add_handler(CommandHandler("rank", cmd_rank, filters.ChatType.GROUPS))
|
|
app.add_handler(MessageHandler(filters.TEXT & filters.ChatType.GROUPS & ~filters.COMMAND, handle_trivia_answer), group=-1)
|
|
app.add_handler(MessageHandler(filters.TEXT & filters.ChatType.GROUPS, handle_trigger), group=2)
|