diff --git a/app/routes/subscription_routes.py b/app/routes/subscription_routes.py index 2d4ce72..6147201 100644 --- a/app/routes/subscription_routes.py +++ b/app/routes/subscription_routes.py @@ -147,6 +147,8 @@ async def get_subscriptions(telegram_id: int, database_manager: DatabaseManager } for sub in subscriptions ] + except HTTPException as e: + raise e except SQLAlchemyError as e: logger.error(f"Ошибка базы данных при получении подписок для пользователя {telegram_id}: {e}") raise HTTPException(status_code=500, detail="Database error") diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/add.py b/tests/add.py deleted file mode 100644 index cc22b76..0000000 --- a/tests/add.py +++ /dev/null @@ -1,128 +0,0 @@ -import argparse -from datetime import datetime -import json -import base64 -from pymongo import MongoClient - -def connect_to_mongo(uri, db_name): - """Подключение к MongoDB.""" - client = MongoClient(uri) - db = client[db_name] - return db - -def load_raw_json(json_path): - """Загружает сырые JSON-данные из файла.""" - with open(json_path, "r", encoding="utf-8") as f: - return json.loads(f.read()) - -def encode_file(file_path): - """Читает файл и кодирует его в Base64.""" - with open(file_path, "rb") as f: - return base64.b64encode(f.read()).decode("utf-8") - -def transform_data(raw_data): - """Преобразует исходные сырые данные в целевую структуру.""" - try: - settings = json.loads(raw_data["obj"]["settings"]) - stream_settings = json.loads(raw_data["obj"]["streamSettings"]) - sniffing_settings = json.loads(raw_data["obj"]["sniffing"]) - - transformed = { - "server": { - "name": raw_data["obj"].get("remark", "Unknown"), - "ip": "45.82.255.110", # Замените на актуальные данные - "port": "2053", - "secretKey": "Hd8OsqN5Jh", # Замените на актуальные данные - "login": "nc1450nP", # Замените на актуальные данные - "password": "KmajQOuf" # Замените на актуальные данные - }, - "clients": [ - { - "email": client["email"], - "inboundId": raw_data["obj"].get("id"), - "id": client["id"], - "flow": client.get("flow", ""), - "limits": { - "ipLimit": client.get("limitIp", 0), - "reset": client.get("reset", 0), - "totalGB": client.get("totalGB", 0) - }, - "subscriptions": { - "subId": client.get("subId", ""), - "tgId": client.get("tgId", "") - } - } for client in settings["clients"] - ], - "connection": { - "destination": stream_settings["realitySettings"].get("dest", ""), - "serverNames": stream_settings["realitySettings"].get("serverNames", []), - "security": stream_settings.get("security", ""), - "publicKey": stream_settings["realitySettings"]["settings"].get("publicKey", ""), - "fingerprint": stream_settings["realitySettings"]["settings"].get("fingerprint", ""), - "shortIds": stream_settings["realitySettings"].get("shortIds", []), - "tcpSettings": { - "acceptProxyProtocol": stream_settings["tcpSettings"].get("acceptProxyProtocol", False), - "headerType": stream_settings["tcpSettings"]["header"].get("type", "none") - }, - "sniffing": { - "enabled": sniffing_settings.get("enabled", False), - "destOverride": sniffing_settings.get("destOverride", []) - } - } - } - return transformed - except KeyError as e: - raise ValueError(f"Ошибка преобразования данных: отсутствует ключ {e}") - -def insert_certificate(data, cert_path, cert_location): - """Добавляет сертификат в указанное место внутри структуры JSON.""" - # Читаем и кодируем сертификат - certificate_data = encode_file(cert_path) - - # Разбиваем путь на вложенные ключи - keys = cert_location.split(".") - target = data - for key in keys[:-1]: - if key not in target: - target[key] = {} # Создаем вложенные ключи, если их нет - target = target[key] - target[keys[-1]] = { - "data": certificate_data, - "uploaded_at": datetime.utcnow() - } - -def insert_data(db, collection_name, data): - """Вставляет данные в указанную коллекцию MongoDB.""" - collection = db[collection_name] - collection.insert_one(data) - print(f"Данные успешно вставлены в коллекцию '{collection_name}'.") - -def main(): - parser = argparse.ArgumentParser(description="Insert raw JSON data into MongoDB with certificate") - parser.add_argument("--mongo-uri", default="mongodb://root:itOj4CE2miKR@mongodb:27017", help="MongoDB URI") - parser.add_argument("--db-name", default="MongoDBSub&Ser", help="MongoDB database name") - parser.add_argument("--collection", default="servers", help="Collection name") - parser.add_argument("--json-path", required=True, help="Path to the JSON file with raw data") - parser.add_argument("--cert-path", help="Path to the certificate file (.crt)") - parser.add_argument("--cert-location", default='server.certificate', help="Path inside JSON structure to store certificate (e.g., 'server.certificate')") - - args = parser.parse_args() - - # Подключение к MongoDB - db = connect_to_mongo(args.mongo_uri, args.db_name) - - # Загрузка сырых данных из JSON-файла - raw_data = load_raw_json(args.json_path) - - # Преобразование данных в нужную структуру - transformed_data = transform_data(raw_data) - - # Вставка сертификата в структуру данных (если путь к сертификату указан) - if args.cert_path: - insert_certificate(transformed_data, args.cert_path, args.cert_location) - - # Вставка данных в MongoDB - insert_data(db, args.collection, transformed_data) - -if __name__ == "__main__": - main() diff --git a/tests/add2.py b/tests/add2.py deleted file mode 100644 index 97acd8a..0000000 --- a/tests/add2.py +++ /dev/null @@ -1,74 +0,0 @@ -import argparse -from datetime import datetime -import json -import glob -from pymongo import MongoClient - -def connect_to_mongo(uri, db_name): - """Подключение к MongoDB.""" - client = MongoClient(uri) - db = client[db_name] - return db - -def load_all_json_from_folder(folder_path): - """Загружает все JSON-файлы из указанной папки.""" - all_data = [] - for file_path in glob.glob(f"{folder_path}/*.json"): - try: - with open(file_path, "r", encoding="utf-8") as f: - data = json.load(f) - all_data.append(data) - except Exception as e: - print(f"Ошибка при чтении файла {file_path}: {e}") - return all_data - - -def fetch_all_documents(mongo_uri, db_name, collection_name): - """Выводит все элементы из указанной коллекции MongoDB.""" - try: - client = MongoClient(mongo_uri) - db = client[db_name] - collection = db[collection_name] - - documents = collection.find() - - print(f"Содержимое коллекции '{collection_name}':") - for doc in documents: - print(doc) - - except Exception as e: - print(f"Ошибка при получении данных: {e}") - finally: - client.close() - -def insert_data(db, collection_name, data): - """Вставляет данные в указанную коллекцию MongoDB.""" - collection = db[collection_name] - for i in data: - collection.insert_one(i) - print(f"Данные '{i}'") - print(f"Данные успешно вставлены в коллекцию '{collection_name}'.") - - - -def main(): - parser = argparse.ArgumentParser(description="Insert JSON data into MongoDB with certificate") - parser.add_argument("--mongo-uri",default="mongodb://root:itOj4CE2miKR@mongodb:27017" ,required=True, help="MongoDB URI") - parser.add_argument("--db-name",default="MongoDBSub&Ser" ,required=True, help="MongoDB database name") - parser.add_argument("--collection",default="plans", required=True, help="Collection name") - parser.add_argument("--json-path", required=True, help="Path to the JSON file with data") - - - args = parser.parse_args() - - db = connect_to_mongo(args.mongo_uri, args.db_name) - - data = load_all_json_from_folder(args.json_path) - - insert_data(db, args.collection, data) - - fetch_all_documents(args.mongo_uri, args.db_name,args.collection) - -if __name__ == "__main__": - main() - diff --git a/tests/add_plans.py b/tests/add_plans.py new file mode 100644 index 0000000..815f24f --- /dev/null +++ b/tests/add_plans.py @@ -0,0 +1,270 @@ +#!/usr/bin/env python3 +""" +Автономный скрипт для инициализации тарифных планов в PostgreSQL. +Использует данные подключения из docker-compose.yml +""" + +import asyncio +import argparse +import sys +from typing import List, Dict +from sqlalchemy import Column, Integer, String, Numeric, Text, delete, insert +from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker +from sqlalchemy.orm import declarative_base +from decimal import Decimal + +Base = declarative_base() + + +class Plan(Base): + """Модель тарифного плана""" + __tablename__ = 'plans' + + id = Column(Integer, primary_key=True) + name = Column(String(100), nullable=False) + price = Column(Numeric(10, 2), nullable=False) + duration_days = Column(Integer, nullable=False) + description = Column(Text, nullable=True) + + +# Данные из вашего docker-compose.yml +DEFAULT_CONFIG = { + 'host': 'localhost', + 'port': 5432, + 'database': 'postgresql', + 'user': 'AH3J9GSPBYOP', + 'password': 'uPS9?y~mcu2', + 'url': 'postgresql+asyncpg://AH3J9GSPBYOP:uPS9?y~mcu2@localhost:5432/postgresql' +} + + +PLANS_DATA = [ + {'name': 'Lark_Standart_1', 'price': Decimal('200.00'), 'duration_days': 30}, + {'name': 'Lark_Pro_1', 'price': Decimal('400.00'), 'duration_days': 30}, + {'name': 'Lark_Family_1', 'price': Decimal('700.00'), 'duration_days': 30}, + {'name': 'Lark_Standart_6', 'price': Decimal('1200.00'), 'duration_days': 180}, + {'name': 'Lark_Standart_12', 'price': Decimal('2400.00'), 'duration_days': 360}, + {'name': 'Lark_Pro_6', 'price': Decimal('2000.00'), 'duration_days': 180}, + {'name': 'Lark_Pro_12', 'price': Decimal('4800.00'), 'duration_days': 360}, + {'name': 'Lark_Family_6', 'price': Decimal('4200.00'), 'duration_days': 180}, + {'name': 'Lark_Family_12', 'price': Decimal('8400.00'), 'duration_days': 360}, +] + + +def print_banner(): + """Печатает баннер скрипта""" + print("=" * 60) + print("🚀 ИНИЦИАЛИЗАЦИЯ ТАРИФНЫХ ПЛАНОВ В БАЗЕ ДАННЫХ") + print("=" * 60) + print() + + +def create_db_url(config: dict) -> str: + """Создает URL для подключения к базе данных""" + if config.get('url'): + return config['url'] + + return f"postgresql+asyncpg://{config['user']}:{config['password']}@{config['host']}:{config['port']}/{config['database']}" + + +async def check_connection(engine) -> bool: + """Проверяет подключение к базе данных""" + try: + async with engine.connect() as conn: + result = await conn.execute("SELECT version()") + version = result.scalar() + print(f"✅ Подключено к PostgreSQL: {version.split(',')[0]}") + return True + except Exception as e: + print(f"❌ Ошибка подключения к базе данных: {e}") + return False + + +async def get_existing_plans(session) -> List: + """Получает существующие тарифные планы""" + result = await session.execute( + "SELECT id, name, price, duration_days FROM plans ORDER BY price" + ) + return result.fetchall() + + +async def clear_table(session, table_name: str = 'plans') -> bool: + """Очищает указанную таблицу""" + try: + await session.execute(delete(Plan)) + await session.commit() + print(f"✅ Таблица '{table_name}' очищена") + return True + except Exception as e: + print(f"❌ Ошибка при очистке таблицы: {e}") + await session.rollback() + return False + + +async def add_plans_to_db(session, plans_data: List[Dict]) -> int: + """Добавляет тарифные планы в базу данных""" + try: + added_count = 0 + for plan in plans_data: + await session.execute( + insert(Plan).values(**plan) + ) + added_count += 1 + + await session.commit() + return added_count + except Exception as e: + await session.rollback() + raise e + + +async def print_plans_table(plans: List) -> None: + """Выводит таблицу с тарифными планами""" + if not plans: + print("📭 Таблица 'plans' пуста") + return + + print(f"\n📊 Текущие тарифные планы ({len(plans)} шт.):") + print("-" * 70) + print(f"{'ID':<5} {'Название':<25} {'Цена (руб.)':<15} {'Дней':<10}") + print("-" * 70) + + for plan in plans: + print(f"{plan[0]:<5} {plan[1]:<25} {plan[2]:<15} {plan[3]:<10}") + + print("-" * 70) + + # Подсчет статистики + total_price = sum(float(p[2]) for p in plans) + avg_price = total_price / len(plans) if plans else 0 + + print(f"💰 Общая сумма всех тарифов: {total_price:.2f} руб.") + print(f"📈 Средняя цена тарифа: {avg_price:.2f} руб.") + print(f"📅 Всего предложений: {len(plans)}") + + +async def main(config: dict, clear_existing: bool = True, dry_run: bool = False): + """Основная функция скрипта""" + + print_banner() + + # Создаем URL для подключения + db_url = create_db_url(config) + print(f"📡 Параметры подключения:") + print(f" Хост: {config['host']}:{config['port']}") + print(f" База данных: {config['database']}") + print(f" Пользователь: {config['user']}") + print(f" {'🚨 РЕЖИМ ТЕСТА (dry-run)' if dry_run else ''}") + print() + + try: + # Подключаемся к базе данных + print("🔄 Подключение к базе данных...") + engine = create_async_engine(db_url, echo=False) + + # Проверяем подключение + if not await check_connection(engine): + print("\n❌ Не удалось подключиться к базе данных") + return False + + # Создаем фабрику сессий + AsyncSessionLocal = async_sessionmaker( + engine, class_=AsyncSession, expire_on_commit=False + ) + + async with AsyncSessionLocal() as session: + # Получаем текущие тарифы + print("\n🔍 Проверяем существующие тарифы...") + existing_plans = await get_existing_plans(session) + + if existing_plans: + await print_plans_table(existing_plans) + + if clear_existing and not dry_run: + print("\n⚠️ ВНИМАНИЕ: Будут удалены все существующие тарифы!") + confirm = input("Продолжить? (y/N): ") + if confirm.lower() != 'y': + print("❌ Операция отменена пользователем") + return False + + # Очищаем таблицу + await clear_table(session) + elif dry_run: + print("\n⚠️ DRY-RUN: Существующие тарифы НЕ будут удалены") + else: + print("📭 Таблица 'plans' пуста, создаем новые тарифы...") + + # Добавляем новые тарифы + if not dry_run: + print(f"\n➕ Добавляем {len(PLANS_DATA)} тарифных планов...") + added_count = await add_plans_to_db(session, PLANS_DATA) + print(f"✅ Успешно добавлено {added_count} тарифов") + else: + print(f"\n⚠️ DRY-RUN: Планируется добавить {len(PLANS_DATA)} тарифов:") + for i, plan in enumerate(PLANS_DATA, 1): + print(f" {i}. {plan['name']} - {plan['price']} руб. ({plan['duration_days']} дней)") + + # Показываем финальный результат + print("\n🎯 ФИНАЛЬНЫЙ РЕЗУЛЬТАТ:") + final_plans = await get_existing_plans(session) + await print_plans_table(final_plans) + + await engine.dispose() + print("\n✅ Скрипт успешно выполнен!") + return True + + except Exception as e: + print(f"\n❌ Критическая ошибка: {e}") + import traceback + traceback.print_exc() + return False + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description='Инициализация тарифных планов в базе данных', + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Примеры использования: + %(prog)s # Использует настройки по умолчанию + %(prog)s --no-clear # Не очищать существующие тарифы + %(prog)s --dry-run # Только показать что будет сделано + %(prog)s --host 192.168.1.100 # Указать другой хост + %(prog)s --url "postgresql://..." # Указать полный URL + """ + ) + + parser.add_argument('--host', help='Хост базы данных', default=DEFAULT_CONFIG['host']) + parser.add_argument('--port', type=int, help='Порт базы данных', default=DEFAULT_CONFIG['port']) + parser.add_argument('--database', help='Имя базы данных', default=DEFAULT_CONFIG['database']) + parser.add_argument('--user', help='Имя пользователя', default=DEFAULT_CONFIG['user']) + parser.add_argument('--password', help='Пароль', default=DEFAULT_CONFIG['password']) + parser.add_argument('--url', help='Полный URL подключения (игнорирует остальные параметры)') + parser.add_argument('--no-clear', action='store_true', help='Не очищать существующие тарифы') + parser.add_argument('--dry-run', action='store_true', help='Только показать что будет сделано') + + args = parser.parse_args() + + # Формируем конфигурацию + config = DEFAULT_CONFIG.copy() + + if args.url: + config['url'] = args.url + else: + config.update({ + 'host': args.host, + 'port': args.port, + 'database': args.database, + 'user': args.user, + 'password': args.password, + 'url': None # Будет сгенерирован автоматически + }) + + # Запускаем скрипт + success = asyncio.run(main( + config=config, + clear_existing=not args.no_clear, + dry_run=args.dry_run + )) + + sys.exit(0 if success else 1) \ No newline at end of file diff --git a/tests/ca.crt b/tests/ca.crt deleted file mode 100644 index 0a23664..0000000 --- a/tests/ca.crt +++ /dev/null @@ -1,26 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIEYzCCA0ugAwIBAgIUEni/Go2t3/FXT7CGBMSnrlDzTKwwDQYJKoZIhvcNAQEL -BQAwgcAxCzAJBgNVBAYTAlVBMRswGQYDVQQIDBJSZXB1YmxpYyBvZiBDcmltZWEx -EzARBgNVBAcMClNpbWZlcm9wb2wxFzAVBgNVBAoMDkxhcmsgQ28gU3lzdGVtMSUw -IwYDVQQLDBxMYXJrIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRgwFgYDVQQDDA9M -YXJrIFRydXN0ZWQgQ0ExJTAjBgkqhkiG9w0BCQEWFmxhcmtjb3N5c3RlbUBwcm90 -b24ubWUwHhcNMjQxMjI3MTQ1NzQ2WhcNMzQxMjI1MTQ1NzQ2WjCBwDELMAkGA1UE -BhMCVUExGzAZBgNVBAgMElJlcHVibGljIG9mIENyaW1lYTETMBEGA1UEBwwKU2lt -ZmVyb3BvbDEXMBUGA1UECgwOTGFyayBDbyBTeXN0ZW0xJTAjBgNVBAsMHExhcmsg -Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGDAWBgNVBAMMD0xhcmsgVHJ1c3RlZCBD -QTElMCMGCSqGSIb3DQEJARYWbGFya2Nvc3lzdGVtQHByb3Rvbi5tZTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBAOzb2ibfe4Arrf5O3d15kObBJQkxcSGi -fzrtYj68/y0ZyNV3BTvp+gCdlmo+WqOrdgD4LCOod0585S2MLCxjvVIcuA+DIq6z -gxZvf6V1FRKjHO3s18HhUX6nl8LYe6bOveqHAiDf9TZ+8grJXYpGD2tybAofXkL5 -8dmn5Jh10DTV2EBHwutET2hoBqSorop/Ro/zawYPOlMZuGXP4Txs/erUmNCzGm+b -AYw6qjBm+o9RG2AWzKVBI06/kFKA5vq7ATcEs2U5bdINy/U1u2vc1R08YuvTpPCh -2Q0uBn49T+WhiF9CpAYBoMj51Am22NqKWsc617ZFkl1OO3mWd4+mgocCAwEAAaNT -MFEwHQYDVR0OBBYEFAXCcmOWdaInuJLeY/5CRfdzb49+MB8GA1UdIwQYMBaAFAXC -cmOWdaInuJLeY/5CRfdzb49+MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL -BQADggEBADoyGv2Gdem/zrHCEy43WlXo9uFqKCX/Z/Rlr+V9OmRodZx83j2B0xIB -QdjuEP/EaxEtuGL98TIln7u8PX/FKApbZAk9zxrn0JNQ6bAVpsLBK1i+w3aw2XlN -p6qmFoc66Z8B1OUiGHrWczw0cV4rr8XoGwD5KS/jXYyuT+JTFBdsYXmUXqwqcwHY -N4qXRKh8FtqTgvjb/TpETMr7bnEHkn0vUwMwKwRe4TB1VwFIAaJeh7DPnrchy5xQ -EpS2DIQoO+ZoOaQYIkFT/8c7zpN79fy5uuVfW4XL8OS7sbZkzsl2YJDtO5zCEDNx -CJeEKQYXpCXRi+n3RvsIedshrnmqZcg= ------END CERTIFICATE----- diff --git a/tests/ser.json b/tests/ser.json deleted file mode 100644 index c1422a3..0000000 --- a/tests/ser.json +++ /dev/null @@ -1 +0,0 @@ -{"success":true,"msg":"","obj":{"id":1,"up":301130896430,"down":4057274949955,"total":0,"remark":"vlv","enable":true,"expiryTime":0,"clientStats":null,"listen":"","port":443,"protocol":"vless","settings":"{\n \"clients\": [\n {\n \"email\": \"j8oajwd3\",\n \"enable\": true,\n \"expiryTime\": 0,\n \"flow\": \"xtls-rprx-vision\",\n \"id\": \"a31d71a4-6afd-4f36-96f6-860691b52873\",\n \"limitIp\": 2,\n \"reset\": 0,\n \"subId\": \"ox2awiqwduryuqnz\",\n \"tgId\": 1342351277,\n \"totalGB\": 0\n },\n {\n \"email\": \"cvvbqpm2\",\n \"enable\": true,\n \"expiryTime\": 0,\n \"flow\": \"xtls-rprx-vision\",\n \"id\": \"b6882942-d69d-4d5e-be9a-168ac89b20b6\",\n \"limitIp\": 1,\n \"reset\": 0,\n \"subId\": \"jk289x00uf7vbr9x\",\n \"tgId\": 123144325,\n \"totalGB\": 0\n },\n {\n \"email\": \"k15vx82w\",\n \"enable\": true,\n \"expiryTime\": 0,\n \"flow\": \"\",\n \"id\": \"3c88e5bb-53ba-443d-9d68-a09f5037030c\",\n \"limitIp\": 0,\n \"reset\": 0,\n \"subId\": \"5ffz56ofveepep1t\",\n \"tgId\": 5364765066,\n \"totalGB\": 0\n },\n {\n \"email\": \"gm5x10tr\",\n \"enable\": true,\n \"expiryTime\": 0,\n \"flow\": \"xtls-rprx-vision\",\n \"id\": \"c0b9ff6c-4c48-4d75-8ca0-c13a2686fa5d\",\n \"limitIp\": 0,\n \"reset\": 0,\n \"subId\": \"132pioffqi6gwhw6\",\n \"tgId\": \"\",\n \"totalGB\": 0\n }\n ],\n \"decryption\": \"none\",\n \"fallbacks\": []\n}","streamSettings":"{\n \"network\": \"tcp\",\n \"security\": \"reality\",\n \"externalProxy\": [],\n \"realitySettings\": {\n \"show\": false,\n \"xver\": 0,\n \"dest\": \"google.com:443\",\n \"serverNames\": [\n \"google.com\",\n \"www.google.com\"\n ],\n \"privateKey\": \"gKsDFmRn0vyLMUdYdk0ZU_LVyrQh7zMl4r-9s0nNFCk\",\n \"minClient\": \"\",\n \"maxClient\": \"\",\n \"maxTimediff\": 0,\n \"shortIds\": [\n \"edfaf8ab\"\n ],\n \"settings\": {\n \"publicKey\": \"Bha0eW7nfRc69CdZyF9HlmGVvtAeOJKammhwf4WShTU\",\n \"fingerprint\": \"random\",\n \"serverName\": \"\",\n \"spiderX\": \"/\"\n }\n },\n \"tcpSettings\": {\n \"acceptProxyProtocol\": false,\n \"header\": {\n \"type\": \"none\"\n }\n }\n}","tag":"inbound-443","sniffing":"{\n \"enabled\": true,\n \"destOverride\": [\n \"http\",\n \"tls\",\n \"quic\",\n \"fakedns\"\n ],\n \"metadataOnly\": false,\n \"routeOnly\": false\n}"}} \ No newline at end of file diff --git a/tests/subs/sub1.json b/tests/subs/sub1.json deleted file mode 100644 index f8e7a72..0000000 --- a/tests/subs/sub1.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "Lark_Standart_1", - "normalName": "Lark Standart", - "type": "standart", - "duration_months": 1, - "ip_limit": 1, - "price": 200 - } \ No newline at end of file diff --git a/tests/subs/sub2.json b/tests/subs/sub2.json deleted file mode 100644 index 98a4b61..0000000 --- a/tests/subs/sub2.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "Lark_Standart_6", - "normalName": "Lark Standart", - "type": "standart", - "duration_months": 6, - "ip_limit": 1, - "price": 1000 -} \ No newline at end of file diff --git a/tests/subs/sub3.json b/tests/subs/sub3.json deleted file mode 100644 index 2e0b277..0000000 --- a/tests/subs/sub3.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "Lark_Standart_12", - "normalName": "Lark Standart", - "type": "standart", - "duration_months": 12, - "ip_limit": 1, - "price": 2000 - } \ No newline at end of file diff --git a/tests/subs/sub4.json b/tests/subs/sub4.json deleted file mode 100644 index fa67c74..0000000 --- a/tests/subs/sub4.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "Lark_Pro_1", - "normalName": "Lark Pro", - "type": "pro", - "duration_months": 1, - "ip_limit": 5, - "price": 600 - } \ No newline at end of file diff --git a/tests/subs/sub5.json b/tests/subs/sub5.json deleted file mode 100644 index 3fb1251..0000000 --- a/tests/subs/sub5.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "Lark_Pro_6", - "normalName": "Lark Pro", - "type": "pro", - "duration_months": 6, - "ip_limit": 5, - "price": 3000 - } \ No newline at end of file diff --git a/tests/subs/sub6.json b/tests/subs/sub6.json deleted file mode 100644 index 2f24325..0000000 --- a/tests/subs/sub6.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "Lark_Pro_12", - "normalName": "Lark Pro", - "type": "pro", - "duration_months": 12, - "ip_limit": 5, - "price": 5000 - } \ No newline at end of file diff --git a/tests/test_auth.py b/tests/test_auth.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/test_users.py b/tests/test_users.py deleted file mode 100644 index e69de29..0000000