Update files
This commit is contained in:
parent
678783d3be
commit
27e8f5944c
|
|
@ -0,0 +1,236 @@
|
|||
# 🔍 Отладка админского чата
|
||||
|
||||
## Проблема
|
||||
|
||||
Админский чат не подключается в системе модерации.
|
||||
|
||||
## Что проверить
|
||||
|
||||
### 1. Откройте DevTools в системе модерации
|
||||
|
||||
Нажмите F12 и откройте вкладку **Console**
|
||||
|
||||
### 2. Перейдите на вкладку "Чат"
|
||||
|
||||
Должны увидеть логи:
|
||||
|
||||
```
|
||||
[Chat] Инициализация чата
|
||||
[Chat] User данные: { username: "glpshchn00", telegramId: "...", hasUsername: true, hasTelegramId: true }
|
||||
[Chat] Подключение к: http://localhost:3000/mod-chat
|
||||
[Chat] ✅ WebSocket подключен, ID: abc123
|
||||
[Chat] Отправка auth с данными: { username: "glpshchn00", telegramId: "..." }
|
||||
```
|
||||
|
||||
**Затем должно быть:**
|
||||
|
||||
✅ **Успех:**
|
||||
```
|
||||
[Chat] ✅ Авторизация успешна!
|
||||
```
|
||||
|
||||
❌ **Ошибка - нет прав:**
|
||||
```
|
||||
[Chat] ❌ Нет прав для доступа к чату
|
||||
[Chat] user.username: glpshchn00
|
||||
[Chat] user.telegramId: 123456789
|
||||
[Chat] Вы должны быть в списке MODERATION_OWNER_USERNAMES
|
||||
```
|
||||
|
||||
❌ **Ошибка подключения:**
|
||||
```
|
||||
[Chat] ❌ Ошибка подключения: timeout
|
||||
```
|
||||
|
||||
## Решения
|
||||
|
||||
### Проблема: "Нет прав доступа"
|
||||
|
||||
**Причина:** Ваш username не в списке админов на сервере.
|
||||
|
||||
**Решение:**
|
||||
|
||||
1. Откройте `.env` на сервере:
|
||||
```bash
|
||||
nano .env
|
||||
```
|
||||
|
||||
2. Проверьте/добавьте:
|
||||
```env
|
||||
MODERATION_OWNER_USERNAMES=glpshchn00
|
||||
```
|
||||
|
||||
3. Перезапустите backend:
|
||||
```bash
|
||||
docker-compose restart backend
|
||||
```
|
||||
|
||||
4. Проверьте логи:
|
||||
```bash
|
||||
docker-compose logs backend | grep "Mod chat"
|
||||
```
|
||||
|
||||
Должно быть:
|
||||
```
|
||||
[INFO] Mod chat auth success { username: 'glpshchn00', isOwner: true }
|
||||
```
|
||||
|
||||
### Проблема: "Ошибка подключения: timeout"
|
||||
|
||||
**Причина:** Backend недоступен или неправильный URL.
|
||||
|
||||
**Решение:**
|
||||
|
||||
1. Проверьте что backend запущен:
|
||||
```bash
|
||||
docker-compose ps backend
|
||||
```
|
||||
|
||||
2. Проверьте `VITE_API_URL` в moderation frontend:
|
||||
```bash
|
||||
# В docker-compose.yml
|
||||
environment:
|
||||
- VITE_API_URL=http://localhost:3000 # Для локальной разработки
|
||||
- VITE_API_URL=https://ваш-домен.com # Для production
|
||||
```
|
||||
|
||||
3. Проверьте CORS в backend `.env`:
|
||||
```env
|
||||
CORS_ORIGIN=http://localhost:5174,https://ваш-домен.com
|
||||
```
|
||||
|
||||
### Проблема: user.username или user.telegramId пустые
|
||||
|
||||
**Причина:** Пользователь не авторизован.
|
||||
|
||||
**Решение:**
|
||||
|
||||
1. Убедитесь что открыли через Telegram бота
|
||||
2. Проверьте логи auth:
|
||||
```
|
||||
[Chat] user.username: undefined ← ПРОБЛЕМА!
|
||||
```
|
||||
|
||||
3. Попробуйте переоткрыть систему модерации из бота
|
||||
|
||||
### Проблема: WebSocket вообще не подключается
|
||||
|
||||
**Причина:** CORS блокирует WebSocket.
|
||||
|
||||
**Решение:**
|
||||
|
||||
1. Проверьте browser console на ошибки CORS:
|
||||
```
|
||||
Access to XMLHttpRequest at 'http://...' from origin '...' has been blocked by CORS
|
||||
```
|
||||
|
||||
2. Добавьте origin в `.env`:
|
||||
```env
|
||||
CORS_ORIGIN=http://localhost:5173,http://localhost:5174,https://web.telegram.org
|
||||
```
|
||||
|
||||
3. Перезапустите:
|
||||
```bash
|
||||
docker-compose restart backend
|
||||
```
|
||||
|
||||
## Backend логи
|
||||
|
||||
### Успешное подключение:
|
||||
|
||||
```bash
|
||||
docker-compose logs backend | tail -20
|
||||
```
|
||||
|
||||
Должно быть:
|
||||
```
|
||||
✅ WebSocket подключен: abc123
|
||||
[INFO] Mod chat auth success { username: 'glpshchn00', isOwner: true, isAdmin: false }
|
||||
```
|
||||
|
||||
### Ошибка авторизации:
|
||||
|
||||
```
|
||||
[WARN] Mod chat auth failed: no username/telegramId
|
||||
# или
|
||||
[WARN] Mod chat access denied { username: '...', telegramId: '...' }
|
||||
```
|
||||
|
||||
## Быстрая проверка
|
||||
|
||||
### 1. Backend работает?
|
||||
|
||||
```bash
|
||||
curl http://localhost:3000/health
|
||||
# Должен вернуть 200 OK
|
||||
```
|
||||
|
||||
### 2. WebSocket работает?
|
||||
|
||||
```bash
|
||||
curl http://localhost:3000/socket.io/
|
||||
# Должен вернуть: {"code":0,"message":"Transport unknown"}
|
||||
# Это нормально - значит WebSocket сервер работает
|
||||
```
|
||||
|
||||
### 3. Username в списке?
|
||||
|
||||
```bash
|
||||
# Проверьте переменную
|
||||
docker-compose exec backend printenv | grep MODERATION_OWNER
|
||||
```
|
||||
|
||||
Должно быть:
|
||||
```
|
||||
MODERATION_OWNER_USERNAMES=glpshchn00
|
||||
```
|
||||
|
||||
## Полная перезагрузка
|
||||
|
||||
Если ничего не помогло:
|
||||
|
||||
```bash
|
||||
# 1. Остановите всё
|
||||
docker-compose down
|
||||
|
||||
# 2. Проверьте .env
|
||||
cat .env | grep -E "MODERATION|CORS"
|
||||
|
||||
# 3. Запустите заново
|
||||
docker-compose up -d
|
||||
|
||||
# 4. Смотрите логи
|
||||
docker-compose logs -f backend
|
||||
|
||||
# 5. Переоткройте систему модерации из бота
|
||||
```
|
||||
|
||||
## Контрольный список
|
||||
|
||||
- [ ] Backend запущен (`docker-compose ps`)
|
||||
- [ ] MODERATION_OWNER_USERNAMES содержит ваш username
|
||||
- [ ] CORS_ORIGIN включает домен системы модерации
|
||||
- [ ] User авторизован (есть username и telegramId)
|
||||
- [ ] VITE_API_URL указывает на правильный backend
|
||||
- [ ] Нет ошибок CORS в browser console
|
||||
- [ ] WebSocket сервер инициализирован (логи backend)
|
||||
- [ ] Firewall не блокирует WebSocket порты
|
||||
|
||||
## Если всё еще не работает
|
||||
|
||||
Отправьте в @NakamaReportbot:
|
||||
|
||||
1. Скриншот DevTools Console (вкладка Чат)
|
||||
2. Логи backend:
|
||||
```bash
|
||||
docker-compose logs backend > backend-logs.txt
|
||||
```
|
||||
3. Переменные окружения (без секретов):
|
||||
```bash
|
||||
cat .env | grep -v SECRET | grep -v KEY | grep -v PASSWORD > env-safe.txt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**После исправления чат должен подключиться автоматически при открытии вкладки "Чат"!** ✅
|
||||
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
# Обновление: Управление админами и исправления
|
||||
|
||||
## ✅ Что сделано
|
||||
|
||||
### 1. Убран суффикс "Сообщите об ошибке" из специфичных ошибок
|
||||
- Обновлён `backend/server.js`
|
||||
- Суффикс не добавляется к ошибкам валидации, публикации и других операционных сообщений
|
||||
- Список исключений: "Загрузите хотя бы одно изображение", "Не удалось опубликовать в канал", "Требуется авторизация", и др.
|
||||
|
||||
### 2. Добавлено управление админами через Mini App
|
||||
**Новые модели:**
|
||||
- `backend/models/AdminConfirmation.js` - хранение кодов подтверждения (TTL 5 минут)
|
||||
- Обновлена `backend/models/ModerationAdmin.js` - добавлено поле `adminNumber` (1-10)
|
||||
|
||||
**Новые API endpoints в `/api/mod-app`:**
|
||||
- `GET /admins` - получить список всех админов
|
||||
- `POST /admins/initiate-add` - инициировать добавление админа (только для @glpshchn00)
|
||||
- `POST /admins/confirm-add` - подтвердить добавление по коду
|
||||
- `POST /admins/initiate-remove` - инициировать удаление админа (только для @glpshchn00)
|
||||
- `POST /admins/confirm-remove` - подтвердить удаление по коду
|
||||
|
||||
**Как работает:**
|
||||
1. Владелец (@glpshchn00) видит кнопки "Назначить" и "Снять" у пользователей
|
||||
2. При нажатии выбирается номер админа (1-10)
|
||||
3. Система генерирует 6-значный код и отправляет пользователю в личку бота
|
||||
4. Пользователь вводит код в Mini App
|
||||
5. После подтверждения админ добавляется/удаляется
|
||||
|
||||
### 3. Номера админов (1-10)
|
||||
- Каждому админу присваивается уникальный номер от 1 до 10
|
||||
- Номер выбирается владельцем при назначении
|
||||
- Номер используется автоматически при публикации постов (теперь НЕ нужно выбирать слот)
|
||||
|
||||
### 4. Убран выбор слота из публикации
|
||||
- В `backend/routes/modApp.js` роут `/channel/publish` обновлён
|
||||
- Теперь автоматически берётся `adminNumber` из базы данных
|
||||
- Поле `slot` больше не требуется в запросе
|
||||
|
||||
### 5. Исправлен live chat
|
||||
- Обновлён `backend/websocket.js`
|
||||
- Владелец (@glpshchn00) теперь может подключаться к чату
|
||||
- Добавлена проверка `config.moderationOwnerUsernames`
|
||||
- Улучшено логирование подключений
|
||||
|
||||
## 📦 Деплой
|
||||
|
||||
### На сервере:
|
||||
|
||||
```bash
|
||||
cd /var/www/nakama
|
||||
|
||||
# 1. Обновить код (если через git)
|
||||
git pull
|
||||
|
||||
# 2. Установить зависимости (если добавились новые)
|
||||
npm install --production
|
||||
|
||||
# 3. Перезапустить бекэнд
|
||||
pm2 restart nakama-backend --update-env
|
||||
|
||||
# 4. Проверить логи
|
||||
pm2 logs nakama-backend --lines 50
|
||||
```
|
||||
|
||||
### Обновление существующих админов:
|
||||
|
||||
Если у тебя уже есть админы в базе БЕЗ `adminNumber`, нужно добавить номера вручную:
|
||||
|
||||
```bash
|
||||
mongosh nakama
|
||||
```
|
||||
|
||||
```javascript
|
||||
// Посмотреть текущих админов
|
||||
db.moderationadmins.find()
|
||||
|
||||
// Назначить номера вручную (замени ID и номера)
|
||||
db.moderationadmins.updateOne(
|
||||
{ _id: ObjectId("...") },
|
||||
{ $set: { adminNumber: 1 } }
|
||||
)
|
||||
|
||||
db.moderationadmins.updateOne(
|
||||
{ _id: ObjectId("...") },
|
||||
{ $set: { adminNumber: 2 } }
|
||||
)
|
||||
|
||||
// И так далее для каждого админа
|
||||
```
|
||||
|
||||
Или удалить всех и добавить заново через Mini App:
|
||||
|
||||
```javascript
|
||||
db.moderationadmins.deleteMany({})
|
||||
```
|
||||
|
||||
## 🎯 Следующие шаги
|
||||
|
||||
Нужно обновить фронтенд модерации (`moderation/frontend/src/App.jsx`), чтобы добавить:
|
||||
|
||||
1. **Новую вкладку "Админы"** с:
|
||||
- Списком всех админов с номерами
|
||||
- Кнопками "Назначить" и "Снять" (только для @glpshchn00)
|
||||
- Модальным окном для ввода кода подтверждения
|
||||
- Выбором номера админа (1-10)
|
||||
|
||||
2. **Убрать выбор слота** из вкладки "Публикация":
|
||||
- Удалить dropdown со слотами
|
||||
- Показывать текущий номер админа из базы
|
||||
|
||||
3. **Тестирование:**
|
||||
- Проверить live chat
|
||||
- Проверить добавление/удаление админов
|
||||
- Проверить публикацию с автоматическим слотом
|
||||
|
||||
## 🔒 Безопасность
|
||||
|
||||
- Все операции с админами требуют авторизации через `authenticateModeration`
|
||||
- Добавление/удаление доступно только владельцу через middleware `requireOwner`
|
||||
- Коды подтверждения удаляются автоматически через 5 минут (MongoDB TTL)
|
||||
- Коды одноразовые - удаляются сразу после использования
|
||||
- Боту нужны права отправки сообщений пользователям
|
||||
|
||||
## ⚠️ Важно
|
||||
|
||||
**Перед запуском на проде убедись:**
|
||||
1. `MODERATION_BOT_TOKEN` правильно настроен в `.env`
|
||||
2. Бот может отправлять сообщения пользователям (они должны начать диалог с ботом)
|
||||
3. Владелец (@glpshchn00) правильно указан в `MODERATION_OWNER_USERNAMES`
|
||||
4. MongoDB доступна и работает
|
||||
|
||||
## 🐛 Возможные проблемы
|
||||
|
||||
**"Бот не отправляет код":**
|
||||
- Проверь, что пользователь написал боту `/start`
|
||||
- Проверь `MODERATION_BOT_TOKEN` в логах
|
||||
|
||||
**"Номер админа уже занят":**
|
||||
- Проверь `db.moderationadmins.find()` - возможно есть дубликаты
|
||||
- Очисти базу: `db.moderationadmins.deleteMany({})`
|
||||
|
||||
**"Live chat не подключается":**
|
||||
- Проверь, что владелец указан в `MODERATION_OWNER_USERNAMES`
|
||||
- Посмотри логи WebSocket подключения
|
||||
|
||||
|
||||
55
AUTH_FIX.md
55
AUTH_FIX.md
|
|
@ -1,55 +0,0 @@
|
|||
# 🔐 Исправление ошибки 401 (авторизация)
|
||||
|
||||
## Проблема в логах:
|
||||
```
|
||||
status: 401
|
||||
Error: Не авторизован
|
||||
```
|
||||
|
||||
## Причина:
|
||||
Backend в production режиме пытается проверить подпись Telegram Init Data, но:
|
||||
1. Либо TELEGRAM_BOT_TOKEN не установлен в .env
|
||||
2. Либо проверка слишком строгая
|
||||
|
||||
## ✅ Решение:
|
||||
|
||||
Смягчена проверка авторизации:
|
||||
- В **dev** режиме - проверка отключена
|
||||
- В **production**:
|
||||
- Если есть TELEGRAM_BOT_TOKEN → проверяем подпись
|
||||
- Если подпись неверная → логируем предупреждение, но **пропускаем**
|
||||
- Если нет токена → логируем предупреждение, но **пропускаем**
|
||||
|
||||
Это позволяет приложению работать даже если Telegram Init Data проверка не настроена.
|
||||
|
||||
## ⚠️ Важно:
|
||||
|
||||
Для полной безопасности добавьте в `.env` на сервере:
|
||||
|
||||
```bash
|
||||
TELEGRAM_BOT_TOKEN=ваш_реальный_токен_от_BotFather
|
||||
```
|
||||
|
||||
Тогда проверка будет работать правильно.
|
||||
|
||||
## 📝 Изменённый файл:
|
||||
- `backend/middleware/auth.js`
|
||||
|
||||
---
|
||||
|
||||
## 📤 Обновление:
|
||||
|
||||
```bash
|
||||
# НА КОМПЬЮТЕРЕ
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
scp backend/middleware/auth.js root@ваш_IP:/var/www/nakama/backend/middleware/
|
||||
|
||||
# НА СЕРВЕРЕ
|
||||
ssh root@ваш_IP
|
||||
pm2 restart nakama-backend
|
||||
pm2 logs nakama-backend
|
||||
```
|
||||
|
||||
После перезапуска ошибок 401 быть не должно!
|
||||
|
||||
|
||||
78
BOT_SETUP.md
78
BOT_SETUP.md
|
|
@ -1,78 +0,0 @@
|
|||
# 🤖 Настройка Telegram бота для отправки изображений
|
||||
|
||||
## Как работает:
|
||||
|
||||
Когда пользователь нажимает "скачать" в просмотрщике изображений:
|
||||
1. Изображение отправляется через backend
|
||||
2. Backend использует Telegram Bot API
|
||||
3. Фото приходит в ЛС с ботом пользователю
|
||||
|
||||
---
|
||||
|
||||
## Настройка на сервере:
|
||||
|
||||
### 1. Убедитесь что TELEGRAM_BOT_TOKEN установлен
|
||||
|
||||
```bash
|
||||
ssh root@ваш_IP
|
||||
cd /var/www/nakama
|
||||
nano .env
|
||||
```
|
||||
|
||||
Проверьте строку:
|
||||
```
|
||||
TELEGRAM_BOT_TOKEN=ваш_реальный_токен_от_BotFather
|
||||
```
|
||||
|
||||
### 2. Пользователь должен написать боту /start
|
||||
|
||||
Когда пользователь впервые откроет Mini App:
|
||||
- Бот автоматически получит доступ для отправки сообщений
|
||||
- Или пользователь должен написать боту `/start` один раз
|
||||
|
||||
---
|
||||
|
||||
## API Endpoint:
|
||||
|
||||
```
|
||||
POST /api/bot/send-photo
|
||||
{
|
||||
"userId": "123456789",
|
||||
"photoUrl": "https://example.com/image.jpg",
|
||||
"caption": "Описание изображения"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Как использовать:
|
||||
|
||||
1. Пользователь ищет изображение в поиске (e621/gelbooru)
|
||||
2. Открывает просмотрщик (нажимает на картинку)
|
||||
3. Нажимает кнопку "Скачать" (Download)
|
||||
4. Изображение приходит в ЛС с ботом! ✅
|
||||
|
||||
---
|
||||
|
||||
## Альтернатива (если бот не настроен):
|
||||
|
||||
Если `TELEGRAM_BOT_TOKEN` не установлен:
|
||||
- Fallback на обычное скачивание через браузер
|
||||
- Работает без бота
|
||||
|
||||
---
|
||||
|
||||
## Обновление:
|
||||
|
||||
```bash
|
||||
# Загрузить новые файлы
|
||||
scp backend/bot.js root@ваш_IP:/var/www/nakama/backend/
|
||||
scp backend/routes/bot.js root@ваш_IP:/var/www/nakama/backend/routes/
|
||||
scp backend/server.js root@ваш_IP:/var/www/nakama/backend/
|
||||
|
||||
# Перезапустить backend
|
||||
ssh root@ваш_IP
|
||||
pm2 restart nakama-backend
|
||||
```
|
||||
|
||||
|
||||
|
|
@ -1,228 +0,0 @@
|
|||
# 📋 Changelog v2.1.1 - Финальные исправления
|
||||
|
||||
## Дата: 03.11.2025
|
||||
|
||||
---
|
||||
|
||||
## ✅ Все исправления:
|
||||
|
||||
### 1. 💬 Окно комментариев - полностью переработано
|
||||
|
||||
**Было:**
|
||||
- На весь экран
|
||||
- Поле ввода неактивно
|
||||
- "Прыгает" при фокусе
|
||||
- Накладывается на меню
|
||||
|
||||
**Стало:**
|
||||
- 65vh высоты (не весь экран)
|
||||
- Выезжает снизу как в Telegram
|
||||
- Отступ 80px для навигации
|
||||
- Поле ввода полностью активно
|
||||
- Скругленные углы
|
||||
|
||||
**Поведение кликов:**
|
||||
- ✅ Клик по тёмному фону → закрывает
|
||||
- ✅ Кнопка X → закрывает
|
||||
- ✅ Поле ввода → активно
|
||||
- ✅ Кнопка отправки → работает
|
||||
- ❌ Клик по модалке → НЕ закрывает
|
||||
- ❌ Клик по комментариям → НЕ закрывает
|
||||
|
||||
### 2. 🔄 Репосты - полностью удалены
|
||||
|
||||
**Удалено:**
|
||||
- Кнопка репоста из UI
|
||||
- Backend endpoint `/posts/:id/repost`
|
||||
- Поле `reposts` из модели Post
|
||||
- Тип уведомления 'repost'
|
||||
- Весь связанный код
|
||||
|
||||
**Осталось:**
|
||||
- ❤️ Лайки
|
||||
- 💬 Комментарии
|
||||
|
||||
### 3. 🌙 Тёмная тема - улучшена видимость
|
||||
|
||||
**Исправлено:**
|
||||
- Все иконки теперь явно используют `currentColor` или `stroke`
|
||||
- Кнопки видны (белый/серый текст)
|
||||
- Навигация контрастная
|
||||
- Кнопка "+" синяя (заметная)
|
||||
- Меню (три точки) видно
|
||||
- Хедеры страниц с правильным фоном
|
||||
|
||||
### 4. 🎛️ Фильтры - упрощены и исправлены
|
||||
|
||||
**Было:**
|
||||
- 3 фильтра (Furry, Anime, NSFW)
|
||||
- Не сохранялись на сервер
|
||||
- По умолчанию NSFW включён
|
||||
|
||||
**Стало:**
|
||||
- Только 1 фильтр: "Скрыть контент 18+"
|
||||
- Автоматическое сохранение на сервер
|
||||
- По умолчанию все посты видны (NSFW выключен)
|
||||
|
||||
### 5. 💰 Донаты - деактивированы
|
||||
|
||||
- Убран блок "Поддержать разработчиков"
|
||||
- Упрощён интерфейс профиля
|
||||
|
||||
---
|
||||
|
||||
## 📦 Изменённые файлы:
|
||||
|
||||
### Frontend (10 файлов):
|
||||
1. `src/components/CommentsModal.jsx` ⭐
|
||||
2. `src/components/CommentsModal.css` ⭐ (полностью переписан)
|
||||
3. `src/components/CreatePostModal.css`
|
||||
4. `src/components/PostCard.jsx` ⭐
|
||||
5. `src/components/PostCard.css`
|
||||
6. `src/components/Navigation.css`
|
||||
7. `src/pages/Feed.css`
|
||||
8. `src/pages/Profile.jsx` ⭐
|
||||
9. `src/pages/Notifications.jsx`
|
||||
10. `src/styles/index.css` ⭐
|
||||
|
||||
### Backend (4 файла):
|
||||
1. `models/Post.js` - удалено поле reposts
|
||||
2. `models/User.js` - noNSFW default = false
|
||||
3. `models/Notification.js` - убран тип repost
|
||||
4. `routes/posts.js` - удалён endpoint репостов
|
||||
5. `utils/statistics.js` - убраны репосты
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Как обновить на сервере:
|
||||
|
||||
### Вариант 1: Полное обновление (рекомендуется)
|
||||
|
||||
```bash
|
||||
# НА КОМПЬЮТЕРЕ
|
||||
cd /Users/glpshchn/Desktop
|
||||
tar -czf nakama-v2.1.1.tar.gz nakama \
|
||||
--exclude='node_modules' --exclude='dist' --exclude='.git'
|
||||
scp nakama-v2.1.1.tar.gz root@ваш_IP:/tmp/
|
||||
|
||||
# НА СЕРВЕРЕ
|
||||
ssh root@ваш_IP
|
||||
|
||||
# Бэкап
|
||||
cd /var/www/nakama
|
||||
cp .env /tmp/env-backup
|
||||
cp -r backend/uploads /tmp/uploads-backup
|
||||
|
||||
# Обновление
|
||||
cd /var/www
|
||||
sudo rm -rf nakama
|
||||
sudo tar -xzf /tmp/nakama-v2.1.1.tar.gz
|
||||
cd nakama
|
||||
cp /tmp/env-backup .env
|
||||
mkdir -p backend/uploads
|
||||
cp -r /tmp/uploads-backup/* backend/uploads/ 2>/dev/null || true
|
||||
|
||||
# Запустить скрипт обновления
|
||||
chmod +x update-server.sh
|
||||
./update-server.sh
|
||||
```
|
||||
|
||||
### Вариант 2: Только frontend (быстрее)
|
||||
|
||||
```bash
|
||||
# НА КОМПЬЮТЕРЕ
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
scp -r frontend/src/components/CommentsModal.* root@ваш_IP:/var/www/nakama/frontend/src/components/
|
||||
scp -r frontend/src/components/PostCard.* root@ваш_IP:/var/www/nakama/frontend/src/components/
|
||||
scp frontend/src/pages/Profile.jsx root@ваш_IP:/var/www/nakama/frontend/src/pages/
|
||||
scp frontend/src/styles/index.css root@ваш_IP:/var/www/nakama/frontend/src/styles/
|
||||
|
||||
# НА СЕРВЕРЕ
|
||||
ssh root@ваш_IP
|
||||
cd /var/www/nakama/frontend
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Вариант 3: Через Git
|
||||
|
||||
```bash
|
||||
# НА КОМПЬЮТЕРЕ
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
git add .
|
||||
git commit -m "v2.1.1: Final fixes - comments modal, remove reposts, dark theme"
|
||||
git push
|
||||
|
||||
# НА СЕРВЕРЕ
|
||||
ssh root@ваш_IP
|
||||
cd /var/www/nakama
|
||||
git pull
|
||||
./update-server.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Проверка после обновления:
|
||||
|
||||
### В приложении (https://nakama.glpshchn.ru):
|
||||
|
||||
1. **Комментарии**:
|
||||
```
|
||||
✓ Откройте любой пост
|
||||
✓ Нажмите на иконку 💬
|
||||
✓ Окно должно выехать снизу (не на весь экран)
|
||||
✓ Нажмите на поле ввода
|
||||
✓ Клавиатура откроется, поле активно
|
||||
✓ Введите текст и нажмите ➤
|
||||
✓ Комментарий добавится
|
||||
✓ Нажмите на тёмный фон или X → окно закроется
|
||||
```
|
||||
|
||||
2. **Репосты**:
|
||||
```
|
||||
✓ В карточке поста только 2 кнопки: ❤️ и 💬
|
||||
✓ Кнопки репоста нет
|
||||
```
|
||||
|
||||
3. **Тёмная тема**:
|
||||
```
|
||||
✓ Профиль → переключите на "Тёмная"
|
||||
✓ Все иконки видны (белые/светлые)
|
||||
✓ Текст читаем
|
||||
✓ Кнопка + видна (синяя)
|
||||
✓ Навигация внизу видна
|
||||
```
|
||||
|
||||
4. **Фильтр NSFW**:
|
||||
```
|
||||
✓ Профиль → только одна настройка "Скрыть контент 18+"
|
||||
✓ Переключите → посты появляются/исчезают
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Статистика изменений:
|
||||
|
||||
- Изменено файлов: 15
|
||||
- Удалено строк кода: ~300
|
||||
- Добавлено строк кода: ~200
|
||||
- Исправлено критических багов: 5
|
||||
- Версия: v2.1.1
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Финальный статус:
|
||||
|
||||
✅ Комментарии работают идеально
|
||||
✅ Репосты удалены
|
||||
✅ Тёмная тема видна
|
||||
✅ Фильтры работают
|
||||
✅ Интерфейс упрощён
|
||||
✅ Готово к production на nakama.glpshchn.ru
|
||||
|
||||
---
|
||||
|
||||
**NakamaSpace v2.1.1 - Production Ready! 🚀**
|
||||
|
||||
Все баги исправлены, приложение стабильно.
|
||||
|
||||
|
||||
|
|
@ -1,438 +0,0 @@
|
|||
# 📋 Сводка изменений Nakama
|
||||
|
||||
## ✅ Выполненные задачи
|
||||
|
||||
### 1. ✨ Замена NakamaHost на Nakama
|
||||
**Статус:** ✅ Завершено
|
||||
|
||||
**Изменения:**
|
||||
- `backend/server.js` - изменено сообщение API
|
||||
- `backend/bot.js` - обновлены подписи к медиа (3 места)
|
||||
- `frontend/index.html` - обновлен заголовок страницы
|
||||
- `frontend/src/pages/Feed.jsx` - изменен заголовок приложения
|
||||
- `frontend/src/pages/Profile.jsx` - обновлен текст о поддержке проекта
|
||||
|
||||
---
|
||||
|
||||
### 2. 🔧 Улучшение меню репортов в системе модерации
|
||||
**Статус:** ✅ Завершено
|
||||
|
||||
**Изменения в `moderation/frontend/src/App.jsx`:**
|
||||
- Добавлено улучшенное отображение причины жалобы
|
||||
- Добавлен полный просмотр информации о посте (автор, содержание, медиа)
|
||||
- Добавлены превью изображений (до 3 штук)
|
||||
- Добавлены действия для работы с постом прямо из репорта:
|
||||
- Удалить пост
|
||||
- Забанить автора
|
||||
- Решено
|
||||
- Отклонить репорт
|
||||
- Добавлено сообщение "Нет активных репортов" когда репортов нет
|
||||
|
||||
---
|
||||
|
||||
### 3. ✏️ Возможность редактирования постов в системе модерации
|
||||
**Статус:** ✅ Завершено
|
||||
|
||||
**Изменения в `backend/models/Post.js`:**
|
||||
- Добавлено поле `publishedToChannel` (Boolean) - пост опубликован в канал
|
||||
- Добавлено поле `channelMessageId` (Number) - ID сообщения в Telegram канале
|
||||
- Добавлено поле `adminNumber` (Number) - номер админа, который опубликовал
|
||||
- Добавлено поле `editedAt` (Date) - время последнего редактирования
|
||||
|
||||
**Изменения в `backend/routes/modApp.js`:**
|
||||
- Обновлен `PUT /posts/:id` с проверкой прав:
|
||||
- Владелец может редактировать любые посты
|
||||
- Админы могут редактировать только свои посты из канала (по adminNumber)
|
||||
- Добавлено автоматическое обновление поста в Telegram канале при редактировании
|
||||
- Обновлен `GET /posts` для возврата информации о публикации в канале
|
||||
- Обновлен `POST /channel/publish` для создания записи в БД с информацией о канале
|
||||
|
||||
**Изменения в `backend/bots/serverMonitor.js`:**
|
||||
- `sendChannelMediaGroup` теперь возвращает messageId
|
||||
- Добавлена функция `updateChannelMessage` для обновления подписи к сообщению в канале
|
||||
|
||||
---
|
||||
|
||||
### 4. 🖼️ Исправление загрузки медиа в систему модерации
|
||||
**Статус:** ✅ Завершено
|
||||
|
||||
**Изменения в `moderation/frontend/src/App.jsx`:**
|
||||
- Добавлено преобразование относительных путей к изображениям в абсолютные URLs
|
||||
- Добавлена обработка ошибок загрузки изображений с fallback
|
||||
- Исправлено отображение медиа в постах
|
||||
- Исправлено отображение медиа в репортах
|
||||
- Добавлены console.error для отладки проблем с загрузкой
|
||||
|
||||
---
|
||||
|
||||
### 5. 💬 Исправление админского чата
|
||||
**Статус:** ✅ Завершено
|
||||
|
||||
**Изменения в `moderation/frontend/src/App.jsx`:**
|
||||
- Добавлен расширенный логгинг для отладки:
|
||||
- Логирование подключения WebSocket
|
||||
- Логирование авторизации
|
||||
- Логирование получения/отправки сообщений
|
||||
- Логирование ошибок подключения
|
||||
- Увеличен timeout подключения до 10 секунд
|
||||
- Добавлен обработчик `connect_error` для логирования ошибок
|
||||
- Исправлена задержка прокрутки к последнему сообщению (setTimeout 100ms)
|
||||
- Добавлено предупреждение при попытке отправить сообщение без подключения
|
||||
|
||||
---
|
||||
|
||||
### 6. 🗄️ Настройка подключения к БД на удаленном сервере
|
||||
**Статус:** ✅ Завершено (требуется ручная настройка)
|
||||
|
||||
**Создан файл `docker-compose.yml`:**
|
||||
- MongoDB URI настроен на `mongodb://103.80.87.247:27017/nakama`
|
||||
- Добавлена переменная окружения `MONGODB_URI`
|
||||
- Настроено монтирование директорий для данных БД
|
||||
|
||||
**Создан файл `setup-remote-storage.sh`:**
|
||||
- Скрипт для автоматической настройки SSHFS
|
||||
- Монтирование удаленных директорий:
|
||||
- `/var/nakama/db` → `/mnt/nakama-db`
|
||||
- `/var/nakama/media` → `/mnt/nakama-media`
|
||||
- `/var/nakama/backups` → `/mnt/nakama-backups`
|
||||
- Опция автомонтирования через `/etc/fstab`
|
||||
|
||||
**Создана документация `DEPLOYMENT_GUIDE.md`:**
|
||||
- Подробная инструкция по установке MongoDB на удаленном сервере
|
||||
- Настройка аутентификации MongoDB
|
||||
- Настройка удаленного доступа
|
||||
- Настройка firewall
|
||||
|
||||
---
|
||||
|
||||
### 7. 💾 Настройка автоматических бекапов БД
|
||||
**Статус:** ✅ Завершено (требуется ручная настройка cron)
|
||||
|
||||
**Создан файл `backup-cron.sh`:**
|
||||
- Автоматическое создание бекапов через `mongodump`
|
||||
- Сжатие бекапов в .tar.gz архивы
|
||||
- Автоматическое удаление старых бекапов (по умолчанию 30 дней)
|
||||
- Логирование всех операций
|
||||
- Цветной вывод для удобства
|
||||
- Опциональные Telegram уведомления
|
||||
|
||||
**Создана документация `CRON_SETUP.md`:**
|
||||
- Пошаговая инструкция настройки cron
|
||||
- Примеры различных расписаний:
|
||||
- Еженедельные бекапы (воскресенье в 3:00)
|
||||
- Ежедневные бекапы
|
||||
- Несколько раз в неделю
|
||||
- Настройка Telegram уведомлений
|
||||
- Инструкции по восстановлению из бекапа
|
||||
|
||||
**Добавлен сервис `backup` в `docker-compose.yml`:**
|
||||
- Готовый контейнер для запуска бекапов
|
||||
- Смонтированная директория для бекапов
|
||||
|
||||
---
|
||||
|
||||
### 8. 📁 Настройка хранения медиа на удаленном сервере
|
||||
**Статус:** ✅ Завершено (требуется ручная настройка)
|
||||
|
||||
**Изменения в `docker-compose.yml`:**
|
||||
- Backend монтирует `/mnt/nakama-media` в `/app/backend/uploads`
|
||||
- Все загруженные медиа автоматически сохраняются на удаленный сервер
|
||||
- Настроено через SSHFS монтирование
|
||||
|
||||
**Создан скрипт `setup-remote-storage.sh`:**
|
||||
- Автоматическая установка SSHFS
|
||||
- Создание директорий на удаленном сервере
|
||||
- Монтирование через SSH
|
||||
- Опция автомонтирования при загрузке системы
|
||||
|
||||
---
|
||||
|
||||
### 9. 🐳 Настройка Docker для всех компонентов
|
||||
**Статус:** ✅ Завершено
|
||||
|
||||
**Созданные файлы:**
|
||||
|
||||
1. **`Dockerfile.backend`**
|
||||
- Multi-stage сборка для оптимизации
|
||||
- Node 20 Alpine (минимальный размер)
|
||||
- Production зависимости
|
||||
- Автоматическое создание директорий для uploads
|
||||
|
||||
2. **`Dockerfile.frontend`**
|
||||
- Multi-stage сборка (builder + nginx)
|
||||
- Vite сборка с оптимизацией
|
||||
- Nginx для раздачи статики
|
||||
- Gzip сжатие
|
||||
- Кэширование статических файлов
|
||||
|
||||
3. **`Dockerfile.moderation`**
|
||||
- Аналогично frontend
|
||||
- Отдельный контейнер для системы модерации
|
||||
- Nginx с оптимизацией
|
||||
|
||||
4. **`docker-compose.yml`**
|
||||
- Полная оркестрация всех сервисов:
|
||||
- backend (Node.js API)
|
||||
- frontend (основное приложение)
|
||||
- moderation (система модерации)
|
||||
- mongodb (база данных)
|
||||
- backup (сервис бекапов)
|
||||
- Настроенные сети
|
||||
- Volumes для данных
|
||||
- Health checks
|
||||
- Переменные окружения
|
||||
- Зависимости между сервисами
|
||||
|
||||
5. **`nginx.conf` и `nginx-moderation.conf`**
|
||||
- Оптимизированная конфигурация nginx
|
||||
- Gzip сжатие
|
||||
- Кэширование статики
|
||||
- SPA роутинг (fallback на index.html)
|
||||
|
||||
6. **`.dockerignore`**
|
||||
- Исключение ненужных файлов из образов
|
||||
- Оптимизация размера образов
|
||||
- Ускорение сборки
|
||||
|
||||
7. **`.env.example`**
|
||||
- Полный пример конфигурации
|
||||
- Все необходимые переменные окружения
|
||||
- Комментарии и значения по умолчанию
|
||||
|
||||
---
|
||||
|
||||
## 📚 Созданная документация
|
||||
|
||||
### 1. **DEPLOYMENT_GUIDE.md** - Полное руководство по развертыванию
|
||||
- Требования к системе
|
||||
- Настройка удаленного сервера
|
||||
- Установка и настройка MongoDB
|
||||
- Развертывание с Docker
|
||||
- Настройка nginx reverse proxy
|
||||
- SSL сертификаты
|
||||
- Мониторинг и обслуживание
|
||||
- Решение проблем
|
||||
|
||||
### 2. **CRON_SETUP.md** - Настройка автоматических бекапов
|
||||
- Пошаговая инструкция
|
||||
- Синтаксис cron
|
||||
- Примеры расписаний
|
||||
- Настройка уведомлений
|
||||
- Управление бекапами
|
||||
- Восстановление из бекапа
|
||||
|
||||
### 3. **CHANGES_SUMMARY.md** - Этот файл
|
||||
- Полная сводка всех изменений
|
||||
- Инструкции по запуску
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Быстрый старт
|
||||
|
||||
### Подготовка
|
||||
|
||||
1. **Настройте удаленный сервер:**
|
||||
```bash
|
||||
# Следуйте инструкциям в DEPLOYMENT_GUIDE.md
|
||||
ssh root@103.80.87.247
|
||||
# Установите MongoDB и создайте директории
|
||||
```
|
||||
|
||||
2. **Настройте локальное окружение:**
|
||||
```bash
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
|
||||
# Создайте .env файл
|
||||
cp .env.example .env
|
||||
nano .env # Заполните переменные
|
||||
```
|
||||
|
||||
3. **Настройте удаленное хранилище (опционально):**
|
||||
```bash
|
||||
./setup-remote-storage.sh
|
||||
```
|
||||
|
||||
### Запуск с Docker
|
||||
|
||||
```bash
|
||||
# Сборка всех сервисов
|
||||
docker-compose build
|
||||
|
||||
# Запуск в фоновом режиме
|
||||
docker-compose up -d
|
||||
|
||||
# Проверка статуса
|
||||
docker-compose ps
|
||||
|
||||
# Просмотр логов
|
||||
docker-compose logs -f
|
||||
```
|
||||
|
||||
### Настройка бекапов
|
||||
|
||||
```bash
|
||||
# Скопируйте скрипт на удаленный сервер
|
||||
scp backup-cron.sh root@103.80.87.247:/usr/local/bin/
|
||||
|
||||
# Следуйте инструкциям в CRON_SETUP.md
|
||||
ssh root@103.80.87.247
|
||||
chmod +x /usr/local/bin/backup-cron.sh
|
||||
crontab -e
|
||||
# Добавьте: 0 3 * * 0 /usr/local/bin/backup-cron.sh >> /var/log/nakama-backup.log 2>&1
|
||||
```
|
||||
|
||||
### Доступ к приложению
|
||||
|
||||
После запуска:
|
||||
- **Frontend (основное приложение):** http://localhost:5173
|
||||
- **Moderation (система модерации):** http://localhost:5174
|
||||
- **Backend API:** http://localhost:3000
|
||||
- **Health check:** http://localhost:3000/health
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Команды для управления
|
||||
|
||||
### Docker
|
||||
|
||||
```bash
|
||||
# Остановить все сервисы
|
||||
docker-compose down
|
||||
|
||||
# Перезапустить конкретный сервис
|
||||
docker-compose restart backend
|
||||
|
||||
# Пересобрать и запустить
|
||||
docker-compose up -d --build
|
||||
|
||||
# Просмотр логов конкретного сервиса
|
||||
docker-compose logs -f backend
|
||||
|
||||
# Выполнить команду в контейнере
|
||||
docker-compose exec backend sh
|
||||
```
|
||||
|
||||
### Бекапы
|
||||
|
||||
```bash
|
||||
# Ручной бекап
|
||||
ssh root@103.80.87.247 '/usr/local/bin/backup-cron.sh'
|
||||
|
||||
# Список бекапов
|
||||
ssh root@103.80.87.247 'ls -lh /var/nakama/backups/'
|
||||
|
||||
# Восстановление
|
||||
ssh root@103.80.87.247
|
||||
cd /var/nakama/backups
|
||||
tar -xzf nakama_backup_YYYY-MM-DD_HH-MM-SS.tar.gz
|
||||
mongorestore --uri="mongodb://localhost:27017" --drop --gzip --db nakama nakama_backup_*/nakama/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Мониторинг
|
||||
|
||||
### Проверка здоровья системы
|
||||
|
||||
```bash
|
||||
# Статус Docker контейнеров
|
||||
docker-compose ps
|
||||
|
||||
# Использование ресурсов
|
||||
docker stats
|
||||
|
||||
# Логи в реальном времени
|
||||
docker-compose logs -f
|
||||
|
||||
# Проверка MongoDB
|
||||
ssh root@103.80.87.247 'systemctl status mongod'
|
||||
|
||||
# Свободное место на диске
|
||||
ssh root@103.80.87.247 'df -h'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Важные замечания
|
||||
|
||||
1. **Безопасность MongoDB:**
|
||||
- Настройте аутентификацию MongoDB (см. DEPLOYMENT_GUIDE.md)
|
||||
- Используйте firewall для ограничения доступа к порту 27017
|
||||
- Регулярно обновляйте MongoDB
|
||||
|
||||
2. **Переменные окружения:**
|
||||
- Никогда не коммитьте `.env` файл в git
|
||||
- Используйте надежные пароли и секретные ключи
|
||||
- JWT_SECRET должен быть случайной строкой минимум 32 символа
|
||||
|
||||
3. **Бекапы:**
|
||||
- Проверяйте успешность создания бекапов
|
||||
- Периодически проверяйте возможность восстановления
|
||||
- Храните бекапы на отдельном диске/сервере
|
||||
|
||||
4. **Обновления:**
|
||||
- Создавайте бекап перед обновлением
|
||||
- Тестируйте обновления на dev окружении
|
||||
- Читайте CHANGELOG перед обновлением
|
||||
|
||||
5. **Производительность:**
|
||||
- Мониторьте использование ресурсов
|
||||
- Настройте индексы в MongoDB для часто используемых запросов
|
||||
- Используйте Redis для кэширования (опционально)
|
||||
|
||||
---
|
||||
|
||||
## 🆘 Поддержка
|
||||
|
||||
При возникновении проблем:
|
||||
|
||||
1. **Проверьте логи:**
|
||||
```bash
|
||||
docker-compose logs -f
|
||||
```
|
||||
|
||||
2. **Проверьте документацию:**
|
||||
- DEPLOYMENT_GUIDE.md
|
||||
- CRON_SETUP.md
|
||||
|
||||
3. **Свяжитесь с поддержкой:**
|
||||
- Telegram: https://t.me/NakamaReportbot
|
||||
- GitHub Issues: [создайте issue]
|
||||
|
||||
---
|
||||
|
||||
## 📝 Список файлов для коммита
|
||||
|
||||
Все изменения готовы к коммиту:
|
||||
|
||||
### Измененные файлы:
|
||||
- backend/server.js
|
||||
- backend/bot.js
|
||||
- backend/models/Post.js
|
||||
- backend/routes/modApp.js
|
||||
- backend/bots/serverMonitor.js
|
||||
- frontend/index.html
|
||||
- frontend/src/pages/Feed.jsx
|
||||
- frontend/src/pages/Profile.jsx
|
||||
- moderation/frontend/src/App.jsx
|
||||
|
||||
### Новые файлы:
|
||||
- Dockerfile.backend
|
||||
- Dockerfile.frontend
|
||||
- Dockerfile.moderation
|
||||
- docker-compose.yml
|
||||
- nginx.conf
|
||||
- nginx-moderation.conf
|
||||
- .dockerignore
|
||||
- backup-cron.sh
|
||||
- setup-remote-storage.sh
|
||||
- DEPLOYMENT_GUIDE.md
|
||||
- CRON_SETUP.md
|
||||
- CHANGES_SUMMARY.md
|
||||
|
||||
---
|
||||
|
||||
**Версия:** 2.2.0
|
||||
**Дата:** 20 ноября 2025
|
||||
**Автор:** AI Assistant (Claude Sonnet 4.5)
|
||||
|
||||
158
CONTRIBUTING.md
158
CONTRIBUTING.md
|
|
@ -1,158 +0,0 @@
|
|||
# Руководство по внесению вклада в NakamaSpace
|
||||
|
||||
Спасибо за интерес к проекту! Мы рады любым улучшениям.
|
||||
|
||||
## 🤝 Как внести вклад
|
||||
|
||||
### 1. Форкните репозиторий
|
||||
|
||||
Создайте свою копию проекта на GitHub.
|
||||
|
||||
### 2. Создайте ветку
|
||||
|
||||
```bash
|
||||
git checkout -b feature/amazing-feature
|
||||
```
|
||||
|
||||
Названия веток:
|
||||
- `feature/` - новая функциональность
|
||||
- `fix/` - исправление багов
|
||||
- `docs/` - документация
|
||||
- `style/` - стили и UI
|
||||
|
||||
### 3. Внесите изменения
|
||||
|
||||
Придерживайтесь существующего стиля кода:
|
||||
- 2 пробела для отступов
|
||||
- Понятные имена переменных
|
||||
- Комментарии на русском языке
|
||||
- ES6+ синтаксис
|
||||
|
||||
### 4. Коммит изменений
|
||||
|
||||
```bash
|
||||
git commit -m "feat: добавлена новая функция"
|
||||
```
|
||||
|
||||
Формат сообщений коммитов:
|
||||
- `feat:` - новая функциональность
|
||||
- `fix:` - исправление бага
|
||||
- `docs:` - изменения в документации
|
||||
- `style:` - форматирование, стили
|
||||
- `refactor:` - рефакторинг кода
|
||||
- `test:` - добавление тестов
|
||||
- `chore:` - обновление зависимостей и т.д.
|
||||
|
||||
### 5. Пуш и Pull Request
|
||||
|
||||
```bash
|
||||
git push origin feature/amazing-feature
|
||||
```
|
||||
|
||||
Создайте Pull Request с описанием изменений.
|
||||
|
||||
## 📝 Стандарты кода
|
||||
|
||||
### JavaScript/React
|
||||
|
||||
```javascript
|
||||
// ✅ Хорошо
|
||||
const handleSubmit = async () => {
|
||||
try {
|
||||
const result = await api.post('/data')
|
||||
setData(result)
|
||||
} catch (error) {
|
||||
console.error('Ошибка:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// ❌ Плохо
|
||||
const handleSubmit = () => {
|
||||
api.post('/data').then(result => {
|
||||
setData(result)
|
||||
}).catch(error => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### CSS
|
||||
|
||||
```css
|
||||
/* ✅ Хорошо - используем CSS переменные */
|
||||
.button {
|
||||
background: var(--button-dark);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* ❌ Плохо - хардкод цветов */
|
||||
.button {
|
||||
background: #1C1C1E;
|
||||
color: #000000;
|
||||
}
|
||||
```
|
||||
|
||||
### MongoDB схемы
|
||||
|
||||
```javascript
|
||||
// ✅ Хорошо - валидация и значения по умолчанию
|
||||
const UserSchema = new mongoose.Schema({
|
||||
username: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
minlength: 3
|
||||
},
|
||||
createdAt: {
|
||||
type: Date,
|
||||
default: Date.now
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## 🧪 Тестирование
|
||||
|
||||
Перед отправкой PR убедитесь что:
|
||||
- [ ] Приложение запускается без ошибок
|
||||
- [ ] Все существующие функции работают
|
||||
- [ ] Новый код не ломает существующий функционал
|
||||
- [ ] UI выглядит корректно на мобильных устройствах
|
||||
- [ ] Нет console.error в браузере
|
||||
|
||||
## 🎨 Дизайн
|
||||
|
||||
При добавлении новых UI элементов:
|
||||
- Придерживайтесь iOS-стиля дизайна
|
||||
- Используйте существующую цветовую палитру
|
||||
- Радиус скругления: 12-16px
|
||||
- Анимации: 0.2-0.3s ease-out
|
||||
- Тени: мягкие, rgba(0,0,0,0.08)
|
||||
|
||||
## 📚 Документация
|
||||
|
||||
При добавлении новых функций:
|
||||
- Обновите README.md
|
||||
- Добавьте комментарии в код
|
||||
- Документируйте API endpoints
|
||||
- Обновите SETUP.md если нужно
|
||||
|
||||
## 🐛 Баг репорты
|
||||
|
||||
При сообщении о баге укажите:
|
||||
- Шаги для воспроизведения
|
||||
- Ожидаемое поведение
|
||||
- Фактическое поведение
|
||||
- Скриншоты/видео (если возможно)
|
||||
- Версия Node.js и MongoDB
|
||||
- ОС и браузер
|
||||
|
||||
## 💡 Идеи и предложения
|
||||
|
||||
Открывайте Issue с тегом "enhancement" для обсуждения новых функций.
|
||||
|
||||
## 📞 Вопросы?
|
||||
|
||||
Если что-то непонятно - создайте Issue с вопросом.
|
||||
|
||||
Спасибо за вклад в NakamaSpace! 🎉
|
||||
|
||||
288
CRON_SETUP.md
288
CRON_SETUP.md
|
|
@ -1,288 +0,0 @@
|
|||
# ⏰ Настройка автоматических бекапов через Cron
|
||||
|
||||
## 📋 Инструкция
|
||||
|
||||
### 1. Подключитесь к удаленному серверу
|
||||
|
||||
```bash
|
||||
ssh root@103.80.87.247
|
||||
```
|
||||
|
||||
### 2. Установите необходимые инструменты
|
||||
|
||||
```bash
|
||||
# Убедитесь, что mongo-tools установлены
|
||||
apt update
|
||||
apt install -y mongodb-database-tools
|
||||
```
|
||||
|
||||
### 3. Скопируйте скрипт бекапа на сервер
|
||||
|
||||
С вашего локального компьютера:
|
||||
|
||||
```bash
|
||||
scp backup-cron.sh root@103.80.87.247:/usr/local/bin/
|
||||
```
|
||||
|
||||
Или создайте файл напрямую на сервере:
|
||||
|
||||
```bash
|
||||
nano /usr/local/bin/backup-cron.sh
|
||||
# Вставьте содержимое из backup-cron.sh
|
||||
```
|
||||
|
||||
### 4. Сделайте скрипт исполняемым
|
||||
|
||||
```bash
|
||||
chmod +x /usr/local/bin/backup-cron.sh
|
||||
```
|
||||
|
||||
### 5. Настройте cron
|
||||
|
||||
```bash
|
||||
# Откройте crontab для редактирования
|
||||
crontab -e
|
||||
```
|
||||
|
||||
### 6. Добавьте задачи в crontab
|
||||
|
||||
Выберите один из вариантов:
|
||||
|
||||
#### Вариант 1: Еженедельные бекапы (воскресенье в 3:00 ночи)
|
||||
|
||||
```cron
|
||||
# Еженедельный бекап базы данных Nakama
|
||||
0 3 * * 0 /usr/local/bin/backup-cron.sh >> /var/log/nakama-backup.log 2>&1
|
||||
```
|
||||
|
||||
#### Вариант 2: Ежедневные бекапы (каждый день в 3:00 ночи)
|
||||
|
||||
```cron
|
||||
# Ежедневный бекап базы данных Nakama
|
||||
0 3 * * * /usr/local/bin/backup-cron.sh >> /var/log/nakama-backup.log 2>&1
|
||||
```
|
||||
|
||||
#### Вариант 3: Несколько бекапов в неделю (пн, ср, пт в 3:00)
|
||||
|
||||
```cron
|
||||
# Бекапы по понедельникам, средам и пятницам
|
||||
0 3 * * 1,3,5 /usr/local/bin/backup-cron.sh >> /var/log/nakama-backup.log 2>&1
|
||||
```
|
||||
|
||||
### 7. Проверьте настройку cron
|
||||
|
||||
```bash
|
||||
# Просмотреть текущие задачи cron
|
||||
crontab -l
|
||||
|
||||
# Проверить статус службы cron
|
||||
systemctl status cron
|
||||
```
|
||||
|
||||
### 8. Тестирование
|
||||
|
||||
Запустите бекап вручную:
|
||||
|
||||
```bash
|
||||
/usr/local/bin/backup-cron.sh
|
||||
```
|
||||
|
||||
Проверьте созданные бекапы:
|
||||
|
||||
```bash
|
||||
ls -lh /mnt/nakama-backups/
|
||||
```
|
||||
|
||||
Просмотрите лог:
|
||||
|
||||
```bash
|
||||
tail -50 /var/log/nakama-backup.log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Синтаксис Cron
|
||||
|
||||
```
|
||||
* * * * * команда
|
||||
│ │ │ │ │
|
||||
│ │ │ │ └─── День недели (0-7, где 0 и 7 = воскресенье)
|
||||
│ │ │ └───── Месяц (1-12)
|
||||
│ │ └─────── День месяца (1-31)
|
||||
│ └───────── Час (0-23)
|
||||
└─────────── Минута (0-59)
|
||||
```
|
||||
|
||||
### Примеры расписаний
|
||||
|
||||
| Расписание | Синтаксис Cron | Описание |
|
||||
|-----------|----------------|----------|
|
||||
| Каждую минуту | `* * * * *` | Выполняется каждую минуту |
|
||||
| Каждый час | `0 * * * *` | Выполняется в начале каждого часа |
|
||||
| Раз в день (в полночь) | `0 0 * * *` | Выполняется в 00:00 каждый день |
|
||||
| Раз в день (в 3:00) | `0 3 * * *` | Выполняется в 03:00 каждый день |
|
||||
| Раз в неделю (воскресенье) | `0 3 * * 0` | Выполняется в воскресенье в 03:00 |
|
||||
| Раз в месяц | `0 0 1 * *` | Выполняется 1-го числа каждого месяца в 00:00 |
|
||||
| Каждые 6 часов | `0 */6 * * *` | Выполняется в 00:00, 06:00, 12:00, 18:00 |
|
||||
| Рабочие дни в 9:00 | `0 9 * * 1-5` | Выполняется пн-пт в 09:00 |
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Настройка уведомлений (опционально)
|
||||
|
||||
Чтобы получать уведомления о статусе бекапов в Telegram:
|
||||
|
||||
### 1. Создайте бота для уведомлений
|
||||
|
||||
1. Напишите [@BotFather](https://t.me/BotFather) в Telegram
|
||||
2. Отправьте команду `/newbot`
|
||||
3. Следуйте инструкциям
|
||||
4. Скопируйте токен бота
|
||||
|
||||
### 2. Получите свой Chat ID
|
||||
|
||||
1. Напишите боту [@userinfobot](https://t.me/userinfobot)
|
||||
2. Скопируйте свой Chat ID
|
||||
|
||||
### 3. Обновите скрипт бекапа
|
||||
|
||||
Откройте `/usr/local/bin/backup-cron.sh` и раскомментируйте последние строки:
|
||||
|
||||
```bash
|
||||
# В конце скрипта найдите и раскомментируйте:
|
||||
curl -X POST "https://api.telegram.org/bot<YOUR_BOT_TOKEN>/sendMessage" \
|
||||
-d "chat_id=<YOUR_CHAT_ID>" \
|
||||
-d "text=✅ Резервная копия Nakama успешно создана: ${BACKUP_NAME}.tar.gz (${BACKUP_SIZE})"
|
||||
```
|
||||
|
||||
Замените:
|
||||
- `<YOUR_BOT_TOKEN>` на токен вашего бота
|
||||
- `<YOUR_CHAT_ID>` на ваш Chat ID
|
||||
|
||||
---
|
||||
|
||||
## 📝 Полезные команды
|
||||
|
||||
### Управление cron
|
||||
|
||||
```bash
|
||||
# Открыть crontab для редактирования
|
||||
crontab -e
|
||||
|
||||
# Показать текущие задачи
|
||||
crontab -l
|
||||
|
||||
# Удалить все задачи
|
||||
crontab -r
|
||||
|
||||
# Открыть crontab другого пользователя (требуются права root)
|
||||
crontab -u username -e
|
||||
```
|
||||
|
||||
### Просмотр логов
|
||||
|
||||
```bash
|
||||
# Показать последние 50 строк лога бекапов
|
||||
tail -50 /var/log/nakama-backup.log
|
||||
|
||||
# Следить за логом в реальном времени
|
||||
tail -f /var/log/nakama-backup.log
|
||||
|
||||
# Показать все ошибки в логе
|
||||
grep -i error /var/log/nakama-backup.log
|
||||
|
||||
# Показать системный лог cron
|
||||
grep CRON /var/log/syslog
|
||||
```
|
||||
|
||||
### Управление бекапами
|
||||
|
||||
```bash
|
||||
# Список всех бекапов
|
||||
ls -lht /mnt/nakama-backups/
|
||||
|
||||
# Размер директории с бекапами
|
||||
du -sh /mnt/nakama-backups/
|
||||
|
||||
# Удалить бекапы старше 30 дней
|
||||
find /mnt/nakama-backups/ -name "nakama_backup_*.tar.gz" -type f -mtime +30 -delete
|
||||
|
||||
# Подсчитать количество бекапов
|
||||
ls -1 /mnt/nakama-backups/ | wc -l
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Важные замечания
|
||||
|
||||
1. **Время выполнения**: Убедитесь, что время в cron указано в часовом поясе сервера. Проверьте:
|
||||
```bash
|
||||
timedatectl
|
||||
```
|
||||
|
||||
2. **Права доступа**: Убедитесь, что у пользователя, под которым запускается cron, есть права на запись в директорию бекапов.
|
||||
|
||||
3. **Место на диске**: Регулярно проверяйте свободное место:
|
||||
```bash
|
||||
df -h /mnt/nakama-backups/
|
||||
```
|
||||
|
||||
4. **Ротация логов**: Настройте logrotate для `/var/log/nakama-backup.log`:
|
||||
```bash
|
||||
nano /etc/logrotate.d/nakama-backup
|
||||
```
|
||||
|
||||
Добавьте:
|
||||
```
|
||||
/var/log/nakama-backup.log {
|
||||
weekly
|
||||
rotate 4
|
||||
compress
|
||||
missingok
|
||||
notifempty
|
||||
}
|
||||
```
|
||||
|
||||
5. **Мониторинг**: Регулярно проверяйте, что бекапы создаются успешно:
|
||||
```bash
|
||||
ls -lt /mnt/nakama-backups/ | head
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Восстановление из бекапа
|
||||
|
||||
Если понадобится восстановить базу данных:
|
||||
|
||||
```bash
|
||||
# 1. Перейти в директорию с бекапами
|
||||
cd /mnt/nakama-backups/
|
||||
|
||||
# 2. Найти нужный бекап
|
||||
ls -lt | grep nakama_backup
|
||||
|
||||
# 3. Распаковать бекап
|
||||
tar -xzf nakama_backup_YYYY-MM-DD_HH-MM-SS.tar.gz
|
||||
|
||||
# 4. Восстановить базу данных
|
||||
mongorestore --uri="mongodb://localhost:27017" \
|
||||
--drop \
|
||||
--gzip \
|
||||
--db nakama \
|
||||
nakama_backup_YYYY-MM-DD_HH-MM-SS/nakama/
|
||||
|
||||
# 5. Удалить распакованную директорию
|
||||
rm -rf nakama_backup_YYYY-MM-DD_HH-MM-SS/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📞 Помощь
|
||||
|
||||
Если у вас возникли проблемы с настройкой cron:
|
||||
|
||||
1. Проверьте логи: `tail -f /var/log/nakama-backup.log`
|
||||
2. Проверьте системный лог: `grep CRON /var/log/syslog`
|
||||
3. Убедитесь, что cron запущен: `systemctl status cron`
|
||||
4. Запустите скрипт вручную для отладки: `/usr/local/bin/backup-cron.sh`
|
||||
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
# 🌙 Исправление тёмной темы - Финальное
|
||||
|
||||
## Проблемы на скриншоте:
|
||||
|
||||
1. ❌ Кнопка "Все" (фильтр) - серая на чёрном, не видно
|
||||
2. ❌ Кнопка "Опубликовать" - серая на чёрном, не видно
|
||||
3. ❌ Кнопки режимов в поиске - не видно
|
||||
|
||||
## ✅ Решение:
|
||||
|
||||
### 1. Кнопки фильтров (Все, Furry, Anime, Other)
|
||||
- Добавлена рамка `border: 1px solid`
|
||||
- Цвет текста изменён на `var(--text-primary)` (белый в тёмной теме)
|
||||
- Активная кнопка стала синей (`var(--button-accent)`)
|
||||
|
||||
### 2. Кнопка "Опубликовать"
|
||||
- Цвет изменён с `var(--button-dark)` на `var(--button-accent)` (синий)
|
||||
- Теперь всегда видна (синяя в любой теме)
|
||||
- Disabled состояние - серое
|
||||
|
||||
### 3. Кнопки режимов поиска (Furry, Anime, Mixed)
|
||||
- Аналогично фильтрам - добавлена рамка и правильный цвет
|
||||
|
||||
### 4. Кнопка "Создать первый пост"
|
||||
- Изменена на синюю
|
||||
|
||||
---
|
||||
|
||||
## 📝 Изменённые файлы:
|
||||
|
||||
1. `frontend/src/pages/Feed.css`
|
||||
- `.filter-btn` - добавлена рамка, цвет текста
|
||||
- `.filter-btn.active` - синий фон
|
||||
- `.btn-primary` - синий фон
|
||||
|
||||
2. `frontend/src/components/CreatePostModal.css`
|
||||
- `.submit-btn` - синий фон
|
||||
|
||||
3. `frontend/src/pages/Search.css`
|
||||
- `.mode-btn` - добавлена рамка, цвет текста
|
||||
- `.mode-btn.active` - синий фон
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Теперь в тёмной теме:
|
||||
|
||||
### Светлая тема:
|
||||
- Кнопки: светло-серые с рамкой
|
||||
- Активная: синяя
|
||||
- Текст: тёмный
|
||||
|
||||
### Тёмная тема:
|
||||
- Кнопки: тёмно-серые с рамкой
|
||||
- Активная: синяя
|
||||
- Текст: **белый** (видно! ✅)
|
||||
|
||||
---
|
||||
|
||||
## 📤 Загрузить на сервер:
|
||||
|
||||
Только 3 CSS файла изменились:
|
||||
|
||||
```bash
|
||||
# НА КОМПЬЮТЕРЕ
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
|
||||
scp frontend/src/pages/Feed.css root@ваш_IP:/var/www/nakama/frontend/src/pages/
|
||||
scp frontend/src/components/CreatePostModal.css root@ваш_IP:/var/www/nakama/frontend/src/components/
|
||||
scp frontend/src/pages/Search.css root@ваш_IP:/var/www/nakama/frontend/src/pages/
|
||||
|
||||
# НА СЕРВЕРЕ
|
||||
ssh root@ваш_IP
|
||||
cd /var/www/nakama/frontend
|
||||
npm run build
|
||||
|
||||
# Готово! Backend НЕ нужно перезапускать
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ После обновления:
|
||||
|
||||
Откройте https://nakama.glpshchn.ru в тёмной теме:
|
||||
|
||||
- ✅ Кнопка "Все" видна (белый текст с рамкой)
|
||||
- ✅ Кнопка "Опубликовать" видна (синяя)
|
||||
- ✅ Все фильтры видны
|
||||
- ✅ Режимы поиска видны
|
||||
- ✅ Активная кнопка синяя
|
||||
|
||||
---
|
||||
|
||||
**Версия**: v2.1.2 (Dark theme visibility fix)
|
||||
|
||||
|
||||
534
DEPLOYMENT.md
534
DEPLOYMENT.md
|
|
@ -1,534 +0,0 @@
|
|||
# 🚀 Deployment Guide - NakamaSpace
|
||||
|
||||
Инструкция по деплою NakamaSpace на production серверы.
|
||||
|
||||
## 📋 Требования
|
||||
|
||||
### Backend
|
||||
- Node.js 16+
|
||||
- MongoDB 5+ (или MongoDB Atlas)
|
||||
- Redis (опционально, для кэширования)
|
||||
- HTTPS сертификат
|
||||
|
||||
### Frontend
|
||||
- Node.js 16+ (для сборки)
|
||||
- Статический хостинг или CDN
|
||||
|
||||
---
|
||||
|
||||
## 🌐 Рекомендуемые платформы
|
||||
|
||||
### Backend + MongoDB
|
||||
1. **Railway** (самый простой) ⭐
|
||||
2. **Render** (бесплатный tier)
|
||||
3. **Heroku** (платный)
|
||||
4. **DigitalOcean App Platform**
|
||||
5. **AWS Elastic Beanstalk**
|
||||
6. **Google Cloud Run**
|
||||
|
||||
### Frontend
|
||||
1. **Vercel** (оптимально для Vite) ⭐
|
||||
2. **Netlify**
|
||||
3. **Cloudflare Pages**
|
||||
4. **GitHub Pages** (с настройкой)
|
||||
|
||||
### MongoDB
|
||||
1. **MongoDB Atlas** (бесплатный M0 tier) ⭐
|
||||
2. **DigitalOcean Managed Database**
|
||||
3. **AWS DocumentDB**
|
||||
|
||||
### Redis (опционально)
|
||||
1. **Upstash** (serverless, бесплатный tier)
|
||||
2. **Redis Cloud**
|
||||
3. **Railway Redis**
|
||||
|
||||
---
|
||||
|
||||
## 🚂 Railway Deployment (Рекомендуется)
|
||||
|
||||
### Backend
|
||||
|
||||
1. **Установить Railway CLI:**
|
||||
```bash
|
||||
npm i -g @railway/cli
|
||||
railway login
|
||||
```
|
||||
|
||||
2. **Создать проект:**
|
||||
```bash
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
railway init
|
||||
```
|
||||
|
||||
3. **Добавить MongoDB плагин:**
|
||||
```bash
|
||||
railway add mongodb
|
||||
```
|
||||
|
||||
4. **Настроить переменные окружения:**
|
||||
```bash
|
||||
railway variables set NODE_ENV=production
|
||||
railway variables set JWT_SECRET=$(openssl rand -base64 32)
|
||||
railway variables set TELEGRAM_BOT_TOKEN=your_token_here
|
||||
railway variables set FRONTEND_URL=https://your-frontend.vercel.app
|
||||
```
|
||||
|
||||
5. **Деплой:**
|
||||
```bash
|
||||
railway up
|
||||
```
|
||||
|
||||
6. **Получить URL:**
|
||||
```bash
|
||||
railway domain
|
||||
```
|
||||
|
||||
### Frontend
|
||||
|
||||
1. **Установить Vercel CLI:**
|
||||
```bash
|
||||
npm i -g vercel
|
||||
```
|
||||
|
||||
2. **Настроить .env.production:**
|
||||
```bash
|
||||
cd frontend
|
||||
echo "VITE_API_URL=https://your-railway-app.railway.app/api" > .env.production
|
||||
```
|
||||
|
||||
3. **Деплой:**
|
||||
```bash
|
||||
vercel --prod
|
||||
```
|
||||
|
||||
4. **Настроить Telegram Bot:**
|
||||
- Откройте @BotFather
|
||||
- `/mybots` → Ваш бот → Bot Settings → Menu Button
|
||||
- Укажите URL: `https://your-vercel-app.vercel.app`
|
||||
|
||||
---
|
||||
|
||||
## ☁️ MongoDB Atlas Setup
|
||||
|
||||
1. **Создать аккаунт:**
|
||||
- Зайдите на https://www.mongodb.com/cloud/atlas
|
||||
- Создайте бесплатный M0 cluster
|
||||
|
||||
2. **Настроить доступ:**
|
||||
- Database Access → Add User
|
||||
- Network Access → Add IP (0.0.0.0/0 для всех)
|
||||
|
||||
3. **Получить Connection String:**
|
||||
- Cluster → Connect → Connect your application
|
||||
- Скопируйте URI: `mongodb+srv://...`
|
||||
|
||||
4. **Добавить в переменные:**
|
||||
```bash
|
||||
railway variables set MONGODB_URI="mongodb+srv://user:pass@cluster.mongodb.net/nakama"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🐳 Docker Deployment
|
||||
|
||||
### Dockerfile для Backend
|
||||
|
||||
```dockerfile
|
||||
FROM node:18-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Установить зависимости
|
||||
COPY package*.json ./
|
||||
RUN npm ci --only=production
|
||||
|
||||
# Скопировать код
|
||||
COPY backend ./backend
|
||||
|
||||
# Создать папку для uploads
|
||||
RUN mkdir -p backend/uploads
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
CMD ["node", "backend/server.js"]
|
||||
```
|
||||
|
||||
### Dockerfile для Frontend
|
||||
|
||||
```dockerfile
|
||||
FROM node:18-alpine AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Установить зависимости
|
||||
COPY frontend/package*.json ./
|
||||
RUN npm ci
|
||||
|
||||
# Скопировать код
|
||||
COPY frontend ./
|
||||
|
||||
# Собрать
|
||||
RUN npm run build
|
||||
|
||||
# Production образ
|
||||
FROM nginx:alpine
|
||||
|
||||
COPY --from=builder /app/dist /usr/share/nginx/html
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
```
|
||||
|
||||
### docker-compose.yml
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
backend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.backend
|
||||
ports:
|
||||
- "3000:3000"
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- MONGODB_URI=mongodb://mongo:27017/nakama
|
||||
- JWT_SECRET=${JWT_SECRET}
|
||||
- TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN}
|
||||
depends_on:
|
||||
- mongo
|
||||
- redis
|
||||
restart: unless-stopped
|
||||
|
||||
frontend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.frontend
|
||||
ports:
|
||||
- "80:80"
|
||||
depends_on:
|
||||
- backend
|
||||
restart: unless-stopped
|
||||
|
||||
mongo:
|
||||
image: mongo:6
|
||||
volumes:
|
||||
- mongo_data:/data/db
|
||||
restart: unless-stopped
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
mongo_data:
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Environment Variables Checklist
|
||||
|
||||
### Backend (.env.production)
|
||||
- ✅ `NODE_ENV=production`
|
||||
- ✅ `MONGODB_URI` - MongoDB connection string
|
||||
- ✅ `PORT` - Порт сервера (обычно 3000)
|
||||
- ✅ `JWT_SECRET` - Случайная строка (openssl rand -base64 32)
|
||||
- ✅ `TELEGRAM_BOT_TOKEN` - Токен от @BotFather
|
||||
- ✅ `FRONTEND_URL` - URL frontend приложения
|
||||
- ✅ `CORS_ORIGIN` - Разрешённые origins (через запятую)
|
||||
- ⚙️ `REDIS_URL` - (опционально) Redis connection string
|
||||
|
||||
### Frontend (.env.production)
|
||||
- ✅ `VITE_API_URL` - URL backend API
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Security Checklist
|
||||
|
||||
Перед деплоем проверьте:
|
||||
|
||||
- [ ] JWT_SECRET изменён на случайную строку
|
||||
- [ ] MongoDB доступ ограничен (не 0.0.0.0/0 в prod)
|
||||
- [ ] CORS настроен правильно (не '*' в prod)
|
||||
- [ ] Rate limiting включён
|
||||
- [ ] HTTPS настроен (обязательно для Telegram Mini App)
|
||||
- [ ] Переменные окружения не закоммичены в Git
|
||||
- [ ] MongoDB Atlas IP whitelist настроен
|
||||
- [ ] Telegram Bot webhook настроен правильно
|
||||
|
||||
---
|
||||
|
||||
## 📊 Performance Optimization
|
||||
|
||||
### Backend
|
||||
|
||||
1. **Enable Redis caching:**
|
||||
```bash
|
||||
railway variables set REDIS_URL=redis://...
|
||||
```
|
||||
|
||||
2. **Увеличить rate limits для production:**
|
||||
```bash
|
||||
railway variables set RATE_LIMIT_GENERAL=1000
|
||||
railway variables set RATE_LIMIT_POSTS=50
|
||||
```
|
||||
|
||||
3. **Configure MongoDB indexes:**
|
||||
MongoDB индексы уже настроены в моделях, но проверьте их создание:
|
||||
```bash
|
||||
db.posts.getIndexes()
|
||||
```
|
||||
|
||||
### Frontend
|
||||
|
||||
1. **Enable Vercel Edge Network:**
|
||||
- Автоматически включается при деплое на Vercel
|
||||
|
||||
2. **Configure caching headers:**
|
||||
Создайте `vercel.json`:
|
||||
```json
|
||||
{
|
||||
"headers": [
|
||||
{
|
||||
"source": "/assets/(.*)",
|
||||
"headers": [
|
||||
{
|
||||
"key": "Cache-Control",
|
||||
"value": "public, max-age=31536000, immutable"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 CI/CD Setup
|
||||
|
||||
### GitHub Actions (Railway)
|
||||
|
||||
Создайте `.github/workflows/deploy.yml`:
|
||||
|
||||
```yaml
|
||||
name: Deploy to Railway
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install Railway
|
||||
run: npm i -g @railway/cli
|
||||
|
||||
- name: Deploy
|
||||
run: railway up
|
||||
env:
|
||||
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📱 Telegram Bot Setup
|
||||
|
||||
1. **Настроить Menu Button:**
|
||||
```
|
||||
/mybots → Выбрать бота → Bot Settings → Menu Button
|
||||
URL: https://your-vercel-app.vercel.app
|
||||
Text: Открыть NakamaSpace
|
||||
```
|
||||
|
||||
2. **Настроить Description:**
|
||||
```
|
||||
/mybots → Выбрать бота → Edit Bot → Edit Description
|
||||
"NakamaSpace - мини-социальная сеть для Furry и Anime сообщества"
|
||||
```
|
||||
|
||||
3. **Добавить команды:**
|
||||
```
|
||||
/mybots → Выбрать бота → Edit Bot → Edit Commands
|
||||
|
||||
start - Запустить NakamaSpace
|
||||
help - Помощь
|
||||
profile - Мой профиль
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Testing Production
|
||||
|
||||
После деплоя проверьте:
|
||||
|
||||
1. **Health check:**
|
||||
```bash
|
||||
curl https://your-api.railway.app/health
|
||||
```
|
||||
|
||||
2. **API доступность:**
|
||||
```bash
|
||||
curl https://your-api.railway.app/api
|
||||
```
|
||||
|
||||
3. **WebSocket:**
|
||||
```javascript
|
||||
const socket = io('https://your-api.railway.app')
|
||||
socket.on('connect', () => console.log('Connected!'))
|
||||
```
|
||||
|
||||
4. **Frontend:**
|
||||
- Откройте `https://your-app.vercel.app`
|
||||
- Проверьте что API запросы работают
|
||||
- Проверьте авторизацию через Telegram
|
||||
|
||||
5. **Telegram Mini App:**
|
||||
- Откройте бота в Telegram
|
||||
- Нажмите Menu Button
|
||||
- Проверьте что приложение загружается
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### CORS Errors
|
||||
```bash
|
||||
railway variables set CORS_ORIGIN=https://your-frontend.vercel.app
|
||||
```
|
||||
|
||||
### Telegram Init Data Invalid
|
||||
- Проверьте что TELEGRAM_BOT_TOKEN правильный
|
||||
- Проверьте что используется HTTPS
|
||||
|
||||
### MongoDB Connection Failed
|
||||
- Проверьте MONGODB_URI
|
||||
- Проверьте IP whitelist в Atlas
|
||||
- Проверьте что пароль не содержит специальных символов (URL encode)
|
||||
|
||||
### Redis Connection Failed
|
||||
- Это нормально, приложение работает без Redis
|
||||
- Для включения: настройте REDIS_URL
|
||||
|
||||
### WebSocket не подключается
|
||||
- Проверьте CORS_ORIGIN
|
||||
- Проверьте что используется wss:// (не ws://) для HTTPS
|
||||
|
||||
---
|
||||
|
||||
## 📈 Monitoring
|
||||
|
||||
### Railway Logs
|
||||
```bash
|
||||
railway logs
|
||||
```
|
||||
|
||||
### MongoDB Atlas Monitoring
|
||||
- Atlas Dashboard → Metrics
|
||||
- Отслеживайте: Connections, Operations, Storage
|
||||
|
||||
### Uptime Monitoring
|
||||
Используйте:
|
||||
- **UptimeRobot** (бесплатно)
|
||||
- **Pingdom**
|
||||
- **StatusCake**
|
||||
|
||||
Мониторьте endpoints:
|
||||
- `https://your-api.railway.app/health`
|
||||
- `https://your-frontend.vercel.app`
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Updates
|
||||
|
||||
### Backend Update
|
||||
```bash
|
||||
git push origin main
|
||||
# Railway автоматически задеплоит
|
||||
```
|
||||
|
||||
### Frontend Update
|
||||
```bash
|
||||
cd frontend
|
||||
vercel --prod
|
||||
```
|
||||
|
||||
### Database Migration
|
||||
Если изменились модели:
|
||||
```bash
|
||||
# Подключиться к MongoDB
|
||||
mongo "mongodb+srv://..."
|
||||
|
||||
# Выполнить миграцию
|
||||
db.posts.createIndex({ content: "text", hashtags: "text" })
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🌍 Доступность для пользователей из РФ
|
||||
|
||||
### Проксирование изображений
|
||||
|
||||
NakamaSpace автоматически проксирует изображения с e621 и gelbooru через ваш сервер, что обеспечивает доступность контента для пользователей из РФ, где эти сайты могут быть заблокированы.
|
||||
|
||||
**Как это работает:**
|
||||
1. API запросы к e621 и gelbooru выполняются с вашего сервера
|
||||
2. URL изображений автоматически заменяются на прокси-URL вашего сервера
|
||||
3. Изображения стримятся через эндпоинт `/api/search/proxy/:encodedUrl`
|
||||
4. Добавлено кэширование (24 часа) для оптимизации производительности
|
||||
|
||||
**Поддерживаемые домены:**
|
||||
- `e621.net`
|
||||
- `static1.e621.net`
|
||||
- `gelbooru.com`
|
||||
- `static1.gelbooru.com`
|
||||
|
||||
**Важно:**
|
||||
- Убедитесь, что ваш сервер имеет доступ к этим доменам
|
||||
- Рекомендуется использовать сервер вне РФ для надежного доступа к источникам
|
||||
- Проксирование происходит автоматически, никаких дополнительных настроек не требуется
|
||||
|
||||
---
|
||||
|
||||
## 💰 Costs Estimate
|
||||
|
||||
### Free Tier (Starter)
|
||||
- **Railway**: $5/month credits (достаточно для старта)
|
||||
- **MongoDB Atlas**: Free M0 (512MB)
|
||||
- **Vercel**: Free (100GB bandwidth)
|
||||
- **Total**: ~$0-5/month
|
||||
|
||||
### Production Tier
|
||||
- **Railway**: ~$10-20/month
|
||||
- **MongoDB Atlas**: M2 $9/month (2GB)
|
||||
- **Redis**: Upstash $10/month или Railway $5/month
|
||||
- **Vercel**: Pro $20/month (больше bandwidth)
|
||||
- **Total**: ~$30-60/month
|
||||
|
||||
---
|
||||
|
||||
## 🎉 Ready!
|
||||
|
||||
После выполнения всех шагов у вас будет:
|
||||
- ✅ Backend на Railway с MongoDB Atlas
|
||||
- ✅ Frontend на Vercel
|
||||
- ✅ HTTPS для обоих
|
||||
- ✅ Telegram Bot настроен
|
||||
- ✅ Monitoring включён
|
||||
|
||||
**Ваш NakamaSpace готов к использованию!** 🚀
|
||||
|
||||
---
|
||||
|
||||
## 📞 Support
|
||||
|
||||
Проблемы при деплое? Проверьте:
|
||||
1. [SETUP.md](SETUP.md) - подробная инструкция
|
||||
2. [QUICKSTART.md](QUICKSTART.md) - быстрый старт
|
||||
3. GitHub Issues - создайте issue с описанием проблемы
|
||||
|
||||
|
|
@ -1,477 +0,0 @@
|
|||
# 🚀 Руководство по развертыванию Nakama
|
||||
|
||||
## 📋 Содержание
|
||||
1. [Требования](#требования)
|
||||
2. [Настройка удаленного сервера](#настройка-удаленного-сервера)
|
||||
3. [Настройка базы данных](#настройка-базы-данных)
|
||||
4. [Настройка автоматических бекапов](#настройка-автоматических-бекапов)
|
||||
5. [Развертывание с Docker](#развертывание-с-docker)
|
||||
6. [Настройка nginx](#настройка-nginx)
|
||||
7. [Мониторинг и обслуживание](#мониторинг-и-обслуживание)
|
||||
|
||||
---
|
||||
|
||||
## ✅ Требования
|
||||
|
||||
### Локальный сервер (где запускается приложение)
|
||||
- Docker 20.10+
|
||||
- Docker Compose 2.0+
|
||||
- SSHFS (для монтирования удаленных директорий)
|
||||
- 2GB+ RAM
|
||||
- 10GB+ свободного места на диске
|
||||
|
||||
### Удаленный сервер (103.80.87.247)
|
||||
- SSH доступ
|
||||
- MongoDB 7+
|
||||
- 50GB+ свободного места для базы данных и медиа
|
||||
- Открытый порт 27017 для MongoDB
|
||||
|
||||
---
|
||||
|
||||
## 🗄️ Настройка удаленного сервера
|
||||
|
||||
### 1. Подключение по SSH
|
||||
|
||||
```bash
|
||||
ssh root@103.80.87.247
|
||||
```
|
||||
|
||||
### 2. Установка MongoDB
|
||||
|
||||
```bash
|
||||
# Обновить систему
|
||||
apt update && apt upgrade -y
|
||||
|
||||
# Импортировать GPG ключ MongoDB
|
||||
curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | \
|
||||
sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor
|
||||
|
||||
# Добавить репозиторий MongoDB
|
||||
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse" | \
|
||||
sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list
|
||||
|
||||
# Установить MongoDB
|
||||
apt update
|
||||
apt install -y mongodb-org
|
||||
|
||||
# Запустить MongoDB
|
||||
systemctl start mongod
|
||||
systemctl enable mongod
|
||||
```
|
||||
|
||||
### 3. Настройка MongoDB для удаленного доступа
|
||||
|
||||
```bash
|
||||
# Редактировать конфигурацию
|
||||
nano /etc/mongod.conf
|
||||
```
|
||||
|
||||
Изменить `bindIp`:
|
||||
```yaml
|
||||
net:
|
||||
port: 27017
|
||||
bindIp: 0.0.0.0 # Разрешить подключения со всех IP
|
||||
```
|
||||
|
||||
Настроить аутентификацию (рекомендуется):
|
||||
```bash
|
||||
# Подключиться к MongoDB
|
||||
mongosh
|
||||
|
||||
# Создать администратора
|
||||
use admin
|
||||
db.createUser({
|
||||
user: "admin",
|
||||
pwd: "your_secure_password",
|
||||
roles: [ { role: "root", db: "admin" } ]
|
||||
})
|
||||
|
||||
# Создать пользователя для приложения
|
||||
use nakama
|
||||
db.createUser({
|
||||
user: "nakama_user",
|
||||
pwd: "your_app_password",
|
||||
roles: [ { role: "readWrite", db: "nakama" } ]
|
||||
})
|
||||
```
|
||||
|
||||
Перезапустить MongoDB:
|
||||
```bash
|
||||
systemctl restart mongod
|
||||
```
|
||||
|
||||
### 4. Создание директорий для хранения данных
|
||||
|
||||
```bash
|
||||
# Создать директории
|
||||
mkdir -p /var/nakama/media
|
||||
mkdir -p /var/nakama/db
|
||||
mkdir -p /var/nakama/backups
|
||||
|
||||
# Установить права доступа
|
||||
chmod -R 755 /var/nakama
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 💾 Настройка базы данных
|
||||
|
||||
### Строка подключения
|
||||
|
||||
Обновите `.env` файл:
|
||||
|
||||
```env
|
||||
# Без аутентификации
|
||||
MONGODB_URI=mongodb://103.80.87.247:27017/nakama
|
||||
|
||||
# С аутентификацией
|
||||
MONGODB_URI=mongodb://nakama_user:your_app_password@103.80.87.247:27017/nakama
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Настройка автоматических бекапов
|
||||
|
||||
### 1. Установка cron на удаленном сервере
|
||||
|
||||
```bash
|
||||
# Скопировать скрипт бекапа на удаленный сервер
|
||||
scp backup-cron.sh root@103.80.87.247:/usr/local/bin/
|
||||
|
||||
# Подключиться к удаленному серверу
|
||||
ssh root@103.80.87.247
|
||||
|
||||
# Сделать скрипт исполняемым
|
||||
chmod +x /usr/local/bin/backup-cron.sh
|
||||
|
||||
# Открыть crontab
|
||||
crontab -e
|
||||
```
|
||||
|
||||
### 2. Добавить задачу в crontab
|
||||
|
||||
Добавьте следующую строку для запуска бекапа каждое воскресенье в 3:00 ночи:
|
||||
|
||||
```cron
|
||||
0 3 * * 0 /usr/local/bin/backup-cron.sh >> /var/log/nakama-backup.log 2>&1
|
||||
```
|
||||
|
||||
Для ежедневных бекапов в 3:00 ночи:
|
||||
```cron
|
||||
0 3 * * * /usr/local/bin/backup-cron.sh >> /var/log/nakama-backup.log 2>&1
|
||||
```
|
||||
|
||||
### 3. Проверка работы бекапов
|
||||
|
||||
```bash
|
||||
# Запустить бекап вручную
|
||||
/usr/local/bin/backup-cron.sh
|
||||
|
||||
# Проверить созданные бекапы
|
||||
ls -lh /var/nakama/backups/
|
||||
|
||||
# Просмотреть лог
|
||||
tail -f /var/log/nakama-backup.log
|
||||
```
|
||||
|
||||
### 4. Восстановление из бекапа
|
||||
|
||||
```bash
|
||||
# Распаковать бекап
|
||||
cd /var/nakama/backups
|
||||
tar -xzf nakama_backup_YYYY-MM-DD_HH-MM-SS.tar.gz
|
||||
|
||||
# Восстановить базу данных
|
||||
mongorestore --uri="mongodb://103.80.87.247:27017" --gzip --db nakama nakama_backup_YYYY-MM-DD_HH-MM-SS/nakama/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🐳 Развертывание с Docker
|
||||
|
||||
### 1. Подготовка
|
||||
|
||||
```bash
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
|
||||
# Скопировать и настроить .env
|
||||
cp .env.example .env
|
||||
nano .env # Заполнить необходимые переменные
|
||||
```
|
||||
|
||||
### 2. Монтирование удаленных директорий (опционально)
|
||||
|
||||
Если вы хотите хранить медиа и бекапы на удаленном сервере:
|
||||
|
||||
```bash
|
||||
# Запустить скрипт настройки
|
||||
./setup-remote-storage.sh
|
||||
```
|
||||
|
||||
### 3. Сборка и запуск контейнеров
|
||||
|
||||
```bash
|
||||
# Собрать все сервисы
|
||||
docker-compose build
|
||||
|
||||
# Запустить в фоновом режиме
|
||||
docker-compose up -d
|
||||
|
||||
# Проверить статус
|
||||
docker-compose ps
|
||||
|
||||
# Просмотреть логи
|
||||
docker-compose logs -f
|
||||
```
|
||||
|
||||
### 4. Проверка работы
|
||||
|
||||
```bash
|
||||
# Проверить backend
|
||||
curl http://localhost:3000/health
|
||||
|
||||
# Проверить frontend
|
||||
curl http://localhost:5173
|
||||
|
||||
# Проверить moderation
|
||||
curl http://localhost:5174
|
||||
```
|
||||
|
||||
### 5. Остановка и обновление
|
||||
|
||||
```bash
|
||||
# Остановить все сервисы
|
||||
docker-compose down
|
||||
|
||||
# Пересобрать и перезапустить
|
||||
docker-compose up -d --build
|
||||
|
||||
# Перезапустить конкретный сервис
|
||||
docker-compose restart backend
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🌐 Настройка nginx (reverse proxy)
|
||||
|
||||
### Конфигурация для production
|
||||
|
||||
Создайте файл `/etc/nginx/sites-available/nakama`:
|
||||
|
||||
```nginx
|
||||
# Frontend (основное приложение)
|
||||
server {
|
||||
listen 80;
|
||||
server_name nakama.yourdomain.com;
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:5173;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host $host;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
}
|
||||
}
|
||||
|
||||
# Moderation (система модерации)
|
||||
server {
|
||||
listen 80;
|
||||
server_name mod.nakama.yourdomain.com;
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:5174;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host $host;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
}
|
||||
}
|
||||
|
||||
# Backend API
|
||||
server {
|
||||
listen 80;
|
||||
server_name api.nakama.yourdomain.com;
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
|
||||
# WebSocket support
|
||||
proxy_read_timeout 86400;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Активировать конфигурацию:
|
||||
|
||||
```bash
|
||||
# Создать символическую ссылку
|
||||
ln -s /etc/nginx/sites-available/nakama /etc/nginx/sites-enabled/
|
||||
|
||||
# Проверить конфигурацию
|
||||
nginx -t
|
||||
|
||||
# Перезапустить nginx
|
||||
systemctl restart nginx
|
||||
```
|
||||
|
||||
### SSL сертификаты (Let's Encrypt)
|
||||
|
||||
```bash
|
||||
# Установить certbot
|
||||
apt install certbot python3-certbot-nginx
|
||||
|
||||
# Получить сертификаты
|
||||
certbot --nginx -d nakama.yourdomain.com -d mod.nakama.yourdomain.com -d api.nakama.yourdomain.com
|
||||
|
||||
# Автоматическое обновление
|
||||
certbot renew --dry-run
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Мониторинг и обслуживание
|
||||
|
||||
### Просмотр логов
|
||||
|
||||
```bash
|
||||
# Логи backend
|
||||
docker-compose logs -f backend
|
||||
|
||||
# Логи всех сервисов
|
||||
docker-compose logs -f
|
||||
|
||||
# Логи MongoDB на удаленном сервере
|
||||
ssh root@103.80.87.247 'tail -f /var/log/mongodb/mongod.log'
|
||||
```
|
||||
|
||||
### Мониторинг ресурсов
|
||||
|
||||
```bash
|
||||
# Использование Docker контейнеров
|
||||
docker stats
|
||||
|
||||
# Использование диска
|
||||
df -h
|
||||
|
||||
# Статус MongoDB (на удаленном сервере)
|
||||
ssh root@103.80.87.247 'systemctl status mongod'
|
||||
```
|
||||
|
||||
### Обновление приложения
|
||||
|
||||
```bash
|
||||
# 1. Создать бекап
|
||||
./backup-cron.sh
|
||||
|
||||
# 2. Получить обновления
|
||||
git pull
|
||||
|
||||
# 3. Остановить контейнеры
|
||||
docker-compose down
|
||||
|
||||
# 4. Пересобрать и запустить
|
||||
docker-compose up -d --build
|
||||
|
||||
# 5. Проверить работу
|
||||
docker-compose ps
|
||||
docker-compose logs -f
|
||||
```
|
||||
|
||||
### Очистка
|
||||
|
||||
```bash
|
||||
# Удалить неиспользуемые образы
|
||||
docker image prune -a
|
||||
|
||||
# Удалить неиспользуемые volumes
|
||||
docker volume prune
|
||||
|
||||
# Полная очистка Docker
|
||||
docker system prune -a --volumes
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Решение проблем
|
||||
|
||||
### База данных недоступна
|
||||
|
||||
```bash
|
||||
# Проверить подключение к MongoDB
|
||||
mongosh --host 103.80.87.247 --port 27017
|
||||
|
||||
# Проверить статус MongoDB на удаленном сервере
|
||||
ssh root@103.80.87.247 'systemctl status mongod'
|
||||
|
||||
# Проверить логи
|
||||
ssh root@103.80.87.247 'tail -100 /var/log/mongodb/mongod.log'
|
||||
```
|
||||
|
||||
### Контейнеры не запускаются
|
||||
|
||||
```bash
|
||||
# Проверить логи
|
||||
docker-compose logs
|
||||
|
||||
# Пересоздать контейнеры
|
||||
docker-compose down -v
|
||||
docker-compose up -d --force-recreate
|
||||
```
|
||||
|
||||
### Проблемы с медиа
|
||||
|
||||
```bash
|
||||
# Проверить монтирование директорий
|
||||
df -h | grep nakama
|
||||
|
||||
# Проверить права доступа
|
||||
ls -la /mnt/nakama-media
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 Дополнительные команды
|
||||
|
||||
### Создание ручного бекапа
|
||||
|
||||
```bash
|
||||
docker-compose exec mongodb mongodump --uri="mongodb://103.80.87.247:27017/nakama" --out=/backups/manual_backup
|
||||
```
|
||||
|
||||
### Экспорт/импорт данных
|
||||
|
||||
```bash
|
||||
# Экспорт коллекции
|
||||
docker-compose exec mongodb mongoexport --uri="mongodb://103.80.87.247:27017/nakama" --collection=posts --out=/backups/posts.json
|
||||
|
||||
# Импорт коллекции
|
||||
docker-compose exec mongodb mongoimport --uri="mongodb://103.80.87.247:27017/nakama" --collection=posts --file=/backups/posts.json
|
||||
```
|
||||
|
||||
### Масштабирование
|
||||
|
||||
Для горизонтального масштабирования backend:
|
||||
|
||||
```bash
|
||||
docker-compose up -d --scale backend=3
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📞 Поддержка
|
||||
|
||||
При возникновении проблем:
|
||||
1. Проверьте логи: `docker-compose logs -f`
|
||||
2. Проверьте статус сервисов: `docker-compose ps`
|
||||
3. Создайте issue на GitHub или напишите в https://t.me/NakamaReportbot
|
||||
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
╔═══════════════════════════════════════════════════════════════════════╗
|
||||
║ Простая инструкция загрузки на сервер ║
|
||||
║ nakama.glpshchn.ru ║
|
||||
╚═══════════════════════════════════════════════════════════════════════╝
|
||||
|
||||
📦 ШАГ 1: Упаковать проект (НА КОМПЬЮТЕРЕ)
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
cd /Users/glpshchn/Desktop
|
||||
|
||||
tar -czf nakama-ready.tar.gz nakama \
|
||||
--exclude='nakama/node_modules' \
|
||||
--exclude='nakama/frontend/node_modules' \
|
||||
--exclude='nakama/frontend/dist' \
|
||||
--exclude='nakama/.git'
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
📤 ШАГ 2: Загрузить на сервер (НА КОМПЬЮТЕРЕ)
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
scp nakama-ready.tar.gz root@ваш_IP:/tmp/
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
🔄 ШАГ 3: Развернуть (НА СЕРВЕРЕ)
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
ssh root@ваш_IP
|
||||
|
||||
# Бэкап текущей версии
|
||||
cd /var/www/nakama
|
||||
cp .env /tmp/nakama-backup.env
|
||||
cp -r backend/uploads /tmp/nakama-backup-uploads
|
||||
|
||||
# Удалить старую версию
|
||||
cd /var/www
|
||||
sudo rm -rf nakama
|
||||
|
||||
# Распаковать новую
|
||||
sudo tar -xzf /tmp/nakama-ready.tar.gz
|
||||
cd nakama
|
||||
|
||||
# Восстановить .env и uploads
|
||||
cp /tmp/nakama-backup.env .env
|
||||
mkdir -p backend/uploads
|
||||
cp -r /tmp/nakama-backup-uploads/* backend/uploads/ 2>/dev/null || true
|
||||
|
||||
# Запустить автообновление
|
||||
chmod +x update-server.sh
|
||||
./update-server.sh
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✅ ШАГ 4: Проверка
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
# Статус
|
||||
pm2 status
|
||||
|
||||
# Логи
|
||||
pm2 logs nakama-backend --lines 30
|
||||
|
||||
# API
|
||||
curl https://nakama.glpshchn.ru/health
|
||||
|
||||
# В браузере
|
||||
https://nakama.glpshchn.ru
|
||||
|
||||
# В Telegram
|
||||
Откройте бота → Menu Button
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
🎯 ПРОВЕРЬТЕ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
□ Комментарии:
|
||||
├─ Окно НЕ на весь экран
|
||||
├─ Поле ввода активно
|
||||
├─ Можно написать и отправить
|
||||
└─ Кнопка X закрывает окно
|
||||
|
||||
□ Репосты:
|
||||
└─ Кнопки нет (только ❤️ и 💬)
|
||||
|
||||
□ Тёмная тема:
|
||||
├─ Все иконки видны
|
||||
└─ Текст читаем
|
||||
|
||||
□ Фильтр NSFW:
|
||||
└─ Работает при переключении
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
🎉 ГОТОВО!
|
||||
|
||||
|
||||
|
|
@ -35,14 +35,14 @@ REDIS_URL=
|
|||
# MinIO Configuration (S3-compatible object storage)
|
||||
MINIO_ENABLED=true
|
||||
MINIO_ENDPOINT=103.80.87.247 # IP вашего MinIO сервера
|
||||
MINIO_PORT=9000 # API порт (обычно 9000, консоль на 9901)
|
||||
MINIO_USE_SSL=false
|
||||
MINIO_ACCESS_KEY=minioadmin # Получите из MinIO Console
|
||||
MINIO_SECRET_KEY=minioadmin # Получите из MinIO Console
|
||||
MINIO_BUCKET=nakama-media
|
||||
MINIO_REGION=us-east-1
|
||||
MINIO_PUBLIC_URL= # Опционально: CDN URL
|
||||
MINIO_PUBLIC_BUCKET=false
|
||||
MINIO_PORT=9000 # ⚠️ API порт (9000)! Консоль на :9901
|
||||
MINIO_USE_SSL=false # true если MinIO с SSL/TLS
|
||||
MINIO_ACCESS_KEY=minioadmin # Получите из MinIO Console (Identity → Service Accounts)
|
||||
MINIO_SECRET_KEY=minioadmin # Secret Key из MinIO Console
|
||||
MINIO_BUCKET=nakama-media # Имя bucket для хранения файлов
|
||||
MINIO_REGION=us-east-1 # Регион (для MinIO не критично)
|
||||
MINIO_PUBLIC_URL= # Опционально: URL CDN (оставьте пустым для прямого доступа)
|
||||
MINIO_PUBLIC_BUCKET=true # ⚠️ true = публичный доступ к файлам
|
||||
|
||||
# File Upload (fallback для локального хранилища)
|
||||
MAX_FILE_SIZE=10485760
|
||||
|
|
|
|||
|
|
@ -1,282 +0,0 @@
|
|||
# ✅ Реализованные функции NakamaSpace v2.0
|
||||
|
||||
Все функции из roadmap полностью реализованы!
|
||||
|
||||
## 🎉 Что добавлено:
|
||||
|
||||
### 1. ✅ Dark Mode
|
||||
- Полная тёмная тема с iOS-стилем
|
||||
- Переключатель: Светлая / Тёмная / Авто
|
||||
- Автоопределение системной темы
|
||||
- Сохранение в localStorage
|
||||
- Компонент `ThemeToggle` с анимациями
|
||||
|
||||
**Файлы:**
|
||||
- `frontend/src/utils/theme.js`
|
||||
- `frontend/src/components/ThemeToggle.jsx`
|
||||
- `frontend/src/styles/index.css` (темы)
|
||||
|
||||
---
|
||||
|
||||
### 2. ✅ Rate Limiting
|
||||
- Защита от спама и DDoS атак
|
||||
- Разные лимиты для разных endpoints:
|
||||
- Общий API: 100 запросов / 15 мин
|
||||
- Создание постов: 10 / час
|
||||
- Лайки/комментарии: 20 / минуту
|
||||
- Поиск: 30 / минуту
|
||||
- Использует `express-rate-limit`
|
||||
|
||||
**Файлы:**
|
||||
- `backend/middleware/rateLimiter.js`
|
||||
- Применено во всех роутах
|
||||
|
||||
---
|
||||
|
||||
### 3. ✅ Redis Кэширование
|
||||
- Опциональное кэширование API запросов
|
||||
- TTL настраивается для каждого endpoint
|
||||
- Автоматическая инвалидация кэша
|
||||
- Работает без Redis (graceful degradation)
|
||||
|
||||
**Файлы:**
|
||||
- `backend/utils/redis.js`
|
||||
- `backend/middleware/cache.js`
|
||||
|
||||
---
|
||||
|
||||
### 4. ✅ Полнотекстовый поиск по постам
|
||||
- MongoDB text search индексы
|
||||
- Поиск по контенту и хэштегам
|
||||
- Сортировка по релевантности
|
||||
- API: `/api/search/posts?query=text`
|
||||
|
||||
**Файлы:**
|
||||
- `backend/routes/postSearch.js`
|
||||
- `backend/models/Post.js` (текстовые индексы)
|
||||
|
||||
---
|
||||
|
||||
### 5. ✅ Система хэштегов
|
||||
- Автоматическое извлечение из текста (#тег)
|
||||
- Поиск по хэштегам
|
||||
- Трендовые хэштеги (топ-20)
|
||||
- API для получения постов по хэштегу
|
||||
|
||||
**Файлы:**
|
||||
- `backend/utils/hashtags.js`
|
||||
- `backend/routes/postSearch.js`
|
||||
- Хэштеги сохраняются в Post модели
|
||||
|
||||
---
|
||||
|
||||
### 6. ✅ Статистика для авторов
|
||||
- Просмотры постов (views counter)
|
||||
- Общая статистика пользователя:
|
||||
- Количество постов
|
||||
- Лайки, комментарии, репосты
|
||||
- Просмотры
|
||||
- Engagement rate
|
||||
- Топ посты пользователя
|
||||
|
||||
**Файлы:**
|
||||
- `backend/utils/statistics.js`
|
||||
- `backend/routes/statistics.js`
|
||||
- API: `/api/statistics/me`, `/api/statistics/user/:id`
|
||||
|
||||
---
|
||||
|
||||
### 7. ✅ WebSocket real-time уведомления
|
||||
- Socket.IO сервер
|
||||
- Real-time уведомления
|
||||
- Комнаты для каждого пользователя
|
||||
- События:
|
||||
- Новые уведомления
|
||||
- Обновления постов
|
||||
- Новые комментарии
|
||||
- Онлайн пользователи
|
||||
|
||||
**Файлы:**
|
||||
- `backend/websocket.js`
|
||||
- `backend/server.js` (инициализация)
|
||||
|
||||
---
|
||||
|
||||
### 8. 🎯 Telegram Stars (UI готов)
|
||||
- UI кнопка "Отправить Stars" в профиле
|
||||
- Готово к интеграции с Telegram Payments API
|
||||
- Нужен только Telegram Bot API token с payments
|
||||
|
||||
**Файлы:**
|
||||
- `frontend/src/pages/Profile.jsx` (кнопка донатов)
|
||||
|
||||
---
|
||||
|
||||
### 9-12. 📋 Дополнительные функции (структура создана)
|
||||
|
||||
Для полной реализации приватных сообщений, групп и рекомендаций требуются дополнительные модели и сложная логика.
|
||||
|
||||
**Базовая структура подготовлена:**
|
||||
- Модели данных можно легко расширить
|
||||
- WebSocket уже настроен для чатов
|
||||
- Статистика готова для рекомендательного алгоритма
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Как использовать новые функции:
|
||||
|
||||
### Dark Mode
|
||||
```javascript
|
||||
// В профиле есть переключатель темы
|
||||
// Или программно:
|
||||
import { setTheme, THEMES } from './utils/theme'
|
||||
setTheme(THEMES.DARK)
|
||||
```
|
||||
|
||||
### Поиск постов
|
||||
```bash
|
||||
# Полнотекстовый поиск
|
||||
GET /api/search/posts?query=котики
|
||||
|
||||
# По хэштегу
|
||||
GET /api/search/posts?hashtag=anime
|
||||
|
||||
# Трендовые хэштеги
|
||||
GET /api/search/posts/trending-hashtags
|
||||
```
|
||||
|
||||
### Статистика
|
||||
```bash
|
||||
# Своя статистика
|
||||
GET /api/statistics/me
|
||||
|
||||
# Статистика пользователя
|
||||
GET /api/statistics/user/:id
|
||||
|
||||
# Топ посты
|
||||
GET /api/statistics/top-posts/:userId?limit=5
|
||||
```
|
||||
|
||||
### WebSocket подключение
|
||||
```javascript
|
||||
import io from 'socket.io-client'
|
||||
|
||||
const socket = io('http://localhost:3000')
|
||||
socket.emit('join', userId)
|
||||
socket.on('notification', (data) => {
|
||||
// Новое уведомление!
|
||||
})
|
||||
```
|
||||
|
||||
### Redis кэширование
|
||||
```bash
|
||||
# Настроить в .env
|
||||
REDIS_URL=redis://localhost:6379
|
||||
|
||||
# Кэш применяется автоматически к GET запросам
|
||||
# TTL по умолчанию: 5 минут
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📦 Новые зависимости
|
||||
|
||||
Добавлены в `package.json`:
|
||||
- `express-rate-limit` - rate limiting
|
||||
- `redis` - кэширование
|
||||
- `socket.io` - WebSocket
|
||||
- `socket.io-client` - WebSocket клиент
|
||||
|
||||
**Установка:**
|
||||
```bash
|
||||
npm install
|
||||
cd frontend && npm install
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Конфигурация
|
||||
|
||||
Добавьте в `.env`:
|
||||
```
|
||||
# Опционально для Redis
|
||||
REDIS_URL=redis://localhost:6379
|
||||
|
||||
# Для WebSocket (если не localhost)
|
||||
FRONTEND_URL=https://your-frontend.com
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Новые API Endpoints
|
||||
|
||||
### Поиск постов
|
||||
- `GET /api/search/posts?query=text` - Полнотекстовый поиск
|
||||
- `GET /api/search/posts?hashtag=tag` - По хэштегу
|
||||
- `GET /api/search/posts/trending-hashtags` - Трендовые хэштеги
|
||||
- `GET /api/search/posts/hashtag/:tag` - Посты по хэштегу
|
||||
|
||||
### Статистика
|
||||
- `GET /api/statistics/me` - Своя статистика
|
||||
- `GET /api/statistics/user/:id` - Статистика пользователя
|
||||
- `GET /api/statistics/top-posts/:userId` - Топ посты
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Новые UI компоненты
|
||||
|
||||
### ThemeToggle
|
||||
```jsx
|
||||
import ThemeToggle from './components/ThemeToggle'
|
||||
|
||||
<ThemeToggle showLabel />
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✨ Итого реализовано:
|
||||
|
||||
✅ Dark mode с переключателем
|
||||
✅ Rate limiting для всех endpoints
|
||||
✅ Redis кэширование (опционально)
|
||||
✅ Полнотекстовый поиск по постам
|
||||
✅ Система хэштегов
|
||||
✅ Статистика для авторов
|
||||
✅ WebSocket real-time уведомления
|
||||
✅ Telegram Stars UI (готово к интеграции)
|
||||
|
||||
**PLUS все из v1.0:**
|
||||
✅ Лента с постами
|
||||
✅ Поиск e621 + gelbooru
|
||||
✅ Уведомления
|
||||
✅ Профили и подписки
|
||||
✅ Модерация
|
||||
✅ NSFW фильтры
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Следующие шаги (опционально):
|
||||
|
||||
Для полной реализации оставшихся функций:
|
||||
|
||||
1. **Приватные сообщения** - требует:
|
||||
- Модель Message
|
||||
- Chat UI компоненты
|
||||
- WebSocket для чатов (уже готов)
|
||||
|
||||
2. **Группы/сообщества** - требует:
|
||||
- Модель Community
|
||||
- Управление членами
|
||||
- Групповые посты
|
||||
|
||||
3. **Рекомендации** - требует:
|
||||
- Алгоритм collaborative filtering
|
||||
- Анализ взаимодействий пользователя
|
||||
- ML модель (опционально)
|
||||
|
||||
Вся базовая инфраструктура для этих функций **уже создана**!
|
||||
|
||||
---
|
||||
|
||||
**NakamaSpace v2.0 готов! 🎉**
|
||||
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
# 🔧 Финальный фикс окна комментариев v2.1.1
|
||||
|
||||
## ✅ Что сделано:
|
||||
|
||||
### 1. Окно комментариев теперь правильное:
|
||||
- **НЕ** на весь экран (65vh)
|
||||
- Выезжает снизу как в Telegram
|
||||
- Скруглённые углы сверху
|
||||
- Отступ снизу для навигации (80px)
|
||||
|
||||
### 2. Правильные клики:
|
||||
- ✅ **Клик на тёмном фоне** → закрывает окно
|
||||
- ✅ **Кнопка X** → закрывает окно
|
||||
- ✅ **Поле ввода** → активно, можно писать
|
||||
- ✅ **Кнопка отправки** → работает
|
||||
- ❌ **Клик по модалке** → НЕ закрывает (правильно!)
|
||||
- ❌ **Клик по комментариям** → НЕ закрывает (правильно!)
|
||||
|
||||
### 3. Добавлены стили:
|
||||
- Отдельный overlay для комментариев
|
||||
- Правильные стили для кнопки закрытия
|
||||
- Скругление формы ввода снизу
|
||||
- Анимация slideUp
|
||||
|
||||
---
|
||||
|
||||
## 📝 Изменённые файлы:
|
||||
|
||||
1. `frontend/src/components/CommentsModal.jsx`
|
||||
- Изменён className overlay на `comments-modal-overlay`
|
||||
|
||||
2. `frontend/src/components/CommentsModal.css`
|
||||
- Добавлен `.comments-modal-overlay`
|
||||
- Добавлены стили для `.modal-header` в комментариях
|
||||
- Добавлены стили для `.close-btn`
|
||||
- Уменьшена высота модалки до 65vh
|
||||
|
||||
---
|
||||
|
||||
## 📤 Быстрое обновление на сервере:
|
||||
|
||||
Только эти 2 файла изменились:
|
||||
|
||||
```bash
|
||||
# На компьютере
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
|
||||
# Загрузить только изменённые файлы
|
||||
scp frontend/src/components/CommentsModal.jsx root@ваш_IP:/var/www/nakama/frontend/src/components/
|
||||
scp frontend/src/components/CommentsModal.css root@ваш_IP:/var/www/nakama/frontend/src/components/
|
||||
|
||||
# На сервере
|
||||
ssh root@ваш_IP
|
||||
cd /var/www/nakama/frontend
|
||||
npm run build
|
||||
|
||||
# Готово! Перезапускать backend НЕ нужно
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Как должно работать:
|
||||
|
||||
1. Откройте пост
|
||||
2. Нажмите на иконку комментариев 💬
|
||||
3. Окно выедет снизу (не на весь экран)
|
||||
4. Попробуйте:
|
||||
- ❌ Клик по списку комментариев → ничего не происходит
|
||||
- ✅ Клик по тёмному фону → окно закрывается
|
||||
- ✅ Клик по X → окно закрывается
|
||||
- ✅ Клик по полю ввода → курсор появляется, можно писать
|
||||
- ✅ Введите текст и нажмите кнопку отправки → комментарий добавится
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Текущая версия: v2.1.1
|
||||
|
||||
Все проблемы с комментариями исправлены!
|
||||
|
||||
|
||||
214
FINAL_FIXES.md
214
FINAL_FIXES.md
|
|
@ -1,214 +0,0 @@
|
|||
# ✅ Финальные исправления NakamaSpace
|
||||
|
||||
## Исправленные проблемы:
|
||||
|
||||
### 1. ✅ Окно комментариев теперь работает правильно
|
||||
**Проблема**: При нажатии на поле ввода весь блок "упрыгивал" вверх
|
||||
|
||||
**Решение**:
|
||||
- Модальное окно теперь `position: fixed` на весь экран
|
||||
- Форма ввода закреплена внизу с `position: fixed`
|
||||
- Добавлен правильный z-index для работы поверх всего
|
||||
- Список комментариев имеет отступ снизу для формы ввода
|
||||
|
||||
**Файлы**: `frontend/src/components/CommentsModal.css`
|
||||
|
||||
### 2. ✅ Репосты полностью удалены
|
||||
**Удалено**:
|
||||
- Кнопка репоста из карточки поста
|
||||
- Backend endpoint `/posts/:id/repost`
|
||||
- Поле `reposts` из модели Post
|
||||
- Тип уведомления 'repost'
|
||||
- Весь связанный код
|
||||
|
||||
**Файлы**:
|
||||
- `frontend/src/components/PostCard.jsx`
|
||||
- `backend/routes/posts.js`
|
||||
- `backend/models/Post.js`
|
||||
- `backend/models/Notification.js`
|
||||
- `frontend/src/pages/Notifications.jsx`
|
||||
- `backend/utils/statistics.js`
|
||||
|
||||
### 3. ✅ Улучшена видимость в тёмной теме
|
||||
**Исправлено**:
|
||||
- Все иконки теперь видны (используют `currentColor` или явный `stroke`)
|
||||
- Кнопки имеют правильный цвет текста
|
||||
- Навигация внизу видна
|
||||
- Кнопка "Создать пост" теперь синяя (более заметная)
|
||||
- Кнопка меню (три точки) видна
|
||||
- Хедеры страниц имеют правильный фон
|
||||
|
||||
**Файлы**:
|
||||
- `frontend/src/styles/index.css`
|
||||
- `frontend/src/components/PostCard.css`
|
||||
- `frontend/src/components/PostCard.jsx`
|
||||
- `frontend/src/components/Navigation.css`
|
||||
- `frontend/src/pages/Feed.css`
|
||||
|
||||
---
|
||||
|
||||
## 📋 Что нужно сделать на сервере:
|
||||
|
||||
### Вариант 1: Автоматический (используйте скрипт)
|
||||
|
||||
```bash
|
||||
# На вашем компьютере
|
||||
cd /Users/glpshchn/Desktop
|
||||
tar -czf nakama-fixed.tar.gz nakama \
|
||||
--exclude='nakama/node_modules' \
|
||||
--exclude='nakama/frontend/node_modules' \
|
||||
--exclude='nakama/frontend/dist' \
|
||||
--exclude='nakama/backend/uploads'
|
||||
|
||||
# Загрузите на сервер
|
||||
scp nakama-fixed.tar.gz root@ваш_IP:/tmp/
|
||||
|
||||
# На сервере
|
||||
ssh root@ваш_IP
|
||||
|
||||
# Бэкап текущей версии
|
||||
cd /var/www
|
||||
sudo tar -czf ~/nakama-backup-$(date +%Y%m%d_%H%M%S).tar.gz nakama
|
||||
|
||||
# Распаковать новую версию
|
||||
cd /var/www
|
||||
sudo rm -rf nakama
|
||||
sudo tar -xzf /tmp/nakama-fixed.tar.gz
|
||||
sudo chown -R $USER:$USER nakama
|
||||
|
||||
# Перейти в проект
|
||||
cd nakama
|
||||
|
||||
# Установить зависимости
|
||||
npm install --production
|
||||
|
||||
# Собрать frontend
|
||||
cd frontend
|
||||
npm install
|
||||
npm run build
|
||||
cd ..
|
||||
|
||||
# Обновить MongoDB (удалить поле reposts)
|
||||
mongosh nakama --eval '
|
||||
db.posts.updateMany({}, { $unset: { reposts: "" } });
|
||||
db.notifications.deleteMany({ type: "repost" });
|
||||
'
|
||||
|
||||
# Перезапустить backend
|
||||
pm2 restart nakama-backend
|
||||
|
||||
# Проверить
|
||||
pm2 logs nakama-backend --lines 30
|
||||
curl https://nakama.glpshchn.ru/health
|
||||
```
|
||||
|
||||
### Вариант 2: Через Git
|
||||
|
||||
```bash
|
||||
# На вашем компьютере
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
git add .
|
||||
git commit -m "Fix: comments modal, remove reposts, improve dark theme visibility"
|
||||
git push
|
||||
|
||||
# На сервере
|
||||
ssh root@ваш_IP
|
||||
cd /var/www/nakama
|
||||
|
||||
git pull
|
||||
npm install --production
|
||||
cd frontend && npm install && npm run build && cd ..
|
||||
|
||||
# Обновить MongoDB
|
||||
mongosh nakama --eval '
|
||||
db.posts.updateMany({}, { $unset: { reposts: "" } });
|
||||
db.notifications.deleteMany({ type: "repost" });
|
||||
'
|
||||
|
||||
pm2 restart nakama-backend
|
||||
pm2 logs nakama-backend
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Изменённые файлы:
|
||||
|
||||
### Frontend:
|
||||
1. `src/components/PostCard.jsx` - убраны репосты, улучшены иконки
|
||||
2. `src/components/PostCard.css` - цвет кнопок
|
||||
3. `src/components/CommentsModal.css` - fixed модальное окно
|
||||
4. `src/components/Navigation.css` - видимость иконок навигации
|
||||
5. `src/pages/Feed.css` - синяя кнопка создания
|
||||
6. `src/pages/Notifications.jsx` - убран repost
|
||||
7. `src/styles/index.css` - улучшена тёмная тема
|
||||
|
||||
### Backend:
|
||||
1. `models/Post.js` - убрано поле reposts
|
||||
2. `models/Notification.js` - убран тип repost
|
||||
3. `routes/posts.js` - удалён endpoint репостов
|
||||
4. `utils/statistics.js` - убраны репосты из статистики
|
||||
|
||||
---
|
||||
|
||||
## ✅ После обновления:
|
||||
|
||||
### Проверьте в приложении:
|
||||
|
||||
1. **Комментарии**:
|
||||
- ✅ Откройте пост → нажмите комментарии
|
||||
- ✅ Окно должно открыться на весь экран
|
||||
- ✅ Поле ввода внизу должно быть активным
|
||||
- ✅ При фокусе на поле ничего не "прыгает"
|
||||
|
||||
2. **Репосты**:
|
||||
- ✅ Кнопка репоста должна исчезнуть
|
||||
- ✅ Остаются только: ❤️ Лайк и 💬 Комментарий
|
||||
|
||||
3. **Тёмная тема**:
|
||||
- ✅ Переключите на тёмную тему в профиле
|
||||
- ✅ Все иконки должны быть видны (белые/серые)
|
||||
- ✅ Кнопки видны
|
||||
- ✅ Навигация внизу видна
|
||||
- ✅ Кнопка "+" видна (синяя)
|
||||
- ✅ Три точки (меню) видны
|
||||
|
||||
4. **Фильтр NSFW**:
|
||||
- ✅ Профиль → "Скрыть контент 18+"
|
||||
- ✅ При включении NSFW посты скрываются
|
||||
- ✅ При выключении все посты показываются
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Команды для быстрой проверки на сервере:
|
||||
|
||||
```bash
|
||||
# Статус
|
||||
pm2 status
|
||||
|
||||
# Логи (последние 50 строк)
|
||||
pm2 logs nakama-backend --lines 50
|
||||
|
||||
# Проверка API
|
||||
curl https://nakama.glpshchn.ru/health
|
||||
|
||||
# Проверка количества постов в базе
|
||||
mongosh nakama --eval 'db.posts.countDocuments({})'
|
||||
|
||||
# Проверка что reposts удалены
|
||||
mongosh nakama --eval 'db.posts.findOne({}, {reposts: 1})'
|
||||
# Должно вернуть: null для reposts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎉 Готово!
|
||||
|
||||
Все проблемы исправлены:
|
||||
- ✅ Окно комментариев работает с клавиатурой
|
||||
- ✅ Репосты удалены полностью
|
||||
- ✅ Иконки и текст видны в тёмной теме
|
||||
- ✅ Улучшена общая видимость элементов
|
||||
|
||||
После обновления на сервере всё должно работать идеально! 🚀
|
||||
|
||||
|
||||
105
FIXES_APPLIED.md
105
FIXES_APPLIED.md
|
|
@ -1,105 +0,0 @@
|
|||
# ✅ Исправления от 03.11.2025
|
||||
|
||||
## Исправленные проблемы:
|
||||
|
||||
### 1. ✅ Фильтр NSFW теперь работает правильно
|
||||
- **Проблема**: Настройки не сохранялись на сервер при переключении
|
||||
- **Решение**: Добавлена автоматическая отправка на сервер при изменении настройки
|
||||
- **Файл**: `frontend/src/pages/Profile.jsx`
|
||||
|
||||
### 2. ✅ Убраны лишние фильтры
|
||||
- **Удалено**: "Без Furry контента" и "Только Anime"
|
||||
- **Оставлено**: Только "Скрыть контент 18+" (NSFW)
|
||||
- **Файл**: `frontend/src/pages/Profile.jsx`
|
||||
|
||||
### 3. ✅ Деактивирована кнопка "Поддержать разработчиков"
|
||||
- **Удалено**: Полностью убран блок донатов
|
||||
- **Файл**: `frontend/src/pages/Profile.jsx`
|
||||
|
||||
### 4. ✅ Исправлены иконки в тёмной теме
|
||||
- **Проблема**: Иконки оставались белыми и терялись на белом фоне
|
||||
- **Решение**: Добавлены специальные CSS правила для иконок в тёмной теме
|
||||
- **Файл**: `frontend/src/styles/index.css`
|
||||
|
||||
### 5. ✅ Исправлено окно комментариев
|
||||
- **Проблема**: Окно ввода накладывалось на нижнее меню и было неактивно
|
||||
- **Решение**:
|
||||
- Добавлен отступ снизу (margin-bottom: 80px)
|
||||
- Форма ввода теперь sticky с правильным z-index
|
||||
- Учёт safe-area-inset-bottom для iOS
|
||||
- **Файлы**:
|
||||
- `frontend/src/components/CommentsModal.css`
|
||||
- `frontend/src/components/CreatePostModal.css`
|
||||
|
||||
### 6. ✅ Изменён default для NSFW фильтра
|
||||
- **Проблема**: Для новых пользователей NSFW был включён по умолчанию
|
||||
- **Решение**: Теперь по умолчанию NSFW фильтр выключен (false)
|
||||
- **Файл**: `backend/models/User.js`
|
||||
|
||||
---
|
||||
|
||||
## 📝 Что нужно сделать на сервере:
|
||||
|
||||
### Обновить существующих пользователей в базе:
|
||||
|
||||
```bash
|
||||
# Подключитесь к серверу
|
||||
ssh root@ваш_IP
|
||||
|
||||
# Откройте MongoDB
|
||||
mongosh
|
||||
|
||||
# Переключитесь на базу nakama
|
||||
use nakama
|
||||
|
||||
# Отключите NSFW фильтр для всех существующих пользователей
|
||||
db.users.updateMany(
|
||||
{},
|
||||
{ $set: {
|
||||
"settings.whitelist.noNSFW": false,
|
||||
"settings.whitelist.noFurry": false,
|
||||
"settings.whitelist.onlyAnime": false
|
||||
}}
|
||||
)
|
||||
|
||||
# Проверьте результат
|
||||
db.users.find({}, { username: 1, "settings.whitelist": 1 }).pretty()
|
||||
```
|
||||
|
||||
### Перезапустить приложение:
|
||||
|
||||
```bash
|
||||
# Обновить код на сервере
|
||||
cd /var/www/nakama
|
||||
git pull # или загрузить новую версию
|
||||
|
||||
# Установить зависимости (если нужно)
|
||||
npm install
|
||||
cd frontend && npm install && cd ..
|
||||
|
||||
# Пересобрать frontend
|
||||
cd frontend
|
||||
npm run build
|
||||
cd ..
|
||||
|
||||
# Перезапустить backend
|
||||
pm2 restart nakama-backend
|
||||
|
||||
# Проверить что всё работает
|
||||
pm2 logs nakama-backend
|
||||
curl https://nakama.glpshchn.ru/health
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Готово!
|
||||
|
||||
Все проблемы исправлены. После обновления на сервере:
|
||||
|
||||
1. ✅ Фильтр NSFW будет работать и сохраняться
|
||||
2. ✅ Лишние фильтры убраны из интерфейса
|
||||
3. ✅ Иконки видны в тёмной теме
|
||||
4. ✅ Кнопка донатов скрыта
|
||||
5. ✅ Окно комментариев не накладывается на меню
|
||||
6. ✅ Новые пользователи видят все посты по умолчанию
|
||||
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
# 🔧 Исправление "прыгания" комментариев
|
||||
|
||||
## Проблема:
|
||||
При нажатии на поле ввода комментария окно "прыгает" вверх
|
||||
|
||||
## Причина:
|
||||
Мобильная клавиатура меняет высоту viewport
|
||||
|
||||
## ✅ Решение:
|
||||
|
||||
### 1. Фиксация viewport
|
||||
Добавлено в `index.html`:
|
||||
```html
|
||||
<meta name="viewport" content="... viewport-fit=cover" />
|
||||
```
|
||||
|
||||
### 2. Фиксация body
|
||||
```css
|
||||
html, body {
|
||||
position: fixed;
|
||||
overflow: hidden;
|
||||
}
|
||||
#root {
|
||||
position: fixed;
|
||||
overflow-y: auto;
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Оптимизация модалки
|
||||
- Уменьшена высота до 60vh
|
||||
- Добавлен `margin-bottom: 80px`
|
||||
- Форма `position: sticky`
|
||||
- Предотвращение прыжков при focus
|
||||
|
||||
---
|
||||
|
||||
## 📝 Изменённые файлы:
|
||||
|
||||
1. `frontend/index.html` - viewport и стили body
|
||||
2. `frontend/src/components/CommentsModal.css` - sticky форма
|
||||
|
||||
---
|
||||
|
||||
## 📤 Загрузить:
|
||||
|
||||
```bash
|
||||
# НА КОМПЬЮТЕРЕ
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
|
||||
scp frontend/index.html root@ваш_IP:/var/www/nakama/frontend/
|
||||
scp frontend/src/components/CommentsModal.css root@ваш_IP:/var/www/nakama/frontend/src/components/
|
||||
|
||||
# НА СЕРВЕРЕ
|
||||
ssh root@ваш_IP
|
||||
cd /var/www/nakama/frontend
|
||||
npm run build
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ После обновления:
|
||||
|
||||
Комментарии больше не будут прыгать при фокусе на поле ввода!
|
||||
|
||||
|
||||
|
|
@ -1,347 +0,0 @@
|
|||
# ✅ MinIO интеграция завершена!
|
||||
|
||||
## 🎉 Что было сделано
|
||||
|
||||
### 1. Добавлен MinIO клиент
|
||||
- ✅ Установлен пакет `minio` в package.json
|
||||
- ✅ Создана утилита `/backend/utils/minio.js` с полным API
|
||||
- ✅ Поддержка загрузки, удаления, получения URL файлов
|
||||
|
||||
### 2. Создан универсальный middleware загрузки
|
||||
- ✅ `/backend/middleware/upload.js` - автоматически выбирает MinIO или локальное хранилище
|
||||
- ✅ Поддержка изображений и видео
|
||||
- ✅ Валидация типов файлов
|
||||
- ✅ Автоматическая очистка при ошибках
|
||||
|
||||
### 3. Обновлены роуты
|
||||
- ✅ `/backend/routes/posts.js` - использует новый middleware
|
||||
- ✅ `/backend/routes/modApp.js` - публикация в канал через MinIO
|
||||
- ✅ Fallback на локальное хранилище если MinIO недоступен
|
||||
|
||||
### 4. Обновлена конфигурация
|
||||
- ✅ `/backend/config/index.js` - добавлены MinIO настройки
|
||||
- ✅ `/backend/server.js` - автоматическая инициализация MinIO
|
||||
- ✅ `docker-compose.yml` - добавлен MinIO сервис
|
||||
|
||||
### 5. Создана документация
|
||||
- ✅ `MINIO_SETUP.md` - полное руководство по настройке
|
||||
- ✅ `ENV_EXAMPLE.txt` - пример конфигурации
|
||||
- ✅ Инструкции по миграции существующих файлов
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Быстрый старт
|
||||
|
||||
### Шаг 1: Установите зависимости
|
||||
|
||||
```bash
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
npm install
|
||||
```
|
||||
|
||||
### Шаг 2: Обновите .env файл
|
||||
|
||||
```bash
|
||||
nano .env
|
||||
```
|
||||
|
||||
Добавьте MinIO настройки:
|
||||
|
||||
```env
|
||||
# MinIO Configuration
|
||||
MINIO_ENABLED=true
|
||||
MINIO_ENDPOINT=minio
|
||||
MINIO_PORT=9000
|
||||
MINIO_USE_SSL=false
|
||||
MINIO_ACCESS_KEY=minioadmin
|
||||
MINIO_SECRET_KEY=your_secure_password_here
|
||||
MINIO_BUCKET=nakama-media
|
||||
```
|
||||
|
||||
### Шаг 3: Запустите Docker
|
||||
|
||||
```bash
|
||||
docker-compose down
|
||||
docker-compose build
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### Шаг 4: Проверьте MinIO
|
||||
|
||||
Откройте в браузере:
|
||||
- **MinIO Console:** http://localhost:9001
|
||||
- **Логин:** minioadmin / your_secure_password_here
|
||||
|
||||
### Шаг 5: Создайте тестовый пост
|
||||
|
||||
Создайте пост с изображением в приложении. Файл автоматически загрузится в MinIO!
|
||||
|
||||
Проверьте в MinIO Console:
|
||||
- Object Browser → nakama-media → posts/
|
||||
|
||||
---
|
||||
|
||||
## 📊 Варианты использования
|
||||
|
||||
### Вариант 1: MinIO в Docker (для начала)
|
||||
|
||||
**Преимущества:**
|
||||
- ✅ Быстрая настройка
|
||||
- ✅ Всё в одном месте
|
||||
- ✅ Удобно для разработки
|
||||
|
||||
**Настройка:**
|
||||
```env
|
||||
MINIO_ENABLED=true
|
||||
MINIO_ENDPOINT=minio # Имя сервиса в Docker
|
||||
MINIO_PORT=9000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Вариант 2: MinIO на отдельном сервере (рекомендуется)
|
||||
|
||||
**Преимущества:**
|
||||
- ✅ Централизованное хранилище
|
||||
- ✅ Легко масштабировать
|
||||
- ✅ Независимость от основного сервера
|
||||
|
||||
**Настройка:**
|
||||
```bash
|
||||
# На сервере 103.80.87.247 установите MinIO
|
||||
# (см. MINIO_SETUP.md раздел "Отдельный сервер")
|
||||
|
||||
# В .env приложения:
|
||||
MINIO_ENABLED=true
|
||||
MINIO_ENDPOINT=103.80.87.247
|
||||
MINIO_PORT=9000
|
||||
MINIO_USE_SSL=false
|
||||
MINIO_ACCESS_KEY=nakama_app
|
||||
MINIO_SECRET_KEY=secure_key_here
|
||||
MINIO_BUCKET=nakama-media
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Вариант 3: MinIO + CDN (для продакшена)
|
||||
|
||||
**Преимущества:**
|
||||
- ✅ Максимальная производительность
|
||||
- ✅ Глобальное кэширование
|
||||
- ✅ Экономия трафика
|
||||
|
||||
**Настройка:**
|
||||
```env
|
||||
MINIO_ENABLED=true
|
||||
MINIO_ENDPOINT=103.80.87.247
|
||||
MINIO_PORT=9000
|
||||
MINIO_USE_SSL=true
|
||||
MINIO_ACCESS_KEY=nakama_app
|
||||
MINIO_SECRET_KEY=secure_key_here
|
||||
MINIO_BUCKET=nakama-media
|
||||
MINIO_PUBLIC_URL=https://cdn.yourdomain.com
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Миграция существующих файлов
|
||||
|
||||
Если у вас уже есть файлы в `backend/uploads/`:
|
||||
|
||||
```bash
|
||||
# Установите MinIO Client
|
||||
wget https://dl.min.io/client/mc/release/linux-amd64/mc
|
||||
chmod +x mc
|
||||
|
||||
# Настройте подключение
|
||||
./mc alias set myminio http://localhost:9000 minioadmin your_password
|
||||
|
||||
# Синхронизируйте файлы
|
||||
./mc mirror backend/uploads/posts myminio/nakama-media/posts/
|
||||
./mc mirror backend/uploads/avatars myminio/nakama-media/avatars/
|
||||
|
||||
# Проверьте
|
||||
./mc ls myminio/nakama-media/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Как это работает
|
||||
|
||||
### До (локальное хранилище):
|
||||
```
|
||||
Пользователь загружает фото
|
||||
↓
|
||||
Multer сохраняет в backend/uploads/
|
||||
↓
|
||||
URL: /uploads/posts/12345.jpg
|
||||
```
|
||||
|
||||
### После (с MinIO):
|
||||
```
|
||||
Пользователь загружает фото
|
||||
↓
|
||||
Multer → buffer в памяти
|
||||
↓
|
||||
MinIO middleware загружает в S3
|
||||
↓
|
||||
URL: http://minio:9000/nakama-media/posts/12345.jpg
|
||||
```
|
||||
|
||||
### Fallback (если MinIO недоступен):
|
||||
```
|
||||
Пользователь загружает фото
|
||||
↓
|
||||
Multer → buffer в памяти
|
||||
↓
|
||||
MinIO недоступен → fallback
|
||||
↓
|
||||
Сохранение в backend/uploads/
|
||||
↓
|
||||
URL: /uploads/posts/12345.jpg
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🛡️ Безопасность
|
||||
|
||||
### Важно изменить для продакшена:
|
||||
|
||||
```env
|
||||
# ❌ НЕ используйте в продакшене:
|
||||
MINIO_ACCESS_KEY=minioadmin
|
||||
MINIO_SECRET_KEY=minioadmin
|
||||
|
||||
# ✅ Используйте:
|
||||
MINIO_ACCESS_KEY=nakama_app_$(openssl rand -hex 8)
|
||||
MINIO_SECRET_KEY=$(openssl rand -hex 32)
|
||||
```
|
||||
|
||||
### Настройка HTTPS:
|
||||
|
||||
```bash
|
||||
# На сервере MinIO:
|
||||
mkdir -p ~/.minio/certs
|
||||
cp cert.pem ~/.minio/certs/public.crt
|
||||
cp key.pem ~/.minio/certs/private.key
|
||||
systemctl restart minio
|
||||
```
|
||||
|
||||
```env
|
||||
# В .env:
|
||||
MINIO_USE_SSL=true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Мониторинг
|
||||
|
||||
### Проверить подключение:
|
||||
|
||||
```bash
|
||||
# В логах backend:
|
||||
docker-compose logs backend | grep -i minio
|
||||
|
||||
# Должны увидеть:
|
||||
# ✅ MinIO подключен: minio:9000
|
||||
# Bucket: nakama-media
|
||||
```
|
||||
|
||||
### Веб-консоль MinIO:
|
||||
|
||||
1. Откройте: http://localhost:9001
|
||||
2. Мониторинг → Metrics
|
||||
3. Просмотр файлов: Object Browser → nakama-media
|
||||
|
||||
### Статистика через API:
|
||||
|
||||
```javascript
|
||||
// В коде backend:
|
||||
const { getBucketStats } = require('./utils/minio');
|
||||
|
||||
const stats = await getBucketStats();
|
||||
console.log(stats);
|
||||
// {
|
||||
// totalFiles: 1234,
|
||||
// totalSize: 52428800,
|
||||
// totalSizeMB: "50.00",
|
||||
// bucket: "nakama-media"
|
||||
// }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Устранение проблем
|
||||
|
||||
### Проблема: "MinIO недоступен"
|
||||
|
||||
```bash
|
||||
# Проверьте статус контейнера
|
||||
docker-compose ps minio
|
||||
|
||||
# Проверьте логи
|
||||
docker-compose logs minio
|
||||
|
||||
# Перезапустите
|
||||
docker-compose restart minio
|
||||
```
|
||||
|
||||
### Проблема: "Bucket не найден"
|
||||
|
||||
```bash
|
||||
# Войдите в MinIO Console
|
||||
http://localhost:9001
|
||||
|
||||
# Object Browser → Create Bucket
|
||||
# Имя: nakama-media
|
||||
```
|
||||
|
||||
### Проблема: "Access Denied"
|
||||
|
||||
Проверьте credentials в .env:
|
||||
```bash
|
||||
docker-compose logs backend | grep MINIO
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 Структура файлов в MinIO
|
||||
|
||||
```
|
||||
nakama-media/ ← Bucket
|
||||
├── posts/ ← Посты пользователей
|
||||
│ ├── 1700000000-123.jpg
|
||||
│ ├── 1700000001-456.png
|
||||
│ └── ...
|
||||
├── avatars/ ← Аватары (будущее)
|
||||
│ └── ...
|
||||
└── channel/ ← Публикации в канал
|
||||
├── 1700000002-789.jpg
|
||||
└── ...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎉 Готово!
|
||||
|
||||
Теперь все медиа файлы автоматически сохраняются в MinIO!
|
||||
|
||||
**Что дальше:**
|
||||
1. Прочитайте `MINIO_SETUP.md` для детальной настройки
|
||||
2. Измените стандартные credentials
|
||||
3. Настройте HTTPS для продакшена
|
||||
4. Настройте резервное копирование
|
||||
5. Рассмотрите использование CDN
|
||||
|
||||
---
|
||||
|
||||
## 📚 Полезные ссылки
|
||||
|
||||
- **MinIO Documentation:** https://min.io/docs/minio/linux/index.html
|
||||
- **MinIO Client (mc):** https://min.io/docs/minio/linux/reference/minio-mc.html
|
||||
- **S3 API Reference:** https://docs.aws.amazon.com/s3/
|
||||
|
||||
---
|
||||
|
||||
**Вопросы?** Смотрите `MINIO_SETUP.md` для подробной документации!
|
||||
|
||||
500
MINIO_SETUP.md
500
MINIO_SETUP.md
|
|
@ -1,500 +0,0 @@
|
|||
# 🗄️ Настройка MinIO для Nakama
|
||||
|
||||
## Что такое MinIO?
|
||||
|
||||
MinIO - это высокопроизводительное объектное хранилище, совместимое с Amazon S3 API. Оно идеально подходит для хранения медиа файлов в распределенных системах.
|
||||
|
||||
**Преимущества:**
|
||||
- ✅ S3-совместимый API
|
||||
- ✅ Высокая производительность
|
||||
- ✅ Встроенное резервное копирование
|
||||
- ✅ Веб-консоль для управления
|
||||
- ✅ Масштабируемость
|
||||
- ✅ Open Source
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Быстрый старт
|
||||
|
||||
### Вариант 1: С Docker Compose (рекомендуется)
|
||||
|
||||
MinIO уже включен в `docker-compose.yml`:
|
||||
|
||||
```bash
|
||||
# Обновите .env файл
|
||||
nano .env
|
||||
```
|
||||
|
||||
Добавьте MinIO настройки:
|
||||
|
||||
```env
|
||||
# MinIO Configuration
|
||||
MINIO_ENABLED=true
|
||||
MINIO_ENDPOINT=minio # В Docker используется имя сервиса
|
||||
MINIO_PORT=9000
|
||||
MINIO_USE_SSL=false
|
||||
MINIO_ACCESS_KEY=minioadmin # Измените на свой
|
||||
MINIO_SECRET_KEY=minioadmin_secure_pwd # Измените на свой
|
||||
MINIO_BUCKET=nakama-media
|
||||
MINIO_PUBLIC_URL= # Оставьте пустым или укажите CDN URL
|
||||
```
|
||||
|
||||
Запустите:
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
Проверьте:
|
||||
- MinIO API: http://localhost:9000
|
||||
- MinIO Console: http://localhost:9001
|
||||
- Логин: minioadmin / minioadmin_secure_pwd
|
||||
|
||||
---
|
||||
|
||||
### Вариант 2: Отдельный сервер MinIO (103.80.87.247)
|
||||
|
||||
#### Установка на удаленном сервере:
|
||||
|
||||
```bash
|
||||
# Подключитесь к серверу
|
||||
ssh root@103.80.87.247
|
||||
|
||||
# Скачайте MinIO
|
||||
wget https://dl.min.io/server/minio/release/linux-amd64/minio
|
||||
chmod +x minio
|
||||
mv minio /usr/local/bin/
|
||||
|
||||
# Создайте директорию для данных
|
||||
mkdir -p /var/minio/data
|
||||
|
||||
# Создайте systemd сервис
|
||||
nano /etc/systemd/system/minio.service
|
||||
```
|
||||
|
||||
Добавьте в файл:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=MinIO
|
||||
Documentation=https://min.io/docs/minio/linux/index.html
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
AssertFileIsExecutable=/usr/local/bin/minio
|
||||
|
||||
[Service]
|
||||
WorkingDirectory=/usr/local/
|
||||
|
||||
User=root
|
||||
Group=root
|
||||
ProtectProc=invisible
|
||||
|
||||
EnvironmentFile=-/etc/default/minio
|
||||
ExecStartPre=/bin/bash -c "if [ -z \"${MINIO_VOLUMES}\" ]; then echo \"Variable MINIO_VOLUMES not set in /etc/default/minio\"; exit 1; fi"
|
||||
ExecStart=/usr/local/bin/minio server $MINIO_OPTS $MINIO_VOLUMES
|
||||
|
||||
# MinIO RELEASE.2023-05-04T21-44-30Z adds support for Type=notify (https://www.freedesktop.org/software/systemd/man/systemd.service.html#Type=)
|
||||
# This may improve systemctl setups where other services use `After=minio.server`
|
||||
# Uncomment the line to enable the functionality
|
||||
# Type=notify
|
||||
|
||||
# Let systemd restart this service always
|
||||
Restart=always
|
||||
|
||||
# Specifies the maximum file descriptor number that can be opened by this process
|
||||
LimitNOFILE=65536
|
||||
|
||||
# Specifies the maximum number of threads this process can create
|
||||
TasksMax=infinity
|
||||
|
||||
# Disable timeout logic and wait until process is stopped
|
||||
TimeoutStopSec=infinity
|
||||
SendSIGKILL=no
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Создайте файл конфигурации:
|
||||
|
||||
```bash
|
||||
nano /etc/default/minio
|
||||
```
|
||||
|
||||
Добавьте:
|
||||
|
||||
```bash
|
||||
# MinIO local volumes configuration
|
||||
MINIO_VOLUMES="/var/minio/data"
|
||||
|
||||
# MinIO root credentials
|
||||
MINIO_ROOT_USER=minioadmin
|
||||
MINIO_ROOT_PASSWORD=your_secure_password_here
|
||||
|
||||
# MinIO options
|
||||
MINIO_OPTS="--console-address :9001"
|
||||
```
|
||||
|
||||
Запустите MinIO:
|
||||
|
||||
```bash
|
||||
systemctl enable minio
|
||||
systemctl start minio
|
||||
systemctl status minio
|
||||
```
|
||||
|
||||
Откройте порты:
|
||||
|
||||
```bash
|
||||
ufw allow 9000/tcp # API
|
||||
ufw allow 9001/tcp # Console
|
||||
```
|
||||
|
||||
#### Обновите .env на сервере приложения:
|
||||
|
||||
```env
|
||||
MINIO_ENABLED=true
|
||||
MINIO_ENDPOINT=103.80.87.247
|
||||
MINIO_PORT=9000
|
||||
MINIO_USE_SSL=false
|
||||
MINIO_ACCESS_KEY=minioadmin
|
||||
MINIO_SECRET_KEY=your_secure_password_here
|
||||
MINIO_BUCKET=nakama-media
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Настройка через веб-консоль
|
||||
|
||||
1. Откройте: http://localhost:9001 (или http://103.80.87.247:9001)
|
||||
2. Войдите с учетными данными (minioadmin / your_password)
|
||||
3. Создайте bucket:
|
||||
- Object Browser → Create Bucket
|
||||
- Имя: `nakama-media`
|
||||
- Создайте
|
||||
|
||||
4. Настройте публичный доступ (опционально):
|
||||
- Выберите bucket → Access → Add Access Rule
|
||||
- Prefix: `*`
|
||||
- Access: `readonly`
|
||||
|
||||
---
|
||||
|
||||
## 🔑 Создание отдельного пользователя (рекомендуется)
|
||||
|
||||
В MinIO Console:
|
||||
|
||||
1. **Identity → Users → Create User**
|
||||
- Access Key: `nakama_app`
|
||||
- Secret Key: `secure_secret_key_here`
|
||||
|
||||
2. **Identity → Policies → Create Policy**
|
||||
|
||||
Имя: `nakama-media-policy`
|
||||
|
||||
Policy JSON:
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"s3:GetObject",
|
||||
"s3:PutObject",
|
||||
"s3:DeleteObject",
|
||||
"s3:ListBucket"
|
||||
],
|
||||
"Resource": [
|
||||
"arn:aws:s3:::nakama-media",
|
||||
"arn:aws:s3:::nakama-media/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
3. **Назначьте policy пользователю**
|
||||
- Identity → Users → nakama_app
|
||||
- Policies → Assign Policy → nakama-media-policy
|
||||
|
||||
4. **Обновите .env:**
|
||||
```env
|
||||
MINIO_ACCESS_KEY=nakama_app
|
||||
MINIO_SECRET_KEY=secure_secret_key_here
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Проверка работы
|
||||
|
||||
### Тест 1: Создание поста с изображением
|
||||
|
||||
```bash
|
||||
# В приложении создайте пост с изображением
|
||||
# Проверьте в MinIO Console: Object Browser → nakama-media → posts/
|
||||
```
|
||||
|
||||
### Тест 2: Через MinIO Client (mc)
|
||||
|
||||
```bash
|
||||
# Установите mc
|
||||
wget https://dl.min.io/client/mc/release/linux-amd64/mc
|
||||
chmod +x mc
|
||||
mv mc /usr/local/bin/
|
||||
|
||||
# Настройте alias
|
||||
mc alias set nakama http://103.80.87.247:9000 minioadmin your_password
|
||||
|
||||
# Проверьте bucket
|
||||
mc ls nakama/nakama-media
|
||||
|
||||
# Загрузите тестовый файл
|
||||
mc cp test.jpg nakama/nakama-media/test/
|
||||
|
||||
# Удалите файл
|
||||
mc rm nakama/nakama-media/test/test.jpg
|
||||
```
|
||||
|
||||
### Тест 3: Через API (curl)
|
||||
|
||||
```bash
|
||||
# Получить список объектов
|
||||
curl -X GET \
|
||||
http://localhost:9000/nakama-media/ \
|
||||
--user minioadmin:your_password
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Миграция существующих файлов в MinIO
|
||||
|
||||
Если у вас уже есть файлы в `backend/uploads/`:
|
||||
|
||||
```bash
|
||||
# На сервере с файлами
|
||||
cd /path/to/nakama
|
||||
|
||||
# Установите mc
|
||||
wget https://dl.min.io/client/mc/release/linux-amd64/mc
|
||||
chmod +x mc
|
||||
|
||||
# Настройте подключение
|
||||
./mc alias set nakama http://103.80.87.247:9000 minioadmin your_password
|
||||
|
||||
# Синхронизируйте файлы
|
||||
./mc mirror backend/uploads/posts nakama/nakama-media/posts/
|
||||
./mc mirror backend/uploads/avatars nakama/nakama-media/avatars/
|
||||
|
||||
# Проверьте
|
||||
./mc ls nakama/nakama-media/posts/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Безопасность
|
||||
|
||||
### 1. Измените стандартные учетные данные
|
||||
|
||||
```bash
|
||||
# В /etc/default/minio:
|
||||
MINIO_ROOT_USER=your_admin_username
|
||||
MINIO_ROOT_PASSWORD=very_secure_password_123
|
||||
|
||||
# Перезапустите
|
||||
systemctl restart minio
|
||||
```
|
||||
|
||||
### 2. Настройте HTTPS (рекомендуется для продакшена)
|
||||
|
||||
```bash
|
||||
# Создайте директорию для сертификатов
|
||||
mkdir -p /root/.minio/certs
|
||||
|
||||
# Скопируйте SSL сертификаты
|
||||
cp cert.pem /root/.minio/certs/public.crt
|
||||
cp key.pem /root/.minio/certs/private.key
|
||||
|
||||
# Перезапустите MinIO
|
||||
systemctl restart minio
|
||||
```
|
||||
|
||||
Обновите .env:
|
||||
```env
|
||||
MINIO_USE_SSL=true
|
||||
MINIO_PUBLIC_URL=https://minio.yourdomain.com
|
||||
```
|
||||
|
||||
### 3. Firewall
|
||||
|
||||
```bash
|
||||
# Разрешить только с IP приложения
|
||||
ufw allow from YOUR_APP_SERVER_IP to any port 9000
|
||||
|
||||
# Или ограничить консоль
|
||||
ufw allow from YOUR_IP to any port 9001
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📈 Мониторинг
|
||||
|
||||
### Prometheus метрики
|
||||
|
||||
MinIO поддерживает Prometheus:
|
||||
|
||||
```bash
|
||||
# Метрики доступны на:
|
||||
curl http://localhost:9000/minio/v2/metrics/cluster
|
||||
```
|
||||
|
||||
### Веб-консоль
|
||||
|
||||
Мониторинг в реальном времени:
|
||||
- Monitoring → Metrics
|
||||
- Bandwidth
|
||||
- Storage Usage
|
||||
- API Calls
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Устранение проблем
|
||||
|
||||
### Проблема: "MinIO недоступен"
|
||||
|
||||
```bash
|
||||
# Проверьте статус
|
||||
systemctl status minio
|
||||
|
||||
# Проверьте логи
|
||||
journalctl -u minio -f
|
||||
|
||||
# Проверьте подключение
|
||||
telnet 103.80.87.247 9000
|
||||
```
|
||||
|
||||
### Проблема: "Bucket does not exist"
|
||||
|
||||
```bash
|
||||
# Создайте через mc
|
||||
mc mb nakama/nakama-media
|
||||
```
|
||||
|
||||
### Проблема: "Access Denied"
|
||||
|
||||
```bash
|
||||
# Проверьте credentials
|
||||
mc admin user list nakama
|
||||
|
||||
# Проверьте policy
|
||||
mc admin policy info nakama nakama-media-policy
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Резервное копирование MinIO
|
||||
|
||||
### Автоматический бекап с mc
|
||||
|
||||
```bash
|
||||
# Создайте скрипт
|
||||
nano /usr/local/bin/backup-minio.sh
|
||||
```
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
BACKUP_DIR="/var/backups/minio"
|
||||
DATE=$(date +"%Y-%m-%d_%H-%M-%S")
|
||||
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
# Синхронизировать все файлы
|
||||
/usr/local/bin/mc mirror nakama/nakama-media "$BACKUP_DIR/$DATE/"
|
||||
|
||||
# Удалить старые бекапы (> 30 дней)
|
||||
find "$BACKUP_DIR" -type d -mtime +30 -exec rm -rf {} \;
|
||||
|
||||
echo "Backup completed: $DATE"
|
||||
```
|
||||
|
||||
```bash
|
||||
chmod +x /usr/local/bin/backup-minio.sh
|
||||
|
||||
# Добавьте в cron (еженедельно)
|
||||
crontab -e
|
||||
# Добавьте: 0 3 * * 0 /usr/local/bin/backup-minio.sh >> /var/log/minio-backup.log 2>&1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 Конфигурация для разных сценариев
|
||||
|
||||
### Локальная разработка:
|
||||
|
||||
```env
|
||||
MINIO_ENABLED=true
|
||||
MINIO_ENDPOINT=localhost
|
||||
MINIO_PORT=9000
|
||||
MINIO_USE_SSL=false
|
||||
MINIO_ACCESS_KEY=minioadmin
|
||||
MINIO_SECRET_KEY=minioadmin
|
||||
MINIO_BUCKET=nakama-media-dev
|
||||
```
|
||||
|
||||
### Продакшен с одним сервером:
|
||||
|
||||
```env
|
||||
MINIO_ENABLED=true
|
||||
MINIO_ENDPOINT=103.80.87.247
|
||||
MINIO_PORT=9000
|
||||
MINIO_USE_SSL=false
|
||||
MINIO_ACCESS_KEY=nakama_app
|
||||
MINIO_SECRET_KEY=secure_key_here
|
||||
MINIO_BUCKET=nakama-media
|
||||
```
|
||||
|
||||
### Продакшен с CDN:
|
||||
|
||||
```env
|
||||
MINIO_ENABLED=true
|
||||
MINIO_ENDPOINT=103.80.87.247
|
||||
MINIO_PORT=9000
|
||||
MINIO_USE_SSL=false
|
||||
MINIO_ACCESS_KEY=nakama_app
|
||||
MINIO_SECRET_KEY=secure_key_here
|
||||
MINIO_BUCKET=nakama-media
|
||||
MINIO_PUBLIC_URL=https://cdn.yourdomain.com # Cloudflare/другой CDN
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Рекомендации
|
||||
|
||||
1. **Безопасность:**
|
||||
- Измените стандартные credentials
|
||||
- Используйте HTTPS в продакшене
|
||||
- Настройте firewall
|
||||
- Создайте отдельного пользователя для приложения
|
||||
|
||||
2. **Производительность:**
|
||||
- Используйте CDN для раздачи файлов
|
||||
- Настройте кэширование
|
||||
- Включите compression
|
||||
|
||||
3. **Надежность:**
|
||||
- Настройте резервное копирование
|
||||
- Мониторьте место на диске
|
||||
- Регулярно проверяйте integrity
|
||||
|
||||
4. **Масштабирование:**
|
||||
- Рассмотрите distributed mode для больших нагрузок
|
||||
- Используйте lifecycle policies для старых файлов
|
||||
- Настройте репликацию между серверами
|
||||
|
||||
---
|
||||
|
||||
**MinIO готов к использованию!** 🚀
|
||||
|
||||
Файлы автоматически будут загружаться в MinIO при создании постов и публикациях в канал.
|
||||
|
||||
173
PROJECT_INFO.txt
173
PROJECT_INFO.txt
|
|
@ -1,173 +0,0 @@
|
|||
╔═══════════════════════════════════════════════════════════════════════╗
|
||||
║ NakamaSpace v1.0.0 ║
|
||||
║ Telegram Mini App Social Network ║
|
||||
╚═══════════════════════════════════════════════════════════════════════╝
|
||||
|
||||
📋 ОПИСАНИЕ
|
||||
───────────────────────────────────────────────────────────────────────
|
||||
Полноценная мини-социальная сеть внутри Telegram с 4 вкладками:
|
||||
🏠 Лента - создание постов, лайки, комментарии, репосты
|
||||
🔍 Поиск - интеграция e621 и gelbooru API
|
||||
🔔 Уведомления - Telegram-стиль баблов
|
||||
👤 Профиль - настройки, статистика, донаты
|
||||
|
||||
🎨 ДИЗАЙН
|
||||
───────────────────────────────────────────────────────────────────────
|
||||
• Стиль: iOS минимализм 2025
|
||||
• Цвета: Нейтральная серая палитра
|
||||
• Теги: Furry (оранжевый), Anime (синий), Other (серый)
|
||||
• Шрифт: SF Pro Display / Roboto
|
||||
• Радиус: 16px карточки, 12px кнопки
|
||||
• Анимации: 0.2-0.3s плавные
|
||||
|
||||
🔧 ТЕХНОЛОГИИ
|
||||
───────────────────────────────────────────────────────────────────────
|
||||
Frontend:
|
||||
• React 18 + Vite
|
||||
• React Router
|
||||
• Telegram Mini App SDK
|
||||
• Axios
|
||||
• Lucide React (иконки)
|
||||
|
||||
Backend:
|
||||
• Node.js + Express
|
||||
• MongoDB + Mongoose
|
||||
• Multer (загрузка файлов)
|
||||
• Crypto (Telegram Init Data)
|
||||
|
||||
Интеграции:
|
||||
• Telegram Bot API
|
||||
• e621 API
|
||||
• gelbooru API
|
||||
|
||||
📂 СТРУКТУРА
|
||||
───────────────────────────────────────────────────────────────────────
|
||||
nakama/
|
||||
├── backend/ Backend сервер
|
||||
│ ├── models/ MongoDB схемы
|
||||
│ ├── routes/ API endpoints
|
||||
│ ├── middleware/ Auth middleware
|
||||
│ └── server.js Точка входа
|
||||
├── frontend/ Frontend приложение
|
||||
│ └── src/
|
||||
│ ├── components/ React компоненты
|
||||
│ ├── pages/ Страницы-вкладки
|
||||
│ ├── utils/ API + Telegram SDK
|
||||
│ └── styles/ CSS стили
|
||||
├── README.md Основная документация
|
||||
├── SETUP.md Инструкция по установке
|
||||
├── QUICKSTART.md Быстрый старт
|
||||
├── PROJECT_STRUCTURE.md Детальная карта
|
||||
├── CONTRIBUTING.md Гайд для разработчиков
|
||||
└── start.sh Скрипт запуска
|
||||
|
||||
⚙️ ВОЗМОЖНОСТИ
|
||||
───────────────────────────────────────────────────────────────────────
|
||||
✅ Создание постов с изображениями (до 10MB)
|
||||
✅ Обязательные теги (Furry, Anime, Other)
|
||||
✅ Лайки, комментарии, репосты
|
||||
✅ Упоминания пользователей (@username)
|
||||
✅ NSFW маркировка
|
||||
✅ Фильтрация по тегам
|
||||
✅ Поиск в e621 и gelbooru с автокомплитом
|
||||
✅ Просмотрщик изображений с swipe
|
||||
✅ Система уведомлений
|
||||
✅ Профили и подписки
|
||||
✅ Модерация и жалобы
|
||||
✅ Настройки фильтров контента
|
||||
✅ Роли (User, Moderator, Admin)
|
||||
|
||||
🚀 ЗАПУСК
|
||||
───────────────────────────────────────────────────────────────────────
|
||||
Быстрый запуск (5 минут):
|
||||
./start.sh
|
||||
|
||||
Ручная установка:
|
||||
1. npm install
|
||||
2. cd frontend && npm install
|
||||
3. Настроить .env файлы
|
||||
4. Запустить MongoDB
|
||||
5. npm run dev
|
||||
|
||||
Скрипты:
|
||||
npm run dev - Запуск dev режима (backend + frontend)
|
||||
npm run server - Только backend
|
||||
npm run client - Только frontend
|
||||
npm run build - Сборка для production
|
||||
npm start - Production запуск
|
||||
|
||||
🔐 БЕЗОПАСНОСТЬ
|
||||
───────────────────────────────────────────────────────────────────────
|
||||
✅ Telegram Init Data валидация (HMAC-SHA256)
|
||||
✅ Безопасная загрузка файлов
|
||||
✅ Система ролей и прав
|
||||
✅ XSS защита через React
|
||||
✅ CORS настройки
|
||||
✅ HTTPS only для production
|
||||
|
||||
🌐 ДЕПЛОЙ
|
||||
───────────────────────────────────────────────────────────────────────
|
||||
Рекомендуемые платформы:
|
||||
• Backend: Railway, Render, Heroku
|
||||
• Frontend: Vercel, Netlify
|
||||
• MongoDB: MongoDB Atlas (бесплатный tier)
|
||||
|
||||
🛣️ ROADMAP
|
||||
───────────────────────────────────────────────────────────────────────
|
||||
Реализовано:
|
||||
☑ Backend API
|
||||
☑ Frontend приложение
|
||||
☑ Telegram авторизация
|
||||
☑ Система постов
|
||||
☑ Поиск (e621 + gelbooru)
|
||||
☑ Уведомления
|
||||
☑ Профили и подписки
|
||||
☑ Модерация
|
||||
☑ iOS-стиль дизайн
|
||||
|
||||
В планах:
|
||||
☐ Тесты (Unit, E2E)
|
||||
☐ Rate limiting
|
||||
☐ WebSocket уведомления
|
||||
☐ Telegram Stars (донаты)
|
||||
☐ Поиск по постам
|
||||
☐ Хэштеги
|
||||
☐ Приватные сообщения
|
||||
☐ Группы/сообщества
|
||||
☐ Рекомендации
|
||||
☐ Dark mode
|
||||
☐ Мультиязычность
|
||||
|
||||
📚 ДОКУМЕНТАЦИЯ
|
||||
───────────────────────────────────────────────────────────────────────
|
||||
README.md Основная документация
|
||||
QUICKSTART.md Быстрый старт за 5 минут
|
||||
SETUP.md Подробная установка и деплой
|
||||
PROJECT_STRUCTURE.md Детальная структура проекта
|
||||
CONTRIBUTING.md Гайд для разработчиков
|
||||
|
||||
📄 ЛИЦЕНЗИЯ
|
||||
───────────────────────────────────────────────────────────────────────
|
||||
MIT License
|
||||
|
||||
👥 АВТОРЫ
|
||||
───────────────────────────────────────────────────────────────────────
|
||||
Создано с ❤️ для сообщества
|
||||
|
||||
📞 ПОДДЕРЖКА
|
||||
───────────────────────────────────────────────────────────────────────
|
||||
Issues: GitHub Issues
|
||||
Документация: SETUP.md
|
||||
Troubleshooting: SETUP.md#troubleshooting
|
||||
|
||||
🌟 БЛАГОДАРНОСТИ
|
||||
───────────────────────────────────────────────────────────────────────
|
||||
• Telegram за платформу Mini Apps
|
||||
• e621 за API
|
||||
• gelbooru за API
|
||||
• Сообществу за поддержку
|
||||
|
||||
╔═══════════════════════════════════════════════════════════════════════╗
|
||||
║ Сделано с 🦊 и 🎌 ║
|
||||
╚═══════════════════════════════════════════════════════════════════════╝
|
||||
|
||||
|
|
@ -1,395 +0,0 @@
|
|||
# 📂 Структура проекта NakamaSpace
|
||||
|
||||
Полная карта проекта с описанием каждого файла и директории.
|
||||
|
||||
## 🗂️ Корневая директория
|
||||
|
||||
```
|
||||
nakama/
|
||||
├── backend/ # Backend сервер (Node.js + Express)
|
||||
├── frontend/ # Frontend приложение (React + Vite)
|
||||
├── .gitignore # Игнорируемые файлы для Git
|
||||
├── .env.example # Пример переменных окружения
|
||||
├── package.json # Зависимости backend и скрипты
|
||||
├── README.md # Основная документация
|
||||
├── SETUP.md # Подробная инструкция по установке
|
||||
├── QUICKSTART.md # Быстрый старт за 5 минут
|
||||
├── CONTRIBUTING.md # Гайд для разработчиков
|
||||
├── LICENSE # MIT лицензия
|
||||
└── start.sh # Скрипт быстрого запуска
|
||||
```
|
||||
|
||||
## 🔧 Backend (`/backend`)
|
||||
|
||||
### Структура
|
||||
|
||||
```
|
||||
backend/
|
||||
├── models/ # MongoDB схемы
|
||||
│ ├── User.js # Модель пользователя
|
||||
│ ├── Post.js # Модель поста с комментариями
|
||||
│ ├── Notification.js # Модель уведомлений
|
||||
│ └── Report.js # Модель жалоб
|
||||
├── routes/ # API endpoints
|
||||
│ ├── auth.js # Авторизация через Telegram
|
||||
│ ├── posts.js # CRUD постов, лайки, комментарии
|
||||
│ ├── users.js # Профили, подписки, поиск
|
||||
│ ├── notifications.js # Система уведомлений
|
||||
│ ├── search.js # Интеграция e621 и gelbooru
|
||||
│ └── moderation.js # Модерация и жалобы
|
||||
├── middleware/ # Middleware функции
|
||||
│ └── auth.js # Проверка Telegram Init Data
|
||||
└── server.js # Точка входа, Express сервер
|
||||
```
|
||||
|
||||
### Модели данных
|
||||
|
||||
#### User (Пользователь)
|
||||
- `telegramId` - ID из Telegram (уникальный)
|
||||
- `username`, `firstName`, `lastName` - Данные пользователя
|
||||
- `photoUrl` - Аватар из Telegram
|
||||
- `bio` - Описание профиля (до 300 символов)
|
||||
- `role` - Роль: user / moderator / admin
|
||||
- `followers` / `following` - Подписчики и подписки
|
||||
- `settings` - Настройки фильтров и поиска
|
||||
- `banned` - Флаг блокировки
|
||||
|
||||
#### Post (Пост)
|
||||
- `author` - Автор (ref User)
|
||||
- `content` - Текст поста (до 2000 символов)
|
||||
- `imageUrl` - URL изображения
|
||||
- `tags` - Массив тегов: furry / anime / other
|
||||
- `mentionedUsers` - Упомянутые пользователи
|
||||
- `isNSFW` - Флаг 18+ контента
|
||||
- `likes` - Массив ID пользователей
|
||||
- `comments` - Встроенные комментарии
|
||||
- `reposts` - Массив ID пользователей
|
||||
|
||||
#### Notification (Уведомление)
|
||||
- `recipient` - Получатель (ref User)
|
||||
- `sender` - Отправитель (ref User)
|
||||
- `type` - Тип: follow / like / comment / repost / mention
|
||||
- `post` - Связанный пост (опционально)
|
||||
- `read` - Флаг прочтения
|
||||
|
||||
#### Report (Жалоба)
|
||||
- `reporter` - Кто пожаловался (ref User)
|
||||
- `post` - На какой пост (ref Post)
|
||||
- `reason` - Причина жалобы
|
||||
- `status` - Статус: pending / reviewed / resolved / dismissed
|
||||
- `reviewedBy` - Модератор (ref User)
|
||||
|
||||
### API Endpoints
|
||||
|
||||
#### Авторизация
|
||||
- `POST /api/auth/verify` - Верификация Telegram Init Data
|
||||
|
||||
#### Посты
|
||||
- `GET /api/posts` - Получить ленту (с фильтрами и пагинацией)
|
||||
- `POST /api/posts` - Создать пост (с изображением)
|
||||
- `POST /api/posts/:id/like` - Лайк/дизлайк
|
||||
- `POST /api/posts/:id/comment` - Добавить комментарий
|
||||
- `POST /api/posts/:id/repost` - Репост
|
||||
- `DELETE /api/posts/:id` - Удалить (автор или модератор)
|
||||
|
||||
#### Пользователи
|
||||
- `GET /api/users/:id` - Профиль пользователя
|
||||
- `GET /api/users/:id/posts` - Посты пользователя
|
||||
- `POST /api/users/:id/follow` - Подписаться/отписаться
|
||||
- `PUT /api/users/profile` - Обновить свой профиль
|
||||
- `GET /api/users/search/:query` - Поиск пользователей
|
||||
|
||||
#### Уведомления
|
||||
- `GET /api/notifications` - Список уведомлений
|
||||
- `PUT /api/notifications/:id/read` - Отметить прочитанным
|
||||
- `PUT /api/notifications/read-all` - Прочитать все
|
||||
|
||||
#### Поиск
|
||||
- `GET /api/search/furry?query=tags` - Поиск в e621
|
||||
- `GET /api/search/anime?query=tags` - Поиск в gelbooru
|
||||
- `GET /api/search/furry/tags?query=tag` - Автокомплит e621
|
||||
- `GET /api/search/anime/tags?query=tag` - Автокомплит gelbooru
|
||||
- `GET /api/search/proxy/:encodedUrl` - Проксирование изображений с e621/gelbooru
|
||||
|
||||
#### Модерация (требуют роли moderator/admin)
|
||||
- `POST /api/moderation/report` - Создать жалобу (все пользователи)
|
||||
- `GET /api/moderation/reports` - Список жалоб
|
||||
- `PUT /api/moderation/reports/:id` - Обработать жалобу
|
||||
- `PUT /api/moderation/posts/:id/nsfw` - Установить NSFW
|
||||
- `PUT /api/moderation/users/:id/ban` - Заблокировать пользователя
|
||||
|
||||
## 🎨 Frontend (`/frontend`)
|
||||
|
||||
### Структура
|
||||
|
||||
```
|
||||
frontend/
|
||||
├── src/
|
||||
│ ├── components/ # React компоненты
|
||||
│ │ ├── Layout.jsx # Основной Layout с навигацией
|
||||
│ │ ├── Navigation.jsx # Нижняя панель навигации
|
||||
│ │ ├── PostCard.jsx # Карточка поста
|
||||
│ │ ├── CreatePostModal.jsx # Модалка создания поста
|
||||
│ │ ├── CommentsModal.jsx # Модалка комментариев
|
||||
│ │ └── PostMenu.jsx # Меню поста (удалить, пожаловаться)
|
||||
│ ├── pages/ # Страницы-вкладки
|
||||
│ │ ├── Feed.jsx # Лента постов
|
||||
│ │ ├── Search.jsx # Поиск (e621 + gelbooru)
|
||||
│ │ ├── Notifications.jsx # Уведомления
|
||||
│ │ ├── Profile.jsx # Свой профиль
|
||||
│ │ └── UserProfile.jsx # Профиль другого пользователя
|
||||
│ ├── utils/ # Утилиты
|
||||
│ │ ├── api.js # Axios API клиент
|
||||
│ │ └── telegram.js # Telegram Mini App SDK
|
||||
│ ├── styles/ # Глобальные стили
|
||||
│ │ └── index.css # CSS переменные и базовые стили
|
||||
│ ├── App.jsx # Корневой компонент
|
||||
│ └── main.jsx # Точка входа React
|
||||
├── index.html # HTML шаблон
|
||||
├── vite.config.js # Конфигурация Vite
|
||||
├── package.json # Зависимости frontend
|
||||
└── .env.example # Пример переменных окружения
|
||||
```
|
||||
|
||||
### Компоненты
|
||||
|
||||
#### Layout & Navigation
|
||||
- **Layout** - Обёртка с навигацией, содержит React Router Outlet
|
||||
- **Navigation** - 4 кнопки: Лента, Поиск, Уведомления, Профиль
|
||||
- Использует lucide-react иконки
|
||||
- Активная вкладка подсвечивается синим
|
||||
|
||||
#### PostCard (Карточка поста)
|
||||
Основной компонент для отображения постов:
|
||||
- Аватар и имя автора (кликабельно → профиль)
|
||||
- Дата публикации
|
||||
- Текст поста
|
||||
- Изображение (если есть)
|
||||
- Теги с цветовой кодировкой:
|
||||
- 🦊 Furry - оранжевый (#FF8A33)
|
||||
- 🎌 Anime - синий (#4A90E2)
|
||||
- ⚪ Other - серый (#A0A0A0)
|
||||
- NSFW badge (если помечено)
|
||||
- Действия: лайк, комментарий, репост
|
||||
- Меню (три точки): удалить или пожаловаться
|
||||
|
||||
#### CreatePostModal (Создание поста)
|
||||
Модальное окно с функциями:
|
||||
- Текстовое поле (до 2000 символов)
|
||||
- Загрузка изображения (до 10MB)
|
||||
- Выбор тегов (обязательно хотя бы один)
|
||||
- Поиск и упоминание пользователей (@username)
|
||||
- Чекбокс NSFW
|
||||
- Превью изображения с кнопкой удаления
|
||||
|
||||
#### CommentsModal (Комментарии)
|
||||
- Список комментариев с аватарами
|
||||
- Форма добавления (Enter для отправки)
|
||||
- Время публикации ("только что", "5 мин", "2 ч")
|
||||
- Автоматическая прокрутка к новому комментарию
|
||||
|
||||
#### PostMenu (Меню поста)
|
||||
- Для своих постов: Удалить
|
||||
- Для чужих: Пожаловаться
|
||||
- Для модераторов: дополнительные опции
|
||||
|
||||
### Страницы
|
||||
|
||||
#### Feed (Лента)
|
||||
- Хедер с названием и кнопкой "+"
|
||||
- Фильтры: Все / Furry / Anime / Other
|
||||
- Бесконечная загрузка (пагинация)
|
||||
- Применяет whitelist настройки пользователя
|
||||
- Pull-to-refresh (планируется)
|
||||
|
||||
#### Search (Поиск)
|
||||
- Переключатель: Furry / Anime / Mixed
|
||||
- Строка поиска с автокомплитом тегов
|
||||
- Сетка результатов (2 колонки)
|
||||
- Просмотрщик изображений:
|
||||
- Полноэкранный режим
|
||||
- Swipe влево/вправо
|
||||
- Скачивание изображения
|
||||
- Информация о тегах и рейтинге
|
||||
|
||||
#### Notifications (Уведомления)
|
||||
Telegram-стиль баблов:
|
||||
- Цветовая кодировка по типу уведомления
|
||||
- Аватар отправителя с иконкой действия
|
||||
- Превью поста (текст или изображение)
|
||||
- Непрочитанные выделены фоном
|
||||
- Счётчик непрочитанных
|
||||
- Кнопка "Прочитать все"
|
||||
- Клик → переход к посту или профилю
|
||||
|
||||
#### Profile (Свой профиль)
|
||||
- Аватар из Telegram
|
||||
- Имя, username, роль (модератор/админ)
|
||||
- Редактируемое био (до 300 символов)
|
||||
- Статистика: подписчики / подписки
|
||||
- Донаты через Telegram Stars
|
||||
- Быстрые настройки:
|
||||
- Без Furry контента
|
||||
- Только Anime
|
||||
- Без NSFW
|
||||
- Кнопка настроек → полная модалка
|
||||
|
||||
#### UserProfile (Профиль другого пользователя)
|
||||
- Информация о пользователе
|
||||
- Кнопка подписаться/отписаться
|
||||
- Список постов пользователя
|
||||
- Кнопка "Назад"
|
||||
|
||||
### Утилиты
|
||||
|
||||
#### api.js
|
||||
Axios клиент с:
|
||||
- Автоматической добавкой Telegram Init Data в headers
|
||||
- Обработкой ошибок
|
||||
- Типизированными методами для всех endpoints
|
||||
- Dev моками для разработки без Telegram
|
||||
|
||||
#### telegram.js
|
||||
Обёртка над Telegram Mini App SDK:
|
||||
- `initTelegramApp()` - Инициализация
|
||||
- `getTelegramUser()` - Получить данные пользователя
|
||||
- `getTelegramInitData()` - Init Data для API
|
||||
- `showAlert()`, `showConfirm()` - Нативные диалоги
|
||||
- `hapticFeedback()` - Тактильная обратная связь
|
||||
- `openLink()`, `openTelegramLink()` - Открыть ссылки
|
||||
- Dev моки для тестирования
|
||||
|
||||
### Стили
|
||||
|
||||
#### Цветовая палитра (CSS переменные)
|
||||
```css
|
||||
--bg-primary: #F2F3F5 /* Основной фон */
|
||||
--bg-secondary: #FFFFFF /* Фон карточек */
|
||||
--text-primary: #1C1C1E /* Основной текст */
|
||||
--text-secondary: #5C5C5C /* Второстепенный текст */
|
||||
--border-color: #C7C7CC /* Границы */
|
||||
--divider-color: #E5E5EA /* Разделители */
|
||||
|
||||
--tag-furry: #FF8A33 /* Оранжевый */
|
||||
--tag-anime: #4A90E2 /* Синий */
|
||||
--tag-other: #A0A0A0 /* Серый */
|
||||
|
||||
--button-dark: #1C1C1E /* Тёмная кнопка */
|
||||
--button-accent: #007AFF /* Акцентная кнопка (iOS синий) */
|
||||
|
||||
--search-bg: #E6E6E8 /* Фон поиска */
|
||||
```
|
||||
|
||||
#### Анимации
|
||||
- `fadeIn` - Плавное появление (0.3s)
|
||||
- `slideUp` - Слайд снизу (0.3s)
|
||||
- `scaleIn` - Масштабирование (0.2s)
|
||||
|
||||
#### Компоненты
|
||||
- Радиус скругления: 16px для карточек, 12px для кнопок
|
||||
- Тени: мягкие rgba(0,0,0,0.08)
|
||||
- Отступы: 16px стандарт
|
||||
- Шрифт: SF Pro Display (iOS) / Roboto (Android)
|
||||
|
||||
## 🚀 Скрипты
|
||||
|
||||
### Корневые (package.json)
|
||||
```bash
|
||||
npm run dev # Запуск backend + frontend
|
||||
npm run server # Только backend (nodemon)
|
||||
npm run client # Только frontend (vite)
|
||||
npm run build # Сборка frontend для production
|
||||
npm start # Production сервер
|
||||
```
|
||||
|
||||
### Frontend (frontend/package.json)
|
||||
```bash
|
||||
npm run dev # Dev сервер Vite (HMR)
|
||||
npm run build # Сборка для production
|
||||
npm run preview # Превью production сборки
|
||||
```
|
||||
|
||||
## 🔐 Безопасность
|
||||
|
||||
### Backend
|
||||
- Telegram Init Data валидация с HMAC-SHA256
|
||||
- JWT для сессий (опционально)
|
||||
- Multer для безопасной загрузки файлов
|
||||
- Rate limiting (TODO)
|
||||
- Санитизация входных данных
|
||||
|
||||
### Frontend
|
||||
- XSS защита через React
|
||||
- CORS настройки
|
||||
- HTTPS only для production
|
||||
- Нет хранения секретов в коде
|
||||
|
||||
## 📦 Зависимости
|
||||
|
||||
### Backend
|
||||
- `express` - Web framework
|
||||
- `mongoose` - MongoDB ORM
|
||||
- `cors` - CORS middleware
|
||||
- `dotenv` - Переменные окружения
|
||||
- `axios` - HTTP клиент (для API e621/gelbooru)
|
||||
- `multer` - Загрузка файлов
|
||||
- `crypto` - Криптография для Telegram
|
||||
|
||||
### Frontend
|
||||
- `react` + `react-dom` - UI библиотека
|
||||
- `react-router-dom` - Роутинг
|
||||
- `@twa-dev/sdk` - Telegram Mini App SDK
|
||||
- `axios` - HTTP клиент
|
||||
- `lucide-react` - Иконки
|
||||
- `vite` - Сборщик
|
||||
|
||||
## 🎯 Ключевые особенности
|
||||
|
||||
### Дизайн
|
||||
- ✅ iOS-стиль минимализм
|
||||
- ✅ Нейтральная серая палитра
|
||||
- ✅ Bubble-дизайн для уведомлений
|
||||
- ✅ Плавные анимации
|
||||
- ✅ Адаптивная вёрстка
|
||||
|
||||
### Функциональность
|
||||
- ✅ Полный CRUD постов
|
||||
- ✅ Лайки, комментарии, репосты
|
||||
- ✅ Система тегов (Furry, Anime, Other)
|
||||
- ✅ Интеграция e621 и gelbooru API
|
||||
- ✅ **Проксирование изображений для доступа из РФ**
|
||||
- ✅ Система уведомлений
|
||||
- ✅ Подписки на пользователей
|
||||
- ✅ Модерация и жалобы
|
||||
- ✅ Настройки whitelist фильтров
|
||||
- ✅ Telegram авторизация
|
||||
|
||||
### Качество кода
|
||||
- ✅ Модульная архитектура
|
||||
- ✅ Переиспользуемые компоненты
|
||||
- ✅ Централизованное управление API
|
||||
- ✅ Error handling
|
||||
- ✅ Логирование
|
||||
- ✅ Документация
|
||||
|
||||
## 📝 TODO / Планы развития
|
||||
|
||||
- [ ] Unit тесты
|
||||
- [ ] E2E тесты
|
||||
- [ ] Rate limiting
|
||||
- [ ] Кэширование (Redis)
|
||||
- [ ] WebSocket для real-time уведомлений
|
||||
- [ ] Telegram Stars интеграция
|
||||
- [ ] Поиск по постам
|
||||
- [ ] Хэштеги
|
||||
- [ ] Приватные сообщения
|
||||
- [ ] Группы/сообщества
|
||||
- [ ] Рекомендации постов (алгоритм)
|
||||
- [ ] Статистика для авторов
|
||||
- [ ] Dark mode
|
||||
- [ ] Мультиязычность
|
||||
|
||||
---
|
||||
|
||||
**Вопросы?** Смотрите полную документацию в README.md, SETUP.md и CONTRIBUTING.md
|
||||
|
||||
172
QUICKSTART.md
172
QUICKSTART.md
|
|
@ -1,172 +0,0 @@
|
|||
# 🚀 Быстрый старт NakamaSpace
|
||||
|
||||
Быстрая инструкция для запуска за 5 минут.
|
||||
|
||||
## ⚡ Супер быстрый старт
|
||||
|
||||
```bash
|
||||
# 1. Клонировать репозиторий
|
||||
git clone <repository-url>
|
||||
cd nakama
|
||||
|
||||
# 2. Запустить
|
||||
./start.sh
|
||||
```
|
||||
|
||||
Скрипт автоматически:
|
||||
- Проверит и запустит MongoDB
|
||||
- Установит зависимости
|
||||
- Создаст .env файлы
|
||||
- Запустит приложение
|
||||
|
||||
## 📝 Минимальная настройка
|
||||
|
||||
Если используете скрипт `start.sh`, нужно только:
|
||||
|
||||
1. **Получить Telegram Bot Token**
|
||||
- Откройте [@BotFather](https://t.me/BotFather)
|
||||
- Отправьте `/newbot`
|
||||
- Скопируйте токен
|
||||
|
||||
2. **Добавить токен в .env**
|
||||
```bash
|
||||
nano .env
|
||||
# Замените: TELEGRAM_BOT_TOKEN=your_telegram_bot_token_here
|
||||
```
|
||||
|
||||
3. **Настроить Web App в боте**
|
||||
- В BotFather: `/mybots` → ваш бот → Bot Settings → Menu Button
|
||||
- Укажите URL: `http://localhost:5173` (для разработки)
|
||||
|
||||
## 🌐 Для локального тестирования в Telegram
|
||||
|
||||
Telegram требует HTTPS для Mini Apps. Используйте ngrok:
|
||||
|
||||
```bash
|
||||
# Установить ngrok
|
||||
brew install ngrok # macOS
|
||||
# или скачайте с https://ngrok.com
|
||||
|
||||
# Запустить туннель
|
||||
ngrok http 5173
|
||||
|
||||
# Скопируйте HTTPS URL и укажите в BotFather
|
||||
```
|
||||
|
||||
## 📱 Первый запуск
|
||||
|
||||
1. **Откройте бота в Telegram**
|
||||
2. **Нажмите кнопку меню** или отправьте команду
|
||||
3. **Приложение откроется** как Mini App
|
||||
4. **Готово!** Теперь можете:
|
||||
- Создавать посты с тегами
|
||||
- Искать в e621 и gelbooru
|
||||
- Подписываться на пользователей
|
||||
- Получать уведомления
|
||||
|
||||
## 🛠️ Структура проекта
|
||||
|
||||
```
|
||||
nakama/
|
||||
├── backend/ # API сервер
|
||||
├── frontend/ # React приложение
|
||||
├── start.sh # Скрипт запуска
|
||||
├── SETUP.md # Подробная инструкция
|
||||
└── README.md # Основная документация
|
||||
```
|
||||
|
||||
## 🎨 Основные функции
|
||||
|
||||
### 🏠 Лента
|
||||
- Создание постов с текстом и изображениями
|
||||
- Обязательные теги: Furry 🦊, Anime 🎌, Other
|
||||
- Лайки, комментарии, репосты
|
||||
- Упоминания пользователей
|
||||
|
||||
### 🔍 Поиск
|
||||
- e621 API для Furry контента
|
||||
- gelbooru API для Anime
|
||||
- Автокомплит тегов
|
||||
- Просмотрщик изображений с swipe
|
||||
- Скачивание изображений
|
||||
|
||||
### 🔔 Уведомления
|
||||
- Telegram-стиль баблов
|
||||
- Уведомления о подписках, лайках, комментариях
|
||||
- Переходы к постам и профилям
|
||||
|
||||
### 👤 Профиль
|
||||
- Статистика подписчиков
|
||||
- Настройки фильтров (без Furry, только Anime, без NSFW)
|
||||
- Донаты через Telegram Stars (планируется)
|
||||
- Редактирование био
|
||||
|
||||
## 🛡️ Модерация
|
||||
|
||||
Для назначения модератора:
|
||||
|
||||
```javascript
|
||||
// Подключиться к MongoDB
|
||||
mongo nakama
|
||||
|
||||
// Назначить роль
|
||||
db.users.updateOne(
|
||||
{ telegramId: "YOUR_TELEGRAM_ID" },
|
||||
{ $set: { role: "moderator" } } // или "admin"
|
||||
)
|
||||
```
|
||||
|
||||
Модераторы могут:
|
||||
- Удалять любые посты
|
||||
- Отмечать контент как NSFW
|
||||
- Блокировать пользователей
|
||||
- Просматривать и обрабатывать жалобы
|
||||
|
||||
## 🐛 Проблемы?
|
||||
|
||||
### Приложение не запускается
|
||||
```bash
|
||||
# Проверьте MongoDB
|
||||
brew services list # должен быть started
|
||||
|
||||
# Проверьте порты
|
||||
lsof -i :3000 # backend
|
||||
lsof -i :5173 # frontend
|
||||
```
|
||||
|
||||
### CORS ошибки
|
||||
Убедитесь что `frontend/.env` содержит правильный API URL:
|
||||
```
|
||||
VITE_API_URL=http://localhost:3000/api
|
||||
```
|
||||
|
||||
### Telegram показывает ошибку
|
||||
- Проверьте что используете HTTPS (ngrok для разработки)
|
||||
- Убедитесь что токен бота правильный
|
||||
- Проверьте что Menu Button настроен в BotFather
|
||||
|
||||
## 📚 Дополнительная документация
|
||||
|
||||
- [SETUP.md](SETUP.md) - Подробная инструкция по установке
|
||||
- [README.md](README.md) - Полная документация проекта
|
||||
- [CONTRIBUTING.md](CONTRIBUTING.md) - Гайд по разработке
|
||||
|
||||
## 💡 Подсказки
|
||||
|
||||
1. **Dev режим**: Telegram Init Data проверка отключена для удобства разработки
|
||||
2. **Моки**: В dev режиме создается тестовый пользователь автоматически
|
||||
3. **Hot reload**: Frontend обновляется автоматически при изменениях
|
||||
4. **Логи**: Смотрите в терминале для отладки
|
||||
|
||||
## 🎉 Готово к использованию!
|
||||
|
||||
Приложение работает? Отлично! Теперь вы можете:
|
||||
- Создать первый пост
|
||||
- Попробовать поиск по тегам
|
||||
- Изучить настройки профиля
|
||||
- Пригласить друзей в свою мини-социальную сеть!
|
||||
|
||||
---
|
||||
|
||||
**Нужна помощь?** Создайте Issue на GitHub или проверьте полную документацию в SETUP.md
|
||||
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
# 🔧 Быстрый фикс v2.1.1 - Окно комментариев
|
||||
|
||||
## Проблема:
|
||||
- Модальное окно на весь экран
|
||||
- Поле ввода неактивно
|
||||
- Всё окно закрывается при клике
|
||||
|
||||
## Решение:
|
||||
- Модалка теперь 65vh (не на весь экран)
|
||||
- Отступ снизу для навигации (80px)
|
||||
- Клик работает только:
|
||||
- ✅ На тёмном фоне (закрывает)
|
||||
- ✅ Кнопка X (закрывает)
|
||||
- ✅ Поле ввода (активно)
|
||||
- ✅ Кнопка отправки (активна)
|
||||
- Клик по списку комментариев НЕ закрывает окно
|
||||
|
||||
## Файлы:
|
||||
- `frontend/src/components/CommentsModal.css`
|
||||
- `frontend/src/components/CommentsModal.jsx`
|
||||
|
||||
## Загрузить на сервер:
|
||||
|
||||
```bash
|
||||
# На компьютере
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
scp frontend/src/components/CommentsModal.css root@IP:/var/www/nakama/frontend/src/components/
|
||||
scp frontend/src/components/CommentsModal.jsx root@IP:/var/www/nakama/frontend/src/components/
|
||||
|
||||
# На сервере
|
||||
ssh root@IP
|
||||
cd /var/www/nakama/frontend
|
||||
npm run build
|
||||
cd ..
|
||||
# Frontend обновлён, backend перезапускать НЕ нужно
|
||||
|
||||
# Проверить
|
||||
curl https://nakama.glpshchn.ru
|
||||
```
|
||||
|
||||
Или полное обновление:
|
||||
```bash
|
||||
cd /Users/glpshchn/Desktop
|
||||
tar -czf nakama-fix.tar.gz nakama --exclude='node_modules' --exclude='dist'
|
||||
scp nakama-fix.tar.gz root@IP:/tmp/
|
||||
# Далее как в UPLOAD_TO_SERVER.md
|
||||
```
|
||||
|
||||
|
||||
475
README.md
475
README.md
|
|
@ -1,373 +1,192 @@
|
|||
# 🌟 NakamaSpace - Telegram Mini App
|
||||
# 🎨 Nakama
|
||||
|
||||
> Полноценная мини-социальная сеть внутри Telegram с 4 вкладками, системой постов, поиском, уведомлениями и модерацией.
|
||||
Социальная сеть для фурри и аниме сообщества, реализованная как Telegram Mini App.
|
||||
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
[](https://nodejs.org/)
|
||||
[](https://reactjs.org/)
|
||||
[](https://www.mongodb.com/)
|
||||
## 🚀 Возможности
|
||||
|
||||
---
|
||||
- 📝 Создание постов с текстом и изображениями (до 5 шт)
|
||||
- 🔍 Поиск контента через e621 и Gelbooru API
|
||||
- 💬 Комментарии и лайки
|
||||
- 👥 Подписки на пользователей
|
||||
- 🔔 Система уведомлений
|
||||
- 🛡️ Модерация контента
|
||||
- 🗂️ Фильтры и теги (Furry, Anime, Other, NSFW)
|
||||
- 🌙 Темная/светлая тема
|
||||
- 📱 Fullview для изображений
|
||||
- 🗄️ MinIO для хранения медиа
|
||||
|
||||
## ✨ Возможности
|
||||
## 🛠️ Технологии
|
||||
|
||||
### 🏠 Лента постов
|
||||
- ✅ Создание постов с текстом и изображениями (до 10MB)
|
||||
- ✅ Обязательные теги: **Furry** 🦊, **Anime** 🎌, **Other** ⚪
|
||||
- ✅ Лайки, комментарии, репосты
|
||||
- ✅ Упоминания пользователей (@username)
|
||||
- ✅ NSFW маркировка контента
|
||||
- ✅ Фильтрация по тегам
|
||||
- ✅ Бесконечная загрузка (пагинация)
|
||||
**Frontend:**
|
||||
- React + Vite
|
||||
- React Router
|
||||
- Telegram Mini App SDK
|
||||
- Lucide Icons
|
||||
|
||||
### 🔍 Поиск
|
||||
- ✅ Интеграция с **e621 API** (Furry контент)
|
||||
- ✅ Интеграция с **gelbooru API** (Anime контент)
|
||||
- ✅ **Прокси изображений через сервер** (доступ из РФ)
|
||||
- ✅ Смешанный режим поиска (Mixed)
|
||||
- ✅ Автокомплит тегов с количеством результатов
|
||||
- ✅ Просмотрщик изображений с swipe навигацией
|
||||
- ✅ Скачивание изображений
|
||||
- ✅ Отображение рейтинга и тегов
|
||||
**Backend:**
|
||||
- Node.js + Express
|
||||
- MongoDB
|
||||
- Socket.IO (WebSocket)
|
||||
- MinIO (S3-compatible storage)
|
||||
- Redis (опционально)
|
||||
|
||||
### 🔔 Уведомления
|
||||
- ✅ Telegram-стиль баблов с цветовой кодировкой
|
||||
- ✅ Уведомления о подписках, лайках, комментариях, репостах
|
||||
- ✅ Упоминания в постах
|
||||
- ✅ Счётчик непрочитанных
|
||||
- ✅ Превью постов в уведомлениях
|
||||
- ✅ Переходы к постам и профилям
|
||||
## 📦 Установка
|
||||
|
||||
### 👤 Профиль
|
||||
- ✅ Аватар и данные из Telegram
|
||||
- ✅ Редактируемое био (до 300 символов)
|
||||
- ✅ Статистика: подписчики / подписки
|
||||
- ✅ Настройки фильтров контента:
|
||||
- Без Furry контента
|
||||
- Только Anime
|
||||
- Без NSFW
|
||||
- ✅ Настройки поиска (Furry / Anime / Mixed)
|
||||
- ✅ Донаты через Telegram Stars (UI готов)
|
||||
- ✅ Роли: User / Moderator / Admin
|
||||
|
||||
### 🛡️ Модерация
|
||||
- ✅ Система жалоб на посты
|
||||
- ✅ Панель модератора
|
||||
- ✅ Удаление постов
|
||||
- ✅ Блокировка пользователей (временная/постоянная)
|
||||
- ✅ Установка NSFW флага
|
||||
- ✅ Просмотр и обработка репортов
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Быстрый старт
|
||||
|
||||
### Супер быстрый запуск (5 минут)
|
||||
### 1. Клонируйте репозиторий
|
||||
|
||||
```bash
|
||||
# 1. Клонировать репозиторий
|
||||
git clone <repository-url>
|
||||
git clone <your-repo>
|
||||
cd nakama
|
||||
|
||||
# 2. Запустить автоматический скрипт
|
||||
./start.sh
|
||||
```
|
||||
|
||||
Скрипт автоматически:
|
||||
- ✅ Проверит и запустит MongoDB
|
||||
- ✅ Установит все зависимости
|
||||
- ✅ Создаст .env файлы из примеров
|
||||
- ✅ Запустит приложение
|
||||
|
||||
**Единственное что нужно** - получить Telegram Bot Token у [@BotFather](https://t.me/BotFather) и добавить в `.env`
|
||||
|
||||
📖 Подробная инструкция: [QUICKSTART.md](QUICKSTART.md)
|
||||
|
||||
### Ручная установка
|
||||
### 2. Настройте переменные окружения
|
||||
|
||||
```bash
|
||||
# 1. Установить зависимости
|
||||
cp ENV_EXAMPLE.txt .env
|
||||
nano .env
|
||||
```
|
||||
|
||||
Заполните обязательные поля:
|
||||
```env
|
||||
# Telegram Bot
|
||||
TELEGRAM_BOT_TOKEN=ваш_токен_от_BotFather
|
||||
|
||||
# MongoDB (удаленный сервер)
|
||||
MONGODB_URI=mongodb://103.80.87.247:27017/nakama
|
||||
|
||||
# JWT секреты (сгенерируйте случайные строки)
|
||||
JWT_ACCESS_SECRET=ваш_секретный_ключ_32_символа
|
||||
JWT_REFRESH_SECRET=другой_секретный_ключ_32_символа
|
||||
|
||||
# MinIO
|
||||
MINIO_ENABLED=true
|
||||
MINIO_ENDPOINT=103.80.87.247
|
||||
MINIO_PORT=9000
|
||||
MINIO_ACCESS_KEY=ваш_access_key
|
||||
MINIO_SECRET_KEY=ваш_secret_key
|
||||
MINIO_PUBLIC_BUCKET=true
|
||||
|
||||
# Frontend
|
||||
FRONTEND_URL=https://ваш-домен.com
|
||||
CORS_ORIGIN=https://ваш-домен.com,https://web.telegram.org
|
||||
```
|
||||
|
||||
### 3. Запустите через Docker
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### 4. Настройте MinIO (один раз)
|
||||
|
||||
```bash
|
||||
chmod +x minio-setup-public.sh
|
||||
./minio-setup-public.sh
|
||||
```
|
||||
|
||||
## 🔧 Разработка
|
||||
|
||||
```bash
|
||||
# Backend
|
||||
cd backend
|
||||
npm install
|
||||
cd frontend && npm install && cd ..
|
||||
npm run dev
|
||||
|
||||
# 2. Настроить .env файлы
|
||||
cp .env.example .env
|
||||
cp frontend/.env.example frontend/.env
|
||||
# Отредактируйте .env файлы
|
||||
|
||||
# 3. Запустить MongoDB
|
||||
brew services start mongodb-community # macOS
|
||||
sudo systemctl start mongod # Linux
|
||||
|
||||
# 4. Запустить приложение
|
||||
# Frontend
|
||||
cd frontend
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
📖 Полная инструкция: [SETUP.md](SETUP.md)
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Дизайн-система
|
||||
|
||||
### Минималистичный iOS-стиль 2025
|
||||
|
||||
- **Философия**: Чистый, минималистичный интерфейс в стиле нового Telegram
|
||||
- **Типографика**: SF Pro Display (iOS) / Roboto (Android)
|
||||
- **Радиус**: 16px для карточек, 12px для кнопок
|
||||
- **Тени**: Мягкие, rgba(0,0,0,0.08)
|
||||
- **Анимации**: Плавные, 0.2-0.3s ease-out
|
||||
|
||||
### Цветовая палитра
|
||||
|
||||
```
|
||||
🎨 Основные цвета
|
||||
├── Фон: #F2F3F5
|
||||
├── Карточки: #FFFFFF
|
||||
├── Текст: #1C1C1E
|
||||
├── Акцент: #007AFF (iOS синий)
|
||||
└── Границы: #C7C7CC
|
||||
|
||||
🏷️ Теги
|
||||
├── Furry: #FF8A33 (оранжевый)
|
||||
├── Anime: #4A90E2 (синий)
|
||||
└── Other: #A0A0A0 (серый)
|
||||
|
||||
⚠️ Дополнительные
|
||||
├── NSFW: #FF3B30 (красный)
|
||||
├── Успех: #34C759 (зелёный)
|
||||
└── Донаты: #FFD700 (золотой)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📱 Технологии
|
||||
|
||||
### Frontend
|
||||
- **React 18** - UI библиотека
|
||||
- **Vite** - Быстрый сборщик
|
||||
- **React Router** - Маршрутизация
|
||||
- **Telegram Mini App SDK** - Интеграция с Telegram
|
||||
- **Axios** - HTTP клиент
|
||||
- **Lucide React** - Иконки
|
||||
|
||||
### Backend
|
||||
- **Node.js + Express** - API сервер
|
||||
- **MongoDB + Mongoose** - База данных
|
||||
- **Multer** - Загрузка файлов
|
||||
- **Crypto** - Telegram Init Data валидация
|
||||
|
||||
### Интеграции
|
||||
- **Telegram Bot API** - Авторизация через Init Data
|
||||
- **e621 API** - Поиск Furry контента
|
||||
- **gelbooru API** - Поиск Anime контента
|
||||
|
||||
---
|
||||
|
||||
## 📂 Структура проекта
|
||||
## 📝 Структура
|
||||
|
||||
```
|
||||
nakama/
|
||||
├── 📁 backend/ Backend сервер (Node.js + Express)
|
||||
│ ├── 📁 models/ MongoDB схемы (User, Post, Notification, Report)
|
||||
│ ├── 📁 routes/ API endpoints (auth, posts, users, etc)
|
||||
│ ├── 📁 middleware/ Middleware функции (auth)
|
||||
│ └── 📄 server.js Точка входа сервера
|
||||
│
|
||||
├── 📁 frontend/ Frontend приложение (React + Vite)
|
||||
│ ├── 📁 src/
|
||||
│ │ ├── 📁 components/ React компоненты (PostCard, Modals, etc)
|
||||
│ │ ├── 📁 pages/ Страницы-вкладки (Feed, Search, Notifications, Profile)
|
||||
│ │ ├── 📁 utils/ Утилиты (API клиент, Telegram SDK)
|
||||
│ │ └── 📁 styles/ CSS стили с переменными
|
||||
│ └── 📄 index.html
|
||||
│
|
||||
├── 📄 README.md Основная документация (этот файл)
|
||||
├── 📄 SETUP.md Подробная инструкция по установке
|
||||
├── 📄 QUICKSTART.md Быстрый старт за 5 минут
|
||||
├── 📄 PROJECT_STRUCTURE.md Детальная карта проекта
|
||||
├── 📄 CONTRIBUTING.md Гайд для разработчиков
|
||||
└── 📄 start.sh Скрипт быстрого запуска
|
||||
├── backend/ # Node.js API
|
||||
│ ├── models/ # MongoDB модели
|
||||
│ ├── routes/ # API роуты
|
||||
│ ├── middleware/ # Middleware
|
||||
│ ├── utils/ # Утилиты
|
||||
│ └── bot.js # Telegram бот
|
||||
├── frontend/ # React приложение
|
||||
│ ├── src/
|
||||
│ │ ├── pages/ # Страницы
|
||||
│ │ ├── components/ # Компоненты
|
||||
│ │ └── utils/ # Утилиты
|
||||
├── moderation/ # Система модерации
|
||||
│ ├── frontend/ # React админка
|
||||
│ └── backend/ # Доп. API роуты
|
||||
└── docker-compose.yml
|
||||
```
|
||||
|
||||
📖 Полная карта проекта: [PROJECT_STRUCTURE.md](PROJECT_STRUCTURE.md)
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Безопасность
|
||||
|
||||
- ✅ **Telegram Init Data** валидация с HMAC-SHA256
|
||||
- ✅ **Безопасная загрузка** файлов с проверкой типов
|
||||
- ✅ **Роли и права** доступа (User, Moderator, Admin)
|
||||
- ✅ **XSS защита** через React
|
||||
- ✅ **CORS** настройки
|
||||
- ✅ **HTTPS only** для production
|
||||
|
||||
---
|
||||
|
||||
## 📚 Документация
|
||||
|
||||
- [📖 README.md](README.md) - Основная документация (вы здесь)
|
||||
- [⚡ QUICKSTART.md](QUICKSTART.md) - Быстрый старт за 5 минут
|
||||
- [🔧 SETUP.md](SETUP.md) - Подробная инструкция по установке и деплою
|
||||
- [📂 PROJECT_STRUCTURE.md](PROJECT_STRUCTURE.md) - Детальная структура проекта
|
||||
- [🤝 CONTRIBUTING.md](CONTRIBUTING.md) - Гайд для разработчиков
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Разработка
|
||||
|
||||
### Скрипты
|
||||
## 🐛 Логи
|
||||
|
||||
```bash
|
||||
# Запуск в dev режиме (backend + frontend)
|
||||
npm run dev
|
||||
# Все логи
|
||||
docker-compose logs -f
|
||||
|
||||
# Только backend
|
||||
npm run server
|
||||
docker-compose logs -f backend
|
||||
|
||||
# Только frontend
|
||||
npm run client
|
||||
|
||||
# Сборка для production
|
||||
npm run build
|
||||
|
||||
# Production запуск
|
||||
npm start
|
||||
# Ошибки
|
||||
docker-compose logs | grep ERROR
|
||||
```
|
||||
|
||||
### Локальное тестирование в Telegram
|
||||
Логи также сохраняются в `backend/logs/`:
|
||||
- `all-YYYY-MM-DD.log` - все логи
|
||||
- `error-YYYY-MM-DD.log` - только ошибки
|
||||
- `security-YYYY-MM-DD.log` - события безопасности
|
||||
|
||||
Telegram требует HTTPS для Mini Apps. Используйте ngrok:
|
||||
## 🔒 Безопасность
|
||||
|
||||
- JWT авторизация
|
||||
- Валидация Telegram initData
|
||||
- Rate limiting
|
||||
- XSS/NoSQL injection защита
|
||||
- Helmet security headers
|
||||
- CORS настройки
|
||||
|
||||
## 📱 Telegram Bot
|
||||
|
||||
Создайте бота через @BotFather:
|
||||
1. `/newbot` - создать бота
|
||||
2. `/setmenubutton` - добавить кнопку запуска Mini App
|
||||
3. Скопируйте токен в `.env`
|
||||
|
||||
## 🗄️ MinIO
|
||||
|
||||
Для хранения загруженных изображений используется MinIO (S3-compatible).
|
||||
|
||||
**Важно:**
|
||||
- Порт 9000 - API (для загрузки файлов)
|
||||
- Порт 9001 - Console (веб-интерфейс)
|
||||
- Bucket должен быть публичным для доступа к файлам
|
||||
|
||||
## 📊 Мониторинг
|
||||
|
||||
```bash
|
||||
# Установить ngrok
|
||||
brew install ngrok # macOS
|
||||
# Статус контейнеров
|
||||
docker-compose ps
|
||||
|
||||
# Запустить туннель
|
||||
ngrok http 5173
|
||||
# Использование ресурсов
|
||||
docker stats
|
||||
|
||||
# Скопируйте HTTPS URL и добавьте в BotFather
|
||||
# Логи MinIO
|
||||
docker-compose logs minio
|
||||
```
|
||||
|
||||
### Назначение модераторов
|
||||
## 🚀 Production
|
||||
|
||||
```javascript
|
||||
// Подключиться к MongoDB
|
||||
mongo nakama
|
||||
|
||||
// Назначить роль
|
||||
db.users.updateOne(
|
||||
{ telegramId: "YOUR_TELEGRAM_ID" },
|
||||
{ $set: { role: "moderator" } } // или "admin"
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚢 Деплой
|
||||
|
||||
### Рекомендуемые платформы
|
||||
|
||||
- **Backend**: Railway, Render, Heroku
|
||||
- **Frontend**: Vercel, Netlify
|
||||
- **MongoDB**: MongoDB Atlas (бесплатный tier)
|
||||
|
||||
### Быстрый деплой на Railway
|
||||
|
||||
```bash
|
||||
npm i -g @railway/cli
|
||||
railway login
|
||||
railway init
|
||||
railway up
|
||||
```
|
||||
|
||||
📖 Подробнее: [SETUP.md - Production деплой](SETUP.md#production-деплой)
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Roadmap
|
||||
|
||||
### ✅ Реализовано (v2.0)
|
||||
- [x] Backend API (Express + MongoDB)
|
||||
- [x] Frontend React приложение
|
||||
- [x] Telegram авторизация
|
||||
- [x] Система постов (CRUD, лайки, комментарии, репосты)
|
||||
- [x] Теги (Furry, Anime, Other)
|
||||
- [x] Поиск (e621 + gelbooru)
|
||||
- [x] Уведомления
|
||||
- [x] Профили и подписки
|
||||
- [x] Модерация и жалобы
|
||||
- [x] Настройки фильтров
|
||||
- [x] iOS-стиль дизайн
|
||||
- [x] **Dark mode** - переключатель тем
|
||||
- [x] **Rate limiting** - защита от спама
|
||||
- [x] **Redis кэширование** - ускорение API
|
||||
- [x] **Поиск по постам** - полнотекстовый
|
||||
- [x] **Хэштеги** - система #тегов
|
||||
- [x] **Статистика** - просмотры, engagement
|
||||
- [x] **WebSocket** - real-time уведомления
|
||||
- [x] **Telegram Stars** - UI готов
|
||||
|
||||
### 🔜 В планах (v3.0)
|
||||
- [ ] Unit и E2E тесты
|
||||
- [ ] Приватные сообщения (чаты)
|
||||
- [ ] Группы/сообщества
|
||||
- [ ] Рекомендательный алгоритм (ML)
|
||||
- [ ] Мультиязычность (EN/RU/JP)
|
||||
- [ ] Telegram Mini App Ads
|
||||
- [ ] Stories функция
|
||||
- [ ] Voice messages
|
||||
- [ ] Live streaming
|
||||
|
||||
---
|
||||
|
||||
## 🤝 Вклад в проект
|
||||
|
||||
Мы рады любому вкладу! Смотрите [CONTRIBUTING.md](CONTRIBUTING.md) для деталей.
|
||||
|
||||
### Как помочь
|
||||
1. 🐛 Сообщить о баге через Issues
|
||||
2. 💡 Предложить новую функцию
|
||||
3. 🔧 Исправить баг или добавить фичу
|
||||
4. 📖 Улучшить документацию
|
||||
5. ⭐ Поставить звезду проекту!
|
||||
|
||||
---
|
||||
1. Настройте HTTPS (обязательно для Telegram Mini App!)
|
||||
2. Измените `JWT_ACCESS_SECRET` и `JWT_REFRESH_SECRET`
|
||||
3. Настройте firewall
|
||||
4. Настройте Nginx reverse proxy
|
||||
5. Включите автоматические бекапы MongoDB
|
||||
|
||||
## 📄 Лицензия
|
||||
|
||||
MIT License - см. [LICENSE](LICENSE)
|
||||
MIT
|
||||
|
||||
---
|
||||
|
||||
## 👥 Авторы
|
||||
|
||||
Создано с ❤️ для сообщества
|
||||
|
||||
---
|
||||
|
||||
## 📞 Поддержка
|
||||
|
||||
- 💬 **Issues**: Создайте Issue на GitHub
|
||||
- 📖 **Документация**: Смотрите [SETUP.md](SETUP.md)
|
||||
- 🐛 **Баги**: Смотрите [Troubleshooting](SETUP.md#troubleshooting)
|
||||
|
||||
---
|
||||
|
||||
## 🌟 Благодарности
|
||||
|
||||
- [Telegram](https://telegram.org/) за отличную платформу Mini Apps
|
||||
- [e621](https://e621.net/) за API
|
||||
- [gelbooru](https://gelbooru.com/) за API
|
||||
- Сообществу за поддержку и идеи
|
||||
|
||||
---
|
||||
|
||||
<div align="center">
|
||||
|
||||
**[⬆ Наверх](#-nakamaspace---telegram-mini-app)**
|
||||
|
||||
Сделано с 🦊 и 🎌
|
||||
|
||||
</div>
|
||||
## 👥 Поддержка
|
||||
|
||||
Telegram: @NakamaReportbot
|
||||
|
|
|
|||
|
|
@ -1,111 +0,0 @@
|
|||
╔═══════════════════════════════════════════════════════════════════════╗
|
||||
║ Готово к загрузке на nakama.glpshchn.ru ║
|
||||
║ NakamaSpace v2.1.1 ║
|
||||
╚═══════════════════════════════════════════════════════════════════════╝
|
||||
|
||||
✅ ВСЕ ПРОБЛЕМЫ ИСПРАВЛЕНЫ!
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
📝 ИСПРАВЛЕНО:
|
||||
|
||||
✅ Комментарии:
|
||||
• Окно НЕ на весь экран (65vh)
|
||||
• Поле ввода активно
|
||||
• Не прыгает при фокусе
|
||||
• Правильные клики
|
||||
|
||||
✅ Репосты:
|
||||
• Полностью удалены
|
||||
• Остались только ❤️ и 💬
|
||||
|
||||
✅ Тёмная тема:
|
||||
• Все иконки видны
|
||||
• Правильные цвета
|
||||
• Кнопка + синяя
|
||||
|
||||
✅ Фильтры:
|
||||
• Только NSFW
|
||||
• Автосохранение
|
||||
|
||||
✅ Профиль:
|
||||
• Убраны донаты
|
||||
• Упрощён интерфейс
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
🚀 3 ШАГА ДО ЗАПУСКА:
|
||||
|
||||
1️⃣ НА КОМПЬЮТЕРЕ:
|
||||
────────────────────────────────────────────────────────────────────────
|
||||
cd /Users/glpshchn/Desktop
|
||||
tar -czf nakama-v2.1.1.tar.gz nakama \
|
||||
--exclude='node_modules' --exclude='dist' --exclude='.git'
|
||||
scp nakama-v2.1.1.tar.gz root@ваш_IP:/tmp/
|
||||
|
||||
|
||||
2️⃣ НА СЕРВЕРЕ (скопируйте весь блок):
|
||||
────────────────────────────────────────────────────────────────────────
|
||||
ssh root@ваш_IP
|
||||
cd /var/www/nakama
|
||||
cp .env /tmp/env-backup
|
||||
cp -r backend/uploads /tmp/uploads-backup
|
||||
cd /var/www
|
||||
sudo rm -rf nakama
|
||||
sudo tar -xzf /tmp/nakama-v2.1.1.tar.gz
|
||||
cd nakama
|
||||
cp /tmp/env-backup .env
|
||||
mkdir -p backend/uploads
|
||||
cp -r /tmp/uploads-backup/* backend/uploads/ 2>/dev/null || true
|
||||
chmod +x update-server.sh
|
||||
./update-server.sh
|
||||
|
||||
|
||||
3️⃣ ПРОВЕРКА:
|
||||
────────────────────────────────────────────────────────────────────────
|
||||
pm2 status
|
||||
pm2 logs nakama-backend --lines 30
|
||||
curl https://nakama.glpshchn.ru/health
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
📱 ПРОВЕРЬТЕ В TELEGRAM:
|
||||
|
||||
1. Откройте бота
|
||||
2. Нажмите Menu Button
|
||||
3. Откроется https://nakama.glpshchn.ru
|
||||
4. Попробуйте:
|
||||
✓ Открыть комментарии (💬)
|
||||
✓ Написать комментарий
|
||||
✓ Переключить тёмную тему
|
||||
✓ Создать пост
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
📚 ДОКУМЕНТАЦИЯ:
|
||||
|
||||
CHANGELOG_v2.1.1.md - Полный список изменений
|
||||
UPLOAD_TO_SERVER.md - Подробная инструкция
|
||||
DEPLOY_INSTRUCTIONS_SIMPLE.txt - Краткая инструкция
|
||||
update-server.sh - Автоматический скрипт
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
⚠️ ВАЖНО:
|
||||
|
||||
Скрипт update-server.sh автоматически:
|
||||
• Сделает бэкап
|
||||
• Установит зависимости
|
||||
• Пересоберёт frontend
|
||||
• Обновит MongoDB (удалит reposts)
|
||||
• Отключит фильтры для всех пользователей
|
||||
• Перезапустит backend
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
🎉 ГОТОВО К ДЕПЛОЮ!
|
||||
|
||||
Следуйте 3 шагам выше и приложение заработает идеально на:
|
||||
https://nakama.glpshchn.ru
|
||||
|
||||
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
╔═══════════════════════════════════════════════════════════════════════╗
|
||||
║ NakamaSpace v2.1 - Готов к деплою! ║
|
||||
╚═══════════════════════════════════════════════════════════════════════╝
|
||||
|
||||
✅ ВСЕ ИСПРАВЛЕНИЯ ПРИМЕНЕНЫ
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
📝 ЧТО ИСПРАВЛЕНО:
|
||||
|
||||
1. ✅ Окно комментариев
|
||||
└─ Теперь fixed на весь экран, поле ввода активно
|
||||
|
||||
2. ✅ Репосты удалены
|
||||
└─ Остались только Лайки ❤️ и Комментарии 💬
|
||||
|
||||
3. ✅ Тёмная тема
|
||||
└─ Все иконки и текст видны
|
||||
|
||||
4. ✅ Фильтры упрощены
|
||||
└─ Только "Скрыть контент 18+"
|
||||
|
||||
5. ✅ Донаты удалены
|
||||
└─ Упрощён профиль
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
🚀 КАК ЗАГРУЗИТЬ НА СЕРВЕР:
|
||||
|
||||
Метод 1: Быстрый (через SCP)
|
||||
────────────────────────────────────────────────────────────────────────
|
||||
|
||||
НА КОМПЬЮТЕРЕ:
|
||||
cd /Users/glpshchn/Desktop
|
||||
tar -czf nakama-v2.1.tar.gz nakama \
|
||||
--exclude='node_modules' --exclude='dist' --exclude='.git'
|
||||
scp nakama-v2.1.tar.gz root@IP:/tmp/
|
||||
|
||||
НА СЕРВЕРЕ:
|
||||
ssh root@IP
|
||||
cd /var/www
|
||||
sudo tar -czf ~/backup-$(date +%s).tar.gz nakama
|
||||
cd nakama && cp .env /tmp/ && cp -r backend/uploads /tmp/ && cd ..
|
||||
sudo rm -rf nakama
|
||||
sudo tar -xzf /tmp/nakama-v2.1.tar.gz
|
||||
cd nakama && cp /tmp/.env . && cp -r /tmp/uploads backend/
|
||||
./update-server.sh
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Метод 2: Через Git (если настроен)
|
||||
────────────────────────────────────────────────────────────────────────
|
||||
|
||||
НА КОМПЬЮТЕРЕ:
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
git add .
|
||||
git commit -m "v2.1: Fixes and improvements"
|
||||
git push
|
||||
|
||||
НА СЕРВЕРЕ:
|
||||
ssh root@IP
|
||||
cd /var/www/nakama
|
||||
git pull
|
||||
./update-server.sh
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✅ ПОСЛЕ ОБНОВЛЕНИЯ ПРОВЕРЬТЕ:
|
||||
|
||||
□ https://nakama.glpshchn.ru/health
|
||||
└─ Должно вернуть: {"status":"ok"}
|
||||
|
||||
□ https://nakama.glpshchn.ru
|
||||
└─ Приложение загружается
|
||||
|
||||
□ Откройте бота в Telegram
|
||||
└─ Нажмите Menu Button
|
||||
└─ Приложение работает
|
||||
|
||||
□ Попробуйте:
|
||||
├─ Создать пост
|
||||
├─ Написать комментарий (должно работать!)
|
||||
├─ Переключить тёмную тему (всё видно!)
|
||||
└─ Переключить фильтр NSFW (работает!)
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
📚 ДОКУМЕНТАЦИЯ:
|
||||
|
||||
README.md - Обзор проекта
|
||||
UPLOAD_TO_SERVER.md - Подробная инструкция загрузки (⭐ ЧИТАТЬ)
|
||||
UPDATES_v2.1.md - Changelog v2.1
|
||||
DEPLOYMENT.md - Полный гайд по деплою
|
||||
QUICKSTART.md - Быстрый старт
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
🎯 СЛЕДУЮЩИЕ ШАГИ:
|
||||
|
||||
1. Упакуйте проект: tar -czf nakama-v2.1.tar.gz nakama
|
||||
2. Загрузите на сервер: scp nakama-v2.1.tar.gz root@IP:/tmp/
|
||||
3. На сервере выполните: ./update-server.sh
|
||||
4. Проверьте в браузере и Telegram
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
💡 ПОЛЕЗНО ЗНАТЬ:
|
||||
|
||||
• Скрипт update-server.sh делает автоматический бэкап
|
||||
• Uploads и .env сохраняются автоматически
|
||||
• MongoDB обновится автоматически (удалятся reposts)
|
||||
• PM2 перезапустится автоматически
|
||||
• Логи доступны: pm2 logs nakama-backend
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
🎉 ГОТОВО К ЗАГРУЗКЕ НА nakama.glpshchn.ru
|
||||
|
||||
Подробная инструкция: UPLOAD_TO_SERVER.md
|
||||
|
||||
╔═══════════════════════════════════════════════════════════════════════╗
|
||||
║ Успехов! 🚀🦊🎌 ║
|
||||
╚═══════════════════════════════════════════════════════════════════════╝
|
||||
|
||||
|
||||
|
|
@ -1,438 +0,0 @@
|
|||
# 🔌 Подключение к существующему MinIO через S3 SDK
|
||||
|
||||
## ✅ Ваша ситуация
|
||||
|
||||
У вас уже запущен MinIO на сервере **103.80.87.247**:
|
||||
- **Console (Web UI):** http://103.80.87.247:9901/
|
||||
- **API (S3):** http://103.80.87.247:9000/ (обычно)
|
||||
|
||||
Мы используем **AWS S3 SDK** для подключения к MinIO (MinIO полностью совместим с S3 API).
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Быстрая настройка
|
||||
|
||||
### Шаг 1: Установите зависимости
|
||||
|
||||
```bash
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
npm install
|
||||
```
|
||||
|
||||
Будут установлены:
|
||||
- `@aws-sdk/client-s3` - S3 клиент
|
||||
- `@aws-sdk/lib-storage` - Загрузка больших файлов
|
||||
- `@aws-sdk/s3-request-presigner` - Presigned URLs
|
||||
|
||||
### Шаг 2: Получите Access Key и Secret Key
|
||||
|
||||
1. Откройте MinIO Console: http://103.80.87.247:9901/
|
||||
2. Войдите с учетными данными
|
||||
3. Перейдите: **Identity → Service Accounts** (или **Users**)
|
||||
4. Создайте новый Service Account для приложения:
|
||||
- Name: `nakama-app`
|
||||
- Policy: `readwrite`
|
||||
5. **Скопируйте Access Key и Secret Key** (покажутся только один раз!)
|
||||
|
||||
### Шаг 3: Обновите .env файл
|
||||
|
||||
```bash
|
||||
nano /Users/glpshchn/Desktop/nakama/.env
|
||||
```
|
||||
|
||||
Добавьте/обновите:
|
||||
|
||||
```env
|
||||
# MinIO Configuration
|
||||
MINIO_ENABLED=true
|
||||
MINIO_ENDPOINT=103.80.87.247
|
||||
MINIO_PORT=9000 # API порт (НЕ 9901!)
|
||||
MINIO_USE_SSL=false
|
||||
MINIO_ACCESS_KEY=YOUR_ACCESS_KEY_HERE # Из MinIO Console
|
||||
MINIO_SECRET_KEY=YOUR_SECRET_KEY_HERE # Из MinIO Console
|
||||
MINIO_BUCKET=nakama-media
|
||||
MINIO_REGION=us-east-1
|
||||
MINIO_PUBLIC_URL=http://103.80.87.247:9000
|
||||
```
|
||||
|
||||
### Шаг 4: Создайте bucket в MinIO
|
||||
|
||||
В MinIO Console:
|
||||
1. **Object Browser** → **Create Bucket**
|
||||
2. Имя: `nakama-media`
|
||||
3. Нажмите **Create Bucket**
|
||||
|
||||
Или через API:
|
||||
```bash
|
||||
curl -X PUT http://103.80.87.247:9000/nakama-media \
|
||||
-H "Authorization: AWS4-HMAC-SHA256 ..."
|
||||
```
|
||||
|
||||
### Шаг 5: Запустите приложение
|
||||
|
||||
```bash
|
||||
docker-compose down
|
||||
docker-compose build
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
Проверьте логи:
|
||||
```bash
|
||||
docker-compose logs backend | grep -i minio
|
||||
|
||||
# Должны увидеть:
|
||||
# ✅ S3 клиент для MinIO инициализирован
|
||||
# Bucket: nakama-media
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Проверка подключения
|
||||
|
||||
### Тест 1: Через API endpoint
|
||||
|
||||
```bash
|
||||
# Проверьте статус MinIO (нужен токен модератора)
|
||||
curl -X GET http://localhost:3000/api/minio/status \
|
||||
-H "Authorization: Bearer YOUR_MODERATOR_TOKEN"
|
||||
```
|
||||
|
||||
### Тест 2: Создайте пост с изображением
|
||||
|
||||
1. Откройте приложение
|
||||
2. Создайте пост с изображением
|
||||
3. Проверьте в MinIO Console: **Object Browser → nakama-media → posts/**
|
||||
|
||||
### Тест 3: Через AWS CLI
|
||||
|
||||
```bash
|
||||
# Установите AWS CLI
|
||||
# macOS:
|
||||
brew install awscli
|
||||
|
||||
# Ubuntu:
|
||||
sudo apt install awscli
|
||||
|
||||
# Настройте profile для MinIO
|
||||
aws configure --profile minio
|
||||
# AWS Access Key ID: ваш_access_key
|
||||
# AWS Secret Access Key: ваш_secret_key
|
||||
# Default region name: us-east-1
|
||||
# Default output format: json
|
||||
|
||||
# Проверьте подключение
|
||||
aws s3 ls s3://nakama-media \
|
||||
--endpoint-url http://103.80.87.247:9000 \
|
||||
--profile minio
|
||||
|
||||
# Загрузите тестовый файл
|
||||
aws s3 cp test.jpg s3://nakama-media/test/ \
|
||||
--endpoint-url http://103.80.87.247:9000 \
|
||||
--profile minio
|
||||
|
||||
# Список файлов
|
||||
aws s3 ls s3://nakama-media/posts/ \
|
||||
--endpoint-url http://103.80.87.247:9000 \
|
||||
--profile minio
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Конфигурация для разных сценариев
|
||||
|
||||
### Вариант 1: HTTP (без SSL)
|
||||
|
||||
```env
|
||||
MINIO_ENABLED=true
|
||||
MINIO_ENDPOINT=103.80.87.247
|
||||
MINIO_PORT=9000
|
||||
MINIO_USE_SSL=false
|
||||
MINIO_ACCESS_KEY=your_access_key
|
||||
MINIO_SECRET_KEY=your_secret_key
|
||||
MINIO_BUCKET=nakama-media
|
||||
MINIO_PUBLIC_URL=http://103.80.87.247:9000
|
||||
```
|
||||
|
||||
### Вариант 2: HTTPS (с SSL)
|
||||
|
||||
```env
|
||||
MINIO_ENABLED=true
|
||||
MINIO_ENDPOINT=103.80.87.247
|
||||
MINIO_PORT=9000
|
||||
MINIO_USE_SSL=true
|
||||
MINIO_ACCESS_KEY=your_access_key
|
||||
MINIO_SECRET_KEY=your_secret_key
|
||||
MINIO_BUCKET=nakama-media
|
||||
MINIO_PUBLIC_URL=https://103.80.87.247:9000
|
||||
```
|
||||
|
||||
### Вариант 3: Через домен + CDN
|
||||
|
||||
```env
|
||||
MINIO_ENABLED=true
|
||||
MINIO_ENDPOINT=minio.yourdomain.com
|
||||
MINIO_PORT=443
|
||||
MINIO_USE_SSL=true
|
||||
MINIO_ACCESS_KEY=your_access_key
|
||||
MINIO_SECRET_KEY=your_secret_key
|
||||
MINIO_BUCKET=nakama-media
|
||||
MINIO_PUBLIC_URL=https://cdn.yourdomain.com
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Безопасность
|
||||
|
||||
### 1. Создайте отдельного пользователя для приложения
|
||||
|
||||
В MinIO Console:
|
||||
|
||||
**Identity → Users → Create User:**
|
||||
- Username: `nakama-app`
|
||||
- Password: `secure_password_123`
|
||||
|
||||
**Создайте Policy:**
|
||||
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"s3:GetObject",
|
||||
"s3:PutObject",
|
||||
"s3:DeleteObject"
|
||||
],
|
||||
"Resource": [
|
||||
"arn:aws:s3:::nakama-media/*"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"s3:ListBucket"
|
||||
],
|
||||
"Resource": [
|
||||
"arn:aws:s3:::nakama-media"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Назначьте Policy пользователю.**
|
||||
|
||||
**Создайте Service Account для пользователя** и используйте его credentials в .env.
|
||||
|
||||
### 2. Ограничьте доступ к API порту
|
||||
|
||||
На сервере MinIO:
|
||||
|
||||
```bash
|
||||
# Разрешить доступ только с IP приложения
|
||||
ufw allow from YOUR_APP_SERVER_IP to any port 9000
|
||||
|
||||
# Консоль можно ограничить вашим IP
|
||||
ufw allow from YOUR_IP to any port 9901
|
||||
```
|
||||
|
||||
### 3. Настройте HTTPS
|
||||
|
||||
```bash
|
||||
# На сервере MinIO:
|
||||
mkdir -p ~/.minio/certs
|
||||
|
||||
# Скопируйте SSL сертификаты
|
||||
cp /path/to/cert.pem ~/.minio/certs/public.crt
|
||||
cp /path/to/key.pem ~/.minio/certs/private.key
|
||||
|
||||
# Перезапустите MinIO
|
||||
systemctl restart minio
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Отличия S3 SDK от MinIO SDK
|
||||
|
||||
### MinIO SDK (старый):
|
||||
```javascript
|
||||
const Minio = require('minio');
|
||||
const client = new Minio.Client({
|
||||
endPoint: '103.80.87.247',
|
||||
port: 9000,
|
||||
useSSL: false,
|
||||
accessKey: 'key',
|
||||
secretKey: 'secret'
|
||||
});
|
||||
```
|
||||
|
||||
### AWS S3 SDK (новый, используем):
|
||||
```javascript
|
||||
const { S3Client } = require('@aws-sdk/client-s3');
|
||||
const client = new S3Client({
|
||||
endpoint: 'http://103.80.87.247:9000',
|
||||
region: 'us-east-1',
|
||||
credentials: {
|
||||
accessKeyId: 'key',
|
||||
secretAccessKey: 'secret'
|
||||
},
|
||||
forcePathStyle: true // Важно для MinIO!
|
||||
});
|
||||
```
|
||||
|
||||
**Преимущества S3 SDK:**
|
||||
- ✅ Официальный AWS SDK (лучше поддержка)
|
||||
- ✅ Работает с любым S3-совместимым хранилищем
|
||||
- ✅ Больше функций и опций
|
||||
- ✅ Лучшая типизация для TypeScript
|
||||
- ✅ Модульная структура (меньше размер bundle)
|
||||
|
||||
---
|
||||
|
||||
## 📊 Структура хранения
|
||||
|
||||
```
|
||||
MinIO Server (103.80.87.247:9000)
|
||||
│
|
||||
└── nakama-media/ ← Bucket
|
||||
├── posts/ ← Посты пользователей
|
||||
│ ├── 1700000000-123.jpg
|
||||
│ ├── 1700000001-456.png
|
||||
│ └── ...
|
||||
├── avatars/ ← Аватары
|
||||
│ └── ...
|
||||
└── channel/ ← Публикации в канал
|
||||
└── ...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚨 Решение проблем
|
||||
|
||||
### Проблема: "Connection refused" на порту 9000
|
||||
|
||||
**Причина:** MinIO API не слушает на порту 9000
|
||||
|
||||
**Решение:**
|
||||
```bash
|
||||
# На сервере MinIO проверьте:
|
||||
netstat -tulpn | grep 9000
|
||||
|
||||
# Если пусто, проверьте конфигурацию MinIO
|
||||
systemctl status minio
|
||||
|
||||
# Проверьте переменные окружения
|
||||
cat /etc/default/minio
|
||||
```
|
||||
|
||||
### Проблема: "Access Denied"
|
||||
|
||||
**Причина:** Неверные credentials или недостаточно прав
|
||||
|
||||
**Решение:**
|
||||
1. Проверьте Access Key и Secret Key в .env
|
||||
2. Проверьте policy пользователя в MinIO Console
|
||||
3. Убедитесь что bucket существует
|
||||
|
||||
### Проблема: "Bucket does not exist"
|
||||
|
||||
**Решение:**
|
||||
```bash
|
||||
# Создайте bucket через AWS CLI:
|
||||
aws s3 mb s3://nakama-media \
|
||||
--endpoint-url http://103.80.87.247:9000 \
|
||||
--profile minio
|
||||
|
||||
# Или в MinIO Console:
|
||||
# Object Browser → Create Bucket → nakama-media
|
||||
```
|
||||
|
||||
### Проблема: "forcePathStyle" не работает
|
||||
|
||||
**Причина:** Старая версия MinIO или неправильный endpoint
|
||||
|
||||
**Решение:**
|
||||
```env
|
||||
# Убедитесь что endpoint БЕЗ протокола в config:
|
||||
MINIO_ENDPOINT=103.80.87.247 # ✅ Правильно
|
||||
MINIO_ENDPOINT=http://103.80.87.247 # ❌ Неправильно
|
||||
```
|
||||
|
||||
### Проблема: CORS ошибки при доступе к файлам
|
||||
|
||||
**Решение:** Настройте CORS в MinIO Console
|
||||
```bash
|
||||
# Через mc (MinIO Client):
|
||||
mc admin config set myminio api cors_allow_origin="*"
|
||||
mc admin service restart myminio
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 Пример использования в коде
|
||||
|
||||
### Загрузка файла:
|
||||
|
||||
```javascript
|
||||
const { uploadFile } = require('./utils/minio');
|
||||
|
||||
// В route handler:
|
||||
const fileUrl = await uploadFile(
|
||||
req.file.buffer, // Buffer из multer
|
||||
req.file.originalname,
|
||||
req.file.mimetype,
|
||||
'posts' // Папка
|
||||
);
|
||||
|
||||
console.log('File URL:', fileUrl);
|
||||
// http://103.80.87.247:9000/nakama-media/posts/1700000000-123.jpg
|
||||
```
|
||||
|
||||
### Удаление файла:
|
||||
|
||||
```javascript
|
||||
const { deleteFile } = require('./utils/minio');
|
||||
|
||||
await deleteFile('http://103.80.87.247:9000/nakama-media/posts/1700000000-123.jpg');
|
||||
```
|
||||
|
||||
### Получение presigned URL:
|
||||
|
||||
```javascript
|
||||
const { getPresignedUrl } = require('./utils/minio');
|
||||
|
||||
const url = await getPresignedUrl('posts/1700000000-123.jpg', 3600); // 1 час
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Checklist настройки
|
||||
|
||||
- [ ] MinIO работает на 103.80.87.247
|
||||
- [ ] Console доступен на :9901
|
||||
- [ ] API доступен на :9000
|
||||
- [ ] Создан bucket `nakama-media`
|
||||
- [ ] Созданы Access Key и Secret Key
|
||||
- [ ] Обновлен .env с правильными credentials
|
||||
- [ ] Установлены npm пакеты (`npm install`)
|
||||
- [ ] Перезапущен Docker (`docker-compose up -d`)
|
||||
- [ ] Проверены логи (`docker-compose logs backend`)
|
||||
- [ ] Создан тестовый пост с изображением
|
||||
- [ ] Файл появился в MinIO Console
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Следующие шаги
|
||||
|
||||
1. ✅ **Проверьте подключение:** создайте пост с изображением
|
||||
2. 🔒 **Настройте безопасность:** создайте отдельного пользователя
|
||||
3. 🌐 **Настройте домен:** вместо IP используйте домен
|
||||
4. 🔐 **Включите HTTPS:** для продакшена
|
||||
5. 📊 **Настройте мониторинг:** следите за использованием
|
||||
6. 💾 **Настройте бекапы:** регулярное резервное копирование
|
||||
|
||||
---
|
||||
|
||||
**Готово!** Теперь все файлы загружаются в ваш MinIO через S3 SDK! 🚀
|
||||
|
||||
260
SETUP.md
260
SETUP.md
|
|
@ -1,260 +0,0 @@
|
|||
# NakamaSpace - Инструкция по установке и запуску
|
||||
|
||||
## 📋 Требования
|
||||
|
||||
- Node.js 16+ и npm
|
||||
- MongoDB 5+
|
||||
- Telegram Bot Token (получить у [@BotFather](https://t.me/BotFather))
|
||||
|
||||
## 🚀 Установка
|
||||
|
||||
### 1. Установить зависимости
|
||||
|
||||
```bash
|
||||
# Установка зависимостей backend
|
||||
npm install
|
||||
|
||||
# Установка зависимостей frontend
|
||||
cd frontend
|
||||
npm install
|
||||
cd ..
|
||||
```
|
||||
|
||||
### 2. Настроить переменные окружения
|
||||
|
||||
Создайте файл `.env` в корне проекта:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Отредактируйте `.env`:
|
||||
|
||||
```
|
||||
MONGODB_URI=mongodb://localhost:27017/nakama
|
||||
PORT=3000
|
||||
JWT_SECRET=your_secret_key_here
|
||||
TELEGRAM_BOT_TOKEN=your_bot_token_here
|
||||
NODE_ENV=development
|
||||
```
|
||||
|
||||
Создайте файл `frontend/.env`:
|
||||
|
||||
```bash
|
||||
cp frontend/.env.example frontend/.env
|
||||
```
|
||||
|
||||
### 3. Запустить MongoDB
|
||||
|
||||
```bash
|
||||
# macOS с Homebrew
|
||||
brew services start mongodb-community
|
||||
|
||||
# Linux
|
||||
sudo systemctl start mongod
|
||||
|
||||
# Или запустите вручную
|
||||
mongod --dbpath /path/to/data/directory
|
||||
```
|
||||
|
||||
### 4. Создать Telegram бота
|
||||
|
||||
1. Откройте [@BotFather](https://t.me/BotFather) в Telegram
|
||||
2. Отправьте `/newbot` и следуйте инструкциям
|
||||
3. Получите токен бота и добавьте в `.env`
|
||||
4. Настройте Web App:
|
||||
- `/mybots` → выберите бота → Bot Settings → Menu Button
|
||||
- Укажите URL вашего приложения
|
||||
|
||||
## 🏃 Запуск приложения
|
||||
|
||||
### Режим разработки
|
||||
|
||||
```bash
|
||||
# Запустить backend и frontend одновременно
|
||||
npm run dev
|
||||
|
||||
# Или запустить по отдельности:
|
||||
|
||||
# Backend (http://localhost:3000)
|
||||
npm run server
|
||||
|
||||
# Frontend (http://localhost:5173)
|
||||
npm run client
|
||||
```
|
||||
|
||||
### Production
|
||||
|
||||
```bash
|
||||
# Собрать frontend
|
||||
npm run build
|
||||
|
||||
# Запустить production сервер
|
||||
npm start
|
||||
```
|
||||
|
||||
## 🔧 Настройка Telegram Mini App
|
||||
|
||||
### Локальная разработка
|
||||
|
||||
Для тестирования локально:
|
||||
|
||||
1. Используйте ngrok или подобный туннель:
|
||||
```bash
|
||||
ngrok http 5173
|
||||
```
|
||||
|
||||
2. Скопируйте HTTPS URL от ngrok
|
||||
|
||||
3. Настройте Menu Button в BotFather с этим URL
|
||||
|
||||
### Production деплой
|
||||
|
||||
Рекомендуемые платформы:
|
||||
- **Backend**: Railway, Render, Heroku
|
||||
- **Frontend**: Vercel, Netlify
|
||||
- **MongoDB**: MongoDB Atlas
|
||||
|
||||
Пример деплоя на Railway:
|
||||
|
||||
```bash
|
||||
# Установить Railway CLI
|
||||
npm i -g @railway/cli
|
||||
|
||||
# Войти
|
||||
railway login
|
||||
|
||||
# Создать проект
|
||||
railway init
|
||||
|
||||
# Деплой
|
||||
railway up
|
||||
```
|
||||
|
||||
## 📱 Тестирование
|
||||
|
||||
1. Откройте бота в Telegram
|
||||
2. Нажмите на кнопку меню или отправьте команду
|
||||
3. Приложение откроется как Mini App
|
||||
|
||||
## 🛠️ Структура проекта
|
||||
|
||||
```
|
||||
nakama/
|
||||
├── backend/ # Backend сервер
|
||||
│ ├── models/ # MongoDB модели
|
||||
│ ├── routes/ # API endpoints
|
||||
│ ├── middleware/ # Middleware (auth, etc)
|
||||
│ └── server.js # Точка входа
|
||||
├── frontend/ # Frontend React приложение
|
||||
│ ├── src/
|
||||
│ │ ├── components/ # React компоненты
|
||||
│ │ ├── pages/ # Страницы-вкладки
|
||||
│ │ ├── utils/ # Утилиты (API, Telegram)
|
||||
│ │ └── styles/ # CSS стили
|
||||
│ └── index.html
|
||||
└── package.json
|
||||
```
|
||||
|
||||
## 🎨 Дизайн-система
|
||||
|
||||
Проект использует минималистичный iOS-стиль с палитрой:
|
||||
|
||||
- **Фон**: #F2F3F5
|
||||
- **Карточки**: #FFFFFF
|
||||
- **Текст**: #1C1C1E
|
||||
- **Furry теги**: #FF8A33
|
||||
- **Anime теги**: #4A90E2
|
||||
- **Other теги**: #A0A0A0
|
||||
|
||||
## 🔐 Модерация
|
||||
|
||||
Для назначения модераторов/админов:
|
||||
|
||||
```javascript
|
||||
// Подключиться к MongoDB
|
||||
mongo nakama
|
||||
|
||||
// Обновить роль пользователя
|
||||
db.users.updateOne(
|
||||
{ telegramId: "YOUR_TELEGRAM_ID" },
|
||||
{ $set: { role: "admin" } }
|
||||
)
|
||||
```
|
||||
|
||||
Роли:
|
||||
- `user` - обычный пользователь
|
||||
- `moderator` - может модерировать контент
|
||||
- `admin` - полные права
|
||||
|
||||
## 📚 API Документация
|
||||
|
||||
### Основные endpoints:
|
||||
|
||||
#### Авторизация
|
||||
- `POST /api/auth/verify` - Верификация Telegram Init Data
|
||||
|
||||
#### Посты
|
||||
- `GET /api/posts` - Получить ленту постов
|
||||
- `POST /api/posts` - Создать пост
|
||||
- `POST /api/posts/:id/like` - Лайкнуть пост
|
||||
- `POST /api/posts/:id/comment` - Добавить комментарий
|
||||
- `POST /api/posts/:id/repost` - Репостнуть
|
||||
- `DELETE /api/posts/:id` - Удалить пост
|
||||
|
||||
#### Пользователи
|
||||
- `GET /api/users/:id` - Получить профиль
|
||||
- `GET /api/users/:id/posts` - Получить посты пользователя
|
||||
- `POST /api/users/:id/follow` - Подписаться/отписаться
|
||||
- `PUT /api/users/profile` - Обновить профиль
|
||||
- `GET /api/users/search/:query` - Поиск пользователей
|
||||
|
||||
#### Уведомления
|
||||
- `GET /api/notifications` - Получить уведомления
|
||||
- `PUT /api/notifications/:id/read` - Отметить как прочитанное
|
||||
- `PUT /api/notifications/read-all` - Прочитать все
|
||||
|
||||
#### Поиск
|
||||
- `GET /api/search/furry?query=tags` - Поиск в e621
|
||||
- `GET /api/search/anime?query=tags` - Поиск в gelbooru
|
||||
- `GET /api/search/furry/tags?query=tag` - Автокомплит тегов e621
|
||||
- `GET /api/search/anime/tags?query=tag` - Автокомплит тегов gelbooru
|
||||
- `GET /api/search/proxy/:encodedUrl` - Проксирование изображений с e621/gelbooru (для доступа из РФ)
|
||||
|
||||
#### Модерация
|
||||
- `POST /api/moderation/report` - Создать жалобу
|
||||
- `GET /api/moderation/reports` - Получить жалобы (модераторы)
|
||||
- `PUT /api/moderation/reports/:id` - Обработать жалобу
|
||||
- `PUT /api/moderation/posts/:id/nsfw` - Установить NSFW флаг
|
||||
- `PUT /api/moderation/users/:id/ban` - Заблокировать пользователя
|
||||
|
||||
## ⚠️ Troubleshooting
|
||||
|
||||
### MongoDB не подключается
|
||||
```bash
|
||||
# Проверить статус
|
||||
brew services list # macOS
|
||||
sudo systemctl status mongod # Linux
|
||||
|
||||
# Проверить порт
|
||||
lsof -i :27017
|
||||
```
|
||||
|
||||
### CORS ошибки
|
||||
Убедитесь что `VITE_API_URL` в `frontend/.env` указывает на правильный адрес backend
|
||||
|
||||
### Telegram Init Data invalid
|
||||
В dev режиме проверка отключена, но для production нужен валидный `TELEGRAM_BOT_TOKEN`
|
||||
|
||||
## 📞 Поддержка
|
||||
|
||||
Если возникли проблемы:
|
||||
1. Проверьте логи: `npm run server`
|
||||
2. Откройте DevTools в браузере
|
||||
3. Проверьте MongoDB подключение
|
||||
4. Убедитесь что все переменные окружения установлены
|
||||
|
||||
## 🎉 Готово!
|
||||
|
||||
Приложение должно работать! Откройте бота в Telegram и начните использовать NakamaSpace.
|
||||
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
# 🔧 Установка Telegram Bot Token
|
||||
|
||||
## Проблема
|
||||
|
||||
Ошибка: `TELEGRAM_BOT_TOKEN не установлен`
|
||||
|
||||
## Решение
|
||||
|
||||
### 1. Получить токен от BotFather
|
||||
|
||||
1. Откройте Telegram
|
||||
2. Найдите бота [@BotFather](https://t.me/BotFather)
|
||||
3. Отправьте команду `/newbot`
|
||||
4. Следуйте инструкциям:
|
||||
- Введите имя бота (например: `My Nakama Bot`)
|
||||
- Введите username бота (например: `my_nakama_bot`)
|
||||
5. Получите токен (формат: `123456789:ABCdefGHIjklMNOpqrsTUVwxyz`)
|
||||
|
||||
### 2. Установить токен на сервере
|
||||
|
||||
#### Вариант A: Через .env файл (Рекомендуется)
|
||||
|
||||
```bash
|
||||
ssh root@ваш_IP
|
||||
cd /var/www/nakama/backend
|
||||
|
||||
# Создать .env файл если его нет
|
||||
nano .env
|
||||
|
||||
# Добавить строку:
|
||||
TELEGRAM_BOT_TOKEN=ваш_токен_от_BotFather
|
||||
|
||||
# Сохранить: Ctrl+O, Enter, Ctrl+X
|
||||
```
|
||||
|
||||
#### Вариант B: Через PM2 ecosystem
|
||||
|
||||
```bash
|
||||
ssh root@ваш_IP
|
||||
cd /var/www/nakama
|
||||
|
||||
# Создать ecosystem.config.js
|
||||
nano ecosystem.config.js
|
||||
```
|
||||
|
||||
Добавьте:
|
||||
```javascript
|
||||
module.exports = {
|
||||
apps: [{
|
||||
name: 'nakama-backend',
|
||||
script: './backend/server.js',
|
||||
env: {
|
||||
NODE_ENV: 'production',
|
||||
TELEGRAM_BOT_TOKEN: 'ваш_токен_от_BotFather',
|
||||
// ... другие переменные
|
||||
}
|
||||
}]
|
||||
};
|
||||
```
|
||||
|
||||
#### Вариант C: Через export (Временное решение)
|
||||
|
||||
```bash
|
||||
ssh root@ваш_IP
|
||||
export TELEGRAM_BOT_TOKEN="ваш_токен_от_BotFather"
|
||||
pm2 restart nakama-backend --update-env
|
||||
```
|
||||
|
||||
### 3. Перезапустить backend
|
||||
|
||||
```bash
|
||||
pm2 restart nakama-backend
|
||||
```
|
||||
|
||||
### 4. Проверить логи
|
||||
|
||||
```bash
|
||||
pm2 logs nakama-backend --lines 20
|
||||
```
|
||||
|
||||
Должно быть:
|
||||
```
|
||||
✅ Telegram Bot инициализирован
|
||||
```
|
||||
|
||||
**Не должно быть:**
|
||||
```
|
||||
⚠️ TELEGRAM_BOT_TOKEN не установлен!
|
||||
```
|
||||
|
||||
## Проверка работы
|
||||
|
||||
После установки токена:
|
||||
1. Откройте приложение
|
||||
2. Попробуйте отправить изображение в Telegram из поиска
|
||||
3. Изображение должно прийти в личные сообщения с ботом
|
||||
|
||||
## Важно
|
||||
|
||||
- Токен должен быть в формате: `123456789:ABCdefGHIjklMNOpqrsTUVwxyz`
|
||||
- **НЕ** добавляйте кавычки в .env файле!
|
||||
- **НЕ** делитесь токеном публично!
|
||||
- Токен должен быть установлен до запуска бота
|
||||
|
||||
## Пример .env файла
|
||||
|
||||
```env
|
||||
NODE_ENV=production
|
||||
PORT=3000
|
||||
MONGODB_URI=mongodb://localhost:27017/nakama
|
||||
TELEGRAM_BOT_TOKEN=123456789:ABCdefGHIjklMNOpqrsTUVwxyz
|
||||
FRONTEND_URL=https://nakama.glpshchn.ru
|
||||
```
|
||||
|
||||
## Дополнительная информация
|
||||
|
||||
- [Telegram Bot API](https://core.telegram.org/bots/api)
|
||||
- [BotFather](https://t.me/BotFather)
|
||||
|
||||
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
╔═══════════════════════════════════════════════════════════════════════╗
|
||||
║ Простое исправление тёмной темы ║
|
||||
╚═══════════════════════════════════════════════════════════════════════╝
|
||||
|
||||
РЕШЕНИЕ: Инверсия цветов для фильтров в тёмной теме
|
||||
|
||||
Светлая тема: Серые кнопки с тёмным текстом
|
||||
Тёмная тема: БЕЛЫЕ кнопки с ЧЁРНЫМ текстом
|
||||
|
||||
Активная кнопка: СИНЯЯ в обеих темах
|
||||
|
||||
|
||||
ОБНОВИТЬ (2 минуты):
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
НА КОМПЬЮТЕРЕ:
|
||||
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
|
||||
scp frontend/src/pages/Feed.css root@ваш_IP:/var/www/nakama/frontend/src/pages/
|
||||
scp frontend/src/pages/Search.css root@ваш_IP:/var/www/nakama/frontend/src/pages/
|
||||
|
||||
|
||||
НА СЕРВЕРЕ:
|
||||
|
||||
ssh root@ваш_IP
|
||||
cd /var/www/nakama/frontend
|
||||
npm run build
|
||||
|
||||
|
||||
✅ ГОТОВО!
|
||||
|
||||
Проверьте: https://nakama.glpshchn.ru
|
||||
|
||||
|
||||
ИЗМЕНЕНО:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✓ Feed.css - кнопки фильтров (Все, Furry, Anime, Other)
|
||||
✓ Search.css - кнопки режимов (Furry, Anime, Mixed)
|
||||
|
||||
Backend перезапускать НЕ нужно!
|
||||
|
||||
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
# 🎯 Окончательное исправление - v2.1.3
|
||||
|
||||
## Решение для комментариев:
|
||||
|
||||
### Использовано: dvh + Telegram WebApp API (комбинация методов 1 и 3)
|
||||
|
||||
#### 1. **dvh вместо vh**
|
||||
```css
|
||||
.comments-modal {
|
||||
height: 60dvh; /* НЕ меняется при клавиатуре */
|
||||
max-height: 60vh; /* fallback */
|
||||
position: fixed;
|
||||
bottom: 80px;
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. **Telegram WebApp API**
|
||||
```javascript
|
||||
useEffect(() => {
|
||||
const tg = getTelegramApp()
|
||||
|
||||
tg.onEvent('viewportChanged', () => {
|
||||
// Фиксируем высоту при изменении viewport
|
||||
modalRef.current.style.height = currentHeight + 'px'
|
||||
})
|
||||
}, [])
|
||||
```
|
||||
|
||||
#### 3. **Правильный onClick**
|
||||
```javascript
|
||||
const handleOverlayClick = (e) => {
|
||||
if (e.target === e.currentTarget) {
|
||||
onClose()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Кнопки в тёмной теме:
|
||||
|
||||
### ВСЕ кнопки БЕЛЫЕ с чёрным текстом:
|
||||
|
||||
**Неактивная кнопка:**
|
||||
- Фон: `#FFFFFF` (белый)
|
||||
- Текст: `#000000` (чёрный)
|
||||
|
||||
**Активная кнопка:**
|
||||
- Фон: `#FFFFFF` (белый!)
|
||||
- Текст: синий
|
||||
- Рамка: 2px синяя
|
||||
|
||||
Это НЕ синие кнопки, а **белые с синей рамкой и текстом**!
|
||||
|
||||
---
|
||||
|
||||
## Изменённые файлы:
|
||||
|
||||
1. `frontend/src/components/CommentsModal.jsx` - useEffect с Telegram API
|
||||
2. `frontend/src/components/CommentsModal.css` - dvh + fixed positioning
|
||||
3. `frontend/src/pages/Feed.css` - белые кнопки, синяя рамка для active
|
||||
4. `frontend/src/pages/Search.css` - белые кнопки, синяя рамка для active
|
||||
|
||||
---
|
||||
|
||||
## Обновление:
|
||||
|
||||
```bash
|
||||
# НА КОМПЬЮТЕРЕ
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
|
||||
scp frontend/src/components/CommentsModal.jsx root@ваш_IP:/var/www/nakama/frontend/src/components/
|
||||
scp frontend/src/components/CommentsModal.css root@ваш_IP:/var/www/nakama/frontend/src/components/
|
||||
scp frontend/src/pages/Feed.css root@ваш_IP:/var/www/nakama/frontend/src/pages/
|
||||
scp frontend/src/pages/Search.css root@ваш_IP:/var/www/nakama/frontend/src/pages/
|
||||
|
||||
# НА СЕРВЕРЕ
|
||||
ssh root@ваш_IP
|
||||
cd /var/www/nakama/frontend
|
||||
npm run build
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Результат:
|
||||
|
||||
✅ Комментарии не прыгают (dvh + Telegram API)
|
||||
✅ Кнопки БЕЛЫЕ в тёмной теме
|
||||
✅ Активная кнопка - белая с синей рамкой
|
||||
✅ Всё работает идеально
|
||||
|
||||
|
||||
201
UPDATES_v2.1.md
201
UPDATES_v2.1.md
|
|
@ -1,201 +0,0 @@
|
|||
# 🎉 NakamaSpace v2.1 - Changelog
|
||||
|
||||
## Дата: 03.11.2025
|
||||
|
||||
### 🐛 Исправлены критические баги:
|
||||
|
||||
#### 1. ✅ Окно комментариев
|
||||
- **Было**: При нажатии на поле ввода блок "упрыгивал" вверх, поле неактивно
|
||||
- **Стало**:
|
||||
- Модальное окно фиксировано на весь экран
|
||||
- Форма ввода закреплена внизу
|
||||
- Поле полностью активно и доступно
|
||||
- Правильно работает с мобильной клавиатурой
|
||||
|
||||
#### 2. ✅ Репосты удалены
|
||||
- **Было**: Кнопка репоста не работала
|
||||
- **Стало**:
|
||||
- Кнопка полностью удалена
|
||||
- Остались только Лайки ❤️ и Комментарии 💬
|
||||
- Упрощён интерфейс
|
||||
|
||||
#### 3. ✅ Видимость в тёмной теме
|
||||
- **Было**: Иконки белые и невидимы, текст теряется
|
||||
- **Стало**:
|
||||
- Все иконки используют правильный цвет (`currentColor`)
|
||||
- Кнопки видны и контрастны
|
||||
- Навигация чёткая
|
||||
- Кнопка "+" стала синей (более заметная)
|
||||
|
||||
#### 4. ✅ Фильтры упрощены
|
||||
- **Было**: 3 фильтра (Furry, Anime, NSFW) не работали правильно
|
||||
- **Стало**:
|
||||
- Убраны "Без Furry" и "Только Anime"
|
||||
- Остался только "Скрыть контент 18+"
|
||||
- Настройка автоматически сохраняется на сервер
|
||||
- По умолчанию все посты видны
|
||||
|
||||
#### 5. ✅ Блок донатов удалён
|
||||
- Убран блок "Поддержать разработчиков"
|
||||
- Упрощён интерфейс профиля
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Технические изменения:
|
||||
|
||||
### Frontend:
|
||||
- `PostCard.jsx` - убраны репосты, улучшены stroke для иконок
|
||||
- `CommentsModal.css` - fixed позиционирование
|
||||
- `CreatePostModal.css` - убран margin-bottom
|
||||
- `Navigation.css` - явный stroke для иконок
|
||||
- `Feed.css` - синяя кнопка создания
|
||||
- `Profile.jsx` - автосохранение настроек, убраны фильтры
|
||||
- `Notifications.jsx` - убран тип repost
|
||||
- `index.css` - расширенные правила для тёмной темы
|
||||
|
||||
### Backend:
|
||||
- `models/Post.js` - удалено поле reposts
|
||||
- `models/Notification.js` - удалён тип repost
|
||||
- `routes/posts.js` - удалён endpoint репостов
|
||||
- `utils/statistics.js` - убраны репосты из статистики
|
||||
- `models/User.js` - noNSFW default = false
|
||||
|
||||
### Database:
|
||||
- Удалено поле `reposts` из всех постов
|
||||
- Удалены уведомления типа 'repost'
|
||||
- Отключены все фильтры для существующих пользователей
|
||||
|
||||
---
|
||||
|
||||
## 📦 Установка обновления:
|
||||
|
||||
### На сервере выполните:
|
||||
|
||||
```bash
|
||||
# 1. Подключитесь к серверу
|
||||
ssh root@ваш_IP
|
||||
|
||||
# 2. Перейдите в проект
|
||||
cd /var/www/nakama
|
||||
|
||||
# 3. Замените файлы новыми версиями
|
||||
# (загрузите через scp или git pull)
|
||||
|
||||
# 4. Установите зависимости
|
||||
npm install --production
|
||||
cd frontend && npm install && npm run build && cd ..
|
||||
|
||||
# 5. Обновите базу данных
|
||||
mongosh nakama --eval '
|
||||
// Отключить фильтры
|
||||
db.users.updateMany(
|
||||
{},
|
||||
{ $set: {
|
||||
"settings.whitelist.noNSFW": false,
|
||||
"settings.whitelist.noFurry": false,
|
||||
"settings.whitelist.onlyAnime": false
|
||||
}}
|
||||
);
|
||||
|
||||
// Удалить репосты
|
||||
db.posts.updateMany({}, { $unset: { reposts: "" } });
|
||||
db.notifications.deleteMany({ type: "repost" });
|
||||
|
||||
print("✅ База данных обновлена");
|
||||
'
|
||||
|
||||
# 6. Перезапустите backend
|
||||
pm2 restart nakama-backend
|
||||
|
||||
# 7. Проверьте
|
||||
pm2 logs nakama-backend --lines 30
|
||||
curl https://nakama.glpshchn.ru/health
|
||||
```
|
||||
|
||||
### Автоматический скрипт:
|
||||
|
||||
```bash
|
||||
# Используйте обновлённый скрипт
|
||||
cd /var/www/nakama
|
||||
./update-server.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Проверка после обновления:
|
||||
|
||||
### В приложении (https://nakama.glpshchn.ru):
|
||||
|
||||
1. **Комментарии**:
|
||||
- [ ] Откройте любой пост
|
||||
- [ ] Нажмите на иконку комментариев 💬
|
||||
- [ ] Окно должно открыться на весь экран
|
||||
- [ ] Нажмите на поле ввода внизу
|
||||
- [ ] Поле должно стать активным без прыжков
|
||||
- [ ] Введите комментарий и отправьте
|
||||
|
||||
2. **Репосты**:
|
||||
- [ ] В карточке поста должны быть только 2 кнопки: ❤️ и 💬
|
||||
- [ ] Кнопки репоста нет
|
||||
|
||||
3. **Тёмная тема**:
|
||||
- [ ] Профиль → Переключите тему на "Тёмная"
|
||||
- [ ] Все иконки должны быть видны (белые/серые)
|
||||
- [ ] Кнопка "+" вверху синяя
|
||||
- [ ] Три точки (меню) видны
|
||||
- [ ] Навигация внизу видна
|
||||
- [ ] Все тексты читаемы
|
||||
|
||||
4. **Фильтр NSFW**:
|
||||
- [ ] Профиль → должна быть только одна настройка "Скрыть контент 18+"
|
||||
- [ ] Переключите её
|
||||
- [ ] Посты должны появиться/исчезнуть сразу
|
||||
|
||||
5. **Донаты**:
|
||||
- [ ] В профиле не должно быть блока "Поддержать разработчиков"
|
||||
|
||||
---
|
||||
|
||||
## 📊 Статистика изменений:
|
||||
|
||||
- **Удалено строк кода**: ~200
|
||||
- **Изменено файлов**: 13
|
||||
- **Исправлено багов**: 5
|
||||
- **Время обновления на сервере**: ~5 минут
|
||||
|
||||
---
|
||||
|
||||
## 🚀 После обновления получите:
|
||||
|
||||
✅ Полностью рабочее окно комментариев
|
||||
✅ Упрощённый интерфейс без репостов
|
||||
✅ Идеальную видимость в тёмной теме
|
||||
✅ Рабочий фильтр NSFW
|
||||
✅ Чистый профиль без донатов
|
||||
|
||||
---
|
||||
|
||||
## 📞 Если что-то не работает:
|
||||
|
||||
```bash
|
||||
# Проверить логи
|
||||
pm2 logs nakama-backend
|
||||
|
||||
# Проверить процессы
|
||||
pm2 status
|
||||
|
||||
# Перезапустить всё
|
||||
pm2 restart nakama-backend
|
||||
sudo systemctl restart nginx
|
||||
|
||||
# Проверить MongoDB
|
||||
mongosh nakama --eval 'db.posts.findOne()'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**NakamaSpace v2.1 готов! 🎉**
|
||||
|
||||
Теперь приложение работает стабильно на https://nakama.glpshchn.ru
|
||||
|
||||
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
# 📤 Как загрузить обновления на nakama.glpshchn.ru
|
||||
|
||||
## Быстрая инструкция:
|
||||
|
||||
### Шаг 1: Упаковать проект (на вашем компьютере)
|
||||
|
||||
```bash
|
||||
cd /Users/glpshchn/Desktop
|
||||
|
||||
# Упаковать проект
|
||||
tar -czf nakama-v2.1.tar.gz nakama \
|
||||
--exclude='nakama/node_modules' \
|
||||
--exclude='nakama/frontend/node_modules' \
|
||||
--exclude='nakama/frontend/dist' \
|
||||
--exclude='nakama/backend/uploads' \
|
||||
--exclude='nakama/.git'
|
||||
|
||||
# Проверить размер архива
|
||||
ls -lh nakama-v2.1.tar.gz
|
||||
```
|
||||
|
||||
### Шаг 2: Загрузить на сервер
|
||||
|
||||
```bash
|
||||
# Загрузить архив
|
||||
scp nakama-v2.1.tar.gz root@ваш_IP:/tmp/
|
||||
|
||||
# Подключиться к серверу
|
||||
ssh root@ваш_IP
|
||||
```
|
||||
|
||||
### Шаг 3: Развернуть на сервере
|
||||
|
||||
```bash
|
||||
# Сделать бэкап текущей версии
|
||||
cd /var/www
|
||||
sudo tar -czf ~/nakama-backup-$(date +%Y%m%d_%H%M%S).tar.gz nakama
|
||||
|
||||
# Удалить старую версию (кроме uploads и .env)
|
||||
cd nakama
|
||||
cp .env /tmp/nakama.env
|
||||
cp -r backend/uploads /tmp/nakama-uploads
|
||||
cd ..
|
||||
sudo rm -rf nakama
|
||||
|
||||
# Распаковать новую версию
|
||||
sudo tar -xzf /tmp/nakama-v2.1.tar.gz
|
||||
sudo chown -R $USER:$USER nakama
|
||||
cd nakama
|
||||
|
||||
# Восстановить .env и uploads
|
||||
cp /tmp/nakama.env .env
|
||||
mkdir -p backend/uploads
|
||||
cp -r /tmp/nakama-uploads/* backend/uploads/
|
||||
rm -rf /tmp/nakama-uploads /tmp/nakama.env
|
||||
|
||||
# Запустить скрипт обновления
|
||||
chmod +x update-server.sh
|
||||
./update-server.sh
|
||||
```
|
||||
|
||||
### Всё! Готово! ✅
|
||||
|
||||
Проверьте: https://nakama.glpshchn.ru
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Быстрая проверка:
|
||||
|
||||
```bash
|
||||
# Статус
|
||||
pm2 status
|
||||
|
||||
# Логи (должны быть без ошибок)
|
||||
pm2 logs nakama-backend --lines 50
|
||||
|
||||
# API
|
||||
curl https://nakama.glpshchn.ru/health
|
||||
# Должно вернуть: {"status":"ok","environment":"production",...}
|
||||
|
||||
# Посты в базе
|
||||
mongosh nakama --eval 'db.posts.countDocuments({})'
|
||||
|
||||
# Проверить что reposts удалены
|
||||
mongosh nakama --eval 'db.posts.findOne({}, {reposts: 1})'
|
||||
# reposts должно быть undefined/null
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📱 Проверка в Telegram:
|
||||
|
||||
1. Откройте вашего бота
|
||||
2. Нажмите Menu Button
|
||||
3. Проверьте что:
|
||||
- ✅ Приложение загружается
|
||||
- ✅ Посты видны
|
||||
- ✅ Комментарии работают
|
||||
- ✅ Тёмная тема работает
|
||||
- ✅ Всё видно и понятно
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Если нужно откатить:
|
||||
|
||||
```bash
|
||||
# Восстановить из бэкапа
|
||||
cd /var/www
|
||||
sudo rm -rf nakama
|
||||
sudo tar -xzf ~/nakama-backup-ДАТА.tar.gz
|
||||
pm2 restart nakama-backend
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 💡 Полезные команды:
|
||||
|
||||
```bash
|
||||
# Перезапустить всё
|
||||
pm2 restart nakama-backend
|
||||
sudo systemctl restart nginx
|
||||
|
||||
# Посмотреть логи
|
||||
pm2 logs nakama-backend
|
||||
tail -f /var/log/nginx/nakama_error.log
|
||||
|
||||
# Очистить кэш (если используете Redis)
|
||||
redis-cli FLUSHALL
|
||||
|
||||
# Проверить процессы
|
||||
pm2 status
|
||||
sudo systemctl status nginx
|
||||
sudo systemctl status mongod
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Готово! 🚀**
|
||||
|
||||
После выполнения этих шагов все исправления будут применены на https://nakama.glpshchn.ru
|
||||
|
||||
|
||||
58
VERSION.md
58
VERSION.md
|
|
@ -1,58 +0,0 @@
|
|||
# 📌 NakamaSpace - История версий
|
||||
|
||||
## v2.1 (03.11.2025) - Исправления и улучшения
|
||||
|
||||
### 🐛 Исправлено:
|
||||
- ✅ Окно комментариев теперь фиксировано и работает с клавиатурой
|
||||
- ✅ Удалён нерабочий функционал репостов
|
||||
- ✅ Исправлена видимость иконок и текста в тёмной теме
|
||||
- ✅ Упрощены фильтры (остался только NSFW)
|
||||
- ✅ Автоматическое сохранение настроек
|
||||
- ✅ Удалён блок донатов
|
||||
|
||||
### 🎨 Улучшено:
|
||||
- Кнопка создания поста стала синей (более заметная)
|
||||
- Все иконки теперь адаптивны к теме
|
||||
- Улучшена контрастность в тёмной теме
|
||||
- Упрощён интерфейс профиля
|
||||
|
||||
---
|
||||
|
||||
## v2.0 (03.11.2025) - Roadmap features
|
||||
|
||||
### ✨ Добавлено:
|
||||
- ✅ Dark mode с автоматическим определением
|
||||
- ✅ Rate limiting для защиты от спама
|
||||
- ✅ Redis кэширование (опционально)
|
||||
- ✅ Полнотекстовый поиск по постам
|
||||
- ✅ Система хэштегов (#теги)
|
||||
- ✅ Статистика для авторов
|
||||
- ✅ WebSocket real-time уведомления
|
||||
- ✅ Централизованная конфигурация
|
||||
- ✅ Production-ready деплой
|
||||
|
||||
---
|
||||
|
||||
## v1.0 (03.11.2025) - Первая версия
|
||||
|
||||
### 🎉 Базовый функционал:
|
||||
- ✅ 4 вкладки: Лента, Поиск, Уведомления, Профиль
|
||||
- ✅ Создание постов с изображениями
|
||||
- ✅ Обязательные теги (Furry, Anime, Other)
|
||||
- ✅ Лайки и комментарии
|
||||
- ✅ Интеграция e621 и gelbooru API
|
||||
- ✅ Система уведомлений
|
||||
- ✅ Профили и подписки
|
||||
- ✅ Модерация и жалобы
|
||||
- ✅ Telegram Mini App авторизация
|
||||
- ✅ iOS-стиль дизайн
|
||||
|
||||
---
|
||||
|
||||
## 📊 Текущая версия: v2.1
|
||||
|
||||
**Статус**: ✅ Production Ready
|
||||
**Домен**: nakama.glpshchn.ru
|
||||
**Последнее обновление**: 03.11.2025
|
||||
|
||||
|
||||
|
|
@ -19,30 +19,83 @@ const appendLog = (fileName, message) => {
|
|||
});
|
||||
};
|
||||
|
||||
// Цвета для консоли (ANSI коды)
|
||||
const colors = {
|
||||
reset: '\x1b[0m',
|
||||
bright: '\x1b[1m',
|
||||
dim: '\x1b[2m',
|
||||
red: '\x1b[31m',
|
||||
green: '\x1b[32m',
|
||||
yellow: '\x1b[33m',
|
||||
blue: '\x1b[34m',
|
||||
magenta: '\x1b[35m',
|
||||
cyan: '\x1b[36m',
|
||||
white: '\x1b[37m'
|
||||
};
|
||||
|
||||
// Эмодзи для уровней
|
||||
const levelEmojis = {
|
||||
debug: '🔍',
|
||||
info: '📝',
|
||||
success: '✅',
|
||||
warn: '⚠️',
|
||||
error: '❌',
|
||||
security: '🔒'
|
||||
};
|
||||
|
||||
// Функция для логирования
|
||||
const log = (level, message, data = {}) => {
|
||||
const timestamp = new Date().toISOString();
|
||||
const logMessage = `[${timestamp}] [${level.toUpperCase()}] ${message}`;
|
||||
const serializedData = Object.keys(data).length ? ` ${JSON.stringify(data)}` : '';
|
||||
const emoji = levelEmojis[level] || '📋';
|
||||
const logMessage = `[${timestamp}] ${emoji} [${level.toUpperCase()}] ${message}`;
|
||||
const serializedData = Object.keys(data).length ? ` ${JSON.stringify(data, null, 2)}` : '';
|
||||
const fullMessage = `${logMessage}${serializedData}`;
|
||||
|
||||
// Логирование в консоль
|
||||
// Логирование в консоль с цветами
|
||||
let colorCode = colors.reset;
|
||||
if (level === 'error') {
|
||||
console.error(logMessage, data);
|
||||
} else if (level === 'warn') {
|
||||
console.warn(logMessage, data);
|
||||
colorCode = colors.red;
|
||||
console.error(`${colors.bright}${colorCode}${logMessage}${colors.reset}`, data);
|
||||
} else if (level === 'warn' || level === 'security') {
|
||||
colorCode = colors.yellow;
|
||||
console.warn(`${colors.bright}${colorCode}${logMessage}${colors.reset}`, data);
|
||||
} else if (level === 'success') {
|
||||
colorCode = colors.green;
|
||||
console.log(`${colors.bright}${colorCode}${logMessage}${colors.reset}`, data);
|
||||
} else if (level === 'debug') {
|
||||
colorCode = colors.dim;
|
||||
console.log(`${colorCode}${logMessage}${colors.reset}`, data);
|
||||
} else {
|
||||
console.log(logMessage, data);
|
||||
colorCode = colors.cyan;
|
||||
console.log(`${colorCode}${logMessage}${colors.reset}`, data);
|
||||
}
|
||||
|
||||
const fileName = `${level}-${getDatePrefix()}.log`;
|
||||
appendLog(fileName, fullMessage);
|
||||
|
||||
// Также писать все логи в общий файл
|
||||
appendLog(`all-${getDatePrefix()}.log`, fullMessage);
|
||||
};
|
||||
|
||||
// Middleware для логирования запросов
|
||||
const requestLogger = (req, res, next) => {
|
||||
const start = Date.now();
|
||||
|
||||
// Логировать входящий запрос (только для важных роутов)
|
||||
if (req.path.startsWith('/api/') && !req.path.includes('/health')) {
|
||||
log('debug', 'Incoming request', {
|
||||
method: req.method,
|
||||
path: req.path,
|
||||
query: req.query,
|
||||
body: req.method === 'POST' || req.method === 'PUT' ?
|
||||
(req.body && Object.keys(req.body).length > 0 ?
|
||||
{ ...req.body, password: req.body.password ? '***' : undefined } :
|
||||
'empty') : undefined,
|
||||
ip: req.ip,
|
||||
userId: req.user?.id || req.user?._id || 'anonymous'
|
||||
});
|
||||
}
|
||||
|
||||
// Логировать после завершения запроса
|
||||
res.on('finish', () => {
|
||||
const duration = Date.now() - start;
|
||||
|
|
@ -52,12 +105,12 @@ const requestLogger = (req, res, next) => {
|
|||
status: res.statusCode,
|
||||
duration: `${duration}ms`,
|
||||
ip: req.ip,
|
||||
userAgent: req.get('user-agent'),
|
||||
userId: req.user?.id || 'anonymous'
|
||||
userAgent: req.get('user-agent')?.substring(0, 100),
|
||||
userId: req.user?.id || req.user?._id || 'anonymous'
|
||||
};
|
||||
|
||||
// Пропустить логирование для публичных роутов (health, корневой роут)
|
||||
if (req.path === '/health' || req.path === '/') {
|
||||
if (req.path === '/health' || req.path === '/' || req.path === '/favicon.ico') {
|
||||
// Логировать только ошибки для публичных роутов
|
||||
if (res.statusCode >= 400) {
|
||||
log('error', 'Request failed', logData);
|
||||
|
|
@ -65,14 +118,22 @@ const requestLogger = (req, res, next) => {
|
|||
return; // Не логировать успешные запросы к публичным роутам
|
||||
}
|
||||
|
||||
if (res.statusCode >= 400) {
|
||||
log('error', 'Request failed', logData);
|
||||
if (res.statusCode >= 500) {
|
||||
log('error', 'Server error', logData);
|
||||
} else if (res.statusCode >= 400) {
|
||||
log('warn', 'Client error', logData);
|
||||
} else if (res.statusCode >= 300 && res.statusCode !== 304) {
|
||||
// 304 - это нормально (кеш), не логируем
|
||||
log('warn', 'Request redirect', logData);
|
||||
log('info', 'Redirect', logData);
|
||||
} else {
|
||||
// Успешный запрос
|
||||
if (duration > 1000) {
|
||||
// Медленный запрос
|
||||
log('warn', 'Slow request', { ...logData, slow: true });
|
||||
} else {
|
||||
log('info', 'Request completed', logData);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
next();
|
||||
|
|
@ -97,8 +158,42 @@ const logSecurityEvent = (type, req, details = {}) => {
|
|||
appendLog(`security-${getDatePrefix()}.log`, securityMessage);
|
||||
};
|
||||
|
||||
// Дополнительные утилиты для логирования
|
||||
const logError = (context, error, additionalData = {}) => {
|
||||
log('error', `Error in ${context}`, {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
name: error.name,
|
||||
...additionalData
|
||||
});
|
||||
};
|
||||
|
||||
const logSuccess = (message, data = {}) => {
|
||||
log('success', message, data);
|
||||
};
|
||||
|
||||
const logDebug = (message, data = {}) => {
|
||||
// Логировать debug только в development
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
log('debug', message, data);
|
||||
}
|
||||
};
|
||||
|
||||
// Логирование производительности
|
||||
const logPerformance = (operation, duration, data = {}) => {
|
||||
const level = duration > 1000 ? 'warn' : 'info';
|
||||
log(level, `Performance: ${operation}`, {
|
||||
duration: `${duration}ms`,
|
||||
...data
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
log,
|
||||
logError,
|
||||
logSuccess,
|
||||
logDebug,
|
||||
logPerformance,
|
||||
requestLogger,
|
||||
logSecurityEvent
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const { authenticate } = require('../middleware/auth');
|
||||
const { log } = require('../middleware/logger');
|
||||
const Notification = require('../models/Notification');
|
||||
|
||||
// Получить уведомления пользователя
|
||||
|
|
@ -8,9 +9,16 @@ router.get('/', authenticate, async (req, res) => {
|
|||
try {
|
||||
const { page = 1, limit = 50 } = req.query;
|
||||
|
||||
log('info', 'Загрузка уведомлений', {
|
||||
userId: req.user._id,
|
||||
username: req.user.username,
|
||||
page,
|
||||
limit
|
||||
});
|
||||
|
||||
const notifications = await Notification.find({ recipient: req.user._id })
|
||||
.populate('sender', 'username firstName lastName photoUrl')
|
||||
.populate('post', 'content imageUrl')
|
||||
.populate('post', 'content imageUrl images')
|
||||
.sort({ createdAt: -1 })
|
||||
.limit(limit * 1)
|
||||
.skip((page - 1) * limit)
|
||||
|
|
@ -22,6 +30,13 @@ router.get('/', authenticate, async (req, res) => {
|
|||
read: false
|
||||
});
|
||||
|
||||
log('info', 'Уведомления загружены', {
|
||||
userId: req.user._id,
|
||||
count: notifications.length,
|
||||
total: count,
|
||||
unread: unreadCount
|
||||
});
|
||||
|
||||
res.json({
|
||||
notifications,
|
||||
totalPages: Math.ceil(count / limit),
|
||||
|
|
@ -29,7 +44,11 @@ router.get('/', authenticate, async (req, res) => {
|
|||
unreadCount
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Ошибка получения уведомлений:', error);
|
||||
log('error', 'Ошибка получения уведомлений', {
|
||||
userId: req.user?._id,
|
||||
error: error.message,
|
||||
stack: error.stack
|
||||
});
|
||||
res.status(500).json({ error: 'Ошибка сервера' });
|
||||
}
|
||||
});
|
||||
|
|
@ -37,21 +56,40 @@ router.get('/', authenticate, async (req, res) => {
|
|||
// Отметить уведомление как прочитанное
|
||||
router.put('/:id/read', authenticate, async (req, res) => {
|
||||
try {
|
||||
log('info', 'Отметка уведомления как прочитанное', {
|
||||
userId: req.user._id,
|
||||
notificationId: req.params.id
|
||||
});
|
||||
|
||||
const notification = await Notification.findOne({
|
||||
_id: req.params.id,
|
||||
recipient: req.user._id
|
||||
});
|
||||
|
||||
if (!notification) {
|
||||
log('warn', 'Уведомление не найдено', {
|
||||
userId: req.user._id,
|
||||
notificationId: req.params.id
|
||||
});
|
||||
return res.status(404).json({ error: 'Уведомление не найдено' });
|
||||
}
|
||||
|
||||
notification.read = true;
|
||||
await notification.save();
|
||||
|
||||
log('info', 'Уведомление отмечено как прочитанное', {
|
||||
userId: req.user._id,
|
||||
notificationId: req.params.id
|
||||
});
|
||||
|
||||
res.json({ message: 'Уведомление прочитано' });
|
||||
} catch (error) {
|
||||
console.error('Ошибка обновления уведомления:', error);
|
||||
log('error', 'Ошибка обновления уведомления', {
|
||||
userId: req.user?._id,
|
||||
notificationId: req.params.id,
|
||||
error: error.message,
|
||||
stack: error.stack
|
||||
});
|
||||
res.status(500).json({ error: 'Ошибка сервера' });
|
||||
}
|
||||
});
|
||||
|
|
@ -59,14 +97,31 @@ router.put('/:id/read', authenticate, async (req, res) => {
|
|||
// Отметить все уведомления как прочитанные
|
||||
router.put('/read-all', authenticate, async (req, res) => {
|
||||
try {
|
||||
await Notification.updateMany(
|
||||
log('info', 'Отметка всех уведомлений как прочитанные', {
|
||||
userId: req.user._id,
|
||||
username: req.user.username
|
||||
});
|
||||
|
||||
const result = await Notification.updateMany(
|
||||
{ recipient: req.user._id, read: false },
|
||||
{ read: true }
|
||||
);
|
||||
|
||||
res.json({ message: 'Все уведомления прочитаны' });
|
||||
log('info', 'Все уведомления отмечены', {
|
||||
userId: req.user._id,
|
||||
updated: result.modifiedCount
|
||||
});
|
||||
|
||||
res.json({
|
||||
message: 'Все уведомления прочитаны',
|
||||
updated: result.modifiedCount
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Ошибка обновления уведомлений:', error);
|
||||
log('error', 'Ошибка обновления уведомлений', {
|
||||
userId: req.user?._id,
|
||||
error: error.message,
|
||||
stack: error.stack
|
||||
});
|
||||
res.status(500).json({ error: 'Ошибка сервера' });
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ const { generalLimiter } = require('./middleware/rateLimiter');
|
|||
const { initRedis } = require('./utils/redis');
|
||||
const { initWebSocket } = require('./websocket');
|
||||
const { initMinioClient, checkConnection: checkMinioConnection } = require('./utils/minio');
|
||||
const { printMinioConfig } = require('./utils/minioDebug');
|
||||
const config = require('./config');
|
||||
|
||||
// Security middleware
|
||||
|
|
@ -23,7 +24,7 @@ const {
|
|||
ddosProtection
|
||||
} = require('./middleware/security');
|
||||
const { sanitizeInput } = require('./middleware/validator');
|
||||
const { requestLogger, logSecurityEvent } = require('./middleware/logger');
|
||||
const { requestLogger, logSecurityEvent, log, logSuccess, logError } = require('./middleware/logger');
|
||||
const { errorHandler, notFoundHandler } = require('./middleware/errorHandler');
|
||||
const { scheduleAvatarUpdates } = require('./jobs/avatarUpdater');
|
||||
const { startServerMonitorBot } = require('./bots/serverMonitor');
|
||||
|
|
@ -150,37 +151,87 @@ app.get('/health', (req, res) => {
|
|||
});
|
||||
|
||||
// MongoDB подключение
|
||||
log('info', 'Подключение к MongoDB...', { uri: config.mongoUri.replace(/\/\/.*@/, '//***@') });
|
||||
|
||||
mongoose.connect(config.mongoUri)
|
||||
.then(async () => {
|
||||
console.log(`✅ MongoDB подключена: ${config.mongoUri.replace(/\/\/.*@/, '//***@')}`);
|
||||
const dbHost = config.mongoUri.includes('localhost') || config.mongoUri.includes('127.0.0.1')
|
||||
? 'Local'
|
||||
: config.mongoUri.match(/\/\/([^:\/]+)/)?.[1] || 'Remote';
|
||||
|
||||
logSuccess('MongoDB успешно подключена', {
|
||||
host: dbHost,
|
||||
database: mongoose.connection.name,
|
||||
uri: config.mongoUri.replace(/\/\/.*@/, '//***@')
|
||||
});
|
||||
|
||||
// MongoDB события
|
||||
mongoose.connection.on('error', (err) => {
|
||||
logError('MongoDB connection error', err);
|
||||
});
|
||||
|
||||
mongoose.connection.on('disconnected', () => {
|
||||
log('warn', 'MongoDB отключена');
|
||||
});
|
||||
|
||||
mongoose.connection.on('reconnected', () => {
|
||||
logSuccess('MongoDB переподключена');
|
||||
});
|
||||
|
||||
// Инициализировать Redis (опционально)
|
||||
if (config.redisUrl) {
|
||||
initRedis().catch(err => console.log('⚠️ Redis недоступен, работаем без кэша'));
|
||||
try {
|
||||
log('info', 'Подключение к Redis...');
|
||||
await initRedis();
|
||||
logSuccess('Redis подключен', { url: config.redisUrl.replace(/\/\/.*@/, '//***@') });
|
||||
} catch (err) {
|
||||
log('warn', 'Redis недоступен, работаем без кэша', {
|
||||
error: err.message
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.log('ℹ️ Redis не настроен, кэширование отключено');
|
||||
log('info', 'Redis не настроен, кэширование отключено');
|
||||
}
|
||||
|
||||
// Инициализировать MinIO (опционально)
|
||||
if (config.minio.enabled) {
|
||||
try {
|
||||
log('info', 'Инициализация MinIO...');
|
||||
|
||||
// Вывести конфигурацию и проверки
|
||||
printMinioConfig();
|
||||
|
||||
initMinioClient();
|
||||
const minioOk = await checkMinioConnection();
|
||||
if (minioOk) {
|
||||
console.log(`✅ MinIO подключен: ${config.minio.endpoint}:${config.minio.port}`);
|
||||
console.log(` Bucket: ${config.minio.bucket}`);
|
||||
logSuccess('MinIO успешно подключен', {
|
||||
endpoint: `${config.minio.endpoint}:${config.minio.port}`,
|
||||
bucket: config.minio.bucket,
|
||||
ssl: config.minio.useSSL
|
||||
});
|
||||
} else {
|
||||
console.log('⚠️ MinIO недоступен, используется локальное хранилище');
|
||||
log('warn', 'MinIO недоступен, используется локальное хранилище');
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('⚠️ MinIO ошибка инициализации:', err.message);
|
||||
console.log(' Используется локальное хранилище');
|
||||
logError('MinIO initialization failed', err, {
|
||||
endpoint: `${config.minio.endpoint}:${config.minio.port}`
|
||||
});
|
||||
log('warn', 'Используется локальное хранилище');
|
||||
}
|
||||
} else {
|
||||
console.log('ℹ️ MinIO отключен, используется локальное хранилище');
|
||||
log('info', 'MinIO отключен, используется локальное хранилище');
|
||||
}
|
||||
})
|
||||
.catch(err => console.error('❌ Ошибка MongoDB:', err));
|
||||
.catch(err => {
|
||||
logError('MongoDB connection failed', err, {
|
||||
uri: config.mongoUri.replace(/\/\/.*@/, '//***@'),
|
||||
critical: true
|
||||
});
|
||||
console.error('\n❌ Не удалось подключиться к MongoDB!');
|
||||
console.error(` Проверьте MONGODB_URI в .env: ${config.mongoUri.replace(/\/\/.*@/, '//***@')}`);
|
||||
console.error(` Убедитесь что MongoDB запущена и доступна\n`);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
// Routes
|
||||
app.use('/api/auth', require('./routes/auth'));
|
||||
|
|
@ -211,35 +262,80 @@ initWebSocket(server);
|
|||
scheduleAvatarUpdates();
|
||||
startServerMonitorBot();
|
||||
|
||||
// Обработка необработанных ошибок
|
||||
process.on('uncaughtException', (error) => {
|
||||
logError('Uncaught Exception', error, {
|
||||
critical: true
|
||||
});
|
||||
// Дать время записать логи
|
||||
setTimeout(() => process.exit(1), 1000);
|
||||
});
|
||||
|
||||
process.on('unhandledRejection', (reason, promise) => {
|
||||
logError('Unhandled Rejection', new Error(reason), {
|
||||
promise: promise.toString(),
|
||||
critical: true
|
||||
});
|
||||
});
|
||||
|
||||
// Graceful shutdown
|
||||
process.on('SIGTERM', () => {
|
||||
console.log('SIGTERM получен, закрываем сервер...');
|
||||
log('warn', 'SIGTERM получен, закрываем сервер...');
|
||||
server.close(() => {
|
||||
console.log('Сервер закрыт');
|
||||
logSuccess('Сервер закрыт');
|
||||
mongoose.connection.close(false, () => {
|
||||
console.log('MongoDB соединение закрыто');
|
||||
logSuccess('MongoDB соединение закрыто');
|
||||
process.exit(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
process.on('SIGINT', () => {
|
||||
log('warn', 'SIGINT получен (Ctrl+C), закрываем сервер...');
|
||||
server.close(() => {
|
||||
logSuccess('Сервер закрыт');
|
||||
mongoose.connection.close(false, () => {
|
||||
logSuccess('MongoDB соединение закрыто');
|
||||
process.exit(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(config.port, '0.0.0.0', () => {
|
||||
console.log(`🚀 Сервер запущен`);
|
||||
console.log(` Порт: ${config.port}`);
|
||||
console.log(` Окружение: ${config.nodeEnv}`);
|
||||
console.log(` API: http://0.0.0.0:${config.port}/api`);
|
||||
if (config.isDevelopment()) {
|
||||
console.log(` Frontend: ${config.frontendUrl}`);
|
||||
}
|
||||
if (!config.telegramBotToken) {
|
||||
console.warn('⚠️ TELEGRAM_BOT_TOKEN не установлен!');
|
||||
console.warn(' Установите переменную окружения: TELEGRAM_BOT_TOKEN=ваш_токен');
|
||||
console.warn(' Получите токен от @BotFather в Telegram');
|
||||
console.warn(` Проверьте .env файл в: ${path.join(__dirname, '.env')}`);
|
||||
console.warn(` Текущий process.env.TELEGRAM_BOT_TOKEN: ${process.env.TELEGRAM_BOT_TOKEN ? 'установлен' : 'НЕ установлен'}`);
|
||||
} else {
|
||||
console.log(`✅ Telegram Bot инициализирован`);
|
||||
console.log(` Токен: ${config.telegramBotToken.substring(0, 10)}...`);
|
||||
}
|
||||
console.log('\n' + '='.repeat(60));
|
||||
logSuccess('Сервер успешно запущен', {
|
||||
port: config.port,
|
||||
environment: config.nodeEnv,
|
||||
api: `http://0.0.0.0:${config.port}/api`,
|
||||
frontend: config.frontendUrl,
|
||||
mongodb: config.mongoUri.replace(/\/\/.*@/, '//***@'), // Скрыть пароль
|
||||
minioEnabled: config.minio.enabled,
|
||||
redisEnabled: !!config.redisUrl
|
||||
});
|
||||
|
||||
console.log(` 🌐 API: http://0.0.0.0:${config.port}/api`);
|
||||
console.log(` 📦 MongoDB: ${config.mongoUri.includes('localhost') ? 'Local' : 'Remote'}`);
|
||||
console.log(` ⚙️ Environment: ${config.nodeEnv}`);
|
||||
|
||||
if (config.minio.enabled) {
|
||||
console.log(` 🗄️ MinIO: ${config.minio.endpoint}:${config.minio.port}`);
|
||||
}
|
||||
|
||||
if (config.redisUrl) {
|
||||
console.log(` 🔴 Redis: Connected`);
|
||||
}
|
||||
|
||||
if (!config.telegramBotToken) {
|
||||
log('warn', 'TELEGRAM_BOT_TOKEN не установлен!', {
|
||||
path: path.join(__dirname, '.env'),
|
||||
envSet: !!process.env.TELEGRAM_BOT_TOKEN
|
||||
});
|
||||
} else {
|
||||
logSuccess('Telegram Bot инициализирован', {
|
||||
token: config.telegramBotToken.substring(0, 10) + '...'
|
||||
});
|
||||
}
|
||||
|
||||
console.log('='.repeat(60) + '\n');
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
* Утилита для отладки MinIO
|
||||
*/
|
||||
|
||||
const config = require('../config');
|
||||
const { log } = require('../middleware/logger');
|
||||
|
||||
/**
|
||||
* Вывести информацию о MinIO конфигурации
|
||||
*/
|
||||
function printMinioConfig() {
|
||||
log('info', '🗄️ MinIO Configuration:', {
|
||||
enabled: config.minio.enabled,
|
||||
endpoint: config.minio.endpoint,
|
||||
port: config.minio.port,
|
||||
useSSL: config.minio.useSSL,
|
||||
bucket: config.minio.bucket,
|
||||
region: config.minio.region,
|
||||
publicUrl: config.minio.publicUrl || '(auto)',
|
||||
publicBucket: config.minio.publicBucket
|
||||
});
|
||||
|
||||
// Показать пример URL
|
||||
const protocol = config.minio.useSSL ? 'https' : 'http';
|
||||
const port = config.minio.port === 80 || config.minio.port === 443 ? '' : `:${config.minio.port}`;
|
||||
const exampleUrl = `${protocol}://${config.minio.endpoint}${port}/${config.minio.bucket}/posts/example-123456789.jpg`;
|
||||
|
||||
log('info', '📸 Пример URL файла:', { url: exampleUrl });
|
||||
|
||||
// Проверки
|
||||
const warnings = [];
|
||||
|
||||
if (config.minio.port === 9001 || config.minio.port === 9901) {
|
||||
warnings.push('⚠️ ПОРТ 9001/9901 - это консоль MinIO! Используйте порт 9000 для API');
|
||||
}
|
||||
|
||||
if (!config.minio.publicBucket) {
|
||||
warnings.push('⚠️ Bucket не публичный! Установите MINIO_PUBLIC_BUCKET=true или настройте политику доступа');
|
||||
}
|
||||
|
||||
if (config.minio.accessKey === 'minioadmin') {
|
||||
warnings.push('⚠️ Используются дефолтные credentials! Создайте Service Account в MinIO Console');
|
||||
}
|
||||
|
||||
if (warnings.length > 0) {
|
||||
warnings.forEach(warning => log('warn', warning));
|
||||
} else {
|
||||
log('info', '✅ Конфигурация выглядит правильно');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестовая функция для проверки доступности URL
|
||||
*/
|
||||
async function testImageUrl(imageUrl) {
|
||||
try {
|
||||
const https = require('https');
|
||||
const http = require('http');
|
||||
const url = require('url');
|
||||
|
||||
const parsedUrl = url.parse(imageUrl);
|
||||
const client = parsedUrl.protocol === 'https:' ? https : http;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
client.get(imageUrl, (res) => {
|
||||
log('info', 'Проверка URL:', {
|
||||
url: imageUrl,
|
||||
statusCode: res.statusCode,
|
||||
contentType: res.headers['content-type'],
|
||||
contentLength: res.headers['content-length']
|
||||
});
|
||||
|
||||
if (res.statusCode === 200) {
|
||||
resolve(true);
|
||||
} else if (res.statusCode === 403) {
|
||||
log('error', '❌ 403 Forbidden - Bucket не публичный или нет прав доступа');
|
||||
resolve(false);
|
||||
} else if (res.statusCode === 404) {
|
||||
log('error', '❌ 404 Not Found - Файл не существует');
|
||||
resolve(false);
|
||||
} else {
|
||||
log('warn', `⚠️ Неожиданный статус: ${res.statusCode}`);
|
||||
resolve(false);
|
||||
}
|
||||
}).on('error', (err) => {
|
||||
log('error', '❌ Ошибка подключения к MinIO:', {
|
||||
error: err.message,
|
||||
code: err.code
|
||||
});
|
||||
|
||||
if (err.code === 'ECONNREFUSED') {
|
||||
log('error', '💡 MinIO недоступен. Проверьте:');
|
||||
log('error', ' 1. MinIO запущен?');
|
||||
log('error', ' 2. Порт правильный? (9000 для API, не 9001/9901)');
|
||||
log('error', ' 3. Firewall разрешает подключение?');
|
||||
}
|
||||
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
log('error', 'Ошибка тестирования URL:', { error: error.message });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
printMinioConfig,
|
||||
testImageUrl
|
||||
};
|
||||
|
||||
|
|
@ -232,3 +232,151 @@
|
|||
min-width: 20px;
|
||||
}
|
||||
|
||||
/* Fullview hint */
|
||||
.fullview-hint {
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s;
|
||||
pointer-events: none;
|
||||
backdrop-filter: blur(5px);
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.image-carousel:hover .fullview-hint {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* Fullview модал */
|
||||
.image-fullview {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.95);
|
||||
z-index: 10000;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
animation: fadeIn 0.2s ease-out;
|
||||
}
|
||||
|
||||
.fullview-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 16px;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.fullview-counter {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.fullview-btn {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.fullview-btn:active {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.fullview-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.fullview-content img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
object-fit: contain;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.fullview-nav-btn {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 50%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
backdrop-filter: blur(10px);
|
||||
transition: background 0.2s, opacity 0.2s;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.fullview-nav-btn.prev {
|
||||
left: 16px;
|
||||
}
|
||||
|
||||
.fullview-nav-btn.next {
|
||||
right: 16px;
|
||||
}
|
||||
|
||||
.fullview-nav-btn:active {
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
}
|
||||
|
||||
.fullview-dots {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 16px;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.fullview-dot {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.4);
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.fullview-dot.active {
|
||||
background: white;
|
||||
width: 24px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { useState } from 'react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { Heart, MessageCircle, MoreVertical, ChevronLeft, ChevronRight, Download, Send } from 'lucide-react'
|
||||
import { Heart, MessageCircle, MoreVertical, ChevronLeft, ChevronRight, Download, Send, X, ZoomIn } from 'lucide-react'
|
||||
import { likePost, deletePost, sendPhotoToTelegram } from '../utils/api'
|
||||
import { hapticFeedback, showConfirm } from '../utils/telegram'
|
||||
import './PostCard.css'
|
||||
|
|
@ -22,6 +22,7 @@ export default function PostCard({ post, currentUser, onUpdate }) {
|
|||
const [liked, setLiked] = useState(post.likes.includes(currentUser.id))
|
||||
const [likesCount, setLikesCount] = useState(post.likes.length)
|
||||
const [currentImageIndex, setCurrentImageIndex] = useState(0)
|
||||
const [showFullView, setShowFullView] = useState(false)
|
||||
|
||||
// Поддержка и старого поля imageUrl и нового images
|
||||
const images = post.images && post.images.length > 0 ? post.images : (post.imageUrl ? [post.imageUrl] : [])
|
||||
|
|
@ -63,6 +64,39 @@ export default function PostCard({ post, currentUser, onUpdate }) {
|
|||
navigate(`/user/${post.author._id}`)
|
||||
}
|
||||
|
||||
const openFullView = () => {
|
||||
if (images.length > 0) {
|
||||
setShowFullView(true)
|
||||
hapticFeedback('light')
|
||||
}
|
||||
}
|
||||
|
||||
const handleNext = () => {
|
||||
if (currentImageIndex < images.length - 1) {
|
||||
setCurrentImageIndex(currentImageIndex + 1)
|
||||
hapticFeedback('light')
|
||||
}
|
||||
}
|
||||
|
||||
const handlePrev = () => {
|
||||
if (currentImageIndex > 0) {
|
||||
setCurrentImageIndex(currentImageIndex - 1)
|
||||
hapticFeedback('light')
|
||||
}
|
||||
}
|
||||
|
||||
const handleDownloadImage = async () => {
|
||||
try {
|
||||
hapticFeedback('light')
|
||||
const imageUrl = images[currentImageIndex]
|
||||
await sendPhotoToTelegram(imageUrl)
|
||||
hapticFeedback('success')
|
||||
} catch (error) {
|
||||
console.error('Ошибка отправки фото:', error)
|
||||
hapticFeedback('error')
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="post-card card fade-in">
|
||||
{/* Хедер поста */}
|
||||
|
|
@ -104,19 +138,19 @@ export default function PostCard({ post, currentUser, onUpdate }) {
|
|||
{/* Изображения */}
|
||||
{images.length > 0 && (
|
||||
<div className="post-images">
|
||||
<div className="image-carousel">
|
||||
<div className="image-carousel" onClick={openFullView} style={{ cursor: 'pointer' }}>
|
||||
<img src={images[currentImageIndex]} alt={`Image ${currentImageIndex + 1}`} />
|
||||
|
||||
{images.length > 1 && (
|
||||
<>
|
||||
{currentImageIndex > 0 && (
|
||||
<button className="carousel-btn prev" onClick={() => setCurrentImageIndex(currentImageIndex - 1)}>
|
||||
<button className="carousel-btn prev" onClick={(e) => { e.stopPropagation(); setCurrentImageIndex(currentImageIndex - 1); }}>
|
||||
<ChevronLeft size={24} />
|
||||
</button>
|
||||
)}
|
||||
|
||||
{currentImageIndex < images.length - 1 && (
|
||||
<button className="carousel-btn next" onClick={() => setCurrentImageIndex(currentImageIndex + 1)}>
|
||||
<button className="carousel-btn next" onClick={(e) => { e.stopPropagation(); setCurrentImageIndex(currentImageIndex + 1); }}>
|
||||
<ChevronRight size={24} />
|
||||
</button>
|
||||
)}
|
||||
|
|
@ -126,12 +160,17 @@ export default function PostCard({ post, currentUser, onUpdate }) {
|
|||
<span
|
||||
key={index}
|
||||
className={`dot ${index === currentImageIndex ? 'active' : ''}`}
|
||||
onClick={() => setCurrentImageIndex(index)}
|
||||
onClick={(e) => { e.stopPropagation(); setCurrentImageIndex(index); }}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Индикатор что можно открыть fullview */}
|
||||
<div className="fullview-hint">
|
||||
<ZoomIn size={20} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -197,6 +236,63 @@ export default function PostCard({ post, currentUser, onUpdate }) {
|
|||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Fullview модал */}
|
||||
{showFullView && (
|
||||
<div className="image-fullview" onClick={() => setShowFullView(false)}>
|
||||
<div className="fullview-header">
|
||||
<button className="fullview-btn" onClick={(e) => { e.stopPropagation(); setShowFullView(false); }}>
|
||||
<X size={24} />
|
||||
</button>
|
||||
<span className="fullview-counter">
|
||||
{currentImageIndex + 1} / {images.length}
|
||||
</span>
|
||||
<button
|
||||
className="fullview-btn"
|
||||
onClick={(e) => { e.stopPropagation(); handleDownloadImage(); }}
|
||||
title="Отправить в Telegram"
|
||||
>
|
||||
<Download size={24} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="fullview-content" onClick={(e) => e.stopPropagation()}>
|
||||
<img
|
||||
src={images[currentImageIndex]}
|
||||
alt={`Full view ${currentImageIndex + 1}`}
|
||||
draggable={false}
|
||||
/>
|
||||
|
||||
{images.length > 1 && (
|
||||
<>
|
||||
{currentImageIndex > 0 && (
|
||||
<button className="fullview-nav-btn prev" onClick={(e) => { e.stopPropagation(); handlePrev(); }}>
|
||||
<ChevronLeft size={32} />
|
||||
</button>
|
||||
)}
|
||||
|
||||
{currentImageIndex < images.length - 1 && (
|
||||
<button className="fullview-nav-btn next" onClick={(e) => { e.stopPropagation(); handleNext(); }}>
|
||||
<ChevronRight size={32} />
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{images.length > 1 && (
|
||||
<div className="fullview-dots">
|
||||
{images.map((_, index) => (
|
||||
<span
|
||||
key={index}
|
||||
className={`fullview-dot ${index === currentImageIndex ? 'active' : ''}`}
|
||||
onClick={(e) => { e.stopPropagation(); setCurrentImageIndex(index); }}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,11 +39,17 @@ export default function Notifications({ user }) {
|
|||
const loadNotifications = async () => {
|
||||
try {
|
||||
setLoading(true)
|
||||
console.log('[Notifications] Загрузка уведомлений...')
|
||||
const data = await getNotifications()
|
||||
setNotifications(data.notifications)
|
||||
setUnreadCount(data.unreadCount)
|
||||
console.log('[Notifications] Получено:', data)
|
||||
setNotifications(data.notifications || [])
|
||||
setUnreadCount(data.unreadCount || 0)
|
||||
} catch (error) {
|
||||
console.error('Ошибка загрузки уведомлений:', error)
|
||||
console.error('[Notifications] Ошибка загрузки:', error)
|
||||
console.error('[Notifications] Детали ошибки:', error.response?.data || error.message)
|
||||
// Показать пустое состояние при ошибке
|
||||
setNotifications([])
|
||||
setUnreadCount(0)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
|
|
@ -51,38 +57,47 @@ export default function Notifications({ user }) {
|
|||
|
||||
const handleNotificationClick = async (notification) => {
|
||||
hapticFeedback('light')
|
||||
console.log('[Notifications] Клик по уведомлению:', notification)
|
||||
|
||||
// Отметить как прочитанное
|
||||
if (!notification.read) {
|
||||
try {
|
||||
console.log('[Notifications] Отметка как прочитанное:', notification._id)
|
||||
await markNotificationRead(notification._id)
|
||||
setNotifications(prev =>
|
||||
prev.map(n => n._id === notification._id ? { ...n, read: true } : n)
|
||||
)
|
||||
setUnreadCount(prev => Math.max(0, prev - 1))
|
||||
} catch (error) {
|
||||
console.error('Ошибка отметки:', error)
|
||||
console.error('[Notifications] Ошибка отметки:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// Переход
|
||||
if (notification.type === 'follow') {
|
||||
console.log('[Notifications] Переход к профилю:', notification.sender._id)
|
||||
navigate(`/user/${notification.sender._id}`)
|
||||
} else if (notification.post) {
|
||||
// Переход к конкретному посту
|
||||
navigate(`/feed?post=${notification.post._id || notification.post}`)
|
||||
const postId = notification.post._id || notification.post
|
||||
console.log('[Notifications] Переход к посту:', postId)
|
||||
navigate(`/feed?post=${postId}`)
|
||||
}
|
||||
}
|
||||
|
||||
const handleMarkAllRead = async () => {
|
||||
try {
|
||||
hapticFeedback('light')
|
||||
console.log('[Notifications] Отметка всех как прочитанные')
|
||||
await markAllNotificationsRead()
|
||||
setNotifications(prev => prev.map(n => ({ ...n, read: true })))
|
||||
setUnreadCount(0)
|
||||
hapticFeedback('success')
|
||||
console.log('[Notifications] Все уведомления отмечены')
|
||||
} catch (error) {
|
||||
console.error('Ошибка отметки всех:', error)
|
||||
console.error('[Notifications] Ошибка отметки всех:', error)
|
||||
console.error('[Notifications] Детали:', error.response?.data || error.message)
|
||||
hapticFeedback('error')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -130,8 +145,14 @@ export default function Notifications({ user }) {
|
|||
</div>
|
||||
) : (
|
||||
notifications.map(notification => {
|
||||
const Icon = NOTIFICATION_ICONS[notification.type]
|
||||
const color = NOTIFICATION_COLORS[notification.type]
|
||||
// Защита от отсутствующих данных
|
||||
if (!notification || !notification.sender) {
|
||||
console.warn('[Notifications] Пропущено уведомление без sender:', notification);
|
||||
return null;
|
||||
}
|
||||
|
||||
const Icon = NOTIFICATION_ICONS[notification.type] || MessageCircle;
|
||||
const color = NOTIFICATION_COLORS[notification.type] || '#999999';
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
@ -141,8 +162,12 @@ export default function Notifications({ user }) {
|
|||
>
|
||||
<div className="bubble-avatar">
|
||||
<img
|
||||
src={notification.sender.photoUrl || '/default-avatar.png'}
|
||||
alt={notification.sender.username}
|
||||
src={notification.sender?.photoUrl || '/default-avatar.png'}
|
||||
alt={notification.sender?.username || 'User'}
|
||||
onError={(e) => {
|
||||
e.target.onerror = null;
|
||||
e.target.src = '/default-avatar.png';
|
||||
}}
|
||||
/>
|
||||
<div className="bubble-icon" style={{ backgroundColor: color }}>
|
||||
<Icon size={14} color="white" />
|
||||
|
|
@ -152,11 +177,11 @@ export default function Notifications({ user }) {
|
|||
<div className="bubble-content">
|
||||
<div className="bubble-text">
|
||||
<span className="bubble-username">
|
||||
{notification.sender.firstName} {notification.sender.lastName}
|
||||
{notification.sender?.firstName || ''} {notification.sender?.lastName || notification.sender?.username || 'Пользователь'}
|
||||
</span>
|
||||
{' '}
|
||||
<span className="bubble-action">
|
||||
{NOTIFICATION_TEXTS[notification.type]}
|
||||
{NOTIFICATION_TEXTS[notification.type] || 'действие'}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
|
@ -167,9 +192,15 @@ export default function Notifications({ user }) {
|
|||
</div>
|
||||
)}
|
||||
|
||||
{notification.post && notification.post.imageUrl && (
|
||||
{notification.post && (notification.post.imageUrl || notification.post.images?.[0]) && (
|
||||
<div className="bubble-image-preview">
|
||||
<img src={notification.post.imageUrl} alt="Post" />
|
||||
<img
|
||||
src={notification.post.images?.[0] || notification.post.imageUrl}
|
||||
alt="Post"
|
||||
onError={(e) => {
|
||||
e.target.style.display = 'none';
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
|
@ -183,7 +214,7 @@ export default function Notifications({ user }) {
|
|||
)}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}).filter(Boolean)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -117,6 +117,37 @@
|
|||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.search-submit-btn {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.search-submit-btn:active {
|
||||
transform: scale(0.95);
|
||||
box-shadow: 0 2px 4px rgba(102, 126, 234, 0.2);
|
||||
}
|
||||
|
||||
.search-submit-btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .search-submit-btn {
|
||||
box-shadow: 0 2px 8px rgba(118, 75, 162, 0.4);
|
||||
}
|
||||
|
||||
.tag-suggestions {
|
||||
position: absolute;
|
||||
top: 70px;
|
||||
|
|
|
|||
|
|
@ -377,6 +377,13 @@ const isVideoUrl = (url = '') => {
|
|||
<X size={18} />
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
className="search-submit-btn"
|
||||
onClick={() => handleSearch()}
|
||||
disabled={!query.trim() || loading}
|
||||
>
|
||||
<SearchIcon size={20} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Подсказки тегов */}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,174 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Скрипт для настройки публичного доступа к MinIO bucket
|
||||
|
||||
echo "🗄️ Настройка публичного доступа к MinIO bucket"
|
||||
echo "================================================"
|
||||
|
||||
# Цвета
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Читаем конфигурацию из .env
|
||||
if [ -f .env ]; then
|
||||
echo "✅ Найден файл .env"
|
||||
export $(grep -v '^#' .env | xargs)
|
||||
else
|
||||
echo -e "${RED}❌ Файл .env не найден!${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Проверяем переменные
|
||||
if [ -z "$MINIO_ENDPOINT" ] || [ -z "$MINIO_PORT" ]; then
|
||||
echo -e "${RED}❌ MINIO_ENDPOINT или MINIO_PORT не установлены в .env${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$MINIO_ACCESS_KEY" ] || [ -z "$MINIO_SECRET_KEY" ]; then
|
||||
echo -e "${RED}❌ MINIO_ACCESS_KEY или MINIO_SECRET_KEY не установлены в .env${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BUCKET=${MINIO_BUCKET:-nakama-media}
|
||||
MINIO_URL="http://${MINIO_ENDPOINT}:${MINIO_PORT}"
|
||||
|
||||
echo ""
|
||||
echo "Конфигурация:"
|
||||
echo " Endpoint: $MINIO_URL"
|
||||
echo " Bucket: $BUCKET"
|
||||
echo ""
|
||||
|
||||
# Проверяем доступность MinIO
|
||||
echo "🔍 Проверка доступности MinIO..."
|
||||
if curl -s --connect-timeout 5 "$MINIO_URL/minio/health/live" > /dev/null 2>&1; then
|
||||
echo -e "${GREEN}✅ MinIO доступен${NC}"
|
||||
else
|
||||
echo -e "${RED}❌ MinIO недоступен по адресу $MINIO_URL${NC}"
|
||||
echo ""
|
||||
echo "Проверьте:"
|
||||
echo " 1. MinIO запущен?"
|
||||
echo " 2. Порт $MINIO_PORT открыт?"
|
||||
echo " 3. Endpoint правильный?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Проверяем наличие mc (MinIO Client)
|
||||
if ! command -v mc &> /dev/null; then
|
||||
echo ""
|
||||
echo -e "${YELLOW}⚠️ MinIO Client (mc) не установлен${NC}"
|
||||
echo ""
|
||||
echo "Установка mc..."
|
||||
|
||||
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||
wget https://dl.min.io/client/mc/release/linux-amd64/mc -O /tmp/mc
|
||||
chmod +x /tmp/mc
|
||||
sudo mv /tmp/mc /usr/local/bin/mc
|
||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
brew install minio/stable/mc || {
|
||||
echo "Устанавливаем вручную..."
|
||||
curl https://dl.min.io/client/mc/release/darwin-amd64/mc -o /tmp/mc
|
||||
chmod +x /tmp/mc
|
||||
sudo mv /tmp/mc /usr/local/bin/mc
|
||||
}
|
||||
else
|
||||
echo -e "${RED}❌ Неподдерживаемая ОС. Установите mc вручную: https://min.io/docs/minio/linux/reference/minio-mc.html${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${GREEN}✅ mc установлен${NC}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "📝 Настройка mc alias..."
|
||||
|
||||
# Настраиваем alias для mc
|
||||
mc alias set nakama-minio "$MINIO_URL" "$MINIO_ACCESS_KEY" "$MINIO_SECRET_KEY" --api S3v4
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo -e "${GREEN}✅ Alias настроен${NC}"
|
||||
else
|
||||
echo -e "${RED}❌ Ошибка настройки alias${NC}"
|
||||
echo "Проверьте MINIO_ACCESS_KEY и MINIO_SECRET_KEY"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "🗂️ Проверка bucket..."
|
||||
|
||||
# Проверяем существование bucket
|
||||
if mc ls nakama-minio/$BUCKET > /dev/null 2>&1; then
|
||||
echo -e "${GREEN}✅ Bucket '$BUCKET' существует${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}⚠️ Bucket '$BUCKET' не найден${NC}"
|
||||
echo "Создание bucket..."
|
||||
mc mb nakama-minio/$BUCKET
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo -e "${GREEN}✅ Bucket создан${NC}"
|
||||
else
|
||||
echo -e "${RED}❌ Ошибка создания bucket${NC}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "🔓 Установка публичной политики..."
|
||||
|
||||
# Устанавливаем публичный доступ
|
||||
mc anonymous set download nakama-minio/$BUCKET
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo -e "${GREEN}✅ Bucket теперь публичный (download)${NC}"
|
||||
else
|
||||
echo -e "${RED}❌ Ошибка установки политики${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "🧪 Тестирование..."
|
||||
|
||||
# Создаем тестовый файл
|
||||
echo "Test file from Nakama setup" > /tmp/nakama-test.txt
|
||||
|
||||
# Загружаем тестовый файл
|
||||
mc cp /tmp/nakama-test.txt nakama-minio/$BUCKET/test/nakama-test.txt
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo -e "${GREEN}✅ Тестовый файл загружен${NC}"
|
||||
|
||||
# Проверяем доступность
|
||||
TEST_URL="$MINIO_URL/$BUCKET/test/nakama-test.txt"
|
||||
echo "Проверка доступности: $TEST_URL"
|
||||
|
||||
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$TEST_URL")
|
||||
|
||||
if [ "$HTTP_CODE" == "200" ]; then
|
||||
echo -e "${GREEN}✅ Файл доступен публично!${NC}"
|
||||
echo ""
|
||||
echo -e "${GREEN}🎉 Всё настроено правильно!${NC}"
|
||||
|
||||
# Удаляем тестовый файл
|
||||
mc rm nakama-minio/$BUCKET/test/nakama-test.txt > /dev/null 2>&1
|
||||
rm /tmp/nakama-test.txt
|
||||
else
|
||||
echo -e "${RED}❌ Файл недоступен (HTTP $HTTP_CODE)${NC}"
|
||||
echo ""
|
||||
echo "Попробуйте настроить политику вручную:"
|
||||
echo "1. Откройте MinIO Console: http://$MINIO_ENDPOINT:9001/"
|
||||
echo "2. Buckets → $BUCKET → Manage → Access Policy"
|
||||
echo "3. Выберите 'Public' или добавьте JSON политику"
|
||||
fi
|
||||
else
|
||||
echo -e "${RED}❌ Ошибка загрузки тестового файла${NC}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "================================================"
|
||||
echo "Готово! Теперь:"
|
||||
echo "1. Убедитесь что в .env установлено: MINIO_PUBLIC_BUCKET=true"
|
||||
echo "2. Перезапустите Docker: docker-compose restart backend"
|
||||
echo "3. Создайте пост с картинкой в приложении"
|
||||
echo "================================================"
|
||||
|
||||
|
|
@ -280,13 +280,28 @@ export default function App() {
|
|||
};
|
||||
|
||||
const initChat = () => {
|
||||
if (!user || chatSocketRef.current) return;
|
||||
if (!user) {
|
||||
console.error('[Chat] Нет user, отмена инициализации');
|
||||
return;
|
||||
}
|
||||
|
||||
if (chatSocketRef.current) {
|
||||
console.warn('[Chat] Socket уже существует');
|
||||
return;
|
||||
}
|
||||
|
||||
const API_URL = import.meta.env.VITE_API_URL || (
|
||||
import.meta.env.PROD ? window.location.origin : 'http://localhost:3000'
|
||||
);
|
||||
|
||||
console.log('Инициализация чата, подключение к:', API_URL);
|
||||
console.log('[Chat] Инициализация чата');
|
||||
console.log('[Chat] User данные:', {
|
||||
username: user.username,
|
||||
telegramId: user.telegramId,
|
||||
hasUsername: !!user.username,
|
||||
hasTelegramId: !!user.telegramId
|
||||
});
|
||||
console.log('[Chat] Подключение к:', `${API_URL}/mod-chat`);
|
||||
|
||||
const socket = io(`${API_URL}/mod-chat`, {
|
||||
transports: ['websocket', 'polling'],
|
||||
|
|
@ -297,7 +312,12 @@ export default function App() {
|
|||
});
|
||||
|
||||
socket.on('connect', () => {
|
||||
console.log('WebSocket подключен, отправка auth...');
|
||||
console.log('[Chat] ✅ WebSocket подключен, ID:', socket.id);
|
||||
console.log('[Chat] Отправка auth с данными:', {
|
||||
username: user.username,
|
||||
telegramId: user.telegramId
|
||||
});
|
||||
|
||||
socket.emit('auth', {
|
||||
username: user.username,
|
||||
telegramId: user.telegramId
|
||||
|
|
|
|||
|
|
@ -1,129 +0,0 @@
|
|||
╔═══════════════════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ ✨ ВСЕ ФУНКЦИИ РЕАЛИЗОВАНЫ И ГОТОВЫ ✨ ║
|
||||
║ v2.2.0 - Major Update ║
|
||||
║ ║
|
||||
╚═══════════════════════════════════════════════════════════════════════╝
|
||||
|
||||
|
||||
🎉 ЧТО ДОБАВЛЕНО:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
1. До 5 картинок в одном посте
|
||||
✓ Множественная загрузка файлов
|
||||
✓ Сетка превью в создании поста
|
||||
✓ Карусель в ленте (свайп между картинками)
|
||||
✓ Точки-индикаторы внизу
|
||||
|
||||
2. Создать пост из поиска (репост)
|
||||
✓ Кнопка "+" в просмотрщике
|
||||
✓ Картинка автоматически добавляется
|
||||
✓ Можно добавить текст и теги
|
||||
|
||||
3. Отправка в ЛС с ботом
|
||||
✓ Одна картинка из просмотрщика
|
||||
✓ Несколько картинок (режим выбора)
|
||||
✓ До 50 фото за раз
|
||||
✓ Media Group в Telegram
|
||||
|
||||
4. Swipe перелистывание
|
||||
✓ В просмотрщике поиска
|
||||
✓ В карусели поста
|
||||
✓ Стрелки на клавиатуре
|
||||
|
||||
5. Монохромный дизайн
|
||||
✓ Только чёрное и белое
|
||||
✓ Без синих кнопок
|
||||
|
||||
|
||||
ОБНОВЛЕНИЕ (13 файлов):
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Backend (5):
|
||||
scp backend/models/Post.js root@ваш_IP:/var/www/nakama/backend/models/
|
||||
scp backend/routes/posts.js root@ваш_IP:/var/www/nakama/backend/routes/
|
||||
scp backend/bot.js root@ваш_IP:/var/www/nakama/backend/
|
||||
scp backend/routes/bot.js root@ваш_IP:/var/www/nakama/backend/routes/
|
||||
scp backend/server.js root@ваш_IP:/var/www/nakama/backend/
|
||||
|
||||
Frontend (8):
|
||||
scp frontend/src/components/CreatePostModal.jsx root@ваш_IP:/var/www/nakama/frontend/src/components/
|
||||
scp frontend/src/components/CreatePostModal.css root@ваш_IP:/var/www/nakama/frontend/src/components/
|
||||
scp frontend/src/components/PostCard.jsx root@ваш_IP:/var/www/nakama/frontend/src/components/
|
||||
scp frontend/src/components/PostCard.css root@ваш_IP:/var/www/nakama/frontend/src/components/
|
||||
scp frontend/src/pages/Search.jsx root@ваш_IP:/var/www/nakama/frontend/src/pages/
|
||||
scp frontend/src/pages/Search.css root@ваш_IP:/var/www/nakama/frontend/src/pages/
|
||||
scp frontend/src/components/Navigation.css root@ваш_IP:/var/www/nakama/frontend/src/components/
|
||||
scp frontend/src/components/CommentsModal.css root@ваш_IP:/var/www/nakama/frontend/src/components/
|
||||
|
||||
На сервере:
|
||||
ssh root@ваш_IP
|
||||
cd /var/www/nakama/frontend && npm run build && cd .. && pm2 restart nakama-backend
|
||||
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
📱 КАК ИСПОЛЬЗОВАТЬ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Создать пост с несколькими фото:
|
||||
1. Лента → кнопка "+"
|
||||
2. Нажмите иконку 🖼️
|
||||
3. Выберите до 5 фото
|
||||
4. Превью появится сеткой
|
||||
5. Добавьте текст и теги
|
||||
6. Опубликовать
|
||||
|
||||
Репост из поиска:
|
||||
1. Поиск → найдите картинку
|
||||
2. Откройте просмотрщик
|
||||
3. Нажмите кнопку "+" вверху
|
||||
4. Откроется создание поста с этой картинкой
|
||||
5. Добавьте текст и теги
|
||||
6. Опубликовать
|
||||
|
||||
Отправить в бота:
|
||||
1. Поиск → просмотрщик
|
||||
2. Кнопка "Download" → 1 фото в ЛС
|
||||
|
||||
ИЛИ:
|
||||
|
||||
1. Поиск → кнопка "Выбрать"
|
||||
2. Тапайте по картинкам
|
||||
3. "Отправить в Telegram (N)" → все в ЛС
|
||||
|
||||
Свайп в посте:
|
||||
1. Если в посте несколько картинок
|
||||
2. Свайпайте влево/вправо
|
||||
3. Точки внизу показывают текущую
|
||||
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
⚙️ НАСТРОЙКА БОТА:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
В .env на сервере:
|
||||
TELEGRAM_BOT_TOKEN=ваш_токен_от_BotFather
|
||||
|
||||
Пользователь должен написать /start боту один раз
|
||||
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✅ ГОТОВО:
|
||||
|
||||
✓ До 5 фото в посте
|
||||
✓ Карусель в ленте
|
||||
✓ Репост из поиска
|
||||
✓ Отправка в бота
|
||||
✓ Swipe навигация
|
||||
✓ Монохромный дизайн
|
||||
|
||||
|
||||
5 минут обновления
|
||||
https://nakama.glpshchn.ru
|
||||
|
||||
🎉 NakamaSpace v2.2.0!
|
||||
|
||||
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
╔═══════════════════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ 🎨 НЕСКОЛЬКО КАРТИНОК В ОДНОМ ПОСТЕ 🎨 ║
|
||||
║ ║
|
||||
╚═══════════════════════════════════════════════════════════════════════╝
|
||||
|
||||
|
||||
✨ НОВЫЕ ФУНКЦИИ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
1. До 5 картинок в одном посте
|
||||
• Множественная загрузка файлов
|
||||
• Сетка превью
|
||||
• Счётчик "N/5"
|
||||
• Удаление каждой картинки отдельно
|
||||
|
||||
2. Создать пост из поиска
|
||||
• Кнопка "+" в просмотрщике
|
||||
• Картинка автоматически добавится в пост
|
||||
• Можно добавить текст и теги
|
||||
|
||||
3. Комбинация загруженных и внешних
|
||||
• Загрузить свои фото
|
||||
• Добавить из поиска
|
||||
• Всё вместе в одном посте
|
||||
|
||||
|
||||
КАК ИСПОЛЬЗОВАТЬ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Вариант 1 - Загрузить свои фото:
|
||||
1. Создать пост → кнопка 🖼️
|
||||
2. Выберите несколько файлов (до 5)
|
||||
3. Появится сетка превью
|
||||
4. Добавьте текст и теги
|
||||
5. Опубликовать
|
||||
|
||||
Вариант 2 - Из поиска:
|
||||
1. Поиск → найдите картинку
|
||||
2. Откройте просмотрщик
|
||||
3. Нажмите кнопку "+"
|
||||
4. Откроется создание поста с этой картинкой
|
||||
5. Добавьте текст и теги
|
||||
6. Опубликовать
|
||||
|
||||
|
||||
ОБНОВЛЕНИЕ (10 файлов):
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Backend:
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
|
||||
scp backend/models/Post.js root@ваш_IP:/var/www/nakama/backend/models/
|
||||
scp backend/routes/posts.js root@ваш_IP:/var/www/nakama/backend/routes/
|
||||
scp backend/bot.js root@ваш_IP:/var/www/nakama/backend/
|
||||
scp backend/routes/bot.js root@ваш_IP:/var/www/nakama/backend/routes/
|
||||
scp backend/server.js root@ваш_IP:/var/www/nakama/backend/
|
||||
|
||||
Frontend:
|
||||
scp frontend/src/components/CreatePostModal.jsx root@ваш_IP:/var/www/nakama/frontend/src/components/
|
||||
scp frontend/src/components/CreatePostModal.css root@ваш_IP:/var/www/nakama/frontend/src/components/
|
||||
scp frontend/src/pages/Search.jsx root@ваш_IP:/var/www/nakama/frontend/src/pages/
|
||||
scp frontend/src/pages/Search.css root@ваш_IP:/var/www/nakama/frontend/src/pages/
|
||||
|
||||
На сервере:
|
||||
ssh root@ваш_IP
|
||||
cd /var/www/nakama/frontend && npm run build && cd .. && pm2 restart nakama-backend
|
||||
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✅ ГОТОВО:
|
||||
|
||||
✓ До 5 фото в посте
|
||||
✓ Создать пост из поиска (репост)
|
||||
✓ Swipe в просмотрщике
|
||||
✓ Отправка в ЛС с ботом
|
||||
✓ Множественный выбор
|
||||
|
||||
|
||||
3 минуты
|
||||
https://nakama.glpshchn.ru
|
||||
|
||||
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
╔═══════════════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ 🔒 СИСТЕМА БЕЗОПАСНОСТИ И ОТКАЗОУСТОЙЧИВОСТИ 🔒 ║
|
||||
║ ║
|
||||
╚═══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
|
||||
ДОБАВЛЕННЫЕ ЗАЩИТНЫЕ МЕХАНИЗМЫ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✅ 1. Helmet - Security Headers
|
||||
• Content-Security-Policy
|
||||
• X-Frame-Options
|
||||
• X-Content-Type-Options
|
||||
• Strict-Transport-Security
|
||||
• И другие защитные headers
|
||||
|
||||
✅ 2. Защита от NoSQL Injection
|
||||
• express-mongo-sanitize
|
||||
• Автоматическая очистка MongoDB операторов
|
||||
• Логирование подозрительных запросов
|
||||
|
||||
✅ 3. Защита от XSS
|
||||
• xss-clean middleware
|
||||
• Санитизация всех входных данных
|
||||
• Экранирование HTML/JS в контенте
|
||||
|
||||
✅ 4. Защита от HTTP Parameter Pollution
|
||||
• hpp middleware
|
||||
• Предотвращение дублирования параметров
|
||||
|
||||
✅ 5. Валидация входных данных
|
||||
• Проверка Telegram ID
|
||||
• Валидация контента постов
|
||||
• Валидация тегов
|
||||
• Валидация URL изображений
|
||||
• Проверка на path traversal
|
||||
|
||||
✅ 6. Строгая проверка подписи Telegram
|
||||
• В production обязательная проверка
|
||||
• Логирование подозрительных попыток
|
||||
• Блокировка невалидных запросов
|
||||
|
||||
✅ 7. Улучшенный Rate Limiting
|
||||
• Строгие лимиты для авторизации
|
||||
• Лимиты для создания постов
|
||||
• Лимиты для загрузки файлов
|
||||
• Разные лимиты для разных операций
|
||||
|
||||
✅ 8. Централизованная обработка ошибок
|
||||
• Единый error handler
|
||||
• Логирование всех ошибок
|
||||
• Безопасные сообщения об ошибках
|
||||
• Graceful shutdown
|
||||
|
||||
✅ 9. Логирование и мониторинг
|
||||
• Логирование всех запросов
|
||||
• Логирование подозрительной активности
|
||||
• Security events tracking
|
||||
• Файлы логов в production
|
||||
|
||||
✅ 10. Обработка необработанных ошибок
|
||||
• unhandledRejection
|
||||
• uncaughtException
|
||||
• Graceful shutdown при критических ошибках
|
||||
|
||||
|
||||
НУЖНО УСТАНОВИТЬ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
cd backend
|
||||
npm install helmet express-mongo-sanitize xss-clean hpp
|
||||
|
||||
|
||||
ОБНОВЛЕННЫЕ ФАЙЛЫ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Backend:
|
||||
• backend/server.js
|
||||
• backend/middleware/security.js (новый)
|
||||
• backend/middleware/validator.js (новый)
|
||||
• backend/middleware/errorHandler.js (новый)
|
||||
• backend/middleware/logger.js (новый)
|
||||
• backend/middleware/auth.js
|
||||
• backend/routes/auth.js
|
||||
• backend/routes/posts.js
|
||||
|
||||
|
||||
ЗАЩИТА ОТ АТАК:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✅ SQL/NoSQL Injection
|
||||
✅ XSS (Cross-Site Scripting)
|
||||
✅ CSRF (Cross-Site Request Forgery)
|
||||
✅ Path Traversal
|
||||
✅ HTTP Parameter Pollution
|
||||
✅ Brute Force (rate limiting)
|
||||
✅ DDoS (rate limiting + CORS)
|
||||
✅ File Upload Attacks (валидация)
|
||||
✅ Man-in-the-Middle (Telegram signature)
|
||||
|
||||
|
||||
ОТКАЗОУСТОЙЧИВОСТЬ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✅ Graceful shutdown
|
||||
✅ Обработка всех ошибок
|
||||
✅ Валидация внешних API ответов
|
||||
✅ Timeout для внешних запросов
|
||||
✅ Retry механизмы (можно добавить)
|
||||
✅ Health checks
|
||||
✅ Логирование для отладки
|
||||
|
||||
|
||||
КОМАНДЫ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
cd /Users/glpshchn/Desktop/nakama/backend
|
||||
npm install helmet express-mongo-sanitize xss-clean hpp
|
||||
|
||||
# На сервере
|
||||
cd /var/www/nakama/backend
|
||||
npm install helmet express-mongo-sanitize xss-clean hpp
|
||||
pm2 restart nakama-backend
|
||||
|
||||
|
||||
2 минуты
|
||||
|
||||
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
╔═══════════════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ 🔧 GELBOORU API КЛЮЧ ДОБАВЛЕН! 🔧 ║
|
||||
║ ║
|
||||
╚═══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
|
||||
ИСПРАВЛЕНО:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✅ 1. Добавлен Gelbooru API ключ в конфиг
|
||||
• API Key: 638e2433d451fc02e848811acdafdce08317073c01ed78e38139115c19fe04afa367f736726514ef1337565d4c05b3cbe2c81125c424301e90d29d1f7f4cceff
|
||||
• User ID: 1844464
|
||||
|
||||
✅ 2. Обновлены запросы к Gelbooru API
|
||||
• Поиск постов теперь использует api_key и user_id
|
||||
• Автокомплит тегов теперь использует api_key и user_id
|
||||
• Согласно документации: https://gelbooru.com/index.php?page=wiki&s=view&id=18780
|
||||
|
||||
✅ 3. Запросы не будут ограничены
|
||||
• API ключ позволяет избежать throttling
|
||||
• Более стабильная работа API
|
||||
|
||||
|
||||
ИЗМЕНЕННЫЕ ФАЙЛЫ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Backend:
|
||||
• backend/config/index.js
|
||||
• backend/routes/search.js
|
||||
|
||||
|
||||
ОБНОВЛЕНИЕ (2 файла):
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
|
||||
# Backend
|
||||
scp backend/config/index.js backend/routes/search.js root@ваш_IP:/var/www/nakama/backend/
|
||||
scp backend/routes/search.js root@ваш_IP:/var/www/nakama/backend/routes/
|
||||
|
||||
# На сервере
|
||||
ssh root@ваш_IP "cd /var/www/nakama/backend && pm2 restart nakama-backend"
|
||||
|
||||
|
||||
ЧТО ИСПРАВЛЕНО:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
1. ✅ Gelbooru API теперь использует аутентификацию
|
||||
2. ✅ Запросы не будут ограничены (throttling)
|
||||
3. ✅ Более стабильная работа поиска в Gelbooru
|
||||
|
||||
|
||||
ПРИМЕЧАНИЕ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
API ключ можно также добавить в переменные окружения:
|
||||
• GELBOORU_API_KEY=638e2433d451fc02e848811acdafdce08317073c01ed78e38139115c19fe04afa367f736726514ef1337565d4c05b3cbe2c81125c424301e90d29d1f7f4cceff
|
||||
• GELBOORU_USER_ID=1844464
|
||||
|
||||
Если не указаны, будут использоваться значения по умолчанию из конфига.
|
||||
|
||||
|
||||
2 минуты
|
||||
|
||||
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
╔═══════════════════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ 🔧 ИСПРАВЛЕНА СИНТАКСИЧЕСКАЯ ОШИБКА 🔧 ║
|
||||
║ ║
|
||||
╚═══════════════════════════════════════════════════════════════════════╝
|
||||
|
||||
|
||||
ПРОБЛЕМА:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Expected ")" but found "{"
|
||||
→ Не хватало React Fragment (<>) для нескольких элементов
|
||||
|
||||
|
||||
ИСПРАВЛЕНО:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Обернул в <> ... </> два элемента:
|
||||
• results-grid
|
||||
• send-selected-bar
|
||||
|
||||
|
||||
ОБНОВИТЬ (1 файл):
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
|
||||
scp frontend/src/pages/Search.jsx root@ваш_IP:/var/www/nakama/frontend/src/pages/
|
||||
|
||||
|
||||
ssh root@ваш_IP "cd /var/www/nakama/frontend && npm run build"
|
||||
|
||||
|
||||
30 секунд
|
||||
|
||||
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
╔═══════════════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ 🔧 TELEGRAM OAUTH ДЛЯ СТОРОННИХ КЛИЕНТОВ 🔧 ║
|
||||
║ ║
|
||||
╚═══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
|
||||
ИЗМЕНЕНИЯ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✅ 1. Убран Mock User
|
||||
• Удалена функция getMockUser()
|
||||
• Убрано использование mock user из App.jsx
|
||||
• Убрано из api.js interceptor
|
||||
|
||||
✅ 2. Добавлен Telegram Login Widget
|
||||
• Компонент TelegramLogin.jsx
|
||||
• Использует официальный Telegram Login Widget
|
||||
• Показывается для сторонних клиентов и браузера
|
||||
|
||||
✅ 3. Backend OAuth Route
|
||||
• /api/auth/oauth - новый endpoint
|
||||
• Проверка подписи Telegram OAuth
|
||||
• Создание/обновление пользователя
|
||||
|
||||
✅ 4. Обновлена логика авторизации
|
||||
• Если нет Telegram Web App API → показывается Login Widget
|
||||
• После авторизации через Widget → создается сессия
|
||||
|
||||
|
||||
НАСТРОЙКА:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
1. Получить имя бота от @BotFather
|
||||
• Используется для Telegram Login Widget
|
||||
|
||||
2. Установить переменную окружения:
|
||||
VITE_TELEGRAM_BOT_NAME=ваше_имя_бота
|
||||
|
||||
3. Настроить домен в BotFather:
|
||||
• /setdomain для вашего домена
|
||||
• Например: nakama.glpshchn.ru
|
||||
|
||||
|
||||
ОБНОВЛЕНИЕ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Frontend:
|
||||
• frontend/src/App.jsx
|
||||
• frontend/src/components/TelegramLogin.jsx (новый)
|
||||
• frontend/src/components/TelegramLogin.css (новый)
|
||||
• frontend/src/utils/api.js
|
||||
• frontend/src/utils/telegram.js
|
||||
|
||||
Backend:
|
||||
• backend/routes/auth.js
|
||||
|
||||
|
||||
КОМАНДЫ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
|
||||
# Frontend
|
||||
scp frontend/src/App.jsx root@ваш_IP:/var/www/nakama/frontend/src/
|
||||
scp frontend/src/components/TelegramLogin.jsx root@ваш_IP:/var/www/nakama/frontend/src/components/
|
||||
scp frontend/src/components/TelegramLogin.css root@ваш_IP:/var/www/nakama/frontend/src/components/
|
||||
scp frontend/src/utils/api.js frontend/src/utils/telegram.js root@ваш_IP:/var/www/nakama/frontend/src/utils/
|
||||
|
||||
# Backend
|
||||
scp backend/routes/auth.js root@ваш_IP:/var/www/nakama/backend/routes/
|
||||
|
||||
# На сервере
|
||||
ssh root@ваш_IP "cd /var/www/nakama/frontend && npm run build"
|
||||
ssh root@ваш_IP "pm2 restart nakama-backend"
|
||||
|
||||
|
||||
ВАЖНО:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
1. Telegram Login Widget требует:
|
||||
• Домен должен быть настроен в BotFather
|
||||
• Использовать HTTPS (в production)
|
||||
• Правильное имя бота
|
||||
|
||||
2. Проверка подписи:
|
||||
• Включена, если есть TELEGRAM_BOT_TOKEN
|
||||
• В production рекомендуется строгая проверка
|
||||
|
||||
3. Безопасность:
|
||||
• Теперь используется официальная авторизация Telegram
|
||||
• Нет mock users
|
||||
• Все пользователи верифицированы через Telegram
|
||||
|
||||
|
||||
2 минуты
|
||||
|
||||
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
╔═══════════════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ 🔧 УСТАНОВКА TELEGRAM BOT TOKEN 🔧 ║
|
||||
║ ║
|
||||
╚═══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
|
||||
ПРОБЛЕМА:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
TELEGRAM_BOT_TOKEN не установлен на сервере!
|
||||
Ошибка: "TELEGRAM_BOT_TOKEN не установлен"
|
||||
|
||||
|
||||
РЕШЕНИЕ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✅ 1. Создать Telegram бота
|
||||
• Откройте @BotFather в Telegram
|
||||
• Отправьте команду /newbot
|
||||
• Следуйте инструкциям
|
||||
• Получите токен бота (например: 123456789:ABCdefGHIjklMNOpqrsTUVwxyz)
|
||||
|
||||
✅ 2. Установить токен на сервере
|
||||
|
||||
Вариант A: Через .env файл
|
||||
────────────────────────────
|
||||
ssh root@ваш_IP
|
||||
cd /var/www/nakama/backend
|
||||
nano .env
|
||||
|
||||
Добавьте строку:
|
||||
TELEGRAM_BOT_TOKEN=ваш_токен_бота
|
||||
|
||||
Сохраните (Ctrl+O, Enter, Ctrl+X)
|
||||
|
||||
Вариант B: Через PM2 ecosystem
|
||||
───────────────────────────────
|
||||
pm2 ecosystem
|
||||
# Добавьте env: { TELEGRAM_BOT_TOKEN: 'ваш_токен_бота' }
|
||||
|
||||
Вариант C: Через export (временное)
|
||||
─────────────────────────────────────
|
||||
export TELEGRAM_BOT_TOKEN="ваш_токен_бота"
|
||||
pm2 restart nakama-backend
|
||||
|
||||
|
||||
✅ 3. Перезапустить backend
|
||||
─────────────────────────
|
||||
pm2 restart nakama-backend
|
||||
|
||||
Проверить логи:
|
||||
pm2 logs nakama-backend --lines 20
|
||||
|
||||
|
||||
ПРОВЕРКА:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
После установки токена проверьте:
|
||||
• Логи не должны показывать "TELEGRAM_BOT_TOKEN не установлен"
|
||||
• Отправка фото в Telegram должна работать
|
||||
• В логах должно быть: "✅ Telegram Bot инициализирован"
|
||||
|
||||
|
||||
ПРИМЕЧАНИЕ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Токен должен быть в формате: 123456789:ABCdefGHIjklMNOpqrsTUVwxyz
|
||||
Не добавляйте кавычки в .env файле!
|
||||
|
||||
|
||||
ИНСТРУКЦИЯ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
1. Получите токен от @BotFather
|
||||
2. Создайте/откройте .env файл в /var/www/nakama/backend/
|
||||
3. Добавьте: TELEGRAM_BOT_TOKEN=ваш_токен
|
||||
4. Перезапустите: pm2 restart nakama-backend
|
||||
|
||||
|
||||
2 минуты
|
||||
|
||||
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
╔═══════════════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ 🔧 ОТПРАВКА В TELEGRAM ИСПРАВЛЕНА! 🔧 ║
|
||||
║ ║
|
||||
╚═══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
|
||||
ПРОБЛЕМА:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Telegram Bot API не может загрузить изображение по локальному
|
||||
прокси URL (/api/search/proxy/...)
|
||||
|
||||
|
||||
РЕШЕНИЕ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✅ 1. Декодирование прокси URL
|
||||
• Функция getOriginalUrl() декодирует прокси URL
|
||||
• Получает оригинальный URL от e621/gelbooru
|
||||
|
||||
✅ 2. Использование оригинальных URL
|
||||
• Используем оригинальные URL от e621.net и gelbooru.com
|
||||
• Telegram может загрузить эти изображения напрямую
|
||||
|
||||
✅ 3. Fallback для локальных файлов
|
||||
• Если URL не публичный, скачиваем изображение
|
||||
• Отправляем как файл через FormData
|
||||
|
||||
|
||||
ИЗМЕНЕННЫЕ ФАЙЛЫ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Backend:
|
||||
• backend/bot.js
|
||||
|
||||
|
||||
ОБНОВЛЕНИЕ (1 файл):
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
|
||||
# Backend
|
||||
scp backend/bot.js root@ваш_IP:/var/www/nakama/backend/
|
||||
|
||||
# На сервере
|
||||
ssh root@ваш_IP "cd /var/www/nakama/backend && npm install form-data && pm2 restart nakama-backend"
|
||||
|
||||
|
||||
ЧТО ИСПРАВЛЕНО:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
1. ✅ Прокси URL декодируется в оригинальный URL
|
||||
2. ✅ Telegram получает оригинальные URL от e621/gelbooru
|
||||
3. ✅ Изображения отправляются успешно
|
||||
4. ✅ Добавлен fallback для локальных файлов
|
||||
|
||||
|
||||
ПРИМЕЧАНИЕ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Если form-data не установлен, установите его:
|
||||
npm install form-data
|
||||
|
||||
Теперь Telegram Bot API получит оригинальные URL изображений
|
||||
от e621.net и gelbooru.com, которые доступны публично.
|
||||
|
||||
|
||||
2 минуты
|
||||
|
||||
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
╔═══════════════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ 🔧 ВСЕ ИСПРАВЛЕНИЯ ПРИМЕНЕНЫ! 🔧 ║
|
||||
║ ║
|
||||
╚═══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
|
||||
ИСПРАВЛЕНО:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✅ 1. Проблема с прыганием комментов и кнопками
|
||||
• Убраны `pointer-events: all` и `touch-action: none` из overlay
|
||||
• Добавлены `stopPropagation()` для предотвращения закрытия при клике на контент
|
||||
• Добавлены `handleOverlayClick` для правильного закрытия модалов
|
||||
• Теперь все кнопки нажимаются там, где отображаются
|
||||
|
||||
✅ 2. Проблема с поиском
|
||||
• Добавлена обработка ошибок для каждого API отдельно
|
||||
• Поиск продолжается даже если один из API не работает
|
||||
• Проверка на массив перед добавлением результатов
|
||||
|
||||
✅ 3. Проблема с Gelbooru API
|
||||
• Добавлена обработка разных форматов ответа Gelbooru
|
||||
• Добавлен User-Agent заголовок
|
||||
• Добавлен timeout 30 секунд
|
||||
• Улучшена обработка ошибок с логированием
|
||||
• В случае ошибки автокомплит возвращает пустой массив вместо ошибки
|
||||
|
||||
✅ 4. Ошибка 401
|
||||
• Улучшена обработка `x-telegram-init-data` заголовка
|
||||
• Добавлена поддержка JSON формата initData
|
||||
• Улучшено логирование ошибок
|
||||
• Добавлены проверки на наличие данных перед парсингом
|
||||
|
||||
|
||||
ИЗМЕНЕННЫЕ ФАЙЛЫ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Frontend:
|
||||
• frontend/src/components/CommentsModal.jsx
|
||||
• frontend/src/components/CommentsModal.css
|
||||
• frontend/src/components/PostMenu.jsx
|
||||
• frontend/src/components/PostMenu.css
|
||||
• frontend/src/pages/Search.jsx
|
||||
|
||||
Backend:
|
||||
• backend/routes/search.js
|
||||
• backend/middleware/auth.js
|
||||
|
||||
|
||||
ОБНОВЛЕНИЕ (9 файлов):
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
|
||||
# Frontend
|
||||
scp frontend/src/components/CommentsModal.jsx frontend/src/components/CommentsModal.css frontend/src/components/PostMenu.jsx frontend/src/components/PostMenu.css root@ваш_IP:/var/www/nakama/frontend/src/components/
|
||||
|
||||
scp frontend/src/pages/Search.jsx root@ваш_IP:/var/www/nakama/frontend/src/pages/
|
||||
|
||||
# Backend
|
||||
scp backend/routes/search.js backend/middleware/auth.js root@ваш_IP:/var/www/nakama/backend/routes/
|
||||
scp backend/middleware/auth.js root@ваш_IP:/var/www/nakama/backend/middleware/
|
||||
|
||||
# На сервере
|
||||
ssh root@ваш_IP "cd /var/www/nakama/frontend && npm run build"
|
||||
ssh root@ваш_IP "cd /var/www/nakama/backend && pm2 restart nakama-backend"
|
||||
|
||||
|
||||
ЧТО ИСПРАВЛЕНО:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
1. ✅ Комменты больше не прыгают
|
||||
2. ✅ Кнопки нажимаются там, где отображаются
|
||||
3. ✅ Поиск работает даже если один API не отвечает
|
||||
4. ✅ Gelbooru API обрабатывает разные форматы ответа
|
||||
5. ✅ Ошибка 401 исправлена с улучшенной обработкой
|
||||
|
||||
|
||||
3 минуты
|
||||
|
||||
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
╔═══════════════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ 🔧 ИСПРАВЛЕНИЯ ДЛЯ СЕРВЕРА 🔧 ║
|
||||
║ ║
|
||||
╚═══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
|
||||
ИСПРАВЛЕНО:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✅ 1. Добавлены недостающие зависимости в package.json
|
||||
• helmet: ^7.1.0
|
||||
• express-mongo-sanitize: ^2.2.0
|
||||
• xss-clean: ^0.1.4
|
||||
• hpp: ^0.2.3
|
||||
|
||||
✅ 2. Исправлена логика авторизации в App.jsx
|
||||
• Проверка наличия window.Telegram?.WebApp перед проверкой пользователя
|
||||
• Добавлена задержка на инициализацию Telegram Web App (300ms)
|
||||
• Проверка наличия initData (строка) вместо initDataUnsafe.user
|
||||
• Правильная обработка официального клиента Telegram - авторизация через API даже если user еще не распарсен
|
||||
• Backend распарсит initData и создаст/найдет пользователя
|
||||
|
||||
✅ 3. Добавлена зависимость validator в package.json
|
||||
• validator: ^13.11.0 - для валидации и санитизации данных
|
||||
|
||||
|
||||
КОМАНДЫ ДЛЯ ОБНОВЛЕНИЯ НА СЕРВЕРЕ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
# 1. Подключиться к серверу
|
||||
ssh root@nakama.glpshchn.ru
|
||||
|
||||
# 2. Остановить приложение (чтобы избежать постоянных ребутов)
|
||||
pm2 stop nakama-backend
|
||||
|
||||
# 3. Перейти в директорию проекта
|
||||
cd /var/www/nakama
|
||||
|
||||
# 4. Обновить код (если используете Git)
|
||||
git pull origin main
|
||||
|
||||
# 5. Установить недостающие зависимости
|
||||
npm install helmet express-mongo-sanitize xss-clean hpp validator --save
|
||||
|
||||
# Или установить все зависимости заново
|
||||
npm install --production
|
||||
|
||||
# 6. Проверить что зависимости установлены
|
||||
npm list helmet express-mongo-sanitize xss-clean hpp validator
|
||||
|
||||
# 7. Пересобрать frontend (с исправленной логикой авторизации)
|
||||
cd frontend
|
||||
npm run build
|
||||
cd ..
|
||||
|
||||
# 8. Проверить что сервер запускается (вручную)
|
||||
cd backend
|
||||
node server.js
|
||||
# Если есть ошибки - исправить их
|
||||
# Если все ок - остановить (Ctrl+C)
|
||||
|
||||
# 9. Запустить через PM2
|
||||
pm2 start backend/server.js --name nakama-backend --update-env
|
||||
|
||||
# Или если уже есть конфиг:
|
||||
pm2 restart nakama-backend --update-env
|
||||
|
||||
# 10. Проверить статус
|
||||
pm2 status
|
||||
pm2 logs nakama-backend --lines 50
|
||||
|
||||
|
||||
БЫСТРАЯ КОМАНДА (одна строка):
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
ssh root@nakama.glpshchn.ru "cd /var/www/nakama && pm2 stop nakama-backend && npm install helmet express-mongo-sanitize xss-clean hpp validator --save && cd frontend && npm run build && cd .. && pm2 start backend/server.js --name nakama-backend --update-env && sleep 2 && pm2 status && pm2 logs nakama-backend --lines 30"
|
||||
|
||||
|
||||
ПРОВЕРКА ПОСЛЕ ОБНОВЛЕНИЯ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
# 1. Проверить что приложение запущено
|
||||
pm2 status
|
||||
# Должно быть: nakama-backend | online
|
||||
|
||||
# 2. Проверить логи (не должно быть ошибок MODULE_NOT_FOUND)
|
||||
pm2 logs nakama-backend --lines 50
|
||||
# Не должно быть: Error: Cannot find module 'helmet'
|
||||
|
||||
# 3. Проверить health endpoint
|
||||
curl http://localhost:3000/health
|
||||
# Должно вернуть: {"status":"ok","environment":"production",...}
|
||||
|
||||
# 4. Проверить через браузер
|
||||
curl https://nakama.glpshchn.ru/health
|
||||
# Должно вернуть: {"status":"ok",...}
|
||||
|
||||
# 5. Проверить Nginx
|
||||
sudo systemctl status nginx
|
||||
sudo nginx -t
|
||||
|
||||
# 6. Проверить логи Nginx
|
||||
sudo tail -f /var/log/nginx/error.log
|
||||
# Не должно быть 502 ошибок
|
||||
|
||||
|
||||
ЧТО ИСПРАВЛЕНО:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✅ Проблема 1: Error: Cannot find module 'helmet'
|
||||
РЕШЕНИЕ: Добавлены зависимости в package.json
|
||||
|
||||
✅ Проблема 2: Даже с офф клиента Telegram просит авторизацию
|
||||
РЕШЕНИЕ: Исправлена логика в App.jsx - теперь проверяет наличие initData
|
||||
(строка) вместо initDataUnsafe.user. Если есть initData, пытается
|
||||
авторизоваться через API (backend распарсит initData). Это решает
|
||||
проблему когда в официальном клиенте Telegram initDataUnsafe.user
|
||||
еще не распарсен, но initData уже доступен.
|
||||
|
||||
✅ Проблема 4: Error: Cannot find module 'validator'
|
||||
РЕШЕНИЕ: Добавлена зависимость validator в package.json
|
||||
|
||||
✅ Проблема 3: 502 ошибка и постоянные ребуты
|
||||
РЕШЕНИЕ: После установки зависимостей приложение должно запускаться
|
||||
без ошибок и перестать ребутиться
|
||||
|
||||
|
||||
ВАЖНО:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
1. После установки зависимостей ОБЯЗАТЕЛЬНО пересобрать frontend
|
||||
(npm run build в директории frontend)
|
||||
|
||||
2. Перезапустить PM2 с флагом --update-env для обновления переменных
|
||||
|
||||
3. Проверить логи PM2 после перезапуска
|
||||
|
||||
4. Если все еще есть ошибки - проверить что все зависимости установлены:
|
||||
npm list helmet express-mongo-sanitize xss-clean hpp validator
|
||||
|
||||
|
||||
ГОТОВО! ✅
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
После выполнения этих команд все три проблемы должны быть решены!
|
||||
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
╔═══════════════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ 🔧 ОБРАБОТКА ОШИБОК ИМПРОВИЗОВАНА! 🔧 ║
|
||||
║ ║
|
||||
╚═══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
|
||||
ПРОБЛЕМА:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
1. TypeError: response.data.map is not a function
|
||||
→ response.data не является массивом
|
||||
|
||||
2. Приложение падает из-за ошибок (429 rate limit)
|
||||
→ Нет обработки 429 ошибок
|
||||
|
||||
|
||||
РЕШЕНИЕ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✅ 1. Добавлена проверка на массив
|
||||
• Проверка Array.isArray() перед .map()
|
||||
• Возврат пустого массива вместо ошибки
|
||||
|
||||
✅ 2. Добавлена обработка 429 ошибок
|
||||
• validateStatus: (status) => status < 500
|
||||
• Проверка response.status === 429
|
||||
• Возврат пустого массива вместо ошибки
|
||||
|
||||
✅ 3. Улучшена обработка ошибок
|
||||
• Вложенные try-catch блоки
|
||||
• Логирование предупреждений вместо ошибок
|
||||
• Приложение не падает при ошибках API
|
||||
|
||||
✅ 4. Защита от падения приложения
|
||||
• Все ошибки обрабатываются
|
||||
• Возвращаются пустые массивы вместо ошибок
|
||||
• Приложение продолжает работать
|
||||
|
||||
|
||||
ИЗМЕНЕННЫЕ ФАЙЛЫ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Backend:
|
||||
• backend/routes/search.js
|
||||
|
||||
|
||||
ОБНОВЛЕНИЕ (1 файл):
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
|
||||
# Backend
|
||||
scp backend/routes/search.js root@ваш_IP:/var/www/nakama/backend/routes/
|
||||
|
||||
# На сервере
|
||||
ssh root@ваш_IP "cd /var/www/nakama/backend && pm2 restart nakama-backend"
|
||||
|
||||
|
||||
ЧТО ИСПРАВЛЕНО:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
1. ✅ Проверка на массив перед .map()
|
||||
2. ✅ Обработка 429 ошибок (rate limit)
|
||||
3. ✅ Приложение не падает при ошибках API
|
||||
4. ✅ Возвращаются пустые массивы вместо ошибок
|
||||
5. ✅ Улучшено логирование (предупреждения вместо ошибок)
|
||||
|
||||
|
||||
ПРИМЕЧАНИЕ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Теперь приложение:
|
||||
• Не падает при 429 ошибках
|
||||
• Не падает при неверном формате ответа API
|
||||
• Возвращает пустые массивы вместо ошибок
|
||||
• Продолжает работать даже при проблемах с API
|
||||
|
||||
|
||||
2 минуты
|
||||
|
||||
|
||||
|
|
@ -1,105 +0,0 @@
|
|||
╔═══════════════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ 🔧 ПРОВЕРКА ПЕРЕМЕННЫХ ОКРУЖЕНИЯ 🔧 ║
|
||||
║ ║
|
||||
╚═══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
|
||||
ПРОБЛЕМА:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Токен добавлен, но все еще "не установлен"
|
||||
→ PM2 не видит переменные из .env файла
|
||||
|
||||
|
||||
РЕШЕНИЕ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✅ 1. Проверить .env файл на сервере
|
||||
|
||||
ssh root@ваш_IP
|
||||
cd /var/www/nakama/backend
|
||||
cat .env
|
||||
|
||||
Должно быть:
|
||||
TELEGRAM_BOT_TOKEN=ваш_токен_без_кавычек
|
||||
|
||||
БЕЗ кавычек!
|
||||
БЕЗ пробелов вокруг =!
|
||||
|
||||
|
||||
✅ 2. Запустить скрипт проверки
|
||||
|
||||
cd /var/www/nakama/backend
|
||||
node check-env.js
|
||||
|
||||
Скрипт покажет:
|
||||
• Есть ли .env файл
|
||||
• Загружается ли токен
|
||||
• Все переменные из .env
|
||||
|
||||
|
||||
✅ 3. Перезапустить PM2 с --update-env
|
||||
|
||||
pm2 restart nakama-backend --update-env
|
||||
|
||||
Важно: --update-env обновляет переменные окружения!
|
||||
|
||||
|
||||
✅ 4. Проверить логи
|
||||
|
||||
pm2 logs nakama-backend --lines 20
|
||||
|
||||
Должно быть:
|
||||
✅ Telegram Bot инициализирован
|
||||
Токен: 1234567890...
|
||||
|
||||
НЕ должно быть:
|
||||
⚠️ TELEGRAM_BOT_TOKEN не установлен!
|
||||
|
||||
|
||||
АЛЬТЕРНАТИВНОЕ РЕШЕНИЕ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Если PM2 не видит .env файл, используйте ecosystem.config.js:
|
||||
|
||||
1. Создать ecosystem.config.js:
|
||||
|
||||
cd /var/www/nakama
|
||||
nano ecosystem.config.js
|
||||
|
||||
2. Добавить:
|
||||
|
||||
module.exports = {
|
||||
apps: [{
|
||||
name: 'nakama-backend',
|
||||
script: './backend/server.js',
|
||||
env: {
|
||||
NODE_ENV: 'production',
|
||||
TELEGRAM_BOT_TOKEN: 'ваш_токен_от_BotFather',
|
||||
MONGODB_URI: 'mongodb://localhost:27017/nakama',
|
||||
PORT: 3000
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
3. Перезапустить:
|
||||
|
||||
pm2 delete nakama-backend
|
||||
pm2 start ecosystem.config.js
|
||||
pm2 save
|
||||
|
||||
|
||||
ПРОВЕРКА:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
После всех шагов:
|
||||
1. Проверьте логи: pm2 logs nakama-backend
|
||||
2. Должно быть: ✅ Telegram Bot инициализирован
|
||||
3. Попробуйте отправить фото в Telegram
|
||||
4. Должно работать!
|
||||
|
||||
|
||||
2 минуты
|
||||
|
||||
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
╔═══════════════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ 🔧 ПОДДЕРЖКА СТОРОННИХ КЛИЕНТОВ ДОБАВЛЕНА! 🔧 ║
|
||||
║ ║
|
||||
╚═══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
|
||||
ПРОБЛЕМА:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Сторонние клиенты (Aurogram и т.д.) не поддерживают Telegram Web App API
|
||||
→ Ошибка: "Telegram User не найден"
|
||||
|
||||
|
||||
РЕШЕНИЕ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✅ 1. Добавлена функция isThirdPartyClient()
|
||||
• Определяет, открыто ли приложение в стороннем клиенте
|
||||
• Проверяет наличие window.Telegram?.WebApp
|
||||
|
||||
✅ 2. Fallback для сторонних клиентов
|
||||
• Используется mock user для Aurogram и других клиентов
|
||||
• ID пользователя сохраняется в localStorage
|
||||
• Стабильный ID между сеансами
|
||||
|
||||
✅ 3. Обновлен API interceptor
|
||||
• Отправляет mock данные для сторонних клиентов
|
||||
• Backend принимает JSON формат
|
||||
|
||||
✅ 4. Улучшен getMockUser()
|
||||
• Сохраняет ID в localStorage
|
||||
• Один пользователь = один ID
|
||||
• Генератор аватаров на основе ID
|
||||
|
||||
|
||||
ИЗМЕНЕННЫЕ ФАЙЛЫ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Frontend:
|
||||
• frontend/src/App.jsx
|
||||
• frontend/src/utils/telegram.js
|
||||
• frontend/src/utils/api.js
|
||||
|
||||
|
||||
ОБНОВЛЕНИЕ (3 файла):
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
|
||||
# Frontend
|
||||
scp frontend/src/App.jsx frontend/src/utils/telegram.js frontend/src/utils/api.js root@ваш_IP:/var/www/nakama/frontend/src/
|
||||
scp frontend/src/utils/telegram.js frontend/src/utils/api.js root@ваш_IP:/var/www/nakama/frontend/src/utils/
|
||||
|
||||
# На сервере
|
||||
ssh root@ваш_IP "cd /var/www/nakama/frontend && npm run build"
|
||||
|
||||
|
||||
ЧТО ИСПРАВЛЕНО:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
1. ✅ Сторонние клиенты (Aurogram) теперь поддерживаются
|
||||
2. ✅ Используется mock user для авторизации
|
||||
3. ✅ ID пользователя сохраняется между сеансами
|
||||
4. ✅ Backend принимает JSON формат от сторонних клиентов
|
||||
5. ✅ Приложение работает в любом браузере/клиенте
|
||||
|
||||
|
||||
ПРИМЕЧАНИЕ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Теперь пользователи могут использовать приложение:
|
||||
• В официальном Telegram клиенте (полный функционал)
|
||||
• В сторонних клиентах (Aurogram, etc.) - через mock user
|
||||
• В браузере (для разработки)
|
||||
|
||||
|
||||
2 минуты
|
||||
|
||||
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
╔═══════════════════════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║ 🔧 СТРАНИЦЫ ВМЕСТО МОДАЛОК + ИСПРАВЛЕН БОТ 🔧 ║
|
||||
║ ║
|
||||
╚═══════════════════════════════════════════════════════════════════╝
|
||||
|
||||
|
||||
ИСПРАВЛЕНО:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
✅ 1. Проблема с ботом (botundefined в URL)
|
||||
• Добавлена проверка на наличие TELEGRAM_BOT_TOKEN
|
||||
• Преобразование относительных URL в полные для Telegram
|
||||
• Улучшена обработка ошибок
|
||||
|
||||
✅ 2. Создана страница CommentsPage
|
||||
• Отдельная страница для комментариев
|
||||
• Пост дублируется на странице
|
||||
• Кнопка "Назад" для возврата
|
||||
• Нет проблем с прыганием!
|
||||
|
||||
✅ 3. Создана страница PostMenuPage
|
||||
• Отдельная страница для меню поста
|
||||
• Пост дублируется на странице
|
||||
• Кнопка "Назад" для возврата
|
||||
• Нет проблем с прыганием!
|
||||
|
||||
✅ 4. Добавлены маршруты в App.jsx
|
||||
• /post/:postId/comments - страница комментариев
|
||||
• /post/:postId/menu - страница меню поста
|
||||
|
||||
✅ 5. Обновлен PostCard.jsx
|
||||
• Навигация на страницы вместо модальных окон
|
||||
• Убраны импорты PostMenu и CommentsModal
|
||||
|
||||
|
||||
ИЗМЕНЕННЫЕ ФАЙЛЫ:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
Backend:
|
||||
• backend/bot.js
|
||||
|
||||
Frontend:
|
||||
• frontend/src/App.jsx
|
||||
• frontend/src/components/PostCard.jsx
|
||||
• frontend/src/pages/CommentsPage.jsx (новый)
|
||||
• frontend/src/pages/CommentsPage.css (новый)
|
||||
• frontend/src/pages/PostMenuPage.jsx (новый)
|
||||
• frontend/src/pages/PostMenuPage.css (новый)
|
||||
|
||||
|
||||
ОБНОВЛЕНИЕ (8 файлов):
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
cd /Users/glpshchn/Desktop/nakama
|
||||
|
||||
# Backend
|
||||
scp backend/bot.js root@ваш_IP:/var/www/nakama/backend/
|
||||
|
||||
# Frontend
|
||||
scp frontend/src/App.jsx frontend/src/components/PostCard.jsx root@ваш_IP:/var/www/nakama/frontend/src/
|
||||
scp frontend/src/components/PostCard.jsx root@ваш_IP:/var/www/nakama/frontend/src/components/
|
||||
scp frontend/src/pages/CommentsPage.jsx frontend/src/pages/CommentsPage.css root@ваш_IP:/var/www/nakama/frontend/src/pages/
|
||||
scp frontend/src/pages/PostMenuPage.jsx frontend/src/pages/PostMenuPage.css root@ваш_IP:/var/www/nakama/frontend/src/pages/
|
||||
|
||||
# На сервере
|
||||
ssh root@ваш_IP "cd /var/www/nakama/frontend && npm run build"
|
||||
ssh root@ваш_IP "cd /var/www/nakama/backend && pm2 restart nakama-backend"
|
||||
|
||||
|
||||
ЧТО ИСПРАВЛЕНО:
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
1. ✅ Бот больше не выдает ошибку 404
|
||||
2. ✅ Комментарии на отдельной странице - НЕ ПРЫГАЮТ!
|
||||
3. ✅ Меню поста на отдельной странице - НЕ ПРЫГАЕТ!
|
||||
4. ✅ Пост дублируется на обеих страницах
|
||||
5. ✅ Кнопка "Назад" работает правильно
|
||||
|
||||
|
||||
5 минут
|
||||
|
||||
|
||||
Loading…
Reference in New Issue