Update files
This commit is contained in:
parent
ed85d8f6db
commit
8092d25c0c
|
|
@ -0,0 +1,177 @@
|
|||
# 🚀 Инструкция по обновлению сервера
|
||||
|
||||
## Вариант 1: PM2 (рекомендуется)
|
||||
|
||||
### 1. Подключитесь к серверу
|
||||
```bash
|
||||
ssh user@your-server
|
||||
cd /var/www/nakama # или путь к вашему проекту
|
||||
```
|
||||
|
||||
### 2. Обновите код
|
||||
```bash
|
||||
# Если используете Git
|
||||
git pull origin main
|
||||
|
||||
# Или загрузите файлы вручную через SFTP/SCP
|
||||
```
|
||||
|
||||
### 3. Установите зависимости (если нужно)
|
||||
```bash
|
||||
# Backend зависимости
|
||||
npm install --production
|
||||
|
||||
# Frontend зависимости и сборка
|
||||
cd frontend
|
||||
npm install
|
||||
npm run build
|
||||
cd ..
|
||||
```
|
||||
|
||||
### 4. Перезапустите backend
|
||||
```bash
|
||||
pm2 restart nakama-backend
|
||||
```
|
||||
|
||||
### 5. Проверьте статус
|
||||
```bash
|
||||
pm2 status
|
||||
pm2 logs nakama-backend --lines 50
|
||||
```
|
||||
|
||||
### Или используйте готовый скрипт:
|
||||
```bash
|
||||
chmod +x update-server.sh
|
||||
./update-server.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Вариант 2: Docker
|
||||
|
||||
### 1. Подключитесь к серверу
|
||||
```bash
|
||||
ssh user@your-server
|
||||
cd /path/to/nakama
|
||||
```
|
||||
|
||||
### 2. Обновите код
|
||||
```bash
|
||||
# Если используете Git
|
||||
git pull origin main
|
||||
|
||||
# Или загрузите файлы вручную
|
||||
```
|
||||
|
||||
### 3. Пересоберите и перезапустите контейнеры
|
||||
```bash
|
||||
# Пересобрать только backend (если изменился только backend)
|
||||
docker-compose build backend
|
||||
docker-compose up -d backend
|
||||
|
||||
# Или пересобрать всё
|
||||
docker-compose build
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### 4. Проверьте статус
|
||||
```bash
|
||||
docker-compose ps
|
||||
docker-compose logs -f backend
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Быстрое обновление (только backend)
|
||||
|
||||
Если изменился только backend код:
|
||||
|
||||
### PM2:
|
||||
```bash
|
||||
cd /var/www/nakama
|
||||
git pull
|
||||
pm2 restart nakama-backend
|
||||
```
|
||||
|
||||
### Docker:
|
||||
```bash
|
||||
cd /path/to/nakama
|
||||
git pull
|
||||
docker-compose build backend
|
||||
docker-compose up -d backend
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Проверка после обновления
|
||||
|
||||
1. **Проверьте логи:**
|
||||
```bash
|
||||
# PM2
|
||||
pm2 logs nakama-backend --lines 50
|
||||
|
||||
# Docker
|
||||
docker-compose logs backend --tail 50
|
||||
```
|
||||
|
||||
2. **Проверьте здоровье сервера:**
|
||||
```bash
|
||||
curl http://localhost:3000/health
|
||||
```
|
||||
|
||||
3. **Проверьте работу приложения:**
|
||||
- Откройте приложение в браузере
|
||||
- Попробуйте авторизоваться
|
||||
- Проверьте, что ники и аватарки отображаются
|
||||
|
||||
---
|
||||
|
||||
## Что изменилось в этом обновлении
|
||||
|
||||
✅ **Отключено автообновление аватарок** - больше не будет автоматического обновления всех аватарок каждый день
|
||||
|
||||
✅ **Улучшено обновление данных при авторизации** - при каждом перезаходе пользователя система проверяет и подтягивает отсутствующие данные (username, firstName, lastName, photoUrl) из Telegram
|
||||
|
||||
✅ **Добавлены fallback значения** - если данные отсутствуют, отображаются значения по умолчанию вместо пустых полей
|
||||
|
||||
---
|
||||
|
||||
## Откат изменений (если что-то пошло не так)
|
||||
|
||||
### PM2:
|
||||
```bash
|
||||
cd /var/www/nakama
|
||||
git checkout HEAD~1 # или конкретный коммит
|
||||
pm2 restart nakama-backend
|
||||
```
|
||||
|
||||
### Docker:
|
||||
```bash
|
||||
cd /path/to/nakama
|
||||
git checkout HEAD~1
|
||||
docker-compose build backend
|
||||
docker-compose up -d backend
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Полезные команды
|
||||
|
||||
### PM2:
|
||||
```bash
|
||||
pm2 list # Список процессов
|
||||
pm2 restart nakama-backend # Перезапуск
|
||||
pm2 stop nakama-backend # Остановка
|
||||
pm2 logs nakama-backend # Логи
|
||||
pm2 monit # Мониторинг
|
||||
```
|
||||
|
||||
### Docker:
|
||||
```bash
|
||||
docker-compose ps # Статус контейнеров
|
||||
docker-compose logs -f # Логи всех сервисов
|
||||
docker-compose restart backend # Перезапуск backend
|
||||
docker-compose down # Остановка всех контейнеров
|
||||
docker-compose up -d # Запуск всех контейнеров
|
||||
```
|
||||
|
||||
|
|
@ -48,40 +48,54 @@ const ensureUserSettings = async (user) => {
|
|||
}
|
||||
};
|
||||
|
||||
// Нормализовать данные пользователя из Telegram (поддержка camelCase и snake_case)
|
||||
const normalizeTelegramUser = (telegramUser) => {
|
||||
return {
|
||||
id: telegramUser.id,
|
||||
username: telegramUser.username || telegramUser.userName,
|
||||
firstName: telegramUser.firstName || telegramUser.first_name || '',
|
||||
lastName: telegramUser.lastName || telegramUser.last_name || '',
|
||||
photoUrl: telegramUser.photoUrl || telegramUser.photo_url || null
|
||||
};
|
||||
};
|
||||
|
||||
// Подтянуть отсутствующие данные пользователя из Telegram
|
||||
const ensureUserData = async (user, telegramUser) => {
|
||||
if (!user || !telegramUser) return;
|
||||
|
||||
// Нормализовать данные (поддержка camelCase и snake_case)
|
||||
const normalized = normalizeTelegramUser(telegramUser);
|
||||
|
||||
let updated = false;
|
||||
|
||||
// Обновить username, если отсутствует или пустой
|
||||
if (!user.username || user.username.trim() === '') {
|
||||
if (telegramUser.username) {
|
||||
user.username = telegramUser.username;
|
||||
if (normalized.username) {
|
||||
user.username = normalized.username;
|
||||
updated = true;
|
||||
} else if (telegramUser.first_name) {
|
||||
user.username = telegramUser.first_name;
|
||||
} else if (normalized.firstName) {
|
||||
user.username = normalized.firstName;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Обновить firstName, если отсутствует
|
||||
if (!user.firstName && telegramUser.first_name) {
|
||||
user.firstName = telegramUser.first_name;
|
||||
if (!user.firstName && normalized.firstName) {
|
||||
user.firstName = normalized.firstName;
|
||||
updated = true;
|
||||
}
|
||||
|
||||
// Обновить lastName, если отсутствует
|
||||
if (user.lastName === undefined || user.lastName === null) {
|
||||
user.lastName = telegramUser.last_name || '';
|
||||
user.lastName = normalized.lastName;
|
||||
updated = true;
|
||||
}
|
||||
|
||||
// Обновить аватарку, если отсутствует
|
||||
if (!user.photoUrl) {
|
||||
// Сначала проверить photo_url из initData
|
||||
if (telegramUser.photo_url) {
|
||||
user.photoUrl = telegramUser.photo_url;
|
||||
// Сначала проверить photoUrl из initData
|
||||
if (normalized.photoUrl) {
|
||||
user.photoUrl = normalized.photoUrl;
|
||||
updated = true;
|
||||
} else {
|
||||
// Если нет в initData, попробовать получить через Bot API
|
||||
|
|
@ -145,37 +159,40 @@ const authenticate = async (req, res, next) => {
|
|||
return res.status(401).json({ error: 'Неверный ID пользователя' });
|
||||
}
|
||||
|
||||
let user = await User.findOne({ telegramId: telegramUser.id.toString() });
|
||||
// Нормализовать данные пользователя (библиотека возвращает camelCase, но может быть и snake_case)
|
||||
const normalizedUser = normalizeTelegramUser(telegramUser);
|
||||
|
||||
let user = await User.findOne({ telegramId: normalizedUser.id.toString() });
|
||||
|
||||
if (!user) {
|
||||
user = new User({
|
||||
telegramId: telegramUser.id.toString(),
|
||||
username: telegramUser.username || telegramUser.first_name || 'user',
|
||||
firstName: telegramUser.first_name || '',
|
||||
lastName: telegramUser.last_name || '',
|
||||
photoUrl: telegramUser.photo_url || null
|
||||
telegramId: normalizedUser.id.toString(),
|
||||
username: normalizedUser.username || normalizedUser.firstName || 'user',
|
||||
firstName: normalizedUser.firstName,
|
||||
lastName: normalizedUser.lastName,
|
||||
photoUrl: normalizedUser.photoUrl
|
||||
});
|
||||
await user.save();
|
||||
} else {
|
||||
// Обновлять только если есть новые данные, не перезаписывать существующие пустыми значениями
|
||||
if (telegramUser.username) {
|
||||
user.username = telegramUser.username;
|
||||
} else if (!user.username && telegramUser.first_name) {
|
||||
// Если username пустой, использовать first_name как fallback
|
||||
user.username = telegramUser.first_name;
|
||||
if (normalizedUser.username) {
|
||||
user.username = normalizedUser.username;
|
||||
} else if (!user.username && normalizedUser.firstName) {
|
||||
// Если username пустой, использовать firstName как fallback
|
||||
user.username = normalizedUser.firstName;
|
||||
}
|
||||
|
||||
if (telegramUser.first_name) {
|
||||
user.firstName = telegramUser.first_name;
|
||||
if (normalizedUser.firstName) {
|
||||
user.firstName = normalizedUser.firstName;
|
||||
}
|
||||
|
||||
if (telegramUser.last_name !== undefined) {
|
||||
user.lastName = telegramUser.last_name || '';
|
||||
if (normalizedUser.lastName !== undefined) {
|
||||
user.lastName = normalizedUser.lastName;
|
||||
}
|
||||
|
||||
// Обновлять аватарку только если есть новая
|
||||
if (telegramUser.photo_url) {
|
||||
user.photoUrl = telegramUser.photo_url;
|
||||
if (normalizedUser.photoUrl) {
|
||||
user.photoUrl = normalizedUser.photoUrl;
|
||||
}
|
||||
|
||||
await user.save();
|
||||
|
|
@ -185,11 +202,13 @@ const authenticate = async (req, res, next) => {
|
|||
return res.status(403).json({ error: 'Пользователь заблокирован' });
|
||||
}
|
||||
|
||||
// Подтянуть отсутствующие данные из Telegram (используем нормализованные данные)
|
||||
await ensureUserData(user, normalizedUser);
|
||||
await ensureUserSettings(user);
|
||||
await touchUserActivity(user);
|
||||
|
||||
req.user = user;
|
||||
req.telegramUser = telegramUser;
|
||||
req.telegramUser = normalizedUser;
|
||||
next();
|
||||
} catch (error) {
|
||||
console.error('❌ Ошибка авторизации:', error);
|
||||
|
|
@ -254,37 +273,40 @@ const authenticateModeration = async (req, res, next) => {
|
|||
return res.status(401).json({ error: 'Неверный ID пользователя' });
|
||||
}
|
||||
|
||||
let user = await User.findOne({ telegramId: telegramUser.id.toString() });
|
||||
// Нормализовать данные пользователя (библиотека возвращает camelCase, но может быть и snake_case)
|
||||
const normalizedUser = normalizeTelegramUser(telegramUser);
|
||||
|
||||
let user = await User.findOne({ telegramId: normalizedUser.id.toString() });
|
||||
|
||||
if (!user) {
|
||||
user = new User({
|
||||
telegramId: telegramUser.id.toString(),
|
||||
username: telegramUser.username || telegramUser.first_name || 'user',
|
||||
firstName: telegramUser.first_name || '',
|
||||
lastName: telegramUser.last_name || '',
|
||||
photoUrl: telegramUser.photo_url || null
|
||||
telegramId: normalizedUser.id.toString(),
|
||||
username: normalizedUser.username || normalizedUser.firstName || 'user',
|
||||
firstName: normalizedUser.firstName,
|
||||
lastName: normalizedUser.lastName,
|
||||
photoUrl: normalizedUser.photoUrl
|
||||
});
|
||||
await user.save();
|
||||
} else {
|
||||
// Обновлять только если есть новые данные, не перезаписывать существующие пустыми значениями
|
||||
if (telegramUser.username) {
|
||||
user.username = telegramUser.username;
|
||||
} else if (!user.username && telegramUser.first_name) {
|
||||
// Если username пустой, использовать first_name как fallback
|
||||
user.username = telegramUser.first_name;
|
||||
if (normalizedUser.username) {
|
||||
user.username = normalizedUser.username;
|
||||
} else if (!user.username && normalizedUser.firstName) {
|
||||
// Если username пустой, использовать firstName как fallback
|
||||
user.username = normalizedUser.firstName;
|
||||
}
|
||||
|
||||
if (telegramUser.first_name) {
|
||||
user.firstName = telegramUser.first_name;
|
||||
if (normalizedUser.firstName) {
|
||||
user.firstName = normalizedUser.firstName;
|
||||
}
|
||||
|
||||
if (telegramUser.last_name !== undefined) {
|
||||
user.lastName = telegramUser.last_name || '';
|
||||
if (normalizedUser.lastName !== undefined) {
|
||||
user.lastName = normalizedUser.lastName;
|
||||
}
|
||||
|
||||
// Обновлять аватарку только если есть новая
|
||||
if (telegramUser.photo_url) {
|
||||
user.photoUrl = telegramUser.photo_url;
|
||||
if (normalizedUser.photoUrl) {
|
||||
user.photoUrl = normalizedUser.photoUrl;
|
||||
}
|
||||
|
||||
await user.save();
|
||||
|
|
@ -294,13 +316,13 @@ const authenticateModeration = async (req, res, next) => {
|
|||
return res.status(403).json({ error: 'Пользователь заблокирован' });
|
||||
}
|
||||
|
||||
// Подтянуть отсутствующие данные из Telegram
|
||||
await ensureUserData(user, telegramUser);
|
||||
// Подтянуть отсутствующие данные из Telegram (используем нормализованные данные)
|
||||
await ensureUserData(user, normalizedUser);
|
||||
await ensureUserSettings(user);
|
||||
await touchUserActivity(user);
|
||||
|
||||
req.user = user;
|
||||
req.telegramUser = telegramUser;
|
||||
req.telegramUser = normalizedUser;
|
||||
next();
|
||||
} catch (error) {
|
||||
console.error('❌ Ошибка авторизации модерации:', error);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Скрипт для исправления ошибки ContainerConfig в Docker
|
||||
|
||||
echo "🔧 Исправление ошибки Docker ContainerConfig..."
|
||||
|
||||
# 1. Остановить и удалить проблемный контейнер
|
||||
echo "📦 Остановка и удаление старого контейнера..."
|
||||
docker-compose stop backend
|
||||
docker-compose rm -f backend
|
||||
|
||||
# 2. Удалить старый образ backend (опционально, если нужно полное пересоздание)
|
||||
echo "🗑️ Удаление старого образа backend..."
|
||||
docker rmi nakama-backend 2>/dev/null || echo "Образ не найден, пропускаем"
|
||||
|
||||
# 3. Очистить кэш Docker (опционально, если проблема сохраняется)
|
||||
# docker system prune -f
|
||||
|
||||
# 4. Пересобрать образ
|
||||
echo "🔨 Пересборка образа backend..."
|
||||
docker-compose build --no-cache backend
|
||||
|
||||
# 5. Запустить контейнер
|
||||
echo "🚀 Запуск контейнера..."
|
||||
docker-compose up -d backend
|
||||
|
||||
# 6. Проверить статус
|
||||
echo "✅ Проверка статуса..."
|
||||
docker-compose ps backend
|
||||
docker-compose logs backend --tail 20
|
||||
|
||||
echo ""
|
||||
echo "✅ Готово! Если проблема сохраняется, попробуйте:"
|
||||
echo " docker-compose down"
|
||||
echo " docker-compose build --no-cache"
|
||||
echo " docker-compose up -d"
|
||||
|
||||
Loading…
Reference in New Issue