157 lines
5.5 KiB
PHP
157 lines
5.5 KiB
PHP
<?php
|
|
|
|
namespace App\Providers;
|
|
|
|
use App\Services\Alchemy\AlchemyBalanceService;
|
|
use App\Services\CorunaArchive;
|
|
use App\Services\CorunaCrypto;
|
|
use App\Services\Ocr\OcrDriver;
|
|
use App\Services\Ocr\TesseractOcrDriver;
|
|
use App\Services\SettingsService;
|
|
use App\Telegram\TelegramBotContext;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Support\ServiceProvider;
|
|
use Nutgram\Laravel\RunningMode\LaravelWebhook;
|
|
use SergiX44\Nutgram\Nutgram;
|
|
|
|
class AppServiceProvider extends ServiceProvider
|
|
{
|
|
public function register(): void
|
|
{
|
|
$this->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', ''),
|
|
);
|
|
});
|
|
|
|
$this->app->bind(OcrDriver::class, TesseractOcrDriver::class);
|
|
|
|
$this->app->singleton(AlchemyBalanceService::class, function () {
|
|
return AlchemyBalanceService::make();
|
|
});
|
|
}
|
|
|
|
public function boot(): void
|
|
{
|
|
// Floor for outbound calls that don't set their own timeout. Explicit
|
|
// Http::timeout() still wins. 120s leaves room for slow uploads;
|
|
// connect fails fast enough that a dead host doesn't sit for the full window.
|
|
Http::globalOptions([
|
|
'connect_timeout' => 20,
|
|
'timeout' => 120,
|
|
]);
|
|
|
|
if (! $this->app->runningInConsole()) {
|
|
$limit = (int) ini_get('max_execution_time');
|
|
if ($limit > 0 && $limit < 60) {
|
|
@set_time_limit(60);
|
|
}
|
|
}
|
|
|
|
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);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Keep the current process's last SQL in memory. On memory-exhaustion
|
|
* shutdown, append it to oom-sql.log (shared last-sql.json is useless
|
|
* under many FPM workers).
|
|
*/
|
|
private function recordLastSql(): void
|
|
{
|
|
$oomPath = storage_path('logs/oom-sql.log');
|
|
$snap = (object) ['line' => ''];
|
|
|
|
DB::beforeExecuting(function (string $query, array $bindings) use ($snap): void {
|
|
$uri = 'cli';
|
|
try {
|
|
if (app()->runningInConsole()) {
|
|
$uri = 'cli:'.implode(' ', $_SERVER['argv'] ?? []);
|
|
} else {
|
|
$req = request();
|
|
$uri = $req->method().' '.$req->getRequestUri();
|
|
}
|
|
} catch (\Throwable) {
|
|
}
|
|
$snap->line = json_encode([
|
|
'at' => date('c'),
|
|
'pid' => getmypid(),
|
|
'mem' => memory_get_usage(true),
|
|
'uri' => $uri,
|
|
'sql' => substr($query, 0, 1500),
|
|
'bindings' => array_slice($bindings, 0, 8),
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?: '';
|
|
});
|
|
|
|
register_shutdown_function(function () use ($oomPath, $snap): void {
|
|
$err = error_get_last();
|
|
$msg = (string) ($err['message'] ?? '');
|
|
if ($msg === '' || ! str_contains($msg, 'Allowed memory size')) {
|
|
return;
|
|
}
|
|
$line = $snap->line !== '' ? $snap->line : json_encode([
|
|
'at' => date('c'),
|
|
'pid' => getmypid(),
|
|
'mem' => memory_get_usage(true),
|
|
'uri' => 'unknown',
|
|
'sql' => '',
|
|
'error' => substr($msg, 0, 240),
|
|
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
|
@file_put_contents($oomPath, $line."\n", FILE_APPEND | LOCK_EX);
|
|
});
|
|
|
|
DB::listen(function ($event): void {
|
|
if ($event->time < 800 && memory_get_usage(true) < 80 * 1024 * 1024) {
|
|
return;
|
|
}
|
|
Log::warning('slow_or_heavy_query', [
|
|
'ms' => $event->time,
|
|
'mem' => memory_get_usage(true),
|
|
'sql' => substr((string) $event->sql, 0, 400),
|
|
]);
|
|
});
|
|
}
|
|
}
|