Пейвол: точный подсчёт страниц (PyMuPDF) + журнал предпоказов + чистка воронки

- _count_pdf_pages/_read_and_count_pdf: сначала fitz (видит страницы в сжатых
  object streams), regex — фоллбэк. Закрывает дыру: 1842-стр. PDF на 7.4 МБ
  считался как 0 стр. и обрабатывался бесплатно (тест: regex 0 / fitz 150).
- /api/paywall/check: показы до загрузки пишутся в WEB_PAYWALL_EVENTS
  (имя файла с фронта, статус «показан», дедуп имя+размер 24ч).
- showPaywall(renew) больше не считается показом пейвола в воронке.
- Пояснение под воронкой: чем «показан» отличается от журнала.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
berkio_admin_gitea
2026-07-16 15:11:41 +00:00
parent 99dad2f343
commit 945a62cc5e
2 changed files with 59 additions and 7 deletions

View File

@@ -2424,9 +2424,9 @@
let paywallJob = null, paywallFilePrice = 99, paywallSubPrice = 299, paywallMode = 'file';
// Предпроверка на сервере БЕЗ загрузки файла
async function checkPaywall(sizeMb, pages) {
async function checkPaywall(sizeMb, pages, fname) {
try {
const body = { size_mb: sizeMb, pages: pages };
const body = { size_mb: sizeMb, pages: pages, name: fname || '' };
if (tgUser) body.user_id = tgUser.user_id || tgUser.id || 0;
const r = await fetch('/api/paywall/check', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
return await r.json();
@@ -2438,7 +2438,8 @@
}
function showPaywall(jobId, filePrice, subPrice, mode) {
track('paywall_shown');
// «Продлить» подписку — не пейвол, в воронке не считаем
if ((mode || 'file') !== 'renew') track('paywall_shown');
paywallMode = mode || 'file';
paywallJob = jobId;
paywallFilePrice = filePrice || 99;
@@ -3420,7 +3421,7 @@
// Пейволл БЕЗ загрузки: только для потенциально больших файлов (мелкие не дёргают сервер)
if (fileSizeMb > AUTH_MAX_MB || filePages > AUTH_MAX_PAGES) {
submitBtn.disabled = true;
const chk = await checkPaywall(fileSizeMb, filePages);
const chk = await checkPaywall(fileSizeMb, filePages, selectedFile.name || '');
submitBtn.disabled = false;
if (chk.requires_payment) { showPaywall(null, chk.file_price, chk.sub_price, 'file'); return; }
}