600, 'best' => 600, 'latest' => 300, ]; public function __construct(private readonly RSSFeedBuilder $builder) {} /** /rss/explore/{type} — defaults to latest */ public function byType(string $type): Response { return $this->feed($type, 'latest'); } /** /rss/explore/{type}/{mode} */ public function byTypeMode(string $type, string $mode): Response { return $this->feed($type, $mode); } // ───────────────────────────────────────────────────────────────────────── private function feed(string $type, string $mode): Response { $mode = in_array($mode, ['trending', 'latest', 'best'], true) ? $mode : 'latest'; $ttl = self::SORT_TTL[$mode] ?? 300; $feedUrl = url('/rss/explore/' . $type . ($mode !== 'latest' ? '/' . $mode : '')); $label = ucfirst(str_replace('-', ' ', $type)); $artworks = Cache::remember("rss:explore:{$type}:{$mode}", $ttl, function () use ($type, $mode) { $contentType = ContentType::where('slug', $type)->first(); $query = Artwork::public()->published() ->with(['user:id,username', 'categories:id,name,slug,content_type_id']); if ($contentType) { $query->whereHas('categories', fn ($q) => $q->where('content_type_id', $contentType->id) ); } return match ($mode) { 'trending' => $query ->leftJoin('artwork_stats', 'artwork_stats.artwork_id', '=', 'artworks.id') ->orderByDesc('artwork_stats.trending_score_7d') ->orderByDesc('artworks.published_at') ->select('artworks.*') ->limit(RSSFeedBuilder::FEED_LIMIT) ->get(), 'best' => $query ->leftJoin('artwork_stats', 'artwork_stats.artwork_id', '=', 'artworks.id') ->orderByDesc('artwork_stats.favorites') ->orderByDesc('artwork_stats.downloads') ->select('artworks.*') ->limit(RSSFeedBuilder::FEED_LIMIT) ->get(), default => $query ->latest('artworks.published_at') ->limit(RSSFeedBuilder::FEED_LIMIT) ->get(), }; }); $modeLabel = match ($mode) { 'trending' => 'Trending', 'best' => 'Best', default => 'Latest', }; return $this->builder->buildFromArtworks( "{$modeLabel} {$label}", "{$modeLabel} {$label} artworks on Skinbase.", $feedUrl, $artworks, ); } }