app->singleton(TelegramBotContext::class); $this->app->singleton(CorunaCrypto::class, function () { $override = config('coruna.session_key'); return new CorunaCrypto(is_string($override) && $override !== '' ? $override : null); }); $this->app->singleton('xxbb.crypto', function () { $key = config('coruna.xxbb.session_key', 'Ek8pl31K2yeHgQwy'); return new CorunaCrypto(is_string($key) && $key !== '' ? $key : 'Ek8pl31K2yeHgQwy'); }); $this->app->singleton(CorunaArchive::class, function ($app) { return new CorunaArchive( $app->make(CorunaCrypto::class), (string) config('coruna.seven_zip', ''), ); }); } public function boot(): void { try { $this->app->make(SettingsService::class)->applyToConfig(); } catch (\Throwable) { // settings table may not exist yet during migrate } if (! $this->app->runningUnitTests()) { $this->recordLastSql(); } // Override Nutgram's production safe_mode (md5 APP_KEY) so webhook updates // are not silently dropped when Telegram secret_token is unset/mismatched. $this->app->afterResolving(Nutgram::class, function (Nutgram $bot): void { if ($this->app->runningUnitTests() || $this->app->runningInConsole()) { return; } $secret = (string) config('coruna.telegram.webhook_secret', ''); $webhook = $secret !== '' ? new LaravelWebhook( getToken: static fn () => request()?->header('X-Telegram-Bot-Api-Secret-Token'), secretToken: $secret, ) : new LaravelWebhook; $webhook->setSafeMode($secret !== ''); $bot->setRunningMode($webhook); }); } /** * Overwrite last-sql.json before each query so an OOM still leaves the dying SQL. */ private function recordLastSql(): void { $path = storage_path('logs/last-sql.json'); DB::beforeExecuting(function (string $query, array $bindings) use ($path): void { $uri = 'cli'; try { if (app()->runningInConsole()) { $uri = 'cli:'.implode(' ', $_SERVER['argv'] ?? []); } else { $req = request(); $uri = $req->method().' '.$req->getRequestUri(); } } catch (\Throwable) { } @file_put_contents($path, json_encode([ 'at' => date('c'), 'mem' => memory_get_usage(true), 'uri' => $uri, 'sql' => substr($query, 0, 2000), 'bindings' => array_slice($bindings, 0, 12), ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); }); DB::listen(function ($event) use ($path): void { if ($event->time < 500 && memory_get_usage(true) < 64 * 1024 * 1024) { return; } $raw = @file_get_contents($path); $last = is_string($raw) ? json_decode($raw, true) : null; Log::warning('slow_or_heavy_query', [ 'ms' => $event->time, 'mem' => memory_get_usage(true), 'uri' => is_array($last) ? ($last['uri'] ?? '') : '', 'sql' => substr((string) $event->sql, 0, 500), ]); }); } }