Tg with Notifications, bags fixxed (Removed)

This commit is contained in:
2025-09-04 14:44:31 +03:00
parent 51995c3695
commit 70b9d456e1
8 changed files with 0 additions and 1022 deletions

View File

@@ -1,134 +0,0 @@
# Улучшения игры - Полный список
## 🆕 Новые функции
### 1. Уведомления о сообщениях в Telegram
- **Описание**: Показываются уведомления о новых сообщениях, когда Telegram не открыт
- **Как работает**:
- WebSocket событие `newMessage` обрабатывается на клиенте
- Уведомление появляется в правом верхнем углу экрана
- Автоматически исчезает через 5 секунд
- Анимированное появление и исчезновение
- **Файлы**: `src/Game.js` - добавлена функция `showMessageNotification()`
### 2. Уведомления о перезагрузке сервера
- **Описание**: Игроки получают предупреждение о перезагрузке сервера
- **Как работает**:
- Сервер отправляет событие `serverRestart` всем клиентам
- Показывается красное уведомление с обратным отсчетом
- Сервер корректно завершает работу через 5 секунд
- **Файлы**:
- `server.js` - добавлена функция `gracefulShutdown()`
- `src/Game.js` - добавлена функция `showServerRestartNotification()`
## 🎮 Улучшения управления
### 3. Исправление застревания в текстурах
- **Проблема**: Игрок застревал в текстурах и не мог выбраться
- **Решение**:
- Уменьшены размеры коллизионной коробки игрока (с 0.25 до 0.2)
- Добавлено скольжение вдоль стен при столкновении
- Увеличен зазор между игроком и объектами (с 0.01 до 0.05)
- Улучшена система определения направления скольжения
- **Файлы**: `src/Game.js` - улучшена функция `updateFirstPersonMovement()`
### 4. Улучшенное управление камерой
- **Новые возможности**:
- `Ctrl + колесо` = вертикальный поворот камеры (как было)
- `Shift + Ctrl + колесо` = горизонтальный поворот камеры (±90 градусов)
- **Ограничения**: Горизонтальный поворот ограничен для предотвращения дезориентации
- **Файлы**: `src/Game.js` - улучшена функция `onMouseWheel()`
### 5. Отключение браузерного масштабирования
- **Проблема**: Браузер масштабировал страницу при Ctrl + колесо
- **Решение**: Добавлены обработчики событий для предотвращения масштабирования
- **Файлы**: `src/Game.js` - добавлены обработчики `wheel` и `keydown`
## 🚀 Оптимизация производительности
### 6. Улучшенная система загрузки ресурсов
- **Проблема**: Панель загрузки блокировала управление игрой
- **Решение**:
- Панель показывается только при начальной загрузке или загрузке >5 ресурсов
- Малые загрузки происходят в фоне без блокировки
- Добавлен флаг `isInitialLoad` для контроля отображения
- **Файлы**: `src/Game.js` - улучшен `LoadingManager`
## 🔧 Технические улучшения
### 7. Graceful Shutdown сервера
- **Описание**: Сервер корректно завершает работу при получении сигналов
- **Сигналы**: `SIGTERM`, `SIGINT` (Ctrl+C)
- **Процесс**:
1. Уведомление всех клиентов
2. Ожидание 5 секунд
3. Закрытие HTTP сервера
4. Принудительное завершение через 10 секунд
### 8. Улучшенная система коллизий
- **Алгоритм скольжения**:
- Определение ближайшего препятствия
- Вычисление направления скольжения
- Проверка возможности движения в направлении скольжения
- Применение скольжения с уменьшенной дистанцией
## 📱 Пользовательский интерфейс
### 9. Подсказки по управлению
- **Описание**: Автоматически показывается подсказка об управлении камерой
- **Время**: Появляется через 3 секунды после загрузки игры
- **Длительность**: Висит 10 секунд, затем плавно исчезает
- **Стиль**: Темная полупрозрачная панель с анимацией
## 🧪 Тестирование
### 10. Тестовые файлы
- `test_telegram_status.html` - тест API статуса пользователей
- `TELEGRAM_STATUS_README.md` - документация по системе статусов
- `TESTING_INSTRUCTIONS.md` - инструкции по тестированию
- `GAME_IMPROVEMENTS_README.md` - этот файл
## 🚀 Как запустить
1. **Запуск сервера**:
```bash
node server.js
```
2. **Тестирование уведомлений**:
- Откройте игру в браузере
- Войдите в систему
- Откройте Telegram и отправьте сообщение
- Проверьте уведомления
3. **Тестирование перезагрузки**:
- Нажмите Ctrl+C в терминале сервера
- Проверьте уведомление о перезагрузке
4. **Тестирование управления**:
- `Ctrl + колесо` = вертикальный поворот
- `Shift + Ctrl + колесо` = горизонтальный поворот
## 🔍 Отладка
- **Сервер**: Логи в консоли терминала
- **Клиент**: Логи в консоли браузера (F12)
- **WebSocket**: Проверка соединения в Network tab
## 📋 Чек-лист тестирования
- [ ] Уведомления о сообщениях работают
- [ ] Уведомления о перезагрузке сервера работают
- [ ] Игрок не застревает в текстурах
- [ ] Управление камерой работает корректно
- [ ] Браузерное масштабирование отключено
- [ ] Панель загрузки не блокирует игру
- [ ] Подсказки по управлению отображаются
## 🎯 Следующие шаги
1. **Кэширование**: Добавить кэширование статуса пользователей
2. **Группировка**: Группировать пользователей по статусу в Telegram
3. **Уведомления**: Push-уведомления для важных событий
4. **Статистика**: Время онлайн, активность пользователей
5. **Оптимизация**: Дальнейшее улучшение производительности

View File

@@ -1,164 +0,0 @@
# Улучшения Telegram в игре
## Обзор
Этот документ описывает улучшения, внесенные в приложение Telegram (Shipgram) в игре, включая систему уведомлений, индикаторы непрочитанных сообщений и исправление проблемы "неизвестного отправителя".
## Основные улучшения
### 1. Уведомления о новых сообщениях
**Проблема**: При получении новых сообщений в Telegram не было уведомлений, если приложение не было открыто.
**Решение**: Реализована система уведомлений, которая показывает красивые всплывающие уведомления в правом верхнем углу экрана.
**Функциональность**:
- Уведомления появляются только когда Telegram не открыт
- Отображают имя отправителя и текст сообщения
- Автоматически исчезают через 5 секунд
- Красивый дизайн с градиентом и анимацией
**Код**: `showMessageNotification(senderId, messageText)` в `src/Game.js`
### 2. Исправление проблемы "неизвестного отправителя"
**Проблема**: В уведомлениях отображалось "Неизвестный" вместо имени отправителя.
**Решение**: Реализована система поиска информации об отправителе:
1. Сначала ищет в списке контактов
2. Если не найден, загружает информацию с сервера через новый API endpoint
**Новые API endpoints**:
- `GET /api/users/:userId` - получение информации о пользователе по ID
- `GET /api/messages-read/:contactId` - получение количества непрочитанных сообщений
**Код**: Обновленная функция `showMessageNotification` в `src/Game.js`
### 3. Индикаторы непрочитанных сообщений
**Проблема**: Не было визуального индикатора непрочитанных сообщений в списке контактов.
**Решение**: Добавлены счетчики непрочитанных сообщений:
- Красные бейджи с количеством непрочитанных сообщений
- Имена контактов выделяются жирным шрифтом при наличии непрочитанных сообщений
- Автоматическое обновление счетчиков
**Функциональность**:
- `updateUnreadCount(senderId)` - обновляет счетчик для конкретного отправителя
- Автоматическое обновление при получении новых сообщений
- Периодическое обновление каждые 30 секунд
**Код**: Функция `updateUnreadCount` и обновленный UI в `src/Game.js`
## Технические детали
### Серверная часть (`server.js`)
#### Новые API endpoints
```javascript
// Получение информации о пользователе по ID
app.get('/api/users/:userId', authenticate, async (req, res) => {
// Возвращает: id, firstName, lastName, avatarURL, isOnline, lastSeen
});
// Получение количества непрочитанных сообщений
app.get('/api/messages-read/:contactId', authenticate, async (req, res) => {
// Возвращает: { unreadCount: number }
});
```
#### Исправления для onlineUsers и lastSeenTimes
- Заменены `onlineUsers.hasOwnProperty()` на `onlineUsers.has()`
- Заменены `lastSeenTimes[userId]` на `lastSeenTimes.get(userId)`
- Исправлен `console.log` для отображения ключей Map
### Клиентская часть (`src/Game.js`)
#### Новые функции
```javascript
// Показ уведомлений о сообщениях
const showMessageNotification = async (senderId, messageText) => {
// Логика поиска имени отправителя и показа уведомления
};
// Обновление счетчика непрочитанных сообщений
const updateUnreadCount = async (senderId) => {
// Загрузка и обновление счетчика
};
```
#### Обновленный UI
- Счетчики непрочитанных сообщений (красные бейджи)
- Выделение имен контактов жирным шрифтом
- Улучшенная структура контактов
### API функции (`src/api/auth.js`)
```javascript
// Загрузка информации о пользователе по ID
export const loadUserInfo = async (userId, token) => {
// Запрос к /api/users/:userId
};
// Обновленная функция получения статуса пользователей
export const getUsersStatus = async (token) => {
// Улучшенная обработка ошибок
};
```
## Тестирование
### Тестовый файл
Создан `test_telegram_improvements.html` для тестирования новых API endpoints:
1. **Тест статуса пользователей** - `/api/users/status`
2. **Тест информации о пользователе** - `/api/users/:userId`
3. **Тест количества непрочитанных сообщений** - `/api/messages-read/:contactId`
### Инструкции по тестированию
1. Откройте `test_telegram_improvements.html` в браузере
2. Введите JWT токен пользователя
3. Протестируйте каждый endpoint
4. Проверьте корректность возвращаемых данных
## Интеграция с существующим кодом
### WebSocket события
- `newMessage` - автоматически вызывает `updateUnreadCount` и `showMessageNotification`
- `userStatusChanged` - обновляет статус пользователей в реальном времени
### Интервалы обновления
- `statusInterval` - каждые 30 секунд обновляет статусы и счетчики непрочитанных сообщений
### Состояние компонента
- `telegramContacts` - расширен для хранения `unreadCount`
- Автоматическое обновление при изменении данных
## Преимущества
1. **Лучший UX**: Пользователи видят уведомления о новых сообщениях
2. **Информативность**: Четко видно, от кого пришло сообщение
3. **Отслеживание**: Легко понять, какие чаты требуют внимания
4. **Производительность**: Эффективное обновление данных через интервалы
5. **Надежность**: Обработка ошибок и fallback для неизвестных отправителей
## Возможные улучшения в будущем
1. **Звуковые уведомления** - добавление звуковых сигналов
2. **Настройки уведомлений** - возможность отключения для определенных контактов
3. **Push-уведомления** - интеграция с браузерными push-уведомлениями
4. **Группировка уведомлений** - объединение уведомлений от одного отправителя
5. **История уведомлений** - сохранение истории показанных уведомлений
## Заключение
Реализованные улучшения значительно повышают удобство использования Telegram в игре, решая основные проблемы с уведомлениями и отображением информации об отправителях. Система стала более информативной и удобной для пользователей.

View File

@@ -1,78 +0,0 @@
# Система статуса пользователей для Telegram (Shipgram)
## Описание
Реализована система отображения статуса "online/offline" для пользователей в Telegram приложении (Shipgram) игрового телефона. Статус показывает, действительно ли игрок находится онлайн в игре.
## Что реализовано
### 1. Серверная часть (server.js)
- **Отслеживание онлайн пользователей**: Переменная `onlineUsers` хранит ID пользователей, которые в данный момент подключены к WebSocket
- **Отслеживание времени последнего онлайн**: Переменная `lastSeenTimes` хранит время последнего подключения/отключения каждого пользователя
- **WebSocket события**:
- При подключении: `userStatusChanged` с `isOnline: true`
- При отключении: `userStatusChanged` с `isOnline: false`
- **API endpoint**: `/api/users/status` возвращает список пользователей с их статусом
### 2. Клиентская часть (Game.js)
- **Обновленный API вызов**: `loadTelegramContacts()` теперь использует `/api/users/status` вместо `/api/users`
- **WebSocket обработчик**: Слушает события `userStatusChanged` и обновляет статус в реальном времени
- **Периодическое обновление**: Каждые 30 секунд обновляет статус пользователей
- **Визуальные индикаторы**:
- Зеленая точка для онлайн пользователей
- Цветной текст статуса (зеленый для онлайн, серый для офлайн)
- Время последнего онлайн для офлайн пользователей
### 3. API функции (auth.js)
- Добавлена функция `getUsersStatus()` для получения статуса пользователей
## Как это работает
1. **Подключение пользователя**:
- Пользователь входит в игру
- WebSocket middleware добавляет его в `onlineUsers`
- Обновляется `lastSeenTimes`
- Отправляется событие `userStatusChanged` всем клиентам
2. **Отключение пользователя**:
- Пользователь выходит из игры или теряет соединение
- Обновляется `lastSeenTimes`
- Отправляется событие `userStatusChanged` всем клиентам
- Пользователь удаляется из `onlineUsers`
3. **Отображение в Telegram**:
- При открытии Telegram загружается список пользователей с их статусом
- Статус обновляется в реальном времени через WebSocket
- Периодически обновляется через API для синхронизации
## Файлы, которые были изменены
- `server.js` - добавлена логика отслеживания статуса и WebSocket события
- `src/Game.js` - обновлено Telegram приложение для отображения статуса
- `src/api/auth.js` - добавлена функция для получения статуса пользователей
- `test_telegram_status.html` - тестовый файл для проверки API
## Тестирование
1. Запустите сервер
2. Откройте `test_telegram_status.html` в браузере
3. Введите JWT токен пользователя
4. Нажмите "Тестировать API"
5. Проверьте, что статус пользователей отображается корректно
## Особенности
- **Реальное время**: Статус обновляется мгновенно при подключении/отключении
- **Надежность**: Периодическое обновление через API обеспечивает синхронизацию
- **Производительность**: WebSocket события отправляются только при изменении статуса
- **Визуальная обратная связь**: Зеленые точки и цветной текст для лучшего UX
## Возможные улучшения
1. **Кэширование**: Добавить кэширование статуса пользователей
2. **Группировка**: Группировать пользователей по статусу
3. **Уведомления**: Уведомления о том, что пользователь стал онлайн
4. **Статистика**: Время, проведенное онлайн, активность и т.д.

View File

@@ -1,60 +0,0 @@
# Инструкция по тестированию системы статуса пользователей
## Быстрый тест
1. **Запустите сервер**:
```bash
node server.js
```
2. **Откройте игру в браузере** и войдите в систему
3. **Откройте Telegram в игровом телефоне** и проверьте:
- Отображается ли статус "Онлайн" для текущего пользователя
- Есть ли зеленая точка рядом с аватаром
- Показывает ли статус "Офлайн" для других пользователей
## Детальное тестирование
### Тест 1: Проверка API
1. Откройте `test_telegram_status.html` в браузере
2. Введите JWT токен из localStorage браузера
3. Нажмите "Тестировать API"
4. Проверьте, что возвращается список пользователей с полями:
- `isOnline`: boolean
- `lastSeen`: timestamp или null
### Тест 2: Проверка WebSocket событий
1. Откройте консоль браузера
2. Войдите в игру
3. Проверьте логи:
```
Статус пользователя изменился: {userId: X, isOnline: true}
```
### Тест 3: Проверка реального времени
1. Откройте игру в двух вкладках браузера
2. Войдите под разными пользователями
3. В одной вкладке откройте Telegram
4. В другой вкладке закройте игру
5. Проверьте, что статус изменился на "Офлайн" в реальном времени
## Ожидаемые результаты
- ✅ Статус "Онлайн" отображается только для пользователей, которые действительно в игре
- ✅ Зеленая точка появляется рядом с аватаром онлайн пользователей
- ✅ Статус обновляется в реальном времени при подключении/отключении
- ✅ Время последнего онлайн отображается для офлайн пользователей
-В консоли сервера видны логи подключения/отключения пользователей
## Возможные проблемы
1. **Статус не обновляется**: Проверьте WebSocket соединение
2. **API возвращает ошибку**: Проверьте JWT токен и права доступа
3. **Статус не синхронизируется**: Проверьте логи сервера на наличие ошибок
## Отладка
- **Сервер**: Смотрите логи в консоли сервера
- **Клиент**: Смотрите логи в консоли браузера
- **WebSocket**: Проверьте соединение в Network tab браузера

View File

@@ -1,14 +0,0 @@
warning: in the working copy of '.env', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of '.gitignore', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'db.js', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'db1.js', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'package-lock.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'server.js', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/Game.js', LF will be replaced by CRLF the next time Git touches it
.env | 4 ++--
db.js | 4 +---
db1.js | 2 +-
package-lock.json | 57 +++++++++++++++++++++++++++++--------------------------
server.js | 10 ++++------
src/Game.js | 40 +++++++++++++-------------------------
6 files changed, 51 insertions(+), 66 deletions(-)

View File

@@ -1,217 +0,0 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Тест исправления Telegram</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background: #f5f5f5;
}
.test-section {
background: white;
padding: 20px;
margin: 20px 0;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.input-group {
margin: 10px 0;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
input, button {
padding: 8px 12px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
}
button {
background: #007bff;
color: white;
cursor: pointer;
margin-left: 10px;
}
button:hover {
background: #0056b3;
}
.result {
background: #f8f9fa;
padding: 15px;
border-radius: 4px;
margin-top: 10px;
white-space: pre-wrap;
font-family: monospace;
max-height: 300px;
overflow-y: auto;
}
.error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.success {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
</style>
</head>
<body>
<h1>Тест исправления Telegram контактов</h1>
<div class="test-section">
<h2>1. Тест загрузки контактов</h2>
<div class="input-group">
<label for="token1">JWT Token:</label>
<input type="text" id="token1" placeholder="Введите JWT токен" style="width: 400px;">
</div>
<button onclick="testLoadContacts()">Загрузить контакты</button>
<div id="contactsResult" class="result"></div>
</div>
<div class="test-section">
<h2>2. Тест получения информации о пользователе</h2>
<div class="input-group">
<label for="token2">JWT Token:</label>
<input type="text" id="token2" placeholder="Введите JWT токен" style="width: 400px;">
</div>
<div class="input-group">
<label for="userId">User ID:</label>
<input type="number" id="userId" placeholder="Введите ID пользователя">
</div>
<button onclick="testGetUserInfo()">Получить информацию о пользователе</button>
<div id="userInfoResult" class="result"></div>
</div>
<div class="test-section">
<h2>3. Тест количества непрочитанных сообщений</h2>
<div class="input-group">
<label for="token3">JWT Token:</label>
<input type="text" id="token3" placeholder="Введите JWT токен" style="width: 400px;">
</div>
<div class="input-group">
<label for="contactId">Contact ID:</label>
<input type="number" id="contactId" placeholder="Введите ID контакта">
</div>
<button onclick="testUnreadCount()">Получить количество непрочитанных</button>
<div id="unreadResult" class="result"></div>
</div>
<script>
async function testLoadContacts() {
const token = document.getElementById('token1').value;
const resultDiv = document.getElementById('contactsResult');
if (!token) {
resultDiv.className = 'result error';
resultDiv.textContent = 'Ошибка: Введите JWT токен';
return;
}
try {
const response = await fetch('/api/users/status', {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
if (response.ok) {
const data = await response.json();
resultDiv.className = 'result success';
resultDiv.textContent = `✅ Успешно загружено ${data.length} контактов:\n\n${JSON.stringify(data, null, 2)}`;
} else {
const errorText = await response.text();
resultDiv.className = 'result error';
resultDiv.textContent = `❌ Ошибка ${response.status}: ${errorText}`;
}
} catch (error) {
resultDiv.className = 'result error';
resultDiv.textContent = `❌ Ошибка сети: ${error.message}`;
}
}
async function testGetUserInfo() {
const token = document.getElementById('token2').value;
const userId = document.getElementById('userId').value;
const resultDiv = document.getElementById('userInfoResult');
if (!token || !userId) {
resultDiv.className = 'result error';
resultDiv.textContent = 'Ошибка: Введите JWT токен и User ID';
return;
}
try {
const response = await fetch(`/api/users/${userId}`, {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
if (response.ok) {
const data = await response.json();
resultDiv.className = 'result success';
resultDiv.textContent = `✅ Информация о пользователе:\n\n${JSON.stringify(data, null, 2)}`;
} else {
const errorText = await response.text();
resultDiv.className = 'result error';
resultDiv.textContent = `❌ Ошибка ${response.status}: ${errorText}`;
}
} catch (error) {
resultDiv.className = 'result error';
resultDiv.textContent = `❌ Ошибка сети: ${error.message}`;
}
}
async function testUnreadCount() {
const token = document.getElementById('token3').value;
const contactId = document.getElementById('contactId').value;
const resultDiv = document.getElementById('unreadResult');
if (!token || !contactId) {
resultDiv.className = 'result error';
resultDiv.textContent = 'Ошибка: Введите JWT токен и Contact ID';
return;
}
try {
const response = await fetch(`/api/messages-read/${contactId}`, {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
if (response.ok) {
const data = await response.json();
resultDiv.className = 'result success';
resultDiv.textContent = `✅ Количество непрочитанных сообщений:\n\n${JSON.stringify(data, null, 2)}`;
} else {
const errorText = await response.text();
resultDiv.className = 'result error';
resultDiv.textContent = `❌ Ошибка ${response.status}: ${errorText}`;
}
} catch (error) {
resultDiv.className = 'result error';
resultDiv.textContent = `❌ Ошибка сети: ${error.message}`;
}
}
// Автоматически копируем токен между полями
document.getElementById('token1').addEventListener('input', function() {
document.getElementById('token2').value = this.value;
document.getElementById('token3').value = this.value;
});
</script>
</body>
</html>

View File

@@ -1,201 +0,0 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Тест улучшений Telegram</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
}
.container {
background: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
margin-bottom: 20px;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
input[type="text"], input[type="number"] {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
box-sizing: border-box;
}
button {
background: #0084ff;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
margin-right: 10px;
}
button:hover {
background: #0073e6;
}
.result {
background: #f8f9fa;
padding: 15px;
border-radius: 4px;
margin-top: 15px;
white-space: pre-wrap;
font-family: monospace;
}
.error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.success {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
</style>
</head>
<body>
<h1>Тест улучшений Telegram</h1>
<div class="container">
<h2>1. Получение статуса пользователей</h2>
<div class="form-group">
<label for="token1">JWT Token:</label>
<input type="text" id="token1" placeholder="Введите JWT токен">
</div>
<button onclick="testUsersStatus()">Получить статус пользователей</button>
<div id="result1" class="result" style="display: none;"></div>
</div>
<div class="container">
<h2>2. Получение информации о пользователе по ID</h2>
<div class="form-group">
<label for="token2">JWT Token:</label>
<input type="text" id="token2" placeholder="Введите JWT токен">
</div>
<div class="form-group">
<label for="userId">ID пользователя:</label>
<input type="number" id="userId" placeholder="Введите ID пользователя">
</div>
<button onclick="testUserInfo()">Получить информацию о пользователе</button>
<div id="result2" class="result" style="display: none;"></div>
</div>
<div class="container">
<h2>3. Получение количества непрочитанных сообщений</h2>
<div class="form-group">
<label for="token3">JWT Token:</label>
<input type="text" id="token3" placeholder="Введите JWT токен">
</div>
<div class="form-group">
<label for="contactId">ID контакта:</label>
<input type="number" id="contactId" placeholder="Введите ID контакта">
</div>
<button onclick="testUnreadCount()">Получить количество непрочитанных сообщений</button>
<div id="result3" class="result" style="display: none;"></div>
</div>
<script>
function showResult(elementId, data, isError = false) {
const element = document.getElementById(elementId);
element.style.display = 'block';
element.className = `result ${isError ? 'error' : 'success'}`;
element.textContent = JSON.stringify(data, null, 2);
}
async function testUsersStatus() {
const token = document.getElementById('token1').value;
if (!token) {
showResult('result1', { error: 'Введите JWT токен' }, true);
return;
}
try {
const response = await fetch('/api/users/status', {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
const data = await response.json();
if (response.ok) {
showResult('result1', data);
} else {
showResult('result1', data, true);
}
} catch (error) {
showResult('result1', { error: error.message }, true);
}
}
async function testUserInfo() {
const token = document.getElementById('token2').value;
const userId = document.getElementById('userId').value;
if (!token || !userId) {
showResult('result2', { error: 'Введите JWT токен и ID пользователя' }, true);
return;
}
try {
const response = await fetch(`/api/users/${userId}`, {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
const data = await response.json();
if (response.ok) {
showResult('result2', data);
} else {
showResult('result2', data, true);
}
} catch (error) {
showResult('result2', { error: error.message }, true);
}
}
async function testUnreadCount() {
const token = document.getElementById('token3').value;
const contactId = document.getElementById('contactId').value;
if (!token || !contactId) {
showResult('result3', { error: 'Введите JWT токен и ID контакта' }, true);
return;
}
try {
const response = await fetch(`/api/messages-read/${contactId}`, {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
const data = await response.json();
if (response.ok) {
showResult('result3', data);
} else {
showResult('result3', data, true);
}
} catch (error) {
showResult('result3', { error: error.message }, true);
}
}
</script>
</body>
</html>

View File

@@ -1,154 +0,0 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Тест Telegram Status API</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.user-item {
display: flex;
align-items: center;
gap: 10px;
padding: 10px;
border: 1px solid #ddd;
margin: 5px 0;
border-radius: 8px;
}
.avatar {
width: 40px;
height: 40px;
border-radius: 20px;
background: #e5e7eb;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
position: relative;
}
.online-indicator {
position: absolute;
bottom: 0;
right: 0;
width: 12px;
height: 12px;
border-radius: 6px;
background: #10b981;
border: 2px solid #fff;
}
.status {
font-size: 14px;
color: #6b7280;
}
.status.online {
color: #10b981;
font-weight: 600;
}
.error {
color: #dc2626;
padding: 10px;
background: #fef2f2;
border-radius: 8px;
}
button {
padding: 10px 20px;
background: #0084ff;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
margin: 10px 0;
}
button:hover {
background: #0066cc;
}
</style>
</head>
<body>
<h1>Тест Telegram Status API</h1>
<div>
<label for="token">JWT Token:</label><br>
<input type="text" id="token" placeholder="Введите JWT токен" style="width: 100%; padding: 10px; margin: 10px 0;">
<br>
<button onclick="testAPI()">Тестировать API</button>
<button onclick="clearResults()">Очистить результаты</button>
</div>
<div id="results"></div>
<script>
async function testAPI() {
const token = document.getElementById('token').value;
const resultsDiv = document.getElementById('results');
if (!token) {
resultsDiv.innerHTML = '<div class="error">Введите JWT токен</div>';
return;
}
try {
resultsDiv.innerHTML = '<div>Загрузка...</div>';
const response = await fetch('/api/users/status', {
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
}
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP ${response.status}: ${errorText}`);
}
const users = await response.json();
let html = '<h2>Результат:</h2>';
html += `<p>Найдено пользователей: ${users.length}</p>`;
users.forEach(user => {
const isOnline = user.isOnline;
const lastSeen = user.lastSeen;
let statusText = isOnline ? 'Онлайн' : 'Офлайн';
if (!isOnline && lastSeen) {
statusText = `Был(а) ${new Date(lastSeen).toLocaleString('ru-RU')}`;
}
html += `
<div class="user-item">
<div class="avatar">
${user.firstName?.[0] || ''}${user.lastName?.[0] || ''}
${isOnline ? '<div class="online-indicator"></div>' : ''}
</div>
<div>
<div><strong>${user.firstName} ${user.lastName}</strong></div>
<div class="status ${isOnline ? 'online' : ''}">${statusText}</div>
<div style="font-size: 12px; color: #999;">
ID: ${user.id} | Online: ${isOnline} | LastSeen: ${lastSeen || 'N/A'}
</div>
</div>
</div>
`;
});
resultsDiv.innerHTML = html;
} catch (error) {
resultsDiv.innerHTML = `<div class="error">Ошибка: ${error.message}</div>`;
console.error('API Error:', error);
}
}
function clearResults() {
document.getElementById('results').innerHTML = '';
}
</script>
</body>
</html>