Skip to content

Commit 27ec4a5

Browse files
committed
add: store torrent deletion reason
To be later used on the unregistered info hash page, in the tracker's torrent deletion message for bittorrent clients and perhaps a work edit log.
1 parent b3d2b36 commit 27ec4a5

27 files changed

+1065
-133
lines changed

.cspell/laravel.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
arrayable
22
assertdontseetext
3+
datetimes
34
dispatchable
45
doesntcontain
56
doesntexist
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* NOTICE OF LICENSE.
7+
*
8+
* UNIT3D Community Edition is open-sourced software licensed under the GNU Affero General Public License v3.0
9+
* The details is bundled with this project in the file LICENSE.txt.
10+
*
11+
* @project UNIT3D Community Edition
12+
*
13+
* @author Roardom <roardom@protonmail.com>
14+
* @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0
15+
*/
16+
17+
namespace App\Http\Controllers\Staff;
18+
19+
use App\Http\Controllers\Controller;
20+
use App\Http\Requests\Staff\DestroyTorrentDeletionReasonRequest;
21+
use App\Http\Requests\Staff\StoreTorrentDeletionReasonRequest;
22+
use App\Http\Requests\Staff\UpdateTorrentDeletionReasonRequest;
23+
use App\Models\TorrentDeletionReason;
24+
use Exception;
25+
26+
class TorrentDeletionReasonController extends Controller
27+
{
28+
/**
29+
* Display all torrent deletion reasons.
30+
*/
31+
public function index(): \Illuminate\Contracts\View\Factory|\Illuminate\View\View
32+
{
33+
return view('Staff.torrent-deletion-reason.index', [
34+
'torrentDeletionReasons' => TorrentDeletionReason::query()->get(),
35+
]);
36+
}
37+
38+
/**
39+
* Show torrent deletion reason create form.
40+
*/
41+
public function create(): \Illuminate\Contracts\View\Factory|\Illuminate\View\View
42+
{
43+
return view('Staff.torrent-deletion-reason.create');
44+
}
45+
46+
/**
47+
* Store a new torrent deletion reason.
48+
*/
49+
public function store(StoreTorrentDeletionReasonRequest $request): \Illuminate\Http\RedirectResponse
50+
{
51+
TorrentDeletionReason::query()->create($request->validated());
52+
53+
return to_route('staff.torrent_deletion_reasons.index')
54+
->with('success', 'Type successfully added');
55+
}
56+
57+
/**
58+
* Torrent deletion reason edit form.
59+
*/
60+
public function edit(TorrentDeletionReason $torrentDeletionReason): \Illuminate\Contracts\View\Factory|\Illuminate\View\View
61+
{
62+
return view('Staff.torrent-deletion-reason.edit', [
63+
'torrentDeletionReason' => $torrentDeletionReason,
64+
]);
65+
}
66+
67+
/**
68+
* Edit a torrent deletion reason.
69+
*/
70+
public function update(UpdateTorrentDeletionReasonRequest $request, TorrentDeletionReason $torrentDeletionReason): \Illuminate\Http\RedirectResponse
71+
{
72+
$torrentDeletionReason->update($request->validated());
73+
74+
return to_route('staff.torrent_deletion_reasons.index')
75+
->with('success', 'Type successfully modified');
76+
}
77+
78+
/**
79+
* Delete edit form.
80+
*/
81+
public function delete(TorrentDeletionReason $torrentDeletionReason): \Illuminate\Contracts\View\Factory|\Illuminate\View\View
82+
{
83+
return view('Staff.torrent-deletion-reason.delete', [
84+
'otherTorrentDeletionReasons' => TorrentDeletionReason::query()->where('id', '!=', $torrentDeletionReason->id)->get(),
85+
'torrentDeletionReason' => $torrentDeletionReason,
86+
]);
87+
}
88+
89+
/**
90+
* Delete a torrent deletion reason.
91+
*
92+
* @throws Exception
93+
*/
94+
public function destroy(DestroyTorrentDeletionReasonRequest $request, TorrentDeletionReason $torrentDeletionReason): \Illuminate\Http\RedirectResponse
95+
{
96+
$torrentDeletionReason->torrents()->update($request->validated());
97+
$torrentDeletionReason->delete();
98+
99+
return to_route('staff.torrent_deletion_reasons.index')
100+
->with('success', 'Type successfully deleted');
101+
}
102+
}

app/Http/Controllers/TorrentController.php

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
use App\Models\TmdbMovie;
3636
use App\Models\TmdbTv;
3737
use App\Models\Torrent;
38+
use App\Models\TorrentDeletionReason;
3839
use App\Models\TorrentFile;
3940
use App\Models\Type;
4041
use App\Models\User;
@@ -49,6 +50,7 @@
4950
use Illuminate\Support\Facades\DB;
5051
use Illuminate\Support\Facades\Notification;
5152
use Illuminate\Support\Facades\Storage;
53+
use Illuminate\Validation\Rule;
5254
use ReflectionException;
5355
use JsonException;
5456

@@ -230,10 +232,11 @@ public function show(Request $request, int|string $id): \Illuminate\Contracts\Vi
230232
|| now()->isBefore($torrent->created_at->addDay())
231233
)
232234
),
233-
'personal_freeleech' => PersonalFreeleech::query()->where('user_id', '=', $user->id)->exists(),
234-
'mediaInfo' => $torrent->mediainfo !== null ? (new MediaInfo())->parse($torrent->mediainfo) : null,
235-
'fileTree' => $fileTree,
236-
'alsoDownloaded' => cache()->flexible(
235+
'personal_freeleech' => PersonalFreeleech::query()->where('user_id', '=', $user->id)->exists(),
236+
'mediaInfo' => $torrent->mediainfo !== null ? (new MediaInfo())->parse($torrent->mediainfo) : null,
237+
'torrentDeletionReasons' => TorrentDeletionReason::query()->get(),
238+
'fileTree' => $fileTree,
239+
'alsoDownloaded' => cache()->flexible(
237240
'also-downloaded:by-torrent-id:'.$torrent->id,
238241
[3600 * 12, 3600 * 24 * 14],
239242
match (true) {
@@ -436,10 +439,21 @@ public function update(UpdateTorrentRequest $request, int $id): \Illuminate\Http
436439
*/
437440
public function destroy(Request $request, int $id): \Illuminate\Http\RedirectResponse
438441
{
442+
$trumpedBy = Torrent::query()->find(basename((string) $request->trumped_by));
443+
444+
if ($request->trumped_by !== null && $trumpedBy === null) {
445+
return back()->withErrors('Submitted trumped torrent link not found or not yet approved.');
446+
}
447+
439448
$request->validate([
440-
'message' => [
449+
'deletion_reason_id' => [
441450
'required',
442-
'min:1',
451+
Rule::exists('torrent_deletion_reasons', 'id'),
452+
],
453+
'deletion_reason_extra' => [
454+
'nullable',
455+
'sometimes',
456+
'max:1000',
443457
],
444458
]);
445459

@@ -448,11 +462,6 @@ public function destroy(Request $request, int $id): \Illuminate\Http\RedirectRes
448462

449463
abort_unless($user->group->is_modo || ($user->id === $torrent->user_id && now()->lt($torrent->created_at->addDay())), 403);
450464

451-
Notification::send(
452-
User::query()->whereHas('history', fn ($query) => $query->where('torrent_id', '=', $torrent->id))->get(),
453-
new TorrentDeleted($torrent, $request->message),
454-
);
455-
456465
// Reset Requests
457466
$torrent->requests()->whereNull('approved_when')->update([
458467
'torrent_id' => null,
@@ -482,10 +491,21 @@ public function destroy(Request $request, int $id): \Illuminate\Http\RedirectRes
482491

483492
cache()->forget('announce-torrents:by-infohash:'.$torrent->info_hash);
484493

494+
$torrent->update([
495+
'trumped_by' => $trumpedBy->id,
496+
'deletion_reason_id' => $request->deletion_reason_id,
497+
'deletion_reason_extra' => $request->deletion_reason_extra,
498+
]);
499+
485500
Unit3dAnnounce::removeTorrent($torrent);
486501

487502
$torrent->delete();
488503

504+
Notification::send(
505+
User::query()->whereHas('history', fn ($query) => $query->withTrashed()->where('torrent_id', '=', $torrent->id))->get(),
506+
new TorrentDeleted($torrent),
507+
);
508+
489509
return to_route('torrents.index')
490510
->with('success', 'Torrent has been deleted!');
491511
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* NOTICE OF LICENSE.
7+
*
8+
* UNIT3D Community Edition is open-sourced software licensed under the GNU Affero General Public License v3.0
9+
* The details is bundled with this project in the file LICENSE.txt.
10+
*
11+
* @project UNIT3D Community Edition
12+
*
13+
* @author HDVinnie <hdinnovations@protonmail.com>
14+
* @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0
15+
*/
16+
17+
namespace App\Http\Controllers;
18+
19+
use App\Models\TorrentDeletionReason;
20+
21+
class TorrentDeletionReasonController extends Controller
22+
{
23+
/**
24+
* Show torrent deletion reasons index.
25+
*/
26+
public function index(): \Illuminate\Contracts\View\Factory|\Illuminate\View\View
27+
{
28+
return view('torrent-deletion-reason.index', [
29+
'torrentDeletionReasons' => TorrentDeletionReason::query()->get(),
30+
]);
31+
}
32+
}

app/Http/Livewire/SimilarTorrent.php

Lines changed: 70 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
use App\Models\Torrent;
3030
use App\Models\TorrentRequest;
3131
use App\Models\TmdbTv;
32+
use App\Models\TorrentDeletionReason;
3233
use App\Models\Type;
3334
use App\Models\User;
3435
use App\Notifications\TorrentsDeleted;
@@ -37,6 +38,8 @@
3738
use App\Traits\LivewireSort;
3839
use App\Traits\TorrentMeta;
3940
use Illuminate\Support\Facades\Notification;
41+
use Illuminate\Support\Facades\Validator;
42+
use Illuminate\Validation\Rule;
4043
use Livewire\Attributes\Url;
4144
use Livewire\Component;
4245

@@ -54,7 +57,11 @@ class SimilarTorrent extends Component
5457

5558
public ?int $igdbId;
5659

57-
public string $reason;
60+
public ?string $trumpedBy = null;
61+
62+
public ?int $deletionReasonId = null;
63+
64+
public string $deletionReasonExtra = '';
5865

5966
#[Url(history: true)]
6067
public string $name = '';
@@ -399,29 +406,57 @@ final public function updatedChecked(): void
399406
get => $this->work instanceof TmdbMovie ? $this->work->collections()->first()?->movies()->get() : null;
400407
}
401408

402-
final public function alertConfirm(): void
409+
/**
410+
* @var \Illuminate\Database\Eloquent\Collection<int, TorrentDeletionReason>
411+
*/
412+
final protected \Illuminate\Database\Eloquent\Collection $torrentDeletionReasons {
413+
get => TorrentDeletionReason::query()->get();
414+
}
415+
416+
/**
417+
* @var \Illuminate\Database\Eloquent\Collection<int, Torrent>
418+
*/
419+
final protected \Illuminate\Database\Eloquent\Collection $deletingTorrents {
420+
get => Torrent::query()->select(['id', 'name'])->whereKey($this->checked)->get();
421+
}
422+
423+
final public function deleteRecords(): void
403424
{
404425
if (!auth()->user()->group->is_modo) {
405426
$this->dispatch('error', type: 'error', message: 'Permission denied!');
406427

407428
return;
408429
}
409430

410-
$torrents = Torrent::query()->whereKey($this->checked)->pluck('name')->toArray();
411-
$names = $torrents;
412-
$this->dispatch(
413-
'swal:confirm',
414-
type: 'warning',
415-
message: 'Are you sure?',
416-
body: 'If deleted, you will not be able to recover the following files!'.nl2br("\n")
417-
.nl2br(implode("\n", $names)),
418-
);
419-
}
431+
$trumpedBy = Torrent::query()->find(basename($this->trumpedBy));
420432

421-
final public function deleteRecords(): void
422-
{
423-
if (!auth()->user()->group->is_modo) {
424-
$this->dispatch('error', type: 'error', message: 'Permission denied!');
433+
if ($this->trumpedBy !== null && $trumpedBy === null) {
434+
$this->dispatch('error', type: 'error', message: 'Submitted trumped torrent link not found or not yet approved.');
435+
436+
return;
437+
}
438+
439+
$validator = Validator::make([
440+
'deletion_reason_id' => $this->deletionReasonId,
441+
'deletion_reason_extra' => $this->deletionReasonExtra,
442+
], [
443+
'deletion_reason_id' => [
444+
'required',
445+
Rule::exists('torrent_deletion_reasons', 'id'),
446+
],
447+
'deletion_reason_extra' => [
448+
'nullable',
449+
'sometimes',
450+
'max:1000',
451+
],
452+
]);
453+
454+
if ($validator->fails()) {
455+
$this->dispatch(
456+
'error',
457+
type: 'error',
458+
message: $validator->messages()->get('deletion_reason_id') + $validator->messages()->get('deletion_reason_extra')
459+
);
425460

426461
return;
427462
}
@@ -473,12 +508,17 @@ final public function deleteRecords(): void
473508

474509
Unit3dAnnounce::removeTorrent($torrent);
475510

511+
$torrent->update([
512+
'trumped_by' => $trumpedBy->id,
513+
'deletion_reason_id' => $this->deletionReasonId,
514+
'deletion_reason_extra' => $this->deletionReasonExtra,
515+
]);
476516
$torrent->delete();
477517
}
478518

479519
Notification::send(
480520
array_map(fn ($userId) => new User(['id' => $userId]), $users),
481-
new TorrentsDeleted($torrents, $title, $this->reason)
521+
new TorrentsDeleted($torrents, $title)
482522
);
483523

484524
$this->checked = [];
@@ -543,17 +583,19 @@ final public function deleteRecords(): void
543583
final public function render(): \Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Contracts\Foundation\Application
544584
{
545585
return view('livewire.similar-torrent', [
546-
'user' => auth()->user(),
547-
'similarTorrents' => $this->torrents,
548-
'personalFreeleech' => $this->personalFreeleech,
549-
'torrentRequests' => $this->torrentRequests,
550-
'media' => $this->work,
551-
'types' => $this->types,
552-
'resolutions' => $this->resolutions,
553-
'regions' => $this->regions,
554-
'distributors' => $this->distributors,
555-
'playlistCategories' => $this->playlistCategories,
556-
'collectionMovies' => $this->collectionMovies,
586+
'user' => auth()->user(),
587+
'similarTorrents' => $this->torrents,
588+
'personalFreeleech' => $this->personalFreeleech,
589+
'torrentRequests' => $this->torrentRequests,
590+
'media' => $this->work,
591+
'types' => $this->types,
592+
'resolutions' => $this->resolutions,
593+
'regions' => $this->regions,
594+
'distributors' => $this->distributors,
595+
'playlistCategories' => $this->playlistCategories,
596+
'collectionMovies' => $this->collectionMovies,
597+
'torrentDeletionReasons' => $this->torrentDeletionReasons,
598+
'deletingTorrents' => $this->deletingTorrents,
557599
]);
558600
}
559601
}

0 commit comments

Comments
 (0)