diff --git a/core/controllers/profile_state/data_filters.py b/core/controllers/profile_state/data_filters.py new file mode 100644 index 0000000..8ab7617 --- /dev/null +++ b/core/controllers/profile_state/data_filters.py @@ -0,0 +1,67 @@ +from core.models.orm_calls.location_calls import get_profile_location_data +from core.models.enum_models import ProtocolChoice, get_choice_list +from core.models.orm_models.Location import Location +from core.errors.logger import logger + +from core.models.Result import Result, ResultError + +ALL_PROTOCOLS = [e.value for e in ProtocolChoice] + + +""" +Outputs: + Returns a list of supported protocols for a given location. +Inputs: + location_codes format: 'location_codes': 'us_wa' +""" + + + # if "_" not in location_codes: +# error_msg = f"This is a developer error. No location data found for {location_codes}" +# logger.error(error_msg) +# return Result(valid=False, error_type=ResultError.INVALID_INPUT, message=error_msg) + + + + +def get_supported_protocols_for_location(location_codes: str, profile_type: str = None) -> Result: + + country, city = location_codes.split("_") + print(f"country is {country}") + print(f"city is {city}") + + # this IS doing sql: + location = get_profile_location_data(country_code=country, city_code=city) + + print(f"location is {location}") + print(f"location type is {type(location)}") + # return location + + if not location: + error_msg = f"This is a developer error. No location data found for {location_codes}" + logger.error(error_msg) + return Result(valid=False, error_type=ResultError.INVALID_INPUT, message=error_msg) + + # this is NOT doing sql + supported_protocols = _get_supported_protocols_for_location(location=location, as_strings=True) + + if profile_type == "system-wide" and ProtocolChoice.SOCK5_PROXY.value in supported_protocols: + supported_protocols.remove(ProtocolChoice.SOCK5_PROXY.value) + + return Result(valid=True, data=supported_protocols) + + +def _get_supported_protocols_for_location(location: Location, as_strings: bool = False) -> list: + """Doesn't do SQL to get a list of supported locations""" + + SUPPORTED_PROTOCOLS = [] + + for each_protocol in ALL_PROTOCOLS: + supported = location.supports_protocol(enum_value=each_protocol) + print(f"supported for {each_protocol} is {supported}") + print(f"type of supported is {type(supported)}") + if supported: + print(f"THIS IS TRUE for {each_protocol}") + SUPPORTED_PROTOCOLS.append(each_protocol) + + return SUPPORTED_PROTOCOLS diff --git a/core/controllers/profile_state/update_profile.py b/core/controllers/profile_state/update_profile.py index 79bdaaa..a4c1997 100644 --- a/core/controllers/profile_state/update_profile.py +++ b/core/controllers/profile_state/update_profile.py @@ -3,21 +3,20 @@ from core.errors.logger import logger from core.models.Result import Result, ResultError from core.services.networking.systemwide.general_tools.manage_sudo_configs import remove_sudo_config -# JSON Models from core.models.BaseProfile import BaseProfile as Profile from core.models.BaseProfile import ProfileType -from core.models.Subscription import Subscription -from core.models.session.SessionProfile import SessionProfile -from core.models.system.SystemProfile import SystemProfile - -# ORM Models -from core.models.orm_models.Location import Location -from core.models.orm_models.Operator import Operator # ORM Calls from core.models.orm_calls.location_calls import get_profile_location_data from core.models.BaseProfile import get_application_version +# previously used: +# from core.models.Subscription import Subscription +# from core.models.session.SessionProfile import SessionProfile +# from core.models.system.SystemProfile import SystemProfile +# from core.models.orm_models.Location import Location +# from core.models.orm_models.Operator import Operator + SYSTEMWIDE_CHOICES = ['wireguard', 'hysteria2', 'vless'] SESSION_CHOICES = ['wireguard', 'tor', 'proxy'] @@ -42,9 +41,7 @@ def update_profile( key: str, new_value: str) -> Result: - return Result(valid=False, error_type=ResultError.UNKNOWN, message="This is a test fail") - - final_data = None + # final_data = None logger.info(f"[UPDATE PROFILE] Recieved profile_id {profile_id}, key {key}, and new_value {new_value}.") if not key or not new_value: @@ -109,14 +106,10 @@ def update_profile( return Result(valid=False, message="Invalid Value to Edit", error_type=ResultError.INVALID_INPUT) logger.info("[UPDATE PROFILE] Passing to Profile model to save..") - return _literally_save(profile) - - -def _literally_save(profile: Profile) -> Result: try: profile.save() logger.info("[UPDATE PROFILE] Save worked, passing to the GUI the Result..") - return Result(valid=True, data=final_data) + return Result(valid=True) except Exception as e: error_msg = f"Profile save failed because {str(e)}" return Result(valid=False, message=error_msg, error_type=ResultError.UNKNOWN) @@ -170,5 +163,5 @@ def change_systemwide_connection(profile: Profile, new_value: str) -> Result: # UPDATE PROFILE logger.info("Literally updating the value..") profile.connection.code = new_value - final_data = "edit_session" + # final_data = "edit_session" return Result(valid=True, data=profile) diff --git a/core/models/enum_models.py b/core/models/enum_models.py index 31c7e4d..adc30a1 100644 --- a/core/models/enum_models.py +++ b/core/models/enum_models.py @@ -6,7 +6,7 @@ class ProtocolChoice(Enum): HYSTERIA2 = "hysteria2" VLESS = "vless" SOCK5_PROXY = "proxy" - MASKED_WIREGUARD = "masked_wireguard" + # MASKED_WIREGUARD = "masked_wireguard" class Currency(Enum): MONERO = "monero" diff --git a/core/models/orm_calls/location_calls.py b/core/models/orm_calls/location_calls.py index 701b24a..c69b189 100644 --- a/core/models/orm_calls/location_calls.py +++ b/core/models/orm_calls/location_calls.py @@ -1,5 +1,6 @@ from core.models.orm_models.Location import Location from core.models.orm_models.Operator import Operator +from core.models.enum_models import ProtocolChoice, get_choice_list from core.models.manage.wrapper import safe_db_operation, WrapperRollback from core.models.DatabaseOperation import DatabaseOperation, DBErrorType from core.errors.logger import logger @@ -11,6 +12,8 @@ from sqlalchemy.orm import Session from typing import Optional import random +ALL_PROTOCOLS = get_choice_list(ProtocolChoice) + @safe_db_operation def execute_location_sql(country_code: str, city_code: str, session: Session) -> DatabaseOperation: location_object = session.execute( @@ -58,3 +61,18 @@ def get_random_location(filter_out_list: Optional[list] = None) -> Location: if random_pick not in filter_out_list: return random_pick + + +def get_supported_protocols_for_location(location: Location, as_strings: bool = False) -> list: + """Doesn't do SQL to get a list of supported locations""" + + SUPPORTED_PROTOCOLS = [] + + for each_protocol in ALL_PROTOCOLS: + if location.supports_protocol(protocol): + if as_strings: + SUPPORTED_PROTOCOLS.append(each_protocol.value) + else: + SUPPORTED_PROTOCOLS.append(each_protocol) + + return SUPPORTED_PROTOCOLS \ No newline at end of file diff --git a/core/models/orm_models/Location.py b/core/models/orm_models/Location.py index 6747fca..c2f7b34 100644 --- a/core/models/orm_models/Location.py +++ b/core/models/orm_models/Location.py @@ -1,11 +1,11 @@ -from sqlalchemy import Integer, String, ForeignKey +from sqlalchemy import Integer, String, ForeignKey, Boolean from sqlalchemy.orm import declarative_base, mapped_column, Mapped, relationship from typing import Optional from sqlalchemy.orm import Mapped from core.models.orm_models.Base import BaseModel from core.models.orm_models.Operator import Operator - +from core.models.enum_models import ProtocolChoice class Location(BaseModel): __tablename__ = 'locations' @@ -40,11 +40,11 @@ class Location(BaseModel): ) provider_name: Mapped[Optional[str]] = mapped_column(String, nullable=True, default=None) - available: Mapped[Optional[bool]] = mapped_column(String, nullable=True, default=None) - is_proxy_capable: Mapped[Optional[bool]] = mapped_column(String, nullable=True, default=None) - is_wireguard_capable: Mapped[Optional[bool]] = mapped_column(String, nullable=True, default=None) - is_hysteria2_capable: Mapped[Optional[bool]] = mapped_column(String, nullable=True, default=None) - is_vless_capable: Mapped[Optional[bool]] = mapped_column(String, nullable=True, default=None) + available: Mapped[Optional[bool]] = mapped_column(Boolean, nullable=True, default=None) + is_proxy_capable: Mapped[Optional[bool]] = mapped_column(Boolean, nullable=True, default=None) + is_wireguard_capable: Mapped[Optional[bool]] = mapped_column(Boolean, nullable=True, default=None) + is_hysteria2_capable: Mapped[Optional[bool]] = mapped_column(Boolean, nullable=True, default=None) + is_vless_capable: Mapped[Optional[bool]] = mapped_column(Boolean, nullable=True, default=None) def convert_to_dict(self): return { @@ -55,6 +55,27 @@ class Location(BaseModel): } + + def supports_protocol(self, enum_value: ProtocolChoice) -> bool: + # print(f"inside {self.country_name} {self.name} location model's supports_protocol, the submitted protocol is {enum_value}") + print(f"enum_value type is {type(enum_value)}") + if enum_value is None: + return False + + # socks5 proxy name doesn't match 'proxy' + if enum_value == ProtocolChoice.SOCK5_PROXY: + return self.is_proxy_capable + + if isinstance(enum_value, ProtocolChoice): + string_version = enum_value.value + else: + string_version = enum_value + + field_name = f'is_{string_version}_capable' + print(f"field_name is {field_name}") + return bool(getattr(self, field_name)) + + # to use: # Lookup by location/city codes # record = session.get(Location, (country_code, code))