fix checkCheater() + handle H&R

This commit is contained in:
xiaomlove
2022-04-08 15:22:30 +08:00
parent e659983724
commit d0449935d8
5 changed files with 79 additions and 18 deletions

View File

@@ -11,6 +11,7 @@ Complete PT website building solution. Based on NexusPHP + Laravel Framework + E
- Exam
- H&R
- Attendance
- Retroactive attendance card
- Medal
- Custom tags
- Forum

View File

@@ -10,6 +10,7 @@
- 考核
- H&R
- 签到
- 补签卡
- 勋章
- 自定义标签
- 论坛

View File

@@ -134,6 +134,9 @@ class Test extends Command
// $key = "dddd1";
// $model = \App\Models\TorrentSecret::query()->where('id', 1)->first();
// \Nexus\Database\NexusDB::cache_put($key, $model);
$r = User::query()->first();
dd($r->donoruntil);
}

View File

@@ -161,7 +161,24 @@ class User extends Authenticatable
*/
protected $casts = [
'added' => 'datetime',
'last_login' => 'datetime',
'last_access' => 'datetime',
'last_home' => 'datetime',
'last_offer' => 'datetime',
'forum_access' => 'datetime',
'last_staffmsg' => 'datetime',
'last_pm' => 'datetime',
'last_comment' => 'datetime',
'last_post' => 'datetime',
'lastwarned' => 'datetime',
'last_browse' => 'datetime:U',
'last_music' => 'datetime:U',
'last_catchup' => 'datetime:U',
'donoruntil' => 'datetime',
'warneduntil' => 'datetime',
'noaduntil' => 'datetime',
'vip_until' => 'datetime',
'leechwarnuntil' => 'datetime',
];
public static $commonFields = [

View File

@@ -9,6 +9,7 @@ namespace App\Repositories;
use App\Exceptions\ClientNotAllowedException;
use App\Models\Cheater;
use App\Models\HitAndRun;
use App\Models\Peer;
use App\Models\Setting;
use App\Models\Snatch;
@@ -58,8 +59,9 @@ class TrackerRepository extends BaseRepository
$user = $this->checkUser($request);
$clientAllow = $this->checkClient($request);
$torrent = $this->checkTorrent($queries, $user);
if ($this->isReAnnounce($queries) === false) {
if ($this->isReAnnounce($request) === false) {
$withPeers = true;
/** @var Peer $peerSelf */
$peerSelf = $this->checkMinInterval($torrent, $queries, $user);
if (!$peerSelf) {
$this->checkPeer($torrent, $queries, $user);
@@ -70,16 +72,24 @@ class TrackerRepository extends BaseRepository
'userid' => $user->id,
'passkey' => $user->passkey,
]);
} else {
$this->checkCheater($torrent, $queries, $user, $peerSelf);
}
/**
* Note: Must get before update peer!
*/
$dataTraffic = $this->getDataTraffic($torrent, $queries, $user, $peerSelf);
/**
* Note: Only check in old session
*/
if ($peerSelf->exists) {
$this->checkCheater($torrent, $dataTraffic, $user, $peerSelf);
}
$this->updatePeer($peerSelf, $queries);
$this->updateSnatch($peerSelf, $queries, $dataTraffic);
$snatch = $this->updateSnatch($peerSelf, $queries, $dataTraffic);
if ($queries['event'] == 'completed') {
$this->handleHitAndRun($user, $torrent, $snatch);
}
$this->updateTorrent($torrent, $queries);
if ($dataTraffic['uploaded_increment_for_user'] > 0) {
@@ -418,7 +428,7 @@ class TrackerRepository extends BaseRepository
return $peer;
}
protected function checkCheater(Torrent $torrent, $queries, User $user, Peer $peer)
protected function checkCheater(Torrent $torrent, $dataTraffic, User $user, Peer $peer)
{
$settingSecurity = Setting::get('security');
$level = $settingSecurity['cheaterdet'];
@@ -435,7 +445,8 @@ class TrackerRepository extends BaseRepository
return;
}
$duration = Carbon::now()->diffInSeconds($peer->last_action);
$upSpeed = $queries['uploaded'] > 0 ? ($queries['uploaded'] / $duration) : 0;
$upSpeed = $dataTraffic['uploaded_increment'] > 0 ? ($dataTraffic['uploaded_increment'] / $duration) : 0;
do_log("peer: " . $peer->toJson() . ", upSpeed: $upSpeed, dataTraffic: " . json_encode($dataTraffic));
$oneGB = 1024 * 1024 * 1024;
$tenMB = 1024 * 1024 * 10;
$nowStr = Carbon::now()->toDateTimeString();
@@ -443,14 +454,14 @@ class TrackerRepository extends BaseRepository
'added' => $nowStr,
'userid' => $user->id,
'torrentid' => $torrent->id,
'uploaded' => $queries['uploaded'],
'downloaded' => $queries['downloaded'],
'uploaded' => $dataTraffic['uploaded_increment'],
'downloaded' => $dataTraffic['downloaded_increment'],
'anctime' => $duration,
'seeders' => $torrent->seeders,
'leechers' => $torrent->leechers,
];
if ($queries['uploaded'] > $oneGB && ($upSpeed > self::MUST_BE_CHEATER_SPEED / $level)) {
if ($dataTraffic['uploaded_increment'] > $oneGB && ($upSpeed > self::MUST_BE_CHEATER_SPEED / $level)) {
//Uploaded more than 1 GB with uploading rate higher than 1024 MByte/S (For Consertive level). This is no doubt cheating.
$comment = "User account was automatically disabled by system";
$data = array_merge($cheaterBaseData, ['comment' => $comment]);
@@ -460,7 +471,7 @@ class TrackerRepository extends BaseRepository
throw new TrackerException($modComment);
}
if ($queries['uploaded'] > $oneGB && ($upSpeed > self::MAY_BE_CHEATER_SPEED / $level)) {
if ($dataTraffic['uploaded_increment'] > $oneGB && ($upSpeed > self::MAY_BE_CHEATER_SPEED / $level)) {
//Uploaded more than 1 GB with uploading rate higher than 100 MByte/S (For Consertive level). This is likely cheating.
$comment = "Abnormally high uploading rate";
$data = array_merge($cheaterBaseData, ['comment' => $comment]);
@@ -468,14 +479,14 @@ class TrackerRepository extends BaseRepository
}
if ($level > 1) {
if ($queries['uploaded'] > $oneGB && ($upSpeed > 1024 * 1024) && ($queries['leechers'] < 2 * $level)) {
if ($dataTraffic['uploaded_increment'] > $oneGB && ($upSpeed > 1024 * 1024) && ($torrent->leechers < 2 * $level)) {
//Uploaded more than 1 GB with uploading rate higher than 1 MByte/S when there is less than 8 leechers (For Consertive level). This is likely cheating.
$comment = "User is uploading fast when there is few leechers";
$data = array_merge($cheaterBaseData, ['comment' => $comment]);
$this->createOrUpdateCheater($torrent, $user, $data);
}
if ($queries['uploaded'] > $tenMB && ($upSpeed > 1024 * 100) && ($queries['leechers'] == 0)) {
if ($dataTraffic['uploaded_increment'] > $tenMB && ($upSpeed > 1024 * 100) && ($torrent->leechers == 0)) {
///Uploaded more than 10 MB with uploading speed faster than 100 KByte/S when there is no leecher. This is likely cheating.
$comment = "User is uploading when there is no leecher";
$data = array_merge($cheaterBaseData, ['comment' => $comment]);
@@ -500,12 +511,15 @@ class TrackerRepository extends BaseRepository
}
}
protected function isReAnnounce(array $queries): bool
protected function isReAnnounce(Request $request): bool
{
unset($queries['key']);
$lockKey = md5(http_build_query($queries));
$key = $request->query->get('key');
$queryString = $request->getQueryString();
$lockKey = md5(str_replace($key, '', $queryString));
$startTimestamp = nexus()->getStartTimestamp();
do_log("key: $key, queryString: $queryString, lockKey: $lockKey, startTimestamp: $startTimestamp");
$redis = Redis::connection()->client();
if (!$redis->set($lockKey, nexus()->getStartTimestamp(), ['nx', 'ex' => 5])) {
if (!$redis->set($lockKey, $startTimestamp, ['nx', 'ex' => 5])) {
do_log('[RE_ANNOUNCE]');
return true;
}
@@ -590,8 +604,8 @@ class TrackerRepository extends BaseRepository
$torrent->id, $user->id, $peer->id, $queries['uploaded'], $queries['downloaded']
);
if ($peer->exists) {
$realUploaded = max($queries['uploaded'] - $peer->uploaded, 0);
$realDownloaded = max($queries['downloaded'] - $peer->downloaded, 0);
$realUploaded = max(bcsub($queries['uploaded'], $peer->uploaded), 0);
$realDownloaded = max(bcsub($queries['downloaded'], $peer->downloaded), 0);
$log .= ", [PEER_EXISTS], realUploaded: $realUploaded, realDownloaded: $realDownloaded";
} else {
$realUploaded = $queries['uploaded'];
@@ -785,6 +799,8 @@ class TrackerRepository extends BaseRepository
$snatch->save();
do_log(last_query(), 'debug');
return $snatch;
}
public function scrape(Request $request): \Illuminate\Http\Response
@@ -877,4 +893,27 @@ class TrackerRepository extends BaseRepository
});
}
private function handleHitAndRun(User $user, Torrent $torrent, Snatch $snatch)
{
$now = Carbon::now();
if ($user->class >= \App\Models\HitAndRun::MINIMUM_IGNORE_USER_CLASS) {
return;
}
if ($user->donoruntil && $user->donoruntil->gte($now)) {
return;
}
$hrMode = Setting::get('hr.mode');
if ($hrMode == HitAndRun::MODE_DISABLED) {
return;
}
if ($hrMode == HitAndRun::MODE_MANUAL && $torrent->hr != Torrent::HR_YES) {
return;
}
$sql = sprintf(
"insert into `hit_and_runs` (`uid`, `torrent_id`, `snatched_id`) values(%d, %d, %d) on duplicate key update updated_at = '%s'",
$user->id, $torrent->id, $snatch->id, $now->toDateTimeString()
);
DB::statement($sql);
}
}