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