restore composer.json, add mysqli extension
Some checks failed
Build and Push to Docker Hub / build-test-push (push) Failing after 1m55s

This commit is contained in:
2026-04-15 15:38:41 +05:00
parent 24f6fe42cc
commit 477e79ed80
5 changed files with 92 additions and 67 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -118,6 +118,7 @@ class AddDebtView(APIView):
"message": "Qarz muvaffaqiyatli qo'shildi.", "message": "Qarz muvaffaqiyatli qo'shildi.",
"debt_unpaid": f"{market.debt_unpaid}", "debt_unpaid": f"{market.debt_unpaid}",
"market_name": f"{market.name}", "market_name": f"{market.name}",
"market_phone": f"{market.phone}",
"market_company": f"{market.company_name}", "market_company": f"{market.company_name}",
}, },
status=status.HTTP_200_OK, status=status.HTTP_200_OK,

View File

@@ -13,13 +13,17 @@ from core.utils import console
def SendConfirm(phone, code): def SendConfirm(phone, code):
try: try:
service: sms_service.SendService = sms_service.SendService() service: sms_service.SendService = sms_service.SendService()
service.send_sms( message = _("Sizning Tasdiqlash ko'dingiz: %(code)s") % {"code": code}
phone, _("Sizning Tasdiqlash ko'dingiz: %(code)s") % {"code": code} res = service.send_sms(phone, message)
)
console.Console().success(f"Success: {phone}-{code}") if res.get("status") == "success" or res.get("status") == "waiting":
console.Console().success(f"SMS Sent Successfully: {phone}-{code} | Response: {res}")
else:
console.Console().error(f"SMS Failed: {phone}-{code} | Error: {res}")
except Exception as e: except Exception as e:
console.Console().error( console.Console().error(
"Error: {phone}-{code}\n\n{error}".format( "Exception in SendConfirm task: {phone}-{code}\n\n{error}".format(
phone=phone, code=code, error=e phone=phone, code=code, error=str(e)
)
) )
) # noqa

View File

@@ -1,22 +1,29 @@
import requests import requests
import logging
from django.core.cache import cache
from common.env import env from common.env import env
logger = logging.getLogger(__name__)
class SendService: class SendService:
GET = "GET" GET = "GET"
POST = "POST" POST = "POST"
PATCH = "PATCH" PATCH = "PATCH"
CONTACT = "contact" CONTACT = "contact"
CACHE_KEY = "eskiz_token"
TOKEN_LIFETIME = 86400 * 20 # Eskiz tokens usually last 30 days, we cache for 20
def __init__( def __init__(
self, api_url=None, email=None, password=None, callback_url=None self, api_url=None, email=None, password=None, callback_url=None
): ):
self.api_url = api_url or env("SMS_API_URL") self.api_url = (api_url or env("SMS_API_URL")).rstrip("/")
self.email = email or env("SMS_LOGIN") self.email = email or env("SMS_LOGIN")
self.password = password or env("SMS_PASSWORD") self.password = password or env("SMS_PASSWORD")
self.callback_url = callback_url self.callback_url = callback_url
self.headers = {} self.headers = {
"Content-Type": "application/json",
"Accept": "application/json",
}
self.methods = { self.methods = {
"auth_user": "auth/user", "auth_user": "auth/user",
@@ -26,66 +33,89 @@ class SendService:
} }
def request(self, api_path, data=None, method=None, headers=None): def request(self, api_path, data=None, method=None, headers=None):
incoming_data = {"status": "error"} incoming_data = {"status": "error", "message": "Unknown error"}
url = f"{self.api_url}/{api_path}"
final_headers = self.headers.copy()
if headers:
final_headers.update(headers)
try: try:
# For Eskiz, data should be JSON for Notify API
response = requests.request( response = requests.request(
method, method,
f"{self.api_url}/{api_path}", url,
data=data, json=data if method != self.GET else None,
headers=headers, params=data if method == self.GET else None,
headers=final_headers,
timeout=10
) )
if api_path == self.methods["auth_refresh"]: if response.status_code == 401:
if response.status_code == 200: # Token might be expired, clear cache
incoming_data["status"] = "success" cache.delete(self.CACHE_KEY)
else:
try:
incoming_data = response.json() incoming_data = response.json()
except ValueError:
incoming_data = {"status": "error", "message": response.text}
if response.status_code >= 400:
logger.error(f"Eskiz API Error ({response.status_code}): {incoming_data}")
except requests.RequestException as error: except requests.RequestException as error:
logger.error(f"Eskiz Request Exception: {str(error)}")
raise Exception(str(error)) raise Exception(str(error))
return incoming_data return incoming_data
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): def auth(self):
data = {"email": self.email, "password": self.password} data = {"email": self.email, "password": self.password}
# Eskiz login expects JSON
return self.request( return self.request(
self.methods["auth_login"], data=data, method=self.POST self.methods["auth_login"], data=data, method=self.POST
) )
def refresh_token(self): def refresh_token(self):
token = self.auth()["data"]["token"] token = self.get_token()
self.headers["Authorization"] = "Bearer " + token headers = {"Authorization": f"Bearer {token}"}
context = { res = self.request(
"headers": self.headers, self.methods["auth_refresh"],
"method": self.PATCH, method=self.PATCH,
"api_path": self.methods["auth_refresh"], headers=headers,
}
return self.request(
context["api_path"],
method=context["method"],
headers=context["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): def get_my_user_info(self):
token = self.auth()["data"]["token"] token = self.get_token()
self.headers["Authorization"] = "Bearer " + token headers = {"Authorization": f"Bearer {token}"}
data = {
"headers": self.headers,
"method": self.GET,
"api_path": self.methods["auth_user"],
}
return self.request( return self.request(
data["api_path"], method=data["method"], headers=data["headers"] self.methods["auth_user"], method=self.GET, headers=headers
) )
def add_sms_contact(self, first_name, phone_number, group): def add_sms_contact(self, first_name, phone_number, group):
token = self.auth()["data"]["token"] token = self.get_token()
self.headers["Authorization"] = "Bearer " + token headers = {"Authorization": f"Bearer {token}"}
data = { data = {
"name": first_name, "name": first_name,
@@ -94,42 +124,32 @@ class SendService:
"mobile_phone": phone_number, "mobile_phone": phone_number,
} }
context = {
"headers": self.headers,
"method": self.POST,
"api_path": self.CONTACT,
"data": data,
}
return self.request( return self.request(
context["api_path"], self.CONTACT,
data=context["data"], data=data,
method=context["method"], method=self.POST,
headers=context["headers"], headers=headers,
) )
def send_sms(self, phone_number, message): def send_sms(self, phone_number, message):
token = self.auth()["data"]["token"] token = self.get_token()
self.headers["Authorization"] = "Bearer " + token if not token:
return {"status": "error", "message": "Failed to obtain auth token"}
headers = {"Authorization": f"Bearer {token}"}
# Use string "4546" for sender name
data = { data = {
"from": 4546, "from": "4546",
"mobile_phone": phone_number, "mobile_phone": phone_number,
"callback_url": self.callback_url, "callback_url": self.callback_url,
"message": message, "message": message,
} }
context = {
"headers": self.headers,
"method": self.POST,
"api_path": self.methods["send_message"],
"data": data,
}
res = self.request( res = self.request(
context["api_path"], self.methods["send_message"],
data=context["data"], data=data,
method=context["method"], method=self.POST,
headers=context["headers"], headers=headers,
) )
return res return res