Passed
Push — develop ( 0b6bc5...79a5e4 )
by Michele
02:17
created

TelegramTrait::resolveChatId()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 3
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 6
rs 10
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\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\Poll\Poll;
25
use Zanzara\Telegram\Type\Response\TelegramException;
26
use Zanzara\Telegram\Type\Update;
27
use Zanzara\Telegram\Type\Webhook\WebhookInfo;
28
use Zanzara\ZanzaraLogger;
29
use Zanzara\ZanzaraMapper;
30
use function React\Promise\all;
31
32
/**
33
 * Class that interacts with Telegram Api.
34
 * Made trait in order to be used both by Telegram and Context classes.
35
 *
36
 * @see Telegram
37
 * @see Context
38
 */
39
trait TelegramTrait
40
{
41
42
    /**
43
     * @var ContainerInterface
44
     */
45
    protected $container;
46
47
    /**
48
     * @var Browser
49
     */
50
    protected $browser;
51
52
    /**
53
     * @var Update|null
54
     */
55
    protected $update;
56
57
    /**
58
     * Use this method to receive incoming updates using long polling (wiki). An Array of @see Update objects is returned.
59
     *
60
     * More on https://core.telegram.org/bots/api#getupdates
61
     *
62
     * @param array $opt
63
     * @return PromiseInterface
64
     */
65
    public function getUpdates(array $opt = []): PromiseInterface
66
    {
67
        $method = "getUpdates";
68
        $query = http_build_query($opt);
69
70
        $browser = $this->browser->withOptions(array(
71
            "timeout" => $opt['timeout'] + 10 //timout browser necessary bigger than telegram timeout. They can't be equal
72
        ));
73
74
        return $this->wrapPromise($browser->get("$method?$query"), $method, $opt, Update::class);
75
    }
76
77
    /**
78
     * Use this method to send text messages. On success, the sent @see Message is returned.
79
     *
80
     * By default the message is sent to the chat_id of the context's update. Use $opt param to specify a different
81
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
82
     *
83
     * More on https://core.telegram.org/bots/api#sendmessage
84
     *
85
     * @param string $text
86
     * @param array|null $opt = [
87
     *     'chat_id' => 123456789,
88
     *     'parse_mode' => 'HTML',
89
     *     'disable_web_page_preview' => true,
90
     *     'disable_notification' => true,
91
     *     'reply_to_message_id' => 123456789,
92
     *     'reply_markup' => ['force_reply' => true],
93
     *     'reply_markup' => ['inline_keyboard' => [[
94
     *          ['callback_data' => 'data', 'text' => 'text']
95
     *      ]]],
96
     *      'reply_markup' => ['resize_keyboard' => true, 'one_time_keyboard' => true, 'selective' => true, 'keyboard' => [[
97
     *          ['text' => 'text', 'request_contact' => true, 'request_location' => true, 'request_poll' => ['type' => 'quiz']]
98
     *      ]]]
99
     * ]
100
     * @return PromiseInterface
101
     */
102
    public function sendMessage(string $text, ?array $opt = [])
103
    {
104
        $opt = $this->resolveChatId($opt);
105
        $required = compact("text");
106
        $params = array_merge($required, $opt);
107
        return $this->doSendMessage($params);
108
    }
109
110
    /**
111
     * Do not use it. Use @see TelegramTrait::sendMessage() instead.
112
     *
113
     * @internal
114
     * @param array $params
115
     * @return PromiseInterface
116
     */
117
    public function doSendMessage(array $params): PromiseInterface
118
    {
119
        return $this->callApi("sendMessage", $params, Message::class);
120
    }
121
122
    /**
123
     * Use this method to send a message to many chats. This method takes care of sending the message
124
     * with a delay in order avoid 429 Telegram errors (https://core.telegram.org/bots/faq#broadcasting-to-users).
125
     *
126
     * Eg. $ctx->sendBulkMessage([1111111111, 2222222222, 333333333], 'A wonderful notification', [parse_mode => 'HTML']);
127
     *
128
     * More on https://core.telegram.org/bots/api#sendmessage
129
     *
130
     * @param array $chatIds
131
     * @param string $text
132
     * @param array $opt
133
     */
134
    public function sendBulkMessage(array $chatIds, string $text, array $opt = []): void
135
    {
136
        $this->container->get(MessageQueue::class)
137
            ->push($chatIds, $text, $opt);
138
    }
139
140
    /**
141
     * Use this method to specify a url and receive incoming updates via an outgoing webhook. Whenever there is an update
142
     * for the bot, we will send an HTTPS POST request to the specified url, containing a JSON-serialized Update. In case
143
     * of an unsuccessful request, we will give up after a reasonable amount of attempts. Returns True on success.
144
     *
145
     * More on https://core.telegram.org/bots/api#setwebhook
146
     *
147
     * @param string $url
148
     * @param array|null $opt
149
     * @return PromiseInterface
150
     */
151
    public function setWebhook(string $url, ?array $opt = []): PromiseInterface
152
    {
153
        $required = compact("url");
154
        $params = array_merge($required, $opt);
155
        return $this->callApi("setWebhook", $params);
156
    }
157
158
    /**
159
     * Use this method to get current webhook status. Requires no parameters. On success, returns a @see WebhookInfo object.
160
     * If the bot is using getUpdates, will return an object with the url field empty.
161
     *
162
     * More on https://core.telegram.org/bots/api#getwebhookinfo
163
     *
164
     * @return PromiseInterface
165
     */
166
    public function getWebhookInfo(): PromiseInterface
167
    {
168
        return $this->callApi("getWebhookInfo", [], WebhookInfo::class);
169
    }
170
171
    /**
172
     * Use this method to remove webhook integration if you decide to switch back to getUpdates. Returns True on
173
     * success. Requires no parameters.
174
     *
175
     * More on https://core.telegram.org/bots/api#deletewebhook
176
     *
177
     * @return PromiseInterface
178
     */
179
    public function deleteWebhook(): PromiseInterface
180
    {
181
        return $this->callApi("deleteWebhook");
182
    }
183
184
    /**
185
     * Use this method to forward messages of any kind. On success, the sent @see Message is returned.
186
     *
187
     * More on https://core.telegram.org/bots/api#forwardmessage
188
     *
189
     * @param int $chat_id
190
     * @param int $from_chat_id
191
     * @param int $message_id
192
     * @param array|null $opt
193
     * @return PromiseInterface
194
     */
195
    public function forwardMessage(int $chat_id, int $from_chat_id, int $message_id, ?array $opt = []): PromiseInterface
196
    {
197
        $required = compact("chat_id", "from_chat_id", "message_id");
198
        $params = array_merge($required, $opt);
199
        return $this->callApi("forwardMessage", $params, Message::class);
200
    }
201
202
    /**
203
     * Use this method to send photos. On success, the sent @see Message is returned.
204
     *
205
     * The photo param can be either a string or a @see InputFile. Note that if you use the latter the file reading
206
     * operation is synchronous, so the main thread is blocked.
207
     * To make it asynchronous see https://github.com/badfarm/zanzara/wiki#working-with-files.
208
     *
209
     * By default the photo is sent to the chat_id of the context's update. Use $opt param to specify a different
210
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
211
     *
212
     * More on https://core.telegram.org/bots/api#sendphoto
213
     *
214
     * @param $photo
215
     * @param array|null $opt
216
     * @return PromiseInterface
217
     */
218
    public function sendPhoto($photo, ?array $opt = []): PromiseInterface
219
    {
220
        $opt = $this->resolveChatId($opt);
221
        $required = compact("photo");
222
        $params = array_merge($required, $opt);
223
        return $this->callApi("sendPhoto", $params, Message::class);
224
    }
225
226
    /**
227
     * Use this method to send audio files, if you want Telegram clients to display them in the music player. Your audio
228
     * must be in the .MP3 or .M4A format. On success, the sent @see Message is returned. Bots can currently send audio files
229
     * of up to 50 MB in size, this limit may be changed in the future.
230
     *
231
     * The audio and thumb params can be either a string or a @see InputFile. Note that if you use the latter the file reading
232
     * operation is synchronous, so the main thread is blocked.
233
     * To make it asynchronous see https://github.com/badfarm/zanzara/wiki#working-with-files.
234
     *
235
     * By default the audio is sent to the chat_id of the context's update. Use $opt param to specify a different
236
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
237
     *
238
     * More on https://core.telegram.org/bots/api#sendaudio
239
     *
240
     * @param $audio
241
     * @param array|null $opt
242
     * @return PromiseInterface
243
     */
244
    public function sendAudio($audio, ?array $opt = []): PromiseInterface
245
    {
246
        $opt = $this->resolveChatId($opt);
247
        $required = compact("audio");
248
        $params = array_merge($required, $opt);
249
        return $this->callApi("sendAudio", $params, Message::class);
250
    }
251
252
    /**
253
     * Use this method to send general files. On success, the sent @see Message is returned. Bots can currently send files of any
254
     * type of up to 50 MB in size, this limit may be changed in the future.
255
     *
256
     * The document and thumb params can be either a string or a @see InputFile. Note that if you use the latter the file reading
257
     * operation is synchronous, so the main thread is blocked.
258
     * To make it asynchronous see https://github.com/badfarm/zanzara/wiki#working-with-files.
259
     *
260
     * By default the document is sent to the chat_id of the context's update. Use $opt param to specify a different
261
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
262
     *
263
     * More on https://core.telegram.org/bots/api#senddocument
264
     *
265
     * @param $document
266
     * @param array|null $opt
267
     * @return PromiseInterface
268
     */
269
    public function sendDocument($document, ?array $opt = []): PromiseInterface
270
    {
271
        $opt = $this->resolveChatId($opt);
272
        $required = compact("document");
273
        $params = array_merge($required, $opt);
274
        return $this->callApi("sendDocument", $params, Message::class);
275
    }
276
277
    /**
278
     * Use this method to send video files, Telegram clients support mp4 videos (other formats may be sent as Document). On
279
     * success, the sent @see Message is returned. Bots can currently send video files of up to 50 MB in size, this limit may
280
     * be changed in the future.
281
     *
282
     * The video and thumb params can be either a string or a @see InputFile. Note that if you use the latter the file reading
283
     * operation is synchronous, so the main thread is blocked.
284
     * To make it asynchronous see https://github.com/badfarm/zanzara/wiki#working-with-files.
285
     *
286
     * By default the video is sent to the chat_id of the context's update. Use $opt param to specify a different
287
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
288
     *
289
     * More on https://core.telegram.org/bots/api#sendvideo
290
     *
291
     * @param $video
292
     * @param array|null $opt
293
     * @return PromiseInterface
294
     */
295
    public function sendVideo($video, ?array $opt = []): PromiseInterface
296
    {
297
        $opt = $this->resolveChatId($opt);
298
        $required = compact("video");
299
        $params = array_merge($required, $opt);
300
        return $this->callApi("sendVideo", $params, Message::class);
301
    }
302
303
    /**
304
     * Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). On success, the sent @see Message
305
     * is returned. Bots can currently send animation files of up to 50 MB in size, this limit may be changed in the
306
     * future.
307
     *
308
     * The animation and thumb params can be either a string or a @see InputFile. Note that if you use the latter the file reading
309
     * operation is synchronous, so the main thread is blocked.
310
     * To make it asynchronous see https://github.com/badfarm/zanzara/wiki#working-with-files.
311
     *
312
     * By default the animation is sent to the chat_id of the context's update. Use $opt param to specify a different
313
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
314
     *
315
     * More on https://core.telegram.org/bots/api#sendanimation
316
     *
317
     * @param $animation
318
     * @param array|null $opt
319
     * @return PromiseInterface
320
     */
321
    public function sendAnimation($animation, ?array $opt = []): PromiseInterface
322
    {
323
        $opt = $this->resolveChatId($opt);
324
        $required = compact("animation");
325
        $params = array_merge($required, $opt);
326
        return $this->callApi("sendAnimation", $params, Message::class);
327
    }
328
329
    /**
330
     * Use this method to send audio files, if you want Telegram clients to display the file as a playable voice message.
331
     * For this to work, your audio must be in an .OGG file encoded with OPUS (other formats may be sent as Audio or
332
     * Document). On success, the sent @see Message is returned. Bots can currently send voice messages of up to 50 MB in
333
     * size, this limit may be changed in the future.
334
     *
335
     * The voice param can be either a string or a @see InputFile. Note that if you use the latter the file reading
336
     * operation is synchronous, so the main thread is blocked.
337
     * To make it asynchronous see https://github.com/badfarm/zanzara/wiki#working-with-files.
338
     *
339
     * By default the voice is sent to the chat_id of the context's update. Use $opt param to specify a different
340
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
341
     *
342
     * More on https://core.telegram.org/bots/api#sendvoice
343
     *
344
     * @param $voice
345
     * @param array|null $opt
346
     * @return PromiseInterface
347
     */
348
    public function sendVoice($voice, ?array $opt = []): PromiseInterface
349
    {
350
        $opt = $this->resolveChatId($opt);
351
        $required = compact("voice");
352
        $params = array_merge($required, $opt);
353
        return $this->callApi("sendVoice", $params, Message::class);
354
    }
355
356
    /**
357
     * As of v.4.0, Telegram clients support rounded square mp4 videos of up to 1 minute long. Use this method to send video
358
     * messages. On success, the sent @see Message is returned.
359
     *
360
     * 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
361
     * operation is synchronous, so the main thread is blocked.
362
     * To make it asynchronous see https://github.com/badfarm/zanzara/wiki#working-with-files.
363
     *
364
     * By default the video note is sent to the chat_id of the context's update. Use $opt param to specify a different
365
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
366
     *
367
     * More on https://core.telegram.org/bots/api#sendvideonote
368
     *
369
     * @param $video_note
370
     * @param array|null $opt
371
     * @return PromiseInterface
372
     */
373
    public function sendVideoNote($video_note, ?array $opt = []): PromiseInterface
374
    {
375
        $opt = $this->resolveChatId($opt);
376
        $required = compact("video_note");
377
        $params = array_merge($required, $opt);
378
        return $this->callApi("sendVideoNote", $params, Message::class);
379
    }
380
381
    /**
382
     * Use this method to send a group of photos or videos as an album. On success, an array of the sent @see Message 's is returned.
383
     *
384
     * By default the media group is sent to the chat_id of the context's update. Use $opt param to specify a different
385
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
386
     *
387
     * More on https://core.telegram.org/bots/api#sendmediagroup
388
     *
389
     * @param $media
390
     * @param array|null $opt
391
     * @return PromiseInterface
392
     */
393
    public function sendMediaGroup($media, ?array $opt = []): PromiseInterface
394
    {
395
        $opt = $this->resolveChatId($opt);
396
        $required = compact("media");
397
        $params = array_merge($required, $opt);
398
        return $this->callApi("sendMediaGroup", $params, Message::class);
399
    }
400
401
    /**
402
     * Use this method to send point on the map. On success, the sent @see Message is returned.
403
     *
404
     * By default the location is sent to the chat_id of the context's update. Use $opt param to specify a different
405
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
406
     *
407
     * More on https://core.telegram.org/bots/api#sendlocation
408
     *
409
     * @param $latitude
410
     * @param $longitude
411
     * @param array|null $opt
412
     * @return PromiseInterface
413
     */
414
    public function sendLocation($latitude, $longitude, ?array $opt = []): PromiseInterface
415
    {
416
        $opt = $this->resolveChatId($opt);
417
        $required = compact("latitude", "longitude");
418
        $params = array_merge($required, $opt);
419
        return $this->callApi("sendLocation", $params, Message::class);
420
    }
421
422
    /**
423
     * Use this method to edit live location messages. A location can be edited until its live_period expires or editing is
424
     * explicitly disabled by a call to stopMessageLiveLocation. On success, if the edited message was sent by the bot,
425
     * the edited @see Message is returned, otherwise True is returned.
426
     *
427
     * By default the chat_id is taken from the context's update. Use $opt param to specify a different
428
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
429
     *
430
     * By default the message_id is taken from the context's update. Use $opt param to specify a different
431
     * message_id. Eg. $opt = ['message_id' => 123456789];
432
     *
433
     * By default the inline_message_id is taken from the context's update. Use $opt param to specify a different
434
     * inline_message_id. Eg. $opt = ['inline_message_id' => 123456789];
435
     *
436
     * More on https://core.telegram.org/bots/api#editmessagelivelocation
437
     *
438
     * @param $latitude
439
     * @param $longitude
440
     * @param array|null $opt
441
     * @return PromiseInterface
442
     */
443
    public function editMessageLiveLocation($latitude, $longitude, ?array $opt = []): PromiseInterface
444
    {
445
        $opt = $this->resolveMessageId($opt);
446
        $required = compact("latitude", "longitude");
447
        $params = array_merge($required, $opt);
448
        return $this->callApi("editMessageLiveLocation", $params, Message::class);
449
    }
450
451
    /**
452
     * Use this method to stop updating a live location message before live_period expires. On success, if the message was
453
     * sent by the bot, the sent @see Message is returned, otherwise True is returned.
454
     *
455
     * By default the chat_id is taken from the context's update. Use $opt param to specify a different
456
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
457
     *
458
     * By default the message_id is taken from the context's update. Use $opt param to specify a different
459
     * message_id. Eg. $opt = ['message_id' => 123456789];
460
     *
461
     * By default the inline_message_id is taken from the context's update. Use $opt param to specify a different
462
     * inline_message_id. Eg. $opt = ['inline_message_id' => 123456789];
463
     *
464
     * More on https://core.telegram.org/bots/api#stopmessagelivelocation
465
     *
466
     * @param array|null $opt
467
     * @return PromiseInterface
468
     */
469
    public function stopMessageLiveLocation(?array $opt = []): PromiseInterface
470
    {
471
        $opt = $this->resolveMessageId($opt);
472
        return $this->callApi("stopMessageLiveLocation", $opt, Message::class);
0 ignored issues
show
Bug introduced by
It seems like $opt can also be of type null; however, parameter $params of Zanzara\Telegram\TelegramTrait::callApi() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

472
        return $this->callApi("stopMessageLiveLocation", /** @scrutinizer ignore-type */ $opt, Message::class);
Loading history...
473
    }
474
475
    /**
476
     * Use this method to send information about a venue. On success, the sent @see Message is returned.
477
     *
478
     * By default the venue is sent to the chat_id of the context's update. Use $opt param to specify a different
479
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
480
     *
481
     * More on https://core.telegram.org/bots/api#sendvenue
482
     *
483
     * @param $latitude
484
     * @param $longitude
485
     * @param string $title
486
     * @param string $address
487
     * @param array|null $opt
488
     * @return PromiseInterface
489
     */
490
    public function sendVenue($latitude, $longitude, string $title, string $address, ?array $opt = []): PromiseInterface
491
    {
492
        $opt = $this->resolveChatId($opt);
493
        $required = compact("latitude", "longitude", "title", "address");
494
        $params = array_merge($required, $opt);
495
        return $this->callApi("sendVenue", $params, Message::class);
496
    }
497
498
    /**
499
     * Use this method to send phone contacts. On success, the sent @see Message is returned.
500
     *
501
     * By default the contact is sent to the chat_id of the context's update. Use $opt param to specify a different
502
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
503
     *
504
     * More on https://core.telegram.org/bots/api#sendcontact
505
     *
506
     * @param string $phone_number
507
     * @param string $first_name
508
     * @param array|null $opt
509
     * @return PromiseInterface
510
     */
511
    public function sendContact(string $phone_number, string $first_name, ?array $opt = []): PromiseInterface
512
    {
513
        $opt = $this->resolveChatId($opt);
514
        $required = compact("phone_number", "first_name");
515
        $params = array_merge($required, $opt);
516
        return $this->callApi("sendContact", $params, Message::class);
517
    }
518
519
    /**
520
     * Use this method to send a native poll. On success, the sent @see Message is returned.
521
     *
522
     * By default the poll is sent to the chat_id of the context's update. Use $opt param to specify a different
523
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
524
     *
525
     * More on https://core.telegram.org/bots/api#sendpoll
526
     *
527
     * @param string $question
528
     * @param $options
529
     * @param array|null $opt
530
     * @return PromiseInterface
531
     */
532
    public function sendPoll(string $question, $options, ?array $opt = []): PromiseInterface
533
    {
534
        $opt = $this->resolveChatId($opt);
535
        $required = compact("question", "options");
536
        $params = array_merge($required, $opt);
537
        return $this->callApi("sendPoll", $params, Message::class);
538
    }
539
540
    /**
541
     * 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.
542
     * (Yes, we're aware of the "proper" singular of die. But it's awkward, and we decided to help it change. One dice at
543
     * a time!)
544
     *
545
     * By default the dice is sent to the chat_id of the context's update. Use $opt param to specify a different
546
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
547
     *
548
     * More on https://core.telegram.org/bots/api#senddice
549
     *
550
     * @param array|null $opt
551
     * @return PromiseInterface
552
     */
553
    public function sendDice(?array $opt = []): PromiseInterface
554
    {
555
        $opt = $this->resolveChatId($opt);
556
        return $this->callApi("sendDice", $opt, Message::class);
0 ignored issues
show
Bug introduced by
It seems like $opt can also be of type null; however, parameter $params of Zanzara\Telegram\TelegramTrait::callApi() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

556
        return $this->callApi("sendDice", /** @scrutinizer ignore-type */ $opt, Message::class);
Loading history...
557
    }
558
559
    /**
560
     * 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
561
     * seconds or less (when a message arrives from your bot, Telegram clients clear its typing status). Returns True on
562
     * success.
563
     *
564
     * By default the chat action is sent to the chat_id of the context's update. Use $opt param to specify a different
565
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
566
     *
567
     * More on https://core.telegram.org/bots/api#sendchataction
568
     *
569
     * @param string $action
570
     * @param array|null $opt
571
     * @return PromiseInterface
572
     */
573
    public function sendChatAction(string $action, ?array $opt = []): PromiseInterface
574
    {
575
        $opt = $this->resolveChatId($opt);
576
        $required = compact("action");
577
        $params = array_merge($required, $opt);
578
        return $this->callApi("sendChatAction", $params);
579
    }
580
581
    /**
582
     * Use this method to get a list of profile pictures for a user. Returns a @see UserProfilePhotos object.
583
     *
584
     * More on https://core.telegram.org/bots/api#getuserprofilephotos
585
     *
586
     * @param int $user_id
587
     * @param array|null $opt
588
     * @return PromiseInterface
589
     */
590
    public function getUserProfilePhotos(int $user_id, ?array $opt = []): PromiseInterface
591
    {
592
        $required = compact("user_id");
593
        $params = array_merge($required, $opt);
594
        return $this->callApi("getUserProfilePhotos", $params, UserProfilePhotos::class);
595
    }
596
597
    /**
598
     * Use this method to get basic info about a file and prepare it for downloading. For the moment, bots can download
599
     * files of up to 20MB in size. On success, a @see File object is returned. The file can then be downloaded via the link
600
     * https://api.telegram.org/file/bot&lt;token&gt;/&lt;file_path&gt;, where &lt;file_path&gt; is taken from the
601
     * response. It is guaranteed that the link will be valid for at least 1 hour. When the link expires, a new one can
602
     * be requested by calling getFile again.
603
     *
604
     * More on https://core.telegram.org/bots/api#getfile
605
     *
606
     * @param string $file_id
607
     * @param array|null $opt
608
     * @return PromiseInterface
609
     */
610
    public function getFile(string $file_id, ?array $opt = []): PromiseInterface
611
    {
612
        $required = compact("file_id");
613
        $params = array_merge($required, $opt);
614
        return $this->callApi("getFile", $params, File::class);
615
    }
616
617
    /**
618
     * Use this method to kick a user from a group, a supergroup or a channel. In the case of supergroups and channels, the
619
     * user will not be able to return to the group on their own using invite links, etc., unless unbanned first. The bot
620
     * must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on
621
     * success.
622
     *
623
     * More on https://core.telegram.org/bots/api#kickchatmember
624
     *
625
     * @param int $chat_id
626
     * @param int $user_id
627
     * @param array|null $opt
628
     * @return PromiseInterface
629
     */
630
    public function kickChatMember(int $chat_id, int $user_id, ?array $opt = []): PromiseInterface
631
    {
632
        $required = compact("chat_id", "user_id");
633
        $params = array_merge($required, $opt);
634
        return $this->callApi("kickChatMember", $params);
635
    }
636
637
    /**
638
     * Use this method to unban a previously kicked user in a supergroup or channel. The user will not return to the group
639
     * or channel automatically, but will be able to join via link, etc. The bot must be an administrator for this to
640
     * work. Returns True on success.
641
     *
642
     * More on https://core.telegram.org/bots/api#unbanchatmember
643
     *
644
     * @param int $chat_id
645
     * @param int $user_id
646
     * @param array|null $opt
647
     * @return PromiseInterface
648
     */
649
    public function unbanChatMember(int $chat_id, int $user_id, ?array $opt = []): PromiseInterface
650
    {
651
        $required = compact("chat_id", "user_id");
652
        $params = array_merge($required, $opt);
653
        return $this->callApi("unbanChatMember", $params);
654
    }
655
656
    /**
657
     * Use this method to restrict a user in a supergroup. The bot must be an administrator in the supergroup for this to
658
     * work and must have the appropriate admin rights. Pass True for all permissions to lift restrictions from a user.
659
     * Returns True on success.
660
     *
661
     * More on https://core.telegram.org/bots/api#restrictchatmember
662
     *
663
     * @param int $chat_id
664
     * @param int $user_id
665
     * @param $permissions
666
     * @param array|null $opt
667
     * @return PromiseInterface
668
     */
669
    public function restrictChatMember(int $chat_id, int $user_id, $permissions, ?array $opt = []): PromiseInterface
670
    {
671
        $required = compact("chat_id", "user_id", "permissions");
672
        $params = array_merge($required, $opt);
673
        return $this->callApi("restrictChatMember", $params);
674
    }
675
676
    /**
677
     * Use this method to promote or demote a user in a supergroup or a channel. The bot must be an administrator in the
678
     * chat for this to work and must have the appropriate admin rights. Pass False for all boolean parameters to demote
679
     * a user. Returns True on success.
680
     *
681
     * More on https://core.telegram.org/bots/api#promotechatmember
682
     *
683
     * @param int $chat_id
684
     * @param int $user_id
685
     * @param array|null $opt
686
     * @return PromiseInterface
687
     */
688
    public function promoteChatMember(int $chat_id, int $user_id, ?array $opt = []): PromiseInterface
689
    {
690
        $required = compact("chat_id", "user_id");
691
        $params = array_merge($required, $opt);
692
        return $this->callApi("promoteChatMember", $params);
693
    }
694
695
    /**
696
     * Use this method to set a custom title for an administrator in a supergroup promoted by the bot. Returns True on success.
697
     *
698
     * More on https://core.telegram.org/bots/api#setchatadministratorcustomtitle
699
     *
700
     * @param int $chat_id
701
     * @param int $user_id
702
     * @param string $custom_title
703
     * @param array|null $opt
704
     * @return PromiseInterface
705
     */
706
    public function setChatAdministratorCustomTitle(int $chat_id, int $user_id, string $custom_title, ?array $opt = []): PromiseInterface
707
    {
708
        $required = compact("chat_id", "user_id", "custom_title");
709
        $params = array_merge($required, $opt);
710
        return $this->callApi("setChatAdministratorCustomTitle", $params);
711
    }
712
713
    /**
714
     * Use this method to set default chat permissions for all members. The bot must be an administrator in the group or a
715
     * supergroup for this to work and must have the can_restrict_members admin rights. Returns True on success.
716
     *
717
     * More on https://core.telegram.org/bots/api#setchatpermissions
718
     *
719
     * @param int $chat_id
720
     * @param $permissions
721
     * @param array|null $opt
722
     * @return PromiseInterface
723
     */
724
    public function setChatPermissions(int $chat_id, $permissions, ?array $opt = []): PromiseInterface
725
    {
726
        $required = compact("chat_id", "permissions");
727
        $params = array_merge($required, $opt);
728
        return $this->callApi("setChatPermissions", $params);
729
    }
730
731
    /**
732
     * Use this method to generate a new invite link for a chat; any previously generated link is revoked. The bot must be
733
     * an administrator in the chat for this to work and must have the appropriate admin rights. Returns the new invite
734
     * link as String on success.
735
     *
736
     * More on https://core.telegram.org/bots/api#exportchatinvitelink
737
     *
738
     * @param int $chat_id
739
     * @param array|null $opt
740
     * @return PromiseInterface
741
     */
742
    public function exportChatInviteLink(int $chat_id, ?array $opt = []): PromiseInterface
743
    {
744
        $required = compact("chat_id");
745
        $params = array_merge($required, $opt);
746
        return $this->callApi("exportChatInviteLink", $params);
747
    }
748
749
    /**
750
     * Use this method to set a new profile photo for the chat. Photos can't be changed for private chats. The bot must be
751
     * an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success.
752
     *
753
     * More on https://core.telegram.org/bots/api#setchatphoto
754
     *
755
     * @param int $chat_id
756
     * @param $photo
757
     * @param array|null $opt
758
     * @return PromiseInterface
759
     */
760
    public function setChatPhoto(int $chat_id, $photo, ?array $opt = []): PromiseInterface
761
    {
762
        $required = compact("chat_id", "photo");
763
        $params = array_merge($required, $opt);
764
        return $this->callApi("setChatPhoto", $params); //bool
765
    }
766
767
    /**
768
     * Use this method to delete a chat photo. Photos can't be changed for private chats. The bot must be an administrator
769
     * in the chat for this to work and must have the appropriate admin rights. Returns True on success.
770
     *
771
     * More on https://core.telegram.org/bots/api#deletechatphoto
772
     *
773
     * @param int $chat_id
774
     * @param array|null $opt
775
     * @return PromiseInterface
776
     */
777
    public function deleteChatPhoto(int $chat_id, ?array $opt = []): PromiseInterface
778
    {
779
        $required = compact("chat_id");
780
        $params = array_merge($required, $opt);
781
        return $this->callApi("deleteChatPhoto", $params);
782
    }
783
784
    /**
785
     * Use this method to change the title of a chat. Titles can't be changed for private chats. The bot must be an
786
     * administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success.
787
     *
788
     * More on https://core.telegram.org/bots/api#setchattitle
789
     *
790
     * @param int $chat_id
791
     * @param string $title
792
     * @param array|null $opt
793
     * @return PromiseInterface
794
     */
795
    public function setChatTitle(int $chat_id, string $title, ?array $opt = []): PromiseInterface
796
    {
797
        $required = compact("chat_id", "title");
798
        $params = array_merge($required, $opt);
799
        return $this->callApi("setChatTitle", $params);
800
    }
801
802
    /**
803
     * Use this method to change the description of a group, a supergroup or a channel. The bot must be an administrator in
804
     * the chat for this to work and must have the appropriate admin rights. Returns True on success.
805
     *
806
     * More on https://core.telegram.org/bots/api#setchatdescription
807
     *
808
     * @param int $chat_id
809
     * @param array|null $opt
810
     * @return PromiseInterface
811
     */
812
    public function setChatDescription(int $chat_id, ?array $opt = []): PromiseInterface
813
    {
814
        $required = compact("chat_id");
815
        $params = array_merge($required, $opt);
816
        return $this->callApi("setChatDescription", $params);
817
    }
818
819
    /**
820
     * Use this method to pin a message in a group, a supergroup, or a channel. The bot must be an administrator in the chat
821
     * for this to work and must have the 'can_pin_messages' admin right in the supergroup or 'can_edit_messages' admin
822
     * right in the channel. Returns True on success.
823
     *
824
     * More on https://core.telegram.org/bots/api#pinchatmessage
825
     *
826
     * @param int $chat_id
827
     * @param int $message_id
828
     * @param array|null $opt
829
     * @return PromiseInterface
830
     */
831
    public function pinChatMessage(int $chat_id, int $message_id, ?array $opt = []): PromiseInterface
832
    {
833
        $required = compact("chat_id", "message_id");
834
        $params = array_merge($required, $opt);
835
        return $this->callApi("pinChatMessage", $params);
836
    }
837
838
    /**
839
     * Use this method to unpin a message in a group, a supergroup, or a channel. The bot must be an administrator in the
840
     * chat for this to work and must have the 'can_pin_messages' admin right in the supergroup or 'can_edit_messages'
841
     * admin right in the channel. Returns True on success.
842
     *
843
     * More on https://core.telegram.org/bots/api#unpinchatmessage
844
     *
845
     * @param int $chat_id
846
     * @param array|null $opt
847
     * @return PromiseInterface
848
     */
849
    public function unpinChatMessage(int $chat_id, ?array $opt = []): PromiseInterface
850
    {
851
        $required = compact("chat_id");
852
        $params = array_merge($required, $opt);
853
        return $this->callApi("unpinChatMessage", $params);
854
    }
855
856
    /**
857
     * Use this method for your bot to leave a group, supergroup or channel. Returns True on success.
858
     *
859
     * More on https://core.telegram.org/bots/api#leavechat
860
     *
861
     * @param int $chat_id
862
     * @param array|null $opt
863
     * @return PromiseInterface
864
     */
865
    public function leaveChat(int $chat_id, ?array $opt = []): PromiseInterface
866
    {
867
        $required = compact("chat_id");
868
        $params = array_merge($required, $opt);
869
        return $this->callApi("leaveChat", $params);
870
    }
871
872
    /**
873
     * Use this method to get up to date information about the chat (current name of the user for one-on-one conversations,
874
     * current username of a user, group or channel, etc.). Returns a @see Chat object on success.
875
     *
876
     * More on https://core.telegram.org/bots/api#getchat
877
     *
878
     * @param int $chat_id
879
     * @param array|null $opt
880
     * @return PromiseInterface
881
     */
882
    public function getChat(int $chat_id, ?array $opt = []): PromiseInterface
883
    {
884
        $required = compact("chat_id");
885
        $params = array_merge($required, $opt);
886
        return $this->callApi("getChat", $params, Chat::class);
887
    }
888
889
    /**
890
     * Use this method to get a list of administrators in a chat. On success, returns an Array of @see ChatMember objects that
891
     * contains information about all chat administrators except other bots. If the chat is a group or a supergroup and
892
     * no administrators were appointed, only the creator will be returned.
893
     *
894
     * More on https://core.telegram.org/bots/api#getchatadministrators
895
     *
896
     * @param int $chat_id
897
     * @param array|null $opt
898
     * @return PromiseInterface
899
     */
900
    public function getChatAdministrators(int $chat_id, ?array $opt = []): PromiseInterface
901
    {
902
        $required = compact("chat_id");
903
        $params = array_merge($required, $opt);
904
        return $this->callApi("getChatAdministrators", $params, ChatMember::class);
905
    }
906
907
    /**
908
     * Use this method to get the number of members in a chat. Returns Int on success.
909
     *
910
     * More on https://core.telegram.org/bots/api#getchatmemberscount
911
     *
912
     * @param int $chat_id
913
     * @param array|null $opt
914
     * @return PromiseInterface
915
     */
916
    public function getChatMembersCount(int $chat_id, ?array $opt = []): PromiseInterface
917
    {
918
        $required = compact("chat_id");
919
        $params = array_merge($required, $opt);
920
        return $this->callApi("getChatMembersCount", $params); //integer
921
    }
922
923
    /**
924
     * Use this method to get information about a member of a chat. Returns a @see ChatMember object on success.
925
     *
926
     * More on https://core.telegram.org/bots/api#getchatmember
927
     *
928
     * @param int $chat_id
929
     * @param int $user_id
930
     * @param array|null $opt
931
     * @return PromiseInterface
932
     */
933
    public function getChatMember(int $chat_id, int $user_id, ?array $opt = []): PromiseInterface
934
    {
935
        $required = compact("chat_id", "user_id");
936
        $params = array_merge($required, $opt);
937
        return $this->callApi("getChatMember", $params, ChatMember::class);
938
    }
939
940
    /**
941
     * Use this method to set a new group sticker set for a supergroup. The bot must be an administrator in the chat for
942
     * this to work and must have the appropriate admin rights. Use the field can_set_sticker_set optionally returned in
943
     * getChat requests to check if the bot can use this method. Returns True on success.
944
     *
945
     * More on https://core.telegram.org/bots/api#setchatstickerset
946
     *
947
     * @param int $chat_id
948
     * @param string $sticker_set_name
949
     * @param array|null $opt
950
     * @return PromiseInterface
951
     */
952
    public function setChatStickerSet(int $chat_id, string $sticker_set_name, ?array $opt = []): PromiseInterface
953
    {
954
        $required = compact("chat_id", "sticker_set_name");
955
        $params = array_merge($required, $opt);
956
        return $this->callApi("setChatStickerSet", $params);
957
    }
958
959
    /**
960
     * Use this method to delete a group sticker set from a supergroup. The bot must be an administrator in the chat for
961
     * this to work and must have the appropriate admin rights. Use the field can_set_sticker_set optionally returned in
962
     * getChat requests to check if the bot can use this method. Returns True on success.
963
     *
964
     * More on https://core.telegram.org/bots/api#deletechatstickerset
965
     *
966
     * @param int $chat_id
967
     * @param array|null $opt
968
     * @return PromiseInterface
969
     */
970
    public function deleteChatStickerSet(int $chat_id, ?array $opt = []): PromiseInterface
971
    {
972
        $required = compact("chat_id");
973
        $params = array_merge($required, $opt);
974
        return $this->callApi("deleteChatStickerSet", $params);
975
    }
976
977
    /**
978
     * Use this method to send answers to callback queries sent from inline keyboards. The answer will be displayed to the
979
     * user as a notification at the top of the chat screen or as an alert. On success, True is returned.
980
     *
981
     * By default it replies to the callback_query_id of the context's update. Use $opt param to specify a different
982
     * callback_query_id. Eg. $opt = ['callback_query_id' => 'abcdefgh'];
983
     *
984
     * More on https://core.telegram.org/bots/api#answercallbackquery
985
     *
986
     * @param array|null $opt
987
     * @return PromiseInterface
988
     */
989
    public function answerCallbackQuery(?array $opt = []): PromiseInterface
990
    {
991
        if (!isset($opt['callback_query_id']) && $this->update) {
992
            $opt['callback_query_id'] = $this->update->getCallbackQuery()->getId();
993
        }
994
        return $this->callApi("answerCallbackQuery", $opt);
995
    }
996
997
    /**
998
     * Use this method to change the list of the bot's commands. Returns True on success.
999
     *
1000
     * More on https://core.telegram.org/bots/api#setmycommands
1001
     *
1002
     * @param $commands
1003
     * @param array|null $opt
1004
     * @return PromiseInterface
1005
     */
1006
    public function setMyCommands($commands, ?array $opt = []): PromiseInterface
1007
    {
1008
        $required = compact("commands");
1009
        $params = array_merge($required, $opt);
1010
        return $this->callApi("setMyCommands", $params);
1011
    }
1012
1013
    /**
1014
     * Use this method to edit text and game messages. On success, if edited message is sent by the bot, the edited @see Message
1015
     * is returned, otherwise True is returned.
1016
     *
1017
     * By default the chat_id is taken from the context's update. Use $opt param to specify a different
1018
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
1019
     *
1020
     * By default the message_id is taken from the context's update. Use $opt param to specify a different
1021
     * message_id. Eg. $opt = ['message_id' => 123456789];
1022
     *
1023
     * By default the inline_message_id is taken from the context's update. Use $opt param to specify a different
1024
     * inline_message_id. Eg. $opt = ['inline_message_id' => 123456789];
1025
     *
1026
     * More on https://core.telegram.org/bots/api#editmessagetext
1027
     *
1028
     * @param string $text
1029
     * @param array|null $opt = [
1030
     *     'reply_markup' => ['inline_keyboard' => [[
1031
     *          ['callback_data' => 'data', 'text' => 'text']
1032
     *      ]]]
1033
     * ]
1034
     * @return PromiseInterface
1035
     */
1036
    public function editMessageText(string $text, ?array $opt = []): PromiseInterface
1037
    {
1038
        $opt = $this->resolveMessageId($opt);
1039
        $required = compact("text");
1040
        $params = array_merge($required, $opt);
1041
        return $this->callApi("editMessageText", $params, Message::class);
1042
    }
1043
1044
    /**
1045
     * Use this method to edit captions of messages. On success, if edited message is sent by the bot, the edited @see Message is
1046
     * returned, otherwise True is returned.
1047
     *
1048
     * By default the chat_id is taken from the context's update. Use $opt param to specify a different
1049
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
1050
     *
1051
     * By default the message_id is taken from the context's update. Use $opt param to specify a different
1052
     * message_id. Eg. $opt = ['message_id' => 123456789];
1053
     *
1054
     * By default the inline_message_id is taken from the context's update. Use $opt param to specify a different
1055
     * inline_message_id. Eg. $opt = ['inline_message_id' => 123456789];
1056
     *
1057
     * More on https://core.telegram.org/bots/api#editmessagecaption
1058
     *
1059
     * @param array|null $opt
1060
     * @return PromiseInterface
1061
     */
1062
    public function editMessageCaption(?array $opt = []): PromiseInterface
1063
    {
1064
        $opt = $this->resolveMessageId($opt);
1065
        return $this->callApi("editMessageCaption", $opt, Message::class);
0 ignored issues
show
Bug introduced by
It seems like $opt can also be of type null; however, parameter $params of Zanzara\Telegram\TelegramTrait::callApi() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1065
        return $this->callApi("editMessageCaption", /** @scrutinizer ignore-type */ $opt, Message::class);
Loading history...
1066
    }
1067
1068
    /**
1069
     * Use this method to edit animation, audio, document, photo, or video messages. If a message is a part of a message
1070
     * album, then it can be edited only to a photo or a video. Otherwise, message type can be changed arbitrarily. When
1071
     * inline message is edited, new file can't be uploaded. Use previously uploaded file via its file_id or specify a
1072
     * URL. On success, if the edited message was sent by the bot, the edited @see Message is returned, otherwise True is
1073
     * returned.
1074
     *
1075
     * By default the chat_id is taken from the context's update. Use $opt param to specify a different
1076
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
1077
     *
1078
     * By default the message_id is taken from the context's update. Use $opt param to specify a different
1079
     * message_id. Eg. $opt = ['message_id' => 123456789];
1080
     *
1081
     * By default the inline_message_id is taken from the context's update. Use $opt param to specify a different
1082
     * inline_message_id. Eg. $opt = ['inline_message_id' => 123456789];
1083
     *
1084
     * More on https://core.telegram.org/bots/api#editmessagemedia
1085
     *
1086
     * @param $media
1087
     * @param array|null $opt
1088
     * @return PromiseInterface
1089
     */
1090
    public function editMessageMedia($media, ?array $opt = []): PromiseInterface
1091
    {
1092
        $opt = $this->resolveMessageId($opt);
1093
        $required = compact("media");
1094
        $params = array_merge($required, $opt);
1095
        return $this->callApi("editMessageMedia", $params, Message::class);
1096
    }
1097
1098
    /**
1099
     * Use this method to edit only the reply markup of messages. On success, if edited message is sent by the bot, the
1100
     * edited @see Message is returned, otherwise True is returned.
1101
     *
1102
     * By default the chat_id is taken from the context's update. Use $opt param to specify a different
1103
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
1104
     *
1105
     * By default the message_id is taken from the context's update. Use $opt param to specify a different
1106
     * message_id. Eg. $opt = ['message_id' => 123456789];
1107
     *
1108
     * By default the inline_message_id is taken from the context's update. Use $opt param to specify a different
1109
     * inline_message_id. Eg. $opt = ['inline_message_id' => 123456789];
1110
     *
1111
     * More on https://core.telegram.org/bots/api#editmessagereplymarkup
1112
     *
1113
     * @param array|null $opt
1114
     * @return PromiseInterface
1115
     */
1116
    public function editMessageReplyMarkup(?array $opt = []): PromiseInterface
1117
    {
1118
        $opt = $this->resolveMessageId($opt);
1119
        return $this->callApi("editMessageReplyMarkup", $opt, Message::class);
0 ignored issues
show
Bug introduced by
It seems like $opt can also be of type null; however, parameter $params of Zanzara\Telegram\TelegramTrait::callApi() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1119
        return $this->callApi("editMessageReplyMarkup", /** @scrutinizer ignore-type */ $opt, Message::class);
Loading history...
1120
    }
1121
1122
    /**
1123
     * Use this method to stop a poll which was sent by the bot. On success, the stopped @see Poll with the final results is
1124
     * returned.
1125
     *
1126
     * More on https://core.telegram.org/bots/api#stoppoll
1127
     *
1128
     * @param int $chat_id
1129
     * @param int $message_id
1130
     * @param array|null $opt
1131
     * @return PromiseInterface
1132
     */
1133
    public function stopPoll(int $chat_id, int $message_id, ?array $opt = []): PromiseInterface
1134
    {
1135
        $required = compact("chat_id", "message_id");
1136
        $params = array_merge($required, $opt);
1137
        return $this->callApi("stopPoll", $params, Poll::class);
1138
    }
1139
1140
    /**
1141
     * Use this method to delete a message, including service messages, with the following limitations:- A message can only
1142
     * 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
1143
     * sent more than 24 hours ago.- Bots can delete outgoing messages in private chats, groups, and supergroups.- Bots
1144
     * can delete incoming messages in private chats.- Bots granted can_post_messages permissions can delete outgoing
1145
     * messages in channels.- If the bot is an administrator of a group, it can delete any message there.- If the bot has
1146
     * can_delete_messages permission in a supergroup or a channel, it can delete any message there.Returns True on
1147
     * success.
1148
     *
1149
     * More on https://core.telegram.org/bots/api#deletemessage
1150
     *
1151
     * @param int $chat_id
1152
     * @param int $message_id
1153
     * @param array|null $opt
1154
     * @return PromiseInterface
1155
     */
1156
    public function deleteMessage(int $chat_id, int $message_id, ?array $opt = []): PromiseInterface
1157
    {
1158
        $required = compact("chat_id", "message_id");
1159
        $params = array_merge($required, $opt);
1160
        return $this->callApi("deleteMessage", $params);
1161
    }
1162
1163
    /**
1164
     * Use this method to send static .WEBP or animated .TGS stickers. On success, the sent @see Message is returned.
1165
     *
1166
     * The sticker param can be either a string or a @see InputFile. Note that if you use the latter the file reading
1167
     * operation is synchronous, so the main thread is blocked.
1168
     * To make it asynchronous see https://github.com/badfarm/zanzara/wiki#working-with-files.
1169
     *
1170
     * By default the sticker is sent to the chat_id of the context's update. Use $opt param to specify a different
1171
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
1172
     *
1173
     * More on https://core.telegram.org/bots/api#sendsticker
1174
     *
1175
     * @param $sticker
1176
     * @param array|null $opt
1177
     * @return PromiseInterface
1178
     */
1179
    public function sendSticker($sticker, ?array $opt = []): PromiseInterface
1180
    {
1181
        $opt = $this->resolveChatId($opt);
1182
        $required = compact("sticker");
1183
        $params = array_merge($required, $opt);
1184
        return $this->callApi("sendSticker", $params, Message::class);
1185
    }
1186
1187
    /**
1188
     * Use this method to get a sticker set. On success, a @see StickerSet object is returned.
1189
     *
1190
     * More on https://core.telegram.org/bots/api#getstickerset
1191
     *
1192
     * @param string $name
1193
     * @param array|null $opt
1194
     * @return PromiseInterface
1195
     */
1196
    public function getStickerSet(string $name, ?array $opt = []): PromiseInterface
1197
    {
1198
        $required = compact("name");
1199
        $params = array_merge($required, $opt);
1200
        return $this->callApi("getStickerSet", $params, StickerSet::class);
1201
    }
1202
1203
    /**
1204
     * Use this method to upload a .PNG file with a sticker for later use in createNewStickerSet and addStickerToSet methods
1205
     * (can be used multiple times). Returns the uploaded @see File on success.
1206
     *
1207
     * More on https://core.telegram.org/bots/api#uploadstickerfile
1208
     *
1209
     * @param int $user_id
1210
     * @param $png_sticker
1211
     * @param array|null $opt
1212
     * @return PromiseInterface
1213
     */
1214
    public function uploadStickerFile(int $user_id, $png_sticker, ?array $opt = []): PromiseInterface
1215
    {
1216
        $required = compact("user_id", "png_sticker");
1217
        $params = array_merge($required, $opt);
1218
        return $this->callApi("uploadStickerFile", $params, File::class);
1219
    }
1220
1221
    /**
1222
     * Use this method to create a new sticker set owned by a user. The bot will be able to edit the sticker set thus
1223
     * created. You must use exactly one of the fields png_sticker or tgs_sticker. Returns True on success.
1224
     *
1225
     * The png_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
     * More on https://core.telegram.org/bots/api#createnewstickerset
1230
     *
1231
     * @param int $user_id
1232
     * @param string $name
1233
     * @param string $title
1234
     * @param string $emojis
1235
     * @param array|null $opt
1236
     * @return PromiseInterface
1237
     */
1238
    public function createNewStickerSet(int $user_id, string $name, string $title, string $emojis, ?array $opt = []): PromiseInterface
1239
    {
1240
        $required = compact("user_id", "name", "title", "emojis");
1241
        $params = array_merge($required, $opt);
1242
        return $this->callApi("createNewStickerSet", $params);
1243
    }
1244
1245
    /**
1246
     * 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
1247
     * or tgs_sticker. Animated stickers can be added to animated sticker sets and only to them. Animated sticker sets
1248
     * can have up to 50 stickers. Static sticker sets can have up to 120 stickers. Returns True on success.
1249
     *
1250
     * The png_sticker param can be either a string or a @see InputFile. Note that if you use the latter the file reading
1251
     * operation is synchronous, so the main thread is blocked.
1252
     * To make it asynchronous see https://github.com/badfarm/zanzara/wiki#working-with-files.
1253
     *
1254
     * More on https://core.telegram.org/bots/api#addstickertoset
1255
     *
1256
     * @param int $user_id
1257
     * @param string $name
1258
     * @param $png_sticker
1259
     * @param string $emojis
1260
     * @param array|null $opt
1261
     * @return PromiseInterface
1262
     */
1263
    public function addStickerToSet(int $user_id, string $name, $png_sticker, string $emojis, ?array $opt = []): PromiseInterface
1264
    {
1265
        $required = compact("user_id", "name", "png_sticker", "emojis");
1266
        $params = array_merge($required, $opt);
1267
        return $this->callApi("addStickerToSet", $params);
1268
    }
1269
1270
    /**
1271
     * Use this method to move a sticker in a set created by the bot to a specific position. Returns True on success.
1272
     *
1273
     * More on https://core.telegram.org/bots/api#setstickerpositioninset
1274
     *
1275
     * @param string $sticker
1276
     * @param int $position
1277
     * @param array|null $opt
1278
     * @return PromiseInterface
1279
     */
1280
    public function setStickerPositionInSet(string $sticker, int $position, ?array $opt = []): PromiseInterface
1281
    {
1282
        $required = compact("sticker", "position");
1283
        $params = array_merge($required, $opt);
1284
        return $this->callApi("setStickerPositionInSet", $params);
1285
    }
1286
1287
    /**
1288
     * Use this method to delete a sticker from a set created by the bot. Returns True on success.
1289
     *
1290
     * More on https://core.telegram.org/bots/api#deletestickerfromset
1291
     *
1292
     * @param string $sticker
1293
     * @param array|null $opt
1294
     * @return PromiseInterface
1295
     */
1296
    public function deleteStickerFromSet(string $sticker, ?array $opt = []): PromiseInterface
1297
    {
1298
        $required = compact("sticker");
1299
        $params = array_merge($required, $opt);
1300
        return $this->callApi("deleteStickerFromSet", $params);
1301
    }
1302
1303
    /**
1304
     * Use this method to set the thumbnail of a sticker set. Animated thumbnails can be set for animated sticker sets only.
1305
     * Returns True on success.
1306
     *
1307
     * The thumb param in $opt can be either a string or a @see InputFile. Note that if you use the latter the file reading
1308
     * operation is synchronous, so the main thread is blocked.
1309
     * To make it asynchronous see https://github.com/badfarm/zanzara/wiki#working-with-files.
1310
     *
1311
     * More on https://core.telegram.org/bots/api#setstickersetthumb
1312
     *
1313
     * @param string $name
1314
     * @param int $user_id
1315
     * @param array|null $opt
1316
     * @return PromiseInterface
1317
     */
1318
    public function setStickerSetThumb(string $name, int $user_id, ?array $opt = []): PromiseInterface
1319
    {
1320
        $required = compact("name", "user_id");
1321
        $params = array_merge($required, $opt);
1322
        return $this->callApi("setStickerSetThumb", $params);
1323
    }
1324
1325
    /**
1326
     * Use this method to send answers to an inline query. On success, True is returned.No more than 50 results per query
1327
     * are allowed.
1328
     *
1329
     * By default it replies to the inline_query_id of the context's update. Use $opt param to specify a different
1330
     * inline_query_id. Eg. $opt = ['inline_query_id' => 'abcdefgh'];
1331
     *
1332
     * More on https://core.telegram.org/bots/api#answerinlinequery
1333
     *
1334
     * @param $results
1335
     * @param array|null $opt
1336
     * @return PromiseInterface
1337
     */
1338
    public function answerInlineQuery($results, ?array $opt = []): PromiseInterface
1339
    {
1340
        if (!isset($opt['inline_query_id']) && $this->update) {
1341
            $opt['inline_query_id'] = $this->update->getInlineQuery()->getId();
1342
        }
1343
        $required = compact("results");
1344
        $params = array_merge($required, $opt);
1345
        return $this->callApi("answerInlineQuery", $params);
1346
    }
1347
1348
    /**
1349
     * Use this method to send invoices. On success, the sent @see Message is returned.
1350
     *
1351
     * By default the invoice is sent to the chat_id of the context's update. Use $opt param to specify a different
1352
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
1353
     *
1354
     * More on https://core.telegram.org/bots/api#sendinvoice
1355
     *
1356
     * @param string $title
1357
     * @param string $description
1358
     * @param string $payload
1359
     * @param string $provider_token
1360
     * @param string $start_parameter
1361
     * @param string $currency
1362
     * @param $prices
1363
     * @param array|null $opt
1364
     * @return PromiseInterface
1365
     */
1366
    public function sendInvoice(string $title, string $description, string $payload, string $provider_token, string $start_parameter, string $currency, $prices, ?array $opt = []): PromiseInterface
1367
    {
1368
        $opt = $this->resolveChatId($opt);
1369
        $required = compact("title", "description", "payload", "provider_token", "start_parameter", "currency", "prices");
1370
        $params = array_merge($required, $opt);
1371
        return $this->callApi("sendInvoice", $params, Message::class);
1372
    }
1373
1374
    /**
1375
     * @param array $params
1376
     * @return PromiseInterface
1377
     */
1378
    public function doSendInvoice(array $params): PromiseInterface
1379
    {
1380
        if (!isset($opt['chat_id']) && $this->update) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $opt seems to never exist and therefore isset should always be false.
Loading history...
1381
            $params['chat_id'] = $this->update->getEffectiveChat()->getId();
1382
        }
1383
        return $this->callApi("sendInvoice", $params, Message::class);
1384
    }
1385
1386
    /**
1387
     * If you sent an invoice requesting a shipping address and the parameter is_flexible was specified, the Bot API will
1388
     * send an Update with a shipping_query field to the bot. Use this method to reply to shipping queries. On success,
1389
     * True is returned.
1390
     *
1391
     * By default it replies to the shipping_query_id of the context's update. Use $opt param to specify a different
1392
     * shipping_query_id. Eg. $opt = ['shipping_query_id' => 'abcdefgh'];
1393
     *
1394
     * More on https://core.telegram.org/bots/api#answershippingquery
1395
     *
1396
     * @param $ok
1397
     * @param array|null $opt
1398
     * @return PromiseInterface
1399
     */
1400
    public function answerShippingQuery($ok, ?array $opt = []): PromiseInterface
1401
    {
1402
        if (!isset($opt['shipping_query_id']) && $this->update) {
1403
            $opt['shipping_query_id'] = $this->update->getShippingQuery()->getId();
1404
        }
1405
        $required = compact("ok");
1406
        $params = array_merge($required, $opt);
1407
        return $this->callApi("answerShippingQuery", $params);
1408
    }
1409
1410
    /**
1411
     * Once the user has confirmed their payment and shipping details, the Bot API sends the final confirmation in the form
1412
     * of an Update with the field pre_checkout_query. Use this method to respond to such pre-checkout queries. On
1413
     * success, True is returned. Note: The Bot API must receive an answer within 10 seconds after the pre-checkout query
1414
     * was sent.
1415
     *
1416
     * By default it replies to the pre_checkout_query_id of the context's update. Use $opt param to specify a different
1417
     * pre_checkout_query_id. Eg. $opt = ['pre_checkout_query_id' => 'abcdefgh'];
1418
     *
1419
     * More on https://core.telegram.org/bots/api#answerprecheckoutquery
1420
     *
1421
     * @param $ok
1422
     * @param array|null $opt
1423
     * @return PromiseInterface
1424
     */
1425
    public function answerPreCheckoutQuery($ok, ?array $opt = []): PromiseInterface
1426
    {
1427
        if (!isset($opt['pre_checkout_query_id']) && $this->update) {
1428
            $opt['pre_checkout_query_id'] = $this->update->getPreCheckoutQuery()->getId();
1429
        }
1430
        $required = compact("ok");
1431
        $params = array_merge($required, $opt);
1432
        return $this->callApi("answerPreCheckoutQuery", $params);
1433
    }
1434
1435
    /**
1436
     * Informs a user that some of the Telegram Passport elements they provided contains errors. The user will not be able
1437
     * to re-submit their Passport to you until the errors are fixed (the contents of the field for which you returned
1438
     * the error must change). Returns True on success.
1439
     *
1440
     * More on https://core.telegram.org/bots/api#setpassportdataerrors
1441
     *
1442
     * @param int $user_id
1443
     * @param $errors
1444
     * @param array|null $opt
1445
     * @return PromiseInterface
1446
     */
1447
    public function setPassportDataErrors(int $user_id, $errors, ?array $opt = []): PromiseInterface
1448
    {
1449
        $required = compact("user_id", "errors");
1450
        $params = array_merge($required, $opt);
1451
        return $this->callApi("setPassportDataErrors", $params);
1452
    }
1453
1454
    /**
1455
     * Use this method to send a game. On success, the sent @see Message is returned.
1456
     *
1457
     * By default the game is sent to the chat_id of the context's update. Use $opt param to specify a different
1458
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
1459
     *
1460
     * More on https://core.telegram.org/bots/api#sendgame
1461
     *
1462
     * @param string $game_short_name
1463
     * @param array|null $opt
1464
     * @return PromiseInterface
1465
     */
1466
    public function sendGame(string $game_short_name, ?array $opt = []): PromiseInterface
1467
    {
1468
        $opt = $this->resolveChatId($opt);
1469
        $required = compact("game_short_name");
1470
        $params = array_merge($required, $opt);
1471
        return $this->callApi("sendGame", $params, Message::class);
1472
    }
1473
1474
    /**
1475
     * Use this method to set the score of the specified user in a game. On success, if the message was sent by the bot,
1476
     * returns the edited @see Message, otherwise returns True. Returns an error, if the new score is not greater than the
1477
     * user's current score in the chat and force is False.
1478
     *
1479
     * By default the chat_id is taken from the context's update. Use $opt param to specify a different
1480
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
1481
     *
1482
     * By default the message_id is taken from the context's update. Use $opt param to specify a different
1483
     * message_id. Eg. $opt = ['message_id' => 123456789];
1484
     *
1485
     * By default the inline_message_id is taken from the context's update. Use $opt param to specify a different
1486
     * inline_message_id. Eg. $opt = ['inline_message_id' => 123456789];
1487
     *
1488
     * More on https://core.telegram.org/bots/api#setgamescore
1489
     *
1490
     * @param int $user_id
1491
     * @param int $score
1492
     * @param array|null $opt
1493
     * @return PromiseInterface
1494
     */
1495
    public function setGameScore(int $user_id, int $score, ?array $opt = []): PromiseInterface
1496
    {
1497
        $opt = $this->resolveMessageId($opt);
1498
        $required = compact("user_id", "score");
1499
        $params = array_merge($required, $opt);
1500
        return $this->callApi("setGameScore", $params, Message::class);
1501
    }
1502
1503
    /**
1504
     * Use this method to get data for high score tables. Will return the score of the specified user and several of his
1505
     * neighbors in a game. On success, returns an Array of @see GameHighScore objects.
1506
     *
1507
     * By default the chat_id is taken from the context's update. Use $opt param to specify a different
1508
     * chat_id. Eg. $opt = ['chat_id' => 123456789];
1509
     *
1510
     * By default the message_id is taken from the context's update. Use $opt param to specify a different
1511
     * message_id. Eg. $opt = ['message_id' => 123456789];
1512
     *
1513
     * By default the inline_message_id is taken from the context's update. Use $opt param to specify a different
1514
     * inline_message_id. Eg. $opt = ['inline_message_id' => 123456789];
1515
     *
1516
     * More on https://core.telegram.org/bots/api#getgamehighscores
1517
     *
1518
     * @param int $user_id
1519
     * @param array|null $opt
1520
     * @return PromiseInterface
1521
     */
1522
    public function getGameHighScores(int $user_id, ?array $opt = []): PromiseInterface
1523
    {
1524
        $opt = $this->resolveMessageId($opt);
1525
        $required = compact("user_id");
1526
        $params = array_merge($required, $opt);
1527
        return $this->callApi("getGameHighScores", $params, GameHighScore::class);
1528
    }
1529
1530
    /**
1531
     * @param string $method
1532
     * @param array $params
1533
     * @param string $class
1534
     * @param string[] $headers
1535
     * @return PromiseInterface
1536
     */
1537
    public function callApi(string $method, array $params = [], string $class = 'Scalar', $headers = ["Content-type" => "application/json"])
1538
    {
1539
        if ($this->container->get(Config::class)->getParseMode() && !isset($params['parse_mode'])) {
1540
            $params['parse_mode'] = $this->container->get(Config::class)->getParseMode();
1541
        }
1542
        foreach ($params as $param) {
1543
            if ($param instanceof InputFile) {
1544
1545
                $async = $this->container->get(Config::class)->isReactFileSystem();
1546
1547
                if ($async) {
1548
                    return $this->prepareMultipartDataAsync($params)->then(function ($result) use ($method) {
1549
                        $headers = array("Content-Length" => $result->getSize(), "Content-Type" => "multipart/form-data; boundary={$result->getBoundary()}");
1550
                        return $this->browser->post($method, $headers, $result);
1551
                    });
1552
                } else {
1553
                    $multipart = $this->prepareMultipartData($params);
1554
                    $headers = array("Content-Length" => $multipart->getSize(), "Content-Type" => "multipart/form-data; boundary={$multipart->getBoundary()}");
1555
                    return $this->browser->post($method, $headers, $multipart);
1556
                }
1557
            }
1558
        }
1559
        return $this->wrapPromise($this->browser->post($method, $headers, json_encode($params)), $method, $params, $class);
1560
    }
1561
1562
    /**
1563
     *
1564
     * Create MultipartStream, iterate over params to find InputFile
1565
     *
1566
     * @param $params
1567
     * @return PromiseInterface
1568
     */
1569
    private function prepareMultipartDataAsync($params)
1570
    {
1571
        $filesystem = $this->container->get(Filesystem::class);
1572
        $multipart_data = [];
1573
        $promises = [];
1574
        foreach ($params as $key => $value) {
1575
1576
            if ($value instanceof InputFile) {
1577
                array_push($promises, $filesystem->getContents($value->getPath())->then(function ($contents) use ($value, $multipart_data, $key) {
0 ignored issues
show
Unused Code introduced by
The import $multipart_data is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
1578
                    $data = ['name' => $key];
1579
                    $data['contents'] = $contents;
1580
                    $data['filename'] = basename($value->getPath());
1581
                    return $data;
1582
                }, function ($error) {
1583
                    $this->container->get(ZanzaraLogger::class)->error($error);
1584
                    return $error;
1585
                }));
1586
1587
            } else {
1588
                $data = ['name' => $key];
1589
                $data['contents'] = strval($value);
1590
                array_push($multipart_data, $data);
1591
            }
1592
        }
1593
1594
        return all($promises)->then(function ($files) use ($multipart_data) {
1595
            foreach ($files as $key => $value) {
1596
                array_push($multipart_data, $value);
1597
            }
1598
            return new MultipartStream($multipart_data);
1599
        }, function ($error) {
1600
            $this->container->get(ZanzaraLogger::class)->error($error);
1601
            return $error;
1602
        });
1603
    }
1604
1605
    private function prepareMultipartData($params)
1606
    {
1607
        $multipart_data = [];
1608
        foreach ($params as $key => $value) {
1609
            $data = ['name' => $key];
1610
            if ($value instanceof InputFile) {
1611
                if (file_exists($value->getPath())) {
1612
                    $fileData = file_get_contents($value->getPath());
1613
                    $data['contents'] = $fileData;
1614
                    $data['filename'] = basename($value->getPath());
1615
                } else {
1616
                    $this->container->get(ZanzaraLogger::class)->error("File not found: {$value->getPath()}");
1617
                }
1618
1619
            } else {
1620
                $data['contents'] = strval($value);
1621
            }
1622
            array_push($multipart_data, $data);
1623
        }
1624
        return new MultipartStream($multipart_data);
1625
    }
1626
1627
    /**
1628
     * ZanzaraPromise class was removed since it swallowed the promise chain.
1629
     * We actually have to call the original promise, get the response and propagate the casted response along
1630
     * the promise chain.
1631
     * For the rejected promise, we have to cast the original exception to a TelegramException and rethrow it
1632
     * in order to let the user receive the exception in his onRejected function.
1633
     *
1634
     * Unfortunately, we don't have control on user's callback input parameter anymore. In this way the user
1635
     * needs to manage the otherwise() promise callback to see the error.
1636
     *
1637
     * @param PromiseInterface $promise
1638
     * @param string $method
1639
     * @param array $params
1640
     * @param string $class
1641
     * @return PromiseInterface
1642
     */
1643
    private function wrapPromise(PromiseInterface $promise, string $method, array $params = [], string $class = "Scalar"): PromiseInterface
1644
    {
1645
        $mapper = $this->container->get(ZanzaraMapper::class);
1646
        $logger = $this->container->get(ZanzaraLogger::class);
1647
1648
        return $promise
1649
            ->then(function (ResponseInterface $response) use ($class, $mapper) {
1650
                $json = (string)$response->getBody();
1651
                $object = json_decode($json);
1652
1653
                if (is_scalar($object->result) && $class === "Scalar") {
1654
                    return $object->result;
1655
                }
1656
1657
                return $mapper->mapObject($object->result, $class);
1658
            }, function ($e) use ($method, $params, $logger, $mapper) {
1659
                if ($e instanceof ResponseException) {
1660
                    $json = (string)$e->getResponse()->getBody();
1661
                    $e = $mapper->mapJson($json, TelegramException::class);
1662
                }
1663
                $logger->errorTelegramApi($method, $params, $e);
1664
                throw $e;
1665
            });
1666
    }
1667
1668
    /**
1669
     * @param array|null $opt
1670
     * @return array|null
1671
     */
1672
    public function resolveMessageId(?array $opt): ?array
1673
    {
1674
        // if the user doesn't provide inline_message_id, chat_id or message_id the framework tries to resolve them
1675
        // based on the Update's type
1676
        if ($this->update) {
1677
            if (!isset($opt['inline_message_id']) && !isset($opt['chat_id']) && !isset($opt['message_id'])) {
1678
                if ($this->update->getUpdateType() == CallbackQuery::class) {
0 ignored issues
show
Bug introduced by
The type Zanzara\Telegram\CallbackQuery 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...
1679
                    $cbQuery = $this->update->getCallbackQuery();
1680
                    if ($cbQuery->getInlineMessageId()) {
1681
                        $opt['inline_message_id'] = $cbQuery->getInlineMessageId();
1682
                    } else if ($cbQuery->getMessage()) {
1683
                        $opt['message_id'] = $cbQuery->getMessage()->getMessageId();
1684
                    }
1685
                }
1686
                // set chat_id only if inline_message_id wasn't set
1687
                if (!isset($opt['inline_message_id']) && $this->update->getEffectiveChat()) {
1688
                    $opt['chat_id'] = $this->update->getEffectiveChat()->getId();
1689
                }
1690
            }
1691
        }
1692
        return $opt;
1693
    }
1694
1695
    /**
1696
     * @param array|null $opt
1697
     * @return array|null
1698
     */
1699
    public function resolveChatId(?array $opt): ?array
1700
    {
1701
        if (!isset($opt['chat_id']) && $this->update) {
1702
            $opt['chat_id'] = $this->update->getEffectiveChat()->getId();
1703
        }
1704
        return $opt;
1705
    }
1706
1707
}