Browse Source

Downsizing: remove Redis

imwald
Nuša Pukšič 9 months ago
parent
commit
c4207be173
  1. 4
      .env.dist
  2. 1
      Dockerfile
  3. 1
      composer.json
  4. 11
      config/packages/cache.yaml
  5. 14
      config/services.yaml
  6. 6
      docker/cron/Dockerfile
  7. 10
      src/Controller/ArticleController.php
  8. 6
      src/Controller/AuthorController.php
  9. 6
      src/Controller/EventController.php
  10. 8
      src/Security/UserDTOProvider.php
  11. 70
      src/Service/RedisCacheService.php
  12. 4
      src/Twig/Components/Header.php
  13. 19
      src/Twig/Components/Molecules/CategoryLink.php
  14. 6
      src/Twig/Components/Molecules/UserFromNpub.php
  15. 4
      src/Twig/Components/Organisms/FeaturedList.php
  16. 10
      src/Util/CommonMark/Converter.php
  17. 7
      src/Util/CommonMark/NostrSchemeExtension/NostrMentionParser.php
  18. 6
      src/Util/CommonMark/NostrSchemeExtension/NostrRawNpubParser.php
  19. 8
      src/Util/CommonMark/NostrSchemeExtension/NostrSchemeExtension.php

4
.env.dist

@ -43,10 +43,6 @@ MERCURE_PUBLIC_URL=https://${SERVER_NAME}/.well-known/mercure
# The secret used to sign the JWTs # The secret used to sign the JWTs
MERCURE_JWT_SECRET="!NotSoSecretMercureHubJWTSecretKey!" MERCURE_JWT_SECRET="!NotSoSecretMercureHubJWTSecretKey!"
###< symfony/mercure-bundle ### ###< symfony/mercure-bundle ###
###> redis ###
REDIS_HOST=localhost
REDIS_PASSWORD=r_password
###< redis ###
###> LNBits ### ###> LNBits ###
LNBITS_URL=https://legend.lnbits.com LNBITS_URL=https://legend.lnbits.com
LNBITS_API_KEY=<your-lnbits-admin-key> LNBITS_API_KEY=<your-lnbits-admin-key>

1
Dockerfile

@ -36,7 +36,6 @@ RUN set -eux; \
zip \ zip \
gmp \ gmp \
gd \ gd \
redis \
; ;
# https://getcomposer.org/doc/03-cli.md#composer-allow-superuser # https://getcomposer.org/doc/03-cli.md#composer-allow-superuser

1
composer.json

@ -10,7 +10,6 @@
"ext-ctype": "*", "ext-ctype": "*",
"ext-iconv": "*", "ext-iconv": "*",
"ext-openssl": "*", "ext-openssl": "*",
"ext-redis": "*",
"doctrine/dbal": "^4.2", "doctrine/dbal": "^4.2",
"doctrine/doctrine-bundle": "^2.13", "doctrine/doctrine-bundle": "^2.13",
"doctrine/doctrine-migrations-bundle": "^3.3", "doctrine/doctrine-migrations-bundle": "^3.3",

11
config/packages/cache.yaml

@ -3,14 +3,9 @@ framework:
# Unique name of your app: used to compute stable namespaces for cache keys. # Unique name of your app: used to compute stable namespaces for cache keys.
prefix_seed: newsroom/app prefix_seed: newsroom/app
# The "app" cache stores to the filesystem by default. # Use filesystem cache
# The data in this cache should persist between deploys. app: cache.adapter.filesystem
# Other options include:
# Redis
app: cache.adapter.redis
default_redis_provider: Redis
# Namespaced pools use the above "app" backend by default # Namespaced pools use the above "app" backend by default
pools: pools:
#my.dedicated.cache: null #my.dedicated.cache: null

14
config/services.yaml

@ -27,17 +27,3 @@ services:
Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler: Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler:
arguments: arguments:
- '%env(DATABASE_URL)%' - '%env(DATABASE_URL)%'
# Redis (still used for cache, just not sessions)
Symfony\Component\Cache\Adapter\RedisAdapter:
arguments:
- '@Redis'
Redis:
# you can also use \RedisArray, \RedisCluster, \Relay\Relay or \Predis\Client classes
class: Redis
calls:
- connect:
- '%env(REDIS_HOST)%'
- auth:
- '%env(REDIS_PASSWORD)%'

6
docker/cron/Dockerfile

@ -8,12 +8,6 @@ RUN apt-get update && apt-get install -y \
libpq-dev \ libpq-dev \
libonig-dev libonig-dev
# Install Redis PHP extension
RUN pecl install redis \
&& docker-php-ext-enable redis
RUN docker-php-ext-install pdo pdo_pgsql
# Set working directory # Set working directory
WORKDIR /var/www/html WORKDIR /var/www/html

10
src/Controller/ArticleController.php

@ -6,7 +6,7 @@ use App\Entity\Article;
use App\Enum\KindsEnum; use App\Enum\KindsEnum;
use App\Form\EditorType; use App\Form\EditorType;
use App\Service\NostrClient; use App\Service\NostrClient;
use App\Service\RedisCacheService; use App\Service\CacheService;
use App\Util\CommonMark\Converter; use App\Util\CommonMark\Converter;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use League\CommonMark\Exception\CommonMarkException; use League\CommonMark\Exception\CommonMarkException;
@ -62,7 +62,7 @@ class ArticleController extends AbstractController
public function article( public function article(
$slug, $slug,
EntityManagerInterface $entityManager, EntityManagerInterface $entityManager,
RedisCacheService $redisCacheService, CacheService $cacheService,
CacheItemPoolInterface $articlesCache, CacheItemPoolInterface $articlesCache,
Converter $converter Converter $converter
): Response ): Response
@ -101,7 +101,7 @@ class ArticleController extends AbstractController
$key = new Key(); $key = new Key();
$npub = $key->convertPublicKeyToBech32($article->getPubkey()); $npub = $key->convertPublicKeyToBech32($article->getPubkey());
$author = $redisCacheService->getMetadata($npub); $author = $cacheService->getMetadata($npub);
return $this->render('pages/article.html.twig', [ return $this->render('pages/article.html.twig', [
@ -120,7 +120,7 @@ class ArticleController extends AbstractController
public function articlePreviewEvent( public function articlePreviewEvent(
Request $request, Request $request,
NostrClient $nostrClient, NostrClient $nostrClient,
RedisCacheService $redisCacheService, CacheService $cacheService,
CacheItemPoolInterface $articlesCache CacheItemPoolInterface $articlesCache
): Response { ): Response {
$data = $request->getContent(); $data = $request->getContent();
@ -136,7 +136,7 @@ class ArticleController extends AbstractController
$hint = json_decode($descriptor->decoded); $hint = json_decode($descriptor->decoded);
$key = new Key(); $key = new Key();
$npub = $key->convertPublicKeyToBech32($hint->pubkey); $npub = $key->convertPublicKeyToBech32($hint->pubkey);
$metadata = $redisCacheService->getMetadata($npub); $metadata = $cacheService->getMetadata($npub);
$metadata->npub = $npub; $metadata->npub = $npub;
$metadata->pubkey = $hint->pubkey; $metadata->pubkey = $hint->pubkey;
$metadata->type = 'nprofile'; $metadata->type = 'nprofile';

6
src/Controller/AuthorController.php

@ -6,7 +6,7 @@ namespace App\Controller;
use App\Repository\ArticleRepository; use App\Repository\ArticleRepository;
use App\Service\NostrClient; use App\Service\NostrClient;
use App\Service\RedisCacheService; use App\Service\CacheService;
use Exception; use Exception;
use swentel\nostr\Key\Key; use swentel\nostr\Key\Key;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
@ -19,12 +19,12 @@ class AuthorController extends AbstractController
* @throws Exception * @throws Exception
*/ */
#[Route('/p/{npub}', name: 'author-profile', requirements: ['npub' => '^npub1.*'])] #[Route('/p/{npub}', name: 'author-profile', requirements: ['npub' => '^npub1.*'])]
public function index($npub, NostrClient $nostrClient, RedisCacheService $redisCacheService, ArticleRepository $articleRepository): Response public function index($npub, NostrClient $nostrClient, CacheService $cacheService, ArticleRepository $articleRepository): Response
{ {
$keys = new Key(); $keys = new Key();
$pubkey = $keys->convertToHex($npub); $pubkey = $keys->convertToHex($npub);
$author = $redisCacheService->getMetadata($npub); $author = $cacheService->getMetadata($npub);
// Retrieve long-form content for the author // Retrieve long-form content for the author
try { try {
$list = $nostrClient->getLongFormContentForPubkey($npub); $list = $nostrClient->getLongFormContentForPubkey($npub);

6
src/Controller/EventController.php

@ -6,7 +6,7 @@ namespace App\Controller;
use App\Service\NostrClient; use App\Service\NostrClient;
use App\Service\NostrLinkParser; use App\Service\NostrLinkParser;
use App\Service\RedisCacheService; use App\Service\CacheService;
use Exception; use Exception;
use nostriphant\NIP19\Bech32; use nostriphant\NIP19\Bech32;
use nostriphant\NIP19\Data; use nostriphant\NIP19\Data;
@ -23,7 +23,7 @@ class EventController extends AbstractController
* @throws Exception * @throws Exception
*/ */
#[Route('/e/{nevent}', name: 'nevent', requirements: ['nevent' => '^nevent1.*'])] #[Route('/e/{nevent}', name: 'nevent', requirements: ['nevent' => '^nevent1.*'])]
public function index($nevent, NostrClient $nostrClient, RedisCacheService $redisCacheService, NostrLinkParser $nostrLinkParser, LoggerInterface $logger): Response public function index($nevent, NostrClient $nostrClient, CacheService $cacheService, NostrLinkParser $nostrLinkParser, LoggerInterface $logger): Response
{ {
$logger->info('Accessing event page', ['nevent' => $nevent]); $logger->info('Accessing event page', ['nevent' => $nevent]);
@ -89,7 +89,7 @@ class EventController extends AbstractController
if (isset($event->pubkey)) { if (isset($event->pubkey)) {
$key = new Key(); $key = new Key();
$npub = $key->convertPublicKeyToBech32($event->pubkey); $npub = $key->convertPublicKeyToBech32($event->pubkey);
$authorMetadata = $redisCacheService->getMetadata($npub); $authorMetadata = $cacheService->getMetadata($npub);
} }
// Render template with the event data and extracted Nostr links // Render template with the event data and extracted Nostr links

8
src/Security/UserDTOProvider.php

@ -3,7 +3,7 @@
namespace App\Security; namespace App\Security;
use App\Entity\User; use App\Entity\User;
use App\Service\RedisCacheService; use App\Service\CacheService;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserInterface;
@ -19,7 +19,7 @@ readonly class UserDTOProvider implements UserProviderInterface
{ {
public function __construct( public function __construct(
private EntityManagerInterface $entityManager, private EntityManagerInterface $entityManager,
private RedisCacheService $redisCacheService, private CacheService $cacheService,
private LoggerInterface $logger private LoggerInterface $logger
) )
{ {
@ -40,7 +40,7 @@ readonly class UserDTOProvider implements UserProviderInterface
$this->logger->info('Refresh user.', ['user' => $user->getUserIdentifier()]); $this->logger->info('Refresh user.', ['user' => $user->getUserIdentifier()]);
$freshUser = $this->entityManager->getRepository(User::class) $freshUser = $this->entityManager->getRepository(User::class)
->findOneBy(['npub' => $user->getUserIdentifier()]); ->findOneBy(['npub' => $user->getUserIdentifier()]);
$metadata = $this->redisCacheService->getMetadata($user->getUserIdentifier()); $metadata = $this->cacheService->getMetadata($user->getUserIdentifier());
$freshUser->setMetadata($metadata); $freshUser->setMetadata($metadata);
return $freshUser; return $freshUser;
} }
@ -75,7 +75,7 @@ readonly class UserDTOProvider implements UserProviderInterface
$this->entityManager->flush(); $this->entityManager->flush();
} }
$metadata = $this->redisCacheService->getMetadata($identifier); $metadata = $this->cacheService->getMetadata($identifier);
$user->setMetadata($metadata); $user->setMetadata($metadata);
$this->logger->debug('User metadata set.', ['metadata' => json_encode($user->getMetadata())]); $this->logger->debug('User metadata set.', ['metadata' => json_encode($user->getMetadata())]);

70
src/Service/RedisCacheService.php

@ -1,70 +0,0 @@
<?php
namespace App\Service;
use Psr\Cache\InvalidArgumentException;
use Psr\Log\LoggerInterface;
use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\ItemInterface;
readonly class RedisCacheService
{
public function __construct(
private NostrClient $nostrClient,
private CacheInterface $redisCache,
private LoggerInterface $logger
)
{
}
/**
* @param string $npub
* @return \stdClass
*/
public function getMetadata(string $npub): \stdClass
{
$cacheKey = '0_' . $npub;
try {
return $this->redisCache->get($cacheKey, function (ItemInterface $item) use ($npub) {
$item->expiresAfter(3600); // 1 hour, adjust as needed
try {
$meta = $this->nostrClient->getNpubMetadata($npub);
} catch (\Exception $e) {
$this->logger->error('Error getting user data.', ['exception' => $e]);
$meta = new \stdClass();
$content = new \stdClass();
$meta->name = substr($npub, 0, 8) . '…' . substr($npub, -4);
$meta->content = json_encode($content);
}
$this->logger->info('Metadata:', ['meta' => json_encode($meta)]);
return json_decode($meta->content);
});
} catch (InvalidArgumentException $e) {
$this->logger->error('Error getting user data.', ['exception' => $e]);
$content = new \stdClass();
$content->name = substr($npub, 0, 8) . '…' . substr($npub, -4);
return $content;
}
}
public function getRelays($npub)
{
$cacheKey = '10002_' . $npub;
try {
return $this->redisCache->get($cacheKey, function (ItemInterface $item) use ($npub) {
$item->expiresAfter(3600); // 1 hour, adjust as needed
try {
$relays = $this->nostrClient->getNpubRelays($npub);
} catch (\Exception $e) {
$this->logger->error('Error getting user relays.', ['exception' => $e]);
}
return $relays ?? [];
});
} catch (InvalidArgumentException $e) {
$this->logger->error('Error getting user relays.', ['exception' => $e]);
return [];
}
}
}

4
src/Twig/Components/Header.php

@ -16,9 +16,9 @@ class Header
/** /**
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function __construct(private readonly CacheInterface $redisCache) public function __construct(private readonly CacheInterface $cache)
{ {
$mag = $this->redisCache->get('magazine-newsroom-magazine-by-newsroom', function (){ $mag = $this->cache->get('magazine-newsroom-magazine-by-newsroom', function (){
return null; return null;
}); });

19
src/Twig/Components/Molecules/CategoryLink.php

@ -11,17 +11,16 @@ final class CategoryLink
public string $title; public string $title;
public string $slug; public string $slug;
public function __construct(private CacheInterface $redisCache) public function __construct(private CacheInterface $cache)
{ {
} }
public function mount($coordinate): void public function mount($category): void
{ {
if (key_exists(1, $coordinate)) { $parts = explode(':', $category[1]);
$parts = explode(':', $coordinate[1]); try {
$this->slug = $parts[2]; $cat = $this->cache->get('magazine-' . $parts[2], function (){
$cat = $this->redisCache->get('magazine-' . $parts[2], function (){ throw new \Exception('Not found');
return null;
}); });
$tags = $cat->getTags(); $tags = $cat->getTags();
@ -31,10 +30,8 @@ final class CategoryLink
}); });
$this->title = $title[array_key_first($title)][1]; $this->title = $title[array_key_first($title)][1];
} else { } catch (\Exception $e) {
dump($coordinate);die(); // Handle cache miss
} }
} }
} }

6
src/Twig/Components/Molecules/UserFromNpub.php

@ -2,7 +2,7 @@
namespace App\Twig\Components\Molecules; namespace App\Twig\Components\Molecules;
use App\Service\RedisCacheService; use App\Service\CacheService;
use swentel\nostr\Key\Key; use swentel\nostr\Key\Key;
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent; use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
@ -13,7 +13,7 @@ final class UserFromNpub
public string $npub; public string $npub;
public $user = null; public $user = null;
public function __construct(private readonly RedisCacheService $redisCacheService) public function __construct(private readonly CacheService $cacheService)
{ {
} }
@ -27,6 +27,6 @@ final class UserFromNpub
} else { } else {
$this->npub = $ident; $this->npub = $ident;
} }
$this->user = $this->redisCacheService->getMetadata($this->npub); $this->user = $this->cacheService->getMetadata($this->npub);
} }
} }

4
src/Twig/Components/Organisms/FeaturedList.php

@ -16,7 +16,7 @@ final class FeaturedList
public array $list = []; public array $list = [];
public function __construct( public function __construct(
private readonly CacheInterface $redisCache, private readonly CacheInterface $cache,
private readonly ArticleRepository $articleRepository) private readonly ArticleRepository $articleRepository)
{ {
} }
@ -29,7 +29,7 @@ final class FeaturedList
{ {
$parts = explode(':', $category[1]); $parts = explode(':', $category[1]);
/** @var Event $catIndex */ /** @var Event $catIndex */
$catIndex = $this->redisCache->get('magazine-' . $parts[2], function (){ $catIndex = $this->cache->get('magazine-' . $parts[2], function (){
throw new \Exception('Not found'); throw new \Exception('Not found');
}); });

10
src/Util/CommonMark/Converter.php

@ -2,7 +2,7 @@
namespace App\Util\CommonMark; namespace App\Util\CommonMark;
use App\Service\RedisCacheService; use App\Service\CacheService;
use App\Util\CommonMark\ImagesExtension\RawImageLinkExtension; use App\Util\CommonMark\ImagesExtension\RawImageLinkExtension;
use App\Util\CommonMark\NostrSchemeExtension\NostrSchemeExtension; use App\Util\CommonMark\NostrSchemeExtension\NostrSchemeExtension;
use League\CommonMark\Environment\Environment; use League\CommonMark\Environment\Environment;
@ -25,8 +25,10 @@ use League\CommonMark\Renderer\HtmlDecorator;
readonly class Converter readonly class Converter
{ {
public function __construct( public function __construct(
private RedisCacheService $redisCacheService private CacheService $cacheService
){} )
{
}
/** /**
* @throws CommonMarkException * @throws CommonMarkException
@ -64,7 +66,7 @@ readonly class Converter
$environment->addExtension(new TableExtension()); $environment->addExtension(new TableExtension());
$environment->addExtension(new StrikethroughExtension()); $environment->addExtension(new StrikethroughExtension());
// create a custom extension, that handles nostr mentions // create a custom extension, that handles nostr mentions
$environment->addExtension(new NostrSchemeExtension($this->redisCacheService)); $environment->addExtension(new NostrSchemeExtension($this->cacheService));
$environment->addExtension(new SmartPunctExtension()); $environment->addExtension(new SmartPunctExtension());
$environment->addExtension(new EmbedExtension()); $environment->addExtension(new EmbedExtension());
$environment->addRenderer(Embed::class, new HtmlDecorator(new EmbedRenderer(), 'div', ['class' => 'embedded-content'])); $environment->addRenderer(Embed::class, new HtmlDecorator(new EmbedRenderer(), 'div', ['class' => 'embedded-content']));

7
src/Util/CommonMark/NostrSchemeExtension/NostrMentionParser.php

@ -2,11 +2,10 @@
namespace App\Util\CommonMark\NostrSchemeExtension; namespace App\Util\CommonMark\NostrSchemeExtension;
use App\Service\RedisCacheService; use App\Service\CacheService;
use League\CommonMark\Parser\Inline\InlineParserInterface; use League\CommonMark\Parser\Inline\InlineParserInterface;
use League\CommonMark\Parser\Inline\InlineParserMatch; use League\CommonMark\Parser\Inline\InlineParserMatch;
use League\CommonMark\Parser\InlineParserContext; use League\CommonMark\Parser\InlineParserContext;
use swentel\nostr\Key\Key;
/** /**
* Class NostrMentionParser * Class NostrMentionParser
@ -17,7 +16,7 @@ use swentel\nostr\Key\Key;
readonly class NostrMentionParser implements InlineParserInterface readonly class NostrMentionParser implements InlineParserInterface
{ {
public function __construct( public function __construct(
private RedisCacheService $redisCacheService private CacheService $cacheService
){} ){}
public function getMatchDefinition(): InlineParserMatch public function getMatchDefinition(): InlineParserMatch
@ -40,7 +39,7 @@ readonly class NostrMentionParser implements InlineParserInterface
$npubLink = substr($fullMatch, strpos($fullMatch, 'npub1'), -1); // e.g., "npubXXXX" $npubLink = substr($fullMatch, strpos($fullMatch, 'npub1'), -1); // e.g., "npubXXXX"
if (empty($label)) { if (empty($label)) {
$metadata = $this->redisCacheService->getMetadata($npubLink); $metadata = $this->cacheService->getMetadata($npubLink);
$label = $metadata->display_name ?? $metadata->name; $label = $metadata->display_name ?? $metadata->name;
} }

6
src/Util/CommonMark/NostrSchemeExtension/NostrRawNpubParser.php

@ -2,7 +2,7 @@
namespace App\Util\CommonMark\NostrSchemeExtension; namespace App\Util\CommonMark\NostrSchemeExtension;
use App\Service\RedisCacheService; use App\Service\CacheService;
use League\CommonMark\Parser\Inline\InlineParserInterface; use League\CommonMark\Parser\Inline\InlineParserInterface;
use League\CommonMark\Parser\Inline\InlineParserMatch; use League\CommonMark\Parser\Inline\InlineParserMatch;
use League\CommonMark\Parser\InlineParserContext; use League\CommonMark\Parser\InlineParserContext;
@ -14,7 +14,7 @@ use League\CommonMark\Parser\InlineParserContext;
readonly class NostrRawNpubParser implements InlineParserInterface readonly class NostrRawNpubParser implements InlineParserInterface
{ {
public function __construct(private RedisCacheService $redisCacheService) public function __construct(private CacheService $cacheService)
{ {
} }
@ -28,7 +28,7 @@ readonly class NostrRawNpubParser implements InlineParserInterface
$cursor = $inlineContext->getCursor(); $cursor = $inlineContext->getCursor();
// Get the match and extract relevant parts // Get the match and extract relevant parts
$fullMatch = $inlineContext->getFullMatch(); $fullMatch = $inlineContext->getFullMatch();
$meta = $this->redisCacheService->getMetadata($fullMatch); $meta = $this->cacheService->getMetadata($fullMatch);
// Create a new inline node for the custom link // Create a new inline node for the custom link
$inlineContext->getContainer()->appendChild(new NostrMentionLink($meta->name, $fullMatch)); $inlineContext->getContainer()->appendChild(new NostrMentionLink($meta->name, $fullMatch));

8
src/Util/CommonMark/NostrSchemeExtension/NostrSchemeExtension.php

@ -2,23 +2,23 @@
namespace App\Util\CommonMark\NostrSchemeExtension; namespace App\Util\CommonMark\NostrSchemeExtension;
use App\Service\RedisCacheService; use App\Service\CacheService;
use League\CommonMark\Environment\EnvironmentBuilderInterface; use League\CommonMark\Environment\EnvironmentBuilderInterface;
use League\CommonMark\Extension\ExtensionInterface; use League\CommonMark\Extension\ExtensionInterface;
class NostrSchemeExtension implements ExtensionInterface class NostrSchemeExtension implements ExtensionInterface
{ {
public function __construct(private readonly RedisCacheService $redisCacheService) public function __construct(private readonly CacheService $cacheService)
{ {
} }
public function register(EnvironmentBuilderInterface $environment): void public function register(EnvironmentBuilderInterface $environment): void
{ {
$environment $environment
->addInlineParser(new NostrMentionParser($this->redisCacheService), 200) ->addInlineParser(new NostrMentionParser($this->cacheService), 200)
->addInlineParser(new NostrSchemeParser(), 199) ->addInlineParser(new NostrSchemeParser(), 199)
->addInlineParser(new NostrRawNpubParser($this->redisCacheService), 198) ->addInlineParser(new NostrRawNpubParser($this->cacheService), 198)
->addRenderer(NostrSchemeData::class, new NostrEventRenderer(), 2) ->addRenderer(NostrSchemeData::class, new NostrEventRenderer(), 2)
->addRenderer(NostrMentionLink::class, new NostrMentionRenderer(), 1) ->addRenderer(NostrMentionLink::class, new NostrMentionRenderer(), 1)

Loading…
Cancel
Save