Skip to content

feat: LAR 10 Send a Telegram notification for articles #150

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ UNSPLASH_ACCESS_KEY=

TELEGRAM_BOT_TOKEN=
TELEGRAM_CHANNEL=
TELEGRAM_CHAT_ID=

MEDIA_DISK=media
FILAMENT_FILESYSTEM_DISK=${MEDIA_DISK}
Expand Down
34 changes: 34 additions & 0 deletions app/Console/Commands/NotifyPendingArticles.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace App\Console\Commands;

use App\Models\Article;
use App\Notifications\PendingArticlesNotification;
use Illuminate\Console\Command;
use Illuminate\Notifications\AnonymousNotifiable;
use Illuminate\Support\Facades\Notification;

final class NotifyPendingArticles extends Command
{
protected $signature = 'lcm:notify-pending-articles';

protected $description = 'Send a Telegram notification for articles that are submitted but neither approved nor declined';

public function handle(AnonymousNotifiable $notifiable): void
{
// Récupérer les articles soumis mais non approuvés ni déclinés via le scope awaitingApproval
$pendingArticles = Article::awaitingApproval()->get();

if ($pendingArticles->isEmpty()) {
$this->info('❌ No pending articles found.');

return;
}

//Envoi de la notification via télégram
$notifiable->notify(new PendingArticlesNotification($pendingArticles));
$this->info('✅ Notification sent successfully.');
}
}
1 change: 1 addition & 0 deletions app/Console/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ protected function schedule(Schedule $schedule): void
$schedule->command('lcm:post-article-to-telegram')->everyFourHours();
$schedule->command('lcm:send-unverified-mails')->weeklyOn(1, '8:00');
$schedule->command('sitemap:generate')->daily();
$schedule->command('lcm:notify-pending-articles')->everyTwoDays();
}
}

Expand Down
45 changes: 45 additions & 0 deletions app/Notifications/PendingArticlesNotification.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

declare(strict_types=1);

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Notifications\Notification;
use NotificationChannels\Telegram\TelegramChannel;
use NotificationChannels\Telegram\TelegramMessage;

final class PendingArticlesNotification extends Notification
{
use Queueable;

public function __construct(public Collection $pendingArticles) {}

public function via(mixed $notifiable): array
{
return [TelegramChannel::class];
}

public function toTelegram(): TelegramMessage
{
$message = $this->content();

return TelegramMessage::create()
->to(config('services.telegram-bot-api.chat_id'))
->content($message);
}

private function content(): string
{
$message = "Articles soumis en attente d'approbation: \n";
foreach ($this->pendingArticles as $article) {
$url = route('articles.show', $article->slug);
$message .= "• Titre: [{$article->title}]({$url})\n";
$message .= '• Par: [@'.$article->user?->username.']('.route('profile', $article->user?->username).")\n";
$message .= "• Soumis le: {$article->submitted_at->format('D/m/Y')}\n\n";
}

return $message;
}
}
1 change: 1 addition & 0 deletions config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
'telegram-bot-api' => [
'token' => env('TELEGRAM_BOT_TOKEN'),
'channel' => env('TELEGRAM_CHANNEL'),
'chat_id' => env('TELEGRAM_CHAT_ID'),
],

];
39 changes: 39 additions & 0 deletions tests/Feature/NotifyPendingArticlesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

use App\Console\Commands\NotifyPendingArticles;
use App\Models\Article;
use App\Notifications\PendingArticlesNotification;
use Illuminate\Notifications\AnonymousNotifiable;
use Illuminate\Support\Facades\Notification;

it('will send a notification when there are pending articles', function (): void {
// Simuler l'envoi d'une fake notification
Notification::fake();

//création de l'article et on s'assure qu'elle est en bd.
$articles = Article::factory()->create(['submitted_at' => now()]);
$this->assertDatabaseCount('articles', 1);

// Exécution de la commande lcm:notify-pending-articles
$this->artisan(NotifyPendingArticles::class)->expectsOutput('✅ Notification sent successfully.')
->assertExitCode(0);

// Vérification qu'une notification à été envoyée pour l'article en attente
Notification::assertSentTo(
new AnonymousNotifiable(),
PendingArticlesNotification::class,
fn ($notification) => $notification->pendingArticles->contains($articles)
);
});

it('will not send a notification when there are no pending articles', function (): void {
Notification::fake();

$this->artisan(NotifyPendingArticles::class)->expectsOutput('❌ No pending articles found.')
->assertExitCode(0);

// Vérifier qu'aucune notification n'a été envoyée
Notification::assertNothingSent();
});