Files
dredgy 37ff8e0a88
linter / quality (push) Canceled after 0s
tests / ci (8.3) (push) Canceled after 0s
tests / ci (8.4) (push) Canceled after 0s
tests / ci (8.5) (push) Canceled after 0s
Initial Commit
2026-08-28 23:53:45 +10:00

102 lines
3.4 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\Story;
use Illuminate\Http\JsonResponse;
class StoryController extends Controller
{
public function index(): JsonResponse
{
$activeStories = Story::active()->get();
$grouped = $activeStories->groupBy('user_id')->map(function ($items) {
$first = $items->first();
return [
'username' => $first->username,
'profile_pic_url' => $first->profile_pic_url,
'is_unread' => $items->contains(fn ($item) => $item->viewed_at === null),
'muted' => $first->muted,
'soonest_expiring_at' => $items->min('expiring_at'),
];
});
$sorted = $grouped
->sortBy(fn ($s) => [$s['muted'] ? 1 : 0, $s['is_unread'] ? 0 : 1, $s['soonest_expiring_at']])
->values()
->map(fn ($s) => [
'username' => $s['username'],
'profile_pic_url' => $s['profile_pic_url'],
'is_unread' => $s['is_unread'],
'muted' => $s['muted'],
]);
return response()->json($sorted);
}
public function show(string $username): JsonResponse
{
$items = Story::where('username', $username)->active()->orderBy('taken_at')->get();
if ($items->isEmpty()) {
return response()->json(['message' => 'No active story found.'], 404);
}
$firstUnread = $items->first(fn ($item) => $item->viewed_at === null);
$startIndex = $firstUnread
? $items->search(fn ($item) => $item->id === $firstUnread->id)
: 0;
return response()->json([
'username' => $username,
'profile_pic_url' => $items->first()->profile_pic_url,
'start_index' => $startIndex,
'items' => $items->map(fn (Story $item) => [
'id' => $item->id,
'code' => $item->code,
'is_video' => $item->is_video,
'image_url' => $item->image_url,
'video_url' => $item->video_url,
'accessibility_caption' => $item->accessibility_caption,
'taken_at' => $item->taken_at,
]),
]);
}
public function markViewed(string $id): JsonResponse
{
Story::where('id', $id)->update(['viewed_at' => now()]);
return response()->json(['ok' => true]);
}
/**
* Fetch a single story item by its own id, regardless of whether it's
* still active — used for opening a story someone shared in a DM long
* after it expired from the live tray.
*/
public function showItem(string $id): JsonResponse
{
$item = Story::find($id);
if (! $item) {
return response()->json(['message' => 'Story not found.'], 404);
}
return response()->json([
'username' => $item->username,
'profile_pic_url' => $item->profile_pic_url,
'start_index' => 0,
'items' => [[
'id' => $item->id,
'code' => $item->code,
'is_video' => $item->is_video,
'image_url' => $item->image_url,
'video_url' => $item->video_url,
'accessibility_caption' => $item->accessibility_caption,
'taken_at' => $item->taken_at,
]],
]);
}
}