From c1212bbc60d18f4f036150a8fc9f55167d536fb7 Mon Sep 17 00:00:00 2001 From: John Whitlock Date: Thu, 25 Jul 2024 11:19:18 -0500 Subject: [PATCH 1/2] Add Puerto Rico to supported regions --- api/tests/phones_views_tests.py | 4 ++-- api/views/phones.py | 10 ++++++---- phones/models.py | 15 ++++++++------- privaterelay/plans.py | 12 ++++++++++-- privaterelay/settings.py | 6 +++++- 5 files changed, 31 insertions(+), 16 deletions(-) diff --git a/api/tests/phones_views_tests.py b/api/tests/phones_views_tests.py index ce566bab88..2d2e2971f6 100644 --- a/api/tests/phones_views_tests.py +++ b/api/tests/phones_views_tests.py @@ -286,8 +286,8 @@ def test_realphone_post_valid_e164_number_in_unsupported_country( response = client.post(path, data, format="json", HTTP_X_CLIENT_REGION="nl") assert response.status_code == 400 expected = [ - "Relay Phone is currently only available for these country codes: ['CA', 'US']." - " Your phone number country code is: 'NL'." + "Relay Phone is currently only available for these country codes:" + " ['CA', 'PR', 'US']. Your phone number country code is: 'NL'." ] assert response.json() == expected diff --git a/api/views/phones.py b/api/views/phones.py index bb0856d8ed..ac08c8fda5 100644 --- a/api/views/phones.py +++ b/api/views/phones.py @@ -41,6 +41,7 @@ from phones.apps import phones_config, twilio_client from phones.iq_utils import send_iq_sms from phones.models import ( + DEFAULT_REGION, InboundContact, RealPhone, RelayNumber, @@ -430,7 +431,7 @@ def search(self, request): if real_phone: country_code = real_phone.country_code else: - country_code = "US" + country_code = DEFAULT_REGION location = request.query_params.get("location") if location is not None: numbers = location_numbers(location, country_code) @@ -798,12 +799,13 @@ def inbound_sms_iq(request: Request) -> response.Response: raise exceptions.ValidationError("Request missing from, to, or text.") from_num = phonenumbers.format_number( - phonenumbers.parse(inbound_from, "US"), + phonenumbers.parse(inbound_from, DEFAULT_REGION), phonenumbers.PhoneNumberFormat.E164, ) single_num = inbound_to[0] relay_num = phonenumbers.format_number( - phonenumbers.parse(single_num, "US"), phonenumbers.PhoneNumberFormat.E164 + phonenumbers.parse(single_num, DEFAULT_REGION), + phonenumbers.PhoneNumberFormat.E164, ) relay_number, real_phone = _get_phone_objects(relay_num) @@ -1539,7 +1541,7 @@ def _match_senders_by_prefix(relay_number: RelayNumber, text: str) -> MatchData contacts_by_number: dict[str, InboundContact] = {} for contact in contacts: # TODO: don't default to US when we support other regions - pn = phonenumbers.parse(contact.inbound_number, "US") + pn = phonenumbers.parse(contact.inbound_number, DEFAULT_REGION) e164 = phonenumbers.format_number(pn, phonenumbers.PhoneNumberFormat.E164) if e164 not in contacts_by_number: contacts_by_number[e164] = contact diff --git a/phones/models.py b/phones/models.py index fe32b2ba65..c4696c9b09 100644 --- a/phones/models.py +++ b/phones/models.py @@ -35,6 +35,7 @@ ("call", "call"), ("text", "text"), ] +DEFAULT_REGION = "US" def verification_code_default(): @@ -137,7 +138,7 @@ class RealPhone(models.Model): ) verified = models.BooleanField(default=False) verified_date = models.DateTimeField(blank=True, null=True) - country_code = models.CharField(max_length=2, default="US") + country_code = models.CharField(max_length=2, default=DEFAULT_REGION) class Meta: constraints = [ @@ -220,7 +221,7 @@ class RelayNumber(models.Model): number = models.CharField(max_length=15, db_index=True, unique=True) vendor = models.CharField(max_length=15, default="twilio") location = models.CharField(max_length=255) - country_code = models.CharField(max_length=2, default="US") + country_code = models.CharField(max_length=2, default=DEFAULT_REGION) vcard_lookup_key = models.CharField( max_length=6, default=vcard_lookup_key_default, unique=True ) @@ -291,9 +292,9 @@ def save(self, *args, **kwargs): # as realphone self.country_code = realphone.country_code.upper() - # Add US numbers to the Relay messaging service, so it goes into our - # US A2P 10DLC campaign - if use_twilio and self.country_code == "US": + # Add numbers to the Relay messaging service, so it goes into our + # US A2P 10DLC campaigns + if use_twilio and self.country_code in settings.TWILIO_NEEDS_10DLC_CAMPAIGN: if settings.TWILIO_MESSAGING_SERVICE_SID: register_with_messaging_service(client, twilio_incoming_number.sid) else: @@ -495,14 +496,14 @@ def suggested_numbers(user): } -def location_numbers(location, country_code="US"): +def location_numbers(location, country_code=DEFAULT_REGION): client = twilio_client() avail_nums = client.available_phone_numbers(country_code) twilio_nums = avail_nums.local.list(in_locality=location, limit=10) return convert_twilio_numbers_to_dict(twilio_nums) -def area_code_numbers(area_code, country_code="US"): +def area_code_numbers(area_code, country_code=DEFAULT_REGION): client = twilio_client() avail_nums = client.available_phone_numbers(country_code) twilio_nums = avail_nums.local.list(area_code=area_code, limit=10) diff --git a/privaterelay/plans.py b/privaterelay/plans.py index ed0a713058..9d65c59438 100644 --- a/privaterelay/plans.py +++ b/privaterelay/plans.py @@ -127,6 +127,7 @@ "NL", # Netherlands "NZ", # New Zealand "PL", # Poland + "PR", # Puerto Rico "PT", # Portugal "RO", # Romania "SE", # Sweden @@ -493,6 +494,7 @@ class _RelayPlansByType(TypedDict, total=False): "CA": "US", # Canada -> United States "MY": "GB", # Malaysia -> United Kingdom "NZ": "GB", # New Zealand -> United Kingdom + "PR": "US", # Puerto Rico -> United States "SG": "GB", # Singapore -> United Kingdom }, "by_country_and_lang": { @@ -510,11 +512,17 @@ class _RelayPlansByType(TypedDict, total=False): }, "phones": { "by_country": ["US"], # United States - "by_country_override": {"CA": "US"}, # Canada -> United States + "by_country_override": { + "CA": "US", # Canada -> United States + "PR": "US", # Puerto Rico -> United States + }, }, "bundle": { "by_country": ["US"], # United States - "by_country_override": {"CA": "US"}, # Canada -> United States + "by_country_override": { + "CA": "US", # Canada -> United States + "PR": "US", # Puerto Rico -> United States + }, }, } diff --git a/privaterelay/settings.py b/privaterelay/settings.py index efe0db2177..1904fdd37c 100644 --- a/privaterelay/settings.py +++ b/privaterelay/settings.py @@ -282,7 +282,11 @@ TWILIO_TEST_ACCOUNT_SID: str | None = config("TWILIO_TEST_ACCOUNT_SID", None) TWILIO_TEST_AUTH_TOKEN: str | None = config("TWILIO_TEST_AUTH_TOKEN", None) TWILIO_ALLOWED_COUNTRY_CODES = { - code.upper() for code in config("TWILIO_ALLOWED_COUNTRY_CODES", "US,CA", cast=Csv()) + code.upper() + for code in config("TWILIO_ALLOWED_COUNTRY_CODES", "US,CA,PR", cast=Csv()) +} +TWILIO_NEEDS_10DLC_CAMPAIGN = { + code.upper() for code in config("TWILIO_NEEDS_10DLC_CAMPAIGN", "US,PR", cast=Csv()) } MAX_MINUTES_TO_VERIFY_REAL_PHONE: int = config( "MAX_MINUTES_TO_VERIFY_REAL_PHONE", 5, cast=int From 21e83265a535c96ca9153abb25033159ce8370c9 Mon Sep 17 00:00:00 2001 From: John Whitlock Date: Thu, 25 Jul 2024 15:43:07 -0500 Subject: [PATCH 2/2] Drop "US" from A2P 10DLC campaigns With PR, these are no longer US-only. Co-authored-by: luke crouch --- phones/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phones/models.py b/phones/models.py index c4696c9b09..6be6aa17af 100644 --- a/phones/models.py +++ b/phones/models.py @@ -293,7 +293,7 @@ def save(self, *args, **kwargs): self.country_code = realphone.country_code.upper() # Add numbers to the Relay messaging service, so it goes into our - # US A2P 10DLC campaigns + # A2P 10DLC campaigns if use_twilio and self.country_code in settings.TWILIO_NEEDS_10DLC_CAMPAIGN: if settings.TWILIO_MESSAGING_SERVICE_SID: register_with_messaging_service(client, twilio_incoming_number.sid)