From 9166b4bbc8418856c83dc9998aa5bcd7497d9657 Mon Sep 17 00:00:00 2001 From: Brock H Caldwell Date: Sat, 3 May 2025 23:55:31 -0500 Subject: [PATCH] feat: movie monitoring --- .env.dev | 1 + compose.yml | 7 + composer.json | 3 +- composer.lock | 583 ++++++++++-------- config/packages/messenger.yaml | 12 +- src/Controller/DownloadController.php | 15 +- .../Action/Command/MonitorMovieCommand.php | 1 - .../Action/Handler/MonitorMovieHandler.php | 15 +- .../Action/Input/AddMovieMonitorInput.php | 8 +- .../DownloadMediaMessageHandler.php | 20 - .../Scheduler/MovieMonitorDispatcher.php | 29 + .../Service/MonitorOptionEvaluator.php | 1 - src/Schedule.php | 29 + src/Tmdb/Tmdb.php | 91 ++- symfony.lock | 12 + templates/search/result.html.twig | 3 +- 16 files changed, 477 insertions(+), 353 deletions(-) delete mode 100644 src/Download/Framework/MessageHandler/DownloadMediaMessageHandler.php create mode 100644 src/Download/Framework/Scheduler/MovieMonitorDispatcher.php create mode 100644 src/Schedule.php diff --git a/.env.dev b/.env.dev index cab7624..a65b9e2 100644 --- a/.env.dev +++ b/.env.dev @@ -5,3 +5,4 @@ DOWNLOAD_DIR=./movies MERCURE_URL=http://mercure/.well-known/mercure MERCURE_PUBLIC_URL=https://dev.caldwell.digital/hub/.well-known/mercure MERCURE_JWT_SECRET="!ChangeThisMercureHubJWTSecretKey!" +MONITOR_FREQUENCY="* * * * *" diff --git a/compose.yml b/compose.yml index 3ac7485..a751135 100755 --- a/compose.yml +++ b/compose.yml @@ -31,6 +31,13 @@ services: - ./var/download:/var/download command: php ./bin/console messenger:consume async -v --time-limit=3600 --limit=10 + scheduler: + build: . + volumes: + - ./:/var/www + - ./var/download:/var/download + command: php ./bin/console messenger:consume scheduler_movie_monitor -v --time-limit=3600 + mercure: image: dunglas/mercure restart: unless-stopped diff --git a/composer.json b/composer.json index 132aeb6..3cae811 100644 --- a/composer.json +++ b/composer.json @@ -9,11 +9,11 @@ "ext-iconv": "*", "1tomany/rich-bundle": "^1.8", "aimeos/map": "^3.12", - "carbondate/carbon": "*", "doctrine/dbal": "^3", "doctrine/doctrine-bundle": "^2.14", "doctrine/doctrine-migrations-bundle": "^3.4", "doctrine/orm": "^3.3", + "dragonmantank/cron-expression": "^3.4", "nihilarr/parse-torrent-name": "^0.0.1", "nyholm/psr7": "*", "p3k/emoji-detector": "^1.2", @@ -29,6 +29,7 @@ "symfony/mercure-bundle": "^0.3.9", "symfony/messenger": "7.2.*", "symfony/runtime": "7.2.*", + "symfony/scheduler": "7.2.*", "symfony/security-bundle": "7.2.*", "symfony/stimulus-bundle": "^2.24", "symfony/twig-bundle": "7.2.*", diff --git a/composer.lock b/composer.lock index 7c9b30a..487ef6a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,85 +4,23 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "909a198b48a473bd53de5b78a2abac1c", + "content-hash": "97689e103d8e0ba79aba71891384895d", "packages": [ - { - "name": "1tomany/data-uri", - "version": "v3.0.0", - "source": { - "type": "git", - "url": "https://github.com/1tomany/data-uri.git", - "reference": "aa347c52ad3494ed3c361a7c47e08ad563f18c6c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/1tomany/data-uri/zipball/aa347c52ad3494ed3c361a7c47e08ad563f18c6c", - "reference": "aa347c52ad3494ed3c361a7c47e08ad563f18c6c", - "shasum": "" - }, - "require": { - "ext-fileinfo": "*", - "php": ">=8.4", - "symfony/filesystem": "^7.2" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^3.74", - "phpstan/phpstan": "^2.1", - "phpunit/phpunit": "^11.5" - }, - "type": "library", - "autoload": { - "files": [ - "src/parse_data.php" - ], - "psr-4": { - "OneToMany\\DataUri\\": "src/" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Vic Cherubini", - "email": "vcherubini@gmail.com" - } - ], - "description": "A simple, low dependency library to parse and decode data URIs defined in RFC 2397", - "keywords": [ - "2397", - "data uri", - "data-uri", - "dataURI", - "rfc 2397", - "rfc2397" - ], - "support": { - "issues": "https://github.com/1tomany/data-uri/issues", - "source": "https://github.com/1tomany/data-uri/tree/v3.0.0" - }, - "time": "2025-04-10T18:21:18+00:00" - }, { "name": "1tomany/rich-bundle", - "version": "v1.8.3", + "version": "v1.9.5", "source": { "type": "git", "url": "https://github.com/1tomany/rich-bundle.git", - "reference": "a4f9dd90b7fbc00877a3eef873d8d643a8e80f69" + "reference": "434c0fa70aefa11a23342006a10221360beb0f71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/1tomany/rich-bundle/zipball/a4f9dd90b7fbc00877a3eef873d8d643a8e80f69", - "reference": "a4f9dd90b7fbc00877a3eef873d8d643a8e80f69", + "url": "https://api.github.com/repos/1tomany/rich-bundle/zipball/434c0fa70aefa11a23342006a10221360beb0f71", + "reference": "434c0fa70aefa11a23342006a10221360beb0f71", "shasum": "" }, "require": { - "1tomany/data-uri": "^3.0", "opis/json-schema": "^2.4", "php": ">=8.4", "symfony/dependency-injection": "^7.2", @@ -99,6 +37,10 @@ "phpstan/phpstan": "^2.1", "phpunit/phpunit": "^11.5" }, + "suggest": { + "1tomany/data-uri": "Provides a data URI parser and file object for handling file uploads", + "symfony/security-bundle": "Provides autowired TokenStorageInterface to extract authenticated users" + }, "type": "symfony-bundle", "autoload": { "psr-4": { @@ -118,9 +60,9 @@ "description": "Symfony bundle that provides easy scaffolding to build RICH applications", "support": { "issues": "https://github.com/1tomany/rich-bundle/issues", - "source": "https://github.com/1tomany/rich-bundle/tree/v1.8.3" + "source": "https://github.com/1tomany/rich-bundle/tree/v1.9.5" }, - "time": "2025-04-14T20:49:47+00:00" + "time": "2025-05-01T16:54:44+00:00" }, { "name": "aimeos/map", @@ -175,57 +117,6 @@ }, "time": "2025-03-05T09:16:18+00:00" }, - { - "name": "carbondate/carbon", - "version": "1.17.0", - "source": { - "type": "git", - "url": "https://github.com/CarbonDate/Carbon.git", - "reference": "a1dd1ad9abfc8b3c4d8768068e6c71d293424e86" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/CarbonDate/Carbon/zipball/a1dd1ad9abfc8b3c4d8768068e6c71d293424e86", - "reference": "a1dd1ad9abfc8b3c4d8768068e6c71d293424e86", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "autoload": { - "psr-0": { - "Carbon": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Brian Nesbitt", - "email": "brian@nesbot.com", - "homepage": "http://nesbot.com" - } - ], - "description": "A simple API extension for DateTime.", - "homepage": "http://carbon.nesbot.com", - "keywords": [ - "date", - "datetime", - "time" - ], - "support": { - "issues": "https://github.com/CarbonDate/Carbon/issues", - "source": "https://github.com/CarbonDate/Carbon/tree/1.17.0" - }, - "abandoned": true, - "time": "2015-03-08T14:05:44+00:00" - }, { "name": "composer/semver", "version": "3.4.3", @@ -1287,16 +1178,16 @@ }, { "name": "doctrine/orm", - "version": "3.3.2", + "version": "3.3.3", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "c9557c588b3a70ed93caff069d0aa75737f25609" + "reference": "1f1891d3e20ef9881e81c2f32c53e9dc88dfc9a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/c9557c588b3a70ed93caff069d0aa75737f25609", - "reference": "c9557c588b3a70ed93caff069d0aa75737f25609", + "url": "https://api.github.com/repos/doctrine/orm/zipball/1f1891d3e20ef9881e81c2f32c53e9dc88dfc9a7", + "reference": "1f1891d3e20ef9881e81c2f32c53e9dc88dfc9a7", "shasum": "" }, "require": { @@ -1316,7 +1207,7 @@ "symfony/var-exporter": "^6.3.9 || ^7.0" }, "require-dev": { - "doctrine/coding-standard": "^12.0", + "doctrine/coding-standard": "^13.0", "phpbench/phpbench": "^1.0", "phpdocumentor/guides-cli": "^1.4", "phpstan/extension-installer": "^1.4", @@ -1324,7 +1215,7 @@ "phpstan/phpstan-deprecation-rules": "^2", "phpunit/phpunit": "^10.4.0", "psr/log": "^1 || ^2 || ^3", - "squizlabs/php_codesniffer": "3.7.2", + "squizlabs/php_codesniffer": "3.12.0", "symfony/cache": "^5.4 || ^6.2 || ^7.0" }, "suggest": { @@ -1371,9 +1262,9 @@ ], "support": { "issues": "https://github.com/doctrine/orm/issues", - "source": "https://github.com/doctrine/orm/tree/3.3.2" + "source": "https://github.com/doctrine/orm/tree/3.3.3" }, - "time": "2025-02-04T19:43:15+00:00" + "time": "2025-05-02T17:42:51+00:00" }, { "name": "doctrine/persistence", @@ -1525,6 +1416,71 @@ }, "time": "2025-01-24T11:45:48+00:00" }, + { + "name": "dragonmantank/cron-expression", + "version": "v3.4.0", + "source": { + "type": "git", + "url": "https://github.com/dragonmantank/cron-expression.git", + "reference": "8c784d071debd117328803d86b2097615b457500" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500", + "reference": "8c784d071debd117328803d86b2097615b457500", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0", + "webmozart/assert": "^1.0" + }, + "replace": { + "mtdowling/cron-expression": "^1.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.0", + "phpunit/phpunit": "^7.0|^8.0|^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Cron\\": "src/Cron/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Tankersley", + "email": "chris@ctankersley.com", + "homepage": "https://github.com/dragonmantank" + } + ], + "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", + "keywords": [ + "cron", + "schedule" + ], + "support": { + "issues": "https://github.com/dragonmantank/cron-expression/issues", + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0" + }, + "funding": [ + { + "url": "https://github.com/dragonmantank", + "type": "github" + } + ], + "time": "2024-10-09T13:47:03+00:00" + }, { "name": "lcobucci/jwt", "version": "5.5.0", @@ -3094,16 +3050,16 @@ }, { "name": "symfony/cache", - "version": "v7.2.5", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "9131e3018872d2ebb6fe8a9a4d6631273513d42c" + "reference": "8b49dde3f5a5e9867595a3a269977f78418d75ee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/9131e3018872d2ebb6fe8a9a4d6631273513d42c", - "reference": "9131e3018872d2ebb6fe8a9a4d6631273513d42c", + "url": "https://api.github.com/repos/symfony/cache/zipball/8b49dde3f5a5e9867595a3a269977f78418d75ee", + "reference": "8b49dde3f5a5e9867595a3a269977f78418d75ee", "shasum": "" }, "require": { @@ -3172,7 +3128,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v7.2.5" + "source": "https://github.com/symfony/cache/tree/v7.2.6" }, "funding": [ { @@ -3188,7 +3144,7 @@ "type": "tidelift" } ], - "time": "2025-03-25T15:54:33+00:00" + "time": "2025-04-08T09:06:23+00:00" }, { "name": "symfony/cache-contracts", @@ -3342,16 +3298,16 @@ }, { "name": "symfony/config", - "version": "v7.2.3", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "7716594aaae91d9141be080240172a92ecca4d44" + "reference": "e0b050b83ba999aa77a3736cb6d5b206d65b9d0d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/7716594aaae91d9141be080240172a92ecca4d44", - "reference": "7716594aaae91d9141be080240172a92ecca4d44", + "url": "https://api.github.com/repos/symfony/config/zipball/e0b050b83ba999aa77a3736cb6d5b206d65b9d0d", + "reference": "e0b050b83ba999aa77a3736cb6d5b206d65b9d0d", "shasum": "" }, "require": { @@ -3397,7 +3353,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v7.2.3" + "source": "https://github.com/symfony/config/tree/v7.2.6" }, "funding": [ { @@ -3413,20 +3369,20 @@ "type": "tidelift" } ], - "time": "2025-01-22T12:07:01+00:00" + "time": "2025-04-03T21:14:15+00:00" }, { "name": "symfony/console", - "version": "v7.2.5", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "e51498ea18570c062e7df29d05a7003585b19b88" + "reference": "0e2e3f38c192e93e622e41ec37f4ca70cfedf218" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/e51498ea18570c062e7df29d05a7003585b19b88", - "reference": "e51498ea18570c062e7df29d05a7003585b19b88", + "url": "https://api.github.com/repos/symfony/console/zipball/0e2e3f38c192e93e622e41ec37f4ca70cfedf218", + "reference": "0e2e3f38c192e93e622e41ec37f4ca70cfedf218", "shasum": "" }, "require": { @@ -3490,7 +3446,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.2.5" + "source": "https://github.com/symfony/console/tree/v7.2.6" }, "funding": [ { @@ -3506,20 +3462,20 @@ "type": "tidelift" } ], - "time": "2025-03-12T08:11:12+00:00" + "time": "2025-04-07T19:09:28+00:00" }, { "name": "symfony/dependency-injection", - "version": "v7.2.5", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "58ab71379f14a741755717cece2868bf41ed45d8" + "reference": "2ca85496cde37f825bd14f7e3548e2793ca90712" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/58ab71379f14a741755717cece2868bf41ed45d8", - "reference": "58ab71379f14a741755717cece2868bf41ed45d8", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/2ca85496cde37f825bd14f7e3548e2793ca90712", + "reference": "2ca85496cde37f825bd14f7e3548e2793ca90712", "shasum": "" }, "require": { @@ -3570,7 +3526,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v7.2.5" + "source": "https://github.com/symfony/dependency-injection/tree/v7.2.6" }, "funding": [ { @@ -3586,7 +3542,7 @@ "type": "tidelift" } ], - "time": "2025-03-13T12:21:46+00:00" + "time": "2025-04-27T13:37:55+00:00" }, { "name": "symfony/deprecation-contracts", @@ -3657,16 +3613,16 @@ }, { "name": "symfony/doctrine-bridge", - "version": "v7.2.5", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "f8a298bbb8eaca08d787bf4d4c74728f1cf98922" + "reference": "d030ea0d45746bf58d7905402bd45e9c35d412dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/f8a298bbb8eaca08d787bf4d4c74728f1cf98922", - "reference": "f8a298bbb8eaca08d787bf4d4c74728f1cf98922", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/d030ea0d45746bf58d7905402bd45e9c35d412dd", + "reference": "d030ea0d45746bf58d7905402bd45e9c35d412dd", "shasum": "" }, "require": { @@ -3746,7 +3702,7 @@ "description": "Provides integration for Doctrine with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-bridge/tree/v7.2.5" + "source": "https://github.com/symfony/doctrine-bridge/tree/v7.2.6" }, "funding": [ { @@ -3762,7 +3718,7 @@ "type": "tidelift" } ], - "time": "2025-03-25T15:54:33+00:00" + "time": "2025-04-27T13:34:41+00:00" }, { "name": "symfony/doctrine-messenger", @@ -4341,16 +4297,16 @@ }, { "name": "symfony/form", - "version": "v7.2.5", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/form.git", - "reference": "81c5d4630d58a5ca3cfa7ac6f44070ed02568009" + "reference": "e4e75b930d7a1ccd47bd3273c859c28e13d89b08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/form/zipball/81c5d4630d58a5ca3cfa7ac6f44070ed02568009", - "reference": "81c5d4630d58a5ca3cfa7ac6f44070ed02568009", + "url": "https://api.github.com/repos/symfony/form/zipball/e4e75b930d7a1ccd47bd3273c859c28e13d89b08", + "reference": "e4e75b930d7a1ccd47bd3273c859c28e13d89b08", "shasum": "" }, "require": { @@ -4418,7 +4374,7 @@ "description": "Allows to easily create, process and reuse HTML forms", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/form/tree/v7.2.5" + "source": "https://github.com/symfony/form/tree/v7.2.6" }, "funding": [ { @@ -4434,7 +4390,7 @@ "type": "tidelift" } ], - "time": "2025-03-28T12:59:59+00:00" + "time": "2025-04-30T07:52:47+00:00" }, { "name": "symfony/framework-bundle", @@ -4761,16 +4717,16 @@ }, { "name": "symfony/http-foundation", - "version": "v7.2.5", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "371272aeb6286f8135e028ca535f8e4d6f114126" + "reference": "6023ec7607254c87c5e69fb3558255aca440d72b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/371272aeb6286f8135e028ca535f8e4d6f114126", - "reference": "371272aeb6286f8135e028ca535f8e4d6f114126", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/6023ec7607254c87c5e69fb3558255aca440d72b", + "reference": "6023ec7607254c87c5e69fb3558255aca440d72b", "shasum": "" }, "require": { @@ -4819,7 +4775,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.2.5" + "source": "https://github.com/symfony/http-foundation/tree/v7.2.6" }, "funding": [ { @@ -4835,20 +4791,20 @@ "type": "tidelift" } ], - "time": "2025-03-25T15:54:33+00:00" + "time": "2025-04-09T08:14:01+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.2.5", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "b1fe91bc1fa454a806d3f98db4ba826eb9941a54" + "reference": "f9dec01e6094a063e738f8945ef69c0cfcf792ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/b1fe91bc1fa454a806d3f98db4ba826eb9941a54", - "reference": "b1fe91bc1fa454a806d3f98db4ba826eb9941a54", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/f9dec01e6094a063e738f8945ef69c0cfcf792ec", + "reference": "f9dec01e6094a063e738f8945ef69c0cfcf792ec", "shasum": "" }, "require": { @@ -4933,7 +4889,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.2.5" + "source": "https://github.com/symfony/http-kernel/tree/v7.2.6" }, "funding": [ { @@ -4949,7 +4905,7 @@ "type": "tidelift" } ], - "time": "2025-03-28T13:32:50+00:00" + "time": "2025-05-02T09:04:03+00:00" }, { "name": "symfony/mercure", @@ -5120,16 +5076,16 @@ }, { "name": "symfony/messenger", - "version": "v7.2.5", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/messenger.git", - "reference": "3ea7cdba88df1f36dad96289291a32cd9ab1862f" + "reference": "7f71d9d08c7708b758477386e7eaaa8ac78063b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/messenger/zipball/3ea7cdba88df1f36dad96289291a32cd9ab1862f", - "reference": "3ea7cdba88df1f36dad96289291a32cd9ab1862f", + "url": "https://api.github.com/repos/symfony/messenger/zipball/7f71d9d08c7708b758477386e7eaaa8ac78063b5", + "reference": "7f71d9d08c7708b758477386e7eaaa8ac78063b5", "shasum": "" }, "require": { @@ -5187,7 +5143,7 @@ "description": "Helps applications send and receive messages to/from other applications or via message queues", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/messenger/tree/v7.2.5" + "source": "https://github.com/symfony/messenger/tree/v7.2.6" }, "funding": [ { @@ -5203,7 +5159,7 @@ "type": "tidelift" } ], - "time": "2025-03-04T12:34:02+00:00" + "time": "2025-04-27T13:34:41+00:00" }, { "name": "symfony/options-resolver", @@ -5346,7 +5302,7 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", @@ -5404,7 +5360,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0" }, "funding": [ { @@ -5424,16 +5380,16 @@ }, { "name": "symfony/polyfill-intl-icu", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-icu.git", - "reference": "d80a05e9904d2c2b9b95929f3e4b5d3a8f418d78" + "reference": "763d2a91fea5681509ca01acbc1c5e450d127811" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/d80a05e9904d2c2b9b95929f3e4b5d3a8f418d78", - "reference": "d80a05e9904d2c2b9b95929f3e4b5d3a8f418d78", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/763d2a91fea5681509ca01acbc1c5e450d127811", + "reference": "763d2a91fea5681509ca01acbc1c5e450d127811", "shasum": "" }, "require": { @@ -5488,7 +5444,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.32.0" }, "funding": [ { @@ -5504,11 +5460,11 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-12-21T18:38:29+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -5569,7 +5525,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0" }, "funding": [ { @@ -5589,19 +5545,20 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", "shasum": "" }, "require": { + "ext-iconv": "*", "php": ">=7.2" }, "provide": { @@ -5649,7 +5606,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" }, "funding": [ { @@ -5665,11 +5622,11 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-12-23T08:48:59+00:00" }, { "name": "symfony/polyfill-php83", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", @@ -5725,7 +5682,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.32.0" }, "funding": [ { @@ -5745,16 +5702,16 @@ }, { "name": "symfony/polyfill-php84", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php84.git", - "reference": "e5493eb51311ab0b1cc2243416613f06ed8f18bd" + "reference": "000df7860439609837bbe28670b0be15783b7fbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/e5493eb51311ab0b1cc2243416613f06ed8f18bd", - "reference": "e5493eb51311ab0b1cc2243416613f06ed8f18bd", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/000df7860439609837bbe28670b0be15783b7fbf", + "reference": "000df7860439609837bbe28670b0be15783b7fbf", "shasum": "" }, "require": { @@ -5801,7 +5758,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php84/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php84/tree/v1.32.0" }, "funding": [ { @@ -5817,7 +5774,7 @@ "type": "tidelift" } ], - "time": "2024-09-09T12:04:04+00:00" + "time": "2025-02-20T12:04:08+00:00" }, { "name": "symfony/process", @@ -6201,6 +6158,86 @@ ], "time": "2024-12-29T21:39:47+00:00" }, + { + "name": "symfony/scheduler", + "version": "v7.2.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/scheduler.git", + "reference": "9c23765119e5a373ea88dc1efa0c85ce933957f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/scheduler/zipball/9c23765119e5a373ea88dc1efa0c85ce933957f4", + "reference": "9c23765119e5a373ea88dc1efa0c85ce933957f4", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/clock": "^6.4|^7.0" + }, + "require-dev": { + "dragonmantank/cron-expression": "^3.1", + "symfony/cache": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Scheduler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Sergey Rabochiy", + "email": "upyx.00@gmail.com" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides scheduling through Symfony Messenger", + "homepage": "https://symfony.com", + "keywords": [ + "cron", + "schedule", + "scheduler" + ], + "support": { + "source": "https://github.com/symfony/scheduler/tree/v7.2.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-01-17T10:56:55+00:00" + }, { "name": "symfony/security-bundle", "version": "v7.2.3", @@ -6309,16 +6346,16 @@ }, { "name": "symfony/security-core", - "version": "v7.2.3", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/security-core.git", - "reference": "466784ffcd0b5a16e05394335897f790b17d07e4" + "reference": "340e120d26b3bf5eee5cea0782aebaa2f36b6722" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-core/zipball/466784ffcd0b5a16e05394335897f790b17d07e4", - "reference": "466784ffcd0b5a16e05394335897f790b17d07e4", + "url": "https://api.github.com/repos/symfony/security-core/zipball/340e120d26b3bf5eee5cea0782aebaa2f36b6722", + "reference": "340e120d26b3bf5eee5cea0782aebaa2f36b6722", "shasum": "" }, "require": { @@ -6376,7 +6413,7 @@ "description": "Symfony Security Component - Core Library", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-core/tree/v7.2.3" + "source": "https://github.com/symfony/security-core/tree/v7.2.6" }, "funding": [ { @@ -6392,7 +6429,7 @@ "type": "tidelift" } ], - "time": "2025-01-27T11:08:17+00:00" + "time": "2025-04-17T08:47:02+00:00" }, { "name": "symfony/security-csrf", @@ -6466,16 +6503,16 @@ }, { "name": "symfony/security-http", - "version": "v7.2.4", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/security-http.git", - "reference": "8478e95e273f8daa23bf4860dbad2a09d3fb3722" + "reference": "324425deb859c6a59a2c2414ae60f742976a193b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-http/zipball/8478e95e273f8daa23bf4860dbad2a09d3fb3722", - "reference": "8478e95e273f8daa23bf4860dbad2a09d3fb3722", + "url": "https://api.github.com/repos/symfony/security-http/zipball/324425deb859c6a59a2c2414ae60f742976a193b", + "reference": "324425deb859c6a59a2c2414ae60f742976a193b", "shasum": "" }, "require": { @@ -6534,7 +6571,7 @@ "description": "Symfony Security Component - HTTP Integration", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-http/tree/v7.2.4" + "source": "https://github.com/symfony/security-http/tree/v7.2.6" }, "funding": [ { @@ -6550,20 +6587,20 @@ "type": "tidelift" } ], - "time": "2025-02-11T16:46:20+00:00" + "time": "2025-04-07T19:09:28+00:00" }, { "name": "symfony/serializer", - "version": "v7.2.5", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "d8b75b2c8144c29ac43b235738411f7cca6d584d" + "reference": "be549655b034edc1a16ed23d8164aa04318c5ec1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/d8b75b2c8144c29ac43b235738411f7cca6d584d", - "reference": "d8b75b2c8144c29ac43b235738411f7cca6d584d", + "url": "https://api.github.com/repos/symfony/serializer/zipball/be549655b034edc1a16ed23d8164aa04318c5ec1", + "reference": "be549655b034edc1a16ed23d8164aa04318c5ec1", "shasum": "" }, "require": { @@ -6632,7 +6669,7 @@ "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/serializer/tree/v7.2.5" + "source": "https://github.com/symfony/serializer/tree/v7.2.6" }, "funding": [ { @@ -6648,7 +6685,7 @@ "type": "tidelift" } ], - "time": "2025-03-24T12:37:32+00:00" + "time": "2025-04-27T13:34:41+00:00" }, { "name": "symfony/serializer-pack", @@ -6917,16 +6954,16 @@ }, { "name": "symfony/string", - "version": "v7.2.0", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82" + "reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82", - "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82", + "url": "https://api.github.com/repos/symfony/string/zipball/a214fe7d62bd4df2a76447c67c6b26e1d5e74931", + "reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931", "shasum": "" }, "require": { @@ -6984,7 +7021,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.2.0" + "source": "https://github.com/symfony/string/tree/v7.2.6" }, "funding": [ { @@ -7000,7 +7037,7 @@ "type": "tidelift" } ], - "time": "2024-11-13T13:31:26+00:00" + "time": "2025-04-20T20:18:16+00:00" }, { "name": "symfony/translation-contracts", @@ -7715,16 +7752,16 @@ }, { "name": "symfony/validator", - "version": "v7.2.5", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "d7edd7f44defbc4e0230512f929b5f4c067bb93e" + "reference": "f7c32e309885a97fc9572335e22c2c2d31f328c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/d7edd7f44defbc4e0230512f929b5f4c067bb93e", - "reference": "d7edd7f44defbc4e0230512f929b5f4c067bb93e", + "url": "https://api.github.com/repos/symfony/validator/zipball/f7c32e309885a97fc9572335e22c2c2d31f328c4", + "reference": "f7c32e309885a97fc9572335e22c2c2d31f328c4", "shasum": "" }, "require": { @@ -7792,7 +7829,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v7.2.5" + "source": "https://github.com/symfony/validator/tree/v7.2.6" }, "funding": [ { @@ -7808,20 +7845,20 @@ "type": "tidelift" } ], - "time": "2025-03-21T15:05:21+00:00" + "time": "2025-05-02T08:36:00+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.2.3", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "82b478c69745d8878eb60f9a049a4d584996f73a" + "reference": "9c46038cd4ed68952166cf7001b54eb539184ccb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/82b478c69745d8878eb60f9a049a4d584996f73a", - "reference": "82b478c69745d8878eb60f9a049a4d584996f73a", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/9c46038cd4ed68952166cf7001b54eb539184ccb", + "reference": "9c46038cd4ed68952166cf7001b54eb539184ccb", "shasum": "" }, "require": { @@ -7875,7 +7912,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.2.3" + "source": "https://github.com/symfony/var-dumper/tree/v7.2.6" }, "funding": [ { @@ -7891,20 +7928,20 @@ "type": "tidelift" } ], - "time": "2025-01-17T11:39:41+00:00" + "time": "2025-04-09T08:14:01+00:00" }, { "name": "symfony/var-exporter", - "version": "v7.2.5", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "c37b301818bd7288715d40de634f05781b686ace" + "reference": "422b8de94c738830a1e071f59ad14d67417d7007" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/c37b301818bd7288715d40de634f05781b686ace", - "reference": "c37b301818bd7288715d40de634f05781b686ace", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/422b8de94c738830a1e071f59ad14d67417d7007", + "reference": "422b8de94c738830a1e071f59ad14d67417d7007", "shasum": "" }, "require": { @@ -7951,7 +7988,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v7.2.5" + "source": "https://github.com/symfony/var-exporter/tree/v7.2.6" }, "funding": [ { @@ -7967,7 +8004,7 @@ "type": "tidelift" } ], - "time": "2025-03-13T12:21:46+00:00" + "time": "2025-05-02T08:36:00+00:00" }, { "name": "symfony/web-link", @@ -8054,16 +8091,16 @@ }, { "name": "symfony/yaml", - "version": "v7.2.5", + "version": "v7.2.6", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "4c4b6f4cfcd7e52053f0c8bfad0f7f30fb924912" + "reference": "0feafffb843860624ddfd13478f481f4c3cd8b23" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/4c4b6f4cfcd7e52053f0c8bfad0f7f30fb924912", - "reference": "4c4b6f4cfcd7e52053f0c8bfad0f7f30fb924912", + "url": "https://api.github.com/repos/symfony/yaml/zipball/0feafffb843860624ddfd13478f481f4c3cd8b23", + "reference": "0feafffb843860624ddfd13478f481f4c3cd8b23", "shasum": "" }, "require": { @@ -8106,7 +8143,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v7.2.5" + "source": "https://github.com/symfony/yaml/tree/v7.2.6" }, "funding": [ { @@ -8122,7 +8159,7 @@ "type": "tidelift" } ], - "time": "2025-03-03T07:12:39+00:00" + "time": "2025-04-04T10:10:11+00:00" }, { "name": "symfonycasts/tailwind-bundle", @@ -8182,16 +8219,16 @@ }, { "name": "twig/extra-bundle", - "version": "v3.20.0", + "version": "v3.21.0", "source": { "type": "git", "url": "https://github.com/twigphp/twig-extra-bundle.git", - "reference": "9df5e1dbb6a68c0665ae5603f6f2c20815647876" + "reference": "62d1cf47a1aa009cbd07b21045b97d3d5cb79896" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/twig-extra-bundle/zipball/9df5e1dbb6a68c0665ae5603f6f2c20815647876", - "reference": "9df5e1dbb6a68c0665ae5603f6f2c20815647876", + "url": "https://api.github.com/repos/twigphp/twig-extra-bundle/zipball/62d1cf47a1aa009cbd07b21045b97d3d5cb79896", + "reference": "62d1cf47a1aa009cbd07b21045b97d3d5cb79896", "shasum": "" }, "require": { @@ -8240,7 +8277,7 @@ "twig" ], "support": { - "source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.20.0" + "source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.21.0" }, "funding": [ { @@ -8252,20 +8289,20 @@ "type": "tidelift" } ], - "time": "2025-02-08T09:47:15+00:00" + "time": "2025-02-19T14:29:33+00:00" }, { "name": "twig/twig", - "version": "v3.20.0", + "version": "v3.21.1", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "3468920399451a384bef53cf7996965f7cd40183" + "reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/3468920399451a384bef53cf7996965f7cd40183", - "reference": "3468920399451a384bef53cf7996965f7cd40183", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/285123877d4dd97dd7c11842ac5fb7e86e60d81d", + "reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d", "shasum": "" }, "require": { @@ -8319,7 +8356,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.20.0" + "source": "https://github.com/twigphp/Twig/tree/v3.21.1" }, "funding": [ { @@ -8331,7 +8368,7 @@ "type": "tidelift" } ], - "time": "2025-02-13T08:34:43+00:00" + "time": "2025-05-03T07:21:55+00:00" }, { "name": "webmozart/assert", @@ -8453,21 +8490,21 @@ }, { "name": "symfony/maker-bundle", - "version": "v1.62.1", + "version": "v1.63.0", "source": { "type": "git", "url": "https://github.com/symfony/maker-bundle.git", - "reference": "468ff2708200c95ebc0d85d3174b6c6711b8a590" + "reference": "69478ab39bc303abfbe3293006a78b09a8512425" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/468ff2708200c95ebc0d85d3174b6c6711b8a590", - "reference": "468ff2708200c95ebc0d85d3174b6c6711b8a590", + "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/69478ab39bc303abfbe3293006a78b09a8512425", + "reference": "69478ab39bc303abfbe3293006a78b09a8512425", "shasum": "" }, "require": { "doctrine/inflector": "^2.0", - "nikic/php-parser": "^4.18|^5.0", + "nikic/php-parser": "^5.0", "php": ">=8.1", "symfony/config": "^6.4|^7.0", "symfony/console": "^6.4|^7.0", @@ -8525,7 +8562,7 @@ ], "support": { "issues": "https://github.com/symfony/maker-bundle/issues", - "source": "https://github.com/symfony/maker-bundle/tree/v1.62.1" + "source": "https://github.com/symfony/maker-bundle/tree/v1.63.0" }, "funding": [ { @@ -8541,7 +8578,7 @@ "type": "tidelift" } ], - "time": "2025-01-15T00:21:40+00:00" + "time": "2025-04-26T01:41:37+00:00" }, { "name": "symfony/web-profiler-bundle", diff --git a/config/packages/messenger.yaml b/config/packages/messenger.yaml index ca007a4..fec8db5 100644 --- a/config/packages/messenger.yaml +++ b/config/packages/messenger.yaml @@ -1,11 +1,19 @@ framework: messenger: # Uncomment this (and the failed transport below) to send failed messages to this transport for later handling. - # failure_transport: failed + failure_transport: failed transports: # https://symfony.com/doc/current/messenger.html#transport-configuration - async: '%env(MESSENGER_TRANSPORT_DSN)%' + async: + dsn: '%env(MESSENGER_TRANSPORT_DSN)%' + options: + use_notify: true + check_delayed_interval: 60000 + retry_strategy: + max_retries: 1 + multiplier: 1 + failed: 'doctrine://default?queue_name=failed' default_bus: messenger.bus.default diff --git a/src/Controller/DownloadController.php b/src/Controller/DownloadController.php index f0d0862..2730534 100644 --- a/src/Controller/DownloadController.php +++ b/src/Controller/DownloadController.php @@ -2,8 +2,9 @@ namespace App\Controller; -use App\Download\Action\Command\AddMovieMonitorCommand; +use App\Download\Action\Command\MonitorMovieCommand; use App\Download\Action\Handler\AddMovieMonitorHandler; +use App\Download\Action\Handler\MonitorMovieHandler; use App\Download\Action\Input\AddMovieMonitorInput; use App\Download\Action\Input\DownloadMediaInput; use App\Download\Framework\Repository\DownloadRepository; @@ -19,6 +20,18 @@ class DownloadController extends AbstractController private MessageBusInterface $bus, ) {} + #[Route('/test', name: 'app_test')] + public function test( + MonitorMovieHandler $handler, + ) { + $command = new MonitorMovieCommand(41); + $handler->handle($command); + return $this->json([ + 'status' => 200, + 'message' => $command + ]); + } + #[Route('/download', name: 'app_download', methods: ['POST'])] public function download( DownloadMediaInput $input, diff --git a/src/Download/Action/Command/MonitorMovieCommand.php b/src/Download/Action/Command/MonitorMovieCommand.php index ec09a74..dc9c28f 100644 --- a/src/Download/Action/Command/MonitorMovieCommand.php +++ b/src/Download/Action/Command/MonitorMovieCommand.php @@ -2,7 +2,6 @@ namespace App\Download\Action\Command; -use App\Download\Framework\Entity\MovieMonitor; use OneToMany\RichBundle\Contract\CommandInterface; class MonitorMovieCommand implements CommandInterface diff --git a/src/Download/Action/Handler/MonitorMovieHandler.php b/src/Download/Action/Handler/MonitorMovieHandler.php index 68a2afe..ed57369 100644 --- a/src/Download/Action/Handler/MonitorMovieHandler.php +++ b/src/Download/Action/Handler/MonitorMovieHandler.php @@ -10,9 +10,11 @@ use App\Download\Service\MonitorOptionEvaluator; use App\Torrentio\Action\Command\GetMovieOptionsCommand; use App\Torrentio\Action\Handler\GetMovieOptionsHandler; use DateTimeImmutable; +use Doctrine\ORM\EntityManagerInterface; use OneToMany\RichBundle\Contract\CommandInterface; use OneToMany\RichBundle\Contract\HandlerInterface; use OneToMany\RichBundle\Contract\ResultInterface; +use Psr\Log\LoggerInterface; use Symfony\Component\Messenger\MessageBusInterface; /** @implements HandlerInterface */ @@ -22,22 +24,31 @@ readonly class MonitorMovieHandler implements HandlerInterface private MovieMonitorRepository $movieMonitorRepository, private GetMovieOptionsHandler $getMovieOptionsHandler, private MonitorOptionEvaluator $monitorOptionEvaluator, + private EntityManagerInterface $entityManager, private MessageBusInterface $bus, + private LoggerInterface $logger, ) {} public function handle(CommandInterface $command): ResultInterface { + $this->logger->info('> [MonitorMovieHandler] Executing MonitorMovieHandler'); $monitor = $this->movieMonitorRepository->find($command->movieMonitorId); + $monitor->setStatus('In Progress'); + + $this->logger->info('> [MonitorMovieHandler] Searching for "' . $monitor->getTitle() . '" download options'); + $results = $this->getMovieOptionsHandler->handle( new GetMovieOptionsCommand($monitor->getTmdbId(), $monitor->getImdbId()) ); + $this->logger->info('> [MonitorMovieHandler] Found ' . count($results->results) . ' download options'); $result = $this->monitorOptionEvaluator->evaluateOptions($monitor, $results->results); if (null !== $result) { + $this->logger->info('> [MonitorMovieHandler] 1 result found: dispatching DownloadMediaCommand for "' . $result->title . '"'); $this->bus->dispatch(new DownloadMediaCommand( $result->url, - $result->title, + $monitor->getTitle(), $result->filename, 'movies', $monitor->getImdbId(), @@ -48,7 +59,7 @@ readonly class MonitorMovieHandler implements HandlerInterface $monitor->setLastSearch(new DateTimeImmutable()); $monitor->setSearchCount($monitor->getSearchCount() + 1); - $this->movieMonitorRepository->getEntityManager()->flush(); + $this->entityManager->flush(); return new MonitorMovieResult( status: 'OK', diff --git a/src/Download/Action/Input/AddMovieMonitorInput.php b/src/Download/Action/Input/AddMovieMonitorInput.php index 16773eb..37d3f7f 100644 --- a/src/Download/Action/Input/AddMovieMonitorInput.php +++ b/src/Download/Action/Input/AddMovieMonitorInput.php @@ -14,18 +14,18 @@ class AddMovieMonitorInput implements InputInterface #[SourceSecurity] public string $userEmail, - #[SourceRoute('title')] - public string $title, - #[SourceRoute('tmdbId')] public string $tmdbId, #[SourceRoute('imdbId')] public string $imdbId, + + #[SourceRoute('title')] + public string $title, ) {} public function toCommand(): CommandInterface { - return new AddMovieMonitorCommand($this->userEmail, $this->title, $this->tmdbId, $this->imdbId); + return new AddMovieMonitorCommand($this->userEmail, $this->title, $this->imdbId, $this->tmdbId); } } diff --git a/src/Download/Framework/MessageHandler/DownloadMediaMessageHandler.php b/src/Download/Framework/MessageHandler/DownloadMediaMessageHandler.php deleted file mode 100644 index 1be4208..0000000 --- a/src/Download/Framework/MessageHandler/DownloadMediaMessageHandler.php +++ /dev/null @@ -1,20 +0,0 @@ -downloadMediaHandler->handle($command); - } -} \ No newline at end of file diff --git a/src/Download/Framework/Scheduler/MovieMonitorDispatcher.php b/src/Download/Framework/Scheduler/MovieMonitorDispatcher.php new file mode 100644 index 0000000..0b43876 --- /dev/null +++ b/src/Download/Framework/Scheduler/MovieMonitorDispatcher.php @@ -0,0 +1,29 @@ +logger->info('[MovieMonitorDispatcher] Executing MovieMonitorDispatcher'); + $monitors = $this->movieMonitorRepository->findBy(['status' => ['New', 'In Progress']]); + + foreach ($monitors as $monitor) { + $this->logger->info('[MovieMonitorDispatcher] Dispatching MovieMonitorCommand for ' . $monitor->getTitle()); + $this->bus->dispatch(new MonitorMovieCommand($monitor->getId())); + } + } +} diff --git a/src/Download/Service/MonitorOptionEvaluator.php b/src/Download/Service/MonitorOptionEvaluator.php index 6387496..bee492b 100644 --- a/src/Download/Service/MonitorOptionEvaluator.php +++ b/src/Download/Service/MonitorOptionEvaluator.php @@ -53,7 +53,6 @@ class MonitorOptionEvaluator $sizeMatches = []; foreach ($bestMatches as $result) { - $size = 0; if (str_contains($result->size, 'GB')) { $size = (int) trim(str_replace('GB', '', $result->size)) * 1024; } else { diff --git a/src/Schedule.php b/src/Schedule.php new file mode 100644 index 0000000..b35acf0 --- /dev/null +++ b/src/Schedule.php @@ -0,0 +1,29 @@ +stateful($this->cache) // ensure missed tasks are executed + ->processOnlyLastMissedRun(true) // ensure only last missed task is run + + // add your own tasks here + // see https://symfony.com/doc/current/scheduler.html#attaching-recurring-messages-to-a-schedule + ; + } +} diff --git a/src/Tmdb/Tmdb.php b/src/Tmdb/Tmdb.php index 2fc8cdc..cca86fd 100644 --- a/src/Tmdb/Tmdb.php +++ b/src/Tmdb/Tmdb.php @@ -3,7 +3,6 @@ namespace App\Tmdb; use App\Enum\MediaType; -use App\Tmdb\TmdbResult; use App\ValueObject\ResultFactory; use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -18,12 +17,8 @@ use Tmdb\Event\Listener\Request\ContentTypeJsonRequestListener; use Tmdb\Event\Listener\Request\UserAgentRequestListener; use Tmdb\Event\Listener\RequestListener; use Tmdb\Event\RequestEvent; -use Tmdb\Model\AbstractModel; -use Tmdb\Model\Image; use Tmdb\Model\Movie; -use Tmdb\Model\Movie\QueryParameter\AppendToResponse; use Tmdb\Model\Search\SearchQuery\KeywordSearchQuery; -use Tmdb\Model\Search\SearchQuery\MovieSearchQuery; use Tmdb\Model\Tv; use Tmdb\Repository\MovieRepository; use Tmdb\Repository\SearchRepository; @@ -210,55 +205,59 @@ class Tmdb throw new \Exception("A media type must be set when parsing from an array."); } - function parseTvShow(array $data, string $posterBasePath): TmdbResult { - return new TmdbResult( - imdbId: $data['external_ids']['imdb_id'], - tmdbId: $data['id'], - title: $data['name'], - poster: $posterBasePath . $data['poster_path'], - description: $data['overview'], - year: (new \DateTime($data['first_air_date']))->format('Y'), - mediaType: "tvshows", - episodes: $data['episodes'], - ); - } - - function parseEpisode(array $data, string $posterBasePath): TmdbResult { - return new TmdbResult( - imdbId: $data['external_ids']['imdb_id'], - tmdbId: $data['id'], - title: $data['name'], - poster: $posterBasePath . $data['still_path'], - description: $data['overview'], - year: (new \DateTime($data['air_date']))->format('Y'), - mediaType: "tvshows", - episodes: null, - ); - } - - function parseMovie(array $data, string $posterBasePath): TmdbResult { - return new TmdbResult( - imdbId: $data['external_ids']['imdb_id'], - tmdbId: $data['id'], - title: $data['title'], - poster: $posterBasePath . $data['poster_path'], - description: $data['overview'], - year: (new \DateTime($data['release_date']))->format('Y'), - mediaType: "movies", - ); - } - if ($mediaType === 'movie') { - $result = parseMovie($data, self::POSTER_IMG_PATH); + $result = $this->parseMovie($data, self::POSTER_IMG_PATH); } elseif ($mediaType === 'tvshow') { - $result = parseTvShow($data, self::POSTER_IMG_PATH); + $result = $this->parseTvShow($data, self::POSTER_IMG_PATH); } elseif ($mediaType === 'episode') { - $result = parseEpisode($data, self::POSTER_IMG_PATH); + $result = $this->parseEpisode($data, self::POSTER_IMG_PATH); } return $result; } + private function parseTvShow(array $data, string $posterBasePath): TmdbResult + { + return new TmdbResult( + imdbId: $data['external_ids']['imdb_id'], + tmdbId: $data['id'], + title: $data['name'], + poster: $posterBasePath . $data['poster_path'], + description: $data['overview'], + year: (new \DateTime($data['first_air_date']))->format('Y'), + mediaType: "tvshows", + episodes: $data['episodes'], + ); + } + + private function parseEpisode(array $data, string $posterBasePath): TmdbResult + { + return new TmdbResult( + imdbId: $data['external_ids']['imdb_id'], + tmdbId: $data['id'], + title: $data['name'], + poster: $posterBasePath . $data['still_path'], + description: $data['overview'], + year: (new \DateTime($data['air_date']))->format('Y'), + mediaType: "tvshows", + episodes: null, + ); + } + + private function parseMovie(array $data, string $posterBasePath): TmdbResult + { + return new TmdbResult( + imdbId: $data['external_ids']['imdb_id'], + tmdbId: $data['id'], + title: $data['title'], + poster: $posterBasePath . $data['poster_path'], + description: $data['overview'], + year: (new \DateTime($data['release_date']))->format('Y'), + mediaType: "movies", + ); + } + + private function parseFromObject($result): TmdbResult { $mediaType = $result instanceof Movie ? MediaType::Movie->value : MediaType::TvShow->value; diff --git a/symfony.lock b/symfony.lock index 3359319..150143d 100644 --- a/symfony.lock +++ b/symfony.lock @@ -158,6 +158,18 @@ "config/routes.yaml" ] }, + "symfony/scheduler": { + "version": "7.2", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "7.2", + "ref": "caea3c928ee9e1b21288fd76aef36f16ea355515" + }, + "files": [ + "src/Schedule.php" + ] + }, "symfony/security-bundle": { "version": "7.2", "recipe": { diff --git a/templates/search/result.html.twig b/templates/search/result.html.twig index 70a3ff4..9490bdf 100644 --- a/templates/search/result.html.twig +++ b/templates/search/result.html.twig @@ -16,9 +16,8 @@