Этот коммит содержится в:
stevefoxru
2025-04-28 16:34:38 +03:00
коммит произвёл GitHub
родитель ab4e5c5c96
Коммит d74e4f8286
+33 -117
Просмотреть файл
@@ -1,4 +1,3 @@
import configparser
import json import json
import os import os
import subprocess import subprocess
@@ -10,12 +9,10 @@ import shutil
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
BASE_DIR = "/root/amnezia-bot/awg" CONFIG_FILE = 'files/config.json'
CONFIG_FILE = os.path.join(BASE_DIR, "files", "setting.ini") USER_EXPIRATION_FILE = 'files/user_expiration.json'
USER_EXPIRATION_FILE = os.path.join(BASE_DIR, "files", "user_expiration.json") USER_TELEGRAM_FILE = 'files/user_telegram.json'
USER_TELEGRAM_FILE = os.path.join(BASE_DIR, "files", "user_telegram.json") PROMOCODES_FILE = 'files/promocodes.json'
PROMOCODES_FILE = os.path.join(BASE_DIR, "files", "promocodes.json")
PAYMENTS_FILE = os.path.join(BASE_DIR, "files", "payments.json")
def load_json(file_path, default=None): def load_json(file_path, default=None):
"""Загружает JSON-файл, возвращает default при ошибке или отсутствии файла.""" """Загружает JSON-файл, возвращает default при ошибке или отсутствии файла."""
@@ -39,94 +36,42 @@ def save_json(file_path, data):
return False return False
def get_config(): def get_config():
"""Возвращает конфигурацию из setting.ini.""" """Возвращает конфигурацию из config.json."""
config = configparser.ConfigParser() return load_json(CONFIG_FILE, {})
try:
config.read(CONFIG_FILE)
if 'Settings' not in config:
logger.error(f"Секция [Settings] не найдена в {CONFIG_FILE}")
return {}
settings = dict(config['Settings'])
# Преобразование pricing из JSON-строки в словарь
if 'pricing' in settings:
try:
settings['pricing'] = json.loads(settings['pricing'])
except json.JSONDecodeError:
logger.error("Ошибка парсинга pricing в setting.ini")
settings['pricing'] = {}
return settings
except Exception as e:
logger.error(f"Ошибка чтения {CONFIG_FILE}: {str(e)}")
return {}
def add_admin(admin_id): def add_admin(admin_id):
"""Добавляет ID администратора в конфигурацию.""" """Добавляет ID администратора в конфигурацию."""
config = get_config() config = get_config()
admin_ids = config.get('admin_ids', '').split(',') if config.get('admin_ids') else [] admin_ids = config.get('admin_ids', [])
admin_id_str = str(admin_id) if str(admin_id) not in admin_ids:
if admin_id_str not in admin_ids: admin_ids.append(str(admin_id))
admin_ids.append(admin_id_str) config['admin_ids'] = admin_ids
config['admin_ids'] = ','.join([aid for aid in admin_ids if aid]) save_json(CONFIG_FILE, config)
config_parser = configparser.ConfigParser()
config_parser['Settings'] = config
try:
with open(CONFIG_FILE, 'w') as configfile:
config_parser.write(configfile)
except Exception as e:
logger.error(f"Ошибка сохранения admin_ids в {CONFIG_FILE}: {str(e)}")
def remove_admin(admin_id): def remove_admin(admin_id):
"""Удаляет ID администратора из конфигурации.""" """Удаляет ID администратора из конфигурации."""
config = get_config() config = get_config()
admin_ids = config.get('admin_ids', '').split(',') if config.get('admin_ids') else [] admin_ids = config.get('admin_ids', [])
admin_id_str = str(admin_id) admin_id_str = str(admin_id)
if admin_id_str in admin_ids: if admin_id_str in admin_ids:
admin_ids.remove(admin_id_str) admin_ids.remove(admin_id_str)
config['admin_ids'] = ','.join([aid for aid in admin_ids if aid]) config['admin_ids'] = admin_ids
config_parser = configparser.ConfigParser() save_json(CONFIG_FILE, config)
config_parser['Settings'] = config
try:
with open(CONFIG_FILE, 'w') as configfile:
config_parser.write(configfile)
except Exception as e:
logger.error(f"Ошибка сохранения admin_ids в {CONFIG_FILE}: {str(e)}")
def set_yoomoney_config(token=None, wallet=None):
"""Обновляет настройки YooMoney в конфигурации."""
config = get_config()
if token:
config['yoomoney_token'] = token
if wallet:
config['yoomoney_wallet'] = wallet
config_parser = configparser.ConfigParser()
config_parser['Settings'] = config
try:
with open(CONFIG_FILE, 'w') as configfile:
config_parser.write(configfile)
except Exception as e:
logger.error(f"Ошибка сохранения YooMoney настроек в {CONFIG_FILE}: {str(e)}")
def set_pricing(period, price): def set_pricing(period, price):
"""Устанавливает цену для указанного периода подписки.""" """Устанавливает цену для указанного периода подписки."""
config = get_config() config = get_config()
pricing = config.get('pricing', {}) config['pricing'] = config.get('pricing', {})
pricing[period] = float(price) config['pricing'][period] = price
config['pricing'] = json.dumps(pricing) # Сохраняем как JSON-строку save_json(CONFIG_FILE, config)
config_parser = configparser.ConfigParser()
config_parser['Settings'] = config
try:
with open(CONFIG_FILE, 'w') as configfile:
config_parser.write(configfile)
except Exception as e:
logger.error(f"Ошибка сохранения pricing в {CONFIG_FILE}: {str(e)}")
def root_add(name, ipv6=False): def root_add(name, ipv6=False):
"""Добавляет нового пользователя через newclient.sh.""" """Добавляет нового пользователя через newclient.sh."""
try: try:
cmd = [os.path.join(BASE_DIR, 'newclient.sh'), name] cmd = ['./newclient.sh', name]
if not ipv6: if not ipv6:
cmd.append('--no-ipv6') cmd.append('--no-ipv6')
process = subprocess.run(cmd, capture_output=True, text=True, cwd=BASE_DIR) process = subprocess.run(cmd, capture_output=True, text=True)
if process.returncode == 0: if process.returncode == 0:
return True return True
logger.error(f"Ошибка добавления пользователя {name}: {process.stderr}") logger.error(f"Ошибка добавления пользователя {name}: {process.stderr}")
@@ -138,7 +83,7 @@ def root_add(name, ipv6=False):
def deactive_user_db(name): def deactive_user_db(name):
"""Деактивирует пользователя через removeclient.sh.""" """Деактивирует пользователя через removeclient.sh."""
try: try:
process = subprocess.run([os.path.join(BASE_DIR, 'removeclient.sh'), name], capture_output=True, text=True, cwd=BASE_DIR) process = subprocess.run(['./removeclient.sh', name], capture_output=True, text=True)
if process.returncode == 0: if process.returncode == 0:
return True return True
logger.error(f"Ошибка удаления пользователя {name}: {process.stderr}") logger.error(f"Ошибка удаления пользователя {name}: {process.stderr}")
@@ -150,7 +95,7 @@ def deactive_user_db(name):
def get_client_list(): def get_client_list():
"""Возвращает список клиентов (имя и конфигурация).""" """Возвращает список клиентов (имя и конфигурация)."""
clients = [] clients = []
users_dir = os.path.join(BASE_DIR, 'users') users_dir = 'users'
if os.path.exists(users_dir): if os.path.exists(users_dir):
for user_dir in os.listdir(users_dir): for user_dir in os.listdir(users_dir):
user_path = os.path.join(users_dir, user_dir) user_path = os.path.join(users_dir, user_dir)
@@ -165,16 +110,17 @@ def get_client_list():
def get_active_list(): def get_active_list():
"""Возвращает список активных клиентов с последним handshake.""" """Возвращает список активных клиентов с последним handshake."""
active = [] active = []
try: users_dir = 'users'
result = subprocess.run(['wg', 'show', 'wg0', 'latest-handshakes'], capture_output=True, text=True) if os.path.exists(users_dir):
lines = result.stdout.strip().split('\n') for user_dir in os.listdir(users_dir):
for line in lines: user_path = os.path.join(users_dir, user_dir)
if line: if os.path.isdir(user_path):
parts = line.split() status_file = os.path.join(user_path, 'status.json')
if len(parts) >= 2: if os.path.exists(status_file):
active.append((parts[0], datetime.fromtimestamp(int(parts[1])).strftime('%Y-%m-%d %H:%M:%S'))) with open(status_file, 'r') as f:
except Exception as e: status = json.load(f)
logger.error(f"Ошибка получения активных клиентов: {str(e)}") last_handshake = status.get('last_handshake', 'never')
active.append((user_dir, last_handshake))
return active return active
def set_user_expiration(username, expiration, transfer_limit): def set_user_expiration(username, expiration, transfer_limit):
@@ -217,7 +163,7 @@ def add_promocode(code, discount, expires_at, max_uses, subscription_period):
if code in promocodes: if code in promocodes:
return False return False
promocodes[code] = { promocodes[code] = {
'discount': float(discount), 'discount': discount,
'expires_at': expires_at.isoformat() if expires_at else None, 'expires_at': expires_at.isoformat() if expires_at else None,
'max_uses': max_uses, 'max_uses': max_uses,
'uses': 0, 'uses': 0,
@@ -266,33 +212,3 @@ def remove_promocode(code):
save_json(PROMOCODES_FILE, promocodes) save_json(PROMOCODES_FILE, promocodes)
return True return True
return False return False
def add_payment(user_id, payment_id, amount, status, period=None):
"""Добавляет информацию о платеже."""
payments = load_json(PAYMENTS_FILE, {})
payments[payment_id] = {
'user_id': user_id,
'amount': float(amount),
'status': status,
'period': period,
'created_at': datetime.now(pytz.utc).isoformat()
}
save_json(PAYMENTS_FILE, payments)
def update_payment_status(payment_id, status):
"""Обновляет статус платежа."""
payments = load_json(PAYMENTS_FILE, {})
if payment_id in payments:
payments[payment_id]['status'] = status
save_json(PAYMENTS_FILE, payments)
return True
return False
def get_pending_payments():
"""Возвращает список незавершенных платежей."""
payments = load_json(PAYMENTS_FILE, {})
return [
(p['user_id'], payment_id, p['amount'], p['period'])
for payment_id, p in payments.items()
if p['status'] == 'pending'
]