From 7005cdf10ae2a81620e36de0ee15d1564b1f7694 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Fri, 29 Mar 2019 20:25:42 +0100 Subject: [PATCH] Multiple async and VoIP improvements --- docs | 2 +- magna.php | 87 ++++---- .../DocsBuilder/Constructors.php | 6 - .../MadelineProto/DocsBuilder/Methods.php | 22 --- src/danog/MadelineProto/MTProto.php | 84 +++++--- .../MTProtoTools/AuthKeyHandler.php | 6 +- .../MTProtoTools/CallHandler.php | 185 ------------------ .../MTProtoTools/ResponseHandler.php | 5 +- .../MTProtoTools/UpdateHandler.php | 4 +- .../MadelineProto/VoIP/AuthKeyHandler.php | 13 +- src/danog/MadelineProto/Wrappers/Login.php | 68 ++++--- src/danog/MadelineProto/Wrappers/Loop.php | 1 - 12 files changed, 158 insertions(+), 325 deletions(-) diff --git a/docs b/docs index 3dbba4bc..f0229af1 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 3dbba4bc60dc830c08d5343e438bcd003ba9d1c5 +Subproject commit f0229af1baa48d7529f90d7c3dcfbf9d5f54187b diff --git a/magna.php b/magna.php index 64b0dc7e..0ef5a177 100755 --- a/magna.php +++ b/magna.php @@ -9,11 +9,11 @@ MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY See the GNU Affero General Public License for more details. You should have received a copy of the GNU General Public License along with MadelineProto. If not, see . -*/ -set_include_path(get_include_path().':'.realpath(dirname(__FILE__).'/MadelineProto/')); + */ +set_include_path(get_include_path() . ':' . realpath(dirname(__FILE__) . '/MadelineProto/')); -if (!file_exists(__DIR__.'/vendor/autoload.php')) { - echo 'You did not run composer update, using madeline.php'.PHP_EOL; +if (!file_exists(__DIR__ . '/vendor/autoload.php')) { + echo 'You did not run composer update, using madeline.php' . PHP_EOL; if (!file_exists('madeline.php')) { copy('https://phar.madelineproto.xyz/madeline.php', 'madeline.php'); } @@ -26,15 +26,15 @@ if (!file_exists('songs.php')) { copy('https://github.com/danog/MadelineProto/raw/master/songs.php', 'songs.php'); } -echo 'Deserializing MadelineProto from session.madeline...'.PHP_EOL; +echo 'Deserializing MadelineProto from session.madeline...' . PHP_EOL; /*if (!isset($MadelineProto->inputEncryptedFilePhoto) && false) { - $MadelineProto->inputEncryptedFilePhoto = $MadelineProto->upload_encrypted('tests/faust.jpg', 'fausticorn.jpg'); // This gets an inputFile object with file name magic - $MadelineProto->inputEncryptedFileGif = $MadelineProto->upload_encrypted('tests/pony.mp4'); - $MadelineProto->inputEncryptedFileSticker = $MadelineProto->upload_encrypted('tests/lel.webp'); - $MadelineProto->inputEncryptedFileDocument = $MadelineProto->upload_encrypted('tests/60', 'magic'); // This gets an inputFile object with file name magic - $MadelineProto->inputEncryptedFileVideo = $MadelineProto->upload_encrypted('tests/swing.mp4'); - $MadelineProto->inputEncryptedFileAudio = $MadelineProto->upload_encrypted('tests/mosconi.mp3'); +$MadelineProto->inputEncryptedFilePhoto = $MadelineProto->upload_encrypted('tests/faust.jpg', 'fausticorn.jpg'); // This gets an inputFile object with file name magic +$MadelineProto->inputEncryptedFileGif = $MadelineProto->upload_encrypted('tests/pony.mp4'); +$MadelineProto->inputEncryptedFileSticker = $MadelineProto->upload_encrypted('tests/lel.webp'); +$MadelineProto->inputEncryptedFileDocument = $MadelineProto->upload_encrypted('tests/60', 'magic'); // This gets an inputFile object with file name magic +$MadelineProto->inputEncryptedFileVideo = $MadelineProto->upload_encrypted('tests/swing.mp4'); +$MadelineProto->inputEncryptedFileAudio = $MadelineProto->upload_encrypted('tests/mosconi.mp3'); }*/ class EventHandler extends \danog\MadelineProto\EventHandler @@ -45,15 +45,7 @@ class EventHandler extends \danog\MadelineProto\EventHandler $call->configuration['enable_NS'] = false; $call->configuration['enable_AGC'] = false; $call->configuration['enable_AEC'] = false; - $call->configuration['shared_config'] = [ - 'audio_init_bitrate' => 100 * 1000, - 'audio_max_bitrate' => 100 * 1000, - 'audio_min_bitrate' => 10 * 1000, - 'audio_congestion_window' => 4 * 1024, - //'audio_bitrate_step_decr' => 0, - //'audio_bitrate_step_incr' => 2000, - ]; - $call->configuration['log_file_path'] = '/tmp/logs'.$call->getCallID()['id'].'.log'; // Default is /dev/null + $call->configuration['log_file_path'] = '/tmp/logs' . $call->getCallID()['id'] . '.log'; // Default is /dev/null //$call->configuration["stats_dump_file_path"] = "/tmp/stats".$call->getCallID()['id'].".txt"; // Default is /dev/null $call->parseConfig(); $call->playOnHold($songs); @@ -91,7 +83,7 @@ Propic art by @magnaluna on [deviantart](https://magnaluna.deviantart.com).", 'p $this->configureCall($call); if ($call->getCallState() !== \danog\MadelineProto\VoIP::CALL_STATE_ENDED) { $this->calls[$call->getOtherID()] = $call; - $this->times[$call->getOtherID()] = [time(), $this->messages->sendMessage(['peer' => $call->getOtherID(), 'message' => 'Total running calls: '.count($this->calls).PHP_EOL.PHP_EOL.$call->getDebugString()])['id']]; + $this->times[$call->getOtherID()] = [time(), $this->messages->sendMessage(['peer' => $call->getOtherID(), 'message' => 'Total running calls: ' . count($this->calls) . PHP_EOL . PHP_EOL . $call->getDebugString()])['id']]; } } if (strpos($message, '/program') === 0) { @@ -181,7 +173,7 @@ Propic art by @magnaluna on [deviantart](https://magnaluna.deviantart.com).", 'p $this->calls[$update['phone_call']->getOtherID()] = $update['phone_call']; try { - $this->times[$update['phone_call']->getOtherID()] = [time(), $this->messages->sendMessage(['peer' => $update['phone_call']->getOtherID(), 'message' => 'Total running calls: '.count($this->calls).PHP_EOL.PHP_EOL])['id']]; + $this->times[$update['phone_call']->getOtherID()] = [time(), $this->messages->sendMessage(['peer' => $update['phone_call']->getOtherID(), 'message' => 'Total running calls: ' . count($this->calls) . PHP_EOL . PHP_EOL])['id']]; } catch (\danog\MadelineProto\RPCErrorException $e) { } } @@ -203,7 +195,7 @@ Propic art by @magnaluna on [deviantart](https://magnaluna.deviantart.com).", 'p $this->configureCall($call); if ($call->getCallState() !== \danog\MadelineProto\VoIP::CALL_STATE_ENDED) { $this->calls[$call->getOtherID()] = $call; - $this->times[$call->getOtherID()] = [time(), $this->messages->sendMessage(['peer' => $call->getOtherID(), 'message' => 'Total running calls: '.count($this->calls).PHP_EOL.PHP_EOL.$call->getDebugString()])['id']]; + $this->times[$call->getOtherID()] = [time(), $this->messages->sendMessage(['peer' => $call->getOtherID(), 'message' => 'Total running calls: ' . count($this->calls) . PHP_EOL . PHP_EOL . $call->getDebugString()])['id']]; } } catch (\danog\MadelineProto\RPCErrorException $e) { try { @@ -239,7 +231,7 @@ Propic art by @magnaluna on [deviantart](https://magnaluna.deviantart.com).", 'p } break; } - \danog\MadelineProto\Logger::log(count($this->calls).' calls running!'); + \danog\MadelineProto\Logger::log(count($this->calls) . ' calls running!'); foreach ($this->calls as $key => $call) { if ($call->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) { try { @@ -248,24 +240,24 @@ Propic art by @magnaluna on [deviantart](https://magnaluna.deviantart.com).", 'p 'reply_to_msg_id' => $this->times[$call->getOtherID()][1], 'peer' => $call->getOtherID(), 'message' => 'Call statistics by @magnaluna', 'media' => [ - '_' => 'inputMediaUploadedDocument', - 'file' => "/tmp/stats".$call->getCallID()['id'].".txt", - 'attributes' => [ - ['_' => 'documentAttributeFilename', 'file_name' => "stats".$call->getCallID()['id'].".txt"] - ] + '_' => 'inputMediaUploadedDocument', + 'file' => "/tmp/stats".$call->getCallID()['id'].".txt", + 'attributes' => [ + ['_' => 'documentAttributeFilename', 'file_name' => "stats".$call->getCallID()['id'].".txt"] + ] ], ]);*/ $this->messages->sendMedia([ - 'reply_to_msg_id' => $this->times[$call->getOtherID()][1], - 'peer' => $call->getOtherID(), 'message' => 'Debug info by @magnaluna', - 'media' => [ - '_' => 'inputMediaUploadedDocument', - 'file' => '/tmp/logs'.$call->getCallID()['id'].'.log', - 'attributes' => [ - ['_' => 'documentAttributeFilename', 'file_name' => 'logs'.$call->getCallID()['id'].'.log'], - ], - ], - ]); + 'reply_to_msg_id' => $this->times[$call->getOtherID()][1], + 'peer' => $call->getOtherID(), 'message' => 'Debug info by @magnaluna', + 'media' => [ + '_' => 'inputMediaUploadedDocument', + 'file' => '/tmp/logs' . $call->getCallID()['id'] . '.log', + 'attributes' => [ + ['_' => 'documentAttributeFilename', 'file_name' => 'logs' . $call->getCallID()['id'] . '.log'], + ], + ], + ]); } } catch (\danog\MadelineProto\Exception $e) { echo $e; @@ -274,14 +266,14 @@ Propic art by @magnaluna on [deviantart](https://magnaluna.deviantart.com).", 'p } catch (\danog\MadelineProto\Exception $e) { echo $e; } - @unlink('/tmp/logs'.$call->getCallID()['id'].'.log'); - @unlink('/tmp/stats'.$call->getCallID()['id'].'.txt'); + @unlink('/tmp/logs' . $call->getCallID()['id'] . '.log'); + @unlink('/tmp/stats' . $call->getCallID()['id'] . '.txt'); unset($this->calls[$key]); } elseif (isset($this->times[$call->getOtherID()]) && $this->times[$call->getOtherID()][0] < time()) { $this->times[$call->getOtherID()][0] += 30 + count($this->calls); try { - $this->messages->editMessage(['id' => $this->times[$call->getOtherID()][1], 'peer' => $call->getOtherID(), 'message' => 'Total running calls: '.count($this->calls).PHP_EOL.PHP_EOL.$call->getDebugString()]); + $this->messages->editMessage(['id' => $this->times[$call->getOtherID()][1], 'peer' => $call->getOtherID(), 'message' => 'Total running calls: ' . count($this->calls) . PHP_EOL . PHP_EOL . $call->getDebugString()]); } catch (\danog\MadelineProto\RPCErrorException $e) { echo $e; } @@ -289,7 +281,16 @@ Propic art by @magnaluna on [deviantart](https://magnaluna.deviantart.com).", 'p } } } -$MadelineProto = new \danog\MadelineProto\API('session.madeline', ['secret_chats' => ['accept_chats' => false], 'logger' => ['logger' => 3, 'logger_param' => getcwd().'/MadelineProto.log']]); + +\danog\MadelineProto\VoIPServerConfig::update( + [ + 'audio_init_bitrate' => 100 * 1000, + 'audio_max_bitrate' => 100 * 1000, + 'audio_min_bitrate' => 10 * 1000, + 'audio_congestion_window' => 4 * 1024, + ] +); +$MadelineProto = new \danog\MadelineProto\API('session.madeline', ['secret_chats' => ['accept_chats' => false], 'logger' => ['logger' => 3, 'logger_param' => getcwd() . '/MadelineProto.log']]); $MadelineProto->start(); if (!isset($MadelineProto->programmed_call)) { diff --git a/src/danog/MadelineProto/DocsBuilder/Constructors.php b/src/danog/MadelineProto/DocsBuilder/Constructors.php index c3b33865..cbe878d9 100644 --- a/src/danog/MadelineProto/DocsBuilder/Constructors.php +++ b/src/danog/MadelineProto/DocsBuilder/Constructors.php @@ -212,12 +212,6 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png $'.$constructor.$layer.' = '.$params.'; ``` -[PWRTelegram](https://pwrtelegram.xyz) json-encoded version: - -``` -'.$pwr_params.' -``` - Or, if you\'re into Lua: diff --git a/src/danog/MadelineProto/DocsBuilder/Methods.php b/src/danog/MadelineProto/DocsBuilder/Methods.php index a0bfd2a2..ad266d35 100644 --- a/src/danog/MadelineProto/DocsBuilder/Methods.php +++ b/src/danog/MadelineProto/DocsBuilder/Methods.php @@ -230,28 +230,6 @@ $MadelineProto->start(); $'.$type.' = $MadelineProto->'.$php_method.'(['.$params.']); ``` -### [PWRTelegram HTTP API](https://pwrtelegram.xyz) example (NOT FOR MadelineProto): - -'.($bot ? '### As a bot: - -POST/GET to `https://api.pwrtelegram.xyz/botTOKEN/madeline` - -Parameters: - -* method - '.$data['method'].' -* params - `{'.$json_params.'}` - -' : '').' - -### As a user: - -POST/GET to `https://api.pwrtelegram.xyz/userTOKEN/'.$data['method'].'` - -Parameters: - -'.$pwr_params.' - - Or, if you\'re into Lua: ```lua diff --git a/src/danog/MadelineProto/MTProto.php b/src/danog/MadelineProto/MTProto.php index e73d6b78..52afc459 100644 --- a/src/danog/MadelineProto/MTProto.php +++ b/src/danog/MadelineProto/MTProto.php @@ -19,6 +19,7 @@ namespace danog\MadelineProto; +use Amp\Loop; use danog\MadelineProto\MTProtoTools\ReferenceDatabase; use danog\MadelineProto\Stream\MTProtoTransport\HttpsStream; use danog\MadelineProto\Stream\MTProtoTransport\HttpStream; @@ -147,6 +148,7 @@ class MTProto implements TLCallback private $supportUser = 0; public $referenceDatabase; public $update_deferred; + public $phoneConfigWatcherId; public function __magic_construct($settings = []) { @@ -162,6 +164,9 @@ class MTProto implements TLCallback if (!extension_loaded('json')) { throw new Exception(['extension', 'json']); } + if (!extension_loaded('mbstring')) { + throw new Exception(['extension', 'mbstring']); + } // Connect to servers $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['inst_dc'], Logger::ULTRA_VERBOSE); if (!isset($this->datacenter)) { @@ -236,6 +241,12 @@ class MTProto implements TLCallback if (!extension_loaded('xml')) { throw new Exception(['extension', 'xml']); } + if (!extension_loaded('mbstring')) { + throw new Exception(['extension', 'mbstring']); + } + if (!extension_loaded('json')) { + throw new Exception(['extension', 'json']); + } if (!isset($this->referenceDatabase)) { $this->referenceDatabase = new ReferenceDatabase($this); @@ -280,7 +291,7 @@ class MTProto implements TLCallback } } - if (isset($this->settings['tl_schema']['src']['botAPI']) && $this->settings['tl_schema']['src']['botAPI'] !== __DIR__.'/TL_botAPI.tl') { + if (isset($this->settings['tl_schema']['src']['botAPI']) && $this->settings['tl_schema']['src']['botAPI'] !== __DIR__ . '/TL_botAPI.tl') { unset($this->v); } @@ -394,6 +405,9 @@ class MTProto implements TLCallback public function __destruct() { + if ($this->phoneConfigWatcherId) { + Loop::cancel($this->phoneConfigWatcherId); + } if (\danog\MadelineProto\Magic::$has_thread && is_object(\Thread::getCurrentThread())) { return; } @@ -498,7 +512,7 @@ class MTProto implements TLCallback $lang_pack = 'android'; } // Detect app version - $app_version = self::RELEASE.' ('.self::V.', '.Magic::$revision.')'; + $app_version = self::RELEASE . ' (' . self::V . ', ' . Magic::$revision . ')'; if ($settings['app_info']['api_id'] === 6) { // TG DEV NOTICE: these app info spoofing measures were implemented for NON-MALICIOUS purposes. // All accounts registered with a custom API ID require manual verification through recover@telegram.org, to avoid instant permabans. @@ -542,9 +556,9 @@ class MTProto implements TLCallback 2 => [ // The rest will be fetched using help.getConfig 'ip_address' => '149.154.167.40', - 'port' => 443, + 'port' => 443, 'media_only' => false, - 'tcpo_only' => false, + 'tcpo_only' => false, ], ], 'ipv6' => [ @@ -552,9 +566,9 @@ class MTProto implements TLCallback 2 => [ // The rest will be fetched using help.getConfig 'ip_address' => '2001:067c:04e8:f002:0000:0000:0000:000e', - 'port' => 443, + 'port' => 443, 'media_only' => false, - 'tcpo_only' => false, + 'tcpo_only' => false, ], ], ], @@ -565,9 +579,9 @@ class MTProto implements TLCallback 2 => [ // The rest will be fetched using help.getConfig 'ip_address' => '149.154.167.51', - 'port' => 443, + 'port' => 443, 'media_only' => false, - 'tcpo_only' => false, + 'tcpo_only' => false, ], ], 'ipv6' => [ @@ -575,9 +589,9 @@ class MTProto implements TLCallback 2 => [ // The rest will be fetched using help.getConfig 'ip_address' => '2001:067c:04e8:f002:0000:0000:0000:000a', - 'port' => 443, + 'port' => 443, 'media_only' => false, - 'tcpo_only' => false, + 'tcpo_only' => false, ], ], ], @@ -598,17 +612,17 @@ class MTProto implements TLCallback 'proxy_extra' => $this->altervista ? ['address' => 'localhost', 'port' => 80] : [], // Extra parameters to pass to the proxy class using setExtra 'obfuscated' => false, - 'transport' => 'tcp', - 'pfs' => extension_loaded('gmp'), + 'transport' => 'tcp', + 'pfs' => extension_loaded('gmp'), ], 'default_dc' => 2, ], 'app_info' => [ // obtained in https://my.telegram.org //'api_id' => you should put an API id in the settings array you provide //'api_hash' => you should put an API hash in the settings array you provide - 'device_model' => $device_model, + 'device_model' => $device_model, 'system_version' => $system_version, - 'app_version' => $app_version, + 'app_version' => $app_version, // 🌚 // 'app_version' => self::V, 'lang_code' => $lang_code, @@ -618,16 +632,16 @@ class MTProto implements TLCallback 'layer' => 95, // layer version 'src' => [ - 'mtproto' => __DIR__.'/TL_mtproto_v1.tl', + 'mtproto' => __DIR__ . '/TL_mtproto_v1.tl', // mtproto TL scheme - 'telegram' => __DIR__.'/TL_telegram_v95.tl', + 'telegram' => __DIR__ . '/TL_telegram_v95.tl', // telegram TL scheme - 'secret' => __DIR__.'/TL_secret.tl', + 'secret' => __DIR__ . '/TL_secret.tl', // secret chats TL scheme - 'calls' => __DIR__.'/TL_calls.tl', + 'calls' => __DIR__ . '/TL_calls.tl', // calls TL scheme //'td' => __DIR__.'/TL_td.tl', // telegram-cli TL scheme - 'botAPI' => __DIR__.'/TL_botAPI.tl', + 'botAPI' => __DIR__ . '/TL_botAPI.tl', ], ], 'logger' => [ // Logger settings @@ -641,11 +655,11 @@ class MTProto implements TLCallback * $message is an array containing the messages the log, $level, is the logging level */ // write to - 'logger_param' => Magic::$script_cwd.'/MadelineProto.log', - 'logger' => php_sapi_name() === 'cli' ? 3 : 2, + 'logger_param' => Magic::$script_cwd . '/MadelineProto.log', + 'logger' => php_sapi_name() === 'cli' ? 3 : 2, // overwrite previous setting and echo logs 'logger_level' => Logger::VERBOSE, - 'max_size' => 100 * 1024 * 1024, + 'max_size' => 100 * 1024 * 1024, // Logging level, available logging levels are: ULTRA_VERBOSE, VERBOSE, NOTICE, WARNING, ERROR, FATAL_ERROR. Can be provided as last parameter to the logging function. 'rollbar_token' => '', ], 'max_tries' => [ @@ -656,8 +670,8 @@ class MTProto implements TLCallback 'response' => 5, ], 'flood_timeout' => ['wait_if_lt' => 20], 'msg_array_limit' => [ // How big should be the arrays containing the incoming and outgoing messages? - 'incoming' => 200, - 'outgoing' => 200, + 'incoming' => 200, + 'outgoing' => 200, 'call_queue' => 200, ], 'peer' => [ 'full_info_cache_time' => 3600, @@ -681,10 +695,10 @@ class MTProto implements TLCallback 'handler_workers' => 10, ], 'upload' => [ 'allow_automatic_upload' => true, - 'part_size' => 512 * 1024, + 'part_size' => 512 * 1024, ], 'download' => [ 'report_broken_media' => true, - 'part_size' => 1024 * 1024, + 'part_size' => 1024 * 1024, ], 'pwr' => [ 'pwr' => false, // Need info ? @@ -825,6 +839,16 @@ class MTProto implements TLCallback } yield $dcs; yield $this->init_authorization_async(); + $this->phoneConfigWatcherId = Loop::repeat(24 * 3600 * 1000, function ($watcherId) { + if ($this->authorized === self::LOGGED_IN) { + $this->logger->logger("Fetching phone config..."); + VoIPServerConfig::updateDefault(yield $this->method_call_async_read('phone.getCallConfig', [], ['datacenter' => $this->datacenter->curdc])); + } else { + $this->logger->logger("Not fetching phone config"); + } + }); + VoIPServerConfig::updateDefault(yield $this->method_call_async_read('phone.getCallConfig', [], ['datacenter' => $this->datacenter->curdc])); + $this->logger->logger("Started phone config fetcher"); } public function get_config($config = [], $options = []) @@ -900,9 +924,13 @@ class MTProto implements TLCallback } public function get_self() + { + return $this->wait($this->get_self_async()); + } + public function get_self_async() { try { - $this->authorization = ['user' => $this->method_call('users.getUsers', ['id' => [['_' => 'inputUserSelf']]], ['datacenter' => $this->datacenter->curdc])[0]]; + $this->authorization = ['user' => (yield $this->method_call_async_read('users.getUsers', ['id' => [['_' => 'inputUserSelf']]], ['datacenter' => $this->datacenter->curdc]))[0]]; } catch (RPCErrorException $e) { $this->logger->logger($e->getMessage()); @@ -952,7 +980,7 @@ class MTProto implements TLCallback public function __debugInfo() { - return ['MadelineProto instance '.spl_object_hash($this)]; + return ['MadelineProto instance ' . spl_object_hash($this)]; } const ALL_MIMES = ['webp' => [0 => 'image/webp'], 'png' => [0 => 'image/png', 1 => 'image/x-png'], 'bmp' => [0 => 'image/bmp', 1 => 'image/x-bmp', 2 => 'image/x-bitmap', 3 => 'image/x-xbitmap', 4 => 'image/x-win-bitmap', 5 => 'image/x-windows-bmp', 6 => 'image/ms-bmp', 7 => 'image/x-ms-bmp', 8 => 'application/bmp', 9 => 'application/x-bmp', 10 => 'application/x-win-bitmap'], 'gif' => [0 => 'image/gif'], 'jpeg' => [0 => 'image/jpeg', 1 => 'image/pjpeg'], 'xspf' => [0 => 'application/xspf+xml'], 'vlc' => [0 => 'application/videolan'], 'wmv' => [0 => 'video/x-ms-wmv', 1 => 'video/x-ms-asf'], 'au' => [0 => 'audio/x-au'], 'ac3' => [0 => 'audio/ac3'], 'flac' => [0 => 'audio/x-flac'], 'ogg' => [0 => 'audio/ogg', 1 => 'video/ogg', 2 => 'application/ogg'], 'kmz' => [0 => 'application/vnd.google-earth.kmz'], 'kml' => [0 => 'application/vnd.google-earth.kml+xml'], 'rtx' => [0 => 'text/richtext'], 'rtf' => [0 => 'text/rtf'], 'jar' => [0 => 'application/java-archive', 1 => 'application/x-java-application', 2 => 'application/x-jar'], 'zip' => [0 => 'application/x-zip', 1 => 'application/zip', 2 => 'application/x-zip-compressed', 3 => 'application/s-compressed', 4 => 'multipart/x-zip'], '7zip' => [0 => 'application/x-compressed'], 'xml' => [0 => 'application/xml', 1 => 'text/xml'], 'svg' => [0 => 'image/svg+xml'], '3g2' => [0 => 'video/3gpp2'], '3gp' => [0 => 'video/3gp', 1 => 'video/3gpp'], 'mp4' => [0 => 'video/mp4'], 'm4a' => [0 => 'audio/x-m4a'], 'f4v' => [0 => 'video/x-f4v'], 'flv' => [0 => 'video/x-flv'], 'webm' => [0 => 'video/webm'], 'aac' => [0 => 'audio/x-acc'], 'm4u' => [0 => 'application/vnd.mpegurl'], 'pdf' => [0 => 'application/pdf', 1 => 'application/octet-stream'], 'pptx' => [0 => 'application/vnd.openxmlformats-officedocument.presentationml.presentation'], 'ppt' => [0 => 'application/powerpoint', 1 => 'application/vnd.ms-powerpoint', 2 => 'application/vnd.ms-office', 3 => 'application/msword'], 'docx' => [0 => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'], 'xlsx' => [0 => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 1 => 'application/vnd.ms-excel'], 'xl' => [0 => 'application/excel'], 'xls' => [0 => 'application/msexcel', 1 => 'application/x-msexcel', 2 => 'application/x-ms-excel', 3 => 'application/x-excel', 4 => 'application/x-dos_ms_excel', 5 => 'application/xls', 6 => 'application/x-xls'], 'xsl' => [0 => 'text/xsl'], 'mpeg' => [0 => 'video/mpeg'], 'mov' => [0 => 'video/quicktime'], 'avi' => [0 => 'video/x-msvideo', 1 => 'video/msvideo', 2 => 'video/avi', 3 => 'application/x-troff-msvideo'], 'movie' => [0 => 'video/x-sgi-movie'], 'log' => [0 => 'text/x-log'], 'txt' => [0 => 'text/plain'], 'css' => [0 => 'text/css'], 'html' => [0 => 'text/html'], 'wav' => [0 => 'audio/x-wav', 1 => 'audio/wave', 2 => 'audio/wav'], 'xhtml' => [0 => 'application/xhtml+xml'], 'tar' => [0 => 'application/x-tar'], 'tgz' => [0 => 'application/x-gzip-compressed'], 'psd' => [0 => 'application/x-photoshop', 1 => 'image/vnd.adobe.photoshop'], 'exe' => [0 => 'application/x-msdownload'], 'js' => [0 => 'application/x-javascript'], 'mp3' => [0 => 'audio/mpeg', 1 => 'audio/mpg', 2 => 'audio/mpeg3', 3 => 'audio/mp3'], 'rar' => [0 => 'application/x-rar', 1 => 'application/rar', 2 => 'application/x-rar-compressed'], 'gzip' => [0 => 'application/x-gzip'], 'hqx' => [0 => 'application/mac-binhex40', 1 => 'application/mac-binhex', 2 => 'application/x-binhex40', 3 => 'application/x-mac-binhex40'], 'cpt' => [0 => 'application/mac-compactpro'], 'bin' => [0 => 'application/macbinary', 1 => 'application/mac-binary', 2 => 'application/x-binary', 3 => 'application/x-macbinary'], 'oda' => [0 => 'application/oda'], 'ai' => [0 => 'application/postscript'], 'smil' => [0 => 'application/smil'], 'mif' => [0 => 'application/vnd.mif'], 'wbxml' => [0 => 'application/wbxml'], 'wmlc' => [0 => 'application/wmlc'], 'dcr' => [0 => 'application/x-director'], 'dvi' => [0 => 'application/x-dvi'], 'gtar' => [0 => 'application/x-gtar'], 'php' => [0 => 'application/x-httpd-php', 1 => 'application/php', 2 => 'application/x-php', 3 => 'text/php', 4 => 'text/x-php', 5 => 'application/x-httpd-php-source'], 'swf' => [0 => 'application/x-shockwave-flash'], 'sit' => [0 => 'application/x-stuffit'], 'z' => [0 => 'application/x-compress'], 'mid' => [0 => 'audio/midi'], 'aif' => [0 => 'audio/x-aiff', 1 => 'audio/aiff'], 'ram' => [0 => 'audio/x-pn-realaudio'], 'rpm' => [0 => 'audio/x-pn-realaudio-plugin'], 'ra' => [0 => 'audio/x-realaudio'], 'rv' => [0 => 'video/vnd.rn-realvideo'], 'jp2' => [0 => 'image/jp2', 1 => 'video/mj2', 2 => 'image/jpx', 3 => 'image/jpm'], 'tiff' => [0 => 'image/tiff'], 'eml' => [0 => 'message/rfc822'], 'pem' => [0 => 'application/x-x509-user-cert', 1 => 'application/x-pem-file'], 'p10' => [0 => 'application/x-pkcs10', 1 => 'application/pkcs10'], 'p12' => [0 => 'application/x-pkcs12'], 'p7a' => [0 => 'application/x-pkcs7-signature'], 'p7c' => [0 => 'application/pkcs7-mime', 1 => 'application/x-pkcs7-mime'], 'p7r' => [0 => 'application/x-pkcs7-certreqresp'], 'p7s' => [0 => 'application/pkcs7-signature'], 'crt' => [0 => 'application/x-x509-ca-cert', 1 => 'application/pkix-cert'], 'crl' => [0 => 'application/pkix-crl', 1 => 'application/pkcs-crl'], 'pgp' => [0 => 'application/pgp'], 'gpg' => [0 => 'application/gpg-keys'], 'rsa' => [0 => 'application/x-pkcs7'], 'ics' => [0 => 'text/calendar'], 'zsh' => [0 => 'text/x-scriptzsh'], 'cdr' => [0 => 'application/cdr', 1 => 'application/coreldraw', 2 => 'application/x-cdr', 3 => 'application/x-coreldraw', 4 => 'image/cdr', 5 => 'image/x-cdr', 6 => 'zz-application/zz-winassoc-cdr'], 'wma' => [0 => 'audio/x-ms-wma'], 'vcf' => [0 => 'text/x-vcard'], 'srt' => [0 => 'text/srt'], 'vtt' => [0 => 'text/vtt'], 'ico' => [0 => 'image/x-icon', 1 => 'image/x-ico', 2 => 'image/vnd.microsoft.icon'], 'csv' => [0 => 'text/x-comma-separated-values', 1 => 'text/comma-separated-values', 2 => 'application/vnd.msexcel'], 'json' => [0 => 'application/json', 1 => 'text/json']]; diff --git a/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php b/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php index c941fc2d..f17228be 100644 --- a/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php @@ -463,11 +463,15 @@ trait AuthKeyHandler } public function get_dh_config() + { + return $this->wait($this->get_dh_config_async()); + } + public function get_dh_config_async() { $this->updates_state['sync_loading'] = true; try { - $dh_config = $this->method_call('messages.getDhConfig', ['version' => $this->dh_config['version'], 'random_length' => 0], ['datacenter' => $this->datacenter->curdc]); + $dh_config = yield $this->method_call_async_read('messages.getDhConfig', ['version' => $this->dh_config['version'], 'random_length' => 0], ['datacenter' => $this->datacenter->curdc]); } finally { $this->updates_state['sync_loading'] = false; } diff --git a/src/danog/MadelineProto/MTProtoTools/CallHandler.php b/src/danog/MadelineProto/MTProtoTools/CallHandler.php index 08a8bdcf..c51eda73 100644 --- a/src/danog/MadelineProto/MTProtoTools/CallHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/CallHandler.php @@ -30,191 +30,6 @@ use function Amp\Promise\all; */ trait CallHandler { - /* - public function select() - { - $result = []; - - try { - /* - if ($this->is_http($this->settings['connection_settings']['default_dc']) || $this->altervista) { - $this->logger->logger("Initial HTTP short poll"); - $waiting = $this->datacenter->select(0.1); - $result = $this->handle_select($waiting, $result); - }/ - $tries = 10; // TODO add setting - $this->logger->logger('Long poll'); - $t = microtime(true); - $waiting = $this->datacenter->select(); - $t = microtime(true) - $t; - $this->logger->logger("Long poll took $t"); - - $result = $this->handle_select($waiting, $result); - - do { - $this->logger->logger('Short poll'); - $waiting = $this->datacenter->select($this->is_http($this->settings['connection_settings']['default_dc']) || $this->altervista ? $this->settings['connection_settings']['all']['timeout'] / 10 : true); - $result = $this->handle_select($waiting, $result); - } while ($tries-- && $waiting); - } catch (\danog\MadelineProto\NothingInTheSocketException $e) { - $this->logger->logger('Nothing in the socket while selecting', \danog\MadelineProto\Logger::ULTRA_VERBOSE); - foreach ($this->datacenter->sockets as $dc => $socket) { - $this->close_and_reopen($dc); - $this->send_messages($dc); - } - } - - return $result; - } - - public $did = []; - - public function handle_select($waiting, $result) - { - foreach ($waiting as $dc) { - $error = $this->recv_message($dc); - if ($error !== true) { - $this->close_and_reopen($dc); - if ($error === -404) { - if ($this->datacenter->sockets[$dc]->temp_auth_key !== null) { - $this->logger->logger('WARNING: Resetting auth key...', \danog\MadelineProto\Logger::WARNING); - $this->datacenter->sockets[$dc]->temp_auth_key = null; - $this->init_authorization(); - - return $result; - } - } - - throw new \danog\MadelineProto\RPCErrorException($error, $error); - } - $result[$dc] = $this->handle_messages($dc) && (isset($result[$dc]) ? $result[$dc] : true); - if (($this->is_http($dc) || $this->altervista) && $this->datacenter->sockets[$dc]->new_outgoing) { - $this->send_messages($dc); - } - } - - return $result; - } - public function iorun($updates) - { - do { - if ($updates && time() - $this->last_getdifference > $this->settings['updates']['getdifference_interval']) { - $this->get_updates_difference(); - - return; - } - - if ($canunset = !$this->updates_state['sync_loading']) { - $this->updates_state['sync_loading'] = true; - } - if ($canunsetpostponeupdates = !$this->postpone_updates) { - $this->postpone_updates = true; - } - if ($canunsetpostponepwrchat = !$this->postpone_pwrchat) { - $this->postpone_pwrchat = true; - } - - if (($this->is_http($this->settings['connection_settings']['default_dc']) || $this->altervista) && $updates) { - $this->send_messages($this->settings['connection_settings']['default_dc']); - } - foreach ($this->datacenter->sockets as $id => $datacenter) { - if ($datacenter->pending_outgoing) { - $this->send_messages($id); - } - } - - $this->logger->logger('Polling for ' . ($updates ? 'updates' : 'replies') . ': selecting', \danog\MadelineProto\Logger::ULTRA_VERBOSE); - $t = microtime(true); - $only_updates = $this->select(); - $t = microtime(true) - $t; - $this->logger->logger('Polling for ' . ($updates ? 'updates' : 'replies') . ': selecting took ' . $t, \danog\MadelineProto\Logger::ULTRA_VERBOSE); - $response_result = $this->has_pending_calls(); - - $repeat = 0; - foreach ($this->datacenter->sockets as $id => $datacenter) { - if ($updates) { - if (isset($only_updates[$id])) { - if ($only_updates[$id]) { - $this->logger->logger("Polling for updates: got only updates for DC $id", \danog\MadelineProto\Logger::VERBOSE); - } else { - $this->logger->logger("Polling for updates: got also RPC replies for DC $id", \danog\MadelineProto\Logger::NOTICE); - } - if ($response_result[$id]) { - $this->logger->logger("Polling for updates: still pending requests, resending for DC $id", \danog\MadelineProto\Logger::WARNING); - $this->send_messages($id); - } - } else { - if ($response_result[$id] || $id === $this->settings['connection_settings']['default_dc']) { - $this->logger->logger("Polling for updates: got nothing for DC $id", \danog\MadelineProto\Logger::ERROR); - - if ($this->is_http($id) || $this->altervista) { - $this->logger->logger("Polling for updates: closing and reopening DC $id since we're on HTTP, and we polled"); - $this->close_and_reopen($id); - $datacenter->last_http_wait = 0; - $repeat |= 1; - $this->logger->logger("Polling for updates: and now repolling for DC $id"); - $this->send_messages($id); - } - } - } - } else { - if (isset($only_updates[$id])) { - if ($only_updates[$id]) { - $this->logger->logger("Polling for replies: got only updates for DC $id", \danog\MadelineProto\Logger::WARNING); - - if ($response_result[$id]) { - $this->logger->logger("Polling for replies: still pending requests, repolling for DC $id", \danog\MadelineProto\Logger::WARNING); - $this->send_messages($id); - $repeat |= 1; - } else { - $this->logger->logger("Polling for replies: got all RPC replies for DC $id", \danog\MadelineProto\Logger::ULTRA_VERBOSE); - } - } else { - if ($response_result[$id]) { - $this->logger->logger("Polling for replies: still pending requests, repolling for DC $id", \danog\MadelineProto\Logger::WARNING); - $this->send_messages($id); - } else { - $this->logger->logger("Polling for replies: got all RPC replies for DC $id", \danog\MadelineProto\Logger::NOTICE); - } - } - } else { - if ($response_result[$id]) { - $this->logger->logger("Polling for replies: got nothing for DC $id", \danog\MadelineProto\Logger::ERROR); - $this->logger->logger("Polling for replies: closing and reopening DC $id", \danog\MadelineProto\Logger::ERROR); - $this->close_and_reopen($id); - $datacenter->last_http_wait = 0; - $repeat |= 1; - $this->logger->logger("Polling for replies: resending for DC $id", \danog\MadelineProto\Logger::WARNING); - $this->send_messages($id); - } else { - $this->logger->logger("Polling for replies: got all RPC replies for DC $id", \danog\MadelineProto\Logger::ULTRA_VERBOSE); - } - } - } - } - $this->logger->logger('Running guzzle promise queue'); - \GuzzleHttp\Promise\queue()->run(); - - if ($repeat) { - $this->logger->logger('Repeat iowait'); - } - } while ($repeat); - - if ($canunset) { - $this->updates_state['sync_loading'] = false; - } - if ($canunsetpostponepwrchat) { - $this->postpone_pwrchat = false; - $this->handle_pending_pwrchat(); - } - if ($canunsetpostponeupdates) { - $this->postpone_updates = false; - $this->handle_pending_updates(); - } - } - - */ - public function has_pending_calls() { $result = []; diff --git a/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php b/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php index 328b3985..659c2fc5 100644 --- a/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php @@ -337,9 +337,12 @@ trait ResponseHandler case 500: if ($response['error_message'] === 'MSG_WAIT_FAILED') { $this->datacenter->sockets[$datacenter]->call_queue[$request['queue']] = []; + Loop::defer([$this, 'method_recall'], ['message_id' => $request_id, 'datacenter' => $datacenter]); + return; } + $this->got_response_for_outgoing_message_id($request_id, $datacenter); - Loop::defer([$this, 'method_recall'], ['message_id' => $request_id, 'datacenter' => $datacenter]); + $this->handle_reject($datacenter, $request, new \danog\MadelineProto\RPCErrorException($response['error_message'], $response['error_code'])); return; case 303: diff --git a/src/danog/MadelineProto/MTProtoTools/UpdateHandler.php b/src/danog/MadelineProto/MTProtoTools/UpdateHandler.php index 4230ad21..fcf2ee56 100644 --- a/src/danog/MadelineProto/MTProtoTools/UpdateHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/UpdateHandler.php @@ -55,7 +55,6 @@ trait UpdateHandler return; } $this->updates[$this->updates_key++] = $update; - $this->logger->logger('Stored '); } public function get_updates_async($params = []) @@ -543,7 +542,8 @@ trait UpdateHandler if (isset($this->calls[$update['phone_call']['id']])) { return; } - $controller = new \danog\MadelineProto\VoIP(false, $update['phone_call']['admin_id'], ['_' => 'inputPhoneCall', 'id' => $update['phone_call']['id'], 'access_hash' => $update['phone_call']['access_hash']], $this, \danog\MadelineProto\VoIP::CALL_STATE_INCOMING, $update['phone_call']['protocol']); + $controller = new \danog\MadelineProto\VoIP(false, $update['phone_call']['admin_id'], $this, \danog\MadelineProto\VoIP::CALL_STATE_INCOMING); + $controller->setCall($update['phone_call']); $controller->storage = ['g_a_hash' => $update['phone_call']['g_a_hash']]; $update['phone_call'] = $this->calls[$update['phone_call']['id']] = $controller; break; diff --git a/src/danog/MadelineProto/VoIP/AuthKeyHandler.php b/src/danog/MadelineProto/VoIP/AuthKeyHandler.php index ce6a1234..96a31f72 100644 --- a/src/danog/MadelineProto/VoIP/AuthKeyHandler.php +++ b/src/danog/MadelineProto/VoIP/AuthKeyHandler.php @@ -51,9 +51,11 @@ trait AuthKeyHandler $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['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_p2p' => true, 'udp_reflector' => true, 'min_layer' => 65, 'max_layer' => 65]], ['datacenter' => $this->datacenter->curdc]); - $this->calls[$res['phone_call']['id']] = $controller = new \danog\MadelineProto\VoIP(true, $user['user_id'], ['_' => 'inputPhoneCall', 'id' => $res['phone_call']['id'], 'access_hash' => $res['phone_call']['access_hash']], $this, \danog\MadelineProto\VoIP::CALL_STATE_REQUESTED, $res['phone_call']['protocol']); + $controller = new \danog\MadelineProto\VoIP(true, $user['user_id'], $this, \danog\MadelineProto\VoIP::CALL_STATE_REQUESTED); $controller->storage = ['a' => $a, 'g_a' => str_pad($g_a->toBytes(), 256, chr(0), \STR_PAD_LEFT)]; + $res = $this->method_call('phone.requestCall', ['user_id' => $user, 'g_a_hash' => hash('sha256', $g_a->toBytes(), true), 'protocol' => ['_' => 'phoneCallProtocol', 'udp_p2p' => true, 'udp_reflector' => true, 'min_layer' => 65, 'max_layer' => \danog\MadelineProto\VoIP::getConnectionMaxLayer()]], ['datacenter' => $this->datacenter->curdc]); + $controller->setCall($res['phone_call']); + $this->calls[$res['phone_call']['id']] = $controller; $this->handle_pending_updates(); $this->get_updates_difference(); @@ -83,7 +85,7 @@ trait AuthKeyHandler $this->check_G($g_b, $dh_config['p']); try { - $res = $this->method_call('phone.acceptCall', ['peer' => $call, 'g_b' => $g_b->toBytes(), 'protocol' => ['_' => 'phoneCallProtocol', 'udp_reflector' => true, 'udp_p2p' => true, 'min_layer' => 65, 'max_layer' => 65]], ['datacenter' => $this->datacenter->curdc]); + $res = $this->method_call('phone.acceptCall', ['peer' => $call, 'g_b' => $g_b->toBytes(), 'protocol' => ['_' => 'phoneCallProtocol', 'udp_reflector' => true, 'udp_p2p' => true, 'min_layer' => 65, 'max_layer' => \danog\MadelineProto\VoIP::getConnectionMaxLayer()]], ['datacenter' => $this->datacenter->curdc]); } catch (\danog\MadelineProto\RPCErrorException $e) { if ($e->rpc === 'CALL_ALREADY_ACCEPTED') { $this->logger->logger(sprintf(\danog\MadelineProto\Lang::$current_lang['call_already_accepted'], $call['id'])); @@ -126,7 +128,7 @@ trait AuthKeyHandler $params['g_b'] = new \phpseclib\Math\BigInteger($params['g_b'], 256); $this->check_G($params['g_b'], $dh_config['p']); $key = str_pad($params['g_b']->powMod($this->calls[$params['id']]->storage['a'], $dh_config['p'])->toBytes(), 256, chr(0), \STR_PAD_LEFT); - $res = $this->method_call('phone.confirmCall', ['key_fingerprint' => substr(sha1($key, true), -8), 'peer' => ['id' => $params['id'], 'access_hash' => $params['access_hash'], '_' => 'inputPhoneCall'], 'g_a' => $this->calls[$params['id']]->storage['g_a'], 'protocol' => ['_' => 'phoneCallProtocol', 'udp_reflector' => true, 'min_layer' => 65, 'max_layer' => 65]], ['datacenter' => $this->datacenter->curdc])['phone_call']; + $res = $this->method_call('phone.confirmCall', ['key_fingerprint' => substr(sha1($key, true), -8), 'peer' => ['id' => $params['id'], 'access_hash' => $params['access_hash'], '_' => 'inputPhoneCall'], 'g_a' => $this->calls[$params['id']]->storage['g_a'], 'protocol' => ['_' => 'phoneCallProtocol', 'udp_reflector' => true, 'min_layer' => 65, 'max_layer' => \danog\MadelineProto\VoIP::getConnectionMaxLayer()]], ['datacenter' => $this->datacenter->curdc])['phone_call']; $visualization = []; $length = new \phpseclib\Math\BigInteger(count(\danog\MadelineProto\Magic::$emojis)); foreach (str_split(hash('sha256', $key.str_pad($this->calls[$params['id']]->storage['g_a'], 256, chr(0), \STR_PAD_LEFT), true), 8) as $number) { @@ -134,7 +136,7 @@ trait AuthKeyHandler $visualization[] = \danog\MadelineProto\Magic::$emojis[(int) (new \phpseclib\Math\BigInteger($number, 256))->divide($length)[1]->toString()]; } $this->calls[$params['id']]->setVisualization($visualization); - $this->calls[$params['id']]->configuration['shared_config'] = array_merge($this->method_call('phone.getCallConfig', [], ['datacenter' => $this->datacenter->curdc]), $this->calls[$params['id']]->configuration['shared_config']); + $this->calls[$params['id']]->configuration['endpoints'] = array_merge([$res['connection']], $res['alternative_connections'], $this->calls[$params['id']]->configuration['endpoints']); $this->calls[$params['id']]->configuration = array_merge(['recv_timeout' => $this->config['call_receive_timeout_ms'] / 1000, 'init_timeout' => $this->config['call_connect_timeout_ms'] / 1000, 'data_saving' => \danog\MadelineProto\VoIP::DATA_SAVING_NEVER, 'enable_NS' => true, 'enable_AEC' => true, 'enable_AGC' => true, 'auth_key' => $key, 'auth_key_id' => substr(sha1($key, true), -8), 'call_id' => substr(hash('sha256', $key, true), -16), 'network_type' => \danog\MadelineProto\VoIP::NET_TYPE_ETHERNET], $this->calls[$params['id']]->configuration); $this->calls[$params['id']]->parseConfig(); @@ -177,7 +179,6 @@ trait AuthKeyHandler $visualization[] = \danog\MadelineProto\Magic::$emojis[(int) (new \phpseclib\Math\BigInteger($number, 256))->divide($length)[1]->toString()]; } $this->calls[$params['id']]->setVisualization($visualization); - $this->calls[$params['id']]->configuration['shared_config'] = array_merge($this->method_call('phone.getCallConfig', [], ['datacenter' => $this->datacenter->curdc]), $this->calls[$params['id']]->configuration['shared_config']); $this->calls[$params['id']]->configuration['endpoints'] = array_merge([$params['connection']], $params['alternative_connections'], $this->calls[$params['id']]->configuration['endpoints']); $this->calls[$params['id']]->configuration = array_merge(['recv_timeout' => $this->config['call_receive_timeout_ms'] / 1000, 'init_timeout' => $this->config['call_connect_timeout_ms'] / 1000, 'data_saving' => \danog\MadelineProto\VoIP::DATA_SAVING_NEVER, 'enable_NS' => true, 'enable_AEC' => true, 'enable_AGC' => true, 'auth_key' => $key, 'auth_key_id' => substr(sha1($key, true), -8), 'call_id' => substr(hash('sha256', $key, true), -16), 'network_type' => \danog\MadelineProto\VoIP::NET_TYPE_ETHERNET], $this->calls[$params['id']]->configuration); $this->calls[$params['id']]->parseConfig(); diff --git a/src/danog/MadelineProto/Wrappers/Login.php b/src/danog/MadelineProto/Wrappers/Login.php index 59e007ee..c252fbcd 100644 --- a/src/danog/MadelineProto/Wrappers/Login.php +++ b/src/danog/MadelineProto/Wrappers/Login.php @@ -20,6 +20,8 @@ namespace danog\MadelineProto\Wrappers; use danog\MadelineProto\MTProtoTools\PasswordCalculator; +use danog\MadelineProto\VoIPServerConfig; +use function Amp\Promise\wait; /** * Manages logging in and out. @@ -27,6 +29,10 @@ use danog\MadelineProto\MTProtoTools\PasswordCalculator; trait Login { public function logout() + { + return $this->wait($this->logout_async()); + } + public function logout_async() { foreach ($this->datacenter->sockets as $socket) { $socket->authorized = false; @@ -40,41 +46,39 @@ trait Login $this->users = []; $this->state = []; $this->tos = ['expires' => 0, 'accepted' => true]; - if (!$this->method_call('auth.logOut', [], ['datacenter' => $this->datacenter->curdc])) { - throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['logout_error']); - } + yield $this->method_call_async_read('auth.logOut', [], ['datacenter' => $this->datacenter->curdc]); $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['logout_ok'], \danog\MadelineProto\Logger::NOTICE); return true; } - public function bot_login($token) + public function bot_login_async($token) { if ($this->authorized === self::LOGGED_IN) { $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['already_logged_in'], \danog\MadelineProto\Logger::NOTICE); - $this->logout(); + yield $this->logout_async(); } $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_bot'], \danog\MadelineProto\Logger::NOTICE); - $this->authorization = $this->method_call('auth.importBotAuthorization', ['bot_auth_token' => $token, 'api_id' => $this->settings['app_info']['api_id'], 'api_hash' => $this->settings['app_info']['api_hash']], ['datacenter' => $this->datacenter->curdc]); + $this->authorization = yield $this->method_call_async_read('auth.importBotAuthorization', ['bot_auth_token' => $token, 'api_id' => $this->settings['app_info']['api_id'], 'api_hash' => $this->settings['app_info']['api_hash']], ['datacenter' => $this->datacenter->curdc]); $this->authorized = self::LOGGED_IN; $this->authorized_dc = $this->datacenter->curdc; $this->datacenter->sockets[$this->datacenter->curdc]->authorized = true; $this->updates = []; $this->updates_key = 0; - $this->init_authorization(); + yield $this->init_authorization_async(); $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_ok'], \danog\MadelineProto\Logger::NOTICE); return $this->authorization; } - public function phone_login($number, $sms_type = 5) + public function phone_login_async($number, $sms_type = 5) { if ($this->authorized === self::LOGGED_IN) { $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['already_logged_in'], \danog\MadelineProto\Logger::NOTICE); - $this->logout(); + yield $this->logout_async(); } $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_code_sending'], \danog\MadelineProto\Logger::NOTICE); - $this->authorization = $this->method_call('auth.sendCode', ['settings' => ['_' => 'codeSettings'], 'phone_number' => $number, 'sms_type' => $sms_type, 'api_id' => $this->settings['app_info']['api_id'], 'api_hash' => $this->settings['app_info']['api_hash'], 'lang_code' => $this->settings['app_info']['lang_code']], ['datacenter' => $this->datacenter->curdc]); + $this->authorization = yield $this->method_call_async_read('auth.sendCode', ['settings' => ['_' => 'codeSettings'], 'phone_number' => $number, 'sms_type' => $sms_type, 'api_id' => $this->settings['app_info']['api_id'], 'api_hash' => $this->settings['app_info']['api_hash'], 'lang_code' => $this->settings['app_info']['lang_code']], ['datacenter' => $this->datacenter->curdc]); $this->authorized_dc = $this->datacenter->curdc; $this->authorization['phone_number'] = $number; //$this->authorization['_'] .= 'MP'; @@ -86,7 +90,7 @@ trait Login return $this->authorization; } - public function complete_phone_login($code) + public function complete_phone_login_async($code) { if ($this->authorized !== self::WAITING_CODE) { throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['login_code_uncalled']); @@ -95,11 +99,11 @@ trait Login $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_user'], \danog\MadelineProto\Logger::NOTICE); try { - $authorization = $this->method_call('auth.signIn', ['phone_number' => $this->authorization['phone_number'], 'phone_code_hash' => $this->authorization['phone_code_hash'], 'phone_code' => (string) $code], ['datacenter' => $this->datacenter->curdc]); + $authorization = yield $this->method_call_async_read('auth.signIn', ['phone_number' => $this->authorization['phone_number'], 'phone_code_hash' => $this->authorization['phone_code_hash'], 'phone_code' => (string) $code], ['datacenter' => $this->datacenter->curdc]); } catch (\danog\MadelineProto\RPCErrorException $e) { if ($e->rpc === 'SESSION_PASSWORD_NEEDED') { $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_2fa_enabled'], \danog\MadelineProto\Logger::NOTICE); - $this->authorization = $this->method_call('account.getPassword', [], ['datacenter' => $this->datacenter->curdc]); + $this->authorization = yield $this->method_call_async_read('account.getPassword', [], ['datacenter' => $this->datacenter->curdc]); if (!isset($this->authorization['hint'])) $this->authorization['hint'] = ''; $this->authorized = self::WAITING_PASSWORD; @@ -118,17 +122,19 @@ trait Login $this->authorized = self::LOGGED_IN; $this->authorization = $authorization; $this->datacenter->sockets[$this->datacenter->curdc]->authorized = true; - $this->init_authorization(); + yield $this->init_authorization_async(); + VoIPServerConfig::updateDefault(yield $this->method_call_async_read('phone.getCallConfig', [], ['datacenter' => $this->datacenter->curdc])); + $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_ok'], \danog\MadelineProto\Logger::NOTICE); return $this->authorization; } - public function import_authorization($authorization) + public function import_authorization_async($authorization) { if ($this->authorized === self::LOGGED_IN) { $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['already_logged_in'], \danog\MadelineProto\Logger::NOTICE); - $this->logout(); + yield $this->logout_async(); } $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_auth_key'], \danog\MadelineProto\Logger::NOTICE); list($dc_id, $auth_key) = $authorization; @@ -147,39 +153,42 @@ trait Login $this->datacenter->sockets[$dc_id]->new_incoming = []; $this->datacenter->sockets[$dc_id]->authorized = true; $this->authorized = self::LOGGED_IN; - $this->init_authorization(); + yield $this->init_authorization_async(); + VoIPServerConfig::updateDefault(yield $this->method_call_async_read('phone.getCallConfig', [], ['datacenter' => $this->datacenter->curdc])); - return $this->get_self(); + return yield $this->get_self_async(); } - public function export_authorization() + public function export_authorization_async() { if ($this->authorized !== self::LOGGED_IN) { throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['not_logged_in']); } - $this->get_self(); + yield $this->get_self_async(); $this->authorized_dc = $this->datacenter->curdc; return [$this->datacenter->curdc, $this->datacenter->sockets[$this->datacenter->curdc]->auth_key['auth_key']]; } - public function complete_signup($first_name, $last_name) + public function complete_signup_async($first_name, $last_name) { if ($this->authorized !== self::WAITING_SIGNUP) { throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['signup_uncalled']); } $this->authorized = self::NOT_LOGGED_IN; $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['signing_up'], \danog\MadelineProto\Logger::NOTICE); - $this->authorization = $this->method_call('auth.signUp', ['phone_number' => $this->authorization['phone_number'], 'phone_code_hash' => $this->authorization['phone_code_hash'], 'phone_code' => $this->authorization['phone_code'], 'first_name' => $first_name, 'last_name' => $last_name], ['datacenter' => $this->datacenter->curdc]); + $this->authorization = yield $this->method_call_async_read('auth.signUp', ['phone_number' => $this->authorization['phone_number'], 'phone_code_hash' => $this->authorization['phone_code_hash'], 'phone_code' => $this->authorization['phone_code'], 'first_name' => $first_name, 'last_name' => $last_name], ['datacenter' => $this->datacenter->curdc]); $this->authorized = self::LOGGED_IN; $this->datacenter->sockets[$this->datacenter->curdc]->authorized = true; - $this->init_authorization(); + yield $this->init_authorization_async(); + VoIPServerConfig::updateDefault(yield $this->method_call_async_read('phone.getCallConfig', [], ['datacenter' => $this->datacenter->curdc])); + $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['signup_ok'], \danog\MadelineProto\Logger::NOTICE); return $this->authorization; } - public function complete_2fa_login($password) + public function complete_2fa_login_async($password) { if ($this->authorized !== self::WAITING_PASSWORD) { throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['2fa_uncalled']); @@ -188,20 +197,21 @@ trait Login $hasher = new PasswordCalculator($this->logger); $hasher->addInfo($this->authorization); $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_user'], \danog\MadelineProto\Logger::NOTICE); - $this->authorization = $this->method_call('auth.checkPassword', ['password' => $hasher->getCheckPassword($password)], ['datacenter' => $this->datacenter->curdc]); + $this->authorization = yield $this->method_call_async_read('auth.checkPassword', ['password' => $hasher->getCheckPassword($password)], ['datacenter' => $this->datacenter->curdc]); $this->authorized = self::LOGGED_IN; $this->datacenter->sockets[$this->datacenter->curdc]->authorized = true; - $this->init_authorization(); + yield $this->init_authorization_async(); $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_ok'], \danog\MadelineProto\Logger::NOTICE); + VoIPServerConfig::updateDefault(yield $this->method_call_async_read('phone.getCallConfig', [], ['datacenter' => $this->datacenter->curdc])); return $this->authorization; } - public function update_2fa(array $params): bool + public function update_2fa_async(array $params) { $hasher = new PasswordCalculator($this->logger); - $hasher->addInfo($this->method_call('account.getPassword', [], ['datacenter' => $this->datacenter->curdc])); + $hasher->addInfo(yield $this->method_call_async_read('account.getPassword', [], ['datacenter' => $this->datacenter->curdc])); - return $this->method_call('account.updatePasswordSettings', $hasher->getPassword($params), ['datacenter' => $this->datacenter->curdc]); + return yield $this->method_call_async_read('account.updatePasswordSettings', $hasher->getPassword($params), ['datacenter' => $this->datacenter->curdc]); } } diff --git a/src/danog/MadelineProto/Wrappers/Loop.php b/src/danog/MadelineProto/Wrappers/Loop.php index d5e0f2fd..27cd6270 100644 --- a/src/danog/MadelineProto/Wrappers/Loop.php +++ b/src/danog/MadelineProto/Wrappers/Loop.php @@ -102,7 +102,6 @@ trait Loop $this->datacenter->sockets[$this->settings['connection_settings']['default_dc']]->updater->start(); $this->logger->logger('Started update loop', \danog\MadelineProto\Logger::NOTICE); - $offset = 0; while (true) { foreach ($this->updates as $update) {