Some more improvements

This commit is contained in:
Daniil Gentili 2020-10-08 11:27:37 +02:00
parent 787f06a314
commit 662f521409
Signed by: danog
GPG Key ID: 8C1BE3B34B230CA7
12 changed files with 212 additions and 97 deletions

View File

@ -371,8 +371,8 @@ class API extends InternalDoc
} catch (\Throwable $e) { } catch (\Throwable $e) {
$errors = [\time() => $errors[\time()] ?? 0]; $errors = [\time() => $errors[\time()] ?? 0];
$errors[\time()]++; $errors[\time()]++;
if ($errors[\time()] > 100 && (!$this->inited() || !$started)) { if ($errors[\time()] > 10 && (!$this->inited() || !$started)) {
$this->logger->logger("More than 100 errors in a second and not inited, exiting!", Logger::FATAL_ERROR); $this->logger->logger("More than 10 errors in a second and not inited, exiting!", Logger::FATAL_ERROR);
return; return;
} }
echo $e; echo $e;

View File

@ -34,7 +34,7 @@ use danog\MadelineProto\Tools;
class WriteLoop extends ResumableSignalLoop class WriteLoop extends ResumableSignalLoop
{ {
const MAX_COUNT = 1020; const MAX_COUNT = 1020;
const MAX_SIZE = 1 << 15; private const MAX_SIZE = 1 << 15;
const MAX_IDS = 8192; const MAX_IDS = 8192;
use Common; use Common;

View File

@ -99,7 +99,7 @@ class MTProto extends AsyncConstruct implements TLCallback
*/ */
const V = 147; const V = 147;
/** /**
* String release version. * Release version.
* *
* @var string * @var string
*/ */
@ -137,12 +137,16 @@ class MTProto extends AsyncConstruct implements TLCallback
/** /**
* Bad message error codes. * Bad message error codes.
* *
* @internal
*
* @var array * @var array
*/ */
const BAD_MSG_ERROR_CODES = [16 => 'msg_id too low (most likely, client time is wrong; it would be worthwhile to synchronize it using msg_id notifications and re-send the original message with the “correct” msg_id or wrap it in a container with a new msg_id if the original message had waited too long on the client to be transmitted)', 17 => 'msg_id too high (similar to the previous case, the client time has to be synchronized, and the message re-sent with the correct msg_id)', 18 => 'incorrect two lower order msg_id bits (the server expects client message msg_id to be divisible by 4)', 19 => 'container msg_id is the same as msg_id of a previously received message (this must never happen)', 20 => 'message too old, and it cannot be verified whether the server has received a message with this msg_id or not', 32 => 'msg_seqno too low (the server has already received a message with a lower msg_id but with either a higher or an equal and odd seqno)', 33 => 'msg_seqno too high (similarly, there is a message with a higher msg_id but with either a lower or an equal and odd seqno)', 34 => 'an even msg_seqno expected (irrelevant message), but odd received', 35 => 'odd msg_seqno expected (relevant message), but even received', 48 => 'incorrect server salt (in this case, the bad_server_salt response is received with the correct salt, and the message is to be re-sent with it)', 64 => 'invalid container']; const BAD_MSG_ERROR_CODES = [16 => 'msg_id too low (most likely, client time is wrong; it would be worthwhile to synchronize it using msg_id notifications and re-send the original message with the “correct” msg_id or wrap it in a container with a new msg_id if the original message had waited too long on the client to be transmitted)', 17 => 'msg_id too high (similar to the previous case, the client time has to be synchronized, and the message re-sent with the correct msg_id)', 18 => 'incorrect two lower order msg_id bits (the server expects client message msg_id to be divisible by 4)', 19 => 'container msg_id is the same as msg_id of a previously received message (this must never happen)', 20 => 'message too old, and it cannot be verified whether the server has received a message with this msg_id or not', 32 => 'msg_seqno too low (the server has already received a message with a lower msg_id but with either a higher or an equal and odd seqno)', 33 => 'msg_seqno too high (similarly, there is a message with a higher msg_id but with either a lower or an equal and odd seqno)', 34 => 'an even msg_seqno expected (irrelevant message), but odd received', 35 => 'odd msg_seqno expected (relevant message), but even received', 48 => 'incorrect server salt (in this case, the bad_server_salt response is received with the correct salt, and the message is to be re-sent with it)', 64 => 'invalid container'];
/** /**
* Localized message info flags. * Localized message info flags.
* *
* @internal
*
* @var array * @var array
*/ */
const MSGS_INFO_FLAGS = [1 => 'nothing is known about the message (msg_id too low, the other party may have forgotten it)', 2 => 'message not received (msg_id falls within the range of stored identifiers; however, the other party has certainly not received a message like that)', 3 => 'message not received (msg_id too high; however, the other party has certainly not received it yet)', 4 => 'message received (note that this response is also at the same time a receipt acknowledgment)', 8 => ' and message already acknowledged', 16 => ' and message not requiring acknowledgment', 32 => ' and RPC query contained in message being processed or processing already complete', 64 => ' and content-related response to message already generated', 128 => ' and other party knows for a fact that message is already received']; const MSGS_INFO_FLAGS = [1 => 'nothing is known about the message (msg_id too low, the other party may have forgotten it)', 2 => 'message not received (msg_id falls within the range of stored identifiers; however, the other party has certainly not received a message like that)', 3 => 'message not received (msg_id too high; however, the other party has certainly not received it yet)', 4 => 'message received (note that this response is also at the same time a receipt acknowledgment)', 8 => ' and message already acknowledged', 16 => ' and message not requiring acknowledgment', 32 => ' and RPC query contained in message being processed or processing already complete', 64 => ' and content-related response to message already generated', 128 => ' and other party knows for a fact that message is already received'];
@ -164,44 +168,29 @@ class MTProto extends AsyncConstruct implements TLCallback
* @var int * @var int
*/ */
const SECRET_READY = 2; const SECRET_READY = 2;
/**
* @internal
*/
const GETUPDATES_HANDLER = 'getUpdates'; const GETUPDATES_HANDLER = 'getUpdates';
/**
* @internal
*/
const TD_PARAMS_CONVERSION = ['updateNewMessage' => ['_' => 'updateNewMessage', 'disable_notification' => ['message', 'silent'], 'message' => ['message']], 'message' => ['_' => 'message', 'id' => ['id'], 'sender_user_id' => ['from_id'], 'chat_id' => ['peer_id', 'choose_chat_id_from_botapi'], 'send_state' => ['choose_incoming_or_sent'], 'can_be_edited' => ['choose_can_edit'], 'can_be_deleted' => ['choose_can_delete'], 'is_post' => ['post'], 'date' => ['date'], 'edit_date' => ['edit_date'], 'forward_info' => ['fwd_info', 'choose_forward_info'], 'reply_to_message_id' => ['reply_to_msg_id'], 'ttl' => ['choose_ttl'], 'ttl_expires_in' => ['choose_ttl_expires_in'], 'via_bot_user_id' => ['via_bot_id'], 'views' => ['views'], 'content' => ['choose_message_content'], 'reply_markup' => ['reply_markup']], 'messages.sendMessage' => ['chat_id' => ['peer'], 'reply_to_message_id' => ['reply_to_msg_id'], 'disable_notification' => ['silent'], 'from_background' => ['background'], 'input_message_content' => ['choose_message_content'], 'reply_markup' => ['reply_markup']]]; const TD_PARAMS_CONVERSION = ['updateNewMessage' => ['_' => 'updateNewMessage', 'disable_notification' => ['message', 'silent'], 'message' => ['message']], 'message' => ['_' => 'message', 'id' => ['id'], 'sender_user_id' => ['from_id'], 'chat_id' => ['peer_id', 'choose_chat_id_from_botapi'], 'send_state' => ['choose_incoming_or_sent'], 'can_be_edited' => ['choose_can_edit'], 'can_be_deleted' => ['choose_can_delete'], 'is_post' => ['post'], 'date' => ['date'], 'edit_date' => ['edit_date'], 'forward_info' => ['fwd_info', 'choose_forward_info'], 'reply_to_message_id' => ['reply_to_msg_id'], 'ttl' => ['choose_ttl'], 'ttl_expires_in' => ['choose_ttl_expires_in'], 'via_bot_user_id' => ['via_bot_id'], 'views' => ['views'], 'content' => ['choose_message_content'], 'reply_markup' => ['reply_markup']], 'messages.sendMessage' => ['chat_id' => ['peer'], 'reply_to_message_id' => ['reply_to_msg_id'], 'disable_notification' => ['silent'], 'from_background' => ['background'], 'input_message_content' => ['choose_message_content'], 'reply_markup' => ['reply_markup']]];
/**
* @internal
*/
const TD_REVERSE = ['sendMessage' => 'messages.sendMessage']; const TD_REVERSE = ['sendMessage' => 'messages.sendMessage'];
/**
* @internal
*/
const TD_IGNORE = ['updateMessageID']; const TD_IGNORE = ['updateMessageID'];
/**
* @internal
*/
const BOTAPI_PARAMS_CONVERSION = ['disable_web_page_preview' => 'no_webpage', 'disable_notification' => 'silent', 'reply_to_message_id' => 'reply_to_msg_id', 'chat_id' => 'peer', 'text' => 'message']; const BOTAPI_PARAMS_CONVERSION = ['disable_web_page_preview' => 'no_webpage', 'disable_notification' => 'silent', 'reply_to_message_id' => 'reply_to_msg_id', 'chat_id' => 'peer', 'text' => 'message'];
// Not content related constructors /**
const NOT_CONTENT_RELATED = [ * @internal
//'rpc_result', */
//'rpc_error',
'rpc_drop_answer',
'rpc_answer_unknown',
'rpc_answer_dropped_running',
'rpc_answer_dropped',
'get_future_salts',
'future_salt',
'future_salts',
'ping',
'pong',
'ping_delay_disconnect',
'destroy_session',
'destroy_session_ok',
'destroy_session_none',
//'new_session_created',
'msg_container',
'msg_copy',
'gzip_packed',
'http_wait',
'msgs_ack',
'bad_msg_notification',
'bad_server_salt',
'msgs_state_req',
'msgs_state_info',
'msgs_all_info',
'msg_detailed_info',
'msg_new_detailed_info',
'msg_resend_req',
'msg_resend_ans_req',
];
const DEFAULT_GETUPDATES_PARAMS = ['offset' => 0, 'limit' => null, 'timeout' => 100]; const DEFAULT_GETUPDATES_PARAMS = ['offset' => 0, 'limit' => null, 'timeout' => 100];
/** /**
* Array of references to all instances of MTProto. * Array of references to all instances of MTProto.

View File

@ -369,7 +369,7 @@ trait ResponseHandler
$this->logger->logger('If you intentionally deleted this account, ignore this message.', \danog\MadelineProto\Logger::FATAL_ERROR); $this->logger->logger('If you intentionally deleted this account, ignore this message.', \danog\MadelineProto\Logger::FATAL_ERROR);
} }
$this->API->resetSession(); $this->API->resetSession();
\danog\MadelineProto\Tools::callFork((function () use (&$request, &$response): \Generator { \danog\MadelineProto\Tools::callFork((function () use ($request, &$response): \Generator {
yield from $this->API->initAuthorization(); yield from $this->API->initAuthorization();
$this->handleReject($request, new \danog\MadelineProto\RPCErrorException($response['error_message'], $response['error_code'], $request['_'] ?? '')); $this->handleReject($request, new \danog\MadelineProto\RPCErrorException($response['error_message'], $response['error_code'], $request['_'] ?? ''));
})()); })());
@ -378,7 +378,7 @@ trait ResponseHandler
case 'AUTH_KEY_INVALID': case 'AUTH_KEY_INVALID':
if ($this->API->authorized !== MTProto::LOGGED_IN) { if ($this->API->authorized !== MTProto::LOGGED_IN) {
$this->gotResponseForOutgoingMessageId($request_id); $this->gotResponseForOutgoingMessageId($request_id);
\danog\MadelineProto\Tools::callFork((function () use (&$request, &$response): \Generator { \danog\MadelineProto\Tools::callFork((function () use ($request, &$response): \Generator {
yield from $this->API->initAuthorization(); yield from $this->API->initAuthorization();
$this->handleReject($request, new \danog\MadelineProto\RPCErrorException($response['error_message'], $response['error_code'], $request['_'] ?? '')); $this->handleReject($request, new \danog\MadelineProto\RPCErrorException($response['error_message'], $response['error_code'], $request['_'] ?? ''));
})()); })());
@ -403,7 +403,7 @@ trait ResponseHandler
$this->logger->logger('Then login again.', \danog\MadelineProto\Logger::FATAL_ERROR); $this->logger->logger('Then login again.', \danog\MadelineProto\Logger::FATAL_ERROR);
$this->logger->logger('If you intentionally deleted this account, ignore this message.', \danog\MadelineProto\Logger::FATAL_ERROR); $this->logger->logger('If you intentionally deleted this account, ignore this message.', \danog\MadelineProto\Logger::FATAL_ERROR);
$this->API->resetSession(); $this->API->resetSession();
\danog\MadelineProto\Tools::callFork((function () use (&$request, &$response): \Generator { \danog\MadelineProto\Tools::callFork((function () use ($request, &$response): \Generator {
yield from $this->API->initAuthorization(); yield from $this->API->initAuthorization();
$this->handleReject($request, new \danog\MadelineProto\RPCErrorException($response['error_message'], $response['error_code'], $request['_'] ?? '')); $this->handleReject($request, new \danog\MadelineProto\RPCErrorException($response['error_message'], $response['error_code'], $request['_'] ?? ''));
})()); })());

View File

@ -19,8 +19,6 @@
namespace danog\MadelineProto\MTProtoSession; namespace danog\MadelineProto\MTProtoSession;
use danog\MadelineProto\MTProto;
/** /**
* Manages sequence number. * Manages sequence number.
*/ */
@ -55,6 +53,37 @@ trait SeqNoHandler
public function contentRelated($method): bool public function contentRelated($method): bool
{ {
$method = \is_array($method) && isset($method['_']) ? $method['_'] : $method; $method = \is_array($method) && isset($method['_']) ? $method['_'] : $method;
return \is_string($method) ? !\in_array($method, MTProto::NOT_CONTENT_RELATED) : true; return \is_string($method) ? !\in_array($method, [
//'rpc_result',
//'rpc_error',
'rpc_drop_answer',
'rpc_answer_unknown',
'rpc_answer_dropped_running',
'rpc_answer_dropped',
'get_future_salts',
'future_salt',
'future_salts',
'ping',
'pong',
'ping_delay_disconnect',
'destroy_session',
'destroy_session_ok',
'destroy_session_none',
//'new_session_created',
'msg_container',
'msg_copy',
'gzip_packed',
'http_wait',
'msgs_ack',
'bad_msg_notification',
'bad_server_salt',
'msgs_state_req',
'msgs_state_info',
'msgs_all_info',
'msg_detailed_info',
'msg_new_detailed_info',
'msg_resend_req',
'msg_resend_ans_req',
]) : true;
} }
} }

View File

@ -68,7 +68,7 @@ class MyTelegramOrgWrapper
/** /**
* Endpoint. * Endpoint.
*/ */
const MY_TELEGRAM_URL = 'https://my.telegram.org'; private const MY_TELEGRAM_URL = 'https://my.telegram.org';
/** /**
* Sleep function. * Sleep function.
* *

View File

@ -28,6 +28,7 @@ use danog\MadelineProto\MTProtoTools\PasswordCalculator;
use danog\MadelineProto\MTProtoTools\ReferenceDatabase; use danog\MadelineProto\MTProtoTools\ReferenceDatabase;
use danog\MadelineProto\MTProtoTools\UpdatesState; use danog\MadelineProto\MTProtoTools\UpdatesState;
use danog\MadelineProto\TL\TL; use danog\MadelineProto\TL\TL;
use danog\MadelineProto\TL\TLCallback;
use danog\MadelineProto\TL\TLConstructors; use danog\MadelineProto\TL\TLConstructors;
use danog\MadelineProto\TL\TLMethods; use danog\MadelineProto\TL\TLMethods;
use danog\MadelineProto\TON\ADNLConnection; use danog\MadelineProto\TON\ADNLConnection;
@ -44,19 +45,11 @@ use phpDocumentor\Reflection\DocBlock\Tags\See;
use phpDocumentor\Reflection\DocBlockFactory; use phpDocumentor\Reflection\DocBlockFactory;
use ReflectionClass; use ReflectionClass;
use ReflectionClassConstant; use ReflectionClassConstant;
use ReflectionMethod;
class PhpDocBuilder class PhpDocBuilder
{ {
private DocBlockFactory $factory; private const DISALLOW = [
public function __construct()
{
$this->factory = DocBlockFactory::createInstance();
}
public function run()
{
$classes = ClassFinder::getClassesInNamespace('danog\\MadelineProto', ClassFinder::RECURSIVE_MODE);
foreach ($classes as $class) {
if (\in_array($class, [
AnnotationsBuilder::class, AnnotationsBuilder::class,
APIFactory::class, APIFactory::class,
APIWrapper::class, APIWrapper::class,
@ -95,12 +88,27 @@ class PhpDocBuilder
TL::class, TL::class,
TLConstructors::class, TLConstructors::class,
TLMethods::class, TLMethods::class,
TLCallback::class,
ADNLConnection::class, ADNLConnection::class,
TAPIFactory::class, TAPIFactory::class,
TInternalDoc::class, TInternalDoc::class,
Lite::class, Lite::class,
]) || str_starts_with($class, 'danog\\MadelineProto\\Ipc')
\ArrayIterator::class,
];
private DocBlockFactory $factory;
private string $output;
public function __construct(string $output)
{
$this->factory = DocBlockFactory::createInstance();
$this->output = $output;
}
public function run()
{
$classes = ClassFinder::getClassesInNamespace('danog\\MadelineProto', ClassFinder::RECURSIVE_MODE);
foreach ($classes as $class) {
if (\in_array($class, self::DISALLOW) || str_starts_with($class, 'danog\\MadelineProto\\Ipc')
|| str_starts_with($class, 'danog\\MadelineProto\\Loop\\Update') || str_starts_with($class, 'danog\\MadelineProto\\Loop\\Update')
|| str_starts_with($class, 'danog\\MadelineProto\\Loop\\Connection') || str_starts_with($class, 'danog\\MadelineProto\\Loop\\Connection')
|| str_starts_with($class, 'danog\\MadelineProto\\MTProto\\') || str_starts_with($class, 'danog\\MadelineProto\\MTProto\\')
@ -117,9 +125,29 @@ class PhpDocBuilder
$this->generate(new ReflectionClass(DbPropertiesTrait::class)); $this->generate(new ReflectionClass(DbPropertiesTrait::class));
} }
/**
* Create directory recursively.
*
* @param string $file
* @return string
*/
private static function createDir(string $file): string
{
$dir = \dirname($file);
if (!\file_exists($dir)) {
$this->createDir($dir);
}
return $file;
}
private function generate(ReflectionClass $class): void private function generate(ReflectionClass $class): void
{ {
$name = $class->getName(); $name = $class->getName();
$fName = $this->output;
$fName .= \str_replace(['\\', 'danog\\MadelineProto'], ['/', ''], $name);
$fName .= '.md';
$handle = \fopen(self::createDir($fName), 'w+');
$doc = $class->getDocComment(); $doc = $class->getDocComment();
if (!$doc) { if (!$doc) {
throw new Exception("$name has no PHPDOC!"); throw new Exception("$name has no PHPDOC!");
@ -163,15 +191,48 @@ class PhpDocBuilder
} }
} }
fwrite($handle, "---\n");
fwrite($handle, "title: $name: $title\n");
fwrite($handle, "description: $description\n");
fwrite($handle, "image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png\n");
fwrite($handle, "---\n");
fwrite($handle, "# $name: $title\n");
fwrite($handle, "[Back to API index](index.md)\n\n");
fwrite($handle, "> Author: $author \n");
$constants = []; $constants = [];
foreach ($class->getConstants() as $key => $value) { foreach ($class->getConstants() as $key => $value) {
$refl = new ReflectionClassConstant($name, $key); $refl = new ReflectionClassConstant($name, $key);
$doc = $this->factory->create($refl->getDocComment() ?? ''); if (!$refl->isPublic()) {
continue;
}
$description = '';
if ($refl->getDocComment()) {
$docConst = $this->factory->create($refl->getDocComment());
if (\in_array($refl->getDeclaringClass()->getName(), self::DISALLOW)) {
continue;
}
$description .= $docConst->getSummary();
if ($docConst->getDescription()) {
$description .= "\n\n";
$description .= $docConst->getDescription();
}
if ($docConst->getTagsByName('internal')) {
continue;
}
}
$description = \trim($description);
$constants[$key] = [ $constants[$key] = [
$value, $value,
$description, $description
$doc->getDescription()
]; ];
} }
$methods = [];
foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
}
} }
} }

View File

@ -169,6 +169,10 @@ class Logger extends SettingsAbstract
*/ */
public function setExtra($extra): self public function setExtra($extra): self
{ {
if ($this->type === MadelineProtoLogger::CALLABLE_LOGGER && !is_callable($extra)) {
$this->setType(MadelineProtoLogger::NO_LOGGER);
return $this;
}
$this->extra = $extra; $this->extra = $extra;
return $this; return $this;

View File

@ -37,7 +37,7 @@ use danog\MadelineProto\Stream\RawStreamInterface;
class BufferedRawStream implements BufferedStreamInterface, BufferInterface, RawStreamInterface class BufferedRawStream implements BufferedStreamInterface, BufferInterface, RawStreamInterface
{ {
use RawStream; use RawStream;
const MAX_SIZE = 10 * 1024 * 1024; private const MAX_SIZE = 10 * 1024 * 1024;
protected $stream; protected $stream;
protected $memory_stream; protected $memory_stream;
private $append = ''; private $append = '';

View File

@ -35,7 +35,7 @@ use danog\MadelineProto\Stream\RawStreamInterface;
*/ */
class SocksProxy implements RawProxyStreamInterface, BufferedProxyStreamInterface class SocksProxy implements RawProxyStreamInterface, BufferedProxyStreamInterface
{ {
const REPS = [0 => 'succeeded', 1 => 'general SOCKS server failure', 2 => 'connection not allowed by ruleset', 3 => 'Network unreachable', 4 => 'Host unreachable', 5 => 'Connection refused', 6 => 'TTL expired', 7 => 'Command not supported', 8 => 'Address type not supported']; private const REPS = [0 => 'succeeded', 1 => 'general SOCKS server failure', 2 => 'connection not allowed by ruleset', 3 => 'Network unreachable', 4 => 'Host unreachable', 5 => 'Connection refused', 6 => 'TTL expired', 7 => 'Command not supported', 8 => 'Address type not supported'];
use RawStream; use RawStream;
/** /**
* Stream. * Stream.

File diff suppressed because one or more lines are too long

View File

@ -25,18 +25,50 @@ namespace danog\MadelineProto\TL;
interface TLCallback interface TLCallback
{ {
/** /**
* Called after serializing a method
* *
* @internal
* *
* @var int * @var int
*/ */
const METHOD_CALLBACK = 0; const METHOD_CALLBACK = 0;
/**
* Called before serializing a method
*
* @internal
*
* @var int
*/
const METHOD_BEFORE_CALLBACK = 1; const METHOD_BEFORE_CALLBACK = 1;
/**
* Called after serializing a constructor
*
* @internal
*
* @var int
*/
const CONSTRUCTOR_CALLBACK = 2; const CONSTRUCTOR_CALLBACK = 2;
/**
* Called before serializing a constructor
*
* @internal
*
* @var int
*/
const CONSTRUCTOR_BEFORE_CALLBACK = 3; const CONSTRUCTOR_BEFORE_CALLBACK = 3;
/**
* Called on constructor serialization
*
* @internal
*
* @var int
*/
const CONSTRUCTOR_SERIALIZE_CALLBACK = 4; const CONSTRUCTOR_SERIALIZE_CALLBACK = 4;
/** /**
* Called if objects of the specified type cannot be serialized. * Called if objects of the specified type cannot be serialized.
* *
* @internal
*
* @var int * @var int
*/ */
const TYPE_MISMATCH_CALLBACK = 5; const TYPE_MISMATCH_CALLBACK = 5;