Created
September 19, 2021 20:12
-
-
Save klim2020/5cddd66e7f2aa5592c420a2f9b6c70e4 to your computer and use it in GitHub Desktop.
My homebrew TelegramBOT PHP class. It isn't perfect but for my needs it's good enough.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Class TelegramBot | |
* @author Lava Git | |
* @version 2.2 | |
*/ | |
class TelegramBot { | |
private $botKey; | |
private $hookKey; | |
private $hookURL; | |
private $botAgent; | |
private $telegramUpdate; | |
private $rootKey = 'message'; | |
/** | |
* TelegramBot constructor. | |
* @param string $botKey The bot key (longest random character string). | |
* @param string $hookKey The hook key (shortest random character string). | |
* @param string $hookURL Where the bots index/root directory is. E.g. https://mybot.ninja/telegrambot/. | |
* @param string $botAgent The user agent used when connecting to Telegram servers. | |
*/ | |
function __construct($botKey, $hookKey = "", $hookURL = "", $botAgent = "Lavas PHP Telegram BOT") { | |
$this->botKey = $botKey; | |
$this->hookKey = $hookKey; | |
$this->hookURL = $hookURL; | |
$this->botAgent = $botAgent; | |
} | |
/** | |
* @return string The bot key. | |
*/ | |
private function getBotKey() { | |
return $this->botKey; | |
} | |
/** | |
* @return string The hook key. | |
*/ | |
private function getHookKey() { | |
return $this->hookKey; | |
} | |
/** | |
* @return string The hook URL. | |
*/ | |
private function getHookURL() { | |
return $this->hookURL; | |
} | |
/** | |
* @return string The bot user agent used when connecting to the Telegram BOT API. | |
*/ | |
private function getBotAgent() { | |
return $this->botAgent; | |
} | |
/** | |
* This is used to check if the hook key presented by the client is valid. Use this before responding to any requests. | |
* @param string $string The hook string that is being used to communicate with the bot (only Telegram should know this). | |
* @return bool|null | |
*/ | |
function isHookValid($string) { | |
if ("$string" == $this->getHookKey()) { | |
return true; | |
} | |
return null; | |
} | |
/** | |
* Was the bot called by Telegram? | |
* @return bool|null true if the bot was called by Telegram, using the correct hook. | |
*/ | |
function fromTelegram() { | |
if (isset($_GET['telegramUpdate']) && $_GET['telegramUpdate'] == $this->isHookValid($_GET['telegramUpdate'])) { | |
return true; | |
} | |
return null; | |
} | |
/** | |
* Downloads a file from telegram servers and returns the contents. Use this with file_put_contents or a similar function. | |
* @param $file_path | |
* @return bool|string | |
*/ | |
function getFile($file_path) { | |
$curl = curl_init("https://api.telegram.org/file/bot" . $this->getBotKey() . "/$file_path"); | |
curl_setopt($curl , CURLOPT_RETURNTRANSFER, true); | |
curl_setopt($curl, CURLOPT_USERAGENT, $this->getBotAgent()); | |
return curl_exec($curl); | |
} | |
/** | |
* Lets the user know that the bot is processing their request. | |
* @param string $action typing, upload_photo, record_video, upload_video, record_voice, upload_voice, upload_document, find_location, record_video_note, upload_video_note | |
*/ | |
function sendChatAction($action) { | |
$this->sendPOST("sendChatAction", array( | |
"chat_id" => $this->getChatID(), | |
"action" => "$action")); | |
} | |
/** | |
* Send a GET request to the Telegram bot API. | |
* @param string $type getFile, etc. | |
* @param array $paramArray arguments used with the API method/type. | |
* @return bool|string Returns Telegram's response. | |
*/ | |
function sendGET($type, $paramArray = array()) { | |
/* | |
$type: getFile etc | |
$paramArray: An array of the fields to put in the GET request to Telegram | |
*/ | |
$fields = "$type?"; | |
foreach ($paramArray as $param => $value) { | |
$fields .= "$param=$value&"; | |
} | |
$curl = curl_init("https://api.telegram.org/bot" . $this->getBotKey() . "/$fields"); | |
curl_setopt($curl , CURLOPT_RETURNTRANSFER, true); | |
curl_setopt($curl, CURLOPT_USERAGENT, $this->getBotAgent()); | |
return curl_exec($curl); | |
} | |
/** | |
* Send a POST request to the Telegram BOT API. | |
* @param string $type sendMessage, sendVoice, sendVideo etc. | |
* @param array $postArray An array of the fields to post to Telegram | |
* @return array|string|null Returns Telegrams response. Null is returned if a file is to be posted but cannot be found. | |
*/ | |
function sendPOST($type, $postArray = array()) { | |
$curl = curl_init("https://api.telegram.org/bot" . $this->getBotKey() . "/$type"); | |
curl_setopt($curl, CURLOPT_HTTPHEADER, array( | |
"Content-Type:multipart/form-data" | |
)); | |
foreach(array("photo", "video", "document", "audio", "voice") as $mediaType) { | |
if (isset($postArray[$mediaType])) { | |
if (file_exists($postArray[$mediaType])) { | |
$postArray[$mediaType] = new CURLFile(realpath($postArray[$mediaType])); | |
} else { | |
error_log("sendPOST: Cannot find the file \"".$postArray[$mediaType]."\""); | |
return null; // File not found | |
} | |
} | |
} | |
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); | |
curl_setopt($curl, CURLOPT_USERAGENT, $this->getBotAgent()); | |
//curl_setopt($curl, CURLOPT_POST, 1); | |
curl_setopt($curl, CURLOPT_POSTFIELDS, $postArray); | |
return curl_exec($curl); | |
} | |
/** | |
* Get the current webhook status from the Telegram API. | |
* @return array Returns an array of Telegram's response message. | |
*/ | |
function getWebhookInfo() { | |
return json_decode($this->sendGET("getWebhookInfo"), true); | |
} | |
/** | |
* Update Telegram with a new webhook location. Webhooks are used so Telegram can directly send new updates to the bot. | |
* @param int $max_connections Maximum connections Telegram can make to the bot (optional, default is 2). | |
* @return mixed Returns an array of Telegram's response message. | |
*/ | |
function updateWebHook($max_connections = 2) { | |
return json_decode($this->sendPOST("setWebhook", array( | |
"max_connections" => "$max_connections", | |
"url" => $this->getHookURL() . "?telegramUpdate=" . $this->getHookKey() | |
)), true); | |
} | |
/** | |
* Automatically update Telegram with the correct webhook URL, if it doesn't match the one defined in the construct. | |
* @param int $max_connections Maximum connections Telegram can make to the bot (optional, default is 2). | |
* @return array|null Returns an array of Telegram's response message, if the hook was updated. | |
*/ | |
function updateWebHookAuto($max_connections = 2) { | |
if ($this->getHookURL() . "?telegramUpdate=" . $this->getHookKey() != $this->getWebhookInfo()['result']['url']) { | |
return $this->updateWebHook($max_connections); | |
} | |
return null; | |
} | |
/** | |
* Decodes Telegram's message and stores it in $telegramUpdate. | |
*/ | |
function parseTelegramUpdate() { | |
$this->telegramUpdate = json_decode(file_get_contents("php://input"), true); | |
if ($this->isMessageEdited()) { | |
$this->rootKey = 'edited_message'; | |
} | |
} | |
/** | |
* @return mixed Returns the contents of the $telegramUpdate array. | |
*/ | |
function getTelegramUpdate() { | |
return $this->telegramUpdate; | |
} | |
/** | |
* @return mixed|null Returns the unique identifier of the account that is communicating with the bot. | |
*/ | |
function getUserID() { | |
if (isset($this->telegramUpdate[$this->rootKey]['from']['id'])) { | |
return $this->telegramUpdate[$this->rootKey]['from']['id']; | |
} | |
return null; | |
} | |
/** | |
* @return mixed|null Returns the locale of the account that is communicating with the bot. | |
*/ | |
function getUserLang() { | |
if (isset($this->telegramUpdate[$this->rootKey]['from']['language_code'])) { | |
return $this->telegramUpdate[$this->rootKey]['from']['language_code']; | |
} | |
return null; | |
} | |
/** | |
* @return mixed|null Returns the username of the account that is communicating with the bot. | |
*/ | |
function getUsername() { | |
if (isset($this->telegramUpdate[$this->rootKey]['from']['username'])) { | |
return $this->telegramUpdate[$this->rootKey]['from']['username']; | |
} | |
return null; | |
} | |
/** | |
* @return mixed|null Returns if it is a private or group chat. | |
*/ | |
function getChatType() { | |
if (isset($this->telegramUpdate[$this->rootKey]['from']['type'])) { | |
return $this->telegramUpdate[$this->rootKey]['from']['type']; | |
} | |
return null; | |
} | |
/** | |
* @return mixed|null Returns the chat unique identifier. Used to replying. | |
*/ | |
function getChatID() { | |
if (isset($this->telegramUpdate[$this->rootKey]['chat']['id'])) { | |
return $this->telegramUpdate[$this->rootKey]['chat']['id']; | |
} | |
return null; | |
} | |
/** | |
* Get the ID of the received message. Used for quoting messages. | |
* @return string|null Returns the ID of the message. | |
*/ | |
function getMessageID() { | |
if (isset($this->telegramUpdate[$this->rootKey]['message_id'])) { | |
return $this->telegramUpdate[$this->rootKey]['message_id']; | |
} | |
return null; | |
} | |
/** | |
* Checks if a message has been edited. | |
* @return bool|null true if the message has been edited, otherwise return null. | |
*/ | |
function isMessageEdited() { | |
if (isset($this->telegramUpdate['edited_message'])) { | |
return true; | |
} | |
return null; | |
} | |
/** | |
* Get the date of which the message was sent. | |
* @return mixed|null Returns the date that the message was received. | |
*/ | |
function getDate() { | |
if (isset($this->telegramUpdate[$this->rootKey]['date'])) { | |
return $this->telegramUpdate[$this->rootKey]['date']; | |
} | |
return null; | |
} | |
/** | |
* Check if the received message contains a picture. | |
* @return bool|null true if the message contains a picture. | |
*/ | |
function isPicture() { | |
if (isset($this->telegramUpdate[$this->rootKey]['photo'])) { | |
return true; | |
} | |
if (isset($this->telegramUpdate[$this->rootKey]['document']['mime_type'])) { | |
if (strpos($this->telegramUpdate[$this->rootKey]['document']['mime_type'], "image") !== false) { | |
return true; | |
} | |
} | |
return null; | |
} | |
/** | |
* Downloads a picture from Telegram. | |
* @return string|null Returns the file path if successful. | |
*/ | |
function downloadPicture() { | |
if ($this->isPicture()) { | |
if (isset($this->telegramUpdate[$this->rootKey]['photo'])) { | |
$photo_count = count($this->telegramUpdate[$this->rootKey]['photo']) - 1; | |
$file_id = $this->telegramUpdate[$this->rootKey]['photo'][$photo_count]['file_id']; | |
$file_info = json_decode($this->sendGET("getFile", array("file_id" => $file_id)), true); | |
$file_path = $file_info['result']['file_path']; | |
$file_ext = "jpg"; | |
} | |
if (isset($this->telegramUpdate[$this->rootKey]['document'])) { | |
$file_id = $this->telegramUpdate[$this->rootKey]['document']['file_id']; | |
$file_info = json_decode($this->sendGET("getFile", array("file_id" => $file_id)), true); | |
$file_path = $file_info['result']['file_path']; | |
$file_ext = pathinfo($this->telegramUpdate[$this->rootKey]['document']['file_name'])['extension']; | |
} | |
if (!file_exists(".tmp/")) { | |
if (!mkdir(".tmp", 0777, true)) { | |
error_log("Failed to create directory '.tmp'!", 0); | |
return null; | |
} | |
} | |
if (!isset($file_id) || !isset($file_ext) || !isset($file_path)) { | |
return null; | |
} | |
file_put_contents(".tmp/$file_id.$file_ext", $this->getFile("$file_path")); | |
if (file_exists(".tmp/$file_id.$file_ext")) { | |
return ".tmp/$file_id.$file_ext"; | |
} else { | |
error_log("Failed to write \".tmp/$file_id.$file_ext\"!"); | |
} | |
} | |
return null; | |
} | |
/** | |
* Get the text contents of the received message. | |
* @return string|null Returns message text. | |
*/ | |
function getText() { | |
if (isset($this->telegramUpdate[$this->rootKey]['text'])) { | |
return $this->telegramUpdate[$this->rootKey]['text']; | |
} | |
if (isset($this->telegramUpdate[$this->rootKey]['caption'])) { | |
return $this->telegramUpdate[$this->rootKey]['caption']; | |
} | |
return null; | |
} | |
/** | |
* Search the message from the user for specific key words. | |
* @param string|array $string The word or word(s) to search for in the received message. String or array can be given. | |
* @return array|null Returns an array of words found in the users message. | |
*/ | |
function textContains($string) { | |
$return = array(); | |
$toSearch = strtolower($this->getText()); | |
/** | |
* The given parameter is an array rather than a single search query/string | |
*/ | |
if (is_array($string)) { | |
error_log("Array search query given.", 0); | |
foreach($string as $searchKey) { | |
$searchKey = strtolower($searchKey); | |
if (preg_match('/(?<=[\s,.:;"\']|^)' . $searchKey . '(?=[\s,.:;"\']|$)/', $toSearch)) { | |
array_push($return, $searchKey); | |
} | |
} | |
return $return; | |
} | |
$string = strtolower($string); | |
if (strpos($toSearch, $string)) { | |
array_push($return, $string); | |
return $return; | |
} | |
return null; | |
} | |
/** | |
* Were we sent a bot command? | |
* @return bool|null true if a command was issued. | |
*/ | |
function isCommand() { | |
if (isset($this->telegramUpdate[$this->rootKey]['entities'][0]['type'])) { | |
if ($this->telegramUpdate[$this->rootKey]['entities'][0]['type'] == "bot_command") { | |
return true; | |
} | |
} | |
if (isset($this->telegramUpdate[$this->rootKey]['caption_entities'][0]['type'])) { | |
if ($this->telegramUpdate[$this->rootKey]['caption_entities'][0]['type'] == "bot_command") { | |
return true; | |
} | |
} | |
return null; | |
} | |
/** | |
* Parses the user's message and returns the requested command. | |
* @return false|string|null | |
*/ | |
function getCommand() { | |
if ($this->isCommand()) { | |
return trim(explode("@", substr($this->getText(), $this->getCommandOffset()['offset'], $this->getCommandOffset()['length']))[0]); | |
} | |
return null; | |
} | |
/** | |
* Called by getCommand() to get the offsets of the /command parameter. | |
* @return array Returns an array of the offsets: { "offset" => int, "length" => int } | |
*/ | |
function getCommandOffset() { | |
$offsetArray = array(); | |
if (isset($this->telegramUpdate[$this->rootKey]['entities'])) { | |
$offsetArray['offset'] = $this->telegramUpdate[$this->rootKey]['entities'][0]['offset'] + 1; | |
$offsetArray['length'] = $this->telegramUpdate[$this->rootKey]['entities'][0]['length']; | |
} else { | |
$offsetArray['offset'] = $this->telegramUpdate[$this->rootKey]['caption_entities'][0]['offset'] + 1; | |
$offsetArray['length'] = $this->telegramUpdate[$this->rootKey]['caption_entities'][0]['length']; | |
} | |
return $offsetArray; | |
} | |
/** | |
* Returns the arguments passed when calling a command. | |
* @return array|null An array of all command arguments. Null if no command was called. | |
*/ | |
function getCommandArgs() { | |
if ($this->isCommand()) { | |
return explode(" ", trim(substr_replace($this->getText(), '', | |
$this->getCommandOffset()['offset'] - 1, | |
$this->getCommandOffset()['offset'] + $this->getCommandOffset()['length'] - 1))); | |
} | |
return null; | |
} | |
/** | |
* Are we talking to another bot? | |
* @return mixed|null | |
*/ | |
function isBot() { | |
if (isset($this->telegramUpdate[$this->rootKey]['from']['is_bot'])) { | |
return $this->telegramUpdate[$this->rootKey]['from']['is_bot']; | |
} | |
return null; | |
} | |
/** | |
* Allows for sending a message directly to a specific chat that isn't the same as the one that called the bot. | |
* @param string $string The message to send. | |
* @param string $chatID The ID of the chat to send the message to. | |
* @param string $file Path to the file we wish to send. (optional) | |
* @param string $fileSendAs Send the file as a photo, video, document, audio, voice? (optional) | |
* @return array|null On success, an array is returned, containing Telegram's response. | |
*/ | |
function sendMessage($string, $chatID, $file = "", $fileSendAs = "") { | |
$messageContents = array( | |
'chat_id' => $chatID, | |
'text' => $string | |
); | |
if ($file != "") { | |
$fileAttach = $this->attachFile($file, $string, $fileSendAs); | |
$messageType = $fileAttach['messageType']; | |
$messageContents = array_merge($messageContents, $fileAttach['messageContents']); | |
} else { | |
$messageType = "sendMessage"; | |
} | |
return $this->sendPOST($messageType, $messageContents); | |
} | |
/** | |
* Make the bot leave the chat (groups only) | |
* @param string $chatID The ID of the chat we wish to leave. | |
* @return array|string|null Returns the Telegram API response. | |
*/ | |
function leaveChat($chatID) { | |
if ($chatID != "") { | |
$messageContents['chat_id'] = $chatID; | |
return $this->sendPOST("leaveChat", $messageContents); | |
} | |
return null; | |
} | |
/** | |
* Get some info about the chat we are in. | |
* @param string $chatID The ID of the chat we wish to get some info about. | |
* @return array|string|null Returns the Telegram API response. | |
*/ | |
function getChat($chatID) { | |
if ($chatID != "") { | |
$messageContents['chat_id'] = $chatID; | |
return $this->sendPOST("getChat", $messageContents); | |
} | |
return null; | |
} | |
/** | |
* Get who is an administrator in this group/chat. | |
* @param string $chatID The ID of the chat we wish to get a list of admins from. | |
* @return array|string|null Returns the Telegram API response. | |
*/ | |
function getChatAdmin($chatID) { | |
if ($chatID != "") { | |
$messageContents['chat_id'] = $chatID; | |
return $this->sendPOST("getChatAdministrators", $messageContents); | |
} | |
return null; | |
} | |
/** | |
* Generate an invite link for a group chat. Bot requires admin privileges. | |
* @param $chatID The ID of the chat we wish to have an invite for. | |
* @return array|string|null Returns the Telegram API response. | |
*/ | |
function getChatInviteLink($chatID) { | |
if ($chatID != "") { | |
$messageContents['chat_id'] = $chatID; | |
return $this->sendPOST("exportChatInviteLink", $messageContents); | |
} | |
return null; | |
} | |
/** | |
* Used to attach a file to a prepared message. | |
* @param string $file The path to the file we wish to send. | |
* @param string $caption The caption of the file (optional). | |
* @param string $fileSendAs Send the file as a photo, video, document, audio, voice? (optional) | |
* @return array Returns a multidimensional array: { "messageContents" => array(), "messageType" => "document, audio, etc" } | |
*/ | |
function attachFile($file, $caption = "", $fileSendAs = "") { | |
$fileExt = pathinfo($file, PATHINFO_EXTENSION); | |
$messageContents = array(); | |
if ($fileSendAs != "") { | |
switch($fileSendAs){ | |
case "photo": | |
$fileExt = "jpg"; // "Spoof" file extension to force sending as a photo. | |
break; | |
case "video": | |
$fileExt = "mp4"; | |
break; | |
case "audio": | |
$fileExt = "mp3"; | |
break; | |
case "voice": | |
$fileExt = "wav"; | |
break; | |
case "document": | |
$fileExt = "document"; | |
break; | |
} | |
} | |
switch($fileExt) { | |
case "jpg": | |
case "png": | |
case "bmp": | |
case "webp": | |
$messageContents['photo'] = $file; | |
$messageContents["caption"] = $caption; | |
$messageType = "sendPhoto"; | |
$this->sendChatAction("upload_photo"); | |
break; | |
case "mp4": | |
case "gif": | |
case "mkv": | |
case "webm": | |
case "ogv": | |
case "wmv": | |
$messageContents['video'] = $file; | |
$messageContents["caption"] = $caption; | |
$messageType = "sendVideo"; | |
$this->sendChatAction("upload_video"); | |
break; | |
case "mp3": | |
case "mp2": | |
case "ogg": | |
case "opus": | |
case "m4a": | |
case "ape": | |
case "wma": | |
case "flac": | |
$messageContents['audio'] = $file; | |
$messageContents["caption"] = $caption; | |
$messageType = "sendAudio"; | |
$this->sendChatAction("upload_document"); | |
break; | |
case "wav": | |
$messageContents['voice'] = $file; | |
$messageContents["caption"] = $caption; | |
$messageType = "sendVoice"; | |
$this->sendChatAction("upload_voice"); | |
break; | |
default: | |
$messageContents['document'] = $file; | |
$messageContents["caption"] = $caption; | |
$messageType = "sendDocument"; | |
$this->sendChatAction("upload_document"); | |
} | |
return array( | |
"messageContents" => $messageContents, | |
"messageType" => "$messageType" | |
); | |
} | |
/** | |
* A method used to easily respond to messages. | |
* @param string $string The message to send. | |
* @param bool $quote Quote the message we're replying to. (optional) | |
* @param string $file Path to the file we wish to send. (optional) | |
* @param string $fileSendAs Send the file as a photo, video, document, audio, voice? (optional) | |
* @return array On success, an array is returned, containing Telegram's response. | |
*/ | |
function sendReply($string, $quote = true, $file = "", $fileSendAs = "") { | |
$messageContents = array(); | |
$messageContents['chat_id'] = $this->getChatID(); | |
if ($quote == true) { | |
$messageContents['reply_to_message_id'] = $this->getMessageID(); | |
} | |
if ($file != "") { | |
$fileAttach = $this->attachFile($file, $string, $fileSendAs); | |
$messageType = $fileAttach['messageType']; | |
$messageContents = array_merge($messageContents, $fileAttach['messageContents']); | |
} else { | |
$messageType = "sendMessage"; | |
} | |
$messageContents["text"] = $string; | |
return $this->sendPOST($messageType, $messageContents); | |
} | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment