Files
post_bot/handlers/new_post.py
Choi A.K. d17f0f5507
Some checks failed
continuous-integration/drone/push Build is failing
async refactor & docker deploy environment
2025-09-05 12:04:58 +09:00

105 lines
5.4 KiB
Python

from telegram import Update, InputMediaPhoto, InlineKeyboardMarkup, InlineKeyboardButton
from telegram.ext import ContextTypes, ConversationHandler, MessageHandler, CommandHandler, filters, CallbackQueryHandler, ContextTypes
from db import AsyncSessionLocal
from models import Channel, Group, Button
SELECT_MEDIA, SELECT_TEXT, SELECT_TARGET = range(3)
async def new_post_start(update: Update, context: ContextTypes.DEFAULT_TYPE):
if update.message:
await update.message.reply_text('Отправьте картинку для поста или /skip:')
return SELECT_MEDIA
return ConversationHandler.END
async def select_media(update: Update, context: ContextTypes.DEFAULT_TYPE):
if update.message and hasattr(update.message, 'photo') and update.message.photo:
if context.user_data is None:
context.user_data = {}
context.user_data['photo'] = update.message.photo[-1].file_id
if update.message:
await update.message.reply_text('Введите текст поста или пересланное сообщение:')
return SELECT_TEXT
return ConversationHandler.END
async def select_text(update: Update, context: ContextTypes.DEFAULT_TYPE):
if update.message:
if context.user_data is None:
context.user_data = {}
context.user_data['text'] = getattr(update.message, 'text', None) or getattr(update.message, 'caption', None)
from sqlalchemy import select
session = AsyncSessionLocal()
try:
channels_result = await session.execute(select(Channel))
channels = channels_result.scalars().all()
groups_result = await session.execute(select(Group))
groups = groups_result.scalars().all()
keyboard = []
for c in channels:
keyboard.append([InlineKeyboardButton(f'Канал: {getattr(c, "name", str(c.name))}', callback_data=f'channel_{getattr(c, "id", str(c.id))}')])
for g in groups:
keyboard.append([InlineKeyboardButton(f'Группа: {getattr(g, "name", str(g.name))}', callback_data=f'group_{getattr(g, "id", str(g.id))}')])
reply_markup = InlineKeyboardMarkup(keyboard)
await update.message.reply_text('Выберите, куда отправить пост:', reply_markup=reply_markup)
return SELECT_TARGET
finally:
await session.close()
return ConversationHandler.END
async def select_target(update: Update, context: ContextTypes.DEFAULT_TYPE):
query = update.callback_query
if not query:
return ConversationHandler.END
await query.answer()
data = query.data
session = AsyncSessionLocal()
try:
chat_id = None
markup = None
if data and data.startswith('channel_'):
from sqlalchemy import select
channel_id = int(data.split('_')[1])
channel_result = await session.execute(select(Channel).where(Channel.id == channel_id))
channel = channel_result.scalar_one_or_none()
buttons_result = await session.execute(select(Button).where(Button.channel_id == channel_id))
buttons = buttons_result.scalars().all()
markup = InlineKeyboardMarkup([[InlineKeyboardButton(str(b.name), url=str(b.url))] for b in buttons]) if buttons else None
chat_id = getattr(channel, 'link', None)
elif data and data.startswith('group_'):
from sqlalchemy import select
group_id = int(data.split('_')[1])
group_result = await session.execute(select(Group).where(Group.id == group_id))
group = group_result.scalar_one_or_none()
buttons_result = await session.execute(select(Button).where(Button.group_id == group_id))
buttons = buttons_result.scalars().all()
markup = InlineKeyboardMarkup([[InlineKeyboardButton(str(b.name), url=str(b.url))] for b in buttons]) if buttons else None
chat_id = getattr(group, 'link', None)
if chat_id:
chat_id = chat_id.strip()
if not (chat_id.startswith('@') or chat_id.startswith('-')):
await query.edit_message_text('Ошибка: ссылка должна быть username (@channel) или числовой ID (-100...)')
return ConversationHandler.END
try:
photo = context.user_data.get('photo') if context.user_data else None
if photo:
await context.bot.send_photo(chat_id=chat_id, photo=photo, caption=context.user_data.get('text') if context.user_data else None, reply_markup=markup)
await query.edit_message_text('Пост отправлен!')
else:
await query.edit_message_text('Ошибка: не выбрано фото для поста.')
except Exception as e:
await query.edit_message_text(f'Ошибка отправки поста: {e}')
finally:
await session.close()
return ConversationHandler.END
new_post_conv = ConversationHandler(
entry_points=[CommandHandler('new_post', new_post_start)],
states={
SELECT_MEDIA: [MessageHandler(filters.PHOTO | filters.Document.IMAGE | filters.COMMAND, select_media)],
SELECT_TEXT: [MessageHandler(filters.TEXT | filters.FORWARDED, select_text)],
SELECT_TARGET: [CallbackQueryHandler(select_target)],
},
fallbacks=[],
)