From 2720c50ca093e8116ae0ae64895d01286e65de84 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Thu, 31 Oct 2019 20:48:06 +0100 Subject: [PATCH] Refactoring and encapsulation --- .../MadelineProto/AnnotationsBuilder.php | 16 +- src/danog/MadelineProto/Connection.php | 4 +- src/danog/MadelineProto/DocsBuilder.php | 13 +- .../DocsBuilder/Constructors.php | 34 +-- .../MadelineProto/DocsBuilder/Methods.php | 6 +- src/danog/MadelineProto/EventHandler.php | 4 +- src/danog/MadelineProto/InternalDoc.php | 269 +++++++++++------- .../Loop/Connection/WriteLoop.php | 14 +- src/danog/MadelineProto/MTProto.php | 172 +++++++---- .../MTProtoTools/AuthKeyHandler.php | 10 +- src/danog/MadelineProto/RSA.php | 26 +- .../SecretChats/AuthKeyHandler.php | 133 +++++++-- .../SecretChats/MessageHandler.php | 4 +- .../MadelineProto/TL/Conversion/BotAPI.php | 2 +- .../TL/Conversion/BotAPIFiles.php | 4 +- src/danog/MadelineProto/TL/TL.php | 216 ++++++++++---- src/danog/MadelineProto/TL/TLConstructor.php | 9 +- src/danog/MadelineProto/Tools.php | 2 +- .../MadelineProto/Wrappers/DialogHandler.php | 8 +- src/danog/MadelineProto/Wrappers/Events.php | 20 +- src/danog/MadelineProto/Wrappers/Login.php | 4 +- src/danog/MadelineProto/Wrappers/TOS.php | 8 +- 22 files changed, 668 insertions(+), 310 deletions(-) diff --git a/src/danog/MadelineProto/AnnotationsBuilder.php b/src/danog/MadelineProto/AnnotationsBuilder.php index 36ec84a0..6315ea7e 100644 --- a/src/danog/MadelineProto/AnnotationsBuilder.php +++ b/src/danog/MadelineProto/AnnotationsBuilder.php @@ -20,17 +20,23 @@ namespace danog\MadelineProto; use Amp\Promise; +use danog\MadelineProto\TL\TL; use phpDocumentor\Reflection\DocBlockFactory; class AnnotationsBuilder { - use \danog\MadelineProto\TL\TL; use Tools; public function __construct($logger, $settings) { $this->logger = $logger; - $this->constructTL($settings['tl_schema']); + $this->TL = new TL(new class($logger) { + public function __construct($logger) + { + $this->logger = $logger; + } + }); + $this->TL->init($settings['tl_schema']); $this->settings = $settings; } @@ -62,7 +68,7 @@ class AnnotationsBuilder } } } - foreach ($this->getMethodNamespaces() as $namespace) { + foreach ($this->TL->getMethodNamespaces() as $namespace) { $content = \preg_replace('/(class( \\w+[,]?){0,}\\n{\\n)/', '${1}'." /**\n"." * @internal this is a internal property generated by build_docs.php, don't change manually\n"." *\n"." * @var {$namespace}\n"." */\n"." public \${$namespace};\n", $content); } \file_put_contents($filename, $content); @@ -87,12 +93,12 @@ class AnnotationsBuilder $handle = \fopen(\dirname(__FILE__).'/InternalDoc.php', 'w'); $internalDoc = []; - foreach ($this->methods->by_id as $id => $data) { + foreach ($this->TL->getMethods()->by_id as $id => $data) { if (!\strpos($data['method'], '.')) { continue; } list($namespace, $method) = \explode('.', $data['method']); - if (!\in_array($namespace, $this->getMethodNamespaces())) { + if (!\in_array($namespace, $this->TL->getMethodNamespaces())) { continue; } $internalDoc[$namespace][$method]['title'] = Lang::$current_lang["method_{$data['method']}"] ?? ''; diff --git a/src/danog/MadelineProto/Connection.php b/src/danog/MadelineProto/Connection.php index 2dc717a9..90786056 100644 --- a/src/danog/MadelineProto/Connection.php +++ b/src/danog/MadelineProto/Connection.php @@ -439,9 +439,9 @@ class Connection extends Session } if ($message['method']) { - $body = yield $this->API->serializeMethod($message['_'], $body); + $body = yield $this->API->getTL()->serializeMethod($message['_'], $body); } else { - $body = yield $this->API->serializeObject(['type' => $message['_']], $body, $message['_']); + $body = yield $this->API->getTL()->serializeObject(['type' => $message['_']], $body, $message['_']); } if ($refreshNext) { $this->API->referenceDatabase->refreshNext(false); diff --git a/src/danog/MadelineProto/DocsBuilder.php b/src/danog/MadelineProto/DocsBuilder.php index b9ffc3c4..3ca83703 100644 --- a/src/danog/MadelineProto/DocsBuilder.php +++ b/src/danog/MadelineProto/DocsBuilder.php @@ -19,10 +19,11 @@ namespace danog\MadelineProto; +use danog\MadelineProto\TL\TL; + // This code was written a few years ago: it is garbage, and has to be rewritten class DocsBuilder { - use \danog\MadelineProto\TL\TL; use \danog\MadelineProto\DocsBuilder\Methods; use \danog\MadelineProto\DocsBuilder\Constructors; use Tools; @@ -32,10 +33,14 @@ class DocsBuilder { $this->logger = $logger; \set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']); - $this->constructTL($settings['tl_schema']); + $this->TL = new TL(new class($logger) { + public function __construct($logger) + { + $this->logger = $logger; + } + }); + $this->TL->init($settings['tl_schema']); if (isset($settings['tl_schema']['td']) && !isset($settings['tl_schema']['telegram'])) { - $this->constructors = $this->td_constructors; - $this->methods = $this->td_methods; $this->td = true; } $this->settings = $settings; diff --git a/src/danog/MadelineProto/DocsBuilder/Constructors.php b/src/danog/MadelineProto/DocsBuilder/Constructors.php index 00933a6a..6d0e2f23 100644 --- a/src/danog/MadelineProto/DocsBuilder/Constructors.php +++ b/src/danog/MadelineProto/DocsBuilder/Constructors.php @@ -35,15 +35,15 @@ trait Constructors $this->docs_constructors = []; $this->logger->logger('Generating constructors documentation...', \danog\MadelineProto\Logger::NOTICE); $got = []; - foreach ($this->constructors->by_predicate_and_layer as $predicate => $id) { - $data = $this->constructors->by_id[$id]; + foreach ($this->TL->getConstructors($this->td)->by_predicate_and_layer as $predicate => $id) { + $data = $this->TL->getConstructors($this->td)->by_id[$id]; if (isset($got[$id])) { $data['layer'] = ''; } $got[$id] = ''; /* if (preg_match('/%/', $type)) { - $type = $this->constructors->findByType(str_replace('%', '', $type))['predicate']; + $type = $this->TL->getConstructors($this->td)->findByType(str_replace('%', '', $type))['predicate']; }*/ $layer = isset($data['layer']) && $data['layer'] !== '' ? '_'.$data['layer'] : ''; $type = \str_replace(['.', '<', '>'], ['_', '_of_', ''], $data['type']); @@ -69,7 +69,7 @@ trait Constructors $type_or_bare_type = \ctype_upper(Tools::end(\explode('.', $param[$type_or_subtype]))[0]) || \in_array($param[$type_or_subtype], ['!X', 'X', 'bytes', 'true', 'false', 'double', 'string', 'Bool', 'int53', 'int', 'long', 'int128', 'int256', 'int512']) ? 'types' : 'constructors'; $param[$type_or_subtype] = \str_replace(['.', 'true', 'false'], ['_', 'Bool', 'Bool'], $param[$type_or_subtype]); if (\preg_match('/%/', $param[$type_or_subtype])) { - $param[$type_or_subtype] = $this->constructors->findByType(\str_replace('%', '', $param[$type_or_subtype]))['predicate']; + $param[$type_or_subtype] = $this->TL->getConstructors($this->td)->findByType(\str_replace('%', '', $param[$type_or_subtype]))['predicate']; } if (\substr($param[$type_or_subtype], -1) === '>') { $param[$type_or_subtype] = \substr($param[$type_or_subtype], 0, -1); @@ -87,14 +87,14 @@ trait Constructors | Name | Type | Required | |----------|---------------|----------| '; - if (!isset($this->td_descriptions['constructors'][$data['predicate']])) { + if (!isset($this->TL->getDescriptions()['constructors'][$data['predicate']])) { $this->addToLang('object_'.$data['predicate']); if (\danog\MadelineProto\Lang::$lang['en']['object_'.$data['predicate']] !== '') { - $this->td_descriptions['constructors'][$data['predicate']]['description'] = \danog\MadelineProto\Lang::$lang['en']['object_'.$data['predicate']]; + $this->TL->getDescriptions()['constructors'][$data['predicate']]['description'] = \danog\MadelineProto\Lang::$lang['en']['object_'.$data['predicate']]; } } - if (isset($this->td_descriptions['constructors'][$data['predicate']]) && !empty($data['params'])) { + if (isset($this->TL->getDescriptions()['constructors'][$data['predicate']]) && !empty($data['params'])) { $table = '### Attributes: | Name | Type | Required | Description | @@ -126,7 +126,7 @@ trait Constructors } }*/ if (\preg_match('/%/', $ptype)) { - $ptype = $this->constructors->findByType(\str_replace('%', '', $ptype))['predicate']; + $ptype = $this->TL->getConstructors($this->td)->findByType(\str_replace('%', '', $ptype))['predicate']; } $type_or_bare_type = (\ctype_upper(Tools::end(\explode('_', $ptype))[0]) || \in_array($ptype, ['!X', 'X', 'bytes', 'true', 'false', 'double', 'string', 'Bool', 'int53', 'int', 'long', 'int128', 'int256', 'int512'])) && $ptype !== 'MTmessage' ? 'types' : 'constructors'; if (\substr($ptype, -1) === '>') { @@ -156,16 +156,16 @@ trait Constructors if (\in_array($ptype, ['InputEncryptedFile']) && !isset($this->settings['td'])) { $human_ptype = 'File path or '.$ptype; } - $table .= '|'.\str_replace('_', '\\_', $param['name']).'|'.(isset($param['subtype']) ? 'Array of ' : '').'['.\str_replace('_', '\\_', $human_ptype).'](../'.$type_or_bare_type.'/'.$ptype.'.md) | '.(isset($param['pow']) || $this->constructors->findByPredicate(\lcfirst($param['type']).'Empty') || ($data['type'] === 'InputMedia' && $param['name'] === 'mime_type') || ($data['type'] === 'DocumentAttribute' && \in_array($param['name'], ['w', 'h', 'duration'])) ? 'Optional' : 'Yes').'|'; + $table .= '|'.\str_replace('_', '\\_', $param['name']).'|'.(isset($param['subtype']) ? 'Array of ' : '').'['.\str_replace('_', '\\_', $human_ptype).'](../'.$type_or_bare_type.'/'.$ptype.'.md) | '.(isset($param['pow']) || $this->TL->getConstructors($this->td)->findByPredicate(\lcfirst($param['type']).'Empty') || ($data['type'] === 'InputMedia' && $param['name'] === 'mime_type') || ($data['type'] === 'DocumentAttribute' && \in_array($param['name'], ['w', 'h', 'duration'])) ? 'Optional' : 'Yes').'|'; - if (!isset($this->td_descriptions['constructors'][$data['predicate']]['params'][$param['name']])) { + if (!isset($this->TL->getDescriptions()['constructors'][$data['predicate']]['params'][$param['name']])) { $this->addToLang('object_'.$data['predicate'].'_param_'.$param['name'].'_type_'.$param['type']); - if (isset($this->td_descriptions['constructors'][$data['predicate']]['description'])) { - $this->td_descriptions['constructors'][$data['predicate']]['params'][$param['name']] = \danog\MadelineProto\Lang::$lang['en']['object_'.$data['predicate'].'_param_'.$param['name'].'_type_'.$param['type']]; + if (isset($this->TL->getDescriptions()['constructors'][$data['predicate']]['description'])) { + $this->TL->getDescriptions()['constructors'][$data['predicate']]['params'][$param['name']] = \danog\MadelineProto\Lang::$lang['en']['object_'.$data['predicate'].'_param_'.$param['name'].'_type_'.$param['type']]; } } - if (isset($this->td_descriptions['constructors'][$data['predicate']]['params'][$param['name']])) { - $table .= $this->td_descriptions['constructors'][$data['predicate']]['params'][$param['name']].'|'; + if (isset($this->TL->getDescriptions()['constructors'][$data['predicate']]['params'][$param['name']])) { + $table .= $this->TL->getDescriptions()['constructors'][$data['predicate']]['params'][$param['name']].'|'; } $table .= PHP_EOL; $pptype = \in_array($ptype, ['string', 'bytes']) ? "'".$ptype."'" : $ptype; @@ -183,7 +183,7 @@ trait Constructors $params = "['_' => '".$data['predicate']."'".$params.']'; $lua_params = "{_='".$data['predicate']."'".$lua_params.'}'; $pwr_params = '{"_": "'.$data['predicate'].'"'.$pwr_params.'}'; - $description = isset($this->td_descriptions['constructors'][$data['predicate']]) ? $this->td_descriptions['constructors'][$data['predicate']]['description'] : $constructor.' attributes, type and example'; + $description = isset($this->TL->getDescriptions()['constructors'][$data['predicate']]) ? $this->TL->getDescriptions()['constructors'][$data['predicate']]['description'] : $constructor.' attributes, type and example'; $header = '--- title: '.$data['predicate'].' description: '.$description.' @@ -199,8 +199,8 @@ image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png '; - if (isset($this->td_descriptions['constructors'][$data['predicate']])) { - $header .= $this->td_descriptions['constructors'][$data['predicate']]['description'].PHP_EOL.PHP_EOL; + if (isset($this->TL->getDescriptions()['constructors'][$data['predicate']])) { + $header .= $this->TL->getDescriptions()['constructors'][$data['predicate']]['description'].PHP_EOL.PHP_EOL; } $type = '### Type: ['.\str_replace('_', '\\_', $php_type).'](../types/'.$php_type.'.md) diff --git a/src/danog/MadelineProto/DocsBuilder/Methods.php b/src/danog/MadelineProto/DocsBuilder/Methods.php index 8de4af0f..953f2581 100644 --- a/src/danog/MadelineProto/DocsBuilder/Methods.php +++ b/src/danog/MadelineProto/DocsBuilder/Methods.php @@ -54,7 +54,7 @@ trait Methods $this->docs_methods = []; $this->human_docs_methods = []; $this->logger->logger('Generating methods documentation...', \danog\MadelineProto\Logger::NOTICE); - foreach ($this->methods->by_id as $id => $data) { + foreach ($this->TL->getMethods($this->td)->by_id as $id => $data) { $method = $data['method']; $php_method = \str_replace('.', '->', $data['method']); $type = \str_replace(['.', '<', '>'], ['_', '_of_', ''], $data['type']); @@ -170,9 +170,9 @@ trait Methods } if (isset($this->td_descriptions['methods'][$data['method']])) { - $table .= '|'.\str_replace('_', '\\_', $param['name']).'|'.(isset($param['subtype']) ? 'Array of ' : '').'['.\str_replace('_', '\\_', $human_ptype).'](../'.$type_or_bare_type.'/'.$ptype.'.md) | '.$this->td_descriptions['methods'][$data['method']]['params'][$param['name']].' | '.(isset($param['pow']) || (($id = $this->constructors->findByPredicate(\lcfirst($param['type']).'Empty')) && $id['type'] === $param['type']) || (($id = $this->constructors->findByPredicate('input'.$param['type'].'Empty')) && $id['type'] === $param['type']) ? 'Optional' : 'Yes').'|'; + $table .= '|'.\str_replace('_', '\\_', $param['name']).'|'.(isset($param['subtype']) ? 'Array of ' : '').'['.\str_replace('_', '\\_', $human_ptype).'](../'.$type_or_bare_type.'/'.$ptype.'.md) | '.$this->td_descriptions['methods'][$data['method']]['params'][$param['name']].' | '.(isset($param['pow']) || (($id = $this->TL->getConstructors($this->td)->findByPredicate(\lcfirst($param['type']).'Empty')) && $id['type'] === $param['type']) || (($id = $this->TL->getConstructors($this->td)->findByPredicate('input'.$param['type'].'Empty')) && $id['type'] === $param['type']) ? 'Optional' : 'Yes').'|'; } else { - $table .= '|'.\str_replace('_', '\\_', $param['name']).'|'.(isset($param['subtype']) ? 'Array of ' : '').'['.\str_replace('_', '\\_', $human_ptype).'](../'.$type_or_bare_type.'/'.$ptype.'.md) | '.(isset($param['pow']) || (($id = $this->constructors->findByPredicate(\lcfirst($param['type']).'Empty')) && $id['type'] === $param['type']) || (($id = $this->constructors->findByPredicate('input'.$param['type'].'Empty')) && $id['type'] === $param['type']) ? 'Optional' : 'Yes').'|'; + $table .= '|'.\str_replace('_', '\\_', $param['name']).'|'.(isset($param['subtype']) ? 'Array of ' : '').'['.\str_replace('_', '\\_', $human_ptype).'](../'.$type_or_bare_type.'/'.$ptype.'.md) | '.(isset($param['pow']) || (($id = $this->TL->getConstructors($this->td)->findByPredicate(\lcfirst($param['type']).'Empty')) && $id['type'] === $param['type']) || (($id = $this->TL->getConstructors($this->td)->findByPredicate('input'.$param['type'].'Empty')) && $id['type'] === $param['type']) ? 'Optional' : 'Yes').'|'; } $table .= PHP_EOL; $pptype = \in_array($ptype, ['string', 'bytes']) ? "'".$ptype."'" : $ptype; diff --git a/src/danog/MadelineProto/EventHandler.php b/src/danog/MadelineProto/EventHandler.php index 6303724d..a747c08c 100644 --- a/src/danog/MadelineProto/EventHandler.php +++ b/src/danog/MadelineProto/EventHandler.php @@ -20,12 +20,12 @@ namespace danog\MadelineProto; /** - * Event handler + * Event handler. */ class EventHandler extends InternalDoc { /** - * Constructor + * Constructor. * * @param API|null $MadelineProto MadelineProto instance */ diff --git a/src/danog/MadelineProto/InternalDoc.php b/src/danog/MadelineProto/InternalDoc.php index e60e275d..8e545502 100644 --- a/src/danog/MadelineProto/InternalDoc.php +++ b/src/danog/MadelineProto/InternalDoc.php @@ -4040,6 +4040,33 @@ class InternalDoc extends APIFactory { return $this->__call(__FUNCTION__, [$param, $level, $file, $extra]); } + /** + * Get TL namespaces. + * + * @return array + */ + public function getMethodNamespaces(array $extra = []): array + { + return $this->__call(__FUNCTION__, [$extra]); + } + /** + * Get namespaced methods (method => namespace). + * + * @return array + */ + public function getMethodsNamespaced(array $extra = []): array + { + return $this->__call(__FUNCTION__, [$extra]); + } + /** + * Get TL serializer. + * + * @return TL + */ + public function getTL(array $extra = []): danog\MadelineProto\TL\TL + { + return $this->__call(__FUNCTION__, [$extra]); + } /** * Get async HTTP client. * @@ -4078,11 +4105,6 @@ class InternalDoc extends APIFactory { return $this->__call(__FUNCTION__, [$extra]); } - - public function hasAllAuth(array $extra = []): bool - { - return $this->__call(__FUNCTION__, [$extra]); - } /** * Get correct settings array for the latest version. * @@ -4139,7 +4161,20 @@ class InternalDoc extends APIFactory { return $this->__call(__FUNCTION__, [$datacenter, $extra]); } - + /** + * Checks whether all datacenters are authorized. + * + * @return boolean + */ + public function hasAllAuth(array $extra = []): bool + { + return $this->__call(__FUNCTION__, [$extra]); + } + /** + * Whether we're initing authorization. + * + * @return boolean + */ public function isInitingAuthorization(array $extra = []) { return $this->__call(__FUNCTION__, [$extra]); @@ -4689,57 +4724,79 @@ class InternalDoc extends APIFactory { return $this->__call(__FUNCTION__, [$message_media, $callable, $cb, $parallelize, $offset, $end, $part_size, $extra]); } - + /** + * Accept secret chat. + * + * @param array $params Secret chat ID + * + * @return \Generator + */ public function acceptSecretChat($params, array $extra = []) { return $this->__call(__FUNCTION__, [$params, $extra]); } - + /** + * Request secret chat. + * + * @param mixed $user User to start secret chat with + * + * @return \Generator + */ public function requestSecretChat($user, array $extra = []) { return $this->__call(__FUNCTION__, [$user, $extra]); } - - public function completeSecretChat($params, array $extra = []) - { - return $this->__call(__FUNCTION__, [$params, $extra]); - } - - public function notifyLayer($chat, array $extra = []) - { - return $this->__call(__FUNCTION__, [$chat, $extra]); - } - + /** + * Rekey secret chat. + * + * @param mixed $chat Secret chat to rekey + * + * @return \Generator + */ public function rekey($chat, array $extra = []) { return $this->__call(__FUNCTION__, [$chat, $extra]); } - - public function acceptRekey($chat, $params, array $extra = []) - { - return $this->__call(__FUNCTION__, [$chat, $params, $extra]); - } - - public function commitRekey($chat, $params, array $extra = []) - { - return $this->__call(__FUNCTION__, [$chat, $params, $extra]); - } - - public function completeRekey($chat, $params, array $extra = []) - { - return $this->__call(__FUNCTION__, [$chat, $params, $extra]); - } - - public function secretChatStatus($chat, array $extra = []) + /** + * Get secret chat status. + * + * @param int $chat Chat ID + * + * @return int One of MTProto::SECRET_EMPTY, MTProto::SECRET_REQUESTED, MTProto::SECRET_READY + */ + public function secretChatStatus(int $chat, array $extra = []): int { return $this->__call(__FUNCTION__, [$chat, $extra]); } - - public function getSecretChat($chat, array $extra = []) + /** + * Get secret chat. + * + * @param array|int $chat Secret chat ID + * + * @return array + */ + public function getSecretChat($chat, array $extra = []): array { return $this->__call(__FUNCTION__, [$chat, $extra]); } - + /** + * Check whether secret chat exists. + * + * @param array|int $chat Secret chat ID + * + * @return boolean + */ + public function hasSecretChat($chat, array $extra = []): bool + { + return $this->__call(__FUNCTION__, [$chat, $extra]); + } + /** + * Discard secret chat. + * + * @param array|int $chat Secret chat ID + * + * @return \Generator + */ public function discardSecretChat($chat, array $extra = []) { return $this->__call(__FUNCTION__, [$chat, $extra]); @@ -4790,63 +4847,6 @@ class InternalDoc extends APIFactory return $this->__call(__FUNCTION__, [$chat, $extra]); } - public function constructTL($files, $objects = [ - ], array $extra = []) - { - return $this->__call(__FUNCTION__, [$files, $objects, $extra]); - } - - public function getMethodNamespaces(array $extra = []) - { - return $this->__call(__FUNCTION__, [$extra]); - } - - public function getMethodsNamespaced(array $extra = []) - { - return $this->__call(__FUNCTION__, [$extra]); - } - - public function updateCallbacks($objects, array $extra = []) - { - return $this->__call(__FUNCTION__, [$objects, $extra]); - } - - public function deserializeBool($id, array $extra = []) - { - return $this->__call(__FUNCTION__, [$id, $extra]); - } - - public function serializeObject($type, $object, $ctx, $layer = -1, array $extra = []) - { - return $this->__call(__FUNCTION__, [$type, $object, $ctx, $layer, $extra]); - } - - public function serializeMethod($method, $arguments, array $extra = []) - { - return $this->__call(__FUNCTION__, [$method, $arguments, $extra]); - } - - public function serializeParams($tl, $arguments, $ctx, $layer = -1, array $extra = []) - { - return $this->__call(__FUNCTION__, [$tl, $arguments, $ctx, $layer, $extra]); - } - - public function getLength($stream, $type = [ - 'type' => '', - ], array $extra = []) - { - return $this->__call(__FUNCTION__, [$stream, $type, $extra]); - } - /** - * :type stream: io.BytesIO object. - */ - public function deserialize($stream, $type = [ - 'type' => '', - ], array $extra = []) - { - return $this->__call(__FUNCTION__, [$stream, $type, $extra]); - } - public function htmlEntityDecode($stuff, array $extra = []) { return $this->__call(__FUNCTION__, [$stuff, $extra]); @@ -5442,6 +5442,19 @@ class InternalDoc extends APIFactory { return $this->__call(__FUNCTION__, [$extra]); } + /** + * Accesses a private variable from an object. + * + * @param object $obj Object + * @param string $var Attribute name + * + * @return mixed + * @access public + */ + public function getVar($obj, string $var, array $extra = []) + { + return $this->__call(__FUNCTION__, [$obj, $var, $extra]); + } public function requestCall($user, array $extra = []) { @@ -5483,28 +5496,58 @@ class InternalDoc extends APIFactory { return $this->__call(__FUNCTION__, [$extra]); } - + /** + * Get dialog peers. + * + * @param boolean $force Whether to refetch all dialogs ignoring cache + * + * @return \Generator> + */ public function getDialogs($force = true, array $extra = []) { return $this->__call(__FUNCTION__, [$force, $extra]); } - + /** + * Get full info of all dialogs. + * + * @param boolean $force Whether to refetch all dialogs ignoring cache + * + * @return \Generator + */ public function getFullDialogs($force = true, array $extra = []) { return $this->__call(__FUNCTION__, [$force, $extra]); } - + /** + * Set event handler. + * + * @param string|EventHandler $event_handler Event handler + * + * @return void + */ public function setEventHandler($event_handler, array $extra = []) { return $this->__call(__FUNCTION__, [$event_handler, $extra]); } - - public function getEventHandler(array $extra = []) + /** + * Get event handler. + * + * @return EventHandler + */ + public function getEventHandler(array $extra = []): EventHandler { return $this->__call(__FUNCTION__, [$extra]); } - - public function eventUpdateHandler($update, array $extra = []) + /** + * Event update handler. + * + * @param array $update Update + * + * @return void + * + * @internal Internal event handler + */ + public function eventUpdateHandler(array $update, array $extra = []) { return $this->__call(__FUNCTION__, [$update, $extra]); } @@ -5645,17 +5688,31 @@ class InternalDoc extends APIFactory { return $this->__call(__FUNCTION__, [$template, $extra]); } - + /** + * Check for terms of service update. + * + * @return \Generator + */ public function checkTos(array $extra = []) { return $this->__call(__FUNCTION__, [$extra]); } - + /** + * Accept terms of service update. + * + * @return \Generator + */ public function acceptTos(array $extra = []) { return $this->__call(__FUNCTION__, [$extra]); } - + /** + * Decline terms of service update. + * + * THIS WILL DELETE YOUR ACCOUNT! + * + * @return \Generator + */ public function declineTos(array $extra = []) { return $this->__call(__FUNCTION__, [$extra]); diff --git a/src/danog/MadelineProto/Loop/Connection/WriteLoop.php b/src/danog/MadelineProto/Loop/Connection/WriteLoop.php index c485d9a8..f36d573b 100644 --- a/src/danog/MadelineProto/Loop/Connection/WriteLoop.php +++ b/src/danog/MadelineProto/Loop/Connection/WriteLoop.php @@ -182,7 +182,7 @@ class WriteLoop extends ResumableSignalLoop $temporary_keys = []; if (\count($to_ack = $connection->ack_queue)) { foreach (\array_chunk($connection->ack_queue, 8192) as $acks) { - $connection->pending_outgoing[$connection->pending_outgoing_key] = ['_' => 'msgs_ack', 'serialized_body' => yield $this->API->serializeObject(['type' => 'msgs_ack'], ['msg_ids' => $acks], 'msgs_ack'), 'contentRelated' => false, 'unencrypted' => false, 'method' => false]; + $connection->pending_outgoing[$connection->pending_outgoing_key] = ['_' => 'msgs_ack', 'serialized_body' => yield $this->API->getTL()->serializeObject(['type' => 'msgs_ack'], ['msg_ids' => $acks], 'msgs_ack'), 'contentRelated' => false, 'unencrypted' => false, 'method' => false]; $temporary_keys[$connection->pending_outgoing_key] = true; $API->logger->logger("Adding msgs_ack {$connection->pending_outgoing_key}", Logger::ULTRA_VERBOSE); $connection->pending_outgoing_key++; @@ -200,7 +200,7 @@ class WriteLoop extends ResumableSignalLoop } if ($shared->isHttp() && !$has_http_wait) { $API->logger->logger("Adding http_wait {$connection->pending_outgoing_key}", Logger::ULTRA_VERBOSE); - $connection->pending_outgoing[$connection->pending_outgoing_key] = ['_' => 'http_wait', 'serialized_body' => yield $this->API->serializeObject(['type' => ''], ['_' => 'http_wait', 'max_wait' => 30000, 'wait_after' => 0, 'max_delay' => 0], 'http_wait'), 'contentRelated' => true, 'unencrypted' => false, 'method' => true]; + $connection->pending_outgoing[$connection->pending_outgoing_key] = ['_' => 'http_wait', 'serialized_body' => yield $this->API->getTL()->serializeObject(['type' => ''], ['_' => 'http_wait', 'max_wait' => 30000, 'wait_after' => 0, 'max_delay' => 0], 'http_wait'), 'contentRelated' => true, 'unencrypted' => false, 'method' => true]; $temporary_keys[$connection->pending_outgoing_key] = true; $connection->pending_outgoing_key++; } @@ -240,11 +240,11 @@ class WriteLoop extends ResumableSignalLoop if (!$shared->getTempAuthKey()->isInited() && $message['_'] !== 'auth.bindTempAuthKey' && !$inited) { $inited = true; $API->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['write_client_info'], $message['_']), \danog\MadelineProto\Logger::NOTICE); - $MTmessage['body'] = yield $API->serializeMethod( + $MTmessage['body'] = yield $API->getTL()->serializeMethod( 'invokeWithLayer', [ 'layer' => $API->settings['tl_schema']['layer'], - 'query' => yield $API->serializeMethod( + 'query' => yield $API->getTL()->serializeMethod( 'initConnection', [ 'api_id' => $API->settings['app_info']['api_id'], @@ -266,7 +266,7 @@ class WriteLoop extends ResumableSignalLoop if (!isset($connection->call_queue[$message['queue']])) { $connection->call_queue[$message['queue']] = []; } - $MTmessage['body'] = yield $API->serializeMethod('invokeAfterMsgs', ['msg_ids' => $connection->call_queue[$message['queue']], 'query' => $MTmessage['body']]); + $MTmessage['body'] = yield $API->getTL()->serializeMethod('invokeAfterMsgs', ['msg_ids' => $connection->call_queue[$message['queue']], 'query' => $MTmessage['body']]); $connection->call_queue[$message['queue']][$message_id] = $message_id; if (\count($connection->call_queue[$message['queue']]) > $API->settings['msg_array_limit']['call_queue']) { @@ -278,7 +278,7 @@ class WriteLoop extends ResumableSignalLoop // TODO /* if ($API->settings['requests']['gzip_encode_if_gt'] !== -1 && ($l = strlen($MTmessage['body'])) > $API->settings['requests']['gzip_encode_if_gt']) { if (($g = strlen($gzipped = gzencode($MTmessage['body']))) < $l) { - $MTmessage['body'] = yield $API->serializeObject(['type' => 'gzip_packed'], ['packed_data' => $gzipped], 'gzipped data'); + $MTmessage['body'] = yield $API->getTL()->serializeObject(['type' => 'gzip_packed'], ['packed_data' => $gzipped], 'gzipped data'); $API->logger->logger('Using GZIP compression for ' . $message['_'] . ', saved ' . ($l - $g) . ' bytes of data, reduced call size by ' . $g * 100 / $l . '%', \danog\MadelineProto\Logger::ULTRA_VERBOSE); } unset($gzipped); @@ -317,7 +317,7 @@ class WriteLoop extends ResumableSignalLoop //var_dumP("container ".bin2hex($message_id)); $keys[$connection->pending_outgoing_key++] = $message_id; - $message_data = yield $API->serializeObject(['type' => ''], ['_' => 'msg_container', 'messages' => $messages], 'container'); + $message_data = yield $API->getTL()->serializeObject(['type' => ''], ['_' => 'msg_container', 'messages' => $messages], 'container'); $message_data_length = \strlen($message_data); $seq_no = $connection->generateOutSeqNo(false); diff --git a/src/danog/MadelineProto/MTProto.php b/src/danog/MadelineProto/MTProto.php index 38fc01bb..34fd2897 100644 --- a/src/danog/MadelineProto/MTProto.php +++ b/src/danog/MadelineProto/MTProto.php @@ -31,6 +31,7 @@ use danog\MadelineProto\MTProtoTools\CombinedUpdatesState; use danog\MadelineProto\MTProtoTools\MinDatabase; use danog\MadelineProto\MTProtoTools\ReferenceDatabase; use danog\MadelineProto\MTProtoTools\UpdatesState; +use danog\MadelineProto\TL\TL; use danog\MadelineProto\TL\TLCallback; /** @@ -49,7 +50,6 @@ class MTProto extends AsyncConstruct implements TLCallback use \danog\MadelineProto\SecretChats\MessageHandler; use \danog\MadelineProto\SecretChats\ResponseHandler; use \danog\MadelineProto\SecretChats\SeqNoHandler; - use \danog\MadelineProto\TL\TL; use \danog\MadelineProto\TL\Conversion\BotAPI; use \danog\MadelineProto\TL\Conversion\BotAPIFiles; use \danog\MadelineProto\TL\Conversion\Extension; @@ -163,10 +163,24 @@ class MTProto extends AsyncConstruct implements TLCallback 64 => ' and content-related response to message already generated', 128 => ' and other party knows for a fact that message is already received' ]; - const REQUESTED = 0; - const ACCEPTED = 1; - const CONFIRMED = 2; - const READY = 3; + /** + * Secret chat was not found. + * + * @var int + */ + const SECRET_EMPTY = 0; + /** + * Secret chat was requested. + * + * @var int + */ + const SECRET_REQUESTED = 1; + /** + * Secret chat was found. + * + * @var int + */ + const SECRET_READY = 2; const TD_PARAMS_CONVERSION = ['updateNewMessage' => ['_' => 'updateNewMessage', 'disable_notification' => ['message', 'silent'], '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'], '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']], 'messages.sendMessage' => ['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']]]; const TD_REVERSE = ['sendMessage' => 'messages.sendMessage']; const TD_IGNORE = ['updateMessageID']; @@ -419,6 +433,13 @@ class MTProto extends AsyncConstruct implements TLCallback */ public $logger; + /** + * TL serializer. + * + * @var \danog\MadelineProto\TL\TL + */ + private $TL; + /** * Constructor function. * @@ -449,19 +470,17 @@ class MTProto extends AsyncConstruct implements TLCallback $this->logger->logger(Lang::$current_lang['load_rsa'], Logger::ULTRA_VERBOSE); $this->rsa_keys = []; foreach ($this->settings['authorization']['rsa_keys'] as $key) { - $key = yield (new RSA())->load($key); + $key = yield (new RSA())->load($this->TL, $key); $this->rsa_keys[$key->fp] = $key; } - /* - * *********************************************************************** - * Define some needed numbers for BigInteger - */ + // (re)-initialize TL $this->logger->logger(Lang::$current_lang['TL_translation'], Logger::ULTRA_VERBOSE); $callbacks = [$this, $this->referenceDatabase]; if (!($this->authorization['user']['bot'] ?? false)) { $callbacks []= $this->minDatabase; } - $this->constructTL($this->settings['tl_schema']['src'], $callbacks); + $this->TL->init($this->settings['tl_schema']['src'], $callbacks); + yield $this->connectToAllDcs(); $this->startLoops(); $this->datacenter->curdc = 2; @@ -495,72 +514,66 @@ class MTProto extends AsyncConstruct implements TLCallback } return [ // Databases - 'chats', - 'full_chats', - 'referenceDatabase', - 'minDatabase', - 'channel_participants', + 'chats', + 'full_chats', + 'referenceDatabase', + 'minDatabase', + 'channel_participants', // Misc caching - 'dialog_params', - 'last_stored', - 'qres', - 'supportUser', + 'dialog_params', + 'last_stored', + 'qres', + 'supportUser', 'tos', // Event handler - 'event_handler', - 'event_handler_instance', + 'event_handler', + 'event_handler_instance', 'loop_callback', - 'updates', - 'updates_key', + 'updates', + 'updates_key', 'hook_url', // Web login template - 'web_template', + 'web_template', // Settings - 'settings', - 'config', + 'settings', + 'config', // Authorization keys - 'datacenter', + 'datacenter', // Authorization state - 'authorization', - 'authorized', - 'authorized_dc', + 'authorization', + 'authorized', + 'authorized_dc', // Authorization cache - 'rsa_keys', - 'dh_config', + 'rsa_keys', + 'dh_config', // Update state - 'got_state', - 'channels_state', - 'msg_ids', + 'got_state', + 'channels_state', + 'msg_ids', // Version - 'v', + 'v', - // TL (we don't need this) - 'constructors', - 'td_constructors', - 'methods', - 'td_methods', - 'td_descriptions', - 'tl_callbacks', + // TL + 'TL', // Secret chats - 'secret_chats', - 'encrypted_layer', - 'temp_requested_secret_chats', - 'temp_rekeyed_secret_chats', + 'secret_chats', + 'temp_requested_secret_chats', + 'temp_rekeyed_secret_chats', // Object storage - 'storage', - ]; + 'storage', + ]; } @@ -576,7 +589,7 @@ class MTProto extends AsyncConstruct implements TLCallback if (!($this->authorization['user']['bot'] ?? false)) { $callbacks []= $this->minDatabase; } - $this->updateCallbacks($callbacks); + $this->TL->updateCallbacks($callbacks); return $this; } @@ -598,6 +611,37 @@ class MTProto extends AsyncConstruct implements TLCallback return isset($this->logger) ? $this->logger->logger($param, $level, $file) : Logger::$default->logger($param, $level, $file); } + /** + * Get TL namespaces. + * + * @return array + */ + public function getMethodNamespaces(): array + { + return $this->TL->getMethodNamespaces(); + } + + + /** + * Get namespaced methods (method => namespace). + * + * @return array + */ + public function getMethodsNamespaced(): array + { + return $this->TL->getMethodsNamespaced(); + } + + /** + * Get TL serializer. + * + * @return TL + */ + public function getTL(): TL + { + return $this->TL; + } + /** * Get async HTTP client. * @@ -736,9 +780,18 @@ class MTProto extends AsyncConstruct implements TLCallback if (!isset($this->minDatabase)) { $this->minDatabase = new MinDatabase($this); } + if (!isset($this->TL)) { + $this->TL = new TL($this); + $this->logger->logger(Lang::$current_lang['TL_translation'], Logger::ULTRA_VERBOSE); + $callbacks = [$this, $this->referenceDatabase]; + if (!($this->authorization['user']['bot'] ?? false)) { + $callbacks []= $this->minDatabase; + } + $this->TL->init($this->settings['tl_schema']['src'], $callbacks); + } } /** - * Upgrade MadelineProto instance + * Upgrade MadelineProto instance. * * @return \Generator */ @@ -863,7 +916,7 @@ class MTProto extends AsyncConstruct implements TLCallback if (!($this->authorization['user']['bot'] ?? false)) { $callbacks []= $this->minDatabase; } - $this->updateCallbacks($callbacks); + $this->TL->updateCallbacks($callbacks); $this->settings['connection_settings']['all']['ipv6'] = Magic::$ipv6; if ($this->authorized === true) { @@ -1350,6 +1403,11 @@ class MTProto extends AsyncConstruct implements TLCallback return $this->datacenter->isHttp($datacenter); } + /** + * Checks whether all datacenters are authorized. + * + * @return boolean + */ public function hasAllAuth(): bool { if ($this->isInitingAuthorization()) { @@ -1365,6 +1423,11 @@ class MTProto extends AsyncConstruct implements TLCallback return true; } + /** + * Whether we're initing authorization. + * + * @return boolean + */ public function isInitingAuthorization() { return $this->initing_authorization; @@ -1563,8 +1626,7 @@ class MTProto extends AsyncConstruct implements TLCallback { try { foreach ((yield $this->methodCallAsyncRead('help.getCdnConfig', [], ['datacenter' => $datacenter]))['public_keys'] as $curkey) { - $tempkey = new \danog\MadelineProto\RSA($curkey['public_key']); - $this->cdn_rsa_keys[$tempkey->fp] = $tempkey; + $this->cdn_rsa_keys[$tempkey->fp] = yield (new RSA)->load($this->TL, $curkey['public_key']); } } catch (\danog\MadelineProto\TL\Exception $e) { $this->logger->logger($e->getMessage(), \danog\MadelineProto\Logger::FATAL_ERROR); diff --git a/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php b/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php index 89c96305..db5352bb 100644 --- a/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php @@ -186,7 +186,7 @@ trait AuthKeyHandler $q_bytes = $q->toBytes(); $new_nonce = \danog\MadelineProto\Tools::random(32); $data_unserialized = ['pq' => $pq_bytes, 'p' => $p_bytes, 'q' => $q_bytes, 'nonce' => $nonce, 'server_nonce' => $server_nonce, 'new_nonce' => $new_nonce, 'expires_in' => $expires_in, 'dc' => \preg_replace('|_.*|', '', $datacenter)]; - $p_q_inner_data = yield $this->serializeObject(['type' => 'p_q_inner_data'.($expires_in < 0 ? '' : '_temp')], $data_unserialized, 'p_q_inner_data'); + $p_q_inner_data = yield $this->TL->serializeObject(['type' => 'p_q_inner_data'.($expires_in < 0 ? '' : '_temp')], $data_unserialized, 'p_q_inner_data'); /* * *********************************************************************** * Encrypt serialized object @@ -265,12 +265,12 @@ trait AuthKeyHandler * int $server_time * ] */ - $server_DH_inner_data = $this->deserialize($answer, ['type' => '']); + $server_DH_inner_data = $this->TL->deserialize($answer, ['type' => '']); /* * *********************************************************************** * Do some checks */ - $server_DH_inner_data_length = $this->getLength($answer); + $server_DH_inner_data_length = $this->TL->getLength($answer); if (\sha1(\substr($answer, 0, $server_DH_inner_data_length), true) != $answer_hash) { throw new \danog\MadelineProto\SecurityException('answer_hash mismatch.'); } @@ -320,7 +320,7 @@ trait AuthKeyHandler * string $g_b : g^b mod dh_prime * ] */ - $data = yield $this->serializeObject(['type' => 'client_DH_inner_data'], ['nonce' => $nonce, 'server_nonce' => $server_nonce, 'retry_id' => $retry_id, 'g_b' => $g_b_str], 'client_DH_inner_data'); + $data = yield $this->TL->serializeObject(['type' => 'client_DH_inner_data'], ['nonce' => $nonce, 'server_nonce' => $server_nonce, 'retry_id' => $retry_id, 'g_b' => $g_b_str], 'client_DH_inner_data'); /* * *********************************************************************** * encrypt client_DH_inner_data @@ -550,7 +550,7 @@ trait AuthKeyHandler $temp_auth_key_id = $datacenterConnection->getTempAuthKey()->getID(); $perm_auth_key_id = $datacenterConnection->getPermAuthKey()->getID(); $temp_session_id = $connection->session_id; - $message_data = yield $this->serializeObject(['type' => 'bind_auth_key_inner'], ['nonce' => $nonce, 'temp_auth_key_id' => $temp_auth_key_id, 'perm_auth_key_id' => $perm_auth_key_id, 'temp_session_id' => $temp_session_id, 'expires_at' => $expires_at], 'bindTempAuthKey_inner'); + $message_data = yield $this->TL->serializeObject(['type' => 'bind_auth_key_inner'], ['nonce' => $nonce, 'temp_auth_key_id' => $temp_auth_key_id, 'perm_auth_key_id' => $perm_auth_key_id, 'temp_session_id' => $temp_session_id, 'expires_at' => $expires_at], 'bindTempAuthKey_inner'); $message_id = $connection->generateMessageId(); $seq_no = 0; $encrypted_data = \danog\MadelineProto\Tools::random(16).$message_id.\pack('VV', $seq_no, \strlen($message_data)).$message_data; diff --git a/src/danog/MadelineProto/RSA.php b/src/danog/MadelineProto/RSA.php index 321f70de..328b1c08 100644 --- a/src/danog/MadelineProto/RSA.php +++ b/src/danog/MadelineProto/RSA.php @@ -18,41 +18,43 @@ namespace danog\MadelineProto; +use danog\MadelineProto\TL\TL; + /** - * RSA class + * RSA class. */ class RSA { - use \danog\MadelineProto\TL\TL; use \danog\MadelineProto\Tools; use \danog\Serializable; /** - * Exponent + * Exponent. * * @var \phpseclib\Math\BigInteger */ public $e; /** - * Modulus + * Modulus. * * @var \phpseclib\Math\BigInteger */ public $n; /** - * Fingerprint + * Fingerprint. * * @var string */ public $fp; /** - * Load RSA key + * Load RSA key. * + * @param TL $TL TL serializer * @param string $rsa_key RSA key - * + * * @return \Generator */ - public function load(string $rsa_key): \Generator + public function load(TL $TL, string $rsa_key): \Generator { \danog\MadelineProto\Logger::log(\danog\MadelineProto\Lang::$current_lang['rsa_init'], Logger::ULTRA_VERBOSE); \danog\MadelineProto\Logger::log(\danog\MadelineProto\Lang::$current_lang['loading_key'], Logger::ULTRA_VERBOSE); @@ -60,13 +62,13 @@ class RSA $this->n = Tools::getVar($key, 'modulus'); $this->e = Tools::getVar($key, 'exponent'); \danog\MadelineProto\Logger::log(\danog\MadelineProto\Lang::$current_lang['computing_fingerprint'], Logger::ULTRA_VERBOSE); - $this->fp = \substr(\sha1((yield $this->serializeObject(['type' => 'bytes'], $this->n->toBytes(), 'key')).(yield $this->serializeObject(['type' => 'bytes'], $this->e->toBytes(), 'key')), true), -8); + $this->fp = \substr(\sha1((yield $TL->serializeObject(['type' => 'bytes'], $this->n->toBytes(), 'key')).(yield $TL->serializeObject(['type' => 'bytes'], $this->e->toBytes(), 'key')), true), -8); return $this; } /** - * Sleep function + * Sleep function. * * @return array */ @@ -76,10 +78,10 @@ class RSA } /** - * Encrypt data + * Encrypt data. * * @param string $data Data to encrypt - * + * * @return string */ public function encrypt($data): string diff --git a/src/danog/MadelineProto/SecretChats/AuthKeyHandler.php b/src/danog/MadelineProto/SecretChats/AuthKeyHandler.php index 3e879d7d..3d4754f6 100644 --- a/src/danog/MadelineProto/SecretChats/AuthKeyHandler.php +++ b/src/danog/MadelineProto/SecretChats/AuthKeyHandler.php @@ -19,6 +19,8 @@ namespace danog\MadelineProto\SecretChats; +use danog\MadelineProto\MTProto; + /** * Manages secret chats. * @@ -26,10 +28,27 @@ namespace danog\MadelineProto\SecretChats; */ trait AuthKeyHandler { + /** + * Temporary requested secret chats. + * + * @var array + */ protected $temp_requested_secret_chats = []; + /** + * Secret chats. + * + * @var array + */ protected $secret_chats = []; - public function acceptSecretChat($params) + /** + * Accept secret chat. + * + * @param array $params Secret chat ID + * + * @return \Generator + */ + public function acceptSecretChat($params): \Generator { //$this->logger->logger($params['id'],$this->secretChatStatus($params['id'])); if ($this->secretChatStatus($params['id']) !== 0) { @@ -56,7 +75,14 @@ trait AuthKeyHandler $this->logger->logger('Secret chat '.$params['id'].' accepted successfully!', \danog\MadelineProto\Logger::NOTICE); } - public function requestSecretChat($user) + /** + * Request secret chat. + * + * @param mixed $user User to start secret chat with + * + * @return \Generator + */ + public function requestSecretChat($user): \Generator { $user = yield $this->getInfo($user); if (!isset($user['InputUser'])) { @@ -78,7 +104,14 @@ trait AuthKeyHandler return $res['id']; } - public function completeSecretChat($params) + /** + * Complete secret chat. + * + * @param array $params Secret chat + * + * @return \Generator + */ + private function completeSecretChat($params): \Generator { if ($this->secretChatStatus($params['id']) !== 1) { //$this->logger->logger($this->secretChatStatus($params['id'])); @@ -105,14 +138,26 @@ trait AuthKeyHandler $this->logger->logger('Secret chat '.$params['id'].' completed successfully!', \danog\MadelineProto\Logger::NOTICE); } - public function notifyLayer($chat) + private function notifyLayer($chat): \Generator { - yield $this->methodCallAsyncRead('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionNotifyLayer', 'layer' => $this->encrypted_layer]]], ['datacenter' => $this->datacenter->curdc]); + yield $this->methodCallAsyncRead('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionNotifyLayer', 'layer' => $this->TL->getSecretLayer()]]], ['datacenter' => $this->datacenter->curdc]); } + /** + * Temporary rekeyed secret chats. + * + * @var array + */ protected $temp_rekeyed_secret_chats = []; - public function rekey($chat) + /** + * Rekey secret chat. + * + * @param mixed $chat Secret chat to rekey + * + * @return \Generator + */ + public function rekey($chat): \Generator { if ($this->secret_chats[$chat]['rekeying'][0] !== 0) { return; @@ -133,7 +178,15 @@ trait AuthKeyHandler return $e; } - public function acceptRekey($chat, $params) + /** + * Accept rekeying. + * + * @param mixed $chat Chat + * @param array $params Parameters + * + * @return \Generator + */ + private function acceptRekey($chat, array $params): \Generator { if ($this->secret_chats[$chat]['rekeying'][0] !== 0) { $my_exchange_id = new \phpseclib\Math\BigInteger($this->secret_chats[$chat]['rekeying'][1], -256); @@ -166,7 +219,15 @@ trait AuthKeyHandler $this->updaters[false]->resume(); } - public function commitRekey($chat, $params) + /** + * Commit rekeying of secret chat. + * + * @param mixed $chat Chat + * @param array $params Parameters + * + * @return \Generator + */ + private function commitRekey($chat, array $params): \Generator { if ($this->secret_chats[$chat]['rekeying'][0] !== 1 || !isset($this->temp_rekeyed_secret_chats[$params['exchange_id']])) { $this->secret_chats[$chat]['rekeying'] = [0]; @@ -196,7 +257,15 @@ trait AuthKeyHandler $this->updaters[false]->resume(); } - public function completeRekey($chat, $params) + /** + * Complete rekeying. + * + * @param mixed $chat Chat + * @param array $params Parameters + * + * @return \Generator + */ + private function completeRekey($chat, array $params): \Generator { if ($this->secret_chats[$chat]['rekeying'][0] !== 2 || !isset($this->temp_rekeyed_secret_chats['fingerprint'])) { return; @@ -219,27 +288,59 @@ trait AuthKeyHandler return true; } - public function secretChatStatus($chat) + /** + * Get secret chat status. + * + * @param int $chat Chat ID + * + * @return int One of MTProto::SECRET_EMPTY, MTProto::SECRET_REQUESTED, MTProto::SECRET_READY + */ + public function secretChatStatus(int $chat): int { if (isset($this->secret_chats[$chat])) { - return 2; + return MTProto::SECRET_READY; } if (isset($this->temp_requested_secret_chats[$chat])) { - return 1; + return MTProto::SECRET_REQUESTED; } - return 0; + return MTProto::SECRET_EMPTY; } - public function getSecretChat($chat) + /** + * Get secret chat. + * + * @param array|int $chat Secret chat ID + * + * @return array + */ + public function getSecretChat($chat): array { return $this->secret_chats[\is_array($chat) ? $chat['chat_id'] : $chat]; } - public function discardSecretChat($chat) + /** + * Check whether secret chat exists. + * + * @param array|int $chat Secret chat ID + * + * @return boolean + */ + public function hasSecretChat($chat): bool + { + return isset($this->secret_chats[\is_array($chat) ? $chat['chat_id'] : $chat]); + } + + /** + * Discard secret chat. + * + * @param array|int $chat Secret chat ID + * + * @return \Generator + */ + public function discardSecretChat($chat): \Generator { $this->logger->logger('Discarding secret chat '.$chat.'...', \danog\MadelineProto\Logger::VERBOSE); - //$this->logger->logger(debug_backtrace(0)[0]); if (isset($this->secret_chats[$chat])) { unset($this->secret_chats[$chat]); } diff --git a/src/danog/MadelineProto/SecretChats/MessageHandler.php b/src/danog/MadelineProto/SecretChats/MessageHandler.php index 7b2a19a4..8f377c09 100644 --- a/src/danog/MadelineProto/SecretChats/MessageHandler.php +++ b/src/danog/MadelineProto/SecretChats/MessageHandler.php @@ -41,7 +41,7 @@ trait MessageHandler $this->secret_chats[$chat_id]['out_seq_no']++; } $this->secret_chats[$chat_id]['outgoing'][$this->secret_chats[$chat_id]['out_seq_no']] = $message; - $message = yield $this->serializeObject(['type' => $constructor = $this->secret_chats[$chat_id]['layer'] === 8 ? 'DecryptedMessage' : 'DecryptedMessageLayer'], $message, $constructor, $this->secret_chats[$chat_id]['layer']); + $message = yield $this->TL->serializeObject(['type' => $constructor = $this->secret_chats[$chat_id]['layer'] === 8 ? 'DecryptedMessage' : 'DecryptedMessageLayer'], $message, $constructor, $this->secret_chats[$chat_id]['layer']); $message = \danog\MadelineProto\Tools::packUnsignedInt(\strlen($message)).$message; if ($this->secret_chats[$chat_id]['mtproto'] === 2) { $padding = \danog\MadelineProto\Tools::posmod(-\strlen($message), 16); @@ -111,7 +111,7 @@ trait MessageHandler $this->secret_chats[$message['message']['chat_id']]['mtproto'] = 2; } } - $deserialized = $this->deserialize($message_data, ['type' => '']); + $deserialized = $this->TL->deserialize($message_data, ['type' => '']); $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] === 0) { yield $this->rekey($message['message']['chat_id']); diff --git a/src/danog/MadelineProto/TL/Conversion/BotAPI.php b/src/danog/MadelineProto/TL/Conversion/BotAPI.php index 5e026d8a..e01256b6 100644 --- a/src/danog/MadelineProto/TL/Conversion/BotAPI.php +++ b/src/danog/MadelineProto/TL/Conversion/BotAPI.php @@ -374,7 +374,7 @@ trait BotAPI $data['document']['_'] = 'bot_'.$type_name; $res['file_size'] = $data['document']['size']; $res['mime_type'] = $data['document']['mime_type']; - $res['file_id'] = \danog\MadelineProto\Tools::base64urlEncode(\danog\MadelineProto\Tools::rleEncode((yield $this->serializeObject(['type' => 'File'], $data['document'], 'File')).\chr(2))); + $res['file_id'] = \danog\MadelineProto\Tools::base64urlEncode(\danog\MadelineProto\Tools::rleEncode((yield $this->TL->serializeObject(['type' => 'File'], $data['document'], 'File')).\chr(2))); return [$type_name => $res, 'caption' => isset($data['caption']) ? $data['caption'] : '']; default: diff --git a/src/danog/MadelineProto/TL/Conversion/BotAPIFiles.php b/src/danog/MadelineProto/TL/Conversion/BotAPIFiles.php index b9284245..176f62b7 100644 --- a/src/danog/MadelineProto/TL/Conversion/BotAPIFiles.php +++ b/src/danog/MadelineProto/TL/Conversion/BotAPIFiles.php @@ -29,7 +29,7 @@ trait BotAPIFiles $photoSize['location']['secret'] = $photo['location']['secret'] ?? 0; $photoSize['location']['dc_id'] = $photo['dc_id'] ?? 0; $photoSize['location']['_'] = $thumbnail ? 'bot_thumbnail' : 'bot_photo'; - $data = (yield $this->serializeObject(['type' => 'File'], $photoSize['location'], 'File')).\chr(2); + $data = (yield $this->TL->serializeObject(['type' => 'File'], $photoSize['location'], 'File')).\chr(2); return [ 'file_id' => \danog\MadelineProto\Tools::base64urlEncode(\danog\MadelineProto\Tools::rleEncode($data)), @@ -47,7 +47,7 @@ trait BotAPIFiles if ($file_id[\strlen($file_id) - 1] !== \chr(2)) { throw new Exception(\danog\MadelineProto\Lang::$current_lang['last_byte_invalid']); } - $deserialized = $this->deserialize($file_id); + $deserialized = $this->TL->deserialize($file_id); $res = ['type' => \str_replace('bot_', '', $deserialized['_'])]; switch ($deserialized['_']) { case 'bot_thumbnail': diff --git a/src/danog/MadelineProto/TL/TL.php b/src/danog/MadelineProto/TL/TL.php index 23ba8733..246e8a22 100644 --- a/src/danog/MadelineProto/TL/TL.php +++ b/src/danog/MadelineProto/TL/TL.php @@ -22,69 +22,123 @@ namespace danog\MadelineProto\TL; use danog\MadelineProto\MTProto; /** - * TL serialization + * TL serialization. */ class TL { /** - * Highest available secret chat layer version + * Highest available secret chat layer version. * * @var integer */ - public $encrypted_layer = -1; + private $encrypted_layer = -1; /** - * Constructors + * Constructors. * * @var TLConstructor */ - public $constructors; + private $constructors; /** - * Methods + * Methods. * - * @var TLMethods + * @var TLMethod */ - public $methods; + private $methods; /** - * TD Constructors + * TD Constructors. * * @var TLConstructors */ - public $td_constructors; + private $td_constructors; /** - * TD Methods + * TD Methods. * - * @var TLMethods + * @var TLMethod */ - public $td_methods; + private $td_methods; /** - * Descriptions + * Descriptions. * * @var array */ - public $td_descriptions; + private $td_descriptions; /** - * TL callbacks + * TL callbacks. * * @var array */ - public $tl_callbacks = []; + private $tl_callbacks = []; /** - * API instance + * API instance. * * @var \danog\MadelineProto\MTProto */ private $API; /** - * Constructor function + * Constructor function. * * @param MTProto $API API instance */ - public function __construct(MTProto $API) { + public function __construct($API = null) + { $this->API = $API; } - public function constructTL($files, $objects = []) + + /** + * Get secret chat layer version. + * + * @return integer + */ + public function getSecretLayer(): int { - $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['TL_loading'], \danog\MadelineProto\Logger::VERBOSE); + return $this->encrypted_layer; + } + + /** + * Get constructors. + * + * @param int $td Whether to get TD or normal methods + * + * @return TLConstructor + */ + public function getConstructors(bool $td = false): TLConstructor + { + return $td ? $this->td_constructors : $this->constructors; + } + + /** + * Get methods. + * + * @param int $td Whether to get TD or normal methods + * + * @return TLMethod + */ + public function getMethods(bool $td = false): TLMethod + { + return $td ? $this->td_methods : $this->methods; + } + + /** + * Get TL descriptions. + * + * @return array + */ + public function getDescriptions(): array + { + return $this->td_descriptions; + } + + /** + * Initialize TL parser. + * + * @param array $files Scheme files + * @param TLCallback[] $objects TL Callback objects + * + * @return void + */ + public function init(array $files, array $objects = []) + { + $this->API->logger->logger(\danog\MadelineProto\Lang::$current_lang['TL_loading'], \danog\MadelineProto\Logger::VERBOSE); $this->updateCallbacks($objects); $this->constructors = new TLConstructor(); $this->methods = new TLMethod(); @@ -92,7 +146,7 @@ class TL $this->td_methods = new TLMethod(); $this->td_descriptions = ['types' => [], 'constructors' => [], 'methods' => []]; foreach ($files as $scheme_type => $file) { - $this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['file_parsing'], \basename($file)), \danog\MadelineProto\Logger::VERBOSE); + $this->API->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['file_parsing'], \basename($file)), \danog\MadelineProto\Logger::VERBOSE); $filec = \file_get_contents(\danog\MadelineProto\Absolute::absolute($file)); $TL_dict = \json_decode($filec, true); if ($TL_dict === null) { @@ -165,7 +219,7 @@ class TL if (\preg_match('/^[^\s]+#([a-f0-9]*)/i', $line, $matches)) { $nid = \str_pad($matches[1], 8, '0', \STR_PAD_LEFT); if ($id !== $nid && $scheme_type !== 'botAPI') { - $this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['crc32_mismatch'], $id, $nid, $line), \danog\MadelineProto\Logger::ERROR); + $this->API->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['crc32_mismatch'], $id, $nid, $line), \danog\MadelineProto\Logger::ERROR); } $id = $nid; } @@ -210,15 +264,14 @@ class TL if (empty($TL_dict) || empty($TL_dict['constructors']) || !isset($TL_dict['methods'])) { throw new Exception(\danog\MadelineProto\Lang::$current_lang['src_file_invalid'].$file); } - $orig = $this->encrypted_layer; - $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['translating_obj'], \danog\MadelineProto\Logger::ULTRA_VERBOSE); + $this->API->logger->logger(\danog\MadelineProto\Lang::$current_lang['translating_obj'], \danog\MadelineProto\Logger::ULTRA_VERBOSE); foreach ($TL_dict['constructors'] as $elem) { if ($scheme_type === 'secret') { $this->encrypted_layer = \max($this->encrypted_layer, $elem['layer']); } $this->{($scheme_type === 'td' ? 'td_' : '').'constructors'}->add($elem, $scheme_type); } - $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['translating_methods'], \danog\MadelineProto\Logger::ULTRA_VERBOSE); + $this->API->logger->logger(\danog\MadelineProto\Lang::$current_lang['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') { @@ -253,7 +306,12 @@ class TL } } - public function getMethodNamespaces() + /** + * Get TL namespaces. + * + * @return array + */ + public function getMethodNamespaces(): array { $res = []; foreach ($this->methods->method_namespace as $pair) { @@ -264,16 +322,28 @@ class TL return $res; } - public function getMethodsNamespaced() + /** + * Get namespaced methods (method => namespace). + * + * @return array + */ + public function getMethodsNamespaced(): array { return $this->methods->method_namespace; } - public function updateCallbacks($objects) + /** + * Update TL callbacks. + * + * @param TLCallback[] $objects TL callbacks + * + * @return void + */ + public function updateCallbacks(array $objects) { $this->tl_callbacks = []; foreach ($objects as $object) { - if (!isset(\class_implements(\get_class($object))['danog\\MadelineProto\\TL\\TLCallback'])) { + if (!isset(\class_implements(\get_class($object))[TLCallback::class])) { throw new Exception('Invalid callback object provided!'); } $new = [ @@ -298,8 +368,14 @@ class TL } } } - - public function deserializeBool($id) + /** + * Deserialize bool. + * + * @param string $id Constructor ID + * + * @return bool + */ + private function deserializeBool(string $id): bool { $tl_elem = $this->constructors->findById($id); if ($tl_elem === false) { @@ -309,7 +385,17 @@ class TL return $tl_elem['predicate'] === 'boolTrue'; } - public function serializeObject($type, $object, $ctx, $layer = -1) + /** + * Serialize TL object. + * + * @param array $type TL type definition + * @param mixed $object Object to serialize + * @param string $ctx Context + * @param integer $layer Layer version + * + * @return \Generator + */ + public function serializeObject(array $type, $object, $ctx, int $layer = -1): \Generator { switch ($type['type']) { case 'int': @@ -464,7 +550,7 @@ class TL $predicate = $object['_']; $constructorData = $this->constructors->findByPredicate($predicate, $layer); if ($constructorData === false) { - $this->logger->logger($object, \danog\MadelineProto\Logger::FATAL_ERROR); + $this->API->logger->logger($object, \danog\MadelineProto\Logger::FATAL_ERROR); throw new Exception(\sprintf(\danog\MadelineProto\Lang::$current_lang['type_extract_error'], $predicate)); } @@ -486,7 +572,15 @@ class TL return $concat.yield $this->serializeParams($constructorData, $object, '', $layer); } - public function serializeMethod($method, $arguments) + /** + * Serialize method. + * + * @param string $method Method name + * @param mixed $arguments Arguments + * + * @return \Generator + */ + public function serializeMethod(string $method, $arguments): \Generator { if ($method === 'messages.importChatInvite' && isset($arguments['hash']) && \is_string($arguments['hash']) && \preg_match('@(?:t|telegram)\.(?:me|dog)/(joinchat/)?([a-z0-9_-]*)@i', $arguments['hash'], $matches)) { if ($matches[1] === '') { @@ -523,7 +617,7 @@ class TL ) && $this->settings['upload']['allow_automatic_upload'] ) { - $arguments['file'] = yield $this->uploadEncrypted($arguments['file']); + $arguments['file'] = yield $this->API->uploadEncrypted($arguments['file']); } if (isset($arguments['file']['key'])) { $arguments['message']['media']['key'] = $arguments['file']['key']; @@ -533,7 +627,7 @@ class TL } } } elseif (\in_array($method, ['messages.addChatUser', 'messages.deleteChatUser', 'messages.editChatAdmin', 'messages.editChatPhoto', 'messages.editChatTitle', 'messages.getFullChat', 'messages.exportChatInvite', 'messages.editChatAdmin', 'messages.migrateChat']) && isset($arguments['chat_id']) && (!\is_numeric($arguments['chat_id']) || $arguments['chat_id'] < 0)) { - $res = yield $this->getInfo($arguments['chat_id']); + $res = yield $this->API->getInfo($arguments['chat_id']); if ($res['type'] !== 'chat') { throw new \danog\MadelineProto\Exception('chat_id is not a chat id (only normal groups allowed, not supergroups)!'); } @@ -566,10 +660,20 @@ class TL return $tl['id'].yield $this->serializeParams($tl, $arguments, $method); } - public function serializeParams($tl, $arguments, $ctx, $layer = -1) + /** + * Serialize parameters. + * + * @param array $tl TL object definition + * @param arrayLike $arguments Arguments + * @param string $ctx Context + * @param integer $layer Layer + * + * @return \Generator + */ + private function serializeParams(array $tl, $arguments, $ctx, int $layer = -1): \Generator { $serialized = ''; - $arguments = yield $this->botAPIToMTProto($arguments); + $arguments = yield $this->API->botAPIToMTProto($arguments); $flags = 0; foreach ($tl['params'] as $cur_flag) { if (isset($cur_flag['pow'])) { @@ -595,7 +699,7 @@ class TL foreach ($tl['params'] as $current_argument) { if (!isset($arguments[$current_argument['name']])) { if (isset($current_argument['pow']) && (\in_array($current_argument['type'], ['true', 'false']) || ($flags & $current_argument['pow']) === 0)) { - //$this->logger->logger('Skipping '.$current_argument['name'].' of type '.$current_argument['type'); + //$this->API->logger->logger('Skipping '.$current_argument['name'].' of type '.$current_argument['type'); continue; } if ($current_argument['name'] === 'random_bytes') { @@ -603,7 +707,7 @@ class TL continue; } if ($current_argument['name'] === 'data' && isset($tl['method']) && \in_array($tl['method'], ['messages.sendEncrypted', 'messages.sendEncryptedFile', 'messages.sendEncryptedService']) && isset($arguments['message'])) { - $serialized .= yield $this->serializeObject($current_argument, yield $this->encryptSecretMessage($arguments['peer']['chat_id'], $arguments['message']), 'data'); + $serialized .= yield $this->serializeObject($current_argument, yield $this->API->encryptSecretMessage($arguments['peer']['chat_id'], $arguments['message']), 'data'); continue; } if ($current_argument['name'] === 'random_id') { @@ -691,27 +795,35 @@ class TL ) && $this->settings['upload']['allow_automatic_upload'] ) { - $arguments[$current_argument['name']] = yield $this->upload($arguments[$current_argument['name']]); + $arguments[$current_argument['name']] = yield $this->API->upload($arguments[$current_argument['name']]); } if ($current_argument['type'] === 'InputEncryptedChat' && (!\is_array($arguments[$current_argument['name']]) || isset($arguments[$current_argument['name']]['_']) && $this->constructors->findByPredicate($arguments[$current_argument['name']]['_'])['type'] !== $current_argument['type'])) { if (\is_array($arguments[$current_argument['name']])) { - $arguments[$current_argument['name']] = (yield $this->getInfo($arguments[$current_argument['name']]))['InputEncryptedChat']; + $arguments[$current_argument['name']] = (yield $this->API->getInfo($arguments[$current_argument['name']]))['InputEncryptedChat']; } else { - if (!isset($this->secret_chats[$arguments[$current_argument['name']]])) { + if (!$this->API->hasSecretChat($arguments[$current_argument['name']])) { throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['sec_peer_not_in_db']); } - $arguments[$current_argument['name']] = $this->secret_chats[$arguments[$current_argument['name']]]['InputEncryptedChat']; + $arguments[$current_argument['name']] = $this->API->getSecretChat($arguments[$current_argument['name']])['InputEncryptedChat']; } } - //$this->logger->logger('Serializing '.$current_argument['name'].' of type '.$current_argument['type'); + //$this->API->logger->logger('Serializing '.$current_argument['name'].' of type '.$current_argument['type'); $serialized .= yield $this->serializeObject($current_argument, $arguments[$current_argument['name']], $current_argument['name'], $layer); } return $serialized; } - public function getLength($stream, $type = ['type' => '']) + /** + * Get length of TL payload. + * + * @param resource $stream Stream + * @param array $type Type identifier + * + * @return int + */ + public function getLength($stream, $type = ['type' => '']): int { if (\is_string($stream)) { $res = \fopen('php://memory', 'rw+b'); @@ -726,8 +838,14 @@ class TL return \ftell($stream); } + /** - * :type stream: io.BytesIO object. + * Deserialize TL object. + * + * @param resource $stream Stream + * @param array $type Type identifier + * + * @return mixed */ public function deserialize($stream, $type = ['type' => '']) { diff --git a/src/danog/MadelineProto/TL/TLConstructor.php b/src/danog/MadelineProto/TL/TLConstructor.php index 43193fb0..c23af03d 100644 --- a/src/danog/MadelineProto/TL/TLConstructor.php +++ b/src/danog/MadelineProto/TL/TLConstructor.php @@ -96,7 +96,14 @@ class TLConstructor return false; } - public function findById($id) + /** + * Find constructor by ID. + * + * @param string $id Constructor ID + * + * @return array|false + */ + public function findById(string $id) { if (isset($this->by_id[$id])) { $constructor = $this->by_id[$id]; diff --git a/src/danog/MadelineProto/Tools.php b/src/danog/MadelineProto/Tools.php index 3e04af7e..bf6efb53 100644 --- a/src/danog/MadelineProto/Tools.php +++ b/src/danog/MadelineProto/Tools.php @@ -826,7 +826,7 @@ trait Tools * * @param object $obj Object * @param string $var Attribute name - * + * * @return mixed * @access public */ diff --git a/src/danog/MadelineProto/Wrappers/DialogHandler.php b/src/danog/MadelineProto/Wrappers/DialogHandler.php index 3feb741d..0b09a2d7 100644 --- a/src/danog/MadelineProto/Wrappers/DialogHandler.php +++ b/src/danog/MadelineProto/Wrappers/DialogHandler.php @@ -22,10 +22,10 @@ namespace danog\MadelineProto\Wrappers; trait DialogHandler { /** - * Get dialog peers + * Get dialog peers. * * @param boolean $force Whether to refetch all dialogs ignoring cache - * + * * @return \Generator> */ public function getDialogs($force = true): \Generator @@ -47,10 +47,10 @@ trait DialogHandler } /** - * Get full info of all dialogs + * Get full info of all dialogs. * * @param boolean $force Whether to refetch all dialogs ignoring cache - * + * * @return \Generator */ public function getFullDialogs($force = true): \Generator diff --git a/src/danog/MadelineProto/Wrappers/Events.php b/src/danog/MadelineProto/Wrappers/Events.php index 24cf24a8..a1be6941 100644 --- a/src/danog/MadelineProto/Wrappers/Events.php +++ b/src/danog/MadelineProto/Wrappers/Events.php @@ -22,34 +22,34 @@ namespace danog\MadelineProto\Wrappers; use EventHandler; /** - * Event handler + * Event handler. */ trait Events { /** - * Event handler class name + * Event handler class name. * * @var string */ public $event_handler; /** - * Event handler instance + * Event handler instance. * * @var \danog\MadelineProto\EventHandler */ private $event_handler_instance; /** - * Event handler method list + * Event handler method list. * * @var array */ private $event_handler_methods = []; /** - * Set event handler + * Set event handler. * * @param string|EventHandler $event_handler Event handler - * + * * @return void */ public function setEventHandler($event_handler) @@ -91,7 +91,7 @@ trait Events } /** - * Get event handler + * Get event handler. * * @return EventHandler */ @@ -101,12 +101,12 @@ trait Events } /** - * Event update handler + * Event update handler. * * @param array $update Update - * + * * @return void - * + * * @internal Internal event handler */ public function eventUpdateHandler(array $update) diff --git a/src/danog/MadelineProto/Wrappers/Login.php b/src/danog/MadelineProto/Wrappers/Login.php index 2655ab22..aec278e7 100644 --- a/src/danog/MadelineProto/Wrappers/Login.php +++ b/src/danog/MadelineProto/Wrappers/Login.php @@ -44,7 +44,7 @@ trait Login yield $this->logout(); } $callbacks = [$this, $this->referenceDatabase]; - $this->updateCallbacks($callbacks); + $this->TL->updateCallbacks($callbacks); $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_bot'], \danog\MadelineProto\Logger::NOTICE); $this->authorization = yield $this->methodCallAsyncRead('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]); @@ -159,7 +159,7 @@ trait Login if (!($this->authorization['user']['bot'] ?? false)) { $callbacks []= $this->minDatabase; } - $this->updateCallbacks($callbacks); + $this->TL->updateCallbacks($callbacks); $this->startUpdateSystem(); diff --git a/src/danog/MadelineProto/Wrappers/TOS.php b/src/danog/MadelineProto/Wrappers/TOS.php index 3d80a51d..2206f193 100644 --- a/src/danog/MadelineProto/Wrappers/TOS.php +++ b/src/danog/MadelineProto/Wrappers/TOS.php @@ -25,7 +25,7 @@ namespace danog\MadelineProto\Wrappers; trait TOS { /** - * Check for terms of service update + * Check for terms of service update. * * @return \Generator */ @@ -52,7 +52,7 @@ trait TOS } /** - * Accept terms of service update + * Accept terms of service update. * * @return \Generator */ @@ -67,8 +67,8 @@ trait TOS } /** - * Decline terms of service update - * + * Decline terms of service update. + * * THIS WILL DELETE YOUR ACCOUNT! * * @return \Generator