pre-deploy commit
This commit is contained in:
108
src/database/migrateOnStartup.ts
Normal file
108
src/database/migrateOnStartup.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
// Script to run migrations on startup
|
||||
import { Pool } from 'pg';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import 'dotenv/config';
|
||||
|
||||
async function runMigrations() {
|
||||
console.log('Starting database migration...');
|
||||
|
||||
// Create a connection pool
|
||||
const pool = new Pool({
|
||||
host: process.env.DB_HOST || 'localhost',
|
||||
port: parseInt(process.env.DB_PORT || '5432'),
|
||||
database: process.env.DB_NAME || 'telegram_tinder_bot',
|
||||
user: process.env.DB_USERNAME || 'postgres',
|
||||
password: process.env.DB_PASSWORD,
|
||||
max: 20,
|
||||
idleTimeoutMillis: 30000,
|
||||
connectionTimeoutMillis: 2000,
|
||||
});
|
||||
|
||||
try {
|
||||
// Test connection
|
||||
const testRes = await pool.query('SELECT NOW()');
|
||||
console.log(`Database connection successful at ${testRes.rows[0].now}`);
|
||||
|
||||
// Create migrations table if not exists
|
||||
await pool.query(`
|
||||
CREATE TABLE IF NOT EXISTS migrations (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
`);
|
||||
|
||||
// Get list of executed migrations
|
||||
const migrationRes = await pool.query('SELECT name FROM migrations');
|
||||
const executedMigrations = migrationRes.rows.map(row => row.name);
|
||||
console.log(`Found ${executedMigrations.length} executed migrations`);
|
||||
|
||||
// Get migration files
|
||||
const migrationsPath = path.join(__dirname, 'migrations');
|
||||
let migrationFiles = [];
|
||||
|
||||
try {
|
||||
migrationFiles = fs.readdirSync(migrationsPath)
|
||||
.filter(file => file.endsWith('.sql'))
|
||||
.sort();
|
||||
console.log(`Found ${migrationFiles.length} migration files`);
|
||||
} catch (error: any) {
|
||||
console.error(`Error reading migrations directory: ${error.message}`);
|
||||
console.log('Continuing with built-in consolidated migration...');
|
||||
|
||||
// If no external files found, use consolidated.sql
|
||||
const consolidatedSQL = fs.readFileSync(path.join(__dirname, 'migrations', 'consolidated.sql'), 'utf8');
|
||||
|
||||
console.log('Executing consolidated migration...');
|
||||
await pool.query(consolidatedSQL);
|
||||
|
||||
if (!executedMigrations.includes('consolidated.sql')) {
|
||||
await pool.query(
|
||||
'INSERT INTO migrations (name) VALUES ($1)',
|
||||
['consolidated.sql']
|
||||
);
|
||||
}
|
||||
|
||||
console.log('Consolidated migration completed successfully');
|
||||
return;
|
||||
}
|
||||
|
||||
// Run each migration that hasn't been executed yet
|
||||
for (const file of migrationFiles) {
|
||||
if (!executedMigrations.includes(file)) {
|
||||
console.log(`Executing migration: ${file}`);
|
||||
const sql = fs.readFileSync(path.join(migrationsPath, file), 'utf8');
|
||||
|
||||
try {
|
||||
await pool.query('BEGIN');
|
||||
await pool.query(sql);
|
||||
await pool.query(
|
||||
'INSERT INTO migrations (name) VALUES ($1)',
|
||||
[file]
|
||||
);
|
||||
await pool.query('COMMIT');
|
||||
console.log(`Migration ${file} completed successfully`);
|
||||
} catch (error: any) {
|
||||
await pool.query('ROLLBACK');
|
||||
console.error(`Error executing migration ${file}: ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
} else {
|
||||
console.log(`Migration ${file} already executed, skipping`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('All migrations completed successfully!');
|
||||
} catch (error: any) {
|
||||
console.error(`Migration failed: ${error.message}`);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
await pool.end();
|
||||
}
|
||||
}
|
||||
|
||||
runMigrations().catch((error: any) => {
|
||||
console.error('Unhandled error during migration:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
182
src/database/migrations/consolidated.sql
Normal file
182
src/database/migrations/consolidated.sql
Normal file
@@ -0,0 +1,182 @@
|
||||
-- Consolidated migrations for Telegram Tinder Bot
|
||||
|
||||
-- Create extension for UUID if not exists
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
|
||||
|
||||
----------------------------------------------
|
||||
-- Core Tables
|
||||
----------------------------------------------
|
||||
|
||||
-- Users table
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
telegram_id BIGINT UNIQUE NOT NULL,
|
||||
username VARCHAR(255),
|
||||
first_name VARCHAR(255),
|
||||
last_name VARCHAR(255),
|
||||
language_code VARCHAR(10) DEFAULT 'ru',
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
last_active_at TIMESTAMP DEFAULT NOW(),
|
||||
premium BOOLEAN DEFAULT FALSE,
|
||||
state VARCHAR(255),
|
||||
state_data JSONB DEFAULT '{}'::jsonb
|
||||
);
|
||||
|
||||
-- Profiles table
|
||||
CREATE TABLE IF NOT EXISTS profiles (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
age INTEGER NOT NULL CHECK (age >= 18 AND age <= 100),
|
||||
gender VARCHAR(10) NOT NULL CHECK (gender IN ('male', 'female', 'other')),
|
||||
interested_in VARCHAR(10) NOT NULL CHECK (interested_in IN ('male', 'female', 'both')),
|
||||
bio TEXT,
|
||||
photos JSONB DEFAULT '[]',
|
||||
interests JSONB DEFAULT '[]',
|
||||
city VARCHAR(255),
|
||||
education VARCHAR(255),
|
||||
job VARCHAR(255),
|
||||
height INTEGER,
|
||||
location_lat DECIMAL(10, 8),
|
||||
location_lon DECIMAL(11, 8),
|
||||
search_min_age INTEGER DEFAULT 18,
|
||||
search_max_age INTEGER DEFAULT 50,
|
||||
search_max_distance INTEGER DEFAULT 50,
|
||||
is_verified BOOLEAN DEFAULT FALSE,
|
||||
is_visible BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW(),
|
||||
religion VARCHAR(255),
|
||||
dating_goal VARCHAR(50),
|
||||
smoking VARCHAR(20),
|
||||
drinking VARCHAR(20),
|
||||
has_kids BOOLEAN DEFAULT FALSE
|
||||
);
|
||||
|
||||
-- Swipes table
|
||||
CREATE TABLE IF NOT EXISTS swipes (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
||||
target_user_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
||||
type VARCHAR(20) NOT NULL CHECK (type IN ('like', 'pass', 'superlike')),
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
is_match BOOLEAN DEFAULT FALSE,
|
||||
UNIQUE(user_id, target_user_id)
|
||||
);
|
||||
|
||||
-- Matches table
|
||||
CREATE TABLE IF NOT EXISTS matches (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id_1 UUID REFERENCES users(id) ON DELETE CASCADE,
|
||||
user_id_2 UUID REFERENCES users(id) ON DELETE CASCADE,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
last_message_at TIMESTAMP,
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
is_super_match BOOLEAN DEFAULT FALSE,
|
||||
unread_count_1 INTEGER DEFAULT 0,
|
||||
unread_count_2 INTEGER DEFAULT 0,
|
||||
UNIQUE(user_id_1, user_id_2)
|
||||
);
|
||||
|
||||
-- Messages table
|
||||
CREATE TABLE IF NOT EXISTS messages (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
match_id UUID REFERENCES matches(id) ON DELETE CASCADE,
|
||||
sender_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
||||
receiver_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
||||
content TEXT NOT NULL,
|
||||
message_type VARCHAR(20) DEFAULT 'text' CHECK (message_type IN ('text', 'photo', 'gif', 'sticker')),
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
is_read BOOLEAN DEFAULT FALSE
|
||||
);
|
||||
|
||||
----------------------------------------------
|
||||
-- Profile Views Table
|
||||
----------------------------------------------
|
||||
|
||||
-- Table for tracking profile views
|
||||
CREATE TABLE IF NOT EXISTS profile_views (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
viewer_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
||||
viewed_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
||||
view_type VARCHAR(20) DEFAULT 'browse' CHECK (view_type IN ('browse', 'search', 'recommended')),
|
||||
viewed_at TIMESTAMP DEFAULT NOW(),
|
||||
CONSTRAINT unique_profile_view UNIQUE (viewer_id, viewed_id, view_type)
|
||||
);
|
||||
|
||||
-- Index for profile views
|
||||
CREATE INDEX IF NOT EXISTS idx_profile_views_viewer ON profile_views(viewer_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_profile_views_viewed ON profile_views(viewed_id);
|
||||
|
||||
----------------------------------------------
|
||||
-- Notification Tables
|
||||
----------------------------------------------
|
||||
|
||||
-- Notifications table
|
||||
CREATE TABLE IF NOT EXISTS notifications (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
type VARCHAR(50) NOT NULL,
|
||||
content JSONB NOT NULL DEFAULT '{}',
|
||||
is_read BOOLEAN DEFAULT FALSE,
|
||||
processed BOOLEAN DEFAULT FALSE,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Notification settings table
|
||||
CREATE TABLE IF NOT EXISTS notification_settings (
|
||||
user_id UUID PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
|
||||
new_matches BOOLEAN DEFAULT TRUE,
|
||||
new_messages BOOLEAN DEFAULT TRUE,
|
||||
new_likes BOOLEAN DEFAULT TRUE,
|
||||
reminders BOOLEAN DEFAULT TRUE,
|
||||
daily_summary BOOLEAN DEFAULT FALSE,
|
||||
time_preference VARCHAR(20) DEFAULT 'evening',
|
||||
do_not_disturb BOOLEAN DEFAULT FALSE,
|
||||
do_not_disturb_start TIME,
|
||||
do_not_disturb_end TIME,
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Scheduled notifications table
|
||||
CREATE TABLE IF NOT EXISTS scheduled_notifications (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
type VARCHAR(50) NOT NULL,
|
||||
content JSONB NOT NULL DEFAULT '{}',
|
||||
scheduled_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
processed BOOLEAN DEFAULT FALSE,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
----------------------------------------------
|
||||
-- Indexes for better performance
|
||||
----------------------------------------------
|
||||
|
||||
-- User Indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_users_telegram_id ON users(telegram_id);
|
||||
|
||||
-- Profile Indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_profiles_user_id ON profiles(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_profiles_location ON profiles(location_lat, location_lon)
|
||||
WHERE location_lat IS NOT NULL AND location_lon IS NOT NULL;
|
||||
CREATE INDEX IF NOT EXISTS idx_profiles_age_gender ON profiles(age, gender, interested_in);
|
||||
|
||||
-- Swipe Indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_swipes_user ON swipes(user_id, target_user_id);
|
||||
|
||||
-- Match Indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_matches_users ON matches(user_id_1, user_id_2);
|
||||
|
||||
-- Message Indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_messages_match ON messages(match_id, created_at);
|
||||
|
||||
-- Notification Indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_notifications_user_id ON notifications(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_notifications_type ON notifications(type);
|
||||
CREATE INDEX IF NOT EXISTS idx_notifications_created_at ON notifications(created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_scheduled_notifications_user_id ON scheduled_notifications(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_scheduled_notifications_scheduled_at ON scheduled_notifications(scheduled_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_scheduled_notifications_processed ON scheduled_notifications(processed);
|
||||
62
src/premium/README.md
Normal file
62
src/premium/README.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# Модуль премиум-функций Telegram Tinder Bot
|
||||
|
||||
Этот каталог содержит модули и скрипты для управления премиум-функциями бота.
|
||||
|
||||
## Содержимое
|
||||
|
||||
- `add-premium-columns.js` - Добавление колонок для премиум-функций в базу данных (версия JavaScript)
|
||||
- `add-premium-columns.ts` - Добавление колонок для премиум-функций в базу данных (версия TypeScript)
|
||||
- `add-premium-columns-direct.js` - Прямое добавление премиум-колонок без миграций
|
||||
- `addPremiumColumn.js` - Добавление отдельной колонки премиум в таблицу пользователей
|
||||
- `setPremiumStatus.js` - Обновление статуса премиум для пользователей
|
||||
|
||||
## Премиум-функции
|
||||
|
||||
В боте реализованы следующие премиум-функции:
|
||||
|
||||
1. **Неограниченные лайки** - снятие дневного лимита на количество лайков
|
||||
2. **Супер-лайки** - возможность отправлять супер-лайки (повышенный приоритет)
|
||||
3. **Просмотр лайков** - возможность видеть, кто поставил лайк вашему профилю
|
||||
4. **Скрытый режим** - возможность скрывать свою активность
|
||||
5. **Расширенные фильтры** - дополнительные параметры для поиска
|
||||
|
||||
## Использование
|
||||
|
||||
### Добавление премиум-колонок в базу данных
|
||||
|
||||
```bash
|
||||
node src/premium/add-premium-columns.js
|
||||
```
|
||||
|
||||
### Изменение премиум-статуса пользователя
|
||||
|
||||
```typescript
|
||||
import { PremiumService } from '../services/premiumService';
|
||||
|
||||
// Установка премиум-статуса для пользователя
|
||||
const premiumService = new PremiumService();
|
||||
await premiumService.setPremiumStatus(userId, true, 30); // 30 дней премиума
|
||||
```
|
||||
|
||||
## Интеграция в основной код
|
||||
|
||||
Проверка премиум-статуса должна выполняться следующим образом:
|
||||
|
||||
```typescript
|
||||
// В классах контроллеров
|
||||
const isPremium = await this.premiumService.checkUserPremium(userId);
|
||||
|
||||
if (isPremium) {
|
||||
// Предоставить премиум-функцию
|
||||
} else {
|
||||
// Сообщить о необходимости премиум-подписки
|
||||
}
|
||||
```
|
||||
|
||||
## Период действия премиум-статуса
|
||||
|
||||
По умолчанию премиум-статус устанавливается на 30 дней. Для изменения срока используйте третий параметр в методе `setPremiumStatus`.
|
||||
|
||||
## Дополнительная информация
|
||||
|
||||
Более подробная информация о премиум-функциях содержится в документации проекта в каталоге `docs/VIP_FUNCTIONS.md`.
|
||||
44
src/premium/add-premium-columns-direct.js
Normal file
44
src/premium/add-premium-columns-direct.js
Normal file
@@ -0,0 +1,44 @@
|
||||
// add-premium-columns.js
|
||||
// Скрипт для добавления колонок premium и premium_expires_at в таблицу users
|
||||
|
||||
const { Pool } = require('pg');
|
||||
|
||||
// Настройки подключения к базе данных - используем те же настройки, что и раньше
|
||||
const pool = new Pool({
|
||||
host: '192.168.0.102',
|
||||
port: 5432,
|
||||
database: 'telegram_tinder_bot',
|
||||
user: 'trevor',
|
||||
password: 'Cl0ud_1985!'
|
||||
});
|
||||
|
||||
async function addPremiumColumns() {
|
||||
try {
|
||||
console.log('Подключение к базе данных...');
|
||||
const client = await pool.connect();
|
||||
|
||||
console.log('Добавление колонок premium и premium_expires_at в таблицу users...');
|
||||
|
||||
// SQL запрос для добавления колонок
|
||||
const sql = `
|
||||
ALTER TABLE users
|
||||
ADD COLUMN IF NOT EXISTS premium BOOLEAN DEFAULT FALSE,
|
||||
ADD COLUMN IF NOT EXISTS premium_expires_at TIMESTAMP;
|
||||
`;
|
||||
|
||||
await client.query(sql);
|
||||
console.log('✅ Колонки premium и premium_expires_at успешно добавлены в таблицу users');
|
||||
|
||||
// Закрытие соединения
|
||||
client.release();
|
||||
await pool.end();
|
||||
console.log('Подключение к базе данных закрыто');
|
||||
} catch (error) {
|
||||
console.error('❌ Ошибка при добавлении колонок:', error);
|
||||
await pool.end();
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Запуск функции
|
||||
addPremiumColumns();
|
||||
40
src/premium/add-premium-columns.js
Normal file
40
src/premium/add-premium-columns.js
Normal file
@@ -0,0 +1,40 @@
|
||||
// add-premium-columns.js
|
||||
// Скрипт для добавления колонок premium и premium_expires_at в таблицу users
|
||||
|
||||
const { Client } = require('pg');
|
||||
|
||||
// Настройки подключения к базе данных
|
||||
const client = new Client({
|
||||
host: '192.168.0.102',
|
||||
port: 5432,
|
||||
user: 'trevor',
|
||||
password: 'Cl0ud_1985!',
|
||||
database: 'telegram_tinder_bot'
|
||||
});
|
||||
|
||||
async function addPremiumColumns() {
|
||||
try {
|
||||
await client.connect();
|
||||
console.log('Подключение к базе данных успешно установлено');
|
||||
|
||||
// SQL запрос для добавления колонок
|
||||
const sql = `
|
||||
ALTER TABLE users
|
||||
ADD COLUMN IF NOT EXISTS premium BOOLEAN DEFAULT FALSE,
|
||||
ADD COLUMN IF NOT EXISTS premium_expires_at TIMESTAMP;
|
||||
`;
|
||||
|
||||
await client.query(sql);
|
||||
console.log('Колонки premium и premium_expires_at успешно добавлены в таблицу users');
|
||||
|
||||
// Закрываем подключение
|
||||
await client.end();
|
||||
console.log('Подключение к базе данных закрыто');
|
||||
} catch (error) {
|
||||
console.error('Ошибка при добавлении колонок:', error);
|
||||
await client.end();
|
||||
}
|
||||
}
|
||||
|
||||
// Запуск функции
|
||||
addPremiumColumns();
|
||||
28
src/premium/add-premium-columns.ts
Normal file
28
src/premium/add-premium-columns.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
// add-premium-columns.ts
|
||||
// Скрипт для добавления колонок premium и premium_expires_at в таблицу users
|
||||
|
||||
import { query } from '../src/database/connection';
|
||||
|
||||
async function addPremiumColumns() {
|
||||
try {
|
||||
console.log('Добавление колонок premium и premium_expires_at в таблицу users...');
|
||||
|
||||
// SQL запрос для добавления колонок
|
||||
const sql = `
|
||||
ALTER TABLE users
|
||||
ADD COLUMN IF NOT EXISTS premium BOOLEAN DEFAULT FALSE,
|
||||
ADD COLUMN IF NOT EXISTS premium_expires_at TIMESTAMP;
|
||||
`;
|
||||
|
||||
await query(sql);
|
||||
console.log('✅ Колонки premium и premium_expires_at успешно добавлены в таблицу users');
|
||||
|
||||
process.exit(0);
|
||||
} catch (error) {
|
||||
console.error('❌ Ошибка при добавлении колонок:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Запуск функции
|
||||
addPremiumColumns();
|
||||
58
src/premium/addPremiumColumn.js
Normal file
58
src/premium/addPremiumColumn.js
Normal file
@@ -0,0 +1,58 @@
|
||||
// Скрипт для добавления колонки premium в таблицу users и установки premium для всех пользователей
|
||||
require('dotenv').config();
|
||||
const { Pool } = require('pg');
|
||||
|
||||
// Создаем пул соединений
|
||||
const pool = new Pool({
|
||||
user: process.env.DB_USERNAME,
|
||||
host: process.env.DB_HOST,
|
||||
database: process.env.DB_NAME,
|
||||
password: process.env.DB_PASSWORD,
|
||||
port: parseInt(process.env.DB_PORT || '5432')
|
||||
});
|
||||
|
||||
async function setAllUsersToPremium() {
|
||||
try {
|
||||
console.log('Проверяем наличие столбца premium в таблице users...');
|
||||
|
||||
const result = await pool.query(`
|
||||
SELECT EXISTS (
|
||||
SELECT FROM information_schema.columns
|
||||
WHERE table_schema = 'public'
|
||||
AND table_name = 'users'
|
||||
AND column_name = 'premium'
|
||||
);
|
||||
`);
|
||||
|
||||
if (!result.rows[0].exists) {
|
||||
console.log('🔄 Добавляем столбец premium...');
|
||||
await pool.query(`ALTER TABLE users ADD COLUMN premium BOOLEAN DEFAULT false;`);
|
||||
console.log('✅ Столбец premium успешно добавлен');
|
||||
} else {
|
||||
console.log('✅ Столбец premium уже существует');
|
||||
}
|
||||
|
||||
console.log('Устанавливаем премиум-статус для всех пользователей...');
|
||||
|
||||
const updateResult = await pool.query(`
|
||||
UPDATE users
|
||||
SET premium = true
|
||||
WHERE true
|
||||
RETURNING id, telegram_id, premium
|
||||
`);
|
||||
|
||||
console.log(`✅ Успешно установлен премиум-статус для ${updateResult.rows.length} пользователей:`);
|
||||
updateResult.rows.forEach(row => {
|
||||
console.log(`ID: ${row.id.substr(0, 8)}... | Telegram ID: ${row.telegram_id} | Premium: ${row.premium}`);
|
||||
});
|
||||
|
||||
console.log('🎉 Все пользователи теперь имеют премиум-статус!');
|
||||
} catch (error) {
|
||||
console.error('Ошибка при установке премиум-статуса:', error);
|
||||
} finally {
|
||||
await pool.end();
|
||||
console.log('Соединение с базой данных закрыто');
|
||||
}
|
||||
}
|
||||
|
||||
setAllUsersToPremium();
|
||||
73
src/premium/setPremiumStatus.js
Normal file
73
src/premium/setPremiumStatus.js
Normal file
@@ -0,0 +1,73 @@
|
||||
// Скрипт для установки премиум-статуса всем пользователям
|
||||
require('dotenv').config();
|
||||
const { Pool } = require('pg');
|
||||
|
||||
// Проверяем и выводим параметры подключения
|
||||
console.log('Параметры подключения к БД:');
|
||||
console.log('DB_USERNAME:', process.env.DB_USERNAME);
|
||||
console.log('DB_HOST:', process.env.DB_HOST);
|
||||
console.log('DB_NAME:', process.env.DB_NAME);
|
||||
console.log('DB_PASSWORD:', process.env.DB_PASSWORD ? '[указан]' : '[не указан]');
|
||||
console.log('DB_PORT:', process.env.DB_PORT);
|
||||
|
||||
// Создаем пул соединений
|
||||
const pool = new Pool({
|
||||
user: process.env.DB_USERNAME,
|
||||
host: process.env.DB_HOST,
|
||||
database: process.env.DB_NAME,
|
||||
password: process.env.DB_PASSWORD,
|
||||
port: parseInt(process.env.DB_PORT || '5432')
|
||||
});
|
||||
|
||||
async function setAllUsersToPremium() {
|
||||
try {
|
||||
console.log('Устанавливаем премиум-статус для всех пользователей...');
|
||||
|
||||
// Проверка соединения с БД
|
||||
console.log('Проверка соединения с БД...');
|
||||
const testResult = await pool.query('SELECT NOW()');
|
||||
console.log('✅ Соединение успешно:', testResult.rows[0].now);
|
||||
|
||||
// Проверка наличия столбца premium
|
||||
console.log('Проверяем наличие столбца premium в таблице users...');
|
||||
|
||||
const checkResult = await pool.query(`
|
||||
SELECT EXISTS (
|
||||
SELECT FROM information_schema.columns
|
||||
WHERE table_schema = 'public'
|
||||
AND table_name = 'users'
|
||||
AND column_name = 'premium'
|
||||
);
|
||||
`);
|
||||
|
||||
if (!checkResult.rows[0].exists) {
|
||||
console.log('🔄 Добавляем столбец premium...');
|
||||
await pool.query(`ALTER TABLE users ADD COLUMN premium BOOLEAN DEFAULT false;`);
|
||||
console.log('✅ Столбец premium успешно добавлен');
|
||||
} else {
|
||||
console.log('✅ Столбец premium уже существует');
|
||||
}
|
||||
|
||||
// Устанавливаем premium=true для всех пользователей
|
||||
const updateResult = await pool.query(`
|
||||
UPDATE users
|
||||
SET premium = true
|
||||
WHERE true
|
||||
RETURNING id, telegram_id, premium
|
||||
`);
|
||||
|
||||
console.log(`✅ Успешно установлен премиум-статус для ${updateResult.rows.length} пользователей:`);
|
||||
updateResult.rows.forEach(row => {
|
||||
console.log(`ID: ${row.id.substr(0, 8)}... | Telegram ID: ${row.telegram_id} | Premium: ${row.premium}`);
|
||||
});
|
||||
|
||||
console.log('🎉 Все пользователи теперь имеют премиум-статус!');
|
||||
} catch (error) {
|
||||
console.error('❌ Ошибка при установке премиум-статуса:', error);
|
||||
} finally {
|
||||
await pool.end();
|
||||
console.log('Соединение с базой данных закрыто');
|
||||
}
|
||||
}
|
||||
|
||||
setAllUsersToPremium();
|
||||
Reference in New Issue
Block a user