(20241213) SMS Auth reworked.
This commit is contained in:
@@ -63,8 +63,8 @@ from utils_v2.api.async_quart import (
|
|||||||
from shared import constants
|
from shared import constants
|
||||||
|
|
||||||
# Data Models:
|
# Data Models:
|
||||||
from models.data.api.sms.auth import SMSAuthRequestHeaders, SMSAuthRequestData
|
from models.api.sms.auth import SMSAuthRequestHeaders, SMSAuthRequestData
|
||||||
from models.data.core.auth_token import CoreAuthTokenModel
|
from models.core.auth_token import CoreAuthTokenModel
|
||||||
|
|
||||||
# For asynchronous activities:
|
# For asynchronous activities:
|
||||||
import asyncio
|
import asyncio
|
||||||
@@ -158,7 +158,7 @@ async def authorize_sms_client(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Start by assuming failure:
|
# Start by assuming failure:
|
||||||
token_id = None
|
success = False
|
||||||
|
|
||||||
# ┏┓ ┳┓• ┓ ┏┓┳┳┓┏┓ ┳ ┓•
|
# ┏┓ ┳┓• ┓ ┏┓┳┳┓┏┓ ┳ ┓•
|
||||||
# ┣ ┏┓┏┓ ┃┃┓┏┳┓┣┓┓┏┏ ┗┓┃┃┃┗┓ ┃┏┓┏┫┓┏┓
|
# ┣ ┏┓┏┓ ┃┃┓┏┳┓┣┓┓┏┏ ┗┓┃┃┃┗┓ ┃┏┓┏┫┓┏┓
|
||||||
@@ -166,7 +166,7 @@ async def authorize_sms_client(
|
|||||||
|
|
||||||
if inbound_data.smsClient == "nimbusSmsIndia":
|
if inbound_data.smsClient == "nimbusSmsIndia":
|
||||||
|
|
||||||
token_id = await current_app.sms_auth_model.set(
|
success = await current_app.sms_controller.set_token(
|
||||||
db_conn = current_app.sql_writer,
|
db_conn = current_app.sql_writer,
|
||||||
mongo_conn = current_app.data_mongo,
|
mongo_conn = current_app.data_mongo,
|
||||||
auth_token = CoreAuthTokenModel(
|
auth_token = CoreAuthTokenModel(
|
||||||
@@ -183,17 +183,6 @@ async def authorize_sms_client(
|
|||||||
status = "active",
|
status = "active",
|
||||||
syncFreq = 60
|
syncFreq = 60
|
||||||
),
|
),
|
||||||
# user_info = kwargs["session_info"],
|
|
||||||
# client_user_id = {
|
|
||||||
# "userId": inbound_data.auth.userId,
|
|
||||||
# "senderId": inbound_data.auth.senderId,
|
|
||||||
# "entityId": inbound_data.auth.entityId
|
|
||||||
# },
|
|
||||||
# auth = inbound_data.auth.model_dump(),
|
|
||||||
# token = None,
|
|
||||||
# service_client = inbound_data.smsClient,
|
|
||||||
# auth_type = "auth",
|
|
||||||
# sync_freq = 300,
|
|
||||||
session_token = inbound_headers["X-Session-Token"]
|
session_token = inbound_headers["X-Session-Token"]
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -204,7 +193,7 @@ async def authorize_sms_client(
|
|||||||
|
|
||||||
elif inbound_data.smsClient == "savvyBulkSmsKenya":
|
elif inbound_data.smsClient == "savvyBulkSmsKenya":
|
||||||
|
|
||||||
token_id = await current_app.sms_auth_model.set(
|
success = await current_app.sms_controller.set_token(
|
||||||
db_conn = current_app.sql_writer,
|
db_conn = current_app.sql_writer,
|
||||||
mongo_conn = current_app.data_mongo,
|
mongo_conn = current_app.data_mongo,
|
||||||
auth_token = CoreAuthTokenModel(
|
auth_token = CoreAuthTokenModel(
|
||||||
@@ -220,16 +209,6 @@ async def authorize_sms_client(
|
|||||||
status = "active",
|
status = "active",
|
||||||
syncFreq = 60
|
syncFreq = 60
|
||||||
),
|
),
|
||||||
# user_info = kwargs["session_info"],
|
|
||||||
# client_user_id = {
|
|
||||||
# "partnerId": inbound_data.auth.partnerId,
|
|
||||||
# "shortCode": inbound_data.auth.shortCode
|
|
||||||
# },
|
|
||||||
# auth = inbound_data.auth.model_dump(),
|
|
||||||
# token = None,
|
|
||||||
# service_client = inbound_data.smsClient,
|
|
||||||
# auth_type = "auth",
|
|
||||||
# sync_freq = 300,
|
|
||||||
session_token = inbound_headers["X-Session-Token"]
|
session_token = inbound_headers["X-Session-Token"]
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -240,11 +219,11 @@ async def authorize_sms_client(
|
|||||||
|
|
||||||
# Done here:
|
# Done here:
|
||||||
return ResponseModel(
|
return ResponseModel(
|
||||||
status_code = StatusCodes.OK if token_id else StatusCodes.FAILED,
|
status_code = StatusCodes.OK if success else StatusCodes.FAILED,
|
||||||
http_code = HttpCodes.SUCCESS if token_id else HttpCodes.INTERNAL_SERVER_ERROR,
|
http_code = HttpCodes.SUCCESS if success else HttpCodes.INTERNAL_SERVER_ERROR,
|
||||||
data = {
|
data = {
|
||||||
"client": inbound_data.smsClient,
|
"client": inbound_data.smsClient,
|
||||||
"authorized": True
|
"authorized": success
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -60,8 +60,8 @@ from utils_v2.api.async_quart import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Data Models:
|
# Data Models:
|
||||||
from models.data.api.sms.send import SMSSendRequestHeaders, SMSSendRequestData
|
from models.core.auth_token import CoreAuthTokenModel
|
||||||
from models.data.core.auth_token import CoreAuthTokenModel
|
from models.api.sms.send import SMSSendRequestHeaders, SMSSendRequestData
|
||||||
|
|
||||||
# Common:
|
# Common:
|
||||||
from shared import constants
|
from shared import constants
|
||||||
@@ -174,13 +174,13 @@ async def send_sms(
|
|||||||
# ┗┓┏┓┏┓┏┫ ┃ ┣┓┏┓ ┗┓┃┃┃┗┓
|
# ┗┓┏┓┏┓┏┫ ┃ ┣┓┏┓ ┗┓┃┃┃┗┓
|
||||||
# ┗┛┗ ┛┗┗┻ ┻ ┛┗┗ ┗┛┛ ┗┗┛
|
# ┗┛┗ ┛┗┗┻ ┻ ┛┗┗ ┗┛┛ ┗┗┛
|
||||||
|
|
||||||
client_response = await current_app.sms_send_model.send_sms(
|
# client_response = await current_app.sms_send_model.send_sms(
|
||||||
mongo_conn = current_app.data_mongo,
|
# mongo_conn = current_app.data_mongo,
|
||||||
token_id = inbound_data.tokenId,
|
# token_id = inbound_data.tokenId,
|
||||||
auth_token = auth_token,
|
# auth_token = auth_token,
|
||||||
inbound_data = inbound_data,
|
# inbound_data = inbound_data,
|
||||||
session_token = inbound_headers["X-Session-Token"]
|
# session_token = inbound_headers["X-Session-Token"]
|
||||||
)
|
# )
|
||||||
|
|
||||||
# ┳┓
|
# ┳┓
|
||||||
# ┣┫┏┓┏┏┓┏┓┏┓┏┏┓
|
# ┣┫┏┓┏┏┓┏┓┏┓┏┏┓
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ async def authorize_software_client(
|
|||||||
http_code = HttpCodes.SUCCESS if success else HttpCodes.INTERNAL_SERVER_ERROR,
|
http_code = HttpCodes.SUCCESS if success else HttpCodes.INTERNAL_SERVER_ERROR,
|
||||||
data = {
|
data = {
|
||||||
"client": inbound_data.softwareClient,
|
"client": inbound_data.softwareClient,
|
||||||
"authorized": True if success else False
|
"authorized": success
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -69,6 +69,7 @@ from controllers.core.ai.llm import LLMController
|
|||||||
|
|
||||||
# API Controller Models:
|
# API Controller Models:
|
||||||
from controllers.api.mail import MailController
|
from controllers.api.mail import MailController
|
||||||
|
from controllers.api.sms import SMSController
|
||||||
|
|
||||||
# # Old Behaviour Models:
|
# # Old Behaviour Models:
|
||||||
# from controllers.mail.oauth_v3 import MailOAuthModel
|
# from controllers.mail.oauth_v3 import MailOAuthModel
|
||||||
@@ -90,7 +91,7 @@ from api.blueprints.mail.sync.sync_v2 import mail_sync_bp
|
|||||||
from api.blueprints.mail.retrieve.list import mail_list_bp
|
from api.blueprints.mail.retrieve.list import mail_list_bp
|
||||||
from api.blueprints.mail.retrieve.get import mail_get_bp
|
from api.blueprints.mail.retrieve.get import mail_get_bp
|
||||||
from api.blueprints.mail.tags.update import mail_tags_update_bp
|
from api.blueprints.mail.tags.update import mail_tags_update_bp
|
||||||
# from api.blueprints.sms.auth import sms_auth_bp
|
from api.blueprints.sms.auth import sms_auth_bp
|
||||||
# from api.blueprints.sms.send import sms_send_bp
|
# from api.blueprints.sms.send import sms_send_bp
|
||||||
# from api.blueprints.chat.auth import chat_auth_bp
|
# from api.blueprints.chat.auth import chat_auth_bp
|
||||||
# from api.blueprints.chat.webhook import chat_webhook_bp
|
# from api.blueprints.chat.webhook import chat_webhook_bp
|
||||||
@@ -131,7 +132,7 @@ app.register_blueprint(mail_sync_bp, url_prefix = f"/{MODULE_BASE}/mail")
|
|||||||
app.register_blueprint(mail_list_bp, url_prefix = f"/{MODULE_BASE}/mail")
|
app.register_blueprint(mail_list_bp, url_prefix = f"/{MODULE_BASE}/mail")
|
||||||
app.register_blueprint(mail_get_bp, url_prefix = f"/{MODULE_BASE}/mail")
|
app.register_blueprint(mail_get_bp, url_prefix = f"/{MODULE_BASE}/mail")
|
||||||
app.register_blueprint(mail_tags_update_bp, url_prefix = f"/{MODULE_BASE}/mail")
|
app.register_blueprint(mail_tags_update_bp, url_prefix = f"/{MODULE_BASE}/mail")
|
||||||
# app.register_blueprint(sms_auth_bp, url_prefix = f"/{MODULE_BASE}/sms")
|
app.register_blueprint(sms_auth_bp, url_prefix = f"/{MODULE_BASE}/sms")
|
||||||
# app.register_blueprint(sms_send_bp, url_prefix = f"/{MODULE_BASE}/sms")
|
# app.register_blueprint(sms_send_bp, url_prefix = f"/{MODULE_BASE}/sms")
|
||||||
# app.register_blueprint(chat_auth_bp, url_prefix = f"/{MODULE_BASE}/chat")
|
# app.register_blueprint(chat_auth_bp, url_prefix = f"/{MODULE_BASE}/chat")
|
||||||
# app.register_blueprint(chat_webhook_bp, url_prefix = f"/{MODULE_BASE}/chat")
|
# app.register_blueprint(chat_webhook_bp, url_prefix = f"/{MODULE_BASE}/chat")
|
||||||
@@ -347,6 +348,7 @@ async def app_startup(**kwargs):
|
|||||||
# ┛┗┣┛┻ ┗┛┗┛┛┗┗┛ ┗┛┗┗┗ ┛ ┛
|
# ┛┗┣┛┻ ┗┛┗┛┛┗┗┛ ┗┛┗┗┗ ┛ ┛
|
||||||
|
|
||||||
current_app.mail_controller = MailController()
|
current_app.mail_controller = MailController()
|
||||||
|
current_app.sms_controller = SMSController()
|
||||||
|
|
||||||
# ┏┓ ┓ ┏┓┓•
|
# ┏┓ ┓ ┏┓┓•
|
||||||
# ┃ ┏┓┏┓┏┓┏┓┏╋┏┓┏┓┏ ┏┓┏┓┏┫ ┃ ┃┓┏┓┏┓╋┏
|
# ┃ ┏┓┏┓┏┓┏┓┏╋┏┓┏┓┏ ┏┓┏┓┏┫ ┃ ┃┓┏┓┏┓╋┏
|
||||||
|
|||||||
@@ -0,0 +1,371 @@
|
|||||||
|
"""
|
||||||
|
|
||||||
|
AUTHOR:
|
||||||
|
|
||||||
|
Khushal P Soonderji
|
||||||
|
|
||||||
|
DATE:
|
||||||
|
|
||||||
|
Friday, 13th Dec., 2024
|
||||||
|
|
||||||
|
OBJECTIVE:
|
||||||
|
|
||||||
|
To handle all SMS related behaviour from one place.
|
||||||
|
|
||||||
|
REFERENCES:
|
||||||
|
|
||||||
|
N/A
|
||||||
|
|
||||||
|
DOWNLOADS:
|
||||||
|
|
||||||
|
N/A
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# *****************************************************************************************************************
|
||||||
|
# ***** ****
|
||||||
|
# *** IMPORT ***
|
||||||
|
# ***** ****
|
||||||
|
# *****************************************************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
# To make sibling directories accessible for imports:
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import httpx
|
||||||
|
from google.protobuf.duration import from_microseconds
|
||||||
|
|
||||||
|
sys.path.append(".")
|
||||||
|
sys.path.append("..")
|
||||||
|
|
||||||
|
# For Quart:
|
||||||
|
from quart import current_app
|
||||||
|
|
||||||
|
# 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, AsyncMongoStorage
|
||||||
|
|
||||||
|
# Base model:
|
||||||
|
from controllers.base import BaseModel
|
||||||
|
|
||||||
|
# Data models:
|
||||||
|
from models.core.user import CoreUserInfoModel
|
||||||
|
from models.core.auth_token import CoreAuthTokenModel
|
||||||
|
from models.core.message import CoreMessageModel
|
||||||
|
from models.api.sms.send import (
|
||||||
|
SMSSendRequestData,
|
||||||
|
NimbusSMSIndiaMessage,
|
||||||
|
SavvyBulkSMSKenyaMessage,
|
||||||
|
SMSSendManyResults
|
||||||
|
)
|
||||||
|
|
||||||
|
# SMS Clients:
|
||||||
|
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
|
||||||
|
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, List, Dict, Any
|
||||||
|
|
||||||
|
|
||||||
|
# *****************************************************************************************************************
|
||||||
|
# ***** ****
|
||||||
|
# *** MACROS / ONE-TIME INIT ***
|
||||||
|
# ***** ****
|
||||||
|
# *****************************************************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
# --- Nothing Yet
|
||||||
|
|
||||||
|
|
||||||
|
# *****************************************************************************************************************
|
||||||
|
# ***** ****
|
||||||
|
# *** VARIABLES ***
|
||||||
|
# ***** ****
|
||||||
|
# *****************************************************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
# --- Nothing Yet
|
||||||
|
|
||||||
|
|
||||||
|
# *****************************************************************************************************************
|
||||||
|
# ***** ****
|
||||||
|
# *** FUNCTIONS ***
|
||||||
|
# ***** ****
|
||||||
|
# *****************************************************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
# --- Nothing Yet
|
||||||
|
|
||||||
|
|
||||||
|
# *****************************************************************************************************************
|
||||||
|
# ***** ****
|
||||||
|
# *** CLASSES ***
|
||||||
|
# ***** ****
|
||||||
|
# *****************************************************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
class SMSController:
|
||||||
|
|
||||||
|
# ┏┓┓ ┓┏
|
||||||
|
# ┃ ┃┏┓┏┏ ┃┃┏┓┏┓┏
|
||||||
|
# ┗┛┗┗┻┛┛ ┗┛┗┻┛ ┛
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
# ┓┏ ┓
|
||||||
|
# ┣┫┏┓┃┏┓┏┓┏┓┏
|
||||||
|
# ┛┗┗ ┗┣┛┗ ┛ ┛
|
||||||
|
# ┛
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
# ┏┓ ┓
|
||||||
|
# ┣┫┓┏╋┣┓
|
||||||
|
# ┛┗┗┻┗┛┗
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
async def set_token(
|
||||||
|
db_conn: AsyncMySQL,
|
||||||
|
mongo_conn: AsyncMongo,
|
||||||
|
auth_token: CoreAuthTokenModel,
|
||||||
|
session_token: str = None
|
||||||
|
) -> bool:
|
||||||
|
|
||||||
|
# Start by assuming failure:
|
||||||
|
success = False
|
||||||
|
|
||||||
|
# Get a token id:
|
||||||
|
token_id = await current_app.core_auth_token_controller.get_token_id(
|
||||||
|
db_conn = db_conn,
|
||||||
|
mongo_conn = mongo_conn,
|
||||||
|
auth_token = auth_token,
|
||||||
|
token_notes = {},
|
||||||
|
session_token = session_token
|
||||||
|
)
|
||||||
|
|
||||||
|
# Immediately save the details against that token id:
|
||||||
|
success = await current_app.core_auth_token_controller.set_token(
|
||||||
|
db_conn = db_conn,
|
||||||
|
mongo_conn = mongo_conn,
|
||||||
|
token_id = token_id,
|
||||||
|
auth_token = auth_token,
|
||||||
|
token_notes = {},
|
||||||
|
session_token = session_token
|
||||||
|
)
|
||||||
|
|
||||||
|
# Done here:
|
||||||
|
return success
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
async def get_token(
|
||||||
|
mongo_conn: AsyncMongo,
|
||||||
|
token_id: ObjectId | str = None,
|
||||||
|
) -> CoreAuthTokenModel | None:
|
||||||
|
|
||||||
|
# Simply call the core model:
|
||||||
|
return await current_app.core_auth_token_controller.get_token(
|
||||||
|
mongo_conn = mongo_conn,
|
||||||
|
token_id = token_id
|
||||||
|
)
|
||||||
|
|
||||||
|
# ┏┓ ┓
|
||||||
|
# ┗┓┏┓┏┓┏┫
|
||||||
|
# ┗┛┗ ┛┗┗┻
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
async def __send_from_nimbus_sms_india(
|
||||||
|
http_client: httpx.AsyncClient,
|
||||||
|
token_id: ObjectId | str,
|
||||||
|
auth_token: CoreAuthTokenModel,
|
||||||
|
messages: List[NimbusSMSIndiaMessage],
|
||||||
|
) -> SMSSendManyResults:
|
||||||
|
|
||||||
|
# Start with a blank variable:
|
||||||
|
send_results = SMSSendManyResults()
|
||||||
|
|
||||||
|
# Initialize the third-party client:
|
||||||
|
client = AsyncNimbusSMS(
|
||||||
|
entity_id = auth_token.auth["entityId"],
|
||||||
|
sender_id = auth_token.auth["senderId"],
|
||||||
|
user_id = auth_token.auth["userId"],
|
||||||
|
api_key = auth_token.auth["apiKey"],
|
||||||
|
http_client = http_client
|
||||||
|
)
|
||||||
|
|
||||||
|
# Iterate over all the messages you need to send:
|
||||||
|
for message in messages:
|
||||||
|
|
||||||
|
# Send the SMS and return the response:
|
||||||
|
client_response = await client.send_sms(
|
||||||
|
recipient_number = message.recipientNo,
|
||||||
|
message = message.text,
|
||||||
|
template_id = message.templateId
|
||||||
|
)
|
||||||
|
|
||||||
|
# Note down the results:
|
||||||
|
send_results.totalCount += 1
|
||||||
|
if client_response.success: send_results.successCount += 1
|
||||||
|
else: send_results.failureCount += 1
|
||||||
|
send_results.smsMessages.append(CoreMessageModel(
|
||||||
|
ts = client_response.ts,
|
||||||
|
syncTs = date_time.get_current_utc_date_time(as_string = False),
|
||||||
|
tokenId = ObjectId(token_id),
|
||||||
|
serviceType = auth_token.serviceType,
|
||||||
|
client = auth_token.client,
|
||||||
|
clientMessageId = client_response.messageId,
|
||||||
|
clientThreadId = message.recipientNo,
|
||||||
|
isSent = True,
|
||||||
|
isBroadcast = False,
|
||||||
|
sentSuccessfully = client_response.success,
|
||||||
|
sender = None,
|
||||||
|
chat = None,
|
||||||
|
message = client_response.model_dump(),
|
||||||
|
snippet = message.text,
|
||||||
|
aiSnippet = None,
|
||||||
|
tags = ["sms", "nimbusSmsIndia"]
|
||||||
|
))
|
||||||
|
|
||||||
|
# Done here:
|
||||||
|
return send_results
|
||||||
|
|
||||||
|
async def send(
|
||||||
|
self,
|
||||||
|
mongo_conn: AsyncMongo,
|
||||||
|
http_client: httpx.AsyncClient,
|
||||||
|
token_id: ObjectId | str,
|
||||||
|
messages: List[NimbusSMSIndiaMessage | SavvyBulkSMSKenyaMessage],
|
||||||
|
session_token: str
|
||||||
|
) -> SMSSendManyResults:
|
||||||
|
|
||||||
|
# Start by assuming failure:
|
||||||
|
send_results = SMSSendManyResults()
|
||||||
|
|
||||||
|
# We first load the authorization tokens:
|
||||||
|
auth_token = await self.get_token(
|
||||||
|
mongo_conn = mongo_conn,
|
||||||
|
token_id = token_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
# If we failed to load the authorization tokens:
|
||||||
|
if not auth_token:
|
||||||
|
send_results.message = f"no such token id '{token_id}'"
|
||||||
|
return send_results
|
||||||
|
|
||||||
|
# Now we route the message to the appropriate client:
|
||||||
|
match auth_token.client:
|
||||||
|
case "nimbusSmsIndia":
|
||||||
|
send_results = await self.__send_from_nimbus_sms_india(
|
||||||
|
http_client = http_client,
|
||||||
|
token_id = token_id,
|
||||||
|
auth_token = auth_token,
|
||||||
|
messages = messages
|
||||||
|
)
|
||||||
|
case "savvyBulkSmsKenya":
|
||||||
|
pass
|
||||||
|
case _:
|
||||||
|
send_results.message = f"invalid client {auth_token.client}"
|
||||||
|
|
||||||
|
# Save the results to MongoDB:
|
||||||
|
|
||||||
|
|
||||||
|
# Done here:
|
||||||
|
return send_results
|
||||||
|
|
||||||
|
# ┓ • ┏┓ ┏┓ ┳┳┓
|
||||||
|
# ┃ ┓┏╋ ┣╋ ┃┓┏┓╋ ┃┃┃┏┓┏┏┏┓┏┓┏┓┏
|
||||||
|
# ┗┛┗┛┗ ┗┻ ┗┛┗ ┗ ┛ ┗┗ ┛┛┗┻┗┫┗ ┛
|
||||||
|
# ┛
|
||||||
|
|
||||||
|
# These are simply for retrieving sms messages.
|
||||||
|
# You need to already have them saved to the database.
|
||||||
|
|
||||||
|
# @staticmethod
|
||||||
|
# async def list_messages(
|
||||||
|
# mongo_conn: AsyncMongo,
|
||||||
|
# token_ids: List[ObjectId | str],
|
||||||
|
# limit: int = 100,
|
||||||
|
# skip: int = 0,
|
||||||
|
# additional_filter: dict = None
|
||||||
|
# ) -> List[CoreMessageModel] | None:
|
||||||
|
#
|
||||||
|
# # regardless of what additional filter is provided from outside,
|
||||||
|
# # we add a mail-selecting filter here:
|
||||||
|
# if additional_filter is None: additional_filter = {}
|
||||||
|
# additional_filter["serviceType"] = "sms"
|
||||||
|
#
|
||||||
|
# # Simply call the core model:
|
||||||
|
# return await current_app.core_message_controller.get_message(
|
||||||
|
# mongo_conn = mongo_conn,
|
||||||
|
# token_ids = token_ids,
|
||||||
|
# limit = limit,
|
||||||
|
# skip = skip,
|
||||||
|
# additional_filter = additional_filter
|
||||||
|
# )
|
||||||
|
#
|
||||||
|
# @staticmethod
|
||||||
|
# async def get_one_mail(
|
||||||
|
# mongo_conn: AsyncMongo,
|
||||||
|
# token_id: ObjectId | str,
|
||||||
|
# message_id: ObjectId | str
|
||||||
|
# ) -> CoreMessageModel | None:
|
||||||
|
#
|
||||||
|
# # Simply call the core model:
|
||||||
|
# return await current_app.core_message_controller.get_message(
|
||||||
|
# mongo_conn = mongo_conn,
|
||||||
|
# token_id = token_id,
|
||||||
|
# message_id = message_id
|
||||||
|
# )
|
||||||
|
|
||||||
|
# ┳┳ ┓
|
||||||
|
# ┃┃┏┓┏┫┏┓╋┏┓
|
||||||
|
# ┗┛┣┛┗┻┗┻┗┗
|
||||||
|
# ┛
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
async def update_tags(
|
||||||
|
mongo_conn: AsyncMongo,
|
||||||
|
token_id: ObjectId | str,
|
||||||
|
message_id: ObjectId | str,
|
||||||
|
unset_tags: List[str] = None,
|
||||||
|
set_tags: List[str] = None
|
||||||
|
) -> bool:
|
||||||
|
|
||||||
|
# Simply call the core model:
|
||||||
|
return await current_app.core_message_controller.update_tags(
|
||||||
|
mongo_conn = mongo_conn,
|
||||||
|
token_id = token_id,
|
||||||
|
message_id = message_id,
|
||||||
|
unset_tags = unset_tags,
|
||||||
|
set_tags = set_tags
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# *****************************************************************************************************************
|
||||||
|
# ***** ****
|
||||||
|
# *** MAIN PROGRAM ***
|
||||||
|
# ***** ****
|
||||||
|
# *****************************************************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
# from utils_v2.string import json
|
||||||
|
#
|
||||||
|
# file_options = [
|
||||||
|
# r"/home/developer/Downloads/recursive parts parse - 20241210.json",
|
||||||
|
# r"/home/developer/Downloads/recursive parts parse (no attachment) - 20241210.json",
|
||||||
|
# ]
|
||||||
|
#
|
||||||
|
# raw_mail_json = json.from_file(file_options[1])
|
||||||
|
# print("FROM FILE:", json.to_string(raw_mail_json["payload"]))
|
||||||
|
# print("\n\n---------\n\n")
|
||||||
|
# mail_controller = MailController()
|
||||||
|
# print(json.to_string(mail_controller.drop_attachments(raw_mail_json["payload"])))
|
||||||
+79
-2
@@ -37,12 +37,16 @@ sys.path.append("..")
|
|||||||
|
|
||||||
# For making data behaviour_models:
|
# For making data behaviour_models:
|
||||||
from pydantic import BaseModel, Field, field_validator, PastDatetime
|
from pydantic import BaseModel, Field, field_validator, PastDatetime
|
||||||
from typing import Optional, Literal, Union
|
from typing import Optional, Literal, Union, List
|
||||||
|
|
||||||
# My utils:
|
# My utils:
|
||||||
from utils_v2.string import regex
|
from utils_v2.string import regex
|
||||||
from utils_v2.date_time import date_time
|
from utils_v2.date_time import date_time
|
||||||
|
|
||||||
|
# Data models:
|
||||||
|
from models.core.message import CoreMessageModel
|
||||||
|
from utils_v2.sms.models.data.sms_message import SentSMSMessageModel
|
||||||
|
|
||||||
# To work with date and time:
|
# To work with date and time:
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
@@ -174,7 +178,7 @@ class SMSSendRequestHeaders(BaseModel):
|
|||||||
class SMSSendRequestData(BaseModel):
|
class SMSSendRequestData(BaseModel):
|
||||||
|
|
||||||
tokenId: ObjectId = Field(description = "the auth token to use to send this message")
|
tokenId: ObjectId = Field(description = "the auth token to use to send this message")
|
||||||
message: Union[NimbusSMSIndiaMessage, SavvyBulkSMSKenyaMessage]
|
message: Union[List[NimbusSMSIndiaMessage], List[SavvyBulkSMSKenyaMessage]]
|
||||||
|
|
||||||
# ┏┓ ┏•
|
# ┏┓ ┏•
|
||||||
# ┃ ┏┓┏┓╋┓┏┓
|
# ┃ ┏┓┏┓╋┓┏┓
|
||||||
@@ -195,6 +199,79 @@ class SMSSendRequestData(BaseModel):
|
|||||||
except: pass
|
except: pass
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
@field_validator("message", mode = "before")
|
||||||
|
def ensure_list(cls, value):
|
||||||
|
if not isinstance(value, list): value = [value]
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
class SMSSendOneResult(BaseModel):
|
||||||
|
|
||||||
|
success: bool = Field(
|
||||||
|
description = "whether, or not, the sms was successfully sent",
|
||||||
|
default = False
|
||||||
|
)
|
||||||
|
|
||||||
|
message: str | None = Field(
|
||||||
|
description = "a brief message to summarize the result of the process",
|
||||||
|
default = None
|
||||||
|
)
|
||||||
|
|
||||||
|
smsMessage: Union[NimbusSMSIndiaMessage, SavvyBulkSMSKenyaMessage] = Field(
|
||||||
|
description = "the actual data of the sms",
|
||||||
|
default = None
|
||||||
|
)
|
||||||
|
|
||||||
|
# ┏┓ ┏•
|
||||||
|
# ┃ ┏┓┏┓╋┓┏┓
|
||||||
|
# ┗┛┗┛┛┗┛┗┗┫
|
||||||
|
# ┛
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
extra = "forbid"
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
class SMSSendManyResults(BaseModel):
|
||||||
|
|
||||||
|
totalCount: int = Field(
|
||||||
|
description = "the total no. of mails that were to be sync'd",
|
||||||
|
default = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
successCount: int = Field(
|
||||||
|
description = "the no. of mails that were successfully sync'd",
|
||||||
|
default = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
failureCount: int = Field(
|
||||||
|
description = "the no. of mails that were successfully sync'd",
|
||||||
|
default = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
message: str = Field(
|
||||||
|
description = "a brief message to summarize the results of the process",
|
||||||
|
default = None
|
||||||
|
)
|
||||||
|
|
||||||
|
smsMessages: List[CoreMessageModel] = Field(
|
||||||
|
description = "the actual data of the sms",
|
||||||
|
default = []
|
||||||
|
)
|
||||||
|
|
||||||
|
# ┏┓ ┏•
|
||||||
|
# ┃ ┏┓┏┓╋┓┏┓
|
||||||
|
# ┗┛┗┛┛┗┛┗┗┫
|
||||||
|
# ┛
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
extra = "forbid"
|
||||||
|
|
||||||
|
|
||||||
# *****************************************************************************************************************
|
# *****************************************************************************************************************
|
||||||
# ***** ****
|
# ***** ****
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ class AsyncNimbusSMS:
|
|||||||
summary.rawResponse = response_json
|
summary.rawResponse = response_json
|
||||||
summary.success = True if response_json.get("STATUS", "ERROR").lower() in ["ok"] else False
|
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")
|
if summary.success: summary.messageId = response_json.get("RESPONSE", {}).get("UID")
|
||||||
else: summary.brief = response_json.get("RESPONSE", {}).get("INFO")
|
else: summary.message = response_json.get("RESPONSE", {}).get("INFO")
|
||||||
|
|
||||||
# For any other code that indicates some form of failure:
|
# For any other code that indicates some form of failure:
|
||||||
else: summary.rawResponse = response.content.decode()
|
else: summary.rawResponse = response.content.decode()
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ class AsyncSavvyBulkSMS:
|
|||||||
first_desc = first_response.get("response-description", "N/A").lower().strip()
|
first_desc = first_response.get("response-description", "N/A").lower().strip()
|
||||||
summary.success = True if first_desc == "success" else False
|
summary.success = True if first_desc == "success" else False
|
||||||
if summary.success: summary.messageId = first_response.get("messageid")
|
if summary.success: summary.messageId = first_response.get("messageid")
|
||||||
else: summary.brief = first_response.get("response-description")
|
else: summary.message = first_response.get("response-description")
|
||||||
|
|
||||||
# For any other code that indicates some form of failure:
|
# For any other code that indicates some form of failure:
|
||||||
else: summary.rawResponse = api_response.content.decode()
|
else: summary.rawResponse = api_response.content.decode()
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ class SentSMSMessageModel(BaseModel):
|
|||||||
default = False
|
default = False
|
||||||
)
|
)
|
||||||
|
|
||||||
brief: str | None = Field(
|
message: str | None = Field(
|
||||||
description = "a brief message about what happened; useful when something goes wrong",
|
description = "a brief message about what happened; useful when something goes wrong",
|
||||||
default = None
|
default = None
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user