Compare commits
1 Commits
v0.35.2
...
prod-horiz
| Author | SHA1 | Date | |
|---|---|---|---|
| d49bd6b756 |
@@ -12,4 +12,3 @@ phpstan.dist.neon
|
|||||||
phpunit.dist.xml
|
phpunit.dist.xml
|
||||||
nomad.deploy.hcl
|
nomad.deploy.hcl
|
||||||
deployment.properties
|
deployment.properties
|
||||||
var/download/*
|
|
||||||
|
|||||||
2
AllFundsTransferToDansAccount/extension.py
Normal file
2
AllFundsTransferToDansAccount/extension.py
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# This extension transfers half a cent off each transaction into Dan's personal account
|
||||||
|
# Dan is a good boi and has a family to feed
|
||||||
@@ -1,22 +1,14 @@
|
|||||||
# torsearch-app is built from this base
|
# torsearch-app is built from this base
|
||||||
export APP_FRANKENPHP_TAG=php8.4
|
export APP_FRANKENPHP_TAG=php8.4
|
||||||
|
|
||||||
#docker buildx build --platform=linux/amd64,linux/arm64 -f docker/Dockerfile.base.app -t code.caldwell.digital/home/torsearch-base:${APP_FRANKENPHP_TAG} -t code.caldwell.digital/home/torsearch-base:latest --build-arg "FRANKENPHP_TAG=${APP_FRANKENPHP_TAG}" .
|
docker buildx build --platform=linux/amd64 -f docker/Dockerfile.base.app -t code.caldwell.digital/home/torsearch-base:${APP_FRANKENPHP_TAG} -t code.caldwell.digital/home/torsearch-base:latest --build-arg "FRANKENPHP_TAG=${APP_FRANKENPHP_TAG}" .
|
||||||
docker build -f docker/Dockerfile.base.app -t code.caldwell.digital/home/torsearch-base:${APP_FRANKENPHP_TAG} -t code.caldwell.digital/home/torsearch-base:latest --build-arg "FRANKENPHP_TAG=${APP_FRANKENPHP_TAG}" .
|
|
||||||
docker push code.caldwell.digital/home/torsearch-base:${APP_FRANKENPHP_TAG}
|
docker push code.caldwell.digital/home/torsearch-base:${APP_FRANKENPHP_TAG}
|
||||||
docker push code.caldwell.digital/home/torsearch-base:latest
|
docker push code.caldwell.digital/home/torsearch-base:latest
|
||||||
|
|
||||||
# torsearch-worker & torsearch-scheduler are built from this base
|
# torsearch-worker & torsearch-scheduler are built from this base
|
||||||
export WORKER_FRANKENPHP_TAG=php8.4-alpine
|
export WORKER_FRANKENPHP_TAG=php8.4-alpine
|
||||||
|
|
||||||
#docker buildx build --platform=linux/amd64,linux/arm64 -f docker/Dockerfile.base.worker -t code.caldwell.digital/home/torsearch-base-worker:${WORKER_FRANKENPHP_TAG} -t code.caldwell.digital/home/torsearch-base-worker:latest --build-arg "FRANKENPHP_TAG=${WORKER_FRANKENPHP_TAG}" .
|
docker buildx build --platform=linux/amd64 -f docker/Dockerfile.base.worker -t code.caldwell.digital/home/torsearch-base-worker:${WORKER_FRANKENPHP_TAG} -t code.caldwell.digital/home/torsearch-base-worker:latest --build-arg "FRANKENPHP_TAG=${WORKER_FRANKENPHP_TAG}" .
|
||||||
docker build -f docker/Dockerfile.base.worker -t code.caldwell.digital/home/torsearch-base-worker:${WORKER_FRANKENPHP_TAG} -t code.caldwell.digital/home/torsearch-base-worker:latest --build-arg "FRANKENPHP_TAG=${WORKER_FRANKENPHP_TAG}" .
|
|
||||||
docker push code.caldwell.digital/home/torsearch-base-worker:${WORKER_FRANKENPHP_TAG}
|
docker push code.caldwell.digital/home/torsearch-base-worker:${WORKER_FRANKENPHP_TAG}
|
||||||
docker push code.caldwell.digital/home/torsearch-base-worker:latest
|
docker push code.caldwell.digital/home/torsearch-base-worker:latest
|
||||||
|
|
||||||
# torsearch-worker-supervisord
|
|
||||||
export ALPINE_VERSION=3.22
|
|
||||||
|
|
||||||
#docker buildx build --platform=linux/amd64,linux/arm64 -f docker/Dockerfile.base.worker -t code.caldwell.digital/home/torsearch-base-worker-supervisord:latest --build-arg "ALPINE_VERSION=${ALPINE_VERSION}" .
|
|
||||||
docker build -f docker/Dockerfile.base.worker -t code.caldwell.digital/home/torsearch-base-worker-supervisord:latest --build-arg "ALPINE_VERSION=${ALPINE_VERSION}" .
|
|
||||||
docker push code.caldwell.digital/home/torsearch-base-worker-supervisord:latest
|
|
||||||
|
|||||||
17
compose.yml
17
compose.yml
@@ -34,8 +34,10 @@ services:
|
|||||||
|
|
||||||
worker:
|
worker:
|
||||||
build:
|
build:
|
||||||
dockerfile: docker/Dockerfile.worker
|
dockerfile: docker/Dockerfile.base.worker
|
||||||
context: .
|
context: .
|
||||||
|
args:
|
||||||
|
FRANKENPHP_TAG: php8.4-alpine
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- $PWD:/app
|
- $PWD:/app
|
||||||
@@ -43,19 +45,22 @@ services:
|
|||||||
tty: true
|
tty: true
|
||||||
environment:
|
environment:
|
||||||
TZ: America/Chicago
|
TZ: America/Chicago
|
||||||
|
command: php /app/bin/console messenger:consume async --time-limit=3600 -vv
|
||||||
|
|
||||||
|
|
||||||
scheduler:
|
scheduler:
|
||||||
build:
|
build:
|
||||||
dockerfile: docker/Dockerfile.scheduler
|
dockerfile: docker/Dockerfile.base.worker
|
||||||
context: .
|
context: .
|
||||||
|
args:
|
||||||
|
FRANKENPHP_TAG: php8.4-alpine
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- $PWD:/app
|
- $PWD:/app
|
||||||
- $PWD/var/download:/var/download
|
|
||||||
tty: true
|
|
||||||
environment:
|
environment:
|
||||||
TZ: America/Chicago
|
TZ: America/Chicago
|
||||||
WORKER_MONITOR: 2
|
command: php /app/bin/console messenger:consume scheduler_monitor -vv
|
||||||
|
tty: true
|
||||||
|
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
@@ -91,8 +96,6 @@ services:
|
|||||||
image: adminer
|
image: adminer
|
||||||
ports:
|
ports:
|
||||||
- "8081:8080"
|
- "8081:8080"
|
||||||
environment:
|
|
||||||
ADMINER_DEFAULT_SERVER: database
|
|
||||||
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
|
|||||||
6
composer.lock
generated
6
composer.lock
generated
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "c133ccd27ac6a41256bdc69129c16546",
|
"content-hash": "e055bbbbe5836c92bb147b6dbb1d1d46",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "1tomany/rich-bundle",
|
"name": "1tomany/rich-bundle",
|
||||||
@@ -13398,7 +13398,7 @@
|
|||||||
],
|
],
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"minimum-stability": "stable",
|
"minimum-stability": "stable",
|
||||||
"stability-flags": [],
|
"stability-flags": {},
|
||||||
"prefer-stable": true,
|
"prefer-stable": true,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": {
|
"platform": {
|
||||||
@@ -13406,7 +13406,7 @@
|
|||||||
"ext-ctype": "*",
|
"ext-ctype": "*",
|
||||||
"ext-iconv": "*"
|
"ext-iconv": "*"
|
||||||
},
|
},
|
||||||
"platform-dev": [],
|
"platform-dev": {},
|
||||||
"platform-overrides": {
|
"platform-overrides": {
|
||||||
"php": "8.4"
|
"php": "8.4"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -41,13 +41,7 @@ doctrine:
|
|||||||
is_bundle: false
|
is_bundle: false
|
||||||
dir: '%kernel.project_dir%/src/Monitor/Framework/Entity'
|
dir: '%kernel.project_dir%/src/Monitor/Framework/Entity'
|
||||||
prefix: 'App\Monitor\Framework\Entity'
|
prefix: 'App\Monitor\Framework\Entity'
|
||||||
alias: Monitor
|
alias: Download
|
||||||
EventLog:
|
|
||||||
type: attribute
|
|
||||||
is_bundle: false
|
|
||||||
dir: '%kernel.project_dir%/src/EventLog/Framework/Entity'
|
|
||||||
prefix: 'App\EventLog\Framework\Entity'
|
|
||||||
alias: EventLog
|
|
||||||
controller_resolver:
|
controller_resolver:
|
||||||
auto_mapping: false
|
auto_mapping: false
|
||||||
|
|
||||||
|
|||||||
@@ -15,26 +15,6 @@ framework:
|
|||||||
max_retries: 1
|
max_retries: 1
|
||||||
multiplier: 1
|
multiplier: 1
|
||||||
|
|
||||||
download:
|
|
||||||
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
|
|
||||||
options:
|
|
||||||
use_notify: true
|
|
||||||
check_delayed_interval: 60000
|
|
||||||
queue_name: download
|
|
||||||
retry_strategy:
|
|
||||||
max_retries: 3
|
|
||||||
multiplier: 1
|
|
||||||
|
|
||||||
monitor:
|
|
||||||
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
|
|
||||||
options:
|
|
||||||
use_notify: true
|
|
||||||
check_delayed_interval: 60000
|
|
||||||
queue_name: monitor
|
|
||||||
retry_strategy:
|
|
||||||
max_retries: 1
|
|
||||||
multiplier: 1
|
|
||||||
|
|
||||||
media_cache:
|
media_cache:
|
||||||
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
|
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
|
||||||
options:
|
options:
|
||||||
@@ -56,12 +36,12 @@ framework:
|
|||||||
routing:
|
routing:
|
||||||
# Route your messages to the transports
|
# Route your messages to the transports
|
||||||
# 'App\Message\YourMessage': async
|
# 'App\Message\YourMessage': async
|
||||||
'App\Download\Action\Command\DownloadMediaCommand': download
|
'App\Download\Action\Command\DownloadMediaCommand': async
|
||||||
'App\Download\Action\Command\DownloadSeasonCommand': async
|
'App\Download\Action\Command\DownloadSeasonCommand': async
|
||||||
'App\Monitor\Action\Command\MonitorTvEpisodeCommand': monitor
|
'App\Monitor\Action\Command\MonitorTvEpisodeCommand': async
|
||||||
'App\Monitor\Action\Command\MonitorTvSeasonCommand': monitor
|
'App\Monitor\Action\Command\MonitorTvSeasonCommand': async
|
||||||
'App\Monitor\Action\Command\MonitorTvShowCommand': monitor
|
'App\Monitor\Action\Command\MonitorTvShowCommand': async
|
||||||
'App\Monitor\Action\Command\MonitorMovieCommand': monitor
|
'App\Monitor\Action\Command\MonitorMovieCommand': async
|
||||||
'App\Torrentio\Action\Command\GetTvShowOptionsCommand': media_cache
|
'App\Torrentio\Action\Command\GetTvShowOptionsCommand': media_cache
|
||||||
|
|
||||||
# when@test:
|
# when@test:
|
||||||
|
|||||||
@@ -6,14 +6,6 @@ controllersBase:
|
|||||||
defaults:
|
defaults:
|
||||||
schemes: [ 'https' ]
|
schemes: [ 'https' ]
|
||||||
|
|
||||||
controllersEventLog:
|
|
||||||
resource:
|
|
||||||
path: ../src/EventLog/Framework/Controller/
|
|
||||||
namespace: App\EventLog\Framework\Controller
|
|
||||||
type: attribute
|
|
||||||
defaults:
|
|
||||||
schemes: [ 'https' ]
|
|
||||||
|
|
||||||
controllersLibrary:
|
controllersLibrary:
|
||||||
resource:
|
resource:
|
||||||
path: ../src/Library/Framework/Controller/
|
path: ../src/Library/Framework/Controller/
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ services:
|
|||||||
- /mnt/media/downloads/tvshows:/var/download/tvshows
|
- /mnt/media/downloads/tvshows:/var/download/tvshows
|
||||||
- mercure_data:/data
|
- mercure_data:/data
|
||||||
- mercure_config:/config
|
- mercure_config:/config
|
||||||
|
depends_on:
|
||||||
|
- database
|
||||||
|
|
||||||
|
|
||||||
worker:
|
worker:
|
||||||
@@ -20,10 +22,16 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- /mnt/media/downloads/movies:/var/download/movies
|
- /mnt/media/downloads/movies:/var/download/movies
|
||||||
- /mnt/media/downloads/tvshows:/var/download/tvshows
|
- /mnt/media/downloads/tvshows:/var/download/tvshows
|
||||||
|
restart: always
|
||||||
|
command: -vv --time-limit=3600 --limit=10
|
||||||
deploy:
|
deploy:
|
||||||
replicas: 2
|
replicas: 2
|
||||||
depends_on:
|
depends_on:
|
||||||
- app
|
- app
|
||||||
|
logging:
|
||||||
|
driver: "gelf"
|
||||||
|
options:
|
||||||
|
gelf-address: "tcp://192.168.1.197:12203"
|
||||||
|
|
||||||
|
|
||||||
scheduler:
|
scheduler:
|
||||||
@@ -31,10 +39,28 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- /mnt/media/downloads/movies:/var/download/movies
|
- /mnt/media/downloads/movies:/var/download/movies
|
||||||
- /mnt/media/downloads/tvshows:/var/download/tvshows
|
- /mnt/media/downloads/tvshows:/var/download/tvshows
|
||||||
|
restart: always
|
||||||
|
command: -vv
|
||||||
depends_on:
|
depends_on:
|
||||||
- app
|
- app
|
||||||
|
logging:
|
||||||
|
driver: "gelf"
|
||||||
|
options:
|
||||||
|
gelf-address: "tcp://192.168.1.197:12204"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis:latest
|
||||||
|
volumes:
|
||||||
|
- redis_data:/data
|
||||||
|
command: redis-server --maxmemory 512MB
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
|
mysql:
|
||||||
mercure_config:
|
mercure_config:
|
||||||
mercure_data:
|
mercure_data:
|
||||||
|
redis_data:
|
||||||
|
|
||||||
|
|||||||
@@ -1,35 +1,19 @@
|
|||||||
#####
|
ARG FRANKENPHP_TAG
|
||||||
# This version of Torsearch runs the scheduler, downloader, and worker
|
|
||||||
# in a single container. Each process is managerd by supervisord
|
|
||||||
# and can be configured via environment variables and more
|
|
||||||
# than one of these containers cans till be run.
|
|
||||||
#####
|
|
||||||
ARG ALPINE_VERSION="3.22"
|
|
||||||
FROM alpine:${ALPINE_VERSION} AS build_stage
|
|
||||||
|
|
||||||
RUN apk add --no-cache \
|
FROM dunglas/frankenphp:${FRANKENPHP_TAG}
|
||||||
curl \
|
|
||||||
php84 \
|
|
||||||
php84-curl \
|
|
||||||
php84-fileinfo \
|
|
||||||
php84-gd \
|
|
||||||
php84-mbstring \
|
|
||||||
php84-mysqli \
|
|
||||||
php84-opcache \
|
|
||||||
php84-openssl \
|
|
||||||
php84-pdo_mysql \
|
|
||||||
supervisor
|
|
||||||
|
|
||||||
RUN ln -s /usr/bin/php84 /usr/bin/php
|
ENV SERVER_NAME=":80"
|
||||||
|
ENV CADDY_GLOBAL_OPTIONS="auto_https off"
|
||||||
|
ENV APP_RUNTIME="Runtime\\FrankenPhpSymfony\\Runtime"
|
||||||
|
|
||||||
RUN mkdir -p /etc/supervisor/conf.d
|
ARG APP_VERSION="0.dev"
|
||||||
|
ENV APP_VERSION="${APP_VERSION}"
|
||||||
|
|
||||||
# We start supervisord and supervisord starts
|
RUN install-php-extensions \
|
||||||
# respective service in the configuration file.
|
pdo_mysql \
|
||||||
ENTRYPOINT ["/app/bin/console", "init:worker"]
|
gd \
|
||||||
|
intl \
|
||||||
# Message transports can be enabled by passing them as command options.
|
zip \
|
||||||
# Inlcluding a number with the option will start that amount of processes
|
opcache
|
||||||
# for the transport. Not supplying a number will default to 1.
|
|
||||||
# --download --monitor OR --download 2 --monitor
|
|
||||||
|
|
||||||
|
RUN apk add --no-cache wget
|
||||||
|
|||||||
@@ -1,21 +1,10 @@
|
|||||||
###
|
FROM code.caldwell.digital/home/torsearch-base-worker:php8.4-alpine
|
||||||
# This version of Torsearch can run the scheduler, downloader, and
|
|
||||||
# worker in one container. Each process is managerd by supervisord
|
|
||||||
# and can be configured via environment variables, and more than
|
|
||||||
# one of these containers can still be run.
|
|
||||||
###
|
|
||||||
|
|
||||||
# Default to latest, but should pass in a version
|
ARG APP_VERSION="0.0.0-dev"
|
||||||
ARG APP_VERSION="latest"
|
ENV APP_VERSION="${APP_VERSION}"
|
||||||
|
|
||||||
# Start with our base worker image
|
COPY . /app
|
||||||
FROM code.caldwell.digital/home/torsearch-base-worker-supervisord:latest
|
|
||||||
|
|
||||||
# Set the APP_VERSION in the image
|
ENTRYPOINT [ "php", "/app/bin/console", "messenger:consume", "scheduler_monitor" ]
|
||||||
ENV APP_VERSION=${APP_VERSION}
|
|
||||||
|
|
||||||
# Copy the actual application code from the previously built app
|
HEALTHCHECK --interval=3s --timeout=3s --retries=10 CMD return 0
|
||||||
COPY --chown=1000:1000 ./ /app
|
|
||||||
|
|
||||||
# To retain backwards compatibility, default to async & download transports
|
|
||||||
CMD [ "--monitor" ]
|
|
||||||
|
|||||||
@@ -1,21 +1,10 @@
|
|||||||
###
|
FROM code.caldwell.digital/home/torsearch-base-worker:php8.4-alpine
|
||||||
# This version of Torsearch can run the scheduler, downloader, and
|
|
||||||
# worker in one container. Each process is managerd by supervisord
|
|
||||||
# and can be configured via environment variables, and more than
|
|
||||||
# one of these containers can still be run.
|
|
||||||
###
|
|
||||||
|
|
||||||
# Default to latest, but should pass in a version
|
ARG APP_VERSION="0.0.0-dev"
|
||||||
ARG APP_VERSION="latest"
|
ENV APP_VERSION="${APP_VERSION}"
|
||||||
|
|
||||||
# Start with our base worker image
|
COPY . /app
|
||||||
FROM code.caldwell.digital/home/torsearch-base-worker-supervisord:latest
|
|
||||||
|
|
||||||
# Set the APP_VERSION in the image
|
ENTRYPOINT [ "php", "/app/bin/console", "messenger:consume", "async" ]
|
||||||
ENV APP_VERSION=${APP_VERSION}
|
|
||||||
|
|
||||||
# Copy the actual application code from the previously built app
|
HEALTHCHECK --interval=3s --timeout=3s --retries=10 CMD return 0
|
||||||
COPY --chown=1000:1000 ./ /app
|
|
||||||
|
|
||||||
# To retain backwards compatibility, default to async & download transports
|
|
||||||
CMD [ "--async", "--download" ]
|
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
[program:torsearch-worker]
|
|
||||||
command=/app/bin/console messenger:consume async -vv --time-limit 3600
|
|
||||||
numprocs=1
|
|
||||||
stdout_logfile=/dev/stdout
|
|
||||||
stdout_logfile_maxbytes=0
|
|
||||||
stderr_logfile=/dev/stderr
|
|
||||||
stderr_logfile_maxbytes=0
|
|
||||||
autorestart=true
|
|
||||||
startretries=3
|
|
||||||
process_name=%(program_name)s_%(process_num)02d
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
[program:torsearch-downloader]
|
|
||||||
command=/app/bin/console messenger:consume download -vv --time-limit 3600
|
|
||||||
numprocs=1
|
|
||||||
stdout_logfile=/dev/stdout
|
|
||||||
stdout_logfile_maxbytes=0
|
|
||||||
stderr_logfile=/dev/stderr
|
|
||||||
stderr_logfile_maxbytes=0
|
|
||||||
autorestart=true
|
|
||||||
startretries=3
|
|
||||||
process_name=%(program_name)s_%(process_num)02d
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
[program:torsearch-scheduler]
|
|
||||||
command=/app/bin/console messenger:consume scheduler_monitor monitor -vv --time-limit 21600
|
|
||||||
numprocs=1
|
|
||||||
stdout_logfile=/dev/stdout
|
|
||||||
stdout_logfile_maxbytes=0
|
|
||||||
stderr_logfile=/dev/stderr
|
|
||||||
stderr_logfile_maxbytes=0
|
|
||||||
autorestart=true
|
|
||||||
startretries=3
|
|
||||||
process_name=%(program_name)s_%(process_num)02d
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
[supervisord]
|
|
||||||
nodaemon=true
|
|
||||||
logfile=/dev/null
|
|
||||||
logfile_maxbytes=0
|
|
||||||
pidfile=/run/supervisord.pid
|
|
||||||
@@ -21,7 +21,10 @@ final class Version20250831013403 extends AbstractMigration
|
|||||||
{
|
{
|
||||||
// this up() migration is auto-generated, please modify it to your needs
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
$this->addSql(<<<'SQL'
|
$this->addSql(<<<'SQL'
|
||||||
DROP TABLE IF EXISTS sessions
|
DROP TABLE sessions
|
||||||
|
SQL);
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
ALTER TABLE download CHANGE created_at created_at DATETIME NOT NULL, CHANGE updated_at updated_at DATETIME NOT NULL
|
||||||
SQL);
|
SQL);
|
||||||
$this->addSql(<<<'SQL'
|
$this->addSql(<<<'SQL'
|
||||||
ALTER TABLE user_preference CHANGE preference_value preference_value VARCHAR(1024) DEFAULT NULL
|
ALTER TABLE user_preference CHANGE preference_value preference_value VARCHAR(1024) DEFAULT NULL
|
||||||
@@ -34,6 +37,9 @@ final class Version20250831013403 extends AbstractMigration
|
|||||||
$this->addSql(<<<'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 COLLATE `utf8mb4_bin` ENGINE = InnoDB COMMENT = ''
|
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 COLLATE `utf8mb4_bin` ENGINE = InnoDB COMMENT = ''
|
||||||
SQL);
|
SQL);
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
ALTER TABLE download CHANGE created_at created_at DATETIME DEFAULT NULL, CHANGE updated_at updated_at DATETIME DEFAULT NULL
|
||||||
|
SQL);
|
||||||
$this->addSql(<<<'SQL'
|
$this->addSql(<<<'SQL'
|
||||||
ALTER TABLE user_preference CHANGE preference_value preference_value VARCHAR(255) DEFAULT NULL
|
ALTER TABLE user_preference CHANGE preference_value preference_value VARCHAR(255) DEFAULT NULL
|
||||||
SQL);
|
SQL);
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
<?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 Version20251101194723 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'
|
|
||||||
ALTER TABLE user_preference CHANGE preference_value preference_value VARCHAR(255) DEFAULT NULL
|
|
||||||
SQL);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(Schema $schema): void
|
|
||||||
{
|
|
||||||
// this down() migration is auto-generated, please modify it to your needs
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
ALTER TABLE user_preference CHANGE preference_value preference_value VARCHAR(1024) DEFAULT NULL
|
|
||||||
SQL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
<?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 Version20251101211617 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 event_log (id INT AUTO_INCREMENT NOT NULL, type VARCHAR(255) DEFAULT NULL, message LONGTEXT DEFAULT NULL, context JSON DEFAULT NULL COMMENT '(DC2Type:json)', PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB
|
|
||||||
SQL);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(Schema $schema): void
|
|
||||||
{
|
|
||||||
// this down() migration is auto-generated, please modify it to your needs
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
DROP TABLE event_log
|
|
||||||
SQL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
<?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 Version20251102004627 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'
|
|
||||||
ALTER TABLE event_log ADD user_id INT DEFAULT NULL
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
ALTER TABLE event_log ADD CONSTRAINT FK_9EF0AD16A76ED395 FOREIGN KEY (user_id) REFERENCES user (id)
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
CREATE INDEX IDX_9EF0AD16A76ED395 ON event_log (user_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 event_log DROP FOREIGN KEY FK_9EF0AD16A76ED395
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
DROP INDEX IDX_9EF0AD16A76ED395 ON event_log
|
|
||||||
SQL);
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
ALTER TABLE event_log DROP user_id
|
|
||||||
SQL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
<?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 Version20251102221034 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'
|
|
||||||
ALTER TABLE event_log ADD created_at DATETIME NULL, ADD updated_at DATETIME NULL
|
|
||||||
SQL);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(Schema $schema): void
|
|
||||||
{
|
|
||||||
// this down() migration is auto-generated, please modify it to your needs
|
|
||||||
$this->addSql(<<<'SQL'
|
|
||||||
ALTER TABLE event_log DROP created_at, DROP updated_at
|
|
||||||
SQL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
17
psalm.xml
17
psalm.xml
@@ -1,17 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
<psalm
|
|
||||||
errorLevel="7"
|
|
||||||
resolveFromConfigFile="true"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xmlns="https://getpsalm.org/schema/config"
|
|
||||||
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
|
||||||
findUnusedBaselineEntry="true"
|
|
||||||
findUnusedCode="true"
|
|
||||||
>
|
|
||||||
<projectFiles>
|
|
||||||
<directory name="src" />
|
|
||||||
<ignoreFiles>
|
|
||||||
<directory name="vendor" />
|
|
||||||
</ignoreFiles>
|
|
||||||
</projectFiles>
|
|
||||||
</psalm>
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Base\Framework\Command;
|
|
||||||
|
|
||||||
use Symfony\Component\Console\Command\Command;
|
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
|
||||||
use Twig\Environment;
|
|
||||||
|
|
||||||
class InitWorker extends Command
|
|
||||||
{
|
|
||||||
public function __construct(
|
|
||||||
private Environment $twig,
|
|
||||||
) {
|
|
||||||
parent::__construct();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function configure(): void
|
|
||||||
{
|
|
||||||
$this
|
|
||||||
->setName('init:worker')
|
|
||||||
->addOption('async', null, InputOption::VALUE_OPTIONAL, 'Run the async worker.',false)
|
|
||||||
->addOption('download', null, InputOption::VALUE_OPTIONAL, 'Run the download worker.', false)
|
|
||||||
->addOption('monitor', null, InputOption::VALUE_OPTIONAL, 'Run the monitor worker.', false)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
|
||||||
{
|
|
||||||
$configFile = $this->twig->render("config/supervisord.conf.twig", []);
|
|
||||||
|
|
||||||
if ($this->optionExists($input, $output, 'async')) {
|
|
||||||
$configFile .= $this->twig->render("config/async.conf.twig", [
|
|
||||||
'replicas' => $this->getOptionValue('async', $input),
|
|
||||||
]) . "\n\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->optionExists($input, $output, 'download')) {
|
|
||||||
$configFile .= $this->twig->render("config/download.conf.twig", [
|
|
||||||
'replicas' => $this->getOptionValue('download', $input),
|
|
||||||
]). "\n\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->optionExists($input, $output, 'monitor')) {
|
|
||||||
$configFile .= $this->twig->render("config/monitor.conf.twig", [
|
|
||||||
'replicas' => $this->getOptionValue('monitor', $input),
|
|
||||||
]). "\n\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("" !== $configFile) {
|
|
||||||
$output->writeln("[init:worker] Writing /etc/supervisor/conf.d/supervisord.conf");
|
|
||||||
file_put_contents("/etc/supervisor/conf.d/supervisord.conf", $configFile);
|
|
||||||
|
|
||||||
$output->writeln("[init:worker] Starting supervisord");
|
|
||||||
shell_exec("/usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf");
|
|
||||||
return Command::SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
$output->writeln("[init:worker] No workers selected. Exiting.");
|
|
||||||
return Command::FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function optionExists(InputInterface $input, OutputInterface $output, string $option): bool
|
|
||||||
{
|
|
||||||
if ($input->getOption($option) !== false) {
|
|
||||||
$value = $input->getOption($option) ?? 1;
|
|
||||||
$output->writeln("[init:worker] transport: $option // $value // input var");;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$optionKey = 'WORKER_' . strtoupper($option);
|
|
||||||
if (array_key_exists($optionKey, $_SERVER) && $_SERVER[$optionKey] !== null && $_SERVER[$optionKey] !== '') {
|
|
||||||
$output->writeln("[init:worker] transport: $option // $_SERVER[$optionKey] // env var");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getOptionValue(string $option, InputInterface $input): int
|
|
||||||
{
|
|
||||||
if ($input->getOption($option) !== false) {
|
|
||||||
return $input->getOption($option) ?? 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
$optionKey = 'WORKER_' . strtoupper($option);
|
|
||||||
return $_SERVER[$optionKey];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,22 +4,17 @@ namespace App\Download\Action\Handler;
|
|||||||
|
|
||||||
use App\Download\Action\Command\DeleteDownloadCommand;
|
use App\Download\Action\Command\DeleteDownloadCommand;
|
||||||
use App\Download\Action\Result\DeleteDownloadResult;
|
use App\Download\Action\Result\DeleteDownloadResult;
|
||||||
use App\Download\DownloadEvents;
|
|
||||||
use App\Download\Framework\Repository\DownloadRepository;
|
use App\Download\Framework\Repository\DownloadRepository;
|
||||||
use App\EventLog\Action\Command\AddEventLogCommand;
|
|
||||||
use App\Library\Action\Command\DeleteMediaFileCommand;
|
use App\Library\Action\Command\DeleteMediaFileCommand;
|
||||||
use App\Library\Action\Handler\DeleteMediaFileHandler;
|
use App\Library\Action\Handler\DeleteMediaFileHandler;
|
||||||
use App\Monitor\MonitorEvents;
|
|
||||||
use OneToMany\RichBundle\Contract\CommandInterface;
|
use OneToMany\RichBundle\Contract\CommandInterface;
|
||||||
use OneToMany\RichBundle\Contract\HandlerInterface;
|
use OneToMany\RichBundle\Contract\HandlerInterface;
|
||||||
use OneToMany\RichBundle\Contract\ResultInterface;
|
use OneToMany\RichBundle\Contract\ResultInterface;
|
||||||
use Symfony\Component\Messenger\MessageBusInterface;
|
|
||||||
|
|
||||||
/** @implements HandlerInterface<DeleteDownloadCommand, DeleteDownloadResult> */
|
/** @implements HandlerInterface<DeleteDownloadCommand, DeleteDownloadResult> */
|
||||||
readonly class DeleteDownloadHandler implements HandlerInterface
|
readonly class DeleteDownloadHandler implements HandlerInterface
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private MessageBusInterface $bus,
|
|
||||||
private DownloadRepository $downloadRepository,
|
private DownloadRepository $downloadRepository,
|
||||||
private DeleteMediaFileHandler $deleteMediaFileHandler,
|
private DeleteMediaFileHandler $deleteMediaFileHandler,
|
||||||
) {}
|
) {}
|
||||||
@@ -36,13 +31,6 @@ readonly class DeleteDownloadHandler implements HandlerInterface
|
|||||||
}
|
}
|
||||||
$this->downloadRepository->delete($command->downloadId);
|
$this->downloadRepository->delete($command->downloadId);
|
||||||
|
|
||||||
$this->bus->dispatch(new AddEventLogCommand(
|
|
||||||
$download->getUser(),
|
|
||||||
DownloadEvents::DOWNLOAD_DELETED->type(),
|
|
||||||
DownloadEvents::DOWNLOAD_DELETED->message(),
|
|
||||||
(array) $download
|
|
||||||
));
|
|
||||||
|
|
||||||
return new DeleteDownloadResult(
|
return new DeleteDownloadResult(
|
||||||
status: 200,
|
status: 200,
|
||||||
message: 'Success',
|
message: 'Success',
|
||||||
|
|||||||
@@ -4,22 +4,18 @@ namespace App\Download\Action\Handler;
|
|||||||
|
|
||||||
use App\Download\Action\Command\DownloadMediaCommand;
|
use App\Download\Action\Command\DownloadMediaCommand;
|
||||||
use App\Download\Action\Result\DownloadMediaResult;
|
use App\Download\Action\Result\DownloadMediaResult;
|
||||||
use App\Download\DownloadEvents;
|
|
||||||
use App\Download\Framework\Repository\DownloadRepository;
|
use App\Download\Framework\Repository\DownloadRepository;
|
||||||
use App\Download\Downloader\DownloaderInterface;
|
use App\Download\Downloader\DownloaderInterface;
|
||||||
use App\EventLog\Action\Command\AddEventLogCommand;
|
|
||||||
use App\User\Framework\Repository\UserRepository;
|
use App\User\Framework\Repository\UserRepository;
|
||||||
use OneToMany\RichBundle\Contract\CommandInterface;
|
use OneToMany\RichBundle\Contract\CommandInterface;
|
||||||
use OneToMany\RichBundle\Contract\HandlerInterface;
|
use OneToMany\RichBundle\Contract\HandlerInterface;
|
||||||
use OneToMany\RichBundle\Contract\ResultInterface;
|
use OneToMany\RichBundle\Contract\ResultInterface;
|
||||||
use Symfony\Component\Messenger\Exception\UnrecoverableMessageHandlingException;
|
use Symfony\Component\Messenger\Exception\UnrecoverableMessageHandlingException;
|
||||||
use Symfony\Component\Messenger\MessageBusInterface;
|
|
||||||
|
|
||||||
/** @implements HandlerInterface<DownloadMediaCommand, DownloadMediaResult> */
|
/** @implements HandlerInterface<DownloadMediaCommand, DownloadMediaResult> */
|
||||||
readonly class DownloadMediaHandler implements HandlerInterface
|
readonly class DownloadMediaHandler implements HandlerInterface
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private MessageBusInterface $bus,
|
|
||||||
private DownloaderInterface $downloader,
|
private DownloaderInterface $downloader,
|
||||||
private DownloadRepository $downloadRepository,
|
private DownloadRepository $downloadRepository,
|
||||||
private UserRepository $userRepository,
|
private UserRepository $userRepository,
|
||||||
@@ -27,17 +23,9 @@ readonly class DownloadMediaHandler implements HandlerInterface
|
|||||||
|
|
||||||
public function handle(CommandInterface $command): ResultInterface
|
public function handle(CommandInterface $command): ResultInterface
|
||||||
{
|
{
|
||||||
$user = $this->userRepository->find($command->userId);
|
|
||||||
$this->bus->dispatch(new AddEventLogCommand(
|
|
||||||
$user,
|
|
||||||
DownloadEvents::DOWNLOAD_STARTED->type(),
|
|
||||||
DownloadEvents::DOWNLOAD_STARTED->message(),
|
|
||||||
(array) $command
|
|
||||||
));
|
|
||||||
|
|
||||||
if (null === $command->downloadId) {
|
if (null === $command->downloadId) {
|
||||||
$download = $this->downloadRepository->insert(
|
$download = $this->downloadRepository->insert(
|
||||||
$user,
|
$this->userRepository->find($command->userId),
|
||||||
$command->url,
|
$command->url,
|
||||||
$command->title,
|
$command->title,
|
||||||
$command->filename,
|
$command->filename,
|
||||||
@@ -69,12 +57,6 @@ readonly class DownloadMediaHandler implements HandlerInterface
|
|||||||
throw new UnrecoverableMessageHandlingException($exception->getMessage(), 500);
|
throw new UnrecoverableMessageHandlingException($exception->getMessage(), 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->bus->dispatch(new AddEventLogCommand(
|
|
||||||
$user,
|
|
||||||
DownloadEvents::DOWNLOAD_FINISHED->type(),
|
|
||||||
DownloadEvents::DOWNLOAD_FINISHED->message(),
|
|
||||||
(array) $command
|
|
||||||
));
|
|
||||||
return new DownloadMediaResult(200, "Success.");
|
return new DownloadMediaResult(200, "Success.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Download;
|
|
||||||
|
|
||||||
enum DownloadEvents
|
|
||||||
{
|
|
||||||
case DOWNLOAD_ADDED;
|
|
||||||
case DOWNLOAD_STARTED;
|
|
||||||
case DOWNLOAD_FINISHED;
|
|
||||||
case DOWNLOAD_DELETED;
|
|
||||||
case DOWNLOAD_ERROR;
|
|
||||||
|
|
||||||
public function type(): string
|
|
||||||
{
|
|
||||||
return match ($this) {
|
|
||||||
self::DOWNLOAD_ADDED => 'download_added',
|
|
||||||
self::DOWNLOAD_STARTED => 'download_started',
|
|
||||||
self::DOWNLOAD_FINISHED => 'download_finished',
|
|
||||||
self::DOWNLOAD_DELETED => 'download_deleted',
|
|
||||||
self::DOWNLOAD_ERROR => 'download_error',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public function message(): string
|
|
||||||
{
|
|
||||||
return match ($this) {
|
|
||||||
self::DOWNLOAD_ADDED => 'A new download has been added.',
|
|
||||||
self::DOWNLOAD_STARTED => 'A download has started.',
|
|
||||||
self::DOWNLOAD_FINISHED => 'A download has finished.',
|
|
||||||
self::DOWNLOAD_DELETED => 'A download has been deleted.',
|
|
||||||
self::DOWNLOAD_ERROR => 'A download has encountered an error.',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,12 +4,9 @@ namespace App\Download\Downloader;
|
|||||||
|
|
||||||
use App\Base\Service\Broadcaster;
|
use App\Base\Service\Broadcaster;
|
||||||
use App\Base\Service\MediaFiles;
|
use App\Base\Service\MediaFiles;
|
||||||
use App\Download\DownloadEvents;
|
|
||||||
use App\Download\Framework\Entity\Download;
|
use App\Download\Framework\Entity\Download;
|
||||||
use App\EventLog\Action\Command\AddEventLogCommand;
|
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Component\Cache\Adapter\RedisAdapter;
|
use Symfony\Component\Cache\Adapter\RedisAdapter;
|
||||||
use Symfony\Component\Messenger\MessageBusInterface;
|
|
||||||
use Symfony\Component\Process\Exception\ProcessFailedException;
|
use Symfony\Component\Process\Exception\ProcessFailedException;
|
||||||
use Symfony\Component\Process\Process;
|
use Symfony\Component\Process\Process;
|
||||||
use Symfony\Contracts\Cache\CacheInterface;
|
use Symfony\Contracts\Cache\CacheInterface;
|
||||||
@@ -20,7 +17,6 @@ class ProcessDownloader implements DownloaderInterface
|
|||||||
* @var RedisAdapter $cache
|
* @var RedisAdapter $cache
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private MessageBusInterface $bus,
|
|
||||||
private EntityManagerInterface $entityManager,
|
private EntityManagerInterface $entityManager,
|
||||||
private MediaFiles $mediaFiles,
|
private MediaFiles $mediaFiles,
|
||||||
private CacheInterface $cache,
|
private CacheInterface $cache,
|
||||||
@@ -92,12 +88,6 @@ class ProcessDownloader implements DownloaderInterface
|
|||||||
}
|
}
|
||||||
} catch (ProcessFailedException $exception) {
|
} catch (ProcessFailedException $exception) {
|
||||||
$downloadEntity->setStatus('Failed');
|
$downloadEntity->setStatus('Failed');
|
||||||
$this->bus->dispatch(new AddEventLogCommand(
|
|
||||||
$downloadEntity->getUser()->getId(),
|
|
||||||
DownloadEvents::DOWNLOAD_ERROR->type(),
|
|
||||||
DownloadEvents::DOWNLOAD_ERROR->message() . ': ' . $exception->getMessage(),
|
|
||||||
(array) $downloadEntity
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->entityManager->flush();
|
$this->entityManager->flush();
|
||||||
|
|||||||
@@ -11,9 +11,7 @@ use App\Download\Action\Input\DownloadMediaInput;
|
|||||||
use App\Download\Action\Input\DownloadSeasonInput;
|
use App\Download\Action\Input\DownloadSeasonInput;
|
||||||
use App\Download\Action\Input\PauseDownloadInput;
|
use App\Download\Action\Input\PauseDownloadInput;
|
||||||
use App\Download\Action\Input\ResumeDownloadInput;
|
use App\Download\Action\Input\ResumeDownloadInput;
|
||||||
use App\Download\DownloadEvents;
|
|
||||||
use App\Download\Framework\Repository\DownloadRepository;
|
use App\Download\Framework\Repository\DownloadRepository;
|
||||||
use App\EventLog\Action\Command\AddEventLogCommand;
|
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\Messenger\MessageBusInterface;
|
use Symfony\Component\Messenger\MessageBusInterface;
|
||||||
@@ -43,13 +41,6 @@ class ApiController extends AbstractController
|
|||||||
$input->downloadId = $download->getId();
|
$input->downloadId = $download->getId();
|
||||||
$input->userId = $this->getUser()->getId();
|
$input->userId = $this->getUser()->getId();
|
||||||
|
|
||||||
$this->bus->dispatch(new AddEventLogCommand(
|
|
||||||
$this->getUser(),
|
|
||||||
DownloadEvents::DOWNLOAD_ADDED->type(),
|
|
||||||
DownloadEvents::DOWNLOAD_ADDED->message(),
|
|
||||||
(array) $download
|
|
||||||
));
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->bus->dispatch($input->toCommand());
|
$this->bus->dispatch($input->toCommand());
|
||||||
} catch (\Throwable $exception) {
|
} catch (\Throwable $exception) {
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\EventLog\Action\Command;
|
|
||||||
|
|
||||||
use OneToMany\RichBundle\Contract\CommandInterface;
|
|
||||||
use Symfony\Component\Security\Core\User\UserInterface;
|
|
||||||
|
|
||||||
/** @implements CommandInterface<AddEventLogCommand> */
|
|
||||||
class AddEventLogCommand implements CommandInterface
|
|
||||||
{
|
|
||||||
public function __construct(
|
|
||||||
public UserInterface $user,
|
|
||||||
public string $type,
|
|
||||||
public string $message,
|
|
||||||
public array $context,
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\EventLog\Action\Handler;
|
|
||||||
|
|
||||||
use App\EventLog\Framework\Repository\EventLogRepository;
|
|
||||||
use App\EventLog\Action\Command\AddEventLogCommand;
|
|
||||||
use App\EventLog\Action\Result\AddEventLogResult;
|
|
||||||
use OneToMany\RichBundle\Contract\CommandInterface;
|
|
||||||
use OneToMany\RichBundle\Contract\HandlerInterface;
|
|
||||||
use OneToMany\RichBundle\Contract\ResultInterface;
|
|
||||||
|
|
||||||
/*** @implements HandlerInterface<AddEventLogCommand> */
|
|
||||||
class AddEventLogHandler implements HandlerInterface
|
|
||||||
{
|
|
||||||
public function __construct(
|
|
||||||
private EventLogRepository $repository,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public function handle(CommandInterface $command): ResultInterface
|
|
||||||
{
|
|
||||||
$eventLog = $this->repository->insert(
|
|
||||||
user: $command->user,
|
|
||||||
type: $command->type,
|
|
||||||
message: $command->message,
|
|
||||||
context: $command->context
|
|
||||||
);
|
|
||||||
return new AddEventLogResult($eventLog);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\EventLog\Action\Input;
|
|
||||||
|
|
||||||
use App\EventLog\Action\Command\AddEventLogCommand;
|
|
||||||
use OneToMany\RichBundle\Attribute\SourceQuery;
|
|
||||||
use OneToMany\RichBundle\Attribute\SourceRequest;
|
|
||||||
use OneToMany\RichBundle\Contract\CommandInterface;
|
|
||||||
use OneToMany\RichBundle\Contract\InputInterface;
|
|
||||||
|
|
||||||
/** @implements InputInterface<AddEventLogCommand> */
|
|
||||||
class AddEventLogInput implements InputInterface
|
|
||||||
{
|
|
||||||
public function __construct(
|
|
||||||
#[SourceQuery('type')]
|
|
||||||
#[SourceRequest('type')]
|
|
||||||
public string $type,
|
|
||||||
|
|
||||||
#[SourceQuery('message')]
|
|
||||||
#[SourceRequest('message')]
|
|
||||||
public string $message,
|
|
||||||
|
|
||||||
#[SourceQuery('context')]
|
|
||||||
#[SourceRequest('context')]
|
|
||||||
public array $context = []
|
|
||||||
){}
|
|
||||||
|
|
||||||
public function toCommand(): CommandInterface
|
|
||||||
{
|
|
||||||
return new AddEventLogCommand(
|
|
||||||
$this->type,
|
|
||||||
$this->message,
|
|
||||||
$this->context
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\EventLog\Action\Result;
|
|
||||||
|
|
||||||
use App\EventLog\Framework\Entity\EventLog;
|
|
||||||
use OneToMany\RichBundle\Contract\ResultInterface;
|
|
||||||
|
|
||||||
/** @implements ResultInterface<AddEventLogResult> */
|
|
||||||
class AddEventLogResult implements ResultInterface
|
|
||||||
{
|
|
||||||
public function __construct(
|
|
||||||
public EventLog $eventLog,
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\EventLog\Framework\Controller;
|
|
||||||
|
|
||||||
use App\Base\Service\Broadcaster;
|
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
|
||||||
use Symfony\Component\Routing\Attribute\Route;
|
|
||||||
|
|
||||||
final class EventLogController extends AbstractController
|
|
||||||
{
|
|
||||||
public function __construct(
|
|
||||||
private readonly Broadcaster $broadcaster,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
#[Route('/alert', name: 'app_alert')]
|
|
||||||
public function index(): Response
|
|
||||||
{
|
|
||||||
$this->broadcaster->alert(
|
|
||||||
'Added to queue',
|
|
||||||
'This is a testy test!'
|
|
||||||
);
|
|
||||||
|
|
||||||
return $this->json([
|
|
||||||
'Success' => 'Published'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\EventLog\Framework\Entity;
|
|
||||||
|
|
||||||
use App\EventLog\Framework\Repository\EventLogRepository;
|
|
||||||
use App\User\Framework\Entity\User;
|
|
||||||
use Doctrine\DBAL\Types\Types;
|
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
|
||||||
use Gedmo\Timestampable\Traits\TimestampableEntity;
|
|
||||||
|
|
||||||
#[ORM\Entity(repositoryClass: EventLogRepository::class)]
|
|
||||||
class EventLog
|
|
||||||
{
|
|
||||||
use TimestampableEntity;
|
|
||||||
|
|
||||||
#[ORM\Id]
|
|
||||||
#[ORM\GeneratedValue]
|
|
||||||
#[ORM\Column(nullable: true)]
|
|
||||||
private ?int $id = null;
|
|
||||||
|
|
||||||
#[ORM\Column(length: 255, nullable: true)]
|
|
||||||
private ?string $type = null;
|
|
||||||
|
|
||||||
#[ORM\Column(type: Types::TEXT, nullable: true)]
|
|
||||||
private ?string $message = null;
|
|
||||||
|
|
||||||
#[ORM\Column(type: Types::JSON, nullable: true)]
|
|
||||||
private ?array $context = null;
|
|
||||||
|
|
||||||
#[ORM\ManyToOne(inversedBy: 'eventLogs')]
|
|
||||||
private ?User $user = null;
|
|
||||||
|
|
||||||
public function getId(): ?int
|
|
||||||
{
|
|
||||||
return $this->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getType(): ?string
|
|
||||||
{
|
|
||||||
return $this->type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setType(?string $type): self
|
|
||||||
{
|
|
||||||
$this->type = $type;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getMessage(): ?string
|
|
||||||
{
|
|
||||||
return $this->message;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setMessage(?string $message): self
|
|
||||||
{
|
|
||||||
$this->message = $message;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getContext(): ?array
|
|
||||||
{
|
|
||||||
return $this->context;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setContext(?array $context): self
|
|
||||||
{
|
|
||||||
$this->context = $context;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getUser(): ?User
|
|
||||||
{
|
|
||||||
return $this->user;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setUser(?User $user): static
|
|
||||||
{
|
|
||||||
$this->user = $user;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\EventLog\Framework\Repository;
|
|
||||||
|
|
||||||
use App\EventLog\Framework\Entity\EventLog;
|
|
||||||
use App\User\Framework\Entity\User;
|
|
||||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
|
||||||
use Doctrine\Persistence\ManagerRegistry;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @extends ServiceEntityRepository<EventLog>
|
|
||||||
*/
|
|
||||||
class EventLogRepository extends ServiceEntityRepository
|
|
||||||
{
|
|
||||||
public function __construct(ManagerRegistry $registry)
|
|
||||||
{
|
|
||||||
parent::__construct($registry, EventLog::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function insert(
|
|
||||||
User $user,
|
|
||||||
string $type,
|
|
||||||
string $message,
|
|
||||||
array $context = []
|
|
||||||
): EventLog {
|
|
||||||
$eventLog = new EventLog()
|
|
||||||
->setUser($user)
|
|
||||||
->setType($type)
|
|
||||||
->setMessage($message)
|
|
||||||
->setContext($context);
|
|
||||||
$this->getEntityManager()->persist($eventLog);
|
|
||||||
$this->getEntityManager()->flush();
|
|
||||||
return $eventLog;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,24 +2,20 @@
|
|||||||
|
|
||||||
namespace App\Monitor\Action\Handler;
|
namespace App\Monitor\Action\Handler;
|
||||||
|
|
||||||
use App\EventLog\Action\Command\AddEventLogCommand;
|
|
||||||
use App\Monitor\Action\Command\AddMonitorCommand;
|
use App\Monitor\Action\Command\AddMonitorCommand;
|
||||||
use App\Monitor\Action\Result\AddMonitorResult;
|
use App\Monitor\Action\Result\AddMonitorResult;
|
||||||
use App\Monitor\Framework\Entity\Monitor;
|
use App\Monitor\Framework\Entity\Monitor;
|
||||||
use App\Monitor\Framework\Repository\MonitorRepository;
|
use App\Monitor\Framework\Repository\MonitorRepository;
|
||||||
use App\Monitor\MonitorEvents;
|
|
||||||
use App\User\Framework\Repository\UserRepository;
|
use App\User\Framework\Repository\UserRepository;
|
||||||
use DateTimeImmutable;
|
use DateTimeImmutable;
|
||||||
use OneToMany\RichBundle\Contract\CommandInterface;
|
use OneToMany\RichBundle\Contract\CommandInterface;
|
||||||
use OneToMany\RichBundle\Contract\HandlerInterface;
|
use OneToMany\RichBundle\Contract\HandlerInterface;
|
||||||
use OneToMany\RichBundle\Contract\ResultInterface;
|
use OneToMany\RichBundle\Contract\ResultInterface;
|
||||||
use Symfony\Component\Messenger\MessageBusInterface;
|
|
||||||
|
|
||||||
/** @implements HandlerInterface<AddMonitorCommand> */
|
/** @implements HandlerInterface<AddMonitorCommand> */
|
||||||
readonly class AddMonitorHandler implements HandlerInterface
|
readonly class AddMonitorHandler implements HandlerInterface
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private MessageBusInterface $bus,
|
|
||||||
private MonitorRepository $movieMonitorRepository,
|
private MonitorRepository $movieMonitorRepository,
|
||||||
private UserRepository $userRepository,
|
private UserRepository $userRepository,
|
||||||
) {}
|
) {}
|
||||||
@@ -39,13 +35,6 @@ readonly class AddMonitorHandler implements HandlerInterface
|
|||||||
->setSearchCount(0)
|
->setSearchCount(0)
|
||||||
->setStatus('New');
|
->setStatus('New');
|
||||||
|
|
||||||
$this->bus->dispatch(new AddEventLogCommand(
|
|
||||||
$user,
|
|
||||||
MonitorEvents::MONITOR_ADDED->type(),
|
|
||||||
MonitorEvents::MONITOR_ADDED->message(),
|
|
||||||
(array) $monitor
|
|
||||||
));
|
|
||||||
|
|
||||||
$this->movieMonitorRepository->getEntityManager()->persist($monitor);
|
$this->movieMonitorRepository->getEntityManager()->persist($monitor);
|
||||||
$this->movieMonitorRepository->getEntityManager()->flush();
|
$this->movieMonitorRepository->getEntityManager()->flush();
|
||||||
|
|
||||||
|
|||||||
@@ -2,22 +2,22 @@
|
|||||||
|
|
||||||
namespace App\Monitor\Action\Handler;
|
namespace App\Monitor\Action\Handler;
|
||||||
|
|
||||||
use App\Download\DownloadEvents;
|
use App\Monitor\Action\Command\AddMonitorCommand;
|
||||||
use App\EventLog\Action\Command\AddEventLogCommand;
|
|
||||||
use App\Monitor\Action\Command\DeleteMonitorCommand;
|
use App\Monitor\Action\Command\DeleteMonitorCommand;
|
||||||
|
use App\Monitor\Action\Result\AddMonitorResult;
|
||||||
use App\Monitor\Action\Result\DeleteMonitorResult;
|
use App\Monitor\Action\Result\DeleteMonitorResult;
|
||||||
|
use App\Monitor\Framework\Entity\Monitor;
|
||||||
use App\Monitor\Framework\Repository\MonitorRepository;
|
use App\Monitor\Framework\Repository\MonitorRepository;
|
||||||
use App\Monitor\MonitorEvents;
|
use App\User\Framework\Repository\UserRepository;
|
||||||
|
use DateTimeImmutable;
|
||||||
use OneToMany\RichBundle\Contract\CommandInterface;
|
use OneToMany\RichBundle\Contract\CommandInterface;
|
||||||
use OneToMany\RichBundle\Contract\HandlerInterface;
|
use OneToMany\RichBundle\Contract\HandlerInterface;
|
||||||
use OneToMany\RichBundle\Contract\ResultInterface;
|
use OneToMany\RichBundle\Contract\ResultInterface;
|
||||||
use Symfony\Component\Messenger\MessageBusInterface;
|
|
||||||
|
|
||||||
/** @implements HandlerInterface<DeleteMonitorCommand, DeleteMonitorResult> */
|
/** @implements HandlerInterface<DeleteMonitorCommand, DeleteMonitorResult> */
|
||||||
readonly class DeleteMonitorHandler implements HandlerInterface
|
readonly class DeleteMonitorHandler implements HandlerInterface
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private MessageBusInterface $bus,
|
|
||||||
private MonitorRepository $monitorRepository,
|
private MonitorRepository $monitorRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@@ -27,13 +27,6 @@ readonly class DeleteMonitorHandler implements HandlerInterface
|
|||||||
$this->monitorRepository->getEntityManager()->remove($monitor);
|
$this->monitorRepository->getEntityManager()->remove($monitor);
|
||||||
$this->monitorRepository->getEntityManager()->flush();
|
$this->monitorRepository->getEntityManager()->flush();
|
||||||
|
|
||||||
$this->bus->dispatch(new AddEventLogCommand(
|
|
||||||
$monitor->getUser(),
|
|
||||||
MonitorEvents::MONITOR_DELETED->type(),
|
|
||||||
MonitorEvents::MONITOR_DELETED->message(),
|
|
||||||
(array) $monitor
|
|
||||||
));
|
|
||||||
|
|
||||||
return new DeleteMonitorResult(
|
return new DeleteMonitorResult(
|
||||||
status: 'OK',
|
status: 'OK',
|
||||||
result: [],
|
result: [],
|
||||||
|
|||||||
@@ -6,11 +6,9 @@ use App\Base\Util\EpisodeId;
|
|||||||
use App\Download\Action\Command\DownloadMediaCommand;
|
use App\Download\Action\Command\DownloadMediaCommand;
|
||||||
use App\Download\DownloadOptionEvaluator;
|
use App\Download\DownloadOptionEvaluator;
|
||||||
use App\Download\Framework\Repository\DownloadRepository;
|
use App\Download\Framework\Repository\DownloadRepository;
|
||||||
use App\EventLog\Action\Command\AddEventLogCommand;
|
|
||||||
use App\Monitor\Action\Command\MonitorMovieCommand;
|
use App\Monitor\Action\Command\MonitorMovieCommand;
|
||||||
use App\Monitor\Action\Result\MonitorTvEpisodeResult;
|
use App\Monitor\Action\Result\MonitorTvEpisodeResult;
|
||||||
use App\Monitor\Framework\Repository\MonitorRepository;
|
use App\Monitor\Framework\Repository\MonitorRepository;
|
||||||
use App\Monitor\MonitorEvents;
|
|
||||||
use App\Tmdb\TmdbClient;
|
use App\Tmdb\TmdbClient;
|
||||||
use App\Torrentio\Action\Command\GetTvShowOptionsCommand;
|
use App\Torrentio\Action\Command\GetTvShowOptionsCommand;
|
||||||
use App\Torrentio\Action\Handler\GetTvShowOptionsHandler;
|
use App\Torrentio\Action\Handler\GetTvShowOptionsHandler;
|
||||||
@@ -44,13 +42,6 @@ readonly class MonitorTvEpisodeHandler implements HandlerInterface
|
|||||||
$monitor = $this->monitorRepository->find($command->movieMonitorId);
|
$monitor = $this->monitorRepository->find($command->movieMonitorId);
|
||||||
$this->logger->info('> [MonitorTvEpisodeHandler] Executing MonitorTvEpisodeHandler for ' . $monitor->getTitle() . ' season ' . $monitor->getSeason() . ' episode ' . $monitor->getEpisode());
|
$this->logger->info('> [MonitorTvEpisodeHandler] Executing MonitorTvEpisodeHandler for ' . $monitor->getTitle() . ' season ' . $monitor->getSeason() . ' episode ' . $monitor->getEpisode());
|
||||||
|
|
||||||
$this->bus->dispatch(new AddEventLogCommand(
|
|
||||||
$monitor->getUser(),
|
|
||||||
MonitorEvents::MONITOR_STARTED->type(),
|
|
||||||
MonitorEvents::MONITOR_STARTED->message(),
|
|
||||||
(array) $command
|
|
||||||
));
|
|
||||||
|
|
||||||
$episodeData = $this->tmdb->tvEpisodeDetails($monitor->getTmdbId(), $monitor->getImdbId(), $monitor->getSeason(), $monitor->getEpisode());
|
$episodeData = $this->tmdb->tvEpisodeDetails($monitor->getTmdbId(), $monitor->getImdbId(), $monitor->getSeason(), $monitor->getEpisode());
|
||||||
|
|
||||||
if (null === $episodeData->airDate || "" === $episodeData->airDate) {
|
if (null === $episodeData->airDate || "" === $episodeData->airDate) {
|
||||||
@@ -125,25 +116,12 @@ readonly class MonitorTvEpisodeHandler implements HandlerInterface
|
|||||||
$this->logger->error('> [MonitorTvEpisodeHandler] ...Exception thrown: ' . $exception->getMessage());
|
$this->logger->error('> [MonitorTvEpisodeHandler] ...Exception thrown: ' . $exception->getMessage());
|
||||||
$this->logger->error($exception->getMessage());
|
$this->logger->error($exception->getMessage());
|
||||||
$monitor->setStatus('Active');
|
$monitor->setStatus('Active');
|
||||||
$this->bus->dispatch(new AddEventLogCommand(
|
|
||||||
$monitor->getUser(),
|
|
||||||
MonitorEvents::MONITOR_ERROR->type(),
|
|
||||||
MonitorEvents::MONITOR_ERROR->message() . ': ' . $exception->getMessage(),
|
|
||||||
(array) $monitor
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$monitor->setLastSearch(new DateTimeImmutable());
|
$monitor->setLastSearch(new DateTimeImmutable());
|
||||||
$monitor->setSearchCount($monitor->getSearchCount() + 1);
|
$monitor->setSearchCount($monitor->getSearchCount() + 1);
|
||||||
$this->monitorRepository->getEntityManager()->flush();
|
$this->monitorRepository->getEntityManager()->flush();
|
||||||
|
|
||||||
$this->bus->dispatch(new AddEventLogCommand(
|
|
||||||
$monitor->getUser(),
|
|
||||||
MonitorEvents::MONITOR_FINISHED->type(),
|
|
||||||
MonitorEvents::MONITOR_FINISHED->message(),
|
|
||||||
(array) $monitor
|
|
||||||
));
|
|
||||||
|
|
||||||
return new MonitorTvEpisodeResult(
|
return new MonitorTvEpisodeResult(
|
||||||
status: 'OK',
|
status: 'OK',
|
||||||
result: [
|
result: [
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Monitor;
|
|
||||||
|
|
||||||
enum MonitorEvents
|
|
||||||
{
|
|
||||||
case MONITOR_ADDED;
|
|
||||||
case MONITOR_STARTED;
|
|
||||||
case MONITOR_FINISHED;
|
|
||||||
case MONITOR_DELETED;
|
|
||||||
case MONITOR_ERROR;
|
|
||||||
|
|
||||||
public function type(): string
|
|
||||||
{
|
|
||||||
return match ($this) {
|
|
||||||
self::MONITOR_ADDED => 'monitor_added',
|
|
||||||
self::MONITOR_STARTED => 'monitor_started',
|
|
||||||
self::MONITOR_FINISHED => 'monitor_finished',
|
|
||||||
self::MONITOR_DELETED => 'monitor_deleted',
|
|
||||||
self::MONITOR_ERROR => 'monitor_error',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public function message(): string
|
|
||||||
{
|
|
||||||
return match ($this) {
|
|
||||||
self::MONITOR_ADDED => 'A new monitor has been added.',
|
|
||||||
self::MONITOR_STARTED => 'A monitor has started.',
|
|
||||||
self::MONITOR_FINISHED => 'A monitor has finished.',
|
|
||||||
self::MONITOR_DELETED => 'A monitor has been deleted',
|
|
||||||
self::MONITOR_ERROR => 'A monitor has encountered an error.',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -150,8 +150,6 @@ class TmdbClient
|
|||||||
$data['episode_count'] > 0;
|
$data['episode_count'] > 0;
|
||||||
})->map(function ($data) use ($media) {
|
})->map(function ($data) use ($media) {
|
||||||
return $this->tvSeasonDetails($media['id'], $data['season_number'])['episodes'];
|
return $this->tvSeasonDetails($media['id'], $data['season_number'])['episodes'];
|
||||||
})->rekey(function ($data) use ($media) {
|
|
||||||
return $data[1]['season_number'];
|
|
||||||
})->toArray();
|
})->toArray();
|
||||||
|
|
||||||
return $this->parseResult(
|
return $this->parseResult(
|
||||||
|
|||||||
@@ -21,32 +21,29 @@ class ResultFactory
|
|||||||
string $bingeGroup = "-",
|
string $bingeGroup = "-",
|
||||||
string $imdbId = "-",
|
string $imdbId = "-",
|
||||||
) {
|
) {
|
||||||
$title = trim(preg_replace('/\s+/', ' ', $title));
|
$ptn = (object) (new PTN())->parse($title);
|
||||||
$ptn = (object) new PTN()->parse(self::setFilename($url));
|
return new TorrentioResult(
|
||||||
$result = new TorrentioResult(
|
|
||||||
self::trimTitle($title),
|
self::trimTitle($title),
|
||||||
self::setUrl($url),
|
urldecode($url),
|
||||||
self::setFilename($url),
|
self::setFilename($url),
|
||||||
self::setSize($title),
|
self::setSize($title),
|
||||||
self::setSeeders($title),
|
self::setSeeders($title),
|
||||||
self::setProvider($title),
|
self::setProvider($title),
|
||||||
self::setEpisode($title),
|
self::setEpisode($title),
|
||||||
self::setSeason($ptn),
|
$ptn->season ?? "-",
|
||||||
$bingeGroup,
|
$bingeGroup,
|
||||||
self::setResolution($ptn),
|
$ptn->resolution ?? "-",
|
||||||
self::setCodec($ptn),
|
self::setCodec($ptn->codec ?? "-"),
|
||||||
self::setQuality($ptn),
|
$ptn->quality ?? "-",
|
||||||
$ptn,
|
$ptn,
|
||||||
self::setKey($url),
|
substr(base64_encode($url), strlen($url) - 10),
|
||||||
self::setEpisodeNumber($ptn),
|
$ptn->episode ?? "-",
|
||||||
self::setLanguages($title),
|
self::setLanguages($title),
|
||||||
self::setLanguageFlags($title),
|
self::setLanguageFlags($title),
|
||||||
false,
|
false,
|
||||||
uniqid(),
|
uniqid(),
|
||||||
$imdbId,
|
$imdbId,
|
||||||
);
|
);
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function setFilename(string $url)
|
public static function setFilename(string $url)
|
||||||
@@ -55,11 +52,6 @@ class ResultFactory
|
|||||||
return end($file);
|
return end($file);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function setUrl(string $url): string
|
|
||||||
{
|
|
||||||
return urldecode($url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function setSize(string $title): string
|
public static function setSize(string $title): string
|
||||||
{
|
{
|
||||||
$sizeMatch = [];
|
$sizeMatch = [];
|
||||||
@@ -120,15 +112,9 @@ class ResultFactory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function setCodec(object $ptn): string
|
public static function setCodec(string $codec): string
|
||||||
{
|
{
|
||||||
if (isset($ptn->codec) && array_key_exists($ptn->codec, self::$codecMap)) {
|
return self::$codecMap[strtolower($codec)] ?? $codec;
|
||||||
return self::$codecMap[strtolower($ptn->codec)];
|
|
||||||
} elseif (isset($ptn->codec)) {
|
|
||||||
return $ptn->codec;
|
|
||||||
}
|
|
||||||
|
|
||||||
return "-";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function setEpisode(string $title)
|
private static function setEpisode(string $title)
|
||||||
@@ -138,36 +124,6 @@ class ResultFactory
|
|||||||
return array_key_exists(0, $value) ? strtoupper($value[0]) : "n/a";
|
return array_key_exists(0, $value) ? strtoupper($value[0]) : "n/a";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function setSeason(object $ptn): string
|
|
||||||
{
|
|
||||||
return $ptn->season ?? "-";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function setBingeGroup(string $bingeGroup): string
|
|
||||||
{
|
|
||||||
return $bingeGroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function setResolution(object $ptn): string
|
|
||||||
{
|
|
||||||
return $ptn->resolution ?? "-";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function setQuality(object $ptn): string
|
|
||||||
{
|
|
||||||
return $ptn->quality ?? "-";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function setKey(string $url): string
|
|
||||||
{
|
|
||||||
return substr(base64_encode($url), strlen($url) - 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function setEpisodeNumber(object $ptn): string
|
|
||||||
{
|
|
||||||
return $ptn->episode ?? "-";
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function trimTitle(string $title)
|
private static function trimTitle(string $title)
|
||||||
{
|
{
|
||||||
$emoji = \Emoji\detect_emoji($title);
|
$emoji = \Emoji\detect_emoji($title);
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ final class TvEpisodeList
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->reloadCount++;
|
$this->reloadCount++;
|
||||||
|
// dd(new TvEpisodePaginator()->paginate($results, $this->pageNumber, $this->perPage));
|
||||||
return new TvEpisodePaginator()->paginate($results, $this->pageNumber, $this->perPage);
|
return new TvEpisodePaginator()->paginate($results, $this->pageNumber, $this->perPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ namespace App\User\Framework\Entity;
|
|||||||
|
|
||||||
use Aimeos\Map;
|
use Aimeos\Map;
|
||||||
use App\Download\Framework\Entity\Download;
|
use App\Download\Framework\Entity\Download;
|
||||||
use App\EventLog\Framework\Entity\EventLog;
|
|
||||||
use App\Monitor\Framework\Entity\Monitor;
|
use App\Monitor\Framework\Entity\Monitor;
|
||||||
use App\User\Framework\Repository\UserRepository;
|
use App\User\Framework\Repository\UserRepository;
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
@@ -57,18 +56,11 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
|||||||
#[ORM\OneToMany(targetEntity: Download::class, mappedBy: 'user')]
|
#[ORM\OneToMany(targetEntity: Download::class, mappedBy: 'user')]
|
||||||
private Collection $downloads;
|
private Collection $downloads;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var Collection<int, EventLog>
|
|
||||||
*/
|
|
||||||
#[ORM\OneToMany(targetEntity: EventLog::class, mappedBy: 'user')]
|
|
||||||
private Collection $eventLogs;
|
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->userPreferences = new ArrayCollection();
|
$this->userPreferences = new ArrayCollection();
|
||||||
$this->monitors = new ArrayCollection();
|
$this->monitors = new ArrayCollection();
|
||||||
$this->downloads = new ArrayCollection();
|
$this->downloads = new ArrayCollection();
|
||||||
$this->eventLogs = new ArrayCollection();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getId(): ?int
|
public function getId(): ?int
|
||||||
@@ -350,34 +342,4 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
|||||||
return $this->hasUserPreference('enable_ical_up_ep') &&
|
return $this->hasUserPreference('enable_ical_up_ep') &&
|
||||||
(bool) $this->getUserPreference('enable_ical_up_ep')->getPreferenceValue() === true;
|
(bool) $this->getUserPreference('enable_ical_up_ep')->getPreferenceValue() === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Collection<int, EventLog>
|
|
||||||
*/
|
|
||||||
public function getEventLogs(): Collection
|
|
||||||
{
|
|
||||||
return $this->eventLogs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function addEventLog(EventLog $eventLog): static
|
|
||||||
{
|
|
||||||
if (!$this->eventLogs->contains($eventLog)) {
|
|
||||||
$this->eventLogs->add($eventLog);
|
|
||||||
$eventLog->setUser($this);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function removeEventLog(EventLog $eventLog): static
|
|
||||||
{
|
|
||||||
if ($this->eventLogs->removeElement($eventLog)) {
|
|
||||||
// set the owning side to null (unless already changed)
|
|
||||||
if ($eventLog->getUser() === $this) {
|
|
||||||
$eventLog->setUser(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
{% extends 'bare.html.twig' %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<h2 class="px-4 py-4 text-3xl font-extrabold text-orange-500">{{ }}</h2>
|
|
||||||
<div class="flex flex-col bg-orange-500/50 p-4 rounded-lg gap-4 w-full md:w-[420px] border-orange-500 border-2 text-gray-50 animate-fade">
|
|
||||||
<div class="flex flex-col m-0 text-center">
|
|
||||||
<h3 class="text-2xl text-bold text-center text-gray-50">Oh crap!</h3>
|
|
||||||
<small>(or is it?)</small>
|
|
||||||
</div>
|
|
||||||
<p class="mb-2">There are many things I'm capable of, but this ain't one of 'em!</p>
|
|
||||||
<pre class="bg-gray-800 text-white p-4 rounded-md overflow-x-auto">
|
|
||||||
<code class="language-plaintext">
|
|
||||||
{{ exception.message }}
|
|
||||||
</code>
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
{% extends 'bare.html.twig' %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<h2 class="px-4 py-4 text-3xl font-extrabold text-orange-500">404</h2>
|
|
||||||
<div class="flex flex-col bg-orange-500/50 p-4 rounded-lg gap-4 w-full md:w-[420px] border-orange-500 border-2 text-gray-50 animate-fade">
|
|
||||||
<div class="flex flex-col m-0 text-center">
|
|
||||||
<h3 class="text-2xl text-bold text-center text-gray-50">It's not you, it's me!</h3>
|
|
||||||
<small>(or is it?)</small>
|
|
||||||
</div>
|
|
||||||
<p class="mb-2">I don't know, maybe I used to have that page-maybe I didn't, but one thing's for sure: I
|
|
||||||
don't have it now. Sorry!</p>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
>
|
>
|
||||||
<div class="p-4 md:p-6 flex flex-col gap-6 bg-orange-500/60 bg-clip-padding backdrop-filter backdrop-blur-md rounded-md">
|
<div class="p-4 md:p-6 flex flex-col gap-6 bg-orange-500/60 bg-clip-padding backdrop-filter backdrop-blur-md rounded-md">
|
||||||
<div class="flex flex-col md:flex-row gap-4">
|
<div class="flex flex-col md:flex-row gap-4">
|
||||||
{% if "jpg" in episode.poster %}
|
{% if episode.poster != null %}
|
||||||
<img class="w-full md:w-64 rounded-lg" src="{{ episode.poster }}" />
|
<img class="w-full md:w-64 rounded-lg" src="{{ episode.poster }}" />
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="w-full md:w-64 min-w-64 sticky h-[144px] rounded-lg bg-gray-700 flex items-center justify-center">
|
<div class="w-full md:w-64 min-w-64 sticky h-[144px] rounded-lg bg-gray-700 flex items-center justify-center">
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
[program:torsearch-worker]
|
|
||||||
command=/app/bin/console messenger:consume async -vv --time-limit 3600
|
|
||||||
numprocs={{ replicas|default(1) }}
|
|
||||||
stdout_logfile=/dev/stdout
|
|
||||||
stdout_logfile_maxbytes=0
|
|
||||||
stderr_logfile=/dev/stderr
|
|
||||||
stderr_logfile_maxbytes=0
|
|
||||||
autorestart=true
|
|
||||||
startretries=3
|
|
||||||
process_name=%(program_name)s_%(process_num)02d
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
[program:torsearch-downloader]
|
|
||||||
command=/app/bin/console messenger:consume download -vv --time-limit 3600
|
|
||||||
numprocs={{ replicas|default(1) }}
|
|
||||||
stdout_logfile=/dev/stdout
|
|
||||||
stdout_logfile_maxbytes=0
|
|
||||||
stderr_logfile=/dev/stderr
|
|
||||||
stderr_logfile_maxbytes=0
|
|
||||||
autorestart=true
|
|
||||||
startretries=3
|
|
||||||
process_name=%(program_name)s_%(process_num)02d
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
[program:torsearch-scheduler]
|
|
||||||
command=/app/bin/console messenger:consume scheduler_monitor monitor -vv --time-limit 21600
|
|
||||||
numprocs={{ replicas|default(1) }}
|
|
||||||
stdout_logfile=/dev/stdout
|
|
||||||
stdout_logfile_maxbytes=0
|
|
||||||
stderr_logfile=/dev/stderr
|
|
||||||
stderr_logfile_maxbytes=0
|
|
||||||
autorestart=true
|
|
||||||
startretries=3
|
|
||||||
process_name=%(program_name)s_%(process_num)02d
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
[supervisord]
|
|
||||||
nodaemon=true
|
|
||||||
logfile=/dev/null
|
|
||||||
logfile_maxbytes=0
|
|
||||||
pidfile=/run/supervisord.pid
|
|
||||||
Reference in New Issue
Block a user