From 9fdaa0556246e2cba3b14cfd0a58cab82cf85c05 Mon Sep 17 00:00:00 2001 From: Tii Date: Sun, 17 Apr 2022 12:15:42 +0200 Subject: [PATCH 01/16] Added the class WebAppInfo and the fields web_app to the classes KeyboardButton and InlineKeyboardButton. --- src/Entities/Factory.php | 6 +++-- src/Entities/InlineKeyboardButton.php | 13 ++++++---- src/Entities/KeyboardButton.php | 28 +++++++++++++++------- src/Entities/WebAppInfo.php | 19 +++++++++++++++ tests/Unit/Entities/KeyboardButtonTest.php | 14 ++++++++++- 5 files changed, 64 insertions(+), 16 deletions(-) create mode 100644 src/Entities/WebAppInfo.php diff --git a/src/Entities/Factory.php b/src/Entities/Factory.php index 60b085560..d2d05eaa6 100644 --- a/src/Entities/Factory.php +++ b/src/Entities/Factory.php @@ -6,9 +6,11 @@ abstract class Factory { abstract public static function make(array $data, string $bot_username): Entity; - public static function resolveEntityClass(string $class, array $property, string $bot_username = ''): Entity + public static function resolveEntityClass(string $class, mixed $property, string $bot_username = ''): Entity { - if (is_subclass_of($class, Factory::class)) { + if (is_a($property, $class)) { + return $property; + } elseif (is_subclass_of($class, Factory::class)) { return $class::make($property, $bot_username); } diff --git a/src/Entities/InlineKeyboardButton.php b/src/Entities/InlineKeyboardButton.php index 2d7ca7f5a..cf604838a 100644 --- a/src/Entities/InlineKeyboardButton.php +++ b/src/Entities/InlineKeyboardButton.php @@ -23,6 +23,7 @@ * @method string getUrl() Optional. HTTP url to be opened when button is pressed * @method LoginUrl getLoginUrl() Optional. An HTTP URL used to automatically authorize the user. Can be used as a replacement for the Telegram Login Widget. * @method string getCallbackData() Optional. Data to be sent in a callback query to the bot when button is pressed, 1-64 bytes + * @method WebAppInfo getWebApp() Optional. Description of the Web App that will be launched when the user presses the button. The Web App will be able to send an arbitrary message on behalf of the user using the method answerWebAppQuery. Available only in private chats between a user and the bot. * @method string getSwitchInlineQuery() Optional. If set, pressing the button will prompt the user to select one of their chats, open that chat and insert the bot's username and the specified inline query in the input field. Can be empty, in which case just the bot’s username will be inserted. * @method string getSwitchInlineQueryCurrentChat() Optional. If set, pressing the button will insert the bot‘s username and the specified inline query in the current chat's input field. Can be empty, in which case only the bot’s username will be inserted. * @method CallbackGame getCallbackGame() Optional. Description of the game that will be launched when the user presses the button. @@ -30,8 +31,9 @@ * * @method $this setText(string $text) Label text on the button * @method $this setUrl(string $url) Optional. HTTP url to be opened when button is pressed - * @method $this setLoginUrl(LoginUrl $login_url) Optional. HTTP url to be opened when button is pressed + * @method $this setLoginUrl(LoginUrl $login_url) Optional. HTTP url to be opened when button is pressed * @method $this setCallbackData(string $callback_data) Optional. Data to be sent in a callback query to the bot when button is pressed, 1-64 bytes + * @method $this setWebApp(WebAppInfo $web_app) Optional. Description of the Web App that will be launched when the user presses the button. The Web App will be able to send an arbitrary message on behalf of the user using the method answerWebAppQuery. Available only in private chats between a user and the bot. * @method $this setSwitchInlineQuery(string $switch_inline_query) Optional. If set, pressing the button will prompt the user to select one of their chats, open that chat and insert the bot's username and the specified inline query in the input field. Can be empty, in which case just the bot’s username will be inserted. * @method $this setSwitchInlineQueryCurrentChat(string $switch_inline_query_current_chat) Optional. If set, pressing the button will insert the bot‘s username and the specified inline query in the current chat's input field. Can be empty, in which case only the bot’s username will be inserted. * @method $this setCallbackGame(CallbackGame $callback_game) Optional. Description of the game that will be launched when the user presses the button. @@ -52,6 +54,7 @@ public static function couldBe(array $data): bool array_key_exists('url', $data) || array_key_exists('login_url', $data) || array_key_exists('callback_data', $data) || + array_key_exists('web_app', $data) || array_key_exists('switch_inline_query', $data) || array_key_exists('switch_inline_query_current_chat', $data) || array_key_exists('callback_game', $data) || @@ -70,7 +73,7 @@ protected function validate(): void $num_params = 0; - foreach (['url', 'login_url', 'callback_data', 'callback_game', 'pay'] as $param) { + foreach (['url', 'login_url', 'callback_data', 'web_app', 'callback_game', 'pay'] as $param) { if ($this->getProperty($param, '') !== '') { $num_params++; } @@ -83,7 +86,7 @@ protected function validate(): void } if ($num_params !== 1) { - throw new TelegramException('You must use only one of these fields: url, login_url, callback_data, switch_inline_query, switch_inline_query_current_chat, callback_game, pay!'); + throw new TelegramException('You must use only one of these fields: url, login_url, callback_data, web_app, switch_inline_query, switch_inline_query_current_chat, callback_game, pay!'); } } @@ -93,8 +96,8 @@ protected function validate(): void public function __call($method, $args) { // Only 1 of these can be set, so clear the others when setting a new one. - if (in_array($method, ['setUrl', 'setLoginUrl', 'setCallbackData', 'setSwitchInlineQuery', 'setSwitchInlineQueryCurrentChat', 'setCallbackGame', 'setPay'], true)) { - unset($this->url, $this->login_url, $this->callback_data, $this->switch_inline_query, $this->switch_inline_query_current_chat, $this->callback_game, $this->pay); + if (in_array($method, ['setUrl', 'setLoginUrl', 'setCallbackData', 'setWebApp', 'setSwitchInlineQuery', 'setSwitchInlineQueryCurrentChat', 'setCallbackGame', 'setPay'], true)) { + unset($this->url, $this->login_url, $this->callback_data, $this->web_app, $this->switch_inline_query, $this->switch_inline_query_current_chat, $this->callback_game, $this->pay); } return parent::__call($method, $args); diff --git a/src/Entities/KeyboardButton.php b/src/Entities/KeyboardButton.php index 17b135998..f2a967043 100644 --- a/src/Entities/KeyboardButton.php +++ b/src/Entities/KeyboardButton.php @@ -20,24 +20,27 @@ * * @link https://core.telegram.org/bots/api#keyboardbutton * - * @property bool $request_contact - * @property bool $request_location + * @property bool $request_contact + * @property bool $request_location * @property KeyboardButtonPollType $request_poll + * @property WebAppInfo $web_app * * @method string getText() Text of the button. If none of the optional fields are used, it will be sent to the bot as a message when the button is pressed * @method bool getRequestContact() Optional. If True, the user's phone number will be sent as a contact when the button is pressed. Available in private chats only * @method bool getRequestLocation() Optional. If True, the user's current location will be sent when the button is pressed. Available in private chats only - * @method KeyboardButtonPollType getRequestPoll() Optional. If specified, the user will be asked to create a poll and send it to the bot when the button is pressed. Available in private chats only + * @method KeyboardButtonPollType getRequestPoll() Optional. If specified, the user will be asked to create a poll and send it to the bot when the button is pressed. Available in private chats only + * @method WebAppInfo getWebApp() Optional. If specified, the described Web App will be launched when the button is pressed. The Web App will be able to send a “web_app_data” service message. Available in private chats only. * * @method $this setText(string $text) Text of the button. If none of the optional fields are used, it will be sent to the bot as a message when the button is pressed * @method $this setRequestContact(bool $request_contact) Optional. If True, the user's phone number will be sent as a contact when the button is pressed. Available in private chats only * @method $this setRequestLocation(bool $request_location) Optional. If True, the user's current location will be sent when the button is pressed. Available in private chats only * @method $this setRequestPoll(KeyboardButtonPollType $request_poll) Optional. If specified, the user will be asked to create a poll and send it to the bot when the button is pressed. Available in private chats only + * @method $this setWebApp(WebAppInfo $web_app) Optional. If specified, the described Web App will be launched when the button is pressed. The Web App will be able to send a “web_app_data” service message. Available in private chats only. */ class KeyboardButton extends Entity { /** - * @param array|string $data + * @param array|string $data */ public function __construct($data) { @@ -47,10 +50,18 @@ public function __construct($data) parent::__construct($data); } + protected function subEntities(): array + { + return [ + 'request_poll' => KeyboardButtonPollType::class, + 'web_app' => WebAppInfo::class, + ]; + } + /** * Check if the passed data array could be a KeyboardButton. * - * @param array $data + * @param array $data * * @return bool */ @@ -73,9 +84,10 @@ protected function validate(): void $this->getRequestContact(), $this->getRequestLocation(), $this->getRequestPoll(), + $this->getWebApp(), ]); if (count($field_count) > 1) { - throw new TelegramException('You must use only one of these fields: request_contact, request_location, request_poll!'); + throw new TelegramException('You must use only one of these fields: request_contact, request_location, request_poll, web_app!'); } } @@ -85,8 +97,8 @@ protected function validate(): void public function __call($method, $args) { // Only 1 of these can be set, so clear the others when setting a new one. - if (in_array($method, ['setRequestContact', 'setRequestLocation', 'setRequestPoll'], true)) { - unset($this->request_contact, $this->request_location, $this->request_poll); + if (in_array($method, ['setRequestContact', 'setRequestLocation', 'setRequestPoll', 'setWebApp'], true)) { + unset($this->request_contact, $this->request_location, $this->request_poll, $this->web_app); } return parent::__call($method, $args); diff --git a/src/Entities/WebAppInfo.php b/src/Entities/WebAppInfo.php new file mode 100644 index 000000000..922774312 --- /dev/null +++ b/src/Entities/WebAppInfo.php @@ -0,0 +1,19 @@ +expectException(TelegramException::class); - $this->expectExceptionMessage('You must use only one of these fields: request_contact, request_location, request_poll!'); + $this->expectExceptionMessage('You must use only one of these fields: request_contact, request_location, request_poll, web_app!'); new KeyboardButton(['text' => 'message', 'request_contact' => true, 'request_location' => true]); } @@ -45,6 +46,7 @@ public function testKeyboardButtonSuccess(): void new KeyboardButton(['text' => 'message', 'request_contact' => true]); new KeyboardButton(['text' => 'message', 'request_location' => true]); new KeyboardButton(['text' => 'message', 'request_poll' => new KeyboardButtonPollType([])]); + new KeyboardButton(['text' => 'message', 'web_app' => new WebAppInfo([])]); self::assertTrue(true); } @@ -61,6 +63,7 @@ public function testKeyboardButtonParameterSetting(): void self::assertEmpty($button->getRequestContact()); self::assertEmpty($button->getRequestLocation()); self::assertEmpty($button->getRequestPoll()); + self::assertEmpty($button->getWebApp()); $button->setText('new message'); self::assertSame('new message', $button->getText()); @@ -69,15 +72,24 @@ public function testKeyboardButtonParameterSetting(): void self::assertTrue($button->getRequestContact()); self::assertEmpty($button->getRequestLocation()); self::assertEmpty($button->getRequestPoll()); + self::assertEmpty($button->getWebApp()); $button->setRequestLocation(true); self::assertEmpty($button->getRequestContact()); self::assertTrue($button->getRequestLocation()); self::assertEmpty($button->getRequestPoll()); + self::assertEmpty($button->getWebApp()); $button->setRequestPoll(new KeyboardButtonPollType([])); self::assertEmpty($button->getRequestContact()); self::assertEmpty($button->getRequestLocation()); self::assertInstanceOf(KeyboardButtonPollType::class, $button->getRequestPoll()); + self::assertEmpty($button->getWebApp()); + + $button->setWebApp(new WebAppInfo([])); + self::assertEmpty($button->getRequestContact()); + self::assertEmpty($button->getRequestLocation()); + self::assertEmpty($button->getRequestPoll()); + self::assertInstanceOf(WebAppInfo::class, $button->getWebApp()); } } From 406b72bc83f2d7a6a78de658bf7932509fb17bc3 Mon Sep 17 00:00:00 2001 From: Tii Date: Sun, 17 Apr 2022 12:26:35 +0200 Subject: [PATCH 02/16] Added test for returning subentities on arrays --- tests/Unit/Entities/KeyboardButtonTest.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/Unit/Entities/KeyboardButtonTest.php b/tests/Unit/Entities/KeyboardButtonTest.php index 88e9c5989..1197c7398 100644 --- a/tests/Unit/Entities/KeyboardButtonTest.php +++ b/tests/Unit/Entities/KeyboardButtonTest.php @@ -92,4 +92,14 @@ public function testKeyboardButtonParameterSetting(): void self::assertEmpty($button->getRequestPoll()); self::assertInstanceOf(WebAppInfo::class, $button->getWebApp()); } + + public function testReturnsSubentitiesOnArray() + { + $button = new KeyboardButton('message'); + $button->request_poll = []; + $this->assertInstanceOf(KeyboardButtonPollType::class, $button->getRequestPoll()); + + $button->web_app = []; + $this->assertInstanceOf(WebAppInfo::class, $button->getWebApp()); + } } From 7ca60aaac3a5b40bb2aeed4a10ccdb3e8bbc47ce Mon Sep 17 00:00:00 2001 From: Tii Date: Sun, 17 Apr 2022 12:39:00 +0200 Subject: [PATCH 03/16] Added the class SentWebAppMessage and the method answerWebAppQuery for sending an answer to a Web App query, which originated from an inline button of the 'web_app' type. --- src/Entities/SentWebAppMessage.php | 20 ++++++++++++++++++++ src/Request.php | 2 ++ 2 files changed, 22 insertions(+) create mode 100644 src/Entities/SentWebAppMessage.php diff --git a/src/Entities/SentWebAppMessage.php b/src/Entities/SentWebAppMessage.php new file mode 100644 index 000000000..27359b1a0 --- /dev/null +++ b/src/Entities/SentWebAppMessage.php @@ -0,0 +1,20 @@ + Date: Sun, 17 Apr 2022 12:46:03 +0200 Subject: [PATCH 04/16] Added the class WebAppData and the field web_app_data to the class Message. --- src/Entities/Message.php | 9 ++++++--- src/Entities/WebAppData.php | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 src/Entities/WebAppData.php diff --git a/src/Entities/Message.php b/src/Entities/Message.php index 4c86d660b..494b40476 100644 --- a/src/Entities/Message.php +++ b/src/Entities/Message.php @@ -79,6 +79,7 @@ * @method VoiceChatStarted getVoiceChatStarted() Optional. Service message: voice chat started * @method VoiceChatEnded getVoiceChatEnded() Optional. Service message: voice chat ended * @method VoiceChatParticipantsInvited getVoiceChatParticipantsInvited() Optional. Service message: new participants invited to a voice chat + * @method WebAppData getWebAppData() Optional. Service message: data sent by a Web App * @method InlineKeyboard getReplyMarkup() Optional. Inline keyboard attached to the message. login_url buttons are represented as ordinary url buttons. */ class Message extends Entity @@ -125,6 +126,7 @@ protected function subEntities(): array 'voice_chat_started' => VoiceChatStarted::class, 'voice_chat_ended' => VoiceChatEnded::class, 'voice_chat_participants_invited' => VoiceChatParticipantsInvited::class, + 'web_app_data' => WebAppData::class, 'reply_markup' => InlineKeyboard::class, ]; } @@ -141,7 +143,7 @@ public function getFullCommand(): ?string return null; } - $no_EOL = strtok($text, PHP_EOL); + $no_EOL = strtok($text, PHP_EOL); $no_space = strtok($text, ' '); //try to understand which separator \n or space divide /command from text @@ -167,7 +169,7 @@ public function getCommand(): ?string //check if command is followed by bot username $split_cmd = explode('@', $full_command); - if (!isset($split_cmd[1])) { + if (! isset($split_cmd[1])) { //command is not followed by name return $full_command; } @@ -183,7 +185,7 @@ public function getCommand(): ?string /** * For text messages, the actual UTF-8 text of the message, 0-4096 characters. * - * @param bool $without_cmd + * @param bool $without_cmd * * @return string|null */ @@ -260,6 +262,7 @@ public function getType(): string 'voice_chat_started', 'voice_chat_ended', 'voice_chat_participants_invited', + 'web_app_data', 'reply_markup', ]; diff --git a/src/Entities/WebAppData.php b/src/Entities/WebAppData.php new file mode 100644 index 000000000..e23ec53c8 --- /dev/null +++ b/src/Entities/WebAppData.php @@ -0,0 +1,21 @@ + Date: Sun, 17 Apr 2022 13:00:11 +0200 Subject: [PATCH 05/16] Added the class MenuButton and the methods setChatMenuButton and getChatMenuButton for managing the behavior of the bot's menu button in private chats. --- src/Entities/MenuButton/MenuButton.php | 10 ++ .../MenuButton/MenuButtonCommands.php | 15 ++ src/Entities/MenuButton/MenuButtonDefault.php | 15 ++ src/Entities/MenuButton/MenuButtonWebApp.php | 32 ++++ src/Request.php | 140 +++++++++--------- 5 files changed, 146 insertions(+), 66 deletions(-) create mode 100644 src/Entities/MenuButton/MenuButton.php create mode 100644 src/Entities/MenuButton/MenuButtonCommands.php create mode 100644 src/Entities/MenuButton/MenuButtonDefault.php create mode 100644 src/Entities/MenuButton/MenuButtonWebApp.php diff --git a/src/Entities/MenuButton/MenuButton.php b/src/Entities/MenuButton/MenuButton.php new file mode 100644 index 000000000..182831930 --- /dev/null +++ b/src/Entities/MenuButton/MenuButton.php @@ -0,0 +1,10 @@ + WebAppInfo::class, + ]; + } + + +} diff --git a/src/Request.php b/src/Request.php index 89b07e737..326891244 100644 --- a/src/Request.php +++ b/src/Request.php @@ -86,7 +86,9 @@ * @method static ServerResponse answerInlineQuery(array $data) Use this method to send answers to an inline query. On success, True is returned. * @method static ServerResponse setMyCommands(array $data) Use this method to change the list of the bot's commands. Returns True on success. * @method static ServerResponse deleteMyCommands(array $data) Use this method to delete the list of the bot's commands for the given scope and user language. After deletion, higher level commands will be shown to affected users. Returns True on success. - * @method static ServerResponse getMyCommands() Use this method to get the current list of the bot's commands. Requires no parameters. Returns Array of BotCommand on success. + * @method static ServerResponse getMyCommands(array $data) Use this method to get the current list of the bot's commands. Requires no parameters. Returns Array of BotCommand on success. + * @method static ServerResponse setChatMenuButton(array $data) Use this method to change the bot's menu button in a private chat, or the default menu button. Returns True on success. + * @method static ServerResponse getChatMenuButton(array $data) Use this method to get the current value of the bot's menu button in a private chat, or the default menu button. Returns MenuButton on success. * @method static ServerResponse editMessageText(array $data) Use this method to edit text and game messages sent by the bot or via the bot (for inline bots). On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. * @method static ServerResponse editMessageCaption(array $data) Use this method to edit captions of messages sent by the bot or via the bot (for inline bots). On success, if edited message is sent by the bot, the edited Message is returned, otherwise True is returned. * @method static ServerResponse editMessageMedia(array $data) Use this method to edit audio, document, photo, or video messages. On success, if the edited message was sent by the bot, the edited Message is returned, otherwise True is returned. @@ -232,6 +234,8 @@ class Request 'setMyCommands', 'deleteMyCommands', 'getMyCommands', + 'setChatMenuButton', + 'getChatMenuButton', 'editMessageText', 'editMessageCaption', 'editMessageMedia', @@ -268,7 +272,10 @@ class Request 'getMe', 'logOut', 'close', + 'deleteMyCommands', 'getMyCommands', + 'setChatMenuButton', + 'getChatMenuButton', ]; /** @@ -299,7 +306,7 @@ class Request /** * Initialize * - * @param Telegram $telegram + * @param Telegram $telegram */ public static function initialize(Telegram $telegram): void { @@ -310,7 +317,7 @@ public static function initialize(Telegram $telegram): void /** * Set a custom Guzzle HTTP Client object * - * @param ClientInterface $client + * @param ClientInterface $client */ public static function setClient(ClientInterface $client): void { @@ -320,8 +327,8 @@ public static function setClient(ClientInterface $client): void /** * Set a custom Bot API URL * - * @param string $api_base_uri - * @param string $api_base_download_uri + * @param string $api_base_uri + * @param string $api_base_download_uri */ public static function setCustomBotApiUri(string $api_base_uri, string $api_base_download_uri = ''): void { @@ -346,7 +353,7 @@ public static function getInput(): string /** * Generate general fake server response * - * @param array $data Data to add to fake response + * @param array $data Data to add to fake response * * @return array Fake response data */ @@ -367,13 +374,13 @@ public static function generateGeneralFakeServerResponse(array $data = []): arra //some data to initialize the class method SendMessage if (isset($data['chat_id'])) { $data['message_id'] = '1234'; - $data['date'] = '1441378360'; - $data['from'] = [ + $data['date'] = '1441378360'; + $data['from'] = [ 'id' => 123456789, 'first_name' => 'botname', 'username' => 'namebot', ]; - $data['chat'] = ['id' => $data['chat_id']]; + $data['chat'] = ['id' => $data['chat_id']]; $fake_response['result'] = $data; } @@ -387,7 +394,7 @@ public static function generateGeneralFakeServerResponse(array $data = []): arra * If any item of the array is a resource, reformat it to a multipart request. * Else, just return the passed data as form params. * - * @param array $data + * @param array $data * * @return array * @throws TelegramException @@ -395,13 +402,14 @@ public static function generateGeneralFakeServerResponse(array $data = []): arra private static function setUpRequestParams(array $data): array { $has_resource = false; - $multipart = []; + $multipart = []; foreach ($data as $key => &$item) { if ($key === 'media') { // Magical media input helper. $item = self::mediaInputHelper($item, $has_resource, $multipart); - } elseif (array_key_exists(self::$current_action, self::$input_file_fields) && in_array($key, self::$input_file_fields[self::$current_action], true)) { + } elseif (array_key_exists(self::$current_action, self::$input_file_fields) && in_array($key, + self::$input_file_fields[self::$current_action], true)) { // Allow absolute paths to local files. if (is_string($item) && file_exists($item)) { $item = new Stream(self::encodeFile($item)); @@ -413,7 +421,7 @@ private static function setUpRequestParams(array $data): array // Reformat data array in multipart way if it contains a resource $has_resource = $has_resource || is_resource($item) || $item instanceof Stream; - $multipart[] = ['name' => $key, 'contents' => $item]; + $multipart[] = ['name' => $key, 'contents' => $item]; } unset($item); @@ -452,9 +460,9 @@ private static function setUpRequestParams(array $data): array * ], * ]); * - * @param mixed $item - * @param bool $has_resource - * @param array $multipart + * @param mixed $item + * @param bool $has_resource + * @param array $multipart * * @return mixed * @throws TelegramException @@ -466,7 +474,7 @@ private static function mediaInputHelper($item, bool &$has_resource, array &$mul /** @var InputMedia|null $media_item */ foreach ($item as $media_item) { - if (!($media_item instanceof InputMedia)) { + if (! ($media_item instanceof InputMedia)) { continue; } @@ -484,11 +492,11 @@ private static function mediaInputHelper($item, bool &$has_resource, array &$mul if (is_resource($media) || $media instanceof Stream) { $has_resource = true; - $unique_key = uniqid($type . '_', false); - $multipart[] = ['name' => $unique_key, 'contents' => $media]; + $unique_key = uniqid($type . '_', false); + $multipart[] = ['name' => $unique_key, 'contents' => $media]; // We're literally overwriting the passed media type data! - $media_item->$type = 'attach://' . $unique_key; + $media_item->$type = 'attach://' . $unique_key; $media_item->raw_data[$type] = 'attach://' . $unique_key; } } @@ -512,15 +520,15 @@ public static function getCurrentAction(): string /** * Execute HTTP Request * - * @param string $action Action to execute - * @param array $data Data to attach to the execution + * @param string $action Action to execute + * @param array $data Data to attach to the execution * * @return string Result of the HTTP Request * @throws TelegramException */ public static function execute(string $action, array $data = []): string { - $request_params = self::setUpRequestParams($data); + $request_params = self::setUpRequestParams($data); $request_params['debug'] = TelegramLog::getDebugLogTempStream(); try { @@ -528,10 +536,10 @@ public static function execute(string $action, array $data = []): string '/bot' . self::$telegram->getApiKey() . '/' . $action, $request_params ); - $result = (string) $response->getBody(); + $result = (string) $response->getBody(); } catch (RequestException $e) { $response = null; - $result = $e->getResponse() ? (string) $e->getResponse()->getBody() : ''; + $result = $e->getResponse() ? (string) $e->getResponse()->getBody() : ''; } //Logging verbose debug output @@ -547,7 +555,7 @@ public static function execute(string $action, array $data = []): string /** * Download file * - * @param File $file + * @param File $file * * @return bool * @throws TelegramException @@ -559,12 +567,12 @@ public static function downloadFile(File $file): bool } $tg_file_path = $file->getFilePath(); - $file_path = $download_path . '/' . $tg_file_path; + $file_path = $download_path . '/' . $tg_file_path; $file_dir = dirname($file_path); //For safety reasons, first try to create the directory, then check that it exists. //This is in case some other process has created the folder in the meantime. - if (!@mkdir($file_dir, 0755, true) && !is_dir($file_dir)) { + if (! @mkdir($file_dir, 0755, true) && ! is_dir($file_dir)) { throw new TelegramException('Directory ' . $file_dir . ' can\'t be created'); } @@ -589,7 +597,7 @@ public static function downloadFile(File $file): bool /** * Encode file * - * @param string $file + * @param string $file * * @return resource * @throws TelegramException @@ -610,8 +618,8 @@ public static function encodeFile(string $file) * @todo Fake response doesn't need json encoding? * @todo Write debug entry on failure * - * @param string $action - * @param array $data + * @param string $action + * @param array $data * * @return ServerResponse * @throws TelegramException @@ -637,7 +645,7 @@ public static function send(string $action, array $data = []): ServerResponse self::$current_action = $action; $raw_response = self::execute($action, $data); - $response = json_decode($raw_response, true); + $response = json_decode($raw_response, true); if (null === $response) { TelegramLog::debug($raw_response); @@ -646,7 +654,7 @@ public static function send(string $action, array $data = []): ServerResponse $response = new ServerResponse($response, $bot_username); - if (!$response->isOk() && $response->getErrorCode() === 401 && $response->getDescription() === 'Unauthorized') { + if (! $response->isOk() && $response->getErrorCode() === 401 && $response->getDescription() === 'Unauthorized') { throw new InvalidBotTokenException(); } @@ -672,8 +680,8 @@ public static function send(string $action, array $data = []): ServerResponse * * @todo Would be nice to find a better solution for this! * - * @param string $action - * @param array $data + * @param string $action + * @param array $data */ protected static function addDummyParamIfNecessary(string $action, array &$data): void { @@ -686,7 +694,7 @@ protected static function addDummyParamIfNecessary(string $action, array &$data) /** * Make sure the data isn't empty, else throw an exception * - * @param array $data + * @param array $data * * @throws TelegramException */ @@ -700,13 +708,13 @@ private static function ensureNonEmptyData(array $data): void /** * Make sure the action is valid, else throw an exception * - * @param string $action + * @param string $action * * @throws TelegramException */ private static function ensureValidAction(string $action): void { - if (!in_array($action, self::$actions, true)) { + if (! in_array($action, self::$actions, true)) { throw new TelegramException('The action "' . $action . '" doesn\'t exist!'); } } @@ -724,8 +732,8 @@ private static function ensureValidAction(string $action): void * * @todo Splitting formatted text may break the message. * - * @param array $data - * @param array|null $extras + * @param array $data + * @param array|null $extras * * @return ServerResponse * @throws TelegramException @@ -737,8 +745,8 @@ public static function sendMessage(array $data, ?array &$extras = []): ServerRes 'encoding' => mb_internal_encoding(), ], (array) $extras); - $text = $data['text']; - $encoding = $extras['encoding']; + $text = $data['text']; + $encoding = $extras['encoding']; $max_length = $extras['split'] ?: mb_strlen($text, $encoding); $responses = []; @@ -746,7 +754,7 @@ public static function sendMessage(array $data, ?array &$extras = []): ServerRes do { // Chop off and send the first message. $data['text'] = mb_substr($text, 0, $max_length, $encoding); - $responses[] = self::send('sendMessage', $data); + $responses[] = self::send('sendMessage', $data); // Prepare the next message. $text = mb_substr($text, $max_length, null, $encoding); @@ -761,8 +769,8 @@ public static function sendMessage(array $data, ?array &$extras = []): ServerRes /** * Any statically called method should be relayed to the `send` method. * - * @param string $action - * @param array $data + * @param string $action + * @param array $data * * @return ServerResponse * @throws TelegramException @@ -789,9 +797,9 @@ public static function emptyResponse(): ServerResponse /** * Send message to all active chats * - * @param string $callback_function - * @param array $data - * @param array $select_chats_params + * @param string $callback_function + * @param array $data + * @param array $select_chats_params * * @return array * @throws TelegramException @@ -809,7 +817,7 @@ public static function sendToActiveChats( if (is_array($chats)) { foreach ($chats as $row) { $data['chat_id'] = $row['chat_id']; - $results[] = self::send($callback_function, $data); + $results[] = self::send($callback_function, $data); } } @@ -819,8 +827,8 @@ public static function sendToActiveChats( /** * Enable request limiter * - * @param bool $enable - * @param array $options + * @param bool $enable + * @param array $options * * @throws TelegramException */ @@ -833,12 +841,12 @@ public static function setLimiter(bool $enable = true, array $options = []): voi $options = array_merge($options_default, $options); - if (!is_numeric($options['interval']) || $options['interval'] <= 0) { + if (! is_numeric($options['interval']) || $options['interval'] <= 0) { throw new TelegramException('Interval must be a number and must be greater than zero!'); } self::$limiter_interval = $options['interval']; - self::$limiter_enabled = $enable; + self::$limiter_enabled = $enable; } } @@ -848,8 +856,8 @@ public static function setLimiter(bool $enable = true, array $options = []): voi * * @link https://core.telegram.org/bots/faq#my-bot-is-hitting-limits-how-do-i-avoid-this * - * @param string $action - * @param array $data + * @param string $action + * @param array $data * * @throws TelegramException */ @@ -893,7 +901,7 @@ private static function limitTelegramRequests(string $action, array $data = []): 'setPassportDataErrors', ]; - $chat_id = $data['chat_id'] ?? null; + $chat_id = $data['chat_id'] ?? null; $inline_message_id = $data['inline_message_id'] ?? null; if (($chat_id || $inline_message_id) && in_array($action, $limited_methods, true)) { @@ -904,16 +912,16 @@ private static function limitTelegramRequests(string $action, array $data = []): throw new TelegramException('Timed out while waiting for a request spot!'); } - if (!($requests = DB::getTelegramRequestCount($chat_id, $inline_message_id))) { + if (! ($requests = DB::getTelegramRequestCount($chat_id, $inline_message_id))) { break; } // Make sure we're handling integers here. $requests = array_map('intval', $requests); - $chat_per_second = ($requests['LIMIT_PER_SEC'] === 0); // No more than one message per second inside a particular chat - $global_per_second = ($requests['LIMIT_PER_SEC_ALL'] < 30); // No more than 30 messages per second to different chats - $groups_per_minute = (((is_numeric($chat_id) && $chat_id > 0) || $inline_message_id !== null) || ((!is_numeric($chat_id) || $chat_id < 0) && $requests['LIMIT_PER_MINUTE'] < 20)); // No more than 20 messages per minute in groups and channels + $chat_per_second = ($requests['LIMIT_PER_SEC'] === 0); // No more than one message per second inside a particular chat + $global_per_second = ($requests['LIMIT_PER_SEC_ALL'] < 30); // No more than 30 messages per second to different chats + $groups_per_minute = (((is_numeric($chat_id) && $chat_id > 0) || $inline_message_id !== null) || ((! is_numeric($chat_id) || $chat_id < 0) && $requests['LIMIT_PER_MINUTE'] < 20)); // No more than 20 messages per minute in groups and channels if ($chat_per_second && $global_per_second && $groups_per_minute) { break; @@ -931,12 +939,12 @@ private static function limitTelegramRequests(string $action, array $data = []): /** * Use this method to kick a user from a group, a supergroup or a channel. In the case of supergroups and channels, the user will not be able to return to the group on their own using invite links, etc., unless unbanned first. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success. * + * @param array $data + * + * @return ServerResponse * @deprecated * @see Request::banChatMember() * - * @param array $data - * - * @return ServerResponse */ public static function kickChatMember(array $data = []): ServerResponse { @@ -946,12 +954,12 @@ public static function kickChatMember(array $data = []): ServerResponse /** * Use this method to get the number of members in a chat. Returns Int on success. * + * @param array $data + * + * @return ServerResponse * @deprecated * @see Request::getChatMemberCount() * - * @param array $data - * - * @return ServerResponse */ public static function getChatMembersCount(array $data = []): ServerResponse { From 44ab57242e16a58a4eee73ab77197b7520eb583b Mon Sep 17 00:00:00 2001 From: Tii Date: Sun, 17 Apr 2022 13:02:21 +0200 Subject: [PATCH 06/16] Fixed Tests for InlineKeyboardButton since we changed the exception message --- tests/Unit/Entities/InlineKeyboardButtonTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Unit/Entities/InlineKeyboardButtonTest.php b/tests/Unit/Entities/InlineKeyboardButtonTest.php index f72a68b32..6f6355022 100644 --- a/tests/Unit/Entities/InlineKeyboardButtonTest.php +++ b/tests/Unit/Entities/InlineKeyboardButtonTest.php @@ -35,14 +35,14 @@ public function testInlineKeyboardButtonNoTextFail(): void public function testInlineKeyboardButtonNoParameterFail(): void { $this->expectException(TelegramException::class); - $this->expectExceptionMessage('You must use only one of these fields: url, login_url, callback_data, switch_inline_query, switch_inline_query_current_chat, callback_game, pay!'); + $this->expectExceptionMessage('You must use only one of these fields: url, login_url, callback_data, web_app, switch_inline_query, switch_inline_query_current_chat, callback_game, pay!'); new InlineKeyboardButton(['text' => 'message']); } public function testInlineKeyboardButtonTooManyParametersFail(): void { $this->expectException(TelegramException::class); - $this->expectExceptionMessage('You must use only one of these fields: url, login_url, callback_data, switch_inline_query, switch_inline_query_current_chat, callback_game, pay!'); + $this->expectExceptionMessage('You must use only one of these fields: url, login_url, callback_data, web_app, switch_inline_query, switch_inline_query_current_chat, callback_game, pay!'); $test_funcs = [ function () { new InlineKeyboardButton([ From 7c22f26d7c04d53006f511cf7c8b5a9af63d84fb Mon Sep 17 00:00:00 2001 From: Tii Date: Sun, 17 Apr 2022 19:20:38 +0200 Subject: [PATCH 07/16] Added the class ChatAdministratorRights and the methods setMyDefaultAdministratorRights and getMyDefaultAdministratorRights for managing the bot's default administrator rights. --- src/Entities/ChatAdministratorRights.php | 35 ++++++++++++++++++++++++ src/Request.php | 6 ++++ 2 files changed, 41 insertions(+) create mode 100644 src/Entities/ChatAdministratorRights.php diff --git a/src/Entities/ChatAdministratorRights.php b/src/Entities/ChatAdministratorRights.php new file mode 100644 index 000000000..eaae81650 --- /dev/null +++ b/src/Entities/ChatAdministratorRights.php @@ -0,0 +1,35 @@ + Date: Sun, 17 Apr 2022 19:24:22 +0200 Subject: [PATCH 08/16] Added the field last_synchronization_error_date to the class WebhookInfo. --- src/Entities/WebhookInfo.php | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/Entities/WebhookInfo.php b/src/Entities/WebhookInfo.php index bbeb16738..abe30e4de 100644 --- a/src/Entities/WebhookInfo.php +++ b/src/Entities/WebhookInfo.php @@ -16,14 +16,15 @@ * * @link https://core.telegram.org/bots/api#webhookinfo * - * @method string getUrl() Webhook URL, may be empty if webhook is not set up - * @method bool getHasCustomCertificate() True, if a custom certificate was provided for webhook certificate checks - * @method int getPendingUpdateCount() Number of updates awaiting delivery - * @method string getIpAddress() Optional. Currently used webhook IP address - * @method int getLastErrorDate() Optional. Unix time for the most recent error that happened when trying to deliver an update via webhook - * @method string getLastErrorMessage() Optional. Error message in human-readable format for the most recent error that happened when trying to deliver an update via webhook - * @method int getMaxConnections() Optional. Maximum allowed number of simultaneous HTTPS connections to the webhook for update delivery - * @method string[] getAllowedUpdates() Optional. A list of update types the bot is subscribed to. Defaults to all update types + * @method string getUrl() Webhook URL, may be empty if webhook is not set up + * @method bool getHasCustomCertificate() True, if a custom certificate was provided for webhook certificate checks + * @method int getPendingUpdateCount() Number of updates awaiting delivery + * @method string getIpAddress() Optional. Currently used webhook IP address + * @method int getLastErrorDate() Optional. Unix time for the most recent error that happened when trying to deliver an update via webhook + * @method string getLastErrorMessage() Optional. Error message in human-readable format for the most recent error that happened when trying to deliver an update via webhook + * @method int getLastSynchronizationErrorDate() Optional. Unix time of the most recent error that happened when trying to synchronize available updates with Telegram datacenters + * @method int getMaxConnections() Optional. Maximum allowed number of simultaneous HTTPS connections to the webhook for update delivery + * @method string[] getAllowedUpdates() Optional. A list of update types the bot is subscribed to. Defaults to all update types */ class WebhookInfo extends Entity { From 048405ba71cdd5102929f1f774ce766ff0172bbd Mon Sep 17 00:00:00 2001 From: Tii Date: Sun, 17 Apr 2022 19:26:03 +0200 Subject: [PATCH 09/16] Renamed the field can_manage_voice_chats to can_manage_video_chats in the class ChatMemberAdministrator. The old field will remain temporarily available --- src/Entities/ChatMember/ChatMemberAdministrator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Entities/ChatMember/ChatMemberAdministrator.php b/src/Entities/ChatMember/ChatMemberAdministrator.php index 9fd3b2322..762c1b461 100644 --- a/src/Entities/ChatMember/ChatMemberAdministrator.php +++ b/src/Entities/ChatMember/ChatMemberAdministrator.php @@ -19,7 +19,7 @@ * @method bool getCanPostMessages() True, if the administrator can post in the channel; channels only * @method bool getCanEditMessages() True, if the administrator can edit messages of other users and can pin messages; channels only * @method bool getCanDeleteMessages() True, if the administrator can delete messages of other users - * @method bool getCanManageVoiceChats() True, if the administrator can manage voice chats + * @method bool getCanManageVideoChats() True, if the administrator can manage video chats * @method bool getCanRestrictMembers() True, if the administrator can restrict, ban or unban chat members * @method bool getCanPromoteMembers() True, if the administrator can add new administrators with a subset of their own privileges or demote administrators that he has promoted, directly or indirectly (promoted by administrators that were appointed by the user) * @method bool getCanChangeInfo() True, if the user is allowed to change the chat title, photo and other settings From 260cd058a94e1d055658d26b34af6c7c8ca565ad Mon Sep 17 00:00:00 2001 From: Tii Date: Sun, 17 Apr 2022 19:36:42 +0200 Subject: [PATCH 10/16] Renamed the fields voice_chat_scheduled, voice_chat_started, voice_chat_ended, and voice_chat_participants_invited to video_chat_scheduled, video_chat_started, video_chat_ended, and video_chat_participants_invited in the class Message. The old fields will remain temporarily available. Old classes are deprecated --- src/Entities/Message.php | 24 +++++++------- src/Entities/VideoChatEnded.php | 24 ++++++++++++++ src/Entities/VideoChatParticipantsInvited.php | 32 +++++++++++++++++++ src/Entities/VideoChatScheduled.php | 24 ++++++++++++++ src/Entities/VideoChatStarted.php | 22 +++++++++++++ src/Entities/VoiceChatEnded.php | 2 ++ src/Entities/VoiceChatParticipantsInvited.php | 2 ++ src/Entities/VoiceChatScheduled.php | 2 ++ src/Entities/VoiceChatStarted.php | 2 ++ 9 files changed, 122 insertions(+), 12 deletions(-) create mode 100644 src/Entities/VideoChatEnded.php create mode 100644 src/Entities/VideoChatParticipantsInvited.php create mode 100644 src/Entities/VideoChatScheduled.php create mode 100644 src/Entities/VideoChatStarted.php diff --git a/src/Entities/Message.php b/src/Entities/Message.php index 494b40476..60a611a77 100644 --- a/src/Entities/Message.php +++ b/src/Entities/Message.php @@ -75,10 +75,10 @@ * @method string getConnectedWebsite() Optional. The domain name of the website on which the user has logged in. * @method PassportData getPassportData() Optional. Telegram Passport data * @method ProximityAlertTriggered getProximityAlertTriggered() Optional. Service message. A user in the chat triggered another user's proximity alert while sharing Live Location. - * @method VoiceChatScheduled getVoiceChatScheduled() Optional. Service message: voice chat scheduled - * @method VoiceChatStarted getVoiceChatStarted() Optional. Service message: voice chat started - * @method VoiceChatEnded getVoiceChatEnded() Optional. Service message: voice chat ended - * @method VoiceChatParticipantsInvited getVoiceChatParticipantsInvited() Optional. Service message: new participants invited to a voice chat + * @method VideoChatScheduled getVideoChatScheduled() Optional. Service message: voice chat scheduled + * @method VideoChatStarted getVideoChatStarted() Optional. Service message: voice chat started + * @method VideoChatEnded getVideoChatEnded() Optional. Service message: voice chat ended + * @method VideoChatParticipantsInvited getVideoChatParticipantsInvited() Optional. Service message: new participants invited to a voice chat * @method WebAppData getWebAppData() Optional. Service message: data sent by a Web App * @method InlineKeyboard getReplyMarkup() Optional. Inline keyboard attached to the message. login_url buttons are represented as ordinary url buttons. */ @@ -122,10 +122,10 @@ protected function subEntities(): array 'successful_payment' => SuccessfulPayment::class, 'passport_data' => PassportData::class, 'proximity_alert_triggered' => ProximityAlertTriggered::class, - 'voice_chat_scheduled' => VoiceChatScheduled::class, - 'voice_chat_started' => VoiceChatStarted::class, - 'voice_chat_ended' => VoiceChatEnded::class, - 'voice_chat_participants_invited' => VoiceChatParticipantsInvited::class, + 'video_chat_scheduled' => VideoChatScheduled::class, + 'video_chat_started' => VideoChatStarted::class, + 'video_chat_ended' => VideoChatEnded::class, + 'video_chat_participants_invited' => VideoChatParticipantsInvited::class, 'web_app_data' => WebAppData::class, 'reply_markup' => InlineKeyboard::class, ]; @@ -258,10 +258,10 @@ public function getType(): string 'successful_payment', 'passport_data', 'proximity_alert_triggered', - 'voice_chat_scheduled', - 'voice_chat_started', - 'voice_chat_ended', - 'voice_chat_participants_invited', + 'video_chat_scheduled', + 'video_chat_started', + 'video_chat_ended', + 'video_chat_participants_invited', 'web_app_data', 'reply_markup', ]; diff --git a/src/Entities/VideoChatEnded.php b/src/Entities/VideoChatEnded.php new file mode 100644 index 000000000..5f3a52773 --- /dev/null +++ b/src/Entities/VideoChatEnded.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Longman\TelegramBot\Entities; + +/** + * This object represents a service message about a video chat ended in the chat. + * + * @link https://core.telegram.org/bots/api#videochatended + * + * @method int getDuration() Video chat duration in seconds + */ +class VideoChatEnded extends Entity +{ + +} diff --git a/src/Entities/VideoChatParticipantsInvited.php b/src/Entities/VideoChatParticipantsInvited.php new file mode 100644 index 000000000..36a67b58e --- /dev/null +++ b/src/Entities/VideoChatParticipantsInvited.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Longman\TelegramBot\Entities; + +/** + * This object represents a service message about new members invited to a video chat. + * + * @link https://core.telegram.org/bots/api#videochatparticipantsinvited + * + * @method User[] getUsers() New members that were invited to the video chat + */ +class VideoChatParticipantsInvited extends Entity +{ + /** + * {@inheritdoc} + */ + protected function subEntities(): array + { + return [ + 'users' => [User::class], + ]; + } +} diff --git a/src/Entities/VideoChatScheduled.php b/src/Entities/VideoChatScheduled.php new file mode 100644 index 000000000..6ac750197 --- /dev/null +++ b/src/Entities/VideoChatScheduled.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Longman\TelegramBot\Entities; + +/** + * This object represents a service message about a video chat scheduled in the chat. + * + * @link https://core.telegram.org/bots/api#videochatscheduled + * + * @method int getStartDate() Point in time (Unix timestamp) when the video chat is supposed to be started by a chat administrator + */ +class VideoChatScheduled extends Entity +{ + +} diff --git a/src/Entities/VideoChatStarted.php b/src/Entities/VideoChatStarted.php new file mode 100644 index 000000000..4e10aa8d5 --- /dev/null +++ b/src/Entities/VideoChatStarted.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Longman\TelegramBot\Entities; + +/** + * This object represents a service message about a video chat started in the chat. Currently holds no information. + * + * @link https://core.telegram.org/bots/api#videochatstarted + */ +class VideoChatStarted extends Entity +{ + +} diff --git a/src/Entities/VoiceChatEnded.php b/src/Entities/VoiceChatEnded.php index d103a6a67..edcd6ecdc 100644 --- a/src/Entities/VoiceChatEnded.php +++ b/src/Entities/VoiceChatEnded.php @@ -16,6 +16,8 @@ * * Represents a service message about new members invited to a voice chat * + * @deprecated See VideoChatEnded instead + * * @link https://core.telegram.org/bots/api#voicechatended * * @method int getDuration() Voice chat duration; in seconds diff --git a/src/Entities/VoiceChatParticipantsInvited.php b/src/Entities/VoiceChatParticipantsInvited.php index 109d63890..a877214f7 100644 --- a/src/Entities/VoiceChatParticipantsInvited.php +++ b/src/Entities/VoiceChatParticipantsInvited.php @@ -16,6 +16,8 @@ * * Represents a service message about new members invited to a voice chat * + * @deprecated See VideoChatParticipantsInvited instead + * * @link https://core.telegram.org/bots/api#voicechatparticipantsinvited * * @method User[] getUsers() Optional. New members that were invited to the voice chat diff --git a/src/Entities/VoiceChatScheduled.php b/src/Entities/VoiceChatScheduled.php index e9049efcb..69c011745 100644 --- a/src/Entities/VoiceChatScheduled.php +++ b/src/Entities/VoiceChatScheduled.php @@ -16,6 +16,8 @@ * * Represents a service message about a voice chat scheduled in the chat. * + * @deprecated See VideoChatScheduled instead + * * @link https://core.telegram.org/bots/api#voicechatscheduled * * @method int getStartDate() Point in time (Unix timestamp) when the voice chat is supposed to be started by a chat administrator diff --git a/src/Entities/VoiceChatStarted.php b/src/Entities/VoiceChatStarted.php index cb9fb81e4..acd392773 100644 --- a/src/Entities/VoiceChatStarted.php +++ b/src/Entities/VoiceChatStarted.php @@ -16,6 +16,8 @@ * * Represents a service message about a voice chat started in the chat * + * @deprecated See VideoChatStarted instead + * * @link https://core.telegram.org/bots/api#voicechatstarted */ class VoiceChatStarted extends Entity From 8c61b781fcb8bf7ae831fbfb09103d88abea774d Mon Sep 17 00:00:00 2001 From: Tii Date: Sun, 17 Apr 2022 19:45:25 +0200 Subject: [PATCH 11/16] Re-added voide entities to message object --- src/Entities/Message.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Entities/Message.php b/src/Entities/Message.php index 60a611a77..b6fabff34 100644 --- a/src/Entities/Message.php +++ b/src/Entities/Message.php @@ -122,6 +122,10 @@ protected function subEntities(): array 'successful_payment' => SuccessfulPayment::class, 'passport_data' => PassportData::class, 'proximity_alert_triggered' => ProximityAlertTriggered::class, + 'voice_chat_scheduled' => VoiceChatScheduled::class, // deprecated + 'voice_chat_started' => VoiceChatStarted::class, // deprecated + 'voice_chat_ended' => VoiceChatEnded::class, // deprecated + 'voice_chat_participants_invited' => VoiceChatParticipantsInvited::class, // deprecated 'video_chat_scheduled' => VideoChatScheduled::class, 'video_chat_started' => VideoChatStarted::class, 'video_chat_ended' => VideoChatEnded::class, From d372bb22743fc8a6d7487099043f516217559ad4 Mon Sep 17 00:00:00 2001 From: Tii Date: Sun, 17 Apr 2022 20:07:16 +0200 Subject: [PATCH 12/16] Added Changelog and updated Bot API Version in README --- CHANGELOG.md | 3 +++ README.md | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d2a4a2d3..398bf898e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,11 @@ Exclamation symbols (:exclamation:) note something of importance e.g. breaking c ### Notes - [:ledger: View file changes][Unreleased] ### Added +- Bot API 6.0 See https://core.telegram.org/bots/api#april-16-2022 (@TiiFuchs) ### Changed ### Deprecated +- Telegram changed voice_chat_scheduled, voice_chat_started, voice_chat_ended and voice_chat_participants_invited to video_chat_scheduled, video_chat_started, video_chat_ended and video_chat_participants_invited. +To reflect that change we marked the corresponding VoiceChat classes as deprecated and created new classes for the VideoChat events. ### Removed ### Fixed ### Security diff --git a/README.md b/README.md index f89ec9437..ab8faa470 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A Telegram Bot based on the official [Telegram Bot API] -[![API Version](https://img.shields.io/badge/Bot%20API-5.7%20%28January%202022%29-32a2da.svg)](https://core.telegram.org/bots/api#january-31-2022) +[![API Version](https://img.shields.io/badge/Bot%20API-6.0%20%28April%202022%29-32a2da.svg)](https://core.telegram.org/bots/api#april-16-2022) [![Join the bot support group on Telegram](https://img.shields.io/badge/telegram-@PHP__Telegram__Bot__Support-64659d.svg)](https://telegram.me/PHP_Telegram_Bot_Support) [![Donate](https://img.shields.io/badge/%F0%9F%92%99-Donate%20%2F%20Support%20Us-blue.svg)](#donate) @@ -78,7 +78,7 @@ This Bot aims to provide a platform where one can simply write a bot and have in The Bot can: - Retrieve updates with [webhook](#webhook-installation) and [getUpdates](#getupdates-installation) methods. -- Supports all types and methods according to Telegram Bot API 5.7 (January 2022). +- Supports all types and methods according to Telegram Bot API 6.0 (April 2022). - Supports supergroups. - Handle commands in chat with other bots. - Manage Channel from the bot admin interface. From af094625cb03d5d3b638b2cf94fddddf616a3528 Mon Sep 17 00:00:00 2001 From: Tii Date: Tue, 19 Apr 2022 08:38:02 +0200 Subject: [PATCH 13/16] Revert Auto format changes --- src/Request.php | 131 ++++++++++++++++++++++++------------------------ 1 file changed, 65 insertions(+), 66 deletions(-) diff --git a/src/Request.php b/src/Request.php index a5ea523e0..4ea831c52 100644 --- a/src/Request.php +++ b/src/Request.php @@ -312,7 +312,7 @@ class Request /** * Initialize * - * @param Telegram $telegram + * @param Telegram $telegram */ public static function initialize(Telegram $telegram): void { @@ -323,7 +323,7 @@ public static function initialize(Telegram $telegram): void /** * Set a custom Guzzle HTTP Client object * - * @param ClientInterface $client + * @param ClientInterface $client */ public static function setClient(ClientInterface $client): void { @@ -333,8 +333,8 @@ public static function setClient(ClientInterface $client): void /** * Set a custom Bot API URL * - * @param string $api_base_uri - * @param string $api_base_download_uri + * @param string $api_base_uri + * @param string $api_base_download_uri */ public static function setCustomBotApiUri(string $api_base_uri, string $api_base_download_uri = ''): void { @@ -359,7 +359,7 @@ public static function getInput(): string /** * Generate general fake server response * - * @param array $data Data to add to fake response + * @param array $data Data to add to fake response * * @return array Fake response data */ @@ -380,13 +380,13 @@ public static function generateGeneralFakeServerResponse(array $data = []): arra //some data to initialize the class method SendMessage if (isset($data['chat_id'])) { $data['message_id'] = '1234'; - $data['date'] = '1441378360'; - $data['from'] = [ + $data['date'] = '1441378360'; + $data['from'] = [ 'id' => 123456789, 'first_name' => 'botname', 'username' => 'namebot', ]; - $data['chat'] = ['id' => $data['chat_id']]; + $data['chat'] = ['id' => $data['chat_id']]; $fake_response['result'] = $data; } @@ -400,7 +400,7 @@ public static function generateGeneralFakeServerResponse(array $data = []): arra * If any item of the array is a resource, reformat it to a multipart request. * Else, just return the passed data as form params. * - * @param array $data + * @param array $data * * @return array * @throws TelegramException @@ -408,14 +408,13 @@ public static function generateGeneralFakeServerResponse(array $data = []): arra private static function setUpRequestParams(array $data): array { $has_resource = false; - $multipart = []; + $multipart = []; foreach ($data as $key => &$item) { if ($key === 'media') { // Magical media input helper. $item = self::mediaInputHelper($item, $has_resource, $multipart); - } elseif (array_key_exists(self::$current_action, self::$input_file_fields) && in_array($key, - self::$input_file_fields[self::$current_action], true)) { + } elseif (array_key_exists(self::$current_action, self::$input_file_fields) && in_array($key, self::$input_file_fields[self::$current_action], true)) { // Allow absolute paths to local files. if (is_string($item) && file_exists($item)) { $item = new Stream(self::encodeFile($item)); @@ -427,7 +426,7 @@ private static function setUpRequestParams(array $data): array // Reformat data array in multipart way if it contains a resource $has_resource = $has_resource || is_resource($item) || $item instanceof Stream; - $multipart[] = ['name' => $key, 'contents' => $item]; + $multipart[] = ['name' => $key, 'contents' => $item]; } unset($item); @@ -466,9 +465,9 @@ private static function setUpRequestParams(array $data): array * ], * ]); * - * @param mixed $item - * @param bool $has_resource - * @param array $multipart + * @param mixed $item + * @param bool $has_resource + * @param array $multipart * * @return mixed * @throws TelegramException @@ -480,7 +479,7 @@ private static function mediaInputHelper($item, bool &$has_resource, array &$mul /** @var InputMedia|null $media_item */ foreach ($item as $media_item) { - if (! ($media_item instanceof InputMedia)) { + if (!($media_item instanceof InputMedia)) { continue; } @@ -498,11 +497,11 @@ private static function mediaInputHelper($item, bool &$has_resource, array &$mul if (is_resource($media) || $media instanceof Stream) { $has_resource = true; - $unique_key = uniqid($type . '_', false); - $multipart[] = ['name' => $unique_key, 'contents' => $media]; + $unique_key = uniqid($type . '_', false); + $multipart[] = ['name' => $unique_key, 'contents' => $media]; // We're literally overwriting the passed media type data! - $media_item->$type = 'attach://' . $unique_key; + $media_item->$type = 'attach://' . $unique_key; $media_item->raw_data[$type] = 'attach://' . $unique_key; } } @@ -526,15 +525,15 @@ public static function getCurrentAction(): string /** * Execute HTTP Request * - * @param string $action Action to execute - * @param array $data Data to attach to the execution + * @param string $action Action to execute + * @param array $data Data to attach to the execution * * @return string Result of the HTTP Request * @throws TelegramException */ public static function execute(string $action, array $data = []): string { - $request_params = self::setUpRequestParams($data); + $request_params = self::setUpRequestParams($data); $request_params['debug'] = TelegramLog::getDebugLogTempStream(); try { @@ -542,10 +541,10 @@ public static function execute(string $action, array $data = []): string '/bot' . self::$telegram->getApiKey() . '/' . $action, $request_params ); - $result = (string) $response->getBody(); + $result = (string) $response->getBody(); } catch (RequestException $e) { $response = null; - $result = $e->getResponse() ? (string) $e->getResponse()->getBody() : ''; + $result = $e->getResponse() ? (string) $e->getResponse()->getBody() : ''; } //Logging verbose debug output @@ -561,7 +560,7 @@ public static function execute(string $action, array $data = []): string /** * Download file * - * @param File $file + * @param File $file * * @return bool * @throws TelegramException @@ -573,12 +572,12 @@ public static function downloadFile(File $file): bool } $tg_file_path = $file->getFilePath(); - $file_path = $download_path . '/' . $tg_file_path; + $file_path = $download_path . '/' . $tg_file_path; $file_dir = dirname($file_path); //For safety reasons, first try to create the directory, then check that it exists. //This is in case some other process has created the folder in the meantime. - if (! @mkdir($file_dir, 0755, true) && ! is_dir($file_dir)) { + if (!@mkdir($file_dir, 0755, true) && !is_dir($file_dir)) { throw new TelegramException('Directory ' . $file_dir . ' can\'t be created'); } @@ -603,7 +602,7 @@ public static function downloadFile(File $file): bool /** * Encode file * - * @param string $file + * @param string $file * * @return resource * @throws TelegramException @@ -624,8 +623,8 @@ public static function encodeFile(string $file) * @todo Fake response doesn't need json encoding? * @todo Write debug entry on failure * - * @param string $action - * @param array $data + * @param string $action + * @param array $data * * @return ServerResponse * @throws TelegramException @@ -651,7 +650,7 @@ public static function send(string $action, array $data = []): ServerResponse self::$current_action = $action; $raw_response = self::execute($action, $data); - $response = json_decode($raw_response, true); + $response = json_decode($raw_response, true); if (null === $response) { TelegramLog::debug($raw_response); @@ -660,7 +659,7 @@ public static function send(string $action, array $data = []): ServerResponse $response = new ServerResponse($response, $bot_username); - if (! $response->isOk() && $response->getErrorCode() === 401 && $response->getDescription() === 'Unauthorized') { + if (!$response->isOk() && $response->getErrorCode() === 401 && $response->getDescription() === 'Unauthorized') { throw new InvalidBotTokenException(); } @@ -686,8 +685,8 @@ public static function send(string $action, array $data = []): ServerResponse * * @todo Would be nice to find a better solution for this! * - * @param string $action - * @param array $data + * @param string $action + * @param array $data */ protected static function addDummyParamIfNecessary(string $action, array &$data): void { @@ -700,7 +699,7 @@ protected static function addDummyParamIfNecessary(string $action, array &$data) /** * Make sure the data isn't empty, else throw an exception * - * @param array $data + * @param array $data * * @throws TelegramException */ @@ -714,13 +713,13 @@ private static function ensureNonEmptyData(array $data): void /** * Make sure the action is valid, else throw an exception * - * @param string $action + * @param string $action * * @throws TelegramException */ private static function ensureValidAction(string $action): void { - if (! in_array($action, self::$actions, true)) { + if (!in_array($action, self::$actions, true)) { throw new TelegramException('The action "' . $action . '" doesn\'t exist!'); } } @@ -738,8 +737,8 @@ private static function ensureValidAction(string $action): void * * @todo Splitting formatted text may break the message. * - * @param array $data - * @param array|null $extras + * @param array $data + * @param array|null $extras * * @return ServerResponse * @throws TelegramException @@ -751,8 +750,8 @@ public static function sendMessage(array $data, ?array &$extras = []): ServerRes 'encoding' => mb_internal_encoding(), ], (array) $extras); - $text = $data['text']; - $encoding = $extras['encoding']; + $text = $data['text']; + $encoding = $extras['encoding']; $max_length = $extras['split'] ?: mb_strlen($text, $encoding); $responses = []; @@ -760,7 +759,7 @@ public static function sendMessage(array $data, ?array &$extras = []): ServerRes do { // Chop off and send the first message. $data['text'] = mb_substr($text, 0, $max_length, $encoding); - $responses[] = self::send('sendMessage', $data); + $responses[] = self::send('sendMessage', $data); // Prepare the next message. $text = mb_substr($text, $max_length, null, $encoding); @@ -775,8 +774,8 @@ public static function sendMessage(array $data, ?array &$extras = []): ServerRes /** * Any statically called method should be relayed to the `send` method. * - * @param string $action - * @param array $data + * @param string $action + * @param array $data * * @return ServerResponse * @throws TelegramException @@ -803,9 +802,9 @@ public static function emptyResponse(): ServerResponse /** * Send message to all active chats * - * @param string $callback_function - * @param array $data - * @param array $select_chats_params + * @param string $callback_function + * @param array $data + * @param array $select_chats_params * * @return array * @throws TelegramException @@ -823,7 +822,7 @@ public static function sendToActiveChats( if (is_array($chats)) { foreach ($chats as $row) { $data['chat_id'] = $row['chat_id']; - $results[] = self::send($callback_function, $data); + $results[] = self::send($callback_function, $data); } } @@ -833,8 +832,8 @@ public static function sendToActiveChats( /** * Enable request limiter * - * @param bool $enable - * @param array $options + * @param bool $enable + * @param array $options * * @throws TelegramException */ @@ -847,12 +846,12 @@ public static function setLimiter(bool $enable = true, array $options = []): voi $options = array_merge($options_default, $options); - if (! is_numeric($options['interval']) || $options['interval'] <= 0) { + if (!is_numeric($options['interval']) || $options['interval'] <= 0) { throw new TelegramException('Interval must be a number and must be greater than zero!'); } self::$limiter_interval = $options['interval']; - self::$limiter_enabled = $enable; + self::$limiter_enabled = $enable; } } @@ -862,8 +861,8 @@ public static function setLimiter(bool $enable = true, array $options = []): voi * * @link https://core.telegram.org/bots/faq#my-bot-is-hitting-limits-how-do-i-avoid-this * - * @param string $action - * @param array $data + * @param string $action + * @param array $data * * @throws TelegramException */ @@ -907,7 +906,7 @@ private static function limitTelegramRequests(string $action, array $data = []): 'setPassportDataErrors', ]; - $chat_id = $data['chat_id'] ?? null; + $chat_id = $data['chat_id'] ?? null; $inline_message_id = $data['inline_message_id'] ?? null; if (($chat_id || $inline_message_id) && in_array($action, $limited_methods, true)) { @@ -918,16 +917,16 @@ private static function limitTelegramRequests(string $action, array $data = []): throw new TelegramException('Timed out while waiting for a request spot!'); } - if (! ($requests = DB::getTelegramRequestCount($chat_id, $inline_message_id))) { + if (!($requests = DB::getTelegramRequestCount($chat_id, $inline_message_id))) { break; } // Make sure we're handling integers here. $requests = array_map('intval', $requests); - $chat_per_second = ($requests['LIMIT_PER_SEC'] === 0); // No more than one message per second inside a particular chat - $global_per_second = ($requests['LIMIT_PER_SEC_ALL'] < 30); // No more than 30 messages per second to different chats - $groups_per_minute = (((is_numeric($chat_id) && $chat_id > 0) || $inline_message_id !== null) || ((! is_numeric($chat_id) || $chat_id < 0) && $requests['LIMIT_PER_MINUTE'] < 20)); // No more than 20 messages per minute in groups and channels + $chat_per_second = ($requests['LIMIT_PER_SEC'] === 0); // No more than one message per second inside a particular chat + $global_per_second = ($requests['LIMIT_PER_SEC_ALL'] < 30); // No more than 30 messages per second to different chats + $groups_per_minute = (((is_numeric($chat_id) && $chat_id > 0) || $inline_message_id !== null) || ((!is_numeric($chat_id) || $chat_id < 0) && $requests['LIMIT_PER_MINUTE'] < 20)); // No more than 20 messages per minute in groups and channels if ($chat_per_second && $global_per_second && $groups_per_minute) { break; @@ -945,12 +944,12 @@ private static function limitTelegramRequests(string $action, array $data = []): /** * Use this method to kick a user from a group, a supergroup or a channel. In the case of supergroups and channels, the user will not be able to return to the group on their own using invite links, etc., unless unbanned first. The bot must be an administrator in the chat for this to work and must have the appropriate admin rights. Returns True on success. * - * @param array $data - * - * @return ServerResponse * @deprecated * @see Request::banChatMember() * + * @param array $data + * + * @return ServerResponse */ public static function kickChatMember(array $data = []): ServerResponse { @@ -960,12 +959,12 @@ public static function kickChatMember(array $data = []): ServerResponse /** * Use this method to get the number of members in a chat. Returns Int on success. * - * @param array $data - * - * @return ServerResponse * @deprecated * @see Request::getChatMemberCount() * + * @param array $data + * + * @return ServerResponse */ public static function getChatMembersCount(array $data = []): ServerResponse { From 464efa2c9aa9dba9b550300be1004931c77ed7a5 Mon Sep 17 00:00:00 2001 From: Tii Date: Tue, 19 Apr 2022 08:43:04 +0200 Subject: [PATCH 14/16] Make use of early returns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Armando Lüscher --- src/Entities/Factory.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Entities/Factory.php b/src/Entities/Factory.php index d2d05eaa6..c821efacc 100644 --- a/src/Entities/Factory.php +++ b/src/Entities/Factory.php @@ -10,7 +10,9 @@ public static function resolveEntityClass(string $class, mixed $property, string { if (is_a($property, $class)) { return $property; - } elseif (is_subclass_of($class, Factory::class)) { + } + + if (is_subclass_of($class, Factory::class)) { return $class::make($property, $bot_username); } From 821d2cfea0e7c255b7bef297f7c92da8a3f1396a Mon Sep 17 00:00:00 2001 From: Tii Date: Wed, 20 Apr 2022 13:34:12 +0200 Subject: [PATCH 15/16] DB Changes for Bot API 6.0 --- src/DB.php | 13 +++++++------ structure.sql | 9 +++++---- utils/db-schema-update/0.76.1-pending.sql | 7 +++++++ 3 files changed, 19 insertions(+), 10 deletions(-) create mode 100644 utils/db-schema-update/0.76.1-pending.sql diff --git a/src/DB.php b/src/DB.php index 545133c09..6953c2d8e 100644 --- a/src/DB.php +++ b/src/DB.php @@ -1137,7 +1137,7 @@ public static function insertMessageRequest(Message $message): bool `new_chat_title`, `new_chat_photo`, `delete_chat_photo`, `group_chat_created`, `supergroup_chat_created`, `channel_chat_created`, `message_auto_delete_timer_changed`, `migrate_to_chat_id`, `migrate_from_chat_id`, `pinned_message`, `invoice`, `successful_payment`, `connected_website`, `passport_data`, `proximity_alert_triggered`, - `voice_chat_scheduled`, `voice_chat_started`, `voice_chat_ended`, `voice_chat_participants_invited`, `reply_markup` + `video_chat_scheduled`, `video_chat_started`, `video_chat_ended`, `video_chat_participants_invited`, `web_app_data`, `reply_markup` ) VALUES ( :message_id, :user_id, :chat_id, :sender_chat_id, :date, :forward_from, :forward_from_chat, :forward_from_message_id, :forward_signature, :forward_sender_name, :forward_date, @@ -1147,7 +1147,7 @@ public static function insertMessageRequest(Message $message): bool :new_chat_title, :new_chat_photo, :delete_chat_photo, :group_chat_created, :supergroup_chat_created, :channel_chat_created, :message_auto_delete_timer_changed, :migrate_to_chat_id, :migrate_from_chat_id, :pinned_message, :invoice, :successful_payment, :connected_website, :passport_data, :proximity_alert_triggered, - :voice_chat_scheduled, :voice_chat_started, :voice_chat_ended, :voice_chat_participants_invited, :reply_markup + :video_chat_scheduled, :video_chat_started, :video_chat_ended, :video_chat_participants_invited, :web_app_data, :reply_markup ) '); @@ -1220,10 +1220,11 @@ public static function insertMessageRequest(Message $message): bool $sth->bindValue(':connected_website', $message->getConnectedWebsite()); $sth->bindValue(':passport_data', $message->getPassportData()); $sth->bindValue(':proximity_alert_triggered', $message->getProximityAlertTriggered()); - $sth->bindValue(':voice_chat_scheduled', $message->getVoiceChatScheduled()); - $sth->bindValue(':voice_chat_started', $message->getVoiceChatStarted()); - $sth->bindValue(':voice_chat_ended', $message->getVoiceChatEnded()); - $sth->bindValue(':voice_chat_participants_invited', $message->getVoiceChatParticipantsInvited()); + $sth->bindValue(':video_chat_scheduled', $message->getVideoChatScheduled()); + $sth->bindValue(':video_chat_started', $message->getVideoChatStarted()); + $sth->bindValue(':video_chat_ended', $message->getVideoChatEnded()); + $sth->bindValue(':video_chat_participants_invited', $message->getVideoChatParticipantsInvited()); + $sth->bindValue(':web_app_data', $message->getWebAppData()); $sth->bindValue(':reply_markup', $message->getReplyMarkup()); return $sth->execute(); diff --git a/structure.sql b/structure.sql index 657f1ee5b..e4ce00527 100644 --- a/structure.sql +++ b/structure.sql @@ -123,10 +123,11 @@ CREATE TABLE IF NOT EXISTS `message` ( `connected_website` TEXT NULL COMMENT 'The domain name of the website on which the user has logged in.', `passport_data` TEXT NULL COMMENT 'Telegram Passport data', `proximity_alert_triggered` TEXT NULL COMMENT 'Service message. A user in the chat triggered another user''s proximity alert while sharing Live Location.', - `voice_chat_scheduled` TEXT COMMENT 'VoiceChatScheduled object. Message is a service message: voice chat scheduled', - `voice_chat_started` TEXT COMMENT 'VoiceChatStarted object. Message is a service message: voice chat started', - `voice_chat_ended` TEXT COMMENT 'VoiceChatEnded object. Message is a service message: voice chat ended', - `voice_chat_participants_invited` TEXT COMMENT 'VoiceChatParticipantsInvited object. Message is a service message: new participants invited to a voice chat', + `video_chat_scheduled` TEXT COMMENT 'Service message: video chat scheduled', + `video_chat_started` TEXT COMMENT 'Service message: video chat started', + `video_chat_ended` TEXT COMMENT 'Service message: video chat ended', + `video_chat_participants_invited` TEXT COMMENT 'Service message: new participants invited to a video chat', + `web_app_data` TEXT COMMENT 'Service message: data sent by a Web App', `reply_markup` TEXT NULL COMMENT 'Inline keyboard attached to the message', PRIMARY KEY (`chat_id`, `id`), diff --git a/utils/db-schema-update/0.76.1-pending.sql b/utils/db-schema-update/0.76.1-pending.sql new file mode 100644 index 000000000..56c518489 --- /dev/null +++ b/utils/db-schema-update/0.76.1-pending.sql @@ -0,0 +1,7 @@ +ALTER TABLE `message` ADD COLUMN `web_app_data` TEXT NULL DEFAULT NULL COMMENT 'Service message: data sent by a Web App' AFTER `voice_chat_participants_invited`; + +ALTER TABLE `message` + CHANGE `voice_chat_scheduled` `video_chat_scheduled` TEXT COMMENT 'Service message: video chat scheduled', + CHANGE `voice_chat_started` `video_chat_started` TEXT COMMENT 'Service message: video chat started', + CHANGE `voice_chat_ended` `video_chat_ended` TEXT COMMENT 'Service message: video chat ended', + CHANGE `voice_chat_participants_invited` `video_chat_participants_invited` TEXT COMMENT 'Service message: new participants invited to a video chat'; From 27cc26cb7836fcb805b93652e3c808017fc62c8c Mon Sep 17 00:00:00 2001 From: Tii Date: Sun, 24 Apr 2022 17:00:04 +0200 Subject: [PATCH 16/16] Added missing stuff for handling ServerResponse->getResult --- src/Entities/MenuButton/Factory.php | 25 +++++++++++++++++++ src/Entities/MenuButton/MenuButton.php | 5 ++++ .../MenuButton/MenuButtonNotImplemented.php | 8 ++++++ src/Entities/ServerResponse.php | 18 +++++++------ 4 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 src/Entities/MenuButton/Factory.php create mode 100644 src/Entities/MenuButton/MenuButtonNotImplemented.php diff --git a/src/Entities/MenuButton/Factory.php b/src/Entities/MenuButton/Factory.php new file mode 100644 index 000000000..1b030e453 --- /dev/null +++ b/src/Entities/MenuButton/Factory.php @@ -0,0 +1,25 @@ + MenuButtonCommands::class, + 'web_app' => MenuButtonWebApp::class, + 'default' => MenuButtonDefault::class, + ]; + + if (! isset($type[$data['type'] ?? ''])) { + return new MenuButtonNotImplemented($data, $bot_username); + } + + $class = $type[$data['type']]; + return new $class($data, $bot_username); + } +} diff --git a/src/Entities/MenuButton/MenuButton.php b/src/Entities/MenuButton/MenuButton.php index 182831930..216d947ae 100644 --- a/src/Entities/MenuButton/MenuButton.php +++ b/src/Entities/MenuButton/MenuButton.php @@ -4,6 +4,11 @@ use Longman\TelegramBot\Entities\Entity; +/** + * @method string getType() Type of the button + * + * @method $this setType($type) Type of the button + */ abstract class MenuButton extends Entity { diff --git a/src/Entities/MenuButton/MenuButtonNotImplemented.php b/src/Entities/MenuButton/MenuButtonNotImplemented.php new file mode 100644 index 000000000..8db8ded05 --- /dev/null +++ b/src/Entities/MenuButton/MenuButtonNotImplemented.php @@ -0,0 +1,8 @@ + Chat::class, - 'getChatMember' => ChatMemberFactory::class, - 'getFile' => File::class, - 'getMe' => User::class, - 'getStickerSet' => StickerSet::class, - 'getUserProfilePhotos' => UserProfilePhotos::class, - 'getWebhookInfo' => WebhookInfo::class, + 'answerWebAppQuery' => SentWebAppMessage::class, + 'getChat' => Chat::class, + 'getMyDefaultAdministratorRights' => ChatAdministratorRights::class, + 'getChatMember' => ChatMemberFactory::class, + 'getChatMenuButton' => MenuButtonFactory::class, + 'getFile' => File::class, + 'getMe' => User::class, + 'getStickerSet' => StickerSet::class, + 'getUserProfilePhotos' => UserProfilePhotos::class, + 'getWebhookInfo' => WebhookInfo::class, ]; $action = Request::getCurrentAction();