+ Auth Middleware Implementation Plan
AI yanıtında [ACTION:CREATE_PLAYLIST:song_ids=325,326,327:title=Rock Müzikler]
formatındaki ACTION button'u tespit et ve parse et
/\[ACTION:CREATE_PLAYLIST:song_ids=([0-9,]+):title=([^\]]+)\]/
function parseActionButton(aiResponse) {
const regex = /\[ACTION:CREATE_PLAYLIST:song_ids=([0-9,]+):title=([^\]]+)\]/;
const match = aiResponse.match(regex);
if (!match) {
return null; // No ACTION button found
}
return {
type: 'CREATE_PLAYLIST',
songIds: match[1].split(',').map(id => parseInt(id)),
title: match[2],
rawAction: match[0] // Original ACTION string
};
}
public/themes/muzibu/js/ai-assistant.js (yeni dosya)
Parse edilen ACTION data'sını "Playlist Olarak Kaydet" butonuna dönüştür
<button
class="action-button playlist-save-btn"
data-song-ids="325,326,327"
data-playlist-title="Rock Müzikler"
onclick="handlePlaylistSave(this)">
<i class="fas fa-save"></i>
Playlist Olarak Kaydet
</button>
.action-button → Base style.playlist-save-btn → Specific stylebg-blue-600 hover:bg-blue-700Butona tıklandığında auth kontrolü yap ve playlist kaydet
async function handlePlaylistSave(button) {
// 1. Get data from button
const songIds = button.dataset.songIds.split(',').map(id => parseInt(id));
const title = button.dataset.playlistTitle;
// 2. Check if user is authenticated
if (!isUserAuthenticated()) {
showLoginModal();
return;
}
// 3. Show loading state
button.disabled = true;
button.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Kaydediliyor...';
// 4. Send API request
try {
const response = await fetch('/api/muzibu/ai/playlist/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
},
body: JSON.stringify({ title, song_ids: songIds })
});
const data = await response.json();
if (data.success) {
handlePlaylistSaveSuccess(data, button);
} else {
handlePlaylistSaveError(data.message, button);
}
} catch (error) {
handlePlaylistSaveError('Bağlantı hatası', button);
}
}
Playlist create endpoint'ine auth middleware ekle
// Modules/Muzibu/routes/api.php
// ❌ ÖNCE (Auth yok):
Route::post('/ai/playlist/create', [PlaylistController::class, 'createFromAI']);
// ✅ SONRA (Auth var):
Route::post('/ai/playlist/create', [PlaylistController::class, 'createFromAI'])
->middleware(['auth:sanctum']); // veya 'auth:web'
public function createFromAI(Request $request): JsonResponse
{
// 1. Validate
$validated = $request->validate([
'title' => 'required|string|max:255',
'song_ids' => 'required|array|min:1',
'song_ids.*' => 'required|integer|exists:songs,id',
]);
// 2. Create playlist for authenticated user
$playlist = Playlist::create([
'user_id' => auth()->id(), // Authenticated user
'title' => ['tr' => $validated['title']],
'is_active' => true,
]);
// 3. Attach songs
$playlist->songs()->attach($validated['song_ids']);
// 4. Check if user is premium
$isPremium = $this->checkUserPremium(auth()->id());
return response()->json([
'success' => true,
'playlist_id' => $playlist->id,
'playlist_url' => route('muzibu.playlist.show', $playlist->slug),
'can_play' => $isPremium, // Premium users can play immediately
'message' => $isPremium
? 'Playlist kaydedildi ve dinlemeye hazır!'
: 'Playlist kaydedildi! Premium ile dinleyebilirsiniz.',
]);
}
Modules/Muzibu/app/Http/Controllers/Api/PlaylistController.php
User'ın Premium subscription'ı olup olmadığını kontrol et
protected function checkUserPremium(int $userId): bool
{
// Check if user has active premium subscription
$subscription = \DB::connection('central')
->table('subscriptions')
->where('user_id', $userId)
->where('status', 'active')
->where('ends_at', '>', now())
->first();
return $subscription !== null;
}
DB::connection('central') kullanılmalı
Müzik çalma endpoint'lerine Premium kontrolü ekle
// app/Http/Middleware/CheckPremiumSubscription.php
namespace App\Http\Middleware;
class CheckPremiumSubscription
{
public function handle($request, Closure $next)
{
if (!auth()->check()) {
return response()->json([
'success' => false,
'message' => 'Lütfen giriş yapın',
'error_code' => 'AUTH_REQUIRED'
], 401);
}
$hasPremium = $this->checkPremiumSubscription(auth()->id());
if (!$hasPremium) {
return response()->json([
'success' => false,
'message' => 'Bu özellik Premium üyelere özeldir',
'error_code' => 'PREMIUM_REQUIRED',
'upgrade_url' => route('subscription.plans')
], 403);
}
return $next($request);
}
}
// Modules/Muzibu/routes/api.php
Route::middleware(['auth:sanctum', 'check.premium'])->group(function() {
Route::post('/ai/play/{type}/{id}', [PlayController::class, 'play']);
Route::post('/ai/queue/add', [PlayController::class, 'addToQueue']);
});
Button tıklandığında önce frontend'de auth kontrolü yap
function isUserAuthenticated() {
// Laravel Blade'den gelen global variable
return typeof window.isAuthenticated !== 'undefined' && window.isAuthenticated === true;
}
function isPremiumUser() {
return typeof window.isPremium !== 'undefined' && window.isPremium === true;
}
// Blade template'de:
<script>
window.isAuthenticated = @json(auth()->check());
window.isPremium = @json(auth()->check() && auth()->user()->hasPremiumSubscription());
</script>
function handlePlaylistSaveSuccess(data, button) {
if (data.can_play) {
// Premium user
showSuccessMessage(
data.message,
`<a href="${data.playlist_url}" class="btn btn-primary">Şimdi Dinle</a>`
);
} else {
// Free user
showSuccessMessage(
data.message,
`<a href="/subscription/plans" class="btn btn-warning">Premium'a Geç</a>`
);
}
// Hide original button
button.style.display = 'none';
}
Toast notification ile user'a feedback ver
function showToast(message, type = 'success', action = null) {
// Alpine.js veya vanilla JS ile toast göster
const toast = document.createElement('div');
toast.className = `toast toast-${type}`;
toast.innerHTML = `
<div class="toast-content">
<span class="toast-icon">${getToastIcon(type)}</span>
<span class="toast-message">${message}</span>
${action ? `<div class="toast-action">${action}</div>` : ''}
</div>
`;
document.body.appendChild(toast);
setTimeout(() => {
toast.classList.add('toast-show');
}, 100);
setTimeout(() => {
toast.classList.remove('toast-show');
setTimeout(() => toast.remove(), 300);
}, 5000);
}
public/themes/muzibu/js/ai-assistant.js - Parser & handler
public/themes/muzibu/css/ai-assistant.css - Button styles
resources/views/themes/muzibu/layouts/app.blade.php - Global JS variables
Modules/Muzibu/routes/api.php - Auth middleware ekle
Modules/Muzibu/app/Http/Controllers/Api/PlaylistController.php - createFromAI method
app/Http/Middleware/CheckPremiumSubscription.php - Premium middleware
app/Http/Kernel.php - Middleware register
🎯 Frontend ACTION Button Parser & Auth Middleware Plan
Muzibu AI Assistant • 16 Aralık 2025