mirror of
https://github.com/lkddi/nexusphp.git
synced 2026-04-03 14:10:57 +08:00
improve paid torrent + hit and run
This commit is contained in:
@@ -4,6 +4,7 @@ namespace App\Console\Commands;
|
||||
|
||||
use App\Jobs\CheckQueueFailedJobs;
|
||||
use App\Jobs\SettleClaim;
|
||||
use App\Jobs\UpdateUserDownloadPrivilege;
|
||||
use App\Models\ExamUser;
|
||||
use App\Models\Language;
|
||||
use App\Models\PersonalAccessToken;
|
||||
@@ -61,7 +62,7 @@ class Test extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
// $failedJob = DB::table('failed_jobs')->find(555);
|
||||
// $failedJob = DB::table('failed_jobs')->find(569);
|
||||
//
|
||||
// $payload = json_decode($failedJob->payload, true);
|
||||
// dd($payload);
|
||||
@@ -71,7 +72,11 @@ class Test extends Command
|
||||
//
|
||||
// dd($job);
|
||||
|
||||
CheckQueueFailedJobs::dispatch();
|
||||
// UpdateUserDownloadPrivilege::dispatch(1, "yes", "test_key");
|
||||
// $res = unserialize("O:36:\"App\\Jobs\\UpdateUserDownloadPrivilege\":3:{s:6:\"userId\";i:1;s:6:\"status\";s:3:\"yes\";s:9:\"reasonKey\";s:8:\"test_key\";}");
|
||||
// $res = unserialize("O:36:\"App\\Jobs\\UpdateUserDownloadPrivilege\":3:{s:6:\"userId\";i:1;s:6:\"status\";s:3:\"yes\";s:9:\"reasonKey\";s:8:\"test_key\";}");
|
||||
// dd($res);
|
||||
UpdateUserDownloadPrivilege::dispatch(1, "yes", "test_key");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
31
app/Console/Commands/Upgrade/MigrateSnatchedHitAndRunId.php
Normal file
31
app/Console/Commands/Upgrade/MigrateSnatchedHitAndRunId.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands\Upgrade;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Nexus\Database\NexusDB;
|
||||
|
||||
class MigrateSnatchedHitAndRunId extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'upgrade:migrate_snatched_hr_id';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Command description';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
NexusDB::statement("update snatched inner join hit_and_runs on snatched.userid = hit_and_runs.uid and snatched.torrentid = hit_and_runs.torrent_id set snatched.hit_and_run_id = hit_and_runs.id");
|
||||
}
|
||||
}
|
||||
31
app/Console/Commands/Upgrade/UpdateSnatchedBuyLogId.php
Normal file
31
app/Console/Commands/Upgrade/UpdateSnatchedBuyLogId.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands\Upgrade;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Nexus\Database\NexusDB;
|
||||
|
||||
class UpdateSnatchedBuyLogId extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'upgrade:migrate_snatched_buy_log_id';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Command description';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
NexusDB::statement("UPDATE snatched INNER JOIN torrent_buy_logs ON snatched.userid = torrent_buy_logs.uid AND snatched.torrentid = torrent_buy_logs.torrent_id SET snatched.buy_log_id = torrent_buy_logs.id");
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ class Kernel extends ConsoleKernel
|
||||
$schedule->command('meilisearch:import')->weeklyOn(1, "03:00");
|
||||
$schedule->command('torrent:load_pieces_hash')->dailyAt("01:00");
|
||||
$schedule->job(new CheckQueueFailedJobs())->everySixHours();
|
||||
$schedule->job(new ThirdPartyJob())->everyMinute();
|
||||
// $schedule->job(new ThirdPartyJob())->everyMinute();
|
||||
$schedule->job(new MaintainPluginState())->everyMinute();
|
||||
$schedule->job(new UpdateIsSeedBoxFromUserRecordsCache())->everySixHours();
|
||||
$schedule->job(new CheckCleanup())->everyFifteenMinutes();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Enums;
|
||||
|
||||
use App\Events\NewsCreated;
|
||||
use App\Events\SnatchedUpdated;
|
||||
use App\Events\TorrentCreated;
|
||||
use App\Events\TorrentDeleted;
|
||||
use App\Events\TorrentUpdated;
|
||||
@@ -12,6 +13,7 @@ use App\Events\UserDisabled;
|
||||
use App\Events\UserEnabled;
|
||||
use App\Events\UserUpdated;
|
||||
use App\Models\News;
|
||||
use App\Models\Snatch;
|
||||
use App\Models\Torrent;
|
||||
use App\Models\User;
|
||||
|
||||
@@ -28,6 +30,8 @@ final class ModelEventEnum {
|
||||
|
||||
const NEWS_CREATED = 'news_created';
|
||||
|
||||
const SNATCHED_UPDATED = 'snatched_updated';
|
||||
|
||||
public static array $eventMaps = [
|
||||
self::TORRENT_CREATED => ['event' => TorrentCreated::class, 'model' => Torrent::class],
|
||||
self::TORRENT_UPDATED => ['event' => TorrentUpdated::class, 'model' => Torrent::class],
|
||||
@@ -40,5 +44,7 @@ final class ModelEventEnum {
|
||||
self::USER_DISABLED => ['event' => UserDisabled::class, 'model' => User::class],
|
||||
|
||||
self::NEWS_CREATED => ['event' => NewsCreated::class, 'model' => News::class],
|
||||
|
||||
self::SNATCHED_UPDATED => ['event' => SnatchedUpdated::class, 'model' => Snatch::class],
|
||||
];
|
||||
}
|
||||
|
||||
41
app/Events/SnatchedUpdated.php
Normal file
41
app/Events/SnatchedUpdated.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use Illuminate\Broadcasting\Channel;
|
||||
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||
use Illuminate\Broadcasting\PresenceChannel;
|
||||
use Illuminate\Broadcasting\PrivateChannel;
|
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class SnatchedUpdated
|
||||
{
|
||||
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||
|
||||
public ?Model $model = null;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Model $model)
|
||||
{
|
||||
$this->model = $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channels the event should broadcast on.
|
||||
*
|
||||
* @return array<int, \Illuminate\Broadcasting\Channel>
|
||||
*/
|
||||
public function broadcastOn(): array
|
||||
{
|
||||
return [
|
||||
new PrivateChannel('channel-name'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,7 @@ class BuyTorrent implements ShouldQueue
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
@@ -42,27 +43,28 @@ class BuyTorrent implements ShouldQueue
|
||||
$userId = $this->userId;
|
||||
$torrentId = $this->torrentId;
|
||||
|
||||
$hasBuy = TorrentBuyLog::query()
|
||||
$buyLog = TorrentBuyLog::query()
|
||||
->where("uid", $userId)
|
||||
->where("torrent_id", $torrentId)
|
||||
->exists()
|
||||
->first();
|
||||
;
|
||||
if ($hasBuy) {
|
||||
if ($buyLog) {
|
||||
//标记购买成功
|
||||
do_log("$logPrefix, already bought");
|
||||
$torrentRep->addBuySuccessCache($userId, $torrentId);
|
||||
$torrentRep->addBuySuccessCache($userId, $torrentId, $buyLog->id);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
$bonusRep = new BonusRepository();
|
||||
$bonusRep->consumeToBuyTorrent($this->userId, $this->torrentId);
|
||||
$buyLog = $bonusRep->consumeToBuyTorrent($this->userId, $this->torrentId);
|
||||
//标记购买成功
|
||||
do_log("$logPrefix, buy torrent success");
|
||||
$torrentRep->addBuySuccessCache($userId, $torrentId);
|
||||
$torrentRep->addBuySuccessCache($userId, $torrentId, $buyLog->id);
|
||||
} catch (\Throwable $throwable) {
|
||||
//标记购买失败,缓存 3600 秒,这个时间内不能再次购买
|
||||
do_log("$logPrefix, buy torrent fail: " . $throwable->getMessage(), "error");
|
||||
$torrentRep->addBuyFailCache($userId, $torrentId);
|
||||
throw $throwable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
30
app/Jobs/UpdateUserDownloadPrivilege.php
Normal file
30
app/Jobs/UpdateUserDownloadPrivilege.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Repositories\UserRepository;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Queue\Queueable;
|
||||
|
||||
class UpdateUserDownloadPrivilege implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*/
|
||||
public function __construct(public int $userId, public string $status, public string $reasonKey)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
$rep = new UserRepository();
|
||||
$rep->updateDownloadPrivileges(null, $this->userId, $this->status, $this->reasonKey);
|
||||
do_log("Updating user download privilege for user {$this->userId} to {$this->status} by reason {$this->reasonKey}");
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ class Snatch extends NexusModel
|
||||
|
||||
protected $fillable = [
|
||||
'torrentid', 'userid', 'ip', 'port', 'uploaded', 'downloaded', 'to_go', 'seedtime', 'leechtime',
|
||||
'last_action', 'startdat', 'completedat', 'finished'
|
||||
'last_action', 'startdat', 'completedat', 'finished', 'hit_and_run_id', 'buy_log_id',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
|
||||
@@ -252,11 +252,11 @@ class BonusRepository extends BaseRepository
|
||||
|
||||
}
|
||||
|
||||
public function consumeToBuyTorrent($uid, $torrentId, $channel = 'Web'): bool
|
||||
public function consumeToBuyTorrent($uid, $torrentId, $channel = 'Web'): TorrentBuyLog
|
||||
{
|
||||
$torrent = Torrent::query()->findOrFail($torrentId, Torrent::$commentFields);
|
||||
$requireBonus = $torrent->price;
|
||||
NexusDB::transaction(function () use ($requireBonus, $torrent, $channel, $uid) {
|
||||
return NexusDB::transaction(function () use ($requireBonus, $torrent, $channel, $uid) {
|
||||
$userQuery = User::query();
|
||||
if ($requireBonus > 0) {
|
||||
$userQuery = $userQuery->lockForUpdate();
|
||||
@@ -269,7 +269,7 @@ class BonusRepository extends BaseRepository
|
||||
], $buyerLocale);
|
||||
do_log("comment: $comment");
|
||||
$this->consumeUserBonus($user, $requireBonus, BonusLogs::BUSINESS_TYPE_BUY_TORRENT, $comment);
|
||||
TorrentBuyLog::query()->create([
|
||||
$buyLog = TorrentBuyLog::query()->create([
|
||||
'uid' => $user->id,
|
||||
'torrent_id' => $torrent->id,
|
||||
'price' => $requireBonus,
|
||||
@@ -314,10 +314,8 @@ class BonusRepository extends BaseRepository
|
||||
], $buyerLocale),
|
||||
];
|
||||
Message::add($buyTorrentSuccessMessage);
|
||||
return $buyLog;
|
||||
});
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public function consumeUserBonus($user, $requireBonus, $logBusinessType, $logComment = '', array $userUpdates = [])
|
||||
|
||||
@@ -257,6 +257,9 @@ LUA;
|
||||
"lastcleantime5" => "five",
|
||||
];
|
||||
$avps = Avp::query()->get()->keyBy("arg");
|
||||
if ($avps->isEmpty()) {
|
||||
return;
|
||||
}
|
||||
foreach ($arvToLevel as $arg => $level) {
|
||||
/** @var NexusModel $value */
|
||||
$value = $avps->get($arg);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Repositories;
|
||||
|
||||
use App\Auth\Permission;
|
||||
use App\Enums\ModelEventEnum;
|
||||
use App\Exceptions\InsufficientPermissionException;
|
||||
use App\Exceptions\NexusException;
|
||||
use App\Http\Resources\TorrentResource;
|
||||
@@ -843,20 +844,51 @@ HTML;
|
||||
}
|
||||
|
||||
/**
|
||||
* 购买成功缓存,保存为 hash,一个种子一个 hash,永久有效
|
||||
* 购买成功,缓存 30 天并更新到 snatched 上
|
||||
* @param $uid
|
||||
* @param $torrentId
|
||||
* @return void
|
||||
* @throws \RedisException
|
||||
*/
|
||||
public function addBuySuccessCache($uid, $torrentId): void
|
||||
public function addBuySuccessCache($uid, $torrentId, $buyLogId): void
|
||||
{
|
||||
NexusDB::redis()->hSet($this->getBoughtUserCacheKey($torrentId), $uid, 1);
|
||||
NexusDB::redis()->set($this->getBoughtUserCacheKey($torrentId, $uid), 1, ['NX', 'EX' => 86400*30]);
|
||||
$record = Snatch::query()
|
||||
->where("torrentid", $torrentId)
|
||||
->where("userid", $uid)
|
||||
->first();
|
||||
if ($record) {
|
||||
$record->buy_log_id = $buyLogId;
|
||||
$record->save();
|
||||
publish_model_event(ModelEventEnum::SNATCHED_UPDATED, $record->id);
|
||||
} else {
|
||||
do_log("addBuySuccessCache, uid: $uid, torrentId: $torrentId, buyLogId: $buyLogId, snatched not exists", 'error');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function hasBuySuccessCache($uid, $torrentId): bool
|
||||
{
|
||||
return NexusDB::redis()->hGet($this->getBoughtUserCacheKey($torrentId), $uid) == 1;
|
||||
$key = $this->getBoughtUserCacheKey($torrentId, $uid);
|
||||
if (NexusDB::redis()->exists($key)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function hasBuySuccess($uid, $torrentId): bool
|
||||
{
|
||||
if ($this->hasBuySuccessCache($uid, $torrentId)) {
|
||||
return true;
|
||||
}
|
||||
$buyLog = TorrentBuyLog::query()
|
||||
->where("torrent_id", $torrentId)
|
||||
->where("uid", $uid)
|
||||
->first();
|
||||
if ($buyLog) {
|
||||
$this->addBuySuccessCache($uid, $torrentId, $buyLog->id);
|
||||
}
|
||||
return $buyLog != null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -868,8 +900,8 @@ HTML;
|
||||
*/
|
||||
public function getBuyStatus($uid, $torrentId): int
|
||||
{
|
||||
//查询是否已经购买
|
||||
if ($this->hasBuySuccessCache($uid, $torrentId)) {
|
||||
//从缓存中判断是否购买过
|
||||
if ($this->hasBuySuccess($uid, $torrentId)) {
|
||||
return self::BUY_STATUS_SUCCESS;
|
||||
}
|
||||
//是否购买失败过
|
||||
@@ -913,12 +945,13 @@ HTML;
|
||||
|
||||
/**
|
||||
* 购买成功缓存 key
|
||||
* @update 改为使用字符串判断键是否存在即可
|
||||
* @param $torrentId
|
||||
* @return string
|
||||
*/
|
||||
public function getBoughtUserCacheKey($torrentId): string
|
||||
public function getBoughtUserCacheKey($torrentId, $userId): string
|
||||
{
|
||||
return sprintf("%s:%s", self::BOUGHT_USER_CACHE_KEY_PREFIX, $torrentId);
|
||||
return sprintf("%s:%s:%s", self::BOUGHT_USER_CACHE_KEY_PREFIX, $torrentId, $userId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('snatched', function (Blueprint $table) {
|
||||
$table->bigInteger("hit_and_run_id")->default(0);
|
||||
$table->bigInteger("buy_log_id")->default(0);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('snatched', function (Blueprint $table) {
|
||||
$table->dropColumn("hit_and_run_id", "buy_log_id");
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
# IMPORTANT: Do not edit below unless you know what you are doing!
|
||||
|
||||
use App\Enums\ModelEventEnum;
|
||||
|
||||
if(!defined('IN_TRACKER'))
|
||||
die('Hacking attempt!');
|
||||
|
||||
@@ -60,12 +62,21 @@ function torrent_promotion_expire($days, $type = 2, $targettype = 1){
|
||||
}
|
||||
while($arr = mysql_fetch_assoc($res)){
|
||||
sql_query("UPDATE torrents SET sp_state = ".sqlesc($sp_state)." WHERE id={$arr['id']}") or sqlerr(__FILE__, __LINE__);
|
||||
publish_model_event(ModelEventEnum::TORRENT_UPDATED, $arr['id']);
|
||||
if ($sp_state == 1)
|
||||
write_log("Torrent {$arr['id']} ({$arr['name']}) is no longer on promotion (time expired)",'normal');
|
||||
else write_log("Promotion type for torrent {$arr['id']} ({$arr['name']}) is changed to ".$become." (time expired)",'normal');
|
||||
}
|
||||
}
|
||||
|
||||
function torrent_promotion_individual_expire() {
|
||||
$res = sql_query("select id from torrents WHERE promotion_time_type=2 AND promotion_until < ".sqlesc(date("Y-m-d H:i:s")));
|
||||
while ($arr = mysql_fetch_assoc($res)) {
|
||||
sql_query("update torrents set sp_state = 1, promotion_time_type=0, promotion_until=null where id=" . $arr['id']);
|
||||
publish_model_event(ModelEventEnum::TORRENT_UPDATED, $arr['id']);
|
||||
}
|
||||
}
|
||||
|
||||
function peasant_to_user($down_floor_gb, $down_roof_gb, $minratio){
|
||||
|
||||
if ($down_floor_gb){
|
||||
@@ -83,6 +94,7 @@ function peasant_to_user($down_floor_gb, $down_roof_gb, $minratio){
|
||||
writecomment($arr['id'],"Leech Warning removed by System.");
|
||||
sql_query("UPDATE users SET class = 1, leechwarn = 'no', leechwarnuntil = null WHERE id = {$arr['id']}") or sqlerr(__FILE__, __LINE__);
|
||||
sql_query("INSERT INTO messages (sender, receiver, added, subject, msg) VALUES(0, {$arr['id']}, $dt, $subject, $msg)") or sqlerr(__FILE__, __LINE__);
|
||||
publish_model_event(ModelEventEnum::USER_UPDATED, $arr['id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,6 +131,7 @@ function promotion($class, $down_floor_gb, $minratio, $time_week, $addinvite = 0
|
||||
sql_query("UPDATE users SET class = $class, max_class_once=$class, invites=invites+$addinvite WHERE id = {$arr['id']}") or sqlerr(__FILE__, __LINE__);
|
||||
}
|
||||
sql_query("INSERT INTO messages (sender, receiver, added, subject, msg) VALUES(0, {$arr['id']}, $dt, $subject, $msg)") or sqlerr(__FILE__, __LINE__);
|
||||
publish_model_event(ModelEventEnum::USER_UPDATED, $arr['id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,6 +154,7 @@ function demotion($class,$deratio){
|
||||
|
||||
sql_query("UPDATE users SET class = $newclass WHERE id = {$arr['id']}") or sqlerr(__FILE__, __LINE__);
|
||||
sql_query("INSERT INTO messages (sender, receiver, added, subject, msg) VALUES(0, {$arr['id']}, $dt, ".sqlesc($subject).", ".sqlesc($msg).")") or sqlerr(__FILE__, __LINE__);
|
||||
publish_model_event(ModelEventEnum::USER_UPDATED, $arr['id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -164,6 +178,7 @@ function user_to_peasant($down_floor_gb, $minratio){
|
||||
writecomment($arr['id'],"Leech Warned by System - Low Ratio.");
|
||||
sql_query("UPDATE users SET class = 0 , leechwarn = 'yes', leechwarnuntil = ".sqlesc($until)." WHERE id = {$arr['id']}") or sqlerr(__FILE__, __LINE__);
|
||||
sql_query("INSERT INTO messages (sender, receiver, added, subject, msg) VALUES(0, {$arr['id']}, $dt, ".sqlesc($subject).", ".sqlesc($msg).")") or sqlerr(__FILE__, __LINE__);
|
||||
publish_model_event(ModelEventEnum::USER_UPDATED, $arr['id']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,6 +218,9 @@ function ban_user_with_leech_warning_expired()
|
||||
\App\Models\User::query()->whereIn('id', $uidArr)->update($update);
|
||||
\App\Models\UserBanLog::query()->insert($userBanLogData);
|
||||
do_log("ban user: " . implode(', ', $uidArr));
|
||||
foreach ($uidArr as $uid) {
|
||||
publish_model_event(ModelEventEnum::USER_UPDATED, $uid);
|
||||
}
|
||||
return $uidArr;
|
||||
}
|
||||
|
||||
@@ -241,6 +259,9 @@ function disable_user(\Illuminate\Database\Eloquent\Builder $query, $reasonKey)
|
||||
\App\Models\UserBanLog::query()->insert($userBanLogData);
|
||||
\App\Models\UserModifyLog::query()->insert($userModifyLogs);
|
||||
do_log("[DISABLE_USER]($reasonKey): " . implode(', ', $uidArr));
|
||||
foreach ($uidArr as $uid) {
|
||||
publish_model_event(ModelEventEnum::USER_DISABLED, $uid);
|
||||
}
|
||||
return $uidArr;
|
||||
}
|
||||
|
||||
@@ -494,8 +515,8 @@ function docleanup($forceAll = 0, $printProgress = false) {
|
||||
torrent_promotion_expire($expirenormal_torrent, 1, $normalbecome_torrent);
|
||||
|
||||
//expire individual torrent promotion
|
||||
sql_query("UPDATE torrents SET sp_state = 1, promotion_time_type=0, promotion_until=null WHERE promotion_time_type=2 AND promotion_until < ".sqlesc(date("Y-m-d H:i:s",TIMENOW))) or sqlerr(__FILE__, __LINE__);
|
||||
|
||||
// sql_query("UPDATE torrents SET sp_state = 1, promotion_time_type=0, promotion_until=null WHERE promotion_time_type=2 AND promotion_until < ".sqlesc(date("Y-m-d H:i:s",TIMENOW))) or sqlerr(__FILE__, __LINE__);
|
||||
torrent_promotion_individual_expire();
|
||||
//End: expire torrent promotion
|
||||
$log = "expire torrent promotion";
|
||||
do_log($log);
|
||||
@@ -734,6 +755,7 @@ function docleanup($forceAll = 0, $printProgress = false) {
|
||||
sql_query("UPDATE users SET class = '1', vip_added = 'no', vip_until = null WHERE id = {$arr['id']}") or sqlerr(__FILE__, __LINE__);
|
||||
sql_query("INSERT INTO messages (sender, receiver, added, msg, subject) VALUES(0, {$arr['id']}, $dt, $msg, $subject)") or sqlerr(__FILE__, __LINE__);
|
||||
}
|
||||
publish_model_event(ModelEventEnum::USER_UPDATED, $arr['id']);
|
||||
}
|
||||
}
|
||||
if (!empty($userModifyLogs)) {
|
||||
@@ -764,6 +786,7 @@ function docleanup($forceAll = 0, $printProgress = false) {
|
||||
];
|
||||
sql_query("UPDATE users SET donor = 'no' WHERE id = {$arr['id']}") or sqlerr(__FILE__, __LINE__);
|
||||
sql_query("INSERT INTO messages (sender, receiver, added, msg, subject) VALUES(0, {$arr['id']}, $dt, $msg, $subject)") or sqlerr(__FILE__, __LINE__);
|
||||
publish_model_event(ModelEventEnum::USER_UPDATED, $arr['id']);
|
||||
}
|
||||
}
|
||||
if (!empty($userModifyLogs)) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
defined('VERSION_NUMBER') || define('VERSION_NUMBER', '1.9.5');
|
||||
defined('RELEASE_DATE') || define('RELEASE_DATE', '2025-06-09');
|
||||
defined('RELEASE_DATE') || define('RELEASE_DATE', '2025-06-17');
|
||||
defined('IN_TRACKER') || define('IN_TRACKER', false);
|
||||
defined('PROJECTNAME') || define("PROJECTNAME","NexusPHP");
|
||||
defined('NEXUSPHPURL') || define("NEXUSPHPURL","https://nexusphp.org");
|
||||
|
||||
@@ -1191,8 +1191,6 @@ function clear_agent_allow_deny_cache()
|
||||
\Nexus\Database\NexusDB::cache_del($denyCacheKey . $suffix);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function user_can($permission, $fail = false, $uid = 0): bool
|
||||
{
|
||||
$log = "permission: $permission, fail: $fail, user: $uid";
|
||||
|
||||
@@ -353,6 +353,15 @@ class Update extends Install
|
||||
Setting::updateUserTokenPermissionAllowedCache(TokenRepository::listUserTokenPermissions(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.9.5
|
||||
*/
|
||||
if (!Schema::hasColumn("snatched", "hit_and_run_id")) {
|
||||
$this->runMigrate("database/migrations/2025_06_09_222012_add_hr_and_buy_id_to_snatched_table.php");
|
||||
Artisan::call("upgrade:migrate_snatched_hr_id");
|
||||
Artisan::call("upgrade:migrate_snatched_buy_log_id");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function runExtraMigrate()
|
||||
|
||||
@@ -422,6 +422,7 @@ final class Nexus
|
||||
public static function dispatchQueueJob(ShouldQueue $job): void
|
||||
{
|
||||
self::getQueueManager()->connection(self::QUEUE_CONNECTION_NAME)->push($job);
|
||||
do_log("dispatchQueueJob: " . nexus_json_encode($job));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -347,6 +347,46 @@ $log .= ", [SEED_BOX], isSeedBoxRuleEnabled: $isSeedBoxRuleEnabled, isIPSeedBox:
|
||||
|
||||
do_log($log);
|
||||
|
||||
//handle paid torrent
|
||||
if (
|
||||
$seeder == 'no'
|
||||
&& isset($az['seedbonus'])
|
||||
&& isset($torrent['price'])
|
||||
&& $torrent['price'] > 0
|
||||
&& $torrent['owner'] != $userid
|
||||
&& get_setting("torrent.paid_torrent_enabled") == "yes"
|
||||
) {
|
||||
$torrentRep = new \App\Repositories\TorrentRepository();
|
||||
$buyStatus = $torrentRep->getBuyStatus($userid, $torrentid);
|
||||
do_log("user: $userid buy torrent: $torrentid, status: $buyStatus");
|
||||
if ($buyStatus > 0) {
|
||||
do_log(sprintf("user: %s buy torrent: %s fail count: %s", $userid, $torrentid, $buyStatus), "error");
|
||||
if ($buyStatus > 3) {
|
||||
//warn
|
||||
\App\Utils\MsgAlert::getInstance()->add(
|
||||
"announce_paid_torrent_too_many_times",
|
||||
time() + 86400,
|
||||
"announce to paid torrent and fail too many times, please make sure you have enough bonus!",
|
||||
"",
|
||||
"black"
|
||||
);
|
||||
}
|
||||
if ($buyStatus > 10) {
|
||||
//disable download
|
||||
(new \App\Repositories\UserRepository())->updateDownloadPrivileges(null, $userid, 'no', 'announce_paid_torrent_too_many_times');
|
||||
}
|
||||
\Nexus\Nexus::dispatchQueueJob(new \App\Jobs\BuyTorrent($userid, $torrentid));
|
||||
//already fail, add fail times
|
||||
$torrentRep->addBuyFailCache($userid, $torrentid);
|
||||
warn("purchase in progress, please try again later, and make sure you have enough bonus", 300);
|
||||
}
|
||||
if ($buyStatus == \App\Repositories\TorrentRepository::BUY_STATUS_UNKNOWN) {
|
||||
//just enqueue job
|
||||
\Nexus\Nexus::dispatchQueueJob(new \App\Jobs\BuyTorrent($userid, $torrentid));
|
||||
warn("purchase started, please wait", 300);
|
||||
}
|
||||
}
|
||||
|
||||
// current peer_id, or you could say session with tracker not found in table peers
|
||||
if (!isset($self))
|
||||
{
|
||||
@@ -393,42 +433,6 @@ if (!isset($self))
|
||||
}
|
||||
}
|
||||
}
|
||||
if (
|
||||
$seeder == 'no'
|
||||
&& isset($az['seedbonus'])
|
||||
&& isset($torrent['price'])
|
||||
&& $torrent['price'] > 0
|
||||
&& $torrent['owner'] != $userid
|
||||
&& get_setting("torrent.paid_torrent_enabled") == "yes"
|
||||
) {
|
||||
$torrentRep = new \App\Repositories\TorrentRepository();
|
||||
$buyStatus = $torrentRep->getBuyStatus($userid, $torrentid);
|
||||
if ($buyStatus > 0) {
|
||||
do_log(sprintf("user: %v buy torrent: %v fail count: %v", $userid, $torrentid, $buyStatus), "error");
|
||||
if ($buyStatus > 3) {
|
||||
//warn
|
||||
\App\Utils\MsgAlert::getInstance()->add(
|
||||
"announce_paid_torrent_too_many_times",
|
||||
time() + 86400,
|
||||
"announce to paid torrent and fail too many times, please make sure you have enough bonus!",
|
||||
"",
|
||||
"black"
|
||||
);
|
||||
}
|
||||
if ($buyStatus > 10) {
|
||||
//disable download
|
||||
(new \App\Repositories\UserRepository())->updateDownloadPrivileges(null, $userid, 'no', 'announce_paid_torrent_too_many_times');
|
||||
}
|
||||
//already fail, add fail times
|
||||
$torrentRep->addBuyFailCache($userid, $torrentid);
|
||||
warn("purchase fail, please try again later, please make sure you have enough bonus", 300);
|
||||
}
|
||||
if ($buyStatus == \App\Repositories\TorrentRepository::BUY_STATUS_UNKNOWN) {
|
||||
//just enqueue job
|
||||
\App\Utils\ThirdPartyJob::addBuyTorrent($userid, $torrentid);
|
||||
warn("purchase in progress, please wait", 300);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // continue an existing session
|
||||
{
|
||||
@@ -567,7 +571,11 @@ if (($left > 0 || $event == "completed") && $az['class'] < \App\Models\HitAndRun
|
||||
$userid, $torrentid, $snatchInfo['id'], $nowStr, $nowStr, $nowStr
|
||||
);
|
||||
$affectedRows = sql_query($sql);
|
||||
do_log("$hrLog, total downloaded: {$snatchInfo['downloaded']} >= required: $requiredDownloaded, [INSERT_H&R], sql: $sql, affectedRows: $affectedRows");
|
||||
$hitAndRunId = mysql_insert_id();
|
||||
do_log("$hrLog, total downloaded: {$snatchInfo['downloaded']} >= required: $requiredDownloaded, [INSERT_H&R], sql: $sql, affectedRows: $affectedRows, hitAndRunId: $hitAndRunId");
|
||||
if ($hitAndRunId > 0) {
|
||||
sql_query("update snatched set hit_and_run_id = $hitAndRunId where id = {$snatchInfo['id']}");
|
||||
}
|
||||
} else {
|
||||
do_log("$hrLog, total downloaded: {$snatchInfo['downloaded']} < required: $requiredDownloaded", "debug");
|
||||
}
|
||||
|
||||
@@ -9,6 +9,9 @@ function bark($msg) {
|
||||
dbconn();
|
||||
loggedinorreturn();
|
||||
user_can('staffmem', true);
|
||||
if (empty($_POST['delreport'])) {
|
||||
stderr('Error', $lang_functions['select_at_least_one_record']);
|
||||
}
|
||||
if ($_POST['setdealt']){
|
||||
$res = sql_query ("SELECT id FROM reports WHERE dealtwith=0 AND id IN (" . implode(", ", $_POST['delreport']) . ")");
|
||||
while ($arr = mysql_fetch_assoc($res))
|
||||
|
||||
@@ -769,7 +769,8 @@ if (isset($searchstr))
|
||||
case 1 : // torrent description
|
||||
{
|
||||
foreach ($like_expression_array as &$like_expression_array_element)
|
||||
$like_expression_array_element = "torrents.descr". $like_expression_array_element;
|
||||
// $like_expression_array_element = "torrents.descr". $like_expression_array_element;
|
||||
$like_expression_array_element = "torrent_extras.descr". $like_expression_array_element;
|
||||
$wherea[] = implode($ANDOR, $like_expression_array);
|
||||
break;
|
||||
}
|
||||
@@ -913,12 +914,16 @@ if ($tagId > 0) {
|
||||
$tagFilter = " inner join torrent_tags on torrents.id = torrent_tags.torrent_id and torrent_tags.tag_id = $tagId ";
|
||||
$addparam .= "tag_id={$tagId}&";
|
||||
}
|
||||
$torrentExtraFilter = "";
|
||||
if ($search_area == 1) {
|
||||
$torrentExtraFilter = " inner join torrent_extras on torrents.id = torrent_extras.torrent_id ";
|
||||
}
|
||||
if ($allsec == 1 || $enablespecial != 'yes')
|
||||
{
|
||||
if ($where != "")
|
||||
$where = "WHERE $where ";
|
||||
else $where = "";
|
||||
$sql = "SELECT COUNT(*) FROM torrents " . ($search_area == 3 || $column == "owner" ? "LEFT JOIN users ON torrents.owner = users.id " : "") . $tagFilter . $where;
|
||||
$sql = "SELECT COUNT(*) FROM torrents " . ($search_area == 3 || $column == "owner" ? "LEFT JOIN users ON torrents.owner = users.id " : "") . $tagFilter . $torrentExtraFilter . $where;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -930,7 +935,7 @@ else
|
||||
$where = "WHERE $where";
|
||||
else $where = "";
|
||||
// $sql = "SELECT COUNT(*), categories.mode FROM torrents LEFT JOIN categories ON category = categories.id " . ($search_area == 3 || $column == "owner" ? "LEFT JOIN users ON torrents.owner = users.id " : "") . $tagFilter . $where . " GROUP BY categories.mode";
|
||||
$sql = "SELECT COUNT(*) FROM torrents " . ($search_area == 3 || $column == "owner" ? "LEFT JOIN users ON torrents.owner = users.id " : "") . $tagFilter . $where;
|
||||
$sql = "SELECT COUNT(*) FROM torrents " . ($search_area == 3 || $column == "owner" ? "LEFT JOIN users ON torrents.owner = users.id " : "") . $tagFilter . $torrentExtraFilter . $where;
|
||||
}
|
||||
|
||||
if ($shouldUseMeili) {
|
||||
@@ -986,7 +991,7 @@ if ($count)
|
||||
// $query = "SELECT $fieldsStr FROM torrents ".($search_area == 3 || $column == "owner" ? "LEFT JOIN users ON torrents.owner = users.id " : "")." $tagFilter $where $orderby $limit";
|
||||
// } else {
|
||||
// $query = "SELECT $fieldsStr, categories.mode as search_box_id FROM torrents ".($search_area == 3 || $column == "owner" ? "LEFT JOIN users ON torrents.owner = users.id " : "")." LEFT JOIN categories ON torrents.category=categories.id $tagFilter $where $orderby $limit";
|
||||
$query = "SELECT $fieldsStr, $sectiontype as search_box_id FROM torrents ".($search_area == 3 || $column == "owner" ? "LEFT JOIN users ON torrents.owner = users.id " : "")."$tagFilter $where $orderby $limit";
|
||||
$query = "SELECT $fieldsStr, $sectiontype as search_box_id FROM torrents ".($search_area == 3 || $column == "owner" ? "LEFT JOIN users ON torrents.owner = users.id " : "")."$tagFilter $torrentExtraFilter $where $orderby $limit";
|
||||
// }
|
||||
do_log("[TORRENT_LIST_SQL] $query", 'debug');
|
||||
if (!$shouldUseMeili) {
|
||||
|
||||
Reference in New Issue
Block a user