Merge branch '7.x.x' into active-peers

This commit is contained in:
HDVinnie
2023-07-24 13:04:12 -04:00
committed by GitHub
64 changed files with 824 additions and 351 deletions
+3 -3
View File
@@ -106,11 +106,11 @@ class SystemBot
$this->target->save();
$bonTransactions = new BonTransactions();
$bonTransactions->itemID = 0;
$bonTransactions->bon_exchange_id = 0;
$bonTransactions->name = 'gift';
$bonTransactions->cost = $value;
$bonTransactions->sender = $this->target->id;
$bonTransactions->receiver = $recipient->id;
$bonTransactions->sender_id = $this->target->id;
$bonTransactions->receiver_id = $recipient->id;
$bonTransactions->comment = $output;
$bonTransactions->torrent_id = null;
$bonTransactions->save();
+10 -18
View File
@@ -107,8 +107,7 @@ class AutoBonAllocation extends Command
->toArray();
$participaintSeeder = DB::table('history')
->select(DB::raw('count(DISTINCT(history.torrent_id)) as value'), 'history.user_id')
->join('torrents', 'torrents.id', 'history.torrent_id')
->select(DB::raw('count(*) as value'), 'history.user_id')
->where('history.active', 1)
->where('history.seedtime', '>=', 2_592_000)
->where('history.seedtime', '<', 2_592_000 * 2)
@@ -117,8 +116,7 @@ class AutoBonAllocation extends Command
->toArray();
$teamplayerSeeder = DB::table('history')
->select(DB::raw('count(DISTINCT(history.torrent_id)) as value'), 'history.user_id')
->join('torrents', 'torrents.id', 'history.torrent_id')
->select(DB::raw('count(*) as value'), 'history.user_id')
->where('history.active', 1)
->where('history.seedtime', '>=', 2_592_000 * 2)
->where('history.seedtime', '<', 2_592_000 * 3)
@@ -127,8 +125,7 @@ class AutoBonAllocation extends Command
->toArray();
$commitedSeeder = DB::table('history')
->select(DB::raw('count(DISTINCT(history.torrent_id)) as value'), 'history.user_id')
->join('torrents', 'torrents.id', 'history.torrent_id')
->select(DB::raw('count(*) as value'), 'history.user_id')
->where('history.active', 1)
->where('history.seedtime', '>=', 2_592_000 * 3)
->where('history.seedtime', '<', 2_592_000 * 6)
@@ -137,8 +134,7 @@ class AutoBonAllocation extends Command
->toArray();
$mvpSeeder = DB::table('history')
->select(DB::raw('count(DISTINCT(history.torrent_id)) as value'), 'history.user_id')
->join('torrents', 'torrents.id', 'history.torrent_id')
->select(DB::raw('count(*) as value'), 'history.user_id')
->where('history.active', 1)
->where('history.seedtime', '>=', 2_592_000 * 6)
->where('history.seedtime', '<', 2_592_000 * 12)
@@ -147,8 +143,7 @@ class AutoBonAllocation extends Command
->toArray();
$legendarySeeder = DB::table('history')
->select(DB::raw('count(DISTINCT(history.torrent_id)) as value'), 'history.user_id')
->join('torrents', 'torrents.id', 'history.torrent_id')
->select(DB::raw('count(*) as value'), 'history.user_id')
->where('history.active', 1)
->where('history.seedtime', '>=', 2_592_000 * 12)
->groupBy('history.user_id')
@@ -250,22 +245,19 @@ class AutoBonAllocation extends Command
//Move data from array to BonTransactions table
/*foreach ($array as $key => $value) {
$log = new BonTransactions();
$log->itemID = 0;
$log->bon_exchange_id = 0;
$log->name = "Seeding Award";
$log->cost = $value;
$log->receiver = $key;
$log->receiver_id = $key;
$log->comment = "Seeding Award";
$log->save();
}*/
//Move data from array to Users table
foreach ($array as $key => $value) {
$user = User::find($key);
if ($user) {
$user->seedbonus += $value;
$user->save();
}
User::whereKey($key)->update([
'seedbonus' => DB::raw('seedbonus + '.$value),
]);
}
$this->comment('Automated BON Allocation Command Complete');
+82
View File
@@ -0,0 +1,82 @@
<?php
/**
* NOTICE OF LICENSE.
*
* UNIT3D Community Edition is open-sourced software licensed under the GNU Affero General Public License v3.0
* The details is bundled with this project in the file LICENSE.txt.
*
* @project UNIT3D Community Edition
*
* @author Roardom <roardom@protonmail.com>
* @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0
*/
namespace App\Console\Commands;
use App\Models\Peer;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Redis;
use Exception;
/**
* @see \Tests\Unit\Console\Commands\AutoFlushPeersTest
*/
class AutoInsertPeers extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'auto:insert_peers';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Inserts peers in batches';
/**
* Execute the console command.
*
* @throws Exception
*/
public function handle(): void
{
/**
* MySql can handle a max of 65k placeholders per query,
* and there are 14 fields on each peer that are updated.
* (`agent`, `connectable`, `created_at`, `downloaded`, `id`, `ip`, `left`, `peer_id`, `port`, `seeder`, `torrent_id`, `updated_at`, `uploaded`, `user_id`).
*/
$peerPerCycle = intdiv(65_000, 14);
$key = config('cache.prefix').':peers:batch';
$peerCount = Redis::connection('announce')->command('LLEN', [$key]);
for ($peersLeft = $peerCount; $peersLeft > 0; $peersLeft -= $peerPerCycle) {
$peers = Redis::connection('announce')->command('LPOP', [$key, $peerPerCycle]);
$peers = array_map('unserialize', $peers);
Peer::upsert(
$peers,
['user_id', 'torrent_id', 'peer_id'],
[
'peer_id',
'ip',
'port',
'agent',
'uploaded',
'downloaded',
'left',
'seeder',
'torrent_id',
'user_id',
'connectable'
],
);
}
$this->comment('Automated insert peers command complete');
}
}
@@ -13,7 +13,7 @@
namespace App\Console\Commands;
use App\Models\Graveyard;
use App\Models\Resurrection;
use App\Models\History;
use App\Models\PrivateMessage;
use App\Models\Torrent;
@@ -25,10 +25,10 @@ use Illuminate\Support\Carbon;
/**
* @see \Tests\Unit\Console\Commands\AutoGraveyardTest
*/
class AutoGraveyard extends Command
class AutoRewardResurrection extends Command
{
/**
* AutoGraveyards Constructor.
* AutoRewardResurrection's Constructor.
*/
public function __construct(private readonly ChatRepository $chatRepository)
{
@@ -40,35 +40,35 @@ class AutoGraveyard extends Command
*
* @var string
*/
protected $signature = 'auto:graveyard';
protected $signature = 'auto:reward_resurrection';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Automatically Checks Graveyard Records For Succesful Ressurections';
protected $description = 'Automatically Hands Out Rewards For Successful Resurrections';
/**
* Execute the console command.
*/
public function handle(): void
{
foreach (Graveyard::where('rewarded', '!=', 1)->oldest()->get() as $reward) {
$user = User::find($reward->user_id);
foreach (Resurrection::where('rewarded', '!=', 1)->oldest()->get() as $resurrection) {
$user = User::find($resurrection->user_id);
$torrent = Torrent::find($reward->torrent_id);
$torrent = Torrent::find($resurrection->torrent_id);
if (isset($user, $torrent)) {
$history = History::where('torrent_id', '=', $torrent->id)
->where('user_id', '=', $user->id)
->where('seedtime', '>=', $reward->seedtime)
->where('seedtime', '>=', $resurrection->seedtime)
->first();
}
if (isset($history)) {
$reward->rewarded = 1;
$reward->save();
$resurrection->rewarded = 1;
$resurrection->save();
$user->fl_tokens += config('graveyard.reward');
$user->save();
@@ -101,6 +101,6 @@ class AutoGraveyard extends Command
}
}
$this->comment('Automated Graveyard Rewards Command Complete');
$this->comment('Automated Reward Resurrections Command Complete');
}
}
+3 -2
View File
@@ -23,12 +23,13 @@ class Kernel extends ConsoleKernel
*/
protected function schedule(Schedule $schedule): void
{
$schedule->command('auto:insert_peers')->everyMinute();
$schedule->command('auto:upsert_histories')->everyFiveSeconds();
$schedule->command('auto:update_user_last_actions')->everyFiveSeconds();
$schedule->command('auto:delete_stopped_peers')->everyTwoMinutes();
$schedule->command('auto:group ')->daily();
$schedule->command('auto:nerdstat ')->hourly();
$schedule->command('auto:graveyard')->daily();
$schedule->command('auto:reward_resurrection')->daily();
$schedule->command('auto:highspeed_tag')->hourly();
$schedule->command('auto:prewarning')->hourly();
$schedule->command('auto:warning')->daily();
@@ -53,7 +54,7 @@ class Kernel extends ConsoleKernel
$schedule->command('auto:torrent_balance')->hourly();
//$schedule->command('auto:ban_disposable_users')->weekends();
//$schedule->command('backup:clean')->daily();
//$schedule->command('backup:run')->daily();
//$schedule->command('backup:run --only-db')->daily();
}
/**
+1 -4
View File
@@ -34,7 +34,6 @@ class TorrentTools
// Whitelisted keys
$result = array_intersect_key($result, [
'announce' => '',
'comment' => '',
'created by' => '',
'encoding' => '',
@@ -46,8 +45,6 @@ class TorrentTools
'name' => '',
'piece length' => '',
'pieces' => '',
'private' => '',
'source' => '',
]);
// The PID will be set if an user downloads the torrent, but for
@@ -63,7 +60,7 @@ class TorrentTools
$result['created by'] = config('torrent.created_by', '');
}
$comment = config('torrent.comment', null);
$comment = config('torrent.comment');
if ($comment !== null) {
$result['comment'] = $comment;
+66 -3
View File
@@ -21,13 +21,16 @@ use App\Http\Resources\TorrentsResource;
use App\Models\Category;
use App\Models\FeaturedTorrent;
use App\Models\Keyword;
use App\Models\Movie;
use App\Models\Torrent;
use App\Models\TorrentFile;
use App\Models\Tv;
use App\Models\User;
use App\Repositories\ChatRepository;
use App\Services\Tmdb\TMDBScraper;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
/**
@@ -53,10 +56,40 @@ class TorrentController extends BaseController
*/
public function index(): TorrentsResource
{
return new TorrentsResource(Torrent::with(['category', 'type', 'resolution'])
$torrents = Torrent::with(['user:id,username', 'category', 'type', 'resolution', 'region', 'distributor'])
->select('*')
->selectRaw("
CASE
WHEN category_id IN (SELECT `id` from `categories` where `movie_meta` = 1) THEN 'movie'
WHEN category_id IN (SELECT `id` from `categories` where `tv_meta` = 1) THEN 'tv'
END as meta
")
->latest('sticky')
->latest('bumped_at')
->paginate(25));
->paginate(25);
$movieIds = $torrents->getCollection()->where('meta', '=', 'movie')->pluck('tmdb');
$tvIds = $torrents->getCollection()->where('meta', '=', 'tv')->pluck('tmdb');
$movies = Movie::select(['id', 'poster'])->with('genres:name')->whereIntegerInRaw('id', $movieIds)->get()->keyBy('id');
$tv = Tv::select(['id', 'poster'])->with('genres:name')->whereIntegerInRaw('id', $tvIds)->get()->keyBy('id');
$torrents = $torrents->through(function ($torrent) use ($movies, $tv) {
switch ($torrent->meta) {
case 'movie':
$torrent->setRelation('movie', $movies[$torrent->tmdb] ?? collect());
break;
case 'tv':
$torrent->setRelation('tv', $tv[$torrent->tmdb] ?? collect());
break;
}
return $torrent;
});
return new TorrentsResource($torrents);
}
/**
@@ -366,7 +399,14 @@ class TorrentController extends BaseController
$cacheKey = $url.'?'.$queryString;
$torrents = cache()->remember($cacheKey, 300, function () use ($request, $isRegex) {
return Torrent::with(['user:id,username,group_id', 'category', 'type', 'resolution'])
$torrents = Torrent::with(['user:id,username', 'category', 'type', 'resolution', 'distributor', 'region'])
->select('*')
->selectRaw("
CASE
WHEN category_id IN (SELECT `id` from `categories` where `movie_meta` = 1) THEN 'movie'
WHEN category_id IN (SELECT `id` from `categories` where `tv_meta` = 1) THEN 'tv'
END as meta
")
->when($request->filled('name'), fn ($query) => $query->ofName($request->name, $isRegex($request->name)))
->when($request->filled('description'), fn ($query) => $query->ofDescription($request->description, $isRegex($request->description)))
->when($request->filled('mediainfo'), fn ($query) => $query->ofMediainfo($request->mediainfo, $isRegex($request->mediainfo)))
@@ -401,6 +441,29 @@ class TorrentController extends BaseController
->latest('sticky')
->orderBy($request->input('sortField') ?? $this->sortField, $request->input('sortDirection') ?? $this->sortDirection)
->cursorPaginate($request->input('perPage') ?? $this->perPage);
$movieIds = $torrents->getCollection()->where('meta', '=', 'movie')->pluck('tmdb');
$tvIds = $torrents->getCollection()->where('meta', '=', 'tv')->pluck('tmdb');
$movies = Movie::select(['id', 'poster'])->with('genres:name')->whereIntegerInRaw('id', $movieIds)->get()->keyBy('id');
$tv = Tv::select(['id', 'poster'])->with('genres:name')->whereIntegerInRaw('id', $tvIds)->get()->keyBy('id');
$torrents = $torrents->through(function ($torrent) use ($movies, $tv) {
switch ($torrent->meta) {
case 'movie':
$torrent->setRelation('movie', $movies[$torrent->tmdb] ?? collect());
break;
case 'tv':
$torrent->setRelation('tv', $tv[$torrent->tmdb] ?? collect());
break;
}
return $torrent;
});
return $torrents;
});
if ($torrents !== null) {
+10 -5
View File
@@ -388,11 +388,6 @@ class AnnounceController extends Controller
$torrentId = Redis::connection('cache')->command('HGET', [$cacheKey, hex2bin($infoHash)]);
$torrent = Torrent::withoutGlobalScope(ApprovedScope::class)
->with([
'peers' => fn ($query) => $query
->select(['id', 'torrent_id', 'peer_id', 'user_id', 'left', 'seeder', 'port', 'updated_at'])
->selectRaw('INET6_NTOA(ip) as ip')
])
->select(['id', 'free', 'doubleup', 'seeders', 'leechers', 'times_completed', 'status'])
->when(
$torrentId === null,
@@ -426,6 +421,16 @@ class AnnounceController extends Controller
new TrackerException(151, [':status' => 'POSTPONED In Moderation'])
);
// Don't use eager loading so that we can make use of mysql prepared statement caching.
// If we use eager loading, then laravel will use `where torrent_id in (123)` instead of `where torrent_id = ?`
$torrent->setRelation(
'peers',
Peer::select(['id', 'torrent_id', 'peer_id', 'user_id', 'left', 'seeder', 'port', 'updated_at'])
->selectRaw('INET6_NTOA(ip) as ip')
->where('torrent_id', '=', $torrent->id)
->get()
);
return $torrent;
}
@@ -53,11 +53,11 @@ class ApprovedRequestFillController extends Controller
]);
BonTransactions::create([
'itemID' => 0,
'name' => 'request',
'cost' => $torrentRequest->bounty,
'receiver' => $torrentRequest->filled_by,
'comment' => sprintf('%s has filled %s and has been awarded %s BONUS.', $filler->username, $torrentRequest->name, $torrentRequest->bounty),
'bon_exchange_id' => 0,
'name' => 'request',
'cost' => $torrentRequest->bounty,
'receiver_id' => $torrentRequest->filled_by,
'comment' => sprintf('%s has filled %s and has been awarded %s BONUS.', $filler->username, $torrentRequest->name, $torrentRequest->bounty),
]);
$filler->increment('seedbonus', $torrentRequest->bounty);
@@ -107,11 +107,11 @@ class ApprovedRequestFillController extends Controller
$refunded = min($torrentRequest->bounty, $filler->seedbonus);
BonTransactions::create([
'itemID' => 0,
'name' => 'request',
'cost' => $refunded,
'sender' => $torrentRequest->filled_by,
'comment' => sprintf('%s has had %s unfilled and has forfeited %s BONUS.', $filler->username, $torrentRequest->name, $refunded),
'bon_exchange_id' => 0,
'name' => 'request',
'cost' => $refunded,
'sender_id' => $torrentRequest->filled_by,
'comment' => sprintf('%s has had %s unfilled and has forfeited %s BONUS.', $filler->username, $torrentRequest->name, $refunded),
]);
$filler->decrement('seedbonus', $refunded);
+5 -5
View File
@@ -50,11 +50,11 @@ class BountyController extends Controller
$torrentRequest->save();
BonTransactions::create([
'itemID' => 0,
'name' => 'request',
'cost' => $request->float('seedbonus'),
'sender' => $user->id,
'comment' => sprintf('adding bonus to %s', $torrentRequest->name),
'bon_exchange_id' => 0,
'name' => 'request',
'cost' => $request->float('seedbonus'),
'sender_id' => $user->id,
'comment' => sprintf('adding bonus to %s', $torrentRequest->name),
]);
$user->decrement('seedbonus', $request->float('seedbonus'));
@@ -14,7 +14,6 @@
namespace App\Http\Controllers\MediaHub;
use App\Http\Controllers\Controller;
use App\Models\Category;
use App\Models\Person;
class PersonController extends Controller
@@ -33,14 +32,7 @@ class PersonController extends Controller
public function show(int $id): \Illuminate\Contracts\View\Factory|\Illuminate\View\View
{
return view('mediahub.person.show', [
'person' => Person::with([
'tv' => fn ($query) => $query->has('torrents'),
'tv.genres',
'movie' => fn ($query) => $query->has('torrents'),
'movie.genres'
])->findOrFail($id),
'movieCategoryIds' => Category::where('movie_meta', '=', 1)->pluck('id')->toArray(),
'tvCategoryIds' => Category::where('tv_meta', '=', 1)->pluck('id')->toArray()
'person' => Person::findOrFail($id),
]);
}
}
+5 -5
View File
@@ -138,11 +138,11 @@ class RequestController extends Controller
]);
BonTransactions::create([
'itemID' => 0,
'name' => 'request',
'cost' => $request->bounty,
'sender' => $user->id,
'comment' => sprintf('new request - %s', $request->name),
'bon_exchange_id' => 0,
'name' => 'request',
'cost' => $request->bounty,
'sender_id' => $user->id,
'comment' => sprintf('new request - %s', $request->name),
]);
$user->decrement('seedbonus', $request->bounty);
@@ -62,9 +62,7 @@ class RequestFillController extends Controller
*/
public function destroy(Request $request, TorrentRequest $torrentRequest): \Illuminate\Http\RedirectResponse
{
$user = $request->user();
abort_unless($request->user()->group->is_modo, 403);
abort_unless($request->user()->id === $torrentRequest->user_id || $request->user()->group->is_modo, 403);
$torrentRequest->update([
'filled_by' => null,
@@ -72,10 +70,11 @@ class RequestFillController extends Controller
'torrent_id' => null,
]);
$sender = $torrentRequest->filled_anon ? 'Anonymous' : $torrentRequest->user()->username;
$filler = $torrentRequest->user;
if ($filler->acceptsNotification($request->user(), $filler, 'request', 'show_request_fill_reject')) {
$filler->notify(new NewRequestFillReject('torrent', $user->username, $torrentRequest));
$filler->notify(new NewRequestFillReject('torrent', $sender, $torrentRequest));
}
return to_route('requests.show', ['torrentRequest' => $torrentRequest])
+18
View File
@@ -385,4 +385,22 @@ class TopicController extends Controller
])
->withFragment('post-'.$postId);
}
/**
* Redirect to the appropriate topic page for the latest post.
*/
public function latestPermalink(int $id): \Illuminate\Http\RedirectResponse
{
$post = Post::query()
->selectRaw('MAX(id) as id')
->selectRaw('count(*) as post_count')
->where('topic_id', '=', $id)
->first();
return to_route('topics.show', [
'id' => $id,
'page' => intdiv($post?->post_count === null ? 0 : $post->post_count - 1, 25) + 1
])
->withFragment('post-'.($post?->id ?? 0));
}
}
+1 -1
View File
@@ -137,7 +137,7 @@ class TorrentController extends Controller
'trailer' => $trailer,
'platforms' => $platforms,
'total_tips' => BonTransactions::where('torrent_id', '=', $id)->sum('cost'),
'user_tips' => BonTransactions::where('torrent_id', '=', $id)->where('sender', '=', $user->id)->sum('cost'),
'user_tips' => BonTransactions::where('torrent_id', '=', $id)->where('sender_id', '=', $user->id)->sum('cost'),
'featured' => $torrent->featured == 1 ? FeaturedTorrent::where('torrent_id', '=', $id)->first() : null,
'mediaInfo' => $torrent->mediainfo !== null ? (new MediaInfo())->parse($torrent->mediainfo) : null,
'last_seed_activity' => History::where('torrent_id', '=', $torrent->id)->where('seeder', '=', 1)->latest('updated_at')->first(),
+10 -10
View File
@@ -40,10 +40,10 @@ class GiftController extends Controller
return view('user.gift.index', [
'user' => $user,
'gifts' => BonTransactions::query()
->with(['senderObj.group', 'receiverObj.group'])
->where(fn ($query) => $query->where('sender', '=', $user->id)->orwhere('receiver', '=', $user->id))
->with(['sender.group', 'receiver.group'])
->where(fn ($query) => $query->where('sender_id', '=', $user->id)->orwhere('receiver_id', '=', $user->id))
->where('name', '=', 'gift')
->latest('date_actioned')
->latest()
->paginate(25),
'bon' => $user->getSeedbonus(),
'sentGifts' => $user->sentGifts()->sum('cost'),
@@ -76,13 +76,13 @@ class GiftController extends Controller
$sender->decrement('seedbonus', $request->cost);
$bonTransactions = BonTransactions::create([
'itemID' => 0,
'name' => 'gift',
'cost' => $request->cost,
'sender' => $sender->id,
'receiver' => $receiver->id,
'comment' => $request->comment,
'torrent_id' => null,
'bon_exchange_id' => 0,
'name' => 'gift',
'cost' => $request->cost,
'sender_id' => $sender->id,
'receiver_id' => $receiver->id,
'comment' => $request->comment,
'torrent_id' => null,
]);
if ($receiver->acceptsNotification($sender, $receiver, 'bon', 'show_bon_gift')) {
@@ -14,7 +14,7 @@
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Models\Graveyard;
use App\Models\Resurrection;
use App\Models\History;
use App\Models\Torrent;
use App\Models\User;
@@ -56,16 +56,16 @@ class ResurrectionController extends Controller
->withErrors('This torrent is not older than 30 days.');
}
$isPending = Graveyard::whereBelongsTo($torrent)->where('rewarded', '=', 0)->exists();
$isPending = Resurrection::whereBelongsTo($torrent)->where('rewarded', '=', 0)->exists();
if ($isPending) {
return to_route('torrents.show', ['id' => $torrent->id])
->withErrors(trans('graveyard.resurrect-failed-pending'));
}
$history = History::whereBelongsTo($torrent)->whereBelongsTo($user)->sole();
$history = History::whereBelongsTo($torrent)->whereBelongsTo($user)->first();
Graveyard::create([
Resurrection::create([
'user_id' => $user->id,
'torrent_id' => $torrent->id,
'seedtime' => config('graveyard.time') + $history?->seedtime ?? 0,
@@ -78,7 +78,7 @@ class ResurrectionController extends Controller
/**
* Cancel A Ressurection.
*/
public function destroy(Request $request, User $user, Graveyard $resurrection): \Illuminate\Http\RedirectResponse
public function destroy(Request $request, User $user, Resurrection $resurrection): \Illuminate\Http\RedirectResponse
{
abort_unless($request->user()->group->is_modo || $request->user()->is($user), 403);
+11 -11
View File
@@ -38,10 +38,10 @@ class TipController extends Controller
return view('user.tip.index', [
'user' => $user,
'tips' => BonTransactions::with(['senderObj.group', 'receiverObj.group', 'torrent'])
->where(fn ($query) => $query->where('sender', '=', $user->id)->orwhere('receiver', '=', $user->id))
'tips' => BonTransactions::with(['sender.group', 'receiver.group', 'torrent'])
->where(fn ($query) => $query->where('sender_id', '=', $user->id)->orwhere('receiver_id', '=', $user->id))
->where('name', '=', 'tip')
->latest('date_actioned')
->latest()
->paginate(25),
'bon' => $user->getSeedbonus(),
'sentTips' => $user->sentTips()->sum('cost'),
@@ -70,14 +70,14 @@ class TipController extends Controller
$user->decrement('seedbonus', $tipAmount);
BonTransactions::create([
'itemID' => 0,
'name' => 'tip',
'cost' => $tipAmount,
'sender' => $user->id,
'receiver' => $recipient->id,
'comment' => 'tip',
'post_id' => $request->has('post') ? $tipable->id : null,
'torrent_id' => $request->has('torrent') ? $tipable->id : null,
'bon_exchange_id' => 0,
'name' => 'tip',
'cost' => $tipAmount,
'sender_id' => $user->id,
'receiver_id' => $recipient->id,
'comment' => 'tip',
'post_id' => $request->has('post') ? $tipable->id : null,
'torrent_id' => $request->has('torrent') ? $tipable->id : null,
]);
if ($request->has('torrent')) {
@@ -23,6 +23,7 @@ use App\Models\User;
use App\Services\Unit3dAnnounce;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
/**
* @see \Tests\Feature\Http\Controllers\BonusControllerTest
@@ -59,51 +60,70 @@ class TransactionController extends Controller
abort_unless($request->user()->is($user), 403);
$request = (object) $request->validated();
$item = BonExchange::findOrFail($request->exchange);
switch (true) {
case $item->upload:
$user->increment('uploaded', $item->value);
return DB::transaction(function () use ($request, $user) {
$user->refresh();
$bonExchange = BonExchange::findOrFail($request->exchange);
break;
case $item->download:
$user->decrement('downloaded', $item->value);
if ($bonExchange->cost > $user->seedbonus) {
return back()->withErrors('Not enough BON.');
}
break;
case $item->personal_freeleech:
PersonalFreeleech::create(['user_id' => $user->id]);
switch (true) {
case $bonExchange->upload:
$user->increment('uploaded', $bonExchange->value);
cache()->put('personal_freeleech:'.$user->id, true);
break;
case $bonExchange->download:
if ($user->downloaded < $bonExchange->value) {
return back()->withErrors('Not enough download.');
}
Unit3dAnnounce::addPersonalFreeleech($user->id);
$user->decrement('downloaded', $bonExchange->value);
PrivateMessage::create([
'sender_id' => 1,
'receiver_id' => $user->id,
'subject' => trans('bon.pm-subject'),
'message' => sprintf(trans('bon.pm-message'), Carbon::now()->addDays(1)->toDayDateTimeString()).config('app.timezone').'[/b]!
break;
case $bonExchange->personal_freeleech:
if (cache()->get('personal_freeleech:'.$user->id)) {
return back()->withErrors('Your previous personal freeleech is still active.');
}
PersonalFreeleech::create(['user_id' => $user->id]);
cache()->put('personal_freeleech:'.$user->id, true);
Unit3dAnnounce::addPersonalFreeleech($user->id);
PrivateMessage::create([
'sender_id' => 1,
'receiver_id' => $user->id,
'subject' => trans('bon.pm-subject'),
'message' => sprintf(trans('bon.pm-message'), Carbon::now()->addDays(1)->toDayDateTimeString()).config('app.timezone').'[/b]!
[color=red][b]'.trans('common.system-message').'[/b][/color]',
]);
]);
break;
case $item->invite:
$user->increment('invites', $item->value);
break;
case $bonExchange->invite:
if ($user->invites >= config('other.max_unused_user_invites', 1)) {
return back()->withErrors('You already have the maximum amount of unused invites allowed per user.');
}
break;
}
$user->increment('invites', $bonExchange->value);
BonTransactions::create([
'itemID' => $item->id,
'name' => $item->description,
'cost' => $item->value,
'sender' => $user->id,
'comment' => $item->description,
'torrent_id' => null,
]);
break;
}
$user->decrement('seedbonus', $item->cost);
BonTransactions::create([
'bon_exchange_id' => $bonExchange->id,
'name' => $bonExchange->description,
'cost' => $bonExchange->value,
'sender_id' => $user->id,
'comment' => $bonExchange->description,
'torrent_id' => null,
]);
return to_route('users.transactions.create', ['user' => $user])
->withSuccess(trans('bon.success'));
$user->decrement('seedbonus', $bonExchange->cost);
return back()->withSuccess(trans('bon.success'));
}, 5);
}
}
+2 -2
View File
@@ -81,8 +81,8 @@ class UserController extends Controller
->with(['torrenttitle', 'warneduser'])
->latest('created_at')
->paginate(10, ['*'], 'deletedWarningsPage'),
'boughtUpload' => BonTransactions::where('sender', '=', $user->id)->where([['name', 'like', '%Upload%']])->sum('cost'),
// 'boughtDownload' => BonTransactions::where('sender', '=', $user->id)->where([['name', 'like', '%Download%']])->sum('cost'),
'boughtUpload' => BonTransactions::where('sender_id', '=', $user->id)->where([['name', 'like', '%Upload%']])->sum('cost'),
// 'boughtDownload' => BonTransactions::where('sender_id', '=', $user->id)->where([['name', 'like', '%Download%']])->sum('cost'),
'invitedBy' => Invite::where('accepted_by', '=', $user->id)->first(),
'clients' => $user->peers()
->select('agent', 'port')
+1 -1
View File
@@ -35,7 +35,7 @@ class BbcodeInput extends Component
$this->name = $name;
$this->label = $label;
$this->isRequired = $required;
$this->contentBbcode = $content ?? old($name) ?? '';
$this->contentBbcode = $content === null ? (old($name) ?? '') : htmlspecialchars_decode($content);
}
final public function updatedIsPreviewEnabled(): void
+33 -27
View File
@@ -24,21 +24,25 @@ class PersonCredit extends Component
{
public Person $person;
public ?Occupations $occupation = null;
public ?int $occupationId = null;
public $queryString = [
'occupationId',
];
final public function mount(): void
{
$this->occupation = match (true) {
0 < $this->createdCount => Occupations::CREATOR,
0 < $this->directedCount => Occupations::DIRECTOR,
0 < $this->writtenCount => Occupations::WRITER,
0 < $this->producedCount => Occupations::PRODUCER,
0 < $this->composedCount => Occupations::COMPOSER,
0 < $this->cinematographedCount => Occupations::CINEMATOGRAPHER,
0 < $this->editedCount => Occupations::EDITOR,
0 < $this->productionDesignedCount => Occupations::PRODUCTION_DESIGNER,
0 < $this->artDirectedCount => Occupations::ART_DIRECTOR,
0 < $this->actedCount => Occupations::ACTOR,
$this->occupationId ??= match (true) {
0 < $this->createdCount => Occupations::CREATOR->value,
0 < $this->directedCount => Occupations::DIRECTOR->value,
0 < $this->writtenCount => Occupations::WRITER->value,
0 < $this->producedCount => Occupations::PRODUCER->value,
0 < $this->composedCount => Occupations::COMPOSER->value,
0 < $this->cinematographedCount => Occupations::CINEMATOGRAPHER->value,
0 < $this->editedCount => Occupations::EDITOR->value,
0 < $this->productionDesignedCount => Occupations::PRODUCTION_DESIGNER->value,
0 < $this->artDirectedCount => Occupations::ART_DIRECTOR->value,
0 < $this->actedCount => Occupations::ACTOR->value,
default => null,
};
}
@@ -108,24 +112,22 @@ class PersonCredit extends Component
final public function getMediasProperty(): \Illuminate\Support\Collection
{
if ($this->occupation === null) {
if ($this->occupationId === null) {
return collect();
}
$movies = $this->person
->movie()
->whereHas('torrents')
->with('genres', 'directors')
->wherePivot('occupation_id', '=', $this->occupation)
->wherePivot('occupation_id', '=', $this->occupationId)
->orderBy('release_date')
->get()
// Since the credits table unique index has nullable columns, we get duplicate credits, which means duplicate movies
->unique();
$tv = $this->person
->tv()
->whereHas('torrents')
->with('genres', 'creators')
->wherePivot('occupation_id', '=', $this->occupation)
->wherePivot('occupation_id', '=', $this->occupationId)
->orderBy('first_air_date')
->get()
// Since the credits table unique index has nullable columns, we get duplicate credits, which means duplicate tv
@@ -302,19 +304,23 @@ class PersonCredit extends Component
$medias = collect();
foreach ($movies as $movie) {
$media = $movie;
$media->meta = 'movie';
$media->torrents = $torrents['movie'][$movie->id];
$media->category_id = $media->torrents->pop();
$medias->add($media);
if ($torrents->has('movie') && $torrents['movie']->has($movie->id)) {
$media = $movie;
$media->meta = 'movie';
$media->torrents = $torrents['movie'][$movie->id];
$media->category_id = $media->torrents->pop();
$medias->add($media);
}
}
foreach ($tv as $show) {
$media = $show;
$media->meta = 'tv';
$media->torrents = $torrents['tv'][$show->id];
$media->category_id = $media->torrents->pop();
$medias->add($media);
if ($torrents->has('tv') && $torrents['tv']->has($show->id)) {
$media = $show;
$media->meta = 'tv';
$media->torrents = $torrents['tv'][$show->id];
$media->category_id = $media->torrents->pop();
$medias->add($media);
}
}
return $medias;
+20 -2
View File
@@ -22,7 +22,16 @@ class QuickSearchDropdown extends Component
'movies' => Movie::query()
->select(['id', 'poster', 'title', 'release_date'])
->selectRaw("concat(title, ' ', release_date) as title_and_year")
->having('title_and_year', 'LIKE', $search)
->when(
preg_match('/^\d+$/', $this->quicksearchText),
fn ($query) => $query->where('id', '=', $this->quicksearchText),
fn ($query) => $query
->when(
preg_match('/tt0*(?=(\d{7,}))/', $this->quicksearchText, $matches),
fn ($query) => $query->where('imdb_id', '=', $matches[1]),
fn ($query) => $query->having('title_and_year', 'LIKE', $search),
)
)
->has('torrents')
->oldest('title')
->take(10)
@@ -30,7 +39,16 @@ class QuickSearchDropdown extends Component
'series' => Tv::query()
->select(['id', 'poster', 'name', 'first_air_date'])
->selectRaw("concat(name, ' ', first_air_date) as title_and_year")
->having('title_and_year', 'LIKE', $search)
->when(
preg_match('/^\d+$/', $this->quicksearchText),
fn ($query) => $query->where('id', '=', $this->quicksearchText),
fn ($query) => $query
->when(
preg_match('/tt0*(?=(\d{7,}))/', $this->quicksearchText, $matches),
fn ($query) => $query->where('imdb_id', '=', $matches[1]),
fn ($query) => $query->having('title_and_year', 'LIKE', $search),
)
)
->has('torrents')
->oldest('name')
->take(10)
+12
View File
@@ -15,6 +15,7 @@ namespace App\Http\Livewire;
use App\Models\Subtitle;
use App\Models\Torrent;
use App\Models\User;
use Livewire\Component;
use Livewire\WithPagination;
@@ -30,6 +31,8 @@ class SubtitleSearch extends Component
public string $language = '';
public string $username = '';
public string $sortField = 'created_at';
public string $sortDirection = 'desc';
@@ -54,6 +57,15 @@ class SubtitleSearch extends Component
return $query->whereIntegerInRaw('torrent_id', $torrents);
})
->when($this->language, fn ($query) => $query->where('language_id', '=', $this->language))
->when(
$this->username,
fn ($query) => $query
->whereIn('user_id', User::select('id')->where('username', '=', $this->username))
->when(
! auth()->user()->group->is_modo,
fn ($query) => $query->where(fn ($query) => $query->where('anon', '=', false)->orWhere('user_id', '=', auth()->id()))
)
)
->orderBy($this->sortField, $this->sortDirection)
->paginate($this->perPage);
}
+10 -10
View File
@@ -13,7 +13,7 @@
namespace App\Http\Livewire;
use App\Models\Graveyard;
use App\Models\Resurrection;
use App\Models\User;
use Livewire\Component;
use Livewire\WithPagination;
@@ -59,23 +59,23 @@ class UserResurrections extends Component
final public function getResurrectionsProperty(): \Illuminate\Contracts\Pagination\LengthAwarePaginator
{
return Graveyard::query()
return Resurrection::query()
->select([
'graveyard.id',
'graveyard.created_at',
'graveyard.seedtime',
'graveyard.rewarded',
'graveyard.torrent_id'
'resurrections.id',
'resurrections.created_at',
'resurrections.seedtime',
'resurrections.rewarded',
'resurrections.torrent_id'
])
->with(['torrent', 'user'])
->leftJoin('torrents', 'torrents.id', '=', 'graveyard.torrent_id')
->where('graveyard.user_id', '=', $this->user->id)
->leftJoin('torrents', 'torrents.id', '=', 'resurrections.torrent_id')
->where('resurrections.user_id', '=', $this->user->id)
->when($this->rewarded === 'include', fn ($query) => $query->where('rewarded', '=', 1))
->when($this->rewarded === 'exclude', fn ($query) => $query->where('rewarded', '=', 0))
->when($this->name, fn ($query) => $query->where('name', 'like', '%'.str_replace(' ', '%', $this->name).'%'))
->when(
\in_array($this->sortField, ['created_at', 'seedtime', 'rewarded']),
fn ($query) => $query->orderBy('graveyard.'.$this->sortField, $this->sortDirection),
fn ($query) => $query->orderBy('resurrections.'.$this->sortField, $this->sortDirection),
fn ($query) => $query->orderBy('torrents.'.$this->sortField, $this->sortDirection)
)
->paginate($this->perPage);
+14 -1
View File
@@ -44,8 +44,11 @@ class StoreTorrentRequest extends FormRequest
'torrent' => [
'required',
'file',
'mimes:torrent',
function (string $attribute, mixed $value, Closure $fail): void {
if ($value->getClientOriginalExtension() !== 'torrent') {
$fail('The torrent file uploaded does not have a ".torrent" file extension (it has "'.$value->getClientOriginalExtension().'"). Did you upload the correct file?');
}
$decodedTorrent = TorrentTools::normalizeTorrent($value);
$v2 = Bencode::is_v2_or_hybrid($decodedTorrent);
@@ -79,6 +82,16 @@ class StoreTorrentRequest extends FormRequest
}
}
],
'nfo' => [
'nullable',
'sometimes',
'file',
function (string $attribute, mixed $value, Closure $fail): void {
if ($value->getClientOriginalExtension() !== 'nfo') {
$fail('The NFO uploaded does not have a ".nfo" file extension (it has "'.$value->getClientOriginalExtension().'"). Did you upload the correct file?');
}
},
],
'name' => [
'required',
'unique:torrents',
@@ -13,7 +13,6 @@
namespace App\Http\Requests;
use App\Models\BonExchange;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Request;
@@ -37,32 +36,8 @@ class StoreTransactionRequest extends FormRequest
{
return [
'exchange' => [
'bail',
'required',
'exists:bon_exchange,id',
function ($attribute, $value, $fail) use ($request): void {
$user = $request->user();
$item = BonExchange::findOrFail($value);
switch (true) {
case $item->cost > $user->seedbonus:
$fail('Not enough BON.');
break;
case $item->download && $user->downloaded < $item->value:
$fail('Not enough download.');
break;
case $item->personal_freeleech && cache()->get('personal_freeleech:'.$user->id):
$fail('Your previous personal freeleech is still active.');
break;
case $item->invite && $user->invites >= config('other.max_unused_user_invites', 1):
$fail('You already have the maximum amount of unused invites allowed per user.');
break;
}
},
],
];
}
+1 -11
View File
@@ -13,8 +13,6 @@
namespace App\Http\Resources;
use App\Models\Movie;
use App\Models\Tv;
use Illuminate\Http\Resources\Json\JsonResource;
class TorrentResource extends JsonResource
@@ -24,15 +22,7 @@ class TorrentResource extends JsonResource
*/
public function toArray($request): array
{
$meta = null;
if ($this->category->tv_meta && ($this->tmdb !== 0)) {
$meta = Tv::with(['genres:name'])->find($this->tmdb);
}
if ($this->category->movie_meta && ($this->tmdb !== 0)) {
$meta = Movie::with(['genres:name'])->find($this->tmdb);
}
$meta = $this->movie ?? $this->tv;
return [
'type' => 'torrent',
+17
View File
@@ -163,6 +163,23 @@ class ProcessAnnounce implements ShouldQueue
$peer->updateConnectableStateIfNeeded();
$peer->updated_at = now();
Redis::connection('announce')->command('LPUSH', [
config('cache.prefix').':peers:batch',
serialize($peer->only([
'peer_id',
'ip',
'port',
'agent',
'uploaded',
'downloaded',
'left',
'seeder',
'torrent_id',
'user_id',
'connectable'
]))
]);
$history->agent = $this->queries['user-agent'];
$history->seeder = (int) ($this->queries['left'] == 0);
$history->client_uploaded = $realUploaded;
+5 -7
View File
@@ -44,10 +44,9 @@ class BonTransactions extends Model
/**
* Belongs To A Sender.
*/
// Bad name to not conflict with sender (not sender_id)
public function senderObj(): \Illuminate\Database\Eloquent\Relations\BelongsTo
public function sender(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(User::class, 'sender', 'id')->withDefault([
return $this->belongsTo(User::class)->withDefault([
'username' => 'System',
'id' => '1',
]);
@@ -56,10 +55,9 @@ class BonTransactions extends Model
/**
* Belongs To A Receiver.
*/
// Bad name to not conflict with sender (not sender_id)
public function receiverObj(): \Illuminate\Database\Eloquent\Relations\BelongsTo
public function receiver(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(User::class, 'receiver', 'id')->withDefault([
return $this->belongsTo(User::class)->withDefault([
'username' => 'System',
'id' => '1',
]);
@@ -70,7 +68,7 @@ class BonTransactions extends Model
*/
public function exchange(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(BonExchange::class, 'itemID', 'id')->withDefault([
return $this->belongsTo(BonExchange::class)->withDefault([
'value' => 0,
'cost' => 0,
]);
-2
View File
@@ -32,7 +32,6 @@ class BotTransaction extends Model
/**
* Belongs To A User.
*/
// Bad name to not conflict with sender (not sender_id)
public function user(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(User::class)->withDefault([
@@ -44,7 +43,6 @@ class BotTransaction extends Model
/**
* Belongs To A Bot.
*/
// Bad name to not conflict with sender (not sender_id)
public function bot(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(Bot::class)->withDefault([
+9
View File
@@ -13,6 +13,7 @@
namespace App\Models;
use DateTimeInterface;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Redis;
@@ -22,6 +23,14 @@ class Peer extends Model
{
use HasFactory;
/**
* Prepare a date for array / JSON serialization.
*/
protected function serializeDate(DateTimeInterface $date): string
{
return $date->format('Y-m-d H:i:s');
}
/**
* Belongs To A User.
*/
+1 -1
View File
@@ -66,6 +66,6 @@ class Playlist extends Model
{
$bbcode = new Bbcode();
return (new Linkify())->linky($bbcode->parse(htmlspecialchars_decode($this->description)));
return (new Linkify())->linky($bbcode->parse($this->description));
}
}
+1 -1
View File
@@ -105,7 +105,7 @@ class Post extends Model
{
$bbcode = new Bbcode();
return (new Linkify())->linky($bbcode->parse(htmlspecialchars_decode($this->content)));
return (new Linkify())->linky($bbcode->parse($this->content));
}
/**
@@ -17,7 +17,7 @@ use App\Traits\Auditable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Graveyard extends Model
class Resurrection extends Model
{
use Auditable;
use HasFactory;
@@ -27,8 +27,6 @@ class Graveyard extends Model
*
* @var string
*/
protected $table = 'graveyard';
protected $guarded = [];
/**
+1 -9
View File
@@ -128,14 +128,6 @@ class Torrent extends Model
return $this->belongsToMany(Playlist::class, 'playlist_torrents')->using(PlaylistTorrent::class)->withPivot('id');
}
/**
* Has Many Genres.
*/
public function genres(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
{
return $this->belongsToMany(Genre::class, 'genre_torrent', 'torrent_id', 'genre_id', 'id', 'id');
}
/**
* Torrent Has Been Moderated By.
*/
@@ -253,7 +245,7 @@ class Torrent extends Model
*/
public function resurrections(): \Illuminate\Database\Eloquent\Relations\HasMany
{
return $this->hasMany(Graveyard::class);
return $this->hasMany(Resurrection::class);
}
/**
+14 -6
View File
@@ -491,7 +491,7 @@ class User extends Authenticatable
*/
public function bonGiven(): \Illuminate\Database\Eloquent\Relations\HasMany
{
return $this->hasMany(BonTransactions::class, 'sender');
return $this->hasMany(BonTransactions::class, 'sender_id');
}
/**
@@ -499,7 +499,7 @@ class User extends Authenticatable
*/
public function bonReceived(): \Illuminate\Database\Eloquent\Relations\HasMany
{
return $this->hasMany(BonTransactions::class, 'receiver');
return $this->hasMany(BonTransactions::class, 'receiver_id');
}
/**
@@ -510,6 +510,14 @@ class User extends Authenticatable
return $this->hasMany(Subscription::class);
}
/**
* Has Many Resurrections.
*/
public function resurrections(): \Illuminate\Database\Eloquent\Relations\HasMany
{
return $this->hasMany(Resurrection::class);
}
/**
* Has Many Subscribed topics.
*/
@@ -579,7 +587,7 @@ class User extends Authenticatable
*/
public function sentGifts(): \Illuminate\Database\Eloquent\Relations\HasMany
{
return $this->hasMany(BonTransactions::class, 'sender')->where('name', '=', 'gift');
return $this->hasMany(BonTransactions::class, 'sender_id')->where('name', '=', 'gift');
}
/**
@@ -587,7 +595,7 @@ class User extends Authenticatable
*/
public function receivedGifts(): \Illuminate\Database\Eloquent\Relations\HasMany
{
return $this->hasMany(BonTransactions::class, 'receiver')->where('name', '=', 'gift');
return $this->hasMany(BonTransactions::class, 'receiver_id')->where('name', '=', 'gift');
}
/**
@@ -595,7 +603,7 @@ class User extends Authenticatable
*/
public function sentTips(): \Illuminate\Database\Eloquent\Relations\HasMany
{
return $this->hasMany(BonTransactions::class, 'sender')->where('name', '=', 'tip');
return $this->hasMany(BonTransactions::class, 'sender_id')->where('name', '=', 'tip');
}
/**
@@ -603,7 +611,7 @@ class User extends Authenticatable
*/
public function receivedTips(): \Illuminate\Database\Eloquent\Relations\HasMany
{
return $this->hasMany(BonTransactions::class, 'receiver')->where('name', '=', 'tip');
return $this->hasMany(BonTransactions::class, 'receiver_id')->where('name', '=', 'tip');
}
/**
+1 -1
View File
@@ -45,7 +45,7 @@ class NewBon extends Notification implements ShouldQueue
return [
'title' => $this->sender.' Has Gifted You '.$this->bonTransactions->cost.' BON',
'body' => $this->sender.' has gifted you '.$this->bonTransactions->cost.' BON with the following note: '.$this->bonTransactions->comment,
'url' => sprintf('/users/%s', $this->bonTransactions->senderObj->username),
'url' => sprintf('/users/%s', $this->bonTransactions->sender->username),
];
}
}
+10 -10
View File
@@ -16,16 +16,16 @@ class BonTransactionsFactory extends Factory
public function definition(): array
{
return [
'itemID' => fn () => BonExchange::factory()->create()->id,
'name' => $this->faker->name(),
'cost' => $this->faker->randomFloat(),
'sender' => fn () => User::factory()->create()->id,
'receiver' => fn () => User::factory()->create()->id,
'torrent_id' => $this->faker->randomNumber(),
'donation_id' => $this->faker->randomNumber(),
'post_id' => $this->faker->randomNumber(),
'comment' => $this->faker->text(),
'date_actioned' => $this->faker->dateTime(),
'bon_exchange_id' => fn () => BonExchange::factory()->create()->id,
'name' => $this->faker->name(),
'cost' => $this->faker->randomFloat(),
'sender_id' => fn () => User::factory()->create()->id,
'receiver_id' => fn () => User::factory()->create()->id,
'torrent_id' => $this->faker->randomNumber(),
'donation_id' => $this->faker->randomNumber(),
'post_id' => $this->faker->randomNumber(),
'comment' => $this->faker->text(),
'created_at' => $this->faker->dateTime(),
];
}
}
@@ -8,7 +8,7 @@ use App\Models\Torrent;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class GraveyardFactory extends Factory
class ResurrectionFactory extends Factory
{
/**
* Define the model's default state.
@@ -0,0 +1,110 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class () extends Migration {
public function up(): void
{
DB::table('recommendations')
->whereNotIn('movie_id', DB::table('movie')->select('id'))
->orWhereNotIn('recommendation_movie_id', DB::table('movie')->select('id'))
->delete();
DB::table('recommendations')
->whereNotIn('tv_id', DB::table('tv')->select('id'))
->orWhereNotIn('recommendation_tv_id', DB::table('tv')->select('id'))
->delete();
DB::table('seasons')->whereNotIn('tv_id', DB::table('tv')->select('id'))->delete();
DB::table('episodes')->whereNotIn('tv_id', DB::table('tv')->select('id'))->delete();
DB::table('company_movie')->whereNotIn('movie_id', DB::table('movie')->select('id'))->delete();
DB::table('company_tv')->whereNotIn('tv_id', DB::table('tv')->select('id'))->delete();
DB::table('collection_movie')->whereNotIn('movie_id', DB::table('movie')->select('id'))->delete();
DB::table('network_tv')->whereNotIn('tv_id', DB::table('tv')->select('id'))->delete();
DB::table('genre_movie')->whereNotIn('movie_id', DB::table('movie')->select('id'))->delete();
DB::table('genre_tv')->whereNotIn('tv_id', DB::table('tv')->select('id'))->delete();
Schema::table('recommendations', function (Blueprint $table): void {
$table->dropForeign(['movie_id']);
$table->dropForeign(['recommendation_movie_id']);
$table->dropForeign(['tv_id']);
$table->dropForeign(['recommendation_tv_id']);
});
Schema::table('credits', function (Blueprint $table): void {
$table->dropForeign(['movie_id']);
$table->dropForeign(['tv_id']);
});
Schema::table('movie', function (Blueprint $table): void {
$table->increments('id')->change();
});
Schema::table('tv', function (Blueprint $table): void {
$table->increments('id')->change();
});
Schema::table('recommendations', function (Blueprint $table): void {
$table->unsignedInteger('movie_id')->change();
$table->foreign('movie_id')->references('id')->on('movie')->cascadeOnUpdate()->cascadeOnDelete();
$table->unsignedInteger('recommendation_movie_id')->change();
$table->foreign('recommendation_movie_id')->references('id')->on('movie')->cascadeOnUpdate()->cascadeOnDelete();
$table->unsignedInteger('tv_id')->change();
$table->foreign('tv_id')->references('id')->on('tv')->cascadeOnUpdate()->cascadeOnDelete();
$table->unsignedInteger('recommendation_tv_id')->change();
$table->foreign('recommendation_tv_id')->references('id')->on('tv')->cascadeOnUpdate()->cascadeOnDelete();
});
Schema::table('credits', function (Blueprint $table): void {
$table->unsignedInteger('movie_id')->nullable()->change();
$table->foreign('movie_id')->references('id')->on('movie')->cascadeOnUpdate()->cascadeOnDelete();
$table->unsignedInteger('tv_id')->nullable()->change();
$table->foreign('tv_id')->references('id')->on('tv')->cascadeOnUpdate()->cascadeOnDelete();
});
Schema::table('seasons', function (Blueprint $table): void {
$table->increments('id')->change();
$table->unsignedInteger('tv_id')->change();
$table->foreign('tv_id')->references('id')->on('tv')->cascadeOnUpdate();
});
Schema::table('episodes', function (Blueprint $table): void {
$table->increments('id')->change();
$table->unsignedInteger('tv_id')->change();
$table->foreign('tv_id')->references('id')->on('tv')->cascadeOnUpdate();
$table->unsignedInteger('season_id')->change();
$table->foreign('season_id')->references('id')->on('seasons')->cascadeOnUpdate();
});
Schema::table('company_movie', function (Blueprint $table): void {
$table->foreign('movie_id')->references('id')->on('movie')->cascadeOnUpdate()->cascadeOnDelete();
});
Schema::table('company_tv', function (Blueprint $table): void {
$table->foreign('tv_id')->references('id')->on('tv')->cascadeOnUpdate()->cascadeOnDelete();
});
Schema::table('collection_movie', function (Blueprint $table): void {
$table->foreign('movie_id')->references('id')->on('movie')->cascadeOnUpdate()->cascadeOnDelete();
});
Schema::table('network_tv', function (Blueprint $table): void {
$table->foreign('tv_id')->references('id')->on('tv')->cascadeOnUpdate()->cascadeOnDelete();
});
Schema::table('genre_movie', function (Blueprint $table): void {
$table->foreign('movie_id')->references('id')->on('movie')->cascadeOnUpdate()->cascadeOnDelete();
});
Schema::table('genre_tv', function (Blueprint $table): void {
$table->foreign('tv_id')->references('id')->on('tv')->cascadeOnUpdate()->cascadeOnDelete();
});
}
};
@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
return new class () extends Migration {
public function up(): void
{
DB::table('posts')
->lazyById()
->each(function (object $post): void {
DB::table('posts')
->where('id', '=', $post->id)
->update([
'content' => htmlspecialchars_decode($post->content),
]);
});
DB::table('playlists')
->lazyById()
->each(function (object $playlist): void {
DB::table('playlists')
->where('id', '=', $playlist->id)
->update([
'description' => htmlspecialchars_decode($playlist->description),
]);
});
}
};
@@ -0,0 +1,17 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class () extends Migration {
public function up(): void
{
Schema::table('bon_transactions', function (Blueprint $table): void {
$table->renameColumn('itemID', 'bon_exchange_id');
$table->renameColumn('sender', 'sender_id');
$table->renameColumn('receiver', 'receiver_id');
$table->renameColumn('date_actioned', 'created_at');
});
}
};
@@ -0,0 +1,14 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class () extends Migration {
public function up(): void
{
Schema::table('genre_torrent', function (Blueprint $table): void {
$table->drop();
});
}
};
@@ -0,0 +1,14 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class () extends Migration {
public function up(): void
{
Schema::table('graveyard', function (Blueprint $table): void {
$table->rename('resurrections');
});
}
};
@@ -0,0 +1,74 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class () extends Migration {
public function up(): void
{
DB::table('company_movie')->whereNotIn('company_id', DB::table('companies')->select('id'))->delete();
DB::table('company_tv')->whereNotIn('company_id', DB::table('companies')->select('id'))->delete();
DB::table('collection_movie')->whereNotIn('collection_id', DB::table('collection')->select('id'))->delete();
DB::table('network_tv')->whereNotIn('network_id', DB::table('networks')->select('id'))->delete();
DB::table('genre_movie')->whereNotIn('genre_id', DB::table('genres')->select('id'))->delete();
DB::table('genre_tv')->whereNotIn('genre_id', DB::table('genres')->select('id'))->delete();
Schema::table('credits', function (Blueprint $table): void {
$table->dropForeign(['person_id']);
});
Schema::table('companies', function (Blueprint $table): void {
$table->increments('id')->change();
});
Schema::table('collection', function (Blueprint $table): void {
$table->increments('id')->change();
});
Schema::table('networks', function (Blueprint $table): void {
$table->increments('id')->change();
});
Schema::table('genres', function (Blueprint $table): void {
$table->increments('id')->change();
});
Schema::table('recommendations', function (Blueprint $table): void {
$table->increments('id')->change();
});
Schema::table('person', function (Blueprint $table): void {
$table->increments('id')->change();
});
Schema::table('company_movie', function (Blueprint $table): void {
$table->foreign('company_id')->references('id')->on('companies')->cascadeOnUpdate()->cascadeOnDelete();
});
Schema::table('company_tv', function (Blueprint $table): void {
$table->foreign('company_id')->references('id')->on('companies')->cascadeOnUpdate()->cascadeOnDelete();
});
Schema::table('collection_movie', function (Blueprint $table): void {
$table->foreign('collection_id')->references('id')->on('collection')->cascadeOnUpdate()->cascadeOnDelete();
});
Schema::table('network_tv', function (Blueprint $table): void {
$table->foreign('network_id')->references('id')->on('networks')->cascadeOnUpdate()->cascadeOnDelete();
});
Schema::table('genre_movie', function (Blueprint $table): void {
$table->foreign('genre_id')->references('id')->on('genres')->cascadeOnUpdate()->cascadeOnDelete();
});
Schema::table('genre_tv', function (Blueprint $table): void {
$table->foreign('genre_id')->references('id')->on('genres')->cascadeOnUpdate()->cascadeOnDelete();
});
Schema::table('credits', function (Blueprint $table): void {
$table->unsignedInteger('person_id')->change();
$table->foreign('person_id')->references('id')->on('person')->cascadeOnUpdate()->cascadeOnDelete();
});
}
};
@@ -43,6 +43,7 @@
<i
v-if="message.user.id != 1 && canMod(message)"
@click="deleteMessage(message.id)"
title="Delete message"
class="fa fa-times text-red"
>
</i>
@@ -50,12 +51,14 @@
<a
v-if="message.user && message.user.id > 1 && message.user.id != $parent.auth.id"
@click.prevent="$parent.forceMessage(message.user.username)"
title="Send chat PM (/msg <username> <message>)"
>
<i class="fas fa-envelope pointee"></i>
</a>
<a
v-if="message.user && message.user.id > 1 && message.user.id != $parent.auth.id"
@click.prevent="$parent.forceGift(message.user.username)"
title="Gift user bon (/gift <username> <amount> <message>)"
>
<i class="fas fa-gift pointee"></i>
</a>
@@ -261,6 +261,8 @@
}
blockquote {
margin-left: 2px;
margin-right: 2px;
padding: 0.25em 0.25em 0.25em 1em;
color: var(--bbcode-rendered-fg-muted);
border-left: 0.25em solid var(--bbcode-rendered-quote-border);
@@ -274,6 +276,11 @@
font-weight: bold;
}
blockquote > blockquote {
margin-left: 6px;
margin-right: 20px;
}
ul,
ol {
margin-top: 0;
@@ -1,4 +1,4 @@
<article class="post" id="post-{{ $post->id }}">
<article class="post" id="post-{{ $post->id }}" x-data>
<header class="post__header">
<time
class="post__datetime"
@@ -74,11 +74,16 @@
<button
class="post__quote"
title="{{ __('forum.quote') }}"
x-data
x-on:click="
document.getElementById('forum_reply_form').style.display = 'block';
input = document.getElementById('bbcode-content');
input.value += '[quote={{ \htmlspecialchars('@'.$post->user->username) }}] {{ \str_replace(["\n", "\r"], ["\\n", "\\r"], \htmlspecialchars($post->content)) }}[/quote]';
input.value += '[quote={{ \htmlspecialchars('@'.$post->user->username) }}]';
input.value += (() => {
var text = document.createElement('textarea');
text.innerHTML = atob($refs.content.dataset.base64Bbcode);
return text.value;
})();
input.value += '[/quote]';
input.dispatchEvent(new Event('input'));
input.focus();
"
@@ -178,7 +183,8 @@
</aside>
<div
class="post__content bbcode-rendered"
data-bbcode="{{ $post->content }}"
x-ref="content"
data-base64-bbcode="{{ base64_encode($post->content) }}"
>
@joypixels($post->getContentHtml())
</div>
@@ -53,7 +53,16 @@
datetime="{{ $subforum->updated_at }}"
title="{{ $subforum->updated_at }}"
>
{{ $subforum->updated_at?->diffForHumans() ?? __('common.unknown') }}
@if ($subforum->last_topic_id === null)
{{ $subforum->updated_at?->diffForHumans() ?? __('common.unknown') }}
@else
<a
class="subforum-listing__latest-post-link"
href="{{ route('topics.latestPermalink', ['id' => $subforum->last_topic_id]) }}"
>
{{ $subforum->updated_at?->diffForHumans() ?? __('common.unknown') }}
</a>
@endif
</time>
@if ($subforum->last_topic_id !== null && $subforum->last_post_user_username !== null)
<address class="subforum-listing__latest-author">
@@ -104,7 +104,12 @@
datetime="{{ $topic->last_reply_at ?? '' }}"
title="{{ $topic->last_reply_at ?? '' }}"
>
{{ $topic->last_reply_at?->diffForHumans() ?? __('common.unknown') }}
<a
class="topic-listing__latest-post-link"
href="{{ route('topics.latestPermalink', ['id' => $topic->id]) }}"
>
{{ $topic->last_reply_at?->diffForHumans() ?? __('common.unknown') }}
</a>
</time>
</article>
</article>
@@ -22,7 +22,7 @@
<span class="torrent-search-grouped__directors-by">by</span>
@foreach($media->directors as $director)
<a
href="{{ route('mediahub.persons.show', ['id' => $director->id]) }}"
href="{{ route('mediahub.persons.show', ['id' => $director->id, 'occupationId' => App\Enums\Occupations::DIRECTOR->value]) }}"
class="torrent-search--grouped__director"
>
{{ $director->name }}
+1 -1
View File
@@ -22,7 +22,7 @@
<span class="torrent-search-grouped__directors-by">by</span>
@foreach($media->creators as $creator)
<a
href="{{ route('mediahub.persons.show', ['id' => $creator->id]) }}"
href="{{ route('mediahub.persons.show', ['id' => $creator->id, 'occupationId' => App\Enums\Occupations::CREATOR->value]) }}"
class="torrent-search--grouped__director"
>
{{ $creator->name }}
@@ -1,16 +1,6 @@
<section class="panelV2" x-data="{ tab: @entangle('occupation') }">
<section class="panelV2" x-data="{ tab: @entangle('occupationId') }">
<h2 class="panel__heading">{{ __('torrent.torrents') }}</h2>
<menu class="panel__tabs">
<li
class="panel__tab"
role="tab"
x-bind:class="tab === {{ App\Enums\Occupations::DIRECTOR->value }} && 'panel__tab--active'"
x-cloak
x-on:click="tab = {{ App\Enums\Occupations::DIRECTOR->value }}"
x-show="{{ $directedCount }} > 0"
>
Director ({{ $directedCount }})
</li>
<li
class="panel__tab"
role="tab"
@@ -21,6 +11,16 @@
>
Creator ({{ $createdCount }})
</li>
<li
class="panel__tab"
role="tab"
x-bind:class="tab === {{ App\Enums\Occupations::DIRECTOR->value }} && 'panel__tab--active'"
x-cloak
x-on:click="tab = {{ App\Enums\Occupations::DIRECTOR->value }}"
x-show="{{ $directedCount }} > 0"
>
Director ({{ $directedCount }})
</li>
<li
class="panel__tab"
role="tab"
@@ -152,6 +152,18 @@
</div>
</fieldset>
</div>
<p class="form__group">
<input
id="username"
wire:model="username"
type="search"
class="form__text"
placeholder=" "
>
<label for="username" class="form__label form__label--floating">
{{ __('subtitle.uploader') }}
</label>
</p>
<p class="form__group">
<select
id="quantity"
+1 -31
View File
@@ -28,42 +28,12 @@
alt="{{ $person->name }}"
style="max-width: 100%;"
>
<div class="panel__body">{{ $person->biography ?? 'No biography' }}</div>
<dl class="key-value">
<dt>{{ __('mediahub.born') }}</dt>
<dd>{{ $person->birthday ?? __('common.unknown') }}</dd>
<dt>Place of Birth</dt>
<dd>{{ $person->place_of_birth ?? __('common.unknown') }}</dd>
<dt>{{ __('mediahub.movie-credits') }}</dt>
<dd>{{ $person->movie->count() ?? '0' }}</dd>
<dt>{{ __('mediahub.first-seen') }} </dt>
<dd>
<a href="{{ route('torrents.index', ['view' => 'group', 'tmdb' => $person->movie->first()->id ?? '0', 'categories' => $movieCategoryIds]) }}">
{{ $person->movie->first()->title ?? 'N/A'}}
</a>
</dd>
<dt>{{ __('mediahub.latest-project') }}</dt>
<dd>
<a href="{{ route('torrents.index', ['view' => 'group', 'tmdb' => $person->movie->last()->id ?? '0', 'categories' => $movieCategoryIds]) }}">
{{ $person->movie->last()->title ?? 'N/A' }}
</a>
</dd>
<dt>{{ __('mediahub.tv-credits') }}</dt>
<dd>{{ $person->tv->count() ?? '0' }}</dd>
<dt>{{ __('mediahub.first-seen') }}</dt>
<dd>
In
<a href="{{ route('torrents.index', ['view' => 'group', 'tmdb' => $person->tv->first()->id ?? '0', 'categories' => $tvCategoryIds]) }}">
{{ $person->tv->first()->name ?? 'N/A'}}
</a>
</dd>
<dt>{{ __('mediahub.latest-project') }}</dt>
<dd>
Last in
<a href="{{ route('torrents.index', ['view' => 'group', 'tmdb' => $person->tv->last()->id ?? '0', 'categories' => $tvCategoryIds]) }}">
{{ $person->tv->last()->name ?? 'N/A' }}
</a>
</dd>
</dl>
<div class="panel__body">{{ $person->biography ?? 'No biography' }}</div>
</section>
@endsection
@@ -114,7 +114,7 @@
<h2 class="meta__heading">Cast</h2>
@foreach ($meta?->credits?->where('occupation_id', '=', App\Enums\Occupations::ACTOR->value)?->sortBy('order') ?? [] as $credit)
<article class="meta-chip-wrapper">
<a href="{{ route('mediahub.persons.show', ['id' => $credit->person->id]) }}" class="meta-chip">
<a href="{{ route('mediahub.persons.show', ['id' => $credit->person->id, 'occupationId' => $credit->occupation_id]) }}" class="meta-chip">
@if ($credit->person->still)
<img
class="meta-chip__image"
@@ -134,7 +134,7 @@
<h2 class="meta__heading">Crew</h2>
@foreach($meta?->credits?->where('occupation_id', '!=', App\Enums\Occupations::ACTOR->value)?->sortBy('occupation.position') ?? [] as $credit)
<article class="meta-chip-wrapper">
<a href="{{ route('mediahub.persons.show', ['id' => $credit->person->id]) }}" class="meta-chip">
<a href="{{ route('mediahub.persons.show', ['id' => $credit->person->id, 'occupationId' => $credit->occupation_id]) }}" class="meta-chip">
@if ($credit->person->still)
<img
class="meta-chip__image"
@@ -114,7 +114,7 @@
<h2 class="meta__heading">Cast</h2>
@foreach ($meta?->credits?->where('occupation_id', '=', App\Enums\Occupations::ACTOR->value)?->sortBy('order') ?? [] as $credit)
<article class="meta-chip-wrapper">
<a href="{{ route('mediahub.persons.show', ['id' => $credit->person->id]) }}" class="meta-chip">
<a href="{{ route('mediahub.persons.show', ['id' => $credit->person->id, 'occupationId' => $credit->occupation_id]) }}" class="meta-chip">
@if ($credit->person->still)
<img
class="meta-chip__image"
@@ -134,7 +134,7 @@
<h2 class="meta__heading">Crew</h2>
@foreach($meta?->credits?->where('occupation_id', '!=', App\Enums\Occupations::ACTOR->value)?->sortBy('occupation.position') ?? [] as $credit)
<article class="meta-chip-wrapper">
<a href="{{ route('mediahub.persons.show', ['id' => $credit->person->id]) }}" class="meta-chip">
<a href="{{ route('mediahub.persons.show', ['id' => $credit->person->id, 'occupationId' => $credit->occupation_id]) }}" class="meta-chip">
@if ($credit->person->still)
<img
class="meta-chip__image"
+3 -3
View File
@@ -52,16 +52,16 @@
@foreach($gifts as $gift)
<tr>
<td>
<x-user_tag :user="$gift->senderObj" :anon="false" />
<x-user_tag :user="$gift->sender" :anon="false" />
</td>
<td>
<x-user_tag :user="$gift->receiverObj" :anon="false" />
<x-user_tag :user="$gift->receiver" :anon="false" />
</td>
<td>
{{ $gift->cost }}
</td>
<td>
{{ $gift->date_actioned }}
{{ $gift->created_at }}
</td>
</tr>
@endforeach
+4 -4
View File
@@ -43,20 +43,20 @@
@foreach($tips as $tip)
<tr>
<td>
<x-user_tag :user="$tip->receiverObj" :anon="false" />
<x-user_tag :user="$tip->receiver" :anon="false" />
</td>
<td>
@switch(true)
@case($tip->torrent_id !== null)
<x-user_tag :user="$tip->receiverObj" :anon="$tip->torrent->anon" />
<x-user_tag :user="$tip->receiver" :anon="$tip->torrent->anon" />
@break
@case($tip->post_id !== null)
<x-user_tag :user="$tip->receiverObj" :anon="false" />
<x-user_tag :user="$tip->receiver" :anon="false" />
@break
@endswitch
</td>
<td>{{ $tip->cost }}</td>
<td>{{ $tip->date_actioned }}</td>
<td>{{ $tip->created_at }}</td>
</tr>
@endforeach
</tbody>
+1
View File
@@ -364,6 +364,7 @@ Route::middleware('language')->group(function (): void {
Route::get('/forum/{id}/create', [App\Http\Controllers\TopicController::class, 'create'])->name('create');
Route::post('/forum/{id}', [App\Http\Controllers\TopicController::class, 'store'])->name('store');
Route::get('/{topicId}/posts/{postId}', [App\Http\Controllers\TopicController::class, 'permalink'])->name('permalink');
Route::get('/{id}/latest', [App\Http\Controllers\TopicController::class, 'latestPermalink'])->name('latestPermalink');
Route::get('/{id}', [App\Http\Controllers\TopicController::class, 'show'])->name('show');
Route::get('/{id}/edit', [App\Http\Controllers\TopicController::class, 'edit'])->name('edit');
Route::patch('/{id}', [App\Http\Controllers\TopicController::class, 'update'])->name('update');
@@ -2,7 +2,7 @@
namespace Tests\Todo\Feature\Http\Controllers;
use App\Models\Graveyard;
use App\Models\Resurrection;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
@@ -10,7 +10,7 @@ use Tests\TestCase;
/**
* @see \App\Http\Controllers\GraveyardController
*/
class GraveyardControllerTest extends TestCase
class ResurrectionControllerTest extends TestCase
{
use RefreshDatabase;
@@ -21,13 +21,13 @@ class GraveyardControllerTest extends TestCase
{
$this->markTestIncomplete('This test case was generated by Shift. When you are ready, remove this line and complete this test case.');
$graveyard = Graveyard::factory()->create();
$resurrection = Resurrection::factory()->create();
$user = User::factory()->create();
$response = $this->actingAs($user)->delete(route('users.resurrections.destroy.destroy', ['user' => $user, 'resurrection' => $graveyard]));
$response = $this->actingAs($user)->delete(route('users.resurrections.destroy', ['user' => $user, 'resurrection' => $resurrection]));
$response->assertRedirect(withSuccess('Resurrection Successfully Canceled!'));
$this->assertModelMissing($graveyard);
$this->assertModelMissing($resurrection);
// TODO: perform additional assertions
}
@@ -39,11 +39,11 @@ class GraveyardControllerTest extends TestCase
{
$this->markTestIncomplete('This test case was generated by Shift. When you are ready, remove this line and complete this test case.');
$graveyard = Graveyard::factory()->create();
$resurrection = Resurrection::factory()->create();
$user = User::factory()->create();
$response = $this->actingAs($user)->post(route('users.resurrections.store', ['user' => $user]), [
'torrent_id' => $graveyard->id,
'torrent_id' => $resurrection->torrent_id,
]);
$response->assertRedirect(withErrors('Torrent Resurrection Failed! This torrent is already pending a resurrection.'));
@@ -1,22 +0,0 @@
<?php
namespace Tests\Unit\Console\Commands;
use Tests\TestCase;
/**
* @see \App\Console\Commands\AutoGraveyard
*/
class AutoGraveyardTest extends TestCase
{
/**
* @test
*/
public function it_runs_successfully(): void
{
$this->artisan('auto:graveyard')
->expectsOutput('Automated Graveyard Rewards Command Complete')
->assertExitCode(0)
->run();
}
}
@@ -0,0 +1,22 @@
<?php
namespace Tests\Unit\Console\Commands;
use Tests\TestCase;
/**
* @see \App\Console\Commands\AutoRewardResurrection
*/
class AutoRewardResurrectionTest extends TestCase
{
/**
* @test
*/
public function it_runs_successfully(): void
{
$this->artisan('auto:reward_resurrection')
->expectsOutput('Automated Reward Resurrections Command Complete')
->assertExitCode(0)
->run();
}
}