Skip to content

Feature/lar 10 schedule notifications #152

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

Merged
Merged
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
26 changes: 26 additions & 0 deletions app/Console/Commands/NotifyPendingArticles.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace App\Console\Commands;

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

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
{
$pendingArticles = Article::awaitingApproval()->get();

if ($pendingArticles->isNotEmpty()) {
$notifiable->notify(new PendingArticlesNotification($pendingArticles));
}
}
}
3 changes: 2 additions & 1 deletion app/Console/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@ 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')->days(2);
}
}

protected function commands(): void
{
$this->load(__DIR__.'/Commands');
}
}
}
52 changes: 52 additions & 0 deletions app/Notifications/PendingArticlesNotification.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Notifications\Messages\MailMessage;
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.channel'))
->content($message);
}

private function content(): string
{
$message = __("Pending approval articles:\n\n");
foreach ($this->pendingArticles as $article) {
$message .= __(
"[@:username](:profile_url) submitted the article [:title](:url) on: :date\n\n", [
'username' => $article->user?->username,
'profile_url' => route('profile', $article->user?->username),
'title' => $article->title,
'url' => route('articles.show', $article->slug),
'date' => $article->submitted_at->translatedFormat('d/m/Y')
]
);
}

return $message;
}
}
6 changes: 4 additions & 2 deletions lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@
"The given :attribute has appeared in a data leak. Please choose a different :attribute.": "The given :attribute has appeared in a data leak. Please choose a different :attribute.",
"Verify Email Address": "Verify Email Address",
"Please click the button below to verify your email address.": "Please click the button below to verify your email address.",
"If you did not create an account, no further action is required.": "If you did not create an account, no further action is required."
}
"If you did not create an account, no further action is required.": "If you did not create an account, no further action is required.",
"Pending approval articles:" : "Pending approval articles:",
"[@:username](:profile_url) submitted the article [:title](:url) on: :date" : "[@:username](:profile_url) submitted the article [:title](:url) on: :date"
}
6 changes: 4 additions & 2 deletions lang/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@
"The given :attribute has appeared in a data leak. Please choose a different :attribute.": "Le champ :attribute donné est apparu dans une fuite de données. Veuillez choisir un autre :attribute.",
"Verify Email Address": "Vérifier l'adresse e-mail",
"Please click the button below to verify your email address.": "Veuillez cliquer sur le bouton ci-dessous pour vérifier votre adresse email.",
"If you did not create an account, no further action is required.": "Si vous n'avez pas créé de compte, aucune autre action n'est requise."
}
"If you did not create an account, no further action is required.": "Si vous n'avez pas créé de compte, aucune autre action n'est requise.",
"Pending approval articles:" : "Articles soumis en attente d'approbation:",
"[@:username](:profile_url) submitted the article [:title](:url) on: :date" : "[@:username](:profile_url) a soumit l'article [:title](:url) le: :date"
}
49 changes: 49 additions & 0 deletions tests/Feature/NotifyPendingArticlesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

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

beforeEach(fn() => Notification::fake());

it('will send a notification when there are pending articles', function (): void {
Article::factory()->createMany([
[
'submitted_at' => now(),
],
[
'submitted_at' => now()->subDay(),
'approved_at' => now(),
],
[
'submitted_at' => now()->subDay(),
'declined_at' => now(),
],
]);

$this->assertDatabaseCount('articles', 3);
$this->artisan(NotifyPendingArticles::class)->assertExitCode(0);

Notification::assertCount(1);
});

it('will not send a notification when there are no pending articles', function (): void {
Article::factory()->createMany([
[
'submitted_at' => now()->subDay(),
'approved_at' => now(),
],
[
'submitted_at' => now()->subDay(),
'declined_at' => now(),
],
]);

$this->assertDatabaseCount('articles', 2);
$this->artisan(NotifyPendingArticles::class)->assertExitCode(0);

Notification::assertNothingSent();
Notification::assertCount(0);
});
7 changes: 1 addition & 6 deletions tests/Integration/DiscussionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,6 @@
use App\Models\Activity;
use App\Models\Discussion;
use App\Models\Tag;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);
uses(DatabaseMigrations::class);

it('can find by slug', function (): void {
Discussion::factory()->create(['slug' => 'foo']);
Expand Down Expand Up @@ -74,4 +69,4 @@

// When providing a slug with invalid url characters, a random 5 character string is returned.
expect($discussion->slug())->toMatch('/\w{5}/');
});
});
7 changes: 1 addition & 6 deletions tests/Integration/ThreadTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,6 @@
use App\Models\Thread;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);
uses(DatabaseMigrations::class);

it('can find by slug', function (): void {
Thread::factory()->create(['slug' => 'foo']);
Expand Down Expand Up @@ -192,4 +187,4 @@ function createActiveThread(): Thread
$reply->save();

return $thread;
}
}