diff --git a/README.md b/README.md index d01055b..e407672 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ git checkout -b my-pr-branch-name + [x] Options + [x] Public + [x] Sensitive - + [ ] Comments + + [x] Comments + [ ] Features + [x] Scrape trackers + [x] Peers @@ -71,7 +71,7 @@ git checkout -b my-pr-branch-name + [x] Leechers + [x] Stars + [x] Downloads - + [ ] Comments + + [x] Threading comments + [ ] Views + [ ] Info page diff --git a/database/yggtracker.mwb b/database/yggtracker.mwb index 59fce6f..9541d33 100644 Binary files a/database/yggtracker.mwb and b/database/yggtracker.mwb differ diff --git a/src/config/app.php.example b/src/config/app.php.example index 9feba8d..c459053 100644 --- a/src/config/app.php.example +++ b/src/config/app.php.example @@ -83,6 +83,12 @@ define('MAGNET_EDITOR_LOCK_TIMEOUT', 60*60); define('MAGNET_META_TITLE_MIN_LENGTH', 10); define('MAGNET_META_DESCRIPTION_MIN_LENGTH', 0); +// Comment +define('COMMENT_DEFAULT_APPROVED', false); +define('COMMENT_DEFAULT_PUBLIC', false); +define('COMMENT_MIN_LENGTH', 1); +define('COMMENT_MAX_LENGTH', 1000); + // Trackers define('TRACKER_LINKS', (object) [ diff --git a/src/library/database.php b/src/library/database.php index 1658d36..c6d78e1 100644 --- a/src/library/database.php +++ b/src/library/database.php @@ -471,6 +471,17 @@ class Database { return $this->addUser($address, $approved, $timeAdded); } + public function updateUserApproved(int $userId, mixed $approved, int $timeUpdated) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `user` SET `approved` = ?, `timeUpdated` = ? WHERE `userId` = ?'); + + $query->execute([(int) $approved, $timeUpdated, $userId]); + + return $query->rowCount(); + } + // Magnet public function addMagnet(int $userId, string $xt, @@ -961,6 +972,61 @@ class Database { } // Magnet comment + public function addMagnetComment( int $magnetId, + int $userId, + mixed $magnetCommentIdParent, + string $value, + bool $approved, + bool $public, + int $timeAdded) : int { + + $this->_debug->query->insert->total++; + + $query = $this->_db->prepare('INSERT INTO `magnetComment` SET `magnetId` = ?, + `userId` = ?, + `magnetCommentIdParent` = ?, + `value` = ?, + `approved` = ?, + `public` = ?, + `timeAdded` = ?'); + + $query->execute( + [ + $magnetId, + $userId, + $magnetCommentIdParent, + $value, + $approved, + $public, + $timeAdded + ] + ); + + return $this->_db->lastInsertId(); + } + + public function updateMagnetCommentPublic(int $magnetCommentId, mixed $public) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `magnetComment` SET `public` = ? WHERE `magnetCommentId` = ?'); + + $query->execute([(int) $public, $magnetCommentId]); + + return $query->rowCount(); + } + + public function updateMagnetCommentApproved(int $magnetCommentId, mixed $approved) : int { + + $this->_debug->query->update->total++; + + $query = $this->_db->prepare('UPDATE `magnetComment` SET `approved` = ? WHERE `magnetCommentId` = ?'); + + $query->execute([(int) $approved, $magnetCommentId]); + + return $query->rowCount(); + } + public function getMagnetCommentsTotal(int $magnetId) : int { $this->_debug->query->select->total++; @@ -972,6 +1038,26 @@ class Database { return $query->fetch()->result; } + public function getMagnetComments(int $magnetId, mixed $magnetCommentIdParent = null) { + + $this->_debug->query->select->total++; + + if ($magnetCommentIdParent) + { + $query = $this->_db->prepare('SELECT * FROM `magnetComment` WHERE `magnetId` = ? AND `magnetCommentIdParent` = ?'); + + $query->execute([$magnetId, $magnetCommentIdParent]); + } + else + { + $query = $this->_db->prepare('SELECT * FROM `magnetComment` WHERE `magnetId` = ? AND `magnetCommentIdParent` IS NULL'); + + $query->execute([$magnetId]); + } + + return $query->fetchAll(); + } + public function findMagnetCommentsTotalByUserId(int $magnetId, int $userId) : int { $this->_debug->query->select->total++; @@ -983,6 +1069,17 @@ class Database { return $query->fetch()->result; } + public function getMagnetComment(int $magnetCommentId) { + + $this->_debug->query->select->total++; + + $query = $this->_db->prepare('SELECT * FROM `magnetComment` WHERE `magnetCommentId` = ?'); + + $query->execute([$magnetCommentId]); + + return $query->fetch(); + } + // Magnet star public function addMagnetStar(int $magnetId, int $userId, int $timeAdded) : int { diff --git a/src/public/action.php b/src/public/action.php index 9ceba22..0cb7581 100644 --- a/src/public/action.php +++ b/src/public/action.php @@ -29,6 +29,246 @@ switch (isset($_GET['target']) ? urldecode($_GET['target']) : false) { case 'comment': + switch (isset($_GET['toggle']) ? $_GET['toggle'] : false) + { + case 'approved': + + // Yggdrasil connections only + if (!preg_match(YGGDRASIL_URL_REGEX, $_SERVER['REMOTE_ADDR'])) + { + $response->success = false; + $response->message = _('Yggdrasil connection required for this action'); + } + + // Init session + else if (!$userId = $db->initUserId($_SERVER['REMOTE_ADDR'], USER_DEFAULT_APPROVED, time())) + { + $response->success = false; + $response->message = _('Could not init user session'); + } + + // Get user + else if (!$user = $db->getUser($userId)) + { + $response->success = false; + $response->message = _('Could not init user info'); + } + + // Magnet comment exists + else if (!$magnetComment = $db->getMagnetComment(isset($_GET['magnetCommentId']) && $_GET['magnetCommentId'] > 0 ? (int) $_GET['magnetCommentId'] : 0)) + { + $response->success = false; + $response->message = _('Requested magnet comment not found'); + } + + // Access allowed + else if (!in_array($user->address, MODERATOR_IP_LIST)) { + + $response->success = false; + $response->message = _('Access denied'); + } + + // Validate callback + else if (empty($_GET['callback'])) + { + $response->success = false; + $response->message = _('Callback required'); + } + + // Validate base64 + else if (!$callback = (string) @base64_decode($_GET['callback'])) + { + $response->success = false; + $response->message = _('Invalid callback encoding'); + } + + // Request valid + else + { + if ($magnetComment->approved) + { + $db->updateMagnetCommentApproved($magnetComment->magnetCommentId, false); + + if (USER_AUTO_APPROVE_ON_COMMENT_APPROVE) + { + $db->updateUserApproved($magnetComment->userId, false, time()); + } + } + else + { + $db->updateMagnetCommentApproved($magnetComment->magnetCommentId, true); + + if (USER_AUTO_APPROVE_ON_COMMENT_APPROVE) + { + $db->updateUserApproved($magnetComment->userId, true, time()); + } + } + + // Redirect to edit page + header( + sprintf('Location: %s', $callback) + ); + } + + break; + + case 'public': + + // Yggdrasil connections only + if (!preg_match(YGGDRASIL_URL_REGEX, $_SERVER['REMOTE_ADDR'])) + { + $response->success = false; + $response->message = _('Yggdrasil connection required for this action'); + } + + // Init session + else if (!$userId = $db->initUserId($_SERVER['REMOTE_ADDR'], USER_DEFAULT_APPROVED, time())) + { + $response->success = false; + $response->message = _('Could not init user session'); + } + + // Get user + else if (!$user = $db->getUser($userId)) + { + $response->success = false; + $response->message = _('Could not init user info'); + } + + // Magnet comment exists + else if (!$magnetComment = $db->getMagnetComment(isset($_GET['magnetCommentId']) && $_GET['magnetCommentId'] > 0 ? (int) $_GET['magnetCommentId'] : 0)) + { + $response->success = false; + $response->message = _('Requested magnet comment not found'); + } + + // Access allowed + else if (!($user->address == $db->getUser($magnetComment->userId)->address || in_array($user->address, MODERATOR_IP_LIST))) { + + $response->success = false; + $response->message = _('Access denied'); + } + + // Validate callback + else if (empty($_GET['callback'])) + { + $response->success = false; + $response->message = _('Callback required'); + } + + // Validate base64 + else if (!$callback = (string) @base64_decode($_GET['callback'])) + { + $response->success = false; + $response->message = _('Invalid callback encoding'); + } + + // Request valid + else + { + if ($magnetComment->public) + { + $db->updateMagnetCommentPublic($magnetComment->magnetCommentId, false); + } + else{ + $db->updateMagnetCommentPublic($magnetComment->magnetCommentId, true); + } + + // Redirect to edit page + header( + sprintf('Location: %s', $callback) + ); + } + + break; + + case 'new': + + // Yggdrasil connections only + if (!preg_match(YGGDRASIL_URL_REGEX, $_SERVER['REMOTE_ADDR'])) + { + $response->success = false; + $response->message = _('Yggdrasil connection required for this action'); + } + + // Init session + else if (!$userId = $db->initUserId($_SERVER['REMOTE_ADDR'], USER_DEFAULT_APPROVED, time())) + { + $response->success = false; + $response->message = _('Could not init user session'); + } + + // Get user + else if (!$user = $db->getUser($userId)) + { + $response->success = false; + $response->message = _('Could not init user info'); + } + + // Magnet exists + else if (!$magnet = $db->getMagnet(isset($_GET['magnetId']) && $_GET['magnetId'] > 0 ? (int) $_GET['magnetId'] : 0)) + { + $response->success = false; + $response->message = _('Requested magnet not found'); + } + + // Access allowed + else if (!($user->address == $db->getUser($magnet->userId)->address || in_array($user->address, MODERATOR_IP_LIST) || ($magnet->public && $magnet->approved))) { + + $response->success = false; + $response->message = _('Magnet not available for this action'); + } + + // Validate callback + else if (empty($_GET['callback'])) + { + $response->success = false; + $response->message = _('Callback required'); + } + + // Validate base64 + else if (!$callback = (string) @base64_decode($_GET['callback'])) + { + $response->success = false; + $response->message = _('Invalid callback encoding'); + } + + // Validate comment value + else if (empty($_POST['comment']) || + mb_strlen($_POST['comment']) < COMMENT_MIN_LENGTH || + mb_strlen($_POST['comment']) > COMMENT_MAX_LENGTH) + { + $response->success = false; + $response->message = sprintf(_('Valid comment value required, %s-%s chars allowed'), COMMENT_MIN_LENGTH, COMMENT_MAX_LENGTH); + } + + // Request valid + else + { + if ($magnetCommentId = $db->addMagnetComment($magnet->magnetId, + $user->userId, + null, // @TODO implement threads + trim($_POST['comment']), + $user->approved || in_array($user->address, MODERATOR_IP_LIST) ? true : COMMENT_DEFAULT_APPROVED, + COMMENT_DEFAULT_PUBLIC, + time())) + { + // Redirect to referrer page + header( + sprintf('Location: %s#comment-%s', $callback, $magnetCommentId) + ); + } + } + + break; + + default: + + header( + sprintf('Location: %s', WEBSITE_URL) + ); + } + break; case 'star': diff --git a/src/public/assets/theme/default/css/common.css b/src/public/assets/theme/default/css/common.css index 2919dfb..1636283 100644 --- a/src/public/assets/theme/default/css/common.css +++ b/src/public/assets/theme/default/css/common.css @@ -50,9 +50,11 @@ input:focus { color: #fff; } +/* @TODO improve focus out textarea:focus { min-height: 120px; } +*/ textarea::placeholder, input::placeholder { diff --git a/src/public/edit.php b/src/public/edit.php index 888dfb0..309ca13 100644 --- a/src/public/edit.php +++ b/src/public/edit.php @@ -114,6 +114,10 @@ $response = (object) 'message' => false, ] ], + 'approved' => (object) + [ + 'value' => false, + ], ] ]; @@ -370,6 +374,7 @@ else { $response->form->public->value = (bool) $magnet->public; $response->form->comments->value = (bool) $magnet->comments; $response->form->sensitive->value = (bool) $magnet->sensitive; + $response->form->approved->value = (bool) $magnet->approved; // Display Name $response->form->dn->value = $magnet->dn; @@ -549,7 +554,7 @@ else { address, MODERATOR_IP_LIST)) { ?>
- + form->approved->value) { ?> diff --git a/src/public/index.php b/src/public/index.php index 3126d13..aa9c142 100644 --- a/src/public/index.php +++ b/src/public/index.php @@ -64,6 +64,13 @@ else if (!$userId = $db->initUserId($_SERVER['REMOTE_ADDR'], USER_DEFAULT_APPROV $response->message = _('Could not init user session'); } +// Get user +else if (!$user = $db->getUser($userId)) +{ + $response->success = false; + $response->message = _('Could not init user info'); +} + // Request valid else { @@ -89,10 +96,10 @@ else if ($magnet = $db->getMagnet($result->magnetid)) { // Get access info - $accessRead = ($_SERVER['REMOTE_ADDR'] == $db->getUser($magnet->userId)->address || in_array($_SERVER['REMOTE_ADDR'], MODERATOR_IP_LIST) || ($magnet->public && $magnet->approved)); - $accessEdit = ($_SERVER['REMOTE_ADDR'] == $db->getUser($magnet->userId)->address || in_array($_SERVER['REMOTE_ADDR'], MODERATOR_IP_LIST)); + $accessRead = ($user->address == $db->getUser($magnet->userId)->address || in_array($user->address, MODERATOR_IP_LIST) || ($magnet->public && $magnet->approved)); + $accessEdit = ($user->address == $db->getUser($magnet->userId)->address || in_array($user->address, MODERATOR_IP_LIST)); - // Update magnet viwed + // Update magnet viewed if ($accessRead) { $db->addMagnetView($magnet->magnetId, $userId, time()); @@ -360,7 +367,6 @@ echo '' . PHP_EOL ?> star->total ?> - download->status) { ?> diff --git a/src/public/magnet.php b/src/public/magnet.php new file mode 100644 index 0000000..4d5f30a --- /dev/null +++ b/src/public/magnet.php @@ -0,0 +1,476 @@ + true, + 'message' => false, + 'magnet' => [], + 'comments' => [], +]; + +// Yggdrasil connections only +if (!preg_match(YGGDRASIL_URL_REGEX, $_SERVER['REMOTE_ADDR'])) +{ + $response->success = false; + $response->message = _('Yggdrasil connection required to enable resource features'); +} + +// Init session +else if (!$userId = $db->initUserId($_SERVER['REMOTE_ADDR'], USER_DEFAULT_APPROVED, time())) +{ + $response->success = false; + $response->message = _('Could not init user session'); +} + +// Get user +else if (!$user = $db->getUser($userId)) +{ + $response->success = false; + $response->message = _('Could not init user info'); +} + +// Init magnet +else if (!$magnet = $db->getMagnet(isset($_GET['magnetId']) ? (int) $_GET['magnetId'] : 0)) +{ + $response->success = false; + $response->message = _('Magnet not found! Submit new magnet link by sending address to the search field.'); +} + +// Request valid +else +{ + // Get access info + $accessRead = ($user->address == $db->getUser($magnet->userId)->address || in_array($user->address, MODERATOR_IP_LIST) || ($magnet->public && $magnet->approved)); + $accessEdit = ($user->address == $db->getUser($magnet->userId)->address || in_array($user->address, MODERATOR_IP_LIST)); + + // Update magnet viwed + if ($accessRead) + { + $db->addMagnetView($magnet->magnetId, $userId, time()); + } + + // Keywords + $keywords = []; + + foreach ($db->findKeywordTopicByMagnetId($magnet->magnetId) as $keyword) + { + $keywords[] = $db->getKeywordTopic($keyword->keywordTopicId)->value; + } + + // Scrapes + $localScrape = (object) + [ + 'seeders' => 0, + 'completed' => 0, + 'leechers' => 0, + ]; + + $totalScrape = (object) + [ + 'seeders' => 0, + 'completed' => 0, + 'leechers' => 0, + ]; + + $trackers = []; + + foreach (TRACKER_LINKS as $tracker) + { + $trackers[] = $tracker->announce; + } + + foreach ($db->findAddressTrackerByMagnetId($magnet->magnetId) as $magnetToAddressTracker) + { + if ($addressTracker = $db->getAddressTracker($magnetToAddressTracker->addressTrackerId)) + { + $scheme = $db->getScheme($addressTracker->schemeId); + $host = $db->getHost($addressTracker->hostId); + $port = $db->getPort($addressTracker->portId); + $uri = $db->getUri($addressTracker->uriId); + + $url = $port->value ? sprintf('%s://%s:%s%s', $scheme->value, + $host->value, + $port->value, + $uri->value) : sprintf('%s://%s%s', $scheme->value, + $host->value, + $uri->value); + + if (in_array($url, $trackers)) + { + $localScrape->seeders += (int) $magnetToAddressTracker->seeders; + $localScrape->completed += (int) $magnetToAddressTracker->completed; + $localScrape->leechers += (int) $magnetToAddressTracker->leechers; + } + + $totalScrape->seeders += (int) $magnetToAddressTracker->seeders; + $totalScrape->completed += (int) $magnetToAddressTracker->completed; + $totalScrape->leechers += (int) $magnetToAddressTracker->leechers; + } + } + + $response->user = $user; + $response->magnet = (object) + [ + 'magnetId' => $magnet->magnetId, + 'metaTitle' => $magnet->metaTitle ? htmlentities($magnet->metaTitle) : ($magnet->dn ? htmlentities($magnet->dn): false), + 'metaDescription' => $magnet->metaDescription ? nl2br( + htmlentities( + substr($magnet->metaDescription, 0, WEBSITE_MAGNET_SHORT_META_DESCRIPTION_LENGTH) + ) + ) : false, + 'approved' => (bool) $magnet->approved, + 'public' => (bool) $magnet->public, + 'sensitive' => (bool) $magnet->sensitive, + 'comments' => (bool) $magnet->comments, + 'timeAdded' => $magnet->timeAdded ? Time::ago((int) $magnet->timeAdded) : false, + 'timeUpdated' => $magnet->timeUpdated ? Time::ago((int) $magnet->timeUpdated) : false, + 'keywords' => $keywords, + 'comment' => (object) + [ + 'total' => $db->getMagnetCommentsTotal($magnet->magnetId), + 'status' => $db->findMagnetCommentsTotalByUserId($magnet->magnetId, $userId), + ], + 'download' => (object) + [ + 'total' => $db->getMagnetDownloadsTotalByUserId($magnet->magnetId), + 'status' => $db->findMagnetDownloadsTotalByUserId($magnet->magnetId, $userId), + ], + 'star' => (object) + [ + 'total' => $db->getMagnetStarsTotal($magnet->magnetId), + 'status' => $db->findMagnetStarsTotalByUserId($magnet->magnetId, $userId), + ], + 'access' => (object) + [ + 'read' => $accessRead, + 'edit' => $accessEdit, + ], + 'scrape' => (object) + [ + 'local' => $localScrape, + 'total' => $totalScrape + ] + ]; +} + +if (isset($_GET['rss']) && $response->success) { ?>' . PHP_EOL ?> + + + + <?php echo sprintf(_('%s - Comments - %s'), htmlentities($response->magnet->metaTitle), WEBSITE_NAME) ?> + + magnet->magnetId) ?> + getMagnetComments($response->magnet->magnetId) as $magnetComment) { ?> + user->address == $db->getUser($magnetComment->userId)->address || in_array($response->user->address, MODERATOR_IP_LIST)) { ?> + + <?php echo sprintf('%s - comment #%s', htmlspecialchars($magnet->metaTitle, ENT_QUOTES, 'UTF-8'), $magnetComment->magnetCommentId) ?> + value, ENT_QUOTES, 'UTF-8') ?> + magnet->magnetId, $magnetComment->magnetCommentId) ?> + magnet->magnetId, $magnetComment->magnetCommentId) ?> + + + + + + + + + + + + success) { ?> + <?php echo sprintf(_('%s - %s'), htmlentities($response->magnet->metaTitle), WEBSITE_NAME) ?> + + + + <?php echo $response->message ?> + + + + + +
+ +
+
+
+
+
+ success) { ?> + magnet->access->read) { ?> +
+
+ +

magnet->metaTitle ?>

+
+ magnet->public) { ?> + + + + + + + + magnet->approved) { ?> + + + + + + + magnet->access->edit) { ?> + + + + + + + + + +
+ magnet->metaDescription) { ?> +
magnet->metaDescription ?>
+ + magnet->keywords) { ?> +
+ magnet->keywords as $keyword) { ?> + + # + + +
+ +
+ + + + magnet->timeUpdated ? _('Updated') : _('Added') ?> + magnet->timeUpdated ? $response->magnet->timeUpdated : $response->magnet->timeAdded ?> + + + + + + + magnet->scrape->local->seeders ?> / magnet->scrape->total->seeders ?> + + + + + + magnet->scrape->local->completed ?> / magnet->scrape->total->completed ?> + + + + + + + magnet->scrape->local->leechers ?> / magnet->scrape->total->leechers ?> + + + + magnet->star->status) { ?> + + + + + + + + + + magnet->star->total ?> + + + + magnet->comment->status) { ?> + + + + + + + + + + magnet->comment->total ?> + + + + magnet->download->status) { ?> + + + + + + + + + + magnet->download->total ?> + +
+
+ magnet->comments) { ?> +
+ +

+ +
+
+ getMagnetComments($response->magnet->magnetId) as $magnetComment) { ?> +
+ + user->address == $db->getUser($magnetComment->userId)->address || in_array($response->user->address, MODERATOR_IP_LIST)) { ?> +
+ value)) ?> +
+ + timeAdded) ?> + + + public) { ?> + + + + + + + + approved) { ?> + + + + + + + + + public) { ?> + + + + + + user->address, MODERATOR_IP_LIST)) { ?> + + approved) { ?> + + + + + + + + + +
+ +
+ +
+
+ +
+
+ +
+
+
+ + +
+
+
+ + +
+
message ?>
+
+ +
+
+
+
+
+
+
+
+ $value) { ?> + + / + + | + + + | + +
+
+
+
+ + + \ No newline at end of file