瀏覽代碼

Add telegram bot handler.

Alexandr Mazur 6 年之前
父節點
當前提交
1284105074
共有 2 個文件被更改,包括 132 次插入0 次删除
  1. 90 0
      src/Monolog/Handler/TelegramBotHandler.php
  2. 42 0
      tests/Monolog/Handler/TelegramBotHandlerTest.php

+ 90 - 0
src/Monolog/Handler/TelegramBotHandler.php

@@ -0,0 +1,90 @@
+<?php
+
+namespace Monolog\Handler;
+
+use RuntimeException;
+use Monolog\Logger;
+
+/**
+ * Handler send logs to Telegram using Telegram Bot API.
+ *
+ * How to use:
+ *  1) Create telegram bot with https://telegram.me/BotFather
+ *  2) Create a telegram channel where logs will be recorded.
+ *  3) Add created bot from step 1 to the created channel from step 2.
+ *
+ * Use telegram bot API key from step 1 and channel name with '@' prefix from step 2 to create instance of TelegramBotHandler
+ *
+ * @link https://core.telegram.org/bots/api
+ *
+ * @author Mazur Alexandr <alexandrmazur96@gmail.com>
+ */
+class TelegramBotHandler extends AbstractProcessingHandler
+{
+    private const BOT_API = 'https://api.telegram.org/bot';
+
+    /**
+     * Telegram bot access token provided by BotFather.
+     * Create telegram bot with https://telegram.me/BotFather and use access token from it.
+     * @var string
+     */
+    private $apiKey;
+
+    /**
+     * Telegram channel name.
+     * Since to start with '@' symbol as prefix.
+     * @var string
+     */
+    private $channel;
+
+    /**
+     * @param string $apiKey Telegram bot access token provided by BotFather
+     * @param string $channel Telegram channel name
+     * @inheritDoc
+     */
+    public function __construct(
+        string $apiKey,
+        string $channel,
+        $level = Logger::DEBUG,
+        bool $bubble = true
+    ) {
+        parent::__construct($level, $bubble);
+
+        $this->apiKey = $apiKey;
+        $this->channel = $channel;
+        $this->level = $level;
+        $this->bubble = $bubble;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    protected function write(array $record): void
+    {
+        $this->send($record['formatted']);
+    }
+
+    /**
+     * Send request to @link https://api.telegram.org/bot on SendMessage action.
+     * @param string $message
+     */
+    protected function send(string $message): void
+    {
+        $ch = curl_init();
+        $url = self::BOT_API . $this->apiKey . '/SendMessage';
+        curl_setopt($ch, CURLOPT_URL, $url);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
+        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
+            'text' => $message,
+            'chat_id' => $this->channel,
+        ]));
+
+        $result = curl_exec($ch);
+        $result = json_decode($result, true);
+
+        if ($result['ok'] === false) {
+            throw new RuntimeException('Telegram API error. Description: ' . $result['description']);
+        }
+    }
+}

+ 42 - 0
tests/Monolog/Handler/TelegramBotHandlerTest.php

@@ -0,0 +1,42 @@
+<?php
+
+namespace Monolog\Handler;
+
+use Monolog\Logger;
+use Monolog\Test\TestCase;
+
+/**
+ * @author Mazur Alexandr <alexandrmazur96@gmail.com>
+ * @link https://core.telegram.org/bots/api
+ */
+class TelegramBotHandlerTest extends TestCase
+{
+    /**
+     * @var TelegramBotHandler
+     */
+    private $handler;
+
+    public function testSendTelegramRequest(): void
+    {
+        $this->createHandler();
+        $this->handler->handle($this->getRecord());
+    }
+
+    /**
+     * @param string $apiKey
+     * @param string $channel
+     */
+    private function createHandler(string $apiKey = 'testKey', string $channel = 'testChannel'): void
+    {
+        $constructorArgs = [$apiKey, $channel, Logger::DEBUG, true];
+
+        $this->handler = $this->getMockBuilder(TelegramBotHandler::class)
+            ->setConstructorArgs($constructorArgs)
+            ->setMethods(['send'])
+            ->getMock();
+
+        $this->handler->expects($this->atLeast(1))
+            ->method('send')
+            ->willReturn(null);
+    }
+}