This commit is contained in:
+116
-35
@@ -16,6 +16,16 @@ from io import BytesIO
|
||||
from flask import Flask, request
|
||||
from formatter import get_post_text, get_event_text
|
||||
from telegram_relay import configure_telebot_api, get_relay_url, bot_api_method_url
|
||||
from season_links import (
|
||||
SEASON,
|
||||
callback_subscribe_post,
|
||||
callback_unsubscribe_post,
|
||||
callback_subscribe_event,
|
||||
callback_unsubscribe_event,
|
||||
parse_start_payload,
|
||||
parse_post_callback,
|
||||
parse_event_callback,
|
||||
)
|
||||
|
||||
# Создаем Flask app на верхнем уровне для экспорта
|
||||
app = Flask(__name__)
|
||||
@@ -179,6 +189,7 @@ logger.info(f"Telegram Bot API через ретранслятор: {relay}")
|
||||
|
||||
# Создаем экземпляр бота
|
||||
bot = telebot.TeleBot(RESPONDER_BOT_TOKEN)
|
||||
logger.info(f"Сезон подписок SEASON={SEASON}")
|
||||
|
||||
def get_user_name(user):
|
||||
"""Форматирует имя пользователя для записи в БД"""
|
||||
@@ -572,6 +583,65 @@ def format_channel_link(post_id=None):
|
||||
else:
|
||||
return f"https://t.me/c/{CHANNEL_ID}"
|
||||
|
||||
|
||||
def get_last_channel_message_id():
|
||||
"""Максимальный tg_message_id среди опубликованных постов и событий (текущая БД)."""
|
||||
conn = create_db_connection()
|
||||
if conn is None:
|
||||
return None
|
||||
try:
|
||||
with conn.cursor() as cursor:
|
||||
cursor.execute(
|
||||
"""
|
||||
SELECT MAX(mid) AS last_id FROM (
|
||||
SELECT MAX(tg_message_id) AS mid FROM posts
|
||||
WHERE tg_message_id IS NOT NULL AND tg_message_id > 0
|
||||
UNION ALL
|
||||
SELECT MAX(tg_message_id) AS mid FROM events
|
||||
WHERE tg_message_id IS NOT NULL AND tg_message_id > 0
|
||||
) t
|
||||
"""
|
||||
)
|
||||
row = cursor.fetchone()
|
||||
last_id = row["last_id"] if row else None
|
||||
return int(last_id) if last_id else None
|
||||
except pymysql.Error as e:
|
||||
logger.error(f"Ошибка получения последнего message_id канала: {e}")
|
||||
return None
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def get_return_to_channel_link():
|
||||
"""Ссылка на последнее известное сообщение в канале или на сам канал."""
|
||||
last_id = get_last_channel_message_id()
|
||||
if last_id:
|
||||
return format_channel_link(last_id)
|
||||
return format_channel_link()
|
||||
|
||||
|
||||
def create_season_ended_keyboard():
|
||||
keyboard = InlineKeyboardMarkup()
|
||||
keyboard.row(
|
||||
InlineKeyboardButton("↩ Вернуться в канал", url=get_return_to_channel_link())
|
||||
)
|
||||
return keyboard
|
||||
|
||||
|
||||
def send_season_ended_message(chat_id):
|
||||
"""Ответ на клик по подписке прошлого сезона (или без префикса SEASON)."""
|
||||
logger.info(f"send_season_ended_message chat_id={chat_id}, current SEASON={SEASON}")
|
||||
text = (
|
||||
"Этот сезон уже завершён.\n\n"
|
||||
"Подписки и кнопки из прошлых анонсов больше не работают. "
|
||||
"Актуальные события — в канале."
|
||||
)
|
||||
bot.send_message(
|
||||
chat_id,
|
||||
text,
|
||||
reply_markup=create_season_ended_keyboard(),
|
||||
)
|
||||
|
||||
def create_help_keyboard():
|
||||
"""Создает клавиатуру для справки"""
|
||||
logger.info(f"starting create_help_keyboard")
|
||||
@@ -601,13 +671,13 @@ def create_manage_keyboard(post_id, is_subscribed):
|
||||
if is_subscribed:
|
||||
keyboard.row(
|
||||
InlineKeyboardButton("❓ Справка", callback_data="cmd_help"),
|
||||
InlineKeyboardButton("❌ Отписаться", callback_data=f"unsubscribe_{post_id}"),
|
||||
InlineKeyboardButton("❌ Отписаться", callback_data=callback_unsubscribe_post(post_id)),
|
||||
InlineKeyboardButton("↪ Назад", url=channel_link)
|
||||
)
|
||||
else:
|
||||
keyboard.row(
|
||||
InlineKeyboardButton("❓ Справка", callback_data="cmd_help"),
|
||||
InlineKeyboardButton("✔ Подписаться", callback_data=f"subscribe_{post_id}"),
|
||||
InlineKeyboardButton("✔ Подписаться", callback_data=callback_subscribe_post(post_id)),
|
||||
InlineKeyboardButton("↪ Назад", url=channel_link)
|
||||
)
|
||||
return keyboard
|
||||
@@ -621,13 +691,13 @@ def create_manage_keyboard_evt(event_id, is_subscribed):
|
||||
if is_subscribed:
|
||||
keyboard.row(
|
||||
InlineKeyboardButton("❓ Справка", callback_data="cmd_help"),
|
||||
InlineKeyboardButton("❌ Отписаться", callback_data=f"unsubscribe_evt_{event_id}"),
|
||||
InlineKeyboardButton("❌ Отписаться", callback_data=callback_unsubscribe_event(event_id)),
|
||||
InlineKeyboardButton("↪ Назад", url=channel_link)
|
||||
)
|
||||
else:
|
||||
keyboard.row(
|
||||
InlineKeyboardButton("❓ Справка", callback_data="cmd_help"),
|
||||
InlineKeyboardButton("✔ Подписаться", callback_data=f"subscribe_evt_{event_id}"),
|
||||
InlineKeyboardButton("✔ Подписаться", callback_data=callback_subscribe_event(event_id)),
|
||||
InlineKeyboardButton("↪ Назад", url=channel_link)
|
||||
)
|
||||
|
||||
@@ -1028,18 +1098,19 @@ def handle_start(message):
|
||||
user_name = get_user_name(user)
|
||||
|
||||
if len(args) > 1:
|
||||
# Обработка команды подписки на посты
|
||||
if args[1].startswith('post_'):
|
||||
post_id = args[1].split('_')[1]
|
||||
# Отправляем сообщение управления подпиской
|
||||
send_management_message(message.chat.id, post_id, user_id, user_name)
|
||||
kind, entity_id, is_current = parse_start_payload(args[1])
|
||||
if not is_current:
|
||||
send_season_ended_message(message.chat.id)
|
||||
return
|
||||
# Обработка команды подписки на события
|
||||
elif args[1].startswith('event_'):
|
||||
event_id = args[1].split('_')[1]
|
||||
# Отправляем сообщение управления подпиской
|
||||
send_management_message_evt(message.chat.id, event_id, user_id, user_name)
|
||||
if kind == "post" and entity_id:
|
||||
send_management_message(message.chat.id, entity_id, user_id, user_name)
|
||||
return
|
||||
if kind == "event" and entity_id:
|
||||
send_management_message_evt(message.chat.id, entity_id, user_id, user_name)
|
||||
return
|
||||
# Неизвестный payload текущего сезона
|
||||
send_season_ended_message(message.chat.id)
|
||||
return
|
||||
|
||||
# Команда /start без параметров
|
||||
welcome_text = get_welcome_text()
|
||||
@@ -1312,17 +1383,26 @@ def handle_callback(call):
|
||||
return
|
||||
|
||||
# Обработка кнопок управления подпиской на посты
|
||||
if (call.data.startswith("subscribe_") or call.data.startswith("unsubscribe_")) and not call.data.startswith(("subscribe_evt_", "unsubscribe_evt_")):
|
||||
action, post_id, is_current = parse_post_callback(call.data)
|
||||
if action and post_id:
|
||||
if not is_current:
|
||||
bot.answer_callback_query(call.id, "Этот сезон уже завершён")
|
||||
send_season_ended_message(call.message.chat.id)
|
||||
return
|
||||
|
||||
user = call.from_user
|
||||
user_id = user.id
|
||||
user_name = get_user_name(user)
|
||||
|
||||
# Разделяем данные callback
|
||||
parts = call.data.split('_', 1)
|
||||
action = parts[0]
|
||||
post_id = parts[1]
|
||||
if not get_post_data(post_id):
|
||||
bot.answer_callback_query(call.id, "Анонс не найден")
|
||||
bot.send_message(
|
||||
call.message.chat.id,
|
||||
"❌ Анонс не найден в базе данных текущего сезона.",
|
||||
reply_markup=create_season_ended_keyboard(),
|
||||
)
|
||||
return
|
||||
|
||||
# Выполняем действие
|
||||
if action == "subscribe":
|
||||
save_mark_to_db(post_id, user_id, user_name)
|
||||
result_text = "✅ Вы успешно подписались!"
|
||||
@@ -1371,15 +1451,26 @@ def handle_callback(call):
|
||||
return
|
||||
|
||||
# Обработка кнопок управления подпиской на события
|
||||
if call.data.startswith("subscribe_evt_") or call.data.startswith("unsubscribe_evt_"):
|
||||
action, event_id, is_current = parse_event_callback(call.data)
|
||||
if action and event_id:
|
||||
if not is_current:
|
||||
bot.answer_callback_query(call.id, "Этот сезон уже завершён")
|
||||
send_season_ended_message(call.message.chat.id)
|
||||
return
|
||||
|
||||
user = call.from_user
|
||||
user_id = user.id
|
||||
user_name = get_user_name(user)
|
||||
parts = call.data.split('_', 2)
|
||||
action = parts[0]
|
||||
event_id = parts[2]
|
||||
|
||||
# Выполняем действие
|
||||
if not get_event_data(event_id):
|
||||
bot.answer_callback_query(call.id, "Событие не найдено")
|
||||
bot.send_message(
|
||||
call.message.chat.id,
|
||||
"❌ Событие не найдено в базе данных текущего сезона.",
|
||||
reply_markup=create_season_ended_keyboard(),
|
||||
)
|
||||
return
|
||||
|
||||
if action == "subscribe":
|
||||
save_mark_to_db_evt(event_id, user_id, user_name)
|
||||
result_text = "✅ Вы успешно подписались!"
|
||||
@@ -1387,22 +1478,14 @@ def handle_callback(call):
|
||||
remove_mark_from_db_evt(event_id, user_id, user_name)
|
||||
result_text = "✅ Вы успешно отписались!"
|
||||
|
||||
# Обновляем сообщение с новым статусом
|
||||
try:
|
||||
# Получаем текущие данные о событии
|
||||
event_data = format_event_message(event_id)
|
||||
text = event_data['text']
|
||||
|
||||
# Создаем новую клавиатуру
|
||||
is_subscribed = action == "subscribe"
|
||||
keyboard = create_manage_keyboard_evt(event_id, is_subscribed)
|
||||
|
||||
# Для сообщений с изображением
|
||||
if call.message.content_type == 'photo':
|
||||
# Получаем file_id существующего изображения
|
||||
file_id = call.message.photo[-1].file_id
|
||||
|
||||
# Редактируем подпись к изображению
|
||||
bot.edit_message_caption(
|
||||
chat_id=call.message.chat.id,
|
||||
message_id=call.message.message_id,
|
||||
@@ -1411,7 +1494,6 @@ def handle_callback(call):
|
||||
parse_mode='HTML'
|
||||
)
|
||||
else:
|
||||
# Редактируем текстовое сообщение
|
||||
bot.edit_message_text(
|
||||
chat_id=call.message.chat.id,
|
||||
message_id=call.message.message_id,
|
||||
@@ -1420,7 +1502,6 @@ def handle_callback(call):
|
||||
parse_mode='HTML'
|
||||
)
|
||||
|
||||
# Отправляем отдельное сообщение о результате
|
||||
bot.answer_callback_query(call.id, result_text)
|
||||
except Exception as e:
|
||||
logger.error(f"Ошибка обновления сообщения (events): {e}")
|
||||
|
||||
Reference in New Issue
Block a user