Skip to content

Commit 8993f1d

Browse files
authored
Merge pull request #94 from smswithoutborders/staging
Staging
2 parents d64d69e + dca9626 commit 8993f1d

3 files changed

Lines changed: 70 additions & 3 deletions

File tree

notification_dispatcher.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@
88
import threading
99
import sentry_sdk
1010
from logutils import get_logger
11-
from sms_outbound import send_with_twilio
11+
from sms_outbound import (
12+
send_with_twilio,
13+
send_with_queuedroid,
14+
get_phonenumber_region_code,
15+
QUEUEDROID_SUPPORTED_REGION_CODES,
16+
)
1217
from publications import create_publication_entry
1318

1419
logger = get_logger(__name__)
@@ -24,7 +29,11 @@ def send_sms_notification(phone_number: str, message: str):
2429
Returns:
2530
bool: True if sent successfully, False otherwise.
2631
"""
27-
send_with_twilio(phone_number, message)
32+
region_code = get_phonenumber_region_code(phone_number)
33+
if region_code not in QUEUEDROID_SUPPORTED_REGION_CODES:
34+
return send_with_twilio(phone_number, message)
35+
36+
return send_with_queuedroid(phone_number, message)
2837

2938

3039
def send_event(

requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ grpcio==1.74.0
55
grpcio-testing==1.74.0
66
grpcio-tools==1.74.0
77
peewee>=3.17.8
8+
phonenumbers==9.0.11
89
pymysql==1.1.1
10+
requests==2.32.3
911
sentry-sdk[grpcio]==2.34.1
1012
tqdm==4.67.1
1113
twilio==9.7.0

sms_outbound.py

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
Public License was not distributed with this file, see <https://www.gnu.org/licenses/>.
55
"""
66

7+
import requests
8+
import phonenumbers
9+
from phonenumbers import geocoder
710
from twilio.rest import Client
811
from twilio.base.exceptions import TwilioRestException
912
from utils import get_configs
@@ -14,6 +17,13 @@
1417
TWILIO_SERVICE_SID = get_configs("TWILIO_SERVICE_SID")
1518
TWILIO_PHONE_NUMBER = get_configs("TWILIO_PHONE_NUMBER")
1619

20+
QUEUEDROID_API_URL = get_configs(
21+
"QUEUEDROID_API_URL", default_value="https://api.queuedroid.com/v1/messages/send"
22+
)
23+
QUEUEDROID_API_KEY = get_configs("QUEUEDROID_API_KEY")
24+
QUEUEDROID_EXCHANGE_ID = get_configs("QUEUEDROID_EXCHANGE_ID")
25+
QUEUEDROID_SUPPORTED_REGION_CODES = get_configs("QUEUEDROID_SUPPORTED_REGION_CODES")
26+
1727
logger = get_logger(__name__)
1828

1929

@@ -37,7 +47,7 @@ def send_with_twilio(phone_number: str, message: str) -> bool:
3747
status = message_response.status
3848

3949
if status in ("accepted", "pending", "queued"):
40-
logger.info("Message sent successfully.")
50+
logger.info("Message sent successfully via Twilio.")
4151
return True
4252

4353
logger.error("Failed to send message. Twilio status: %s", status)
@@ -46,3 +56,49 @@ def send_with_twilio(phone_number: str, message: str) -> bool:
4656
except TwilioRestException as exc:
4757
logger.error("Error sending message with Twilio: %s", exc)
4858
return False
59+
60+
61+
def send_with_queuedroid(phone_number: str, message: str) -> bool:
62+
"""
63+
Sends a message using Queuedroid to a specified phone number.
64+
65+
Args:
66+
phone_number (str): The recipient's phone number in E.164 format (e.g., +237123456789).
67+
message (str): The content to be sent to the specified phone number.
68+
69+
Returns:
70+
bool: True if the message was sent successfully, False otherwise.
71+
"""
72+
try:
73+
data = {
74+
"content": message,
75+
"exchange_id": QUEUEDROID_EXCHANGE_ID,
76+
"phone_number": phone_number,
77+
}
78+
headers = {"Authorization": f"Bearer {QUEUEDROID_API_KEY}"}
79+
response = requests.post(
80+
QUEUEDROID_API_URL, json=data, headers=headers, timeout=10
81+
)
82+
83+
if response.ok:
84+
logger.info("Message sent successfully via Queuedroid.")
85+
return True
86+
response.raise_for_status()
87+
return False
88+
except requests.RequestException as exc:
89+
logger.exception("Error sending message via Queuedroid: %s", exc)
90+
return False
91+
92+
93+
def get_phonenumber_region_code(phone_number: str) -> str:
94+
"""
95+
Get the region code for a given phone number.
96+
97+
Args:
98+
phone_number (str): The phone number in E.164 format.
99+
100+
Returns:
101+
str: The ISO 3166-1 alpha-2 region code corresponding to the phone number.
102+
"""
103+
parsed_number = phonenumbers.parse(phone_number)
104+
return geocoder.region_code_for_number(parsed_number)

0 commit comments

Comments
 (0)