From bb000fb67af7dbe1f7642a2afda559352f32f6e8 Mon Sep 17 00:00:00 2001 From: xiaomlove Date: Sun, 2 Oct 2022 21:14:11 +0800 Subject: [PATCH] [admin] torrent add more bulk action --- app/Filament/OptionsTrait.php | 8 ++ .../System/SeedBoxRecordResource.php | 1 + .../SettingResource/Pages/EditSetting.php | 1 + .../Resources/Torrent/TorrentResource.php | 113 +++++++++++++++++- app/Models/NexusModel.php | 15 +++ app/Models/Tag.php | 8 ++ app/Models/Torrent.php | 15 +++ app/Repositories/TagRepository.php | 17 +-- app/Repositories/TorrentRepository.php | 50 ++++++++ include/functions.php | 27 +++-- include/globalfunctions.php | 17 ++- nexus/Field/Field.php | 1 + nexus/Install/settings.default.php | 2 + public/announce.php | 2 +- public/mybonus.php | 4 +- public/settings.php | 3 +- resources/lang/en/admin.php | 3 + resources/lang/en/label.php | 7 +- resources/lang/en/permission.php | 4 + resources/lang/en/torrent.php | 5 + resources/lang/zh_CN/admin.php | 3 + resources/lang/zh_CN/label.php | 7 +- resources/lang/zh_CN/permission.php | 4 + resources/lang/zh_CN/torrent.php | 5 + resources/lang/zh_TW/admin.php | 3 + resources/lang/zh_TW/label.php | 7 +- resources/lang/zh_TW/permission.php | 4 + resources/lang/zh_TW/torrent.php | 5 + 28 files changed, 313 insertions(+), 28 deletions(-) diff --git a/app/Filament/OptionsTrait.php b/app/Filament/OptionsTrait.php index 0da89a5f..c210d280 100644 --- a/app/Filament/OptionsTrait.php +++ b/app/Filament/OptionsTrait.php @@ -15,4 +15,12 @@ trait OptionsTrait $disableValue => __('label.disabled'), ]; } + + private static function getYesNoOptions($yesValue = 1, $noValue = 0): array + { + return [ + $yesValue => 'Yes', + $noValue => 'No', + ]; + } } diff --git a/app/Filament/Resources/System/SeedBoxRecordResource.php b/app/Filament/Resources/System/SeedBoxRecordResource.php index 14565204..fca5b10c 100644 --- a/app/Filament/Resources/System/SeedBoxRecordResource.php +++ b/app/Filament/Resources/System/SeedBoxRecordResource.php @@ -56,6 +56,7 @@ class SeedBoxRecordResource extends Resource ->columns([ Tables\Columns\TextColumn::make('id'), Tables\Columns\TextColumn::make('typeText')->label(__('label.seed_box_record.type')), + Tables\Columns\TextColumn::make('uid')->searchable(), Tables\Columns\TextColumn::make('user.username')->label(__('label.username'))->searchable(), Tables\Columns\TextColumn::make('operator')->label(__('label.seed_box_record.operator'))->searchable(), Tables\Columns\TextColumn::make('bandwidth')->label(__('label.seed_box_record.bandwidth')), diff --git a/app/Filament/Resources/System/SettingResource/Pages/EditSetting.php b/app/Filament/Resources/System/SettingResource/Pages/EditSetting.php index 7dc8b37b..53c207db 100644 --- a/app/Filament/Resources/System/SettingResource/Pages/EditSetting.php +++ b/app/Filament/Resources/System/SettingResource/Pages/EditSetting.php @@ -112,6 +112,7 @@ class EditSetting extends Page implements Forms\Contracts\HasForms Forms\Components\TextInput::make('seed_box.not_seed_box_max_speed')->label(__('label.setting.seed_box.not_seed_box_max_speed'))->helperText(__('label.setting.seed_box.not_seed_box_max_speed_help'))->integer(), Forms\Components\Radio::make('seed_box.no_promotion')->options(self::$yesOrNo)->inline(true)->label(__('label.setting.seed_box.no_promotion'))->helperText(__('label.setting.seed_box.no_promotion_help')), Forms\Components\TextInput::make('seed_box.max_uploaded')->label(__('label.setting.seed_box.max_uploaded'))->helperText(__('label.setting.seed_box.max_uploaded_help'))->integer(), + Forms\Components\TextInput::make('seed_box.max_uploaded_duration')->label(__('label.setting.seed_box.max_uploaded_duration'))->helperText(__('label.setting.seed_box.max_uploaded_duration_help'))->integer(), ])->columns(2); $tabs[] = Forms\Components\Tabs\Tab::make(__('label.setting.system.tab_header')) diff --git a/app/Filament/Resources/Torrent/TorrentResource.php b/app/Filament/Resources/Torrent/TorrentResource.php index 49f14881..f4b09701 100644 --- a/app/Filament/Resources/Torrent/TorrentResource.php +++ b/app/Filament/Resources/Torrent/TorrentResource.php @@ -9,6 +9,7 @@ use App\Models\Setting; use App\Models\Tag; use App\Models\Torrent; use App\Models\TorrentTag; +use App\Models\User; use App\Repositories\TagRepository; use App\Repositories\TorrentRepository; use Filament\Facades\Filament; @@ -24,6 +25,7 @@ use Illuminate\Support\Collection; use Illuminate\Support\Facades\Auth; use Illuminate\Support\HtmlString; use Illuminate\Support\Str; +use Illuminate\Validation\Rule; class TorrentResource extends Resource { @@ -83,10 +85,16 @@ class TorrentResource extends Resource })->label(__('label.name'))->searchable(), Tables\Columns\TextColumn::make('posStateText')->label(__('label.torrent.pos_state')), Tables\Columns\TextColumn::make('spStateText')->label(__('label.torrent.sp_state')), + Tables\Columns\TextColumn::make('pickInfoText') + ->label(__('label.torrent.picktype')) + ->formatStateUsing(fn ($record) => $record->pickInfo['text']) + , + Tables\Columns\BooleanColumn::make('hr') + ->label(__('label.torrent.hr')) + , 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\TextColumn::make('times_completed')->label(__('label.torrent.times_completed')), Tables\Columns\BadgeColumn::make('approval_status') ->visible($showApproval) ->label(__('label.torrent.approval_status')) @@ -113,10 +121,18 @@ class TorrentResource extends Resource ->options(Torrent::listPromotionTypes(true)) ->label(__('label.torrent.sp_state')), + Tables\Filters\SelectFilter::make('picktype') + ->options(Torrent::listPickInfo(true)) + ->label(__('label.torrent.picktype')), + Tables\Filters\SelectFilter::make('approval_status') ->options(Torrent::listApprovalStatus(true)) ->visible($showApproval) ->label(__('label.torrent.approval_status')), + + Tables\Filters\SelectFilter::make('hr') + ->options(self::getYesNoOptions()) + ->label(__('label.torrent.hr')), ]) ->actions(self::getActions()) ->bulkActions(self::getBulkActions()); @@ -146,6 +162,7 @@ class TorrentResource extends Resource private static function getBulkActions(): array { + $user = Auth::user(); $actions = []; if (user_can('torrentsticky')) { $actions[] = Tables\Actions\BulkAction::make('posState') @@ -174,6 +191,66 @@ class TorrentResource extends Resource ->deselectRecordsAfterCompletion(); } + if (user_can('torrentonpromotion')) { + $actions[] = Tables\Actions\BulkAction::make('sp_state') + ->label(__('admin.resources.torrent.bulk_action_sp_state')) + ->form([ + Forms\Components\Select::make('sp_state') + ->label(__('label.torrent.sp_state')) + ->options(Torrent::listPromotionTypes(true)) + ->required() + , + Forms\Components\Select::make('promotion_time_type') + ->label(__('label.torrent.promotion_time_type')) + ->options(Torrent::listPromotionTimeTypes(true)) + ->required() + , + Forms\Components\DateTimePicker::make('promotion_until') + ->label(__('label.deadline')) + , + ]) + ->icon('heroicon-o-speakerphone') + ->action(function (Collection $records, array $data) { + $idArr = $records->pluck('id')->toArray(); + try { + $torrentRep = new TorrentRepository(); + $torrentRep->setSpState($idArr, $data['sp_state'], $data['promotion_time_type'], $data['promotion_until']); + } catch (\Exception $exception) { + do_log($exception->getMessage() . $exception->getTraceAsString(), 'error'); + Filament::notify('danger', $exception->getMessage()); + } + }) + ->deselectRecordsAfterCompletion(); + } + + if (user_can('torrentmanage') && ($user->picker == 'yes' || $user->class >= User::CLASS_SYSOP)) { + $actions[] = Tables\Actions\BulkAction::make('recommend') + ->label(__('admin.resources.torrent.bulk_action_recommend')) + ->form([ + Forms\Components\Radio::make('picktype') + ->label(__('admin.resources.torrent.bulk_action_recommend')) + ->inline() + ->options(Torrent::listPickInfo(true)) + ->required(), + + ]) + ->icon('heroicon-o-fire') + ->action(function (Collection $records, array $data) { + if (empty($data['picktype'])) { + return; + } + $idArr = $records->pluck('id')->toArray(); + try { + $torrentRep = new TorrentRepository(); + $torrentRep->setPickType($idArr, $data['picktype']); + } catch (\Exception $exception) { + do_log($exception->getMessage() . $exception->getTraceAsString(), 'error'); + Filament::notify('danger', class_basename($exception)); + } + }) + ->deselectRecordsAfterCompletion(); + } + if (user_can('torrentmanage')) { $actions[] = Tables\Actions\BulkAction::make('remove_tag') ->label(__('admin.resources.torrent.bulk_action_remove_tag')) @@ -217,6 +294,38 @@ class TorrentResource extends Resource } }) ->deselectRecordsAfterCompletion(); + + $actions[] = Tables\Actions\BulkAction::make('hr') + ->label(__('admin.resources.torrent.bulk_action_hr')) + ->form([ + Forms\Components\Radio::make('hr') + ->label(__('admin.resources.torrent.bulk_action_hr')) + ->inline() + ->options(self::getYesNoOptions()) + ->required(), + + ]) + ->icon('heroicon-o-sparkles') + ->action(function (Collection $records, array $data) { + if (empty($data['hr'])) { + return; + } + $idArr = $records->pluck('id')->toArray(); + try { + $torrentRep = new TorrentRepository(); + $torrentRep->setHr($idArr, $data['hr']); + } catch (\Exception $exception) { + do_log($exception->getMessage() . $exception->getTraceAsString(), 'error'); + Filament::notify('danger', class_basename($exception)); + } + }) + ->deselectRecordsAfterCompletion(); + } + + if (user_can('torrent-delete')) { + $actions[] = Tables\Actions\DeleteBulkAction::make('bulk-delete')->using(function (Collection $records) { + deletetorrent($records->pluck('id')->toArray()); + }); } return $actions; @@ -248,7 +357,7 @@ class TorrentResource extends Resource }); } - if (user_can('torrentmanage')) { + if (user_can('torrent-delete')) { $actions[] = Tables\Actions\DeleteAction::make('delete')->using(function ($record) { deletetorrent($record->id); }); diff --git a/app/Models/NexusModel.php b/app/Models/NexusModel.php index fcead220..75248fe4 100644 --- a/app/Models/NexusModel.php +++ b/app/Models/NexusModel.php @@ -51,4 +51,19 @@ class NexusModel extends Model return sprintf('%s: %s', nexus_trans('label.deadline'), $raw); } + public static function listStaticProps($dataSource, $textTransPrefix, $onlyKeyValue = false, $valueField = 'text'): array + { + $result = $dataSource; + $keyValue = []; + foreach ($result as $key => &$info) { + $text = $textTransPrefix ? nexus_trans("$textTransPrefix.$key") : $info['text']; + $info['text'] = $text; + $keyValue[$key] = $info[$valueField]; + } + if ($onlyKeyValue) { + return $keyValue; + } + return $result; + } + } diff --git a/app/Models/Tag.php b/app/Models/Tag.php index b9d42700..03858aec 100644 --- a/app/Models/Tag.php +++ b/app/Models/Tag.php @@ -48,6 +48,14 @@ class Tag extends NexusModel ], ]; + public static function listSpecial(): array + { + return array_filter([ + Setting::get('system.official_tag'), + Setting::get('system.zero_bonus_tag'), + ]); + } + public function torrents(): \Illuminate\Database\Eloquent\Relations\BelongsToMany { return $this->belongsToMany(Torrent::class, 'torrent_tags', 'tag_id', 'torrent_id'); diff --git a/app/Models/Torrent.php b/app/Models/Torrent.php index 4d8c656b..a36faa4c 100644 --- a/app/Models/Torrent.php +++ b/app/Models/Torrent.php @@ -130,6 +130,16 @@ class Torrent extends NexusModel self::PICK_RECOMMENDED => ['text' => self::PICK_RECOMMENDED, 'color' => '#820084'], ]; + const PROMOTION_TIME_TYPE_GLOBAL = 0; + const PROMOTION_TIME_TYPE_PERMANENT = 1; + const PROMOTION_TIME_TYPE_DEADLINE = 2; + + public static array $promotionTimeTypes = [ + self::PROMOTION_TIME_TYPE_GLOBAL => ['text' => 'Global'], + self::PROMOTION_TIME_TYPE_PERMANENT => ['text' => 'Permanent'], + self::PROMOTION_TIME_TYPE_DEADLINE => ['text' => 'Until'], + ]; + const BONUS_REWARD_VALUES = [50, 100, 200, 500, 1000]; const APPROVAL_STATUS_NONE = 0; @@ -272,6 +282,11 @@ class Torrent extends NexusModel return $result; } + public static function listPromotionTimeTypes($onlyKeyValue = false, $valueField = 'text'): array + { + return self::listStaticProps(self::$promotionTimeTypes, 'torrent.promotion_time_types', $onlyKeyValue, $valueField); + } + public static function listPickInfo($onlyKeyValue = false, $valueField = 'text'): array { $result = self::$pickTypes; diff --git a/app/Repositories/TagRepository.php b/app/Repositories/TagRepository.php index 2353101d..ab107dd0 100644 --- a/app/Repositories/TagRepository.php +++ b/app/Repositories/TagRepository.php @@ -50,10 +50,14 @@ class TagRepository extends BaseRepository return Tag::query()->orderBy('priority', 'desc')->orderBy('id', 'desc'); } - public function renderCheckbox(array $checked = []): string + public function renderCheckbox(array $checked = [], $ignorePermission = false): string { $html = ''; - $results = $this->createBasicQuery()->get(); + $results = $this->listAll(); + if (!$ignorePermission && !user_can('torrent-set-special-tag')) { + $specialTags = Tag::listSpecial(); + $results = $results->filter(fn ($item) => !in_array($item->id, $specialTags)); + } foreach ($results as $value) { $html .= sprintf( '', @@ -65,11 +69,8 @@ class TagRepository extends BaseRepository public function renderSpan(array $renderIdArr = [], $withFilterLink = false): string { - if (empty(self::$allTags)) { - self::$allTags = self::createBasicQuery()->get(); - } $html = ''; - foreach (self::$allTags as $value) { + foreach ($this->listAll() as $value) { if (in_array($value->id, $renderIdArr) || (isset($renderIdArr[0]) && $renderIdArr[0] == '*')) { $tagId = $value->id; if ($value) { @@ -150,7 +151,9 @@ class TagRepository extends BaseRepository public function listAll() { - self::$allTags = self::createBasicQuery()->get(); + if (empty(self::$allTags)) { + self::$allTags = self::createBasicQuery()->get(); + } return self::$allTags; } diff --git a/app/Repositories/TorrentRepository.php b/app/Repositories/TorrentRepository.php index fe91ad6d..2d161b7e 100644 --- a/app/Repositories/TorrentRepository.php +++ b/app/Repositories/TorrentRepository.php @@ -616,6 +616,56 @@ class TorrentRepository extends BaseRepository return Torrent::query()->whereIn('id', $idArr)->update($update); } + public function setPickType($id, $pickType): int + { + user_can('torrentmanage', true); + if (!isset(Torrent::$pickTypes[$pickType])) { + throw new \InvalidArgumentException("Invalid pickType: $pickType"); + } + $update = [ + 'picktype' => $pickType, + 'picktime' => now(), + ]; + $idArr = Arr::wrap($id); + return Torrent::query()->whereIn('id', $idArr)->update($update); + } + + public function setHr($id, $hrStatus): int + { + user_can('torrentmanage', true); + if (!isset(Torrent::$hrStatus[$hrStatus])) { + throw new \InvalidArgumentException("Invalid hrStatus: $hrStatus"); + } + $update = [ + 'hr' => $hrStatus, + ]; + $idArr = Arr::wrap($id); + return Torrent::query()->whereIn('id', $idArr)->update($update); + } + + public function setSpState($id, $spState, $promotionTimeType, $promotionUntil = null): int + { + user_can('torrentonpromotion', true); + if (!isset(Torrent::$promotionTypes[$spState])) { + throw new \InvalidArgumentException("Invalid spState: $spState"); + } + if (!isset(Torrent::$promotionTimeTypes[$promotionTimeType])) { + throw new \InvalidArgumentException("Invalid promotionTimeType: $promotionTimeType"); + } + if (in_array($promotionTimeType, [Torrent::PROMOTION_TIME_TYPE_GLOBAL, Torrent::PROMOTION_TIME_TYPE_PERMANENT])) { + $promotionUntil = null; + } elseif (!$promotionUntil || Carbon::parse($promotionUntil)->lte(now())) { + throw new \InvalidArgumentException("Invalid promotionUntil: $promotionUntil"); + } + $update = [ + 'sp_state' => $spState, + 'promotion_time_type' => $promotionTimeType, + 'promotion_until' => $promotionUntil, + ]; + $idArr = Arr::wrap($id); + return Torrent::query()->whereIn('id', $idArr)->update($update); + } + public function buildUploadFieldInput($name, $value, $noteText, $btnText): string { $btn = $note = ''; diff --git a/include/functions.php b/include/functions.php index 808e7804..89052420 100644 --- a/include/functions.php +++ b/include/functions.php @@ -3049,18 +3049,21 @@ function loggedinorreturn($mainpage = false) { } function deletetorrent($id) { - $id = intval($id); + $idArr = \Illuminate\Support\Arr::wrap($id); + $idStr = implode(', ', $idArr ?: [0]); $torrent_dir = get_setting('main.torrent_dir'); - \Nexus\Database\NexusDB::statement("DELETE FROM torrents WHERE id = $id"); - \Nexus\Database\NexusDB::statement("DELETE FROM snatched WHERE torrentid = $id"); + \Nexus\Database\NexusDB::statement("DELETE FROM torrents WHERE id in ($idStr)"); + \Nexus\Database\NexusDB::statement("DELETE FROM snatched WHERE torrentid in ($idStr)"); foreach(array("peers", "files", "comments") as $x) { - \Nexus\Database\NexusDB::statement("DELETE FROM $x WHERE torrent = $id"); + \Nexus\Database\NexusDB::statement("DELETE FROM $x WHERE torrent in ($idStr)"); } - \Nexus\Database\NexusDB::statement("DELETE FROM hit_and_runs WHERE torrent_id = $id"); - \Nexus\Database\NexusDB::statement("DELETE FROM claims WHERE torrent_id = $id"); - do_action("torrent_delete", $id); - do_log("delete torrent: $id", "error"); - unlink(getFullDirectory("$torrent_dir/$id.torrent")); + \Nexus\Database\NexusDB::statement("DELETE FROM hit_and_runs WHERE torrent_id in ($idStr)"); + \Nexus\Database\NexusDB::statement("DELETE FROM claims WHERE torrent_id in ($idStr)"); + foreach ($idArr as $_id) { + do_action("torrent_delete", $_id); + do_log("delete torrent: $_id", "error"); + unlink(getFullDirectory("$torrent_dir/$_id.torrent")); + } } function pager($rpp, $count, $href, $opts = array(), $pagename = "page") { @@ -5790,6 +5793,8 @@ function build_medal_image(\Illuminate\Support\Collection $medals, $maxHeight = function insert_torrent_tags($torrentId, $tagIdArr, $sync = false) { + $specialTags = \App\Models\Tag::listSpecial(); + $canSetSpecialTag = user_can('torrent-set-special-tag'); $dateTimeStringNow = date('Y-m-d H:i:s'); if ($sync) { sql_query("delete from torrent_tags where torrent_id = $torrentId"); @@ -5800,6 +5805,10 @@ function insert_torrent_tags($torrentId, $tagIdArr, $sync = false) $insertTagsSql = 'insert into torrent_tags (`torrent_id`, `tag_id`, `created_at`, `updated_at`) values '; $values = []; foreach ($tagIdArr as $tagId) { + if (in_array($tagId, $specialTags) && !$canSetSpecialTag) { + do_log("special tag: $tagId, and user no permission"); + continue; + } $values[] = sprintf("(%s, %s, '%s', '%s')", $torrentId, $tagId, $dateTimeStringNow, $dateTimeStringNow); } $insertTagsSql .= implode(', ', $values); diff --git a/include/globalfunctions.php b/include/globalfunctions.php index 5534c4a2..51d23737 100644 --- a/include/globalfunctions.php +++ b/include/globalfunctions.php @@ -942,9 +942,20 @@ function getDataTraffic(array $torrent, array $queries, array $user, $peer, $sna $log .= ", isIPSeedBox && isSeedBoxNoPromotion, increment for user = real"; } $maxUploadedTimes = get_setting('seed_box.max_uploaded'); - if (!empty($snatch) && isset($torrent['size']) && $snatch['uploaded'] >= $torrent['size'] * $maxUploadedTimes) { - $log .= ", snatchUploaded >= torrentSize * times($maxUploadedTimes), uploadedIncrementForUser = 0"; - $uploadedIncrementForUser = 0; + $maxUploadedDurationSeconds = get_setting('seed_box.max_uploaded_duration', 0) * 3600; + $torrentTTL = time() - strtotime($torrent['added']); + $timeRangeValid = ($maxUploadedDurationSeconds == 0) || ($torrentTTL < $maxUploadedDurationSeconds); + $log .= ", maxUploadedTimes: $maxUploadedTimes, maxUploadedDurationSeconds: $maxUploadedDurationSeconds, timeRangeValid: $timeRangeValid"; + if ($maxUploadedTimes > 0 && $timeRangeValid) { + $log .= ", [LIMIT_UPLOADED]"; + if (!empty($snatch) && isset($torrent['size']) && $snatch['uploaded'] >= $torrent['size'] * $maxUploadedTimes) { + $log .= ", snatchUploaded({$snatch['uploaded']}) >= torrentSize({$torrent['size']}) * times($maxUploadedTimes), uploadedIncrementForUser = 0"; + $uploadedIncrementForUser = 0; + } else { + $log .= ", snatchUploaded({$snatch['uploaded']}) < torrentSize({$torrent['size']}) * times($maxUploadedTimes), uploadedIncrementForUser do not change to 0"; + } + } else { + $log .= ", [NOT_LIMIT_UPLOADED]"; } } } diff --git a/nexus/Field/Field.php b/nexus/Field/Field.php index 8ca7cc18..9906c060 100644 --- a/nexus/Field/Field.php +++ b/nexus/Field/Field.php @@ -3,6 +3,7 @@ namespace Nexus\Field; use App\Models\SearchBox; +use App\Models\Tag; use App\Models\TorrentCustomField; use App\Models\TorrentCustomFieldValue; use Elasticsearch\Endpoints\Search; diff --git a/nexus/Install/settings.default.php b/nexus/Install/settings.default.php index 99330be6..bdb20baf 100644 --- a/nexus/Install/settings.default.php +++ b/nexus/Install/settings.default.php @@ -180,6 +180,7 @@ return array ( 'torrent-delete' => User::CLASS_ADMINISTRATOR, 'user-delete' => User::CLASS_ADMINISTRATOR, 'user-change-class' => User::CLASS_ADMINISTRATOR, + 'torrent-set-special-tag' => User::CLASS_ADMINISTRATOR, ), 'tweak' => array ( @@ -425,6 +426,7 @@ return array ( 'no_promotion' => 'yes', 'max_uploaded' => 3, 'not_seed_box_max_speed' => 10240, + 'max_uploaded_duration' => 0, ], 'system' => [ 'change_username_min_interval_in_days' => '365', diff --git a/public/announce.php b/public/announce.php index c93ca683..eb041ac9 100644 --- a/public/announce.php +++ b/public/announce.php @@ -156,7 +156,7 @@ elseif ($az['showclienterror'] == 'yes'){ } // check torrent based on info_hash -$checkTorrentSql = "SELECT torrents.id, size, owner, sp_state, seeders, leechers, UNIX_TIMESTAMP(added) AS ts, banned, hr, approval_status, categories.mode FROM torrents left join categories on torrents.category = categories.id WHERE " . hash_where("info_hash", $info_hash); +$checkTorrentSql = "SELECT torrents.id, size, owner, sp_state, seeders, leechers, UNIX_TIMESTAMP(added) AS ts, added, banned, hr, approval_status, categories.mode FROM torrents left join categories on torrents.category = categories.id WHERE " . hash_where("info_hash", $info_hash); if (!$torrent = $Cache->get_value('torrent_hash_'.$info_hash.'_content')){ $res = sql_query($checkTorrentSql); $torrent = mysql_fetch_array($res); diff --git a/public/mybonus.php b/public/mybonus.php index e7ac933d..8a5d851e 100644 --- a/public/mybonus.php +++ b/public/mybonus.php @@ -580,14 +580,14 @@ if ($action == "exchange") { $up = $upload + $bonusarray['menge']; // $bonuscomment = date("Y-m-d") . " - " .$points. " Points for upload bonus.\n " .$bonuscomment; // sql_query("UPDATE users SET uploaded = ".sqlesc($up).", seedbonus = seedbonus - $points, bonuscomment = ".sqlesc($bonuscomment)." WHERE id = ".sqlesc($userid)) or sqlerr(__FILE__, __LINE__); - $bonusRep->consumeUserBonus($CURUSER['id'], $points, \App\Models\BonusLogs::BUSINESS_TYPE_EXCHANGE_UPLOAD, $points. " Points for upload bonus.", ['uploaded' => $up]); + $bonusRep->consumeUserBonus($CURUSER['id'], $points, \App\Models\BonusLogs::BUSINESS_TYPE_EXCHANGE_UPLOAD, $points. " Points for uploaded.", ['uploaded' => $up]); nexus_redirect("" . get_protocol_prefix() . "$BASEURL/mybonus.php?do=upload"); } } if($art == "traffic_downloaded") { $downloaded = $CURUSER['downloaded']; $down = $downloaded + $bonusarray['menge']; - $bonusRep->consumeUserBonus($CURUSER['id'], $points, \App\Models\BonusLogs::BUSINESS_TYPE_EXCHANGE_DOWNLOAD, $points. " Points for download bonus.", ['downloaded' => $down]); + $bonusRep->consumeUserBonus($CURUSER['id'], $points, \App\Models\BonusLogs::BUSINESS_TYPE_EXCHANGE_DOWNLOAD, $points. " Points for downloaded.", ['downloaded' => $down]); nexus_redirect("" . get_protocol_prefix() . "$BASEURL/mybonus.php?do=download"); } //=== trade for one month VIP status ***note "SET class = '10'" change "10" to whatever your VIP class number is diff --git a/public/settings.php b/public/settings.php index 7b70aa36..005d9ede 100644 --- a/public/settings.php +++ b/public/settings.php @@ -224,7 +224,7 @@ elseif ($action == 'savesettings_authority') // save user authority 'torrentstructure','sendinvite','viewhistory','topten','log','confilog','userprofile', 'torrenthistory','prfmanage', 'cruprfmanage', 'uploadsub','delownsub','submanage','updateextinfo', 'viewanonymous','beanonymous','addoffer','offermanage', 'upload','uploadspecial', 'view_special_torrent','movetorrent','chrmanage','viewinvite', 'buyinvite','seebanned','againstoffer','userbar', 'torrent-approval', - 'torrent-delete', 'user-delete', 'user-change-class', + 'torrent-delete', 'user-delete', 'user-change-class', 'torrent-set-special-tag' ); GetVar($validConfig); $AUTHORITY = []; @@ -452,6 +452,7 @@ elseif ($action == 'authoritysettings') //Authority settings tr($lang_settings['row_torrent_sticky'], $lang_settings['text_minimum_class'].classlist('torrentsticky',$maxclass,$AUTHORITY['torrentsticky'],0,true).$lang_settings['text_default'].get_user_class_name(UC_ADMINISTRATOR,false,true,true).$lang_settings['text_torrent_sticky_note'],1); tr($lang_settings['row_torrent_on_promotion'], $lang_settings['text_minimum_class'].classlist('torrentonpromotion',$maxclass,$AUTHORITY['torrentonpromotion'] ?? '',0,true).$lang_settings['text_default'].get_user_class_name(UC_ADMINISTRATOR,false,true,true).$lang_settings['text_torrent_promotion_note'],1); tr($lang_settings['row_torrent_hr'], $lang_settings['text_minimum_class'].classlist('torrent_hr',$maxclass,$AUTHORITY['torrent_hr'] ?? '',0,true).$lang_settings['text_default'].get_user_class_name(UC_ADMINISTRATOR,false,true,true).$lang_settings['text_torrent_hr_note'],1); + tr(nexus_trans('permission.torrent-set-special-tag.text'), $lang_settings['text_minimum_class'].classlist('torrent-set-special-tag',$maxclass,$AUTHORITY['torrent-set-special-tag'] ?? '',0,true).$lang_settings['text_default'].get_user_class_name(UC_ADMINISTRATOR,false,true,true).nexus_trans('permission.torrent-set-special-tag.desc'),1); tr(nexus_trans('permission.torrent-approval.text'), $lang_settings['text_minimum_class'].classlist('torrent-approval',$maxclass,$AUTHORITY['torrent-approval'] ?? '',0,true).$lang_settings['text_default'].get_user_class_name(UC_ADMINISTRATOR,false,true,true).nexus_trans('permission.torrent-approval.desc'),1); tr($lang_settings['row_ask_for_reseed'], $lang_settings['text_minimum_class'].classlist('askreseed',$maxclass,$AUTHORITY['askreseed'],0,true).$lang_settings['text_default'].get_user_class_name(UC_POWER_USER,false,true,true).$lang_settings['text_ask_for_reseed_note'],1); tr($lang_settings['row_view_nfo'], $lang_settings['text_minimum_class'].classlist('viewnfo',$maxclass,$AUTHORITY['viewnfo'],0,true).$lang_settings['text_default'].get_user_class_name(UC_POWER_USER,false,true,true).$lang_settings['text_view_nfo_note'],1); diff --git a/resources/lang/en/admin.php b/resources/lang/en/admin.php index 82480c32..ce81cbeb 100644 --- a/resources/lang/en/admin.php +++ b/resources/lang/en/admin.php @@ -89,6 +89,9 @@ return [ 'bulk_action_attach_tag' => 'Attach tag', 'action_approval' => 'Approval', 'bulk_action_attach_tag_remove_old' => 'Also delete old tags', + 'bulk_action_recommend' => 'Recommend', + 'bulk_action_sp_state' => 'Promotion', + 'bulk_action_hr' => 'H&R', ], 'seed_box_record' => [ 'toggle_status' => 'Change status', diff --git a/resources/lang/en/label.php b/resources/lang/en/label.php index a865ef26..3273d595 100644 --- a/resources/lang/en/label.php +++ b/resources/lang/en/label.php @@ -73,9 +73,11 @@ return [ 'no_promotion' => 'No promotion', 'no_promotion_help' => 'No Promotion, uploaded/downloaded are calculated according to the actual value', 'max_uploaded' => 'Maximum upload volume multiplier', - 'max_uploaded_help' => 'The total upload volume is at most a multiple of its volume', + 'max_uploaded_help' => 'The total upload volume is at most a multiple of its volume. Set to 0 No limitation', 'not_seed_box_max_speed' => 'Not SeedBox max upload speed', 'not_seed_box_max_speed_help' => 'Unit: Mbps, if this value is exceeded and the SeedBox record cannot be matched, download permission is disabled', + 'max_uploaded_duration' => 'Maximum upload volume multiplier effective time range', + 'max_uploaded_duration_help' => 'Unit: hours. The maximum upload volume multiplier takes effect within this time range after the torrent is published, and does not take effect beyond this range. A setting of 0 is always in effect', ], 'system' => [ 'tab_header' => 'System', @@ -149,6 +151,9 @@ return [ 'pos_state' => 'Pos state', 'sp_state' => 'Promotion', 'visible' => 'Visible', + 'picktype' => 'Recommend', + 'promotion_time_type' => 'Promotion type time', + 'hr' => 'H&R', ], 'hit_and_run' => [ 'label' => 'User H&R', diff --git a/resources/lang/en/permission.php b/resources/lang/en/permission.php index 47ae27aa..3555f17e 100644 --- a/resources/lang/en/permission.php +++ b/resources/lang/en/permission.php @@ -5,6 +5,10 @@ return [ 'text' => 'Approval Torrent', 'desc' => 'Allow, Deny, or mark as unreviewed', ], + 'torrent-set-special-tag' => [ + 'text' => 'Set torrent special tags', + 'desc' => 'Set the Official/Zero bonus tag to torrents', + ], 'defaultclass' => [ 'text' => 'Default Class', 'desc' => ' Class upon registration', diff --git a/resources/lang/en/torrent.php b/resources/lang/en/torrent.php index 907d2e0d..f30409bd 100644 --- a/resources/lang/en/torrent.php +++ b/resources/lang/en/torrent.php @@ -76,4 +76,9 @@ return [ 'logs_label' => 'Approval logs' ], 'show_hide_media_info' => 'Show/Hide raw MediaInfo', + 'promotion_time_types' => [ + \App\Models\Torrent::PROMOTION_TIME_TYPE_GLOBAL => 'Global', + \App\Models\Torrent::PROMOTION_TIME_TYPE_PERMANENT => 'Permanent', + \App\Models\Torrent::PROMOTION_TIME_TYPE_DEADLINE => 'Until', + ], ]; diff --git a/resources/lang/zh_CN/admin.php b/resources/lang/zh_CN/admin.php index 546c835e..69ecf72a 100644 --- a/resources/lang/zh_CN/admin.php +++ b/resources/lang/zh_CN/admin.php @@ -90,6 +90,9 @@ return [ 'bulk_action_attach_tag' => '设置标签', 'action_approval' => '审核', 'bulk_action_attach_tag_remove_old' => '同时删除旧标签', + 'bulk_action_recommend' => '推荐', + 'bulk_action_sp_state' => '优惠', + 'bulk_action_hr' => 'H&R', ], 'seed_box_record' => [ 'toggle_status' => '更改状态', diff --git a/resources/lang/zh_CN/label.php b/resources/lang/zh_CN/label.php index fc750670..42985d70 100644 --- a/resources/lang/zh_CN/label.php +++ b/resources/lang/zh_CN/label.php @@ -73,9 +73,11 @@ return [ 'no_promotion' => '无优惠', 'no_promotion_help' => '不享受任何优惠,上传量/下载量按实际值计算', 'max_uploaded' => '最大上传量倍数', - 'max_uploaded_help' => '总上传量最多为其体积的多少倍', + 'max_uploaded_help' => '总上传量最多为其体积的多少倍。设置为 0 无此限制', 'not_seed_box_max_speed' => '非 SeedBox 最高限速', 'not_seed_box_max_speed_help' => '单位:Mbps。若超过此值又不能匹配 SeedBox 记录,禁用下载权限', + 'max_uploaded_duration' => '最大上传量倍数有效时间范围', + 'max_uploaded_duration_help' => '单位:小时。种子发布后的这个时间范围内,最大上传量倍数生效,超过此范围不生效。设置为 0 一直生效', ], 'system' => [ 'tab_header' => '系统', @@ -148,6 +150,9 @@ return [ 'pos_state' => '置顶', 'sp_state' => '优惠', 'visible' => '活种', + 'picktype' => '推荐', + 'promotion_time_type' => '优惠时间类型', + 'hr' => 'H&R', ], 'hit_and_run' => [ 'label' => '用户 H&R', diff --git a/resources/lang/zh_CN/permission.php b/resources/lang/zh_CN/permission.php index 1e50fba3..8d85f91f 100644 --- a/resources/lang/zh_CN/permission.php +++ b/resources/lang/zh_CN/permission.php @@ -5,6 +5,10 @@ return [ 'text' => '审核种子', 'desc' => '通过种子、拒绝种子、或将种子标记为未审', ], + 'torrent-set-special-tag' => [ + 'text' => '设定种子特殊标签', + 'desc' => '设定种子的官方、零魔标签', + ], 'defaultclass' => [ 'text' => '默认等级', 'desc' => '注册时获得的等级', diff --git a/resources/lang/zh_CN/torrent.php b/resources/lang/zh_CN/torrent.php index 4870f6de..7740eb33 100644 --- a/resources/lang/zh_CN/torrent.php +++ b/resources/lang/zh_CN/torrent.php @@ -76,4 +76,9 @@ return [ 'logs_label' => '审核记录', ], 'show_hide_media_info' => '显示/隐藏原始 MediaInfo', + 'promotion_time_types' => [ + \App\Models\Torrent::PROMOTION_TIME_TYPE_GLOBAL => '全局', + \App\Models\Torrent::PROMOTION_TIME_TYPE_PERMANENT => '永久', + \App\Models\Torrent::PROMOTION_TIME_TYPE_DEADLINE => '直到', + ], ]; diff --git a/resources/lang/zh_TW/admin.php b/resources/lang/zh_TW/admin.php index c46b91fd..07664aed 100644 --- a/resources/lang/zh_TW/admin.php +++ b/resources/lang/zh_TW/admin.php @@ -89,6 +89,9 @@ return [ 'bulk_action_attach_tag' => '設置標簽', 'action_approval' => '審核', 'bulk_action_attach_tag_remove_old' => '同時刪除舊標簽', + 'bulk_action_recommend' => '推薦', + 'bulk_action_sp_state' => '優惠', + 'bulk_action_hr' => 'H&R', ], 'seed_box_record' => [ 'toggle_status' => '更改狀態', diff --git a/resources/lang/zh_TW/label.php b/resources/lang/zh_TW/label.php index e19d82f0..d1ac1dca 100644 --- a/resources/lang/zh_TW/label.php +++ b/resources/lang/zh_TW/label.php @@ -73,9 +73,11 @@ return [ 'no_promotion' => '無優惠', 'no_promotion_help' => '不享受任何優惠,上傳量/下載量按實際值計算', 'max_uploaded' => '最大上傳量倍數', - 'max_uploaded_help' => '總上傳量最多為其體積的多少倍', + 'max_uploaded_help' => '總上傳量最多為其體積的多少倍。設置為 0 無此限製', 'not_seed_box_max_speed' => '非 SeedBox 最高限速', 'not_seed_box_max_speed_help' => '單位:Mbps。若超過此值又不能匹配 SeedBox 記錄,禁用下載權限', + 'max_uploaded_duration' => '最大上傳量倍數有效時間範圍', + 'max_uploaded_duration_help' => '單位:小時。種子發布後的這個時間範圍內,最大上傳量倍數生效,超過此範圍不生效。設置為 0 一直生效', ], 'system' => [ 'tab_header' => '系統', @@ -149,6 +151,9 @@ return [ 'pos_state' => '置頂', 'sp_state' => '優惠', 'visible' => '活種', + 'picktype' => '推薦', + 'promotion_time_type' => '優惠時間類型', + 'hr' => 'H&R', ], 'hit_and_run' => [ 'label' => '用戶 H&R', diff --git a/resources/lang/zh_TW/permission.php b/resources/lang/zh_TW/permission.php index da0889d6..c0a254bb 100644 --- a/resources/lang/zh_TW/permission.php +++ b/resources/lang/zh_TW/permission.php @@ -5,6 +5,10 @@ return [ 'text' => '審核種子', 'desc' => '通過種子、拒絕種子、或將種子標記為未審', ], + 'torrent-set-special-tag' => [ + 'text' => '設定種子特殊標簽', + 'desc' => '設定種子的官方、零魔標簽', + ], 'defaultclass' => [ 'text' => '預設等級', 'desc' => '註冊時獲得的等級', diff --git a/resources/lang/zh_TW/torrent.php b/resources/lang/zh_TW/torrent.php index e2d99a49..790c82e0 100644 --- a/resources/lang/zh_TW/torrent.php +++ b/resources/lang/zh_TW/torrent.php @@ -76,4 +76,9 @@ return [ 'logs_label' => '審核記錄' ], 'show_hide_media_info' => '顯示/隱藏原始 MediaInfo', + 'promotion_time_types' => [ + \App\Models\Torrent::PROMOTION_TIME_TYPE_GLOBAL => '全局', + \App\Models\Torrent::PROMOTION_TIME_TYPE_PERMANENT => '永久', + \App\Models\Torrent::PROMOTION_TIME_TYPE_DEADLINE => '直到', + ], ];