Skip to content

Commit

Permalink
SMS Log viewer added
Browse files Browse the repository at this point in the history
  • Loading branch information
hafijul233 committed May 19, 2024
1 parent 9cba736 commit 181981a
Show file tree
Hide file tree
Showing 8 changed files with 357 additions and 21 deletions.
32 changes: 22 additions & 10 deletions config/sms.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,6 @@
use Laraflow\Sms\Providers;

return [

/*
|--------------------------------------------------------------------------
| Response Logger
|--------------------------------------------------------------------------
| this configuration is for debugging purpose. if enabled then program will log
| sms vendor response in debug category.
*/
'log' => (bool)env('SMS_LOG', env('APP_DEBUG', false)),

/*
|--------------------------------------------------------------------------
| Default Vendor
Expand Down Expand Up @@ -42,6 +32,28 @@
*/
'from' => env('SMS_FROM_NAME', env('APP_NAME', 'Laravel')),

/*
|--------------------------------------------------------------------------
| Response Logger
|--------------------------------------------------------------------------
| this configuration is for debugging purpose. if enabled then program will log
| sms vendor response in debug category.
*/
'log' => (bool)env('SMS_LOG', env('APP_DEBUG', false)),

/*
|--------------------------------------------------------------------------
| Response Log Viewer
|--------------------------------------------------------------------------
| this configuration is for debugging purpose. if enabled then program will log
| sms vendor response in debug category.
*/
'log_viewer' => [
'enabled' => env('SMS_LOG_VIEWER', env('APP_DEBUG', false)),
'uri' => 'sms-logs',
'middleware' => null,
],

/*
|--------------------------------------------------------------------------
| Vendor Configuration
Expand Down
125 changes: 125 additions & 0 deletions src/Controllers/SmsLogController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<?php

namespace Laraflow\Sms\Controllers;


use Carbon\CarbonImmutable;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class SmsLogController extends Controller
{
public Collection $entries;

public function __construct()
{
$this->entries = collect();

$this->loadEntries();
}

private function loadEntries(): void
{
foreach (Storage::disk('log')->files() as $file) {
if (!str_contains($file, 'sms-')) {
continue;
}

$date = CarbonImmutable::createFromFormat('Y-m-d', preg_replace('/sms-(\d{4}-\d{2}-\d{2})\.log/i', '$1', $file));

$this->entries->put($date->format('Y-m-d'), [
'position' => now()->diffInDays($date),
'file' => $file,
'date' => $date,
'size' => Storage::disk('log')->size($file),
'modified_at' => CarbonImmutable::parse(Storage::disk('log')->lastModified($file)),
]);
}

$this->entries = $this->entries->sortBy('position');
}

/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$current = $request->has('date') ? $this->entries->get($request->input('date')) : $this->entries->first();

if (!$current) {
throw (new ModelNotFoundException)->setModel('SmsLog', $request->input('date', now()->format('Y-m-d')));
}

$current['logs'] = $this->parseFileContent($current['file']);

return view('sms::index', [
'entries' => $this->entries,
'current' => $current
]);
}

/**
* Display the specified resource.
*/
public function download(string $date)
{
//
}

/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}

private function parseFileContent(string $file): Collection
{
$file = Storage::disk('log')->readStream($file);

$entries = collect();

while (!feof($file)) {
$item = $this->parseLine(fgets($file));

if (!empty($item)) {
$entries->push($item);
}
}

return $entries->sortBy('position');
}

private function parseLine(string $line): array
{
$pattern = '/\[(\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2})\] .*\.INFO:\sResponse:\s+(.*)/';

$matches = [];

preg_match($pattern, $line, $matches);

$data = [];

if (!empty($matches)) {

$timestamp = CarbonImmutable::parse($matches[1] ?? null, 'Asia/Dhaka');

$data['position'] = now()->diffInSeconds($timestamp);
$data['timestamp'] = $timestamp;

$response = json_decode($matches[2] ?? '{}', true);
$data['vendor'] = Str::studly($response['vendor'] ?? 'N/A');
$data['mode'] = Str::studly($response['mode'] ?? 'N/A');
$data['code'] = Str::studly($response['status_code'] ?? 'N/A');
$data['response'] = json_encode($response['response'] ?? [], JSON_PRETTY_PRINT);
}

return $data;
}
}
25 changes: 21 additions & 4 deletions src/SmsChannel.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,20 +59,31 @@ private function logSmsResponse(): void
if (config('sms.log', false)) {
Log::channel('sms')->info('Response: ', [
'vendor' => $this->driver_code,
'model' => $this->driver->mode,
'mode' => $this->driver->mode,
'status_code' => $this->response->status(),
'response' => $this->response->body()
'response' => $this->processResponseBody($this->response->body())
]);
}
}

private function processResponseBody($content)
{
$dump = json_decode($content, true);

if (json_last_error() == JSON_ERROR_NONE) {
return $dump;
}

return $content;
}

private function validate(SmsMessage $message): void
{
if (strlen($message->getReceiver()) == 0) {
if (empty($message->getReceiver())) {
throw new InvalidArgumentException('Message recipient(s) is empty.');
}

if (strlen($message->getContent()) == 0) {
if (empty($message->getContent())) {
throw new InvalidArgumentException('Message content is empty.');
}
}
Expand All @@ -95,6 +106,12 @@ public function send(object $notifiable, Notification $notification): void
*/
$message = $notification->toSms($notifiable);

if (!$to = $notifiable->routeNotificationFor('sms', $notification)) {
throw new BadMethodCallException(get_class($notifiable) . " notifiable is missing the `routeNotificationForSms(object $notifiable): string` method.");
}

$message->to($to);

$this->initDriver($message->getDriver());

$this->validate($message);
Expand Down
15 changes: 10 additions & 5 deletions src/SmsMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ class SmsMessage

private ?string $driver;

public function __construct()
public function __construct(array $options = [])
{
$this->receiver = null;
$this->sender = config('sms.from', config('app.name'));
$this->content = null;
$this->driver = config('sms.default');
$this->receiver = $options['to'] ?? null;
$this->sender = $options['from'] ?? config('sms.from', config('app.name'));
$this->content = $options['message'] ?? null;
$this->driver = $options['vendor'] ?? config('sms.default');
}

public function getReceiver(): ?string
Expand Down Expand Up @@ -73,4 +73,9 @@ public function vendor($name = null): self

return $this;
}

public function send()
{

}
}
8 changes: 6 additions & 2 deletions src/SmsServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ public function boot(): void
], 'sms-config');

$this->extendNotificationChannel();

$this->loadRoutesFrom(__DIR__.'/routes.php');

$this->loadViewsFrom(__DIR__.'/../view', 'sms');
}

/**
Expand All @@ -44,9 +48,9 @@ private function extendNotificationChannel(): void
});
}

private function extendLoggerChannel()
private function extendLoggerChannel(): void
{
Config::set('sms', [
Config::set('logging.channels.sms', [
'driver' => 'daily',
'path' => storage_path('logs/sms.log'),
'level' => 'info',
Expand Down
11 changes: 11 additions & 0 deletions src/routes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

use Illuminate\Support\Facades\Route;

if (config('sms.log_viewer.enabled')) {
Route::prefix(config('sms.log_viewer.uri'))->group(function () {
Route::get('/', [\Laraflow\Sms\Controllers\SmsLogController::class, 'index'])->name('sms-logs.index');
Route::get('/{date}', [\Laraflow\Sms\Controllers\SmsLogController::class, 'show'])->name('sms-logs.show');
Route::delete('/{date}', [\Laraflow\Sms\Controllers\SmsLogController::class, 'destroy'])->name('sms-logs.destroy');
});
}
42 changes: 42 additions & 0 deletions view/index.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
@extends('sms::layout')

@section('content')
<div
class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">{{ $current['date']->format('D, d M Y') }}</h1>
<div class="btn-toolbar mb-2 mb-md-0 gap-3">
<button type="button" class="btn btn-sm btn-outline-primary">
<span data-feather="file"></span>
Download
</button>
<button type="button" class="btn btn-sm btn-outline-danger">
<span data-feather="file"></span>
Delete
</button>
</div>
</div>
<div class="table-responsive">
<table class="table table-bordered table-hover" id="logs">
<thead>
<tr class="text-center">
<th scope="col">Timestamp</th>
<th scope="col">Vendor</th>
<th scope="col">Mode</th>
<th scope="col">Code</th>
<th scope="col">Response</th>
</tr>
</thead>
<tbody>
@foreach($current['logs'] as $response)
<tr>
<td>{{ $response['timestamp']->format('D, d M Y h:m:s A') }}</td>
<td>{{ $response['vendor'] ?? 'N/A' }}</td>
<td>{{ $response['mode'] ?? 'N/A' }}</td>
<td>{{ $response['code'] ?? 'N/A' }}</td>
<td><code><pre>{{ $response['response'] ?? '{}' }}</pre></code></td>
</tr>
@endforeach
</tbody>
</table>
</div>
@endsection
Loading

0 comments on commit 181981a

Please sign in to comment.