Skip to content

Commit 5c49b7c

Browse files
committed
feat(console): check running app in command or job and get topic from handle function
1 parent 748feb8 commit 5c49b7c

File tree

2 files changed

+224
-174
lines changed

2 files changed

+224
-174
lines changed

src/TelegramBotHandler.php

Lines changed: 20 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,11 @@
33
namespace TheCoder\MonologTelegram;
44

55
use GuzzleHttp\Exception\GuzzleException;
6-
use Illuminate\Routing\Router;
7-
use Illuminate\Support\Facades\Route;
86
use Monolog\Handler\AbstractProcessingHandler;
97
use Monolog\Logger;
10-
use ReflectionMethod;
11-
use TheCoder\MonologTelegram\Attributes\TopicLogInterface;
128

139
class TelegramBotHandler extends AbstractProcessingHandler
1410
{
15-
16-
protected Router $router;
17-
1811
/**
1912
* text parameter in sendMessage method
2013
* @see https://core.telegram.org/bots/api#sendmessage
@@ -25,69 +18,68 @@ class TelegramBotHandler extends AbstractProcessingHandler
2518
* bot api url
2619
* @var string
2720
*/
28-
protected $botApi;
21+
protected string $botApi;
2922

3023
/**
3124
* Telegram bot access token provided by BotFather.
3225
* Create telegram bot with https://telegram.me/BotFather and use access token from it.
3326
* @var string
3427
*/
35-
protected $token;
28+
protected string $token;
3629

3730
/**
3831
* if telegram is blocked in your region you can use proxy
3932
* @var null
4033
*/
41-
protected $proxy;
34+
protected string|null $proxy;
4235

4336
/**
4437
* Telegram channel name.
4538
* Since to start with '@' symbol as prefix.
4639
* @var string
4740
*/
48-
protected $chatId;
41+
protected string|int $chatId;
4942

5043
/**
5144
* If chat groups are used instead of telegram channels,
5245
* and the ability to set topics on groups is enabled,
5346
* this configuration can be utilized.
5447
* @var string|null
5548
*/
56-
protected $topicId;
49+
protected string|int|null $topicId;
5750

58-
protected $queue = null;
51+
protected string|null $queue = null;
5952

60-
protected $topicsLevel;
53+
protected TopicDetector $topicDetector;
6154

6255
/**
6356
* @param string $token Telegram bot access token provided by BotFather
6457
* @param string $channel Telegram channel name
6558
* @inheritDoc
6659
*/
6760
public function __construct(
68-
Router $router,
69-
string $token,
70-
string $chat_id,
71-
?string $topic_id = null,
72-
?string $queue = null,
73-
$topics_level = [],
74-
$level = Logger::DEBUG,
75-
bool $bubble = true,
76-
$bot_api = 'https://api.telegram.org/bot',
77-
$proxy = null)
61+
string $token,
62+
string|int $chat_id,
63+
string|null $topic_id = null,
64+
string|null $queue = null,
65+
array $topics_level = [],
66+
$level = Logger::DEBUG,
67+
bool $bubble = true,
68+
string $bot_api = 'https://api.telegram.org/bot',
69+
string|null $proxy = null)
7870
{
7971
parent::__construct($level, $bubble);
8072

81-
$this->router = $router;
8273
$this->token = $token;
8374
$this->botApi = $bot_api;
8475
$this->chatId = $chat_id;
8576
$this->topicId = $topic_id;
8677
$this->queue = $queue;
87-
$this->topicsLevel = $topics_level;
8878
$this->level = $level;
8979
$this->bubble = $bubble;
9080
$this->proxy = $proxy;
81+
82+
$this->topicDetector = new TopicDetector($topics_level);
9183
}
9284

9385
/**
@@ -96,7 +88,8 @@ public function __construct(
9688
*/
9789
protected function write($record): void
9890
{
99-
$topicId = $this->getTopicByAttribute($record);
91+
$topicId = $this->topicDetector->getTopicByAttribute($record);
92+
10093
$token = $record['context']['token'] ?? null;
10194
$chatId = $record['context']['chat_id'] ?? null;
10295
$topicId = $topicId ?? $record['context']['topic_id'] ?? null;
@@ -140,151 +133,4 @@ protected function send(string $message, $token = null, $chatId = null, $topicId
140133
}
141134
}
142135

143-
protected function getTopicByAttribute($record): string|null
144-
{
145-
if (isset($record['context']['exception'])) {
146-
$trace = $record['context']['exception']->getTrace();
147-
148-
$commandClass = $this->getClassForCommand($trace);
149-
if ($commandClass) {
150-
return $this->getTopicIdByReflection($commandClass, 'handle');
151-
}
152-
153-
$jobClass = $this->getClassForJob($trace);
154-
if ($jobClass) {
155-
return $this->getTopicIdByReflection($jobClass, 'handle');
156-
}
157-
}
158-
159-
return $this->getTopicByRoute();
160-
}
161-
162-
protected function getClassForCommand(array $trace): ?string
163-
{
164-
if (!app()->runningInConsole()) {
165-
return null;
166-
}
167-
168-
foreach ($trace as $frame) {
169-
if ($frame['function'] === 'handle' && isset($frame['class']) && str_contains($frame['class'], 'Console\Commands')) {
170-
return $frame['class'];
171-
}
172-
}
173-
174-
return null;
175-
}
176-
177-
protected function getClassForJob(array $trace): ?string
178-
{
179-
if (!app()->bound('queue.worker')) {
180-
return null;
181-
}
182-
183-
foreach ($trace as $frame) {
184-
if ($frame['function'] === 'handle' && isset($frame['class']) && str_contains($frame['class'], 'App\Jobs')) {
185-
return $frame['class'];
186-
}
187-
}
188-
189-
return null;
190-
}
191-
192-
protected function getTopicByRoute(): string|null
193-
{
194-
$route = Route::current();
195-
if (!$route || !isset($route->getAction()['controller'])) {
196-
return null;
197-
}
198-
199-
[$controller, $method] = explode('@', $route->getAction()['controller']);
200-
201-
$topicId = $this->getTopicIdByReflection($controller, $method);
202-
if ($topicId === false) {
203-
$topicId = $this->getTopicIdByRegex($route->getAction());
204-
}
205-
206-
return $topicId;
207-
}
208-
209-
protected function getTopicIdByReflection($class, $method): bool|string|null
210-
{
211-
try {
212-
$reflectionMethod = new ReflectionMethod($class, $method);
213-
214-
$attributes = $reflectionMethod->getAttributes();
215-
216-
if ($attributes[0] !== null) {
217-
/** @var TopicLogInterface $notifyException */
218-
$notifyException = $attributes[0]->newInstance() ?? null;
219-
return $notifyException->getTopicId($this->topicsLevel);
220-
}
221-
222-
} catch (\Throwable $e) {
223-
224-
}
225-
return false;
226-
}
227-
228-
protected function getTopicIdByRegex($action)
229-
{
230-
try {
231-
// if reflection could not get attribute use regex instead
232-
[$controller, $method] = explode('@', $action['controller']);
233-
234-
$filePath = base_path(str_replace('App', 'app', $controller) . '.php');
235-
$fileContent = file_get_contents($filePath);
236-
$allAttributes = [];
237-
238-
// Regex to match attributes and methods
239-
$regex = '/\#\[\s*(.*?)\s*\]\s*public\s*function\s*(\w+)/';
240-
if (preg_match_all($regex, $fileContent, $matches, PREG_SET_ORDER)) {
241-
foreach ($matches as $match) {
242-
$attributeString = $match[1];
243-
$methodName = $match[2];
244-
245-
$attributes = array_map('trim', explode(',', $attributeString));
246-
foreach ($attributes as $attribute) {
247-
$attributeName = preg_replace('/\(.*/', '', $attribute);
248-
$allAttributes[$methodName][] = $attributeName;
249-
}
250-
}
251-
}
252-
253-
if (empty($allAttributes)) {
254-
return null;
255-
}
256-
257-
if (isset($allAttributes[$method][0])) {
258-
foreach ($this->topicsLevel as $key => $_topicLevel) {
259-
if (str_contains($key, $allAttributes[$method][0])) {
260-
return $_topicLevel;
261-
}
262-
}
263-
}
264-
265-
} catch (\Throwable $e) {
266-
}
267-
return null;
268-
}
269-
270-
public function setToken(string $token): static
271-
{
272-
$this->token = $token;
273-
274-
return $this;
275-
}
276-
277-
public function setChatId(string $chatId): static
278-
{
279-
$this->chatId = $chatId;
280-
281-
return $this;
282-
}
283-
284-
public function setTopicId(string $topicId): static
285-
{
286-
$this->topicId = $topicId;
287-
288-
return $this;
289-
}
290136
}

0 commit comments

Comments
 (0)