v1.8.2: AGENTS.md, consent revocation, delete bot users, dialogues fix, intent improvements, CI for max_bot
Tests / test (push) Has been cancelled
Tests / test-max-bot (push) Has been cancelled

This commit is contained in:
2026-06-02 18:22:45 +03:00
parent a64a274829
commit 4c3026a80f
17 changed files with 572 additions and 54 deletions
+5
View File
@@ -1434,3 +1434,8 @@ async def proxy_delete_conversation(conv_id: int, request: Request, user: dict =
return await _proxy("DELETE", f"/api/bot/conversations/{conv_id}")
@router.delete("/api/bot/users/{user_id}")
async def proxy_delete_bot_user(user_id: int, request: Request, user: dict = Depends(require_role("owner"))):
return await _proxy("DELETE", f"/api/bot/users/{user_id}")
@@ -1,5 +1,6 @@
{% extends "page.html" %}
{% block page_content %}
<script>var USER_ROLE = '{{ user.role }}';</script>
<style>
.consent-table { width:100%; border-collapse:collapse; }
.consent-table th, .consent-table td { padding:10px 14px; text-align:left; border-bottom:1px solid var(--border); font-size:13px; }
@@ -53,10 +54,11 @@
<th>Username</th>
<th>Согласие</th>
<th>Дата</th>
{% if user.role == 'owner' %}<th>Действия</th>{% endif %}
</tr>
</thead>
<tbody id="consent-table-body">
<tr><td colspan="8" style="text-align:center;padding:30px;color:var(--text-muted);">Загрузка...</td></tr>
<tr><td colspan="{% if user.role == 'owner' %}9{% else %}8{% endif %}" style="text-align:center;padding:30px;color:var(--text-muted);">Загрузка...</td></tr>
</tbody>
</table>
</div>
@@ -98,7 +100,8 @@ var confirmSeconds = 10;
function loadConsents(){
var tbody = document.getElementById('consent-table-body');
tbody.innerHTML = '<tr><td colspan="8" style="text-align:center;padding:30px;color:var(--text-muted);">Загрузка...</td></tr>';
var colspan = USER_ROLE === 'owner' ? 9 : 8;
tbody.innerHTML = '<tr><td colspan="' + colspan + '" style="text-align:center;padding:30px;color:var(--text-muted);">Загрузка...</td></tr>';
fetch('/api/bot/users/consented').then(function(r){ return r.json() }).then(function(data){
allConsents = data;
document.getElementById('consent-count').textContent = data.length + ' пользователей';
@@ -106,15 +109,16 @@ function loadConsents(){
document.getElementById('send-btn').disabled = data.length === 0;
renderConsents(data);
}).catch(function(err){
tbody.innerHTML = '<tr><td colspan="8" style="text-align:center;padding:30px;color:var(--text-muted);">Ошибка загрузки</td></tr>';
tbody.innerHTML = '<tr><td colspan="' + colspan + '" style="text-align:center;padding:30px;color:var(--text-muted);">Ошибка загрузки</td></tr>';
showNotification('Ошибка загрузки согласий', 'error');
});
}
function renderConsents(list){
var tbody = document.getElementById('consent-table-body');
var colspan = USER_ROLE === 'owner' ? 9 : 8;
if(!list.length){
tbody.innerHTML = '<tr><td colspan="8" style="text-align:center;padding:30px;color:var(--text-muted);">Нет данных</td></tr>';
tbody.innerHTML = '<tr><td colspan="' + colspan + '" style="text-align:center;padding:30px;color:var(--text-muted);">Нет данных</td></tr>';
return;
}
var html = '';
@@ -129,8 +133,11 @@ function renderConsents(list){
'<td>' + escapeHtml(u.organization || '—') + '</td>' +
'<td>' + escapeHtml(u.username || '—') + '</td>' +
'<td class="consent-yes">Да</td>' +
'<td style="font-size:12px;color:var(--text-muted);">' + dateStr + '</td>' +
'</tr>';
'<td style="font-size:12px;color:var(--text-muted);">' + dateStr + '</td>';
if(USER_ROLE === 'owner'){
html += '<td><button class="btn btn-danger btn-sm" onclick="confirmDeleteUser(' + u.id + ', \'' + escapeHtml(name).replace(/'/g, "\\'") + '\')" title="Удалить пользователя">🗑</button></td>';
}
html += '</tr>';
});
tbody.innerHTML = html;
}
@@ -215,6 +222,25 @@ function escapeHtml(s){
return s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
}
function confirmDeleteUser(userId, userName){
if(!confirm('Удалить пользователя ' + userName + ' (ID: ' + userId + ')?\n\nВсе его диалоги и сообщения будут удалены навсегда. Заявки останутся.')) return;
fetch('/api/bot/users/' + userId, { method: 'DELETE' })
.then(function(r){ return r.json() })
.then(function(d){
if(d.ok){
showNotification('Пользователь ' + userName + ' удалён', 'success');
allConsents = allConsents.filter(function(u){ return u.id !== userId; });
renderConsents(allConsents);
document.getElementById('consent-count').textContent = allConsents.length + ' пользователей';
document.getElementById('recipient-count').textContent = 'Получателей: ' + allConsents.length;
} else {
showNotification('Ошибка: ' + (d.error || 'неизвестная'), 'error');
}
}).catch(function(){
showNotification('Ошибка соединения', 'error');
});
}
loadConsents();
</script>
{% endblock %}