diff --git a/app/Console/Commands/Test.php b/app/Console/Commands/Test.php index eea695a7..e2a26947 100644 --- a/app/Console/Commands/Test.php +++ b/app/Console/Commands/Test.php @@ -60,6 +60,9 @@ class Test extends Command // $disk = Storage::disk('google_dirve'); // $r = $disk->put('/', base_path('composer.json')); // $r = DB::table('users')->where('id', 1)->update(['modcomment' => DB::raw("concat_ws(',', 'ddddd', modcomment)")]); + $user = User::query()->find(1); + $r = $user->peer_torrents; + dd($r); } } diff --git a/app/Http/Controllers/CommentController.php b/app/Http/Controllers/CommentController.php new file mode 100644 index 00000000..1419cc6b --- /dev/null +++ b/app/Http/Controllers/CommentController.php @@ -0,0 +1,70 @@ +torrent_id; + $with = ['create_user', 'update_user']; + $comments = Comment::query()->with($with)->where('torrent', $torrentId)->paginate(); + $resource = CommentResource::collection($comments); + + return $this->success($resource); + } + + /** + * Store a newly created resource in storage. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function store(Request $request) + { + // + } + + /** + * Display the specified resource. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function show($id) + { + // + } + + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param int $id + * @return \Illuminate\Http\Response + */ + public function update(Request $request, $id) + { + // + } + + /** + * Remove the specified resource from storage. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function destroy($id) + { + // + } +} diff --git a/app/Http/Controllers/FileController.php b/app/Http/Controllers/FileController.php new file mode 100644 index 00000000..a4c4305f --- /dev/null +++ b/app/Http/Controllers/FileController.php @@ -0,0 +1,70 @@ +torrent_id; + $files = File::query()->where('torrent', $torrentId)->get(); + $resource = FileResource::collection($files); + + return $this->success($resource); + } + + /** + * Store a newly created resource in storage. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function store(Request $request) + { + // + } + + /** + * Display the specified resource. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function show($id) + { + // + } + + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param int $id + * @return \Illuminate\Http\Response + */ + public function update(Request $request, $id) + { + // + } + + /** + * Remove the specified resource from storage. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function destroy($id) + { + // + } +} diff --git a/app/Http/Controllers/MessageController.php b/app/Http/Controllers/MessageController.php new file mode 100644 index 00000000..274567e3 --- /dev/null +++ b/app/Http/Controllers/MessageController.php @@ -0,0 +1,74 @@ +where('receiver', $user->id)->with(['send_user'])->paginate(); + $resource = MessageResource::collection($messages); + return $this->success($resource); + + } + + /** + * Store a newly created resource in storage. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function store(Request $request) + { + // + } + + /** + * Display the specified resource. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function show($id) + { + $message = Message::query()->with(['send_user'])->findOrFail($id); + $resource = new MessageResource($message); + + return $this->success($resource); + } + + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param int $id + * @return \Illuminate\Http\Response + */ + public function update(Request $request, $id) + { + // + } + + /** + * Remove the specified resource from storage. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function destroy($id) + { + // + } +} diff --git a/app/Http/Controllers/PeerController.php b/app/Http/Controllers/PeerController.php new file mode 100644 index 00000000..1ba392c8 --- /dev/null +++ b/app/Http/Controllers/PeerController.php @@ -0,0 +1,85 @@ +torrent_id; + $peers = Peer::query()->where('torrent', $torrentId)->with(['user', 'relative_torrent'])->get()->groupBy('seeder'); + $seederResource = []; + $leecherResource = []; + if ($peers->has(Peer::SEEDER_YES)) { + $seederResource = PeerResource::collection($peers->get(Peer::SEEDER_YES)); + } + if ($peers->has(Peer::SEEDER_NO)) { + $leecherResource = PeerResource::collection($peers->get(Peer::SEEDER_NO)); + } + + $response = [ + 'seeder_list' => $seederResource, + 'leecher_list' => $leecherResource, + 'card_titles' => Peer::$cardTitles, + ]; + + return $this->success($response); + + } + + /** + * Store a newly created resource in storage. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function store(Request $request) + { + // + } + + /** + * Display the specified resource. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function show($id) + { + // + } + + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param int $id + * @return \Illuminate\Http\Response + */ + public function update(Request $request, $id) + { + // + } + + /** + * Remove the specified resource from storage. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function destroy($id) + { + // + } +} diff --git a/app/Http/Controllers/SnatchController.php b/app/Http/Controllers/SnatchController.php new file mode 100644 index 00000000..9bedc036 --- /dev/null +++ b/app/Http/Controllers/SnatchController.php @@ -0,0 +1,71 @@ +torrent_id; + $snatches = Snatch::query()->where('torrentid', $torrentId)->with(['user'])->paginate(); + $resource = SnatchResource::collection($snatches); + $resource->additional(['card_titles' => Snatch::$cardTitles]); + + return $this->success($resource); + } + + /** + * Store a newly created resource in storage. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function store(Request $request) + { + // + } + + /** + * Display the specified resource. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function show($id) + { + // + } + + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param int $id + * @return \Illuminate\Http\Response + */ + public function update(Request $request, $id) + { + // + } + + /** + * Remove the specified resource from storage. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function destroy($id) + { + // + } +} diff --git a/app/Http/Controllers/ThankController.php b/app/Http/Controllers/ThankController.php new file mode 100644 index 00000000..8071dede --- /dev/null +++ b/app/Http/Controllers/ThankController.php @@ -0,0 +1,69 @@ +torrent_id; + $thanks = Thank::query()->where('torrentid', $torrentId)->with(['user'])->paginate(); + $resource = ThankResource::collection($thanks); + + return $this->success($resource); + } + + /** + * Store a newly created resource in storage. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function store(Request $request) + { + // + } + + /** + * Display the specified resource. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function show($id) + { + // + } + + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param int $id + * @return \Illuminate\Http\Response + */ + public function update(Request $request, $id) + { + // + } + + /** + * Remove the specified resource from storage. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function destroy($id) + { + // + } +} diff --git a/app/Http/Controllers/TorrentController.php b/app/Http/Controllers/TorrentController.php new file mode 100644 index 00000000..624d8cb8 --- /dev/null +++ b/app/Http/Controllers/TorrentController.php @@ -0,0 +1,88 @@ +repository = $repository; + } + + public function index(Request $request) + { + $params = $request->all(); + $params['visible'] = Torrent::VISIBLE_YES; + $result = $this->repository->getList($params); + $resource = TorrentResource::collection($result); + + return $this->success($resource); + } + + /** + * Store a newly created resource in storage. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function store(Request $request) + { + // + } + + /** + * Display the specified resource. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function show($id) + { + $with = ['user', 'basic_audiocodec', 'basic_category', 'basic_codec', 'basic_media', 'basic_source', 'basic_standard', 'basic_team']; + + $result = Torrent::query()->with($with)->withCount(['peers', 'thank_users'])->visible()->findOrFail($id); + +// dd($result); + + $resource = new TorrentResource($result); + + return $this->success($resource); + } + + /** + * Update the specified resource in storage. + * + * @param \Illuminate\Http\Request $request + * @param int $id + * @return \Illuminate\Http\Response + */ + public function update(Request $request, $id) + { + // + } + + /** + * Remove the specified resource from storage. + * + * @param int $id + * @return \Illuminate\Http\Response + */ + public function destroy($id) + { + // + } + + public function searchBox() + { + $result = $this->repository->getSearchBox(); + + return $this->success($result); + } +} diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 1a807ecc..3f1c5e81 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -4,8 +4,13 @@ namespace App\Http\Controllers; use App\Http\Resources\ExamResource; use App\Http\Resources\InviteResource; +use App\Http\Resources\TorrentResource; use App\Http\Resources\UserResource; +use App\Models\Peer; +use App\Models\Snatch; +use App\Models\User; use App\Repositories\ExamRepository; +use App\Repositories\TorrentRepository; use App\Repositories\UserRepository; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; @@ -163,4 +168,105 @@ class UserController extends Controller return $this->success($result); } + public function me() + { + $user = Auth::user(); + + $resource = $this->getUserProfile($user->id); + + $rows = [ + [ + ['icon' => 'icon-user', 'label' => '种子评论', 'name' => 'comments_count'], + ['icon' => 'icon-user', 'label' => '论坛坛子', 'name' => 'posts_count'], + ],[ + ['icon' => 'icon-user', 'label' => '发布种子', 'name' => 'comments_count'], + ['icon' => 'icon-user', 'label' => '当前做种', 'name' => 'posts_count'], + ['icon' => 'icon-user', 'label' => '当前下载', 'name' => 'posts_count'], + ['icon' => 'icon-user', 'label' => '完成种子', 'name' => 'posts_count'], + ['icon' => 'icon-user', 'label' => '未完成种子', 'name' => 'posts_count'], + ] + ]; + $resource->additional([ + 'card_titles' => User::$cardTitles, + 'rows' => $rows + ]); + + return $this->success($resource); + } + + private function getUserProfile($id) + { + $user = User::query()->withCount(['comments', 'posts'])->findOrFail($id); + $resource = new UserResource($user); + return $resource; + } + + public function publishTorrent(Request $request) + { + $user = Auth::user(); + + $result = $user->torrents()->orderBy('id', 'desc')->paginate(); + + $resource = TorrentResource::collection($result); + + return $resource; + + } + + public function seedingTorrent(Request $request) + { + $user = Auth::user(); + + $result = $user->peers_torrents()->where('seeder', Peer::SEEDER_YES)->orderBy('torrent', 'desc')->paginate(); + + $resource = TorrentResource::collection($result); + + return $resource; + + } + + public function LeechingTorrent(Request $request) + { + $user = Auth::user(); + + $result = $user->peers_torrents()->where('seeder', Peer::SEEDER_NO)->orderBy('torrent', 'desc')->paginate(); + + $resource = TorrentResource::collection($result); + + return $resource; + + } + + public function finishedTorrent(Request $request) + { + $user = Auth::user(); + + $result = $user->snatched_torrents() + ->where('owner', '<>', $user->id) + ->where('finished', Snatch::FINISHED_YES) + ->orderBy('torrentid', 'desc') + ->paginate(); + + $resource = TorrentResource::collection($result); + + return $resource; + + } + + public function notFinishedTorrent(Request $request) + { + $user = Auth::user(); + + $result = $user->snatched_torrents() + ->where('owner', '<>', $user->id) + ->where('finished', Snatch::FINISHED_NO) + ->orderBy('torrentid', 'desc') + ->paginate(); + + $resource = TorrentResource::collection($result); + + return $resource; + + } + } diff --git a/app/Http/Resources/AudioCodecResource.php b/app/Http/Resources/AudioCodecResource.php new file mode 100644 index 00000000..6d43ed4f --- /dev/null +++ b/app/Http/Resources/AudioCodecResource.php @@ -0,0 +1,22 @@ + $this->id, + 'name' => $this->name, + ]; + } +} diff --git a/app/Http/Resources/CategoryResource.php b/app/Http/Resources/CategoryResource.php new file mode 100644 index 00000000..199328ac --- /dev/null +++ b/app/Http/Resources/CategoryResource.php @@ -0,0 +1,22 @@ + $this->id, + 'name' => $this->name, + ]; + } +} diff --git a/app/Http/Resources/CodecResource.php b/app/Http/Resources/CodecResource.php new file mode 100644 index 00000000..a93a07a6 --- /dev/null +++ b/app/Http/Resources/CodecResource.php @@ -0,0 +1,22 @@ + $this->id, + 'name' => $this->name, + ]; + } +} diff --git a/app/Http/Resources/CommentResource.php b/app/Http/Resources/CommentResource.php new file mode 100644 index 00000000..4ecaec39 --- /dev/null +++ b/app/Http/Resources/CommentResource.php @@ -0,0 +1,29 @@ +text); + return [ + 'id' => $this->id, + 'description' => $descriptionArr, + 'images' => get_image_from_description($descriptionArr), + 'updated_at_human' => format_datetime($this->editdate), + 'created_at_human' => $this->added->format('Y-m-d H:i'), + 'create_user' => new UserResource($this->whenLoaded('create_user')), + 'update_user' => new UserResource($this->whenLoaded('update_user')), + ]; + } +} diff --git a/app/Http/Resources/FileResource.php b/app/Http/Resources/FileResource.php new file mode 100644 index 00000000..ec11caf3 --- /dev/null +++ b/app/Http/Resources/FileResource.php @@ -0,0 +1,23 @@ + $this->id, + 'filename' => $this->filename, + 'size_human' => mksize($this->size), + ]; + } +} diff --git a/app/Http/Resources/MediaResource.php b/app/Http/Resources/MediaResource.php new file mode 100644 index 00000000..bcd6a984 --- /dev/null +++ b/app/Http/Resources/MediaResource.php @@ -0,0 +1,22 @@ + $this->id, + 'name' => $this->name, + ]; + } +} diff --git a/app/Http/Resources/MessageResource.php b/app/Http/Resources/MessageResource.php new file mode 100644 index 00000000..730541fa --- /dev/null +++ b/app/Http/Resources/MessageResource.php @@ -0,0 +1,25 @@ + $this->id, + 'subject' => $this->subject, + 'msg' => strip_all_tags($this->msg), + 'added_human' => $this->added->diffForHumans(), + 'send_user' => new UserResource($this->whenLoaded('send_user')), + ]; + } +} diff --git a/app/Http/Resources/PeerResource.php b/app/Http/Resources/PeerResource.php new file mode 100644 index 00000000..c5b6e161 --- /dev/null +++ b/app/Http/Resources/PeerResource.php @@ -0,0 +1,82 @@ +started->diff($this->last_action)->s; + if ($this->uploaded == 0) { + $uploadSpeed = mksize(0) . '/s'; + } else { + $uploadSpeed = mksize(($this->uploaded - $this->uploadoffset) / $seconds) . '/s'; + } + $nowTimestamp = time(); + return [ + 'id' => $this->id, + 'connectable_text' => $this->connectableText, + + 'upload_text' => sprintf('%s@%s', mksize($this->uploaded), $uploadSpeed), + + 'download_text' => sprintf('%s@%s', mksize($this->downloaded), $this->getUploadSpeed($this->resource)), + + 'share_ratio' => $this->getShareRatio($this->resource), + 'download_progress' => $this->getDownloadProgress($this->resource), + 'connect_time_total' => mkprettytime($nowTimestamp - $this->started->timestamp), + 'last_action_human' => mkprettytime($nowTimestamp - $this->last_action->timestamp), + 'agent_human' => htmlspecialchars(get_agent($this->peer_id, $this->agent)), + 'user' => new UserResource($this->whenLoaded('user')), + + ]; + } + + + /** + * 获得上传速度 + * + * @see viewpeerlist.php + * + * @param $peer + * @return string + */ + protected function getUploadSpeed($peer) + { + $diff = $peer->downloaded - $peer->downloadoffset; + if ($peer->isSeeder()) { + $seconds = $peer->finishedat - $peer->started->getTimestamp(); + } else { + $seconds = $this->started->diff($this->last_action)->s; + } + + return mksize($diff / $seconds) . '/s'; + } + + protected function getShareRatio($peer) + { + if ($peer->downloaded) { + $ratio = floor(($peer->uploaded / $peer->downloaded) * 1000) / 1000; + } elseif ($peer->uploaded) { + //@todo 读语言文件 + $ratio = '无限'; + } else { + $ratio = '---'; + } + + return $ratio; + } + + protected function getDownloadProgress($peer) + { + return sprintf("%.2f%%", 100 * (1 - ($peer->to_go / $peer->relative_torrent->size))); + } + +} diff --git a/app/Http/Resources/ProcessingResource.php b/app/Http/Resources/ProcessingResource.php new file mode 100644 index 00000000..2ac16187 --- /dev/null +++ b/app/Http/Resources/ProcessingResource.php @@ -0,0 +1,22 @@ + $this->id, + 'name' => $this->name, + ]; + } +} diff --git a/app/Http/Resources/SnatchResource.php b/app/Http/Resources/SnatchResource.php new file mode 100644 index 00000000..0c2e7ca1 --- /dev/null +++ b/app/Http/Resources/SnatchResource.php @@ -0,0 +1,38 @@ +uploaded); + $downloaded = mksize($this->downloaded); + $seedtime = mkprettytime($this->seedtime); + $leechtime = mkprettytime($this->leechtime); + $uprate = $this->seedtime > 0 ? mksize($this->uploaded / ($this->seedtime + $this->leechtime)) : mksize(0); + $downrate = $this->leechtime > 0 ? mksize($this->downloaded / $this->leechtime) : mksize(0); + $nowTimestamp = time(); + + return [ + 'id' => $this->id, + 'upload_text' => $uploaded . "@" . $uprate . "/s", + 'download_text' => $downloaded . "@" . $downrate . "/s", + 'share_ratio' => $this->getShareRatio($this->resource), + 'seed_time' => $seedtime, + 'leech_time' => $leechtime, + 'completed_at_human' => mkprettytime($nowTimestamp - $this->completedat->timestamp), + 'last_action_human' => mkprettytime($nowTimestamp - $this->last_action->timestamp), + 'user' => new UserResource($this->whenLoaded('user')), + ]; + } +} diff --git a/app/Http/Resources/SourceResource.php b/app/Http/Resources/SourceResource.php new file mode 100644 index 00000000..21d5e17d --- /dev/null +++ b/app/Http/Resources/SourceResource.php @@ -0,0 +1,22 @@ + $this->id, + 'name' => $this->name, + ]; + } +} diff --git a/app/Http/Resources/StandardResource.php b/app/Http/Resources/StandardResource.php new file mode 100644 index 00000000..e2ae652e --- /dev/null +++ b/app/Http/Resources/StandardResource.php @@ -0,0 +1,22 @@ + $this->id, + 'name' => $this->name, + ]; + } +} diff --git a/app/Http/Resources/TeamResource.php b/app/Http/Resources/TeamResource.php new file mode 100644 index 00000000..d8516798 --- /dev/null +++ b/app/Http/Resources/TeamResource.php @@ -0,0 +1,22 @@ + $this->id, + 'name' => $this->name, + ]; + } +} diff --git a/app/Http/Resources/ThankResource.php b/app/Http/Resources/ThankResource.php new file mode 100644 index 00000000..9e0dae41 --- /dev/null +++ b/app/Http/Resources/ThankResource.php @@ -0,0 +1,22 @@ + $this->id, + 'user' => new UserResource($this->whenLoaded('user')), + ]; + } +} diff --git a/app/Http/Resources/TorrentResource.php b/app/Http/Resources/TorrentResource.php new file mode 100644 index 00000000..76f9300a --- /dev/null +++ b/app/Http/Resources/TorrentResource.php @@ -0,0 +1,85 @@ + $this->id, + 'name' => $this->name, + 'filename' => $this->filename, + 'small_descr' => $this->small_descr, + 'comments' => $this->comments, + 'size_human' => mksize($this->size), + 'added' => $this->added->toDateTimeString(), + 'added_human' => $this->added->format('Y-m-d H:i'), + 'ttl' => $this->added->diffForHumans(['syntax' => CarbonInterface::DIFF_ABSOLUTE]), + 'leechers' => $this->leechers, + 'seeders' => $this->seeders, + 'times_completed' => $this->times_completed, + 'numfiles' => $this->numfiles, + 'user' => new UserResource($this->whenLoaded('user')), + 'basic_category' => new CategoryResource($this->whenLoaded('basic_category')), + ]; + + if ($request->routeIs('torrents.show')) { + $baseInfo = [ + ['label' => '大小', 'value' => mksize($this->size)], + ]; + if ($info = $this->whenLoaded('basic_category')) { + $baseInfo[] = ['label' => '类型', 'value' => $info->name]; + } + if ($info = $this->whenLoaded('basic_audiocodec')) { + $baseInfo[] = ['label' => '音频编码', 'value' => $info->name]; + } + if ($info = $this->whenLoaded('basic_codec')) { + $baseInfo[] = ['label' => '视频编码', 'value' => $info->name]; + } + if ($info = $this->whenLoaded('basic_media')) { + $baseInfo[] = ['label' => '媒介', 'value' => $info->name]; + } + if ($info = $this->whenLoaded('basic_source')) { + $baseInfo[] = ['label' => '来源', 'value' => $info->name]; + } + if ($info = $this->whenLoaded('basic_standard')) { + $baseInfo[] = ['label' => '分辨率', 'value' => $info->name]; + } + if ($info = $this->whenLoaded('basic_team')) { + $baseInfo[] = ['label' => '制作组', 'value' => $info->name]; + } + $out['base_info'] = $baseInfo; + $descriptionArr = format_description($this->descr); + $out['description'] = $descriptionArr; + + $out['images'] = get_image_from_description($descriptionArr); + + $out['thank_users_count'] = $this->thank_users_count; + $out['peers_count'] = $this->peers_count; + } + + $out['cover'] = get_image_from_description(format_description($this->descr), true); +// $out['upload_peers_count'] = $this->upload_peers_count; +// $out['download_peers_count'] = $this->download_peers_count; +// $out['finish_peers_count'] = $this->finish_peers_count; + + return $out; + + } + + + +} diff --git a/app/Http/Resources/UserResource.php b/app/Http/Resources/UserResource.php index 4d5404a1..b5282ee2 100644 --- a/app/Http/Resources/UserResource.php +++ b/app/Http/Resources/UserResource.php @@ -14,7 +14,7 @@ class UserResource extends JsonResource */ public function toArray($request) { - return [ + $out = [ 'id' => $this->id, 'email' => $this->email, 'username' => $this->username, @@ -35,5 +35,17 @@ class UserResource extends JsonResource 'leechtime_text' => mkprettytime($this->leechtime), 'inviter' => new UserResource($this->whenLoaded('inviter')), ]; + if ($request->routeIs('user.me')) { + $out['downloaded_human'] = mksize($this->downloaded); + $out['uploaded_human'] = mksize($this->uploaded); + $out['seed_time'] = mkprettytime($this->seedtime); + $out['leech_time'] = mkprettytime($this->leechtime); + $out['share_ratio'] = get_share_ratio($this->uploaded, $this->downloaded); + $out['seed_bonus'] = $this->seedbonus; + $out['invites'] = $this->invites; + $out['comments_count'] = $this->comments_count; + $out['posts_count'] = $this->posts_count; + } + return $out; } } diff --git a/app/Models/Attachment.php b/app/Models/Attachment.php new file mode 100644 index 00000000..3ce464c7 --- /dev/null +++ b/app/Models/Attachment.php @@ -0,0 +1,8 @@ + 'datetime', + 'editdate' => 'datetime', + ]; + + public function related_torrent() + { + return $this->belongsTo(Torrent::class, 'torrent'); + } + + public function create_user() + { + return $this->belongsTo(User::class, 'user'); + } + + public function update_user() + { + return $this->belongsTo(User::class, 'editedby'); + } +} diff --git a/app/Models/File.php b/app/Models/File.php new file mode 100644 index 00000000..f28ca347 --- /dev/null +++ b/app/Models/File.php @@ -0,0 +1,9 @@ + 'datetime', + ]; + + public function send_user() + { + return $this->belongsTo(User::class, 'sender')->withDefault(['id' => 0, 'username' => 'System']); + } + + public function receive_user() + { + return $this->belongsTo(User::class, 'receiver'); + } + } diff --git a/app/Models/Peer.php b/app/Models/Peer.php new file mode 100644 index 00000000..e0875ada --- /dev/null +++ b/app/Models/Peer.php @@ -0,0 +1,73 @@ + 'datetime', + 'last_action' => 'datetime', + 'prev_action' => 'datetime', + ]; + + public static $connectableText = [ + self::CONNECTABLE_YES => '是', + self::CONNECTABLE_NO => '否', + ]; + + const SEEDER_YES = 'yes'; + + const SEEDER_NO = 'no'; + + public static $cardTitles = [ + 'upload_text' => '上传', + 'download_text' => '下载', + 'share_ratio' => '分享率', + 'agent_human' => '客户端', + 'connect_time_total' => '连接时间', + 'download_progress' => '完成进度', + + ]; + + public function getConnectableTextAttribute() + { + return self::$connectableText[$this->connectable] ?? ''; + } + + public function scopeIsSeeder(Builder $builder) + { + return $builder->where('seeder', self::SEEDER_YES); + } + + public function scopeIsNotSeeder(Builder $builder) + { + return $builder->where('seeder', self::SEEDER_NO); + } + + public function isSeeder() + { + return $this->seeder == self::SEEDER_YES; + } + + public function isNotSeeder() + { + return $this->seeder == self::SEEDER_NO; + } + + public function user() + { + return $this->belongsTo(User::class, 'userid'); + } + + public function relative_torrent() + { + return $this->belongsTo(Torrent::class, 'torrent'); + } +} diff --git a/app/Models/Post.php b/app/Models/Post.php new file mode 100644 index 00000000..7919ba84 --- /dev/null +++ b/app/Models/Post.php @@ -0,0 +1,9 @@ + 'datetime', + 'startdat' => 'datetime', + 'completedat' => 'datetime', + ]; + + public static $cardTitles = [ + 'upload_text' => '上传', + 'download_text' => '下载', + 'share_ratio' => '分享率', + 'seed_time' => '做种时间', + 'leech_time' => '下载时间', + 'completed_at_human' => '完成', + ]; + + const FINISHED_YES = 'yes'; + + const FINISHED_NO = 'no'; + + public function scopeIsFinished(Builder $builder) + { + return $builder->where('finished', self::FINISHED_YES); + } + + public function scopeIsNotFinished(Builder $builder) + { + return $builder->where('finished', self::FINISHED_NO); + } + + public function torrent() + { + return $this->belongsTo(Torrent::class, 'torrentid'); + } + + public function user() + { + return $this->belongsTo(User::class, 'userid'); + } +} diff --git a/app/Models/Source.php b/app/Models/Source.php new file mode 100644 index 00000000..aab4ab1d --- /dev/null +++ b/app/Models/Source.php @@ -0,0 +1,8 @@ +belongsTo(User::class, 'userid'); + } + + public function torrent() + { + return $this->belongsTo(Torrent::class. 'torrentid'); + } +} diff --git a/app/Models/Torrent.php b/app/Models/Torrent.php index b920c32e..eea074ed 100644 --- a/app/Models/Torrent.php +++ b/app/Models/Torrent.php @@ -18,7 +18,9 @@ class Torrent extends NexusModel const BANNED_YES = 'yes'; const BANNED_NO = 'no'; - public $timestamps = true; + protected $casts = [ + 'added' => 'datetime' + ]; public function checkIsNormal(array $fields = ['visible', 'banned']) { @@ -31,4 +33,104 @@ class Torrent extends NexusModel return true; } + + public function user() + { + return $this->belongsTo(User::class, 'owner'); + } + + public function thanks() + { + return $this->hasMany(Thank::class, 'torrentid'); + } + + public function thank_users() + { + return $this->belongsToMany(User::class, 'thanks', 'torrentid', 'userid'); + } + + /** + * 同伴 + * + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ + public function peers() + { + return $this->hasMany(Peer::class, 'torrent'); + } + + /** + * 完成情况 + * + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ + public function snatches() + { + return $this->hasMany(Snatch::class, 'torrentid'); + } + + public function upload_peers() + { + return $this->peers()->where('seeder', Peer::SEEDER_YES); + } + + public function download_peers() + { + return $this->peers()->where('seeder', Peer::SEEDER_NO); + } + + public function finish_peers() + { + return $this->peers()->where('finishedat', '>', 0); + } + + public function files() + { + return $this->hasMany(File::class, 'torrent'); + } + + public function basic_category() + { + return $this->belongsTo(Category::class, 'category'); + } + + public function basic_source() + { + return $this->belongsTo(Source::class, 'source'); + } + + public function basic_media() + { + return $this->belongsTo(Media::class, 'medium'); + } + + public function basic_codec() + { + return $this->belongsTo(Codec::class, 'codec'); + } + + public function basic_standard() + { + return $this->belongsTo(Standard::class, 'standard'); + } + + public function basic_processing() + { + return $this->belongsTo(Processing::class, 'processing'); + } + + public function basic_team() + { + return $this->belongsTo(Team::class, 'team'); + } + + public function basic_audiocodec() + { + return $this->belongsTo(AudioCodec::class, 'audiocodec'); + } + + public function scopeVisible($query, $visible = self::VISIBLE_YES) + { + $query->where('visible', $visible); + } } diff --git a/app/Models/User.php b/app/Models/User.php index 82da0210..3176b8a1 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -59,6 +59,15 @@ class User extends Authenticatable self::CLASS_STAFF_LEADER => ['text' => 'Staff Leader'], ]; + public static $cardTitles = [ + 'uploaded_human' => '上传', + 'downloaded_human' => '下载', + 'share_ratio' => '分享率', + 'seed_time' => '做种时间', + 'seed_bonus' => '魔力值', + 'invites' => '邀请', + ]; + public function getClassTextAttribute(): string { return self::$classes[$this->class]['text'] ?? ''; @@ -157,6 +166,68 @@ class User extends Authenticatable return $this->belongsTo(User::class, 'invited_by'); } + public function send_messages() + { + return $this->hasMany(Message::class, 'sender'); + } + + public function receive_messages() + { + return $this->hasMany(Message::class, 'receiver'); + } + + public function comments() + { + return $this->hasMany(Comment::class, 'user'); + } + + public function posts() + { + return $this->hasMany(Post::class, 'userid'); + } + + public function torrents() + { + return $this->hasMany(Torrent::class, 'owner'); + } + + + public function peers_torrents() + { + return $this->hasManyThrough( + Torrent::class, + Peer::class, + 'userid', + 'id', + 'id', + 'torrent'); + } + + public function snatched_torrents() + { + return $this->hasManyThrough( + Torrent::class, + Snatch::class, + 'userid', + 'id', + 'id', + 'torrentid'); + } + + public function getAvatarAttribute($value) + { + if ($value) { + if (substr($value, 0, 4) == 'http') { + return $value; + } else { + do_log("用户头像: $value 不是 http 地址"); + } + } + + return getSchemeAndHttpHost() . '/pic/default_avatar.png'; + + } + public function updateWithModComment(array $update, $modComment) { if (!$this->exists) { diff --git a/app/Repositories/ToolRepository.php b/app/Repositories/ToolRepository.php index 509921a6..f055bb23 100644 --- a/app/Repositories/ToolRepository.php +++ b/app/Repositories/ToolRepository.php @@ -10,13 +10,13 @@ class ToolRepository extends BaseRepository public function getSystemInfo(): array { $systemInfo = [ - 'nexus_version' => config('app.nexus_version'), + 'nexus_version' => VERSION_NUMBER, + 'nexus_release_date' => RELEASE_DATE, 'laravel_version' => \Illuminate\Foundation\Application::VERSION, 'php_version' => PHP_VERSION, 'mysql_version' => DB::select(DB::raw('select version() as info'))[0]->info, 'os' => PHP_OS, 'server_software' => $_SERVER['SERVER_SOFTWARE'], - ]; return $systemInfo; diff --git a/app/Repositories/TorrentRepository.php b/app/Repositories/TorrentRepository.php new file mode 100644 index 00000000..4dbd06f6 --- /dev/null +++ b/app/Repositories/TorrentRepository.php @@ -0,0 +1,127 @@ +where('category', $params['category']); + } + if (!empty($params['source'])) { + $query->where('source', $params['source']); + } + if (!empty($params['medium'])) { + $query->where('medium', $params['medium']); + } + if (!empty($params['codec'])) { + $query->where('codec', $params['codec']); + } + if (!empty($params['audio_codec'])) { + $query->where('audiocodec', $params['audio_codec']); + } + if (!empty($params['standard'])) { + $query->where('standard', $params['standard']); + } + if (!empty($params['processing'])) { + $query->where('processing', $params['processing']); + } + if (!empty($params['team'])) { + $query->where('team', $params['team']); + } + if (!empty($params['owner'])) { + $query->where('owner', $params['owner']); + } + if (!empty($params['visible'])) { + $query->where('visible', $params['visible']); + } + + if (!empty($params['query'])) { + $query->where(function (Builder $query) use ($params) { + $query->where('name', 'like', "%{$params['query']}%") + ->orWhere('small_descr', 'like', "%{$params['query']}%"); + }); + } + + list($sortField, $sortType) = $this->getSortFieldAndType($params); + $query->orderBy($sortField, $sortType); + + $with = ['user']; + $torrents = $query->with($with)->paginate(); + return $torrents; + } + + public function getSearchBox() + { + $category = Category::query()->orderBy('sort_index')->orderBy('id')->get(); + $source = Source::query()->orderBy('sort_index')->orderBy('id')->get(); + $media = Media::query()->orderBy('sort_index')->orderBy('id')->get(); + $codec = Codec::query()->orderBy('sort_index')->orderBy('id')->get(); + $standard = Standard::query()->orderBy('sort_index')->orderBy('id')->get(); + $processing = Processing::query()->orderBy('sort_index')->orderBy('id')->get(); + $team = Team::query()->orderBy('sort_index')->orderBy('id')->get(); + $audioCodec = AudioCodec::query()->orderBy('sort_index')->orderBy('id')->get(); + + $modalRows = []; + $modalRows[] = $categoryFormatted = $this->formatRow('类型', $category, 'category'); + $modalRows[] = $this->formatRow('媒介', $source, 'source'); + $modalRows[] = $this->formatRow('媒介', $media, 'medium'); + $modalRows[] = $this->formatRow('编码', $codec, 'codec'); + $modalRows[] = $this->formatRow('音频编码', $audioCodec, 'audio_codec'); + $modalRows[] = $this->formatRow('分辨率', $standard, 'standard'); + $modalRows[] = $this->formatRow('处理', $processing, 'processing'); + $modalRows[] = $this->formatRow('制作组', $team, 'team'); + + $results = []; + $categories = $categoryFormatted['rows']; + $categories[0]['active'] = 1; + $results['categories'] = $categories; + $results['modal_rows'] = $modalRows; + + + return $results; + } + + private function formatRow($header, $items, $name) + { + $result['header'] = $header; + $result['rows'][] = [ + 'label' => '全部', + 'value' => 0, + 'name' => $name, + 'active' => 1, + ]; + foreach ($items as $value) { + $item = [ + 'label' => $value->name, + 'value' => $value->id, + 'name' => $name, + 'active' => 0, + ]; + $result['rows'][] = $item; + } + return $result; + } + +} diff --git a/bootstrap/app.php b/bootstrap/app.php index b4756cd0..3db5aec2 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -1,9 +1,9 @@ '1.6.0-beta5', - ]; diff --git a/include/bittorrent.php b/include/bittorrent.php index 67ded965..b423ce5d 100644 --- a/include/bittorrent.php +++ b/include/bittorrent.php @@ -1,15 +1,9 @@ ".PROJECTNAME.""); -define("THISTRACKER","General"); -$showversion = " - Powered by ".PROJECTNAME; -$rootpath= dirname(__DIR__); +define('IN_NEXUS', true); +$rootpath = dirname(__DIR__) . '/'; set_include_path(get_include_path() . PATH_SEPARATOR . $rootpath); -$rootpath .= "/"; +require $rootpath . 'include/core.php'; require $rootpath . 'classes/class_advertisement.php'; require $rootpath . 'classes/class_attendance.php'; -require $rootpath . 'include/core.php'; + diff --git a/include/bittorrent_announce.php b/include/bittorrent_announce.php index f630620f..92fa10c5 100644 --- a/include/bittorrent_announce.php +++ b/include/bittorrent_announce.php @@ -1,7 +1,7 @@ ".PROJECTNAME.""); +define("THISTRACKER","General"); +$showversion = " - Powered by ".PROJECTNAME; +define('ROOT_PATH', dirname(__DIR__) . '/'); +define('CURRENT_SCRIPT', strstr(basename($_SERVER['SCRIPT_FILENAME']), '.', true)); +define('IS_ANNOUNCE', CURRENT_SCRIPT == 'announce'); +define('REQUEST_ID', $_SERVER['HTTP_X_REQUEST_ID'] ?? $_SERVER['REQUEST_ID'] ?? str_pad(str_replace('.', '', NEXUS_START), 14, "0", STR_PAD_RIGHT)); diff --git a/include/core.php b/include/core.php index e48a5cc4..0c39b667 100644 --- a/include/core.php +++ b/include/core.php @@ -1,13 +1,5 @@ whereIn('dlkey', $matches[2])->get()->keyBy('dlkey'); + if ($attachments->isNotEmpty()) { + $description = preg_replace_callback($pattern, function ($matches) use ($attachments) { + $item = $attachments->get($matches[2]); + $url = attachmentUrl($item->location); + return str_replace($matches[2], $url, $matches[1]); + }, $description); + } + } + //去除引用 +// $pattern = '/\[quote.*\].*\[\/quote\]/is'; +// $description = preg_replace($pattern, '', $description); + + //去掉引用自 + $pattern = '/\[quote=.*\]/isU'; + $description = preg_replace_callback($pattern, function ($matches) { + return '[quote]'; + }, $description); + + //过虑多层引用 + $delimiter = '__CYLX__'; + $pattern = '/(\[quote\]){2,}(((?!\[quote\]).)*)\[\/quote\]/isU'; + $description = preg_replace_callback($pattern, function ($matches) use ($delimiter) { + return $delimiter; + }, $description); + + $pattern = "/$delimiter(((?!\[quote\]).)+)\[\/quote\]/is"; + $description = preg_replace_callback($pattern, function ($matches) use ($delimiter) { + $arr = array_reverse(explode('[/quote]', $matches[0])); + foreach ($arr as $value) { + $value = trim(str_replace($delimiter, '', $value)); + if (!empty($value)) { + return "[quote]{$value}[/quote]"; + } + } + }, $description); + + + //匹配不同块 + $attachPattern = '\[attach\].*\[\/attach\]'; + $imgPattern = '\[img\].*\[\/img\]'; + $urlPattern = '\[url=.*\].*\[\/url\]'; + $quotePattern = '\[quote.*\].*\[\/quote\]'; + $pattern = "/($attachPattern)|($imgPattern)|($urlPattern)|($quotePattern)/isU"; +// $pattern = "/($attachPattern)|($imgPattern)|($urlPattern)/isU"; + $delimiter = '{{||}}'; + $description = preg_replace_callback($pattern, function ($matches) use ($delimiter) { + return $delimiter . $matches[0] . $delimiter; + }, $description); + + //再进行分割 + $descriptionArr = preg_split("/[$delimiter]+/", $description); + $results = []; + foreach ($descriptionArr as $item) { + if (preg_match('/\[attach\](.*)\[\/attach\]/isU', $item, $matches)) { + //是否附件 + $results[] = [ + 'type' => 'attachment', + 'data' => [ + 'url' => $matches[1] + ] + ]; + } elseif (preg_match('/\[img\](.*)\[\/img\]/isU', $item, $matches)) { + //是否图片 + $results[] = [ + 'type' => 'image', + 'data' => [ + 'url' => $matches[1] + ] + ]; + } elseif (preg_match('/\[url=(.*)\](.*)\[\/url\]/isU', $item, $matches)) { + $results[] = [ + 'type' => 'url', + 'data' => [ + 'url' => $matches[1], + 'text' => strip_all_tags($matches[2]) + ] + ]; + } elseif (preg_match('/\[quote=?(.*)\](.*)\[\/quote\]/isU', $item, $matches)) { + $results[] = [ + 'type' => 'quote', + 'data' => [ + 'quote_text' => $matches[1], + 'text' => strip_all_tags($matches[2]), + ] + ]; + } elseif (!empty($item)) { + $results[] = [ + 'type' => 'text', + 'data' => [ + 'text' => strip_all_tags($item) + ] + ]; + } + } +// dd($description, $results); + return $results; +} + +function get_image_from_description(array $descriptionArr, $first = false) +{ + $imageType = ['attachment', 'image']; + $images = []; + foreach ($descriptionArr as $value) { + if (!in_array($value['type'], $imageType)) { + continue; + } + $url = $value['data']['url'] ?? ''; + if (!$url) { + continue; + } + if ($first) { + return $url; + } else { + $images[] = $url; + } + } + if ($first) { + return getSchemeAndHttpHost() . "/pic/imdb_pic/nophoto.gif"; + } + return $images; +} + +function get_share_ratio($uploaded, $downloaded) +{ + if ($downloaded) { + $ratio = floor(($uploaded / $downloaded) * 1000) / 1000; + } elseif ($uploaded) { + //@todo 读语言文件 + $ratio = '无限'; + } else { + $ratio = '---'; + } + return $ratio; +} + ?> diff --git a/include/globalfunctions.php b/include/globalfunctions.php index 52168c8b..3fb41523 100644 --- a/include/globalfunctions.php +++ b/include/globalfunctions.php @@ -422,10 +422,6 @@ function getSchemeAndHttpHost() $protocol = $isHttps ? 'https' : 'http'; $port = $_SERVER['SERVER_PORT']; $result = "$protocol://" . $_SERVER['HTTP_HOST']; - //HTTP_HOST include port -// if ((!$isHttps && $port != 80) || ($isHttps && $port != 443)) { -// $result .= ":$port"; -// } return $result; } diff --git a/public/aboutnexus.php b/public/aboutnexus.php index 462c1de6..242b6e1e 100644 --- a/public/aboutnexus.php +++ b/public/aboutnexus.php @@ -9,9 +9,9 @@ begin_main_frame(); begin_frame("".$lang_aboutnexus['text_version'].""); print ($lang_aboutnexus['text_version_note']); print ("

"); -tr($lang_aboutnexus['text_main_version'],$mainversion_code,1); -tr($lang_aboutnexus['text_sub_version'],$subversion_code,1); -tr($lang_aboutnexus['text_release_date'],$releasedate_code,1); +tr($lang_aboutnexus['text_main_version'],PROJECTNAME,1); +tr($lang_aboutnexus['text_sub_version'],VERSION_NUMBER,1); +tr($lang_aboutnexus['text_release_date'],RELEASE_DATE,1); print ("
"); print ("

"); end_frame(); @@ -56,7 +56,7 @@ end_frame(); begin_frame("".$lang_aboutnexus['text_contact'].PROJECTNAME.""); print ($lang_aboutnexus['text_contact_note']); print ("

"); -tr($lang_aboutnexus['text_web_site'],$website_code ? $website_code : "N/A",1); +tr($lang_aboutnexus['text_web_site'],'' . NEXUSPHPURL . '',1); print ("
"); print ("

"); end_frame(); diff --git a/routes/api.php b/routes/api.php index 2f5b2557..5119694a 100644 --- a/routes/api.php +++ b/routes/api.php @@ -29,6 +29,22 @@ Route::group(['middleware' => ['auth:sanctum', 'permission', 'locale']], functio Route::post('user-enable', [\App\Http\Controllers\UserController::class, 'enable']); Route::post('user-reset-password', [\App\Http\Controllers\UserController::class, 'resetPassword']); + Route::get('user-me',[\App\Http\Controllers\UserController::class, 'me'])->name('user.me'); + Route::get('user-publish-torrent',[\App\Http\Controllers\UserController::class, 'publishTorrent']); + Route::get('user-seeding-torrent',[\App\Http\Controllers\UserController::class, 'seedingTorrent']); + Route::get('user-leeching-torrent',[\App\Http\Controllers\UserController::class, 'leechingTorrent']); + Route::get('user-finished-torrent',[\App\Http\Controllers\UserController::class, 'finishedTorrent']); + Route::get('user-not-finished-torrent',[\App\Http\Controllers\UserController::class, 'notFinishedTorrent']); + Route::resource('messages', \App\Http\Controllers\MessageController::class); + Route::resource('torrents', \App\Http\Controllers\TorrentController::class); + Route::resource('comments', \App\Http\Controllers\CommentController::class); + Route::resource('peers', \App\Http\Controllers\PeerController::class); + 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::get('search-box', [\App\Http\Controllers\TorrentController::class, 'searchBox']); + + Route::resource('exams', \App\Http\Controllers\ExamController::class); Route::get('exam-indexes', [\App\Http\Controllers\ExamController::class, 'indexes']);