feat: chat

This commit is contained in:
2026-06-09 11:24:15 -04:00
parent 454bb57484
commit 8fac3d2bae
15 changed files with 2015 additions and 38 deletions
+96 -1
View File
@@ -10,10 +10,17 @@ class UEXError(RuntimeError):
class UEXClient:
def __init__(self, base_url: str, secret_key: str | None = None, bearer_token: str | None = None) -> None:
def __init__(
self,
base_url: str,
secret_key: str | None = None,
bearer_token: str | None = None,
negotiation_close_endpoint: str = "marketplace_negotiations_close",
) -> None:
self.base_url = base_url.rstrip("/")
self.secret_key = secret_key
self.bearer_token = bearer_token
self.negotiation_close_endpoint = negotiation_close_endpoint.strip().strip("/") or "marketplace_negotiations_close"
def _headers(self, authenticated: bool = False) -> dict[str, str]:
headers = {"Accept": "application/json"}
@@ -49,6 +56,94 @@ class UEXClient:
data = [data]
return {"status": body.get("status"), "notifications": data}
async def list_negotiations(
self,
id: int | None = None,
id_listing: int | None = None,
hash: str | None = None,
) -> dict[str, Any]:
body = await self.get(
"marketplace_negotiations",
{"id": id, "id_listing": id_listing, "hash": hash},
authenticated=True,
)
data = body.get("data") or []
if isinstance(data, dict):
data = [data]
return {"status": body.get("status"), "negotiations": data}
async def get_negotiation_messages(self, hash: str | None = None, id_negotiation: int | None = None) -> dict[str, Any]:
body = await self.get(
"marketplace_negotiations_messages",
{"hash": hash, "id_negotiation": id_negotiation},
authenticated=True,
)
data = body.get("data") or []
if isinstance(data, dict):
data = [data]
return {"status": body.get("status"), "messages": data}
async def send_negotiation_message(
self,
*,
message: str,
hash: str | None = None,
id_negotiation: int | None = None,
is_production: int = 1,
) -> dict[str, Any]:
return await self.post(
"marketplace_negotiations_messages",
{
"hash": hash,
"id_negotiation": id_negotiation,
"message": message,
"is_production": is_production,
},
authenticated=True,
)
async def close_negotiation(
self,
*,
hash: str | None = None,
id_negotiation: int | None = None,
deal_closed: bool,
deal_value: float | None = None,
currency: str | None = None,
clarity_rating: int | None = None,
speed_rating: int | None = None,
respect_rating: int | None = None,
fairness_rating: int | None = None,
comment: str | None = None,
is_production: int = 1,
) -> dict[str, Any]:
payload = {
"hash": hash,
"id_negotiation": id_negotiation,
"deal_closed": 1 if deal_closed else 0,
"deal_value": deal_value,
"currency": currency,
"clarity_rating": clarity_rating,
"speed_rating": speed_rating,
"respect_rating": respect_rating,
"fairness_rating": fairness_rating,
"comment": comment,
"is_production": is_production,
}
try:
return await self.post(
self.negotiation_close_endpoint,
payload,
authenticated=True,
)
except UEXError as exc:
raise UEXError(
"UEX negotiation close failed via endpoint "
f"`{self.negotiation_close_endpoint}`. If UEX changed this route, set "
"`UEX_NEGOTIATION_CLOSE_ENDPOINT` to the correct endpoint and retry. "
f"Original error: {exc}"
) from exc
async def post(self, path: str, payload: dict[str, Any], authenticated: bool = True) -> dict[str, Any]:
async with httpx.AsyncClient(timeout=30) as client:
response = await client.post(