diff --git a/a.php b/a.php new file mode 100644 index 000000000..9f6ddf422 --- /dev/null +++ b/a.php @@ -0,0 +1,7 @@ +bots->sendCustomRequest](../methods/bots_sendCustomRequest.md) - -[$MadelineProto->phone->getCallConfig](../methods/phone_getCallConfig.md) - - +## Type: DataJSON +[Back to constructor index](index.md) +Any json-encodable data. \ No newline at end of file diff --git a/docs/MTProto_docs/types/DataJSON.md b/docs/MTProto_docs/types/DataJSON.md new file mode 100644 index 000000000..b43fab0eb --- /dev/null +++ b/docs/MTProto_docs/types/DataJSON.md @@ -0,0 +1,8 @@ +--- +title: DataJSON +description: Any json-encodable data +--- +## Type: DataJSON +[Back to constructor index](index.md) + +Any json-encodable data. \ No newline at end of file diff --git a/docs/TD_docs/types/DataJSON.md b/docs/TD_docs/types/DataJSON.md new file mode 100644 index 000000000..b43fab0eb --- /dev/null +++ b/docs/TD_docs/types/DataJSON.md @@ -0,0 +1,8 @@ +--- +title: DataJSON +description: Any json-encodable data +--- +## Type: DataJSON +[Back to constructor index](index.md) + +Any json-encodable data. \ No newline at end of file diff --git a/old_docs/API_docs_v18/types/DataJSON.md b/old_docs/API_docs_v18/types/DataJSON.md new file mode 100644 index 000000000..b43fab0eb --- /dev/null +++ b/old_docs/API_docs_v18/types/DataJSON.md @@ -0,0 +1,8 @@ +--- +title: DataJSON +description: Any json-encodable data +--- +## Type: DataJSON +[Back to constructor index](index.md) + +Any json-encodable data. \ No newline at end of file diff --git a/old_docs/API_docs_v23/types/DataJSON.md b/old_docs/API_docs_v23/types/DataJSON.md new file mode 100644 index 000000000..b43fab0eb --- /dev/null +++ b/old_docs/API_docs_v23/types/DataJSON.md @@ -0,0 +1,8 @@ +--- +title: DataJSON +description: Any json-encodable data +--- +## Type: DataJSON +[Back to constructor index](index.md) + +Any json-encodable data. \ No newline at end of file diff --git a/old_docs/API_docs_v25/types/DataJSON.md b/old_docs/API_docs_v25/types/DataJSON.md new file mode 100644 index 000000000..b43fab0eb --- /dev/null +++ b/old_docs/API_docs_v25/types/DataJSON.md @@ -0,0 +1,8 @@ +--- +title: DataJSON +description: Any json-encodable data +--- +## Type: DataJSON +[Back to constructor index](index.md) + +Any json-encodable data. \ No newline at end of file diff --git a/old_docs/API_docs_v27/types/DataJSON.md b/old_docs/API_docs_v27/types/DataJSON.md new file mode 100644 index 000000000..b43fab0eb --- /dev/null +++ b/old_docs/API_docs_v27/types/DataJSON.md @@ -0,0 +1,8 @@ +--- +title: DataJSON +description: Any json-encodable data +--- +## Type: DataJSON +[Back to constructor index](index.md) + +Any json-encodable data. \ No newline at end of file diff --git a/old_docs/API_docs_v33/types/DataJSON.md b/old_docs/API_docs_v33/types/DataJSON.md new file mode 100644 index 000000000..b43fab0eb --- /dev/null +++ b/old_docs/API_docs_v33/types/DataJSON.md @@ -0,0 +1,8 @@ +--- +title: DataJSON +description: Any json-encodable data +--- +## Type: DataJSON +[Back to constructor index](index.md) + +Any json-encodable data. \ No newline at end of file diff --git a/old_docs/API_docs_v38/types/DataJSON.md b/old_docs/API_docs_v38/types/DataJSON.md new file mode 100644 index 000000000..b43fab0eb --- /dev/null +++ b/old_docs/API_docs_v38/types/DataJSON.md @@ -0,0 +1,8 @@ +--- +title: DataJSON +description: Any json-encodable data +--- +## Type: DataJSON +[Back to constructor index](index.md) + +Any json-encodable data. \ No newline at end of file diff --git a/old_docs/API_docs_v40/types/DataJSON.md b/old_docs/API_docs_v40/types/DataJSON.md new file mode 100644 index 000000000..b43fab0eb --- /dev/null +++ b/old_docs/API_docs_v40/types/DataJSON.md @@ -0,0 +1,8 @@ +--- +title: DataJSON +description: Any json-encodable data +--- +## Type: DataJSON +[Back to constructor index](index.md) + +Any json-encodable data. \ No newline at end of file diff --git a/old_docs/API_docs_v41/types/DataJSON.md b/old_docs/API_docs_v41/types/DataJSON.md new file mode 100644 index 000000000..b43fab0eb --- /dev/null +++ b/old_docs/API_docs_v41/types/DataJSON.md @@ -0,0 +1,8 @@ +--- +title: DataJSON +description: Any json-encodable data +--- +## Type: DataJSON +[Back to constructor index](index.md) + +Any json-encodable data. \ No newline at end of file diff --git a/old_docs/API_docs_v42/types/DataJSON.md b/old_docs/API_docs_v42/types/DataJSON.md new file mode 100644 index 000000000..b43fab0eb --- /dev/null +++ b/old_docs/API_docs_v42/types/DataJSON.md @@ -0,0 +1,8 @@ +--- +title: DataJSON +description: Any json-encodable data +--- +## Type: DataJSON +[Back to constructor index](index.md) + +Any json-encodable data. \ No newline at end of file diff --git a/old_docs/API_docs_v44/types/DataJSON.md b/old_docs/API_docs_v44/types/DataJSON.md new file mode 100644 index 000000000..b43fab0eb --- /dev/null +++ b/old_docs/API_docs_v44/types/DataJSON.md @@ -0,0 +1,8 @@ +--- +title: DataJSON +description: Any json-encodable data +--- +## Type: DataJSON +[Back to constructor index](index.md) + +Any json-encodable data. \ No newline at end of file diff --git a/old_docs/API_docs_v45/types/DataJSON.md b/old_docs/API_docs_v45/types/DataJSON.md new file mode 100644 index 000000000..b43fab0eb --- /dev/null +++ b/old_docs/API_docs_v45/types/DataJSON.md @@ -0,0 +1,8 @@ +--- +title: DataJSON +description: Any json-encodable data +--- +## Type: DataJSON +[Back to constructor index](index.md) + +Any json-encodable data. \ No newline at end of file diff --git a/old_docs/API_docs_v46/types/DataJSON.md b/old_docs/API_docs_v46/types/DataJSON.md new file mode 100644 index 000000000..b43fab0eb --- /dev/null +++ b/old_docs/API_docs_v46/types/DataJSON.md @@ -0,0 +1,8 @@ +--- +title: DataJSON +description: Any json-encodable data +--- +## Type: DataJSON +[Back to constructor index](index.md) + +Any json-encodable data. \ No newline at end of file diff --git a/old_docs/API_docs_v51/types/DataJSON.md b/old_docs/API_docs_v51/types/DataJSON.md new file mode 100644 index 000000000..b43fab0eb --- /dev/null +++ b/old_docs/API_docs_v51/types/DataJSON.md @@ -0,0 +1,8 @@ +--- +title: DataJSON +description: Any json-encodable data +--- +## Type: DataJSON +[Back to constructor index](index.md) + +Any json-encodable data. \ No newline at end of file diff --git a/old_docs/API_docs_v53/types/DataJSON.md b/old_docs/API_docs_v53/types/DataJSON.md new file mode 100644 index 000000000..b43fab0eb --- /dev/null +++ b/old_docs/API_docs_v53/types/DataJSON.md @@ -0,0 +1,8 @@ +--- +title: DataJSON +description: Any json-encodable data +--- +## Type: DataJSON +[Back to constructor index](index.md) + +Any json-encodable data. \ No newline at end of file diff --git a/old_docs/API_docs_v55/types/DataJSON.md b/old_docs/API_docs_v55/types/DataJSON.md new file mode 100644 index 000000000..b43fab0eb --- /dev/null +++ b/old_docs/API_docs_v55/types/DataJSON.md @@ -0,0 +1,8 @@ +--- +title: DataJSON +description: Any json-encodable data +--- +## Type: DataJSON +[Back to constructor index](index.md) + +Any json-encodable data. \ No newline at end of file diff --git a/old_docs/API_docs_v57/types/DataJSON.md b/old_docs/API_docs_v57/types/DataJSON.md new file mode 100644 index 000000000..b43fab0eb --- /dev/null +++ b/old_docs/API_docs_v57/types/DataJSON.md @@ -0,0 +1,8 @@ +--- +title: DataJSON +description: Any json-encodable data +--- +## Type: DataJSON +[Back to constructor index](index.md) + +Any json-encodable data. \ No newline at end of file diff --git a/old_docs/API_docs_v62/types/DataJSON.md b/old_docs/API_docs_v62/types/DataJSON.md new file mode 100644 index 000000000..b43fab0eb --- /dev/null +++ b/old_docs/API_docs_v62/types/DataJSON.md @@ -0,0 +1,8 @@ +--- +title: DataJSON +description: Any json-encodable data +--- +## Type: DataJSON +[Back to constructor index](index.md) + +Any json-encodable data. \ No newline at end of file diff --git a/src/danog/MadelineProto/API.php b/src/danog/MadelineProto/API.php index ad10cb8d5..5b9ef3a16 100644 --- a/src/danog/MadelineProto/API.php +++ b/src/danog/MadelineProto/API.php @@ -35,6 +35,7 @@ class API extends APIFactory //$this->future_salts = $this->get_future_salts(['num' => 3]); $this->API->v = $this->API->getV(); \danog\MadelineProto\Logger::log(['MadelineProto is ready!'], Logger::NOTICE); + $this->setup_threads(); } /* @@ -45,11 +46,57 @@ class API extends APIFactory return ['API']; } */ + public function setup_threads() + { + if ($this->API->threads = $this->API->run_workers = class_exists('\Pool') && php_sapi_name() == 'cli' && $this->API->settings['threading']['allow_threading']) { + \danog\MadelineProto\Logger::log(['THREADING IS ENABLED'], \danog\MadelineProto\Logger::NOTICE); + $this->start_threads(); + } + } + + public function start_threads() + { + if ($this->API->threads) { + $dcs = $this->API->datacenter->get_dcs(); + if (!isset($this->reader_pool)) { + $this->reader_pool = new \Pool(count($dcs)); + } + if (!isset($this->readers)) { + $this->readers = []; + } + foreach ($dcs as $dc) { + if (!isset($this->readers[$dc])) { + $this->readers[$dc] = new \danog\MadelineProto\Threads\SocketReader($this->API, $dc); + } + if (!$this->readers[$dc]->isRunning()) { + $this->readers[$dc]->garbage = false; + $this->reader_pool->submit($this->readers[$dc]); + Logger::log(['Socket reader on DC '.$dc.': RESTARTED'], Logger::WARNING); + } else { + Logger::log(['Socket reader on DC '.$dc.': WORKING'], Logger::NOTICE); + } + } + } + } + + public function __sleep() + { + $t = get_object_vars($this); + if (isset($t['reader_pool'])) { + unset($t['reader_pool']); + } + if (isset($t['readers'])) { + unset($t['readers']); + } + + return array_keys($t); + } public function __wakeup() { set_error_handler(['\danog\MadelineProto\Exception', 'ExceptionErrorHandler']); - //$this->APIFactory(); + $this->setup_threads(); + if (!isset($this->messages)) $this->APIFactory(); } public function __destruct() diff --git a/src/danog/MadelineProto/Connection.php b/src/danog/MadelineProto/Connection.php index cdc71e7ff..280292b59 100644 --- a/src/danog/MadelineProto/Connection.php +++ b/src/danog/MadelineProto/Connection.php @@ -142,7 +142,7 @@ class Connection throw new Exception("Connection: couldn't connect to socket."); } if (($wrote = fwrite($this->sock, $what)) !== strlen($what)) { - throw new \danog\MadelineProto\Exception("WARNING: Wrong length was read (should've written ".strlen($what).', wrote '.$wrote.')!'); + throw new \danog\MadelineProto\Exception("WARNING: Wrong length was written (should've written ".strlen($what).', wrote '.$wrote.')!'); } return $wrote; diff --git a/src/danog/MadelineProto/DocsBuilder.php b/src/danog/MadelineProto/DocsBuilder.php index 55e93afe1..4b8680d60 100755 --- a/src/danog/MadelineProto/DocsBuilder.php +++ b/src/danog/MadelineProto/DocsBuilder.php @@ -694,6 +694,16 @@ description: Represents a boolean. Represents a boolean.'); + file_put_contents('types/DataJSON.md', '--- +title: DataJSON +description: Any json-encodable data +--- +## Type: DataJSON +[Back to constructor index](index.md) + +Any json-encodable data.'); + + \danog\MadelineProto\Logger::log(['Done!'], \danog\MadelineProto\Logger::NOTICE); } } diff --git a/src/danog/MadelineProto/MTProto.php b/src/danog/MadelineProto/MTProto.php index a1cf63d11..722ea813a 100644 --- a/src/danog/MadelineProto/MTProto.php +++ b/src/danog/MadelineProto/MTProto.php @@ -39,6 +39,7 @@ class MTProto use \danog\MadelineProto\TL\Conversion\Extension; use \danog\MadelineProto\TL\Conversion\TD; use \danog\MadelineProto\Tools; + use \danog\MadelineProto\VoIP\AuthKeyHandler; public $settings = []; public $config = ['expires' => -1]; @@ -102,51 +103,6 @@ class MTProto $this->should_serialize = true; } - public function setup_threads() - { - if ($this->threads = $this->run_workers = class_exists('\Pool') && php_sapi_name() == 'cli' && $this->settings['threading']['allow_threading']) { - \danog\MadelineProto\Logger::log(['THREADING IS ENABLED'], \danog\MadelineProto\Logger::NOTICE); - $this->start_threads(); - } - } - - public function start_threads() - { - if ($this->threads) { - $dcs = $this->datacenter->get_dcs(); - if (!isset($this->reader_pool)) { - $this->reader_pool = new \Pool(count($dcs)); - } - if (!isset($this->readers)) { - $this->readers = []; - } - foreach ($dcs as $dc) { - if (!isset($this->readers[$dc])) { - $this->readers[$dc] = new \danog\MadelineProto\Threads\SocketReader($this, $dc); - } - if (!$this->readers[$dc]->isRunning()) { - $this->readers[$dc]->garbage = false; - $this->reader_pool->submit($this->readers[$dc]); - Logger::log(['Socket reader on DC '.$dc.': RESTARTED'], Logger::WARNING); - } else { - Logger::log(['Socket reader on DC '.$dc.': WORKING'], Logger::NOTICE); - } - } - } - } - - public function __sleep() - { - $t = get_object_vars($this); - if (isset($t['reader_pool'])) { - unset($t['reader_pool']); - } - if (isset($t['readers'])) { - unset($t['readers']); - } - - return array_keys($t); - } public function __wakeup() { @@ -160,7 +116,6 @@ class MTProto \danog\MadelineProto\Logger::log(['Serialization is out of date, reconstructing object!'], Logger::WARNING); $this->__construct($this->settings); } - $this->setup_threads(); $this->datacenter->__construct($this->settings['connection'], $this->settings['connection_settings']); if ($this->authorized && $this->settings['updates']['handle_updates']) { \danog\MadelineProto\Logger::log(['Getting updates after deserialization...'], Logger::NOTICE); @@ -329,7 +284,7 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB 'accept_calls' => true, // Should I accept calls? Can be true, false or on array of user ids from which to accept calls ], 'threading' => [ - 'allow_threading' => false, // Should I use threading, if it is enabled? + 'allow_threading' => true, // Should I use threading, if it is enabled? 'handler_workers' => 10, // How many workers should every message handler pool of each socket reader have ], 'pwr' => ['pwr' => false, 'db_token' => false, 'strict' => false], @@ -389,7 +344,6 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB $this->datacenter->dc_connect($new_dc); } } - $this->setup_threads(); $this->init_authorization(); if ($old !== $this->datacenter->get_dcs()) { $this->connect_to_all_dcs(); diff --git a/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php b/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php index dff10fcf0..1349358fb 100644 --- a/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php @@ -508,85 +508,6 @@ trait AuthKeyHandler return $this->dh_config = $dh_config; } - private $temp_requested_calls = []; - private $calls = []; - - public function accept_call($params) - { - $dh_config = $this->get_dh_config(); - \danog\MadelineProto\Logger::log(['Generating b...'], \danog\MadelineProto\Logger::VERBOSE); - $b = new \phpseclib\Math\BigInteger($this->random(256), 256); - $params['g_a'] = new \phpseclib\Math\BigInteger($params['g_a'], 256); - $this->check_G($params['g_a'], $dh_config['p']); - $key = ['auth_key' => str_pad($params['g_a']->powMod($b, $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT)]; - $key['fingerprint'] = substr(sha1($key['auth_key'], true), -8); - $key['visualization_orig'] = substr(sha1($key['auth_key'], true), 16); - $key['visualization_46'] = substr(hash('sha256', $key['auth_key'], true), 20); - $this->secret_chats[$params['id']] = ['key' => $key, 'admin' => false, 'user_id' => $params['admin_id'], 'InputPhoneCall' => ['id' => $params['id'], 'access_hash' => $params['access_hash'], '_' => 'inputPhoneCall'], 'in_seq_no_x' => 0, 'out_seq_no_x' => 1, 'layer' => 65, 'ttr' => 100, 'updated' => time(), 'incoming' => [], 'outgoing' => [], 'created' => time(), 'rekeying' => [0], 'protocol' => $params['protocol'], 'connection' => $params['connection'], 'alternative_connections' => $params['alternative_connections']]; - //$this->secret_chats[$params['id']] = ['key' => $key, 'admin' => false, 'user_id' => $params['admin_id'], 'InputEncryptedChat' => ['_' => 'inputEncryptedChat', 'chat_id' => $params['id'], 'access_hash' => $params['access_hash']], 'in_seq_no_x' => 1, 'out_seq_no_x' => 0, 'layer' => 8, 'ttl' => PHP_INT_MAX, 'ttr' => 100, 'updated' => time(), 'incoming' => [], 'outgoing' => [], 'created' => time(), 'rekeying' => [0]]; - $g_b = $dh_config['g']->powMod($b, $dh_config['p']); - $this->check_G($g_b, $dh_config['p']); - $this->handle_pending_updates(); - } - - public function request_call($user) - { - $user = $this->get_info($user)['InputUser']; - \danog\MadelineProto\Logger::log(['Calling '.$user['user_id'].'...'], \danog\MadelineProto\Logger::VERBOSE); - $dh_config = $this->get_dh_config(); - \danog\MadelineProto\Logger::log(['Generating a...'], \danog\MadelineProto\Logger::VERBOSE); - $a = new \phpseclib\Math\BigInteger($this->random(256), 256); - \danog\MadelineProto\Logger::log(['Generating g_a...'], \danog\MadelineProto\Logger::VERBOSE); - $g_a = $dh_config['g']->powMod($a, $dh_config['p']); - $this->check_G($g_a, $dh_config['p']); -// $res = $this->method_call('phone.requestCall', ['user_id' => $user, 'g_a' => $g_a->toBytes(), 'protocol' => ['_' => 'phoneCallProtocol', 'min_layer' => $this->settings['tl_schema']['layer'], 'max_layer' => $this->settings['tl_schema']['layer']]], ['datacenter' => $this->datacenter->curdc]); - $res = $this->method_call('phone.requestCall', ['user_id' => $user, 'g_a' => $g_a->toBytes(), 'protocol' => ['_' => 'phoneCallProtocol', 'min_layer' => 65, 'max_layer' => 65, 'udp_reflector' => true]], ['datacenter' => $this->datacenter->curdc]); - $this->temp_requested_calls[$res['phone_call']['id']] = $a; - $this->handle_pending_updates(); - $this->get_updates_difference(); - - return $res['phone_call']['id']; - } - - public function complete_call($params) - { - if ($this->call_status($params['id']) !== 1) { - \danog\MadelineProto\Logger::log(['Could not find and complete secret chat '.$params['id']]); - - return false; - } - $dh_config = $this->get_dh_config(); - $params['g_a_or_b'] = new \phpseclib\Math\BigInteger($params['g_a_or_b'], 256); - $this->check_G($params['g_a_or_b'], $dh_config['p']); - $key = ['auth_key' => str_pad($params['g_a_or_b']->powMod($this->temp_requested_secret_chats[$params['id']], $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT)]; - unset($this->temp_requested_calls[$params['id']]); - $key['fingerprint'] = substr(sha1($key['auth_key'], true), -8); - if ($key['fingerprint'] !== $params['key_fingerprint']) { - throw new \danog\MadelineProto\SecurityException('Invalid key fingerprint!'); - } - $key['visualization_orig'] = substr(sha1($key['auth_key'], true), 16); - $key['visualization_46'] = substr(hash('sha256', $key['auth_key'], true), 20); - $this->secret_chats[$params['id']] = ['key' => $key, 'admin' => true, 'user_id' => $params['participant_id'], 'InputPhoneCall' => ['id' => $params['id'], 'access_hash' => $params['access_hash'], '_' => 'inputPhoneCall'], 'in_seq_no_x' => 0, 'out_seq_no_x' => 1, 'layer' => 65, 'ttr' => 100, 'updated' => time(), 'incoming' => [], 'outgoing' => [], 'created' => time(), 'rekeying' => [0], 'protocol' => $params['protocol'], 'connection' => $params['connection'], 'alternative_connections' => $params['alternative_connections']]; - $this->handle_pending_updates(); - } - - public function call_status($id) - { - if (isset($this->calls[$id])) { - return 2; - } - if (isset($this->temp_requested_calls[$id])) { - return 1; - } - - return 0; - } - - public function get_secret_chat($chat) - { - return $this->secret_chats[$chat]; - } - public function bind_temp_auth_key($expires_in, $datacenter) { for ($retry_id_total = 1; $retry_id_total <= $this->settings['max_tries']['authorization']; $retry_id_total++) { diff --git a/src/danog/MadelineProto/MTProtoTools/CallHandler.php b/src/danog/MadelineProto/MTProtoTools/CallHandler.php index 41cd23c97..9e5eb602b 100644 --- a/src/danog/MadelineProto/MTProtoTools/CallHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/CallHandler.php @@ -52,7 +52,7 @@ trait CallHandler while ($server_answer === null && $res_count++ < $this->settings['max_tries']['response'] + 1) { // Loop until we get a response, loop for a max of $this->settings['max_tries']['response'] times try { \danog\MadelineProto\Logger::log(['Getting response (try number '.$res_count.' for '.$method.')...'], \danog\MadelineProto\Logger::ULTRA_VERBOSE); - $this->start_threads(); + //$this->start_threads(); if (!isset($this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages[$int_message_id]['response']) || !isset($this->datacenter->sockets[$aargs['datacenter']]->incoming_messages[$this->datacenter->sockets[$aargs['datacenter']]->outgoing_messages[$int_message_id]['response']]['content'])) { // Checks if I have received the response to the called method, if not continue looping if ($only_updates) { if ($update_count > 50) { @@ -86,7 +86,7 @@ trait CallHandler throw new \danog\MadelineProto\Exception("Couldn't get response"); } if (!isset($server_answer['_'])) { - \danog\MadelineProto\Logger::log(['Response does not have a type!', $server_answer], \danog\MadelineProto\Logger::FATAL_ERROR); + return $server_answer; } switch ($server_answer['_']) { case 'rpc_error': diff --git a/src/danog/MadelineProto/TL/TL.php b/src/danog/MadelineProto/TL/TL.php index 863f4cf66..8d11441e5 100644 --- a/src/danog/MadelineProto/TL/TL.php +++ b/src/danog/MadelineProto/TL/TL.php @@ -340,6 +340,9 @@ trait TL if ($constructorData['predicate'] === 'messageEntityMentionName') { $constructorData = $this->constructors->find_by_predicate('inputMessageEntityMentionName'); } + if ($constructorData['predicate'] === 'dataJSON') { + $object['data'] = json_encode($object['data']); + } if (!$bare) { $concat .= \danog\PHP\Struct::pack('pos); + //\danog\MadelineProto\Logger::log(['Deserializing '.$type['type'].' at byte '.$bytes_io->pos]); switch ($type['type']) { case 'Bool': return $this->deserialize_bool($bytes_io->read(4)); @@ -570,7 +573,9 @@ trait TL if (isset($x['flags'])) { // I don't think we need this anymore unset($x['flags']); } - + if ($x['_'] === 'dataJSON') { + return json_decode($x['data'], true); + } return $x; } } diff --git a/src/danog/MadelineProto/Threads/SocketReader.php b/src/danog/MadelineProto/Threads/SocketReader.php index 7cec02322..6525da412 100644 --- a/src/danog/MadelineProto/Threads/SocketReader.php +++ b/src/danog/MadelineProto/Threads/SocketReader.php @@ -51,7 +51,7 @@ class SocketReader extends \Threaded implements \Collectable try { $this->API->recv_message($this->current); $handler_pool->submit(new SocketHandler($this->API, $this->current)); - } catch (\danog\MadelineProto\Exception $e) { + } catch (\danog\MadelineProto\NothingInTheSocketException $e) { } } while ($handler_pool->collect()); diff --git a/src/danog/MadelineProto/VoIP/AuthKeyHandler.php b/src/danog/MadelineProto/VoIP/AuthKeyHandler.php new file mode 100644 index 000000000..7c5226849 --- /dev/null +++ b/src/danog/MadelineProto/VoIP/AuthKeyHandler.php @@ -0,0 +1,102 @@ +. +*/ + +namespace danog\MadelineProto\VoIP; + +/** + * Manages the creation of the authorization key. + * + * https://core.telegram.org/mtproto/auth_key + * https://core.telegram.org/mtproto/samples-auth_key + */ +trait AuthKeyHandler +{ + private $temp_requested_calls = []; + private $calls = []; + + public function accept_call($params) + { + $dh_config = $this->get_dh_config(); + $phone_config = $this->method_call('phone.getCallConfig'); + $b = new \phpseclib\Math\BigInteger($this->random(256), 256); + $params['g_a'] = new \phpseclib\Math\BigInteger($params['g_a'], 256); + $this->check_G($params['g_a'], $dh_config['p']); + $key = ['auth_key' => str_pad($params['g_a']->powMod($b, $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT)]; + $key['fingerprint'] = substr(sha1($key['auth_key'], true), -8); + $key['visualization_orig'] = substr(sha1($key['auth_key'], true), 16); + $key['visualization_46'] = substr(hash('sha256', $key['auth_key'], true), 20); + $this->calls[$params['id']] = ['key' => $key, 'admin' => false, 'user_id' => $params['admin_id'], 'InputPhoneCall' => ['id' => $params['id'], 'access_hash' => $params['access_hash'], '_' => 'inputPhoneCall'], 'in_seq_no_x' => 0, 'out_seq_no_x' => 1, 'layer' => 65, 'ttr' => 100, 'updated' => time(), 'incoming' => [], 'outgoing' => [], 'created' => time(), 'rekeying' => [0], 'protocol' => $params['protocol'], 'connection' => $params['connection'], 'alternative_connections' => $params['alternative_connections']]; + //$this->calls[$params['id']] = ['key' => $key, 'admin' => false, 'user_id' => $params['admin_id'], 'InputEncryptedChat' => ['_' => 'inputEncryptedChat', 'chat_id' => $params['id'], 'access_hash' => $params['access_hash']], 'in_seq_no_x' => 1, 'out_seq_no_x' => 0, 'layer' => 8, 'ttl' => PHP_INT_MAX, 'ttr' => 100, 'updated' => time(), 'incoming' => [], 'outgoing' => [], 'created' => time(), 'rekeying' => [0]]; + $g_b = $dh_config['g']->powMod($b, $dh_config['p']); + $this->check_G($g_b, $dh_config['p']); + $this->handle_pending_updates(); + } + + public function request_call($user) + { + $user = $this->get_info($user)['InputUser']; + \danog\MadelineProto\Logger::log(['Calling '.$user['user_id'].'...'], \danog\MadelineProto\Logger::VERBOSE); + $dh_config = $this->get_dh_config(); + $phone_config = $this->method_call('phone.getCallConfig', [], ['datacenter' => $this->datacenter->curdc]); + \danog\MadelineProto\Logger::log(['Generating a...'], \danog\MadelineProto\Logger::VERBOSE); + $a = new \phpseclib\Math\BigInteger($this->random(256), 256); + \danog\MadelineProto\Logger::log(['Generating g_a...'], \danog\MadelineProto\Logger::VERBOSE); + $g_a = $dh_config['g']->powMod($a, $dh_config['p']); + $this->check_G($g_a, $dh_config['p']); + $res = $this->method_call('phone.requestCall', ['user_id' => $user, 'g_a_hash' => hash('sha256', $g_a->toBytes(), true), 'protocol' => ['_' => 'phoneCallProtocol', 'udp_reflector' => true, 'min_layer' => $this->settings['tl_schema']['layer'], 'max_layer' => $this->settings['tl_schema']['layer']]], ['datacenter' => $this->datacenter->curdc]); + $this->temp_requested_calls[$res['phone_call']['id']] = $a; + $this->handle_pending_updates(); + $this->get_updates_difference(); + + return $res['phone_call']['id']; + } + + public function complete_call($params) + { + if ($this->call_status($params['id']) !== 1) { + \danog\MadelineProto\Logger::log(['Could not find and complete secret chat '.$params['id']]); + + return false; + } + $dh_config = $this->get_dh_config(); + $params['g_a_or_b'] = new \phpseclib\Math\BigInteger($params['g_a_or_b'], 256); + $this->check_G($params['g_a_or_b'], $dh_config['p']); + $key = ['auth_key' => str_pad($params['g_a_or_b']->powMod($this->temp_requested_calls[$params['id']], $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT)]; + unset($this->temp_requested_calls[$params['id']]); + $key['fingerprint'] = substr(sha1($key['auth_key'], true), -8); + if ($key['fingerprint'] !== $params['key_fingerprint']) { + throw new \danog\MadelineProto\SecurityException('Invalid key fingerprint!'); + } + $key['visualization_orig'] = substr(sha1($key['auth_key'], true), 16); + $key['visualization_46'] = substr(hash('sha256', $key['auth_key'], true), 20); + $this->calls[$params['id']] = ['key' => $key, 'admin' => true, 'user_id' => $params['participant_id'], 'InputPhoneCall' => ['id' => $params['id'], 'access_hash' => $params['access_hash'], '_' => 'inputPhoneCall'], 'in_seq_no_x' => 0, 'out_seq_no_x' => 1, 'layer' => 65, 'ttr' => 100, 'updated' => time(), 'incoming' => [], 'outgoing' => [], 'created' => time(), 'rekeying' => [0], 'protocol' => $params['protocol'], 'connection' => $params['connection'], 'alternative_connections' => $params['alternative_connections']]; + $this->handle_pending_updates(); + } + + public function call_status($id) + { + if (isset($this->calls[$id])) { + return 2; + } + if (isset($this->temp_requested_calls[$id])) { + return 1; + } + + return 0; + } + + public function get_secret_chat($chat) + { + return $this->calls[$chat]; + } + +} diff --git a/tests/testing.php b/tests/testing.php index d8e223b35..f4c25d3e0 100755 --- a/tests/testing.php +++ b/tests/testing.php @@ -66,7 +66,7 @@ if ($MadelineProto === false) { } $message = (getenv('TRAVIS_COMMIT') == '') ? 'I iz works always (io laborare sembre) (yo lavorar siempre) (mi labori ĉiam) (я всегда работать) (Ik werkuh altijd)' : ('Travis ci tests in progress: commit '.getenv('TRAVIS_COMMIT').', job '.getenv('TRAVIS_JOB_NUMBER').', PHP version: '.getenv('TRAVIS_PHP_VERSION')); -//$MadelineProto->API->request_secret_chat('@Harold_Saxon'); +//$MadelineProto->API->request_call('@danogentili'); echo 'Serializing MadelineProto to session.madeline...'.PHP_EOL; echo 'Wrote '.\danog\MadelineProto\Serialization::serialize('session.madeline', $MadelineProto).' bytes'.PHP_EOL; echo 'Size of MadelineProto instance is '.strlen(serialize($MadelineProto)).' bytes'.PHP_EOL;