Skip to content

Commit a5a638d

Browse files
committed
feat: add media type to series and optimise generating it
1 parent 91d034f commit a5a638d

8 files changed

Lines changed: 97 additions & 35 deletions

File tree

app/Enums/MediaType.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
namespace App\Enums;
4+
5+
enum MediaType: int {
6+
case VIDEO = 0;
7+
case AUDIO = 1;
8+
9+
public function isVideo(): bool {
10+
return $this === self::VIDEO;
11+
}
12+
13+
public function isAudio(): bool {
14+
return $this === self::AUDIO;
15+
}
16+
17+
/**
18+
* Check if a given value is a valid enum case.
19+
*/
20+
public static function isValid(int $type): bool {
21+
foreach (self::cases() as $case) {
22+
if ($case->value == $type) {
23+
return true;
24+
}
25+
}
26+
27+
return false;
28+
}
29+
30+
public static function getValues(): array {
31+
return array_column(self::cases(), 'value');
32+
}
33+
34+
public static function getLabel(TaskStatus $type): string {
35+
return match ($type) {
36+
self::VIDEO => 'video',
37+
self::AUDIO => 'audio',
38+
};
39+
}
40+
}

app/Http/Controllers/DirectoryController.php

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
namespace App\Http\Controllers;
44

55
use App\Http\Resources\FolderResource;
6-
use App\Http\Resources\SeriesResource;
7-
use App\Http\Resources\VideoResource;
86
use App\Models\Category;
97
use App\Models\Folder;
108
use App\Services\PathResolverService;
@@ -97,12 +95,8 @@ private function loadCategoryFolders(int $categoryId): Collection {
9795
private function loadFolderData(array $data, FolderResource $folder): array {
9896
$folder->load(['videos.metadata.videoTags.tag', 'series.folderTags.tag']);
9997

100-
$data['folder'] = [
101-
'id' => $folder->id,
102-
'name' => $folder->name,
103-
'videos' => VideoResource::collection($folder->videos),
104-
'series' => new SeriesResource($folder->series),
105-
];
98+
$request = Request::create('', 'GET', ['videos' => true]);
99+
$data['folder'] = $folder->toArray($request);
106100

107101
return $data;
108102
}

app/Http/Resources/FolderResource.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public function toArray(Request $request): array {
1818
'path' => $this->path,
1919
'file_count' => $this->videos_count ?? $this->series->episodes ?? 0, // $videos->count(),
2020
'total_size' => $this->series->total_size,
21+
'is_majority_audio' => $this->series->primary_media_type ? true : false,
2122
'category_id' => $this->category_id,
2223
'videos' => $this->when($request->videos, function () {
2324
return VideoResource::collection($this->videos);

app/Jobs/VerifyFolders.php

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
use App\Enums\TaskStatus;
66
use App\Models\Series;
77
use App\Models\SubTask;
8-
use App\Models\Video;
98
use App\Services\TaskService;
109
use Illuminate\Bus\Batchable;
1110
use Illuminate\Bus\Queueable;
@@ -84,6 +83,11 @@ private function verifyFolders() {
8483
$error = false;
8584
$index = 0;
8685

86+
$this->folders->load([
87+
'series',
88+
'videos.metadata',
89+
]);
90+
8791
foreach ($this->folders as $folder) {
8892
try {
8993
$stored = [];
@@ -94,22 +98,25 @@ private function verifyFolders() {
9498
$stored = $series->toArray();
9599

96100
// if (is_null($series->episodes)) {
97-
$changes['episodes'] = Video::where('folder_id', $folder->id)->count();
101+
$changes['episodes'] = $folder->videos->count();
98102
// }
99103

104+
$changes['primary_media_type'] = $folder->primary_media_type;
105+
100106
if (is_null($series->title)) {
101107
$changes['title'] = $folder->name;
102108
}
103109

104110
if (isset($series->thumbnail_url) && ! strpos($series->thumbnail_url, str_replace('http://', '', str_replace('https://', '', config('api.app_url'))))) {
105111
$thumbnailResult = $this->getThumbnailAsFile($series->thumbnail_url, explode('/', $series->composite_id ?? 'unsorted/unsorted')[0] . '/' . basename($series->id));
106112
if ($thumbnailResult) {
113+
$changes['raw_thumbnail_url'] = $series->thumbnail_url;
107114
$changes['thumbnail_url'] = $thumbnailResult;
108-
dump('got thumbnail for ' . $series->id . ' at ' . $thumbnailResult);
115+
dump('got thumbnail for ' . $series->id . ' at ' . $thumbnailResult . ' from ' . $changes['raw_thumbnail_url']);
109116
}
110117
}
111118

112-
$totalSize = $series->folder->total_size;
119+
$totalSize = $folder->total_size;
113120
if ($stored['total_size'] !== $totalSize) {
114121
$changes['total_size'] = $totalSize;
115122
}
@@ -140,7 +147,7 @@ private function verifyFolders() {
140147
return 'No Changes Found';
141148
}
142149

143-
Series::upsert($transactions, 'id', ['folder_id', 'title', 'episodes', 'thumbnail_url', 'total_size']);
150+
Series::upsert($transactions, 'id', ['folder_id', 'title', 'episodes', 'thumbnail_url', 'raw_thumbnail_url', 'total_size', 'primary_media_type']);
144151

145152
$summary = 'Updated ' . count($transactions) . ' folders from id ' . ($transactions[0]['folder_id']) . ' to ' . ($transactions[count($transactions) - 1]['folder_id']);
146153
dump($summary);

app/Models/Folder.php

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Illuminate\Database\Eloquent\Model;
77
use Illuminate\Database\Eloquent\Relations\BelongsTo;
88
use Illuminate\Database\Eloquent\Relations\HasMany;
9+
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
910
use Illuminate\Database\Eloquent\Relations\HasOne;
1011

1112
class Folder extends Model {
@@ -25,34 +26,25 @@ public function category(): BelongsTo {
2526
return $this->belongsTo(Category::class);
2627
}
2728

28-
public function folderTags(): HasMany {
29-
return $this->hasMany(FolderTag::class);
29+
public function folderTags(): HasManyThrough {
30+
return $this->hasManyThrough(FolderTag::class, Series::class);
3031
}
3132

3233
public function getTotalSizeAttribute() {
3334
return $this->videos()->join('metadata', 'videos.id', '=', 'metadata.video_id')->sum('metadata.file_size');
3435
}
3536

36-
public function isMajorityAudio(): bool {
37-
$totalVideos = $this->videos()->count();
38-
39-
if ($totalVideos === 0) {
40-
return false;
41-
}
37+
public function getPrimaryMediaTypeAttribute() {
38+
return $this->isMajorityAudio() ? 1 : 0;
39+
}
4240

43-
$audioVideos = $this->videos()
44-
->whereHas('metadata', function ($query) {
45-
$query->where('mime_type', 'like', 'audio%');
46-
})
47-
->count();
41+
public function isMajorityAudio(): bool {
42+
$counts = $this->videos()
43+
->selectRaw('COUNT(*) as total')
44+
->selectRaw("SUM(CASE WHEN metadata.mime_type LIKE 'audio%' THEN 1 ELSE 0 END) as audio")
45+
->join('metadata', 'videos.id', '=', 'metadata.video_id')
46+
->first();
4847

49-
return $audioVideos >= ($totalVideos / 2);
48+
return $counts->total > 0 && $counts->audio >= ($counts->total / 2);
5049
}
51-
52-
// protected static function boot() {
53-
// parent::boot(); // Automatic withCount
54-
// static::addGlobalScope('videosCount', function ($builder) {
55-
// $builder->withCount('videos');
56-
// });
57-
// }
5850
}

app/Services/PreviewGeneratorService.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ protected function buildFolderPreviewData(Category $category, ?Folder $folder, R
9494
$folderResource = $this->getDecodedResource(new FolderResource($folder));
9595
$thumbnail = $folder->series->thumbnail_url ?: $this->defaultThumbnail;
9696

97-
$isAudio = $folder->isMajorityAudio();
97+
$isAudio = $folder->series->primary_media_type === 1;
9898
$fileCount = $folderResource->file_count ?? 0;
9999
$fileType = ($isAudio ? 'Track' : 'Episode') . ($fileCount === 1 ? '' : 's');
100100
$contentString = ($folderResource->series->date_start ? $this->getMediaReleaseSeason($folderResource->series->date_start) . '' : '') . "$fileCount $fileType";
@@ -109,6 +109,7 @@ protected function buildFolderPreviewData(Category $category, ?Folder $folder, R
109109
'thumbnail_url' => $thumbnail,
110110
'upload_date' => $this->formatDate($folderResource->series->date_created),
111111
'content_string' => $contentString,
112+
'rating' => $folderResource->series->rating,
112113
'tags' => $folderResource->series->folder_tags ? array_map(fn ($tag) => $tag->name, $folderResource->series->folder_tags) : null,
113114
'url' => $request->fullUrl(),
114115
];
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
use App\Enums\MediaType;
4+
use Illuminate\Database\Migrations\Migration;
5+
use Illuminate\Database\Schema\Blueprint;
6+
use Illuminate\Support\Facades\Schema;
7+
8+
return new class extends Migration {
9+
/**
10+
* Run the migrations.
11+
*/
12+
public function up(): void {
13+
Schema::table('series', function (Blueprint $table) {
14+
$table->tinyInteger('primary_media_type')->default(MediaType::VIDEO);
15+
});
16+
}
17+
18+
/**
19+
* Reverse the migrations.
20+
*/
21+
public function down(): void {
22+
Schema::table('series', function (Blueprint $table) {
23+
$table->dropColumn('primary_media_type');
24+
});
25+
}
26+
};

resources/js/types/resources.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export interface FolderResource {
2828
path: string;
2929
file_count: number;
3030
total_size: number;
31+
is_majority_audio: boolean;
3132
category_id: number;
3233
videos?: VideoResource[];
3334
series?: SeriesResource;

0 commit comments

Comments
 (0)