Add playlist loading feature and integrate YouTube API for playlist generation
This commit is contained in:
parent
95969b897b
commit
094c5c104d
9 changed files with 230 additions and 39 deletions
17
game/migrations/0014_musikgame_playlist_loading.py
Normal file
17
game/migrations/0014_musikgame_playlist_loading.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
# Generated by Django 5.2.3 on 2025-06-14 09:44
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("game", "0013_alter_group_unique_together_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="musikgame",
|
||||
name="playlist_loading",
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
|
@ -47,6 +47,7 @@ class MusikGame(models.Model):
|
|||
n = models.PositiveIntegerField(default=2, verbose_name="Nombre de musiques")
|
||||
players = models.ManyToManyField(User, verbose_name="Joueurs")
|
||||
playlist = models.CharField(blank=True, verbose_name="Playlist YouTube")
|
||||
playlist_loading = models.BooleanField(default=False)
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse("game_detail", kwargs={"pk": self.pk})
|
||||
|
|
45
game/tasks.py
Normal file
45
game/tasks.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
import google.oauth2.credentials
|
||||
import googleapiclient.discovery
|
||||
from celery import shared_task
|
||||
|
||||
from . import models
|
||||
|
||||
|
||||
@shared_task
|
||||
def generate_playlist(creds, game_pk):
|
||||
game = models.MusikGame.objects.get(pk=game_pk)
|
||||
credentials = google.oauth2.credentials.Credentials(**creds)
|
||||
yt_api = googleapiclient.discovery.build("youtube", "v3", credentials=credentials)
|
||||
pl_request = yt_api.playlists().insert(
|
||||
part="snippet,status",
|
||||
body={
|
||||
"snippet": {
|
||||
"title": f"Musik – {game.group.name} – {game.date.strftime('%x')}",
|
||||
"description": "Playlist générée par Musik",
|
||||
},
|
||||
"status": {
|
||||
"privacyStatus": "private",
|
||||
},
|
||||
},
|
||||
)
|
||||
pl_response = pl_request.execute()
|
||||
pl_id = pl_response.get("id")
|
||||
game.playlist = pl_id
|
||||
game.save()
|
||||
for music in game.musicgameorder_set.all():
|
||||
request = yt_api.playlistItems().insert(
|
||||
part="snippet",
|
||||
body={
|
||||
"snippet": {
|
||||
"playlistId": pl_id,
|
||||
"resourceId": {
|
||||
"kind": "youtube#video",
|
||||
"videoId": music.music_video.yt_id,
|
||||
},
|
||||
}
|
||||
},
|
||||
)
|
||||
request.execute()
|
||||
|
||||
game.playlist_loading = False
|
||||
game.save()
|
|
@ -3,11 +3,12 @@
|
|||
<h1>
|
||||
<i class="ri-play-circle-fill"></i> {{ musikgame.date }}
|
||||
</h1>
|
||||
{% if musikgame.playlist %}
|
||||
{% if musikgame.playlist or musikgame.playlist_loading %}
|
||||
<p>
|
||||
<a target="_blank"
|
||||
href="https://youtube.com/watch?v={{ musikgame.musicgameorder_set.first.music_video.yt_id }}&list={{ musikgame.playlist }}"
|
||||
role="button"><i class="ri-youtube-fill"></i> Playlist</a>
|
||||
role="button"
|
||||
{% if musikgame.playlist_loading %}aria-busy="true"{% endif %}><i class="ri-youtube-fill"></i> Playlist</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
<h2>
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import random
|
||||
|
||||
import google.oauth2.credentials
|
||||
import google_auth_oauthlib
|
||||
import googleapiclient.discovery
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
|
@ -15,7 +13,7 @@ from django.views import View
|
|||
from django.views.generic.detail import DetailView, SingleObjectMixin
|
||||
from django.views.generic.edit import CreateView, DeleteView, UpdateView
|
||||
|
||||
from . import forms, models, utils
|
||||
from . import forms, models, tasks, utils
|
||||
|
||||
|
||||
class OwnerFilterMixin(LoginRequiredMixin):
|
||||
|
@ -207,7 +205,7 @@ class GameCreateView(LoginRequiredMixin, CreateView):
|
|||
players = []
|
||||
musics = []
|
||||
for player in form.instance.players.all():
|
||||
players += 2 * [player]
|
||||
players += form.instance.n * [player]
|
||||
musics += random.sample(
|
||||
list(
|
||||
player.musicvideo_set.filter(group=group, blacklisted=False).all()
|
||||
|
@ -225,40 +223,9 @@ class GameCreateView(LoginRequiredMixin, CreateView):
|
|||
)
|
||||
|
||||
if creds := self.request.user.youtubecredentials:
|
||||
credentials = google.oauth2.credentials.Credentials(**creds.credentials)
|
||||
yt_api = googleapiclient.discovery.build(
|
||||
"youtube", "v3", credentials=credentials
|
||||
)
|
||||
pl_request = yt_api.playlists().insert(
|
||||
part="snippet,status",
|
||||
body={
|
||||
"snippet": {
|
||||
"title": f"Musik – {group.name} – {form.instance.date.strftime('%x')}",
|
||||
"description": "Playlist générée par Musik",
|
||||
},
|
||||
"status": {
|
||||
"privacyStatus": "private",
|
||||
},
|
||||
},
|
||||
)
|
||||
pl_response = pl_request.execute()
|
||||
pl_id = pl_response.get("id")
|
||||
form.instance.playlist = pl_id
|
||||
form.instance.playlist_loading = True
|
||||
form.instance.save()
|
||||
for _, music in pm_list:
|
||||
request = yt_api.playlistItems().insert(
|
||||
part="snippet",
|
||||
body={
|
||||
"snippet": {
|
||||
"playlistId": pl_id,
|
||||
"resourceId": {
|
||||
"kind": "youtube#video",
|
||||
"videoId": music.yt_id,
|
||||
},
|
||||
}
|
||||
},
|
||||
)
|
||||
request.execute()
|
||||
tasks.generate_playlist.delay_on_commit(creds.credentials, form.instance.pk)
|
||||
return res
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue