From fcc00b9c9d2e9adc1e62ead5d8342e2a2dc07226 Mon Sep 17 00:00:00 2001 From: Marc Kelechava Date: Tue, 18 Nov 2025 14:44:19 -0800 Subject: [PATCH] Expand Proxy locations to current list of all Massive supported countries (#4022) --- skyvern/schemas/proxy_locations.py | 264 ++++++++++++++++++++ skyvern/schemas/runs.py | 380 +++++++++++++++++++---------- 2 files changed, 514 insertions(+), 130 deletions(-) create mode 100644 skyvern/schemas/proxy_locations.py diff --git a/skyvern/schemas/proxy_locations.py b/skyvern/schemas/proxy_locations.py new file mode 100644 index 00000000..1d9ab2ab --- /dev/null +++ b/skyvern/schemas/proxy_locations.py @@ -0,0 +1,264 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING +from zoneinfo import ZoneInfo + +if TYPE_CHECKING: + from skyvern.schemas.runs import ProxyLocation + + +# Mapping derived from the IANA tz database (zone.tab). For multi-timezone +# countries we choose the primary commercial hub; Kosovo falls back to Europe/Belgrade. +RESIDENTIAL_COUNTRY_TIMEZONES: dict[str, str] = { + "AD": "Europe/Andorra", + "AE": "Asia/Dubai", + "AF": "Asia/Kabul", + "AG": "America/Antigua", + "AI": "America/Anguilla", + "AL": "Europe/Tirane", + "AM": "Asia/Yerevan", + "AO": "Africa/Luanda", + "AR": "America/Argentina/Buenos_Aires", + "AS": "Pacific/Pago_Pago", + "AT": "Europe/Vienna", + "AU": "Australia/Sydney", + "AW": "America/Aruba", + "AX": "Europe/Mariehamn", + "AZ": "Asia/Baku", + "BA": "Europe/Sarajevo", + "BB": "America/Barbados", + "BD": "Asia/Dhaka", + "BE": "Europe/Brussels", + "BF": "Africa/Ouagadougou", + "BG": "Europe/Sofia", + "BH": "Asia/Bahrain", + "BI": "Africa/Bujumbura", + "BJ": "Africa/Porto-Novo", + "BM": "Atlantic/Bermuda", + "BN": "Asia/Brunei", + "BO": "America/La_Paz", + "BQ": "America/Kralendijk", + "BR": "America/Sao_Paulo", + "BS": "America/Nassau", + "BT": "Asia/Thimphu", + "BW": "Africa/Gaborone", + "BY": "Europe/Minsk", + "BZ": "America/Belize", + "CA": "America/Toronto", + "CD": "Africa/Kinshasa", + "CF": "Africa/Bangui", + "CG": "Africa/Brazzaville", + "CH": "Europe/Zurich", + "CI": "Africa/Abidjan", + "CK": "Pacific/Rarotonga", + "CL": "America/Santiago", + "CM": "Africa/Douala", + "CN": "Asia/Shanghai", + "CO": "America/Bogota", + "CR": "America/Costa_Rica", + "CU": "America/Havana", + "CV": "Atlantic/Cape_Verde", + "CW": "America/Curacao", + "CY": "Asia/Nicosia", + "CZ": "Europe/Prague", + "DE": "Europe/Berlin", + "DJ": "Africa/Djibouti", + "DK": "Europe/Copenhagen", + "DM": "America/Dominica", + "DO": "America/Santo_Domingo", + "DZ": "Africa/Algiers", + "EC": "America/Guayaquil", + "EE": "Europe/Tallinn", + "EG": "Africa/Cairo", + "ES": "Europe/Madrid", + "ET": "Africa/Addis_Ababa", + "FI": "Europe/Helsinki", + "FJ": "Pacific/Fiji", + "FK": "Atlantic/Stanley", + "FM": "Pacific/Pohnpei", + "FO": "Atlantic/Faroe", + "FR": "Europe/Paris", + "GA": "Africa/Libreville", + "GB": "Europe/London", + "GD": "America/Grenada", + "GE": "Asia/Tbilisi", + "GF": "America/Cayenne", + "GG": "Europe/Guernsey", + "GH": "Africa/Accra", + "GI": "Europe/Gibraltar", + "GL": "America/Nuuk", + "GM": "Africa/Banjul", + "GN": "Africa/Conakry", + "GP": "America/Guadeloupe", + "GQ": "Africa/Malabo", + "GR": "Europe/Athens", + "GT": "America/Guatemala", + "GU": "Pacific/Guam", + "GW": "Africa/Bissau", + "GY": "America/Guyana", + "HK": "Asia/Hong_Kong", + "HN": "America/Tegucigalpa", + "HR": "Europe/Zagreb", + "HT": "America/Port-au-Prince", + "HU": "Europe/Budapest", + "ID": "Asia/Jakarta", + "IE": "Europe/Dublin", + "IL": "Asia/Jerusalem", + "IM": "Europe/Isle_of_Man", + "IN": "Asia/Kolkata", + "IO": "Indian/Chagos", + "IQ": "Asia/Baghdad", + "IR": "Asia/Tehran", + "IS": "Atlantic/Reykjavik", + "IT": "Europe/Rome", + "JE": "Europe/Jersey", + "JM": "America/Jamaica", + "JO": "Asia/Amman", + "JP": "Asia/Tokyo", + "KE": "Africa/Nairobi", + "KG": "Asia/Bishkek", + "KH": "Asia/Phnom_Penh", + "KI": "Pacific/Tarawa", + "KM": "Indian/Comoro", + "KN": "America/St_Kitts", + "KR": "Asia/Seoul", + "KW": "Asia/Kuwait", + "KY": "America/Cayman", + "KZ": "Asia/Almaty", + "LA": "Asia/Vientiane", + "LB": "Asia/Beirut", + "LC": "America/St_Lucia", + "LI": "Europe/Vaduz", + "LK": "Asia/Colombo", + "LR": "Africa/Monrovia", + "LS": "Africa/Maseru", + "LT": "Europe/Vilnius", + "LU": "Europe/Luxembourg", + "LV": "Europe/Riga", + "LY": "Africa/Tripoli", + "MA": "Africa/Casablanca", + "MC": "Europe/Monaco", + "MD": "Europe/Chisinau", + "ME": "Europe/Podgorica", + "MF": "America/Marigot", + "MG": "Indian/Antananarivo", + "MK": "Europe/Skopje", + "ML": "Africa/Bamako", + "MM": "Asia/Yangon", + "MN": "Asia/Ulaanbaatar", + "MO": "Asia/Macau", + "MP": "Pacific/Saipan", + "MQ": "America/Martinique", + "MR": "Africa/Nouakchott", + "MS": "America/Montserrat", + "MT": "Europe/Malta", + "MU": "Indian/Mauritius", + "MV": "Indian/Maldives", + "MW": "Africa/Blantyre", + "MX": "America/Mexico_City", + "MY": "Asia/Kuala_Lumpur", + "MZ": "Africa/Maputo", + "NA": "Africa/Windhoek", + "NC": "Pacific/Noumea", + "NE": "Africa/Niamey", + "NG": "Africa/Lagos", + "NI": "America/Managua", + "NL": "Europe/Amsterdam", + "NO": "Europe/Oslo", + "NP": "Asia/Kathmandu", + "NZ": "Pacific/Auckland", + "OM": "Asia/Muscat", + "PA": "America/Panama", + "PE": "America/Lima", + "PF": "Pacific/Tahiti", + "PG": "Pacific/Port_Moresby", + "PH": "Asia/Manila", + "PK": "Asia/Karachi", + "PL": "Europe/Warsaw", + "PM": "America/Miquelon", + "PR": "America/Puerto_Rico", + "PS": "Asia/Hebron", + "PT": "Europe/Lisbon", + "PW": "Pacific/Palau", + "PY": "America/Asuncion", + "QA": "Asia/Qatar", + "RE": "Indian/Reunion", + "RO": "Europe/Bucharest", + "RS": "Europe/Belgrade", + "RU": "Europe/Moscow", + "RW": "Africa/Kigali", + "SA": "Asia/Riyadh", + "SB": "Pacific/Guadalcanal", + "SC": "Indian/Mahe", + "SD": "Africa/Khartoum", + "SE": "Europe/Stockholm", + "SG": "Asia/Singapore", + "SI": "Europe/Ljubljana", + "SK": "Europe/Bratislava", + "SL": "Africa/Freetown", + "SM": "Europe/San_Marino", + "SN": "Africa/Dakar", + "SO": "Africa/Mogadishu", + "SR": "America/Paramaribo", + "SS": "Africa/Juba", + "ST": "Africa/Sao_Tome", + "SV": "America/El_Salvador", + "SX": "America/Lower_Princes", + "SY": "Asia/Damascus", + "SZ": "Africa/Mbabane", + "TC": "America/Grand_Turk", + "TD": "Africa/Ndjamena", + "TG": "Africa/Lome", + "TH": "Asia/Bangkok", + "TJ": "Asia/Dushanbe", + "TL": "Asia/Dili", + "TM": "Asia/Ashgabat", + "TN": "Africa/Tunis", + "TO": "Pacific/Tongatapu", + "TR": "Europe/Istanbul", + "TT": "America/Port_of_Spain", + "TW": "Asia/Taipei", + "TZ": "Africa/Dar_es_Salaam", + "UA": "Europe/Kyiv", + "UG": "Africa/Kampala", + "US": "America/New_York", + "UY": "America/Montevideo", + "UZ": "Asia/Tashkent", + "VA": "Europe/Vatican", + "VC": "America/St_Vincent", + "VE": "America/Caracas", + "VG": "America/Tortola", + "VI": "America/St_Thomas", + "VN": "Asia/Ho_Chi_Minh", + "VU": "Pacific/Efate", + "WS": "Pacific/Apia", + "XK": "Europe/Belgrade", + "YE": "Asia/Aden", + "YT": "Indian/Mayotte", + "ZA": "Africa/Johannesburg", + "ZM": "Africa/Lusaka", + "ZW": "Africa/Harare", +} + + +def build_residential_locations_by_iso(enum_cls: type[ProxyLocation]) -> dict[str, ProxyLocation]: + mapping: dict[str, ProxyLocation] = {"US": enum_cls.RESIDENTIAL} + for iso_code in sorted(RESIDENTIAL_COUNTRY_TIMEZONES): + if iso_code == "US": + continue + mapping[iso_code] = getattr(enum_cls, f"RESIDENTIAL_{iso_code}") + return mapping + + +def build_iso_by_residential_location( + residential_locations_by_iso: dict[str, ProxyLocation], +) -> dict[ProxyLocation, str]: + return {location: iso for iso, location in residential_locations_by_iso.items()} + + +def build_tzinfo_by_residential_location( + residential_locations_by_iso: dict[str, ProxyLocation], +) -> dict[ProxyLocation, ZoneInfo]: + return { + location: ZoneInfo(RESIDENTIAL_COUNTRY_TIMEZONES[iso]) for iso, location in residential_locations_by_iso.items() + } diff --git a/skyvern/schemas/runs.py b/skyvern/schemas/runs.py index 08e6d586..fd6b7c6a 100644 --- a/skyvern/schemas/runs.py +++ b/skyvern/schemas/runs.py @@ -30,6 +30,11 @@ from skyvern.schemas.docs.doc_strings import ( TOTP_URL_DOC_STRING, WEBHOOK_URL_DOC_STRING, ) +from skyvern.schemas.proxy_locations import ( + build_iso_by_residential_location, + build_residential_locations_by_iso, + build_tzinfo_by_residential_location, +) from skyvern.utils.url_validators import validate_url @@ -40,25 +45,236 @@ class ProxyLocation(StrEnum): US_TX = "US-TX" US_FL = "US-FL" US_WA = "US-WA" - RESIDENTIAL_ES = "RESIDENTIAL_ES" - RESIDENTIAL_IE = "RESIDENTIAL_IE" - RESIDENTIAL_GB = "RESIDENTIAL_GB" - RESIDENTIAL_IN = "RESIDENTIAL_IN" - RESIDENTIAL_JP = "RESIDENTIAL_JP" - RESIDENTIAL_FR = "RESIDENTIAL_FR" - RESIDENTIAL_DE = "RESIDENTIAL_DE" - RESIDENTIAL_NZ = "RESIDENTIAL_NZ" - RESIDENTIAL_ZA = "RESIDENTIAL_ZA" - RESIDENTIAL_AR = "RESIDENTIAL_AR" - RESIDENTIAL_AU = "RESIDENTIAL_AU" - RESIDENTIAL_BR = "RESIDENTIAL_BR" - RESIDENTIAL_TR = "RESIDENTIAL_TR" - RESIDENTIAL_CA = "RESIDENTIAL_CA" - RESIDENTIAL_MX = "RESIDENTIAL_MX" - RESIDENTIAL_IT = "RESIDENTIAL_IT" - RESIDENTIAL_NL = "RESIDENTIAL_NL" RESIDENTIAL_ISP = "RESIDENTIAL_ISP" NONE = "NONE" + # JoinMassive residential locations + RESIDENTIAL_AD = "RESIDENTIAL_AD" + RESIDENTIAL_AE = "RESIDENTIAL_AE" + RESIDENTIAL_AF = "RESIDENTIAL_AF" + RESIDENTIAL_AG = "RESIDENTIAL_AG" + RESIDENTIAL_AI = "RESIDENTIAL_AI" + RESIDENTIAL_AL = "RESIDENTIAL_AL" + RESIDENTIAL_AM = "RESIDENTIAL_AM" + RESIDENTIAL_AO = "RESIDENTIAL_AO" + RESIDENTIAL_AR = "RESIDENTIAL_AR" + RESIDENTIAL_AS = "RESIDENTIAL_AS" + RESIDENTIAL_AT = "RESIDENTIAL_AT" + RESIDENTIAL_AU = "RESIDENTIAL_AU" + RESIDENTIAL_AW = "RESIDENTIAL_AW" + RESIDENTIAL_AX = "RESIDENTIAL_AX" + RESIDENTIAL_AZ = "RESIDENTIAL_AZ" + RESIDENTIAL_BA = "RESIDENTIAL_BA" + RESIDENTIAL_BB = "RESIDENTIAL_BB" + RESIDENTIAL_BD = "RESIDENTIAL_BD" + RESIDENTIAL_BE = "RESIDENTIAL_BE" + RESIDENTIAL_BF = "RESIDENTIAL_BF" + RESIDENTIAL_BG = "RESIDENTIAL_BG" + RESIDENTIAL_BH = "RESIDENTIAL_BH" + RESIDENTIAL_BI = "RESIDENTIAL_BI" + RESIDENTIAL_BJ = "RESIDENTIAL_BJ" + RESIDENTIAL_BM = "RESIDENTIAL_BM" + RESIDENTIAL_BN = "RESIDENTIAL_BN" + RESIDENTIAL_BO = "RESIDENTIAL_BO" + RESIDENTIAL_BQ = "RESIDENTIAL_BQ" + RESIDENTIAL_BR = "RESIDENTIAL_BR" + RESIDENTIAL_BS = "RESIDENTIAL_BS" + RESIDENTIAL_BT = "RESIDENTIAL_BT" + RESIDENTIAL_BW = "RESIDENTIAL_BW" + RESIDENTIAL_BY = "RESIDENTIAL_BY" + RESIDENTIAL_BZ = "RESIDENTIAL_BZ" + RESIDENTIAL_CA = "RESIDENTIAL_CA" + RESIDENTIAL_CD = "RESIDENTIAL_CD" + RESIDENTIAL_CF = "RESIDENTIAL_CF" + RESIDENTIAL_CG = "RESIDENTIAL_CG" + RESIDENTIAL_CH = "RESIDENTIAL_CH" + RESIDENTIAL_CI = "RESIDENTIAL_CI" + RESIDENTIAL_CK = "RESIDENTIAL_CK" + RESIDENTIAL_CL = "RESIDENTIAL_CL" + RESIDENTIAL_CM = "RESIDENTIAL_CM" + RESIDENTIAL_CN = "RESIDENTIAL_CN" + RESIDENTIAL_CO = "RESIDENTIAL_CO" + RESIDENTIAL_CR = "RESIDENTIAL_CR" + RESIDENTIAL_CU = "RESIDENTIAL_CU" + RESIDENTIAL_CV = "RESIDENTIAL_CV" + RESIDENTIAL_CW = "RESIDENTIAL_CW" + RESIDENTIAL_CY = "RESIDENTIAL_CY" + RESIDENTIAL_CZ = "RESIDENTIAL_CZ" + RESIDENTIAL_DE = "RESIDENTIAL_DE" + RESIDENTIAL_DJ = "RESIDENTIAL_DJ" + RESIDENTIAL_DK = "RESIDENTIAL_DK" + RESIDENTIAL_DM = "RESIDENTIAL_DM" + RESIDENTIAL_DO = "RESIDENTIAL_DO" + RESIDENTIAL_DZ = "RESIDENTIAL_DZ" + RESIDENTIAL_EC = "RESIDENTIAL_EC" + RESIDENTIAL_EE = "RESIDENTIAL_EE" + RESIDENTIAL_EG = "RESIDENTIAL_EG" + RESIDENTIAL_ES = "RESIDENTIAL_ES" + RESIDENTIAL_ET = "RESIDENTIAL_ET" + RESIDENTIAL_FI = "RESIDENTIAL_FI" + RESIDENTIAL_FJ = "RESIDENTIAL_FJ" + RESIDENTIAL_FK = "RESIDENTIAL_FK" + RESIDENTIAL_FM = "RESIDENTIAL_FM" + RESIDENTIAL_FO = "RESIDENTIAL_FO" + RESIDENTIAL_FR = "RESIDENTIAL_FR" + RESIDENTIAL_GA = "RESIDENTIAL_GA" + RESIDENTIAL_GB = "RESIDENTIAL_GB" + RESIDENTIAL_GD = "RESIDENTIAL_GD" + RESIDENTIAL_GE = "RESIDENTIAL_GE" + RESIDENTIAL_GF = "RESIDENTIAL_GF" + RESIDENTIAL_GG = "RESIDENTIAL_GG" + RESIDENTIAL_GH = "RESIDENTIAL_GH" + RESIDENTIAL_GI = "RESIDENTIAL_GI" + RESIDENTIAL_GL = "RESIDENTIAL_GL" + RESIDENTIAL_GM = "RESIDENTIAL_GM" + RESIDENTIAL_GN = "RESIDENTIAL_GN" + RESIDENTIAL_GP = "RESIDENTIAL_GP" + RESIDENTIAL_GQ = "RESIDENTIAL_GQ" + RESIDENTIAL_GR = "RESIDENTIAL_GR" + RESIDENTIAL_GT = "RESIDENTIAL_GT" + RESIDENTIAL_GU = "RESIDENTIAL_GU" + RESIDENTIAL_GW = "RESIDENTIAL_GW" + RESIDENTIAL_GY = "RESIDENTIAL_GY" + RESIDENTIAL_HK = "RESIDENTIAL_HK" + RESIDENTIAL_HN = "RESIDENTIAL_HN" + RESIDENTIAL_HR = "RESIDENTIAL_HR" + RESIDENTIAL_HT = "RESIDENTIAL_HT" + RESIDENTIAL_HU = "RESIDENTIAL_HU" + RESIDENTIAL_ID = "RESIDENTIAL_ID" + RESIDENTIAL_IE = "RESIDENTIAL_IE" + RESIDENTIAL_IL = "RESIDENTIAL_IL" + RESIDENTIAL_IM = "RESIDENTIAL_IM" + RESIDENTIAL_IN = "RESIDENTIAL_IN" + RESIDENTIAL_IO = "RESIDENTIAL_IO" + RESIDENTIAL_IQ = "RESIDENTIAL_IQ" + RESIDENTIAL_IR = "RESIDENTIAL_IR" + RESIDENTIAL_IS = "RESIDENTIAL_IS" + RESIDENTIAL_IT = "RESIDENTIAL_IT" + RESIDENTIAL_JE = "RESIDENTIAL_JE" + RESIDENTIAL_JM = "RESIDENTIAL_JM" + RESIDENTIAL_JO = "RESIDENTIAL_JO" + RESIDENTIAL_JP = "RESIDENTIAL_JP" + RESIDENTIAL_KE = "RESIDENTIAL_KE" + RESIDENTIAL_KG = "RESIDENTIAL_KG" + RESIDENTIAL_KH = "RESIDENTIAL_KH" + RESIDENTIAL_KI = "RESIDENTIAL_KI" + RESIDENTIAL_KM = "RESIDENTIAL_KM" + RESIDENTIAL_KN = "RESIDENTIAL_KN" + RESIDENTIAL_KR = "RESIDENTIAL_KR" + RESIDENTIAL_KW = "RESIDENTIAL_KW" + RESIDENTIAL_KY = "RESIDENTIAL_KY" + RESIDENTIAL_KZ = "RESIDENTIAL_KZ" + RESIDENTIAL_LA = "RESIDENTIAL_LA" + RESIDENTIAL_LB = "RESIDENTIAL_LB" + RESIDENTIAL_LC = "RESIDENTIAL_LC" + RESIDENTIAL_LI = "RESIDENTIAL_LI" + RESIDENTIAL_LK = "RESIDENTIAL_LK" + RESIDENTIAL_LR = "RESIDENTIAL_LR" + RESIDENTIAL_LS = "RESIDENTIAL_LS" + RESIDENTIAL_LT = "RESIDENTIAL_LT" + RESIDENTIAL_LU = "RESIDENTIAL_LU" + RESIDENTIAL_LV = "RESIDENTIAL_LV" + RESIDENTIAL_LY = "RESIDENTIAL_LY" + RESIDENTIAL_MA = "RESIDENTIAL_MA" + RESIDENTIAL_MC = "RESIDENTIAL_MC" + RESIDENTIAL_MD = "RESIDENTIAL_MD" + RESIDENTIAL_ME = "RESIDENTIAL_ME" + RESIDENTIAL_MF = "RESIDENTIAL_MF" + RESIDENTIAL_MG = "RESIDENTIAL_MG" + RESIDENTIAL_MK = "RESIDENTIAL_MK" + RESIDENTIAL_ML = "RESIDENTIAL_ML" + RESIDENTIAL_MM = "RESIDENTIAL_MM" + RESIDENTIAL_MN = "RESIDENTIAL_MN" + RESIDENTIAL_MO = "RESIDENTIAL_MO" + RESIDENTIAL_MP = "RESIDENTIAL_MP" + RESIDENTIAL_MQ = "RESIDENTIAL_MQ" + RESIDENTIAL_MR = "RESIDENTIAL_MR" + RESIDENTIAL_MS = "RESIDENTIAL_MS" + RESIDENTIAL_MT = "RESIDENTIAL_MT" + RESIDENTIAL_MU = "RESIDENTIAL_MU" + RESIDENTIAL_MV = "RESIDENTIAL_MV" + RESIDENTIAL_MW = "RESIDENTIAL_MW" + RESIDENTIAL_MX = "RESIDENTIAL_MX" + RESIDENTIAL_MY = "RESIDENTIAL_MY" + RESIDENTIAL_MZ = "RESIDENTIAL_MZ" + RESIDENTIAL_NA = "RESIDENTIAL_NA" + RESIDENTIAL_NC = "RESIDENTIAL_NC" + RESIDENTIAL_NE = "RESIDENTIAL_NE" + RESIDENTIAL_NG = "RESIDENTIAL_NG" + RESIDENTIAL_NI = "RESIDENTIAL_NI" + RESIDENTIAL_NL = "RESIDENTIAL_NL" + RESIDENTIAL_NO = "RESIDENTIAL_NO" + RESIDENTIAL_NP = "RESIDENTIAL_NP" + RESIDENTIAL_NZ = "RESIDENTIAL_NZ" + RESIDENTIAL_OM = "RESIDENTIAL_OM" + RESIDENTIAL_PA = "RESIDENTIAL_PA" + RESIDENTIAL_PE = "RESIDENTIAL_PE" + RESIDENTIAL_PF = "RESIDENTIAL_PF" + RESIDENTIAL_PG = "RESIDENTIAL_PG" + RESIDENTIAL_PH = "RESIDENTIAL_PH" + RESIDENTIAL_PK = "RESIDENTIAL_PK" + RESIDENTIAL_PL = "RESIDENTIAL_PL" + RESIDENTIAL_PM = "RESIDENTIAL_PM" + RESIDENTIAL_PR = "RESIDENTIAL_PR" + RESIDENTIAL_PS = "RESIDENTIAL_PS" + RESIDENTIAL_PT = "RESIDENTIAL_PT" + RESIDENTIAL_PW = "RESIDENTIAL_PW" + RESIDENTIAL_PY = "RESIDENTIAL_PY" + RESIDENTIAL_QA = "RESIDENTIAL_QA" + RESIDENTIAL_RE = "RESIDENTIAL_RE" + RESIDENTIAL_RO = "RESIDENTIAL_RO" + RESIDENTIAL_RS = "RESIDENTIAL_RS" + RESIDENTIAL_RU = "RESIDENTIAL_RU" + RESIDENTIAL_RW = "RESIDENTIAL_RW" + RESIDENTIAL_SA = "RESIDENTIAL_SA" + RESIDENTIAL_SB = "RESIDENTIAL_SB" + RESIDENTIAL_SC = "RESIDENTIAL_SC" + RESIDENTIAL_SD = "RESIDENTIAL_SD" + RESIDENTIAL_SE = "RESIDENTIAL_SE" + RESIDENTIAL_SG = "RESIDENTIAL_SG" + RESIDENTIAL_SI = "RESIDENTIAL_SI" + RESIDENTIAL_SK = "RESIDENTIAL_SK" + RESIDENTIAL_SL = "RESIDENTIAL_SL" + RESIDENTIAL_SM = "RESIDENTIAL_SM" + RESIDENTIAL_SN = "RESIDENTIAL_SN" + RESIDENTIAL_SO = "RESIDENTIAL_SO" + RESIDENTIAL_SR = "RESIDENTIAL_SR" + RESIDENTIAL_SS = "RESIDENTIAL_SS" + RESIDENTIAL_ST = "RESIDENTIAL_ST" + RESIDENTIAL_SV = "RESIDENTIAL_SV" + RESIDENTIAL_SX = "RESIDENTIAL_SX" + RESIDENTIAL_SY = "RESIDENTIAL_SY" + RESIDENTIAL_SZ = "RESIDENTIAL_SZ" + RESIDENTIAL_TC = "RESIDENTIAL_TC" + RESIDENTIAL_TD = "RESIDENTIAL_TD" + RESIDENTIAL_TG = "RESIDENTIAL_TG" + RESIDENTIAL_TH = "RESIDENTIAL_TH" + RESIDENTIAL_TJ = "RESIDENTIAL_TJ" + RESIDENTIAL_TL = "RESIDENTIAL_TL" + RESIDENTIAL_TM = "RESIDENTIAL_TM" + RESIDENTIAL_TN = "RESIDENTIAL_TN" + RESIDENTIAL_TO = "RESIDENTIAL_TO" + RESIDENTIAL_TR = "RESIDENTIAL_TR" + RESIDENTIAL_TT = "RESIDENTIAL_TT" + RESIDENTIAL_TW = "RESIDENTIAL_TW" + RESIDENTIAL_TZ = "RESIDENTIAL_TZ" + RESIDENTIAL_UA = "RESIDENTIAL_UA" + RESIDENTIAL_UG = "RESIDENTIAL_UG" + RESIDENTIAL_UY = "RESIDENTIAL_UY" + RESIDENTIAL_UZ = "RESIDENTIAL_UZ" + RESIDENTIAL_VA = "RESIDENTIAL_VA" + RESIDENTIAL_VC = "RESIDENTIAL_VC" + RESIDENTIAL_VE = "RESIDENTIAL_VE" + RESIDENTIAL_VG = "RESIDENTIAL_VG" + RESIDENTIAL_VI = "RESIDENTIAL_VI" + RESIDENTIAL_VN = "RESIDENTIAL_VN" + RESIDENTIAL_VU = "RESIDENTIAL_VU" + RESIDENTIAL_WS = "RESIDENTIAL_WS" + RESIDENTIAL_XK = "RESIDENTIAL_XK" + RESIDENTIAL_YE = "RESIDENTIAL_YE" + RESIDENTIAL_YT = "RESIDENTIAL_YT" + RESIDENTIAL_ZA = "RESIDENTIAL_ZA" + RESIDENTIAL_ZM = "RESIDENTIAL_ZM" + RESIDENTIAL_ZW = "RESIDENTIAL_ZW" @staticmethod def get_zone(proxy_location: ProxyLocation) -> str: @@ -76,74 +292,25 @@ class ProxyLocation(StrEnum): @classmethod def residential_country_locations(cls) -> set[ProxyLocation]: - return { - cls.RESIDENTIAL, - cls.RESIDENTIAL_ES, - cls.RESIDENTIAL_IE, - cls.RESIDENTIAL_GB, - cls.RESIDENTIAL_IN, - cls.RESIDENTIAL_JP, - cls.RESIDENTIAL_FR, - cls.RESIDENTIAL_DE, - cls.RESIDENTIAL_NZ, - cls.RESIDENTIAL_ZA, - cls.RESIDENTIAL_AR, - cls.RESIDENTIAL_AU, - cls.RESIDENTIAL_BR, - cls.RESIDENTIAL_TR, - cls.RESIDENTIAL_CA, - cls.RESIDENTIAL_MX, - cls.RESIDENTIAL_IT, - cls.RESIDENTIAL_NL, - } + return set(_RESIDENTIAL_LOCATIONS_BY_ISO.values()) @staticmethod def get_proxy_count(proxy_location: ProxyLocation) -> int: - counts = { - ProxyLocation.RESIDENTIAL: 10000, - ProxyLocation.RESIDENTIAL_ES: 2000, - ProxyLocation.RESIDENTIAL_IE: 2000, - ProxyLocation.RESIDENTIAL_GB: 2000, - ProxyLocation.RESIDENTIAL_IN: 2000, - ProxyLocation.RESIDENTIAL_JP: 2000, - ProxyLocation.RESIDENTIAL_FR: 2000, - ProxyLocation.RESIDENTIAL_DE: 2000, - ProxyLocation.RESIDENTIAL_NZ: 2000, - ProxyLocation.RESIDENTIAL_ZA: 2000, - ProxyLocation.RESIDENTIAL_AR: 2000, - ProxyLocation.RESIDENTIAL_AU: 2000, - ProxyLocation.RESIDENTIAL_BR: 2000, - ProxyLocation.RESIDENTIAL_TR: 2000, - ProxyLocation.RESIDENTIAL_CA: 2000, - ProxyLocation.RESIDENTIAL_MX: 2000, - ProxyLocation.RESIDENTIAL_IT: 2000, - ProxyLocation.RESIDENTIAL_NL: 2000, - } - return counts.get(proxy_location, 10000) + iso_code = _ISO_BY_RESIDENTIAL_LOCATION.get(proxy_location) + if iso_code == "US": + return 10000 + if iso_code is not None: + return 2000 + return 10000 @staticmethod def get_country_code(proxy_location: ProxyLocation) -> str: - mapping = { - ProxyLocation.RESIDENTIAL: "US", - ProxyLocation.RESIDENTIAL_ES: "ES", - ProxyLocation.RESIDENTIAL_IE: "IE", - ProxyLocation.RESIDENTIAL_GB: "GB", - ProxyLocation.RESIDENTIAL_IN: "IN", - ProxyLocation.RESIDENTIAL_JP: "JP", - ProxyLocation.RESIDENTIAL_FR: "FR", - ProxyLocation.RESIDENTIAL_DE: "DE", - ProxyLocation.RESIDENTIAL_NZ: "NZ", - ProxyLocation.RESIDENTIAL_ZA: "ZA", - ProxyLocation.RESIDENTIAL_AR: "AR", - ProxyLocation.RESIDENTIAL_AU: "AU", - ProxyLocation.RESIDENTIAL_BR: "BR", - ProxyLocation.RESIDENTIAL_TR: "TR", - ProxyLocation.RESIDENTIAL_CA: "CA", - ProxyLocation.RESIDENTIAL_MX: "MX", - ProxyLocation.RESIDENTIAL_IT: "IT", - ProxyLocation.RESIDENTIAL_NL: "NL", - } - return mapping.get(proxy_location, "US") + return _ISO_BY_RESIDENTIAL_LOCATION.get(proxy_location, "US") + + +_RESIDENTIAL_LOCATIONS_BY_ISO = build_residential_locations_by_iso(ProxyLocation) +_ISO_BY_RESIDENTIAL_LOCATION = build_iso_by_residential_location(_RESIDENTIAL_LOCATIONS_BY_ISO) +_TZINFO_BY_RESIDENTIAL_LOCATION = build_tzinfo_by_residential_location(_RESIDENTIAL_LOCATIONS_BY_ISO) def get_tzinfo_from_proxy(proxy_location: ProxyLocation) -> ZoneInfo | None: @@ -168,60 +335,13 @@ def get_tzinfo_from_proxy(proxy_location: ProxyLocation) -> ZoneInfo | None: if proxy_location == ProxyLocation.RESIDENTIAL: return ZoneInfo("America/New_York") - if proxy_location == ProxyLocation.RESIDENTIAL_ES: - return ZoneInfo("Europe/Madrid") - - if proxy_location == ProxyLocation.RESIDENTIAL_IE: - return ZoneInfo("Europe/Dublin") - - if proxy_location == ProxyLocation.RESIDENTIAL_GB: - return ZoneInfo("Europe/London") - - if proxy_location == ProxyLocation.RESIDENTIAL_IN: - return ZoneInfo("Asia/Kolkata") - - if proxy_location == ProxyLocation.RESIDENTIAL_JP: - return ZoneInfo("Asia/Tokyo") - - if proxy_location == ProxyLocation.RESIDENTIAL_FR: - return ZoneInfo("Europe/Paris") - - if proxy_location == ProxyLocation.RESIDENTIAL_DE: - return ZoneInfo("Europe/Berlin") - - if proxy_location == ProxyLocation.RESIDENTIAL_NZ: - return ZoneInfo("Pacific/Auckland") - - if proxy_location == ProxyLocation.RESIDENTIAL_ZA: - return ZoneInfo("Africa/Johannesburg") - - if proxy_location == ProxyLocation.RESIDENTIAL_AR: - return ZoneInfo("America/Argentina/Buenos_Aires") - - if proxy_location == ProxyLocation.RESIDENTIAL_AU: - return ZoneInfo("Australia/Sydney") - - if proxy_location == ProxyLocation.RESIDENTIAL_BR: - return ZoneInfo("America/Sao_Paulo") - - if proxy_location == ProxyLocation.RESIDENTIAL_TR: - return ZoneInfo("Europe/Istanbul") - - if proxy_location == ProxyLocation.RESIDENTIAL_CA: - return ZoneInfo("America/Toronto") - - if proxy_location == ProxyLocation.RESIDENTIAL_MX: - return ZoneInfo("America/Mexico_City") - - if proxy_location == ProxyLocation.RESIDENTIAL_IT: - return ZoneInfo("Europe/Rome") - - if proxy_location == ProxyLocation.RESIDENTIAL_NL: - return ZoneInfo("Europe/Amsterdam") - if proxy_location == ProxyLocation.RESIDENTIAL_ISP: return ZoneInfo("America/New_York") + tzinfo = _TZINFO_BY_RESIDENTIAL_LOCATION.get(proxy_location) + if tzinfo is not None: + return tzinfo + return None