PluginProbe
Media Cloud Sync / 1.2.5
Media Cloud Sync v1.2.5
1.4.2 1.4.1 1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 All 36 releases
media-cloud-sync / includes / sdk / google / monolog / monolog / src / Monolog / Handler / TelegramBotHandler.php

TelegramBotHandler.php in Media Cloud Sync 1.2.5, at includes/sdk/google/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php

217 lines 8.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare (strict_types=1);
4 /*
5 * This file is part of the Monolog package.
6 *
7 * (c) Jordi Boggiano <[email protected]>
8 *
9 * For the full copyright and license information, please view the LICENSE
10 * file that was distributed with this source code.
11 */
12 namespace Dudlewebs\WPMCS\Monolog\Handler;
13
14 use RuntimeException;
15 use Dudlewebs\WPMCS\Monolog\Logger;
16 use Dudlewebs\WPMCS\Monolog\Utils;
17 /**
18 * Handler send logs to Telegram using Telegram Bot API.
19 *
20 * How to use:
21 * 1) Create telegram bot with https://telegram.me/BotFather
22 * 2) Create a telegram channel where logs will be recorded.
23 * 3) Add created bot from step 1 to the created channel from step 2.
24 *
25 * Use telegram bot API key from step 1 and channel name with '@' prefix from step 2 to create instance of TelegramBotHandler
26 *
27 * @link https://core.telegram.org/bots/api
28 *
29 * @author Mazur Alexandr <[email protected]>
30 *
31 * @phpstan-import-type Record from \Monolog\Logger
32 */
33 class TelegramBotHandler extends AbstractProcessingHandler
34 {
35 private const BOT_API = 'https://api.telegram.org/bot';
36 /**
37 * The available values of parseMode according to the Telegram api documentation
38 */
39 private const AVAILABLE_PARSE_MODES = ['HTML', 'MarkdownV2', 'Markdown'];
40 /**
41 * The maximum number of characters allowed in a message according to the Telegram api documentation
42 */
43 private const MAX_MESSAGE_LENGTH = 4096;
44 /**
45 * Telegram bot access token provided by BotFather.
46 * Create telegram bot with https://telegram.me/BotFather and use access token from it.
47 * @var string
48 */
49 private $apiKey;
50 /**
51 * Telegram channel name.
52 * Since to start with '@' symbol as prefix.
53 * @var string
54 */
55 private $channel;
56 /**
57 * The kind of formatting that is used for the message.
58 * See available options at https://core.telegram.org/bots/api#formatting-options
59 * or in AVAILABLE_PARSE_MODES
60 * @var ?string
61 */
62 private $parseMode;
63 /**
64 * Disables link previews for links in the message.
65 * @var ?bool
66 */
67 private $disableWebPagePreview;
68 /**
69 * Sends the message silently. Users will receive a notification with no sound.
70 * @var ?bool
71 */
72 private $disableNotification;
73 /**
74 * True - split a message longer than MAX_MESSAGE_LENGTH into parts and send in multiple messages.
75 * False - truncates a message that is too long.
76 * @var bool
77 */
78 private $splitLongMessages;
79 /**
80 * Adds 1-second delay between sending a split message (according to Telegram API to avoid 429 Too Many Requests).
81 * @var bool
82 */
83 private $delayBetweenMessages;
84 /**
85 * @param string $apiKey Telegram bot access token provided by BotFather
86 * @param string $channel Telegram channel name
87 * @param bool $splitLongMessages Split a message longer than MAX_MESSAGE_LENGTH into parts and send in multiple messages
88 * @param bool $delayBetweenMessages Adds delay between sending a split message according to Telegram API
89 * @throws MissingExtensionException
90 */
91 public function __construct(string $apiKey, string $channel, $level = Logger::DEBUG, bool $bubble = \true, ?string $parseMode = null, ?bool $disableWebPagePreview = null, ?bool $disableNotification = null, bool $splitLongMessages = \false, bool $delayBetweenMessages = \false)
92 {
93 if (!extension_loaded('curl')) {
94 throw new MissingExtensionException('The curl extension is needed to use the TelegramBotHandler');
95 }
96 parent::__construct($level, $bubble);
97 $this->apiKey = $apiKey;
98 $this->channel = $channel;
99 $this->setParseMode($parseMode);
100 $this->disableWebPagePreview($disableWebPagePreview);
101 $this->disableNotification($disableNotification);
102 $this->splitLongMessages($splitLongMessages);
103 $this->delayBetweenMessages($delayBetweenMessages);
104 }
105 public function setParseMode(?string $parseMode = null): self
106 {
107 if ($parseMode !== null && !in_array($parseMode, self::AVAILABLE_PARSE_MODES)) {
108 throw new \InvalidArgumentException('Unknown parseMode, use one of these: ' . implode(', ', self::AVAILABLE_PARSE_MODES) . '.');
109 }
110 $this->parseMode = $parseMode;
111 return $this;
112 }
113 public function disableWebPagePreview(?bool $disableWebPagePreview = null): self
114 {
115 $this->disableWebPagePreview = $disableWebPagePreview;
116 return $this;
117 }
118 public function disableNotification(?bool $disableNotification = null): self
119 {
120 $this->disableNotification = $disableNotification;
121 return $this;
122 }
123 /**
124 * True - split a message longer than MAX_MESSAGE_LENGTH into parts and send in multiple messages.
125 * False - truncates a message that is too long.
126 * @param bool $splitLongMessages
127 * @return $this
128 */
129 public function splitLongMessages(bool $splitLongMessages = \false): self
130 {
131 $this->splitLongMessages = $splitLongMessages;
132 return $this;
133 }
134 /**
135 * Adds 1-second delay between sending a split message (according to Telegram API to avoid 429 Too Many Requests).
136 * @param bool $delayBetweenMessages
137 * @return $this
138 */
139 public function delayBetweenMessages(bool $delayBetweenMessages = \false): self
140 {
141 $this->delayBetweenMessages = $delayBetweenMessages;
142 return $this;
143 }
144 /**
145 * {@inheritDoc}
146 */
147 public function handleBatch(array $records): void
148 {
149 /** @var Record[] $messages */
150 $messages = [];
151 foreach ($records as $record) {
152 if (!$this->isHandling($record)) {
153 continue;
154 }
155 if ($this->processors) {
156 /** @var Record $record */
157 $record = $this->processRecord($record);
158 }
159 $messages[] = $record;
160 }
161 if (!empty($messages)) {
162 $this->send((string) $this->getFormatter()->formatBatch($messages));
163 }
164 }
165 /**
166 * @inheritDoc
167 */
168 protected function write(array $record): void
169 {
170 $this->send($record['formatted']);
171 }
172 /**
173 * Send request to @link https://api.telegram.org/bot on SendMessage action.
174 * @param string $message
175 */
176 protected function send(string $message): void
177 {
178 $messages = $this->handleMessageLength($message);
179 foreach ($messages as $key => $msg) {
180 if ($this->delayBetweenMessages && $key > 0) {
181 sleep(1);
182 }
183 $this->sendCurl($msg);
184 }
185 }
186 protected function sendCurl(string $message): void
187 {
188 $ch = curl_init();
189 $url = self::BOT_API . $this->apiKey . '/SendMessage';
190 curl_setopt($ch, \CURLOPT_URL, $url);
191 curl_setopt($ch, \CURLOPT_RETURNTRANSFER, \true);
192 curl_setopt($ch, \CURLOPT_SSL_VERIFYPEER, \true);
193 curl_setopt($ch, \CURLOPT_POSTFIELDS, http_build_query(['text' => $message, 'chat_id' => $this->channel, 'parse_mode' => $this->parseMode, 'disable_web_page_preview' => $this->disableWebPagePreview, 'disable_notification' => $this->disableNotification]));
194 $result = Curl\Util::execute($ch);
195 if (!is_string($result)) {
196 throw new RuntimeException('Telegram API error. Description: No response');
197 }
198 $result = json_decode($result, \true);
199 if ($result['ok'] === \false) {
200 throw new RuntimeException('Telegram API error. Description: ' . $result['description']);
201 }
202 }
203 /**
204 * Handle a message that is too long: truncates or splits into several
205 * @param string $message
206 * @return string[]
207 */
208 private function handleMessageLength(string $message): array
209 {
210 $truncatedMarker = ' (...truncated)';
211 if (!$this->splitLongMessages && strlen($message) > self::MAX_MESSAGE_LENGTH) {
212 return [Utils::substr($message, 0, self::MAX_MESSAGE_LENGTH - strlen($truncatedMarker)) . $truncatedMarker];
213 }
214 return str_split($message, self::MAX_MESSAGE_LENGTH);
215 }
216 }
217