Auto commit: 2025-11-13T12:53:49.811Z
This commit is contained in:
parent
9a0ee35f75
commit
dd83710108
56
api/mood.php
Normal file
56
api/mood.php
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../ai/LocalAIApi.php';
|
||||||
|
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user_id'])) {
|
||||||
|
echo json_encode(['error' => 'User not logged in']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$moodText = isset($_POST['mood_text']) ? trim($_POST['mood_text']) : '';
|
||||||
|
|
||||||
|
if (empty($moodText)) {
|
||||||
|
echo json_encode(['error' => 'Mood text cannot be empty']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$musicDatabase = [
|
||||||
|
'happy' => [['videoId' => 'y6Sxv-sUYtM', 'title' => 'Pharrell Williams - Happy'], ['videoId' => 'HgzGwKwLmgM', 'title' => 'Queen - Don\'t Stop Me Now'], ['videoId' => 'iPUmE-tne5s', 'title' => 'Katrina & The Waves - Walking On Sunshine']],
|
||||||
|
'sad' => [['videoId' => 'hLQl3WQQoQ0', 'title' => 'Adele - Someone Like You'], ['videoId' => '8AHCfZTRGiI', 'title' => 'Johnny Cash - Hurt'], ['videoId' => 'XFkzRNyygfk', 'title' => 'Radiohead - Creep']],
|
||||||
|
'energetic' => [['videoId' => 'v2AC41dglnM', 'title' => 'AC/DC - Thunderstruck'], ['videoId' => 'o1tj2zJ2Wvg', 'title' => 'Guns N\' Roses - Welcome to the Jungle'], ['videoId' => 'CD-E-LDc384', 'title' => 'Metallica - Enter Sandman']],
|
||||||
|
'calm' => [['videoId' => 'vNwYtllyt3Q', 'title' => 'Brian Eno - Music for Airports 1/1'], ['videoId' => 'S-Xm7s9eGxU', 'title' => 'Erik Satie - Gymnopédie No. 1'], ['videoId' => 'U3u4pQ44e14', 'title' => 'Claude Debussy - Clair de Lune']],
|
||||||
|
'upbeat' => [['videoId' => 'FGBhQbmPwH8', 'title' => 'Daft Punk - One More Time'], ['videoId' => 'sy1dYFGkPUE', 'title' => 'Justice - D.A.N.C.E.'], ['videoId' => 'Cj8JrQ9w5jY', 'title' => 'LCD Soundsystem - Daft Punk Is Playing at My House']]
|
||||||
|
];
|
||||||
|
|
||||||
|
$prompt = 'Based on the following text, what is the primary mood? Please respond with only one of the following words: happy, sad, energetic, calm, upbeat. Text: ' . $moodText;
|
||||||
|
|
||||||
|
$resp = LocalAIApi::createResponse([
|
||||||
|
'input' => [
|
||||||
|
['role' => 'system', 'content' => 'You are a mood detection assistant.'],
|
||||||
|
['role' => 'user', 'content' => $prompt],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!empty($resp['success'])) {
|
||||||
|
$decoded = LocalAIApi::decodeJsonFromResponse($resp);
|
||||||
|
$aiReply = $decoded['choices'][0]['message']['content'] ?? '';
|
||||||
|
$mood = trim(strtolower($aiReply));
|
||||||
|
|
||||||
|
if (array_key_exists($mood, $musicDatabase)) {
|
||||||
|
$songs = $musicDatabase[$mood];
|
||||||
|
echo json_encode(['mood' => $mood, 'songs' => $songs]);
|
||||||
|
} else {
|
||||||
|
// Fallback to a random mood if the AI response is not a valid key
|
||||||
|
$randomMood = array_rand($musicDatabase);
|
||||||
|
$songs = $musicDatabase[$randomMood];
|
||||||
|
echo json_encode(['mood' => $randomMood, 'songs' => $songs]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Fallback to a random mood if the AI call fails
|
||||||
|
$randomMood = array_rand($musicDatabase);
|
||||||
|
$songs = $musicDatabase[$randomMood];
|
||||||
|
echo json_encode(['mood' => $randomMood, 'songs' => $songs]);
|
||||||
|
}
|
||||||
@ -1,5 +1,7 @@
|
|||||||
document.addEventListener('DOMContentLoaded', function () {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
const moodButtons = document.querySelectorAll('.btn-mood');
|
const moodButtons = document.querySelectorAll('.btn-mood');
|
||||||
|
const suggestByTextButton = document.getElementById('suggest-by-text');
|
||||||
|
const moodTextInput = document.getElementById('mood-text');
|
||||||
const resultsSection = document.getElementById('results');
|
const resultsSection = document.getElementById('results');
|
||||||
const resultsTitle = document.getElementById('results-title');
|
const resultsTitle = document.getElementById('results-title');
|
||||||
const videoGrid = document.getElementById('video-grid');
|
const videoGrid = document.getElementById('video-grid');
|
||||||
@ -22,16 +24,37 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
moodButtons.forEach(btn => btn.classList.remove('active'));
|
moodButtons.forEach(btn => btn.classList.remove('active'));
|
||||||
this.classList.add('active');
|
this.classList.add('active');
|
||||||
|
|
||||||
displayVideos(mood);
|
const videos = musicDatabase[mood] || [];
|
||||||
|
displayVideos(videos, `Here's your ${mood} playlist`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function displayVideos(mood) {
|
suggestByTextButton.addEventListener('click', function() {
|
||||||
const videos = musicDatabase[mood] || [];
|
const moodText = moodTextInput.value.trim();
|
||||||
|
if (moodText === '') return;
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('mood_text', moodText);
|
||||||
|
|
||||||
|
fetch('/api/mood.php', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.error) {
|
||||||
|
alert('Error: ' + data.error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
displayVideos(data.songs, `Based on your mood, we suggest...`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function displayVideos(videos, title) {
|
||||||
videoGrid.innerHTML = ''; // Clear previous results
|
videoGrid.innerHTML = ''; // Clear previous results
|
||||||
|
|
||||||
if (videos.length > 0) {
|
if (videos.length > 0) {
|
||||||
resultsTitle.textContent = `Here's your ${mood} playlist`;
|
resultsTitle.textContent = title;
|
||||||
resultsSection.style.display = 'block';
|
resultsSection.style.display = 'block';
|
||||||
|
|
||||||
videos.forEach(video => {
|
videos.forEach(video => {
|
||||||
@ -42,7 +65,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
videoContainer.className = 'video-container';
|
videoContainer.className = 'video-container';
|
||||||
|
|
||||||
const iframe = document.createElement('iframe');
|
const iframe = document.createElement('iframe');
|
||||||
iframe.src = `https://www.youtube.com/embed/${video.id}`;
|
iframe.src = `https://www.youtube.com/embed/${video.videoId}`;
|
||||||
iframe.title = 'YouTube video player';
|
iframe.title = 'YouTube video player';
|
||||||
iframe.frameBorder = '0';
|
iframe.frameBorder = '0';
|
||||||
iframe.allow = 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture';
|
iframe.allow = 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture';
|
||||||
@ -54,7 +77,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
const saveButton = document.createElement('button');
|
const saveButton = document.createElement('button');
|
||||||
saveButton.className = 'btn btn-sm btn-outline-light mt-2';
|
saveButton.className = 'btn btn-sm btn-outline-light mt-2';
|
||||||
saveButton.textContent = 'Save to favorites';
|
saveButton.textContent = 'Save to favorites';
|
||||||
saveButton.addEventListener('click', () => saveToFavorites(video.id, video.title));
|
saveButton.addEventListener('click', () => saveToFavorites(video.videoId, video.title));
|
||||||
videoContainer.appendChild(saveButton);
|
videoContainer.appendChild(saveButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -54,6 +54,14 @@
|
|||||||
<button class="btn btn-mood" data-mood="calm">🧘 Calm</button>
|
<button class="btn btn-mood" data-mood="calm">🧘 Calm</button>
|
||||||
<button class="btn btn-mood" data-mood="upbeat">🔥 Upbeat</button>
|
<button class="btn btn-mood" data-mood="upbeat">🔥 Upbeat</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="text-center mt-4">
|
||||||
|
<p>Or, tell me how you feel:</p>
|
||||||
|
<div class="input-group mb-3 mx-auto" style="max-width: 500px;">
|
||||||
|
<input type="text" id="mood-text" class="form-control" placeholder="e.g., 'I had a great day!'">
|
||||||
|
<button class="btn btn-primary" type="button" id="suggest-by-text">Suggest</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="results" class="mt-5" style="display: none;">
|
<section id="results" class="mt-5" style="display: none;">
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user