Tg with Notifications, bags fixxed (Removed)
This commit is contained in:
@@ -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. **Оптимизация**: Дальнейшее улучшение производительности
|
|
||||||
@@ -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 в игре, решая основные проблемы с уведомлениями и отображением информации об отправителях. Система стала более информативной и удобной для пользователей.
|
|
||||||
@@ -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. **Статистика**: Время, проведенное онлайн, активность и т.д.
|
|
||||||
@@ -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 браузера
|
|
||||||
@@ -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 [32m++[m[31m--[m
|
|
||||||
db.js | 4 [32m+[m[31m---[m
|
|
||||||
db1.js | 2 [32m+[m[31m-[m
|
|
||||||
package-lock.json | 57 [32m+++++++++++++++++++++++++++++[m[31m--------------------------[m
|
|
||||||
server.js | 10 [32m++++[m[31m------[m
|
|
||||||
src/Game.js | 40 [32m+++++++++++++[m[31m-------------------------[m
|
|
||||||
6 files changed, 51 insertions(+), 66 deletions(-)
|
|
||||||
@@ -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>
|
|
||||||
@@ -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>
|
|
||||||
@@ -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>
|
|
||||||
Reference in New Issue
Block a user