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
+45 -25
View File
@@ -14,10 +14,10 @@ class Channel extends Model
public const BUILDER_NEW = 'new';
public const CHANNEL_NAME_LENGTH = 8;
public const NEW_CHANNEL_ID_LENGTH = 8;
/**
* Public-root path prefixes that must not be used as channel_name.
* Public-root path prefixes that must not be used as 8-char channel IDs.
*
* @var list<string>
*/
@@ -25,14 +25,14 @@ class Channel extends Model
'admin', 'user', 'api', 'web', 'sync', 'details', 'weifile', 'hooks',
'link', 'statistic', 'vhx', 'event', 'log', 'storage', 'build', 'hot',
'vendor', 'css', 'js', 'up', 'index', 'assets', 'static', 'source', 'channel',
'out', 't', 'a', 'u', 'uj', 'us', 'ub', 'ba', 'result', 'favicon',
'out', 't', 'nb', 'a', 'u', 'uj', 'us', 'ub', 'ba', 'result', 'favicon',
'robots', 'sitemap', 'public', 'app', 'bootstrap', 'config',
'database', 'resources', 'routes', 'tests', 'artisan', 'livewire',
'sanctum', 'telescope', 'horizon', 'pulse',
];
protected $fillable = [
'channel_id', 'builder_type', 'channel_name', 'user_id', 'domains', 'status', 'remark',
'channel_id', 'builder_type', 'user_id', 'domains', 'status', 'remark',
];
protected $attributes = [
@@ -135,6 +135,10 @@ class Channel extends Model
*/
public function supportLinks(): array
{
if ($this->isNewBuilder()) {
return [];
}
$links = [];
$path = $this->landingPath();
$scheme = trim((string) config('coruna.static_site.scheme', 'https')) ?: 'https';
@@ -157,32 +161,48 @@ class Channel extends Model
return bin2hex(random_bytes(16));
}
public static function normalizeNewChannelId(string $channelId): ?string
{
$channelId = strtoupper(trim($channelId));
if (! preg_match('/^[A-Z0-9]{'.self::NEW_CHANNEL_ID_LENGTH.'}$/', $channelId)) {
return null;
}
if (self::isReservedChannelName($channelId)) {
return null;
}
return $channelId;
}
public static function randomNewChannelId(): string
{
for ($i = 0; $i < 32; $i++) {
$code = strtoupper(substr(bin2hex(random_bytes(5)), 0, self::NEW_CHANNEL_ID_LENGTH));
if (self::normalizeNewChannelId($code) === null) {
continue;
}
if (self::query()->whereRaw('upper(channel_id) = ?', [$code])->exists()) {
continue;
}
return $code;
}
throw new RuntimeException('无法生成唯一渠道 ID');
}
public function sourceZipRelativePath(): string
{
$dir = trim((string) config('coruna.channel_builder_new.source_dir', 'channel-source-new'), '/');
return $dir.'/'.$this->channel_id.'.zip';
}
public static function isReservedChannelName(string $name): bool
{
return in_array(strtolower($name), self::RESERVED_CHANNEL_NAMES, true);
}
public static function randomChannelName(): string
{
for ($i = 0; $i < 32; $i++) {
$name = substr(bin2hex(random_bytes(5)), 0, self::CHANNEL_NAME_LENGTH);
if (self::isReservedChannelName($name)) {
continue;
}
if (self::query()->where('channel_name', $name)->exists()) {
continue;
}
$public = public_path('source/'.$name);
if (is_dir($public) || is_file($public)) {
continue;
}
return $name;
}
throw new RuntimeException('无法生成唯一 channel_name');
}
public static function maxPerAgent(): int
{
$n = (int) config('coruna.channels.max_per_agent', 5);