diff --git a/app/Filament/Resources/Torrent/AnnounceLogResource.php b/app/Filament/Resources/Torrent/AnnounceLogResource.php index 4ed49ef7..d1f55352 100644 --- a/app/Filament/Resources/Torrent/AnnounceLogResource.php +++ b/app/Filament/Resources/Torrent/AnnounceLogResource.php @@ -5,6 +5,7 @@ namespace App\Filament\Resources\Torrent; use App\Filament\Resources\Torrent\AnnounceLogResource\Pages; use App\Filament\Resources\Torrent\AnnounceLogResource\RelationManagers; use App\Models\AnnounceLog; +use App\Models\Torrent; use Filament\Forms; use Filament\Forms\Form; use Filament\Resources\Resource; @@ -14,6 +15,9 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\SoftDeletingScope; use Filament\Infolists; use Filament\Infolists\Infolist; +use Filament\Infolists\Components\Tabs; +use Filament\Infolists\Components\Fieldset; + class AnnounceLogResource extends Resource { @@ -39,50 +43,79 @@ class AnnounceLogResource extends Resource { return $infolist ->schema([ - Infolists\Components\TextEntry::make('timestamp')->label(__('announce-log.timestamp')), - Infolists\Components\TextEntry::make('request_id')->label(__('announce-log.request_id'))->copyable(), - Infolists\Components\TextEntry::make('user_id')->label(__('announce-log.user_id'))->copyable(), + Tabs::make('Tabs') + ->tabs([ + Tabs\Tab::make(__('announce-log.tab_primary')) + ->schema([ + Fieldset::make(__('announce-log.fieldset_basic')) + ->schema([ + Infolists\Components\TextEntry::make('timestamp')->label(__('announce-log.timestamp')), + Infolists\Components\TextEntry::make('user_id')->label(__('announce-log.user_id'))->copyable(), + Infolists\Components\TextEntry::make('torrent_id')->label(__('announce-log.torrent_id'))->copyable(), + Infolists\Components\TextEntry::make('torrent_size')->label(__('announce-log.torrent_size'))->formatStateUsing(fn($state) => mksize($state)), + Infolists\Components\TextEntry::make('seeder_count')->label(__('announce-log.seeder_count')), + Infolists\Components\TextEntry::make('leecher_count')->label(__('announce-log.leecher_count')), + Infolists\Components\TextEntry::make('promotion_state')->label(__('announce-log.promotion_state'))->formatStateUsing(fn($state) => Torrent::$promotionTypes[$state]['text'] ?? ''), + Infolists\Components\TextEntry::make('promotion_state_desc')->label(__('announce-log.promotion_state_desc')), + Infolists\Components\TextEntry::make('event')->label(__('announce-log.event')), + Infolists\Components\TextEntry::make('left')->label(__('announce-log.left'))->formatStateUsing(fn($state) => mksize($state)), + Infolists\Components\TextEntry::make('announce_time')->label(__('announce-log.announce_time')), + Infolists\Components\TextEntry::make('speed')->label(__('announce-log.speed'))->formatStateUsing(fn($state) => mksize($state) . "/s"), + ])->columns(4), + Fieldset::make(__('announce-log.fieldset_uploaded')) + ->schema([ + Infolists\Components\TextEntry::make('uploaded_offset')->label(__('announce-log.uploaded_offset'))->formatStateUsing(fn($state) => mksize($state)), + Infolists\Components\TextEntry::make('uploaded_total_last')->label(__('announce-log.uploaded_total_last'))->formatStateUsing(fn($state) => mksize($state)), + Infolists\Components\TextEntry::make('uploaded_total')->label(__('announce-log.uploaded_total'))->formatStateUsing(fn($state) => mksize($state)), + Infolists\Components\TextEntry::make('uploaded_increment')->label(__('announce-log.uploaded_increment'))->formatStateUsing(fn($state) => mksize($state)), + Infolists\Components\TextEntry::make('up_factor')->label(__('announce-log.up_factor')), + Infolists\Components\TextEntry::make('up_factor_desc')->label(__('announce-log.up_factor_desc')), + Infolists\Components\TextEntry::make('uploaded_increment_for_user')->label(__('announce-log.uploaded_increment_for_user'))->formatStateUsing(fn($state) => mksize($state)), + ])->columns(4), - Infolists\Components\TextEntry::make('torrent_id')->label(__('announce-log.torrent_id'))->copyable(), - Infolists\Components\TextEntry::make('torrent_size')->label(__('announce-log.torrent_size'))->formatStateUsing(fn($state) => mksize($state)), - Infolists\Components\TextEntry::make('peer_id')->label(__('announce-log.peer_id'))->copyable(), + Fieldset::make(__('announce-log.fieldset_downloaded')) + ->schema([ + Infolists\Components\TextEntry::make('downloaded_offset')->label(__('announce-log.downloaded_offset'))->formatStateUsing(fn($state) => mksize($state)), + Infolists\Components\TextEntry::make('downloaded_total_last')->label(__('announce-log.downloaded_total_last'))->formatStateUsing(fn($state) => mksize($state)), + Infolists\Components\TextEntry::make('downloaded_total')->label(__('announce-log.downloaded_total'))->formatStateUsing(fn($state) => mksize($state)), + Infolists\Components\TextEntry::make('downloaded_increment')->label(__('announce-log.downloaded_increment'))->formatStateUsing(fn($state) => mksize($state)), + Infolists\Components\TextEntry::make('down_factor')->label(__('announce-log.down_factor')), + Infolists\Components\TextEntry::make('down_factor_desc')->label(__('announce-log.down_factor_desc')), + Infolists\Components\TextEntry::make('downloaded_increment_for_user')->label(__('announce-log.downloaded_increment_for_user'))->formatStateUsing(fn($state) => mksize($state)), + ])->columns(4), + ]), + Tabs\Tab::make(__('announce-log.tab_secondary')) + ->schema([ + Fieldset::make(__('announce-log.fieldset_client')) + ->schema([ + Infolists\Components\TextEntry::make('port')->label(__('announce-log.port')), + Infolists\Components\TextEntry::make('agent')->label(__('announce-log.agent')), + Infolists\Components\TextEntry::make('peer_id')->label(__('announce-log.peer_id'))->copyable(), + Infolists\Components\TextEntry::make('client_select')->label(__('announce-log.client_select')), + ])->columns(4), + Fieldset::make(__('announce-log.fieldset_location')) + ->schema([ + Infolists\Components\TextEntry::make('ip')->label(__('announce-log.ip'))->copyable()->limit(25), + Infolists\Components\TextEntry::make('ipv4')->label(__('announce-log.ipv4'))->copyable(), + Infolists\Components\TextEntry::make('ipv6')->label(__('announce-log.ipv6'))->copyable()->limit(25), + Infolists\Components\TextEntry::make('continent')->label(__('announce-log.continent')), + Infolists\Components\TextEntry::make('country')->label(__('announce-log.country')), + Infolists\Components\TextEntry::make('city')->label(__('announce-log.city')), - Infolists\Components\TextEntry::make('announce_time')->label(__('announce-log.announce_time'))->copyable(), - Infolists\Components\TextEntry::make('seeder_count')->label(__('announce-log.seeder_count')), - Infolists\Components\TextEntry::make('leecher_count')->label(__('announce-log.leecher_count')), + ])->columns(4), + Fieldset::make(__('announce-log.fieldset_request')) + ->schema([ + Infolists\Components\TextEntry::make('scheme')->label(__('announce-log.scheme')), + Infolists\Components\TextEntry::make('host')->label(__('announce-log.host')), + Infolists\Components\TextEntry::make('path')->label(__('announce-log.path')), + Infolists\Components\TextEntry::make('request_id')->label(__('announce-log.request_id'))->copyable()->limit(25), + Infolists\Components\TextEntry::make('batch_no')->label(__('announce-log.batch_no'))->copyable(), - Infolists\Components\TextEntry::make('uploaded_offset')->label(__('announce-log.uploaded_offset'))->formatStateUsing(fn($state) => mksize($state)), - Infolists\Components\TextEntry::make('uploaded_total')->label(__('announce-log.uploaded_total'))->formatStateUsing(fn($state) => mksize($state)), - Infolists\Components\TextEntry::make('uploaded_increment')->label(__('announce-log.uploaded_increment'))->formatStateUsing(fn($state) => mksize($state)), - - Infolists\Components\TextEntry::make('downloaded_offset')->label(__('announce-log.downloaded_offset'))->formatStateUsing(fn($state) => mksize($state)), - Infolists\Components\TextEntry::make('downloaded_total')->label(__('announce-log.downloaded_total'))->formatStateUsing(fn($state) => mksize($state)), - Infolists\Components\TextEntry::make('downloaded_increment')->label(__('announce-log.downloaded_increment'))->formatStateUsing(fn($state) => mksize($state)), - - Infolists\Components\TextEntry::make('left')->label(__('announce-log.left'))->formatStateUsing(fn($state) => mksize($state)), - Infolists\Components\TextEntry::make('port')->label(__('announce-log.port')), - Infolists\Components\TextEntry::make('agent')->label(__('announce-log.agent')), - - Infolists\Components\TextEntry::make('started')->label(__('announce-log.started')), - Infolists\Components\TextEntry::make('last_action')->label(__('announce-log.last_action')), - Infolists\Components\TextEntry::make('prev_action')->label(__('announce-log.prev_action')), - - - Infolists\Components\TextEntry::make('scheme')->label(__('announce-log.scheme')), - Infolists\Components\TextEntry::make('host')->label(__('announce-log.host')), - Infolists\Components\TextEntry::make('path')->label(__('announce-log.path')), - Infolists\Components\TextEntry::make('ip')->label(__('announce-log.ip'))->copyable(), - Infolists\Components\TextEntry::make('ipv4')->label(__('announce-log.ipv4'))->copyable(), - Infolists\Components\TextEntry::make('ipv6')->label(__('announce-log.ipv6'))->copyable(), - Infolists\Components\TextEntry::make('continent')->label(__('announce-log.continent')), - Infolists\Components\TextEntry::make('country')->label(__('announce-log.country')), - Infolists\Components\TextEntry::make('city')->label(__('announce-log.city')), - - Infolists\Components\TextEntry::make('event')->label(__('announce-log.event')), - Infolists\Components\TextEntry::make('passkey')->label(__('announce-log.passkey'))->copyable(), - Infolists\Components\TextEntry::make('client_select')->label(__('announce-log.client_select')), - ])->columns(3); + ])->columns(4), + ]), + ])->columnSpanFull() + ]); } public static function table(Table $table): Table @@ -171,7 +204,7 @@ class AnnounceLogResource extends Resource , ]) ->actions([ - Tables\Actions\ViewAction::make(), + Tables\Actions\ViewAction::make()->modalWidth('5xl'), ]) ->bulkActions([ // Tables\Actions\BulkActionGroup::make([ diff --git a/app/Filament/Resources/Torrent/AnnounceLogResource/Pages/ListAnnounceLogs.php b/app/Filament/Resources/Torrent/AnnounceLogResource/Pages/ListAnnounceLogs.php index 046a5acb..f37f4619 100644 --- a/app/Filament/Resources/Torrent/AnnounceLogResource/Pages/ListAnnounceLogs.php +++ b/app/Filament/Resources/Torrent/AnnounceLogResource/Pages/ListAnnounceLogs.php @@ -21,18 +21,24 @@ class ListAnnounceLogs extends PageListSingle public function getTableRecords(): Collection|Paginator|CursorPaginator { - $filterableColumns = ['user_id', 'torrent_id', 'peer_id', 'ip', 'event']; + $filterableColumns = [ + 'user_id' => 'is_numeric', + 'torrent_id'=> 'is_numeric', + 'peer_id' => 'is_string', + 'ip' => 'is_string', + 'event' => 'is_string', + ]; $sortableColumns = ['timestamp', 'uploaded_total', 'uploaded_increment', 'downloaded_total', 'downloaded_increment', 'left', 'announce_time']; $sortableDirections = ['asc', 'desc']; $request = request(); // dd($request->all()); $filters = []; foreach ($request->get('tableFilters', []) as $field => $values) { - if (!in_array($field, $filterableColumns)) { + if (!isset($filterableColumns[$field])) { continue; } foreach ($values as $k => $v) { - if (in_array($k, $filterableColumns)) { + if (isset($filterableColumns[$k])) { $filters[$field] = $v; } } @@ -77,7 +83,7 @@ class ListAnnounceLogs extends PageListSingle // dd($snapshot['data']['tableFilters']); foreach ($snapshot['data']['tableFilters'] as $filterItems) { foreach ($filterItems as $field => $items) { - if (!in_array($field, $filterableColumns) || !is_array($items)) { + if (!isset($filterableColumns[$field]) || !is_array($items)) { continue; } foreach ($items as $values) { @@ -121,12 +127,16 @@ class ListAnnounceLogs extends PageListSingle } } } - foreach ($filterableColumns as $field) { + foreach ($filterableColumns as $field => $filterFunc) { if (isset($component['updates']["tableFilters.$field.$field"])) { $filters[$field] = $component['updates']["tableFilters.$field.$field"]; } } - + } + foreach ($filters as $field => $value) { + if (!isset($filterableColumns[$field]) || !call_user_func($filterableColumns[$field], $value)) { + unset($filters[$field]); + } } $rep = new AnnounceLogRepository(); $result = $rep->listAll($filters, $page, $perPage, $sortColumn, $sortDirection); diff --git a/app/Models/AnnounceLog.php b/app/Models/AnnounceLog.php index ddfc044d..0865483e 100644 --- a/app/Models/AnnounceLog.php +++ b/app/Models/AnnounceLog.php @@ -10,12 +10,14 @@ use Illuminate\Database\Eloquent\Casts\Attribute; class AnnounceLog extends NexusModel { protected $fillable = [ - 'timestamp', 'user_id', 'passkey', 'torrent_id', 'info_hash', 'torrent_size', 'event', 'peer_id', - 'uploaded_total', 'uploaded_increment', 'uploaded_offset', - 'downloaded_total', 'downloaded_increment', 'downloaded_offset', - 'announce_time', 'ip', 'ipv4', 'ipv6', 'port', 'agent', 'left', 'started', 'prev_action', 'last_action', + 'timestamp', 'user_id', 'passkey', 'torrent_id', 'info_hash', 'torrent_size', + 'promotion_state', 'promotion_state_desc', 'up_factor', 'up_factor_desc', 'down_factor', 'down_factor_desc', + 'event', 'peer_id', + 'uploaded_total_last', 'uploaded_total', 'uploaded_increment', 'uploaded_increment_for_user','uploaded_offset', + 'downloaded_total_last', 'downloaded_total', 'downloaded_increment', 'downloaded_increment_for_user', 'downloaded_offset', + 'announce_time', 'speed', 'ip', 'ipv4', 'ipv6', 'port', 'agent', 'left', 'started', 'prev_action', 'last_action', 'client_select', 'seeder_count', 'leecher_count', 'scheme', 'host', 'path', - 'continent', 'country', 'city', 'request_id' + 'continent', 'country', 'city', 'request_id', 'batch_no' ]; protected $table = null; diff --git a/app/Repositories/AnnounceLogRepository.php b/app/Repositories/AnnounceLogRepository.php index 702935e8..868ae7bb 100644 --- a/app/Repositories/AnnounceLogRepository.php +++ b/app/Repositories/AnnounceLogRepository.php @@ -12,6 +12,10 @@ class AnnounceLogRepository extends BaseRepository public function listAll(array $filters, int $page, int $perPage, ?string $sortColumn, ?string $sortDirection) { $beginTimestamp = microtime(true); + do_log(sprintf( + "[REQUEST_CLICKHOUSE] [BEGIN], filters: %s, page: %s, perPage: %s, sortColumn: %s, sortDirection: %s", + json_encode($filters), $page, $perPage, $sortColumn, $sortDirection + )); $totalAlias = "total"; $offset = ($page - 1) * $perPage; $client = $this->getClient(); @@ -37,8 +41,8 @@ class AnnounceLogRepository extends BaseRepository $data = $client->select($selectSql, $bindValues); $total = $client->select($countSql, $bindValues)->rows()[0][$totalAlias] ?? 0; do_log(sprintf( - "[REQUEST_CLICKHOUSE], filters: %s, page: %s, perPage: %s, sortColumn: %s, sortDirection: %s, selectSql: %s, binds: %s, costTime: %.3f sec.", - json_encode($filters), $page, $perPage, $sortColumn, $sortDirection, $selectSql, json_encode($bindValues), microtime(true) - $beginTimestamp + "[REQUEST_CLICKHOUSE] [END], selectSql: %s, binds: %s, costTime: %.3f sec.", + $selectSql, json_encode($bindValues), microtime(true) - $beginTimestamp )); return [ 'data' => $data->rows(), diff --git a/app/Repositories/UploadRepository.php b/app/Repositories/UploadRepository.php index 072a868d..e39c8391 100644 --- a/app/Repositories/UploadRepository.php +++ b/app/Repositories/UploadRepository.php @@ -126,6 +126,7 @@ class UploadRepository extends BaseRepository 'media_info' => $request->technical_info ?? '', 'nfo' => $this->getNfoContent($request), 'created_at' => $nowStr, + 'pt_gen' => $request->pt_gen ?? '', ]; $newTorrent = DB::transaction(function () use ($torrentInsert, $extraInsert, $fileListInfo, $subCategoriesAngTags, $dict, $torrentSavePath) { $newTorrent = Torrent::query()->create($torrentInsert); diff --git a/database/clickhouse-migrations/2025_07_04_052258_add_user_increment_fields.php b/database/clickhouse-migrations/2025_07_04_052258_add_user_increment_fields.php new file mode 100644 index 00000000..ade11e8b --- /dev/null +++ b/database/clickhouse-migrations/2025_07_04_052258_add_user_increment_fields.php @@ -0,0 +1,29 @@ +clickhouseClient->write( + << 'Reporting time', + 'request_id' => 'Request ID', + + 'uploaded_offset' => 'Upload start offset', + 'uploaded_total_last' => 'Last cumulative upload amount', + 'uploaded_total' => 'Cumulative upload amount', + 'uploaded_increment' => 'Upload increment', + 'uploaded_increment_for_user' => 'User Upload Increment', + + 'downloaded_offset' => 'Download Start Volume', + 'downloaded_total_last' => 'Last Cumulative Download Volume', + 'downloaded_total' => 'Cumulative Download Volume', + 'downloaded_increment' => 'Download Increment', + 'downloaded_increment_for_user' => 'User download increment', + + 'left' => 'Remaining amount', + 'seeder' => 'Seeder', + 'leecher' => 'Downloader', + 'announce_time' => 'Time interval', + 'agent' => 'Client', + 'user_id' => 'User ID', + 'passkey' => 'User Passkey', + 'torrent_id' => 'Torrent ID', + 'peer_id' => 'Peer ID', + 'event' => 'Event', + 'ip' => 'IP', + 'ipv4' => 'IPV4', + 'ipv6' => 'IPV6', + 'port' => 'Port', + 'started' => 'Start time', + 'prev_action' => 'Previous report', + 'last_action' => 'Last report', + 'seeder_count' => 'Seeder count', + 'leecher_count' => 'Number of downloaders', + 'scheme' => 'Reporting protocol', + 'host' => 'Reporting host', + 'path' => 'Reporting path', + 'continent' => 'Continent', + 'country' => 'Country', + 'city' => 'City', + 'show_client_error' => 'Show client error', + 'client_select' => 'Client ID', + 'torrent_size' => 'Seed size', + 'events' => [ + 'started' => 'Started', + 'stopped' => 'Stopped', + 'paused' => 'Paused', + 'completed' => 'Completed', + 'none' => 'None', + ], + 'batch_no' => 'Batch number', + 'promotion_state' => 'Promotion status', + 'promotion_state_desc' => 'Promotion source', + 'up_factor' => 'Upload factor', + 'up_factor_desc' => 'Upload factor source', + 'down_factor' => 'Download Multiplier', + 'down_factor_desc' => 'Download Multiplier Source', + 'speed' => 'Speed', + 'tab_primary' => 'Primary Information', + 'tab_secondary' => 'Secondary Information', + 'fieldset_basic' => 'Basic Information', + 'fieldset_uploaded' => 'Uploads', + 'fieldset_downloaded' => 'Downloads', + 'fieldset_client' => 'Client', + 'fieldset_location' => 'Location', + 'fieldset_request' => 'Requests', + +]; diff --git a/resources/lang/zh_CN/announce-log.php b/resources/lang/zh_CN/announce-log.php index 3768edfa..51dc9f8a 100644 --- a/resources/lang/zh_CN/announce-log.php +++ b/resources/lang/zh_CN/announce-log.php @@ -3,12 +3,19 @@ return [ 'timestamp' => '汇报时间', 'request_id' => '请求 ID', + + 'uploaded_offset' => '上传起始量', + 'uploaded_total_last' => '上次累计上传量', 'uploaded_total' => '累计上传量', 'uploaded_increment' => '上传增量', - 'uploaded_offset' => '上传起始量', + 'uploaded_increment_for_user' => '用户上传增量', + + 'downloaded_offset' => '下载起始量', + 'downloaded_total_last' => '上次累计下载量', 'downloaded_total' => '累计下载量', 'downloaded_increment' => '下载增量', - 'downloaded_offset' => '下载起始量', + 'downloaded_increment_for_user' => '用户下载增量', + 'left' => '剩余量', 'seeder' => '做种', 'leecher' => '下载', @@ -44,4 +51,20 @@ return [ 'completed' => '完成', 'none' => '无', ], + 'batch_no' => '汇总批次号', + 'promotion_state' => '促销状态', + 'promotion_state_desc' => '促销来源', + 'up_factor' => '上传倍数', + 'up_factor_desc' => '上传倍数来源', + 'down_factor' => '下载倍数', + 'down_factor_desc' => '下载倍数来源', + 'speed' => '速度', + 'tab_primary' => '主要信息', + 'tab_secondary' => '次要信息', + 'fieldset_basic' => '基本信息', + 'fieldset_uploaded' => '上传', + 'fieldset_downloaded' => '下载', + 'fieldset_client' => '客户端', + 'fieldset_location' => '位置', + 'fieldset_request' => '请求', ]; diff --git a/resources/lang/zh_TW/announce-log.php b/resources/lang/zh_TW/announce-log.php index 3cdd7743..3e2dfec7 100644 --- a/resources/lang/zh_TW/announce-log.php +++ b/resources/lang/zh_TW/announce-log.php @@ -3,12 +3,19 @@ return [ 'timestamp' => '匯報時間', 'request_id' => '請求 ID', + + 'uploaded_offset' => '上傳起始量', + 'uploaded_total_last' => '上次累計上傳量', 'uploaded_total' => '累計上傳量', 'uploaded_increment' => '上傳增量', - 'uploaded_offset' => '上傳起始量', + 'uploaded_increment_for_user' => '用戶上傳增量', + + 'downloaded_offset' => '下載起始量', + 'downloaded_total_last' => '上次累計下載量', 'downloaded_total' => '累計下載量', 'downloaded_increment' => '下載增量', - 'downloaded_offset' => '下載起始量', + 'downloaded_increment_for_user' => '用戶下載增量', + 'left' => '剩餘量', 'seeder' => '做種', 'leecher' => '下載', @@ -44,4 +51,20 @@ return [ 'completed' => '完成', 'none' => '無', ], + 'batch_no' => '匯總批次號', + 'promotion_state' => '促銷狀態', + 'promotion_state_desc' => '促銷來源', + 'up_factor' => '上傳倍數', + 'up_factor_desc' => '上傳倍數來源', + 'down_factor' => '下載倍數', + 'down_factor_desc' => '下載倍數來源', + 'speed' => '速度', + 'tab_primary' => '主要信息', + 'tab_secondary' => '次要信息', + 'fieldset_basic' => '基本信息', + 'fieldset_uploaded' => '上傳', + 'fieldset_downloaded' => '下載', + 'fieldset_client' => '客戶端', + 'fieldset_location' => '位置', + 'fieldset_request' => '請求', ];