Админка: колонка «Пользователь» в обработанных документах + FILES.web_account
- бот: @username / имя / tg:id; веб: аккаунт сессии или «аноним» - новая колонка FILES.web_account (tg:/yandex:/vk:/email:) — пишется в _finalize_submit из резолвнутого аккаунта, чтобы у залогиненных веб-юзеров атрибуция работала для любого способа входа (раньше только Telegram) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
23
app/main.py
23
app/main.py
@@ -138,7 +138,7 @@ def _convert_doc_to_pdf(src_path: str, dst_path: str) -> None:
|
|||||||
def _db_insert_job(
|
def _db_insert_job(
|
||||||
name_or_f, stitching, title, numeration, flip_side,
|
name_or_f, stitching, title, numeration, flip_side,
|
||||||
color, pdfa, quality, original_name, source_size_mb,
|
color, pdfa, quality, original_name, source_size_mb,
|
||||||
ocr=0, web_owner_id=0,
|
ocr=0, web_owner_id=0, web_account=None,
|
||||||
):
|
):
|
||||||
now = datetime.datetime.now()
|
now = datetime.datetime.now()
|
||||||
date_str = now.strftime("%Y.%m.%d")
|
date_str = now.strftime("%Y.%m.%d")
|
||||||
@@ -178,6 +178,9 @@ def _db_insert_job(
|
|||||||
if "web_owner_id" in cols:
|
if "web_owner_id" in cols:
|
||||||
fields.append("web_owner_id")
|
fields.append("web_owner_id")
|
||||||
values.append(int(web_owner_id or 0))
|
values.append(int(web_owner_id or 0))
|
||||||
|
if "web_account" in cols:
|
||||||
|
fields.append("web_account")
|
||||||
|
values.append(web_account or "")
|
||||||
|
|
||||||
placeholders = ", ".join(["?"] * len(fields))
|
placeholders = ", ".join(["?"] * len(fields))
|
||||||
sql = f"INSERT INTO FILES ({', '.join(fields)}) VALUES ({placeholders})"
|
sql = f"INSERT INTO FILES ({', '.join(fields)}) VALUES ({placeholders})"
|
||||||
@@ -409,6 +412,9 @@ def _db_ensure_auth_table():
|
|||||||
con.execute("ALTER TABLE FILES ADD COLUMN ocr INTEGER DEFAULT 0")
|
con.execute("ALTER TABLE FILES ADD COLUMN ocr INTEGER DEFAULT 0")
|
||||||
if "web_owner_id" not in have:
|
if "web_owner_id" not in have:
|
||||||
con.execute("ALTER TABLE FILES ADD COLUMN web_owner_id INTEGER DEFAULT 0")
|
con.execute("ALTER TABLE FILES ADD COLUMN web_owner_id INTEGER DEFAULT 0")
|
||||||
|
if "web_account" not in have:
|
||||||
|
# аккаунт сессии (tg:/yandex:/vk:/email:) — кто загрузил с сайта
|
||||||
|
con.execute("ALTER TABLE FILES ADD COLUMN web_account TEXT DEFAULT ''")
|
||||||
except Exception as _mig:
|
except Exception as _mig:
|
||||||
print(f"FILES migrate error: {_mig}")
|
print(f"FILES migrate error: {_mig}")
|
||||||
# Авто-миграция WEB_ACCOUNTS: авто-продление подписки (сохранённый способ оплаты)
|
# Авто-миграция WEB_ACCOUNTS: авто-продление подписки (сохранённый способ оплаты)
|
||||||
@@ -1094,6 +1100,7 @@ def _finalize_submit(job_id, file_path, original_name, stitching, title,
|
|||||||
source_size_mb=size_mb,
|
source_size_mb=size_mb,
|
||||||
ocr=ocr,
|
ocr=ocr,
|
||||||
web_owner_id=owner,
|
web_owner_id=owner,
|
||||||
|
web_account=acc,
|
||||||
)
|
)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
_safe_remove(file_path)
|
_safe_remove(file_path)
|
||||||
@@ -3205,7 +3212,7 @@ _ADMIN_HTML = """<!doctype html>
|
|||||||
<h2 style="margin:0">Обработанные документы <span class="muted" id="docs-totals"></span></h2>
|
<h2 style="margin:0">Обработанные документы <span class="muted" id="docs-totals"></span></h2>
|
||||||
<button class="ghost" onclick="downloadCsv()">Экспорт CSV</button>
|
<button class="ghost" onclick="downloadCsv()">Экспорт CSV</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="scroll"><table><thead><tr><th>Дата</th><th>Файл</th><th class="num">Стр.</th><th class="num">Время</th><th class="num">Исходник</th><th class="num">Результат</th><th>Кач-во</th><th>Сшивка</th><th>OCR</th><th>Источник</th></tr></thead>
|
<div class="scroll"><table><thead><tr><th>Дата</th><th>Файл</th><th class="num">Стр.</th><th class="num">Время</th><th class="num">Исходник</th><th class="num">Результат</th><th>Кач-во</th><th>Сшивка</th><th>OCR</th><th>Источник</th><th>Пользователь</th></tr></thead>
|
||||||
<tbody id="t-docs"></tbody></table></div>
|
<tbody id="t-docs"></tbody></table></div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -3425,11 +3432,15 @@ _ADMIN_HTML = """<!doctype html>
|
|||||||
document.getElementById('t-docs').innerHTML = docs.length ? docs.map(function(f){
|
document.getElementById('t-docs').innerHTML = docs.length ? docs.map(function(f){
|
||||||
var web = (f.user_id === wid);
|
var web = (f.user_id === wid);
|
||||||
var srcPill = web ? '<span class="pill web">сайт</span>' : '<span class="pill bot">бот</span>';
|
var srcPill = web ? '<span class="pill web">сайт</span>' : '<span class="pill bot">бот</span>';
|
||||||
|
var who = web
|
||||||
|
? (f.web_account || (f.web_owner_id ? 'tg:'+f.web_owner_id : ''))
|
||||||
|
: ((f.username && f.username!=='webuser') ? '@'+f.username : (f.first_name || ('tg:'+f.user_id)));
|
||||||
|
var whoCell = who ? esc(who) : '<span class="muted">аноним</span>';
|
||||||
var dd = (f.date||'') + (f.time ? ' '+String(f.time).slice(0,5) : '');
|
var dd = (f.date||'') + (f.time ? ' '+String(f.time).slice(0,5) : '');
|
||||||
return '<tr><td>'+esc(dd)+'</td><td class="fname" title="'+esc(f.name)+'">'+esc(f.name)+'</td><td class="num">'+(f.pages||'—')+
|
return '<tr><td>'+esc(dd)+'</td><td class="fname" title="'+esc(f.name)+'">'+esc(f.name)+'</td><td class="num">'+(f.pages||'—')+
|
||||||
'</td><td class="num">'+psec(f.secs)+'</td><td class="num">'+size(f.source_size_mb)+'</td><td class="num">'+size(f.result_size_mb)+
|
'</td><td class="num">'+psec(f.secs)+'</td><td class="num">'+size(f.source_size_mb)+'</td><td class="num">'+size(f.result_size_mb)+
|
||||||
'</td><td>'+esc(f.quality||'—')+'</td><td>'+esc(f.stitching||'—')+'</td><td>'+(f.ocr?'✓':'')+'</td><td>'+srcPill+'</td></tr>';
|
'</td><td>'+esc(f.quality||'—')+'</td><td>'+esc(f.stitching||'—')+'</td><td>'+(f.ocr?'✓':'')+'</td><td>'+srcPill+'</td><td>'+whoCell+'</td></tr>';
|
||||||
}).join('') : '<tr><td colspan="10" class="muted">Пока нет документов</td></tr>';
|
}).join('') : '<tr><td colspan="11" class="muted">Пока нет документов</td></tr>';
|
||||||
}
|
}
|
||||||
|
|
||||||
function showGate(err){
|
function showGate(err){
|
||||||
@@ -3743,9 +3754,11 @@ def _admin_collect_stats() -> dict:
|
|||||||
# Документы
|
# Документы
|
||||||
cols = {r[1] for r in con.execute("PRAGMA table_info(FILES)")}
|
cols = {r[1] for r in con.execute("PRAGMA table_info(FILES)")}
|
||||||
pages_expr = "COALESCE(NULLIF(pages_total,0), num_pages, 0)" if "pages_total" in cols else "COALESCE(num_pages,0)"
|
pages_expr = "COALESCE(NULLIF(pages_total,0), num_pages, 0)" if "pages_total" in cols else "COALESCE(num_pages,0)"
|
||||||
|
wa_expr = "COALESCE(web_account,'')" if "web_account" in cols else "''"
|
||||||
docs = [dict(r) for r in con.execute(
|
docs = [dict(r) for r in con.execute(
|
||||||
f"SELECT date, time, COALESCE(NULLIF(original_name,''), name_or_f) AS name, {pages_expr} AS pages, "
|
f"SELECT date, time, COALESCE(NULLIF(original_name,''), name_or_f) AS name, {pages_expr} AS pages, "
|
||||||
"source_size_mb, result_size_mb, quality, stitching, ocr, elapsed_time, user_id, url_res_f "
|
"source_size_mb, result_size_mb, quality, stitching, ocr, elapsed_time, user_id, url_res_f, "
|
||||||
|
f"username, first_name, COALESCE(web_owner_id,0) AS web_owner_id, {wa_expr} AS web_account "
|
||||||
"FROM FILES ORDER BY rowid DESC LIMIT 150")]
|
"FROM FILES ORDER BY rowid DESC LIMIT 150")]
|
||||||
for _d in docs:
|
for _d in docs:
|
||||||
_d["secs"] = _elapsed_to_sec(_d.get("elapsed_time"))
|
_d["secs"] = _elapsed_to_sec(_d.get("elapsed_time"))
|
||||||
|
|||||||
Reference in New Issue
Block a user