This commit is contained in:
46
app/Bots/BashScript.php
Normal file
46
app/Bots/BashScript.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\Bots;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class BashScript implements BotContract
|
||||
{
|
||||
protected array $config;
|
||||
|
||||
public function __construct(array $config = [])
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
if (!empty($this->config['script'])) {
|
||||
// Execute the bash script
|
||||
$script = $this->config['script'];
|
||||
$output = [];
|
||||
$returnVar = null;
|
||||
exec($script, $output, $returnVar);
|
||||
|
||||
if ($returnVar !== 0) {
|
||||
// Log error if the script failed
|
||||
\Illuminate\Support\Facades\Log::error("Bash script execution failed: " . implode("\n", $output));
|
||||
} else {
|
||||
Log::info("Bash script executed successfully: " . implode("\n", $output));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function configSchema(): array
|
||||
{
|
||||
return [
|
||||
'script' => [
|
||||
'type' => 'textarea',
|
||||
'label' => 'Bash Script',
|
||||
'rules' => [
|
||||
'required',
|
||||
]
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,13 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$bots = \App\Models\Bot::all();
|
||||
$bots = Auth::user()->bots;
|
||||
|
||||
return view('dashboard', compact('bots'));
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\Bot;
|
||||
use App\Models\BotLog;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Queue\Queueable;
|
||||
|
||||
@@ -13,9 +14,7 @@ class RunBot implements ShouldQueue
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*/
|
||||
public function __construct(private Bot $bot)
|
||||
{
|
||||
}
|
||||
public function __construct(private Bot $bot, private BotLog $log) {}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
@@ -24,6 +23,22 @@ class RunBot implements ShouldQueue
|
||||
{
|
||||
$class = new $this->bot->class($this->bot->config ?? []);
|
||||
|
||||
$class->run();
|
||||
try {
|
||||
$class->run();
|
||||
|
||||
// Update the log entry on success
|
||||
$this->log->update([
|
||||
'finished_at' => now(),
|
||||
'status' => 'success',
|
||||
// 'output' => is_string($result) ? $result : json_encode($result, JSON_PRETTY_PRINT),
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
// Log the error in the bot log
|
||||
$this->log->update([
|
||||
'finished_at' => now(),
|
||||
'status' => 'failed',
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
35
app/Livewire/BotLogs.php
Normal file
35
app/Livewire/BotLogs.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire;
|
||||
|
||||
use App\Models\BotLog;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithoutUrlPagination;
|
||||
use Livewire\WithPagination;
|
||||
|
||||
class BotLogs extends Component
|
||||
{
|
||||
use WithPagination;
|
||||
use WithoutUrlPagination;
|
||||
|
||||
// public function mount()
|
||||
// {
|
||||
// $this->getLogs();
|
||||
// }
|
||||
|
||||
// public function getLogs(): void
|
||||
// {
|
||||
// $this->logs = Auth::user()->bots->pluck('logs')->flatten()->sortByDesc('created_at');
|
||||
// }
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.bot-logs', [
|
||||
'logs' => BotLog::whereHas('bot', fn($q) => $q->where('user_id', Auth::id()))
|
||||
->orderBy('created_at', 'desc')
|
||||
->latest()
|
||||
->paginate(10),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -12,11 +12,21 @@ class BotsList extends Component
|
||||
{
|
||||
public $bots;
|
||||
|
||||
public string $query = '';
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->bots = Auth::user()->bots;
|
||||
}
|
||||
|
||||
public function search()
|
||||
{
|
||||
$this->bots = Auth::user()->bots()
|
||||
->where('name', 'like', '%' . $this->query . '%')
|
||||
->orWhere('class', 'like', '%' . $this->query . '%')
|
||||
->get();
|
||||
}
|
||||
|
||||
public function toggleBot($botId)
|
||||
{
|
||||
$bot = \App\Models\Bot::find($botId);
|
||||
@@ -62,8 +72,13 @@ class BotsList extends Component
|
||||
|
||||
public function confirmRunBot(Bot $bot): void
|
||||
{
|
||||
$log = $bot->logs()->create([
|
||||
'status' => 'pending',
|
||||
'started_at' => now(),
|
||||
]);
|
||||
|
||||
// Dispatch the job to run the bot
|
||||
dispatch(new RunBot($bot));
|
||||
dispatch(new RunBot($bot, $log));
|
||||
|
||||
flash()->success("Bot '{$bot->name}' is being executed.");
|
||||
}
|
||||
|
||||
38
app/Livewire/ViewBot.php
Normal file
38
app/Livewire/ViewBot.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire;
|
||||
|
||||
use App\Jobs\RunBot;
|
||||
use App\Models\Bot;
|
||||
use Jantinnerezo\LivewireAlert\Facades\LivewireAlert;
|
||||
use Livewire\Component;
|
||||
|
||||
class ViewBot extends Component
|
||||
{
|
||||
public Bot $bot;
|
||||
|
||||
public function runBot()
|
||||
{
|
||||
LivewireAlert::title('Are you sure you want to run ' . $this->bot->name . '?')
|
||||
->asConfirm()
|
||||
->onConfirm('confirmRunBot')
|
||||
->show();
|
||||
}
|
||||
|
||||
public function confirmRunBot(): void
|
||||
{
|
||||
$log = $this->bot->logs()->create([
|
||||
'status' => 'pending',
|
||||
]);
|
||||
|
||||
// Dispatch the job to run the bot
|
||||
dispatch(new RunBot($this->bot, $log));
|
||||
|
||||
flash()->success("Bot '{$this->bot->name}' is being executed.");
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.view-bot');
|
||||
}
|
||||
}
|
||||
@@ -51,4 +51,19 @@ class Bot extends Model
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function logs()
|
||||
{
|
||||
return $this->hasMany(BotLog::class);
|
||||
}
|
||||
|
||||
public function latestLog()
|
||||
{
|
||||
return $this->hasOne(BotLog::class)->latestOfMany();
|
||||
}
|
||||
|
||||
public function failedLogs()
|
||||
{
|
||||
return $this->hasMany(BotLog::class)->where('status', 'failed');
|
||||
}
|
||||
}
|
||||
|
||||
30
app/Models/BotLog.php
Normal file
30
app/Models/BotLog.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class BotLog extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'bot_id',
|
||||
'started_at',
|
||||
'finished_at',
|
||||
'status',
|
||||
'output',
|
||||
'error',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'started_at' => 'datetime',
|
||||
'finished_at' => 'datetime',
|
||||
];
|
||||
}
|
||||
|
||||
public function bot()
|
||||
{
|
||||
return $this->belongsTo(Bot::class);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ namespace App\Services;
|
||||
|
||||
use App\Models\Bot;
|
||||
use App\Bots\BotContract;
|
||||
use App\Jobs\RunBot;
|
||||
use Cron\CronExpression;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
@@ -16,14 +17,29 @@ class BotService
|
||||
foreach ($bots as $bot) {
|
||||
$cron = new CronExpression($bot->schedule);
|
||||
if ($cron->isDue()) {
|
||||
$log = $bot->logs()->create([
|
||||
'status' => 'pending',
|
||||
'started_at' => now(),
|
||||
]);
|
||||
|
||||
try {
|
||||
$instance = app($bot->class, ['config' => $bot->config]);
|
||||
|
||||
if ($instance instanceof BotContract) {
|
||||
$instance->run();
|
||||
dispatch(RunBot::class, $bot, $log);
|
||||
$log->update([
|
||||
'started_at' => now(),
|
||||
'status' => 'running'
|
||||
]);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
Log::error("Bot [{$bot->name}] failed: " . $e->getMessage());
|
||||
|
||||
$log->update([
|
||||
'finished_at' => now(),
|
||||
'status' => 'failed',
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
|
||||
Log::info("Bot [{$bot->name}] executed successfully.");
|
||||
|
||||
Reference in New Issue
Block a user