Skip to content

Commit

Permalink
Merge pull request #56 from ECFMP/approaching-flow-measure-messages
Browse files Browse the repository at this point in the history
feat: notified flow measure messages
  • Loading branch information
AndyTWF authored May 23, 2022
2 parents c1a5b84 + c73d922 commit 79d963b
Show file tree
Hide file tree
Showing 13 changed files with 541 additions and 11 deletions.
1 change: 1 addition & 0 deletions app/Console/Commands/SendDiscordNotifications.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public function handle(FlowMeasureDiscordMessageService $discordMessageService)
}

$this->info('Sending discord notifications');
$discordMessageService->sendMeasureNotifiedDiscordNotifications();
$discordMessageService->sendMeasureActivatedDiscordNotifications();
$discordMessageService->sendMeasureWithdrawnDiscordNotifications();
$discordMessageService->sendMeasureExpiredDiscordNotifications();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

namespace App\Discord\FlowMeasure\Message;

use App\Discord\FlowMeasure\Description\EventName;
use App\Discord\FlowMeasure\Field\ArrivalAirports;
use App\Discord\FlowMeasure\Field\DepartureAirports;
use App\Discord\FlowMeasure\Field\EndTime;
use App\Discord\FlowMeasure\Field\Filters\AdditionalFilterParser;
use App\Discord\FlowMeasure\Field\Reason;
use App\Discord\FlowMeasure\Field\Restriction;
use App\Discord\FlowMeasure\Field\StartTime;
use App\Discord\FlowMeasure\Title\IdentifierAndStatus;
use App\Discord\Message\Embed\BlankField;
use App\Discord\Message\Embed\Colour;
use App\Discord\Message\Embed\Embed;
use App\Discord\Message\Embed\EmbedCollection;
use App\Discord\Message\Embed\Field;
use App\Discord\Message\Embed\FieldProviderInterface;
use App\Discord\Message\MessageInterface;
use App\Models\FlowMeasure;

class FlowMeasureActivatedWithoutRecipientsMessage implements MessageInterface
{
private readonly FlowMeasure $measure;

public function __construct(FlowMeasure $measure)
{
$this->measure = $measure;
}

public function content(): string
{
return '';
}

public function embeds(): EmbedCollection
{
return (new EmbedCollection())->add(
Embed::make()->withColour(Colour::ACTIVATED)
->withTitle(new IdentifierAndStatus($this->measure))
->withDescription(new EventName($this->measure))
->withField(Field::makeInline(new Restriction($this->measure)))
->withField(Field::makeInline(new StartTime($this->measure)))
->withField(Field::makeInline(new EndTime($this->measure)))
->withField(Field::makeInline(new DepartureAirports($this->measure)))
->withField(Field::makeInline(new ArrivalAirports($this->measure)))
->withField(Field::makeInline(BlankField::make()))
->withFields(
AdditionalFilterParser::parseAdditionalFilters($this->measure)->map(
fn(FieldProviderInterface $provider) => Field::make($provider)
)
)
->withField(
Field::make(new Reason($this->measure))
)
);
}
}
59 changes: 59 additions & 0 deletions app/Discord/FlowMeasure/Message/FlowMeasureNotifiedMessage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

namespace App\Discord\FlowMeasure\Message;

use App\Discord\FlowMeasure\Description\EventNameAndInterestedParties;
use App\Discord\FlowMeasure\Field\ArrivalAirports;
use App\Discord\FlowMeasure\Field\DepartureAirports;
use App\Discord\FlowMeasure\Field\EndTime;
use App\Discord\FlowMeasure\Field\Filters\AdditionalFilterParser;
use App\Discord\FlowMeasure\Field\Reason;
use App\Discord\FlowMeasure\Field\Restriction;
use App\Discord\FlowMeasure\Field\StartTime;
use App\Discord\FlowMeasure\Title\IdentifierAndStatus;
use App\Discord\Message\Embed\BlankField;
use App\Discord\Message\Embed\Colour;
use App\Discord\Message\Embed\Embed;
use App\Discord\Message\Embed\EmbedCollection;
use App\Discord\Message\Embed\Field;
use App\Discord\Message\Embed\FieldProviderInterface;
use App\Discord\Message\MessageInterface;
use App\Models\FlowMeasure;

class FlowMeasureNotifiedMessage implements MessageInterface
{
private readonly FlowMeasure $measure;

public function __construct(FlowMeasure $measure)
{
$this->measure = $measure;
}

public function content(): string
{
return '';
}

public function embeds(): EmbedCollection
{
return (new EmbedCollection())->add(
Embed::make()->withColour(Colour::NOTIFIED)
->withTitle(new IdentifierAndStatus($this->measure))
->withDescription(new EventNameAndInterestedParties($this->measure))
->withField(Field::makeInline(new Restriction($this->measure)))
->withField(Field::makeInline(new StartTime($this->measure)))
->withField(Field::makeInline(new EndTime($this->measure)))
->withField(Field::makeInline(new DepartureAirports($this->measure)))
->withField(Field::makeInline(new ArrivalAirports($this->measure)))
->withField(Field::makeInline(BlankField::make()))
->withFields(
AdditionalFilterParser::parseAdditionalFilters($this->measure)->map(
fn(FieldProviderInterface $provider) => Field::make($provider)
)
)
->withField(
Field::make(new Reason($this->measure))
)
);
}
}
2 changes: 1 addition & 1 deletion app/Discord/FlowMeasure/Title/IdentifierAndStatus.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ private function status(): string
}

if ($this->flowMeasure->start_time > Carbon::now()) {
return 'Approaching';
return 'Notified';
}

return $this->flowMeasure->end_time > Carbon::now()
Expand Down
2 changes: 1 addition & 1 deletion app/Discord/Message/Embed/Colour.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

enum Colour: int
{
case UPCOMING = 16763904;
case NOTIFIED = 16763904;
case ACTIVATED = 52326;
case WITHDRAWN = 13369344;
}
1 change: 1 addition & 0 deletions app/Enums/DiscordNotificationType.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

enum DiscordNotificationType: string
{
case FLOW_MEASURE_NOTIFIED = 'flow_measure_notified';
case FLOW_MEASURE_ACTIVATED = 'flow_measure_activated';
case FLOW_MEASURE_WITHDRAWN = 'flow_measure_withdrawn';
case FLOW_MEASURE_EXPIRED = 'flow_measure_expired';
Expand Down
5 changes: 5 additions & 0 deletions app/Models/DiscordNotification.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,9 @@ public function scopeType(Builder $query, DiscordNotificationType $type): Builde
{
return $query->where('type', $type);
}

public function scopeTypes(Builder $query, array $types): Builder
{
return $query->whereIn('type', $types);
}
}
47 changes: 40 additions & 7 deletions app/Service/FlowMeasureDiscordMessageService.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@

use App\Discord\DiscordInterface;
use App\Discord\FlowMeasure\Message\FlowMeasureActivatedMessage;
use App\Discord\FlowMeasure\Message\FlowMeasureActivatedWithoutRecipientsMessage;
use App\Discord\FlowMeasure\Message\FlowMeasureNotifiedMessage;
use App\Discord\FlowMeasure\Message\FlowMeasureExpiredMessage;
use App\Discord\FlowMeasure\Message\FlowMeasureWithdrawnMessage;
use App\Discord\Message\MessageInterface;
use App\Enums\DiscordNotificationType;
use App\Models\DiscordNotification;
use App\Models\FlowMeasure;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use JetBrains\PhpStorm\NoReturn;

Expand All @@ -21,22 +25,53 @@ public function __construct(DiscordInterface $discord)
$this->discord = $discord;
}

public function sendMeasureActivatedDiscordNotifications(): void
public function sendMeasureNotifiedDiscordNotifications(): void
{
FlowMeasure::whereDoesntHave('discordNotifications', function (Builder $notification) {
$notification->type(DiscordNotificationType::FLOW_MEASURE_ACTIVATED);
$notification->types(
[DiscordNotificationType::FLOW_MEASURE_ACTIVATED, DiscordNotificationType::FLOW_MEASURE_NOTIFIED]
);
})
->where('start_time', '<', Carbon::now()->addDay())
->where('start_time', '>', Carbon::now())
->get()
->each(function (FlowMeasure $flowMeasure) {
$this->sendDiscordNotification(
$flowMeasure,
DiscordNotificationType::FLOW_MEASURE_NOTIFIED,
new FlowMeasureNotifiedMessage($flowMeasure)
);
});
}

public function sendMeasureActivatedDiscordNotifications(): void
{
FlowMeasure::with('discordNotifications')
->whereDoesntHave('discordNotifications', function (Builder $notification) {
$notification->type(DiscordNotificationType::FLOW_MEASURE_ACTIVATED);
})
->active()
->get()
->each(function (FlowMeasure $flowMeasure) {
$this->sendDiscordNotification(
$flowMeasure,
DiscordNotificationType::FLOW_MEASURE_ACTIVATED,
new FlowMeasureActivatedMessage($flowMeasure)
$this->notifiedMessageSentWithinTheLastHour($flowMeasure)
? new FlowMeasureActivatedWithoutRecipientsMessage($flowMeasure)
: new FlowMeasureActivatedMessage($flowMeasure)
);
});
}

private function notifiedMessageSentWithinTheLastHour(FlowMeasure $measure): bool
{
return $measure->discordNotifications->firstWhere(
fn(DiscordNotification $notification
) => $notification->type === DiscordNotificationType::FLOW_MEASURE_NOTIFIED &&
$notification->created_at > Carbon::now()->subHour()
) !== null;
}

public function sendMeasureWithdrawnDiscordNotifications(): void
{
FlowMeasure::whereHas('discordNotifications', function (Builder $notification) {
Expand All @@ -61,10 +96,8 @@ public function sendMeasureExpiredDiscordNotifications(): void
FlowMeasure::whereHas('discordNotifications', function (Builder $notification) {
$notification->type(DiscordNotificationType::FLOW_MEASURE_ACTIVATED);
})->whereDoesntHave('discordNotifications', function (Builder $notification) {
$notification->type(DiscordNotificationType::FLOW_MEASURE_WITHDRAWN)->orWhere(
function (Builder $notification) {
$notification->type(DiscordNotificationType::FLOW_MEASURE_EXPIRED);
}
$notification->types(
[DiscordNotificationType::FLOW_MEASURE_WITHDRAWN, DiscordNotificationType::FLOW_MEASURE_EXPIRED]
);
})
->withTrashed()
Expand Down
2 changes: 2 additions & 0 deletions tests/Console/Commands/SendDiscordNotificationsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public function testItRunsNotificationSending()
Config::set('discord.enabled', true);

$serviceMock = Mockery::mock(FlowMeasureDiscordMessageService::class);
$serviceMock->shouldReceive('sendMeasureNotifiedDiscordNotifications')->once();
$serviceMock->shouldReceive('sendMeasureActivatedDiscordNotifications')->once();
$serviceMock->shouldReceive('sendMeasureWithdrawnDiscordNotifications')->once();
$serviceMock->shouldReceive('sendMeasureExpiredDiscordNotifications')->once();
Expand All @@ -28,6 +29,7 @@ public function testItDoesntRunsNotificationSendingIfSwitchedOff()
Config::set('discord.enabled', false);

$serviceMock = Mockery::mock(FlowMeasureDiscordMessageService::class);
$serviceMock->shouldNotReceive('sendMeasureNotifiedDiscordNotifications');
$serviceMock->shouldNotReceive('sendMeasureActivatedDiscordNotifications');
$serviceMock->shouldNotReceive('sendMeasureWithdrawnDiscordNotifications');
$serviceMock->shouldNotReceive('sendMeasureExpiredDiscordNotifications');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

namespace Tests\Discord\FlowMeasure\Message;

use App\Discord\FlowMeasure\Message\FlowMeasureActivatedWithoutRecipientsMessage;
use App\Discord\Message\Embed\Colour;
use App\Models\DiscordTag;
use App\Models\FlightInformationRegion;
use App\Models\FlowMeasure;
use Carbon\Carbon;
use Tests\TestCase;

class FlowMeasureActivatedWithoutRecipientsMessageTest extends TestCase
{
public function setUp(): void
{
parent::setUp();
Carbon::setTestNow(Carbon::parse('2022-05-22T14:59:23Z'));
}

public function testItHasNoContent()
{
$measure = FlowMeasure::factory()->create();

$this->assertEquals(
'',
(new FlowMeasureActivatedWithoutRecipientsMessage($measure))->content()
);
}

public function testItHasEmbeds()
{
$measure = FlowMeasure::factory()
->withTimes(Carbon::parse('2022-05-22T14:54:23Z'), Carbon::parse('2022-05-22T16:37:22Z'))
->withEvent()
->withAdditionalFilter(['type' => 'level_below', 'value' => 220])->create();

$fir = FlightInformationRegion::factory()->has(DiscordTag::factory()->count(2))->create();
$measure->notifiedFlightInformationRegions()->sync([$fir->id]);

$this->assertEquals(
[
[
'title' => $measure->identifier . ' - ' . 'Active',
'color' => Colour::ACTIVATED->value,
'description' => $measure->event->name,
'fields' => [
[
'name' => 'Minimum Departure Interval [MDI]',
'value' => '2 Minutes',
'inline' => true,
],
[
'name' => 'Start Time',
'value' => '22/05 1454Z',
'inline' => true,
],
[
'name' => 'End Time',
'value' => '1637Z',
'inline' => true,
],
[
'name' => 'Departure Airports',
'value' => 'EG**',
'inline' => true,
],
[
'name' => 'Arrival Airports',
'value' => 'EHAM',
'inline' => true,
],
[
'name' => "\u{200b}",
'value' => "\u{200b}",
'inline' => true,
],
[
'name' => 'Level at or Below',
'value' => '220',
'inline' => false,
],
[
'name' => 'Reason',
'value' => $measure->reason,
'inline' => false,
],
],
],
],
(new FlowMeasureActivatedWithoutRecipientsMessage($measure))->embeds()->toArray()
);
}
}
Loading

0 comments on commit 79d963b

Please sign in to comment.