diff --git a/app/Enums/Permission/RoutePermissionEnum.php b/app/Enums/Permission/RoutePermissionEnum.php index c0b9f3e8..845caf57 100644 --- a/app/Enums/Permission/RoutePermissionEnum.php +++ b/app/Enums/Permission/RoutePermissionEnum.php @@ -7,4 +7,6 @@ enum RoutePermissionEnum: string { case TORRENT_VIEW = 'torrent:view'; case TORRENT_UPLOAD = 'torrent:upload'; case USER_VIEW = "user:view"; + case BOOKMARK_STORE = "bookmark:store"; + case BOOKMARK_DELETE = "bookmark:delete"; } diff --git a/app/Http/Controllers/BookmarkController.php b/app/Http/Controllers/BookmarkController.php index 8db884c3..b8ec3656 100644 --- a/app/Http/Controllers/BookmarkController.php +++ b/app/Http/Controllers/BookmarkController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers; +use App\Http\Resources\BookmarkResource; use App\Http\Resources\TorrentResource; use App\Models\Torrent; use App\Repositories\BookmarkRepository; @@ -25,7 +26,7 @@ class BookmarkController extends Controller * Store a newly created resource in storage. * * @param \Illuminate\Http\Request $request - * @return \Illuminate\Http\Response + * @return array */ public function store(Request $request) { @@ -33,7 +34,8 @@ class BookmarkController extends Controller 'torrent_id' => 'required|integer', ]); $result = $this->repository->add(Auth::user(), $request->torrent_id); - return $this->success($result->toArray(), nexus_trans('bookmark.actions.store_success')); + $resource = new BookmarkResource($result); + return $this->success($resource, nexus_trans('bookmark.actions.store_success')); } /** @@ -62,12 +64,15 @@ class BookmarkController extends Controller * Remove the specified resource from storage. * * @param int $id - * @return \Illuminate\Http\Response + * @return array */ - public function destroy($id) + public function destroy(Request $request) { - $result = $this->repository->remove(Auth::user(), $id); - return $this->success($result, nexus_trans('bookmark.actions.delete_success')); + $request->validate([ + 'torrent_id' => 'required|integer', + ]); + $result = $this->repository->remove(Auth::user(), $request->torrent_id); + return $this->success(true, nexus_trans('bookmark.actions.delete_success')); } } diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index cc467a9b..2c980827 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -24,8 +24,7 @@ class Controller extends BaseController protected ?array $extraSettingNames = null; /** - * 返回成功信息,这里是旧方法,大部分情况下 $data 已经是 JsonResource - * 但很多地方有使用,历史原因保留不动,尽量使用 successJsonResource + * 返回成功信息 * * @param $data * @param $msg @@ -44,6 +43,7 @@ class Controller extends BaseController /** * 返回成功信息,对于不是 JsonResource 的数据,进行包装。返回的数据在 data.data 中 * + * @deprecated 没有必要,已经在 api() 中添加 data 包裹,使用 success() 即可 * @param $data * @param $msg * @return array diff --git a/app/Http/Controllers/TokenController.php b/app/Http/Controllers/TokenController.php index 8c662767..53aa74e0 100644 --- a/app/Http/Controllers/TokenController.php +++ b/app/Http/Controllers/TokenController.php @@ -37,7 +37,7 @@ class TokenController extends Controller $newAccessToken = $user->createToken($request->name, $request->permissions); $tokenText = $newAccessToken->plainTextToken; $msg = nexus_trans("token.create_success_tip", ['token' => $tokenText]); - return $this->successJsonResource(['token' => $tokenText], $msg); + return $this->success(['token' => $tokenText], $msg); } catch (\Exception $exception) { return $this->fail(false, $exception->getMessage()); } diff --git a/app/Models/Bookmark.php b/app/Models/Bookmark.php index 5cb085bd..e9633e39 100644 --- a/app/Models/Bookmark.php +++ b/app/Models/Bookmark.php @@ -9,6 +9,10 @@ class Bookmark extends NexusModel protected $fillable = ['userid', 'torrentid']; + const FILTER_IGNORE = '0'; + const FILTER_INCLUDE = '1'; + const FILTER_EXCLUDE = '2'; + public function torrent() { return $this->belongsTo(Torrent::class, 'torrentid'); diff --git a/app/Repositories/BookmarkRepository.php b/app/Repositories/BookmarkRepository.php index 5bdbb9e5..8278330f 100644 --- a/app/Repositories/BookmarkRepository.php +++ b/app/Repositories/BookmarkRepository.php @@ -3,6 +3,7 @@ namespace App\Repositories; use App\Exceptions\NexusException; +use App\Models\Bookmark; use App\Models\Torrent; use App\Models\User; @@ -10,11 +11,14 @@ class BookmarkRepository extends BaseRepository { public function add(User $user, $torrentId) { - $torrent = Torrent::query()->findOrFail($torrentId); + $torrent = Torrent::query()->find($torrentId); + if (!$torrent) { + throw new NexusException(nexus_trans('bookmark.torrent_not_exists', ['torrent_id' => $torrentId])); + } $torrent->checkIsNormal(); $exists = $user->bookmarks()->where('torrentid', $torrentId)->exists(); if ($exists) { - throw new NexusException("torrent: $torrentId already bookmarked."); + throw new NexusException(nexus_trans('bookmark.torrent_already_bookmarked', ['torrent_id' => $torrentId])); } $result = $user->bookmarks()->create(['torrentid' => $torrentId]); return $result; @@ -22,12 +26,15 @@ class BookmarkRepository extends BaseRepository public function remove(User $user, $torrentId) { - $torrent = Torrent::query()->findOrFail($torrentId); - $exists = $user->bookmarks()->where('torrentid', $torrentId)->exists(); - if (!$exists) { - throw new NexusException("torrent: $torrentId has not been bookmarked."); + /** + * @var Bookmark $record + */ + $record = $user->bookmarks()->where('torrentid', $torrentId)->first(); + if (!$record) { + throw new NexusException(nexus_trans('bookmark.torrent_has_not_been_bookmarked', ['torrent_id' => $torrentId])); } - $result = $user->bookmarks()->where('torrentid', $torrentId)->delete(); - return $result; + do_log("going to remove bookmark of torrent: $torrentId"); + $record->delete(); + return true; } } diff --git a/app/Repositories/TokenRepository.php b/app/Repositories/TokenRepository.php index 8374741a..25c566eb 100644 --- a/app/Repositories/TokenRepository.php +++ b/app/Repositories/TokenRepository.php @@ -11,6 +11,8 @@ class TokenRepository extends BaseRepository RoutePermissionEnum::TORRENT_VIEW->value, RoutePermissionEnum::TORRENT_UPLOAD->value, RoutePermissionEnum::USER_VIEW->value, + RoutePermissionEnum::BOOKMARK_STORE->value, + RoutePermissionEnum::BOOKMARK_DELETE->value, ]; public static function listUserTokenPermissions(bool $format = true): array diff --git a/app/Repositories/TorrentRepository.php b/app/Repositories/TorrentRepository.php index 6af66cea..e27a0644 100644 --- a/app/Repositories/TorrentRepository.php +++ b/app/Repositories/TorrentRepository.php @@ -9,6 +9,7 @@ use App\Exceptions\InsufficientPermissionException; use App\Exceptions\NexusException; use App\Http\Resources\TorrentResource; use App\Models\AudioCodec; +use App\Models\Bookmark; use App\Models\Category; use App\Models\Claim; use App\Models\Codec; @@ -36,6 +37,7 @@ use Carbon\Carbon; use Elasticsearch\Endpoints\Search; use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Query\JoinClause; use Illuminate\Http\Request; use Illuminate\Support\Arr; use Illuminate\Support\Collection; @@ -96,7 +98,8 @@ class TorrentRepository extends BaseRepository ]; $allowFilters = [ 'title', 'category', 'source', 'medium', 'codec', 'audiocodec', 'standard', 'processing', 'team', - 'owner', 'visible', 'added', 'size', 'sp_state', 'leechers', 'seeders', 'times_completed' + 'owner', 'visible', 'added', 'size', 'sp_state', 'leechers', 'seeders', 'times_completed', + 'bookmark' ]; $allowSorts = ['id', 'comments', 'size', 'seeders', 'leechers', 'times_completed']; $apiQueryBuilder = ApiQueryBuilder::for(TorrentResource::NAME, $query, $request) @@ -114,6 +117,18 @@ class TorrentRepository extends BaseRepository }); } }) + ->registerCustomFilter('bookmark', function (Builder $query, Request $request) use ($user) { + $filterBookmark = $request->input(ApiQueryBuilder::PARAM_NAME_FILTER.".bookmark"); + if ($filterBookmark === Bookmark::FILTER_INCLUDE) { + $query->whereHas("bookmarks", function (Builder $query) use ($user) { + $query->where("userid", $user->id); + }); + } elseif ($filterBookmark === Bookmark::FILTER_EXCLUDE) { + $query->whereDoesntHave("bookmarks", function (Builder $query) use ($user) { + $query->where("userid", $user->id); + }); + } + }) ; $query = $apiQueryBuilder->build(); if (!$apiQueryBuilder->hasSort()) { diff --git a/include/globalfunctions.php b/include/globalfunctions.php index 8c6dd7da..3dc2922a 100644 --- a/include/globalfunctions.php +++ b/include/globalfunctions.php @@ -542,6 +542,8 @@ function api(...$args) } if ($data instanceof \Illuminate\Http\Resources\Json\JsonResource) { $data = $data->response()->getData(true); + } else { + $data = ['data' => $data]; } // dd($data); $time = (float)number_format(microtime(true) - nexus()->getStartTimestamp(), 3); diff --git a/resources/lang/en/bookmark.php b/resources/lang/en/bookmark.php index 395fe79c..4ced2cd7 100644 --- a/resources/lang/en/bookmark.php +++ b/resources/lang/en/bookmark.php @@ -4,5 +4,8 @@ return [ 'actions' => [ 'store_success' => 'Add to bookmark success!', 'delete_success' => 'Cancel bookmark success!', - ] + ], + 'torrent_not_exists' => 'Torrent: :torrent_id not exists!', + 'torrent_already_bookmarked' => 'Torrent: :torrent_id already bookmarked!', + 'torrent_has_not_been_bookmarked' => 'Torrent: :torrent_id not bookmarked!', ]; diff --git a/resources/lang/en/route-permission.php b/resources/lang/en/route-permission.php index a359f4fc..5d8bb1f0 100644 --- a/resources/lang/en/route-permission.php +++ b/resources/lang/en/route-permission.php @@ -17,4 +17,12 @@ return [ 'text' => 'View user basic info', 'desc' => 'View user basic info', ], + 'bookmark:store' => [ + 'text' => 'Add bookmark', + 'desc' => 'Add bookmark', + ], + 'bookmark:delete' => [ + 'text' => 'Delete bookmark', + 'desc' => 'Delete bookmark', + ], ]; diff --git a/resources/lang/zh_CN/bookmark.php b/resources/lang/zh_CN/bookmark.php index 32132513..cad2f88f 100644 --- a/resources/lang/zh_CN/bookmark.php +++ b/resources/lang/zh_CN/bookmark.php @@ -4,5 +4,8 @@ return [ 'actions' => [ 'store_success' => '添加收藏成功!', 'delete_success' => '取消收藏成功!', - ] + ], + 'torrent_not_exists' => '种子: :torrent_id 不存在', + 'torrent_already_bookmarked' => '种子: :torrent_id 已经收藏', + 'torrent_has_not_been_bookmarked' => '种子: :torrent_id 未被收藏', ]; diff --git a/resources/lang/zh_CN/route-permission.php b/resources/lang/zh_CN/route-permission.php index c4d00f99..7966c544 100644 --- a/resources/lang/zh_CN/route-permission.php +++ b/resources/lang/zh_CN/route-permission.php @@ -17,4 +17,12 @@ return [ 'text' => '查看用户基本信息', 'desc' => '查看用户基本信息', ], + 'bookmark:store' => [ + 'text' => '添加收藏种子', + 'desc' => '添加收藏的种子', + ], + 'bookmark:delete' => [ + 'text' => '删除收藏的种子', + 'desc' => '删除收藏的种子', + ], ]; diff --git a/resources/lang/zh_TW/bookmark.php b/resources/lang/zh_TW/bookmark.php index 32132513..6f29f293 100644 --- a/resources/lang/zh_TW/bookmark.php +++ b/resources/lang/zh_TW/bookmark.php @@ -4,5 +4,8 @@ return [ 'actions' => [ 'store_success' => '添加收藏成功!', 'delete_success' => '取消收藏成功!', - ] + ], + 'torrent_not_exists' => '種子: :torrent_id 不存在', + 'torrent_already_bookmarked' => '種子: :torrent_id 已經收藏', + 'torrent_has_not_been_bookmarked' => '種子: :torrent_id 未被收藏', ]; diff --git a/resources/lang/zh_TW/route-permission.php b/resources/lang/zh_TW/route-permission.php index c7274e7f..d519a067 100644 --- a/resources/lang/zh_TW/route-permission.php +++ b/resources/lang/zh_TW/route-permission.php @@ -17,4 +17,12 @@ return [ 'text' => '查看用戶基本信息', 'desc' => '查看用戶基本信息', ], + 'bookmark:store' => [ + 'text' => '添加收藏種子', + 'desc' => '添加收藏的種子', + ], + 'bookmark:delete' => [ + 'text' => '刪除收藏的種子', + 'desc' => '刪除收藏的種子', + ], ]; diff --git a/routes/api.php b/routes/api.php index b9da6e1b..3f0f2195 100644 --- a/routes/api.php +++ b/routes/api.php @@ -34,7 +34,6 @@ Route::group(['middleware' => ['auth:sanctum']], function () { // Route::resource('files', \App\Http\Controllers\FileController::class); // Route::resource('thanks', \App\Http\Controllers\ThankController::class); // Route::resource('snatches', \App\Http\Controllers\SnatchController::class); -// Route::resource('bookmarks', \App\Http\Controllers\BookmarkController::class); // Route::get('search-box', [\App\Http\Controllers\TorrentController::class, 'searchBox']); // Route::resource('news', \App\Http\Controllers\NewsController::class); // Route::get('attend', [\App\Http\Controllers\AttendanceController::class, 'attend']); @@ -55,6 +54,9 @@ Route::group(['middleware' => ['auth:sanctum']], function () { Route::get('/profile/{id?}', [\App\Http\Controllers\UserController::class, 'show'])->middleware(ability(RoutePermissionEnum::USER_VIEW)); + Route::post('bookmarks', [\App\Http\Controllers\BookmarkController::class, 'store'])->middleware(ability(RoutePermissionEnum::BOOKMARK_STORE)); + Route::post('bookmarks/delete', [\App\Http\Controllers\BookmarkController::class, 'destroy'])->middleware(ability(RoutePermissionEnum::BOOKMARK_DELETE)); + });