(20241209) Many changes to the SMS section.
This commit is contained in:
+32
-37
@@ -43,6 +43,9 @@ sys.path.append("..")
|
||||
# To make API Calls:
|
||||
import httpx
|
||||
|
||||
# Data models:
|
||||
from utils_v2.sms.models.data.sms_message import SentSMSMessageModel
|
||||
|
||||
# For debugging:
|
||||
from icecream import IceCreamDebugger
|
||||
|
||||
@@ -172,12 +175,12 @@ class AsyncNimbusSMS:
|
||||
|
||||
async def send_sms(
|
||||
self,
|
||||
template_id,
|
||||
recipient_number,
|
||||
message,
|
||||
message_type = MESSAGE_TYPE_REGULAR,
|
||||
flash = MESSAGE_TYPE_NOT_FLASH
|
||||
):
|
||||
template_id: str,
|
||||
recipient_number: str,
|
||||
message: str,
|
||||
message_type: int = MESSAGE_TYPE_REGULAR,
|
||||
flash: int = MESSAGE_TYPE_NOT_FLASH
|
||||
) -> SentSMSMessageModel:
|
||||
|
||||
"""
|
||||
Sends one SMS through Nimbus IT's system. The text of the message must match the template that had been
|
||||
@@ -195,17 +198,14 @@ class AsyncNimbusSMS:
|
||||
"""
|
||||
|
||||
# Construct the basic structure of the response of this method:
|
||||
summary = {
|
||||
"success": False,
|
||||
"info": None,
|
||||
"sender": self.__sender_id,
|
||||
"recipient": recipient_number,
|
||||
"message": message,
|
||||
"length": len(message),
|
||||
"template_id": template_id,
|
||||
"raw": None,
|
||||
"isFlash": True if flash else False
|
||||
}
|
||||
summary = SentSMSMessageModel(
|
||||
sender = {"senderId": self.__sender_id},
|
||||
recipient = {"recipientNo": recipient_number},
|
||||
text = message,
|
||||
length = len(message),
|
||||
isFlash = True if flash else False,
|
||||
metadata = {"templateId": template_id}
|
||||
)
|
||||
|
||||
try:
|
||||
|
||||
@@ -231,18 +231,13 @@ class AsyncNimbusSMS:
|
||||
# For a successful API call:
|
||||
if response.status_code == 200:
|
||||
response_json = response.json()
|
||||
summary["success"] = True if response_json.get("STATUS", "ERROR").lower() in ["ok"] else False
|
||||
summary["info"] = response_json.get("RESPONSE", {}).get("INFO")
|
||||
summary["raw"] = {
|
||||
"http_code": response.status_code,
|
||||
"response": response_json,
|
||||
}
|
||||
summary.rawResponse = response_json
|
||||
summary.success = True if response_json.get("STATUS", "ERROR").lower() in ["ok"] else False
|
||||
if summary.success: summary.messageId = response_json.get("RESPONSE", {}).get("UID")
|
||||
else: summary.brief = response_json.get("RESPONSE", {}).get("INFO")
|
||||
|
||||
# For any other code that indicates some form of failure:
|
||||
else: summary["raw"] = {
|
||||
"http_code": response.status_code,
|
||||
"response": response.content.decode()
|
||||
}
|
||||
else: summary.rawResponse = response.content.decode()
|
||||
|
||||
except Exception as exception:
|
||||
self.__printer(exception)
|
||||
@@ -263,21 +258,21 @@ if __name__ == "__main__":
|
||||
|
||||
async def main():
|
||||
|
||||
sender = AsyncNimbusSMS(
|
||||
entity_id = "<your_entity_id>",
|
||||
sender_id = "<your_sender_id>",
|
||||
user_id = "<your_nimbus_user_id>",
|
||||
api_key = "<your_nimbus_api_key>"
|
||||
client = AsyncNimbusSMS(
|
||||
entity_id = "1701172465456946915",
|
||||
sender_id = "TCAOFF",
|
||||
user_id = "210844",
|
||||
api_key = "92UnZwiiY7zps"
|
||||
)
|
||||
|
||||
response = await sender.send_sms(
|
||||
template_id = "<your_sms_template_id>",
|
||||
recipient_number = "<the_number_you_want_to_send_the_message_to>",
|
||||
message = "<your_sms_message>"
|
||||
response = await client.send_sms(
|
||||
template_id = "1707172474709021546",
|
||||
recipient_number = "987039115511",
|
||||
message = "OTP for The CA Office registration request is 583920. Please enter this to verify your identity and proceed with the registration request. - TCAOFF"
|
||||
)
|
||||
print("SMS API RESPONSE:", response)
|
||||
|
||||
my_balance = await sender.get_balance()
|
||||
my_balance = await client.get_balance()
|
||||
print("REMAINING BALANCE:", my_balance)
|
||||
|
||||
|
||||
+25
-24
@@ -42,6 +42,9 @@ sys.path.append("..")
|
||||
# To make API Calls:
|
||||
import httpx
|
||||
|
||||
# Data models:
|
||||
from utils_v2.sms.models.data.sms_message import SentSMSMessageModel
|
||||
|
||||
# For debugging:
|
||||
from icecream import IceCreamDebugger
|
||||
|
||||
@@ -149,18 +152,19 @@ class AsyncSavvyBulkSMS:
|
||||
"""
|
||||
|
||||
# Construct the basic structure of the response of this method:
|
||||
summary = {
|
||||
"success": False,
|
||||
"info": None,
|
||||
"sender": {
|
||||
summary = SentSMSMessageModel(
|
||||
sender = {
|
||||
"partnerId": self.__partner_id,
|
||||
"shortCode": self.__short_code
|
||||
},
|
||||
"recipient": recipient_number,
|
||||
"message": message,
|
||||
"length": len(message),
|
||||
"raw": None,
|
||||
}
|
||||
recipient = {
|
||||
"recipientNo": recipient_number
|
||||
},
|
||||
text = message,
|
||||
length = len(message),
|
||||
isFlash = False,
|
||||
metadata = None
|
||||
)
|
||||
|
||||
try:
|
||||
|
||||
@@ -179,18 +183,15 @@ class AsyncSavvyBulkSMS:
|
||||
# For a successful API call:
|
||||
if api_response.status_code in [200]:
|
||||
api_json = api_response.json()
|
||||
first_desc = api_json.get("responses", [{}])[0].get("response-description", "N/A").lower().strip()
|
||||
summary["success"] = True if first_desc == "success" else False
|
||||
summary["raw"] = {
|
||||
"http_code": api_response.status_code,
|
||||
"response": api_json,
|
||||
}
|
||||
summary.rawResponse = api_json
|
||||
first_response = api_json.get("responses", [{}])[0]
|
||||
first_desc = first_response.get("response-description", "N/A").lower().strip()
|
||||
summary.success = True if first_desc == "success" else False
|
||||
if summary.success: summary.messageId = first_response.get("messageid")
|
||||
else: summary.brief = first_response.get("response-description")
|
||||
|
||||
# For any other code that indicates some form of failure:
|
||||
else: summary["raw"] = {
|
||||
"http_code": api_response.status_code,
|
||||
"response": api_response.content.decode()
|
||||
}
|
||||
else: summary.rawResponse = api_response.content.decode()
|
||||
|
||||
# If something goes wrong along the way:
|
||||
except Exception as exception:
|
||||
@@ -214,14 +215,14 @@ if __name__ == "__main__":
|
||||
async def main():
|
||||
|
||||
sender = AsyncSavvyBulkSMS(
|
||||
api_key = "<your_api_key>",
|
||||
partner_id = "<your_partner_id>",
|
||||
short_code = "<your_short_code>"
|
||||
api_key = "19250bdd74050f7cec980c71e75f851a",
|
||||
partner_id = "7462",
|
||||
short_code = "HTL TV-NET"
|
||||
)
|
||||
|
||||
response = await sender.send_sms(
|
||||
recipient_number = "<target_recipient>",
|
||||
message = "<message_for_recipient>"
|
||||
recipient_number = "254748877373 123",
|
||||
message = "Test 123"
|
||||
)
|
||||
print("SMS API RESPONSE:", response)
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
"""
|
||||
|
||||
AUTHOR:
|
||||
|
||||
Khushal P Soonderji
|
||||
|
||||
DATE:
|
||||
|
||||
Monday, 9th Dec., 2024.
|
||||
|
||||
OBJECTIVE:
|
||||
|
||||
To define how messages will be stored in the database.
|
||||
|
||||
REFERENCES:
|
||||
|
||||
N/A
|
||||
|
||||
DOWNLOADS:
|
||||
|
||||
N/A
|
||||
|
||||
"""
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** IMPORT ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# To make sibling directories accessible for imports:
|
||||
import sys
|
||||
sys.path.append(".")
|
||||
sys.path.append("..")
|
||||
|
||||
# For making data behaviour_models:
|
||||
from pydantic import BaseModel, Field, field_validator, PastDatetime, AwareDatetime
|
||||
from typing import Optional, Literal, Union, Any
|
||||
|
||||
# My utils:
|
||||
from utils_v2.string import regex
|
||||
from utils_v2.date_time import date_time
|
||||
|
||||
# To work with MongoDB:
|
||||
from bson.objectid import ObjectId
|
||||
|
||||
# To work with date and time:
|
||||
import datetime
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** MACROS / ONE-TIME INIT ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# --- Nothing Yet
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** VARIABLES ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# --- Nothing Yet
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** FUNCTIONS ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
class SentSMSMessageModel(BaseModel):
|
||||
|
||||
ts: AwareDatetime = Field(
|
||||
description = "the time (utc) at which this message was sent by the sender",
|
||||
frozen = True,
|
||||
default_factory = lambda: date_time.get_current_utc_date_time(as_string = False)
|
||||
)
|
||||
|
||||
sender: dict = Field(
|
||||
description = "the sender of this message",
|
||||
frozen = True
|
||||
)
|
||||
|
||||
recipient: dict = Field(
|
||||
description = "the recipient of this message",
|
||||
frozen = True
|
||||
)
|
||||
|
||||
text: str = Field(
|
||||
description = "the actual text that was sent",
|
||||
frozen = True
|
||||
)
|
||||
|
||||
length: int = Field(
|
||||
description = "the no. of chars in this message",
|
||||
frozen = True
|
||||
)
|
||||
|
||||
isFlash: bool = Field(
|
||||
description = "to know whether this message is a flash message or a regular message",
|
||||
frozen = True
|
||||
)
|
||||
|
||||
success: bool = Field(
|
||||
description = "to know whether this message was sent successfully or not",
|
||||
default = False
|
||||
)
|
||||
|
||||
brief: str | None = Field(
|
||||
description = "a brief message about what happened; useful when something goes wrong",
|
||||
default = None
|
||||
)
|
||||
|
||||
metadata: dict | None = Field(
|
||||
description = "any extra data about this message",
|
||||
frozen = True
|
||||
)
|
||||
|
||||
rawResponse: Any | None = Field(
|
||||
description = "the raw response from the third-party client",
|
||||
default = None
|
||||
)
|
||||
|
||||
messageId: int | str | None = Field(
|
||||
description = "how the client recognizes this message",
|
||||
frozen = False,
|
||||
default = None
|
||||
)
|
||||
|
||||
# ┏┓ ┏•
|
||||
# ┃ ┏┓┏┓╋┓┏┓
|
||||
# ┗┛┗┛┛┗┛┗┗┫
|
||||
# ┛
|
||||
|
||||
class Config:
|
||||
extra = "allow"
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** MAIN PROGRAM ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
pass
|
||||
Reference in New Issue
Block a user