CampFireID/backend/server.ts
2025-03-16 11:25:09 +03:00

184 lines
5.4 KiB
TypeScript

import express from 'express';
import mongoose from 'mongoose';
import dotenv from 'dotenv';
import jwt from 'jsonwebtoken';
import User, { IUser } from './models/User';
import ShopItem from './models/ShopItem';
dotenv.config();
// Расширяем типы Express
declare global {
namespace Express {
interface Request {
user?: {
userId: string;
telegramId: string;
}
}
}
}
const app = express();
app.use(express.json());
// Подключение к MongoDB
mongoose.connect(process.env.MONGODB_URI || 'mongodb://localhost:27017/campfire-id')
.then(() => console.log('Connected to MongoDB'))
.catch(err => console.error('MongoDB connection error:', err));
// Middleware для проверки JWT
const authenticateToken = (req: express.Request, res: express.Response, next: express.NextFunction) => {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
return res.status(401).json({ error: 'Требуется авторизация' });
}
jwt.verify(token, process.env.JWT_SECRET || 'your-secret-key', (err: any, user: any) => {
if (err) {
return res.status(403).json({ error: 'Недействительный токен' });
}
req.user = user;
next();
});
};
// Регистрация/авторизация пользователя
app.post('/api/auth', async (req, res) => {
try {
const { telegramId, username } = req.body;
let user = await User.findOne({ telegramId });
if (!user) {
user = new User({
telegramId,
username,
// Начальный бонус для новых пользователей
balance: 100
});
await user.save();
}
const token = jwt.sign(
{ userId: user._id, telegramId },
process.env.JWT_SECRET || 'your-secret-key',
{ expiresIn: '7d' }
);
res.json({ token, user });
} catch (error) {
res.status(500).json({ error: 'Ошибка сервера' });
}
});
// Получение профиля пользователя
app.get('/api/profile', authenticateToken, async (req, res) => {
try {
const user = await User.findById(req.user.userId);
if (!user) {
return res.status(404).json({ error: 'Пользователь не найден' });
}
res.json(user);
} catch (error) {
res.status(500).json({ error: 'Ошибка сервера' });
}
});
// Получение списка предметов в магазине
app.get('/api/shop', authenticateToken, async (req, res) => {
try {
const items = await ShopItem.find({ available: true });
res.json(items);
} catch (error) {
res.status(500).json({ error: 'Ошибка сервера' });
}
});
// Покупка предмета
app.post('/api/shop/purchase', authenticateToken, async (req, res) => {
try {
const { itemId } = req.body;
const user = await User.findById(req.user.userId);
const item = await ShopItem.findById(itemId);
if (!user || !item) {
return res.status(404).json({ error: 'Пользователь или предмет не найден' });
}
if (user.balance < item.price) {
return res.status(400).json({ error: 'Недостаточно средств' });
}
// Обновляем баланс и инвентарь
user.balance -= item.price;
const existingItem = user.inventory.find(i => i.itemId === itemId);
if (existingItem) {
existingItem.quantity += 1;
} else {
user.inventory.push({
itemId: item._id,
name: item.name,
description: item.description,
quantity: 1,
imageUrl: item.imageUrl
});
}
await user.save();
res.json({ success: true, user });
} catch (error) {
res.status(500).json({ error: 'Ошибка сервера' });
}
});
// Перевод баланса между пользователями
app.post('/api/transfer', authenticateToken, async (req, res) => {
try {
const { recipientUsername, amount } = req.body;
if (amount <= 0) {
return res.status(400).json({ error: 'Неверная сумма перевода' });
}
const sender = await User.findById(req.user.userId);
const recipient = await User.findOne({ username: recipientUsername });
if (!sender || !recipient) {
return res.status(404).json({ error: 'Отправитель или получатель не найден' });
}
if (sender.balance < amount) {
return res.status(400).json({ error: 'Недостаточно средств' });
}
// Выполняем перевод
sender.balance -= amount;
recipient.balance += amount;
await sender.save();
await recipient.save();
// Добавляем достижение за первый перевод
if (sender.achievements.every(a => a.id !== 'first_transfer')) {
await sender.addAchievement({
id: 'first_transfer',
name: 'Щедрая душа',
description: 'Совершили первый перевод',
dateUnlocked: new Date()
});
}
res.json({ success: true, balance: sender.balance });
} catch (error) {
res.status(500).json({ error: 'Ошибка сервера' });
}
});
const PORT = process.env.PORT || 3001;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});