Passed
Push — master ( 4f5b3b...1c5d75 )
by Darko
09:48
created

Release::nfo()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace App\Models;
4
5
use Blacklight\ElasticSearchSiteSearch;
6
use Blacklight\ManticoreSearch;
7
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
8
use Illuminate\Database\Eloquent\Factories\HasFactory;
9
use Illuminate\Database\Eloquent\Model;
10
use Illuminate\Database\Eloquent\Relations\BelongsTo;
11
use Illuminate\Database\Eloquent\Relations\HasMany;
12
use Illuminate\Database\Eloquent\Relations\HasOne;
13
use Illuminate\Support\Arr;
14
use Illuminate\Support\Facades\Cache;
15
use Illuminate\Support\Facades\DB;
16
17
class Release extends Model
18
{
19
    use HasFactory;
0 ignored issues
show
Bug introduced by
The trait Illuminate\Database\Eloquent\Factories\HasFactory requires the property $factoryClass which is not provided by App\Models\Release.
Loading history...
20
21
    /**
22
     * @var bool
23
     */
24
    protected $dateFormat = false;
25
26
    /**
27
     * @var bool
28
     */
29
    public $timestamps = false;
30
31
    /**
32
     * @var array
33
     */
34
    protected $guarded = [];
35
36
    public function group(): BelongsTo
37
    {
38
        return $this->belongsTo(UsenetGroup::class, 'groups_id');
39
    }
40
41
    public function download(): HasMany
42
    {
43
        return $this->hasMany(UserDownload::class, 'releases_id');
44
    }
45
46
    public function userRelease(): HasMany
47
    {
48
        return $this->hasMany(UsersRelease::class, 'releases_id');
49
    }
50
51
    public function file(): HasMany
52
    {
53
        return $this->hasMany(ReleaseFile::class, 'releases_id');
54
    }
55
56
    public function category(): BelongsTo
57
    {
58
        return $this->belongsTo(Category::class, 'categories_id');
59
    }
60
61
    public function predb(): BelongsTo
62
    {
63
        return $this->belongsTo(Predb::class, 'predb_id');
64
    }
65
66
    public function failed(): HasMany
67
    {
68
        return $this->hasMany(DnzbFailure::class, 'release_id');
69
    }
70
71
    public function nfo(): HasOne
72
    {
73
        return $this->hasOne(ReleaseNfo::class, 'releases_id');
74
    }
75
76
    public function comment(): HasMany
77
    {
78
        return $this->hasMany(ReleaseComment::class, 'releases_id');
79
    }
80
81
    public function releaseGroup(): HasMany
82
    {
83
        return $this->hasMany(ReleasesGroups::class, 'releases_id');
84
    }
85
86
    public function video(): BelongsTo
87
    {
88
        return $this->belongsTo(Video::class, 'videos_id');
89
    }
90
91
    public function videoData(): HasOne
92
    {
93
        return $this->hasOne(VideoData::class, 'releases_id');
94
    }
95
96
    public function episode(): BelongsTo
97
    {
98
        return $this->belongsTo(TvEpisode::class, 'tv_episodes_id');
99
    }
100
101
    /**
102
     * Insert a single release returning the ID on success or false on failure.
103
     *
104
     * @param  array  $parameters  Insert parameters, must be escaped if string.
105
     * @return bool|int
106
     *
107
     * @throws \Exception
108
     */
109
    public static function insertRelease(array $parameters = [])
110
    {
111
        $passwordStatus = config('nntmux_settings.check_passworded_rars') === true ? -1 : 0;
112
        $parameters['id'] = self::query()
113
            ->insertGetId(
114
                [
115
                    'name' => $parameters['name'],
116
                    'searchname' => $parameters['searchname'],
117
                    'totalpart' => $parameters['totalpart'],
118
                    'groups_id' => $parameters['groups_id'],
119
                    'adddate' => now(),
120
                    'guid' => $parameters['guid'],
121
                    'leftguid' => $parameters['guid'][0],
122
                    'postdate' => $parameters['postdate'],
123
                    'fromname' => $parameters['fromname'],
124
                    'size' => $parameters['size'],
125
                    'passwordstatus' => $passwordStatus,
126
                    'haspreview' => -1,
127
                    'categories_id' => $parameters['categories_id'],
128
                    'nfostatus' => -1,
129
                    'nzbstatus' => $parameters['nzbstatus'],
130
                    'isrenamed' => $parameters['isrenamed'],
131
                    'iscategorized' => 1,
132
                    'predb_id' => $parameters['predb_id'],
133
                    'source' => $parameters['source'] ?? null,
134
                    'ishashed' => $parameters['ishashed'] ?? 0,
135
                ]
136
            );
137
138
        if (config('nntmux.elasticsearch_enabled') === true) {
139
            (new ElasticSearchSiteSearch)->insertRelease($parameters);
140
        } else {
141
            (new ManticoreSearch)->insertRelease($parameters);
142
        }
143
144
        return $parameters['id'];
0 ignored issues
show
Bug Best Practice introduced by
The expression return $parameters['id'] also could return the type Illuminate\Database\Eloquent\Builder which is incompatible with the documented return type boolean|integer.
Loading history...
145
    }
146
147
    /**
148
     * @throws \Exception
149
     */
150
    public static function updateRelease($id, $name, $searchName, $fromName, $categoryId, $parts, $grabs, $size, $postedDate, $addedDate, $videoId, $episodeId, $imDbId, $aniDbId): void
151
    {
152
        $movieInfoId = null;
153
        if (! empty($imDbId)) {
154
            $movieInfoId = MovieInfo::whereImdbid($imDbId)->first(['id']);
155
        }
156
        self::whereId($id)->update(
157
            [
158
                'name' => $name,
159
                'searchname' => $searchName,
160
                'fromname' => $fromName,
161
                'categories_id' => $categoryId,
162
                'totalpart' => $parts,
163
                'grabs' => $grabs,
164
                'size' => $size,
165
                'postdate' => $postedDate,
166
                'adddate' => $addedDate,
167
                'videos_id' => $videoId,
168
                'tv_episodes_id' => $episodeId,
169
                'imdbid' => $imDbId,
170
                'anidbid' => $aniDbId,
171
                'movieinfo_id' => $movieInfoId !== null ? $movieInfoId->id : $movieInfoId,
172
            ]
173
        );
174
175
        if (config('nntmux.elasticsearch_enabled') === true) {
176
            (new ElasticSearchSiteSearch)->updateRelease($id);
177
        } else {
178
            (new ManticoreSearch)->updateRelease($id);
179
        }
180
    }
181
182
    /**
183
     * @throws \Exception
184
     */
185
    public static function updateGrab(string $guid): void
186
    {
187
        $updateGrabs = ((int) Settings::settingValue('grabstatus') !== 0);
188
        if ($updateGrabs) {
189
            self::whereGuid($guid)->increment('grabs');
190
        }
191
    }
192
193
    /**
194
     * @return Model|null|static
195
     */
196
    public static function getCatByRelId($id)
197
    {
198
        return self::whereId($id)->first(['categories_id']);
199
    }
200
201
    public static function removeVideoIdFromReleases($videoId): int
202
    {
203
        return self::whereVideosId($videoId)->update(['videos_id' => 0, 'tv_episodes_id' => 0]);
204
    }
205
206
    public static function removeAnidbIdFromReleases($anidbID): int
207
    {
208
        return self::whereAnidbid($anidbID)->update(['anidbid' => -1]);
209
    }
210
211
    /**
212
     * @return \Illuminate\Database\Eloquent\Collection|\Illuminate\Support\Collection|static[]
213
     */
214
    public static function getTopDownloads()
215
    {
216
        $expiresAt = now()->addMinutes(config('nntmux.cache_expiry_long'));
217
        $releases = Cache::get(md5('topDownloads'));
218
        if ($releases !== null) {
219
            return $releases;
220
        }
221
        $releases = self::query()
222
            ->where('grabs', '>', 0)
223
            ->select(['id', 'searchname', 'guid', 'adddate'])
224
            ->selectRaw('SUM(grabs) as grabs')
225
            ->groupBy('id', 'searchname', 'adddate')
226
            ->havingRaw('SUM(grabs) > 0')
227
            ->orderByDesc('grabs')
0 ignored issues
show
Bug introduced by
'grabs' of type string is incompatible with the type Closure|Illuminate\Datab...\Database\Query\Builder expected by parameter $column of Illuminate\Database\Query\Builder::orderByDesc(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

227
            ->orderByDesc(/** @scrutinizer ignore-type */ 'grabs')
Loading history...
228
            ->limit(10)
229
            ->get();
230
231
        Cache::put(md5('topDownloads'), $releases, $expiresAt);
232
233
        return $releases;
234
    }
235
236
    /**
237
     * @return \Illuminate\Database\Eloquent\Collection|\Illuminate\Support\Collection|static[]
238
     */
239
    public static function getTopComments()
240
    {
241
        $expiresAt = now()->addMinutes(config('nntmux.cache_expiry_long'));
242
        $releases = Cache::get(md5('topComments'));
243
        if ($releases !== null) {
244
            return $releases;
245
        }
246
        $releases = self::query()
247
            ->where('comments', '>', 0)
248
            ->select(['id', 'guid', 'searchname'])
249
            ->selectRaw('SUM(comments) AS comments')
250
            ->groupBy('id', 'searchname', 'adddate')
251
            ->havingRaw('SUM(comments) > 0')
252
            ->orderByDesc('comments')
0 ignored issues
show
Bug introduced by
'comments' of type string is incompatible with the type Closure|Illuminate\Datab...\Database\Query\Builder expected by parameter $column of Illuminate\Database\Query\Builder::orderByDesc(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

252
            ->orderByDesc(/** @scrutinizer ignore-type */ 'comments')
Loading history...
253
            ->limit(10)
254
            ->get();
255
256
        Cache::put(md5('topComments'), $releases, $expiresAt);
257
258
        return $releases;
259
    }
260
261
    /**
262
     * @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Query\Builder[]|\Illuminate\Support\Collection|mixed
263
     */
264
    public static function getReleases()
265
    {
266
        $expiresAt = now()->addMinutes(config('nntmux.cache_expiry_long'));
267
        $releases = Cache::get(md5('releases'));
268
        if ($releases !== null) {
269
            return $releases;
270
        }
271
272
        $releases = self::query()
273
            ->select(['releases.*', 'g.name as group_name', 'c.title as category_name'])
274
            ->leftJoin('categories as c', 'c.id', '=', 'releases.categories_id')
275
            ->leftJoin('usenet_groups as g', 'g.id', '=', 'releases.groups_id')
276
            ->get();
277
278
        Cache::put(md5('releases'), $releases, $expiresAt);
279
280
        return $releases;
281
    }
282
283
    /**
284
     * Used for admin page release-list.
285
     *
286
     * @param  int  $page  The page number to retrieve
287
     * @return LengthAwarePaginator|mixed
288
     */
289
    public static function getReleasesRange(int $page = 1): mixed
290
    {
291
        $expiresAt = now()->addMinutes(config('nntmux.cache_expiry_long'));
292
        $cacheKey = md5('releasesRange_'.$page);
293
        $releases = Cache::get($cacheKey);
294
        if ($releases !== null) {
295
            return $releases;
296
        }
297
298
        $releases = self::query()
299
            ->select(
300
                [
301
                    'releases.id',
302
                    'releases.name',
303
                    'releases.searchname',
304
                    'releases.size',
305
                    'releases.guid',
306
                    'releases.totalpart',
307
                    'releases.postdate',
308
                    'releases.adddate',
309
                    'releases.grabs',
310
                    'cp.title as parent_category',
311
                    'c.title as sub_category',
312
                    DB::raw('CONCAT(cp.title, \' > \', c.title) AS category_name'),
313
                ]
314
            )
315
            ->leftJoin('categories as c', 'c.id', '=', 'releases.categories_id')
316
            ->leftJoin('root_categories as cp', 'cp.id', '=', 'c.root_categories_id')
317
            ->orderByDesc('releases.postdate')
0 ignored issues
show
Bug introduced by
'releases.postdate' of type string is incompatible with the type Closure|Illuminate\Datab...\Database\Query\Builder expected by parameter $column of Illuminate\Database\Query\Builder::orderByDesc(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

317
            ->orderByDesc(/** @scrutinizer ignore-type */ 'releases.postdate')
Loading history...
318
            ->paginate(config('nntmux.items_per_page'), ['*'], 'page', $page);
319
320
        Cache::put($cacheKey, $releases, $expiresAt);
321
322
        return $releases;
323
    }
324
325
    public static function getByGuid($guid)
326
    {
327
        $query = self::with([
328
            'group:id,name',
329
            'category:id,title,root_categories_id',
330
            'category.parent:id,title',
331
            'video:id,title,tvdb,trakt,tvrage,tvmaze,source',
332
            'video.tvInfo:videos_id,summary,image',
333
            'episode:id,title,firstaired,se_complete',
334
        ]);
335
336
        if (is_array($guid)) {
337
            $query->whereIn('guid', $guid);
338
        } else {
339
            $query->where('guid', $guid);
340
        }
341
342
        $releases = $query->get();
343
344
        $releases->each(function ($release) {
345
            $release->group_name = $release->group->name ?? null;
346
            $release->showtitle = $release->video->title ?? null;
347
            $release->tvdb = $release->video->tvdb ?? null;
348
            $release->trakt = $release->video->trakt ?? null;
349
            $release->tvrage = $release->video->tvrage ?? null;
350
            $release->tvmaze = $release->video->tvmaze ?? null;
351
            $release->source = $release->video->source ?? null;
352
            $release->summary = $release->video->tvInfo->summary ?? null;
353
            $release->image = $release->video->tvInfo->image ?? null;
354
            $release->title = $release->episode->title ?? null;
355
            $release->firstaired = $release->episode->firstaired ?? null;
356
            $release->se_complete = $release->episode->se_complete ?? null;
357
            $release->parent_category = $release->category->parent->title ?? null;
358
            $release->sub_category = $release->category->title ?? null;
359
            $release->category_name = $release->parent_category.' > '.$release->sub_category;
360
            $release->category_ids = $release->category ? ($release->category->parentid.','.$release->category->id) : '';
361
            $release->group_names = $release->releaseGroup->map(function ($relGroup) {
362
                return $relGroup->group ? $relGroup->group->name : null;
363
            })->implode(',');
364
        });
365
366
        return is_array($guid) ? $releases : $releases->first();
367
    }
368
369
    /**
370
     * Get a range of releases. used in admin manage list.
371
     */
372
    public static function getFailedRange(): LengthAwarePaginator
373
    {
374
        $failedList = self::query()
375
            ->select(['name', 'searchname', 'size', 'guid', 'totalpart', 'postdate', 'adddate', 'grabs', 'cp.title as parent_category', 'c.title as sub_category', DB::raw("CONCAT(cp.title, ' > ', c.title) AS category_name")])
376
            ->rightJoin('dnzb_failures', 'dnzb_failures.release_id', '=', 'releases.id')
377
            ->leftJoin('categories as c', 'c.id', '=', 'releases.categories_id')
378
            ->leftJoin('root_categories as cp', 'cp.id', '=', 'c.root_categories_id')
379
            ->orderByDesc('postdate');
0 ignored issues
show
Bug introduced by
'postdate' of type string is incompatible with the type Closure|Illuminate\Datab...\Database\Query\Builder expected by parameter $column of Illuminate\Database\Query\Builder::orderByDesc(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

379
            ->orderByDesc(/** @scrutinizer ignore-type */ 'postdate');
Loading history...
380
381
        return $failedList->paginate(config('nntmux.items_per_page'));
382
    }
383
384
    /**
385
     * @return Release|false|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|\Illuminate\Database\Query\Builder|object|null
386
     */
387
    public static function getAlternate(string $guid, int $userid)
388
    {
389
        $rel = self::whereGuid($guid)->first(['id', 'searchname', 'categories_id']);
390
391
        if ($rel === null) {
392
            return false;
393
        }
394
        DnzbFailure::insertOrIgnore(['release_id' => $rel['id'], 'users_id' => $userid, 'failed' => 1]);
395
396
        preg_match('/(^\w+[-_. ].+?\.(\d+p)).+/i', $rel['searchname'], $similar);
397
398
        if (! empty($similar)) {
399
            if (config('nntmux.elasticsearch_enabled') === true) {
400
                $searchResult = (new ElasticSearchSiteSearch)->indexSearch($similar[1], 10);
401
            } else {
402
                $searchResult = (new ManticoreSearch)->searchIndexes('releases_rt', $similar[1]);
403
                if (! empty($searchResult)) {
404
                    $searchResult = Arr::wrap(Arr::get($searchResult, 'id'));
405
                }
406
            }
407
408
            if (empty($searchResult)) {
409
                return false;
410
            }
411
412
            return self::query()->leftJoin('dnzb_failures as df', 'df.release_id', '=', 'releases.id')->whereIn('releases.id', $searchResult)->where('df.release_id', '=', null)->where('releases.categories_id', $rel['categories_id'])->where('id', '<>', $rel['id'])->orderByDesc('releases.postdate')->first(['guid']);
0 ignored issues
show
Bug introduced by
'releases.postdate' of type string is incompatible with the type Closure|Illuminate\Datab...\Database\Query\Builder expected by parameter $column of Illuminate\Database\Query\Builder::orderByDesc(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

412
            return self::query()->leftJoin('dnzb_failures as df', 'df.release_id', '=', 'releases.id')->whereIn('releases.id', $searchResult)->where('df.release_id', '=', null)->where('releases.categories_id', $rel['categories_id'])->where('id', '<>', $rel['id'])->orderByDesc(/** @scrutinizer ignore-type */ 'releases.postdate')->first(['guid']);
Loading history...
413
        }
414
415
        return false;
416
    }
417
418
    public static function checkGuidForApi($guid): bool
419
    {
420
        $check = self::whereGuid($guid)->first();
421
422
        return $check !== null;
423
    }
424
}
425