Skip to content
This repository has been archived by the owner on Nov 2, 2020. It is now read-only.

Commit

Permalink
feat(Favour): Add full favour support
Browse files Browse the repository at this point in the history
  • Loading branch information
Rhilip committed Mar 16, 2019
1 parent 86f49e7 commit 1c83715
Show file tree
Hide file tree
Showing 16 changed files with 226 additions and 61 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ Some rule or Docs May help you when you rebuild this project,
Or you can join our chat group on Telegram -- [@ridpt](https://t.me/ridpt)

| Name | Used As | Docs |
|:--|:--:|:--:|:--:|
|:--|:--:|:--:|
| [MixPHP](https://github.com/mix-php/mix-framework/tree/v1) | Framework | https://www.kancloud.cn/onanying/mixphp1/379324 ( Chinese Version ) |
| [siriusphp/validation](https://github.com/siriusphp/validation) | Validator | http://www.sirius.ro/php/sirius/validation/ |
| [league/plates](https://github.com/thephpleague/plates) | Template system | http://platesphp.com/ |
Expand Down
11 changes: 9 additions & 2 deletions apps/config/http_base.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,19 @@
'rules' => [
'GET tracker/{tracker_action}' => ['tracker','index'],
'GET captcha' => ['captcha', 'index'],

// Auth By Passkey Route
'GET rss' => ['rss', 'index','middleware' => [
apps\middleware\AuthByPasskeyMiddleware::class
]],
'api/v1/{controller}/{action}' => ['api/{controller}', '{action}', 'middleware' => [
apps\middleware\ApiMiddleware::class

// API version 1
'api/v1/{controller}/{action}' => ['api/v1/{controller}', '{action}', 'middleware' => [
apps\middleware\ApiMiddleware::class,
apps\middleware\AuthByCookiesMiddleware::class
]],

// Web view
'{controller}/{action}' => ['{controller}', '{action}', 'middleware' => [
apps\middleware\AuthByCookiesMiddleware::class
]],
Expand Down
18 changes: 0 additions & 18 deletions apps/controllers/api/IndexController.php

This file was deleted.

37 changes: 37 additions & 0 deletions apps/controllers/api/v1/TorrentsController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php
/**
* Created by PhpStorm.
* User: Rhilip
* Date: 2019/3/16
* Time: 10:39
*/

namespace apps\controllers\api\v1;

use apps\models\api\v1\form\TorrentsBookmarkForm;
use Rid\Http\ApiController;

class TorrentsController extends ApiController
{
public function actionBookmark() {
if ($this->checkMethod('POST')) {
$bookmark = new TorrentsBookmarkForm();
$bookmark->setData(app()->request->post());
$success = $bookmark->validate();
if (!$success) {
return [
'success' => false,
'errors' => $bookmark->getErrors()
];
} else {
$ret = $bookmark->updateRecord();
return array_merge(
['success' => true],
$ret
);
}
} else {
return $this->buildMethodFailMsg('POST');
}
}
}
8 changes: 8 additions & 0 deletions apps/middleware/ApiMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,17 @@ class ApiMiddleware
public function handle($callable, \Closure $next)
{
app()->response->format = \Rid\Http\Response::FORMAT_JSON;

// No cache for api response
app()->response->setHeader('Expires', 'Mon, 26 Jul 1997 05:00:00 GMT');
app()->response->setHeader('Last-Modified', gmdate("D, d M Y H:i:s") . " GMT");
app()->response->setHeader('Cache-Control', 'no-cache, must-revalidate');
app()->response->setHeader('Pragma', 'no-cache');

if (env("APP_DEBUG")) {
app()->response->setHeader("access-control-allow-origin","*");
}

return $next();
}
}
60 changes: 60 additions & 0 deletions apps/models/api/v1/form/TorrentsBookmarkForm.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php
/**
* Created by PhpStorm.
* User: Rhilip
* Date: 2019/3/16
* Time: 11:30
*/

namespace apps\models\api\v1\form;


use Rid\Validators\Validator;

class TorrentsBookmarkForm extends Validator
{
public $tid;

public static function inputRules()
{
return [
'tid' => 'required | Integer'
];
}

public static function callbackRules() {
return ['isExistTorrent'];
}

protected function isExistTorrent() {
$torrent_exist = app()->pdo->createCommand('SELECT COUNT(`id`) FROM `torrents` WHERE `id` = :tid')->bindParams([
'tid' => $this->tid
])->queryScalar();
if ($torrent_exist == 0) {
$this->buildCallbackFailMsg('Torrent', 'The torrent id ('. $this->tid. ') is not exist in our database');
}
}

public function updateRecord() {
$bookmark_exist = app()->pdo->createCommand('SELECT `id` FROM `bookmarks` WHERE `uid` = :uid AND `tid` = :tid ')->bindParams([
'uid' => app()->user->getId(),
'tid' => $this->tid
])->queryScalar() ?: 0;
if ($bookmark_exist > 0) { // Delete the exist record
app()->pdo->createCommand('DELETE FROM `bookmarks` WHERE `id` = :bid')->bindParams([
'bid' => $bookmark_exist
])->execute();
app()->redis->del('User:' . app()->user->getId() . ':bookmark_array');

return ['msg' => 'Delete Old Bookmark Success', 'result' => 'deleted'];
} else { // Add new record
app()->pdo->createCommand('INSERT INTO `bookmarks` (`uid`, `tid`) VALUES (:uid, :tid)')->bindParams([
'uid' => app()->user->getId(),
'tid' => $this->tid
])->execute();
app()->redis->del('User:' . app()->user->getId() . ':bookmark_array');

return ['msg' => 'Add New Bookmark Success', 'result' => 'added'];
}
}
}
3 changes: 2 additions & 1 deletion apps/public/static/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,5 @@ nav#menu .layui-nav-item{line-height:45px}
.icon-leeching {color: red}


.torrent-title-block {margin: 15px}
.torrent-title-block{margin:15px}
.torrent-action-item{padding:3px}
35 changes: 22 additions & 13 deletions apps/public/static/js/main.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
;layui.use(['layer', 'form','element','laypage','jquery'], function(){
let $=layui.jquery;
let $ = layui.jquery;
let layer = layui.layer;
let api_point = '/api/v1';

// Add favour action
$('.torrent-favour > i').click(function () {
let star = $(this);
// TODO Do ajax to api, if success then change the star
let old_is_stared = star.hasClass('fas');
star.toggleClass('fas',!old_is_stared).toggleClass('far',old_is_stared);
new NoticeJs({
text: 'Torrent add/remove from your favour',
position: 'bottomRight',
}).show();
// TODO Notice user
})
// Add/Remove favour action
$('.torrent-favour').click(function () {
let that = $(this);
let tid = that.attr('data-tid');
let star = that.find(' > i');

$.post(api_point + '/torrents/bookmark', {'tid': tid}, function (res) {
if (res.success) {
let old_is_stared = star.hasClass('fas');
star.toggleClass('fas', !old_is_stared).toggleClass('far', old_is_stared);
layer.msg(`Torrent(${tid}) ${res.result} from your favour successfully`, {
icon: 6,
offset: 'rb',
});
} else {
layer.alert(res.errors.join(', '), {icon: 2});
}
});
});
});
32 changes: 26 additions & 6 deletions apps/views/torrents/details.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,39 @@
<div class="layui-card" id="torrent-action-card">
<div class="layui-card-header"><b>Torrent Action</b></div>
<div class="layui-card-body">
<div><!--suppress HtmlUnknownTarget --><a href="/torrents/download?id=<?= $torrent->getId() ?>"><i class="fa fa-download fa-fw"></i> Download Torrent</a></div>
<div><a class="torrent-favour" href="javascript:" data-tid="<?= $torrent->getId() ?>"><i class="<?= app()->user->inBookmarkList($torrent->getId()) ? 'fas' : 'far' ?> fa-star fa-fw"></i> Add to Favour</a> </div><!-- add remove from Favour -->
<div><!--suppress HtmlUnknownTarget --><a href="/report?type=torrent&id=<?= $torrent->getId() ?>"><i class="fa fa-bug fa-fw"></i> Report this Torrent</a></div>
<div class="torrent-action-item"><!--suppress HtmlUnknownTarget -->
<a href="/torrents/download?id=<?= $torrent->getId() ?>"><i class="fa fa-download fa-fw"></i>&nbsp;Download Torrent</a>
</div><!-- Download Torrent -->
<div class="torrent-action-item">
<a class="torrent-favour" href="javascript:" data-tid="<?= $torrent->getId() ?>"><i class="<?= app()->user->inBookmarkList($torrent->getId()) ? 'fas' : 'far' ?> fa-star fa-fw"></i>&nbsp;Add to Favour</a>
</div><!-- TODO Add to Favour -->
<div class="torrent-action-item">
<a class="torrent-myrss" href="javascript:" data-tid="<?= $torrent->getId() ?>"><i class="fas fa-rss fa-fw"></i>&nbsp;Add to RSS Basket</a>
</div><!-- TODO Add to RSS Basket -->
<hr>
<div class="torrent-action-item"><!--suppress HtmlUnknownTarget -->
<a class="torrent-edit" href="/torrents/edit?id=<?= $torrent->getId() ?>"><i class="fas fa-edit fa-fw"></i>&nbsp;Edit/Remove this Torrent</a>
</div><!-- TODO Edit/Remove this Torrent -->
<div class="torrent-action-item"><!--suppress HtmlUnknownTarget -->
<a class="torrent-report" href="/report?type=torrent&id=<?= $torrent->getId() ?>"><i class="fa fa-bug fa-fw"></i>&nbsp;Report this Torrent</a>
</div><!-- TODO Report this Torrent -->
<hr>
<div class="torrent-action-item"><!--suppress HtmlUnknownTarget -->
<a class="torrent-files" href="javascript:" data-tid="<?= $torrent->getId() ?>"><i class="fas fa-file fa-fw"></i>&nbsp;View Torrent's Files</a>
</div><!-- TODO View Torrent's Files -->
<div class="torrent-action-item"><!--suppress HtmlUnknownTarget -->
<a class="torrent-structure" href="javascript:" data-tid="<?= $torrent->getId() ?>"><i class="fas fa-folder-open fa-fw"></i>&nbsp;View Torrent's Structure</a>
</div><!-- TODO View Torrent's Structure -->
</div>
</div>
<div class="layui-card" id="torrent-info-card">
<div class="layui-card-header"><b>Torrent Information</b></div>
<div class="layui-card-body">
<div data-field="added_date" data-timestamp="<?= strtotime($torrent->getAddedAt()) ?>"><b>Date:</b> <?= $torrent->getAddedAt() ?></div>
<div data-field="added_date" data-timestamp="<?= strtotime($torrent->getAddedAt()) ?>"><b>Uploaded Date:</b> <?= $torrent->getAddedAt() ?></div>
<div data-field="size" data-filesize="<?= $torrent->getTorrentSize() ?>"><b>File size:</b> <?= $this->e($torrent->getTorrentSize(),'format_bytes') ?></div>
<div data-field="uploader"><b>Uploader:</b> <?= get_torrent_uploader($torrent) ?></div>
<div data-field="uploader" data-owner-id="<?= get_torrent_uploader_id($torrent) ?>"><b>Uploader:</b> <?= get_torrent_uploader($torrent) ?></div>
<div data-field="peers" data-seeders="<?= $torrent->getComplete() ?>" data-leechers="<?= $torrent->getComplete() ?>" data-completed="<?= $torrent->getDownloaded() ?>">
<b>Peers:</b> <span style="color: green;"><i class="fas fa-arrow-up"></i> <?= $torrent->getComplete() ?></span> / <span style="color: red;"><i class="fas fa-arrow-down"></i> <?= $torrent->getIncomplete() ?></span> / <span><i class="fas fa-check"></i> <?= $torrent->getDownloaded() ?></span>
<b>Peers:</b> <span style="color: green;"><i class="fas fa-arrow-up fa-fw"></i> <?= $torrent->getComplete() ?></span> / <span style="color: red;"><i class="fas fa-arrow-down fa-fw"></i> <?= $torrent->getIncomplete() ?></span> / <span><i class="fas fa-check fa-fw"></i> <?= $torrent->getDownloaded() ?></span>
</div>
<div data-field="info_hash" data-infohash="<?= $torrent->getInfoHash() ?>"><b>Info Hash:</b> <kbd><?= $torrent->getInfoHash() ?></kbd></div>
</div>
Expand Down
13 changes: 12 additions & 1 deletion apps/views/torrents/helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,20 @@
* @param \apps\models\Torrent $torrent
* @return string
*/
function get_torrent_uploader(\apps\models\Torrent $torrent)

function get_torrent_uploader_id(\apps\models\Torrent $torrent)
{
if ($torrent->getUplver() == 'yes' and app()->user->getClass(true) < app()->config->get('authority.see_anonymous_uploader')) {
return 0;
} else {
return $torrent->getOwnerId();
}
}

function get_torrent_uploader(\apps\models\Torrent $torrent)
{
$owner_id = get_torrent_uploader_id($torrent);
if ($owner_id == 0) {
return '<i>Anonymous</i>';
} else {
return "<a class=\"text-default\" href=\"/user/panel?id={$torrent->getOwnerId()}\" data-toggle=\"tooltip\" title=\"User\">{$torrent->getOwner()->getUsername()}</a>";
Expand Down
42 changes: 42 additions & 0 deletions framework/Http/ApiController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php
/**
* Created by PhpStorm.
* User: Rhilip
* Date: 2019/3/16
* Time: 10:41
*/

namespace Rid\Http;


class ApiController extends Controller
{
/**
* @param array|string $methods
* @return bool
*/
protected function checkMethod($methods) {
if (is_string($methods)) $methods = [$methods];

foreach ($methods as $method) {
if (strtolower(app()->request->method()) == strtolower($method))
return true;
}
return false;
}

protected function buildMethodFailMsg($want_methods)
{
if (is_array($want_methods)) $want_methods = implode(',', $want_methods);

app()->response->setStatusCode(405);
$method = app()->request->method();

return [
'error' => 'Method Not Allowed',
'detail' => [
'method' => "The method `$method` is not allowed, You should use `$want_methods` in this action."
]
];
}
}
12 changes: 0 additions & 12 deletions framework/Http/BaseResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,11 @@ class BaseResponse extends Component
const FORMAT_HTML = 'html';
const FORMAT_JSON = 'json';
const FORMAT_JSONP = 'jsonp';
const FORMAT_XML = 'xml';
const FORMAT_RAW = 'raw';

// 默认输出格式
public $defaultFormat = self::FORMAT_HTML;

/**
* @var \Rid\Http\Xml
*/
public $xml;

// 当前输出格式
public $format;

Expand Down Expand Up @@ -71,9 +65,6 @@ protected function prepare()
case self::FORMAT_JSONP:
$this->setHeader('Content-Type', 'application/json; charset=utf-8');
break;
case self::FORMAT_XML:
$this->setHeader('Content-Type', 'text/xml; charset=utf-8');
break;
}
}
// 转换内容为字符型
Expand All @@ -91,9 +82,6 @@ protected function prepare()
$content = $callback_key . '(' . $content . ')';
break;
}
case self::FORMAT_XML:
$content = $this->xml->encode($content);
break;
}
}
$this->content = $content;
Expand Down
1 change: 0 additions & 1 deletion framework/Http/Error.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ class Error extends Component
// 格式值
const FORMAT_HTML = 'html';
const FORMAT_JSON = 'json';
const FORMAT_XML = 'xml';

// 输出格式
public $format = self::FORMAT_HTML;
Expand Down
4 changes: 2 additions & 2 deletions framework/User/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,12 @@ public function getBookmarkList()
if (!is_null($this->bookmark_list))
return $this->bookmark_list;

$bookmaks = app()->redis->hGet($this->infoCacheKey, 'bookmark_array');
$bookmaks = app()->redis->get('User:' . $this->id . ':bookmark_array');
if ($bookmaks === false) {
$bookmaks = app()->pdo->createCommand('SELECT `tid` FROM `bookmarks` WHERE `uid` = :uid')->bindParams([
'uid' => $this->id
])->queryColumn() ?: [0];
app()->redis->hSet($this->infoCacheKey, 'bookmark_array', $bookmaks);
app()->redis->set('User:' . $this->id . ':bookmark_array', $bookmaks, 132800);
}

$this->bookmark_list = $bookmaks; // Store in avg to reduce the cache call
Expand Down
2 changes: 1 addition & 1 deletion framework/User/UserTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ trait UserTrait

public function loadUserContentById($id)
{
$this->infoCacheKey = 'User:id_' . $id . '_content';
$this->infoCacheKey = 'User:' . $id . ':base_content';
$self = app()->redis->hGetAll($this->infoCacheKey);
if (empty($self)) {
$self = app()->pdo->createCommand("SELECT * FROM `users` WHERE id = :id;")->bindParams([
Expand Down
Loading

0 comments on commit 1c83715

Please sign in to comment.