diff --git a/app/Mail/WeeklyDigest.php b/app/Mail/WeeklyDigest.php new file mode 100644 index 0000000..b1f6440 --- /dev/null +++ b/app/Mail/WeeklyDigest.php @@ -0,0 +1,34 @@ +view('emails.weekly-digest') + ->subject('Weekly Digest'); + } +} diff --git a/composer.json b/composer.json index 229fe3b..735e41c 100644 --- a/composer.json +++ b/composer.json @@ -1,8 +1,8 @@ { - "name": "laravel/laravel", + "name": "rumperuu/bentracker", "type": "project", - "description": "The Laravel Framework.", - "keywords": ["framework", "laravel"], + "description": "A Web app. for tracking my travels.", + "keywords": ["travel", "laravel"], "license": "MIT", "require": { "php": "^8.0.2", @@ -10,7 +10,9 @@ "laravel/framework": "^9.19", "laravel/sanctum": "^3.0", "laravel/tinker": "^2.7", - "larswiegers/laravel-maps": "^0.12.0" + "larswiegers/laravel-maps": "^0.12.0", + "mailjet/laravel-mailjet": "^3.0", + "symfony/http-client": "^6.1" }, "require-dev": { "fakerphp/faker": "^1.9.1", diff --git a/composer.lock b/composer.lock index e43694e..533701c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "2352b8039a1d97d54047acb2dc1032a0", + "content-hash": "44109efc12ef74a29f8aa0c4886fb3d2", "packages": [ { "name": "brick/math", @@ -1706,6 +1706,142 @@ ], "time": "2022-04-17T13:12:02+00:00" }, + { + "name": "mailjet/laravel-mailjet", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/mailjet/laravel-mailjet.git", + "reference": "f1c2ab525c2f99e05b3e811bda9561a9115fd302" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mailjet/laravel-mailjet/zipball/f1c2ab525c2f99e05b3e811bda9561a9115fd302", + "reference": "f1c2ab525c2f99e05b3e811bda9561a9115fd302", + "shasum": "" + }, + "require": { + "laravel/framework": "~5.1|^6.0|^7.0|^8.0|^9.0", + "mailjet/mailjet-apiv3-php": "^1.5.6", + "php": "^7.1.3|^8.0", + "symfony/mailjet-mailer": "^6.0" + }, + "require-dev": { + "fakerphp/faker": "~1", + "mockery/mockery": "0.9.*|^1.0", + "orchestra/testbench": "3.6|^4.0|^5.0|^6.0", + "phpunit/phpunit": "~7.0|^8.0|^9" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Mailjet\\LaravelMailjet\\MailjetServiceProvider" + ], + "aliases": { + "Mailjet": "Mailjet\\LaravelMailjet\\Facades\\Mailjet" + } + } + }, + "autoload": { + "psr-4": { + "Mailjet\\LaravelMailjet\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gaetan DELBART", + "email": "gaetan@moltencore.io", + "homepage": "https://github.com/gagaXD" + }, + { + "name": "Titouan BENOIT", + "email": "titouan.benoit@gmx.fr", + "homepage": "https://github.com/Nightbr" + }, + { + "name": "Mailjet API", + "email": "api@mailjet.com", + "homepage": "https://dev.mailjet.com/" + } + ], + "description": "Laravel package for Mailjet API V3 and Laravel Mailjet Mail Transport", + "homepage": "https://github.com/mailjet/laravel-mailjet", + "keywords": [ + "Mailjet", + "framework", + "laravel", + "mailjet API", + "mailjet wrapper", + "transport" + ], + "support": { + "issues": "https://github.com/mailjet/laravel-mailjet/issues", + "source": "https://github.com/mailjet/laravel-mailjet/tree/3.0.3" + }, + "time": "2022-07-06T16:41:42+00:00" + }, + { + "name": "mailjet/mailjet-apiv3-php", + "version": "v1.5.8", + "source": { + "type": "git", + "url": "https://github.com/mailjet/mailjet-apiv3-php.git", + "reference": "747518ce0eebf64d27e9903441a255c85472a139" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mailjet/mailjet-apiv3-php/zipball/747518ce0eebf64d27e9903441a255c85472a139", + "reference": "747518ce0eebf64d27e9903441a255c85472a139", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/guzzle": "^7.4.4", + "php": "^7.2|^8.0", + "psr/http-client": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^1.4", + "php-coveralls/php-coveralls": "^2.0", + "phpunit/phpunit": "^8|^9" + }, + "type": "library", + "autoload": { + "psr-0": { + "Mailjet": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mailjet", + "email": "dev@mailjet.com", + "homepage": "https://dev.mailjet.com" + } + ], + "description": "PHP wrapper for the Mailjet API", + "homepage": "https://github.com/mailjet/mailjet-apiv3-php/", + "keywords": [ + "Mailjet", + "api", + "email", + "php", + "v3" + ], + "support": { + "issues": "https://github.com/mailjet/mailjet-apiv3-php/issues", + "source": "https://github.com/mailjet/mailjet-apiv3-php/tree/v1.5.8" + }, + "time": "2022-10-15T16:24:08+00:00" + }, { "name": "monolog/monolog", "version": "2.8.0", @@ -3455,6 +3591,171 @@ ], "time": "2022-07-29T07:42:06+00:00" }, + { + "name": "symfony/http-client", + "version": "v6.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client.git", + "reference": "c8c887f4813370550147afd27d9eb8a8523e53b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client/zipball/c8c887f4813370550147afd27d9eb8a8523e53b2", + "reference": "c8c887f4813370550147afd27d9eb8a8523e53b2", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^1|^2|^3", + "symfony/http-client-contracts": "^3", + "symfony/service-contracts": "^1.0|^2|^3" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "1.0", + "symfony/http-client-implementation": "3.0" + }, + "require-dev": { + "amphp/amp": "^2.5", + "amphp/http-client": "^4.2.1", + "amphp/http-tunnel": "^1.0", + "amphp/socket": "^1.1", + "guzzlehttp/promises": "^1.4", + "nyholm/psr7": "^1.0", + "php-http/httplug": "^1.0|^2.0", + "psr/http-client": "^1.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/stopwatch": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-client/tree/v6.1.6" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-10-12T05:10:31+00:00" + }, + { + "name": "symfony/http-client-contracts", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client-contracts.git", + "reference": "fd038f08c623ab5d22b26e9ba35afe8c79071800" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/fd038f08c623ab5d22b26e9ba35afe8c79071800", + "reference": "fd038f08c623ab5d22b26e9ba35afe8c79071800", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "suggest": { + "symfony/http-client-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.1-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to HTTP clients", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/http-client-contracts/tree/v3.1.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-04-22T07:30:54+00:00" + }, { "name": "symfony/http-foundation", "version": "v6.1.3", @@ -3711,6 +4012,71 @@ ], "time": "2022-07-27T15:50:51+00:00" }, + { + "name": "symfony/mailjet-mailer", + "version": "v6.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/mailjet-mailer.git", + "reference": "a538f1d86b71107daaff2691094c877edf54e5ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mailjet-mailer/zipball/a538f1d86b71107daaff2691094c877edf54e5ef", + "reference": "a538f1d86b71107daaff2691094c877edf54e5ef", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/mailer": "^5.4|^6.0" + }, + "require-dev": { + "symfony/http-client": "^5.4|^6.0" + }, + "type": "symfony-mailer-bridge", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mailer\\Bridge\\Mailjet\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Mailjet Mailer Bridge", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/mailjet-mailer/tree/v6.1.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-09-27T10:43:34+00:00" + }, { "name": "symfony/mime", "version": "v6.1.3", diff --git a/config/app.php b/config/app.php index 7cffa1e..488f557 100644 --- a/config/app.php +++ b/config/app.php @@ -197,6 +197,10 @@ return [ App\Providers\EventServiceProvider::class, App\Providers\RouteServiceProvider::class, + /* + * Mail Service Providers... + */ + Mailjet\LaravelMailjet\MailjetServiceProvider::class, ], /* @@ -211,7 +215,7 @@ return [ */ 'aliases' => Facade::defaultAliases()->merge([ - // 'ExampleClass' => App\Example\ExampleClass::class, + 'Mailjet' => Mailjet\LaravelMailjet\Facades\Mailjet::class, ])->toArray(), ]; diff --git a/config/mail.php b/config/mail.php index 534395a..3239339 100644 --- a/config/mail.php +++ b/config/mail.php @@ -62,6 +62,10 @@ return [ 'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -bs -i'), ], + 'mailjet' => [ + 'transport' => 'mailjet', + ], + 'log' => [ 'transport' => 'log', 'channel' => env('MAIL_LOG_CHANNEL'), diff --git a/config/services.php b/config/services.php index 0ace530..004f0c2 100644 --- a/config/services.php +++ b/config/services.php @@ -14,21 +14,9 @@ return [ | */ - 'mailgun' => [ - 'domain' => env('MAILGUN_DOMAIN'), - 'secret' => env('MAILGUN_SECRET'), - 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), - 'scheme' => 'https', - ], - - 'postmark' => [ - 'token' => env('POSTMARK_TOKEN'), - ], - - 'ses' => [ - 'key' => env('AWS_ACCESS_KEY_ID'), - 'secret' => env('AWS_SECRET_ACCESS_KEY'), - 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), - ], + 'mailjet' => [ + 'key' => env('MAILJET_APIKEY'), + 'secret' => env('MAILJET_APISECRET'), + ] ]; diff --git a/resources/views/emails/weekly-digest.blade.php b/resources/views/emails/weekly-digest.blade.php new file mode 100644 index 0000000..100d283 --- /dev/null +++ b/resources/views/emails/weekly-digest.blade.php @@ -0,0 +1 @@ +

Hello, world

diff --git a/resources/views/past-trips.blade.php b/resources/views/past-trips.blade.php index 93b142b..15a7609 100644 --- a/resources/views/past-trips.blade.php +++ b/resources/views/past-trips.blade.php @@ -26,9 +26,10 @@
- +
diff --git a/routes/web.php b/routes/web.php index 1b61799..500d22a 100644 --- a/routes/web.php +++ b/routes/web.php @@ -2,39 +2,53 @@ use GuzzleHttp\Client; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Storage; +use App\Mail\WeeklyDigest; +use Illuminate\Support\Facades\Mail; Route::get('/past-trips', function () { return view('past-trips'); }); Route::get('/{tripId?}', function (Request $request, $tripId = null) { + //Mail::to('me@bengoldsworthy.net')->send(new WeeklyDigest()); + if (!$tripId && !config('app.current_trip_id')) return view('no-trip'); $viewMode = $request->input('show', null); - /* - * If there is a file in the local cache that is less than 1–3 hours old - * (depending on whether it was actively tracking at last check), use that. - */ + // If there is a file in the local cache that is less than 1–3 hours old + // (depending on whether it was actively tracking at last check), use that. $tripFileName = ( $tripId ?? config('app.current_trip_id') ) . '.json'; + if (Storage::disk('local')->exists($tripFileName)) { - $cachedData = json_decode(Storage::disk('local')->get($tripFileName)); - if ($cachedData->trip->is_active) { - $cachedDataUpdatedAt = new DateTime($cachedData->trip->updated_at); + Log::debug("Cached trip file '{$tripFileName}' found..."); + $cachedData = json_decode(Storage::disk('local')->get($tripFileName))->trip; + + if ($cachedData->is_active) { + Log::debug("Cached trip file '{$tripFileName}' is for an active trip."); + + $cachedDataUpdatedAt = new DateTime($cachedData->updated_at); $now = new DateTime(); - if (intval(($now->getTimestamp() - $cachedDataUpdatedAt->getTimestamp()) / 3600) <= ($cachedData->trip->is_tracking) ? 1 : 3) { - return view('tracker', ['trip' => $cachedData->trip, 'showAllCheckins' => ($viewMode === 'all')]); + $cachingTimeout = ($cachedData->is_tracking) ? 1 : 3; + $cachedDataAge = intval(($now->getTimestamp() - $cachedDataUpdatedAt->getTimestamp()) / 3600); + + if ($cachedDataAge <= $cachingTimeout) { + Log::debug("Cached trip file '{$tripFileName}' is younger than {$cachingTimeout} hours, showing from cache..."); + return view('tracker', ['trip' => $cachedData, 'showAllCheckins' => ($viewMode === 'all')]); } } else { - return view('tracker', ['trip' => $cachedData->trip, 'showAllCheckins' => ($viewMode === 'all')]); + Log::debug("Cached trip file '{$tripFileName}' is for an old trip, showing from cache..."); + return view('tracker', ['trip' => $cachedData, 'showAllCheckins' => ($viewMode === 'all')]); } } /* * Otherwise, download the latest tracking data. */ + Log::debug("No cached trip file found for '{$tripFileName}'."); $client = new Client([ 'base_uri' => 'https://app.wayward.travel/', 'timeout' => 3.0 @@ -46,19 +60,23 @@ Route::get('/{tripId?}', function (Request $request, $tripId = null) { // Cache the downloaded file if it does not exist locally. if (Storage::disk('local')->missing($tripFileName)) { + Log::debug("Caching new trip file '{$tripFileName}'."); Storage::disk('local')->put($tripFileName, json_encode($data)); } else { $cachedData = json_decode(Storage::disk('local')->get($tripFileName)); if ($data->trip->updated_at !== $cachedData->trip->updated_at) { + Log::debug("Cached trip file '{$tripFileName}' has different 'updated_at' time, updating cache..."); Storage::disk('local')->put($tripFileName, json_encode($data)); // TODO: Cache photos locally } else { + Log::debug("Cached trip file '{$tripFileName}' has same 'updated_at' time, showing from cache..."); $data = $cachedData; } } return view('tracker', ['trip' => $data->trip, 'showAllCheckins' => ($viewMode === 'all')]); } else { + // TODO: Return proper error return 'Something went wrong'; } })->where('tripId', '[0-9a-z]{20}');