Failed Conditions
Pull Request — master (#201)
by Michael
07:07 queued 03:24
created

IrcNotificationHelper::requestUnreserved()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
1
<?php
2
/******************************************************************************
3
 * Wikipedia Account Creation Assistance tool                                 *
4
 * ACC Development Team. Please see team.json for a list of contributors.     *
5
 *                                                                            *
6
 * This is free and unencumbered software released into the public domain.    *
7
 * Please see LICENSE.md for the full licencing statement.                    *
8
 ******************************************************************************/
9
10
namespace Waca\Helpers;
11
12
use Exception;
13
use PhpAmqpLib\Connection\AMQPConnectionConfig;
14
use PhpAmqpLib\Connection\AMQPConnectionFactory;
15
use PhpAmqpLib\Message\AMQPMessage;
16
use Waca\DataObjects\Ban;
17
use Waca\DataObjects\Comment;
18
use Waca\DataObjects\Domain;
19
use Waca\DataObjects\EmailTemplate;
20
use Waca\DataObjects\Request;
21
use Waca\DataObjects\RequestQueue;
22
use Waca\DataObjects\User;
23
use Waca\DataObjects\WelcomeTemplate;
24
use Waca\ExceptionHandler;
25
use Waca\IrcColourCode;
26
use Waca\PdoDatabase;
27
use Waca\SiteConfiguration;
28
29
/**
30
 * Class IrcNotificationHelper
31
 * @package Waca\Helpers
32
 */
33
class IrcNotificationHelper
34
{
35
    /** @var bool $notificationsEnabled */
36
    private $notificationsEnabled;
37
    /** @var User $currentUser */
38
    private $currentUser;
39
    /** @var string $instanceName */
40
    private $instanceName;
41
    /** @var string */
42
    private $baseUrl;
43
    /** @var SiteConfiguration */
44
    private $siteConfiguration;
45
    /** @var PdoDatabase */
46
    private $primaryDatabase;
47
48
    /**
49
     * IrcNotificationHelper constructor.
50
     *
51
     * @param SiteConfiguration $siteConfiguration
52
     * @param PdoDatabase       $primaryDatabase
53
     */
54
    public function __construct(
55
        SiteConfiguration $siteConfiguration,
56
        PdoDatabase $primaryDatabase
57
    ) {
58
        $this->siteConfiguration = $siteConfiguration;
59
        $this->primaryDatabase = $primaryDatabase;
60
61
        $this->notificationsEnabled = $siteConfiguration->getIrcNotificationsEnabled();
62
        $this->instanceName = $siteConfiguration->getIrcNotificationsInstance();
63
        $this->baseUrl = $siteConfiguration->getBaseUrl();
64
65
        $this->currentUser = User::getCurrent($primaryDatabase);
66
    }
67
68
    /**
69
     * Send a notification
70
     *
71
     * This method does some *basic* filtering for IRC safety, and then delivers the message to an AMQP queue manager.
72
     * It is the responsibility of the queue manager and consumer to handle message delivery to IRC, message routing to
73
     * the correct channel, and message expiry.
74
     *
75
     * It's also arguably the responsibility of the consumer to ensure the message is *safe* for delivery to IRC.
76
     *
77
     * As of Feb 2022, the message consumer is stwalkerster's IRC bot Helpmebot.
78
     *
79
     * @param string $message The text to send
80
     */
81
    protected function send($message)
82
    {
83
        $instanceName = $this->instanceName;
84
85
        if (!$this->notificationsEnabled) {
86
            return;
87
        }
88
89
        $blacklist = array("DCC", "CCTP", "PRIVMSG");
90
        $message = str_replace($blacklist, "(IRC Blacklist)", $message); // Lets stop DCC etc
91
92
        $msg = $message;
93
        if ($instanceName !== null && mb_strlen($instanceName) > 0) {
94
            $msg = IrcColourCode::RESET . IrcColourCode::BOLD . "[$instanceName]" . IrcColourCode::RESET . ": $message";
95
        }
96
97
        // FIXME: domains!
98
        /** @var Domain $domain */
99
        $domain = Domain::getById(1, $this->primaryDatabase);
100
101
        try {
102
            $amqpSiteConfig = $this->siteConfiguration->getamqpSiteConfiguration();
0 ignored issues
show
Bug introduced by
The method getamqpSiteConfiguration() does not exist on Waca\SiteConfiguration. ( Ignorable by Annotation )

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

102
            /** @scrutinizer ignore-call */ 
103
            $amqpSiteConfig = $this->siteConfiguration->getamqpSiteConfiguration();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
103
104
            $amqpConnectionConfig = new AMQPConnectionConfig();
105
            $amqpConnectionConfig->setHost($amqpSiteConfig['host']);
106
            $amqpConnectionConfig->setPort($amqpSiteConfig['port']);
107
            $amqpConnectionConfig->setUser($amqpSiteConfig['user']);
108
            $amqpConnectionConfig->setPassword($amqpSiteConfig['password']);
109
            $amqpConnectionConfig->setVhost($amqpSiteConfig['vhost']);
110
111
            if ($amqpSiteConfig['tls']) {
112
                $amqpConnectionConfig->setIsSecure(true);
113
                $amqpConnectionConfig->setSslVerify(true);
114
            }
115
            else {
116
                $amqpConnectionConfig->setIsSecure(false);
117
            }
118
            $connection = AMQPConnectionFactory::create($amqpConnectionConfig);
119
120
            $channel = $connection->channel();
121
122
            $msg = new AMQPMessage(substr($msg, 0, 512));
123
            $msg->set('user_id', $amqpSiteConfig['user']);
124
            $msg->set('app_id', $this->siteConfiguration->getUserAgent());
125
            $msg->set('content_type', 'text/plain');
126
            $channel->basic_publish($msg, $amqpSiteConfig['exchange'], $domain->getNotificationTarget());
127
            $channel->close();
128
        }
129
        catch (Exception $ex) {
130
            // OK, so we failed to send the notification - that db might be down?
131
            // This is non-critical, so silently fail.
132
            ExceptionHandler::logExceptionToDisk($ex, $this->siteConfiguration);
133
134
            // Disable notifications for remainder of request.
135
            $this->notificationsEnabled = false;
136
        }
137
    }
138
139
    #region user management
140
141
    /**
142
     * send a new user notification
143
     *
144
     * @param User $user
145
     */
146
    public function userNew(User $user)
147
    {
148
        $this->send("New user: {$user->getUsername()}");
149
    }
150
151
    /**
152
     * send an approved notification
153
     *
154
     * @param User $user
155
     */
156
    public function userApproved(User $user)
157
    {
158
        $this->send("{$user->getUsername()} approved by " . $this->currentUser->getUsername());
159
    }
160
161
    /**
162
     * send a declined notification
163
     *
164
     * @param User   $user
165
     * @param string $reason the reason the user was declined
166
     */
167
    public function userDeclined(User $user, $reason)
168
    {
169
        $this->send("{$user->getUsername()} declined by " . $this->currentUser->getUsername() . " ($reason)");
170
    }
171
172
    /**
173
     * send a suspended notification
174
     *
175
     * @param User   $user
176
     * @param string $reason The reason the user has been suspended
177
     */
178
    public function userSuspended(User $user, $reason)
179
    {
180
        $this->send("{$user->getUsername()} suspended by " . $this->currentUser->getUsername() . " ($reason)");
181
    }
182
183
    /**
184
     * Send a preference change notification
185
     *
186
     * @param User $user
187
     */
188
    public function userPrefChange(User $user)
189
    {
190
        $this->send("{$user->getUsername()}'s preferences were changed by " . $this->currentUser->getUsername());
191
    }
192
193
    /**
194
     * Send a user renamed notification
195
     *
196
     * @param User   $user
197
     * @param string $old
198
     */
199
    public function userRenamed(User $user, $old)
200
    {
201
        $this->send($this->currentUser->getUsername() . " renamed $old to {$user->getUsername()}");
202
    }
203
204
    /**
205
     * @param User   $user
206
     * @param string $reason
207
     */
208
    public function userRolesEdited(User $user, $reason)
209
    {
210
        $currentUser = $this->currentUser->getUsername();
211
        $this->send("Active roles for {$user->getUsername()} changed by " . $currentUser . " ($reason)");
212
    }
213
214
    #endregion
215
216
    #region Site Notice
217
218
    /**
219
     * Summary of siteNoticeEdited
220
     */
221
    public function siteNoticeEdited()
222
    {
223
        $this->send("Site notice edited by " . $this->currentUser->getUsername());
224
    }
225
    #endregion
226
227
    #region Welcome Templates
228
    /**
229
     * Summary of welcomeTemplateCreated
230
     *
231
     * @param WelcomeTemplate $template
232
     */
233
    public function welcomeTemplateCreated(WelcomeTemplate $template)
234
    {
235
        $this->send("Welcome template {$template->getId()} created by " . $this->currentUser->getUsername());
236
    }
237
238
    /**
239
     * Summary of welcomeTemplateDeleted
240
     *
241
     * @param int $templateid
242
     */
243
    public function welcomeTemplateDeleted($templateid)
244
    {
245
        $this->send("Welcome template {$templateid} deleted by " . $this->currentUser->getUsername());
246
    }
247
248
    /**
249
     * Summary of welcomeTemplateEdited
250
     *
251
     * @param WelcomeTemplate $template
252
     */
253
    public function welcomeTemplateEdited(WelcomeTemplate $template)
254
    {
255
        $this->send("Welcome template {$template->getId()} edited by " . $this->currentUser->getUsername());
256
    }
257
258
    #endregion
259
260
    #region bans
261
    /**
262
     * Summary of banned
263
     *
264
     * @param Ban $ban
265
     */
266
    public function banned(Ban $ban)
267
    {
268
        if ($ban->getDuration() === null) {
269
            $duration = "indefinitely";
270
        }
271
        else {
272
            $duration = "until " . date("F j, Y, g:i a", $ban->getDuration());
273
        }
274
275
        $username = $this->currentUser->getUsername();
276
277
        if ($ban->getVisibility() == 'user') {
278
            $this->send("Ban {$ban->getId()} set by {$username} for '{$ban->getReason()}' {$duration}");
279
        }
280
        else {
281
            $this->send("Ban {$ban->getId()} set by {$username} {$duration}");
282
        }
283
    }
284
285
    /**
286
     * Summary of unbanned
287
     *
288
     * @param Ban    $ban
289
     * @param string $unbanReason
290
     */
291
    public function unbanned(Ban $ban, $unbanReason)
292
    {
293
        $this->send("Ban {$ban->getId()} unbanned by " . $this->currentUser
294
                ->getUsername() . " (" . $unbanReason . ")");
295
    }
296
297
    #endregion
298
299
    #region request management
300
301
    /**
302
     * Summary of requestReceived
303
     *
304
     * @param Request $request
305
     */
306
    public function requestReceived(Request $request)
307
    {
308
        $this->send(
309
            IrcColourCode::DARK_GREY . "[["
310
            . IrcColourCode::DARK_GREEN . "acc:"
311
            . IrcColourCode::ORANGE . $request->getId()
312
            . IrcColourCode::DARK_GREY . "]]"
313
            . IrcColourCode::RED . " N "
314
            . IrcColourCode::DARK_BLUE . $this->baseUrl . "/internal.php/viewRequest?id={$request->getId()} "
315
            . IrcColourCode::DARK_RED . "* "
316
            . IrcColourCode::DARK_GREEN . $request->getName()
317
            . IrcColourCode::DARK_RED . " * "
318
            . IrcColourCode::RESET
319
        );
320
    }
321
322
    /**
323
     * Summary of requestDeferred
324
     *
325
     * @param Request $request
326
     */
327
    public function requestDeferred(Request $request)
328
    {
329
        /** @var RequestQueue $queue */
330
        $queue = RequestQueue::getById($request->getQueue(), $request->getDatabase());
331
332
        $deferTo = $queue->getDisplayName();
333
        $username = $this->currentUser->getUsername();
334
335
        $this->send("Request {$request->getId()} ({$request->getName()}) deferred to {$deferTo} by {$username}");
336
    }
337
338
    /**
339
     *
340
     * Summary of requestDeferredWithMail
341
     *
342
     * @param Request $request
343
     */
344
    public function requestDeferredWithMail(Request $request)
345
    {
346
        /** @var RequestQueue $queue */
347
        $queue = RequestQueue::getById($request->getQueue(), $request->getDatabase());
348
349
        $deferTo = $queue->getDisplayName();
350
        $username = $this->currentUser->getUsername();
351
        $id = $request->getId();
352
        $name = $request->getName();
353
354
        $this->send("Request {$id} ({$name}) deferred to {$deferTo} with an email by {$username}");
355
    }
356
357
    /**
358
     * Summary of requestClosed
359
     *
360
     * @param Request $request
361
     * @param string  $closetype
362
     */
363
    public function requestClosed(Request $request, $closetype)
364
    {
365
        $username = $this->currentUser->getUsername();
366
367
        $this->send("Request {$request->getId()} ({$request->getName()}) closed ($closetype) by {$username}");
368
    }
369
370
    /**
371
     * Summary of requestClosed
372
     *
373
     * @param Request $request
374
     * @param string  $closetype
375
     */
376
    public function requestCloseQueued(Request $request, $closetype)
377
    {
378
        $username = $this->currentUser->getUsername();
379
380
        $this->send("Request {$request->getId()} ({$request->getName()}) queued for creation ($closetype) by {$username}");
381
    }
382
383
    /**
384
     * Summary of requestClosed
385
     *
386
     * @param Request $request
387
     * @param User    $triggerUser
388
     */
389
    public function requestCreationFailed(Request $request, User $triggerUser)
390
    {
391
        $this->send("Request {$request->getId()} ({$request->getName()}) failed auto-creation for {$triggerUser->getUsername()}, and was sent to the hospital queue.");
392
    }
393
394
    /**
395
     * @param Request $request
396
     * @param User    $triggerUser
397
     */
398
    public function requestWelcomeFailed(Request $request, User $triggerUser)
399
    {
400
        $this->send("Request {$request->getId()} ({$request->getName()}) failed welcome for {$triggerUser->getUsername()}.");
401
    }
402
403
    /**
404
     * Summary of sentMail
405
     *
406
     * @param Request $request
407
     */
408
    public function sentMail(Request $request)
409
    {
410
        $this->send($this->currentUser->getUsername()
411
            . " sent an email related to Request {$request->getId()} ({$request->getName()})");
412
    }
413
414
    #endregion
415
416
    #region reservations
417
418
    /**
419
     * Summary of requestReserved
420
     *
421
     * @param Request $request
422
     */
423
    public function requestReserved(Request $request)
424
    {
425
        $username = $this->currentUser->getUsername();
426
427
        $this->send("Request {$request->getId()} ({$request->getName()}) reserved by {$username}");
428
    }
429
430
    /**
431
     * Summary of requestReserveBroken
432
     *
433
     * @param Request $request
434
     */
435
    public function requestReserveBroken(Request $request)
436
    {
437
        $username = $this->currentUser->getUsername();
438
439
        $this->send("Reservation on request {$request->getId()} ({$request->getName()}) broken by {$username}");
440
    }
441
442
    /**
443
     * Summary of requestUnreserved
444
     *
445
     * @param Request $request
446
     */
447
    public function requestUnreserved(Request $request)
448
    {
449
        $this->send("Request {$request->getId()} ({$request->getName()}) is no longer being handled.");
450
    }
451
452
    /**
453
     * Summary of requestReservationSent
454
     *
455
     * @param Request $request
456
     * @param User    $target
457
     */
458
    public function requestReservationSent(Request $request, User $target)
459
    {
460
        $username = $this->currentUser->getUsername();
461
462
        $this->send(
463
            "Reservation of request {$request->getId()} ({$request->getName()}) sent to {$target->getUsername()} by "
464
            . $username);
465
    }
466
467
    #endregion
468
469
    #region comments
470
471
    /**
472
     * Summary of commentCreated
473
     *
474
     * @param Comment $comment
475
     * @param Request $request
476
     */
477
    public function commentCreated(Comment $comment, Request $request)
478
    {
479
        $username = $this->currentUser->getUsername();
480
        switch ($comment->getVisibility()) {
481
            case 'admin':
482
                $visibility = " with visibility 'admin'";
483
                break;
484
            case 'checkuser':
485
                $visibility = " with visibility 'checkuser'";
486
                break;
487
            default:
488
                $visibility = "";
489
                break;
490
        }
491
492
        $this->send("{$username} posted a comment on request {$request->getId()} ({$request->getName()}){$visibility}");
493
    }
494
495
    /**
496
     * Summary of commentEdited
497
     *
498
     * @param Comment $comment
499
     * @param Request $request
500
     */
501
    public function commentEdited(Comment $comment, Request $request)
502
    {
503
        $username = $this->currentUser->getUsername();
504
505
        $this->send(<<<TAG
506
Comment {$comment->getId()} on request {$request->getId()} ({$request->getName()}) edited by {$username}
507
TAG
508
        );
509
    }
510
511
    public function alertFlaggedComments(int $count)
512
    {
513
        $this->send("There are ${count} flagged comments on closed requests currently awaiting redaction.");
514
    }
515
516
    #endregion
517
518
    #region email management (close reasons)
519
520
    /**
521
     * Summary of emailCreated
522
     *
523
     * @param EmailTemplate $template
524
     */
525
    public function emailCreated(EmailTemplate $template)
526
    {
527
        $username = $this->currentUser->getUsername();
528
        $this->send("Email {$template->getId()} ({$template->getName()}) created by " . $username);
529
    }
530
531
    /**
532
     * Summary of emailEdited
533
     *
534
     * @param EmailTemplate $template
535
     */
536
    public function emailEdited(EmailTemplate $template)
537
    {
538
        $username = $this->currentUser->getUsername();
539
        $this->send("Email {$template->getId()} ({$template->getName()}) edited by " . $username);
540
    }
541
    #endregion
542
}
543