some fixes

This commit is contained in:
2025-10-22 21:22:44 +09:00
parent 46fad7ecc2
commit 6ff35e26f4
514 changed files with 156165 additions and 0 deletions

View File

@@ -0,0 +1,885 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Telegram Bot - SmartSolTech Admin</title>
<!-- Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Font Awesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<!-- Custom CSS -->
<link rel="stylesheet" href="/css/main.css">
<link rel="stylesheet" href="/css/fixes.css">
</head>
<body class="bg-gray-100">
<!-- Admin Header -->
<header class="bg-white shadow-sm border-b">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between items-center h-16">
<div class="flex items-center">
<h1 class="text-xl font-semibold text-gray-900">
<i class="fas fa-cogs mr-2"></i>
SmartSolTech Admin
</h1>
</div>
<div class="flex items-center space-x-4">
<span class="text-sm text-gray-600">
Добро пожаловать, <%= user ? user.name : 'Admin' %>!
</span>
<a href="/" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-external-link-alt mr-1"></i>
Посмотреть сайт
</a>
<form action="/admin/logout" method="post" class="inline">
<button type="submit" class="text-red-600 hover:text-red-800">
<i class="fas fa-sign-out-alt mr-1"></i>
Выход
</button>
</form>
</div>
</div>
</div>
</header>
<div class="flex">
<!-- Admin Sidebar -->
<aside class="w-64 bg-white shadow-sm admin-sidebar min-h-screen">
<nav class="mt-5 px-2">
<div class="space-y-1">
<a href="/admin/dashboard" class="group flex items-center px-2 py-2 text-sm font-medium rounded-md text-gray-600 hover:bg-gray-50 hover:text-gray-900">
<i class="fas fa-tachometer-alt mr-3"></i>
Панель управления
</a>
<a href="/admin/portfolio" class="group flex items-center px-2 py-2 text-sm font-medium rounded-md text-gray-600 hover:bg-gray-50 hover:text-gray-900">
<i class="fas fa-briefcase mr-3"></i>
Портфолио
</a>
<a href="/admin/services" class="group flex items-center px-2 py-2 text-sm font-medium rounded-md text-gray-600 hover:bg-gray-50 hover:text-gray-900">
<i class="fas fa-cog mr-3"></i>
Услуги
</a>
<a href="/admin/contacts" class="group flex items-center px-2 py-2 text-sm font-medium rounded-md text-gray-600 hover:bg-gray-50 hover:text-gray-900">
<i class="fas fa-envelope mr-3"></i>
Сообщения
</a>
<a href="/admin/media" class="group flex items-center px-2 py-2 text-sm font-medium rounded-md text-gray-600 hover:bg-gray-50 hover:text-gray-900">
<i class="fas fa-images mr-3"></i>
Медиа
</a>
<a href="/admin/settings" class="group flex items-center px-2 py-2 text-sm font-medium rounded-md text-gray-600 hover:bg-gray-50 hover:text-gray-900">
<i class="fas fa-cogs mr-3"></i>
Настройки
</a>
<a href="/admin/telegram" class="group flex items-center px-2 py-2 text-sm font-medium rounded-md bg-blue-100 text-blue-700">
<i class="fab fa-telegram mr-3"></i>
Telegram Bot
</a>
<a href="/admin/banner-editor" class="group flex items-center px-2 py-2 text-sm font-medium rounded-md text-gray-600 hover:bg-gray-50 hover:text-gray-900">
<i class="fas fa-paint-brush mr-3"></i>
Редактор баннеров
</a>
</div>
</nav>
</aside>
<!-- Main Content -->
<main class="flex-1 p-8">
<div class="space-y-6">
<!-- Header -->
<div class="bg-white shadow rounded-lg p-6">
<div class="flex items-center justify-between">
<div>
<h1 class="text-2xl font-bold text-gray-900 flex items-center">
<i class="fab fa-telegram mr-3 text-blue-500"></i>
Telegram Bot
</h1>
<p class="mt-2 text-gray-600">Настройка и управление уведомлениями через Telegram</p>
</div>
<div class="flex items-center space-x-3">
<div class="flex items-center">
<div class="w-3 h-3 rounded-full <%= botConfigured ? 'bg-green-500' : 'bg-red-500' %> mr-2"></div>
<span class="text-sm font-medium <%= botConfigured ? 'text-green-700' : 'text-red-700' %>">
<%= botConfigured ? 'Подключен' : 'Не настроен' %>
</span>
</div>
</div>
</div>
</div>
<!-- Bot Configuration -->
<div class="bg-white shadow rounded-lg p-6">
<h3 class="text-lg font-semibold text-gray-900 mb-6">
<i class="fas fa-cog mr-2 text-blue-500"></i>
Конфигурация бота
</h3>
<form id="bot-config-form" class="space-y-6">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<!-- Bot Token -->
<div>
<label for="botToken" class="block text-sm font-medium text-gray-700 mb-2">
Токен бота *
</label>
<div class="relative">
<input type="password" id="botToken" name="botToken"
value="<%= botToken %>"
placeholder="1234567890:ABCDEFGHIJKLMNOPQRSTUVWXYZ"
class="block w-full pr-10 border border-gray-300 rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
<button type="button" onclick="toggleTokenVisibility()"
class="absolute inset-y-0 right-0 pr-3 flex items-center">
<i id="token-eye" class="fas fa-eye text-gray-400"></i>
</button>
</div>
<p class="mt-1 text-sm text-gray-500">
Получите токен от <a href="https://t.me/BotFather" target="_blank" class="text-blue-600 underline">@BotFather</a>
</p>
</div>
<!-- Default Chat ID -->
<div>
<label for="chatId" class="block text-sm font-medium text-gray-700 mb-2">
ID чата по умолчанию
</label>
<input type="text" id="chatId" name="chatId"
value="<%= chatId %>"
placeholder="-1001234567890"
class="block w-full border border-gray-300 rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
<p class="mt-1 text-sm text-gray-500">
Оставьте пустым, если будете выбирать чат из списка
</p>
</div>
</div>
<div class="flex space-x-3">
<button type="submit" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition-colors">
<i class="fas fa-save mr-2"></i>
Сохранить настройки
</button>
<button type="button" onclick="getBotInfo()" class="bg-gray-600 hover:bg-gray-700 text-white px-4 py-2 rounded-lg transition-colors">
<i class="fas fa-info-circle mr-2"></i>
Получить информацию о боте
</button>
</div>
</form>
<div id="config-result" class="mt-4 hidden"></div>
</div>
<% if (botConfigured) { %>
<!-- Bot Information -->
<div class="bg-white shadow rounded-lg p-6">
<div class="flex items-center justify-between mb-6">
<h3 class="text-lg font-semibold text-gray-900">
<i class="fas fa-robot mr-2 text-green-500"></i>
Информация о боте
</h3>
<button onclick="refreshBotInfo()" class="text-blue-600 hover:text-blue-800 text-sm">
<i class="fas fa-refresh mr-1"></i>
Обновить
</button>
</div>
<div id="bot-info-container">
<% if (botInfo) { %>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<div class="bg-gray-50 p-4 rounded-lg">
<div class="text-sm text-gray-600">Имя бота</div>
<div class="text-lg font-semibold text-gray-900">@<%= botInfo.username %></div>
</div>
<div class="bg-gray-50 p-4 rounded-lg">
<div class="text-sm text-gray-600">Отображаемое имя</div>
<div class="text-lg font-semibold text-gray-900"><%= botInfo.first_name %></div>
</div>
<div class="bg-gray-50 p-4 rounded-lg">
<div class="text-sm text-gray-600">ID бота</div>
<div class="text-lg font-semibold text-gray-900"><%= botInfo.id %></div>
</div>
<div class="bg-gray-50 p-4 rounded-lg">
<div class="text-sm text-gray-600">Может читать сообщения</div>
<div class="text-lg font-semibold <%= botInfo.can_read_all_group_messages ? 'text-green-600' : 'text-red-600' %>">
<%= botInfo.can_read_all_group_messages ? 'Да' : 'Нет' %>
</div>
</div>
</div>
<% } else { %>
<div class="text-center py-4 text-gray-500">
<i class="fas fa-robot text-4xl text-gray-300 mb-2"></i>
<p>Настройте токен бота для получения информации</p>
</div>
<% } %>
</div>
</div>
<!-- Available Chats -->
<div class="bg-white shadow rounded-lg p-6">
<div class="flex items-center justify-between mb-6">
<h3 class="text-lg font-semibold text-gray-900">
<i class="fas fa-comments mr-2 text-blue-500"></i>
Доступные чаты
</h3>
<button onclick="discoverChats()" class="bg-blue-600 hover:bg-blue-700 text-white px-3 py-1 rounded text-sm transition-colors">
<i class="fas fa-search mr-1"></i>
Найти чаты
</button>
</div>
<div id="available-chats-container">
<% if (availableChats && availableChats.length > 0) { %>
<div class="grid gap-3">
<% availableChats.forEach(chat => { %>
<div class="flex items-center justify-between p-3 bg-gray-50 rounded-lg">
<div class="flex items-center space-x-3">
<div class="w-8 h-8 bg-blue-100 rounded-full flex items-center justify-center">
<i class="fas <%= chat.type === 'group' || chat.type === 'supergroup' ? 'fa-users' : 'fa-user' %> text-blue-600 text-sm"></i>
</div>
<div>
<div class="font-medium text-gray-900"><%= chat.title %></div>
<div class="text-sm text-gray-500">
<%= chat.type %> • ID: <%= chat.id %>
<% if (chat.username) { %>• @<%= chat.username %><% } %>
</div>
</div>
</div>
<button onclick="selectChat('<%= chat.id %>', '<%= chat.title %>')"
class="text-blue-600 hover:text-blue-800 text-sm">
Выбрать
</button>
</div>
<% }); %>
</div>
<% } else { %>
<div class="text-center py-8 text-gray-500">
<i class="fas fa-comments text-4xl text-gray-300 mb-4"></i>
<p class="mb-2">Чаты не найдены</p>
<p class="text-sm">Отправьте боту сообщение или добавьте его в группу, затем нажмите "Найти чаты"</p>
</div>
<% } %>
</div>
</div>
<% } %>
<!-- Message Sender -->
<div class="bg-white shadow rounded-lg p-6">
<h3 class="text-lg font-semibold text-gray-900 mb-6">
<i class="fas fa-paper-plane mr-2 text-purple-500"></i>
Отправить сообщение
</h3>
<form id="send-message-form" class="space-y-6">
<!-- Message Content -->
<div>
<label for="messageText" class="block text-sm font-medium text-gray-700 mb-2">
Текст сообщения *
</label>
<textarea id="messageText" name="message" rows="4" required
placeholder="Введите сообщение..."
class="block w-full border border-gray-300 rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"></textarea>
</div>
<!-- Recipients -->
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">
Получатели
</label>
<div id="recipients-container" class="space-y-2">
<% if (availableChats && availableChats.length > 0) { %>
<% availableChats.forEach(chat => { %>
<label class="flex items-center">
<input type="checkbox" name="chatIds" value="<%= chat.id %>"
class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
<span class="ml-2 text-sm text-gray-900">
<%= chat.title %>
<span class="text-gray-500">(<%= chat.type %>)</span>
</span>
</label>
<% }); %>
<% } else { %>
<div class="text-sm text-gray-500">
<i class="fas fa-info-circle mr-1"></i>
Сообщение будет отправлено в чат по умолчанию
</div>
<% } %>
</div>
</div>
<!-- Message Options -->
<div class="bg-gray-50 p-4 rounded-lg">
<h4 class="text-sm font-medium text-gray-900 mb-3">Настройки сообщения</h4>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<label class="flex items-center">
<input type="checkbox" name="disableWebPagePreview"
class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
<span class="ml-2 text-sm text-gray-900">Отключить предпросмотр ссылок</span>
</label>
<label class="flex items-center">
<input type="checkbox" name="disableNotification"
class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
<span class="ml-2 text-sm text-gray-900">Тихое уведомление</span>
</label>
</div>
<div class="mt-4">
<label for="parseMode" class="block text-sm font-medium text-gray-700 mb-1">
Формат текста
</label>
<select name="parseMode" id="parseMode"
class="block w-full border border-gray-300 rounded-md px-3 py-2 text-sm">
<option value="HTML">HTML</option>
<option value="Markdown">Markdown</option>
<option value="">Обычный текст</option>
</select>
</div>
</div>
<!-- Submit Buttons -->
<div class="flex justify-between">
<button type="button" onclick="previewMessage()"
class="inline-flex items-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50">
<i class="fas fa-eye mr-2"></i>
Предпросмотр
</button>
<div class="space-x-3">
<button type="button" onclick="testConnection()"
class="inline-flex items-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50">
<i class="fas fa-vial mr-2"></i>
Тест соединения
</button>
<button type="submit" id="sendMessageBtn"
class="inline-flex items-center px-6 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700">
<i class="fas fa-paper-plane mr-2"></i>
Отправить сообщение
</button>
</div>
</div>
</form>
<div id="send-result" class="mt-4 hidden"></div>
</div>
<!-- Bot Status and Controls -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<!-- Connection Test -->
<div class="bg-white shadow rounded-lg p-6">
<h3 class="text-lg font-semibold text-gray-900 mb-4">
<i class="fas fa-plug mr-2 text-green-500"></i>
Проверка подключения
</h3>
<p class="text-gray-600 mb-4">
Отправить тестовое сообщение для проверки работоспособности бота.
</p>
<button id="test-connection" class="w-full bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded-lg transition-colors">
<i class="fas fa-vial mr-2"></i>
Тестировать подключение
</button>
<div id="test-result" class="mt-4 hidden"></div>
</div>
<!-- Send Custom Message -->
<div class="bg-white shadow rounded-lg p-6">
<h3 class="text-lg font-semibold text-gray-900 mb-4">
<i class="fas fa-paper-plane mr-2 text-blue-500"></i>
Отправить сообщение
</h3>
<form id="send-message-form">
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 mb-2">
Сообщение
</label>
<textarea
id="custom-message"
rows="4"
class="w-full border border-gray-300 rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
placeholder="Введите текст сообщения..."></textarea>
</div>
<button type="submit" class="w-full bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg transition-colors">
<i class="fas fa-send mr-2"></i>
Отправить
</button>
</form>
<div id="send-result" class="mt-4 hidden"></div>
</div>
</div>
<!-- Notification Settings -->
<div class="bg-white shadow rounded-lg p-6">
<h3 class="text-lg font-semibold text-gray-900 mb-6">
<i class="fas fa-bell mr-2 text-purple-500"></i>
Настройки уведомлений
</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Notification Types -->
<div>
<h4 class="font-medium text-gray-900 mb-4">Типы уведомлений</h4>
<div class="space-y-3">
<div class="flex items-center justify-between p-3 bg-gray-50 rounded-lg">
<div class="flex items-center">
<i class="fas fa-envelope mr-3 text-blue-500"></i>
<span class="text-sm text-gray-900">Новые обращения</span>
</div>
<div class="w-3 h-3 bg-green-500 rounded-full"></div>
</div>
<div class="flex items-center justify-between p-3 bg-gray-50 rounded-lg">
<div class="flex items-center">
<i class="fas fa-calculator mr-3 text-green-500"></i>
<span class="text-sm text-gray-900">Расчеты стоимости</span>
</div>
<div class="w-3 h-3 bg-green-500 rounded-full"></div>
</div>
<div class="flex items-center justify-between p-3 bg-gray-50 rounded-lg">
<div class="flex items-center">
<i class="fas fa-briefcase mr-3 text-purple-500"></i>
<span class="text-sm text-gray-900">Новые проекты</span>
</div>
<div class="w-3 h-3 bg-green-500 rounded-full"></div>
</div>
<div class="flex items-center justify-between p-3 bg-gray-50 rounded-lg">
<div class="flex items-center">
<i class="fas fa-cog mr-3 text-orange-500"></i>
<span class="text-sm text-gray-900">Новые услуги</span>
</div>
<div class="w-3 h-3 bg-green-500 rounded-full"></div>
</div>
</div>
</div>
<!-- Bot Information -->
<div>
<h4 class="font-medium text-gray-900 mb-4">Информация о боте</h4>
<div class="space-y-3">
<div class="flex justify-between">
<span class="text-sm text-gray-600">Статус:</span>
<span class="text-sm font-medium text-green-600">Активен</span>
</div>
<div class="flex justify-between">
<span class="text-sm text-gray-600">Токен:</span>
<span class="text-sm font-mono text-gray-800">••••••••••</span>
</div>
<div class="flex justify-between">
<span class="text-sm text-gray-600">Chat ID:</span>
<span class="text-sm font-mono text-gray-800">••••••••••</span>
</div>
<div class="flex justify-between">
<span class="text-sm text-gray-600">Последнее уведомление:</span>
<span class="text-sm text-gray-600">Недавно</span>
</div>
</div>
</div>
</div>
</div>
<!-- Recent Notifications -->
<div class="bg-white shadow rounded-lg p-6">
<h3 class="text-lg font-semibold text-gray-900 mb-6">
<i class="fas fa-history mr-2 text-gray-500"></i>
Недавние уведомления
</h3>
<div class="text-center py-8 text-gray-500">
<i class="fas fa-inbox text-4xl text-gray-300 mb-4"></i>
<p>Уведомления будут отображаться здесь после отправки</p>
</div>
</div>
<% } %>
</div>
</main>
</div>
<!-- JavaScript -->
<script src="/js/main.js"></script>
<script>
// Bot Configuration
document.getElementById('bot-config-form').addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const data = Object.fromEntries(formData);
try {
showLoading('Сохранение настроек...');
const response = await fetch('/admin/telegram/configure', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
const result = await response.json();
if (result.success) {
showResult('config-result', result.message, 'success');
// Update bot info if available
if (result.botInfo) {
updateBotInfo(result.botInfo);
}
if (result.availableChats) {
updateAvailableChats(result.availableChats);
}
} else {
showResult('config-result', result.message, 'error');
}
} catch (error) {
showResult('config-result', 'Ошибка при сохранении настроек', 'error');
} finally {
hideLoading();
}
});
// Send message form
document.getElementById('send-message-form').addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const message = formData.get('message');
const chatIds = formData.getAll('chatIds');
const parseMode = formData.get('parseMode');
const disableWebPagePreview = formData.has('disableWebPagePreview');
const disableNotification = formData.has('disableNotification');
if (!message.trim()) {
showResult('send-result', 'Введите текст сообщения', 'error');
return;
}
const data = {
message: message.trim(),
chatIds: chatIds.length > 0 ? chatIds : [],
parseMode,
disableWebPagePreview,
disableNotification
};
try {
const btn = document.getElementById('sendMessageBtn');
btn.disabled = true;
btn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i>Отправка...';
const response = await fetch('/admin/telegram/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
const result = await response.json();
if (result.success) {
showResult('send-result', result.message, 'success');
document.getElementById('messageText').value = '';
} else {
showResult('send-result', result.message, 'error');
}
} catch (error) {
showResult('send-result', 'Ошибка при отправке сообщения', 'error');
} finally {
const btn = document.getElementById('sendMessageBtn');
btn.disabled = false;
btn.innerHTML = '<i class="fas fa-paper-plane mr-2"></i>Отправить сообщение';
}
});
// Utility functions
function toggleTokenVisibility() {
const input = document.getElementById('botToken');
const eye = document.getElementById('token-eye');
if (input.type === 'password') {
input.type = 'text';
eye.className = 'fas fa-eye-slash text-gray-400';
} else {
input.type = 'password';
eye.className = 'fas fa-eye text-gray-400';
}
}
async function getBotInfo() {
try {
showLoading('Получение информации о боте...');
const response = await fetch('/admin/telegram/info');
const result = await response.json();
if (result.success) {
updateBotInfo(result.botInfo);
updateAvailableChats(result.availableChats);
showResult('config-result', 'Информация о боте обновлена', 'success');
} else {
showResult('config-result', result.message, 'error');
}
} catch (error) {
showResult('config-result', 'Ошибка при получении информации о боте', 'error');
} finally {
hideLoading();
}
}
async function refreshBotInfo() {
await getBotInfo();
}
async function discoverChats() {
try {
showLoading('Поиск доступных чатов...');
const response = await fetch('/admin/telegram/info');
const result = await response.json();
if (result.success && result.availableChats) {
updateAvailableChats(result.availableChats);
showNotification('Найдено чатов: ' + result.availableChats.length, 'success');
} else {
showNotification('Чаты не найдены', 'warning');
}
} catch (error) {
showNotification('Ошибка при поиске чатов', 'error');
} finally {
hideLoading();
}
}
function selectChat(chatId, chatTitle) {
document.getElementById('chatId').value = chatId;
showNotification(`Выбран чат: ${chatTitle}`, 'success');
}
async function testConnection() {
try {
showLoading('Тестирование соединения...');
const response = await fetch('/admin/telegram/test', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
const result = await response.json();
if (result.success) {
showResult('send-result', 'Соединение успешно! Тестовое сообщение отправлено.', 'success');
} else {
showResult('send-result', result.message, 'error');
}
} catch (error) {
showResult('send-result', 'Ошибка при тестировании соединения', 'error');
} finally {
hideLoading();
}
}
function previewMessage() {
const message = document.getElementById('messageText').value;
const parseMode = document.getElementById('parseMode').value;
if (!message.trim()) {
showNotification('Введите текст сообщения для предпросмотра', 'warning');
return;
}
// Simple preview modal (you can enhance this)
const preview = window.open('', 'preview', 'width=400,height=300');
preview.document.write(`
<html>
<head><title>Предпросмотр сообщения</title></head>
<body style="font-family: Arial, sans-serif; padding: 20px;">
<h3>Предпросмотр сообщения (${parseMode || 'Обычный текст'})</h3>
<div style="border: 1px solid #ccc; padding: 10px; background: #f9f9f9;">
${parseMode === 'HTML' ? message : message.replace(/\n/g, '<br>')}
</div>
<button onclick="window.close()" style="margin-top: 10px;">Закрыть</button>
</body>
</html>
`);
}
// UI Helper functions
function updateBotInfo(botInfo) {
const container = document.getElementById('bot-info-container');
if (!botInfo) return;
container.innerHTML = `
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<div class="bg-gray-50 p-4 rounded-lg">
<div class="text-sm text-gray-600">Имя бота</div>
<div class="text-lg font-semibold text-gray-900">@${botInfo.username}</div>
</div>
<div class="bg-gray-50 p-4 rounded-lg">
<div class="text-sm text-gray-600">Отображаемое имя</div>
<div class="text-lg font-semibold text-gray-900">${botInfo.first_name}</div>
</div>
<div class="bg-gray-50 p-4 rounded-lg">
<div class="text-sm text-gray-600">ID бота</div>
<div class="text-lg font-semibold text-gray-900">${botInfo.id}</div>
</div>
<div class="bg-gray-50 p-4 rounded-lg">
<div class="text-sm text-gray-600">Может читать сообщения</div>
<div class="text-lg font-semibold ${botInfo.can_read_all_group_messages ? 'text-green-600' : 'text-red-600'}">
${botInfo.can_read_all_group_messages ? 'Да' : 'Нет'}
</div>
</div>
</div>
`;
}
function updateAvailableChats(chats) {
const container = document.getElementById('available-chats-container');
if (!chats || chats.length === 0) {
container.innerHTML = `
<div class="text-center py-8 text-gray-500">
<i class="fas fa-comments text-4xl text-gray-300 mb-4"></i>
<p class="mb-2">Чаты не найдены</p>
<p class="text-sm">Отправьте боту сообщение или добавьте его в группу, затем нажмите "Найти чаты"</p>
</div>
`;
return;
}
const chatsHtml = chats.map(chat => `
<div class="flex items-center justify-between p-3 bg-gray-50 rounded-lg">
<div class="flex items-center space-x-3">
<div class="w-8 h-8 bg-blue-100 rounded-full flex items-center justify-center">
<i class="fas ${chat.type === 'group' || chat.type === 'supergroup' ? 'fa-users' : 'fa-user'} text-blue-600 text-sm"></i>
</div>
<div>
<div class="font-medium text-gray-900">${chat.title}</div>
<div class="text-sm text-gray-500">
${chat.type} • ID: ${chat.id}
${chat.username ? '• @' + chat.username : ''}
</div>
</div>
</div>
<button onclick="selectChat('${chat.id}', '${chat.title}')"
class="text-blue-600 hover:text-blue-800 text-sm">
Выбрать
</button>
</div>
`).join('');
container.innerHTML = `<div class="grid gap-3">${chatsHtml}</div>`;
// Also update recipients list
updateRecipientsList(chats);
}
function updateRecipientsList(chats) {
const container = document.getElementById('recipients-container');
if (!chats || chats.length === 0) {
container.innerHTML = `
<div class="text-sm text-gray-500">
<i class="fas fa-info-circle mr-1"></i>
Сообщение будет отправлено в чат по умолчанию
</div>
`;
return;
}
const recipientsHtml = chats.map(chat => `
<label class="flex items-center">
<input type="checkbox" name="chatIds" value="${chat.id}"
class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
<span class="ml-2 text-sm text-gray-900">
${chat.title}
<span class="text-gray-500">(${chat.type})</span>
</span>
</label>
`).join('');
container.innerHTML = recipientsHtml;
}
function showResult(elementId, message, type) {
const element = document.getElementById(elementId);
const className = type === 'success' ? 'bg-green-100 text-green-800' :
type === 'warning' ? 'bg-yellow-100 text-yellow-800' :
'bg-red-100 text-red-800';
const icon = type === 'success' ? 'fa-check' :
type === 'warning' ? 'fa-exclamation-triangle' :
'fa-times';
element.className = `mt-4 p-3 rounded-lg ${className}`;
element.innerHTML = `<i class="fas ${icon} mr-2"></i>${message}`;
element.classList.remove('hidden');
setTimeout(() => {
element.classList.add('hidden');
}, 5000);
}
function showNotification(message, type = 'info') {
const notification = document.createElement('div');
notification.className = `fixed top-4 right-4 z-50 px-4 py-3 rounded-lg shadow-lg text-white max-w-sm transform transition-all duration-300 translate-x-full`;
switch(type) {
case 'success':
notification.classList.add('bg-green-600');
break;
case 'error':
notification.classList.add('bg-red-600');
break;
case 'warning':
notification.classList.add('bg-yellow-600');
break;
default:
notification.classList.add('bg-blue-600');
}
notification.innerHTML = `
<div class="flex items-center">
<i class="fas ${type === 'success' ? 'fa-check-circle' : type === 'error' ? 'fa-exclamation-circle' : type === 'warning' ? 'fa-exclamation-triangle' : 'fa-info-circle'} mr-2"></i>
<span>${message}</span>
</div>
`;
document.body.appendChild(notification);
setTimeout(() => {
notification.classList.remove('translate-x-full');
}, 100);
setTimeout(() => {
notification.classList.add('translate-x-full');
setTimeout(() => {
if (document.body.contains(notification)) {
document.body.removeChild(notification);
}
}, 300);
}, 4000);
}
function showLoading(message) {
// Create or show loading overlay
let overlay = document.getElementById('loading-overlay');
if (!overlay) {
overlay = document.createElement('div');
overlay.id = 'loading-overlay';
overlay.className = 'fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50';
overlay.innerHTML = `
<div class="bg-white p-6 rounded-lg shadow-lg">
<div class="flex items-center">
<i class="fas fa-spinner fa-spin text-blue-600 text-xl mr-3"></i>
<span id="loading-message">${message}</span>
</div>
</div>
`;
document.body.appendChild(overlay);
} else {
document.getElementById('loading-message').textContent = message;
overlay.style.display = 'flex';
}
}
function hideLoading() {
const overlay = document.getElementById('loading-overlay');
if (overlay) {
overlay.style.display = 'none';
}
}
</script>
</body>
</html>