Start of the API class
This commit is contained in:
parent
11078c1767
commit
0289f00aa5
|
@ -7,4 +7,4 @@ namespace Aryess\PhpMatrixSdk\Exceptions;
|
|||
*
|
||||
* @package Aryess\PhpMatrixSdk\Exceptions
|
||||
*/
|
||||
abstract class MatrixException extends \Exception {}
|
||||
class MatrixException extends \Exception {}
|
|
@ -2,4 +2,261 @@
|
|||
|
||||
namespace Aryess\PhpMatrixSdk;
|
||||
|
||||
class MatrixHttpApi {}
|
||||
use Aryess\PhpMatrixSdk\Exceptions\MatrixException;
|
||||
use Aryess\PhpMatrixSdk\Exceptions\MatrixHttpLibException;
|
||||
use Aryess\PhpMatrixSdk\Exceptions\MatrixRequestException;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
|
||||
/**
|
||||
* Contains all raw Matrix HTTP Client-Server API calls.
|
||||
* For room and sync handling, consider using MatrixClient.
|
||||
*
|
||||
* Examples:
|
||||
* Create a client and send a message::
|
||||
*
|
||||
* $matrix = new MatrixHttpApi("https://matrix.org", $token="foobar");
|
||||
* $response = $matrix.sync();
|
||||
* $response = $matrix->sendMessage("!roomid:matrix.org", "Hello!");
|
||||
*
|
||||
* @package Aryess\PhpMatrixSdk
|
||||
*/
|
||||
class MatrixHttpApi {
|
||||
|
||||
const MATRIX_V2_API_PATH = "/_matrix/client/r0";
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $baseUrl;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $token;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $identity;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $default429WaitMs;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $useAuthorizationHeader;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $txnId;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $vallidateCert;
|
||||
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
private $client;
|
||||
|
||||
/**
|
||||
* MatrixHttpApi constructor.
|
||||
*
|
||||
* @param string $baseUrl The home server URL e.g. 'http://localhost:8008'
|
||||
* @param string|null $token Optional. The client's access token.
|
||||
* @param string|null $identity Optional. The mxid to act as (For application services only).
|
||||
* @param int $default429WaitMs Optional. Time in milliseconds to wait before retrying a request
|
||||
* when server returns a HTTP 429 response without a 'retry_after_ms' key.
|
||||
* @param bool $useAuthorizationHeader Optional. Use Authorization header instead of access_token query parameter.
|
||||
* @throws MatrixException
|
||||
*/
|
||||
public function __construct(string $baseUrl, ?string $token = null, ?string $identity = null,
|
||||
int $default429WaitMs = 5000, bool $useAuthorizationHeader = true) {
|
||||
if (!filter_var($baseUrl, FILTER_VALIDATE_URL)) {
|
||||
throw new MatrixException("Invalid homeserver url $baseUrl");
|
||||
}
|
||||
|
||||
if (!array_get(parse_url($baseUrl), 'scheme')) {
|
||||
throw new MatrixException("No scheme in homeserver url $baseUrl");
|
||||
}
|
||||
$this->baseUrl = $baseUrl;
|
||||
$this->token = $token;
|
||||
$this->identity = $identity;
|
||||
$this->txnId = 0;
|
||||
$this->vallidateCert = true;//FIXME: use config
|
||||
$this->client = new Client();
|
||||
$this->default429WaitMs = $default429WaitMs;
|
||||
$this->useAuthorizationHeader = $useAuthorizationHeader;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $since Optional. A token which specifies where to continue a sync from.
|
||||
* @param int $timeoutMs
|
||||
* @param null $filter
|
||||
* @param bool $fullState
|
||||
* @param string|null $setPresence
|
||||
* @return array|string
|
||||
* @throws MatrixException
|
||||
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||
*/
|
||||
public function sync(?string $since = null, int $timeoutMs = 30000, $filter = null,
|
||||
bool $fullState = false, ?string $setPresence = null) {
|
||||
$request = [
|
||||
'timeout' => (int)$timeoutMs,
|
||||
];
|
||||
|
||||
if ($since) {
|
||||
$request['since'] = $since;
|
||||
}
|
||||
|
||||
if ($filter) {
|
||||
$request['filter'] = $filter;
|
||||
}
|
||||
|
||||
if ($fullState) {
|
||||
$request['full_state'] = json_encode($fullState);
|
||||
}
|
||||
|
||||
if ($setPresence) {
|
||||
$request['set_presence'] = $setPresence;
|
||||
}
|
||||
|
||||
return $this->send('GET', "/sync", null, $request);
|
||||
}
|
||||
|
||||
public function validateCertificate(bool $validity) {
|
||||
$this->vallidateCert = $validity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs /register.
|
||||
*
|
||||
* @param array $authBody Authentication Params.
|
||||
* @param string $kind Specify kind of account to register. Can be 'guest' or 'user'.
|
||||
* @param bool $bindEmail Whether to use email in registration and authentication.
|
||||
* @param string|null $username The localpart of a Matrix ID.
|
||||
* @param string|null $password The desired password of the account.
|
||||
* @param string|null $deviceId ID of the client device.
|
||||
* @param string|null $initialDeviceDisplayName Display name to be assigned.
|
||||
* @param bool $inhibitLogin Whether to login after registration. Defaults to false.
|
||||
*/
|
||||
public function register(array $authBody = [], string $kind = "user", bool $bindEmail = false,
|
||||
?string $username = null, ?string $password = null, ?string $deviceId = null,
|
||||
?string $initialDeviceDisplayName = null, bool $inhibitLogin = false) {
|
||||
$content = [
|
||||
'kind' => $kind
|
||||
];
|
||||
if ($authBody) {
|
||||
$content['auth'] = $authBody;
|
||||
}
|
||||
if ($username) {
|
||||
$content['username'] = $username;
|
||||
}
|
||||
if ($password) {
|
||||
$content['password'] = $password;
|
||||
}
|
||||
if ($deviceId) {
|
||||
$content['device_id'] = $deviceId;
|
||||
}
|
||||
if ($initialDeviceDisplayName) {
|
||||
$content['initial_device_display_name'] = $initialDeviceDisplayName;
|
||||
}
|
||||
if ($bindEmail) {
|
||||
$content['bind_email'] = $bindEmail;
|
||||
}
|
||||
if ($inhibitLogin) {
|
||||
$content['inhibit_login'] = $inhibitLogin;
|
||||
}
|
||||
|
||||
return $this->send('POST', '/register', $content, ['kind' => $kind]);
|
||||
}
|
||||
|
||||
public function getDisplayName(string $userId): ?string {
|
||||
$content = $this->send("GET", "/profile/$userId/displayname");
|
||||
return array_get($content, 'displayname', json_encode($content));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $method
|
||||
* @param string $path
|
||||
* @param mixed $content
|
||||
* @param array $queryParams
|
||||
* @param array $headers
|
||||
* @param string $apiPath
|
||||
* @param bool $returnJson
|
||||
* @return array|string
|
||||
* @throws MatrixException
|
||||
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||
*/
|
||||
private function send(string $method, string $path, $content = null, array $queryParams = [], array $headers = [],
|
||||
$apiPath = self::MATRIX_V2_API_PATH, $returnJson = true) {
|
||||
$options = [];
|
||||
if (!in_array('User-Agent', $headers)) {
|
||||
$headers['User-Agent'] = 'php-matrix-sdk/0.0.1-dev'; //TODO: add version
|
||||
}
|
||||
|
||||
$method = strtoupper($method);
|
||||
if (!in_array($method, ['GET', 'POST', 'PUT', 'DELETE'])) {
|
||||
throw new MatrixException("Unsupported HTTP method: $method");
|
||||
}
|
||||
|
||||
if (!in_array('Content-Type', $headers)) {
|
||||
$headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
|
||||
if ($this->useAuthorizationHeader) {
|
||||
$headers['Authorization'] = sprintf('Bearer %s', $this->token);
|
||||
} else {
|
||||
$queryParams['access_token'] = $this->token;
|
||||
}
|
||||
|
||||
if ($this->identity) {
|
||||
$queryParams['user_id'] = $this->identity;
|
||||
}
|
||||
|
||||
$endpoint = $this->baseUrl . $apiPath . $path;
|
||||
if ($headers['Content-Type'] == "application/json" && $content != null) {
|
||||
$content = json_encode($content);
|
||||
}
|
||||
|
||||
$options = array_merge($options, [
|
||||
'headers' => $headers,
|
||||
'query' => $queryParams,
|
||||
'body' => $content,
|
||||
'verify' => $this->vallidateCert,
|
||||
]);
|
||||
|
||||
$responseBody = '';
|
||||
while (true) {
|
||||
try {
|
||||
$response = $this->client->request($method, $endpoint, $options);
|
||||
} catch (RequestException $e) {
|
||||
throw new MatrixHttpLibException($e, $method, $endpoint);
|
||||
}
|
||||
|
||||
if ($response->getStatusCode() != 429) {
|
||||
$responseBody = $response->getBody()->getContents();
|
||||
break;
|
||||
}
|
||||
|
||||
$jsonResponse = json_decode($responseBody, true);
|
||||
$waitTime = array_get($jsonResponse, 'retry_after_ms');
|
||||
$waitTime = $waitTime ?: array_get($jsonResponse, 'error.retry_after_ms', $this->default429WaitMs);
|
||||
$waitTime /= 1000;
|
||||
sleep($waitTime);
|
||||
}
|
||||
|
||||
if ($response->getStatusCode() < 200 || $response->getStatusCode() >= 300) {
|
||||
throw new MatrixRequestException($response->getStatusCode(), $responseBody);
|
||||
}
|
||||
|
||||
return $returnJson ? json_decode($responseBody, true) : $responseBody;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue