diff --git a/core/scripts/normalsub/normalsub.py b/core/scripts/normalsub/normalsub.py index fb407f5..550cfe9 100644 --- a/core/scripts/normalsub/normalsub.py +++ b/core/scripts/normalsub/normalsub.py @@ -5,7 +5,8 @@ import re import time import shlex import base64 -from typing import Dict, List, Optional, Tuple, Any, Union +import sys +from typing import Dict, List, Optional, Tuple, Any from dataclasses import dataclass, field from io import BytesIO @@ -16,6 +17,9 @@ from dotenv import load_dotenv import qrcode from jinja2 import Environment, FileSystemLoader +sys.path.append(os.path.join(os.path.dirname(__file__), '..')) +from db.database import db + load_dotenv() @@ -28,7 +32,6 @@ class AppConfig: sni_file: str singbox_template_path: str hysteria_cli_path: str - users_json_path: str nodes_json_path: str extra_config_path: str rate_limit: int @@ -172,9 +175,8 @@ class Utils: class HysteriaCLI: - def __init__(self, cli_path: str, users_json_path: str): + def __init__(self, cli_path: str): self.cli_path = cli_path - self.users_json_path = users_json_path def _run_command(self, args: List[str]) -> str: try: @@ -192,61 +194,29 @@ class HysteriaCLI: print(f"Hysteria CLI error: {e}") raise - def get_user_details_from_json(self, username: str) -> Optional[Dict[str, Any]]: - try: - with open(self.users_json_path, 'r') as f: - users_data = json.load(f) - return users_data.get(username) - except (FileNotFoundError, json.JSONDecodeError) as e: - print(f"Error reading user details from {self.users_json_path}: {e}") - return None - except Exception as e: - print(f"An unexpected error occurred while reading users file: {e}") - return None - def get_username_by_password(self, password_token: str) -> Optional[str]: - try: - with open(self.users_json_path, 'r') as f: - users_data = json.load(f) - for username, details in users_data.items(): - if details.get('password') == password_token: - return username - return None - except FileNotFoundError: - print(f"Error: Users file not found at {self.users_json_path}") - return None - except json.JSONDecodeError: - print(f"Error: Could not decode JSON from {self.users_json_path}") - return None - except Exception as e: - print(f"An unexpected error occurred while reading users file: {e}") + if not db: return None + user_doc = db.collection.find_one({"password": password_token}, {"_id": 1}) + return user_doc['_id'] if user_doc else None def get_user_info(self, username: str) -> Optional[UserInfo]: - raw_info_str = self._run_command(['get-user', '-u', username]) - if raw_info_str is None: + if not db: return None - - user_details = self.get_user_details_from_json(username) - if not user_details or 'password' not in user_details: - print(f"Warning: Password for user '{username}' could not be fetched from {self.users_json_path}. Cannot create UserInfo.") - return None - - try: - raw_info = json.loads(raw_info_str) - return UserInfo( - username=username, - password=user_details['password'], - upload_bytes=raw_info.get('upload_bytes', 0), - download_bytes=raw_info.get('download_bytes', 0), - max_download_bytes=raw_info.get('max_download_bytes', 0), - account_creation_date=raw_info.get('account_creation_date', ''), - expiration_days=raw_info.get('expiration_days', 0), - blocked=user_details.get('blocked', False) - ) - except json.JSONDecodeError as e: - print(f"JSONDecodeError: {e}, Raw output: {raw_info_str}") + user_doc = db.get_user(username) + if not user_doc: return None + + return UserInfo( + username=user_doc.get('_id'), + password=user_doc.get('password'), + upload_bytes=user_doc.get('upload_bytes', 0), + download_bytes=user_doc.get('download_bytes', 0), + max_download_bytes=user_doc.get('max_download_bytes', 0), + account_creation_date=user_doc.get('account_creation_date', ''), + expiration_days=user_doc.get('expiration_days', 0), + blocked=user_doc.get('blocked', False) + ) def get_all_uris(self, username: str) -> List[str]: output = self._run_command(['show-user-uri', '-u', username, '-a']) @@ -409,11 +379,10 @@ class SubscriptionManager: processed_uris = [] for uri in all_uris: if "v2ray" in user_agent and "ng" in user_agent: - match = re.search(r'pinSHA256=sha256/([^&]+)', uri) + match = re.search(r'pinSHA256=([^&]+)', uri) if match: - decoded = base64.b64decode(match.group(1)) - formatted = ":".join("{:02X}".format(byte) for byte in decoded) - uri = uri.replace(f'pinSHA256=sha256/{match.group(1)}', f'pinSHA256={formatted}') + formatted = ":".join("{:02X}".format(byte) for byte in base64.b64decode(match.group(1))) + uri = uri.replace(f'pinSHA256={match.group(1)}', f'pinSHA256={formatted}') processed_uris.append(uri) extra_uris = self._get_extra_configs() @@ -446,7 +415,7 @@ class HysteriaServer: def __init__(self): self.config = self._load_config() self.rate_limiter = RateLimiter(self.config.rate_limit, self.config.rate_limit_window) - self.hysteria_cli = HysteriaCLI(self.config.hysteria_cli_path, self.config.users_json_path) + self.hysteria_cli = HysteriaCLI(self.config.hysteria_cli_path) self.singbox_generator = SingboxConfigGenerator(self.hysteria_cli, self.config.sni) self.singbox_generator.set_template_path(self.config.singbox_template_path) self.subscription_manager = SubscriptionManager(self.hysteria_cli, self.config) @@ -478,7 +447,6 @@ class HysteriaServer: sni_file = '/etc/hysteria/.configs.env' singbox_template_path = '/etc/hysteria/core/scripts/normalsub/singbox.json' hysteria_cli_path = '/etc/hysteria/core/cli.py' - users_json_path = os.getenv('HYSTERIA_USERS_JSON_PATH', '/etc/hysteria/users.json') nodes_json_path = '/etc/hysteria/nodes.json' extra_config_path = '/etc/hysteria/extra.json' rate_limit = 100 @@ -492,7 +460,6 @@ class HysteriaServer: sni_file=sni_file, singbox_template_path=singbox_template_path, hysteria_cli_path=hysteria_cli_path, - users_json_path=users_json_path, nodes_json_path=nodes_json_path, extra_config_path=extra_config_path, rate_limit=rate_limit, rate_limit_window=rate_limit_window, @@ -681,4 +648,4 @@ class HysteriaServer: if __name__ == '__main__': server = HysteriaServer() - server.run() + server.run() \ No newline at end of file