clone of github.com/decent-newsroom/newsroom
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

140 lines
4.4 KiB

<?php
declare(strict_types=1);
namespace App\Controller;
use App\Service\NostrClient;
use App\Service\RedisCacheService;
use Elastica\Query\Terms;
use Exception;
use FOS\ElasticaBundle\Finder\FinderInterface;
use swentel\nostr\Key\Key;
use swentel\nostr\Nip19\Nip19Helper;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class AuthorController extends AbstractController
{
/**
* @throws Exception
*/
#[Route('/p/{npub}/media', name: 'author-media', requirements: ['npub' => '^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]);
}
}