"""Provider عمومی مبتنی بر HTTP؛ مقادیر از SMSProviderConfig خوانده می‌شوند.""" import requests from .base import SMSProvider, SMSResult from .normalize import normalize_mobile class HTTPSMSProvider(SMSProvider): def __init__(self, config=None): self.config = config def send_message(self, mobile, message): config = self.config if config is None or not config.api_url: return SMSResult(False, error="آدرس سرویس پیامک (api_url) تنظیم نشده است.") if not normalize_mobile(str(mobile)): return SMSResult( False, provider_code="INVALID_NUMBER", error="شمارهٔ موبایل گیرنده معتبر نیست.", ) headers = {"Accept": "application/json", "Content-Type": "application/json"} if config.api_token: headers["Authorization"] = f"Bearer {config.api_token}" try: response = requests.post( config.api_url, json={"to": mobile, "message": message, "sender": config.sender}, headers=headers, timeout=config.timeout_seconds or 30, ) response.raise_for_status() try: data = response.json() if response.content else {} except ValueError: # بدنهٔ پاسخ JSON نبود (مثلاً صفحهٔ HTML خطای سرویس‌دهنده). return SMSResult( False, provider_code="BAD_RESPONSE", error=f"پاسخ سرویس پیامک JSON معتبر نبود (HTTP {response.status_code}).", ) # بعضی سرویس‌دهنده‌ها به‌جای آبجکت، لیست برمی‌گردانند. if isinstance(data, list): data = data[0] if data and isinstance(data[0], dict) else {} elif not isinstance(data, dict): data = {} if data.get("success") is False: return SMSResult(False, error=str(data.get("error", "Provider rejected SMS"))) return SMSResult(True, str(data.get("id") or data.get("message_id") or "http")) except requests.RequestException as exc: return SMSResult(False, error=str(exc))