diff --git a/bots/MadelineProto_bot.php b/bots/MadelineProto_bot.php index 4fcfbac4..3834ee8f 100755 --- a/bots/MadelineProto_bot.php +++ b/bots/MadelineProto_bot.php @@ -101,9 +101,11 @@ while (true) { } else { array_walk($rows, function (&$value, $key) { $value = explode('|', $value); - array_walk($value, function (&$value, $key) { $value = ['text' => trim($value)]; }); + array_walk($value, function (&$value, $key) { + $value = ['text' => trim($value)]; + }); }); - $toset['results'] = [['_' => 'inputBotInlineResult', 'id' => rand(0, pow(2,31)-1), 'type' => 'article', 'title' => $text, 'description' => 'Your keyboard', 'send_message' => ['_' => 'inputBotInlineMessageText', 'message' => $text, 'reply_markup' => ['inline_keyboard' => $rows]]]]; + $toset['results'] = [['_' => 'inputBotInlineResult', 'id' => rand(0, pow(2, 31) - 1), 'type' => 'article', 'title' => $text, 'description' => 'Your keyboard', 'send_message' => ['_' => 'inputBotInlineMessageText', 'message' => $text, 'reply_markup' => ['inline_keyboard' => $rows]]]]; $MadelineProto->messages->setInlineBotResults($toset); } } diff --git a/build_docs.php b/build_docs.php index 8b46e592..488ec623 100755 --- a/build_docs.php +++ b/build_docs.php @@ -38,7 +38,7 @@ $docs = [ 'readme' => false, ], [ - 'tl_schema' => ['telegram' => __DIR__.'/src/danog/MadelineProto/TL_telegram_v62.tl', 'secret' => __DIR__.'/src/danog/MadelineProto/TL_secret.tl','td' => __DIR__.'/src/danog/MadelineProto/TL_td.tl'], + 'tl_schema' => ['telegram' => __DIR__.'/src/danog/MadelineProto/TL_telegram_v62.tl', 'secret' => __DIR__.'/src/danog/MadelineProto/TL_secret.tl', 'td' => __DIR__.'/src/danog/MadelineProto/TL_td.tl'], 'title' => 'MadelineProto API documentation (layer 62)', 'description' => 'MadelineProto API documentation (layer 62)', 'output_dir' => __DIR__.'/docs/API_docs', diff --git a/src/danog/MadelineProto/Conversion/BotAPI.php b/src/danog/MadelineProto/Conversion/BotAPI.php index c4dcf4c5..e45b1b32 100644 --- a/src/danog/MadelineProto/Conversion/BotAPI.php +++ b/src/danog/MadelineProto/Conversion/BotAPI.php @@ -97,6 +97,7 @@ trait BotAPI foreach ($data as $key => $element) { $newd[$key] = $this->MTProto_to_botAPI($element, $sent_arguments); } + return $newd; } switch ($data['_']) { @@ -450,5 +451,4 @@ trait BotAPI return $arguments; } - } diff --git a/src/danog/MadelineProto/Conversion/BotAPIFiles.php b/src/danog/MadelineProto/Conversion/BotAPIFiles.php index eb571e4a..fa7f6849 100644 --- a/src/danog/MadelineProto/Conversion/BotAPIFiles.php +++ b/src/danog/MadelineProto/Conversion/BotAPIFiles.php @@ -59,6 +59,7 @@ trait BotAPIFiles $new .= $cur; } } + return $new; } @@ -146,7 +147,6 @@ trait BotAPIFiles return $res; - case 9: $constructor = ['_' => 'document', 'mime_type' => '', 'attributes' => [['_' => 'documentAttributeAudio', 'voice' => false]]]; list($type, $constructor['dc_id'], $constructor['id'], $constructor['access_hash'], $verify) = \danog\PHP\Struct::unpack(' [ - '_' => 'updateNewMessage', + '_' => 'updateNewMessage', 'disable_notification' => ['message', 'silent'], - 'message' => ['message'], + 'message' => ['message'], ], 'message' => [ - '_' => 'message', - 'id' => ['id'], - 'sender_user_id' => ['from_id'], - 'chat_id' => ['to_id', 'choose_chat_id_from_botapi'], - 'send_state' => ['choose_incoming_or_sent'], - 'can_be_edited' => ['choose_can_edit'], - 'can_be_deleted' => ['choose_can_delete'], - 'is_post' => ['post'], - 'date' => ['date'], - 'edit_date' => ['edit_date'], - 'forward_info' => ['fwd_info', 'choose_forward_info'], + '_' => 'message', + 'id' => ['id'], + 'sender_user_id' => ['from_id'], + 'chat_id' => ['to_id', 'choose_chat_id_from_botapi'], + 'send_state' => ['choose_incoming_or_sent'], + 'can_be_edited' => ['choose_can_edit'], + 'can_be_deleted' => ['choose_can_delete'], + 'is_post' => ['post'], + 'date' => ['date'], + 'edit_date' => ['edit_date'], + 'forward_info' => ['fwd_info', 'choose_forward_info'], 'reply_to_message_id' => ['reply_to_msg_id'], - 'ttl' => ['choose_ttl'], - 'ttl_expires_in' => ['choose_ttl_expires_in'], - 'via_bot_user_id' => ['via_bot_id'], - 'views' => ['views'], - 'content' => ['choose_message_content'], - 'reply_markup' => ['reply_markup'] + 'ttl' => ['choose_ttl'], + 'ttl_expires_in' => ['choose_ttl_expires_in'], + 'via_bot_user_id' => ['via_bot_id'], + 'views' => ['views'], + 'content' => ['choose_message_content'], + 'reply_markup' => ['reply_markup'], ], 'messages.sendMessage' => [ - 'chat_id' => ['peer'], - 'reply_to_message_id' => ['reply_to_msg_id'], - 'disable_notification' => ['silent'], - 'from_background' => ['background'], + 'chat_id' => ['peer'], + 'reply_to_message_id' => ['reply_to_msg_id'], + 'disable_notification' => ['silent'], + 'from_background' => ['background'], 'input_message_content' => ['choose_message_content'], - 'reply_markup' => ['reply_markup'] - ] + 'reply_markup' => ['reply_markup'], + ], ]; private $reverse = [ 'sendMessage'=> 'messages.sendMessage', ]; private $ignore = ['updateMessageID']; - public function tdcli_to_td(&$params, $key=null) { - if (!is_array($params)) return $params; - if (!isset($params['ID'])) { array_walk($params, [$this, 'tdcli_to_td']); return $params; } + + public function tdcli_to_td(&$params, $key = null) + { + if (!is_array($params)) { + return $params; + } + if (!isset($params['ID'])) { + array_walk($params, [$this, 'tdcli_to_td']); + + return $params; + } foreach ($params as $key => $value) { $value = $this->tdcli_to_td($value); if (preg_match('/_$/', $key)) { @@ -67,9 +75,12 @@ trait TD } $params['_'] = lcfirst($params['ID']); unset($params['ID']); + return $params; } - public function td_to_mtproto($params) { + + public function td_to_mtproto($params) + { $newparams = ['_' => $this->reverse[$params['_']]]; foreach ($this->td_params_conversion[$newparams['_']] as $td => $mtproto) { @@ -79,28 +90,45 @@ trait TD switch ($params[$td]['_']) { case 'inputMessageText': $params[$td]['_'] = 'messages.sendMessage'; - if (isset($params['disable_web_page_preview'])) $newparams['no_webpage'] = $params[$td]['disable_web_page_preview']; - $newparams = array_merge($params[$td],$newparams); + if (isset($params['disable_web_page_preview'])) { + $newparams['no_webpage'] = $params[$td]['disable_web_page_preview']; + } + $newparams = array_merge($params[$td], $newparams); break; default: throw new Exception("Can't convert non text messages yet!"); } break; default: $newparams[$mtproto[0]] = isset($params[$td]) ? $params[$td] : null; - if (is_array($newparams[$mtproto[0]])) $newparams[$mtproto[0]] = $this->mtproto_to_td($newparams[$mtproto[0]]); + if (is_array($newparams[$mtproto[0]])) { + $newparams[$mtproto[0]] = $this->mtproto_to_td($newparams[$mtproto[0]]); + } } } } + return $newparams; - } - public function mtproto_to_tdcli($params) { + } + + public function mtproto_to_tdcli($params) + { return $this->td_to_tdcli($this->mtproto_to_td($params)); } - public function mtproto_to_td(&$params) { - if (!is_array($params)) return $params; - if (!isset($params['_'])) { array_walk($params, [$this, 'mtproto_to_td']); return $params; } + + public function mtproto_to_td(&$params) + { + if (!is_array($params)) { + return $params; + } + if (!isset($params['_'])) { + array_walk($params, [$this, 'mtproto_to_td']); + + return $params; + } $newparams = ['_' => $params['_']]; - if (in_array($params['_'], $this->ignore)) return $params; + if (in_array($params['_'], $this->ignore)) { + return $params; + } foreach ($this->td_params_conversion[$params['_']] as $td => $mtproto) { if (is_string($mtproto)) { $newparams[$td] = $mtproto; @@ -121,11 +149,19 @@ trait TD case 'choose_forward_info': if (isset($params['fwd_from'])) { $newparams[$td] = ['_' => 'messageForwardedFromUser']; - if (isset($params['fwd_from']['channel_id'])) $newparams[$td] = ['_'=> 'messageForwardedPost', 'chat_id' => '-100'.$params['fwd_from']['channel_id']]; + if (isset($params['fwd_from']['channel_id'])) { + $newparams[$td] = ['_'=> 'messageForwardedPost', 'chat_id' => '-100'.$params['fwd_from']['channel_id']]; + } $newparams[$td]['date'] = $params['fwd_from']['date']; - if (isset($params['fwd_from']['channel_post'])) $newparams[$td]['channel_post'] = $params['fwd_from']['channel_post']; - if (isset($params['fwd_from']['from_id'])) $newparams[$td]['sender_user_id'] = $params['fwd_from']['from_id']; - } else $newparams[$td] = null; + if (isset($params['fwd_from']['channel_post'])) { + $newparams[$td]['channel_post'] = $params['fwd_from']['channel_post']; + } + if (isset($params['fwd_from']['from_id'])) { + $newparams[$td]['sender_user_id'] = $params['fwd_from']['from_id']; + } + } else { + $newparams[$td] = null; + } break; case 'choose_ttl': $newparams[$td] = isset($params['ttl']) ? $params['ttl'] : 0; @@ -136,9 +172,15 @@ trait TD case 'choose_message_content': if ($params['message'] !== '') { $newparams[$td] = ['_' => 'messageText', 'text' => $params['message']]; - if (isset($params['media']['_']) && $params['media']['_'] === 'messageMediaWebPage') $newparams[$td]['web_page'] = $this->mtproto_to_td($params['media']['webpage']); - if (isset($params['entities'])) $newparams[$td]['entities'] = $params['entities']; - } else throw new Exception("Can't convert non text messages yet!"); + if (isset($params['media']['_']) && $params['media']['_'] === 'messageMediaWebPage') { + $newparams[$td]['web_page'] = $this->mtproto_to_td($params['media']['webpage']); + } + if (isset($params['entities'])) { + $newparams[$td]['entities'] = $params['entities']; + } + } else { + throw new Exception("Can't convert non text messages yet!"); + } break; default: if (isset($mtproto[1])) { @@ -146,24 +188,33 @@ trait TD } else { $newparams[$td] = isset($params[$mtproto[0]]) ? $params[$mtproto[0]] : null; } - if (is_array($newparams[$td])) $newparams[$td] = $this->mtproto_to_td($newparams[$td]); + if (is_array($newparams[$td])) { + $newparams[$td] = $this->mtproto_to_td($newparams[$td]); + } } } } return $newparams; } - public function td_to_tdcli($params) { - if (!is_array($params)) return $params; + + public function td_to_tdcli($params) + { + if (!is_array($params)) { + return $params; + } $newparams = []; foreach ($params as $key => $value) { if ($key === '_') { $newparams['ID'] = ucfirst($value); } else { - if (!is_numeric($key) && !preg_match('/_^/', $key)) $key = $key.'_'; + if (!is_numeric($key) && !preg_match('/_^/', $key)) { + $key = $key.'_'; + } $newparams[$key] = $this->td_to_tdcli($value); } } + return $newparams; } } diff --git a/src/danog/MadelineProto/DocsBuilder.php b/src/danog/MadelineProto/DocsBuilder.php index b4ebde10..75ec68b2 100755 --- a/src/danog/MadelineProto/DocsBuilder.php +++ b/src/danog/MadelineProto/DocsBuilder.php @@ -20,8 +20,12 @@ class DocsBuilder { set_error_handler(['\danog\MadelineProto\Exception', 'ExceptionErrorHandler']); $this->construct_TL($settings['tl_schema']); - if (isset($settings['tl_schema']['td']) && !isset($settings['tl_schema']['telegram'])) $this->constructors = $this->td_constructors; - if (isset($settings['tl_schema']['td']) && !isset($settings['tl_schema']['telegram'])) $this->methods = $this->td_methods; + if (isset($settings['tl_schema']['td']) && !isset($settings['tl_schema']['telegram'])) { + $this->constructors = $this->td_constructors; + } + if (isset($settings['tl_schema']['td']) && !isset($settings['tl_schema']['telegram'])) { + $this->methods = $this->td_methods; + } $this->settings = $settings; if (!file_exists($this->settings['output_dir'])) { mkdir($this->settings['output_dir']); @@ -149,13 +153,13 @@ description: '.$this->settings['description'].' } $table .= '|'.str_replace('_', '\_', $param['name']).'|'.(isset($param['subtype']) ? 'Array of ' : '').'['.str_replace('_', '\_', $ptype).'](../types/'.$ptype.'.md) | '.($param['flag'] ? 'Optional' : 'Yes').'|'; if (isset($this->td_descriptions['methods'][$rmethod])) { - $table .= $this->td_descriptions['methods'][$rmethod]['params'][$param['name']].'|'; + $table .= $this->td_descriptions['methods'][$rmethod]['params'][$param['name']].'|'; } $table .= PHP_EOL; $params .= "'".$param['name']."' => "; $params .= (isset($param['subtype']) ? '['.$ptype.']' : $ptype).', '; - $lua_params .= $param['name']."="; + $lua_params .= $param['name'].'='; $lua_params .= (isset($param['subtype']) ? '{'.$ptype.'}' : $ptype).', '; if ($param['name'] === 'entities') { $hasentities = true; @@ -383,13 +387,13 @@ description: List of methods } $table .= '|'.str_replace('_', '\_', $param['name']).'|'.(isset($param['subtype']) ? 'Array of ' : '').'['.str_replace('_', '\_', $ptype).'](../'.$link_type.'/'.$ptype.'.md) | '.($param['flag'] ? 'Optional' : 'Yes').'|'; if (isset($this->td_descriptions['constructors'][$rconstructor]['params'][$param['name']])) { - $table .= $this->td_descriptions['constructors'][$rconstructor]['params'][$param['name']].'|'; + $table .= $this->td_descriptions['constructors'][$rconstructor]['params'][$param['name']].'|'; } $table .= PHP_EOL; $params .= "'".$param['name']."' => "; $params .= (isset($param['subtype']) ? '['.$param['subtype'].']' : $param['type']).', '; - $lua_params .= $param['name']."="; + $lua_params .= $param['name'].'='; $lua_params .= (isset($param['subtype']) ? '{'.$param['subtype'].'}' : $param['type']).', '; } $params = "['_' => '".$rconstructor."', ".$params.']'; @@ -531,11 +535,11 @@ $".$type." = 'channel#38575794'; // tg-cli style id (channels) $header .= 'The following syntax can also be used: ``` -$'.$type." = -147286699; // Numeric chat id returned by request_secret_chat, can be positive or negative +$'.$type.' = -147286699; // Numeric chat id returned by request_secret_chat, can be positive or negative ``` -"; +'; } $constructors = '### Possible values (constructors): diff --git a/src/danog/MadelineProto/Lua.php b/src/danog/MadelineProto/Lua.php index c85e76e9..6d8770bc 100644 --- a/src/danog/MadelineProto/Lua.php +++ b/src/danog/MadelineProto/Lua.php @@ -18,8 +18,11 @@ class Lua private $Lua; private $script; - public function __construct($script, $MadelineProto) { - if (!file_exists($script)) throw new Exception('Provided script does not exist'); + public function __construct($script, $MadelineProto) + { + if (!file_exists($script)) { + throw new Exception('Provided script does not exist'); + } $this->MadelineProto = $MadelineProto; $settings = $this->MadelineProto->get_settings(); $settings['updates']['handle_updates'] = true; @@ -27,8 +30,14 @@ class Lua $this->script = $script; $this->__wakeup(); } - public function __sleep() { return ['MadelineProto', 'script']; } - public function __wakeup() { + + public function __sleep() + { + return ['MadelineProto', 'script']; + } + + public function __wakeup() + { $this->Lua = new \Lua($this->script); $this->madelineproto_lua = 1; $this->Lua->registerCallback('tdcli_function', [$this, 'tdcli_function']); @@ -45,37 +54,73 @@ class Lua $this->{$namespace} = $methods[$namespace]; } } - public function tdcli_function ($params, $cb = null, $cb_extra = null) { + + public function tdcli_function($params, $cb = null, $cb_extra = null) + { $params = $this->MadelineProto->td_to_mtproto($this->MadelineProto->tdcli_to_td($params)); - if ($params === 0) return 0; + if ($params === 0) { + return 0; + } $result = $this->MadelineProto->API->method_call($params['_'], $params); - if (is_callable($cb)) $cb($this->MadelineProto->mtproto_to_td($result), $cb_extra); + if (is_callable($cb)) { + $cb($this->MadelineProto->mtproto_to_td($result), $cb_extra); + } + return $result; } - public function madeline_function ($params, $cb = null, $cb_extra = null) { + public function madeline_function($params, $cb = null, $cb_extra = null) + { $result = $this->MadelineProto->API->method_call($params['_'], $params); - if (is_callable($cb)) $cb($result, $cb_extra); + if (is_callable($cb)) { + $cb($result, $cb_extra); + } + return $result; } - public function tdcli_update_callback($update) { + + public function tdcli_update_callback($update) + { $this->Lua->tdcli_update_callback($this->MadelineProto->mtproto_to_tdcli($update)); } - - private function convert_array($array) { - if (!is_array($value)) return $array; - if ($this->is_seqential($value)) return array_flip(array_map(function($el){ return $el + 1; }, array_flip($array))); + private function convert_array($array) + { + if (!is_array($value)) { + return $array; + } + if ($this->is_seqential($value)) { + return array_flip(array_map(function ($el) { + return $el + 1; + }, array_flip($array))); + } } - private function is_sequential(array $arr) { - if (array() === $arr) return false; + private function is_sequential(array $arr) + { + if ([] === $arr) { + return false; + } + return isset($arr[0]) && array_keys($arr) === range(0, count($arr) - 1); } - public function __get($name) { - if ($name === 'API') return $this->MadelineProto->API; + + public function __get($name) + { + if ($name === 'API') { + return $this->MadelineProto->API; + } + return $this->Lua->{$name}; } - public function __call($name, $params) { return $this->Lua->{$name}(...$params); } - public function __set($name, $value) { return $this->Lua->{$name} = $value; } + + public function __call($name, $params) + { + return $this->Lua->{$name}(...$params); + } + + public function __set($name, $value) + { + return $this->Lua->{$name} = $value; + } } diff --git a/src/danog/MadelineProto/MTProto.php b/src/danog/MadelineProto/MTProto.php index e6d0203c..caec6630 100644 --- a/src/danog/MadelineProto/MTProto.php +++ b/src/danog/MadelineProto/MTProto.php @@ -71,7 +71,6 @@ class MTProto $this->twoe2047 = new \phpseclib\Math\BigInteger('16158503035655503650357438344334975980222051334857742016065172713762327569433945446598600705761456731844358980460949009747059779575245460547544076193224141560315438683650498045875098875194826053398028819192033784138396109321309878080919047169238085235290822926018152521443787945770532904303776199561965192760957166694834171210342487393282284747428088017663161029038902829665513096354230157075129296432088558362971801859230928678799175576150822952201848806616643615613562842355410104862578550863465661734839271290328348967522998634176499319107762583194718667771801067716614802322659239302476074096777926805529798115328'); $this->twoe2048 = new \phpseclib\Math\BigInteger('32317006071311007300714876688669951960444102669715484032130345427524655138867890893197201411522913463688717960921898019494119559150490921095088152386448283120630877367300996091750197750389652106796057638384067568276792218642619756161838094338476170470581645852036305042887575891541065808607552399123930385521914333389668342420684974786564569494856176035326322058077805659331026192708460314150258592864177116725943603718461857357598351152301645904403697613233287231227125684710820209725157101726931323469678542580656697935045997268352998638215525166389437335543602135433229604645318478604952148193555853611059596230656'); - $this->switch_dc(2, true); $this->get_config(); } @@ -200,8 +199,8 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB 'src' => [ 'mtproto' => __DIR__.'/TL_mtproto_v1.json', // mtproto TL scheme 'telegram' => __DIR__.'/TL_telegram_v62.tl', // telegram TL scheme - 'secret' => __DIR__.'/TL_secret.tl', // secret chats TL scheme - 'td' => __DIR__.'/TL_td.tl', // telegram-cli TL scheme + 'secret' => __DIR__.'/TL_secret.tl', // secret chats TL scheme + 'td' => __DIR__.'/TL_td.tl', // telegram-cli TL scheme ], ], 'logger' => [ // Logger settings @@ -387,7 +386,9 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB { return 2; } - public function get_self() { + + public function get_self() + { return $this->datacenter->authorization['user']; } } diff --git a/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php b/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php index 91d40e75..e19eae5e 100644 --- a/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php @@ -414,7 +414,9 @@ trait AuthKeyHandler throw new \danog\MadelineProto\SecurityException('Auth Failed'); } - public function check_G($g_a, $p) { + + public function check_G($g_a, $p) + { /* * *********************************************************************** @@ -437,7 +439,9 @@ trait AuthKeyHandler return true; } - public function check_p_g($p, $g) { + + public function check_p_g($p, $g) + { /* * *********************************************************************** * Check validity of dh_prime @@ -468,11 +472,11 @@ trait AuthKeyHandler * 2^2047 < p < 2^2048 */ \danog\MadelineProto\Logger::log(['Executing p/g checks (2/2)...'], \danog\MadelineProto\Logger::VERBOSE); - if ($p->compare($this->twoe2047) <= 0 // 2^2047 < p or p > 2^2047 or ! p <= 2^2047 + if ($p->compare($this->twoe2047) <= 0 // 2^2047 < p or p > 2^2047 or ! p <= 2^2047 || $p->compare($this->twoe2048) >= 0 // p < 2^2048 or ! p >= 2^2048 ) { - throw new \danog\MadelineProto\SecurityException("g isn't a safe 2048-bit prime (2^2047 < p < 2^2048 is false)."); - } + throw new \danog\MadelineProto\SecurityException("g isn't a safe 2048-bit prime (2^2047 < p < 2^2048 is false)."); + } /* * *********************************************************************** @@ -481,29 +485,37 @@ trait AuthKeyHandler */ \danog\MadelineProto\Logger::log(['Executing g check...'], \danog\MadelineProto\Logger::VERBOSE); - if ($g->compare($this->one) <= 0 // 1 < g or g > 1 or ! g <= 1 + if ($g->compare($this->one) <= 0 // 1 < g or g > 1 or ! g <= 1 || $g->compare($p->subtract($this->one)) >= 0 // g < p - 1 or ! g >= p - 1 ) { - throw new \danog\MadelineProto\SecurityException('g is invalid (1 < g < p - 1 is false).'); - } + throw new \danog\MadelineProto\SecurityException('g is invalid (1 < g < p - 1 is false).'); + } + return true; } - public function get_dh_config() { + + public function get_dh_config() + { $this->getting_state = true; $dh_config = $this->method_call('messages.getDhConfig', ['version' => $this->dh_config['version'], 'random_length' => 0]); $this->getting_state = false; if ($dh_config['_'] === 'messages.dhConfigNotModified') { \danog\MadelineProto\Logger::log(\danog\MadelineProto\Logger::VERBOSE, ['DH configuration not modified']); + return $this->dh_config; } $dh_config['p'] = new \phpseclib\Math\BigInteger($dh_config['p'], 256); $dh_config['g'] = new \phpseclib\Math\BigInteger($dh_config['g']); $this->check_p_g($dh_config['p'], $dh_config['g']); + return $this->dh_config = $dh_config; } + private $temp_requested_secret_chats = []; private $secret_chats = []; - public function accept_secret_chat($params) { + + public function accept_secret_chat($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); @@ -518,9 +530,10 @@ trait AuthKeyHandler $this->check_G($g_b, $dh_config['p']); $this->notify_layer($params['id']); $this->handle_pending_updates(); - } - public function request_secret_chat($user) { + + public function request_secret_chat($user) + { $user = $this->get_info($user)['InputUser']; \danog\MadelineProto\Logger::log(['Creating secret chat with '.$user['user_id'].'...'], \danog\MadelineProto\Logger::VERBOSE); $dh_config = $this->get_dh_config(); @@ -533,11 +546,15 @@ trait AuthKeyHandler $this->temp_requested_secret_chats[$res['id']] = $a; $this->handle_pending_updates(); $this->get_updates_difference(); + return $res['id']; } - public function complete_secret_chat($params) { + + public function complete_secret_chat($params) + { if ($this->secret_chat_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(); @@ -556,12 +573,19 @@ trait AuthKeyHandler $this->notify_layer($params['id']); $this->handle_pending_updates(); } - public function notify_layer($chat) { + + public function notify_layer($chat) + { $this->method_call('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionNotifyLayer', 'layer' => $this->encrypted_layer]]]); } + private $temp_rekeyed_secret_chats = []; - public function rekey($chat) { - if ($this->secret_chats[$chat]['rekeying'][0] !== 0) return; + + public function rekey($chat) + { + if ($this->secret_chats[$chat]['rekeying'][0] !== 0) { + return; + } \danog\MadelineProto\Logger::log(['Rekeying secret chat '.$chat.'...'], \danog\MadelineProto\Logger::VERBOSE); $dh_config = $this->get_dh_config(); \danog\MadelineProto\Logger::log(['Generating a...'], \danog\MadelineProto\Logger::VERBOSE); @@ -575,9 +599,12 @@ trait AuthKeyHandler $this->secret_chats[$chat]['rekeying'] = [1, $e]; $this->handle_pending_updates(); $this->get_updates_difference(); + return $e; } - public function accept_rekey($chat, $params) { + + public function accept_rekey($chat, $params) + { if ($this->secret_chats[$chat]['rekeying'][0] !== 0) { $my = $this->temp_rekeyed_secret_chats[$this->secret_chats[$chat]['rekeying'][1]]; if ($my['exchange_id'] > $params['exchange_id']) { @@ -586,6 +613,7 @@ trait AuthKeyHandler if ($my['exchange_id'] === $params['exchange_id']) { $this->secret_chats[$chat]['rekeying'] = [0]; $this->rekey($chat); + return; } } @@ -606,10 +634,13 @@ trait AuthKeyHandler $this->method_call('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionAcceptKey', 'g_b' => $g_b->toBytes(), 'exchange_id' => $params['exchange_id'], 'key_fingerprint' => $key['fingerprint']]]]); $this->handle_pending_updates(); $this->get_updates_difference(); - } - public function commit_rekey($chat, $params) { - if ($this->secret_chats[$chat]['rekeying'][0] !== 1) return; + + public function commit_rekey($chat, $params) + { + if ($this->secret_chats[$chat]['rekeying'][0] !== 1) { + return; + } \danog\MadelineProto\Logger::log(['Committing rekeying of secret chat '.$chat.'...'], \danog\MadelineProto\Logger::VERBOSE); $dh_config = $this->get_dh_config(); $params['g_b'] = new \phpseclib\Math\BigInteger($params['g_b'], 256); @@ -631,10 +662,13 @@ trait AuthKeyHandler $this->handle_pending_updates(); $this->get_updates_difference(); - } - public function complete_rekey($chat, $params) { - if ($this->secret_chats[$chat]['rekeying'][0] !== 2) return; + + public function complete_rekey($chat, $params) + { + if ($this->secret_chats[$chat]['rekeying'][0] !== 2) { + return; + } if ($this->temp_rekeyed_secret_chats['fingerprint'] !== $params['key_fingerprint']) { $this->method_call('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionAbortKey', 'exchange_id' => $params['exchange_id']]]]); throw new \danog\MadelineProto\SecurityException('Invalid key fingerprint!'); @@ -647,14 +681,24 @@ trait AuthKeyHandler unset($this->temp_rekeyed_secret_chats[$params['exchange_id']]); $this->method_call('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionNoop']]]); } - public function secret_chat_status($chat) { - if (isset($this->secret_chats[$chat])) return 2; - if (isset($this->temp_requested_secret_chats[$chat])) return 1; + + public function secret_chat_status($chat) + { + if (isset($this->secret_chats[$chat])) { + return 2; + } + if (isset($this->temp_requested_secret_chats[$chat])) { + return 1; + } + return 0; } - public function get_secret_chat($chat) { + + public function get_secret_chat($chat) + { return $this->secret_chats[$chat]; } + public function bind_temp_auth_key($expires_in) { 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 06047e1c..44f34ca4 100644 --- a/src/danog/MadelineProto/MTProtoTools/CallHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/CallHandler.php @@ -158,7 +158,9 @@ trait CallHandler throw new \danog\MadelineProto\Exception('An error occurred while calling method '.$method.' ('.$last_error.').'); } - public function object_call($object, $args = [], $aargs = ['message_id' => null, 'heavy' => false]) { + + public function object_call($object, $args = [], $aargs = ['message_id' => null, 'heavy' => false]) + { if (!is_array($args)) { throw new \danog\MadelineProto\Exception("Arguments aren't an array."); } diff --git a/src/danog/MadelineProto/MTProtoTools/Files.php b/src/danog/MadelineProto/MTProtoTools/Files.php index e8ee5d4c..6d96202e 100644 --- a/src/danog/MadelineProto/MTProtoTools/Files.php +++ b/src/danog/MadelineProto/MTProtoTools/Files.php @@ -13,7 +13,7 @@ If not, see . namespace danog\MadelineProto\MTProtoTools; /** - * Manages upload and download of files + * Manages upload and download of files. */ trait Files { @@ -46,7 +46,7 @@ trait Files $key = $this->random(32); $iv = $this->random(32); $digest = hash('md5', $key.$iv, true); - $fingerprint = \danog\PHP\Struct::unpack('setIV($iv); $ige->setKey($key); @@ -70,12 +70,15 @@ trait Files $constructor['key'] = $key; $constructor['key'] = $iv; } + return $constructor; } + public function upload_encrypted($file, $file_name = '', $cb = null) { return $this->upload($file, $file_name, $cb, true); } + public function get_download_info($message_media) { if (is_string($message_media)) { @@ -93,16 +96,18 @@ trait Files $res['key'] = $message_media['decrypted_message']['media']['key']; $res['iv'] = $message_media['decrypted_message']['media']['iv']; if (isset($message_media['decrypted_message']['media']['file_name'])) { - $pathinfo = pathinfo($message_media['decrypted_message']['media']['file_name']); - if (isset($pathinfo['extension'])) { - $res['ext'] = '.'.$pathinfo['extension']; - } - $res['name'] = $pathinfo['filename']; + $pathinfo = pathinfo($message_media['decrypted_message']['media']['file_name']); + if (isset($pathinfo['extension'])) { + $res['ext'] = '.'.$pathinfo['extension']; + } + $res['name'] = $pathinfo['filename']; + } + if (isset($message_media['decrypted_message']['media']['mime_type'])) { + $res['mime'] = $message_media['decrypted_message']['media']['mime_type']; } - if (isset($message_media['decrypted_message']['media']['mime_type'])) $res['mime'] = $message_media['decrypted_message']['media']['mime_type']; if (isset($message_media['decrypted_message']['media']['attributes'])) { - foreach ($message_media['decrypted_message']['media']['attributes'] as $attribute) { - switch ($attribute['_']) { + foreach ($message_media['decrypted_message']['media']['attributes'] as $attribute) { + switch ($attribute['_']) { case 'documentAttributeFilename': $pathinfo = pathinfo($attribute['file_name']); if (isset($pathinfo['extension'])) { @@ -114,7 +119,7 @@ trait Files $audio = $attribute; break; } - } + } } if (isset($audio) && isset($audio['title']) && !isset($res['name'])) { $res['name'] = $audio['title']; @@ -128,6 +133,7 @@ trait Files if (!isset($res['name'])) { $res['name'] = $message_media['file']['access_hash']; } + return $res; case 'messageMediaPhoto': $photo = end($message_media['photo']['sizes']); @@ -245,8 +251,10 @@ trait Files } if (isset($info['key'])) { $digest = hash('md5', $info['key'].$info['iv'], true); - $fingerprint = \danog\PHP\Struct::unpack('setIV($info['iv']); $ige->setKey($info['key']); diff --git a/src/danog/MadelineProto/MTProtoTools/MessageHandler.php b/src/danog/MadelineProto/MTProtoTools/MessageHandler.php index 67306fdd..1eb710ae 100644 --- a/src/danog/MadelineProto/MTProtoTools/MessageHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/MessageHandler.php @@ -129,15 +129,18 @@ trait MessageHandler $this->datacenter->new_incoming[$message_id] = $message_id; $this->handle_messages(); } - public function encrypt_secret_message($chat_id, $message) { + + public function encrypt_secret_message($chat_id, $message) + { if (!isset($this->secret_chats[$chat_id])) { \danog\MadelineProto\Logger::log('I do not have the secret chat '.$chat_id.' in the database, skipping message...'); + return false; } $message = $this->serialize_object(['type' => $message['_']], $message, $this->secret_chats[$chat_id]['layer']); $this->secret_chats[$chat_id]['outgoing'][] = $message; $this->secret_chats[$chat_id]['ttr']--; - if (($this->secret_chats[$chat_id]['ttr'] <= 0 || time() - $this->secret_chats[$chat_id]['updated'] > 7*24*60*60) && $this->secret_chats[$chat_id]['rekeying'] === 0) { + if (($this->secret_chats[$chat_id]['ttr'] <= 0 || time() - $this->secret_chats[$chat_id]['updated'] > 7 * 24 * 60 * 60) && $this->secret_chats[$chat_id]['rekeying'] === 0) { $this->rekey($chat_id); } @@ -146,15 +149,21 @@ trait MessageHandler list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->secret_chats[$chat_id]['key']['auth_key'], 'to server'); $padding = $this->random($this->posmod(-strlen($message), 16)); $message = $this->secret_chats[$chat_id]['key']['fingerprint'].$message_key.$this->ige_encrypt($message.$padding, $aes_key, $aes_iv); + return $message; } - public function handle_encrypted_update($message) { + + public function handle_encrypted_update($message) + { if (!isset($this->secret_chats[$message['message']['chat_id']])) { \danog\MadelineProto\Logger::log('I do not have the secret chat '.$message['message']['chat_id'].' in the database, skipping message...'); + return false; } $auth_key_id = \danog\PHP\Struct::unpack('secret_chats[$message['message']['chat_id']]['key']['fingerprint']) throw new \danog\MadelineProto\SecurityException('Key fingerprint mismatch'); + if ($auth_key_id !== $this->secret_chats[$message['message']['chat_id']]['key']['fingerprint']) { + throw new \danog\MadelineProto\SecurityException('Key fingerprint mismatch'); + } $message_key = substr($message['message']['bytes'], 8, 16); $encrypted_data = substr($message['message']['bytes'], 24); list($aes_key, $aes_iv) = $this->aes_calculate($message_key, $this->secret_chats[$message['message']['chat_id']]['key']['auth_key'], 'to server'); @@ -180,7 +189,7 @@ trait MessageHandler throw new \danog\MadelineProto\SecurityException('random_bytes is too short'); } $this->secret_chats[$message['message']['chat_id']]['ttr']--; - if (($this->secret_chats[$message['message']['chat_id']]['ttr'] <= 0 || time() - $this->secret_chats[$message['message']['chat_id']]['updated'] > 7*24*60*60) && $this->secret_chats[$message['message']['chat_id']]['rekeying'] === 0) { + if (($this->secret_chats[$message['message']['chat_id']]['ttr'] <= 0 || time() - $this->secret_chats[$message['message']['chat_id']]['updated'] > 7 * 24 * 60 * 60) && $this->secret_chats[$message['message']['chat_id']]['rekeying'] === 0) { $this->rekey($message['message']['chat_id']); } unset($message['message']['bytes']); diff --git a/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php b/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php index 91c7fe0b..2d83e60b 100644 --- a/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php @@ -332,31 +332,42 @@ trait ResponseHandler break; } } - public function handle_decrypted_update($update) { - if (isset($update['message']['decrypted_message']['random_bytes']) && strlen($update['message']['decrypted_message']['random_bytes']) < 15) throw new \danog\MadelineProto\ResponseException('random_bytes is too short!'); + + public function handle_decrypted_update($update) + { + if (isset($update['message']['decrypted_message']['random_bytes']) && strlen($update['message']['decrypted_message']['random_bytes']) < 15) { + throw new \danog\MadelineProto\ResponseException('random_bytes is too short!'); + } $this->secret_chats[$update['message']['chat_id']]['incoming'][] = $update['message']; switch ($update['message']['decrypted_message']['_']) { case 'decryptedMessageService': switch ($update['message']['decrypted_message']['action']) { case 'decryptedMessageActionRequestKey': $this->accept_rekey($update['message']['chat_id'], $update['message']['decrypted_message']['action']); + return; case 'decryptedMessageActionAcceptKey': $this->commit_rekey($update['message']['chat_id'], $update['message']['decrypted_message']['action']); + return; case 'decryptedMessageActionCommitKey': $this->complete_rekey($update['message']['chat_id'], $update['message']['decrypted_message']['action']); + return; case 'decryptedMessageActionNotifyLayer': $this->secret_chats[$update['message']['chat_id']]['layer'] = $update['message']['decrypted_message']['action']['layer']; - if ($update['message']['decrypted_message']['action']['layer'] >= 17 && time() - $this->secret_chats[$update['message']['chat_id']]['created'] > 15) $this->notify_layer($update['message']['chat_id']); + if ($update['message']['decrypted_message']['action']['layer'] >= 17 && time() - $this->secret_chats[$update['message']['chat_id']]['created'] > 15) { + $this->notify_layer($update['message']['chat_id']); + } + return; case 'decryptedMessageActionSetMessageTTL': $this->secret_chats[$update['message']['chat_id']]['ttl'] = $update['message']['decrypted_message']['action']['ttl_seconds']; + return; case 'decryptedMessageActionResend': @@ -366,6 +377,7 @@ trait ResponseHandler // $this->send_encrypted_message($update['message']['chat_id'], $update['message']['decrypted_message']); } } + return; default: // $this->save_update(['_' => 'updateNewDecryptedMessage', 'peer' => $this->secret_chats[$update['message']['chat_id']]['InputEncryptedChat'], 'in_seq_no' => $this->get_in_seq_no($update['message']['chat_id']), 'out_seq_no' => $this->get_out_seq_no($update['message']['chat_id']), 'message' => $update['message']['decrypted_message']]); diff --git a/src/danog/MadelineProto/MTProtoTools/SeqNoHandler.php b/src/danog/MadelineProto/MTProtoTools/SeqNoHandler.php index c89c544f..6d4cbc19 100644 --- a/src/danog/MadelineProto/MTProtoTools/SeqNoHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/SeqNoHandler.php @@ -25,10 +25,14 @@ trait SeqNoHandler return ($value * 2) + $in; } - public function get_in_seq_no($chat) { + + public function get_in_seq_no($chat) + { return count($this->secret_chats[$chat]['incoming']); } - public function get_out_seq_no($chat) { + + public function get_out_seq_no($chat) + { return count($this->secret_chats[$chat]['outgoing']); } } diff --git a/src/danog/MadelineProto/MTProtoTools/UpdateHandler.php b/src/danog/MadelineProto/MTProtoTools/UpdateHandler.php index bc9cd55f..7d6ea6b2 100644 --- a/src/danog/MadelineProto/MTProtoTools/UpdateHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/UpdateHandler.php @@ -198,6 +198,7 @@ trait UpdateHandler $this->should_serialize = true; $this->updates_state['qts'] = 0; } + return $this->updates_state; } @@ -500,7 +501,7 @@ trait UpdateHandler return false; } - if ($update['qts'] > $cur_state['qts']+1) { + if ($update['qts'] > $cur_state['qts'] + 1) { \danog\MadelineProto\Logger::log(['Qts hole. update qts: '.$update['qts'].' > current qts '.$cur_state['qts'].'+1, chat id: '.$update['message']['chat_id']], \danog\MadelineProto\Logger::ERROR); $this->get_updates_difference(); @@ -511,6 +512,7 @@ trait UpdateHandler $cur_state['qts'] = $update['qts']; $this->should_serialize = true; $this->handle_encrypted_update($update); + return; } /* @@ -521,16 +523,25 @@ trait UpdateHandler if ($update['_'] === 'updateEncryption') { switch ($update['chat']['_']) { case 'encryptedChatRequested': - if ($this->settings['secret_chats']['accept_chats'] === false || (is_array($this->settings['secret_chats']['accept_chats']) && !in_array($update['chat']['admin_id'], $this->settings['secret_chats']['accept_chats']))) return; + if ($this->settings['secret_chats']['accept_chats'] === false || (is_array($this->settings['secret_chats']['accept_chats']) && !in_array($update['chat']['admin_id'], $this->settings['secret_chats']['accept_chats']))) { + return; + } \danog\MadelineProto\Logger::log(['Accepting secret chat '.$update['chat']['id']], \danog\MadelineProto\Logger::NOTICE); + return $this->accept_secret_chat($update['chat']); case 'encryptedChatDiscarded': \danog\MadelineProto\Logger::log(['Revoking secret chat '.$update['chat']['id']], \danog\MadelineProto\Logger::NOTICE); - if (isset($this->secret_chats[$update['chat']['id']])) unset($this->secret_chats[$update['chat']['id']]); - if (isset($this->temp_requested_secret_chats[$update['chat']['id']])) unset($this->temp_requested_secret_chats[$update['chat']['id']]); + if (isset($this->secret_chats[$update['chat']['id']])) { + unset($this->secret_chats[$update['chat']['id']]); + } + if (isset($this->temp_requested_secret_chats[$update['chat']['id']])) { + unset($this->temp_requested_secret_chats[$update['chat']['id']]); + } + return; case 'encryptedChat': \danog\MadelineProto\Logger::log(['Completing creation of secret chat '.$update['chat']['id']], \danog\MadelineProto\Logger::NOTICE); + return $this->complete_secret_chat($update['chat']); } \danog\MadelineProto\Logger::log([$update], \danog\MadelineProto\Logger::NOTICE); diff --git a/src/danog/MadelineProto/Serialization.php b/src/danog/MadelineProto/Serialization.php index 834dcd36..ca8c8ee0 100644 --- a/src/danog/MadelineProto/Serialization.php +++ b/src/danog/MadelineProto/Serialization.php @@ -63,6 +63,7 @@ class Serialization if ($unserialized === false) { throw new Exception('An error occurred on deserialization'); } + return $unserialized; } } diff --git a/src/danog/MadelineProto/TL/TL.php b/src/danog/MadelineProto/TL/TL.php index ffd316e2..b301dca3 100644 --- a/src/danog/MadelineProto/TL/TL.php +++ b/src/danog/MadelineProto/TL/TL.php @@ -15,6 +15,7 @@ namespace danog\MadelineProto\TL; trait TL { public $encrypted_layer = -1; + public function construct_tl($files) { \danog\MadelineProto\Logger::log(['Loading TL schemes...'], \danog\MadelineProto\Logger::VERBOSE); @@ -40,7 +41,9 @@ trait TL if (preg_match('|^//@|', $line)) { $list = explode(' @', str_replace('//', ' ', $line)); foreach ($list as $elem) { - if ($elem === '') continue; + if ($elem === '') { + continue; + } $elem = explode(' ', $elem, 2); if ($elem[0] === 'class') { $elem = explode(' ', $elem[1], 2); @@ -51,11 +54,15 @@ trait TL if (!is_null($class)) { $this->td_descriptions['types'][$class] = $elem[1]; $class = null; - } else $e = $elem[1]; + } else { + $e = $elem[1]; + } continue; } - if ($elem[0] === 'param_description') $elem[0] = 'description'; - $dparams[$elem[0]]= $elem[1]; + if ($elem[0] === 'param_description') { + $elem[0] = 'description'; + } + $dparams[$elem[0]] = $elem[1]; } continue; } @@ -78,9 +85,13 @@ trait TL if (preg_match('/^vector#/', $line)) { continue; } - if (preg_match('/ \?= /', $line)) continue; + if (preg_match('/ \?= /', $line)) { + continue; + } $name = preg_replace(['/#.*/', '/\s.*/'], '', $line); - if (in_array($name, ['bytes', 'int128', 'int256', 'int512'])) continue; + if (in_array($name, ['bytes', 'int128', 'int256', 'int512'])) { + continue; + } $clean = preg_replace([ '/:bytes /', '/;/', @@ -93,7 +104,7 @@ trait TL '/ $/', '/\?bytes /', '/{/', - '/}/' + '/}/', ], [ ':string ', '', @@ -106,10 +117,10 @@ trait TL '', '?string ', '', - ''], $line); + '', ], $line); $id = hash('crc32b', $clean); if (preg_match('/^[^\s]+#/', $line)) { - $nid = str_pad(preg_replace(['/^[^#]+#/', '/\s.+/'], '', $line), 8, "0", \STR_PAD_LEFT); + $nid = str_pad(preg_replace(['/^[^#]+#/', '/\s.+/'], '', $line), 8, '0', \STR_PAD_LEFT); if ($id !== $nid) { \danog\MadelineProto\Logger::log(['CRC32 mismatch ('.$id.', '.$nid.') for '.$line], \danog\MadelineProto\Logger::ERROR); } @@ -123,7 +134,9 @@ trait TL $TL_dict[$type][$key]['id'] = \danog\PHP\Struct::unpack('encrypted_layer; \danog\MadelineProto\Logger::log(['Translating objects...'], \danog\MadelineProto\Logger::ULTRA_VERBOSE); foreach ($TL_dict['constructors'] as $elem) { - if ($scheme_type === 'secret') $this->encrypted_layer = max($this->encrypted_layer, $elem['layer']); + if ($scheme_type === 'secret') { + $this->encrypted_layer = max($this->encrypted_layer, $elem['layer']); + } $this->{($scheme_type === 'td' ? 'td_' : '').'constructors'}->add($elem, $scheme_type); } \danog\MadelineProto\Logger::log(['Translating methods...'], \danog\MadelineProto\Logger::ULTRA_VERBOSE); foreach ($TL_dict['methods'] as $elem) { $this->{($scheme_type === 'td' ? 'td_' : '').'methods'}->add($elem); - if ($scheme_type === 'secret') $this->encrypted_layer = max($this->encrypted_layer, $elem['layer']); + if ($scheme_type === 'secret') { + $this->encrypted_layer = max($this->encrypted_layer, $elem['layer']); + } } if ($this->encrypted_layer != $orig && isset($this->secret_chats)) { - foreach ($this->secret_chats as $chat => $data) { $this->notify_layer($chat); } + foreach ($this->secret_chats as $chat => $data) { + $this->notify_layer($chat); + } } } if (isset($files['td']) && isset($files['telegram'])) { @@ -185,7 +204,6 @@ trait TL return array_unique(array_values($this->methods->method_namespace)); } - public function serialize_bool($bool) { return \danog\PHP\Struct::pack('constructors->find_by_predicate('bool'.($bool ? 'True' : 'False'))['id']); @@ -224,13 +242,19 @@ trait TL return \danog\PHP\Struct::pack('constructors->find_by_predicate('inputMessageEntityMentionName'); + if ($constructorData['predicate'] === 'messageEntityMentionName') { + $constructorData = $this->constructors->find_by_predicate('inputMessageEntityMentionName'); + } if (!$bare) { $concat .= \danog\PHP\Struct::pack('serialize_params($constructorData, $object); } @@ -310,10 +337,10 @@ trait TL if ($tl === false) { throw new Exception('Could not find method: '.$method); } + return \danog\PHP\Struct::pack('serialize_params($tl, $arguments); } - public function serialize_params($tl, $arguments) { $serialized = ''; @@ -348,7 +375,7 @@ trait TL continue; } if ($current_argument['name'] === 'random_bytes') { - $serialized .= $this->random(15+random_int(0, 10)); + $serialized .= $this->random(15 + random_int(0, 10)); continue; } if ($current_argument['name'] === 'data' && isset($arguments['message'])) { diff --git a/src/danog/MadelineProto/TL/TLConstructor.php b/src/danog/MadelineProto/TL/TLConstructor.php index 47cfefb1..d59ed39c 100644 --- a/src/danog/MadelineProto/TL/TLConstructor.php +++ b/src/danog/MadelineProto/TL/TLConstructor.php @@ -27,7 +27,9 @@ class TLConstructor extends TLParams $this->predicate[$this->key] = (string) ((($scheme_type === 'mtproto' && $json_dict['predicate'] === 'message') ? 'MT' : '').$json_dict['predicate']); $this->type[$this->key] = (($scheme_type === 'mtproto' && $json_dict['type'] === 'Message') ? 'MT' : '').$json_dict['type']; $this->params[$this->key] = $json_dict['params']; - if ($scheme_type === 'secret') $this->layer[$this->key] = $json_dict['layer']; + if ($scheme_type === 'secret') { + $this->layer[$this->key] = $json_dict['layer']; + } $this->parse_params($this->key, $scheme_type === 'mtproto'); $this->key++; } @@ -50,10 +52,16 @@ class TLConstructor extends TLParams $key = 0; $keys = array_keys($this->predicate, $predicate); foreach ($keys as $k) { - if ($this->layer[$k] === $layer) $key = $k; + if ($this->layer[$k] === $layer) { + $key = $k; + } } - if ($key === 0) $key = array_search($predicate, $this->predicate); - } else $key = array_search($predicate, $this->predicate); + if ($key === 0) { + $key = array_search($predicate, $this->predicate); + } + } else { + $key = array_search($predicate, $this->predicate); + } return ($key === false) ? false : [ 'id' => $this->id[$key], diff --git a/src/danog/MadelineProto/TL/TLMethod.php b/src/danog/MadelineProto/TL/TLMethod.php index c06483c2..45f4fee2 100644 --- a/src/danog/MadelineProto/TL/TLMethod.php +++ b/src/danog/MadelineProto/TL/TLMethod.php @@ -47,9 +47,11 @@ class TLMethod extends TLParams 'params' => $this->params[$key], ]; } + public function find_by_id($id) { $key = array_search($id, $this->id); + return ($key === false) ? false : [ 'id' => $this->id[$key], 'method' => $this->method[$key], diff --git a/tests/testing.php b/tests/testing.php index ac3161ce..d2a69e8c 100755 --- a/tests/testing.php +++ b/tests/testing.php @@ -32,7 +32,6 @@ echo 'Loading settings...'.PHP_EOL; $settings = json_decode(getenv('MTPROTO_SETTINGS'), true) ?: []; if ($MadelineProto === false) { - echo 'Loading MadelineProto...'.PHP_EOL; $MadelineProto = new \danog\MadelineProto\API($settings); if (getenv('TRAVIS_COMMIT') == '') { @@ -88,7 +87,6 @@ $media['document_photo'] = ['_' => 'inputMediaUploadedDocument', 'file' => $inpu //$inputFile = $MadelineProto->upload_encrypted('tests/faust.jpg', 'fausticorn.jpg'); // This gets an inputFile object with file name magic //$secret_media['document_photo'] = ['peer' => $secret, 'file' => $inputFile, 'message' => ['ttl' => PHP_INT_MAX, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'mime_type' => mime_content_type('tests/faust.jpg'), 'caption' => 'This file was uploaded using MadelineProto', 'attributes' => [['_' => 'documentAttributeImageSize', 'w' => 1280, 'h' => 914]]]]]; - // Photo $media['photo'] = ['_' => 'inputMediaUploadedPhoto', 'file' => $inputFile, 'mime_type' => mime_content_type('tests/faust.jpg'), 'caption' => 'This photo was uploaded using MadelineProto'];