diff --git a/bootstrap/bootstrap.php b/bootstrap/bootstrap.php index a8194ad..3e481c6 100644 --- a/bootstrap/bootstrap.php +++ b/bootstrap/bootstrap.php @@ -3,6 +3,7 @@ #[\AllowDynamicProperties] class erLhcoreClassExtensionLhctelegram { + private $lastTelegramSendData = null; public function __construct() { @@ -408,6 +409,152 @@ private function appendTelegramMessageFile(& $files, & $seen, $id, $hash) ); } + /** + * Return the raw Telegram message payload on old and new telegram-core releases. + * telegram-core 79e5e3a keeps unknown fields (including Message.quote) in raw_data + * and exposes them through Entity::__call(), but does not define a Quote entity. + */ + public static function getTelegramRawMessageData($message) + { + if (is_array($message)) { + return $message; + } + + if (!is_object($message)) { + return array(); + } + + if (isset($message->raw_data) && is_array($message->raw_data)) { + return $message->raw_data; + } + + if (method_exists($message, 'getRawData')) { + try { + $raw = $message->getRawData(); + return is_array($raw) ? $raw : array(); + } catch (\Throwable $e) { + return array(); + } + } + + return array(); + } + + private static function getTelegramEntityProperty($entity, $property) + { + if (!is_object($entity)) { + return null; + } + + if (method_exists($entity, 'getProperty')) { + try { + return $entity->getProperty($property); + } catch (\Throwable $e) { + // Fall through to the dynamic getter below. + } + } + + try { + $getter = 'get' . str_replace(' ', '', ucwords(str_replace('_', ' ', $property))); + return $entity->$getter(); + } catch (\Throwable $e) { + return null; + } + } + + private static function getTelegramQuoteText($quote) + { + if (is_array($quote)) { + return trim((string)($quote['text'] ?? '')); + } + + if (is_object($quote)) { + $text = self::getTelegramEntityProperty($quote, 'text'); + if ($text !== null) { + return trim((string)$text); + } + + if (isset($quote->raw_data) && is_array($quote->raw_data)) { + return trim((string)($quote->raw_data['text'] ?? '')); + } + } + + return trim((string)$quote); + } + + /** + * Normalize reply/quote information without relying on Quote or ReplyParameters + * classes that are absent in the installed telegram-core 79e5e3a. + * + * @return array{message_id:int,thread_id:int,reply_message_id:int,is_explicit_reply:bool,quote_text:string} + */ + public static function extractTelegramReplyData($message) + { + $raw = self::getTelegramRawMessageData($message); + $replyRaw = isset($raw['reply_to_message']) && is_array($raw['reply_to_message']) ? $raw['reply_to_message'] : array(); + + $messageId = (int)($raw['message_id'] ?? self::getTelegramEntityProperty($message, 'message_id')); + $threadId = (int)($raw['message_thread_id'] ?? self::getTelegramEntityProperty($message, 'message_thread_id')); + $replyMessageId = (int)($replyRaw['message_id'] ?? 0); + + $replyObject = self::getTelegramEntityProperty($message, 'reply_to_message'); + if ($replyMessageId <= 0 && is_object($replyObject)) { + $replyMessageId = (int)self::getTelegramEntityProperty($replyObject, 'message_id'); + } + + $quote = $raw['quote'] ?? null; + if ($quote === null && isset($replyRaw['quote'])) { + $quote = $replyRaw['quote']; + } + if ($quote === null && is_object($replyObject)) { + $quote = self::getTelegramEntityProperty($replyObject, 'quote'); + } elseif ($quote === null && is_array($replyObject) && isset($replyObject['quote'])) { + $quote = $replyObject['quote']; + } + + $quoteObject = self::getTelegramEntityProperty($message, 'quote'); + $quoteText = self::getTelegramQuoteText($quoteObject); + if ($quoteText === '') { + $quoteText = self::getTelegramQuoteText($quote); + } + + $forumTopicCreated = isset($replyRaw['forum_topic_created']); + if (!$forumTopicCreated && is_object($replyObject)) { + $forumTopicCreated = (bool)self::getTelegramEntityProperty($replyObject, 'forum_topic_created'); + } + + return array( + 'message_id' => $messageId, + 'thread_id' => $threadId, + 'reply_message_id' => $replyMessageId, + 'is_explicit_reply' => $replyMessageId > 0 && $replyMessageId !== $threadId && !$forumTopicCreated, + 'quote_text' => $quoteText + ); + } + + /** + * Return the text/caption that was sent for a stored Telegram message. + * This is used when Telegram omitted Message.quote (the normal case on core 79e5e3a). + */ + public static function getStoredTelegramMessageText($msg, $topicMsgId = null) + { + if (!is_object($msg)) { + return ''; + } + + $meta = is_array($msg->meta_msg_array) ? $msg->meta_msg_array : array(); + $key = $topicMsgId !== null ? (string)(int)$topicMsgId : ''; + if ($key !== '' && isset($meta['tg_topic_msg_map'][$key]) && is_array($meta['tg_topic_msg_map'][$key])) { + $entry = $meta['tg_topic_msg_map'][$key]; + $mappedText = trim((string)($entry['caption'] ?? ($entry['text'] ?? ''))); + if ($mappedText !== '') { + return $mappedText; + } + } + + return trim(preg_replace('/\[file=\d+_[a-f0-9]{32}\]/i', '', (string)$msg->msg)); + } + private function getTelegramFileCaption($msg, $chat, $file, $messageText = null) { $sender = $msg->name_support != '' ? '🤖 [' . $msg->name_support . ']' : '👤 [' . $chat->nick . ']'; @@ -441,8 +588,304 @@ private function isMeaningfulTelegramUploadName($file) return true; } - private function sendTelegramChatFile($tchat, $fileData, $caption, $disableNotification = false) + public function saveTopicMsgId($msg, $topicMsgId, $messageData = array()) + { + if (!($msg instanceof erLhcoreClassModelmsg) || !(int)$topicMsgId || $msg->id <= 0) { + return; + } + + $db = ezcDbInstance::get(); + $startedTransaction = method_exists($db, 'inTransaction') && !$db->inTransaction(); + if ($startedTransaction) { + $db->beginTransaction(); + } + + try { + // Lock while merging to preserve IDs written by concurrent workers. + $select = $db->prepare('SELECT meta_msg FROM lh_msg WHERE id = :id FOR UPDATE'); + $select->bindValue(':id', (int)$msg->id, PDO::PARAM_INT); + $select->execute(); + $row = $select->fetch(PDO::FETCH_ASSOC); + + $meta = array(); + if (is_array($row) && isset($row['meta_msg']) && $row['meta_msg'] !== '') { + $decoded = json_decode($row['meta_msg'], true); + if (is_array($decoded)) { + $meta = $decoded; + } + } + if (empty($meta) && is_array($msg->meta_msg_array)) { + $meta = $msg->meta_msg_array; + } + + $topicMsgIds = isset($meta['tg_topic_msg_ids']) && is_array($meta['tg_topic_msg_ids']) ? array_map('intval', $meta['tg_topic_msg_ids']) : array(); + $topicMsgIds[] = (int)$topicMsgId; + $topicMsgIds = array_values(array_unique(array_filter($topicMsgIds, function ($id) { return (int)$id > 0; }))); + $meta['tg_topic_msg_ids'] = $topicMsgIds; + $meta['tg_topic_msg_id'] = (int)$topicMsgId; + + $topicMap = isset($meta['tg_topic_msg_map']) && is_array($meta['tg_topic_msg_map']) ? $meta['tg_topic_msg_map'] : array(); + $entry = array(); + foreach (array('text', 'caption', 'embed', 'kind') as $key) { + if (isset($messageData[$key]) && is_scalar($messageData[$key])) { + $entry[$key] = (string)$messageData[$key]; + } + } + if (isset($messageData['file_id']) && (int)$messageData['file_id'] > 0) { + $entry['file_id'] = (int)$messageData['file_id']; + } + if (isset($messageData['security_hash']) && is_scalar($messageData['security_hash'])) { + $entry['security_hash'] = (string)$messageData['security_hash']; + } + $mapKey = (string)(int)$topicMsgId; + if (!isset($topicMap[$mapKey]) || !is_array($topicMap[$mapKey])) { + $topicMap[$mapKey] = array(); + } + if (!empty($entry)) { + $topicMap[$mapKey] = array_merge($topicMap[$mapKey], $entry); + } + $meta['tg_topic_msg_map'] = $topicMap; + + $msg->meta_msg_array = $meta; + $msg->meta_msg = json_encode($meta, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_SUBSTITUTE); + + $stmt = $db->prepare('UPDATE lh_msg SET meta_msg = :meta_msg WHERE id = :id'); + $stmt->bindValue(':meta_msg', $msg->meta_msg); + $stmt->bindValue(':id', (int)$msg->id, PDO::PARAM_INT); + $stmt->execute(); + + if ($startedTransaction) { + $db->commit(); + } + } catch (\Throwable $e) { + if ($startedTransaction && $db->inTransaction()) { + $db->rollBack(); + } + throw $e; + } + } + + private function saveTelegramFileTopicMsgId($msg, $topicMsgId, $telegramFile, $caption = '') { + if (!is_array($telegramFile) || !isset($telegramFile['file']) || !is_object($telegramFile['file'])) { + $this->saveTopicMsgId($msg, $topicMsgId); + return; + } + + $file = $telegramFile['file']; + $this->saveTopicMsgId($msg, $topicMsgId, array( + 'file_id' => (int)$file->id, + 'security_hash' => (string)$file->security_hash, + 'embed' => (string)($telegramFile['embed'] ?? ''), + 'caption' => (string)$caption, + 'text' => (string)$caption, + 'kind' => (string)$file->type + )); + } + + private function getStoredTopicMessageId($msg, $preferredId = null) + { + if (!($msg instanceof erLhcoreClassModelmsg)) { + return null; + } + + $meta = is_array($msg->meta_msg_array) ? $msg->meta_msg_array : array(); + $knownIds = array(); + if (isset($meta['tg_topic_msg_ids']) && is_array($meta['tg_topic_msg_ids'])) { + foreach ($meta['tg_topic_msg_ids'] as $id) { + if ((int)$id > 0) { + $knownIds[(int)$id] = true; + } + } + } + if (isset($meta['tg_topic_msg_map']) && is_array($meta['tg_topic_msg_map'])) { + foreach (array_keys($meta['tg_topic_msg_map']) as $id) { + if ((int)$id > 0) { + $knownIds[(int)$id] = true; + } + } + } + if (isset($meta['tg_topic_msg_id']) && (int)$meta['tg_topic_msg_id'] > 0) { + $knownIds[(int)$meta['tg_topic_msg_id']] = true; + } + + if ($preferredId !== null && isset($knownIds[(int)$preferredId])) { + return (int)$preferredId; + } + if (isset($meta['tg_topic_msg_id']) && (int)$meta['tg_topic_msg_id'] > 0) { + return (int)$meta['tg_topic_msg_id']; + } + if (!empty($knownIds)) { + return (int)array_key_last($knownIds); + } + + return null; + } + + public function getTopicReplyId($msg, $chatId) + { + if (!($msg instanceof erLhcoreClassModelmsg)) { + return null; + } + + $meta = is_array($msg->meta_msg_array) ? $msg->meta_msg_array : array(); + + if (isset($meta['content']['reply_to']['db_msg_id']) && (int)$meta['content']['reply_to']['db_msg_id'] > 0) { + $targetMsg = erLhcoreClassModelmsg::fetch((int)$meta['content']['reply_to']['db_msg_id']); + if ($targetMsg instanceof erLhcoreClassModelmsg && (int)$targetMsg->chat_id === (int)$chatId) { + $preferredId = $meta['content']['reply_to']['telegram_message_id'] ?? ($meta['content']['reply_to']['tg_topic_msg_id'] ?? null); + $resolvedId = $this->getStoredTopicMessageId($targetMsg, $preferredId); + if ($resolvedId !== null) { + return $resolvedId; + } + } + } + + if (isset($meta['content']['reply_to']['iwh_msg_id']) && $meta['content']['reply_to']['iwh_msg_id'] != '') { + $iwhId = (string)$meta['content']['reply_to']['iwh_msg_id']; + $targetMsg = erLhcoreClassModelmsg::findOne([ + 'filter' => ['chat_id' => $chatId], + 'customfilter' => ["`meta_msg` != '' AND JSON_VALID(`meta_msg`) AND (JSON_UNQUOTE(JSON_EXTRACT(meta_msg,'$.iwh_msg_id')) = " . ezcDbInstance::get()->quote($iwhId) . " OR JSON_EXTRACT(meta_msg,'$.iwh_msg_id') = " . (is_numeric($iwhId) ? (int)$iwhId : ezcDbInstance::get()->quote($iwhId)) . ")"] + ]); + if ($targetMsg instanceof erLhcoreClassModelmsg && (int)$targetMsg->chat_id === (int)$chatId) { + $resolvedId = $this->getStoredTopicMessageId($targetMsg); + if ($resolvedId !== null) { + return $resolvedId; + } + } + } + + if (isset($meta['content']['quote']['id']) && (int)$meta['content']['quote']['id'] > 0) { + $targetMsg = erLhcoreClassModelmsg::fetch((int)$meta['content']['quote']['id']); + if ($targetMsg instanceof erLhcoreClassModelmsg && (int)$targetMsg->chat_id === (int)$chatId) { + $resolvedId = $this->getStoredTopicMessageId($targetMsg); + if ($resolvedId !== null) { + return $resolvedId; + } + } + } + + if (preg_match('#\[quote="?([0-9]+)"?\]#is', (string)$msg->msg, $m)) { + $targetMsg = erLhcoreClassModelmsg::fetch((int)$m[1]); + if ($targetMsg instanceof erLhcoreClassModelmsg && (int)$targetMsg->chat_id === (int)$chatId) { + $resolvedId = $this->getStoredTopicMessageId($targetMsg); + if ($resolvedId !== null) { + return $resolvedId; + } + } + } + + return null; + } + + public function getTopicMessageId($msg, $chatId) + { + if (!($msg instanceof erLhcoreClassModelmsg) || (int)$msg->chat_id !== (int)$chatId) { + return null; + } + + $meta = is_array($msg->meta_msg_array) ? $msg->meta_msg_array : array(); + if (isset($meta['tg_topic_msg_id']) && (int)$meta['tg_topic_msg_id'] > 0) { + return (int)$meta['tg_topic_msg_id']; + } + + return $this->getStoredTopicMessageId($msg); + } + + private function shouldRetryTelegramWithoutReply($sendData) + { + if (!is_object($sendData) || $sendData->isOk() || (int)$sendData->getErrorCode() !== 400) { + return false; + } + + $description = strtolower((string)$sendData->getDescription()); + foreach (array('message to be replied not found', 'reply message not found', 'message_id_invalid', "message can't be replied", 'message cannot be replied') as $needle) { + if (strpos($description, $needle) !== false) { + return true; + } + } + + return false; + } + + private function isTelegramTopicUnavailable($sendData) + { + if (!is_object($sendData) || $sendData->isOk() || (int)$sendData->getErrorCode() !== 400) { + return false; + } + + $description = strtolower((string)$sendData->getDescription()); + return strpos($description, 'message thread not found') !== false + || strpos($description, 'topic_deleted') !== false + || strpos($description, 'thread not found') !== false; + } + + private function rewindTelegramResources(array &$data) + { + foreach ($data as &$value) { + if (is_resource($value)) { + @rewind($value); + } + } + unset($value); + } + + private function closeTelegramResources(array &$data) + { + foreach ($data as &$value) { + if (is_resource($value)) { + @fclose($value); + } + } + unset($value); + } + + /** + * Send once, then retry without a stale reply target for known 400 errors. + * + * Guzzle closes the raw resource returned by Request::encodeFile() after + * consuming a multipart request. Keep the source path/field as private + * retry context so a file upload can be reopened for the retry. + */ + private function sendTelegramRequest($method, array $data, $multipartFilePath = '', $multipartFileField = '') + { + $multipartFilePath = (string)$multipartFilePath; + $multipartFileField = (string)$multipartFileField; + + try { + $this->rewindTelegramResources($data); + $sendData = Longman\TelegramBot\Request::send($method, $data); + } catch (\Throwable $e) { + $this->closeTelegramResources($data); + erLhcoreClassLog::write('Telegram request exception ' . $e->getMessage(), ezcLog::SUCCESS_AUDIT, array('source' => 'lhc', 'category' => 'telegram_exception', 'line' => __LINE__, 'file' => __FILE__)); + return new Longman\TelegramBot\Entities\ServerResponse(array('ok' => false, 'error_code' => 500, 'description' => 'Telegram request failed')); + } + + if ($this->shouldRetryTelegramWithoutReply($sendData) && isset($data['reply_to_message_id'])) { + unset($data['reply_to_message_id']); + try { + if ($multipartFilePath !== '' && $multipartFileField !== '') { + if (isset($data[$multipartFileField]) && is_resource($data[$multipartFileField])) { + @fclose($data[$multipartFileField]); + } + $data[$multipartFileField] = Longman\TelegramBot\Request::encodeFile($multipartFilePath); + } else { + $this->rewindTelegramResources($data); + } + $sendData = Longman\TelegramBot\Request::send($method, $data); + } catch (\Throwable $e) { + $this->closeTelegramResources($data); + erLhcoreClassLog::write('Telegram reply fallback exception ' . $e->getMessage(), ezcLog::SUCCESS_AUDIT, array('source' => 'lhc', 'category' => 'telegram_exception', 'line' => __LINE__, 'file' => __FILE__)); + return new Longman\TelegramBot\Entities\ServerResponse(array('ok' => false, 'error_code' => 500, 'description' => 'Telegram reply fallback failed')); + } + } + + return $sendData; + } + + private function sendTelegramChatFile($tchat, $fileData, $caption, $disableNotification = false, $params = array()) + { + $this->lastTelegramSendData = null; $file = $fileData['file']; if (!file_exists($file->file_path_server) || !is_readable($file->file_path_server)) { @@ -468,12 +911,21 @@ private function sendTelegramChatFile($tchat, $fileData, $caption, $disableNotif $field = 'video'; } - $data = array( - 'chat_id' => $tchat->bot->group_chat_id, - 'message_thread_id' => $tchat->tchat_id, - 'parse_mode' => 'HTML', - $field => $this->getTelegramChatFileUrl($file) - ); + try { + $data = array( + 'chat_id' => $tchat->bot->group_chat_id, + 'message_thread_id' => $tchat->tchat_id, + 'parse_mode' => 'HTML', + $field => Longman\TelegramBot\Request::encodeFile($file->file_path_server) + ); + } catch (\Throwable $e) { + erLhcoreClassLog::write('SendFile encode exception ' . $e->getMessage(), ezcLog::SUCCESS_AUDIT, array('source' => 'lhc', 'category' => 'telegram_exception', 'line' => __LINE__, 'file' => __FILE__, 'object_id' => $file->chat_id)); + return false; + } + + if (isset($params['reply_to_message_id']) && $params['reply_to_message_id'] > 0) { + $data['reply_to_message_id'] = $params['reply_to_message_id']; + } if ($caption !== '') { $data['caption'] = $caption; @@ -483,20 +935,9 @@ private function sendTelegramChatFile($tchat, $fileData, $caption, $disableNotif $data['disable_notification'] = true; } - try { - $sendData = Longman\TelegramBot\Request::send($method, $data); - } catch (Exception $e) { - erLhcoreClassLog::write('SendFile exception '.$e->getMessage(), - ezcLog::SUCCESS_AUDIT, - array( - 'source' => 'lhc', - 'category' => 'telegram_exception', - 'line' => __LINE__, - 'file' => __FILE__, - 'object_id' => $file->chat_id - ) - ); - + $sendData = $this->sendTelegramRequest($method, $data, $file->file_path_server, $field); + $this->lastTelegramSendData = $sendData; + if ($sendData === null) { return false; } @@ -515,7 +956,7 @@ private function sendTelegramChatFile($tchat, $fileData, $caption, $disableNotif return false; } - return true; + return $sendData->getResult()->getMessageId(); } private function getTelegramChatFileUrl($file) @@ -580,9 +1021,18 @@ public function messageAdded($params) $data['disable_notification'] = true; } - $sendData = Longman\TelegramBot\Request::sendMessage($data); + $replyTopicMsgId = $this->getTopicReplyId($params['msg'], $chat->id); + if ($replyTopicMsgId > 0) { + $data['reply_to_message_id'] = $replyTopicMsgId; + } + + $sendData = $this->sendTelegramRequest('sendMessage', $data); - if (!$sendData->isOk() && $sendData->getErrorCode() == 400 && str_contains( $sendData->getDescription(), 'TOPIC_DELETED') === true) { + if ($sendData->isOk()) { + $this->saveTopicMsgId($params['msg'], $sendData->getResult()->getMessageId(), array('text' => $messageText, 'kind' => 'text')); + } + + if ($this->isTelegramTopicUnavailable($sendData)) { // Reset telegram chat $tchat->tchat_id = 0; $tchat->updateThis(['update' => ['tchat_id']]); @@ -610,15 +1060,25 @@ public function messageAdded($params) $failedEmbedCodes = array(); $fileIndex = 0; + $replyTopicMsgId = $this->getTopicReplyId($params['msg'], $chat->id); foreach ($telegramFiles as $telegramFile) { - if ($this->sendTelegramChatFile($tchat, $telegramFile, $this->getTelegramFileCaption($params['msg'], $chat, $telegramFile['file'], $fileIndex === 0 ? $messageText : ''), $chat->status == erLhcoreClassModelChat::STATUS_BOT_CHAT) === false) { + $sentFileMsgId = $this->sendTelegramChatFile($tchat, $telegramFile, $this->getTelegramFileCaption($params['msg'], $chat, $telegramFile['file'], $fileIndex === 0 ? $messageText : ''), $chat->status == erLhcoreClassModelChat::STATUS_BOT_CHAT, ['reply_to_message_id' => $replyTopicMsgId]); + if ($sentFileMsgId === false) { + if ($fileIndex === 0 && $this->isTelegramTopicUnavailable($this->lastTelegramSendData)) { + $tchat->tchat_id = 0; + $tchat->updateThis(['update' => ['tchat_id']]); + $this->chatStarted(['chat' => $chat]); + return; + } $failedEmbedCodes[] = $telegramFile['embed']; + } else { + $this->saveTelegramFileTopicMsgId($params['msg'], $sentFileMsgId, $telegramFile, $this->getTelegramFileCaption($params['msg'], $chat, $telegramFile['file'], $fileIndex === 0 ? $messageText : '')); } $fileIndex++; } if (!empty($failedEmbedCodes)) { - Longman\TelegramBot\Request::sendMessage(array( + $this->sendTelegramRequest('sendMessage', array( 'chat_id' => $tchat->bot->group_chat_id, 'message_thread_id' => $tchat->tchat_id, 'parse_mode' => 'HTML', @@ -640,6 +1100,7 @@ public function messageAdded($params) // Send bot responses if any $botMessages = erLhcoreClassModelmsg::getList(array('filter' => array('user_id' => -2, 'chat_id' => $chat->id), 'filtergt' => array('id' => $params['msg']->id))); + $botReplyTopicMsgId = $this->getTopicMessageId($params['msg'], $chat->id); foreach ($botMessages as $botMessage) { @@ -669,9 +1130,14 @@ public function messageAdded($params) if ($chat->status == erLhcoreClassModelChat::STATUS_BOT_CHAT) { $data['disable_notification'] = true; } - $sendData = Longman\TelegramBot\Request::sendMessage($data); + if ($botReplyTopicMsgId > 0) { + $data['reply_to_message_id'] = $botReplyTopicMsgId; + } + $sendData = $this->sendTelegramRequest('sendMessage', $data); - if (!$sendData->isOk()) { + if ($sendData->isOk()) { + $this->saveTopicMsgId($botMessage, $sendData->getResult()->getMessageId(), array('text' => $messageText, 'kind' => 'text')); + } else { erLhcoreClassLog::write('SendMessage BOT ['.$sendData->getErrorCode().']'. $sendData->getDescription(), ezcLog::SUCCESS_AUDIT, array( @@ -690,14 +1156,17 @@ public function messageAdded($params) $fileIndex = 0; foreach ($telegramFiles as $telegramFile) { - if ($this->sendTelegramChatFile($tchat, $telegramFile, $this->getTelegramFileCaption($botMessage, $chat, $telegramFile['file'], $fileIndex === 0 ? $messageText : ''), $chat->status == erLhcoreClassModelChat::STATUS_BOT_CHAT) === false) { + $sentFileMsgId = $this->sendTelegramChatFile($tchat, $telegramFile, $this->getTelegramFileCaption($botMessage, $chat, $telegramFile['file'], $fileIndex === 0 ? $messageText : ''), $chat->status == erLhcoreClassModelChat::STATUS_BOT_CHAT, ['reply_to_message_id' => $botReplyTopicMsgId]); + if ($sentFileMsgId === false) { $failedEmbedCodes[] = $telegramFile['embed']; + } else { + $this->saveTelegramFileTopicMsgId($botMessage, $sentFileMsgId, $telegramFile, $this->getTelegramFileCaption($botMessage, $chat, $telegramFile['file'], $fileIndex === 0 ? $messageText : '')); } $fileIndex++; } if (!empty($failedEmbedCodes)) { - Longman\TelegramBot\Request::sendMessage(array( + $this->sendTelegramRequest('sendMessage', array( 'chat_id' => $tchat->bot->group_chat_id, 'message_thread_id' => $tchat->tchat_id, 'parse_mode' => 'HTML', @@ -754,6 +1223,7 @@ public function triggerClicked($params) $telegramFiles = $this->getTelegramMessageFiles($botMessage); $messageText = $this->stripTelegramFileEmbeds($botMessage->msg); + $botReplyTopicMsgId = $this->getTopicMessageId($params['msg'], $chat->id); if ($messageText !== '' && empty($telegramFiles)) { $data = [ @@ -765,9 +1235,14 @@ public function triggerClicked($params) if ($chat->status == erLhcoreClassModelChat::STATUS_BOT_CHAT) { $data['disable_notification'] = true; } - $sendData = Longman\TelegramBot\Request::sendMessage($data); + if ($botReplyTopicMsgId > 0) { + $data['reply_to_message_id'] = $botReplyTopicMsgId; + } + $sendData = $this->sendTelegramRequest('sendMessage', $data); - if (!$sendData->isOk()) { + if ($sendData->isOk()) { + $this->saveTopicMsgId($botMessage, $sendData->getResult()->getMessageId(), array('text' => $messageText, 'kind' => 'text')); + } else { erLhcoreClassLog::write('['.$sendData->getErrorCode().']'. $sendData->getDescription(), ezcLog::SUCCESS_AUDIT, array( @@ -786,14 +1261,17 @@ public function triggerClicked($params) $fileIndex = 0; foreach ($telegramFiles as $telegramFile) { - if ($this->sendTelegramChatFile($tchat, $telegramFile, $this->getTelegramFileCaption($botMessage, $chat, $telegramFile['file'], $fileIndex === 0 ? $messageText : ''), $chat->status == erLhcoreClassModelChat::STATUS_BOT_CHAT) === false) { + $sentFileMsgId = $this->sendTelegramChatFile($tchat, $telegramFile, $this->getTelegramFileCaption($botMessage, $chat, $telegramFile['file'], $fileIndex === 0 ? $messageText : ''), $chat->status == erLhcoreClassModelChat::STATUS_BOT_CHAT, ['reply_to_message_id' => $botReplyTopicMsgId]); + if ($sentFileMsgId === false) { $failedEmbedCodes[] = $telegramFile['embed']; + } else { + $this->saveTelegramFileTopicMsgId($botMessage, $sentFileMsgId, $telegramFile, $this->getTelegramFileCaption($botMessage, $chat, $telegramFile['file'], $fileIndex === 0 ? $messageText : '')); } $fileIndex++; } if (!empty($failedEmbedCodes)) { - Longman\TelegramBot\Request::sendMessage(array( + $this->sendTelegramRequest('sendMessage', array( 'chat_id' => $tchat->bot->group_chat_id, 'message_thread_id' => $tchat->tchat_id, 'parse_mode' => 'HTML', @@ -892,6 +1370,7 @@ public function chatStarted($params) // Collect all chat messages including bot $initialTelegramFiles = array(); + $initialAggregateMessages = array(); $botMessages = erLhcoreClassModelmsg::getList(array('filterin' => ['user_id' => [0, -2]], 'filter' => array('chat_id' => $params['chat']->id))); foreach ($botMessages as $botMessage) { $tChat->last_msg_id = $botMessage->id; @@ -904,6 +1383,7 @@ public function chatStarted($params) if ($messageText !== '' && empty($telegramFiles)) { $visitor[] = trim(($botMessage->name_support != '' ? '🤖 [' . $botMessage->name_support . ']: ' : '👤 ['. erLhcoreClassBBCodePlain::make_clickable($params['chat']->nick, array('sender' => 0)) . ']: ') . erLhcoreClassBBCodePlain::make_clickable($messageText, array('sender' => 0)) . ($botMessage->name_support != '' ? '' : '')); + $initialAggregateMessages[] = array('msg' => $botMessage, 'text' => $messageText); } $fileIndex = 0; @@ -924,9 +1404,20 @@ public function chatStarted($params) $data['disable_notification'] = true; } - $sendData = Longman\TelegramBot\Request::sendMessage($data); + $sendData = $this->sendTelegramRequest('sendMessage', $data); - if (!$sendData->isOk()) { + if ($sendData->isOk()) { + $aggregateMsgId = $sendData->getResult()->getMessageId(); + foreach ($initialAggregateMessages as $aggregateMessage) { + $this->saveTopicMsgId($aggregateMessage['msg'], $aggregateMsgId, array('text' => $aggregateMessage['text'], 'kind' => 'aggregate')); + } + if (empty($initialAggregateMessages)) { + $firstMsg = erLhcoreClassModelmsg::findOne(['filter' => ['chat_id' => $params['chat']->id], 'sort' => 'id ASC']); + if ($firstMsg instanceof erLhcoreClassModelmsg) { + $this->saveTopicMsgId($firstMsg, $aggregateMsgId, array('text' => $data['text'], 'kind' => 'aggregate')); + } + } + } else { // Try first time to create a topic if old one is gone if ($sendData->getErrorCode() == 400 && (str_contains($sendData->getDescription(), 'message thread not found') || str_contains($sendData->getDescription(), 'TOPIC_DELETED'))) { @@ -944,9 +1435,20 @@ public function chatStarted($params) } $data['message_thread_id'] = $tChat->tchat_id; - $sendData = Longman\TelegramBot\Request::sendMessage($data); + $sendData = $this->sendTelegramRequest('sendMessage', $data); - if (!$sendData->isOk()) { + if ($sendData->isOk()) { + $aggregateMsgId = $sendData->getResult()->getMessageId(); + foreach ($initialAggregateMessages as $aggregateMessage) { + $this->saveTopicMsgId($aggregateMessage['msg'], $aggregateMsgId, array('text' => $aggregateMessage['text'], 'kind' => 'aggregate')); + } + if (empty($initialAggregateMessages)) { + $firstMsg = erLhcoreClassModelmsg::findOne(['filter' => ['chat_id' => $params['chat']->id], 'sort' => 'id ASC']); + if ($firstMsg instanceof erLhcoreClassModelmsg) { + $this->saveTopicMsgId($firstMsg, $aggregateMsgId, array('text' => $data['text'], 'kind' => 'aggregate')); + } + } + } else { erLhcoreClassLog::write('['.$sendData->getErrorCode().']'. $sendData->getDescription(), ezcLog::SUCCESS_AUDIT, array( @@ -964,13 +1466,16 @@ public function chatStarted($params) $failedEmbedCodes = array(); foreach ($initialTelegramFiles as $initialTelegramFile) { - if ($this->sendTelegramChatFile($tChat, $initialTelegramFile['file'], $this->getTelegramFileCaption($initialTelegramFile['msg'], $params['chat'], $initialTelegramFile['file']['file'], $initialTelegramFile['text']), $params['chat']->status == erLhcoreClassModelChat::STATUS_BOT_CHAT) === false) { + $sentFileMsgId = $this->sendTelegramChatFile($tChat, $initialTelegramFile['file'], $this->getTelegramFileCaption($initialTelegramFile['msg'], $params['chat'], $initialTelegramFile['file']['file'], $initialTelegramFile['text']), $params['chat']->status == erLhcoreClassModelChat::STATUS_BOT_CHAT); + if ($sentFileMsgId === false) { $failedEmbedCodes[] = $initialTelegramFile['file']['embed']; + } else if (isset($initialTelegramFile['msg']) && $initialTelegramFile['msg'] instanceof erLhcoreClassModelmsg) { + $this->saveTelegramFileTopicMsgId($initialTelegramFile['msg'], $sentFileMsgId, $initialTelegramFile['file'], $this->getTelegramFileCaption($initialTelegramFile['msg'], $params['chat'], $initialTelegramFile['file']['file'], $initialTelegramFile['text'])); } } if (!empty($failedEmbedCodes)) { - Longman\TelegramBot\Request::sendMessage(array( + $this->sendTelegramRequest('sendMessage', array( 'chat_id' => $tChat->bot->group_chat_id, 'message_thread_id' => $tChat->tchat_id, 'parse_mode' => 'HTML', diff --git a/classes/Commands/GenericmessageCommand.php b/classes/Commands/GenericmessageCommand.php index c80c493..ef91d85 100644 --- a/classes/Commands/GenericmessageCommand.php +++ b/classes/Commands/GenericmessageCommand.php @@ -341,7 +341,64 @@ public function execute(): ServerResponse if ($ignoreMessage == false) { $msg = new \erLhcoreClassModelmsg(); - $msg->msg = $text; + $msgText = $text; + $metaMsg = []; + + $replyData = \erLhcoreClassExtensionLhctelegram::extractTelegramReplyData($message); + $isExplicitReply = !empty($replyData['is_explicit_reply']) && (int)($replyData['reply_message_id'] ?? 0) > 0; + + if ($isExplicitReply) { + $replyTopicMsgId = (int)$replyData['reply_message_id']; + $metaMsg['tg_topic_msg_id'] = (int)$replyData['message_id']; + + $replyMsg = \erLhcoreClassModelmsg::findOne([ + 'filter' => ['chat_id' => $chat->id], + 'customfilter' => ['`meta_msg` != \'\' AND JSON_VALID(`meta_msg`) AND JSON_EXTRACT(meta_msg, \'$.tg_topic_msg_id\') = ' . $replyTopicMsgId] + ]); + + if (!($replyMsg instanceof \erLhcoreClassModelmsg)) { + $replyMsg = \erLhcoreClassModelmsg::findOne([ + 'filter' => ['chat_id' => $chat->id], + 'customfilter' => ['meta_msg != \'\' AND JSON_VALID(meta_msg) AND JSON_CONTAINS(JSON_EXTRACT(meta_msg, \'$.tg_topic_msg_ids\'), \'[' . $replyTopicMsgId . ']\')'] + ]); + } + + if ($replyMsg instanceof \erLhcoreClassModelmsg) { + $quoteText = trim((string)($replyData['quote_text'] ?? '')); + if ($quoteText === '') { + $quoteText = \erLhcoreClassExtensionLhctelegram::getStoredTelegramMessageText($replyMsg, $replyTopicMsgId); + } + if ($quoteText === '') { + $quoteText = (string)$replyMsg->msg; + } + $replyNick = $replyMsg->name_support != '' ? $replyMsg->name_support : $chat->nick; + $msgText = '[quote=' . $replyMsg->id . ']' . $quoteText . '[/quote]' . $msgText; + + $metaMsg['content'] = [ + 'quote' => [ + 'id' => $replyMsg->id, + 'text' => $quoteText, + 'nick' => $replyNick + ], + 'reply_to' => [ + 'db_msg_id' => $replyMsg->id, + 'telegram_message_id' => $replyTopicMsgId + ] + ]; + + if (isset($replyMsg->meta_msg_array['iwh_msg_id']) && $replyMsg->meta_msg_array['iwh_msg_id'] != '') { + $metaMsg['content']['reply_to']['iwh_msg_id'] = $replyMsg->meta_msg_array['iwh_msg_id']; + } + } + } else { + $metaMsg['tg_topic_msg_id'] = (int)$replyData['message_id']; + } + + $msg->msg = $msgText; + if (!empty($metaMsg)) { + $msg->meta_msg = json_encode($metaMsg); + $msg->meta_msg_array = $metaMsg; + } $msg->chat_id = $chat->id; $msg->user_id = $messageUserId; $msg->time = time(); diff --git a/doc/telegram/incoming-webhook.json b/doc/telegram/incoming-webhook.json index 9399c29..91df02f 100644 --- a/doc/telegram/incoming-webhook.json +++ b/doc/telegram/incoming-webhook.json @@ -1 +1 @@ -{"name":"TelegramIntegration","dep_id":1,"disabled":0,"identifier":"","scope":"telegram","configuration":"{\"attr\":[{\"key\":\"access_token\",\"value\":\"___replace_me___\",\"id\":\"temp1694762926692\",\"$$hashKey\":\"object:195\"},{\"key\":\"bot_username\",\"value\":\"___replace_me___\",\"id\":\"temp1695295631652\",\"$$hashKey\":\"object:300\"}],\"messages\":\"\",\"message_direct\":true,\"nick\":\"message.from.first_name|||message.from.last_name|||callback_query.from.first_name|||callback_query.from.last_name|||message_reaction.chat.first_name|||message_reaction.chat.last_name|||edited_message.from.first_name|||edited_message.from.last_name\",\"country_code\":\"\",\"chat_id\":\"message.chat.id|||callback_query.message.chat.id|||message_reaction.chat.id|||edited_message.chat.id\",\"msg_body\":\"{{msg.message.text}}\",\"msg_cond\":\"message.text=__exists__\",\"msg_cond_img\":\"message.photo=__exists__\",\"msg_img\":\"{{msg.message.caption}}\\n{{msg.body}}\",\"msg_cond_2\":\"\",\"msg_body_2\":\"\",\"msg_cond_img_url_decode\":\"https:\/\/api.telegram.org\/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}\/getFile?file_id={{msg.message.photo___array_pop.file_id}}\",\"msg_cond_img_url_decode_output\":\"result.file_path||https:\/\/api.telegram.org\/file\/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}\/{{response}}\",\"msg_cond_img_body\":\"body\",\"msg_img_download\":false,\"msg_cond_img_url_remote_location\":true,\"msg_cond_attachments\":\"message.document=__exists__\",\"msg_attachments\":\"{{msg.body}}\\n{{msg.message.document.file_name}}\",\"msg_cond_attachments_body\":\"body\",\"msg_cond_attachments_url_decode\":\"https:\/\/api.telegram.org\/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}\/getFile?file_id={{msg.message.document.file_id}}\",\"msg_cond_attachments_url_remote_location\":true,\"msg_cond_attachments_url_remote_headers_content\":\"\",\"msg_cond_attachments_url_decode_output\":\"result.file_path||https:\/\/api.telegram.org\/file\/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}\/{{response}}\",\"msg_cond_attachments_file_name\":\"\",\"msg_img_2\":\"{{msg.body}}\\n{{msg.message.sticker.set_name}}\",\"msg_cond_img_2_body\":\"body\",\"msg_cond_img_2_url_decode\":\"https:\/\/api.telegram.org\/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}\/getFile?file_id={{msg.message.sticker.file_id}}\",\"msg_cond_img_2_url_decode_output\":\"result.file_path||https:\/\/api.telegram.org\/file\/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}\/{{response}}\",\"msg_cond_img_2_url_remote_location\":true,\"msg_cond_img_2\":\"message.sticker=__exists__\",\"msg_img_3\":\"{{msg.body}}\",\"msg_cond_img_3_body\":\"body\",\"msg_cond_img_3_url_decode\":\"https:\/\/api.telegram.org\/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}\/getFile?file_id={{msg.message.voice.file_id}}\",\"msg_cond_img_3_url_decode_output\":\"result.file_path||https:\/\/api.telegram.org\/file\/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}\/{{response}}\",\"msg_cond_img_3_url_remote_location\":true,\"msg_cond_img_3\":\"message.voice=__exists__\",\"msg_img_4\":\"{{msg.body}}\",\"msg_cond_img_4_body\":\"body\",\"msg_cond_img_4_url_decode\":\"https:\/\/api.telegram.org\/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}\/getFile?file_id={{msg.message.video_note.file_id}}\",\"msg_cond_img_4_url_decode_output\":\"result.file_path||https:\/\/api.telegram.org\/file\/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}\/{{response}}\",\"msg_cond_img_4_url_remote_location\":true,\"msg_cond_img_4\":\"message.video_note=__exists__\",\"msg_img_5\":\"{{msg.body}}\\n{{msg.message.audio.file_name}}\",\"msg_cond_img_5_body\":\"body\",\"msg_cond_img_5_url_decode\":\"https:\/\/api.telegram.org\/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}\/getFile?file_id={{msg.message.audio.file_id}}\",\"msg_cond_img_5_url_decode_output\":\"result.file_path||https:\/\/api.telegram.org\/file\/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}\/{{response}}\",\"msg_cond_img_5_url_remote_location\":true,\"msg_cond_img_5\":\"message.audio=__exists__\",\"msg_btn_cond_1\":\"callback_query.data=__exists__\",\"msg_btn_payload_1\":\"callback_query.data\",\"add_field_2_value\":\"telegram_bot_id\",\"add_field_value\":\"message.from.username|||callback_query.from.username|||message_reaction.chat.username|||edited_message.chat.username\",\"msg_cond_img_file_size\":\"message.photo___array_pop.file_size\",\"msg_cond_img_2_file_size\":\"message.sticker.file_size\",\"msg_cond_img_3_file_size\":\"message.voice.file_size\",\"msg_cond_img_4_file_size\":\"message.video_note.file_size\",\"msg_cond_img_5_file_size\":\"message.audio.file_size\",\"msg_cond_attachments_file_size\":\"message.document.file_size\",\"msg_img_6\":\"{{msg.body}}\\n{{msg.message.video.file_name}}\",\"msg_cond_img_6_file_size\":\"message.video.file_size\",\"msg_cond_img_6_url_decode\":\"https:\/\/api.telegram.org\/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}\/getFile?file_id={{msg.message.video.file_id}}\",\"msg_cond_img_6_url_decode_output\":\"result.file_path||https:\/\/api.telegram.org\/file\/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}\/{{response}}\",\"msg_cond_img_6_url_remote_location\":true,\"msg_cond_img_6\":\"message.video=__exists__\",\"msg_cond_img_6_body\":\"body\",\"msg_delivery_reaction_id\":\"message_reaction.message_id\",\"msg_delivery_reaction_condition\":\"message_reaction.new_reaction.0.type=__exists__\",\"msg_delivery_reaction_use_emoji\":true,\"msg_delivery_reaction_location\":\"message_reaction.new_reaction.0.emoji\",\"msg_delivery_reaction_remove_if_empty\":false,\"msg_delivery_reaction_remove_prev\":true,\"msg_delivery_un_reaction_id\":\"message_reaction.message_id\",\"msg_delivery_un_reaction_condition\":\"message_reaction.old_reaction.0.type=__exists__\",\"msg_delivery_un_reaction_use_emoji\":true,\"msg_delivery_edited_id\":\"edited_message.message_id\",\"msg_delivery_edited_condition\":\"edited_message=__exists__\",\"msg_delivery_edited_location\":\"edited_message.text\",\"message_id\":\"message.message_id\"}","icon":"social\/telegram-ico.png","icon_color":"","log_incoming":0,"log_failed_parse":0} \ No newline at end of file +{"name": "TelegramIntegration", "dep_id": 1, "disabled": 0, "identifier": "", "scope": "telegram", "configuration": "{\"attr\": [{\"key\": \"access_token\", \"value\": \"___replace_me___\", \"id\": \"temp1694762926692\", \"$$hashKey\": \"object:195\"}, {\"key\": \"bot_username\", \"value\": \"___replace_me___\", \"id\": \"temp1695295631652\", \"$$hashKey\": \"object:300\"}], \"messages\": \"\", \"message_direct\": true, \"nick\": \"message.from.first_name|||message.from.last_name|||callback_query.from.first_name|||callback_query.from.last_name|||message_reaction.chat.first_name|||message_reaction.chat.last_name|||edited_message.from.first_name|||edited_message.from.last_name\", \"country_code\": \"\", \"chat_id\": \"message.chat.id|||callback_query.message.chat.id|||message_reaction.chat.id|||edited_message.chat.id\", \"msg_body\": \"{{msg.message.text}}\", \"msg_cond\": \"message.text=__exists__\", \"msg_cond_img\": \"message.photo=__exists__\", \"msg_img\": \"{{msg.message.caption}}\\n{{msg.body}}\", \"msg_cond_2\": \"\", \"msg_body_2\": \"\", \"msg_cond_img_url_decode\": \"https://api.telegram.org/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}/getFile?file_id={{msg.message.photo___array_pop.file_id}}\", \"msg_cond_img_url_decode_output\": \"result.file_path||https://api.telegram.org/file/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}/{{response}}\", \"msg_cond_img_body\": \"body\", \"msg_img_download\": false, \"msg_cond_img_url_remote_location\": true, \"msg_cond_attachments\": \"message.document=__exists__\", \"msg_attachments\": \"{{msg.body}}\\n{{msg.message.document.file_name}}\", \"msg_cond_attachments_body\": \"body\", \"msg_cond_attachments_url_decode\": \"https://api.telegram.org/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}/getFile?file_id={{msg.message.document.file_id}}\", \"msg_cond_attachments_url_remote_location\": true, \"msg_cond_attachments_url_remote_headers_content\": \"\", \"msg_cond_attachments_url_decode_output\": \"result.file_path||https://api.telegram.org/file/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}/{{response}}\", \"msg_cond_attachments_file_name\": \"\", \"msg_img_2\": \"{{msg.body}}\\n{{msg.message.sticker.set_name}}\", \"msg_cond_img_2_body\": \"body\", \"msg_cond_img_2_url_decode\": \"https://api.telegram.org/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}/getFile?file_id={{msg.message.sticker.file_id}}\", \"msg_cond_img_2_url_decode_output\": \"result.file_path||https://api.telegram.org/file/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}/{{response}}\", \"msg_cond_img_2_url_remote_location\": true, \"msg_cond_img_2\": \"message.sticker=__exists__\", \"msg_img_3\": \"{{msg.body}}\", \"msg_cond_img_3_body\": \"body\", \"msg_cond_img_3_url_decode\": \"https://api.telegram.org/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}/getFile?file_id={{msg.message.voice.file_id}}\", \"msg_cond_img_3_url_decode_output\": \"result.file_path||https://api.telegram.org/file/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}/{{response}}\", \"msg_cond_img_3_url_remote_location\": true, \"msg_cond_img_3\": \"message.voice=__exists__\", \"msg_img_4\": \"{{msg.body}}\", \"msg_cond_img_4_body\": \"body\", \"msg_cond_img_4_url_decode\": \"https://api.telegram.org/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}/getFile?file_id={{msg.message.video_note.file_id}}\", \"msg_cond_img_4_url_decode_output\": \"result.file_path||https://api.telegram.org/file/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}/{{response}}\", \"msg_cond_img_4_url_remote_location\": true, \"msg_cond_img_4\": \"message.video_note=__exists__\", \"msg_img_5\": \"{{msg.body}}\\n{{msg.message.audio.file_name}}\", \"msg_cond_img_5_body\": \"body\", \"msg_cond_img_5_url_decode\": \"https://api.telegram.org/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}/getFile?file_id={{msg.message.audio.file_id}}\", \"msg_cond_img_5_url_decode_output\": \"result.file_path||https://api.telegram.org/file/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}/{{response}}\", \"msg_cond_img_5_url_remote_location\": true, \"msg_cond_img_5\": \"message.audio=__exists__\", \"msg_btn_cond_1\": \"callback_query.data=__exists__\", \"msg_btn_payload_1\": \"callback_query.data\", \"add_field_2_value\": \"telegram_bot_id\", \"add_field_value\": \"message.from.username|||callback_query.from.username|||message_reaction.chat.username|||edited_message.chat.username\", \"msg_cond_img_file_size\": \"message.photo___array_pop.file_size\", \"msg_cond_img_2_file_size\": \"message.sticker.file_size\", \"msg_cond_img_3_file_size\": \"message.voice.file_size\", \"msg_cond_img_4_file_size\": \"message.video_note.file_size\", \"msg_cond_img_5_file_size\": \"message.audio.file_size\", \"msg_cond_attachments_file_size\": \"message.document.file_size\", \"msg_img_6\": \"{{msg.body}}\\n{{msg.message.video.file_name}}\", \"msg_cond_img_6_file_size\": \"message.video.file_size\", \"msg_cond_img_6_url_decode\": \"https://api.telegram.org/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}/getFile?file_id={{msg.message.video.file_id}}\", \"msg_cond_img_6_url_decode_output\": \"result.file_path||https://api.telegram.org/file/bot{{msg.incoming_webhook.incoming_dynamic_array.access_token}}/{{response}}\", \"msg_cond_img_6_url_remote_location\": true, \"msg_cond_img_6\": \"message.video=__exists__\", \"msg_cond_img_6_body\": \"body\", \"msg_delivery_reaction_id\": \"message_reaction.message_id\", \"msg_delivery_reaction_condition\": \"message_reaction.new_reaction.0.type=__exists__\", \"msg_delivery_reaction_use_emoji\": true, \"msg_delivery_reaction_location\": \"message_reaction.new_reaction.0.emoji\", \"msg_delivery_reaction_remove_if_empty\": false, \"msg_delivery_reaction_remove_prev\": true, \"msg_delivery_un_reaction_id\": \"message_reaction.message_id\", \"msg_delivery_un_reaction_condition\": \"message_reaction.old_reaction.0.type=__exists__\", \"msg_delivery_un_reaction_use_emoji\": true, \"msg_delivery_edited_id\": \"edited_message.message_id\", \"msg_delivery_edited_condition\": \"edited_message=__exists__\", \"msg_delivery_edited_location\": \"edited_message.text\", \"message_id\": \"message.message_id\", \"message_id_reply\": \"message.reply_to_message.message_id\"}", "icon": "social/telegram-ico.png", "icon_color": "", "log_incoming": 0, "log_failed_parse": 0} \ No newline at end of file diff --git a/doc/telegram/rest-api.json b/doc/telegram/rest-api.json index b03eaaf..551cc7a 100644 --- a/doc/telegram/rest-api.json +++ b/doc/telegram/rest-api.json @@ -1 +1 @@ -{"name":"TelegramIntegration","description":"","configuration":"{\"host\":\"https://api.telegram.org\",\"ecache\":false,\"parameters\":[{\"method\":\"POST\",\"authorization\":\"\",\"api_key_location\":\"header\",\"query\":[],\"header\":[],\"conditions\":[],\"postparams\":[],\"userparams\":[],\"output\":[{\"key\":\"\",\"value\":\"\",\"id\":\"temp1706685738487\",\"success_name\":\"Success\",\"success_header\":\"200\"}],\"id\":\"temp1695212526903\",\"name\":\"Send\",\"suburl\":\"/bot{{args.chat.incoming_chat.incoming_dynamic_array.access_token}}/sendMessage\",\"body_request_type\":\"raw\",\"body_raw\":\"{\\n \\\"chat_id\\\":{{args.chat.incoming_chat.chat_external_id}},\\\"parse_mode\\\":\\\"HTML\\\",\\n \\\"text\\\":{{msg_html_nobr}}\\n{interactive_api}\\n,\\\"reply_markup\\\":{\\n \\\"resize_keyboard\\\":true,\\n\\\"inline_keyboard\\\":[\\n{button_template}\\n [{\\n \\\"text\\\": {{button_title}},\\n \\\"{is_url}url{/is_url}{is_button}callback_data{/is_button}\\\":{{button_payload}}\\n }]\\n{/button_template}\\n]\\n}\\n\\n{/interactive_api}\\n}\",\"body_request_type_content\":\"json\",\"remote_message_id\":\"result:message_id\",\"suburl_file\":\"/bot{{args.chat.incoming_chat.incoming_dynamic_array.access_token}}/{api_by_ext__tgs}sendSticker{/api_by_ext}{api_by_ext__ogg}sendVoice{/api_by_ext}{api_by_ext__mp3_m4a}sendAudio{/api_by_ext}{api_by_ext__mp4}sendVideo{/api_by_ext}{image_api}sendPhoto{/image_api}{file_api}sendDocument{/file_api}\",\"body_raw_file\":\"{\\n \\\"chat_id\\\":{{args.chat.incoming_chat.chat_external_id}},\\n \\\"{api_by_ext__tgs}sticker{/api_by_ext}{api_by_ext__ogg}voice{/api_by_ext}{api_by_ext__mp3_m4a}audio{/api_by_ext}{api_by_ext__mp4}video{/api_by_ext}{file_api}document{/file_api}{image_api}photo{/image_api}\\\":{{file_url}}\\n{api_by_ext__ogg},\\\"caption\\\":{{msg_clean}}{/api_by_ext}{api_by_ext__mp3_m4a},\\\"caption\\\":{{msg_clean}}{/api_by_ext}{api_by_ext__mp4},\\\"caption\\\":{{msg_clean}}{/api_by_ext}{file_api},\\\"caption\\\":{{msg_clean}}{/file_api}{image_api},\\\"caption\\\":{{msg_clean}}{/image_api}\\n}\",\"check_not_empty\":\"{{msg_html_nobr}}\",\"suburl_file_convert\":\"tgs,file_api,mp3_m4a,ogg\",\"suburl_file_skip_ext\":\"tgs\"},{\"method\":\"POST\",\"authorization\":\"\",\"api_key_location\":\"header\",\"query\":[],\"header\":[],\"conditions\":[],\"postparams\":[],\"userparams\":[],\"output\":[{\"key\":\"\",\"value\":\"\",\"id\":\"telegram_typing_success\",\"success_name\":\"Success\",\"success_header\":\"200\"}],\"id\":\"telegram_send_typing\",\"name\":\"Send typing\",\"suburl\":\"/bot{{args.chat.incoming_chat.incoming_dynamic_array.access_token}}/sendChatAction\",\"body_request_type\":\"raw\",\"body_request_type_content\":\"json\",\"body_raw\":\"{\\n \\\"chat_id\\\": {{args.chat.incoming_chat.chat_external_id}},\\n \\\"action\\\": \\\"typing\\\"\\n}\",\"check_not_empty\":\"{{args.chat.incoming_chat.chat_external_id}}\"}]}"} \ No newline at end of file +{"name": "TelegramIntegration", "description": "", "configuration": "{\"host\": \"https://api.telegram.org\", \"ecache\": false, \"parameters\": [{\"method\": \"POST\", \"authorization\": \"\", \"api_key_location\": \"header\", \"query\": [], \"header\": [], \"conditions\": [], \"postparams\": [], \"userparams\": [], \"output\": [{\"key\": \"\", \"value\": \"\", \"id\": \"temp1706685738487\", \"success_name\": \"Success\", \"success_header\": \"200\"}], \"id\": \"temp1695212526903\", \"name\": \"Send\", \"suburl\": \"/bot{{args.chat.incoming_chat.incoming_dynamic_array.access_token}}/sendMessage\", \"body_request_type\": \"raw\", \"body_raw\": \"{\\n \\\"chat_id\\\":{{args.chat.incoming_chat.chat_external_id}},\\\"parse_mode\\\":\\\"HTML\\\",\\n \\\"text\\\":{{msg_html_nobr}}\\n{reply_to},\\\"reply_parameters\\\":{\\\"message_id\\\":raw_{{iwh_msg_id}}}{/reply_to}\\n{interactive_api}\\n,\\\"reply_markup\\\":{\\n \\\"resize_keyboard\\\":true,\\n\\\"inline_keyboard\\\":[\\n{button_template}\\n [{\\n \\\"text\\\": {{button_title}},\\n \\\"{is_url}url{/is_url}{is_button}callback_data{/is_button}\\\":{{button_payload}}\\n }]\\n{/button_template}\\n]\\n}\\n\\n{/interactive_api}\\n}\", \"body_request_type_content\": \"json\", \"remote_message_id\": \"result:message_id\", \"suburl_file\": \"/bot{{args.chat.incoming_chat.incoming_dynamic_array.access_token}}/{api_by_ext__tgs}sendSticker{/api_by_ext}{api_by_ext__ogg}sendVoice{/api_by_ext}{api_by_ext__mp3_m4a}sendAudio{/api_by_ext}{api_by_ext__mp4}sendVideo{/api_by_ext}{image_api}sendPhoto{/image_api}{file_api}sendDocument{/file_api}\", \"body_raw_file\": \"{\\n \\\"chat_id\\\":{{args.chat.incoming_chat.chat_external_id}},\\n \\\"{api_by_ext__tgs}sticker{/api_by_ext}{api_by_ext__ogg}voice{/api_by_ext}{api_by_ext__mp3_m4a}audio{/api_by_ext}{api_by_ext__mp4}video{/api_by_ext}{file_api}document{/file_api}{image_api}photo{/image_api}\\\":{{file_url}}\\n{reply_to},\\\"reply_parameters\\\":{\\\"message_id\\\":raw_{{iwh_msg_id}}}{/reply_to}\\n{api_by_ext__ogg},\\\"caption\\\":{{msg_clean}}{/api_by_ext}{api_by_ext__mp3_m4a},\\\"caption\\\":{{msg_clean}}{/api_by_ext}{api_by_ext__mp4},\\\"caption\\\":{{msg_clean}}{/api_by_ext}{file_api},\\\"caption\\\":{{msg_clean}}{/file_api}{image_api},\\\"caption\\\":{{msg_clean}}{/image_api}\\n}\", \"check_not_empty\": \"{{msg_html_nobr}}\", \"suburl_file_convert\": \"tgs,file_api,mp3_m4a,ogg\", \"suburl_file_skip_ext\": \"tgs\"}, {\"method\": \"POST\", \"authorization\": \"\", \"api_key_location\": \"header\", \"query\": [], \"header\": [], \"conditions\": [], \"postparams\": [], \"userparams\": [], \"output\": [{\"key\": \"\", \"value\": \"\", \"id\": \"telegram_typing_success\", \"success_name\": \"Success\", \"success_header\": \"200\"}], \"id\": \"telegram_send_typing\", \"name\": \"Send typing\", \"suburl\": \"/bot{{args.chat.incoming_chat.incoming_dynamic_array.access_token}}/sendChatAction\", \"body_request_type\": \"raw\", \"body_request_type_content\": \"json\", \"body_raw\": \"{\\n \\\"chat_id\\\": {{args.chat.incoming_chat.chat_external_id}},\\n \\\"action\\\": \\\"typing\\\"\\n}\", \"check_not_empty\": \"{{args.chat.incoming_chat.chat_external_id}}\"}]}"} \ No newline at end of file