import requests import logging from django.core.cache import cache from common.env import env logger = logging.getLogger(__name__) class SendService: GET = "GET" POST = "POST" PATCH = "PATCH" CONTACT = "contact" CACHE_KEY = "eskiz_token" TOKEN_LIFETIME = 86400 * 20 # Eskiz tokens usually last 30 days, we cache for 20 def __init__( self, api_url=None, email=None, password=None, callback_url=None ): self.api_url = (api_url or env("SMS_API_URL")).rstrip("/") self.email = email or env("SMS_LOGIN") self.password = password or env("SMS_PASSWORD") self.callback_url = callback_url self.headers = { "Accept": "application/json", } self.methods = { "auth_user": "auth/user", "auth_login": "auth/login", "auth_refresh": "auth/refresh", "send_message": "message/sms/send", } def request(self, api_path, data=None, method=None, headers=None): url = f"{self.api_url}/{api_path}" method = method or self.POST final_headers = self.headers.copy() if headers: final_headers.update(headers) try: # Reverting to data=data (form-encoded) as it was working before response = requests.request( method, url, data=data if method != self.GET else None, params=data if method == self.GET else None, headers=final_headers, timeout=10 ) response.raise_for_status() return response.json() except requests.exceptions.HTTPError as e: logger.error(f"SMS API HTTP Error: {e.response.status_code} - {e.response.text}") return e.response.json() except Exception as e: logger.error(f"SMS API Request Exception: {str(e)}") return {"status": "error", "message": str(e)} def get_token(self): token = cache.get(self.CACHE_KEY) if not token: logger.info("Eskiz token not found in cache, authenticating...") auth_res = self.auth() if auth_res.get("status") == "success" or "data" in auth_res: token = auth_res.get("data", {}).get("token") if token: cache.set(self.CACHE_KEY, token, self.TOKEN_LIFETIME) else: logger.error(f"Eskiz Auth Failed: {auth_res}") return token def auth(self): data = {"email": self.email, "password": self.password} # Eskiz login expects JSON return self.request( self.methods["auth_login"], data=data, method=self.POST ) def refresh_token(self): token = self.get_token() headers = {"Authorization": f"Bearer {token}"} res = self.request( self.methods["auth_refresh"], method=self.PATCH, headers=headers, ) if res.get("status") == "success": # Some Eskiz versions return a new token on refresh new_token = res.get("data", {}).get("token") if new_token: cache.set(self.CACHE_KEY, new_token, self.TOKEN_LIFETIME) return res def get_my_user_info(self): token = self.get_token() headers = {"Authorization": f"Bearer {token}"} return self.request( self.methods["auth_user"], method=self.GET, headers=headers ) def add_sms_contact(self, first_name, phone_number, group): token = self.get_token() headers = {"Authorization": f"Bearer {token}"} data = { "name": first_name, "email": self.email, "group": group, "mobile_phone": phone_number, } return self.request( self.CONTACT, data=data, method=self.POST, headers=headers, ) def send_sms(self, phone_number, message): token = self.get_token() if not token: return {"status": "error", "message": "Failed to obtain auth token"} headers = {"Authorization": f"Bearer {token}"} # Use integer 4546 for sender name data = { "from": 4546, "mobile_phone": phone_number, "callback_url": self.callback_url, "message": message, } res = self.request( self.methods["send_message"], data=data, method=self.POST, headers=headers, ) return res