├── src ├── Resources │ ├── doc │ │ └── index.md │ ├── config │ │ └── services.xml │ └── views │ │ └── data_collector.html.twig ├── Exception │ ├── InvalidArgumentException.php │ ├── InvalidPhoneNumberException.php │ ├── InvalidTdlibParametersException.php │ ├── InvalidAuthenticationCodeException.php │ ├── InvalidDatabaseEncryptionKeyException.php │ └── InvalidResponseException.php ├── TDLib │ ├── Response │ │ ├── Ok.php │ │ ├── Error.php │ │ ├── UpdateConnectionState.php │ │ ├── UpdateOption.php │ │ └── UpdateAuthorizationState.php │ ├── ResponseInterface.php │ ├── AbstractResponse.php │ ├── JsonClient.php │ └── AbstractJsonClient.php ├── YaroslavcheTDLibBundle.php ├── Service │ └── TDLib.php ├── DependencyInjection │ ├── YaroslavcheTDLibExtension.php │ └── Configuration.php ├── DataCollector │ └── TDLibCollector.php └── Command │ └── TDLibStartCommand.php ├── .gitignore ├── infection.json ├── phpstan.neon ├── phpcs.xml.dist ├── tests ├── TDLib │ └── JsonClientTest.php ├── FunctionalTest.php └── Kernel.php ├── LICENSE ├── phpunit.xml.dist ├── composer.json └── README.md /src/Resources/doc/index.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | /vendor/ 3 | /composer.lock 4 | /phpunit.xml 5 | /tests/cache/ 6 | .phpunit.result.cache 7 | .php_cs.cache 8 | clover.xml 9 | infection.log 10 | -------------------------------------------------------------------------------- /src/Exception/InvalidArgumentException.php: -------------------------------------------------------------------------------- 1 | extension) { 13 | $this->extension = new DependencyInjection\YaroslavcheTDLibExtension(); 14 | } 15 | 16 | return $this->extension; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /phpcs.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | src/ 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/TDLib/Response/Error.php: -------------------------------------------------------------------------------- 1 | code = $this->getProperty('code'); 20 | $this->message = $this->getProperty('message'); 21 | } 22 | 23 | /** 24 | * @return int|null 25 | */ 26 | public function getCode(): ?int 27 | { 28 | return $this->code; 29 | } 30 | 31 | /** 32 | * @return string|null 33 | */ 34 | public function getMessage(): ?string 35 | { 36 | return $this->message; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tests/TDLib/JsonClientTest.php: -------------------------------------------------------------------------------- 1 | client = new JsonClient($tdlibParameters, $clientConfig); 22 | $this->client->initJsonClient($clientConfig['phone_number']); 23 | } 24 | 25 | public function testVersion() 26 | { 27 | $clientVersion = $this->client->getOption('version'); 28 | $this->assertSame('1.4.0', $clientVersion); 29 | } 30 | 31 | /** @todo have problems in tests =( */ 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 yaroslavche 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | ./tests 24 | 25 | 26 | 27 | 28 | 29 | ./src 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/TDLib/Response/UpdateConnectionState.php: -------------------------------------------------------------------------------- 1 | getProperty('state'); 21 | $state = $stateProperty->{'@type'}; 22 | if (!in_array($state, [ 23 | static::CONNECTION_STATE_READY, 24 | ])) { 25 | throw new InvalidResponseException($state, InvalidResponseException::INVALID_VALUE); 26 | } 27 | $this->state = $state; 28 | } 29 | 30 | /** 31 | * @return string|null 32 | */ 33 | public function getState(): ?string 34 | { 35 | return $this->state; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/FunctionalTest.php: -------------------------------------------------------------------------------- 1 | kernel = new Kernel(); 25 | $this->kernel->boot(); 26 | $container = $this->kernel->getContainer(); 27 | LogConfiguration::setLogVerbosityLevel(LogConfiguration::LVL_ERROR); 28 | $this->tdlibService = $container->get('yaroslavche_tdlib.service.tdlib'); 29 | } 30 | 31 | public function testServiceWiring() 32 | { 33 | $this->assertInstanceOf(TDLib::class, $this->tdlibService); 34 | } 35 | 36 | protected function tearDown(): void 37 | { 38 | parent::tearDown(); 39 | td_json_client_destroy($this->tdlibService->getJsonClient()->getJsonClient()); 40 | }*/ 41 | } 42 | -------------------------------------------------------------------------------- /src/Resources/config/services.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/Service/TDLib.php: -------------------------------------------------------------------------------- 1 | jsonClient = new JsonClient($parameters, $client); 33 | } 34 | 35 | /** 36 | * @return JsonClient 37 | */ 38 | public function getJsonClient(): JsonClient 39 | { 40 | return $this->jsonClient; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/DependencyInjection/YaroslavcheTDLibExtension.php: -------------------------------------------------------------------------------- 1 | load('services.xml'); 27 | 28 | $configuration = $this->getConfiguration($configs, $container); 29 | $config = $this->processConfiguration($configuration, $configs); 30 | 31 | $definition = $container->getDefinition('yaroslavche_tdlib.service.tdlib'); 32 | $definition->setArguments([ 33 | $config['parameters'], 34 | $config['client'], 35 | ]); 36 | } 37 | 38 | /** 39 | * @return string 40 | */ 41 | public function getAlias() 42 | { 43 | return static::EXTENSION_ALIAS; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/TDLib/Response/UpdateOption.php: -------------------------------------------------------------------------------- 1 | name = $this->getProperty('name'); 32 | $optionValue = $this->getProperty('value'); 33 | $this->value = $optionValue->value; 34 | $this->valueType = $optionValue->{'@type'}; 35 | } 36 | 37 | public function getName(): ?string 38 | { 39 | return $this->name; 40 | } 41 | 42 | /** 43 | * @return string|bool|int|null 44 | */ 45 | public function getValue() 46 | { 47 | return $this->value; 48 | } 49 | 50 | /** 51 | * @return string|null 52 | */ 53 | public function getValueType(): ?string 54 | { 55 | return $this->valueType; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yaroslavche/tdlib-bundle", 3 | "type": "symfony-bundle", 4 | "description": "Symfony tdlib/td API bundle", 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "yaroslavche", 9 | "email": "yaroslav429@gmail.com" 10 | } 11 | ], 12 | "require": { 13 | "php": "^7.2", 14 | "ext-tdlib": "*", 15 | "ext-json": "*", 16 | "symfony/framework-bundle": "^4.3", 17 | "symfony/config": "^4.3", 18 | "symfony/dependency-injection": "^4.3", 19 | "symfony/options-resolver": "^4.3", 20 | "symfony/console": "^4.3", 21 | "cboden/ratchet": "^0.4.1" 22 | }, 23 | "autoload": { 24 | "psr-4": { 25 | "Yaroslavche\\TDLibBundle\\": "src/" 26 | } 27 | }, 28 | "autoload-dev": { 29 | "psr-4": { 30 | "Yaroslavche\\TDLibBundle\\Tests\\": "tests/" 31 | } 32 | }, 33 | "require-dev": { 34 | "phptdlib/phptdlib-stubs": "@dev", 35 | "symfony/phpunit-bridge": "^4.3", 36 | "phpunit/phpunit": "^8.2", 37 | "symfony/debug-pack": "^1.0", 38 | "phpstan/phpstan": "^0.11.12", 39 | "squizlabs/php_codesniffer": "^3.4", 40 | "thecodingmachine/phpstan-strict-rules": "^0.11.2", 41 | "infection/infection": "^0.13.4", 42 | "roave/backward-compatibility-check": "^3.0" 43 | }, 44 | "scripts": { 45 | "cscheck": "phpcs", 46 | "csfix": "phpcbf", 47 | "phpstan": "phpstan analyse src/ -c phpstan.neon --level=7 --no-progress -vvv --memory-limit=1024M", 48 | "phpunit": "phpunit", 49 | "infection": "infection --min-msi=50 --min-covered-msi=70 --log-verbosity=all", 50 | "clover": "phpunit --coverage-clover clover.xml", 51 | "bccheck": "roave-backward-compatibility-check" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Resources/views/data_collector.html.twig: -------------------------------------------------------------------------------- 1 | {% extends '@WebProfiler/Profiler/layout.html.twig' %} 2 | 3 | {% block toolbar %} 4 | {% set icon %} 5 |
6 | {{ collector.version }} 7 | TDLib 8 |
9 | {% endset %} 10 | 11 | {% set text %} 12 |
13 | TDLib client version 14 | {{ collector.version }} 15 |
16 |
17 | Authorization State 18 | {{ collector.authorizationState.type }} 19 |
20 | {% endset %} 21 | 22 | {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { 'link': true }) }} 23 | {% endblock %} 24 | 25 | {% block head %} 26 | {{- parent() -}} 27 | {% endblock %} 28 | 29 | {% block menu %} 30 | 31 | TDLib 32 | TDLib 33 | 34 | {% endblock %} 35 | 36 | {% block panel %} 37 | {{ collector.version }} 38 | {{ dump(collector.authorizationState) }} 39 | {{ dump(collector.me) }} 40 | 56 | {% endblock %} 57 | -------------------------------------------------------------------------------- /src/TDLib/Response/UpdateAuthorizationState.php: -------------------------------------------------------------------------------- 1 | getProperty('authorization_state'); 26 | $authorizationState = $authorizationStateProperty->{'@type'}; 27 | if (!in_array($authorizationState, [ 28 | static::AUTHORIZATION_STATE_READY, 29 | static::AUTHORIZATION_STATE_WAIT_PHONE_NUMBER, 30 | static::AUTHORIZATION_STATE_WAIT_CODE, 31 | static::AUTHORIZATION_STATE_WAIT_TDLIB_PARAMETERS, 32 | static::AUTHORIZATION_STATE_WAIT_ENCRYPTION_KEY, 33 | static::AUTHORIZATION_STATE_LOGGING_OUT, 34 | ])) { 35 | throw new InvalidResponseException($authorizationState, InvalidResponseException::INVALID_VALUE); 36 | } 37 | $this->authorizationState = $authorizationState; 38 | } 39 | 40 | /** 41 | * @return string|null 42 | */ 43 | public function getAuthorizationState(): ?string 44 | { 45 | return $this->authorizationState; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/DataCollector/TDLibCollector.php: -------------------------------------------------------------------------------- 1 | jsonClient = $tdlib->getJsonClient(); 27 | } 28 | 29 | 30 | /** 31 | * Collects data for the given Request and Response. 32 | * @param Request $request 33 | * @param Response $response 34 | * @param Exception|null $exception 35 | */ 36 | public function collect(Request $request, Response $response, Exception $exception = null) 37 | { 38 | $this->data['version'] = $this->jsonClient->getOption('version'); 39 | $this->data['authorizationState'] = $this->jsonClient->getAuthorizationState(); 40 | $this->data['me'] = $this->jsonClient->getMe(); 41 | } 42 | 43 | /** 44 | * Returns the name of the collector. 45 | * 46 | * @return string The collector name 47 | */ 48 | public function getName() 49 | { 50 | return static::DATA_COLLECTOR_NAME; 51 | } 52 | 53 | public function reset() 54 | { 55 | $this->data = []; 56 | } 57 | 58 | /** 59 | * @return string 60 | */ 61 | public function getVersion(): string 62 | { 63 | return $this->data['version']; 64 | } 65 | 66 | /** 67 | * @return ResponseInterface 68 | */ 69 | public function getAuthorizationState(): ResponseInterface 70 | { 71 | return $this->data['authorizationState']; 72 | } 73 | 74 | /** 75 | * @return ResponseInterface 76 | */ 77 | public function getMe(): ResponseInterface 78 | { 79 | return $this->data['me']; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/TDLib/AbstractResponse.php: -------------------------------------------------------------------------------- 1 | rawResponse = $rawResponse; 45 | $this->response = $response; 46 | $this->type = $response->{'@type'}; 47 | $this->extra = property_exists($response, '@extra') ? $response->{'@extra'} : null; 48 | } 49 | 50 | /** 51 | * @return string|null 52 | */ 53 | public function getType(): ?string 54 | { 55 | return $this->type; 56 | } 57 | 58 | /** 59 | * @return string|null 60 | */ 61 | public function getExtra(): ?string 62 | { 63 | return $this->extra; 64 | } 65 | 66 | /** 67 | * @param string $name 68 | * @return mixed|null 69 | * @throws InvalidResponseException 70 | */ 71 | protected function getProperty(string $name) 72 | { 73 | if (!property_exists($this->response, $name)) { 74 | throw new InvalidResponseException('', InvalidResponseException::UNRECOGNIZED_PROPERTY); 75 | } 76 | return $this->response->{$name}; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/DependencyInjection/Configuration.php: -------------------------------------------------------------------------------- 1 | getRootNode(); 17 | $rootNode 18 | ->children() 19 | ->arrayNode('parameters') 20 | ->children() 21 | /** required */ 22 | ->integerNode('api_id')->isRequired()->end() 23 | ->scalarNode('api_hash')->isRequired()->end() 24 | ->scalarNode('system_language_code')->isRequired()->defaultValue('en')->end() 25 | ->scalarNode('device_model')->isRequired()->defaultValue(php_uname('s'))->end() 26 | ->scalarNode('system_version')->isRequired()->defaultValue(php_uname('v'))->end() 27 | ->scalarNode('application_version')->isRequired()->defaultValue('0.0.1')->end() 28 | /** optional */ 29 | ->scalarNode('use_test_dc')->defaultTrue()->end() 30 | ->scalarNode('database_directory')->defaultValue('/var/tmp/tdlib')->end() 31 | ->scalarNode('files_directory')->defaultValue('/var/tmp/tdlib')->end() 32 | ->booleanNode('use_file_database')->defaultTrue()->end() 33 | ->booleanNode('use_chat_info_database')->defaultTrue()->end() 34 | ->booleanNode('use_message_database')->defaultTrue()->end() 35 | ->booleanNode('use_secret_chats')->defaultTrue()->end() 36 | ->booleanNode('enable_storage_optimizer')->defaultTrue()->end() 37 | ->booleanNode('ignore_file_names')->defaultTrue()->end() 38 | ->end() 39 | ->end() 40 | ->arrayNode('client') 41 | ->children() 42 | ->scalarNode('phone_number')->defaultNull()->end() 43 | ->scalarNode('encryption_key')->defaultValue('')->end() 44 | ->floatNode('default_timeout')->defaultValue(0.5)->end() 45 | ->booleanNode('auto_init')->defaultFalse()->end() 46 | ->end() 47 | ->end() 48 | ->end(); 49 | return $treeBuilder; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /tests/Kernel.php: -------------------------------------------------------------------------------- 1 | [ 55 | /** required */ 56 | TDLibParameters::API_ID => (int)$_ENV['API_ID'], 57 | TDLibParameters::API_HASH => $_ENV['API_HASH'], 58 | TDLibParameters::SYSTEM_LANGUAGE_CODE => 'en', 59 | TDLibParameters::DEVICE_MODEL => 'test', 60 | TDLibParameters::SYSTEM_VERSION => 'stable', 61 | TDLibParameters::APPLICATION_VERSION => '0.0.1', 62 | /** optional */ 63 | TDLibParameters::USE_TEST_DC => true, 64 | TDLibParameters::IGNORE_FILE_NAMES => true, 65 | TDLibParameters::USE_SECRET_CHATS => true, 66 | TDLibParameters::USE_MESSAGE_DATABASE => true, 67 | TDLibParameters::USE_CHAT_INFO_DATABASE => true, 68 | TDLibParameters::USE_FILE_DATABASE => true, 69 | TDLibParameters::FILES_DIRECTORY => '/var/tmp/tdlib', 70 | TDLibParameters::DATABASE_DIRECTORY => '/var/tmp/tdlib', 71 | ], 72 | 'client' => [ 73 | 'phone_number' => $_ENV['PHONE_NUMBER'], 74 | 'encryption_key' => '', 75 | 'default_timeout' => 10, 76 | 'auto_init' => false, 77 | ] 78 | ]; 79 | } 80 | 81 | /** 82 | * @param RouteCollectionBuilder $routes 83 | * @throws LoaderLoadException 84 | */ 85 | protected function configureRoutes(RouteCollectionBuilder $routes) 86 | { 87 | $routes->import(__DIR__ . '/../src/Resources/config/routes.xml'); 88 | } 89 | 90 | /** 91 | * @param ContainerBuilder $c 92 | * @param LoaderInterface $loader 93 | */ 94 | protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader) 95 | { 96 | $c->loadFromExtension( 97 | 'framework', 98 | [ 99 | 'secret' => 'test' 100 | ] 101 | ); 102 | $c->loadFromExtension('yaroslavche_tdlib', static::getBundleConfig()); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/Command/TDLibStartCommand.php: -------------------------------------------------------------------------------- 1 | ready = true; 38 | $this->io = $io; 39 | try { 40 | LogConfiguration::setLogVerbosityLevel(LogConfiguration::LVL_ERROR); 41 | $this->jsonClient = new JsonClient(); 42 | $setTdlibParametersResponse = $this->jsonClient->query(json_encode([ 43 | '@type' => 'setTdlibParameters', 44 | 'parameters' => $tdlibParameters 45 | ])); 46 | $checkDatabaseEncryptionKeyResponse = $this->jsonClient->query(json_encode([ 47 | '@type' => 'checkDatabaseEncryptionKey', 48 | 'encryption_key' => $clientConfig['encryption_key'] ?? '' 49 | ])); 50 | /** @todo $this->jsonClient = (new BundleJsonClient($tdlibParameters, $clientConfig))->getJsonClient(); */ 51 | } catch (Exception $e) { 52 | $this->ready = false; 53 | $io->error(get_class($e)); 54 | } 55 | if ($this->ready) { 56 | $io->success('created'); 57 | } 58 | } 59 | 60 | public function onOpen(ConnectionInterface $conn) 61 | { 62 | $this->io->writeln('onOpen'); 63 | } 64 | 65 | public function onMessage(ConnectionInterface $from, $message) 66 | { 67 | 68 | $this->io->writeln(sprintf('Request: %s', $message)); 69 | if ($this->ready) { 70 | $response = $this->jsonClient->query($message); 71 | $this->io->writeln(sprintf('Response: %s', $response)); 72 | $from->send($response); 73 | } else { 74 | $from->send(json_encode(['@type' => 'error'])); 75 | } 76 | } 77 | 78 | public function onClose(ConnectionInterface $conn) 79 | { 80 | $this->io->writeln('onClose'); 81 | } 82 | 83 | public function onError(ConnectionInterface $conn, Exception $exception) 84 | { 85 | $conn->send(json_encode(['@type' => 'error', 'message' => $exception->getMessage()])); 86 | } 87 | } 88 | 89 | class TDLibStartCommand extends Command 90 | { 91 | protected static $defaultName = 'tdlib:start'; 92 | 93 | protected function configure() 94 | { 95 | $this 96 | ->setDescription('Start socket server with TDLib JsonClient') 97 | ->addOption('port', null, InputOption::VALUE_OPTIONAL, 'Port', 8080) 98 | ->addOption('api_id', null, InputOption::VALUE_REQUIRED, 'API Id') 99 | ->addOption('api_hash', null, InputOption::VALUE_REQUIRED, 'API Hash') 100 | ->addOption('encryption_key', null, InputOption::VALUE_REQUIRED, 'Phone number'); 101 | } 102 | 103 | protected function execute(InputInterface $input, OutputInterface $output) 104 | { 105 | $io = new SymfonyStyle($input, $output); 106 | $port = $input->getOption('port'); 107 | $apiId = $input->getOption('api_id'); 108 | $apiHash = $input->getOption('api_hash'); 109 | $encryptionKey = $input->getOption('encryption_key') ?? ''; 110 | if (null === $apiId || null === $apiHash) { 111 | $io->error('Please fill required options. Type --help for view options list'); 112 | return 1; 113 | } 114 | 115 | $tdlibParameters = [ 116 | TDLibParameters::USE_TEST_DC => false, 117 | TDLibParameters::DATABASE_DIRECTORY => '/var/tmp/tdlib', 118 | TDLibParameters::FILES_DIRECTORY => '/var/tmp/tdlib', 119 | TDLibParameters::USE_FILE_DATABASE => true, 120 | TDLibParameters::USE_CHAT_INFO_DATABASE => true, 121 | TDLibParameters::USE_MESSAGE_DATABASE => true, 122 | TDLibParameters::USE_SECRET_CHATS => true, 123 | TDLibParameters::API_ID => $apiId, 124 | TDLibParameters::API_HASH => $apiHash, 125 | TDLibParameters::SYSTEM_LANGUAGE_CODE => 'en', 126 | TDLibParameters::DEVICE_MODEL => php_uname('s'), 127 | TDLibParameters::SYSTEM_VERSION => php_uname('v'), 128 | TDLibParameters::APPLICATION_VERSION => '0.0.1', 129 | TDLibParameters::ENABLE_STORAGE_OPTIMIZER => true, 130 | TDLibParameters::IGNORE_FILE_NAMES => true, 131 | ]; 132 | $clientConfig = [ 133 | 'encryption_key' => $encryptionKey 134 | ]; 135 | 136 | $server = IoServer::factory( 137 | new HttpServer( 138 | new WsServer( 139 | new TDLibWS($io, $tdlibParameters, $clientConfig) 140 | ) 141 | ), 142 | $port 143 | ); 144 | 145 | $server->run(); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Installation 2 | ```bash 3 | $ composer require yaroslavche/tdlib-bundle 4 | ``` 5 | 6 | ## WebSocket server with initialized JsonClient (experimental) 7 | Create console application (`console.php`): 8 | ```php 9 | #!/usr/bin/env php 10 | add(new TDLibStartCommand()); 21 | 22 | $application->run(); 23 | 24 | ``` 25 | and run: 26 | ```bash 27 | $ php console.php tdlib:start --port=12345 --api_id=11111 --api_hash=abcdef1234567890abcdef1234567890 28 | ``` 29 | Then create HTML file (`index.html`) 30 | ```html 31 | 32 | 33 | 34 | 35 | 36 | TDLib WebSocket Example 37 | 38 | 39 | 42 | 43 | 44 |
45 |
46 |
47 |
48 |
49 | 50 |
51 |
52 | Query 53 |
54 |
55 |
56 |
57 | 60 |
61 |

{{ entry }}

62 |
63 |
64 |
65 |
66 |
67 |
68 | 69 | 98 | 99 | 100 | ``` 101 | Open in browser. Queries: 102 | ``` 103 | {"@type": "setAuthenticationPhoneNumber", "phone_number": "+380991234567"} 104 | {"@type": "checkAuthenticationCode", "code": "12345"} 105 | ``` 106 | And [others](https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_function.html). 107 | 108 | # Symfony bundle configuration 109 | Create file `config/packages/yaroslavche_tdlib.yaml` with following content 110 | ```yaml 111 | # config/packages/yaroslavche_tdlib.yaml 112 | 113 | yaroslavche_tdlib: 114 | parameters: 115 | use_test_dc: true 116 | database_directory: "/var/tmp/tdlib" 117 | files_directory: "/var/tmp/tdlib" 118 | use_file_database: true 119 | use_chat_info_database: true 120 | use_message_database: true 121 | use_secret_chats: true 122 | api_id: 11111 123 | api_hash: 'abcdef1234567890abcdef1234567890' 124 | system_language_code: "en" 125 | device_model: "php" 126 | system_version: "7.2" 127 | application_version: "0.0.1" 128 | enable_storage_optimizer: true 129 | ignore_file_names: true 130 | client: 131 | phone_number: "+380991234567" 132 | encryption_key: "" 133 | default_timeout: 0.5 134 | auto_init: false 135 | ``` 136 | 137 | ## Data Collector 138 | With installed `symfony/profiler-pack`. 139 | 140 | *If reached timeout exception, then seems bundle config is passed, but can't connect to client. Should configure for real one `api_id`, `api_hash` and `phone_number` (can be `test_dc`). 141 | 142 | ## Usage 143 | 144 | ### JsonClient 145 | ```php 146 | use TDApi\LogConfiguration; 147 | use Yaroslavche\TDLibBundle\TDLib\JsonClient; 148 | use Yaroslavche\TDLibBundle\TDLib\Response\UpdateAuthorizationState; 149 | 150 | LogConfiguration::setLogVerbosityLevel(LogConfiguration::LVL_FATAL_ERROR); 151 | $tdlibParameters = [/** from config */]; 152 | $clientConfig = [/** from config */]; 153 | $client = new JsonClient($tdlibParameters, $clientConfig); 154 | 155 | if ($clientConfig['auto_init'] === false) 156 | { 157 | $client->initJsonClient(); 158 | } 159 | 160 | var_dump($client->getOption('version')); 161 | 162 | $authorizationStateResponse = $client->getAuthorizationState(); 163 | if ($authorizationStateResponse->getType() === UpdateAuthorizationState::AUTHORIZATION_STATE_WAIT_PHONE_NUMBER) 164 | { 165 | $client->setAuthenticationPhoneNumber('+380991234567'); 166 | } 167 | else if ($authorizationStateResponse->getType() === UpdateAuthorizationState::AUTHORIZATION_STATE_READY) 168 | { 169 | var_dump($client->getMe()); 170 | } 171 | ``` 172 | 173 | ### TDLib Service 174 | Service provides `getJsonClient` method, which will return `Yaroslavche\TDLibBundle\TDLib\JsonClient`. Inject service and use as you need. For example: 175 | ```php 176 | use Yaroslavche\TDLibBundle\Service\TDLib; 177 | 178 | final class GetMeController 179 | { 180 | /** 181 | * @Route("/getMe", name="getMe") 182 | */ 183 | public function __invoke(TDLib $tdlib): Response 184 | { 185 | $tdlib->getJsonClient()->getMe(); 186 | } 187 | } 188 | ``` 189 | -------------------------------------------------------------------------------- /src/TDLib/JsonClient.php: -------------------------------------------------------------------------------- 1 | query('setAuthenticationPhoneNumber', [ 12 | 'phone_number' => $phoneNumber, 13 | 'allow_flash_call' => $allowFlashCall ?? false, 14 | 'is_current_phone_number' => $isCurrentPhoneNumber ?? false, 15 | ]); 16 | } 17 | 18 | public function getAuthorizationState(): ResponseInterface 19 | { 20 | return $this->query('getAuthorizationState'); 21 | } 22 | 23 | public function getMe(): ResponseInterface 24 | { 25 | return $this->query('getMe'); 26 | } 27 | } 28 | 29 | 30 | // https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_function.html 31 | /* 32 | - [ ] acceptCall 33 | - [ ] acceptTermsOfService 34 | - [ ] addChatMember 35 | - [ ] addChatMembers 36 | - [ ] addFavoriteSticker 37 | - [ ] addLocalMessage 38 | - [ ] addNetworkStatistics 39 | - [ ] addProxy 40 | - [ ] addRecentlyFoundChat 41 | - [ ] addRecentSticker 42 | - [ ] addSavedAnimation 43 | - [ ] addStickerToSet 44 | - [ ] answerCallbackQuery 45 | - [ ] answerCustomQuery 46 | - [ ] answerInlineQuery 47 | - [ ] answerPreCheckoutQuery 48 | - [ ] answerShippingQuery 49 | - [ ] blockUser 50 | - [ ] cancelDownloadFile 51 | - [ ] cancelUploadFile 52 | - [ ] changeChatReportSpamState 53 | - [ ] changeImportedContacts 54 | - [ ] changePhoneNumber 55 | - [ ] changeStickerSet 56 | - [ ] checkAuthenticationBotToken 57 | - [ ] checkAuthenticationCode 58 | - [ ] checkAuthenticationPassword 59 | - [ ] checkChangePhoneNumberCode 60 | - [ ] checkChatInviteLink 61 | - [ ] checkChatUsername 62 | - [ ] checkDatabaseEncryptionKey 63 | - [ ] checkEmailAddressVerificationCode 64 | - [ ] checkPhoneNumberConfirmationCode 65 | - [ ] checkPhoneNumberVerificationCode 66 | - [ ] cleanFileName 67 | - [ ] clearAllDraftMessages 68 | - [ ] clearImportedContacts 69 | - [ ] clearRecentlyFoundChats 70 | - [ ] clearRecentStickers 71 | - [ ] close 72 | - [ ] closeChat 73 | - [ ] closeSecretChat 74 | - [ ] createBasicGroupChat 75 | - [ ] createCall 76 | - [ ] createNewBasicGroupChat 77 | - [ ] createNewSecretChat 78 | - [ ] createNewStickerSet 79 | - [ ] createNewSupergroupChat 80 | - [ ] createPrivateChat 81 | - [ ] createSecretChat 82 | - [ ] createSupergroupChat 83 | - [ ] createTemporaryPassword 84 | - [ ] deleteAccount 85 | - [ ] deleteChatHistory 86 | - [ ] deleteChatMessagesFromUser 87 | - [ ] deleteChatReplyMarkup 88 | - [ ] deleteFile 89 | - [ ] deleteLanguagePack 90 | - [ ] deleteMessages 91 | - [ ] deletePassportElement 92 | - [ ] deleteProfilePhoto 93 | - [ ] deleteSavedCredentials 94 | - [ ] deleteSavedOrderInfo 95 | - [ ] deleteSupergroup 96 | - [ ] destroy 97 | - [ ] disableProxy 98 | - [ ] discardCall 99 | - [ ] disconnectAllWebsites 100 | - [ ] disconnectWebsite 101 | - [ ] downloadFile 102 | - [ ] editCustomLanguagePackInfo 103 | - [ ] editInlineMessageCaption 104 | - [ ] editInlineMessageLiveLocation 105 | - [ ] editInlineMessageMedia 106 | - [ ] editInlineMessageReplyMarkup 107 | - [ ] editInlineMessageText 108 | - [ ] editMessageCaption 109 | - [ ] editMessageLiveLocation 110 | - [ ] editMessageMedia 111 | - [ ] editMessageReplyMarkup 112 | - [ ] editMessageText 113 | - [ ] editProxy 114 | - [ ] enableProxy 115 | - [ ] finishFileGeneration 116 | - [ ] forwardMessages 117 | - [ ] generateChatInviteLink 118 | - [ ] getAccountTtl 119 | - [ ] getActiveLiveLocationMessages 120 | - [ ] getActiveSessions 121 | - [ ] getAllPassportElements 122 | - [ ] getArchivedStickerSets 123 | - [ ] getAttachedStickerSets 124 | - [ ] getAuthorizationState 125 | - [ ] getBasicGroup 126 | - [ ] getBasicGroupFullInfo 127 | - [ ] getBlockedUsers 128 | - [ ] getCallbackQueryAnswer 129 | - [ ] getChat 130 | - [ ] getChatAdministrators 131 | - [ ] getChatEventLog 132 | - [ ] getChatHistory 133 | - [ ] getChatMember 134 | - [ ] getChatMessageByDate 135 | - [ ] getChatMessageCount 136 | - [ ] getChatPinnedMessage 137 | - [ ] getChatReportSpamState 138 | - [ ] getChats 139 | - [ ] getConnectedWebsites 140 | - [ ] getContacts 141 | - [ ] getCountryCode 142 | - [ ] getCreatedPublicChats 143 | - [ ] getDeepLinkInfo 144 | - [ ] getFavoriteStickers 145 | - [ ] getFile 146 | - [ ] getFileExtension 147 | - [ ] getFileMimeType 148 | - [ ] getGameHighScores 149 | - [ ] getGroupsInCommon 150 | - [ ] getImportedContactCount 151 | - [ ] getInlineGameHighScores 152 | - [ ] getInlineQueryResults 153 | - [ ] getInstalledStickerSets 154 | - [ ] getInviteText 155 | - [ ] getLanguagePackString 156 | - [ ] getLanguagePackStrings 157 | - [ ] getLocalizationTargetInfo 158 | - [ ] getMapThumbnailFile 159 | - [ ] getMe 160 | - [ ] getMessage 161 | - [ ] getMessages 162 | - [ ] getNetworkStatistics 163 | - [ ] getOption 164 | - [ ] getPassportAuthorizationForm 165 | - [ ] getPassportElement 166 | - [ ] getPasswordState 167 | - [ ] getPaymentForm 168 | - [ ] getPaymentReceipt 169 | - [ ] getPreferredCountryLanguage 170 | - [ ] getProxies 171 | - [ ] getProxyLink 172 | - [ ] getPublicMessageLink 173 | - [ ] getRecentInlineBots 174 | - [ ] getRecentlyVisitedTMeUrls 175 | - [ ] getRecentStickers 176 | - [ ] getRecoveryEmailAddress 177 | - [ ] getRemoteFile 178 | - [ ] getRepliedMessage 179 | - [ ] getSavedAnimations 180 | - [ ] getSavedOrderInfo 181 | - [ ] getScopeNotificationSettings 182 | - [ ] getSecretChat 183 | - [ ] getStickerEmojis 184 | - [ ] getStickers 185 | - [ ] getStickerSet 186 | - [ ] getStorageStatistics 187 | - [ ] getStorageStatisticsFast 188 | - [ ] getSupergroup 189 | - [ ] getSupergroupFullInfo 190 | - [ ] getSupergroupMembers 191 | - [ ] getSupportUser 192 | - [ ] getTemporaryPasswordState 193 | - [ ] getTextEntities 194 | - [ ] getTopChats 195 | - [ ] getTrendingStickerSets 196 | - [ ] getUser 197 | - [ ] getUserFullInfo 198 | - [ ] getUserPrivacySettingRules 199 | - [ ] getUserProfilePhotos 200 | - [ ] getWallpapers 201 | - [ ] getWebPageInstantView 202 | - [ ] getWebPagePreview 203 | - [ ] importContacts 204 | - [ ] joinChat 205 | - [ ] joinChatByInviteLink 206 | - [ ] leaveChat 207 | - [ ] logOut 208 | - [ ] openChat 209 | - [ ] openMessageContent 210 | - [ ] optimizeStorage 211 | - [ ] parseTextEntities 212 | - [ ] pingProxy 213 | - [ ] pinSupergroupMessage 214 | - [ ] processDcUpdate 215 | - [ ] readAllChatMentions 216 | - [ ] recoverAuthenticationPassword 217 | - [ ] recoverPassword 218 | - [ ] registerDevice 219 | - [ ] removeContacts 220 | - [ ] removeFavoriteSticker 221 | - [ ] removeProxy 222 | - [ ] removeRecentHashtag 223 | - [ ] removeRecentlyFoundChat 224 | - [ ] removeRecentSticker 225 | - [ ] removeSavedAnimation 226 | - [ ] removeStickerFromSet 227 | - [ ] removeTopChat 228 | - [ ] reorderInstalledStickerSets 229 | - [ ] reportChat 230 | - [ ] reportSupergroupSpam 231 | - [ ] requestAuthenticationPasswordRecovery 232 | - [ ] requestPasswordRecovery 233 | - [ ] resendAuthenticationCode 234 | - [ ] resendChangePhoneNumberCode 235 | - [ ] resendEmailAddressVerificationCode 236 | - [ ] resendPhoneNumberConfirmationCode 237 | - [ ] resendPhoneNumberVerificationCode 238 | - [ ] resetAllNotificationSettings 239 | - [ ] resetNetworkStatistics 240 | - [ ] searchCallMessages 241 | - [ ] searchChatMembers 242 | - [ ] searchChatMessages 243 | - [ ] searchChatRecentLocationMessages 244 | - [ ] searchChats 245 | - [ ] searchChatsOnServer 246 | - [ ] searchContacts 247 | - [ ] searchHashtags 248 | - [ ] searchInstalledStickerSets 249 | - [ ] searchMessages 250 | - [ ] searchPublicChat 251 | - [ ] searchPublicChats 252 | - [ ] searchSecretMessages 253 | - [ ] searchStickers 254 | - [ ] searchStickerSet 255 | - [ ] searchStickerSets 256 | - [ ] sendBotStartMessage 257 | - [ ] sendCallDebugInformation 258 | - [ ] sendCallRating 259 | - [ ] sendChatAction 260 | - [ ] sendChatScreenshotTakenNotification 261 | - [ ] sendChatSetTtlMessage 262 | - [ ] sendCustomRequest 263 | - [ ] sendEmailAddressVerificationCode 264 | - [ ] sendInlineQueryResultMessage 265 | - [ ] sendMessage 266 | - [ ] sendMessageAlbum 267 | - [ ] sendPassportAuthorizationForm 268 | - [ ] sendPaymentForm 269 | - [ ] sendPhoneNumberConfirmationCode 270 | - [ ] sendPhoneNumberVerificationCode 271 | - [ ] setAccountTtl 272 | - [ ] setAlarm 273 | - [ ] setAuthenticationPhoneNumber 274 | - [ ] setBio 275 | - [ ] setBotUpdatesStatus 276 | - [ ] setChatClientData 277 | - [ ] setChatDraftMessage 278 | - [ ] setChatMemberStatus 279 | - [ ] setChatNotificationSettings 280 | - [ ] setChatPhoto 281 | - [ ] setChatTitle 282 | - [ ] setCustomLanguagePack 283 | - [ ] setCustomLanguagePackString 284 | - [ ] setDatabaseEncryptionKey 285 | - [ ] setFileGenerationProgress 286 | - [ ] setGameScore 287 | - [ ] setInlineGameScore 288 | - [ ] setName 289 | - [ ] setNetworkType 290 | - [ ] setOption 291 | - [ ] setPassportElement 292 | - [ ] setPassportElementErrors 293 | - [ ] setPassword 294 | - [ ] setPinnedChats 295 | - [ ] setProfilePhoto 296 | - [ ] setRecoveryEmailAddress 297 | - [ ] setScopeNotificationSettings 298 | - [ ] setStickerPositionInSet 299 | - [ ] setSupergroupDescription 300 | - [ ] setSupergroupStickerSet 301 | - [ ] setSupergroupUsername 302 | - [ ] setTdlibParameters 303 | - [ ] setUsername 304 | - [ ] setUserPrivacySettingRules 305 | - [ ] terminateAllOtherSessions 306 | - [ ] terminateSession 307 | - [ ] testCallBytes 308 | - [ ] testCallEmpty 309 | - [ ] testCallString 310 | - [ ] testCallVectorInt 311 | - [ ] testCallVectorIntObject 312 | - [ ] testCallVectorString 313 | - [ ] testCallVectorStringObject 314 | - [ ] testGetDifference 315 | - [ ] testNetwork 316 | - [ ] testSquareInt 317 | - [ ] testUseError 318 | - [ ] testUseUpdate 319 | - [ ] toggleBasicGroupAdministrators 320 | - [ ] toggleChatDefaultDisableNotification 321 | - [ ] toggleChatIsMarkedAsUnread 322 | - [ ] toggleChatIsPinned 323 | - [ ] toggleSupergroupInvites 324 | - [ ] toggleSupergroupIsAllHistoryAvailable 325 | - [ ] toggleSupergroupSignMessages 326 | - [ ] unblockUser 327 | - [ ] unpinSupergroupMessage 328 | - [ ] upgradeBasicGroupChatToSupergroupChat 329 | - [ ] uploadFile 330 | - [ ] uploadStickerFile 331 | - [ ] validateOrderInfo 332 | - [ ] viewMessages 333 | - [ ] viewTrendingStickerSets 334 | */ 335 | -------------------------------------------------------------------------------- /src/TDLib/AbstractJsonClient.php: -------------------------------------------------------------------------------- 1 | optionsResolver = new OptionsResolver(); 50 | $this->tdlibParameters = $this->resolve($tdlibParameters, [ 51 | TDLibParameters::USE_TEST_DC => true, 52 | TDLibParameters::DATABASE_DIRECTORY => '/var/tmp/tdlib', 53 | TDLibParameters::FILES_DIRECTORY => '/var/tmp/tdlib', 54 | TDLibParameters::USE_FILE_DATABASE => true, 55 | TDLibParameters::USE_CHAT_INFO_DATABASE => true, 56 | TDLibParameters::USE_MESSAGE_DATABASE => true, 57 | TDLibParameters::USE_SECRET_CHATS => true, 58 | TDLibParameters::API_ID => null, 59 | TDLibParameters::API_HASH => null, 60 | TDLibParameters::SYSTEM_LANGUAGE_CODE => 'en', 61 | TDLibParameters::DEVICE_MODEL => php_uname('s'), 62 | TDLibParameters::SYSTEM_VERSION => php_uname('v'), 63 | TDLibParameters::APPLICATION_VERSION => '0.0.1', 64 | TDLibParameters::ENABLE_STORAGE_OPTIMIZER => true, 65 | TDLibParameters::IGNORE_FILE_NAMES => true, 66 | ]); 67 | /** 68 | * @todo 69 | * - check if directories exists and accessible and will be used 70 | * - enable debug if test_dc true? 71 | * - check other important (?) 72 | */ 73 | $this->clientConfig = $this->resolve($clientConfig, [ 74 | 'phone_number' => null, 75 | 'encryption_key' => '', 76 | 'default_timeout' => 0.5, 77 | 'auto_init' => true 78 | ]); 79 | if (false !== $this->clientConfig['auto_init']) { 80 | $this->initJsonClient($clientConfig['phone_number']); 81 | } 82 | } 83 | 84 | /** 85 | * @param string $type 86 | * @param mixed[] $params 87 | * @param float|null $timeout 88 | * @return ResponseInterface 89 | * @throws InvalidArgumentException 90 | * @throws InvalidResponseException 91 | */ 92 | public function query(string $type, array $params = [], ?float $timeout = null): ResponseInterface 93 | { 94 | $query = json_encode(array_merge(['@type' => $type], $params)); 95 | if (!$query) { 96 | throw new InvalidArgumentException(); 97 | } 98 | /** @todo invalid timeout parameter */ 99 | $rawResponse = $this->jsonClient->query($query); //, $timeout ?? $this->clientConfig['default_timeout']); 100 | $response = AbstractResponse::fromRaw($rawResponse); 101 | $responseClass = sprintf('%s\\Response\\%s', __NAMESPACE__, ucfirst($response->getType())); 102 | if (class_exists($responseClass)) { 103 | $response = new $responseClass($rawResponse); 104 | } 105 | return $response; 106 | } 107 | 108 | /** 109 | * @param string $name 110 | * @return bool|int|string|null 111 | */ 112 | public function getOption(string $name) 113 | { 114 | return $this->options[$name]; 115 | } 116 | 117 | /** 118 | * @param string|null $phoneNumber 119 | * @param bool|null $force 120 | * @throws InvalidArgumentException 121 | * @throws InvalidAuthenticationCodeException 122 | * @throws InvalidDatabaseEncryptionKeyException 123 | * @throws InvalidPhoneNumberException 124 | * @throws InvalidResponseException 125 | * @throws InvalidTdlibParametersException 126 | */ 127 | public function initJsonClient(?string $phoneNumber = null, ?bool $force = null): void 128 | { 129 | if (!$force && $this->jsonClient instanceof JsonClient) { 130 | return; 131 | } 132 | $this->jsonClient = new JsonClient(); 133 | $this->jsonClient->setDefaultTimeout(floatval($this->clientConfig['default_timeout'])); 134 | /** set tdlib parameters */ 135 | $setParametersResponse = $this->query('setTdlibParameters', [ 136 | 'parameters' => $this->tdlibParameters, 137 | ]); 138 | if ($setParametersResponse->getType() !== 'ok') { 139 | throw new InvalidTdlibParametersException(); 140 | } 141 | /** set database encryption key */ 142 | $setEncryptionKeyResult = $this->query('setDatabaseEncryptionKey', [ 143 | 'new_encryption_key' => $this->clientConfig['encryption_key'] ?? '' 144 | ]); 145 | if ($setEncryptionKeyResult->getType() !== 'ok') { 146 | throw new InvalidDatabaseEncryptionKeyException(); 147 | } 148 | /** check all received responses */ 149 | $this->handleResponses(); 150 | 151 | if (null !== $phoneNumber && $this->authorizationState === UpdateAuthorizationState::AUTHORIZATION_STATE_WAIT_PHONE_NUMBER) { 152 | $setAuthenticationPhoneNumberResponse = $this->query('setAuthenticationPhoneNumber', [ 153 | 'phone_number' => $phoneNumber 154 | ]); 155 | if ($setAuthenticationPhoneNumberResponse->getType() !== 'ok') { 156 | throw new InvalidPhoneNumberException(); 157 | } 158 | $this->handleResponses(); 159 | } 160 | 161 | if ($this->authorizationState === UpdateAuthorizationState::AUTHORIZATION_STATE_WAIT_CODE) { 162 | $code = $_POST[sprintf('code_%s', $phoneNumber)] ?? null; 163 | if (null === $code) { 164 | throw new RuntimeException(sprintf('Please set authentication code for %s', $phoneNumber)); 165 | } 166 | $checkAuthenticationCodeResponse = $this->query('checkAuthenticationCode', [ 167 | 'code' => $code 168 | ]); 169 | if ($checkAuthenticationCodeResponse->getType() !== 'ok') { 170 | throw new InvalidAuthenticationCodeException(); 171 | } 172 | } 173 | } 174 | 175 | /** 176 | * @param mixed[] $options 177 | * @param mixed[] $defaults 178 | * @return mixed[] 179 | */ 180 | protected function resolve(array $options, array $defaults = []): array 181 | { 182 | $this->optionsResolver->clear(); 183 | $this->optionsResolver->setDefaults($defaults); 184 | return $this->optionsResolver->resolve($options); 185 | } 186 | 187 | /** 188 | * @throws InvalidArgumentException 189 | * @throws InvalidResponseException 190 | */ 191 | protected function handleResponses(): void 192 | { 193 | $responses = $this->jsonClient->getReceivedResponses(); 194 | foreach ($responses as $rawResponse) { 195 | $responseObject = AbstractResponse::fromRaw($rawResponse); 196 | switch ($responseObject->getType()) { 197 | case 'updateOption': 198 | $this->updateOption(UpdateOption::fromRaw($rawResponse)); 199 | break; 200 | case 'updateAuthorizationState': 201 | $this->updateAuthorizationState(UpdateAuthorizationState::fromRaw($rawResponse)); 202 | break; 203 | default: 204 | break; 205 | } 206 | } 207 | } 208 | 209 | /** 210 | * @param ResponseInterface $updateOptionResponse 211 | * @throws InvalidArgumentException 212 | */ 213 | protected function updateOption(ResponseInterface $updateOptionResponse): void 214 | { 215 | if (!$updateOptionResponse instanceof UpdateOption) { 216 | throw new InvalidArgumentException(); 217 | } 218 | $value = $updateOptionResponse->getValue(); 219 | switch ($updateOptionResponse->getValueType()) { 220 | case UpdateOption::OPTION_VALUE_INTEGER: 221 | $value = (int)$value; 222 | break; 223 | case UpdateOption::OPTION_VALUE_BOOLEAN: 224 | $value = (bool)$value; 225 | break; 226 | case UpdateOption::OPTION_VALUE_STRING: 227 | default: 228 | break; 229 | } 230 | $this->options[$updateOptionResponse->getName()] = $value; 231 | } 232 | 233 | /** 234 | * @param ResponseInterface $updateAuthorizationStateResponse 235 | * @throws InvalidArgumentException 236 | */ 237 | protected function updateAuthorizationState(ResponseInterface $updateAuthorizationStateResponse): void 238 | { 239 | if (!$updateAuthorizationStateResponse instanceof UpdateAuthorizationState) { 240 | throw new InvalidArgumentException(); 241 | } 242 | $this->authorizationState = $updateAuthorizationStateResponse->getAuthorizationState(); 243 | } 244 | } 245 | --------------------------------------------------------------------------------