]> git.0d.be Git - panikdb.git/blob - panikdb/views.py
1d358b521854336ca6e0d1b0a384eba04044c158
[panikdb.git] / panikdb / views.py
1 import datetime
2 import logging
3
4 import emissions.views
5 import newsletter.views
6 from combo.data.models import Page
7 from django.conf import settings
8 from django.contrib import messages
9 from django.contrib.auth.decorators import login_required
10 from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
11 from django.core.exceptions import PermissionDenied
12 from django.shortcuts import redirect
13 from django.template import loader
14 from django.urls import reverse
15 from django.views.generic.base import RedirectView, TemplateView
16 from django.views.generic.list import ListView
17 from emissions.models import Diffusion, Emission, Episode, Focus, NewsCategory, NewsItem, SoundFile
18 from emissions.utils import period_program
19
20 from .pige.views import PigeDownloadMixin
21 from .poll.models import Vote
22 from .service_messages.models import Message
23
24 logger = logging.getLogger('panikdb')
25
26
27 class Home(TemplateView, PigeDownloadMixin):
28     template_name = 'home.html'
29
30     def get_context_data(self, **kwargs):
31         context = super().get_context_data(**kwargs)
32
33         context.update(self.get_pige_context_data())
34
35         try:
36             vote = Vote.objects.get(user=self.request.user)
37         except Vote.DoesNotExist:
38             context['display_poll_button'] = True
39         context['emissions'] = self.request.user.emissions.all().order_by('title')
40         context['news_categories'] = self.request.user.news_categories.all().order_by('title')
41         context['service_message'] = Message.objects.all().first()
42         if not context['service_message']:
43             context['service_message'] = Message.objects.create(style='info')
44         if not context['service_message'].text and not self.request.user.has_perm(
45             'service_messages.change_message'
46         ):
47             context['service_message'] = None
48         if self.request.user.has_perm('emissions.add_focus'):
49             context['focused_items'] = Focus.objects.select_related().filter(current=True)
50             context['recent_episodes'] = Episode.objects.select_related().order_by('-last_update_timestamp')
51             context['recent_newsitems'] = NewsItem.objects.select_related().order_by('-last_update_timestamp')
52             context['recent_soundfiles'] = SoundFile.objects.select_related().order_by(
53                 '-last_update_timestamp'
54             )
55         context['extra_top_links'] = settings.HOME_EXTRA_TOP_LINKS
56
57         return context
58
59
60 home = login_required(Home.as_view())
61
62
63 class Search(TemplateView):
64     template_name = 'search/search.html'
65
66     def get_context_data(self, **kwargs):
67         context = super().get_context_data(**kwargs)
68         context['query'] = self.request.GET.get('q', '')
69         vector = (
70             SearchVector('title', config=settings.FTS_DICTIONARY_CONFIG, weight='A')
71             + SearchVector('subtitle', config=settings.FTS_DICTIONARY_CONFIG, weight='A')
72             + SearchVector('text', config=settings.FTS_DICTIONARY_CONFIG, weight='B')
73         )
74         query = SearchQuery(self.request.GET.get('q', ''), config=settings.FTS_DICTIONARY_CONFIG)
75         context['hits'] = {
76             'episodes': Episode.objects.annotate(rank=SearchRank(vector, query))
77             .filter(rank__gte=0.1)
78             .select_related('emission')
79             .order_by('-rank')[:10],
80             'emissions': Emission.objects.annotate(rank=SearchRank(vector, query))
81             .filter(rank__gte=0.1)
82             .order_by('-rank')[:10],
83             'newsitems': NewsItem.objects.annotate(rank=SearchRank(vector, query))
84             .filter(rank__gte=0.1)
85             .order_by('-rank')[:10],
86         }
87         return context
88
89
90 search = Search.as_view()
91
92
93 class EmissionListView(emissions.views.EmissionListView):
94     pass
95
96
97 emissions_list = login_required(EmissionListView.as_view())
98
99
100 class NewsListView(ListView):
101     model = NewsCategory
102
103     def get_queryset(self):
104         return NewsCategory.objects.order_by('title')
105
106     def get_context_data(self, **kwargs):
107         context = super().get_context_data(**kwargs)
108         context['unsorted_newsitems'] = NewsItem.objects.filter(category__isnull=True).order_by('title')
109         return context
110
111
112 news = login_required(NewsListView.as_view())
113
114
115 class NewsletterCreateView(newsletter.views.NewsletterCreateView):
116     def get_initial(self):
117         initial = super().get_initial()
118
119         newsletter_body = loader.get_template('newsletter/body.html')
120         newsletter_subject = loader.get_template('newsletter/subject.txt')
121         context = {}
122
123         date = datetime.datetime.today()
124         if date.weekday() < 3:
125             # before and on Wednesday, use current week
126             date = date - datetime.timedelta(days=date.weekday())
127         elif date.weekday():
128             # after Wednesday, use next week
129             date = date + datetime.timedelta(days=7 - date.weekday())
130
131         date = datetime.datetime(*date.timetuple()[:3])
132         date_end = date + datetime.timedelta(days=7)
133
134         context['date'] = date
135         context['date_end'] = date_end
136
137         context['soundfiles'] = (
138             SoundFile.objects.filter(podcastable=True, fragment=False)
139             .select_related()
140             .filter(creation_timestamp__gte=date - datetime.timedelta(days=7))
141         )
142
143         context['diffusions'] = list(
144             Diffusion.objects.select_related()
145             .filter(datetime__gte=date, datetime__lte=date + datetime.timedelta(days=7))
146             .order_by('datetime')
147         )
148
149         # remove rebroadcasts made during the same week
150         seen_episodes = {}
151         for diff in context['diffusions'][:]:
152             if diff.episode.id in seen_episodes:
153                 context['diffusions'].remove(diff)
154             seen_episodes[diff.episode.id] = True
155
156         initial['subject'] = newsletter_subject.render(context)
157         initial['text'] = newsletter_body.render(context)
158         return initial
159
160
161 newsletter_create = NewsletterCreateView.as_view()
162
163
164 class FocusSetView(RedirectView):
165     permanent = False
166
167     def get_redirect_url(self, object_type, object_id):
168         if not self.request.user.has_perm('emissions.add_focus'):
169             raise PermissionDenied()
170         messages.success(self.request, emissions.views.SUCCESS_MESSAGE)
171         if object_type == 'emission':
172             emission = Emission.objects.get(id=object_id)
173             f, _created = Focus.objects.get_or_create(emission=emission)
174             f.current = True
175             f.save()
176             logger.info('set focus on emission %s', emission)
177             return reverse('emission-view', kwargs={'slug': emission.slug})
178         if object_type == 'episode':
179             episode = Episode.objects.get(id=object_id)
180             f, _created = Focus.objects.get_or_create(episode=episode)
181             f.current = True
182             f.episode = episode
183             f.save()
184             logger.info('set focus on episode %s', episode)
185             return reverse(
186                 'episode-view', kwargs={'emission_slug': episode.emission.slug, 'slug': episode.slug}
187             )
188         if object_type == 'newsitem':
189             newsitem = NewsItem.objects.get(id=object_id)
190             f, _created = Focus.objects.get_or_create(newsitem=newsitem)
191             f.current = True
192             f.newsitem = newsitem
193             f.save()
194             logger.info('set focus on newsitem %s', newsitem)
195             return reverse('newsitem-view', kwargs={'slug': newsitem.slug})
196         if object_type == 'soundfile':
197             soundfile = SoundFile.objects.get(id=object_id)
198             f, _created = Focus.objects.get_or_create(soundfile=soundfile)
199             f.current = True
200             f.soundfile = soundfile
201             f.save()
202             logger.info('set focus on sound %s', soundfile)
203             return reverse(
204                 'episode-view',
205                 kwargs={
206                     'slug': soundfile.episode.slug,
207                     'emission_slug': soundfile.episode.emission.slug,
208                 },
209             )
210         if object_type == 'page':
211             page = Page.objects.get(id=object_id)
212             try:
213                 f = Focus.objects.get(page=page)
214             except Focus.DoesNotExist:
215                 f = Focus()
216             f.current = True
217             f.page = page
218             f.save()
219             logger.info('set focus on page %s', page)
220             return reverse('combo-manager-page-view', kwargs={'pk': object_id})
221
222
223 focus_set = FocusSetView.as_view()
224
225
226 class FocusUnsetView(RedirectView):
227     permanent = False
228
229     def get_redirect_url(self, object_type, object_id):
230         if not self.request.user.has_perm('emissions.delete_focus'):
231             raise PermissionDenied()
232         messages.success(self.request, emissions.views.SUCCESS_MESSAGE)
233         if object_type == 'emission':
234             emission = Emission.objects.get(id=object_id)
235             focus = Focus.objects.get(emission=emission)
236             focus.current = False
237             focus.save()
238             logger.info('unset focus of emission %s', emission)
239             return reverse('emission-view', kwargs={'slug': emission.slug})
240         if object_type == 'episode':
241             episode = Episode.objects.get(id=object_id)
242             focus = Focus.objects.get(episode=episode)
243             focus.current = False
244             focus.save()
245             logger.info('unset focus of episode %s', episode)
246             return reverse(
247                 'episode-view', kwargs={'emission_slug': episode.emission.slug, 'slug': episode.slug}
248             )
249         if object_type == 'newsitem':
250             newsitem = NewsItem.objects.get(id=object_id)
251             focus = Focus.objects.get(newsitem=newsitem)
252             focus.current = False
253             focus.save()
254             logger.info('unset focus of newsitem %s', newsitem)
255             return reverse('newsitem-view', kwargs={'slug': newsitem.slug})
256         if object_type == 'soundfile':
257             soundfile = SoundFile.objects.get(id=object_id)
258             focus = Focus.objects.get(soundfile=soundfile)
259             focus.current = False
260             focus.save()
261             logger.info('unset focus of soundfile %s', soundfile)
262             return reverse(
263                 'episode-view',
264                 kwargs={
265                     'slug': soundfile.episode.slug,
266                     'emission_slug': soundfile.episode.emission.slug,
267                 },
268             )
269         if object_type == 'page':
270             focus = Focus.objects.get(page=object_id)
271             focus.current = False
272             focus.save()
273             logger.info('unset focus of page %s', object_id)
274             return reverse('combo-manager-page-view', kwargs={'pk': object_id})
275
276
277 focus_unset = FocusUnsetView.as_view()