Auto commit: 2025-11-25T16:17:51.853Z

This commit is contained in:
Flatlogic Bot 2025-11-25 16:17:51 +00:00
parent b0df731824
commit 0187c43d11
9 changed files with 40 additions and 20 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 MiB

View File

@ -20,6 +20,9 @@ load_dotenv(BASE_DIR.parent / ".env")
SECRET_KEY = os.getenv("DJANGO_SECRET_KEY", "change-me")
DEBUG = os.getenv("DJANGO_DEBUG", "true").lower() == "true"
YOUTUBE_API_KEY = os.getenv("YOUTUBE_API_KEY", "REPLACE_WITH_YOUR_YOUTUBE_API_KEY")
# Trust proxy headers from Cloudflare Tunnel / Apache
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
USE_X_FORWARDED_HOST = True

View File

@ -33,18 +33,7 @@
</form>
</div>
{% if playlist %}
<div class="playlist-container">
<h2 class="playlist-title">Your Playlist</h2>
<ul class="playlist">
{% for song in playlist %}
<li class="playlist-item">
<span class="song-title">{{ song.title }}</span> - <span class="song-artist">{{ song.artist }}</span>
</li>
{% endfor %}
</ul>
</div>
{% endif %}
</div>
<script src="{% static 'js/chat.js' %}"></script>
{% endblock %}

View File

@ -2,6 +2,23 @@ from django.shortcuts import render
from django.http import JsonResponse
from ai.local_ai_api import LocalAIApi
import json
from django.conf import settings
from googleapiclient.discovery import build
def youtube_search(query):
if not settings.YOUTUBE_API_KEY or settings.YOUTUBE_API_KEY == "REPLACE_WITH_YOUR_YOUTUBE_API_KEY":
return None
youtube = build('youtube', 'v3', developerKey=settings.YOUTUBE_API_KEY)
request = youtube.search().list(
q=query,
part='snippet',
maxResults=1,
type='video'
)
response = request.execute()
if response['items']:
return response['items'][0]['id']['videoId']
return None
def get_playlist_for_mood(mood):
"""
@ -41,7 +58,7 @@ def index(request):
response = LocalAIApi.create_response({
"input": [
{'role': 'system', 'content': 'You are a friendly AI that helps users find music based on their mood. Ask up to 6 questions to understand their mood. Once you have determined the mood, respond with ONLY a JSON object with a single key "mood" and the mood as the value (e.g. {"mood": "happy"}).'},
{'role': 'system', 'content': 'You are a friendly AI that helps users find music based on their mood. Ask up to 6 questions to understand their mood. Once you have determined the mood, respond with ONLY a JSON object with a single key "playlist" and the value as a list of songs, where each song is a JSON object with "title" and "artist" as keys (e.g. {"playlist": [{"title": "Happy", "artist": "Pharrell Williams"}]}).'},
*conversation
],
})
@ -49,10 +66,12 @@ def index(request):
ai_message = 'Sorry, I had an error.'
if response.get("success"):
json_response = LocalAIApi.decode_json_from_response(response)
if json_response and 'mood' in json_response:
mood = json_response['mood']
playlist = get_playlist_for_mood(mood)
ai_message = f"I've created a playlist for your {mood} mood. I hope you like it!"
if json_response and 'playlist' in json_response:
playlist = json_response['playlist']
for song in playlist:
video_id = youtube_search(f"{song['title']} {song['artist']}")
song['video_id'] = video_id
ai_message = "I've created a playlist for you. I hope you like it!"
else:
ai_message = LocalAIApi.extract_text(response)
@ -67,4 +86,4 @@ def index(request):
else:
# Start of a new conversation
request.session['conversation'] = []
return render(request, 'core/index.html', {'ai_message': 'Hi! How are you feeling today?'})
return render(request, 'core/index.html', {'ai_message': 'Hi! How are you feeling today?'})

View File

@ -1,3 +1,4 @@
Django==5.2.7
mysqlclient==2.2.7
python-dotenv==1.1.1
google-api-python-client>=2.136.0

View File

@ -77,7 +77,11 @@ document.addEventListener('DOMContentLoaded', function() {
playlist.forEach(song => {
const li = document.createElement('li');
li.classList.add('playlist-item');
li.innerHTML = `<span class="song-title">${song.title}</span> - <span class="song-artist">${song.artist}</span>`;
if (song.video_id) {
li.innerHTML = `<iframe width="100%" height="315" src="https://www.youtube.com/embed/${song.video_id}" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>`;
} else {
li.innerHTML = `<span class="song-title">${song.title}</span> - <span class="song-artist">${song.artist}</span> (Video not found)`;
}
ul.appendChild(li);
});

View File

@ -77,7 +77,11 @@ document.addEventListener('DOMContentLoaded', function() {
playlist.forEach(song => {
const li = document.createElement('li');
li.classList.add('playlist-item');
li.innerHTML = `<span class="song-title">${song.title}</span> - <span class="song-artist">${song.artist}</span>`;
if (song.video_id) {
li.innerHTML = `<iframe width="100%" height="315" src="https://www.youtube.com/embed/${song.video_id}" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>`;
} else {
li.innerHTML = `<span class="song-title">${song.title}</span> - <span class="song-artist">${song.artist}</span> (Video not found)`;
}
ul.appendChild(li);
});