diff --git a/bot.php b/bot.php index b08e8d9f..33cbc70b 100755 --- a/bot.php +++ b/bot.php @@ -46,19 +46,6 @@ class EventHandler extends \danog\MadelineProto\EventHandler yield $this->messages->sendMessage(['peer' => $update, 'message' => "$res", 'reply_to_msg_id' => isset($update['message']['id']) ? $update['message']['id'] : null, 'parse_mode' => 'HTML']); //'entities' => [['_' => 'messageEntityPre', 'offset' => 0, 'length' => strlen($res), 'language' => 'json']]]); if (isset($update['message']['media']) && $update['message']['media']['_'] !== 'messageMediaGame') { yield $this->messages->sendMedia(['peer' => $update, 'message' => $update['message']['message'], 'media' => $update]); - yield $this->messages->sendMedia([ - 'peer' => '@danogentili', - 'media' => [ - '_' => 'inputMediaUploadedDocument', - 'file' => 'https://google.com', - 'attributes' => [ - ['_' => 'documentAttributeFilename', 'file_name' => 'document.txt'] - ] - ], - 'message' => '[This is the caption](https://t.me/MadelineProto)', - 'parse_mode' => 'Markdown' - ]); - //yield $this->download_to_dir($update, '/tmp'); } } catch (\danog\MadelineProto\RPCErrorException $e) { diff --git a/docs b/docs index cbd913fb..dc05dc5c 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit cbd913fba2249a0055bb732452a67f911119c40a +Subproject commit dc05dc5cebfcec90ac7851928c522a4d635dbab6 diff --git a/src/danog/MadelineProto/MTProtoTools/Files.php b/src/danog/MadelineProto/MTProtoTools/Files.php index 2c3d3478..4e9aa90d 100644 --- a/src/danog/MadelineProto/MTProtoTools/Files.php +++ b/src/danog/MadelineProto/MTProtoTools/Files.php @@ -34,7 +34,7 @@ use danog\MadelineProto\Exception; use danog\MadelineProto\FileCallbackInterface; use danog\MadelineProto\Logger; use danog\MadelineProto\RPCErrorException; -use danog\MadelineProto\Stream\Common\BufferedRawStream; +use danog\MadelineProto\Stream\Common\SimpleBufferedRawStream; use danog\MadelineProto\Stream\ConnectionContext; use danog\MadelineProto\Stream\Transport\PremadeStream; use function Amp\File\exists; @@ -43,6 +43,7 @@ use function Amp\File\stat; use function Amp\File\touch; use function Amp\Promise\all; use Amp\File\BlockingHandle; +use Amp\Artax\Client; /** * Manages upload and download of files. @@ -94,7 +95,7 @@ trait Files $url = $url->getFile(); } /** @var $response \Amp\Artax\Response */ - $response = yield $this->datacenter->getHTTPClient()->request($url); + $response = yield $this->datacenter->getHTTPClient()->request($url, [Client::OP_MAX_BODY_BYTES => 512 * 1024 * 3000, Client::OP_TRANSFER_TIMEOUT => 10*1000*3600]); if (200 !== $status = $response->getStatus()) { throw new Exception("Wrong status code: $status ".$response->getReason()); } @@ -103,6 +104,8 @@ trait Files $stream = $response->getBody(); if (!$size) { + $this->logger->logger("No content length for $url, caching first"); + $body = $stream; $stream = new BlockingHandle(fopen('php://temp', 'r+b'), 'php://temp', 'r+b'); @@ -141,7 +144,9 @@ trait Files } } - if ($stream instanceof Handle || $stream instanceof BufferedRawStream) { + $created = false; + + if ($stream instanceof Handle) { $callable = static function (int $offset, int $size) use ($stream, $seekable) { if ($seekable) { while ($stream->tell() !== $offset) { @@ -151,18 +156,30 @@ trait Files return yield $stream->read($size); }; } else { - $ctx = (new ConnectionContext) - ->addStream(PremadeStream::getName(), $stream) - ->addStream(BufferedRawStream::getName()); - - $stream = yield $ctx->getStream(); - + if (!$stream instanceof BufferedRawStream) { + $ctx = (new ConnectionContext) + ->addStream(PremadeStream::getName(), $stream) + ->addStream(SimpleBufferedRawStream::getName()); + $stream = yield $ctx->getStream(); + $created = true; + } $callable = static function (int $offset, int $size) use ($stream) { - return yield $stream->read($size); + $reader = yield $stream->getReadBuffer($l); + try { + return yield $reader->bufferRead($size); + } catch (\danog\MadelineProto\NothingInTheSocketException $e) { + $reader = yield $stream->getReadBuffer($size); + return yield $reader->bufferRead($size); + } }; + $seekable = false; } - return yield $this->upload_from_callable_async($callable, $size, $mime, $file_name, $cb, $seekable, $encrypted); + $res = yield $this->upload_from_callable_async($callable, $size, $mime, $file_name, $cb, $seekable, $encrypted); + if ($created) { + $stream->disconnect(); + } + return $res; } public function upload_from_callable_async($callable, int $size, string $mime, string $file_name = '', $cb = null, bool $refetchable = true, bool $encrypted = false) { diff --git a/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php b/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php index 0c0eeaf1..9f0b7728 100644 --- a/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php +++ b/src/danog/MadelineProto/MTProtoTools/ResponseHandler.php @@ -368,6 +368,10 @@ trait ResponseHandler return; } + if (in_array($response['error_message'], ['MSGID_DECREASE_RETRY', 'RPC_CALL_FAIL', 'RPC_MCGET_FAIL', 'no workers running'])) { + Loop::delay(1 * 1000, [$this, 'method_recall'], ['message_id' => $request_id, 'datacenter' => $datacenter]); + return; + } $this->got_response_for_outgoing_message_id($request_id, $datacenter); $this->handle_reject($datacenter, $request, new \danog\MadelineProto\RPCErrorException($response['error_message'], $response['error_code'], isset($request['_']) ? $request['_'] : '')); diff --git a/src/danog/MadelineProto/Stream/Common/SimpleBufferedRawStream.php b/src/danog/MadelineProto/Stream/Common/SimpleBufferedRawStream.php new file mode 100644 index 00000000..f55d0b71 --- /dev/null +++ b/src/danog/MadelineProto/Stream/Common/SimpleBufferedRawStream.php @@ -0,0 +1,77 @@ +. + * + * @author Daniil Gentili + * @copyright 2016-2019 Daniil Gentili + * @license https://opensource.org/licenses/AGPL-3.0 AGPLv3 + * + * @link https://docs.madelineproto.xyz MadelineProto documentation + */ + +namespace danog\MadelineProto\Stream\Common; + +use Amp\Promise; +use Amp\Success; +use danog\MadelineProto\Exception; +use danog\MadelineProto\Stream\Async\RawStream; +use danog\MadelineProto\Stream\ConnectionContext; +use function Amp\Socket\connect; +use danog\MadelineProto\Stream\BufferedStreamInterface; +use danog\MadelineProto\Stream\BufferInterface; +use danog\MadelineProto\Stream\RawStreamInterface; + +/** + * Buffered raw stream. + * + * @author Daniil Gentili + */ +class SimpleBufferedRawStream extends BufferedRawStream implements BufferedStreamInterface, BufferInterface, RawStreamInterface +{ + /** + * Read data asynchronously. + * + * @param int $length Amount of data to read + * + * @return \Generator + */ + public function bufferReadAsync(int $length): \Generator + { + $size = fstat($this->memory_stream)['size']; + $offset = ftell($this->memory_stream); + $buffer_length = $size - $offset; + if ($buffer_length < $length && $buffer_length) { + fseek($this->memory_stream, $offset + $buffer_length); + } + + while ($buffer_length < $length) { + $chunk = yield $this->read(); + if ($chunk === null) { + fseek($this->memory_stream, $offset); + break; + } + fwrite($this->memory_stream, $chunk); + $buffer_length += strlen($chunk); + } + fseek($this->memory_stream, $offset); + + return fread($this->memory_stream, $length); + } + + /** + * Get class name. + * + * @return string + */ + public static function getName(): string + { + return __CLASS__; + } +} diff --git a/src/danog/MadelineProto/Stream/Transport/PremadeStream.php b/src/danog/MadelineProto/Stream/Transport/PremadeStream.php index 7fd2dc8d..ee2faf60 100644 --- a/src/danog/MadelineProto/Stream/Transport/PremadeStream.php +++ b/src/danog/MadelineProto/Stream/Transport/PremadeStream.php @@ -95,7 +95,9 @@ class PremadeStream extends Socket implements RawStreamInterface, ProxyStreamInt { try { if ($this->stream) { - $this->stream->close(); + if (method_exists($this->stream, 'close')) { + $this->stream->close(); + } $this->stream = null; } } catch (\Throwable $e) { diff --git a/src/danog/MadelineProto/VoIP/AuthKeyHandler.php b/src/danog/MadelineProto/VoIP/AuthKeyHandler.php index 3d25a39d..27eb379e 100644 --- a/src/danog/MadelineProto/VoIP/AuthKeyHandler.php +++ b/src/danog/MadelineProto/VoIP/AuthKeyHandler.php @@ -191,7 +191,6 @@ trait AuthKeyHandler $visualization[] = \danog\MadelineProto\Magic::$emojis[(int) (new \phpseclib\Math\BigInteger($number, 256))->divide($length)[1]->toString()]; } $this->calls[$params['id']]->setVisualization($visualization); - var_dump($params); $this->calls[$params['id']]->configuration['endpoints'] = array_merge($params['connections'], $this->calls[$params['id']]->configuration['endpoints']); $this->calls[$params['id']]->configuration = array_merge(['recv_timeout' => $this->config['call_receive_timeout_ms'] / 1000, 'init_timeout' => $this->config['call_connect_timeout_ms'] / 1000, 'data_saving' => \danog\MadelineProto\VoIP::DATA_SAVING_NEVER, 'enable_NS' => true, 'enable_AEC' => true, 'enable_AGC' => true, 'auth_key' => $key, 'auth_key_id' => substr(sha1($key, true), -8), 'call_id' => substr(hash('sha256', $key, true), -16), 'network_type' => \danog\MadelineProto\VoIP::NET_TYPE_ETHERNET], $this->calls[$params['id']]->configuration); $this->calls[$params['id']]->parseConfig();