215 lines
8.9 KiB
Python
215 lines
8.9 KiB
Python
"""
|
|
|
|
AUTHOR:
|
|
|
|
Khushal P Soonderji
|
|
|
|
DATE:
|
|
|
|
Monday, 9th Dec., 2024
|
|
|
|
OBJECTIVE:
|
|
|
|
To send SMS from clients like Nimbus SMS (India) and Savvy Bulk SMS (Kenya).
|
|
|
|
REFERENCES:
|
|
|
|
N/A
|
|
|
|
DOWNLOADS:
|
|
|
|
N/A
|
|
|
|
"""
|
|
|
|
# *****************************************************************************************************************
|
|
# ***** ****
|
|
# *** IMPORT ***
|
|
# ***** ****
|
|
# *****************************************************************************************************************
|
|
|
|
|
|
# To make sibling directories accessible for imports:
|
|
import sys
|
|
sys.path.append(".")
|
|
sys.path.append("..")
|
|
|
|
# My async utils:
|
|
from utils_v2.string import json
|
|
from utils_v2.date_time import date_time
|
|
from utils_v2.database.async_mysql_v2 import AsyncMySQL
|
|
from utils_v2.database.async_mongo_v2 import AsyncMongo
|
|
|
|
# SMS-related utils:
|
|
from utils_v2.sms.models.behaviour.nimbus.async_nimbus import AsyncNimbusSMS
|
|
from utils_v2.sms.models.behaviour.savvy_bulk_sms.async_savvy_bulk_sms import AsyncSavvyBulkSMS
|
|
|
|
# Base model:
|
|
from models.behaviour.base import BaseModel
|
|
|
|
# Data models:
|
|
from models.data.core.auth_token import CoreAuthTokenModel
|
|
from models.data.core.message import CoreMessageModel
|
|
from models.data.api.sms.send import (
|
|
SMSSendRequestHeaders,
|
|
SMSSendRequestData,
|
|
NimbusSMSIndiaMessage,
|
|
SavvyBulkSMSKenyaMessage
|
|
)
|
|
from utils_v2.sms.models.data.sms_message import SentSMSMessageModel
|
|
|
|
# To work with MongoDB:
|
|
from bson import ObjectId
|
|
|
|
# To work with datatypes:
|
|
from typing import Literal
|
|
|
|
# To make deep-copies:
|
|
import copy
|
|
|
|
|
|
# *****************************************************************************************************************
|
|
# ***** ****
|
|
# *** MACROS / ONE-TIME INIT ***
|
|
# ***** ****
|
|
# *****************************************************************************************************************
|
|
|
|
|
|
# --- Nothing Yet
|
|
|
|
|
|
# *****************************************************************************************************************
|
|
# ***** ****
|
|
# *** VARIABLES ***
|
|
# ***** ****
|
|
# *****************************************************************************************************************
|
|
|
|
|
|
# --- Nothing Yet
|
|
|
|
|
|
# *****************************************************************************************************************
|
|
# ***** ****
|
|
# *** FUNCTIONS ***
|
|
# ***** ****
|
|
# *****************************************************************************************************************
|
|
|
|
|
|
# --- Nothing Yet
|
|
|
|
|
|
# *****************************************************************************************************************
|
|
# ***** ****
|
|
# *** CLASSES ***
|
|
# ***** ****
|
|
# *****************************************************************************************************************
|
|
|
|
|
|
class SMSSendModel(BaseModel):
|
|
|
|
MESSAGES_COLLECTION = "_messages"
|
|
|
|
async def send_sms(
|
|
self,
|
|
mongo_conn: AsyncMongo,
|
|
token_id: ObjectId | str,
|
|
auth_token: CoreAuthTokenModel,
|
|
inbound_data: SMSSendRequestData,
|
|
session_token: str = None
|
|
) -> SentSMSMessageModel:
|
|
|
|
"""
|
|
To store auth/tokens for a particular service to the database.
|
|
:param mongo_conn: The database connection (MongoDB) to use to perform the action.
|
|
:param auth_token: An instance of the core auth-token model that holds data in the database.
|
|
:param session_token: The session token of the user who requested this service.
|
|
:return: An ObjectId to later store the granted tokens.
|
|
"""
|
|
|
|
# Basic prep:
|
|
event_ts = date_time.get_current_utc_date_time(as_string = False)
|
|
client_response = None
|
|
message_id = None
|
|
sms_sent = None
|
|
|
|
# ┏┓ ┳┓• ┓ ┏┓┳┳┓┏┓ ┳ ┓•
|
|
# ┣ ┏┓┏┓ ┃┃┓┏┳┓┣┓┓┏┏ ┗┓┃┃┃┗┓ ┃┏┓┏┫┓┏┓
|
|
# ┻ ┗┛┛ ┛┗┗┛┗┗┗┛┗┻┛ ┗┛┛ ┗┗┛ ┻┛┗┗┻┗┗┻
|
|
|
|
if isinstance(inbound_data.message, NimbusSMSIndiaMessage):
|
|
|
|
# Prepare the client:
|
|
sms_client = AsyncNimbusSMS(
|
|
entity_id = auth_token.auth.get("entityId"),
|
|
sender_id = auth_token.auth.get("senderId"),
|
|
user_id = auth_token.auth.get("userId"),
|
|
api_key = auth_token.auth.get("apiKey"),
|
|
http_client = self._http_client
|
|
)
|
|
|
|
# Send the SMS:
|
|
client_response = await sms_client.send_sms(
|
|
recipient_number = inbound_data.message.recipientNo,
|
|
message = inbound_data.message.text,
|
|
template_id = inbound_data.message.templateId
|
|
)
|
|
|
|
# ┏┓ ┏┓ ┳┓ ┓┓ ┏┓┳┳┓┏┓ ┓┏┓
|
|
# ┣ ┏┓┏┓ ┗┓┏┓┓┏┓┏┓┏ ┣┫┓┏┃┃┏ ┗┓┃┃┃┗┓ ┃┫ ┏┓┏┓┓┏┏┓
|
|
# ┻ ┗┛┛ ┗┛┗┻┗┛┗┛┗┫ ┻┛┗┻┗┛┗ ┗┛┛ ┗┗┛ ┛┗┛┗ ┛┗┗┫┗┻
|
|
# ┛ ┛
|
|
|
|
elif isinstance(inbound_data.message, SavvyBulkSMSKenyaMessage):
|
|
|
|
# Prepare the client:
|
|
sms_client = AsyncSavvyBulkSMS(
|
|
api_key = auth_token.auth.get("apiKey"),
|
|
partner_id = auth_token.auth.get("partnerId"),
|
|
short_code = auth_token.auth.get("shortCode"),
|
|
http_client = self._http_client
|
|
)
|
|
|
|
# Send the SMS:
|
|
client_response = await sms_client.send_sms(
|
|
recipient_number = inbound_data.message.recipientNo,
|
|
message = inbound_data.message.text
|
|
)
|
|
|
|
# ┏┓ ┏┳┓┓ ┳┳┓
|
|
# ┗┓┏┓┓┏┏┓ ┃ ┣┓┏┓ ┃┃┃┏┓┏┏┏┓┏┓┏┓
|
|
# ┗┛┗┻┗┛┗ ┻ ┛┗┗ ┛ ┗┗ ┛┛┗┻┗┫┗
|
|
# ┛
|
|
|
|
# Save the message:
|
|
if client_response:
|
|
message_id = await mongo_conn.insert_one(
|
|
collection = self.MESSAGES_COLLECTION,
|
|
document = CoreMessageModel(
|
|
ts = event_ts,
|
|
readTs = event_ts,
|
|
tokenId = ObjectId(token_id),
|
|
serviceType = auth_token.serviceType,
|
|
client = auth_token.client,
|
|
clientMessageId = client_response.messageId,
|
|
clientThreadId = None,
|
|
isInward = False,
|
|
sentSuccessfully = client_response.success,
|
|
payload = client_response.model_dump()
|
|
).model_dump()
|
|
)
|
|
|
|
# Done here:
|
|
return client_response
|
|
|
|
|
|
# *****************************************************************************************************************
|
|
# ***** ****
|
|
# *** MAIN PROGRAM ***
|
|
# ***** ****
|
|
# *****************************************************************************************************************
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
pass
|