Переделал нахуй всё
This commit is contained in:
74
databases/db_config.py
Normal file
74
databases/db_config.py
Normal file
@@ -0,0 +1,74 @@
|
||||
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from motor.motor_asyncio import AsyncIOMotorClient
|
||||
from databases.model import Base
|
||||
from utils.LogCon import setup_logger, load_config
|
||||
|
||||
# Загружаем конфигурацию
|
||||
config = load_config()
|
||||
|
||||
# Настройки PostgreSQL
|
||||
postgres_user = config['postgreSQL']['username']
|
||||
postgres_password = config['postgreSQL']['password_DB']
|
||||
postgres_host = "postgres" # Хост для PostgreSQL в Docker
|
||||
POSTGRES_DSN = f"postgresql+asyncpg://{postgres_user}:{postgres_password}@{postgres_host}:5432/bot_db"
|
||||
|
||||
# Создание движка для PostgreSQL
|
||||
postgres_engine = create_async_engine(POSTGRES_DSN, echo=False)
|
||||
AsyncSessionLocal = sessionmaker(bind=postgres_engine, class_=AsyncSession, expire_on_commit=False)
|
||||
|
||||
# Настройки MongoDB
|
||||
mongodb_user = config['mongodb']['mongodb_username']
|
||||
mongodb_password = config['mongodb']['mongodb_password']
|
||||
mongodb_host = "mongodb" # Хост для MongoDB в Docker
|
||||
mongodb_uri = f"mongodb://{mongodb_user}:{mongodb_password}@{mongodb_host}:27017"
|
||||
database_name = config['mongodb']['database_name']
|
||||
|
||||
# Создание клиента MongoDB
|
||||
mongo_client = AsyncIOMotorClient(mongodb_uri)
|
||||
mongo_db = mongo_client[database_name]
|
||||
|
||||
# Инициализация PostgreSQL
|
||||
async def init_postgresql():
|
||||
"""
|
||||
Инициализация подключения к PostgreSQL.
|
||||
"""
|
||||
try:
|
||||
async with postgres_engine.begin() as conn:
|
||||
await conn.run_sync(Base.metadata.create_all)
|
||||
print("PostgreSQL connected.")
|
||||
except Exception as e:
|
||||
print(f"Failed to connect to PostgreSQL: {e}")
|
||||
|
||||
# Инициализация MongoDB
|
||||
async def init_mongodb():
|
||||
"""
|
||||
Проверка подключения к MongoDB.
|
||||
"""
|
||||
try:
|
||||
# Проверяем подключение к MongoDB
|
||||
await mongo_client.admin.command("ping")
|
||||
print("MongoDB connected.")
|
||||
except Exception as e:
|
||||
print(f"Failed to connect to MongoDB: {e}")
|
||||
|
||||
# Получение сессии PostgreSQL
|
||||
async def get_postgres_session():
|
||||
"""
|
||||
Асинхронный генератор сессий PostgreSQL.
|
||||
"""
|
||||
async with AsyncSessionLocal() as session:
|
||||
yield session
|
||||
|
||||
# Закрытие соединений
|
||||
async def close_connections():
|
||||
"""
|
||||
Закрытие всех соединений с базами данных.
|
||||
"""
|
||||
# Закрытие PostgreSQL
|
||||
await postgres_engine.dispose()
|
||||
print("PostgreSQL connection closed.")
|
||||
|
||||
# Закрытие MongoDB
|
||||
mongo_client.close()
|
||||
print("MongoDB connection closed.")
|
||||
60
databases/model.py
Normal file
60
databases/model.py
Normal file
@@ -0,0 +1,60 @@
|
||||
from sqlalchemy import Column, String, Numeric, DateTime, Boolean, ForeignKey, Integer
|
||||
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
|
||||
from sqlalchemy.orm import declarative_base, relationship, sessionmaker
|
||||
from datetime import datetime
|
||||
import uuid
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
def generate_uuid():
|
||||
return str(uuid.uuid4())
|
||||
|
||||
"""Пользователи"""
|
||||
class User(Base):
|
||||
__tablename__ = 'users'
|
||||
|
||||
id = Column(String, primary_key=True, default=generate_uuid)
|
||||
telegram_id = Column(Integer, unique=True, nullable=False)
|
||||
username = Column(String)
|
||||
balance = Column(Numeric(10, 2), default=0.0)
|
||||
created_at = Column(DateTime, default=datetime.utcnow)
|
||||
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
subscriptions = relationship("Subscription", back_populates="user")
|
||||
transactions = relationship("Transaction", back_populates="user")
|
||||
admins = relationship("Administrators", back_populates="user")
|
||||
|
||||
"""Подписки"""
|
||||
class Subscription(Base):
|
||||
__tablename__ = 'subscriptions'
|
||||
|
||||
id = Column(String, primary_key=True, default=generate_uuid)
|
||||
user_id = Column(String, ForeignKey('users.id'))
|
||||
vpn_server_id = Column(String)
|
||||
plan = Column(String)
|
||||
expiry_date = Column(DateTime)
|
||||
created_at = Column(DateTime, default=datetime.utcnow)
|
||||
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
user = relationship("User", back_populates="subscriptions")
|
||||
|
||||
"""Транзакции"""
|
||||
class Transaction(Base):
|
||||
__tablename__ = 'transactions'
|
||||
|
||||
id = Column(String, primary_key=True, default=generate_uuid)
|
||||
user_id = Column(String, ForeignKey('users.id'))
|
||||
amount = Column(Numeric(10, 2))
|
||||
transaction_type = Column(String)
|
||||
created_at = Column(DateTime, default=datetime.utcnow)
|
||||
|
||||
user = relationship("User", back_populates="transactions")
|
||||
|
||||
"""Администраторы"""
|
||||
class Administrators(Base):
|
||||
__tablename__ = 'admins'
|
||||
|
||||
id = Column(String, primary_key=True, default=generate_uuid)
|
||||
user_id = Column(String, ForeignKey('users.id'))
|
||||
|
||||
user = relationship("User", back_populates="admins")
|
||||
53
databases/mongodb.py
Normal file
53
databases/mongodb.py
Normal file
@@ -0,0 +1,53 @@
|
||||
from pymongo import MongoClient
|
||||
from utils.LogCon import setup_logger, load_config
|
||||
|
||||
class MongoDBRepository:
|
||||
def __init__(self, config_path="config.json"):
|
||||
self.config = load_config()
|
||||
self.client = MongoClient(config["mongodb_uri"])
|
||||
self.db = self.client[config["database_name"]]
|
||||
self.collection = self.db["vpn_servers"]
|
||||
|
||||
def add_server(self, server_data):
|
||||
"""Добавляет новый VPN сервер в коллекцию."""
|
||||
result = self.collection.insert_one(server_data)
|
||||
print(f"VPN сервер добавлен с ID: {result.inserted_id}")
|
||||
return result.inserted_id
|
||||
|
||||
def get_server(self, server_id):
|
||||
"""Получает сервер VPN по его ID."""
|
||||
server = self.collection.find_one({"_id": server_id})
|
||||
if server:
|
||||
print(f"Найден VPN сервер: {server}")
|
||||
else:
|
||||
print(f"VPN сервер с ID {server_id} не найден.")
|
||||
return server
|
||||
|
||||
def update_server(self, server_id, update_data):
|
||||
"""Обновляет данные VPN сервера."""
|
||||
result = self.collection.update_one({"_id": server_id}, {"$set": update_data})
|
||||
if result.matched_count > 0:
|
||||
print(f"VPN сервер с ID {server_id} обновлен.")
|
||||
else:
|
||||
print(f"VPN сервер с ID {server_id} не найден.")
|
||||
return result.matched_count > 0
|
||||
|
||||
def delete_server(self, server_id):
|
||||
"""Удаляет VPN сервер по его ID."""
|
||||
result = self.collection.delete_one({"_id": server_id})
|
||||
if result.deleted_count > 0:
|
||||
print(f"VPN сервер с ID {server_id} удален.")
|
||||
else:
|
||||
print(f"VPN сервер с ID {server_id} не найден.")
|
||||
return result.deleted_count > 0
|
||||
|
||||
def list_servers(self):
|
||||
"""Возвращает список всех VPN серверов."""
|
||||
servers = list(self.collection.find())
|
||||
print(f"Найдено {len(servers)} VPN серверов.")
|
||||
return servers
|
||||
|
||||
def close_connection(self):
|
||||
"""Закрывает подключение к базе данных MongoDB."""
|
||||
self.client.close()
|
||||
print("Подключение к MongoDB закрыто.")
|
||||
105
databases/postgresql.py
Normal file
105
databases/postgresql.py
Normal file
@@ -0,0 +1,105 @@
|
||||
from databases.model import User, Subscription, Transaction, Administrators
|
||||
from sqlalchemy.future import select
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from sqlalchemy import desc
|
||||
import random
|
||||
import string
|
||||
import logging
|
||||
|
||||
|
||||
class DatabaseManager:
|
||||
def __init__(self, session_generator):
|
||||
"""
|
||||
Инициализация с асинхронным генератором сессий (например, get_postgres_session).
|
||||
"""
|
||||
self.session_generator = session_generator
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
async def create_user(self, telegram_id):
|
||||
"""
|
||||
Создаёт нового пользователя, если его нет.
|
||||
"""
|
||||
async for session in self.session_generator():
|
||||
try:
|
||||
username = self.generate_string(6)
|
||||
result = await session.execute(select(User).where(User.telegram_id == telegram_id))
|
||||
user = result.scalars().first()
|
||||
if not user:
|
||||
new_user = User(telegram_id=telegram_id, username=username)
|
||||
session.add(new_user)
|
||||
await session.commit()
|
||||
return new_user
|
||||
return user
|
||||
except SQLAlchemyError as e:
|
||||
self.logger.error(f"Ошибка при создании пользователя {telegram_id}: {e}")
|
||||
await session.rollback()
|
||||
return "ERROR"
|
||||
|
||||
|
||||
async def get_user_by_telegram_id(self, telegram_id: int):
|
||||
"""
|
||||
Возвращает пользователя по Telegram ID.
|
||||
"""
|
||||
async for session in self.session_generator():
|
||||
try:
|
||||
result = await session.execute(select(User).where(User.telegram_id == telegram_id))
|
||||
return result.scalars().first()
|
||||
except SQLAlchemyError as e:
|
||||
self.logger.error(f"Ошибка при получении пользователя {telegram_id}: {e}")
|
||||
return None
|
||||
|
||||
async def add_transaction(self, user_id: int, amount: float):
|
||||
"""
|
||||
Добавляет транзакцию для пользователя.
|
||||
"""
|
||||
async for session in self.session_generator():
|
||||
try:
|
||||
transaction = Transaction(user_id=user_id, amount=amount)
|
||||
session.add(transaction)
|
||||
await session.commit()
|
||||
except SQLAlchemyError as e:
|
||||
self.logger.error(f"Ошибка добавления транзакции для пользователя {user_id}: {e}")
|
||||
await session.rollback()
|
||||
|
||||
async def update_balance(self, telegram_id: int, amount: float):
|
||||
"""
|
||||
Обновляет баланс пользователя и добавляет транзакцию.
|
||||
"""
|
||||
async for session in self.session_generator():
|
||||
try:
|
||||
result = await session.execute(select(User).where(User.telegram_id == telegram_id))
|
||||
user = result.scalars().first()
|
||||
if user:
|
||||
user.balance = amount
|
||||
await self.add_transaction(user.id, amount)
|
||||
await session.commit()
|
||||
else:
|
||||
self.logger.warning(f"Пользователь с Telegram ID {telegram_id} не найден.")
|
||||
except SQLAlchemyError as e:
|
||||
self.logger.error(f"Ошибка при обновлении баланса: {e}")
|
||||
await session.rollback()
|
||||
|
||||
async def last_subscription(self, user_id: int):
|
||||
"""
|
||||
Возвращает последнюю подписку пользователя.
|
||||
"""
|
||||
async for session in self.session_generator():
|
||||
try:
|
||||
result = await session.execute(
|
||||
select(Subscription)
|
||||
.where(Subscription.user_id == user_id)
|
||||
.order_by(desc(Subscription.created_at))
|
||||
)
|
||||
print(result)
|
||||
return result.scalars().all()
|
||||
except SQLAlchemyError as e:
|
||||
self.logger.error(f"Ошибка при получении последней подписки пользователя {user_id}: {e}")
|
||||
return "ERROR"
|
||||
|
||||
@staticmethod
|
||||
def generate_string(length):
|
||||
"""
|
||||
Генерирует случайную строку заданной длины.
|
||||
"""
|
||||
characters = string.ascii_lowercase + string.digits
|
||||
return ''.join(random.choices(characters, k=length))
|
||||
Reference in New Issue
Block a user