orderBy('is_active', 'desc') ->orderBy('name') ->get(); return $this->sendResponse( PlatformChannelResource::collection($channels), 'Platform channels retrieved successfully.' ); } /** * Store a newly created platform channel */ public function store(Request $request): JsonResponse { try { $validated = $request->validate([ 'platform_instance_id' => 'required|exists:platform_instances,id', 'channel_id' => 'required|string|max:255', 'name' => 'required|string|max:255', 'display_name' => 'nullable|string|max:255', 'description' => 'nullable|string', 'is_active' => 'boolean', ]); $validated['is_active'] = $validated['is_active'] ?? true; // Get the platform instance to check for active accounts $platformInstance = \Domains\Platform\Models\PlatformInstance::findOrFail($validated['platform_instance_id']); // Check if there are active platform accounts for this instance $activeAccounts = PlatformAccount::where('instance_url', $platformInstance->url) ->where('is_active', true) ->get(); if ($activeAccounts->isEmpty()) { return $this->sendError( 'Cannot create channel: No active platform accounts found for this instance. Please create a platform account first.', [], 422 ); } // Detect and validate channel languages $languageDetectionService = app(ChannelLanguageDetectionService::class); try { $languageInfo = $languageDetectionService->detectChannelLanguages( $validated['name'], $validated['platform_instance_id'] ); // Add detected language to validated data $validated['language_id'] = $languageInfo['language_id']; } catch (ChannelException $e) { return $this->sendError($e->getMessage(), [], 422); } $channel = PlatformChannel::create($validated); // Automatically attach the first active account to the channel $firstAccount = $activeAccounts->first(); $channel->platformAccounts()->attach($firstAccount->id, [ 'is_active' => true, 'priority' => 1, 'created_at' => now(), 'updated_at' => now(), ]); $responseMessage = 'Platform channel created successfully and linked to platform account!'; // Add information about language detection if fallback was used if (isset($languageInfo['fallback_used']) && $languageInfo['fallback_used']) { $responseMessage .= ' Note: Used default language due to detection issue.'; } return $this->sendResponse( new PlatformChannelResource($channel->load(['platformInstance', 'platformAccounts', 'language'])), $responseMessage, 201 ); } catch (ValidationException $e) { return $this->sendValidationError($e->errors()); } catch (\Exception $e) { return $this->sendError('Failed to create platform channel: ' . $e->getMessage(), [], 500); } } /** * Display the specified platform channel */ public function show(PlatformChannel $platformChannel): JsonResponse { return $this->sendResponse( new PlatformChannelResource($platformChannel->load('platformInstance')), 'Platform channel retrieved successfully.' ); } /** * Update the specified platform channel */ public function update(Request $request, PlatformChannel $platformChannel): JsonResponse { try { $validated = $request->validate([ 'name' => 'required|string|max:255', 'display_name' => 'nullable|string|max:255', 'description' => 'nullable|string', 'is_active' => 'boolean', ]); $platformChannel->update($validated); return $this->sendResponse( new PlatformChannelResource($platformChannel->fresh(['platformInstance'])), 'Platform channel updated successfully!' ); } catch (ValidationException $e) { return $this->sendValidationError($e->errors()); } catch (\Exception $e) { return $this->sendError('Failed to update platform channel: ' . $e->getMessage(), [], 500); } } /** * Remove the specified platform channel */ public function destroy(PlatformChannel $platformChannel): JsonResponse { try { $platformChannel->delete(); return $this->sendResponse( null, 'Platform channel deleted successfully!' ); } catch (\Exception $e) { return $this->sendError('Failed to delete platform channel: ' . $e->getMessage(), [], 500); } } /** * Toggle platform channel active status */ public function toggle(PlatformChannel $channel): JsonResponse { try { $newStatus = !$channel->is_active; $channel->update(['is_active' => $newStatus]); $status = $newStatus ? 'activated' : 'deactivated'; return $this->sendResponse( new PlatformChannelResource($channel->fresh(['platformInstance', 'platformAccounts'])), "Platform channel {$status} successfully!" ); } catch (\Exception $e) { return $this->sendError('Failed to toggle platform channel status: ' . $e->getMessage(), [], 500); } } /** * Attach a platform account to a channel */ public function attachAccount(PlatformChannel $channel, Request $request): JsonResponse { try { $validated = $request->validate([ 'platform_account_id' => 'required|exists:platform_accounts,id', 'is_active' => 'boolean', 'priority' => 'nullable|integer|min:1|max:100', ]); $platformAccount = PlatformAccount::findOrFail($validated['platform_account_id']); // Check if account is already attached if ($channel->platformAccounts()->where('platform_account_id', $platformAccount->id)->exists()) { return $this->sendError('Platform account is already attached to this channel.', [], 422); } $channel->platformAccounts()->attach($platformAccount->id, [ 'is_active' => $validated['is_active'] ?? true, 'priority' => $validated['priority'] ?? 1, 'created_at' => now(), 'updated_at' => now(), ]); return $this->sendResponse( new PlatformChannelResource($channel->fresh(['platformInstance', 'platformAccounts'])), 'Platform account attached to channel successfully!' ); } catch (ValidationException $e) { return $this->sendValidationError($e->errors()); } catch (\Exception $e) { return $this->sendError('Failed to attach platform account: ' . $e->getMessage(), [], 500); } } /** * Detach a platform account from a channel */ public function detachAccount(PlatformChannel $channel, PlatformAccount $account): JsonResponse { try { if (!$channel->platformAccounts()->where('platform_account_id', $account->id)->exists()) { return $this->sendError('Platform account is not attached to this channel.', [], 422); } $channel->platformAccounts()->detach($account->id); return $this->sendResponse( new PlatformChannelResource($channel->fresh(['platformInstance', 'platformAccounts'])), 'Platform account detached from channel successfully!' ); } catch (\Exception $e) { return $this->sendError('Failed to detach platform account: ' . $e->getMessage(), [], 500); } } /** * Update platform account-channel relationship settings */ public function updateAccountRelation(PlatformChannel $channel, PlatformAccount $account, Request $request): JsonResponse { try { $validated = $request->validate([ 'is_active' => 'boolean', 'priority' => 'nullable|integer|min:1|max:100', ]); if (!$channel->platformAccounts()->where('platform_account_id', $account->id)->exists()) { return $this->sendError('Platform account is not attached to this channel.', [], 422); } $channel->platformAccounts()->updateExistingPivot($account->id, [ 'is_active' => $validated['is_active'] ?? true, 'priority' => $validated['priority'] ?? 1, 'updated_at' => now(), ]); return $this->sendResponse( new PlatformChannelResource($channel->fresh(['platformInstance', 'platformAccounts'])), 'Platform account-channel relationship updated successfully!' ); } catch (ValidationException $e) { return $this->sendValidationError($e->errors()); } catch (\Exception $e) { return $this->sendError('Failed to update platform account relationship: ' . $e->getMessage(), [], 500); } } /** * Get available communities for a platform instance */ public function getCommunities(Request $request): JsonResponse { try { $validated = $request->validate([ 'platform_instance_id' => 'required|exists:platform_instances,id', 'type' => 'sometimes|string|in:Local,All,Subscribed', 'sort' => 'sometimes|string|in:Hot,Active,New,TopDay,TopWeek,TopMonth,TopYear,TopAll', 'limit' => 'sometimes|integer|min:1|max:100', 'page' => 'sometimes|integer|min:1', 'show_nsfw' => 'sometimes|boolean', ]); $platformInstance = PlatformInstance::findOrFail($validated['platform_instance_id']); // Check if there are active platform accounts for this instance to get auth token $activeAccount = PlatformAccount::where('instance_url', $platformInstance->url) ->where('is_active', true) ->first(); if (!$activeAccount) { return $this->sendError( 'Cannot fetch communities: No active platform accounts found for this instance. Please create a platform account first.', [], 422 ); } // Create cache key based on instance and parameters $cacheKey = sprintf( 'communities:%s:%s:%s:%d:%d:%s', $platformInstance->id, $validated['type'] ?? 'Local', $validated['sort'] ?? 'Active', $validated['limit'] ?? 50, $validated['page'] ?? 1, $validated['show_nsfw'] ?? false ? '1' : '0' ); // Try to get communities from cache first (cache for 10 minutes) $communities = Cache::remember($cacheKey, 600, function () use ($platformInstance, $activeAccount, $validated) { $apiService = app(LemmyApiService::class, ['instance' => $platformInstance->url]); return $apiService->listCommunities( $activeAccount->settings['api_token'] ?? null, $validated['type'] ?? 'Local', $validated['sort'] ?? 'Active', $validated['limit'] ?? 50, $validated['page'] ?? 1, $validated['show_nsfw'] ?? false ); }); // Transform the response to include only relevant data and add helpful fields $transformedCommunities = collect($communities['communities'] ?? [])->map(function ($item) { $community = $item['community'] ?? []; return [ 'id' => $community['id'] ?? null, 'name' => $community['name'] ?? null, 'title' => $community['title'] ?? null, 'description' => $community['description'] ?? null, 'nsfw' => $community['nsfw'] ?? false, 'local' => $community['local'] ?? false, 'subscribers' => $item['counts']['subscribers'] ?? 0, 'posts' => $item['counts']['posts'] ?? 0, 'display_text' => sprintf( '%s (%s subscribers)', $community['title'] ?? $community['name'] ?? 'Unknown', number_format($item['counts']['subscribers'] ?? 0) ), ]; }); return $this->sendResponse([ 'communities' => $transformedCommunities, 'total' => $transformedCommunities->count(), 'platform_instance' => [ 'id' => $platformInstance->id, 'name' => $platformInstance->name, 'url' => $platformInstance->url, ], 'parameters' => [ 'type' => $validated['type'] ?? 'Local', 'sort' => $validated['sort'] ?? 'Active', 'limit' => $validated['limit'] ?? 50, 'page' => $validated['page'] ?? 1, 'show_nsfw' => $validated['show_nsfw'] ?? false, ] ], 'Communities retrieved successfully.'); } catch (ValidationException $e) { return $this->sendValidationError($e->errors()); } catch (\Exception $e) { // Clear cache on error to prevent serving stale data if (isset($cacheKey)) { Cache::forget($cacheKey); } return $this->sendError('Failed to fetch communities: ' . $e->getMessage(), [], 500); } } }