Skip to content

Commit 468a6ce

Browse files
committed
json way to send data to telegram
1 parent 6984427 commit 468a6ce

File tree

6 files changed

+56
-99
lines changed

6 files changed

+56
-99
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@
1818
/UPGRADING.md export-ignore
1919
/phpstan.neon.dist export-ignore
2020
/phpstan-baseline.neon export-ignore
21+
/.env

.github/workflows/run-tests.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@ jobs:
1818
matrix:
1919
os: [ubuntu-latest, windows-latest]
2020
php: [8.4, 8.3]
21-
laravel: [11.*, 10.*]
21+
laravel: [12.*,11.*, 10.*]
2222
stability: [prefer-lowest, prefer-stable]
2323
include:
24+
- laravel: 12.*
25+
testbench: 9.*
26+
carbon: ^2.63
2427
- laravel: 11.*
2528
testbench: 9.*
2629
carbon: ^2.63

composer.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@
2121
"illuminate/contracts": "^10.0||^11.0||^12.0"
2222
},
2323
"require-dev": {
24+
"larastan/larastan": "^3.6",
2425
"laravel/pint": "^1.14",
2526
"nunomaduro/collision": "^8.1.1||^7.10.0",
2627
"orchestra/testbench": "^9.0.0||^8.22.0",
2728
"pestphp/pest": "^3.0",
28-
"pestphp/pest-plugin-arch": "^3.0",
29-
"pestphp/pest-plugin-laravel": "^3.0"
29+
"pestphp/pest-plugin-arch": "^3.1",
30+
"pestphp/pest-plugin-laravel": "^3.0",
31+
"phpstan/phpstan": "^2.1"
3032
},
3133
"autoload": {
3234
"psr-4": {

src/Telegramlogs.php

Lines changed: 26 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,29 @@
1111
class Telegramlogs extends AbstractProcessingHandler
1212
{
1313
protected string $botToken;
14+
1415
protected string $chatId;
16+
1517
protected ?string $topicId;
18+
1619
protected Client $client;
20+
1721
protected bool $ignoreEmptyMessages;
22+
1823
protected int $timeout;
24+
1925
protected bool $splitLongMessages;
26+
2027
protected int $maxMessageLength;
2128

2229
public function __construct(
2330
$level = Logger::DEBUG,
2431
bool $bubble = true,
2532
?Client $client = null,
2633
bool $ignoreEmptyMessages = true,
27-
int $timeout = null,
28-
bool $splitLongMessages = null,
29-
int $maxMessageLength = null
34+
?int $timeout = null,
35+
?bool $splitLongMessages = null,
36+
?int $maxMessageLength = null
3037
) {
3138
parent::__construct($level, $bubble);
3239

@@ -50,122 +57,50 @@ protected function write(LogRecord $record): void
5057
return;
5158
}
5259

53-
$formattedMessage = $this->formatRecord($record);
54-
5560
try {
56-
$this->sendMessage($formattedMessage);
57-
} catch (GuzzleException $e) {
58-
// Log the error to the default logger if Telegram fails
59-
error_log('Failed to send Telegram log: ' . $e->getMessage());
60-
}
61-
}
62-
63-
protected function formatRecord(LogRecord $record): string
64-
{
65-
$includeContext = config('telegramlogs.formatting.include_context', true);
66-
$includeStackTrace = config('telegramlogs.formatting.include_stack_trace', true);
67-
$parseMode = config('telegramlogs.formatting.parse_mode', 'MarkdownV2');
68-
69-
$context = '';
70-
if ($includeContext && $record->context) {
71-
$context = "\n\nContext:\n```json\n" .
72-
json_encode($record->context, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) .
73-
"\n```";
74-
}
61+
// Convert LogRecord to array for JSON serialization
62+
$recordArray = $record->toArray();
7563

76-
$extra = '';
77-
if ($record->extra) {
78-
$extra = "\n\nExtra:\n```json\n" .
79-
json_encode($record->extra, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) .
80-
"\n```";
81-
}
82-
83-
// Add stack trace for error-level logs if enabled
84-
$stackTrace = '';
85-
if ($includeStackTrace &&
86-
$record->level->value >= \Monolog\Level::Error->value &&
87-
isset($record->context['exception'])) {
88-
$stackTrace = "\n\nStack Trace:\n```\n" .
89-
$record->context['exception']->getTraceAsString() .
90-
"\n```";
91-
}
92-
93-
if ($parseMode === 'MarkdownV2') {
94-
return sprintf(
95-
"*[%s] %s*\n\n`%s`%s%s%s",
96-
$record->datetime->format('Y-m-d H:i:s'),
97-
strtoupper($record->level->getName()),
98-
$this->escapeMarkdown($record->message),
99-
$context,
100-
$extra,
101-
$stackTrace
102-
);
103-
} elseif ($parseMode === 'HTML') {
104-
return sprintf(
105-
"<b>[%s] %s</b>\n\n<code>%s</code>%s%s%s",
106-
$record->datetime->format('Y-m-d H:i:s'),
107-
strtoupper($record->level->getName()),
108-
htmlspecialchars($record->message),
109-
str_replace(['```json', '```'], ['<pre>', '</pre>'], $context),
110-
str_replace(['```json', '```'], ['<pre>', '</pre>'], $extra),
111-
str_replace(['```', '```'], ['<pre>', '</pre>'], $stackTrace)
112-
);
113-
} else {
114-
// Plain text
115-
return sprintf(
116-
"[%s] %s\n\n%s%s%s%s",
117-
$record->datetime->format('Y-m-d H:i:s'),
118-
strtoupper($record->level->getName()),
119-
$record->message,
120-
str_replace(['```json', '```', "\n"], ['', '', "\n"], $context),
121-
str_replace(['```json', '```', "\n"], ['', '', "\n"], $extra),
122-
str_replace(['```', '```'], ['', ''], $stackTrace)
123-
);
124-
}
125-
}
64+
// Encode the record array into JSON
65+
$message = json_encode($recordArray, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
12666

127-
protected function escapeMarkdown(string $text): string
128-
{
129-
$characters = ['_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!'];
130-
foreach ($characters as $char) {
131-
$text = str_replace($char, '\\' . $char, $text);
67+
// Send the JSON message
68+
$this->sendMessage($message);
69+
} catch (GuzzleException $e) {
70+
// Log the error to the default logger if Telegram fails
71+
error_log('Failed to send Telegram log: '.$e->getMessage());
13272
}
133-
134-
return $text;
13573
}
13674

13775
protected function sendMessage(string $message): void
13876
{
13977
$url = "/bot{$this->botToken}/sendMessage";
14078

141-
if ($this->splitLongMessages && strlen($message) > $this->maxMessageLength) {
142-
$messages = str_split($message, $this->maxMessageLength - 100);
79+
// Format message as JSON code block for better readability in Telegram
80+
$formattedMessage = "```json\n".$message."\n```";
81+
82+
if ($this->splitLongMessages && strlen($formattedMessage) > $this->maxMessageLength) {
83+
$messages = str_split($formattedMessage, $this->maxMessageLength - 100);
14384
foreach ($messages as $index => $partialMessage) {
14485
$this->sendPartialMessage(
14586
$url,
14687
sprintf("(%d/%d)\n%s", $index + 1, count($messages), $partialMessage)
14788
);
14889
}
14990
} else {
150-
$this->sendPartialMessage($url, $message);
91+
$this->sendPartialMessage($url, $formattedMessage);
15192
}
15293
}
15394

15495
protected function sendPartialMessage(string $url, string $message): void
15596
{
156-
$parseMode = config('telegramlogs.formatting.parse_mode', 'MarkdownV2');
157-
15897
$payload = [
15998
'chat_id' => $this->chatId,
16099
'text' => $message,
100+
'parse_mode' => 'MarkdownV2',
161101
'disable_web_page_preview' => true,
162102
];
163103

164-
// Only add parse_mode if it's not null (plain text)
165-
if ($parseMode) {
166-
$payload['parse_mode'] = $parseMode;
167-
}
168-
169104
if ($this->topicId) {
170105
$payload['message_thread_id'] = $this->topicId;
171106
}

src/TelegramlogsServiceProvider.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public function register()
1010
{
1111
// Merge package config with app config
1212
$this->mergeConfigFrom(
13-
__DIR__ . '/../config/telegramlogs.php',
13+
__DIR__.'/../config/telegramlogs.php',
1414
'telegramlogs'
1515
);
1616
}
@@ -19,7 +19,7 @@ public function boot()
1919
{
2020
// Publish config file
2121
$this->publishes([
22-
__DIR__ . '/../config/telegramlogs.php' => config_path('telegramlogs.php'),
22+
__DIR__.'/../config/telegramlogs.php' => config_path('telegramlogs.php'),
2323
], 'telegramlogs-config');
2424

2525
// Add telegram channel to logging configuration
@@ -32,7 +32,7 @@ protected function addTelegramLogChannel()
3232
$loggingConfig = config('logging.channels', []);
3333

3434
// Add telegram channel if it doesn't exist, using the config from telegramlogs
35-
if (!isset($loggingConfig['telegram'])) {
35+
if (! isset($loggingConfig['telegram'])) {
3636
$telegramChannelConfig = config('telegramlogs.channels.telegram', [
3737
'driver' => 'custom',
3838
'via' => Telegramlogs::class,

tests/ArchTest.php

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
<?php
22

33
arch('it will not use debugging functions')
4-
->expect(['dd', 'dump', 'ray'])
5-
->each->not->toBeUsed();
4+
->expect('App')
5+
->toUseStrictTypes()
6+
->not->toUse(['die', 'dd', 'dump']);
7+
8+
arch()
9+
->expect('Uzhlaravel\Telegramlogs\Commands')
10+
->toBeClasses()
11+
->toExtend('Illuminate\Console\Command')
12+
->toOnlyBeUsedIn('src\Commands');
13+
14+
arch()
15+
->expect('Uzhlaravel\Telegramlogs\Facades')
16+
->toBeClasses()
17+
->toExtend('Illuminate\Support\Facades\Facade');
18+
19+
arch('package classes should be in correct namespace')
20+
->expect('Uzhlaravel\\Telegramlogs')
21+
->toBeClasses();

0 commit comments

Comments
 (0)