From ebceeda29bdbd90a789915d04ddef26159a623c9 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Mon, 19 Feb 2018 11:48:43 +0000 Subject: [PATCH] Stability fixes --- bot.php | 10 ++-- secret_bot.php | 15 ++--- src/Socket.php | 7 ++- src/danog/MadelineProto/Connection.php | 23 ++++--- src/danog/MadelineProto/DataCenter.php | 60 ++++++++----------- src/danog/MadelineProto/MTProto.php | 2 +- .../MTProtoTools/AuthKeyHandler.php | 15 +++-- .../MadelineProto/MTProtoTools/Files.php | 24 ++++---- .../MTProtoTools/ResponseHandler.php | 2 +- .../MadelineProto/TL/Conversion/BotAPI.php | 27 ++++----- tests/testing.php | 20 +++---- 11 files changed, 90 insertions(+), 115 deletions(-) diff --git a/bot.php b/bot.php index da36f28c..e684be8a 100755 --- a/bot.php +++ b/bot.php @@ -13,7 +13,7 @@ If not, see . set_include_path(get_include_path().':'.realpath(dirname(__FILE__).'/MadelineProto/')); require 'vendor/autoload.php'; -$settings = ['app_info' => ['api_id' => 6, 'api_hash' => 'eb06d4abfb49dc3eeb1aeb98ae0f581e']]; //, 'connection_settings' => ['all' => ['test_mode' => true]]]; +$settings = ['app_info' => ['api_id' => 6, 'api_hash' => 'eb06d4abfb49dc3eeb1aeb98ae0f581e']];//, 'connection_settings' => ['all' => ['test_mode' => true]]]; try { $MadelineProto = new \danog\MadelineProto\API('bot.madeline'); @@ -37,7 +37,7 @@ while (true) { case 'updateNewMessage': case 'updateNewChannelMessage': if (isset($update['update']['message']['out']) && $update['update']['message']['out']) { - continue; +// continue; } $res = json_encode($update, JSON_PRETTY_PRINT); if ($res == '') { @@ -45,16 +45,16 @@ while (true) { } try { - $MadelineProto->messages->sendMessage(['peer' => $update['update']['_'] === 'updateNewMessage' ? $update['update']['message']['from_id'] : $update['update']['message']['to_id'], 'message' => $res, 'reply_to_msg_id' => $update['update']['message']['id'], 'entities' => [['_' => 'messageEntityPre', 'offset' => 0, 'length' => strlen($res), 'language' => 'json']]]); +// $MadelineProto->messages->sendMessage(['peer' => $update['update']['_'] === 'updateNewMessage' ? $update['update']['message']['from_id'] : $update['update']['message']['to_id'], 'message' => $res, 'reply_to_msg_id' => $update['update']['message']['id'], 'entities' => [['_' => 'messageEntityPre', 'offset' => 0, 'length' => strlen($res), 'language' => 'json']]]); } catch (\danog\MadelineProto\RPCErrorException $e) { $MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => $e->getCode().': '.$e->getMessage().PHP_EOL.$e->getTraceAsString()]); } try { if (isset($update['update']['message']['media']) && ($update['update']['message']['media']['_'] == 'messageMediaPhoto' || $update['update']['message']['media']['_'] == 'messageMediaDocument')) { - $time = time(); + $time = microtime(true); $file = $MadelineProto->download_to_dir($update['update']['message']['media'], '/tmp'); - $MadelineProto->messages->sendMessage(['peer' => isset($update['update']['message']['from_id']) ? $update['update']['message']['from_id'] : $update['update']['message']['to_id'], 'message' => 'Downloaded to '.$file.' in '.(time() - $time).' seconds', 'reply_to_msg_id' => $update['update']['message']['id'], 'entities' => [['_' => 'messageEntityPre', 'offset' => 0, 'length' => strlen($res), 'language' => 'json']]]); + $MadelineProto->messages->sendMessage(['peer' => isset($update['update']['message']['from_id']) ? $update['update']['message']['from_id'] : $update['update']['message']['to_id'], 'message' => 'Downloaded to '.$file.' in '.(microtime(true) - $time).' seconds', 'reply_to_msg_id' => $update['update']['message']['id'], 'entities' => [['_' => 'messageEntityPre', 'offset' => 0, 'length' => strlen($res), 'language' => 'json']]]); } } catch (\danog\MadelineProto\RPCErrorException $e) { $MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => $e->getCode().': '.$e->getMessage().PHP_EOL.$e->getTraceAsString()]); diff --git a/secret_bot.php b/secret_bot.php index 817b15a3..f86574cf 100755 --- a/secret_bot.php +++ b/secret_bot.php @@ -54,27 +54,22 @@ if ($MadelineProto === false) { \danog\MadelineProto\Logger::log(['Registering new user'], \danog\MadelineProto\Logger::NOTICE); $authorization = $MadelineProto->complete_signup(readline('Please enter your first name: '), readline('Please enter your last name (can be empty): ')); } - - echo 'Serializing MadelineProto to s.madeline...'.PHP_EOL; - echo 'Wrote '.\danog\MadelineProto\Serialization::serialize('s.madeline', $MadelineProto).' bytes'.PHP_EOL; } else { $MadelineProto->bot_login(getenv('BOT_TOKEN')); } } $message = (getenv('TRAVIS_COMMIT') == '') ? 'I iz works always (io laborare sembre) (yo lavorar siempre) (mi labori ĉiam) (я всегда работать) (Ik werkuh altijd) (Ngimbonga ngaso sonke isikhathi ukusebenza)' : ('Travis ci tests in progress: commit '.getenv('TRAVIS_COMMIT').', job '.getenv('TRAVIS_JOB_NUMBER').', PHP version: '.getenv('TRAVIS_PHP_VERSION')); -echo 'Serializing MadelineProto to s.madeline...'.PHP_EOL; -echo 'Wrote '.\danog\MadelineProto\Serialization::serialize('s.madeline', $MadelineProto).' bytes'.PHP_EOL; +$MadelineProto->session = 's.madeline'; $sent = [-440592694 => true]; $offset = 0; while (true) { try { - $updates = $MadelineProto->API->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout + $updates = $MadelineProto->get_updates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout //\danog\MadelineProto\Logger::log([$updates]); foreach ($updates as $update) { - echo 'Wrote '.\danog\MadelineProto\Serialization::serialize('s.madeline', $MadelineProto).' bytes'.PHP_EOL; $offset = $update['update_id'] + 1; // Just like in the bot API, the offset must be set to the last update_id switch ($update['update']['_']) { /*case 'updateNewChannelMessage': @@ -87,11 +82,11 @@ while (true) { } break;*/ case 'updateNewEncryptedMessage': - //var_dump($MadelineProto->download_to_dir($update['update']['message'], '.')); + var_dump($MadelineProto->download_to_dir($update['update']['message'], '.')); if (isset($sent[$update['update']['message']['chat_id']])) { continue; } -$secret = $update['update']['message']['chat_id']; + $secret = $update['update']['message']['chat_id']; $secret_media = []; // Photo uploaded as document, secret chat @@ -133,7 +128,6 @@ $secret = $update['update']['message']['chat_id']; while ($i < $argv[1]) { echo "SENDING MESSAGE $i TO ".$update['update']['message']['chat_id'].PHP_EOL; $MadelineProto->messages->sendEncrypted(['peer' => $update['update']['message']['chat_id'], 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => (string) ($i++)]]); - \danog\MadelineProto\Serialization::serialize('s.madeline', $MadelineProto); } $sent[$update['update']['message']['chat_id']] = true; } @@ -144,5 +138,4 @@ $secret = $update['update']['message']['chat_id']; var_dump($e->getMessage()); } //sleep(1); - echo 'Wrote '.\danog\MadelineProto\Serialization::serialize('s.madeline', $MadelineProto).' bytes'.PHP_EOL; } diff --git a/src/Socket.php b/src/Socket.php index bdbe0fcc..dee834d1 100644 --- a/src/Socket.php +++ b/src/Socket.php @@ -45,7 +45,6 @@ if (!extension_loaded('pthreads')) { { if (in_array($name, [\SO_RCVTIMEO, \SO_SNDTIMEO])) { $this->timeout = ['sec' => (int) $value, 'usec' => (int) (($value - (int) $value) * 1000000)]; - stream_set_timeout($this->sock, $this->timeout['sec'], $this->timeout['usec']); return true; } @@ -83,8 +82,10 @@ if (!extension_loaded('pthreads')) { if ($this->domain === AF_INET6 && strpos($address, ':') !== false) { $address = '['.$address.']'; } - - $this->sock = fsockopen($this->protocol.'://'.$address, $port); + $errno = 0; + $errstr = ''; + $this->sock = fsockopen($this->protocol.'://'.$address, $port, $errno, $errstr, $this->timeout['sec'] + ($this->timeout['usec']/1000000)); + stream_set_timeout($this->sock, $this->timeout['sec'], $this->timeout['usec']); return true; } diff --git a/src/danog/MadelineProto/Connection.php b/src/danog/MadelineProto/Connection.php index 8236bfd9..e91f3e92 100644 --- a/src/danog/MadelineProto/Connection.php +++ b/src/danog/MadelineProto/Connection.php @@ -51,7 +51,6 @@ class Connection public function __magic_construct($proxy, $extra, $ip, $port, $protocol, $timeout, $ipv6) { - // Can use: /* - tcp_full @@ -77,11 +76,11 @@ class Connection if ($has_proxy && $this->extra !== []) { $this->sock->setExtra($this->extra); } + $this->sock->setOption(\SOL_SOCKET, \SO_RCVTIMEO, $timeout); + $this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout); if (!$this->sock->connect($ip, $port)) { throw new Exception(\danog\MadelineProto\Lang::$current_lang['socket_con_error']); } - $this->sock->setOption(\SOL_SOCKET, \SO_RCVTIMEO, $timeout); - $this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout); $this->sock->setBlocking(true); $this->write(chr(239)); break; @@ -90,11 +89,11 @@ class Connection if ($has_proxy && $this->extra !== []) { $this->sock->setExtra($this->extra); } + $this->sock->setOption(\SOL_SOCKET, \SO_RCVTIMEO, $timeout); + $this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout); if (!$this->sock->connect($ip, $port)) { throw new Exception(\danog\MadelineProto\Lang::$current_lang['socket_con_error']); } - $this->sock->setOption(\SOL_SOCKET, \SO_RCVTIMEO, $timeout); - $this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout); $this->sock->setBlocking(true); $this->write(str_repeat(chr(238), 4)); break; @@ -104,11 +103,11 @@ class Connection if ($has_proxy && $this->extra !== []) { $this->sock->setExtra($this->extra); } + $this->sock->setOption(\SOL_SOCKET, \SO_RCVTIMEO, $timeout); + $this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout); if (!$this->sock->connect($ip, $port)) { throw new Exception(\danog\MadelineProto\Lang::$current_lang['socket_con_error']); } - $this->sock->setOption(\SOL_SOCKET, \SO_RCVTIMEO, $timeout); - $this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout); $this->sock->setBlocking(true); $this->out_seq_no = -1; @@ -119,11 +118,11 @@ class Connection if ($has_proxy && $this->extra !== []) { $this->sock->setExtra($this->extra); } + $this->sock->setOption(\SOL_SOCKET, \SO_RCVTIMEO, $timeout); + $this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout); if (!$this->sock->connect($ip, $port)) { throw new Exception(\danog\MadelineProto\Lang::$current_lang['socket_con_error']); } - $this->sock->setOption(\SOL_SOCKET, \SO_RCVTIMEO, $timeout); - $this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout); $this->sock->setBlocking(true); do { $random = $this->random(64); @@ -166,13 +165,11 @@ class Connection if ($has_proxy && $this->extra !== []) { $this->sock->setExtra($this->extra); } + $this->sock->setOption(\SOL_SOCKET, \SO_RCVTIMEO, $timeout); + $this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout); if (!$this->sock->connect($this->parsed['host'], $port)) { throw new Exception(\danog\MadelineProto\Lang::$current_lang['socket_con_error']); } - if (!\danog\MadelineProto\Logger::$has_thread) { - $this->sock->setOption(\SOL_SOCKET, \SO_RCVTIMEO, $timeout); - $this->sock->setOption(\SOL_SOCKET, \SO_SNDTIMEO, $timeout); - } $this->sock->setBlocking(true); break; case 'udp': diff --git a/src/danog/MadelineProto/DataCenter.php b/src/danog/MadelineProto/DataCenter.php index 1ac37f7c..23049731 100644 --- a/src/danog/MadelineProto/DataCenter.php +++ b/src/danog/MadelineProto/DataCenter.php @@ -63,8 +63,13 @@ class DataCenter } $dc_config_number = isset($this->settings[$dc_number]) ? $dc_number : 'all'; $test = $this->settings[$dc_config_number]['test_mode'] ? 'test' : 'main'; + $x = 0; + + do { + $ipv6 = $this->settings[$dc_config_number]['ipv6'] ? 'ipv6' : 'ipv4'; + if (!isset($this->dclist[$test][$ipv6][$dc_number]['ip_address'])) { unset($this->sockets[$dc_number]); @@ -96,50 +101,33 @@ class DataCenter $address = $this->settings[$dc_config_number]['protocol'].'://'.$address.'/api'; } \danog\MadelineProto\Logger::log([sprintf(\danog\MadelineProto\Lang::$current_lang['dc_con_test_start'], $dc_number, $test, $ipv6, $this->settings[$dc_config_number]['protocol'])], \danog\MadelineProto\Logger::VERBOSE); - - $x = 0; - do { - try { - if (isset($this->sockets[$dc_number]->old)) { - $this->sockets[$dc_number]->__construct($this->settings[$dc_config_number]['proxy'], $this->settings[$dc_config_number]['proxy_extra'], $address, $port, $this->settings[$dc_config_number]['protocol'], $this->settings[$dc_config_number]['timeout'], $this->settings[$dc_config_number]['ipv6']); - unset($this->sockets[$dc_number]->old); - } else { - $this->sockets[$dc_number] = new Connection($this->settings[$dc_config_number]['proxy'], $this->settings[$dc_config_number]['proxy_extra'], $address, $port, $this->settings[$dc_config_number]['protocol'], $this->settings[$dc_config_number]['timeout'], $this->settings[$dc_config_number]['ipv6']); + foreach (array_unique([$port, 443, 80, 88]) as $port) { + \danog\MadelineProto\Logger::log(['Trying connection on port '.$port.'...'], \danog\MadelineProto\Logger::WARNING); + try { + if (isset($this->sockets[$dc_number]->old)) { + $this->sockets[$dc_number]->__construct($this->settings[$dc_config_number]['proxy'], $this->settings[$dc_config_number]['proxy_extra'], $address, $port, $this->settings[$dc_config_number]['protocol'], $this->settings[$dc_config_number]['timeout'], $this->settings[$dc_config_number]['ipv6']); + unset($this->sockets[$dc_number]->old); + } else { + $this->sockets[$dc_number] = new Connection($this->settings[$dc_config_number]['proxy'], $this->settings[$dc_config_number]['proxy_extra'], $address, $port, $this->settings[$dc_config_number]['protocol'], $this->settings[$dc_config_number]['timeout'], $this->settings[$dc_config_number]['ipv6']); + } + \danog\MadelineProto\Logger::log(['OK!'], \danog\MadelineProto\Logger::WARNING); + return true; + } catch (\danog\MadelineProto\Exception $e) { + } catch (\danog\MadelineProto\NothingInTheSocketException $e) { } - \danog\MadelineProto\Logger::log(['OK!'], \danog\MadelineProto\Logger::WARNING); - - return true; - } catch (\danog\MadelineProto\Exception $e) { - } catch (\danog\MadelineProto\NothingInTheSocketException $e) { } - switch ($x) { case 0: - \danog\MadelineProto\Logger::log(['Connection failed, retrying connection on port 443...'], \danog\MadelineProto\Logger::WARNING); - $port = 443; + $this->settings[$dc_config_number]['ipv6'] = !$this->settings[$dc_config_number]['ipv6']; + \danog\MadelineProto\Logger::log(['Connection failed, retrying connection with '.($this->settings[$dc_config_number]['ipv6'] ? 'ipv6' : 'ipv4').'...'], \danog\MadelineProto\Logger::WARNING); continue; case 1: - \danog\MadelineProto\Logger::log(['Connection failed, retrying connection on port 80...'], \danog\MadelineProto\Logger::WARNING); - $port = 80; + $this->settings[$dc_config_number]['proxy'] = '\Socket'; + \danog\MadelineProto\Logger::log(['Connection failed, retrying connection without the proxy with '.($this->settings[$dc_config_number]['ipv6'] ? 'ipv6' : 'ipv4').'...'], \danog\MadelineProto\Logger::WARNING); continue; case 2: - \danog\MadelineProto\Logger::log(['Connection failed, retrying connection on port 88...'], \danog\MadelineProto\Logger::WARNING); - $port = 88; - continue; - case 3: - \danog\MadelineProto\Logger::log(['Connection failed, retrying connection on port 443 without the proxy...'], \danog\MadelineProto\Logger::WARNING); - $port = 443; - $this->settings[$dc_config_number]['proxy'] = '\Socket'; - continue; - case 4: - \danog\MadelineProto\Logger::log(['Connection failed, retrying connection on port 80 without the proxy...'], \danog\MadelineProto\Logger::WARNING); - $port = 80; - $this->settings[$dc_config_number]['proxy'] = '\Socket'; - continue; - case 5: - \danog\MadelineProto\Logger::log(['Connection failed, retrying connection on port 88 without the proxy...'], \danog\MadelineProto\Logger::WARNING); - $port = 88; - $this->settings[$dc_config_number]['proxy'] = '\Socket'; + $this->settings[$dc_config_number]['ipv6'] = !$this->settings[$dc_config_number]['ipv6']; + \danog\MadelineProto\Logger::log(['Connection failed, retrying connection without the proxy with '.($this->settings[$dc_config_number]['ipv6'] ? 'ipv6' : 'ipv4').'...'], \danog\MadelineProto\Logger::WARNING); continue; default: return false; diff --git a/src/danog/MadelineProto/MTProto.php b/src/danog/MadelineProto/MTProto.php index 93dd9f65..9ce79f1f 100644 --- a/src/danog/MadelineProto/MTProto.php +++ b/src/danog/MadelineProto/MTProto.php @@ -46,7 +46,7 @@ class MTProto /* const V = 71; */ - const V = 89; + const V = 90; const NOT_LOGGED_IN = 0; const WAITING_CODE = 1; diff --git a/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php b/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php index 6f52ac73..d9ba6a92 100644 --- a/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php @@ -22,6 +22,7 @@ trait AuthKeyHandler { public function create_auth_key($expires_in, $datacenter) { + $req_pq = strpos($datacenter, 'cdn') ? 'req_pq' : 'req_pq_multi'; for ($retry_id_total = 1; $retry_id_total <= $this->settings['max_tries']['authorization']; $retry_id_total++) { try { \danog\MadelineProto\Logger::log([\danog\MadelineProto\Lang::$current_lang['req_pq']], \danog\MadelineProto\Logger::VERBOSE); @@ -44,7 +45,7 @@ trait AuthKeyHandler * ] */ $nonce = $this->random(16); - $ResPQ = $this->method_call('req_pq_multi', + $ResPQ = $this->method_call($req_pq, [ 'nonce' => $nonce, ], @@ -370,6 +371,7 @@ trait AuthKeyHandler $res_authorization['server_salt'] = substr($new_nonce, 0, 8 - 0) ^ substr($server_nonce, 0, 8 - 0); $res_authorization['auth_key'] = $auth_key_str; $res_authorization['id'] = substr($auth_key_sha, -8); + $res_authorization['connection_inited'] = false; \danog\MadelineProto\Logger::log(['Auth key generated'], \danog\MadelineProto\Logger::NOTICE); @@ -398,6 +400,7 @@ trait AuthKeyHandler \danog\MadelineProto\Logger::log(['An exception occurred while generating the authorization key: '.$e->getMessage().' in '.basename($e->getFile(), '.php').' on line '.$e->getLine().'. Retrying...'], \danog\MadelineProto\Logger::WARNING); } catch (\danog\MadelineProto\Exception $e) { \danog\MadelineProto\Logger::log(['An exception occurred while generating the authorization key: '.$e->getMessage().' in '.basename($e->getFile(), '.php').' on line '.$e->getLine().'. Retrying...'], \danog\MadelineProto\Logger::WARNING); + $req_pq = $req_pq === 'req_pq_multi' ? 'req_pq' : 'req_pq_multi'; } catch (\danog\MadelineProto\RPCErrorException $e) { if ($e->rpc === 'RPC_CALL_FAIL') { throw $e; @@ -595,15 +598,17 @@ trait AuthKeyHandler $socket->temp_auth_key = $this->create_auth_key($this->settings['authorization']['default_temp_auth_key_expires_in'], $id); if (!$cdn) { $this->bind_temp_auth_key($this->settings['authorization']['default_temp_auth_key_expires_in'], $id); - $config = $this->write_client_info('help.getConfig', [], ['datacenter' => $id]); + $config = $this->method_call('help.getConfig', [], ['datacenter' => $id]); $this->sync_authorization($id); $this->get_config($config); } } else { $socket->temp_auth_key = $socket->auth_key; - $config = $this->write_client_info('help.getConfig', [], ['datacenter' => $id]); - $this->sync_authorization($id); - $this->get_config($config); + if (!$cdn) { + $config = $this->method_call('help.getConfig', [], ['datacenter' => $id]); + $this->sync_authorization($id); + $this->get_config($config); + } } } elseif (!$cdn) { $this->sync_authorization($id); diff --git a/src/danog/MadelineProto/MTProtoTools/Files.php b/src/danog/MadelineProto/MTProtoTools/Files.php index bf2d2217..d71eb37b 100644 --- a/src/danog/MadelineProto/MTProtoTools/Files.php +++ b/src/danog/MadelineProto/MTProtoTools/Files.php @@ -349,10 +349,10 @@ trait Files if (isset($message_media['cdn_key'])) { $ivec = substr($message_media['cdn_iv'], 0, 12).pack('N', $offset >> 4); $res['bytes'] = $this->ctr_encrypt($res['bytes'], $message_media['cdn_key'], $ivec); + $this->check_cdn_hash($message_media['file_token'], $offset, $res['bytes'], $datacenter); } if (isset($message_media['key'])) { $res['bytes'] = $ige->decrypt($res['bytes']); - $this->check_cdn_hash($message_media['file_token'], $offset, $res['bytes'], $datacenter); } if ($start_at) { $res['bytes'] = substr($res['bytes'], $start_at); @@ -399,17 +399,19 @@ trait Files private function check_cdn_hash($file, $offset, $data, &$datacenter) { - if (!isset($this->cdn_hashes[$file][$offset])) { - $this->add_cdn_hashes($this->method_call('upload.getCdnFileHashes', ['file_token' => $file, 'offset' => $offset], ['datacenter' => &$datacenter])); + while (strlen($data)) { + if (!isset($this->cdn_hashes[$file][$offset])) { + $this->add_cdn_hashes($this->method_call('upload.getCdnFileHashes', ['file_token' => $file, 'offset' => $offset], ['datacenter' => &$datacenter])); + } + if (!isset($this->cdn_hashes[$file][$offset])) { + throw new \danog\MadelineProto\Exception('Could not fetch CDN hashes for offset '.$offset); + } + if (hash('sha256', substr($data, 0, $this->cdn_hashes[$file][$offset]['limit']), true) !== $this->cdn_hashes[$file][$offset]['hash']) { + throw new \danog\MadelineProto\SecurityException('CDN hash mismatch for offset '.$offset); + } + $data = substr($data, $this->cdn_hashes[$file][$offset]['limit']); + $offset += $this->cdn_hashes[$file][$offset]['limit']; } - if (!isset($this->cdn_hashes[$file][$offset])) { - throw new \danog\MadelineProto\Exception('Could not fetch CDN hashes for offset '.$offset); - } - if (hash('sha256', $data, true) !== $this->cdn_hashes[$file][$offset]['hash']) { - throw new \danog\MadelineProto\SecurityException('CDN hashe mismatch for offset '.$offset); - } - unset($this->cdn_hashes[$file][$offset]); - return true; } diff --git a/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php b/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php index 545362af..852ac2c1 100644 --- a/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php @@ -246,7 +246,7 @@ trait ResponseHandler case 'Updates': unset($this->datacenter->sockets[$datacenter]->new_incoming[$current_msg_id]); $unset = true; - $this->handle_updates($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']); + if (strpos($datacenter, 'cdn') === false) $this->handle_updates($this->datacenter->sockets[$datacenter]->incoming_messages[$current_msg_id]['content']); $only_updates = true && $only_updates; break; default: diff --git a/src/danog/MadelineProto/TL/Conversion/BotAPI.php b/src/danog/MadelineProto/TL/Conversion/BotAPI.php index ed47a175..3af89720 100644 --- a/src/danog/MadelineProto/TL/Conversion/BotAPI.php +++ b/src/danog/MadelineProto/TL/Conversion/BotAPI.php @@ -473,11 +473,11 @@ trait BotAPI public function split_to_chunks($text) { - $total_length = 4096; + $max_length = 4096; $text_arr = []; foreach ($this->multipleExplodeKeepDelimiters(["\n"], $text) as $word) { - if (strlen($word) > 4096) { - foreach (str_split($word, 4096) as $vv) { + if (strlen($word) > $max_length) { + foreach (str_split($word, $max_length) as $vv) { $text_arr[] = $vv; } } else { @@ -485,21 +485,13 @@ trait BotAPI } } $i = 0; - $message[0] = ''; + $message = ['']; foreach ($text_arr as $word) { - if (strlen($message[$i].$word.' ') <= $total_length) { - if ($text_arr[count($text_arr) - 1] == $word) { - $message[$i] .= $word; - } else { - $message[$i] .= $word.' '; - } + if (strlen($message[$i].$word) <= $max_length) { + $message[$i] .= $word; } else { $i++; - if ($text_arr[count($text_arr) - 1] == $word) { - $message[$i] = $word; - } else { - $message[$i] = $word.' '; - } + $message[$i] = $word; } } @@ -510,10 +502,13 @@ trait BotAPI { $initialArray = explode(chr(1), str_replace($delimiters, chr(1), $string)); $finalArray = []; + $delimOffset = 0; foreach ($initialArray as $item) { + $delimOffset += strlen($item); if (strlen($item) > 0) { - $finalArray[] = $item.$string[strpos($string, $item) + strlen($item)]; + $finalArray[] = $item.($delimOffset < strlen($string) ? $string[$delimOffset] : ''); } + $delimOffset++; } return $finalArray; diff --git a/tests/testing.php b/tests/testing.php index ea464647..634c19c3 100755 --- a/tests/testing.php +++ b/tests/testing.php @@ -216,28 +216,22 @@ $time = time(); $inputFile = $MadelineProto->upload('tests/60', 'magic'); // This gets an inputFile object with file name magic var_dump(time() - $time); $media['document'] = ['_' => 'inputMediaUploadedDocument', 'file' => $inputFile, 'mime_type' => 'magic/magic', 'caption' => 'This file was uploaded using MadelineProto', 'attributes' => [['_' => 'documentAttributeFilename', 'file_name' => 'magic.magic']]]; + +$message = 'yay'; +$mention = $MadelineProto->get_info(getenv('TEST_USERNAME')); // Returns an array with all of the constructors that can be extracted from a username or an id +$mention = $mention['user_id']; // Selects only the numeric user id + + foreach (json_decode(getenv('TEST_DESTINATION_GROUPS'), true) as $peer) { $sentMessage = $MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => $message, 'entities' => [['_' => 'inputMessageEntityMentionName', 'offset' => 0, 'length' => mb_strlen($message), 'user_id' => $mention]]]); \danog\MadelineProto\Logger::log([$sentMessage], \danog\MadelineProto\Logger::NOTICE); foreach ($media as $type => $inputMedia) { - $type = $MadelineProto->messages->sendMedia(['peer' => $peer, 'media' => $inputMedia]); + $type = $MadelineProto->messages->sendMedia(['peer' => $peer, 'media' => $inputMedia, 'message' => '['.$message.'](mention:'.$mention.')', 'parse_mode' => 'markdown']); } } -//var_dump($MadelineProto->API->get_updates()); - -if ($bot_token = getenv('BOT_TOKEN')) { - $MadelineProto = new \danog\MadelineProto\API($settings); - $authorization = $MadelineProto->bot_login($bot_token); - \danog\MadelineProto\Logger::log([$authorization], \danog\MadelineProto\Logger::NOTICE); -} -$message = 'yay'; -$mention = $MadelineProto->get_info(getenv('TEST_USERNAME')); // Returns an array with all of the constructors that can be extracted from a username or an id -$mention = $mention['user_id']; // Selects only the numeric user id foreach (json_decode(getenv('TEST_DESTINATION_GROUPS'), true) as $peer) { $sentMessage = $MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => $message, 'entities' => [['_' => 'inputMessageEntityMentionName', 'offset' => 0, 'length' => mb_strlen($message), 'user_id' => $mention]]]); \danog\MadelineProto\Logger::log([$sentMessage], \danog\MadelineProto\Logger::NOTICE); } -//var_dump($MadelineProto->API->get_updates()); -var_dump('HERE');