Update files

This commit is contained in:
glpshchn 2025-11-21 04:14:56 +03:00
parent 678783d3be
commit 27e8f5944c
60 changed files with 1325 additions and 8249 deletions

236
ADMIN_CHAT_DEBUG.md Normal file
View File

@ -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
```
---
**После исправления чат должен подключиться автоматически при открытии вкладки "Чат"!** ✅

View File

@ -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 подключения

View File

@ -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 быть не должно!

View File

@ -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
```

View File

@ -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! 🚀**
Все баги исправлены, приложение стабильно.

View File

@ -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)

View File

@ -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! 🎉

View File

@ -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`

View File

@ -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)

View File

@ -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 с описанием проблемы

View File

@ -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

View File

@ -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:
└─ Работает при переключении
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🎉 ГОТОВО!

View File

@ -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

View File

@ -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 готов! 🎉**

View File

@ -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
Все проблемы с комментариями исправлены!

View File

@ -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
```
---
## 🎉 Готово!
Все проблемы исправлены:
- ✅ Окно комментариев работает с клавиатурой
- ✅ Репосты удалены полностью
- ✅ Иконки и текст видны в тёмной теме
- ✅ Улучшена общая видимость элементов
После обновления на сервере всё должно работать идеально! 🚀

View File

@ -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. ✅ Новые пользователи видят все посты по умолчанию

View File

@ -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
```
---
## ✅ После обновления:
Комментарии больше не будут прыгать при фокусе на поле ввода!

View File

@ -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` для подробной документации!

View File

@ -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 при создании постов и публикациях в канал.

View File

@ -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
• Сообществу за поддержку
╔═══════════════════════════════════════════════════════════════════════╗
║ Сделано с 🦊 и 🎌 ║
╚═══════════════════════════════════════════════════════════════════════╝

View File

@ -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

View File

@ -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

View File

@ -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
View File

@ -1,373 +1,192 @@
# 🌟 NakamaSpace - Telegram Mini App
# 🎨 Nakama
> Полноценная мини-социальная сеть внутри Telegram с 4 вкладками, системой постов, поиском, уведомлениями и модерацией.
Социальная сеть для фурри и аниме сообщества, реализованная как Telegram Mini App.
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![Node.js](https://img.shields.io/badge/Node.js-16+-green.svg)](https://nodejs.org/)
[![React](https://img.shields.io/badge/React-18+-61DAFB.svg)](https://reactjs.org/)
[![MongoDB](https://img.shields.io/badge/MongoDB-5+-47A248.svg)](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

View File

@ -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

View File

@ -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
╔═══════════════════════════════════════════════════════════════════════╗
║ Успехов! 🚀🦊🎌 ║
╚═══════════════════════════════════════════════════════════════════════╝

View File

@ -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
View File

@ -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.

View File

@ -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)

View File

@ -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 перезапускать НЕ нужно!

View File

@ -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)
✅ Кнопки БЕЛЫЕ в тёмной теме
✅ Активная кнопка - белая с синей рамкой
✅ Всё работает идеально

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
};

View File

@ -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: 'Ошибка сервера' });
}
});

View File

@ -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');
});

111
backend/utils/minioDebug.js Normal file
View File

@ -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
};

View File

@ -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;
}
}

View File

@ -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>
)
}

View File

@ -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>

View File

@ -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;

View File

@ -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>
{/* Подсказки тегов */}

174
minio-setup-public.sh Normal file
View File

@ -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 "================================================"

View File

@ -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

View File

@ -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!

View File

@ -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

View File

@ -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 минуты

View File

@ -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 минуты

View File

@ -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 секунд

View File

@ -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 минуты

View File

@ -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 минуты

View File

@ -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 минуты

View File

@ -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 минуты

View File

@ -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
ГОТОВО! ✅
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
После выполнения этих команд все три проблемы должны быть решены!

View File

@ -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 минуты

View File

@ -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 минуты

View File

@ -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 минуты

View File

@ -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 минут