TG бот (предложка). Как решить проблему выкладки постов
Когда планируешь два поста, то он выставляет самый последний по времени самого первого поста. Как исправить?
Говорят, что проблема в переменной user_data, оно перезаписывается при каждом новом добавлении поста. Когда админ добавляет новый пост, то старый стирается. Но как это исправить я без понятия.
from telebot import TeleBot, types
from datetime import datetime
import threading
import time
bot = TeleBot("BOT_TOKEN")
# Временное хранилище данных для каждого пользователя
user_data = {}
# Каналы для публикации (используем ID канала)
CHANNELS = {
"long_term": id_channel, # 1 группа
"medium_term": id_channel, # 2 группа
"news": id_channel # 3 группа
}
# Команда /start для начала создания поста
@bot.message_handler(commands=['start'])
def start_post(message):
user_id = message.from_user.id
user_data[user_id] = {"content": [], "posting_in_progress": True}
request_skip_or_photo(user_id)
# Функция для отображения кнопок пропуска или отправки фото
def request_skip_or_photo(user_id):
markup = types.InlineKeyboardMarkup(row_width=1)
markup.add(
types.InlineKeyboardButton("Пропустить", callback_data="skip_photo")
)
bot.send_message(user_id, "Отправьте картинку или пропустите:", reply_markup=markup)
# Обработчик для пропуска фото
@bot.callback_query_handler(func=lambda call: call.data == "skip_photo")
def skip_photo(call):
user_id = call.from_user.id
user_data[user_id]["content"].append({"type": "photo", "file_id": None})
request_skip_or_text(user_id)
# Функция для отображения кнопок пропуска или отправки текста
def request_skip_or_text(user_id):
markup = types.InlineKeyboardMarkup(row_width=1)
markup.add(
types.InlineKeyboardButton("Пропустить", callback_data="skip_text")
)
bot.send_message(user_id, "Отправьте текст или пропустите:", reply_markup=markup)
# Обработчик для пропуска текста
@bot.callback_query_handler(func=lambda call: call.data == "skip_text")
def skip_text(call):
user_id = call.from_user.id
user_data[user_id]["content"].append({"type": "text", "text": None})
bot.send_message(user_id, "Выберите канал для публикации.")
request_channel(user_id)
# Обработчик для картинок (если пользователь отправляет фото вместо пропуска)
@bot.message_handler(content_types=['photo'])
def save_photo_content(message):
user_id = message.from_user.id
if user_id not in user_data or not user_data[user_id].get("posting_in_progress"):
bot.send_message(user_id, "Сначала отправьте команду /start.")
return
# Сохраняем фото
user_data[user_id]["content"].append({"type": "photo", "file_id": message.photo[-1].file_id})
request_skip_or_text(user_id)
# Обработчик для текстового контента
@bot.message_handler(func=lambda message: message.from_user.id in user_data and user_data[message.from_user.id].get(
"posting_in_progress"))
def save_text_content(message):
user_id = message.from_user.id
user_data[user_id]["content"].append({"type": "text", "text": message.text})
request_channel(user_id)
# Функция для отображения кнопок выбора канала
def request_channel(user_id):
markup = types.InlineKeyboardMarkup(row_width=1)
markup.add(
types.InlineKeyboardButton("Долгосрочные инвестиции | Phipness Core", callback_data="long_term"),
types.InlineKeyboardButton("Среднесрочные инвестиции | Phipness Core", callback_data="medium_term"),
types.InlineKeyboardButton("Новости Инвестиции | Phipness Core", callback_data="news")
)
bot.send_message(user_id, "Выберите канал для публикации:", reply_markup=markup)
# Обработчик для выбора канала
@bot.callback_query_handler(func=lambda call: call.data in CHANNELS)
def channel_selection(call):
user_id = call.from_user.id
user_data[user_id]["channel"] = CHANNELS[call.data]
# Получаем текущую дату и время
current_time = datetime.now().strftime("%d.%m.%Y %H:%M")
# Формируем сообщение с примером времени
markup = types.InlineKeyboardMarkup(row_width=1)
markup.add(
types.InlineKeyboardButton("Выставить пост сразу", callback_data="post_now")
)
bot.send_message(
user_id,
f"Когда мне выставить пост?\nПример: {current_time}",
reply_markup=markup
)
# Убираем флаг ожидания канала
user_data[user_id]["posting_in_progress"] = False
# Обработчик для немедленной отправки поста
@bot.callback_query_handler(func=lambda call: call.data == "post_now")
def post_now(call):
user_id = call.from_user.id
if user_id in user_data:
channel_id = user_data[user_id]["channel"]
content = user_data[user_id]["content"]
# Отправка содержимого (картинка + текст)
photo_sent = False
for item in content:
if item["type"] == "photo" and item["file_id"]:
caption = next((i["text"] for i in content if i["type"] == "text" and i["text"]), "")
bot.send_photo(channel_id, item["file_id"], caption=caption)
photo_sent = True
if not photo_sent:
text_content = next((i["text"] for i in content if i["type"] == "text" and i["text"]), None)
if text_content:
bot.send_message(channel_id, text_content)
# Подтверждение отправки поста
bot.send_message(user_id, "Ваш пост был успешно опубликован!")
# Удаление данных после отправки
del user_data[user_id]
# Обработчик для установки времени публикации
@bot.message_handler(
func=lambda message: message.from_user.id in user_data and "post_time" not in user_data[message.from_user.id])
def set_time(message):
user_id = message.from_user.id
try:
post_time = datetime.strptime(message.text, "%d.%m.%Y %H:%M")
user_data[user_id]["post_time"] = post_time
bot.send_message(message.chat.id,
f"Ваш пост запланирован на {post_time.strftime('%d.%m.%Y %H:%M')}. Он будет опубликован.")
# Запуск задачи для отложенной публикации
threading.Thread(target=schedule_post, args=(user_id, post_time)).start()
except ValueError:
bot.send_message(message.chat.id, "Неверный формат времени. Попробуйте ещё раз.")
# Функция для отложенной отправки поста
def schedule_post(user_id, post_time):
# Ожидание до времени публикации
while datetime.now() < post_time:
time.sleep(5)
# Проверка, что данные пользователя не были удалены
if user_id in user_data:
channel_id = user_data[user_id]["channel"]
content = user_data[user_id]["content"]
# Отправка содержимого (картинка + текст)
photo_sent = False
for item in content:
if item["type"] == "photo" and item["file_id"]:
caption = next((i["text"] for i in content if i["type"] == "text" and i["text"]), "")
bot.send_photo(channel_id, item["file_id"], caption=caption)
photo_sent = True
if not photo_sent:
text_content = next((i["text"] for i in content if i["type"] == "text" and i["text"]), None)
if text_content:
bot.send_message(channel_id, text_content)
# Подтверждение отправки поста
bot.send_message(user_id, "Ваш пост был успешно опубликован!")
# Удаление данных после отправки
del user_data[user_id]
# Запуск бота
bot.polling(none_stop=True)