120 lines
4.3 KiB
Python
120 lines
4.3 KiB
Python
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,
|
||
ONLY_ADMINS_CAN_BIND,
|
||
ALREADY_BOUND,
|
||
)
|
||
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:
|
||
fwd_chat = getattr(message, "forward_from_chat", None)
|
||
if fwd_chat:
|
||
return fwd_chat.id
|
||
origin = getattr(message, "forward_origin", None)
|
||
if origin:
|
||
chat = getattr(origin, "chat", None)
|
||
if chat:
|
||
return chat.id
|
||
return None
|
||
|
||
async def add_group_cmd(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
|
||
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 = _get_forwarded_chat_id(msg)
|
||
if not raw:
|
||
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_bot, can_post = await verify_and_fetch_chat(ctx, raw)
|
||
except BadRequest:
|
||
await msg.reply_text("Такого чата не существует или у меня нет доступа. Проверьте chat_id/username.")
|
||
return
|
||
|
||
if member_bot is None:
|
||
await msg.reply_text(NEED_ADD_FIRST.format(title_or_id=(chat.title or chat.id)))
|
||
return
|
||
|
||
# --- Новое: проверяем, что привязку делает АДМИН этого чата/канала ---
|
||
try:
|
||
user_member = await ctx.bot.get_chat_member(chat.id, update.effective_user.id)
|
||
user_status = getattr(user_member, "status", "")
|
||
is_admin = user_status in ("administrator", "creator")
|
||
except Exception:
|
||
is_admin = False
|
||
|
||
if not is_admin:
|
||
await msg.reply_text(ONLY_ADMINS_CAN_BIND)
|
||
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 row and row.owner_user_id and row.owner_user_id != me.id:
|
||
await msg.reply_text(ALREADY_BOUND)
|
||
ctx.user_data.pop(STATE_KEY, None)
|
||
return
|
||
|
||
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
|
||
row.owner_user_id = row.owner_user_id or 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))
|