Files
tg_post_min/app/bot/handlers/add_group.py
2025-08-20 21:10:31 +09:00

124 lines
4.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from telegram import Update
from telegram.constants import ParseMode, ChatType
from telegram.ext import ContextTypes
from telegram.error import BadRequest
from app.bot.messages import (
ASK_ADD_GROUP,
GROUP_BOUND,
NEED_ADD_FIRST,
NO_RIGHTS_CHANNEL,
NO_RIGHTS_GROUP,
)
from app.db.session import get_session
from app.db.models import User, Chat
from .utils import parse_chat_id, verify_and_fetch_chat
STATE_KEY = "await_chat_id"
def _get_forwarded_chat_id(message) -> int | None:
"""
Универсально достаём chat_id источника пересылки.
Поддерживает старые поля (forward_from_chat) и новые (forward_origin.chat).
"""
if not message:
return None
# Старое поле (иногда ещё присутствует)
fwd_chat = getattr(message, "forward_from_chat", None)
if fwd_chat:
return fwd_chat.id
# Новая схема Bot API: forward_origin с типами MessageOrigin*
origin = getattr(message, "forward_origin", None)
if origin:
chat = getattr(origin, "chat", None) # у MessageOriginChat/Channel есть .chat
if chat:
return chat.id
return None
async def add_group_cmd(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
# ensure user exists
with get_session() as s:
u = s.query(User).filter_by(tg_id=update.effective_user.id).first()
if not u:
u = User(tg_id=update.effective_user.id, name=update.effective_user.full_name)
s.add(u)
s.commit()
ctx.user_data[STATE_KEY] = True
await update.effective_message.reply_text(ASK_ADD_GROUP, parse_mode=ParseMode.MARKDOWN)
async def add_group_capture(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
if update.effective_chat.type != ChatType.PRIVATE:
return
if not ctx.user_data.get(STATE_KEY):
return
msg = update.effective_message
raw = None
# 1) Пересланное сообщение из чата/канала
fwd_cid = _get_forwarded_chat_id(msg)
if fwd_cid:
raw = fwd_cid
else:
# 2) Ввод в виде текста или подписи (caption)
txt = (getattr(msg, "text", None) or getattr(msg, "caption", None) or "").strip()
if not txt:
await msg.reply_text("Вставьте chat_id или перешлите сообщение из группы/канала.")
return
if txt.startswith("@") or "t.me/" in txt:
raw = txt
else:
cid = parse_chat_id(txt)
if cid is None:
await msg.reply_text("Не удалось распознать chat_id. Пример: -1001234567890 или @username.")
return
raw = cid
# Проверяем, что бот в чате и что у него есть право постить (если нужно)
try:
chat, member, can_post = await verify_and_fetch_chat(ctx, raw)
except BadRequest:
await msg.reply_text("Такого чата не существует или у меня нет доступа. Проверьте chat_id/username.")
return
if member is None:
await msg.reply_text(NEED_ADD_FIRST.format(title_or_id=(chat.title or chat.id)))
return
# Сохраняем привязку
with get_session() as s:
me = s.query(User).filter_by(tg_id=update.effective_user.id).first()
row = s.query(Chat).filter_by(chat_id=chat.id).first()
if not row:
row = Chat(
chat_id=chat.id,
type=chat.type,
title=chat.title,
owner_user_id=me.id,
can_post=can_post,
)
s.add(row)
else:
row.title = chat.title
row.type = chat.type
if row.owner_user_id is None:
row.owner_user_id = me.id
row.can_post = can_post
s.commit()
ctx.user_data.pop(STATE_KEY, None)
rights = (
"У меня есть право публиковать."
if can_post
else (NO_RIGHTS_CHANNEL if chat.type == ChatType.CHANNEL else NO_RIGHTS_GROUP)
)
await msg.reply_text(GROUP_BOUND.format(title_or_id=(chat.title or chat.id), rights=rights))