From 894470a14789fa97a038f92674f4b9571027207e Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sat, 28 Dec 2019 16:07:09 +0100 Subject: [PATCH] Refactor public API: full encapsulation and strict typing --- .../MadelineProto/AnnotationsBuilder.php | 24 +- src/danog/MadelineProto/DocsBuilder.php | 1 - src/danog/MadelineProto/InternalDoc.php | 793 +++++++----------- src/danog/MadelineProto/Logger.php | 7 +- src/danog/MadelineProto/MTProto.php | 75 +- .../MadelineProto/MTProtoTools/Files.php | 40 +- .../MTProtoTools/PeerHandler.php | 92 +- .../MTProtoTools/UpdateHandler.php | 128 ++- .../SecretChats/MessageHandler.php | 18 +- .../SecretChats/ResponseHandler.php | 2 +- .../SecretChats/SeqNoHandler.php | 8 +- .../MadelineProto/TL/Conversion/BotAPI.php | 67 +- .../TL/Conversion/BotAPIFiles.php | 11 +- .../MadelineProto/TL/Conversion/Extension.php | 53 +- src/danog/MadelineProto/TL/Conversion/TD.php | 44 +- src/danog/MadelineProto/TL/TLCallback.php | 12 +- src/danog/MadelineProto/Tools.php | 8 +- .../MadelineProto/VoIP/AuthKeyHandler.php | 107 ++- src/danog/MadelineProto/Wrappers/ApiStart.php | 6 +- .../MadelineProto/Wrappers/ApiTemplates.php | 18 +- src/danog/MadelineProto/Wrappers/Events.php | 2 +- src/danog/MadelineProto/Wrappers/Login.php | 76 +- src/danog/MadelineProto/Wrappers/Start.php | 10 +- .../MadelineProto/Wrappers/Templates.php | 4 +- tests/testing.php | 333 ++++---- 25 files changed, 1157 insertions(+), 782 deletions(-) diff --git a/src/danog/MadelineProto/AnnotationsBuilder.php b/src/danog/MadelineProto/AnnotationsBuilder.php index c49344a8..f2f143e5 100644 --- a/src/danog/MadelineProto/AnnotationsBuilder.php +++ b/src/danog/MadelineProto/AnnotationsBuilder.php @@ -21,6 +21,7 @@ namespace danog\MadelineProto; use Amp\Promise; use danog\MadelineProto\TL\TL; +use danog\MadelineProto\TL\TLCallback; use phpDocumentor\Reflection\DocBlockFactory; class AnnotationsBuilder @@ -78,9 +79,11 @@ class AnnotationsBuilder } /** - * Create file InternalDoc with all interfaces. + * Create internalDoc. + * + * @return void */ - private function createInternalClasses() + private function createInternalClasses(): void { \danog\MadelineProto\Logger::log('Creating internal classes...', \danog\MadelineProto\Logger::NOTICE); $handle = \fopen($this->output, 'w'); @@ -92,6 +95,13 @@ class AnnotationsBuilder foreach ($methods as $method) { $ignoreMethods[$method->getName()] = $method->getName(); } + + $class = new \ReflectionClass(TLCallback::class); + $methods = $class->getMethods(\ReflectionMethod::IS_STATIC | \ReflectionMethod::IS_PUBLIC); + foreach ($methods as $method) { + $ignoreMethods[$method->getName()] = $method->getName(); + } + \fclose($handle); $handle = \fopen($this->output, 'w'); @@ -169,6 +179,9 @@ class AnnotationsBuilder if (isset($ignoreMethods[$name])) { continue; } + if (\strpos($method->getDocComment() ?? '', '@internal') !== false) { + continue; + } if ($name == 'methodCallAsyncRead') { $name = 'methodCall'; @@ -249,6 +262,13 @@ class AnnotationsBuilder $doc .= " $ret \$this->__call(__FUNCTION__, $paramList);\n"; $doc .= "}\n"; + if (!$method->getDocComment()) { + Logger::log("$name has no PHPDOC!", Logger::FATAL_ERROR); + } + if (!$type) { + Logger::log("$name has no return type!", Logger::FATAL_ERROR); + } + $internalDoc['InternalDoc'][$name]['method'] = $method->getDocComment() ?? ''; $internalDoc['InternalDoc'][$name]['method'] .= "\n ".\implode("\n ", \explode("\n", $doc)); } diff --git a/src/danog/MadelineProto/DocsBuilder.php b/src/danog/MadelineProto/DocsBuilder.php index ee965aff..69d402a3 100644 --- a/src/danog/MadelineProto/DocsBuilder.php +++ b/src/danog/MadelineProto/DocsBuilder.php @@ -635,7 +635,6 @@ class Lang public static function addToLang(string $key, string $value = '', bool $force = false) { if (!isset(\danog\MadelineProto\Lang::$lang['en'][$key]) || $force) { - \var_dump("Adding $key"); \danog\MadelineProto\Lang::$lang['en'][$key] = $value; \file_put_contents(__DIR__.'/Lang.php', \sprintf(self::$template, \var_export(\danog\MadelineProto\Lang::$lang, true), \var_export(\danog\MadelineProto\Lang::$lang['en'], true))); } diff --git a/src/danog/MadelineProto/InternalDoc.php b/src/danog/MadelineProto/InternalDoc.php index c3dc0e1b..3c7c0fba 100644 --- a/src/danog/MadelineProto/InternalDoc.php +++ b/src/danog/MadelineProto/InternalDoc.php @@ -4027,9 +4027,9 @@ class InternalDoc extends APIFactory /** * Cleanup memory and session file. * - * @return void + * @return self */ - public function cleanup(array $extra = []) + public function cleanup(array $extra = []): self { return $this->__call(__FUNCTION__, [$extra]); } @@ -4042,9 +4042,9 @@ class InternalDoc extends APIFactory * * @return void */ - public function logger($param, int $level = \danog\MadelineProto\Logger::NOTICE, string $file = '', array $extra = []) + public function logger($param, int $level = \danog\MadelineProto\Logger::NOTICE, string $file = '', array $extra = []): void { - return $this->__call(__FUNCTION__, [$param, $level, $file, $extra]); + $this->__call(__FUNCTION__, [$param, $level, $file, $extra]); } /** * Get TL namespaces. @@ -4133,37 +4133,14 @@ class InternalDoc extends APIFactory { return $this->__call(__FUNCTION__, [$settings, $previousSettings, $extra]); } - /** - * Parse and store settings. - * - * @param array $settings Settings - * - * @return void - */ - public function parseSettings(array $settings, array $extra = []) - { - return $this->__call(__FUNCTION__, [$settings, $extra]); - } /** * Setup logger. * * @return void */ - public function setupLogger(array $extra = []) + public function setupLogger(array $extra = []): void { - return $this->__call(__FUNCTION__, [$extra]); - } - /** - * Reset all MTProto sessions. - * - * @param boolean $de Whether to reset the session ID - * @param boolean $auth_key Whether to reset the auth key - * - * @return void - */ - public function resetMTProtoSession(bool $de = true, bool $auth_key = false, array $extra = []) - { - return $this->__call(__FUNCTION__, [$de, $auth_key, $extra]); + $this->__call(__FUNCTION__, [$extra]); } /** * Check if connected to datacenter using HTTP. @@ -4185,15 +4162,6 @@ class InternalDoc extends APIFactory { return $this->__call(__FUNCTION__, [$extra]); } - /** - * Whether we're initing authorization. - * - * @return boolean - */ - public function isInitingAuthorization(array $extra = []) - { - return $this->__call(__FUNCTION__, [$extra]); - } /** * Connects to all datacenters and if necessary creates authorization keys, binds them and writes client info. * @@ -4210,40 +4178,18 @@ class InternalDoc extends APIFactory * * @return void */ - public function resetSession(array $extra = []) + public function resetSession(array $extra = []): void { - return $this->__call(__FUNCTION__, [$extra]); + $this->__call(__FUNCTION__, [$extra]); } /** * Reset the update state and fetch all updates from the beginning. * * @return void */ - public function resetUpdateState(array $extra = []) + public function resetUpdateState(array $extra = []): void { - return $this->__call(__FUNCTION__, [$extra]); - } - /** - * Start the update system. - * - * @param boolean $anyway Force start update system? - * - * @return void - */ - public function startUpdateSystem($anyway = false, array $extra = []) - { - return $this->__call(__FUNCTION__, [$anyway, $extra]); - } - /** - * Store shared phone config. - * - * @param mixed $watcherId Watcher ID - * - * @return void - */ - public function getPhoneConfig($watcherId = null, array $extra = []) - { - return $this->__call(__FUNCTION__, [$watcherId, $extra]); + $this->__call(__FUNCTION__, [$extra]); } /** * Store RSA keys for CDN datacenters. @@ -4288,36 +4234,6 @@ class InternalDoc extends APIFactory { return $this->__call(__FUNCTION__, [$extra]); } - - public function getMethodCallbacks(array $extra = []): array - { - return $this->__call(__FUNCTION__, [$extra]); - } - - public function getMethodBeforeCallbacks(array $extra = []): array - { - return $this->__call(__FUNCTION__, [$extra]); - } - - public function getConstructorCallbacks(array $extra = []): array - { - return $this->__call(__FUNCTION__, [$extra]); - } - - public function getConstructorBeforeCallbacks(array $extra = []): array - { - return $this->__call(__FUNCTION__, [$extra]); - } - - public function getConstructorSerializeCallbacks(array $extra = []): array - { - return $this->__call(__FUNCTION__, [$extra]); - } - - public function getTypeMismatchCallbacks(array $extra = []): array - { - return $this->__call(__FUNCTION__, [$extra]); - } /** * Create authorization key. * @@ -4535,7 +4451,7 @@ class InternalDoc extends APIFactory * * @return int */ - public function fromSupergroup($id, array $extra = []) + public function fromSupergroup($id, array $extra = []): int { return $this->__call(__FUNCTION__, [$id, $extra]); } @@ -4550,25 +4466,16 @@ class InternalDoc extends APIFactory { return $this->__call(__FUNCTION__, [$id, $extra]); } - - public function addSupport($support, array $extra = []) + /** + * Add user info. + * + * @param array $user User info + * + * @return void + */ + public function addUser(array $user, array $extra = []): void { - return $this->__call(__FUNCTION__, [$support, $extra]); - } - - public function addUser($user, array $extra = []) - { - return $this->__call(__FUNCTION__, [$user, $extra]); - } - - public function addChat($chat, array $extra = []) - { - return $this->__call(__FUNCTION__, [$chat, $extra]); - } - - public function cachePwrChat($id, $full_fetch, $send, array $extra = []) - { - return $this->__call(__FUNCTION__, [$id, $full_fetch, $send, $extra]); + $this->__call(__FUNCTION__, [$user, $extra]); } /** * Check if peer is present in internal peer database. @@ -4581,16 +4488,6 @@ class InternalDoc extends APIFactory { return $this->__call(__FUNCTION__, [$id, $extra]); } - - public function entitiesPeerIsset($entities, array $extra = []) - { - return $this->__call(__FUNCTION__, [$entities, $extra]); - } - - public function fwdPeerIsset($fwd, array $extra = []) - { - return $this->__call(__FUNCTION__, [$fwd, $extra]); - } /** * Get folder ID from object. * @@ -4598,7 +4495,7 @@ class InternalDoc extends APIFactory * * @return ?int */ - public function getFolderId($id, array $extra = []) + public function getFolderId($id, array $extra = []): ?int { return $this->__call(__FUNCTION__, [$id, $extra]); } @@ -4627,13 +4524,14 @@ class InternalDoc extends APIFactory { return $this->__call(__FUNCTION__, [$id, $recursive, $extra]); } - - public function genAll($constructor, $folder_id = null, array $extra = []) - { - return $this->__call(__FUNCTION__, [$constructor, $folder_id, $extra]); - } - - public function fullChatLastUpdated($id, array $extra = []) + /** + * When were full info for this chat last cached. + * + * @param mixed $id Chat ID + * + * @return integer + */ + public function fullChatLastUpdated($id, array $extra = []): int { return $this->__call(__FUNCTION__, [$id, $extra]); } @@ -4663,108 +4561,17 @@ class InternalDoc extends APIFactory { return $this->__call(__FUNCTION__, [$id, $fullfetch, $send, $extra]); } - - public function recurseAlphabetSearchParticipants($channel, $filter, $q, $total_count, &$res, array $extra = []) - { - return $this->__call(__FUNCTION__, [$channel, $filter, $q, $total_count, $res, $extra]); - } - - public function fetchParticipants($channel, $filter, $q, $total_count, &$res, array $extra = []) - { - return $this->__call(__FUNCTION__, [$channel, $filter, $q, $total_count, $res, $extra]); - } - - public function fetchParticipantsCache($channel, $filter, $q, $offset, $limit, array $extra = []) - { - return $this->__call(__FUNCTION__, [$channel, $filter, $q, $offset, $limit, $extra]); - } - - public function storeParticipantsCache($gres, $channel, $filter, $q, $offset, $limit, array $extra = []) - { - return $this->__call(__FUNCTION__, [$gres, $channel, $filter, $q, $offset, $limit, $extra]); - } - - public function getParticipantsHash($channel, $filter, $q, $offset, $limit, array $extra = []) - { - return $this->__call(__FUNCTION__, [$channel, $filter, $q, $offset, $limit, $extra]); - } - - public function storeDb($res, $force = false, array $extra = []) - { - return $this->__call(__FUNCTION__, [$res, $force, $extra]); - } - - public function resolveUsername($username, array $extra = []) + /** + * Resolve username (use getInfo instead). + * + * @param string $username Username + * + * @return \Generator + */ + public function resolveUsername(string $username, array $extra = []) { return $this->__call(__FUNCTION__, [$username, $extra]); } - - public function pwrUpdateHandler($update, array $extra = []) - { - return $this->__call(__FUNCTION__, [$update, $extra]); - } - - public function getUpdatesUpdateHandler($update, array $extra = []) - { - return $this->__call(__FUNCTION__, [$update, $extra]); - } - - public function getUpdates($params = [ - ], array $extra = []) - { - return $this->__call(__FUNCTION__, [$params, $extra]); - } - - public function waitUpdate(array $extra = []) - { - return $this->__call(__FUNCTION__, [$extra]); - } - - public function signalUpdate(array $extra = []) - { - return $this->__call(__FUNCTION__, [$extra]); - } - - public function checkMsgId($message, array $extra = []) - { - return $this->__call(__FUNCTION__, [$message, $extra]); - } - - public function loadUpdateState(array $extra = []) - { - return $this->__call(__FUNCTION__, [$extra]); - } - - public function loadChannelState($channelId = null, $init = [ - ], array $extra = []) - { - return $this->__call(__FUNCTION__, [$channelId, $init, $extra]); - } - - public function getChannelStates(array $extra = []) - { - return $this->__call(__FUNCTION__, [$extra]); - } - - public function getUpdatesState(array $extra = []) - { - return $this->__call(__FUNCTION__, [$extra]); - } - - public function handleUpdates($updates, $actual_updates = null, array $extra = []) - { - return $this->__call(__FUNCTION__, [$updates, $actual_updates, $extra]); - } - - public function saveUpdate($update, array $extra = []) - { - return $this->__call(__FUNCTION__, [$update, $extra]); - } - - public function pwrWebhook($update, array $extra = []) - { - return $this->__call(__FUNCTION__, [$update, $extra]); - } /** * Upload file. * @@ -4773,7 +4580,7 @@ class InternalDoc extends APIFactory * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface) * @param boolean $encrypted Whether to encrypt file for secret chats * - * @return array + * @return \Generator */ public function upload($file, string $file_name = '', $cb = null, bool $encrypted = false, array $extra = []) { @@ -4824,7 +4631,7 @@ class InternalDoc extends APIFactory * @param boolean $seekable Whether chunks can be fetched out of order * @param boolean $encrypted Whether to encrypt file for secret chats * - * @return array + * @return \Generator */ public function uploadFromCallable($callable, int $size, string $mime, string $file_name = '', $cb = null, bool $seekable = true, bool $encrypted = false, array $extra = []) { @@ -4837,7 +4644,7 @@ class InternalDoc extends APIFactory * @param string $file_name File name * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface) * - * @return array + * @return \Generator */ public function uploadEncrypted($file, string $file_name = '', $cb = null, array $extra = []) { @@ -4850,18 +4657,19 @@ class InternalDoc extends APIFactory * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface) * @param boolean $encrypted Whether to encrypt file for secret chats * - * @return array + * @return \Generator */ public function uploadFromTgfile($media, $cb = null, bool $encrypted = false, array $extra = []) { return $this->__call(__FUNCTION__, [$media, $cb, $encrypted, $extra]); } - - public function genAllFile($media, array $extra = []) - { - return $this->__call(__FUNCTION__, [$media, $extra]); - } - + /** + * Get info about file. + * + * @param mixed $constructor File ID + * + * @return \Generator + */ public function getFileInfo($constructor, array $extra = []) { return $this->__call(__FUNCTION__, [$constructor, $extra]); @@ -4900,11 +4708,6 @@ class InternalDoc extends APIFactory { return $this->__call(__FUNCTION__, [$message_media, $extra]); } - - public function extractPhotosize($photo, array $extra = []) - { - return $this->__call(__FUNCTION__, [$photo, $extra]); - } /** * Download file to directory. * @@ -5043,178 +4846,186 @@ class InternalDoc extends APIFactory { return $this->__call(__FUNCTION__, [$chat, $extra]); } - - public function encryptSecretMessage($chat_id, $message, array $extra = []) - { - return $this->__call(__FUNCTION__, [$chat_id, $message, $extra]); - } - - public function handleEncryptedUpdate($message, $test = false, array $extra = []) - { - return $this->__call(__FUNCTION__, [$message, $test, $extra]); - } - - public function tryMTProtoV1Decrypt($message_key, $chat_id, $old, $encrypted_data, array $extra = []) - { - return $this->__call(__FUNCTION__, [$message_key, $chat_id, $old, $encrypted_data, $extra]); - } - - public function tryMTProtoV2Decrypt($message_key, $chat_id, $old, $encrypted_data, array $extra = []) - { - return $this->__call(__FUNCTION__, [$message_key, $chat_id, $old, $encrypted_data, $extra]); - } - - public function handleDecryptedUpdate($update, array $extra = []) - { - return $this->__call(__FUNCTION__, [$update, $extra]); - } - - public function checkSecretInSeqNo($chat_id, $seqno, array $extra = []) - { - return $this->__call(__FUNCTION__, [$chat_id, $seqno, $extra]); - } - - public function checkSecretOutSeqNo($chat_id, $seqno, array $extra = []) - { - return $this->__call(__FUNCTION__, [$chat_id, $seqno, $extra]); - } - - public function generateSecretInSeqNo($chat, array $extra = []) - { - return $this->__call(__FUNCTION__, [$chat, $extra]); - } - - public function generateSecretOutSeqNo($chat, array $extra = []) - { - return $this->__call(__FUNCTION__, [$chat, $extra]); - } - - public function htmlEntityDecode($stuff, array $extra = []) - { - return $this->__call(__FUNCTION__, [$stuff, $extra]); - } - - public function mbStrlen($text, array $extra = []) + /** + * Get Telegram UTF-8 length of string. + * + * @param string $text Text + * + * @return int + */ + public function mbStrlen(string $text, array $extra = []): int { return $this->__call(__FUNCTION__, [$text, $extra]); } - - public function mbSubstr($text, $offset, $length = null, array $extra = []) + /** + * Telegram UTF-8 multibyte substring. + * + * @param string $text Text to substring + * @param integer $offset Offset + * @param ?int $length Length + * + * @return string + */ + public function mbSubstr(string $text, int $offset, $length = null, array $extra = []): string { return $this->__call(__FUNCTION__, [$text, $offset, $length, $extra]); } - - public function mbStrSplit($text, $length, array $extra = []) + /** + * Telegram UTF-8 multibyte split. + * + * @param string $text Text + * @param integer $length Length + * + * @return string + */ + public function mbStrSplit(string $text, int $length, array $extra = []): string { return $this->__call(__FUNCTION__, [$text, $length, $extra]); } - - public function parseButtons($rows, array $extra = []) - { - return $this->__call(__FUNCTION__, [$rows, $extra]); - } - - public function parseReplyMarkup($markup, array $extra = []) - { - return $this->__call(__FUNCTION__, [$markup, $extra]); - } - - public function MTProtoToBotAPI($data, $sent_arguments = [ + /** + * Convert MTProto parameters to bot API parameters. + * + * @param array $data Data + * @param array $sent_arguments Sent arguments + * + * @return \Generator + */ + public function MTProtoToBotAPI(array $data, array $sent_arguments = [ ], array $extra = []) { return $this->__call(__FUNCTION__, [$data, $sent_arguments, $extra]); } - - public function botAPIToMTProto($arguments, array $extra = []) + /** + * Convert bot API parameters to MTProto parameters. + * + * @param array $arguments Arguments + * + * @return \Generator + */ + public function botAPIToMTProto(array $arguments, array $extra = []) { return $this->__call(__FUNCTION__, [$arguments, $extra]); } - - public function parseNode($node, &$entities, &$new_message, &$offset, array $extra = []) - { - return $this->__call(__FUNCTION__, [$node, $entities, $new_message, $offset, $extra]); - } - - public function parseMode($arguments, array $extra = []) - { - return $this->__call(__FUNCTION__, [$arguments, $extra]); - } - - public function splitToChunks($args, array $extra = []) - { - return $this->__call(__FUNCTION__, [$args, $extra]); - } - - public function multipleExplodeKeepDelimiters($delimiters, $string, array $extra = []) - { - return $this->__call(__FUNCTION__, [$delimiters, $string, $extra]); - } - - public function htmlFixtags($text, array $extra = []) - { - return $this->__call(__FUNCTION__, [$text, $extra]); - } - - public function buildRows($button_list, array $extra = []) - { - return $this->__call(__FUNCTION__, [$button_list, $extra]); - } - - public function photosizeToBotAPI($photoSize, $photo, $thumbnail = false, array $extra = []) - { - return $this->__call(__FUNCTION__, [$photoSize, $photo, $thumbnail, $extra]); - } - - public function unpackFileId($file_id, array $extra = []) + /** + * Unpack bot API file ID. + * + * @param string $file_id Bot API file ID + * + * @return array Unpacked file ID + */ + public function unpackFileId(string $file_id, array $extra = []): array { return $this->__call(__FUNCTION__, [$file_id, $extra]); } - - public function getMimeFromExtension($extension, $default, array $extra = []) + /** + * Get mime type from file extension. + * + * @param string $extension File extension + * @param string $default Default mime type + * + * @return string + */ + public function getMimeFromExtension(string $extension, string $default, array $extra = []): string { return $this->__call(__FUNCTION__, [$extension, $default, $extra]); } - - public function getExtensionFromMime($mime, array $extra = []) + /** + * Get extension from mime type. + * + * @param string $mime MIME type + * + * @return string + */ + public function getExtensionFromMime(string $mime, array $extra = []): string { return $this->__call(__FUNCTION__, [$mime, $extra]); } - - public function getExtensionFromLocation($location, $default, array $extra = []) + /** + * Get extension from file location. + * + * @param mixed $location File location + * @param string $default Default extension + * + * @return string + */ + public function getExtensionFromLocation($location, string $default, array $extra = []): string { return $this->__call(__FUNCTION__, [$location, $default, $extra]); } - - public function getMimeFromFile($file, array $extra = []) + /** + * Get mime type of file. + * + * @param string $file File + * + * @return string + */ + public function getMimeFromFile(string $file, array $extra = []): string { return $this->__call(__FUNCTION__, [$file, $extra]); } - - public function getMimeFromBuffer($buffer, array $extra = []) + /** + * Get mime type from buffer. + * + * @param string $buffer Buffer + * + * @return string + */ + public function getMimeFromBuffer(string $buffer, array $extra = []): string { return $this->__call(__FUNCTION__, [$buffer, $extra]); } - - public function tdcliToTd(&$params, $key = null, array $extra = []) + /** + * Convert tdcli parameters to tdcli. + * + * @param array $params Params + * @param array $key Key + * + * @return array + */ + public function tdcliToTd(&$params, $key = null, array $extra = []): array { return $this->__call(__FUNCTION__, [$params, $key, $extra]); } - - public function tdToMTProto($params, array $extra = []) + /** + * Convert TD to MTProto parameters. + * + * @param array $params Parameters + * + * @return \Generator + */ + public function tdToMTProto(array $params, array $extra = []) { return $this->__call(__FUNCTION__, [$params, $extra]); } - + /** + * MTProto to TDCLI params. + * + * @param mixed $params Params + * + * @return \Generator + */ public function MTProtoToTdcli($params, array $extra = []) { return $this->__call(__FUNCTION__, [$params, $extra]); } - + /** + * MTProto to TD params. + * + * @param mixed $params Params + * + * @return \Generator + */ public function MTProtoToTd(&$params, array $extra = []) { return $this->__call(__FUNCTION__, [$params, $extra]); } - + /** + * Convert TD parameters to tdcli. + * + * @param mixed $params Parameters + * + * @return mixed + */ public function tdToTdcli($params, array $extra = []) { return $this->__call(__FUNCTION__, [$params, $extra]); @@ -5465,9 +5276,9 @@ class InternalDoc extends APIFactory * * @return void */ - public function callForkDefer($promise, array $extra = []) + public function callForkDefer($promise, array $extra = []): void { - return $this->__call(__FUNCTION__, [$promise, $extra]); + $this->__call(__FUNCTION__, [$promise, $extra]); } /** * Rethrow error catched in strand. @@ -5477,9 +5288,9 @@ class InternalDoc extends APIFactory * * @return void */ - public function rethrow(\Throwable $e, $file = '', array $extra = []) + public function rethrow(\Throwable $e, $file = '', array $extra = []): void { - return $this->__call(__FUNCTION__, [$e, $file, $extra]); + $this->__call(__FUNCTION__, [$e, $file, $extra]); } /** * Call promise $b after promise $a. @@ -5519,19 +5330,6 @@ class InternalDoc extends APIFactory { return $this->__call(__FUNCTION__, [$file, $operation, $polling, $extra]); } - /** - * Asynchronously lock a file (internal generator function). - * - * @param string $file File to lock - * @param integer $operation Locking mode - * @param float $polling Polling interval - * - * @return \Generator - */ - public function flockGenerator(string $file, int $operation, float $polling, array $extra = []) - { - return $this->__call(__FUNCTION__, [$file, $operation, $polling, $extra]); - } /** * Asynchronously sleep. * @@ -5554,17 +5352,6 @@ class InternalDoc extends APIFactory { return $this->__call(__FUNCTION__, [$prompt, $extra]); } - /** - * Asynchronously read line (generator function). - * - * @param string $prompt Prompt - * - * @return \Generator - */ - public function readLineGenerator(string $prompt = '', array $extra = []) - { - return $this->__call(__FUNCTION__, [$prompt, $extra]); - } /** * Asynchronously write to stdout/browser. * @@ -5708,46 +5495,95 @@ class InternalDoc extends APIFactory { return $this->__call(__FUNCTION__, [$obj, $var, $extra]); } - - public function requestCall($user, array $extra = []) - { - return $this->__call(__FUNCTION__, [$user, $extra]); - } - - public function acceptCall($call, array $extra = []) - { - return $this->__call(__FUNCTION__, [$call, $extra]); - } - + /** + * Discard call. + * + * @param array $call Call + * @param string $reason Discard reason + * @param array $rating Rating + * @param boolean $need_debug Need debug? + * + * @return \Generator + */ public function discardCall($call, $reason, $rating = [ ], $need_debug = true, array $extra = []) { return $this->__call(__FUNCTION__, [$call, $reason, $rating, $need_debug, $extra]); } - + /** + * Request VoIP call. + * + * @param mixed $user User + * + * @return void + */ + public function requestCall($user, array $extra = []) + { + return $this->__call(__FUNCTION__, [$user, $extra]); + } + /** + * Accept call. + * + * @param array $call Call + * + * @return \Generator + */ + public function acceptCall($call, array $extra = []) + { + return $this->__call(__FUNCTION__, [$call, $extra]); + } + /** + * Confirm call. + * + * @param array $params Params + * + * @return \Generator + */ public function confirmCall($params, array $extra = []) { return $this->__call(__FUNCTION__, [$params, $extra]); } - + /** + * Complete call handshake. + * + * @param array $params Params + * + * @return \Generator + */ public function completeCall($params, array $extra = []) { return $this->__call(__FUNCTION__, [$params, $extra]); } - - public function callStatus($id, array $extra = []) + /** + * Get call status. + * + * @param array $id Call ID + * + * @return integer + */ + public function callStatus($id, array $extra = []): int { return $this->__call(__FUNCTION__, [$id, $extra]); } - - public function getCall($call, array $extra = []) + /** + * Get call info. + * + * @param mixed $call Call ID + * + * @return array + */ + public function getCall($call, array $extra = []): array { return $this->__call(__FUNCTION__, [$call, $extra]); } - - public function checkCalls(array $extra = []) + /** + * Check state of calls. + * + * @return void + */ + public function checkCalls(array $extra = []): void { - return $this->__call(__FUNCTION__, [$extra]); + $this->__call(__FUNCTION__, [$extra]); } /** * Get dialog peers. @@ -5778,9 +5614,9 @@ class InternalDoc extends APIFactory * * @return void */ - public function setEventHandler($event_handler, array $extra = []) + public function setEventHandler($event_handler, array $extra = []): void { - return $this->__call(__FUNCTION__, [$event_handler, $extra]); + $this->__call(__FUNCTION__, [$event_handler, $extra]); } /** * Get event handler. @@ -5791,19 +5627,6 @@ class InternalDoc extends APIFactory { return $this->__call(__FUNCTION__, [$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]); - } /** * Set webhook update handler. * @@ -5827,43 +5650,89 @@ class InternalDoc extends APIFactory { $this->__call(__FUNCTION__, [$callback, $extra]); } - + /** + * Log out currently logged in user. + * + * @return \Generator + */ public function logout(array $extra = []) { return $this->__call(__FUNCTION__, [$extra]); } - - public function botLogin($token, array $extra = []) + /** + * Login as bot. + * + * @param string $token Bot token + * + * @return \Generator + */ + public function botLogin(string $token, array $extra = []) { return $this->__call(__FUNCTION__, [$token, $extra]); } - + /** + * Login as user. + * + * @param string $number Phone number + * @param integer $sms_type SMS type + * + * @return \Generator + */ public function phoneLogin($number, $sms_type = 5, array $extra = []) { return $this->__call(__FUNCTION__, [$number, $sms_type, $extra]); } - + /** + * Complet user login using login code. + * + * @param string $code Login code + * + * @return \Generator + */ public function completePhoneLogin($code, array $extra = []) { return $this->__call(__FUNCTION__, [$code, $extra]); } - + /** + * Import authorization. + * + * @param mixed $authorization Authorization info + * + * @return \Generator + */ public function importAuthorization($authorization, array $extra = []) { return $this->__call(__FUNCTION__, [$authorization, $extra]); } - + /** + * Export authorization. + * + * @return \Generator + */ public function exportAuthorization(array $extra = []) { return $this->__call(__FUNCTION__, [$extra]); } - - public function completeSignup($first_name, $last_name, array $extra = []) + /** + * Complete signup to Telegram. + * + * @param string $first_name First name + * @param string $last_name Last name + * + * @return \Generator + */ + public function completeSignup(string $first_name, string $last_name = '', array $extra = []) { return $this->__call(__FUNCTION__, [$first_name, $last_name, $extra]); } - - public function complete2faLogin($password, array $extra = []) + /** + * Complete 2FA login. + * + * @param string $password Password + * + * @return \Generator + */ + public function complete2faLogin(string $password, array $extra = []) { return $this->__call(__FUNCTION__, [$password, $extra]); } @@ -5873,7 +5742,8 @@ class InternalDoc extends APIFactory * The params array can contain password, new_password, email and hint params. * * @param array $params The params - * @return void + * + * @return \Generator */ public function update2fa(array $params, array $extra = []) { @@ -5939,41 +5809,6 @@ class InternalDoc extends APIFactory { return $this->__call(__FUNCTION__, [$extra]); } - - public function webPhoneLogin(array $extra = []) - { - return $this->__call(__FUNCTION__, [$extra]); - } - - public function webCompletePhoneLogin(array $extra = []) - { - return $this->__call(__FUNCTION__, [$extra]); - } - - public function webComplete2faLogin(array $extra = []) - { - return $this->__call(__FUNCTION__, [$extra]); - } - - public function webCompleteSignup(array $extra = []) - { - return $this->__call(__FUNCTION__, [$extra]); - } - - public function webBotLogin(array $extra = []) - { - return $this->__call(__FUNCTION__, [$extra]); - } - - public function webEcho(string $message = '', array $extra = []) - { - return $this->__call(__FUNCTION__, [$message, $extra]); - } - - public function webEchoTemplate($message, $form, array $extra = []): string - { - return $this->__call(__FUNCTION__, [$message, $form, $extra]); - } /** * Get web template. * diff --git a/src/danog/MadelineProto/Logger.php b/src/danog/MadelineProto/Logger.php index 59908aee..17c71f5b 100644 --- a/src/danog/MadelineProto/Logger.php +++ b/src/danog/MadelineProto/Logger.php @@ -257,10 +257,10 @@ class Logger * * @return void */ - public function logger($param, int $level = self::NOTICE, string $file = '') + public function logger($param, int $level = self::NOTICE, string $file = ''): void { if ($level > $this->level || $this->mode === 0) { - return false; + return; } if (!self::$printed) { self::$printed = true; @@ -274,7 +274,8 @@ class Logger $this->colors[self::NOTICE] = \implode(';', [self::FOREGROUND['yellow'], self::SET['bold']]); } if ($this->mode === 4) { - return \call_user_func_array($this->optional, [$param, $level]); + \call_user_func_array($this->optional, [$param, $level]); + return; } $prefix = $this->prefix; if (\danog\MadelineProto\Magic::$has_thread && \is_object(\Thread::getCurrentThread())) { diff --git a/src/danog/MadelineProto/MTProto.php b/src/danog/MadelineProto/MTProto.php index 1398637b..6492669d 100644 --- a/src/danog/MadelineProto/MTProto.php +++ b/src/danog/MadelineProto/MTProto.php @@ -581,9 +581,9 @@ class MTProto extends AsyncConstruct implements TLCallback /** * Cleanup memory and session file. * - * @return void + * @return self */ - public function cleanup() + public function cleanup(): self { $this->referenceDatabase = new ReferenceDatabase($this); $callbacks = [$this, $this->referenceDatabase]; @@ -603,13 +603,13 @@ class MTProto extends AsyncConstruct implements TLCallback * * @return void */ - public function logger($param, int $level = Logger::NOTICE, string $file = '') + public function logger($param, int $level = Logger::NOTICE, string $file = ''): void { if ($file === null) { $file = \basename(\debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]['file'], '.php'); } - return isset($this->logger) ? $this->logger->logger($param, $level, $file) : Logger::$default->logger($param, $level, $file); + isset($this->logger) ? $this->logger->logger($param, $level, $file) : Logger::$default->logger($param, $level, $file); } /** @@ -767,6 +767,8 @@ class MTProto extends AsyncConstruct implements TLCallback /** * Clean up properties from previous versions of MadelineProto. * + * @internal + * * @return void */ private function cleanupProperties() @@ -1358,7 +1360,7 @@ class MTProto extends AsyncConstruct implements TLCallback * * @return void */ - public function parseSettings(array $settings) + private function parseSettings(array $settings): void { $settings = self::getSettings($settings, $this->settings); if ($settings['app_info'] === null) { @@ -1377,7 +1379,7 @@ class MTProto extends AsyncConstruct implements TLCallback * * @return void */ - public function setupLogger() + public function setupLogger(): void { $this->logger = Logger::getLoggerFromSettings($this->settings, isset($this->authorization['user']) ? isset($this->authorization['user']['username']) ? $this->authorization['user']['username'] : $this->authorization['user']['id'] : ''); } @@ -1388,9 +1390,11 @@ class MTProto extends AsyncConstruct implements TLCallback * @param boolean $de Whether to reset the session ID * @param boolean $auth_key Whether to reset the auth key * + * @internal + * * @return void */ - public function resetMTProtoSession(bool $de = true, bool $auth_key = false) + public function resetMTProtoSession(bool $de = true, bool $auth_key = false): void { if (!\is_object($this->datacenter)) { throw new Exception(Lang::$current_lang['session_corrupted']); @@ -1440,6 +1444,8 @@ class MTProto extends AsyncConstruct implements TLCallback /** * Whether we're initing authorization. * + * @internal + * * @return boolean */ public function isInitingAuthorization() @@ -1493,7 +1499,7 @@ class MTProto extends AsyncConstruct implements TLCallback * * @return void */ - public function resetSession() + public function resetSession(): void { if (isset($this->seqUpdater)) { $this->seqUpdater->signal(true); @@ -1539,7 +1545,7 @@ class MTProto extends AsyncConstruct implements TLCallback * * @return void */ - public function resetUpdateState() + public function resetUpdateState(): void { if (isset($this->seqUpdater)) { $this->seqUpdater->signal(true); @@ -1571,9 +1577,11 @@ class MTProto extends AsyncConstruct implements TLCallback * * @param boolean $anyway Force start update system? * + * @internal + * * @return void */ - public function startUpdateSystem($anyway = false) + public function startUpdateSystem($anyway = false): void { if ($this->asyncInitPromise && !$anyway) { $this->logger("Not starting update system"); @@ -1617,9 +1625,11 @@ class MTProto extends AsyncConstruct implements TLCallback * * @param mixed $watcherId Watcher ID * - * @return void + * @internal + * + * @return \Generator */ - public function getPhoneConfig($watcherId = null) + public function getPhoneConfig($watcherId = null): \Generator { if ($this->authorized === self::LOGGED_IN && \class_exists(VoIPServerConfigInternal::class) && !$this->authorization['user']['bot'] && $this->datacenter->getDataCenterConnection($this->settings['connection_settings']['default_dc'])->hasTempAuthKey()) { $this->logger->logger('Fetching phone config...'); @@ -1747,16 +1757,35 @@ class MTProto extends AsyncConstruct implements TLCallback return $this->authorization['user']; } + /** + * Called right before serialization of method starts. + * + * Pass the method name + * + * @return array + */ public function getMethodCallbacks(): array { return []; } + /** + * Called right before serialization of method starts. + * + * Pass the method name + * + * @return array + */ public function getMethodBeforeCallbacks(): array { return []; } + /** + * Called right after deserialization of object, passing the final object. + * + * @return array + */ public function getConstructorCallbacks(): array { return \array_merge( @@ -1766,16 +1795,38 @@ class MTProto extends AsyncConstruct implements TLCallback ); } + /** + * Called right before deserialization of object. + * + * Pass only the constructor name + * + * @return array + */ public function getConstructorBeforeCallbacks(): array { return []; } + /** + * Called right before serialization of constructor. + * + * Passed the object, will return a modified version. + * + * @return array + */ public function getConstructorSerializeCallbacks(): array { return []; } + /** + * Called if objects of the specified type cannot be serialized. + * + * Passed the unserializable object, + * will try to convert it to an object of the proper type. + * + * @return array + */ public function getTypeMismatchCallbacks(): array { return \array_merge( diff --git a/src/danog/MadelineProto/MTProtoTools/Files.php b/src/danog/MadelineProto/MTProtoTools/Files.php index c3afebaf..a6a08526 100644 --- a/src/danog/MadelineProto/MTProtoTools/Files.php +++ b/src/danog/MadelineProto/MTProtoTools/Files.php @@ -56,7 +56,7 @@ trait Files * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface) * @param boolean $encrypted Whether to encrypt file for secret chats * - * @return array + * @return \Generator */ public function upload($file, string $file_name = '', $cb = null, bool $encrypted = false): \Generator { @@ -229,9 +229,9 @@ trait Files * @param boolean $seekable Whether chunks can be fetched out of order * @param boolean $encrypted Whether to encrypt file for secret chats * - * @return array + * @return \Generator */ - public function uploadFromCallable($callable, int $size, string $mime, string $file_name = '', $cb = null, bool $seekable = true, bool $encrypted = false) + public function uploadFromCallable($callable, int $size, string $mime, string $file_name = '', $cb = null, bool $seekable = true, bool $encrypted = false): \Generator { if (\is_object($callable) && $callable instanceof FileCallbackInterface) { $cb = $callable; @@ -360,9 +360,9 @@ trait Files * @param string $file_name File name * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface) * - * @return array + * @return \Generator */ - public function uploadEncrypted($file, string $file_name = '', $cb = null) + public function uploadEncrypted($file, string $file_name = '', $cb = null): \Generator { return $this->upload($file, $file_name, $cb, true); } @@ -374,9 +374,9 @@ trait Files * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface) * @param boolean $encrypted Whether to encrypt file for secret chats * - * @return array + * @return \Generator */ - public function uploadFromTgfile($media, $cb = null, bool $encrypted = false) + public function uploadFromTgfile($media, $cb = null, bool $encrypted = false): \Generator { if (\is_object($media) && $media instanceof FileCallbackInterface) { $cb = $media; @@ -447,7 +447,7 @@ trait Files return $res; } - public function genAllFile($media) + private function genAllFile($media) { $res = [$this->TL->getConstructors()->findByPredicate($media['_'])['type'] => $media]; switch ($media['_']) { @@ -540,7 +540,14 @@ trait Files return $res; } - public function getFileInfo($constructor) + /** + * Get info about file. + * + * @param mixed $constructor File ID + * + * @return \Generator + */ + public function getFileInfo($constructor): \Generator { if (\is_string($constructor)) { $constructor = $this->unpackFileId($constructor)['MessageMedia']; @@ -932,6 +939,15 @@ trait Files header('Content-Length: '.$info['size']); header('Content-Type: '.$info['mime']); }*/ + /** + * Extract photo size. + * + * @param mixed $photo Photo + * + * @internal + * + * @return void + */ public function extractPhotosize($photo) { } @@ -1224,7 +1240,7 @@ trait Files ]; } - $x = 0; + //$x = 0; while (true) { try { $res = yield $this->methodCallAsyncRead( @@ -1241,7 +1257,7 @@ trait Files break; } catch (\danog\MadelineProto\RPCErrorException $e) { if (\strpos($e->rpc, 'FLOOD_WAIT_') === 0) { - if ($x++ === 5) { + /*if ($x++ === 5) { if (isset($message_media['MessageMedia']) && !$this->authorization['user']['bot'] && $this->settings['download']['report_broken_media']) { try { yield $this->methodCallAsyncRead('messages.sendMedia', ['peer' => 'support', 'media' => $message_media['MessageMedia'], 'message' => "I can't download this file, could you please help?"], ['datacenter' => $this->datacenter->curdc]); @@ -1253,7 +1269,7 @@ trait Files } throw new \danog\MadelineProto\Exception('The media server where this file is hosted is offline/overloaded, please try again later. Send the media to the telegram devs or to @danogentili to fix this.'); - } + }*/ yield Tools::sleep(1); continue; } diff --git a/src/danog/MadelineProto/MTProtoTools/PeerHandler.php b/src/danog/MadelineProto/MTProtoTools/PeerHandler.php index 9fb6d29d..512fb1d0 100644 --- a/src/danog/MadelineProto/MTProtoTools/PeerHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/PeerHandler.php @@ -51,7 +51,7 @@ trait PeerHandler * * @return int */ - public static function fromSupergroup($id) + public static function fromSupergroup($id): int { return -$id - \pow(10, (int) \floor(\log(-$id, 10))); } @@ -70,12 +70,28 @@ trait PeerHandler return ($log - \intval($log)) * 1000 < 10; } - public function addSupport($support) + /** + * Set support info. + * + * @param array $support Support info + * + * @internal + * + * @return void + */ + public function addSupport(array $support): void { $this->supportUser = $support['user']['id']; } - public function addUser($user) + /** + * Add user info. + * + * @param array $user User info + * + * @return void + */ + public function addUser(array $user): void { if (!isset($user['access_hash']) && !($user['min'] ?? false)) { if (isset($this->chats[$user['id']]['access_hash']) && $this->chats[$user['id']]['access_hash']) { @@ -117,11 +133,19 @@ trait PeerHandler break; default: throw new \danog\MadelineProto\Exception('Invalid user provided', $user); - break; } } - public function addChat($chat) + /** + * Add chat to database. + * + * @param array $chat Chat + * + * @internal + * + * @return void + */ + public function addChat($chat): \Generator { switch ($chat['_']) { case 'chat': @@ -182,7 +206,7 @@ trait PeerHandler } } - public function cachePwrChat($id, $full_fetch, $send) + private function cachePwrChat($id, $full_fetch, $send) { \danog\MadelineProto\Tools::callFork((function () use ($id, $full_fetch, $send) { try { @@ -220,7 +244,16 @@ trait PeerHandler } } - public function entitiesPeerIsset($entities): \Generator + /** + * Check if all peer entities are in db. + * + * @param array $entities Entity list + * + * @internal + * + * @return \Generator + */ + public function entitiesPeerIsset(array $entities): \Generator { try { foreach ($entities as $entity) { @@ -237,7 +270,16 @@ trait PeerHandler return true; } - public function fwdPeerIsset($fwd): \Generator + /** + * Check if fwd peer is set. + * + * @param array $fwd Forward info + * + * @internal + * + * @return \Generator + */ + public function fwdPeerIsset(array $fwd): \Generator { try { if (isset($fwd['user_id']) && !yield $this->peerIsset($fwd['user_id'])) { @@ -260,7 +302,7 @@ trait PeerHandler * * @return ?int */ - public function getFolderId($id) + public function getFolderId($id): ?int { if (!\is_array($id)) { return null; @@ -593,7 +635,7 @@ trait PeerHandler throw new \danog\MadelineProto\Exception('This peer is not present in the internal peer database'); } - public function genAll($constructor, $folder_id = null) + private function genAll($constructor, $folder_id = null) { $res = [$this->TL->getConstructors()->findByPredicate($constructor['_'])['type'] => $constructor]; switch ($constructor['_']) { @@ -655,7 +697,14 @@ trait PeerHandler return $res; } - public function fullChatLastUpdated($id) + /** + * When were full info for this chat last cached. + * + * @param mixed $id Chat ID + * + * @return integer + */ + public function fullChatLastUpdated($id): int { return isset($this->full_chats[$id]['last_update']) ? $this->full_chats[$id]['last_update'] : 0; } @@ -845,7 +894,7 @@ trait PeerHandler return $res; } - public function recurseAlphabetSearchParticipants($channel, $filter, $q, $total_count, &$res) + private function recurseAlphabetSearchParticipants($channel, $filter, $q, $total_count, &$res) { if (!yield $this->fetchParticipants($channel, $filter, $q, $total_count, $res)) { return false; @@ -856,7 +905,7 @@ trait PeerHandler } } - public function fetchParticipants($channel, $filter, $q, $total_count, &$res) + private function fetchParticipants($channel, $filter, $q, $total_count, &$res) { $offset = 0; $limit = 200; @@ -942,12 +991,12 @@ trait PeerHandler return $has_more; } - public function fetchParticipantsCache($channel, $filter, $q, $offset, $limit) + private function fetchParticipantsCache($channel, $filter, $q, $offset, $limit) { return $this->channel_participants[$channel['channel_id']][$filter][$q][$offset][$limit]; } - public function storeParticipantsCache($gres, $channel, $filter, $q, $offset, $limit) + private function storeParticipantsCache($gres, $channel, $filter, $q, $offset, $limit) { //return; unset($gres['users']); @@ -960,12 +1009,12 @@ trait PeerHandler $this->channel_participants[$channel['channel_id']][$filter][$q][$offset][$limit] = $gres; } - public function getParticipantsHash($channel, $filter, $q, $offset, $limit) + private function getParticipantsHash($channel, $filter, $q, $offset, $limit) { return isset($this->channel_participants[$channel['channel_id']][$filter][$q][$offset][$limit]) ? $this->channel_participants[$channel['channel_id']][$filter][$q][$offset][$limit]['hash'] : 0; } - public function storeDb($res, $force = false) + private function storeDb($res, $force = false) { $settings = isset($this->settings['connection_settings'][$this->datacenter->curdc]) ? $this->settings['connection_settings'][$this->datacenter->curdc] : $this->settings['connection_settings']['all']; if (!isset($this->settings['pwr']) || $this->settings['pwr']['pwr'] === false || $settings['test_mode']) { @@ -1007,7 +1056,14 @@ trait PeerHandler } } - public function resolveUsername($username) + /** + * Resolve username (use getInfo instead). + * + * @param string $username Username + * + * @return \Generator + */ + public function resolveUsername(string $username): \Generator { try { $this->caching_simple_username[$username] = true; diff --git a/src/danog/MadelineProto/MTProtoTools/UpdateHandler.php b/src/danog/MadelineProto/MTProtoTools/UpdateHandler.php index 1ee560d6..2fa3f2eb 100644 --- a/src/danog/MadelineProto/MTProtoTools/UpdateHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/UpdateHandler.php @@ -35,6 +35,15 @@ trait UpdateHandler public $updates = []; public $updates_key = 0; + /** + * PWR update handler. + * + * @param array $update Update + * + * @internal + * + * @return void + */ public function pwrUpdateHandler($update) { if (isset($this->settings['pwr']['updateHandler'])) { @@ -48,7 +57,16 @@ trait UpdateHandler } } - public function getUpdatesUpdateHandler($update) + /** + * Getupdates update handler. + * + * @param array $update Update + * + * @internal + * + * @return void + */ + public function getUpdatesUpdateHandler(array $update): void { if (!$this->settings['updates']['handle_updates']) { return; @@ -56,7 +74,16 @@ trait UpdateHandler $this->updates[$this->updates_key++] = $update; } - public function getUpdates($params = []) + /** + * Get updates. + * + * @param array $params Params + * + * @internal + * + * @return \Generator + */ + public function getUpdates($params = []): \Generator { if (!$this->settings['updates']['handle_updates']) { $this->settings['updates']['handle_updates'] = true; @@ -98,7 +125,14 @@ trait UpdateHandler public $update_resolved = false; public $update_deferred; - public function waitUpdate() + /** + * Wait for update. + * + * @internal + * + * @return \Generator + */ + public function waitUpdate(): \Generator { if (!$this->update_deferred) { $this->update_deferred = new Deferred(); @@ -108,7 +142,14 @@ trait UpdateHandler $this->update_deferred = new Deferred(); } - public function signalUpdate() + /** + * Signal update. + * + * @internal + * + * @return void + */ + public function signalUpdate(): void { if (!$this->update_deferred) { $this->update_deferred = new Deferred(); @@ -121,7 +162,17 @@ trait UpdateHandler }); } - public function checkMsgId($message) + + /** + * Check message ID. + * + * @param array $message Message + * + * @internal + * + * @return boolean + */ + public function checkMsgId(array $message): bool { if (!isset($message['to_id'])) { return true; @@ -144,6 +195,13 @@ trait UpdateHandler return false; } + /** + * Get channel state. + * + * @internal + * + * @return UpdatesState|UpdatesState[] + */ public function loadUpdateState() { if (!$this->got_state) { @@ -154,17 +212,41 @@ trait UpdateHandler return $this->channels_state->get(false); } + /** + * Load channel state. + * + * @param ?int $channelId Channel ID + * @param array $init Init + * + * @internal + * + * @return UpdatesState|UpdatesState[] + */ public function loadChannelState($channelId = null, $init = []) { return $this->channels_state->get($channelId, $init); } + /** + * Get channel states. + * + * @internal + * + * @return CombinedUpdatesState + */ public function getChannelStates() { return $this->channels_state; } - public function getUpdatesState() + /** + * Get update state. + * + * @internal + * + * @return \Generator + */ + public function getUpdatesState(): \Generator { $data = yield $this->methodCallAsyncRead('updates.getState', [], ['datacenter' => $this->settings['connection_settings']['default_dc']]); yield $this->getCdnConfig($this->settings['connection_settings']['default_dc']); @@ -173,7 +255,17 @@ trait UpdateHandler } - public function handleUpdates($updates, $actual_updates = null) + /** + * Undocumented function. + * + * @param array $updates Updates + * @param array $actual_updates Actual updates for deferred + * + * @internal + * + * @return \Generator + */ + public function handleUpdates($updates, $actual_updates = null): \Generator { if (!$this->settings['updates']['handle_updates']) { return; @@ -252,7 +344,16 @@ trait UpdateHandler break; } } - public function saveUpdate($update) + /** + * Save update. + * + * @param array $update Update to save + * + * @internal + * + * @return \Generator + */ + public function saveUpdate(array $update): \Generator { if ($update['_'] === 'updateConfig') { $this->config['expires'] = 0; @@ -388,14 +489,21 @@ trait UpdateHandler } } - public function pwrWebhook($update) + /** + * Send update to webhook. + * + * @param array $update Update + * + * @return void + */ + private function pwrWebhook(array $update): void { $payload = \json_encode($update); //$this->logger->logger($update, $payload, json_last_error()); if ($payload === '') { $this->logger->logger('EMPTY UPDATE'); - return false; + return; } \danog\MadelineProto\Tools::callFork((function () use ($payload) { $request = new Request($this->hook_url, 'POST'); diff --git a/src/danog/MadelineProto/SecretChats/MessageHandler.php b/src/danog/MadelineProto/SecretChats/MessageHandler.php index 8f377c09..a1485f9d 100644 --- a/src/danog/MadelineProto/SecretChats/MessageHandler.php +++ b/src/danog/MadelineProto/SecretChats/MessageHandler.php @@ -24,7 +24,17 @@ namespace danog\MadelineProto\SecretChats; */ trait MessageHandler { - public function encryptSecretMessage($chat_id, $message) + /** + * Encrypt secret chat message. + * + * @param integer $chat_id Chat ID + * @param array $message Message to encrypt + * + * @internal + * + * @return \Generator + */ + public function encryptSecretMessage(int $chat_id, array $message): \Generator { if (!isset($this->secret_chats[$chat_id])) { $this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['secret_chat_skipping'], $chat_id)); @@ -61,7 +71,7 @@ trait MessageHandler return $message; } - public function handleEncryptedUpdate($message, $test = false) + private function handleEncryptedUpdate(array $message): \Generator { if (!isset($this->secret_chats[$message['message']['chat_id']])) { $this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['secret_chat_skipping'], $message['message']['chat_id'])); @@ -122,7 +132,7 @@ trait MessageHandler yield $this->handleDecryptedUpdate($message); } - public function tryMTProtoV1Decrypt($message_key, $chat_id, $old, $encrypted_data) + private function tryMTProtoV1Decrypt($message_key, $chat_id, $old, $encrypted_data) { list($aes_key, $aes_iv) = $this->oldAesCalculate($message_key, $this->secret_chats[$chat_id][$old ? 'old_key' : 'key']['auth_key'], true); $decrypted_data = $this->igeDecrypt($encrypted_data, $aes_key, $aes_iv); @@ -144,7 +154,7 @@ trait MessageHandler return $message_data; } - public function tryMTProtoV2Decrypt($message_key, $chat_id, $old, $encrypted_data) + private function tryMTProtoV2Decrypt($message_key, $chat_id, $old, $encrypted_data) { list($aes_key, $aes_iv) = $this->aesCalculate($message_key, $this->secret_chats[$chat_id][$old ? 'old_key' : 'key']['auth_key'], !$this->secret_chats[$chat_id]['admin']); $decrypted_data = $this->igeDecrypt($encrypted_data, $aes_key, $aes_iv); diff --git a/src/danog/MadelineProto/SecretChats/ResponseHandler.php b/src/danog/MadelineProto/SecretChats/ResponseHandler.php index baca989f..8fadebb8 100644 --- a/src/danog/MadelineProto/SecretChats/ResponseHandler.php +++ b/src/danog/MadelineProto/SecretChats/ResponseHandler.php @@ -24,7 +24,7 @@ namespace danog\MadelineProto\SecretChats; */ trait ResponseHandler { - public function handleDecryptedUpdate($update) + private function handleDecryptedUpdate($update) { /*if (isset($update['message']['decrypted_message']['random_bytes']) && strlen($update['message']['decrypted_message']['random_bytes']) < 15) { throw new \danog\MadelineProto\ResponseException(\danog\MadelineProto\Lang::$current_lang['rand_bytes_too_short']); diff --git a/src/danog/MadelineProto/SecretChats/SeqNoHandler.php b/src/danog/MadelineProto/SecretChats/SeqNoHandler.php index 277d22dd..6dda54c4 100644 --- a/src/danog/MadelineProto/SecretChats/SeqNoHandler.php +++ b/src/danog/MadelineProto/SecretChats/SeqNoHandler.php @@ -24,7 +24,7 @@ namespace danog\MadelineProto\SecretChats; */ trait SeqNoHandler { - public function checkSecretInSeqNo($chat_id, $seqno) + private function checkSecretInSeqNo($chat_id, $seqno) { $seqno = ($seqno - $this->secret_chats[$chat_id]['out_seq_no_x']) / 2; $last = 0; @@ -47,7 +47,7 @@ trait SeqNoHandler return true; } - public function checkSecretOutSeqNo($chat_id, $seqno) + private function checkSecretOutSeqNo($chat_id, $seqno) { $seqno = ($seqno - $this->secret_chats[$chat_id]['in_seq_no_x']) / 2; $C = 0; @@ -78,12 +78,12 @@ trait SeqNoHandler return true; } - public function generateSecretInSeqNo($chat) + private function generateSecretInSeqNo($chat) { return $this->secret_chats[$chat]['layer'] > 8 ? $this->secret_chats[$chat]['in_seq_no'] * 2 + $this->secret_chats[$chat]['in_seq_no_x'] : -1; } - public function generateSecretOutSeqNo($chat) + private function generateSecretOutSeqNo($chat) { return $this->secret_chats[$chat]['layer'] > 8 ? $this->secret_chats[$chat]['out_seq_no'] * 2 + $this->secret_chats[$chat]['out_seq_no_x'] : -1; } diff --git a/src/danog/MadelineProto/TL/Conversion/BotAPI.php b/src/danog/MadelineProto/TL/Conversion/BotAPI.php index e01256b6..7f5d8643 100644 --- a/src/danog/MadelineProto/TL/Conversion/BotAPI.php +++ b/src/danog/MadelineProto/TL/Conversion/BotAPI.php @@ -23,12 +23,19 @@ use danog\MadelineProto\Logger; trait BotAPI { - public function htmlEntityDecode($stuff) + private function htmlEntityDecode($stuff) { return \html_entity_decode(\preg_replace('#< *br */? *>#', "\n", $stuff)); } - public function mbStrlen($text) + /** + * Get Telegram UTF-8 length of string. + * + * @param string $text Text + * + * @return int + */ + public function mbStrlen(string $text): int { $length = 0; $textlength = \strlen($text); @@ -42,7 +49,16 @@ trait BotAPI return $length; } - public function mbSubstr($text, $offset, $length = null) + /** + * Telegram UTF-8 multibyte substring. + * + * @param string $text Text to substring + * @param integer $offset Offset + * @param ?int $length Length + * + * @return string + */ + public function mbSubstr(string $text, int $offset, $length = null): string { $mb_text_length = $this->mbStrlen($text); if ($offset < 0) { @@ -75,7 +91,15 @@ trait BotAPI return $new_text; } - public function mbStrSplit($text, $length) + /** + * Telegram UTF-8 multibyte split. + * + * @param string $text Text + * @param integer $length Length + * + * @return string + */ + public function mbStrSplit(string $text, int $length): string { $tlength = \mb_strlen($text, 'UTF-8'); $result = []; @@ -86,7 +110,7 @@ trait BotAPI return $result; } - public function parseButtons($rows) + private function parseButtons($rows) { $newrows = []; $key = 0; @@ -125,7 +149,7 @@ trait BotAPI return $newrows; } - public function parseReplyMarkup($markup) + private function parseReplyMarkup($markup) { if (isset($markup['force_reply']) && $markup['force_reply']) { $markup['_'] = 'replyKeyboardForceReply'; @@ -157,7 +181,15 @@ trait BotAPI return $markup; } - public function MTProtoToBotAPI($data, $sent_arguments = []) + /** + * Convert MTProto parameters to bot API parameters. + * + * @param array $data Data + * @param array $sent_arguments Sent arguments + * + * @return \Generator + */ + public function MTProtoToBotAPI(array $data, array $sent_arguments = []): \Generator { $newd = []; if (!isset($data['_'])) { @@ -382,7 +414,14 @@ trait BotAPI } } - public function botAPIToMTProto($arguments) + /** + * Convert bot API parameters to MTProto parameters. + * + * @param array $arguments Arguments + * + * @return \Generator + */ + public function botAPIToMTProto(array $arguments): \Generator { foreach (self::BOTAPI_PARAMS_CONVERSION as $bot => $mtproto) { if (isset($arguments[$bot]) && !isset($arguments[$mtproto])) { @@ -400,7 +439,7 @@ trait BotAPI return $arguments; } - public function parseNode($node, &$entities, &$new_message, &$offset) + private function parseNode($node, &$entities, &$new_message, &$offset) { switch ($node->nodeName) { case 'br': @@ -518,7 +557,7 @@ trait BotAPI } } - public function parseMode($arguments) + private function parseMode($arguments) { if ($arguments['message'] === '' || !isset($arguments['message']) || !isset($arguments['parse_mode'])) { return $arguments; @@ -555,7 +594,7 @@ trait BotAPI return $arguments; } - public function splitToChunks($args) + private function splitToChunks($args) { $args = yield $this->parseMode($args); if (!isset($args['entities'])) { @@ -665,7 +704,7 @@ trait BotAPI return $multiple_args; } - public function multipleExplodeKeepDelimiters($delimiters, $string) + private function multipleExplodeKeepDelimiters($delimiters, $string) { $initialArray = \explode(\chr(1), \str_replace($delimiters, \chr(1), $string)); $finalArray = []; @@ -681,7 +720,7 @@ trait BotAPI return $finalArray; } - public function htmlFixtags($text) + private function htmlFixtags($text) { $diff = 0; \preg_match_all('#(.*?)(<(\bu\b|\bs\b|\ba\b|\bb\b|\bstrong\b|\bblockquote\b|\bstrike\b|\bdel\b|\bem\b|i|\bcode\b|\bpre\b)[^>]*>)(.*?)([<]\s*/\s*\3[>])#is', $text, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE); @@ -724,7 +763,7 @@ trait BotAPI return \htmlentities($text); } - public function buildRows($button_list) + private function buildRows($button_list) { $end = false; $rows = []; diff --git a/src/danog/MadelineProto/TL/Conversion/BotAPIFiles.php b/src/danog/MadelineProto/TL/Conversion/BotAPIFiles.php index 176f62b7..58ae98fd 100644 --- a/src/danog/MadelineProto/TL/Conversion/BotAPIFiles.php +++ b/src/danog/MadelineProto/TL/Conversion/BotAPIFiles.php @@ -21,7 +21,7 @@ namespace danog\MadelineProto\TL\Conversion; trait BotAPIFiles { - public function photosizeToBotAPI($photoSize, $photo, $thumbnail = false) + private function photosizeToBotAPI($photoSize, $photo, $thumbnail = false) { $ext = '.jpg';//$this->getExtensionFromLocation(['_' => 'inputFileLocation', 'volume_id' => $photoSize['location']['volume_id'], 'local_id' => $photoSize['location']['local_id'], 'secret' => $photoSize['location']['secret'], 'dc_id' => $photoSize['location']['dc_id']], '.jpg'); $photoSize['location']['access_hash'] = $photo['access_hash'] ?? 0; @@ -41,7 +41,14 @@ trait BotAPIFiles ]; } - public function unpackFileId($file_id) + /** + * Unpack bot API file ID. + * + * @param string $file_id Bot API file ID + * + * @return array Unpacked file ID + */ + public function unpackFileId(string $file_id): array { $file_id = \danog\MadelineProto\Tools::rleDecode(\danog\MadelineProto\Tools::base64urlDecode($file_id)); if ($file_id[\strlen($file_id) - 1] !== \chr(2)) { diff --git a/src/danog/MadelineProto/TL/Conversion/Extension.php b/src/danog/MadelineProto/TL/Conversion/Extension.php index 66afccab..13eab0bb 100644 --- a/src/danog/MadelineProto/TL/Conversion/Extension.php +++ b/src/danog/MadelineProto/TL/Conversion/Extension.php @@ -14,22 +14,39 @@ If not, see . namespace danog\MadelineProto\TL\Conversion; +use danog\MadelineProto\MTProto; + /** * Manages generation of extensions for files. */ trait Extension { - public function getMimeFromExtension($extension, $default) + /** + * Get mime type from file extension. + * + * @param string $extension File extension + * @param string $default Default mime type + * + * @return string + */ + public function getMimeFromExtension(string $extension, string $default): string { $ext = \ltrim($extension, '.'); - if (isset(self::ALL_MIMES[$ext])) { - return self::ALL_MIMES[$ext][0]; + if (isset(MTProto::ALL_MIMES[$ext])) { + return MTProto::ALL_MIMES[$ext][0]; } return $default; } - public function getExtensionFromMime($mime) + /** + * Get extension from mime type. + * + * @param string $mime MIME type + * + * @return string + */ + public function getExtensionFromMime(string $mime): string { foreach (self::ALL_MIMES as $key => $value) { if (\array_search($mime, $value) !== false) { @@ -40,7 +57,15 @@ trait Extension return ''; } - public function getExtensionFromLocation($location, $default) + /** + * Get extension from file location. + * + * @param mixed $location File location + * @param string $default Default extension + * + * @return string + */ + public function getExtensionFromLocation($location, string $default): string { return $default; //('upload.getFile', ['location' => $location, 'offset' => 0, 'limit' => 2], ['heavy' => true, 'datacenter' => $location['dc_id']]); @@ -69,14 +94,28 @@ trait Extension } } - public function getMimeFromFile($file) + /** + * Get mime type of file. + * + * @param string $file File + * + * @return string + */ + public function getMimeFromFile(string $file): string { $finfo = new \finfo(FILEINFO_MIME_TYPE); return $finfo->file($file); } - public function getMimeFromBuffer($buffer) + /** + * Get mime type from buffer. + * + * @param string $buffer Buffer + * + * @return string + */ + public function getMimeFromBuffer(string $buffer): string { $finfo = new \finfo(FILEINFO_MIME_TYPE); diff --git a/src/danog/MadelineProto/TL/Conversion/TD.php b/src/danog/MadelineProto/TL/Conversion/TD.php index a6c02c18..1b45b0aa 100644 --- a/src/danog/MadelineProto/TL/Conversion/TD.php +++ b/src/danog/MadelineProto/TL/Conversion/TD.php @@ -21,7 +21,15 @@ namespace danog\MadelineProto\TL\Conversion; trait TD { - public function tdcliToTd(&$params, $key = null) + /** + * Convert tdcli parameters to tdcli. + * + * @param array $params Params + * @param array $key Key + * + * @return array + */ + public function tdcliToTd(&$params, $key = null): array { if (!\is_array($params)) { return $params; @@ -44,7 +52,14 @@ trait TD return $params; } - public function tdToMTProto($params) + /** + * Convert TD to MTProto parameters. + * + * @param array $params Parameters + * + * @return \Generator + */ + public function tdToMTProto(array $params): \Generator { $newparams = ['_' => self::REVERSE[$params['_']]]; foreach (self::TD_PARAMS_CONVERSION[$newparams['_']] as $td => $mtproto) { @@ -75,12 +90,26 @@ trait TD return $newparams; } - public function MTProtoToTdcli($params) + /** + * MTProto to TDCLI params. + * + * @param mixed $params Params + * + * @return \Generator + */ + public function MTProtoToTdcli($params): \Generator { return $this->tdToTdcli(yield $this->MTProtoToTd($params)); } - public function MTProtoToTd(&$params) + /** + * MTProto to TD params. + * + * @param mixed $params Params + * + * @return \Generator + */ + public function MTProtoToTd(&$params): \Generator { if (!\is_array($params)) { return $params; @@ -163,6 +192,13 @@ trait TD return $newparams; } + /** + * Convert TD parameters to tdcli. + * + * @param mixed $params Parameters + * + * @return mixed + */ public function tdToTdcli($params) { if (!\is_array($params)) { diff --git a/src/danog/MadelineProto/TL/TLCallback.php b/src/danog/MadelineProto/TL/TLCallback.php index b34e2ea1..1102ad8f 100644 --- a/src/danog/MadelineProto/TL/TLCallback.php +++ b/src/danog/MadelineProto/TL/TLCallback.php @@ -45,7 +45,7 @@ interface TLCallback * * Pass the method name and arguments * - * @var array + * @return array */ public function getMethodCallbacks(): array; @@ -54,14 +54,14 @@ interface TLCallback * * Pass the method name * - * @var array + * @return array */ public function getMethodBeforeCallbacks(): array; /** * Called right after deserialization of object, passing the final object. * - * @var array + * @return array */ public function getConstructorCallbacks(): array; @@ -70,7 +70,7 @@ interface TLCallback * * Pass only the constructor name * - * @var array + * @return array */ public function getConstructorBeforeCallbacks(): array; @@ -79,7 +79,7 @@ interface TLCallback * * Passed the object, will return a modified version. * - * @var array + * @return array */ public function getConstructorSerializeCallbacks(): array; @@ -89,7 +89,7 @@ interface TLCallback * Passed the unserializable object, * will try to convert it to an object of the proper type. * - * @var array + * @return array */ public function getTypeMismatchCallbacks(): array; } diff --git a/src/danog/MadelineProto/Tools.php b/src/danog/MadelineProto/Tools.php index 4baff3db..7b353f26 100644 --- a/src/danog/MadelineProto/Tools.php +++ b/src/danog/MadelineProto/Tools.php @@ -480,7 +480,7 @@ trait Tools * * @return void */ - public static function callForkDefer($promise) + public static function callForkDefer($promise): void { Loop::defer([__CLASS__, 'callFork'], $promise); } @@ -493,7 +493,7 @@ trait Tools * * @return void */ - public static function rethrow(\Throwable $e, $file = '') + public static function rethrow(\Throwable $e, $file = ''): void { $zis = isset($this) ? $this : null; $logger = isset($zis->logger) ? $zis->logger : Logger::$default; @@ -593,6 +593,8 @@ trait Tools * @param integer $operation Locking mode * @param float $polling Polling interval * + * @internal Generator function + * * @return \Generator */ public static function flockGenerator(string $file, int $operation, float $polling): \Generator @@ -646,6 +648,8 @@ trait Tools * * @param string $prompt Prompt * + * @internal Generator function + * * @return \Generator */ public static function readLineGenerator(string $prompt = ''): \Generator diff --git a/src/danog/MadelineProto/VoIP/AuthKeyHandler.php b/src/danog/MadelineProto/VoIP/AuthKeyHandler.php index bf91c317..1af0c2c7 100644 --- a/src/danog/MadelineProto/VoIP/AuthKeyHandler.php +++ b/src/danog/MadelineProto/VoIP/AuthKeyHandler.php @@ -29,22 +29,57 @@ trait AuthKeyHandler { private $calls = []; + /** + * Request call (synchronous). + * + * @param mixed $user User info + * + * @internal + * + * @return \danog\MadelineProto\VoIPController + */ public function requestCall($user) { return \danog\MadelineProto\Tools::wait($this->requestCallAsync($user)); } - public function acceptCall($user) + /** + * Accept call (synchronous). + * + * @param mixed $user Accept call + * + * @internal + * + * @return bool + */ + public function acceptCall($user): bool { return \danog\MadelineProto\Tools::wait($this->acceptCallAsync($user)); } - public function discardCall($call, $reason, $rating = [], $need_debug = true) + /** + * Discard call (synchronous). + * + * @param array $call Call + * @param string $reason Discard reason + * @param array $rating Rating + * @param boolean $need_debug Need debug? + * + * @return array + */ + public function discardCall($call, $reason, $rating = [], $need_debug = true): void { - return \danog\MadelineProto\Tools::wait($this->discardCallAsync($call, $reason, $rating, $need_debug)); + \danog\MadelineProto\Tools::wait($this->discardCallAsync($call, $reason, $rating, $need_debug)); } - public function requestCallAsync($user) + /** + * Request VoIP call. + * + * @param mixed $user User + * + * @return void + */ + public function requestCallAsync($user): \Generator { if (!\class_exists('\\danog\\MadelineProto\\VoIP')) { throw \danog\MadelineProto\Exception::extension('libtgvoip'); @@ -71,7 +106,14 @@ trait AuthKeyHandler return $controller; } - public function acceptCallAsync($call) + /** + * Accept call. + * + * @param array $call Call + * + * @return \Generator + */ + public function acceptCallAsync($call): \Generator { if (!\class_exists('\\danog\\MadelineProto\\VoIP')) { throw new \danog\MadelineProto\Exception(); @@ -111,7 +153,14 @@ trait AuthKeyHandler return true; } - public function confirmCall($params) + /** + * Confirm call. + * + * @param array $params Params + * + * @return \Generator + */ + public function confirmCall($params): \Generator { if (!\class_exists('\\danog\\MadelineProto\\VoIP')) { throw \danog\MadelineProto\Exception::extension('libtgvoip'); @@ -160,7 +209,14 @@ trait AuthKeyHandler return $res; } - public function completeCall($params) + /** + * Complete call handshake. + * + * @param array $params Params + * + * @return \Generator + */ + public function completeCall($params): \Generator { if (!\class_exists('\\danog\\MadelineProto\\VoIP')) { throw \danog\MadelineProto\Exception::extension('libtgvoip'); @@ -195,7 +251,14 @@ trait AuthKeyHandler return $this->calls[$params['id']]->startTheMagic(); } - public function callStatus($id) + /** + * Get call status. + * + * @param array $id Call ID + * + * @return integer + */ + public function callStatus($id): int { if (!\class_exists('\\danog\\MadelineProto\\VoIP')) { throw \danog\MadelineProto\Exception::extension('libtgvoip'); @@ -207,7 +270,14 @@ trait AuthKeyHandler return \danog\MadelineProto\VoIP::CALL_STATE_NONE; } - public function getCall($call) + /** + * Get call info. + * + * @param mixed $call Call ID + * + * @return array + */ + public function getCall($call): array { if (!\class_exists('\\danog\\MadelineProto\\VoIP')) { throw \danog\MadelineProto\Exception::extension('libtgvoip'); @@ -216,7 +286,17 @@ trait AuthKeyHandler return $this->calls[$call]; } - public function discardCallAsync($call, $reason, $rating = [], $need_debug = true) + /** + * Discard call. + * + * @param array $call Call + * @param string $reason Discard reason + * @param array $rating Rating + * @param boolean $need_debug Need debug? + * + * @return \Generator + */ + public function discardCallAsync($call, $reason, $rating = [], $need_debug = true): \Generator { if (!\class_exists('\\danog\\MadelineProto\\VoIP')) { throw \danog\MadelineProto\Exception::extension('libtgvoip'); @@ -249,7 +329,12 @@ trait AuthKeyHandler } unset($this->calls[$call['id']]); } - public function checkCalls() + /** + * Check state of calls. + * + * @return void + */ + public function checkCalls(): void { \array_walk($this->calls, function ($controller, $id) { if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) { diff --git a/src/danog/MadelineProto/Wrappers/ApiStart.php b/src/danog/MadelineProto/Wrappers/ApiStart.php index 7b1d4cc4..c0d68ea9 100644 --- a/src/danog/MadelineProto/Wrappers/ApiStart.php +++ b/src/danog/MadelineProto/Wrappers/ApiStart.php @@ -108,7 +108,7 @@ Note that you can also provide the API parameters directly in the code using the exit; } - public function webAPIPhoneLogin($settings) + private function webAPIPhoneLogin($settings) { try { $this->my_telegram_org_wrapper = new \danog\MadelineProto\MyTelegramOrgWrapper($settings); @@ -119,7 +119,7 @@ Note that you can also provide the API parameters directly in the code using the } } - public function webAPICompleteLogin() + private function webAPICompleteLogin() { try { yield $this->my_telegram_org_wrapper->completeLogin($_POST['code']); @@ -130,7 +130,7 @@ Note that you can also provide the API parameters directly in the code using the } } - public function webAPICreateApp() + private function webAPICreateApp() { try { $params = $_POST; diff --git a/src/danog/MadelineProto/Wrappers/ApiTemplates.php b/src/danog/MadelineProto/Wrappers/ApiTemplates.php index 04d0d16e..dc5eb723 100644 --- a/src/danog/MadelineProto/Wrappers/ApiTemplates.php +++ b/src/danog/MadelineProto/Wrappers/ApiTemplates.php @@ -38,22 +38,32 @@ trait ApiTemplates '; - public function webAPIEchoTemplate($message, $form) + private function webAPIEchoTemplate($message, $form) { return \sprintf($this->web_api_template, $message, $form); } - public function getWebAPITemplate() + /** + * Get web API login HTML template string. + * + * @return string + */ + public function getWebAPITemplate(): string { return $this->web_template; } - public function setWebAPITemplate($template) + /** + * Set web API login HTML template string. + * + * @return string + */ + public function setWebAPITemplate(string $template) { $this->web_template = $template; } - public function webAPIEcho($message = '') + private function webAPIEcho(string $message = '') { $stdout = getOutputBufferStream(); if (!isset($this->my_telegram_org_wrapper)) { diff --git a/src/danog/MadelineProto/Wrappers/Events.php b/src/danog/MadelineProto/Wrappers/Events.php index 03a2b435..084d0bcf 100644 --- a/src/danog/MadelineProto/Wrappers/Events.php +++ b/src/danog/MadelineProto/Wrappers/Events.php @@ -52,7 +52,7 @@ trait Events * * @return void */ - public function setEventHandler($event_handler) + public function setEventHandler($event_handler): void { if (!\class_exists($event_handler) || !\is_subclass_of($event_handler, '\danog\MadelineProto\EventHandler')) { throw new \danog\MadelineProto\Exception('Wrong event handler was defined'); diff --git a/src/danog/MadelineProto/Wrappers/Login.php b/src/danog/MadelineProto/Wrappers/Login.php index aec278e7..4474c4f1 100644 --- a/src/danog/MadelineProto/Wrappers/Login.php +++ b/src/danog/MadelineProto/Wrappers/Login.php @@ -27,7 +27,13 @@ use danog\MadelineProto\MTProtoTools\PasswordCalculator; */ trait Login { - public function logout() + + /** + * Log out currently logged in user. + * + * @return \Generator + */ + public function logout(): \Generator { yield $this->methodCallAsyncRead('auth.logOut', [], ['datacenter' => $this->datacenter->curdc]); $this->resetSession(); @@ -37,7 +43,14 @@ trait Login return true; } - public function botLogin($token) + /** + * Login as bot. + * + * @param string $token Bot token + * + * @return \Generator + */ + public function botLogin(string $token): \Generator { if ($this->authorized === self::LOGGED_IN) { $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['already_loggedIn'], \danog\MadelineProto\Logger::NOTICE); @@ -61,7 +74,15 @@ trait Login return $this->authorization; } - public function phoneLogin($number, $sms_type = 5) + /** + * Login as user. + * + * @param string $number Phone number + * @param integer $sms_type SMS type + * + * @return \Generator + */ + public function phoneLogin($number, $sms_type = 5): \Generator { if ($this->authorized === self::LOGGED_IN) { $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['already_loggedIn'], \danog\MadelineProto\Logger::NOTICE); @@ -80,7 +101,14 @@ trait Login return $this->authorization; } - public function completePhoneLogin($code) + /** + * Complet user login using login code. + * + * @param string $code Login code + * + * @return \Generator + */ + public function completePhoneLogin($code): \Generator { if ($this->authorized !== self::WAITING_CODE) { throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['login_code_uncalled']); @@ -131,7 +159,14 @@ trait Login return $this->authorization; } - public function importAuthorization($authorization) + /** + * Import authorization. + * + * @param mixed $authorization Authorization info + * + * @return \Generator + */ + public function importAuthorization($authorization): \Generator { if ($this->authorized === self::LOGGED_IN) { $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['already_loggedIn'], \danog\MadelineProto\Logger::NOTICE); @@ -166,7 +201,12 @@ trait Login return $res; } - public function exportAuthorization() + /** + * Export authorization. + * + * @return \Generator + */ + public function exportAuthorization(): \Generator { if ($this->authorized !== self::LOGGED_IN) { throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['not_loggedIn']); @@ -177,7 +217,15 @@ trait Login return [$this->datacenter->curdc, $this->datacenter->getDataCenterConnection($this->datacenter->curdc)->getPermAuthKey()->getAuthKey()]; } - public function completeSignup($first_name, $last_name) + /** + * Complete signup to Telegram. + * + * @param string $first_name First name + * @param string $last_name Last name + * + * @return \Generator + */ + public function completeSignup(string $first_name, string $last_name = ''): \Generator { if ($this->authorized !== self::WAITING_SIGNUP) { throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['signup_uncalled']); @@ -196,7 +244,14 @@ trait Login return $this->authorization; } - public function complete2faLogin($password) + /** + * Complete 2FA login. + * + * @param string $password Password + * + * @return \Generator + */ + public function complete2faLogin(string $password): \Generator { if ($this->authorized !== self::WAITING_PASSWORD) { throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['2fa_uncalled']); @@ -222,9 +277,10 @@ trait Login * The params array can contain password, new_password, email and hint params. * * @param array $params The params - * @return void + * + * @return \Generator */ - public function update2fa(array $params) + public function update2fa(array $params): \Generator { $hasher = new PasswordCalculator($this->logger); $hasher->addInfo(yield $this->methodCallAsyncRead('account.getPassword', [], ['datacenter' => $this->datacenter->curdc])); diff --git a/src/danog/MadelineProto/Wrappers/Start.php b/src/danog/MadelineProto/Wrappers/Start.php index 07dbb939..2275d3b2 100644 --- a/src/danog/MadelineProto/Wrappers/Start.php +++ b/src/danog/MadelineProto/Wrappers/Start.php @@ -88,7 +88,7 @@ trait Start exit; } - public function webPhoneLogin() + private function webPhoneLogin() { try { yield $this->phoneLogin($_POST['phone_number']); @@ -100,7 +100,7 @@ trait Start } } - public function webCompletePhoneLogin() + private function webCompletePhoneLogin() { try { yield $this->completePhoneLogin($_POST['phone_code']); @@ -112,7 +112,7 @@ trait Start } } - public function webComplete2faLogin() + private function webComplete2faLogin() { try { yield $this->complete2faLogin($_POST['password']); @@ -124,7 +124,7 @@ trait Start } } - public function webCompleteSignup() + private function webCompleteSignup() { try { yield $this->completeSignup($_POST['first_name'], isset($_POST['last_name']) ? $_POST['last_name'] : ''); @@ -136,7 +136,7 @@ trait Start } } - public function webBotLogin() + private function webBotLogin() { try { yield $this->botLogin($_POST['token']); diff --git a/src/danog/MadelineProto/Wrappers/Templates.php b/src/danog/MadelineProto/Wrappers/Templates.php index 11f1453c..7f60d8da 100644 --- a/src/danog/MadelineProto/Wrappers/Templates.php +++ b/src/danog/MadelineProto/Wrappers/Templates.php @@ -23,7 +23,7 @@ use function Amp\ByteStream\getOutputBufferStream; trait Templates { - public function webEcho(string $message = '') + private function webEcho(string $message = '') { $stdout = getOutputBufferStream(); switch ($this->authorized) { @@ -68,7 +68,7 @@ trait Templates '; - public function webEchoTemplate($message, $form): string + private function webEchoTemplate($message, $form): string { return \sprintf($this->web_template, $form, $message); } diff --git a/tests/testing.php b/tests/testing.php index 22d97a05..b647c855 100755 --- a/tests/testing.php +++ b/tests/testing.php @@ -64,218 +64,221 @@ $settings = \json_decode(\getenv('MTPROTO_SETTINGS'), true) ?: []; */ echo 'Loading MadelineProto...'.PHP_EOL; $MadelineProto = new \danog\MadelineProto\API(\getcwd().'/testing.madeline', $settings); -$MadelineProto->fileGetContents('https://google.com'); -$MadelineProto->start(); -$MadelineProto->async(false); +$MadelineProto->async(true); +$MadelineProto->loop(function () use ($MadelineProto) { + yield $MadelineProto->fileGetContents('https://google.com'); + yield $MadelineProto->start(); -try { - $MadelineProto->getSelf(); -} catch (\danog\MadelineProto\Exception $e) { - if ($e->getMessage() === 'TOS action required, check the logs') { - $MadelineProto->acceptTos(); + try { + yield $MadelineProto->getSelf(); + } catch (\danog\MadelineProto\Exception $e) { + if ($e->getMessage() === 'TOS action required, check the logs') { + yield $MadelineProto->acceptTos(); + } } -} -//var_dump(count($MadelineProto->getPwrChat('@madelineproto')['participants'])); + //var_dump(count($MadelineProto->getPwrChat('@madelineproto')['participants'])); -/* - * Test logging - */ -\danog\MadelineProto\Logger::log('hey', \danog\MadelineProto\Logger::ULTRA_VERBOSE); -\danog\MadelineProto\Logger::log('hey', \danog\MadelineProto\Logger::VERBOSE); -\danog\MadelineProto\Logger::log('hey', \danog\MadelineProto\Logger::NOTICE); -\danog\MadelineProto\Logger::log('hey', \danog\MadelineProto\Logger::WARNING); -\danog\MadelineProto\Logger::log('hey', \danog\MadelineProto\Logger::ERROR); -\danog\MadelineProto\Logger::log('hey', \danog\MadelineProto\Logger::FATAL_ERROR); + /* + * Test logging + */ + $MadelineProto->logger('hey', \danog\MadelineProto\Logger::ULTRA_VERBOSE); + $MadelineProto->logger('hey', \danog\MadelineProto\Logger::VERBOSE); + $MadelineProto->logger('hey', \danog\MadelineProto\Logger::NOTICE); + $MadelineProto->logger('hey', \danog\MadelineProto\Logger::WARNING); + $MadelineProto->logger('hey', \danog\MadelineProto\Logger::ERROR); + $MadelineProto->logger('hey', \danog\MadelineProto\Logger::FATAL_ERROR); -/** - * A small example message to use for tests. - */ -$message = (\getenv('TRAVIS_COMMIT') == '') ? 'I iz works always (io laborare sembre) (yo lavorar siempre) (mi labori ĉiam) (я всегда работать) (Ik werkuh altijd) (Ngimbonga ngaso sonke isikhathi ukusebenza)' : ('Travis ci tests in progress: commit '.\getenv('TRAVIS_COMMIT').', job '.\getenv('TRAVIS_JOB_NUMBER').', PHP version: '.\getenv('TRAVIS_PHP_VERSION')); + /** + * A small example message to use for tests. + */ + $message = (\getenv('TRAVIS_COMMIT') == '') ? 'I iz works always (io laborare sembre) (yo lavorar siempre) (mi labori ĉiam) (я всегда работать) (Ik werkuh altijd) (Ngimbonga ngaso sonke isikhathi ukusebenza)' : ('Travis ci tests in progress: commit '.\getenv('TRAVIS_COMMIT').', job '.\getenv('TRAVIS_JOB_NUMBER').', PHP version: '.\getenv('TRAVIS_PHP_VERSION')); -/* - * Try making a phone call - */ -if (!\getenv('TRAVIS_COMMIT') && \stripos($MadelineProto->readline('Do you want to make a call? (y/n): '), 'y') !== false) { - $controller = $MadelineProto->requestCall(\getenv('TEST_SECRET_CHAT'))->play('input.raw')->then('input.raw')->playOnHold(['input.raw'])->setOutputFile('output.raw'); - while ($controller->getCallState() < \danog\MadelineProto\VoIP::CALL_STATE_READY) { - $MadelineProto->getUpdates(); + /* + * Try making a phone call + */ + if (!\getenv('TRAVIS_COMMIT') && \stripos(yield $MadelineProto->readline('Do you want to make a call? (y/n): '), 'y') !== false) { + $controller = yield $MadelineProto->requestCall(\getenv('TEST_SECRET_CHAT'))->play('input.raw')->then('input.raw')->playOnHold(['input.raw'])->setOutputFile('output.raw'); + while ($controller->getCallState() < \danog\MadelineProto\VoIP::CALL_STATE_READY) { + yield $MadelineProto->getUpdates(); + } + $MadelineProto->logger($controller->configuration); + while ($controller->getCallState() < \danog\MadelineProto\VoIP::CALL_STATE_ENDED) { + yield $MadelineProto->getUpdates(); + } } - \danog\MadelineProto\Logger::log($controller->configuration); - while ($controller->getCallState() < \danog\MadelineProto\VoIP::CALL_STATE_ENDED) { - $MadelineProto->getUpdates(); - } -} -/* - * Try receiving a phone call - */ -if (!\getenv('TRAVIS_COMMIT') && \stripos($MadelineProto->readline('Do you want to handle incoming calls? (y/n): '), 'y') !== false) { - $howmany = $MadelineProto->readline('How many calls would you like me to handle? '); - $offset = 0; - while ($howmany > 0) { - $updates = $MadelineProto->getUpdates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout - foreach ($updates as $update) { - \danog\MadelineProto\Logger::log($update); - $offset = $update['update_id'] + 1; // Just like in the bot API, the offset must be set to the last update_id - switch ($update['update']['_']) { + /* + * Try receiving a phone call + */ + if (!\getenv('TRAVIS_COMMIT') && \stripos(yield $MadelineProto->readline('Do you want to handle incoming calls? (y/n): '), 'y') !== false) { + $howmany = yield $MadelineProto->readline('How many calls would you like me to handle? '); + $offset = 0; + while ($howmany > 0) { + $updates = yield $MadelineProto->getUpdates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]); // Just like in the bot API, you can specify an offset, a limit and a timeout + foreach ($updates as $update) { + $MadelineProto->logger($update); + $offset = $update['update_id'] + 1; // Just like in the bot API, the offset must be set to the last update_id + switch ($update['update']['_']) { case 'updatePhoneCall': if (\is_object($update['update']['phone_call']) && $update['update']['phone_call']->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_INCOMING) { $update['update']['phone_call']->accept()->play('input.raw')->then('input.raw')->playOnHold(['input.raw'])->setOutputFile('output.raw'); $howmany--; } } + } } } -} - -/* - * Secret chat usage - */ -if (!\getenv('TRAVIS_COMMIT') && \stripos($MadelineProto->readline('Do you want to make the secret chat tests? (y/n): '), 'y') !== false) { - /** - * Request a secret chat. - */ - $secret_chat_id = $MadelineProto->requestSecretChat(\getenv('TEST_SECRET_CHAT')); - echo 'Waiting for '.\getenv('TEST_SECRET_CHAT').' (secret chat id '.$secret_chat_id.') to accept the secret chat...'.PHP_EOL; /* - * Wait until the other party accepts it + * Secret chat usage */ - while ($MadelineProto->secretChatStatus($secret_chat_id) !== 2) { - $MadelineProto->getUpdates(); - } + if (!\getenv('TRAVIS_COMMIT') && \stripos(yield $MadelineProto->readline('Do you want to make the secret chat tests? (y/n): '), 'y') !== false) { + /** + * Request a secret chat. + */ + $secret_chat_id = yield $MadelineProto->requestSecretChat(\getenv('TEST_SECRET_CHAT')); + echo 'Waiting for '.\getenv('TEST_SECRET_CHAT').' (secret chat id '.$secret_chat_id.') to accept the secret chat...'.PHP_EOL; - /** - * Send a markdown-formatted text message with expiration after 10 seconds. - */ - $sentMessage = $MadelineProto->messages->sendEncrypted([ - 'peer' => $secret_chat_id, - 'message' => [ - '_' => 'decryptedMessage', - 'media' => ['_' => 'decryptedMessageMediaEmpty'], // No media - 'ttl' => 10, // This message self-destructs 10 seconds after reception - 'message' => '```'.$message.'```', // Code Markdown - 'parse_mode' => 'Markdown', - ], - ]); - \danog\MadelineProto\Logger::log($sentMessage, \danog\MadelineProto\Logger::NOTICE); + /* + * Wait until the other party accepts it + */ + while (yield $MadelineProto->secretChatStatus($secret_chat_id) !== 2) { + yield $MadelineProto->getUpdates(); + } - /** - * Send secret media. - */ - $secret_media = []; + /** + * Send a markdown-formatted text message with expiration after 10 seconds. + */ + $sentMessage = yield $MadelineProto->messages->sendEncrypted([ + 'peer' => $secret_chat_id, + 'message' => [ + '_' => 'decryptedMessage', + 'media' => ['_' => 'decryptedMessageMediaEmpty'], // No media + 'ttl' => 10, // This message self-destructs 10 seconds after reception + 'message' => '```'.$message.'```', // Code Markdown + 'parse_mode' => 'Markdown', + ], + ]); + $MadelineProto->logger($sentMessage, \danog\MadelineProto\Logger::NOTICE); - // Photo uploaded as document, secret chat - $secret_media['document_photo'] = [ - 'peer' => $secret_chat_id, - 'file' => 'tests/faust.jpg', // The file to send - 'message' => [ - '_' => 'decryptedMessage', - 'ttl' => 0, // This message does not self-destruct - 'message' => '', // No text message, only media - 'media' => [ - '_' => 'decryptedMessageMediaDocument', - 'thumb' => \file_get_contents('tests/faust.preview.jpg'), // The thumbnail must be generated manually, it must be in jpg format, 90x90 - 'thumb_w' => 90, - 'thumb_h' => 90, - 'mime_type' => \mime_content_type('tests/faust.jpg'), // The file's mime type - 'caption' => 'This file was uploaded using @MadelineProto', // The caption - 'file_name' => 'faust.jpg', // The file's name - 'size' => \filesize('tests/faust.jpg'), // The file's size - 'attributes' => [ - ['_' => 'documentAttributeImageSize', 'w' => 1280, 'h' => 914], // Image's resolution + /** + * Send secret media. + */ + $secret_media = []; + + // Photo uploaded as document, secret chat + $secret_media['document_photo'] = [ + 'peer' => $secret_chat_id, + 'file' => 'tests/faust.jpg', // The file to send + 'message' => [ + '_' => 'decryptedMessage', + 'ttl' => 0, // This message does not self-destruct + 'message' => '', // No text message, only media + 'media' => [ + '_' => 'decryptedMessageMediaDocument', + 'thumb' => \file_get_contents('tests/faust.preview.jpg'), // The thumbnail must be generated manually, it must be in jpg format, 90x90 + 'thumb_w' => 90, + 'thumb_h' => 90, + 'mime_type' => \mime_content_type('tests/faust.jpg'), // The file's mime type + 'caption' => 'This file was uploaded using @MadelineProto', // The caption + 'file_name' => 'faust.jpg', // The file's name + 'size' => \filesize('tests/faust.jpg'), // The file's size + 'attributes' => [ + ['_' => 'documentAttributeImageSize', 'w' => 1280, 'h' => 914], // Image's resolution + ], ], ], - ], - ]; + ]; - // Photo, secret chat - $secret_media['photo'] = [ - 'peer' => $secret_chat_id, - 'file' => 'tests/faust.jpg', - 'message' => [ - '_' => 'decryptedMessage', - 'ttl' => 0, - 'message' => '', - 'media' => [ - '_' => 'decryptedMessageMediaPhoto', - 'thumb' => \file_get_contents('tests/faust.preview.jpg'), - 'thumb_w' => 90, - 'thumb_h' => 90, - 'caption' => 'This file was uploaded using @MadelineProto', - 'size' => \filesize('tests/faust.jpg'), - 'w' => 1280, - 'h' => 914, + // Photo, secret chat + $secret_media['photo'] = [ + 'peer' => $secret_chat_id, + 'file' => 'tests/faust.jpg', + 'message' => [ + '_' => 'decryptedMessage', + 'ttl' => 0, + 'message' => '', + 'media' => [ + '_' => 'decryptedMessageMediaPhoto', + 'thumb' => \file_get_contents('tests/faust.preview.jpg'), + 'thumb_w' => 90, + 'thumb_h' => 90, + 'caption' => 'This file was uploaded using @MadelineProto', + 'size' => \filesize('tests/faust.jpg'), + 'w' => 1280, + 'h' => 914, + ], ], - ], - ]; + ]; - // GIF, secret chat - $secret_media['gif'] = ['peer' => $secret_chat_id, 'file' => 'tests/pony.mp4', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/pony.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => \mime_content_type('tests/pony.mp4'), 'caption' => 'test', 'file_name' => 'pony.mp4', 'size' => \filesize('tests/faust.jpg'), 'attributes' => [['_' => 'documentAttributeAnimated']]]]]; + // GIF, secret chat + $secret_media['gif'] = ['peer' => $secret_chat_id, 'file' => 'tests/pony.mp4', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/pony.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => \mime_content_type('tests/pony.mp4'), 'caption' => 'test', 'file_name' => 'pony.mp4', 'size' => \filesize('tests/faust.jpg'), 'attributes' => [['_' => 'documentAttributeAnimated']]]]]; - // Sticker, secret chat - $secret_media['sticker'] = ['peer' => $secret_chat_id, 'file' => 'tests/lel.webp', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/lel.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => \mime_content_type('tests/lel.webp'), 'caption' => 'test', 'file_name' => 'lel.webp', 'size' => \filesize('tests/lel.webp'), 'attributes' => [['_' => 'documentAttributeSticker', 'alt' => 'LEL', 'stickerset' => ['_' => 'inputStickerSetEmpty']]]]]]; + // Sticker, secret chat + $secret_media['sticker'] = ['peer' => $secret_chat_id, 'file' => 'tests/lel.webp', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/lel.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => \mime_content_type('tests/lel.webp'), 'caption' => 'test', 'file_name' => 'lel.webp', 'size' => \filesize('tests/lel.webp'), 'attributes' => [['_' => 'documentAttributeSticker', 'alt' => 'LEL', 'stickerset' => ['_' => 'inputStickerSetEmpty']]]]]]; - // Document, secret chat - $secret_media['document'] = ['peer' => $secret_chat_id, 'file' => 'tests/60', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/faust.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => 'magic/magic', 'caption' => 'test', 'file_name' => 'magic.magic', 'size' => \filesize('tests/60'), 'attributes' => [['_' => 'documentAttributeFilename', 'file_name' => 'fairy']]]]]; + // Document, secret chat + $secret_media['document'] = ['peer' => $secret_chat_id, 'file' => 'tests/60', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/faust.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => 'magic/magic', 'caption' => 'test', 'file_name' => 'magic.magic', 'size' => \filesize('tests/60'), 'attributes' => [['_' => 'documentAttributeFilename', 'file_name' => 'fairy']]]]]; - // Video, secret chat - $secret_media['video'] = ['peer' => $secret_chat_id, 'file' => 'tests/swing.mp4', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/swing.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => \mime_content_type('tests/swing.mp4'), 'caption' => 'test', 'file_name' => 'swing.mp4', 'size' => \filesize('tests/swing.mp4'), 'attributes' => [['_' => 'documentAttributeVideo']]]]]; + // Video, secret chat + $secret_media['video'] = ['peer' => $secret_chat_id, 'file' => 'tests/swing.mp4', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/swing.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => \mime_content_type('tests/swing.mp4'), 'caption' => 'test', 'file_name' => 'swing.mp4', 'size' => \filesize('tests/swing.mp4'), 'attributes' => [['_' => 'documentAttributeVideo']]]]]; - // audio, secret chat - $secret_media['audio'] = ['peer' => $secret_chat_id, 'file' => 'tests/mosconi.mp3', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/faust.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => \mime_content_type('tests/mosconi.mp3'), 'caption' => 'test', 'file_name' => 'mosconi.mp3', 'size' => \filesize('tests/mosconi.mp3'), 'attributes' => [['_' => 'documentAttributeAudio', 'voice' => false, 'title' => 'AH NON LO SO IO', 'performer' => 'IL DIO GERMANO MOSCONI']]]]]; - $secret_media['voice'] = ['peer' => $secret_chat_id, 'file' => 'tests/mosconi.mp3', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/faust.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => \mime_content_type('tests/mosconi.mp3'), 'caption' => 'test', 'file_name' => 'mosconi.mp3', 'size' => \filesize('tests/mosconi.mp3'), 'attributes' => [['_' => 'documentAttributeAudio', 'voice' => true, 'title' => 'AH NON LO SO IO', 'performer' => 'IL DIO GERMANO MOSCONI']]]]]; + // audio, secret chat + $secret_media['audio'] = ['peer' => $secret_chat_id, 'file' => 'tests/mosconi.mp3', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/faust.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => \mime_content_type('tests/mosconi.mp3'), 'caption' => 'test', 'file_name' => 'mosconi.mp3', 'size' => \filesize('tests/mosconi.mp3'), 'attributes' => [['_' => 'documentAttributeAudio', 'voice' => false, 'title' => 'AH NON LO SO IO', 'performer' => 'IL DIO GERMANO MOSCONI']]]]]; + $secret_media['voice'] = ['peer' => $secret_chat_id, 'file' => 'tests/mosconi.mp3', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/faust.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => \mime_content_type('tests/mosconi.mp3'), 'caption' => 'test', 'file_name' => 'mosconi.mp3', 'size' => \filesize('tests/mosconi.mp3'), 'attributes' => [['_' => 'documentAttributeAudio', 'voice' => true, 'title' => 'AH NON LO SO IO', 'performer' => 'IL DIO GERMANO MOSCONI']]]]]; - foreach ($secret_media as $type => $smessage) { - \danog\MadelineProto\Logger::log("Encrypting and uploading $type..."); - $type = $MadelineProto->messages->sendEncryptedFile($smessage); + foreach ($secret_media as $type => $smessage) { + $MadelineProto->logger("Encrypting and uploading $type..."); + $type = yield $MadelineProto->messages->sendEncryptedFile($smessage); + } } -} -$mention = $MadelineProto->getInfo(\getenv('TEST_USERNAME')); // Returns an array with all of the constructors that can be extracted from a username or an id -$mention = $mention['user_id']; // Selects only the numeric user id -$media = []; + $mention = yield $MadelineProto->getInfo(\getenv('TEST_USERNAME')); // Returns an array with all of the constructors that can be extracted from a username or an id + $mention = $mention['user_id']; // Selects only the numeric user id + $media = []; -// Image -$media['photo'] = ['_' => 'inputMediaUploadedPhoto', 'file' => 'tests/faust.jpg']; + // Image + $media['photo'] = ['_' => 'inputMediaUploadedPhoto', 'file' => 'tests/faust.jpg']; -// Sticker -$media['sticker'] = ['_' => 'inputMediaUploadedDocument', 'file' => 'tests/lel.webp', 'attributes' => [['_' => 'documentAttributeSticker', 'alt' => 'LEL']]]; + // Sticker + $media['sticker'] = ['_' => 'inputMediaUploadedDocument', 'file' => 'tests/lel.webp', 'attributes' => [['_' => 'documentAttributeSticker', 'alt' => 'LEL']]]; -// Video -$media['video'] = ['_' => 'inputMediaUploadedDocument', 'file' => 'tests/swing.mp4', 'attributes' => [['_' => 'documentAttributeVideo']]]; + // Video + $media['video'] = ['_' => 'inputMediaUploadedDocument', 'file' => 'tests/swing.mp4', 'attributes' => [['_' => 'documentAttributeVideo']]]; -// audio -$media['audio'] = ['_' => 'inputMediaUploadedDocument', 'file' => 'tests/mosconi.mp3', 'attributes' => [['_' => 'documentAttributeAudio', 'voice' => false, 'title' => 'AH NON LO SO IO', 'performer' => 'IL DIO GERMANO MOSCONI']]]; + // audio + $media['audio'] = ['_' => 'inputMediaUploadedDocument', 'file' => 'tests/mosconi.mp3', 'attributes' => [['_' => 'documentAttributeAudio', 'voice' => false, 'title' => 'AH NON LO SO IO', 'performer' => 'IL DIO GERMANO MOSCONI']]]; -// voice -$media['voice'] = ['_' => 'inputMediaUploadedDocument', 'file' => 'tests/mosconi.mp3', 'attributes' => [['_' => 'documentAttributeAudio', 'voice' => true, 'title' => 'AH NON LO SO IO', 'performer' => 'IL DIO GERMANO MOSCONI']]]; + // voice + $media['voice'] = ['_' => 'inputMediaUploadedDocument', 'file' => 'tests/mosconi.mp3', 'attributes' => [['_' => 'documentAttributeAudio', 'voice' => true, 'title' => 'AH NON LO SO IO', 'performer' => 'IL DIO GERMANO MOSCONI']]]; -// Document -$media['document'] = ['_' => 'inputMediaUploadedDocument', 'file' => 'tests/60', 'mime_type' => 'magic/magic', 'attributes' => [['_' => 'documentAttributeFilename', 'file_name' => 'magic.magic']]]; + // Document + $media['document'] = ['_' => 'inputMediaUploadedDocument', 'file' => 'tests/60', 'mime_type' => 'magic/magic', 'attributes' => [['_' => 'documentAttributeFilename', 'file_name' => 'magic.magic']]]; -$message = 'yay '.\PHP_VERSION_ID; -$mention = $MadelineProto->getInfo(\getenv('TEST_USERNAME')); // Returns an array with all of the constructors that can be extracted from a username or an id -$mention = $mention['user_id']; // Selects only the numeric user id + $message = 'yay '.\PHP_VERSION_ID; + $mention = yield $MadelineProto->getInfo(\getenv('TEST_USERNAME')); // Returns an array with all of the constructors that can be extracted from a username or an id + $mention = $mention['user_id']; // Selects only the numeric user id /* $t = time(); -$MadelineProto->upload('big'); +yield $MadelineProto->upload('big'); var_dump(time()-$t); */ -foreach (\json_decode(\getenv('TEST_DESTINATION_GROUPS'), true) as $peer) { - $sentMessage = $MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => $message, 'entities' => [['_' => 'inputMessageEntityMentionName', 'offset' => 0, 'length' => \mb_strlen($message), 'user_id' => $mention]]]); - \danog\MadelineProto\Logger::log($sentMessage, \danog\MadelineProto\Logger::NOTICE); + foreach (\json_decode(\getenv('TEST_DESTINATION_GROUPS'), true) as $peer) { + $sentMessage = yield $MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => $message, 'entities' => [['_' => 'inputMessageEntityMentionName', 'offset' => 0, 'length' => \mb_strlen($message), 'user_id' => $mention]]]); + $MadelineProto->logger($sentMessage, \danog\MadelineProto\Logger::NOTICE); - foreach ($media as $type => $inputMedia) { - \danog\MadelineProto\Logger::log("Sending $type"); - $type = $MadelineProto->messages->sendMedia(['peer' => $peer, 'media' => $inputMedia, 'message' => '['.$message.'](mention:'.$mention.')', 'parse_mode' => 'markdown']); + foreach ($media as $type => $inputMedia) { + $MadelineProto->logger("Sending $type"); + $type = yield $MadelineProto->messages->sendMedia(['peer' => $peer, 'media' => $inputMedia, 'message' => '['.$message.'](mention:'.$mention.')', 'parse_mode' => 'markdown']); + yield $MadelineProto->downloadToDir(yield $MadelineProto->messages->uploadMedia(['peer' => '@me', 'media' => $inputMedia]), '/tmp'); + } } -} -foreach (\json_decode(\getenv('TEST_DESTINATION_GROUPS'), true) as $peer) { - $sentMessage = $MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => $message, 'entities' => [['_' => 'inputMessageEntityMentionName', 'offset' => 0, 'length' => \mb_strlen($message), 'user_id' => $mention]]]); - \danog\MadelineProto\Logger::log($sentMessage, \danog\MadelineProto\Logger::NOTICE); -} + foreach (\json_decode(\getenv('TEST_DESTINATION_GROUPS'), true) as $peer) { + $sentMessage = yield $MadelineProto->messages->sendMessage(['peer' => $peer, 'message' => $message, 'entities' => [['_' => 'inputMessageEntityMentionName', 'offset' => 0, 'length' => \mb_strlen($message), 'user_id' => $mention]]]); + $MadelineProto->logger($sentMessage, \danog\MadelineProto\Logger::NOTICE); + } +});