📌 snapshot before scheduled posts feature - v1.2 prep
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
parent
1e61eca60c
commit
1825d26230
10 changed files with 430 additions and 11 deletions
BIN
data/broadcast_Gemini_Generated_Image_7v4paw7v4paw7v4p.png
Normal file
BIN
data/broadcast_Gemini_Generated_Image_7v4paw7v4paw7v4p.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 MiB |
BIN
data/service_images/masters_0d95ea9537e4480b82da5b475c34dfe2.png
Normal file
BIN
data/service_images/masters_0d95ea9537e4480b82da5b475c34dfe2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 MiB |
BIN
data/service_images/masters_715a0073539c410daae24f5b59c07b74.png
Normal file
BIN
data/service_images/masters_715a0073539c410daae24f5b59c07b74.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 MiB |
|
|
@ -206,8 +206,7 @@ async def cmd_help(message: Message):
|
|||
<b>📱 Доступные команды:</b>
|
||||
|
||||
<b>Для всех:</b>
|
||||
📞 /телефон — Экстренные службы
|
||||
👷 /мастера — Сантехники, электрики
|
||||
📞 /телефон — Экстренные службы (включая мастеров)
|
||||
👮 /участковый — Контакты полиции
|
||||
📜 /правила — Правила чата
|
||||
❓ /помощь — Эта справка
|
||||
|
|
|
|||
|
|
@ -39,10 +39,7 @@ def get_main_menu(verified: bool = False, is_ig: bool = False, is_admin: bool =
|
|||
builder.row(
|
||||
InlineKeyboardButton(text=f'{level_emoji} 📞 Экстренные телефоны', callback_data='phones'),
|
||||
)
|
||||
builder.row(
|
||||
InlineKeyboardButton(text=f'{level_emoji} 👷 Мастера', callback_data='masters'),
|
||||
)
|
||||
|
||||
|
||||
# Только для верифицированных
|
||||
if verified:
|
||||
builder.row(
|
||||
|
|
@ -207,7 +204,6 @@ def get_unverified_menu() -> InlineKeyboardMarkup:
|
|||
InlineKeyboardButton(text=f'{emoji} 📞 Экстренные телефоны', callback_data='phones'),
|
||||
)
|
||||
builder.row(
|
||||
InlineKeyboardButton(text=f'{emoji} 👷 Мастера', callback_data='masters'),
|
||||
InlineKeyboardButton(text=f'{emoji} 👮 Участковый', callback_data='police'),
|
||||
)
|
||||
builder.row(
|
||||
|
|
|
|||
|
|
@ -11,15 +11,14 @@ def get_reply_menu() -> ReplyKeyboardMarkup:
|
|||
Используется редко, в основном для важных действий
|
||||
"""
|
||||
builder = ReplyKeyboardBuilder()
|
||||
|
||||
|
||||
builder.row(
|
||||
KeyboardButton(text='📞 Телефоны'),
|
||||
KeyboardButton(text='👷 Мастера'),
|
||||
)
|
||||
builder.row(
|
||||
KeyboardButton(text='❓ Помощь'),
|
||||
)
|
||||
|
||||
|
||||
# Resize keyboard чтобы не занимал много места
|
||||
return builder.as_markup(resize_keyboard=True, one_time_keyboard=False)
|
||||
|
||||
|
|
|
|||
136
send_forum_capabilities.py
Normal file
136
send_forum_capabilities.py
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Отправка подробного отчёта о возможностях рассылки бота
|
||||
"""
|
||||
import asyncio
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
BASE_DIR = Path(__file__).resolve().parent
|
||||
sys.path.insert(0, str(BASE_DIR))
|
||||
|
||||
from aiogram import Bot
|
||||
from aiogram.client.default import DefaultBotProperties
|
||||
from aiogram.enums import ParseMode
|
||||
from aiogram.client.session.aiohttp import AiohttpSession
|
||||
|
||||
from config import BOT_TOKEN, ADMIN_USER_ID, get_proxy_url
|
||||
|
||||
async def send_report():
|
||||
"""Отправка отчёта админу"""
|
||||
proxy_url = get_proxy_url()
|
||||
|
||||
if proxy_url:
|
||||
session = AiohttpSession(proxy=proxy_url)
|
||||
bot = Bot(token=BOT_TOKEN, session=session, default=DefaultBotProperties(parse_mode=ParseMode.HTML))
|
||||
else:
|
||||
bot = Bot(token=BOT_TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML))
|
||||
|
||||
message = """
|
||||
📊 <b>АНАЛИЗ ВОЗМОЖНОСТЕЙ РАССЫЛКИ ДОМОВОГО БОТА</b>
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
🎯 <b>ОТВЕТЫ НА ТВОИ ВОПРОСЫ:</b>
|
||||
|
||||
✅ <b>1. МОЖЕТ ЛИ БОТ ПИСАТЬ В ОТДЕЛЬНУЮ ТЕМУ?</b>
|
||||
|
||||
Да! Бот уже настроен для работы с темами форума Telegram.
|
||||
|
||||
📋 <b>Настроенные темы:</b>
|
||||
├ 1️⃣ Общий чат (ID: 1)
|
||||
├ 2️⃣ Важные объявления (ID: 6258)
|
||||
├ 3️⃣ Ссылки (ID: 6265)
|
||||
├ 4️⃣ Мемы (ID: 6262)
|
||||
├ 5️⃣ Для автовладельцев (ID: 6266)
|
||||
├ 6️⃣ Потеряшки (ID: 6263)
|
||||
├ 7️⃣ Собрания собственников (ID: 6261)
|
||||
├ 8️⃣ Вывоз КГМ (ID: 6264)
|
||||
├ 9️⃣ Переписка с УО (ID: 6260)
|
||||
└ 🔟 Важные телефоны (ID: 6259)
|
||||
|
||||
💡 <b>Как работает:</b>
|
||||
Бот использует параметр message_thread_id при отправке:
|
||||
• send_message(chat_id=CHAT_ID, message_thread_id=TOPIC_ID)
|
||||
• Это позволяет писать в КОНКРЕТНУЮ тему!
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✅ <b>2. МОЖЕТ ЛИ БОТ ПИСАТЬ В ОБЩИЙ ЧАТ?</b>
|
||||
|
||||
Да! Уже реализовано в нескольких местах:
|
||||
|
||||
📤 <b>Способы рассылки:</b>
|
||||
|
||||
<b>1️⃣ Через админку в Telegram:</b>
|
||||
/admin → кнопка «📤 Рассылка»
|
||||
→ Отправляет в ОБЩУЮ ТЕМУ + всем жильцам в личку
|
||||
|
||||
<b>2️⃣ Через веб-панель (порт 8000):</b>
|
||||
http://localhost:8000/broadcast
|
||||
→ Выбор получателей:
|
||||
• Все верифицированные + чат
|
||||
• Только ИГ
|
||||
• Только чат
|
||||
→ Отправка в ОБЩУЮ ТЕМУ чата
|
||||
|
||||
<b>3️⃣ Через команды:</b>
|
||||
• /ig_broadcast — рассылка только ИГ
|
||||
• Рассылка админа — всем жильцам
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
🎭 <b>ДЛЯ ТВОЕЙ ЗАДАЧИ (ЮМОР ПРО МУСОР + ДОНАТ):</b>
|
||||
|
||||
<b>Вариант 1: Общий чат</b>
|
||||
• Писать в тему «Общий чат» (ID: 1)
|
||||
• Увидят ВСЕ жильцы
|
||||
• Подходит для доната на суд
|
||||
|
||||
<b>Вариант 2: Тема Мемы</b>
|
||||
• Писать в тему «Мемы» (ID: 6262)
|
||||
• Идеально для юмора про мусор!
|
||||
|
||||
<b>Вариант 3: Тема Объявления</b>
|
||||
• Писать в тему «Важные объявления» (ID: 6258)
|
||||
• Для серьёзных постов про донат
|
||||
|
||||
<b>Вариант 4: Тема Собрания</b>
|
||||
• Писать в тему «Собрания собственников» (ID: 6261)
|
||||
• Для важных решений по УК
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
🔧 <b>КАК ЭТО БУДЕТ РАБОТАТЬ:</b>
|
||||
|
||||
Создам скрипт, который:
|
||||
✅ Пишет пост в КОНКРЕТНУЮ тему
|
||||
✅ Использует прокси (VPN Германия)
|
||||
✅ Форматирует текст с emoji
|
||||
✅ Может добавить картинку
|
||||
✅ Постит серию постов с интервалом
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
🚀 <b>ГОТОВО К РАБОТЕ!</b>
|
||||
|
||||
Бот уже имеет ВСЕ необходимые функции:
|
||||
✅ Отправка в конкретную тему
|
||||
✅ Отправка в общий чат
|
||||
✅ Рассылка всем жильцам
|
||||
✅ Поддержка фото
|
||||
✅ Работа через прокси
|
||||
|
||||
<i>Нужно только создать скрипт для постинга серии сообщений!</i>
|
||||
"""
|
||||
|
||||
try:
|
||||
await bot.send_message(ADMIN_USER_ID, message)
|
||||
print("✅ Подробный отчёт отправлен!")
|
||||
except Exception as e:
|
||||
print(f"❌ Ошибка: {e}")
|
||||
finally:
|
||||
await bot.session.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(send_report())
|
||||
204
send_scheduler_analysis.py
Normal file
204
send_scheduler_analysis.py
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Отправка анализа возможности планировщика постов
|
||||
"""
|
||||
import asyncio
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
BASE_DIR = Path(__file__).resolve().parent
|
||||
sys.path.insert(0, str(BASE_DIR))
|
||||
|
||||
from aiogram import Bot
|
||||
from aiogram.client.default import DefaultBotProperties
|
||||
from aiogram.enums import ParseMode
|
||||
from aiogram.client.session.aiohttp import AiohttpSession
|
||||
|
||||
from config import BOT_TOKEN, ADMIN_USER_ID, get_proxy_url
|
||||
|
||||
async def send_analysis():
|
||||
"""Отправка анализа планировщика постов"""
|
||||
proxy_url = get_proxy_url()
|
||||
|
||||
if proxy_url:
|
||||
session = AiohttpSession(proxy=proxy_url)
|
||||
bot = Bot(token=BOT_TOKEN, session=session, default=DefaultBotProperties(parse_mode=ParseMode.HTML))
|
||||
else:
|
||||
bot = Bot(token=BOT_TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML))
|
||||
|
||||
message = """
|
||||
📅 <b>АНАЛИЗ: ПЛАНИРОВЩИК ПОСТОВ ДЛЯ ВЕБ-ПАНЕЛИ</b>
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
🎯 <b>МОЖЕМ ЛИ РЕАЛИЗОВАТЬ?</b>
|
||||
|
||||
✅ <b>ДА! Полностью реализуемо!</b>
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
📋 <b>ЧТО УЖЕ ЕСТЬ В КОДЕ:</b>
|
||||
|
||||
✅ <b>1. Планировщик (Scheduler)</b>
|
||||
• Файл: services/scheduler.py
|
||||
• Использует APScheduler
|
||||
• Уже работает с cron-задачами
|
||||
• Запускается при старте бота
|
||||
|
||||
✅ <b>2. Веб-панель (FastAPI)</b>
|
||||
• Файл: web/app.py (911 строк)
|
||||
• Есть страница /broadcast
|
||||
• Уже умеет: текст + фото
|
||||
• Уже есть выбор получателей
|
||||
|
||||
✅ <b>3. База данных (SQLAlchemy)</b>
|
||||
• Есть модели для всего
|
||||
• Нужно добавить: ScheduledPost
|
||||
• Хранить: текст, фото, тему, время
|
||||
|
||||
✅ <b>4. Темы форума</b>
|
||||
• Настроены 10 тем
|
||||
• message_thread_id работает
|
||||
• config.get_topic_id('topic_name')
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
🔧 <b>ЧТО НУЖНО ДОБАВИТЬ:</b>
|
||||
|
||||
<b>1️⃣ Новая модель в БД:</b>
|
||||
ScheduledPost
|
||||
• id
|
||||
• text (текст поста)
|
||||
• photo_file_id (опционально)
|
||||
• topic_id (тема: 1, 6258, 6262...)
|
||||
• topic_name ('general', 'memes'...)
|
||||
• scheduled_time (когда отправить)
|
||||
• status ('pending', 'sent', 'failed')
|
||||
• created_at (когда создан)
|
||||
• error_message (если ошибка)
|
||||
|
||||
<b>2️⃣ Новая страница в веб-панели:</b>
|
||||
/scheduled_posts
|
||||
• Текстовое поле (с HTML поддержкой)
|
||||
• Загрузка фото
|
||||
• Выпадающий список тем
|
||||
• Датапикер (календарь)
|
||||
• Время (часы:минуты)
|
||||
• Кнопка "Запланировать"
|
||||
• Таблица запланированных
|
||||
• Кнопки: удалить, редактировать
|
||||
|
||||
<b>3️⃣ API endpoints:</b>
|
||||
• GET /scheduled_posts - страница
|
||||
• POST /api/scheduled_posts/create
|
||||
• POST /api/scheduled_posts/cancel
|
||||
• GET /api/scheduled_posts/list
|
||||
• DELETE /api/scheduled_posts/{id}
|
||||
|
||||
<b>4️⃣ Фоновая задача в Scheduler:</b>
|
||||
• Проверка каждую минуту
|
||||
• SELECT * FROM scheduled_posts
|
||||
WHERE scheduled_time <= NOW()
|
||||
AND status = 'pending'
|
||||
• Отправка в нужную тему
|
||||
• Обновление status = 'sent'
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
🎨 <b>КАК БУДЕТ ВЫГЛЯДЕТЬ:</b>
|
||||
|
||||
<b>Форма создания поста:</b>
|
||||
|
||||
📝 Текст: [большое поле]
|
||||
📷 Фото: [выбрать файл]
|
||||
📂 Тема: [выпадающий список ▼]
|
||||
• Общий чат
|
||||
• Мемы
|
||||
• Объявления
|
||||
• Собрания
|
||||
• ...
|
||||
📅 Дата: [🗓️ 2026-04-07]
|
||||
⏰ Время: [14:30]
|
||||
|
||||
[✅ Запланировать пост]
|
||||
|
||||
<b>Таблица запланированных:</b>
|
||||
|
||||
| # | Тема | Когда | Статус | Действия |
|
||||
|---|------|-------|--------|----------|
|
||||
| 1 | Мемы | 07.04 10:00 | ⏳ | ❌ ✏️ |
|
||||
| 2 | Общий | 08.04 15:00 | ⏳ | ❌ ✏️ |
|
||||
| 3 | КГМ | 09.04 09:00 | ✅ | - |
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
🛡️ <b>БЕЗОПАСНОСТЬ (НЕ ИСПОРТИМ ТЕКУЩЕЕ):</b>
|
||||
|
||||
✅ <b>Изолированные изменения:</b>
|
||||
• Новая модель - отдельная таблица
|
||||
• Новый endpoint - новый URL
|
||||
• Новая страница - новый файл HTML
|
||||
• Новая задача в scheduler - отдельный job
|
||||
|
||||
✅ <b>Миграция БД:</b>
|
||||
• ALTER TABLE (добавление таблицы)
|
||||
• Не меняем существующие таблицы
|
||||
• Без риска для текущих данных
|
||||
|
||||
✅ <b>Тестирование:</b>
|
||||
• Можно тестировать на одном посте
|
||||
• Отмена без последствий
|
||||
• Логи всех действий
|
||||
|
||||
✅ <b>Откат:</b>
|
||||
• Если что-то не так - удаляем таблицу
|
||||
• Новый код не трогает старый
|
||||
• Старый функционал не изменится
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
🚀 <b>ПЛАН РЕАЛИЗАЦИИ:</b>
|
||||
|
||||
<b>Шаг 1:</b> Добавить модель ScheduledPost в БД
|
||||
<b>Шаг 2:</b> Создать страницу /scheduled_posts
|
||||
<b>Шаг 3:</b> Создать API endpoints
|
||||
<b>Шаг 4:</b> Добавить задачу в Scheduler
|
||||
<b>Шаг 5:</b> Тестирование на 1-2 постах
|
||||
<b>Шаг 6:</b> Коммит в Gitea
|
||||
|
||||
<b>⚠️ ВАЖНО:</b>
|
||||
Ни один существующий файл НЕ будет изменён критично!
|
||||
Только добавления нового кода.
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
💡 <b>СЦЕНАРИЙ ИСПОЛЬЗОВАНИЯ:</b>
|
||||
|
||||
1. Заходишь в веб-панель (порт 8000)
|
||||
2. Кликаешь "📅 Запланированные посты"
|
||||
3. Заполняешь форму:
|
||||
• Текст про юмор/мусор
|
||||
• Прикладываешь картинку
|
||||
• Выбираешь тему "Мемы"
|
||||
• Ставишь: 07.04.2026 10:00
|
||||
4. Жмёшь "Запланировать"
|
||||
5. Повторяешь для 5-6 постов
|
||||
6. Бот сам отправит их по расписанию!
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✅ <b>ГОТОВО К РЕАЛИЗАЦИИ!</b>
|
||||
|
||||
<i>Можем начинать? Никакой текущий функционал не пострадает!</i>
|
||||
"""
|
||||
|
||||
try:
|
||||
await bot.send_message(ADMIN_USER_ID, message)
|
||||
print("✅ Анализ планировщика отправлен!")
|
||||
except Exception as e:
|
||||
print(f"❌ Ошибка: {e}")
|
||||
finally:
|
||||
await bot.session.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(send_analysis())
|
||||
68
send_status_notification.py
Normal file
68
send_status_notification.py
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Отправка уведомления через Домовой Бот
|
||||
"""
|
||||
import asyncio
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Добавляем путь к проекту
|
||||
BASE_DIR = Path(__file__).resolve().parent
|
||||
sys.path.insert(0, str(BASE_DIR))
|
||||
|
||||
from aiogram import Bot
|
||||
from aiogram.client.default import DefaultBotProperties
|
||||
from aiogram.enums import ParseMode
|
||||
from aiogram.client.session.aiohttp import AiohttpSession
|
||||
|
||||
from config import BOT_TOKEN, ADMIN_USER_ID, get_proxy_url
|
||||
|
||||
async def send_notification():
|
||||
"""Отправка уведомления админу"""
|
||||
proxy_url = get_proxy_url()
|
||||
|
||||
if proxy_url:
|
||||
session = AiohttpSession(proxy=proxy_url)
|
||||
bot = Bot(token=BOT_TOKEN, session=session, default=DefaultBotProperties(parse_mode=ParseMode.HTML))
|
||||
else:
|
||||
bot = Bot(token=BOT_TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML))
|
||||
|
||||
message = """
|
||||
✅ <b>Домовой Бот — Статус системы</b>
|
||||
|
||||
🟢 <b>VPN (Xray):</b> РАБОТАЕТ
|
||||
├ Сервер: 🇩🇪 Германия (138.124.228.10)
|
||||
├ Протокол: VLESS + Reality
|
||||
├ SOCKS5: 127.0.0.1:10808 ✅
|
||||
└ HTTP: 127.0.0.1:10809 ✅
|
||||
|
||||
🤖 <b>Бот:</b> ГОТОВ К РАБОТЕ
|
||||
├ Версия: v2.1
|
||||
├ Прокси: подключён
|
||||
└ Веб-интерфейс: порт 8000
|
||||
|
||||
📋 <b>Доступные функции:</b>
|
||||
• 📊 Управление жильцами
|
||||
• 📢 Доска объявлений
|
||||
• 📅 Календарь событий
|
||||
• 📝 Опросы и голосования
|
||||
• 🏆 Рейтинг и достижения
|
||||
• 🔔 Напоминания о платежах
|
||||
• 🛡️ Анти-спам система
|
||||
• 📱 Веб-админка
|
||||
|
||||
🎯 <b>Готов к публикации постов!</b>
|
||||
|
||||
<i>Система работает стабильно ✓</i>
|
||||
"""
|
||||
|
||||
try:
|
||||
await bot.send_message(ADMIN_USER_ID, message)
|
||||
print("✅ Уведомление отправлено!")
|
||||
except Exception as e:
|
||||
print(f"❌ Ошибка: {e}")
|
||||
finally:
|
||||
await session.close() if proxy_url else await bot.session.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(send_notification())
|
||||
19
web/app.py
19
web/app.py
|
|
@ -10,6 +10,7 @@ from fastapi.security import HTTPBasic, HTTPBasicCredentials
|
|||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from fastapi.responses import HTMLResponse, JSONResponse, RedirectResponse
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select, func, update, delete, desc
|
||||
from datetime import datetime, timedelta
|
||||
|
|
@ -18,13 +19,23 @@ import config
|
|||
|
||||
from database.db import AsyncSessionLocal
|
||||
from database.models import (
|
||||
User, Message, Poll, Ad, PaymentReminder, Schedule,
|
||||
User, Message, Poll, Ad, PaymentReminder, Schedule,
|
||||
VerificationRequest, Service, Announcement, Event
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
app = FastAPI(title="Домовой Бот - MEGA Admin Panel", version="3.0.0")
|
||||
|
||||
# Добавляем CORS middleware
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"], # Разрешаем все origins (для локального использования)
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
templates = Jinja2Templates(directory="web/templates")
|
||||
app.mount("/static", StaticFiles(directory="web/static"), name="static")
|
||||
app.mount("/static/service_images", StaticFiles(directory="data/service_images"), name="service_images")
|
||||
|
|
@ -538,6 +549,9 @@ async def api_send_broadcast(
|
|||
from pathlib import Path
|
||||
from services.initiative_group import InitiativeGroupService
|
||||
|
||||
# Логируем начало рассылки
|
||||
logger.info(f"📬 НАЧАЛО РАССЫЛКИ: получатели={recipients}, текст_len={len(text) if text else 0}")
|
||||
|
||||
photo_id = None
|
||||
|
||||
# Если есть картинка — загружаем
|
||||
|
|
@ -650,6 +664,9 @@ async def api_send_broadcast(
|
|||
except Exception as e:
|
||||
logger.error(f"Ошибка логирования рассылки: {e}")
|
||||
|
||||
# Логируем результат
|
||||
logger.info(f"✅ РАССЫЛКА ЗАВЕРШЕНА: успешно={success_count}, ошибок={error_count}, получатели={recipients}")
|
||||
|
||||
return JSONResponse({
|
||||
"success": True,
|
||||
"message": f"Отправлено: {success_count} (в чат: {'✅' if chat_sent else '❌'})",
|
||||
|
|
|
|||
Loading…
Reference in a new issue