From 44fc4dae31c3c0836205b287dc80af2c613ea6a8 Mon Sep 17 00:00:00 2001 From: bkfox Date: Tue, 17 Nov 2015 15:45:29 +0100 Subject: [PATCH] add a rerun field to diffusion; fix minor bug that can happen on new year's eve --- .../aircox_liquidsoap/controller.html | 5 ++ aircox_liquidsoap/utils.py | 16 ++++- aircox_programs/admin.py | 8 +-- .../management/commands/diffusions_monitor.py | 16 +++-- aircox_programs/models.py | 64 +++++++++++++++++-- 5 files changed, 90 insertions(+), 19 deletions(-) diff --git a/aircox_liquidsoap/templates/aircox_liquidsoap/controller.html b/aircox_liquidsoap/templates/aircox_liquidsoap/controller.html index dac4539..46fa95f 100644 --- a/aircox_liquidsoap/templates/aircox_liquidsoap/controller.html +++ b/aircox_liquidsoap/templates/aircox_liquidsoap/controller.html @@ -117,6 +117,11 @@ {% include 'aircox_liquidsoap/base_source.html' %} {% endfor %} + {% endwith %} {% endfor %} diff --git a/aircox_liquidsoap/utils.py b/aircox_liquidsoap/utils.py index 091a97d..16426bb 100644 --- a/aircox_liquidsoap/utils.py +++ b/aircox_liquidsoap/utils.py @@ -38,7 +38,7 @@ class Connector: self.__socket.connect(self.address) self.__available = True except: - print('can not connect to liquidsoap socket {}'.format(address)) + print('can not connect to liquidsoap socket {}'.format(self.address)) self.__available = False return -1 @@ -218,7 +218,12 @@ class Dealer (Source): pass def get_next_diffusion (self): - pass + diffusions = models.Diffusion.get_next(self.station) + if not diffusions.count(): + return + + diffusion = diffusions[0] + return diffusion def on_air (self, value = True): pass @@ -286,6 +291,12 @@ class Controller: return self.dealer return self.streams.get(source_id) + def next_diffusions (self, count = 5): + """ + Return a list of the count next diffusions + """ + return models.Diffusion.get_next(self.station)[:count] + def update_all (self): """ Fetch and update all sources metadata. @@ -316,4 +327,3 @@ class Monitor: controller.update_all() - diff --git a/aircox_programs/admin.py b/aircox_programs/admin.py index 4e9a960..6343b9d 100755 --- a/aircox_programs/admin.py +++ b/aircox_programs/admin.py @@ -5,7 +5,6 @@ from django.contrib import admin from django.db import models from suit.admin import SortableTabularInline, SortableModelAdmin -from autocomplete_light.contrib.taggit_field import TaggitWidget, TaggitField from aircox_programs.forms import * from aircox_programs.models import * @@ -73,7 +72,7 @@ class StationAdmin (NameableAdmin): @admin.register(Program) class ProgramAdmin (NameableAdmin): - fields = NameableAdmin.fields + [ 'stations', 'active' ] + fields = NameableAdmin.fields + [ 'station', 'active' ] inlines = [ ScheduleInline, StreamInline ] def get_form (self, request, obj=None, **kwargs): @@ -101,13 +100,14 @@ class DiffusionAdmin (admin.ModelAdmin): if sound.type == Sound.Type['archive'] ) return ', '.join(sounds) if sounds else '' - list_display = ('id', 'type', 'date', 'archives', 'episode', 'program') + list_display = ('id', 'type', 'date', 'archives', 'episode', 'program', 'rerun') list_filter = ('type', 'date', 'program') list_editable = ('type', 'date') def get_queryset(self, request): qs = super(DiffusionAdmin, self).get_queryset(request) - if 'type__exact' in request.GET and \ + if '_changelist_filters' in request.GET or \ + 'type__exact' in request.GET and \ str(Diffusion.Type['unconfirmed']) in request.GET['type__exact']: return qs return qs.exclude(type = Diffusion.Type['unconfirmed']) diff --git a/aircox_programs/management/commands/diffusions_monitor.py b/aircox_programs/management/commands/diffusions_monitor.py index 807da91..2f74090 100644 --- a/aircox_programs/management/commands/diffusions_monitor.py +++ b/aircox_programs/management/commands/diffusions_monitor.py @@ -23,16 +23,20 @@ from aircox_programs.models import * class Actions: @staticmethod def update (date): - items = [] - for schedule in Schedule.objects.filter(program__active = True): - items += schedule.diffusions_of_month(date, exclude_saved = True) + count = 0 + for schedule in Schedule.objects.filter(program__active = True) \ + .order_by('rerun'): + # in order to allow rerun links between diffusions, we save items + # by schedule; + items = schedule.diffusions_of_month(date, exclude_saved = True) + count += len(items) + Diffusion.objects.bulk_create(items) print('> {} new diffusions for schedule #{} ({})'.format( len(items), schedule.id, str(schedule) )) - print('total of {} diffusions will be created. To be used, they need ' - 'manual approval.'.format(len(items))) - Diffusion.objects.bulk_create(items) + print('total of {} diffusions have been created. They need a ' + 'manual approval.'.format(count)) @staticmethod def clean (date): diff --git a/aircox_programs/models.py b/aircox_programs/models.py index e7765ca..f5cd7cd 100755 --- a/aircox_programs/models.py +++ b/aircox_programs/models.py @@ -30,6 +30,10 @@ class Nameable (models.Model): max_length = 128, ) + @property + def slug (self): + return self.get_slug_name() + def get_slug_name (self): return slugify(self.name).replace('-', '_') @@ -305,8 +309,8 @@ class Schedule (models.Model): Return a list with all matching dates of date.month (=today) """ date = date_or_default(date, True).replace(day=1) - wday = self.date.weekday() fwday = date.weekday() + wday = self.date.weekday() # move date to the date weekday of the schedule # check on SO#3284452 for the formula @@ -322,8 +326,14 @@ class Schedule (models.Model): # if both week are the same, then the date week of the month # matches. Note: wday % 2 + fwday % 2 => (wday + fwday) % 2 fweek = date.isocalendar()[1] + + if date.month == 1 and fweek >= 50: + # isocalendar can think we are on the last week of the + # previous year + fweek = 0 week = self.date.isocalendar()[1] weeks = 0b010101 if not (fweek + week) % 2 else 0b001010 + print(date, fweek, week, "{0:b}".format(weeks)) dates = [] for week in range(0,5): @@ -331,8 +341,10 @@ class Schedule (models.Model): if not weeks & (0b1 << week): continue wdate = date + tz.timedelta(days = week * 7) + print(wdate, wdate.month == date.month) if wdate.month == date.month: dates.append(self.normalize(wdate)) + print(dates) return dates def diffusions_of_month (self, date, exclude_saved = False): @@ -363,15 +375,18 @@ class Schedule (models.Model): if self.rerun: first_date -= self.date - self.rerun.date - diffusion = Diffusion.objects.filter(date = first_date, - program = self.program) - episode = diffusion[0].episode if diffusion.count() else None - + first_diffusion = Diffusion.objects.filter(date = first_date, + program = self.program) + first_diffusion = first_diffusion[0] if first_diffusion.count() \ + else None + episode = first_diffusion.episode if first_diffusion else None + # print(self.rerun, episode, first_diffusion, first_date) diffusions.append(Diffusion( episode = episode, program = self.program, type = Diffusion.Type['unconfirmed'], date = date, + rerun = first_diffusion if self.rerun else None )) return diffusions @@ -422,10 +437,47 @@ class Diffusion (models.Model): choices = [ (y, x) for x,y in Type.items() ], ) date = models.DateTimeField( _('start of the diffusion') ) + rerun = models.ForeignKey ( + 'self', + verbose_name = _('rerun'), + blank = True, null = True, + help_text = _('the diffusion is a rerun of this one. Remove this if ' + 'you want to change the concerned episode') + ) + + @classmethod + def get_next (cl, station = None): + """ + Return a queryset with the upcoming diffusions, ordered by + +date + """ + args = { + 'date__gte': tz.datetime.now() + } + if station: + args['program__station'] = station + return cl.objects.filter(**args).order_by('date') + + @classmethod + def get_prev (cl, station = None): + """ + Return a queryset with the previous diffusion, ordered by + -date + """ + args = { + 'date__lt': tz.datetime.now() + } + if station: + args['program__station'] = station + return cl.objects.filter(**args).order_by('-date') def save (self, *args, **kwargs): - if self.episode: # FIXME self.episode or kwargs['episode'] + if self.rerun: + self.episode = self.rerun.episode self.program = self.episode.program + elif self.episode: + self.program = self.episode.program + super(Diffusion, self).save(*args, **kwargs) def __str__ (self):