mirror of
https://github.com/HolgerHatGarKeineNode/einundzwanzig-app.git
synced 2026-03-21 04:18:40 +00:00
🛠️ Remove deprecated Forge deployment workflow, add logic for fetching missing highscore names via Nostr, and update API routes with refined highscore endpoints.
This commit is contained in:
19
.github/workflows/deploy_on_forge.yml
vendored
19
.github/workflows/deploy_on_forge.yml
vendored
@@ -1,19 +0,0 @@
|
|||||||
name: 'Deploy on push'
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
forge-deploy:
|
|
||||||
name: 'Laravel Forge Deploy'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
environment: production
|
|
||||||
|
|
||||||
steps:
|
|
||||||
# Trigger Laravel Forge Deploy
|
|
||||||
- name: Deploy
|
|
||||||
uses: jbrooksuk/laravel-forge-action@v1.0.2
|
|
||||||
with:
|
|
||||||
trigger_url: ${{ secrets.TRIGGER_URL }}
|
|
||||||
@@ -8,6 +8,12 @@ use App\Models\Highscore;
|
|||||||
use Carbon\CarbonImmutable;
|
use Carbon\CarbonImmutable;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use swentel\nostr\Filter\Filter;
|
||||||
|
use swentel\nostr\Message\RequestMessage;
|
||||||
|
use swentel\nostr\Relay\Relay;
|
||||||
|
use swentel\nostr\Relay\RelaySet;
|
||||||
|
use swentel\nostr\Request\Request;
|
||||||
|
use swentel\nostr\Subscription\Subscription;
|
||||||
|
|
||||||
class HighscoreController extends Controller
|
class HighscoreController extends Controller
|
||||||
{
|
{
|
||||||
@@ -50,6 +56,14 @@ class HighscoreController extends Controller
|
|||||||
|
|
||||||
$highscore->save();
|
$highscore->save();
|
||||||
|
|
||||||
|
if (empty($highscore->name)) {
|
||||||
|
$fetchedName = $this->fetchNostrName($highscore->npub);
|
||||||
|
if ($fetchedName) {
|
||||||
|
$highscore->name = $fetchedName;
|
||||||
|
$highscore->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Log::info('Highscore submission received', [
|
Log::info('Highscore submission received', [
|
||||||
'npub' => $highscore->npub,
|
'npub' => $highscore->npub,
|
||||||
'name' => $highscore->name,
|
'name' => $highscore->name,
|
||||||
@@ -69,4 +83,64 @@ class HighscoreController extends Controller
|
|||||||
],
|
],
|
||||||
], 202);
|
], 202);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function fetchNostrName(string $npub): ?string
|
||||||
|
{
|
||||||
|
$author = trim($npub);
|
||||||
|
|
||||||
|
if (! str_starts_with($author, 'npub1')) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$subscription = new Subscription;
|
||||||
|
$filter = new Filter;
|
||||||
|
$filter->setAuthors([$author]);
|
||||||
|
$filter->setKinds([0]);
|
||||||
|
|
||||||
|
$requestMessage = new RequestMessage($subscription->getId(), [$filter]);
|
||||||
|
$relaySet = new RelaySet;
|
||||||
|
$relaySet->setRelays([
|
||||||
|
new Relay('wss://nos.lol'),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$request = new Request($relaySet, $requestMessage);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = $request->send();
|
||||||
|
|
||||||
|
foreach ($response as $relayUrl => $relayResponses) {
|
||||||
|
foreach ($relayResponses as $message) {
|
||||||
|
if (! isset($message->event)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$profile = json_decode($message->event->content, true, 512, JSON_THROW_ON_ERROR);
|
||||||
|
|
||||||
|
if (isset($profile['name']) && is_string($profile['name']) && $profile['name'] !== '') {
|
||||||
|
Log::info('Fetched nostr profile name for highscore', [
|
||||||
|
'npub' => $author,
|
||||||
|
'relay' => $relayUrl,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $profile['name'];
|
||||||
|
}
|
||||||
|
} catch (\JsonException $e) {
|
||||||
|
Log::warning('Failed to decode nostr profile for highscore', [
|
||||||
|
'npub' => $author,
|
||||||
|
'relay' => $relayUrl,
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::warning('Failed to fetch nostr profile for highscore', [
|
||||||
|
'npub' => $author,
|
||||||
|
'error' => $e->getMessage(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ Route::middleware([])
|
|||||||
Route::resource('courses', CourseController::class);
|
Route::resource('courses', CourseController::class);
|
||||||
Route::resource('cities', CityController::class);
|
Route::resource('cities', CityController::class);
|
||||||
Route::resource('venues', VenueController::class);
|
Route::resource('venues', VenueController::class);
|
||||||
|
Route::get('highscores', [HighscoreController::class, 'index'])->name('highscores.index');
|
||||||
|
Route::post('highscores', [HighscoreController::class, 'store'])->name('highscores.store');
|
||||||
Route::get('nostrplebs', function () {
|
Route::get('nostrplebs', function () {
|
||||||
return User::query()
|
return User::query()
|
||||||
->select([
|
->select([
|
||||||
@@ -185,6 +187,3 @@ Route::get('/lnurl-auth-callback', [\App\Http\Controllers\LnurlAuthController::c
|
|||||||
|
|
||||||
Route::post('/check-auth-error', [\App\Http\Controllers\LnurlAuthController::class, 'checkError'])
|
Route::post('/check-auth-error', [\App\Http\Controllers\LnurlAuthController::class, 'checkError'])
|
||||||
->name('auth.check-error');
|
->name('auth.check-error');
|
||||||
|
|
||||||
Route::get('highscores', [HighscoreController::class, 'index'])->name('highscores.index');
|
|
||||||
Route::post('highscores', [HighscoreController::class, 'store'])->name('highscores.store');
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Http\Controllers\Api\HighscoreController;
|
||||||
use App\Models\Highscore;
|
use App\Models\Highscore;
|
||||||
use Carbon\CarbonImmutable;
|
use Carbon\CarbonImmutable;
|
||||||
|
|
||||||
@@ -66,6 +67,35 @@ test('highscore submission updates existing attempt for same npub and datetime',
|
|||||||
$this->assertSame(1, Highscore::query()->count());
|
$this->assertSame(1, Highscore::query()->count());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('missing name is fetched from nostr when available', function () {
|
||||||
|
$fetchedName = 'Fetched Player';
|
||||||
|
|
||||||
|
$controllerMock = \Mockery::mock(HighscoreController::class)->makePartial();
|
||||||
|
$controllerMock->shouldAllowMockingProtectedMethods();
|
||||||
|
$controllerMock->shouldReceive('fetchNostrName')->once()->andReturn($fetchedName);
|
||||||
|
|
||||||
|
app()->instance(HighscoreController::class, $controllerMock);
|
||||||
|
|
||||||
|
$payload = [
|
||||||
|
'npub' => 'npub1fetchnamevalue',
|
||||||
|
'satoshis' => 1337,
|
||||||
|
'blocks' => 2,
|
||||||
|
'datetime' => CarbonImmutable::now()->subMinute()->toIso8601String(),
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = $this->postJson(route('api.highscores.store'), $payload);
|
||||||
|
|
||||||
|
$response->assertAccepted()
|
||||||
|
->assertJsonPath('data.name', $fetchedName);
|
||||||
|
|
||||||
|
$this->assertDatabaseHas('highscores', [
|
||||||
|
'npub' => $payload['npub'],
|
||||||
|
'name' => $fetchedName,
|
||||||
|
'satoshis' => $payload['satoshis'],
|
||||||
|
'blocks' => $payload['blocks'],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
test('highscore submission does not clear existing name when omitted', function () {
|
test('highscore submission does not clear existing name when omitted', function () {
|
||||||
$datetime = CarbonImmutable::now()->subMinutes(15);
|
$datetime = CarbonImmutable::now()->subMinutes(15);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user