Passed
Push — main ( aee526...df35b1 )
by Tan
13:15
created

NotificationService::handle()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 9
rs 10
c 2
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace CSlant\LaravelTelegramGitNotifier\Services;
6
7
use CSlant\TelegramGitNotifier\Exceptions\InvalidViewTemplateException;
8
use CSlant\TelegramGitNotifier\Exceptions\MessageIsEmptyException;
9
use CSlant\TelegramGitNotifier\Exceptions\SendNotificationException;
10
use CSlant\TelegramGitNotifier\Models\Setting;
11
use CSlant\TelegramGitNotifier\Notifier;
12
use CSlant\TelegramGitNotifier\Objects\Validator;
13
use Symfony\Component\HttpFoundation\Request;
14
15
class NotificationService
16
{
17
    /**
18
     * @var array<string, array<int|string>>
19
     */
20
    private array $chatIds = [];
21
22
    public function __construct(
23
        private Notifier $notifier,
24
        private Setting $setting,
25
        private Request $request
26
    ) {
27
        $this->initialize();
28
    }
29
30
    public static function create(Notifier $notifier, Setting $setting, ?Request $request = null): self
31
    {
32
        return new self(
33
            $notifier,
34
            $setting,
35
            $request ?? Request::createFromGlobals()
36
        );
37
    }
38
39
    private function initialize(): void
40
    {
41
        $this->chatIds = $this->notifier->parseNotifyChatIds();
42
    }
43
44
    /**
45
     * Handle sending notification from webhook event to Telegram.
46
     *
47
     * @throws InvalidViewTemplateException
48
     * @throws SendNotificationException
49
     * @throws MessageIsEmptyException
50
     */
51
    public function handle(): void
52
    {
53
        $eventName = $this->notifier->handleEventFromRequest($this->request);
54
55
        if ($eventName === null) {
56
            return;
57
        }
58
59
        $this->sendNotification($eventName);
60
    }
61
62
    /**
63
     * Send notification to all configured chat IDs and threads.
64
     *
65
     * @throws InvalidViewTemplateException
66
     * @throws SendNotificationException
67
     * @throws MessageIsEmptyException
68
     */
69
    private function sendNotification(string $event): void
70
    {
71
        if (!$this->isValidEvent($event)) {
72
            return;
73
        }
74
75
        foreach ($this->chatIds as $chatId => $threads) {
76
            if (empty($chatId)) {
77
                continue;
78
            }
79
80
            $this->sendToRecipients((string) $chatId, $threads);
81
        }
82
    }
83
84
    /**
85
     * Send notification to appropriate recipients (chat or threads).
86
     *
87
     * @param string $chatId The chat ID to send to
88
     * @param array<int|string> $threads Array of thread IDs (empty for direct chat)
89
     * @throws SendNotificationException
90
     */
91
    private function sendToRecipients(string $chatId, array $threads): void
92
    {
93
        if (empty($threads)) {
94
            $this->sendToChat($chatId);
95
96
            return;
97
        }
98
99
        $this->sendToThreads($chatId, $threads);
100
    }
101
102
    /**
103
     * Send notification to a single chat.
104
     *
105
     * @throws SendNotificationException
106
     */
107
    private function sendToChat(string $chatId): void
108
    {
109
        $this->notifier->sendNotify(null, [
110
            'chat_id' => $chatId,
111
        ]);
112
    }
113
114
    /**
115
     * Send notification to multiple threads in a chat.
116
     *
117
     * @param string $chatId The chat ID containing the threads
118
     * @param array<int|string> $threads Array of thread IDs
119
     * @throws SendNotificationException
120
     */
121
    private function sendToThreads(string $chatId, array $threads): void
122
    {
123
        foreach ($threads as $threadId) {
124
            $this->sendToThread($chatId, (string) $threadId);
125
        }
126
    }
127
128
    /**
129
     * Send notification to a specific thread in a chat.
130
     *
131
     * @param string $chatId The chat ID
132
     * @param string $threadId The thread ID
133
     * @throws SendNotificationException
134
     */
135
    private function sendToThread(string $chatId, string $threadId): void
136
    {
137
        $this->notifier->sendNotify(null, [
138
            'chat_id' => $chatId,
139
            'message_thread_id' => $threadId,
140
        ]);
141
    }
142
143
    /**
144
     * Check if the event is valid and accessible.
145
     */
146
    private function isValidEvent(string $event): bool
147
    {
148
        $payload = $this->notifier->setPayload($this->request, $event);
149
150
        if (empty($payload) || !is_object($payload)) {
151
            return false;
152
        }
153
154
        return $this->validateEventAccess($event, $payload);
155
    }
156
157
    /**
158
     * Validate if the event has access.
159
     *
160
     * @param string $event The event name
161
     * @param object $payload The event payload
162
     */
163
    private function validateEventAccess(string $event, object $payload): bool
164
    {
165
        $validator = new Validator($this->setting, $this->notifier->event);
166
167
        return $validator->isAccessEvent(
168
            $this->notifier->event->platform,
169
            $event,
170
            $payload
171
        );
172
    }
173
}
174