comment(Inspiring::quote()); })->purpose('Display an inspiring quote'); Artisan::command('dewemoji:import-live-sql {path : Absolute path to dewemojiAPI_DB.sql} {--truncate : Truncate target tables first} {--batch=500 : Insert batch size}', function () { $path = (string) $this->argument('path'); $truncate = (bool) $this->option('truncate'); $batch = (int) $this->option('batch'); $importer = app(LiveSqlImportService::class); $importer->import($path, $truncate, $batch, $this->output); })->purpose('Import live SQL dump into the current database'); Artisan::command('dewemoji:webhooks:process {--limit=100 : Max events to process} {--status=pending,received : Comma-separated statuses}', function () { $limit = (int) $this->option('limit'); $statuses = array_filter(array_map('trim', explode(',', (string) $this->option('status')))); if (empty($statuses)) { $this->error('No statuses provided.'); return 1; } $processor = app(PaypalWebhookProcessor::class); $events = WebhookEvent::query() ->whereIn('status', $statuses) ->orderBy('id') ->limit($limit) ->get(); $processed = 0; $failed = 0; foreach ($events as $event) { try { if ($event->provider === 'paypal') { $processor->process((string) ($event->event_type ?? ''), $event->payload ?? []); } $event->update([ 'status' => 'processed', 'processed_at' => now(), 'error' => null, ]); $processed++; } catch (\Throwable $e) { $event->update([ 'status' => 'error', 'processed_at' => now(), 'error' => $e->getMessage(), ]); $failed++; } } $this->info("Processed {$processed} events, failed {$failed}."); return 0; })->purpose('Process pending webhook events'); Schedule::command('dewemoji:webhooks:process --limit=200')->everyMinute()->withoutOverlapping(); Artisan::command('paypal:sync-plans {--mode=both : sandbox|live|both}', function () { $mode = (string) $this->option('mode'); $service = app(PayPalPlanSyncService::class); $runMode = match ($mode) { 'sandbox' => ['sandbox'], 'live' => ['live'], default => ['sandbox', 'live'], }; foreach ($runMode as $env) { $this->info("Syncing PayPal plans: {$env}"); $result = $service->sync($env); $this->line("Created: {$result['created']} · Updated: {$result['updated']} · Deactivated: {$result['deactivated']} · Skipped: {$result['skipped']}"); } })->purpose('Create/rotate PayPal plans based on pricing plans'); Artisan::command('mailketing:test {email : Recipient email address}', function () { $email = (string) $this->argument('email'); try { Mail::to($email)->send(new TestMailketing()); $this->info("Mailketing test email sent to {$email}."); return 0; } catch (\Throwable $e) { $this->error('Mailketing test failed: '.$e->getMessage()); return 1; } })->purpose('Send a Mailketing API test email');