bgneal@60
|
1 """
|
bgneal@60
|
2 Automatic admin definitions for the videos application.
|
bgneal@60
|
3
|
bgneal@60
|
4 """
|
bgneal@60
|
5 import datetime
|
bgneal@60
|
6 import urlparse
|
bgneal@60
|
7
|
bgneal@60
|
8 from django.contrib import admin
|
bgneal@60
|
9 from django.contrib import messages
|
bgneal@60
|
10 from gdata.youtube.service import YouTubeService
|
bgneal@60
|
11
|
bgneal@60
|
12 from videos.models import Playlist
|
bgneal@60
|
13
|
bgneal@60
|
14
|
bgneal@60
|
15 class PlaylistAdmin(admin.ModelAdmin):
|
bgneal@60
|
16 list_display = ['__unicode__', 'playlist_url', 'sync_date']
|
bgneal@60
|
17 readonly_fields = ['playlist_title', 'video_list', 'sync_date']
|
bgneal@60
|
18 actions = ['sync']
|
bgneal@60
|
19
|
bgneal@60
|
20 def sync(self, request, queryset):
|
bgneal@60
|
21 for playlist in queryset:
|
bgneal@60
|
22 self.sync_playlist(request, playlist)
|
bgneal@60
|
23
|
bgneal@60
|
24 sync.short_description = 'Synchronize with YouTube'
|
bgneal@60
|
25
|
bgneal@60
|
26 def sync_playlist(self, request, playlist):
|
bgneal@60
|
27 """
|
bgneal@60
|
28 Retrieve the title and list of videos for a
|
bgneal@60
|
29 YouTube playlist.
|
bgneal@60
|
30
|
bgneal@60
|
31 """
|
bgneal@60
|
32 # Find the playlist ID:
|
bgneal@60
|
33 parts = urlparse.urlparse(playlist.playlist_url)
|
bgneal@60
|
34 query = urlparse.parse_qs(parts.query)
|
bgneal@60
|
35 if 'list' not in query:
|
bgneal@60
|
36 messages.error(request, 'Invalid playlist %s' %
|
bgneal@60
|
37 playlist.playlist_url)
|
bgneal@60
|
38 return
|
bgneal@60
|
39
|
bgneal@60
|
40 playlist_id = query['list'][0]
|
bgneal@60
|
41 if not playlist_id.startswith('PL'):
|
bgneal@60
|
42 messages.error(request, 'Invalid playlist ID in %s' %
|
bgneal@60
|
43 playlist.playlist_url)
|
bgneal@60
|
44 return
|
bgneal@60
|
45 playlist_id = playlist_id[2:]
|
bgneal@60
|
46
|
bgneal@60
|
47 # Get the playlist feed:
|
bgneal@60
|
48 yt = YouTubeService()
|
bgneal@60
|
49 feed = yt.GetYouTubePlaylistVideoFeed(playlist_id=playlist_id)
|
bgneal@60
|
50 feed_title = feed.title.text
|
bgneal@60
|
51 expected_count = int(feed.total_results.text)
|
bgneal@60
|
52
|
bgneal@60
|
53 # Get all the videos in the feed; this may take multiple requests:
|
bgneal@60
|
54 vids = []
|
bgneal@60
|
55 while True:
|
bgneal@60
|
56 vids.extend(feed.entry)
|
bgneal@60
|
57 next_link = feed.GetNextLink()
|
bgneal@60
|
58 if not next_link:
|
bgneal@60
|
59 break
|
bgneal@60
|
60 feed = yt.Query(next_link.href)
|
bgneal@60
|
61
|
bgneal@60
|
62 if len(vids) != expected_count:
|
bgneal@60
|
63 messages.error(request, "%s: expected %d videos, got %d" %
|
bgneal@60
|
64 (playlist.playlist_url, expected_count, len(vids)))
|
bgneal@60
|
65
|
bgneal@60
|
66 # Find the video ID for each video
|
bgneal@60
|
67
|
bgneal@60
|
68 vid_ids = []
|
bgneal@60
|
69 for vid in vids:
|
bgneal@60
|
70 for link in vid.link:
|
bgneal@60
|
71 parts = urlparse.urlparse(link.href)
|
bgneal@60
|
72 query = urlparse.parse_qs(parts.query)
|
bgneal@60
|
73 if 'v' in query:
|
bgneal@60
|
74 vid_ids.append(query['v'][0])
|
bgneal@60
|
75 break
|
bgneal@60
|
76 else:
|
bgneal@60
|
77 messages.error(request, "%s: video id not found for %s" %
|
bgneal@60
|
78 (playlist.playlist_url, vid.title.text))
|
bgneal@60
|
79
|
bgneal@60
|
80 # Okay, save what we got
|
bgneal@60
|
81 playlist.playlist_title = feed_title
|
bgneal@60
|
82 playlist.video_list = ",".join(vid_ids)
|
bgneal@60
|
83 playlist.sync_date = datetime.datetime.now()
|
bgneal@60
|
84 playlist.save()
|
bgneal@60
|
85
|
bgneal@60
|
86 messages.info(request, "Synchronized %s (%s)" % (feed_title,
|
bgneal@60
|
87 playlist.playlist_url))
|
bgneal@60
|
88
|
bgneal@60
|
89
|
bgneal@60
|
90 admin.site.register(Playlist, PlaylistAdmin)
|