From a739cf924ea3c0822c5a8cf0432644badacaf564 Mon Sep 17 00:00:00 2001 From: xiaomlove Date: Thu, 5 May 2022 22:19:48 +0800 Subject: [PATCH] new feature: claim --- app/Console/Commands/ClaimSettle.php | 57 ++++ app/Console/Commands/Test.php | 8 +- app/Models/Claim.php | 79 ++++++ app/Repositories/ClaimRepository.php | 267 ++++++++++++++++++ app/Repositories/TorrentRepository.php | 1 + .../2022_05_04_234639_create_claims_table.php | 38 +++ include/constants.php | 2 +- include/functions.php | 17 +- lang/chs/lang_claim.php | 16 ++ lang/chs/lang_clients.php | 41 --- lang/chs/lang_details.php | 6 + lang/chs/lang_functions.php | 5 +- lang/chs/lang_settings.php | 8 + lang/cht/lang_details.php | 6 + lang/cht/lang_functions.php | 5 +- lang/cht/lang_settings.php | 13 + lang/en/lang_details.php | 6 + lang/en/lang_functions.php | 5 +- lang/en/lang_settings.php | 13 + nexus/Install/settings.default.php | 8 + public/ajax.php | 14 + public/claim.php | 105 +++++++ public/details.php | 47 ++- public/settings.php | 14 +- resources/lang/en/claim.php | 28 ++ resources/lang/en/torrent.php | 4 + resources/lang/zh_CN/claim.php | 28 ++ resources/lang/zh_CN/torrent.php | 4 + resources/lang/zh_TW/claim.php | 25 ++ resources/lang/zh_TW/torrent.php | 4 + 30 files changed, 815 insertions(+), 59 deletions(-) create mode 100644 app/Console/Commands/ClaimSettle.php create mode 100644 app/Models/Claim.php create mode 100644 app/Repositories/ClaimRepository.php create mode 100644 database/migrations/2022_05_04_234639_create_claims_table.php create mode 100644 lang/chs/lang_claim.php delete mode 100644 lang/chs/lang_clients.php create mode 100644 public/claim.php create mode 100644 resources/lang/en/claim.php create mode 100644 resources/lang/zh_CN/claim.php create mode 100644 resources/lang/zh_TW/claim.php diff --git a/app/Console/Commands/ClaimSettle.php b/app/Console/Commands/ClaimSettle.php new file mode 100644 index 00000000..4addd0bd --- /dev/null +++ b/app/Console/Commands/ClaimSettle.php @@ -0,0 +1,57 @@ +option('uid'); + $force = $this->option('force'); + $test = $this->option('test'); + $this->info(sprintf('uid: %s, force: %s, test: %s', $uid, $force, $test)); + if (!$uid) { + $result = $rep->settleCronjob(); + } else { + $result = $rep->settleUser($uid, $force, $test); + } + $log = sprintf('[%s], %s, result: %s', nexus()->getRequestId(), __METHOD__, var_export($result, true)); + $this->info($log); + do_log($log); + return 0; + } +} diff --git a/app/Console/Commands/Test.php b/app/Console/Commands/Test.php index 7ec6d3f9..edb8388a 100644 --- a/app/Console/Commands/Test.php +++ b/app/Console/Commands/Test.php @@ -126,11 +126,9 @@ class Test extends Command // $r = $rep->getContinuousDays($attendance); // $r = $rep->getContinuousPoints(11); - $database = nexus_env('GEOIP2_DATABASE'); - $reader = new \GeoIp2\Database\Reader($database); - $city = $reader->city("95.211.156.168"); - $r = $city->country; - dd($r); + $arr = [1,2]; + $r = collect($arr)->map(fn($item) => $item * 2)->implode(','); + dd($r, $arr); } diff --git a/app/Models/Claim.php b/app/Models/Claim.php new file mode 100644 index 00000000..3e9d8409 --- /dev/null +++ b/app/Models/Claim.php @@ -0,0 +1,79 @@ + 'datetime', + ]; + + public function user() + { + return $this->belongsTo(User::class, 'uid'); + } + + public function torrent() + { + return $this->belongsTo(Torrent::class, 'torrent_id'); + } + + public function snatch() + { + return $this->belongsTo(Snatch::class, 'snatched_id'); + } + + public static function getConfigTorrentTTL() + { + return Setting::get('torrent.claim_torrent_ttl', self::TORRENT_TTL); + } + + public static function getConfigUserUpLimit() + { + return Setting::get('torrent.claim_torrent_user_counts_up_limit', self::USER_UP_LIMIT); + } + + public static function getConfigTorrentUpLimit() + { + return Setting::get('torrent.claim_user_torrent_counts_up_limit', self::TORRENT_UP_LIMIT); + } + + public static function getConfigRemoveDeductBonus() + { + return Setting::get('torrent.claim_remove_deduct_user_bonus', self::REMOVE_DEDUCT); + } + + public static function getConfigGiveUpDeductBonus() + { + return Setting::get('torrent.claim_give_up_deduct_user_bonus', self::GIVE_UP_DEDUCT); + } + + public static function getConfigBonusMultiplier() + { + return Setting::get('torrent.claim_bonus_multiplier', self::BONUS_MULTIPLIER); + } + + public static function getConfigStandardSeedTimeHours() + { + return Setting::get('torrent.claim_reach_standard_seed_time', self::STANDARD_SEED_TIME_HOURS); + } + + public static function getConfigStandardUploadedTimes() + { + return Setting::get('torrent.claim_reach_standard_uploaded', self::STANDARD_UPLOADED_TIMES); + } +} diff --git a/app/Repositories/ClaimRepository.php b/app/Repositories/ClaimRepository.php new file mode 100644 index 00000000..c9874cd8 --- /dev/null +++ b/app/Repositories/ClaimRepository.php @@ -0,0 +1,267 @@ +with(['family']); + if (!empty($params['family_id'])) { + $query->where('family_id', $params['family_id']); + } + $query->orderBy('family_id', 'desc'); + return $query->paginate(); + } + + public function store($uid, $torrentId) + { + $exists = Claim::query()->where('uid', $uid)->where('torrent_id', $torrentId)->exists(); + if ($exists) { + throw new \RuntimeException(nexus_trans("torrent.claim_already")); + } + $max = Claim::getConfigTorrentUpLimit(); + $count = Claim::query()->where('uid', $uid)->count(); + if ($count >= $max) { + throw new \RuntimeException(nexus_trans("torrent.claim_number_reach_maximum")); + } + $snatch = Snatch::query()->where('userid', $uid)->where('torrentid', $torrentId)->first(); + if (!$snatch) { + throw new \RuntimeException(nexus_trans("torrent.no_snatch")); + } + $claimTorrentTTL = Claim::getConfigTorrentTTL(); + $torrent = Torrent::query()->findOrFail($torrentId, Torrent::$commentFields); + if ($torrent->added->addDays($claimTorrentTTL)->gte(Carbon::now())) { + throw new \RuntimeException(nexus_trans("torrent.can_no_be_claimed_yet")); + } + $insert = [ + 'uid' => $uid, + 'torrent_id' => $torrentId, + 'snatched_id' => $snatch->id, + 'seed_time_begin' => $snatch->seedtime, + 'uploaded_begin' => $snatch->uploaded, + ]; + return Claim::query()->create($insert); + } + + public function update(array $params, $id) + { + $model = Claim::query()->findOrFail($id); + $model->update($params); + return $model; + } + + public function getDetail($id) + { + $model = Claim::query()->findOrFail($id); + return $model; + } + + public function delete($id, $uid) + { + $model = Claim::query()->findOrFail($id); + if ($model->uid != $uid) { + throw new \RuntimeException("No permission"); + } + $deductBonus = Claim::getConfigGiveUpDeductBonus(); + return NexusDB::transaction(function () use ($model, $deductBonus) { + User::query()->where('id', $model->uid)->decrement('seedbonus', $deductBonus); + do_log(sprintf("[GIVE_UP_CLAIM_TORRENT], user: %s, deduct bonus: %s", $model->uid, $deductBonus), 'alert'); + return $model->delete(); + }); + } + + public function getStats($uid) + { + $key = "claim_stats_$uid"; + return NexusDB::remember($key, 60, function () use ($uid) { + $max = Claim::getConfigTorrentUpLimit(); + return sprintf('%s/%s', Claim::query()->where('uid', $uid)->count(), $max); + }); + } + + public function settleCronjob(): array + { + $query = Claim::query()->select(['uid'])->groupBy('uid'); + $size = 10000; + $page = 1; + $successCount = $failCount = 0; + while (true) { + $logPrefix = "page: $page, size: $size"; + $result = (clone $query)->forPage($page, $size)->get(); + if ($result->isEmpty()) { + do_log("$logPrefix, no more data..."); + break; + } + foreach ($result as $row) { + $uid = $row->uid; + do_log("$logPrefix, begin to settle user: $uid..."); + $result = $this->settleUser($row->uid); + do_log("$logPrefix, settle user: $uid done!, result: " . var_export($result, true)); + if ($result) { + $successCount++; + } else { + $failCount++; + } + } + $page++; + } + return ['success_count' => $successCount, 'fail_count' => $failCount]; + } + + public function settleUser($uid, $force = false, $test = false): bool + { + $user = User::query()->with('language')->findOrFail($uid); + $list = Claim::query()->where('uid', $uid)->with(['snatch'])->get(); + $now = Carbon::now(); + $startOfThisMonth = $now->clone()->startOfMonth(); + $seedTimeRequiredHours = Claim::getConfigStandardSeedTimeHours(); + $uploadedRequiredTimes = Claim::getConfigStandardUploadedTimes(); + $bonusMultiplier = Claim::getConfigBonusMultiplier(); + $bonusDeduct = Claim::getConfigRemoveDeductBonus(); + $reachedTorrentIdArr = $unReachedTorrentIdArr = $remainTorrentIdArr = $unReachedIdArr = $toUpdateIdArr = []; + $totalSeedTime = 0; + $seedTimeCaseWhen = $uploadedCaseWhen = []; + do_log( + "uid: $uid, claim torrent count: " . $list->count() + . ", seedTimeRequiredHours: $seedTimeRequiredHours" + . ", uploadedRequiredTimes: $uploadedRequiredTimes" + . ", bonusMultiplier: $bonusMultiplier" + . ", bonusDeduct: $bonusDeduct" + ); + foreach ($list as $row) { + if ($row->last_settle_at && $row->last_settle_at->gte($startOfThisMonth)) { + do_log("ID: {$row->id} already settle", 'alert'); + if (!$force) { + do_log("No force, return", 'alert'); + return false; + } + } + if ( + bcsub($row->snatch->seedtime, $row->seed_time_begin) >= $seedTimeRequiredHours * 3600 + || bcsub($row->snatch->uploaded, $row->uploaded_begin) >= $uploadedRequiredTimes * $row->torrent->size + ) { + do_log("[REACHED], uid: $uid, torrent: " . $row->torrent_id); + $reachedTorrentIdArr[] = $row->torrent_id; + $toUpdateIdArr[] = $row->id; + $totalSeedTime += bcsub($row->snatch->seedtime, $row->seed_time_begin); + $seedTimeCaseWhen[] = sprintf('when %s then %s', $row->id, $row->snatch->seedtime); + $uploadedCaseWhen[] = sprintf('when %s then %s', $row->id, $row->snatch->uploaded); + } else { + $targetStartOfMonth = $row->created_at->startOfMonth(); + if ($startOfThisMonth->diffInMonths($targetStartOfMonth) > 1) { + do_log("[UNREACHED_REMOVE], uid: $uid, torrent: " . $row->torrent_id); + $unReachedIdArr[] = $row->id; + $unReachedTorrentIdArr = $row->torrent_id; + } else { + do_log("[UNREACHED_FIRST_MONTH], uid: $uid, torrent: " . $row->torrent_id); + $seedTimeCaseWhen[] = sprintf('when %s then %s', $row->id, $row->snatch->seedtime); + $uploadedCaseWhen[] = sprintf('when %s then %s', $row->id, $row->snatch->uploaded); + $toUpdateIdArr[] = $row->id; + $remainTorrentIdArr[] = $row->torrent_id; + } + } + } + $bonusResult = calculate_seed_bonus($uid, $reachedTorrentIdArr); + $seedTimeHoursAvg = $totalSeedTime / (count($reachedTorrentIdArr) ?: 1) / 3600; + do_log(sprintf( + "reachedTorrentIdArr: %s, unReachedIdArr: %s, bonusResult: %s, seedTimeHours: %s", + json_encode($reachedTorrentIdArr), json_encode($unReachedIdArr), json_encode($bonusResult), $seedTimeHoursAvg + ), 'alert'); + $bonusFinal = $bonusResult['seed_bonus'] * $seedTimeHoursAvg * $bonusMultiplier; + do_log("bonus final: $bonusFinal", 'alert'); + + $totalDeduct = $bonusDeduct * count($unReachedIdArr); + do_log("totalDeduct: $totalDeduct", 'alert'); + + /** + * Just do a test, debug from log + */ + if ($test) { + do_log("[TEST], return"); + return true; + } + + //Increase user bonus + User::query()->where('id', $uid)->increment('seedbonus', $bonusFinal); + do_log("Increase user bonus: $bonusFinal", 'alert'); + + //Handle unreached + if (!empty($unReachedIdArr)) { + Claim::query()->whereIn('id', $unReachedIdArr)->delete(); + User::query()->where('id', $uid)->decrement('seedbonus', $totalDeduct); + do_log("Deduct user bonus: $totalDeduct", 'alert'); + } + + //Update claim `last_settle_at` and init `seed_time_begin` & `uploaded_begin` + $sql = sprintf( + "update claims set uploaded_begin = case id %s end, seed_time_begin = case id %s end, last_settle_at = '%s', updated_at = '%s' where id in (%s)", + implode(' ', $uploadedCaseWhen), implode(' ', $seedTimeCaseWhen), $now->toDateTimeString(), $now->toDateTimeString(), implode(',', $toUpdateIdArr) + ); + $affectedRows = DB::update($sql); + do_log("query: $sql, affectedRows: $affectedRows"); + + //Send message + $torrentInfo = Torrent::query() + ->whereIn('id', array_merge($reachedTorrentIdArr, $unReachedTorrentIdArr, $remainTorrentIdArr)) + ->get(Torrent::$commentFields) + ->keyBy('id') + ; + $msg = []; + $locale = $user->locale; + $msg[] = nexus_trans('claim.msg_title', ['month' => $now->clone()->subMonths(1)->format('Y-m')], $locale); + $msg[] = nexus_trans('claim.claim_total', [ 'total' => $list->count()], $locale); + + $reachList = collect($reachedTorrentIdArr)->map( + fn($item) => sprintf("[url=details.php?id=%s]%s[/url]", $item, $torrentInfo->get($item)->name) + )->implode("\n"); + $msg[] = nexus_trans("claim.claim_reached_counts", ['counts' => count($reachedTorrentIdArr)], $locale) . "\n$reachList"; + $msg[] = nexus_trans( + "claim.claim_reached_summary", [ + 'bonus_per_hour' => number_format($bonusResult['seed_bonus'], 2), + 'hours'=> number_format($seedTimeHoursAvg, 2), + 'bonus_total'=> number_format($bonusFinal, 2) + ], $locale + ); + + $remainList = collect($remainTorrentIdArr)->map( + fn($item) => sprintf("[url=details.php?id=%s]%s[/url]", $item, $torrentInfo->get($item)->name) + )->implode("\n"); + $msg[] = nexus_trans("claim.claim_unreached_remain_counts", ['counts' => count($remainTorrentIdArr)], $locale) . "\n$remainList"; + + $unReachList = collect($unReachedTorrentIdArr)->map( + fn($item) => sprintf("[url=details.php?id=%s]%s[/url]", $item, $torrentInfo->get($item)->name) + )->implode("\n"); + $msg[] = nexus_trans("claim.claim_unreached_remove_counts", ['counts' => count($unReachedTorrentIdArr)], $locale) . "\n$unReachList"; + if ($totalDeduct) { + $msg[] = nexus_trans( + "claim.claim_unreached_summary", [ + 'deduct_per_torrent '=> number_format($bonusDeduct, 2), + 'deduct_total' => number_format($totalDeduct, 2) + ], $locale + ); + } + + $message = [ + 'receiver' => $uid, + 'added' => $now, + 'subject' => nexus_trans('claim.msg_subject', ['month' => $now->clone()->subMonths(1)->format('Y-m')], $locale), + 'msg' => implode("\n\n", $msg), + ]; + Message::query()->insert($message); + + do_log("[DONE], cost time: " . (time() - $now->timestamp) . " seconds"); + return true; + } +} diff --git a/app/Repositories/TorrentRepository.php b/app/Repositories/TorrentRepository.php index 0a1385bb..b49f9bb0 100644 --- a/app/Repositories/TorrentRepository.php +++ b/app/Repositories/TorrentRepository.php @@ -5,6 +5,7 @@ namespace App\Repositories; use App\Exceptions\NexusException; use App\Models\AudioCodec; use App\Models\Category; +use App\Models\Claim; use App\Models\Codec; use App\Models\HitAndRun; use App\Models\Media; diff --git a/database/migrations/2022_05_04_234639_create_claims_table.php b/database/migrations/2022_05_04_234639_create_claims_table.php new file mode 100644 index 00000000..d85059cd --- /dev/null +++ b/database/migrations/2022_05_04_234639_create_claims_table.php @@ -0,0 +1,38 @@ +id(); + $table->integer('uid'); + $table->integer('torrent_id')->index(); + $table->integer('snatched_id')->index(); + $table->bigInteger('seed_time_begin')->default(0); + $table->bigInteger('uploaded_begin')->default(0); + $table->dateTime('last_settle_at')->nullable(); + $table->timestamps(); + $table->unique(['uid', 'torrent_id']); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('claims'); + } +}; diff --git a/include/constants.php b/include/constants.php index d057b281..11bc754c 100644 --- a/include/constants.php +++ b/include/constants.php @@ -1,6 +1,6 @@ Torrents seeding Torrents leeching   H&R: %s]', (new \App\Repositories\HitAndRunRepository())->getStatusStats($CURUSER['id']))?> + %s]', $CURUSER['id'], (new \App\Repositories\ClaimRepository())->getStats($CURUSER['id']))?> = UC_SYSOP) { ?> [] @@ -2953,6 +2954,7 @@ function deletetorrent($id) { sql_query("DELETE FROM $x WHERE torrent = ".mysql_real_escape_string($id)); } sql_query("DELETE FROM hit_and_runs WHERE torrent_id = ".mysql_real_escape_string($id)); + sql_query("DELETE FROM claims WHERE torrent_id = ".mysql_real_escape_string($id)); unlink(getFullDirectory("$torrent_dir/$id.torrent")); } @@ -5542,10 +5544,11 @@ function get_smile($num) * Calculate user seed bonus per hour * * @param $uid + * @param $torrentIdArr * @return array * @throws \Nexus\Database\DatabaseException */ -function calculate_seed_bonus($uid): array +function calculate_seed_bonus($uid, $torrentIdArr = null): array { $settingBonus = \App\Models\Setting::get('bonus'); $donortimes_bonus = $settingBonus['donortimes']; @@ -5567,9 +5570,15 @@ function calculate_seed_bonus($uid): array $A = 0; $count = $torrent_peer_count = 0; - $logPrefix = "[CALCULATE_SEED_BONUS], uid: $uid"; - - $sql = "select torrents.id, torrents.added, torrents.size, torrents.seeders, peers.id as peerID from torrents LEFT JOIN peers ON peers.torrent = torrents.id WHERE peers.userid = $uid AND peers.seeder ='yes' group by peers.torrent, peers.peer_id"; + $logPrefix = "[CALCULATE_SEED_BONUS], uid: $uid, torrentIdArr: " . json_encode($torrentIdArr); + $whereTorrent = ''; + if ($torrentIdArr !== null) { + if (empty($torrentIdArr)) { + $torrentIdArr = [-1]; + } + $whereTorrent = sprintf("and peers.torrent in (%s)", implode(',', $torrentIdArr)); + } + $sql = "select torrents.id, torrents.added, torrents.size, torrents.seeders, peers.id as peerID from torrents LEFT JOIN peers ON peers.torrent = torrents.id WHERE peers.userid = $uid AND peers.seeder ='yes' $whereTorrent group by peers.torrent, peers.peer_id"; $torrentResult = \Nexus\Database\NexusDB::select($sql); do_log("$logPrefix, sql: $sql, count: " . count($torrentResult)); foreach ($torrentResult as $torrent) diff --git a/lang/chs/lang_claim.php b/lang/chs/lang_claim.php new file mode 100644 index 00000000..b04e891f --- /dev/null +++ b/lang/chs/lang_claim.php @@ -0,0 +1,16 @@ + '种子认领详情', + 'title_for_user' => '用户认领种子详情', + 'th_id' => 'ID', + 'th_username' => '用户', + 'th_torrent_name' => '种子名称', + 'th_torrent_size' => '种子大小', + 'th_torrent_ttl' => '种子存活', + 'th_claim_at' => '认领时间', + 'th_last_settle' => '上次结算时间', + 'th_seed_time_this_month' => '本月做种时间', + 'th_uploaded_this_month' => '本月上传量', + 'th_reached_or_not' => '本月是否达标', +]; diff --git a/lang/chs/lang_clients.php b/lang/chs/lang_clients.php deleted file mode 100644 index 9ee2bc84..00000000 --- a/lang/chs/lang_clients.php +++ /dev/null @@ -1,41 +0,0 @@ - '客户端管理', - 'text_manage' => '管理', - 'text_add' => '添加', - 'text_client' => '客户端', - 'text_delete' => '删除', - 'text_edit' => '编辑', - 'col_id' => 'ID', - 'col_name' => 'Name', - 'col_name_help' => '仅允许数字、字母、下划线', - 'col_label' => '显示标签', - 'col_type' => '类型', - 'col_required' => '不能为空', - 'col_help' => '辅助说明', - 'col_options' => '选项', - 'col_options_help' => '类型为单选、多选、下拉时必填,一行一个,格式:选项值|选项描述文本', - 'col_action' => '操作', - 'col_is_single_row' => '展示时单独一行', - 'col_family' => '家族', - 'col_start_name' => '起始名称', - 'col_peer_id_pattern' => 'Peer 正则', - 'col_peer_id_match_num' => 'Peer 匹配次数', - 'col_peer_id_matchtype' => 'Peer 匹配类型', - 'col_peer_id_start' => 'Peer 起始', - 'col_agent_pattern' => 'Agent 正则', - 'col_agent_match_num' => 'Agent 匹配次数', - 'col_agent_matchtype' => 'Agent 匹配类型', - 'col_agent_start' => 'Agent 起始', - - 'js_sure_to_delete_this' => '你确信要删除此项目吗?', - 'submit_submit' => '提交', - 'client_type_text' => '短文本', - 'client_type_textarea' => '长文本', - 'client_type_radio' => '横向单选', - 'client_type_checkbox' => '横向多选', - 'client_type_select' => '下拉单选', - 'client_type_image' => '图片', - -]; \ No newline at end of file diff --git a/lang/chs/lang_details.php b/lang/chs/lang_details.php index 12d1fc4e..a144efe5 100644 --- a/lang/chs/lang_details.php +++ b/lang/chs/lang_details.php @@ -231,6 +231,12 @@ $lang_details = array 'magic_show_all_description' => '查看详单', 'magic_haveGotBonus' => '目前发布人已获得Number个魔力值奖励。', 'magic_have_no_enough_bonus_value' => '需要更多魔力值。', + 'claim_already' => '已认领', + 'claim_now' => '认领', + 'claim_info' => '已被 %s 个用户认领,剩余 %s 个名额。', + 'claim_detail' => '认领详情', + 'claim_label' => '认领种子', + 'claim_confirm' => '确定要认领此种子吗?', ); ?> diff --git a/lang/chs/lang_functions.php b/lang/chs/lang_functions.php index 2509a83e..035f8e3e 100644 --- a/lang/chs/lang_functions.php +++ b/lang/chs/lang_functions.php @@ -295,8 +295,8 @@ $lang_functions = array 'text_thirty_percent_down' => "30%", 'text_please_download_something_within' => "请在", 'text_inactive_account_be_deleted' => "内做些下载。没有流量的用户会被删除账号。", - 'text_attendance' => '签到得魔力', - 'text_attended' => '(签到已得%u, 补签卡:%d)', + 'text_attendance' => '[签到得魔力]', + 'text_attended' => '[签到已得%u, 补签卡:%d]', 'imdb_cache_dir_can_not_create' => 'imdb 缓存目录无法创建', 'imdb_cache_dir_is_not_writeable' => 'imdb 缓存目录不可写', 'imdb_photo_dir_can_not_create' => 'imdb 图片目录无法创建', @@ -316,6 +316,7 @@ $lang_functions = array 'text_seed_points' => '做种积分', 'spoiler_expand_collapse' => '点击展开/收缩', 'spoiler_default_title' => '折叠内容', + 'menu_claim' => '认领: ', ); ?> diff --git a/lang/chs/lang_settings.php b/lang/chs/lang_settings.php index 37f564f6..9ffcd81e 100644 --- a/lang/chs/lang_settings.php +++ b/lang/chs/lang_settings.php @@ -744,6 +744,14 @@ $lang_settings = array 'row_default_user_two' => '', 'row_show_top_uploader' => '显示最多上传(种子数)', 'text_show_top_uploader_note' => "默认'否'。在首页显示最多上传的用户(按种子数计算)。", + 'claim_label' => '种子认领', + 'claim_torrent_ttl' => '种子发布 %s 天后可以认领。', + 'claim_torrent_user_counts_up_limit' => '一个种子最多可以被 %s 个用户认领。', + 'claim_user_torrent_counts_up_limit' => '一个用户最多可以认领 %s 个种子。', + 'claim_remove_deduct_user_bonus' => '种子不达标时将被删除并扣除用户 %s 魔力(非认领首月)。', + 'claim_give_up_deduct_user_bonus' => '用户主动放弃认领扣除用户 %s 魔力。', + 'claim_reach_standard' => '达标标准:每月做种时间大于等于 %s 小时, 或上传量大于等于其体积 %s 倍。', + 'claim_bonus_multiplier' => '计算达标种子魔力奖励是正常魔力值的 %s 倍。', ); ?> diff --git a/lang/cht/lang_details.php b/lang/cht/lang_details.php index 3bdc7da8..895fb753 100644 --- a/lang/cht/lang_details.php +++ b/lang/cht/lang_details.php @@ -230,6 +230,12 @@ $lang_details = array 'magic_show_all_description' => '查看詳單', 'magic_haveGotBonus' => '目前發佈人已獲得Number個魔力值獎勵。', 'magic_have_no_enough_bonus_value' => '需要更多魔力值。', + 'claim_already' => '已認領', + 'claim_now' => '認領', + 'claim_info' => '已被 %s 個用戶認領,剩余 %s 個名額。', + 'claim_detail' => '認領詳情', + 'claim_label' => '認領種子', + 'claim_confirm' => '確定要認領此種子嗎?', ); ?> diff --git a/lang/cht/lang_functions.php b/lang/cht/lang_functions.php index 0936fe9d..d8983a3f 100644 --- a/lang/cht/lang_functions.php +++ b/lang/cht/lang_functions.php @@ -297,8 +297,8 @@ $lang_functions = array 'text_thirty_percent_down' => "30%", 'text_please_download_something_within' => "請在", 'text_inactive_account_be_deleted' => "內做些下載。沒有流量的用戶會被移除賬號。", - 'text_attendance' => '簽到得魔力', - 'text_attended' => '(簽到已得%u, 補簽卡:%d)', + 'text_attendance' => '[簽到得魔力]', + 'text_attended' => '[簽到已得%u, 補簽卡:%d]', 'text_pt_gen_douban_url_note' => "(來自 douban 的鏈接。如電影 Transformers 的鏈接是 https://movie.douban.com/subject/1794171/)", 'row_pt_gen_imdb_url' => "PT-Gen imdb 鏈接", 'text_pt_gen_imdb_url_note' => "(來自 imdb 的鏈接。如電影 Transformers 的鏈接是 https://www.imdb.com/title/tt0418279/)", @@ -323,6 +323,7 @@ $lang_functions = array 'text_seed_points' => '做種積分', 'spoiler_expand_collapse' => '點擊展開/收縮', 'spoiler_default_title' => '折疊內容', + 'menu_claim' => '認領: ', ); ?> diff --git a/lang/cht/lang_settings.php b/lang/cht/lang_settings.php index 51eb7ebc..f5e0beca 100644 --- a/lang/cht/lang_settings.php +++ b/lang/cht/lang_settings.php @@ -738,6 +738,19 @@ $lang_settings = array 'row_site_language_enabled' => '站點啟用語言', 'text_site_language_enabled_note' => '選擇站點啟用的語言', 'keep_at_least_one' => '至少保留一個', + 'text_alias' => '等級別名:', + 'row_default_user_one' => '默認為', + 'row_default_user_two' => '', + 'row_show_top_uploader' => '顯示最多上傳(種子數)', + 'text_show_top_uploader_note' => "默認'否'。在首頁顯示最多上傳的用戶(按種子數計算)。", + 'claim_label' => '種子認領', + 'claim_torrent_ttl' => '種子發布 %s 天後可以認領。', + 'claim_torrent_user_counts_up_limit' => '一個種子最多可以被 %s 個用戶認領。', + 'claim_user_torrent_counts_up_limit' => '一個用戶最多可以認領 %s 個種子。', + 'claim_remove_deduct_user_bonus' => '種子不達標時將被刪除並扣除用戶 %s 魔力(非認領首月)。', + 'claim_give_up_deduct_user_bonus' => '用戶主動放棄認領扣除用戶 %s 魔力。', + 'claim_reach_standard' => '達標標準:每月做種時間大於等於 %s 小時, 或上傳量大於等於其體積 %s 倍。', + 'claim_bonus_multiplier' => '計算達標種子魔力獎勵是正常魔力值的 %s 倍。', ); ?> diff --git a/lang/en/lang_details.php b/lang/en/lang_details.php index dc88ae7e..b3624fef 100644 --- a/lang/en/lang_details.php +++ b/lang/en/lang_details.php @@ -230,6 +230,12 @@ $lang_details = array 'magic_show_all_description' => 'View details of a single', 'magic_haveGotBonus' => 'Publisher now has been got Number Bonus of award.', 'magic_have_no_enough_bonus_value' => 'more points needed', + 'claim_already' => 'Claimed', + 'claim_now' => 'Claim', + 'claim_info' => 'Already claimed by %s users, %s place left.', + 'claim_detail' => 'Claim detail', + 'claim_label' => 'Claim torrent', + 'claim_confirm' => 'Are you sure to claim this torrent?', ); diff --git a/lang/en/lang_functions.php b/lang/en/lang_functions.php index 7a5a3690..6ef014db 100644 --- a/lang/en/lang_functions.php +++ b/lang/en/lang_functions.php @@ -297,8 +297,8 @@ $lang_functions = array 'text_thirty_percent_down' => "30%", 'text_please_download_something_within' => "Please download something within ", 'text_inactive_account_be_deleted' => ". Inactive accounts (with no transfer amount) will be deleted.", - 'text_attendance' => 'Attend get bouns', - 'text_attended' => '(Attend got bouns %u, card:%d)', + 'text_attendance' => '[Attend get bouns]', + 'text_attended' => '[Attend got bouns %u, card:%d]', 'row_pt_gen_douban_url' => "PT-Gen douban link", 'text_pt_gen_douban_url_note' => "(URL taken from douban. e.g. for movie Transformers the URL is https://movie.douban.com/subject/1794171//)", 'row_pt_gen_imdb_url' => "PT-Gen imdb link", @@ -324,6 +324,7 @@ $lang_functions = array 'text_seed_points' => 'Seed points', 'spoiler_expand_collapse' => 'Click to expand/collapse', 'spoiler_default_title' => 'Collapse content', + 'menu_claim' => 'Claim: ', ); ?> diff --git a/lang/en/lang_settings.php b/lang/en/lang_settings.php index a7dd3b16..7339c24f 100644 --- a/lang/en/lang_settings.php +++ b/lang/en/lang_settings.php @@ -738,6 +738,19 @@ $lang_settings = array 'row_site_language_enabled' => 'Site enabled language', 'text_site_language_enabled_note' => 'Select site enabled language', 'keep_at_least_one' => 'Keep at least one', + 'text_alias' => 'Class alias: ', + 'row_default_user_one' => 'Default is', + 'row_default_user_two' => '', + 'row_show_top_uploader' => 'Show top uploaded(Torrent count)', + 'text_show_top_uploader_note' => "Default 'No'. Show top upload user(Torrent count) at homepage.", + 'claim_label' => 'Torrent claim', + 'claim_torrent_ttl' => 'Torrent can be claimed after %s of days of release.', + 'claim_torrent_user_counts_up_limit' => 'A Torrent can be claimed by up to %s of users.', + 'claim_user_torrent_counts_up_limit' => 'A user can claim up to %s of torrents.', + 'claim_remove_deduct_user_bonus' => "Claimed torrent will be deleted and %s of the user's bonus will be deducted if they do not meet the standard (not the first month of claiming).", + 'claim_give_up_deduct_user_bonus' => 'User actively gives up claiming deduct user %s bonus.', + 'claim_reach_standard' => 'Standard: Monthly seeding time greater than or equal to %s of hours, or uploaded greater than or equal to %s times its size.', + 'claim_bonus_multiplier' => 'Calculate %s times the normal bonus value of the attained seed bonus.', ); ?> diff --git a/nexus/Install/settings.default.php b/nexus/Install/settings.default.php index ea3e175a..802af786 100644 --- a/nexus/Install/settings.default.php +++ b/nexus/Install/settings.default.php @@ -322,6 +322,14 @@ return array ( 'minvotes' => '10', 'sticky_first_level_background_color' => '#89c9e6', 'sticky_second_level_background_color' => '#aadbf3', + 'claim_torrent_ttl' => \App\Models\Claim::TORRENT_TTL, + 'claim_torrent_user_counts_up_limit' => \App\Models\Claim::USER_UP_LIMIT, + 'claim_user_torrent_counts_up_limit' => \App\Models\Claim::TORRENT_UP_LIMIT, + 'claim_remove_deduct_user_bonus' => \App\Models\Claim::REMOVE_DEDUCT, + 'claim_give_up_deduct_user_bonus' => \App\Models\Claim::GIVE_UP_DEDUCT, + 'claim_bonus_multiplier' => \App\Models\Claim::BONUS_MULTIPLIER, + 'claim_reach_standard_seed_time' => \App\Models\Claim::STANDARD_SEED_TIME_HOURS, + 'claim_reach_standard_uploaded' => \App\Models\Claim::STANDARD_UPLOADED_TIMES, ), 'attachment' => array ( diff --git a/public/ajax.php b/public/ajax.php index 87724836..5c2ef046 100644 --- a/public/ajax.php +++ b/public/ajax.php @@ -47,3 +47,17 @@ function getPtGen($params) } } +function addClaim($params) +{ + global $CURUSER; + $rep = new \App\Repositories\ClaimRepository(); + return $rep->store($CURUSER['id'], $params['torrent_id']); +} + +function removeClaim($params) +{ + global $CURUSER; + $rep = new \App\Repositories\ClaimRepository(); + return $rep->delete($params['id'], $CURUSER['id']); +} + diff --git a/public/claim.php b/public/claim.php new file mode 100644 index 00000000..effe1d84 --- /dev/null +++ b/public/claim.php @@ -0,0 +1,105 @@ +where('id', $torrentId)->first(\App\Models\Torrent::$commentFields); + if (!$torrent) { + stderr("Error", "Invalid torrent_id: $torrentId"); + } + stdhead(nexus_trans('claim.title_for_torrent')); + $query = \App\Models\Claim::query()->where('torrent_id', $torrentId); + $pagerParam = "?torrent_id=$torrentId"; + print("

".nexus_trans('claim.title_for_torrent') . " ".htmlspecialchars($torrent['name'])."

"); +} elseif (!empty($_GET['uid'])) { + $uid = $_GET['uid']; + int_check($uid,true); + $user = \App\Models\User::query()->where('id', $uid)->first(\App\Models\User::$commonFields); + if (!$user) { + stderr("Error", "Invalid uid: $uid"); + } + stdhead(nexus_trans('claim.title_for_user')); + $query = \App\Models\Claim::query()->where('uid', $uid); + $pagerParam = "?uid=$uid"; + print("

".nexus_trans('claim.title_for_user') . " ".htmlspecialchars($user->username)."

"); + if ($uid == $CURUSER['id']) { + $actionTh = sprintf("%s", nexus_trans("claim.th_action")); + $actionTd = ""; + $confirmMsg = nexus_trans('claim.confirm_give_up'); + $removeJs = <<count(); +list($pagertop, $pagerbottom, $limit, $offset, $pageSize) = pager(50, $total, $pagerParam); +$list = (clone $query)->with(['user', 'torrent', 'snatch'])->get(); +print(""); +print(" + + + + + + + + + + + ".$actionTh." +"); +$now = \Carbon\Carbon::now(); +$seedTimeRequiredHours = \App\Models\Claim::getConfigStandardSeedTimeHours(); +$uploadedRequiredTimes = \App\Models\Claim::getConfigStandardUploadedTimes(); +foreach ($list as $row) { + if ( + bcsub($row->snatch->seedtime, $row->seed_time_begin) >= $seedTimeRequiredHours * 3600 + || bcsub($row->snatch->uploaded, $row->uploaded_begin) >= $uploadedRequiredTimes * $row->torrent->size + ) { + $reached = 'Yes'; + } else { + $reached = 'No'; + } + print(" + + + + + + + + + + + ".sprintf($actionTd, $row->id)." + "); +} + +print("
".nexus_trans('claim.th_id')."".nexus_trans('claim.th_username')."".nexus_trans('claim.th_torrent_name')."".nexus_trans('claim.th_torrent_size')."".nexus_trans('claim.th_torrent_ttl')."".nexus_trans('claim.th_claim_at')."".nexus_trans('claim.th_last_settle')."".nexus_trans('claim.th_seed_time_this_month')."".nexus_trans('claim.th_uploaded_this_month')."".nexus_trans('claim.th_reached_or_not')."
" . $row->id . "" . $row->user->username . "" . $row->torrent->name . "" . mksize($row->torrent->size) . "" . mkprettytime($row->torrent->added->diffInSeconds($now)) . "" . format_datetime($row->created_at) . "" . format_datetime($row->last_settle_at) . "" . mkprettytime($row->snatch->seedtime - $row->seed_time_begin) . "" . mksize($row->snatch->uploaded - $row->uploaded_begin) . "" . $reached . "
"); +print($pagerbottom); +end_main_frame(); +stdfoot(); + + diff --git a/public/details.php b/public/details.php index 9eea10e0..d14670a3 100644 --- a/public/details.php +++ b/public/details.php @@ -132,7 +132,52 @@ if (!$row) { $download = "\"download\" ".$lang_details['text_download_torrent']." | "; else $download = ""; - tr($lang_details['row_action'], $download. ($owned == 1 ? "<$editlink>\"edit\" ".$lang_details['text_edit_torrent'] . " | " : ""). (get_user_class() >= $askreseed_class && $row['seeders'] == 0 ? "\"reseed\" ".$lang_details['text_ask_for_reseed'] ." | " : "") . "\"report\" ".$lang_details['text_report_torrent']."", 1); + tr( + $lang_details['row_action'], + $download.($owned == 1 ? "<$editlink>\"edit\" ".$lang_details['text_edit_torrent'] . " | " : "") + .(get_user_class() >= $askreseed_class && $row['seeders'] == 0 ? "\"reseed\" ".$lang_details['text_ask_for_reseed'] ." | " : "") + ."\"report\" ".$lang_details['text_report_torrent']."" + , 1 + ); + + // ------------- start claim block ------------------// + $claimTorrentTTL = \App\Models\Claim::getConfigTorrentTTL(); + if (\Carbon\Carbon::parse($row['added'])->addDays($claimTorrentTTL)->lte(\Carbon\Carbon::now())) { + $baseClaimQuery = \App\Models\Claim::query()->where('torrent_id', $id); + $claimCounts = (clone $baseClaimQuery)->count(); + $isClaimed = (clone $baseClaimQuery)->where('uid', $CURUSER['id'])->exists(); + if ($isClaimed) { + $inputValue = $lang_details['claim_already']; + $disabled = ' disabled'; + } else { + $inputValue = $lang_details['claim_now']; + $disabled = ''; + $claimJs = <<', $inputValue, $id, $disabled); + $y .= sprintf(' ' . $lang_details['claim_info'], $claimCounts, bcsub($maxUserCounts, $claimCounts)); + $y .= sprintf(' '.$lang_details['claim_detail'].'', $id); + tr($lang_details['claim_label'], $y, 1); + } + // ------------- end claim block ------------------// + tr($lang_details['torrent_dl_url'],sprintf('%s',$lang_details['torrent_dl_url_notice'], getSchemeAndHttpHost(), $CURUSER['id'], $torrentRep->encryptDownHash($row['id'], $CURUSER), $lang_details['torrent_dl_url_text']),1); // ---------------- start subtitle block -------------------// diff --git a/public/settings.php b/public/settings.php index d4efadee..a4a26bcf 100644 --- a/public/settings.php +++ b/public/settings.php @@ -150,7 +150,8 @@ elseif($action == 'savesettings_torrent') // save account 'expirefree','expiretwoup','expiretwoupfree','expiretwouphalfleech', 'expirenormal','hotdays','hotseeder','halfleechbecome','freebecome', 'twoupbecome','twoupfreebecome', 'twouphalfleechbecome','normalbecome','uploaderdouble','deldeadtorrent', 'randomthirtypercentdown', 'thirtypercentleechbecome', 'expirethirtypercentleech', 'sticky_first_level_background_color', 'sticky_second_level_background_color', - 'download_support_passkey' + 'download_support_passkey', 'claim_torrent_ttl', 'claim_torrent_user_counts_up_limit', 'claim_user_torrent_counts_up_limit', 'claim_remove_deduct_user_bonus', + 'claim_give_up_deduct_user_bonus', 'claim_bonus_multiplier', 'claim_reach_standard_seed_time', 'claim_reach_standard_uploaded' ); GetVar($validConfig); $TORRENT = []; @@ -663,6 +664,17 @@ elseif ($action == 'torrentsettings')
  • ".$lang_settings['text_normal_will_become']."".$lang_settings['text_after']."".$lang_settings['text_normal_timeout_default']."
  • ".$lang_settings['text_promotion_timeout_note_two'], 1); + + tr($lang_settings['claim_label'], "
      +
    • ".sprintf($lang_settings['claim_torrent_ttl'], sprintf('', $TORRENT['claim_torrent_ttl'] ?? \App\Models\Claim::TORRENT_TTL))."
    • +
    • ".sprintf($lang_settings['claim_torrent_user_counts_up_limit'], sprintf('', $TORRENT['claim_torrent_user_counts_up_limit'] ?? \App\Models\Claim::USER_UP_LIMIT))."
    • +
    • ".sprintf($lang_settings['claim_user_torrent_counts_up_limit'], sprintf('', $TORRENT['claim_user_torrent_counts_up_limit'] ?? \App\Models\Claim::TORRENT_UP_LIMIT))."
    • +
    • ".sprintf($lang_settings['claim_remove_deduct_user_bonus'], sprintf('', $TORRENT['claim_remove_deduct_user_bonus'] ?? \App\Models\Claim::REMOVE_DEDUCT))."
    • +
    • ".sprintf($lang_settings['claim_give_up_deduct_user_bonus'], sprintf('', $TORRENT['claim_give_up_deduct_user_bonus'] ?? \App\Models\Claim::GIVE_UP_DEDUCT))."
    • +
    • ".sprintf($lang_settings['claim_bonus_multiplier'], sprintf('', $TORRENT['claim_bonus_multiplier'] ?? \App\Models\Claim::BONUS_MULTIPLIER))."
    • +
    • ".sprintf($lang_settings['claim_reach_standard'], sprintf('', $TORRENT['claim_reach_standard_seed_time'] ?? \App\Models\Claim::STANDARD_SEED_TIME_HOURS), sprintf('', $TORRENT['claim_reach_standard_uploaded'] ?? \App\Models\Claim::STANDARD_UPLOADED_TIMES))."
    • +
    ", 1); + tr($lang_settings['row_auto_pick_hot'], $lang_settings['text_torrents_uploaded_within']."".$lang_settings['text_days_with_more_than']."".$lang_settings['text_be_picked_as_hot']."
    ".$lang_settings['text_auto_pick_hot_default'], 1); tr($lang_settings['row_uploader_get_double'], $lang_settings['text_torrent_uploader_gets']."".$lang_settings['text_times_uploading_credit'].$lang_settings['text_uploader_get_double_default'], 1); tr($lang_settings['row_delete_dead_torrents'], $lang_settings['text_torrents_being_dead_for']."".$lang_settings['text_days_be_deleted']."
    ".$lang_settings['row_delete_dead_torrents_note'], 1); diff --git a/resources/lang/en/claim.php b/resources/lang/en/claim.php new file mode 100644 index 00000000..a33dc293 --- /dev/null +++ b/resources/lang/en/claim.php @@ -0,0 +1,28 @@ + 'Torrent claim detail', + 'title_for_user' => 'User claim detail', + 'th_id' => 'ID', + 'th_username' => 'User', + 'th_torrent_name' => 'Torrent name', + 'th_torrent_size' => 'Torrent size', + 'th_torrent_ttl' => 'Torrent TTL', + 'th_claim_at' => 'Claim at', + 'th_last_settle' => 'Last settle at', + 'th_seed_time_this_month' => 'Se. this month', + 'th_uploaded_this_month' => 'Up. this month', + 'th_reached_or_not' => 'Reached', + 'th_action' => 'Action', + + 'msg_title' => 'Claim settle result last month(:month):', + 'msg_subject' => ':month claim settlement', + 'claim_total' => 'Claim torrent total: :total', + 'claim_reached_counts' => 'Reached torrent counts: :counts', + 'claim_reached_summary' => 'Reached torrent get bonus per hour: :bonus_per_hour, seed time average(hour): :hours, get bonus total: :bonus_total', + 'claim_unreached_remain_counts' => 'Unreached torrent remain counts: :counts', + 'claim_unreached_remove_counts' => 'Unreached torrent remove counts: :counts', + 'claim_unreached_summary' => 'Deduct bonus every unreached torrent::deduct_per_torrent, total deduct: :deduct_total', + + 'confirm_give_up' => 'Are you sure you want to give up claiming this torrent?', +]; diff --git a/resources/lang/en/torrent.php b/resources/lang/en/torrent.php index 9d4947d1..240435d6 100644 --- a/resources/lang/en/torrent.php +++ b/resources/lang/en/torrent.php @@ -38,4 +38,8 @@ return [ 'classic' => 'Classic', 'recommended' => 'Recommend', ], + 'claim_already' => 'Claimed already', + 'no_snatch' => 'Never download this torrent yet', + 'can_no_be_claimed_yet' => 'Can not be claimed yet', + 'claim_number_reach_maximum' => 'The maximum number of torrent claimed is reached', ]; diff --git a/resources/lang/zh_CN/claim.php b/resources/lang/zh_CN/claim.php new file mode 100644 index 00000000..484af200 --- /dev/null +++ b/resources/lang/zh_CN/claim.php @@ -0,0 +1,28 @@ + '种子认领详情', + 'title_for_user' => '用户认领种子详情', + 'th_id' => 'ID', + 'th_username' => '用户', + 'th_torrent_name' => '种子名称', + 'th_torrent_size' => '种子大小', + 'th_torrent_ttl' => '种子存活', + 'th_claim_at' => '认领时间', + 'th_last_settle' => '上次结算时间', + 'th_seed_time_this_month' => '本月做种时间', + 'th_uploaded_this_month' => '本月上传量', + 'th_reached_or_not' => '本月是否达标', + 'th_action' => '操作', + + 'msg_title' => '上个月(:month)认领结算如下:', + 'msg_subject' => ':month 认领结算', + 'claim_total' => '认领种子数::total', + 'claim_reached_counts' => '达标数::counts', + 'claim_reached_summary' => '达标种子数每小时魔力::bonus_per_hour, 平均做种小时数::hours, 获得魔力::bonus_total', + 'claim_unreached_remain_counts' => '未达标保留数::counts', + 'claim_unreached_remove_counts' => '未达标删除数::counts', + 'claim_unreached_summary' => '未达标每个种子扣除魔力::deduct_per_torrent,总扣除魔力::deduct_total', + + 'confirm_give_up' => '确定要放弃认领此种子吗?', +]; diff --git a/resources/lang/zh_CN/torrent.php b/resources/lang/zh_CN/torrent.php index 52a67c2c..edcd3411 100644 --- a/resources/lang/zh_CN/torrent.php +++ b/resources/lang/zh_CN/torrent.php @@ -38,4 +38,8 @@ return [ 'classic' => '经典', 'recommended' => '推荐', ], + 'claim_already' => '此种子已经认领', + 'no_snatch' => '没有下载过此种子', + 'can_no_be_claimed_yet' => '还不能被认领', + 'claim_number_reach_maximum' => '认领种子数达到上限', ]; diff --git a/resources/lang/zh_TW/claim.php b/resources/lang/zh_TW/claim.php new file mode 100644 index 00000000..0b5ec93a --- /dev/null +++ b/resources/lang/zh_TW/claim.php @@ -0,0 +1,25 @@ + '種子認領詳情', + 'title_for_user' => '用戶認領種子詳情', + 'th_id' => 'ID', + 'th_username' => '用戶', + 'th_torrent_name' => '種子名稱', + 'th_torrent_size' => '種子大小', + 'th_torrent_ttl' => '種子存活', + 'th_claim_at' => '認領時間', + 'th_last_settle' => '上次結算時間', + 'th_seed_time_this_month' => '本月做種時間', + 'th_uploaded_this_month' => '本月上傳量', + 'th_reached_or_not' => '本月是否達標', + + 'msg_title' => '上個月(:month)認領結算如下:', + 'msg_subject' => ':month 認領結算', + 'claim_total' => '認領種子數::total', + 'claim_reached_counts' => '達標數::counts', + 'claim_reached_summary' => '達標種子數每小時魔力::bonus_per_hour, 平均做種小時數::hours, 獲得魔力::bonus_total', + 'claim_unreached_remain_counts' => '未達標保留數::counts', + 'claim_unreached_remove_counts' => '未達標刪除數::counts', + 'claim_unreached_summary' => '未達標每個種子扣除魔力::deduct_per_torrent,總扣除魔力::deduct_total', +]; diff --git a/resources/lang/zh_TW/torrent.php b/resources/lang/zh_TW/torrent.php index 2aba515b..0ffa56b4 100644 --- a/resources/lang/zh_TW/torrent.php +++ b/resources/lang/zh_TW/torrent.php @@ -38,4 +38,8 @@ return [ 'classic' => '經典', 'recommended' => '推薦', ], + 'claim_already' => '此種子已經認領', + 'no_snatch' => '沒有下載過此種子', + 'can_no_be_claimed_yet' => '還不能被認領', + 'claim_number_reach_maximum' => '認領種子數達到上限', ];