📰 fix: Исправлена генерация дайджеста
- Добавлен API endpoint /api/digest/generate - Исправлена JS функция generateNow() — теперь реально вызывает API - Превью отправляется админу в Telegram после генерации - Время авто-генерации изменено на 19:00 Ульяновск (15:00 UTC) - Проверка на дубликаты за ту же неделю Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
parent
9a8dafba27
commit
9033310cfa
3 changed files with 100 additions and 5 deletions
|
|
@ -111,15 +111,15 @@ class Scheduler:
|
||||||
)
|
)
|
||||||
logger.info('✅ Добавлена задача проверки запланированных постов')
|
logger.info('✅ Добавлена задача проверки запланированных постов')
|
||||||
|
|
||||||
# Еженедельная генерация дайджеста (воскресенье 09:00)
|
# Еженедельная генерация дайджеста (воскресенье 15:00 UTC = 19:00 Ульяновск)
|
||||||
self.scheduler.add_job(
|
self.scheduler.add_job(
|
||||||
self.weekly_digest_generation,
|
self.weekly_digest_generation,
|
||||||
CronTrigger.from_crontab('0 9 * * 0'), # Каждое воскресенье в 09:00
|
CronTrigger.from_crontab('0 15 * * 0'), # Каждое воскресенье в 15:00 UTC (19:00 local)
|
||||||
id='weekly_digest',
|
id='weekly_digest',
|
||||||
name='Генерация еженедельного дайджеста',
|
name='Генерация еженедельного дайджеста',
|
||||||
replace_existing=True
|
replace_existing=True
|
||||||
)
|
)
|
||||||
logger.info('✅ Добавлена задача генерации дайджеста')
|
logger.info('✅ Добавлена задача генерации дайджеста (воскресенье 19:00 Ульяновск)')
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""Остановка планировщика"""
|
"""Остановка планировщика"""
|
||||||
|
|
|
||||||
75
web/app.py
75
web/app.py
|
|
@ -1227,6 +1227,81 @@ async def api_get_broadcast_non_readers(broadcast_id: int, username: str = Depen
|
||||||
# V3.1 - ДАЙДЖЕСТЫ
|
# V3.1 - ДАЙДЖЕСТЫ
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
|
@app.post("/api/digest/generate")
|
||||||
|
async def api_generate_digest(username: str = Depends(get_current_admin)):
|
||||||
|
"""Сгенерировать дайджест прямо сейчас (из веб-панели)"""
|
||||||
|
from services.digest_service import DigestService
|
||||||
|
from database.models import Digest
|
||||||
|
from datetime import date
|
||||||
|
|
||||||
|
try:
|
||||||
|
async with AsyncSessionLocal() as session:
|
||||||
|
service = DigestService(session)
|
||||||
|
|
||||||
|
# Генерируем
|
||||||
|
digest_data = await service.generate_weekly_digest()
|
||||||
|
|
||||||
|
if not digest_data:
|
||||||
|
return JSONResponse({
|
||||||
|
"success": False,
|
||||||
|
"error": "Не удалось сгенерировать дайджест. Проверьте логи."
|
||||||
|
}, status_code=500)
|
||||||
|
|
||||||
|
# Проверяем нет ли уже за эту неделю
|
||||||
|
check_stmt = select(Digest).where(
|
||||||
|
Digest.week_number == digest_data['week_number'],
|
||||||
|
Digest.year == digest_data['year']
|
||||||
|
)
|
||||||
|
result = await session.execute(check_stmt)
|
||||||
|
existing = result.scalar_one_or_none()
|
||||||
|
|
||||||
|
if existing:
|
||||||
|
return JSONResponse({
|
||||||
|
"success": True,
|
||||||
|
"message": f"Дайджест за неделю #{digest_data['week_number']}/{digest_data['year']} уже существует (ID: #{existing.id}). Вы можете отправить его в разделе 'Архив'.",
|
||||||
|
"digest_id": existing.id,
|
||||||
|
"already_exists": True
|
||||||
|
})
|
||||||
|
|
||||||
|
# Сохраняем
|
||||||
|
digest_id = await service.save_digest(digest_data, status='pending_approval')
|
||||||
|
|
||||||
|
# Отправляем превью админу в личку
|
||||||
|
from bot_instance import get_bot
|
||||||
|
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
|
||||||
|
|
||||||
|
bot = get_bot()
|
||||||
|
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||||
|
[InlineKeyboardButton(text="🌐 Утвердить в веб-панели", url="http://localhost:8000/digests")],
|
||||||
|
])
|
||||||
|
|
||||||
|
await bot.send_message(
|
||||||
|
config.ADMIN_USER_ID,
|
||||||
|
f"📰 <b>Дайджест за неделю готов!</b>\n\n"
|
||||||
|
f"Неделя #{digest_data['week_number']}/{digest_data['year']}\n"
|
||||||
|
f"Период: {digest_data['period_start'].strftime('%d.%m')} - {digest_data['period_end'].strftime('%d.%m.%Y')}\n\n"
|
||||||
|
f"Зайдите в веб-панель для утверждения:\n"
|
||||||
|
f"http://localhost:8000/digests",
|
||||||
|
parse_mode='HTML',
|
||||||
|
reply_markup=keyboard
|
||||||
|
)
|
||||||
|
|
||||||
|
return JSONResponse({
|
||||||
|
"success": True,
|
||||||
|
"message": f"✅ Дайджест #{digest_id} сгенерирован! Превью отправлено вам в Telegram.",
|
||||||
|
"digest_id": digest_id
|
||||||
|
})
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
import traceback
|
||||||
|
logger.error(f"Ошибка генерации дайджеста: {e}")
|
||||||
|
traceback.print_exc()
|
||||||
|
return JSONResponse({
|
||||||
|
"success": False,
|
||||||
|
"error": f"Критическая ошибка: {str(e)}"
|
||||||
|
}, status_code=500)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/digests", response_class=HTMLResponse)
|
@app.get("/digests", response_class=HTMLResponse)
|
||||||
async def digests_page(request: Request, username: str = Depends(get_current_admin)):
|
async def digests_page(request: Request, username: str = Depends(get_current_admin)):
|
||||||
"""Страница дайджестов"""
|
"""Страница дайджестов"""
|
||||||
|
|
|
||||||
|
|
@ -245,8 +245,28 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateNow() {
|
async function generateNow() {
|
||||||
alert('Генерация дайджеста запущена! Проверьте Telegram - бот отправит превью.');
|
const btn = event.target;
|
||||||
|
btn.disabled = true;
|
||||||
|
btn.textContent = '⏳ Генерация...';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const r = await fetch('/api/digest/generate', { method: 'POST' });
|
||||||
|
const result = await r.json();
|
||||||
|
|
||||||
|
if (result.success) {
|
||||||
|
alert('✅ ' + result.message);
|
||||||
|
location.reload();
|
||||||
|
} else {
|
||||||
|
alert('❌ Ошибка: ' + (result.error || 'Неизвестная'));
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.textContent = '🔄 Сгенерировать сейчас';
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
alert('❌ Ошибка: ' + err.message);
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.textContent = '🔄 Сгенерировать сейчас';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue