1
0
mirror of https://github.com/danog/MadelineProto.git synced 2024-11-26 17:04:39 +01:00
This commit is contained in:
Daniil Gentili 2024-03-10 15:48:55 +01:00
parent 61b438a38e
commit 8721db3f31
8 changed files with 1163 additions and 1375 deletions

View File

@ -24,7 +24,8 @@ $config->getFinder()
->in(__DIR__ . '/tests')
->in(__DIR__ . '/examples')
->in(__DIR__ . '/tools')
->exclude('TLParser.php');
->notName('TLParser.php')
->notName('SecretTLParser.php');
$cacheDir = getenv('TRAVIS') ? getenv('HOME') . '/.php-cs-fixer' : __DIR__;

View File

@ -17,6 +17,10 @@
</enableExtensions>
<projectFiles>
<directory name="src" />
<ignoreFiles>
<file name="src/TL/TLParser.php" />
<file name="src/TL/SecretTLParser.php" />
</ignoreFiles>
</projectFiles>
<issueHandlers>
<!-- Should totally go in level 1... -->

View File

@ -903,6 +903,11 @@ abstract class InternalDoc
{
return $this->wrapper->getAPI()->getInfo($id, $type);
}
public function getInputDialogPeer(mixed $id): array
{
return $this->wrapper->getAPI()->getInputDialogPeer($id);
}
/**
* Get logger.
*/

View File

@ -675,7 +675,7 @@ final class MTProto implements TLCallback, LoggerGetter, SettingsGetter
if (empty($file)) {
$file = basename(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]['file'], '.php');
}
($this->logger ?? Logger::$default)->logger($param, $level, $file);
($this->logger ?? Logger::$default)?->logger($param, $level, $file);
}
/**
* Get TL namespaces.
@ -1814,18 +1814,28 @@ final class MTProto implements TLCallback, LoggerGetter, SettingsGetter
{
return [];
}
/**
* @internal
*/
public function populateSupportUser(array $support): void
{
$this->supportUser = $support['user']['id'];
}
/**
* @internal
*/
public function populateConfig(array $config): void
{
$this->config = $config;
}
/**
* @internal
*/
public function getConstructorAfterDeserializationCallbacks(): array
{
return [
'help.support' => [function (array $support): void {
$this->supportUser = $support['user']['id'];
}],
'config' => [function (array $config): void {
$this->config = $config;
}],
'help.support' => [$this->populateSupportUser(...)],
'config' => [$this->populateConfig(...)],
];
}
/**
@ -1866,11 +1876,20 @@ final class MTProto implements TLCallback, LoggerGetter, SettingsGetter
[
'InputFileLocation' => $this->getDownloadInfo(...),
'InputPeer' => $this->getInputPeer(...),
'InputDialogPeer' => fn (mixed $id): array => ['_' => 'inputDialogPeer', 'peer' => $this->getInputPeer($id)],
'InputCheckPasswordSRP' => fn (string $password): array => (new PasswordCalculator($this->methodCallAsyncRead('account.getPassword', [], $this->authorized_dc)))->getCheckPassword($password),
'InputDialogPeer' => $this->getInputDialogPeer(...),
'InputCheckPasswordSRP' => $this->getPasswordSRP(...),
],
);
}
public function getInputDialogPeer(mixed $id): array
{
return ['_' => 'inputDialogPeer', 'peer' => $this->getInputPeer($id)];
}
/** @internal */
public function getPasswordSRP(string $password): array
{
return (new PasswordCalculator($this->methodCallAsyncRead('account.getPassword', [], $this->authorized_dc)))->getCheckPassword($password);
}
/**
* Get debug information for var_dump.
*/

View File

@ -145,7 +145,7 @@ final class MinDatabase implements TLCallback
$this->cache = [];
}
}
public function addPeer(array $location): bool
public function addPeer(array|int $location): bool
{
$peers = [];
switch ($location['_']) {

File diff suppressed because it is too large Load Diff

View File

@ -24,24 +24,26 @@ use danog\MadelineProto\MTProtoTools\MinDatabase;
use danog\MadelineProto\MTProtoTools\PeerDatabase;
use danog\MadelineProto\MTProtoTools\ReferenceDatabase;
use danog\MadelineProto\Settings\TLSchema;
use ReflectionClass;
use ReflectionFunction;
use Webmozart\Assert\Assert;
/**
* @internal
*/
final class Builder
class Builder
{
/**
* TL instance.
*/
private TL $TL;
private readonly array $byType;
private readonly array $idByPredicate;
private readonly array $typeByPredicate;
private readonly array $constructorByPredicate;
private readonly array $methodVectorTypes;
private $output;
protected TL $TL;
protected readonly array $byType;
protected readonly array $idByPredicate;
protected readonly array $typeByPredicate;
protected readonly array $constructorByPredicate;
protected readonly array $methodVectorTypes;
protected readonly string $class;
protected $output;
public function __construct(
TLSchema $settings,
/**
@ -51,12 +53,21 @@ final class Builder
/**
* Output namespace.
*/
private string $namespace,
protected string $namespace,
) {
$this->output = fopen($output, 'w');
$this->TL = new TL();
$this->TL->init($settings);
$this->class = basename($output, '.php');
$callbacks = [];
$callbacks []= (new ReflectionClass(MTProto::class))->newInstanceWithoutConstructor();
$callbacks []= (new ReflectionClass(ReferenceDatabase::class))->newInstanceWithoutConstructor();
$callbacks []= (new ReflectionClass(MinDatabase::class))->newInstanceWithoutConstructor();
$callbacks []= (new ReflectionClass(PeerDatabase::class))->newInstanceWithoutConstructor();
$this->TL->updateCallbacks($callbacks);
$byType = [];
$idByPredicate = ['vector' => var_export(hex2bin('1cb5c415'), true)];
$constructorByPredicate = [];
@ -82,8 +93,11 @@ final class Builder
}
if (isset($constructor['layer'])) {
$constructor['predicate'] .= '_'.$constructor['layer'];
if (!$this instanceof SecretBuilder) {
continue;
}
}
$constructor['id'] = $id;
$constructorByPredicate[$constructor['predicate']] = $constructor;
@ -121,15 +135,15 @@ final class Builder
$this->byType = $byType;
}
private static function escapeConstructorName(array $constructor): string
protected static function escapeConstructorName(array $constructor): string
{
return str_replace(['.', ' '], '___', $constructor['predicate']);
}
private static function escapeTypeName(string $name): string
protected static function escapeTypeName(string $name): string
{
return str_replace(['.', ' '], '___', $name);
}
private function needFullConstructor(string $predicate): bool
protected function needFullConstructor(string $predicate): bool
{
if (isset($this->TL->beforeConstructorDeserialization[$predicate])
|| isset($this->TL->afterConstructorDeserialization[$predicate])) {
@ -137,7 +151,7 @@ final class Builder
}
return false;
}
private static function methodFromClosure(ReflectionFunction $closure): string
protected static function methodFromClosure(\Closure $closure): string
{
$refl = new ReflectionFunction($closure);
return match ($refl->getClosureThis()::class) {
@ -148,18 +162,18 @@ final class Builder
}."->".$refl->getName();
}
private function buildTypes(array $constructors, string $type): string
protected function buildTypes(array $constructors, string $type): string
{
$typeMethod = "_type_".self::escapeTypeName($type);
$result = "match (stream_get_contents(\$stream, 4)) {\n";
foreach ($constructors as ['predicate' => $predicate, 'id' => $id]) {
foreach ($constructors as ['predicate' => $predicate]) {
if ($predicate === 'gzip_packed') {
continue;
}
if ($predicate === 'jsonObjectValue') {
throw new AssertionError("Impossible!");
}
$result .= var_export($id, true)." => ";
$result .= $this->idByPredicate[$predicate]." => ";
$result .= $this->buildConstructor($predicate);
$result .= ",\n";
}
@ -182,7 +196,7 @@ final class Builder
$result .= "default => self::err(\$stream)\n";
return $result."}\n";
}
private array $createdConstructors = [];
protected array $createdConstructors = [];
public function buildConstructor(string $predicate): string
{
$constructor = $this->constructorByPredicate[$predicate];
@ -207,7 +221,6 @@ final class Builder
$callback($tmp);
}
}
return $tmp;
';
} elseif ($flags) {
$result = $this->buildConstructorFull($predicate, $params, $flags);
@ -216,7 +229,7 @@ final class Builder
if (!$this->needFullConstructor($predicate)) {
return $result;
}
$result = "\$tmp = $result";
$result = "\$tmp = $result;\n";
}
$pre = '';
@ -227,6 +240,7 @@ final class Builder
foreach ($this->TL->afterConstructorDeserialization[$predicate] ?? [] as $closure) {
$result .= self::methodFromClosure($closure)."(\$tmp);\n";
}
$result .= "return \$tmp;\n";
$nameEscaped = self::escapeConstructorName($constructor);
if (!isset($this->createdConstructors[$predicate])) {
@ -236,7 +250,7 @@ final class Builder
return $this->methodCall("deserialize_$nameEscaped");
}
private function buildConstructorFull(string $predicate, array $params, array $flags): string
protected function buildConstructorFull(string $predicate, array $params, array $flags): string
{
$result = "\$tmp = ['_' => '$predicate'];\n";
$flagNames = [];
@ -263,10 +277,10 @@ final class Builder
$code = $this->buildType($param['type']);
$result .= "if ($flag) \$tmp['$name'] = $code;\n";
}
return "$result\nreturn \$tmp;";
return $result;
}
private function buildConstructorShort(string $predicate, array $params = []): string
protected function buildConstructorShort(string $predicate, array $params = []): string
{
if ($predicate === 'dataJSON') {
return 'json_decode('.$this->buildType('string').', true, 512, \\JSON_THROW_ON_ERROR)';
@ -277,23 +291,18 @@ final class Builder
$superBare = $this->typeByPredicate[$predicate] === 'JSONValue'
|| $this->typeByPredicate[$predicate] === 'Peer';
$result = '';
if (!$superBare) {
$result .= "[\n";
$result .= "'_' => '$predicate',\n";
}
foreach ($params as $param) {
$code = $this->buildType($param['type']);
if ($superBare) {
$result .= $code;
$result = $this->buildType(end($params)['type']);
} else {
$result .= var_export($param['name'], true)." => $code,\n";
$result = "[\n";
$result .= "'_' => '$predicate',\n";
foreach ($params as $param) {
$result .= var_export($param['name'], true).' => ';
$result .= $this->buildType($param['type']).",\n";
}
}
if (!$superBare) {
$result .= ']';
}
if ($predicate === 'peerChat') {
$result = "-$result";
} elseif ($predicate === 'peerChannel') {
@ -302,8 +311,8 @@ final class Builder
return $result;
}
private array $createdVectors = [];
private function buildVector(string $type, bool $bare, ?string $payload = null): string
protected array $createdVectors = [];
protected function buildVector(string $type, bool $bare, ?string $payload = null): string
{
if (!isset($this->createdVectors[$type])) {
$this->createdVectors[$type] = true;
@ -334,9 +343,9 @@ final class Builder
);
}
private array $createdTypes = ['Object' => true];
private array $typeStack = [];
private function buildType(string $type): string
protected array $createdTypes = ['Object' => true];
protected array $typeStack = [];
protected function buildType(string $type): string
{
if (str_starts_with($type, 'Vector<')) {
return $this->buildVector(str_replace(['Vector<', '>'], '', $type), false);
@ -376,7 +385,7 @@ final class Builder
);
}
$had = array_search($type, $this->typeStack) !== false;
$had = array_search($type, $this->typeStack, true) !== false;
$this->typeStack []= $type;
try {
if (!$had) {
@ -388,8 +397,8 @@ final class Builder
}
}
private array $methodsCreated = [];
private function methodCall(string $method, string $stream = '$stream'): string
protected array $methodsCreated = [];
protected function methodCall(string $method, string $stream = '$stream'): string
{
return ($this->methodsCreated[$method] ?? true)
? "\$this->$method($stream)"
@ -407,13 +416,13 @@ final class Builder
$static = $static ? 'static' : '';
$this->w(" $public $static function $methodName(mixed \$stream$extraArg): $returnType {\n{$body}\n }\n");
}
private function w(string $data): void
protected function w(string $data): void
{
fwrite($this->output, $data);
}
public function build(): void
{
$this->w("<?php namespace {$this->namespace};\n/** @internal Autogenerated using tools/TL/Builder.php */\nfinal class TLParser {\n");
$this->w("<?php namespace {$this->namespace};\n/** @internal Autogenerated using tools/TL/Builder.php */\nfinal class {$this->class} {\n");
$this->m('err', '
fseek($stream, -4, SEEK_CUR);
@ -500,6 +509,13 @@ final class Builder
$this->buildVector($type, false, '$result []= '.$this->buildType($type));
}
$this->buildMain();
$this->w("}\n");
}
protected function buildMain(): void
{
$initial_constructors = array_filter(
$this->constructorByPredicate,
static fn (array $arr) => (
@ -513,7 +529,5 @@ final class Builder
);
$this->m("deserialize_type_Object", "return {$this->buildTypes($initial_constructors, 'Object')};", 'mixed', true, static: false);
$this->w("}\n");
}
}

View File

@ -2,6 +2,7 @@
use danog\MadelineProto\Settings\TLSchema;
use danog\MadelineProto\TL\Builder;
use danog\MadelineProto\TL\SecretBuilder;
require __DIR__.'/../vendor/autoload.php';
@ -9,3 +10,6 @@ require __DIR__.'/../vendor/autoload.php';
$builder = new Builder(new TLSchema, __DIR__.'/../src/TL/TLParser.php', 'danog\\MadelineProto\\TL');
$builder->build();
$builder = new SecretBuilder(new TLSchema, __DIR__.'/../src/TL/SecretTLParser.php', 'danog\\MadelineProto\\TL');
$builder->build();