Files
digest_app/module_project/service.py
2024-02-26 13:28:32 +05:30

256 lines
8.2 KiB
Python

from django.conf import settings
from django.core.files.uploadedfile import UploadedFile
from django.core.mail import EmailMessage
from django.utils.html import strip_tags
from django.template.loader import render_to_string
from django.shortcuts import get_object_or_404
from smtplib import SMTPException
from module_iam.models import IAmPrincipal, IAmPrincipalOtp, IAmPrincipalType
from .utils import RandomGenerator
# from twilio.rest import Client
from django.db.models import Q
import phonenumbers
from decimal import Decimal
from django.db.models import F
from django.db import transaction
from datetime import timedelta, time, datetime
from django.utils import timezone
# from onesignal_sdk.client import Client as OneSignalClient
import logging
logger = logging.getLogger(__name__)
class EmailService:
email = None
body = None
subject = None
to = None
from_email = None
content_subtype = "html"
def __init__(self, subject=None, to=None, from_email=None):
self.subject = subject
self.to = (to,)
self.from_email = from_email
def set_to(self, to):
self.to = to
def set_subject(self, subject):
self.subject = subject
def set_from_email(self, from_email):
self.from_email = from_email
def set_text_body(self, body):
self.body = strip_tags(body)
def set_html_body(self, html_body):
self.body = html_body
def load_template(self, path=None, context={}):
if path is None:
raise Exception("Email temaplate path is not provided.")
self.content_subtype = "html"
html_body = render_to_string(path, context=context)
self.body = html_body
def attach(self, file_path):
self.email.attach_file(file_path)
def send(self):
try:
self.email = EmailMessage(
subject=self.subject,
body=self.body,
to=self.to,
from_email=self.from_email,
)
self.email.content_subtype = self.content_subtype
self.email.send()
except SMTPException as e:
logger.error(str(e))
class SMSError(Exception):
def __init__(self, message, payload=None):
self.message = message
self.payload = payload
def __str__(self):
return str(self.message)
class SMSService:
# def send(self, to: list, text: str):
# """
# Sends text sms to the given user(s).
# Parameters:
# to (list): list of phone numbers
# text (str): a text message.
# Return:
# True or False
# """
# # if settings.TESTING_ENV:
# # logger.info(f"TESTING ENV SMS LOG : {text}")
# # return True
# account_sid = settings.TWILIO_ACCOUNT_SID
# auth_token = settings.TWILIO_AUTH_TOKEN
# my_twilio_number = settings.MY_TWILIO_NUMBER
# client = Client(account_sid, auth_token)
# try:
# for number in to:
# logger.info("SENDING SMS TO " + str(number))
# message = client.messages.create(
# from_=my_twilio_number, body=text, to=number
# )
# except Exception as e:
# logger.error(str(e))
# raise SMSError(message=str(e))
def create_otp(self, principal: IAmPrincipal, otp_purpose: str):
otp = IAmPrincipalOtp.objects.create(
principal=principal, otp_purpose=otp_purpose
)
otp.save()
return otp.otp_code
def send_otp(self, principal: IAmPrincipal, otp_purpose: str):
"""
Sends otp to the given user.
Parameters:
user (User): User object
otp_purpose (str) : a text that describe otp purpose
Return:
True or False
"""
if not isinstance(principal, IAmPrincipal):
raise Exception(
f"parameter 'principal' required type of User object, Given {type(principal)} type object"
)
otp_code = self.create_otp(principal=principal, otp_purpose=otp_purpose)
# below working will change as it is temporary purpose
body = f"Your Nifty11 OTP is {otp_code}."
print(body)
phone_numbers = []
try:
parsed_number = phonenumbers.parse(str(principal.phone_no), None)
if phonenumbers.is_valid_number(parsed_number):
formatted_number = phonenumbers.format_number(
parsed_number, phonenumbers.PhoneNumberFormat.E164
)
phone_numbers.append(formatted_number)
else:
raise ValueError("Invalid phone number")
except Exception as e:
logger.warning(f"{e}")
raise ValueError("Invalid phone number")
if not phone_numbers:
raise ValueError("Invalid phone number")
print(f"phone number {type(phone_numbers)} {phone_numbers}")
# self.send(phone_numbers, body)
return otp_code
# class OneSignalNotificationService:
# """
# Class for sending notifications using the OneSignal API.
# Provides a convenient way to create and send notifications to OneSignal users,
# with features like targeting specific devices or segments, customizing notification content,
# and handling errors gracefully.
# **Parameters:**
# - **app_id** (str): Your OneSignal App ID.
# - **rest_api_key** (str): Your OneSignal REST API Key.
# - **user_auth_key** (str): Your OneSignal User Auth Key.
# **Keyword Arguments:**
# This method accepts additional keyword arguments (`**kwargs`) to customize the notification
# further, including:
# - `url` (str): URL to open when the notification is clicked.
# - `data` (dict): Custom data to be sent with the notification.
# - `buttons` (list): List of action buttons to display within the notification.
# - `send_after` (str): Timestamp for scheduling the notification.
# - `delayed_option` (dict): Option for delayed delivery (Android-specific).
# - `android_channel_id` (str): Channel ID for Android notifications.
# - `ios_sound` (str): Sound to play for iOS notifications.
# - `ios_badgeType` (str): Badge type for iOS notifications.
# - `ios_badgeCount` (int): Badge count for iOS notifications.
# - `ios_thread_id` (str): Thread ID to group notifications in iOS.
# - `android_background_layout` (str): Layout for background notifications on Android.
# - `android_group` (str): Group notification on Android.
# - `android_group_message` (str): Summary for grouped notifications on Android.
# - `android_group_summary` (str): Summary for grouped notifications on Android.
# - `android_led_color` (str): LED color for Android notifications.
# - `android_accent_color` (str): Accent color for Android notifications.
# - `android_visibility` (str): Visibility settings for Android notifications.
# **Example usage:**
# notification = OneSignalNotificationService()
# response = notification.send_notification(
# headings="Welcome",
# message="Thanks for signing up!",
# player_tokens=["PLAYER_TOKEN1", "PLAYER_TOKEN2"],
# url="https://yourwebsite.com/welcome",
# data={"user_id": 123},
# )
# """
# def __init__(self):
# self.config = OneSignalClient(
# app_id=settings.ONESIGNAL_APP_ID,
# rest_api_key=settings.ONESIGNAL_REST_API_KEY,
# user_auth_key=settings.ONESIGNAL_USER_AUTH_KEY
# )
# # Set up logging
# self.logger = logging.getLogger(__name__)
# def send_notification(self, headings, message, player_tokens=None, **kwargs):
# notification_obj = {
# "headings": {"en": headings},
# "contents": {"en": message},
# **kwargs
# }
# if player_tokens:
# notification_obj["include_player_ids"] = player_tokens
# try:
# response = self.config.send_notification(notification_obj)
# self.logger.info(f"Notification send successfully : {response}")
# return response
# except Exception as e:
# self.logger.error(f"OneSignal error {e}")
# raise Exception("Generic OneSignal error: {}".format(e))