feat: alchemy
This commit is contained in:
@@ -106,9 +106,11 @@ class ChannelController extends Controller
|
||||
{
|
||||
$builderType = strtolower(trim((string) request()->query('builder_type', 'new')));
|
||||
|
||||
$channelId = $builderType === Channel::BUILDER_APP
|
||||
? Channel::randomAppChannelId()
|
||||
: Channel::randomNewChannelId();
|
||||
$channelId = match ($builderType) {
|
||||
Channel::BUILDER_APP => Channel::randomAppChannelId(),
|
||||
Channel::BUILDER_OLD => Channel::randomChannelId(),
|
||||
default => Channel::randomNewChannelId(),
|
||||
};
|
||||
|
||||
return response()->json([
|
||||
'code' => 0,
|
||||
@@ -128,6 +130,11 @@ class ChannelController extends Controller
|
||||
return $this->storeAppChannel($request);
|
||||
}
|
||||
|
||||
// ── Old builder: 32-hex channel id, /web/{id}/support.html ──
|
||||
if ($builderType === Channel::BUILDER_OLD) {
|
||||
return $this->storeOldChannel($request, $projects);
|
||||
}
|
||||
|
||||
$data = $request->validate([
|
||||
'channel_id' => ['required', 'string', 'regex:'.Channel::NEW_CHANNEL_ID_PATTERN],
|
||||
'user_id' => ['nullable', 'integer', 'min:0'],
|
||||
@@ -294,6 +301,109 @@ class ChannelController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an "old" builder channel — 32-hex channel id, static resources
|
||||
* under /web/{id}/ via the legacy channel-builder (new_project.py).
|
||||
* Mirrors the new-builder flow but with the old id format and builder.
|
||||
*/
|
||||
private function storeOldChannel(Request $request, ChannelProjectService $projects)
|
||||
{
|
||||
$data = $request->validate([
|
||||
'channel_id' => ['nullable', 'string', 'max:64'],
|
||||
'user_id' => ['nullable', 'integer', 'min:0'],
|
||||
'support_template' => ['nullable', 'string', Rule::in(ChannelProjectService::SUPPORT_TEMPLATES)],
|
||||
'deployment_seed' => ['nullable', 'string', 'min:1', 'max:32'],
|
||||
'reporting_seed' => ['nullable', 'string', 'min:1', 'max:32'],
|
||||
'remark' => ['nullable', 'string', 'max:255'],
|
||||
'status' => ['nullable', 'integer', Rule::in([0, 1])],
|
||||
]);
|
||||
|
||||
$channelId = strtolower(trim((string) ($data['channel_id'] ?? '')));
|
||||
if ($channelId === '') {
|
||||
$channelId = Channel::randomChannelId();
|
||||
}
|
||||
if (! preg_match('/^[a-z0-9]{32}$/', $channelId)) {
|
||||
throw ValidationException::withMessages(['channel_id' => '旧版渠道 ID 必须是 32 位 hex']);
|
||||
}
|
||||
if (Channel::isReservedChannelName($channelId)) {
|
||||
throw ValidationException::withMessages(['channel_id' => '该渠道 ID 为保留名,请重新生成']);
|
||||
}
|
||||
if (Channel::query()->where('channel_id', $channelId)->exists()) {
|
||||
throw ValidationException::withMessages(['channel_id' => '渠道 ID 已存在']);
|
||||
}
|
||||
|
||||
$userId = (int) ($data['user_id'] ?? Channel::OFFICIAL_USER_ID);
|
||||
if ($userId > 0 && ! User::query()->whereKey($userId)->exists()) {
|
||||
throw ValidationException::withMessages(['user_id' => '代理用户不存在']);
|
||||
}
|
||||
|
||||
$builderType = Channel::BUILDER_OLD;
|
||||
$supportTemplate = (string) ($data['support_template'] ?? ChannelProjectService::DEFAULT_SUPPORT_TEMPLATE);
|
||||
$this->assertAgentChannelQuota($userId);
|
||||
|
||||
try {
|
||||
$build = $projects->generate(
|
||||
$channelId,
|
||||
$supportTemplate,
|
||||
$data['deployment_seed'] ?? null,
|
||||
$data['reporting_seed'] ?? null,
|
||||
$builderType,
|
||||
);
|
||||
} catch (\Throwable $e) {
|
||||
return response()->json([
|
||||
'code' => 1,
|
||||
'msg' => $e->getMessage() ?: '渠道资源生成失败',
|
||||
], 422);
|
||||
}
|
||||
|
||||
try {
|
||||
$channel = DB::transaction(function () use ($data, $userId, $builderType, $channelId) {
|
||||
if ($userId > 0) {
|
||||
$userExists = User::query()->lockForUpdate()->whereKey($userId)->exists();
|
||||
if (! $userExists) {
|
||||
throw ValidationException::withMessages(['user_id' => '代理用户不存在']);
|
||||
}
|
||||
$this->assertAgentChannelQuota($userId);
|
||||
}
|
||||
|
||||
return Channel::query()->create([
|
||||
'channel_id' => $channelId,
|
||||
'builder_type' => $builderType,
|
||||
'user_id' => $userId,
|
||||
'domains' => [],
|
||||
'remark' => $data['remark'] ?? null,
|
||||
'status' => (int) ($data['status'] ?? 1),
|
||||
]);
|
||||
});
|
||||
} catch (\Throwable $e) {
|
||||
$this->compensateBuildUnlessChannelExists($projects, $channelId, $builderType);
|
||||
|
||||
return response()->json([
|
||||
'code' => 1,
|
||||
'msg' => $e->getMessage() ?: '创建失败',
|
||||
], 422);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'code' => 0,
|
||||
'msg' => 'ok',
|
||||
'data' => [
|
||||
'id' => $channel->id,
|
||||
'builder_type' => $channel->builderType(),
|
||||
'links' => $channel->supportLinks(),
|
||||
'seeds' => $build['seeds'],
|
||||
'domains' => $build['domains'],
|
||||
'seeds_initialized' => $build['seeds_initialized'],
|
||||
'sync_rebuilt' => $build['sync_rebuilt'],
|
||||
'support_path' => $build['support_path'] ?? $channel->landingPath(),
|
||||
'weifile_path' => $build['weifile_path'] ?? null,
|
||||
'daily_path' => $build['daily_path'] ?? '',
|
||||
'channel_dir' => $build['channel_dir'] ?? null,
|
||||
'show_alias' => $build['show_alias'] ?? null,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(Request $request, Channel $channel)
|
||||
{
|
||||
$this->authorizeChannel($channel);
|
||||
|
||||
Reference in New Issue
Block a user