diff --git a/app/Mod/Names/Controllers/NamesController.php b/app/Mod/Names/Controllers/NamesController.php index ddee12e..164bc18 100644 --- a/app/Mod/Names/Controllers/NamesController.php +++ b/app/Mod/Names/Controllers/NamesController.php @@ -497,6 +497,14 @@ class NamesController extends Controller 'email' => $claim->email, ]); + // Send approval notification email (queued, non-blocking) + try { + \Illuminate\Support\Facades\Mail::to($claim->email) + ->send(new \Mod\Names\Mail\ClaimApproved($claim)); + } catch (\Throwable $e) { + // Email delivery failure shouldn't break approval + } + return response()->json([ 'claim_id' => $claim->claim_id, 'name' => $claim->name, diff --git a/app/Mod/Names/Controllers/OgImageController.php b/app/Mod/Names/Controllers/OgImageController.php new file mode 100644 index 0000000..744869e --- /dev/null +++ b/app/Mod/Names/Controllers/OgImageController.php @@ -0,0 +1,64 @@ +getAliasByName(strtolower(trim($name))); + + $type = 'Available'; + $typeColour = '#34d399'; + + if ($alias) { + $comment = $alias['comment'] ?? ''; + if (str_contains($comment, 'type=reserved')) { + $type = 'Reserved'; + $typeColour = '#fbbf24'; + } elseif (str_contains($comment, 'type=gateway')) { + $type = 'Gateway'; + $typeColour = '#34d399'; + } else { + $type = 'Registered'; + $typeColour = '#818cf8'; + } + } + + $escapedName = htmlspecialchars($name, ENT_XML1); + + $svg = << + + + + + {$escapedName}.lthn + + + + {$type} + + Blockchain domain name on the Lethean network + + lthn.io + Lethean CIC + + SVG; + + return response($svg, 200)->header('Content-Type', 'image/svg+xml') + ->header('Cache-Control', 'public, max-age=3600'); + } +} diff --git a/app/Mod/Names/Mail/ClaimApproved.php b/app/Mod/Names/Mail/ClaimApproved.php new file mode 100644 index 0000000..33a081a --- /dev/null +++ b/app/Mod/Names/Mail/ClaimApproved.php @@ -0,0 +1,66 @@ +email)->send(new ClaimApproved($claim)); + */ +class ClaimApproved extends Mailable +{ + public function __construct( + public readonly NameClaim $claim, + ) {} + + public function envelope(): Envelope + { + return new Envelope( + subject: "{$this->claim->name}.lthn — Your Name Claim Has Been Approved", + ); + } + + public function content(): Content + { + return new Content( + htmlString: $this->buildHtml(), + ); + } + + private function buildHtml(): string + { + $name = e($this->claim->name); + $fqdn = "{$name}.lthn"; + + return << +

Your .lthn Name is Ready

+

Great news — your claim for {$fqdn} has been approved and registered on the Lethean blockchain.

+ +
+

Name

+

{$fqdn}

+
+ +

What's Next?

+ + +

+ Lethean CIC — Community Interest Company
+ lthn.io +

+ + HTML; + } +} diff --git a/app/Mod/Names/Routes/web.php b/app/Mod/Names/Routes/web.php index 4ca7ff9..b862722 100644 --- a/app/Mod/Names/Routes/web.php +++ b/app/Mod/Names/Routes/web.php @@ -7,4 +7,5 @@ use Mod\Names\Controllers\NamesWebController; Route::get('/', [NamesWebController::class, 'index']); Route::get('/register', [NamesWebController::class, 'register']); +Route::get('/{name}/og.svg', \Mod\Names\Controllers\OgImageController::class); Route::get('/{name}', [NamesWebController::class, 'show']); diff --git a/app/Mod/Names/Views/show.blade.php b/app/Mod/Names/Views/show.blade.php index e984649..85e52d0 100644 --- a/app/Mod/Names/Views/show.blade.php +++ b/app/Mod/Names/Views/show.blade.php @@ -3,6 +3,12 @@ @section('title', $name . '.lthn') @section('meta_description', $name . '.lthn — blockchain domain name registered on the Lethean network. ' . ($alias['comment'] ?? '')) +@push('head') + + + +@endpush + @section('content')

{{ $name }}.lthn

diff --git a/app/Website/Lethean/Views/layout.blade.php b/app/Website/Lethean/Views/layout.blade.php index 2d40057..ee9183f 100644 --- a/app/Website/Lethean/Views/layout.blade.php +++ b/app/Website/Lethean/Views/layout.blade.php @@ -97,6 +97,7 @@ code { background: var(--surface); padding: 0.125rem 0.375rem; border-radius: 0.25rem; font-size: 0.85em; } + @stack('head')