Passed
Push — master ( 68504f...ba1af3 )
by Darko
03:47
created

Release::getTopComments()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 20
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

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

226
            ->orderByDesc(/** @scrutinizer ignore-type */ 'grabs')
Loading history...
227
            ->limit(10)
228
            ->get();
229
230
        Cache::put(md5('topDownloads'), $releases, $expiresAt);
231
232
        return $releases;
233
    }
234
235
    /**
236
     * @return \Illuminate\Database\Eloquent\Collection|\Illuminate\Support\Collection|static[]
237
     */
238
    public static function getTopComments()
239
    {
240
        $expiresAt = now()->addMinutes(config('nntmux.cache_expiry_long'));
241
        $releases = Cache::get(md5('topComments'));
242
        if ($releases !== null) {
243
            return $releases;
244
        }
245
        $releases = self::query()
246
            ->where('comments', '>', 0)
247
            ->select(['id', 'guid', 'searchname'])
248
            ->selectRaw('SUM(comments) AS comments')
249
            ->groupBy('id', 'searchname', 'adddate')
250
            ->havingRaw('SUM(comments) > 0')
251
            ->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

251
            ->orderByDesc(/** @scrutinizer ignore-type */ 'comments')
Loading history...
252
            ->limit(10)
253
            ->get();
254
255
        Cache::put(md5('topComments'), $releases, $expiresAt);
256
257
        return $releases;
258
    }
259
260
    /**
261
     * @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Query\Builder[]|\Illuminate\Support\Collection|mixed
262
     */
263
    public static function getReleases()
264
    {
265
        $expiresAt = now()->addMinutes(config('nntmux.cache_expiry_long'));
266
        $releases = Cache::get(md5('releases'));
267
        if ($releases !== null) {
268
            return $releases;
269
        }
270
271
        $releases = self::query()
272
273
            ->where('nzbstatus', '=', NZB::NZB_ADDED)
274
            ->select(['releases.*', 'g.name as group_name', 'c.title as category_name'])
275
            ->leftJoin('categories as c', 'c.id', '=', 'releases.categories_id')
276
            ->leftJoin('usenet_groups as g', 'g.id', '=', 'releases.groups_id')
277
            ->get();
278
279
        Cache::put(md5('releases'), $releases, $expiresAt);
280
281
        return $releases;
282
    }
283
284
    /**
285
     * Used for admin page release-list.
286
     *
287
     *
288
     * @return LengthAwarePaginator|mixed
289
     */
290
    public static function getReleasesRange()
291
    {
292
        $expiresAt = now()->addMinutes(config('nntmux.cache_expiry_long'));
293
        $releases = Cache::get(md5('releasesRange'));
294
        if ($releases !== null) {
295
            return $releases;
296
        }
297
298
        $releases = self::query()
299
            ->where('nzbstatus', '=', NZB::NZB_ADDED)
300
            ->select(
301
                [
302
                    'releases.id',
303
                    'releases.name',
304
                    'releases.searchname',
305
                    'releases.size',
306
                    'releases.guid',
307
                    'releases.totalpart',
308
                    'releases.postdate',
309
                    'releases.adddate',
310
                    'releases.grabs',
311
                    'cp.title as parent_category',
312
                    'c.title as sub_category',
313
                    DB::raw('CONCAT(cp.title, ' > ', c.title) AS category_name'),
314
                ]
315
            )
316
            ->leftJoin('categories as c', 'c.id', '=', 'releases.categories_id')
317
            ->leftJoin('root_categories as cp', 'cp.id', '=', 'c.root_categories_id')
318
            ->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

318
            ->orderByDesc(/** @scrutinizer ignore-type */ 'releases.postdate')
Loading history...
319
            ->paginate(config('nntmux.items_per_page'));
320
321
        Cache::put(md5('releasesRange'), $releases, $expiresAt);
322
323
        return $releases;
324
    }
325
326
    public static function getByGuid($guid)
327
    {
328
        $query = self::with([
329
            'group:id,name',
330
            'category:id,title,root_categories_id',
331
            'category.parent:id,title',
332
            'video:id,title,tvdb,trakt,tvrage,tvmaze,source',
333
            'video.tvInfo:videos_id,summary,image',
334
            'episode:id,title,firstaired,se_complete',
335
        ]);
336
337
        if (is_array($guid)) {
338
            $query->whereIn('guid', $guid);
339
        } else {
340
            $query->where('guid', $guid);
341
        }
342
343
        $releases = $query->get();
344
345
        $releases->each(function ($release) {
346
            $release->group_name = $release->group->name ?? null;
347
            $release->showtitle = $release->video->title ?? null;
348
            $release->tvdb = $release->video->tvdb ?? null;
349
            $release->trakt = $release->video->trakt ?? null;
350
            $release->tvrage = $release->video->tvrage ?? null;
351
            $release->tvmaze = $release->video->tvmaze ?? null;
352
            $release->source = $release->video->source ?? null;
353
            $release->summary = $release->video->tvInfo->summary ?? null;
354
            $release->image = $release->video->tvInfo->image ?? null;
355
            $release->title = $release->episode->title ?? null;
356
            $release->firstaired = $release->episode->firstaired ?? null;
357
            $release->se_complete = $release->episode->se_complete ?? null;
358
            $release->parent_category = $release->category->parent->title ?? null;
359
            $release->sub_category = $release->category->title ?? null;
360
            $release->category_name = $release->parent_category.' > '.$release->sub_category;
361
            $release->category_ids = $release->category->parentid.','.$release->category->id;
362
            $release->group_names = $release->releaseGroup->pluck('group.name')->implode(',');
363
        });
364
365
        return is_array($guid) ? $releases : $releases->first();
366
    }
367
368
    /**
369
     * Get a range of releases. used in admin manage list.
370
     */
371
    public static function getFailedRange(): LengthAwarePaginator
372
    {
373
        $failedList = self::query()
374
            ->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")])
375
            ->rightJoin('dnzb_failures', 'dnzb_failures.release_id', '=', 'releases.id')
376
            ->leftJoin('categories as c', 'c.id', '=', 'releases.categories_id')
377
            ->leftJoin('root_categories as cp', 'cp.id', '=', 'c.root_categories_id')
378
            ->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

378
            ->orderByDesc(/** @scrutinizer ignore-type */ 'postdate');
Loading history...
379
380
        return $failedList->paginate(config('nntmux.items_per_page'));
381
    }
382
383
    /**
384
     * @return Release|false|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|\Illuminate\Database\Query\Builder|object|null
385
     */
386
    public static function getAlternate(string $guid, int $userid)
387
    {
388
        $rel = self::whereGuid($guid)->first(['id', 'searchname', 'categories_id']);
389
390
        if ($rel === null) {
391
            return false;
392
        }
393
        DnzbFailure::insertOrIgnore(['release_id' => $rel['id'], 'users_id' => $userid, 'failed' => 1]);
394
395
        preg_match('/(^\w+[-_. ].+?\.(\d+p)).+/i', $rel['searchname'], $similar);
396
397
        if (! empty($similar)) {
398
            if (config('nntmux.elasticsearch_enabled') === true) {
399
                $searchResult = (new ElasticSearchSiteSearch)->indexSearch($similar[1], 10);
400
            } else {
401
                $searchResult = (new ManticoreSearch)->searchIndexes('releases_rt', $similar[1]);
402
                if (! empty($searchResult)) {
403
                    $searchResult = Arr::wrap(Arr::get($searchResult, 'id'));
404
                }
405
            }
406
407
            if (empty($searchResult)) {
408
                return false;
409
            }
410
411
            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

411
            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...
412
        }
413
414
        return false;
415
    }
416
417
    public static function checkGuidForApi($guid): bool
418
    {
419
        $check = self::whereGuid($guid)->first();
420
421
        return $check !== null;
422
    }
423
}
424