views.py 7.15 KB
Newer Older
fred's avatar
fred committed
1
import csv
fred's avatar
fred committed
2
import datetime
fred's avatar
fred committed
3
from cStringIO import StringIO
fred's avatar
fred committed
4
import os
5
import tempfile
fred's avatar
fred committed
6

fred's avatar
fred committed
7 8 9
import mutagen

from django.core.files.storage import default_storage
fred's avatar
fred committed
10
from django.core.urlresolvers import reverse
fred's avatar
fred committed
11
from django.contrib import messages
fred's avatar
fred committed
12
from django.http import HttpResponse
fred's avatar
fred committed
13
from django.utils.translation import ugettext_lazy as _
fred's avatar
fred committed
14
from django.views.generic.base import RedirectView, TemplateView
fred's avatar
fred committed
15
from django.views.generic.dates import DayArchiveView
fred's avatar
fred committed
16
from django.views.generic.detail import DetailView
fred's avatar
fred committed
17
from django.views.generic.edit import FormView
fred's avatar
fred committed
18
from django.views.generic.list import ListView
fred's avatar
fred committed
19

fred's avatar
fred committed
20 21
from .forms import UploadTracksForm
from .models import SomaLogLine, Track, Artist, NonstopFile
fred's avatar
fred committed
22
from emissions.models import Nonstop
fred's avatar
fred committed
23 24 25 26 27 28

class SomaDayArchiveView(DayArchiveView):
    queryset = SomaLogLine.objects.all()
    date_field = "play_timestamp"
    make_object_list = True
    allow_future = False
fred's avatar
fred committed
29 30 31
    month_format = '%m'


fred's avatar
fred committed
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
class SomaDayArchiveCsvView(SomaDayArchiveView):
    def render_to_response(self, context, **response_kwargs):
        out = StringIO()
        writer = csv.writer(out)
        for line in context['object_list']:
            if line.filepath.track:
                writer.writerow([line.play_timestamp.strftime('%Y-%m-%d %H:%M'),
                    line.filepath.short.encode('utf-8', 'replace'),
                    line.filepath.track.title.encode('utf-8', 'replace'),
                    line.filepath.track.artist.name.encode('utf-8', 'replace'),
                    line.filepath.track.language,
                    line.filepath.track.instru and 'instru' or '',
                    line.filepath.track.cfwb and 'cfwb' or ''])
            else:
                writer.writerow([line.play_timestamp.strftime('%Y-%m-%d %H:%M'),
                                line.filepath.short.encode('utf-8', 'replace')])
48
        return HttpResponse(out.getvalue(), content_type='text/csv; charset=utf-8')
fred's avatar
fred committed
49 50


fred's avatar
fred committed
51 52 53 54 55 56 57
class RedirectTodayView(RedirectView):
    def get_redirect_url(self, *args, **kwargs):
        today = datetime.datetime.today()
        return reverse('archive_day', kwargs={
                        'year': today.year,
                        'month': today.month,
                        'day': today.day})
fred's avatar
fred committed
58 59 60 61


class TrackDetailView(DetailView):
    model = Track
fred's avatar
fred committed
62 63 64 65


class ArtistDetailView(DetailView):
    model = Artist
fred's avatar
fred committed
66 67 68 69


class ArtistListView(ListView):
    model = Artist
fred's avatar
fred committed
70 71 72


class ZoneStats(object):
73
    def __init__(self, zone, from_date=None, until_date=None, **kwargs):
fred's avatar
fred committed
74
        self.zone = zone
75 76 77 78 79 80 81
        self.qs = Track.objects.filter(nonstop_zones=self.zone, **kwargs)
        self.from_date = from_date
        if from_date:
            self.qs = self.qs.filter(nonstopfile__somalogline__play_timestamp__gte=from_date)
        if until_date:
            self.qs = self.qs.filter(nonstopfile__somalogline__play_timestamp__lte=until_date)
        self.qs = self.qs.distinct()
fred's avatar
fred committed
82 83

    def count(self, **kwargs):
84
        return self.qs.filter(**kwargs).count()
fred's avatar
fred committed
85 86 87 88 89

    def percentage(self, **kwargs):
        total = self.count()
        if total == 0:
            return '-'
fred's avatar
fred committed
90
        return '%.2f%%' % (100. * self.count(**kwargs) / total)
fred's avatar
fred committed
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

    def instru(self):
        return self.count(instru=True)

    def instru_percentage(self):
        return self.percentage(instru=True)

    def sabam(self):
        return self.count(sabam=True)

    def sabam_percentage(self):
        return self.percentage(sabam=True)

    def cfwb(self):
        return self.count(cfwb=True)

    def cfwb_percentage(self):
        return self.percentage(cfwb=True)

fred's avatar
fred committed
110 111 112 113 114 115 116
    def french(self):
        return self.count(language='fr')

    def french_percentage(self):
        considered_tracks = self.count() - self.instru()
        if considered_tracks == 0:
            return '-'
fred's avatar
fred committed
117
        return '%.2f%%' % (100. * self.french() / considered_tracks)
fred's avatar
fred committed
118

119 120 121 122 123 124 125 126 127 128 129 130
    def new_files(self):
        return self.count(nonstopfile__creation_timestamp__gte=self.from_date)

    def percent_new_files(self):
        return self.percentage(nonstopfile__creation_timestamp__gte=self.from_date)


def parse_date(date):
    if date.endswith('d'):
        return datetime.datetime.today() + datetime.timedelta(int(date.rstrip('d')))
    return datetime.datetime.strptime(date, '%Y-%m-%d').date()

fred's avatar
fred committed
131 132 133 134 135 136
class StatisticsView(TemplateView):
    template_name = 'nonstop/statistics.html'

    def get_context_data(self, **kwargs):
        context = super(StatisticsView, self).get_context_data(**kwargs)
        context['zones'] = Nonstop.objects.all().order_by('start')
137 138 139 140 141 142 143 144
        kwargs = {}
        if 'from' in self.request.GET:
            kwargs['from_date'] = parse_date(self.request.GET['from'])
            context['from_date'] = kwargs['from_date']
        if 'until' in self.request.GET:
            kwargs['until_date'] = parse_date(self.request.GET['until'])
        if 'onair' in self.request.GET:
            kwargs['nonstopfile__somalogline__on_air'] = True
fred's avatar
fred committed
145
        for zone in context['zones']:
146
            zone.stats = ZoneStats(zone, **kwargs)
fred's avatar
fred committed
147
        return context
fred's avatar
fred committed
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163


class UploadTracksView(FormView):
    form_class = UploadTracksForm
    template_name = 'nonstop/upload.html'
    success_url = '.'

    def post(self, request, *args, **kwargs):
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        tracks = request.FILES.getlist('tracks')
        if not form.is_valid():
            return self.form_invalid(form)
        missing_metadata = []
        metadatas = {}
        for f in tracks:
164 165 166 167
            with tempfile.NamedTemporaryFile(prefix='track-upload') as tmpfile:
                tmpfile.write(f.read())
                f.seek(0)
                metadata = mutagen.File(tmpfile.name, easy=True)
fred's avatar
fred committed
168 169 170 171 172 173 174 175 176
            if not metadata or not metadata.get('artist') or not metadata.get('title'):
                missing_metadata.append(f.name)
            else:
                metadatas[f.name] = metadata
        if missing_metadata:
            form.add_error('tracks', _('Missing metadata in: ') + ', '.join(missing_metadata))
            return self.form_invalid(form)

        for f in tracks:
fred's avatar
fred committed
177 178 179 180
            metadata = metadatas[f.name]
            artist_name = metadata.get('artist')[0]
            track_title = metadata.get('title')[0]

fred's avatar
fred committed
181
            monthdir = datetime.datetime.today().strftime('%Y-%m')
fred's avatar
fred committed
182 183 184 185 186 187
            filepath = '%s/%s - %s - %s%s' % (monthdir,
                datetime.datetime.today().strftime('%y%m%d'),
                artist_name[:50].replace('/', ' ').strip(),
                track_title[:80].replace('/', ' ').strip(),
                os.path.splitext(f.name)[-1])

fred's avatar
fred committed
188
            default_storage.save(os.path.join('nonstop', 'tracks', filepath), content=f)
fred's avatar
fred committed
189

fred's avatar
fred committed
190 191
            nonstop_file = NonstopFile()
            nonstop_file.set_track_filepath(filepath)
fred's avatar
fred committed
192 193
            artist, created = Artist.objects.get_or_create(name=artist_name)
            track, created = Track.objects.get_or_create(title=track_title, artist=artist)
fred's avatar
fred committed
194 195 196 197 198 199 200 201
            nonstop_file.track = track
            nonstop_file.save()
            if request.POST.get('nonstop_zone'):
                track.nonstop_zones.add(
                        Nonstop.objects.get(id=request.POST.get('nonstop_zone')))

        messages.info(self.request, '%d new track(s)' % len(tracks))
        return self.form_valid(form)