admin add torrents

This commit is contained in:
xiaomlove
2022-07-03 14:00:07 +08:00
parent 9cf1cc7277
commit bd11527f4b
26 changed files with 393 additions and 31 deletions
+9 -4
View File
@@ -12,14 +12,14 @@ class NexusUpdate extends Command
*
* @var string
*/
protected $signature = 'nexus:update {--tag=} {--keep_tmp}';
protected $signature = 'nexus:update {--tag=} {--keep_tmp} {--include_composer}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Update nexusphp after code updated, remember run `composer update` first. Options: --tag=, --keep_tmp';
protected $description = 'Update nexusphp after code updated, remember run `composer update` first. Options: --tag=, --keep_tmp, --include_composer';
private $update;
@@ -45,14 +45,19 @@ class NexusUpdate extends Command
require ROOT_PATH . 'nexus/Database/helpers.php';
$tag = $this->option('tag');
$keepTmp = $this->option('keep_tmp');
$includeComposer = $this->option('include_composer');
$includes = [];
if ($includeComposer) {
$includes[] = 'composer';
}
if ($tag !== null) {
if ($tag === 'dev') {
$url = "https://github.com/xiaomlove/nexusphp/archive/refs/heads/php8.zip";
} else {
$url = "https://api.github.com/repos/xiaomlove/nexusphp/tarball/v$tag";
}
$this->doLog("Specific tag: '$tag', download from '$url' and extra code...");
$tmpPath = $this->update->downAndExtractCode($url);
$this->doLog("Specific tag: '$tag', download from '$url' and extra code, includes: " . implode(', ', $includes));
$tmpPath = $this->update->downAndExtractCode($url, $includes);
}
//Step 1
$step = $this->update->currentStep();
+2 -2
View File
@@ -78,8 +78,8 @@ class Test extends Command
*/
public function handle()
{
$r = User::query()->find(10003, ['id', 'added', 'donoruntil']);
dd($r->donoruntil->toDateTimeString() < '1978');
$r = Carbon::parse('2022-07-03 04:00:00')->diffInSeconds();
dd($r);
}
@@ -21,7 +21,7 @@ class TagResource extends Resource
protected static ?string $navigationGroup = 'Torrent';
protected static ?int $navigationSort = 1;
protected static ?int $navigationSort = 2;
protected static function getNavigationLabel(): string
{
@@ -0,0 +1,198 @@
<?php
namespace App\Filament\Resources\Torrent;
use App\Filament\Resources\Torrent\TorrentResource\Pages;
use App\Filament\Resources\Torrent\TorrentResource\RelationManagers;
use App\Models\Tag;
use App\Models\Torrent;
use App\Models\TorrentTag;
use App\Repositories\TagRepository;
use App\Repositories\TorrentRepository;
use Filament\Forms;
use Filament\Resources\Form;
use Filament\Resources\Resource;
use Filament\Resources\Table;
use Filament\Tables;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
class TorrentResource extends Resource
{
protected static ?string $model = Torrent::class;
protected static ?string $navigationIcon = 'heroicon-o-collection';
protected static ?string $navigationGroup = 'Torrent';
protected static ?int $navigationSort = 1;
protected static function getNavigationLabel(): string
{
return __('admin.sidebar.torrent_list');
}
public static function getBreadcrumb(): string
{
return self::getNavigationLabel();
}
public static function form(Form $form): Form
{
return $form
->schema([
//
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('id')->sortable(),
Tables\Columns\BadgeColumn::make('basic_category.name')->label(__('label.torrent.category')),
Tables\Columns\TextColumn::make('name')
->label(__('label.name'))
->limit(30)
->url(fn ($record) => sprintf('/details.php?id=%s', $record->id))
->openUrlInNewTab(true)
,
Tables\Columns\BadgeColumn::make('posStateText')->label(__('label.torrent.pos_state')),
Tables\Columns\BadgeColumn::make('spStateText')->label(__('label.torrent.sp_state')),
Tables\Columns\TextColumn::make('tagsFormatted')->label(__('label.tag.label'))->html(),
Tables\Columns\TextColumn::make('size')->label(__('label.torrent.size'))->formatStateUsing(fn ($state) => mksize($state)),
Tables\Columns\TextColumn::make('seeders')->label(__('label.torrent.seeders')),
Tables\Columns\TextColumn::make('leechers')->label(__('label.torrent.leechers')),
Tables\Columns\BadgeColumn::make('approval_status')
->label(__('label.torrent.approval_status'))
->colors(array_flip(Torrent::listApprovalStatus(true, 'badge_color')))
->formatStateUsing(fn ($record) => $record->approvalStatusText),
Tables\Columns\TextColumn::make('added')->label(__('label.added'))->dateTime(),
Tables\Columns\TextColumn::make('user.username')
->label(__('label.user.label'))
->url(fn ($record) => sprintf('/userdetails.php?id=%s', $record->owner))
->openUrlInNewTab(true)
,
])
->defaultSort('id', 'desc')
->filters([
Tables\Filters\SelectFilter::make('approval_status')
->options(Torrent::listApprovalStatus(true))
->label(__('label.torrent.approval_status')),
Tables\Filters\SelectFilter::make('pos_state')
->options(Torrent::listPosStates(true))
->label(__('label.torrent.pos_state')),
Tables\Filters\SelectFilter::make('sp_state')
->options(Torrent::listPromotionTypes(true))
->label(__('label.torrent.sp_state')),
])
->actions([
// Tables\Actions\EditAction::make(),
Tables\Actions\Action::make('approval')
->label(__('admin.resources.torrent.action_approval'))
->form([
Forms\Components\Radio::make('approval_status')
->label(__('label.torrent.approval_status'))
->inline()
->required()
->options(Torrent::listApprovalStatus(true))
,
Forms\Components\Textarea::make('comment')->label(__('label.comment')),
])
->icon('heroicon-o-check')
->color('success')
->action(function (Torrent $record, array $data) {
$torrentRep = new TorrentRepository();
try {
$data['torrent_id'] = $record->id;
$torrentRep->approval(Auth::user(), $data);
} catch (\Exception $exception) {
do_log($exception->getMessage(), 'error');
}
})
])
->bulkActions([
// Tables\Actions\DeleteBulkAction::make(),
Tables\Actions\BulkAction::make('posState')
->label(__('admin.resources.torrent.bulk_action_pos_state'))
->form([
Forms\Components\Select::make('pos_state')
->label(__('label.torrent.pos_state'))
->options(Torrent::listPosStates(true))
])
->icon('heroicon-o-arrow-circle-up')
->action(function (Collection $records, array $data) {
$idArr = $records->pluck('id')->toArray();
Torrent::query()->whereIn('id', $idArr)->update(['pos_state' => $data['pos_state']]);
})
->deselectRecordsAfterCompletion(),
Tables\Actions\BulkAction::make('remove_tag')
->label(__('admin.resources.torrent.bulk_action_remove_tag'))
->requiresConfirmation()
->icon('heroicon-o-minus-circle')
->action(function (Collection $records) {
$idArr = $records->pluck('id')->toArray();
TorrentTag::query()->whereIn('torrent_id', $idArr)->delete();
})
->deselectRecordsAfterCompletion(),
Tables\Actions\BulkAction::make('attach_tag')
->label(__('admin.resources.torrent.bulk_action_attach_tag'))
->form([
Forms\Components\CheckboxList::make('tags')
->label(__('label.tag.label'))
->columns(4)
->options(TagRepository::createBasicQuery()->pluck('name', 'id')->toArray()),
])
->icon('heroicon-o-tag')
->action(function (Collection $records, array $data) {
if (empty($data['tags'])) {
return;
}
$insert = $torrentIdArr = [];
$time = now()->toDateTimeString();
foreach ($records as $torrent) {
$torrentIdArr[] = $torrent->id;
foreach ($data['tags'] as $tagId) {
$insert[] = [
'torrent_id' => $torrent->id,
'tag_id' => $tagId,
'created_at' => $time,
'updated_at' => $time,
];
}
}
TorrentTag::query()->whereIn('torrent_id', $torrentIdArr)->delete();
TorrentTag::query()->insert($insert);
})
->deselectRecordsAfterCompletion(),
]);
}
public static function getEloquentQuery(): Builder
{
return parent::getEloquentQuery()->with(['user', 'basic_category', 'tags']);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListTorrents::route('/'),
'create' => Pages\CreateTorrent::route('/create'),
'edit' => Pages\EditTorrent::route('/{record}/edit'),
];
}
}
@@ -0,0 +1,12 @@
<?php
namespace App\Filament\Resources\Torrent\TorrentResource\Pages;
use App\Filament\Resources\Torrent\TorrentResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\CreateRecord;
class CreateTorrent extends CreateRecord
{
protected static string $resource = TorrentResource::class;
}
@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\Torrent\TorrentResource\Pages;
use App\Filament\Resources\Torrent\TorrentResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\EditRecord;
class EditTorrent extends EditRecord
{
protected static string $resource = TorrentResource::class;
protected function getActions(): array
{
return [
Actions\DeleteAction::make(),
];
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Filament\Resources\Torrent\TorrentResource\Pages;
use App\Filament\PageList;
use App\Filament\Resources\Torrent\TorrentResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\ListRecords;
class ListTorrents extends PageList
{
protected static string $resource = TorrentResource::class;
protected function getActions(): array
{
return [
// Actions\CreateAction::make(),
];
}
}
@@ -11,6 +11,7 @@ use Filament\Resources\Resource;
use Filament\Resources\Table;
use Filament\Tables;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletingScope;
class ClaimResource extends Resource
@@ -48,8 +49,8 @@ class ClaimResource extends Resource
Tables\Columns\TextColumn::make('id')->sortable(),
Tables\Columns\TextColumn::make('user.username')->label(__('label.user.label'))->searchable(),
Tables\Columns\TextColumn::make('torrent.name')->limit(50)->label(__('label.torrent.label'))->searchable(),
Tables\Columns\TextColumn::make('torrent.size')->label(__('label.torrent.size'))->formatStateUsing(fn ($record) => mksize($record->size)),
Tables\Columns\TextColumn::make('torrent.added')->label(__('label.torrent.ttl'))->formatStateUsing(fn ($record) => mkprettytime($record->added)),
Tables\Columns\TextColumn::make('torrent.size')->label(__('label.torrent.size'))->formatStateUsing(fn (Model $record) => mksize($record->torrent->size)),
Tables\Columns\TextColumn::make('torrent.added')->label(__('label.torrent.ttl'))->formatStateUsing(fn (Model $record) => mkprettytime($record->torrent->added->diffInSeconds())),
Tables\Columns\TextColumn::make('created_at')->label(__('label.created_at'))->dateTime(),
Tables\Columns\TextColumn::make('last_settle_at')->label(__('label.claim.last_settle_at'))->dateTime(),
Tables\Columns\TextColumn::make('seedTimeThisMonth')->label(__('label.claim.seed_time_this_month')),
+53 -4
View File
@@ -138,14 +138,17 @@ class Torrent extends NexusModel
public static array $approvalStatus = [
self::APPROVAL_STATUS_NONE => [
'text' => 'None',
'badge_color' => 'primary',
'icon' => '<svg t="1655184824967" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="34118" width="16" height="16"><path d="M450.267 772.245l0 92.511 92.511 0 0-92.511L450.267 772.245zM689.448 452.28c13.538-24.367 20.311-50.991 20.311-79.875 0-49.938-19.261-92.516-57.765-127.713-38.517-35.197-90.114-52.8-154.797-52.8-61.077 0-110.191 16.4-147.342 49.188-37.16 32.798-59.497 80.032-67.014 141.703l83.486 9.927c7.218-46.025 22.41-79.875 45.576-101.533 23.166-21.665 52.047-32.494 86.647-32.494 35.802 0 66.038 11.957 90.711 35.874 24.667 23.92 37.01 51.675 37.01 83.266 0 17.451-4.222 33.55-12.642 48.284-8.425 14.747-26.698 34.526-54.83 59.346s-47.607 43.701-58.442 56.637c-14.741 17.754-25.424 35.354-32.037 52.797-9.028 23.172-13.537 50.701-13.537 82.584 0 5.418 0.146 13.539 0.45 24.374l78.069 0c0.599-32.495 2.855-55.966 6.772-70.4 3.903-14.44 9.926-27.229 18.047-38.363 8.127-11.123 25.425-28.43 51.901-51.895C649.43 506.288 675.908 476.656 689.448 452.28L689.448 452.28z" p-id="34119" fill="#e78d0f"></path></svg>',
],
self::APPROVAL_STATUS_ALLOW => [
'text' => 'Allow',
'badge_color' => 'success',
'icon' => '<svg t="1655145688503" class="icon" viewBox="0 0 1413 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="16225" width="16" height="16"><path d="M1381.807797 107.47394L1274.675044 0.438669 465.281736 809.880718l-322.665524-322.714266L35.434718 594.152982l430.041982 430.041982 107.084012-107.035271-0.243705-0.292446z" fill="#1afa29" p-id="16226"></path></svg>',
],
self::APPROVAL_STATUS_DENY => [
'text' => 'Deny',
'badge_color' => 'danger',
'icon' => '<svg t="1655184952662" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="35029" width="16" height="16"><path d="M220.8 812.8l22.4 22.4 272-272 272 272 48-44.8-275.2-272 275.2-272-48-48-272 275.2-272-275.2-22.4 25.6-22.4 22.4 272 272-272 272z" fill="#d81e06" p-id="35030"></path></svg>',
],
];
@@ -190,13 +193,27 @@ class Torrent extends NexusModel
return $spState;
}
public function posStateText(): Attribute
protected function posStateText(): Attribute
{
return new Attribute(
get: fn($value, $attributes) => nexus_trans('torrent.pos_state_' . $attributes['pos_state'])
);
}
protected function approvalStatusText(): Attribute
{
return new Attribute(
get: fn($value, $attributes) => nexus_trans('torrent.approval.status_text.' . $attributes['approval_status'])
);
}
protected function spStateText(): Attribute
{
return new Attribute(
get: fn($value, $attributes) => self::$promotionTypes[$this->sp_state]['text'] ?? ''
);
}
public static function getGlobalPromotionState()
{
if (is_null(self::$globalPromotionState)) {
@@ -221,14 +238,29 @@ class Torrent extends NexusModel
return $fields;
}
public static function listApprovalStatus($onlyKeyValue = false): array
public static function listApprovalStatus($onlyKeyValue = false, $valueField = 'text'): array
{
$result = self::$approvalStatus;
$keyValue = [];
foreach ($result as $status => &$info) {
$text = nexus_trans("torrent.approval.status_text.$status");
$info['text'] = $text;
$keyValue[$status] = $text;
$keyValue[$status] = $info[$valueField];
}
if ($onlyKeyValue) {
return $keyValue;
}
return $result;
}
public static function listPromotionTypes($onlyKeyValue = false, $valueField = 'text'): array
{
$result = self::$promotionTypes;
$keyValue = [];
foreach ($result as $status => &$info) {
$text = $info['text'];
$info['text'] = $text;
$keyValue[$status] = $info[$valueField];
}
if ($onlyKeyValue) {
return $keyValue;
@@ -253,6 +285,18 @@ class Torrent extends NexusModel
return self::$hrStatus[$this->hr] ?? '';
}
public function getTagsFormattedAttribute(): string
{
$html = [];
foreach ($this->tags as $tag) {
$html[] = sprintf(
'<span style="color: %s;background-color: %s;border-radius: %s;font-size: %s;padding: %s;margin: %s">%s</span>',
$tag->font_color, $tag->color, $tag->border_radius, $tag->font_size, $tag->padding, $tag->margin, $tag->name
);
}
return implode('', $html);
}
public static function getBasicInfo(): array
{
$result = [];
@@ -262,11 +306,16 @@ class Torrent extends NexusModel
return $result;
}
public static function listPosStates(): array
public static function listPosStates($onlyKeyValue = false, $valueField = 'text'): array
{
$result = self::$posStates;
$keyValues = [];
foreach ($result as $key => &$value) {
$value['text'] = nexus_trans('torrent.pos_state_' . $key);
$keyValues[$key] = $value[$valueField];
}
if ($onlyKeyValue) {
return $keyValues;
}
return $result;
}
+1
View File
@@ -64,5 +64,6 @@ class TorrentOperationLog extends NexusModel
Message::query()->insert($message);
NexusDB::cache_del("user_{$receiver->id}_unread_message_count");
NexusDB::cache_del("user_{$receiver->id}_inbox_count");
do_log("notify user: {$receiver->id}, $subject");
}
}
+3 -1
View File
@@ -12,6 +12,8 @@ use Illuminate\Support\Facades\DB;
class DashboardRepository extends BaseRepository
{
const FILAMENT_VERSION = '2.13.15';
public function getSystemInfo(): array
{
$result = [];
@@ -37,7 +39,7 @@ class DashboardRepository extends BaseRepository
$result[$name] = [
'name' => $name,
'text' => nexus_trans("dashboard.system_info.$name"),
'value' => "2.13.14",
'value' => self::FILAMENT_VERSION,
];
$name = 'php_version';
$result[$name] = [
+2 -2
View File
@@ -521,11 +521,11 @@ class TorrentRepository extends BaseRepository
NexusDB::transaction(function () use ($torrent, $torrentOperationLog, $torrentUpdate, $notifyUser) {
$log = "torrent: " . $torrent->id;
if (!empty($torrentUpdate)) {
$log .= "[UPDATE_TORRENT]: " . nexus_json_encode($torrentUpdate);
$log .= ", [UPDATE_TORRENT]: " . nexus_json_encode($torrentUpdate);
$torrent->update($torrentUpdate);
}
if (!empty($torrentOperationLog)) {
$log .= "[ADD_TORRENT_OPERATION_LOG]: " . nexus_json_encode($torrentOperationLog);
$log .= ", [ADD_TORRENT_OPERATION_LOG]: " . nexus_json_encode($torrentOperationLog);
TorrentOperationLog::add($torrentOperationLog, $notifyUser);
}
do_log($log);