remove manual_gc decorator
[mygpo.git] / mygpo / web / views / __init__.py
blob246024b9f05efb86273ba677478740308a05d096
2 # This file is part of my.gpodder.org.
4 # my.gpodder.org is free software: you can redistribute it and/or modify it
5 # under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or (at your
7 # option) any later version.
9 # my.gpodder.org is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
12 # License for more details.
14 # You should have received a copy of the GNU Affero General Public License
15 # along with my.gpodder.org. If not, see <http://www.gnu.org/licenses/>.
18 from django.core.urlresolvers import reverse
19 from django.http import HttpResponseRedirect, Http404
20 from django.contrib.auth.models import User
21 from django.template import RequestContext
22 from mygpo.core import models
23 from mygpo.api.models import Podcast, Episode, Device, EpisodeAction, SubscriptionAction, ToplistEntry, Subscription, UserProfile
24 from mygpo.data.models import PodcastTag
25 from django.contrib.auth.decorators import login_required
26 from django.shortcuts import render_to_response
27 from datetime import datetime, timedelta
28 from django.contrib.sites.models import Site
29 from mygpo.constants import PODCAST_LOGO_SIZE, PODCAST_LOGO_BIG_SIZE
30 from mygpo.web import utils
31 from mygpo.api import backend
32 from mygpo.migrate import use_couchdb
33 import os
34 import Image
35 import ImageDraw
36 import StringIO
39 def home(request):
40 if request.user.is_authenticated():
41 return dashboard(request)
42 else:
43 return welcome(request)
46 def welcome(request, toplist_entries=10):
47 current_site = Site.objects.get_current()
48 podcasts = Podcast.objects.count()
49 users = User.objects.filter(is_active=True).count()
50 episodes = Episode.objects.count()
51 hours_listened = utils.get_hours_listened()
53 try:
54 lang = utils.process_lang_params(request, '/toplist/')
55 except utils.UpdatedException, updated:
56 lang = []
58 if len(lang) == 0:
59 entries = ToplistEntry.objects.all()[:toplist_entries]
60 else:
61 entries = backend.get_toplist(toplist_entries, lang)
63 toplist = [e.get_podcast() for e in entries]
64 sponsored_podcast = utils.get_sponsored_podcast()
66 return render_to_response('home.html', {
67 'podcast_count': podcasts,
68 'user_count': users,
69 'episode_count': episodes,
70 'url': current_site,
71 'hours_listened': hours_listened,
72 'toplist': toplist,
73 'sponsored_podcast': sponsored_podcast,
74 }, context_instance=RequestContext(request))
77 @login_required
78 def dashboard(request, episode_count=10):
79 site = Site.objects.get_current()
80 devices = Device.objects.filter(user=request.user, deleted=False)
81 subscribed_podcasts = set([s.podcast for s in Subscription.objects.filter(user=request.user)])
83 tomorrow = datetime.today() + timedelta(days=1)
84 newest_episodes = Episode.objects.filter(podcast__in=subscribed_podcasts).filter(timestamp__lt=tomorrow).order_by('-timestamp')[:episode_count]
86 lang = utils.get_accepted_lang(request)
87 lang = utils.sanitize_language_codes(lang)
89 random_podcasts = backend.get_random_picks(lang)[:5]
90 sponsored_podcast = utils.get_sponsored_podcast()
92 return render_to_response('dashboard.html', {
93 'site': site,
94 'devices': devices,
95 'subscribed_podcasts': subscribed_podcasts,
96 'newest_episodes': newest_episodes,
97 'random_podcasts': random_podcasts,
98 'sponsored_podcast': sponsored_podcast,
99 }, context_instance=RequestContext(request))
102 def cover_art(request, size, filename):
103 size = int(size)
104 if size not in (PODCAST_LOGO_SIZE, PODCAST_LOGO_BIG_SIZE):
105 raise Http404('Wrong size')
107 # XXX: Is there a "cleaner" way to get the root directory of the installation?
108 root = os.path.join(os.path.dirname(__file__), '..', '..', '..')
109 target = os.path.join(root, 'htdocs', 'media', 'logo', str(size), filename+'.jpg')
110 filepath = os.path.join(root, 'htdocs', 'media', 'logo', filename)
112 if os.path.exists(target):
113 return HttpResponseRedirect('/media/logo/%s/%s.jpg' % (str(size), filename))
115 if os.path.exists(filepath):
116 target_dir = os.path.dirname(target)
117 if not os.path.isdir(target_dir):
118 os.makedirs(target_dir)
120 try:
121 im = Image.open(filepath)
122 if im.mode not in ('RGB', 'RGBA'):
123 im = im.convert('RGB')
124 except:
125 raise Http404('Cannot open cover file')
127 try:
128 resized = im.resize((size, size), Image.ANTIALIAS)
129 except IOError:
130 # raised when trying to read an interlaced PNG; we use the original instead
131 return HttpResponseRedirect('/media/logo/%s' % filename)
133 # If it's a RGBA image, composite it onto a white background for JPEG
134 if resized.mode == 'RGBA':
135 background = Image.new('RGB', resized.size)
136 draw = ImageDraw.Draw(background)
137 draw.rectangle((-1, -1, resized.size[0]+1, resized.size[1]+1), \
138 fill=(255, 255, 255))
139 del draw
140 resized = Image.composite(resized, background, resized)
142 io = StringIO.StringIO()
143 resized.save(io, 'JPEG', optimize=True, progression=True, quality=80)
144 s = io.getvalue()
146 fp = open(target, 'wb')
147 fp.write(s)
148 fp.close()
150 return HttpResponseRedirect('/media/logo/%s/%s.jpg' % (str(size), filename))
151 else:
152 raise Http404('Cover art not available')
154 @login_required
155 def history(request, len=15, device_id=None):
156 if device_id:
157 devices = Device.objects.filter(id=device_id)
158 else:
159 devices = Device.objects.filter(user=request.user)
161 history = SubscriptionAction.objects.filter(device__in=devices).order_by('-timestamp')[:len]
162 episodehistory = EpisodeAction.objects.filter(device__in=devices).order_by('-timestamp')[:len]
164 generalhistory = []
166 for row in history:
167 generalhistory.append(row)
168 for row in episodehistory:
169 generalhistory.append(row)
171 generalhistory.sort(key=lambda x: x.timestamp,reverse=True)
173 return render_to_response('history.html', {
174 'generalhistory': generalhistory,
175 'singledevice': devices[0] if device_id else None
176 }, context_instance=RequestContext(request))
179 @login_required
180 @use_couchdb()
181 def blacklist(request, podcast_id):
182 blacklisted_podcast = models.Podcast.for_oldid(podcast_id)
183 suggestion = models.Suggestions.for_user_oldid(request.user.id)
184 suggestion.blacklist.append(blacklisted_podcast._id)
185 suggestion.save()
187 p, _created = UserProfile.objects.get_or_create(user=request.user)
188 p.suggestion_up_to_date = False
189 p.save()
191 return HttpResponseRedirect(reverse('suggestions'))
194 @login_required
195 @use_couchdb()
196 def rate_suggestions(request):
197 rating_val = int(request.GET.get('rate', None))
199 if rating_val in (1, -1):
200 suggestion = models.Suggestions.for_user_oldid(request.user.id)
201 rating = models.Rating(rating=rating_val)
202 suggestion.ratings.append(rating)
203 suggestion.save()
204 # TODO: when we use Django messaging system,
205 # add a message for successful rating here
208 return HttpResponseRedirect(reverse('suggestions'))
211 @login_required
212 @use_couchdb()
213 def suggestions(request):
214 suggestion_obj = models.Suggestions.for_user_oldid(request.user.id)
215 suggestions = [p.get_old_obj() for p in suggestion_obj.get_podcasts()]
216 current_site = Site.objects.get_current()
217 return render_to_response('suggestions.html', {
218 'entries': suggestions,
219 'url': current_site
220 }, context_instance=RequestContext(request))
223 @login_required
224 def mytags(request):
225 tags_podcast = {}
226 tags_tag = {}
227 for tag in PodcastTag.objects.filter(user=request.user):
228 if not tag.podcast in tags_podcast:
229 tags_podcast[tag.podcast] = []
231 if not tag.tag in tags_tag:
232 tags_tag[tag.tag] = []
234 tag.is_own = True
235 tags_podcast[tag.podcast].append(tag)
236 tags_tag[tag.tag].append(tag)
238 return render_to_response('mytags.html', {
239 'tags_podcast': tags_podcast,
240 'tags_tag': tags_tag,
241 }, context_instance=RequestContext(request))