Completed
Push — develop ( 23b8a0...80c8c3 )
by Michele
11:06
created

TelegramTrait::copyMessage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 4
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Zanzara\Telegram;
6
7
use Clue\React\Buzz\Browser;
8
use Clue\React\Buzz\Message\ResponseException;
9
use Psr\Container\ContainerInterface;
10
use Psr\Http\Message\ResponseInterface;
11
use React\Filesystem\Filesystem;
12
use React\Promise\PromiseInterface;
13
use RingCentral\Psr7\MultipartStream;
14
use Zanzara\Config;
15
use Zanzara\MessageQueue;
16
use Zanzara\Telegram\Type\CallbackQuery;
17
use Zanzara\Telegram\Type\Chat;
18
use Zanzara\Telegram\Type\ChatMember;
19
use Zanzara\Telegram\Type\File\File;
20
use Zanzara\Telegram\Type\File\StickerSet;
21
use Zanzara\Telegram\Type\File\UserProfilePhotos;
22
use Zanzara\Telegram\Type\Game\GameHighScore;
23
use Zanzara\Telegram\Type\Input\InputFile;
24
use Zanzara\Telegram\Type\Message;
25
use Zanzara\Telegram\Type\MessageId;
26
use Zanzara\Telegram\Type\Poll\Poll;
27
use Zanzara\Telegram\Type\Response\TelegramException;
28
use Zanzara\Telegram\Type\Update;
29
use Zanzara\Telegram\Type\User;
30
use Zanzara\Telegram\Type\Webhook\WebhookInfo;
31
use Zanzara\ZanzaraLogger;
32
use Zanzara\ZanzaraMapper;
33
use function React\Promise\all;
34
35
/**
36
 * Class that interacts with Telegram Api.
37
 * Made trait in order to be used both by Telegram and Context classes.
38
 *
39
 * @see Telegram
40
 * @see Context
41
 */
42
trait TelegramTrait
43
{
44
45
    /**
46
     * @var ContainerInterface
47
     */
48
    protected $container;
49
50
    /**
51
     * @var Browser
52
     */
53
    protected $browser;
54
55
    /**
56
     * @var Update|null
57
     */
58
    protected $update;
59
60
    /**
61
     * Use this method to receive incoming updates using long polling (wiki). An Array of @see Update objects is returned.
62
     *
63
     * More on https://core.telegram.org/bots/api#getupdates
64
     *
65
     * @param array $opt
66
     * @return PromiseInterface
67
     */
68
    public function getUpdates(array $opt = []): PromiseInterface
69
    {
70
        $method = "getUpdates";
71
        $query = http_build_query($opt);
72
73
        $browser = $this->browser->withOptions(array(
74
            "timeout" => $opt['timeout'] + 10 //timout browser necessary bigger than telegram timeout. They can't be equal
75
        ));
76
77
        return $this->wrapPromise($browser->get("$method?$query"), $method, $opt, Update::class);
78
    }
79
80
    /**
81
     * A simple method for testing your bot's auth token. Requires no parameters. Returns basic information about the
82
     * bot in form of a User object.
83
     *
84
     * @return PromiseInterface
85
     */
86
    public function getMe(): PromiseInterface
87
    {
88
        return $this->callApi("getMe", [], User::class);
89
    }
90
91
    /**
92
     * Use this method to send text messages. On success, the sent @see Message is returned.
93
     *
94
     * By default the message is sent to the chat_id of the context's update. Use $opt param to specify a different
95
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
96
     *
97
     * More on https://core.telegram.org/bots/api#sendmessage
98
     *
99
     * @param string $text
100
     * @param array $opt = [
101
     *     'chat_id' => 123456789,
102
     *     'parse_mode' => 'HTML',
103
     *     'disable_web_page_preview' => true,
104
     *     'disable_notification' => true,
105
     *     'reply_to_message_id' => 123456789,
106
     *     'reply_markup' => ['force_reply' => true],
107
     *     'reply_markup' => ['inline_keyboard' => [[
108
     *          ['callback_data' => 'data', 'text' => 'text']
109
     *      ]]],
110
     *      'reply_markup' => ['resize_keyboard' => true, 'one_time_keyboard' => true, 'selective' => true, 'keyboard' => [[
111
     *          ['text' => 'text', 'request_contact' => true, 'request_location' => true, 'request_poll' => ['type' => 'quiz']]
112
     *      ]]]
113
     * ]
114
     * @return PromiseInterface
115
     */
116
    public function sendMessage(string $text, array $opt = [])
117
    {
118
        $opt = $this->resolveChatId($opt);
119
        $required = compact("text");
120
        $params = array_merge($required, $opt);
121
        return $this->doSendMessage($params);
122
    }
123
124
    /**
125
     * Do not use it. Use @see TelegramTrait::sendMessage() instead.
126
     *
127
     * @internal
128
     * @param array $params
129
     * @return PromiseInterface
130
     */
131
    public function doSendMessage(array $params): PromiseInterface
132
    {
133
        return $this->callApi("sendMessage", $params, Message::class);
134
    }
135
136
    /**
137
     * Use this method to send a message to many chats. This method takes care of sending the message
138
     * with a delay in order avoid 429 Telegram errors (https://core.telegram.org/bots/faq#broadcasting-to-users).
139
     *
140
     * Eg. $ctx->sendBulkMessage([1111111111, 2222222222, 333333333], 'A wonderful notification', [parse_mode => 'HTML']);
141
     *
142
     * More on https://core.telegram.org/bots/api#sendmessage
143
     *
144
     * @param array $chatIds
145
     * @param string $text
146
     * @param array $opt
147
     */
148
    public function sendBulkMessage(array $chatIds, string $text, array $opt = []): void
149
    {
150
        $this->container->get(MessageQueue::class)
151
            ->push($chatIds, $text, $opt);
152
    }
153
154
    /**
155
     * Use this method to specify a url and receive incoming updates via an outgoing webhook. Whenever there is an update
156
     * for the bot, we will send an HTTPS POST request to the specified url, containing a JSON-serialized Update. In case
157
     * of an unsuccessful request, we will give up after a reasonable amount of attempts. Returns True on success.
158
     *
159
     * More on https://core.telegram.org/bots/api#setwebhook
160
     *
161
     * @param string $url
162
     * @param array $opt
163
     * @return PromiseInterface
164
     */
165
    public function setWebhook(string $url, array $opt = []): PromiseInterface
166
    {
167
        $required = compact("url");
168
        $params = array_merge($required, $opt);
169
        return $this->callApi("setWebhook", $params);
170
    }
171
172
    /**
173
     * Use this method to get current webhook status. Requires no parameters. On success, returns a @see WebhookInfo object.
174
     * If the bot is using getUpdates, will return an object with the url field empty.
175
     *
176
     * More on https://core.telegram.org/bots/api#getwebhookinfo
177
     *
178
     * @return PromiseInterface
179
     */
180
    public function getWebhookInfo(): PromiseInterface
181
    {
182
        return $this->callApi("getWebhookInfo", [], WebhookInfo::class);
183
    }
184
185
    /**
186
     * Use this method to remove webhook integration if you decide to switch back to getUpdates. Returns True on
187
     * success. Requires no parameters.
188
     *
189
     * More on https://core.telegram.org/bots/api#deletewebhook
190
     *
191
     * @param array $opt
192
     * @return PromiseInterface
193
     */
194
    public function deleteWebhook($opt = []): PromiseInterface
195
    {
196
        return $this->callApi("deleteWebhook", $opt);
197
    }
198
199
    /**
200
     * Use this method to forward messages of any kind. On success, the sent @see Message is returned.
201
     *
202
     * More on https://core.telegram.org/bots/api#forwardmessage
203
     *
204
     * @param $chat_id
205
     * @param $from_chat_id
206
     * @param $message_id
207
     * @param array $opt
208
     * @return PromiseInterface
209
     */
210
    public function forwardMessage($chat_id, $from_chat_id, $message_id, array $opt = []): PromiseInterface
211
    {
212
        $required = compact("chat_id", "from_chat_id", "message_id");
213
        $params = array_merge($required, $opt);
214
        return $this->callApi("forwardMessage", $params, Message::class);
215
    }
216
217
    /**
218
     * Use this method to copy messages of any kind. The method is analogous to the method forwardMessages, but the
219
     * copied message doesn't have a link to the original message. Returns the MessageId of the sent message on success.
220
     *
221
     * More on https://core.telegram.org/bots/api#copymessage
222
     *
223
     * @since zanzara 0.5.0, Telegram Bot Api 5.0
224
     *
225
     * @param $chat_id
226
     * @param $from_chat_id
227
     * @param $message_id
228
     * @param array $opt
229
     * @return PromiseInterface
230
     */
231
    public function copyMessage($chat_id, $from_chat_id, $message_id, array $opt = []): PromiseInterface
232
    {
233
        $required = compact("chat_id", "from_chat_id", "message_id");
234
        $params = array_merge($required, $opt);
235
        return $this->callApi("copyMessage", $params, MessageId::class);
236
    }
237
238
    /**
239
     * Use this method to send photos. On success, the sent @see Message is returned.
240
     *
241
     * The photo param can be either a string or a @see InputFile. Note that if you use the latter the file reading
242
     * operation is synchronous, so the main thread is blocked.
243
     * To make it asynchronous see https://github.com/badfarm/zanzara/wiki#working-with-files.
244
     *
245
     * By default the photo is sent to the chat_id of the context's update. Use $opt param to specify a different
246
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
247
     *
248
     * More on https://core.telegram.org/bots/api#sendphoto
249
     *
250
     * @param $photo
251
     * @param array $opt
252
     * @return PromiseInterface
253
     */
254
    public function sendPhoto($photo, array $opt = []): PromiseInterface
255
    {
256
        $opt = $this->resolveChatId($opt);
257
        $required = compact("photo");
258
        $params = array_merge($required, $opt);
259
        return $this->callApi("sendPhoto", $params, Message::class);
260
    }
261
262
    /**
263
     * Use this method to send audio files, if you want Telegram clients to display them in the music player. Your audio
264
     * must be in the .MP3 or .M4A format. On success, the sent @see Message is returned. Bots can currently send audio files
265
     * of up to 50 MB in size, this limit may be changed in the future.
266
     *
267
     * The audio and thumb params can be either a string or a @see InputFile. Note that if you use the latter the file reading
268
     * operation is synchronous, so the main thread is blocked.
269
     * To make it asynchronous see https://github.com/badfarm/zanzara/wiki#working-with-files.
270
     *
271
     * By default the audio is sent to the chat_id of the context's update. Use $opt param to specify a different
272
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
273
     *
274
     * More on https://core.telegram.org/bots/api#sendaudio
275
     *
276
     * @param $audio
277
     * @param array $opt
278
     * @return PromiseInterface
279
     */
280
    public function sendAudio($audio, array $opt = []): PromiseInterface
281
    {
282
        $opt = $this->resolveChatId($opt);
283
        $required = compact("audio");
284
        $params = array_merge($required, $opt);
285
        return $this->callApi("sendAudio", $params, Message::class);
286
    }
287
288
    /**
289
     * Use this method to send general files. On success, the sent @see Message is returned. Bots can currently send files of any
290
     * type of up to 50 MB in size, this limit may be changed in the future.
291
     *
292
     * The document and thumb params can be either a string or a @see InputFile. Note that if you use the latter the file reading
293
     * operation is synchronous, so the main thread is blocked.
294
     * To make it asynchronous see https://github.com/badfarm/zanzara/wiki#working-with-files.
295
     *
296
     * By default the document is sent to the chat_id of the context's update. Use $opt param to specify a different
297
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
298
     *
299
     * More on https://core.telegram.org/bots/api#senddocument
300
     *
301
     * @param $document
302
     * @param array $opt
303
     * @return PromiseInterface
304
     */
305
    public function sendDocument($document, array $opt = []): PromiseInterface
306
    {
307
        $opt = $this->resolveChatId($opt);
308
        $required = compact("document");
309
        $params = array_merge($required, $opt);
310
        return $this->callApi("sendDocument", $params, Message::class);
311
    }
312
313
    /**
314
     * Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). On
315
     * success, the sent @see Message is returned. Bots can currently send video files of up to 50 MB in size, this limit may
316
     * be changed in the future.
317
     *
318
     * The video and thumb params can be either a string or a @see InputFile. Note that if you use the latter the file reading
319
     * operation is synchronous, so the main thread is blocked.
320
     * To make it asynchronous see https://github.com/badfarm/zanzara/wiki#working-with-files.
321
     *
322
     * By default the video is sent to the chat_id of the context's update. Use $opt param to specify a different
323
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
324
     *
325
     * More on https://core.telegram.org/bots/api#sendvideo
326
     *
327
     * @param $video
328
     * @param array $opt
329
     * @return PromiseInterface
330
     */
331
    public function sendVideo($video, array $opt = []): PromiseInterface
332
    {
333
        $opt = $this->resolveChatId($opt);
334
        $required = compact("video");
335
        $params = array_merge($required, $opt);
336
        return $this->callApi("sendVideo", $params, Message::class);
337
    }
338
339
    /**
340
     * Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). On success, the sent @see Message
341
     * is returned. Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the
342
     * future.
343
     *
344
     * The animation and thumb params can be either a string or a @see InputFile. Note that if you use the latter the file reading
345
     * operation is synchronous, so the main thread is blocked.
346
     * To make it asynchronous see https://github.com/badfarm/zanzara/wiki#working-with-files.
347
     *
348
     * By default the animation is sent to the chat_id of the context's update. Use $opt param to specify a different
349
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
350
     *
351
     * More on https://core.telegram.org/bots/api#sendanimation
352
     *
353
     * @param $animation
354
     * @param array $opt
355
     * @return PromiseInterface
356
     */
357
    public function sendAnimation($animation, array $opt = []): PromiseInterface
358
    {
359
        $opt = $this->resolveChatId($opt);
360
        $required = compact("animation");
361
        $params = array_merge($required, $opt);
362
        return $this->callApi("sendAnimation", $params, Message::class);
363
    }
364
365
    /**
366
     * Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message.
367
     * For this to work, your audio must be in an .OGG file encoded with OPUS (other formats may be sent as Audio or
368
     * Document). On success, the sent @see Message is returned. Bots can currently send voice messages of up to 50 MB in
369
     * size, this limit may be changed in the future.
370
     *
371
     * The voice param can be either a string or a @see InputFile. Note that if you use the latter the file reading
372
     * operation is synchronous, so the main thread is blocked.
373
     * To make it asynchronous see https://github.com/badfarm/zanzara/wiki#working-with-files.
374
     *
375
     * By default the voice is sent to the chat_id of the context's update. Use $opt param to specify a different
376
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
377
     *
378
     * More on https://core.telegram.org/bots/api#sendvoice
379
     *
380
     * @param $voice
381
     * @param array $opt
382
     * @return PromiseInterface
383
     */
384
    public function sendVoice($voice, array $opt = []): PromiseInterface
385
    {
386
        $opt = $this->resolveChatId($opt);
387
        $required = compact("voice");
388
        $params = array_merge($required, $opt);
389
        return $this->callApi("sendVoice", $params, Message::class);
390
    }
391
392
    /**
393
     * As of v.4.0, Telegram clients support rounded square mp4 videos of up to 1 minute long. Use this method to send video
394
     * messages. On success, the sent @see Message is returned.
395
     *
396
     * The video_note and thumb params can be either a string or a @see InputFile. Note that if you use the latter the file reading
397
     * operation is synchronous, so the main thread is blocked.
398
     * To make it asynchronous see https://github.com/badfarm/zanzara/wiki#working-with-files.
399
     *
400
     * By default the video note is sent to the chat_id of the context's update. Use $opt param to specify a different
401
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
402
     *
403
     * More on https://core.telegram.org/bots/api#sendvideonote
404
     *
405
     * @param $video_note
406
     * @param array $opt
407
     * @return PromiseInterface
408
     */
409
    public function sendVideoNote($video_note, array $opt = []): PromiseInterface
410
    {
411
        $opt = $this->resolveChatId($opt);
412
        $required = compact("video_note");
413
        $params = array_merge($required, $opt);
414
        return $this->callApi("sendVideoNote", $params, Message::class);
415
    }
416
417
    /**
418
     * Use this method to send a group of photos, videos, documents or audios as an album. Documents and audio files can
419
     * be only group in an album with messages of the same type. On success, an array of @see Message 's that were sent
420
     * is returned.
421
     *
422
     * By default the media group is sent to the chat_id of the context's update. Use $opt param to specify a different
423
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
424
     *
425
     * More on https://core.telegram.org/bots/api#sendmediagroup
426
     *
427
     * @param $media
428
     * @param array $opt
429
     * @return PromiseInterface
430
     */
431
    public function sendMediaGroup($media, array $opt = []): PromiseInterface
432
    {
433
        $opt = $this->resolveChatId($opt);
434
        $required = compact("media");
435
        $params = array_merge($required, $opt);
436
        return $this->callApi("sendMediaGroup", $params, Message::class);
437
    }
438
439
    /**
440
     * Use this method to send point on the map. On success, the sent @see Message is returned.
441
     *
442
     * By default the location is sent to the chat_id of the context's update. Use $opt param to specify a different
443
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
444
     *
445
     * More on https://core.telegram.org/bots/api#sendlocation
446
     *
447
     * @param $latitude
448
     * @param $longitude
449
     * @param array $opt
450
     * @return PromiseInterface
451
     */
452
    public function sendLocation($latitude, $longitude, array $opt = []): PromiseInterface
453
    {
454
        $opt = $this->resolveChatId($opt);
455
        $required = compact("latitude", "longitude");
456
        $params = array_merge($required, $opt);
457
        return $this->callApi("sendLocation", $params, Message::class);
458
    }
459
460
    /**
461
     * Use this method to edit live location messages. A location can be edited until its live_period expires or editing is
462
     * explicitly disabled by a call to stopMessageLiveLocation. On success, if the edited message was sent by the bot,
463
     * the edited @see Message is returned, otherwise True is returned.
464
     *
465
     * By default the chat_id is taken from the context's update. Use $opt param to specify a different
466
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
467
     *
468
     * By default the message_id is taken from the context's update. Use $opt param to specify a different
469
     * message_id. Eg. $opt = ['message_id' => 123456789];
470
     *
471
     * By default the inline_message_id is taken from the context's update. Use $opt param to specify a different
472
     * inline_message_id. Eg. $opt = ['inline_message_id' => 123456789];
473
     *
474
     * More on https://core.telegram.org/bots/api#editmessagelivelocation
475
     *
476
     * @param $latitude
477
     * @param $longitude
478
     * @param array $opt
479
     * @return PromiseInterface
480
     */
481
    public function editMessageLiveLocation($latitude, $longitude, array $opt = []): PromiseInterface
482
    {
483
        $opt = $this->resolveMessageId($opt);
484
        $required = compact("latitude", "longitude");
485
        $params = array_merge($required, $opt);
486
        return $this->callApi("editMessageLiveLocation", $params, Message::class);
487
    }
488
489
    /**
490
     * Use this method to stop updating a live location message before live_period expires. On success, if the message was
491
     * sent by the bot, the sent @see Message is returned, otherwise True is returned.
492
     *
493
     * By default the chat_id is taken from the context's update. Use $opt param to specify a different
494
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
495
     *
496
     * By default the message_id is taken from the context's update. Use $opt param to specify a different
497
     * message_id. Eg. $opt = ['message_id' => 123456789];
498
     *
499
     * By default the inline_message_id is taken from the context's update. Use $opt param to specify a different
500
     * inline_message_id. Eg. $opt = ['inline_message_id' => 123456789];
501
     *
502
     * More on https://core.telegram.org/bots/api#stopmessagelivelocation
503
     *
504
     * @param array $opt
505
     * @return PromiseInterface
506
     */
507
    public function stopMessageLiveLocation(array $opt = []): PromiseInterface
508
    {
509
        $opt = $this->resolveMessageId($opt);
510
        return $this->callApi("stopMessageLiveLocation", $opt, Message::class);
511
    }
512
513
    /**
514
     * Use this method to send information about a venue. On success, the sent @see Message is returned.
515
     *
516
     * By default the venue is sent to the chat_id of the context's update. Use $opt param to specify a different
517
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
518
     *
519
     * More on https://core.telegram.org/bots/api#sendvenue
520
     *
521
     * @param $latitude
522
     * @param $longitude
523
     * @param string $title
524
     * @param string $address
525
     * @param array $opt
526
     * @return PromiseInterface
527
     */
528
    public function sendVenue($latitude, $longitude, string $title, string $address, array $opt = []): PromiseInterface
529
    {
530
        $opt = $this->resolveChatId($opt);
531
        $required = compact("latitude", "longitude", "title", "address");
532
        $params = array_merge($required, $opt);
533
        return $this->callApi("sendVenue", $params, Message::class);
534
    }
535
536
    /**
537
     * Use this method to send phone contacts. On success, the sent @see Message is returned.
538
     *
539
     * By default the contact is sent to the chat_id of the context's update. Use $opt param to specify a different
540
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
541
     *
542
     * More on https://core.telegram.org/bots/api#sendcontact
543
     *
544
     * @param string $phone_number
545
     * @param string $first_name
546
     * @param array $opt
547
     * @return PromiseInterface
548
     */
549
    public function sendContact(string $phone_number, string $first_name, array $opt = []): PromiseInterface
550
    {
551
        $opt = $this->resolveChatId($opt);
552
        $required = compact("phone_number", "first_name");
553
        $params = array_merge($required, $opt);
554
        return $this->callApi("sendContact", $params, Message::class);
555
    }
556
557
    /**
558
     * Use this method to send a native poll. On success, the sent @see Message is returned.
559
     *
560
     * By default the poll is sent to the chat_id of the context's update. Use $opt param to specify a different
561
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
562
     *
563
     * More on https://core.telegram.org/bots/api#sendpoll
564
     *
565
     * @param string $question
566
     * @param $options
567
     * @param array $opt
568
     * @return PromiseInterface
569
     */
570
    public function sendPoll(string $question, $options, array $opt = []): PromiseInterface
571
    {
572
        $opt = $this->resolveChatId($opt);
573
        $required = compact("question", "options");
574
        $params = array_merge($required, $opt);
575
        return $this->callApi("sendPoll", $params, Message::class);
576
    }
577
578
    /**
579
     * Use this method to send a dice, which will have a random value from 1 to 6. On success, the sent @see Message is returned.
580
     * (Yes, we're aware of the "proper" singular of die. But it's awkward, and we decided to help it change. One dice at
581
     * a time!)
582
     *
583
     * By default the dice is sent to the chat_id of the context's update. Use $opt param to specify a different
584
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
585
     *
586
     * More on https://core.telegram.org/bots/api#senddice
587
     *
588
     * @param array $opt
589
     * @return PromiseInterface
590
     */
591
    public function sendDice(array $opt = []): PromiseInterface
592
    {
593
        $opt = $this->resolveChatId($opt);
594
        return $this->callApi("sendDice", $opt, Message::class);
595
    }
596
597
    /**
598
     * Use this method when you need to tell the user that something is happening on the bot's side. The status is set for 5
599
     * seconds or less (when a message arrives from your bot, Telegram clients clear its typing status). Returns True on
600
     * success.
601
     *
602
     * By default the chat action is sent to the chat_id of the context's update. Use $opt param to specify a different
603
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
604
     *
605
     * More on https://core.telegram.org/bots/api#sendchataction
606
     *
607
     * @param string $action
608
     * @param array $opt
609
     * @return PromiseInterface
610
     */
611
    public function sendChatAction(string $action, array $opt = []): PromiseInterface
612
    {
613
        $opt = $this->resolveChatId($opt);
614
        $required = compact("action");
615
        $params = array_merge($required, $opt);
616
        return $this->callApi("sendChatAction", $params);
617
    }
618
619
    /**
620
     * Use this method to get a list of profile pictures for a user. Returns a @see UserProfilePhotos object.
621
     *
622
     * More on https://core.telegram.org/bots/api#getuserprofilephotos
623
     *
624
     * @param $user_id
625
     * @param array $opt
626
     * @return PromiseInterface
627
     */
628
    public function getUserProfilePhotos($user_id, array $opt = []): PromiseInterface
629
    {
630
        $required = compact("user_id");
631
        $params = array_merge($required, $opt);
632
        return $this->callApi("getUserProfilePhotos", $params, UserProfilePhotos::class);
633
    }
634
635
    /**
636
     * Use this method to get basic info about a file and prepare it for downloading. For the moment, bots can download
637
     * files of up to 20MB in size. On success, a @see File object is returned. The file can then be downloaded via the link
638
     * https://api.telegram.org/file/bot&lt;token&gt;/&lt;file_path&gt;, where &lt;file_path&gt; is taken from the
639
     * response. It is guaranteed that the link will be valid for at least 1 hour. When the link expires, a new one can
640
     * be requested by calling getFile again.
641
     *
642
     * More on https://core.telegram.org/bots/api#getfile
643
     *
644
     * @param string $file_id
645
     * @param array $opt
646
     * @return PromiseInterface
647
     */
648
    public function getFile(string $file_id, array $opt = []): PromiseInterface
649
    {
650
        $required = compact("file_id");
651
        $params = array_merge($required, $opt);
652
        return $this->callApi("getFile", $params, File::class);
653
    }
654
655
    /**
656
     * Use this method to kick a user from a group, a supergroup or a channel. In the case of supergroups and channels, the
657
     * user will not be able to return to the group on their own using invite links, etc., unless unbanned first. The bot
658
     * must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on
659
     * success.
660
     *
661
     * More on https://core.telegram.org/bots/api#kickchatmember
662
     *
663
     * @param $chat_id
664
     * @param $user_id
665
     * @param array $opt
666
     * @return PromiseInterface
667
     */
668
    public function kickChatMember($chat_id, $user_id, array $opt = []): PromiseInterface
669
    {
670
        $required = compact("chat_id", "user_id");
671
        $params = array_merge($required, $opt);
672
        return $this->callApi("kickChatMember", $params);
673
    }
674
675
    /**
676
     * Use this method to unban a previously kicked user in a supergroup or channel. The user will not return to the
677
     * group or channel automatically, but will be able to join via link, etc. The bot must be an administrator for this
678
     * to work. By default, this method guarantees that after the call the user is not a member of the chat, but will be
679
     * able to join it. So if the user is a member of the chat they will also be removed from the chat. If you don't
680
     * want this, use the parameter only_if_banned. Returns True on success.
681
     *
682
     * More on https://core.telegram.org/bots/api#unbanchatmember
683
     *
684
     * @param $chat_id
685
     * @param $user_id
686
     * @param array $opt
687
     * @return PromiseInterface
688
     */
689
    public function unbanChatMember($chat_id, $user_id, array $opt = []): PromiseInterface
690
    {
691
        $required = compact("chat_id", "user_id");
692
        $params = array_merge($required, $opt);
693
        return $this->callApi("unbanChatMember", $params);
694
    }
695
696
    /**
697
     * Use this method to restrict a user in a supergroup. The bot must be an administrator in the supergroup for this to
698
     * work and must have the appropriate admin rights. Pass True for all permissions to lift restrictions from a user.
699
     * Returns True on success.
700
     *
701
     * More on https://core.telegram.org/bots/api#restrictchatmember
702
     *
703
     * @param $chat_id
704
     * @param $user_id
705
     * @param $permissions
706
     * @param array $opt
707
     * @return PromiseInterface
708
     */
709
    public function restrictChatMember($chat_id, $user_id, $permissions, array $opt = []): PromiseInterface
710
    {
711
        $required = compact("chat_id", "user_id", "permissions");
712
        $params = array_merge($required, $opt);
713
        return $this->callApi("restrictChatMember", $params);
714
    }
715
716
    /**
717
     * Use this method to promote or demote a user in a supergroup or a channel. The bot must be an administrator in the
718
     * chat for this to work and must have the appropriate admin rights. Pass False for all boolean parameters to demote
719
     * a user. Returns True on success.
720
     *
721
     * More on https://core.telegram.org/bots/api#promotechatmember
722
     *
723
     * @param $chat_id
724
     * @param $user_id
725
     * @param array $opt
726
     * @return PromiseInterface
727
     */
728
    public function promoteChatMember($chat_id, $user_id, array $opt = []): PromiseInterface
729
    {
730
        $required = compact("chat_id", "user_id");
731
        $params = array_merge($required, $opt);
732
        return $this->callApi("promoteChatMember", $params);
733
    }
734
735
    /**
736
     * Use this method to set a custom title for an administrator in a supergroup promoted by the bot. Returns True on success.
737
     *
738
     * More on https://core.telegram.org/bots/api#setchatadministratorcustomtitle
739
     *
740
     * @param $chat_id
741
     * @param $user_id
742
     * @param string $custom_title
743
     * @param array $opt
744
     * @return PromiseInterface
745
     */
746
    public function setChatAdministratorCustomTitle($chat_id, $user_id, string $custom_title, array $opt = []): PromiseInterface
747
    {
748
        $required = compact("chat_id", "user_id", "custom_title");
749
        $params = array_merge($required, $opt);
750
        return $this->callApi("setChatAdministratorCustomTitle", $params);
751
    }
752
753
    /**
754
     * Use this method to set default chat permissions for all members. The bot must be an administrator in the group or a
755
     * supergroup for this to work and must have the can_restrict_members admin rights. Returns True on success.
756
     *
757
     * More on https://core.telegram.org/bots/api#setchatpermissions
758
     *
759
     * @param $chat_id
760
     * @param $permissions
761
     * @param array $opt
762
     * @return PromiseInterface
763
     */
764
    public function setChatPermissions($chat_id, $permissions, array $opt = []): PromiseInterface
765
    {
766
        $required = compact("chat_id", "permissions");
767
        $params = array_merge($required, $opt);
768
        return $this->callApi("setChatPermissions", $params);
769
    }
770
771
    /**
772
     * Use this method to generate a new invite link for a chat; any previously generated link is revoked. The bot must be
773
     * an administrator in the chat for this to work and must have the appropriate admin rights. Returns the new invite
774
     * link as String on success.
775
     *
776
     * More on https://core.telegram.org/bots/api#exportchatinvitelink
777
     *
778
     * @param $chat_id
779
     * @param array $opt
780
     * @return PromiseInterface
781
     */
782
    public function exportChatInviteLink($chat_id, array $opt = []): PromiseInterface
783
    {
784
        $required = compact("chat_id");
785
        $params = array_merge($required, $opt);
786
        return $this->callApi("exportChatInviteLink", $params);
787
    }
788
789
    /**
790
     * Use this method to set a new profile photo for the chat. Photos can't be changed for private chats. The bot must be
791
     * an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success.
792
     *
793
     * More on https://core.telegram.org/bots/api#setchatphoto
794
     *
795
     * @param $chat_id
796
     * @param $photo
797
     * @param array $opt
798
     * @return PromiseInterface
799
     */
800
    public function setChatPhoto($chat_id, $photo, array $opt = []): PromiseInterface
801
    {
802
        $required = compact("chat_id", "photo");
803
        $params = array_merge($required, $opt);
804
        return $this->callApi("setChatPhoto", $params); //bool
805
    }
806
807
    /**
808
     * Use this method to delete a chat photo. Photos can't be changed for private chats. The bot must be an administrator
809
     * in the chat for this to work and must have the appropriate admin rights. Returns True on success.
810
     *
811
     * More on https://core.telegram.org/bots/api#deletechatphoto
812
     *
813
     * @param $chat_id
814
     * @param array $opt
815
     * @return PromiseInterface
816
     */
817
    public function deleteChatPhoto($chat_id, array $opt = []): PromiseInterface
818
    {
819
        $required = compact("chat_id");
820
        $params = array_merge($required, $opt);
821
        return $this->callApi("deleteChatPhoto", $params);
822
    }
823
824
    /**
825
     * Use this method to change the title of a chat. Titles can't be changed for private chats. The bot must be an
826
     * administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success.
827
     *
828
     * More on https://core.telegram.org/bots/api#setchattitle
829
     *
830
     * @param $chat_id
831
     * @param string $title
832
     * @param array $opt
833
     * @return PromiseInterface
834
     */
835
    public function setChatTitle($chat_id, string $title, array $opt = []): PromiseInterface
836
    {
837
        $required = compact("chat_id", "title");
838
        $params = array_merge($required, $opt);
839
        return $this->callApi("setChatTitle", $params);
840
    }
841
842
    /**
843
     * Use this method to change the description of a group, a supergroup or a channel. The bot must be an administrator in
844
     * the chat for this to work and must have the appropriate admin rights. Returns True on success.
845
     *
846
     * More on https://core.telegram.org/bots/api#setchatdescription
847
     *
848
     * @param $chat_id
849
     * @param array $opt
850
     * @return PromiseInterface
851
     */
852
    public function setChatDescription($chat_id, array $opt = []): PromiseInterface
853
    {
854
        $required = compact("chat_id");
855
        $params = array_merge($required, $opt);
856
        return $this->callApi("setChatDescription", $params);
857
    }
858
859
    /**
860
     * Use this method to pin a message in a group, a supergroup, or a channel. The bot must be an administrator in the chat
861
     * for this to work and must have the 'can_pin_messages' admin right in the supergroup or 'can_edit_messages' admin
862
     * right in the channel. Returns True on success.
863
     *
864
     * More on https://core.telegram.org/bots/api#pinchatmessage
865
     *
866
     * @param $chat_id
867
     * @param $message_id
868
     * @param array $opt
869
     * @return PromiseInterface
870
     */
871
    public function pinChatMessage($chat_id, $message_id, array $opt = []): PromiseInterface
872
    {
873
        $required = compact("chat_id", "message_id");
874
        $params = array_merge($required, $opt);
875
        return $this->callApi("pinChatMessage", $params);
876
    }
877
878
    /**
879
     * Use this method to unpin a message in a group, a supergroup, or a channel. The bot must be an administrator in the
880
     * chat for this to work and must have the 'can_pin_messages' admin right in the supergroup or 'can_edit_messages'
881
     * admin right in the channel. Returns True on success.
882
     *
883
     * More on https://core.telegram.org/bots/api#unpinchatmessage
884
     *
885
     * @param $chat_id
886
     * @param array $opt
887
     * @return PromiseInterface
888
     */
889
    public function unpinChatMessage($chat_id, array $opt = []): PromiseInterface
890
    {
891
        $required = compact("chat_id");
892
        $params = array_merge($required, $opt);
893
        return $this->callApi("unpinChatMessage", $params);
894
    }
895
896
    /**
897
     * Use this method to clear the list of pinned messages in a chat. If the chat is not a private chat, the bot must
898
     * be an administrator in the chat for this to work and must have the 'can_pin_messages' admin right in a supergroup
899
     * or 'can_edit_messages' admin right in a channel. Returns True on success.
900
     *
901
     * By default the chat_id is taken from the context's update. Use $opt param to specify a different
902
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
903
     *
904
     * More on https://core.telegram.org/bots/api#unpinallchatmessages
905
     *
906
     * @since zanzara 0.5.0, Telegram Bot Api 5.0
907
     *
908
     * @param array $opt
909
     * @return PromiseInterface
910
     */
911
    public function unpinAllChatMessages(array $opt = []): PromiseInterface
912
    {
913
        $opt = $this->resolveChatId($opt);
914
        return $this->callApi("unpinAllChatMessages", $opt);
915
    }
916
917
    /**
918
     * Use this method for your bot to leave a group, supergroup or channel. Returns True on success.
919
     *
920
     * More on https://core.telegram.org/bots/api#leavechat
921
     *
922
     * @param $chat_id
923
     * @param array $opt
924
     * @return PromiseInterface
925
     */
926
    public function leaveChat($chat_id, array $opt = []): PromiseInterface
927
    {
928
        $required = compact("chat_id");
929
        $params = array_merge($required, $opt);
930
        return $this->callApi("leaveChat", $params);
931
    }
932
933
    /**
934
     * Use this method to get up to date information about the chat (current name of the user for one-on-one conversations,
935
     * current username of a user, group or channel, etc.). Returns a @see Chat object on success.
936
     *
937
     * More on https://core.telegram.org/bots/api#getchat
938
     *
939
     * @param $chat_id
940
     * @param array $opt
941
     * @return PromiseInterface
942
     */
943
    public function getChat($chat_id, array $opt = []): PromiseInterface
944
    {
945
        $required = compact("chat_id");
946
        $params = array_merge($required, $opt);
947
        return $this->callApi("getChat", $params, Chat::class);
948
    }
949
950
    /**
951
     * Use this method to get a list of administrators in a chat. On success, returns an Array of @see ChatMember objects that
952
     * contains information about all chat administrators except other bots. If the chat is a group or a supergroup and
953
     * no administrators were appointed, only the creator will be returned.
954
     *
955
     * More on https://core.telegram.org/bots/api#getchatadministrators
956
     *
957
     * @param $chat_id
958
     * @param array $opt
959
     * @return PromiseInterface
960
     */
961
    public function getChatAdministrators($chat_id, array $opt = []): PromiseInterface
962
    {
963
        $required = compact("chat_id");
964
        $params = array_merge($required, $opt);
965
        return $this->callApi("getChatAdministrators", $params, ChatMember::class);
966
    }
967
968
    /**
969
     * Use this method to get the number of members in a chat. Returns Int on success.
970
     *
971
     * More on https://core.telegram.org/bots/api#getchatmemberscount
972
     *
973
     * @param $chat_id
974
     * @param array $opt
975
     * @return PromiseInterface
976
     */
977
    public function getChatMembersCount($chat_id, array $opt = []): PromiseInterface
978
    {
979
        $required = compact("chat_id");
980
        $params = array_merge($required, $opt);
981
        return $this->callApi("getChatMembersCount", $params); //integer
982
    }
983
984
    /**
985
     * Use this method to get information about a member of a chat. Returns a @see ChatMember object on success.
986
     *
987
     * More on https://core.telegram.org/bots/api#getchatmember
988
     *
989
     * @param $chat_id
990
     * @param $user_id
991
     * @param array $opt
992
     * @return PromiseInterface
993
     */
994
    public function getChatMember($chat_id, $user_id, array $opt = []): PromiseInterface
995
    {
996
        $required = compact("chat_id", "user_id");
997
        $params = array_merge($required, $opt);
998
        return $this->callApi("getChatMember", $params, ChatMember::class);
999
    }
1000
1001
    /**
1002
     * Use this method to set a new group sticker set for a supergroup. The bot must be an administrator in the chat for
1003
     * this to work and must have the appropriate admin rights. Use the field can_set_sticker_set optionally returned in
1004
     * getChat requests to check if the bot can use this method. Returns True on success.
1005
     *
1006
     * More on https://core.telegram.org/bots/api#setchatstickerset
1007
     *
1008
     * @param $chat_id
1009
     * @param string $sticker_set_name
1010
     * @param array $opt
1011
     * @return PromiseInterface
1012
     */
1013
    public function setChatStickerSet($chat_id, string $sticker_set_name, array $opt = []): PromiseInterface
1014
    {
1015
        $required = compact("chat_id", "sticker_set_name");
1016
        $params = array_merge($required, $opt);
1017
        return $this->callApi("setChatStickerSet", $params);
1018
    }
1019
1020
    /**
1021
     * Use this method to delete a group sticker set from a supergroup. The bot must be an administrator in the chat for
1022
     * this to work and must have the appropriate admin rights. Use the field can_set_sticker_set optionally returned in
1023
     * getChat requests to check if the bot can use this method. Returns True on success.
1024
     *
1025
     * More on https://core.telegram.org/bots/api#deletechatstickerset
1026
     *
1027
     * @param $chat_id
1028
     * @param array $opt
1029
     * @return PromiseInterface
1030
     */
1031
    public function deleteChatStickerSet($chat_id, array $opt = []): PromiseInterface
1032
    {
1033
        $required = compact("chat_id");
1034
        $params = array_merge($required, $opt);
1035
        return $this->callApi("deleteChatStickerSet", $params);
1036
    }
1037
1038
    /**
1039
     * Use this method to send answers to callback queries sent from inline keyboards. The answer will be displayed to the
1040
     * user as a notification at the top of the chat screen or as an alert. On success, True is returned.
1041
     *
1042
     * By default it replies to the callback_query_id of the context's update. Use $opt param to specify a different
1043
     * callback_query_id. Eg. $opt = ['callback_query_id' => 'abcdefgh'];
1044
     *
1045
     * More on https://core.telegram.org/bots/api#answercallbackquery
1046
     *
1047
     * @param array $opt
1048
     * @return PromiseInterface
1049
     */
1050
    public function answerCallbackQuery(array $opt = []): PromiseInterface
1051
    {
1052
        if (!isset($opt['callback_query_id']) && $this->update) {
1053
            $opt['callback_query_id'] = $this->update->getCallbackQuery()->getId();
1054
        }
1055
        return $this->callApi("answerCallbackQuery", $opt);
1056
    }
1057
1058
    /**
1059
     * Use this method to change the list of the bot's commands. Returns True on success.
1060
     *
1061
     * More on https://core.telegram.org/bots/api#setmycommands
1062
     *
1063
     * @param $commands
1064
     * @param array $opt
1065
     * @return PromiseInterface
1066
     */
1067
    public function setMyCommands($commands, array $opt = []): PromiseInterface
1068
    {
1069
        $required = compact("commands");
1070
        $params = array_merge($required, $opt);
1071
        return $this->callApi("setMyCommands", $params);
1072
    }
1073
1074
    /**
1075
     * Use this method to edit text and game messages. On success, if edited message is sent by the bot, the edited @see Message
1076
     * is returned, otherwise True is returned.
1077
     *
1078
     * By default the chat_id is taken from the context's update. Use $opt param to specify a different
1079
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
1080
     *
1081
     * By default the message_id is taken from the context's update. Use $opt param to specify a different
1082
     * message_id. Eg. $opt = ['message_id' => 123456789];
1083
     *
1084
     * By default the inline_message_id is taken from the context's update. Use $opt param to specify a different
1085
     * inline_message_id. Eg. $opt = ['inline_message_id' => 123456789];
1086
     *
1087
     * More on https://core.telegram.org/bots/api#editmessagetext
1088
     *
1089
     * @param string $text
1090
     * @param array $opt = [
1091
     *     'reply_markup' => ['inline_keyboard' => [[
1092
     *          ['callback_data' => 'data', 'text' => 'text']
1093
     *      ]]]
1094
     * ]
1095
     * @return PromiseInterface
1096
     */
1097
    public function editMessageText(string $text, array $opt = []): PromiseInterface
1098
    {
1099
        $opt = $this->resolveMessageId($opt);
1100
        $required = compact("text");
1101
        $params = array_merge($required, $opt);
1102
        return $this->callApi("editMessageText", $params, Message::class);
1103
    }
1104
1105
    /**
1106
     * Use this method to edit captions of messages. On success, if edited message is sent by the bot, the edited @see Message is
1107
     * returned, otherwise True is returned.
1108
     *
1109
     * By default the chat_id is taken from the context's update. Use $opt param to specify a different
1110
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
1111
     *
1112
     * By default the message_id is taken from the context's update. Use $opt param to specify a different
1113
     * message_id. Eg. $opt = ['message_id' => 123456789];
1114
     *
1115
     * By default the inline_message_id is taken from the context's update. Use $opt param to specify a different
1116
     * inline_message_id. Eg. $opt = ['inline_message_id' => 123456789];
1117
     *
1118
     * More on https://core.telegram.org/bots/api#editmessagecaption
1119
     *
1120
     * @param array $opt
1121
     * @return PromiseInterface
1122
     */
1123
    public function editMessageCaption(array $opt = []): PromiseInterface
1124
    {
1125
        $opt = $this->resolveMessageId($opt);
1126
        return $this->callApi("editMessageCaption", $opt, Message::class);
1127
    }
1128
1129
    /**
1130
     * Use this method to edit animation, audio, document, photo, or video messages. If a message is a part of a message
1131
     * album, then it can be edited only to a photo or a video. Otherwise, message type can be changed arbitrarily. When
1132
     * inline message is edited, new file can't be uploaded. Use previously uploaded file via its file_id or specify a
1133
     * URL. On success, if the edited message was sent by the bot, the edited @see Message is returned, otherwise True is
1134
     * returned.
1135
     *
1136
     * By default the chat_id is taken from the context's update. Use $opt param to specify a different
1137
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
1138
     *
1139
     * By default the message_id is taken from the context's update. Use $opt param to specify a different
1140
     * message_id. Eg. $opt = ['message_id' => 123456789];
1141
     *
1142
     * By default the inline_message_id is taken from the context's update. Use $opt param to specify a different
1143
     * inline_message_id. Eg. $opt = ['inline_message_id' => 123456789];
1144
     *
1145
     * More on https://core.telegram.org/bots/api#editmessagemedia
1146
     *
1147
     * @param $media
1148
     * @param array $opt
1149
     * @return PromiseInterface
1150
     */
1151
    public function editMessageMedia($media, array $opt = []): PromiseInterface
1152
    {
1153
        $opt = $this->resolveMessageId($opt);
1154
        $required = compact("media");
1155
        $params = array_merge($required, $opt);
1156
        return $this->callApi("editMessageMedia", $params, Message::class);
1157
    }
1158
1159
    /**
1160
     * Use this method to edit only the reply markup of messages. On success, if edited message is sent by the bot, the
1161
     * edited @see Message is returned, otherwise True is returned.
1162
     *
1163
     * By default the chat_id is taken from the context's update. Use $opt param to specify a different
1164
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
1165
     *
1166
     * By default the message_id is taken from the context's update. Use $opt param to specify a different
1167
     * message_id. Eg. $opt = ['message_id' => 123456789];
1168
     *
1169
     * By default the inline_message_id is taken from the context's update. Use $opt param to specify a different
1170
     * inline_message_id. Eg. $opt = ['inline_message_id' => 123456789];
1171
     *
1172
     * More on https://core.telegram.org/bots/api#editmessagereplymarkup
1173
     *
1174
     * @param array $opt
1175
     * @return PromiseInterface
1176
     */
1177
    public function editMessageReplyMarkup(array $opt = []): PromiseInterface
1178
    {
1179
        $opt = $this->resolveMessageId($opt);
1180
        return $this->callApi("editMessageReplyMarkup", $opt, Message::class);
1181
    }
1182
1183
    /**
1184
     * Use this method to stop a poll which was sent by the bot. On success, the stopped @see Poll with the final results is
1185
     * returned.
1186
     *
1187
     * More on https://core.telegram.org/bots/api#stoppoll
1188
     *
1189
     * @param $chat_id
1190
     * @param $message_id
1191
     * @param array $opt
1192
     * @return PromiseInterface
1193
     */
1194
    public function stopPoll($chat_id, $message_id, array $opt = []): PromiseInterface
1195
    {
1196
        $required = compact("chat_id", "message_id");
1197
        $params = array_merge($required, $opt);
1198
        return $this->callApi("stopPoll", $params, Poll::class);
1199
    }
1200
1201
    /**
1202
     * Use this method to delete a message, including service messages, with the following limitations:- A message can only
1203
     * be deleted if it was sent less than 48 hours ago.- A dice message in a private chat can only be deleted if it was
1204
     * sent more than 24 hours ago.- Bots can delete outgoing messages in private chats, groups, and supergroups.- Bots
1205
     * can delete incoming messages in private chats.- Bots granted can_post_messages permissions can delete outgoing
1206
     * messages in channels.- If the bot is an administrator of a group, it can delete any message there.- If the bot has
1207
     * can_delete_messages permission in a supergroup or a channel, it can delete any message there.Returns True on
1208
     * success.
1209
     *
1210
     * More on https://core.telegram.org/bots/api#deletemessage
1211
     *
1212
     * @param $chat_id
1213
     * @param $message_id
1214
     * @param array $opt
1215
     * @return PromiseInterface
1216
     */
1217
    public function deleteMessage($chat_id, $message_id, array $opt = []): PromiseInterface
1218
    {
1219
        $required = compact("chat_id", "message_id");
1220
        $params = array_merge($required, $opt);
1221
        return $this->callApi("deleteMessage", $params);
1222
    }
1223
1224
    /**
1225
     * Use this method to send static .WEBP or animated .TGS stickers. On success, the sent @see Message is returned.
1226
     *
1227
     * The sticker param can be either a string or a @see InputFile. Note that if you use the latter the file reading
1228
     * operation is synchronous, so the main thread is blocked.
1229
     * To make it asynchronous see https://github.com/badfarm/zanzara/wiki#working-with-files.
1230
     *
1231
     * By default the sticker is sent to the chat_id of the context's update. Use $opt param to specify a different
1232
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
1233
     *
1234
     * More on https://core.telegram.org/bots/api#sendsticker
1235
     *
1236
     * @param $sticker
1237
     * @param array $opt
1238
     * @return PromiseInterface
1239
     */
1240
    public function sendSticker($sticker, array $opt = []): PromiseInterface
1241
    {
1242
        $opt = $this->resolveChatId($opt);
1243
        $required = compact("sticker");
1244
        $params = array_merge($required, $opt);
1245
        return $this->callApi("sendSticker", $params, Message::class);
1246
    }
1247
1248
    /**
1249
     * Use this method to get a sticker set. On success, a @see StickerSet object is returned.
1250
     *
1251
     * More on https://core.telegram.org/bots/api#getstickerset
1252
     *
1253
     * @param string $name
1254
     * @param array $opt
1255
     * @return PromiseInterface
1256
     */
1257
    public function getStickerSet(string $name, array $opt = []): PromiseInterface
1258
    {
1259
        $required = compact("name");
1260
        $params = array_merge($required, $opt);
1261
        return $this->callApi("getStickerSet", $params, StickerSet::class);
1262
    }
1263
1264
    /**
1265
     * Use this method to upload a .PNG file with a sticker for later use in createNewStickerSet and addStickerToSet methods
1266
     * (can be used multiple times). Returns the uploaded @see File on success.
1267
     *
1268
     * More on https://core.telegram.org/bots/api#uploadstickerfile
1269
     *
1270
     * @param $user_id
1271
     * @param $png_sticker
1272
     * @param array $opt
1273
     * @return PromiseInterface
1274
     */
1275
    public function uploadStickerFile($user_id, $png_sticker, array $opt = []): PromiseInterface
1276
    {
1277
        $required = compact("user_id", "png_sticker");
1278
        $params = array_merge($required, $opt);
1279
        return $this->callApi("uploadStickerFile", $params, File::class);
1280
    }
1281
1282
    /**
1283
     * Use this method to create a new sticker set owned by a user. The bot will be able to edit the sticker set thus
1284
     * created. You must use exactly one of the fields png_sticker or tgs_sticker. Returns True on success.
1285
     *
1286
     * The png_sticker param can be either a string or a @see InputFile. Note that if you use the latter the file reading
1287
     * operation is synchronous, so the main thread is blocked.
1288
     * To make it asynchronous see https://github.com/badfarm/zanzara/wiki#working-with-files.
1289
     *
1290
     * More on https://core.telegram.org/bots/api#createnewstickerset
1291
     *
1292
     * @param $user_id
1293
     * @param string $name
1294
     * @param string $title
1295
     * @param string $emojis
1296
     * @param array $opt
1297
     * @return PromiseInterface
1298
     */
1299
    public function createNewStickerSet($user_id, string $name, string $title, string $emojis, array $opt = []): PromiseInterface
1300
    {
1301
        $required = compact("user_id", "name", "title", "emojis");
1302
        $params = array_merge($required, $opt);
1303
        return $this->callApi("createNewStickerSet", $params);
1304
    }
1305
1306
    /**
1307
     * Use this method to add a new sticker to a set created by the bot. You must use exactly one of the fields png_sticker
1308
     * or tgs_sticker. Animated stickers can be added to animated sticker sets and only to them. Animated sticker sets
1309
     * can have up to 50 stickers. Static sticker sets can have up to 120 stickers. Returns True on success.
1310
     *
1311
     * The png_sticker param can be either a string or a @see InputFile. Note that if you use the latter the file reading
1312
     * operation is synchronous, so the main thread is blocked.
1313
     * To make it asynchronous see https://github.com/badfarm/zanzara/wiki#working-with-files.
1314
     *
1315
     * More on https://core.telegram.org/bots/api#addstickertoset
1316
     *
1317
     * @param $user_id
1318
     * @param string $name
1319
     * @param $png_sticker
1320
     * @param string $emojis
1321
     * @param array $opt
1322
     * @return PromiseInterface
1323
     */
1324
    public function addStickerToSet($user_id, string $name, $png_sticker, string $emojis, array $opt = []): PromiseInterface
1325
    {
1326
        $required = compact("user_id", "name", "png_sticker", "emojis");
1327
        $params = array_merge($required, $opt);
1328
        return $this->callApi("addStickerToSet", $params);
1329
    }
1330
1331
    /**
1332
     * Use this method to move a sticker in a set created by the bot to a specific position. Returns True on success.
1333
     *
1334
     * More on https://core.telegram.org/bots/api#setstickerpositioninset
1335
     *
1336
     * @param string $sticker
1337
     * @param int $position
1338
     * @param array $opt
1339
     * @return PromiseInterface
1340
     */
1341
    public function setStickerPositionInSet(string $sticker, int $position, array $opt = []): PromiseInterface
1342
    {
1343
        $required = compact("sticker", "position");
1344
        $params = array_merge($required, $opt);
1345
        return $this->callApi("setStickerPositionInSet", $params);
1346
    }
1347
1348
    /**
1349
     * Use this method to delete a sticker from a set created by the bot. Returns True on success.
1350
     *
1351
     * More on https://core.telegram.org/bots/api#deletestickerfromset
1352
     *
1353
     * @param string $sticker
1354
     * @param array $opt
1355
     * @return PromiseInterface
1356
     */
1357
    public function deleteStickerFromSet(string $sticker, array $opt = []): PromiseInterface
1358
    {
1359
        $required = compact("sticker");
1360
        $params = array_merge($required, $opt);
1361
        return $this->callApi("deleteStickerFromSet", $params);
1362
    }
1363
1364
    /**
1365
     * Use this method to set the thumbnail of a sticker set. Animated thumbnails can be set for animated sticker sets only.
1366
     * Returns True on success.
1367
     *
1368
     * The thumb param in $opt can be either a string or a @see InputFile. Note that if you use the latter the file reading
1369
     * operation is synchronous, so the main thread is blocked.
1370
     * To make it asynchronous see https://github.com/badfarm/zanzara/wiki#working-with-files.
1371
     *
1372
     * More on https://core.telegram.org/bots/api#setstickersetthumb
1373
     *
1374
     * @param string $name
1375
     * @param $user_id
1376
     * @param array $opt
1377
     * @return PromiseInterface
1378
     */
1379
    public function setStickerSetThumb(string $name, $user_id, array $opt = []): PromiseInterface
1380
    {
1381
        $required = compact("name", "user_id");
1382
        $params = array_merge($required, $opt);
1383
        return $this->callApi("setStickerSetThumb", $params);
1384
    }
1385
1386
    /**
1387
     * Use this method to send answers to an inline query. On success, True is returned.No more than 50 results per query
1388
     * are allowed.
1389
     *
1390
     * By default it replies to the inline_query_id of the context's update. Use $opt param to specify a different
1391
     * inline_query_id. Eg. $opt = ['inline_query_id' => 'abcdefgh'];
1392
     *
1393
     * More on https://core.telegram.org/bots/api#answerinlinequery
1394
     *
1395
     * @param $results
1396
     * @param array $opt
1397
     * @return PromiseInterface
1398
     */
1399
    public function answerInlineQuery($results, array $opt = []): PromiseInterface
1400
    {
1401
        if (!isset($opt['inline_query_id']) && $this->update) {
1402
            $opt['inline_query_id'] = $this->update->getInlineQuery()->getId();
1403
        }
1404
        $required = compact("results");
1405
        $params = array_merge($required, $opt);
1406
        return $this->callApi("answerInlineQuery", $params);
1407
    }
1408
1409
    /**
1410
     * Use this method to send invoices. On success, the sent @see Message is returned.
1411
     *
1412
     * By default the invoice is sent to the chat_id of the context's update. Use $opt param to specify a different
1413
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
1414
     *
1415
     * More on https://core.telegram.org/bots/api#sendinvoice
1416
     *
1417
     * @param string $title
1418
     * @param string $description
1419
     * @param string $payload
1420
     * @param string $provider_token
1421
     * @param string $start_parameter
1422
     * @param string $currency
1423
     * @param $prices
1424
     * @param array $opt
1425
     * @return PromiseInterface
1426
     */
1427
    public function sendInvoice(string $title, string $description, string $payload, string $provider_token, string $start_parameter, string $currency, $prices, array $opt = []): PromiseInterface
1428
    {
1429
        $opt = $this->resolveChatId($opt);
1430
        $required = compact("title", "description", "payload", "provider_token", "start_parameter", "currency", "prices");
1431
        $params = array_merge($required, $opt);
1432
        return $this->callApi("sendInvoice", $params, Message::class);
1433
    }
1434
1435
    /**
1436
     * @param array $params
1437
     * @return PromiseInterface
1438
     */
1439
    public function doSendInvoice(array $params): PromiseInterface
1440
    {
1441
        if (!isset($params['chat_id']) && $this->update) {
1442
            $params['chat_id'] = $this->update->getEffectiveChat()->getId();
1443
        }
1444
        return $this->callApi("sendInvoice", $params, Message::class);
1445
    }
1446
1447
    /**
1448
     * If you sent an invoice requesting a shipping address and the parameter is_flexible was specified, the Bot API will
1449
     * send an Update with a shipping_query field to the bot. Use this method to reply to shipping queries. On success,
1450
     * True is returned.
1451
     *
1452
     * By default it replies to the shipping_query_id of the context's update. Use $opt param to specify a different
1453
     * shipping_query_id. Eg. $opt = ['shipping_query_id' => 'abcdefgh'];
1454
     *
1455
     * More on https://core.telegram.org/bots/api#answershippingquery
1456
     *
1457
     * @param $ok
1458
     * @param array $opt
1459
     * @return PromiseInterface
1460
     */
1461
    public function answerShippingQuery($ok, array $opt = []): PromiseInterface
1462
    {
1463
        if (!isset($opt['shipping_query_id']) && $this->update) {
1464
            $opt['shipping_query_id'] = $this->update->getShippingQuery()->getId();
1465
        }
1466
        $required = compact("ok");
1467
        $params = array_merge($required, $opt);
1468
        return $this->callApi("answerShippingQuery", $params);
1469
    }
1470
1471
    /**
1472
     * Once the user has confirmed their payment and shipping details, the Bot API sends the final confirmation in the form
1473
     * of an Update with the field pre_checkout_query. Use this method to respond to such pre-checkout queries. On
1474
     * success, True is returned. Note: The Bot API must receive an answer within 10 seconds after the pre-checkout query
1475
     * was sent.
1476
     *
1477
     * By default it replies to the pre_checkout_query_id of the context's update. Use $opt param to specify a different
1478
     * pre_checkout_query_id. Eg. $opt = ['pre_checkout_query_id' => 'abcdefgh'];
1479
     *
1480
     * More on https://core.telegram.org/bots/api#answerprecheckoutquery
1481
     *
1482
     * @param $ok
1483
     * @param array $opt
1484
     * @return PromiseInterface
1485
     */
1486
    public function answerPreCheckoutQuery($ok, array $opt = []): PromiseInterface
1487
    {
1488
        if (!isset($opt['pre_checkout_query_id']) && $this->update) {
1489
            $opt['pre_checkout_query_id'] = $this->update->getPreCheckoutQuery()->getId();
1490
        }
1491
        $required = compact("ok");
1492
        $params = array_merge($required, $opt);
1493
        return $this->callApi("answerPreCheckoutQuery", $params);
1494
    }
1495
1496
    /**
1497
     * Informs a user that some of the Telegram Passport elements they provided contains errors. The user will not be able
1498
     * to re-submit their Passport to you until the errors are fixed (the contents of the field for which you returned
1499
     * the error must change). Returns True on success.
1500
     *
1501
     * More on https://core.telegram.org/bots/api#setpassportdataerrors
1502
     *
1503
     * @param $user_id
1504
     * @param $errors
1505
     * @param array $opt
1506
     * @return PromiseInterface
1507
     */
1508
    public function setPassportDataErrors($user_id, $errors, array $opt = []): PromiseInterface
1509
    {
1510
        $required = compact("user_id", "errors");
1511
        $params = array_merge($required, $opt);
1512
        return $this->callApi("setPassportDataErrors", $params);
1513
    }
1514
1515
    /**
1516
     * Use this method to send a game. On success, the sent @see Message is returned.
1517
     *
1518
     * By default the game is sent to the chat_id of the context's update. Use $opt param to specify a different
1519
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
1520
     *
1521
     * More on https://core.telegram.org/bots/api#sendgame
1522
     *
1523
     * @param string $game_short_name
1524
     * @param array $opt
1525
     * @return PromiseInterface
1526
     */
1527
    public function sendGame(string $game_short_name, array $opt = []): PromiseInterface
1528
    {
1529
        $opt = $this->resolveChatId($opt);
1530
        $required = compact("game_short_name");
1531
        $params = array_merge($required, $opt);
1532
        return $this->callApi("sendGame", $params, Message::class);
1533
    }
1534
1535
    /**
1536
     * Use this method to set the score of the specified user in a game. On success, if the message was sent by the bot,
1537
     * returns the edited @see Message, otherwise returns True. Returns an error, if the new score is not greater than the
1538
     * user's current score in the chat and force is False.
1539
     *
1540
     * By default the chat_id is taken from the context's update. Use $opt param to specify a different
1541
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
1542
     *
1543
     * By default the message_id is taken from the context's update. Use $opt param to specify a different
1544
     * message_id. Eg. $opt = ['message_id' => 123456789];
1545
     *
1546
     * By default the inline_message_id is taken from the context's update. Use $opt param to specify a different
1547
     * inline_message_id. Eg. $opt = ['inline_message_id' => 123456789];
1548
     *
1549
     * More on https://core.telegram.org/bots/api#setgamescore
1550
     *
1551
     * @param $user_id
1552
     * @param int $score
1553
     * @param array $opt
1554
     * @return PromiseInterface
1555
     */
1556
    public function setGameScore($user_id, int $score, array $opt = []): PromiseInterface
1557
    {
1558
        $opt = $this->resolveMessageId($opt);
1559
        $required = compact("user_id", "score");
1560
        $params = array_merge($required, $opt);
1561
        return $this->callApi("setGameScore", $params, Message::class);
1562
    }
1563
1564
    /**
1565
     * Use this method to get data for high score tables. Will return the score of the specified user and several of his
1566
     * neighbors in a game. On success, returns an Array of @see GameHighScore objects.
1567
     *
1568
     * By default the chat_id is taken from the context's update. Use $opt param to specify a different
1569
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
1570
     *
1571
     * By default the message_id is taken from the context's update. Use $opt param to specify a different
1572
     * message_id. Eg. $opt = ['message_id' => 123456789];
1573
     *
1574
     * By default the inline_message_id is taken from the context's update. Use $opt param to specify a different
1575
     * inline_message_id. Eg. $opt = ['inline_message_id' => 123456789];
1576
     *
1577
     * More on https://core.telegram.org/bots/api#getgamehighscores
1578
     *
1579
     * @param $user_id
1580
     * @param array $opt
1581
     * @return PromiseInterface
1582
     */
1583
    public function getGameHighScores($user_id, array $opt = []): PromiseInterface
1584
    {
1585
        $opt = $this->resolveMessageId($opt);
1586
        $required = compact("user_id");
1587
        $params = array_merge($required, $opt);
1588
        return $this->callApi("getGameHighScores", $params, GameHighScore::class);
1589
    }
1590
1591
    /**
1592
     * Use this method to log out from the cloud Bot API server before launching the bot locally. You must log out the
1593
     * bot before running it locally, otherwise there is no guarantee that the bot will receive updates. After a
1594
     * successful call, you can immediately log in on a local server, but will not be able to log in back to the
1595
     * cloud Bot API server for 10 minutes. Returns True on success. Requires no parameters.
1596
     *
1597
     * More on https://core.telegram.org/bots/api#logout
1598
     *
1599
     * @since zanzara 0.5.0, Telegram Bot Api 5.0
1600
     *
1601
     * @return PromiseInterface
1602
     */
1603
    public function logOut(): PromiseInterface
1604
    {
1605
        return $this->callApi("logOut");
1606
    }
1607
1608
    /**
1609
     * Use this method to close the bot instance before moving it from one local server to another. You need to delete
1610
     * the webhook before calling this method to ensure that the bot isn't launched again after server restart. The
1611
     * method will return error 429 in the first 10 minutes after the bot is launched. Returns True on success.
1612
     * Requires no parameters.
1613
     *
1614
     * More on https://core.telegram.org/bots/api#close
1615
     *
1616
     * @since zanzara 0.5.0, Telegram Bot Api 5.0
1617
     *
1618
     * @return PromiseInterface
1619
     */
1620
    public function close(): PromiseInterface
1621
    {
1622
        return $this->callApi("close");
1623
    }
1624
1625
    /**
1626
     * @param string $method
1627
     * @param array $params
1628
     * @param string $class
1629
     * @param string[] $headers
1630
     * @return PromiseInterface
1631
     */
1632
    public function callApi(string $method, array $params = [], string $class = 'Scalar', $headers = ["Content-type" => "application/json"])
1633
    {
1634
        if ($this->container->get(Config::class)->getParseMode() && !isset($params['parse_mode'])) {
1635
            $params['parse_mode'] = $this->container->get(Config::class)->getParseMode();
1636
        }
1637
        foreach ($params as $param) {
1638
            if ($param instanceof InputFile) {
1639
1640
                $async = $this->container->get(Config::class)->isReactFileSystem();
1641
1642
                if ($async) {
1643
                    return $this->prepareMultipartDataAsync($params)->then(function ($result) use ($method) {
1644
                        $headers = array("Content-Length" => $result->getSize(), "Content-Type" => "multipart/form-data; boundary={$result->getBoundary()}");
1645
                        return $this->browser->post($method, $headers, $result);
1646
                    });
1647
                } else {
1648
                    $multipart = $this->prepareMultipartData($params);
1649
                    $headers = array("Content-Length" => $multipart->getSize(), "Content-Type" => "multipart/form-data; boundary={$multipart->getBoundary()}");
1650
                    return $this->browser->post($method, $headers, $multipart);
1651
                }
1652
            }
1653
        }
1654
        return $this->wrapPromise($this->browser->post($method, $headers, json_encode($params)), $method, $params, $class);
1655
    }
1656
1657
    /**
1658
     *
1659
     * Create MultipartStream, iterate over params to find InputFile
1660
     *
1661
     * @param $params
1662
     * @return PromiseInterface
1663
     */
1664
    private function prepareMultipartDataAsync($params)
1665
    {
1666
        $filesystem = $this->container->get(Filesystem::class);
1667
        $multipart_data = [];
1668
        $promises = [];
1669
        foreach ($params as $key => $value) {
1670
1671
            if ($value instanceof InputFile) {
1672
                array_push($promises, $filesystem->getContents($value->getPath())->then(function ($contents) use ($value, $key) {
1673
                    $data = ['name' => $key];
1674
                    $data['contents'] = $contents;
1675
                    $data['filename'] = basename($value->getPath());
1676
                    return $data;
1677
                }, function ($error) {
1678
                    $this->container->get(ZanzaraLogger::class)->error($error);
1679
                    return $error;
1680
                }));
1681
1682
            } else {
1683
                $data = ['name' => $key];
1684
                $data['contents'] = strval($value);
1685
                array_push($multipart_data, $data);
1686
            }
1687
        }
1688
1689
        return all($promises)->then(function ($files) use ($multipart_data) {
1690
            foreach ($files as $key => $value) {
1691
                array_push($multipart_data, $value);
1692
            }
1693
            return new MultipartStream($multipart_data);
1694
        }, function ($error) {
1695
            $this->container->get(ZanzaraLogger::class)->error($error);
1696
            return $error;
1697
        });
1698
    }
1699
1700
    private function prepareMultipartData($params)
1701
    {
1702
        $multipart_data = [];
1703
        foreach ($params as $key => $value) {
1704
            $data = ['name' => $key];
1705
            if ($value instanceof InputFile) {
1706
                if (file_exists($value->getPath())) {
1707
                    $fileData = file_get_contents($value->getPath());
1708
                    $data['contents'] = $fileData;
1709
                    $data['filename'] = basename($value->getPath());
1710
                } else {
1711
                    $this->container->get(ZanzaraLogger::class)->error("File not found: {$value->getPath()}");
1712
                }
1713
1714
            } else {
1715
                $data['contents'] = strval($value);
1716
            }
1717
            array_push($multipart_data, $data);
1718
        }
1719
        return new MultipartStream($multipart_data);
1720
    }
1721
1722
    /**
1723
     * ZanzaraPromise class was removed since it swallowed the promise chain.
1724
     * We actually have to call the original promise, get the response and propagate the casted response along
1725
     * the promise chain.
1726
     * For the rejected promise, we have to cast the original exception to a TelegramException and rethrow it
1727
     * in order to let the user receive the exception in his onRejected function.
1728
     *
1729
     * Unfortunately, we don't have control on user's callback input parameter anymore. In this way the user
1730
     * needs to manage the otherwise() promise callback to see the error.
1731
     *
1732
     * @param PromiseInterface $promise
1733
     * @param string $method
1734
     * @param array $params
1735
     * @param string $class
1736
     * @return PromiseInterface
1737
     */
1738
    private function wrapPromise(PromiseInterface $promise, string $method, array $params = [], string $class = "Scalar"): PromiseInterface
1739
    {
1740
        $mapper = $this->container->get(ZanzaraMapper::class);
1741
        $logger = $this->container->get(ZanzaraLogger::class);
1742
1743
        return $promise
1744
            ->then(function (ResponseInterface $response) use ($class, $mapper) {
1745
                $json = (string)$response->getBody();
1746
                $object = json_decode($json);
1747
1748
                if (is_scalar($object->result) && $class === "Scalar") {
1749
                    return $object->result;
1750
                }
1751
1752
                return $mapper->mapObject($object->result, $class);
1753
            }, function ($e) use ($method, $params, $logger, $mapper) {
1754
                if ($e instanceof ResponseException) {
1755
                    // with the introduction of Local Api server (https://core.telegram.org/bots/api#using-a-local-bot-api-server)
1756
                    // we can no longer assume that the response is with the TelegramException format, so catch any mapping
1757
                    // exception
1758
                    try {
1759
                        $json = (string)$e->getResponse()->getBody();
1760
                        $e = $mapper->mapJson($json, TelegramException::class);
1761
                    } catch (\Exception $ignore) {
1762
                        // ignore
1763
                    }
1764
                }
1765
                $logger->errorTelegramApi($method, $params, $e);
1766
                throw $e;
1767
            });
1768
    }
1769
1770
    /**
1771
     * @param array $opt
1772
     * @return array
1773
     */
1774
    public function resolveMessageId(array $opt): array
1775
    {
1776
        // if the user doesn't provide inline_message_id, chat_id or message_id the framework tries to resolve them
1777
        // based on the Update's type
1778
        if ($this->update) {
1779
            if (!isset($opt['inline_message_id']) && !isset($opt['chat_id']) && !isset($opt['message_id'])) {
1780
                if ($this->update->getUpdateType() == CallbackQuery::class) {
1781
                    $cbQuery = $this->update->getCallbackQuery();
1782
                    if ($cbQuery->getInlineMessageId()) {
1783
                        $opt['inline_message_id'] = $cbQuery->getInlineMessageId();
1784
                    } else if ($cbQuery->getMessage()) {
1785
                        $opt['message_id'] = $cbQuery->getMessage()->getMessageId();
1786
                    }
1787
                }
1788
                // set chat_id only if inline_message_id wasn't set
1789
                if (!isset($opt['inline_message_id']) && $this->update->getEffectiveChat()) {
1790
                    $opt['chat_id'] = $this->update->getEffectiveChat()->getId();
1791
                }
1792
            }
1793
        }
1794
        return $opt;
1795
    }
1796
1797
    /**
1798
     * @param array $opt
1799
     * @return array
1800
     */
1801
    public function resolveChatId(array $opt): array
1802
    {
1803
        if (!isset($opt['chat_id']) && $this->update) {
1804
            $opt['chat_id'] = $this->update->getEffectiveChat()->getId();
1805
        }
1806
        return $opt;
1807
    }
1808
1809
}