oliverthiele/ot-alerts

OT Alerts - Alert management for TYPO3 extensions — Pushover notifications with rate limiting

Maintainers

Package info

github.com/oliverthiele/ot-alerts

Homepage

Type:typo3-cms-extension

pkg:composer/oliverthiele/ot-alerts

Statistics

Installs: 15

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.2.1 2026-05-15 12:13 UTC

This package is auto-updated.

Last update: 2026-05-15 12:14:55 UTC


README

Centralised alert proxy for TYPO3 extensions — sends Pushover push notifications with built-in rate limiting and deduplication. Other extensions simply call AlertManager::notify() and AlertManager::resolve(); ot_alerts handles throttling, state tracking, and channel dispatch.

TYPO3 Packagist Version PHP License Changelog

Features

  • Pushover push notifications via REST API with HTML formatting
  • Event key and occurrence count visible in every notification
  • Optional tappable link button in Pushover (via context['url'])
  • Rate limiting: first occurrence triggers immediately, then once per configurable reminder interval
  • State machine: NEW → NOTIFIED → RESOLVED — resolved errors trigger fresh notifications when they reappear
  • DB-backed event log (tx_otalerts_events) for audit trail and future backend module
  • Optional integration: inject ?AlertManager via constructor — ot_alerts is not a hard dependency, the service is simply null when not installed
  • Configurable reminder interval via TYPO3 Extension Configuration

Requirements

Requirement Version
TYPO3 ^13.4 || ^14.0
PHP ^8.4
guzzlehttp/guzzle ^7.0

Installation

composer require oliverthiele/ot-alerts

After installation, run database schema update:

vendor/bin/typo3 database:updateschema

Configuration

Environment Variables

Add the following to your .env file:

PUSHOVER_APP_TOKEN=your_app_token_here
PUSHOVER_USER_KEY=your_user_key_here

Both values are available in your Pushover dashboard.

Extension Configuration

Configure in the TYPO3 backend under Admin Tools → Settings → Extension Configuration → ot_alerts:

Key Type Default Description
reminderInterval int 3600 Seconds between reminder notifications (1 hour)
pushoverEmergencyRetry int 60 Seconds between retries for CRITICAL alerts (min 30)
pushoverEmergencyExpire int 3600 Seconds until Pushover stops retrying (max 10800)

Usage

Optional dependency via constructor injection

The recommended integration pattern uses TYPO3's Symfony DI container. Declare ?AlertManager as a nullable constructor parameter — when ot_alerts is not installed, the container injects null and all calls are silently skipped via the null-safe operator:

use OliverThiele\OtAlerts\Alert\Alert;
use OliverThiele\OtAlerts\Alert\AlertSeverity;
use OliverThiele\OtAlerts\Service\AlertManager;

class MyService
{
    public function __construct(
        private readonly ?AlertManager $alertManager = null,
    ) {}

    public function doSomething(): void
    {
        // ... your logic ...

        // notify — only fires when ot_alerts is installed
        $this->alertManager?->notify(new Alert(
            source: 'my_extension',
            eventKey: 'api.connection.failed',
            message: 'Could not connect to external API',
            severity: AlertSeverity::ERROR,
        ));
    }
}

No class_exists() guard or GeneralUtility::makeInstance() needed — the container resolves the optional service automatically.

Sending an alert

$this->alertManager?->notify(new Alert(
    source: 'my_extension',
    eventKey: 'api.connection.failed',
    message: 'Could not connect to external API',
    severity: AlertSeverity::ERROR,
));

Sending an alert with a URL

Pass context['url'] to add a tappable link button to the Pushover notification. This is useful to open the affected page directly from the push:

$this->alertManager?->notify(new Alert(
    source: 'my_extension',
    eventKey: 'api.connection.failed',
    message: 'Could not connect to external API',
    severity: AlertSeverity::ERROR,
    context: ['url' => 'https://example.com/affected-page/'],
));

Resolving an alert

Call resolve() once the error condition is no longer present. This resets the state so the next occurrence will trigger a fresh notification immediately.

$this->alertManager?->resolve('my_extension', 'api.connection.failed');

Notification format

Pushover messages use HTML formatting for readability:

Title:    [ERROR] my_extension

Message:  api.connection.failed       ← bold event key

          Could not connect to
          external API

          occurrence #3               ← italic, only shown from 2nd occurrence onwards

[Open page →]                         ← tappable link button, only shown when context['url'] is set

Severity levels and Pushover priorities

Severity Pushover priority Behaviour
INFO Low (-1) Quiet notification, no sound
WARNING Normal (0) Default sound and vibration
ERROR High (1) Bypasses quiet hours
CRITICAL Emergency (2) Repeated every pushoverEmergencyRetry seconds until acknowledged

Emergency notifications (CRITICAL) require acknowledgement in the Pushover app.

Notification behaviour

First error  →  Push sent immediately  →  status: NOTIFIED
Still broken →  Push after reminderInterval  →  status: NOTIFIED
Error fixed  →  resolve() called  →  status: RESOLVED
New error    →  Push sent immediately  →  status: NOTIFIED

CLI

Test notification

Verify that Pushover credentials are configured and a push is delivered:

vendor/bin/typo3 ot_alerts:test

Send with a specific severity:

vendor/bin/typo3 ot_alerts:test --severity=error

Reset the rate limit after the test so the next real error triggers immediately:

vendor/bin/typo3 ot_alerts:test --resolve

Show per-channel dispatch result including HTTP status:

vendor/bin/typo3 ot_alerts:test -v

Show the raw Pushover API response body (full debug output):

vendor/bin/typo3 ot_alerts:test -vvv

If the alert was previously sent and the reminder interval has not yet elapsed, the command shows [WARNING] Rate limit active. Use --resolve to bypass: the command pre-resolves the event before sending (so the rate limit is skipped) and post-resolves after (so the next test also sends immediately).

The command shows which ENV variables are present, dispatches the alert, and prints the result.

License

GPL-2.0-or-later — © 2025 Oliver Thiele