diff --git a/data/scheduled_post_Gemini_Generated_Image_lnhu05lnhu05lnhu.png b/data/scheduled_post_Gemini_Generated_Image_lnhu05lnhu05lnhu.png new file mode 100644 index 0000000..083d957 Binary files /dev/null and b/data/scheduled_post_Gemini_Generated_Image_lnhu05lnhu05lnhu.png differ diff --git a/services/scheduler.py b/services/scheduler.py index af3fc28..47d24db 100644 --- a/services/scheduler.py +++ b/services/scheduler.py @@ -358,8 +358,14 @@ class Scheduler: # HTTP прокси connector = aiohttp.TCPConnector() + # Отправляем пост в тему форума + message_id = None + + # Telegram не поддерживает фото + документ в одном сообщении + # Поэтому отправляем их отдельными сообщениями + + # 1. Сначала документ (если есть) — он главный if post.document_file_id: - # С документом - отправляем по file_id url = f"{base_url}/sendDocument" params = { 'chat_id': ADMIN_CHAT_ID, @@ -378,16 +384,16 @@ class Scheduler: else: error_text = await resp.text() raise Exception(f"Telegram API {resp.status}: {error_text}") - elif post.photo_file_id: - # С фото - отправляем по file_id + + # 2. Потом фото (если есть) — отдельным сообщением + if post.photo_file_id: url = f"{base_url}/sendPhoto" params = { 'chat_id': ADMIN_CHAT_ID, 'photo': post.photo_file_id, - 'caption': post.text, + 'caption': '📷 Приложение к посту' if post.document_file_id else post.text, 'parse_mode': 'HTML' } - # Не добавляем message_thread_id для general (1) — это общий чат if post.topic_id and post.topic_id > 1: params['message_thread_id'] = post.topic_id @@ -395,19 +401,21 @@ class Scheduler: async with http_session.post(url, json=params, timeout=30) as resp: if resp.status == 200: result_data = await resp.json() - message_id = result_data['result']['message_id'] + # message_id остаётся от документа или берём от фото + if not message_id: + message_id = result_data['result']['message_id'] else: error_text = await resp.text() - raise Exception(f"Telegram API {resp.status}: {error_text}") - else: - # Только текст + logger.warning(f"Не удалось отправить фото: {error_text}") + + # 3. Если ни документа ни фото — только текст + if not post.document_file_id and not post.photo_file_id: url = f"{base_url}/sendMessage" params = { 'chat_id': ADMIN_CHAT_ID, 'text': post.text, 'parse_mode': 'HTML' } - # Не добавляем message_thread_id для general (1) — это общий чат if post.topic_id and post.topic_id > 1: params['message_thread_id'] = post.topic_id @@ -428,6 +436,7 @@ class Scheduler: for user in users: try: + # Документ + фото отдельными сообщениями if post.document_file_id: url = f"{base_url}/sendDocument" params = { diff --git a/web/app.py b/web/app.py index 8ab7595..f30c27a 100644 --- a/web/app.py +++ b/web/app.py @@ -788,11 +788,17 @@ async def api_create_scheduled_post( # Парсим время scheduled_dt = datetime.fromisoformat(scheduled_time) - # Если есть timezone - конвертируем в UTC - if scheduled_dt.tzinfo is not None: + # Если нет timezone — считаем что это локальное время (UTC+4) + # и конвертируем в UTC для scheduler + if scheduled_dt.tzinfo is None: from datetime import timezone as tz + local_tz = tz(timedelta(hours=4)) # Ульяновск UTC+4 + scheduled_dt = scheduled_dt.replace(tzinfo=local_tz) # Помечаем как локальное + scheduled_dt = scheduled_dt.astimezone(tz.utc).replace(tzinfo=None) # Конвертируем в UTC + logger.info(f"⏰ Время конвертирована из локального в UTC: {scheduled_dt}") + else: scheduled_dt = scheduled_dt.astimezone(tz.utc).replace(tzinfo=None) - logger.info(f"⏰ Время конвертирована в UTC: {scheduled_dt}") + logger.info(f"⏰ Время уже с timezone, конвертирована в UTC: {scheduled_dt}") # Проверяем что время в будущем (по UTC) if scheduled_dt < datetime.utcnow(): @@ -816,7 +822,7 @@ async def api_create_scheduled_post( async with aiohttp.ClientSession() as session: url = f"https://api.telegram.org/bot{config.BOT_TOKEN}/sendPhoto" data = aiohttp.FormData() - data.add_field('chat_id', config.ADMIN_USER_ID) + data.add_field('chat_id', str(config.ADMIN_USER_ID)) data.add_field('photo', open(temp_path, 'rb'), filename=photo.filename) data.add_field('caption', 'Preview') @@ -851,8 +857,8 @@ async def api_create_scheduled_post( async with aiohttp.ClientSession() as session: url = f"https://api.telegram.org/bot{config.BOT_TOKEN}/sendDocument" data = aiohttp.FormData() - data.add_field('chat_id', config.ADMIN_USER_ID) - + data.add_field('chat_id', str(config.ADMIN_USER_ID)) + with open(temp_path, 'rb') as doc_file: data.add_field('document', doc_file, filename=document.filename) data.add_field('caption', 'Document preview') diff --git a/web/templates/scheduled_posts.html b/web/templates/scheduled_posts.html index e231a71..7332787 100644 --- a/web/templates/scheduled_posts.html +++ b/web/templates/scheduled_posts.html @@ -163,9 +163,7 @@ if (file) { nameSpan.textContent = file.name; preview.style.display = 'block'; - // Очищаем фото если выбран документ - document.getElementById('postPhoto').value = ''; - document.getElementById('preview').style.display = 'none'; + // НЕ очищаем фото — можно прикрепить и то и другое } else { preview.style.display = 'none'; }