diff --git a/.gitignore b/.gitignore index 91c7fb3..4e6114f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,5 @@ composer.phar Thumbs.db *.dat *.db +test.php +tags diff --git a/AvailableMethods.md b/AvailableMethods.md new file mode 100644 index 0000000..ad413d1 --- /dev/null +++ b/AvailableMethods.md @@ -0,0 +1,49 @@ +## Telegram Methods +- [x] getMe +- [x] sendMessage +- [x] forwardMessage +- [x] sendPhoto +- [x] sendAudio +- [x] sendDocument +- [x] sendSticker (Stickers section) +- [x] sendVideo +- [x] sendVoice +- [] sendVideoNote +- [] sendMediaGroup +- [x] sendLocation +- [] editMessageLiveLocation +- [] stopMessageLiveLocation +- [x] sendVenue +- [x] sendContact +- [x] sendChatAction +- [x] getUserProfilePhotos +- [x] getFile +- [] kickChatMember +- [] unbanChatMember +- [] restrictChatMember +- [] promoteChatMember +- [] exportChatInviteLink +- [] setChatPhoto +- [] deleteChatPhoto +- [] setChatTitle +- [] setChatDescription +- [] pinChatMessage +- [] unpinChatMessage +- [x] leaveChat +- [x] getChat +- [x] getChatAdministrators +- [x] getChatMembersCount +- [x] getChatMember +- [] setChatStickerSet +- [] deleteChatStickerSet +- [] answerCallbackQuery + +## Additional +- [x] getFileData +- [x] setWebhook +- [x] getWebhookUpdates +- [x] replyKeyboardMarkup +- [x] replyKeyboardHide +- [x] forceReply +- [x] sendRequest +- [x] uploadFile diff --git a/README.md b/README.md index 027c654..6c1be4a 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ A PHP wrapper for the Telegram Bot API. ## Requirements -- PHP 5.3 or higher +- PHP 5.5 or higher - cURL - Telegram app (mobile or desktop) diff --git a/composer.json b/composer.json index 4a059b9..9bc6d8e 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,7 @@ ] }, "require": { - "php": ">=5.3", + "php": ">=5.5", "ext-curl": "*" } } diff --git a/examples/exampleFunctional.php b/examples/exampleFunctional.php index f0caf32..495fde1 100644 --- a/examples/exampleFunctional.php +++ b/examples/exampleFunctional.php @@ -2,14 +2,24 @@ require '../src/Telegram.php'; -// // -///////// CONFIG YOUR BOT'S TOKEN ///////// +///////////// CONFIG YOUR BOT'S TOKEN ///////// +// Create telegram Bot token with @BotFather - https://github.com/mgp25/Telegram-Bot-API/wiki/Setup-Guide +$token = ""; // HERE YOUR TOKEN +////////////////////////////////////////////////// +echo "####################################\n"; +echo "# Telegram CLIENT #\n"; +echo "####################################\n\n"; + $tg = new telegramBot($token); $chat_id = null; $guessed = false; $sendQuestion = false; +$offset = 0; +echo "Get Bot Information:\n"; +$updates = $tg->getMe(); +echo json_encode($updates) . "\n"; // Custom keyboard $customKeyboard = [ @@ -25,7 +35,7 @@ // Get updates the bot has received // Offset to confirm previous updates $updates = $tg->pollUpdates($offset); - if ($updates['ok']) + if ($updates['ok'] && count($updates['result']) > 0) { foreach($updates['result'] as $data) { @@ -38,7 +48,8 @@ $tg->sendChatAction($chat_id, 'typing'); // send message with a custom reply markup - $tg->sendMessage($chat_id, 'Guess the number', false, null, $reply_markup); + $tg->sendMessage($chat_id, 'Guess the number', null, false, null, $reply_markup); + $sendQuestion = true; } @@ -51,8 +62,8 @@ $tg->sendPhoto($chat_id, 'https://upload.wikimedia.org/wikipedia/commons/thumb/f/fa/718smiley.png/220px-718smiley.png'); $guessed = true; } - else - $tg->sendMessage($chat_id, 'Wrong number :/ try again', false, null, $reply_markup); + else + $tg->sendMessage($chat_id, 'Wrong number :/ try again', null, false, null, $reply_markup); } $offset = $updates['result'][count($updates['result']) - 1]['update_id'] + 1; } diff --git a/examples/quoteBot.php b/examples/quoteBot.php new file mode 100644 index 0000000..03fa465 --- /dev/null +++ b/examples/quoteBot.php @@ -0,0 +1,138 @@ +pollUpdates($offset, 60); + $response = json_decode($response, true); + + if ($response['ok']) + { + foreach($response['result'] as $data) + { + $chatID = $data['message']['chat']['id']; + switch ($data['message']['text']) + { + case '/start': + addContact($chatID); + break; + case '/remove': + deleteContact($chatID); + break; + } + } + $offset = $response['result'][count($response['result']) - 1]['update_id'] + 1; + } + $chats = allChats(); + $quotes = readQuotes(); + + $i = 0; + for ($i; $i < count($chats); $i++) + { + $tg->sendMessage($chats[$i]['chat_id'], $quotes[$chats[$i]['init']]); + updateInit($chats[$i]['chat_id']); + + if ($chats[$i]['init'] == count($quotes) - 1) + resetInit($chats[$i]['chat_id']); + } + + +function addContact($chatID) +{ + $contactsDB = __DIR__ . DIRECTORY_SEPARATOR . 'contacts.db'; + if (!file_exists($contactsDB)) + { + $db = new \PDO("sqlite:" . $contactsDB, null, null, array(PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); + $db->exec('CREATE TABLE contacts (`chat_id` TEXT, `init` INT)'); + } + else { + $db = new \PDO("sqlite:" . $contactsDB, null, null, array(PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); + } + + $sql = 'SELECT chat_id FROM contacts WHERE chat_id = :chat_id'; + $query = $db->prepare($sql); + $query->execute( + array( + ':chat_id' => $chatID + ) + ); + $chat = $query->fetchAll(); + if ($chat[0]['chat_id'] == null) + { + $sql = 'INSERT INTO contacts (`chat_id`, `init`) VALUES (:chat_id, :init)'; + $query = $db->prepare($sql); + + $query->execute( + array( + ':chat_id' => $chatID, + ':init' => 0 + ) + ); + } +} + +function deleteContact($chatID) +{ + $contactsDB = __DIR__ . DIRECTORY_SEPARATOR . 'contacts.db'; + $cDB = new \PDO("sqlite:" . $contactsDB, null, null, array(PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); + $sql = "DELETE FROM contacts WHERE chat_id = :chat_id"; + $query = $cDB->prepare($sql); + $query->execute(array(':chat_id' => $chatID)); +} + +function allChats() +{ + $contactsDB = __DIR__ . DIRECTORY_SEPARATOR . 'contacts.db'; + $db = new \PDO("sqlite:" . $contactsDB, null, null, array(PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); + + $sql = 'SELECT chat_id, init FROM contacts'; + $query = $db->prepare($sql); + $query->execute(); + + $chats = $query->fetchAll(); + + return $chats; +} + +function readQuotes() +{ + $quotesFile = __DIR__ . DIRECTORY_SEPARATOR . 'quotes'; + $quotes = array_filter(explode("\n", file_get_contents($quotesFile))); + + return $quotes; +} + +function updateInit($chatID) +{ + $contactsDB = __DIR__ . DIRECTORY_SEPARATOR . 'contacts.db'; + $db = new \PDO("sqlite:" . $contactsDB, null, null, array(PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); + + $sql = "UPDATE contacts SET init = init + 1 WHERE chat_id = :chat_id"; + $query = $db->prepare($sql); + $query->execute( + array( + ':chat_id' => $chatID + ) + ); +} + +function resetInit($chatID) +{ + $contactsDB = __DIR__ . DIRECTORY_SEPARATOR . 'contacts.db'; + $db = new \PDO("sqlite:" . $contactsDB, null, null, array(PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); + + $sql = "UPDATE contacts SET init = 0 WHERE chat_id = :chat_id"; + $query = $db->prepare($sql); + $query->execute( + array( + ':chat_id' => $chatID + ) + ); +} diff --git a/src/Telegram.php b/src/Telegram.php index 0a678c0..632654a 100644 --- a/src/Telegram.php +++ b/src/Telegram.php @@ -4,426 +4,582 @@ class telegramBot { - const BASE_URL = 'https://api.telegram.org/bot'; - - protected $token; - - public function __construct($token) - { - $this->token = $token; - if (is_null($this->token)) - throw new TelegramException('Required "token" key not supplied'); - - $this->baseURL = self::BASE_URL . $this->token . DIRECTORY_SEPARATOR; - } - - /** - * A simple method for testing your bot's auth token. - * Returns basic information about the bot in form of a User object. - * - * @link https://core.telegram.org/bots/api#getme - * - * @return Array - */ - public function getMe() - { - return $this->sendRequest('getMe', array()); - } - - - /** - * Use this method to receive incoming updates using long polling. - * - * @link https://core.telegram.org/bots/api#getupdates - * - * @param int $offset - * @param int $limit - * @param int $timeout - * - * @return Array - */ - public function pollUpdates($offset = null, $timeout = null, $limit = null) - { - $params = compact('offset', 'limit', 'timeout'); - - return $this->sendRequest('getUpdates', $params); - } - - /** - * Send text messages. - * - * @link https://core.telegram.org/bots/api#sendmessage - * - * @param int $chat_id - * @param string $text - * @param bool $disable_web_page_preview - * @param int $reply_to_message_id - * @param KeyboardMarkup $reply_markup - * - * @return Array - */ - public function sendMessage($chat_id, $text, $disable_web_page_preview = false, $reply_to_message_id = null, $reply_markup = null) - { - $params = compact('chat_id', 'text', 'disable_web_page_preview', 'reply_to_message_id', 'reply_markup'); - - return $this->sendRequest('sendMessage', $params); - } - - /** - * Forward messages of any kind. - * - * @link https://core.telegram.org/bots/api#forwardmessage - * - * @param int $chat_id - * @param int $from_chat_id - * @param int $message_id - * - * @return Array - */ - public function forwardMessage($chat_id, $from_chat_id, $from_chat_id) - { - $params = compact('chat_id', 'from_chat_id', 'from_chat_id'); - - return $this->sendRequest('forwardMessage', $params); - } - - /** - * Send Photos. - * - * @link https://core.telegram.org/bots/api#sendphoto - * - * @param int $chat_id - * @param string $photo - * @param string $caption - * @param int $reply_to_message_id - * @param KeyboardMarkup $reply_markup - * - * @return Array - */ - public function sendPhoto($chat_id, $photo, $caption = null, $reply_to_message_id = null, $replyMarkup = null) - { - $data = compact('chat_id', 'photo', 'caption', 'reply_to_message_id', 'reply_markup'); - - if (((!is_dir($photo)) && (filter_var($photo, FILTER_VALIDATE_URL) === FALSE))) - return $this->sendRequest('sendPhoto', $data); - - return $this->uploadFile('sendPhoto', $data); - } - - /** - * Send Audio. - * - * @link https://core.telegram.org/bots/api#sendaudio - * - * @param int $chat_id - * @param string $audio - * @param int $reply_to_message_id - * @param KeyboardMarkup $reply_markup - * - * @return Array - */ - public function sendAudio($chat_id, $audio, $reply_to_message_id = null, $replyMarkup = null) - { - $data = compact('chat_id', 'audio', 'reply_to_message_id', 'reply_markup'); - - if (((!is_dir($audio)) && (filter_var($audio, FILTER_VALIDATE_URL) === FALSE))) - return $this->sendRequest('sendAudio', $data); - - return $this->uploadFile('sendAudio', $data); - } - - /** - * Send Document. - * - * @link https://core.telegram.org/bots/api#senddocument - * - * @param int $chat_id - * @param string $document - * @param int $reply_to_message_id - * @param KeyboardMarkup $reply_markup - * - * @return Array - */ - public function sendDocument($chat_id, $document, $reply_to_message_id = null, $replyMarkup = null) - { - $data = compact('chat_id', 'document', 'reply_to_message_id', 'reply_markup'); - - if (((!is_dir($document)) && (filter_var($document, FILTER_VALIDATE_URL) === FALSE))) - return $this->sendRequest('sendDocument', $data); - - return $this->uploadFile('sendDocument', $data); - } - - /** - * Send Sticker. - * - * @link https://core.telegram.org/bots/api#sendsticker - * - * @param int $chat_id - * @param string $sticker - * @param int $reply_to_message_id - * @param KeyboardMarkup $reply_markup - * - * @return Array - */ - public function sendSticker($chat_id, $sticker, $reply_to_message_id = null, $replyMarkup = null) - { - $data = compact('chat_id', 'sticker', 'reply_to_message_id', 'reply_markup'); - - if (((!is_dir($sticker)) && (filter_var($sticker, FILTER_VALIDATE_URL) === FALSE))) - return $this->sendRequest('sendSticker', $data); - - return $this->uploadFile('sendSticker', $data); - } - - /** - * Send Video. - * - * @link https://core.telegram.org/bots/api#sendvideo - * - * @param int $chat_id - * @param string $video - * @param int $reply_to_message_id - * @param KeyboardMarkup $reply_markup - * - * @return Array - */ - public function sendVideo($chat_id, $video, $reply_to_message_id = null, $replyMarkup = null) - { - $data = compact('chat_id', 'video', 'reply_to_message_id', 'reply_markup'); - - if (((!is_dir($video)) && (filter_var($video, FILTER_VALIDATE_URL) === FALSE))) - return $this->sendRequest('sendVideo', $data); - - return $this->uploadFile('sendVideo', $data); - } - - /** - * Send Location. - * - * @link https://core.telegram.org/bots/api#sendlocation - * - * @param int $chat_id - * @param float $latitude - * @param float $longitude - * @param int $reply_to_message_id - * @param KeyboardMarkup $reply_markup - * - * @return Array - */ - public function sendLocation($chat_id, $latitude, $longitude, $reply_to_message_id = null, $reply_markup = null) - { - $params = compact('chat_id', 'latitude', 'longitude', 'reply_to_message_id', 'reply_markup'); - - return $this->sendRequest('sendLocation', $params); - } - - /** - * Send Chat Action. - * - * @link https://core.telegram.org/bots/api#sendchataction - * - * @param int $chat_id - * @param string $action - * - * @return Array - */ - public function sendChatAction($chat_id, $action) - { - $actions = array( - 'typing', - 'upload_photo', - 'record_video', - 'upload_video', - 'record_audio', - 'upload_audio', - 'upload_document', - 'find_location', - ); - if (isset($action) && in_array($action, $actions)) - { - $params = compact('chat_id', 'action'); - return $this->sendRequest('sendChatAction', $params); - } - - throw new TelegramException('Invalid Action! Accepted value: '.implode(', ', $actions)); - } - - /** - * Get user profile photos. - * - * @link https://core.telegram.org/bots/api#getsserprofilephotos - * - * @param int $chat_id - * @param int $offset - * @param int $limit - * - * @return Array - */ - public function getUserProfilePhotos($user_id, $offset = null, $limit = null) - { - $param = compact('user_id', 'offset', 'limit'); - - return $this->sendRequest('getUserProfilePhotos', $params); - } - - /** - * Set a Webhook to receive incoming updates via an outgoing webhook. - * - * @param string $url HTTPS url to send updates to. - * - * @return Array - * - */ - public function setWebhook($url) - { - if (filter_var($url, FILTER_VALIDATE_URL) === false) - throw new TelegramException('Invalid URL provided'); - - if (parse_url(http://github.com/$url,%20PHP_URL_SCHEME) !== 'https') - throw new TelegramException('Invalid URL, it should be a HTTPS url.'); - - return $this->sendRequest('setWebhook', $url); -} - - /** - * Returns webhook updates sent by Telegram. - * Works only if you set a webhook. - * - * @see setWebhook - * - * @return Array - */ - public function getWebhookUpdates() - { - $body = json_decode(file_get_contents('php://input'), true); - - return $body; - } - - /** - * Removes the outgoing webhook. - * - * @return Array - */ - public function removeWebhook() - { - $url = ''; - return $this->sendRequest('setWebhook', compact('url')); - } - - /** - * Builds a custom keyboard markup. - * - * @link https://core.telegram.org/bots/api#replykeyboardmarkup - * - * @param array $keyboard - * @param bool $resize_keyboard - * @param bool $one_time_keyboard - * @param bool $selective - * - * @return string - */ - public function replyKeyboardMarkup($keyboard, $resize_keyboard = false, $one_time_keyboard = false, $selective = false) - { - return json_encode(compact('keyboard', 'resize_keyboard', 'one_time_keyboard', 'selective')); - } - - /** - * Hide the current custom keyboard and display the default letter-keyboard. - * - * @link https://core.telegram.org/bots/api#replykeyboardhide - * - * @param bool $selective - * - * @return string - */ - public static function replyKeyboardHide($selective = false) - { - $hide_keyboard = true; - return json_encode(compact('hide_keyboard', 'selective')); - } - - /** - * Display a reply interface to the user (act as if the user has selected the bots message and tapped 'Reply'). - * - * @link https://core.telegram.org/bots/api#forcereply - * - * @param bool $selective - * - * @return string - */ - public static function forceReply($selective = false) - { - $force_reply = true; - return json_encode(compact('force_reply', 'selective')); - } - - private function sendRequest($method, $params) - { - return json_decode(file_get_contents($this->baseURL . $method . '?' . http_build_query($params)), true); - } - - private function uploadFile($method, $data) - { - $key = array( - 'sendPhoto' => 'photo', - 'sendAudio' => 'audio', - 'sendDocument' => 'document', - 'sendSticker' => 'sticker', - 'sendVideo' => 'video' - ); - - $file = __DIR__ . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR . mt_rand(0, 9999); - if (filter_var($data[$key[$method]], FILTER_VALIDATE_URL)) - { - $url = true; - file_put_contents($file, file_get_contents($data[$key[$method]])); - $finfo = finfo_open(FILEINFO_MIME_TYPE); - $mime_type = finfo_file($finfo, $file); - - $extensions = array( - 'image/jpeg' => '.jpg', - 'image/png' => '.png', - 'image/gif' => '.gif', - 'image/bmp' => '.bmp', - 'image/tiff' => '.tif', - 'audio/ogg' => '.ogg', - 'video/mp4' => '.mp4', - 'image/webp' => '.webp' - ); - - if ($method != 'sendDocument') - { - if (!array_key_exists($mime_type, $extensions)) - { - unlink($file); - throw new TelegramException('Bad file type/extension'); - } - } - - $newFile = $file . $extensions[$mime_type]; - rename($file, $newFile); - $data[$key[$method]] = new CurlFile($newFile, $mime_type, $newFile); - } - else - { - $finfo = finfo_open(FILEINFO_MIME_TYPE); - $mime_type = finfo_file($finfo, $data[$key[$method]]); - $data[$key[$method]] = new CurlFile($data[$key[$method]], $mime_type, $data[$key[$method]]); - } - - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $this->baseURL . $method); - curl_setopt($ch, CURLOPT_POST, 1); - curl_setopt($ch, CURLOPT_POSTFIELDS, $data); - - $response = json_decode(curl_exec($ch), true); - - if ($url) - unlink($newFile); - - return $response; - } + const BASE_URL = 'https://api.telegram.org/'; + const BOT_URL = '/bot'; + const FILE_URL = '/file'; + + protected $token; + + public function __construct($token) + { + $this->token = $token; + if (is_null($this->token)) { + throw new TelegramException('Required "token" key not supplied'); + } + $this->baseURL = self::BASE_URL . self::BOT_URL . $this->token . '/'; + $this->baseFileURL = self::BASE_URL . self::FILE_URL . self::BOT_URL . $this->token . '/'; + } + + /** + * Use this method to receive incoming updates using long polling. + * + * @link https://core.telegram.org/bots/api#getupdates + * + * @param int $offset + * @param int $limit + * @param int $timeout + * + * @return Array + */ + public function pollUpdates($offset = null, $timeout = null, $limit = null) + { + $params = compact('offset', 'limit', 'timeout'); + return $this->sendRequest('getUpdates', $params); + } + + /** + * A simple method for testing your bot's auth token. + * Returns basic information about the bot in form of a User object. + * + * @link https://core.telegram.org/bots/api#getme + * + * @return Array + */ + public function getMe() + { + return $this->sendRequest('getMe', array()); + } + + /** + * Send text messages. + * + * @link https://core.telegram.org/bots/api#sendmessage + * + * @param int $chat_id + * @param string $text + * @param string $parse_mode + * @param bool $disable_web_page_preview + * @param int $reply_to_message_id + * @param KeyboardMarkup $reply_markup + * + * @return Array + */ + public function sendMessage($chat_id, $text, $parse_mode = null, $disable_web_page_preview = false, $reply_to_message_id = null, $reply_markup = null) + { + $params = compact('chat_id', 'text', 'parse_mode', 'disable_web_page_preview', 'reply_to_message_id', 'reply_markup'); + return $this->sendRequest('sendMessage', $params); + } + + /** + * Forward messages of any kind. + * + * @link https://core.telegram.org/bots/api#forwardmessage + * + * @param int $chat_id + * @param int $from_chat_id + * @param int $message_id + * + * @return Array + */ + public function forwardMessage($chat_id, $from_chat_id, $message_id) + { + $params = compact('chat_id', 'from_chat_id', 'message_id'); + return $this->sendRequest('forwardMessage', $params); + } + + /** + * Send Photos. + * + * @link https://core.telegram.org/bots/api#sendphoto + * + * @param int $chat_id + * @param string $photo + * @param string $caption + * @param int $reply_to_message_id + * @param KeyboardMarkup $reply_markup + * + * @return Array + */ + public function sendPhoto($chat_id, $photo, $caption = null, $reply_to_message_id = null, $reply_markup = null) + { + $data = compact('chat_id', 'photo', 'caption', 'reply_to_message_id', 'reply_markup'); + if (((!is_dir($photo)) && (filter_var($photo, FILTER_VALIDATE_URL) === FALSE))) { + return $this->sendRequest('sendPhoto', $data); + } + return $this->uploadFile('sendPhoto', $data); + } + + /** + * Send Audio. + * + * @link https://core.telegram.org/bots/api#sendaudio + * + * @param int $chat_id + * @param string $audio + * @param int $duration + * @param string $performer + * @param string $title + * @param int $reply_to_message_id + * @param KeyboardMarkup $reply_markup + * + * @return Array + */ + public function sendAudio($chat_id, $audio, $duration = null, $performer = null, $title = null, $reply_to_message_id = null, $reply_markup = null) + { + $data = compact('chat_id', 'audio', 'duration', 'performer', 'title', 'reply_to_message_id', 'reply_markup'); + if (((!is_dir($audio)) && (filter_var($audio, FILTER_VALIDATE_URL) === FALSE))) { + return $this->sendRequest('sendAudio', $data); + } + return $this->uploadFile('sendAudio', $data); + } + + /** + * Send Document. + * + * @link https://core.telegram.org/bots/api#senddocument + * + * @param int $chat_id + * @param string $document + * @param int $reply_to_message_id + * @param KeyboardMarkup $reply_markup + * + * @return Array + */ + public function sendDocument($chat_id, $document, $reply_to_message_id = null, $reply_markup = null) + { + $data = compact('chat_id', 'document', 'reply_to_message_id', 'reply_markup'); + if (((!is_dir($document)) && (filter_var($document, FILTER_VALIDATE_URL) === FALSE))) { + return $this->sendRequest('sendDocument', $data); + } + return $this->uploadFile('sendDocument', $data); + } + + /** + * Send Sticker. + * + * @link https://core.telegram.org/bots/api#sendsticker + * + * @param int $chat_id + * @param string $sticker + * @param int $reply_to_message_id + * @param KeyboardMarkup $reply_markup + * + * @return Array + */ + public function sendSticker($chat_id, $sticker, $reply_to_message_id = null, $reply_markup = null) + { + $data = compact('chat_id', 'sticker', 'reply_to_message_id', 'reply_markup'); + if (((!is_dir($sticker)) && (filter_var($sticker, FILTER_VALIDATE_URL) === FALSE))) { + return $this->sendRequest('sendSticker', $data); + } + return $this->uploadFile('sendSticker', $data); + } + + /** + * Send Video. + * + * @link https://core.telegram.org/bots/api#sendvideo + * + * @param int $chat_id + * @param string $video + * @param int $duration + * @param string $caption + * @param int $reply_to_message_id + * @param KeyboardMarkup $reply_markup + * + * @return Array + */ + public function sendVideo($chat_id, $video, $duration = null, $caption = null, $reply_to_message_id = null, $reply_markup = null) + { + $data = compact('chat_id', 'video', 'duration', 'caption', 'reply_to_message_id', 'reply_markup'); + + if (((!is_dir($video)) && (filter_var($video, FILTER_VALIDATE_URL) === FALSE))) { + return $this->sendRequest('sendVideo', $data); + } + return $this->uploadFile('sendVideo', $data); + } + + /** + * Send Voice. + * + * @link https://core.telegram.org/bots/api#sendvoice + * + * @param int $chat_id + * @param string $audio + * @param int $duration + * @param int $reply_to_message_id + * @param KeyboardMarkup $reply_markup + * + * @return Array + */ + public function sendVoice($chat_id, $audio, $duration = null, $reply_to_message_id = null, $reply_markup = null) + { + $data = compact('chat_id', 'audio', 'duration', 'reply_to_message_id', 'reply_markup'); + if (((!is_dir($audio)) && (filter_var($audio, FILTER_VALIDATE_URL) === FALSE))) { + return $this->sendRequest('sendVoice', $data); + } + return $this->uploadFile('sendVoice', $data); + } + + /** + * Send Location. + * + * @link https://core.telegram.org/bots/api#sendlocation + * + * @param int $chat_id + * @param float $latitude + * @param float $longitude + * @param int $reply_to_message_id + * @param KeyboardMarkup $reply_markup + * + * @return Array + */ + public function sendLocation($chat_id, $latitude, $longitude, $reply_to_message_id = null, $reply_markup = null) + { + $params = compact('chat_id', 'latitude', 'longitude', 'reply_to_message_id', 'reply_markup'); + return $this->sendRequest('sendLocation', $params); + } + + /** + * Send Venue. + * + * @link https://core.telegram.org/bots/api#sendvenue + * + * @param int $chat_id + * @param float $latitude + * @param float $longitude + * @param string $title + * @param string $address + * @param string $foursquare_id + * @param int $reply_to_message_id + * @param KeyboardMarkup $reply_markup + * + * @return Array + */ + public function sendVenue($chat_id, $latitude, $longitude, $title, $address, $foursquare_id = null, $reply_to_message_id = null, $reply_markup = null) + { + $params = compact('chat_id', 'latitude', 'longitude', 'title', 'address', 'foursquare_id', 'reply_to_message_id', 'reply_markup'); + return $this->sendRequest('sendVenue', $params); + } + /** + * Send Contact. + * + * @link https://core.telegram.org/bots/api#sendcontact + * + * @param int $chat_id + * @param string $phonenumber + * @param string $first_name + * @param string $last_name + * @param bool $disable_notification + * @param int $reply_to_message_id + * @param KeyboardMarkup $reply_markup + * + * @return Array + */ + public function sendContact($chat_id, $phone_number, $first_name, $last_name = null, $reply_to_message_id = null, $reply_markup = null) + { + $params = compact('chat_id', 'phone_number', 'first_name', 'last_name', 'reply_to_message_id', 'reply_markup'); + return $this->sendRequest('sendContact', $params); + } + + /** + * Send Chat Action. + * + * @link https://core.telegram.org/bots/api#sendchataction + * + * @param int $chat_id + * @param string $action + * + * @return Array + */ + public function sendChatAction($chat_id, $action) + { + $actions = array( + 'typing', + 'upload_photo', + 'record_video', + 'upload_video', + 'record_audio', + 'upload_audio', + 'upload_document', + 'find_location', + ); + if (isset($action) && in_array($action, $actions)) { + $params = compact('chat_id', 'action'); + return $this->sendRequest('sendChatAction', $params); + } + throw new TelegramException('Invalid Action! Accepted value: '.implode(', ', $actions)); + } + + /** + * Get user profile photos. + * + * @link https://core.telegram.org/bots/api#getsserprofilephotos + * + * @param int $chat_id + * @param int $offset + * @param int $limit + * + * @return Array + */ + public function getUserProfilePhotos($user_id, $offset = null, $limit = null) + { + $params = compact('user_id', 'offset', 'limit'); + return $this->sendRequest('getUserProfilePhotos', $params); + } + + /** + * Use this method to get basic info about a file and prepare it for downloading. + * + * @link https://core.telegram.org/bots/api#getfile + * + * @param String $file_id + * + * @return On success, a File object is returned + */ + public function getFile($file_id) + { + return $this->sendRequest('getFile', compact('file_id')); + } + + /** + * Use this method for your bot to leave a group, supergroup or channel. + * Returns True on success. + * + * @link https://core.telegram.org/bots/api#leavechat + * + * @param int|string id or username of the supergroup or channel + * + * @return True on success + */ + public function leaveChat($chat_id) + { + $params = compact('chat_id'); + return $this->sendRequest('leaveChat', $params); + } + + /** + * Use this method to get up to date information about the chat. + * Returns a Chat object on success. + * + * @link https://core.telegram.org/bots/api#getchat + * + * @param int|string id or username of the supergroup or channel + * + * @return Chat object + */ + public function getChat($chat_id) + { + $params = compact('chat_id'); + return $this->sendRequest('getChat', $params); + } + + /** + * Use this method to get a list of administrators in a chat. + * Returns an Array of ChatMember objects on success + * + * @link https://core.telegram.org/bots/api#getchatadministrators + * + * @param int|string id or username of the supergroup or channel + * + * @return Array of ChatMember objects + */ + public function getChatAdministrators($chat_id) + { + $params = compact('chat_id'); + return $this->sendRequest('getChatAdministrators', $params); + } + + /** + * Use this method to get the number of members in a chat. + * Returns Int on success. + * + * @link https://core.telegram.org/bots/api#getchatmemberscount + * + * @param int|string id or username of the supergroup or channel + * + * @return int amount of chat members + */ + public function getChatMembersCount($chat_id) + { + $params = compact('chat_id'); + return $this->sendRequest('getChatMembersCount', $params); + } + + /** + * Use this method to get information about a member of a chat. + * Returns a ChatMember object on success. + * + * @link https://core.telegram.org/bots/api#getchatmember + * + * @param int|string id or username of the supergroup or channel + * @param int Unique identifier of the target user + * + * @return ChatMember object + */ + public function getChatMember($chat_id, $user_id) + { + $params = compact('chat_id', 'user_id'); + return $this->sendRequest('getChatMember', $params); + } + + /** + * Use this method to get file Data. + * + * @link https://core.telegram.org/bots/api#getfile + * + * @see getFile + * + * @param string $file_id + * @param string $file_path Is taken from the getFile response + * + * @return On success, a File Data is returned + */ + public function getFileData($file_id, $file_path) + { + return file_get_contents($this->baseFileURL . $file_path . '?' . http_build_query(compact('file_id'))); + } + + /** + * Set a Webhook to receive incoming updates via an outgoing webhook. + * + * @param string $url HTTPS url to send updates to. Use an empty string to remove webhook integration + * @param InputFile $cerificate Upload your public key certificate so that the root certificate in use can be checked + * + * @return Array + * + */ + public function setWebhook($url, $certificate = null) + { + if (filter_var($url, FILTER_VALIDATE_URL) === false) { + throw new TelegramException('Invalid URL provided'); + } + if (parse_url(http://github.com/$url,%20PHP_URL_SCHEME) !== 'https') { + throw new TelegramException('Invalid URL, it should be a HTTPS url.'); + } + if (is_null($certificate)) { + return $this->sendRequest('setWebhook', compact('url', 'certificate')); + } else { + return $this->uploadFile('setWebhook', compact('url', 'certificate')); + } + } + + /** + * Returns webhook updates sent by Telegram. + * Works only if you set a webhook. + * + * @see setWebhook + * + * @return Array + */ + public function getWebhookUpdates() + { + $body = json_decode(file_get_contents('php://input'), true); + return $body; + } + + /** + * Builds a custom keyboard markup. + * + * @link https://core.telegram.org/bots/api#replykeyboardmarkup + * + * @param array $keyboard + * @param bool $resize_keyboard + * @param bool $one_time_keyboard + * @param bool $selective + * + * @return string + */ + public function replyKeyboardMarkup($keyboard, $resize_keyboard = false, $one_time_keyboard = false, $selective = false) + { + return json_encode(compact('keyboard', 'resize_keyboard', 'one_time_keyboard', 'selective')); + } + + /** + * Hide the current custom keyboard and display the default letter-keyboard. + * + * @link https://core.telegram.org/bots/api#replykeyboardhide + * + * @param bool $selective + * + * @return string + */ + public static function replyKeyboardHide($selective = false) + { + $hide_keyboard = true; + return json_encode(compact('hide_keyboard', 'selective')); + } + + /** + * Display a reply interface to the user (act as if the user has selected the bots message and tapped 'Reply'). + * + * @link https://core.telegram.org/bots/api#forcereply + * + * @param bool $selective + * + * @return string + */ + public static function forceReply($selective = false) + { + $force_reply = true; + return json_encode(compact('force_reply', 'selective')); + } + + private function sendRequest($method, $params) + { + return json_decode(file_get_contents($this->baseURL . $method . '?' . http_build_query($params)), true); + } + + private function uploadFile($method, $data) + { + $key = array( + 'sendPhoto' => 'photo', + 'sendAudio' => 'audio', + 'sendDocument' => 'document', + 'sendSticker' => 'sticker', + 'sendVideo' => 'video', + 'setWebhook' => 'certificate' + ); + if (filter_var($data[$key[$method]], FILTER_VALIDATE_URL)) { + $file = __DIR__ . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR . mt_rand(0, 9999); + $url = true; + file_put_contents($file, file_get_contents($data[$key[$method]])); + $finfo = finfo_open(FILEINFO_MIME_TYPE); + $mime_type = finfo_file($finfo, $file); + $extensions = array( + 'image/jpeg' => '.jpg', + 'image/png' => '.png', + 'image/gif' => '.gif', + 'image/bmp' => '.bmp', + 'image/tiff' => '.tif', + 'audio/ogg' => '.ogg', + 'audio/mpeg' => '.mp3', + 'video/mp4' => '.mp4', + 'image/webp' => '.webp' + ); + if ($method != 'sendDocument') { + if (!array_key_exists($mime_type, $extensions)) { + unlink($file); + throw new TelegramException('Bad file type/extension'); + } + } + $newFile = $file . $extensions[$mime_type]; + rename($file, $newFile); + $data[$key[$method]] = new CurlFile($newFile, $mime_type, $newFile); + } else { + $finfo = finfo_open(FILEINFO_MIME_TYPE); + $mime_type = finfo_file($finfo, $data[$key[$method]]); + $data[$key[$method]] = new CurlFile($data[$key[$method]], $mime_type, $data[$key[$method]]); + } + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $this->baseURL . $method); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $data); + $response = json_decode(curl_exec($ch), true); + if ($url) { + unlink($newFile); + } + return $response; + } }