diff --git a/src/Loop/Connection/CheckLoop.php b/src/Loop/Connection/CheckLoop.php index 5264299aa..d784068f3 100644 --- a/src/Loop/Connection/CheckLoop.php +++ b/src/Loop/Connection/CheckLoop.php @@ -106,7 +106,13 @@ final class CheckLoop extends Loop $this->connection->methodRecall(message_id: $message_id, postpone: true); break; case 4: - if ($chr & 32) { + if ($chr & 128) { + $this->logger->logger("Message $message received by server and was already sent, requesting reply...", Logger::ERROR); + $reply[] = $message_id; + } elseif ($chr & 64) { + $this->logger->logger("Message $message received by server and was already processed, requesting reply...", Logger::ERROR); + $reply[] = $message_id; + } elseif ($chr & 32) { if ($message->getSent() + $this->resendTimeout < \time()) { if ($message->isCancellationRequested()) { unset($this->connection->new_outgoing[$message_id], $this->connection->outgoing_messages[$message_id]); @@ -119,12 +125,6 @@ final class CheckLoop extends Loop } else { $this->logger->logger("Message $message received by server and is being processed, waiting...", Logger::ERROR); } - } elseif ($chr & 64) { - $this->logger->logger("Message $message received by server and was already processed, requesting reply...", Logger::ERROR); - $reply[] = $message_id; - } elseif ($chr & 128) { - $this->logger->logger("Message $message received by server and was already sent, requesting reply...", Logger::ERROR); - $reply[] = $message_id; } else { $this->logger->logger("Message $message received by server, waiting...", Logger::ERROR); $reply[] = $message_id; diff --git a/src/MTProtoTools/PeerHandler.php b/src/MTProtoTools/PeerHandler.php index 5f98518b1..2b96f9eeb 100644 --- a/src/MTProtoTools/PeerHandler.php +++ b/src/MTProtoTools/PeerHandler.php @@ -308,10 +308,10 @@ trait PeerHandler return DialogId::fromSupergroupOrChannel((int) $matches[1]); } if (\preg_match('/^chat#(\\d*)/', $id, $matches)) { - $id = '-'.$matches[1]; + return -((int) $matches[1]); } if (\preg_match('/^user#(\\d*)/', $id, $matches)) { - return $matches[1]; + return (int) $matches[1]; } } } diff --git a/src/TL/TL.php b/src/TL/TL.php index 3a5f77b46..cc25d7549 100644 --- a/src/TL/TL.php +++ b/src/TL/TL.php @@ -642,32 +642,37 @@ final class TL implements TLInterface { $serialized = ''; $arguments = $this->API->botAPIToMTProto($arguments instanceof Button ? $arguments->jsonSerialize() : $arguments); - foreach ($tl['params'] as $cur_flag) { - if (isset($cur_flag['pow'])) { - $arguments[$cur_flag['flag']] ??= 0; - switch ($cur_flag['type']) { - case 'true': - $arguments[$cur_flag['flag']] = isset($arguments[$cur_flag['name']]) && $arguments[$cur_flag['name']] ? $arguments[$cur_flag['flag']] | $cur_flag['pow'] : $arguments[$cur_flag['flag']] & ~$cur_flag['pow']; - unset($arguments[$cur_flag['name']]); - break; - default: - $arguments[$cur_flag['flag']] = isset($arguments[$cur_flag['name']]) && $arguments[$cur_flag['name']] !== null ? $arguments[$cur_flag['flag']] | $cur_flag['pow'] : $arguments[$cur_flag['flag']] & ~$cur_flag['pow']; - break; - } + foreach ($tl['flags'] as [ + 'flag' => $flag, + 'name' => $name, + 'type' => $type, + 'pow' => $pow + ]) { + $arguments[$flag] ??= 0; + if ($type === 'true') { + $arguments[$flag] = isset($arguments[$name]) && $arguments[$name] + ? $arguments[$flag] | $pow + : $arguments[$flag] & ~$pow; + } else { + $arguments[$flag] = isset($arguments[$name]) && $arguments[$name] !== null + ? $arguments[$flag] | $pow + : $arguments[$flag] & ~$pow; } } foreach ($tl['params'] as $current_argument) { - if (!isset($arguments[$current_argument['name']])) { - if (isset($current_argument['pow']) && ($current_argument['type'] === 'true' || ($arguments[$current_argument['flag']] & $current_argument['pow']) === 0)) { - //$this->API->logger->logger('Skipping '.$current_argument['name'].' of type '.$current_argument['type'); + $name = $current_argument['name']; + $type = $current_argument['type']; + if (!isset($arguments[$name])) { + if (isset($current_argument['pow']) && ($type === 'true' || ($arguments[$current_argument['flag']] & $current_argument['pow']) === 0)) { + //$this->API->logger->logger('Skipping '.$name.' of type '.$current_argument['type'); continue; } - if ($current_argument['name'] === 'random_bytes') { + if ($name === 'random_bytes') { $serialized .= $this->serializeObject(['type' => 'bytes'], Tools::random(15 + 4 * Tools::randomInt(modulus: 3)), 'random_bytes'); continue; } - if ($current_argument['name'] === 'random_id') { - switch ($current_argument['type']) { + if ($name === 'random_id') { + switch ($type) { case 'long': $serialized .= Tools::random(8); continue 2; @@ -683,59 +688,60 @@ final class TL implements TLInterface } } } - if ($current_argument['type'] === 'long') { + if ($type === 'long') { $serialized .= "\0\0\0\0\0\0\0\0"; continue; } - if ($current_argument['type'] === 'double') { + if ($type === 'double') { $serialized .= "\0\0\0\0\0\0\0\0"; continue; } - if ($tl['type'] === 'InputMedia' && $current_argument['name'] === 'mime_type') { - $serialized .= ($this->serializeObject($current_argument, $arguments['file']['mime_type'], $current_argument['name'], $layer)); + if ($tl['type'] === 'InputMedia' && $name === 'mime_type') { + $serialized .= ($this->serializeObject($current_argument, $arguments['file']['mime_type'], $name, $layer)); continue; } - if (\in_array($current_argument['type'], ['bytes', 'string', 'int'], true)) { + if (\in_array($type, ['bytes', 'string', 'int'], true)) { $serialized .= "\0\0\0\0"; continue; } - if (($id = $this->constructors->findByPredicate(\lcfirst($current_argument['type']).'Empty', $tl['layer'] ?? -1)) && $id['type'] === $current_argument['type']) { + if (($id = $this->constructors->findByPredicate(\lcfirst($type).'Empty', $tl['layer'] ?? -1)) && $id['type'] === $type) { $serialized .= $id['id']; continue; } - if (($id = $this->constructors->findByPredicate('input'.$current_argument['type'].'Empty', $tl['layer'] ?? -1)) && $id['type'] === $current_argument['type']) { + if (($id = $this->constructors->findByPredicate('input'.$type.'Empty', $tl['layer'] ?? -1)) && $id['type'] === $type) { $serialized .= $id['id']; continue; } - switch ($current_argument['type']) { + switch ($type) { case 'Vector t': case 'vector': - $arguments[$current_argument['name']] = []; + $value = []; break; case 'DataJSON': case '%DataJSON': - $arguments[$current_argument['name']] = null; + $value = null; break; default: - throw new Exception(Lang::$current_lang['params_missing'].' '.$current_argument['name']); + throw new Exception(Lang::$current_lang['params_missing'].' '.$name); } + } else { + $value = $arguments[$name]; } - if (\in_array($current_argument['type'], ['DataJSON', '%DataJSON'], true)) { - $arguments[$current_argument['name']] = ['_' => 'dataJSON', 'data' => \json_encode($arguments[$current_argument['name']])]; + if (\in_array($type, ['DataJSON', '%DataJSON'], true)) { + $value = ['_' => 'dataJSON', 'data' => \json_encode($value)]; } if (isset($current_argument['subtype']) && \in_array($current_argument['subtype'], ['DataJSON', '%DataJSON'], true)) { - \array_walk($arguments[$current_argument['name']], function (&$arg): void { + \array_walk($value, function (&$arg): void { $arg = ['_' => 'dataJSON', 'data' => \json_encode($arg)]; }); } - if ($current_argument['type'] === 'InputFile' && (!\is_array($arguments[$current_argument['name']]) || !(isset($arguments[$current_argument['name']]['_']) && $this->constructors->findByPredicate($arguments[$current_argument['name']]['_'])['type'] === 'InputFile'))) { - $arguments[$current_argument['name']] = ($this->API->upload($arguments[$current_argument['name']])); + if ($type === 'InputFile' && (!\is_array($value) || !(isset($value['_']) && $this->constructors->findByPredicate($value['_'])['type'] === 'InputFile'))) { + $value = ($this->API->upload($value)); } - if ($current_argument['type'] === 'InputEncryptedChat' && (!\is_array($arguments[$current_argument['name']]) || isset($arguments[$current_argument['name']]['_']) && $this->constructors->findByPredicate($arguments[$current_argument['name']]['_'])['type'] !== $current_argument['type'])) { - $arguments[$current_argument['name']] = $this->API->getSecretChatController($arguments[$current_argument['name']])->inputChat; + if ($type === 'InputEncryptedChat' && (!\is_array($value) || isset($value['_']) && $this->constructors->findByPredicate($value['_'])['type'] !== $type)) { + $value = $this->API->getSecretChatController($value)->inputChat; } - //$this->API->logger->logger('Serializing '.$current_argument['name'].' of type '.$current_argument['type'); - $serialized .= ($this->serializeObject($current_argument, $arguments[$current_argument['name']], $current_argument['name'], $layer)); + $serialized .= ($this->serializeObject($current_argument, $value, $name, $layer)); } return $serialized; } diff --git a/src/TL/TLConstructors.php b/src/TL/TLConstructors.php index 8565d7784..14b43b109 100644 --- a/src/TL/TLConstructors.php +++ b/src/TL/TLConstructors.php @@ -42,6 +42,7 @@ final class TLConstructors $this->by_id[$json_dict['id']] = [ 'predicate' => $predicate, 'params' => $json_dict['params'], + 'flags' => [], 'type' => ($scheme_type === 'mtproto' && $json_dict['type'] === 'Message' ? 'MT' : '').$json_dict['type'], 'encrypted' => $scheme_type !== 'mtproto' ]; diff --git a/src/TL/TLMethods.php b/src/TL/TLMethods.php index fe7aad7f2..5f7eed384 100644 --- a/src/TL/TLMethods.php +++ b/src/TL/TLMethods.php @@ -39,6 +39,7 @@ final class TLMethods 'method' => $json_dict['method'], 'type' => $json_dict['type'], 'params' => $json_dict['params'], + 'flags' => [], 'encrypted' => $scheme_type !== 'mtproto' ]; $this->by_method[$json_dict['method']] = $json_dict['id']; diff --git a/src/TL/TLParams.php b/src/TL/TLParams.php index 946a9ae5b..56dcaf506 100644 --- a/src/TL/TLParams.php +++ b/src/TL/TLParams.php @@ -59,6 +59,9 @@ trait TLParams } $this->by_id[$key]['params'][$kkey] = $param; + if (isset($param['pow'])) { + $this->by_id[$key]['flags'][$kkey] = $param; + } } } }