diff --git a/assets/schema.sql b/assets/schema.sql
index bbed31cb..f3c1d063 100644
--- a/assets/schema.sql
+++ b/assets/schema.sql
@@ -1,16 +1,15 @@
-
-CREATE TABLE IF NOT EXISTS users
-(
+CREATE TABLE IF NOT EXISTS users (
tg_id BIGINT PRIMARY KEY NOT NULL,
username TEXT,
first_name TEXT,
last_name TEXT,
language_code TEXT,
- is_bot BOOLEAN DEFAULT FALSE,
+ is_bot BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
- balance REAL NOT NULL DEFAULT 0.0,
- trial INTEGER NOT NULL DEFAULT 0
+ balance REAL NOT NULL DEFAULT 0.0,
+ trial INTEGER NOT NULL DEFAULT 0,
+ source_code TEXT REFERENCES tracking_sources (code)
);
DO $$
@@ -28,44 +27,43 @@ BEGIN
) THEN
ALTER TABLE users ADD COLUMN trial INTEGER NOT NULL DEFAULT 0;
END IF;
+
+ IF NOT EXISTS (
+ SELECT 1 FROM information_schema.columns
+ WHERE table_name = 'users' AND column_name = 'source_code'
+ ) THEN
+ ALTER TABLE users ADD COLUMN source_code TEXT REFERENCES tracking_sources (code);
+ END IF;
END$$;
-
-CREATE TABLE IF NOT EXISTS payments
-(
+CREATE TABLE IF NOT EXISTS payments (
id SERIAL PRIMARY KEY,
tg_id BIGINT NOT NULL,
amount REAL NOT NULL,
payment_system TEXT NOT NULL,
- status TEXT DEFAULT 'success',
+ status TEXT DEFAULT 'success',
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (tg_id) REFERENCES users (tg_id)
);
-CREATE TABLE IF NOT EXISTS keys
-(
+CREATE TABLE IF NOT EXISTS keys (
tg_id BIGINT NOT NULL,
client_id TEXT NOT NULL,
email TEXT NOT NULL,
created_at BIGINT NOT NULL,
expiry_time BIGINT NOT NULL,
- key TEXT NOT NULL,
+ key TEXT,
server_id TEXT NOT NULL DEFAULT 'cluster1',
notified BOOLEAN NOT NULL DEFAULT FALSE,
notified_24h BOOLEAN NOT NULL DEFAULT FALSE,
+ remnawave_link TEXT,
+ is_frozen BOOLEAN DEFAULT FALSE,
+ alias TEXT,
PRIMARY KEY (tg_id, client_id)
);
DO $$
BEGIN
- IF EXISTS (
- SELECT 1
- FROM information_schema.columns
- WHERE table_name = 'keys' AND column_name = 'key' AND is_nullable = 'NO'
- ) THEN
- ALTER TABLE keys ALTER COLUMN key DROP NOT NULL;
- END IF;
-
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'keys' AND column_name = 'remnawave_link'
@@ -88,22 +86,20 @@ BEGIN
END IF;
END$$;
-CREATE TABLE IF NOT EXISTS referrals
-(
+CREATE TABLE IF NOT EXISTS referrals (
referred_tg_id BIGINT PRIMARY KEY NOT NULL,
- referrer_tg_id BIGINT NOT NULL,
+ referrer_tg_id BIGINT NOT NULL,
reward_issued BOOLEAN DEFAULT FALSE
);
-CREATE TABLE IF NOT EXISTS coupons
-(
+CREATE TABLE IF NOT EXISTS coupons (
id SERIAL PRIMARY KEY,
code TEXT UNIQUE NOT NULL,
- amount INTEGER NOT NULL,
+ amount INTEGER NOT NULL,
days INTEGER CHECK (days > 0 OR days IS NULL),
- usage_limit INTEGER NOT NULL DEFAULT 1,
- usage_count INTEGER NOT NULL DEFAULT 0,
- is_used BOOLEAN NOT NULL DEFAULT FALSE
+ usage_limit INTEGER NOT NULL DEFAULT 1,
+ usage_count INTEGER NOT NULL DEFAULT 0,
+ is_used BOOLEAN NOT NULL DEFAULT FALSE
);
DO $$
@@ -116,24 +112,21 @@ BEGIN
END IF;
END$$;
-CREATE TABLE IF NOT EXISTS coupon_usages
-(
- coupon_id INTEGER NOT NULL REFERENCES coupons (id) ON DELETE CASCADE,
- user_id BIGINT NOT NULL,
+CREATE TABLE IF NOT EXISTS coupon_usages (
+ coupon_id INTEGER NOT NULL REFERENCES coupons (id) ON DELETE CASCADE,
+ user_id BIGINT NOT NULL,
used_at TIMESTAMP NOT NULL DEFAULT NOW(),
PRIMARY KEY (coupon_id, user_id)
);
-CREATE TABLE IF NOT EXISTS notifications
-(
- tg_id BIGINT NOT NULL,
+CREATE TABLE IF NOT EXISTS notifications (
+ tg_id BIGINT NOT NULL,
last_notification_time TIMESTAMP NOT NULL DEFAULT NOW(),
- notification_type TEXT NOT NULL,
+ notification_type TEXT NOT NULL,
PRIMARY KEY (tg_id, notification_type)
);
-CREATE TABLE IF NOT EXISTS servers
-(
+CREATE TABLE IF NOT EXISTS servers (
id SERIAL PRIMARY KEY,
cluster_name TEXT NOT NULL,
server_name TEXT NOT NULL,
@@ -143,28 +136,19 @@ CREATE TABLE IF NOT EXISTS servers
panel_type TEXT NOT NULL DEFAULT '3x-ui',
enabled BOOLEAN NOT NULL DEFAULT TRUE,
max_keys INTEGER,
- UNIQUE (cluster_name, server_name)
+ tariff_group TEXT,
+ UNIQUE (cluster_name, server_name)
);
-ALTER TABLE servers ADD COLUMN IF NOT EXISTS panel_type TEXT NOT NULL DEFAULT '3x-ui';
- ALTER TABLE servers
- ALTER COLUMN subscription_url DROP NOT NULL;
- ALTER TABLE servers
- ADD COLUMN IF NOT EXISTS enabled BOOLEAN NOT NULL DEFAULT TRUE;
- ALTER TABLE servers ADD COLUMN IF NOT EXISTS max_keys INTEGER;
-
-CREATE TABLE IF NOT EXISTS gifts
-(
- gift_id TEXT PRIMARY KEY NOT NULL,
- sender_tg_id BIGINT NOT NULL,
- selected_months INTEGER NOT NULL,
- expiry_time TIMESTAMP WITH TIME ZONE NOT NULL,
- gift_link TEXT NOT NULL,
- created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
- is_used BOOLEAN NOT NULL DEFAULT FALSE,
- recipient_tg_id BIGINT,
- CONSTRAINT fk_sender FOREIGN KEY (sender_tg_id) REFERENCES users (tg_id),
- CONSTRAINT fk_recipient FOREIGN KEY (recipient_tg_id) REFERENCES users (tg_id)
+CREATE TABLE IF NOT EXISTS gifts (
+ gift_id TEXT PRIMARY KEY NOT NULL,
+ sender_tg_id BIGINT NOT NULL REFERENCES users (tg_id),
+ selected_months INTEGER NOT NULL,
+ expiry_time TIMESTAMP WITH TIME ZONE NOT NULL,
+ gift_link TEXT NOT NULL,
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
+ is_used BOOLEAN NOT NULL DEFAULT FALSE,
+ recipient_tg_id BIGINT REFERENCES users (tg_id)
);
CREATE TABLE IF NOT EXISTS temporary_data (
@@ -175,41 +159,42 @@ CREATE TABLE IF NOT EXISTS temporary_data (
);
CREATE TABLE IF NOT EXISTS blocked_users (
- tg_id BIGINT PRIMARY KEY,
- blocked_at TIMESTAMP DEFAULT NOW()
+ tg_id BIGINT PRIMARY KEY,
+ blocked_at TIMESTAMP DEFAULT NOW()
);
-
CREATE TABLE IF NOT EXISTS tracking_sources (
- id SERIAL PRIMARY KEY,
- code TEXT UNIQUE NOT NULL,
- type TEXT NOT NULL,
- name TEXT NOT NULL,
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
- created_by BIGINT,
- is_active BOOLEAN DEFAULT TRUE
+ id SERIAL PRIMARY KEY,
+ code TEXT UNIQUE NOT NULL,
+ type TEXT NOT NULL,
+ name TEXT NOT NULL,
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ created_by BIGINT,
+ is_active BOOLEAN DEFAULT TRUE
);
-
-ALTER TABLE users ADD COLUMN IF NOT EXISTS source_code TEXT REFERENCES tracking_sources (code);
-
CREATE TABLE IF NOT EXISTS tariffs (
- id SERIAL PRIMARY KEY,
- name TEXT NOT NULL,
- group_code TEXT NOT NULL,
- duration_days INTEGER NOT NULL CHECK (duration_days > 0),
- price_rub INTEGER NOT NULL CHECK (price_rub >= 0),
- traffic_limit BIGINT,
- device_limit INTEGER,
- is_active BOOLEAN NOT NULL DEFAULT TRUE,
- created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
- updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
+ id SERIAL PRIMARY KEY,
+ name TEXT NOT NULL,
+ group_code TEXT NOT NULL,
+ duration_days INTEGER NOT NULL CHECK (duration_days > 0),
+ price_rub INTEGER NOT NULL CHECK (price_rub >= 0),
+ traffic_limit BIGINT,
+ device_limit INTEGER,
+ is_active BOOLEAN NOT NULL DEFAULT TRUE,
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
+ updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-ALTER TABLE servers ADD COLUMN IF NOT EXISTS tariff_group TEXT;
-ALTER TABLE tariffs
-ADD COLUMN IF NOT EXISTS device_limit INTEGER;
-
+DO $$
+BEGIN
+ IF NOT EXISTS (
+ SELECT 1 FROM information_schema.columns
+ WHERE table_name = 'tariffs' AND column_name = 'device_limit'
+ ) THEN
+ ALTER TABLE tariffs ADD COLUMN device_limit INTEGER;
+ END IF;
+END$$;
DO $$
BEGIN
@@ -227,4 +212,4 @@ BEGIN
EXECUTE 'DROP TABLE connections';
END IF;
-END$$;
\ No newline at end of file
+END$$;
diff --git a/handlers/admin/clusters/clusters_handler.py b/handlers/admin/clusters/clusters_handler.py
index 36e5429d..70063fbf 100644
--- a/handlers/admin/clusters/clusters_handler.py
+++ b/handlers/admin/clusters/clusters_handler.py
@@ -242,10 +242,15 @@ async def handle_panel_type_selection(
inbound_id = user_data.get("inbound_id")
conn = await asyncpg.connect(DATABASE_URL)
+ tariff_group = await conn.fetchval(
+ "SELECT tariff_group FROM servers WHERE cluster_name = $1 LIMIT 1",
+ cluster_name,
+ )
+
await conn.execute(
"""
- INSERT INTO servers (cluster_name, server_name, api_url, subscription_url, inbound_id, panel_type)
- VALUES ($1, $2, $3, $4, $5, $6)
+ INSERT INTO servers (cluster_name, server_name, api_url, subscription_url, inbound_id, panel_type, tariff_group)
+ VALUES ($1, $2, $3, $4, $5, $6, $7)
""",
cluster_name,
server_name,
@@ -253,7 +258,9 @@ async def handle_panel_type_selection(
subscription_url,
inbound_id,
panel_type,
+ tariff_group,
)
+
await conn.close()
await callback_query.message.edit_text(
@@ -269,8 +276,20 @@ async def handle_clusters_manage(
):
cluster_name = callback_data.data
+ row = await session.fetchrow(
+ "SELECT tariff_group FROM servers WHERE cluster_name = $1 AND tariff_group IS NOT NULL LIMIT 1",
+ cluster_name,
+ )
+
+ tariff_group = row["tariff_group"] if row else "—"
+
+ text = (
+ f"🔧 Управление кластером {cluster_name}\n\n"
+ f"📁 Тарифная группа: {tariff_group}\n"
+ )
+
await callback_query.message.edit_text(
- text=f"🔧 Управление кластером {cluster_name}",
+ text=text,
reply_markup=build_cluster_management_kb(cluster_name),
)