* Discord notifications for events #433 * Style fixes * Check for blank webhook urls and disable * Cleanup items after review * Changes and fixes * Style fixes * Don't load env for testing * Fix status text * Refactor saving fields/fares so events get the latest data * Cleanup * Style fixes
This commit is contained in:
@@ -2,7 +2,7 @@ FROM php:7.4-fpm-alpine
|
||||
|
||||
WORKDIR /var/www/
|
||||
|
||||
RUN apk add gmp-dev icu-dev
|
||||
RUN apk add gmp-dev icu-dev zlib-dev libpng-dev
|
||||
RUN curl --silent --show-error https://getcomposer.org/installer | php
|
||||
|
||||
# Copy any config files in
|
||||
|
||||
@@ -17,8 +17,8 @@ class EmailTest extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
/** @var App\Notifications\EventHandler $eventHandler */
|
||||
$eventHandler = app(App\Notifications\EventHandler::class);
|
||||
/** @var App\Notifications\NotificationEventsHandler $eventHandler */
|
||||
$eventHandler = app(App\Notifications\NotificationEventsHandler::class);
|
||||
|
||||
$news = new App\Models\News();
|
||||
$news->user_id = 1;
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
namespace App\Contracts;
|
||||
|
||||
use App\Notifications\Channels\Discord\DiscordMessage;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class Notification extends \Illuminate\Notifications\Notification implements ShouldQueue
|
||||
{
|
||||
@@ -17,14 +17,14 @@ class Notification extends \Illuminate\Notifications\Notification implements Sho
|
||||
{
|
||||
// Look in the notifications.channels config and see where this particular
|
||||
// notification can go. Map it to $channels
|
||||
$klass = static::class;
|
||||
/*$klass = static::class;
|
||||
$notif_config = config('notifications.channels', []);
|
||||
if (!array_key_exists($klass, $notif_config)) {
|
||||
Log::error('Notification type '.$klass.' missing from notifications config, defaulting to mail');
|
||||
return;
|
||||
}
|
||||
|
||||
$this->channels = $notif_config[$klass];
|
||||
$this->channels = $notif_config[$klass];*/
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -34,8 +34,16 @@ class Notification extends \Illuminate\Notifications\Notification implements Sho
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function via($notifiable)
|
||||
/*public function via($notifiable)
|
||||
{
|
||||
return $this->channels;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* @return DiscordMessage|null
|
||||
*/
|
||||
public function toDiscordChannel($notifiable): ?DiscordMessage
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,14 @@
|
||||
|
||||
namespace App\Contracts;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Validation\Validator;
|
||||
use function is_array;
|
||||
use Prettus\Repository\Eloquent\BaseRepository;
|
||||
use Prettus\Repository\Exceptions\RepositoryException;
|
||||
|
||||
/**
|
||||
* @mixin \Prettus\Repository\Eloquent\BaseRepository
|
||||
* @mixin BaseRepository
|
||||
*/
|
||||
abstract class Repository extends BaseRepository
|
||||
{
|
||||
@@ -20,8 +23,8 @@ abstract class Repository extends BaseRepository
|
||||
{
|
||||
try {
|
||||
return $this->find($id, $columns);
|
||||
} catch (\Exception $e) {
|
||||
return;
|
||||
} catch (Exception $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,11 +35,7 @@ abstract class Repository extends BaseRepository
|
||||
*/
|
||||
public function validate($values)
|
||||
{
|
||||
$validator = Validator::make(
|
||||
$values,
|
||||
$this->model()->rules
|
||||
);
|
||||
|
||||
$validator = Validator::make($values, $this->model()->rules);
|
||||
if ($validator->fails()) {
|
||||
return $validator->messages();
|
||||
}
|
||||
@@ -50,6 +49,8 @@ abstract class Repository extends BaseRepository
|
||||
* @param int $count
|
||||
* @param string $sort_by created_at (default) or updated_at
|
||||
*
|
||||
* @throws RepositoryException
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function recent($count = null, $sort_by = 'created_at')
|
||||
@@ -71,7 +72,7 @@ abstract class Repository extends BaseRepository
|
||||
return $this->scopeQuery(function ($query) use ($where, $sort_by, $order_by) {
|
||||
$q = $query->where($where);
|
||||
// See if there are multi-column sorts
|
||||
if (\is_array($sort_by)) {
|
||||
if (is_array($sort_by)) {
|
||||
foreach ($sort_by as $key => $sort) {
|
||||
$q = $q->orderBy($key, $sort);
|
||||
}
|
||||
@@ -98,7 +99,7 @@ abstract class Repository extends BaseRepository
|
||||
return $this->scopeQuery(function ($query) use ($col, $values, $sort_by, $order_by) {
|
||||
$q = $query->whereNotIn($col, $values);
|
||||
// See if there are multi-column sorts
|
||||
if (\is_array($sort_by)) {
|
||||
if (is_array($sort_by)) {
|
||||
foreach ($sort_by as $key => $sort) {
|
||||
$q = $q->orderBy($key, $sort);
|
||||
}
|
||||
@@ -118,7 +119,7 @@ abstract class Repository extends BaseRepository
|
||||
* @param array $columns
|
||||
* @param string $method
|
||||
*
|
||||
* @throws \Prettus\Repository\Exceptions\RepositoryException
|
||||
* @throws RepositoryException
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
|
||||
32
app/Database/migrations/2021_06_01_141152_discord_fields.php
Normal file
32
app/Database/migrations/2021_06_01_141152_discord_fields.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use App\Contracts\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class DiscordFields extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
// Delete the old Discord fields and then a webhook will get added
|
||||
DB::table('settings')
|
||||
->where(['key' => 'notifications.discord_api_key'])
|
||||
->delete();
|
||||
|
||||
DB::table('settings')
|
||||
->where(['key' => 'notifications.discord_public_channel_id'])
|
||||
->delete();
|
||||
|
||||
DB::table('settings')
|
||||
->where(['key' => 'notifications.discord_public_channel_id'])
|
||||
->delete();
|
||||
|
||||
// Add a field to the user to enter their own Discord ID
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->string('discord_id')
|
||||
->default('')
|
||||
->after('rank_id');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -368,20 +368,20 @@
|
||||
options: ''
|
||||
type: boolean
|
||||
description: 'Count transfer hours in calculations, like ranks and the total hours'
|
||||
- key: notifications.discord_api_key
|
||||
name: Discord API token
|
||||
- key: notifications.discord_public_webhook_url
|
||||
name: Discord Public Webhook URL
|
||||
group: notifications
|
||||
value: ''
|
||||
options: ''
|
||||
type: text
|
||||
description: Discord API token for notifications
|
||||
- key: 'notifications.discord_public_channel_id'
|
||||
name: 'Discord Public Channel ID'
|
||||
group: 'notifications'
|
||||
description: The Discord Webhook URL for public notifications
|
||||
- key: notifications.discord_private_webhook_url
|
||||
name: Discord Private Webhook URL
|
||||
group: notifications
|
||||
value: ''
|
||||
options: ''
|
||||
type: 'text'
|
||||
description: 'Discord public channel ID for broadcasat notifications'
|
||||
type: text
|
||||
description: The Discord Webhook URL for private notifications
|
||||
- key: 'cron.random_id'
|
||||
name: 'Cron Randomized ID'
|
||||
group: 'cron'
|
||||
|
||||
16
app/Events/PirepStateChange.php
Normal file
16
app/Events/PirepStateChange.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Contracts\Event;
|
||||
use App\Models\Pirep;
|
||||
|
||||
class PirepStateChange extends Event
|
||||
{
|
||||
public $pirep;
|
||||
|
||||
public function __construct(Pirep $pirep)
|
||||
{
|
||||
$this->pirep = $pirep;
|
||||
}
|
||||
}
|
||||
19
app/Events/PirepStatusChange.php
Normal file
19
app/Events/PirepStatusChange.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Contracts\Event;
|
||||
use App\Models\Pirep;
|
||||
|
||||
/**
|
||||
* Status change like Boarding, Taxi, etc
|
||||
*/
|
||||
class PirepStatusChange extends Event
|
||||
{
|
||||
public $pirep;
|
||||
|
||||
public function __construct(Pirep $pirep)
|
||||
{
|
||||
$this->pirep = $pirep;
|
||||
}
|
||||
}
|
||||
@@ -23,10 +23,10 @@ use App\Models\Enums\PirepFieldSource;
|
||||
use App\Models\Enums\PirepSource;
|
||||
use App\Models\Pirep;
|
||||
use App\Models\PirepComment;
|
||||
use App\Repositories\AcarsRepository;
|
||||
use App\Models\PirepFare;
|
||||
use App\Models\PirepFieldValue;
|
||||
use App\Repositories\JournalRepository;
|
||||
use App\Repositories\PirepRepository;
|
||||
use App\Services\FareService;
|
||||
use App\Services\Finance\PirepFinanceService;
|
||||
use App\Services\PirepService;
|
||||
use App\Services\UserService;
|
||||
@@ -37,8 +37,6 @@ use Illuminate\Support\Facades\Log;
|
||||
|
||||
class PirepController extends Controller
|
||||
{
|
||||
private $acarsRepo;
|
||||
private $fareSvc;
|
||||
private $financeSvc;
|
||||
private $journalRepo;
|
||||
private $pirepRepo;
|
||||
@@ -46,8 +44,6 @@ class PirepController extends Controller
|
||||
private $userSvc;
|
||||
|
||||
/**
|
||||
* @param AcarsRepository $acarsRepo
|
||||
* @param FareService $fareSvc
|
||||
* @param PirepFinanceService $financeSvc
|
||||
* @param JournalRepository $journalRepo
|
||||
* @param PirepRepository $pirepRepo
|
||||
@@ -55,16 +51,12 @@ class PirepController extends Controller
|
||||
* @param UserService $userSvc
|
||||
*/
|
||||
public function __construct(
|
||||
AcarsRepository $acarsRepo,
|
||||
FareService $fareSvc,
|
||||
PirepFinanceService $financeSvc,
|
||||
JournalRepository $journalRepo,
|
||||
PirepRepository $pirepRepo,
|
||||
PirepService $pirepSvc,
|
||||
UserService $userSvc
|
||||
) {
|
||||
$this->acarsRepo = $acarsRepo;
|
||||
$this->fareSvc = $fareSvc;
|
||||
$this->financeSvc = $financeSvc;
|
||||
$this->journalRepo = $journalRepo;
|
||||
$this->pirepRepo = $pirepRepo;
|
||||
@@ -101,7 +93,7 @@ class PirepController extends Controller
|
||||
/**
|
||||
* Check if a PIREP is cancelled
|
||||
*
|
||||
* @param $pirep
|
||||
* @param Pirep $pirep
|
||||
*
|
||||
* @throws \App\Exceptions\PirepCancelled
|
||||
*/
|
||||
@@ -113,50 +105,52 @@ class PirepController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $pirep
|
||||
* @param Request $request
|
||||
*
|
||||
* @return PirepFieldValue[]
|
||||
*/
|
||||
protected function updateFields($pirep, Request $request)
|
||||
protected function getFields(Request $request): ?array
|
||||
{
|
||||
if (!$request->filled('fields')) {
|
||||
return;
|
||||
return [];
|
||||
}
|
||||
|
||||
$pirep_fields = [];
|
||||
foreach ($request->input('fields') as $field_name => $field_value) {
|
||||
$pirep_fields[] = [
|
||||
$pirep_fields[] = new PirepFieldValue([
|
||||
'name' => $field_name,
|
||||
'value' => $field_value,
|
||||
'source' => PirepFieldSource::ACARS,
|
||||
];
|
||||
]);
|
||||
}
|
||||
|
||||
$this->pirepSvc->updateCustomFields($pirep->id, $pirep_fields);
|
||||
return $pirep_fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the fares
|
||||
*
|
||||
* @param $pirep
|
||||
* @param Request $request
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return PirepFare[]
|
||||
*/
|
||||
protected function updateFares($pirep, Request $request)
|
||||
protected function getFares(Request $request): ?array
|
||||
{
|
||||
if (!$request->filled('fares')) {
|
||||
return;
|
||||
return [];
|
||||
}
|
||||
|
||||
$fares = [];
|
||||
foreach ($request->post('fares') as $fare) {
|
||||
$fares[] = [
|
||||
$fares[] = new PirepFare([
|
||||
'fare_id' => $fare['id'],
|
||||
'count' => $fare['count'],
|
||||
];
|
||||
]);
|
||||
}
|
||||
|
||||
$this->fareSvc->saveForPirep($pirep, $fares);
|
||||
return $fares;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -210,14 +204,13 @@ class PirepController extends Controller
|
||||
$attrs = $this->parsePirep($request);
|
||||
$attrs['source'] = PirepSource::ACARS;
|
||||
|
||||
$pirep = $this->pirepSvc->prefile($user, $attrs);
|
||||
$fields = $this->getFields($request);
|
||||
$fares = $this->getFares($request);
|
||||
$pirep = $this->pirepSvc->prefile($user, $attrs, $fields, $fares);
|
||||
|
||||
Log::info('PIREP PREFILED');
|
||||
Log::info($pirep->id);
|
||||
|
||||
$this->updateFields($pirep, $request);
|
||||
$this->updateFares($pirep, $request);
|
||||
|
||||
return $this->get($pirep->id);
|
||||
}
|
||||
|
||||
@@ -258,9 +251,9 @@ class PirepController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
$pirep = $this->pirepRepo->update($attrs, $pirep_id);
|
||||
$this->updateFields($pirep, $request);
|
||||
$this->updateFares($pirep, $request);
|
||||
$fields = $this->getFields($request);
|
||||
$fares = $this->getFares($request);
|
||||
$pirep = $this->pirepSvc->update($pirep_id, $attrs, $fields, $fares);
|
||||
|
||||
event(new PirepUpdated($pirep));
|
||||
|
||||
@@ -303,9 +296,9 @@ class PirepController extends Controller
|
||||
}
|
||||
|
||||
try {
|
||||
$pirep = $this->pirepSvc->file($pirep, $attrs);
|
||||
$this->updateFields($pirep, $request);
|
||||
$this->updateFares($pirep, $request);
|
||||
$fields = $this->getFields($request);
|
||||
$fares = $this->getFares($request);
|
||||
$pirep = $this->pirepSvc->file($pirep, $attrs, $fields, $fares);
|
||||
} catch (\Exception $e) {
|
||||
Log::error($e);
|
||||
|
||||
@@ -411,7 +404,8 @@ class PirepController extends Controller
|
||||
$pirep = Pirep::find($pirep_id);
|
||||
$this->checkCancelled($pirep);
|
||||
|
||||
$this->updateFields($pirep, $request);
|
||||
$fields = $this->getFields($request);
|
||||
$this->pirepSvc->updateCustomFields($pirep_id, $fields);
|
||||
|
||||
return new PirepFieldCollection($pirep->fields);
|
||||
}
|
||||
|
||||
@@ -6,10 +6,7 @@ use App\Contracts\Listener;
|
||||
use App\Events\PirepPrefiled;
|
||||
|
||||
/**
|
||||
* Look for and run any of the award classes. Don't modify this.
|
||||
* See the documentation on creating awards:
|
||||
*
|
||||
* @url http://docs.phpvms.net/customizing/awards
|
||||
* Handler for PIREP events
|
||||
*/
|
||||
class PirepEventsHandler extends Listener
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ use Carbon\Carbon;
|
||||
* @property int id
|
||||
* @property mixed subfleet_id
|
||||
* @property string airport_id The apt where the aircraft is
|
||||
* @property string ident
|
||||
* @property string name
|
||||
* @property string icao
|
||||
* @property string registration
|
||||
@@ -71,6 +72,14 @@ class Aircraft extends Model
|
||||
'zfw' => 'nullable|numeric',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getIdentAttribute(): string
|
||||
{
|
||||
return $this->registration.' ('.$this->icao.')';
|
||||
}
|
||||
|
||||
/**
|
||||
* See if this aircraft is active
|
||||
*
|
||||
|
||||
@@ -33,7 +33,7 @@ class PirepStatus extends Enum
|
||||
public const LANDED = 'LAN';
|
||||
public const ARRIVED = 'ONB'; // On block
|
||||
public const CANCELLED = 'DX';
|
||||
public const EMERG_DECENT = 'EMG';
|
||||
public const EMERG_DESCENT = 'EMG';
|
||||
|
||||
protected static $labels = [
|
||||
self::INITIATED => 'pireps.status.initialized',
|
||||
@@ -58,6 +58,6 @@ class PirepStatus extends Enum
|
||||
self::LANDED => 'pireps.status.landed',
|
||||
self::ARRIVED => 'pireps.status.arrived',
|
||||
self::CANCELLED => 'pireps.status.cancelled',
|
||||
self::EMERG_DECENT => 'pireps.status.emerg_decent',
|
||||
self::EMERG_DESCENT => 'pireps.status.emerg_decent',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Contracts\Model;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
|
||||
/**
|
||||
* @property int id
|
||||
@@ -13,6 +14,8 @@ use App\Contracts\Model;
|
||||
*/
|
||||
class News extends Model
|
||||
{
|
||||
use Notifiable;
|
||||
|
||||
public $table = 'news';
|
||||
|
||||
protected $fillable = [
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Contracts\Model;
|
||||
use App\Events\PirepStateChange;
|
||||
use App\Events\PirepStatusChange;
|
||||
use App\Models\Enums\AcarsType;
|
||||
use App\Models\Enums\PirepFieldSource;
|
||||
use App\Models\Enums\PirepState;
|
||||
@@ -10,7 +12,9 @@ use App\Models\Traits\HashIdTrait;
|
||||
use App\Support\Units\Distance;
|
||||
use App\Support\Units\Fuel;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Support\Collection;
|
||||
use Kleemans\AttributeEvents;
|
||||
|
||||
/**
|
||||
* @property string id
|
||||
@@ -44,8 +48,8 @@ use Illuminate\Support\Collection;
|
||||
* @property Flight|null flight
|
||||
* @property Collection fields
|
||||
* @property string status
|
||||
* @property PirepState state
|
||||
* @property int source
|
||||
* @property int state
|
||||
* @property int source
|
||||
* @property string source_name
|
||||
* @property Carbon submitted_at
|
||||
* @property Carbon created_at
|
||||
@@ -57,7 +61,9 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
class Pirep extends Model
|
||||
{
|
||||
use AttributeEvents;
|
||||
use HashIdTrait;
|
||||
use Notifiable;
|
||||
|
||||
public $table = 'pireps';
|
||||
|
||||
@@ -137,6 +143,14 @@ class Pirep extends Model
|
||||
'route' => 'nullable',
|
||||
];
|
||||
|
||||
/**
|
||||
* Auto-dispatch events for lifecycle state changes
|
||||
*/
|
||||
protected $dispatchesEvents = [
|
||||
'status:*' => PirepStatusChange::class,
|
||||
'state:*' => PirepStateChange::class,
|
||||
];
|
||||
|
||||
/*
|
||||
* If a PIREP is in these states, then it can't be changed.
|
||||
*/
|
||||
|
||||
@@ -11,6 +11,7 @@ use App\Models\Enums\PirepFieldSource;
|
||||
* @property string slug
|
||||
* @property string value
|
||||
* @property string source
|
||||
* @property Pirep pirep
|
||||
*
|
||||
* @method static updateOrCreate(array $array, array $array1)
|
||||
*/
|
||||
|
||||
@@ -32,6 +32,7 @@ use Laratrust\Traits\LaratrustUserTrait;
|
||||
* @property Rank rank
|
||||
* @property Journal journal
|
||||
* @property int rank_id
|
||||
* @property string discord_id
|
||||
* @property int state
|
||||
* @property bool opt_in
|
||||
* @property Pirep[] pireps
|
||||
@@ -66,6 +67,7 @@ class User extends Authenticatable
|
||||
'pilot_id',
|
||||
'airline_id',
|
||||
'rank_id',
|
||||
'discord_id',
|
||||
'api_key',
|
||||
'country',
|
||||
'home_airport_id',
|
||||
@@ -89,6 +91,7 @@ class User extends Authenticatable
|
||||
*/
|
||||
protected $hidden = [
|
||||
'api_key',
|
||||
'discord_id',
|
||||
'password',
|
||||
'remember_token',
|
||||
];
|
||||
|
||||
36
app/Notifications/Channels/Discord/Discord.php
Normal file
36
app/Notifications/Channels/Discord/Discord.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications\Channels\Discord;
|
||||
|
||||
use App\Contracts\Notification;
|
||||
use App\Support\HttpClient;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use GuzzleHttp\Psr7;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class Discord
|
||||
{
|
||||
private $httpClient;
|
||||
|
||||
public function __construct(HttpClient $httpClient)
|
||||
{
|
||||
$this->httpClient = $httpClient;
|
||||
}
|
||||
|
||||
public function send($notifiable, Notification $notification)
|
||||
{
|
||||
$message = $notification->toDiscordChannel($notifiable);
|
||||
if ($message === null || empty($message->webhook_url)) {
|
||||
Log::debug('Discord notifications not configured, skipping');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$data = $message->toArray();
|
||||
$this->httpClient->post($message->webhook_url, $data);
|
||||
} catch (RequestException $e) {
|
||||
$response = Psr7\Message::toString($e->getResponse());
|
||||
Log::error('Error sending Discord notification: '.$e->getMessage().', '.$response);
|
||||
}
|
||||
}
|
||||
}
|
||||
140
app/Notifications/Channels/Discord/DiscordMessage.php
Normal file
140
app/Notifications/Channels/Discord/DiscordMessage.php
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications\Channels\Discord;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
||||
/**
|
||||
* Original is from https://gist.github.com/freekmurze/e4415090f650e070d3de8b905875cf78
|
||||
*
|
||||
* Markdown guide: https://birdie0.github.io/discord-webhooks-guide/other/discord_markdown.html
|
||||
*/
|
||||
class DiscordMessage
|
||||
{
|
||||
const COLOR_SUCCESS = '#0B6623';
|
||||
const COLOR_WARNING = '#FD6A02';
|
||||
const COLOR_ERROR = '#ED2939';
|
||||
|
||||
public $webhook_url;
|
||||
|
||||
protected $title;
|
||||
protected $url;
|
||||
protected $description;
|
||||
protected $timestamp;
|
||||
protected $footer;
|
||||
protected $color;
|
||||
protected $author = [];
|
||||
protected $fields = [];
|
||||
|
||||
/**
|
||||
* Supply the webhook URL that this should be going to
|
||||
*/
|
||||
public function webhook(string $url): self
|
||||
{
|
||||
$this->webhook_url = $url;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Title of the notification
|
||||
*/
|
||||
public function title(string $title): self
|
||||
{
|
||||
$this->title = $title;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function url(string $url): self
|
||||
{
|
||||
$this->url = $url;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|string $descriptionLines
|
||||
*/
|
||||
public function description($descriptionLines): self
|
||||
{
|
||||
if (!is_array($descriptionLines)) {
|
||||
$descriptionLines = [$descriptionLines];
|
||||
}
|
||||
|
||||
$this->description = implode(PHP_EOL, $descriptionLines);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the author information:
|
||||
* [
|
||||
* 'name' => '',
|
||||
* 'url' => '',
|
||||
* 'icon_url' => '',
|
||||
*/
|
||||
public function author(array $author): self
|
||||
{
|
||||
$this->author = $author;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the fields
|
||||
*/
|
||||
public function fields(array $fields): self
|
||||
{
|
||||
$this->fields = [];
|
||||
foreach ($fields as $name => $value) {
|
||||
$this->fields[] = [
|
||||
'name' => '**'.$name.'**', // bold
|
||||
'value' => $value,
|
||||
'inline' => true,
|
||||
];
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function footer(string $footer): self
|
||||
{
|
||||
$this->footer = $footer;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function success(): self
|
||||
{
|
||||
$this->color = static::COLOR_SUCCESS;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function warning(): self
|
||||
{
|
||||
$this->color = static::COLOR_WARNING;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function error(): self
|
||||
{
|
||||
$this->color = static::COLOR_ERROR;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'embeds' => [
|
||||
[
|
||||
'title' => $this->title,
|
||||
'url' => $this->url,
|
||||
'type' => 'rich',
|
||||
'description' => $this->description,
|
||||
// 'color' => hexdec($this->color),
|
||||
'author' => $this->author,
|
||||
'fields' => $this->fields,
|
||||
'footer' => [
|
||||
'text' => $this->footer ?? '',
|
||||
],
|
||||
'timestamp' => Carbon::now('UTC'),
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ trait MailChannel
|
||||
* @param string $template Markdown template to use
|
||||
* @param array $args Arguments to pass to the template
|
||||
*/
|
||||
public function setMailable($subject, $template, $args)
|
||||
public function setMailable(string $subject, string $template, array $args)
|
||||
{
|
||||
$this->mailSubject = $subject;
|
||||
$this->mailTemplate = $template;
|
||||
|
||||
@@ -4,17 +4,15 @@ namespace App\Notifications\Messages;
|
||||
|
||||
use App\Contracts\Notification;
|
||||
use App\Models\User;
|
||||
use App\Notifications\Channels\Discord\Discord;
|
||||
use App\Notifications\Channels\Discord\DiscordMessage;
|
||||
use App\Notifications\Channels\MailChannel;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
class AdminUserRegistered extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
use MailChannel;
|
||||
|
||||
public $channels = ['mail'];
|
||||
|
||||
private $user;
|
||||
|
||||
/**
|
||||
@@ -34,6 +32,32 @@ class AdminUserRegistered extends Notification implements ShouldQueue
|
||||
);
|
||||
}
|
||||
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['mail', Discord::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a Discord notification
|
||||
*
|
||||
* @param User $pirep
|
||||
* @param mixed $user
|
||||
*
|
||||
* @return DiscordMessage|null
|
||||
*/
|
||||
public function toDiscordChannel($user): ?DiscordMessage
|
||||
{
|
||||
if (empty(setting('notifications.discord_private_webhook_url'))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$dm = new DiscordMessage();
|
||||
return $dm->webhook(setting('notifications.discord_private_webhook_url'))
|
||||
->success()
|
||||
->title('New User Registered: '.$user->ident)
|
||||
->fields([]);
|
||||
}
|
||||
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
|
||||
@@ -4,16 +4,15 @@ namespace App\Notifications\Messages;
|
||||
|
||||
use App\Contracts\Notification;
|
||||
use App\Models\News;
|
||||
use App\Notifications\Channels\Discord\Discord;
|
||||
use App\Notifications\Channels\Discord\DiscordMessage;
|
||||
use App\Notifications\Channels\MailChannel;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
class NewsAdded extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
use MailChannel;
|
||||
|
||||
public $channels = ['mail'];
|
||||
public $requires_opt_in = true;
|
||||
|
||||
private $news;
|
||||
@@ -30,6 +29,34 @@ class NewsAdded extends Notification implements ShouldQueue
|
||||
);
|
||||
}
|
||||
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['mail', Discord::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param News $news
|
||||
*
|
||||
* @return DiscordMessage|null
|
||||
*/
|
||||
public function toDiscordChannel($news): ?DiscordMessage
|
||||
{
|
||||
if (empty(setting('notifications.discord_public_webhook_url'))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$dm = new DiscordMessage();
|
||||
return $dm->webhook(setting('notifications.discord_public_webhook_url'))
|
||||
->success()
|
||||
->title('News: '.$news->subject)
|
||||
->author([
|
||||
'name' => $news->user->ident.' - '.$news->user->name_private,
|
||||
'url' => '',
|
||||
'icon_url' => $news->user->resolveAvatarUrl(),
|
||||
])
|
||||
->description($news->body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
|
||||
@@ -5,19 +5,15 @@ namespace App\Notifications\Messages;
|
||||
use App\Contracts\Notification;
|
||||
use App\Models\Pirep;
|
||||
use App\Notifications\Channels\MailChannel;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
/**
|
||||
* Send the PIREP accepted message to a particular user
|
||||
* Send the PIREP accepted message to a particular user, can also be sent to Discord
|
||||
*/
|
||||
class PirepAccepted extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
use MailChannel;
|
||||
|
||||
public $channels = ['mail'];
|
||||
|
||||
private $pirep;
|
||||
|
||||
/**
|
||||
@@ -38,6 +34,11 @@ class PirepAccepted extends Notification implements ShouldQueue
|
||||
);
|
||||
}
|
||||
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
|
||||
102
app/Notifications/Messages/PirepPrefiled.php
Normal file
102
app/Notifications/Messages/PirepPrefiled.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications\Messages;
|
||||
|
||||
use App\Contracts\Notification;
|
||||
use App\Models\Pirep;
|
||||
use App\Notifications\Channels\Discord\Discord;
|
||||
use App\Notifications\Channels\Discord\DiscordMessage;
|
||||
use App\Support\Units\Distance;
|
||||
use App\Support\Units\Time;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use PhpUnitsOfMeasure\Exception\NonNumericValue;
|
||||
use PhpUnitsOfMeasure\Exception\NonStringUnitName;
|
||||
|
||||
/**
|
||||
* Send the PIREP accepted message to a particular user, can also be sent to Discord
|
||||
*/
|
||||
class PirepPrefiled extends Notification implements ShouldQueue
|
||||
{
|
||||
private $pirep;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @param Pirep $pirep
|
||||
*/
|
||||
public function __construct(Pirep $pirep)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->pirep = $pirep;
|
||||
}
|
||||
|
||||
public function via($notifiable)
|
||||
{
|
||||
return [Discord::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a Discord notification
|
||||
*
|
||||
* @param Pirep $pirep
|
||||
*
|
||||
* @return DiscordMessage|null
|
||||
*/
|
||||
public function toDiscordChannel($pirep): ?DiscordMessage
|
||||
{
|
||||
if (empty(setting('notifications.discord_public_webhook_url'))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$title = 'Flight '.$pirep->airline->code.$pirep->ident.' Prefiled';
|
||||
$fields = [
|
||||
'Flight' => $pirep->airline->code.$pirep->ident,
|
||||
'Departure Airport' => $pirep->dpt_airport_id,
|
||||
'Arrival Airport' => $pirep->arr_airport_id,
|
||||
'Equipment' => $pirep->aircraft->ident,
|
||||
'Flight Time (Planned)' => Time::minutesToTimeString($pirep->planned_flight_time),
|
||||
];
|
||||
|
||||
if ($pirep->planned_distance) {
|
||||
try {
|
||||
$planned_distance = new Distance(
|
||||
$pirep->planned_distance,
|
||||
config('phpvms.internal_units.distance')
|
||||
);
|
||||
|
||||
$pd = $planned_distance[$planned_distance->unit].' '.$planned_distance->unit;
|
||||
$fields['Distance (Planned)'] = $pd;
|
||||
} catch (NonNumericValue $e) {
|
||||
} catch (NonStringUnitName $e) {
|
||||
}
|
||||
}
|
||||
|
||||
$dm = new DiscordMessage();
|
||||
return $dm->webhook(setting('notifications.discord_public_webhook_url'))
|
||||
->success()
|
||||
->title($title)
|
||||
->description($pirep->user->discord_id ? 'Flight by <@'.$pirep->user->discord_id.'>' : '')
|
||||
->url(route('frontend.pireps.show', [$pirep->id]))
|
||||
->author([
|
||||
'name' => $pirep->user->ident.' - '.$pirep->user->name_private,
|
||||
'url' => route('frontend.pireps.show', [$pirep->id]),
|
||||
'icon_url' => $pirep->user->resolveAvatarUrl(),
|
||||
])
|
||||
->fields($fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
'pirep_id' => $this->pirep->id,
|
||||
'user_id' => $this->pirep->user_id,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -5,22 +5,18 @@ namespace App\Notifications\Messages;
|
||||
use App\Contracts\Notification;
|
||||
use App\Models\Pirep;
|
||||
use App\Notifications\Channels\MailChannel;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
class PirepRejected extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
use MailChannel;
|
||||
|
||||
public $channels = ['mail'];
|
||||
|
||||
private $pirep;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @param \App\Models\Pirep $pirep
|
||||
* @param Pirep $pirep
|
||||
*/
|
||||
public function __construct(Pirep $pirep)
|
||||
{
|
||||
@@ -35,6 +31,11 @@ class PirepRejected extends Notification implements ShouldQueue
|
||||
);
|
||||
}
|
||||
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
|
||||
141
app/Notifications/Messages/PirepStatusChanged.php
Normal file
141
app/Notifications/Messages/PirepStatusChanged.php
Normal file
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications\Messages;
|
||||
|
||||
use App\Contracts\Notification;
|
||||
use App\Models\Enums\PirepStatus;
|
||||
use App\Models\Pirep;
|
||||
use App\Notifications\Channels\Discord\Discord;
|
||||
use App\Notifications\Channels\Discord\DiscordMessage;
|
||||
use App\Support\Units\Distance;
|
||||
use App\Support\Units\Time;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use PhpUnitsOfMeasure\Exception\NonNumericValue;
|
||||
use PhpUnitsOfMeasure\Exception\NonStringUnitName;
|
||||
|
||||
/**
|
||||
* Send the PIREP accepted message to a particular user, can also be sent to Discord
|
||||
*/
|
||||
class PirepStatusChanged extends Notification implements ShouldQueue
|
||||
{
|
||||
private $pirep;
|
||||
|
||||
// TODO: Int'l languages for these
|
||||
protected static $verbs = [
|
||||
PirepStatus::INITIATED => 'is initialized',
|
||||
PirepStatus::SCHEDULED => 'is scheduled',
|
||||
PirepStatus::BOARDING => 'is boarding',
|
||||
PirepStatus::RDY_START => 'is ready for start',
|
||||
PirepStatus::PUSHBACK_TOW => 'is pushing back',
|
||||
PirepStatus::DEPARTED => 'has departed',
|
||||
PirepStatus::RDY_DEICE => 'is ready for de-icing',
|
||||
PirepStatus::STRT_DEICE => 'is de-icing',
|
||||
PirepStatus::GRND_RTRN => 'on ground return',
|
||||
PirepStatus::TAXI => 'is taxiing',
|
||||
PirepStatus::TAKEOFF => 'has taken off',
|
||||
PirepStatus::INIT_CLIM => 'in initial climb',
|
||||
PirepStatus::AIRBORNE => 'is enroute',
|
||||
PirepStatus::ENROUTE => 'is enroute',
|
||||
PirepStatus::DIVERTED => 'has diverted',
|
||||
PirepStatus::APPROACH => 'on approach',
|
||||
PirepStatus::APPROACH_ICAO => 'on approach',
|
||||
PirepStatus::ON_FINAL => 'on final approach',
|
||||
PirepStatus::LANDING => 'is landing',
|
||||
PirepStatus::LANDED => 'has landed',
|
||||
PirepStatus::ARRIVED => 'has arrived',
|
||||
PirepStatus::CANCELLED => 'has cancelled',
|
||||
PirepStatus::EMERG_DESCENT => 'in emergency descent',
|
||||
];
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @param Pirep $pirep
|
||||
*/
|
||||
public function __construct(Pirep $pirep)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->pirep = $pirep;
|
||||
}
|
||||
|
||||
public function via($notifiable)
|
||||
{
|
||||
return [Discord::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a Discord notification
|
||||
*
|
||||
* @param Pirep $pirep
|
||||
*
|
||||
* @return DiscordMessage|null
|
||||
*/
|
||||
public function toDiscordChannel($pirep): ?DiscordMessage
|
||||
{
|
||||
if (empty(setting('notifications.discord_public_webhook_url'))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$title = 'Flight '.$pirep->airline->code.$pirep->ident.' '.self::$verbs[$pirep->status];
|
||||
|
||||
$fields = [
|
||||
'Flight' => $pirep->airline->code.$pirep->ident,
|
||||
'Departure Airport' => $pirep->dpt_airport_id,
|
||||
'Arrival Airport' => $pirep->arr_airport_id,
|
||||
'Equipment' => $pirep->aircraft->ident,
|
||||
'Flight Time' => Time::minutesToTimeString($pirep->flight_time),
|
||||
];
|
||||
|
||||
// Show the distance, but include the planned distance if it's been set
|
||||
if ($pirep->distance) {
|
||||
$unit = config('phpvms.internal_units.distance');
|
||||
|
||||
try {
|
||||
$planned_distance = new Distance($pirep->distance, $unit);
|
||||
$pd = $planned_distance[$planned_distance->unit];
|
||||
$fields['Distance'] = $pd;
|
||||
|
||||
// Add the planned distance in
|
||||
if ($pirep->planned_distance) {
|
||||
try {
|
||||
$planned_distance = new Distance($pirep->planned_distance, $unit);
|
||||
$pd = $planned_distance[$planned_distance->unit];
|
||||
$fields['Distance'] .= '/'.$pd;
|
||||
} catch (NonNumericValue | NonStringUnitName $e) {
|
||||
}
|
||||
}
|
||||
|
||||
$fields['Distance'] .= ' '.$planned_distance->unit;
|
||||
} catch (NonNumericValue | NonStringUnitName $e) {
|
||||
}
|
||||
}
|
||||
|
||||
$dm = new DiscordMessage();
|
||||
return $dm->webhook(setting('notifications.discord_public_webhook_url'))
|
||||
->success()
|
||||
->title($title)
|
||||
->description($pirep->user->discord_id ? 'Flight by <@'.$pirep->user->discord_id.'>' : '')
|
||||
->url(route('frontend.pireps.show', [$pirep->id]))
|
||||
->author([
|
||||
'name' => $pirep->user->ident.' - '.$pirep->user->name_private,
|
||||
'url' => route('frontend.pireps.show', [$pirep->id]),
|
||||
'icon_url' => $pirep->user->resolveAvatarUrl(),
|
||||
])
|
||||
->fields($fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
'pirep_id' => $this->pirep->id,
|
||||
'user_id' => $this->pirep->user_id,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -4,17 +4,19 @@ namespace App\Notifications\Messages;
|
||||
|
||||
use App\Contracts\Notification;
|
||||
use App\Models\Pirep;
|
||||
use App\Notifications\Channels\Discord\Discord;
|
||||
use App\Notifications\Channels\Discord\DiscordMessage;
|
||||
use App\Notifications\Channels\MailChannel;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use App\Support\Units\Distance;
|
||||
use App\Support\Units\Time;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use PhpUnitsOfMeasure\Exception\NonNumericValue;
|
||||
use PhpUnitsOfMeasure\Exception\NonStringUnitName;
|
||||
|
||||
class PirepSubmitted extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
use MailChannel;
|
||||
|
||||
public $channels = ['mail'];
|
||||
|
||||
private $pirep;
|
||||
|
||||
/**
|
||||
@@ -35,6 +37,60 @@ class PirepSubmitted extends Notification implements ShouldQueue
|
||||
);
|
||||
}
|
||||
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['mail', Discord::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a Discord notification
|
||||
*
|
||||
* @param Pirep $pirep
|
||||
*
|
||||
* @return DiscordMessage|null
|
||||
*/
|
||||
public function toDiscordChannel($pirep): ?DiscordMessage
|
||||
{
|
||||
if (empty(setting('notifications.discord_public_webhook_url'))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$title = 'Flight '.$pirep->airline->code.$pirep->ident.' Filed';
|
||||
$fields = [
|
||||
'Flight' => $pirep->airline->code.$pirep->ident,
|
||||
'Departure Airport' => $pirep->dpt_airport_id,
|
||||
'Arrival Airport' => $pirep->arr_airport_id,
|
||||
'Equipment' => $pirep->aircraft->ident,
|
||||
'Flight Time (Planned)' => Time::minutesToTimeString($pirep->planned_flight_time),
|
||||
];
|
||||
|
||||
if ($pirep->planned_distance) {
|
||||
try {
|
||||
$planned_distance = new Distance(
|
||||
$pirep->planned_distance,
|
||||
config('phpvms.internal_units.distance')
|
||||
);
|
||||
|
||||
$pd = $planned_distance[$planned_distance->unit].' '.$planned_distance->unit;
|
||||
$fields['Distance (Planned)'] = $pd;
|
||||
} catch (NonNumericValue | NonStringUnitName $e) {
|
||||
}
|
||||
}
|
||||
|
||||
$dm = new DiscordMessage();
|
||||
return $dm->webhook(setting('notifications.discord_public_webhook_url'))
|
||||
->success()
|
||||
->title($title)
|
||||
->description($pirep->user->discord_id ? 'Flight by <@'.$pirep->user->discord_id.'>' : '')
|
||||
->url(route('frontend.pireps.show', [$pirep->id]))
|
||||
->author([
|
||||
'name' => $pirep->user->ident.' - '.$pirep->user->name_private,
|
||||
'url' => route('frontend.pireps.show', [$pirep->id]),
|
||||
'icon_url' => $pirep->user->resolveAvatarUrl(),
|
||||
])
|
||||
->fields($fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
|
||||
@@ -5,20 +5,16 @@ namespace App\Notifications\Messages;
|
||||
use App\Contracts\Notification;
|
||||
use App\Models\User;
|
||||
use App\Notifications\Channels\MailChannel;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
class UserPending extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
use MailChannel;
|
||||
|
||||
public $channels = ['mail'];
|
||||
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* @param \App\Models\User $user
|
||||
* @param User $user
|
||||
*/
|
||||
public function __construct(User $user)
|
||||
{
|
||||
@@ -33,6 +29,11 @@ class UserPending extends Notification implements ShouldQueue
|
||||
);
|
||||
}
|
||||
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
|
||||
@@ -5,22 +5,18 @@ namespace App\Notifications\Messages;
|
||||
use App\Contracts\Notification;
|
||||
use App\Models\User;
|
||||
use App\Notifications\Channels\MailChannel;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
class UserRegistered extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
use MailChannel;
|
||||
|
||||
public $channels = ['mail'];
|
||||
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @param User $user
|
||||
*/
|
||||
public function __construct(User $user)
|
||||
{
|
||||
@@ -35,6 +31,11 @@ class UserRegistered extends Notification implements ShouldQueue
|
||||
);
|
||||
}
|
||||
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
|
||||
@@ -13,8 +13,6 @@ class UserRejected extends Notification implements ShouldQueue
|
||||
use Queueable;
|
||||
use MailChannel;
|
||||
|
||||
public $channels = ['mail'];
|
||||
|
||||
private $user;
|
||||
|
||||
/**
|
||||
@@ -33,6 +31,11 @@ class UserRejected extends Notification implements ShouldQueue
|
||||
);
|
||||
}
|
||||
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
|
||||
@@ -6,13 +6,13 @@ use App\Contracts\Listener;
|
||||
use App\Events\NewsAdded;
|
||||
use App\Events\PirepAccepted;
|
||||
use App\Events\PirepFiled;
|
||||
use App\Events\PirepPrefiled;
|
||||
use App\Events\PirepRejected;
|
||||
use App\Events\PirepStatusChange;
|
||||
use App\Events\UserRegistered;
|
||||
use App\Events\UserStateChanged;
|
||||
use App\Models\Enums\UserState;
|
||||
use App\Models\User;
|
||||
use App\Notifications\Messages\PirepSubmitted;
|
||||
use App\Notifications\Messages\UserPending;
|
||||
use App\Notifications\Messages\UserRejected;
|
||||
use App\Notifications\Notifiables\Broadcast;
|
||||
use Exception;
|
||||
@@ -23,17 +23,19 @@ use Illuminate\Support\Facades\Notification;
|
||||
/**
|
||||
* Listen for different events and map them to different notifications
|
||||
*/
|
||||
class EventHandler extends Listener
|
||||
class NotificationEventsHandler extends Listener
|
||||
{
|
||||
private static $broadcastNotifyable;
|
||||
|
||||
public static $callbacks = [
|
||||
NewsAdded::class => 'onNewsAdded',
|
||||
PirepAccepted::class => 'onPirepAccepted',
|
||||
PirepFiled::class => 'onPirepFile',
|
||||
PirepRejected::class => 'onPirepRejected',
|
||||
UserRegistered::class => 'onUserRegister',
|
||||
UserStateChanged::class => 'onUserStateChange',
|
||||
NewsAdded::class => 'onNewsAdded',
|
||||
PirepPrefiled::class => 'onPirepPrefile',
|
||||
PirepStatusChange::class => 'onPirepStatusChange',
|
||||
PirepAccepted::class => 'onPirepAccepted',
|
||||
PirepFiled::class => 'onPirepFile',
|
||||
PirepRejected::class => 'onPirepRejected',
|
||||
UserRegistered::class => 'onUserRegister',
|
||||
UserStateChanged::class => 'onUserStateChange',
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
@@ -56,7 +58,8 @@ class EventHandler extends Listener
|
||||
}
|
||||
|
||||
try {
|
||||
Notification::send([$user], $notification);
|
||||
$this->notifyUser($user, $notification);
|
||||
// Notification::send([$user], $notification);
|
||||
} catch (Exception $e) {
|
||||
Log::emergency('Error emailing admin ('.$user->email.'). Error='.$e->getMessage());
|
||||
}
|
||||
@@ -117,19 +120,24 @@ class EventHandler extends Listener
|
||||
.$event->user->ident.' is '
|
||||
.UserState::label($event->user->state).', sending active email');
|
||||
|
||||
/*
|
||||
* Send all of the admins a notification that a new user registered
|
||||
*/
|
||||
$this->notifyAdmins(new Messages\AdminUserRegistered($event->user));
|
||||
|
||||
/*
|
||||
* Send the user a confirmation email
|
||||
*/
|
||||
if ($event->user->state === UserState::ACTIVE) {
|
||||
$this->notifyUser($event->user, new Messages\UserRegistered($event->user));
|
||||
} elseif ($event->user->state === UserState::PENDING) {
|
||||
$this->notifyUser($event->user, new UserPending($event->user));
|
||||
$this->notifyUser($event->user, new Messages\UserPending($event->user));
|
||||
}
|
||||
|
||||
/*
|
||||
* Send all of the admins a notification that a new user registered
|
||||
*/
|
||||
$this->notifyAdmins(new Messages\AdminUserRegistered($event->user));
|
||||
|
||||
/**
|
||||
* Discord and other notifications
|
||||
*/
|
||||
Notification::send([$event->user], new Messages\AdminUserRegistered($event->user));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,15 +160,34 @@ class EventHandler extends Listener
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefile notification
|
||||
*/
|
||||
public function onPirepPrefile(PirepPrefiled $event): void
|
||||
{
|
||||
Log::info('NotificationEvents::onPirepPrefile: '.$event->pirep->id.' prefiled');
|
||||
Notification::send([$event->pirep], new Messages\PirepPrefiled($event->pirep));
|
||||
}
|
||||
|
||||
/**
|
||||
* Status Change notification
|
||||
*/
|
||||
public function onPirepStatusChange(PirepStatusChange $event): void
|
||||
{
|
||||
Log::info('NotificationEvents::onPirepStatusChange: '.$event->pirep->id.' prefiled');
|
||||
Notification::send([$event->pirep], new Messages\PirepStatusChanged($event->pirep));
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the admins that a new PIREP has been filed
|
||||
*
|
||||
* @param \App\Events\PirepFiled $event
|
||||
* @param PirepFiled $event
|
||||
*/
|
||||
public function onPirepFile(PirepFiled $event): void
|
||||
{
|
||||
Log::info('NotificationEvents::onPirepFile: '.$event->pirep->id.' filed ');
|
||||
$this->notifyAdmins(new PirepSubmitted($event->pirep));
|
||||
Log::info('NotificationEvents::onPirepFile: '.$event->pirep->id.' filed');
|
||||
$this->notifyAdmins(new Messages\PirepSubmitted($event->pirep));
|
||||
Notification::send([$event->pirep], new Messages\PirepSubmitted($event->pirep));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -194,5 +221,6 @@ class EventHandler extends Listener
|
||||
{
|
||||
Log::info('NotificationEvents::onNewsAdded');
|
||||
$this->notifyAllUsers(new Messages\NewsAdded($event->news));
|
||||
Notification::send([$event->news], new Messages\NewsAdded($event->news));
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ use App\Listeners\ExpenseListener;
|
||||
use App\Listeners\FinanceEventHandler;
|
||||
use App\Listeners\PirepEventsHandler;
|
||||
use App\Listeners\UserStateListener;
|
||||
use App\Notifications\EventHandler;
|
||||
use App\Notifications\NotificationEventsHandler;
|
||||
use Codedge\Updater\Events\UpdateAvailable;
|
||||
use Codedge\Updater\Events\UpdateSucceeded;
|
||||
use Illuminate\Auth\Events\Registered;
|
||||
@@ -49,7 +49,7 @@ class EventServiceProvider extends ServiceProvider
|
||||
protected $subscribe = [
|
||||
BidEventHandler::class,
|
||||
FinanceEventHandler::class,
|
||||
EventHandler::class,
|
||||
NotificationEventsHandler::class,
|
||||
AwardHandler::class,
|
||||
PirepEventsHandler::class,
|
||||
];
|
||||
|
||||
@@ -292,14 +292,14 @@ class FareService extends Service
|
||||
/**
|
||||
* Save the list of fares
|
||||
*
|
||||
* @param Pirep $pirep
|
||||
* @param array $fares ['fare_id', 'count']
|
||||
* @param Pirep $pirep
|
||||
* @param PirepFare[] $fares
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function saveForPirep(Pirep $pirep, array $fares)
|
||||
{
|
||||
if (!$fares) {
|
||||
if (!$fares || empty($fares)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -308,13 +308,9 @@ class FareService extends Service
|
||||
|
||||
// Add them in
|
||||
foreach ($fares as $fare) {
|
||||
$fare['pirep_id'] = $pirep->id;
|
||||
// other fields: ['fare_id', 'count']
|
||||
|
||||
$fare->pirep_id = $pirep->id;
|
||||
Log::info('Saving fare pirep='.$pirep->id.', fare='.$fare['count']);
|
||||
|
||||
$field = new PirepFare($fare);
|
||||
$field->save();
|
||||
$fare->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ use App\Repositories\AircraftRepository;
|
||||
use App\Repositories\AirportRepository;
|
||||
use App\Repositories\PirepRepository;
|
||||
use Carbon\Carbon;
|
||||
use function count;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
@@ -45,16 +44,18 @@ class PirepService extends Service
|
||||
private $aircraftRepo;
|
||||
private $airportRepo;
|
||||
private $airportSvc;
|
||||
private $fareSvc;
|
||||
private $geoSvc;
|
||||
private $pirepRepo;
|
||||
private $simBriefSvc;
|
||||
private $userSvc;
|
||||
|
||||
/**
|
||||
* @param AircraftRepository $aircraftRepo
|
||||
* @param GeoService $geoSvc
|
||||
* @param AirportRepository $airportRepo
|
||||
* @param AirportService $airportSvc
|
||||
* @param AircraftRepository $aircraftRepo
|
||||
* @param FareService $fareSvc
|
||||
* @param GeoService $geoSvc
|
||||
* @param PirepRepository $pirepRepo
|
||||
* @param SimBriefService $simBriefSvc
|
||||
* @param UserService $userSvc
|
||||
@@ -63,6 +64,7 @@ class PirepService extends Service
|
||||
AirportRepository $airportRepo,
|
||||
AirportService $airportSvc,
|
||||
AircraftRepository $aircraftRepo,
|
||||
FareService $fareSvc,
|
||||
GeoService $geoSvc,
|
||||
PirepRepository $pirepRepo,
|
||||
SimBriefService $simBriefSvc,
|
||||
@@ -71,6 +73,7 @@ class PirepService extends Service
|
||||
$this->airportRepo = $airportRepo;
|
||||
$this->airportSvc = $airportSvc;
|
||||
$this->aircraftRepo = $aircraftRepo;
|
||||
$this->fareSvc = $fareSvc;
|
||||
$this->geoSvc = $geoSvc;
|
||||
$this->pirepRepo = $pirepRepo;
|
||||
$this->simBriefSvc = $simBriefSvc;
|
||||
@@ -80,15 +83,17 @@ class PirepService extends Service
|
||||
/**
|
||||
* Create a prefiled PIREP
|
||||
*
|
||||
* @param \App\Models\User $user
|
||||
* @param array $attrs
|
||||
* @param User $user
|
||||
* @param array $attrs
|
||||
* @param PirepFieldValue[] $fields
|
||||
* @param PirepFare[] $fares
|
||||
*
|
||||
* @throws AirportNotFound If one of the departure or arrival airports isn't found locally
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return \App\Models\Pirep
|
||||
*/
|
||||
public function prefile(User $user, array $attrs): Pirep
|
||||
public function prefile(User $user, array $attrs, array $fields = [], array $fares = []): Pirep
|
||||
{
|
||||
$attrs['user_id'] = $user->id;
|
||||
$attrs['state'] = PirepState::IN_PROGRESS;
|
||||
@@ -176,6 +181,7 @@ class PirepService extends Service
|
||||
}
|
||||
}
|
||||
|
||||
$pirep->status = PirepStatus::INITIATED;
|
||||
$pirep->save();
|
||||
$pirep->refresh();
|
||||
|
||||
@@ -189,6 +195,9 @@ class PirepService extends Service
|
||||
}
|
||||
}
|
||||
|
||||
$this->updateCustomFields($pirep->id, $fields);
|
||||
$this->fareSvc->saveForPirep($pirep, $fares);
|
||||
|
||||
event(new PirepPrefiled($pirep));
|
||||
|
||||
return $pirep;
|
||||
@@ -202,10 +211,10 @@ class PirepService extends Service
|
||||
*
|
||||
* @return Pirep
|
||||
*/
|
||||
public function create(Pirep $pirep, array $field_values = []): Pirep
|
||||
public function create(Pirep $pirep, array $fields = []): Pirep
|
||||
{
|
||||
if (empty($field_values)) {
|
||||
$field_values = [];
|
||||
if (empty($fields)) {
|
||||
$fields = [];
|
||||
}
|
||||
|
||||
// Check the block times. If a block on (arrival) time isn't
|
||||
@@ -241,9 +250,23 @@ class PirepService extends Service
|
||||
$pirep->save();
|
||||
$pirep->refresh();
|
||||
|
||||
if (count($field_values) > 0) {
|
||||
$this->updateCustomFields($pirep->id, $field_values);
|
||||
}
|
||||
$this->updateCustomFields($pirep->id, $fields);
|
||||
|
||||
return $pirep;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PirepFieldValue[] $fields
|
||||
* @param PirepFare[] $fares
|
||||
*
|
||||
* @throws \Prettus\Validator\Exceptions\ValidatorException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function update(string $pirep_id, array $attrs, array $fields = [], array $fares = []): Pirep
|
||||
{
|
||||
$pirep = $this->pirepRepo->update($attrs, $pirep_id);
|
||||
$this->updateCustomFields($pirep_id, $fields);
|
||||
$this->fareSvc->saveForPirep($pirep, $fares);
|
||||
|
||||
return $pirep;
|
||||
}
|
||||
@@ -251,18 +274,19 @@ class PirepService extends Service
|
||||
/**
|
||||
* Finalize a PIREP (meaning it's been filed)
|
||||
*
|
||||
* @param Pirep $pirep
|
||||
* @param array $attrs
|
||||
* @param array PirepFieldValue[] $field_values
|
||||
* @param Pirep $pirep
|
||||
* @param array $attrs
|
||||
* @param PirepFieldValue[] $fields
|
||||
* @param PirepFare[] $fares
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @return Pirep
|
||||
*/
|
||||
public function file(Pirep $pirep, array $attrs = [], array $field_values = []): Pirep
|
||||
public function file(Pirep $pirep, array $attrs = [], array $fields = [], array $fares = []): Pirep
|
||||
{
|
||||
if (empty($field_values)) {
|
||||
$field_values = [];
|
||||
if (empty($fields)) {
|
||||
$fields = [];
|
||||
}
|
||||
|
||||
// Check if the PIREP has already been submitted
|
||||
@@ -319,9 +343,8 @@ class PirepService extends Service
|
||||
$pirep->save();
|
||||
$pirep->refresh();
|
||||
|
||||
if (count($field_values) > 0) {
|
||||
$this->updateCustomFields($pirep->id, $field_values);
|
||||
}
|
||||
$this->updateCustomFields($pirep->id, $fields);
|
||||
$this->fareSvc->saveForPirep($pirep, $fares);
|
||||
|
||||
return $pirep;
|
||||
}
|
||||
@@ -518,30 +541,41 @@ class PirepService extends Service
|
||||
*/
|
||||
public function delete(Pirep $pirep): void
|
||||
{
|
||||
$user_id = $pirep->user_id;
|
||||
|
||||
$w = ['pirep_id' => $pirep->id];
|
||||
PirepComment::where($w)->forceDelete();
|
||||
PirepFare::where($w)->forceDelete();
|
||||
PirepFieldValue::where($w)->forceDelete();
|
||||
SimBrief::where($w)->forceDelete();
|
||||
$pirep->forceDelete();
|
||||
|
||||
// Update the user's last PIREP
|
||||
$last_pirep = Pirep::where(['user_id' => $user_id, 'state' => PirepState::ACCEPTED])
|
||||
->latest('submitted_at')
|
||||
->first();
|
||||
|
||||
$user = User::find($user_id);
|
||||
$user->last_pirep_id = !empty($last_pirep) ? $last_pirep->id : null;
|
||||
$user->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update any custom PIREP fields
|
||||
*
|
||||
* @param $pirep_id
|
||||
* @param array $field_values
|
||||
* @param string $pirep_id
|
||||
* @param PirepFieldValue[] $field_values
|
||||
*/
|
||||
public function updateCustomFields($pirep_id, array $field_values)
|
||||
public function updateCustomFields(string $pirep_id, array $field_values): void
|
||||
{
|
||||
if (!$field_values || empty($field_values)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($field_values as $fv) {
|
||||
PirepFieldValue::updateOrCreate(
|
||||
['pirep_id' => $pirep_id,
|
||||
'name' => $fv['name'],
|
||||
],
|
||||
['value' => $fv['value'],
|
||||
'source' => $fv['source'],
|
||||
]
|
||||
['pirep_id' => $pirep_id, 'name' => $fv->name],
|
||||
['value' => $fv->value, 'source' => $fv->source]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -554,7 +588,7 @@ class PirepService extends Service
|
||||
*
|
||||
* @return Pirep
|
||||
*/
|
||||
public function changeState(Pirep $pirep, int $new_state)
|
||||
public function changeState(Pirep $pirep, int $new_state): Pirep
|
||||
{
|
||||
Log::info('PIREP '.$pirep->id.' state change from '.$pirep->state.' to '.$new_state);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Support;
|
||||
|
||||
use GuzzleHttp\Client as GuzzleClient;
|
||||
use GuzzleHttp\RequestOptions;
|
||||
|
||||
/**
|
||||
* Helper for HTTP stuff
|
||||
@@ -11,9 +12,8 @@ class HttpClient
|
||||
{
|
||||
private $httpClient;
|
||||
|
||||
public function __construct(
|
||||
GuzzleClient $httpClient
|
||||
) {
|
||||
public function __construct(GuzzleClient $httpClient)
|
||||
{
|
||||
$this->httpClient = $httpClient;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,29 @@ class HttpClient
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $uri
|
||||
* @param $body
|
||||
* @param array $opts
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function post($uri, $body, array $opts = [])
|
||||
{
|
||||
$opts = array_merge([
|
||||
'connect_timeout' => 2,
|
||||
RequestOptions::JSON => $body,
|
||||
], $opts);
|
||||
|
||||
$response = $this->httpClient->post($uri, $opts);
|
||||
$content_type = $response->getHeaderLine('content-type');
|
||||
if (strpos($content_type, 'application/json') !== false) {
|
||||
$body = \GuzzleHttp\json_decode($body, true);
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a file to a given path
|
||||
*
|
||||
|
||||
@@ -67,7 +67,8 @@
|
||||
"laravel/legacy-factories": "^1.1",
|
||||
"fakerphp/faker": "^v1.14",
|
||||
"wildbit/swiftmailer-postmark": "^3.3",
|
||||
"queueworker/sansdaemon": "^1.2"
|
||||
"queueworker/sansdaemon": "^1.2",
|
||||
"jpkleemans/attribute-events": "^1.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"barryvdh/laravel-debugbar": "^3.5",
|
||||
|
||||
573
composer.lock
generated
573
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -26,6 +26,7 @@ services:
|
||||
- ./composer-lock.json:/var/www/composer-lock.json
|
||||
- ./env.php:/var/www/env.php
|
||||
- ./resources/docker/php/www.conf:/usr/local/etc/php-fpm.d/www.conf
|
||||
- ./vendor/var/www/vendor
|
||||
depends_on:
|
||||
- mysql
|
||||
- redis
|
||||
|
||||
@@ -46,7 +46,7 @@ class FlightRouteAwards extends Award
|
||||
*/
|
||||
public function check($dptarr = null): bool
|
||||
{
|
||||
if ($this->user->last_pirep_id === null) {
|
||||
if ($this->user->last_pirep_id === null || empty($this->user->last_pirep)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Modules\Awards\Awards;
|
||||
|
||||
use App\Contracts\Award;
|
||||
use Log;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* All award classes need to extend Award and implement the check() method
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="col-md-12">
|
||||
<table class="table">
|
||||
<tr>
|
||||
<td>@lang('common.name')</td>
|
||||
<td>{{ __('common.name') }}</td>
|
||||
<td>
|
||||
<div class="input-group form-group-no-border{{ $errors->has('name') ? ' has-danger' : '' }}">
|
||||
{{ Form::text('name', null, ['class' => 'form-control']) }}
|
||||
@@ -14,7 +14,7 @@
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>@lang('common.email')</td>
|
||||
<td>{{ __('common.email') }}</td>
|
||||
<td>
|
||||
<div class="input-group form-group-no-border{{ $errors->has('email') ? ' has-danger' : '' }}">
|
||||
{{ Form::text('email', null, ['class' => 'form-control']) }}
|
||||
@@ -26,7 +26,22 @@
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>@lang('common.airline')</td>
|
||||
<td>Discord ID <span class="small">
|
||||
<a href="https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID-" target="_blank">
|
||||
How to find your ID</a></span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="input-group form-group-no-border{{ $errors->has('discord_id') ? ' has-danger' : '' }}">
|
||||
{{ Form::text('discord_id', null, ['class' => 'form-control']) }}
|
||||
</div>
|
||||
@if ($errors->has('discord_id'))
|
||||
<p class="text-danger">{{ $errors->first('discord_id') }}</p>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>{{ __('common.airline') }}</td>
|
||||
<td>
|
||||
<div class="input-group form-group-no-border{{ $errors->has('airline') ? ' has-danger' : '' }}">
|
||||
{{ Form::select('airline_id', $airlines, null , ['class' => 'form-control select2']) }}
|
||||
@@ -38,7 +53,7 @@
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>@lang('airports.home')</td>
|
||||
<td>{{ __('airports.home') }}</td>
|
||||
<td>
|
||||
<div class="input-group form-group-no-border{{ $errors->has('home_airport_id') ? ' has-danger' : '' }}">
|
||||
{{ Form::select('home_airport_id', $airports, null , ['class' => 'form-control select2']) }}
|
||||
@@ -50,7 +65,7 @@
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>@lang('common.country')</td>
|
||||
<td>{{ __('common.country') }}</td>
|
||||
<td>
|
||||
<div class="input-group form-group-no-border{{ $errors->has('country') ? ' has-danger' : '' }}">
|
||||
{{ Form::select('country', $countries, null, ['class' => 'form-control select2' ]) }}
|
||||
@@ -62,7 +77,7 @@
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>@lang('common.timezone')</td>
|
||||
<td>{{ __('common.timezone') }}</td>
|
||||
<td>
|
||||
<div class="input-group form-group-no-border{{ $errors->has('timezone') ? ' has-danger' : '' }}">
|
||||
{{ Form::select('timezone', $timezones, null, ['class' => 'form-control select2' ]) }}
|
||||
@@ -74,9 +89,9 @@
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>@lang('profile.changepassword')</td>
|
||||
<td>{{ __('profile.changepassword') }}</td>
|
||||
<td>
|
||||
<p>@lang('profile.newpassword'):</p>
|
||||
<p>{{ __('profile.newpassword') }}:</p>
|
||||
<div class="input-group form-group-no-border{{ $errors->has('password') ? ' has-danger' : '' }}">
|
||||
{{ Form::password('password', ['class' => 'form-control']) }}
|
||||
</div>
|
||||
@@ -84,7 +99,7 @@
|
||||
<p class="text-danger">{{ $errors->first('password') }}</p>
|
||||
@endif
|
||||
|
||||
<p>@lang('passwords.confirm'):</p>
|
||||
<p>{{ __('passwords.confirm') }}:</p>
|
||||
<div class="input-group form-group-no-border{{ $errors->has('password_confirmation') ? ' has-danger' : '' }}">
|
||||
{{ Form::password('password_confirmation', ['class' => 'form-control']) }}
|
||||
</div>
|
||||
@@ -94,14 +109,14 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>@lang('profile.avatar')</td>
|
||||
<td>{{ __('profile.avatar') }}</td>
|
||||
<td>
|
||||
<div class="input-group form-group-no-border{{ $errors->has('avatar') ? ' has-danger' : '' }}">
|
||||
{{ Form::file('avatar', null) }}
|
||||
</div>
|
||||
<p class="small">@lang('profile.avatarresize', [
|
||||
<p class="small">{{ __('profile.avatarresize', [
|
||||
'width' => config('phpvms.avatar.width'),
|
||||
'height' => config('phpvms.avatar.height')])
|
||||
'height' => config('phpvms.avatar.height')]) }}
|
||||
</p>
|
||||
@if ($errors->has('avatar'))
|
||||
<p class="text-danger">{{ $errors->first('avatar') }}</p>
|
||||
@@ -130,13 +145,13 @@
|
||||
@endforeach
|
||||
|
||||
<tr>
|
||||
<td>@lang('profile.opt-in')</td>
|
||||
<td>{{ __('profile.opt-in') }}</td>
|
||||
<td>
|
||||
<div class="input-group form-group-no-border">
|
||||
{{ Form::hidden('opt_in', 0, false) }}
|
||||
{{ Form::checkbox('opt_in', 1, null) }}
|
||||
</div>
|
||||
<p class="small">@lang('profile.opt-in-descrip')
|
||||
<p class="small">{{ __('profile.opt-in-descrip') }}
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -153,6 +153,10 @@
|
||||
<td>@lang('profile.apikey') <span class="description">(@lang('profile.dontshare'))</span></td>
|
||||
<td><span id="apiKey_show" style="display: none">{{ $user->api_key }} <i class="fas fa-eye-slash" onclick="apiKeyHide()"></i></span><span id="apiKey_hide">@lang('profile.apikey-show') <i class="fas fa-eye" onclick="apiKeyShow()"></i></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Discord ID</td>
|
||||
<td>{{ $user->discord_id ?? '-' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>@lang('common.timezone')</td>
|
||||
<td>{{ $user->timezone }}</td>
|
||||
@@ -174,7 +178,7 @@
|
||||
@if(!$field->private)
|
||||
<tr>
|
||||
<td>{{ $field->name }}</td>
|
||||
<td>{{ $field->value }}</td>
|
||||
<td>{{ $field->value ?? '-'}}</td>
|
||||
</tr>
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
@@ -450,6 +450,7 @@ class AcarsTest extends TestCase
|
||||
'level' => 38000,
|
||||
'planned_distance' => 400,
|
||||
'planned_flight_time' => 120,
|
||||
'status' => PirepStatus::BOARDING,
|
||||
'route' => 'POINTA POINTB',
|
||||
'source_name' => 'AcarsTest::testAcarsUpdates',
|
||||
'fields' => [
|
||||
@@ -487,6 +488,8 @@ class AcarsTest extends TestCase
|
||||
$uri = '/api/pireps/'.$pirep_id.'/update';
|
||||
$this->post($uri, [
|
||||
'flight_time' => 60,
|
||||
'distance' => 20,
|
||||
'status' => PirepStatus::AIRBORNE,
|
||||
'fields' => [
|
||||
'custom_field' => 'custom_value_changed',
|
||||
],
|
||||
|
||||
@@ -14,6 +14,7 @@ trait CreatesApplication
|
||||
public function createApplication()
|
||||
{
|
||||
$app = require __DIR__.'/../bootstrap/app.php';
|
||||
$app->loadEnvironmentFrom('');
|
||||
$app->make(Kernel::class)->bootstrap();
|
||||
|
||||
return $app;
|
||||
|
||||
@@ -13,6 +13,7 @@ use App\Models\Flight;
|
||||
use App\Models\Journal;
|
||||
use App\Models\JournalTransaction;
|
||||
use App\Models\Pirep;
|
||||
use App\Models\PirepFare;
|
||||
use App\Models\Subfleet;
|
||||
use App\Models\User;
|
||||
use App\Repositories\ExpenseRepository;
|
||||
@@ -763,11 +764,10 @@ class FinanceTest extends TestCase
|
||||
// Override the fares
|
||||
$fare_counts = [];
|
||||
foreach ($fares as $fare) {
|
||||
$fare_counts[] = [
|
||||
$fare_counts[] = new PirepFare([
|
||||
'fare_id' => $fare->id,
|
||||
'price' => $fare->price,
|
||||
'count' => round($fare->capacity / 2),
|
||||
];
|
||||
]);
|
||||
}
|
||||
|
||||
$this->fareSvc->saveForPirep($pirep, $fare_counts);
|
||||
@@ -777,7 +777,7 @@ class FinanceTest extends TestCase
|
||||
foreach ($all_fares as $fare) {
|
||||
$set_fare = $fare_counts->where('fare_id', $fare->id)->first();
|
||||
$this->assertEquals($set_fare['count'], $fare->count);
|
||||
$this->assertEquals($set_fare['price'], $fare->price);
|
||||
$this->assertNotEmpty($fare->price);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -892,11 +892,10 @@ class FinanceTest extends TestCase
|
||||
// Override the fares
|
||||
$fare_counts = [];
|
||||
foreach ($fares as $fare) {
|
||||
$fare_counts[] = [
|
||||
$fare_counts[] = new PirepFare([
|
||||
'fare_id' => $fare->id,
|
||||
'price' => $fare->price,
|
||||
'count' => 100,
|
||||
];
|
||||
]);
|
||||
}
|
||||
|
||||
$this->fareSvc->saveForPirep($pirep, $fare_counts);
|
||||
@@ -948,11 +947,10 @@ class FinanceTest extends TestCase
|
||||
// Override the fares
|
||||
$fare_counts = [];
|
||||
foreach ($fares as $fare) {
|
||||
$fare_counts[] = [
|
||||
$fare_counts[] = new PirepFare([
|
||||
'fare_id' => $fare->id,
|
||||
'price' => $fare->price,
|
||||
'count' => 100,
|
||||
];
|
||||
]);
|
||||
}
|
||||
|
||||
$this->fareSvc->saveForPirep($pirep, $fare_counts);
|
||||
@@ -1074,11 +1072,11 @@ class FinanceTest extends TestCase
|
||||
// Override the fares
|
||||
$fare_counts = [];
|
||||
foreach ($fares as $fare) {
|
||||
$fare_counts[] = [
|
||||
$fare_counts[] = new PirepFare([
|
||||
'fare_id' => $fare->id,
|
||||
'price' => $fare->price,
|
||||
'count' => 100,
|
||||
];
|
||||
]);
|
||||
}
|
||||
|
||||
$this->fareSvc->saveForPirep($pirep, $fare_counts);
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Tests;
|
||||
|
||||
use App\Events\UserRegistered;
|
||||
use App\Models\Enums\UserState;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
@@ -26,7 +27,7 @@ class RegistrationTest extends TestCase
|
||||
|
||||
setting('pilots.auto_accept', true);
|
||||
|
||||
$attrs = factory(\App\Models\User::class)->make()->toArray();
|
||||
$attrs = factory(User::class)->make()->toArray();
|
||||
$attrs['password'] = Hash::make('secret');
|
||||
$user = $userSvc->createUser($attrs);
|
||||
|
||||
|
||||
@@ -57,11 +57,10 @@ abstract class TestCase extends \Illuminate\Foundation\Testing\TestCase
|
||||
ThrottleRequests::class
|
||||
);
|
||||
|
||||
Notification::fake();
|
||||
|
||||
Artisan::call('database:create', ['--reset' => true]);
|
||||
Artisan::call('migrate:refresh', ['--env' => 'testing', '--force' => true]);
|
||||
|
||||
Notification::fake();
|
||||
// $this->disableExceptionHandling();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user