new feature: claim

This commit is contained in:
xiaomlove
2022-05-05 22:19:48 +08:00
parent 3990c74038
commit a739cf924e
30 changed files with 815 additions and 59 deletions

View File

@@ -0,0 +1,57 @@
<?php
namespace App\Console\Commands;
use App\Repositories\ClaimRepository;
use App\Repositories\ExamRepository;
use Illuminate\Console\Command;
class ClaimSettle extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'claim:settle {--uid=} {--force=}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Claim settle, options: --uid, --force';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$rep = new ClaimRepository();
$uid = $this->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;
}
}

View File

@@ -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);
}

79
app/Models/Claim.php Normal file
View File

@@ -0,0 +1,79 @@
<?php
namespace App\Models;
class Claim extends NexusModel
{
protected $fillable = ['uid', 'torrent_id', 'snatched_id', 'seed_time_begin', 'uploaded_begin', 'last_settle_at'];
public $timestamps = true;
const TORRENT_TTL = 30;
const USER_UP_LIMIT = 10;
const TORRENT_UP_LIMIT = 1000;
const REMOVE_DEDUCT = 600;
const GIVE_UP_DEDUCT = 400;
const BONUS_MULTIPLIER = 1;
const STANDARD_SEED_TIME_HOURS = 300;
const STANDARD_UPLOADED_TIMES = 2;
protected $casts = [
'last_settle_at' => '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);
}
}

View File

@@ -0,0 +1,267 @@
<?php
namespace App\Repositories;
use App\Models\BonusLogs;
use App\Models\Claim;
use App\Models\Message;
use App\Models\Setting;
use App\Models\Snatch;
use App\Models\Torrent;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use JetBrains\PhpStorm\ArrayShape;
use Nexus\Database\NexusDB;
class ClaimRepository extends BaseRepository
{
public function getList(array $params)
{
$query = Claim::query()->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;
}
}

View File

@@ -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;

View File

@@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('claims', function (Blueprint $table) {
$table->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');
}
};

View File

@@ -1,6 +1,6 @@
<?php
defined('VERSION_NUMBER') || define('VERSION_NUMBER', '1.7.8');
defined('RELEASE_DATE') || define('RELEASE_DATE', '2022-05-04');
defined('RELEASE_DATE') || define('RELEASE_DATE', '2022-05-05');
defined('IN_TRACKER') || define('IN_TRACKER', true);
defined('PROJECTNAME') || define("PROJECTNAME","NexusPHP");
defined('NEXUSPHPURL') || define("NEXUSPHPURL","https://nexusphp.org");

View File

@@ -2598,6 +2598,7 @@ else {
<font class='color_active'><?php echo $lang_functions['text_active_torrents'] ?></font> <img class="arrowup" alt="Torrents seeding" title="<?php echo $lang_functions['title_torrents_seeding'] ?>" src="pic/trans.gif" /><?php echo $activeseed?> <img class="arrowdown" alt="Torrents leeching" title="<?php echo $lang_functions['title_torrents_leeching'] ?>" src="pic/trans.gif" /><?php echo $activeleech?>&nbsp;&nbsp;
<font class='color_connectable'><?php echo $lang_functions['text_connectable'] ?></font><?php echo $connectable?> <?php echo maxslots();?>
<?php if(\App\Models\HitAndRun::getIsEnabled()) { ?><font class='color_bonus'>H&R: </font> <?php echo sprintf('[<a href="myhr.php">%s</a>]', (new \App\Repositories\HitAndRunRepository())->getStatusStats($CURUSER['id']))?><?php }?>
<font class='color_bonus'><?php echo $lang_functions['menu_claim']?></font> <?php echo sprintf('[<a href="claim.php?uid=%s">%s</a>]', $CURUSER['id'], (new \App\Repositories\ClaimRepository())->getStats($CURUSER['id']))?>
<?php if(get_user_class() >= UC_SYSOP) { ?> [<a href="/admin" target="_blank"><?php echo $lang_functions['text_management_system'] ?></a>]<?php }?>
</span>
</td>
@@ -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)

16
lang/chs/lang_claim.php Normal file
View File

@@ -0,0 +1,16 @@
<?php
$lang_claim = [
'title_for_torrent' => '种子认领详情',
'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' => '本月是否达标',
];

View File

@@ -1,41 +0,0 @@
<?php
$lang_clients = [
'client_management' => '客户端管理',
'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' => '图片',
];

View File

@@ -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' => '已被 <b>%s</b> 个用户认领,剩余 <b>%s</b> 个名额。',
'claim_detail' => '认领详情',
'claim_label' => '认领种子',
'claim_confirm' => '确定要认领此种子吗?',
);
?>

View File

@@ -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' => '认领: ',
);
?>

View File

@@ -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 倍。',
);
?>

View File

@@ -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' => '已被 <b>%s</b> 個用戶認領,剩余 <b>%s</b> 個名額。',
'claim_detail' => '認領詳情',
'claim_label' => '認領種子',
'claim_confirm' => '確定要認領此種子嗎?',
);
?>

View File

@@ -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' => "(來自 <strong><a href=\"https://www.douban.com/\">douban</a></strong> 的鏈接。如電影 <b>Transformers</b> 的鏈接是<b> https://movie.douban.com/subject/1794171/</b>)",
'row_pt_gen_imdb_url' => "PT-Gen imdb 鏈接",
'text_pt_gen_imdb_url_note' => "(來自 <strong><a href=\"https://www.imdb.com//\">imdb</a></strong> 的鏈接。如電影 <b>Transformers</b> 的鏈接是<b> https://www.imdb.com/title/tt0418279/</b>)",
@@ -323,6 +323,7 @@ $lang_functions = array
'text_seed_points' => '做種積分',
'spoiler_expand_collapse' => '點擊展開/收縮',
'spoiler_default_title' => '折疊內容',
'menu_claim' => '認領: ',
);
?>

View File

@@ -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 倍。',
);
?>

View File

@@ -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 <b>%s</b> users, <b>%s</b> place left.',
'claim_detail' => 'Claim detail',
'claim_label' => 'Claim torrent',
'claim_confirm' => 'Are you sure to claim this torrent?',
);

View File

@@ -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 <strong><a href=\"https://www.douban.com/\">douban</a></strong>. e.g.&nbsp;for movie <b>Transformers</b> the URL is <b> https://movie.douban.com/subject/1794171//</b>)",
'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: ',
);
?>

View File

@@ -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.',
);
?>

View File

@@ -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 (

View File

@@ -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']);
}

105
public/claim.php Normal file
View File

@@ -0,0 +1,105 @@
<?php
require "../include/bittorrent.php";
dbconn();
loggedinorreturn();
$torrentId = $uid = 0;
$actionTh = $actionTd = '';
if (!empty($_GET['torrent_id'])) {
$torrentId = $_GET['torrent_id'];
int_check($torrentId,true);
$torrent = \App\Models\Torrent::query()->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("<h1 align=center>".nexus_trans('claim.title_for_torrent') . "<a href=details.php?id=" . htmlspecialchars($torrentId) . "><b>&nbsp;".htmlspecialchars($torrent['name'])."</b></a></h1>");
} 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("<h1 align=center>".nexus_trans('claim.title_for_user') . "<a href=userdetails.php?id=" . htmlspecialchars($uid) . "><b>&nbsp;".htmlspecialchars($user->username)."</b></a></h1>");
if ($uid == $CURUSER['id']) {
$actionTh = sprintf("<td class='colhead' align='center'>%s</td>", nexus_trans("claim.th_action"));
$actionTd = "<td class='rowfollow nowrap' align='center'><input class='claim-remove' type='button' value='Remove' data-id='%s'></td>";
$confirmMsg = nexus_trans('claim.confirm_give_up');
$removeJs = <<<JS
jQuery("#claim-table").on("click", '.claim-remove', function () {
if (!window.confirm('$confirmMsg')) {
return
}
let params = {action: "removeClaim", params: {id: jQuery(this).attr("data-id")}}
jQuery.post('ajax.php', params, function (response) {
console.log(response)
if (response.ret == 0) {
location.reload()
} else {
window.alert(response.msg)
}
}, 'json')
})
JS;
\Nexus\Nexus::js($removeJs, 'footer', false);
}
} else {
stderr("Invalid parameters", "Require torrent_id or uid");
}
begin_main_frame();
$total = (clone $query)->count();
list($pagertop, $pagerbottom, $limit, $offset, $pageSize) = pager(50, $total, $pagerParam);
$list = (clone $query)->with(['user', 'torrent', 'snatch'])->get();
print("<table id='claim-table' width='100%'>");
print("<tr>
<td class='colhead' align='center'>".nexus_trans('claim.th_id')."</td>
<td class='colhead' align='center'>".nexus_trans('claim.th_username')."</td>
<td class='colhead' align='center'>".nexus_trans('claim.th_torrent_name')."</td>
<td class='colhead' align='center'>".nexus_trans('claim.th_torrent_size')."</td>
<td class='colhead' align='center'>".nexus_trans('claim.th_torrent_ttl')."</td>
<td class='colhead' align='center'>".nexus_trans('claim.th_claim_at')."</td>
<td class='colhead' align='center'>".nexus_trans('claim.th_last_settle')."</td>
<td class='colhead' align='center'>".nexus_trans('claim.th_seed_time_this_month')."</td>
<td class='colhead' align='center'>".nexus_trans('claim.th_uploaded_this_month')."</td>
<td class='colhead' align='center'>".nexus_trans('claim.th_reached_or_not')."</td>
".$actionTh."
</tr>");
$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("<tr>
<td class='rowfollow nowrap' align='center'>" . $row->id . "</td>
<td class='rowfollow' align='left'><a href='userdetails.php?id=" . $row->uid . "'>" . $row->user->username . "</a></td>
<td class='rowfollow' align='left'><a href='details.php?id=" . $row->torrent_id . "'>" . $row->torrent->name . "</a></td>
<td class='rowfollow nowrap' align='center'>" . mksize($row->torrent->size) . "</td>
<td class='rowfollow nowrap' align='center'>" . mkprettytime($row->torrent->added->diffInSeconds($now)) . "</td>
<td class='rowfollow nowrap' align='center'>" . format_datetime($row->created_at) . "</td>
<td class='rowfollow nowrap' align='center'>" . format_datetime($row->last_settle_at) . "</td>
<td class='rowfollow nowrap' align='center'>" . mkprettytime($row->snatch->seedtime - $row->seed_time_begin) . "</td>
<td class='rowfollow nowrap' align='center'>" . mksize($row->snatch->uploaded - $row->uploaded_begin) . "</td>
<td class='rowfollow nowrap' align='center'>" . $reached . "</td>
".sprintf($actionTd, $row->id)."
</tr>");
}
print("</table>");
print($pagerbottom);
end_main_frame();
stdfoot();

View File

@@ -132,7 +132,52 @@ if (!$row) {
$download = "<a title=\"".$lang_details['title_download_torrent']."\" href=\"download.php?id=".$id."\"><img class=\"dt_download\" src=\"pic/trans.gif\" alt=\"download\" />&nbsp;<b><font class=\"small\">".$lang_details['text_download_torrent']."</font></b></a>&nbsp;|&nbsp;";
else $download = "";
tr($lang_details['row_action'], $download. ($owned == 1 ? "<$editlink><img class=\"dt_edit\" src=\"pic/trans.gif\" alt=\"edit\" />&nbsp;<b><font class=\"small\">".$lang_details['text_edit_torrent'] . "</font></b></a>&nbsp;|&nbsp;" : ""). (get_user_class() >= $askreseed_class && $row['seeders'] == 0 ? "<a title=\"".$lang_details['title_ask_for_reseed']."\" href=\"takereseed.php?reseedid=$id\"><img class=\"dt_reseed\" src=\"pic/trans.gif\" alt=\"reseed\">&nbsp;<b><font class=\"small\">".$lang_details['text_ask_for_reseed'] ."</font></b></a>&nbsp;|&nbsp;" : "") . "<a title=\"".$lang_details['title_report_torrent']."\" href=\"report.php?torrent=$id\"><img class=\"dt_report\" src=\"pic/trans.gif\" alt=\"report\" />&nbsp;<b><font class=\"small\">".$lang_details['text_report_torrent']."</font></b></a>", 1);
tr(
$lang_details['row_action'],
$download.($owned == 1 ? "<$editlink><img class=\"dt_edit\" src=\"pic/trans.gif\" alt=\"edit\" />&nbsp;<b><font class=\"small\">".$lang_details['text_edit_torrent'] . "</font></b></a>&nbsp;|&nbsp;" : "")
.(get_user_class() >= $askreseed_class && $row['seeders'] == 0 ? "<a title=\"".$lang_details['title_ask_for_reseed']."\" href=\"takereseed.php?reseedid=$id\"><img class=\"dt_reseed\" src=\"pic/trans.gif\" alt=\"reseed\">&nbsp;<b><font class=\"small\">".$lang_details['text_ask_for_reseed'] ."</font></b></a>&nbsp;|&nbsp;" : "")
."<a title=\"".$lang_details['title_report_torrent']."\" href=\"report.php?torrent=$id\"><img class=\"dt_report\" src=\"pic/trans.gif\" alt=\"report\" />&nbsp;<b><font class=\"small\">".$lang_details['text_report_torrent']."</font></b></a>"
, 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 = <<<JS
jQuery('#add-claim').on('click', function () {
if (!window.confirm('{$lang_details['claim_confirm']}')) {
return
}
let params = {action: "addClaim", params: {"torrent_id": jQuery(this).attr('data-torrent_id')}}
jQuery.post("ajax.php", params, function (response) {
console.log(response)
if (response.ret != 0) {
alert(response.msg)
} else {
window.location.reload()
}
}, 'json')
})
JS;
\Nexus\Nexus::js($claimJs, 'footer', false);
}
$maxUserCounts = get_setting('torrent.claim_torrent_user_counts_up_limit', \App\Models\Claim::USER_UP_LIMIT);
$y = sprintf('<input type="button" value="%s" id="add-claim" data-torrent_id="%s"%s>', $inputValue, $id, $disabled);
$y .= sprintf('&nbsp;' . $lang_details['claim_info'], $claimCounts, bcsub($maxUserCounts, $claimCounts));
$y .= sprintf('&nbsp;<b><a href="claim.php?torrent_id=%s">'.$lang_details['claim_detail'].'</a></b>', $id);
tr($lang_details['claim_label'], $y, 1);
}
// ------------- end claim block ------------------//
tr($lang_details['torrent_dl_url'],sprintf('<a title="%s" href="%s/download.php?downhash=%s|%s">%s</a>',$lang_details['torrent_dl_url_notice'], getSchemeAndHttpHost(), $CURUSER['id'], $torrentRep->encryptDownHash($row['id'], $CURUSER), $lang_details['torrent_dl_url_text']),1);
// ---------------- start subtitle block -------------------//

View File

@@ -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')
<li>".$lang_settings['text_normal_will_become']."<select name=normalbecome>".promotion_selection((isset($TORRENT['normalbecome']) ? $TORRENT['normalbecome'] : 1), 0)."</select>".$lang_settings['text_after']."<input type='text' style=\"width: 50px\" name=expirenormal value='".(isset($TORRENT["expirenormal"]) ? $TORRENT["expirenormal"] : 0 )."'>".$lang_settings['text_normal_timeout_default']."</li>
</ul>".$lang_settings['text_promotion_timeout_note_two'], 1);
tr($lang_settings['claim_label'], "<ul>
<li>".sprintf($lang_settings['claim_torrent_ttl'], sprintf('<input type="number" name="claim_torrent_ttl" value="%s" style="width: 50px"/>', $TORRENT['claim_torrent_ttl'] ?? \App\Models\Claim::TORRENT_TTL))."</li>
<li>".sprintf($lang_settings['claim_torrent_user_counts_up_limit'], sprintf('<input type="number" name="claim_torrent_user_counts_up_limit" value="%s" style="width: 50px"/>', $TORRENT['claim_torrent_user_counts_up_limit'] ?? \App\Models\Claim::USER_UP_LIMIT))."</li>
<li>".sprintf($lang_settings['claim_user_torrent_counts_up_limit'], sprintf('<input type="number" name="claim_user_torrent_counts_up_limit" value="%s" style="width: 50px"/>', $TORRENT['claim_user_torrent_counts_up_limit'] ?? \App\Models\Claim::TORRENT_UP_LIMIT))."</li>
<li>".sprintf($lang_settings['claim_remove_deduct_user_bonus'], sprintf('<input type="number" name="claim_remove_deduct_user_bonus" value="%s" style="width: 50px"/>', $TORRENT['claim_remove_deduct_user_bonus'] ?? \App\Models\Claim::REMOVE_DEDUCT))."</li>
<li>".sprintf($lang_settings['claim_give_up_deduct_user_bonus'], sprintf('<input type="number" name="claim_give_up_deduct_user_bonus" value="%s" style="width: 50px"/>', $TORRENT['claim_give_up_deduct_user_bonus'] ?? \App\Models\Claim::GIVE_UP_DEDUCT))."</li>
<li>".sprintf($lang_settings['claim_bonus_multiplier'], sprintf('<input type="number" name="claim_bonus_multiplier" value="%s" style="width: 50px"/>', $TORRENT['claim_bonus_multiplier'] ?? \App\Models\Claim::BONUS_MULTIPLIER))."</li>
<li>".sprintf($lang_settings['claim_reach_standard'], sprintf('<input type="number" name="claim_reach_standard_seed_time" value="%s" style="width: 50px"/>', $TORRENT['claim_reach_standard_seed_time'] ?? \App\Models\Claim::STANDARD_SEED_TIME_HOURS), sprintf('<input type="number" name="claim_reach_standard_uploaded" value="%s" style="width: 50px"/>', $TORRENT['claim_reach_standard_uploaded'] ?? \App\Models\Claim::STANDARD_UPLOADED_TIMES))."</li>
</ul>", 1);
tr($lang_settings['row_auto_pick_hot'], $lang_settings['text_torrents_uploaded_within']."<input type='text' style=\"width: 50px\" name=hotdays value='".(isset($TORRENT["hotdays"]) ? $TORRENT["hotdays"] : 7 )."'>".$lang_settings['text_days_with_more_than']."<input type='text' style=\"width: 50px\" name=hotseeder value='".(isset($TORRENT["hotseeder"]) ? $TORRENT["hotseeder"] : 10 )."'>".$lang_settings['text_be_picked_as_hot']."<br />".$lang_settings['text_auto_pick_hot_default'], 1);
tr($lang_settings['row_uploader_get_double'], $lang_settings['text_torrent_uploader_gets']."<input type='text' style=\"width: 50px\" name=uploaderdouble value='".(isset($TORRENT["uploaderdouble"]) ? $TORRENT["uploaderdouble"] : 1 )."'>".$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']."<input type='text' style=\"width: 50px\" name=deldeadtorrent value='".(isset($TORRENT["deldeadtorrent"]) ? $TORRENT["deldeadtorrent"] : 0 )."'>".$lang_settings['text_days_be_deleted']."<br />".$lang_settings['row_delete_dead_torrents_note'], 1);

View File

@@ -0,0 +1,28 @@
<?php
return [
'title_for_torrent' => '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: <b>:total</b>',
'claim_reached_counts' => 'Reached torrent counts: <b>:counts</b>',
'claim_reached_summary' => 'Reached torrent get bonus per hour: <b>:bonus_per_hour</b>, seed time average(hour): <b>:hours</b>, get bonus total: <b>:bonus_total</b>',
'claim_unreached_remain_counts' => 'Unreached torrent remain counts: <b>:counts</b>',
'claim_unreached_remove_counts' => 'Unreached torrent remove counts: <b>:counts</b>',
'claim_unreached_summary' => 'Deduct bonus every unreached torrent<b>:deduct_per_torrent</b>, total deduct: <b>:deduct_total</b>',
'confirm_give_up' => 'Are you sure you want to give up claiming this torrent?',
];

View File

@@ -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',
];

View File

@@ -0,0 +1,28 @@
<?php
return [
'title_for_torrent' => '种子认领详情',
'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' => '认领种子数:<b>:total</b>',
'claim_reached_counts' => '达标数:<b>:counts</b>',
'claim_reached_summary' => '达标种子数每小时魔力:<b>:bonus_per_hour</b>, 平均做种小时数:<b>:hours</b>, 获得魔力:<b>:bonus_total</b>',
'claim_unreached_remain_counts' => '未达标保留数:<b>:counts</b>',
'claim_unreached_remove_counts' => '未达标删除数:<b>:counts</b>',
'claim_unreached_summary' => '未达标每个种子扣除魔力:<b>:deduct_per_torrent</b>,总扣除魔力:<b>:deduct_total</b>',
'confirm_give_up' => '确定要放弃认领此种子吗?',
];

View File

@@ -38,4 +38,8 @@ return [
'classic' => '经典',
'recommended' => '推荐',
],
'claim_already' => '此种子已经认领',
'no_snatch' => '没有下载过此种子',
'can_no_be_claimed_yet' => '还不能被认领',
'claim_number_reach_maximum' => '认领种子数达到上限',
];

View File

@@ -0,0 +1,25 @@
<?php
return [
'title_for_torrent' => '種子認領詳情',
'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' => '認領種子數:<b>:total</b>',
'claim_reached_counts' => '達標數:<b>:counts</b>',
'claim_reached_summary' => '達標種子數每小時魔力:<b>:bonus_per_hour</b>, 平均做種小時數:<b>:hours</b>, 獲得魔力:<b>:bonus_total</b>',
'claim_unreached_remain_counts' => '未達標保留數:<b>:counts</b>',
'claim_unreached_remove_counts' => '未達標刪除數:<b>:counts</b>',
'claim_unreached_summary' => '未達標每個種子扣除魔力:<b>:deduct_per_torrent</b>,總扣除魔力:<b>:deduct_total</b>',
];

View File

@@ -38,4 +38,8 @@ return [
'classic' => '經典',
'recommended' => '推薦',
],
'claim_already' => '此種子已經認領',
'no_snatch' => '沒有下載過此種子',
'can_no_be_claimed_yet' => '還不能被認領',
'claim_number_reach_maximum' => '認領種子數達到上限',
];