From f64834b594d84e4c23734a7338aae3bfcd318720 Mon Sep 17 00:00:00 2001 From: xiaomlove Date: Fri, 6 May 2022 15:50:26 +0800 Subject: [PATCH] improve claim settle --- app/Console/Commands/ClaimSettle.php | 1 - app/Console/Commands/Test.php | 2 +- app/Console/Kernel.php | 16 ++- app/Models/Claim.php | 5 + app/Repositories/ClaimRepository.php | 131 +++++++++++------- .../2022_05_04_234639_create_claims_table.php | 5 +- include/constants.php | 2 +- include/functions.php | 2 +- lang/chs/lang_settings.php | 1 + lang/cht/lang_settings.php | 1 + lang/en/lang_settings.php | 1 + nexus/Install/settings.default.php | 3 +- public/details.php | 2 +- public/settings.php | 3 +- public/userdetails.php | 6 +- resources/lang/en/torrent.php | 4 +- resources/lang/zh_CN/torrent.php | 4 +- resources/lang/zh_TW/torrent.php | 4 +- 18 files changed, 124 insertions(+), 69 deletions(-) diff --git a/app/Console/Commands/ClaimSettle.php b/app/Console/Commands/ClaimSettle.php index b16d0e75..529095d8 100644 --- a/app/Console/Commands/ClaimSettle.php +++ b/app/Console/Commands/ClaimSettle.php @@ -3,7 +3,6 @@ namespace App\Console\Commands; use App\Repositories\ClaimRepository; -use App\Repositories\ExamRepository; use Illuminate\Console\Command; class ClaimSettle extends Command diff --git a/app/Console/Commands/Test.php b/app/Console/Commands/Test.php index edb8388a..709009f7 100644 --- a/app/Console/Commands/Test.php +++ b/app/Console/Commands/Test.php @@ -127,7 +127,7 @@ class Test extends Command // $r = $rep->getContinuousPoints(11); $arr = [1,2]; - $r = collect($arr)->map(fn($item) => $item * 2)->implode(','); + $r = Carbon::now()->format('d'); dd($r, $arr); } diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index ad5a4d33..17cb1723 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -2,6 +2,7 @@ namespace App\Console; +use Carbon\Carbon; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; @@ -24,14 +25,15 @@ class Kernel extends ConsoleKernel */ protected function schedule(Schedule $schedule) { - $schedule->command('exam:assign_cronjob')->everyMinute(); - $schedule->command('exam:checkout_cronjob')->everyMinute(); - $schedule->command('exam:update_progress --bulk=1')->hourly(); - $schedule->command('backup:cronjob')->everyMinute(); - $schedule->command('hr:update_status')->everyMinute(); - $schedule->command('hr:update_status --ignore_time=1')->hourly(); + $schedule->command('exam:assign_cronjob')->everyMinute()->withoutOverlapping(); + $schedule->command('exam:checkout_cronjob')->everyMinute()->withoutOverlapping(); + $schedule->command('exam:update_progress --bulk=1')->hourly()->withoutOverlapping(); + $schedule->command('backup:cronjob')->everyMinute()->withoutOverlapping(); + $schedule->command('hr:update_status')->everyMinute()->withoutOverlapping(); + $schedule->command('hr:update_status --ignore_time=1')->hourly()->withoutOverlapping(); $schedule->command('user:delete_expired_token')->dailyAt('04:00'); - $schedule->command('claim:settle')->monthlyOn(); + $schedule->command('claim:settle')->hourly()->between("00:00", "12:00") + ->when(function () {Carbon::now()->format('d') == '01';})->withoutOverlapping(); } /** diff --git a/app/Models/Claim.php b/app/Models/Claim.php index 3e9d8409..3355a4ab 100644 --- a/app/Models/Claim.php +++ b/app/Models/Claim.php @@ -37,6 +37,11 @@ class Claim extends NexusModel return $this->belongsTo(Snatch::class, 'snatched_id'); } + public static function getConfigIsEnabled(): bool + { + return Setting::get('torrent.claim_enabled', 'no') == 'yes'; + } + public static function getConfigTorrentTTL() { return Setting::get('torrent.claim_torrent_ttl', self::TORRENT_TTL); diff --git a/app/Repositories/ClaimRepository.php b/app/Repositories/ClaimRepository.php index c9874cd8..e00d3704 100644 --- a/app/Repositories/ClaimRepository.php +++ b/app/Repositories/ClaimRepository.php @@ -1,16 +1,13 @@ where('uid', $uid)->where('torrent_id', $torrentId)->exists(); if ($exists) { throw new \RuntimeException(nexus_trans("torrent.claim_already")); @@ -34,7 +35,12 @@ class ClaimRepository extends BaseRepository $max = Claim::getConfigTorrentUpLimit(); $count = Claim::query()->where('uid', $uid)->count(); if ($count >= $max) { - throw new \RuntimeException(nexus_trans("torrent.claim_number_reach_maximum")); + throw new \RuntimeException(nexus_trans("torrent.claim_number_reach_torrent_maximum")); + } + $max = Claim::getConfigUserUpLimit(); + $count = Claim::query()->where('torrent_id', $torrentId)->count(); + if ($count >= $max) { + throw new \RuntimeException(nexus_trans("torrent.claim_number_reach_user_maximum")); } $snatch = Snatch::query()->where('userid', $uid)->where('torrentid', $torrentId)->first(); if (!$snatch) { @@ -70,6 +76,10 @@ class ClaimRepository extends BaseRepository public function delete($id, $uid) { + $isEnabled = Claim::getConfigIsEnabled(); + if ($isEnabled) { + throw new \RuntimeException(nexus_trans("torrent.claim_disabled")); + } $model = Claim::query()->findOrFail($id); if ($model->uid != $uid) { throw new \RuntimeException("No permission"); @@ -93,29 +103,38 @@ class ClaimRepository extends BaseRepository public function settleCronjob(): array { - $query = Claim::query()->select(['uid'])->groupBy('uid'); + $startOfThisMonth = Carbon::now()->startOfMonth(); + $query = Claim::query() + ->select(['uid']) + ->where('last_settle_at', '<', $startOfThisMonth) + ->groupBy('uid') + ; $size = 10000; - $page = 1; $successCount = $failCount = 0; while (true) { - $logPrefix = "page: $page, size: $size"; - $result = (clone $query)->forPage($page, $size)->get(); + $logPrefix = "size: $size"; + $result = (clone $query)->take($size)->get(); if ($result->isEmpty()) { do_log("$logPrefix, no more data..."); break; } + do_log("get counts: " . $result->count()); 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 { + try { + $result = $this->settleUser($uid); + do_log("$logPrefix, settle user: $uid done!, result: " . var_export($result, true)); + if ($result) { + $successCount++; + } else { + $failCount++; + } + } catch (\Throwable $exception) { + do_log("$logPrefix, settle user: $uid fail!, error: " . $exception->getMessage() . $exception->getTraceAsString(), 'error'); $failCount++; } } - $page++; } return ['success_count' => $successCount, 'fail_count' => $failCount]; } @@ -185,6 +204,12 @@ class ClaimRepository extends BaseRepository $totalDeduct = $bonusDeduct * count($unReachedIdArr); do_log("totalDeduct: $totalDeduct", 'alert'); + $message = $this->buildMessage( + $user, $reachedTorrentIdArr, $unReachedTorrentIdArr, $remainTorrentIdArr, + $bonusResult, $bonusFinal, $seedTimeHoursAvg, $bonusDeduct, $totalDeduct + ); + do_log("message: " . nexus_json_encode($message), 'alert'); + /** * Just do a test, debug from log */ @@ -193,35 +218,50 @@ class ClaimRepository extends BaseRepository return true; } - //Increase user bonus - User::query()->where('id', $uid)->increment('seedbonus', $bonusFinal); - do_log("Increase user bonus: $bonusFinal", 'alert'); + //Wrap with transaction + DB::transaction(function () use ($uid, $unReachedIdArr, $toUpdateIdArr, $bonusFinal, $totalDeduct, $uploadedCaseWhen, $seedTimeCaseWhen, $message, $now) { + //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'); - } + //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"); + //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 + //Send message + Message::query()->insert($message); + }); + do_log("[DONE], cost time: " . (time() - $now->timestamp) . " seconds"); + return true; + } + + private function buildMessage( + User $user, $reachedTorrentIdArr, $unReachedTorrentIdArr, $remainTorrentIdArr, + $bonusResult, $bonusFinal, $seedTimeHoursAvg, $deductPerTorrent, $deductTotal + ) { + $now = Carbon::now(); + $allTorrentIdArr = array_merge($reachedTorrentIdArr, $unReachedTorrentIdArr, $remainTorrentIdArr); $torrentInfo = Torrent::query() - ->whereIn('id', array_merge($reachedTorrentIdArr, $unReachedTorrentIdArr, $remainTorrentIdArr)) + ->whereIn('id', $allTorrentIdArr) ->get(Torrent::$commentFields) ->keyBy('id') ; $msg = []; $locale = $user->locale; + do_log("build message, user: {$user->id}, locale: $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); + $msg[] = nexus_trans('claim.claim_total', [ 'total' => count($allTorrentIdArr)], $locale); $reachList = collect($reachedTorrentIdArr)->map( fn($item) => sprintf("[url=details.php?id=%s]%s[/url]", $item, $torrentInfo->get($item)->name) @@ -229,10 +269,10 @@ class ClaimRepository extends BaseRepository $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 + '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( @@ -244,24 +284,19 @@ class ClaimRepository extends BaseRepository 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) { + if ($deductTotal) { $msg[] = nexus_trans( "claim.claim_unreached_summary", [ - 'deduct_per_torrent '=> number_format($bonusDeduct, 2), - 'deduct_total' => number_format($totalDeduct, 2) - ], $locale + 'deduct_per_torrent '=> number_format($deductPerTorrent, 2), + 'deduct_total' => number_format($deductTotal, 2) + ], $locale ); } - - $message = [ - 'receiver' => $uid, + return [ + 'receiver' => $user->id, '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/database/migrations/2022_05_04_234639_create_claims_table.php b/database/migrations/2022_05_04_234639_create_claims_table.php index d85059cd..5a860976 100644 --- a/database/migrations/2022_05_04_234639_create_claims_table.php +++ b/database/migrations/2022_05_04_234639_create_claims_table.php @@ -13,6 +13,9 @@ return new class extends Migration */ public function up() { + if (Schema::hasTable('claims')) { + return; + } Schema::create('claims', function (Blueprint $table) { $table->id(); $table->integer('uid'); @@ -20,7 +23,7 @@ return new class extends Migration $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->dateTime('last_settle_at')->nullable()->index(); $table->timestamps(); $table->unique(['uid', 'torrent_id']); }); diff --git a/include/constants.php b/include/constants.php index 11bc754c..46fa3636 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']))?> + %s]', $CURUSER['id'], (new \App\Repositories\ClaimRepository())->getStats($CURUSER['id']))?> = UC_SYSOP) { ?> [] diff --git a/lang/chs/lang_settings.php b/lang/chs/lang_settings.php index 9ffcd81e..a7543d7a 100644 --- a/lang/chs/lang_settings.php +++ b/lang/chs/lang_settings.php @@ -745,6 +745,7 @@ $lang_settings = array 'row_show_top_uploader' => '显示最多上传(种子数)', 'text_show_top_uploader_note' => "默认'否'。在首页显示最多上传的用户(按种子数计算)。", 'claim_label' => '种子认领', + 'claim_enabled' => '启用认领', 'claim_torrent_ttl' => '种子发布 %s 天后可以认领。', 'claim_torrent_user_counts_up_limit' => '一个种子最多可以被 %s 个用户认领。', 'claim_user_torrent_counts_up_limit' => '一个用户最多可以认领 %s 个种子。', diff --git a/lang/cht/lang_settings.php b/lang/cht/lang_settings.php index f5e0beca..9be3bbbc 100644 --- a/lang/cht/lang_settings.php +++ b/lang/cht/lang_settings.php @@ -744,6 +744,7 @@ $lang_settings = array 'row_show_top_uploader' => '顯示最多上傳(種子數)', 'text_show_top_uploader_note' => "默認'否'。在首頁顯示最多上傳的用戶(按種子數計算)。", 'claim_label' => '種子認領', + 'claim_enabled' => '啟用認領', 'claim_torrent_ttl' => '種子發布 %s 天後可以認領。', 'claim_torrent_user_counts_up_limit' => '一個種子最多可以被 %s 個用戶認領。', 'claim_user_torrent_counts_up_limit' => '一個用戶最多可以認領 %s 個種子。', diff --git a/lang/en/lang_settings.php b/lang/en/lang_settings.php index 7339c24f..8444afde 100644 --- a/lang/en/lang_settings.php +++ b/lang/en/lang_settings.php @@ -744,6 +744,7 @@ $lang_settings = array '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_enabled' => 'Claim enabled', '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.', diff --git a/nexus/Install/settings.default.php b/nexus/Install/settings.default.php index 802af786..0e26494b 100644 --- a/nexus/Install/settings.default.php +++ b/nexus/Install/settings.default.php @@ -322,6 +322,8 @@ return array ( 'minvotes' => '10', 'sticky_first_level_background_color' => '#89c9e6', 'sticky_second_level_background_color' => '#aadbf3', + 'download_support_passkey' => 'yes', + 'claim_enabled' => 'no', '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, @@ -363,7 +365,6 @@ return array ( 'watermarkquality' => '85', 'altthumbwidth' => '180', 'altthumbheight' => '135', - 'download_support_passkey' => 'yes', ), 'advertisement' => array ( diff --git a/public/details.php b/public/details.php index d14670a3..e744affe 100644 --- a/public/details.php +++ b/public/details.php @@ -142,7 +142,7 @@ if (!$row) { // ------------- start claim block ------------------// $claimTorrentTTL = \App\Models\Claim::getConfigTorrentTTL(); - if (\Carbon\Carbon::parse($row['added'])->addDays($claimTorrentTTL)->lte(\Carbon\Carbon::now())) { + if (\App\Models\Claim::getConfigIsEnabled() && \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(); diff --git a/public/settings.php b/public/settings.php index a4a26bcf..4d129967 100644 --- a/public/settings.php +++ b/public/settings.php @@ -150,7 +150,7 @@ 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', 'claim_torrent_ttl', 'claim_torrent_user_counts_up_limit', 'claim_user_torrent_counts_up_limit', 'claim_remove_deduct_user_bonus', + 'download_support_passkey', 'claim_enabled', '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); @@ -666,6 +666,7 @@ elseif ($action == 'torrentsettings') ".$lang_settings['text_promotion_timeout_note_two'], 1); tr($lang_settings['claim_label'], "