Core configuration synchronized with the CLI

This commit is contained in:
Zenaku 2026-06-03 17:54:29 -05:00
parent 50bf6503d9
commit 35d94908f4
5 changed files with 127 additions and 48 deletions

View file

@ -45,6 +45,8 @@ class ConnectionController:
@staticmethod
def establish_connection(profile: Union[SessionProfile, SystemProfile], ignore: tuple[type[Exception]] = (), connection_observer: Optional[ConnectionObserver] = None):
from core.controllers.ConnectionController import ConnectionController
connection = profile.connection
if connection.needs_proxy_configuration() and not profile.has_proxy_configuration():
@ -66,32 +68,6 @@ class ConnectionController:
if connection.needs_wireguard_configuration() and not profile.has_wireguard_configuration():
if connection.needs_operator_proxy():
if profile.has_subscription():
if not profile.subscription.has_been_activated():
ProfileController.activate_subscription(profile, connection_observer=connection_observer)
operator_proxy_session = ConnectionController.with_preferred_connection(
profile.subscription.billing_code,
profile.subscription.operator_id,
connection.get_protocol(),
task=WebServiceApiService.post_operator_proxy,
connection_observer=connection_observer
)
if operator_proxy_session is None:
raise InvalidSubscriptionError()
profile.attach_operator_proxy_session(operator_proxy_session)
else:
raise MissingSubscriptionError()
if profile.has_subscription():
if not profile.subscription.has_been_activated():
@ -112,6 +88,29 @@ class ConnectionController:
raise MissingSubscriptionError()
if connection.needs_operator_proxy() and not profile.has_operator_proxy_session():
if profile.has_subscription():
if not profile.subscription.has_been_activated():
ProfileController.activate_subscription(profile, connection_observer=connection_observer)
operator_proxy_session = ConnectionController.with_preferred_connection(
profile.subscription.billing_code,
profile.subscription.operator_id,
connection.get_protocol(),
task=WebServiceApiService.post_operator_proxy,
connection_observer=connection_observer
)
if operator_proxy_session is None:
raise InvalidSubscriptionError()
profile.attach_operator_proxy_session(operator_proxy_session)
else:
raise MissingSubscriptionError()
if profile.is_session_profile():
try:
@ -143,7 +142,6 @@ class ConnectionController:
raise ConnectionError('The connection could not be established.')
return None
@staticmethod
def establish_session_connection(profile: SessionProfile, ignore: tuple[type[Exception]] = (), connection_observer: Optional[ConnectionObserver] = None):
@ -212,6 +210,20 @@ class ConnectionController:
@staticmethod
def establish_system_connection(profile: SystemProfile, ignore: tuple[type[Exception]] = (), connection_observer: Optional[ConnectionObserver] = None):
if profile.connection.needs_operator_proxy():
operator_proxy_session = profile.get_operator_proxy_session()
protocol = profile.connection.get_protocol()
if protocol == 'vless':
from core.controllers.encrypted_proxy.VlessController import VlessController
VlessController(1080).enable(operator_proxy_session.links[0], operator_proxy_session.username, connection_observer)
elif protocol == 'hysteria2':
from core.controllers.encrypted_proxy.HysteriaController import HysteriaController
HysteriaController(1080).enable(operator_proxy_session.username, operator_proxy_session.password, operator_proxy_session.operator_hysteria2_host, connection_observer)
SystemStateController.create(profile.id)
return
if ConfigurationController.get_endpoint_verification_enabled():
ProfileController.verify_wireguard_endpoint(profile, ignore=ignore)
@ -219,36 +231,28 @@ class ConnectionController:
ConnectionController.__establish_system_connection(profile, connection_observer)
except ConnectionError:
try:
ConnectionController.terminate_system_connection()
except ConnectionTerminationError:
pass
raise ConnectionError('The connection could not be established.')
except CalledProcessError:
try:
ConnectionController.terminate_system_connection()
except ConnectionTerminationError:
pass
try:
ConnectionController.__establish_system_connection(profile, connection_observer)
except (ConnectionError, CalledProcessError):
try:
ConnectionController.terminate_system_connection()
except ConnectionTerminationError:
pass
raise ConnectionError('The connection could not be established.')
ConnectionController.terminate_tor_connection()
time.sleep(1.0)
@staticmethod
def establish_tor_connection(connection_observer: Optional[ConnectionObserver] = None):
@ -334,6 +338,19 @@ class ConnectionController:
@staticmethod
def terminate_system_connection():
system_state = SystemStateController.get()
if system_state is not None:
profile = ProfileController.get(system_state.profile_id)
if profile is not None and profile.connection.needs_operator_proxy():
protocol = profile.connection.get_protocol()
if protocol == 'vless':
from core.controllers.encrypted_proxy.VlessController import VlessController
VlessController(1080).disable()
elif protocol == 'hysteria2':
from core.controllers.encrypted_proxy.HysteriaController import HysteriaController
HysteriaController(1080).disable()
SystemState.dissolve()
return
if shutil.which('nmcli') is None:
raise CommandNotFoundError('nmcli')
@ -351,7 +368,6 @@ class ConnectionController:
else:
raise ConnectionTerminationError('The connection could not be terminated.')
@staticmethod
def get_proxies(port_number: int):

View file

@ -156,13 +156,17 @@ class ProfileController:
if profile.has_subscription():
print(f"DEBUG activate_subscription:")
print(f" billing_code: {profile.subscription.billing_code}")
print(f" operator_id: {profile.subscription.operator_id}")
subscription = ConnectionController.with_preferred_connection(profile.subscription.billing_code, task=WebServiceApiService.get_subscription, connection_observer=connection_observer)
if subscription is not None:
print(f" get_subscription returned: {subscription}")
if subscription is not None:
profile.subscription = subscription
profile.save()
else:
raise InvalidSubscriptionError()

View file

@ -5,7 +5,6 @@ from core.observers.ConnectionObserver import ConnectionObserver
from core.services.WebServiceApiService import WebServiceApiService
from typing import Union
class SubscriptionController:
@staticmethod
@ -18,4 +17,51 @@ class SubscriptionController:
def create(subscription_plan: SubscriptionPlan, profile: Union[SessionProfile, SystemProfile], connection_observer: ConnectionObserver = None):
from core.controllers.ConnectionController import ConnectionController
return ConnectionController.with_preferred_connection(subscription_plan.id, profile.location.id, task=WebServiceApiService.post_subscription, connection_observer=connection_observer)
if profile.location:
return ConnectionController.with_preferred_connection(
subscription_plan.id,
profile.location.id,
task=WebServiceApiService.post_subscription,
connection_observer=connection_observer
)
else:
return ConnectionController.with_preferred_connection(
subscription_plan.id,
operator_id=profile.connection.operator_id,
task=WebServiceApiService.post_subscription,
connection_observer=connection_observer
)
from core.controllers.ConnectionController import ConnectionController
if profile.location:
return ConnectionController.with_preferred_connection(
subscription_plan.id,
profile.location.id,
task=WebServiceApiService.post_subscription,
connection_observer=connection_observer
)
else:
return ConnectionController.with_preferred_connection(
subscription_plan.id,
task=WebServiceApiService.post_subscription,
connection_observer=connection_observer
)
from core.controllers.ConnectionController import ConnectionController
if profile.location:
# Para WireGuard (con location)
return ConnectionController.with_preferred_connection(
subscription_plan.id,
profile.location.id,
task=WebServiceApiService.post_subscription,
connection_observer=connection_observer
)
else:
return ConnectionController.with_preferred_connection(
subscription_plan.id,
task=WebServiceApiService.post_subscription,
connection_observer=connection_observer
)

View file

@ -53,6 +53,9 @@ class SubscriptionPlan(Model):
if connection.code == 'wireguard':
features_wireguard = True
if connection.code == 'operator':
features_proxy = True
Model._create_table_if_not_exists(table_name=_table_name, table_definition=_table_definition)
return Model._query_one('SELECT * FROM subscription_plans WHERE features_proxy = ? AND features_wireguard = ? AND duration = ? LIMIT 1', SubscriptionPlan.factory, [features_proxy, features_wireguard, duration])
@ -76,6 +79,9 @@ class SubscriptionPlan(Model):
if connection.code == 'wireguard':
features_wireguard = True
if connection.code == 'operator':
features_proxy = True
return Model._query_all('SELECT * FROM subscription_plans WHERE features_proxy = ? AND features_wireguard = ?', SubscriptionPlan.factory, [features_proxy, features_wireguard])
@staticmethod

View file

@ -1,15 +1,22 @@
from core.models.BaseConnection import BaseConnection
from dataclasses import dataclass
from dataclasses import dataclass, field
from typing import Optional
@dataclass
class SystemConnection (BaseConnection):
class SystemConnection(BaseConnection):
operator_id: Optional[int] = field(default=None)
protocol: Optional[str] = field(default=None)
def __post_init__(self):
if self.code != 'wireguard':
if self.code not in ('wireguard', 'operator'):
raise ValueError('Invalid connection code.')
@staticmethod
def needs_proxy_configuration():
return False
def needs_operator_proxy(self):
return self.code == 'operator'
def get_protocol(self):
return self.protocol