# import logging # from telegram.ext import ( # ApplicationBuilder, CommandHandler, MessageHandler, # CallbackQueryHandler, ChatMemberHandler, filters # ) # from app.config import load_config # from app.infra.metrics import start_metrics_server # # базовые хэндлеры # from app.bot.handlers.start import start, help_cmd, groups_cmd # from app.bot.handlers.add_group import add_group_cmd, add_group_capture # from app.bot.handlers.drafts import new_cmd, on_text # from app.bot.handlers.media import on_media # from app.bot.handlers.callbacks import on_callback # from app.bot.handlers.join_info import on_my_chat_member # from app.bot.handlers.chat_id_cmd import chat_id_cmd # from app.bot.handlers.bind_chat import bind_chat_cb # # безопасность/словарь # from app.bot.handlers.security import ( # security_cmd, security_cb, # spam_import_cmd, spam_import_capture, spam_import_text_capture, # dicts_cmd, dicts_cb, # ) # # модерация и диагностика # from app.bot.handlers.moderation import moderate_message # from app.bot.handlers.mod_status import mod_status_cmd # если нет — можете закомментировать # from app.bot.handlers.errors import on_error # from app.bot.handlers.cancel import cancel_cmd # from app.bot.handlers.drafts import on_text_gate # from app.bot.handlers.debug import dbg_state_cmd # async def spam_import_redirect(update, ctx): # await update.effective_message.reply_text( # "Эту команду нужно выполнять в личке. " # "Откройте чат со мной и пришлите /spam_import." # ) # def main(): # cfg = load_config() # logging.basicConfig(level=getattr(logging, cfg.log_level.upper(), logging.INFO)) # # ← СКРОЕМ «HTTP Request: …» от httpx/httpcore # logging.getLogger("httpx").setLevel(logging.WARNING) # logging.getLogger("httpx").propagate = False # logging.getLogger("httpcore").setLevel(logging.WARNING) # logging.getLogger("httpcore").propagate = False # # (опционально) если лишний шум от urllib3/telegram: # # logging.getLogger("urllib3").setLevel(logging.WARNING) # # logging.getLogger("telegram").setLevel(logging.INFO) # # запустить эндпоинт метрик (Prometheus будет ходить на порт cfg.metrics_port) # start_metrics_server(cfg.metrics_port) # app = ApplicationBuilder().token(cfg.bot_token).build() # # --- Commands --- # app.add_handler(CommandHandler("start", start)) # app.add_handler(CommandHandler("help", help_cmd)) # app.add_handler(CommandHandler("groups", groups_cmd)) # app.add_handler(CommandHandler("add_group", add_group_cmd)) # app.add_handler(CommandHandler("new", new_cmd)) # app.add_handler(CommandHandler("id", chat_id_cmd)) # app.add_handler(CommandHandler("mod_status", mod_status_cmd)) # app.add_handler(CommandHandler("cancel", cancel_cmd)) # app.add_handler(CommandHandler("dbg_state", dbg_state_cmd)) # # --- Callbacks (порядок важен) --- # app.add_handler(CallbackQueryHandler(security_cb, pattern=r"^pol:")) # настройки защитника # app.add_handler(CallbackQueryHandler(dicts_cb, pattern=r"^dict:")) # привязка словарей # app.add_handler(CallbackQueryHandler(bind_chat_cb, pattern=r"^bind:")) # привязка канала кнопкой # app.add_handler(CallbackQueryHandler(on_callback, pattern=r"^(draft_next_text:|tgl:|selall:|clear:|sendmulti:)")) # # --- Private chat helpers --- # app.add_handler(MessageHandler(filters.ChatType.PRIVATE & filters.FORWARDED, add_group_capture)) # app.add_handler(MessageHandler(filters.ChatType.PRIVATE & (filters.PHOTO | filters.VIDEO | filters.ANIMATION), on_media)) # # --- Join/rights updates --- # app.add_handler(ChatMemberHandler(on_my_chat_member, chat_member_types=ChatMemberHandler.MY_CHAT_MEMBER)) # # --- Security / Dict --- # app.add_handler(CommandHandler("security", security_cmd)) # # /spam_import — ТОЛЬКО в ЛС # app.add_handler(CommandHandler("spam_import", spam_import_cmd, filters.ChatType.PRIVATE)) # # редирект в группах # app.add_handler(CommandHandler("spam_import", spam_import_redirect, filters.ChatType.GROUPS)) # # файл словаря # app.add_handler(MessageHandler(filters.ChatType.PRIVATE & filters.Document.ALL, spam_import_capture)) # # текст словаря/параметров — ДО редактора, и не блокируем цепочку # app.add_handler(MessageHandler( # filters.ChatType.PRIVATE & filters.TEXT & ~filters.COMMAND, # spam_import_text_capture, # block=False # )) # # обзор словарей для политики # app.add_handler(CommandHandler("dicts", dicts_cmd)) # # --- Moderation in groups --- # app.add_handler(MessageHandler(filters.ChatType.GROUPS & ~filters.COMMAND, moderate_message)) # app.add_handler(MessageHandler( # filters.ChatType.PRIVATE & filters.TEXT & ~filters.COMMAND, # on_text_gate, # block=True # )) # # --- Draft editor (ПОСЛЕ импорт-хэндлеров) --- # app.add_handler(MessageHandler(filters.ChatType.PRIVATE & filters.TEXT & ~filters.COMMAND, on_text)) # app.add_error_handler(on_error) # app.run_polling(allowed_updates=None) # if __name__ == "__main__": # main() import logging from telegram.ext import ( ApplicationBuilder, CommandHandler, MessageHandler, CallbackQueryHandler, ChatMemberHandler, filters ) from app.config import load_config from app.infra.metrics import start_metrics_server # базовые хэндлеры from app.bot.handlers.start import start, help_cmd, groups_cmd from app.bot.handlers.add_group import add_group_cmd, add_group_capture from app.bot.handlers.drafts import new_cmd, on_text, on_text_gate # ← шлюз + редактор from app.bot.handlers.media import on_media from app.bot.handlers.callbacks import on_callback from app.bot.handlers.join_info import on_my_chat_member from app.bot.handlers.chat_id_cmd import chat_id_cmd from app.bot.handlers.bind_chat import bind_chat_cb # безопасность / словари from app.bot.handlers.security import ( security_cmd, security_cb, spam_import_cmd, spam_import_capture, spam_import_text_capture, dicts_cmd, dicts_cb, ) # модерация и диагностика from app.bot.handlers.moderation import moderate_message from app.bot.handlers.mod_status import mod_status_cmd # если нет — закомментировать from app.bot.handlers.errors import on_error from app.bot.handlers.cancel import cancel_cmd from app.bot.handlers.debug import dbg_state_cmd async def spam_import_redirect(update, ctx): await update.effective_message.reply_text( "Эту команду нужно выполнить в личке со мной. Откройте чат со мной и пришлите /spam_import." ) def main(): cfg = load_config() logging.basicConfig(level=getattr(logging, cfg.log_level.upper(), logging.INFO)) # скрыть шум httpx/httpcore logging.getLogger("httpx").setLevel(logging.WARNING) logging.getLogger("httpx").propagate = False logging.getLogger("httpcore").setLevel(logging.WARNING) logging.getLogger("httpcore").propagate = False # метрики Prometheus start_metrics_server(cfg.metrics_port) app = ApplicationBuilder().token(cfg.bot_token).build() # --- Commands --- app.add_handler(CommandHandler("start", start)) app.add_handler(CommandHandler("help", help_cmd)) app.add_handler(CommandHandler("groups", groups_cmd)) app.add_handler(CommandHandler("add_group", add_group_cmd)) app.add_handler(CommandHandler("new", new_cmd)) app.add_handler(CommandHandler("id", chat_id_cmd)) app.add_handler(CommandHandler("mod_status", mod_status_cmd)) app.add_handler(CommandHandler("cancel", cancel_cmd)) app.add_handler(CommandHandler("dbg_state", dbg_state_cmd)) # --- Callbacks (от узких к широким) --- app.add_handler(CallbackQueryHandler(security_cb, pattern=r"^pol:")) app.add_handler(CallbackQueryHandler(dicts_cb, pattern=r"^dict:")) app.add_handler(CallbackQueryHandler(bind_chat_cb, pattern=r"^bind:")) app.add_handler(CallbackQueryHandler( on_callback, pattern=r"^(draft_.*|tgl:|selall:|clear:|sendmulti:)" )) # --- Private chat helpers --- app.add_handler(MessageHandler(filters.ChatType.PRIVATE & filters.FORWARDED, add_group_capture)) app.add_handler(MessageHandler(filters.ChatType.PRIVATE & (filters.PHOTO | filters.VIDEO | filters.ANIMATION), on_media)) # --- Join/rights updates --- app.add_handler(ChatMemberHandler(on_my_chat_member, chat_member_types=ChatMemberHandler.MY_CHAT_MEMBER)) # --- Security / Dict --- app.add_handler(CommandHandler("security", security_cmd)) # /spam_import — только в ЛС app.add_handler(CommandHandler("spam_import", spam_import_cmd, filters.ChatType.PRIVATE)) # редирект из групп app.add_handler(CommandHandler("spam_import", spam_import_redirect, filters.ChatType.GROUPS)) # файл словаря app.add_handler(MessageHandler(filters.ChatType.PRIVATE & filters.Document.ALL, spam_import_capture)) # --- Private text handlers (ПОРЯДОК КРИТИЧЕН!) --- # 1) ШЛЮЗ: если ждём текст поста (await_text) — перехватываем и зовём on_text, блокируя цепочку app.add_handler(MessageHandler( filters.ChatType.PRIVATE & filters.TEXT & ~filters.COMMAND, on_text_gate, block=True )) # 2) Импорт словаря текстом — НЕ блокирует цепочку app.add_handler(MessageHandler( filters.ChatType.PRIVATE & filters.TEXT & ~filters.COMMAND, spam_import_text_capture, block=False )) # 3) Обычный редактор — последним app.add_handler(MessageHandler( filters.ChatType.PRIVATE & filters.TEXT & ~filters.COMMAND, on_text )) # --- Moderation in groups --- app.add_handler(MessageHandler(filters.ChatType.GROUPS & ~filters.COMMAND, moderate_message)) # --- Errors --- app.add_error_handler(on_error) app.run_polling(allowed_updates=None) if __name__ == "__main__": main()