Source path: app/Listeners/NotifyUser.php
Extracted from supplied specification. Review before copying into application.

<?php
namespace App\Listeners;

use App\Events\{PostFailed, PostPublished, TokenExpiring, VideoReady};
use App\Notifications\GenericAlert;

class NotifyUser
{
    public function published(PostPublished $e): void
    {
        $t = $e->target;
        $this->send($t->post->user, 'post_published', 'Post is live',
            "Published to {$t->socialAccount->platform} ({$t->socialAccount->name}).", $t->permalink);
    }

    public function failed(PostFailed $e): void
    {
        $t = $e->target;
        $this->send($t->post->user, 'post_failed', 'Post failed',
            "Failed on {$t->socialAccount->platform}: {$t->error}");
    }

    public function tokenExpiring(TokenExpiring $e): void
    {
        $a = $e->account;
        $this->send($a->user, 'token_expiring', 'Reconnect your account',
            "Your {$a->platform} connection ({$a->name}) is expiring. Please reconnect.");
    }

    public function videoReady(VideoReady $e): void
    {
        $this->send($e->media->user, 'video_ready', 'Your AI video is ready', 'Open the composer to attach it.');
    }

    private function send($user, string $event, string $title, string $body, ?string $url = null): void
    {
        $channels = $user->notificationRules()
            ->where('event', $event)->where('is_enabled', 1)->pluck('channel')->all()
            ?: ['mail']; // default

        $via = array_map(fn ($c) => $c === 'telegram' ? \App\Channels\TelegramChannel::class : $c, $channels);
        $user->notify(new GenericAlert($title, $body, $url, $via));
    }
}
