Passed
Push — main ( 1a1ee7...5cb4cc )
by Tan
25:44 queued 13:14
created

Notification::sendTelegramRequest()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 10
dl 0
loc 14
rs 9.9332
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace CSlant\TelegramGitNotifier\Structures;
6
7
use CSlant\TelegramGitNotifier\Constants\EventConstant;
8
use CSlant\TelegramGitNotifier\Exceptions\MessageIsEmptyException;
9
use CSlant\TelegramGitNotifier\Exceptions\SendNotificationException;
10
use GuzzleHttp\Exception\GuzzleException;
11
use JsonException;
12
use RuntimeException;
13
use Symfony\Component\HttpFoundation\Request;
14
15
/**
16
 * Trait Notification
17
 * 
18
 * Handles notification-related functionality including message formatting
19
 * and sending notifications to Telegram.
20
 */
21
trait Notification
22
{
23
    /** @var object The payload received from the webhook */
24
    public object $payload;
25
26
    /** @var string The formatted message to be sent */
27
    public string $message = '';
28
29
    /**
30
     * Send an access denied message to the chat
31
     *
32
     * @param string|null $chatId The chat ID to send the message to
33
     * @param string|null $viewTemplate Custom view template to use
34
     * @throws SendNotificationException If the message cannot be sent
35
     */
36
    public function accessDenied(
37
        ?string $chatId = null,
38
        ?string $viewTemplate = null
39
    ): void {
40
        try {
41
            $template = $viewTemplate ?? config('telegram-git-notifier.view.globals.access_denied');
42
            $message = tgn_view($template, ['chatId' => $chatId]);
43
44
            if (empty($message)) {
45
                throw new MessageIsEmptyException('Access denied message template is empty');
46
            }
47
48
            $this->telegram->sendMessage([
49
                'chat_id' => $this->chatBotId,
50
                'text' => $message,
51
                'disable_web_page_preview' => true,
52
                'parse_mode' => 'HTML',
53
            ]);
54
        } catch (\Exception $e) {
55
            throw SendNotificationException::create('Failed to send access denied message', 0, $e);
0 ignored issues
show
Unused Code introduced by
The call to CSlant\TelegramGitNotifi...tionException::create() has too many arguments starting with 0. ( Ignorable by Annotation )

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

55
            throw SendNotificationException::/** @scrutinizer ignore-call */ create('Failed to send access denied message', 0, $e);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
56
        }
57
    }
58
59
    /**
60
     * Set the payload from the incoming request
61
     *
62
     * @param Request $request The HTTP request
63
     * @param string $event The event type
64
     * @return object The parsed payload
65
     * @throws MessageIsEmptyException If the payload is empty or invalid
66
     */
67
    public function setPayload(Request $request, string $event): object
68
    {
69
        $content = $this->extractContentFromRequest($request);
70
        
71
        if ($content === null) {
72
            throw new MessageIsEmptyException('No content found in the request');
73
        }
74
75
        try {
76
            $this->payload = json_decode($content, false, 512, JSON_THROW_ON_ERROR);
77
            $this->setMessage($event);
78
            
79
            return $this->payload;
80
        } catch (JsonException $e) {
81
            throw new MessageIsEmptyException('Invalid JSON payload: ' . $e->getMessage(), 0, $e);
82
        }
83
    }
84
85
    /**
86
     * Extract content from the request based on the platform
87
     */
88
    private function extractContentFromRequest(Request $request): ?string
89
    {
90
        if ($this->event->platform === 'gitlab') {
91
            return $request->getContent() ?: null;
92
        }
93
        
94
        if ($this->event->platform === EventConstant::DEFAULT_PLATFORM) {
95
            return $request->request->get('payload');
96
        }
97
        
98
        return null;
99
    }
100
101
    /**
102
     * Set the message from the payload using the appropriate template
103
     *
104
     * @param string $eventType The type of event
105
     * @throws MessageIsEmptyException If the message cannot be generated
106
     */
107
    private function setMessage(string $eventType): void
108
    {
109
        $event = tgn_event_name($eventType);
110
        $action = $this->getActionOfEvent($this->payload);
0 ignored issues
show
Bug introduced by
It seems like getActionOfEvent() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

110
        /** @scrutinizer ignore-call */ 
111
        $action = $this->getActionOfEvent($this->payload);
Loading history...
111
        
112
        $viewTemplate = $this->buildViewTemplate($event, $action);
113
        $viewData = [
114
            'payload' => $this->payload,
115
            'event' => tgn_convert_event_name($eventType),
116
        ];
117
118
        $viewResult = tgn_view($viewTemplate, $viewData);
119
120
        if ($viewResult === null) {
121
            throw MessageIsEmptyException::create(
122
                "Failed to generate message for event: {$eventType}"
0 ignored issues
show
Unused Code introduced by
The call to CSlant\TelegramGitNotifi...mptyException::create() has too many arguments starting with 'Failed to generate mess...for event: '.$eventType. ( Ignorable by Annotation )

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

122
            throw MessageIsEmptyException::/** @scrutinizer ignore-call */ create(

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
123
            );
124
        }
125
126
        $this->message = $viewResult;
127
    }
128
129
    /**
130
     * Build the view template path based on event and action
131
     */
132
    private function buildViewTemplate(string $event, ?string $action): string
133
    {
134
        $template = "events.{$this->event->platform}.{$event}";
135
        
136
        return $action 
137
            ? "{$template}.{$action}" 
138
            : "{$template}.default";
139
    }
140
141
    /**
142
     * Send a notification to Telegram
143
     *
144
     * @param string|null $message The message to send (uses stored message if null)
145
     * @param array<string, mixed> $options Additional options for the Telegram API
146
     * @return bool True if the notification was sent successfully
147
     * @throws SendNotificationException If the notification fails to send
148
     */
149
    public function sendNotify(?string $message = null, array $options = []): bool
150
    {
151
        $this->message = $message ?? $this->message;
152
153
        if (trim($this->message) === (config('telegram-git-notifier.view.ignore-message') ?? '')) {
154
            return false;
155
        }
156
157
        try {
158
            $queryParams = array_merge(
159
                $this->createTelegramBaseContent(),
0 ignored issues
show
Bug introduced by
It seems like createTelegramBaseContent() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

159
                $this->/** @scrutinizer ignore-call */ 
160
                       createTelegramBaseContent(),
Loading history...
160
                ['text' => $this->message],
161
                $options
162
            );
163
164
            $response = $this->sendTelegramRequest($queryParams);
165
            return $response->getStatusCode() === 200;
166
        } catch (\Exception $e) {
167
            throw new SendNotificationException(
168
                'Failed to send notification: ' . $e->getMessage(),
169
                $e->getCode(),
170
                $e
171
            );
172
        }
173
    }
174
175
    /**
176
     * Send a request to the Telegram API
177
     *
178
     * @param array<string, mixed> $queryParams The query parameters to send
179
     * @return \Psr\Http\Message\ResponseInterface The API response
180
     * @throws \RuntimeException If the request fails
181
     */
182
    private function sendTelegramRequest(array $queryParams): \Psr\Http\Message\ResponseInterface
183
    {
184
        $url = 'https://api.telegram.org/bot' . config('telegram-git-notifier.bot.token') . '/sendMessage';
185
        
186
        try {
187
            return $this->client->request('POST', $url, [
188
                'form_params' => $queryParams,
189
                'verify' => config('telegram-git-notifier.app.request_verify', true),
0 ignored issues
show
Unused Code introduced by
The call to config() has too many arguments starting with true. ( Ignorable by Annotation )

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

189
                'verify' => /** @scrutinizer ignore-call */ config('telegram-git-notifier.app.request_verify', true),

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
190
            ]);
191
        } catch (\Exception $e) {
192
            throw new \RuntimeException(
193
                'Failed to send request to Telegram API: ' . $e->getMessage(),
194
                $e->getCode(),
195
                $e
196
            );
197
        }
198
    }
199
}
200