feat: ntfy integration

This commit is contained in:
2025-08-08 23:38:53 -05:00
parent caeda625fd
commit 7d35b6266b
8 changed files with 229 additions and 13 deletions

7
.env
View File

@@ -51,3 +51,10 @@ OIDC_CLIENT_ID="Enter your OIDC client id"
OIDC_CLIENT_SECRET="Enter your OIDC client secret"
OIDC_BYPASS_FORM_LOGIN=false
###< drenso/symfony-oidc-bundle ###
###> symfony/ntfy-notifier ###
# NTFY_DSN=ntfy://default/TOPIC
###< symfony/ntfy-notifier ###
NOTIFICATION_TRANSPORT=
NTFY_DNS=

View File

@@ -43,6 +43,8 @@
"symfony/mailer": "7.3.*",
"symfony/mercure-bundle": "^0.3.9",
"symfony/messenger": "7.3.*",
"symfony/notifier": "7.3.*",
"symfony/ntfy-notifier": "7.3.*",
"symfony/runtime": "7.3.*",
"symfony/scheduler": "7.3.*",
"symfony/security-bundle": "7.3.*",

148
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "f4953f7b233a466d94269f35096f3385",
"content-hash": "6f57ba35ae317ec6370836bda0012db8",
"packages": [
{
"name": "1tomany/rich-bundle",
@@ -7578,6 +7578,152 @@
],
"time": "2025-02-19T08:51:26+00:00"
},
{
"name": "symfony/notifier",
"version": "v7.3.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/notifier.git",
"reference": "9e68a3266c8b0381f8756022b1c1ba3c0264416e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/notifier/zipball/9e68a3266c8b0381f8756022b1c1ba3c0264416e",
"reference": "9e68a3266c8b0381f8756022b1c1ba3c0264416e",
"shasum": ""
},
"require": {
"php": ">=8.2",
"psr/log": "^1|^2|^3"
},
"conflict": {
"symfony/event-dispatcher": "<6.4",
"symfony/event-dispatcher-contracts": "<2.5",
"symfony/http-client-contracts": "<2.5",
"symfony/http-kernel": "<6.4"
},
"require-dev": {
"symfony/event-dispatcher-contracts": "^2.5|^3",
"symfony/http-client-contracts": "^2.5|^3",
"symfony/http-foundation": "^6.4|^7.0",
"symfony/messenger": "^6.4|^7.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Notifier\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Sends notifications via one or more channels (email, SMS, ...)",
"homepage": "https://symfony.com",
"keywords": [
"notification",
"notifier"
],
"support": {
"source": "https://github.com/symfony/notifier/tree/v7.3.0"
},
"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-05-01T12:12:53+00:00"
},
{
"name": "symfony/ntfy-notifier",
"version": "v7.3.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/ntfy-notifier.git",
"reference": "094154ba36eac54078a71076effe46feaec59036"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/ntfy-notifier/zipball/094154ba36eac54078a71076effe46feaec59036",
"reference": "094154ba36eac54078a71076effe46feaec59036",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/clock": "^6.4|^7.0",
"symfony/http-client": "^6.4|^7.0",
"symfony/notifier": "^7.3"
},
"type": "symfony-notifier-bridge",
"autoload": {
"psr-4": {
"Symfony\\Component\\Notifier\\Bridge\\Ntfy\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mickael Perraud",
"email": "mikaelkael.fr@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Ntfy Notifier Bridge",
"homepage": "https://symfony.com",
"keywords": [
"Ntfy",
"notifier"
],
"support": {
"source": "https://github.com/symfony/ntfy-notifier/tree/v7.3.0"
},
"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-02-13T10:27:54+00:00"
},
{
"name": "symfony/options-resolver",
"version": "v7.3.0",

View File

@@ -0,0 +1,13 @@
framework:
notifier:
chatter_transports:
texter_transports:
ntfy: '%notification.ntfy.dsn%'
channel_policy:
# use chat/slack, chat/telegram, sms/twilio or sms/nexmo
urgent: ['email']
high: ['email']
medium: ['email']
low: ['email']
admin_recipients:
- { email: admin@example.com }

View File

@@ -44,6 +44,10 @@ parameters:
auth.oidc.client_secret: '%env(OIDC_CLIENT_SECRET)%'
auth.oidc.bypass_form_login: '%env(bool:OIDC_BYPASS_FORM_LOGIN)%'
# Notifications
notification.transport: '%env(NOTIFICATION_TRANSPORT)%'
notification.ntfy.dsn: '%env(NTFY_DSN)%'
services:
# default configuration for services in *this* file
_defaults:

View File

@@ -2,23 +2,31 @@
namespace App\Base\Service;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Mercure\HubInterface;
use Symfony\Component\Mercure\Update;
use Symfony\Component\Notifier\Notification\Notification;
use Symfony\Component\Notifier\NotifierInterface;
use Twig\Environment;
readonly class Broadcaster
{
public function __construct(
#[Autowire(param: 'notification.transport')]
private string $notificationTransport,
#[Autowire(service: 'twig')]
private Environment $renderer,
private HubInterface $hub,
private RequestStack $requestStack,
private NotifierInterface $notifier,
private LoggerInterface $logger,
) {}
public function alert(string $title, string $message, string $type = "success"): void
public function alert(string $title, string $message, string $type = "success", bool $sendPush = false): void
{
try {
$userAlertTopic = $this->requestStack->getCurrentRequest()->getSession()->get('mercure_alert_topic');
$update = new Update(
$userAlertTopic,
@@ -30,5 +38,17 @@ readonly class Broadcaster
])
);
$this->hub->publish($update);
} catch (\Throwable $exception) {
// ToDo: look for better handling to get message to end user
}
if (true === $sendPush && in_array($this->notificationTransport, ['ntfy'])) {
try {
$notification = new Notification($title, ['push'])->content($message);
$this->notifier->send($notification);
} catch (\Throwable $exception) {
$this->logger->error('Unable to send push notification: ' . $exception->getMessage());
}
}
}
}

View File

@@ -2,6 +2,7 @@
namespace App\Download\Downloader;
use App\Base\Service\Broadcaster;
use App\Base\Service\MediaFiles;
use App\Download\Framework\Entity\Download;
use Doctrine\ORM\EntityManagerInterface;
@@ -19,6 +20,7 @@ class ProcessDownloader implements DownloaderInterface
private EntityManagerInterface $entityManager,
private MediaFiles $mediaFiles,
private CacheInterface $cache,
private readonly Broadcaster $broadcaster,
) {}
/**
@@ -82,6 +84,7 @@ class ProcessDownloader implements DownloaderInterface
});
if ($downloadEntity->getStatus() !== 'Paused') {
$downloadEntity->setProgress(100);
$this->broadcaster->alert('Success', '"'.$title.'" has finished downloading."', sendPush: true);
}
} catch (ProcessFailedException $exception) {
$downloadEntity->setStatus('Failed');

View File

@@ -232,6 +232,27 @@
"config/packages/messenger.yaml"
]
},
"symfony/notifier": {
"version": "7.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.0",
"ref": "178877daf79d2dbd62129dd03612cb1a2cb407cc"
},
"files": [
"config/packages/notifier.yaml"
]
},
"symfony/ntfy-notifier": {
"version": "7.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.4",
"ref": "0d5e496659d7361bb4e6648eb8332f8cf097533d"
}
},
"symfony/property-info": {
"version": "7.3",
"recipe": {