init commit
This commit is contained in:
118
app/bot/handlers/callbacks.py
Normal file
118
app/bot/handlers/callbacks.py
Normal file
@@ -0,0 +1,118 @@
|
||||
from telegram import Update, InputMediaPhoto, InputMediaVideo, InputMediaAnimation
|
||||
from telegram.constants import ParseMode, ChatType
|
||||
from telegram.ext import ContextTypes
|
||||
|
||||
from app.db.session import get_session
|
||||
from app.db.models import Draft, Chat, Delivery
|
||||
from app.bot.keyboards.common import kb_choose_chat
|
||||
from app.bot.messages import READY_SELECT_CHAT, SENT_OK, SEND_ERR, NEED_MEDIA_BEFORE_NEXT, CANCELLED
|
||||
from .drafts import STATE_DRAFT, KEY_DRAFT_ID, STATE_AWAIT_TEXT, STATE_CONFIRM
|
||||
from .add_group import STATE_KEY # чтобы не конфликтовать по user_data ключам
|
||||
|
||||
|
||||
async def on_callback(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
|
||||
q = update.callback_query
|
||||
await q.answer()
|
||||
data = q.data
|
||||
|
||||
# --- Переход с медиа на текст ---
|
||||
if data.startswith("draft_next_text:"):
|
||||
draft_id = int(data.split(":")[1])
|
||||
with get_session() as s:
|
||||
d = s.get(Draft, draft_id)
|
||||
if not d:
|
||||
await q.edit_message_text("Черновик не найден.")
|
||||
return
|
||||
if len(d.media) == 0:
|
||||
await q.edit_message_text(NEED_MEDIA_BEFORE_NEXT)
|
||||
return
|
||||
ctx.user_data[KEY_DRAFT_ID] = draft_id
|
||||
ctx.user_data[STATE_DRAFT] = STATE_AWAIT_TEXT
|
||||
await q.edit_message_text("Шаг 2/3 — текст.\nОтправьте текст поста.")
|
||||
|
||||
# --- Подтверждение (Отправить) -> выбор чата ---
|
||||
elif data.startswith("draft_confirm_send:"):
|
||||
draft_id = int(data.split(":")[1])
|
||||
with get_session() as s:
|
||||
d = s.get(Draft, draft_id)
|
||||
if not d:
|
||||
await q.edit_message_text("Черновик не найден.")
|
||||
return
|
||||
d.status = "ready"
|
||||
s.commit()
|
||||
# Разрешённые чаты владельца черновика
|
||||
chats = s.query(Chat).filter_by(owner_user_id=d.user_id, can_post=True).all()
|
||||
buttons = [(c.title or str(c.chat_id), c.chat_id) for c in chats]
|
||||
kb = kb_choose_chat(draft_id, buttons)
|
||||
if not kb:
|
||||
await q.edit_message_text("Нет чатов с правом публикации. Добавьте/обновите через /add_group.")
|
||||
return
|
||||
ctx.user_data[STATE_DRAFT] = STATE_CONFIRM
|
||||
await q.edit_message_text(READY_SELECT_CHAT, reply_markup=kb)
|
||||
|
||||
# --- Отмена черновика ---
|
||||
elif data.startswith("draft_cancel:"):
|
||||
draft_id = int(data.split(":")[1])
|
||||
with get_session() as s:
|
||||
d = s.get(Draft, draft_id)
|
||||
if d:
|
||||
d.status = "cancelled"
|
||||
s.commit()
|
||||
ctx.user_data.pop(KEY_DRAFT_ID, None)
|
||||
ctx.user_data.pop(STATE_DRAFT, None)
|
||||
await q.edit_message_text(CANCELLED)
|
||||
|
||||
# --- Отправка в выбранный чат ---
|
||||
elif data.startswith("send:"):
|
||||
_, draft_id, chat_id = data.split(":")
|
||||
draft_id = int(draft_id); chat_id = int(chat_id)
|
||||
|
||||
with get_session() as s:
|
||||
d = s.get(Draft, draft_id)
|
||||
if not d:
|
||||
await q.edit_message_text("Черновик не найден.")
|
||||
return
|
||||
|
||||
media = list(sorted(d.media, key=lambda m: m.order))
|
||||
sent_ids = []
|
||||
try:
|
||||
if media:
|
||||
if len(media) > 1:
|
||||
im = []
|
||||
for i, m in enumerate(media):
|
||||
cap = d.text if i == 0 else None
|
||||
if m.kind == "photo":
|
||||
im.append(InputMediaPhoto(media=m.file_id, caption=cap, parse_mode=ParseMode.HTML))
|
||||
elif m.kind == "video":
|
||||
im.append(InputMediaVideo(media=m.file_id, caption=cap, parse_mode=ParseMode.HTML))
|
||||
elif m.kind == "animation":
|
||||
im.append(InputMediaAnimation(media=m.file_id, caption=cap, parse_mode=ParseMode.HTML))
|
||||
msgs = await ctx.bot.send_media_group(chat_id=chat_id, media=im)
|
||||
sent_ids = [str(m.message_id) for m in msgs]
|
||||
else:
|
||||
m = media[0]
|
||||
if m.kind == "photo":
|
||||
msg = await ctx.bot.send_photo(chat_id=chat_id, photo=m.file_id, caption=d.text, parse_mode=ParseMode.HTML)
|
||||
elif m.kind == "video":
|
||||
msg = await ctx.bot.send_video(chat_id=chat_id, video=m.file_id, caption=d.text, parse_mode=ParseMode.HTML)
|
||||
else:
|
||||
msg = await ctx.bot.send_animation(chat_id=chat_id, animation=m.file_id, caption=d.text, parse_mode=ParseMode.HTML)
|
||||
sent_ids = [str(msg.message_id)]
|
||||
else:
|
||||
msg = await ctx.bot.send_message(chat_id=chat_id, text=d.text or "(пусто)", parse_mode=ParseMode.HTML)
|
||||
sent_ids = [str(msg.message_id)]
|
||||
|
||||
deliv = Delivery(draft_id=d.id, chat_id=chat_id, status="sent", message_ids=",".join(sent_ids))
|
||||
s.add(deliv)
|
||||
d.status = "sent"
|
||||
s.commit()
|
||||
|
||||
# Сбрасываем пользовательское состояние редактора
|
||||
ctx.user_data.pop(KEY_DRAFT_ID, None)
|
||||
ctx.user_data.pop(STATE_DRAFT, None)
|
||||
|
||||
await q.edit_message_text(SENT_OK)
|
||||
except Exception as e:
|
||||
deliv = Delivery(draft_id=d.id, chat_id=chat_id, status="failed", error=str(e))
|
||||
s.add(deliv); s.commit()
|
||||
await q.edit_message_text(SEND_ERR.format(e=e))
|
||||
Reference in New Issue
Block a user