├── src ├── Objects │ ├── EditedMessage.php │ ├── UnknownObject.php │ ├── Location.php │ ├── PollOption.php │ ├── LabeledPrice.php │ ├── Dice.php │ ├── InputContent │ │ ├── InputMediaDocument.php │ │ ├── InputMediaAudio.php │ │ ├── InputLocationMessageContent.php │ │ ├── InputMediaAnimation.php │ │ ├── InputContactMessageContent.php │ │ ├── InputTextMessageContent.php │ │ └── InputVenueMessageContent.php │ ├── GameHighScore.php │ ├── BotCommand.php │ ├── InlineKeyboard │ │ ├── InlineKeyboardMarkup.php │ │ ├── LoginUrl.php │ │ ├── CallbackGame.php │ │ └── InlineKeyboardButton.php │ ├── UserProfilePhotos.php │ ├── ShippingOption.php │ ├── PollAnswer.php │ ├── PhotoSize.php │ ├── OrderInfo.php │ ├── ShippingAddress.php │ ├── Contact.php │ ├── Invoice.php │ ├── Venue.php │ ├── Passport │ │ ├── PassportFile.php │ │ ├── PassportData.php │ │ ├── EncryptedCredentials.php │ │ └── EncryptedPassportElement.php │ ├── ShippingQuery.php │ ├── Voice.php │ ├── MaskPosition.php │ ├── ChatPhoto.php │ ├── InlineQuery.php │ ├── StickerSet.php │ ├── InlineQuery │ │ ├── InlineBaseObject.php │ │ ├── InlineQueryResultGame.php │ │ ├── InlineQueryResultCachedSticker.php │ │ ├── InlineQueryResultCachedAudio.php │ │ ├── InlineQueryResultCachedVoice.php │ │ ├── InlineQueryResultCachedGif.php │ │ ├── InlineQueryResultCachedMpeg4Gif.php │ │ ├── InlineQueryResultVoice.php │ │ ├── InlineQueryResultCachedPhoto.php │ │ ├── InlineQueryResultCachedVideo.php │ │ ├── InlineQueryResultCachedDocument.php │ │ ├── InlineQueryResultAudio.php │ │ ├── InlineQueryResultLocation.php │ │ ├── InlineQueryResultContact.php │ │ ├── InlineQueryResultArticle.php │ │ ├── InlineQueryResultPhoto.php │ │ ├── InlineQueryResultGif.php │ │ ├── InlineQueryResultMpeg4Gif.php │ │ ├── InlineQueryResultVenue.php │ │ ├── InlineQueryResultDocument.php │ │ └── InlineQueryResultVideo.php │ ├── Video.php │ ├── VideoNote.php │ ├── Animation.php │ ├── Document.php │ ├── File.php │ ├── PreCheckoutQuery.php │ ├── SuccessfulPayment.php │ ├── WebhookInfo.php │ ├── Audio.php │ ├── MessageEntity.php │ ├── User.php │ ├── ChosenInlineResult.php │ ├── Sticker.php │ ├── Game.php │ ├── CallbackQuery.php │ ├── Chat │ │ └── ChatPermissions.php │ ├── Poll.php │ ├── Chat.php │ ├── ChatMember.php │ ├── BaseObject.php │ ├── Update.php │ └── Message.php ├── Exceptions │ ├── TelegramSDKException.php │ ├── TelegramOtherException.php │ ├── TelegramEmojiMapFileNotFoundException.php │ ├── TelegramUndefinedPropertyException.php │ └── TelegramResponseException.php ├── Laravel │ ├── Facades │ │ └── Telegram.php │ ├── TelegramServiceProvider.php │ └── config │ │ └── telegram.php ├── Keyboard │ ├── Base.php │ ├── Button.php │ └── Keyboard.php ├── HttpClients │ ├── HttpClientInterface.php │ └── GuzzleHttpClient.php ├── Commands │ ├── HelpCommand.php │ ├── CommandInterface.php │ ├── Command.php │ └── CommandBus.php ├── Actions.php ├── FileUpload │ └── InputFile.php ├── Callbacks │ ├── CallbackCommandInterface.php │ ├── CallbackCommand.php │ └── CallbackCommandBus.php ├── Answers │ ├── AnswerBus.php │ └── Answerable.php ├── TelegramClient.php ├── TelegramResponse.php ├── Helpers │ └── Emojify.php ├── TelegramRequest.php └── BotsManager.php ├── phpcs.xml.dist ├── .github └── workflows │ └── main.yml ├── LICENSE └── composer.json /src/Objects/EditedMessage.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | The PSR12 coding standard. 4 | 5 | 6 | src 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Laravel/Facades/Telegram.php: -------------------------------------------------------------------------------- 1 | 11 | * $params = [ 12 | * 'type' => '', 13 | * 'media' => '', 14 | * 'thumb' => '', 15 | * 'caption' => '', 16 | * 'parse_mode' => '', 17 | * ]; 18 | * 19 | * 20 | */ 21 | class InputMediaDocument extends InlineBaseObject 22 | { 23 | } 24 | -------------------------------------------------------------------------------- /src/Objects/GameHighScore.php: -------------------------------------------------------------------------------- 1 | User::class, 21 | ]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Objects/BotCommand.php: -------------------------------------------------------------------------------- 1 | InlineKeyboardButton::class, 21 | ]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Objects/InputContent/InputMediaAudio.php: -------------------------------------------------------------------------------- 1 | 11 | * $params = [ 12 | * 'type' => '', 13 | * 'media' => '', 14 | * 'thumb' => '', 15 | * 'caption' => '', 16 | * 'parse_mode' => '', 17 | * 'duration' => '', 18 | * 'performer' => '', 19 | * 'title' => '', 20 | * ]; 21 | * 22 | * 23 | */ 24 | class InputMediaAudio extends InlineBaseObject 25 | { 26 | } 27 | -------------------------------------------------------------------------------- /src/Objects/UserProfilePhotos.php: -------------------------------------------------------------------------------- 1 | PhotoSize::class, 21 | ]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Objects/InputContent/InputLocationMessageContent.php: -------------------------------------------------------------------------------- 1 | 11 | * $params = [ 12 | * 'latitude' => '', 13 | * 'longitude' => '', 14 | * ]; 15 | * 16 | * @method $this setLatitude($float) Latitude of the location in degrees 17 | * @method $this setLongitude($float) Longitude of the location in degrees 18 | */ 19 | class InputLocationMessageContent extends InlineBaseObject 20 | { 21 | } 22 | -------------------------------------------------------------------------------- /src/Objects/ShippingOption.php: -------------------------------------------------------------------------------- 1 | LabeledPrice::class, 22 | ]; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Objects/InputContent/InputMediaAnimation.php: -------------------------------------------------------------------------------- 1 | 11 | * $params = [ 12 | * 'type' => '', 13 | * 'media' => '', 14 | * 'thumb' => '', 15 | * 'caption' => '', 16 | * 'parse_mode' => '', 17 | * 'width' => '', 18 | * 'height' => '', 19 | * 'duration' => '', 20 | * ]; 21 | * 22 | * 23 | */ 24 | class InputMediaAnimation extends InlineBaseObject 25 | { 26 | } 27 | -------------------------------------------------------------------------------- /src/Objects/PollAnswer.php: -------------------------------------------------------------------------------- 1 | User::class, 23 | ]; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Objects/PhotoSize.php: -------------------------------------------------------------------------------- 1 | ShippingAddress::class, 23 | ]; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Objects/ShippingAddress.php: -------------------------------------------------------------------------------- 1 | items[$property] = $args[0]; 25 | 26 | return $this; 27 | } 28 | 29 | return parent::__call($method, $args); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Objects/Venue.php: -------------------------------------------------------------------------------- 1 | Location::class, 24 | ]; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Objects/Passport/PassportFile.php: -------------------------------------------------------------------------------- 1 | User::class, 23 | 'shipping_address' => ShippingAddress::class, 24 | ]; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Objects/Voice.php: -------------------------------------------------------------------------------- 1 | EncryptedPassportElement::class, 24 | 'credentials' => EncryptedCredentials::class, 25 | ]; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Objects/InputContent/InputContactMessageContent.php: -------------------------------------------------------------------------------- 1 | 11 | * $params = [ 12 | * 'phone_number' => '', 13 | * 'first_name' => '', 14 | * 'last_name' => '', 15 | * ]; 16 | * 17 | * 18 | * @method $this setPhoneNumber($string) Contact's phone number 19 | * @method $this setFirstName($string) Contact's first name 20 | * @method $this setLastName($string) Optional. Contact's last name 21 | * @method $this setVcard() Optional. Additional data about the contact in the form of a vCard. 22 | */ 23 | class InputContactMessageContent extends InlineBaseObject 24 | { 25 | } 26 | -------------------------------------------------------------------------------- /src/Objects/MaskPosition.php: -------------------------------------------------------------------------------- 1 | User::class, 26 | 'location' => Location::class, 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/HttpClients/HttpClientInterface.php: -------------------------------------------------------------------------------- 1 | Sticker::class, 25 | 'thumb' => PhotoSize::class, 26 | ]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Objects/InlineKeyboard/LoginUrl.php: -------------------------------------------------------------------------------- 1 | 11 | * $params = [ 12 | * 'message_text' => '', 13 | * 'parse_mode' => '', 14 | * 'disable_web_page_preview' => '', 15 | * ]; 16 | * 17 | * 18 | * @method $this setMessageText($string) Text of the message to be sent, 1-4096 characters. 19 | * @method $this setParseMode($string) Optional. Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in your bot's message. 20 | * @method $this setDisableWebPagePreview($bool) Optional. Disables link previews for links in the sent message 21 | */ 22 | class InputTextMessageContent extends InlineBaseObject 23 | { 24 | } 25 | -------------------------------------------------------------------------------- /src/Objects/InlineQuery/InlineBaseObject.php: -------------------------------------------------------------------------------- 1 | put($property, $arguments[0]); 29 | 30 | return $this; 31 | } 32 | 33 | throw new BadMethodCallException("Method {$name} does not exist."); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Objects/Video.php: -------------------------------------------------------------------------------- 1 | PhotoSize::class, 26 | ]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Objects/VideoNote.php: -------------------------------------------------------------------------------- 1 | PhotoSize::class, 26 | ]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Commands/HelpCommand.php: -------------------------------------------------------------------------------- 1 | telegram->getCommands(); 31 | 32 | $text = ''; 33 | foreach ($commands as $name => $handler) { 34 | $text .= sprintf('/%s - %s' . PHP_EOL, $name, $handler->getDescription()); 35 | } 36 | 37 | $this->replyWithMessage(compact('text')); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Objects/Animation.php: -------------------------------------------------------------------------------- 1 | PhotoSize::class, 24 | ]; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Objects/Document.php: -------------------------------------------------------------------------------- 1 | PhotoSize::class, 26 | ]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Objects/InlineQuery/InlineQueryResultGame.php: -------------------------------------------------------------------------------- 1 | 9 | * $params = [ 10 | * 'id' => '', 11 | * 'game_short_name' => '', 12 | * 'reply_markup' => '', 13 | * ]; 14 | * 15 | * 16 | * @link https://core.telegram.org/bots/api#inlinequeryresultgame 17 | * 18 | * @method InlineQueryResultGame setId($string) Unique identifier for this result, 1-64 Bytes. 19 | * @method InlineQueryResultGame setGameShortName($string) Short name of the game. 20 | * @method InlineQueryResultGame setReplyMarkup($object) Optional. Inline keyboard attached to the message 21 | */ 22 | class InlineQueryResultGame extends InlineBaseObject 23 | { 24 | /** {@inheritdoc} */ 25 | public function __construct($params = []) 26 | { 27 | parent::__construct($params); 28 | $this->put('type', 'game'); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Objects/InlineKeyboard/CallbackGame.php: -------------------------------------------------------------------------------- 1 | /' to get the file. 14 | */ 15 | class File extends BaseObject 16 | { 17 | /** 18 | * {@inheritdoc} 19 | */ 20 | public function relations() 21 | { 22 | return []; 23 | } 24 | 25 | /** 26 | * @param string $token the bot token 27 | * 28 | * @return string the http url of the file 29 | */ 30 | public function getUrl($token) 31 | { 32 | return 'https://api.telegram.org/file/bot' . $token . '/' . $this->getFilePath(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Objects/PreCheckoutQuery.php: -------------------------------------------------------------------------------- 1 | User::class, 26 | 'order_info' => OrderInfo::class, 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Objects/SuccessfulPayment.php: -------------------------------------------------------------------------------- 1 | OrderInfo::class, 26 | ]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Objects/InputContent/InputVenueMessageContent.php: -------------------------------------------------------------------------------- 1 | 11 | * $params = [ 12 | * 'latitude' => '', 13 | * 'longitude' => '', 14 | * 'title' => '', 15 | * 'address' => '', 16 | * 'foursquare_id' => '', 17 | * ]; 18 | * 19 | * 20 | * @method $this setLatitude($float) Latitude of the location in degrees 21 | * @method $this setLongitude($float) Longitude of the location in degrees 22 | * @method $this setTitle($string) Name of the venue 23 | * @method $this setAddress($string) Address of the venue 24 | * @method $this setFoursquareIdTitle($string) Optional. Foursquare identifier of the venue, if known 25 | * @method $this setFoursquareType() Optional. Foursquare type of the venue. 26 | */ 27 | class InputVenueMessageContent extends InlineBaseObject 28 | { 29 | } 30 | -------------------------------------------------------------------------------- /src/Objects/WebhookInfo.php: -------------------------------------------------------------------------------- 1 | 9 | * $params = [ 10 | * 'id' => '', 11 | * 'sticker_file_id' => '', 12 | * 'reply_markup' => '', 13 | * 'input_message_content' => '', 14 | * ]; 15 | * 16 | * 17 | * @link https://core.telegram.org/bots/api#inlinequeryresultcachedsticker 18 | * 19 | * @method $this setId($string) Unique identifier for this result, 1-64 Bytes 20 | * @method $this setStickerFileId($string) A valid file identifier of the sticker 21 | * @method $this setReplyMarkup($object) Optional. Inline keyboard attached to the message 22 | * @method $this setInputMessageContent($object) Optional. Content of the message to be sent instead of the photo 23 | */ 24 | class InlineQueryResultCachedSticker extends InlineBaseObject 25 | { 26 | public function __construct($params = []) 27 | { 28 | parent::__construct($params); 29 | $this->put('type', 'sticker'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Objects/InlineQuery/InlineQueryResultCachedAudio.php: -------------------------------------------------------------------------------- 1 | 9 | * $params = [ 10 | * 'id' => '', 11 | * 'audio_file_id' => '', 12 | * 'reply_markup' => '', 13 | * 'input_message_content' => '', 14 | * ]; 15 | * 16 | * 17 | * @link https://core.telegram.org/bots/api#inlinequeryresultcachedaudio 18 | * 19 | * @method $this setId($string) Unique identifier for this result, 1-64 bytes 20 | * @method $this setAudioFileId($string) A valid file identifier for the audio file 21 | * @method $this setReplyMarkup($object) Optional. Inline keyboard attached to the message 22 | * @method $this setInputMessageContent($object) Optional. Content of the message to be sent instead of the photo 23 | */ 24 | class InlineQueryResultCachedAudio extends InlineBaseObject 25 | { 26 | public function __construct($params = []) 27 | { 28 | parent::__construct($params); 29 | $this->put('type', 'audio'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Objects/ChosenInlineResult.php: -------------------------------------------------------------------------------- 1 | User::class, 26 | 'location' => Location::class, 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Commands/CommandInterface.php: -------------------------------------------------------------------------------- 1 | PhotoSize::class, 30 | 'mask_position' => MaskPosition::class, 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Objects/Game.php: -------------------------------------------------------------------------------- 1 | PhotoSize::class, 28 | 'text_entities' => MessageEntity::class, 29 | 'animation' => Animation::class, 30 | ]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Keyboard/Button.php: -------------------------------------------------------------------------------- 1 | items['text'] = $text; 26 | 27 | return $this; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Objects/InlineQuery/InlineQueryResultCachedVoice.php: -------------------------------------------------------------------------------- 1 | 9 | * $params = [ 10 | * 'id' => '', 11 | * 'voice_file_id' => '', 12 | * 'title' => '', 13 | * 'caption' => '', 14 | * 'reply_markup' => '', 15 | * 'input_message_content' => '', 16 | * ]; 17 | * 18 | * 19 | * @link https://core.telegram.org/bots/api#inlinequeryresultcachedvoice 20 | * 21 | * @method $this setId($string) Unique identifier for this result, 1-64 bytes 22 | * @method $this setVoiceFileId($string) A valid file identifier for the voice message 23 | * @method $this setTitle($string) Voice message title 24 | * @method $this setCaption($string) Optional. Caption, 0-200 characters 25 | * @method $this setReplyMarkup($object) Optional. Inline keyboard attached to the message 26 | * @method $this setInputMessageContent($object) Optional. Content of the message to be sent instead of the photo 27 | */ 28 | class InlineQueryResultCachedVoice extends InlineBaseObject 29 | { 30 | public function __construct($params = []) 31 | { 32 | parent::__construct($params); 33 | $this->put('type', 'voice'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Objects/CallbackQuery.php: -------------------------------------------------------------------------------- 1 | User::class, 25 | 'message' => Message::class, 26 | ]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Objects/InlineQuery/InlineQueryResultCachedGif.php: -------------------------------------------------------------------------------- 1 | 9 | * $params = [ 10 | * 'id' => '', 11 | * 'gif_file_id' => '', 12 | * 'title' => '', 13 | * 'caption' => '', 14 | * 'reply_markup' => '', 15 | * 'input_message_content' => '', 16 | * ]; 17 | * 18 | * 19 | * @link https://core.telegram.org/bots/api#inlinequeryresultcachedgif 20 | * 21 | * @method $this setId($string) Unique identifier for this result, 1-64 bytes 22 | * @method $this setGifFileId($string) A valid file identifier for the GIF file 23 | * @method $this setTitle($string) Optional. Title for the result 24 | * @method $this setCaption($string) Optional. Caption of the GIF file to be sent, 0-200 characters 25 | * @method $this setReplyMarkup($object) Optional. Inline keyboard attached to the message 26 | * @method $this setInputMessageContent($object) Optional. Content of the message to be sent instead of the photo 27 | */ 28 | class InlineQueryResultCachedGif extends InlineBaseObject 29 | { 30 | public function __construct($params = []) 31 | { 32 | parent::__construct($params); 33 | $this->put('type', 'gif'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Objects/InlineQuery/InlineQueryResultCachedMpeg4Gif.php: -------------------------------------------------------------------------------- 1 | 9 | * $params = [ 10 | * 'id' => '', 11 | * 'mpeg4_file_id' => '', 12 | * 'title' => '', 13 | * 'caption' => '', 14 | * 'reply_markup' => '', 15 | * 'input_message_content' => '', 16 | * ]; 17 | * 18 | * 19 | * @link https://core.telegram.org/bots/api#inlinequeryresultcachedmpeg4gif 20 | * 21 | * @method $this setId($string) Unique identifier for this result, 1-64 bytes 22 | * @method $this setMpeg4FileId($string) A valid file identifier for the MP4 file 23 | * @method $this setTitle($string) Optional. Title for the result 24 | * @method $this setCaption($string) Optional. Caption of the MPEG-4 file to be sent, 0-200 characters 25 | * @method $this setReplyMarkup($object) Optional. Inline keyboard attached to the message 26 | * @method $this setInputMessageContent($object) Optional. Content of the message to be sent instead of the photo 27 | */ 28 | class InlineQueryResultCachedMpeg4Gif extends InlineBaseObject 29 | { 30 | public function __construct($params = []) 31 | { 32 | parent::__construct($params); 33 | $this->put('type', 'mpeg4_gif'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Actions.php: -------------------------------------------------------------------------------- 1 | 9 | * $params = [ 10 | * 'id' => '', 11 | * 'voice_url' => '', 12 | * 'title' => '', 13 | * 'caption' => '', 14 | * 'voice_duration' => '', 15 | * 'reply_markup' => '', 16 | * 'input_message_content' => '', 17 | * ]; 18 | * 19 | * 20 | * @link https://core.telegram.org/bots/api#inlinequeryresultvoice 21 | * 22 | * @method $this setId($string) Unique identifier for this result, 1-64 bytes 23 | * @method $this setVoiceUrl($string) A valid URL for the voice recording 24 | * @method $this setTitle($string) Voice message title 25 | * @method $this setCaption($string) Optional. Caption, 0-200 characters 26 | * @method $this setVoiceDuration($int) Optional. Recording duration in seconds 27 | * @method $this setReplyMarkup($object) Optional. Inline keyboard attached to the message 28 | * @method $this setInputMessageContent($object) Optional. Content of the message to be sent instead of the photo 29 | */ 30 | class InlineQueryResultVoice extends InlineBaseObject 31 | { 32 | public function __construct($params = []) 33 | { 34 | parent::__construct($params); 35 | $this->put('type', 'voice'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Objects/Chat/ChatPermissions.php: -------------------------------------------------------------------------------- 1 | 9 | * $params = [ 10 | * 'id' => '', 11 | * 'photo_file_id' => '', 12 | * 'title' => '', 13 | * 'description' => '', 14 | * 'caption' => '', 15 | * 'reply_markup' => '', 16 | * 'input_message_content' => '', 17 | * ]; 18 | * 19 | * 20 | * @link https://core.telegram.org/bots/api#inlinequeryresultcachedphoto 21 | * 22 | * @method $this setId($string) Unique identifier for this result, 1-64 Bytes 23 | * @method $this setPhotoFileId($string) A valid file identifier of the photo 24 | * @method $this setTitle($string) Optional. Title for the result 25 | * @method $this setDescription($string) Optional. Short description of the result 26 | * @method $this setCaption($string) Optional. Caption of the photo to be sent, 0-200 characters 27 | * @method $this setReplyMarkup($object) Optional. Inline keyboard attached to the message 28 | * @method $this setInputMessageContent($object) Optional. Content of the message to be sent instead of the photo 29 | */ 30 | class InlineQueryResultCachedPhoto extends InlineBaseObject 31 | { 32 | public function __construct($params = []) 33 | { 34 | parent::__construct($params); 35 | $this->put('type', 'photo'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015-16, Syed Irfaq R. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of test nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /src/Objects/InlineQuery/InlineQueryResultCachedVideo.php: -------------------------------------------------------------------------------- 1 | 9 | * $params = [ 10 | * 'id' => '', 11 | * 'video_file_id => '', 12 | * 'title' => '', 13 | * 'description' => '', 14 | * 'caption' => '', 15 | * 'reply_markup' => '', 16 | * 'input_message_content' => '', 17 | * ]; 18 | * 19 | * 20 | * @link https://core.telegram.org/bots/api#inlinequeryresultcachedvideo 21 | * 22 | * @method $this setId($string) Unique identifier for this result, 1-64 bytes 23 | * @method $this setVideoFileId($string) A valid file identifier for the video file 24 | * @method $this setTitle($string) Title for the result 25 | * @method $this setDescription($string) Optional. Short description of the result 26 | * @method $this setCaption($string) Optional. Caption of the video to be sent, 0-200 characters 27 | * @method $this setReplyMarkup($object) Optional. Inline keyboard attached to the message 28 | * @method $this setInputMessageContent($object) Optional. Content of the message to be sent instead of the photo 29 | */ 30 | class InlineQueryResultCachedVideo extends InlineBaseObject 31 | { 32 | public function __construct($params = []) 33 | { 34 | parent::__construct($params); 35 | $this->put('type', 'video'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Objects/InlineQuery/InlineQueryResultCachedDocument.php: -------------------------------------------------------------------------------- 1 | 9 | * $params = [ 10 | * 'id' => '', 11 | * 'title' => '', 12 | * 'document_file_id' => '', 13 | * 'description' => '', 14 | * 'caption' => '', 15 | * 'reply_markup' => '', 16 | * 'input_message_content' => '', 17 | * ]; 18 | * 19 | * 20 | * @link https://core.telegram.org/bots/api#inlinequeryresultcacheddocument 21 | * 22 | * @method $this setId($string) Unique identifier for this result, 1-64 bytes 23 | * @method $this setTitle($string) Title for the result 24 | * @method $this setDocumentFileId($string) A valid file identifier for the file 25 | * @method $this setDescription($string) Optional. Short description of the result 26 | * @method $this setCaption($string) Optional. Caption of the document to be sent, 0-200 characters 27 | * @method $this setReplyMarkup($object) Optional. Inline keyboard attached to the message 28 | * @method $this setInputMessageContent($object) Optional. Content of the message to be sent instead of the file 29 | */ 30 | class InlineQueryResultCachedDocument extends InlineBaseObject 31 | { 32 | public function __construct($params = []) 33 | { 34 | parent::__construct($params); 35 | $this->put('type', 'document'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Objects/InlineKeyboard/InlineKeyboardButton.php: -------------------------------------------------------------------------------- 1 | LoginUrl::class, 33 | 'callback_game' => CallbackGame::class, 34 | ]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Objects/InlineQuery/InlineQueryResultAudio.php: -------------------------------------------------------------------------------- 1 | 9 | * $params = [ 10 | * 'id' => '', 11 | * 'audio_url' => '', 12 | * 'title' => '', 13 | * 'caption' => '', 14 | * 'performer' => '', 15 | * 'audio_duration' => '', 16 | * 'reply_markup' => '', 17 | * 'input_message_content' => '', 18 | * ]; 19 | * 20 | * 21 | * @link https://core.telegram.org/bots/api#inlinequeryresultaudio 22 | * 23 | * @method $this setId($string) Unique identifier for this result, 1-64 bytes 24 | * @method $this setAudioUrl($string) A valid URL for the audio file 25 | * @method $this setTitle($string) Title 26 | * @method $this setCaption($string) Optional. Caption, 0-200 characters 27 | * @method $this setPerformer($string) Optional. Performer 28 | * @method $this setAudioDuration($int) Optional. Audio duration in seconds 29 | * @method $this setReplyMarkup($object) Optional. Inline keyboard attached to the message 30 | * @method $this setInputMessageContent($object) Optional. Content of the message to be sent instead of the photo 31 | */ 32 | class InlineQueryResultAudio extends InlineBaseObject 33 | { 34 | public function __construct($params = []) 35 | { 36 | parent::__construct($params); 37 | $this->put('type', 'audio'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Objects/InlineQuery/InlineQueryResultLocation.php: -------------------------------------------------------------------------------- 1 | 9 | * $params = [ 10 | * 'id' => '', 11 | * 'latitude' => '', 12 | * 'longitude' => '', 13 | * 'title' => '', 14 | * 'reply_markup' => '', 15 | * 'input_message_content' => '', 16 | * 'thumb_url' => '', 17 | * 'thumb_width' => '', 18 | * 'thumb_height' => '', 19 | * ]; 20 | * 21 | * 22 | * @link https://core.telegram.org/bots/api#inlinequeryresultlocation 23 | * 24 | * @method $this setId($string) Unique identifier for this result, 1-64 Bytes 25 | * @method $this setLatitude($float) Location latitude in degrees 26 | * @method $this setLongitude($float) Location longitude in degrees 27 | * @method $this setTitle($string) Location title 28 | * @method $this setReplyMarkup($object) Optional. Inline keyboard attached to the message 29 | * @method $this setInputMessageContent($object) Optional. Content of the message to be sent instead of the location 30 | * @method $this setThumbUrl($string) Optional. Url of the thumbnail for the result 31 | * @method $this setThumbWidth($int) Optional. Thumbnail width 32 | * @method $this setThumbHeight($int) Optional. Thumbnail height */ 33 | class InlineQueryResultLocation extends InlineBaseObject 34 | { 35 | public function __construct($params = []) 36 | { 37 | parent::__construct($params); 38 | $this->put('type', 'location'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/FileUpload/InputFile.php: -------------------------------------------------------------------------------- 1 | path = $filePath; 33 | } 34 | 35 | /** 36 | * Return the name of the file. 37 | * 38 | * @return string 39 | */ 40 | public function getFileName() 41 | { 42 | return basename($this->path); 43 | } 44 | 45 | /** 46 | * Opens file stream. 47 | * 48 | * @throws TelegramSDKException 49 | * 50 | * @return resource 51 | */ 52 | public function open() 53 | { 54 | if (is_resource($this->path)) { 55 | return $this->path; 56 | } 57 | 58 | if (!$this->isRemoteFile() && !is_readable($this->path)) { 59 | throw new TelegramSDKException('Failed to create InputFile entity. Unable to read resource: ' . $this->path . '.'); 60 | } 61 | 62 | return Psr7\try_fopen($this->path, 'r'); 63 | } 64 | 65 | /** 66 | * Returns true if the path to the file is remote. 67 | * 68 | * @return bool 69 | */ 70 | protected function isRemoteFile() 71 | { 72 | return preg_match('/^(https?|ftp):\/\/.*/', $this->path) === 1; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/Callbacks/CallbackCommandInterface.php: -------------------------------------------------------------------------------- 1 | 5 | * 6 | * @link http://exileed.com 7 | */ 8 | 9 | namespace Telegram\Bot\Callbacks; 10 | 11 | use Telegram\Bot\Api as Telegram; 12 | use Telegram\Bot\Objects\CallbackQuery; 13 | use Telegram\Bot\Objects\Update; 14 | 15 | /** 16 | * Interface CallbackQueryInterface. 17 | */ 18 | interface CallbackCommandInterface 19 | { 20 | /** 21 | * @return array 22 | */ 23 | public function getArguments(); 24 | /** 25 | * @param array $arguments 26 | * 27 | * @return CallbackCommand 28 | */ 29 | public function setArguments($arguments); 30 | /** 31 | * Get Callback Query Command Name. 32 | * 33 | * The name of the Telegram callback query command. 34 | * 35 | * @return string 36 | */ 37 | public function getName(); 38 | /** 39 | * Set Callback Query Command Name. 40 | * 41 | * @param string $name 42 | * 43 | * @return CallbackCommand 44 | */ 45 | public function setName($name); 46 | /** 47 | * Unique identifier for the query to be answered. 48 | * 49 | * @return int 50 | */ 51 | public function getCallbackQueryId(); 52 | /** 53 | * Unique identifier for the query to be answered. 54 | * 55 | * @param int $callbackQueryId 56 | * 57 | * @return CallbackCommand 58 | */ 59 | public function setCallbackQueryId($callbackQueryId); 60 | /** 61 | * Make command. 62 | * 63 | * @param Telegram $telegram 64 | * @param array $arguments 65 | * @param Update $update 66 | * @param CallbackQuery $callbackQuery 67 | * 68 | * @return 69 | */ 70 | public function make(Telegram $telegram, $arguments, Update $update, CallbackQuery $callbackQuery); 71 | } 72 | -------------------------------------------------------------------------------- /src/Objects/Poll.php: -------------------------------------------------------------------------------- 1 | PollOption::class, 37 | 'explanation_entities' => MessageEntity::class, 38 | ]; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Objects/InlineQuery/InlineQueryResultContact.php: -------------------------------------------------------------------------------- 1 | 9 | * $params = [ 10 | * 'id' => '', 11 | * 'phone_number' => '', 12 | * 'first_name' => '', 13 | * 'last_name' => '', 14 | * 'reply_markup' => '', 15 | * 'input_message_content' => '', 16 | * 'thumb_url' => '', 17 | * 'thumb_width' => '', 18 | * 'thumb_height' => '', 19 | * ]; 20 | * 21 | * 22 | * @link https://core.telegram.org/bots/api#inlinequeryresultcontact 23 | * 24 | * @method $this setId($string) Unique identifier for this result, 1-64 Bytes 25 | * @method $this setPhoneNumber($string) Contact's phone number 26 | * @method $this setFirstName($string) Contact's first name 27 | * @method $this setLastName($string) Optional. Contact's last name 28 | * @method $this setReplyMarkup($object) Optional. Inline keyboard attached to the message 29 | * @method $this setInputMessageContent($object) Optional. Content of the message to be sent instead of the contact 30 | * @method $this setThumbUrl($string) Optional. Url of the thumbnail for the result 31 | * @method $this setThumbWidth($int) Optional. Thumbnail width 32 | * @method $this setThumbHeight($int) Optional. Thumbnail height 33 | * @method $this setVcard() Optional. Additional data about the contact in the form of a vCard. 34 | */ 35 | class InlineQueryResultContact extends InlineBaseObject 36 | { 37 | public function __construct($params = []) 38 | { 39 | parent::__construct($params); 40 | $this->put('type', 'contact'); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Objects/InlineQuery/InlineQueryResultArticle.php: -------------------------------------------------------------------------------- 1 | 9 | * $params = [ 10 | * 'id' => '', 11 | * 'title' => '', 12 | * 'input_message_content' => '', 13 | * 'reply_markup' => '', 14 | * 'url' => '', 15 | * 'hide_url' => '', 16 | * 'description' => '', 17 | * 'thumb_url' => '', 18 | * 'thumb_width' => '', 19 | * 'thumb_height' => '', 20 | * ]; 21 | * 22 | * 23 | * @link https://core.telegram.org/bots/api#inlinequeryresultarticle 24 | * 25 | * @method $this setId($string) Unique identifier for this result, 1-64 Bytes 26 | * @method $this setTitle($string) Title of the result 27 | * @method $this setInputMessageContent($object) Content of the message to be sent. 28 | * @method $this setReplyMarkup($object) Optional. Inline keyboard attached to the message 29 | * @method $this setUrl($string) Optional. URL of the result 30 | * @method $this setHideUrl($bool) Optional. Pass True, if you don't want the URL to be shown in the message 31 | * @method $this setDescription($string) Optional. Short description of the result 32 | * @method $this setThumbUrl($string) Optional. Url of the thumbnail for the result 33 | * @method $this setThumbWidth($int) Optional. Thumbnail width 34 | * @method $this setThumbHeight($int) Optional. Thumbnail height 35 | */ 36 | class InlineQueryResultArticle extends InlineBaseObject 37 | { 38 | /** {@inheritdoc} */ 39 | public function __construct($params = []) 40 | { 41 | parent::__construct($params); 42 | $this->put('type', 'article'); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "exileed/telegram-bot-api", 3 | "description": "The Telegram Bot API PHP", 4 | "keywords": ["telegram", "telegram bot", "telegram bot api", "telegram sdk", "telegram php", "laravel telegram", "laravel"], 5 | "type": "library", 6 | "homepage": "https://github.com/exileed/telegram-bot-sdk", 7 | "license": "BSD-3-Clause", 8 | "authors": [ 9 | { 10 | "name": "Syed Irfaq R.", 11 | "email": "syed+gh@lukonet.com", 12 | "homepage": "https://github.com/irazasyed" 13 | }, 14 | { 15 | "name": "Dmitriy Kuts (ExileeD)", 16 | "email": "me@exileed.com", 17 | "homepage": "https://exileed.com" 18 | } 19 | ], 20 | "require": { 21 | "php": "~7.3 || ~8.0", 22 | "ext-json": "*", 23 | "guzzlehttp/guzzle": "~6.0 || ^7.0", 24 | "illuminate/support": "^5.0 || ^6.0 || ^7.0 || ^8.0", 25 | "league/event": "^2.1" 26 | }, 27 | "require-dev": { 28 | "phpunit/phpunit": "^9.0", 29 | "squizlabs/php_codesniffer": "^3.5" 30 | }, 31 | "autoload": { 32 | "psr-4": { 33 | "Telegram\\Bot\\": "src/" 34 | } 35 | }, 36 | "autoload-dev": { 37 | "psr-4": { 38 | "Telegram\\Bot\\Tests\\": "tests/" 39 | } 40 | }, 41 | "suggest": { 42 | "illuminate/container": "Hold dependencies to be injected in commands constructors" 43 | }, 44 | "scripts": { 45 | "test": "phpunit", 46 | "fix": "phpcbf", 47 | "phpcs": "phpcs" 48 | }, 49 | "extra": { 50 | "branch-alias": { 51 | "dev-master": "0.3-dev", 52 | "dev-develop": "0.3-dev" 53 | }, 54 | "laravel": { 55 | "providers": [ 56 | "Telegram\\Bot\\Laravel\\TelegramServiceProvider" 57 | ], 58 | "aliases": { 59 | "Telegram": "Telegram\\Bot\\Laravel\\Facades\\Telegram" 60 | } 61 | } 62 | }, 63 | "config": { 64 | "preferred-install": "dist" 65 | }, 66 | "minimum-stability": "dev", 67 | "prefer-stable": true 68 | } 69 | -------------------------------------------------------------------------------- /src/Objects/InlineQuery/InlineQueryResultPhoto.php: -------------------------------------------------------------------------------- 1 | 9 | * $params = [ 10 | * 'id' => '', 11 | * 'photo_url' => '', 12 | * 'thumb_url' => '', 13 | * 'photo_width' => '', 14 | * 'photo_height' => '', 15 | * 'title' => '', 16 | * 'description' => '', 17 | * 'caption' => '', 18 | * 'reply_markup' => '', 19 | * 'input_message_content' => '', 20 | * ]; 21 | * 22 | * 23 | * @link https://core.telegram.org/bots/api#inlinequeryresultphoto 24 | * 25 | * @method $this setId($string) Unique identifier for this result, 1-64 Bytes 26 | * @method $this setPhotoUrl($string) A valid URL of the photo. Photo must be in jpeg format. Photo size must not exceed 5MB 27 | * @method $this setThumbUrl($string) URL of the thumbnail for the photo 28 | * @method $this setPhotoWidth($int) Optional. Width of the photo 29 | * @method $this setPhotoHeight($int) Optional. Height of the photo 30 | * @method $this setTitle($string) Optional. Title for the result 31 | * @method $this setDescription($string) Optional. Short description of the result 32 | * @method $this setCaption($string) Optional. Caption of the photo to be sent, 0-200 characters 33 | * @method $this setReplyMarkup($object) Optional. Inline keyboard attached to the message 34 | * @method $this setInputMessageContent($object) Optional. Content of the message to be sent instead of the photo 35 | */ 36 | class InlineQueryResultPhoto extends InlineBaseObject 37 | { 38 | public function __construct($params = []) 39 | { 40 | parent::__construct($params); 41 | $this->put('type', 'photo'); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Objects/InlineQuery/InlineQueryResultGif.php: -------------------------------------------------------------------------------- 1 | 9 | * $params = [ 10 | * 'id' => '', 11 | * 'gif_url' => '', 12 | * 'gif_width' => '', 13 | * 'gif_height' => '', 14 | * 'gif_duration' => '', 15 | * 'thumb_url' => '', 16 | * 'title' => '', 17 | * 'caption' => '', 18 | * 'reply_markup' => '', 19 | * 'input_message_content' => '', 20 | * ]; 21 | * 22 | * 23 | * @link https://core.telegram.org/bots/api#inlinequeryresultgif 24 | * 25 | * @method $this setId($string) Unique identifier for this result, 1-64 bytes 26 | * @method $this setGifUrl($string) A valid URL for the GIF file. File size must not exceed 1MB 27 | * @method $this setGifWidth($int) Optional. Width of the GIF 28 | * @method $this setGifHeight($int) Optional. Height of the GIF 29 | * @method $this setGifDuration($int) Optional. Duration of the GIF 30 | * @method $this setThumbUrl($string) URL of the static thumbnail for the result (jpeg or gif) 31 | * @method $this setTitle($string) Optional. Title for the result 32 | * @method $this setCaption($string) Optional. Caption of the GIF file to be sent, 0-200 characters 33 | * @method $this setReplyMarkup($object) Optional. Inline keyboard attached to the message 34 | * @method $this setInputMessageContent($object) Optional. Content of the message to be sent instead of the photo 35 | */ 36 | class InlineQueryResultGif extends InlineBaseObject 37 | { 38 | public function __construct($params = []) 39 | { 40 | parent::__construct($params); 41 | $this->put('type', 'gif'); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Objects/InlineQuery/InlineQueryResultMpeg4Gif.php: -------------------------------------------------------------------------------- 1 | 9 | * $params = [ 10 | * 'id' => '', 11 | * 'mpeg4_url' => '', 12 | * 'mpeg4_width' => '', 13 | * 'mpeg4_height' => '', 14 | * 'mpeg4_duration' => '', 15 | * 'thumb_url' => '', 16 | * 'title' => '', 17 | * 'caption' => '', 18 | * 'reply_markup' => '', 19 | * 'input_message_content' => '', 20 | * ]; 21 | * 22 | * 23 | * @link https://core.telegram.org/bots/api#inlinequeryresultmpeg4gif 24 | * 25 | * @method $this setId($string) Unique identifier for this result, 1-64 bytes 26 | * @method $this setMpeg4Url($string) A valid URL for the MP4 file. File size must not exceed 1MB 27 | * @method $this setMpeg4Width($int) Optional. Video width 28 | * @method $this setMpeg4Height($int) Optional. Video height 29 | * @method $this setMpeg4Duration($int) Optional. Video duration 30 | * @method $this setThumbUrl($string) URL of the static thumbnail (jpeg or gif) for the result 31 | * @method $this setTitle($string) Optional. Title for the result 32 | * @method $this setCaption($string) Optional. Caption of the MPEG-4 file to be sent, 0-200 characters 33 | * @method $this setReplyMarkup($object) Optional. Inline keyboard attached to the message 34 | * @method $this setInputMessageContent($object) Optional. Content of the message to be sent instead of the photo 35 | */ 36 | class InlineQueryResultMpeg4Gif extends InlineBaseObject 37 | { 38 | /** {@inheritdoc} */ 39 | public function __construct($params = []) 40 | { 41 | parent::__construct($params); 42 | $this->put('type', 'mpeg4_gif'); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Objects/Passport/EncryptedPassportElement.php: -------------------------------------------------------------------------------- 1 | PassportFile::class, 32 | 'reverse_side' => PassportFile::class, 33 | 'selfie' => PassportFile::class, 34 | ]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Objects/InlineQuery/InlineQueryResultVenue.php: -------------------------------------------------------------------------------- 1 | 9 | * $params = [ 10 | * 'id' => '', 11 | * 'latitude' => '', 12 | * 'longitude' => '', 13 | * 'title' => '', 14 | * 'address' => '', 15 | * 'foursquare_id' => '', 16 | * 'reply_markup' => '', 17 | * 'input_message_content' => '', 18 | * 'thumb_url' => '', 19 | * 'thumb_width' => '', 20 | * 'thumb_height' => '', 21 | * ]; 22 | * 23 | * 24 | * @link https://core.telegram.org/bots/api#inlinequeryresultvenue 25 | * 26 | * @method $this setId($string) Unique identifier for this result, 1-64 Bytes 27 | * @method $this setLatitude($float) Latitude of the venue location in degrees 28 | * @method $this setLongitude($float) Longitude of the venue location in degrees 29 | * @method $this setTitle($string) Title of the venue 30 | * @method $this setAddress($string) Address of the venue 31 | * @method $this setFoursquareId($string) Optional. Foursquare identifier of the venue if known 32 | * @method $this setFoursquareType() Optional. Foursquare type of the venue. 33 | * @method $this setReplyMarkup($object) Optional. Inline keyboard attached to the message 34 | * @method $this setInputMessageContent($object) Optional. Content of the message to be sent instead of the venue 35 | * @method $this setThumbUrl($string) Optional. Url of the thumbnail for the result 36 | * @method $this setThumbWidth($int) Optional. Thumbnail width 37 | * @method $this setThumbHeight($int) Optional. Thumbnail height 38 | */ 39 | class InlineQueryResultVenue extends InlineBaseObject 40 | { 41 | public function __construct($params = []) 42 | { 43 | parent::__construct($params); 44 | $this->put('type', 'venue'); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Objects/InlineQuery/InlineQueryResultDocument.php: -------------------------------------------------------------------------------- 1 | 9 | * $params = [ 10 | * 'id' => '', 11 | * 'title' => '', 12 | * 'caption' => '', 13 | * 'document_url' => '', 14 | * 'mime_type' => '', 15 | * 'description' => '', 16 | * 'reply_markup' => '', 17 | * 'input_message_content' => '', 18 | * 'thumb_url' => '', 19 | * 'thumb_width' => '', 20 | * 'thumb_height' => '', 21 | * ]; 22 | * 23 | * 24 | * @link https://core.telegram.org/bots/api#inlinequeryresultdocument 25 | * 26 | * @method $this setId($string) Unique identifier for this result, 1-64 bytes 27 | * @method $this setTitle($string) Title for the result 28 | * @method $this setCaption($string) Optional. Caption of the document to be sent, 0-200 characters 29 | * @method $this setDocumentUrl($string) A valid URL for the file 30 | * @method $this setMimeType($string) Mime type of the content of the file, either “application/pdf” or “application/zip” 31 | * @method $this setDescription($string) Optional. Short description of the result 32 | * @method $this setReplyMarkup($object) Optional. Inline keyboard attached to the message 33 | * @method $this setInputMessageContent($object) Optional. Content of the message to be sent instead of the file 34 | * @method $this setThumbUrl($string) Optional. URL of the thumbnail (jpeg only) for the file 35 | * @method $this setThumbWidth($int) Optional. Thumbnail width 36 | * @method $this setThumbHeight($int) Optional. Thumbnail height */ 37 | class InlineQueryResultDocument extends InlineBaseObject 38 | { 39 | /** {@inheritdoc} */ 40 | public function __construct($params = []) 41 | { 42 | parent::__construct($params); 43 | $this->put('type', 'document'); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Objects/InlineQuery/InlineQueryResultVideo.php: -------------------------------------------------------------------------------- 1 | 9 | * $params = [ 10 | * 'id' => '', 11 | * 'video_url' => '', 12 | * 'mime_type' => '', 13 | * 'thumb_url' => '', 14 | * 'title' => '', 15 | * 'caption' => '', 16 | * 'video_width' => '', 17 | * 'video_height' => '', 18 | * 'video_duration' => '', 19 | * 'description' => '', 20 | * 'reply_markup' => '', 21 | * 'input_message_content' => '', 22 | * ]; 23 | * 24 | * 25 | * @link https://core.telegram.org/bots/api#inlinequeryresultvideo 26 | * 27 | * @method $this setId($string) Unique identifier for this result, 1-64 bytes 28 | * @method $this setVideoUrl($string) A valid URL for the embedded video player or video file 29 | * @method $this setMimeType($string) Mime type of the content of video url, “text/html” or “video/mp4” 30 | * @method $this setThumbUrl($string) URL of the thumbnail (jpeg only) for the video 31 | * @method $this setTitle($string) Title for the result 32 | * @method $this setCaption($string) Optional. Caption of the video to be sent, 0-200 characters 33 | * @method $this setVideoWidth($int) Optional. Video width 34 | * @method $this setVideoHeight($int) Optional. Video height 35 | * @method $this setVideoDuration($int) Optional. Video duration in seconds 36 | * @method $this setDescription($string) Optional. Short description of the result 37 | * @method $this setReplyMarkup($object) Optional. Inline keyboard attached to the message 38 | * @method $this setInputMessageContent($object) Optional. Content of the message to be sent instead of the photo 39 | */ 40 | class InlineQueryResultVideo extends InlineBaseObject 41 | { 42 | public function __construct($params = []) 43 | { 44 | parent::__construct($params); 45 | $this->put('type', 'video'); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Answers/AnswerBus.php: -------------------------------------------------------------------------------- 1 | telegram; 42 | } 43 | 44 | /** 45 | * Use PHP Reflection and Laravel Container to instantiate the answer with type hinted dependencies. 46 | * 47 | * @param $answerClass 48 | * 49 | * @return object 50 | */ 51 | protected function buildDependencyInjectedAnswer($answerClass) 52 | { 53 | // check if the command has a constructor 54 | if (!method_exists($answerClass, '__construct')) { 55 | return new $answerClass(); 56 | } 57 | 58 | // get constructor params 59 | $constructorReflector = new \ReflectionMethod($answerClass, '__construct'); 60 | $params = $constructorReflector->getParameters(); 61 | 62 | // if no params are needed proceed with normal instantiation 63 | if (empty($params)) { 64 | return new $answerClass(); 65 | } 66 | 67 | // otherwise fetch each dependency out of the container 68 | $container = $this->telegram->getContainer(); 69 | $dependencies = []; 70 | foreach ($params as $param) { 71 | $dependencies[] = $container->make($param->getClass()->name); 72 | } 73 | 74 | // and instantiate the object with dependencies through ReflectionClass 75 | $classReflector = new \ReflectionClass($answerClass); 76 | 77 | return $classReflector->newInstanceArgs($dependencies); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Objects/Chat.php: -------------------------------------------------------------------------------- 1 | ChatPhoto::class, 39 | 'pinned_message' => Message::class, 40 | 'permissions' => ChatPermissions::class 41 | ]; 42 | } 43 | 44 | /** 45 | * Check if this is a private chat. 46 | * 47 | * @return bool 48 | */ 49 | public function isPrivate() 50 | { 51 | return $this->getType() === 'private'; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Laravel/TelegramServiceProvider.php: -------------------------------------------------------------------------------- 1 | setupConfig($this->app); 33 | } 34 | 35 | /** 36 | * Setup the config. 37 | * 38 | * @param \Illuminate\Contracts\Container\Container $app 39 | * 40 | * @return void 41 | */ 42 | protected function setupConfig(Application $app) 43 | { 44 | $source = __DIR__ . '/config/telegram.php'; 45 | 46 | if ($app instanceof LaravelApplication && $app->runningInConsole()) { 47 | $this->publishes([$source => config_path('telegram.php')]); 48 | } elseif ($app instanceof LumenApplication) { 49 | $app->configure('telegram'); 50 | } 51 | 52 | $this->mergeConfigFrom($source, 'telegram'); 53 | } 54 | 55 | /** 56 | * Register the service provider. 57 | * 58 | * @return void 59 | */ 60 | public function register() 61 | { 62 | $this->registerManager($this->app); 63 | $this->registerBindings($this->app); 64 | } 65 | 66 | /** 67 | * Register the manager class. 68 | * 69 | * @param \Illuminate\Contracts\Container\Container $app 70 | * 71 | * @return void 72 | */ 73 | protected function registerManager(Application $app) 74 | { 75 | $app->singleton( 76 | 'telegram', 77 | function ($app) { 78 | $config = (array)$app[ 'config' ][ 'telegram' ]; 79 | 80 | return (new BotsManager($config))->setContainer($app); 81 | } 82 | ); 83 | 84 | $app->alias('telegram', BotsManager::class); 85 | } 86 | 87 | /** 88 | * Register the bindings. 89 | * 90 | * @param \Illuminate\Contracts\Container\Container $app 91 | * 92 | * @return void 93 | */ 94 | protected function registerBindings(Application $app) 95 | { 96 | $app->bind( 97 | 'telegram.bot', 98 | function ($app) { 99 | $manager = $app[ 'telegram' ]; 100 | 101 | return $manager->bot(); 102 | } 103 | ); 104 | 105 | $app->alias('telegram.bot', Api::class); 106 | } 107 | 108 | /** 109 | * Get the services provided by the provider. 110 | * 111 | * @return array 112 | */ 113 | public function provides() 114 | { 115 | return ['telegram', 'telegram.bot', BotsManager::class, Api::class]; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/Answers/Answerable.php: -------------------------------------------------------------------------------- 1 | telegram, $methodName)) { 50 | throw new \BadMethodCallException("Method [$method] does not exist."); 51 | } 52 | 53 | if (null === $chat = $this->update->getChat()) { 54 | throw new \BadMethodCallException("No chat available for reply with [$method]."); 55 | } 56 | 57 | $chat_id = $chat->getId(); 58 | 59 | $params = array_merge(compact('chat_id'), $arguments[0]); 60 | 61 | return call_user_func_array([$this->telegram, $methodName], [$params]); 62 | } 63 | 64 | throw new \BadMethodCallException("Method [$method] does not exist."); 65 | } 66 | 67 | /** 68 | * @return Api 69 | */ 70 | public function getTelegram() 71 | { 72 | return $this->telegram; 73 | } 74 | 75 | /** 76 | * @return Update 77 | */ 78 | public function getUpdate() 79 | { 80 | return $this->update; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/Objects/ChatMember.php: -------------------------------------------------------------------------------- 1 | User::class, 38 | ]; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Callbacks/CallbackCommand.php: -------------------------------------------------------------------------------- 1 | 5 | * 6 | * @link http://exileed.com 7 | */ 8 | 9 | namespace Telegram\Bot\Callbacks; 10 | 11 | use Telegram\Bot\Answers\Answerable; 12 | use Telegram\Bot\Api as Telegram; 13 | use Telegram\Bot\Objects\CallbackQuery; 14 | use Telegram\Bot\Objects\Update; 15 | 16 | /** 17 | * Class CallbackCommand. 18 | */ 19 | abstract class CallbackCommand implements CallbackCommandInterface 20 | { 21 | use Answerable; 22 | 23 | /** 24 | * The name of the Telegram callback query command. 25 | * 26 | * @var string 27 | */ 28 | protected $name; 29 | /** 30 | * Unique identifier for the query to be answered. 31 | * 32 | * @var int 33 | */ 34 | protected $callbackQueryId; 35 | /** 36 | * Arguments passed to the command. 37 | * 38 | * @var array 39 | */ 40 | protected $arguments = []; 41 | /** 42 | * This object represents an incoming callback query from a callback button in an inline keyboard. 43 | * 44 | * @var CallbackQuery 45 | */ 46 | protected $callbackQuery; 47 | /** 48 | * @return array 49 | */ 50 | public function getArguments() 51 | { 52 | return $this->arguments; 53 | } 54 | 55 | /** 56 | * @param array $arguments 57 | * 58 | * @return $this 59 | */ 60 | public function setArguments($arguments) 61 | { 62 | $this->arguments = $arguments; 63 | return $this; 64 | } 65 | 66 | /** 67 | * Get Callback Query Command Name. 68 | * 69 | * The name of the Telegram callback query command. 70 | * 71 | * @return string 72 | */ 73 | public function getName() 74 | { 75 | return $this->name; 76 | } 77 | 78 | /** 79 | * Set Callback Query Command Name. 80 | * 81 | * @param string $name 82 | * 83 | * @return $this 84 | */ 85 | public function setName($name) 86 | { 87 | $this->name = $name; 88 | return $this; 89 | } 90 | 91 | /** 92 | * Unique identifier for the query to be answered. 93 | * 94 | * @return int 95 | */ 96 | public function getCallbackQueryId() 97 | { 98 | return $this->callbackQueryId; 99 | } 100 | 101 | /** 102 | * Unique identifier for the query to be answered. 103 | * 104 | * @param int $callbackQueryId 105 | * 106 | * @return $this 107 | */ 108 | public function setCallbackQueryId($callbackQueryId) 109 | { 110 | $this->callbackQueryId = $callbackQueryId; 111 | return $this; 112 | } 113 | 114 | /** 115 | * @param Telegram $telegram 116 | * @param array $arguments 117 | * @param Update $update 118 | * @param CallbackQuery $callbackQuery 119 | */ 120 | public function make(Telegram $telegram, $arguments, Update $update, CallbackQuery $callbackQuery) 121 | { 122 | $this->telegram = $telegram; 123 | $this->arguments = $arguments; 124 | $this->update = $update; 125 | $this->callbackQuery = $callbackQuery; 126 | $this->callbackQueryId = $callbackQuery->getId(); 127 | $this->handle($arguments); 128 | } 129 | 130 | /** 131 | * {@inheritdoc} 132 | */ 133 | abstract public function handle($arguments); 134 | } 135 | -------------------------------------------------------------------------------- /src/Objects/BaseObject.php: -------------------------------------------------------------------------------- 1 | getRawResult($data)); 22 | 23 | $this->mapRelatives(); 24 | } 25 | 26 | /** 27 | * Property relations. 28 | * 29 | * @return array 30 | */ 31 | abstract public function relations(); 32 | 33 | /** 34 | * Get an item from the collection by key. 35 | * 36 | * @param mixed $key 37 | * @param mixed $default 38 | * 39 | * @return mixed|static 40 | */ 41 | public function get($key, $default = null) 42 | { 43 | if ($this->offsetExists($key)) { 44 | return is_array($this->items[$key]) ? new static($this->items[$key]) : $this->items[$key]; 45 | } 46 | 47 | return value($default); 48 | } 49 | 50 | /** 51 | * Map property relatives to appropriate objects. 52 | * 53 | * @return array|bool 54 | */ 55 | public function mapRelatives() 56 | { 57 | $relations = collect($this->relations()); 58 | 59 | if ($relations->isEmpty()) { 60 | return false; 61 | } 62 | 63 | return $this->items = collect($this->all()) 64 | ->map(function ($value, $key) use ($relations) { 65 | if ($relations->has($key)) { 66 | $className = $relations->get($key); 67 | 68 | return new $className($value); 69 | } 70 | 71 | return $value; 72 | }) 73 | ->all(); 74 | } 75 | 76 | /** 77 | * Returns raw response. 78 | * 79 | * @return array|mixed 80 | */ 81 | public function getRawResponse() 82 | { 83 | return $this->items; 84 | } 85 | 86 | /** 87 | * Returns raw result. 88 | * 89 | * @param $data 90 | * 91 | * @return mixed 92 | */ 93 | public function getRawResult($data) 94 | { 95 | return Arr::get($data, 'result', $data); 96 | } 97 | 98 | /** 99 | * Get Status of request. 100 | * 101 | * @return mixed 102 | */ 103 | public function getStatus() 104 | { 105 | return Arr::get($this->items, 'ok', false); 106 | } 107 | 108 | /** 109 | * Magic method to get properties dynamically. 110 | * 111 | * @param $name 112 | * @param $arguments 113 | * 114 | * @return mixed 115 | */ 116 | public function __call($name, $arguments) 117 | { 118 | $action = substr($name, 0, 3); 119 | 120 | if ($action === 'get') { 121 | $property = Str::snake(substr($name, 3)); 122 | $response = $this->get($property); 123 | 124 | // Map relative property to an object 125 | $relations = $this->relations(); 126 | if ($response !== null && isset($relations[$property])) { 127 | return new $relations[$property]($response); 128 | } 129 | 130 | return $response; 131 | } 132 | 133 | return false; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/Exceptions/TelegramResponseException.php: -------------------------------------------------------------------------------- 1 | response = $response; 31 | $this->responseData = $response->getDecodedBody(); 32 | 33 | $errorMessage = $this->get('description', 'Unknown error from API Response.'); 34 | $errorCode = $this->get('error_code', -1); 35 | 36 | parent::__construct($errorMessage, $errorCode, $previousException); 37 | } 38 | 39 | /** 40 | * A factory for creating the appropriate exception based on the response from Telegram. 41 | * 42 | * @param TelegramResponse $response The response that threw the exception. 43 | * 44 | * @return TelegramResponseException 45 | */ 46 | public static function create(TelegramResponse $response) 47 | { 48 | $data = $response->getDecodedBody(); 49 | 50 | $code = null; 51 | $message = null; 52 | if (isset($data['ok'], $data['error_code']) && $data['ok'] === false) { 53 | $code = $data['error_code']; 54 | $message = isset($data['description']) ? $data['description'] : 'Unknown error from API.'; 55 | } 56 | 57 | // Others 58 | return new static($response, new TelegramOtherException($message, $code)); 59 | } 60 | 61 | /** 62 | * Checks isset and returns that or a default value. 63 | * 64 | * @param string $key 65 | * @param mixed $default 66 | * 67 | * @return mixed 68 | */ 69 | private function get($key, $default = null) 70 | { 71 | if (isset($this->responseData[$key])) { 72 | return $this->responseData[$key]; 73 | } 74 | 75 | return $default; 76 | } 77 | 78 | /** 79 | * Returns the HTTP status code. 80 | * 81 | * @return int 82 | */ 83 | public function getHttpStatusCode() 84 | { 85 | return $this->response->getHttpStatusCode(); 86 | } 87 | 88 | /** 89 | * Returns the error type. 90 | * 91 | * @return string 92 | */ 93 | public function getErrorType() 94 | { 95 | return $this->get('type', ''); 96 | } 97 | 98 | /** 99 | * Returns the raw response used to create the exception. 100 | * 101 | * @return string 102 | */ 103 | public function getRawResponse() 104 | { 105 | return $this->response->getBody(); 106 | } 107 | 108 | /** 109 | * Returns the decoded response used to create the exception. 110 | * 111 | * @return array 112 | */ 113 | public function getResponseData() 114 | { 115 | return $this->responseData; 116 | } 117 | 118 | /** 119 | * Returns the response entity used to create the exception. 120 | * 121 | * @return TelegramResponse 122 | */ 123 | public function getResponse() 124 | { 125 | return $this->response; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/HttpClients/GuzzleHttpClient.php: -------------------------------------------------------------------------------- 1 | client = $client ?: new Client(); 51 | } 52 | 53 | /** 54 | * Unwrap Promises. 55 | */ 56 | public function __destruct() 57 | { 58 | Utils::unwrap(self::$promises); 59 | } 60 | 61 | /** 62 | * Sets HTTP client. 63 | * 64 | * @param Client $client 65 | * 66 | * @return GuzzleHttpClient 67 | */ 68 | public function setClient(Client $client) 69 | { 70 | $this->client = $client; 71 | 72 | return $this; 73 | } 74 | 75 | /** 76 | * Gets HTTP client for internal class use. 77 | * 78 | * @return Client 79 | */ 80 | private function getClient() 81 | { 82 | return $this->client; 83 | } 84 | 85 | /** 86 | * {@inheritdoc} 87 | */ 88 | public function send( 89 | $url, 90 | $method, 91 | array $headers = [], 92 | array $options = [], 93 | $timeOut = 30, 94 | $isAsyncRequest = false, 95 | $connectTimeOut = 10 96 | ) { 97 | $this->timeOut = $timeOut; 98 | $this->connectTimeOut = $connectTimeOut; 99 | 100 | $body = $options[ 'body' ] ?? null; 101 | $options = $this->getOptions($headers, $body, $options, $timeOut, $isAsyncRequest, $connectTimeOut); 102 | 103 | try { 104 | $response = $this->getClient()->requestAsync($method, $url, $options); 105 | 106 | if ($isAsyncRequest) { 107 | self::$promises[] = $response; 108 | } else { 109 | $response = $response->wait(); 110 | } 111 | } catch (RequestException $e) { 112 | $response = $e->getResponse(); 113 | 114 | if (!$response instanceof ResponseInterface) { 115 | throw new TelegramSDKException($e->getMessage(), $e->getCode()); 116 | } 117 | } 118 | 119 | return $response; 120 | } 121 | 122 | /** 123 | * Prepares and returns request options. 124 | * 125 | * @param array $headers 126 | * @param $body 127 | * @param $options 128 | * @param $timeOut 129 | * @param $isAsyncRequest 130 | * @param int $connectTimeOut 131 | * 132 | * @return array 133 | */ 134 | private function getOptions(array $headers, $body, $options, $timeOut, $isAsyncRequest = false, $connectTimeOut = 10) 135 | { 136 | $default_options = [ 137 | RequestOptions::HEADERS => $headers, 138 | RequestOptions::BODY => $body, 139 | RequestOptions::TIMEOUT => $timeOut, 140 | RequestOptions::CONNECT_TIMEOUT => $connectTimeOut, 141 | RequestOptions::SYNCHRONOUS => !$isAsyncRequest, 142 | ]; 143 | 144 | return array_merge($default_options, $options); 145 | } 146 | 147 | /** 148 | * @return int 149 | */ 150 | public function getTimeOut() 151 | { 152 | return $this->timeOut; 153 | } 154 | 155 | /** 156 | * @return int 157 | */ 158 | public function getConnectTimeOut() 159 | { 160 | return $this->connectTimeOut; 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/TelegramClient.php: -------------------------------------------------------------------------------- 1 | httpClientHandler = $httpClientHandler ?: new GuzzleHttpClient(); 44 | } 45 | 46 | /** 47 | * Returns the HTTP client handler. 48 | * 49 | * @return HttpClientInterface 50 | */ 51 | public function getHttpClientHandler() 52 | { 53 | return $this->httpClientHandler; 54 | } 55 | 56 | /** 57 | * Sets the HTTP client handler. 58 | * 59 | * @param HttpClientInterface $httpClientHandler 60 | */ 61 | public function setHttpClientHandler(HttpClientInterface $httpClientHandler) 62 | { 63 | $this->httpClientHandler = $httpClientHandler; 64 | } 65 | 66 | /** 67 | * Send an API request and process the result. 68 | * 69 | * @param TelegramRequest $request 70 | * 71 | * @return TelegramResponse 72 | * @throws TelegramSDKException 73 | * 74 | */ 75 | public function sendRequest(TelegramRequest $request) 76 | { 77 | [$url, $method, $headers, $isAsyncRequest] = $this->prepareRequest($request); 78 | 79 | $timeOut = $request->getTimeOut(); 80 | $connectTimeOut = $request->getConnectTimeOut(); 81 | 82 | $options = $this->getOptions($request, $method); 83 | 84 | $rawResponse = $this->httpClientHandler->send( 85 | $url, 86 | $method, 87 | $headers, 88 | $options, 89 | $timeOut, 90 | $isAsyncRequest, 91 | $connectTimeOut 92 | ); 93 | 94 | $returnResponse = $this->getResponse($request, $rawResponse); 95 | 96 | if ($returnResponse->isError()) { 97 | throw $returnResponse->getThrownException(); 98 | } 99 | 100 | return $returnResponse; 101 | } 102 | 103 | /** 104 | * Prepares the API request for sending to the client handler. 105 | * 106 | * @param TelegramRequest $request 107 | * 108 | * @return array 109 | */ 110 | public function prepareRequest(TelegramRequest $request) 111 | { 112 | $url = $this->getBaseBotUrl() . $request->getAccessToken() . '/' . $request->getEndpoint(); 113 | 114 | return [ 115 | $url, 116 | $request->getMethod(), 117 | $request->getHeaders(), 118 | $request->isAsyncRequest(), 119 | ]; 120 | } 121 | 122 | /** 123 | * Returns the base Bot URL. 124 | * 125 | * @return string 126 | */ 127 | public function getBaseBotUrl() 128 | { 129 | return static::BASE_BOT_URL; 130 | } 131 | 132 | /** 133 | * @param \Telegram\Bot\TelegramRequest $request 134 | * @param string $method 135 | * @return array 136 | * + */ 137 | private function getOptions(TelegramRequest $request, $method) 138 | { 139 | if ($method === 'POST') { 140 | return $request->getPostParams(); 141 | } 142 | 143 | return ['query' => $request->getParams()]; 144 | } 145 | 146 | /** 147 | * Creates response object. 148 | * 149 | * @param TelegramRequest $request 150 | * @param ResponseInterface|PromiseInterface $response 151 | * 152 | * @return TelegramResponse 153 | */ 154 | protected function getResponse(TelegramRequest $request, $response) 155 | { 156 | return new TelegramResponse($request, $response); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/Commands/Command.php: -------------------------------------------------------------------------------- 1 | name; 61 | } 62 | 63 | /** 64 | * Get Command Aliases. 65 | * 66 | * @return array 67 | */ 68 | public function getAliases() 69 | { 70 | return $this->aliases; 71 | } 72 | 73 | /** 74 | * Set Command Name. 75 | * 76 | * @param $name 77 | * 78 | * @return Command 79 | */ 80 | public function setName($name) 81 | { 82 | $this->name = $name; 83 | 84 | return $this; 85 | } 86 | 87 | /** 88 | * Get Command Description. 89 | * 90 | * @return string 91 | */ 92 | public function getDescription() 93 | { 94 | return $this->description; 95 | } 96 | 97 | /** 98 | * Set Command Description. 99 | * 100 | * @param $description 101 | * 102 | * @return Command 103 | */ 104 | public function setDescription($description) 105 | { 106 | $this->description = $description; 107 | 108 | return $this; 109 | } 110 | 111 | /** 112 | * Get Arguments passed to the command. 113 | * 114 | * @return string 115 | */ 116 | public function getArguments() 117 | { 118 | return $this->arguments; 119 | } 120 | 121 | /** 122 | * Returns an instance of Command Bus. 123 | * 124 | * @return CommandBus 125 | */ 126 | public function getCommandBus() 127 | { 128 | return $this->telegram->getCommandBus(); 129 | } 130 | 131 | /** 132 | * {@inheritdoc} 133 | */ 134 | public function make(Api $telegram, $arguments, Update $update) 135 | { 136 | $this->telegram = $telegram; 137 | $this->arguments = $arguments; 138 | $this->update = $update; 139 | 140 | return $this->handle($arguments); 141 | } 142 | 143 | /** 144 | * Helper to Trigger other Commands. 145 | * 146 | * @param $command 147 | * @param null $arguments 148 | * 149 | * @return mixed 150 | */ 151 | protected function triggerCommand($command, $arguments = null) 152 | { 153 | return $this->getCommandBus()->execute($command, $arguments ?: $this->arguments, $this->update); 154 | } 155 | 156 | /** 157 | * {@inheritdoc} 158 | */ 159 | abstract public function handle($arguments); 160 | } 161 | -------------------------------------------------------------------------------- /src/Callbacks/CallbackCommandBus.php: -------------------------------------------------------------------------------- 1 | telegram = $telegram; 35 | } 36 | 37 | /** 38 | * Returns the list of commands. 39 | * 40 | * @return array 41 | */ 42 | public function getCommands() 43 | { 44 | return $this->commands; 45 | } 46 | 47 | /** 48 | * Add a list of commands. 49 | * 50 | * @param array $commands 51 | * 52 | * @return CallbackCommandBus 53 | */ 54 | public function addCallbackCommands(array $commands) 55 | { 56 | foreach ($commands as $command) { 57 | $this->addCallbackCommand($command); 58 | } 59 | 60 | return $this; 61 | } 62 | 63 | /** 64 | * Add a command to the commands list. 65 | * 66 | * @param CallbackCommandInterface|string $command Either an object or full path to the command class. 67 | * 68 | * @throws TelegramSDKException 69 | * 70 | * @return CallbackCommandBus 71 | */ 72 | public function addCallbackCommand($command) 73 | { 74 | if (!is_object($command)) { 75 | if (!class_exists($command)) { 76 | throw new TelegramSDKException( 77 | sprintf( 78 | 'Command class "%s" not found! Please make sure the class exists.', 79 | $command 80 | ) 81 | ); 82 | } 83 | 84 | if ($this->telegram->hasContainer()) { 85 | $command = $this->buildDependencyInjectedAnswer($command); 86 | } else { 87 | $command = new $command(); 88 | } 89 | } 90 | 91 | if ($command instanceof CallbackCommandInterface) { 92 | /* 93 | * At this stage we definitely have a proper command to use. 94 | * 95 | * @var CallbackCommand $command 96 | */ 97 | $this->commands[$command->getName()] = $command; 98 | 99 | return $this; 100 | } 101 | 102 | throw new TelegramSDKException( 103 | sprintf( 104 | 'Command class "%s" should be an instance of "Telegram\Bot\Callback\CallbackCommandInterface"', 105 | get_class($command) 106 | ) 107 | ); 108 | } 109 | 110 | /** 111 | * Removes a list of commands. 112 | * 113 | * @param array $names 114 | * 115 | * @return CallbackCommandBus 116 | */ 117 | public function removeCommands(array $names) 118 | { 119 | foreach ($names as $name) { 120 | $this->removeCommand($name); 121 | } 122 | 123 | return $this; 124 | } 125 | 126 | /** 127 | * Remove a command from the list. 128 | * 129 | * @param $name 130 | * 131 | * @return CallbackCommandBus 132 | */ 133 | public function removeCommand($name) 134 | { 135 | unset($this->commands[$name]); 136 | 137 | return $this; 138 | } 139 | 140 | /** 141 | * Handles Inbound Messages and Executes Appropriate Command. 142 | * 143 | * @param string $message 144 | * @param Update $update 145 | * 146 | * @throws TelegramSDKException 147 | * 148 | * @return Update 149 | */ 150 | protected function handler($message, Update $update) 151 | { 152 | $match = $this->parseArguments($message); 153 | 154 | $command = strtolower($match[0]); //All commands must be lowercase. 155 | array_shift($match); 156 | 157 | $this->execute($command, $match, $update, $update->getCallbackQuery()); 158 | 159 | return $update; 160 | } 161 | 162 | private function parseArguments($message) 163 | { 164 | return explode(' ', $message); 165 | } 166 | 167 | /** 168 | * Execute the command. 169 | * 170 | * @param $name 171 | * @param $arguments 172 | * @param $message 173 | * @param $callback 174 | * 175 | * @return mixed 176 | */ 177 | protected function execute($name, $arguments, $message, $callback) 178 | { 179 | if (array_key_exists($name, $this->commands)) { 180 | return $this->commands[$name]->make($this->telegram, $arguments, $message, $callback); 181 | } 182 | 183 | return 'ok'; 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /src/TelegramResponse.php: -------------------------------------------------------------------------------- 1 | httpStatusCode = $response->getStatusCode(); 62 | $this->body = $response->getBody(); 63 | $this->headers = $response->getHeaders(); 64 | 65 | $this->decodeBody(); 66 | } elseif ($response instanceof PromiseInterface) { 67 | $this->httpStatusCode = null; 68 | } else { 69 | throw new \InvalidArgumentException( 70 | 'Second constructor argument "response" must be instance of ResponseInterface or PromiseInterface' 71 | ); 72 | } 73 | 74 | $this->request = $request; 75 | $this->endPoint = (string) $request->getEndpoint(); 76 | } 77 | 78 | /** 79 | * Return the original request that returned this response. 80 | * 81 | * @return TelegramRequest 82 | */ 83 | public function getRequest() 84 | { 85 | return $this->request; 86 | } 87 | 88 | /** 89 | * Gets the HTTP status code. 90 | * Returns NULL if the request was asynchronous since we are not waiting for the response. 91 | * 92 | * @return null|int 93 | */ 94 | public function getHttpStatusCode() 95 | { 96 | return $this->httpStatusCode; 97 | } 98 | 99 | /** 100 | * Gets the Request Endpoint used to get the response. 101 | * 102 | * @return string 103 | */ 104 | public function getEndpoint() 105 | { 106 | return $this->endPoint; 107 | } 108 | 109 | /** 110 | * Return the bot access token that was used for this request. 111 | * 112 | * @return string|null 113 | */ 114 | public function getAccessToken() 115 | { 116 | return $this->request->getAccessToken(); 117 | } 118 | 119 | /** 120 | * Return the HTTP headers for this response. 121 | * 122 | * @return array 123 | */ 124 | public function getHeaders() 125 | { 126 | return $this->headers; 127 | } 128 | 129 | /** 130 | * Return the raw body response. 131 | * 132 | * @return string 133 | */ 134 | public function getBody() 135 | { 136 | return $this->body; 137 | } 138 | 139 | /** 140 | * Return the decoded body response. 141 | * 142 | * @return array 143 | */ 144 | public function getDecodedBody() 145 | { 146 | return $this->decodedBody; 147 | } 148 | 149 | /** 150 | * Helper function to return the payload of a successful response. 151 | * 152 | * @return mixed 153 | */ 154 | public function getResult() 155 | { 156 | return $this->decodedBody['result']; 157 | } 158 | 159 | /** 160 | * Checks if response is an error. 161 | * 162 | * @return bool 163 | */ 164 | public function isError() 165 | { 166 | return isset($this->decodedBody['ok']) && ($this->decodedBody['ok'] === false); 167 | } 168 | 169 | /** 170 | * Throws the exception. 171 | * 172 | * @throws TelegramSDKException 173 | */ 174 | public function throwException() 175 | { 176 | throw $this->thrownException; 177 | } 178 | 179 | /** 180 | * Instantiates an exception to be thrown later. 181 | */ 182 | public function makeException() 183 | { 184 | $this->thrownException = TelegramResponseException::create($this); 185 | } 186 | 187 | /** 188 | * Returns the exception that was thrown for this request. 189 | * 190 | * @return TelegramSDKException 191 | */ 192 | public function getThrownException() 193 | { 194 | return $this->thrownException; 195 | } 196 | 197 | /** 198 | * Converts raw API response to proper decoded response. 199 | */ 200 | public function decodeBody() 201 | { 202 | $this->decodedBody = json_decode($this->body, true); 203 | 204 | if ($this->decodedBody === null) { 205 | $this->decodedBody = []; 206 | parse_str($this->body, $this->decodedBody); 207 | } 208 | 209 | if (!is_array($this->decodedBody)) { 210 | $this->decodedBody = []; 211 | } 212 | 213 | if ($this->isError()) { 214 | $this->makeException(); 215 | } 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /src/Keyboard/Keyboard.php: -------------------------------------------------------------------------------- 1 | 9 | * // For Standard Keyboard 10 | * $params = [ 11 | * 'keyboard' => '', 12 | * 'resize_keyboard' => '', 13 | * 'one_time_keyboard' => '', 14 | * 'selective' => '', 15 | * ]; 16 | * 17 | * 18 | * OR 19 | * 20 | * 21 | * // For Inline Keyboard 22 | * $params = [ 23 | * 'inline_keyboard' => '', 24 | * ]; 25 | * 26 | * 27 | * @method $this setResizeKeyboard($boolean) Optional. Requests clients to resize the keyboard vertically for optimal fit. 28 | * @method $this setOneTimeKeyboard($boolean) Optional. Requests clients to hide the keyboard as soon as it's been used. 29 | * @method $this setSelective($boolean) Optional. Use this parameter if you want to show the keyboard to specific users only. 30 | */ 31 | class Keyboard extends Base 32 | { 33 | /** 34 | * Make an Inline Keyboard. 35 | * 36 | * @var bool 37 | */ 38 | protected $inline = false; 39 | 40 | /** 41 | * Make this keyboard inline, So it appears right next to the message it belongs to. 42 | * 43 | * @link https://core.telegram.org/bots/api#inlinekeyboardmarkup 44 | * 45 | * @return $this 46 | */ 47 | public function inline() 48 | { 49 | $this->inline = true; 50 | 51 | return $this; 52 | } 53 | 54 | /** 55 | * Determine if it's an inline keyboard. 56 | * 57 | * @return bool 58 | */ 59 | public function isInlineKeyboard() 60 | { 61 | return $this->inline; 62 | } 63 | 64 | /** 65 | * Create a new row in keyboard to add buttons. 66 | * 67 | * @return $this 68 | */ 69 | public function row() 70 | { 71 | $property = 'keyboard'; 72 | if ($this->isInlineKeyboard()) { 73 | $property = 'inline_keyboard'; 74 | } 75 | 76 | $this->items[$property][] = func_get_args(); 77 | 78 | return $this; 79 | } 80 | 81 | /** 82 | * Represents one button of the Reply keyboard. 83 | * 84 | * For simple text buttons String can be used instead of an array. 85 | * You can also utilise the fluent API to build the params payload. 86 | * 87 | * 88 | * $params = 'string' 89 | * 90 | * OR 91 | * 92 | * $params = [ 93 | * 'text' => '', 94 | * 'request_contact' => '', 95 | * 'request_location' => '', 96 | * ]; 97 | * 98 | * 99 | * @link https://core.telegram.org/bots/api#keyboardbutton 100 | * 101 | * @param string|array $params 102 | * 103 | * @var string $params ['text'] 104 | * @var bool $params ['request_contact'] 105 | * @var bool $params ['request_location'] 106 | * 107 | * @return mixed 108 | */ 109 | public static function button($params = []) 110 | { 111 | if (is_string($params)) { 112 | return $params; 113 | } 114 | 115 | return Button::make($params); 116 | } 117 | 118 | /** 119 | * Represents one button of an inline keyboard. 120 | * 121 | * You must use exactly one of the optional fields. 122 | * You can also utilise the fluent API to build the params payload. 123 | * 124 | * 125 | * $params = [ 126 | * 'text' => '', 127 | * 'url' => '', 128 | * 'callback_data' => '', 129 | * 'switch_inline_query' => '', 130 | * 'switch_inline_query_current_chat' => '', 131 | * 'callback_game' => '', 132 | * 'pay' => '', 133 | * ]; 134 | * 135 | * 136 | * @link https://core.telegram.org/bots/api#inlinekeyboardbutton 137 | * 138 | * @param string|array $params 139 | * 140 | * @var string $params ['text'] 141 | * @var string $params ['url'] 142 | * @var string $params ['callback_data'] 143 | * @var string $params ['switch_inline_query'] 144 | * @var string $params ['switch_inline_query_current_chat'] 145 | * @var string $params ['callback_game'] 146 | * @var bool $params ['pay'] 147 | * 148 | * @return string 149 | */ 150 | public static function inlineButton($params = []) 151 | { 152 | return self::button($params); 153 | } 154 | 155 | /** 156 | * Hide the current custom keyboard and display the default letter-keyboard. 157 | * 158 | * 159 | * $params = [ 160 | * 'hide_keyboard' => true, 161 | * 'selective' => false, 162 | * ]; 163 | * 164 | * 165 | * @link https://core.telegram.org/bots/api#replykeyboardhide 166 | * 167 | * @param array $params 168 | * 169 | * @var bool $params ['hide_keyboard'] 170 | * @var bool $params ['selective'] 171 | * 172 | * @return string 173 | */ 174 | public static function hide(array $params = []) 175 | { 176 | return new static(array_merge(['remove_keyboard' => true, 'selective' => false], $params)); 177 | } 178 | 179 | /** 180 | * Display a reply interface to the user (act as if the user has selected the bot‘s message and tapped ’Reply'). 181 | * 182 | * 183 | * $params = [ 184 | * 'force_reply' => true, 185 | * 'selective' => false, 186 | * ]; 187 | * 188 | * 189 | * @link https://core.telegram.org/bots/api#forcereply 190 | * 191 | * @param array $params 192 | * 193 | * @var bool $params ['force_reply'] 194 | * @var bool $params ['selective'] 195 | * 196 | * @return string 197 | */ 198 | public static function forceReply(array $params = []) 199 | { 200 | return new static(array_merge(['force_reply' => true, 'selective' => false], $params)); 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /src/Helpers/Emojify.php: -------------------------------------------------------------------------------- 1 | setupEmojiMaps(); 51 | } 52 | 53 | /** 54 | * Returns the *Singleton* instance of this class. 55 | * 56 | * @return Emojify The *Singleton* instance. 57 | */ 58 | public static function getInstance() 59 | { 60 | if (null === static::$instance) { 61 | static::$instance = new static(); 62 | } 63 | 64 | return static::$instance; 65 | } 66 | 67 | /** 68 | * Set File Path to Emoji Map File. 69 | * 70 | * @param string $emojiMapFile 71 | * 72 | * @return Emojify 73 | */ 74 | public function setEmojiMapFile($emojiMapFile) 75 | { 76 | $this->emojiMapFile = $emojiMapFile; 77 | $this->setupEmojiMaps(); 78 | 79 | return $this; 80 | } 81 | 82 | /** 83 | * Translate Word to Emoji. 84 | * 85 | * @param $text 86 | * 87 | * @return mixed 88 | */ 89 | public function toEmoji($text) 90 | { 91 | return $this->replace($text, $this->emojiMap); 92 | } 93 | 94 | /** 95 | * Alias of toEmoji(). 96 | * 97 | * @param $text 98 | * 99 | * @return mixed 100 | */ 101 | public static function text($text) 102 | { 103 | return self::getInstance()->toEmoji($text); 104 | } 105 | 106 | /** 107 | * Translate Emoji to Word. 108 | * 109 | * @param $text 110 | * 111 | * @return mixed 112 | */ 113 | public function toWord($text) 114 | { 115 | return $this->replace($text, $this->wordMap, true); 116 | } 117 | 118 | /** 119 | * Alias of toWord(). 120 | * 121 | * @param $text 122 | * 123 | * @return mixed 124 | */ 125 | public static function translate($text) 126 | { 127 | return self::getInstance()->toWord($text); 128 | } 129 | 130 | /** 131 | * Replace. 132 | * 133 | * @param $line 134 | * @param $replace 135 | * @param bool $toWord 136 | * @param string $delimiter 137 | * 138 | * @return mixed 139 | */ 140 | protected function replace($line, $replace, $toWord = false, $delimiter = ':') 141 | { 142 | if ($toWord) { 143 | return $this->emojiToWordReplace($line, $replace, $delimiter); 144 | } 145 | 146 | return $this->wordToEmojiReplace($line, $replace, $delimiter); 147 | } 148 | 149 | /** 150 | * Finds words enclosed by the delimiter and converts them to the 151 | * appropriate emoji character. 152 | * 153 | * @param $line 154 | * @param $replace 155 | * @param $delimiter 156 | * 157 | * @return mixed 158 | */ 159 | protected function wordToEmojiReplace($line, $replace, $delimiter) 160 | { 161 | foreach ($replace as $key => $value) { 162 | $line = str_replace($delimiter . $key . $delimiter, $value, $line); 163 | } 164 | 165 | return $line; 166 | } 167 | 168 | /** 169 | * Finds emojis and replaces them with text enclosed by the delimiter. 170 | * 171 | * @param $line 172 | * @param $replace 173 | * @param $delimiter 174 | * 175 | * @return mixed 176 | */ 177 | protected function emojiToWordReplace($line, $replace, $delimiter) 178 | { 179 | foreach ($replace as $key => $value) { 180 | $line = str_replace($key, $delimiter . $value . $delimiter, $line); 181 | } 182 | 183 | return $line; 184 | } 185 | 186 | /** 187 | * Get Emoji Map Array. 188 | * 189 | * @throws TelegramEmojiMapFileNotFoundException 190 | * 191 | * @return array 192 | */ 193 | protected function getEmojiMap() 194 | { 195 | if (!isset($this->emojiMapFile)) { 196 | $this->emojiMapFile = realpath(__DIR__ . self::DEFAULT_EMOJI_MAP_FILE); 197 | } 198 | 199 | if (!file_exists($this->emojiMapFile)) { 200 | throw new TelegramEmojiMapFileNotFoundException(); 201 | } 202 | 203 | return json_decode(file_get_contents($this->emojiMapFile), true); 204 | } 205 | 206 | /** 207 | * Setup Emoji Maps. 208 | * 209 | * @throws TelegramEmojiMapFileNotFoundException 210 | */ 211 | protected function setupEmojiMaps() 212 | { 213 | $this->emojiMap = $this->getEmojiMap(); 214 | $this->wordMap = array_flip($this->emojiMap); 215 | } 216 | 217 | /** 218 | * Private clone method to prevent cloning of the instance of the 219 | * *Singleton* instance. 220 | * 221 | * @return void 222 | */ 223 | private function __clone() 224 | { 225 | } 226 | 227 | /** 228 | * Private unserialize method to prevent unserializing of the *Singleton* 229 | * instance. 230 | * 231 | * @return void 232 | */ 233 | private function __wakeup() 234 | { 235 | } 236 | } 237 | -------------------------------------------------------------------------------- /src/Objects/Update.php: -------------------------------------------------------------------------------- 1 | Message::class, 34 | 'edited_message' => EditedMessage::class, 35 | 'channel_post' => Message::class, 36 | 'edited_channel_post' => EditedMessage::class, 37 | 'inline_query' => InlineQuery::class, 38 | 'chosen_inline_result' => ChosenInlineResult::class, 39 | 'callback_query' => CallbackQuery::class, 40 | 'shipping_query' => ShippingQuery::class, 41 | 'pre_checkout_query' => PreCheckoutQuery::class, 42 | 'poll' => Poll::class, 43 | 'poll_answer' => PollAnswer::class, 44 | ]; 45 | } 46 | 47 | /** 48 | * Get recent message. 49 | * 50 | * @return Update 51 | */ 52 | public function recentMessage() 53 | { 54 | return new static($this->last()); 55 | } 56 | 57 | /** 58 | * Determine if the update is of given type. 59 | * 60 | * @param string $type 61 | * 62 | * @return bool 63 | */ 64 | public function isType($type) 65 | { 66 | if ($this->has(strtolower($type))) { 67 | return true; 68 | } 69 | 70 | return $this->detectType() === $type; 71 | } 72 | 73 | /** 74 | * Detect type based on properties. 75 | * 76 | * @return string|null 77 | */ 78 | public function detectType() 79 | { 80 | $types = [ 81 | 'message', 82 | 'edited_message', 83 | 'channel_post', 84 | 'edited_channel_post', 85 | 'inline_query', 86 | 'chosen_inline_result', 87 | 'callback_query', 88 | 'shipping_query', 89 | 'pre_checkout_query', 90 | 'poll', 91 | 'poll_answer', 92 | ]; 93 | 94 | return $this->keys() 95 | ->intersect($types) 96 | ->pop(); 97 | } 98 | 99 | /** 100 | * Return the related message. 101 | * 102 | * @return null|Message 103 | */ 104 | public function getRelatedMessage() 105 | { 106 | if ($this->has('message')) { 107 | return $this->getMessage(); 108 | } elseif ($this->has('edited_message')) { 109 | return $this->getEditedMessage(); 110 | } elseif ($this->has('callback_query')) { 111 | return $this->getCallbackQuery()->getMessage(); 112 | } elseif ($this->has('channel_post')) { 113 | return $this->getChannelPost(); 114 | } elseif ($this->has('edited_channel_post')) { 115 | return $this->getEditedChannelPost(); 116 | } 117 | } 118 | 119 | /** 120 | * Get message object (if exists). 121 | * 122 | * @return null|Chat 123 | */ 124 | public function getChat() 125 | { 126 | switch ($this->detectType()) { 127 | case 'message': 128 | return $this->getMessage()->getChat(); 129 | case 'edited_message': 130 | return $this->getEditedMessage()->getChat(); 131 | case 'channel_post': 132 | return $this->getChannelPost()->getChat(); 133 | case 'callback_query': 134 | return $this->getCallbackQuery()->getMessage()->getChat(); 135 | default: 136 | // nothing to return 137 | return null; 138 | } 139 | } 140 | 141 | /** 142 | * Return the related user that created the update. 143 | * 144 | * @return null|User 145 | */ 146 | public function getFrom() 147 | { 148 | if ($this->has('message')) { 149 | return $this->getMessage()->getFrom(); 150 | } elseif ($this->has('edited_message')) { 151 | return $this->getEditedMessage()->getFrom(); 152 | } elseif ($this->has('inline_query')) { 153 | return $this->getInlineQuery()->getFrom(); 154 | } elseif ($this->has('chosen_inline_result')) { 155 | return $this->getChosenInlineResult()->getFrom(); 156 | } elseif ($this->has('callback_query')) { 157 | return $this->getCallbackQuery()->getFrom(); 158 | } elseif ($this->has('channel_post')) { 159 | return $this->getChannelPost()->getFrom(); 160 | } elseif ($this->has('edited_channel_post')) { 161 | return $this->getEditedChannelPost()->getFrom(); 162 | } 163 | 164 | return null; 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /src/Commands/CommandBus.php: -------------------------------------------------------------------------------- 1 | telegram = $telegram; 35 | } 36 | 37 | /** 38 | * Returns the list of commands. 39 | * 40 | * @return array 41 | */ 42 | public function getCommands() 43 | { 44 | return $this->commands; 45 | } 46 | 47 | /** 48 | * Add a list of commands. 49 | * 50 | * @param array $commands 51 | * 52 | * @return CommandBus 53 | */ 54 | public function addCommands(array $commands) 55 | { 56 | foreach ($commands as $command) { 57 | $this->addCommand($command); 58 | } 59 | 60 | return $this; 61 | } 62 | 63 | /** 64 | * Add a command to the commands list. 65 | * 66 | * @param CommandInterface|string $command Either an object or full path to the command class. 67 | * 68 | * @throws TelegramSDKException 69 | * 70 | * @return CommandBus 71 | */ 72 | public function addCommand($command) 73 | { 74 | if (!is_object($command)) { 75 | if (!class_exists($command)) { 76 | throw new TelegramSDKException( 77 | sprintf( 78 | 'Command class "%s" not found! Please make sure the class exists.', 79 | $command 80 | ) 81 | ); 82 | } 83 | 84 | if ($this->telegram->hasContainer()) { 85 | $command = $this->buildDependencyInjectedAnswer($command); 86 | } else { 87 | $command = new $command(); 88 | } 89 | } 90 | 91 | if ($command instanceof CommandInterface) { 92 | /* 93 | * At this stage we definitely have a proper command to use. 94 | * 95 | * @var Command $command 96 | */ 97 | $this->commands[$command->getName()] = $command; 98 | 99 | $aliases = $command->getAliases(); 100 | 101 | if (empty($aliases)) { 102 | return $this; 103 | } 104 | 105 | foreach ($command->getAliases() as $alias) { 106 | if (isset($this->commands[$alias])) { 107 | throw new TelegramSDKException(sprintf( 108 | '[Error] Alias [%s] conflicts with command name of "%s" try with another name or remove this alias from the list.', 109 | $alias, 110 | get_class($command) 111 | )); 112 | } 113 | 114 | if (isset($this->commandAliases[$alias])) { 115 | throw new TelegramSDKException(sprintf( 116 | '[Error] Alias [%s] conflicts with another command\'s alias list: "%s", try with another name or remove this alias from the list.', 117 | $alias, 118 | get_class($command) 119 | )); 120 | } 121 | 122 | $this->commandAliases[$alias] = $command; 123 | } 124 | 125 | return $this; 126 | } 127 | 128 | throw new TelegramSDKException( 129 | sprintf( 130 | 'Command class "%s" should be an instance of "Telegram\Bot\Commands\CommandInterface"', 131 | get_class($command) 132 | ) 133 | ); 134 | } 135 | 136 | /** 137 | * Remove a command from the list. 138 | * 139 | * @param $name 140 | * 141 | * @return CommandBus 142 | */ 143 | public function removeCommand($name) 144 | { 145 | unset($this->commands[$name]); 146 | 147 | return $this; 148 | } 149 | 150 | /** 151 | * Removes a list of commands. 152 | * 153 | * @param array $names 154 | * 155 | * @return CommandBus 156 | */ 157 | public function removeCommands(array $names) 158 | { 159 | foreach ($names as $name) { 160 | $this->removeCommand($name); 161 | } 162 | 163 | return $this; 164 | } 165 | 166 | /** 167 | * Parse a Command for a Match. 168 | * 169 | * @param $text 170 | * 171 | * @throws \InvalidArgumentException 172 | * 173 | * @return array 174 | */ 175 | public function parseCommand($text) 176 | { 177 | preg_match('/^\/([^\s@]+)@?(\S+)?\s?(.*)$/s', $text, $matches); 178 | 179 | return $matches; 180 | } 181 | 182 | /** 183 | * Handles Inbound Messages and Executes Appropriate Command. 184 | * 185 | * @param $message 186 | * @param $update 187 | * 188 | * @throws TelegramSDKException 189 | * 190 | * @return Update 191 | */ 192 | protected function handler($message, Update $update) 193 | { 194 | $match = $this->parseCommand($message); 195 | if (!empty($match)) { 196 | $command = strtolower($match[1]); //All commands must be lowercase. 197 | $arguments = $match[3]; 198 | 199 | $this->execute($command, $arguments, $update); 200 | } 201 | 202 | return $update; 203 | } 204 | 205 | /** 206 | * Execute the command. 207 | * 208 | * @param $name 209 | * @param $arguments 210 | * @param $message 211 | * 212 | * @return mixed 213 | */ 214 | protected function execute($name, $arguments, $message) 215 | { 216 | if (array_key_exists($name, $this->commands)) { 217 | return $this->commands[$name]->make($this->telegram, $arguments, $message); 218 | } elseif (array_key_exists($name, $this->commandAliases)) { 219 | return $this->commandAliases[$name]->make($this->telegram, $arguments, $message); 220 | } elseif (array_key_exists('help', $this->commands)) { 221 | return $this->commands['help']->make($this->telegram, $arguments, $message); 222 | } 223 | 224 | return 'Ok'; 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /src/TelegramRequest.php: -------------------------------------------------------------------------------- 1 | setAccessToken($accessToken); 86 | $this->setMethod($method); 87 | $this->setEndpoint($endpoint); 88 | $this->setParams($params); 89 | $this->setAsyncRequest($isAsyncRequest); 90 | $this->setTimeOut($timeOut); 91 | $this->setConnectTimeOut($connectTimeOut); 92 | } 93 | 94 | /** 95 | * Set the bot access token for this request. 96 | * 97 | * @param string 98 | * 99 | * @return TelegramRequest 100 | */ 101 | public function setAccessToken($accessToken) 102 | { 103 | $this->accessToken = $accessToken; 104 | 105 | return $this; 106 | } 107 | 108 | /** 109 | * Return the bot access token for this request. 110 | * 111 | * @return string|null 112 | */ 113 | public function getAccessToken() 114 | { 115 | return $this->accessToken; 116 | } 117 | 118 | /** 119 | * Validate that bot access token exists for this request. 120 | * 121 | * @throws TelegramSDKException 122 | */ 123 | public function validateAccessToken() 124 | { 125 | $accessToken = $this->getAccessToken(); 126 | if ($accessToken === null) { 127 | throw new TelegramSDKException('You must provide your bot access token to make any API requests.'); 128 | } 129 | } 130 | 131 | /** 132 | * Set the HTTP method for this request. 133 | * 134 | * @param string 135 | * 136 | * @return TelegramRequest 137 | */ 138 | public function setMethod($method) 139 | { 140 | $this->method = strtoupper($method); 141 | 142 | return $this; 143 | } 144 | 145 | /** 146 | * Return the HTTP method for this request. 147 | * 148 | * @return string 149 | */ 150 | public function getMethod() 151 | { 152 | return $this->method; 153 | } 154 | 155 | /** 156 | * Validate that the HTTP method is set. 157 | * 158 | * @throws TelegramSDKException 159 | */ 160 | public function validateMethod() 161 | { 162 | if (!$this->method) { 163 | throw new TelegramSDKException('HTTP method not specified.'); 164 | } 165 | 166 | if (!in_array($this->method, ['GET', 'POST'])) { 167 | throw new TelegramSDKException('Invalid HTTP method specified.'); 168 | } 169 | } 170 | 171 | /** 172 | * Set the endpoint for this request. 173 | * 174 | * @param string $endpoint 175 | * 176 | * @return TelegramRequest 177 | */ 178 | public function setEndpoint($endpoint) 179 | { 180 | $this->endpoint = $endpoint; 181 | 182 | return $this; 183 | } 184 | 185 | /** 186 | * Return the API Endpoint for this request. 187 | * 188 | * @return string 189 | */ 190 | public function getEndpoint() 191 | { 192 | return $this->endpoint; 193 | } 194 | 195 | /** 196 | * Set the params for this request. 197 | * 198 | * @param array $params 199 | * 200 | * @return TelegramRequest 201 | */ 202 | public function setParams(array $params = []) 203 | { 204 | $this->params = array_merge($this->params, $params); 205 | 206 | return $this; 207 | } 208 | 209 | /** 210 | * Return the params for this request. 211 | * 212 | * @return array 213 | */ 214 | public function getParams() 215 | { 216 | return $this->params; 217 | } 218 | 219 | /** 220 | * Set the headers for this request. 221 | * 222 | * @param array $headers 223 | * 224 | * @return TelegramRequest 225 | */ 226 | public function setHeaders(array $headers) 227 | { 228 | $this->headers = array_merge($this->headers, $headers); 229 | 230 | return $this; 231 | } 232 | 233 | /** 234 | * Return the headers for this request. 235 | * 236 | * @return array 237 | */ 238 | public function getHeaders() 239 | { 240 | $headers = $this->getDefaultHeaders(); 241 | 242 | return array_merge($this->headers, $headers); 243 | } 244 | 245 | /** 246 | * Make this request asynchronous (non-blocking). 247 | * 248 | * @param $isAsyncRequest 249 | * 250 | * @return TelegramRequest 251 | */ 252 | public function setAsyncRequest($isAsyncRequest) 253 | { 254 | $this->isAsyncRequest = $isAsyncRequest; 255 | 256 | return $this; 257 | } 258 | 259 | /** 260 | * Check if this is an asynchronous request (non-blocking). 261 | * 262 | * @return bool 263 | */ 264 | public function isAsyncRequest() 265 | { 266 | return $this->isAsyncRequest; 267 | } 268 | 269 | /** 270 | * Only return params on POST requests. 271 | * 272 | * @return array 273 | */ 274 | public function getPostParams() 275 | { 276 | if ($this->getMethod() === 'POST') { 277 | return $this->getParams(); 278 | } 279 | 280 | return []; 281 | } 282 | 283 | /** 284 | * The default headers used with every request. 285 | * 286 | * @return array 287 | */ 288 | public function getDefaultHeaders() 289 | { 290 | return [ 291 | 'User-Agent' => 'Telegram Bot API v' . Api::VERSION . ' - (https://github.com/exileed/telegram-bot-sdk)', 292 | ]; 293 | } 294 | 295 | /** 296 | * @return int 297 | */ 298 | public function getTimeOut() 299 | { 300 | return $this->timeOut; 301 | } 302 | 303 | /** 304 | * @param int $timeOut 305 | * 306 | * @return $this 307 | */ 308 | public function setTimeOut($timeOut) 309 | { 310 | $this->timeOut = $timeOut; 311 | 312 | return $this; 313 | } 314 | 315 | /** 316 | * @return int 317 | */ 318 | public function getConnectTimeOut() 319 | { 320 | return $this->connectTimeOut; 321 | } 322 | 323 | /** 324 | * @param int $connectTimeOut 325 | * 326 | * @return $this 327 | */ 328 | public function setConnectTimeOut($connectTimeOut) 329 | { 330 | $this->connectTimeOut = $connectTimeOut; 331 | 332 | return $this; 333 | } 334 | } 335 | -------------------------------------------------------------------------------- /src/Laravel/config/telegram.php: -------------------------------------------------------------------------------- 1 | 'common', 15 | 16 | /* 17 | |-------------------------------------------------------------------------- 18 | | Telegram Bots 19 | |-------------------------------------------------------------------------- 20 | | 21 | | Here are each of the telegram bots config. 22 | | 23 | | Supported Params: 24 | | - username: Your Telegram Bot's Username. 25 | | Example: (string) 'BotFather'. 26 | | 27 | | - token: Your Telegram Bot's Access Token. 28 | Refer for more details: https://core.telegram.org/bots#botfather 29 | | Example: (string) '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11'. 30 | | 31 | | - commands: (Optional) Commands to register for this bot, 32 | | Supported Values: "Command Group Name", "Shared Command Name", "Full Path to Class". 33 | | Default: Registers Global Commands. 34 | | Example: (array) [ 35 | | 'admin', // Command Group Name. 36 | | 'status', // Shared Command Name. 37 | | Acme\Project\Commands\BotFather\HelloCommand::class, 38 | | Acme\Project\Commands\BotFather\ByeCommand::class, 39 | | ] 40 | | - callbacks: (Optional) Callbacks to register for this bot, 41 | | Supported Values: "Callbacks Group Name", "Shared Callbacks Name", "Full Path to Class". 42 | | Default: Registers Global Callbacks. 43 | | Example: (array) [ 44 | | Acme\Project\Commands\BotFather\HelloCallbackCommand::class, 45 | | Acme\Project\Commands\BotFather\ByeCallbackCommand::class, 46 | | ] 47 | */ 48 | 'bots' => [ 49 | 'common' => [ 50 | 'username' => 'MyTelegramBot', 51 | 'token' => env('TELEGRAM_BOT_TOKEN', 'YOUR-BOT-TOKEN'), 52 | 'commands' => [ 53 | // Acme\Project\Commands\MyTelegramBot\BotCommand::class 54 | ], 55 | 'callbacks' => [ 56 | // Acme\Project\Commands\MyTelegramBot\CallbackCommand::class 57 | ], 58 | ], 59 | 60 | // 'second' => [ 61 | // 'username' => 'MySecondBot', 62 | // 'token' => '123456:abc', 63 | // ], 64 | ], 65 | 66 | /* 67 | |-------------------------------------------------------------------------- 68 | | Asynchronous Requests [Optional] 69 | |-------------------------------------------------------------------------- 70 | | 71 | | When set to True, All the requests would be made non-blocking (Async). 72 | | 73 | | Default: false 74 | | Possible Values: (Boolean) "true" OR "false" 75 | | 76 | */ 77 | 'async_requests' => env('TELEGRAM_ASYNC_REQUESTS', false), 78 | 79 | /* 80 | |-------------------------------------------------------------------------- 81 | | HTTP Client Handler [Optional] 82 | |-------------------------------------------------------------------------- 83 | | 84 | | If you'd like to use a custom HTTP Client Handler. 85 | | Should be an instance of \Telegram\Bot\HttpClients\HttpClientInterface 86 | | 87 | | Default: GuzzlePHP 88 | | 89 | */ 90 | 'http_client_handler' => null, 91 | 92 | /* 93 | |-------------------------------------------------------------------------- 94 | | Resolve Injected Dependencies in commands [Optional] 95 | |-------------------------------------------------------------------------- 96 | | 97 | | Using Laravel's IoC container, we can easily type hint dependencies in 98 | | our command's constructor and have them automatically resolved for us. 99 | | 100 | | Default: true 101 | | Possible Values: (Boolean) "true" OR "false" 102 | | 103 | */ 104 | 'resolve_command_dependencies' => true, 105 | 106 | /* 107 | |-------------------------------------------------------------------------- 108 | | Register Telegram Global Commands [Optional] 109 | |-------------------------------------------------------------------------- 110 | | 111 | | If you'd like to use the SDK's built in command handler system, 112 | | You can register all the global commands here. 113 | | 114 | | Global commands will apply to all the bots in system and are always active. 115 | | 116 | | The command class should extend the \Telegram\Bot\Commands\Command class. 117 | | 118 | | Default: The SDK registers, a help command which when a user sends /help 119 | | will respond with a list of available commands and description. 120 | | 121 | */ 122 | 'commands' => [ 123 | Telegram\Bot\Commands\HelpCommand::class, 124 | ], 125 | 126 | 'callbacks' => [ 127 | ], 128 | 129 | /* 130 | |-------------------------------------------------------------------------- 131 | | Command Groups [Optional] 132 | |-------------------------------------------------------------------------- 133 | | 134 | | You can organize a set of commands into groups which can later, 135 | | be re-used across all your bots. 136 | | 137 | | You can create 4 types of groups: 138 | | 1. Group using full path to command classes. 139 | | 2. Group using shared commands: Provide the key name of the shared command 140 | | and the system will automatically resolve to the appropriate command. 141 | | 3. Group using other groups of commands: You can create a group which uses other 142 | | groups of commands to bundle them into one group. 143 | | 4. You can create a group with a combination of 1, 2 and 3 all together in one group. 144 | | 145 | | Examples shown below are by the group type for you to understand each of them. 146 | */ 147 | 'command_groups' => [ 148 | /* // Group Type: 1 149 | 'commmon' => [ 150 | Acme\Project\Commands\TodoCommand::class, 151 | Acme\Project\Commands\TaskCommand::class, 152 | ], 153 | */ 154 | 155 | /* // Group Type: 2 156 | 'subscription' => [ 157 | 'start', // Shared Command Name. 158 | 'stop', // Shared Command Name. 159 | ], 160 | */ 161 | 162 | /* // Group Type: 3 163 | 'auth' => [ 164 | Acme\Project\Commands\LoginCommand::class, 165 | Acme\Project\Commands\SomeCommand::class, 166 | ], 167 | 168 | 'stats' => [ 169 | Acme\Project\Commands\UserStatsCommand::class, 170 | Acme\Project\Commands\SubscriberStatsCommand::class, 171 | Acme\Project\Commands\ReportsCommand::class, 172 | ], 173 | 174 | 'admin' => [ 175 | 'auth', // Command Group Name. 176 | 'stats' // Command Group Name. 177 | ], 178 | */ 179 | 180 | /* // Group Type: 4 181 | 'myBot' => [ 182 | 'admin', // Command Group Name. 183 | 'subscription', // Command Group Name. 184 | 'status', // Shared Command Name. 185 | 'Acme\Project\Commands\BotCommand' // Full Path to Command Class. 186 | ], 187 | */ 188 | ], 189 | 190 | /* 191 | |-------------------------------------------------------------------------- 192 | | Shared Commands [Optional] 193 | |-------------------------------------------------------------------------- 194 | | 195 | | Shared commands let you register commands that can be shared between, 196 | | one or more bots across the project. 197 | | 198 | | This will help you prevent from having to register same set of commands, 199 | | for each bot over and over again and make it easier to maintain them. 200 | | 201 | | Shared commands are not active by default, You need to use the key name to register them, 202 | | individually in a group of commands or in bot commands. 203 | | Think of this as a central storage, to register, reuse and maintain them across all bots. 204 | | 205 | */ 206 | 'shared_commands' => [ 207 | // 'start' => Acme\Project\Commands\StartCommand::class, 208 | // 'stop' => Acme\Project\Commands\StopCommand::class, 209 | // 'status' => Acme\Project\Commands\StatusCommand::class, 210 | ], 211 | 212 | 'shared_callbacks' => [ 213 | // 'start' => Acme\Project\Commands\StartCommand::class, 214 | // 'stop' => Acme\Project\Commands\StopCommand::class, 215 | // 'status' => Acme\Project\Commands\StatusCommand::class, 216 | ], 217 | ]; 218 | -------------------------------------------------------------------------------- /src/BotsManager.php: -------------------------------------------------------------------------------- 1 | config = $config; 32 | } 33 | 34 | /** 35 | * Set the IoC Container. 36 | * 37 | * @param $container Container instance 38 | * 39 | * @return $this 40 | */ 41 | public function setContainer(Container $container) 42 | { 43 | $this->container = $container; 44 | 45 | return $this; 46 | } 47 | 48 | /** 49 | * Reconnect to the given bot. 50 | * 51 | * @param string $name 52 | * 53 | * @return Api 54 | */ 55 | public function reconnect($name = null) 56 | { 57 | $name = $name ?: $this->getDefaultBot(); 58 | $this->disconnect($name); 59 | 60 | return $this->bot($name); 61 | } 62 | 63 | /** 64 | * Disconnect from the given bot. 65 | * 66 | * @param string $name 67 | * 68 | * @return void 69 | */ 70 | public function disconnect($name = null) 71 | { 72 | $name = $name ?: $this->getDefaultBot(); 73 | unset($this->bots[$name]); 74 | } 75 | 76 | /** 77 | * Get a bot instance. 78 | * 79 | * @param string $name 80 | * 81 | * @return Api 82 | */ 83 | public function bot($name = null) 84 | { 85 | $name = $name ?: $this->getDefaultBot(); 86 | 87 | if (!isset($this->bots[$name])) { 88 | $this->bots[$name] = $this->makeBot($name); 89 | } 90 | 91 | return $this->bots[$name]; 92 | } 93 | 94 | /** 95 | * Make the bot instance. 96 | * 97 | * @param string $name 98 | * 99 | * @return Api 100 | */ 101 | protected function makeBot($name) 102 | { 103 | $config = $this->getBotConfig($name); 104 | 105 | $token = Arr::get($config, 'token'); 106 | $commands = Arr::get($config, 'commands', []); 107 | $callbacks = Arr::get($config, 'callbacks', []); 108 | 109 | $telegram = new Api( 110 | $token, 111 | $this->getConfig('async_requests', false), 112 | $this->getConfig('http_client_handler', null) 113 | ); 114 | 115 | // Check if DI needs to be enabled for Commands 116 | if ($this->getConfig('resolve_command_dependencies', false) && isset($this->container)) { 117 | $telegram->setContainer($this->container); 118 | } 119 | 120 | $commands = $this->parseBotCommands($commands); 121 | $callbacks = $this->parseCallbacks($callbacks); 122 | 123 | // Register Commands 124 | $telegram->addCommands($commands); 125 | $telegram->getCallbackBus()->addCallbackCommands($callbacks); 126 | 127 | return $telegram; 128 | } 129 | 130 | /** 131 | * Get the configuration for a bot. 132 | * 133 | * @param string|null $name 134 | * 135 | * @throws \InvalidArgumentException 136 | * 137 | * @return array 138 | */ 139 | public function getBotConfig($name = null) 140 | { 141 | $name = $name ?: $this->getDefaultBot(); 142 | 143 | $bots = $this->getConfig('bots'); 144 | if (!is_array($config = Arr::get($bots, $name)) && !$config) { 145 | throw new InvalidArgumentException("Bot [$name] not configured."); 146 | } 147 | 148 | $config['bot'] = $name; 149 | 150 | return $config; 151 | } 152 | 153 | /** 154 | * Get the default bot name. 155 | * 156 | * @return string 157 | */ 158 | public function getDefaultBot() 159 | { 160 | return $this->getConfig('default'); 161 | } 162 | 163 | /** 164 | * Get the specified configuration value for Telegram. 165 | * 166 | * @param string $key 167 | * @param mixed $default 168 | * 169 | * @return mixed 170 | */ 171 | public function getConfig($key, $default = null) 172 | { 173 | return Arr::get($this->config, $key, $default); 174 | } 175 | 176 | /** 177 | * Builds the list of commands for the given commands array. 178 | * 179 | * @param array $commands 180 | * 181 | * @return array An array of commands which includes global and bot specific commands. 182 | */ 183 | protected function parseBotCommands(array $commands) 184 | { 185 | $globalCommands = $this->getConfig('commands', []); 186 | $parsedCommands = $this->parseCommands($commands); 187 | 188 | return $this->deduplicateArray(array_merge($globalCommands, $parsedCommands)); 189 | } 190 | 191 | /** 192 | * Parse an array of commands and build a list. 193 | * 194 | * @param array $commands 195 | * 196 | * @return array 197 | */ 198 | protected function parseCommands(array $commands) 199 | { 200 | if (!is_array($commands)) { 201 | return $commands; 202 | } 203 | 204 | $commandGroups = $this->getConfig('command_groups'); 205 | $sharedCommands = $this->getConfig('shared_commands'); 206 | 207 | $results = []; 208 | foreach ($commands as $command) { 209 | // If the command is a group, we'll parse through the group of commands 210 | // and resolve the full class name. 211 | if (isset($commandGroups[$command])) { 212 | $results = array_merge( 213 | $results, 214 | $this->parseCommands($commandGroups[$command]) 215 | ); 216 | 217 | continue; 218 | } 219 | 220 | // If this command is actually a shared command, we'll extract the full 221 | // class name out of the command list now. 222 | if (isset($sharedCommands[$command])) { 223 | $command = $sharedCommands[$command]; 224 | } 225 | 226 | if (!in_array($command, $results)) { 227 | $results[] = $command; 228 | } 229 | } 230 | 231 | return $results; 232 | } 233 | 234 | /** 235 | * De-duplicate an array. 236 | * 237 | * @param array $array 238 | * 239 | * @return array 240 | */ 241 | protected function deduplicateArray(array $array) 242 | { 243 | return array_values(array_unique($array)); 244 | } 245 | 246 | /** 247 | * Parse an array of commands and build a list. 248 | * 249 | * @param array $commands 250 | * 251 | * @return array 252 | */ 253 | protected function parseCallbacks(array $commands) 254 | { 255 | if (!is_array($commands)) { 256 | return $commands; 257 | } 258 | 259 | $commandGroups = $this->getConfig('callback_groups'); 260 | $sharedCommands = $this->getConfig('shared_callbacks'); 261 | 262 | $results = []; 263 | foreach ($commands as $command) { 264 | // If the command is a group, we'll parse through the group of commands 265 | // and resolve the full class name. 266 | if (isset($commandGroups[$command])) { 267 | $results = array_merge( 268 | $results, 269 | $this->parseCallbacks($commandGroups[$command]) 270 | ); 271 | 272 | continue; 273 | } 274 | 275 | // If this command is actually a shared command, we'll extract the full 276 | // class name out of the command list now. 277 | if (isset($sharedCommands[$command])) { 278 | $command = $sharedCommands[$command]; 279 | } 280 | 281 | if (!in_array($command, $results)) { 282 | $results[] = $command; 283 | } 284 | } 285 | 286 | return $results; 287 | } 288 | 289 | /** 290 | * Set the default bot name. 291 | * 292 | * @param string $name 293 | * 294 | * @return $this 295 | */ 296 | public function setDefaultBot($name) 297 | { 298 | array_set($this->config, 'default', $name); 299 | 300 | return $this; 301 | } 302 | 303 | /** 304 | * Return all of the created bots. 305 | * 306 | * @return Api[] 307 | */ 308 | public function getBots() 309 | { 310 | return $this->bots; 311 | } 312 | 313 | /** 314 | * Magically pass methods to the default bot. 315 | * 316 | * @param string $method 317 | * @param array $parameters 318 | * 319 | * @return mixed 320 | */ 321 | public function __call($method, $parameters) 322 | { 323 | return call_user_func_array([$this->bot(), $method], $parameters); 324 | } 325 | } 326 | -------------------------------------------------------------------------------- /src/Objects/Message.php: -------------------------------------------------------------------------------- 1 | User::class, 70 | 'chat' => Chat::class, 71 | 'forward_from' => User::class, 72 | 'forward_from_chat' => Chat::class, 73 | 'reply_to_message' => self::class, 74 | 'via_bot' => User::class, 75 | 'entities' => MessageEntity::class, 76 | 'audio' => Audio::class, 77 | 'document' => Document::class, 78 | 'game' => Game::class, 79 | 'photo' => PhotoSize::class, 80 | 'sticker' => Sticker::class, 81 | 'video' => Video::class, 82 | 'voice' => Voice::class, 83 | 'video_note' => VideoNote::class, 84 | 'contact' => Contact::class, 85 | 'dice' => Dice::class, 86 | 'location' => Location::class, 87 | 'venue' => Venue::class, 88 | 'new_chat_member' => User::class, 89 | 'new_chat_members' => User::class, 90 | 'left_chat_member' => User::class, 91 | 'new_chat_photo' => PhotoSize::class, 92 | 'pinned_message' => self::class, 93 | 'invoice' => Invoice::class, 94 | 'successful_payment' => SuccessfulPayment::class, 95 | 'caption_entities' => MessageEntity::class, 96 | 'passport_data' => PassportData::class, 97 | ]; 98 | } 99 | 100 | /** 101 | * (Optional). For text messages, the actual UTF-8 text of the message. 102 | * 103 | * @return string 104 | */ 105 | public function getText() 106 | { 107 | return $this->get('text'); 108 | } 109 | 110 | /** 111 | * (Optional). Caption for the document, photo or video contact. 112 | * 113 | * @return string 114 | */ 115 | public function getCaption() 116 | { 117 | return $this->get('caption'); 118 | } 119 | 120 | /** 121 | * Determine if the message is of given type. 122 | * 123 | * @param string $type 124 | * 125 | * @return bool 126 | */ 127 | public function isType($type) 128 | { 129 | if ($this->has(strtolower($type))) { 130 | return true; 131 | } 132 | 133 | return $this->detectType() === $type; 134 | } 135 | 136 | /** 137 | * Detect type based on properties. 138 | * 139 | * @return string|null 140 | */ 141 | public function detectType() 142 | { 143 | $types = [ 144 | 'text', 145 | 'audio', 146 | 'document', 147 | 'game', 148 | 'photo', 149 | 'sticker', 150 | 'video', 151 | 'voice', 152 | 'video_note', 153 | 'contact', 154 | 'dice', 155 | 'location', 156 | 'venue', 157 | 'new_chat_member', 158 | 'new_chat_members', 159 | 'left_chat_member', 160 | 'new_chat_title', 161 | 'new_chat_photo', 162 | 'delete_chat_photo', 163 | 'group_chat_created', 164 | 'supergroup_chat_created', 165 | 'channel_chat_created', 166 | 'migrate_to_chat_id', 167 | 'migrate_from_chat_id', 168 | 'pinned_message', 169 | 'invoice', 170 | 'successful_payment', 171 | 'caption_entities', 172 | ]; 173 | 174 | return $this->keys() 175 | ->intersect($types) 176 | ->pop(); 177 | } 178 | } 179 | --------------------------------------------------------------------------------