mirror of
https://github.com/HDInnovations/UNIT3D-Community-Edition.git
synced 2026-05-01 16:00:53 -05:00
Merge branch '6.x.x' into Warnings-System
This commit is contained in:
+17
-12
@@ -1,17 +1,22 @@
|
||||
name: Lint
|
||||
name: PHP Linting (Pint)
|
||||
on:
|
||||
- push
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches-ignore:
|
||||
- 'dependabot/npm_and_yarn/*'
|
||||
jobs:
|
||||
lint:
|
||||
name: Lint
|
||||
phplint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
php-version: '8.1'
|
||||
tools: phplint
|
||||
- name: Check syntax
|
||||
run: phplint .
|
||||
fetch-depth: 2
|
||||
- name: "laravel-pint"
|
||||
uses: aglipanci/laravel-pint-action@0.1.0
|
||||
with:
|
||||
preset: psr12
|
||||
- name: Commit changes
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: PSR12 Linting
|
||||
skip_fetch: true
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
php:
|
||||
preset: recommended
|
||||
risky: true
|
||||
version: 8.1
|
||||
enabled:
|
||||
- method_argument_space
|
||||
- not_operator_with_successor_space
|
||||
- no_useless_else
|
||||
- ternary_to_null_coalescing
|
||||
disabled:
|
||||
- method_argument_space_strict
|
||||
- psr4
|
||||
finder:
|
||||
exclude:
|
||||
- node_modules
|
||||
- storage
|
||||
- vendor
|
||||
- .github
|
||||
not-name:
|
||||
- index.php
|
||||
- server.php
|
||||
name:
|
||||
- "*.php"
|
||||
- "*.blade.php"
|
||||
js:
|
||||
finder:
|
||||
not-name:
|
||||
- webpack.mix.js
|
||||
css: true
|
||||
vue: true
|
||||
@@ -8,7 +8,7 @@
|
||||
<a href="http://laravel.com"><img src="https://img.shields.io/badge/Laravel-9-f4645f.svg" /></a>
|
||||
<a href="https://github.com/HDInnovations/UNIT3D/blob/master/LICENSE"><img src="https://img.shields.io/badge/License-AGPL%20v3.0-yellow.svg" /></a>
|
||||
<br>
|
||||
<a href="https://github.styleci.io/repos/113471037"><img src="https://github.styleci.io/repos/113471037/shield?style=flat&branch=master" alt="StyleCI"></a>
|
||||
<a href="https://github.com/HDInnovations/UNIT3D-Community-Edition/actions/workflows/lint.yml/badge.svg"><img src="https://github.com/HDInnovations/UNIT3D-Community-Edition/actions/workflows/lint.yml/badge.svg" /></a>
|
||||
<a href="https://github.com/HDInnovations/UNIT3D-Community-Edition/actions/workflows/phpunit-test.yml/badge.svg"><img src="https://github.com/HDInnovations/UNIT3D-Community-Edition/actions/workflows/phpunit-test.yml/badge.svg" /></a>
|
||||
<a href="https://github.com/HDInnovations/UNIT3D-Community-Edition/actions/workflows/compile-assets-test.yml/badge.svg"><img src="https://github.com/HDInnovations/UNIT3D-Community-Edition/actions/workflows/compile-assets-test.yml/badge.svg" /></a>
|
||||
<br>
|
||||
|
||||
@@ -57,7 +57,7 @@ class AutoDisableInactiveUsers extends Command
|
||||
->all();
|
||||
|
||||
foreach ($users as $user) {
|
||||
if ($user->getSeeding() === 0) {
|
||||
if ($user->seedingTorrents()->count() === 0) {
|
||||
$user->group_id = $disabledGroup[0];
|
||||
$user->can_upload = 0;
|
||||
$user->can_download = 0;
|
||||
|
||||
@@ -96,7 +96,7 @@ class AutoGroup extends Command
|
||||
}
|
||||
|
||||
// Seeder Seedsize >= 5TiB and account 1 month old and seedtime average 30 days or better
|
||||
if ($user->getTotalSeedSize() >= $byteUnits->bytesFromUnit('5TiB') && $user->getRatio() >= \config('other.ratio') && \round($user->getTotalSeedTime() / \max(1, $hiscount)) > 2_592_000 && $user->created_at < $current->copy()->subDays(30)->toDateTimeString() && $user->group_id != UserGroups::SEEDER) {
|
||||
if ($user->seedingTorrents()->sum('size') >= $byteUnits->bytesFromUnit('5TiB') && $user->getRatio() >= \config('other.ratio') && \round($user->history()->sum('seedtime') / \max(1, $hiscount)) > 2_592_000 && $user->created_at < $current->copy()->subDays(30)->toDateTimeString() && $user->group_id != UserGroups::SEEDER) {
|
||||
$user->group_id = UserGroups::SEEDER;
|
||||
$user->save();
|
||||
}
|
||||
@@ -108,7 +108,7 @@ class AutoGroup extends Command
|
||||
}
|
||||
|
||||
// Archivist Seedsize >= 10TiB and account 3 month old and seedtime average 60 days or better
|
||||
if ($user->getTotalSeedSize() >= $byteUnits->bytesFromUnit('10TiB') && $user->getRatio() >= \config('other.ratio') && \round($user->getTotalSeedTime() / \max(1, $hiscount)) > 2_592_000 * 2 && $user->created_at < $current->copy()->subDays(90)->toDateTimeString() && $user->group_id != UserGroups::ARCHIVIST) {
|
||||
if ($user->seedingTorrents()->sum('size') >= $byteUnits->bytesFromUnit('10TiB') && $user->getRatio() >= \config('other.ratio') && \round($user->history()->sum('seedtime') / \max(1, $hiscount)) > 2_592_000 * 2 && $user->created_at < $current->copy()->subDays(90)->toDateTimeString() && $user->group_id != UserGroups::ARCHIVIST) {
|
||||
$user->group_id = UserGroups::ARCHIVIST;
|
||||
$user->save();
|
||||
}
|
||||
|
||||
@@ -51,7 +51,8 @@ class AutoHighspeedTag extends Command
|
||||
->select('torrent_id')
|
||||
->whereRaw("ip IN ('".$seedboxIps->implode("','")."')"),
|
||||
'highspeed_torrents',
|
||||
fn ($join) => $join->on('torrents.id', '=', 'highspeed_torrents.torrent_id'))
|
||||
fn ($join) => $join->on('torrents.id', '=', 'highspeed_torrents.torrent_id')
|
||||
)
|
||||
->update([
|
||||
'highspeed' => DB::raw('CASE WHEN highspeed_torrents.torrent_id IS NOT NULL THEN 1 ELSE 0 END'),
|
||||
]);
|
||||
|
||||
@@ -39,7 +39,8 @@ class AutoStatsClients extends Command
|
||||
public function handle(): void
|
||||
{
|
||||
$clients = Peer::selectRaw('agent, count(*) as count')
|
||||
->fromSub(fn ($sub) => $sub
|
||||
->fromSub(
|
||||
fn ($sub) => $sub
|
||||
->select(['agent', 'user_id'])
|
||||
->from('peers')
|
||||
->groupBy('agent', 'user_id'),
|
||||
|
||||
@@ -346,8 +346,10 @@ class GitUpdater extends Command
|
||||
}
|
||||
} elseif (\is_file(\base_path($path)) && \dirname($path) !== '.') {
|
||||
$path = \dirname($path);
|
||||
if (! \is_dir(\storage_path(\sprintf('gitupdate/%s', $path))) && ! \mkdir($concurrentDirectory = \storage_path(\sprintf('gitupdate/%s',
|
||||
$path)), 0775, true) && ! \is_dir($concurrentDirectory)) {
|
||||
if (! \is_dir(\storage_path(\sprintf('gitupdate/%s', $path))) && ! \mkdir($concurrentDirectory = \storage_path(\sprintf(
|
||||
'gitupdate/%s',
|
||||
$path
|
||||
)), 0775, true) && ! \is_dir($concurrentDirectory)) {
|
||||
throw new \RuntimeException(\sprintf('Directory "%s" was not created', $concurrentDirectory));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,10 +27,9 @@ class BBCodeConverter
|
||||
*/
|
||||
protected function replaceSize(): void
|
||||
{
|
||||
$this->text = \preg_replace_callback('#\[size=([\W\D\w\s]*?)\]([\W\D\w\s]*?)\[/size\]#iu',
|
||||
|
||||
$this->text = \preg_replace_callback(
|
||||
'#\[size=([\W\D\w\s]*?)\]([\W\D\w\s]*?)\[/size\]#iu',
|
||||
fn ($matches) => '<div style="font-size: '.\trim($matches[1], '').';">'.\trim($matches[1], '').'</span>',
|
||||
|
||||
$this->text
|
||||
);
|
||||
}
|
||||
@@ -40,10 +39,9 @@ class BBCodeConverter
|
||||
*/
|
||||
protected function replaceCenter(): void
|
||||
{
|
||||
$this->text = \preg_replace_callback('#\[center\]([\W\D\w\s]*?)\[/center\]#iu',
|
||||
|
||||
$this->text = \preg_replace_callback(
|
||||
'#\[center\]([\W\D\w\s]*?)\[/center\]#iu',
|
||||
fn ($matches) => '<div class="text-center">'.\trim($matches[1], ' ').'</div>',
|
||||
|
||||
$this->text
|
||||
);
|
||||
}
|
||||
@@ -53,10 +51,9 @@ class BBCodeConverter
|
||||
*/
|
||||
protected function replaceBold(): void
|
||||
{
|
||||
$this->text = \preg_replace_callback('#\[b\]([\W\D\w\s]*?)\[/b\]#iu',
|
||||
|
||||
$this->text = \preg_replace_callback(
|
||||
'#\[b\]([\W\D\w\s]*?)\[/b\]#iu',
|
||||
fn ($matches) => '**'.\trim($matches[1], ' ').'**',
|
||||
|
||||
$this->text
|
||||
);
|
||||
}
|
||||
@@ -66,10 +63,9 @@ class BBCodeConverter
|
||||
*/
|
||||
protected function replaceItalic(): void
|
||||
{
|
||||
$this->text = \preg_replace_callback('#\[i\]([\W\D\w\s]*?)\[/i\]#iu',
|
||||
|
||||
$this->text = \preg_replace_callback(
|
||||
'#\[i\]([\W\D\w\s]*?)\[/i\]#iu',
|
||||
fn ($matches) => '*'.\trim($matches[1], ' ').'*',
|
||||
|
||||
$this->text
|
||||
);
|
||||
}
|
||||
@@ -79,10 +75,9 @@ class BBCodeConverter
|
||||
*/
|
||||
protected function replaceUnderline(): void
|
||||
{
|
||||
$this->text = \preg_replace_callback('#\[u\]([\W\D\w\s]*?)\[/u\]#iu',
|
||||
|
||||
$this->text = \preg_replace_callback(
|
||||
'#\[u\]([\W\D\w\s]*?)\[/u\]#iu',
|
||||
fn ($matches) => '_'.\trim($matches[1], ' ').'_',
|
||||
|
||||
$this->text
|
||||
);
|
||||
}
|
||||
@@ -92,10 +87,9 @@ class BBCodeConverter
|
||||
*/
|
||||
protected function replaceStrikethrough(): void
|
||||
{
|
||||
$this->text = \preg_replace_callback('#\[s\]([\W\D\w\s]*?)\[/s\]#iu',
|
||||
|
||||
$this->text = \preg_replace_callback(
|
||||
'#\[s\]([\W\D\w\s]*?)\[/s\]#iu',
|
||||
fn ($matches) => '~~'.\trim($matches[1], ' ').'~~',
|
||||
|
||||
$this->text
|
||||
);
|
||||
}
|
||||
@@ -105,8 +99,8 @@ class BBCodeConverter
|
||||
*/
|
||||
protected function replaceLists(): void
|
||||
{
|
||||
$this->text = \preg_replace_callback('#\[list(?P<type>=1)?\](?P<items>[\W\D\w\s]*?)\[/list\]#iu',
|
||||
|
||||
$this->text = \preg_replace_callback(
|
||||
'#\[list(?P<type>=1)?\](?P<items>[\W\D\w\s]*?)\[/list\]#iu',
|
||||
function ($matches) {
|
||||
$buffer = '';
|
||||
|
||||
@@ -140,7 +134,6 @@ class BBCodeConverter
|
||||
|
||||
return $buffer;
|
||||
},
|
||||
|
||||
$this->text
|
||||
);
|
||||
}
|
||||
@@ -200,8 +193,8 @@ class BBCodeConverter
|
||||
*/
|
||||
protected function replaceUrls(): void
|
||||
{
|
||||
$this->text = \preg_replace_callback('#\[url\s*=\s*("(?:[^"]*")|\A[^\']*\Z|(?:[^\'">\]\s]+))\s*(?:[^]\s]*)\]([\W\D\w\s]*?)\[/url\]#iu',
|
||||
|
||||
$this->text = \preg_replace_callback(
|
||||
'#\[url\s*=\s*("(?:[^"]*")|\A[^\']*\Z|(?:[^\'">\]\s]+))\s*(?:[^]\s]*)\]([\W\D\w\s]*?)\[/url\]#iu',
|
||||
function ($matches) {
|
||||
if (isset($matches[1], $matches[2])) {
|
||||
return '['.$matches[2].']('.$matches[1].')';
|
||||
@@ -209,7 +202,6 @@ class BBCodeConverter
|
||||
|
||||
throw new \RuntimeException('Text has malformed BBCode urls');
|
||||
},
|
||||
|
||||
$this->text
|
||||
);
|
||||
}
|
||||
@@ -219,10 +211,9 @@ class BBCodeConverter
|
||||
*/
|
||||
protected function replaceImage(): void
|
||||
{
|
||||
$this->text = \preg_replace_callback('#\[img\]([\W\D\w\s]*?)\[/img\]#iu',
|
||||
|
||||
$this->text = \preg_replace_callback(
|
||||
'#\[img\]([\W\D\w\s]*?)\[/img\]#iu',
|
||||
fn ($matches) => PHP_EOL.'![]'.'('.$matches[1].')'.PHP_EOL,
|
||||
|
||||
$this->text
|
||||
);
|
||||
}
|
||||
@@ -232,10 +223,9 @@ class BBCodeConverter
|
||||
*/
|
||||
protected function replaceImages(): void
|
||||
{
|
||||
$this->text = \preg_replace_callback('#\[img\s*=\s*("(?:[^"]*")|\A[^\']*\Z|(?:[^\'">\]\s]+))\s*(?:[^]\s]*)\[/img\]#iu',
|
||||
|
||||
fn ($matches) => PHP_EOL.'!['.$matches[2].']'.'('.$matches[1].')'.PHP_EOL,
|
||||
|
||||
$this->text = \preg_replace_callback(
|
||||
'#\[img\s*=\s*("(?:[^"]*")|\A[^\']*\Z|(?:[^\'">\]\s]+))\s*(?:[^]\s]*)\[/img\]#iu',
|
||||
fn ($matches) => PHP_EOL.'!['.$matches[2].']'.'('.$matches[1].')'.PHP_EOL,
|
||||
$this->text
|
||||
);
|
||||
}
|
||||
@@ -249,14 +239,13 @@ class BBCodeConverter
|
||||
$this->text = \preg_replace('#\G(?<!^)(?>(\[quote\b[^]]*](?>[^[]++|\[(?!/?quote)|(?1))*\[/quote])|(?<!\[)(?>[^[]++|\[(?!/?quote))+\K)|\[quote\b[^]]*]\K#', '', $this->text);
|
||||
|
||||
// Replaces all the remaining quotes with '> ' characters.
|
||||
$this->text = \preg_replace_callback('#\[quote\b[^]]*\]((?>[^[]++|\[(?!/?quote))*)\[/quote\]#i',
|
||||
|
||||
$this->text = \preg_replace_callback(
|
||||
'#\[quote\b[^]]*\]((?>[^[]++|\[(?!/?quote))*)\[/quote\]#i',
|
||||
function ($matches) {
|
||||
$quote = \preg_replace('#^\s*#mu', '', \trim($matches[1]));
|
||||
|
||||
return '> '.$quote.PHP_EOL.PHP_EOL;
|
||||
},
|
||||
|
||||
$this->text
|
||||
);
|
||||
}
|
||||
@@ -266,8 +255,8 @@ class BBCodeConverter
|
||||
*/
|
||||
protected function replaceSnippets(): void
|
||||
{
|
||||
$this->text = \preg_replace_callback('#\[code\s*=?(?P<language>\w*)\](?P<snippet>[\W\D\w\s]*?)\[\/code\]#iu',
|
||||
|
||||
$this->text = \preg_replace_callback(
|
||||
'#\[code\s*=?(?P<language>\w*)\](?P<snippet>[\W\D\w\s]*?)\[\/code\]#iu',
|
||||
function ($matches) {
|
||||
if (isset($matches['snippet'])) {
|
||||
$language = \strtolower($matches['language']);
|
||||
@@ -303,7 +292,6 @@ class BBCodeConverter
|
||||
|
||||
throw new \RuntimeException('Text has malformed BBCode snippet.');
|
||||
},
|
||||
|
||||
$this->text
|
||||
);
|
||||
}
|
||||
@@ -313,10 +301,9 @@ class BBCodeConverter
|
||||
*/
|
||||
protected function replaceSpoilers(): void
|
||||
{
|
||||
$this->text = \preg_replace_callback('#\[spoiler\](.*?)\[\/spoiler\]#ius',
|
||||
|
||||
$this->text = \preg_replace_callback(
|
||||
'#\[spoiler\](.*?)\[\/spoiler\]#ius',
|
||||
fn ($matches) => '<p><details class="label label-primary"><summary>Spoiler</summary><pre><code>'.\trim($matches[1]).'</code></pre></details></p>',
|
||||
|
||||
$this->text
|
||||
);
|
||||
}
|
||||
@@ -326,10 +313,9 @@ class BBCodeConverter
|
||||
*/
|
||||
protected function replaceNamedSpoilers(): void
|
||||
{
|
||||
$this->text = \preg_replace_callback('#\[spoiler\=(.*?)\](.*?)\[\/spoiler\]#ius',
|
||||
|
||||
$this->text = \preg_replace_callback(
|
||||
'#\[spoiler\=(.*?)\](.*?)\[\/spoiler\]#ius',
|
||||
fn ($matches) => '<p><details class="label label-primary"><summary>'.\trim($matches[1]).'</summary><pre><code>'.\trim($matches[2]).'</code></pre></details></p>',
|
||||
|
||||
$this->text
|
||||
);
|
||||
}
|
||||
@@ -339,10 +325,9 @@ class BBCodeConverter
|
||||
*/
|
||||
protected function replaceColor(): void
|
||||
{
|
||||
$this->text = \preg_replace_callback('#\[color=([\W\D\w\s]*?)\]([\W\D\w\s]*?)\[/color\]#iu',
|
||||
|
||||
$this->text = \preg_replace_callback(
|
||||
'#\[color=([\W\D\w\s]*?)\]([\W\D\w\s]*?)\[/color\]#iu',
|
||||
fn ($matches) => '<span style="color: '.\trim($matches[1], '').';">'.\trim($matches[2], '').'</span>',
|
||||
|
||||
$this->text
|
||||
);
|
||||
}
|
||||
@@ -352,10 +337,9 @@ class BBCodeConverter
|
||||
*/
|
||||
protected function replaceVideo(): void
|
||||
{
|
||||
$this->text = \preg_replace_callback('#\[video=[^\]]*.([\W\D\w\s][^\[]*)\[/video]#iu',
|
||||
|
||||
$this->text = \preg_replace_callback(
|
||||
'#\[video=[^\]]*.([\W\D\w\s][^\[]*)\[/video]#iu',
|
||||
fn ($matches) => '<iframe src="https://www.youtube-nocookie.com/embed/'.\trim($matches[1], '').'?rel=0" width="640" height="480" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>',
|
||||
|
||||
$this->text
|
||||
);
|
||||
}
|
||||
@@ -365,10 +349,9 @@ class BBCodeConverter
|
||||
*/
|
||||
protected function replaceYoutube(): void
|
||||
{
|
||||
$this->text = \preg_replace_callback('#\[youtube\]([\W\D\w\s]*?)\[/youtube\]#iu',
|
||||
|
||||
$this->text = \preg_replace_callback(
|
||||
'#\[youtube\]([\W\D\w\s]*?)\[/youtube\]#iu',
|
||||
fn ($matches) => '<iframe src="https://www.youtube-nocookie.com/embed/'.\trim($matches[1], '').'?rel=0" width="640" height="480" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>',
|
||||
|
||||
$this->text
|
||||
);
|
||||
}
|
||||
@@ -378,10 +361,9 @@ class BBCodeConverter
|
||||
*/
|
||||
protected function replaceAlert(): void
|
||||
{
|
||||
$this->text = \preg_replace_callback('#\[alert\]([\W\D\w\s]*?)\[/alert\]#iu',
|
||||
|
||||
$this->text = \preg_replace_callback(
|
||||
'#\[alert\]([\W\D\w\s]*?)\[/alert\]#iu',
|
||||
fn ($matches) => '<div class="bbcode-alert">'.\trim($matches[1], '').'</div>',
|
||||
|
||||
$this->text
|
||||
);
|
||||
}
|
||||
@@ -391,10 +373,9 @@ class BBCodeConverter
|
||||
*/
|
||||
protected function replaceNote(): void
|
||||
{
|
||||
$this->text = \preg_replace_callback('#\[note\]([\W\D\w\s]*?)\[/note\]#iu',
|
||||
|
||||
$this->text = \preg_replace_callback(
|
||||
'#\[note\]([\W\D\w\s]*?)\[/note\]#iu',
|
||||
fn ($matches) => '<div class="bbcode-note">'.\trim($matches[1], '').'</div>',
|
||||
|
||||
$this->text
|
||||
);
|
||||
}
|
||||
|
||||
@@ -22,26 +22,26 @@ class BackupEncryption
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public final const ENCRYPTION_DEFAULT = ZipArchive::EM_AES_128;
|
||||
final public const ENCRYPTION_DEFAULT = ZipArchive::EM_AES_128;
|
||||
|
||||
/**
|
||||
* AES-128 encryption contants.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public final const ENCRYPTION_WINZIP_AES_128 = ZipArchive::EM_AES_128;
|
||||
final public const ENCRYPTION_WINZIP_AES_128 = ZipArchive::EM_AES_128;
|
||||
|
||||
/**
|
||||
* AES-192 encryption contants.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public final const ENCRYPTION_WINZIP_AES_192 = ZipArchive::EM_AES_192;
|
||||
final public const ENCRYPTION_WINZIP_AES_192 = ZipArchive::EM_AES_192;
|
||||
|
||||
/**
|
||||
* AES-256 encryption contants.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public final const ENCRYPTION_WINZIP_AES_256 = ZipArchive::EM_AES_256;
|
||||
final public const ENCRYPTION_WINZIP_AES_256 = ZipArchive::EM_AES_256;
|
||||
}
|
||||
|
||||
@@ -165,7 +165,8 @@ class Markdown
|
||||
foreach ($lines as $line) {
|
||||
if (\rtrim($line) === '') {
|
||||
if (isset($CurrentBlock)) {
|
||||
$CurrentBlock['interrupted'] = (isset($CurrentBlock['interrupted'])
|
||||
$CurrentBlock['interrupted'] = (
|
||||
isset($CurrentBlock['interrupted'])
|
||||
? $CurrentBlock['interrupted'] + 1 : 1
|
||||
);
|
||||
}
|
||||
@@ -798,8 +799,10 @@ class Markdown
|
||||
}
|
||||
|
||||
if (
|
||||
(! \str_contains((string) $Block['element']['handler']['argument'], '|') && ! \str_contains((string) $Line['text'], '|') && ! \str_contains((string) $Line['text'],
|
||||
':')) || \str_contains((string) $Block['element']['handler']['argument'], "\n")
|
||||
(! \str_contains((string) $Block['element']['handler']['argument'], '|') && ! \str_contains((string) $Line['text'], '|') && ! \str_contains(
|
||||
(string) $Line['text'],
|
||||
':'
|
||||
)) || \str_contains((string) $Block['element']['handler']['argument'], "\n")
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -1020,7 +1023,8 @@ class Markdown
|
||||
|
||||
$Elements = [];
|
||||
|
||||
$nonNestables = (empty($nonNestables)
|
||||
$nonNestables = (
|
||||
empty($nonNestables)
|
||||
? []
|
||||
: \array_combine($nonNestables, $nonNestables)
|
||||
);
|
||||
@@ -1580,7 +1584,8 @@ class Markdown
|
||||
continue;
|
||||
}
|
||||
|
||||
$autoBreakNext = ($Element['autobreak'] ?? isset($Element['name'])
|
||||
$autoBreakNext = (
|
||||
$Element['autobreak'] ?? isset($Element['name'])
|
||||
);
|
||||
// (autobreak === false) covers both sides of an element
|
||||
$autoBreak = $autoBreak ? $autoBreakNext : $autoBreak;
|
||||
|
||||
@@ -15,15 +15,15 @@ namespace App\Helpers;
|
||||
|
||||
class StringHelper
|
||||
{
|
||||
public final const KIB = 1_024;
|
||||
final public const KIB = 1_024;
|
||||
|
||||
public final const MIB = 1_024 * 1_024;
|
||||
final public const MIB = 1_024 * 1_024;
|
||||
|
||||
public final const GIB = 1_024 * 1_024 * 1_024;
|
||||
final public const GIB = 1_024 * 1_024 * 1_024;
|
||||
|
||||
public final const TIB = 1_024 * 1_024 * 1_024 * 1_024;
|
||||
final public const TIB = 1_024 * 1_024 * 1_024 * 1_024;
|
||||
|
||||
public final const PIB = 1_024 * 1_024 * 1_024 * 1_024 * 1_024;
|
||||
final public const PIB = 1_024 * 1_024 * 1_024 * 1_024 * 1_024;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
|
||||
@@ -282,13 +282,17 @@ class TorrentController extends BaseController
|
||||
if ($free >= 1 && $featured == 0) {
|
||||
if ($torrent->fl_until === null) {
|
||||
$this->chatRepository->systemMessage(
|
||||
\sprintf('Ladies and Gents, [url=%s/torrents/',
|
||||
$appurl).$torrent->id.']'.$torrent->name.'[/url] has been granted '.$free.'% FreeLeech! Grab It While You Can! :fire:'
|
||||
\sprintf(
|
||||
'Ladies and Gents, [url=%s/torrents/',
|
||||
$appurl
|
||||
).$torrent->id.']'.$torrent->name.'[/url] has been granted '.$free.'% FreeLeech! Grab It While You Can! :fire:'
|
||||
);
|
||||
} else {
|
||||
$this->chatRepository->systemMessage(
|
||||
\sprintf('Ladies and Gents, [url=%s/torrents/',
|
||||
$appurl).$torrent->id.']'.$torrent->name.'[/url] has been granted '.$free.'% FreeLeech for '.$request->input('fl_until').' days. :stopwatch:'
|
||||
\sprintf(
|
||||
'Ladies and Gents, [url=%s/torrents/',
|
||||
$appurl
|
||||
).$torrent->id.']'.$torrent->name.'[/url] has been granted '.$free.'% FreeLeech for '.$request->input('fl_until').' days. :stopwatch:'
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -296,13 +300,17 @@ class TorrentController extends BaseController
|
||||
if ($doubleup == 1 && $featured == 0) {
|
||||
if ($torrent->du_until === null) {
|
||||
$this->chatRepository->systemMessage(
|
||||
\sprintf('Ladies and Gents, [url=%s/torrents/',
|
||||
$appurl).$torrent->id.']'.$torrent->name.'[/url] has been granted Double Upload! Grab It While You Can! :fire:'
|
||||
\sprintf(
|
||||
'Ladies and Gents, [url=%s/torrents/',
|
||||
$appurl
|
||||
).$torrent->id.']'.$torrent->name.'[/url] has been granted Double Upload! Grab It While You Can! :fire:'
|
||||
);
|
||||
} else {
|
||||
$this->chatRepository->systemMessage(
|
||||
\sprintf('Ladies and Gents, [url=%s/torrents/',
|
||||
$appurl).$torrent->id.']'.$torrent->name.'[/url] has been granted Double Upload for '.$request->input('du_until').' days. :stopwatch:'
|
||||
\sprintf(
|
||||
'Ladies and Gents, [url=%s/torrents/',
|
||||
$appurl
|
||||
).$torrent->id.']'.$torrent->name.'[/url] has been granted Double Upload for '.$request->input('du_until').' days. :stopwatch:'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace App\Http\Controllers;
|
||||
use App\Exceptions\TrackerException;
|
||||
use App\Helpers\Bencode;
|
||||
use App\Jobs\ProcessAnnounce;
|
||||
use App\Models\BlacklistClient;
|
||||
use App\Models\Group;
|
||||
use App\Models\Peer;
|
||||
use App\Models\Torrent;
|
||||
@@ -146,17 +147,22 @@ class AnnounceController extends Controller
|
||||
|| $request->header('want-digest'), new TrackerException(122));
|
||||
|
||||
$userAgent = $request->header('User-Agent');
|
||||
$clientBlacklist = BlacklistClient::all()->pluck('name')->toArray();
|
||||
|
||||
// Should also block User-Agent strings that are too long. (For Database reasons)
|
||||
\throw_if(\strlen((string) $userAgent) > 64, new TrackerException(123));
|
||||
|
||||
// Block Browser by checking the User-Agent
|
||||
\throw_if(\preg_match('/(Mozilla|Browser|Chrome|Safari|AppleWebKit|Opera|Links|Lynx|Bot|Unknown)/i',
|
||||
(string) $userAgent), new TrackerException(121));
|
||||
\throw_if(\preg_match(
|
||||
'/(Mozilla|Browser|Chrome|Safari|AppleWebKit|Opera|Links|Lynx|Bot|Unknown)/i',
|
||||
(string) $userAgent
|
||||
), new TrackerException(121));
|
||||
|
||||
// Block Blacklisted Clients
|
||||
\throw_if(\in_array($request->header('User-Agent'), \config('client-blacklist.clients')),
|
||||
new TrackerException(128, [':ua' => $request->header('User-Agent')]));
|
||||
\throw_if(
|
||||
\in_array($request->header('User-Agent'), $clientBlacklist),
|
||||
new TrackerException(128, [':ua' => $request->header('User-Agent')])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,12 +177,16 @@ class AnnounceController extends Controller
|
||||
\throw_if($passkey === null, new TrackerException(130, [':attribute' => 'passkey']));
|
||||
|
||||
// If Passkey Length Is Wrong
|
||||
\throw_if(\strlen((string) $passkey) !== 32,
|
||||
new TrackerException(132, [':attribute' => 'passkey', ':rule' => 32]));
|
||||
\throw_if(
|
||||
\strlen((string) $passkey) !== 32,
|
||||
new TrackerException(132, [':attribute' => 'passkey', ':rule' => 32])
|
||||
);
|
||||
|
||||
// If Passkey Format Is Wrong
|
||||
\throw_if(\strspn(\strtolower($passkey), 'abcdef0123456789') !== 32,
|
||||
new TrackerException(131, [':attribute' => 'passkey', ':reason' => 'Passkey format is incorrect']));
|
||||
\throw_if(
|
||||
\strspn(\strtolower($passkey), 'abcdef0123456789') !== 32,
|
||||
new TrackerException(131, [':attribute' => 'passkey', ':reason' => 'Passkey format is incorrect'])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -202,14 +212,18 @@ class AnnounceController extends Controller
|
||||
}
|
||||
|
||||
foreach (['info_hash', 'peer_id'] as $item) {
|
||||
\throw_if(\strlen((string) $queries[$item]) !== 20,
|
||||
new TrackerException(133, [':attribute' => $item, ':rule' => 20]));
|
||||
\throw_if(
|
||||
\strlen((string) $queries[$item]) !== 20,
|
||||
new TrackerException(133, [':attribute' => $item, ':rule' => 20])
|
||||
);
|
||||
}
|
||||
|
||||
foreach (['uploaded', 'downloaded', 'left'] as $item) {
|
||||
$itemData = $queries[$item];
|
||||
\throw_if(! \is_numeric($itemData) || $itemData < 0,
|
||||
new TrackerException(134, [':attribute' => $item]));
|
||||
\throw_if(
|
||||
! \is_numeric($itemData) || $itemData < 0,
|
||||
new TrackerException(134, [':attribute' => $item])
|
||||
);
|
||||
}
|
||||
|
||||
// Part.2 Extract optional announce fields
|
||||
@@ -223,25 +237,33 @@ class AnnounceController extends Controller
|
||||
}
|
||||
|
||||
foreach (['numwant', 'corrupt'] as $item) {
|
||||
\throw_if(! \is_numeric($queries[$item]) || $queries[$item] < 0,
|
||||
new TrackerException(134, [':attribute' => $item]));
|
||||
\throw_if(
|
||||
! \is_numeric($queries[$item]) || $queries[$item] < 0,
|
||||
new TrackerException(134, [':attribute' => $item])
|
||||
);
|
||||
}
|
||||
|
||||
\throw_if(! \in_array(\strtolower($queries['event']), ['started', 'completed', 'stopped', 'paused', '']),
|
||||
new TrackerException(136, [':event' => \strtolower($queries['event'])]));
|
||||
\throw_if(
|
||||
! \in_array(\strtolower($queries['event']), ['started', 'completed', 'stopped', 'paused', '']),
|
||||
new TrackerException(136, [':event' => \strtolower($queries['event'])])
|
||||
);
|
||||
|
||||
// Part.3 check Port is Valid and Allowed
|
||||
/**
|
||||
* Normally , the port must in 1 - 65535 , that is ( $port > 0 && $port < 0xffff )
|
||||
* However, in some case , When `&event=stopped` the port may set to 0.
|
||||
*/
|
||||
\throw_if($queries['port'] === 0 && \strtolower($queries['event']) !== 'stopped',
|
||||
new TrackerException(137, [':event' => \strtolower($queries['event'])]));
|
||||
\throw_if(
|
||||
$queries['port'] === 0 && \strtolower($queries['event']) !== 'stopped',
|
||||
new TrackerException(137, [':event' => \strtolower($queries['event'])])
|
||||
);
|
||||
|
||||
\throw_if(! \is_numeric($queries['port']) || $queries['port'] < 0 || $queries['port'] > 0xFFFF
|
||||
|| \in_array($queries['port'],
|
||||
|| \in_array(
|
||||
$queries['port'],
|
||||
self::BLACK_PORTS,
|
||||
true), new TrackerException(135, [':port' => $queries['port']]));
|
||||
true
|
||||
), new TrackerException(135, [':port' => $queries['port']]));
|
||||
|
||||
// Part.4 Get User Ip Address
|
||||
$queries['ip-address'] = $request->getClientIp();
|
||||
@@ -267,12 +289,18 @@ class AnnounceController extends Controller
|
||||
protected function checkUser($passkey, $queries): object
|
||||
{
|
||||
// Caached System Required Groups
|
||||
$bannedGroup = \cache()->rememberForever('banned_group',
|
||||
fn () => Group::where('slug', '=', 'banned')->pluck('id'));
|
||||
$validatingGroup = \cache()->rememberForever('validating_group',
|
||||
fn () => Group::where('slug', '=', 'validating')->pluck('id'));
|
||||
$disabledGroup = \cache()->rememberForever('disabled_group',
|
||||
fn () => Group::where('slug', '=', 'disabled')->pluck('id'));
|
||||
$bannedGroup = \cache()->rememberForever(
|
||||
'banned_group',
|
||||
fn () => Group::where('slug', '=', 'banned')->pluck('id')
|
||||
);
|
||||
$validatingGroup = \cache()->rememberForever(
|
||||
'validating_group',
|
||||
fn () => Group::where('slug', '=', 'validating')->pluck('id')
|
||||
);
|
||||
$disabledGroup = \cache()->rememberForever(
|
||||
'disabled_group',
|
||||
fn () => Group::where('slug', '=', 'disabled')->pluck('id')
|
||||
);
|
||||
|
||||
// Check Passkey Against Users Table
|
||||
$user = User::with('group')
|
||||
@@ -284,20 +312,28 @@ class AnnounceController extends Controller
|
||||
\throw_if($user === null, new TrackerException(140));
|
||||
|
||||
// If User Account Is Unactivated/Validating Return Error to Client
|
||||
\throw_if($user->active === 0 || $user->group->id === $validatingGroup[0],
|
||||
new TrackerException(141, [':status' => 'Unactivated/Validating']));
|
||||
\throw_if(
|
||||
$user->active === 0 || $user->group->id === $validatingGroup[0],
|
||||
new TrackerException(141, [':status' => 'Unactivated/Validating'])
|
||||
);
|
||||
|
||||
// If User Download Rights Are Disabled Return Error to Client
|
||||
\throw_if($user->can_download === 0 && $queries['left'] !== '0',
|
||||
new TrackerException(142));
|
||||
\throw_if(
|
||||
$user->can_download === 0 && $queries['left'] !== '0',
|
||||
new TrackerException(142)
|
||||
);
|
||||
|
||||
// If User Is Banned Return Error to Client
|
||||
\throw_if($user->group->id === $bannedGroup[0],
|
||||
new TrackerException(141, [':status' => 'Banned']));
|
||||
\throw_if(
|
||||
$user->group->id === $bannedGroup[0],
|
||||
new TrackerException(141, [':status' => 'Banned'])
|
||||
);
|
||||
|
||||
// If User Is Disabled Return Error to Client
|
||||
throw_if($user->group->id === $disabledGroup[0],
|
||||
new TrackerException(141, [':status' => 'Disabled']));
|
||||
throw_if(
|
||||
$user->group->id === $disabledGroup[0],
|
||||
new TrackerException(141, [':status' => 'Disabled'])
|
||||
);
|
||||
|
||||
return $user;
|
||||
}
|
||||
@@ -321,16 +357,22 @@ class AnnounceController extends Controller
|
||||
\throw_if($torrent === null, new TrackerException(150));
|
||||
|
||||
// If Torrent Is Pending Moderation Return Error to Client
|
||||
\throw_if($torrent->status === self::PENDING,
|
||||
new TrackerException(151, [':status' => 'PENDING In Moderation']));
|
||||
\throw_if(
|
||||
$torrent->status === self::PENDING,
|
||||
new TrackerException(151, [':status' => 'PENDING In Moderation'])
|
||||
);
|
||||
|
||||
// If Torrent Is Rejected Return Error to Client
|
||||
\throw_if($torrent->status === self::REJECTED,
|
||||
new TrackerException(151, [':status' => 'REJECTED In Moderation']));
|
||||
\throw_if(
|
||||
$torrent->status === self::REJECTED,
|
||||
new TrackerException(151, [':status' => 'REJECTED In Moderation'])
|
||||
);
|
||||
|
||||
// If Torrent Is Postponed Return Error to Client
|
||||
\throw_if($torrent->status === self::POSTPONED,
|
||||
new TrackerException(151, [':status' => 'POSTPONED In Moderation']));
|
||||
\throw_if(
|
||||
$torrent->status === self::POSTPONED,
|
||||
new TrackerException(151, [':status' => 'POSTPONED In Moderation'])
|
||||
);
|
||||
|
||||
return $torrent;
|
||||
}
|
||||
@@ -368,9 +410,11 @@ class AnnounceController extends Controller
|
||||
->first();
|
||||
$setMin = \config('announce.min_interval.interval') ?? self::MIN;
|
||||
$randomMinInterval = random_int($setMin, $setMin * 2);
|
||||
\throw_if($prevAnnounce && $prevAnnounce->updated_at->greaterThan(now()->subSeconds($randomMinInterval))
|
||||
\throw_if(
|
||||
$prevAnnounce && $prevAnnounce->updated_at->greaterThan(now()->subSeconds($randomMinInterval))
|
||||
&& \strtolower($queries['event']) !== 'completed' && \strtolower($queries['event']) !== 'stopped',
|
||||
new TrackerException(162, [':min' => $randomMinInterval]));
|
||||
new TrackerException(162, [':min' => $randomMinInterval])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -388,8 +432,10 @@ class AnnounceController extends Controller
|
||||
->count();
|
||||
|
||||
// If Users Peer Count On A Single Torrent Is Greater Than X Return Error to Client
|
||||
\throw_if($connections > \config('announce.rate_limit'),
|
||||
new TrackerException(138, [':limit' => \config('announce.rate_limit')]));
|
||||
\throw_if(
|
||||
$connections > \config('announce.rate_limit'),
|
||||
new TrackerException(138, [':limit' => \config('announce.rate_limit')])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -409,8 +455,10 @@ class AnnounceController extends Controller
|
||||
->where('seeder', '=', 0)
|
||||
->count();
|
||||
|
||||
\throw_if($count >= $max,
|
||||
new TrackerException(164, [':max' => $max]));
|
||||
\throw_if(
|
||||
$count >= $max,
|
||||
new TrackerException(164, [':max' => $max])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,733 +0,0 @@
|
||||
<?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 HDVinnie <hdinnovations@protonmail.com>
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Achievements\UserMade100Comments;
|
||||
use App\Achievements\UserMade200Comments;
|
||||
use App\Achievements\UserMade300Comments;
|
||||
use App\Achievements\UserMade400Comments;
|
||||
use App\Achievements\UserMade500Comments;
|
||||
use App\Achievements\UserMade50Comments;
|
||||
use App\Achievements\UserMade600Comments;
|
||||
use App\Achievements\UserMade700Comments;
|
||||
use App\Achievements\UserMade800Comments;
|
||||
use App\Achievements\UserMade900Comments;
|
||||
use App\Achievements\UserMadeComment;
|
||||
use App\Achievements\UserMadeTenComments;
|
||||
use App\Models\Article;
|
||||
use App\Models\Collection;
|
||||
use App\Models\Comment;
|
||||
use App\Models\Playlist;
|
||||
use App\Models\Ticket;
|
||||
use App\Models\Torrent;
|
||||
use App\Models\TorrentRequest;
|
||||
use App\Models\User;
|
||||
use App\Notifications\NewComment;
|
||||
use App\Repositories\ChatRepository;
|
||||
use App\Repositories\TaggedUserRepository;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\RateLimiter;
|
||||
|
||||
/**
|
||||
* @see \Tests\Feature\Http\Controllers\CommentControllerTest
|
||||
*/
|
||||
class CommentController extends Controller
|
||||
{
|
||||
public $tag;
|
||||
|
||||
/**
|
||||
* CommentController Constructor.
|
||||
*/
|
||||
public function __construct(private readonly TaggedUserRepository $taggedUserRepository, private readonly ChatRepository $chatRepository)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Add A Comment To A Collection.
|
||||
*/
|
||||
public function collection(Request $request, int $id): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
$collection = Collection::findOrFail($id);
|
||||
$user = $request->user();
|
||||
|
||||
if (RateLimiter::tooManyAttempts('collection-comment:'.$user->id, \config('unit3d.comment-rate-limit'))) {
|
||||
return \to_route('collection.show', ['id' => $id])
|
||||
->withErrors(\trans('comment.slow-down'));
|
||||
}
|
||||
|
||||
RateLimiter::hit('collection-comment:'.$user->id);
|
||||
|
||||
if ($user->can_comment == 0) {
|
||||
return \to_route('collection.show', ['id' => $collection->id])
|
||||
->withErrors(\trans('comment.rights-revoked'));
|
||||
}
|
||||
|
||||
$comment = new Comment();
|
||||
$comment->content = $request->input('content');
|
||||
$comment->anon = $request->input('anonymous');
|
||||
$comment->user_id = $user->id;
|
||||
$comment->collection_id = $collection->id;
|
||||
|
||||
$v = \validator($comment->toArray(), [
|
||||
'content' => 'required',
|
||||
'user_id' => 'required',
|
||||
'collection_id' => 'required',
|
||||
'anon' => 'required',
|
||||
]);
|
||||
|
||||
if ($v->fails()) {
|
||||
return \to_route('collection.show', ['id' => $collection->id])
|
||||
->withErrors($v->errors());
|
||||
}
|
||||
|
||||
$comment->save();
|
||||
|
||||
$collectionUrl = \href_collection($collection);
|
||||
$profileUrl = \href_profile($user);
|
||||
|
||||
// Auto Shout
|
||||
if ($comment->anon == 0) {
|
||||
$this->chatRepository->systemMessage(
|
||||
\sprintf('[url=%s]%s[/url] has left a comment on collection [url=%s]%s[/url]', $profileUrl, $user->username, $collectionUrl, $collection->name)
|
||||
);
|
||||
} else {
|
||||
$this->chatRepository->systemMessage(
|
||||
\sprintf('An anonymous user has left a comment on collection [url=%s]%s[/url]', $collectionUrl, $collection->name)
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->taggedUserRepository->hasTags($request->input('content'))) {
|
||||
if ($this->taggedUserRepository->contains($request->input('content'), '@here') && $user->group->is_modo) {
|
||||
$users = \collect([]);
|
||||
|
||||
$collection->comments()->get()->each(function ($c, $v) use ($users) {
|
||||
$users->push($c->user);
|
||||
});
|
||||
$this->tag->messageCommentUsers(
|
||||
'collection',
|
||||
$users,
|
||||
$user,
|
||||
'Staff',
|
||||
$comment
|
||||
);
|
||||
} else {
|
||||
$sender = $comment->anon ? 'Anonymous' : $user->username;
|
||||
$this->taggedUserRepository->messageTaggedCommentUsers(
|
||||
'collection',
|
||||
$request->input('content'),
|
||||
$user,
|
||||
$sender,
|
||||
$comment
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Achievements
|
||||
if ($comment->anon == 0) {
|
||||
$user->unlock(new UserMadeComment(), 1);
|
||||
$user->addProgress(new UserMadeTenComments(), 1);
|
||||
$user->addProgress(new UserMade50Comments(), 1);
|
||||
$user->addProgress(new UserMade100Comments(), 1);
|
||||
$user->addProgress(new UserMade200Comments(), 1);
|
||||
$user->addProgress(new UserMade300Comments(), 1);
|
||||
$user->addProgress(new UserMade400Comments(), 1);
|
||||
$user->addProgress(new UserMade500Comments(), 1);
|
||||
$user->addProgress(new UserMade600Comments(), 1);
|
||||
$user->addProgress(new UserMade700Comments(), 1);
|
||||
$user->addProgress(new UserMade800Comments(), 1);
|
||||
$user->addProgress(new UserMade900Comments(), 1);
|
||||
}
|
||||
|
||||
return \to_route('mediahub.collections.show', ['id' => $collection->id, 'hash' => '#comments'])
|
||||
->withSuccess(\trans('comment.added'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store A New Comment To A Article.
|
||||
*/
|
||||
public function article(Request $request, int $id): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
$article = Article::findOrFail($id);
|
||||
$user = $request->user();
|
||||
|
||||
if (RateLimiter::tooManyAttempts('article-comment:'.$user->id, \config('unit3d.comment-rate-limit'))) {
|
||||
return \to_route('articles.show', ['id' => $id])
|
||||
->withErrors(\trans('comment.slow-down'));
|
||||
}
|
||||
|
||||
RateLimiter::hit('article-comment:'.$user->id);
|
||||
|
||||
if ($user->can_comment == 0) {
|
||||
return \to_route('articles.show', ['id' => $article->id])
|
||||
->withErrors(\trans('comment.rights-revoked'));
|
||||
}
|
||||
|
||||
$comment = new Comment();
|
||||
$comment->content = $request->input('content');
|
||||
$comment->anon = $request->input('anonymous');
|
||||
$comment->user_id = $user->id;
|
||||
$comment->article_id = $article->id;
|
||||
|
||||
$v = \validator($comment->toArray(), [
|
||||
'content' => 'required',
|
||||
'user_id' => 'required',
|
||||
'article_id' => 'required',
|
||||
'anon' => 'required',
|
||||
]);
|
||||
|
||||
if ($v->fails()) {
|
||||
return \to_route('articles.show', ['id' => $article->id])
|
||||
->withErrors($v->errors());
|
||||
}
|
||||
|
||||
$comment->save();
|
||||
$articleUrl = \href_article($article);
|
||||
$profileUrl = \href_profile($user);
|
||||
// Auto Shout
|
||||
if ($comment->anon == 0) {
|
||||
$this->chatRepository->systemMessage(
|
||||
\sprintf('[url=%s]%s[/url] has left a comment on article [url=%s]%s[/url]', $profileUrl, $user->username, $articleUrl, $article->title)
|
||||
);
|
||||
} else {
|
||||
$this->chatRepository->systemMessage(
|
||||
\sprintf('An anonymous user has left a comment on article [url=%s]%s[/url]', $articleUrl, $article->title)
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->taggedUserRepository->hasTags($request->input('content'))) {
|
||||
if ($this->taggedUserRepository->contains($request->input('content'), '@here') && $user->group->is_modo) {
|
||||
$users = \collect([]);
|
||||
|
||||
$article->comments()->get()->each(function ($c) use ($users) {
|
||||
$users->push($c->user);
|
||||
});
|
||||
$this->taggedUserRepository->messageCommentUsers(
|
||||
'article',
|
||||
$users,
|
||||
$user,
|
||||
'Staff',
|
||||
$comment
|
||||
);
|
||||
} else {
|
||||
$sender = $comment->anon ? 'Anonymous' : $user->username;
|
||||
$this->taggedUserRepository->messageTaggedCommentUsers(
|
||||
'article',
|
||||
$request->input('content'),
|
||||
$user,
|
||||
$sender,
|
||||
$comment
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Achievements
|
||||
if ($comment->anon == 0) {
|
||||
$user->unlock(new UserMadeComment(), 1);
|
||||
$user->addProgress(new UserMadeTenComments(), 1);
|
||||
$user->addProgress(new UserMade50Comments(), 1);
|
||||
$user->addProgress(new UserMade100Comments(), 1);
|
||||
$user->addProgress(new UserMade200Comments(), 1);
|
||||
$user->addProgress(new UserMade300Comments(), 1);
|
||||
$user->addProgress(new UserMade400Comments(), 1);
|
||||
$user->addProgress(new UserMade500Comments(), 1);
|
||||
$user->addProgress(new UserMade600Comments(), 1);
|
||||
$user->addProgress(new UserMade700Comments(), 1);
|
||||
$user->addProgress(new UserMade800Comments(), 1);
|
||||
$user->addProgress(new UserMade900Comments(), 1);
|
||||
}
|
||||
|
||||
return \to_route('articles.show', ['id' => $article->id])
|
||||
->withSuccess(\trans('comment.added'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store A New Comment To A Playlist.
|
||||
*/
|
||||
public function playlist(Request $request, int $id): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
$playlist = Playlist::findOrFail($id);
|
||||
$user = $request->user();
|
||||
|
||||
if (RateLimiter::tooManyAttempts('playlist-comment:'.$user->id, \config('unit3d.comment-rate-limit'))) {
|
||||
return \to_route('playlists.show', ['id' => $id])
|
||||
->withErrors(\trans('comment.slow-down'));
|
||||
}
|
||||
|
||||
RateLimiter::hit('playlist-comment:'.$user->id);
|
||||
|
||||
if ($user->can_comment == 0) {
|
||||
return \to_route('playlists.show', ['id' => $playlist->id])
|
||||
->withErrors(\trans('comment.rights-revoked'));
|
||||
}
|
||||
|
||||
$comment = new Comment();
|
||||
$comment->content = $request->input('content');
|
||||
$comment->anon = $request->input('anonymous');
|
||||
$comment->user_id = $user->id;
|
||||
$comment->playlist_id = $playlist->id;
|
||||
|
||||
$v = \validator($comment->toArray(), [
|
||||
'content' => 'required',
|
||||
'user_id' => 'required',
|
||||
'playlist_id' => 'required',
|
||||
'anon' => 'required',
|
||||
]);
|
||||
|
||||
if ($v->fails()) {
|
||||
return \to_route('playlists.show', ['id' => $playlist->id])
|
||||
->withErrors($v->errors());
|
||||
}
|
||||
|
||||
$comment->save();
|
||||
$playlistUrl = \href_playlist($playlist);
|
||||
$profileUrl = \href_profile($user);
|
||||
// Auto Shout
|
||||
if ($comment->anon == 0) {
|
||||
$this->chatRepository->systemMessage(
|
||||
\sprintf('[url=%s]%s[/url] has left a comment on playlist [url=%s]%s[/url]', $profileUrl, $user->username, $playlistUrl, $playlist->name)
|
||||
);
|
||||
} else {
|
||||
$this->chatRepository->systemMessage(
|
||||
\sprintf('An anonymous user has left a comment on playlist [url=%s]%s[/url]', $playlistUrl, $playlist->name)
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->taggedUserRepository->hasTags($request->input('content'))) {
|
||||
if ($this->taggedUserRepository->contains($request->input('content'), '@here') && $user->group->is_modo) {
|
||||
$users = \collect([]);
|
||||
|
||||
$playlist->comments()->get()->each(function ($c) use ($users) {
|
||||
$users->push($c->user);
|
||||
});
|
||||
$this->taggedUserRepository->messageCommentUsers(
|
||||
'playlist',
|
||||
$users,
|
||||
$user,
|
||||
'Staff',
|
||||
$comment
|
||||
);
|
||||
} else {
|
||||
$sender = $comment->anon ? 'Anonymous' : $user->username;
|
||||
$this->taggedUserRepository->messageTaggedCommentUsers(
|
||||
'playlist',
|
||||
$request->input('content'),
|
||||
$user,
|
||||
$sender,
|
||||
$comment
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Achievements
|
||||
if ($comment->anon == 0) {
|
||||
$user->unlock(new UserMadeComment(), 1);
|
||||
$user->addProgress(new UserMadeTenComments(), 1);
|
||||
$user->addProgress(new UserMade50Comments(), 1);
|
||||
$user->addProgress(new UserMade100Comments(), 1);
|
||||
$user->addProgress(new UserMade200Comments(), 1);
|
||||
$user->addProgress(new UserMade300Comments(), 1);
|
||||
$user->addProgress(new UserMade400Comments(), 1);
|
||||
$user->addProgress(new UserMade500Comments(), 1);
|
||||
$user->addProgress(new UserMade600Comments(), 1);
|
||||
$user->addProgress(new UserMade700Comments(), 1);
|
||||
$user->addProgress(new UserMade800Comments(), 1);
|
||||
$user->addProgress(new UserMade900Comments(), 1);
|
||||
}
|
||||
|
||||
return \to_route('playlists.show', ['id' => $playlist->id, 'hash' => '#comments'])
|
||||
->withSuccess(\trans('comment.added'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store A New Comment To A Torrent.
|
||||
*/
|
||||
public function torrent(Request $request, int $id): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
$torrent = Torrent::findOrFail($id);
|
||||
$user = $request->user();
|
||||
|
||||
if (RateLimiter::tooManyAttempts('torrent-comment:'.$user->id, \config('unit3d.comment-rate-limit'))) {
|
||||
return \to_route('torrent', ['id' => $torrent->id])
|
||||
->withErrors(\trans('comment.slow-down'));
|
||||
}
|
||||
|
||||
RateLimiter::hit('torrent-comment:'.$user->id);
|
||||
|
||||
if ($user->can_comment == 0) {
|
||||
return \to_route('torrent', ['id' => $torrent->id])
|
||||
->withErrors(\trans('comment.rights-revoked'));
|
||||
}
|
||||
|
||||
$comment = new Comment();
|
||||
$comment->content = $request->input('content');
|
||||
$comment->anon = $request->input('anonymous');
|
||||
$comment->user_id = $user->id;
|
||||
$comment->torrent_id = $torrent->id;
|
||||
|
||||
$v = \validator($comment->toArray(), [
|
||||
'content' => 'required',
|
||||
'user_id' => 'required',
|
||||
'torrent_id' => 'required',
|
||||
'anon' => 'required',
|
||||
]);
|
||||
|
||||
if ($v->fails()) {
|
||||
return \to_route('torrent', ['id' => $torrent->id])
|
||||
->withErrors($v->errors());
|
||||
}
|
||||
|
||||
$comment->save();
|
||||
//Notification
|
||||
if ($user->id != $torrent->user_id) {
|
||||
$torrent->notifyUploader('comment', $comment);
|
||||
}
|
||||
|
||||
$torrentUrl = \href_torrent($torrent);
|
||||
$profileUrl = \href_profile($user);
|
||||
// Auto Shout
|
||||
if ($comment->anon == 0) {
|
||||
$this->chatRepository->systemMessage(
|
||||
\sprintf('[url=%s]%s[/url] has left a comment on Torrent [url=%s]%s[/url]', $profileUrl, $user->username, $torrentUrl, $torrent->name)
|
||||
);
|
||||
} else {
|
||||
$this->chatRepository->systemMessage(
|
||||
\sprintf('An anonymous user has left a comment on torrent [url=%s]%s[/url]', $torrentUrl, $torrent->name)
|
||||
);
|
||||
}
|
||||
|
||||
if ($this->taggedUserRepository->hasTags($request->input('content'))) {
|
||||
if ($this->taggedUserRepository->contains($request->input('content'), '@here') && $user->group->is_modo) {
|
||||
$users = \collect([]);
|
||||
|
||||
$torrent->comments()->get()->each(function ($c) use ($users) {
|
||||
$users->push($c->user);
|
||||
});
|
||||
$this->taggedUserRepository->messageCommentUsers(
|
||||
'torrent',
|
||||
$users,
|
||||
$user,
|
||||
'Staff',
|
||||
$comment
|
||||
);
|
||||
} else {
|
||||
$sender = $comment->anon ? 'Anonymous' : $user->username;
|
||||
$this->taggedUserRepository->messageTaggedCommentUsers(
|
||||
'torrent',
|
||||
$request->input('content'),
|
||||
$user,
|
||||
$sender,
|
||||
$comment
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Achievements
|
||||
if ($comment->anon == 0) {
|
||||
$user->unlock(new UserMadeComment(), 1);
|
||||
$user->addProgress(new UserMadeTenComments(), 1);
|
||||
$user->addProgress(new UserMade50Comments(), 1);
|
||||
$user->addProgress(new UserMade100Comments(), 1);
|
||||
$user->addProgress(new UserMade200Comments(), 1);
|
||||
$user->addProgress(new UserMade300Comments(), 1);
|
||||
$user->addProgress(new UserMade400Comments(), 1);
|
||||
$user->addProgress(new UserMade500Comments(), 1);
|
||||
$user->addProgress(new UserMade600Comments(), 1);
|
||||
$user->addProgress(new UserMade700Comments(), 1);
|
||||
$user->addProgress(new UserMade800Comments(), 1);
|
||||
$user->addProgress(new UserMade900Comments(), 1);
|
||||
}
|
||||
|
||||
return \to_route('torrent', ['id' => $torrent->id, 'hash' => '#comments'])
|
||||
->withSuccess(\trans('comment.added'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store A New Comment To A Request.
|
||||
*/
|
||||
public function request(Request $request, int $id): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
$tr = TorrentRequest::findOrFail($id);
|
||||
$user = $request->user();
|
||||
|
||||
if (RateLimiter::tooManyAttempts('request-comment:'.$user->id, \config('unit3d.comment-rate-limit'))) {
|
||||
return \to_route('request', ['id' => $id])
|
||||
->withErrors(\trans('comment.slow-down'));
|
||||
}
|
||||
|
||||
RateLimiter::hit('request-comment:'.$user->id);
|
||||
|
||||
if ($user->can_comment == 0) {
|
||||
return \to_route('request', ['id' => $tr->id])
|
||||
->withErrors(\trans('comment.rights-revoked'));
|
||||
}
|
||||
|
||||
$comment = new Comment();
|
||||
$comment->content = $request->input('content');
|
||||
$comment->anon = $request->input('anonymous');
|
||||
$comment->user_id = $user->id;
|
||||
$comment->requests_id = $tr->id;
|
||||
|
||||
$v = \validator($comment->toArray(), [
|
||||
'content' => 'required',
|
||||
'user_id' => 'required',
|
||||
'requests_id' => 'required',
|
||||
'anon' => 'required',
|
||||
]);
|
||||
|
||||
if ($v->fails()) {
|
||||
return \to_route('request', ['id' => $tr->id])
|
||||
->withErrors($v->errors());
|
||||
}
|
||||
|
||||
$comment->save();
|
||||
$trUrl = \href_request($tr);
|
||||
$profileUrl = \href_profile($user);
|
||||
// Auto Shout
|
||||
if ($comment->anon == 0) {
|
||||
$this->chatRepository->systemMessage(
|
||||
\sprintf('[url=%s]%s[/url] has left a comment on Request [url=%s]%s[/url]', $profileUrl, $user->username, $trUrl, $tr->name)
|
||||
);
|
||||
} else {
|
||||
$this->chatRepository->systemMessage(
|
||||
\sprintf('An anonymous user has left a comment on Request [url=%s]%s[/url]', $trUrl, $tr->name)
|
||||
);
|
||||
}
|
||||
|
||||
//Notification
|
||||
if ($user->id != $tr->user_id) {
|
||||
$tr->notifyRequester('comment', $comment);
|
||||
}
|
||||
|
||||
if ($this->taggedUserRepository->hasTags($request->input('content'))) {
|
||||
if ($this->taggedUserRepository->contains($request->input('content'), '@here') && $user->group->is_modo) {
|
||||
$users = \collect([]);
|
||||
|
||||
$tr->comments()->get()->each(function ($c) use ($users) {
|
||||
$users->push($c->user);
|
||||
});
|
||||
$this->taggedUserRepository->messageCommentUsers(
|
||||
'request',
|
||||
$users,
|
||||
$user,
|
||||
'Staff',
|
||||
$comment
|
||||
);
|
||||
} else {
|
||||
$sender = $comment->anon ? 'Anonymous' : $user->username;
|
||||
$this->taggedUserRepository->messageTaggedCommentUsers(
|
||||
'request',
|
||||
$request->input('content'),
|
||||
$user,
|
||||
$sender,
|
||||
$comment
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Achievements
|
||||
if ($comment->anon == 0) {
|
||||
$user->unlock(new UserMadeComment(), 1);
|
||||
$user->addProgress(new UserMadeTenComments(), 1);
|
||||
$user->addProgress(new UserMade50Comments(), 1);
|
||||
$user->addProgress(new UserMade100Comments(), 1);
|
||||
$user->addProgress(new UserMade200Comments(), 1);
|
||||
$user->addProgress(new UserMade300Comments(), 1);
|
||||
$user->addProgress(new UserMade400Comments(), 1);
|
||||
$user->addProgress(new UserMade500Comments(), 1);
|
||||
$user->addProgress(new UserMade600Comments(), 1);
|
||||
$user->addProgress(new UserMade700Comments(), 1);
|
||||
$user->addProgress(new UserMade800Comments(), 1);
|
||||
$user->addProgress(new UserMade900Comments(), 1);
|
||||
}
|
||||
|
||||
return \to_route('request', ['id' => $tr->id, 'hash' => '#comments'])
|
||||
->withSuccess(\trans('comment.added'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store A New Comment To A Request.
|
||||
*/
|
||||
public function ticket(Request $request, int $id): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
$ticket = Ticket::findOrFail($id);
|
||||
$user = $request->user();
|
||||
|
||||
if (RateLimiter::tooManyAttempts('ticket-comment:'.$user->id, \config('unit3d.comment-rate-limit'))) {
|
||||
return \to_route('tickets.show', ['id' => $id])
|
||||
->withErrors(\trans('comment.slow-down'));
|
||||
}
|
||||
|
||||
RateLimiter::hit('ticket-comment:'.$user->id);
|
||||
|
||||
$comment = new Comment();
|
||||
$comment->content = $request->input('content');
|
||||
$comment->anon = 0;
|
||||
$comment->user_id = $user->id;
|
||||
$comment->ticket_id = $ticket->id;
|
||||
|
||||
$v = \validator($comment->toArray(), [
|
||||
'content' => 'required',
|
||||
'user_id' => 'required',
|
||||
'ticket_id' => 'required',
|
||||
'anon' => 'required',
|
||||
]);
|
||||
|
||||
if ($v->fails()) {
|
||||
return \to_route('tickets.show', ['id' => $id])
|
||||
->withErrors($v->errors());
|
||||
}
|
||||
|
||||
if ($user->id != $ticket->user_id) {
|
||||
$ticket->user_read = 0;
|
||||
}
|
||||
|
||||
if ($user->id == $ticket->user_id) {
|
||||
$ticket->staff_read = 0;
|
||||
}
|
||||
|
||||
$comment->save();
|
||||
$ticket->save();
|
||||
|
||||
return \to_route('tickets.show', ['id' => $ticket->id])
|
||||
->withSuccess(\trans('comment.added'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store A New Comment To A Torrent Via Quick Thanks.
|
||||
*/
|
||||
public function quickthanks(Request $request, int $id): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
$torrent = Torrent::findOrFail($id);
|
||||
$user = $request->user();
|
||||
|
||||
if (RateLimiter::tooManyAttempts('torrent-comment:'.$user->id, \config('unit3d.comment-rate-limit'))) {
|
||||
return \to_route('torrent', ['id' => $torrent->id])
|
||||
->withErrors(\trans('comment.slow-down'));
|
||||
}
|
||||
|
||||
RateLimiter::hit('torrent-comment:'.$user->id);
|
||||
|
||||
if ($user->can_comment == 0) {
|
||||
return \to_route('torrent', ['id' => $torrent->id])
|
||||
->withErrors(\trans('comment.rights-revoked'));
|
||||
}
|
||||
|
||||
$comment = new Comment();
|
||||
|
||||
if ($torrent->anon === 1) {
|
||||
$thankArray = [
|
||||
'Thanks for the upload! :thumbsup_tone2:',
|
||||
'Time and effort is much appreciated :thumbsup_tone2:',
|
||||
'Great upload! :fire:', 'Thank you :smiley:',
|
||||
];
|
||||
} else {
|
||||
$uploader = User::where('id', '=', $torrent->user_id)->first();
|
||||
$uploaderUrl = \href_profile($uploader);
|
||||
|
||||
$thankArray = [
|
||||
\sprintf('Thanks for the upload [url=%s][color=%s][b]%s[/b][/color][/url] :vulcan_tone2:', $uploaderUrl, $uploader->group->color, $uploader->username),
|
||||
\sprintf('Beautiful upload [url=%s][color=%s][b]%s[/b][/color][/url] :fire:', $uploaderUrl, $uploader->group->color, $uploader->username),
|
||||
\sprintf('Cheers [url=%s][color=%s][b]%s[/b][/color][/url] for the upload :beers:', $uploaderUrl, $uploader->group->color, $uploader->username),
|
||||
];
|
||||
}
|
||||
|
||||
$selected = random_int(0, (\is_countable($thankArray) ? \count($thankArray) : 0) - 1);
|
||||
$comment->content = $thankArray[$selected];
|
||||
$comment->user_id = $user->id;
|
||||
$comment->torrent_id = $torrent->id;
|
||||
|
||||
$v = \validator($comment->toArray(), [
|
||||
'content' => 'required',
|
||||
'user_id' => 'required',
|
||||
'torrent_id' => 'required',
|
||||
]);
|
||||
|
||||
if ($v->fails()) {
|
||||
return \to_route('torrent', ['id' => $torrent->id])
|
||||
->withErrors($v->errors());
|
||||
}
|
||||
|
||||
$comment->save();
|
||||
|
||||
// Achievements
|
||||
if ($comment->anon == 0) {
|
||||
$user->unlock(new UserMadeComment(), 1);
|
||||
$user->addProgress(new UserMadeTenComments(), 1);
|
||||
$user->addProgress(new UserMade50Comments(), 1);
|
||||
$user->addProgress(new UserMade100Comments(), 1);
|
||||
$user->addProgress(new UserMade200Comments(), 1);
|
||||
$user->addProgress(new UserMade300Comments(), 1);
|
||||
$user->addProgress(new UserMade400Comments(), 1);
|
||||
$user->addProgress(new UserMade500Comments(), 1);
|
||||
$user->addProgress(new UserMade600Comments(), 1);
|
||||
$user->addProgress(new UserMade700Comments(), 1);
|
||||
$user->addProgress(new UserMade800Comments(), 1);
|
||||
$user->addProgress(new UserMade900Comments(), 1);
|
||||
}
|
||||
|
||||
//Notification
|
||||
if ($user->id != $torrent->user_id) {
|
||||
User::find($torrent->user_id)->notify(new NewComment('torrent', $comment));
|
||||
}
|
||||
|
||||
// Auto Shout
|
||||
$torrentUrl = \href_torrent($torrent);
|
||||
$profileUrl = \href_profile($user);
|
||||
$this->chatRepository->systemMessage(
|
||||
\sprintf('[url=%s]%s[/url] has left a comment on Torrent [url=%s]%s[/url]', $profileUrl, $user->username, $torrentUrl, $torrent->name)
|
||||
);
|
||||
|
||||
return \to_route('torrent', ['id' => $torrent->id])
|
||||
->withSuccess(\trans('comment.added'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit A Comment.
|
||||
*/
|
||||
public function editComment(Request $request, int $commentId): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
$user = $request->user();
|
||||
$comment = Comment::findOrFail($commentId);
|
||||
|
||||
\abort_unless($user->group->is_modo || $user->id == $comment->user_id, 403);
|
||||
$comment->content = $request->input('comment-edit');
|
||||
|
||||
$v = \validator($comment->toArray(), [
|
||||
'content' => 'required',
|
||||
]);
|
||||
|
||||
if ($v->fails()) {
|
||||
return \redirect()->back()
|
||||
->withErrors($v->errors());
|
||||
}
|
||||
|
||||
$comment->save();
|
||||
|
||||
return \redirect()->back()->withSuccess(\trans('comment.edited'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete A Comment.
|
||||
*/
|
||||
public function deleteComment(Request $request, int $commentId): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
$user = $request->user();
|
||||
$comment = Comment::findOrFail($commentId);
|
||||
|
||||
\abort_unless($user->group->is_modo || $user->id == $comment->user_id, 403);
|
||||
$comment->delete();
|
||||
|
||||
return \redirect()->back()->withSuccess(\trans('comment.deleted'));
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ class FollowController extends Controller
|
||||
->withErrors(\trans('user.follow-yourself'));
|
||||
}
|
||||
|
||||
if (! $request->user()->isFollowing($user->id)) {
|
||||
if ($request->user()->follows()->following($user->id)->doesntExist()) {
|
||||
$follow = new Follow();
|
||||
$follow->user_id = $request->user()->id;
|
||||
$follow->target_id = $user->id;
|
||||
@@ -60,8 +60,8 @@ class FollowController extends Controller
|
||||
{
|
||||
$user = User::where('username', '=', $username)->firstOrFail();
|
||||
|
||||
if ($request->user()->isFollowing($user->id)) {
|
||||
$follow = $request->user()->follows()->where('target_id', '=', $user->id)->first();
|
||||
if ($request->user()->follows()->following($user->id)->exists()) {
|
||||
$follow = $request->user()->follows()->following($user->id)->first();
|
||||
$follow->delete();
|
||||
if ($user->acceptsNotification($request->user(), $user, 'account', 'show_account_unfollow')) {
|
||||
$user->notify(new NewUnfollow('user', $request->user(), $user, $follow));
|
||||
|
||||
@@ -109,7 +109,7 @@ class HomeController extends Controller
|
||||
$groups = \cache()->remember('user-groups', $expiresAt, fn () => Group::select(['name', 'color', 'effect', 'icon'])->oldest('position')->get());
|
||||
|
||||
// Featured Torrents Block
|
||||
$featured = \cache()->remember('latest_featured', $expiresAt, fn () => FeaturedTorrent::with('torrent', 'user')->get());
|
||||
$featured = \cache()->remember('latest_featured', $expiresAt, fn () => FeaturedTorrent::with('torrent', 'torrent.resolution', 'torrent.type', 'torrent.category', 'user', 'user.group')->get());
|
||||
|
||||
// Latest Poll Block
|
||||
$poll = \cache()->remember('latest_poll', $expiresAt, fn () => Poll::latest()->first());
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\BlacklistClient;
|
||||
use App\Models\Group;
|
||||
use App\Models\Internal;
|
||||
use App\Models\Page;
|
||||
@@ -47,7 +48,12 @@ class PageController extends Controller
|
||||
*/
|
||||
public function staff(): \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
{
|
||||
$staff = Group::with('users:id,username,group_id,title')->where('is_modo', '=', 1)->orWhere('is_admin', '=', 1)->get()->sortByDesc('position');
|
||||
$staff = Group::query()
|
||||
->with('users:id,username,group_id,title')
|
||||
->where('is_modo', '=', 1)
|
||||
->orWhere('is_admin', '=', 1)
|
||||
->get()
|
||||
->sortByDesc('position');
|
||||
|
||||
return \view('page.staff', ['staff' => $staff]);
|
||||
}
|
||||
@@ -57,19 +63,22 @@ class PageController extends Controller
|
||||
*/
|
||||
public function internal(): \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
{
|
||||
$internals = Internal::with('users')->get()->sortBy('name');
|
||||
$internals = Internal::query()
|
||||
->with('users')
|
||||
->get()
|
||||
->sortBy('name');
|
||||
|
||||
return \view('page.internal', ['internals' => $internals]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show Blacklist Page.
|
||||
* Show Client-Blacklist Page.
|
||||
*/
|
||||
public function blacklist(): \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
public function clientblacklist(): \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
{
|
||||
$clients = \config('client-blacklist.clients', []);
|
||||
$clients = BlacklistClient::all();
|
||||
|
||||
return \view('page.blacklist', ['clients' => $clients]);
|
||||
return \view('page.blacklist.client', ['clients' => $clients]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -156,7 +156,8 @@ class RssController extends Controller
|
||||
|
||||
$rss = Rss::query()
|
||||
->where('id', '=', $id)
|
||||
->where(fn ($query) => $query
|
||||
->where(
|
||||
fn ($query) => $query
|
||||
->where('user_id', '=', $user->id)
|
||||
->orWhere('is_private', '=', 0)
|
||||
)
|
||||
@@ -164,33 +165,37 @@ class RssController extends Controller
|
||||
|
||||
$search = $rss->object_torrent;
|
||||
|
||||
$torrents = Torrent::with('user', 'category', 'type', 'resolution')
|
||||
->when($search->search !== null, fn ($query) => $query->ofName($search->search))
|
||||
->when($search->description !== null, fn ($query) => $query->ofDescription($search->description)->orWhere->ofMediainfo($search->description))
|
||||
->when($search->uploader !== null, fn ($query) => $query->ofUploader($search->uploader))
|
||||
->when($search->categories !== null, fn ($query) => $query->ofCategory($search->categories))
|
||||
->when($search->types !== null, fn ($query) => $query->ofType($search->types))
|
||||
->when($search->resolutions !== null, fn ($query) => $query->ofResolution($search->resolutions))
|
||||
->when($search->genres !== null, fn ($query) => $query->ofGenre($search->genres))
|
||||
->when($search->tmdb !== null, fn ($query) => $query->ofTmdb((int) $search->tmdb))
|
||||
->when($search->imdb !== null, fn ($query) => $query->ofImdb((int) (\preg_match('/tt0*(?=(\d{7,}))/', $search->imdb, $matches) ? $matches[1] : $search->imdb)))
|
||||
->when($search->tvdb !== null, fn ($query) => $query->ofTvdb((int) $search->tvdb))
|
||||
->when($search->mal !== null, fn ($query) => $query->ofMal((int) $search->mal))
|
||||
->when($search->freeleech !== null, fn ($query) => $query->ofFreeleech([25, 50, 75, 100]))
|
||||
->when($search->doubleupload !== null, fn ($query) => $query->doubleup())
|
||||
->when($search->featured !== null, fn ($query) => $query->featured())
|
||||
->when($search->stream !== null, fn ($query) => $query->streamOptimized())
|
||||
->when($search->sd !== null, fn ($query) => $query->sd())
|
||||
->when($search->highspeed !== null, fn ($query) => $query->highspeed())
|
||||
->when($search->bookmark !== null, fn ($query) => $query->bookmarkedBy($user))
|
||||
->when($search->internal !== null, fn ($query) => $query->internal())
|
||||
->when($search->personalrelease !== null, fn ($query) => $query->personalRelease())
|
||||
->when($search->alive !== null, fn ($query) => $query->alive())
|
||||
->when($search->dying !== null, fn ($query) => $query->dying())
|
||||
->when($search->dead !== null, fn ($query) => $query->dead())
|
||||
->orderByDesc('bumped_at')
|
||||
->take(50)
|
||||
->get();
|
||||
$cacheKey = \md5(\sprintf('%s.%s.%s', $rss->id, $user->id, $user->rsskey));
|
||||
|
||||
$torrents = \cache()->remember($cacheKey, 300, function () use ($search, $user) {
|
||||
return Torrent::with('user', 'category', 'type', 'resolution')
|
||||
->when($search->search !== null, fn ($query) => $query->ofName($search->search))
|
||||
->when($search->description !== null, fn ($query) => $query->ofDescription($search->description)->orWhere->ofMediainfo($search->description))
|
||||
->when($search->uploader !== null, fn ($query) => $query->ofUploader($search->uploader))
|
||||
->when($search->categories !== null, fn ($query) => $query->ofCategory($search->categories))
|
||||
->when($search->types !== null, fn ($query) => $query->ofType($search->types))
|
||||
->when($search->resolutions !== null, fn ($query) => $query->ofResolution($search->resolutions))
|
||||
->when($search->genres !== null, fn ($query) => $query->ofGenre($search->genres))
|
||||
->when($search->tmdb !== null, fn ($query) => $query->ofTmdb((int) $search->tmdb))
|
||||
->when($search->imdb !== null, fn ($query) => $query->ofImdb((int) (\preg_match('/tt0*(?=(\d{7,}))/', $search->imdb, $matches) ? $matches[1] : $search->imdb)))
|
||||
->when($search->tvdb !== null, fn ($query) => $query->ofTvdb((int) $search->tvdb))
|
||||
->when($search->mal !== null, fn ($query) => $query->ofMal((int) $search->mal))
|
||||
->when($search->freeleech !== null, fn ($query) => $query->ofFreeleech([25, 50, 75, 100]))
|
||||
->when($search->doubleupload !== null, fn ($query) => $query->doubleup())
|
||||
->when($search->featured !== null, fn ($query) => $query->featured())
|
||||
->when($search->stream !== null, fn ($query) => $query->streamOptimized())
|
||||
->when($search->sd !== null, fn ($query) => $query->sd())
|
||||
->when($search->highspeed !== null, fn ($query) => $query->highspeed())
|
||||
->when($search->bookmark !== null, fn ($query) => $query->bookmarkedBy($user))
|
||||
->when($search->internal !== null, fn ($query) => $query->internal())
|
||||
->when($search->personalrelease !== null, fn ($query) => $query->personalRelease())
|
||||
->when($search->alive !== null, fn ($query) => $query->alive())
|
||||
->when($search->dying !== null, fn ($query) => $query->dying())
|
||||
->when($search->dead !== null, fn ($query) => $query->dead())
|
||||
->orderByDesc('bumped_at')
|
||||
->take(50)
|
||||
->get();
|
||||
});
|
||||
|
||||
return \response()->view('rss.show', [
|
||||
'torrents' => $torrents,
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
<?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 HDVinnie <hdinnovations@protonmail.com>
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Staff;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\BlacklistClient;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* @see \Tests\Feature\Http\Controllers\Staff\GroupControllerTest
|
||||
*/
|
||||
class BlacklistClientController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display All Blacklisted Clients.
|
||||
*/
|
||||
public function index(Request $request): \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
{
|
||||
\abort_unless($request->user()->group->is_modo, 403);
|
||||
|
||||
$clients = BlacklistClient::latest()->get();
|
||||
|
||||
return \view('Staff.blacklist.clients.index', ['clients' => $clients]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Blacklisted Client Edit Form.
|
||||
*/
|
||||
public function edit(Request $request, int $id): \Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
|
||||
{
|
||||
\abort_unless($request->user()->group->is_modo, 403);
|
||||
|
||||
$client = BlacklistClient::findOrFail($id);
|
||||
|
||||
return \view('Staff.blacklist.clients.edit', ['client' => $client]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit A Blacklisted Client.
|
||||
*/
|
||||
public function update(Request $request, int $id): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
\abort_unless($request->user()->group->is_modo, 403);
|
||||
|
||||
$client = BlacklistClient::findOrFail($id);
|
||||
$client->name = $request->input('name');
|
||||
$client->reason = $request->input('reason');
|
||||
|
||||
$v = \validator($client->toArray(), [
|
||||
'name' => 'required|string',
|
||||
'reason' => 'sometimes|string',
|
||||
]);
|
||||
|
||||
if ($v->fails()) {
|
||||
return \to_route('staff.blacklists.clients.index')
|
||||
->withErrors($v->errors());
|
||||
}
|
||||
|
||||
$client->save();
|
||||
|
||||
return \to_route('staff.blacklists.clients.index')
|
||||
->withSuccess('Blacklisted Client Was Updated Successfully!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Blacklisted Client Add Form.
|
||||
*/
|
||||
public function create(): \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
{
|
||||
return \view('Staff.blacklist.clients.create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store A New Blacklisted Client.
|
||||
*/
|
||||
public function store(Request $request): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
\abort_unless($request->user()->group->is_admin, 403);
|
||||
|
||||
$client = new BlacklistClient();
|
||||
$client->name = $request->input('name');
|
||||
$client->reason = $request->input('reason');
|
||||
|
||||
$v = \validator($client->toArray(), [
|
||||
'name' => 'required|string|unique:blacklist_clients',
|
||||
'reason' => 'sometimes|string',
|
||||
]);
|
||||
|
||||
if ($v->fails()) {
|
||||
return \to_route('staff.blacklists.clients.index')
|
||||
->withErrors($v->errors());
|
||||
}
|
||||
|
||||
$client->save();
|
||||
|
||||
return \to_route('staff.blacklists.clients.index')
|
||||
->withSuccess('Blacklisted Client Stored Successfully!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete A Blacklisted Client.
|
||||
*/
|
||||
public function destroy(Request $request, int $id): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
\abort_unless($request->user()->group->is_admin, 403);
|
||||
|
||||
$client = BlacklistClient::findOrFail($id);
|
||||
$client->delete();
|
||||
|
||||
return \to_route('staff.blacklists.clients.index')
|
||||
->withSuccess('Blacklisted Client Destroyed Successfully!');
|
||||
}
|
||||
}
|
||||
@@ -14,8 +14,8 @@
|
||||
namespace App\Http\Controllers\Staff;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\History;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Models\Group;
|
||||
use App\Models\User;
|
||||
|
||||
/**
|
||||
* @see \Tests\Feature\Http\Controllers\Staff\CheaterControllerTest
|
||||
@@ -27,20 +27,19 @@ class CheaterController extends Controller
|
||||
*/
|
||||
public function index(): \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
{
|
||||
$cheaters = History::with('user')
|
||||
->select(['*'])
|
||||
->join(
|
||||
DB::raw('(SELECT MAX(id) AS id FROM history GROUP BY history.user_id) AS unique_history'),
|
||||
function ($join) {
|
||||
$join->on('history.id', '=', 'unique_history.id');
|
||||
}
|
||||
)
|
||||
->where('seeder', '=', 0)
|
||||
->where('active', '=', 0)
|
||||
->where('seedtime', '=', 0)
|
||||
->where('actual_downloaded', '=', 0)
|
||||
->where('actual_uploaded', '=', 0)
|
||||
->whereNull('completed_at')
|
||||
$bannedGroup = \cache()->rememberForever('banned_group', fn () => Group::where('slug', '=', 'banned')->pluck('id'));
|
||||
|
||||
$cheaters = User::query()
|
||||
->whereHas('history', function ($query) {
|
||||
$query->where('seeder', '=', 0);
|
||||
$query->where('active', '=', 0);
|
||||
$query->where('seedtime', '=', 0);
|
||||
$query->where('actual_downloaded', '=', 0);
|
||||
$query->where('actual_uploaded', '=', 0);
|
||||
$query->whereNull('completed_at');
|
||||
})
|
||||
->where('group_id', '!=', $bannedGroup[0]) // Banned Users
|
||||
->where('id', '!=', 1) // System
|
||||
->latest()
|
||||
->paginate(25);
|
||||
|
||||
|
||||
@@ -35,26 +35,32 @@ class HomeController extends Controller
|
||||
// User Info
|
||||
$bannedGroup = \cache()->rememberForever('banned_group', fn () => Group::where('slug', '=', 'banned')->pluck('id'));
|
||||
$validatingGroup = \cache()->rememberForever('validating_group', fn () => Group::where('slug', '=', 'validating')->pluck('id'));
|
||||
$users = DB::table('users')
|
||||
->selectRaw('count(*) as total')
|
||||
->selectRaw(\sprintf('count(case when group_id = %s then 1 end) as banned', $bannedGroup[0]))
|
||||
->selectRaw(\sprintf('count(case when group_id = %s then 1 end) as validating', $validatingGroup[0]))
|
||||
->first();
|
||||
$users = \cache()->remember('dashboard_users', 300, function () use ($bannedGroup, $validatingGroup) {
|
||||
return DB::table('users')
|
||||
->selectRaw('count(*) as total')
|
||||
->selectRaw(\sprintf('count(case when group_id = %s then 1 end) as banned', $bannedGroup[0]))
|
||||
->selectRaw(\sprintf('count(case when group_id = %s then 1 end) as validating', $validatingGroup[0]))
|
||||
->first();
|
||||
});
|
||||
|
||||
// Torrent Info
|
||||
$torrents = DB::table('torrents')
|
||||
->selectRaw('count(*) as total')
|
||||
->selectRaw('count(case when status = 0 then 1 end) as pending')
|
||||
->selectRaw('count(case when status = 2 then 1 end) as rejected')
|
||||
->selectRaw('count(case when status = 3 then 1 end) as postponed')
|
||||
->first();
|
||||
$torrents = \cache()->remember('dashboard_torrents', 300, function () {
|
||||
return DB::table('torrents')
|
||||
->selectRaw('count(*) as total')
|
||||
->selectRaw('count(case when status = 0 then 1 end) as pending')
|
||||
->selectRaw('count(case when status = 2 then 1 end) as rejected')
|
||||
->selectRaw('count(case when status = 3 then 1 end) as postponed')
|
||||
->first();
|
||||
});
|
||||
|
||||
// Peers Info
|
||||
$peers = DB::table('peers')
|
||||
->selectRaw('count(*) as total')
|
||||
->selectRaw('count(case when seeder = 0 then 1 end) as leechers')
|
||||
->selectRaw('count(case when seeder = 1 then 1 end) as seeders')
|
||||
->first();
|
||||
$peers = \cache()->remember('dashboard_peers', 300, function () {
|
||||
return DB::table('peers')
|
||||
->selectRaw('count(*) as total')
|
||||
->selectRaw('count(case when seeder = 0 then 1 end) as leechers')
|
||||
->selectRaw('count(case when seeder = 1 then 1 end) as seeders')
|
||||
->first();
|
||||
});
|
||||
|
||||
// Reports Info
|
||||
$reports = DB::table('reports')
|
||||
|
||||
@@ -39,7 +39,7 @@ class SubscriptionController extends Controller
|
||||
$params = ['id' => $topic->id];
|
||||
}
|
||||
|
||||
if (! $request->user()->isSubscribed('topic', $topic->id)) {
|
||||
if ($request->user()->subscriptions()->ofTopic($topic->id)->doesntExist()) {
|
||||
$subscription = new Subscription();
|
||||
$subscription->user_id = $request->user()->id;
|
||||
$subscription->topic_id = $topic->id;
|
||||
@@ -69,8 +69,8 @@ class SubscriptionController extends Controller
|
||||
$params = ['id' => $topic->id];
|
||||
}
|
||||
|
||||
if ($request->user()->isSubscribed('topic', $topic->id)) {
|
||||
$subscription = $request->user()->subscriptions()->where('topic_id', '=', $topic->id)->first();
|
||||
if ($request->user()->subscriptions()->ofTopic($topic->id)->exists()) {
|
||||
$subscription = $request->user()->subscriptions()->ofTopic($topic->id)->first();
|
||||
$subscription->delete();
|
||||
|
||||
return \to_route($logger, $params)
|
||||
@@ -97,7 +97,7 @@ class SubscriptionController extends Controller
|
||||
$params = ['id' => $forum->id];
|
||||
}
|
||||
|
||||
if (! $request->user()->isSubscribed('forum', $forum->id)) {
|
||||
if ($request->user()->subscriptions()->ofForum($forum->id)->doesntExist()) {
|
||||
$subscription = new Subscription();
|
||||
$subscription->user_id = $request->user()->id;
|
||||
$subscription->forum_id = $forum->id;
|
||||
@@ -127,8 +127,8 @@ class SubscriptionController extends Controller
|
||||
$params = ['id' => $forum->id];
|
||||
}
|
||||
|
||||
if ($request->user()->isSubscribed('forum', $forum->id)) {
|
||||
$subscription = $request->user()->subscriptions()->where('forum_id', '=', $forum->id)->first();
|
||||
if ($request->user()->subscriptions()->ofForum($forum->id)->exists()) {
|
||||
$subscription = $request->user()->subscriptions()->ofForum($forum->id)->first();
|
||||
$subscription->delete();
|
||||
|
||||
return \to_route($logger, $params)
|
||||
|
||||
@@ -58,7 +58,9 @@ class UserEarningController extends Controller
|
||||
|
||||
$dying = $distinctSeeds
|
||||
->clone()
|
||||
->whereHas('torrent', fn ($query) => $query
|
||||
->whereHas(
|
||||
'torrent',
|
||||
fn ($query) => $query
|
||||
->where('seeders', '=', 1)
|
||||
->where('times_completed', '>=', 3)
|
||||
)
|
||||
@@ -71,7 +73,9 @@ class UserEarningController extends Controller
|
||||
|
||||
$old = $distinctSeeds
|
||||
->clone()
|
||||
->whereHas('torrent', fn ($query) => $query
|
||||
->whereHas(
|
||||
'torrent',
|
||||
fn ($query) => $query
|
||||
->where('created_at', '<', Carbon::now()->subMonths(6)->toDateTimeString())
|
||||
->where('created_at', '>', Carbon::now()->subYear()->toDateTimeString()),
|
||||
)
|
||||
@@ -84,7 +88,9 @@ class UserEarningController extends Controller
|
||||
|
||||
$large = $distinctSeeds
|
||||
->clone()
|
||||
->whereHas('torrent', fn ($query) => $query
|
||||
->whereHas(
|
||||
'torrent',
|
||||
fn ($query) => $query
|
||||
->where('size', '>=', $this->byteUnits->bytesFromUnit('25GiB'))
|
||||
->where('size', '<', $this->byteUnits->bytesFromUnit('100GiB'))
|
||||
)
|
||||
@@ -92,7 +98,9 @@ class UserEarningController extends Controller
|
||||
|
||||
$regular = $distinctSeeds
|
||||
->clone()
|
||||
->whereHas('torrent', fn ($query) => $query
|
||||
->whereHas(
|
||||
'torrent',
|
||||
fn ($query) => $query
|
||||
->where('size', '>=', $this->byteUnits->bytesFromUnit('1GiB'))
|
||||
->where('size', '<', $this->byteUnits->bytesFromUnit('25GiB'))
|
||||
)
|
||||
|
||||
@@ -42,7 +42,8 @@ class UserGiftController extends Controller
|
||||
|
||||
$gifttransactions = BonTransactions::query()
|
||||
->with(['senderObj', 'receiverObj'])
|
||||
->where(fn ($query) => $query
|
||||
->where(
|
||||
fn ($query) => $query
|
||||
->where('sender', '=', $user->id)
|
||||
->orwhere('receiver', '=', $user->id)
|
||||
)
|
||||
@@ -118,7 +119,8 @@ class UserGiftController extends Controller
|
||||
}
|
||||
|
||||
$this->chatRepository->systemMessage(
|
||||
\sprintf('[url=%s]%s[/url] has gifted %s BON to [url=%s]%s[/url]',
|
||||
\sprintf(
|
||||
'[url=%s]%s[/url] has gifted %s BON to [url=%s]%s[/url]',
|
||||
\href_profile($user),
|
||||
$user->username,
|
||||
$value,
|
||||
|
||||
@@ -39,7 +39,8 @@ class UserTipController extends Controller
|
||||
$userbon = $user->getSeedbonus();
|
||||
$bontransactions = BonTransactions::query()
|
||||
->with(['senderObj', 'receiverObj'])
|
||||
->where(fn ($query) => $query
|
||||
->where(
|
||||
fn ($query) => $query
|
||||
->where('sender', '=', $user->id)
|
||||
->orwhere('receiver', '=', $user->id)
|
||||
)
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
<?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 HDVinnie <hdinnovations@protonmail.com>
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0
|
||||
*/
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
|
||||
use App\Achievements\UserMade100Comments;
|
||||
use App\Achievements\UserMade200Comments;
|
||||
use App\Achievements\UserMade300Comments;
|
||||
use App\Achievements\UserMade400Comments;
|
||||
use App\Achievements\UserMade500Comments;
|
||||
use App\Achievements\UserMade50Comments;
|
||||
use App\Achievements\UserMade600Comments;
|
||||
use App\Achievements\UserMade700Comments;
|
||||
use App\Achievements\UserMade800Comments;
|
||||
use App\Achievements\UserMade900Comments;
|
||||
use App\Achievements\UserMadeComment;
|
||||
use App\Achievements\UserMadeTenComments;
|
||||
use App\Models\User;
|
||||
use App\Notifications\NewComment;
|
||||
use App\Repositories\TaggedUserRepository;
|
||||
use Livewire\Component;
|
||||
use voku\helper\AntiXSS;
|
||||
|
||||
class Comment extends Component
|
||||
{
|
||||
public $comment;
|
||||
|
||||
public $anon = false;
|
||||
|
||||
private TaggedUserRepository $taggedUserRepository;
|
||||
|
||||
public \Illuminate\Contracts\Auth\Authenticatable|\App\Models\User $user;
|
||||
|
||||
protected $listeners = [
|
||||
'refresh' => '$refresh',
|
||||
];
|
||||
|
||||
protected $validationAttributes = [
|
||||
'replyState.content' => 'reply',
|
||||
];
|
||||
|
||||
public $isReplying = false;
|
||||
|
||||
public $replyState = [
|
||||
'content' => '',
|
||||
];
|
||||
|
||||
public $isEditing = false;
|
||||
|
||||
public $editState = [
|
||||
'content' => '',
|
||||
];
|
||||
|
||||
final public function mount(TaggedUserRepository $taggedUserRepository): void
|
||||
{
|
||||
$this->taggedUserRepository = $taggedUserRepository;
|
||||
$this->user = \auth()->user();
|
||||
}
|
||||
|
||||
final public function updatedIsEditing($isEditing): void
|
||||
{
|
||||
if (! $isEditing) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->editState = [
|
||||
'content' => $this->comment->content,
|
||||
];
|
||||
}
|
||||
|
||||
final public function editComment(): void
|
||||
{
|
||||
if (\auth()->user()->id !== $this->comment->user_id || ! \auth()->user()->group->is_modo) {
|
||||
$this->dispatchBrowserEvent('error', ['type' => 'error', 'message' => 'Permission Denied!']);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->comment->update((new AntiXSS())->xss_clean($this->editState));
|
||||
|
||||
$this->isEditing = false;
|
||||
}
|
||||
|
||||
final public function deleteComment(): void
|
||||
{
|
||||
if (\auth()->user()->id !== $this->comment->user_id || ! \auth()->user()->group->is_modo) {
|
||||
$this->dispatchBrowserEvent('error', ['type' => 'error', 'message' => 'Permission Denied!']);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->comment->delete();
|
||||
|
||||
$this->emitUp('refresh');
|
||||
}
|
||||
|
||||
final public function postReply(): void
|
||||
{
|
||||
if (\auth()->user()->can_comment === 0) {
|
||||
$this->dispatchBrowserEvent('error', ['type' => 'error', 'message' => \trans('comment.rights-revoked')]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (! $this->comment->isParent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->validate([
|
||||
'replyState.content' => 'required',
|
||||
]);
|
||||
|
||||
$reply = $this->comment->children()->make((new AntiXSS())->xss_clean($this->replyState));
|
||||
$reply->user()->associate(\auth()->user());
|
||||
$reply->commentable()->associate($this->comment->commentable);
|
||||
$reply->anon = $this->anon;
|
||||
$reply->save();
|
||||
|
||||
$this->replyState = [
|
||||
'content' => '',
|
||||
];
|
||||
|
||||
// Achievements
|
||||
if ($reply->anon === 0) {
|
||||
$this->user->unlock(new UserMadeComment(), 1);
|
||||
$this->user->addProgress(new UserMadeTenComments(), 1);
|
||||
$this->user->addProgress(new UserMade50Comments(), 1);
|
||||
$this->user->addProgress(new UserMade100Comments(), 1);
|
||||
$this->user->addProgress(new UserMade200Comments(), 1);
|
||||
$this->user->addProgress(new UserMade300Comments(), 1);
|
||||
$this->user->addProgress(new UserMade400Comments(), 1);
|
||||
$this->user->addProgress(new UserMade500Comments(), 1);
|
||||
$this->user->addProgress(new UserMade600Comments(), 1);
|
||||
$this->user->addProgress(new UserMade700Comments(), 1);
|
||||
$this->user->addProgress(new UserMade800Comments(), 1);
|
||||
$this->user->addProgress(new UserMade900Comments(), 1);
|
||||
}
|
||||
|
||||
//Notification
|
||||
if ($this->user->id !== $this->comment->user_id) {
|
||||
User::find($this->comment->user_id)->notify(new NewComment($this->comment, $reply));
|
||||
}
|
||||
|
||||
// Tagging
|
||||
if ($this->taggedUserRepository->hasTags($this->replyState)) {
|
||||
if ($this->user->group->is_modo && $this->taggedUserRepository->contains($this->replyState, '@here')) {
|
||||
$users = \collect([]);
|
||||
|
||||
$this->comment->children()->get()->each(function ($c) use ($users) {
|
||||
$users->push($c->user);
|
||||
});
|
||||
$this->taggedUserRepository->messageCommentUsers(
|
||||
$this->comment,
|
||||
$users,
|
||||
$this->user,
|
||||
'Staff',
|
||||
$reply
|
||||
);
|
||||
} else {
|
||||
$sender = $reply->anon !== 0 ? $this->user->username : 'Anonymous';
|
||||
$this->taggedUserRepository->messageTaggedCommentUsers(
|
||||
$this->comment,
|
||||
$this->replyState[],
|
||||
$this->user,
|
||||
$sender,
|
||||
$reply
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$this->isReplying = false;
|
||||
|
||||
$this->emitSelf('refresh');
|
||||
}
|
||||
|
||||
final public function render(): \Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Contracts\Foundation\Application
|
||||
{
|
||||
return \view('livewire.comment');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
<?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 HDVinnie <hdinnovations@protonmail.com>
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0
|
||||
*/
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
|
||||
use App\Achievements\UserMade100Comments;
|
||||
use App\Achievements\UserMade200Comments;
|
||||
use App\Achievements\UserMade300Comments;
|
||||
use App\Achievements\UserMade400Comments;
|
||||
use App\Achievements\UserMade500Comments;
|
||||
use App\Achievements\UserMade50Comments;
|
||||
use App\Achievements\UserMade600Comments;
|
||||
use App\Achievements\UserMade700Comments;
|
||||
use App\Achievements\UserMade800Comments;
|
||||
use App\Achievements\UserMade900Comments;
|
||||
use App\Achievements\UserMadeComment;
|
||||
use App\Achievements\UserMadeTenComments;
|
||||
use App\Models\User;
|
||||
use App\Notifications\NewComment;
|
||||
use App\Repositories\TaggedUserRepository;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithPagination;
|
||||
use voku\helper\AntiXSS;
|
||||
|
||||
class Comments extends Component
|
||||
{
|
||||
use WithPagination;
|
||||
|
||||
private TaggedUserRepository $taggedUserRepository;
|
||||
|
||||
public \Illuminate\Contracts\Auth\Authenticatable|\App\Models\User $user;
|
||||
|
||||
public $model;
|
||||
|
||||
public $anon = false;
|
||||
|
||||
public int $perPage = 10;
|
||||
|
||||
protected $listeners = [
|
||||
'refresh' => '$refresh',
|
||||
];
|
||||
|
||||
public $newCommentState = [
|
||||
'content' => '',
|
||||
];
|
||||
|
||||
protected $validationAttributes = [
|
||||
'newCommentState.content' => 'comment',
|
||||
];
|
||||
|
||||
final public function mount(TaggedUserRepository $taggedUserRepository): void
|
||||
{
|
||||
$this->taggedUserRepository = $taggedUserRepository;
|
||||
$this->user = \auth()->user();
|
||||
}
|
||||
|
||||
final public function loadMore()
|
||||
{
|
||||
$this->perPage += 10;
|
||||
}
|
||||
|
||||
final public function postComment(): void
|
||||
{
|
||||
if ($this->user->can_comment === 0) {
|
||||
$this->dispatchBrowserEvent('error', ['type' => 'error', 'message' => \trans('comment.rights-revoked')]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->validate([
|
||||
'newCommentState.content' => 'required',
|
||||
]);
|
||||
|
||||
$comment = $this->model->comments()->make((new AntiXSS())->xss_clean($this->newCommentState));
|
||||
$comment->user()->associate($this->user);
|
||||
$comment->anon = $this->anon;
|
||||
$comment->save();
|
||||
|
||||
$this->newCommentState = [
|
||||
'content' => '',
|
||||
];
|
||||
|
||||
// Achievements
|
||||
if ($comment->anon === 0) {
|
||||
$this->user->unlock(new UserMadeComment(), 1);
|
||||
$this->user->addProgress(new UserMadeTenComments(), 1);
|
||||
$this->user->addProgress(new UserMade50Comments(), 1);
|
||||
$this->user->addProgress(new UserMade100Comments(), 1);
|
||||
$this->user->addProgress(new UserMade200Comments(), 1);
|
||||
$this->user->addProgress(new UserMade300Comments(), 1);
|
||||
$this->user->addProgress(new UserMade400Comments(), 1);
|
||||
$this->user->addProgress(new UserMade500Comments(), 1);
|
||||
$this->user->addProgress(new UserMade600Comments(), 1);
|
||||
$this->user->addProgress(new UserMade700Comments(), 1);
|
||||
$this->user->addProgress(new UserMade800Comments(), 1);
|
||||
$this->user->addProgress(new UserMade900Comments(), 1);
|
||||
}
|
||||
|
||||
//Notification
|
||||
if ($this->user->id !== $this->model->user_id) {
|
||||
User::find($this->model->user_id)->notify(new NewComment($this->model, $comment));
|
||||
}
|
||||
|
||||
// Tagging
|
||||
if ($this->taggedUserRepository->hasTags($this->newCommentState)) {
|
||||
if ($this->user->group->is_modo && $this->taggedUserRepository->contains($this->newCommentState, '@here')) {
|
||||
$users = \collect([]);
|
||||
|
||||
$this->model->comments()->get()->each(function ($c) use ($users) {
|
||||
$users->push($c->user);
|
||||
});
|
||||
$this->taggedUserRepository->messageCommentUsers(
|
||||
$this->model,
|
||||
$users,
|
||||
$this->user,
|
||||
'Staff',
|
||||
$comment
|
||||
);
|
||||
} else {
|
||||
$sender = $comment->anon !== 0 ? $this->user->username : 'Anonymous';
|
||||
$this->taggedUserRepository->messageTaggedCommentUsers(
|
||||
$this->model,
|
||||
$this->newCommentState[],
|
||||
$this->user,
|
||||
$sender,
|
||||
$comment
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$this->gotoPage(1);
|
||||
}
|
||||
|
||||
final public function getCommentsProperty(): \Illuminate\Contracts\Pagination\LengthAwarePaginator
|
||||
{
|
||||
return $this->model
|
||||
->comments()
|
||||
->with('user', 'children.user', 'children.children')
|
||||
->parent()
|
||||
->latest()
|
||||
->paginate($this->perPage);
|
||||
}
|
||||
|
||||
final public function render(): \Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Contracts\Foundation\Application
|
||||
{
|
||||
return \view('livewire.comments', [
|
||||
'comments' => $this->comments,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -99,7 +99,9 @@ class UserActive extends Component
|
||||
)
|
||||
->selectRaw('(1 - (peers.left / NULLIF(torrents.size, 0))) AS progress')
|
||||
->where('peers.user_id', '=', $this->user->id)
|
||||
->when($this->name, fn ($query) => $query
|
||||
->when(
|
||||
$this->name,
|
||||
fn ($query) => $query
|
||||
->where('name', 'like', '%'.str_replace(' ', '%', $this->name).'%')
|
||||
)
|
||||
->when($this->ip !== '', fn ($query) => $query->where('ip', '=', $this->ip))
|
||||
|
||||
@@ -92,9 +92,10 @@ class UserTorrents extends Component
|
||||
final public function getHistoryProperty(): \Illuminate\Contracts\Pagination\LengthAwarePaginator
|
||||
{
|
||||
return History::query()
|
||||
->join('torrents', fn ($join) => $join
|
||||
->join(
|
||||
'torrents',
|
||||
fn ($join) => $join
|
||||
->on('history.torrent_id', '=', 'torrents.id')
|
||||
->where('history.created_at', '>=', $this->user->created_at) // Unneeded, but increases performance
|
||||
->where('history.user_id', '=', $this->user->id)
|
||||
)
|
||||
->select(
|
||||
@@ -126,18 +127,27 @@ class UserTorrents extends Component
|
||||
->selectRaw('TIMESTAMPDIFF(SECOND, history.created_at, history.completed_at) AS leechtime')
|
||||
->selectRaw('CAST(history.uploaded AS float) / CAST((history.downloaded + 1) AS float) AS ratio')
|
||||
->selectRaw('CAST(history.actual_uploaded AS float) / CAST((history.actual_downloaded + 1) AS float) AS actual_ratio')
|
||||
->when($this->name, fn ($query) => $query
|
||||
->when(
|
||||
$this->name,
|
||||
fn ($query) => $query
|
||||
->where('name', 'like', '%'.str_replace(' ', '%', $this->name).'%')
|
||||
)
|
||||
->when(\config('hitrun.enabled') === true, fn ($query) => $query
|
||||
->when($this->unsatisfied === 'exclude', fn ($query) => $query
|
||||
->where(fn ($query) => $query
|
||||
->when(
|
||||
\config('hitrun.enabled') === true,
|
||||
fn ($query) => $query
|
||||
->when(
|
||||
$this->unsatisfied === 'exclude',
|
||||
fn ($query) => $query
|
||||
->where(
|
||||
fn ($query) => $query
|
||||
->where('seedtime', '>', \config('hitrun.seedtime'))
|
||||
->orWhere('immune', '=', 1)
|
||||
->orWhereRaw('actual_downloaded < (torrents.size * ? / 100)', [\config('hitrun.buffer')])
|
||||
)
|
||||
)
|
||||
->when($this->unsatisfied === 'include', fn ($query) => $query
|
||||
->when(
|
||||
$this->unsatisfied === 'include',
|
||||
fn ($query) => $query
|
||||
->where('seedtime', '<', \config('hitrun.seedtime'))
|
||||
->where('immune', '=', 0)
|
||||
->whereRaw('actual_downloaded > (torrents.size * ? / 100)', [\config('hitrun.buffer')])
|
||||
|
||||
@@ -75,7 +75,9 @@ class UserUploads extends Component
|
||||
->withAnyStatus()
|
||||
->where('created_at', '>=', $this->user->created_at) // Unneeded, but increases performances
|
||||
->where('user_id', '=', $this->user->id)
|
||||
->when($this->name, fn ($query) => $query
|
||||
->when(
|
||||
$this->name,
|
||||
fn ($query) => $query
|
||||
->where('name', 'like', '%'.str_replace(' ', '%', $this->name).'%')
|
||||
)
|
||||
->when(! empty($this->status), fn ($query) => $query->whereIntegerInRaw('status', $this->status))
|
||||
|
||||
@@ -291,7 +291,7 @@ class ProcessAnnounce implements ShouldQueue
|
||||
$this->user->uploaded += $modUploaded;
|
||||
$this->user->downloaded += $modDownloaded;
|
||||
$this->user->save();
|
||||
// End User Update
|
||||
// End User Update
|
||||
}
|
||||
|
||||
$peerCount = DB::table('peers')
|
||||
|
||||
@@ -22,6 +22,10 @@ use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class ProcessMassPM implements ShouldQueue
|
||||
{
|
||||
use Dispatchable;
|
||||
use InteractsWithQueue;
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
@@ -32,11 +36,6 @@ class ProcessMassPM implements ShouldQueue
|
||||
*/
|
||||
public $receiver_id;
|
||||
|
||||
use Dispatchable;
|
||||
use InteractsWithQueue;
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* ProcessMassPM Constructor.
|
||||
*/
|
||||
|
||||
@@ -36,12 +36,9 @@ class Article extends Model
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Has Many Comments.
|
||||
*/
|
||||
public function comments(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
public function comments(): \Illuminate\Database\Eloquent\Relations\MorphMany
|
||||
{
|
||||
return $this->hasMany(Comment::class);
|
||||
return $this->morphMany(Comment::class, 'commentable');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?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 HDVinnie <hdinnovations@protonmail.com>
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0
|
||||
*/
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class BlacklistClient extends Model
|
||||
{
|
||||
}
|
||||
@@ -23,12 +23,9 @@ class Collection extends Model
|
||||
|
||||
protected $table = 'collection';
|
||||
|
||||
/**
|
||||
* Has Many Comments.
|
||||
*/
|
||||
public function comments(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
public function comments(): \Illuminate\Database\Eloquent\Relations\MorphMany
|
||||
{
|
||||
return $this->hasMany(Comment::class, 'collection_id');
|
||||
return $this->morphMany(Comment::class, 'commentable');
|
||||
}
|
||||
|
||||
public function movie(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
|
||||
+18
-37
@@ -17,15 +17,24 @@ use App\Events\TicketWentStale;
|
||||
use App\Helpers\Bbcode;
|
||||
use App\Helpers\Linkify;
|
||||
use App\Traits\Auditable;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use voku\helper\AntiXSS;
|
||||
|
||||
class Comment extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use Auditable;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*/
|
||||
protected $fillable = [
|
||||
'content',
|
||||
'user_id',
|
||||
'anon',
|
||||
];
|
||||
|
||||
/**
|
||||
* Belongs To A User.
|
||||
*/
|
||||
@@ -37,52 +46,24 @@ class Comment extends Model
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Belongs To A Torrent.
|
||||
*/
|
||||
public function torrent(): \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
public function commentable(): \Illuminate\Database\Eloquent\Relations\MorphTo
|
||||
{
|
||||
return $this->belongsTo(Torrent::class);
|
||||
return $this->morphTo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Belongs To A Article.
|
||||
*/
|
||||
public function article(): \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
public function children(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
{
|
||||
return $this->belongsTo(Article::class);
|
||||
return $this->hasMany(__CLASS__, 'parent_id')->oldest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Belongs To A Request.
|
||||
*/
|
||||
public function request(): \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
public function isParent(): bool
|
||||
{
|
||||
return $this->belongsTo(TorrentRequest::class, 'requests_id', 'id');
|
||||
return is_null($this->parent_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Belongs To A Playlist.
|
||||
*/
|
||||
public function playlist(): \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
public function scopeParent(Builder $builder): void
|
||||
{
|
||||
return $this->belongsTo(Playlist::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Belongs To A Ticket.
|
||||
*/
|
||||
public function ticket(): \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Ticket::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set The Comments Content After Its Been Purified.
|
||||
*/
|
||||
public function setContentAttribute(?string $value): void
|
||||
{
|
||||
$this->attributes['content'] = \htmlspecialchars((new AntiXSS())->xss_clean($value), ENT_NOQUOTES);
|
||||
$builder->whereNull('parent_id');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Traits\Auditable;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
@@ -45,4 +46,12 @@ class Follow extends Model
|
||||
'id' => '1',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only included follows following a user
|
||||
*/
|
||||
public function scopeFollowing($query, $user_id): Builder
|
||||
{
|
||||
return $query->where('target_id', '=', $user_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,11 +41,8 @@ class Playlist extends Model
|
||||
return $this->hasMany(PlaylistTorrent::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Has Many Comments.
|
||||
*/
|
||||
public function comments(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
public function comments(): \Illuminate\Database\Eloquent\Relations\MorphMany
|
||||
{
|
||||
return $this->hasMany(Comment::class, 'playlist_id');
|
||||
return $this->morphMany(Comment::class, 'commentable');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Traits\Auditable;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
@@ -48,4 +49,20 @@ class Subscription extends Model
|
||||
{
|
||||
return $this->belongsTo(Forum::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only include subscriptions of a forum
|
||||
*/
|
||||
public function scopeOfForum($query, $forum_id): Builder
|
||||
{
|
||||
return $query->where('forum_id', '=', $forum_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only include subscriptions of a topic
|
||||
*/
|
||||
public function scopeOfTopic($query, $topic_id): Builder
|
||||
{
|
||||
return $query->where('topic_id', '=', $topic_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,11 +95,8 @@ class Ticket extends Model
|
||||
return $this->hasMany(TicketAttachment::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Has Many Comments.
|
||||
*/
|
||||
public function comments(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
public function comments(): \Illuminate\Database\Eloquent\Relations\MorphMany
|
||||
{
|
||||
return $this->hasMany(Comment::class);
|
||||
return $this->morphMany(Comment::class, 'commentable');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,12 +182,9 @@ class Torrent extends Model
|
||||
return $this->hasMany(TorrentFile::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Has Many Comments.
|
||||
*/
|
||||
public function comments(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
public function comments(): \Illuminate\Database\Eloquent\Relations\MorphMany
|
||||
{
|
||||
return $this->hasMany(Comment::class);
|
||||
return $this->morphMany(Comment::class, 'commentable');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -108,12 +108,9 @@ class TorrentRequest extends Model
|
||||
return $this->belongsTo(Torrent::class, 'filled_hash', 'info_hash');
|
||||
}
|
||||
|
||||
/**
|
||||
* Has Many Comments.
|
||||
*/
|
||||
public function comments(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
public function comments(): \Illuminate\Database\Eloquent\Relations\MorphMany
|
||||
{
|
||||
return $this->hasMany(Comment::class, 'requests_id', 'id');
|
||||
return $this->morphMany(Comment::class, 'commentable');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+9
-169
@@ -22,7 +22,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Str;
|
||||
use voku\helper\AntiXSS;
|
||||
|
||||
@@ -128,6 +127,15 @@ class User extends Authenticatable
|
||||
}
|
||||
|
||||
/**
|
||||
* Belongs To Many Seeding Torrents.
|
||||
*/
|
||||
public function leechingTorrents(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Torrent::class, 'history')->wherePivot('active', '=', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
* Has Many Messages.
|
||||
*/
|
||||
public function messages(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
@@ -604,26 +612,6 @@ class User extends Authenticatable
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does Subscription Exist.
|
||||
*/
|
||||
public function isSubscribed(string $type, int $topicId): bool
|
||||
{
|
||||
if ($type === 'topic') {
|
||||
return (bool) $this->subscriptions()->where('topic_id', '=', $topicId)->first(['id']);
|
||||
}
|
||||
|
||||
return (bool) $this->subscriptions()->where('forum_id', '=', $topicId)->first(['id']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get All Followers Of A User.
|
||||
*/
|
||||
public function isFollowing(int $targetId): bool
|
||||
{
|
||||
return (bool) $this->follows()->where('target_id', '=', $targetId)->first(['id']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return Upload In Human Format.
|
||||
*/
|
||||
@@ -767,152 +755,4 @@ class User extends Authenticatable
|
||||
{
|
||||
return \number_format($this->seedbonus, 0, '.', ',');
|
||||
}
|
||||
|
||||
/**
|
||||
* @method getSeeding
|
||||
*
|
||||
* Gets the amount of torrents a user seeds
|
||||
*/
|
||||
public function getSeeding(): int
|
||||
{
|
||||
return Peer::where('user_id', '=', $this->id)
|
||||
->where('seeder', '=', '1')
|
||||
->distinct('torrent_id')
|
||||
->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* @method getLast30Uploads
|
||||
*
|
||||
* Gets the amount of torrents a user seeds
|
||||
*/
|
||||
public function getLast30Uploads(): int
|
||||
{
|
||||
$current = Carbon::now();
|
||||
|
||||
return Torrent::withAnyStatus()
|
||||
->where('user_id', '=', $this->id)
|
||||
->where('created_at', '>', $current->copy()->subDays(30)->toDateTimeString())
|
||||
->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* @method getUploads
|
||||
*
|
||||
* Gets the amount of torrents a user seeds
|
||||
*/
|
||||
public function getUploads(): int
|
||||
{
|
||||
return Torrent::withAnyStatus()
|
||||
->where('user_id', '=', $this->id)
|
||||
->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* @method getLeeching
|
||||
*
|
||||
* Gets the amount of torrents a user seeds
|
||||
*/
|
||||
public function getLeeching(): int
|
||||
{
|
||||
return Peer::where('user_id', '=', $this->id)
|
||||
->where('left', '>', '0')
|
||||
->distinct('torrent_id')
|
||||
->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* @method getWarning
|
||||
*
|
||||
* Gets count on users active warnings
|
||||
*/
|
||||
public function getWarning(): int
|
||||
{
|
||||
return Warning::where('user_id', '=', $this->id)
|
||||
->whereNotNull('torrent')
|
||||
->where('active', '=', '1')
|
||||
->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* @method getTotalSeedTime
|
||||
*
|
||||
* Gets the users total seedtime
|
||||
*/
|
||||
public function getTotalSeedTime(): int
|
||||
{
|
||||
return History::where('user_id', '=', $this->id)
|
||||
->sum('seedtime');
|
||||
}
|
||||
|
||||
/**
|
||||
* @method getTotalSeedSize
|
||||
*
|
||||
* Gets the users total seedsoze
|
||||
*/
|
||||
public function getTotalSeedSize(): int
|
||||
{
|
||||
$peers = Peer::where('user_id', '=', $this->id)->where('seeder', '=', 1)->pluck('torrent_id');
|
||||
|
||||
return Torrent::whereIntegerInRaw('id', $peers)->sum('size');
|
||||
}
|
||||
|
||||
/**
|
||||
* @method getCompletedSeeds
|
||||
*
|
||||
* Gets the users satisfied torrent count.
|
||||
*/
|
||||
public function getCompletedSeeds(): int
|
||||
{
|
||||
return History::where('user_id', '=', $this->id)->where('seedtime', '>=', \config('hitrun.seedtime'))->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* @method getSpecialSeedingSize
|
||||
*
|
||||
* Gets the seeding size of torrents with at least 15 days seedtime in the past 30 days.
|
||||
*/
|
||||
public function getSpecialSeedingSize(): int
|
||||
{
|
||||
$current = Carbon::now();
|
||||
$seeding = History::where('user_id', '=', $this->id)
|
||||
->where('completed_at', '<=', $current->copy()->subDays(30)->toDateTimeString())
|
||||
->where('active', '=', 1)
|
||||
->where('seeder', '=', 1)
|
||||
->where('seedtime', '>=', 1_296_000)
|
||||
->pluck('torrent_id');
|
||||
|
||||
return Torrent::whereIntergerIn('id', $seeding)->sum('size');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the seeding size of torrents that are connectable.
|
||||
*/
|
||||
public function getConnectableSeedsizeAttribute(): int
|
||||
{
|
||||
if (\config('announce.connectable_check')) {
|
||||
$unconnectablePeers = Peer::query()
|
||||
->select('ip', 'port', 'agent')
|
||||
->distinct()
|
||||
->where('user_id', '=', 3)
|
||||
->get()
|
||||
->filter(fn ($peer) => ! cache()->get('peers:connectable:'.$peer->ip.'-'.$peer->port.'-'.$peer->agent, false));
|
||||
|
||||
return Torrent::whereHas('peers', function ($query) use ($unconnectablePeers) {
|
||||
$query->where('user_id', '=', $this->id);
|
||||
|
||||
foreach ($unconnectablePeers as $peer) {
|
||||
$query->whereNot(function ($query) use ($peer) {
|
||||
$query
|
||||
->where('ip', '=', $peer->ip)
|
||||
->where('port', '=', $peer->port)
|
||||
->where('agent', '=', $peer->agent);
|
||||
});
|
||||
}
|
||||
})
|
||||
->sum('size');
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Traits\Auditable;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
@@ -64,4 +65,12 @@ class Warning extends Model
|
||||
'id' => '1',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Active Warnings
|
||||
*/
|
||||
public function scopeActive($query): Builder
|
||||
{
|
||||
return $query->where('active', '=', 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,8 +63,8 @@ class RouteServiceProvider extends ServiceProvider
|
||||
*/
|
||||
protected function configureRateLimiting(): void
|
||||
{
|
||||
RateLimiter::for('api', fn (Request $request) => Limit::perMinute(5)->by($request->ip()));
|
||||
RateLimiter::for('announce', fn (Request $request) => Limit::perMinute(2000)->by($request->ip()));
|
||||
RateLimiter::for('rss', fn (Request $request) => Limit::perMinute(2)->by($request->ip()));
|
||||
RateLimiter::for('api', fn (Request $request) => Limit::perMinute(30)->by($request->ip()));
|
||||
RateLimiter::for('announce', fn (Request $request) => Limit::perMinute(500)->by($request->ip()));
|
||||
RateLimiter::for('rss', fn (Request $request) => Limit::perMinute(30)->by($request->ip()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ class Collection
|
||||
{
|
||||
public \GuzzleHttp\Client $client;
|
||||
|
||||
public final const API_BASE_URI = 'https://api.TheMovieDB.org/3';
|
||||
final public const API_BASE_URI = 'https://api.TheMovieDB.org/3';
|
||||
|
||||
public $data;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ class Company
|
||||
|
||||
public ?int $page = null;
|
||||
|
||||
public final const API_BASE_URI = 'https://api.TheMovieDB.org/3';
|
||||
final public const API_BASE_URI = 'https://api.TheMovieDB.org/3';
|
||||
|
||||
public $data;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class Episode
|
||||
{
|
||||
public \GuzzleHttp\Client $client;
|
||||
|
||||
public final const API_BASE_URI = 'https://api.TheMovieDB.org/3';
|
||||
final public const API_BASE_URI = 'https://api.TheMovieDB.org/3';
|
||||
|
||||
public $data;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class FindMovie
|
||||
{
|
||||
public \GuzzleHttp\Client $client;
|
||||
|
||||
public final const API_BASE_URI = 'https://api.TheMovieDB.org/3';
|
||||
final public const API_BASE_URI = 'https://api.TheMovieDB.org/3';
|
||||
|
||||
public $data;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class FindTv
|
||||
{
|
||||
public \GuzzleHttp\Client $client;
|
||||
|
||||
public final const API_BASE_URI = 'https://api.TheMovieDB.org/3';
|
||||
final public const API_BASE_URI = 'https://api.TheMovieDB.org/3';
|
||||
|
||||
public $data;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class Genre
|
||||
{
|
||||
public \GuzzleHttp\Client $client;
|
||||
|
||||
public final const API_BASE_URI = 'https://api.TheMovieDB.org/3';
|
||||
final public const API_BASE_URI = 'https://api.TheMovieDB.org/3';
|
||||
|
||||
public $data;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class Movie
|
||||
{
|
||||
public \GuzzleHttp\Client $client;
|
||||
|
||||
public final const API_BASE_URI = 'https://api.themoviedb.org/3/';
|
||||
final public const API_BASE_URI = 'https://api.themoviedb.org/3/';
|
||||
|
||||
public $data;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class Network
|
||||
{
|
||||
public \GuzzleHttp\Client $client;
|
||||
|
||||
public final const API_BASE_URI = 'https://api.TheMovieDB.org/3';
|
||||
final public const API_BASE_URI = 'https://api.TheMovieDB.org/3';
|
||||
|
||||
public $data;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class Person
|
||||
{
|
||||
public \GuzzleHttp\Client $client;
|
||||
|
||||
public final const API_BASE_URI = 'https://api.TheMovieDB.org/3';
|
||||
final public const API_BASE_URI = 'https://api.TheMovieDB.org/3';
|
||||
|
||||
public $data;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class Season
|
||||
{
|
||||
public \GuzzleHttp\Client $client;
|
||||
|
||||
public final const API_BASE_URI = 'https://api.TheMovieDB.org/3';
|
||||
final public const API_BASE_URI = 'https://api.TheMovieDB.org/3';
|
||||
|
||||
public $data;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class TV
|
||||
{
|
||||
public \GuzzleHttp\Client $client;
|
||||
|
||||
public final const API_BASE_URI = 'https://api.TheMovieDB.org/3';
|
||||
final public const API_BASE_URI = 'https://api.TheMovieDB.org/3';
|
||||
|
||||
public $data;
|
||||
|
||||
|
||||
@@ -29,13 +29,12 @@ use Illuminate\Support\Str;
|
||||
|
||||
class TMDBScraper implements ShouldQueue
|
||||
{
|
||||
use SerializesModels;
|
||||
/**
|
||||
* @var mixed|array|string|null
|
||||
*/
|
||||
public $id;
|
||||
|
||||
use SerializesModels;
|
||||
|
||||
public function __construct(Request $request = null)
|
||||
{
|
||||
if ($request != null) {
|
||||
@@ -97,8 +96,11 @@ class TMDBScraper implements ShouldQueue
|
||||
\preg_match($re, (string) $movie['title'], $matches);
|
||||
|
||||
$year = (new DateTime($movie['release_date']))->format('Y');
|
||||
$titleSort = \addslashes(\str_replace(['The ', 'An ', 'A ', '"'], [''],
|
||||
Str::limit($matches['namesort'] ? $matches['namesort'].' '.$year : $movie['title'], 100)));
|
||||
$titleSort = \addslashes(\str_replace(
|
||||
['The ', 'An ', 'A ', '"'],
|
||||
[''],
|
||||
Str::limit($matches['namesort'] ? $matches['namesort'].' '.$year : $movie['title'], 100)
|
||||
));
|
||||
|
||||
$array = [
|
||||
'adult' => $movie['adult'] ?? 0,
|
||||
|
||||
@@ -26,26 +26,29 @@ trait TorrentFilter
|
||||
{
|
||||
public function scopeOfName(Builder $query, string $name, bool $isRegex = false): Builder
|
||||
{
|
||||
return $query->when($isRegex,
|
||||
fn ($query) => $query->where('name', 'REGEXP', \substr($name, 1, -1)),
|
||||
fn ($query) => $query->where('name', 'LIKE', '%'.\str_replace(' ', '%', $name).'%')
|
||||
);
|
||||
return $query->when(
|
||||
$isRegex,
|
||||
fn ($query) => $query->where('name', 'REGEXP', \substr($name, 1, -1)),
|
||||
fn ($query) => $query->where('name', 'LIKE', '%'.\str_replace(' ', '%', $name).'%')
|
||||
);
|
||||
}
|
||||
|
||||
public function scopeOfDescription(Builder $query, string $description, bool $isRegex = false): Builder
|
||||
{
|
||||
return $query->when($isRegex,
|
||||
fn ($query) => $query->where('description', 'REGEXP', \substr($description, 1, -1)),
|
||||
fn ($query) => $query->where('description', 'LIKE', '%'.$description.'%')
|
||||
);
|
||||
return $query->when(
|
||||
$isRegex,
|
||||
fn ($query) => $query->where('description', 'REGEXP', \substr($description, 1, -1)),
|
||||
fn ($query) => $query->where('description', 'LIKE', '%'.$description.'%')
|
||||
);
|
||||
}
|
||||
|
||||
public function scopeOfMediainfo(Builder $query, string $mediainfo, bool $isRegex = false): Builder
|
||||
{
|
||||
return $query->when($isRegex,
|
||||
fn ($query) => $query->where('mediainfo', 'REGEXP', \substr($mediainfo, 1, -1)),
|
||||
fn ($query) => $query->where('mediainfo', 'LIKE', '%'.$mediainfo.'%')
|
||||
);
|
||||
return $query->when(
|
||||
$isRegex,
|
||||
fn ($query) => $query->where('mediainfo', 'REGEXP', \substr($mediainfo, 1, -1)),
|
||||
fn ($query) => $query->where('mediainfo', 'LIKE', '%'.$mediainfo.'%')
|
||||
);
|
||||
}
|
||||
|
||||
public function scopeOfUploader(Builder $query, string $username): Builder
|
||||
@@ -88,12 +91,15 @@ trait TorrentFilter
|
||||
public function scopeOfGenre(Builder $query, array $genres): Builder
|
||||
{
|
||||
return $query
|
||||
->where(fn ($query) => $query
|
||||
->where(fn ($query) => $query
|
||||
->where(
|
||||
fn ($query) => $query
|
||||
->where(
|
||||
fn ($query) => $query
|
||||
->whereIn('category_id', Category::select('id')->where('movie_meta', '=', 1))
|
||||
->whereIn('tmdb', DB::table('genre_movie')->select('movie_id')->whereIn('genre_id', $genres))
|
||||
)
|
||||
->orWhere(fn ($query) => $query
|
||||
->orWhere(
|
||||
fn ($query) => $query
|
||||
->whereIn('category_id', Category::select('id')->where('tv_meta', '=', 1))
|
||||
->whereIn('tmdb', DB::table('genre_tv')->select('tv_id')->whereIn('genre_id', $genres))
|
||||
)
|
||||
@@ -212,7 +218,9 @@ trait TorrentFilter
|
||||
public function scopeNotDownloadedBy(Builder $query, User $user): Builder
|
||||
{
|
||||
return $query
|
||||
->whereDoesntHave('history', fn ($query) => $query
|
||||
->whereDoesntHave(
|
||||
'history',
|
||||
fn ($query) => $query
|
||||
->where('user_id', '=', $user->id)
|
||||
);
|
||||
}
|
||||
@@ -220,7 +228,9 @@ trait TorrentFilter
|
||||
public function scopeDownloadedBy(Builder $query, User $user): Builder
|
||||
{
|
||||
return $query
|
||||
->whereHas('history', fn (Builder $query) => $query
|
||||
->whereHas(
|
||||
'history',
|
||||
fn (Builder $query) => $query
|
||||
->where('user_id', '=', $user->id)
|
||||
);
|
||||
}
|
||||
@@ -228,7 +238,9 @@ trait TorrentFilter
|
||||
public function scopeSeededBy(Builder $query, User $user): Builder
|
||||
{
|
||||
return $query
|
||||
->whereHas('history', fn ($query) => $query
|
||||
->whereHas(
|
||||
'history',
|
||||
fn ($query) => $query
|
||||
->where('user_id', '=', $user->id)
|
||||
->where('active', '=', 1)
|
||||
->where('seeder', '=', 1)
|
||||
@@ -238,7 +250,9 @@ trait TorrentFilter
|
||||
public function scopeLeechedby(Builder $query, User $user): Builder
|
||||
{
|
||||
return $query
|
||||
->whereHas('history', fn ($query) => $query
|
||||
->whereHas(
|
||||
'history',
|
||||
fn ($query) => $query
|
||||
->where('user_id', '=', $user->id)
|
||||
->where('active', '=', 1)
|
||||
->where('seeder', '=', 0)
|
||||
@@ -248,7 +262,9 @@ trait TorrentFilter
|
||||
public function scopeUncompletedBy(Builder $query, User $user): Builder
|
||||
{
|
||||
return $query
|
||||
->whereHas('history', fn ($query) => $query
|
||||
->whereHas(
|
||||
'history',
|
||||
fn ($query) => $query
|
||||
->where('user_id', '=', $user->id)
|
||||
->where('active', '=', 0)
|
||||
->where('seeder', '=', 0)
|
||||
@@ -259,7 +275,9 @@ trait TorrentFilter
|
||||
public function scopeOfFilename(Builder $query, string $filename): Builder
|
||||
{
|
||||
return $query
|
||||
->whereHas('files', fn ($query) => $query
|
||||
->whereHas(
|
||||
'files',
|
||||
fn ($query) => $query
|
||||
->where('name', $filename)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
"league/flysystem-sftp-v3": "^3.0",
|
||||
"livewire/livewire": "^2.0",
|
||||
"marcreichel/igdb-laravel": "^3.1.2",
|
||||
"opcodesio/log-viewer": "^1.3",
|
||||
"paragonie/constant_time_encoding": "^2.0",
|
||||
"predis/predis": "^2.0",
|
||||
"spatie/laravel-backup": "^8.0.1",
|
||||
|
||||
Generated
+543
-568
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
use Opcodes\LogViewer\Level;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Log Viewer Route
|
||||
|--------------------------------------------------------------------------
|
||||
| Log Viewer will be available under this URL.
|
||||
|
|
||||
*/
|
||||
|
||||
'route_path' => 'dashboard/laravel-log-viewer',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Back to system URL
|
||||
|--------------------------------------------------------------------------
|
||||
| When set, displays a link to easily get back to this URL.
|
||||
| Set to `null` to hide this link.
|
||||
|
|
||||
| Optional label to display for the above URL.
|
||||
|
|
||||
*/
|
||||
|
||||
'back_to_system_url' => config('app.url', null),
|
||||
|
||||
'back_to_system_label' => null, // Displayed by default: "Back to {{ app.name }}"
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Log Viewer route middleware.
|
||||
|--------------------------------------------------------------------------
|
||||
| The middleware should enable session and cookies support in order for the Log Viewer to work.
|
||||
| The 'web' middleware will be applied automatically if empty.
|
||||
|
|
||||
*/
|
||||
|
||||
'middleware' => ['web', 'owner'],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Include file patterns
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
*/
|
||||
|
||||
'include_files' => [
|
||||
'*.log',
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Exclude file patterns.
|
||||
|--------------------------------------------------------------------------
|
||||
| This will take precedence over included files.
|
||||
|
|
||||
*/
|
||||
|
||||
'exclude_files' => [
|
||||
//'my_secret.log'
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Shorter stack trace filters.
|
||||
|--------------------------------------------------------------------------
|
||||
| Lines containing any of these strings will be excluded from the full log.
|
||||
| This setting is only active when the function is enabled via the user interface.
|
||||
|
|
||||
*/
|
||||
|
||||
'shorter_stack_trace_excludes' => [
|
||||
'/vendor/symfony/',
|
||||
'/vendor/laravel/framework/',
|
||||
'/vendor/barryvdh/laravel-debugbar/',
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Log matching patterns
|
||||
|--------------------------------------------------------------------------
|
||||
| Regexes for matching log files
|
||||
|
|
||||
*/
|
||||
|
||||
'patterns' => [
|
||||
'laravel' => [
|
||||
'log_matching_regex' => '/^\[(\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}\.?(\d{6}([\+-]\d\d:\d\d)?)?)\].*/',
|
||||
|
||||
/**
|
||||
* This pattern, used for processing Laravel logs, returns these results:
|
||||
* $matches[0] - the full log line being tested.
|
||||
* $matches[1] - full timestamp between the square brackets (includes microseconds and timezone offset)
|
||||
* $matches[2] - timestamp microseconds, if available
|
||||
* $matches[3] - timestamp timezone offset, if available
|
||||
* $matches[4] - contents between timestamp and the severity level
|
||||
* $matches[5] - environment (local, production, etc)
|
||||
* $matches[6] - log severity (info, debug, error, etc)
|
||||
* $matches[7] - the log text, the rest of the text.
|
||||
*/
|
||||
'log_parsing_regex' => '/^\[(\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}\.?(\d{6}([\+-]\d\d:\d\d)?)?)\](.*?(\w+)\.|.*?)('
|
||||
.implode('|', array_filter(Level::caseValues()))
|
||||
.')?: (.*?)( in [\/].*?:[0-9]+)?$/is',
|
||||
],
|
||||
],
|
||||
];
|
||||
+2
-2
@@ -22,7 +22,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'powered-by' => 'Powered By UNIT3D Community Edition v6.4.0',
|
||||
'powered-by' => 'Powered By UNIT3D Community Edition v6.4.1',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -44,7 +44,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'version' => 'v6.4.0',
|
||||
'version' => 'v6.4.1',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
return new class() extends Migration {
|
||||
return new class () extends Migration {
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user