From 0636a7a4cd2fc45c340a7873e517fc84517d3033 Mon Sep 17 00:00:00 2001 From: exanlv Date: Tue, 28 May 2024 11:29:37 +0200 Subject: [PATCH] Crude implementation to allow Promise V3 --- composer.json | 2 +- src/Discord/Bucket.php | 13 +++++++++- src/Discord/DriverInterface.php | 6 ++--- src/Discord/Drivers/Guzzle.php | 4 +-- src/Discord/Drivers/React.php | 4 +-- src/Discord/Http.php | 44 +++++++++++++++++++++------------ src/Discord/RateLimit.php | 4 ++- 7 files changed, 51 insertions(+), 26 deletions(-) diff --git a/composer.json b/composer.json index e4f2868..e10fe6d 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,7 @@ "php": "^7.4|^8.0", "react/http": "^1.2", "psr/log": "^1.1 || ^2.0 || ^3.0", - "react/promise": "^2.2" + "react/promise": "^2.2 || ^3.0.0" }, "suggest": { "guzzlehttp/guzzle": "For alternative to ReactPHP/Http Browser" diff --git a/src/Discord/Bucket.php b/src/Discord/Bucket.php index 990c339..59b753e 100644 --- a/src/Discord/Bucket.php +++ b/src/Discord/Bucket.php @@ -11,6 +11,7 @@ namespace Discord\Http; +use Composer\InstalledVersions; use Psr\Http\Message\ResponseInterface; use Psr\Log\LoggerInterface; use React\EventLoop\LoopInterface; @@ -87,6 +88,11 @@ class Bucket */ protected $resetTimer; + /** + * Whether react/promise v3 is used, if false, using v2 + */ + protected $promiseV3 = true; + /** * Bucket constructor. * @@ -100,6 +106,10 @@ public function __construct(string $name, LoopInterface $loop, LoggerInterface $ $this->loop = $loop; $this->logger = $logger; $this->runRequest = $runRequest; + + if (str_starts_with(InstalledVersions::getVersion('react/promise'), '0.3.')) { + $this->promiseV3 = true; + } } /** @@ -149,7 +159,8 @@ public function checkQueue() /** @var Request */ $request = $this->queue->dequeue(); - ($this->runRequest)($request)->done(function (ResponseInterface $response) use (&$checkQueue) { + // Promises v3 changed `->then` to behave as `->done` and removed `->then`. We still need the behaviour of `->done` in projects using v2 + ($this->runRequest)($request)->{$this->promiseV3 ? 'then' : 'done'}(function (ResponseInterface $response) use (&$checkQueue) { $resetAfter = (float) $response->getHeaderLine('X-Ratelimit-Reset-After'); $limit = $response->getHeaderLine('X-Ratelimit-Limit'); $remaining = $response->getHeaderLine('X-Ratelimit-Remaining'); diff --git a/src/Discord/DriverInterface.php b/src/Discord/DriverInterface.php index c83e809..4389149 100644 --- a/src/Discord/DriverInterface.php +++ b/src/Discord/DriverInterface.php @@ -12,7 +12,7 @@ namespace Discord\Http; use Psr\Http\Message\ResponseInterface; -use React\Promise\ExtendedPromiseInterface; +use React\Promise\PromiseInterface; /** * Interface for an HTTP driver. @@ -28,7 +28,7 @@ interface DriverInterface * * @param Request $request * - * @return ExtendedPromiseInterface + * @return PromiseInterface */ - public function runRequest(Request $request): ExtendedPromiseInterface; + public function runRequest(Request $request): PromiseInterface; } diff --git a/src/Discord/Drivers/Guzzle.php b/src/Discord/Drivers/Guzzle.php index 28af4f3..17b9bb6 100644 --- a/src/Discord/Drivers/Guzzle.php +++ b/src/Discord/Drivers/Guzzle.php @@ -17,7 +17,7 @@ use GuzzleHttp\RequestOptions; use React\EventLoop\LoopInterface; use React\Promise\Deferred; -use React\Promise\ExtendedPromiseInterface; +use React\Promise\PromiseInterface; /** * guzzlehttp/guzzle driver for Discord HTTP client. (still with React Promise). @@ -55,7 +55,7 @@ public function __construct(?LoopInterface $loop = null, array $options = []) $this->client = new Client($options); } - public function runRequest(Request $request): ExtendedPromiseInterface + public function runRequest(Request $request): PromiseInterface { // Create a React promise $deferred = new Deferred(); diff --git a/src/Discord/Drivers/React.php b/src/Discord/Drivers/React.php index 5f58fc8..de7697a 100644 --- a/src/Discord/Drivers/React.php +++ b/src/Discord/Drivers/React.php @@ -15,7 +15,7 @@ use Discord\Http\Request; use React\EventLoop\LoopInterface; use React\Http\Browser; -use React\Promise\ExtendedPromiseInterface; +use React\Promise\PromiseInterface; use React\Socket\Connector; /** @@ -54,7 +54,7 @@ public function __construct(LoopInterface $loop, array $options = []) $this->browser = $browser->withRejectErrorResponse(false); } - public function runRequest(Request $request): ExtendedPromiseInterface + public function runRequest(Request $request): PromiseInterface { return $this->browser->{$request->getMethod()}( $request->getUrl(), diff --git a/src/Discord/Http.php b/src/Discord/Http.php index 7a87e05..1b57b94 100644 --- a/src/Discord/Http.php +++ b/src/Discord/Http.php @@ -11,6 +11,7 @@ namespace Discord\Http; +use Composer\InstalledVersions; use Discord\Http\Exceptions\BadRequestException; use Discord\Http\Exceptions\ContentTooLongException; use Discord\Http\Exceptions\InvalidTokenException; @@ -24,7 +25,7 @@ use Psr\Log\LoggerInterface; use React\EventLoop\LoopInterface; use React\Promise\Deferred; -use React\Promise\ExtendedPromiseInterface; +use React\Promise\PromiseInterface; use SplQueue; /** @@ -127,6 +128,12 @@ class Http */ protected $waiting = 0; + + /** + * Whether react/promise v3 is used, if false, using v2 + */ + protected $promiseV3 = true; + /** * Http wrapper constructor. * @@ -141,6 +148,10 @@ public function __construct(string $token, LoopInterface $loop, LoggerInterface $this->logger = $logger; $this->driver = $driver; $this->queue = new SplQueue; + + if (str_starts_with(InstalledVersions::getVersion('react/promise'), '0.3.')) { + $this->promiseV3 = true; + } } /** @@ -160,9 +171,9 @@ public function setDriver(DriverInterface $driver): void * @param mixed $content * @param array $headers * - * @return ExtendedPromiseInterface + * @return PromiseInterface */ - public function get($url, $content = null, array $headers = []): ExtendedPromiseInterface + public function get($url, $content = null, array $headers = []): PromiseInterface { if (! ($url instanceof Endpoint)) { $url = Endpoint::bind($url); @@ -178,9 +189,9 @@ public function get($url, $content = null, array $headers = []): ExtendedPromise * @param mixed $content * @param array $headers * - * @return ExtendedPromiseInterface + * @return PromiseInterface */ - public function post($url, $content = null, array $headers = []): ExtendedPromiseInterface + public function post($url, $content = null, array $headers = []): PromiseInterface { if (! ($url instanceof Endpoint)) { $url = Endpoint::bind($url); @@ -196,9 +207,9 @@ public function post($url, $content = null, array $headers = []): ExtendedPromis * @param mixed $content * @param array $headers * - * @return ExtendedPromiseInterface + * @return PromiseInterface */ - public function put($url, $content = null, array $headers = []): ExtendedPromiseInterface + public function put($url, $content = null, array $headers = []): PromiseInterface { if (! ($url instanceof Endpoint)) { $url = Endpoint::bind($url); @@ -214,9 +225,9 @@ public function put($url, $content = null, array $headers = []): ExtendedPromise * @param mixed $content * @param array $headers * - * @return ExtendedPromiseInterface + * @return PromiseInterface */ - public function patch($url, $content = null, array $headers = []): ExtendedPromiseInterface + public function patch($url, $content = null, array $headers = []): PromiseInterface { if (! ($url instanceof Endpoint)) { $url = Endpoint::bind($url); @@ -232,9 +243,9 @@ public function patch($url, $content = null, array $headers = []): ExtendedPromi * @param mixed $content * @param array $headers * - * @return ExtendedPromiseInterface + * @return PromiseInterface */ - public function delete($url, $content = null, array $headers = []): ExtendedPromiseInterface + public function delete($url, $content = null, array $headers = []): PromiseInterface { if (! ($url instanceof Endpoint)) { $url = Endpoint::bind($url); @@ -251,9 +262,9 @@ public function delete($url, $content = null, array $headers = []): ExtendedProm * @param mixed $content * @param array $headers * - * @return ExtendedPromiseInterface + * @return PromiseInterface */ - public function queueRequest(string $method, Endpoint $url, $content, array $headers = []): ExtendedPromiseInterface + public function queueRequest(string $method, Endpoint $url, $content, array $headers = []): PromiseInterface { $deferred = new Deferred(); @@ -318,9 +329,9 @@ protected function guessContent(&$content) * @param Request $request * @param Deferred $deferred * - * @return ExtendedPromiseInterface + * @return PromiseInterface */ - protected function executeRequest(Request $request, Deferred $deferred = null): ExtendedPromiseInterface + protected function executeRequest(Request $request, Deferred $deferred = null): PromiseInterface { if ($deferred === null) { $deferred = new Deferred(); @@ -332,7 +343,8 @@ protected function executeRequest(Request $request, Deferred $deferred = null): return $deferred->promise(); } - $this->driver->runRequest($request)->done(function (ResponseInterface $response) use ($request, $deferred) { + // Promises v3 changed `->then` to behave as `->done` and removed `->then`. We still need the behaviour of `->done` in projects using v2 + $this->driver->runRequest($request)->{$this->promiseV3 ? 'then' : 'done'}(function (ResponseInterface $response) use ($request, $deferred) { $data = json_decode((string) $response->getBody()); $statusCode = $response->getStatusCode(); diff --git a/src/Discord/RateLimit.php b/src/Discord/RateLimit.php index 57ea2d6..0373f3f 100644 --- a/src/Discord/RateLimit.php +++ b/src/Discord/RateLimit.php @@ -11,12 +11,14 @@ namespace Discord\Http; +use RuntimeException; + /** * Represents a rate-limit given by Discord. * * @author David Cole */ -class RateLimit +class RateLimit extends RuntimeException { /** * Whether the rate-limit is global.