storageClient = new StorageClient([ 'keyFile' => json_decode(file_get_contents(module_path('StudioPlus', 'google-cloud-platform.json')), true) ]); $this->bucketName = Config::get('studioplus.bucket_name'); $this->googleApiEndpoint = Config::get('studioplus.google_api_endpoint'); $this->bucket = $this->storageClient->bucket($this->bucketName); } public function index(Request $request, StudioPlusChannel $studioPlusChannel) { $status = explode(',', $request->status) ?: ''; $globalSetting = GlobalSetting::query() ->where('type', 'Studio Pagination') ->where('is_active', 1) ->latest() ->first(); $defaultPagination = $globalSetting && $globalSetting->value ? explode(',', $globalSetting->value)[0] : 10; $defaultPagination = 50; $rows = $defaultPagination; $page = 0; if ($request->has('paging')) { $paging = $request->paging; $page = $paging['page']; } $columns = ColumnPreset::where('user_id', auth()->id())->first(); if ($columns) { $max_rows_per_page = $columns->rows; } else { $max_rows_per_page = 100; } $first = 0; if ($request->has('first')) { $rows = 25; $first = $request->first; if ($first + $rows > $max_rows_per_page) { $rows = $max_rows_per_page - $first; } } //$query = auth()->user()->role->type === 'superadmin' || permissionCheck('studio-plus.can_view_all_videos') $query = auth()->user()->role->type === 'superadmin' || permissionCheck('studioplus.manage.videos') || $request->status == 'MVL' ? StudioPlusVideo::query() : StudioPlusVideo::query() ->where( fn ($query) => $query->where('studio_plus_channel_id', $studioPlusChannel->id) ->when(permissionCheck('studioplus.manage.team') && $request->filled('user_id'), fn ($query) => $query->orWhereHas( 'channel.user', fn ($query) => $query->where('parent_id', auth()->id()) )) ->when(permissionCheck('studioplus.manage.team') && $request->filled('users'), fn ($query) => $query->orWhereHas( 'channel.user', fn ($query) => $query->where('parent_id', auth()->id()) )) ); $videos = $query->with([ 'thumbnail', 'category', 'asinData', 'videoType', 'channel.user', 'urls', ]) ->filter($request) ->when($request->filled('category_id'), fn ($query) => $query->where('studio_plus_category_id', $request->category_id)) ->when($request->filled('status') && $request->status !== 'All' && $request->status !== 'MVL', fn ($query) => $query->where('status', $status)) ->when($request->filled('start_date') && $request->filled('end_date'), fn ($query) => $query->whereBetween(DB::raw('DATE(created_at)'), [$request->start_date, $request->end_date])) ->when($request->filled('user_id'), function($query) use($request) { $query->whereHas('channel.user', function($query) use($request) { $query->where('id', $request->user_id); }); }) ->when($request->filled('team_leader_id'), fn ($query) => $query->whereHas('channel.user', fn ($query) => $query->where('parent_id', $request->team_leader_id)->orWhere('id', $request->team_leader_id) ) ) ->when($request->filled('keyword') && !empty($request->keyword), function($query) use($request) { $keyword = $request->keyword; $query->where(function($query) use($keyword) { $query ->where('title', 'LIKE', "%{$keyword}%") ->orWhere('description', 'LIKE', "%{$keyword}%") ->orWhere('asin', 'LIKE', "%{$keyword}%") ->orWhere('product_name', 'LIKE', "%{$keyword}%") ->orWhere('brand', 'LIKE', "%{$keyword}%") ->orWhere('id', $keyword); }); }) ->when($request->filled('leaders'), function($query) use($request) { $query->whereHas('channel.user', function($query) use($request) { $query->whereIn('parent_id', $request->leaders); }); }) ->when($request->filled('users'), function($query) use($request) { $query->whereHas('channel.user', function($query) use($request) { $query->whereIn('id', $request->users); }); }) ->when($request->filled('categories'), function($query) use($request) { $query->whereIn('studio_plus_category_id', $request->categories); }) ->when($request->filled('types'), function($query) use($request) { $types = array_map(function($item) { return strtoupper($item); }, $request->types); $query->where(function($query) use($types) { for ($i = 0; $i < count($types); $i++) { $type = $types[$i]; if ($type == 'POV') { $query->orWhere(function($query) { $query->whereJsonLength('types', 0)->where('is_short', false); }); } else { $query->orWhereJsonContains('types',[$type]); } } if (in_array('SHORTS', $types)) { $query->orWhere('is_short', true); } }); }) ->when($request->filled('asins'), function($query) use($request) { $query->whereIn('studio_plus_asin_id', $request->asins); }) ->when($request->filled('labels'), function($query) use($request) { $labels = $request->labels; foreach ($labels as $item) { if ($item['include'] == 'true') { $query->whereHas('urls', function ($query) use ($item) { $query->where('label', $item['label']); }); } else if ($item['include'] == 'false') { $query->whereDoesntHave('urls', function ($query) use ($item) { $query->where('label', $item['label']); }); } } }) ->when($request->filled('ratings'), function($query) use($request) { $ratings = $request->ratings; $min = $ratings[0]['min']; $max = 0; foreach ($ratings as $rating) { if ($rating['min'] < $min) { $min = $rating['min']; } if ($rating['max'] > $max) { $max = $rating['max']; } } $query->whereBetween('amazon_total_reviews', [$min, $max]); }) ->when($request->filled('type'), function($query) use($request) { if ($request->type == 'SHORTS') { $query->where('is_short', true); } else { $query->whereJsonContains('types', [$request->type]); } }) ->when($request->filled('tags'), function($query) use($request) { $tags = $request->tags; $query->where(function($query) use($tags) { for ($i = 0; $i < count($tags); $i++) { $tag = $tags[$i]; switch ($tag['code']) { case 'has-youtube': $query->where('in_youtube', true)->whereHas('urls', function ($query) { $query->where('label', 'Youtube'); }); break; case 'has-ott': $query->where('in_ott', true)->whereHas('urls', function ($query) { $query->where('label', 'OTT'); }); break; case 'no-youtube': $query->where('in_youtube', false); break; case 'no-ott': $query->where('in_ott', false); break; case 'has-watermark': $query->where('upload_status', 'COMPLETE'); break; case 'no-watermark': $query->where('upload_status', '<>', 'COMPLETE'); break; } } }); }) ->when($request->filled('customTags'), function ($query) use ($request) { $tags = $request->customTags; $query->where('tags', '<>', 'null')->whereNotNull('tags')->where(function ($query) use ($tags) { foreach ($tags as $tag) { $query->orWhereJsonContains('tags', $tag); } }); }) ->when($request->filled('activeStatuses') && !in_array('all', $request->activeStatuses), function() use($request) { $statuses = $request->activeStatuses; }) ->when($request->filled('orderBy') && $request->filled('sortBy'), function ($query) use ($request) { if ($request->orderBy === 'category') { $query->orderBy(StudioPlusCategory::select('name')->whereColumn('id', 'studio_plus_category_id')->orderBy('name', $request->sortBy), $request->sortBy); } else if ($request->orderBy === 'asin_data') { $query->orderBy(StudioPlusAsin::select('range_amount')->whereColumn('id', 'studio_plus_asin_id')->orderBy('range_amount', $request->sortBy), $request->sortBy); } else if ($request->orderBy === 'first_name') { $query->leftJoin('studio_plus_channels as channel', 'channel.id', '=', 'studio_plus_videos.studio_plus_channel_id') ->leftJoin('users', 'users.id', '=', 'channel.user_id') ->select('studio_plus_videos.*') ->orderBy($request->orderBy, $request->sortBy); } else if ($request->orderBy === 'video_types') { $query->orderBy('types', $request->sortBy); } else { $query->orderBy($request->orderBy, $request->sortBy); } }, fn ($query) => $query->latest()) ->skip($first + $page * ($request->has('first') ? $max_rows_per_page : $rows)) ->take($rows) ->get(); return response()->json([ 'items' => $videos, 'rows' => $request->has('first') ? $max_rows_per_page : $rows, 'fresh' => $first == 0 ]); } public function store(Request $request, StudioPlusChannel $studioPlusChannel) { $request->validate([ 'video' => ['required'] ]); $response = (new GoogleCloudPlatform)->handleUploadVideo($request, $studioPlusChannel); return $response; } public function show(Request $request, StudioPlusChannel $studioPlusChannel, StudioPlusVideo $studioPlusVideo) { return $studioPlusVideo->load([ 'thumbnail', 'thumbnails' ]); } public function update(StudioPlusVideoRequest $request, StudioPlusChannel $studioPlusChannel, StudioPlusVideo $studioPlusVideo) { $validated = $request->validated(); if ($request->filled('is_schedule') && $request->is_schedule) { $validated['visibility'] = StudioPlusVideo::VISIBILITY_TYPE_SCHEDULE; } $validated['upload_status'] = $request->filled('is_short') && $request->is_short ? StudioPlusVideo::UPLOAD_STATUS_COMPLETE : StudioPlusVideo::UPLOAD_STATUS_PROCESSING; $validated['amazon_total_reviews'] = Arr::get((new AmazonProductService)->getASINReviews($validated['asin']), 'total_reviews') ?? 0; $studioPlusVideo->update($validated); $this->addIncentiveItem($studioPlusVideo); if ($request->filled('thumbnail_id')) { $studioPlusVideo->thumbnails() ->where('studio_plus_thumbnails.id', '!=', $request->thumbnail_id) ->update(['is_active' => 0]); $studioPlusVideo->thumbnails() ->where('studio_plus_thumbnails.id', $request->thumbnail_id) ->update(['is_active' => 1]); } if ($request->filled('tags')) { $tags = []; foreach ($request->tags as $tag) { $tags[] = StudioPlusTag::updateOrCreate([ 'name' => $tag ]); } $tags = collect($tags)->pluck('id')->toArray(); $studioPlusVideo->tags()->attach($tags); } if ($request->filled('is_short') && $request->is_short) { return response()->noContent(); } ProcessUploadedVideo::dispatch($studioPlusVideo); return response()->noContent(); } public function updateVisibility(Request $request, StudioPlusChannel $studioPlusChannel, StudioPlusVideo $studioPlusVideo) { $validated = $request->validate([ 'is_schedule' => ['required', 'boolean'], 'visibility' => [Rule::requiredIf($request->filled('is_schedule') && !$request->is_schedule), Rule::in(StudioPlusVideo::visibilityTypes())], 'schedule_to_publish' => [Rule::requiredIf($request->filled('is_schedule') && $request->is_schedule)], ]); if ($request->filled('is_schedule') && $request->is_schedule) { $validated['visibility'] = StudioPlusVideo::VISIBILITY_TYPE_SCHEDULE; } $studioPlusVideo->update($validated); return response()->json([ 'message' => 'Visibility updated' ]); } public function updateStatus(Request $request, StudioPlusChannel $studioPlusChannel, StudioPlusVideo $studioPlusVideo) { $validated = $request->validate([ 'status' => ['required', Rule::in(StudioPlusVideo::statusTypes())] ]); try { DB::beginTransaction(); $studioPlusVideo->update(['status' => $validated['status']]); StudioPlusVideoStatusTrack::create([ 'studio_plus_video_id' => $studioPlusVideo->id, 'name' => $validated['status'] ]); $this->addIncentiveItem($studioPlusVideo); DB::commit(); //return response()->noContent(); return response()->json([ 'message' => 'Status updated' ]); } catch (\Exception $ex) { DB::rollBack(); //throw new \Exception($ex->getMessage()); return response()->json([ 'message' => 'Failed to update status.' ], 400); } } public function validateRequest(Request $request) { return $request->validate([ 'video' => ['required', 'mimetypes:video/avi,video/mpeg,video/quicktime'] ]); } private function isValidStatus(StudioPlusVideo $studioPlusVideo): bool { return in_array($studioPlusVideo->status, [StudioPlusVideo::STATUS_PUBLISHED, StudioPlusVideo::STATUS_AMAZON_APPROVED, StudioPlusVideo::STATUS_AMAZON_UPLOADED]); } private function addIncentiveItem(StudioPlusVideo $studioPlusVideo): void { if (!InvoiceSettingService::isValidUserRole($studioPlusVideo->channel->user)) { return; } if ($this->isValidStatus($studioPlusVideo)) { $studioPlusVideo = $studioPlusVideo->load('asinData'); $user = $studioPlusVideo->channel->user; $latestInvoiceNumber = $this->invoiceSettingService->getLatestInvoiceNumber($user); $invoice = $this->invoiceRepository->getInvoiceOfMonth($user, $latestInvoiceNumber); $invoice->items()->updateOrCreate( [ 'studio_plus_video_id' => $studioPlusVideo->id, ], [ 'item_no' => 1, 'name' => 'Video upload payout', 'description' => "ASIN {$studioPlusVideo->asin}", 'amount' => $studioPlusVideo->asinData->payout_amount, 'quantity' => 1, 'issue_date' => now()->toDateString(), 'type' => InvoiceItem::TYPE_VIDEO_UPLOAD_PAYOUT, 'range_amount' => $studioPlusVideo->asinData->range_amount ] ); $this->addIncentiveItemToUpline($user, $studioPlusVideo); } else { InvoiceItem::query() ->where('studio_plus_video_id', $studioPlusVideo->id) ->delete(); } } private function addIncentiveItemToUpline(User $user, StudioPlusVideo $studioPlusVideo): void { if (!$user->parent_id) return; $incentive = StudioPlusIncentive::query() ->where('description', '$1 per video from Team Members') ->first(); if (!$incentive) return; $parentUser = User::query() ->where('id', $user->parent_id) ->first(); $latestInvoiceNumber = $this->invoiceSettingService->getLatestInvoiceNumber($parentUser); $invoice = $this->invoiceRepository->getInvoiceOfMonth($parentUser, $latestInvoiceNumber); $invoice->items()->updateOrCreate( [ 'studio_plus_video_id' => $studioPlusVideo->id, ], [ 'item_no' => 1, 'name' => 'Downline Incentives', 'description' => "Downline bonus ({$user->first_name})", 'amount' => $incentive->amount_value_earned, 'quantity' => 1, 'issue_date' => now()->toDateString(), 'type' => InvoiceItem::TYPE_DOWNLINE_INCENTIVES, 'range_amount' => $studioPlusVideo->asinData->range_amount ] ); } public function statistics(Request $request) { $current_month = Carbon::now()->month; $current_year = Carbon::now()->year; $start_date = Carbon::create($current_year, $current_month, 1)->startOfDay(); $end_date = $start_date->copy()->endOfMonth(); $bonus50 = StudioPlusVideo::query() ->select('status', DB::raw('COUNT(id) as count')) ->when(auth()->user()->role->type !== 'superadmin', fn ($query) => $query->whereHas('channel.user', fn ($query) => $query->where('id', auth()->id()))) ->whereHas('asinData.incentives', fn ($query) => $query->where('description', '50 Videos Published this month')) ->whereIn('status', [StudioPlusVideo::STATUS_EDITED, StudioPlusVideo::STATUS_INTERNAL_PUBLISHED, StudioPlusVideo::STATUS_PUBLISHED,]) ->groupBy('status') ->whereBetween('created_at', [$start_date, $end_date]) ->where('is_short', false) ->get(); $bonus25 = StudioPlusVideo::query() ->select('status', DB::raw('COUNT(id) as count')) ->when(auth()->user()->role->type !== 'superadmin', fn ($query) => $query->whereHas('channel.user', fn ($query) => $query->where('id', auth()->id()))) ->whereHas('asinData.incentives', fn ($query) => $query->where('description', '25 Videos Published this month')) ->whereIn('status', [StudioPlusVideo::STATUS_EDITED, StudioPlusVideo::STATUS_INTERNAL_PUBLISHED, StudioPlusVideo::STATUS_PUBLISHED]) ->groupBy('status') ->whereBetween('created_at', [$start_date, $end_date]) ->where('is_short', false) ->get(); $asins = StudioPlusAsin::query() ->select('range_amount', DB::raw('COUNT(studio_plus_videos.id) as count')) ->join('studio_plus_videos', 'studio_plus_videos.studio_plus_asin_id', 'studio_plus_asins.id') ->join('studio_plus_channels', 'studio_plus_channels.id', 'studio_plus_videos.studio_plus_channel_id') ->join('users', 'users.id', 'studio_plus_channels.user_id') ->when(auth()->user()->role->type !== 'superadmin', fn ($query) => $query->where('users.id', auth()->id())) ->groupBy('range_amount') ->get(); return [ 'bonus_50' => $bonus50, 'bonus_25' => $bonus25, 'asins' => $asins ]; } public function destroy(StudioPlusChannel $studioPlusChannel, StudioPlusVideo $studioPlusVideo) { $studioPlusVideo->thumbnails()->delete(); $studioPlusVideo->comments()->delete(); $studioPlusVideo->delete(); return response()->noContent(); } public function videoStatistics(Request $request, StudioPlusChannel $studioPlusChannel) { $statistics = auth()->user()->role->type === 'superadmin' || permissionCheck('studioplus.manage.videos') || $request->status === 'MVL' ? StudioPlusVideo::query() : StudioPlusVideo::query() ->where( fn ($query) => $query->where('studio_plus_channel_id', $studioPlusChannel->id) ->when(permissionCheck('studioplus.manage.team') && $request->filled('user_id'), fn ($query) => $query->orWhereHas( 'channel.user', fn ($query) => $query->where('parent_id', auth()->id()) )) ->when(permissionCheck('studioplus.manage.team') && $request->filled('users'), fn ($query) => $query->orWhereHas( 'channel.user', fn ($query) => $query->where('parent_id', auth()->id()) )) ); $statistics = $statistics //->when((auth()->user()->role->type !== 'superadmin' && !permissionCheck('studio-plus.can_view_all_videos')), fn ($query) => $query->whereHas('channel.studioPlusUser', fn ($query) => $query->where('id', auth()->id()) //->whereHas('channel', fn ($query) => $query->where('id', $studioPlusChannel->id)))) ->filter($request) ->when($request->filled('category_id'), fn ($query) => $query->where('studio_plus_category_id', $request->category_id)) ->when($request->filled('status') && $request->status !== 'All' && $request->status !== 'MVL', fn ($query) => $query->where('status', explode(',', $request->status) ?: '')) ->when($request->filled('start_date') && $request->filled('end_date'), fn ($query) => $query->whereBetween(DB::raw('DATE(created_at)'), [$request->start_date, $request->end_date])) ->when($request->filled('user_id'), function($query) use($request) { $query->whereHas('channel.user', function($query) use($request) { $query->where('id', $request->user_id); }); /*->when(permissionCheck('studio-plus.can_view_downlines_user_video'), function($query) { $query->orWhereHas('channel.user', function($query) { $query->where('parent_id', auth()->id()); }); });*/ }) ->when($request->filled('team_leader_id'), fn ($query) => $query->whereHas('channel.user', fn ($query) => $query->where('parent_id', $request->team_leader_id)->orWhere('id', $request->team_leader_id) ) ) ->when($request->filled('keyword') && !empty($request->keyword), function($query) use($request) { $keyword = $request->keyword; $query->where(function($query) use($keyword) { $query ->where('title', 'LIKE', "%{$keyword}%") ->orWhere('description', 'LIKE', "%{$keyword}%") ->orWhere('asin', 'LIKE', "%{$keyword}%") ->orWhere('product_name', 'LIKE', "%{$keyword}%") ->orWhere('brand', 'LIKE', "%{$keyword}%"); }); }) ->when($request->filled('leaders'), function($query) use($request) { $query->whereHas('channel.user', function($query) use($request) { $query->whereIn('parent_id', $request->leaders); }); }) ->when($request->filled('users'), function($query) use($request) { $query->whereHas('channel.user', function($query) use($request) { $query->whereIn('id', $request->users); }); }) ->when($request->filled('categories'), function($query) use($request) { $query->whereIn('studio_plus_category_id', $request->categories); }) ->when($request->filled('types'), function($query) use($request) { $types = array_map(function($item) { return strtoupper($item); }, $request->types); $query->where(function($query) use($types) { for ($i = 0; $i < count($types); $i++) { $type = $types[$i]; if ($type == 'POV') { $query->orWhere(function($query) { $query->whereJsonLength('types', 0)->where('is_short', false); }); } else { $query->orWhereJsonContains('types',[$type]); } } if (in_array('SHORTS', $types)) { $query->orWhere('is_short', true); } }); }) ->when($request->filled('asins'), function($query) use($request) { $query->whereIn('studio_plus_asin_id', $request->asins); }) ->when($request->filled('labels'), function($query) use($request) { $labels = $request->labels; foreach ($labels as $item) { if ($item['include'] == 'true') { $query->whereHas('urls', function ($query) use ($item) { $query->where('label', $item['label']); }); } else if ($item['include'] == 'false') { $query->whereDoesntHave('urls', function ($query) use ($item) { $query->where('label', $item['label']); }); } } }) ->when($request->filled('ratings'), function($query) use($request) { $ratings = $request->ratings; $min = $ratings[0]['min']; $max = 0; foreach ($ratings as $rating) { if ($rating['min'] < $min) { $min = $rating['min']; } if ($rating['max'] > $max) { $max = $rating['max']; } } $query->whereBetween('amazon_total_reviews', [$min, $max]); }) ->when($request->filled('type'), function($query) use($request) { if ($request->type == 'SHORTS') { $query->where('is_short', true); } else { $query->whereJsonContains('types', [$request->type]); } }) ->when($request->filled('tags'), function($query) use($request) { $tags = $request->tags; $query->where(function($query) use($tags) { for ($i = 0; $i < count($tags); $i++) { $tag = $tags[$i]; switch ($tag['code']) { case 'has-youtube': $query->where('in_youtube', true)->whereHas('urls', function ($query) { $query->where('label', 'Youtube'); }); break; case 'has-ott': $query->where('in_ott', true)->whereHas('urls', function ($query) { $query->where('label', 'OTT'); }); break; case 'no-youtube': $query->where('in_youtube', false); break; case 'no-ott': $query->where('in_ott', false); break; case 'has-watermark': $query->where('upload_status', 'COMPLETE'); break; case 'no-watermark': $query->where('upload_status', '<>', 'COMPLETE'); break; } } }); }) ->when($request->filled('customTags'), function ($query) use ($request) { $tags = $request->customTags; $query->where('tags', '<>', 'null')->whereNotNull('tags')->where(function ($query) use ($tags) { foreach ($tags as $tag) { $query->orWhereJsonContains('tags', $tag); } }); }) ->toBase()->get(); $all = $statistics->count(); $rejected = $statistics->where('status', StudioPlusVideo::STATUS_REJECTED) ->count(); $published = $statistics->where('status', StudioPlusVideo::STATUS_PUBLISHED) ->count(); return [ 'all' => $all, 'rejected' => $rejected, 'published' => $published ]; } public function updateAmazonUrl(StudioPlusAmazonUrl $request, StudioPlusChannel $studioPlusChannel, StudioPlusVideo $studioPlusVideo) { $studioPlusVideo->update($request->validated()); if($studioPlusVideo->job){ $data['id'] = $studioPlusVideo->job->id; if(!$studioPlusVideo->job->is_received){ $data['received_at'] = \Carbon\Carbon::now()->format('Y-m-d H:i:s'); (new JobRequestShipmentsRepository())->received($data); } $data['fulfilled_at'] = \Carbon\Carbon::now()->format('Y-m-d H:i:s'); (new JobRequestsRepository())->fulfilled($data); } $studioPlusVideo->update([ 'status' => StudioPlusVideo::STATUS_PUBLISHED ]); StudioPlusVideoStatusTrack::create([ 'studio_plus_video_id' => $studioPlusVideo->id, 'name' => StudioPlusVideo::STATUS_PUBLISHED ]); return response()->json([ 'message' => 'Amazon URL successfully updated.' ]); } public function uploadVideo(Request $request) { $upload_service = new UploadService(); $ret = $upload_service->handleUpload($request); if ($ret) { if ($ret == 'invalid-resolution') { return response()->json([ 'message' => 'Invalid video resolution.' ], 405); } else { return response()->json([ 'message' => 'File has been uploaded.', 'video' => $ret ]); } } return response()->json([ 'message' => 'Failed to process upload.' ], 400); } public function processVideo(Request $request, StudioPlusChannel $studioPlusChannel, StudioPlusVideo $studioPlusVideo) { ignore_user_abort(true); set_time_limit(0); $upload_service = new UploadService(); $upload_service->processVideo($studioPlusVideo->id, $request->mode); } public function storeVideo(Request $request, StudioPlusChannel $studioPlusChannel, StudioPlusVideo $studioPlusVideo) { ignore_user_abort(true); set_time_limit(0); (new UploadService())->asyncStoreVideo($studioPlusVideo->id); } public function patchVideo(StudioPlusVideoRequest $request, StudioPlusChannel $studioPlusChannel, StudioPlusVideo $studioPlusVideo) { $validated = $request->validated(); $upload_service = new UploadService(); $video = StudioPlusVideo::find($request->id); if ($video) { $changes = $request->changes; if (in_array('new-video-uploaded', $changes)) { $temp_path = $upload_service->getTempLocalStoragePath($video->id); if ($request->has('is_short') && $request->is_short) { Storage::put("$temp_path/short.dat", 'Short Video'); } Storage::put("$temp_path/temp_path.dat", $temp_path); $video_upload_path = $upload_service->getTempUploadStoragePath($video->id); File::copyDirectory(storage_path("app/$temp_path"), storage_path("app/$video_upload_path")); $video->upload_status = StudioPlusVideo::UPLOAD_STATUS_PENDING; } if ($request->filled('is_schedule') && $request->is_schedule) { $validated['visibility'] = StudioPlusVideo::VISIBILITY_TYPE_SCHEDULE; } //$validated['upload_status'] = $request->filled('is_short') && $request->is_short ? StudioPlusVideo::UPLOAD_STATUS_COMPLETE : StudioPlusVideo::UPLOAD_STATUS_PROCESSING; //$validated['amazon_total_reviews'] = Arr::get((new AmazonProductService)->getASINReviews($validated['asin']), 'total_reviews') ?? 0; if (!isset($validated['amazon_total_reviews'])) { $validated['amazon_total_reviews'] = $studioPlusVideo->amazon_total_reviews; } $video->update($validated); $this->addIncentiveItem($video); if ($request->filled('thumbnail_id')) { $video->thumbnails() ->where('studio_plus_thumbnails.id', '!=', $request->thumbnail_id) ->update(['is_active' => 0]); $video->thumbnails() ->where('studio_plus_thumbnails.id', $request->thumbnail_id) ->update(['is_active' => 1]); } if ($request->filled('tags')) { $tags = []; foreach ($request->tags as $tag) { $tags[] = StudioPlusTag::updateOrCreate([ 'name' => $tag ]); } $tags = collect($tags)->pluck('id')->toArray(); $video->tags()->attach($tags); } $video->load([ 'thumbnail', 'thumbnails', 'category', 'asinData', 'channel.user', 'urls', ]); return response()->json([ 'message' => 'Video has been updated.', 'video' => $video ]); if ($request->filled('is_short') && $request->is_short) { return response()->noContent(); } return response()->noContent(); } } public function createVideo(Request $request, StudioPlusChannel $studioPlusChannel) { //validation for new video uploader if($request->has('studio_plus_video_type_id')){ $request->validate([ 'studio_plus_video_type_id' => ['required', 'exists:studio_plus_video_types,id'], 'studio_plus_category_id' => ['required', 'exists:studio_plus_categories,id'], 'studio_plus_asin_id' => ['required_without:is_short'], 'job_request_id' => $request->video_type['need_job_request'] ? ['required', 'exists:job_requests,id'] : ['nullable'], 'title' => ['required'], 'asin' => ['required'], 'product_name' => ['required'], 'brand' => ['required'] ]); } $ret = (new UploadService())->createVideo($request, $studioPlusChannel); if ($ret) { return response()->json([ 'message' => 'Video has been created successfully.', 'video' => $ret ]); } return response()->json([ 'message' => 'Failed to create new video.' ], 400); } public function refetchRatings(Request $request, StudioPlusChannel $studioPlusChannel, StudioPlusVideo $studioPlusVideo) { if ($studioPlusVideo) { $product_details = (new AmazonProductService())->getProductDetails($studioPlusVideo->asin); $studioPlusVideo->amazon_total_reviews = $product_details['amazon_total_reviews']; $studioPlusVideo->update(); $studioPlusVideo->load([ 'thumbnail', 'thumbnails', 'category', 'asinData', 'channel.user', 'urls', ]); return response()->json([ 'message' => 'Ratings has been updated.', 'video' => $studioPlusVideo ]); } return 'Video not found'; } public function reprocessVideo(Request $request, StudioPlusChannel $studioPlusChannel, StudioPlusVideo $studioPlusVideo) { $service = new WatermarkService(); if ($studioPlusVideo) { $studioPlusVideo->upload_status = StudioPlusVideo::UPLOAD_STATUS_PROCESSING; $studioPlusVideo->update(); } //ReprocessVideo::dispatch($studioPlusVideo->id); //$job = ApplyWatermark::dispatch($studioPlusVideo)->onConnection('watermarking')->onQueue('watermarking'); //$task = new ApplyWatermark($studioPlusVideo); //$task->dispatch($studioPlusVideo)->onConnection('watermarking')->onQueue('watermarking'); $queued_job = WatermarkingJob::where('video_id', $studioPlusVideo->id)->first(); if (true || !$queued_job) { $job = new ApplyWatermark($studioPlusVideo); $job_id = $service->dispatch($job); $wjob = WatermarkingJob::create([ 'video_id' => $studioPlusVideo->id, 'job_id' => $job_id, 'status' => 'pending' ]); event(new CreateJobEvent($wjob)); $studioPlusVideo->load([ 'thumbnail', 'thumbnails', 'category', 'asinData', 'channel.user', 'urls', ]); return response()->json([ 'message' => 'Video has been added to the processing queue.', 'video' => $studioPlusVideo ]); } else { return response()->json([ 'message' => 'Already in the processing queue.', 'video' => $studioPlusVideo ]); } } public function reprocessVideo2(Request $request, StudioPlusChannel $studioPlusChannel, StudioPlusVideo $studioPlusVideo) { $service = new WatermarkService(); if ($studioPlusVideo) { $studioPlusVideo->upload_status = StudioPlusVideo::UPLOAD_STATUS_PROCESSING; $studioPlusVideo->update(); } $queued_job = WatermarkingJob::where('video_id', $studioPlusVideo->id)->first(); if (true || !$queued_job) { $job = new ApplyWatermarkNewServer($studioPlusVideo, Auth::user()); $job_id = $service->dispatch($job); $wjob = WatermarkingJob::create([ 'video_id' => $studioPlusVideo->id, 'job_id' => $job_id, 'status' => 'pending' ]); event(new CreateJobEvent($wjob)); $studioPlusVideo->load([ 'thumbnail', 'thumbnails', 'category', 'asinData', 'channel.user', 'urls', ]); return response()->json([ 'message' => 'Video has been added to the processing queue.', 'video' => $studioPlusVideo ]); } else { return response()->json([ 'message' => 'Already in the processing queue.', 'video' => $studioPlusVideo ]); } } public function reprocessVideos(Request $request) { $ids = $request->ids; if (count($ids) > 0) { foreach ($ids as $id) { ReprocessVideo::dispatch($id); } } return response()->json([ 'message' => 'Reprocessing videos.' ]); } public function videoProcessor(Request $request) { $videos = (new VideoProcessingService())->getUnprocessedVideos(); return view('studioplus::video_processor', compact('videos')); } public function checkASIN(Request $request) { $existing = null; if ($request->has('asin')) { $asin = $request->asin; if (preg_match("/[A-Z0-9]{10}/", $asin)) { $video = StudioPlusVideo::where('asin', $asin)->first(); if ($video) { $existing = true; } else { $existing = false; } } } return response()->json([ 'existing' => $existing ]); } public function downloadVideo(Request $request, StudioPlusVideo $studioPlusVideo) { $path = (new DownloadService())->download($studioPlusVideo->id); return Storage::download($path, str_replace('.mov', '.mp4', $studioPlusVideo->filename)); } public function getTypes() { return response()->json([ 'data' => [ [ 'id' => 'REACH OUT', 'name' => 'REACH OUT' ], [ 'id' => 'SHORTS', 'name' => 'SHORTS' ], [ 'id' => 'VIDEO BASED ON A JOB', 'name' => 'VIDEO BASED ON A JOB' ] ] ]); } public function getVideo(Request $request, StudioPlusChannel $studioPlusChannel, StudioPlusVideo $studioPlusVideo) { return $studioPlusVideo->load([ 'thumbnail', 'thumbnails', 'category', 'asinData', 'channel.user', 'urls', ]); } public function saveTags(Request $request, StudioPlusChannel $studioPlusChannel, StudioPlusVideo $studioPlusVideo) { if ($studioPlusVideo) { $studioPlusVideo->tags = json_encode($request->tags); $studioPlusVideo->update(); if ($request->has('youtube')) { $meta = StudioPlusVideoMeta::where('studioplus_video_id', $studioPlusVideo->id)->where('name', 'youtube')->first(); if ($meta) { $meta->value = $request->youtube; $meta->update(); } else { StudioPlusVideoMeta::create([ 'studioplus_video_id' => $studioPlusVideo->id, 'name' => 'youtube', 'value' => $request->youtube ]); } $studioPlusVideo->in_youtube = $request->youtube === 'true' ? true : false; $studioPlusVideo->update(); } if ($request->has('ott')) { $meta = StudioPlusVideoMeta::where('studioplus_video_id', $studioPlusVideo->id)->where('name', 'ott')->first(); if ($meta) { $meta->value = $request->ott; $meta->update(); } else { StudioPlusVideoMeta::create([ 'studioplus_video_id' => $studioPlusVideo->id, 'name' => 'ott', 'value' => $request->ott ]); } $studioPlusVideo->in_ott = $request->ott === 'true' ? true : false; $studioPlusVideo->update(); } return response()->json([ 'message' => 'Video tags has been saved.' ]); } return response()->json([ 'message' => 'Video not found.' ], 404); } public function getTracks(Request $request, StudioPlusVideo $video) { if ($video) { $tracks = $video->tracks; return response()->json([ 'message' => 'Success', 'tracks' => $tracks ]); } return response()->json([ 'message' => 'Video not found.' ], 404); } public function studioMetaUpdater() { $jobs = StudioMetaBatchJob::get(); return view('studioplus::studio-meta-updater', compact('jobs')); } public function updateMeta() { UpdateVideoMeta::dispatch(); return redirect()->back(); } public function toggleUploadStatus(Request $request, StudioPlusVideo $video) { if (in_array($video->upload_status, [StudioPlusVideo::UPLOAD_STATUS_PENDING, StudioPlusVideo::UPLOAD_STATUS_PROCESSING])) { $video->upload_status = StudioPlusVideo::UPLOAD_STATUS_COMPLETE; $message = 'Video has been marked as completed.'; } else { $video->upload_status = StudioPlusVideo::UPLOAD_STATUS_PENDING; $message = 'Video has been marked as pending.'; } $video->update(); $video->load([ 'thumbnail', 'thumbnails', 'category', 'asinData', 'channel.user', 'urls' ]); return response()->json([ 'message' => $message, 'video' => $video, ]); } public function getCustomTags() { $tags = []; $videos = StudioPlusVideo::whereNotNull('tags')->get(); foreach ($videos as $item) { if (is_array($item->tags)) { $tags = array_unique(array_merge($tags, $item->tags)); } } $tags = array_values($tags); sort($tags, SORT_NATURAL | SORT_FLAG_CASE); return response()->json([ 'tags' => $tags, ]); } }