Browse Source

Downsizing

imwald
Nuša Pukšič 9 months ago
parent
commit
eb1fdd7db8
  1. 2
      .env.dist
  2. 213
      composer.lock
  3. 71
      migrations/Version20250729102713.php
  4. 48
      src/Command/DatabaseCleanupCommand.php
  5. 67
      src/Command/DeduplicateArticlesCommand.php
  6. 41
      src/Command/MarkAsIndexedCommand.php
  7. 69
      src/Service/CacheService.php
  8. 10
      src/Service/NostrClient.php

2
.env.dist

@ -39,7 +39,7 @@ DATABASE_URL="mysql://${MYSQL_USER}:${MYSQL_PASSWORD}@database:3306/${MYSQL_DATA @@ -39,7 +39,7 @@ DATABASE_URL="mysql://${MYSQL_USER}:${MYSQL_PASSWORD}@database:3306/${MYSQL_DATA
# The URL of the Mercure hub, used by the app to publish updates (can be a local URL)
MERCURE_URL=https://newsroom-php/.well-known/mercure
# The public URL of the Mercure hub, used by the browser to connect
MERCURE_PUBLIC_URL=https://${SERVER_NAME}/.well-known/mercure
MERCURE_PUBLIC_URL="https://${SERVER_NAME}/.well-known/mercure"
# The secret used to sign the JWTs
MERCURE_JWT_SECRET="!NotSoSecretMercureHubJWTSecretKey!"
###< symfony/mercure-bundle ###

213
composer.lock generated

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "9363e776834fe38b6d383eabb8461adb",
"content-hash": "0cd33192da4ef60028e3b2dab8d92170",
"packages": [
{
"name": "bacon/bacon-qr-code",
@ -476,21 +476,21 @@ @@ -476,21 +476,21 @@
},
{
"name": "doctrine/dbal",
"version": "4.2.4",
"version": "4.3.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/dbal.git",
"reference": "b37d160498ea91a2382a2ebe825c4ea6254fc0ec"
"reference": "ac336c95ea9e13433d56ca81c308b39db0e1a2a7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/b37d160498ea91a2382a2ebe825c4ea6254fc0ec",
"reference": "b37d160498ea91a2382a2ebe825c4ea6254fc0ec",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/ac336c95ea9e13433d56ca81c308b39db0e1a2a7",
"reference": "ac336c95ea9e13433d56ca81c308b39db0e1a2a7",
"shasum": ""
},
"require": {
"doctrine/deprecations": "^0.5.3|^1",
"php": "^8.1",
"doctrine/deprecations": "^1.1.5",
"php": "^8.2",
"psr/cache": "^1|^2|^3",
"psr/log": "^1|^2|^3"
},
@ -501,7 +501,7 @@ @@ -501,7 +501,7 @@
"phpstan/phpstan": "2.1.17",
"phpstan/phpstan-phpunit": "2.0.6",
"phpstan/phpstan-strict-rules": "^2",
"phpunit/phpunit": "10.5.46",
"phpunit/phpunit": "11.5.23",
"slevomat/coding-standard": "8.16.2",
"squizlabs/php_codesniffer": "3.13.1",
"symfony/cache": "^6.3.8|^7.0",
@ -562,7 +562,7 @@ @@ -562,7 +562,7 @@
],
"support": {
"issues": "https://github.com/doctrine/dbal/issues",
"source": "https://github.com/doctrine/dbal/tree/4.2.4"
"source": "https://github.com/doctrine/dbal/tree/4.3.1"
},
"funding": [
{
@ -578,7 +578,7 @@ @@ -578,7 +578,7 @@
"type": "tidelift"
}
],
"time": "2025-06-15T23:15:01+00:00"
"time": "2025-07-22T10:09:51+00:00"
},
{
"name": "doctrine/deprecations",
@ -1166,16 +1166,16 @@ @@ -1166,16 +1166,16 @@
},
{
"name": "doctrine/migrations",
"version": "3.9.0",
"version": "3.9.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/migrations.git",
"reference": "325b61e41d032f5f7d7e2d11cbefff656eadc9ab"
"reference": "0f1e0c960ac29866d648a4f50142a74fe1cb6999"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/migrations/zipball/325b61e41d032f5f7d7e2d11cbefff656eadc9ab",
"reference": "325b61e41d032f5f7d7e2d11cbefff656eadc9ab",
"url": "https://api.github.com/repos/doctrine/migrations/zipball/0f1e0c960ac29866d648a4f50142a74fe1cb6999",
"reference": "0f1e0c960ac29866d648a4f50142a74fe1cb6999",
"shasum": ""
},
"require": {
@ -1249,7 +1249,7 @@ @@ -1249,7 +1249,7 @@
],
"support": {
"issues": "https://github.com/doctrine/migrations/issues",
"source": "https://github.com/doctrine/migrations/tree/3.9.0"
"source": "https://github.com/doctrine/migrations/tree/3.9.1"
},
"funding": [
{
@ -1265,20 +1265,20 @@ @@ -1265,20 +1265,20 @@
"type": "tidelift"
}
],
"time": "2025-03-26T06:48:45+00:00"
"time": "2025-06-27T07:19:23+00:00"
},
{
"name": "doctrine/orm",
"version": "3.4.0",
"version": "3.5.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/orm.git",
"reference": "4664373bd0668d71b40cc368b950de95e1dba2f8"
"reference": "6deec3655ba3e8f15280aac11e264225854d2369"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/orm/zipball/4664373bd0668d71b40cc368b950de95e1dba2f8",
"reference": "4664373bd0668d71b40cc368b950de95e1dba2f8",
"url": "https://api.github.com/repos/doctrine/orm/zipball/6deec3655ba3e8f15280aac11e264225854d2369",
"reference": "6deec3655ba3e8f15280aac11e264225854d2369",
"shasum": ""
},
"require": {
@ -1353,9 +1353,9 @@ @@ -1353,9 +1353,9 @@
],
"support": {
"issues": "https://github.com/doctrine/orm/issues",
"source": "https://github.com/doctrine/orm/tree/3.4.0"
"source": "https://github.com/doctrine/orm/tree/3.5.0"
},
"time": "2025-06-14T11:47:14+00:00"
"time": "2025-07-01T17:40:53+00:00"
},
{
"name": "doctrine/persistence",
@ -1658,16 +1658,16 @@ @@ -1658,16 +1658,16 @@
},
{
"name": "endroid/qr-code",
"version": "6.0.8",
"version": "6.0.9",
"source": {
"type": "git",
"url": "https://github.com/endroid/qr-code.git",
"reference": "8102273afbcd5e3d95f1faaab2c5aa31e3637f61"
"reference": "21e888e8597440b2205e2e5c484b6c8e556bcd1a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/endroid/qr-code/zipball/8102273afbcd5e3d95f1faaab2c5aa31e3637f61",
"reference": "8102273afbcd5e3d95f1faaab2c5aa31e3637f61",
"url": "https://api.github.com/repos/endroid/qr-code/zipball/21e888e8597440b2205e2e5c484b6c8e556bcd1a",
"reference": "21e888e8597440b2205e2e5c484b6c8e556bcd1a",
"shasum": ""
},
"require": {
@ -1718,7 +1718,7 @@ @@ -1718,7 +1718,7 @@
],
"support": {
"issues": "https://github.com/endroid/qr-code/issues",
"source": "https://github.com/endroid/qr-code/tree/6.0.8"
"source": "https://github.com/endroid/qr-code/tree/6.0.9"
},
"funding": [
{
@ -1726,7 +1726,7 @@ @@ -1726,7 +1726,7 @@
"type": "github"
}
],
"time": "2025-05-10T14:28:45+00:00"
"time": "2025-07-13T19:59:45+00:00"
},
{
"name": "endroid/qr-code-bundle",
@ -2042,16 +2042,16 @@ @@ -2042,16 +2042,16 @@
},
{
"name": "league/commonmark",
"version": "2.7.0",
"version": "2.7.1",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/commonmark.git",
"reference": "6fbb36d44824ed4091adbcf4c7d4a3923cdb3405"
"reference": "10732241927d3971d28e7ea7b5712721fa2296ca"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/6fbb36d44824ed4091adbcf4c7d4a3923cdb3405",
"reference": "6fbb36d44824ed4091adbcf4c7d4a3923cdb3405",
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/10732241927d3971d28e7ea7b5712721fa2296ca",
"reference": "10732241927d3971d28e7ea7b5712721fa2296ca",
"shasum": ""
},
"require": {
@ -2080,7 +2080,7 @@ @@ -2080,7 +2080,7 @@
"symfony/process": "^5.4 | ^6.0 | ^7.0",
"symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0",
"unleashedtech/php-coding-standard": "^3.1.1",
"vimeo/psalm": "^4.24.0 || ^5.0.0"
"vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0"
},
"suggest": {
"symfony/yaml": "v2.3+ required if using the Front Matter extension"
@ -2145,7 +2145,7 @@ @@ -2145,7 +2145,7 @@
"type": "tidelift"
}
],
"time": "2025-05-05T12:20:28+00:00"
"time": "2025-07-20T12:47:49+00:00"
},
{
"name": "league/config",
@ -2547,16 +2547,16 @@ @@ -2547,16 +2547,16 @@
},
{
"name": "masterminds/html5",
"version": "2.9.0",
"version": "2.10.0",
"source": {
"type": "git",
"url": "https://github.com/Masterminds/html5-php.git",
"reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6"
"reference": "fcf91eb64359852f00d921887b219479b4f21251"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f5ac2c0b0a2eefca70b2ce32a5809992227e75a6",
"reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6",
"url": "https://api.github.com/repos/Masterminds/html5-php/zipball/fcf91eb64359852f00d921887b219479b4f21251",
"reference": "fcf91eb64359852f00d921887b219479b4f21251",
"shasum": ""
},
"require": {
@ -2608,9 +2608,9 @@ @@ -2608,9 +2608,9 @@
],
"support": {
"issues": "https://github.com/Masterminds/html5-php/issues",
"source": "https://github.com/Masterminds/html5-php/tree/2.9.0"
"source": "https://github.com/Masterminds/html5-php/tree/2.10.0"
},
"time": "2024-03-31T07:05:07+00:00"
"time": "2025-07-25T09:04:22+00:00"
},
{
"name": "ml/iri",
@ -2963,16 +2963,16 @@ @@ -2963,16 +2963,16 @@
},
{
"name": "paragonie/ecc",
"version": "v2.4.0",
"version": "v2.5.0",
"source": {
"type": "git",
"url": "https://github.com/paragonie/phpecc.git",
"reference": "fdba22a506492eb6e5fe38c501c0df61eaf0b54c"
"reference": "d25bd2aab9b1205db1cf3aa3e83531d4549377bf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paragonie/phpecc/zipball/fdba22a506492eb6e5fe38c501c0df61eaf0b54c",
"reference": "fdba22a506492eb6e5fe38c501c0df61eaf0b54c",
"url": "https://api.github.com/repos/paragonie/phpecc/zipball/d25bd2aab9b1205db1cf3aa3e83531d4549377bf",
"reference": "d25bd2aab9b1205db1cf3aa3e83531d4549377bf",
"shasum": ""
},
"require": {
@ -2982,11 +2982,13 @@ @@ -2982,11 +2982,13 @@
"php": "^7.1||^8.0"
},
"require-dev": {
"bitcoin/bips": "dev-master",
"c2sp/wycheproof": "dev-master",
"ext-json": "*",
"phpunit/phpunit": "^6|^7|^8|^9",
"squizlabs/php_codesniffer": "^2|^3",
"symfony/yaml": "^2.6|^3.0|^4",
"vimeo/psalm": "^2|^3|^4|^5"
"symfony/yaml": "^2.6|^3.0|^4|^5|^6|^7",
"vimeo/psalm": "^2|^3|^4|^5|^6"
},
"suggest": {
"ext-openssl": "(PHP 8.1, OpenSSL 3+) Improved performance, less worries about side-channels"
@ -3045,9 +3047,9 @@ @@ -3045,9 +3047,9 @@
],
"support": {
"issues": "https://github.com/paragonie/phpecc/issues",
"source": "https://github.com/paragonie/phpecc/tree/v2.4.0"
"source": "https://github.com/paragonie/phpecc/tree/v2.5.0"
},
"time": "2025-01-21T17:53:03+00:00"
"time": "2025-07-19T01:25:49+00:00"
},
{
"name": "paragonie/sodium_compat",
@ -3317,16 +3319,16 @@ @@ -3317,16 +3319,16 @@
},
{
"name": "phpstan/phpdoc-parser",
"version": "2.1.0",
"version": "2.2.0",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "9b30d6fd026b2c132b3985ce6b23bec09ab3aa68"
"reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/9b30d6fd026b2c132b3985ce6b23bec09ab3aa68",
"reference": "9b30d6fd026b2c132b3985ce6b23bec09ab3aa68",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/b9e61a61e39e02dd90944e9115241c7f7e76bfd8",
"reference": "b9e61a61e39e02dd90944e9115241c7f7e76bfd8",
"shasum": ""
},
"require": {
@ -3358,9 +3360,9 @@ @@ -3358,9 +3360,9 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/2.1.0"
"source": "https://github.com/phpstan/phpdoc-parser/tree/2.2.0"
},
"time": "2025-02-19T13:28:12+00:00"
"time": "2025-07-13T07:04:09+00:00"
},
{
"name": "phrity/comparison",
@ -5640,16 +5642,16 @@ @@ -5640,16 +5642,16 @@
},
{
"name": "symfony/flex",
"version": "v2.7.1",
"version": "v2.8.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/flex.git",
"reference": "4ae50d368415a06820739e54d38a4a29d6df9155"
"reference": "423c36e369361003dc31ef11c5f15fb589e52c01"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/flex/zipball/4ae50d368415a06820739e54d38a4a29d6df9155",
"reference": "4ae50d368415a06820739e54d38a4a29d6df9155",
"url": "https://api.github.com/repos/symfony/flex/zipball/423c36e369361003dc31ef11c5f15fb589e52c01",
"reference": "423c36e369361003dc31ef11c5f15fb589e52c01",
"shasum": ""
},
"require": {
@ -5688,7 +5690,7 @@ @@ -5688,7 +5690,7 @@
"description": "Composer plugin for Symfony",
"support": {
"issues": "https://github.com/symfony/flex/issues",
"source": "https://github.com/symfony/flex/tree/v2.7.1"
"source": "https://github.com/symfony/flex/tree/v2.8.1"
},
"funding": [
{
@ -5704,7 +5706,7 @@ @@ -5704,7 +5706,7 @@
"type": "tidelift"
}
],
"time": "2025-05-28T14:22:54+00:00"
"time": "2025-07-05T07:45:19+00:00"
},
{
"name": "symfony/form",
@ -8104,16 +8106,16 @@ @@ -8104,16 +8106,16 @@
},
{
"name": "symfony/stimulus-bundle",
"version": "v2.26.1",
"version": "v2.28.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/stimulus-bundle.git",
"reference": "82c174ebe564e6ecc1412974b6380b86d450675f"
"reference": "960868a682271e133a631ffb70c7e2ceb5031be6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/stimulus-bundle/zipball/82c174ebe564e6ecc1412974b6380b86d450675f",
"reference": "82c174ebe564e6ecc1412974b6380b86d450675f",
"url": "https://api.github.com/repos/symfony/stimulus-bundle/zipball/960868a682271e133a631ffb70c7e2ceb5031be6",
"reference": "960868a682271e133a631ffb70c7e2ceb5031be6",
"shasum": ""
},
"require": {
@ -8153,7 +8155,7 @@ @@ -8153,7 +8155,7 @@
"symfony-ux"
],
"support": {
"source": "https://github.com/symfony/stimulus-bundle/tree/v2.26.1"
"source": "https://github.com/symfony/stimulus-bundle/tree/v2.28.1"
},
"funding": [
{
@ -8169,7 +8171,7 @@ @@ -8169,7 +8171,7 @@
"type": "tidelift"
}
],
"time": "2025-06-05T17:25:17+00:00"
"time": "2025-07-28T19:36:26+00:00"
},
{
"name": "symfony/stopwatch",
@ -8769,16 +8771,16 @@ @@ -8769,16 +8771,16 @@
},
{
"name": "symfony/ux-icons",
"version": "v2.26.0",
"version": "v2.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/ux-icons.git",
"reference": "e5c1e5b5093ae26dba45d0f3390a1e21f305c47a"
"reference": "1b48034b46a38595d576a425976dac7b33d428b3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/ux-icons/zipball/e5c1e5b5093ae26dba45d0f3390a1e21f305c47a",
"reference": "e5c1e5b5093ae26dba45d0f3390a1e21f305c47a",
"url": "https://api.github.com/repos/symfony/ux-icons/zipball/1b48034b46a38595d576a425976dac7b33d428b3",
"reference": "1b48034b46a38595d576a425976dac7b33d428b3",
"shasum": ""
},
"require": {
@ -8838,7 +8840,7 @@ @@ -8838,7 +8840,7 @@
"twig"
],
"support": {
"source": "https://github.com/symfony/ux-icons/tree/v2.26.0"
"source": "https://github.com/symfony/ux-icons/tree/v2.28.0"
},
"funding": [
{
@ -8854,7 +8856,7 @@ @@ -8854,7 +8856,7 @@
"type": "tidelift"
}
],
"time": "2025-05-30T02:07:34+00:00"
"time": "2025-07-25T06:20:58+00:00"
},
{
"name": "symfony/ux-live-component",
@ -8955,16 +8957,16 @@ @@ -8955,16 +8957,16 @@
},
{
"name": "symfony/ux-twig-component",
"version": "v2.26.0",
"version": "v2.28.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/ux-twig-component.git",
"reference": "825e653b34fb48ed2198913c603d80f7632fe9c1"
"reference": "8b10610f7976aee34c40b51fed2244555ce9ead0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/ux-twig-component/zipball/825e653b34fb48ed2198913c603d80f7632fe9c1",
"reference": "825e653b34fb48ed2198913c603d80f7632fe9c1",
"url": "https://api.github.com/repos/symfony/ux-twig-component/zipball/8b10610f7976aee34c40b51fed2244555ce9ead0",
"reference": "8b10610f7976aee34c40b51fed2244555ce9ead0",
"shasum": ""
},
"require": {
@ -9018,7 +9020,7 @@ @@ -9018,7 +9020,7 @@
"twig"
],
"support": {
"source": "https://github.com/symfony/ux-twig-component/tree/v2.26.0"
"source": "https://github.com/symfony/ux-twig-component/tree/v2.28.0"
},
"funding": [
{
@ -9034,7 +9036,7 @@ @@ -9034,7 +9036,7 @@
"type": "tidelift"
}
],
"time": "2025-05-26T06:21:54+00:00"
"time": "2025-06-27T09:05:08+00:00"
},
{
"name": "symfony/var-dumper",
@ -9838,16 +9840,16 @@ @@ -9838,16 +9840,16 @@
"packages-dev": [
{
"name": "myclabs/deep-copy",
"version": "1.13.1",
"version": "1.13.3",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
"reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c"
"reference": "faed855a7b5f4d4637717c2b3863e277116beb36"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c",
"reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c",
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/faed855a7b5f4d4637717c2b3863e277116beb36",
"reference": "faed855a7b5f4d4637717c2b3863e277116beb36",
"shasum": ""
},
"require": {
@ -9886,7 +9888,7 @@ @@ -9886,7 +9888,7 @@
],
"support": {
"issues": "https://github.com/myclabs/DeepCopy/issues",
"source": "https://github.com/myclabs/DeepCopy/tree/1.13.1"
"source": "https://github.com/myclabs/DeepCopy/tree/1.13.3"
},
"funding": [
{
@ -9894,20 +9896,20 @@ @@ -9894,20 +9896,20 @@
"type": "tidelift"
}
],
"time": "2025-04-29T12:36:36+00:00"
"time": "2025-07-05T12:25:42+00:00"
},
{
"name": "nikic/php-parser",
"version": "v5.5.0",
"version": "v5.6.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "ae59794362fe85e051a58ad36b289443f57be7a9"
"reference": "221b0d0fdf1369c71047ad1d18bb5880017bbc56"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ae59794362fe85e051a58ad36b289443f57be7a9",
"reference": "ae59794362fe85e051a58ad36b289443f57be7a9",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/221b0d0fdf1369c71047ad1d18bb5880017bbc56",
"reference": "221b0d0fdf1369c71047ad1d18bb5880017bbc56",
"shasum": ""
},
"require": {
@ -9950,9 +9952,9 @@ @@ -9950,9 +9952,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v5.5.0"
"source": "https://github.com/nikic/PHP-Parser/tree/v5.6.0"
},
"time": "2025-05-31T08:24:38+00:00"
"time": "2025-07-27T20:03:57+00:00"
},
{
"name": "phar-io/manifest",
@ -11667,16 +11669,16 @@ @@ -11667,16 +11669,16 @@
},
{
"name": "symfony/maker-bundle",
"version": "v1.63.0",
"version": "v1.64.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/maker-bundle.git",
"reference": "69478ab39bc303abfbe3293006a78b09a8512425"
"reference": "c86da84640b0586e92aee2b276ee3638ef2f425a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/maker-bundle/zipball/69478ab39bc303abfbe3293006a78b09a8512425",
"reference": "69478ab39bc303abfbe3293006a78b09a8512425",
"url": "https://api.github.com/repos/symfony/maker-bundle/zipball/c86da84640b0586e92aee2b276ee3638ef2f425a",
"reference": "c86da84640b0586e92aee2b276ee3638ef2f425a",
"shasum": ""
},
"require": {
@ -11704,6 +11706,7 @@ @@ -11704,6 +11706,7 @@
"symfony/http-client": "^6.4|^7.0",
"symfony/phpunit-bridge": "^6.4.1|^7.0",
"symfony/security-core": "^6.4|^7.0",
"symfony/security-http": "^6.4|^7.0",
"symfony/yaml": "^6.4|^7.0",
"twig/twig": "^3.0|^4.x-dev"
},
@ -11739,7 +11742,7 @@ @@ -11739,7 +11742,7 @@
],
"support": {
"issues": "https://github.com/symfony/maker-bundle/issues",
"source": "https://github.com/symfony/maker-bundle/tree/v1.63.0"
"source": "https://github.com/symfony/maker-bundle/tree/v1.64.0"
},
"funding": [
{
@ -11755,20 +11758,20 @@ @@ -11755,20 +11758,20 @@
"type": "tidelift"
}
],
"time": "2025-04-26T01:41:37+00:00"
"time": "2025-06-23T16:12:08+00:00"
},
{
"name": "symfony/phpunit-bridge",
"version": "v7.3.0",
"version": "v7.3.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/phpunit-bridge.git",
"reference": "2eabda563921f21cbce1d1e3247b3c36568905e6"
"reference": "71624984d8bcad6acf7a790d4e3ceafe04bc2485"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/2eabda563921f21cbce1d1e3247b3c36568905e6",
"reference": "2eabda563921f21cbce1d1e3247b3c36568905e6",
"url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/71624984d8bcad6acf7a790d4e3ceafe04bc2485",
"reference": "71624984d8bcad6acf7a790d4e3ceafe04bc2485",
"shasum": ""
},
"require": {
@ -11820,8 +11823,11 @@ @@ -11820,8 +11823,11 @@
],
"description": "Provides utilities for PHPUnit, especially user deprecation notices management",
"homepage": "https://symfony.com",
"keywords": [
"testing"
],
"support": {
"source": "https://github.com/symfony/phpunit-bridge/tree/v7.3.0"
"source": "https://github.com/symfony/phpunit-bridge/tree/v7.3.1"
},
"funding": [
{
@ -11837,7 +11843,7 @@ @@ -11837,7 +11843,7 @@
"type": "tidelift"
}
],
"time": "2025-05-23T07:26:30+00:00"
"time": "2025-06-04T10:09:06+00:00"
},
{
"name": "symfony/process",
@ -12041,8 +12047,7 @@ @@ -12041,8 +12047,7 @@
"php": ">=8.3.13",
"ext-ctype": "*",
"ext-iconv": "*",
"ext-openssl": "*",
"ext-redis": "*"
"ext-openssl": "*"
},
"platform-dev": {},
"plugin-api-version": "2.6.0"

71
migrations/Version20250729102713.php

@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20250729102713 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql(<<<'SQL'
CREATE TABLE app_user (id INT AUTO_INCREMENT NOT NULL, npub VARCHAR(255) NOT NULL, roles JSON DEFAULT NULL, UNIQUE INDEX UNIQ_88BDF3E95FB8BABB (npub), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4
SQL);
$this->addSql(<<<'SQL'
CREATE TABLE article (id INT AUTO_INCREMENT NOT NULL, raw JSON DEFAULT NULL, event_id VARCHAR(225) DEFAULT NULL, slug LONGTEXT DEFAULT NULL, content LONGTEXT DEFAULT NULL, kind INT DEFAULT NULL, title LONGTEXT DEFAULT NULL, summary LONGTEXT DEFAULT NULL, pubkey VARCHAR(255) NOT NULL, created_at DATETIME DEFAULT NULL, sig VARCHAR(255) NOT NULL, image LONGTEXT DEFAULT NULL, published_at DATETIME DEFAULT NULL, topics JSON DEFAULT NULL, event_status INT DEFAULT NULL, current_places JSON DEFAULT NULL, rating_negative INT DEFAULT NULL, rating_positive INT DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4
SQL);
$this->addSql(<<<'SQL'
CREATE TABLE event (id VARCHAR(225) NOT NULL, event_id VARCHAR(225) DEFAULT NULL, kind INT NOT NULL, pubkey VARCHAR(255) NOT NULL, content LONGTEXT NOT NULL, created_at BIGINT NOT NULL, tags JSON NOT NULL, sig VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4
SQL);
$this->addSql(<<<'SQL'
CREATE TABLE nzine (id INT AUTO_INCREMENT NOT NULL, npub VARCHAR(255) NOT NULL, main_categories JSON NOT NULL, lists JSON DEFAULT NULL, editor VARCHAR(255) DEFAULT NULL, slug LONGTEXT DEFAULT NULL, state VARCHAR(255) NOT NULL, nzine_bot_id INT DEFAULT NULL, UNIQUE INDEX UNIQ_65025D9871FD5427 (nzine_bot_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4
SQL);
$this->addSql(<<<'SQL'
CREATE TABLE nzine_bot (id INT AUTO_INCREMENT NOT NULL, encrypted_nsec VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4
SQL);
$this->addSql(<<<'SQL'
CREATE TABLE sessions (sess_id VARBINARY(128) NOT NULL, sess_data LONGBLOB NOT NULL, sess_lifetime INT UNSIGNED NOT NULL, sess_time INT UNSIGNED NOT NULL, INDEX sess_lifetime_idx (sess_lifetime), PRIMARY KEY(sess_id)) DEFAULT CHARACTER SET utf8mb4 ENGINE = InnoDB
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE nzine ADD CONSTRAINT FK_65025D9871FD5427 FOREIGN KEY (nzine_bot_id) REFERENCES nzine_bot (id)
SQL);
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql(<<<'SQL'
ALTER TABLE nzine DROP FOREIGN KEY FK_65025D9871FD5427
SQL);
$this->addSql(<<<'SQL'
DROP TABLE app_user
SQL);
$this->addSql(<<<'SQL'
DROP TABLE article
SQL);
$this->addSql(<<<'SQL'
DROP TABLE event
SQL);
$this->addSql(<<<'SQL'
DROP TABLE nzine
SQL);
$this->addSql(<<<'SQL'
DROP TABLE nzine_bot
SQL);
$this->addSql(<<<'SQL'
DROP TABLE sessions
SQL);
}
}

48
src/Command/DatabaseCleanupCommand.php

@ -1,48 +0,0 @@ @@ -1,48 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Command;
use App\Entity\Article;
use App\Enum\IndexStatusEnum;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
#[AsCommand(name: 'db:cleanup', description: 'Remove articles with do_not_index rating')]
class
DatabaseCleanupCommand extends Command
{
public function __construct(private readonly EntityManagerInterface $entityManager)
{
parent::__construct();
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$repository = $this->entityManager->getRepository(Article::class);
$items = $repository->findBy(['indexStatus' => IndexStatusEnum::DO_NOT_INDEX]);
if (empty($items)) {
$output->writeln('<info>No items found.</info>');
return Command::SUCCESS;
}
foreach ($items as $item) {
$this->entityManager->remove($item);
}
$this->entityManager->flush();
$output->writeln('<comment>Deleted ' . count($items) . ' items.</comment>');
return Command::SUCCESS;
}
}

67
src/Command/DeduplicateArticlesCommand.php

@ -1,67 +0,0 @@ @@ -1,67 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Command;
use App\Entity\Article;
use App\Enum\IndexStatusEnum;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
#[AsCommand(name: 'articles:deduplicate', description: 'Mark duplicates with DO_NOT_INDEX.')]
class DeduplicateArticlesCommand extends Command
{
private const BATCH_SIZE = 500;
public function __construct(private EntityManagerInterface $em)
{
parent::__construct();
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$repo = $this->em->getRepository(Article::class);
$slugIndex = [];
$page = 0;
// Process articles in batches
while (true) {
// Fetch a batch of articles
$articles = $repo->findBy([], ['createdAt' => 'DESC'], self::BATCH_SIZE, $page * self::BATCH_SIZE);
if (empty($articles)) {
break;
}
foreach ($articles as $article) {
$slug = $article->getSlug();
// If this slug hasn't been seen, store the slug
if (!in_array($slug, $slugIndex)) {
$slugIndex[] = $slug;
continue;
}
// The articles are sorted, so the first one should be kept
// Mark current article as DO_NOT_INDEX
$article->setIndexStatus(IndexStatusEnum::DO_NOT_INDEX);
}
// Flush the batch and clear memory to avoid overload
$this->em->flush();
$this->em->clear(); // Clear the entity manager to free up memory
$output->writeln("Processed batch " . ($page + 1));
$page++;
}
$output->writeln('Article deduplication complete.');
return Command::SUCCESS;
}
}

41
src/Command/MarkAsIndexedCommand.php

@ -1,41 +0,0 @@ @@ -1,41 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Command;
use App\Entity\Article;
use App\Enum\IndexStatusEnum;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
#[AsCommand(name: 'articles:indexed', description: 'Mark articles as indexed after populating')]
class MarkAsIndexedCommand extends Command
{
public function __construct(private readonly EntityManagerInterface $entityManager)
{
parent::__construct();
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$articles = $this->entityManager->getRepository(Article::class)->findBy(['indexStatus' => IndexStatusEnum::TO_BE_INDEXED]);
$count = 0;
foreach ($articles as $article) {
if ($article instanceof Article) {
$count += 1;
$article->setIndexStatus(IndexStatusEnum::INDEXED);
$this->entityManager->persist($article);
}
}
$this->entityManager->flush();
$output->writeln($count . ' articles marked as indexed successfully.');
return Command::SUCCESS;
}
}

69
src/Service/CacheService.php

@ -0,0 +1,69 @@ @@ -0,0 +1,69 @@
<?php
namespace App\Service;
use Psr\Cache\InvalidArgumentException;
use Psr\Log\LoggerInterface;
use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\ItemInterface;
readonly class CacheService
{
public function __construct(
private NostrClient $nostrClient,
private CacheInterface $cache,
private LoggerInterface $logger
)
{
}
/**
* @param string $npub
* @return \stdClass
*/
public function getMetadata(string $npub): \stdClass
{
$cacheKey = '0_' . $npub;
try {
return $this->cache->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 = '3_' . $npub;
try {
return $this->cache->get($cacheKey, function (ItemInterface $item) use ($npub) {
$item->expiresAfter(3600); // 1 hour
try {
return $this->nostrClient->getRelaysForNpub($npub);
} catch (\Exception $e) {
$this->logger->error('Error getting relays.', ['exception' => $e]);
return [];
}
});
} catch (InvalidArgumentException $e) {
$this->logger->error('Error getting relay data.', ['exception' => $e]);
return [];
}
}
}

10
src/Service/NostrClient.php

@ -28,12 +28,6 @@ class NostrClient @@ -28,12 +28,6 @@ class NostrClient
*/
private const array REPUTABLE_RELAYS = [
'wss://theforest.nostr1.com',
'wss://relay.damus.io',
'wss://relay.primal.net',
'wss://nos.lol',
'wss://relay.snort.social',
'wss://nostr.land',
'wss://purplepag.es',
];
public function __construct(private readonly EntityManagerInterface $entityManager,
@ -43,9 +37,7 @@ class NostrClient @@ -43,9 +37,7 @@ class NostrClient
private readonly LoggerInterface $logger)
{
$this->defaultRelaySet = new RelaySet();
$this->defaultRelaySet->addRelay(new Relay('wss://theforest.nostr1.com')); // public aggregator relay
$this->defaultRelaySet->addRelay(new Relay('wss://relay.damus.io')); // public aggregator relay
$this->defaultRelaySet->addRelay(new Relay('wss://relay.primal.net')); // public aggregator relay
$this->defaultRelaySet->addRelay(new Relay('wss://theforest.nostr1.com'));
}
/**

Loading…
Cancel
Save