Passed
Branch master (96d419)
by Shahrad
02:15
created

CrashPad::report()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 7
c 1
b 0
f 0
dl 0
loc 10
rs 10
cc 1
nc 1
nop 1
1
<?php
2
declare(strict_types=1);
3
4
namespace TelegramBot;
5
6
use Symfony\Component\Dotenv\Dotenv;
7
8
/**
9
 * CrashPad class
10
 *
11
 * @link    https://github.com/telegram-bot-php/core
12
 * @author  Shahrad Elahi (https://github.com/shahradelahi)
13
 * @license https://github.com/telegram-bot-php/core/blob/master/LICENSE (MIT License)
14
 */
15
class CrashPad
16
{
17
18
    /**
19
     * Clear crash files.
20
     *
21
     * @return void
22
     */
23
    public static function clearCrashFiles(): void
24
    {
25
        $files = glob(getcwd() . '.telegram-bot/*.log');
26
        foreach ($files as $file) {
27
            unlink($file);
28
        }
29
    }
30
31
    /**
32
     * Debug mode. Catch the crash reports.
33
     *
34
     * @param int $admin_id (optional) The admin chat id.
35
     * @return void
36
     */
37
    public static function setDebugMode(int $admin_id = -1): void
38
    {
39
        error_reporting(E_ALL);
40
        ini_set('display_errors', '1');
41
42
        defined('DEBUG_MODE') or define('DEBUG_MODE', true);
43
        if ($admin_id !== -1) {
44
            Telegram::setAdminId($admin_id);
45
        }
46
47
        set_exception_handler(function (\Throwable $throwable) {
48
            if (!defined('DEBUG_MODE') && !DEBUG_MODE) {
49
                throw new \RuntimeException(
50
                    $throwable->getMessage(),
51
                    $throwable->getCode(),
52
                    $throwable->getPrevious()
53
                );
54
            } else {
55
                if (Telegram::getAdminId() !== -1) {
56
                    $input = getenv('TG_CURRENT_UPDATE') ?? Telegram::getInput();
57
                    $update = Telegram::processUpdate($input, Telegram::getApiToken());
0 ignored issues
show
Bug introduced by
It seems like $input can also be of type null; however, parameter $input of TelegramBot\Telegram::processUpdate() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

57
                    $update = Telegram::processUpdate(/** @scrutinizer ignore-type */ $input, Telegram::getApiToken());
Loading history...
Bug introduced by
It seems like TelegramBot\Telegram::getApiToken() can also be of type false; however, parameter $apiKey of TelegramBot\Telegram::processUpdate() does only seem to accept null|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

57
                    $update = Telegram::processUpdate($input, /** @scrutinizer ignore-type */ Telegram::getApiToken());
Loading history...
58
                    $exception = new \Exception($throwable->getMessage(), $throwable->getCode(), $throwable->getPrevious());
59
                    CrashPad::sendCrash(Telegram::getAdminId(), $exception, json_encode($update));
60
                    CrashPad::report($exception);
61
                }
62
            }
63
        });
64
    }
65
66
    /**
67
     * Send crash message and log
68
     *
69
     * @param int $chat_id The chat id of the group to send the message to.
70
     * @param \Exception $exception The exception to report.
71
     * @param string|null $update (Optional) The update that caused the exception.
72
     *
73
     * @retrun bool
74
     */
75
    public static function sendCrash(int $chat_id, \Exception $exception, string|null $update = null): bool
76
    {
77
        if ($chat_id === -1) {
78
            throw new \RuntimeException(sprintf(
79
                'The given `chat_id` is not valid. given: %s',
80
                $chat_id
81
            ));
82
        }
83
84
        if (!Telegram::validateToken($_ENV['TELEGRAM_BOT_TOKEN'] ?? '')) {
85
            (new Dotenv())->load(Telegram::getEnvFilePath());
86
            Telegram::setToken($_ENV['TELEGRAM_BOT_TOKEN']);
87
        }
88
89
        $text = Request::sendMessage([
90
            'chat_id' => $chat_id,
91
            'parse_mode' => 'HTML',
92
            'text' => ($message = sprintf(
93
                "<b>Message</b>: %s\n\n<b>File</b>: %s(%d)\n\n<b>Trace</b>: \n%s",
94
                $exception->getMessage(),
95
                $exception->getFile(),
96
                $exception->getLine(),
97
                $exception->getTraceAsString()
98
            )),
99
        ]);
100
101
        if ($update !== null) {
102
            $document = Request::sendDocument([
103
                'chat_id' => $chat_id,
104
                'document' => self::createCrashFile(
105
                    $message . "\n\n" . $update
106
                ),
107
            ]);
108
            return $text->isOk() && $document->isOk();
109
        }
110
111
        return $text->isOk();
112
    }
113
114
    /**
115
     * Create a log file for the error.
116
     *
117
     * @param string $content The content of the log file.
118
     * @retrun string The path of the log file.
119
     */
120
    private static function createCrashFile(string $content): string
121
    {
122
        $base_path = $_SERVER['DOCUMENT_ROOT'] . '.telegram-bot/';
123
        if (!file_exists($base_path)) {
124
            mkdir($base_path, 0777, true);
125
        }
126
127
        file_put_contents(($file = $base_path . uniqid('error_') . '.log'), $content);
128
        return $file;
129
    }
130
131
    /**
132
     * Report the error to the developers from the Telegram Bot API.
133
     *
134
     * @param \Exception $exception The exception to report.
135
     * @retrun void
136
     */
137
    public static function report(\Exception $exception): void
138
    {
139
        TelegramLog::error(($message = sprintf(
140
            "%s(%d): %s\n%s",
141
            $exception->getFile(),
142
            $exception->getLine(),
143
            $exception->getMessage(),
144
            $exception->getTraceAsString()
145
        )));
146
        echo '<b>TelegramError:</b> ' . $message;
147
    }
148
149
}