Compare commits

...
3 Commits
3 changed files with 74 additions and 4 deletions
+22 -2
View File
@@ -60,6 +60,7 @@ class OutboundFactory:
outbound_cls = cls._scheme_registry[scheme] outbound_cls = cls._scheme_registry[scheme]
return outbound_cls.from_link(target_storage, link) return outbound_cls.from_link(target_storage, link)
# устаревший метод, удалить после рефакторинга
@classmethod @classmethod
def from_inbound( def from_inbound(
cls, cls,
@@ -79,6 +80,19 @@ class OutboundFactory:
) )
return username, outbound return username, outbound
@classmethod
def from_xray_inbound(
cls, ts: TargetStorage, client: dict, inbound: dict
) -> Outbound:
protocol = inbound.get("protocol")
if protocol not in cls._registry:
raise ValueError(f"Unsupported protocol: {protocol}")
outbound_cls = cls._registry[protocol]
outbound = outbound_cls.from_xray_inbound(ts, client, inbound)
return outbound
@classmethod @classmethod
def from_spec( def from_spec(
cls, cls,
@@ -121,6 +135,12 @@ class Outbound(ABC):
inbound: dict, inbound: dict,
) -> tuple[str, Outbound]: ... ) -> tuple[str, Outbound]: ...
@classmethod
@abstractmethod
def from_xray_inbound(
cls, ts: TargetStorage, client: dict, inbound: dict
) -> Outbound: ...
@classmethod @classmethod
@abstractmethod @abstractmethod
def from_scratch( def from_scratch(
@@ -145,8 +165,8 @@ class Outbound(ABC):
@staticmethod @staticmethod
def split_client_email(email: str) -> tuple[str, str]: def split_client_email(email: str) -> tuple[str, str]:
username, target = email.rsplit("-", 1) username, target_id = email.rsplit("-", 1)
return username, target return username, target_id
@abstractmethod @abstractmethod
def __hash__(self) -> int: ... def __hash__(self) -> int: ...
+36 -2
View File
@@ -7,7 +7,7 @@ from .outbound import Outbound, OutboundFactory, OutboundSpec
if TYPE_CHECKING: if TYPE_CHECKING:
from .target import TargetStorage from .target import TargetStorage
from .xray_config import XrayConfig from .xray_config import XrayConfig, XrayStorage
@dataclass @dataclass
@@ -41,6 +41,18 @@ class User:
self.outbounds = list(user_specs.values()) self.outbounds = list(user_specs.values())
def add_to_xray_inbounds(self, xrs: XrayStorage):
added = False
xray_inbounds = xrs.load_inbounds()
for outbound in self.outbounds:
for xray_inbound in xray_inbounds:
if outbound.matches_inbound(xray_inbound):
outbound.add_to_inbound(xray_inbound, self.username)
added = True
if not added:
raise RuntimeError(f"Inbound not found for {outbound}")
class UserFactory: class UserFactory:
@staticmethod @staticmethod
@@ -62,5 +74,27 @@ class UserFactory:
return user return user
@staticmethod @staticmethod
def empty(username: str): def empty(username: str) -> User:
return User(username, []) return User(username, [])
@staticmethod
def from_xray_inbound(username: str, ts: TargetStorage, xrs: XrayStorage):
user_outbounds: list[Outbound] = []
inbounds: list[dict] = xrs.load_inbounds()
for inbound in inbounds:
protocol = inbound.get("protocol")
if protocol in OutboundFactory._registry:
settings = inbound.get("settings", {})
clients = settings.get("clients", [])
for client in clients:
email = client.get("email", "")
inbound_username, _ = Outbound.split_client_email(email)
if inbound_username == username:
user_outbound = OutboundFactory.from_xray_inbound(
ts, client, inbound
)
user_outbounds.append(user_outbound)
+16
View File
@@ -157,3 +157,19 @@ class XrayConfig:
self._save_json(self.inbounds_data[filename], path) self._save_json(self.inbounds_data[filename], path)
return True return True
class XrayStorage:
def __init__(self, config_path: Path):
self.path = config_path
self.inbounds_files: list
self.outbound_files: list
self.routings_files: list
self.inbounds: list[dict]
self.outbouns: list[dict]
self.routings: list[dict]
def load_inbounds(self) -> list[dict]:
return self.inbounds