TelegramTrait   F
last analyzed

Complexity

Total Complexity 119

Size/Duplication

Total Lines 1764
Duplicated Lines 0 %

Importance

Changes 13
Bugs 2 Features 0
Metric Value
eloc 325
dl 0
loc 1764
rs 2
c 13
b 2
f 0
wmc 119

82 Methods

Rating   Name   Duplication   Size   Complexity  
A getStickerSet() 0 5 1
A getChatMember() 0 5 1
A setChatPhoto() 0 5 1
A sendSticker() 0 6 1
A sendVideoNote() 0 6 1
A sendGame() 0 6 1
A editMessageMedia() 0 6 1
A setChatPermissions() 0 5 1
A forwardMessage() 0 5 1
A callApi() 0 23 6
A sendPhoto() 0 6 1
A deleteMessage() 0 5 1
A setWebhook() 0 5 1
A deleteWebhook() 0 3 1
A unpinChatMessage() 0 5 1
A stopMessageLiveLocation() 0 4 1
A getChat() 0 5 1
A sendAnimation() 0 6 1
A getMe() 0 3 1
A getChatAdministrators() 0 5 1
A copyMessage() 0 5 1
A deleteChatStickerSet() 0 5 1
A answerShippingQuery() 0 8 3
A doSendInvoice() 0 6 3
A answerCallbackQuery() 0 6 3
A setChatAdministratorCustomTitle() 0 5 1
A getUpdates() 0 9 1
B resolveMessageId() 0 21 10
A sendVenue() 0 6 1
A exportChatInviteLink() 0 5 1
A setStickerPositionInSet() 0 5 1
A sendMessage() 0 6 1
A sendDice() 0 4 1
A getFile() 0 5 1
A wrapPromise() 0 29 5
A sendChatAction() 0 6 1
A deleteChatPhoto() 0 5 1
A sendVideo() 0 6 1
A pinChatMessage() 0 5 1
A sendContact() 0 6 1
A sendPoll() 0 6 1
A setGameScore() 0 6 1
A deleteStickerFromSet() 0 5 1
A setChatStickerSet() 0 5 1
A setPassportDataErrors() 0 5 1
A sendDocument() 0 6 1
A sendLocation() 0 6 1
A getWebhookInfo() 0 3 1
A editMessageCaption() 0 4 1
A editMessageReplyMarkup() 0 4 1
A close() 0 3 1
A leaveChat() 0 5 1
A sendAudio() 0 6 1
A sendMediaGroup() 0 6 1
A editMessageText() 0 6 1
A uploadStickerFile() 0 5 1
A setStickerSetThumb() 0 5 1
A unbanChatMember() 0 5 1
A promoteChatMember() 0 5 1
A addStickerToSet() 0 5 1
A restrictChatMember() 0 5 1
A sendBulkMessage() 0 4 1
A setChatDescription() 0 5 1
A kickChatMember() 0 5 1
A setChatTitle() 0 5 1
A logOut() 0 3 1
A prepareMultipartDataAsync() 0 33 4
A answerPreCheckoutQuery() 0 8 3
A unpinAllChatMessages() 0 4 1
A prepareMultipartData() 0 20 4
A sendVoice() 0 6 1
A editMessageLiveLocation() 0 6 1
A setMyCommands() 0 5 1
A resolveChatId() 0 6 4
A getUserProfilePhotos() 0 5 1
A getGameHighScores() 0 6 1
A createNewStickerSet() 0 5 1
A sendInvoice() 0 6 1
A getChatMembersCount() 0 5 1
A doSendMessage() 0 3 1
A answerInlineQuery() 0 8 3
A stopPoll() 0 5 1

How to fix   Complexity   

Complex Class

Complex classes like TelegramTrait often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use TelegramTrait, and based on these observations, apply Extract Interface, too.

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

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1665
        $multipart_data = [];
1666
        $promises = [];
1667
        foreach ($params as $key => $value) {
1668
1669
            if ($value instanceof InputFile) {
1670
                array_push($promises, $filesystem->getContents($value->getPath())->then(function ($contents) use ($value, $key) {
1671
                    $data = ['name' => $key];
1672
                    $data['contents'] = $contents;
1673
                    $data['filename'] = basename($value->getPath());
1674
                    return $data;
1675
                }, function ($error) {
1676
                    $this->container->get(ZanzaraLogger::class)->error($error);
1677
                    return $error;
1678
                }));
1679
1680
            } else {
1681
                $data = ['name' => $key];
1682
                $data['contents'] = strval($value);
1683
                array_push($multipart_data, $data);
1684
            }
1685
        }
1686
1687
        return all($promises)->then(function ($files) use ($multipart_data) {
1688
            foreach ($files as $key => $value) {
1689
                array_push($multipart_data, $value);
1690
            }
1691
            return new MultipartStream($multipart_data);
1692
        }, function ($error) {
1693
            $this->container->get(ZanzaraLogger::class)->error($error);
1694
            return $error;
1695
        });
1696
    }
1697
1698
    private function prepareMultipartData($params)
1699
    {
1700
        $multipart_data = [];
1701
        foreach ($params as $key => $value) {
1702
            $data = ['name' => $key];
1703
            if ($value instanceof InputFile) {
1704
                if (file_exists($value->getPath())) {
1705
                    $fileData = file_get_contents($value->getPath());
1706
                    $data['contents'] = $fileData;
1707
                    $data['filename'] = basename($value->getPath());
1708
                } else {
1709
                    $this->container->get(ZanzaraLogger::class)->error("File not found: {$value->getPath()}");
1710
                }
1711
1712
            } else {
1713
                $data['contents'] = strval($value);
1714
            }
1715
            array_push($multipart_data, $data);
1716
        }
1717
        return new MultipartStream($multipart_data);
1718
    }
1719
1720
    /**
1721
     * ZanzaraPromise class was removed since it swallowed the promise chain.
1722
     * We actually have to call the original promise, get the response and propagate the casted response along
1723
     * the promise chain.
1724
     * For the rejected promise, we have to cast the original exception to a TelegramException and rethrow it
1725
     * in order to let the user receive the exception in his onRejected function.
1726
     *
1727
     * Unfortunately, we don't have control on user's callback input parameter anymore. In this way the user
1728
     * needs to manage the otherwise() promise callback to see the error.
1729
     *
1730
     * @param PromiseInterface $promise
1731
     * @param string $method
1732
     * @param array $params
1733
     * @param string $class
1734
     * @return PromiseInterface
1735
     */
1736
    private function wrapPromise(PromiseInterface $promise, string $method, array $params = [], string $class = "Scalar"): PromiseInterface
1737
    {
1738
        $mapper = $this->container->get(ZanzaraMapper::class);
1739
        $logger = $this->container->get(ZanzaraLogger::class);
1740
1741
        return $promise
1742
            ->then(function (ResponseInterface $response) use ($class, $mapper) {
1743
                $json = (string)$response->getBody();
1744
                $object = json_decode($json);
1745
1746
                if (is_scalar($object->result) && $class === "Scalar") {
1747
                    return $object->result;
1748
                }
1749
1750
                return $mapper->mapObject($object->result, $class);
1751
            }, function ($e) use ($method, $params, $logger, $mapper) {
1752
                if ($e instanceof ResponseException) {
1753
                    // with the introduction of Local Api server (https://core.telegram.org/bots/api#using-a-local-bot-api-server)
1754
                    // we can no longer assume that the response is with the TelegramException format, so catch any mapping
1755
                    // exception
1756
                    try {
1757
                        $json = (string)$e->getResponse()->getBody();
1758
                        $e = $mapper->mapJson($json, TelegramException::class);
1759
                    } catch (\Exception $ignore) {
1760
                        // ignore
1761
                    }
1762
                }
1763
                $logger->errorTelegramApi($method, $params, $e);
1764
                throw $e;
1765
            });
1766
    }
1767
1768
    /**
1769
     * @param array $opt
1770
     * @return array
1771
     */
1772
    public function resolveMessageId(array $opt): array
1773
    {
1774
        // if the user doesn't provide inline_message_id, chat_id or message_id the framework tries to resolve them
1775
        // based on the Update's type
1776
        if ($this->update) {
1777
            if (!isset($opt['inline_message_id']) && !isset($opt['chat_id']) && !isset($opt['message_id'])) {
1778
                if ($this->update->getUpdateType() == CallbackQuery::class) {
1779
                    $cbQuery = $this->update->getCallbackQuery();
1780
                    if ($cbQuery->getInlineMessageId()) {
1781
                        $opt['inline_message_id'] = $cbQuery->getInlineMessageId();
1782
                    } else if ($cbQuery->getMessage()) {
1783
                        $opt['message_id'] = $cbQuery->getMessage()->getMessageId();
1784
                    }
1785
                }
1786
                // set chat_id only if inline_message_id wasn't set
1787
                if (!isset($opt['inline_message_id']) && $this->update->getEffectiveChat()) {
1788
                    $opt['chat_id'] = $this->update->getEffectiveChat()->getId();
1789
                }
1790
            }
1791
        }
1792
        return $opt;
1793
    }
1794
1795
    /**
1796
     * @param array $opt
1797
     * @return array
1798
     */
1799
    public function resolveChatId(array $opt): array
1800
    {
1801
        if (!isset($opt['chat_id']) && $this->update && $this->update->getEffectiveChat()) {
1802
            $opt['chat_id'] = $this->update->getEffectiveChat()->getId();
1803
        }
1804
        return $opt;
1805
    }
1806
1807
}