@@ -25,83 +25,122 @@ public InlineQueryHandler(IReadOnlyCollection<MethodInfo> controllerMethods, Upd
2525 {
2626 return null ;
2727 }
28+
2829 var inlineQuery = update . CallbackQuery ;
2930 string command = inlineQuery . Data ! ;
30- List < MethodInfo > methods = new List < MethodInfo > ( ) ;
31+
32+ // Collect all candidate methods with their parsed arguments
33+ var candidates = new List < ( MethodInfo Method , List < object > Args ) > ( ) ;
3134 foreach ( var method in controllerMethods )
3235 {
33- bool isValidMethod = IsValidMethod ( method , command ) ;
34- if ( isValidMethod )
36+ if ( TryMatchMethod ( method , command , out var args ) )
3537 {
36- methods . Add ( method ) ;
38+ candidates . Add ( ( method , args ) ) ;
3739 }
3840 }
39- if ( methods . Count == 1 )
41+
42+ if ( candidates . Count == 1 )
4043 {
41- var args = _args . ToArray ( ) ;
42- ObjectHelpers . TryConvertParameters ( methods [ 0 ] , args ) ;
44+ var ( method , rawArgs ) = candidates [ 0 ] ;
45+ var argsArray = rawArgs . ToArray ( ) ;
46+ ObjectHelpers . TryConvertParameters ( method , argsArray ) ;
4347 _args . Clear ( ) ;
44- _args . AddRange ( args ) ;
45- return methods [ 0 ] ;
48+ _args . AddRange ( argsArray ) ;
49+ return method ;
4650 }
47- else if ( methods . Count > 1 )
51+
52+ if ( candidates . Count > 1 )
4853 {
49- throw new AmbiguousMatchException ( "Multiple methods found with the same command and arguments: " + command + "\n " +
50- string . Join ( "\n " , methods . Select ( m => m . Name + " - " + m . GetParameters ( ) . Length + " parameters" ) ) ) ;
54+ throw new AmbiguousMatchException ( "Multiple methods found with the same command and arguments: " + command + "\n " +
55+ string . Join ( "\n " , candidates . Select ( c => c . Method . Name + " - " + c . Method . GetParameters ( ) . Length + " parameters" ) ) ) ;
5156 }
57+
5258 return null ;
5359 }
5460
55- private bool IsValidMethod ( MethodInfo method , string command )
61+ private static bool IsPlaceholder ( string segment )
5662 {
57- var attributes = method . GetCustomAttributes ( typeof ( InlineCommandAttribute ) , false ) ;
58- string [ ] incomingCommandParts = command . Split ( '/' ) ;
63+ return segment . Length > 1 && segment [ 0 ] == '{' && segment [ segment . Length - 1 ] == '}' ;
64+ }
65+
66+ private static string PlaceholderName ( string segment )
67+ {
68+ return segment . Trim ( '{' , '}' ) ;
69+ }
70+
71+ private bool TryMatchMethod ( MethodInfo method , string command , out List < object > args )
72+ {
73+ args = new List < object > ( ) ;
74+
75+ var attributes = method . GetCustomAttributes ( typeof ( InlineCommandAttribute ) , inherit : false ) ;
76+ if ( attributes . Length == 0 )
77+ {
78+ return false ;
79+ }
80+
81+ var incomingCommandParts = command . Split ( '/' ) ;
82+ var methodParameters = method . GetParameters ( ) ;
5983
6084 foreach ( var attribute in attributes )
6185 {
62- if ( ! ( attribute is InlineCommandAttribute botAttribute ) // Skip if the attribute is not of type InlineCommandAttribute
63- || ( method . GetParameters ( ) . Length == 0 && botAttribute . Command != command ) ) // Skip methods without parameters if the command does not match
86+ if ( ! ( attribute is InlineCommandAttribute botAttribute ) )
87+ {
88+ continue ;
89+ }
90+
91+ var controllerCommandParts = botAttribute . Command . Split ( '/' ) ;
92+
93+ // Exact match shortcut for methods without parameters
94+ if ( methodParameters . Length == 0 )
6495 {
65- continue ;
96+ if ( string . Equals ( botAttribute . Command , command , StringComparison . Ordinal ) )
97+ {
98+ return true ;
99+ }
100+ continue ;
66101 }
67102
68- string [ ] controllerCommandParts = botAttribute . Command . Split ( '/' ) ;
69103 if ( controllerCommandParts . Length != incomingCommandParts . Length )
70104 {
71105 continue ;
72106 }
73107
108+ var tempArgs = new List < object > ( incomingCommandParts . Length ) ;
74109 bool match = true ;
110+
75111 for ( int i = 0 ; i < controllerCommandParts . Length ; i ++ )
76112 {
77- if ( controllerCommandParts [ i ] != incomingCommandParts [ i ]
78- && ! controllerCommandParts [ i ] . StartsWith ( '{' )
79- && ! controllerCommandParts [ i ] . EndsWith ( '}' ) )
80- {
81- match = false ;
82- break ;
83- }
113+ var controllerPart = controllerCommandParts [ i ] ;
114+ var incomingPart = incomingCommandParts [ i ] ;
84115
85- if ( controllerCommandParts [ i ] . StartsWith ( '{' ) && controllerCommandParts [ i ] . EndsWith ( '}' ) )
116+ if ( IsPlaceholder ( controllerPart ) )
86117 {
87- var parameter = method . GetParameters ( ) . FirstOrDefault ( p => p . Name == controllerCommandParts [ i ] . Trim ( '{' , '}' ) ) ;
118+ var name = PlaceholderName ( controllerPart ) ;
119+ var parameter = methodParameters . FirstOrDefault ( p => p . Name == name ) ;
88120 if ( parameter != null )
89121 {
90- if ( ! TryConvertToType ( incomingCommandParts [ i ] , parameter . ParameterType ) )
122+ if ( ! TryConvertToType ( incomingPart , parameter . ParameterType ) )
91123 {
92- match = false ; // If type conversion fails, break the match
124+ match = false ;
93125 break ;
94126 }
95127 }
96- _args . Add ( incomingCommandParts [ i ] ) ;
128+ tempArgs . Add ( incomingPart ) ;
129+ }
130+ else if ( ! string . Equals ( controllerPart , incomingPart , StringComparison . Ordinal ) )
131+ {
132+ match = false ;
133+ break ;
97134 }
98135 }
99136
100137 if ( match )
101138 {
139+ args = tempArgs ;
102140 return true ;
103141 }
104142 }
143+
105144 return false ;
106145 }
107146
0 commit comments