@@ -33,7 +33,7 @@ public function validateParams(string $constructor, bool $isCons, array $params)
3333 Assert::notFalse ($ data , "Constructor or method not found for $ constructor " );
3434 foreach ($ data ['params ' ] as $ param ) {
3535 if (!isset ($ params [$ param ['name ' ]])) {
36- if (isset ($ param ['pow ' ])) {
36+ if (isset ($ param ['pow ' ]) || $ param [ ' name ' ] === ' flags ' ) {
3737 continue ;
3838 }
3939 throw new AssertionError ("Mandatory parameter {$ param ['name ' ]} not found in constructor or method $ constructor " );
@@ -58,7 +58,7 @@ public function validateParams(string $constructor, bool $isCons, array $params)
5858 public function getTypeAtPosition (SimpleExtractorOp $ _path ): string
5959 {
6060 if ($ _path instanceof ExtractFromHereOp) {
61- Assert::eq ($ this ->position , $ _path ->path [0 ], "Current constructor {$ this ->position } does not match expected constructor {$ _path ->path [0 ]}" );
61+ Assert::eq ($ this ->position , $ _path ->path [0 ], "getTypeAtPosition: Current constructor {$ this ->position } does not match expected constructor {$ _path ->path [0 ]}" );
6262 }
6363 $ path = $ _path ->path ;
6464 $ idx = 0 ;
@@ -82,9 +82,8 @@ public function getTypeAtPosition(SimpleExtractorOp $_path): string
8282 $ n = $ constructor ['predicate ' ] ?? $ constructor ['method ' ];
8383 foreach ($ constructor ['params ' ] as $ param ) {
8484 if ($ param ['name ' ] === $ path [$ idx ]) {
85- Assert::false (isset ($ param ['subtype ' ]), "Got flag for parameter {$ path [$ idx ]} in constructor or method $ n " );
8685 $ hadFlag = $ hadFlag || isset ($ param ['pow ' ]);
87- $ type = $ param ['type ' ];
86+ $ type = isset ( $ param [ ' subtype ' ]) ? " Vector< { $ param [ ' subtype ' ]} > " : $ param ['type ' ];
8887 break ;
8988 }
9089 }
@@ -147,6 +146,10 @@ interface ActionOp extends Op
147146
148147final class Noop implements ActionOp
149148{
149+ public function __construct (private readonly string $ why )
150+ {
151+ }
152+
150153 public function getType (TLContext $ tl ): string
151154 {
152155 return '' ;
@@ -164,7 +167,7 @@ public function normalize(array $stack): ?Op
164167
165168 public function build (TLContext $ tl ): array
166169 {
167- return ['op ' => 'noop ' ];
170+ return ['op ' => 'noop ' , ' why ' => $ this -> why ];
168171 }
169172}
170173
@@ -348,15 +351,14 @@ final class ExtractStickerSetFromDocumentAttributesOp implements SimpleExtractor
348351{
349352 public function __construct (
350353 private readonly SimpleExtractorOp $ path ,
351- )
352- {
354+ ) {
353355 }
354356
355357 public function hasBackreference (): bool
356358 {
357359 return $ this ->path ->hasBackreference ();
358360 }
359-
361+
360362 public function normalize (array $ stack ): ?Op
361363 {
362364 $ path = $ this ->path ->normalize ($ stack );
@@ -368,7 +370,7 @@ public function normalize(array $stack): ?Op
368370 }
369371 return $ this ;
370372 }
371-
373+
372374 public function getType (TLContext $ tl ): string
373375 {
374376 return 'InputStickerSet ' ;
@@ -534,15 +536,15 @@ public function hasBackreference(): bool
534536 public function normalize (array $ stack ): ?Op
535537 {
536538 $ final = [];
537- $ isDifferent = false ;
539+ $ isDifferent = false ;
538540 foreach ($ this ->values as $ value ) {
539541 $ normalized = $ value ->normalize ($ stack );
540542 if ($ normalized === null ) {
541543 return null ;
542544 }
543545 if ($ normalized !== $ value ) {
544546 $ isDifferent = true ;
545- }
547+ }
546548 $ final [] = $ normalized ;
547549 }
548550 if ($ isDifferent ) {
@@ -573,7 +575,7 @@ final class LiteralOp implements ExtractorOrLiteralOp
573575{
574576 public function __construct (private readonly string $ type , private readonly mixed $ value )
575577 {
576- Assert::inArray ($ type , ['int ' , 'long ' , 'string ' , 'bool ' , 'float ' , ' # ' ], "Invalid type ' $ type' for LiteralOp " );
578+ Assert::inArray ($ type , ['int ' , 'long ' , 'string ' , 'bool ' , 'float ' ], "Invalid type ' $ type' for LiteralOp " );
577579 }
578580
579581 public function hasBackreference (): bool
@@ -599,7 +601,7 @@ public function build(TLContext $tl): array
599601 }
600602}
601603
602- final class GetMessageOp implements ExtractorOrLiteralOp
604+ final class GetMessageOp implements ActionOp
603605{
604606 public function __construct (
605607 private readonly Op $ peer ,
@@ -804,7 +806,6 @@ public function build(TLContext $tl): array
804806 'min_id ' => new ExtractFromHereOp (['channelAdminLogEvent ' , 'id ' ]),
805807 'limit ' => new LiteralOp ('int ' , 1 ),
806808 'q ' => new LiteralOp ('string ' , '' ),
807- 'flags ' => new LiteralOp ('# ' , 0 ),
808809 ]
809810);
810811$ locations ['bots.getPreviewInfo ' ][] = new CopyMethodCallOp ('bots.getPreviewInfo ' );
@@ -834,18 +835,19 @@ public function build(TLContext $tl): array
834835 ]
835836);
836837$ locations ['help.getPremiumPromo ' ][] = new CopyMethodCallOp ('help.getPremiumPromo ' );
837- foreach (TLContext::getConstructorsOfType ($ TL , 'StarsTransaction ' , false ) as $ method => $ _ ) {
838- $ locations [$ constructor ][] = new CallOp (
839- 'payments.getStarsTransactionByID ' ,
838+ foreach (TLContext::getConstructorsOfType ($ TL , 'payments.StarsStatus ' , true ) as $ method => $ _ ) {
839+ $ locations [' starsTransaction ' ][] = new CallOp (
840+ 'payments.getStarsTransactionsByID ' ,
840841 [
841- 'peer ' => new ExtractFromMethodCallOp ([$ constructor , 'peer ' ]),
842- 'id ' => new ConstructorOp (
842+ 'peer ' => new ExtractFromMethodCallOp ([$ method , 'peer ' ]),
843+ ...($ method === 'payments.getStarsSubscriptions ' ? [] : ['ton ' => new ExtractFromMethodCallOp ([$ method , 'ton ' ], true )]),
844+ 'id ' => new ArrayOp (new ConstructorOp (
843845 'inputStarsTransaction ' ,
844846 [
845- 'id ' => new ExtractFromHereOp ([$ constructor , 'id ' ]),
846- 'refund ' => new ExtractFromHereOp ([$ constructor , 'refund ' ]),
847+ 'id ' => new ExtractFromHereOp ([' starsTransaction ' , 'id ' ]),
848+ 'refund ' => new ExtractFromHereOp ([' starsTransaction ' , 'refund ' ], true ),
847849 ]
848- ),
850+ )) ,
849851 ]
850852 );
851853}
@@ -947,7 +949,7 @@ public function build(TLContext $tl): array
947949 'limit ' => new LiteralOp ('int ' , 1 ),
948950 ]
949951);
950- foreach (['photos.updateProfilePhoto ' , 'photos.updateProfilePhoto ' ] as $ method ) {
952+ foreach (['photos.updateProfilePhoto ' , 'photos.uploadProfilePhoto ' ] as $ method ) {
951953 $ locations ['photo ' ][] = new CallOp (
952954 'photos.getUserPhotos ' ,
953955 [
@@ -965,6 +967,19 @@ public function build(TLContext $tl): array
965967 ]
966968 );
967969}
970+ $ locations ['photo ' ][] = new CallOp (
971+ 'photos.getUserPhotos ' ,
972+ [
973+ 'user_id ' => new ExtractFromMethodCallOp (
974+ ['photos.uploadContactProfilePhoto ' , 'user_id ' ],
975+ ),
976+ 'offset ' => new LiteralOp ('int ' , -1 ),
977+ 'max_id ' => new ExtractFromHereOp (['photo ' , 'id ' ]),
978+ 'limit ' => new LiteralOp ('int ' , 1 ),
979+ ]
980+ );
981+
982+ $ locations ['messages.uploadMedia ' ][]= new Noop ('A freshly uploaded media file will obtain a context only once it is sent to a chat ' );
968983
969984$ locations ['document ' ][] = new CallOp (
970985 'messages.getStickerSet ' ,
@@ -974,69 +989,49 @@ public function build(TLContext $tl): array
974989 ]
975990);
976991$ locations ['messages.getDocumentByHash ' ][] = new CopyMethodCallOp ('messages.getDocumentByHash ' );
992+ $ locations ['updateServiceNotification ' ][] = new Noop ('Cannot refetch service notifications ' );
977993
978994// Ignore these for now
979995foreach (['payments.ResaleStarGifts ' , 'payments.StarGiftUpgradePreview ' , 'StarGift ' ] as $ type ) {
980996 foreach (TLContext::getConstructorsOfType ($ TL , $ type , false ) as $ constructor => $ _ ) {
981- $ locations [$ constructor ][] = new Noop ();
997+ $ locations [$ constructor ][] = new Noop (' Contexts for star gifts are not yet implemented ' );
982998 }
983999}
9841000
985- $ recurse = static function (Closure $ earlyReturn , Closure $ onStackEnd , string $ type , array $ stack = []) use ($ TL , &$ recurse ): void {
986- if ($ earlyReturn ($ type )) {
987- return ;
988- }
1001+ $ recurse = static function (Closure $ onStackEnd , string $ type , array &$ stack , array &$ stackTypes ) use ($ TL , &$ recurse ): void {
9891002 $ pos = count ($ stack );
9901003 $ found = false ;
9911004 foreach ([...$ TL ->getConstructors ()->by_id , ...$ TL ->getMethods ()->by_id ] as $ constructor ) {
9921005 $ name = $ constructor ['predicate ' ] ?? $ constructor ['method ' ];
1006+ $ t = $ constructor ['type ' ];
1007+ if (isset ($ stackTypes [$ t ])) {
1008+ continue ;
1009+ }
1010+ $ stackTypes [$ t ] = true ;
9931011 foreach ($ constructor ['params ' ] as $ param ) {
994- if ($ param ['type ' ] === $ type && !in_array ($ name , $ stack , true )) {
1012+ if ((
1013+ $ param ['type ' ] === $ type ||
1014+ ($ param ['subtype ' ] ?? null ) === $ type
1015+ )) {
9951016 $ stack [$ pos ] = $ name ;
996- $ recurse ($ earlyReturn , $ onStackEnd , $ constructor ['type ' ], $ stack );
997- $ found = true ;
998- }
999- if (isset ($ param ['subtype ' ])
1000- && $ param ['subtype ' ] === $ type
1001- && !in_array ($ name , $ stack , true )
1002- ) {
1003- $ stack [$ pos ] = $ name ;
1004- $ recurse ($ earlyReturn , $ onStackEnd , $ constructor ['type ' ], $ stack );
1017+ $ recurse ($ onStackEnd , $ t , $ stack , $ stackTypes );
10051018 $ found = true ;
1019+ unset($ stack [$ pos ]);
10061020 }
10071021 }
1022+ unset($ stackTypes [$ t ]);
10081023 }
1009- unset($ stack [$ pos ]);
1010- if (!$ found
1011- || $ type === 'Update '
1012- || $ type === 'Updates '
1013- || TLContext::getConstructorsOfType ($ TL , $ type , true , true )
1014- ) {
1015- if (
1016- (
1017- in_array ($ stack [0 ], ['photo ' , 'document ' ], true )
1018- && ($ stack [1 ] ?? null ) === 'game '
1019- && in_array (end ($ stack ), [
1020- 'messages.webPagePreview ' ,
1021- 'payments.starsStatus ' ,
1022- 'messages.invitedUsers ' ,
1023- 'payments.paymentResult ' ,
1024- ], true )
1025- ) || array_intersect (
1026- [
1027- 'updateServiceNotification ' ,
1028- 'updateShortSentMessage ' ,
1029- 'updateShortMessage ' ,
1030- 'updateShortChatMessage ' ,
1031- ],
1032- $ stack ,
1033- ) || end ($ stack ) === 'messages.webPagePreview '
1034- || end ($ stack ) === 'help.appUpdate '
1035- ) {
1036- return ;
1024+ if (!$ found ) {
1025+ foreach (TLContext::getConstructorsOfType ($ TL , $ type , true , true ) as $ method => $ data ) {
1026+ $ stack [$ pos ] = $ method ;
1027+ $ onStackEnd ($ stack );
10371028 }
1029+ unset($ stack [$ pos ]);
1030+ } elseif ($ type === 'Update ' ) {
1031+ unset($ stack [$ pos ]);
10381032 $ onStackEnd ($ stack );
10391033 }
1034+
10401035};
10411036
10421037$ fileRefs = ['Document ' => 'document ' , 'Photo ' => 'photo ' ];
@@ -1077,23 +1072,56 @@ public function build(TLContext $tl): array
10771072}
10781073$ locationTypes = array_filter ($ locationTypes );
10791074
1075+ foreach ($ locations as $ constructor => $ ops ) {
1076+ var_dump ("Processing $ constructor " );
1077+ foreach ($ ops as $ op ) {
1078+ $ op ->build (new TLContext ($ TL , $ constructor ));
1079+ }
1080+ }
1081+ var_dump ("Finished initial validation " );
1082+
10801083$ normalizedLocations = [];
10811084
10821085foreach ($ fileRefs as $ type => $ constructor ) {
1086+ $ stack = [$ constructor ];
1087+ $ stackTypes = [$ type => true ];
10831088 $ recurse (
1084- static fn (string $ type ) => false ,//isset($locationTypes[$type]),
10851089 static function (array $ stack ) use ($ locations ): void {
1086- $ stack = array_reverse ($ stack );
1090+ if (end ($ stack ) === 'messages.getWebPagePreview '
1091+ || end ($ stack ) === 'help.appUpdate '
1092+ || (
1093+ in_array ($ stack [0 ], ['photo ' , 'document ' ], true )
1094+ && ($ stack [1 ] ?? null ) === 'game '
1095+ && in_array (end ($ stack ), [
1096+ 'messages.getWebPagePreview ' ,
1097+ 'messages.invitedUsers ' ,
1098+ 'payments.paymentResult ' ,
1099+ ], true )
1100+ ) || array_intersect (
1101+ [
1102+ 'updateServiceNotification ' ,
1103+ 'updateShortSentMessage ' ,
1104+ 'updateShortMessage ' ,
1105+ 'updateShortChatMessage ' ,
1106+ ],
1107+ $ stack ,
1108+ )
1109+ ) {
1110+ return ;
1111+ }
1112+ $ slice = [];
10871113 $ had = false ;
1088- foreach ($ stack as $ constructor ) {
1114+ for ($ x = count ($ stack )-1 ; $ x >= 0 ; $ x --) {
1115+ $ constructor = $ stack [$ x ];
1116+ $ slice [] = $ constructor ;
10891117 if (isset ($ locations [$ constructor ])) {
10901118 foreach ($ locations [$ constructor ] as $ op ) {
1091- $ normalized = $ op ->normalize ($ stack );
1119+ $ normalized = $ op ->normalize ($ slice );
10921120 if ($ normalized === null ) {
10931121 continue ;
10941122 }
10951123 $ had = true ;
1096- $ normalizedLocations [$ constructor ] = $ normalized ;
1124+ $ normalizedLocations [$ constructor ][] = $ normalized ;
10971125 }
10981126 }
10991127 }
@@ -1102,14 +1130,7 @@ static function (array $stack) use ($locations): void {
11021130 }
11031131 },
11041132 $ type ,
1105- [$ constructor ]
1133+ $ stack ,
1134+ $ stackTypes ,
11061135 );
11071136}
1108- die;
1109-
1110- foreach ($ locations as $ constructor => $ ops ) {
1111- var_dump ("Processing $ constructor " );
1112- foreach ($ ops as $ op ) {
1113- var_dump ([$ constructor , $ op ->build (new TLContext ($ TL , $ constructor ))]);
1114- }
1115- }
0 commit comments