import time from json import JSONDecodeError from typing import Any, Optional from urllib.parse import urljoin import requests from aleksis.core.util.core_helpers import get_site_preferences class MatrixException(Exception): pass def build_url(path: str) -> str: """Build a URL to the Matrix Client Server API.""" return urljoin( urljoin(get_site_preferences()["matrix__homeserver"], "_matrix/client/v3/"), path ) def get_headers() -> dict[str, str]: """Get the headers for a Matrix Client Server API request.""" return { "Authorization": "Bearer " + get_site_preferences()["matrix__access_token"], } def do_matrix_request(method: str, url: str, body: Optional[dict] = None) -> dict[str, Any]: """Do a HTTP request to the Matrix Client Server API.""" while True: res = requests.request(method=method, url=build_url(url), headers=get_headers(), json=body) try: data = res.json() except JSONDecodeError: raise MatrixException(res.text) from JSONDecodeError if res.status_code == requests.codes.ok: break # If rate limit exceeded, wait and retry if data.get("errcode", "") == "M_LIMIT_EXCEEDED": time.sleep(data["retry_after_ms"] / 1000) else: raise MatrixException(data) return data