'^npub1.*'])] public function media($npub, NostrClient $nostrClient, RedisCacheService $redisCacheService): Response { $keys = new Key(); $pubkey = $keys->convertToHex($npub); $author = $redisCacheService->getMetadata($npub); // Retrieve picture events (kind 20) for the author try { $pictureEvents = $nostrClient->getPictureEventsForPubkey($npub, 30); } catch (Exception $e) { $pictureEvents = []; } // Deduplicate by event ID $uniqueEvents = []; foreach ($pictureEvents as $event) { if (!isset($uniqueEvents[$event->id])) { $uniqueEvents[$event->id] = $event; } } // Convert back to indexed array and sort by date (newest first) $pictureEvents = array_values($uniqueEvents); usort($pictureEvents, function ($a, $b) { return $b->created_at <=> $a->created_at; }); // Encode event IDs as note1... for each event foreach ($pictureEvents as $event) { $nip19 = new Nip19Helper(); // The NIP-19 helper class. $event->noteId = $nip19->encodeNote($event->id); } return $this->render('pages/author-media.html.twig', [ 'author' => $author, 'npub' => $npub, 'pictureEvents' => $pictureEvents, 'is_author_profile' => true, ]); } /** * @throws Exception */ #[Route('/p/{npub}/about', name: 'author-about', requirements: ['npub' => '^npub1.*'])] public function about($npub, RedisCacheService $redisCacheService): Response { $keys = new Key(); $pubkey = $keys->convertToHex($npub); // Get metadata with raw event for debugging $profileData = $redisCacheService->getMetadataWithRawEvent($npub); $author = $profileData['metadata']; $rawEvent = $profileData['rawEvent']; return $this->render('pages/author-about.html.twig', [ 'author' => $author, 'npub' => $npub, 'pubkey' => $pubkey, 'rawEvent' => $rawEvent, 'is_author_profile' => true, ]); } /** * @throws Exception */ #[Route('/p/{npub}', name: 'author-profile', requirements: ['npub' => '^npub1.*'])] public function index($npub, NostrClient $nostrClient, RedisCacheService $redisCacheService, FinderInterface $finder): Response { $keys = new Key(); $pubkey = $keys->convertToHex($npub); $author = $redisCacheService->getMetadata($npub); // Retrieve long-form content for the author try { $list = $nostrClient->getLongFormContentForPubkey($npub); } catch (Exception $e) { $list = []; } // Also look for articles in the Elastica index $query = new Terms('pubkey', [$pubkey]); $list = array_merge($list, $finder->find($query, 25)); // Sort articles by date usort($list, function ($a, $b) { return $b->getCreatedAt() <=> $a->getCreatedAt(); }); $articles = []; // Deduplicate by slugs foreach ($list as $item) { if (!key_exists((string) $item->getSlug(), $articles)) { $articles[(string) $item->getSlug()] = $item; } } return $this->render('pages/author.html.twig', [ 'author' => $author, 'npub' => $npub, 'articles' => $articles, 'is_author_profile' => true, ]); } /** * @throws Exception */ #[Route('/p/{pubkey}', name: 'author-redirect')] public function authorRedirect($pubkey): Response { $keys = new Key(); $npub = $keys->convertPublicKeyToBech32($pubkey); return $this->redirectToRoute('author-profile', ['npub' => $npub]); } }