From d7166ccf3ba4b0e5e71dd135c873e88fbfa0d9aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFck=20Piera?= Date: Wed, 11 Dec 2024 11:19:19 +0100 Subject: [PATCH] Send the Discord spoiling code in attachment file (#307) * Remove Restcord and use symfony/http-client instead * Send the Discord spoiling code in attachment to avoid admin message length limit * Fix CI CS job * Use a retryable aware http client --- .github/workflows/ci.yml | 2 +- composer.json | 8 +- composer.lock | 538 +++++++++-------------------- config/packages/framework.yaml | 7 + src/Controller/SantaController.php | 2 +- src/Discord/ApiHelper.php | 114 ++++-- src/Discord/MessageSender.php | 13 +- src/Discord/UserExtractor.php | 30 +- src/Model/File.php | 21 ++ symfony.lock | 15 - 10 files changed, 297 insertions(+), 453 deletions(-) create mode 100644 src/Model/File.php diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b33b27ee..62f65e0e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,4 +54,4 @@ jobs: run: castor qa:phpstan - name: "Run PHP-CS-Fixer" - run: castor qa:cs + run: castor qa:cs --dry-run diff --git a/composer.json b/composer.json index 09fd0590..5c7e4f83 100644 --- a/composer.json +++ b/composer.json @@ -27,13 +27,13 @@ "nelmio/security-bundle": "^3.4.2", "nyholm/psr7": "^1.8.2", "predis/predis": "^2.2.2", - "restcord/restcord": "dev-feature/update-sf", "symfony/asset": ">=7.1.1", "symfony/console": ">=7.1.5", "symfony/flex": "^2.4.7", "symfony/form": ">=7.1.5", "symfony/framework-bundle": ">=7.1.5", "symfony/http-client": ">=7.1.5", + "symfony/mime": "7.1.*", "symfony/monolog-bundle": "^3.10", "symfony/runtime": ">=7.1.1", "symfony/twig-bundle": ">=7.1.5", @@ -53,12 +53,6 @@ "symfony/var-dumper": ">=7.1.5", "symfony/web-profiler-bundle": ">=7.1.4" }, - "repositories": { - "jewome62_restcord": { - "type": "vcs", - "url": "git@github.com:jewome62/restcord.git" - } - }, "config": { "optimize-autoloader": true, "preferred-install": { diff --git a/composer.lock b/composer.lock index 14cebc2d..421b758c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "029da97be237a184acf0505786c2f0fa", + "content-hash": "2afff3ef65d6c29ae77e5e8f8ad3bb92", "packages": [ { "name": "adam-paterson/oauth2-slack", @@ -539,89 +539,6 @@ ], "time": "2024-02-05T11:35:39+00:00" }, - { - "name": "guzzlehttp/command", - "version": "1.3.1", - "source": { - "type": "git", - "url": "https://github.com/guzzle/command.git", - "reference": "0eebc653784f4902b3272e826fe8e88743d14e77" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/command/zipball/0eebc653784f4902b3272e826fe8e88743d14e77", - "reference": "0eebc653784f4902b3272e826fe8e88743d14e77", - "shasum": "" - }, - "require": { - "guzzlehttp/guzzle": "^7.8", - "guzzlehttp/promises": "^1.5.3 || ^2.0.1", - "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", - "php": "^7.2.5 || ^8.0" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.19 || ^9.5.8" - }, - "type": "library", - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Command\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Jeremy Lindblom", - "email": "jeremeamia@gmail.com", - "homepage": "https://github.com/jeremeamia" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - } - ], - "description": "Provides the foundation for building command-based web service clients", - "support": { - "issues": "https://github.com/guzzle/command/issues", - "source": "https://github.com/guzzle/command/tree/1.3.1" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://github.com/Nyholm", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/command", - "type": "tidelift" - } - ], - "time": "2023-12-03T20:46:20+00:00" - }, { "name": "guzzlehttp/guzzle", "version": "7.9.2", @@ -748,93 +665,6 @@ ], "time": "2024-07-24T11:22:20+00:00" }, - { - "name": "guzzlehttp/guzzle-services", - "version": "1.4.1", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle-services.git", - "reference": "bcab7c0d61672b606510a6fe5af3039d04968c0f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle-services/zipball/bcab7c0d61672b606510a6fe5af3039d04968c0f", - "reference": "bcab7c0d61672b606510a6fe5af3039d04968c0f", - "shasum": "" - }, - "require": { - "guzzlehttp/command": "^1.3.1", - "guzzlehttp/guzzle": "^7.8", - "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", - "guzzlehttp/uri-template": "^1.0.1", - "php": "^7.2.5 || ^8.0" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.19 || ^9.5.8" - }, - "suggest": { - "gimler/guzzle-description-loader": "^0.0.4" - }, - "type": "library", - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Command\\Guzzle\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Stefano Kowalke", - "email": "blueduck@mail.org", - "homepage": "https://github.com/Konafets" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - } - ], - "description": "Provides an implementation of the Guzzle Command library that uses Guzzle service descriptions to describe web services, serialize requests, and parse responses into easy to use model structures.", - "support": { - "issues": "https://github.com/guzzle/guzzle-services/issues", - "source": "https://github.com/guzzle/guzzle-services/tree/1.4.1" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://github.com/Nyholm", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle-services", - "type": "tidelift" - } - ], - "time": "2023-12-03T20:48:14+00:00" - }, { "name": "guzzlehttp/promises", "version": "2.0.3", @@ -1034,92 +864,6 @@ ], "time": "2024-07-18T11:15:46+00:00" }, - { - "name": "guzzlehttp/uri-template", - "version": "v1.0.3", - "source": { - "type": "git", - "url": "https://github.com/guzzle/uri-template.git", - "reference": "ecea8feef63bd4fef1f037ecb288386999ecc11c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/uri-template/zipball/ecea8feef63bd4fef1f037ecb288386999ecc11c", - "reference": "ecea8feef63bd4fef1f037ecb288386999ecc11c", - "shasum": "" - }, - "require": { - "php": "^7.2.5 || ^8.0", - "symfony/polyfill-php80": "^1.24" - }, - "require-dev": { - "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.36 || ^9.6.15", - "uri-template/tests": "1.0.0" - }, - "type": "library", - "extra": { - "bamarni-bin": { - "bin-links": true, - "forward-command": false - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\UriTemplate\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Graham Campbell", - "email": "hello@gjcampbell.co.uk", - "homepage": "https://github.com/GrahamCampbell" - }, - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "George Mponos", - "email": "gmponos@gmail.com", - "homepage": "https://github.com/gmponos" - }, - { - "name": "Tobias Nyholm", - "email": "tobias.nyholm@gmail.com", - "homepage": "https://github.com/Nyholm" - } - ], - "description": "A polyfill class for uri_template of PHP", - "keywords": [ - "guzzlehttp", - "uri-template" - ], - "support": { - "issues": "https://github.com/guzzle/uri-template/issues", - "source": "https://github.com/guzzle/uri-template/tree/v1.0.3" - }, - "funding": [ - { - "url": "https://github.com/GrahamCampbell", - "type": "github" - }, - { - "url": "https://github.com/Nyholm", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/uri-template", - "type": "tidelift" - } - ], - "time": "2023-12-03T19:50:20+00:00" - }, { "name": "jane-php/json-schema-runtime", "version": "v7.8.1", @@ -1736,57 +1480,6 @@ }, "time": "2024-09-10T13:22:26+00:00" }, - { - "name": "netresearch/jsonmapper", - "version": "v1.6.0", - "source": { - "type": "git", - "url": "https://github.com/cweiske/jsonmapper.git", - "reference": "0d4d1b48d682a93b6bfedf60b88c7750e9cb0b06" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/0d4d1b48d682a93b6bfedf60b88c7750e9cb0b06", - "reference": "0d4d1b48d682a93b6bfedf60b88c7750e9cb0b06", - "shasum": "" - }, - "require": { - "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=5.6" - }, - "require-dev": { - "phpunit/phpunit": "~4.8.35 || ~5.7 || ~6.4", - "squizlabs/php_codesniffer": "~1.5" - }, - "type": "library", - "autoload": { - "psr-0": { - "JsonMapper": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "OSL-3.0" - ], - "authors": [ - { - "name": "Christian Weiske", - "email": "cweiske@cweiske.de", - "homepage": "http://github.com/cweiske/jsonmapper/", - "role": "Developer" - } - ], - "description": "Map nested JSON structures onto PHP classes", - "support": { - "email": "cweiske@cweiske.de", - "issues": "https://github.com/cweiske/jsonmapper/issues", - "source": "https://github.com/cweiske/jsonmapper/tree/master" - }, - "time": "2019-08-15T19:41:25+00:00" - }, { "name": "nyholm/psr7", "version": "1.8.2", @@ -2770,64 +2463,6 @@ }, "time": "2019-03-08T08:55:37+00:00" }, - { - "name": "restcord/restcord", - "version": "dev-feature/update-sf", - "source": { - "type": "git", - "url": "https://github.com/jewome62/restcord.git", - "reference": "fd55135723f0e3073d0d1667f8537bcde01f3bf3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/jewome62/restcord/zipball/fd55135723f0e3073d0d1667f8537bcde01f3bf3", - "reference": "fd55135723f0e3073d0d1667f8537bcde01f3bf3", - "shasum": "" - }, - "require": { - "guzzlehttp/guzzle": "^7.0", - "guzzlehttp/guzzle-services": "^1.0", - "netresearch/jsonmapper": "^1.4", - "php": "^7.3|^8.0", - "psr/log": "^2.0|^3.0", - "symfony/options-resolver": "^3.4|^4.4|^5.1|^6.0|^7.0" - }, - "require-dev": { - "beberlei/assert": "^2.7", - "gossi/php-code-generator": "^0.5.0", - "monolog/monolog": "^2.0|^3.0", - "phpunit/phpunit": "^8.0|^9.0", - "symfony/console": "^2.6|^3.0|^4.0", - "symfony/process": "^2.6|^3.0|^4.0", - "symfony/var-dumper": "^2.6|^3.0|^4.0", - "twig/twig": "^1.20|^2.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "RestCord\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "RestCord\\Test\\": "tests/" - } - }, - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Aaron Scherer", - "email": "aequasi@gmail.com" - } - ], - "description": "REST Library for the Discord API", - "support": { - "source": "https://github.com/jewome62/restcord/tree/feature/update-sf" - }, - "time": "2024-03-17T11:30:26+00:00" - }, { "name": "symfony/asset", "version": "v7.1.1", @@ -4421,6 +4056,90 @@ ], "time": "2024-11-13T14:25:32+00:00" }, + { + "name": "symfony/mime", + "version": "v7.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "caa1e521edb2650b8470918dfe51708c237f0598" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/caa1e521edb2650b8470918dfe51708c237f0598", + "reference": "caa1e521edb2650b8470918dfe51708c237f0598", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "egulias/email-validator": "~3.0.0", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/mailer": "<6.4", + "symfony/serializer": "<6.4.3|>7.0,<7.0.3" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10|^3.1|^4", + "league/html-to-markdown": "^5.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/serializer": "^6.4.3|^7.0.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows manipulating MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "support": { + "source": "https://github.com/symfony/mime/tree/v7.1.6" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-10-25T15:11:02+00:00" + }, { "name": "symfony/monolog-bridge", "version": "v7.1.1", @@ -4881,6 +4600,89 @@ ], "time": "2024-09-09T11:45:10+00:00" }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c36586dcf89a12315939e00ec9b4474adcb1d773", + "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, { "name": "symfony/polyfill-intl-normalizer", "version": "v1.31.0", @@ -7939,9 +7741,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "restcord/restcord": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/config/packages/framework.yaml b/config/packages/framework.yaml index 533c6c4d..0a66bacd 100644 --- a/config/packages/framework.yaml +++ b/config/packages/framework.yaml @@ -21,6 +21,13 @@ framework: php_errors: log: true + http_client: + default_options: + headers: + User-Agent: "secret-santa.team" + retry_failed: + enabled: true + when@test: framework: test: true diff --git a/src/Controller/SantaController.php b/src/Controller/SantaController.php index fbc85161..7c08e471 100644 --- a/src/Controller/SantaController.php +++ b/src/Controller/SantaController.php @@ -196,7 +196,7 @@ public function validate(Rudolph $rudolph, FormFactoryInterface $formFactory, Sp $config = $this->getConfigOrThrow404($request); if (!$config->getShuffledUsers()) { - if (count($config->getSelectedUsers()) < 2) { + if (\count($config->getSelectedUsers()) < 2) { return new RedirectResponse($this->router->generate('participants', ['application' => $application->getCode()])); } $config->setShuffledUsers($rudolph->associateUsers($config->getSelectedUsers())); diff --git a/src/Discord/ApiHelper.php b/src/Discord/ApiHelper.php index df0c3396..4d052e95 100644 --- a/src/Discord/ApiHelper.php +++ b/src/Discord/ApiHelper.php @@ -11,66 +11,108 @@ namespace JoliCode\SecretSanta\Discord; -use RestCord\DiscordClient; -use RestCord\Model\Guild\GuildMember; -use RestCord\Model\Permissions\Role; +use JoliCode\SecretSanta\Model\File; +use Symfony\Component\Mime\Part\DataPart; +use Symfony\Component\Mime\Part\Multipart\FormDataPart; +use Symfony\Contracts\HttpClient\HttpClientInterface; +use Symfony\Contracts\HttpClient\ResponseInterface; class ApiHelper { - private const TOKEN_TYPE_BOT = 'Bot'; - - private ?DiscordClient $client = null; - - public function __construct(private string $discordBotToken) - { + public function __construct( + private string $discordBotToken, + private HttpClientInterface $httpClient, + ) { } /** - * @return GuildMember[] + * @return list */ public function getMembersInGuild(int $guildId, ?int $after = null): array { - return $this->getClient()->guild->listGuildMembers([ - 'guild.id' => $guildId, - 'limit' => 200, - 'after' => $after, - ]); + $url = '/guilds/' . $guildId . '/members?limit=200'; + if ($after) { + $url .= '&after=' . $after; + } + + $response = $this->callApi('GET', $url, []); + + if (200 !== $response->getStatusCode()) { + throw new \RuntimeException('Failed to retrieve members: ' . $response->getContent(false)); + } + + return $response->toArray(); } /** - * @return Role[] + * @return list */ public function getRolesInGuild(int $guildId): array { - return $this->getClient()->guild->getGuildRoles([ - 'guild.id' => $guildId, - 'limit' => 100, - ]); + $response = $this->callApi('GET', '/guilds/' . $guildId . '/roles', []); + + if (200 !== $response->getStatusCode()) { + throw new \RuntimeException('Failed to retrieve roles: ' . $response->getContent(false)); + } + + return $response->toArray(); } - public function sendMessage(int $userId, string $message): void + public function sendMessage(int $userId, string $message, ?File $file = null): void { - $client = $this->getClient(); - - $channel = $client->user->createDm([ - 'recipient_id' => $userId, + // Create a private channel with the user + $response = $this->callApi('POST', '/users/@me/channels', [ + 'json' => [ + 'recipient_id' => $userId, + ], ]); - $client->channel->createMessage([ - 'channel.id' => $channel->id, + if (200 !== $response->getStatusCode()) { + throw new \RuntimeException('Failed to create private channel: ' . $response->getContent(false)); + } + + $channel = $response->toArray(); + $channelId = $channel['id']; + + $body = []; + $payload = [ 'content' => $message, - ]); + ]; + + if ($file) { + $payload['attachements'][] = [ + 'id' => 0, + 'description' => 'Secret Santa spoiling code', + 'filename' => $file->name, + ]; + $body['files[0]'] = new DataPart($file->content, $file->name, 'text/plain'); + } + + $body['payload_json'] = new DataPart(json_encode($payload), null, 'application/json'); + + $formData = new FormDataPart($body); + + $options = [ + 'body' => $formData->bodyToString(), + 'headers' => $formData->getPreparedHeaders()->toArray(), + ]; + + // Send message to the private channel + $response = $this->callApi('POST', "/channels/{$channelId}/messages", $options); + + if (200 !== $response->getStatusCode()) { + throw new \RuntimeException('Failed to send private message: ' . $response->getContent(false)); + } } - private function getClient(): DiscordClient + /** + * @param array $options + */ + private function callApi(string $method, string $endpoint, array $options): ResponseInterface { - if (!($this->client instanceof DiscordClient)) { - $this->client = new DiscordClient([ - 'token' => $this->discordBotToken, - 'tokenType' => self::TOKEN_TYPE_BOT, - ]); - } + $options['headers'] ??= []; + $options['headers'][] = 'Authorization: Bot ' . $this->discordBotToken; - return $this->client; + return $this->httpClient->request($method, 'https://discord.com/api/v10/' . $endpoint, $options); } } diff --git a/src/Discord/MessageSender.php b/src/Discord/MessageSender.php index f398d808..24b76089 100644 --- a/src/Discord/MessageSender.php +++ b/src/Discord/MessageSender.php @@ -11,9 +11,10 @@ namespace JoliCode\SecretSanta\Discord; -use GuzzleHttp\Command\Exception\CommandClientException; use JoliCode\SecretSanta\Exception\MessageSendFailedException; +use JoliCode\SecretSanta\Model\File; use JoliCode\SecretSanta\Model\SecretSanta; +use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface; class MessageSender { @@ -69,7 +70,7 @@ public function sendSecretMessage(SecretSanta $secretSanta, string $giver, strin try { $this->apiHelper->sendMessage((int) $giver, $text); - } catch (CommandClientException $e) { + } catch (ClientExceptionInterface $e) { $precision = null; if (($response = $e->getResponse()) && 403 === $response->getStatusCode()) { @@ -96,20 +97,18 @@ public function sendAdminMessage(SecretSanta $secretSanta, string $code, string In case of trouble or if you need it for whatever reason, here is a way to **retrieve the secret repartition**: -- Copy the following content: -```%s``` +- Copy the content of the `secret-santa-spoil-code.txt` file attached to this message - Paste the content on <%s> then submit Remember, with great power comes great responsibility! Happy Secret Santa!', - $code, $spoilUrl ); try { - $this->apiHelper->sendMessage((int) $secretSanta->getConfig()->getAdmin()->getIdentifier(), $text); - } catch (CommandClientException $e) { + $this->apiHelper->sendMessage((int) $secretSanta->getConfig()->getAdmin()->getIdentifier(), $text, new File('secret-santa-spoil-code.txt', $code)); + } catch (ClientExceptionInterface $e) { $precision = null; if (($response = $e->getResponse()) && 403 === $response->getStatusCode()) { diff --git a/src/Discord/UserExtractor.php b/src/Discord/UserExtractor.php index 7fa7be61..c30562b3 100644 --- a/src/Discord/UserExtractor.php +++ b/src/Discord/UserExtractor.php @@ -15,8 +15,6 @@ use JoliCode\SecretSanta\Exception\UserExtractionFailedException; use JoliCode\SecretSanta\Model\Group; use JoliCode\SecretSanta\Model\User; -use RestCord\Model\Guild\GuildMember; -use RestCord\Model\Guild\Role; class UserExtractor { @@ -29,10 +27,10 @@ public function __construct(private ApiHelper $apiHelper) */ public function extractForGuild(int $guildId): array { - /** @var GuildMember[] $members */ + /** @var list $members */ $members = []; - /** @var GuildMember[] $lastMembers */ + /** @var list $lastMembers */ $lastMembers = []; $startTime = time(); @@ -44,8 +42,7 @@ public function extractForGuild(int $guildId): array $lastMember = $lastMembers ? end($lastMembers) : null; try { - /** @var GuildMember[] $members */ - $lastMembers = $this->apiHelper->getMembersInGuild($guildId, $lastMember?->user->id); + $lastMembers = $this->apiHelper->getMembersInGuild($guildId, $lastMember['user']['id'] ?? null); } catch (\Throwable $t) { throw new UserExtractionFailedException(DiscordApplication::APPLICATION_CODE, 'Could not fetch members in guild.', $t); } @@ -53,20 +50,20 @@ public function extractForGuild(int $guildId): array $members = array_merge($members, $lastMembers); } while (!empty($lastMembers)); - $members = array_filter($members, function (GuildMember $member) { - return !$member->user->bot; + $members = array_filter($members, function (array $member) { + return !($member['user']['bot'] ?? false); }); $users = []; foreach ($members as $member) { $user = new User( - (string) $member->user->id, - $member->user->username, + (string) $member['user']['id'], + $member['user']['username'], [ - 'nickname' => $member->nick ?? null, - 'image' => $member->user->avatar ? \sprintf('https://cdn.discordapp.com/avatars/%s/%s.png', $member->user->id, $member->user->avatar) : null, - 'groups' => (array) $member->roles, + 'nickname' => $member['nick'] ?? null, + 'image' => ($member['user']['avatar'] ?? null) ? \sprintf('https://cdn.discordapp.com/avatars/%s/%s.png', $member['user']['id'], $member['user']['avatar']) : null, + 'groups' => (array) $member['roles'], ] ); @@ -85,19 +82,18 @@ public function extractForGuild(int $guildId): array */ public function extractGroupsForGuild(int $guildId): array { - /** @var Role[] $roles */ $roles = $this->apiHelper->getRolesInGuild($guildId); $groups = []; foreach ($roles as $role) { - if ('@everyone' === $role->name) { + if ('@everyone' === $role['name']) { continue; } $group = new Group( - (string) $role->id, - $role->name + (string) $role['id'], + $role['name'] ); $groups[$group->getIdentifier()] = $group; diff --git a/src/Model/File.php b/src/Model/File.php new file mode 100644 index 00000000..7db5cac0 --- /dev/null +++ b/src/Model/File.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace JoliCode\SecretSanta\Model; + +readonly class File +{ + public function __construct( + public string $name, + public string $content, + ) { + } +} diff --git a/symfony.lock b/symfony.lock index ca627da6..5439a17a 100644 --- a/symfony.lock +++ b/symfony.lock @@ -51,24 +51,15 @@ ".php-cs-fixer.dist.php" ] }, - "guzzlehttp/command": { - "version": "1.2.1" - }, "guzzlehttp/guzzle": { "version": "7.4.1" }, - "guzzlehttp/guzzle-services": { - "version": "1.3.1" - }, "guzzlehttp/promises": { "version": "1.5.1" }, "guzzlehttp/psr7": { "version": "2.1.0" }, - "guzzlehttp/uri-template": { - "version": "v1.0.1" - }, "jane-php/json-schema-runtime": { "version": "v7.1.5" }, @@ -102,9 +93,6 @@ "config/packages/nelmio_security.yaml" ] }, - "netresearch/jsonmapper": { - "version": "v1.6.0" - }, "nikic/php-parser": { "version": "v4.13.2" }, @@ -186,9 +174,6 @@ "ralouphie/getallheaders": { "version": "3.0.3" }, - "restcord/restcord": { - "version": "dev-Nispeon-patch-2" - }, "symfony/asset": { "version": "v6.0.1" },