| import asyncio |
| import os |
| import logging |
| import json |
| from fastapi import FastAPI, Request |
| from aiogram import Bot, Dispatcher, types, F |
| from aiogram.types import Update |
| from aiogram.enums import ParseMode |
| from aiogram.client.default import DefaultBotProperties |
|
|
| |
| logging.basicConfig(level=logging.INFO) |
|
|
| |
| BOT_TOKEN = os.getenv("BOT_TOKEN") |
| WEBHOOK_URL = os.getenv("WEBHOOK_URL") |
|
|
| bot = Bot(token=BOT_TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML)) |
| dp = Dispatcher() |
| app = FastAPI() |
|
|
| |
| |
| CHANNEL_MAP = { |
| -1001234567890: -1009876543210 |
| } |
|
|
| |
| album_buffer = {} |
|
|
|
|
| |
| |
| |
| @dp.message(F.web_app_data) |
| async def handle_web_app_data(message: types.Message): |
| |
| data_str = message.web_app_data.data |
| |
| try: |
| data = json.loads(data_str) |
| if data.get("action") == "set_sync": |
| source = data.get("source") |
| target = data.get("target") |
| |
| logging.info(f"收到新配置: {source} -> {target}") |
| |
| |
| CHANNEL_MAP[source] = target |
| |
| await message.answer( |
| f"✅ <b>配置保存成功!</b>\n\n将来从 <code>{source}</code> 发布的消息会自动同步到 <code>{target}</code>。", |
| parse_mode=ParseMode.HTML |
| ) |
| |
| except Exception as e: |
| logging.error(f"解析小程序数据失败: {e}") |
| await message.answer("❌ 配置解析失败,请重试。") |
| |
|
|
|
|
| |
| @dp.channel_post() |
| async def handle_channel_post(message: types.Message): |
| source_id = message.chat.id |
| |
| |
| if source_id not in CHANNEL_MAP: |
| return |
| |
| target_id = CHANNEL_MAP[source_id] |
|
|
| |
| if message.media_group_id: |
| mg_id = message.media_group_id |
| |
| |
| if mg_id not in album_buffer: |
| album_buffer[mg_id] = [message.message_id] |
| |
| asyncio.create_task(send_album_delayed(mg_id, source_id, target_id)) |
| else: |
| |
| album_buffer[mg_id].append(message.message_id) |
| |
| |
| else: |
| await bot.copy_message( |
| chat_id=target_id, |
| from_chat_id=source_id, |
| message_id=message.message_id |
| ) |
|
|
| |
| async def send_album_delayed(mg_id: str, source_id: int, target_id: int): |
| |
| await asyncio.sleep(2.5) |
| |
| |
| msg_ids = album_buffer.pop(mg_id, []) |
| |
| if msg_ids: |
| try: |
| |
| await bot.copy_messages( |
| chat_id=target_id, |
| from_chat_id=source_id, |
| message_ids=msg_ids |
| ) |
| logging.info(f"成功同步媒体组: {mg_id}") |
| except Exception as e: |
| logging.error(f"同步媒体组失败: {e}") |
|
|
|
|
| |
| @app.on_event("startup") |
| async def on_startup(): |
| |
| webhook_path = f"{WEBHOOK_URL}/webhook" |
| await bot.set_webhook(url=webhook_path) |
| logging.info(f"Webhook 已设置为: {webhook_path}") |
|
|
| @app.post("/webhook") |
| async def telegram_webhook(request: Request): |
| |
| update_dict = await request.json() |
| update = Update.model_validate(update_dict, context={"bot": bot}) |
| await dp.feed_update(bot, update) |
| return {"status": "ok"} |
|
|
| @app.get("/ping") |
| async def ping(): |
| |
| return {"status": "alive"} |
|
|