232 lines
8.4 KiB
PHP
232 lines
8.4 KiB
PHP
<?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;
|
||
|
||
/**
|
||
* @OA\Tag(
|
||
* name="Room Control Song",
|
||
* description="包廂歌曲點歌控制"
|
||
* )
|
||
*/
|
||
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
|
||
]);
|
||
}
|
||
} |