10
10
use BushlanovDev \MaxMessengerBot \Enums \UploadType ;
11
11
use BushlanovDev \MaxMessengerBot \Exceptions \ClientApiException ;
12
12
use BushlanovDev \MaxMessengerBot \Exceptions \NetworkException ;
13
- use BushlanovDev \MaxMessengerBot \Exceptions \SecurityException ;
14
13
use BushlanovDev \MaxMessengerBot \Exceptions \SerializationException ;
15
14
use BushlanovDev \MaxMessengerBot \Models \AbstractModel ;
16
15
use BushlanovDev \MaxMessengerBot \Models \Attachments \Requests \AbstractAttachmentRequest ;
31
30
use BushlanovDev \MaxMessengerBot \Models \Result ;
32
31
use BushlanovDev \MaxMessengerBot \Models \Subscription ;
33
32
use BushlanovDev \MaxMessengerBot \Models \UpdateList ;
34
- use BushlanovDev \MaxMessengerBot \Models \Updates \AbstractUpdate ;
35
33
use BushlanovDev \MaxMessengerBot \Models \UploadEndpoint ;
36
34
use BushlanovDev \MaxMessengerBot \Models \VideoAttachmentDetails ;
37
35
use InvalidArgumentException ;
38
36
use LogicException ;
39
- use Psr \Http \Message \ServerRequestInterface ;
40
37
use Psr \Log \LoggerInterface ;
41
38
use Psr \Log \NullLogger ;
42
39
use ReflectionException ;
@@ -83,13 +80,16 @@ class Api
83
80
84
81
private readonly LoggerInterface $ logger ;
85
82
83
+ private readonly UpdateDispatcher $ updateDispatcher ;
84
+
86
85
/**
87
86
* Api constructor.
88
87
*
89
88
* @param string $accessToken Your bot's access token from @MasterBot.
90
89
* @param ClientApiInterface|null $client Http api client.
91
- * @param ModelFactory|null $modelFactory
92
- * @param LoggerInterface|null $logger
90
+ * @param ModelFactory|null $modelFactory The model factory.
91
+ * @param LoggerInterface|null $logger PSR LoggerInterface.
92
+ * @param UpdateDispatcher|null $updateDispatcher The update dispatcher.
93
93
*
94
94
* @throws InvalidArgumentException
95
95
*/
@@ -98,6 +98,7 @@ public function __construct(
98
98
?ClientApiInterface $ client = null ,
99
99
?ModelFactory $ modelFactory = null ,
100
100
?LoggerInterface $ logger = null ,
101
+ ?UpdateDispatcher $ updateDispatcher = null ,
101
102
) {
102
103
$ this ->logger = $ logger ?? new NullLogger ();
103
104
@@ -129,6 +130,7 @@ public function __construct(
129
130
130
131
$ this ->client = $ client ;
131
132
$ this ->modelFactory = $ modelFactory ?? new ModelFactory ();
133
+ $ this ->updateDispatcher = $ updateDispatcher ?? new UpdateDispatcher ($ this );
132
134
}
133
135
134
136
/**
@@ -151,67 +153,45 @@ public function request(string $method, string $uri, array $queryParams = [], ar
151
153
}
152
154
153
155
/**
154
- * Creates a WebhookHandler instance, pre-configured with the necessary dependencies.
155
- *
156
- * @param string|null $secret The secret key for request verification.
157
- * Should be the same one you used when calling the subscribe() method.
156
+ * Gets the central update dispatcher instance. Use this to register your event and command handlers.
158
157
*
159
- * @return WebhookHandler
158
+ * @return UpdateDispatcher
159
+ * @codeCoverageIgnore
160
160
*/
161
- public function createWebhookHandler (? string $ secret = null ): WebhookHandler
161
+ public function getUpdateDispatcher ( ): UpdateDispatcher
162
162
{
163
- return new WebhookHandler ( $ this , $ this -> modelFactory , $ secret , $ this -> logger ) ;
163
+ return $ this -> updateDispatcher ;
164
164
}
165
165
166
166
/**
167
- * Parses an incoming webhook request and returns a single Update object.
168
- * This is an alternative to the event-driven WebhookHandler::handle() method,
169
- * allowing for manual processing of updates.
167
+ * Creates a WebhookHandler instance, pre-configured with the necessary dependencies.
170
168
*
171
- * @param string|null $secret The secret key to verify the request signature.
172
- * @param ServerRequestInterface|null $request The PSR-7 request object. If null, it's created from globals.
169
+ * @param string|null $secret The secret key for request verification.
173
170
*
174
- * @return AbstractUpdate The parsed update object (e.g., MessageCreatedUpdate).
175
- * @throws \ReflectionException
176
- * @throws SecurityException
177
- * @throws SerializationException
178
- * @throws \LogicException
171
+ * @return WebhookHandler
179
172
*/
180
- public function getWebhookUpdate (?string $ secret = null , ? ServerRequestInterface $ request = null ): AbstractUpdate
173
+ public function createWebhookHandler (?string $ secret = null ): WebhookHandler
181
174
{
182
- return $ this ->createWebhookHandler ($ secret )->getUpdate ($ request );
175
+ return new WebhookHandler (
176
+ $ this ->updateDispatcher ,
177
+ $ this ->modelFactory ,
178
+ $ this ->logger ,
179
+ $ secret ,
180
+ );
183
181
}
184
182
185
183
/**
186
- * A simple way to process a single incoming webhook request using callbacks.
187
- * This method creates a WebhookHandler, registers the provided callbacks, and processes the request.
184
+ * Creates a LongPollingHandler instance, pre-configured for running a long-polling loop.
188
185
*
189
- * @param array<string, callable> $handlers An associative array where keys are UpdateType string values
190
- * (e.g., UpdateType::MessageCreated->value) and values are handlers.
191
- * @param string|null $secret The secret key for request verification.
192
- * @param ServerRequestInterface|null $request The PSR-7 request object.
193
- *
194
- * @throws SecurityException
195
- * @throws SerializationException
196
- * @throws ReflectionException
197
- * @throws LogicException
186
+ * @return LongPollingHandler
198
187
*/
199
- public function handleWebhooks (
200
- array $ handlers ,
201
- ?string $ secret = null ,
202
- ?ServerRequestInterface $ request = null ,
203
- ): void {
204
- $ webhookHandler = $ this ->createWebhookHandler ($ secret );
205
-
206
- foreach ($ handlers as $ updateType => $ callback ) {
207
- $ updateType = UpdateType::tryFrom ($ updateType );
208
- // @phpstan-ignore-next-line
209
- if ($ updateType && is_callable ($ callback )) {
210
- $ webhookHandler ->addHandler ($ updateType , $ callback );
211
- }
212
- }
213
-
214
- $ webhookHandler ->handle ($ request );
188
+ public function createLongPollingHandler (): LongPollingHandler
189
+ {
190
+ return new LongPollingHandler (
191
+ $ this ,
192
+ $ this ->updateDispatcher ,
193
+ $ this ->logger ,
194
+ );
215
195
}
216
196
217
197
/**
@@ -251,64 +231,6 @@ public function getUpdates(
251
231
);
252
232
}
253
233
254
- /**
255
- * Starts a long-polling loop to process updates using callbacks.
256
- * This method will run indefinitely until the script is terminated.
257
- *
258
- * @param array<string, callable> $handlers An associative array where keys are UpdateType enums
259
- * and values are the corresponding handler functions.
260
- * @param int|null $timeout Timeout in seconds for long polling (0-90). Defaults to 90.
261
- * @param int|null $marker Pass `null` to get updates you didn't get yet.
262
- */
263
- public function handleUpdates (array $ handlers , ?int $ timeout = null , ?int $ marker = null ): void
264
- {
265
- // @phpstan-ignore-next-line
266
- while (true ) {
267
- try {
268
- $ this ->processUpdatesBatch ($ handlers , $ timeout , $ marker );
269
- } catch (NetworkException $ e ) {
270
- $ this ->logger ->error (
271
- 'Long-polling network error: {message} ' ,
272
- ['message ' => $ e ->getMessage (), 'exception ' => $ e ],
273
- );
274
- sleep (5 );
275
- } catch (\Exception $ e ) {
276
- $ this ->logger ->error (
277
- 'An error occurred during long-polling: {message} ' ,
278
- ['message ' => $ e ->getMessage (), 'exception ' => $ e ],
279
- );
280
- sleep (1 );
281
- }
282
- }
283
- }
284
-
285
- /**
286
- * Processes a single batch of updates. This is the core logic used by handleUpdates().
287
- * Useful for custom loop implementations or for testing.
288
- *
289
- * @param array<string, callable> $handlers An associative array of update handlers.
290
- * @param int|null $timeout Timeout for the getUpdates call.
291
- * @param int|null $marker The marker for which updates to fetch.
292
- *
293
- * @throws ClientApiException
294
- * @throws NetworkException
295
- * @throws ReflectionException
296
- * @throws SerializationException
297
- */
298
- public function processUpdatesBatch (array $ handlers , ?int $ timeout , ?int &$ marker = null ): void
299
- {
300
- $ updateList = $ this ->getUpdates (timeout: $ timeout , marker: $ marker );
301
-
302
- foreach ($ updateList ->updates as $ update ) {
303
- $ handler = $ handlers [$ update ->updateType ->value ] ?? null ;
304
- if ($ handler ) {
305
- $ handler ($ update , $ this );
306
- }
307
- }
308
-
309
- $ marker = $ updateList ->marker ;
310
- }
311
-
312
234
/**
313
235
* Information about the current bot, identified by an access token.
314
236
*
0 commit comments