script update
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2025-09-06 13:38:55 +09:00
parent ce8ec7db45
commit 2bcf07f6a9
2 changed files with 129 additions and 203 deletions

View File

@@ -140,149 +140,6 @@ async def select_text(update: Update, context: ContextTypes.DEFAULT_TYPE):
await update.message.reply_text('Выберите, куда отправить пост:', reply_markup=InlineKeyboardMarkup(keyboard))
return SELECT_TARGET
# 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
# async with AsyncSessionLocal() as session:
# chat_id = None
# markup = None
# selected_kind = None # "channel" | "group"
# selected_title = None
# if data and data.startswith('channel_'):
# selected_kind = "channel"
# channel_id = int(data.split('_')[1])
# # ACL: право постинга
# me = await get_or_create_admin(session, update.effective_user.id)
# allowed = await has_scope_on_channel(session, me.id, channel_id, SCOPE_POST)
# if not allowed:
# await query.edit_message_text("У вас нет права постить в этот канал.")
# return ConversationHandler.END
# channel = (await session.execute(sa_select(Channel).where(Channel.id == channel_id))).scalar_one_or_none()
# if not channel:
# await query.edit_message_text("Канал не найден.")
# return ConversationHandler.END
# chat_id = (channel.link or "").strip()
# selected_title = channel.name
# # кнопки канала
# btns = (await session.execute(sa_select(Button).where(Button.channel_id == channel_id))).scalars().all()
# if btns:
# markup = InlineKeyboardMarkup(
# [[InlineKeyboardButton(str(b.name), url=str(b.url))] for b in btns]
# )
# elif data and data.startswith('group_'):
# selected_kind = "group"
# group_id = int(data.split('_')[1])
# group = (await session.execute(sa_select(Group).where(Group.id == group_id))).scalar_one_or_none()
# if not group:
# await query.edit_message_text("Группа не найдена.")
# return ConversationHandler.END
# chat_id = (group.link or "").strip()
# selected_title = group.name
# # кнопки группы
# btns = (await session.execute(sa_select(Button).where(Button.group_id == group_id))).scalars().all()
# if btns:
# markup = InlineKeyboardMarkup(
# [[InlineKeyboardButton(str(b.name), url=str(b.url))] for b in btns]
# )
# if not chat_id or not (chat_id.startswith('@') or chat_id.startswith('-')):
# await query.edit_message_text('Ошибка: ссылка должна быть username (@channel) или числовой ID (-100...)')
# return ConversationHandler.END
# ud = context.user_data or {}
# text: str = ud.get("text", "") or ""
# entities: List[MessageEntity] = ud.get("entities", []) or []
# # санация для custom_emoji
# entities = _strip_broken_entities(entities)
# entities = _split_custom_emoji_by_utf16(text, entities)
# # если есть клавиатура, ПРЕДПОЧИТАЕМ отправку "вручную" (а не copyMessage),
# # т.к. в некоторых кейсах клавиатура при копировании может не приклеиться
# prefer_manual_send = markup is not None
# # определим, были ли “части медиа”
# has_media_parts = any(k in ud for k in ("photo","animation","video","document","audio","voice","sticker"))
# try:
# if not prefer_manual_send and ud.get("src_chat_id") and ud.get("src_msg_id") and not has_media_parts:
# # 1) copyMessage без медиа и без клавиатуры — максимальная идентичность
# msg_id_obj = await context.bot.copy_message(
# chat_id=chat_id,
# from_chat_id=ud["src_chat_id"],
# message_id=ud["src_msg_id"],
# reply_markup=markup # если вдруг есть, попробуем сразу
# )
# # страховка: если клавиатуры нет/не приклеилась — прикрутим edit_message_reply_markup
# if markup and getattr(msg_id_obj, "message_id", None):
# try:
# await context.bot.edit_message_reply_markup(
# chat_id=chat_id,
# message_id=msg_id_obj.message_id,
# reply_markup=markup
# )
# except Exception:
# pass
# await query.edit_message_text(f'Пост отправлен{" в: " + selected_title if selected_title else "!"}')
# return ConversationHandler.END
# # 2) fallback / manual — ВСЕГДА прикладываем reply_markup
# sent = False
# if "photo" in ud:
# await context.bot.send_photo(chat_id=chat_id, photo=ud["photo"],
# caption=(text or None), caption_entities=(entities if text else None),
# reply_markup=markup)
# sent = True
# elif "animation" in ud:
# await context.bot.send_animation(chat_id=chat_id, animation=ud["animation"],
# caption=(text or None), caption_entities=(entities if text else None),
# reply_markup=markup)
# sent = True
# elif "video" in ud:
# await context.bot.send_video(chat_id=chat_id, video=ud["video"],
# caption=(text or None), caption_entities=(entities if text else None),
# reply_markup=markup)
# sent = True
# elif "document" in ud:
# await context.bot.send_document(chat_id=chat_id, document=ud["document"],
# caption=(text or None), caption_entities=(entities if text else None),
# reply_markup=markup)
# sent = True
# elif "audio" in ud:
# await context.bot.send_audio(chat_id=chat_id, audio=ud["audio"],
# caption=(text or None), caption_entities=(entities if text else None),
# reply_markup=markup)
# sent = True
# elif "voice" in ud:
# await context.bot.send_voice(chat_id=chat_id, voice=ud["voice"],
# caption=(text or None), caption_entities=(entities if text else None),
# reply_markup=markup)
# sent = True
# elif "sticker" in ud:
# await context.bot.send_sticker(chat_id=chat_id, sticker=ud["sticker"], reply_markup=markup)
# if text:
# await context.bot.send_message(chat_id=chat_id, text=text, entities=entities)
# sent = True
# else:
# await context.bot.send_message(chat_id=chat_id, text=text, entities=entities, reply_markup=markup)
# sent = True
# await query.edit_message_text(f'Пост отправлен{" в: " + selected_title if selected_title else "!"}' if sent else 'Ошибка: не удалось отправить сообщение.')
# except BadRequest as e:
# await query.edit_message_text(f'Ошибка отправки поста: {e}')
# return ConversationHandler.END
async def select_target(update: Update, context: ContextTypes.DEFAULT_TYPE):
@@ -296,11 +153,11 @@ async def select_target(update: Update, context: ContextTypes.DEFAULT_TYPE):
chat_id = None
markup = None
selected_title = None
btns = []
if data and data.startswith('channel_'):
channel_id = int(data.split('_')[1])
# ACL
me = await get_or_create_admin(session, update.effective_user.id)
if not await has_scope_on_channel(session, me.id, channel_id, SCOPE_POST):
await query.edit_message_text("У вас нет права постить в этот канал.")
@@ -310,10 +167,10 @@ async def select_target(update: Update, context: ContextTypes.DEFAULT_TYPE):
if not channel:
await query.edit_message_text("Канал не найден.")
return ConversationHandler.END
chat_id = (channel.link or "").strip()
selected_title = channel.name
# КНОПКИ
btns = (await session.execute(sa_select(Button).where(Button.channel_id == channel_id))).scalars().all()
if btns:
markup = InlineKeyboardMarkup([[InlineKeyboardButton(str(b.name), url=str(b.url))] for b in btns])
@@ -324,74 +181,79 @@ async def select_target(update: Update, context: ContextTypes.DEFAULT_TYPE):
if not group:
await query.edit_message_text("Группа не найдена.")
return ConversationHandler.END
chat_id = (group.link or "").strip()
selected_title = group.name
btns = (await session.execute(sa_select(Button).where(Button.group_id == group_id))).scalars().all()
if btns:
markup = InlineKeyboardMarkup([[InlineKeyboardButton(str(b.name), url=str(b.url))] for b in btns])
markup = InlineKeyboardMarkup([[InlineKeyboardButton(str(b.name), url=str(b.url))] for b in btns]])
if not chat_id or not (chat_id.startswith('@') or chat_id.startswith('-')):
await query.edit_message_text('Ошибка: ссылка должна быть @username или -100...')
await query.edit_message_text('Ошибка: ссылка должна быть @username или -100')
return ConversationHandler.END
# DEBUG: покажем, сколько кнопок нашли и куда шлём
print(f"[DEBUG] send -> chat_id={chat_id} title={selected_title!r} buttons={len(btns)} has_markup={bool(markup)}")
ud = context.user_data or {}
text: str = ud.get("text", "") or ""
entities: List[MessageEntity] = ud.get("entities", []) or []
# санация custom_emoji/UTF-16
entities = _strip_broken_entities(entities)
entities = _split_custom_emoji_by_utf16(text, entities)
# >>> ВАЖНО: НИКАКОГО copyMessage. Всегда manual send с reply_markup <<<
try:
sent = False
sent_msg = None
# ВСЕГДА ручная отправка (никакого copyMessage), чтобы приклеить reply_markup
if "photo" in ud:
await context.bot.send_photo(chat_id=chat_id, photo=ud["photo"],
caption=(text or None),
caption_entities=(entities if text else None),
reply_markup=markup)
sent = True
sent_msg = await context.bot.send_photo(chat_id=chat_id, photo=ud["photo"],
caption=(text or None),
caption_entities=(entities if text else None),
reply_markup=markup)
elif "animation" in ud:
await context.bot.send_animation(chat_id=chat_id, animation=ud["animation"],
caption=(text or None),
caption_entities=(entities if text else None),
reply_markup=markup)
sent = True
sent_msg = await context.bot.send_animation(chat_id=chat_id, animation=ud["animation"],
caption=(text or None),
caption_entities=(entities if text else None),
reply_markup=markup)
elif "video" in ud:
await context.bot.send_video(chat_id=chat_id, video=ud["video"],
caption=(text or None),
caption_entities=(entities if text else None),
reply_markup=markup)
sent = True
sent_msg = await context.bot.send_video(chat_id=chat_id, video=ud["video"],
caption=(text or None),
caption_entities=(entities if text else None),
reply_markup=markup)
elif "document" in ud:
await context.bot.send_document(chat_id=chat_id, document=ud["document"],
caption=(text or None),
caption_entities=(entities if text else None),
reply_markup=markup)
sent = True
sent_msg = await context.bot.send_document(chat_id=chat_id, document=ud["document"],
caption=(text or None),
caption_entities=(entities if text else None),
reply_markup=markup)
elif "audio" in ud:
await context.bot.send_audio(chat_id=chat_id, audio=ud["audio"],
caption=(text or None),
caption_entities=(entities if text else None),
reply_markup=markup)
sent = True
sent_msg = await context.bot.send_audio(chat_id=chat_id, audio=ud["audio"],
caption=(text or None),
caption_entities=(entities if text else None),
reply_markup=markup)
elif "voice" in ud:
await context.bot.send_voice(chat_id=chat_id, voice=ud["voice"],
caption=(text or None),
caption_entities=(entities if text else None),
reply_markup=markup)
sent = True
sent_msg = await context.bot.send_voice(chat_id=chat_id, voice=ud["voice"],
caption=(text or None),
caption_entities=(entities if text else None),
reply_markup=markup)
elif "sticker" in ud:
await context.bot.send_sticker(chat_id=chat_id, sticker=ud["sticker"], reply_markup=markup)
sent_msg = await context.bot.send_sticker(chat_id=chat_id, sticker=ud["sticker"], reply_markup=markup)
if text:
await context.bot.send_message(chat_id=chat_id, text=text, entities=entities)
sent = True
else:
await context.bot.send_message(chat_id=chat_id, text=text, entities=entities, reply_markup=markup)
sent = True
sent_msg = await context.bot.send_message(chat_id=chat_id, text=text, entities=entities, reply_markup=markup)
# страховка: если вдруг Telegram проглотил клаву — доклеим через edit_message_reply_markup
if markup and getattr(sent_msg, "message_id", None):
try:
await context.bot.edit_message_reply_markup(chat_id=chat_id,
message_id=sent_msg.message_id,
reply_markup=markup)
except Exception:
pass
await query.edit_message_text(f'Пост отправлен{(" в: " + selected_title) if selected_title else "!"}')
await query.edit_message_text(f'Пост отправлен{(" в: " + selected_title) if selected_title else "!"}' if sent else 'Ошибка: не удалось отправить сообщение.')
except BadRequest as e:
await query.edit_message_text(f'Ошибка отправки поста: {e}')