KTV/app/Http/Controllers/Api/RoomSongController.php
allen.yan 6cff9886d4 202508281602
調整 語法收到 Model
2025-08-28 16:06:07 +08:00

226 lines
8.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Requests\OrderSongRequest;
use App\Http\Requests\SyncOrderSongRequest;
use App\Http\Requests\RoomSongRequest;
use Illuminate\Http\Request;
use App\Services\MachineStatusForwarder;
use App\Models\Room;
use App\Models\Song;
use App\Models\OrderedSong;
use App\Models\RoomSession;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Carbon;
use App\Http\Responses\ApiResponse;
class RoomSongController extends Controller
{
/**
* @OA\Post(
* path="/api/room/order-song",
* summary="點歌",
* description="在指定包廂點一首歌曲",
* tags={"Room Control Song"},
* security={{"Authorization":{}}},
* @OA\RequestBody(
* required=true,
* @OA\JsonContent(ref="#/components/schemas/OrderSongRequest")
* ),
* @OA\Response(
* response=200,
* description="成功",
* @OA\JsonContent(
* type="object",
* @OA\Property(property="success", type="boolean", example=true),
* @OA\Property(
* property="ordered_song",
* ref="#/components/schemas/OrderedSong"
* ),
* @OA\Property(property="next_song_name", type="string", example="XXXSSSS")
* )
* ),
* @OA\Response(
* response=422,
* description="驗證失敗",
* @OA\JsonContent(
* type="object",
* @OA\Property(property="message", type="string", example="The given data was invalid."),
* @OA\Property(property="errors", type="object")
* )
* )
* )
*/
public function orderSong(OrderSongRequest $request)
{
// 取得對應的 RoomSession透過 api_token
$roomSession = $this->getRoomSession($request->api_token) ;
// 找這個 session 的最大 order_number下一首加 1
$lastOrder = OrderedSong::forSession($roomSession->id)->max('order_number');
$orderNumber = $lastOrder ? $lastOrder + 1 : 1;
// 取得歌曲名稱
$song = Song::findOrFail($request->song_id);
// 建立 OrderedSong
$orderedSong = OrderedSong::create([
'room_session_id' => $roomSession->id,
'from_by' => $request->from_by,
'order_number' => $orderNumber,
'status' => $request->status,
'song_id' => $request->song_id,
'song_name' => $song->name,
'artist_name' => $song->str_artists_plus(),
'ordered_at' => now(),
]);
// 檢查這首歌在此 session 是否第一次點
$countInSession = OrderedSong::forSession($roomSession->id)
->where('song_id', $request->song_id)
->count();
if ($countInSession === 1) { // 第一次點才加
$song->increment('song_counts');
}
$this->sys($roomSession,$orderedSong);
return ApiResponse::success([
'ordered_song' => $orderedSong,
'next_song_name' => $this->nextSongName($roomSession),
]);
}
/**
* @OA\Get(
* path="/api/room/ordered-songs",
* summary="取得包廂點歌列表",
* description="取得指定包廂的已播、正在播放、待播/插播歌曲列表",
* tags={"Room Control Song"},
* security={{"Authorization":{}}},
* @OA\Parameter(ref="#/components/parameters/ApiTokenQuery"),
* @OA\Response(
* response=200,
* description="成功取得點歌列表",
* @OA\JsonContent(
* type="object",
* @OA\Property(
* property="played",
* type="array",
* description="已播放 (Played, Skipped, NoFile)",
* @OA\Items(ref="#/components/schemas/OrderedSong")
* ),
* @OA\Property(
* property="playing",
* type="array",
* description="正在播放中 (Playing)",
* @OA\Items(ref="#/components/schemas/OrderedSong")
* ),
* @OA\Property(
* property="not_played",
* type="array",
* description="未播放 (NotPlayed, InsertPlayback)",
* @OA\Items(ref="#/components/schemas/OrderedSong")
* )
* )
* ),
* @OA\Response(
* response=422,
* description="驗證失敗",
* @OA\JsonContent(
* type="object",
* @OA\Property(property="message", type="string", example="The given data was invalid."),
* @OA\Property(property="errors", type="object")
* )
* )
* )
*/
public function listOrderedSongs(RoomSongRequest $request)
{
$roomSession = $this->getRoomSession($request->api_token) ;
// 已結束 (finished + canceled)
$played = OrderedSong::forSession($roomSession->id)->finished()->get();
$playing = OrderedSong::forSession($roomSession->id)->playing()->get();
// 正在播 + 插播 + 待播
$not_played = OrderedSong::forSession($roomSession->id)->nextSong()->get();
return ApiResponse::success([
'played' => $played,
'playing' => $playing,
'not_played' => $not_played,
]);
}
private function nextSongName(RoomSession $roomSession)
{
// 找下首
$next = OrderedSong::forSession($roomSession->id)->with('song')->nextSong()->first();
return $next?->song?->name;
}
/**
* 取得對應的 RoomSession
*/
private function getRoomSession($api_token): RoomSession
{
return RoomSession::where('api_token', $api_token)
->whereIn('status', ['active', 'maintain'])
->firstOrFail();
}
private function sys($roomSession,$orderedSong)
{
$validated = [
'api_token' => $roomSession->api_token,
'order_number' => $orderedSong->order_number,
'from_by' => $orderedSong->from_by,
'song_id' => $orderedSong->song_id,
'song_name' => $orderedSong->song_name,
'artist_name' => $orderedSong->artist_name,
'status' => $orderedSong->status,
'ordered_at' => $orderedSong->ordered_at,
'started_at' => $orderedSong->started_at,
'finished_at' => $orderedSong->finished_at,
];
$response = (new MachineStatusForwarder(
$roomSession->room->branch->external_ip,
"/api/room/sync-order-song",
$validated
))->forward();
}
public function syncOrderSong(SyncOrderSongRequest $request)
{
$roomSession = $this->getRoomSession($request->api_token) ;
// 建立或更新 OrderedSong
$orderedSong = OrderedSong::updateOrCreate(
[
'room_session_id' => $roomSession->id,
'order_number' => $request->order_number,
],
[
'from_by' => $request->from_by,
'song_id' => $request->song_id,
'song_name' => $request->song_name,
'artist_name' => $request->artist_name,
'status' => $request->status,
'ordered_at' => $request->ordered_at,
'started_at' => $request->started_at,
'finished_at' => $request->finished_at,
]
);
// 檢查這首歌在此 session 是否第一次點
if ($orderedSong->wasRecentlyCreated) {
$countInSession = OrderedSong::where('room_session_id', $roomSession->id)
->where('song_id', $request->song_id)->count();
if ($countInSession === 1) { // 第一次點才加
$song->increment('song_counts');
}
}
return ApiResponse::success([
'ordered_song' => $orderedSong
]);
}
}