diff --git a/app/Repositories/TorrentRepository.php b/app/Repositories/TorrentRepository.php
index c93f5780..83f7c67a 100644
--- a/app/Repositories/TorrentRepository.php
+++ b/app/Repositories/TorrentRepository.php
@@ -41,10 +41,17 @@
class TorrentRepository extends BaseRepository
{
- const BOUGHT_USER_CACHE_KEY_PREFIX = "torrent_purchasers:";
+ const BOUGHT_USER_CACHE_KEY_PREFIX = "torrent_purchasers";
+
+ const BUY_FAIL_CACHE_KEY_PREFIX = "torrent_purchase_fails";
const PIECES_HASH_CACHE_KEY = "torrent_pieces_hash";
+ const BUY_STATUS_SUCCESS = 0;
+ const BUY_STATUS_NOT_YET = -1;
+
+
+
/**
* fetch torrent list
*
@@ -764,15 +771,102 @@ public function loadBoughtUser($torrentId): int
return $total;
}
- public function addBoughtUserToCache($torrentId, $uid)
+ /**
+ * 购买成功缓存,保存为 hash,一个种子一个 hash,永久有效
+ * @param $uid
+ * @param $torrentId
+ * @return void
+ * @throws \RedisException
+ */
+ public function addBuySuccessCache($uid, $torrentId): void
{
NexusDB::redis()->hSet($this->getBoughtUserCacheKey($torrentId), $uid, 1);
}
+ public function hasBuySuccessCache($uid, $torrentId): bool
+ {
+ return NexusDB::redis()->hGet($this->getBoughtUserCacheKey($torrentId), $uid) == 1;
+ }
- private function getBoughtUserCacheKey($torrentId): string
+ /**
+ * 获取购买种子的缓存状态
+ *
+ * @param $uid
+ * @param $torrentId
+ * @return int
+ */
+ public function getBuyStatus($uid, $torrentId): int
+ {
+ //查询是否已经购买
+ if ($this->hasBuySuccessCache($uid, $torrentId)) {
+ return self::BUY_STATUS_SUCCESS;
+ }
+ //是否购买失败过
+ $buyFailCount = $this->getBuyFailCache($uid, $torrentId);
+ if ($buyFailCount > 0) {
+ //根据失败次数,禁用下载权限并做提示等
+ return $buyFailCount;
+ }
+ //购买失败缓存失效后,再重新查询数据库确定最终状态
+ $hasBuyFromDB = TorrentBuyLog::query()->where("uid", $uid)->where("torrent_id", $torrentId)->exists();
+ if ($hasBuyFromDB) {
+ //标记购买成功, 返回已购买
+ $this->addBuySuccessCache($uid, $torrentId);
+ return self::BUY_STATUS_SUCCESS;
+ } else {
+ //返回未购买,前端可执行购买逻辑
+ return self::BUY_STATUS_NOT_YET;
+ }
+ }
+
+ /**
+ * 添加购买失败缓存, 结果累加
+ * @param $uid
+ * @param $torrentId
+ * @return void
+ * @throws \RedisException
+ */
+ public function addBuyFailCache($uid, $torrentId): void
+ {
+ $key = $this->getBuyFailCacheKey($uid, $torrentId);
+ $result = NexusDB::redis()->incr($key);
+ if ($result == 1) {
+ NexusDB::redis()->expire($key, 3600);
+ }
+ }
+
+ /**
+ * 获取失败缓存 ,结果是失败的次数
+ *
+ * @param $uid
+ * @param $torrentId
+ * @return int
+ * @throws \RedisException
+ */
+ public function getBuyFailCache($uid, $torrentId): int
+ {
+ return intval(NexusDB::redis()->get($this->getBuyFailCacheKey($uid, $torrentId)));
+ }
+
+ /**
+ * 购买成功缓存 key
+ * @param $torrentId
+ * @return string
+ */
+ public function getBoughtUserCacheKey($torrentId): string
+ {
+ return sprintf("%s:%s", self::BOUGHT_USER_CACHE_KEY_PREFIX, $torrentId);
+ }
+
+ /**
+ * 购买失败缓存 key
+ * @param int $userId
+ * @param int $torrentId
+ * @return string
+ */
+ public function getBuyFailCacheKey(int $userId, int $torrentId): string
{
- return self::BOUGHT_USER_CACHE_KEY_PREFIX . $torrentId;
+ return sprintf("%s:%s:%s", self::BUY_FAIL_CACHE_KEY_PREFIX, $userId, $torrentId);
}
public function addPiecesHashCache(int $torrentId, string $piecesHash): bool|int|\Redis
diff --git a/include/constants.php b/include/constants.php
index f03d4ca2..bda539d3 100644
--- a/include/constants.php
+++ b/include/constants.php
@@ -1,6 +1,6 @@
render();
+
/*
$pending_invitee = $Cache->get_value('user_'.$CURUSER["id"].'_pending_invitee_count');
if ($pending_invitee == ""){
@@ -5907,7 +5909,11 @@ function get_ip_location_from_geoip($ip): bool|array
function msgalert($url, $text, $bgcolor = "red")
{
print("
\n");
- print("".$text."");
+ if (!empty($url)) {
+ print("".$text."");
+ } else {
+ print("".$text."");
+ }
print(" |
");
}
diff --git a/public/announce.php b/public/announce.php
index 50370fe5..6c99a9f9 100644
--- a/public/announce.php
+++ b/public/announce.php
@@ -164,6 +164,13 @@
$redis->set("$passkeyInvalidKey:$passkey", TIMENOW, ['ex' => 24*3600]);
warn("Invalid passkey! Re-download the .torrent from $BASEURL");
}
+if ($az["enabled"] == "no")
+ warn("Your account is disabled!", 300);
+elseif ($az["parked"] == "yes")
+ warn("Your account is parked! (Read the FAQ)", 300);
+elseif ($az["downloadpos"] == "no")
+ warn("Your downloading privileges have been disabled! (Read the rules)", 300);
+
$userid = intval($az['id'] ?? 0);
unset($GLOBALS['CURUSER']);
$CURUSER = $GLOBALS["CURUSER"] = $az;
@@ -401,13 +408,6 @@
if ($valid[0] >= 1 && $seeder == 'no') err("You already are downloading the same torrent. You may only leech from one location at a time.", 300);
if ($valid[0] >= 3 && $seeder == 'yes') err("You cannot seed the same torrent from more than 3 locations.", 300);
- if ($az["enabled"] == "no")
- warn("Your account is disabled!", 300);
- elseif ($az["parked"] == "yes")
- warn("Your account is parked! (Read the FAQ)", 300);
- elseif ($az["downloadpos"] == "no")
- warn("Your downloading privileges have been disabled! (Read the rules)", 300);
-
if ($az["class"] < UC_VIP)
{
$ratio = (($az["downloaded"] > 0) ? ($az["uploaded"] / $az["downloaded"]) : 1);
@@ -451,43 +451,48 @@
&& $torrent['owner'] != $userid
&& get_setting("torrent.paid_torrent_enabled") == "yes"
) {
- $hasBuyCacheKey = \App\Repositories\TorrentRepository::BOUGHT_USER_CACHE_KEY_PREFIX . $torrentid;
- $hasBuy = $redis->hGet($hasBuyCacheKey, $userid);
- if ($hasBuy === false) {
- //no cache
- $lockName = "load_torrent_bought_user:$torrentid";
- $loadBoughtLock = new \Nexus\Database\NexusLock($lockName, 300);
- if ($loadBoughtLock->get()) {
- //get lock, do load
- executeCommand("torrent:load_bought_user $torrentid", "string", true, false);
- } else {
- do_log("can not get loadBoughtLock: $lockName", 'debug');
+ $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');
}
- //simple cache the hasBuy result
- $hasBuy = \Nexus\Database\NexusDB::remember(sprintf("user_has_buy_torrent:%s:%s", $userid, $torrentid), 86400*10, function () use($userid, $torrentid) {
- $exists = \App\Models\TorrentBuyLog::query()->where('uid', $userid)->where('torrent_id', $torrentid)->exists();
- return intval($exists);
- });
+ warn("purchase fail, please try again later, please make sure you have enough bonus", 300);
}
- if (!$hasBuy) {
- $lock = new \Nexus\Database\NexusLock("buying_torrent:$userid", 5);
+ if ($buyStatus == \App\Repositories\TorrentRepository::BUY_STATUS_NOT_YET) {
+ //one by one
+ $lock = new \Nexus\Database\NexusLock("buying_torrent", 5);
if (!$lock->get()) {
$msg = "buying torrent, wait!";
do_log("[ANNOUNCE] user: $userid, torrent: $torrentid, $msg", 'error');
- err($msg);
+ warn($msg, 300);
}
$bonusRep = new \App\Repositories\BonusRepository();
try {
$bonusRep->consumeToBuyTorrent($az['id'], $torrent['id'], 'Web');
- $redis->hSet($hasBuyCacheKey, $userid, 1);
+ $torrentRep->addBuySuccessCache($userid, $torrentid);
$lock->release();
} catch (\Exception $exception) {
$msg = $exception->getMessage();
do_log("[ANNOUNCE] user: $userid, torrent: $torrentid, $msg " . $exception->getTraceAsString(), 'error');
+ $torrentRep->addBuyFailCache($userid, $torrentid);
$lock->release();
err($msg);
}
}
+
}
}
else // continue an existing session
@@ -570,19 +575,7 @@
if ($event != 'stopped') {
$isPeerExistResultSet = sql_query("select id from peers where $selfwhere limit 1");
if (mysql_num_rows($isPeerExistResultSet) == 0) {
- $cacheKey = 'peers:connectable:'.$ip.'-'.$port.'-'.$agent;
- $connectable = \Nexus\Database\NexusDB::remember($cacheKey, 3600, function () use ($ip, $port) {
- if (isIPV6($ip)) {
- $sockres = @fsockopen("tcp://[".$ip."]",$port,$errno,$errstr,1);
- } else {
- $sockres = @fsockopen($ip, $port, $errno, $errstr, 1);
- }
- if (is_resource($sockres)) {
- fclose($sockres);
- return 'yes';
- }
- return 'no';
- });
+ $connectable = "yes";
$insertPeerSql = "INSERT INTO peers (torrent, userid, peer_id, ip, port, connectable, uploaded, downloaded, to_go, started, last_action, seeder, agent, downloadoffset, uploadoffset, passkey, ipv4, ipv6, is_seed_box) VALUES ($torrentid, $userid, ".sqlesc($peer_id).", ".sqlesc($ip).", $port, '$connectable', $uploaded, $downloaded, $left, $dt, $dt, '$seeder', ".sqlesc($agent).", $downloaded, $uploaded, ".sqlesc($passkey).", ".sqlesc($ipv4).", ".sqlesc($ipv6).", ".intval($isIPSeedBox).")";
do_log("[INSERT PEER] peer not exists for $selfwhere, do insert with $insertPeerSql");
@@ -617,7 +610,7 @@
$hrLog = sprintf("[HR_LOG] user: %d, torrent: %d, hrMode: %s", $userid, $torrentid, $hrMode);
if ($hrMode == \App\Models\HitAndRun::MODE_GLOBAL || ($hrMode == \App\Models\HitAndRun::MODE_MANUAL && $torrent['hr'] == \App\Models\Torrent::HR_YES)) {
$hrCacheKey = sprintf("hit_and_run:%d:%d", $userid, $torrentid);
- $hrExists = \Nexus\Database\NexusDB::remember($hrCacheKey, 24*3600, function () use ($torrentid, $userid) {
+ $hrExists = \Nexus\Database\NexusDB::remember($hrCacheKey, mt_rand(86400*365*5, 86400*365*10), function () use ($torrentid, $userid) {
return \App\Models\HitAndRun::query()->where("uid", $userid)->where("torrent_id", $torrentid)->exists();
});
$hrLog .= ", hrExists: $hrExists";
diff --git a/public/details.php b/public/details.php
index 9801a622..24dc8eeb 100644
--- a/public/details.php
+++ b/public/details.php
@@ -6,7 +6,7 @@
loggedinorreturn();
$id = intval($_GET["id"] ?? 0);
$customField = new \Nexus\Field\Field();
-int_check($id);
+int_check($id, true);
if (!isset($id) || !$id)
die();
diff --git a/resources/lang/en/message.php b/resources/lang/en/message.php
index c9f9abf6..3b726590 100644
--- a/resources/lang/en/message.php
+++ b/resources/lang/en/message.php
@@ -19,6 +19,10 @@
'subject' => 'Download permission canceled',
'body' => 'Your download permission has been cancelled due to excessive upload speed, please file if you are a seed box user.' ,
],
+ 'download_disable_announce_paid_torrent_too_many_times' => [
+ 'subject' => 'Download permission canceled',
+ 'body' => 'Your download permission has been cancelled due to announce to paid torrent too many times, please make sure you have enough bonus.' ,
+ ],
'download_enable' => [
'subject' => 'Download permission restored',
'body' => 'Your download privileges restored, you can now download torrents. By: :operator',
diff --git a/resources/lang/zh_CN/message.php b/resources/lang/zh_CN/message.php
index 4e195039..3c57994c 100644
--- a/resources/lang/zh_CN/message.php
+++ b/resources/lang/zh_CN/message.php
@@ -19,6 +19,10 @@
'subject' => '下载权限取消',
'body' => '你因上传速度过快下载权限被取消,若是盒子用户请备案。',
],
+ 'download_disable_announce_paid_torrent_too_many_times' => [
+ 'subject' => '下载权限取消',
+ 'body' => '你因向付费种子汇报失败次数过多下载权限被取消,请确保你有足够的魔力。',
+ ],
'download_enable' => [
'subject' => '下载权限恢复',
'body' => '你的下载权限恢复,你现在可以下载种子。By: :operator',
diff --git a/resources/lang/zh_TW/message.php b/resources/lang/zh_TW/message.php
index b1035fc9..0769ec95 100644
--- a/resources/lang/zh_TW/message.php
+++ b/resources/lang/zh_TW/message.php
@@ -18,6 +18,10 @@
'subject' => '下載權限取消',
'body' => '你因上傳速度過快下載權限被取消,若是盒子用戶請備案。',
],
+ 'download_disable_announce_paid_torrent_too_many_times' => [
+ 'subject' => '下载权限取消',
+ 'body' => '你因向付費種子匯報失敗次數過多下載權限被取消,請確保你有足夠的魔力。',
+ ],
'download_enable' => [
'subject' => '下載權限恢復',
'body' => '你的下載權限恢復,你現在可以下載種子。By: :operator',