| <?php |
|
|
| namespace App\Http\Controllers; |
|
|
| use App\Models\SocialMediaAsset; |
| use App\Models\User; |
| use App\Services\HuggingFaceMediaStorageService; |
| use Illuminate\Http\JsonResponse; |
| use Illuminate\Http\Request; |
| use Illuminate\Support\Facades\Storage; |
| use Illuminate\Support\Str; |
| use RuntimeException; |
|
|
| class ApiMediaController extends Controller |
| { |
| public function upload(Request $request, HuggingFaceMediaStorageService $hfMedia): JsonResponse |
| { |
| $data = $request->validate([ |
| 'file' => ['nullable', 'file', 'max:51200', 'mimetypes:image/jpeg,image/png,image/webp,image/gif,video/mp4,video/quicktime,video/webm'], |
| 'asset' => ['nullable', 'file', 'max:51200', 'mimetypes:image/jpeg,image/png,image/webp,image/gif,video/mp4,video/quicktime,video/webm'], |
| 'label' => ['nullable', 'string', 'max:250'], |
| ]); |
|
|
| $file = $request->file('file') ?? $request->file('asset'); |
| if ($file === null) { |
| return response()->json([ |
| 'message' => 'Field file atau asset wajib diisi.', |
| ], 422); |
| } |
|
|
| $owner = $this->resolveOwner(); |
|
|
| try { |
| $mime = (string) $file->getMimeType(); |
| $type = Str::startsWith($mime, 'video/') ? 'video' : 'image'; |
|
|
| $ext = strtolower((string) $file->getClientOriginalExtension()); |
| if ($ext === '') { |
| $ext = $type === 'video' ? 'mp4' : 'jpg'; |
| } |
|
|
| $folder = $type === 'video' ? 'social_assets/videos' : 'social_assets/images'; |
| $filename = now()->format('Ymd_His').'_'.$owner->id.'_'.Str::lower(Str::random(8)).'.'.$ext; |
| $storedPath = $file->storeAs($folder, $filename, 'public'); |
| $publicUrl = $hfMedia->offloadPublicRelativePath($storedPath); |
|
|
| $asset = SocialMediaAsset::query()->create([ |
| 'user_id' => $owner->id, |
| 'type' => $type, |
| 'provider' => 'upload_api', |
| 'prompt' => trim((string) ($data['label'] ?? '')), |
| 'url' => $publicUrl, |
| 'thumbnail_url' => $type === 'image' ? $publicUrl : null, |
| 'meta' => [ |
| 'source' => 'api_upload', |
| 'mime' => $mime, |
| 'original_name' => $file->getClientOriginalName(), |
| 'size_bytes' => $file->getSize(), |
| 'stored_path' => $storedPath, |
| ], |
| ]); |
|
|
| return response()->json([ |
| 'message' => ucfirst($type).' uploaded successfully.', |
| 'asset' => [ |
| 'id' => $asset->id, |
| 'type' => $asset->type, |
| 'url' => $asset->url, |
| 'thumbnail_url' => $asset->thumbnail_url, |
| 'label' => $asset->prompt, |
| 'owner_email' => $owner->email, |
| ], |
| ], 201); |
| } catch (\Throwable $e) { |
| return response()->json([ |
| 'message' => $e->getMessage(), |
| ], 500); |
| } |
| } |
|
|
| private function resolveOwner(): User |
| { |
| $ownerEmail = trim((string) config('services.huggingface.media_owner_email', '')); |
|
|
| $owner = null; |
| if ($ownerEmail !== '') { |
| $owner = User::query()->where('email', $ownerEmail)->first(); |
| } |
|
|
| $owner ??= User::query()->orderBy('id')->first(); |
|
|
| if (! $owner) { |
| throw new RuntimeException('Belum ada user owner untuk media upload. Jalankan seeder atau set HF_MEDIA_OWNER_EMAIL dengan user yang valid.'); |
| } |
|
|
| return $owner; |
| } |
| } |
|
|