. * * @author Daniil Gentili * @copyright 2016-2023 Daniil Gentili * @license https://opensource.org/licenses/AGPL-3.0 AGPLv3 * @link https://docs.madelineproto.xyz MadelineProto documentation */ namespace danog\MadelineProto\MTProto; use Amp\Future; /** * Incoming message. * * @internal */ final class IncomingMessage extends Message { /** * We have received this message. */ const STATE_RECEIVED = 4; /** * We have acknowledged this message. */ const STATE_ACKED = 8; /** * We have read the contents of this message. */ const STATE_READ = 128; /** * Response field map. */ private const RESPONSE_ID_MAP = [ 'rpc_result' => 'req_msg_id', 'future_salts' => 'req_msg_id', 'msgs_state_info' => 'req_msg_id', 'bad_server_salt' => 'bad_msg_id', 'bad_msg_notification' => 'bad_msg_id', 'pong' => 'msg_id', ]; /** * State. */ private int $state = self::STATE_RECEIVED; /** * Receive date. */ private int $received; /** * Deserialized response content. */ private array $content; /** * Was present in container. */ private bool $fromContainer; private ?Future $sideEffects = null; /** * Constructor. * * @param array $content Content * @param boolean $fromContainer Whether this message was in a container */ public function __construct(array $content, int $msgId, bool $fromContainer = false) { $this->content = $content; $this->fromContainer = $fromContainer; $this->msgId = $msgId; $this->received = \time(); $this->contentRelated = !isset(Message::NOT_CONTENT_RELATED[$content['_']]); if (!$this->contentRelated) { $this->state |= 16; // message not requiring acknowledgment } } public function setSideEffects(?Future $sideEffects): void { $this->sideEffects = $sideEffects; } public function consumeSideEffects(): ?Future { $side = $this->sideEffects; $this->sideEffects = null; return $side; } /** * Get deserialized response content. */ public function getContent(): array { return $this->content; } /** * Get was present in container. */ public function isFromContainer(): bool { return $this->fromContainer; } /** * Get log line. * * @param int $dc DC ID */ public function log(int $dc): string { if ($this->fromContainer) { return "Inside of container, received {$this->content['_']} from DC $dc"; } return "Received {$this->content['_']} from DC $dc"; } /** * Get message type. */ public function getType(): string { return $this->content['_']; } /** * Get message type. */ public function __toString(): string { return "incoming message {$this->content['_']}"; } /** * We have acked this message. */ public function ack(): void { $this->state |= self::STATE_ACKED; } /** * Read this message, clearing its contents. */ public function read(): array { $this->state |= self::STATE_READ; $content = $this->content; $this->content = ['_' => $content['_']]; return $content; } /** * Check if this message can be garbage collected. */ public function canGarbageCollect(): bool { return (bool) ($this->state & self::STATE_READ); } /** * Get ID of message to which this message replies. */ public function getRequestId(): int { return $this->content[self::RESPONSE_ID_MAP[$this->content['_']]]; } /** * Get state. */ public function getState(): int { return $this->state; } /** * Get receive date. */ public function getReceived(): int { return $this->received; } }