ваше сообщение коммита

This commit is contained in:
2025-04-21 10:40:57 +03:00
parent f371521511
commit 16c3534239
22 changed files with 637 additions and 84 deletions

41
backend/.env.example Normal file
View File

@@ -0,0 +1,41 @@
PORT=8000
NODE_ENV=development
SESSION_SECRET=your_session_secret
# RPC URLs
RPC_URL_ETH=https://your-ethereum-rpc-url
RPC_URL_POLYGON=https://your-polygon-rpc-url
RPC_URL_BSC=https://your-bsc-rpc-url
RPC_URL_ARBITRUM=https://your-arbitrum-rpc-url
RPC_URL=https://your-default-rpc-url
ETHEREUM_NETWORK_URL=https://your-ethereum-network-url
PRIVATE_KEY=your_private_key_here
ETHERSCAN_API_KEY=your_etherscan_api_key
# Database
DATABASE_URL=postgresql://dapp_user:dapp_password@postgres:5432/dapp_db
DB_HOST=postgres
DB_PORT=5432
DB_NAME=dapp_db
DB_USER=dapp_user
DB_PASSWORD=dapp_password
# Email Configuration
EMAIL_USER=your_email@example.com
EMAIL_PASSWORD=your_email_password
EMAIL_SMTP_HOST=smtp.example.com
EMAIL_SMTP_PORT=465
EMAIL_IMAP_HOST=imap.example.com
EMAIL_IMAP_PORT=993
# Ollama AI Configuration
OLLAMA_BASE_URL=http://ollama:11434
OLLAMA_EMBEDDINGS_MODEL=qwen2.5:7b
OLLAMA_MODEL=qwen2.5:7b
# Telegram Bot
TELEGRAM_BOT_TOKEN=your_telegram_bot_token
TELEGRAM_BOT_USERNAME=your_bot_username
# Frontend URL
FRONTEND_URL=http://localhost:5173

69
backend/.gitignore vendored
View File

@@ -1,45 +1,44 @@
# Зависимости
node_modules/
yarn-error.log
# Переменные окружения
.env
.env.local
.env.development
.env.test
.env.production
/.pnp
.pnp.js
# Логи
logs/*
!logs/.gitkeep
logs/
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Кэш и временные файлы
# Файлы окружения
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# Кэши и временные файлы
.cache/
cache/
dist/
build/
tmp/
temp/
# Артефакты Hardhat
artifacts/
cache/
typechain/
typechain-types/
# Файлы покрытия кода
coverage/
coverage.json
# Файлы IDE
.temp/
.DS_Store
.idea/
.vscode/
*.sublime-project
*.sublime-workspace
*.swp
*.swo
# Системные файлы
.DS_Store
Thumbs.db
# Compiled output
/dist
/build
# Файлы сессий
sessions/
# Приватные ключи и сертификаты
*.pem
*.key
# Локальные настройки
.prettierrc.local
.eslintrc.local
# Файлы базы данных
*.db
*.sqlite
*.sqlite3

21
backend/Dockerfile Normal file
View File

@@ -0,0 +1,21 @@
FROM node:20-alpine
WORKDIR /app
# Устанавливаем зависимости, включая Python для node-gyp
RUN apk add --no-cache python3 make g++
# Копируем package.json и yarn.lock для установки зависимостей
COPY package.json yarn.lock ./
# Устанавливаем зависимости
RUN yarn install --frozen-lockfile
# Копируем остальные файлы проекта
COPY . .
# Экспозим порт
EXPOSE 8000
# Команда запуска по умолчанию
CMD ["yarn", "run", "dev"]

View File

@@ -22,7 +22,7 @@ const tokensRouter = require('./routes/tokens');
const app = express();
// Указываем хост явно
app.set('host', '127.0.0.1');
app.set('host', '0.0.0.0');
app.set('port', process.env.PORT || 8000);
// Настройка CORS

View File

@@ -1,6 +1,14 @@
const { Pool } = require('pg');
require('dotenv').config();
// Выводим настройки подключения (без пароля)
console.log('Настройки подключения к базе данных:');
console.log('DATABASE_URL:', process.env.DATABASE_URL?.replace(/:([^:@]+)@/, ':***@'));
console.log('DB_HOST:', process.env.DB_HOST);
console.log('DB_PORT:', process.env.DB_PORT);
console.log('DB_NAME:', process.env.DB_NAME);
console.log('DB_USER:', process.env.DB_USER);
// Создаем пул соединений с базой данных
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
@@ -11,10 +19,30 @@ const pool = new Pool({
pool.query('SELECT NOW()', (err, res) => {
if (err) {
console.error('Ошибка подключения к базе данных:', err);
console.log('Переключение на временное хранилище данных в памяти...');
// Если не удалось подключиться к базе данных, используем временное хранилище
module.exports = createInMemoryStorage();
// Пробуем альтернативное подключение
console.log('Попытка альтернативного подключения через прямые параметры...');
const altPool = new Pool({
host: process.env.DB_HOST || 'localhost',
port: parseInt(process.env.DB_PORT || '5432'),
database: process.env.DB_NAME || 'dapp_db',
user: process.env.DB_USER || 'dapp_user',
password: process.env.DB_PASSWORD,
});
altPool.query('SELECT NOW()', (altErr, altRes) => {
if (altErr) {
console.error('Альтернативное подключение тоже не удалось:', altErr);
console.log('Переключение на временное хранилище данных в памяти...');
module.exports = createInMemoryStorage();
} else {
console.log('Альтернативное подключение успешно:', altRes.rows[0]);
// Заменяем основной пул на альтернативный
module.exports.pool = altPool;
module.exports.query = (text, params) => altPool.query(text, params);
}
});
} else {
console.log('Успешное подключение к базе данных:', res.rows[0]);
}

View File

@@ -8,7 +8,7 @@ CREATE TABLE IF NOT EXISTS messages (
metadata JSONB,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
role VARCHAR(20) NOT NULL DEFAULT 'user',
guest_message_id INTEGER,
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
tokens_used INTEGER DEFAULT 0,
is_processed BOOLEAN DEFAULT FALSE
);
@@ -17,4 +17,5 @@ CREATE INDEX IF NOT EXISTS idx_messages_conversation_id ON messages(conversation
CREATE INDEX IF NOT EXISTS idx_messages_sender_type ON messages(sender_type);
CREATE INDEX IF NOT EXISTS idx_messages_created_at ON messages(created_at);
CREATE INDEX IF NOT EXISTS idx_messages_channel ON messages(channel);
CREATE INDEX IF NOT EXISTS idx_messages_metadata ON messages USING gin(metadata);
CREATE INDEX IF NOT EXISTS idx_messages_metadata ON messages USING gin(metadata);
CREATE INDEX IF NOT EXISTS idx_messages_user_id ON messages(user_id);

View File

@@ -53,7 +53,7 @@ BEGIN
content,
role,
channel,
guest_message_id,
user_id,
created_at
)
SELECT
@@ -63,14 +63,16 @@ BEGIN
content,
CASE WHEN is_ai THEN 'assistant' ELSE 'user' END,
'chat',
id, -- Сохраняем связь с гостевым сообщением
p_user_id,
created_at
FROM guest_messages
WHERE guest_id = p_guest_id
-- Проверка, чтобы избежать дублирования сообщений
-- Проверка, чтобы избежать дублирования сообщений на основе содержимого и времени
AND NOT EXISTS (
SELECT 1 FROM messages m
WHERE m.guest_message_id = guest_messages.id
WHERE m.conversation_id = v_conversation_id
AND m.content = guest_messages.content
AND m.created_at = guest_messages.created_at
)
ORDER BY created_at
RETURNING id

View File

0
backend/logs/error.log Normal file
View File

View File

@@ -18,8 +18,8 @@ async function checkOllamaModels() {
});
console.log('\nДля использования конкретной модели, укажите ее в .env файле:');
console.log('OLLAMA_EMBEDDINGS_MODEL=mistral:7b-instruct-q4_K_M');
console.log('OLLAMA_MODEL=mistral:7b-instruct-q4_K_M');
console.log('OLLAMA_EMBEDDINGS_MODEL=qwen2.5');
console.log('OLLAMA_MODEL=qwen2.5');
} else {
console.log('Не удалось получить список моделей');
}

View File

@@ -0,0 +1,17 @@
#!/bin/bash
set -e
host="$1"
shift
port="$1"
shift
cmd="$@"
until PGPASSWORD=$DB_PASSWORD psql -h "$host" -U "$DB_USER" -p "$port" -d "$DB_NAME" -c '\q'; do
>&2 echo "Ожидание подключения к PostgreSQL..."
sleep 1
done
>&2 echo "PostgreSQL запущен - выполнение команды"
exec $cmd

View File

@@ -7,7 +7,7 @@ const fetch = require('node-fetch');
class AIAssistant {
constructor() {
this.baseUrl = process.env.OLLAMA_BASE_URL || 'http://localhost:11434';
this.defaultModel = process.env.OLLAMA_MODEL || 'mistral:7b-instruct-q4_K_M';
this.defaultModel = process.env.OLLAMA_MODEL || 'qwen2.5';
}
// Создание экземпляра ChatOllama с нужными параметрами