Final fixes, and update to latest version of websocket lib

This commit is contained in:
Daniil Gentili 2020-10-04 16:27:22 +02:00
parent d49f59eec5
commit d31b798df9
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
36 changed files with 251 additions and 173 deletions

View File

@ -40,7 +40,8 @@
"danog/loop": "^0.1.0",
"danog/tgseclib": "^3",
"amphp/redis": "^1.0",
"symfony/polyfill-php80": "^1.18"
"symfony/polyfill-php80": "^1.18",
"amphp/websocket-client": "^1.0"
},
"require-dev": {
"vlucas/phpdotenv": "^3",
@ -51,8 +52,6 @@
"haydenpierce/class-finder": "^0.4",
"amphp/http-server": "dev-master",
"amphp/http": "^1.6",
"amphp/websocket-client": "dev-master as 1",
"amphp/websocket": "dev-master as 1",
"ext-ctype": "*",
"danog/7to70": "^1",
"danog/7to5": "^1",

View File

@ -1,65 +0,0 @@
<?php
/**
* Async parameters class.
*
* This file is part of MadelineProto.
* MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Affero General Public License for more details.
* You should have received a copy of the GNU General Public License along with MadelineProto.
* If not, see <http://www.gnu.org/licenses/>.
*
* @author Daniil Gentili <daniil@daniil.it>
* @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
* @license https://opensource.org/licenses/AGPL-3.0 AGPLv3
*
* @link https://docs.madelineproto.xyz MadelineProto documentation
*/
namespace danog\MadelineProto\Async;
/**
* Async parameters class.
*
* Manages asynchronous generation of method parameters
*
* @author Daniil Gentili <daniil@daniil.it>
*/
class AsyncParameters
{
/**
* Async callable.
*
* @var callable
*/
private $callable;
/**
* Create async parameters.
*
* @param callable $callable Async callable that will return parameters
*/
public function __construct(callable $callable)
{
$this->callable = $callable;
}
/**
* Create async parameters.
*
* @param callable $callable Async callable that will return parameters
*/
public function setCallable(callable $callable): void
{
$this->callable = $callable;
}
/**
* Get parameters asynchronously.
*
* @return \Generator<array>|\Amp\Promise<array>
*/
public function getParameters()
{
$callable = $this->callable;
return $callable();
}
}

View File

@ -393,7 +393,9 @@ class Connection
{
$deferred = new Deferred();
if (!isset($message['serialized_body'])) {
$body = \is_object($message['body']) ? yield from $message['body'] : $message['body'];
$body = $message['body'] instanceof \Generator
? yield from $message['body']
: $message['body'];
$refreshNext = $message['refreshReferences'] ?? false;
if ($refreshNext) {
$this->API->referenceDatabase->refreshNext(true);

View File

@ -122,7 +122,7 @@ class DataCenter
/**
* DoH connector.
*/
private Rfc6455Connector $webSocketConnnector;
private Rfc6455Connector $webSocketConnector;
public function __sleep()
{
@ -238,7 +238,7 @@ class DataCenter
$this->dnsConnector = new DnsConnector(new Rfc1035StubResolver());
if (\class_exists(Rfc6455Connector::class)) {
$this->webSocketConnnector = new Rfc6455Connector($this->HTTPClient);
$this->webSocketConnector = new Rfc6455Connector($this->HTTPClient);
}
}
$this->settings->applyChanges();
@ -420,6 +420,7 @@ class DataCenter
if ($stream[0] === DefaultStream::class && $stream[1] === []) {
$stream[1] = $useDoH ? new DoHConnector($this, $ctx) : $this->dnsConnector;
}
/** @var array{0: class-string, 1: mixed} $stream */
$ctx->addStream(...$stream);
}
$ctxs[] = $ctx;
@ -480,8 +481,9 @@ class DataCenter
if (!\class_exists(Handshake::class)) {
throw new Exception('Please install amphp/websocket-client by running "composer require amphp/websocket-client:dev-master"');
}
$stream[1] = $this->webSocketConnnector;
$stream[1] = $this->webSocketConnector;
}
/** @var array{0: class-string, 1: mixed} $stream */
$ctx->addStream(...$stream);
}
$ctxs[] = $ctx;

View File

@ -7,8 +7,6 @@ use danog\MadelineProto\Logger;
/**
* Array caching trait.
*
* @property string $table
*/
trait ArrayCacheTrait
{
@ -94,8 +92,8 @@ trait ArrayCacheTrait
Logger::log(
\sprintf(
"cache for table:%s; keys left: %s; keys removed: %s",
$this->table,
"cache for table: %s; keys left: %s; keys removed: %s",
(string) $this,
\count($this->cache),
$oldCount
),

View File

@ -8,8 +8,6 @@ use ReflectionClass;
/**
* Array caching trait.
*
* @property string $table
*/
abstract class DriverArray implements DbArray
{
@ -20,6 +18,12 @@ abstract class DriverArray implements DbArray
$this->stopCacheCleanupLoop();
}
/**
* Get string representation of driver/table.
*
* @return string
*/
abstract public function __toString(): string;
public function __wakeup()
{
@ -62,7 +66,7 @@ abstract class DriverArray implements DbArray
$counter++;
if ($counter % 500 === 0) {
yield $new->offsetSet($key, $item);
Logger::log("Loading data to table {$new->table}: $counter/$total", Logger::WARNING);
Logger::log("Loading data to table {$new}: $counter/$total", Logger::WARNING);
} else {
$new->offsetSet($key, $item);
}

View File

@ -22,6 +22,20 @@ class MysqlArray extends SqlArray
// Legacy
protected array $settings;
/**
* Initialize on startup.
*
* @return \Generator
*/
public function initStartup(): \Generator
{
return $this->initConnection($this->dbSettings);
}
public function __toString(): string
{
return $this->table;
}
public function __sleep(): array
{
return ['table', 'dbSettings'];

View File

@ -22,6 +22,19 @@ class PostgresArray extends SqlArray
// Legacy
protected array $settings;
/**
* Initialize on startup.
*
* @return \Generator
*/
public function initStartup(): \Generator
{
return $this->initConnection($this->dbSettings);
}
public function __toString(): string
{
return $this->table;
}
/**
* Initialize connection.
*

View File

@ -15,13 +15,25 @@ use function Amp\call;
class RedisArray extends SqlArray
{
protected string $table;
protected DatabaseRedis $dbSettings;
private RedisRedis $db;
// Legacy
protected array $settings;
/**
* Initialize on startup.
*
* @return \Generator
*/
public function initStartup(): \Generator
{
return $this->initConnection($this->dbSettings);
}
public function __toString(): string
{
return $this->table;
}
/**
* @return Generator
*

View File

@ -9,6 +9,8 @@ use function Amp\call;
abstract class SqlArray extends DriverArray
{
protected string $table;
/**
* Create table for property.
*
@ -20,15 +22,6 @@ abstract class SqlArray extends DriverArray
abstract protected function renameTable(string $from, string $to): \Generator;
/**
* Initialize on startup.
*
* @return \Generator
*/
public function initStartup(): \Generator
{
return $this->initConnection($this->dbSettings);
}
/**
* @param string $name
@ -37,7 +30,7 @@ abstract class SqlArray extends DriverArray
* @param DatabaseAbstract $settings
*
* @return Promise
*
*
* @psalm-return Promise<static>
*/
public static function getInstance(string $name, $value = null, string $tablePrefix = '', $settings): Promise
@ -50,6 +43,7 @@ abstract class SqlArray extends DriverArray
$instance->table = $tableName;
}
/** @psalm-suppress UndefinedPropertyAssignment */
$instance->dbSettings = $settings;
$instance->ttl = $settings->getCacheTtl();

View File

@ -117,13 +117,13 @@ class DoHConnector implements Connector
foreach ($uris as $builtUri) {
try {
$streamContext = \stream_context_create($socketContext->withoutTlsContext()->toStreamContextArray());
/** @psalm-ignore NullArgument */
/** @psalm-suppress NullArgument */
if (!($socket = @\stream_socket_client($builtUri, $errno, $errstr, null, $flags, $streamContext))) {
throw new ConnectException(\sprintf('Connection to %s failed: [Error #%d] %s%s', $uri, $errno, $errstr, $failures ? '; previous attempts: '.\implode($failures) : ''), $errno);
}
\stream_set_blocking($socket, false);
$deferred = new Deferred();
/** @psalm-ignore InvalidArgument */
/** @psalm-suppress InvalidArgument */
$watcher = Loop::onWritable($socket, [$deferred, 'resolve']);
$id = $token->subscribe([$deferred, 'fail']);
try {

View File

@ -33,9 +33,9 @@ interface FileCallbackInterface
/**
* Invoke callback.
*
* @param int $percent Percent
* @param int $speed Speed in mbps
* @param int $time Time
* @param float $percent Percent
* @param float $speed Speed in mbps
* @param float $time Time
*
* @return mixed
*/

View File

@ -5172,7 +5172,7 @@ class InternalDoc extends APIFactory
*/
public function getExtensionFromLocation($location, string $default): string
{
return \danog\MadelineProto\MTProto::getExtensionFromLocation($location, $default);
return \danog\MadelineProto\TL\Conversion\Extension::getExtensionFromLocation($location, $default);
}
/**
* Get extension from mime type.
@ -5183,7 +5183,7 @@ class InternalDoc extends APIFactory
*/
public function getExtensionFromMime(string $mime): string
{
return \danog\MadelineProto\MTProto::getExtensionFromMime($mime);
return \danog\MadelineProto\TL\Conversion\Extension::getExtensionFromMime($mime);
}
/**
* Get info about file.
@ -5272,7 +5272,21 @@ class InternalDoc extends APIFactory
*
* @return \Amp\Promise Info object
*
* @psalm-return \Amp\Promise<array|mixed>
* @psalm-return \Generator<int|mixed, \Amp\Promise|\Amp\Promise<string>|array, mixed, array{
* InputPeer: array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed},
* Peer: array{_: string, user_id?: mixed, chat_id?: mixed, channel_id?: mixed},
* DialogPeer: array{_: string, peer: array{_: string, user_id?: mixed, chat_id?: mixed, channel_id?: mixed}},
* NotifyPeer: array{_: string, peer: array{_: string, user_id?: mixed, chat_id?: mixed, channel_id?: mixed}},
* InputDialogPeer: array{_: string, peer: array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed}},
* InputNotifyPeer: array{_: string, peer: array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed}},
* bot_api_id: int|string,
* user_id?: int,
* chat_id?: int,
* channel_id?: int,
* InputUser?: {_: string, user_id?: int, access_hash?: mixed, min?: bool},
* InputChannel?: {_: string, channel_id: int, access_hash: mixed, min: bool},
* type: string
* }>
*/
public function getInfo($id, $recursive = true, array $extra = [])
{
@ -5312,7 +5326,7 @@ class InternalDoc extends APIFactory
*/
public function getMimeFromBuffer(string $buffer): string
{
return \danog\MadelineProto\MTProto::getMimeFromBuffer($buffer);
return \danog\MadelineProto\TL\Conversion\Extension::getMimeFromBuffer($buffer);
}
/**
* Get mime type from file extension.
@ -5324,7 +5338,7 @@ class InternalDoc extends APIFactory
*/
public function getMimeFromExtension(string $extension, string $default): string
{
return \danog\MadelineProto\MTProto::getMimeFromExtension($extension, $default);
return \danog\MadelineProto\TL\Conversion\Extension::getMimeFromExtension($extension, $default);
}
/**
* Get mime type of file.
@ -5335,7 +5349,7 @@ class InternalDoc extends APIFactory
*/
public function getMimeFromFile(string $file): string
{
return \danog\MadelineProto\MTProto::getMimeFromFile($file);
return \danog\MadelineProto\TL\Conversion\Extension::getMimeFromFile($file);
}
/**
* Get download info of the propic of a user
@ -5670,9 +5684,11 @@ class InternalDoc extends APIFactory
*
* If the $aargs['noResponse'] is true, will not wait for a response.
*
* @param string $method Method name
* @param array $args Arguments
* @param array $aargs Additional arguments
* @param string $method Method name
* @param array|\Generator $args Arguments
* @param array $aargs Additional arguments
*
* @psalm-param array|\Generator<mixed, mixed, mixed, array> $args
*
* @return \Amp\Promise
*/
@ -5686,9 +5702,11 @@ class InternalDoc extends APIFactory
/**
* Call method and make sure it is asynchronously sent.
*
* @param string $method Method name
* @param array $args Arguments
* @param array $aargs Additional arguments
* @param string $method Method name
* @param array|\Generator $args Arguments
* @param array $aargs Additional arguments
*
* @psalm-param array|\Generator<mixed, mixed, mixed, array> $args
*
* @return \Amp\Promise
*/

View File

@ -18,14 +18,16 @@ class FileCallback extends Obj implements FileCallbackInterface
/**
* Invoke callback.
*
* @param int $percent Percent
* @param int $speed Speed in mbps
* @param int $time Time
* @param float $percent Percent
* @param float $speed Speed in mbps
* @param float $time Time
*
* @psalm-suppress MethodSignatureMismatch
*
* @return mixed
*/
public function __invoke(...$args)
public function __invoke($percent, $speed, $time)
{
return $this->__call('__invoke', $args);
return $this->__call('__invoke', [$percent, $speed, $time]);
}
}

View File

@ -21,6 +21,7 @@ namespace danog\MadelineProto\Loop\Update;
use danog\Loop\ResumableSignalLoop;
use danog\MadelineProto\Loop\InternalLoop;
use danog\MadelineProto\MTProtoTools\UpdatesState;
/**
* update feed loop.
@ -42,6 +43,10 @@ class SeqLoop extends ResumableSignalLoop
* Pending updates.
*/
private array $pendingWakeups = [];
/**
* State.
*/
private ?UpdatesState $state = null;
/**
* Main loop.
*

File diff suppressed because one or more lines are too long

View File

@ -20,7 +20,6 @@
namespace danog\MadelineProto\MTProtoSession;
use Amp\Deferred;
use danog\MadelineProto\Async\AsyncParameters;
use danog\MadelineProto\TL\Exception;
use danog\MadelineProto\Tools;
@ -79,9 +78,11 @@ trait CallHandler
*
* If the $aargs['noResponse'] is true, will not wait for a response.
*
* @param string $method Method name
* @param array $args Arguments
* @param array $aargs Additional arguments
* @param string $method Method name
* @param array|\Generator $args Arguments
* @param array $aargs Additional arguments
*
* @psalm-param array|\Generator<mixed, mixed, mixed, array> $args
*
* @return \Generator
*/
@ -100,9 +101,11 @@ trait CallHandler
/**
* Call method and make sure it is asynchronously sent (generator).
*
* @param string $method Method name
* @param array $args Arguments
* @param array $aargs Additional arguments
* @param string $method Method name
* @param array|\Generator $args Arguments
* @param array $aargs Additional arguments
*
* @psalm-param array|\Generator<mixed, mixed, mixed, array> $args
*
* @return \Generator
*/
@ -160,6 +163,7 @@ trait CallHandler
$aargs,
[
'_' => $method,
'body' => $args,
'type' => $methodInfo['type'],
'contentRelated' => $this->contentRelated($method),
'promise' => $deferred,
@ -167,16 +171,11 @@ trait CallHandler
'unencrypted' => !$this->shared->hasTempAuthKey() && \strpos($method, '.') === false
]
);
if (\is_object($args) && $args instanceof AsyncParameters) {
$message['body'] = yield $args->fetchParameters();
} else {
$message['body'] = $args;
}
if ($method === 'users.getUsers' && $args === ['id' => [['_' => 'inputUserSelf']]] || $method === 'auth.exportAuthorization' || $method === 'updates.getDifference') {
$message['user_related'] = true;
}
$aargs['postpone'] = $aargs['postpone'] ?? false;
$deferred = (yield from $this->sendMessage($message, !$aargs['postpone']));
$deferred = yield from $this->sendMessage($message, !$aargs['postpone']);
$this->checker->resume();
return $deferred;
}

View File

@ -229,6 +229,7 @@ trait AuthKeyHandler
* Separate answer and hash
*/
$answer_hash = \substr($answer_with_hash, 0, 20);
/** @var string */
$answer = \substr($answer_with_hash, 20);
/*
* ***********************************************************************
@ -553,6 +554,7 @@ trait AuthKeyHandler
foreach ($dcs as $id => &$dc) {
$dc = $dc();
}
/** @var \Generator[] $dcs */
yield \danog\MadelineProto\Tools::all($dcs);
foreach ($postpone as $id => $socket) {
yield from $this->initAuthorizationSocket($id, $socket);

View File

@ -31,9 +31,11 @@ trait CallHandler
/**
* Synchronous wrapper for methodCall.
*
* @param string $method Method name
* @param array $args Arguments
* @param array $aargs Additional arguments
* @param string $method Method name
* @param array|\Generator $args Arguments
* @param array $aargs Additional arguments
*
* @psalm-param array|\Generator<mixed, mixed, mixed, array> $args
*
* @return mixed
*/
@ -46,9 +48,11 @@ trait CallHandler
*
* If the $aargs['noResponse'] is true, will not wait for a response.
*
* @param string $method Method name
* @param array $args Arguments
* @param array $aargs Additional arguments
* @param string $method Method name
* @param array|\Generator $args Arguments
* @param array $aargs Additional arguments
*
* @psalm-param array|\Generator<mixed, mixed, mixed, array> $args
*
* @return \Generator
*/
@ -59,9 +63,11 @@ trait CallHandler
/**
* Call method and make sure it is asynchronously sent.
*
* @param string $method Method name
* @param array $args Arguments
* @param array $aargs Additional arguments
* @param string $method Method name
* @param array|\Generator $args Arguments
* @param array $aargs Additional arguments
*
* @psalm-param array|\Generator<mixed, mixed, mixed, array> $args
*
* @return \Generator
*/

View File

@ -172,7 +172,9 @@ trait Files
$exception = null;
$start = \microtime(true);
while ($part_num < $part_total_num) {
$writePromise = Tools::call($this->methodCallAsyncWrite($method, $callable($part_num), ['heavy' => true, 'file' => true, 'datacenter' => &$datacenter]));
$resa = $callable($part_num);
\var_dump($resa);
$writePromise = Tools::call($this->methodCallAsyncWrite($method, $resa, ['heavy' => true, 'file' => true, 'datacenter' => &$datacenter]));
if (!$seekable) {
yield $writePromise;
}
@ -622,10 +624,10 @@ trait Files
}
}
if (!isset($res['ext']) || $res['ext'] === '') {
$res['ext'] = $this->getExtensionFromLocation($res['InputFileLocation'], $this->getExtensionFromMime($res['mime'] ?? 'image/jpeg'));
$res['ext'] = Tools::getExtensionFromLocation($res['InputFileLocation'], Tools::getExtensionFromMime($res['mime'] ?? 'image/jpeg'));
}
if (!isset($res['mime']) || $res['mime'] === '') {
$res['mime'] = $this->getMimeFromExtension($res['ext'], 'image/jpeg');
$res['mime'] = Tools::getMimeFromExtension($res['ext'], 'image/jpeg');
}
if (!isset($res['name']) || $res['name'] === '') {
$res['name'] = Tools::unpackSignedLongString($messageMedia['file']['access_hash']);
@ -680,8 +682,8 @@ trait Files
$res['thumb_size'] = $messageMedia['type'];
if ($messageMedia['location']['_'] === 'fileLocationUnavailable') {
$res['name'] = Tools::unpackSignedLongString($messageMedia['volume_id']).'_'.$messageMedia['local_id'];
$res['mime'] = $this->getMimeFromBuffer($res['data']);
$res['ext'] = $this->getExtensionFromMime($res['mime']);
$res['mime'] = Tools::getMimeFromBuffer($res['data']);
$res['ext'] = TOols::getExtensionFromMime($res['mime']);
} else {
$res = \array_merge($res, yield from $this->getDownloadInfo($messageMedia['location']));
}
@ -699,13 +701,13 @@ trait Files
case 'fileLocation':
$res['name'] = Tools::unpackSignedLongString($messageMedia['volume_id']).'_'.$messageMedia['local_id'];
$res['InputFileLocation'] = ['_' => 'inputFileLocation', 'volume_id' => $messageMedia['volume_id'], 'local_id' => $messageMedia['local_id'], 'secret' => $messageMedia['secret'], 'dc_id' => $messageMedia['dc_id'], 'file_reference' => yield from $this->referenceDatabase->getReference(ReferenceDatabase::PHOTO_LOCATION_LOCATION, $messageMedia)];
$res['ext'] = $this->getExtensionFromLocation($res['InputFileLocation'], '.jpg');
$res['mime'] = $this->getMimeFromExtension($res['ext'], 'image/jpeg');
$res['ext'] = Tools::getExtensionFromLocation($res['InputFileLocation'], '.jpg');
$res['mime'] = Tools::getMimeFromExtension($res['ext'], 'image/jpeg');
return $res;
case 'fileLocationToBeDeprecated':
$res['name'] = Tools::unpackSignedLongString($messageMedia['volume_id']).'_'.$messageMedia['local_id'];
$res['ext'] = '.jpg';
$res['mime'] = $this->getMimeFromExtension($res['ext'], 'image/jpeg');
$res['mime'] = Tools::getMimeFromExtension($res['ext'], 'image/jpeg');
$res['InputFileLocation'] = [
'_' => 'inputFileLocationTemp',
// Will be overwritten
@ -742,7 +744,7 @@ trait Files
}
$res['InputFileLocation'] = ['_' => 'inputDocumentFileLocation', 'id' => $messageMedia['document']['id'], 'access_hash' => $messageMedia['document']['access_hash'], 'version' => isset($messageMedia['document']['version']) ? $messageMedia['document']['version'] : 0, 'dc_id' => $messageMedia['document']['dc_id'], 'file_reference' => yield from $this->referenceDatabase->getReference(ReferenceDatabase::DOCUMENT_LOCATION, $messageMedia['document'])];
if (!isset($res['ext']) || $res['ext'] === '') {
$res['ext'] = $this->getExtensionFromLocation($res['InputFileLocation'], $this->getExtensionFromMime($messageMedia['document']['mime_type']));
$res['ext'] = Tools::getExtensionFromLocation($res['InputFileLocation'], Tools::getExtensionFromMime($messageMedia['document']['mime_type']));
}
if (!isset($res['name']) || $res['name'] === '') {
$res['name'] = Tools::unpackSignedLongString($messageMedia['document']['access_hash']);
@ -962,7 +964,7 @@ trait Files
* @param array $messageMedia File object
* @param bool $cdn Whether this is a CDN file
* @param string $datacenter DC ID
* @param string $old_dc Previous DC ID
* @param ?string $old_dc Previous DC ID
* @param AES $ige IGE decryptor instance
* @param callable $cb Status callback
* @param array $offset Offset

View File

@ -25,6 +25,7 @@ use danog\MadelineProto\Stream\Common\BufferedRawStream;
use danog\MadelineProto\Stream\Common\SimpleBufferedRawStream;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\Transport\PremadeStream;
use danog\MadelineProto\TL\Conversion\Extension;
use danog\MadelineProto\Tools;
@ -245,7 +246,7 @@ trait FilesLogic
throw new \danog\MadelineProto\Exception('Given file is too big!');
}
$stream = yield open($file, 'rb');
$mime = $this->getMimeFromFile($file);
$mime = Extension::getMimeFromFile($file);
try {
return yield from $this->uploadFromStream($stream, $size, $mime, $fileName, $cb, $encrypted);
} finally {

View File

@ -432,7 +432,7 @@ trait PeerHandler
case 'contact':
return $id['user_id'];
case 'updatePhoneCall':
return $id->getOtherID();
return $id['phone_call']->getOtherID();
case 'updateReadHistoryInbox':
case 'updateReadHistoryOutbox':
return $this->getId($id['peer']);

View File

@ -155,7 +155,7 @@ trait UpdateHandler
*
* @internal
*
* @return \Generator
* @return \Generator<mixed, mixed, mixed, UpdatesState>
*/
public function loadUpdateState(): \Generator
{

View File

@ -104,11 +104,17 @@ class MyTelegramOrgWrapper
$this->settings = new Settings;
} elseif (\is_array($this->settings)) {
$this->settings = Settings::parseFromLegacy($this->settings);
if (!$this->settings instanceof Settings) {
$settings = new Settings;
$settings->merge($this->settings);
$this->settings = $settings;
}
}
if (!$this->jar || !$this->jar instanceof InMemoryCookieJar) {
$this->jar = new InMemoryCookieJar();
}
$this->datacenter = new DataCenter(new class(new Logger($this->settings->getLogger())) {
public Logger $logger;
public function __construct(Logger $logger)
{
$this->logger = $logger;
@ -347,7 +353,7 @@ class MyTelegramOrgWrapper
* @param string $name Function name
* @param array $arguments Arguments
*
* @return void
* @return mixed
*/
public function __call(string $name, array $arguments)
{

View File

@ -106,7 +106,7 @@ class SessionPaths
* @param string $path Object path, defaults to session path
*
* @return \Generator
*
*
* @psalm-return \Generator<mixed, mixed, mixed, object>
*/
public function unserialize(string $path = ''): \Generator

View File

@ -19,10 +19,12 @@
namespace danog\MadelineProto;
use danog\MadelineProto\TL\Conversion\Extension;
/**
* Some tools.
*/
abstract class StrTools
abstract class StrTools extends Extension
{
/**
* Convert to camelCase.

View File

@ -42,7 +42,6 @@ use danog\MadelineProto\Stream\WriteBufferInterface;
class UdpBufferedStream extends DefaultStream implements BufferedStreamInterface, MTProtoBufferInterface
{
use BufferedStream;
private RawStreamInterface $stream;
/**
* Connect to stream.
*
@ -72,7 +71,7 @@ class UdpBufferedStream extends DefaultStream implements BufferedStreamInterface
*
* @psalm-return \Generator<int, Promise, mixed, Failure<mixed>|Success<object>>
*/
public function getReadBuffer(&$length): \Generator
public function getReadBufferGenerator(&$length): \Generator
{
if (!$this->stream) {
return new Failure(new ClosedException("MadelineProto stream was disconnected"));
@ -185,7 +184,7 @@ class UdpBufferedStream extends DefaultStream implements BufferedStreamInterface
*/
public function getSocket(): EncryptableSocket
{
return $this->stream->getSocket();
return $this->getSocket();
}
/**
* {@inheritDoc}
@ -194,7 +193,7 @@ class UdpBufferedStream extends DefaultStream implements BufferedStreamInterface
*/
public function getStream(): RawStreamInterface
{
return $this->stream;
return $this;
}
public static function getName(): string
{

View File

@ -100,7 +100,7 @@ class ConnectionContext
/**
* An array of arrays containing an array with the stream name and the extra parameter to pass to it.
*
* @var array<array<string, mixed>>
* @var array<0: class-string, 1: mixed>[]
*/
private $nextStreams = [];
/**
@ -344,7 +344,9 @@ class ConnectionContext
* Add a stream to the stream chain.
*
* @param string $streamName
* @param mixed $extra
* @param mixed $extra
*
* @psalm-param class-string $streamName
*
* @return self
*/

View File

@ -38,7 +38,7 @@ class HttpStream implements MTProtoBufferInterface, BufferedProxyStreamInterface
{
use BufferedStream;
/**
* Stream
* Stream.
*
* @var RawStreamInterface
*/

View File

@ -19,11 +19,14 @@
namespace danog\MadelineProto\Stream\Transport;
use Amp\Http\Client\HttpClientBuilder;
use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use Amp\Websocket\Client\Connection;
use Amp\Websocket\Client\Connector;
use Amp\Websocket\Client\Handshake;
use Amp\Websocket\Client\Rfc6455Connector;
use Amp\Websocket\ClosedException;
use Amp\Websocket\Message;
use danog\MadelineProto\Stream\Async\RawStream;
use danog\MadelineProto\Stream\ConnectionContext;
@ -73,7 +76,7 @@ class WsStream implements RawStreamInterface, ProxyStreamInterface
$uri = $ctx->getStringUri();
$uri = \str_replace('tcp://', $ctx->isSecure() ? 'wss://' : 'ws://', $uri);
$handshake = new Handshake($uri);
$this->stream = yield ($this->connector ?? connector())->connect($handshake, $ctx->getCancellationToken());
$this->stream = yield ($this->connector ?? new Rfc6455Connector(HttpClientBuilder::buildDefault()))->connect($handshake, $ctx->getCancellationToken());
if (\strlen($header)) {
yield $this->write($header);
}
@ -100,7 +103,7 @@ class WsStream implements RawStreamInterface, ProxyStreamInterface
$this->message = null;
}
} catch (\Throwable $e) {
if ($e instanceof Amp\Websocket\ClosedException && $e->getReason() !== 'Client closed the underlying TCP connection') {
if ($e instanceof ClosedException && $e->getReason() !== 'Client closed the underlying TCP connection') {
throw $e;
}
return null;

View File

@ -22,6 +22,7 @@ namespace danog\MadelineProto\TL\Conversion;
use danog\Decoder\FileId;
use danog\MadelineProto\Logger;
use danog\MadelineProto\MTProtoTools\PeerHandler;
use danog\MadelineProto\Tools;
use const danog\Decoder\TYPES_IDS;
@ -387,7 +388,7 @@ trait BotAPI
$res['file_name'] .= $res['ext'];
unset($res['ext']);
} else {
$res['file_name'] .= $this->getExtensionFromMime($data['document']['mime_type']);
$res['file_name'] .= Tools::getExtensionFromMime($data['document']['mime_type']);
}
$res['file_size'] = $data['document']['size'];
$res['mime_type'] = $data['document']['mime_type'];
@ -698,9 +699,8 @@ trait BotAPI
$delimOffset = 0;
foreach ($initialArray as $item) {
$delimOffset += $this->mbStrlen($item);
//if ($this->mbStrlen($item) > 0) {
/** @var int $delimOffset */
$finalArray[] = $item.($delimOffset < $this->mbStrlen($string) ? $string[$delimOffset] : '');
//}
$delimOffset++;
}
return $finalArray;

File diff suppressed because one or more lines are too long

View File

@ -787,8 +787,8 @@ class TL
/**
* Get length of TL payload.
*
* @param resource $stream Stream
* @param array $type Type identifier
* @param resource|string $stream Stream
* @param array $type Type identifier
*
* @return int
*/

View File

@ -26,6 +26,8 @@ class Button implements \JsonSerializable, \ArrayAccess
{
/**
* Button data.
*
* @psalm-var non-empty-array<array-key, mixed>
*/
private array $button;
/**
@ -139,7 +141,7 @@ class Button implements \JsonSerializable, \ArrayAccess
*
* @param $name Field name
*
* @return void
* @return mixed
*/
public function offsetGet($name)
{

View File

@ -88,7 +88,7 @@ class APIFactory extends AbstractAPIFactory
*
* @param string $name Method name
* @param array $arguments Arguments
*
* @psalm-suppress UndefinedThisPropertyFetch
* @return \Generator
*/
public function __call_async(string $name, array $arguments): \Generator

View File

@ -1105,6 +1105,29 @@ class InternalDoc extends APIFactory
{
return \danog\MadelineProto\Tools::genVectorHash($ints);
}
/**
* 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 \danog\MadelineProto\TL\Conversion\Extension::getExtensionFromLocation($location, $default);
}
/**
* Get extension from mime type.
*
* @param string $mime MIME type
*
* @return string
*/
public function getExtensionFromMime(string $mime): string
{
return \danog\MadelineProto\TL\Conversion\Extension::getExtensionFromMime($mime);
}
/**
* Get TL method namespaces.
*
@ -1114,6 +1137,40 @@ class InternalDoc extends APIFactory
{
return $this->API->getMethodNamespaces();
}
/**
* Get mime type from buffer.
*
* @param string $buffer Buffer
*
* @return string
*/
public function getMimeFromBuffer(string $buffer): string
{
return \danog\MadelineProto\TL\Conversion\Extension::getMimeFromBuffer($buffer);
}
/**
* 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
{
return \danog\MadelineProto\TL\Conversion\Extension::getMimeFromExtension($extension, $default);
}
/**
* Get mime type of file.
*
* @param string $file File
*
* @return string
*/
public function getMimeFromFile(string $file): string
{
return \danog\MadelineProto\TL\Conversion\Extension::getMimeFromFile($file);
}
/**
* Accesses a private variable from an object.
*