diff --git a/bin/QUICK_FIX.md b/bin/QUICK_FIX.md new file mode 100644 index 0000000..e99aded --- /dev/null +++ b/bin/QUICK_FIX.md @@ -0,0 +1,54 @@ +# Быстрое исправление проблем с миграциями + +## Проблема +При запуске миграций возникают ошибки с TypeScript-файлами и проблемы с модульными разрешениями. + +## Быстрое решение + +1. **Примените прямые SQL-миграции (рекомендуемый способ)**: + ```bash + chmod +x bin/apply_direct_sql.sh + ./bin/apply_direct_sql.sh + ``` + Этот скрипт создаст и применит консолидированную SQL-миграцию, которая создаст все необходимые таблицы. + +2. **Создайте консолидированную JS-миграцию**: + ```bash + chmod +x bin/create_consolidated_migration.sh + ./bin/create_consolidated_migration.sh + ``` + Затем примените её: + ```bash + DATABASE_URL="postgres://$DB_USERNAME:$DB_PASSWORD@$DB_HOST:$DB_PORT/$DB_NAME" npx node-pg-migrate up + ``` + +## Проверка результата + +После выполнения миграций проверьте наличие таблиц в базе данных: + +```bash +export PGPASSWORD=$DB_PASSWORD +psql -h $DB_HOST -p $DB_PORT -U $DB_USERNAME -d $DB_NAME -c "\dt" +``` + +## Если проблемы сохраняются + +1. **Проверьте доступность базы данных**: + ```bash + export PGPASSWORD=$DB_PASSWORD + psql -h $DB_HOST -p $DB_PORT -U $DB_USERNAME -d $DB_NAME -c "SELECT 1" + ``` + +2. **Проверьте правильность переменных окружения**: + ```bash + echo "DB_HOST: $DB_HOST" + echo "DB_PORT: $DB_PORT" + echo "DB_NAME: $DB_NAME" + echo "DB_USERNAME: $DB_USERNAME" + ``` + +3. **Установите PostgreSQL-клиент**, если он отсутствует: + ```bash + apt-get update + apt-get install -y postgresql-client + ``` diff --git a/bin/apply_direct_sql.sh b/bin/apply_direct_sql.sh new file mode 100644 index 0000000..044b1e3 --- /dev/null +++ b/bin/apply_direct_sql.sh @@ -0,0 +1,208 @@ +#!/bin/bash +# apply_direct_sql.sh - Прямое выполнение SQL-миграций с помощью psql + +echo "🚀 Прямое выполнение SQL-миграций..." + +# Загрузка переменных окружения из .env +if [ -f .env ]; then + echo "📝 Загрузка переменных окружения из .env..." + set -o allexport + source .env + set +o allexport +else + echo "⚠️ Файл .env не найден, используем значения по умолчанию" + export DB_HOST="localhost" + export DB_PORT="5432" + export DB_NAME="telegram_tinder_bot" + export DB_USERNAME="postgres" + export DB_PASSWORD="postgres" +fi + +# Создаем консолидированный SQL-файл +echo "📝 Создание консолидированного SQL-файла..." +consolidated_sql="consolidated_migration.sql" + +cat > "$consolidated_sql" << EOL +-- Консолидированная миграция для Telegram Tinder Bot +-- Создана автоматически: $(date) + +-- Создаем таблицу migrations, если её еще нет +CREATE TABLE IF NOT EXISTS migrations ( + id SERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL, + executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- Основная структура базы данных + +-- Таблица пользователей +CREATE TABLE IF NOT EXISTS users ( + id BIGINT PRIMARY KEY, + username VARCHAR(255), + first_name VARCHAR(255), + last_name VARCHAR(255), + language_code VARCHAR(10), + is_bot BOOLEAN DEFAULT FALSE, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + state VARCHAR(50) DEFAULT 'START', + state_data JSONB, + gender VARCHAR(10), + looking_for VARCHAR(10), + bio TEXT, + age INTEGER, + location VARCHAR(255), + photos JSONB DEFAULT '[]'::jsonb, + interests TEXT[], + premium BOOLEAN DEFAULT FALSE, + premium_expires_at TIMESTAMP +); + +-- Таблица профилей +CREATE TABLE IF NOT EXISTS profiles ( + id SERIAL PRIMARY KEY, + user_id BIGINT REFERENCES users(id) ON DELETE CASCADE, + name VARCHAR(255), + age INTEGER, + gender VARCHAR(10), + bio TEXT, + photos JSONB DEFAULT '[]'::jsonb, + interests TEXT[], + location VARCHAR(255), + religion VARCHAR(50), + education VARCHAR(255), + job VARCHAR(255), + height INTEGER, + smoking VARCHAR(50), + drinking VARCHAR(50), + looking_for VARCHAR(10), + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- Таблица лайков +CREATE TABLE IF NOT EXISTS likes ( + id SERIAL PRIMARY KEY, + from_user_id BIGINT REFERENCES users(id) ON DELETE CASCADE, + to_user_id BIGINT REFERENCES users(id) ON DELETE CASCADE, + is_like BOOLEAN NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + UNIQUE(from_user_id, to_user_id) +); + +-- Таблица матчей +CREATE TABLE IF NOT EXISTS matches ( + id SERIAL PRIMARY KEY, + user1_id BIGINT REFERENCES users(id) ON DELETE CASCADE, + user2_id BIGINT REFERENCES users(id) ON DELETE CASCADE, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + active BOOLEAN DEFAULT TRUE, + UNIQUE(user1_id, user2_id) +); + +-- Таблица сообщений +CREATE TABLE IF NOT EXISTS messages ( + id SERIAL PRIMARY KEY, + match_id INTEGER REFERENCES matches(id) ON DELETE CASCADE, + sender_id BIGINT REFERENCES users(id) ON DELETE CASCADE, + message_text TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- Таблица просмотров профилей +CREATE TABLE IF NOT EXISTS profile_views ( + id SERIAL PRIMARY KEY, + viewer_id BIGINT REFERENCES users(id) ON DELETE CASCADE, + viewed_id BIGINT REFERENCES users(id) ON DELETE CASCADE, + viewed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + UNIQUE(viewer_id, viewed_id) +); + +-- Таблица уведомлений +CREATE TABLE IF NOT EXISTS notifications ( + id SERIAL PRIMARY KEY, + user_id BIGINT REFERENCES users(id) ON DELETE CASCADE, + type VARCHAR(50) NOT NULL, + data JSONB, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + scheduled_for TIMESTAMP, + processed BOOLEAN DEFAULT FALSE +); + +-- Индексы для оптимизации запросов + +-- Индексы для таблицы пользователей +CREATE INDEX IF NOT EXISTS users_username_idx ON users(username); +CREATE INDEX IF NOT EXISTS users_gender_idx ON users(gender); +CREATE INDEX IF NOT EXISTS users_looking_for_idx ON users(looking_for); +CREATE INDEX IF NOT EXISTS users_premium_idx ON users(premium); + +-- Индексы для таблицы лайков +CREATE INDEX IF NOT EXISTS likes_from_user_id_idx ON likes(from_user_id); +CREATE INDEX IF NOT EXISTS likes_to_user_id_idx ON likes(to_user_id); +CREATE INDEX IF NOT EXISTS likes_is_like_idx ON likes(is_like); + +-- Индексы для таблицы матчей +CREATE INDEX IF NOT EXISTS matches_user1_id_idx ON matches(user1_id); +CREATE INDEX IF NOT EXISTS matches_user2_id_idx ON matches(user2_id); +CREATE INDEX IF NOT EXISTS matches_active_idx ON matches(active); + +-- Индексы для таблицы сообщений +CREATE INDEX IF NOT EXISTS messages_match_id_idx ON messages(match_id); +CREATE INDEX IF NOT EXISTS messages_sender_id_idx ON messages(sender_id); + +-- Индексы для таблицы профилей +CREATE INDEX IF NOT EXISTS profiles_user_id_idx ON profiles(user_id); +CREATE INDEX IF NOT EXISTS profiles_gender_idx ON profiles(gender); +CREATE INDEX IF NOT EXISTS profiles_looking_for_idx ON profiles(looking_for); + +-- Индексы для таблицы просмотров профилей +CREATE INDEX IF NOT EXISTS profile_views_viewer_id_idx ON profile_views(viewer_id); +CREATE INDEX IF NOT EXISTS profile_views_viewed_id_idx ON profile_views(viewed_id); + +-- Индексы для таблицы уведомлений +CREATE INDEX IF NOT EXISTS notifications_user_id_idx ON notifications(user_id); +CREATE INDEX IF NOT EXISTS notifications_scheduled_for_idx ON notifications(scheduled_for); +CREATE INDEX IF NOT EXISTS notifications_processed_idx ON notifications(processed); + +-- Запись о выполнении миграции +INSERT INTO migrations (name) VALUES ('consolidated_migration.sql') +ON CONFLICT DO NOTHING; +EOL + +echo "✅ Консолидированный SQL-файл создан: $consolidated_sql" + +# Вывод информации о подключении +echo "🔍 Используемые параметры подключения:" +echo "DB_HOST: $DB_HOST" +echo "DB_PORT: $DB_PORT" +echo "DB_NAME: $DB_NAME" +echo "DB_USERNAME: $DB_USERNAME" +echo "DB_PASSWORD: ********" + +# Проверка наличия psql +if command -v psql >/dev/null; then + echo "✅ Найдена команда psql, продолжаем..." +else + echo "⚠️ Команда psql не найдена, установите PostgreSQL клиент:" + echo "apt-get update && apt-get install -y postgresql-client" + exit 1 +fi + +# Применение миграции +echo "🔄 Применение консолидированной миграции..." +export PGPASSWORD=$DB_PASSWORD +psql -h $DB_HOST -p $DB_PORT -U $DB_USERNAME -d $DB_NAME -f "$consolidated_sql" + +# Проверка результата +if [ $? -eq 0 ]; then + echo "✅ Миграция успешно применена!" +else + echo "❌ Ошибка при применении миграции!" + exit 1 +fi + +# Удаление временного файла +rm -f "$consolidated_sql" + +echo "🚀 Миграция базы данных завершена!" diff --git a/bin/compile_ts_migrations.sh b/bin/compile_ts_migrations.sh index df65729..19756b4 100644 --- a/bin/compile_ts_migrations.sh +++ b/bin/compile_ts_migrations.sh @@ -18,9 +18,15 @@ cat > migrations/tsconfig.json << EOL "module": "commonjs", "esModuleInterop": true, "forceConsistentCasingInFileNames": true, - "strict": true, + "moduleResolution": "node", + "resolveJsonModule": true, "skipLibCheck": true, - "outDir": "../temp_migrations" + "strict": false, + "outDir": "../temp_migrations", + "baseUrl": "..", + "paths": { + "*": ["node_modules/*"] + } }, "include": ["./*.ts"] } diff --git a/bin/create_consolidated_migration.sh b/bin/create_consolidated_migration.sh new file mode 100644 index 0000000..74bbf87 --- /dev/null +++ b/bin/create_consolidated_migration.sh @@ -0,0 +1,188 @@ +#!/bin/bash +# create_consolidated_migration.sh - Создание консолидированной миграции из всех источников + +echo "🚀 Создание консолидированной миграции..." + +# Создаем каталог для миграций если его нет +mkdir -p migrations + +# Текущее время для имени файла +timestamp=$(date +%s) + +# Путь к консолидированной миграции +consolidated_file="migrations/${timestamp}_consolidated_migration.js" + +echo "📝 Создание файла $consolidated_file..." + +# Создаем JS-миграцию +cat > "$consolidated_file" << EOL +/* eslint-disable camelcase */ + +exports.shorthands = undefined; + +exports.up = pgm => { + // Консолидированная миграция, созданная автоматически + + // Создаем таблицу migrations, если её ещё нет + pgm.sql(\` + CREATE TABLE IF NOT EXISTS migrations ( + id SERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL, + executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ); + \`); + + // Создаем основную структуру базы данных + pgm.sql(\` + -- Таблица пользователей + CREATE TABLE IF NOT EXISTS users ( + id BIGINT PRIMARY KEY, + username VARCHAR(255), + first_name VARCHAR(255), + last_name VARCHAR(255), + language_code VARCHAR(10), + is_bot BOOLEAN DEFAULT FALSE, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + state VARCHAR(50) DEFAULT 'START', + state_data JSONB, + gender VARCHAR(10), + looking_for VARCHAR(10), + bio TEXT, + age INTEGER, + location VARCHAR(255), + photos JSONB DEFAULT '[]'::jsonb, + interests TEXT[], + premium BOOLEAN DEFAULT FALSE, + premium_expires_at TIMESTAMP + ); + + -- Таблица профилей + CREATE TABLE IF NOT EXISTS profiles ( + id SERIAL PRIMARY KEY, + user_id BIGINT REFERENCES users(id) ON DELETE CASCADE, + name VARCHAR(255), + age INTEGER, + gender VARCHAR(10), + bio TEXT, + photos JSONB DEFAULT '[]'::jsonb, + interests TEXT[], + location VARCHAR(255), + religion VARCHAR(50), + education VARCHAR(255), + job VARCHAR(255), + height INTEGER, + smoking VARCHAR(50), + drinking VARCHAR(50), + looking_for VARCHAR(10), + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ); + + -- Таблица лайков + CREATE TABLE IF NOT EXISTS likes ( + id SERIAL PRIMARY KEY, + from_user_id BIGINT REFERENCES users(id) ON DELETE CASCADE, + to_user_id BIGINT REFERENCES users(id) ON DELETE CASCADE, + is_like BOOLEAN NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + UNIQUE(from_user_id, to_user_id) + ); + + -- Таблица матчей + CREATE TABLE IF NOT EXISTS matches ( + id SERIAL PRIMARY KEY, + user1_id BIGINT REFERENCES users(id) ON DELETE CASCADE, + user2_id BIGINT REFERENCES users(id) ON DELETE CASCADE, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + active BOOLEAN DEFAULT TRUE, + UNIQUE(user1_id, user2_id) + ); + + -- Таблица сообщений + CREATE TABLE IF NOT EXISTS messages ( + id SERIAL PRIMARY KEY, + match_id INTEGER REFERENCES matches(id) ON DELETE CASCADE, + sender_id BIGINT REFERENCES users(id) ON DELETE CASCADE, + message_text TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ); + + -- Таблица просмотров профилей + CREATE TABLE IF NOT EXISTS profile_views ( + id SERIAL PRIMARY KEY, + viewer_id BIGINT REFERENCES users(id) ON DELETE CASCADE, + viewed_id BIGINT REFERENCES users(id) ON DELETE CASCADE, + viewed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + UNIQUE(viewer_id, viewed_id) + ); + + -- Таблица уведомлений + CREATE TABLE IF NOT EXISTS notifications ( + id SERIAL PRIMARY KEY, + user_id BIGINT REFERENCES users(id) ON DELETE CASCADE, + type VARCHAR(50) NOT NULL, + data JSONB, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + scheduled_for TIMESTAMP, + processed BOOLEAN DEFAULT FALSE + ); + \`); + + // Индексы для оптимизации запросов + pgm.sql(\` + -- Индексы для таблицы пользователей + CREATE INDEX IF NOT EXISTS users_username_idx ON users(username); + CREATE INDEX IF NOT EXISTS users_gender_idx ON users(gender); + CREATE INDEX IF NOT EXISTS users_looking_for_idx ON users(looking_for); + CREATE INDEX IF NOT EXISTS users_premium_idx ON users(premium); + + -- Индексы для таблицы лайков + CREATE INDEX IF NOT EXISTS likes_from_user_id_idx ON likes(from_user_id); + CREATE INDEX IF NOT EXISTS likes_to_user_id_idx ON likes(to_user_id); + CREATE INDEX IF NOT EXISTS likes_is_like_idx ON likes(is_like); + + -- Индексы для таблицы матчей + CREATE INDEX IF NOT EXISTS matches_user1_id_idx ON matches(user1_id); + CREATE INDEX IF NOT EXISTS matches_user2_id_idx ON matches(user2_id); + CREATE INDEX IF NOT EXISTS matches_active_idx ON matches(active); + + -- Индексы для таблицы сообщений + CREATE INDEX IF NOT EXISTS messages_match_id_idx ON messages(match_id); + CREATE INDEX IF NOT EXISTS messages_sender_id_idx ON messages(sender_id); + + -- Индексы для таблицы профилей + CREATE INDEX IF NOT EXISTS profiles_user_id_idx ON profiles(user_id); + CREATE INDEX IF NOT EXISTS profiles_gender_idx ON profiles(gender); + CREATE INDEX IF NOT EXISTS profiles_looking_for_idx ON profiles(looking_for); + + -- Индексы для таблицы просмотров профилей + CREATE INDEX IF NOT EXISTS profile_views_viewer_id_idx ON profile_views(viewer_id); + CREATE INDEX IF NOT EXISTS profile_views_viewed_id_idx ON profile_views(viewed_id); + + -- Индексы для таблицы уведомлений + CREATE INDEX IF NOT EXISTS notifications_user_id_idx ON notifications(user_id); + CREATE INDEX IF NOT EXISTS notifications_scheduled_for_idx ON notifications(scheduled_for); + CREATE INDEX IF NOT EXISTS notifications_processed_idx ON notifications(processed); + \`); +}; + +exports.down = pgm => { + // Эта функция не будет фактически использоваться, + // но для полноты оставляем возможность отката + pgm.sql(\` + DROP TABLE IF EXISTS notifications; + DROP TABLE IF EXISTS profile_views; + DROP TABLE IF EXISTS messages; + DROP TABLE IF EXISTS matches; + DROP TABLE IF EXISTS likes; + DROP TABLE IF EXISTS profiles; + DROP TABLE IF EXISTS users; + \`); +}; +EOL + +echo "✅ Консолидированная миграция создана: $consolidated_file" +echo "" +echo "🚀 Для применения миграции выполните:" +echo "DATABASE_URL=postgres://\${DB_USERNAME}:\${DB_PASSWORD}@\${DB_HOST}:\${DB_PORT}/\${DB_NAME} npx node-pg-migrate up" diff --git a/bin/fix_permissions.sh b/bin/fix_permissions.sh new file mode 100644 index 0000000..7aa6206 --- /dev/null +++ b/bin/fix_permissions.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# fix_permissions.sh - Устанавливает права на выполнение для всех скриптов + +echo "🔧 Установка прав на выполнение для всех скриптов..." + +# Находим все .sh файлы и устанавливаем права на выполнение +find . -name "*.sh" -type f -exec chmod +x {} \; + +echo "✅ Права на выполнение установлены!" + +# Исправление переносов строк +echo "🔧 Исправление переносов строк..." +find . -name "*.sh" -type f -exec sh -c 'tr -d "\r" < "$1" > "$1.fixed" && mv "$1.fixed" "$1"' -- {} \; + +echo "✅ Переносы строк исправлены!" + +echo "🚀 Готово! Все скрипты готовы к использованию."